ocaml style rooting macros
This commit is contained in:
@@ -183,6 +183,25 @@ void JS_DeleteGCRef (JSContext *ctx, JSGCRef *ref) {
|
||||
}
|
||||
}
|
||||
|
||||
/* JS_FRAME/JS_ROOT/JS_LOCAL helper functions */
|
||||
JSGCRef *JS_GetGCFrame (JSContext *ctx) {
|
||||
return ctx->top_gc_ref;
|
||||
}
|
||||
|
||||
JSLocalRef *JS_GetLocalFrame (JSContext *ctx) {
|
||||
return ctx->top_local_ref;
|
||||
}
|
||||
|
||||
void JS_PushLocalRef (JSContext *ctx, JSLocalRef *ref) {
|
||||
ref->prev = ctx->top_local_ref;
|
||||
ctx->top_local_ref = ref;
|
||||
}
|
||||
|
||||
void JS_RestoreFrame (JSContext *ctx, JSGCRef *gc_frame, JSLocalRef *local_frame) {
|
||||
ctx->top_gc_ref = gc_frame;
|
||||
ctx->top_local_ref = local_frame;
|
||||
}
|
||||
|
||||
void *ct_alloc (JSContext *ctx, size_t bytes, size_t align) {
|
||||
/* Align the request */
|
||||
bytes = (bytes + align - 1) & ~(align - 1);
|
||||
@@ -1608,6 +1627,14 @@ int ctx_gc (JSContext *ctx, int allow_grow, size_t alloc_size) {
|
||||
ref->val = gc_copy_value (ctx, ref->val, from_base, from_end, to_base, &to_free, to_end);
|
||||
}
|
||||
|
||||
/* Copy JS_LOCAL roots (update C locals through pointers) */
|
||||
#ifdef DUMP_GC_DETAIL
|
||||
printf(" roots: top_local_ref\n"); fflush(stdout);
|
||||
#endif
|
||||
for (JSLocalRef *ref = ctx->top_local_ref; ref != NULL; ref = ref->prev) {
|
||||
*ref->ptr = gc_copy_value (ctx, *ref->ptr, from_base, from_end, to_base, &to_free, to_end);
|
||||
}
|
||||
|
||||
/* Copy JS_AddGCRef/JS_DeleteGCRef roots */
|
||||
#ifdef DUMP_GC_DETAIL
|
||||
printf(" roots: last_gc_ref\n"); fflush(stdout);
|
||||
@@ -4383,6 +4410,10 @@ JSValue js_call_c_function (JSContext *ctx, JSValue func_obj, JSValue this_obj,
|
||||
ctx->trace_hook (ctx, JS_HOOK_CALL, &dbg, ctx->trace_data);
|
||||
}
|
||||
|
||||
#ifdef VALIDATE_GC
|
||||
uint8_t *pre_heap_base = ctx->heap_base;
|
||||
#endif
|
||||
|
||||
switch (cproto) {
|
||||
case JS_CFUNC_generic:
|
||||
ret_val = func.generic (ctx, this_obj, argc, arg_copy);
|
||||
@@ -4449,6 +4480,21 @@ JSValue js_call_c_function (JSContext *ctx, JSValue func_obj, JSValue this_obj,
|
||||
abort ();
|
||||
}
|
||||
|
||||
#ifdef VALIDATE_GC
|
||||
if (ctx->heap_base != pre_heap_base && JS_IsPtr (ret_val)) {
|
||||
void *rp = JS_VALUE_GET_PTR (ret_val);
|
||||
if (!is_ct_ptr (ctx, rp) &&
|
||||
((uint8_t *)rp < ctx->heap_base || (uint8_t *)rp >= ctx->heap_free)) {
|
||||
/* Note: f is stale after GC (func_obj was passed by value), so we
|
||||
cannot read f->name here. Just report the pointer. */
|
||||
fprintf (stderr, "VALIDATE_GC: C function returned stale ptr=%p "
|
||||
"heap=[%p,%p) after GC\n", rp,
|
||||
(void *)ctx->heap_base, (void *)ctx->heap_free);
|
||||
fflush (stderr);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ctx->c_call_root = root.prev;
|
||||
|
||||
if (unlikely (ctx->trace_hook) && (ctx->trace_type & JS_HOOK_RET))
|
||||
@@ -5356,19 +5402,27 @@ static JSValue cjson_to_jsvalue (JSContext *ctx, const cJSON *item) {
|
||||
if (cJSON_IsString (item)) return JS_NewString (ctx, item->valuestring);
|
||||
if (cJSON_IsArray (item)) {
|
||||
int n = cJSON_GetArraySize (item);
|
||||
JSValue arr = JS_NewArrayLen (ctx,n);
|
||||
JSGCRef arr_ref;
|
||||
JS_AddGCRef (ctx, &arr_ref);
|
||||
arr_ref.val = JS_NewArrayLen (ctx, n);
|
||||
for (int i = 0; i < n; i++) {
|
||||
cJSON *child = cJSON_GetArrayItem (item, i);
|
||||
JS_SetPropertyNumber (ctx, arr, i, cjson_to_jsvalue (ctx, child));
|
||||
JS_SetPropertyNumber (ctx, arr_ref.val, i, cjson_to_jsvalue (ctx, child));
|
||||
}
|
||||
return arr;
|
||||
JSValue result = arr_ref.val;
|
||||
JS_DeleteGCRef (ctx, &arr_ref);
|
||||
return result;
|
||||
}
|
||||
if (cJSON_IsObject (item)) {
|
||||
JSValue obj = JS_NewObject (ctx);
|
||||
JSGCRef obj_ref;
|
||||
JS_AddGCRef (ctx, &obj_ref);
|
||||
obj_ref.val = JS_NewObject (ctx);
|
||||
for (cJSON *child = item->child; child; child = child->next) {
|
||||
JS_SetPropertyStr (ctx, obj, child->string, cjson_to_jsvalue (ctx, child));
|
||||
JS_SetPropertyStr (ctx, obj_ref.val, child->string, cjson_to_jsvalue (ctx, child));
|
||||
}
|
||||
return obj;
|
||||
JSValue result = obj_ref.val;
|
||||
JS_DeleteGCRef (ctx, &obj_ref);
|
||||
return result;
|
||||
}
|
||||
return JS_NULL;
|
||||
}
|
||||
@@ -11879,9 +11933,13 @@ static const JSCFunctionListEntry js_math_radians_funcs[]
|
||||
JS_CFUNC_DEF ("e", 1, js_math_e) };
|
||||
|
||||
JSValue js_math_radians_use (JSContext *ctx) {
|
||||
JSValue obj = JS_NewObject (ctx);
|
||||
JS_SetPropertyFunctionList (ctx, obj, js_math_radians_funcs, countof (js_math_radians_funcs));
|
||||
return obj;
|
||||
JSGCRef obj_ref;
|
||||
JS_PushGCRef (ctx, &obj_ref);
|
||||
obj_ref.val = JS_NewObject (ctx);
|
||||
JS_SetPropertyFunctionList (ctx, obj_ref.val, js_math_radians_funcs, countof (js_math_radians_funcs));
|
||||
JSValue result = obj_ref.val;
|
||||
JS_PopGCRef (ctx, &obj_ref);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
@@ -11945,9 +12003,13 @@ static const JSCFunctionListEntry js_math_degrees_funcs[]
|
||||
JS_CFUNC_DEF ("e", 1, js_math_e) };
|
||||
|
||||
JSValue js_math_degrees_use (JSContext *ctx) {
|
||||
JSValue obj = JS_NewObject (ctx);
|
||||
JS_SetPropertyFunctionList (ctx, obj, js_math_degrees_funcs, countof (js_math_degrees_funcs));
|
||||
return obj;
|
||||
JSGCRef obj_ref;
|
||||
JS_PushGCRef (ctx, &obj_ref);
|
||||
obj_ref.val = JS_NewObject (ctx);
|
||||
JS_SetPropertyFunctionList (ctx, obj_ref.val, js_math_degrees_funcs, countof (js_math_degrees_funcs));
|
||||
JSValue result = obj_ref.val;
|
||||
JS_PopGCRef (ctx, &obj_ref);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
@@ -12010,9 +12072,13 @@ static const JSCFunctionListEntry js_math_cycles_funcs[]
|
||||
JS_CFUNC_DEF ("e", 1, js_math_e) };
|
||||
|
||||
JSValue js_math_cycles_use (JSContext *ctx) {
|
||||
JSValue obj = JS_NewObject (ctx);
|
||||
JS_SetPropertyFunctionList (ctx, obj, js_math_cycles_funcs, countof (js_math_cycles_funcs));
|
||||
return obj;
|
||||
JSGCRef obj_ref;
|
||||
JS_PushGCRef (ctx, &obj_ref);
|
||||
obj_ref.val = JS_NewObject (ctx);
|
||||
JS_SetPropertyFunctionList (ctx, obj_ref.val, js_math_cycles_funcs, countof (js_math_cycles_funcs));
|
||||
JSValue result = obj_ref.val;
|
||||
JS_PopGCRef (ctx, &obj_ref);
|
||||
return result;
|
||||
}
|
||||
/* Public API: get stack trace as cJSON array */
|
||||
cJSON *JS_GetStack(JSContext *ctx) {
|
||||
|
||||
Reference in New Issue
Block a user