varref cleanup
This commit is contained in:
@@ -28,7 +28,6 @@ FMT(none)
|
||||
FMT(none_int)
|
||||
FMT(none_loc)
|
||||
FMT(none_arg)
|
||||
FMT(none_var_ref)
|
||||
FMT(u8)
|
||||
FMT(i8)
|
||||
FMT(loc8)
|
||||
@@ -42,7 +41,6 @@ FMT(npopx)
|
||||
FMT(npop_u16)
|
||||
FMT(loc)
|
||||
FMT(arg)
|
||||
FMT(var_ref)
|
||||
FMT(u32)
|
||||
FMT(i32)
|
||||
FMT(const)
|
||||
@@ -108,16 +106,18 @@ DEF( eval, 5, 1, 1, npop_u16) /* func args... -> ret_val */
|
||||
DEF( regexp, 1, 2, 1, none) /* create a RegExp object from the pattern and a
|
||||
bytecode string */
|
||||
|
||||
DEF( check_var, 5, 0, 1, key) /* check if a variable exists */
|
||||
DEF( get_var_undef, 5, 0, 1, key) /* push undefined if the variable does not exist */
|
||||
DEF( get_var, 5, 0, 1, key) /* throw an exception if the variable does not exist */
|
||||
DEF( put_var, 5, 1, 0, key) /* must come after get_var */
|
||||
DEF( put_var_init, 5, 1, 0, key) /* must come after put_var. Used to initialize a global lexical variable */
|
||||
DEF( put_var_strict, 5, 2, 0, key) /* for strict mode variable write */
|
||||
/* Global variable access - resolved by linker to get/set_global_slot */
|
||||
DEF( check_var, 5, 0, 1, key) /* check if a variable exists - resolved by linker */
|
||||
DEF( get_var_undef, 5, 0, 1, key) /* resolved by linker to get_global_slot */
|
||||
DEF( get_var, 5, 0, 1, key) /* resolved by linker to get_global_slot */
|
||||
DEF( put_var, 5, 1, 0, key) /* resolved by linker to set_global_slot */
|
||||
DEF( put_var_init, 5, 1, 0, key) /* resolved by linker to set_global_slot */
|
||||
DEF( put_var_strict, 5, 2, 0, key) /* resolved by linker to set_global_slot */
|
||||
|
||||
DEF( get_ref_value, 1, 2, 3, none)
|
||||
DEF( put_ref_value, 1, 3, 0, none)
|
||||
|
||||
/* Global variable opcodes - resolved by linker to get/set_global_slot */
|
||||
DEF( define_var, 6, 0, 0, key_u8)
|
||||
DEF(check_define_var, 6, 0, 0, key_u8)
|
||||
DEF( define_func, 6, 1, 0, key_u8)
|
||||
@@ -144,18 +144,19 @@ DEF( set_loc, 3, 1, 1, loc) /* must come after put_loc */
|
||||
DEF( get_arg, 3, 0, 1, arg)
|
||||
DEF( put_arg, 3, 1, 0, arg) /* must come after get_arg */
|
||||
DEF( set_arg, 3, 1, 1, arg) /* must come after put_arg */
|
||||
DEF( get_var_ref, 3, 0, 1, var_ref)
|
||||
DEF( put_var_ref, 3, 1, 0, var_ref) /* must come after get_var_ref */
|
||||
DEF( set_var_ref, 3, 1, 1, var_ref) /* must come after put_var_ref */
|
||||
/* Var ref opcodes - deprecated, resolved to get_up/set_up during scope resolution */
|
||||
DEF( get_var_ref, 3, 0, 1, loc) /* deprecated - use get_up */
|
||||
DEF( put_var_ref, 3, 1, 0, loc) /* deprecated - use set_up */
|
||||
DEF( set_var_ref, 3, 1, 1, loc) /* deprecated - use set_up */
|
||||
DEF(set_loc_uninitialized, 3, 0, 0, loc)
|
||||
DEF( get_loc_check, 3, 0, 1, loc)
|
||||
DEF( put_loc_check, 3, 1, 0, loc) /* must come after get_loc_check */
|
||||
DEF( put_loc_check_init, 3, 1, 0, loc)
|
||||
DEF(get_loc_checkthis, 3, 0, 1, loc)
|
||||
DEF(get_var_ref_check, 3, 0, 1, var_ref)
|
||||
DEF(put_var_ref_check, 3, 1, 0, var_ref) /* must come after get_var_ref_check */
|
||||
DEF(put_var_ref_check_init, 3, 1, 0, var_ref)
|
||||
DEF( close_loc, 3, 0, 0, loc)
|
||||
DEF(get_var_ref_check, 3, 0, 1, loc) /* deprecated - use get_up */
|
||||
DEF(put_var_ref_check, 3, 1, 0, loc) /* deprecated - use set_up */
|
||||
DEF(put_var_ref_check_init, 3, 1, 0, loc) /* deprecated - use set_up */
|
||||
DEF( close_loc, 3, 0, 0, loc) /* deprecated - no longer needed */
|
||||
DEF( if_false, 5, 1, 0, label)
|
||||
DEF( if_true, 5, 1, 0, label) /* must come after if_false */
|
||||
DEF( goto, 5, 0, 0, label) /* must come after if_true */
|
||||
@@ -166,10 +167,11 @@ DEF( nip_catch, 1, 2, 1, none) /* catch ... a -> a */
|
||||
|
||||
DEF( to_propkey, 1, 1, 1, none)
|
||||
|
||||
DEF( make_loc_ref, 7, 0, 2, key_u16)
|
||||
DEF( make_arg_ref, 7, 0, 2, key_u16)
|
||||
DEF(make_var_ref_ref, 7, 0, 2, key_u16)
|
||||
DEF( make_var_ref, 5, 0, 2, key)
|
||||
/* Deprecated make_*_ref opcodes - no longer needed with outer_frame model */
|
||||
DEF( make_loc_ref, 7, 0, 2, key_u16) /* deprecated */
|
||||
DEF( make_arg_ref, 7, 0, 2, key_u16) /* deprecated */
|
||||
DEF(make_var_ref_ref, 7, 0, 2, key_u16) /* deprecated */
|
||||
DEF( make_var_ref, 5, 0, 2, key) /* deprecated */
|
||||
|
||||
/* arithmetic/logic operations */
|
||||
DEF( neg, 1, 1, 1, none)
|
||||
@@ -184,7 +186,7 @@ DEF( add_loc, 2, 1, 0, loc8)
|
||||
DEF( not, 1, 1, 1, none)
|
||||
DEF( lnot, 1, 1, 1, none)
|
||||
DEF( delete, 1, 2, 1, none)
|
||||
DEF( delete_var, 5, 0, 1, key)
|
||||
DEF( delete_var, 5, 0, 1, key) /* deprecated - global object is immutable */
|
||||
|
||||
DEF( mul, 1, 2, 1, none)
|
||||
DEF( mul_float, 1, 2, 1, none)
|
||||
@@ -292,18 +294,6 @@ DEF( set_arg0, 1, 1, 1, none_arg)
|
||||
DEF( set_arg1, 1, 1, 1, none_arg)
|
||||
DEF( set_arg2, 1, 1, 1, none_arg)
|
||||
DEF( set_arg3, 1, 1, 1, none_arg)
|
||||
DEF( get_var_ref0, 1, 0, 1, none_var_ref)
|
||||
DEF( get_var_ref1, 1, 0, 1, none_var_ref)
|
||||
DEF( get_var_ref2, 1, 0, 1, none_var_ref)
|
||||
DEF( get_var_ref3, 1, 0, 1, none_var_ref)
|
||||
DEF( put_var_ref0, 1, 1, 0, none_var_ref)
|
||||
DEF( put_var_ref1, 1, 1, 0, none_var_ref)
|
||||
DEF( put_var_ref2, 1, 1, 0, none_var_ref)
|
||||
DEF( put_var_ref3, 1, 1, 0, none_var_ref)
|
||||
DEF( set_var_ref0, 1, 1, 1, none_var_ref)
|
||||
DEF( set_var_ref1, 1, 1, 1, none_var_ref)
|
||||
DEF( set_var_ref2, 1, 1, 1, none_var_ref)
|
||||
DEF( set_var_ref3, 1, 1, 1, none_var_ref)
|
||||
|
||||
DEF( if_false8, 2, 1, 0, label8)
|
||||
DEF( if_true8, 2, 1, 0, label8) /* must come after if_false8 */
|
||||
|
||||
332
source/quickjs.c
332
source/quickjs.c
@@ -129,7 +129,6 @@ typedef struct JSRecord JSRecord;
|
||||
typedef struct JSFunction JSFunction;
|
||||
typedef struct JSFrame JSFrame;
|
||||
typedef struct JSCode JSCode;
|
||||
typedef struct JSVarRef JSVarRef;
|
||||
|
||||
#define OBJHDR_CAP_SHIFT 8u
|
||||
#define OBJHDR_CAP_MASK (((objhdr_t)1ull << 56) - 1ull)
|
||||
@@ -147,14 +146,6 @@ typedef struct JSVarRef JSVarRef;
|
||||
/* Extract pointer (clear low bits) */
|
||||
#define JS_VALUE_GET_PTR(v) ((void *)((v) & ~((JSValue)(JSW - 1))))
|
||||
|
||||
/* JSVarRef - variable reference for closures */
|
||||
struct JSVarRef {
|
||||
uint8_t is_detached; /* TRUE if pvalue points to value field */
|
||||
uint8_t pad[7];
|
||||
JSValue *pvalue; /* pointer to the value (stack or &value) */
|
||||
JSValue value; /* captured value when detached */
|
||||
struct list_head var_ref_link; /* link in frame's var_ref_list */
|
||||
};
|
||||
|
||||
static inline JS_BOOL JS_VALUE_IS_TEXT (JSValue v) {
|
||||
int tag = JS_VALUE_GET_TAG (v);
|
||||
@@ -278,7 +269,6 @@ enum {
|
||||
JS_CLASS_ERROR,
|
||||
JS_CLASS_REGEXP, /* u.regexp */
|
||||
JS_CLASS_BLOB, /* u.opaque (blob *) */
|
||||
JS_CLASS_VAR_REF_OBJECT, /* u.opaque (JSVarRef *) - for var ref objects */
|
||||
|
||||
JS_CLASS_INIT_COUNT, /* last entry for predefined classes */
|
||||
};
|
||||
@@ -414,7 +404,6 @@ typedef struct JSStackFrame {
|
||||
JSValue cur_func; /* current function, JS_NULL if the frame is detached */
|
||||
JSValue *arg_buf; /* arguments */
|
||||
JSValue *var_buf; /* variables */
|
||||
struct list_head var_ref_list; /* list of JSVarRef.var_ref_link */
|
||||
const uint8_t *cur_pc; /* only used in bytecode functions : PC of the
|
||||
instruction after the call */
|
||||
int arg_count;
|
||||
@@ -444,8 +433,6 @@ struct VMFrame {
|
||||
|
||||
JSValue cur_func; /* current function object */
|
||||
JSValue this_obj; /* this binding */
|
||||
struct JSVarRef **var_refs; /* closure variable references */
|
||||
struct list_head var_ref_list; /* list of JSVarRef.var_ref_link */
|
||||
int arg_count;
|
||||
int js_mode;
|
||||
int stack_size_allocated; /* total size allocated for this frame */
|
||||
@@ -1630,7 +1617,6 @@ typedef struct JSFunction {
|
||||
} cfunc;
|
||||
struct {
|
||||
struct JSFunctionBytecode *function_bytecode;
|
||||
JSVarRef **var_refs; /* legacy closure refs (to be removed) */
|
||||
JSValue outer_frame; /* JSFrame JSValue, lexical parent for closures */
|
||||
JSValue env_record; /* stone record, module environment */
|
||||
} func;
|
||||
@@ -1748,10 +1734,7 @@ typedef struct JSBoundFunction {
|
||||
} JSBoundFunction;
|
||||
|
||||
typedef struct JSProperty {
|
||||
union {
|
||||
JSValue value; /* JS_PROP_NORMAL */
|
||||
JSVarRef *var_ref; /* JS_PROP_VARREF */
|
||||
} u;
|
||||
JSValue value;
|
||||
} JSProperty;
|
||||
|
||||
#define JS_PROP_INITIAL_SIZE 2
|
||||
@@ -1810,8 +1793,6 @@ static __maybe_unused void JS_DumpValue (JSContext *ctx, const char *str, JSValu
|
||||
static void js_dump_value_write (void *opaque, const char *buf, size_t len);
|
||||
static JSValue js_function_apply (JSContext *ctx, JSValue this_val, int argc, JSValue *argv, int magic);
|
||||
static void js_regexp_finalizer (JSRuntime *rt, JSValue val);
|
||||
static void js_varref_object_finalizer (JSRuntime *rt, JSValue val);
|
||||
static void js_varref_object_gc_mark (JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func);
|
||||
static JSValue js_new_function (JSContext *ctx, JSFunctionKind kind);
|
||||
static void mark_function_children (JSRuntime *rt, JSFunction *func, JS_MarkFunc *mark_func);
|
||||
static void mark_function_children_decref (JSRuntime *rt, JSFunction *func);
|
||||
@@ -2102,7 +2083,6 @@ static JSClass const js_std_class_def[] = {
|
||||
{ "error", NULL, NULL }, /* JS_CLASS_ERROR */
|
||||
{ "regexp", js_regexp_finalizer, NULL }, /* JS_CLASS_REGEXP */
|
||||
{ "blob", NULL, NULL }, /* JS_CLASS_BLOB - registered separately */
|
||||
{ "varref", js_varref_object_finalizer, js_varref_object_gc_mark }, /* JS_CLASS_VAR_REF_OBJECT */
|
||||
};
|
||||
|
||||
static int init_class_range (JSRuntime *rt, JSClass const *tab, int start, int count) {
|
||||
@@ -3889,31 +3869,6 @@ JSValue JS_NewCFunction2 (JSContext *ctx, JSCFunction *func, const char *name, i
|
||||
|
||||
/* free_property is defined earlier as a stub since shapes are removed */
|
||||
|
||||
static void free_var_ref (JSRuntime *rt, JSVarRef *var_ref) {
|
||||
/* With copying GC, var_ref lifetime is managed by the GC.
|
||||
We still do bookkeeping for the var_ref_link list. */
|
||||
if (var_ref && !var_ref->is_detached) {
|
||||
list_del (&var_ref->var_ref_link);
|
||||
}
|
||||
/* The actual memory is reclaimed by the copying GC */
|
||||
}
|
||||
|
||||
/* Finalizer for JS_CLASS_VAR_REF_OBJECT - frees the stored var_ref */
|
||||
static void js_varref_object_finalizer (JSRuntime *rt, JSValue val) {
|
||||
JSVarRef *var_ref = JS_GetOpaque (val, JS_CLASS_VAR_REF_OBJECT);
|
||||
if (var_ref) {
|
||||
free_var_ref (rt, var_ref);
|
||||
}
|
||||
}
|
||||
|
||||
/* GC mark for JS_CLASS_VAR_REF_OBJECT - marks the value if detached */
|
||||
static void js_varref_object_gc_mark (JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func) {
|
||||
JSVarRef *var_ref = JS_GetOpaque (val, JS_CLASS_VAR_REF_OBJECT);
|
||||
if (var_ref && var_ref->is_detached) {
|
||||
JS_MarkValue (rt, var_ref->value, mark_func);
|
||||
}
|
||||
}
|
||||
|
||||
/* GC-safe array growth function.
|
||||
Takes JSValue* pointer to a GC-tracked location (like &argv[n]).
|
||||
Allocates new array, copies data, installs forward header at old location. */
|
||||
@@ -6796,7 +6751,6 @@ static JSValue js_closure2 (JSContext *ctx, JSValue func_obj, JSFunctionBytecode
|
||||
JSFunction *f;
|
||||
f = JS_VALUE_GET_FUNCTION (func_obj);
|
||||
f->u.func.function_bytecode = b;
|
||||
f->u.func.var_refs = NULL;
|
||||
|
||||
/* Set outer_frame to parent's JSFrame for the new closure model.
|
||||
This allows OP_get_up/OP_set_up to access captured variables via frame chain. */
|
||||
@@ -7479,61 +7433,43 @@ restart:
|
||||
}
|
||||
BREAK;
|
||||
|
||||
CASE (OP_check_var) : {
|
||||
/* Global object is immutable - linker should have resolved or removed this */
|
||||
/* Global variable opcodes - resolved by linker to get/set_global_slot */
|
||||
CASE (OP_check_var) :
|
||||
pc += 4;
|
||||
JS_ThrowInternalError (ctx, "OP_check_var: linker should have resolved this");
|
||||
goto exception;
|
||||
}
|
||||
BREAK;
|
||||
|
||||
CASE (OP_get_var_undef) : CASE (OP_get_var) : {
|
||||
/* Global object is immutable - linker should have resolved this */
|
||||
CASE (OP_get_var_undef) :
|
||||
CASE (OP_get_var) :
|
||||
pc += 4;
|
||||
JS_ThrowInternalError (ctx, "OP_get_var: linker should have resolved to get_global_slot");
|
||||
goto exception;
|
||||
}
|
||||
BREAK;
|
||||
|
||||
CASE (OP_put_var) : CASE (OP_put_var_init) : {
|
||||
/* Global object is immutable - linker should have resolved this */
|
||||
CASE (OP_put_var) :
|
||||
CASE (OP_put_var_init) :
|
||||
pc += 4;
|
||||
sp--;
|
||||
JS_ThrowInternalError (ctx, "OP_put_var: global object is immutable, linker should resolve");
|
||||
goto exception;
|
||||
}
|
||||
BREAK;
|
||||
|
||||
CASE (OP_put_var_strict) : {
|
||||
/* Global object is immutable - linker should have resolved this */
|
||||
CASE (OP_put_var_strict) :
|
||||
pc += 4;
|
||||
sp -= 2;
|
||||
JS_ThrowInternalError (ctx, "OP_put_var_strict: global object is immutable, linker should resolve");
|
||||
goto exception;
|
||||
}
|
||||
BREAK;
|
||||
|
||||
CASE (OP_check_define_var) : {
|
||||
/* Global object is immutable - this opcode should not be emitted */
|
||||
CASE (OP_define_var) :
|
||||
CASE (OP_check_define_var) :
|
||||
pc += 5;
|
||||
JS_ThrowInternalError (ctx, "OP_check_define_var: global object is immutable");
|
||||
JS_ThrowInternalError (ctx, "global object is immutable - cannot define variables at runtime");
|
||||
goto exception;
|
||||
}
|
||||
BREAK;
|
||||
CASE (OP_define_var) : {
|
||||
/* Global object is immutable - this opcode should not be emitted */
|
||||
pc += 5;
|
||||
JS_ThrowInternalError (ctx, "OP_define_var: global object is immutable");
|
||||
goto exception;
|
||||
}
|
||||
BREAK;
|
||||
CASE (OP_define_func) : {
|
||||
/* Global object is immutable - this opcode should not be emitted */
|
||||
CASE (OP_define_func) :
|
||||
pc += 5;
|
||||
sp--;
|
||||
JS_ThrowInternalError (ctx, "OP_define_func: global object is immutable");
|
||||
JS_ThrowInternalError (ctx, "global object is immutable - cannot define functions at runtime");
|
||||
goto exception;
|
||||
}
|
||||
BREAK;
|
||||
|
||||
CASE (OP_get_loc) : {
|
||||
@@ -7648,33 +7584,7 @@ restart:
|
||||
CASE (OP_set_arg3)
|
||||
: set_value (ctx, &arg_buf[3], sp[-1]);
|
||||
BREAK;
|
||||
/* Legacy var_ref opcodes - deprecated, replaced by OP_get_up/OP_set_up */
|
||||
CASE (OP_get_var_ref0) :
|
||||
CASE (OP_get_var_ref1) :
|
||||
CASE (OP_get_var_ref2) :
|
||||
CASE (OP_get_var_ref3) :
|
||||
CASE (OP_put_var_ref0) :
|
||||
CASE (OP_put_var_ref1) :
|
||||
CASE (OP_put_var_ref2) :
|
||||
CASE (OP_put_var_ref3) :
|
||||
CASE (OP_set_var_ref0) :
|
||||
CASE (OP_set_var_ref1) :
|
||||
CASE (OP_set_var_ref2) :
|
||||
CASE (OP_set_var_ref3) :
|
||||
JS_ThrowInternalError(ctx, "deprecated var_ref opcode (use OP_get_up/OP_set_up)");
|
||||
goto exception;
|
||||
BREAK;
|
||||
#endif
|
||||
CASE (OP_get_var_ref) :
|
||||
CASE (OP_put_var_ref) :
|
||||
CASE (OP_set_var_ref) :
|
||||
CASE (OP_get_var_ref_check) :
|
||||
CASE (OP_put_var_ref_check) :
|
||||
CASE (OP_put_var_ref_check_init) :
|
||||
pc += 2; /* skip the index */
|
||||
JS_ThrowInternalError(ctx, "deprecated var_ref opcode (use OP_get_up/OP_set_up)");
|
||||
goto exception;
|
||||
BREAK;
|
||||
CASE (OP_set_loc_uninitialized) : {
|
||||
int idx;
|
||||
idx = get_u16 (pc);
|
||||
@@ -7730,24 +7640,24 @@ restart:
|
||||
sp--;
|
||||
}
|
||||
BREAK;
|
||||
/* Legacy var_ref reference creation - deprecated, replaced by OP_get_up/OP_set_up */
|
||||
|
||||
/* Deprecated var_ref opcodes - should be resolved to get_up/set_up during scope resolution */
|
||||
CASE (OP_get_var_ref) :
|
||||
CASE (OP_put_var_ref) :
|
||||
CASE (OP_set_var_ref) :
|
||||
CASE (OP_get_var_ref_check) :
|
||||
CASE (OP_put_var_ref_check) :
|
||||
CASE (OP_put_var_ref_check_init) :
|
||||
pc += 2; /* skip the index */
|
||||
JS_ThrowInternalError(ctx, "deprecated var_ref opcode (use OP_get_up/OP_set_up)");
|
||||
goto exception;
|
||||
BREAK;
|
||||
|
||||
CASE (OP_close_loc) :
|
||||
pc += 2;
|
||||
JS_ThrowInternalError(ctx, "deprecated close_loc opcode");
|
||||
goto exception;
|
||||
BREAK;
|
||||
CASE (OP_make_loc_ref) :
|
||||
CASE (OP_make_arg_ref) :
|
||||
CASE (OP_make_var_ref_ref) :
|
||||
pc += 6;
|
||||
JS_ThrowInternalError(ctx, "deprecated make_*_ref opcode");
|
||||
goto exception;
|
||||
BREAK;
|
||||
CASE (OP_make_var_ref) :
|
||||
pc += 4;
|
||||
JS_ThrowInternalError(ctx, "deprecated make_var_ref opcode");
|
||||
goto exception;
|
||||
BREAK;
|
||||
|
||||
CASE (OP_goto) : pc += (int32_t)get_u32 (pc);
|
||||
if (unlikely (js_poll_interrupts (ctx))) goto exception;
|
||||
@@ -8110,20 +8020,6 @@ restart:
|
||||
|
||||
sf->cur_pc = pc;
|
||||
|
||||
/* Check if this is a var ref object */
|
||||
if (JS_VALUE_GET_TAG (ref_obj) == JS_TAG_PTR) {
|
||||
JSRecord *p = JS_VALUE_GET_OBJ (ref_obj);
|
||||
if (REC_GET_CLASS_ID(p) == JS_CLASS_VAR_REF_OBJECT) {
|
||||
JSVarRef *var_ref = (JSVarRef *)REC_GET_OPAQUE(p);
|
||||
if (var_ref) {
|
||||
val = var_ref->is_detached ? var_ref->value : *var_ref->pvalue;
|
||||
*sp++ = val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Fall through to standard property lookup */
|
||||
if (JS_IsText (key)) { key = js_key_from_string (ctx, key); }
|
||||
if (unlikely (JS_IsNull (ref_obj))) {
|
||||
JS_ThrowReferenceErrorNotDefined (ctx, key);
|
||||
@@ -8166,22 +8062,6 @@ restart:
|
||||
|
||||
sf->cur_pc = pc;
|
||||
|
||||
/* Check if this is a var ref object */
|
||||
if (JS_VALUE_GET_TAG (ref_obj) == JS_TAG_PTR) {
|
||||
JSRecord *p = JS_VALUE_GET_OBJ (ref_obj);
|
||||
if (REC_GET_CLASS_ID(p) == JS_CLASS_VAR_REF_OBJECT) {
|
||||
JSVarRef *var_ref = (JSVarRef *)REC_GET_OPAQUE(p);
|
||||
if (var_ref) {
|
||||
JSValue *pval = var_ref->is_detached ? &var_ref->value
|
||||
: var_ref->pvalue;
|
||||
set_value (ctx, pval, val);
|
||||
sp -= 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Fall through to standard property lookup */
|
||||
if (JS_IsText (key)) { key = js_key_from_string (ctx, key); }
|
||||
if (unlikely (JS_IsNull (ref_obj))) {
|
||||
JS_ThrowReferenceErrorNotDefined (ctx, key);
|
||||
@@ -8747,12 +8627,11 @@ restart:
|
||||
if (js_operator_delete (ctx, sp)) goto exception;
|
||||
sp--;
|
||||
BREAK;
|
||||
CASE (OP_delete_var) : {
|
||||
/* Global object is immutable - cannot delete globals */
|
||||
|
||||
CASE (OP_delete_var) :
|
||||
pc += 4;
|
||||
JS_ThrowInternalError (ctx, "OP_delete_var: global object is immutable");
|
||||
goto exception;
|
||||
}
|
||||
BREAK;
|
||||
|
||||
CASE (OP_to_propkey) : switch (JS_VALUE_GET_TAG (sp[-1])) {
|
||||
@@ -8767,6 +8646,21 @@ restart:
|
||||
break;
|
||||
}
|
||||
BREAK;
|
||||
|
||||
/* Deprecated make_*_ref opcodes - no longer needed with outer_frame model */
|
||||
CASE (OP_make_loc_ref) :
|
||||
CASE (OP_make_arg_ref) :
|
||||
CASE (OP_make_var_ref_ref) :
|
||||
pc += 6;
|
||||
JS_ThrowInternalError(ctx, "deprecated make_*_ref opcode");
|
||||
goto exception;
|
||||
BREAK;
|
||||
CASE (OP_make_var_ref) :
|
||||
pc += 4;
|
||||
JS_ThrowInternalError(ctx, "deprecated make_var_ref opcode");
|
||||
goto exception;
|
||||
BREAK;
|
||||
|
||||
CASE (OP_template_concat) : {
|
||||
int n, i;
|
||||
JSValue out;
|
||||
@@ -14652,17 +14546,6 @@ static void dump_byte_code (JSContext *ctx, int pass, const uint8_t *tab, int le
|
||||
printf (" %d: ", idx);
|
||||
if (idx < arg_count) { print_atom (ctx, args[idx].var_name); }
|
||||
break;
|
||||
case OP_FMT_none_var_ref:
|
||||
idx = (op - OP_get_var_ref0) % 4;
|
||||
goto has_var_ref;
|
||||
case OP_FMT_var_ref:
|
||||
idx = get_u16 (tab + pos);
|
||||
has_var_ref:
|
||||
printf (" %d: ", idx);
|
||||
if (idx < closure_var_count) {
|
||||
print_atom (ctx, closure_var[idx].var_name);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -15693,8 +15576,7 @@ static BOOL code_match (CodeContext *s, int pos, ...) {
|
||||
case OP_FMT_u16:
|
||||
case OP_FMT_npop:
|
||||
case OP_FMT_loc:
|
||||
case OP_FMT_arg:
|
||||
case OP_FMT_var_ref: {
|
||||
case OP_FMT_arg: {
|
||||
int idx = get_u16 (tab + pos);
|
||||
int arg = va_arg (ap, int);
|
||||
if (arg == -1) {
|
||||
@@ -16442,15 +16324,6 @@ static void put_short_code (DynBuf *bc_out, int op, int idx) {
|
||||
case OP_set_arg:
|
||||
dbuf_putc (bc_out, OP_set_arg0 + idx);
|
||||
return;
|
||||
case OP_get_var_ref:
|
||||
dbuf_putc (bc_out, OP_get_var_ref0 + idx);
|
||||
return;
|
||||
case OP_put_var_ref:
|
||||
dbuf_putc (bc_out, OP_put_var_ref0 + idx);
|
||||
return;
|
||||
case OP_set_var_ref:
|
||||
dbuf_putc (bc_out, OP_set_var_ref0 + idx);
|
||||
return;
|
||||
case OP_call:
|
||||
dbuf_putc (bc_out, OP_call0 + idx);
|
||||
return;
|
||||
@@ -18101,7 +17974,7 @@ static void js_parse_init (JSContext *ctx, JSParseState *s, const char *input, s
|
||||
s->get_line_col_cache.col_num = 0;
|
||||
}
|
||||
|
||||
static JSValue JS_EvalFunctionInternal (JSContext *ctx, JSValue fun_obj, JSValue this_obj, JSVarRef **var_refs, JSStackFrame *sf) {
|
||||
static JSValue JS_EvalFunctionInternal (JSContext *ctx, JSValue fun_obj, JSValue this_obj, JSStackFrame *sf) {
|
||||
JSValue ret_val;
|
||||
uint32_t tag;
|
||||
|
||||
@@ -18117,7 +17990,7 @@ static JSValue JS_EvalFunctionInternal (JSContext *ctx, JSValue fun_obj, JSValue
|
||||
}
|
||||
|
||||
JSValue JS_EvalFunction (JSContext *ctx, JSValue fun_obj) {
|
||||
return JS_EvalFunctionInternal (ctx, fun_obj, ctx->global_obj, NULL, NULL);
|
||||
return JS_EvalFunctionInternal (ctx, fun_obj, ctx->global_obj, NULL);
|
||||
}
|
||||
|
||||
/* Link compiled bytecode to context - resolves global references.
|
||||
@@ -18145,7 +18018,6 @@ static JSValue __JS_EvalInternal (JSContext *ctx, JSValue this_obj, const char *
|
||||
int err, js_mode, eval_type;
|
||||
JSValue fun_obj, ret_val;
|
||||
JSStackFrame *sf;
|
||||
JSVarRef **var_refs;
|
||||
JSFunctionBytecode *b;
|
||||
JSFunctionDef *fd;
|
||||
|
||||
@@ -18160,12 +18032,10 @@ static JSValue __JS_EvalInternal (JSContext *ctx, JSValue this_obj, const char *
|
||||
fn = JS_VALUE_GET_FUNCTION (sf->cur_func);
|
||||
assert (fn->kind == JS_FUNC_KIND_BYTECODE);
|
||||
b = fn->u.func.function_bytecode;
|
||||
var_refs = fn->u.func.var_refs;
|
||||
js_mode = b->js_mode;
|
||||
} else {
|
||||
sf = NULL;
|
||||
b = NULL;
|
||||
var_refs = NULL;
|
||||
js_mode = 0;
|
||||
}
|
||||
fd = js_new_function_def (ctx, NULL, TRUE, FALSE, filename, s->buf_start, &s->get_line_col_cache);
|
||||
@@ -18200,7 +18070,7 @@ static JSValue __JS_EvalInternal (JSContext *ctx, JSValue this_obj, const char *
|
||||
if (flags & JS_EVAL_FLAG_COMPILE_ONLY) {
|
||||
ret_val = fun_obj;
|
||||
} else {
|
||||
ret_val = JS_EvalFunctionInternal (ctx, fun_obj, this_obj, var_refs, sf);
|
||||
ret_val = JS_EvalFunctionInternal (ctx, fun_obj, this_obj, sf);
|
||||
}
|
||||
return ret_val;
|
||||
fail1:
|
||||
@@ -18507,7 +18377,6 @@ static void bc_byte_swap (uint8_t *bc_buf, int bc_len) {
|
||||
case OP_FMT_npop:
|
||||
case OP_FMT_loc:
|
||||
case OP_FMT_arg:
|
||||
case OP_FMT_var_ref:
|
||||
put_u16 (bc_buf + pos + 1, bswap16 (get_u16 (bc_buf + pos + 1)));
|
||||
break;
|
||||
case OP_FMT_i32:
|
||||
@@ -23147,12 +23016,6 @@ static void dump_bytecode_opcodes (JSContext *ctx, JSFunctionBytecode *b) {
|
||||
case OP_FMT_arg:
|
||||
printf (" arg%d", get_u16 (tab + pos));
|
||||
break;
|
||||
case OP_FMT_none_var_ref:
|
||||
printf (" var_ref%d", (op - OP_get_var_ref0) % 4);
|
||||
break;
|
||||
case OP_FMT_var_ref:
|
||||
printf (" var_ref%d", get_u16 (tab + pos));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -26686,56 +26549,6 @@ JSValue js_debugger_fn_bytecode (JSContext *ctx, JSValue fn) {
|
||||
idx);
|
||||
}
|
||||
} break;
|
||||
case OP_FMT_none_var_ref: {
|
||||
int idx = (op - OP_get_var_ref0) % 4;
|
||||
if (idx < b->closure_var_count) {
|
||||
const char *var_name
|
||||
= JS_ToCString (ctx, b->closure_var[idx].var_name);
|
||||
if (var_name) {
|
||||
snprintf (opcode_str + strlen (opcode_str),
|
||||
sizeof (opcode_str) - strlen (opcode_str),
|
||||
" %d: %s",
|
||||
idx,
|
||||
var_name);
|
||||
JS_FreeCString (ctx, var_name);
|
||||
} else {
|
||||
snprintf (opcode_str + strlen (opcode_str),
|
||||
sizeof (opcode_str) - strlen (opcode_str),
|
||||
" %d",
|
||||
idx);
|
||||
}
|
||||
} else {
|
||||
snprintf (opcode_str + strlen (opcode_str),
|
||||
sizeof (opcode_str) - strlen (opcode_str),
|
||||
" %d",
|
||||
idx);
|
||||
}
|
||||
} break;
|
||||
case OP_FMT_var_ref: {
|
||||
int idx = get_u16 (tab + arg_pos);
|
||||
if (idx < b->closure_var_count) {
|
||||
const char *var_name
|
||||
= JS_ToCString (ctx, b->closure_var[idx].var_name);
|
||||
if (var_name) {
|
||||
snprintf (opcode_str + strlen (opcode_str),
|
||||
sizeof (opcode_str) - strlen (opcode_str),
|
||||
" %u: %s",
|
||||
idx,
|
||||
var_name);
|
||||
JS_FreeCString (ctx, var_name);
|
||||
} else {
|
||||
snprintf (opcode_str + strlen (opcode_str),
|
||||
sizeof (opcode_str) - strlen (opcode_str),
|
||||
" %u",
|
||||
idx);
|
||||
}
|
||||
} else {
|
||||
snprintf (opcode_str + strlen (opcode_str),
|
||||
sizeof (opcode_str) - strlen (opcode_str),
|
||||
" %u",
|
||||
idx);
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -26800,55 +26613,14 @@ done:
|
||||
}
|
||||
|
||||
void js_debugger_set_closure_variable (JSContext *ctx, JSValue fn, JSValue var_name, JSValue val) {
|
||||
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) return;
|
||||
|
||||
for (uint32_t i = 0; i < b->closure_var_count; i++) {
|
||||
JSClosureVar *cvar = b->closure_var + i;
|
||||
const char *cvar_name = JS_ToCString (ctx, cvar->var_name);
|
||||
if (!cvar_name) continue;
|
||||
|
||||
if (strcmp (name_str, cvar_name) == 0) {
|
||||
JS_FreeCString (ctx, cvar_name);
|
||||
JSVarRef *var_ref = NULL;
|
||||
if (f->u.func.var_refs) var_ref = f->u.func.var_refs[i];
|
||||
if (var_ref && var_ref->pvalue) {
|
||||
*var_ref->pvalue = val;
|
||||
}
|
||||
break;
|
||||
}
|
||||
JS_FreeCString (ctx, cvar_name);
|
||||
}
|
||||
|
||||
JS_FreeCString (ctx, name_str);
|
||||
/* TODO: Reimplement using outer_frame mechanism if debugging is needed */
|
||||
(void)ctx; (void)fn; (void)var_name; (void)val;
|
||||
}
|
||||
|
||||
JSValue js_debugger_closure_variables (JSContext *ctx, JSValue fn) {
|
||||
JSValue ret = JS_NewObject (ctx);
|
||||
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++) {
|
||||
JSClosureVar *cvar = b->closure_var + i;
|
||||
JSValue var_val;
|
||||
JSVarRef *var_ref = NULL;
|
||||
if (f->u.func.var_refs) var_ref = f->u.func.var_refs[i];
|
||||
if (!var_ref || !var_ref->pvalue) continue;
|
||||
var_val = *var_ref->pvalue;
|
||||
|
||||
if (JS_IsUninitialized (var_val)) continue;
|
||||
|
||||
JS_SetProperty (ctx, ret, cvar->var_name, var_val);
|
||||
}
|
||||
|
||||
done:
|
||||
return ret;
|
||||
/* TODO: Reimplement using outer_frame mechanism if debugging is needed */
|
||||
(void)fn;
|
||||
return JS_NewObject (ctx);
|
||||
}
|
||||
|
||||
void *js_debugger_val_address (JSContext *ctx, JSValue val) {
|
||||
|
||||
Reference in New Issue
Block a user