Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions ext/openssl/ossl_ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -579,12 +579,21 @@ ssl_npn_select_cb_common(SSL *ssl, VALUE cb, const unsigned char **out,
return SSL_TLSEXT_ERR_OK;
}

static VALUE
ossl_sslctx_obj_from_ssl(const SSL *ssl)
{
SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);

return (VALUE)SSL_CTX_get_ex_data(ctx, ossl_sslctx_ex_ptr_idx);
}

#ifdef OSSL_USE_NEXTPROTONEG
static int
ssl_npn_advertise_cb(SSL *ssl, const unsigned char **out, unsigned int *outlen,
void *arg)
{
VALUE protocols = rb_attr_get((VALUE)arg, id_npn_protocols_encoded);
VALUE protocols = rb_attr_get(ossl_sslctx_obj_from_ssl(ssl),
id_npn_protocols_encoded);

*out = (const unsigned char *) RSTRING_PTR(protocols);
*outlen = RSTRING_LENINT(protocols);
Expand All @@ -598,7 +607,7 @@ ssl_npn_select_cb(SSL *ssl, unsigned char **out, unsigned char *outlen,
{
VALUE sslctx_obj, cb;

sslctx_obj = (VALUE) arg;
sslctx_obj = ossl_sslctx_obj_from_ssl(ssl);
cb = rb_attr_get(sslctx_obj, id_i_npn_select_cb);

return ssl_npn_select_cb_common(ssl, cb, (const unsigned char **)out,
Expand All @@ -612,7 +621,7 @@ ssl_alpn_select_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen,
{
VALUE sslctx_obj, cb;

sslctx_obj = (VALUE) arg;
sslctx_obj = ossl_sslctx_obj_from_ssl(ssl);
cb = rb_attr_get(sslctx_obj, id_i_alpn_select_cb);

return ssl_npn_select_cb_common(ssl, cb, out, outlen, in, inlen);
Expand Down Expand Up @@ -807,11 +816,11 @@ ossl_sslctx_setup(VALUE self)
if (!NIL_P(val)) {
VALUE encoded = ssl_encode_npn_protocols(val);
rb_ivar_set(self, id_npn_protocols_encoded, encoded);
SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_npn_advertise_cb, (void *)self);
SSL_CTX_set_next_protos_advertised_cb(ctx, ssl_npn_advertise_cb, NULL);
OSSL_Debug("SSL NPN advertise callback added");
}
if (RTEST(rb_attr_get(self, id_i_npn_select_cb))) {
SSL_CTX_set_next_proto_select_cb(ctx, ssl_npn_select_cb, (void *) self);
SSL_CTX_set_next_proto_select_cb(ctx, ssl_npn_select_cb, NULL);
OSSL_Debug("SSL NPN select callback added");
}
#endif
Expand All @@ -827,7 +836,7 @@ ossl_sslctx_setup(VALUE self)
OSSL_Debug("SSL ALPN values added");
}
if (RTEST(rb_attr_get(self, id_i_alpn_select_cb))) {
SSL_CTX_set_alpn_select_cb(ctx, ssl_alpn_select_cb, (void *) self);
SSL_CTX_set_alpn_select_cb(ctx, ssl_alpn_select_cb, NULL);
OSSL_Debug("SSL ALPN select callback added");
}

Expand Down
19 changes: 6 additions & 13 deletions hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,8 @@ RHASH_AR_TABLE_MAX_BOUND(VALUE h)
#define RHASH_AR_TABLE_MISS RHASH_AR_TABLE_MAX_SIZE

#define RHASH_AR_TABLE_REF(hash, n) (&RHASH_AR_TABLE(hash)->pairs[n])
#define RHASH_AR_CLEARED_HINT 0xff
#define RHASH_AR_CLEARED_HINT 0x00
#define RHASH_AR_SUBSTITUTION_HINT 0x01

static inline st_hash_t
ar_do_hash(VALUE hash, st_data_t key)
Expand All @@ -445,7 +446,8 @@ ar_do_hash(VALUE hash, st_data_t key)
static inline ar_hint_t
ar_do_hash_hint(st_hash_t hash_value)
{
return (ar_hint_t)hash_value;
ar_hint_t hint = (ar_hint_t)hash_value;
return hint == RHASH_AR_CLEARED_HINT ? RHASH_AR_SUBSTITUTION_HINT : hint;
}

static inline ar_hint_t
Expand Down Expand Up @@ -474,19 +476,10 @@ ar_clear_entry(VALUE hash, unsigned int index)
ar_hint_set_hint(hash, index, RHASH_AR_CLEARED_HINT);
}

static inline int
static inline bool
ar_cleared_entry(VALUE hash, unsigned int index)
{
if (ar_hint(hash, index) == RHASH_AR_CLEARED_HINT) {
/* RHASH_AR_CLEARED_HINT is only a hint, not mean cleared entry,
* so you need to check key == Qundef
*/
ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, index);
return UNDEF_P(pair->key);
}
else {
return FALSE;
}
return ar_hint(hash, index) == RHASH_AR_CLEARED_HINT;
}

static inline void
Expand Down
126 changes: 86 additions & 40 deletions id_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,33 +30,67 @@ id2key(ID id)
uses mark-bit on collisions - need extra 1 bit,
ID is strictly 3 bits larger than rb_id_serial_t */

typedef struct rb_id_item {
id_key_t key;
#if SIZEOF_VALUE == 8
int collision;
#endif
VALUE val;
} item_t;
/* The table body is a single buffer laid out as:

[VALUE values[capa] | id_key_t keys[capa] | collision bitmap]

where the collision bitmap uses one mark bit per slot. Keeping the
keys out of the item struct avoids padding them to the alignment of
VALUE. The three regions are computed from buf and capa, so the
struct only needs to store the buffer pointer. */
#define COLLISION_TABLE_SIZE(capa) roomof((size_t)(capa), CHAR_BIT)
#define ID_TABLE_BUF_SIZE(capa) \
((sizeof(VALUE) + sizeof(id_key_t)) * (size_t)(capa) + COLLISION_TABLE_SIZE(capa))

static inline VALUE *
id_table_items(struct rb_id_table *tbl)
{
return (VALUE *)tbl->buf;
}

static inline id_key_t *
id_table_keys(struct rb_id_table *tbl)
{
return (id_key_t *)(id_table_items(tbl) + tbl->capa);
}

static inline uint8_t *
id_table_collision_table(struct rb_id_table *tbl)
{
return (uint8_t *)(id_table_keys(tbl) + tbl->capa);
}

#define ITEM_GET_KEY(tbl, i) (id_table_keys(tbl)[i])
#define ITEM_KEY_ISSET(tbl, i) ((tbl)->buf && id_table_keys(tbl)[i])
#define ITEM_COLLIDED(tbl, i) (id_table_collision_table(tbl)[(i) / CHAR_BIT] & ((uint8_t)1 << ((i) % CHAR_BIT)))
#define ITEM_SET_COLLIDED(tbl, i) (id_table_collision_table(tbl)[(i) / CHAR_BIT] |= ((uint8_t)1 << ((i) % CHAR_BIT)))
#define ITEM_VALUE(tbl, i) (id_table_items(tbl)[i])

#if SIZEOF_VALUE == 8
#define ITEM_GET_KEY(tbl, i) ((tbl)->items[i].key)
#define ITEM_KEY_ISSET(tbl, i) ((tbl)->items && (tbl)->items[i].key)
#define ITEM_COLLIDED(tbl, i) ((tbl)->items[i].collision)
#define ITEM_SET_COLLIDED(tbl, i) ((tbl)->items[i].collision = 1)
static inline void
ITEM_SET_KEY(struct rb_id_table *tbl, int i, id_key_t key)
{
tbl->items[i].key = key;
id_table_keys(tbl)[i] = key;
}
#else
#define ITEM_GET_KEY(tbl, i) ((tbl)->items[i].key >> 1)
#define ITEM_KEY_ISSET(tbl, i) ((tbl)->items[i].key > 1)
#define ITEM_COLLIDED(tbl, i) ((tbl)->items[i].key & 1)
#define ITEM_SET_COLLIDED(tbl, i) ((tbl)->items[i].key |= 1)
typedef struct rb_id_item {
id_key_t key;
VALUE val;
} item_t;

#define ID_TABLE_BUF_SIZE(capa) (sizeof(item_t) * (size_t)(capa))
#define id_table_items(tbl) ((item_t *)(tbl)->buf)

#define ITEM_GET_KEY(tbl, i) (id_table_items(tbl)[i].key >> 1)
#define ITEM_KEY_ISSET(tbl, i) (id_table_items(tbl)[i].key > 1)
#define ITEM_COLLIDED(tbl, i) (id_table_items(tbl)[i].key & 1)
#define ITEM_SET_COLLIDED(tbl, i) (id_table_items(tbl)[i].key |= 1)
#define ITEM_VALUE(tbl, i) (id_table_items(tbl)[i].val)

static inline void
ITEM_SET_KEY(struct rb_id_table *tbl, int i, id_key_t key)
{
tbl->items[i].key = (key << 1) | ITEM_COLLIDED(tbl, i);
id_table_items(tbl)[i].key = (key << 1) | ITEM_COLLIDED(tbl, i);
}
#endif

Expand All @@ -73,6 +107,16 @@ round_capa(int capa)
return (capa + 1) << 2;
}

static void
id_table_alloc_buf(struct rb_id_table *tbl, int capa)
{
#if SIZEOF_VALUE == 8
tbl->buf = ruby_xcalloc(1, ID_TABLE_BUF_SIZE(capa));
#else
tbl->buf = ZALLOC_N(item_t, capa);
#endif
}

struct rb_id_table *
rb_id_table_init(struct rb_id_table *tbl, size_t s_capa)
{
Expand All @@ -81,7 +125,7 @@ rb_id_table_init(struct rb_id_table *tbl, size_t s_capa)
if (capa > 0) {
capa = round_capa(capa);
tbl->capa = (int)capa;
tbl->items = ZALLOC_N(item_t, capa);
id_table_alloc_buf(tbl, capa);
}
return tbl;
}
Expand All @@ -96,13 +140,13 @@ rb_id_table_create(size_t capa)
void
rb_id_table_free_items(struct rb_id_table *tbl)
{
xfree(tbl->items);
xfree(tbl->buf);
}

void
rb_id_table_free(struct rb_id_table *tbl)
{
xfree(tbl->items);
xfree(tbl->buf);
xfree(tbl);
}

Expand All @@ -111,7 +155,9 @@ rb_id_table_clear(struct rb_id_table *tbl)
{
tbl->num = 0;
tbl->used = 0;
MEMZERO(tbl->items, item_t, tbl->capa);
if (tbl->buf) {
memset(tbl->buf, 0, ID_TABLE_BUF_SIZE(tbl->capa));
}
}

size_t
Expand All @@ -123,7 +169,7 @@ rb_id_table_size(const struct rb_id_table *tbl)
size_t
rb_id_table_memsize(const struct rb_id_table *tbl)
{
return sizeof(item_t) * tbl->capa + sizeof(struct rb_id_table);
return ID_TABLE_BUF_SIZE(tbl->capa) + sizeof(struct rb_id_table);
}

static int
Expand Down Expand Up @@ -161,7 +207,7 @@ hash_table_raw_insert(struct rb_id_table *tbl, id_key_t key, VALUE val)
tbl->used++;
}
ITEM_SET_KEY(tbl, ix, key);
tbl->items[ix].val = val;
ITEM_VALUE(tbl, ix) = val;
}

static int
Expand All @@ -173,7 +219,7 @@ hash_delete_index(struct rb_id_table *tbl, int ix)
}
tbl->num--;
ITEM_SET_KEY(tbl, ix, 0);
tbl->items[ix].val = 0;
ITEM_VALUE(tbl, ix) = 0;
return TRUE;
}
else {
Expand All @@ -187,20 +233,20 @@ hash_table_extend(struct rb_id_table* tbl)
if (tbl->used + (tbl->used >> 1) >= tbl->capa) {
int new_cap = round_capa(tbl->num + (tbl->num >> 1));
int i;
item_t* old;
struct rb_id_table tmp_tbl = {0, 0, 0};
void *old;
struct rb_id_table tmp_tbl = {0};
if (new_cap < tbl->capa) {
new_cap = round_capa(tbl->used + (tbl->used >> 1));
}
tmp_tbl.capa = new_cap;
tmp_tbl.items = ZALLOC_N(item_t, new_cap);
id_table_alloc_buf(&tmp_tbl, new_cap);
for (i = 0; i < tbl->capa; i++) {
id_key_t key = ITEM_GET_KEY(tbl, i);
if (key != 0) {
hash_table_raw_insert(&tmp_tbl, key, tbl->items[i].val);
hash_table_raw_insert(&tmp_tbl, key, ITEM_VALUE(tbl, i));
}
}
old = tbl->items;
old = tbl->buf;
*tbl = tmp_tbl;
xfree(old);
}
Expand All @@ -210,14 +256,14 @@ hash_table_extend(struct rb_id_table* tbl)
static void
hash_table_show(struct rb_id_table *tbl)
{
const id_key_t *keys = tbl->keys;
const int capa = tbl->capa;
int i;

fprintf(stderr, "tbl: %p (capa: %d, num: %d, used: %d)\n", tbl, tbl->capa, tbl->num, tbl->used);
for (i=0; i<capa; i++) {
if (ITEM_KEY_ISSET(tbl, i)) {
fprintf(stderr, " -> [%d] %s %d\n", i, rb_id2name(key2id(keys[i])), (int)keys[i]);
const id_key_t key = ITEM_GET_KEY(tbl, i);
fprintf(stderr, " -> [%d] %s %d\n", i, rb_id2name(key2id(key)), (int)key);
}
}
}
Expand All @@ -230,7 +276,7 @@ rb_id_table_lookup(struct rb_id_table *tbl, ID id, VALUE *valp)
int index = hash_table_index(tbl, key);

if (index >= 0) {
*valp = tbl->items[index].val;
*valp = ITEM_VALUE(tbl, index);
return TRUE;
}
else {
Expand All @@ -244,7 +290,7 @@ rb_id_table_insert_key(struct rb_id_table *tbl, const id_key_t key, const VALUE
const int index = hash_table_index(tbl, key);

if (index >= 0) {
tbl->items[index].val = val;
ITEM_VALUE(tbl, index) = val;
}
else {
hash_table_extend(tbl);
Expand Down Expand Up @@ -275,7 +321,7 @@ rb_id_table_foreach(struct rb_id_table *tbl, rb_id_table_foreach_func_t *func, v
for (i=0; i<capa; i++) {
if (ITEM_KEY_ISSET(tbl, i)) {
const id_key_t key = ITEM_GET_KEY(tbl, i);
enum rb_id_table_iterator_result ret = (*func)(key2id(key), tbl->items[i].val, data);
enum rb_id_table_iterator_result ret = (*func)(key2id(key), ITEM_VALUE(tbl, i), data);
RUBY_ASSERT(key != 0);

if (ret == ID_TABLE_DELETE)
Expand All @@ -291,13 +337,13 @@ rb_id_table_foreach_values(struct rb_id_table *tbl, rb_id_table_foreach_values_f
{
int i, capa = tbl->capa;

if (!tbl->items) {
if (!tbl->buf) {
return;
}

for (i=0; i<capa; i++) {
if (ITEM_KEY_ISSET(tbl, i)) {
enum rb_id_table_iterator_result ret = (*func)(tbl->items[i].val, data);
enum rb_id_table_iterator_result ret = (*func)(ITEM_VALUE(tbl, i), data);

if (ret == ID_TABLE_DELETE)
hash_delete_index(tbl, i);
Expand All @@ -314,12 +360,12 @@ rb_id_table_foreach_values_with_replace(struct rb_id_table *tbl, rb_id_table_for

for (i = 0; i < capa; i++) {
if (ITEM_KEY_ISSET(tbl, i)) {
enum rb_id_table_iterator_result ret = (*func)(tbl->items[i].val, data);
enum rb_id_table_iterator_result ret = (*func)(ITEM_VALUE(tbl, i), data);

if (ret == ID_TABLE_REPLACE) {
VALUE val = tbl->items[i].val;
VALUE val = ITEM_VALUE(tbl, i);
ret = (*replace)(&val, data, TRUE);
tbl->items[i].val = val;
ITEM_VALUE(tbl, i) = val;
}

if (ret == ID_TABLE_STOP)
Expand Down Expand Up @@ -367,7 +413,7 @@ rb_managed_id_table_create(const rb_data_type_t *type, size_t capa)
struct rb_id_table *tbl;
VALUE obj = TypedData_Make_Struct(0, struct rb_id_table, type, tbl);
RB_OBJ_SET_SHAREABLE(obj);
rb_id_table_init(tbl, capa); // NOTE: this can cause GC, so dmark and dsize need to check tbl->items
rb_id_table_init(tbl, capa); // NOTE: this can cause GC, so dmark and dsize need to check tbl->buf
return obj;
}

Expand Down
Loading