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;
}
예제 #2
0
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;
}