static void duk__dump_stringtable(duk_heap *heap) { duk_uint_fast32_t i; char buf[64+1]; DUK_D(DUK_DPRINT("stringtable %p, used %ld, size %ld, load %ld%%", (void *) heap->st, (long) heap->st_used, (long) heap->st_size, (long) (((double) heap->st_used) / ((double) heap->st_size) * 100.0))); for (i = 0; i < (duk_uint_fast32_t) heap->st_size; i++) { duk_hstring *e = heap->st[i]; if (!e) { DUK_D(DUK_DPRINT(" [%ld]: NULL", (long) i)); } else if (e == DUK_STRTAB_DELETED_MARKER(heap)) { DUK_D(DUK_DPRINT(" [%ld]: DELETED", (long) i)); } else { duk__sanitize_snippet(buf, sizeof(buf), e); #ifdef DUK_USE_REFERENCE_COUNTING DUK_D(DUK_DPRINT(" [%ld]: %p (flags: 0x%08lx, ref: %ld) '%s', strhash=0x%08lx, blen=%ld, clen=%ld, " "arridx=%ld, internal=%ld, reserved_word=%ld, strict_reserved_word=%ld, eval_or_arguments=%ld", (long) i, (void *) e, (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) e), (long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) e), (const char *) buf, (unsigned long) e->hash, (long) e->blen, (long) e->clen, (long) (DUK_HSTRING_HAS_ARRIDX(e) ? 1 : 0), (long) (DUK_HSTRING_HAS_INTERNAL(e) ? 1 : 0), (long) (DUK_HSTRING_HAS_RESERVED_WORD(e) ? 1 : 0), (long) (DUK_HSTRING_HAS_STRICT_RESERVED_WORD(e) ? 1 : 0), (long) (DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(e) ? 1 : 0))); #else DUK_D(DUK_DPRINT(" [%ld]: %p (flags: 0x%08lx) '%s', strhash=0x%08lx, blen=%ld, clen=%ld, " "arridx=%ld, internal=%ld, reserved_word=%ld, strict_reserved_word=%ld, eval_or_arguments=%ld", (long) i, (void *) e, (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) e), (const char *) buf, (long) e->hash, (long) e->blen, (long) e->clen, (long) (DUK_HSTRING_HAS_ARRIDX(e) ? 1 : 0), (long) (DUK_HSTRING_HAS_INTERNAL(e) ? 1 : 0), (long) (DUK_HSTRING_HAS_RESERVED_WORD(e) ? 1 : 0), (long) (DUK_HSTRING_HAS_STRICT_RESERVED_WORD(e) ? 1 : 0), (long) (DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(e) ? 1 : 0))); #endif } } }
static void dump_stringtable(duk_heap *heap) { duk_uint32_t i; char buf[64+1]; DUK_DPRINT("stringtable %p, used %d, size %d, load %d%%", (void *) heap->st, (int) heap->st_used, (int) heap->st_size, (int) (((double) heap->st_used) / ((double) heap->st_size) * 100.0)); for (i = 0; i < heap->st_size; i++) { duk_hstring *e = heap->st[i]; if (!e) { DUK_DPRINT(" [%d]: NULL", i); } else if (e == DUK_STRTAB_DELETED_MARKER(heap)) { DUK_DPRINT(" [%d]: DELETED", i); } else { sanitize_snippet(buf, sizeof(buf), e); /* FIXME: all string flags not printed now */ #ifdef DUK_USE_REFERENCE_COUNTING DUK_DPRINT(" [%d]: %p (flags: 0x%08x, ref: %d) '%s', strhash=0x%08x, blen=%d, clen=%d, arridx=%d, internal=%d", i, (void *) e, (int) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) e), (int) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr *) e), buf, (int) e->hash, (int) e->blen, (int) e->clen, DUK_HSTRING_HAS_ARRIDX(e) ? 1 : 0, DUK_HSTRING_HAS_INTERNAL(e) ? 1 : 0); #else DUK_DPRINT(" [%d]: %p (flags: 0x%08x) '%s', strhash=0x%08x, blen=%d, clen=%d, arridx=%d, internal=%d", i, (void *) e, (int) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr *) e), buf, (int) e->hash, (int) e->blen, (int) e->clen, DUK_HSTRING_HAS_ARRIDX(e) ? 1 : 0, DUK_HSTRING_HAS_INTERNAL(e) ? 1 : 0); #endif } } }
static duk_hstring *duk__alloc_init_hstring(duk_heap *heap, duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) { duk_hstring *res = NULL; duk_uint8_t *data; duk_size_t alloc_size; duk_uarridx_t dummy; /* NUL terminate for convenient C access */ alloc_size = (duk_size_t) (sizeof(duk_hstring) + blen + 1); res = (duk_hstring *) DUK_ALLOC(heap, alloc_size); if (!res) { goto error; } DUK_MEMZERO(res, sizeof(duk_hstring)); #ifdef DUK_USE_EXPLICIT_NULL_INIT DUK_HEAPHDR_STRING_INIT_NULLS(&res->hdr); #endif DUK_HEAPHDR_SET_TYPE_AND_FLAGS(&res->hdr, DUK_HTYPE_STRING, 0); if (duk_js_to_arrayindex_raw_string(str, blen, &dummy)) { DUK_HSTRING_SET_ARRIDX(res); } /* All strings beginning with 0xff are treated as "internal", * even strings interned by the user. This allows user code to * create internal properties too, and makes behavior consistent * in case user code happens to use a string also used by Duktape * (such as string has already been interned and has the 'internal' * flag set). */ if (blen > 0 && str[0] == (duk_uint8_t) 0xff) { DUK_HSTRING_SET_INTERNAL(res); } res->hash = strhash; res->blen = blen; res->clen = (duk_uint32_t) duk_unicode_unvalidated_utf8_length(str, (duk_size_t) blen); /* clen <= blen */ data = (duk_uint8_t *) (res + 1); DUK_MEMCPY(data, str, blen); data[blen] = (duk_uint8_t) 0; DUK_DDD(DUK_DDDPRINT("interned string, hash=0x%08lx, blen=%ld, clen=%ld, has_arridx=%ld", (unsigned long) DUK_HSTRING_GET_HASH(res), (long) DUK_HSTRING_GET_BYTELEN(res), (long) DUK_HSTRING_GET_CHARLEN(res), (long) DUK_HSTRING_HAS_ARRIDX(res) ? 1 : 0)); return res; error: DUK_FREE(heap, res); return NULL; }
/* Called by duk_hstring.h macros */ DUK_INTERNAL duk_uarridx_t duk_js_to_arrayindex_string_helper(duk_hstring *h) { duk_uarridx_t res; duk_small_int_t rc; if (!DUK_HSTRING_HAS_ARRIDX(h)) { return DUK_HSTRING_NO_ARRAY_INDEX; } rc = duk_js_to_arrayindex_raw_string(DUK_HSTRING_GET_DATA(h), DUK_HSTRING_GET_BYTELEN(h), &res); DUK_UNREF(rc); DUK_ASSERT(rc != 0); return res; }
static duk_hstring *duk__alloc_init_hstring(duk_heap *heap, duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash) { duk_hstring *res = NULL; duk_uint8_t *data; duk_uint32_t alloc_size; duk_uint32_t dummy; /* NUL terminate for convenient C access */ alloc_size = sizeof(duk_hstring) + blen + 1; res = (duk_hstring *) DUK_ALLOC(heap, alloc_size); if (!res) { goto error; } DUK_MEMZERO(res, sizeof(duk_hstring)); #ifdef DUK_USE_EXPLICIT_NULL_INIT DUK_HEAPHDR_STRING_INIT_NULLS(&res->hdr); #endif DUK_HEAPHDR_SET_TYPE_AND_FLAGS(&res->hdr, DUK_HTYPE_STRING, 0); if (duk_js_to_arrayindex_raw_string(str, blen, &dummy)) { DUK_HSTRING_SET_ARRIDX(res); } res->hash = strhash; res->blen = blen; res->clen = (duk_uint32_t) duk_unicode_unvalidated_utf8_length(str, (duk_size_t) blen); /* clen <= blen */ data = (duk_uint8_t *) (res + 1); DUK_MEMCPY(data, str, blen); data[blen] = (duk_uint8_t) 0; DUK_DDD(DUK_DDDPRINT("interned string, hash=0x%08x, blen=%d, clen=%d, arridx=%d", DUK_HSTRING_GET_HASH(res), DUK_HSTRING_GET_BYTELEN(res), DUK_HSTRING_GET_CHARLEN(res), DUK_HSTRING_HAS_ARRIDX(res) ? 1 : 0)); return res; error: DUK_FREE(heap, res); return NULL; }
DUK_LOCAL duk_hstring *duk__alloc_init_hstring(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash, const duk_uint8_t *extdata) { duk_hstring *res = NULL; duk_uint8_t *data; duk_size_t alloc_size; duk_uarridx_t dummy; duk_uint32_t clen; #if defined(DUK_USE_STRLEN16) /* If blen <= 0xffffUL, clen is also guaranteed to be <= 0xffffUL. */ if (blen > 0xffffUL) { DUK_D(DUK_DPRINT("16-bit string blen/clen active and blen over 16 bits, reject intern")); return NULL; } #endif if (extdata) { alloc_size = (duk_size_t) sizeof(duk_hstring_external); res = (duk_hstring *) DUK_ALLOC(heap, alloc_size); if (!res) { goto alloc_error; } DUK_MEMZERO(res, sizeof(duk_hstring_external)); #ifdef DUK_USE_EXPLICIT_NULL_INIT DUK_HEAPHDR_STRING_INIT_NULLS(&res->hdr); #endif DUK_HEAPHDR_SET_TYPE_AND_FLAGS(&res->hdr, DUK_HTYPE_STRING, DUK_HSTRING_FLAG_EXTDATA); ((duk_hstring_external *) res)->extdata = extdata; } else { /* NUL terminate for convenient C access */ alloc_size = (duk_size_t) (sizeof(duk_hstring) + blen + 1); res = (duk_hstring *) DUK_ALLOC(heap, alloc_size); if (!res) { goto alloc_error; } DUK_MEMZERO(res, sizeof(duk_hstring)); #ifdef DUK_USE_EXPLICIT_NULL_INIT DUK_HEAPHDR_STRING_INIT_NULLS(&res->hdr); #endif DUK_HEAPHDR_SET_TYPE_AND_FLAGS(&res->hdr, DUK_HTYPE_STRING, 0); data = (duk_uint8_t *) (res + 1); DUK_MEMCPY(data, str, blen); data[blen] = (duk_uint8_t) 0; } if (duk_js_to_arrayindex_raw_string(str, blen, &dummy)) { DUK_HSTRING_SET_ARRIDX(res); } /* All strings beginning with 0xff are treated as "internal", * even strings interned by the user. This allows user code to * create internal properties too, and makes behavior consistent * in case user code happens to use a string also used by Duktape * (such as string has already been interned and has the 'internal' * flag set). */ if (blen > 0 && str[0] == (duk_uint8_t) 0xff) { DUK_HSTRING_SET_INTERNAL(res); } DUK_HSTRING_SET_HASH(res, strhash); DUK_HSTRING_SET_BYTELEN(res, blen); clen = (duk_uint32_t) duk_unicode_unvalidated_utf8_length(str, (duk_size_t) blen); DUK_ASSERT(clen <= blen); DUK_HSTRING_SET_CHARLEN(res, clen); DUK_DDD(DUK_DDDPRINT("interned string, hash=0x%08lx, blen=%ld, clen=%ld, has_arridx=%ld, has_extdata=%ld", (unsigned long) DUK_HSTRING_GET_HASH(res), (long) DUK_HSTRING_GET_BYTELEN(res), (long) DUK_HSTRING_GET_CHARLEN(res), (long) (DUK_HSTRING_HAS_ARRIDX(res) ? 1 : 0), (long) (DUK_HSTRING_HAS_EXTDATA(res) ? 1 : 0))); return res; alloc_error: DUK_FREE(heap, res); return NULL; }