2 * Debug dumping of duk_heap.
5 #include "duk_internal.h"
10 DUK_LOCAL
void duk__sanitize_snippet(char *buf
, duk_size_t buf_size
, duk_hstring
*str
) {
16 DUK_MEMZERO(buf
, buf_size
);
18 maxchars
= (duk_size_t
) (buf_size
- 1);
19 data
= DUK_HSTRING_GET_DATA(str
);
20 nchars
= ((duk_size_t
) str
->blen
< maxchars
? (duk_size_t
) str
->blen
: maxchars
);
21 for (i
= 0; i
< nchars
; i
++) {
22 duk_small_int_t c
= (duk_small_int_t
) data
[i
];
23 if (c
< 0x20 || c
> 0x7e) {
32 DUK_LOCAL
const char *duk__get_heap_type_string(duk_heaphdr
*hdr
) {
33 switch (DUK_HEAPHDR_GET_TYPE(hdr
)) {
34 case DUK_HTYPE_STRING
:
36 case DUK_HTYPE_OBJECT
:
38 case DUK_HTYPE_BUFFER
:
47 DUK_LOCAL
void duk__dump_indented(duk_heaphdr
*obj
, int index
) {
50 DUK_UNREF(duk__get_heap_type_string
);
52 #ifdef DUK_USE_REFERENCE_COUNTING
53 DUK_D(DUK_DPRINT(" [%ld]: %p %s (flags: 0x%08lx, ref: %ld) -> %!O",
56 (const char *) duk__get_heap_type_string(obj
),
57 (unsigned long) DUK_HEAPHDR_GET_FLAGS(obj
),
58 (long) DUK_HEAPHDR_GET_REFCOUNT(obj
),
59 (duk_heaphdr
*) obj
));
61 DUK_D(DUK_DPRINT(" [%ld]: %p %s (flags: 0x%08lx) -> %!O",
64 (const char *) duk__get_heap_type_string(obj
),
65 (unsigned long) DUK_HEAPHDR_GET_FLAGS(obj
),
66 (duk_heaphdr
*) obj
));
72 DUK_LOCAL
void duk__dump_heaphdr_list(duk_heap
*heap
, duk_heaphdr
*root
, const char *name
) {
83 curr
= DUK_HEAPHDR_GET_NEXT(curr
);
86 DUK_D(DUK_DPRINT("%s, %ld objects", (const char *) name
, (long) count
));
92 duk__dump_indented(curr
, count
);
93 curr
= DUK_HEAPHDR_GET_NEXT(curr
);
99 DUK_LOCAL
void duk__dump_stringtable(duk_heap
*heap
) {
103 DUK_D(DUK_DPRINT("stringtable %p, used %ld, size %ld, load %ld%%",
104 (void *) heap
->strtable
,
105 (long) heap
->st_used
,
106 (long) heap
->st_size
,
107 (long) (((double) heap
->st_used
) / ((double) heap
->st_size
) * 100.0)));
109 for (i
= 0; i
< (duk_uint_fast32_t
) heap
->st_size
; i
++) {
110 duk_hstring
*e
= heap
->strtable
[i
];
113 DUK_D(DUK_DPRINT(" [%ld]: NULL", (long) i
));
114 } else if (e
== DUK_STRTAB_DELETED_MARKER(heap
)) {
115 DUK_D(DUK_DPRINT(" [%ld]: DELETED", (long) i
));
117 duk__sanitize_snippet(buf
, sizeof(buf
), e
);
119 #ifdef DUK_USE_REFERENCE_COUNTING
120 DUK_D(DUK_DPRINT(" [%ld]: %p (flags: 0x%08lx, ref: %ld) '%s', strhash=0x%08lx, blen=%ld, clen=%ld, "
121 "arridx=%ld, internal=%ld, reserved_word=%ld, strict_reserved_word=%ld, eval_or_arguments=%ld",
124 (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr
*) e
),
125 (long) DUK_HEAPHDR_GET_REFCOUNT((duk_heaphdr
*) e
),
127 (unsigned long) e
->hash
,
130 (long) (DUK_HSTRING_HAS_ARRIDX(e
) ? 1 : 0),
131 (long) (DUK_HSTRING_HAS_INTERNAL(e
) ? 1 : 0),
132 (long) (DUK_HSTRING_HAS_RESERVED_WORD(e
) ? 1 : 0),
133 (long) (DUK_HSTRING_HAS_STRICT_RESERVED_WORD(e
) ? 1 : 0),
134 (long) (DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(e
) ? 1 : 0)));
136 DUK_D(DUK_DPRINT(" [%ld]: %p (flags: 0x%08lx) '%s', strhash=0x%08lx, blen=%ld, clen=%ld, "
137 "arridx=%ld, internal=%ld, reserved_word=%ld, strict_reserved_word=%ld, eval_or_arguments=%ld",
140 (unsigned long) DUK_HEAPHDR_GET_FLAGS((duk_heaphdr
*) e
),
145 (long) (DUK_HSTRING_HAS_ARRIDX(e
) ? 1 : 0),
146 (long) (DUK_HSTRING_HAS_INTERNAL(e
) ? 1 : 0),
147 (long) (DUK_HSTRING_HAS_RESERVED_WORD(e
) ? 1 : 0),
148 (long) (DUK_HSTRING_HAS_STRICT_RESERVED_WORD(e
) ? 1 : 0),
149 (long) (DUK_HSTRING_HAS_EVAL_OR_ARGUMENTS(e
) ? 1 : 0)));
157 DUK_LOCAL
void duk__dump_strcache(duk_heap
*heap
) {
161 DUK_D(DUK_DPRINT("stringcache"));
163 for (i
= 0; i
< (duk_uint_fast32_t
) DUK_HEAP_STRCACHE_SIZE
; i
++) {
164 duk_strcache
*c
= &heap
->strcache
[i
];
166 DUK_D(DUK_DPRINT(" [%ld]: bidx=%ld, cidx=%ld, str=NULL",
167 (long) i
, (long) c
->bidx
, (long) c
->cidx
));
169 duk__sanitize_snippet(buf
, sizeof(buf
), c
->h
);
170 DUK_D(DUK_DPRINT(" [%ld]: bidx=%ld cidx=%ld str=%s",
171 (long) i
, (long) c
->bidx
, (long) c
->cidx
, (const char *) buf
));
178 DUK_INTERNAL
void duk_debug_dump_heap(duk_heap
*heap
) {
181 DUK_D(DUK_DPRINT("=== heap %p ===", (void *) heap
));
182 DUK_D(DUK_DPRINT(" flags: 0x%08lx", (unsigned long) heap
->flags
));
184 /* Note: there is no standard formatter for function pointers */
185 #ifdef DUK_USE_GCC_PRAGMAS
186 #pragma GCC diagnostic push
187 #pragma GCC diagnostic ignored "-pedantic"
189 duk_debug_format_funcptr(buf
, sizeof(buf
), (duk_uint8_t
*) &heap
->alloc_func
, sizeof(heap
->alloc_func
));
190 DUK_D(DUK_DPRINT(" alloc_func: %s", (const char *) buf
));
191 duk_debug_format_funcptr(buf
, sizeof(buf
), (duk_uint8_t
*) &heap
->realloc_func
, sizeof(heap
->realloc_func
));
192 DUK_D(DUK_DPRINT(" realloc_func: %s", (const char *) buf
));
193 duk_debug_format_funcptr(buf
, sizeof(buf
), (duk_uint8_t
*) &heap
->free_func
, sizeof(heap
->free_func
));
194 DUK_D(DUK_DPRINT(" free_func: %s", (const char *) buf
));
195 duk_debug_format_funcptr(buf
, sizeof(buf
), (duk_uint8_t
*) &heap
->fatal_func
, sizeof(heap
->fatal_func
));
196 DUK_D(DUK_DPRINT(" fatal_func: %s", (const char *) buf
));
197 #ifdef DUK_USE_GCC_PRAGMAS
198 #pragma GCC diagnostic pop
201 DUK_D(DUK_DPRINT(" heap_udata: %p", (void *) heap
->heap_udata
));
203 #ifdef DUK_USE_MARK_AND_SWEEP
204 #ifdef DUK_USE_VOLUNTARY_GC
205 DUK_D(DUK_DPRINT(" mark-and-sweep trig counter: %ld", (long) heap
->mark_and_sweep_trigger_counter
));
207 DUK_D(DUK_DPRINT(" mark-and-sweep rec depth: %ld", (long) heap
->mark_and_sweep_recursion_depth
));
208 DUK_D(DUK_DPRINT(" mark-and-sweep base flags: 0x%08lx", (unsigned long) heap
->mark_and_sweep_base_flags
));
211 DUK_D(DUK_DPRINT(" lj.jmpbuf_ptr: %p", (void *) heap
->lj
.jmpbuf_ptr
));
212 DUK_D(DUK_DPRINT(" lj.type: %ld", (long) heap
->lj
.type
));
213 DUK_D(DUK_DPRINT(" lj.value1: %!T", (duk_tval
*) &heap
->lj
.value1
));
214 DUK_D(DUK_DPRINT(" lj.value2: %!T", (duk_tval
*) &heap
->lj
.value2
));
215 DUK_D(DUK_DPRINT(" lj.iserror: %ld", (long) heap
->lj
.iserror
));
217 DUK_D(DUK_DPRINT(" handling_error: %ld", (long) heap
->handling_error
));
219 DUK_D(DUK_DPRINT(" heap_thread: %!@O", (duk_heaphdr
*) heap
->heap_thread
));
220 DUK_D(DUK_DPRINT(" curr_thread: %!@O", (duk_heaphdr
*) heap
->curr_thread
));
221 DUK_D(DUK_DPRINT(" heap_object: %!@O", (duk_heaphdr
*) heap
->heap_object
));
223 DUK_D(DUK_DPRINT(" call_recursion_depth: %ld", (long) heap
->call_recursion_depth
));
224 DUK_D(DUK_DPRINT(" call_recursion_limit: %ld", (long) heap
->call_recursion_limit
));
226 DUK_D(DUK_DPRINT(" hash_seed: 0x%08lx", (unsigned long) heap
->hash_seed
));
227 DUK_D(DUK_DPRINT(" rnd_state: 0x%08lx", (unsigned long) heap
->rnd_state
));
229 duk__dump_strcache(heap
);
231 duk__dump_heaphdr_list(heap
, heap
->heap_allocated
, "heap allocated");
233 #ifdef DUK_USE_REFERENCE_COUNTING
234 duk__dump_heaphdr_list(heap
, heap
->refzero_list
, "refcounting refzero list");
237 #ifdef DUK_USE_MARK_AND_SWEEP
238 duk__dump_heaphdr_list(heap
, heap
->finalize_list
, "mark-and-sweep finalize list");
241 duk__dump_stringtable(heap
);
243 /* heap->strs: not worth dumping */
247 #endif /* DUK_USE_DEBUG */