go
This commit is contained in:
@@ -32,6 +32,7 @@ DEF(true, "true")
|
|||||||
DEF(if, "if")
|
DEF(if, "if")
|
||||||
DEF(else, "else")
|
DEF(else, "else")
|
||||||
DEF(return, "return")
|
DEF(return, "return")
|
||||||
|
DEF(go, "go")
|
||||||
DEF(var, "var")
|
DEF(var, "var")
|
||||||
DEF(def, "def")
|
DEF(def, "def")
|
||||||
DEF(this, "this")
|
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 */
|
uint64_t hit_count; /* how many times this prop site was executed */
|
||||||
} JSPropSite;
|
} JSPropSite;
|
||||||
|
|
||||||
/* Forward declare JSFunctionBytecode for JSProfileSample */
|
/* Forward declarations */
|
||||||
typedef struct JSFunctionBytecode JSFunctionBytecode;
|
typedef struct JSFunctionBytecode JSFunctionBytecode;
|
||||||
|
typedef struct JSVarRef JSVarRef;
|
||||||
|
typedef struct VMFrame VMFrame;
|
||||||
|
|
||||||
/* Sampling profiler sample */
|
/* Sampling profiler sample */
|
||||||
typedef struct JSProfileSample {
|
typedef struct JSProfileSample {
|
||||||
@@ -262,6 +264,7 @@ struct JSRuntime {
|
|||||||
BOOL in_out_of_memory : 8;
|
BOOL in_out_of_memory : 8;
|
||||||
|
|
||||||
struct JSStackFrame *current_stack_frame;
|
struct JSStackFrame *current_stack_frame;
|
||||||
|
struct VMFrame *current_vm_frame; /* for trampoline VM */
|
||||||
|
|
||||||
JSInterruptHandler *interrupt_handler;
|
JSInterruptHandler *interrupt_handler;
|
||||||
void *interrupt_opaque;
|
void *interrupt_opaque;
|
||||||
@@ -306,6 +309,26 @@ typedef struct JSStackFrame {
|
|||||||
int js_mode; /* not supported for C functions */
|
int js_mode; /* not supported for C functions */
|
||||||
} JSStackFrame;
|
} 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 {
|
typedef enum {
|
||||||
JS_GC_OBJ_TYPE_JS_OBJECT,
|
JS_GC_OBJ_TYPE_JS_OBJECT,
|
||||||
JS_GC_OBJ_TYPE_FUNCTION_BYTECODE,
|
JS_GC_OBJ_TYPE_FUNCTION_BYTECODE,
|
||||||
@@ -12700,6 +12723,113 @@ static void profile_record_prop_site(JSRuntime *rt, JSFunctionBytecode *b, uint3
|
|||||||
}
|
}
|
||||||
#endif
|
#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,
|
static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||||
JSValueConst this_obj, JSValueConst new_target,
|
JSValueConst this_obj, JSValueConst new_target,
|
||||||
int argc, JSValue *argv, int flags)
|
int argc, JSValue *argv, int flags)
|
||||||
@@ -15349,6 +15479,7 @@ enum {
|
|||||||
TOK_IF,
|
TOK_IF,
|
||||||
TOK_ELSE,
|
TOK_ELSE,
|
||||||
TOK_RETURN,
|
TOK_RETURN,
|
||||||
|
TOK_GO,
|
||||||
TOK_VAR,
|
TOK_VAR,
|
||||||
TOK_DEF,
|
TOK_DEF,
|
||||||
TOK_THIS,
|
TOK_THIS,
|
||||||
|
|||||||
Reference in New Issue
Block a user