static duk_hstring *duk__do_intern(duk_heap *heap, duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) { duk_hstring *res; if (duk__recheck_strtab_size(heap, heap->st_used + 1)) { return NULL; } res = duk__alloc_init_hstring(heap, str, blen, strhash); if (!res) { return NULL; } duk__insert_hstring(heap, heap->st, heap->st_size, &heap->st_used, res); /* guaranteed to succeed */ /* 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). */ return res; }
static duk_hstring *duk__do_intern(duk_heap *heap, duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) { duk_hstring *res; if (duk__recheck_strtab_size(heap, heap->st_used + 1)) { return NULL; } /* For manual testing only. */ #if 0 { duk_size_t i; printf("INTERN: \""); for (i = 0; i < blen; i++) { duk_uint8_t x = str[i]; if (x >= 0x20 && x <= 0x7e && x != '"' && x != '\\') { printf("%c", (int) x); /* char: use int cast */ } else { printf("\\x%02lx", (long) x); } } printf("\"\n"); } #endif res = duk__alloc_init_hstring(heap, str, blen, strhash); if (!res) { return NULL; } duk__insert_hstring(heap, heap->st, heap->st_size, &heap->st_used, res); /* guaranteed to succeed */ /* 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). */ return res; }
static int duk__resize_strtab_raw(duk_heap *heap, duk_uint32_t new_size) { #ifdef DUK_USE_MARK_AND_SWEEP int prev_mark_and_sweep_base_flags; #endif #ifdef DUK_USE_DEBUG duk_uint32_t old_used = heap->st_used; #endif duk_uint32_t old_size = heap->st_size; duk_hstring **old_entries = heap->st; duk_hstring **new_entries = NULL; duk_uint32_t new_used = 0; duk_uint32_t i; #ifdef DUK_USE_DEBUG DUK_UNREF(old_used); /* unused with some debug level combinations */ #endif #ifdef DUK_USE_DDDPRINT DUK_DDD(DUK_DDDPRINT("attempt to resize stringtable: %d entries, %d bytes, %d used, %d%% load -> %d entries, %d bytes, %d used, %d%% load", (int) old_size, (int) (sizeof(duk_hstring *) * old_size), (int) old_used, (int) (((double) old_used) / ((double) old_size) * 100.0), (int) new_size, (int) (sizeof(duk_hstring *) * new_size), (int) duk__count_used(heap), (int) (((double) duk__count_used(heap)) / ((double) new_size) * 100.0))); #endif DUK_ASSERT(new_size > (duk_uint32_t) duk__count_used(heap)); /* required for rehash to succeed, equality not that useful */ DUK_ASSERT(old_entries); #ifdef DUK_USE_MARK_AND_SWEEP DUK_ASSERT((heap->mark_and_sweep_base_flags & DUK_MS_FLAG_NO_STRINGTABLE_RESIZE) == 0); #endif /* * The attempt to allocate may cause a GC. Such a GC must not attempt to resize * the stringtable (though it can be swept); finalizer execution and object * compaction must also be postponed to avoid the pressure to add strings to the * string table. */ #ifdef DUK_USE_MARK_AND_SWEEP prev_mark_and_sweep_base_flags = heap->mark_and_sweep_base_flags; heap->mark_and_sweep_base_flags |= \ DUK_MS_FLAG_NO_STRINGTABLE_RESIZE | /* avoid recursive call here */ DUK_MS_FLAG_NO_FINALIZERS | /* avoid pressure to add/remove strings */ DUK_MS_FLAG_NO_OBJECT_COMPACTION; /* avoid array abandoning which interns strings */ #endif new_entries = (duk_hstring **) DUK_ALLOC(heap, sizeof(duk_hstring *) * new_size); #ifdef DUK_USE_MARK_AND_SWEEP heap->mark_and_sweep_base_flags = prev_mark_and_sweep_base_flags; #endif if (!new_entries) { goto error; } #ifdef DUK_USE_EXPLICIT_NULL_INIT for (i = 0; i < new_size; i++) { new_entries[i] = NULL; } #else DUK_MEMZERO(new_entries, sizeof(duk_hstring *) * new_size); #endif /* Because new_size > duk__count_used(heap), guaranteed to work */ for (i = 0; i < old_size; i++) { duk_hstring *e; e = old_entries[i]; if (e == NULL || e == DUK__DELETED_MARKER(heap)) { continue; } /* checking for DUK__DELETED_MARKER is not necessary here, but helper does it now */ duk__insert_hstring(heap, new_entries, new_size, &new_used, e); } #ifdef DUK_USE_DDPRINT DUK_DD(DUK_DDPRINT("resized stringtable: %d entries, %d bytes, %d used, %d%% load -> %d entries, %d bytes, %d used, %d%% load", (int) old_size, (int) (sizeof(duk_hstring *) * old_size), (int) old_used, (int) (((double) old_used) / ((double) old_size) * 100.0), (int) new_size, (int) (sizeof(duk_hstring *) * new_size), (int) new_used, (int) (((double) new_used) / ((double) new_size) * 100.0))); #endif DUK_FREE(heap, heap->st); heap->st = new_entries; heap->st_size = new_size; heap->st_used = new_used; /* may be less, since DELETED entries are NULLed by rehash */ return 0; /* OK */ error: DUK_FREE(heap, new_entries); return 1; /* FAIL */ }