Github User Fetcher 1.0.0
C Application with Server and GUI
Loading...
Searching...
No Matches
duk_heap_stringtable.c File Reference
#include "duk_internal.h"

Go to the source code of this file.

Macros

#define DUK__HASH_INITIAL(hash, h_size)   DUK_STRTAB_HASH_INITIAL((hash),(h_size))
 
#define DUK__HASH_PROBE_STEP(hash)   DUK_STRTAB_HASH_PROBE_STEP((hash))
 
#define DUK__DELETED_MARKER(heap)   DUK_STRTAB_DELETED_MARKER((heap))
 
#define DUK__PREVENT_MS_SIDE_EFFECTS(heap)
 

Functions

DUK_LOCAL duk_hstringduk__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_LOCAL duk_int_t duk__count_used_probe (duk_heap *heap)
 
DUK_LOCAL void duk__insert_hstring_probe (duk_heap *heap, duk_hstring **entries, duk_uint32_t size, duk_uint32_t *p_used, duk_hstring *h)
 
DUK_LOCAL duk_hstringduk__find_matching_string_probe (duk_heap *heap, duk_hstring **entries, duk_uint32_t size, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash)
 
DUK_LOCAL void duk__remove_matching_hstring_probe (duk_heap *heap, duk_hstring **entries, duk_uint32_t size, duk_hstring *h)
 
DUK_LOCAL duk_bool_t duk__resize_strtab_raw_probe (duk_heap *heap, duk_uint32_t new_size)
 
DUK_LOCAL duk_bool_t duk__resize_strtab_probe (duk_heap *heap)
 
DUK_LOCAL duk_bool_t duk__recheck_strtab_size_probe (duk_heap *heap, duk_uint32_t new_used)
 
DUK_LOCAL duk_hstringduk__do_intern (duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash)
 
DUK_LOCAL duk_hstringduk__do_lookup (duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t *out_strhash)
 
DUK_INTERNAL duk_hstringduk_heap_string_intern (duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen)
 
DUK_INTERNAL duk_hstringduk_heap_string_intern_checked (duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t blen)
 
DUK_INTERNAL duk_hstringduk_heap_string_intern_u32 (duk_heap *heap, duk_uint32_t val)
 
DUK_INTERNAL duk_hstringduk_heap_string_intern_u32_checked (duk_hthread *thr, duk_uint32_t val)
 
DUK_INTERNAL void duk_heap_string_remove (duk_heap *heap, duk_hstring *h)
 
DUK_INTERNAL void duk_heap_force_strtab_resize (duk_heap *heap)
 
DUK_INTERNAL void duk_heap_free_strtab (duk_heap *heap)
 

Macro Definition Documentation

◆ DUK__DELETED_MARKER

◆ DUK__HASH_INITIAL

#define DUK__HASH_INITIAL ( hash,
h_size )   DUK_STRTAB_HASH_INITIAL((hash),(h_size))

◆ DUK__HASH_PROBE_STEP

◆ DUK__PREVENT_MS_SIDE_EFFECTS

#define DUK__PREVENT_MS_SIDE_EFFECTS ( heap)
Value:
do { \
(heap)->mark_and_sweep_base_flags |= \
DUK_MS_FLAG_NO_STRINGTABLE_RESIZE | /* avoid recursive string table call */ \
DUK_MS_FLAG_NO_FINALIZERS | /* avoid pressure to add/remove strings, invalidation of call data argument, etc. */ \
DUK_MS_FLAG_NO_OBJECT_COMPACTION; /* avoid array abandoning which interns strings */ \
} while (0)
#define DUK_MS_FLAG_NO_OBJECT_COMPACTION
#define DUK_MS_FLAG_NO_FINALIZERS
#define DUK_MS_FLAG_NO_STRINGTABLE_RESIZE

Definition at line 14 of file duktape-1.5.2/src-separate/duk_heap_stringtable.c.

14#define DUK__PREVENT_MS_SIDE_EFFECTS(heap) do { \
15 (heap)->mark_and_sweep_base_flags |= \
16 DUK_MS_FLAG_NO_STRINGTABLE_RESIZE | /* avoid recursive string table call */ \
17 DUK_MS_FLAG_NO_FINALIZERS | /* avoid pressure to add/remove strings, invalidation of call data argument, etc. */ \
18 DUK_MS_FLAG_NO_OBJECT_COMPACTION; /* avoid array abandoning which interns strings */ \
19 } while (0)

Referenced by duk__do_intern(), and duk_heap_force_strtab_resize().

Function Documentation

◆ duk__alloc_init_hstring()

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 )

Definition at line 32 of file duktape-1.5.2/src-separate/duk_heap_stringtable.c.

36 {
37 duk_hstring *res = NULL;
38 duk_uint8_t *data;
39 duk_size_t alloc_size;
41 duk_uint32_t clen;
42
43#if defined(DUK_USE_STRLEN16)
44 /* If blen <= 0xffffUL, clen is also guaranteed to be <= 0xffffUL. */
45 if (blen > 0xffffUL) {
46 DUK_D(DUK_DPRINT("16-bit string blen/clen active and blen over 16 bits, reject intern"));
47 return NULL;
48 }
49#endif
50
51 if (extdata) {
52 alloc_size = (duk_size_t) sizeof(duk_hstring_external);
53 res = (duk_hstring *) DUK_ALLOC(heap, alloc_size);
54 if (!res) {
55 goto alloc_error;
56 }
58#if defined(DUK_USE_EXPLICIT_NULL_INIT)
60#endif
62
63 ((duk_hstring_external *) res)->extdata = extdata;
64 } else {
65 /* NUL terminate for convenient C access */
66 alloc_size = (duk_size_t) (sizeof(duk_hstring) + blen + 1);
67 res = (duk_hstring *) DUK_ALLOC(heap, alloc_size);
68 if (!res) {
69 goto alloc_error;
70 }
71 DUK_MEMZERO(res, sizeof(duk_hstring));
72#if defined(DUK_USE_EXPLICIT_NULL_INIT)
74#endif
76
77 data = (duk_uint8_t *) (res + 1);
78 DUK_MEMCPY(data, str, blen);
79 data[blen] = (duk_uint8_t) 0;
80 }
81
83 if (duk_js_to_arrayindex_raw_string(str, blen, &dummy)) {
85 }
86
87 /* All strings beginning with 0xff are treated as "internal",
88 * even strings interned by the user. This allows user code to
89 * create internal properties too, and makes behavior consistent
90 * in case user code happens to use a string also used by Duktape
91 * (such as string has already been interned and has the 'internal'
92 * flag set).
93 */
95 if (blen > 0 && str[0] == (duk_uint8_t) 0xff) {
97 }
98
99 DUK_HSTRING_SET_HASH(res, strhash);
100 DUK_HSTRING_SET_BYTELEN(res, blen);
101
102 clen = (duk_uint32_t) duk_unicode_unvalidated_utf8_length(str, (duk_size_t) blen);
103 DUK_ASSERT(clen <= blen);
104#if defined(DUK_USE_HSTRING_CLEN)
105 DUK_HSTRING_SET_CHARLEN(res, clen);
106#endif
107
108 /* Using an explicit 'ASCII' flag has larger footprint (one call site
109 * only) but is quite useful for the case when there's no explicit
110 * 'clen' in duk_hstring.
111 */
113 if (clen == blen) {
115 }
116
117 DUK_DDD(DUK_DDDPRINT("interned string, hash=0x%08lx, blen=%ld, clen=%ld, has_arridx=%ld, has_extdata=%ld",
118 (unsigned long) DUK_HSTRING_GET_HASH(res),
119 (long) DUK_HSTRING_GET_BYTELEN(res),
120 (long) DUK_HSTRING_GET_CHARLEN(res),
121 (long) (DUK_HSTRING_HAS_ARRIDX(res) ? 1 : 0),
122 (long) (DUK_HSTRING_HAS_EXTDATA(res) ? 1 : 0)));
123
124 return res;
125
126 alloc_error:
127 DUK_FREE(heap, res);
128 return NULL;
129}
#define DUK_MEMZERO(p, n)
#define DUK_HSTRING_HAS_ASCII(x)
DUK_INTERNAL_DECL duk_size_t duk_unicode_unvalidated_utf8_length(const duk_uint8_t *data, duk_size_t blen)
#define DUK_ALLOC(heap, size)
#define DUK_HEAPHDR_STRING_INIT_NULLS(h)
#define DUK_HSTRING_GET_CHARLEN(x)
#define DUK_HSTRING_GET_HASH(x)
#define DUK_FREE(heap, ptr)
#define DUK_HSTRING_HAS_EXTDATA(x)
DUK_INTERNAL_DECL duk_small_int_t duk_js_to_arrayindex_raw_string(const duk_uint8_t *str, duk_uint32_t blen, duk_uarridx_t *out_idx)
#define DUK_HSTRING_GET_BYTELEN(x)
#define DUK_HSTRING_SET_CHARLEN(x, v)
#define DUK_HSTRING_FLAG_EXTDATA
#define DUK_HSTRING_SET_HASH(x, v)
#define DUK_HSTRING_SET_ARRIDX(x)
#define DUK_HSTRING_HAS_INTERNAL(x)
#define DUK_HSTRING_SET_ASCII(x)
#define DUK_HEAPHDR_SET_TYPE_AND_FLAGS(h, tval, fval)
#define DUK_HSTRING_HAS_ARRIDX(x)
#define DUK_HSTRING_SET_INTERNAL(x)
#define DUK_HSTRING_SET_BYTELEN(x, v)
#define NULL
Definition gmacros.h:924

References DUK_ALLOC, DUK_ASSERT, DUK_D, DUK_DDD, DUK_DDDPRINT, DUK_DPRINT, DUK_FREE, DUK_HEAPHDR_SET_TYPE_AND_FLAGS, DUK_HEAPHDR_STRING_INIT_NULLS, DUK_HSTRING_FLAG_EXTDATA, DUK_HSTRING_GET_BYTELEN, DUK_HSTRING_GET_CHARLEN, DUK_HSTRING_GET_HASH, DUK_HSTRING_HAS_ARRIDX, DUK_HSTRING_HAS_ASCII, DUK_HSTRING_HAS_EXTDATA, DUK_HSTRING_HAS_INTERNAL, DUK_HSTRING_SET_ARRIDX, DUK_HSTRING_SET_ASCII, DUK_HSTRING_SET_BYTELEN, DUK_HSTRING_SET_CHARLEN, DUK_HSTRING_SET_HASH, DUK_HSTRING_SET_INTERNAL, DUK_HTYPE_STRING, duk_js_to_arrayindex_raw_string(), DUK_MEMCPY, DUK_MEMZERO, duk_unicode_unvalidated_utf8_length(), dummy, duk_hstring::hdr, and NULL.

Referenced by duk__do_intern().

◆ duk__count_used_probe()

DUK_LOCAL duk_int_t duk__count_used_probe ( duk_heap * heap)

Definition at line 469 of file duktape-1.5.2/src-separate/duk_heap_stringtable.c.

469 {
470 duk_int_t res = 0;
472#if defined(DUK_USE_HEAPPTR16)
473 duk_uint16_t null16 = heap->heapptr_null16;
474 duk_uint16_t deleted16 = heap->heapptr_deleted16;
475#endif
476
477 n = (duk_uint_fast32_t) heap->st_size;
478 for (i = 0; i < n; i++) {
479#if defined(DUK_USE_HEAPPTR16)
480 if (heap->strtable16[i] != null16 && heap->strtable16[i] != deleted16) {
481#else
482 if (heap->strtable[i] != NULL && heap->strtable[i] != DUK__DELETED_MARKER(heap)) {
483#endif
484 res++;
485 }
486 }
487 return res;
488}
duk_int_fast32_t duk_int_t
duk_uint32_t duk_uint_fast32_t

References DUK__DELETED_MARKER, duk__insert_hstring_probe(), DUK_LOCAL, NULL, duk_heap::st_size, and duk_heap::strtable.

Referenced by duk__resize_strtab_probe(), and duk__resize_strtab_raw_probe().

◆ duk__do_intern()

DUK_LOCAL duk_hstring * duk__do_intern ( duk_heap * heap,
const duk_uint8_t * str,
duk_uint32_t blen,
duk_uint32_t strhash )

Definition at line 833 of file duktape-1.5.2/src-separate/duk_heap_stringtable.c.

833 {
834 duk_hstring *res;
835 const duk_uint8_t *extdata;
836#if defined(DUK_USE_MARK_AND_SWEEP)
837 duk_small_uint_t prev_mark_and_sweep_base_flags;
838#endif
839
840 /* Prevent any side effects on the string table and the caller provided
841 * str/blen arguments while interning is in progress. For example, if
842 * the caller provided str/blen from a dynamic buffer, a finalizer might
843 * resize that dynamic buffer, invalidating the call arguments.
844 */
845#if defined(DUK_USE_MARK_AND_SWEEP)
847 prev_mark_and_sweep_base_flags = heap->mark_and_sweep_base_flags;
849#endif
850
851#if defined(DUK_USE_STRTAB_PROBE)
852 if (duk__recheck_strtab_size_probe(heap, heap->st_used + 1)) {
853 goto failed;
854 }
855#endif
856
857 /* For manual testing only. */
858#if 0
859 {
860 duk_size_t i;
861 DUK_PRINTF("INTERN: \"");
862 for (i = 0; i < blen; i++) {
863 duk_uint8_t x = str[i];
864 if (x >= 0x20 && x <= 0x7e && x != '"' && x != '\\') {
865 DUK_PRINTF("%c", (int) x); /* char: use int cast */
866 } else {
867 DUK_PRINTF("\\x%02lx", (long) x);
868 }
869 }
870 DUK_PRINTF("\"\n");
871 }
872#endif
873
874#if defined(DUK_USE_HSTRING_EXTDATA) && defined(DUK_USE_EXTSTR_INTERN_CHECK)
875 extdata = (const duk_uint8_t *) DUK_USE_EXTSTR_INTERN_CHECK(heap->heap_udata, (void *) DUK_LOSE_CONST(str), (duk_size_t) blen);
876#else
877 extdata = (const duk_uint8_t *) NULL;
878#endif
879 res = duk__alloc_init_hstring(heap, str, blen, strhash, extdata);
880 if (!res) {
881 goto failed;
882 }
883
884#if defined(DUK_USE_STRTAB_CHAIN)
885 if (duk__insert_hstring_chain(heap, res)) {
886 /* failed */
887 DUK_FREE(heap, res);
888 goto failed;
889 }
890#elif defined(DUK_USE_STRTAB_PROBE)
891 /* guaranteed to succeed */
893#if defined(DUK_USE_HEAPPTR16)
894 heap->strtable16,
895#else
896 heap->strtable,
897#endif
898 heap->st_size,
899 &heap->st_used,
900 res);
901#else
902#error internal error, invalid strtab options
903#endif
904
905 /* Note: hstring is in heap but has refcount zero and is not strongly reachable.
906 * Caller should increase refcount and make the hstring reachable before any
907 * operations which require allocation (and possible gc).
908 */
909
910 done:
911#if defined(DUK_USE_MARK_AND_SWEEP)
912 heap->mark_and_sweep_base_flags = prev_mark_and_sweep_base_flags;
913#endif
914 return res;
915
916 failed:
917 res = NULL;
918 goto done;
919}
unsigned int duk_small_uint_t
#define DUK_LOSE_CONST(src)
DUK_LOCAL duk_bool_t duk__recheck_strtab_size_probe(duk_heap *heap, duk_uint32_t new_used)
DUK_LOCAL void duk__insert_hstring_probe(duk_heap *heap, duk_hstring **entries, duk_uint32_t size, duk_uint32_t *p_used, duk_hstring *h)
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_small_uint_t mark_and_sweep_base_flags

References duk__alloc_init_hstring(), duk__insert_hstring_probe(), DUK__PREVENT_MS_SIDE_EFFECTS, duk__recheck_strtab_size_probe(), DUK_ASSERT, DUK_FREE, DUK_LOSE_CONST, DUK_MS_FLAG_NO_STRINGTABLE_RESIZE, DUK_PRINTF, duk_heap::heap_udata, duk_heap::mark_and_sweep_base_flags, NULL, duk_heap::st_size, duk_heap::st_used, and duk_heap::strtable.

Referenced by duk_heap_string_intern().

◆ duk__do_lookup()

DUK_LOCAL duk_hstring * duk__do_lookup ( duk_heap * heap,
const duk_uint8_t * str,
duk_uint32_t blen,
duk_uint32_t * out_strhash )

Definition at line 921 of file duktape-1.5.2/src-separate/duk_heap_stringtable.c.

921 {
922 duk_hstring *res;
923
924 DUK_ASSERT(out_strhash);
925
926 *out_strhash = duk_heap_hashstring(heap, str, (duk_size_t) blen);
927
928#if defined(DUK_USE_ROM_STRINGS)
929 {
931 /* XXX: This is VERY inefficient now, and should be e.g. a
932 * binary search or perfect hash, to be fixed.
933 */
934 for (i = 0; i < (duk_small_uint_t) (sizeof(duk_rom_strings) / sizeof(duk_hstring *)); i++) {
935 duk_hstring *romstr;
936 romstr = (duk_hstring *) DUK_LOSE_CONST(duk_rom_strings[i]);
937 if (blen == DUK_HSTRING_GET_BYTELEN(romstr) &&
938 DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(romstr), blen) == 0) {
939 DUK_DD(DUK_DDPRINT("intern check: rom string: %!O, computed hash 0x%08lx, rom hash 0x%08lx",
940 romstr, (unsigned long) *out_strhash, (unsigned long) DUK_HSTRING_GET_HASH(romstr)));
941 DUK_ASSERT(*out_strhash == DUK_HSTRING_GET_HASH(romstr));
942 *out_strhash = DUK_HSTRING_GET_HASH(romstr);
943 return romstr;
944 }
945 }
946 }
947#endif /* DUK_USE_ROM_STRINGS */
948
949#if defined(DUK_USE_STRTAB_CHAIN)
950 res = duk__find_matching_string_chain(heap, str, blen, *out_strhash);
951#elif defined(DUK_USE_STRTAB_PROBE)
953#if defined(DUK_USE_HEAPPTR16)
954 heap->strtable16,
955#else
956 heap->strtable,
957#endif
958 heap->st_size,
959 str,
960 blen,
961 *out_strhash);
962#else
963#error internal error, invalid strtab options
964#endif
965
966 return res;
967}
#define DUK_HSTRING_GET_DATA(x)
DUK_INTERNAL_DECL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len)
DUK_LOCAL duk_hstring * duk__find_matching_string_probe(duk_heap *heap, duk_hstring **entries, duk_uint32_t size, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash)

References duk__find_matching_string_probe(), DUK_ASSERT, DUK_DD, DUK_DDPRINT, duk_heap_hashstring(), DUK_HSTRING_GET_BYTELEN, DUK_HSTRING_GET_DATA, DUK_HSTRING_GET_HASH, DUK_LOSE_CONST, DUK_MEMCMP, duk_heap::st_size, and duk_heap::strtable.

Referenced by duk_heap_string_intern().

◆ duk__find_matching_string_probe()

DUK_LOCAL duk_hstring * duk__find_matching_string_probe ( duk_heap * heap,
duk_hstring ** entries,
duk_uint32_t size,
const duk_uint8_t * str,
duk_uint32_t blen,
duk_uint32_t strhash )

Definition at line 554 of file duktape-1.5.2/src-separate/duk_heap_stringtable.c.

554 {
555#endif
556 duk_uint32_t i;
557 duk_uint32_t step;
558
559 DUK_ASSERT(size > 0);
560
561 i = DUK__HASH_INITIAL(strhash, size);
562 step = DUK__HASH_PROBE_STEP(strhash);
563 for (;;) {
564 duk_hstring *e;
565#if defined(DUK_USE_HEAPPTR16)
566 e = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, entries16[i]);
567#else
568 e = entries[i];
569#endif
570
571 if (!e) {
572 return NULL;
573 }
574 if (e != DUK__DELETED_MARKER(heap) && DUK_HSTRING_GET_BYTELEN(e) == blen) {
575 if (DUK_MEMCMP((const void *) str, (const void *) DUK_HSTRING_GET_DATA(e), (size_t) blen) == 0) {
576 DUK_DDD(DUK_DDDPRINT("find matching hit: %ld (step %ld, size %ld)",
577 (long) i, (long) step, (long) size));
578 return e;
579 }
580 }
581 DUK_DDD(DUK_DDDPRINT("find matching miss: %ld (step %ld, size %ld)",
582 (long) i, (long) step, (long) size));
583 i = (i + step) % size;
584
585 /* looping should never happen */
586 DUK_ASSERT(i != DUK__HASH_INITIAL(strhash, size));
587 }
589}
#define DUK__HASH_INITIAL(hash, h_size)

References DUK__DELETED_MARKER, DUK__HASH_INITIAL, DUK__HASH_PROBE_STEP, DUK_ASSERT, DUK_DDD, DUK_DDDPRINT, DUK_HSTRING_GET_BYTELEN, DUK_HSTRING_GET_DATA, DUK_MEMCMP, DUK_UNREACHABLE, duk_heap::heap_udata, and NULL.

Referenced by duk__do_lookup(), and duk__insert_hstring_probe().

◆ duk__insert_hstring_probe()

DUK_LOCAL void duk__insert_hstring_probe ( duk_heap * heap,
duk_hstring ** entries,
duk_uint32_t size,
duk_uint32_t * p_used,
duk_hstring * h )

Definition at line 493 of file duktape-1.5.2/src-separate/duk_heap_stringtable.c.

493 {
494#endif
495 duk_uint32_t i;
496 duk_uint32_t step;
497#if defined(DUK_USE_HEAPPTR16)
498 duk_uint16_t null16 = heap->heapptr_null16;
499 duk_uint16_t deleted16 = heap->heapptr_deleted16;
500#endif
501
502 DUK_ASSERT(size > 0);
503
506 for (;;) {
507#if defined(DUK_USE_HEAPPTR16)
508 duk_uint16_t e16 = entries16[i];
509#else
510 duk_hstring *e = entries[i];
511#endif
512
513#if defined(DUK_USE_HEAPPTR16)
514 /* XXX: could check for e16 == 0 because NULL is guaranteed to
515 * encode to zero.
516 */
517 if (e16 == null16) {
518#else
519 if (e == NULL) {
520#endif
521 DUK_DDD(DUK_DDDPRINT("insert hit (null): %ld", (long) i));
522#if defined(DUK_USE_HEAPPTR16)
523 entries16[i] = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
524#else
525 entries[i] = h;
526#endif
527 (*p_used)++;
528 break;
529#if defined(DUK_USE_HEAPPTR16)
530 } else if (e16 == deleted16) {
531#else
532 } else if (e == DUK__DELETED_MARKER(heap)) {
533#endif
534 /* st_used remains the same, DELETED is counted as used */
535 DUK_DDD(DUK_DDDPRINT("insert hit (deleted): %ld", (long) i));
536#if defined(DUK_USE_HEAPPTR16)
537 entries16[i] = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
538#else
539 entries[i] = h;
540#endif
541 break;
542 }
543 DUK_DDD(DUK_DDDPRINT("insert miss: %ld", (long) i));
544 i = (i + step) % size;
545
546 /* looping should never happen */
548 }
549}

References DUK__DELETED_MARKER, duk__find_matching_string_probe(), DUK__HASH_INITIAL, DUK__HASH_PROBE_STEP, DUK_ASSERT, DUK_DDD, DUK_DDDPRINT, DUK_HSTRING_GET_HASH, DUK_LOCAL, duk_heap::heap_udata, and NULL.

Referenced by duk__count_used_probe(), duk__do_intern(), and duk__resize_strtab_raw_probe().

◆ duk__recheck_strtab_size_probe()

DUK_LOCAL duk_bool_t duk__recheck_strtab_size_probe ( duk_heap * heap,
duk_uint32_t new_used )

Definition at line 780 of file duktape-1.5.2/src-separate/duk_heap_stringtable.c.

780 {
781 duk_uint32_t new_free;
782 duk_uint32_t tmp1;
783 duk_uint32_t tmp2;
784
785 DUK_ASSERT(new_used <= heap->st_size); /* grow by at most one */
786 new_free = heap->st_size - new_used; /* unsigned intentionally */
787
788 /* new_free / size <= 1 / DIV <=> new_free <= size / DIV */
789 /* new_used / size <= 1 / DIV <=> new_used <= size / DIV */
790
793
794 if (new_free <= tmp1 || new_used <= tmp2) {
795 /* load factor too low or high, count actually used entries and resize */
796 return duk__resize_strtab_probe(heap);
797 } else {
798 return 0; /* OK */
799 }
800}
#define DUK_STRTAB_MIN_USED_DIVISOR
#define DUK_STRTAB_MIN_FREE_DIVISOR
DUK_LOCAL duk_bool_t duk__resize_strtab_probe(duk_heap *heap)

References duk__resize_strtab_probe(), DUK_ASSERT, DUK_STRTAB_MIN_FREE_DIVISOR, DUK_STRTAB_MIN_USED_DIVISOR, and duk_heap::st_size.

Referenced by duk__do_intern().

◆ duk__remove_matching_hstring_probe()

DUK_LOCAL void duk__remove_matching_hstring_probe ( duk_heap * heap,
duk_hstring ** entries,
duk_uint32_t size,
duk_hstring * h )

Definition at line 594 of file duktape-1.5.2/src-separate/duk_heap_stringtable.c.

594 {
595#endif
596 duk_uint32_t i;
597 duk_uint32_t step;
598 duk_uint32_t hash;
599#if defined(DUK_USE_HEAPPTR16)
600 duk_uint16_t null16 = heap->heapptr_null16;
601 duk_uint16_t h16 = DUK_USE_HEAPPTR_ENC16(heap->heap_udata, (void *) h);
602#endif
603
604 DUK_ASSERT(size > 0);
605
606 hash = DUK_HSTRING_GET_HASH(h);
607 i = DUK__HASH_INITIAL(hash, size);
608 step = DUK__HASH_PROBE_STEP(hash);
609 for (;;) {
610#if defined(DUK_USE_HEAPPTR16)
611 duk_uint16_t e16 = entries16[i];
612#else
613 duk_hstring *e = entries[i];
614#endif
615
616#if defined(DUK_USE_HEAPPTR16)
617 if (e16 == null16) {
618#else
619 if (!e) {
620#endif
622 break;
623 }
624#if defined(DUK_USE_HEAPPTR16)
625 if (e16 == h16) {
626#else
627 if (e == h) {
628#endif
629 /* st_used remains the same, DELETED is counted as used */
630 DUK_DDD(DUK_DDDPRINT("free matching hit: %ld", (long) i));
631#if defined(DUK_USE_HEAPPTR16)
632 entries16[i] = heap->heapptr_deleted16;
633#else
634 entries[i] = DUK__DELETED_MARKER(heap);
635#endif
636 break;
637 }
638
639 DUK_DDD(DUK_DDDPRINT("free matching miss: %ld", (long) i));
640 i = (i + step) % size;
641
642 /* looping should never happen */
643 DUK_ASSERT(i != DUK__HASH_INITIAL(hash, size));
644 }
645}

References DUK__DELETED_MARKER, DUK__HASH_INITIAL, DUK__HASH_PROBE_STEP, DUK_ASSERT, DUK_DDD, DUK_DDDPRINT, DUK_HSTRING_GET_HASH, DUK_UNREACHABLE, and duk_heap::heap_udata.

Referenced by duk_heap_string_remove().

◆ duk__resize_strtab_probe()

DUK_LOCAL duk_bool_t duk__resize_strtab_probe ( duk_heap * heap)

Definition at line 758 of file duktape-1.5.2/src-separate/duk_heap_stringtable.c.

758 {
759 duk_uint32_t new_size;
760 duk_bool_t ret;
761
762 new_size = (duk_uint32_t) duk__count_used_probe(heap);
763 if (new_size >= 0x80000000UL) {
765 } else {
767 new_size = duk_util_get_hash_prime(new_size);
768 }
769 DUK_ASSERT(new_size > 0);
770
771 /* rehash even if old and new sizes are the same to get rid of
772 * DELETED entries.
773 */
774
775 ret = duk__resize_strtab_raw_probe(heap, new_size);
776
777 return ret;
778}
duk_small_int_t duk_bool_t
#define DUK_STRTAB_HIGHEST_32BIT_PRIME
#define DUK_STRTAB_GROW_ST_SIZE(n)
DUK_INTERNAL_DECL duk_uint32_t duk_util_get_hash_prime(duk_uint32_t size)
DUK_LOCAL duk_bool_t duk__resize_strtab_raw_probe(duk_heap *heap, duk_uint32_t new_size)
DUK_LOCAL duk_int_t duk__count_used_probe(duk_heap *heap)

References duk__count_used_probe(), duk__resize_strtab_raw_probe(), DUK_ASSERT, DUK_STRTAB_GROW_ST_SIZE, DUK_STRTAB_HIGHEST_32BIT_PRIME, and duk_util_get_hash_prime().

Referenced by duk__recheck_strtab_size_probe(), and duk_heap_force_strtab_resize().

◆ duk__resize_strtab_raw_probe()

DUK_LOCAL duk_bool_t duk__resize_strtab_raw_probe ( duk_heap * heap,
duk_uint32_t new_size )

Definition at line 647 of file duktape-1.5.2/src-separate/duk_heap_stringtable.c.

647 {
648#if defined(DUK_USE_DEBUG)
649 duk_uint32_t old_used = heap->st_used;
650#endif
651 duk_uint32_t old_size = heap->st_size;
652#if defined(DUK_USE_HEAPPTR16)
653 duk_uint16_t *old_entries = heap->strtable16;
654 duk_uint16_t *new_entries = NULL;
655#else
656 duk_hstring **old_entries = heap->strtable;
657 duk_hstring **new_entries = NULL;
658#endif
659 duk_uint32_t new_used = 0;
660 duk_uint32_t i;
661
662#if defined(DUK_USE_DEBUG)
663 DUK_UNREF(old_used); /* unused with some debug level combinations */
664#endif
665
666#ifdef DUK_USE_DDDPRINT
667 DUK_DDD(DUK_DDDPRINT("attempt to resize stringtable: %ld entries, %ld bytes, %ld used, %ld%% load -> %ld entries, %ld bytes, %ld used, %ld%% load",
668 (long) old_size, (long) (sizeof(duk_hstring *) * old_size), (long) old_used,
669 (long) (((double) old_used) / ((double) old_size) * 100.0),
670 (long) new_size, (long) (sizeof(duk_hstring *) * new_size), (long) duk__count_used_probe(heap),
671 (long) (((double) duk__count_used_probe(heap)) / ((double) new_size) * 100.0)));
672#endif
673
674 DUK_ASSERT(new_size > (duk_uint32_t) duk__count_used_probe(heap)); /* required for rehash to succeed, equality not that useful */
675 DUK_ASSERT(old_entries);
676
677 /*
678 * The attempt to allocate may cause a GC. Such a GC must not attempt to resize
679 * the stringtable (though it can be swept); finalizer execution and object
680 * compaction must also be postponed to avoid the pressure to add strings to the
681 * string table. Call site must prevent these.
682 */
683
684#if defined(DUK_USE_MARK_AND_SWEEP)
688#endif
689
690#if defined(DUK_USE_HEAPPTR16)
691 new_entries = (duk_uint16_t *) DUK_ALLOC(heap, sizeof(duk_uint16_t) * new_size);
692#else
693 new_entries = (duk_hstring **) DUK_ALLOC(heap, sizeof(duk_hstring *) * new_size);
694#endif
695
696 if (!new_entries) {
697 goto resize_error;
698 }
699
700#if defined(DUK_USE_EXPLICIT_NULL_INIT)
701 for (i = 0; i < new_size; i++) {
702#if defined(DUK_USE_HEAPPTR16)
703 new_entries[i] = heap->heapptr_null16;
704#else
705 new_entries[i] = NULL;
706#endif
707 }
708#else
709#if defined(DUK_USE_HEAPPTR16)
710 /* Relies on NULL encoding to zero. */
711 DUK_MEMZERO(new_entries, sizeof(duk_uint16_t) * new_size);
712#else
713 DUK_MEMZERO(new_entries, sizeof(duk_hstring *) * new_size);
714#endif
715#endif
716
717 /* Because new_size > duk__count_used_probe(heap), guaranteed to work */
718 for (i = 0; i < old_size; i++) {
719 duk_hstring *e;
720
721#if defined(DUK_USE_HEAPPTR16)
722 e = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, old_entries[i]);
723#else
724 e = old_entries[i];
725#endif
726 if (e == NULL || e == DUK__DELETED_MARKER(heap)) {
727 continue;
728 }
729 /* checking for DUK__DELETED_MARKER is not necessary here, but helper does it now */
730 duk__insert_hstring_probe(heap, new_entries, new_size, &new_used, e);
731 }
732
733#ifdef DUK_USE_DDPRINT
734 DUK_DD(DUK_DDPRINT("resized stringtable: %ld entries, %ld bytes, %ld used, %ld%% load -> %ld entries, %ld bytes, %ld used, %ld%% load",
735 (long) old_size, (long) (sizeof(duk_hstring *) * old_size), (long) old_used,
736 (long) (((double) old_used) / ((double) old_size) * 100.0),
737 (long) new_size, (long) (sizeof(duk_hstring *) * new_size), (long) new_used,
738 (long) (((double) new_used) / ((double) new_size) * 100.0)));
739#endif
740
741#if defined(DUK_USE_HEAPPTR16)
742 DUK_FREE(heap, heap->strtable16);
743 heap->strtable16 = new_entries;
744#else
745 DUK_FREE(heap, heap->strtable);
746 heap->strtable = new_entries;
747#endif
748 heap->st_size = new_size;
749 heap->st_used = new_used; /* may be less, since DELETED entries are NULLed by rehash */
750
751 return 0; /* OK */
752
753 resize_error:
754 DUK_FREE(heap, new_entries);
755 return 1; /* FAIL */
756}

References duk__count_used_probe(), DUK__DELETED_MARKER, duk__insert_hstring_probe(), DUK_ALLOC, DUK_ASSERT, DUK_DD, DUK_DDD, DUK_DDDPRINT, DUK_DDPRINT, DUK_FREE, DUK_MEMZERO, DUK_MS_FLAG_NO_FINALIZERS, DUK_MS_FLAG_NO_OBJECT_COMPACTION, DUK_MS_FLAG_NO_STRINGTABLE_RESIZE, DUK_UNREF, duk_heap::heap_udata, duk_heap::mark_and_sweep_base_flags, NULL, duk_heap::st_size, duk_heap::st_used, and duk_heap::strtable.

Referenced by duk__resize_strtab_probe().

◆ duk_heap_force_strtab_resize()

DUK_INTERNAL void duk_heap_force_strtab_resize ( duk_heap * heap)

Definition at line 1053 of file duktape-1.5.2/src-separate/duk_heap_stringtable.c.

1053 {
1054 duk_small_uint_t prev_mark_and_sweep_base_flags;
1055 /* Force a resize so that DELETED entries are eliminated.
1056 * Another option would be duk__recheck_strtab_size_probe();
1057 * but since that happens on every intern anyway, this whole
1058 * check can now be disabled.
1059 */
1060
1062 prev_mark_and_sweep_base_flags = heap->mark_and_sweep_base_flags;
1064
1065#if defined(DUK_USE_STRTAB_CHAIN)
1066 DUK_UNREF(heap);
1067#elif defined(DUK_USE_STRTAB_PROBE)
1068 (void) duk__resize_strtab_probe(heap);
1069#endif
1070
1071 heap->mark_and_sweep_base_flags = prev_mark_and_sweep_base_flags;
1072}

References DUK__PREVENT_MS_SIDE_EFFECTS, duk__resize_strtab_probe(), DUK_ASSERT, DUK_MS_FLAG_NO_STRINGTABLE_RESIZE, DUK_UNREF, and duk_heap::mark_and_sweep_base_flags.

◆ duk_heap_free_strtab()

DUK_INTERNAL void duk_heap_free_strtab ( duk_heap * heap)

Definition at line 1139 of file duktape-1.5.2/src-separate/duk_heap_stringtable.c.

1139 {
1141 duk_hstring *h;
1142
1143#if defined(DUK_USE_HEAPPTR16)
1144 if (heap->strtable16) {
1145#else
1146 if (heap->strtable) {
1147#endif
1148 for (i = 0; i < (duk_uint_fast32_t) heap->st_size; i++) {
1149#if defined(DUK_USE_HEAPPTR16)
1150 h = (duk_hstring *) DUK_USE_HEAPPTR_DEC16(heap->heap_udata, heap->strtable16[i]);
1151#else
1152 h = heap->strtable[i];
1153#endif
1154 if (h == NULL || h == DUK_STRTAB_DELETED_MARKER(heap)) {
1155 continue;
1156 }
1157 DUK_ASSERT(h != NULL);
1158
1159 /* strings may have inner refs (extdata) in some cases */
1160 duk_free_hstring_inner(heap, h);
1161 DUK_FREE(heap, h);
1162#if 0 /* not strictly necessary */
1163 heap->strtable[i] = NULL;
1164#endif
1165 }
1166#if defined(DUK_USE_HEAPPTR16)
1167 DUK_FREE(heap, heap->strtable16);
1168#else
1169 DUK_FREE(heap, heap->strtable);
1170#endif
1171#if 0 /* not strictly necessary */
1172 heap->strtable = NULL;
1173#endif
1174 }
1175}
#define DUK_STRTAB_DELETED_MARKER(heap)
DUK_INTERNAL_DECL void duk_free_hstring_inner(duk_heap *heap, duk_hstring *h)

References DUK_ASSERT, DUK_FREE, duk_free_hstring_inner(), DUK_STRTAB_DELETED_MARKER, duk_heap::heap_udata, NULL, duk_heap::st_size, and duk_heap::strtable.

◆ duk_heap_string_intern()

DUK_INTERNAL duk_hstring * duk_heap_string_intern ( duk_heap * heap,
const duk_uint8_t * str,
duk_uint32_t blen )

Definition at line 980 of file duktape-1.5.2/src-separate/duk_heap_stringtable.c.

980 {
981 duk_hstring *res;
982 duk_uint32_t strhash;
983
984 /* caller is responsible for ensuring this */
986
987 res = duk__do_lookup(heap, str, blen, &strhash);
988 if (res) {
989 return res;
990 }
991
992 res = duk__do_intern(heap, str, blen, strhash);
993 return res; /* may be NULL */
994}
#define DUK_HSTRING_MAX_BYTELEN
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_LOCAL duk_hstring * duk__do_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen, duk_uint32_t strhash)

References duk__do_intern(), duk__do_lookup(), DUK_ASSERT, and DUK_HSTRING_MAX_BYTELEN.

Referenced by duk_heap_string_intern_checked(), and duk_heap_string_intern_u32().

◆ duk_heap_string_intern_checked()

DUK_INTERNAL duk_hstring * duk_heap_string_intern_checked ( duk_hthread * thr,
const duk_uint8_t * str,
duk_uint32_t blen )

Definition at line 996 of file duktape-1.5.2/src-separate/duk_heap_stringtable.c.

996 {
997 duk_hstring *res = duk_heap_string_intern(thr->heap, str, blen);
998 if (!res) {
1000 }
1001 return res;
1002}
#define DUK_ERROR_ALLOC_DEFMSG(thr)
DUK_INTERNAL duk_hstring * duk_heap_string_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen)

References DUK_ERROR_ALLOC_DEFMSG, duk_heap_string_intern(), and duk_hthread::heap.

◆ duk_heap_string_intern_u32()

DUK_INTERNAL duk_hstring * duk_heap_string_intern_u32 ( duk_heap * heap,
duk_uint32_t val )

Definition at line 1014 of file duktape-1.5.2/src-separate/duk_heap_stringtable.c.

1014 {
1015 char buf[DUK_STRTAB_U32_MAX_STRLEN+1];
1016 DUK_SNPRINTF(buf, sizeof(buf), "%lu", (unsigned long) val);
1017 buf[sizeof(buf) - 1] = (char) 0;
1018 DUK_ASSERT(DUK_STRLEN(buf) <= DUK_UINT32_MAX); /* formatted result limited */
1019 return duk_heap_string_intern(heap, (const duk_uint8_t *) buf, (duk_uint32_t) DUK_STRLEN(buf));
1020}
#define DUK_STRTAB_U32_MAX_STRLEN

References DUK_ASSERT, duk_heap_string_intern(), DUK_SNPRINTF, DUK_STRLEN, DUK_STRTAB_U32_MAX_STRLEN, and DUK_UINT32_MAX.

Referenced by duk_heap_string_intern_u32_checked().

◆ duk_heap_string_intern_u32_checked()

DUK_INTERNAL duk_hstring * duk_heap_string_intern_u32_checked ( duk_hthread * thr,
duk_uint32_t val )

Definition at line 1022 of file duktape-1.5.2/src-separate/duk_heap_stringtable.c.

1022 {
1024 if (!res) {
1026 }
1027 return res;
1028}
DUK_INTERNAL duk_hstring * duk_heap_string_intern_u32(duk_heap *heap, duk_uint32_t val)

References DUK_ERROR_ALLOC_DEFMSG, duk_heap_string_intern_u32(), and duk_hthread::heap.

◆ duk_heap_string_remove()

DUK_INTERNAL void duk_heap_string_remove ( duk_heap * heap,
duk_hstring * h )

Definition at line 1032 of file duktape-1.5.2/src-separate/duk_heap_stringtable.c.

1032 {
1033 DUK_DDD(DUK_DDDPRINT("remove string from stringtable: %!O", (duk_heaphdr *) h));
1034
1035#if defined(DUK_USE_STRTAB_CHAIN)
1036 duk__remove_matching_hstring_chain(heap, h);
1037#elif defined(DUK_USE_STRTAB_PROBE)
1039#if defined(DUK_USE_HEAPPTR16)
1040 heap->strtable16,
1041#else
1042 heap->strtable,
1043#endif
1044 heap->st_size,
1045 h);
1046#else
1047#error internal error, invalid strtab options
1048#endif
1049}
DUK_LOCAL void duk__remove_matching_hstring_probe(duk_heap *heap, duk_hstring **entries, duk_uint32_t size, duk_hstring *h)

References duk__remove_matching_hstring_probe(), DUK_DDD, DUK_DDDPRINT, duk_heap::st_size, and duk_heap::strtable.