add function aware to gc
This commit is contained in:
@@ -126,7 +126,7 @@ void script_startup(cell_rt *prt)
|
|||||||
rt = JS_NewRuntime();
|
rt = JS_NewRuntime();
|
||||||
|
|
||||||
JSContext *js = JS_NewContextRaw(rt);
|
JSContext *js = JS_NewContextRaw(rt);
|
||||||
JS_SetInterruptHandler(rt, actor_interrupt_cb, prt);
|
JS_SetInterruptHandler(rt, (JSInterruptHandler *)actor_interrupt_cb, prt);
|
||||||
|
|
||||||
JS_AddIntrinsicBaseObjects(js);
|
JS_AddIntrinsicBaseObjects(js);
|
||||||
JS_AddIntrinsicEval(js);
|
JS_AddIntrinsicEval(js);
|
||||||
|
|||||||
156
source/quickjs.c
156
source/quickjs.c
@@ -486,7 +486,9 @@ static inline objhdr_t *chase(JSValue v) {
|
|||||||
objhdr_t *oh = JS_VALUE_GET_PTR(v);
|
objhdr_t *oh = JS_VALUE_GET_PTR(v);
|
||||||
if (objhdr_type(*oh) != OBJ_FORWARD) return oh;
|
if (objhdr_type(*oh) != OBJ_FORWARD) return oh;
|
||||||
do {
|
do {
|
||||||
oh = (objhdr_t*)objhdr_fwd_ptr(*oh);
|
objhdr_t *next = (objhdr_t*)objhdr_fwd_ptr(*oh);
|
||||||
|
if (!next) return oh; /* NULL forward pointer (stale reference bug) */
|
||||||
|
oh = next;
|
||||||
} while (objhdr_type(*oh) == OBJ_FORWARD);
|
} while (objhdr_type(*oh) == OBJ_FORWARD);
|
||||||
return oh;
|
return oh;
|
||||||
}
|
}
|
||||||
@@ -2200,13 +2202,17 @@ static void buddy_destroy (BuddyAllocator *b) {
|
|||||||
|
|
||||||
/* Forward declarations for GC helpers */
|
/* Forward declarations for GC helpers */
|
||||||
static int ctx_gc (JSContext *ctx);
|
static int ctx_gc (JSContext *ctx);
|
||||||
static JSValue gc_copy_value (JSContext *ctx, JSValue v, uint8_t *to_base, uint8_t **to_free, uint8_t *to_end);
|
static JSValue gc_copy_value (JSContext *ctx, JSValue v, uint8_t *from_base, uint8_t *from_end, uint8_t *to_base, uint8_t **to_free, uint8_t *to_end);
|
||||||
static void gc_scan_object (JSContext *ctx, void *ptr, uint8_t *to_base, uint8_t **to_free, uint8_t *to_end);
|
static void gc_scan_object (JSContext *ctx, void *ptr, uint8_t *from_base, uint8_t *from_end, uint8_t *to_base, uint8_t **to_free, uint8_t *to_end);
|
||||||
static size_t gc_object_size (void *ptr);
|
static size_t gc_object_size (void *ptr);
|
||||||
|
|
||||||
|
/* Alignment for GC object sizes - must match max alignment requirement */
|
||||||
|
#define GC_ALIGN 8
|
||||||
|
static inline size_t gc_align_up (size_t n) { return (n + GC_ALIGN - 1) & ~(GC_ALIGN - 1); }
|
||||||
|
|
||||||
/* Get size of a heap object based on its type */
|
/* Get size of a heap object based on its type */
|
||||||
static size_t gc_object_size (void *ptr) {
|
static size_t gc_object_size (void *ptr) {
|
||||||
objhdr_t *hdr = ptr;
|
objhdr_t hdr = *(objhdr_t *)ptr;
|
||||||
uint8_t type = objhdr_type (hdr);
|
uint8_t type = objhdr_type (hdr);
|
||||||
uint64_t cap = objhdr_cap56 (hdr);
|
uint64_t cap = objhdr_cap56 (hdr);
|
||||||
|
|
||||||
@@ -2214,97 +2220,75 @@ static size_t gc_object_size (void *ptr) {
|
|||||||
case OBJ_ARRAY: {
|
case OBJ_ARRAY: {
|
||||||
/* JSArray + inline values array. Cap is element capacity. */
|
/* JSArray + inline values array. Cap is element capacity. */
|
||||||
size_t values_size = sizeof (JSValue) * cap;
|
size_t values_size = sizeof (JSValue) * cap;
|
||||||
return sizeof (JSArray) + values_size;
|
return gc_align_up (sizeof (JSArray) + values_size);
|
||||||
}
|
}
|
||||||
case OBJ_TEXT: {
|
case OBJ_TEXT: {
|
||||||
/* JSText: header + pad + hdr + length + packed chars */
|
/* JSText: header + pad + hdr + length + packed chars */
|
||||||
size_t word_count = (cap + 1) / 2;
|
size_t word_count = (cap + 1) / 2;
|
||||||
return sizeof (JSText) + word_count * sizeof (uint64_t);
|
return gc_align_up (sizeof (JSText) + word_count * sizeof (uint64_t));
|
||||||
}
|
}
|
||||||
case OBJ_RECORD: {
|
case OBJ_RECORD: {
|
||||||
/* JSRecord + inline tab. Cap is mask, so tab size is mask+1 entries. */
|
/* JSRecord + inline tab. Cap is mask, so tab size is mask+1 entries. */
|
||||||
size_t tab_size = sizeof (JSRecordEntry) * (cap + 1);
|
size_t tab_size = sizeof (JSRecordEntry) * (cap + 1);
|
||||||
return sizeof (JSRecord) + tab_size;
|
return gc_align_up (sizeof (JSRecord) + tab_size);
|
||||||
}
|
}
|
||||||
case OBJ_FUNCTION:
|
case OBJ_FUNCTION:
|
||||||
case OBJ_CODE:
|
return gc_align_up (sizeof (JSFunction));
|
||||||
case OBJ_FRAME:
|
|
||||||
case OBJ_BLOB:
|
|
||||||
default:
|
default:
|
||||||
/* Conservative estimate for unknown types */
|
/* Unknown type - fatal error, heap is corrupt or scan desync'd */
|
||||||
return 64;
|
fprintf (stderr, "gc_object_size: unknown object type %d at %p\n", type, ptr);
|
||||||
|
abort ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy a single value, returning the new value with updated pointer if needed.
|
/* Copy a single value, returning the new value with updated pointer if needed.
|
||||||
Follows and collapses forward pointer chains. */
|
Simple Cheney: if already forwarded, return new address; else copy and forward.
|
||||||
static JSValue gc_copy_value (JSContext *ctx, JSValue v, uint8_t *to_base,
|
from_base/from_end define the OLD heap bounds (where objects are being copied FROM). */
|
||||||
uint8_t **to_free, uint8_t *to_end) {
|
static JSValue gc_copy_value (JSContext *ctx, JSValue v, uint8_t *from_base, uint8_t *from_end,
|
||||||
if (!JS_IsPtr (v)) return v; /* Immediate value - no copy needed */
|
uint8_t *to_base, uint8_t **to_free, uint8_t *to_end) {
|
||||||
|
if (!JS_IsPtr (v)) {
|
||||||
|
return v; /* Immediate value - no copy needed */
|
||||||
|
}
|
||||||
|
|
||||||
void *ptr = JS_VALUE_GET_PTR (v);
|
void *ptr = JS_VALUE_GET_PTR (v);
|
||||||
if (is_stone_ptr (ctx, ptr)) return v; /* Stone memory - don't copy */
|
if (is_stone_ptr (ctx, ptr)) return v; /* Stone memory - don't copy */
|
||||||
|
|
||||||
/* Check if pointer is in current heap (not external allocation) */
|
/* Check if pointer is in old heap (from-space) */
|
||||||
if ((uint8_t *)ptr < ctx->heap_base || (uint8_t *)ptr >= ctx->heap_end) {
|
if ((uint8_t *)ptr < from_base || (uint8_t *)ptr >= from_end) {
|
||||||
/* External allocation (using js_malloc_rt) - keep reference */
|
/* External allocation - keep reference as-is */
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
objhdr_t *hdr_ptr = ptr;
|
objhdr_t *hdr_ptr = ptr;
|
||||||
objhdr_t hdr = *hdr_ptr;
|
objhdr_t hdr = *hdr_ptr;
|
||||||
|
|
||||||
/* Collect forward pointer chain */
|
/* Already forwarded? Return the new location. */
|
||||||
objhdr_t *chain[64];
|
if (objhdr_type (hdr) == OBJ_FORWARD) {
|
||||||
int chain_len = 0;
|
|
||||||
|
|
||||||
while (objhdr_type (hdr) == OBJ_FORWARD) {
|
|
||||||
void *fwd_target = objhdr_fwd_ptr (hdr);
|
void *fwd_target = objhdr_fwd_ptr (hdr);
|
||||||
|
return JS_MKPTR (fwd_target);
|
||||||
/* Stale pointer bug: forward target is NULL (should not happen with proper rooting) */
|
|
||||||
if (!fwd_target) {
|
|
||||||
return v; /* Return original value and let caller handle it */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if forward target is in new space */
|
|
||||||
if ((uint8_t *)fwd_target >= to_base && (uint8_t *)fwd_target < *to_free) {
|
|
||||||
/* Target is in new space - update chain and return */
|
|
||||||
for (int i = 0; i < chain_len; i++) {
|
|
||||||
*chain[i] = objhdr_make_fwd (fwd_target);
|
|
||||||
}
|
|
||||||
return JS_MKPTR (fwd_target);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chain_len < 64) chain[chain_len++] = hdr_ptr;
|
|
||||||
hdr_ptr = (objhdr_t *)fwd_target;
|
|
||||||
hdr = *hdr_ptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* hdr_ptr points to real object in old space - copy it */
|
/* Copy object to to-space */
|
||||||
size_t size = gc_object_size (hdr_ptr);
|
size_t size = gc_object_size (hdr_ptr);
|
||||||
if (*to_free + size > to_end) {
|
if (*to_free + size > to_end) {
|
||||||
/* Should not happen if we sized new block correctly */
|
/* Out of space - this is a fatal error */
|
||||||
return v;
|
fprintf (stderr, "gc_copy_value: out of to-space, need %zu bytes\n", size);
|
||||||
|
abort ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void *new_ptr = *to_free;
|
void *new_ptr = *to_free;
|
||||||
memcpy (new_ptr, hdr_ptr, size);
|
memcpy (new_ptr, hdr_ptr, size);
|
||||||
*to_free += size;
|
*to_free += size;
|
||||||
|
|
||||||
/* Install forward in old location */
|
/* Install forward pointer in old location */
|
||||||
*hdr_ptr = objhdr_make_fwd (new_ptr);
|
*hdr_ptr = objhdr_make_fwd (new_ptr);
|
||||||
|
|
||||||
/* Update ALL chain pointers to final location */
|
|
||||||
for (int i = 0; i < chain_len; i++) {
|
|
||||||
*chain[i] = objhdr_make_fwd (new_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
return JS_MKPTR (new_ptr);
|
return JS_MKPTR (new_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Scan a copied object and update its internal references */
|
/* Scan a copied object and update its internal references */
|
||||||
static void gc_scan_object (JSContext *ctx, void *ptr, uint8_t *to_base,
|
static void gc_scan_object (JSContext *ctx, void *ptr, uint8_t *from_base, uint8_t *from_end,
|
||||||
uint8_t **to_free, uint8_t *to_end) {
|
uint8_t *to_base, uint8_t **to_free, uint8_t *to_end) {
|
||||||
objhdr_t hdr = *(objhdr_t *)ptr;
|
objhdr_t hdr = *(objhdr_t *)ptr;
|
||||||
uint8_t type = objhdr_type (hdr);
|
uint8_t type = objhdr_type (hdr);
|
||||||
|
|
||||||
@@ -2312,7 +2296,7 @@ static void gc_scan_object (JSContext *ctx, void *ptr, uint8_t *to_base,
|
|||||||
case OBJ_ARRAY: {
|
case OBJ_ARRAY: {
|
||||||
JSArray *arr = (JSArray *)ptr;
|
JSArray *arr = (JSArray *)ptr;
|
||||||
for (uint32_t i = 0; i < arr->len; i++) {
|
for (uint32_t i = 0; i < arr->len; i++) {
|
||||||
arr->values[i] = gc_copy_value (ctx, arr->values[i], to_base, to_free, to_end);
|
arr->values[i] = gc_copy_value (ctx, arr->values[i], from_base, from_end, to_base, to_free, to_end);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2321,7 +2305,7 @@ static void gc_scan_object (JSContext *ctx, void *ptr, uint8_t *to_base,
|
|||||||
/* Copy prototype */
|
/* Copy prototype */
|
||||||
if (rec->proto) {
|
if (rec->proto) {
|
||||||
JSValue proto_val = JS_MKPTR (rec->proto);
|
JSValue proto_val = JS_MKPTR (rec->proto);
|
||||||
proto_val = gc_copy_value (ctx, proto_val, to_base, to_free, to_end);
|
proto_val = gc_copy_value (ctx, proto_val, from_base, from_end, to_base, to_free, to_end);
|
||||||
rec->proto = (JSRecord *)JS_VALUE_GET_PTR (proto_val);
|
rec->proto = (JSRecord *)JS_VALUE_GET_PTR (proto_val);
|
||||||
}
|
}
|
||||||
/* Copy table entries */
|
/* Copy table entries */
|
||||||
@@ -2329,19 +2313,28 @@ static void gc_scan_object (JSContext *ctx, void *ptr, uint8_t *to_base,
|
|||||||
for (uint32_t i = 0; i <= mask; i++) {
|
for (uint32_t i = 0; i <= mask; i++) {
|
||||||
JSValue k = rec->slots[i].key;
|
JSValue k = rec->slots[i].key;
|
||||||
if (!rec_key_is_empty (k) && !rec_key_is_tomb (k)) {
|
if (!rec_key_is_empty (k) && !rec_key_is_tomb (k)) {
|
||||||
rec->slots[i].key = gc_copy_value (ctx, k, to_base, to_free, to_end);
|
rec->slots[i].key = gc_copy_value (ctx, k, from_base, from_end, to_base, to_free, to_end);
|
||||||
rec->slots[i].val = gc_copy_value (ctx, rec->slots[i].val, to_base, to_free, to_end);
|
rec->slots[i].val = gc_copy_value (ctx, rec->slots[i].val, from_base, from_end, to_base, to_free, to_end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case OBJ_FUNCTION: {
|
||||||
|
JSFunction *fn = (JSFunction *)ptr;
|
||||||
|
/* Scan the function name */
|
||||||
|
fn->name = gc_copy_value (ctx, fn->name, from_base, from_end, to_base, to_free, to_end);
|
||||||
|
/* Note: function_bytecode and var_refs are allocated via js_malloc, not bump allocator */
|
||||||
|
break;
|
||||||
|
}
|
||||||
case OBJ_TEXT:
|
case OBJ_TEXT:
|
||||||
case OBJ_BLOB:
|
case OBJ_BLOB:
|
||||||
case OBJ_CODE:
|
case OBJ_CODE:
|
||||||
/* No internal references to scan */
|
/* No internal references to scan */
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
/* Unknown type during scan - fatal error */
|
||||||
|
fprintf (stderr, "gc_scan_object: unknown object type %d at %p\n", type, ptr);
|
||||||
|
abort ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2351,6 +2344,14 @@ static int ctx_gc (JSContext *ctx) {
|
|||||||
size_t old_used = ctx->heap_free - ctx->heap_base;
|
size_t old_used = ctx->heap_free - ctx->heap_base;
|
||||||
size_t old_heap_size = ctx->current_block_size;
|
size_t old_heap_size = ctx->current_block_size;
|
||||||
|
|
||||||
|
/* Save OLD heap bounds before allocating new block */
|
||||||
|
uint8_t *from_base = ctx->heap_base;
|
||||||
|
uint8_t *from_end = ctx->heap_end;
|
||||||
|
|
||||||
|
#ifdef DUMP_GC
|
||||||
|
printf("ctx_gc: from_base=%p from_end=%p size=%zu\n", (void*)from_base, (void*)from_end, old_heap_size);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Request new block from runtime */
|
/* Request new block from runtime */
|
||||||
size_t new_size = ctx->next_block_size;
|
size_t new_size = ctx->next_block_size;
|
||||||
uint8_t *new_block = buddy_alloc (&rt->buddy, new_size);
|
uint8_t *new_block = buddy_alloc (&rt->buddy, new_size);
|
||||||
@@ -2366,55 +2367,55 @@ static int ctx_gc (JSContext *ctx) {
|
|||||||
uint8_t *to_end = new_block + new_size;
|
uint8_t *to_end = new_block + new_size;
|
||||||
|
|
||||||
/* Copy roots: global object, class prototypes, exception, etc. */
|
/* Copy roots: global object, class prototypes, exception, etc. */
|
||||||
ctx->global_obj = gc_copy_value (ctx, ctx->global_obj, to_base, &to_free, to_end);
|
ctx->global_obj = gc_copy_value (ctx, ctx->global_obj, from_base, from_end, to_base, &to_free, to_end);
|
||||||
ctx->global_var_obj = gc_copy_value (ctx, ctx->global_var_obj, to_base, &to_free, to_end);
|
ctx->global_var_obj = gc_copy_value (ctx, ctx->global_var_obj, from_base, from_end, to_base, &to_free, to_end);
|
||||||
ctx->regexp_ctor = gc_copy_value (ctx, ctx->regexp_ctor, to_base, &to_free, to_end);
|
ctx->regexp_ctor = gc_copy_value (ctx, ctx->regexp_ctor, from_base, from_end, to_base, &to_free, to_end);
|
||||||
ctx->throw_type_error = gc_copy_value (ctx, ctx->throw_type_error, to_base, &to_free, to_end);
|
ctx->throw_type_error = gc_copy_value (ctx, ctx->throw_type_error, from_base, from_end, to_base, &to_free, to_end);
|
||||||
ctx->eval_obj = gc_copy_value (ctx, ctx->eval_obj, to_base, &to_free, to_end);
|
ctx->eval_obj = gc_copy_value (ctx, ctx->eval_obj, from_base, from_end, to_base, &to_free, to_end);
|
||||||
|
|
||||||
for (int i = 0; i < JS_NATIVE_ERROR_COUNT; i++) {
|
for (int i = 0; i < JS_NATIVE_ERROR_COUNT; i++) {
|
||||||
ctx->native_error_proto[i] = gc_copy_value (ctx, ctx->native_error_proto[i], to_base, &to_free, to_end);
|
ctx->native_error_proto[i] = gc_copy_value (ctx, ctx->native_error_proto[i], from_base, from_end, to_base, &to_free, to_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy class prototypes */
|
/* Copy class prototypes */
|
||||||
for (int i = 0; i < rt->class_count; i++) {
|
for (int i = 0; i < rt->class_count; i++) {
|
||||||
ctx->class_proto[i] = gc_copy_value (ctx, ctx->class_proto[i], to_base, &to_free, to_end);
|
ctx->class_proto[i] = gc_copy_value (ctx, ctx->class_proto[i], from_base, from_end, to_base, &to_free, to_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy value stack */
|
/* Copy value stack */
|
||||||
for (int i = 0; i < ctx->value_stack_top; i++) {
|
for (int i = 0; i < ctx->value_stack_top; i++) {
|
||||||
ctx->value_stack[i] = gc_copy_value (ctx, ctx->value_stack[i], to_base, &to_free, to_end);
|
ctx->value_stack[i] = gc_copy_value (ctx, ctx->value_stack[i], from_base, from_end, to_base, &to_free, to_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy frame stack references */
|
/* Copy frame stack references */
|
||||||
for (int i = 0; i <= ctx->frame_stack_top; i++) {
|
for (int i = 0; i <= ctx->frame_stack_top; i++) {
|
||||||
struct VMFrame *frame = &ctx->frame_stack[i];
|
struct VMFrame *frame = &ctx->frame_stack[i];
|
||||||
frame->cur_func = gc_copy_value (ctx, frame->cur_func, to_base, &to_free, to_end);
|
frame->cur_func = gc_copy_value (ctx, frame->cur_func, from_base, from_end, to_base, &to_free, to_end);
|
||||||
frame->this_obj = gc_copy_value (ctx, frame->this_obj, to_base, &to_free, to_end);
|
frame->this_obj = gc_copy_value (ctx, frame->this_obj, from_base, from_end, to_base, &to_free, to_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy JS_PUSH_VALUE/JS_POP_VALUE roots */
|
/* Copy JS_PUSH_VALUE/JS_POP_VALUE roots */
|
||||||
for (JSGCRef *ref = ctx->top_gc_ref; ref != NULL; ref = ref->prev) {
|
for (JSGCRef *ref = ctx->top_gc_ref; ref != NULL; ref = ref->prev) {
|
||||||
ref->val = gc_copy_value (ctx, ref->val, to_base, &to_free, to_end);
|
ref->val = gc_copy_value (ctx, ref->val, from_base, from_end, to_base, &to_free, to_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy JS_AddGCRef/JS_DeleteGCRef roots */
|
/* Copy JS_AddGCRef/JS_DeleteGCRef roots */
|
||||||
for (JSGCRef *ref = ctx->last_gc_ref; ref != NULL; ref = ref->prev) {
|
for (JSGCRef *ref = ctx->last_gc_ref; ref != NULL; ref = ref->prev) {
|
||||||
ref->val = gc_copy_value (ctx, ref->val, to_base, &to_free, to_end);
|
ref->val = gc_copy_value (ctx, ref->val, from_base, from_end, to_base, &to_free, to_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cheney scan: scan copied objects to find more references */
|
/* Cheney scan: scan copied objects to find more references */
|
||||||
uint8_t *scan = to_base;
|
uint8_t *scan = to_base;
|
||||||
while (scan < to_free) {
|
while (scan < to_free) {
|
||||||
gc_scan_object (ctx, scan, to_base, &to_free, to_end);
|
gc_scan_object (ctx, scan, from_base, from_end, to_base, &to_free, to_end);
|
||||||
scan += gc_object_size (scan);
|
scan += gc_object_size (scan);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return old block to buddy allocator */
|
/* Return old block to buddy allocator */
|
||||||
#ifdef POISON_HEAP
|
#ifdef POISON_HEAP
|
||||||
gc_poison_region(ctx->heap_base, ctx->current_block_size);
|
gc_poison_region(from_base, old_heap_size);
|
||||||
#endif
|
#endif
|
||||||
buddy_free (&rt->buddy, ctx->heap_base, ctx->current_block_size);
|
buddy_free (&rt->buddy, from_base, old_heap_size);
|
||||||
|
|
||||||
/* Update context with new block */
|
/* Update context with new block */
|
||||||
size_t new_used = to_free - to_base;
|
size_t new_used = to_free - to_base;
|
||||||
@@ -2612,7 +2613,16 @@ JSContext *JS_NewContextRawWithHeapSize (JSRuntime *rt, size_t heap_size) {
|
|||||||
ctx->heap_free = ctx->heap_base;
|
ctx->heap_free = ctx->heap_base;
|
||||||
ctx->heap_end = ctx->heap_base + ctx->current_block_size;
|
ctx->heap_end = ctx->heap_base + ctx->current_block_size;
|
||||||
|
|
||||||
|
#ifdef DUMP_GC
|
||||||
|
printf("Context init: heap_base=%p heap_end=%p size=%zu\n", (void*)ctx->heap_base, (void*)ctx->heap_end, ctx->current_block_size);
|
||||||
|
#endif
|
||||||
|
|
||||||
JS_AddIntrinsicBasicObjects (ctx);
|
JS_AddIntrinsicBasicObjects (ctx);
|
||||||
|
|
||||||
|
#ifdef DUMP_GC
|
||||||
|
printf("After BasicObjects: heap_base=%p heap_end=%p heap_free=%p\n", (void*)ctx->heap_base, (void*)ctx->heap_end, (void*)ctx->heap_free);
|
||||||
|
#endif
|
||||||
|
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user