1 /* 2 * Heap structure. 3 * 4 * Heap contains allocated heap objects, interned strings, and built-in 5 * strings for one or more threads. 6 */ 7 8 #ifndef DUK_HEAP_H_INCLUDED 9 #define DUK_HEAP_H_INCLUDED 10 11 /* alloc function typedefs in duktape.h */ 12 13 /* 14 * Heap flags 15 */ 16 17 #define DUK_HEAP_FLAG_MARKANDSWEEP_RUNNING (1 << 0) /* mark-and-sweep is currently running */ 18 #define DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED (1 << 1) /* mark-and-sweep marking reached a recursion limit and must use multi-pass marking */ 19 #define DUK_HEAP_FLAG_REFZERO_FREE_RUNNING (1 << 2) /* refcount code is processing refzero list */ 20 #define DUK_HEAP_FLAG_ERRHANDLER_RUNNING (1 << 3) /* an error handler (user callback to augment/replace error) is running */ 21 #define DUK_HEAP_FLAG_INTERRUPT_RUNNING (1 << 4) /* executor interrupt running (used to avoid nested interrupts) */ 22 #define DUK_HEAP_FLAG_FINALIZER_NORESCUE (1 << 5) /* heap destruction ongoing, finalizer rescue no longer possible */ 23 24 #define DUK__HEAP_HAS_FLAGS(heap,bits) ((heap)->flags & (bits)) 25 #define DUK__HEAP_SET_FLAGS(heap,bits) do { \ 26 (heap)->flags |= (bits); \ 27 } while (0) 28 #define DUK__HEAP_CLEAR_FLAGS(heap,bits) do { \ 29 (heap)->flags &= ~(bits); \ 30 } while (0) 31 32 #define DUK_HEAP_HAS_MARKANDSWEEP_RUNNING(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RUNNING) 33 #define DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED) 34 #define DUK_HEAP_HAS_REFZERO_FREE_RUNNING(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_REFZERO_FREE_RUNNING) 35 #define DUK_HEAP_HAS_ERRHANDLER_RUNNING(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_ERRHANDLER_RUNNING) 36 #define DUK_HEAP_HAS_INTERRUPT_RUNNING(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING) 37 #define DUK_HEAP_HAS_FINALIZER_NORESCUE(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE) 38 39 #define DUK_HEAP_SET_MARKANDSWEEP_RUNNING(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RUNNING) 40 #define DUK_HEAP_SET_MARKANDSWEEP_RECLIMIT_REACHED(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED) 41 #define DUK_HEAP_SET_REFZERO_FREE_RUNNING(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_REFZERO_FREE_RUNNING) 42 #define DUK_HEAP_SET_ERRHANDLER_RUNNING(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_ERRHANDLER_RUNNING) 43 #define DUK_HEAP_SET_INTERRUPT_RUNNING(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING) 44 #define DUK_HEAP_SET_FINALIZER_NORESCUE(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE) 45 46 #define DUK_HEAP_CLEAR_MARKANDSWEEP_RUNNING(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RUNNING) 47 #define DUK_HEAP_CLEAR_MARKANDSWEEP_RECLIMIT_REACHED(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED) 48 #define DUK_HEAP_CLEAR_REFZERO_FREE_RUNNING(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_REFZERO_FREE_RUNNING) 49 #define DUK_HEAP_CLEAR_ERRHANDLER_RUNNING(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_ERRHANDLER_RUNNING) 50 #define DUK_HEAP_CLEAR_INTERRUPT_RUNNING(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING) 51 #define DUK_HEAP_CLEAR_FINALIZER_NORESCUE(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE) 52 53 /* 54 * Longjmp types, also double as identifying continuation type for a rethrow (in 'finally') 55 */ 56 57 #define DUK_LJ_TYPE_UNKNOWN 0 /* unused */ 58 #define DUK_LJ_TYPE_THROW 1 /* value1 -> error object */ 59 #define DUK_LJ_TYPE_YIELD 2 /* value1 -> yield value, iserror -> error / normal */ 60 #define DUK_LJ_TYPE_RESUME 3 /* value1 -> resume value, value2 -> resumee thread, iserror -> error/normal */ 61 #define DUK_LJ_TYPE_BREAK 4 /* value1 -> label number, pseudo-type to indicate a break continuation (for ENDFIN) */ 62 #define DUK_LJ_TYPE_CONTINUE 5 /* value1 -> label number, pseudo-type to indicate a continue continuation (for ENDFIN) */ 63 #define DUK_LJ_TYPE_RETURN 6 /* value1 -> return value, pseudo-type to indicate a return continuation (for ENDFIN) */ 64 #define DUK_LJ_TYPE_NORMAL 7 /* no value, pseudo-type to indicate a normal continuation (for ENDFIN) */ 65 66 /* 67 * Mark-and-sweep flags 68 * 69 * These are separate from heap level flags now but could be merged. 70 * The heap structure only contains a 'base mark-and-sweep flags' 71 * field and the GC caller can impose further flags. 72 */ 73 74 #define DUK_MS_FLAG_EMERGENCY (1 << 0) /* emergency mode: try extra hard */ 75 #define DUK_MS_FLAG_NO_STRINGTABLE_RESIZE (1 << 1) /* don't resize stringtable (but may sweep it); needed during stringtable resize */ 76 #define DUK_MS_FLAG_NO_OBJECT_COMPACTION (1 << 2) /* don't compact objects; needed during object property allocation resize */ 77 #define DUK_MS_FLAG_NO_FINALIZERS (1 << 3) /* don't run finalizers; leave finalizable objects in finalize_list for next round */ 78 #define DUK_MS_FLAG_SKIP_FINALIZERS (1 << 4) /* don't run finalizers; queue finalizable objects back to heap_allocated */ 79 80 /* 81 * Thread switching 82 * 83 * To switch heap->curr_thread, use the macro below so that interrupt counters 84 * get updated correctly. The macro allows a NULL target thread because that 85 * happens e.g. in call handling. 86 */ 87 88 #if defined(DUK_USE_INTERRUPT_COUNTER) 89 #define DUK_HEAP_SWITCH_THREAD(heap,newthr) duk_heap_switch_thread((heap), (newthr)) 90 #else 91 #define DUK_HEAP_SWITCH_THREAD(heap,newthr) do { \ 92 (heap)->curr_thread = (newthr); \ 93 } while (0) 94 #endif 95 96 /* 97 * Other heap related defines 98 */ 99 100 /* Mark-and-sweep interval is relative to combined count of objects and 101 * strings kept in the heap during the latest mark-and-sweep pass. 102 * Fixed point .8 multiplier and .0 adder. Trigger count (interval) is 103 * decreased by each (re)allocation attempt (regardless of size), and each 104 * refzero processed object. 105 * 106 * 'SKIP' indicates how many (re)allocations to wait until a retry if 107 * GC is skipped because there is no thread do it with yet (happens 108 * only during init phases). 109 */ 110 #if defined(DUK_USE_MARK_AND_SWEEP) 111 #if defined(DUK_USE_REFERENCE_COUNTING) 112 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT 12800L /* 50x heap size */ 113 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD 1024L 114 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP 256L 115 #else 116 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT 256L /* 1x heap size */ 117 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD 1024L 118 #define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP 256L 119 #endif 120 #endif 121 122 /* Stringcache is used for speeding up char-offset-to-byte-offset 123 * translations for non-ASCII strings. 124 */ 125 #define DUK_HEAP_STRCACHE_SIZE 4 126 #define DUK_HEAP_STRINGCACHE_NOCACHE_LIMIT 16 /* strings up to the this length are not cached */ 127 128 /* helper to insert a (non-string) heap object into heap allocated list */ 129 #define DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap,hdr) duk_heap_insert_into_heap_allocated((heap),(hdr)) 130 131 /* 132 * Stringtable 133 */ 134 135 /* initial stringtable size, must be prime and higher than DUK_UTIL_MIN_HASH_PRIME */ 136 #define DUK_STRTAB_INITIAL_SIZE 17 137 138 /* indicates a deleted string; any fixed non-NULL, non-hstring pointer works */ 139 #define DUK_STRTAB_DELETED_MARKER(heap) ((duk_hstring *) heap) 140 141 /* resizing parameters */ 142 #define DUK_STRTAB_MIN_FREE_DIVISOR 4 /* load factor max 75% */ 143 #define DUK_STRTAB_MIN_USED_DIVISOR 4 /* load factor min 25% */ 144 #define DUK_STRTAB_GROW_ST_SIZE(n) ((n) + (n)) /* used entries + approx 100% -> reset load to 50% */ 145 146 #define DUK_STRTAB_U32_MAX_STRLEN 10 /* 4'294'967'295 */ 147 #define DUK_STRTAB_HIGHEST_32BIT_PRIME 0xfffffffbUL 148 149 /* probe sequence (open addressing) */ 150 #define DUK_STRTAB_HASH_INITIAL(hash,h_size) ((hash) % (h_size)) 151 #define DUK_STRTAB_HASH_PROBE_STEP(hash) DUK_UTIL_GET_HASH_PROBE_STEP((hash)) 152 153 /* fixed top level hashtable size (separate chaining) */ 154 #define DUK_STRTAB_CHAIN_SIZE DUK_USE_STRTAB_CHAIN_SIZE 155 156 /* 157 * Built-in strings 158 */ 159 160 /* heap string indices are autogenerated in duk_strings.h */ 161 #if defined(DUK_USE_ROM_STRINGS) 162 #define DUK_HEAP_GET_STRING(heap,idx) \ 163 ((duk_hstring *) DUK_LOSE_CONST(duk_rom_strings_stridx[(idx)])) 164 #else /* DUK_USE_ROM_STRINGS */ 165 #if defined(DUK_USE_HEAPPTR16) 166 #define DUK_HEAP_GET_STRING(heap,idx) \ 167 ((duk_hstring *) DUK_USE_HEAPPTR_DEC16((heap)->heap_udata, (heap)->strs16[(idx)])) 168 #else 169 #define DUK_HEAP_GET_STRING(heap,idx) \ 170 ((heap)->strs[(idx)]) 171 #endif 172 #endif /* DUK_USE_ROM_STRINGS */ 173 174 /* 175 * Raw memory calls: relative to heap, but no GC interaction 176 */ 177 178 #define DUK_ALLOC_RAW(heap,size) \ 179 ((heap)->alloc_func((heap)->heap_udata, (size))) 180 181 #define DUK_REALLOC_RAW(heap,ptr,newsize) \ 182 ((heap)->realloc_func((heap)->heap_udata, (void *) (ptr), (newsize))) 183 184 #define DUK_FREE_RAW(heap,ptr) \ 185 ((heap)->free_func((heap)->heap_udata, (void *) (ptr))) 186 187 /* 188 * Memory calls: relative to heap, GC interaction, but no error throwing. 189 * 190 * XXX: Currently a mark-and-sweep triggered by memory allocation will run 191 * using the heap->heap_thread. This thread is also used for running 192 * mark-and-sweep finalization; this is not ideal because it breaks the 193 * isolation between multiple global environments. 194 * 195 * Notes: 196 * 197 * - DUK_FREE() is required to ignore NULL and any other possible return 198 * value of a zero-sized alloc/realloc (same as ANSI C free()). 199 * 200 * - There is no DUK_REALLOC_ZEROED because we don't assume to know the 201 * old size. Caller must zero the reallocated memory. 202 * 203 * - DUK_REALLOC_INDIRECT() must be used when a mark-and-sweep triggered 204 * by an allocation failure might invalidate the original 'ptr', thus 205 * causing a realloc retry to use an invalid pointer. Example: we're 206 * reallocating the value stack and a finalizer resizes the same value 207 * stack during mark-and-sweep. The indirect variant requests for the 208 * current location of the pointer being reallocated using a callback 209 * right before every realloc attempt; this circuitous approach is used 210 * to avoid strict aliasing issues in a more straightforward indirect 211 * pointer (void **) approach. Note: the pointer in the storage 212 * location is read but is NOT updated; the caller must do that. 213 */ 214 215 /* callback for indirect reallocs, request for current pointer */ 216 typedef void *(*duk_mem_getptr)(duk_heap *heap, void *ud); 217 218 #define DUK_ALLOC(heap,size) duk_heap_mem_alloc((heap), (size)) 219 #define DUK_ALLOC_ZEROED(heap,size) duk_heap_mem_alloc_zeroed((heap), (size)) 220 #define DUK_REALLOC(heap,ptr,newsize) duk_heap_mem_realloc((heap), (ptr), (newsize)) 221 #define DUK_REALLOC_INDIRECT(heap,cb,ud,newsize) duk_heap_mem_realloc_indirect((heap), (cb), (ud), (newsize)) 222 #define DUK_FREE(heap,ptr) duk_heap_mem_free((heap), (ptr)) 223 224 /* 225 * Memory constants 226 */ 227 228 #define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT 5 /* Retry allocation after mark-and-sweep for this 229 * many times. A single mark-and-sweep round is 230 * not guaranteed to free all unreferenced memory 231 * because of finalization (in fact, ANY number of 232 * rounds is strictly not enough). 233 */ 234 235 #define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT 3 /* Starting from this round, use emergency mode 236 * for mark-and-sweep. 237 */ 238 239 /* 240 * Debugger support 241 */ 242 243 /* Maximum number of breakpoints. Only breakpoints that are set are 244 * consulted so increasing this has no performance impact. 245 */ 246 #define DUK_HEAP_MAX_BREAKPOINTS 16 247 248 /* Opcode interval for a Date-based status/peek rate limit check. Only 249 * relevant when debugger is attached. Requesting a timestamp may be a 250 * slow operation on some platforms so this shouldn't be too low. On the 251 * other hand a high value makes Duktape react to a pause request slowly. 252 */ 253 #define DUK_HEAP_DBG_RATELIMIT_OPCODES 4000 254 255 /* Milliseconds between status notify and transport peeks. */ 256 #define DUK_HEAP_DBG_RATELIMIT_MILLISECS 200 257 258 /* Step types */ 259 #define DUK_STEP_TYPE_NONE 0 260 #define DUK_STEP_TYPE_INTO 1 261 #define DUK_STEP_TYPE_OVER 2 262 #define DUK_STEP_TYPE_OUT 3 263 264 struct duk_breakpoint { 265 duk_hstring *filename; 266 duk_uint32_t line; 267 }; 268 269 #if defined(DUK_USE_DEBUGGER_SUPPORT) 270 #define DUK_HEAP_IS_DEBUGGER_ATTACHED(heap) ((heap)->dbg_read_cb != NULL) 271 #define DUK_HEAP_CLEAR_STEP_STATE(heap) do { \ 272 (heap)->dbg_step_type = DUK_STEP_TYPE_NONE; \ 273 (heap)->dbg_step_thread = NULL; \ 274 (heap)->dbg_step_csindex = 0; \ 275 (heap)->dbg_step_startline = 0; \ 276 } while (0) 277 #define DUK_HEAP_SET_PAUSED(heap) do { \ 278 (heap)->dbg_paused = 1; \ 279 (heap)->dbg_state_dirty = 1; \ 280 DUK_HEAP_CLEAR_STEP_STATE((heap)); \ 281 } while (0) 282 #define DUK_HEAP_CLEAR_PAUSED(heap) do { \ 283 (heap)->dbg_paused = 0; \ 284 (heap)->dbg_state_dirty = 1; \ 285 DUK_HEAP_CLEAR_STEP_STATE((heap)); \ 286 } while (0) 287 #define DUK_HEAP_IS_PAUSED(heap) ((heap)->dbg_paused) 288 #endif /* DUK_USE_DEBUGGER_SUPPORT */ 289 290 /* 291 * String cache should ideally be at duk_hthread level, but that would 292 * cause string finalization to slow down relative to the number of 293 * threads; string finalization must check the string cache for "weak" 294 * references to the string being finalized to avoid dead pointers. 295 * 296 * Thus, string caches are now at the heap level now. 297 */ 298 299 struct duk_strcache { 300 duk_hstring *h; 301 duk_uint32_t bidx; 302 duk_uint32_t cidx; 303 }; 304 305 /* 306 * Longjmp state, contains the information needed to perform a longjmp. 307 * Longjmp related values are written to value1, value2, and iserror. 308 */ 309 310 struct duk_ljstate { 311 duk_jmpbuf *jmpbuf_ptr; /* current setjmp() catchpoint */ 312 duk_small_uint_t type; /* longjmp type */ 313 duk_bool_t iserror; /* isError flag for yield */ 314 duk_tval value1; /* 1st related value (type specific) */ 315 duk_tval value2; /* 2nd related value (type specific) */ 316 }; 317 318 /* 319 * Stringtable entry for fixed size stringtable 320 */ 321 322 struct duk_strtab_entry { 323 #if defined(DUK_USE_HEAPPTR16) 324 /* A 16-bit listlen makes sense with 16-bit heap pointers: there 325 * won't be space for 64k strings anyway. 326 */ 327 duk_uint16_t listlen; /* if 0, 'str16' used, if > 0, 'strlist16' used */ 328 union { 329 duk_uint16_t strlist16; 330 duk_uint16_t str16; 331 } u; 332 #else 333 duk_size_t listlen; /* if 0, 'str' used, if > 0, 'strlist' used */ 334 union { 335 duk_hstring **strlist; 336 duk_hstring *str; 337 } u; 338 #endif 339 }; 340 341 /* 342 * Main heap structure 343 */ 344 345 struct duk_heap { 346 duk_small_uint_t flags; 347 348 /* Allocator functions. */ 349 duk_alloc_function alloc_func; 350 duk_realloc_function realloc_func; 351 duk_free_function free_func; 352 353 /* Heap udata, used for allocator functions but also for other heap 354 * level callbacks like pointer compression, etc. 355 */ 356 void *heap_udata; 357 358 /* Precomputed pointers when using 16-bit heap pointer packing. */ 359 #if defined(DUK_USE_HEAPPTR16) 360 duk_uint16_t heapptr_null16; 361 duk_uint16_t heapptr_deleted16; 362 #endif 363 364 /* Fatal error handling, called e.g. when a longjmp() is needed but 365 * lj.jmpbuf_ptr is NULL. fatal_func must never return; it's not 366 * declared as "noreturn" because doing that for typedefs is a bit 367 * challenging portability-wise. 368 */ 369 duk_fatal_function fatal_func; 370 371 /* allocated heap objects */ 372 duk_heaphdr *heap_allocated; 373 374 /* work list for objects whose refcounts are zero but which have not been 375 * "finalized"; avoids recursive C calls when refcounts go to zero in a 376 * chain of objects. 377 */ 378 #if defined(DUK_USE_REFERENCE_COUNTING) 379 duk_heaphdr *refzero_list; 380 duk_heaphdr *refzero_list_tail; 381 #endif 382 383 #if defined(DUK_USE_MARK_AND_SWEEP) 384 /* mark-and-sweep control */ 385 #if defined(DUK_USE_VOLUNTARY_GC) 386 duk_int_t mark_and_sweep_trigger_counter; 387 #endif 388 duk_int_t mark_and_sweep_recursion_depth; 389 390 /* mark-and-sweep flags automatically active (used for critical sections) */ 391 duk_small_uint_t mark_and_sweep_base_flags; 392 393 /* work list for objects to be finalized (by mark-and-sweep) */ 394 duk_heaphdr *finalize_list; 395 #endif 396 397 /* longjmp state */ 398 duk_ljstate lj; 399 400 /* marker for detecting internal "double faults", see duk_error_throw.c */ 401 duk_bool_t handling_error; 402 403 /* heap thread, used internally and for finalization */ 404 duk_hthread *heap_thread; 405 406 /* current thread */ 407 duk_hthread *curr_thread; /* currently running thread */ 408 409 /* heap level "stash" object (e.g., various reachability roots) */ 410 duk_hobject *heap_object; 411 412 /* duk_handle_call / duk_handle_safe_call recursion depth limiting */ 413 duk_int_t call_recursion_depth; 414 duk_int_t call_recursion_limit; 415 416 /* mix-in value for computing string hashes; should be reasonably unpredictable */ 417 duk_uint32_t hash_seed; 418 419 /* rnd_state for duk_util_tinyrandom.c */ 420 duk_uint32_t rnd_state; 421 422 /* For manual debugging: instruction count based on executor and 423 * interrupt counter book-keeping. Inspect debug logs to see how 424 * they match up. 425 */ 426 #if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG) 427 duk_int_t inst_count_exec; 428 duk_int_t inst_count_interrupt; 429 #endif 430 431 /* debugger */ 432 433 #if defined(DUK_USE_DEBUGGER_SUPPORT) 434 /* callbacks and udata; dbg_read_cb != NULL is used to indicate attached state */ 435 duk_debug_read_function dbg_read_cb; /* required, NULL implies detached */ 436 duk_debug_write_function dbg_write_cb; /* required */ 437 duk_debug_peek_function dbg_peek_cb; 438 duk_debug_read_flush_function dbg_read_flush_cb; 439 duk_debug_write_flush_function dbg_write_flush_cb; 440 duk_debug_request_function dbg_request_cb; 441 duk_debug_detached_function dbg_detached_cb; 442 void *dbg_udata; 443 444 /* debugger state, only relevant when attached */ 445 duk_bool_t dbg_processing; /* currently processing messages or breakpoints: don't enter message processing recursively (e.g. no breakpoints when processing debugger eval) */ 446 duk_bool_t dbg_paused; /* currently paused: talk with debug client until step/resume */ 447 duk_bool_t dbg_state_dirty; /* resend state next time executor is about to run */ 448 duk_bool_t dbg_force_restart; /* force executor restart to recheck breakpoints; used to handle function returns (see GH-303) */ 449 duk_bool_t dbg_detaching; /* debugger detaching; used to avoid calling detach handler recursively */ 450 duk_small_uint_t dbg_step_type; /* step type: none, step into, step over, step out */ 451 duk_hthread *dbg_step_thread; /* borrowed; NULL if no step state (NULLed in unwind) */ 452 duk_size_t dbg_step_csindex; /* callstack index */ 453 duk_uint32_t dbg_step_startline; /* starting line number */ 454 duk_breakpoint dbg_breakpoints[DUK_HEAP_MAX_BREAKPOINTS]; /* breakpoints: [0,breakpoint_count[ gc reachable */ 455 duk_small_uint_t dbg_breakpoint_count; 456 duk_breakpoint *dbg_breakpoints_active[DUK_HEAP_MAX_BREAKPOINTS + 1]; /* currently active breakpoints: NULL term, borrowed pointers */ 457 /* XXX: make active breakpoints actual copies instead of pointers? */ 458 459 /* These are for rate limiting Status notifications and transport peeking. */ 460 duk_uint32_t dbg_exec_counter; /* cumulative opcode execution count (overflows are OK) */ 461 duk_uint32_t dbg_last_counter; /* value of dbg_exec_counter when we last did a Date-based check */ 462 duk_double_t dbg_last_time; /* time when status/peek was last done (Date-based rate limit) */ 463 464 /* Used to support single-byte stream lookahead. */ 465 duk_bool_t dbg_have_next_byte; 466 duk_uint8_t dbg_next_byte; 467 #endif 468 469 /* string intern table (weak refs) */ 470 #if defined(DUK_USE_STRTAB_PROBE) 471 #if defined(DUK_USE_HEAPPTR16) 472 duk_uint16_t *strtable16; 473 #else 474 duk_hstring **strtable; 475 #endif 476 duk_uint32_t st_size; /* alloc size in elements */ 477 duk_uint32_t st_used; /* used elements (includes DELETED) */ 478 #endif 479 480 /* XXX: static alloc is OK until separate chaining stringtable 481 * resizing is implemented. 482 */ 483 #if defined(DUK_USE_STRTAB_CHAIN) 484 duk_strtab_entry strtable[DUK_STRTAB_CHAIN_SIZE]; 485 #endif 486 487 /* string access cache (codepoint offset -> byte offset) for fast string 488 * character looping; 'weak' reference which needs special handling in GC. 489 */ 490 duk_strcache strcache[DUK_HEAP_STRCACHE_SIZE]; 491 492 /* built-in strings */ 493 #if defined(DUK_USE_ROM_STRINGS) 494 /* No field needed when strings are in ROM. */ 495 #else 496 #if defined(DUK_USE_HEAPPTR16) 497 duk_uint16_t strs16[DUK_HEAP_NUM_STRINGS]; 498 #else 499 duk_hstring *strs[DUK_HEAP_NUM_STRINGS]; 500 #endif 501 #endif 502 }; 503 504 /* 505 * Prototypes 506 */ 507 508 DUK_INTERNAL_DECL 509 duk_heap *duk_heap_alloc(duk_alloc_function alloc_func, 510 duk_realloc_function realloc_func, 511 duk_free_function free_func, 512 void *heap_udata, 513 duk_fatal_function fatal_func); 514 DUK_INTERNAL_DECL void duk_heap_free(duk_heap *heap); 515 DUK_INTERNAL_DECL void duk_free_hobject_inner(duk_heap *heap, duk_hobject *h); 516 DUK_INTERNAL_DECL void duk_free_hbuffer_inner(duk_heap *heap, duk_hbuffer *h); 517 DUK_INTERNAL_DECL void duk_free_hstring_inner(duk_heap *heap, duk_hstring *h); 518 DUK_INTERNAL_DECL void duk_heap_free_heaphdr_raw(duk_heap *heap, duk_heaphdr *hdr); 519 520 DUK_INTERNAL_DECL void duk_heap_insert_into_heap_allocated(duk_heap *heap, duk_heaphdr *hdr); 521 #if defined(DUK_USE_DOUBLE_LINKED_HEAP) && defined(DUK_USE_REFERENCE_COUNTING) 522 DUK_INTERNAL_DECL void duk_heap_remove_any_from_heap_allocated(duk_heap *heap, duk_heaphdr *hdr); 523 #endif 524 #if defined(DUK_USE_INTERRUPT_COUNTER) 525 DUK_INTERNAL_DECL void duk_heap_switch_thread(duk_heap *heap, duk_hthread *new_thr); 526 #endif 527 528 #if 0 /*unused*/ 529 DUK_INTERNAL_DECL duk_hstring *duk_heap_string_lookup(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen); 530 #endif 531 DUK_INTERNAL_DECL duk_hstring *duk_heap_string_intern(duk_heap *heap, const duk_uint8_t *str, duk_uint32_t blen); 532 DUK_INTERNAL_DECL duk_hstring *duk_heap_string_intern_checked(duk_hthread *thr, const duk_uint8_t *str, duk_uint32_t len); 533 #if 0 /*unused*/ 534 DUK_INTERNAL_DECL duk_hstring *duk_heap_string_lookup_u32(duk_heap *heap, duk_uint32_t val); 535 #endif 536 DUK_INTERNAL_DECL duk_hstring *duk_heap_string_intern_u32(duk_heap *heap, duk_uint32_t val); 537 DUK_INTERNAL_DECL duk_hstring *duk_heap_string_intern_u32_checked(duk_hthread *thr, duk_uint32_t val); 538 #if defined(DUK_USE_REFERENCE_COUNTING) 539 DUK_INTERNAL_DECL void duk_heap_string_remove(duk_heap *heap, duk_hstring *h); 540 #endif 541 #if defined(DUK_USE_MARK_AND_SWEEP) && defined(DUK_USE_MS_STRINGTABLE_RESIZE) 542 DUK_INTERNAL_DECL void duk_heap_force_strtab_resize(duk_heap *heap); 543 #endif 544 DUK_INTERNAL void duk_heap_free_strtab(duk_heap *heap); 545 #if defined(DUK_USE_DEBUG) 546 DUK_INTERNAL void duk_heap_dump_strtab(duk_heap *heap); 547 #endif 548 549 550 DUK_INTERNAL_DECL void duk_heap_strcache_string_remove(duk_heap *heap, duk_hstring *h); 551 DUK_INTERNAL_DECL duk_uint_fast32_t duk_heap_strcache_offset_char2byte(duk_hthread *thr, duk_hstring *h, duk_uint_fast32_t char_offset); 552 553 #if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS) 554 DUK_INTERNAL_DECL void *duk_default_alloc_function(void *udata, duk_size_t size); 555 DUK_INTERNAL_DECL void *duk_default_realloc_function(void *udata, void *ptr, duk_size_t newsize); 556 DUK_INTERNAL_DECL void duk_default_free_function(void *udata, void *ptr); 557 #endif 558 559 DUK_INTERNAL_DECL void *duk_heap_mem_alloc(duk_heap *heap, duk_size_t size); 560 DUK_INTERNAL_DECL void *duk_heap_mem_alloc_zeroed(duk_heap *heap, duk_size_t size); 561 DUK_INTERNAL_DECL void *duk_heap_mem_realloc(duk_heap *heap, void *ptr, duk_size_t newsize); 562 DUK_INTERNAL_DECL void *duk_heap_mem_realloc_indirect(duk_heap *heap, duk_mem_getptr cb, void *ud, duk_size_t newsize); 563 DUK_INTERNAL_DECL void duk_heap_mem_free(duk_heap *heap, void *ptr); 564 565 #ifdef DUK_USE_REFERENCE_COUNTING 566 #if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT) 567 DUK_INTERNAL_DECL void duk_tval_incref(duk_tval *tv); 568 #endif 569 #if 0 /* unused */ 570 DUK_INTERNAL_DECL void duk_tval_incref_allownull(duk_tval *tv); 571 #endif 572 DUK_INTERNAL_DECL void duk_tval_decref(duk_hthread *thr, duk_tval *tv); 573 #if 0 /* unused */ 574 DUK_INTERNAL_DECL void duk_tval_decref_allownull(duk_hthread *thr, duk_tval *tv); 575 #endif 576 #if !defined(DUK_USE_FAST_REFCOUNT_DEFAULT) 577 DUK_INTERNAL_DECL void duk_heaphdr_incref(duk_heaphdr *h); 578 #endif 579 #if 0 /* unused */ 580 DUK_INTERNAL_DECL void duk_heaphdr_incref_allownull(duk_heaphdr *h); 581 #endif 582 DUK_INTERNAL_DECL void duk_heaphdr_decref(duk_hthread *thr, duk_heaphdr *h); 583 DUK_INTERNAL_DECL void duk_heaphdr_decref_allownull(duk_hthread *thr, duk_heaphdr *h); 584 DUK_INTERNAL_DECL void duk_heaphdr_refzero(duk_hthread *thr, duk_heaphdr *h); 585 DUK_INTERNAL_DECL void duk_heaphdr_refcount_finalize(duk_hthread *thr, duk_heaphdr *hdr); 586 #else 587 /* no refcounting */ 588 #endif 589 590 #if defined(DUK_USE_MARK_AND_SWEEP) 591 DUK_INTERNAL_DECL duk_bool_t duk_heap_mark_and_sweep(duk_heap *heap, duk_small_uint_t flags); 592 #endif 593 594 DUK_INTERNAL_DECL duk_uint32_t duk_heap_hashstring(duk_heap *heap, const duk_uint8_t *str, duk_size_t len); 595 596 #endif /* DUK_HEAP_H_INCLUDED */ 597