DUK_LOCAL duk_hstring *duk__do_lookup(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t *out_strhash) { duk_hstring *res; DUK_ASSERT(out_strhash); *out_strhash = duk_heap_hashstring(heap, str, (duk_size_t) blen); #if defined(DUK_USE_ROM_STRINGS) { duk_small_uint_t i; /* XXX: This is VERY inefficient now, and should be e.g. a * binary search or perfect hash, to be fixed. */ for (i = 0; i < (duk_small_uint_t) (sizeof(duk_rom_strings) / sizeof(duk_hstring *)); i++) { duk_hstring *romstr; romstr = (duk_hstring *) DUK_LOSE_CONST(duk_rom_strings[i]); if (blen == DUK_HSTRING_GET_BYTELEN(romstr) && DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(romstr), blen) == 0) { DUK_DD(DUK_DDPRINT("intern check: rom string: %!O, computed hash 0x%08lx, rom hash 0x%08lx", romstr, (unsigned long) *out_strhash, (unsigned long) DUK_HSTRING_GET_HASH(romstr))); DUK_ASSERT(*out_strhash == DUK_HSTRING_GET_HASH(romstr)); *out_strhash = DUK_HSTRING_GET_HASH(romstr); return romstr; } } } #endif /* DUK_USE_ROM_STRINGS */ #if defined(DUK_USE_STRTAB_CHAIN) res = duk__find_matching_string_chain(heap, str, blen, *out_strhash); #elif defined(DUK_USE_STRTAB_PROBE) res = duk__find_matching_string_probe(heap, #if defined(DUK_USE_HEAPPTR16) heap->strtable16, #else heap->strtable, #endif heap->st_size, str, blen, *out_strhash); #else #error internal error, invalid strtab options #endif return res; }
DUK_INTERNAL void duk_hthread_create_builtin_objects(duk_hthread *thr) { /* Setup builtins from ROM objects. All heaps/threads will share * the same readonly objects. */ duk_small_uint_t i; for (i = 0; i < DUK_NUM_BUILTINS; i++) { duk_hobject *h; h = (duk_hobject *) DUK_LOSE_CONST(duk_rom_builtins_bidx[i]); DUK_ASSERT(h != NULL); thr->builtins[i] = h; } #if defined(DUK_USE_ROM_GLOBAL_CLONE) || defined(DUK_USE_ROM_GLOBAL_INHERIT) /* By default the global object is read-only which is often much * more of an issue than having read-only built-in objects (like * RegExp, Date, etc). Use a RAM-based copy of the global object * and the global environment object for convenience. */ duk__duplicate_ram_global_object(thr); #endif }
DUK_LOCAL duk_hstring *duk__do_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) { duk_hstring *res; const duk_uint8_t *extdata; #if defined(DUK_USE_MARK_AND_SWEEP) duk_small_uint_t prev_mark_and_sweep_base_flags; #endif /* Prevent any side effects on the string table and the caller provided * str/blen arguments while interning is in progress. For example, if * the caller provided str/blen from a dynamic buffer, a finalizer might * resize that dynamic buffer, invalidating the call arguments. */ #if defined(DUK_USE_MARK_AND_SWEEP) DUK_ASSERT((heap->mark_and_sweep_base_flags & DUK_MS_FLAG_NO_STRINGTABLE_RESIZE) == 0); prev_mark_and_sweep_base_flags = heap->mark_and_sweep_base_flags; DUK__PREVENT_MS_SIDE_EFFECTS(heap); #endif #if defined(DUK_USE_STRTAB_PROBE) if (duk__recheck_strtab_size_probe(heap, heap->st_used + 1)) { goto failed; } #endif /* For manual testing only. */ #if 0 { duk_size_t i; DUK_PRINTF("INTERN: \""); for (i = 0; i < blen; i++) { duk_uint8_t x = str[i]; if (x >= 0x20 && x <= 0x7e && x != '"' && x != '\\') { DUK_PRINTF("%c", (int) x); /* char: use int cast */ } else { DUK_PRINTF("\\x%02lx", (long) x); } } DUK_PRINTF("\"\n"); } #endif #if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_INTERN_CHECK) extdata = (const duk_uint8_t *) DUK_USE_EXTSTR_INTERN_CHECK(heap->heap_udata, (void *) DUK_LOSE_CONST(str), (duk_size_t) blen); #else extdata = (const duk_uint8_t *) NULL; #endif res = duk__alloc_init_hstring(heap, str, blen, strhash, extdata); if (!res) { goto failed; } #if defined(DUK_USE_STRTAB_CHAIN) if (duk__insert_hstring_chain(heap, res)) { /* failed */ DUK_FREE(heap, res); goto failed; } #elif defined(DUK_USE_STRTAB_PROBE) /* guaranteed to succeed */ duk__insert_hstring_probe(heap, #if defined(DUK_USE_HEAPPTR16) heap->strtable16, #else heap->strtable, #endif heap->st_size, &heap->st_used, res); #else #error internal error, invalid strtab options #endif /* Note: hstring is in heap but has refcount zero and is not strongly reachable. * Caller should increase refcount and make the hstring reachable before any * operations which require allocation (and possible gc). */ done: #if defined(DUK_USE_MARK_AND_SWEEP) heap->mark_and_sweep_base_flags = prev_mark_and_sweep_base_flags; #endif return res; failed: res = NULL; goto done; }