static void grow_shard(slice_shard *shard) { size_t capacity = shard->capacity * 2; size_t i; interned_slice_refcount **strtab; interned_slice_refcount *s, *next; GPR_TIMER_BEGIN("grow_strtab", 0); strtab = (interned_slice_refcount **)gpr_zalloc( sizeof(interned_slice_refcount *) * capacity); for (i = 0; i < shard->capacity; i++) { for (s = shard->strs[i]; s; s = next) { size_t idx = TABLE_IDX(s->hash, capacity); next = s->bucket_next; s->bucket_next = strtab[idx]; strtab[idx] = s; } } gpr_free(shard->strs); shard->strs = strtab; shard->capacity = capacity; GPR_TIMER_END("grow_strtab", 0); }
static void interned_slice_destroy(interned_slice_refcount *s) { slice_shard *shard = &g_shards[SHARD_IDX(s->hash)]; gpr_mu_lock(&shard->mu); GPR_ASSERT(0 == gpr_atm_no_barrier_load(&s->refcnt)); interned_slice_refcount **prev_next; interned_slice_refcount *cur; for (prev_next = &shard->strs[TABLE_IDX(s->hash, shard->capacity)], cur = *prev_next; cur != s; prev_next = &cur->bucket_next, cur = cur->bucket_next) ; *prev_next = cur->bucket_next; shard->count--; gpr_free(s); gpr_mu_unlock(&shard->mu); }
static bool dirFuncValues( directive_t *dir, dir_table_enum parm ) //**************************************************************** { dir_operand *dirop; static int_8 byte; static int_16 half; static int_32 word; static signed_64 quad; static float flt; static double dbl; int_32 rep; uint_8 prev_alignment = 0; int opnum; void *target = NULL; owl_reloc_type rtype = 0; struct { int size; void *ptr; uint_8 alignment; } data_table[] = { { 1, &byte, 0 }, // DT_VAL_INT8 { 8, &dbl, 3 }, // DT_VAL_DOUBLE { 4, &flt, 2 }, // DT_VAL_FLOAT { 2, &half, 1 }, // DT_VAL_INT16 { 4, &word, 2 }, // DT_VAL_INT32 { 8, &quad, 3 }, // DT_VAL_INT64 }; #define TABLE_IDX( x ) ( ( x ) - DT_VAL_FIRST ) #ifdef _STANDALONE_ if( OWLTellSectionType( CurrentSection ) & OWL_SEC_ATTR_BSS ) { Error( INVALID_BSS_DIRECTIVE, SymName( dir->dir_sym ) ); return( TRUE ); } #endif if( autoAlignment ) { prev_alignment = CurrAlignment; CurrAlignment = data_table[TABLE_IDX(parm)].alignment; } dirop = dir->operand_list; opnum = 0; while( dirop ) { rep = 1; switch( parm ) { case DT_VAL_INT8: assert( dirop->type == DIROP_INTEGER || dirop->type == DIROP_REP_INT ); if( dirop->type == DIROP_INTEGER ) { byte = (int_8)NUMBER_INTEGER( dirop ); } else { // repeat rep = REPEAT_COUNT( dirop ); byte = (int_8)REPEAT_INTEGER( dirop ); } break; case DT_VAL_INT64: assert( dirop->type == DIROP_INTEGER || dirop->type == DIROP_REP_INT ); if( dirop->type == DIROP_INTEGER ) { quad.u._32[I64LO32] = NUMBER_INTEGER( dirop ); } else { // repeat rep = REPEAT_COUNT( dirop ); quad.u._32[I64LO32] = REPEAT_INTEGER( dirop ); } break; case DT_VAL_DOUBLE: assert( dirop->type == DIROP_FLOATING || dirop->type == DIROP_REP_FLT ); if( dirop->type == DIROP_FLOATING ) { dbl = NUMBER_FLOAT( dirop ); } else { rep = REPEAT_COUNT( dirop ); dbl = REPEAT_FLOAT( dirop ); } break; case DT_VAL_FLOAT: assert( dirop->type == DIROP_FLOATING || dirop->type == DIROP_REP_FLT ); if( dirop->type == DIROP_FLOATING ) { flt = (float)NUMBER_FLOAT( dirop ); } else { rep = REPEAT_COUNT( dirop ); flt = (float)REPEAT_FLOAT( dirop ); } break; case DT_VAL_INT32: assert( dirop->type == DIROP_INTEGER || dirop->type == DIROP_REP_INT || dirop->type == DIROP_SYMBOL || dirop->type == DIROP_NUMLABEL_REF ); if( dirop->type == DIROP_INTEGER ) { word = NUMBER_INTEGER( dirop ); } else if( dirop->type == DIROP_REP_INT ) { rep = REPEAT_COUNT( dirop ); word = REPEAT_INTEGER( dirop ); } else { // reloc word = SYMBOL_OFFSET( dirop ); if( assignRelocType( &rtype, SYMBOL_RELOC_TYPE( dirop ), parm ) ) { if( dirop->type == DIROP_SYMBOL ) { target = SymName( SYMBOL_HANDLE( dirop ) ); } else { assert( dirop->type == DIROP_NUMLABEL_REF ); target = &SYMBOL_LABEL_REF( dirop ); } } else { Error( IMPROPER_DIROP, opnum ); } } break; case DT_VAL_INT16: assert( dirop->type == DIROP_INTEGER || dirop->type == DIROP_REP_INT || dirop->type == DIROP_SYMBOL || dirop->type == DIROP_NUMLABEL_REF ); if( dirop->type == DIROP_INTEGER ) { half = (int_16)NUMBER_INTEGER( dirop ); } else if( dirop->type == DIROP_REP_INT ) { rep = REPEAT_COUNT( dirop ); half = (int_16)REPEAT_INTEGER( dirop ); } else { // reloc half = (int_16)SYMBOL_OFFSET( dirop ); if( assignRelocType( &rtype, SYMBOL_RELOC_TYPE( dirop ), parm ) ) { if( dirop->type == DIROP_SYMBOL ) { target = SymName( SYMBOL_HANDLE( dirop ) ); } else { assert( dirop->type == DIROP_NUMLABEL_REF ); target = &SYMBOL_LABEL_REF( dirop ); } } else { Error( IMPROPER_DIROP, opnum ); } } break; default: Error( INTERNAL_UNKNOWN_DT_PARM, parm ); return( FALSE ); } if( target != NULL ) { assert( (parm == DT_VAL_INT32 || parm == DT_VAL_INT16) && rep == 1 ); #ifdef _STANDALONE_ // align with data ObjEmitReloc( CurrentSection, target, rtype, ( opnum == 0 ), (dirop->type == DIROP_SYMBOL) ); #else // align with data ObjEmitReloc( target, rtype, ( opnum == 0 ), (dirop->type == DIROP_SYMBOL ) ); #endif target = NULL; } #ifdef _STANDALONE_ // only align for the first data operand ObjEmitData( CurrentSection, data_table[TABLE_IDX(parm)].ptr, data_table[TABLE_IDX(parm)].size, ( opnum == 0 ) ); #else // only align for the first data operand ObjEmitData( data_table[TABLE_IDX(parm)].ptr, data_table[TABLE_IDX(parm)].size, ( opnum == 0 ) ); #endif for( rep--; rep > 0; rep-- ) { #ifdef _STANDALONE_ OWLEmitData( CurrentSection, data_table[TABLE_IDX(parm)].ptr, data_table[TABLE_IDX(parm)].size ); #else ObjDirectEmitData( data_table[TABLE_IDX(parm)].ptr, data_table[TABLE_IDX(parm)].size ); #endif #if 0 printf( "Size=%d\n", data_table[TABLE_IDX(parm)].size ); switch( parm ) { case DT_VAL_INT8: printf( "Out->%d\n", *(int_8 *)(data_table[TABLE_IDX(parm)].ptr) ); break; case DT_VAL_DOUBLE: printf( "Out->%lf\n", *(double *)(data_table[TABLE_IDX(parm)].ptr) ); break; case DT_VAL_FLOAT: printf( "Out->%f\n", *(float *)(data_table[TABLE_IDX(parm)].ptr) ); break; case DT_VAL_INT16: printf( "Out->%d\n", *(int_16 *)(data_table[TABLE_IDX(parm)].ptr) ); break; case DT_VAL_INT32: printf( "Out->%d\n", *(int_32 *)(data_table[TABLE_IDX(parm)].ptr) ); break; case DT_VAL_INT64: printf( "Out->%d\n", ((signed_64 *)(data_table[TABLE_IDX(parm)].ptr))->_32[0] ); break; default: assert( FALSE ); } #endif } opnum++; dirop = dirop->next; } if( autoAlignment ) { CurrAlignment = prev_alignment; } return( TRUE ); }
grpc_slice grpc_slice_intern(grpc_slice slice) { GPR_TIMER_BEGIN("grpc_slice_intern", 0); if (GRPC_IS_STATIC_METADATA_STRING(slice)) { GPR_TIMER_END("grpc_slice_intern", 0); return slice; } uint32_t hash = grpc_slice_hash(slice); for (uint32_t i = 0; i <= max_static_metadata_hash_probe; i++) { static_metadata_hash_ent ent = static_metadata_hash[(hash + i) % GPR_ARRAY_SIZE(static_metadata_hash)]; if (ent.hash == hash && ent.idx < GRPC_STATIC_MDSTR_COUNT && grpc_slice_eq(grpc_static_slice_table[ent.idx], slice)) { GPR_TIMER_END("grpc_slice_intern", 0); return grpc_static_slice_table[ent.idx]; } } interned_slice_refcount *s; slice_shard *shard = &g_shards[SHARD_IDX(hash)]; gpr_mu_lock(&shard->mu); /* search for an existing string */ size_t idx = TABLE_IDX(hash, shard->capacity); for (s = shard->strs[idx]; s; s = s->bucket_next) { if (s->hash == hash && grpc_slice_eq(slice, materialize(s))) { if (gpr_atm_no_barrier_fetch_add(&s->refcnt, 1) == 0) { /* If we get here, we've added a ref to something that was about to * die - drop it immediately. * The *only* possible path here (given the shard mutex) should be to * drop from one ref back to zero - assert that with a CAS */ GPR_ASSERT(gpr_atm_rel_cas(&s->refcnt, 1, 0)); /* and treat this as if we were never here... sshhh */ } else { gpr_mu_unlock(&shard->mu); GPR_TIMER_END("grpc_slice_intern", 0); return materialize(s); } } } /* not found: create a new string */ /* string data goes after the internal_string header */ s = (interned_slice_refcount *)gpr_malloc(sizeof(*s) + GRPC_SLICE_LENGTH(slice)); gpr_atm_rel_store(&s->refcnt, 1); s->length = GRPC_SLICE_LENGTH(slice); s->hash = hash; s->base.vtable = &interned_slice_vtable; s->base.sub_refcount = &s->sub; s->sub.vtable = &interned_slice_sub_vtable; s->sub.sub_refcount = &s->sub; s->bucket_next = shard->strs[idx]; shard->strs[idx] = s; memcpy(s + 1, GRPC_SLICE_START_PTR(slice), GRPC_SLICE_LENGTH(slice)); shard->count++; if (shard->count > shard->capacity * 2) { grow_shard(shard); } gpr_mu_unlock(&shard->mu); GPR_TIMER_END("grpc_slice_intern", 0); return materialize(s); }