From f9170b33e5ba152d12a5005a5f84901a2eb4bf95 Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Sat, 24 Jan 2026 09:55:24 -0600 Subject: [PATCH] rm old function as object code --- source/quickjs.c | 489 +++-------------------------------------------- 1 file changed, 23 insertions(+), 466 deletions(-) diff --git a/source/quickjs.c b/source/quickjs.c index 417d13cf..ec308ea1 100644 --- a/source/quickjs.c +++ b/source/quickjs.c @@ -172,10 +172,6 @@ enum { /* classid tag */ /* union usage | properties */ JS_CLASS_OBJECT = 1, /* must be first */ JS_CLASS_ERROR, - JS_CLASS_C_FUNCTION, /* u.cfunc */ - JS_CLASS_BYTECODE_FUNCTION, /* u.func */ - JS_CLASS_BOUND_FUNCTION, /* u.bound_function */ - JS_CLASS_C_FUNCTION_DATA, /* u.c_function_data_record */ JS_CLASS_REGEXP, /* u.regexp */ JS_CLASS_FINALIZATION_REGISTRY, JS_CLASS_BLOB, /* u.opaque (blob *) */ @@ -933,19 +929,6 @@ struct JSObject { uint32_t objkey_size; /* allocated size (power of 2, 0 if none) */ union { void *opaque; - struct JSBoundFunction *bound_function; /* JS_CLASS_BOUND_FUNCTION */ - struct JSCFunctionDataRecord *c_function_data_record; /* JS_CLASS_C_FUNCTION_DATA */ - struct { /* JS_CLASS_BYTECODE_FUNCTION: 12/24 bytes */ - struct JSFunctionBytecode *function_bytecode; - JSVarRef **var_refs; - } func; - struct { /* JS_CLASS_C_FUNCTION: 12/20 bytes */ - JSContext *realm; - JSCFunctionType c_function; - uint8_t length; - uint8_t cproto; - int16_t magic; - } cfunc; JSRegExp regexp; /* JS_CLASS_REGEXP: 8/16 bytes */ } u; }; @@ -1039,14 +1022,6 @@ static void js_dump_value_write(void *opaque, const char *buf, size_t len); static JSValue js_function_apply(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic); static void free_array(JSRuntime *rt, JSArray *arr); -static void js_c_function_finalizer(JSRuntime *rt, JSValue val); -static void js_c_function_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func); -static void js_bytecode_function_finalizer(JSRuntime *rt, JSValue val); -static void js_bytecode_function_mark(JSRuntime *rt, JSValueConst val, - JS_MarkFunc *mark_func); -static void js_bound_function_finalizer(JSRuntime *rt, JSValue val); -static void js_bound_function_mark(JSRuntime *rt, JSValueConst val, - JS_MarkFunc *mark_func); static void js_regexp_finalizer(JSRuntime *rt, JSValue val); static JSValue js_new_function(JSContext *ctx, JSFunctionKind kind); static void free_function(JSRuntime *rt, JSFunction *func); @@ -1129,9 +1104,6 @@ static JSValue *build_arg_list(JSContext *ctx, uint32_t *plen, JSValueConst array_arg); static BOOL js_get_fast_array(JSContext *ctx, JSValueConst obj, JSValue **arrpp, uint32_t *countp); -static void js_c_function_data_finalizer(JSRuntime *rt, JSValue val); -static void js_c_function_data_mark(JSRuntime *rt, JSValueConst val, - JS_MarkFunc *mark_func); static JSValue js_c_function_data_call(JSContext *ctx, JSValueConst func_obj, JSValueConst this_val, int argc, JSValueConst *argv, int flags); @@ -1332,10 +1304,6 @@ typedef struct JSClassShortDef { static JSClassShortDef const js_std_class_def[] = { { JS_ATOM_Object, NULL, NULL }, /* JS_CLASS_OBJECT */ { JS_ATOM_Error, NULL, NULL }, /* JS_CLASS_ERROR */ - { JS_ATOM_Function, js_c_function_finalizer, js_c_function_mark }, /* JS_CLASS_C_FUNCTION */ - { JS_ATOM_Function, js_bytecode_function_finalizer, js_bytecode_function_mark }, /* JS_CLASS_BYTECODE_FUNCTION */ - { JS_ATOM_Function, js_bound_function_finalizer, js_bound_function_mark }, /* JS_CLASS_BOUND_FUNCTION */ - { JS_ATOM_Function, js_c_function_data_finalizer, js_c_function_data_mark }, /* JS_CLASS_C_FUNCTION_DATA */ { JS_ATOM_RegExp, js_regexp_finalizer, NULL }, /* JS_CLASS_REGEXP */ }; @@ -1419,9 +1387,6 @@ JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque) if (init_class_range(rt, js_std_class_def, JS_CLASS_OBJECT, countof(js_std_class_def)) < 0) goto fail; - rt->class_array[JS_CLASS_C_FUNCTION].call = js_call_c_function; - rt->class_array[JS_CLASS_C_FUNCTION_DATA].call = js_c_function_data_call; - rt->class_array[JS_CLASS_BOUND_FUNCTION].call = js_call_bound_function; if (init_shape_hash(rt)) goto fail; @@ -4837,9 +4802,6 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas switch(class_id) { case JS_CLASS_OBJECT: break; - case JS_CLASS_C_FUNCTION: - p->prop[0].u.value = JS_NULL; - break; case JS_CLASS_REGEXP: p->u.regexp.pattern = NULL; p->u.regexp.bytecode = NULL; @@ -4936,9 +4898,13 @@ static void js_function_set_properties(JSContext *ctx, JSValueConst func_obj, JS_SetPropertyInternal(ctx, func_obj, JS_ATOM_name, JS_AtomToString(ctx, name)); } -static BOOL js_class_has_bytecode(JSClassID class_id) +/* Helper to check if a value is a bytecode function */ +static BOOL js_is_bytecode_function(JSValueConst val) { - return class_id == JS_CLASS_BYTECODE_FUNCTION; + if (JS_VALUE_GET_TAG(val) != JS_TAG_FUNCTION) + return FALSE; + JSFunction *f = JS_VALUE_GET_FUNCTION(val); + return f->kind == JS_FUNC_KIND_BYTECODE; } /* Check if a value is a function that uses proxy-call syntax (fn.a -> fn("a")) */ @@ -4977,13 +4943,10 @@ static JSValue js_get_function_name(JSContext *ctx, JSAtom name) static int js_method_set_properties(JSContext *ctx, JSValueConst func_obj, JSAtom name, int flags, JSValueConst home_obj) { - JSValue name_str; - - name_str = js_get_function_name(ctx, name); - if (JS_IsException(name_str)) - return -1; - if (JS_SetPropertyInternal(ctx, func_obj, JS_ATOM_name, name_str) < 0) + if (JS_VALUE_GET_TAG(func_obj) != JS_TAG_FUNCTION) return -1; + JSFunction *f = JS_VALUE_GET_FUNCTION(func_obj); + f->name = JS_DupAtom(ctx, name); return 0; } @@ -5036,32 +4999,6 @@ typedef struct JSCFunctionDataRecord { JSValue data[0]; } JSCFunctionDataRecord; -static void js_c_function_data_finalizer(JSRuntime *rt, JSValue val) -{ - JSCFunctionDataRecord *s = JS_GetOpaque(val, JS_CLASS_C_FUNCTION_DATA); - int i; - - if (s) { - for(i = 0; i < s->data_len; i++) { - JS_FreeValueRT(rt, s->data[i]); - } - js_free_rt(rt, s); - } -} - -static void js_c_function_data_mark(JSRuntime *rt, JSValueConst val, - JS_MarkFunc *mark_func) -{ - JSCFunctionDataRecord *s = JS_GetOpaque(val, JS_CLASS_C_FUNCTION_DATA); - int i; - - if (s) { - for(i = 0; i < s->data_len; i++) { - JS_MarkValue(rt, s->data[i], mark_func); - } - } -} - static JSValue js_c_function_data_call(JSContext *ctx, JSValueConst func_obj, JSValueConst this_val, int argc, JSValueConst *argv, int flags) @@ -5277,23 +5214,6 @@ static int js_intrinsic_array_set(JSContext *ctx, JSArray *arr, uint32_t idx, JS return TRUE; } -static void js_c_function_finalizer(JSRuntime *rt, JSValue val) -{ - JSObject *p = JS_VALUE_GET_OBJ(val); - - if (p->u.cfunc.realm) - JS_FreeContext(p->u.cfunc.realm); -} - -static void js_c_function_mark(JSRuntime *rt, JSValueConst val, - JS_MarkFunc *mark_func) -{ - JSObject *p = JS_VALUE_GET_OBJ(val); - - if (p->u.cfunc.realm) - mark_func(rt, &p->u.cfunc.realm->header); -} - /* Allocate intrinsic function (JS_TAG_FUNCTION) */ static JSValue js_new_function(JSContext *ctx, JSFunctionKind kind) { @@ -5475,75 +5395,6 @@ static void mark_function_children_decref(JSRuntime *rt, JSFunction *func) } } -static void js_bytecode_function_finalizer(JSRuntime *rt, JSValue val) -{ - JSObject *p = JS_VALUE_GET_OBJ(val); - JSFunctionBytecode *b; - JSVarRef **var_refs; - int i; - - b = p->u.func.function_bytecode; - if (b) { - var_refs = p->u.func.var_refs; - if (var_refs) { - for(i = 0; i < b->closure_var_count; i++) - free_var_ref(rt, var_refs[i]); - js_free_rt(rt, var_refs); - } - JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_FUNCTION_BYTECODE, b)); - } -} - -static void js_bytecode_function_mark(JSRuntime *rt, JSValueConst val, - JS_MarkFunc *mark_func) -{ - JSObject *p = JS_VALUE_GET_OBJ(val); - JSVarRef **var_refs = p->u.func.var_refs; - JSFunctionBytecode *b = p->u.func.function_bytecode; - int i; - - if (b) { - if (var_refs) { - for(i = 0; i < b->closure_var_count; i++) { - JSVarRef *var_ref = var_refs[i]; - if (var_ref) { - mark_func(rt, &var_ref->header); - } - } - } - /* must mark the function bytecode because template objects may be - part of a cycle */ - JS_MarkValue(rt, JS_MKPTR(JS_TAG_FUNCTION_BYTECODE, b), mark_func); - } -} - -static void js_bound_function_finalizer(JSRuntime *rt, JSValue val) -{ - JSObject *p = JS_VALUE_GET_OBJ(val); - JSBoundFunction *bf = p->u.bound_function; - int i; - - JS_FreeValueRT(rt, bf->func_obj); - JS_FreeValueRT(rt, bf->this_val); - for(i = 0; i < bf->argc; i++) { - JS_FreeValueRT(rt, bf->argv[i]); - } - js_free_rt(rt, bf); -} - -static void js_bound_function_mark(JSRuntime *rt, JSValueConst val, - JS_MarkFunc *mark_func) -{ - JSObject *p = JS_VALUE_GET_OBJ(val); - JSBoundFunction *bf = p->u.bound_function; - int i; - - JS_MarkValue(rt, bf->func_obj, mark_func); - JS_MarkValue(rt, bf->this_val, mark_func); - for(i = 0; i < bf->argc; i++) - JS_MarkValue(rt, bf->argv[i], mark_func); -} - static void free_object(JSRuntime *rt, JSObject *p) { int i; @@ -5591,7 +5442,6 @@ static void free_object(JSRuntime *rt, JSObject *p) /* fail safe */ p->class_id = 0; p->u.opaque = NULL; - p->u.func.var_refs = NULL; remove_gc_object(&p->header); /* no more weakrefs: free if no strong refs, else queue for zero-ref processing */ @@ -6372,55 +6222,6 @@ void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s) } switch(p->class_id) { - case JS_CLASS_C_FUNCTION: /* u.cfunc */ - s->c_func_count++; - break; - case JS_CLASS_BYTECODE_FUNCTION: /* u.func */ - { - JSFunctionBytecode *b = p->u.func.function_bytecode; - JSVarRef **var_refs = p->u.func.var_refs; - /* home_object: object will be accounted for in list scan */ - if (var_refs) { - s->memory_used_count++; - s->js_func_size += b->closure_var_count * sizeof(*var_refs); - for (i = 0; i < b->closure_var_count; i++) { - if (var_refs[i]) { - double ref_count = var_refs[i]->header.ref_count; - s->memory_used_count += 1 / ref_count; - s->js_func_size += sizeof(*var_refs[i]) / ref_count; - /* handle non object closed values */ - if (var_refs[i]->pvalue == &var_refs[i]->value) { - /* potential multiple count */ - compute_value_size(var_refs[i]->value, hp); - } - } - } - } - } - break; - case JS_CLASS_BOUND_FUNCTION: /* u.bound_function */ - { - JSBoundFunction *bf = p->u.bound_function; - /* func_obj and this_val are objects */ - for (i = 0; i < bf->argc; i++) { - compute_value_size(bf->argv[i], hp); - } - s->memory_used_count += 1; - s->memory_used_size += sizeof(*bf) + bf->argc * sizeof(*bf->argv); - } - break; - case JS_CLASS_C_FUNCTION_DATA: /* u.c_function_data_record */ - { - JSCFunctionDataRecord *fd = p->u.c_function_data_record; - if (fd) { - for (i = 0; i < fd->data_len; i++) { - compute_value_size(fd->data[i], hp); - } - s->memory_used_count += 1; - s->memory_used_size += sizeof(*fd) + fd->data_len * sizeof(*fd->data); - } - } - break; case JS_CLASS_REGEXP: /* u.regexp */ compute_jsstring_size(p->u.regexp.pattern, hp); compute_jsstring_size(p->u.regexp.bytecode, hp); @@ -9351,22 +9152,7 @@ static void js_print_object(JSPrintValueState *s, JSObject *p) comma_state = 0; is_array = FALSE; - if (p->class_id == JS_CLASS_BYTECODE_FUNCTION || rt->class_array[p->class_id].call != NULL) { - js_printf(s, "[Function"); - /* XXX: allow dump without ctx */ - if (!s->options.raw_dump && s->ctx) { - const char *func_name_str; - js_putc(s, ' '); - func_name_str = get_func_name(s->ctx, JS_MKPTR(JS_TAG_OBJECT, p)); - if (!func_name_str || func_name_str[0] == '\0') - js_puts(s, "(anonymous)"); - else - js_puts(s, func_name_str); - JS_FreeCString(s->ctx, func_name_str); - } - js_printf(s, "]"); - comma_state = 2; - } else if (p->class_id == JS_CLASS_REGEXP && s->ctx && !s->options.raw_dump) { + if (p->class_id == JS_CLASS_REGEXP && s->ctx && !s->options.raw_dump) { JSValue str = js_regexp_toString(s->ctx, JS_MKPTR(JS_TAG_OBJECT, p), 0, NULL); if (JS_IsException(str)) goto default_obj; @@ -9428,22 +9214,6 @@ static void js_print_object(JSPrintValueState *s, JSObject *p) if (j > s->options.max_item_count) js_print_more_items(s, &comma_state, j - s->options.max_item_count); } - if (s->options.raw_dump && js_class_has_bytecode(p->class_id)) { - JSFunctionBytecode *b = p->u.func.function_bytecode; - if (b->closure_var_count) { - JSVarRef **var_refs; - var_refs = p->u.func.var_refs; - - js_print_comma(s, &comma_state); - js_printf(s, "[[Closure]]: ["); - for(i = 0; i < b->closure_var_count; i++) { - if (i != 0) - js_printf(s, ", "); - js_print_value(s, var_refs[i]->value); - } - js_printf(s, " ]"); - } - } if (!is_array) { if (comma_state != 2) { @@ -10649,219 +10419,6 @@ static void profile_record_prop_site(JSRuntime *rt, JSFunctionBytecode *b, uint3 } #endif -/* VM frame management for trampoline - no malloc/free! */ -static struct VMFrame *vm_push_frame(JSContext *ctx, - JSValueConst func_obj, JSValueConst this_obj, - int argc, JSValue *argv, int flags, - const uint8_t *ret_pc, int ret_sp_offset, - int call_argc, int call_has_this) -{ - JSFunction *f; - JSFunctionBytecode *b; - struct VMFrame *frame; - int total_slots, i, arg_allocated_size; - JSValue *stack_base, *arg_buf, *var_buf; - - f = JS_VALUE_GET_FUNCTION(func_obj); - b = f->u.func.function_bytecode; - - /* Check frame stack capacity */ - if (ctx->frame_stack_top + 1 >= ctx->frame_stack_capacity) { - /* TODO: grow frame stack (for now, fail) */ - return NULL; - } - - /* Calculate space needed: args + vars + operand stack */ - if (argc < b->arg_count || (flags & JS_CALL_FLAG_COPY_ARGV)) { - arg_allocated_size = b->arg_count; - } else { - arg_allocated_size = 0; - } - total_slots = arg_allocated_size + b->var_count + b->stack_size; - - /* Check value stack capacity */ - if (ctx->value_stack_top + total_slots > ctx->value_stack_capacity) { - /* TODO: grow value stack (for now, fail) */ - return NULL; - } - - /* Push frame */ - ctx->frame_stack_top++; - frame = &ctx->frame_stack[ctx->frame_stack_top]; - - /* Store offsets (safe with realloc) */ - frame->value_stack_base = ctx->value_stack_top; - frame->stack_size_allocated = total_slots; - - /* Get pointers for initialization (only used locally) */ - stack_base = &ctx->value_stack[frame->value_stack_base]; - - if (arg_allocated_size) { - frame->arg_buf_offset = 0; - arg_buf = stack_base; - for (i = 0; i < min_int(argc, b->arg_count); i++) - arg_buf[i] = JS_DupValue(ctx, argv[i]); - for (; i < b->arg_count; i++) - arg_buf[i] = JS_NULL; - frame->arg_count = b->arg_count; - } else { - frame->arg_buf_offset = -1; /* signal: args are aliased from caller */ - frame->arg_count = argc; - } - - frame->var_buf_offset = arg_allocated_size; - var_buf = stack_base + arg_allocated_size; - for (i = 0; i < b->var_count; i++) - var_buf[i] = JS_NULL; - - frame->sp_offset = arg_allocated_size + b->var_count; - - /* Initialize frame metadata */ - frame->cur_func = JS_DupValue(ctx, func_obj); - frame->this_obj = JS_DupValue(ctx, this_obj); - frame->b = b; - frame->ctx = b->realm; - frame->pc = b->byte_code_buf; - frame->js_mode = b->js_mode; - frame->var_refs = f->u.func.var_refs; - init_list_head(&frame->var_ref_list); - - /* Continuation info for return */ - frame->ret_pc = ret_pc; - frame->ret_sp_offset = ret_sp_offset; - frame->call_argc = call_argc; - frame->call_has_this = call_has_this; - - /* Bump value stack top */ - ctx->value_stack_top += total_slots; - - return frame; -} - -static void vm_pop_frame(JSContext *ctx) -{ - struct VMFrame *frame; - int i; - struct list_head *el, *el1; - JSValue *stack_base; - - if (ctx->frame_stack_top < 0) - return; - - frame = &ctx->frame_stack[ctx->frame_stack_top]; - stack_base = &ctx->value_stack[frame->value_stack_base]; - - /* Close variable references */ - if (!list_empty(&frame->var_ref_list)) { - list_for_each_safe(el, el1, &frame->var_ref_list) { - struct JSVarRef *var_ref = list_entry(el, struct JSVarRef, var_ref_link); - var_ref->value = JS_DupValue(ctx, *var_ref->pvalue); - var_ref->pvalue = &var_ref->value; - var_ref->is_detached = TRUE; - list_del(&var_ref->var_ref_link); - } - } - - /* Free all values in this frame's value stack region */ - for (i = 0; i < frame->stack_size_allocated; i++) - JS_FreeValue(ctx, stack_base[i]); - - /* Free frame values */ - JS_FreeValue(ctx, frame->cur_func); - JS_FreeValue(ctx, frame->this_obj); - - /* Pop frame and value stack */ - ctx->value_stack_top -= frame->stack_size_allocated; - ctx->frame_stack_top--; -} - -/* Helper: get pointer from offset (used in hot path) */ -static inline JSValue *vm_frame_get_stack_ptr(JSContext *ctx, struct VMFrame *frame, int offset) -{ - return &ctx->value_stack[frame->value_stack_base + offset]; -} - -/* Helper: get current sp pointer for a frame */ -static inline JSValue *vm_frame_get_sp(JSContext *ctx, struct VMFrame *frame) -{ - return &ctx->value_stack[frame->value_stack_base + frame->sp_offset]; -} - -/* Helper: get var_buf pointer for a frame */ -static inline JSValue *vm_frame_get_var_buf(JSContext *ctx, struct VMFrame *frame) -{ - return &ctx->value_stack[frame->value_stack_base + frame->var_buf_offset]; -} - -/* Helper: get arg_buf pointer for a frame (or NULL if aliased) */ -static inline JSValue *vm_frame_get_arg_buf(JSContext *ctx, struct VMFrame *frame) -{ - if (frame->arg_buf_offset < 0) - return NULL; /* aliased */ - return &ctx->value_stack[frame->value_stack_base + frame->arg_buf_offset]; -} - -/* Trampoline VM dispatcher - runs frames without C recursion */ -static JSValue JS_CallTrampoline(JSContext *caller_ctx, JSValueConst func_obj, - JSValueConst this_obj, - int argc, JSValue *argv, int flags) -{ - JSRuntime *rt = caller_ctx->rt; - JSObject *p; - JSValue ret_val = JS_NULL; - struct VMFrame *frame; - - /* Check if function is callable */ - if (js_poll_interrupts(caller_ctx)) - return JS_EXCEPTION; - if (unlikely(JS_VALUE_GET_TAG(func_obj) != JS_TAG_OBJECT)) - return JS_ThrowTypeError(caller_ctx, "not a function"); - - p = JS_VALUE_GET_OBJ(func_obj); - if (unlikely(p->class_id != JS_CLASS_BYTECODE_FUNCTION)) { - JSClassCall *call_func; - call_func = rt->class_array[p->class_id].call; - if (!call_func) - return JS_ThrowTypeError(caller_ctx, "not a function"); - return call_func(caller_ctx, func_obj, this_obj, argc, - (JSValueConst *)argv, flags); - } - - /* Push initial frame (entry point, no continuation) */ - frame = vm_push_frame(caller_ctx, func_obj, this_obj, - argc, argv, flags, - NULL, 0, 0, 0); - if (!frame) - return JS_ThrowStackOverflow(caller_ctx); - - /* Trampoline loop - execute frames without C recursion */ - while (caller_ctx->frame_stack_top >= 0) { - /* For now, fall back to old JS_CallInternal for the actual execution */ - /* This is a stub - we'll implement vm_execute_frame next */ - /* TODO: call vm_execute_frame(caller_ctx, frame) here */ - - /* For now, just return and clean up */ - vm_pop_frame(caller_ctx); - break; - } - - return ret_val; -} - -/* Execute a single frame (delegates to OLD implementation for now) */ -static VMExecState vm_execute_frame(JSContext *ctx, struct VMFrame *frame, - JSValue *ret_val, VMCallInfo *call_info) -{ - /* TODO: Replace with proper bytecode loop extraction */ - /* For now, delegate to the old recursive implementation */ - *ret_val = JS_CallInternal(ctx, frame->cur_func, frame->this_obj, - frame->arg_count, - vm_frame_get_arg_buf(ctx, frame), 0); - if (JS_IsException(*ret_val)) - return VM_EXEC_EXCEPTION; - return VM_EXEC_RETURN; -} - static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, JSValueConst this_obj, int argc, JSValue *argv, int flags) @@ -30707,10 +30264,10 @@ static void JS_AddIntrinsicBasicObjects(JSContext *ctx) ctx->class_proto[JS_CLASS_OBJECT] = JS_NewObjectProto(ctx, JS_NULL); + /* function_proto is kept for API compatibility but functions are now intrinsic types */ ctx->function_proto = JS_NewCFunction3(ctx, js_function_proto, "", 0, JS_CFUNC_generic, 0, ctx->class_proto[JS_CLASS_OBJECT]); - ctx->class_proto[JS_CLASS_BYTECODE_FUNCTION] = JS_DupValue(ctx, ctx->function_proto); ctx->class_proto[JS_CLASS_ERROR] = JS_NewObject(ctx); for(i = 0; i < JS_NATIVE_ERROR_COUNT; i++) { @@ -31072,10 +30629,10 @@ JSValue js_debugger_build_backtrace(JSContext *ctx, const uint8_t *cur_pc) JSValue js_debugger_fn_info(JSContext *ctx, JSValue fn) { JSValue ret = JS_NewObject(ctx); - JSObject *f = JS_VALUE_GET_OBJ(fn); - if (!f || !js_class_has_bytecode(f->class_id)) + if (!js_is_bytecode_function(fn)) goto done; + JSFunction *f = JS_VALUE_GET_FUNCTION(fn); JSFunctionBytecode *b = f->u.func.function_bytecode; char atom_buf[ATOM_GET_STR_BUF_SIZE]; const char *str; @@ -31177,10 +30734,10 @@ static const char *opcode_names[] = { JSValue js_debugger_fn_bytecode(JSContext *ctx, JSValue fn) { - JSObject *f = JS_VALUE_GET_OBJ(fn); - if (!f || !js_class_has_bytecode(f->class_id)) + if (!js_is_bytecode_function(fn)) return JS_NULL; + JSFunction *f = JS_VALUE_GET_FUNCTION(fn); JSFunctionBytecode *b = f->u.func.function_bytecode; JSValue ret = JS_NewArray(ctx); @@ -31493,8 +31050,8 @@ JSValue js_debugger_local_variables(JSContext *ctx, int stack_index) { for(sf = ctx->rt->current_stack_frame; sf != NULL; sf = sf->prev_frame) { // this val is one frame up if (cur_index == stack_index - 1) { - JSObject *f = JS_VALUE_GET_OBJ(sf->cur_func); - if (f && js_class_has_bytecode(f->class_id)) { + if (js_is_bytecode_function(sf->cur_func)) { + JSFunction *f = JS_VALUE_GET_FUNCTION(sf->cur_func); JSFunctionBytecode *b = f->u.func.function_bytecode; JSValue this_obj = sf->var_buf[b->var_count]; @@ -31509,9 +31066,9 @@ JSValue js_debugger_local_variables(JSContext *ctx, int stack_index) { continue; } - JSObject *f = JS_VALUE_GET_OBJ(sf->cur_func); - if (!f || !js_class_has_bytecode(f->class_id)) + if (!js_is_bytecode_function(sf->cur_func)) goto done; + JSFunction *f = JS_VALUE_GET_FUNCTION(sf->cur_func); JSFunctionBytecode *b = f->u.func.function_bytecode; for (uint32_t i = 0; i < b->arg_count + b->var_count; i++) { @@ -31537,10 +31094,10 @@ done: void js_debugger_set_closure_variable(JSContext *ctx, JSValue fn, JSValue var_name, JSValue val) { - JSObject *f = JS_VALUE_GET_OBJ(fn); - if (!f || !js_class_has_bytecode(f->class_id)) + if (!js_is_bytecode_function(fn)) return; + JSFunction *f = JS_VALUE_GET_FUNCTION(fn); JSFunctionBytecode *b = f->u.func.function_bytecode; const char *name_str = JS_ToCString(ctx, var_name); if (!name_str) @@ -31571,10 +31128,10 @@ void js_debugger_set_closure_variable(JSContext *ctx, JSValue fn, JSValue var_na JSValue js_debugger_closure_variables(JSContext *ctx, JSValue fn) { JSValue ret = JS_NewObject(ctx); - JSObject *f = JS_VALUE_GET_OBJ(fn); - if (!f || !js_class_has_bytecode(f->class_id)) + if (!js_is_bytecode_function(fn)) goto done; + JSFunction *f = JS_VALUE_GET_FUNCTION(fn); JSFunctionBytecode *b = f->u.func.function_bytecode; for (uint32_t i = 0; i < b->closure_var_count; i++) {