kill actor when abusive
This commit is contained in:
@@ -678,14 +678,14 @@ static JSValue reg_vm_binop(JSContext *ctx, int op, JSValue a, JSValue b) {
|
||||
return JS_ThrowTypeError(ctx, "type mismatch in binary operation");
|
||||
}
|
||||
|
||||
/* Check for interrupt */
|
||||
/* Check for interrupt — returns: 0 = continue, -1 = hard kill, 1 = suspend */
|
||||
int reg_vm_check_interrupt(JSContext *ctx) {
|
||||
if (--ctx->interrupt_counter <= 0) {
|
||||
ctx->interrupt_counter = JS_INTERRUPT_COUNTER_INIT;
|
||||
if (ctx->interrupt_handler) {
|
||||
if (ctx->interrupt_handler(ctx->rt, ctx->interrupt_opaque)) {
|
||||
return -1;
|
||||
}
|
||||
int r = ctx->interrupt_handler(ctx->rt, ctx->interrupt_opaque);
|
||||
if (r < 0) return -1; /* hard kill */
|
||||
if (r > 0) return 1; /* suspend request */
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@@ -731,6 +731,31 @@ void __asan_on_error(void) {
|
||||
JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
||||
JSValue this_obj, int argc, JSValue *argv,
|
||||
JSValue env, JSValue outer_frame) {
|
||||
JSGCRef frame_ref;
|
||||
JSFrameRegister *frame;
|
||||
uint32_t pc;
|
||||
JSValue result;
|
||||
|
||||
/* Resume path: if VM was suspended, restore state and jump into dispatch */
|
||||
if (ctx->suspended) {
|
||||
ctx->suspended = 0;
|
||||
JS_AddGCRef(ctx, &frame_ref);
|
||||
frame_ref.val = ctx->suspended_frame_ref.val;
|
||||
ctx->suspended_frame_ref.val = JS_NULL;
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
JSFunction *fn = JS_VALUE_GET_FUNCTION(frame->function);
|
||||
code = fn->u.reg.code;
|
||||
env = fn->u.reg.env_record;
|
||||
pc = ctx->suspended_pc;
|
||||
result = JS_NULL;
|
||||
#ifdef HAVE_ASAN
|
||||
__asan_js_ctx = ctx;
|
||||
#endif
|
||||
goto vm_dispatch;
|
||||
}
|
||||
|
||||
{
|
||||
/* Normal path: set up a new call */
|
||||
/* Protect env and outer_frame from GC — alloc_frame_register can trigger
|
||||
collection which moves heap objects, invalidating stack-local copies */
|
||||
JSGCRef env_gc, of_gc;
|
||||
@@ -752,7 +777,7 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
||||
}
|
||||
|
||||
/* Allocate initial frame */
|
||||
JSFrameRegister *frame = alloc_frame_register(ctx, code->nr_slots);
|
||||
frame = alloc_frame_register(ctx, code->nr_slots);
|
||||
if (!frame) {
|
||||
for (int i = nargs_copy - 1; i >= 0; i--) JS_PopGCRef(ctx, &arg_gcs[i]);
|
||||
JS_PopGCRef(ctx, &this_gc);
|
||||
@@ -762,7 +787,6 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
||||
}
|
||||
|
||||
/* Protect frame from GC */
|
||||
JSGCRef frame_ref;
|
||||
JS_AddGCRef(ctx, &frame_ref);
|
||||
frame_ref.val = JS_MKPTR(frame);
|
||||
#ifdef HAVE_ASAN
|
||||
@@ -786,9 +810,11 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
||||
JS_PopGCRef(ctx, &of_gc);
|
||||
JS_PopGCRef(ctx, &env_gc);
|
||||
|
||||
uint32_t pc = code->entry_point;
|
||||
JSValue result = JS_NULL;
|
||||
pc = code->entry_point;
|
||||
result = JS_NULL;
|
||||
} /* end normal path block */
|
||||
|
||||
vm_dispatch:
|
||||
/* Execution loop — 32-bit instruction dispatch */
|
||||
for (;;) {
|
||||
#ifndef NDEBUG
|
||||
@@ -1379,9 +1405,13 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
||||
VM_CASE(MACH_JMP): {
|
||||
int offset = MACH_GET_sJ(instr);
|
||||
pc = (uint32_t)((int32_t)pc + offset);
|
||||
if (offset < 0 && reg_vm_check_interrupt(ctx)) {
|
||||
result = JS_ThrowInternalError(ctx, "interrupted");
|
||||
goto done;
|
||||
if (offset < 0) {
|
||||
int irc = reg_vm_check_interrupt(ctx);
|
||||
if (irc < 0) {
|
||||
result = JS_ThrowInternalError(ctx, "interrupted");
|
||||
goto done;
|
||||
}
|
||||
if (irc > 0) goto suspend;
|
||||
}
|
||||
VM_BREAK();
|
||||
}
|
||||
@@ -1395,9 +1425,13 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
||||
if (cond) {
|
||||
int offset = MACH_GET_sBx(instr);
|
||||
pc = (uint32_t)((int32_t)pc + offset);
|
||||
if (offset < 0 && reg_vm_check_interrupt(ctx)) {
|
||||
result = JS_ThrowInternalError(ctx, "interrupted");
|
||||
goto done;
|
||||
if (offset < 0) {
|
||||
int irc = reg_vm_check_interrupt(ctx);
|
||||
if (irc < 0) {
|
||||
result = JS_ThrowInternalError(ctx, "interrupted");
|
||||
goto done;
|
||||
}
|
||||
if (irc > 0) goto suspend;
|
||||
}
|
||||
}
|
||||
VM_BREAK();
|
||||
@@ -1412,9 +1446,13 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
||||
if (!cond) {
|
||||
int offset = MACH_GET_sBx(instr);
|
||||
pc = (uint32_t)((int32_t)pc + offset);
|
||||
if (offset < 0 && reg_vm_check_interrupt(ctx)) {
|
||||
result = JS_ThrowInternalError(ctx, "interrupted");
|
||||
goto done;
|
||||
if (offset < 0) {
|
||||
int irc = reg_vm_check_interrupt(ctx);
|
||||
if (irc < 0) {
|
||||
result = JS_ThrowInternalError(ctx, "interrupted");
|
||||
goto done;
|
||||
}
|
||||
if (irc > 0) goto suspend;
|
||||
}
|
||||
}
|
||||
VM_BREAK();
|
||||
@@ -1927,11 +1965,13 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
||||
/* C or bytecode function: args already in fr->slots (GC-protected via frame chain) */
|
||||
ctx->reg_current_frame = frame_ref.val;
|
||||
ctx->current_register_pc = pc > 0 ? pc - 1 : 0;
|
||||
ctx->vm_call_depth++;
|
||||
JSValue ret;
|
||||
if (fn->kind == JS_FUNC_KIND_C)
|
||||
ret = js_call_c_function(ctx, fn_val, fr->slots[0], c_argc, &fr->slots[1]);
|
||||
else
|
||||
ret = JS_CallInternal(ctx, fn_val, fr->slots[0], c_argc, &fr->slots[1], 0);
|
||||
ctx->vm_call_depth--;
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
ctx->reg_current_frame = JS_NULL;
|
||||
if (JS_IsException(ret)) goto disrupt;
|
||||
@@ -2010,11 +2050,13 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
||||
/* C/bytecode function: call it, then return result to our caller */
|
||||
ctx->reg_current_frame = frame_ref.val;
|
||||
ctx->current_register_pc = pc > 0 ? pc - 1 : 0;
|
||||
ctx->vm_call_depth++;
|
||||
JSValue ret;
|
||||
if (fn->kind == JS_FUNC_KIND_C)
|
||||
ret = js_call_c_function(ctx, fn_val, fr->slots[0], c_argc, &fr->slots[1]);
|
||||
else
|
||||
ret = JS_CallInternal(ctx, fn_val, fr->slots[0], c_argc, &fr->slots[1], 0);
|
||||
ctx->vm_call_depth--;
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
ctx->reg_current_frame = JS_NULL;
|
||||
if (JS_IsException(ret)) goto disrupt;
|
||||
@@ -2144,6 +2186,17 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
||||
}
|
||||
}
|
||||
|
||||
suspend:
|
||||
ctx->suspended = 1;
|
||||
ctx->suspended_pc = pc;
|
||||
ctx->suspended_frame_ref.val = frame_ref.val;
|
||||
result = JS_SUSPENDED;
|
||||
JS_DeleteGCRef(ctx, &frame_ref);
|
||||
#ifdef HAVE_ASAN
|
||||
__asan_js_ctx = NULL;
|
||||
#endif
|
||||
return result;
|
||||
|
||||
done:
|
||||
#ifdef HAVE_ASAN
|
||||
__asan_js_ctx = NULL;
|
||||
@@ -2157,6 +2210,13 @@ done:
|
||||
return result;
|
||||
}
|
||||
|
||||
JSValue JS_ResumeRegisterVM(JSContext *ctx) {
|
||||
if (!ctx->suspended)
|
||||
return JS_ThrowInternalError(ctx, "no suspended VM to resume");
|
||||
/* ctx->suspended is set; JS_CallRegisterVM will take the resume path */
|
||||
return JS_CallRegisterVM(ctx, NULL, JS_NULL, 0, NULL, JS_NULL, JS_NULL);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
MCODE Lowering — mcode JSON IR → MachInstr32
|
||||
============================================================ */
|
||||
|
||||
Reference in New Issue
Block a user