go
This commit is contained in:
@@ -32,6 +32,7 @@ DEF(true, "true")
|
||||
DEF(if, "if")
|
||||
DEF(else, "else")
|
||||
DEF(return, "return")
|
||||
DEF(go, "go")
|
||||
DEF(var, "var")
|
||||
DEF(def, "def")
|
||||
DEF(this, "this")
|
||||
|
||||
133
source/quickjs.c
133
source/quickjs.c
@@ -125,8 +125,10 @@ typedef struct JSPropSite {
|
||||
uint64_t hit_count; /* how many times this prop site was executed */
|
||||
} JSPropSite;
|
||||
|
||||
/* Forward declare JSFunctionBytecode for JSProfileSample */
|
||||
/* Forward declarations */
|
||||
typedef struct JSFunctionBytecode JSFunctionBytecode;
|
||||
typedef struct JSVarRef JSVarRef;
|
||||
typedef struct VMFrame VMFrame;
|
||||
|
||||
/* Sampling profiler sample */
|
||||
typedef struct JSProfileSample {
|
||||
@@ -262,6 +264,7 @@ struct JSRuntime {
|
||||
BOOL in_out_of_memory : 8;
|
||||
|
||||
struct JSStackFrame *current_stack_frame;
|
||||
struct VMFrame *current_vm_frame; /* for trampoline VM */
|
||||
|
||||
JSInterruptHandler *interrupt_handler;
|
||||
void *interrupt_opaque;
|
||||
@@ -306,6 +309,26 @@ typedef struct JSStackFrame {
|
||||
int js_mode; /* not supported for C functions */
|
||||
} JSStackFrame;
|
||||
|
||||
/* Heap-allocated VM frame for trampoline execution */
|
||||
struct VMFrame {
|
||||
struct VMFrame *prev_frame;
|
||||
struct JSFunctionBytecode *b; /* current function bytecode */
|
||||
JSContext *ctx; /* execution context / realm */
|
||||
const uint8_t *pc; /* program counter */
|
||||
JSValue *sp; /* current stack pointer */
|
||||
JSValue *stack_base; /* base of operand stack (points into heap) */
|
||||
JSValue *arg_buf; /* arguments (points into stack_base region) */
|
||||
JSValue *var_buf; /* local variables (points into stack_base region) */
|
||||
JSValue cur_func; /* current function object */
|
||||
JSValue this_obj; /* this binding */
|
||||
JSValue new_target; /* new.target 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 of stack_base allocation */
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
JS_GC_OBJ_TYPE_JS_OBJECT,
|
||||
JS_GC_OBJ_TYPE_FUNCTION_BYTECODE,
|
||||
@@ -12700,6 +12723,113 @@ static void profile_record_prop_site(JSRuntime *rt, JSFunctionBytecode *b, uint3
|
||||
}
|
||||
#endif
|
||||
|
||||
/* VM frame management for trampoline */
|
||||
static struct VMFrame *vm_push_frame(JSRuntime *rt, JSContext *ctx,
|
||||
JSValueConst func_obj, JSValueConst this_obj,
|
||||
JSValueConst new_target,
|
||||
int argc, JSValue *argv, int flags)
|
||||
{
|
||||
JSObject *p;
|
||||
JSFunctionBytecode *b;
|
||||
struct VMFrame *frame;
|
||||
int total_slots, i, arg_allocated_size;
|
||||
|
||||
p = JS_VALUE_GET_OBJ(func_obj);
|
||||
b = p->u.func.function_bytecode;
|
||||
|
||||
frame = js_malloc(ctx, sizeof(struct VMFrame));
|
||||
if (!frame)
|
||||
return NULL;
|
||||
|
||||
/* Calculate space needed: args + vars + 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;
|
||||
|
||||
/* Allocate VM stack space */
|
||||
frame->stack_base = js_mallocz(ctx, sizeof(JSValue) * total_slots);
|
||||
if (!frame->stack_base) {
|
||||
js_free(ctx, frame);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
frame->stack_size_allocated = total_slots;
|
||||
|
||||
/* Set up pointers into stack */
|
||||
if (arg_allocated_size) {
|
||||
frame->arg_buf = frame->stack_base;
|
||||
for (i = 0; i < min_int(argc, b->arg_count); i++)
|
||||
frame->arg_buf[i] = JS_DupValue(ctx, argv[i]);
|
||||
for (; i < b->arg_count; i++)
|
||||
frame->arg_buf[i] = JS_NULL;
|
||||
frame->arg_count = b->arg_count;
|
||||
} else {
|
||||
frame->arg_buf = argv;
|
||||
frame->arg_count = argc;
|
||||
}
|
||||
|
||||
frame->var_buf = frame->stack_base + arg_allocated_size;
|
||||
for (i = 0; i < b->var_count; i++)
|
||||
frame->var_buf[i] = JS_NULL;
|
||||
|
||||
frame->sp = frame->var_buf + b->var_count;
|
||||
|
||||
/* Initialize frame metadata */
|
||||
frame->cur_func = JS_DupValue(ctx, func_obj);
|
||||
frame->this_obj = JS_DupValue(ctx, this_obj);
|
||||
frame->new_target = JS_DupValue(ctx, new_target);
|
||||
frame->b = b;
|
||||
frame->ctx = b->realm;
|
||||
frame->pc = b->byte_code_buf;
|
||||
frame->js_mode = b->js_mode;
|
||||
frame->var_refs = p->u.func.var_refs;
|
||||
init_list_head(&frame->var_ref_list);
|
||||
|
||||
/* Link to previous frame */
|
||||
frame->prev_frame = rt->current_vm_frame;
|
||||
rt->current_vm_frame = frame;
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
static void vm_pop_frame(JSRuntime *rt, struct VMFrame *frame)
|
||||
{
|
||||
int i;
|
||||
struct list_head *el, *el1;
|
||||
JSContext *ctx = frame->ctx;
|
||||
|
||||
/* Close variable references */
|
||||
if (!list_empty(&frame->var_ref_list)) {
|
||||
list_for_each_safe(el, el1, &frame->var_ref_list) {
|
||||
JSVarRef *var_ref = list_entry(el, 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 stack */
|
||||
for (i = 0; i < frame->stack_size_allocated; i++)
|
||||
JS_FreeValue(ctx, frame->stack_base[i]);
|
||||
|
||||
/* Free frame values */
|
||||
JS_FreeValue(ctx, frame->cur_func);
|
||||
JS_FreeValue(ctx, frame->this_obj);
|
||||
JS_FreeValue(ctx, frame->new_target);
|
||||
|
||||
/* Free allocations */
|
||||
js_free(ctx, frame->stack_base);
|
||||
|
||||
/* Update runtime pointer */
|
||||
rt->current_vm_frame = frame->prev_frame;
|
||||
|
||||
js_free(ctx, frame);
|
||||
}
|
||||
|
||||
static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||
JSValueConst this_obj, JSValueConst new_target,
|
||||
int argc, JSValue *argv, int flags)
|
||||
@@ -15349,6 +15479,7 @@ enum {
|
||||
TOK_IF,
|
||||
TOK_ELSE,
|
||||
TOK_RETURN,
|
||||
TOK_GO,
|
||||
TOK_VAR,
|
||||
TOK_DEF,
|
||||
TOK_THIS,
|
||||
|
||||
Reference in New Issue
Block a user