/*
* Heap structure .
*
* Heap contains allocated heap objects , interned strings , and built - in
* strings for one or more threads .
*/
# if !defined(DUK_HEAP_H_INCLUDED)
# define DUK_HEAP_H_INCLUDED
/* alloc function typedefs in duktape.h */
/*
* Heap flags
*/
# define DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED (1 << 0) /* mark-and-sweep marking reached a recursion limit and must use multi-pass marking */
# define DUK_HEAP_FLAG_INTERRUPT_RUNNING (1 << 1) /* executor interrupt running (used to avoid nested interrupts) */
# define DUK_HEAP_FLAG_FINALIZER_NORESCUE (1 << 2) /* heap destruction ongoing, finalizer rescue no longer possible */
# define DUK_HEAP_FLAG_DEBUGGER_PAUSED (1 << 3) /* debugger is paused: talk with debug client until step/resume */
# define DUK__HEAP_HAS_FLAGS(heap,bits) ((heap)->flags & (bits))
# define DUK__HEAP_SET_FLAGS(heap,bits) do { \
( heap ) - > flags | = ( bits ) ; \
} while ( 0 )
# define DUK__HEAP_CLEAR_FLAGS(heap,bits) do { \
( heap ) - > flags & = ~ ( bits ) ; \
} while ( 0 )
# define DUK_HEAP_HAS_MARKANDSWEEP_RECLIMIT_REACHED(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
# define DUK_HEAP_HAS_INTERRUPT_RUNNING(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
# define DUK_HEAP_HAS_FINALIZER_NORESCUE(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
# define DUK_HEAP_HAS_DEBUGGER_PAUSED(heap) DUK__HEAP_HAS_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED)
# define DUK_HEAP_SET_MARKANDSWEEP_RECLIMIT_REACHED(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
# define DUK_HEAP_SET_INTERRUPT_RUNNING(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
# define DUK_HEAP_SET_FINALIZER_NORESCUE(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
# define DUK_HEAP_SET_DEBUGGER_PAUSED(heap) DUK__HEAP_SET_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED)
# define DUK_HEAP_CLEAR_MARKANDSWEEP_RECLIMIT_REACHED(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_MARKANDSWEEP_RECLIMIT_REACHED)
# define DUK_HEAP_CLEAR_INTERRUPT_RUNNING(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_INTERRUPT_RUNNING)
# define DUK_HEAP_CLEAR_FINALIZER_NORESCUE(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_FINALIZER_NORESCUE)
# define DUK_HEAP_CLEAR_DEBUGGER_PAUSED(heap) DUK__HEAP_CLEAR_FLAGS((heap), DUK_HEAP_FLAG_DEBUGGER_PAUSED)
/*
* Longjmp types , also double as identifying continuation type for a rethrow ( in ' finally ' )
*/
# define DUK_LJ_TYPE_UNKNOWN 0 /* unused */
# define DUK_LJ_TYPE_THROW 1 /* value1 -> error object */
# define DUK_LJ_TYPE_YIELD 2 /* value1 -> yield value, iserror -> error / normal */
# define DUK_LJ_TYPE_RESUME 3 /* value1 -> resume value, value2 -> resumee thread, iserror -> error/normal */
# define DUK_LJ_TYPE_BREAK 4 /* value1 -> label number, pseudo-type to indicate a break continuation (for ENDFIN) */
# define DUK_LJ_TYPE_CONTINUE 5 /* value1 -> label number, pseudo-type to indicate a continue continuation (for ENDFIN) */
# define DUK_LJ_TYPE_RETURN 6 /* value1 -> return value, pseudo-type to indicate a return continuation (for ENDFIN) */
# define DUK_LJ_TYPE_NORMAL 7 /* no value, pseudo-type to indicate a normal continuation (for ENDFIN) */
/*
* Mark - and - sweep flags
*
* These are separate from heap level flags now but could be merged .
* The heap structure only contains a ' base mark - and - sweep flags '
* field and the GC caller can impose further flags .
*/
/* Emergency mark-and-sweep: try extra hard, even at the cost of
* performance .
*/
# define DUK_MS_FLAG_EMERGENCY (1 << 0)
/* Voluntary mark-and-sweep: triggered periodically. */
# define DUK_MS_FLAG_VOLUNTARY (1 << 1)
/* Postpone rescue decisions for reachable objects with FINALIZED set.
* Used during finalize_list processing to avoid incorrect rescue
* decisions due to finalize_list being a reachability root .
*/
# define DUK_MS_FLAG_POSTPONE_RESCUE (1 << 2)
/* Don't compact objects; needed during object property table resize
* to prevent a recursive resize . It would suffice to protect only the
* current object being resized , but this is not yet implemented .
*/
# define DUK_MS_FLAG_NO_OBJECT_COMPACTION (1 << 2)
/*
* Thread switching
*
* To switch heap - > curr_thread , use the macro below so that interrupt counters
* get updated correctly . The macro allows a NULL target thread because that
* happens e . g . in call handling .
*/
# if defined(DUK_USE_INTERRUPT_COUNTER)
# define DUK_HEAP_SWITCH_THREAD(heap,newthr) duk_heap_switch_thread((heap), (newthr))
# else
# define DUK_HEAP_SWITCH_THREAD(heap,newthr) do { \
( heap ) - > curr_thread = ( newthr ) ; \
} while ( 0 )
# endif
/*
* Stats
*/
# if defined(DUK_USE_DEBUG)
# define DUK_STATS_INC(heap,fieldname) do { \
( heap ) - > fieldname + = 1 ; \
} while ( 0 )
# else
# define DUK_STATS_INC(heap,fieldname) do {} while (0)
# endif
/*
* Other heap related defines
*/
/* Mark-and-sweep interval is relative to combined count of objects and
* strings kept in the heap during the latest mark - and - sweep pass .
* Fixed point .8 multiplier and .0 adder . Trigger count ( interval ) is
* decreased by each ( re ) allocation attempt ( regardless of size ) , and each
* refzero processed object .
*
* ' SKIP ' indicates how many ( re ) allocations to wait until a retry if
* GC is skipped because there is no thread do it with yet ( happens
* only during init phases ) .
*/
# if defined(DUK_USE_REFERENCE_COUNTING)
# define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT 12800L /* 50x heap size */
# define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD 1024L
# define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP 256L
# else
# define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_MULT 256L /* 1x heap size */
# define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_ADD 1024L
# define DUK_HEAP_MARK_AND_SWEEP_TRIGGER_SKIP 256L
# endif
/* GC torture. */
# if defined(DUK_USE_GC_TORTURE)
# define DUK_GC_TORTURE(heap) do { duk_heap_mark_and_sweep((heap), 0); } while (0)
# else
# define DUK_GC_TORTURE(heap) do { } while (0)
# endif
/* Stringcache is used for speeding up char-offset-to-byte-offset
* translations for non - ASCII strings .
*/
# define DUK_HEAP_STRCACHE_SIZE 4
# define DUK_HEAP_STRINGCACHE_NOCACHE_LIMIT 16 /* strings up to the this length are not cached */
/* Some list management macros. */
# define DUK_HEAP_INSERT_INTO_HEAP_ALLOCATED(heap,hdr) duk_heap_insert_into_heap_allocated((heap), (hdr))
# if defined(DUK_USE_REFERENCE_COUNTING)
# define DUK_HEAP_REMOVE_FROM_HEAP_ALLOCATED(heap,hdr) duk_heap_remove_from_heap_allocated((heap), (hdr))
# endif
# if defined(DUK_USE_FINALIZER_SUPPORT)
# define DUK_HEAP_INSERT_INTO_FINALIZE_LIST(heap,hdr) duk_heap_insert_into_finalize_list((heap), (hdr))
# define DUK_HEAP_REMOVE_FROM_FINALIZE_LIST(heap,hdr) duk_heap_remove_from_finalize_list((heap), (hdr))
# endif
/*
* Built - in strings
*/
/* heap string indices are autogenerated in duk_strings.h */
# if defined(DUK_USE_ROM_STRINGS)
# define DUK_HEAP_GET_STRING(heap,idx) \
( ( duk_hstring * ) DUK_LOSE_CONST ( duk_rom_strings_stridx [ ( idx ) ] ) )
# else /* DUK_USE_ROM_STRINGS */
16-bit fields and heap pointer compression work
Memory optimization work for very low memory devices (96 to 256kB system RAM).
Overall changes are:
- 16-bit fields for various internal structures to reduce their size
- Heap pointer compression to reduce pointer size to 16 bits
When DUK_OPT_LIGHTFUNC_BUILTINS and the new low memory options are enabled,
Duktape initial heap memory usage is about 23kB (compared to baseline of
about 45kB) on x86.
Unless low memory feature options are enabled, there should be no visible
changes to Duktape behavior.
More detailed changes:
- 16-bit changes for duk_heaphdr: pointer compression, refcount
- 16-bit changes for duk_hstring: hash, blen, and clen can all be 16 bits,
use 0xFFFF as string byte length limit (call sites ensure this limit is
never exceeded)
- 16-bit changes for duk_hbuffer, use 0xFFFF as buffer length limit
- 16-bit fields for hobject size (entry part, array part), drop hash part
since it's not usually needed for extremely low memory environments
- 16-bit changes for duk_hcompiledfunction
- Heap pointer packing for stringtable
- Heap pointer packing for 'strs' built-in strings list (saves around 600
to 700 bytes but may not be a good tradeoff because call site size will
increase)
Other changes:
- Heaphdr NULL init fix. The original macros were broken: the double/single
linked macro variants were the wrong way around. Now sets through macro
to work properly with compressed pointers.
- Rename duk_hbuffer CURR_DATA_PTR -> DATA_PTR to reduce macro length
(previous name was tediously long)
- Rename buffer "usable_size" to "alloc_size" throughout as they have been
the same for a while now (they used to differ when buffer had an extra NUL).
- Add memory optimization markers to Duktape.env (pointer compression and
individual 16-bit field options)
- Rename a few internal fields for clarity: duk_hobject 'p' to 'props',
heap->st to heap->strtable
- Add a safety check for buffer alloc size (should not be triggered but
prevents wrapping if call sites don't properly check for sizes)
- Other minor cleanups
10 years ago
# if defined(DUK_USE_HEAPPTR16)
# define DUK_HEAP_GET_STRING(heap,idx) \
( ( duk_hstring * ) DUK_USE_HEAPPTR_DEC16 ( ( heap ) - > heap_udata , ( heap ) - > strs16 [ ( idx ) ] ) )
16-bit fields and heap pointer compression work
Memory optimization work for very low memory devices (96 to 256kB system RAM).
Overall changes are:
- 16-bit fields for various internal structures to reduce their size
- Heap pointer compression to reduce pointer size to 16 bits
When DUK_OPT_LIGHTFUNC_BUILTINS and the new low memory options are enabled,
Duktape initial heap memory usage is about 23kB (compared to baseline of
about 45kB) on x86.
Unless low memory feature options are enabled, there should be no visible
changes to Duktape behavior.
More detailed changes:
- 16-bit changes for duk_heaphdr: pointer compression, refcount
- 16-bit changes for duk_hstring: hash, blen, and clen can all be 16 bits,
use 0xFFFF as string byte length limit (call sites ensure this limit is
never exceeded)
- 16-bit changes for duk_hbuffer, use 0xFFFF as buffer length limit
- 16-bit fields for hobject size (entry part, array part), drop hash part
since it's not usually needed for extremely low memory environments
- 16-bit changes for duk_hcompiledfunction
- Heap pointer packing for stringtable
- Heap pointer packing for 'strs' built-in strings list (saves around 600
to 700 bytes but may not be a good tradeoff because call site size will
increase)
Other changes:
- Heaphdr NULL init fix. The original macros were broken: the double/single
linked macro variants were the wrong way around. Now sets through macro
to work properly with compressed pointers.
- Rename duk_hbuffer CURR_DATA_PTR -> DATA_PTR to reduce macro length
(previous name was tediously long)
- Rename buffer "usable_size" to "alloc_size" throughout as they have been
the same for a while now (they used to differ when buffer had an extra NUL).
- Add memory optimization markers to Duktape.env (pointer compression and
individual 16-bit field options)
- Rename a few internal fields for clarity: duk_hobject 'p' to 'props',
heap->st to heap->strtable
- Add a safety check for buffer alloc size (should not be triggered but
prevents wrapping if call sites don't properly check for sizes)
- Other minor cleanups
10 years ago
# else
# define DUK_HEAP_GET_STRING(heap,idx) \
( ( heap ) - > strs [ ( idx ) ] )
# endif
# endif /* DUK_USE_ROM_STRINGS */
/*
* Raw memory calls : relative to heap , but no GC interaction
*/
# define DUK_ALLOC_RAW(heap,size) \
( ( heap ) - > alloc_func ( ( heap ) - > heap_udata , ( size ) ) )
# define DUK_REALLOC_RAW(heap,ptr,newsize) \
( ( heap ) - > realloc_func ( ( heap ) - > heap_udata , ( void * ) ( ptr ) , ( newsize ) ) )
# define DUK_FREE_RAW(heap,ptr) \
( ( heap ) - > free_func ( ( heap ) - > heap_udata , ( void * ) ( ptr ) ) )
/*
* Memory calls : relative to heap , GC interaction , but no error throwing .
*
* XXX : Currently a mark - and - sweep triggered by memory allocation will run
* using the heap - > heap_thread . This thread is also used for running
* mark - and - sweep finalization ; this is not ideal because it breaks the
* isolation between multiple global environments .
*
* Notes :
*
* - DUK_FREE ( ) is required to ignore NULL and any other possible return
* value of a zero - sized alloc / realloc ( same as ANSI C free ( ) ) .
*
* - There is no DUK_REALLOC_ZEROED because we don ' t assume to know the
* old size . Caller must zero the reallocated memory .
*
* - DUK_REALLOC_INDIRECT ( ) must be used when a mark - and - sweep triggered
* by an allocation failure might invalidate the original ' ptr ' , thus
* causing a realloc retry to use an invalid pointer . Example : we ' re
* reallocating the value stack and a finalizer resizes the same value
* stack during mark - and - sweep . The indirect variant requests for the
* current location of the pointer being reallocated using a callback
* right before every realloc attempt ; this circuitous approach is used
* to avoid strict aliasing issues in a more straightforward indirect
* pointer ( void * * ) approach . Note : the pointer in the storage
* location is read but is NOT updated ; the caller must do that .
*/
/* callback for indirect reallocs, request for current pointer */
typedef void * ( * duk_mem_getptr ) ( duk_heap * heap , void * ud ) ;
# define DUK_ALLOC(heap,size) duk_heap_mem_alloc((heap), (size))
# define DUK_ALLOC_ZEROED(heap,size) duk_heap_mem_alloc_zeroed((heap), (size))
# define DUK_REALLOC(heap,ptr,newsize) duk_heap_mem_realloc((heap), (ptr), (newsize))
# define DUK_REALLOC_INDIRECT(heap,cb,ud,newsize) duk_heap_mem_realloc_indirect((heap), (cb), (ud), (newsize))
# define DUK_FREE(heap,ptr) duk_heap_mem_free((heap), (ptr))
/*
* Checked allocation , relative to a thread
*
* DUK_FREE_CHECKED ( ) doesn ' t actually throw , but accepts a ' thr ' argument
* for convenience .
*/
# define DUK_ALLOC_CHECKED(thr,size) duk_heap_mem_alloc_checked((thr), (size))
# define DUK_ALLOC_CHECKED_ZEROED(thr,size) duk_heap_mem_alloc_checked_zeroed((thr), (size))
# define DUK_FREE_CHECKED(thr,ptr) duk_heap_mem_free((thr)->heap, (ptr))
/*
* Memory constants
*/
# define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_LIMIT 10 / * Retry allocation after mark-and-sweep for this
* many times . A single mark - and - sweep round is
* not guaranteed to free all unreferenced memory
* because of finalization ( in fact , ANY number of
* rounds is strictly not enough ) .
*/
# define DUK_HEAP_ALLOC_FAIL_MARKANDSWEEP_EMERGENCY_LIMIT 3 / * Starting from this round, use emergency mode
* for mark - and - sweep .
*/
/*
* Debugger support
*/
/* Maximum number of breakpoints. Only breakpoints that are set are
* consulted so increasing this has no performance impact .
*/
# define DUK_HEAP_MAX_BREAKPOINTS 16
/* Opcode interval for a Date-based status/peek rate limit check. Only
* relevant when debugger is attached . Requesting a timestamp may be a
* slow operation on some platforms so this shouldn ' t be too low . On the
* other hand a high value makes Duktape react to a pause request slowly .
*/
# define DUK_HEAP_DBG_RATELIMIT_OPCODES 4000
/* Milliseconds between status notify and transport peeks. */
# define DUK_HEAP_DBG_RATELIMIT_MILLISECS 200
/* Step types */
# define DUK_STEP_TYPE_NONE 0
# define DUK_STEP_TYPE_INTO 1
# define DUK_STEP_TYPE_OVER 2
# define DUK_STEP_TYPE_OUT 3
struct duk_breakpoint {
duk_hstring * filename ;
duk_uint32_t line ;
} ;
/*
* String cache should ideally be at duk_hthread level , but that would
* cause string finalization to slow down relative to the number of
* threads ; string finalization must check the string cache for " weak "
* references to the string being finalized to avoid dead pointers .
*
* Thus , string caches are now at the heap level now .
*/
struct duk_strcache {
duk_hstring * h ;
duk_uint32_t bidx ;
duk_uint32_t cidx ;
} ;
/*
* Longjmp state , contains the information needed to perform a longjmp .
* Longjmp related values are written to value1 , value2 , and iserror .
*/
struct duk_ljstate {
duk_jmpbuf * jmpbuf_ptr ; /* current setjmp() catchpoint */
duk_small_uint_t type ; /* longjmp type */
duk_bool_t iserror ; /* isError flag for yield */
duk_tval value1 ; /* 1st related value (type specific) */
duk_tval value2 ; /* 2nd related value (type specific) */
} ;
# define DUK_ASSERT_LJSTATE_UNSET(heap) do { \
DUK_ASSERT ( heap ! = NULL ) ; \
DUK_ASSERT ( heap - > lj . type = = DUK_LJ_TYPE_UNKNOWN ) ; \
DUK_ASSERT ( heap - > lj . iserror = = 0 ) ; \
DUK_ASSERT ( DUK_TVAL_IS_UNDEFINED ( & heap - > lj . value1 ) ) ; \
DUK_ASSERT ( DUK_TVAL_IS_UNDEFINED ( & heap - > lj . value2 ) ) ; \
} while ( 0 )
# define DUK_ASSERT_LJSTATE_SET(heap) do { \
DUK_ASSERT ( heap ! = NULL ) ; \
DUK_ASSERT ( heap - > lj . type ! = DUK_LJ_TYPE_UNKNOWN ) ; \
} while ( 0 )
/*
* Main heap structure
*/
struct duk_heap {
duk_small_uint_t flags ;
/* Allocator functions. */
duk_alloc_function alloc_func ;
duk_realloc_function realloc_func ;
duk_free_function free_func ;
/* Heap udata, used for allocator functions but also for other heap
* level callbacks like fatal function , pointer compression , etc .
*/
void * heap_udata ;
/* Fatal error handling, called e.g. when a longjmp() is needed but
* lj . jmpbuf_ptr is NULL . fatal_func must never return ; it ' s not
* declared as " noreturn " because doing that for typedefs is a bit
* challenging portability - wise .
*/
duk_fatal_function fatal_func ;
/* Main list of allocated heap objects. Objects are either here,
* in finalize_list waiting for processing , or in refzero_list
* temporarily while a DECREF refzero cascade finishes .
*/
duk_heaphdr * heap_allocated ;
/* Temporary work list for freeing a cascade of objects when a DECREF
* ( or DECREF_NORZ ) encounters a zero refcount . Using a work list
* allows fixed C stack size when refcounts go to zero for a chain of
* objects . Outside of DECREF this is always a NULL because DECREF is
* processed without side effects ( only memory free calls ) .
*/
# if defined(DUK_USE_REFERENCE_COUNTING)
duk_heaphdr * refzero_list ;
# endif
# if defined(DUK_USE_FINALIZER_SUPPORT)
/* Work list for objects to be finalized. */
duk_heaphdr * finalize_list ;
# if defined(DUK_USE_ASSERTIONS)
/* Object whose finalizer is executing right now (no nesting). */
duk_heaphdr * currently_finalizing ;
# endif
# endif
/* Freelist for duk_activations and duk_catchers. */
# if defined(DUK_USE_CACHE_ACTIVATION)
duk_activation * activation_free ;
# endif
# if defined(DUK_USE_CACHE_CATCHER)
duk_catcher * catcher_free ;
# endif
/* Voluntary mark-and-sweep trigger counter. Intentionally signed
* because we continue decreasing the value when voluntary GC cannot
* run .
*/
# if defined(DUK_USE_VOLUNTARY_GC)
duk_int_t ms_trigger_counter ;
# endif
/* Mark-and-sweep recursion control: too deep recursion causes
* multi - pass processing to avoid growing C stack without bound .
*/
duk_uint_t ms_recursion_depth ;
/* Mark-and-sweep flags automatically active (used for critical sections). */
duk_small_uint_t ms_base_flags ;
/* Mark-and-sweep running flag. Prevents re-entry, and also causes
* refzero events to be ignored ( = objects won ' t be queued to refzero_list ) .
*/
duk_uint_t ms_running ;
/* Mark-and-sweep prevent count, stacking. Used to avoid M&S side
* effects ( besides finalizers which are controlled separately ) such
* as compacting the string table or object property tables . This
* is also bumped when ms_running is set to prevent recursive re - entry .
* Can also be bumped when mark - and - sweep is not running .
*/
duk_uint_t ms_prevent_count ;
/* Finalizer processing prevent count, stacking. Bumped when finalizers
* are processed to prevent recursive finalizer processing ( first call site
* processing finalizers handles all finalizers until the list is empty ) .
* Can also be bumped explicitly to prevent finalizer execution .
*/
duk_uint_t pf_prevent_count ;
/* When processing finalize_list, don't actually run finalizers but
* queue finalizable objects back to heap_allocated as is . This is
* used during heap destruction to deal with finalizers that keep
* on creating more finalizable garbage .
*/
duk_uint_t pf_skip_finalizers ;
# if defined(DUK_USE_ASSERTIONS)
/* Set when we're in a critical path where an error throw would cause
* e . g . sandboxing / protected call violations or state corruption . This
* is just used for asserts .
*/
duk_bool_t error_not_allowed ;
# endif
# if defined(DUK_USE_ASSERTIONS)
/* Set when heap is still being initialized, helps with writing
* some assertions .
*/
duk_bool_t heap_initializing ;
# endif
/* Marker for detecting internal "double faults", errors thrown when
* we ' re trying to create an error object , see duk_error_throw . c .
*/
duk_bool_t creating_error ;
/* Marker for indicating we're calling a user error augmentation
* ( errCreate / errThrow ) function . Errors created / thrown during
* such a call are not augmented .
*/
# if defined(DUK_USE_AUGMENT_ERROR_THROW) || defined(DUK_USE_AUGMENT_ERROR_CREATE)
duk_bool_t augmenting_error ;
# endif
/* Longjmp state. */
duk_ljstate lj ;
/* Heap thread, used internally and for finalization. */
duk_hthread * heap_thread ;
/* Current running thread. */
duk_hthread * curr_thread ;
/* Heap level "stash" object (e.g., various reachability roots). */
duk_hobject * heap_object ;
/* duk_handle_call / duk_handle_safe_call recursion depth limiting */
duk_int_t call_recursion_depth ;
duk_int_t call_recursion_limit ;
/* Mix-in value for computing string hashes; should be reasonably unpredictable. */
duk_uint32_t hash_seed ;
/* Random number state for duk_util_tinyrandom.c. */
# if !defined(DUK_USE_GET_RANDOM_DOUBLE)
# if defined(DUK_USE_PREFER_SIZE) || !defined(DUK_USE_64BIT_OPS)
duk_uint32_t rnd_state ; /* State for Shamir's three-op algorithm */
# else
duk_uint64_t rnd_state [ 2 ] ; /* State for xoroshiro128+ */
# endif
# endif
/* Counter for unique local symbol creation. */
/* XXX: When 64-bit types are available, it would be more efficient to
* use a duk_uint64_t at least for incrementing but maybe also for
* string formatting in the Symbol constructor .
*/
duk_uint32_t sym_counter [ 2 ] ;
/* For manual debugging: instruction count based on executor and
* interrupt counter book - keeping . Inspect debug logs to see how
* they match up .
*/
# if defined(DUK_USE_INTERRUPT_COUNTER) && defined(DUK_USE_DEBUG)
duk_int_t inst_count_exec ;
duk_int_t inst_count_interrupt ;
# endif
/* Debugger state. */
# if defined(DUK_USE_DEBUGGER_SUPPORT)
/* Callbacks and udata; dbg_read_cb != NULL is used to indicate attached state. */
duk_debug_read_function dbg_read_cb ; /* required, NULL implies detached */
duk_debug_write_function dbg_write_cb ; /* required */
duk_debug_peek_function dbg_peek_cb ;
duk_debug_read_flush_function dbg_read_flush_cb ;
duk_debug_write_flush_function dbg_write_flush_cb ;
duk_debug_request_function dbg_request_cb ;
duk_debug_detached_function dbg_detached_cb ;
void * dbg_udata ;
/* The following are only relevant when debugger is attached. */
duk_bool_t dbg_processing ; /* currently processing messages or breakpoints: don't enter message processing recursively (e.g. no breakpoints when processing debugger eval) */
duk_bool_t dbg_state_dirty ; /* resend state next time executor is about to run */
duk_bool_t dbg_force_restart ; /* force executor restart to recheck breakpoints; used to handle function returns (see GH-303) */
duk_bool_t dbg_detaching ; /* debugger detaching; used to avoid calling detach handler recursively */
duk_small_uint_t dbg_step_type ; /* step type: none, step into, step over, step out */
duk_activation * dbg_step_act ; /* activation related to step into/over/out */
duk_uint32_t dbg_step_startline ; /* starting line number */
duk_breakpoint dbg_breakpoints [ DUK_HEAP_MAX_BREAKPOINTS ] ; /* breakpoints: [0,breakpoint_count[ gc reachable */
duk_small_uint_t dbg_breakpoint_count ;
duk_breakpoint * dbg_breakpoints_active [ DUK_HEAP_MAX_BREAKPOINTS + 1 ] ; /* currently active breakpoints: NULL term, borrowed pointers */
/* XXX: make active breakpoints actual copies instead of pointers? */
/* These are for rate limiting Status notifications and transport peeking. */
duk_uint32_t dbg_exec_counter ; /* cumulative opcode execution count (overflows are OK) */
duk_uint32_t dbg_last_counter ; /* value of dbg_exec_counter when we last did a Date-based check */
duk_double_t dbg_last_time ; /* time when status/peek was last done (Date-based rate limit) */
/* Used to support single-byte stream lookahead. */
duk_bool_t dbg_have_next_byte ;
duk_uint8_t dbg_next_byte ;
# endif
/* String intern table (weak refs). */
# if defined(DUK_USE_STRTAB_PTRCOMP)
16-bit fields and heap pointer compression work
Memory optimization work for very low memory devices (96 to 256kB system RAM).
Overall changes are:
- 16-bit fields for various internal structures to reduce their size
- Heap pointer compression to reduce pointer size to 16 bits
When DUK_OPT_LIGHTFUNC_BUILTINS and the new low memory options are enabled,
Duktape initial heap memory usage is about 23kB (compared to baseline of
about 45kB) on x86.
Unless low memory feature options are enabled, there should be no visible
changes to Duktape behavior.
More detailed changes:
- 16-bit changes for duk_heaphdr: pointer compression, refcount
- 16-bit changes for duk_hstring: hash, blen, and clen can all be 16 bits,
use 0xFFFF as string byte length limit (call sites ensure this limit is
never exceeded)
- 16-bit changes for duk_hbuffer, use 0xFFFF as buffer length limit
- 16-bit fields for hobject size (entry part, array part), drop hash part
since it's not usually needed for extremely low memory environments
- 16-bit changes for duk_hcompiledfunction
- Heap pointer packing for stringtable
- Heap pointer packing for 'strs' built-in strings list (saves around 600
to 700 bytes but may not be a good tradeoff because call site size will
increase)
Other changes:
- Heaphdr NULL init fix. The original macros were broken: the double/single
linked macro variants were the wrong way around. Now sets through macro
to work properly with compressed pointers.
- Rename duk_hbuffer CURR_DATA_PTR -> DATA_PTR to reduce macro length
(previous name was tediously long)
- Rename buffer "usable_size" to "alloc_size" throughout as they have been
the same for a while now (they used to differ when buffer had an extra NUL).
- Add memory optimization markers to Duktape.env (pointer compression and
individual 16-bit field options)
- Rename a few internal fields for clarity: duk_hobject 'p' to 'props',
heap->st to heap->strtable
- Add a safety check for buffer alloc size (should not be triggered but
prevents wrapping if call sites don't properly check for sizes)
- Other minor cleanups
10 years ago
duk_uint16_t * strtable16 ;
# else
duk_hstring * * strtable ;
# endif
duk_uint32_t st_mask ; /* mask for lookup, st_size - 1 */
duk_uint32_t st_size ; /* stringtable size */
# if (DUK_USE_STRTAB_MINSIZE != DUK_USE_STRTAB_MAXSIZE)
duk_uint32_t st_count ; /* string count for resize load factor checks */
# endif
duk_bool_t st_resizing ; /* string table is being resized; avoid recursive resize */
/* String access cache (codepoint offset -> byte offset) for fast string
* character looping ; ' weak ' reference which needs special handling in GC .
*/
duk_strcache strcache [ DUK_HEAP_STRCACHE_SIZE ] ;
/* Built-in strings. */
# if defined(DUK_USE_ROM_STRINGS)
/* No field needed when strings are in ROM. */
# else
16-bit fields and heap pointer compression work
Memory optimization work for very low memory devices (96 to 256kB system RAM).
Overall changes are:
- 16-bit fields for various internal structures to reduce their size
- Heap pointer compression to reduce pointer size to 16 bits
When DUK_OPT_LIGHTFUNC_BUILTINS and the new low memory options are enabled,
Duktape initial heap memory usage is about 23kB (compared to baseline of
about 45kB) on x86.
Unless low memory feature options are enabled, there should be no visible
changes to Duktape behavior.
More detailed changes:
- 16-bit changes for duk_heaphdr: pointer compression, refcount
- 16-bit changes for duk_hstring: hash, blen, and clen can all be 16 bits,
use 0xFFFF as string byte length limit (call sites ensure this limit is
never exceeded)
- 16-bit changes for duk_hbuffer, use 0xFFFF as buffer length limit
- 16-bit fields for hobject size (entry part, array part), drop hash part
since it's not usually needed for extremely low memory environments
- 16-bit changes for duk_hcompiledfunction
- Heap pointer packing for stringtable
- Heap pointer packing for 'strs' built-in strings list (saves around 600
to 700 bytes but may not be a good tradeoff because call site size will
increase)
Other changes:
- Heaphdr NULL init fix. The original macros were broken: the double/single
linked macro variants were the wrong way around. Now sets through macro
to work properly with compressed pointers.
- Rename duk_hbuffer CURR_DATA_PTR -> DATA_PTR to reduce macro length
(previous name was tediously long)
- Rename buffer "usable_size" to "alloc_size" throughout as they have been
the same for a while now (they used to differ when buffer had an extra NUL).
- Add memory optimization markers to Duktape.env (pointer compression and
individual 16-bit field options)
- Rename a few internal fields for clarity: duk_hobject 'p' to 'props',
heap->st to heap->strtable
- Add a safety check for buffer alloc size (should not be triggered but
prevents wrapping if call sites don't properly check for sizes)
- Other minor cleanups
10 years ago
# if defined(DUK_USE_HEAPPTR16)
duk_uint16_t strs16 [ DUK_HEAP_NUM_STRINGS ] ;
# else
duk_hstring * strs [ DUK_HEAP_NUM_STRINGS ] ;
16-bit fields and heap pointer compression work
Memory optimization work for very low memory devices (96 to 256kB system RAM).
Overall changes are:
- 16-bit fields for various internal structures to reduce their size
- Heap pointer compression to reduce pointer size to 16 bits
When DUK_OPT_LIGHTFUNC_BUILTINS and the new low memory options are enabled,
Duktape initial heap memory usage is about 23kB (compared to baseline of
about 45kB) on x86.
Unless low memory feature options are enabled, there should be no visible
changes to Duktape behavior.
More detailed changes:
- 16-bit changes for duk_heaphdr: pointer compression, refcount
- 16-bit changes for duk_hstring: hash, blen, and clen can all be 16 bits,
use 0xFFFF as string byte length limit (call sites ensure this limit is
never exceeded)
- 16-bit changes for duk_hbuffer, use 0xFFFF as buffer length limit
- 16-bit fields for hobject size (entry part, array part), drop hash part
since it's not usually needed for extremely low memory environments
- 16-bit changes for duk_hcompiledfunction
- Heap pointer packing for stringtable
- Heap pointer packing for 'strs' built-in strings list (saves around 600
to 700 bytes but may not be a good tradeoff because call site size will
increase)
Other changes:
- Heaphdr NULL init fix. The original macros were broken: the double/single
linked macro variants were the wrong way around. Now sets through macro
to work properly with compressed pointers.
- Rename duk_hbuffer CURR_DATA_PTR -> DATA_PTR to reduce macro length
(previous name was tediously long)
- Rename buffer "usable_size" to "alloc_size" throughout as they have been
the same for a while now (they used to differ when buffer had an extra NUL).
- Add memory optimization markers to Duktape.env (pointer compression and
individual 16-bit field options)
- Rename a few internal fields for clarity: duk_hobject 'p' to 'props',
heap->st to heap->strtable
- Add a safety check for buffer alloc size (should not be triggered but
prevents wrapping if call sites don't properly check for sizes)
- Other minor cleanups
10 years ago
# endif
# endif
/* Stats. */
# if defined(DUK_USE_DEBUG)
duk_int_t stats_exec_opcodes ;
duk_int_t stats_exec_throw ;
duk_int_t stats_call_all ;
duk_int_t stats_call_tailcall ;
duk_int_t stats_call_ecmatoecma ;
duk_int_t stats_safecall_all ;
duk_int_t stats_safecall_nothrow ;
duk_int_t stats_safecall_throw ;
duk_int_t stats_ms_try_count ;
duk_int_t stats_ms_skip_count ;
duk_int_t stats_ms_emergency_count ;
duk_int_t stats_intern_hit ;
duk_int_t stats_intern_miss ;
duk_int_t stats_getprop_all ;
duk_int_t stats_getprop_arrayidx ;
duk_int_t stats_getprop_bufobjidx ;
duk_int_t stats_getprop_bufferidx ;
duk_int_t stats_getprop_bufferlen ;
duk_int_t stats_getprop_stringidx ;
duk_int_t stats_getprop_stringlen ;
duk_int_t stats_getprop_proxy ;
duk_int_t stats_getprop_arguments ;
duk_int_t stats_putprop_all ;
duk_int_t stats_putprop_arrayidx ;
duk_int_t stats_putprop_bufobjidx ;
duk_int_t stats_putprop_bufferidx ;
duk_int_t stats_putprop_proxy ;
duk_int_t stats_getvar_all ;
duk_int_t stats_putvar_all ;
# endif
} ;
/*
* Prototypes
*/
DUK_INTERNAL_DECL
duk_heap * duk_heap_alloc ( duk_alloc_function alloc_func ,
duk_realloc_function realloc_func ,
duk_free_function free_func ,
void * heap_udata ,
duk_fatal_function fatal_func ) ;
DUK_INTERNAL_DECL void duk_heap_free ( duk_heap * heap ) ;
DUK_INTERNAL_DECL void duk_free_hobject ( duk_heap * heap , duk_hobject * h ) ;
DUK_INTERNAL_DECL void duk_free_hbuffer ( duk_heap * heap , duk_hbuffer * h ) ;
DUK_INTERNAL_DECL void duk_free_hstring ( duk_heap * heap , duk_hstring * h ) ;
DUK_INTERNAL_DECL void duk_heap_free_heaphdr_raw ( duk_heap * heap , duk_heaphdr * hdr ) ;
DUK_INTERNAL_DECL void duk_heap_insert_into_heap_allocated ( duk_heap * heap , duk_heaphdr * hdr ) ;
# if defined(DUK_USE_REFERENCE_COUNTING)
DUK_INTERNAL_DECL void duk_heap_remove_from_heap_allocated ( duk_heap * heap , duk_heaphdr * hdr ) ;
# endif
# if defined(DUK_USE_FINALIZER_SUPPORT)
DUK_INTERNAL_DECL void duk_heap_insert_into_finalize_list ( duk_heap * heap , duk_heaphdr * hdr ) ;
DUK_INTERNAL_DECL void duk_heap_remove_from_finalize_list ( duk_heap * heap , duk_heaphdr * hdr ) ;
# endif
# if defined(DUK_USE_ASSERTIONS)
DUK_INTERNAL_DECL duk_bool_t duk_heap_in_heap_allocated ( duk_heap * heap , duk_heaphdr * ptr ) ;
# endif
# if defined(DUK_USE_INTERRUPT_COUNTER)
DUK_INTERNAL_DECL void duk_heap_switch_thread ( duk_heap * heap , duk_hthread * new_thr ) ;
# endif
DUK_INTERNAL_DECL duk_hstring * duk_heap_strtable_intern ( duk_heap * heap , const duk_uint8_t * str , duk_uint32_t blen ) ;
DUK_INTERNAL_DECL duk_hstring * duk_heap_strtable_intern_checked ( duk_hthread * thr , const duk_uint8_t * str , duk_uint32_t len ) ;
DUK_INTERNAL_DECL duk_hstring * duk_heap_strtable_intern_u32 ( duk_heap * heap , duk_uint32_t val ) ;
DUK_INTERNAL_DECL duk_hstring * duk_heap_strtable_intern_u32_checked ( duk_hthread * thr , duk_uint32_t val ) ;
# if defined(DUK_USE_REFERENCE_COUNTING)
DUK_INTERNAL_DECL void duk_heap_strtable_unlink ( duk_heap * heap , duk_hstring * h ) ;
# endif
DUK_INTERNAL_DECL void duk_heap_strtable_unlink_prev ( duk_heap * heap , duk_hstring * h , duk_hstring * prev ) ;
DUK_INTERNAL_DECL void duk_heap_strtable_force_resize ( duk_heap * heap ) ;
DUK_INTERNAL void duk_heap_strtable_free ( duk_heap * heap ) ;
# if defined(DUK_USE_DEBUG)
DUK_INTERNAL void duk_heap_strtable_dump ( duk_heap * heap ) ;
# endif
DUK_INTERNAL_DECL void duk_heap_strcache_string_remove ( duk_heap * heap , duk_hstring * h ) ;
DUK_INTERNAL_DECL duk_uint_fast32_t duk_heap_strcache_offset_char2byte ( duk_hthread * thr , duk_hstring * h , duk_uint_fast32_t char_offset ) ;
# if defined(DUK_USE_PROVIDE_DEFAULT_ALLOC_FUNCTIONS)
DUK_INTERNAL_DECL void * duk_default_alloc_function ( void * udata , duk_size_t size ) ;
DUK_INTERNAL_DECL void * duk_default_realloc_function ( void * udata , void * ptr , duk_size_t newsize ) ;
DUK_INTERNAL_DECL void duk_default_free_function ( void * udata , void * ptr ) ;
# endif
DUK_INTERNAL_DECL void * duk_heap_mem_alloc ( duk_heap * heap , duk_size_t size ) ;
DUK_INTERNAL_DECL void * duk_heap_mem_alloc_zeroed ( duk_heap * heap , duk_size_t size ) ;
DUK_INTERNAL_DECL void * duk_heap_mem_alloc_checked ( duk_hthread * thr , duk_size_t size ) ;
DUK_INTERNAL_DECL void * duk_heap_mem_alloc_checked_zeroed ( duk_hthread * thr , duk_size_t size ) ;
DUK_INTERNAL_DECL void * duk_heap_mem_realloc ( duk_heap * heap , void * ptr , duk_size_t newsize ) ;
DUK_INTERNAL_DECL void * duk_heap_mem_realloc_indirect ( duk_heap * heap , duk_mem_getptr cb , void * ud , duk_size_t newsize ) ;
DUK_INTERNAL_DECL void duk_heap_mem_free ( duk_heap * heap , void * ptr ) ;
DUK_INTERNAL_DECL void duk_heap_free_freelists ( duk_heap * heap ) ;
# if defined(DUK_USE_FINALIZER_SUPPORT)
DUK_INTERNAL_DECL void duk_heap_run_finalizer ( duk_heap * heap , duk_hobject * obj ) ;
DUK_INTERNAL_DECL void duk_heap_process_finalize_list ( duk_heap * heap ) ;
# endif /* DUK_USE_FINALIZER_SUPPORT */
DUK_INTERNAL_DECL void duk_heap_mark_and_sweep ( duk_heap * heap , duk_small_uint_t flags ) ;
DUK_INTERNAL_DECL duk_uint32_t duk_heap_hashstring ( duk_heap * heap , const duk_uint8_t * str , duk_size_t len ) ;
# endif /* DUK_HEAP_H_INCLUDED */