|
|
|
|
@@ -373,31 +373,11 @@ struct JSRuntime {
|
|
|
|
|
/* Buddy allocator for actor memory blocks */
|
|
|
|
|
BuddyAllocator buddy;
|
|
|
|
|
|
|
|
|
|
int class_count; /* size of class_array */
|
|
|
|
|
JSClass *class_array;
|
|
|
|
|
|
|
|
|
|
/* see JS_SetStripInfo() */
|
|
|
|
|
uint8_t strip_flags;
|
|
|
|
|
|
|
|
|
|
/* Stack overflow protection */
|
|
|
|
|
size_t stack_size;
|
|
|
|
|
const uint8_t *stack_top;
|
|
|
|
|
const uint8_t *stack_limit;
|
|
|
|
|
|
|
|
|
|
/* Current exception (for error propagation) */
|
|
|
|
|
JSValue current_exception;
|
|
|
|
|
struct JSStackFrame *current_stack_frame;
|
|
|
|
|
|
|
|
|
|
/* User data */
|
|
|
|
|
void *user_opaque;
|
|
|
|
|
|
|
|
|
|
/* Interrupt handler for checking execution limits */
|
|
|
|
|
JSInterruptHandler *interrupt_handler;
|
|
|
|
|
void *interrupt_opaque;
|
|
|
|
|
|
|
|
|
|
/* Register VM frame tracking for stack traces */
|
|
|
|
|
void *current_register_frame; /* JSFrameRegister* at exception time */
|
|
|
|
|
uint32_t current_register_pc; /* PC at exception time */
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct JSClass {
|
|
|
|
|
@@ -1052,6 +1032,8 @@ struct JSContext {
|
|
|
|
|
JSGCRef *top_gc_ref; /* used to reference temporary GC roots (stack top) */
|
|
|
|
|
JSGCRef *last_gc_ref; /* used to reference temporary GC roots (list) */
|
|
|
|
|
|
|
|
|
|
int class_count; /* size of class_array and class_proto */
|
|
|
|
|
JSClass *class_array;
|
|
|
|
|
JSValue *class_proto;
|
|
|
|
|
JSValue regexp_ctor;
|
|
|
|
|
JSValue native_error_proto[JS_NATIVE_ERROR_COUNT];
|
|
|
|
|
@@ -1082,14 +1064,22 @@ struct JSContext {
|
|
|
|
|
|
|
|
|
|
/* Register VM frame root (updated by GC when frame moves) */
|
|
|
|
|
JSValue reg_current_frame; /* current JSFrameRegister being executed */
|
|
|
|
|
uint32_t current_register_pc; /* PC at exception time */
|
|
|
|
|
|
|
|
|
|
/* Execution state (moved from JSRuntime — per-actor) */
|
|
|
|
|
JSValue current_exception;
|
|
|
|
|
struct JSStackFrame *current_stack_frame;
|
|
|
|
|
BOOL current_exception_is_uncatchable : 8;
|
|
|
|
|
BOOL in_out_of_memory : 8;
|
|
|
|
|
|
|
|
|
|
JSInterruptHandler *interrupt_handler;
|
|
|
|
|
void *interrupt_opaque;
|
|
|
|
|
|
|
|
|
|
/* Stack overflow protection */
|
|
|
|
|
size_t stack_size;
|
|
|
|
|
const uint8_t *stack_top;
|
|
|
|
|
const uint8_t *stack_limit;
|
|
|
|
|
|
|
|
|
|
/* Parser state (for GC to scan cpool during parsing) */
|
|
|
|
|
struct JSFunctionDef *current_parse_fd;
|
|
|
|
|
};
|
|
|
|
|
@@ -2066,7 +2056,7 @@ static JSValue js_new_string8_len (JSContext *ctx, const char *buf, int len);
|
|
|
|
|
static JSValue pretext_end (JSContext *ctx, JSText *s);
|
|
|
|
|
static JSValue js_compile_regexp (JSContext *ctx, JSValue pattern, JSValue flags);
|
|
|
|
|
static JSValue js_regexp_constructor_internal (JSContext *ctx, JSValue pattern, JSValue bc);
|
|
|
|
|
static int JS_NewClass1 (JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def, const char *name);
|
|
|
|
|
static int JS_NewClass1 (JSContext *ctx, JSClassID class_id, const JSClassDef *class_def, const char *name);
|
|
|
|
|
|
|
|
|
|
static BOOL js_strict_eq (JSContext *ctx, JSValue op1, JSValue op2);
|
|
|
|
|
static JSValue js_cell_text (JSContext *ctx, JSValue this_val, int argc, JSValue *argv);
|
|
|
|
|
@@ -2450,7 +2440,7 @@ static JSClass const js_std_class_def[] = {
|
|
|
|
|
{ "blob", NULL, NULL }, /* JS_CLASS_BLOB - registered separately */
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static int init_class_range (JSRuntime *rt, JSClass const *tab, int start, int count) {
|
|
|
|
|
static int init_class_range (JSContext *ctx, JSClass const *tab, int start, int count) {
|
|
|
|
|
JSClassDef cm_s, *cm = &cm_s;
|
|
|
|
|
int i, class_id;
|
|
|
|
|
|
|
|
|
|
@@ -2459,7 +2449,7 @@ static int init_class_range (JSRuntime *rt, JSClass const *tab, int start, int c
|
|
|
|
|
memset (cm, 0, sizeof (*cm));
|
|
|
|
|
cm->finalizer = tab[i].finalizer;
|
|
|
|
|
cm->gc_mark = tab[i].gc_mark;
|
|
|
|
|
if (JS_NewClass1 (rt, class_id, cm, tab[i].class_name) < 0) return -1;
|
|
|
|
|
if (JS_NewClass1 (ctx, class_id, cm, tab[i].class_name) < 0) return -1;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
@@ -2468,7 +2458,7 @@ static int init_class_range (JSRuntime *rt, JSClass const *tab, int start, int c
|
|
|
|
|
/* no stack limitation */
|
|
|
|
|
static inline uintptr_t js_get_stack_pointer (void) { return 0; }
|
|
|
|
|
|
|
|
|
|
static inline BOOL js_check_stack_overflow (JSRuntime *rt,
|
|
|
|
|
static inline BOOL js_check_stack_overflow (JSContext *ctx,
|
|
|
|
|
size_t alloca_size) {
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
@@ -2478,11 +2468,11 @@ static inline uintptr_t js_get_stack_pointer (void) {
|
|
|
|
|
return (uintptr_t)__builtin_frame_address (0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline BOOL js_check_stack_overflow (JSRuntime *rt,
|
|
|
|
|
static inline BOOL js_check_stack_overflow (JSContext *ctx,
|
|
|
|
|
size_t alloca_size) {
|
|
|
|
|
uintptr_t sp;
|
|
|
|
|
sp = js_get_stack_pointer () - alloca_size;
|
|
|
|
|
return unlikely (sp < (uintptr_t)rt->stack_limit);
|
|
|
|
|
return unlikely (sp < (uintptr_t)ctx->stack_limit);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
@@ -2849,7 +2839,7 @@ static int ctx_gc (JSContext *ctx, int allow_grow, size_t alloc_size) {
|
|
|
|
|
#ifdef DUMP_GC_DETAIL
|
|
|
|
|
printf(" roots: current_exception\n"); fflush(stdout);
|
|
|
|
|
#endif
|
|
|
|
|
rt->current_exception = gc_copy_value (ctx, rt->current_exception, from_base, from_end, to_base, &to_free, to_end);
|
|
|
|
|
ctx->current_exception = gc_copy_value (ctx, ctx->current_exception, from_base, from_end, to_base, &to_free, to_end);
|
|
|
|
|
|
|
|
|
|
#ifdef DUMP_GC_DETAIL
|
|
|
|
|
printf(" roots: native_error_proto\n"); fflush(stdout);
|
|
|
|
|
@@ -2860,9 +2850,9 @@ static int ctx_gc (JSContext *ctx, int allow_grow, size_t alloc_size) {
|
|
|
|
|
|
|
|
|
|
/* Copy class prototypes */
|
|
|
|
|
#ifdef DUMP_GC_DETAIL
|
|
|
|
|
printf(" roots: class_proto (count=%d)\n", rt->class_count); fflush(stdout);
|
|
|
|
|
printf(" roots: class_proto (count=%d)\n", ctx->class_count); fflush(stdout);
|
|
|
|
|
#endif
|
|
|
|
|
for (int i = 0; i < rt->class_count; i++) {
|
|
|
|
|
for (int i = 0; i < ctx->class_count; i++) {
|
|
|
|
|
ctx->class_proto[i] = gc_copy_value (ctx, ctx->class_proto[i], from_base, from_end, to_base, &to_free, to_end);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -2894,7 +2884,7 @@ static int ctx_gc (JSContext *ctx, int allow_grow, size_t alloc_size) {
|
|
|
|
|
#ifdef DUMP_GC_DETAIL
|
|
|
|
|
printf(" roots: current_stack_frame chain\n"); fflush(stdout);
|
|
|
|
|
#endif
|
|
|
|
|
for (JSStackFrame *sf = rt->current_stack_frame; sf != NULL; sf = sf->prev_frame) {
|
|
|
|
|
for (JSStackFrame *sf = ctx->current_stack_frame; sf != NULL; sf = sf->prev_frame) {
|
|
|
|
|
sf->cur_func = gc_copy_value (ctx, sf->cur_func, from_base, from_end, to_base, &to_free, to_end);
|
|
|
|
|
/* Also scan bytecode cpool if it's a bytecode object outside GC heap */
|
|
|
|
|
gc_scan_bytecode_cpool (ctx, sf->cur_func, from_base, from_end, to_base, &to_free, to_end);
|
|
|
|
|
@@ -3036,20 +3026,7 @@ JSRuntime *JS_NewRuntime (void) {
|
|
|
|
|
if (!rt) return NULL;
|
|
|
|
|
memset (rt, 0, sizeof (*rt));
|
|
|
|
|
|
|
|
|
|
/* create the object, array and function classes */
|
|
|
|
|
if (init_class_range (rt, js_std_class_def, JS_CLASS_OBJECT, countof (js_std_class_def))
|
|
|
|
|
< 0)
|
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
|
|
rt->stack_size = JS_DEFAULT_STACK_SIZE;
|
|
|
|
|
JS_UpdateStackTop (rt);
|
|
|
|
|
|
|
|
|
|
rt->current_exception = JS_UNINITIALIZED;
|
|
|
|
|
|
|
|
|
|
return rt;
|
|
|
|
|
fail:
|
|
|
|
|
JS_FreeRuntime (rt);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void *JS_GetRuntimeOpaque (JSRuntime *rt) { return rt->user_opaque; }
|
|
|
|
|
@@ -3071,9 +3048,9 @@ static void *sys_realloc (void *ptr, size_t size) { return realloc (ptr, size);
|
|
|
|
|
#define free(p) free_is_forbidden (p)
|
|
|
|
|
#define realloc(p, s) realloc_is_forbidden (p, s)
|
|
|
|
|
|
|
|
|
|
void JS_SetInterruptHandler (JSRuntime *rt, JSInterruptHandler *cb, void *opaque) {
|
|
|
|
|
rt->interrupt_handler = cb;
|
|
|
|
|
rt->interrupt_opaque = opaque;
|
|
|
|
|
void JS_SetInterruptHandler (JSContext *ctx, JSInterruptHandler *cb, void *opaque) {
|
|
|
|
|
ctx->interrupt_handler = cb;
|
|
|
|
|
ctx->interrupt_opaque = opaque;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void JS_SetStripInfo (JSRuntime *rt, int flags) { rt->strip_flags = flags; }
|
|
|
|
|
@@ -3104,11 +3081,9 @@ void JS_SetRuntimeInfo (JSRuntime *rt, const char *s) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void JS_FreeRuntime (JSRuntime *rt) {
|
|
|
|
|
/* free the classes */
|
|
|
|
|
js_free_rt (rt->class_array);
|
|
|
|
|
|
|
|
|
|
/* Destroy buddy allocator */
|
|
|
|
|
buddy_destroy (&rt->buddy);
|
|
|
|
|
sys_free (rt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Forward declarations for intrinsics */
|
|
|
|
|
@@ -3118,7 +3093,6 @@ static void JS_AddIntrinsicRegExp (JSContext *ctx);
|
|
|
|
|
|
|
|
|
|
JSContext *JS_NewContextRawWithHeapSize (JSRuntime *rt, size_t heap_size) {
|
|
|
|
|
JSContext *ctx;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
/* Round up to buddy allocator minimum */
|
|
|
|
|
size_t min_size = 1ULL << BUDDY_MIN_ORDER;
|
|
|
|
|
@@ -3135,17 +3109,15 @@ JSContext *JS_NewContextRawWithHeapSize (JSRuntime *rt, size_t heap_size) {
|
|
|
|
|
|
|
|
|
|
if (!ctx) return NULL;
|
|
|
|
|
ctx->trace_hook = NULL;
|
|
|
|
|
ctx->rt = rt;
|
|
|
|
|
|
|
|
|
|
ctx->class_proto
|
|
|
|
|
= js_malloc_rt (sizeof (ctx->class_proto[0]) * rt->class_count);
|
|
|
|
|
if (!ctx->class_proto) {
|
|
|
|
|
/* Bootstrap class_array and class_proto together via JS_NewClass1 */
|
|
|
|
|
if (init_class_range (ctx, js_std_class_def, JS_CLASS_OBJECT, countof (js_std_class_def)) < 0) {
|
|
|
|
|
js_free_rt (ctx->class_array);
|
|
|
|
|
js_free_rt (ctx->class_proto);
|
|
|
|
|
js_free_rt (ctx);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
ctx->rt = rt;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < rt->class_count; i++)
|
|
|
|
|
ctx->class_proto[i] = JS_NULL;
|
|
|
|
|
|
|
|
|
|
ctx->regexp_ctor = JS_NULL;
|
|
|
|
|
|
|
|
|
|
@@ -3154,6 +3126,7 @@ JSContext *JS_NewContextRawWithHeapSize (JSRuntime *rt, size_t heap_size) {
|
|
|
|
|
ctx->frame_stack
|
|
|
|
|
= js_malloc_rt (sizeof (struct VMFrame) * ctx->frame_stack_capacity);
|
|
|
|
|
if (!ctx->frame_stack) {
|
|
|
|
|
js_free_rt (ctx->class_array);
|
|
|
|
|
js_free_rt (ctx->class_proto);
|
|
|
|
|
js_free_rt (ctx);
|
|
|
|
|
return NULL;
|
|
|
|
|
@@ -3165,6 +3138,7 @@ JSContext *JS_NewContextRawWithHeapSize (JSRuntime *rt, size_t heap_size) {
|
|
|
|
|
= js_malloc_rt (sizeof (JSValue) * ctx->value_stack_capacity);
|
|
|
|
|
if (!ctx->value_stack) {
|
|
|
|
|
js_free_rt (ctx->frame_stack);
|
|
|
|
|
js_free_rt (ctx->class_array);
|
|
|
|
|
js_free_rt (ctx->class_proto);
|
|
|
|
|
js_free_rt (ctx);
|
|
|
|
|
return NULL;
|
|
|
|
|
@@ -3174,6 +3148,12 @@ JSContext *JS_NewContextRawWithHeapSize (JSRuntime *rt, size_t heap_size) {
|
|
|
|
|
/* Initialize register VM frame root */
|
|
|
|
|
ctx->reg_current_frame = JS_NULL;
|
|
|
|
|
|
|
|
|
|
/* Initialize per-context execution state (moved from JSRuntime) */
|
|
|
|
|
ctx->current_exception = JS_UNINITIALIZED;
|
|
|
|
|
ctx->current_stack_frame = NULL;
|
|
|
|
|
ctx->stack_size = JS_DEFAULT_STACK_SIZE;
|
|
|
|
|
JS_UpdateStackTop (ctx);
|
|
|
|
|
|
|
|
|
|
/* Initialize stone text intern table */
|
|
|
|
|
ctx->st_pages = NULL;
|
|
|
|
|
ctx->st_text_array = NULL;
|
|
|
|
|
@@ -3184,6 +3164,7 @@ JSContext *JS_NewContextRawWithHeapSize (JSRuntime *rt, size_t heap_size) {
|
|
|
|
|
if (st_text_resize (ctx) < 0) {
|
|
|
|
|
js_free_rt (ctx->value_stack);
|
|
|
|
|
js_free_rt (ctx->frame_stack);
|
|
|
|
|
js_free_rt (ctx->class_array);
|
|
|
|
|
js_free_rt (ctx->class_proto);
|
|
|
|
|
js_free_rt (ctx);
|
|
|
|
|
return NULL;
|
|
|
|
|
@@ -3198,6 +3179,7 @@ JSContext *JS_NewContextRawWithHeapSize (JSRuntime *rt, size_t heap_size) {
|
|
|
|
|
js_free_rt (ctx->st_text_array);
|
|
|
|
|
js_free_rt (ctx->value_stack);
|
|
|
|
|
js_free_rt (ctx->frame_stack);
|
|
|
|
|
js_free_rt (ctx->class_array);
|
|
|
|
|
js_free_rt (ctx->class_proto);
|
|
|
|
|
js_free_rt (ctx);
|
|
|
|
|
return NULL;
|
|
|
|
|
@@ -3253,14 +3235,12 @@ static inline void set_value (JSContext *ctx, JSValue *pval, JSValue new_val) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void JS_SetClassProto (JSContext *ctx, JSClassID class_id, JSValue obj) {
|
|
|
|
|
JSRuntime *rt = ctx->rt;
|
|
|
|
|
assert (class_id < rt->class_count);
|
|
|
|
|
assert (class_id < ctx->class_count);
|
|
|
|
|
set_value (ctx, &ctx->class_proto[class_id], obj);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JSValue JS_GetClassProto (JSContext *ctx, JSClassID class_id) {
|
|
|
|
|
JSRuntime *rt = ctx->rt;
|
|
|
|
|
assert (class_id < rt->class_count);
|
|
|
|
|
assert (class_id < ctx->class_count);
|
|
|
|
|
return ctx->class_proto[class_id];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -3278,8 +3258,9 @@ void JS_FreeContext (JSContext *ctx) {
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < JS_NATIVE_ERROR_COUNT; i++) {
|
|
|
|
|
}
|
|
|
|
|
for (i = 0; i < rt->class_count; i++) {
|
|
|
|
|
for (i = 0; i < ctx->class_count; i++) {
|
|
|
|
|
}
|
|
|
|
|
js_free_rt (ctx->class_array);
|
|
|
|
|
js_free_rt (ctx->class_proto);
|
|
|
|
|
|
|
|
|
|
/* Free VM stacks */
|
|
|
|
|
@@ -3298,26 +3279,28 @@ void JS_FreeContext (JSContext *ctx) {
|
|
|
|
|
ctx->heap_free = NULL;
|
|
|
|
|
ctx->heap_end = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
js_free_rt (ctx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JSRuntime *JS_GetRuntime (JSContext *ctx) { return ctx->rt; }
|
|
|
|
|
|
|
|
|
|
static void update_stack_limit (JSRuntime *rt) {
|
|
|
|
|
if (rt->stack_size == 0) {
|
|
|
|
|
rt->stack_limit = 0; /* no limit */
|
|
|
|
|
static void update_stack_limit (JSContext *ctx) {
|
|
|
|
|
if (ctx->stack_size == 0) {
|
|
|
|
|
ctx->stack_limit = 0; /* no limit */
|
|
|
|
|
} else {
|
|
|
|
|
rt->stack_limit = rt->stack_top - rt->stack_size;
|
|
|
|
|
ctx->stack_limit = ctx->stack_top - ctx->stack_size;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void JS_SetMaxStackSize (JSRuntime *rt, size_t stack_size) {
|
|
|
|
|
rt->stack_size = stack_size;
|
|
|
|
|
update_stack_limit (rt);
|
|
|
|
|
void JS_SetMaxStackSize (JSContext *ctx, size_t stack_size) {
|
|
|
|
|
ctx->stack_size = stack_size;
|
|
|
|
|
update_stack_limit (ctx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void JS_UpdateStackTop (JSRuntime *rt) {
|
|
|
|
|
rt->stack_top = (const uint8_t *)js_get_stack_pointer ();
|
|
|
|
|
update_stack_limit (rt);
|
|
|
|
|
void JS_UpdateStackTop (JSContext *ctx) {
|
|
|
|
|
ctx->stack_top = (const uint8_t *)js_get_stack_pointer ();
|
|
|
|
|
update_stack_limit (ctx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static JSText *js_alloc_string (JSContext *ctx, int max_len);
|
|
|
|
|
@@ -3376,46 +3359,54 @@ JSClassID JS_GetClassID (JSValue v) {
|
|
|
|
|
return REC_GET_CLASS_ID(rec);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL JS_IsRegisteredClass (JSRuntime *rt, JSClassID class_id) {
|
|
|
|
|
return (class_id < rt->class_count
|
|
|
|
|
&& rt->class_array[class_id].class_id != 0);
|
|
|
|
|
BOOL JS_IsRegisteredClass (JSContext *ctx, JSClassID class_id) {
|
|
|
|
|
return (class_id < ctx->class_count
|
|
|
|
|
&& ctx->class_array[class_id].class_id != 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* create a new object internal class. Return -1 if error, 0 if
|
|
|
|
|
OK. The finalizer can be NULL if none is needed. */
|
|
|
|
|
static int JS_NewClass1 (JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def, const char *name) {
|
|
|
|
|
int new_size;
|
|
|
|
|
static int JS_NewClass1 (JSContext *ctx, JSClassID class_id, const JSClassDef *class_def, const char *name) {
|
|
|
|
|
int new_size, i;
|
|
|
|
|
JSClass *cl, *new_class_array;
|
|
|
|
|
JSValue *new_class_proto;
|
|
|
|
|
|
|
|
|
|
if (class_id >= (1 << 16)) return -1;
|
|
|
|
|
if (class_id < rt->class_count && rt->class_array[class_id].class_id != 0)
|
|
|
|
|
if (class_id < ctx->class_count && ctx->class_array[class_id].class_id != 0)
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
if (class_id >= rt->class_count) {
|
|
|
|
|
if (class_id >= ctx->class_count) {
|
|
|
|
|
new_size = max_int (JS_CLASS_INIT_COUNT,
|
|
|
|
|
max_int (class_id + 1, rt->class_count * 3 / 2));
|
|
|
|
|
max_int (class_id + 1, ctx->class_count * 3 / 2));
|
|
|
|
|
|
|
|
|
|
/* reallocate the class array */
|
|
|
|
|
new_class_array
|
|
|
|
|
= js_realloc_rt (rt->class_array, sizeof (JSClass) * new_size);
|
|
|
|
|
= js_realloc_rt (ctx->class_array, sizeof (JSClass) * new_size);
|
|
|
|
|
if (!new_class_array) return -1;
|
|
|
|
|
memset (new_class_array + rt->class_count, 0, (new_size - rt->class_count) * sizeof (JSClass));
|
|
|
|
|
rt->class_array = new_class_array;
|
|
|
|
|
rt->class_count = new_size;
|
|
|
|
|
memset (new_class_array + ctx->class_count, 0, (new_size - ctx->class_count) * sizeof (JSClass));
|
|
|
|
|
ctx->class_array = new_class_array;
|
|
|
|
|
|
|
|
|
|
/* reallocate the class proto array */
|
|
|
|
|
new_class_proto
|
|
|
|
|
= js_realloc_rt (ctx->class_proto, sizeof (JSValue) * new_size);
|
|
|
|
|
if (!new_class_proto) return -1;
|
|
|
|
|
for (i = ctx->class_count; i < new_size; i++)
|
|
|
|
|
new_class_proto[i] = JS_NULL;
|
|
|
|
|
ctx->class_proto = new_class_proto;
|
|
|
|
|
|
|
|
|
|
ctx->class_count = new_size;
|
|
|
|
|
}
|
|
|
|
|
cl = &rt->class_array[class_id];
|
|
|
|
|
cl = &ctx->class_array[class_id];
|
|
|
|
|
cl->class_id = class_id;
|
|
|
|
|
cl->class_name = name; /* name is already a const char* */
|
|
|
|
|
cl->finalizer = class_def->finalizer;
|
|
|
|
|
cl->gc_mark = class_def->gc_mark;
|
|
|
|
|
/* call field removed from JSClass - use class_def->call directly if needed
|
|
|
|
|
*/
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int JS_NewClass (JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def) {
|
|
|
|
|
int JS_NewClass (JSContext *ctx, JSClassID class_id, const JSClassDef *class_def) {
|
|
|
|
|
/* class_name is stored directly as const char* */
|
|
|
|
|
return JS_NewClass1 (rt, class_id, class_def, class_def->class_name);
|
|
|
|
|
return JS_NewClass1 (ctx, class_id, class_def, class_def->class_name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static JSValue js_new_string8_len (JSContext *ctx, const char *buf, int len) {
|
|
|
|
|
@@ -4250,24 +4241,20 @@ void JS_DumpMemoryUsage (FILE *fp, const JSMemoryUsage *s, JSRuntime *rt) {
|
|
|
|
|
|
|
|
|
|
/* WARNING: obj is freed */
|
|
|
|
|
JSValue JS_Throw (JSContext *ctx, JSValue obj) {
|
|
|
|
|
JSRuntime *rt = ctx->rt;
|
|
|
|
|
rt->current_exception = obj;
|
|
|
|
|
/* uncatchable flag removed - not needed with copying GC */
|
|
|
|
|
ctx->current_exception = obj;
|
|
|
|
|
return JS_EXCEPTION;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* return the pending exception (cannot be called twice). */
|
|
|
|
|
JSValue JS_GetException (JSContext *ctx) {
|
|
|
|
|
JSValue val;
|
|
|
|
|
JSRuntime *rt = ctx->rt;
|
|
|
|
|
val = rt->current_exception;
|
|
|
|
|
rt->current_exception = JS_UNINITIALIZED;
|
|
|
|
|
JSValue val = ctx->current_exception;
|
|
|
|
|
ctx->current_exception = JS_UNINITIALIZED;
|
|
|
|
|
return val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
JS_BOOL
|
|
|
|
|
JS_HasException (JSContext *ctx) {
|
|
|
|
|
return !JS_IsUninitialized (ctx->rt->current_exception);
|
|
|
|
|
return !JS_IsUninitialized (ctx->current_exception);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void dbuf_put_leb128 (DynBuf *s, uint32_t v) {
|
|
|
|
|
@@ -4438,7 +4425,7 @@ static void build_backtrace (JSContext *ctx, JSValue error_obj, const char *file
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (sf = ctx->rt->current_stack_frame; sf != NULL; sf = sf->prev_frame) {
|
|
|
|
|
for (sf = ctx->current_stack_frame; sf != NULL; sf = sf->prev_frame) {
|
|
|
|
|
if (sf->js_mode & JS_MODE_BACKTRACE_BARRIER) break;
|
|
|
|
|
if (backtrace_flags & JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL) {
|
|
|
|
|
backtrace_flags &= ~JS_BACKTRACE_FLAG_SKIP_FIRST_LEVEL;
|
|
|
|
|
@@ -4527,12 +4514,11 @@ static JSValue JS_ThrowError2 (JSContext *ctx, JSErrorEnum error_num, const char
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static JSValue JS_ThrowError (JSContext *ctx, JSErrorEnum error_num, const char *fmt, va_list ap) {
|
|
|
|
|
JSRuntime *rt = ctx->rt;
|
|
|
|
|
JSStackFrame *sf;
|
|
|
|
|
BOOL add_backtrace;
|
|
|
|
|
|
|
|
|
|
/* the backtrace is added later if called from a bytecode function */
|
|
|
|
|
sf = rt->current_stack_frame;
|
|
|
|
|
sf = ctx->current_stack_frame;
|
|
|
|
|
add_backtrace = (!sf || (JS_GetFunctionBytecode (sf->cur_func) == NULL));
|
|
|
|
|
return JS_ThrowError2 (ctx, error_num, fmt, ap, add_backtrace);
|
|
|
|
|
}
|
|
|
|
|
@@ -4628,8 +4614,7 @@ static JSValue JS_ThrowReferenceErrorUninitialized2 (JSContext *ctx,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static JSValue JS_ThrowTypeErrorInvalidClass (JSContext *ctx, int class_id) {
|
|
|
|
|
JSRuntime *rt = ctx->rt;
|
|
|
|
|
const char *name = rt->class_array[class_id].class_name;
|
|
|
|
|
const char *name = ctx->class_array[class_id].class_name;
|
|
|
|
|
return JS_ThrowTypeError (ctx, "%s object expected", name ? name : "unknown");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -4639,10 +4624,9 @@ static void JS_ThrowInterrupted (JSContext *ctx) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static no_inline __exception int __js_poll_interrupts (JSContext *ctx) {
|
|
|
|
|
JSRuntime *rt = ctx->rt;
|
|
|
|
|
ctx->interrupt_counter = JS_INTERRUPT_COUNTER_INIT;
|
|
|
|
|
if (rt->interrupt_handler) {
|
|
|
|
|
if (rt->interrupt_handler (rt, rt->interrupt_opaque)) {
|
|
|
|
|
if (ctx->interrupt_handler) {
|
|
|
|
|
if (ctx->interrupt_handler (ctx->rt, ctx->interrupt_opaque)) {
|
|
|
|
|
JS_ThrowInterrupted (ctx);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
@@ -6609,7 +6593,6 @@ fail:
|
|
|
|
|
#define JS_CALL_FLAG_COPY_ARGV (1 << 1)
|
|
|
|
|
|
|
|
|
|
static JSValue js_call_c_function (JSContext *ctx, JSValue func_obj, JSValue this_obj, int argc, JSValue *argv) {
|
|
|
|
|
JSRuntime *rt = ctx->rt;
|
|
|
|
|
JSCFunctionType func;
|
|
|
|
|
JSFunction *f;
|
|
|
|
|
JSStackFrame sf_s, *sf = &sf_s, *prev_sf;
|
|
|
|
|
@@ -6624,12 +6607,12 @@ static JSValue js_call_c_function (JSContext *ctx, JSValue func_obj, JSValue thi
|
|
|
|
|
arg_count = f->length;
|
|
|
|
|
|
|
|
|
|
/* better to always check stack overflow */
|
|
|
|
|
if (js_check_stack_overflow (rt, sizeof (arg_buf[0]) * arg_count))
|
|
|
|
|
if (js_check_stack_overflow (ctx, sizeof (arg_buf[0]) * arg_count))
|
|
|
|
|
return JS_ThrowStackOverflow (ctx);
|
|
|
|
|
|
|
|
|
|
prev_sf = rt->current_stack_frame;
|
|
|
|
|
prev_sf = ctx->current_stack_frame;
|
|
|
|
|
sf->prev_frame = prev_sf;
|
|
|
|
|
rt->current_stack_frame = sf;
|
|
|
|
|
ctx->current_stack_frame = sf;
|
|
|
|
|
sf->js_mode = 0;
|
|
|
|
|
sf->cur_func = (JSValue)func_obj;
|
|
|
|
|
sf->arg_count = argc;
|
|
|
|
|
@@ -6728,7 +6711,7 @@ static JSValue js_call_c_function (JSContext *ctx, JSValue func_obj, JSValue thi
|
|
|
|
|
abort ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rt->current_stack_frame = sf->prev_frame;
|
|
|
|
|
ctx->current_stack_frame = sf->prev_frame;
|
|
|
|
|
|
|
|
|
|
/* Restore value stack if we used it for arg padding */
|
|
|
|
|
if (saved_vs_top >= 0)
|
|
|
|
|
@@ -6748,7 +6731,6 @@ typedef enum {
|
|
|
|
|
|
|
|
|
|
/* argv[] is modified if (flags & JS_CALL_FLAG_COPY_ARGV) = 0. */
|
|
|
|
|
static JSValue JS_CallInternal (JSContext *caller_ctx, JSValue func_obj, JSValue this_obj, int argc, JSValue *argv, int flags) {
|
|
|
|
|
JSRuntime *rt = caller_ctx->rt;
|
|
|
|
|
JSContext *ctx = caller_ctx;
|
|
|
|
|
JSFunction *f;
|
|
|
|
|
JSFunctionBytecode *b;
|
|
|
|
|
@@ -6830,7 +6812,7 @@ static JSValue JS_CallInternal (JSContext *caller_ctx, JSValue func_obj, JSValue
|
|
|
|
|
|
|
|
|
|
alloca_size
|
|
|
|
|
= sizeof (JSValue) * (arg_allocated_size + b->var_count + b->stack_size);
|
|
|
|
|
if (js_check_stack_overflow (rt, alloca_size))
|
|
|
|
|
if (js_check_stack_overflow (ctx, alloca_size))
|
|
|
|
|
return JS_ThrowStackOverflow (caller_ctx);
|
|
|
|
|
|
|
|
|
|
sf->js_mode = b->js_mode;
|
|
|
|
|
@@ -6877,8 +6859,8 @@ static JSValue JS_CallInternal (JSContext *caller_ctx, JSValue func_obj, JSValue
|
|
|
|
|
pc = b->byte_code_buf;
|
|
|
|
|
sf->stack_buf = stack_buf;
|
|
|
|
|
sf->p_sp = &sp; /* GC uses this to find current stack top */
|
|
|
|
|
sf->prev_frame = rt->current_stack_frame;
|
|
|
|
|
rt->current_stack_frame = sf;
|
|
|
|
|
sf->prev_frame = ctx->current_stack_frame;
|
|
|
|
|
ctx->current_stack_frame = sf;
|
|
|
|
|
|
|
|
|
|
restart:
|
|
|
|
|
for (;;) {
|
|
|
|
|
@@ -8579,12 +8561,12 @@ restart:
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
exception:
|
|
|
|
|
if (is_backtrace_needed (ctx, rt->current_exception)) {
|
|
|
|
|
if (is_backtrace_needed (ctx, ctx->current_exception)) {
|
|
|
|
|
/* add the backtrace information now (it is not done
|
|
|
|
|
before if the exception happens in a bytecode
|
|
|
|
|
operation */
|
|
|
|
|
sf->cur_pc = pc;
|
|
|
|
|
build_backtrace (ctx, rt->current_exception, NULL, 0, 0, 0);
|
|
|
|
|
build_backtrace (ctx, ctx->current_exception, NULL, 0, 0, 0);
|
|
|
|
|
}
|
|
|
|
|
/* All exceptions are catchable in the simplified runtime */
|
|
|
|
|
while (sp > stack_buf) {
|
|
|
|
|
@@ -8592,8 +8574,8 @@ exception:
|
|
|
|
|
if (JS_VALUE_GET_TAG (val) == JS_TAG_CATCH_OFFSET) {
|
|
|
|
|
int pos = JS_VALUE_GET_INT (val);
|
|
|
|
|
if (pos != 0) {
|
|
|
|
|
*sp++ = rt->current_exception;
|
|
|
|
|
rt->current_exception = JS_UNINITIALIZED;
|
|
|
|
|
*sp++ = ctx->current_exception;
|
|
|
|
|
ctx->current_exception = JS_UNINITIALIZED;
|
|
|
|
|
pc = b->byte_code_buf + pos;
|
|
|
|
|
goto restart;
|
|
|
|
|
}
|
|
|
|
|
@@ -8601,7 +8583,7 @@ exception:
|
|
|
|
|
}
|
|
|
|
|
ret_val = JS_EXCEPTION;
|
|
|
|
|
done:
|
|
|
|
|
rt->current_stack_frame = sf->prev_frame;
|
|
|
|
|
ctx->current_stack_frame = sf->prev_frame;
|
|
|
|
|
|
|
|
|
|
if (unlikely (caller_ctx->trace_hook)
|
|
|
|
|
&& (caller_ctx->trace_type & JS_HOOK_RET))
|
|
|
|
|
@@ -9549,7 +9531,7 @@ static int js_parse_error_v (JSParseState *s, const uint8_t *ptr, const char *fm
|
|
|
|
|
int line_num, col_num;
|
|
|
|
|
line_num = get_line_col (&col_num, s->buf_start, ptr - s->buf_start);
|
|
|
|
|
JS_ThrowError2 (ctx, JS_SYNTAX_ERROR, fmt, ap, FALSE);
|
|
|
|
|
build_backtrace (ctx, ctx->rt->current_exception, s->filename, line_num + 1, col_num + 1, 0);
|
|
|
|
|
build_backtrace (ctx, ctx->current_exception, s->filename, line_num + 1, col_num + 1, 0);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -10098,7 +10080,7 @@ static __exception int next_token (JSParseState *s) {
|
|
|
|
|
BOOL ident_has_escape;
|
|
|
|
|
JSValue ident_str;
|
|
|
|
|
|
|
|
|
|
if (js_check_stack_overflow (s->ctx->rt, 0)) {
|
|
|
|
|
if (js_check_stack_overflow (s->ctx, 0)) {
|
|
|
|
|
return js_parse_error (s, "stack overflow");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -10711,7 +10693,7 @@ static __exception int json_next_token (JSParseState *s) {
|
|
|
|
|
int c;
|
|
|
|
|
JSValue ident_str;
|
|
|
|
|
|
|
|
|
|
if (js_check_stack_overflow (s->ctx->rt, 0)) {
|
|
|
|
|
if (js_check_stack_overflow (s->ctx, 0)) {
|
|
|
|
|
return js_parse_error (s, "stack overflow");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -12490,7 +12472,7 @@ static __exception int js_parse_postfix_expr (JSParseState *s,
|
|
|
|
|
int line_num, col_num;
|
|
|
|
|
line_num
|
|
|
|
|
= get_line_col (&col_num, s->buf_start, s->token.ptr - s->buf_start);
|
|
|
|
|
build_backtrace (s->ctx, s->ctx->rt->current_exception, s->filename, line_num + 1, col_num + 1, 0);
|
|
|
|
|
build_backtrace (s->ctx, s->ctx->current_exception, s->filename, line_num + 1, col_num + 1, 0);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
ret = emit_push_const (s, str);
|
|
|
|
|
@@ -17479,7 +17461,7 @@ fail:
|
|
|
|
|
static int JS_WriteObjectRec (BCWriterState *s, JSValue obj) {
|
|
|
|
|
uint32_t tag;
|
|
|
|
|
|
|
|
|
|
if (js_check_stack_overflow (s->ctx->rt, 0)) {
|
|
|
|
|
if (js_check_stack_overflow (s->ctx, 0)) {
|
|
|
|
|
JS_ThrowStackOverflow (s->ctx);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
@@ -18127,7 +18109,7 @@ static JSValue JS_ReadObjectRec (BCReaderState *s) {
|
|
|
|
|
uint8_t tag;
|
|
|
|
|
JSValue obj = JS_NULL;
|
|
|
|
|
|
|
|
|
|
if (js_check_stack_overflow (ctx->rt, 0)) return JS_ThrowStackOverflow (ctx);
|
|
|
|
|
if (js_check_stack_overflow (ctx, 0)) return JS_ThrowStackOverflow (ctx);
|
|
|
|
|
|
|
|
|
|
if (bc_get_u8 (s, &tag)) return JS_EXCEPTION;
|
|
|
|
|
|
|
|
|
|
@@ -20129,14 +20111,13 @@ static JSValue js_regexp_toString (JSContext *ctx, JSValue this_val, int argc, J
|
|
|
|
|
|
|
|
|
|
int lre_check_stack_overflow (void *opaque, size_t alloca_size) {
|
|
|
|
|
JSContext *ctx = opaque;
|
|
|
|
|
return js_check_stack_overflow (ctx->rt, alloca_size);
|
|
|
|
|
return js_check_stack_overflow (ctx, alloca_size);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int lre_check_timeout (void *opaque) {
|
|
|
|
|
JSContext *ctx = opaque;
|
|
|
|
|
JSRuntime *rt = ctx->rt;
|
|
|
|
|
return (rt->interrupt_handler
|
|
|
|
|
&& rt->interrupt_handler (rt, rt->interrupt_opaque));
|
|
|
|
|
return (ctx->interrupt_handler
|
|
|
|
|
&& ctx->interrupt_handler (ctx->rt, ctx->interrupt_opaque));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void *lre_realloc (void *opaque, void *ptr, size_t size) {
|
|
|
|
|
@@ -20653,7 +20634,7 @@ static JSValue internalize_json_property (JSContext *ctx, JSValue holder, JSValu
|
|
|
|
|
uint32_t i, len = 0;
|
|
|
|
|
JSValue prop;
|
|
|
|
|
|
|
|
|
|
if (js_check_stack_overflow (ctx->rt, 0)) {
|
|
|
|
|
if (js_check_stack_overflow (ctx, 0)) {
|
|
|
|
|
return JS_ThrowStackOverflow (ctx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -20808,7 +20789,7 @@ static int js_json_to_str (JSContext *ctx, JSONStringifyContext *jsc, JSValue ho
|
|
|
|
|
tab_ref.val = JS_NULL;
|
|
|
|
|
prop_ref.val = JS_NULL;
|
|
|
|
|
|
|
|
|
|
if (js_check_stack_overflow (ctx->rt, 0)) {
|
|
|
|
|
if (js_check_stack_overflow (ctx, 0)) {
|
|
|
|
|
JS_ThrowStackOverflow (ctx);
|
|
|
|
|
goto exception;
|
|
|
|
|
}
|
|
|
|
|
@@ -26397,7 +26378,7 @@ static void JS_AddIntrinsicBaseObjects (JSContext *ctx) {
|
|
|
|
|
.class_name = "blob",
|
|
|
|
|
.finalizer = js_blob_finalizer,
|
|
|
|
|
};
|
|
|
|
|
JS_NewClass (JS_GetRuntime (ctx), JS_CLASS_BLOB, &blob_class);
|
|
|
|
|
JS_NewClass (ctx, JS_CLASS_BLOB, &blob_class);
|
|
|
|
|
ctx->class_proto[JS_CLASS_BLOB] = JS_NewObject (ctx);
|
|
|
|
|
JS_SetPropertyFunctionList (ctx, ctx->class_proto[JS_CLASS_BLOB], js_blob_proto_funcs, countof (js_blob_proto_funcs));
|
|
|
|
|
|
|
|
|
|
@@ -26559,7 +26540,7 @@ void js_debug_sethook (JSContext *ctx, js_hook hook, int type, void *user) {
|
|
|
|
|
|
|
|
|
|
uint32_t js_debugger_stack_depth (JSContext *ctx) {
|
|
|
|
|
uint32_t stack_index = 0;
|
|
|
|
|
JSStackFrame *sf = ctx->rt->current_stack_frame;
|
|
|
|
|
JSStackFrame *sf = ctx->current_stack_frame;
|
|
|
|
|
while (sf != NULL) {
|
|
|
|
|
sf = sf->prev_frame;
|
|
|
|
|
stack_index++;
|
|
|
|
|
@@ -26572,7 +26553,7 @@ JSValue js_debugger_backtrace_fns (JSContext *ctx, const uint8_t *cur_pc) {
|
|
|
|
|
JSStackFrame *sf;
|
|
|
|
|
uint32_t stack_index = 0;
|
|
|
|
|
|
|
|
|
|
for (sf = ctx->rt->current_stack_frame; sf != NULL; sf = sf->prev_frame) {
|
|
|
|
|
for (sf = ctx->current_stack_frame; sf != NULL; sf = sf->prev_frame) {
|
|
|
|
|
uint32_t id = stack_index++;
|
|
|
|
|
JS_SetPropertyUint32 (ctx, ret, id, sf->cur_func);
|
|
|
|
|
}
|
|
|
|
|
@@ -26586,7 +26567,7 @@ JSValue js_debugger_build_backtrace (JSContext *ctx, const uint8_t *cur_pc) {
|
|
|
|
|
JSValue ret = JS_NewArray (ctx);
|
|
|
|
|
uint32_t stack_index = 0;
|
|
|
|
|
|
|
|
|
|
for (sf = ctx->rt->current_stack_frame; sf != NULL; sf = sf->prev_frame) {
|
|
|
|
|
for (sf = ctx->current_stack_frame; sf != NULL; sf = sf->prev_frame) {
|
|
|
|
|
JSValue current_frame = JS_NewObject (ctx);
|
|
|
|
|
|
|
|
|
|
uint32_t id = stack_index++;
|
|
|
|
|
@@ -26607,7 +26588,7 @@ JSValue js_debugger_build_backtrace (JSContext *ctx, const uint8_t *cur_pc) {
|
|
|
|
|
|
|
|
|
|
b = f->u.func.function_bytecode;
|
|
|
|
|
if (b->has_debug) {
|
|
|
|
|
const uint8_t *pc = sf != ctx->rt->current_stack_frame || !cur_pc
|
|
|
|
|
const uint8_t *pc = sf != ctx->current_stack_frame || !cur_pc
|
|
|
|
|
? sf->cur_pc
|
|
|
|
|
: cur_pc;
|
|
|
|
|
int col_num;
|
|
|
|
|
@@ -27099,7 +27080,7 @@ JSValue js_debugger_local_variables (JSContext *ctx, int stack_index) {
|
|
|
|
|
JSStackFrame *sf;
|
|
|
|
|
int cur_index = 0;
|
|
|
|
|
|
|
|
|
|
for (sf = ctx->rt->current_stack_frame; sf != NULL; sf = sf->prev_frame) {
|
|
|
|
|
for (sf = ctx->current_stack_frame; sf != NULL; sf = sf->prev_frame) {
|
|
|
|
|
// this val is one frame up
|
|
|
|
|
if (cur_index == stack_index - 1) {
|
|
|
|
|
if (js_is_bytecode_function (sf->cur_func)) {
|
|
|
|
|
@@ -31675,6 +31656,8 @@ char *JS_Tokenize (const char *source, size_t len, const char *filename) {
|
|
|
|
|
s.function_nr = 0;
|
|
|
|
|
s.errors = NULL;
|
|
|
|
|
s.has_error = 0;
|
|
|
|
|
s.lc_cache.ptr = s.buf_start;
|
|
|
|
|
s.lc_cache.buf_start = s.buf_start;
|
|
|
|
|
|
|
|
|
|
cJSON *root = cJSON_CreateObject ();
|
|
|
|
|
cJSON_AddStringToObject (root, "filename", filename);
|
|
|
|
|
@@ -33876,11 +33859,10 @@ static JSValue reg_vm_binop(JSContext *ctx, int op, JSValue a, JSValue b) {
|
|
|
|
|
|
|
|
|
|
/* Check for interrupt */
|
|
|
|
|
static int reg_vm_check_interrupt(JSContext *ctx) {
|
|
|
|
|
JSRuntime *rt = ctx->rt;
|
|
|
|
|
if (--ctx->interrupt_counter <= 0) {
|
|
|
|
|
ctx->interrupt_counter = JS_INTERRUPT_COUNTER_INIT;
|
|
|
|
|
if (rt->interrupt_handler) {
|
|
|
|
|
if (rt->interrupt_handler(rt, rt->interrupt_opaque)) {
|
|
|
|
|
if (ctx->interrupt_handler) {
|
|
|
|
|
if (ctx->interrupt_handler(ctx->rt, ctx->interrupt_opaque)) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -33894,7 +33876,7 @@ void __asan_on_error(void) {
|
|
|
|
|
if (!ctx) return;
|
|
|
|
|
if (JS_IsNull(ctx->reg_current_frame)) return;
|
|
|
|
|
JSFrameRegister *frame = (JSFrameRegister *)JS_VALUE_GET_PTR(ctx->reg_current_frame);
|
|
|
|
|
uint32_t cur_pc = ctx->rt->current_register_pc;
|
|
|
|
|
uint32_t cur_pc = ctx->current_register_pc;
|
|
|
|
|
fprintf(stderr, "\n=== ASAN error: VM stack trace ===\n");
|
|
|
|
|
int is_first = 1;
|
|
|
|
|
while (frame) {
|
|
|
|
|
@@ -34018,7 +34000,7 @@ static JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
|
|
|
|
|
|
|
|
|
MachInstr32 instr = code->instructions[pc++];
|
|
|
|
|
ctx->reg_current_frame = frame_ref.val;
|
|
|
|
|
ctx->rt->current_register_pc = pc > 0 ? pc - 1 : 0;
|
|
|
|
|
ctx->current_register_pc = pc > 0 ? pc - 1 : 0;
|
|
|
|
|
int op = MACH_GET_OP(instr);
|
|
|
|
|
int a = MACH_GET_A(instr);
|
|
|
|
|
int b = MACH_GET_B(instr);
|
|
|
|
|
@@ -34347,7 +34329,7 @@ static JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
|
|
|
|
ctx->value_stack[vs_base + i] = frame->slots[base + 1 + i];
|
|
|
|
|
ctx->value_stack_top = vs_base + nargs;
|
|
|
|
|
ctx->reg_current_frame = frame_ref.val;
|
|
|
|
|
ctx->rt->current_register_pc = pc > 0 ? pc - 1 : 0;
|
|
|
|
|
ctx->current_register_pc = pc > 0 ? pc - 1 : 0;
|
|
|
|
|
JSValue ret = js_call_c_function(ctx, func_val, JS_NULL, nargs, &ctx->value_stack[vs_base]);
|
|
|
|
|
ctx->value_stack_top = vs_base;
|
|
|
|
|
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
|
|
|
|
@@ -34423,7 +34405,7 @@ static JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
|
|
|
|
ctx->value_stack[vs_base + 1] = frame->slots[base + 1]; /* the array */
|
|
|
|
|
ctx->value_stack_top = vs_base + 2;
|
|
|
|
|
ctx->reg_current_frame = frame_ref.val;
|
|
|
|
|
ctx->rt->current_register_pc = pc > 0 ? pc - 1 : 0;
|
|
|
|
|
ctx->current_register_pc = pc > 0 ? pc - 1 : 0;
|
|
|
|
|
JSValue ret = JS_CallInternal(ctx, frame->slots[base], JS_NULL, 2, &ctx->value_stack[vs_base], 0);
|
|
|
|
|
ctx->value_stack_top = vs_base;
|
|
|
|
|
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
|
|
|
|
@@ -34452,7 +34434,7 @@ static JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
|
|
|
|
ctx->value_stack[vs_base + i] = frame->slots[base + 2 + i];
|
|
|
|
|
ctx->value_stack_top = vs_base + nargs;
|
|
|
|
|
ctx->reg_current_frame = frame_ref.val;
|
|
|
|
|
ctx->rt->current_register_pc = pc > 0 ? pc - 1 : 0;
|
|
|
|
|
ctx->current_register_pc = pc > 0 ? pc - 1 : 0;
|
|
|
|
|
JSValue ret = js_call_c_function(ctx, method, frame->slots[base], nargs, &ctx->value_stack[vs_base]);
|
|
|
|
|
ctx->value_stack_top = vs_base;
|
|
|
|
|
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
|
|
|
|
@@ -34686,7 +34668,7 @@ done:
|
|
|
|
|
ctx->reg_current_frame = JS_NULL;
|
|
|
|
|
if (JS_IsException(result)) {
|
|
|
|
|
ctx->reg_current_frame = frame_ref.val;
|
|
|
|
|
ctx->rt->current_register_pc = pc > 0 ? pc - 1 : 0;
|
|
|
|
|
ctx->current_register_pc = pc > 0 ? pc - 1 : 0;
|
|
|
|
|
}
|
|
|
|
|
JS_DeleteGCRef(ctx, &frame_ref);
|
|
|
|
|
return result;
|
|
|
|
|
@@ -37606,7 +37588,7 @@ static JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
|
|
|
|
|
}
|
|
|
|
|
ctx->value_stack_top = vs_base + c_argc;
|
|
|
|
|
ctx->reg_current_frame = frame_ref.val;
|
|
|
|
|
ctx->rt->current_register_pc = pc > 0 ? pc - 1 : 0;
|
|
|
|
|
ctx->current_register_pc = pc > 0 ? pc - 1 : 0;
|
|
|
|
|
JSValue c_result = JS_Call(ctx, new_frame->function, new_frame->slots[0], c_argc, &ctx->value_stack[vs_base]);
|
|
|
|
|
ctx->value_stack_top = vs_base;
|
|
|
|
|
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
|
|
|
|
@@ -37651,7 +37633,7 @@ static JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
|
|
|
|
|
ctx->value_stack[vs_base + 1] = frame->slots[dest];
|
|
|
|
|
ctx->value_stack_top = vs_base + 2;
|
|
|
|
|
ctx->reg_current_frame = frame_ref.val;
|
|
|
|
|
ctx->rt->current_register_pc = pc > 0 ? pc - 1 : 0;
|
|
|
|
|
ctx->current_register_pc = pc > 0 ? pc - 1 : 0;
|
|
|
|
|
JSValue ret = JS_CallInternal(ctx, frame->slots[obj_reg], JS_NULL, 2, &ctx->value_stack[vs_base], 0);
|
|
|
|
|
ctx->value_stack_top = vs_base;
|
|
|
|
|
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
|
|
|
|
@@ -37703,7 +37685,7 @@ static JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
|
|
|
|
|
}
|
|
|
|
|
ctx->value_stack_top = vs_base + nargs;
|
|
|
|
|
ctx->reg_current_frame = frame_ref.val;
|
|
|
|
|
ctx->rt->current_register_pc = pc > 0 ? pc - 1 : 0;
|
|
|
|
|
ctx->current_register_pc = pc > 0 ? pc - 1 : 0;
|
|
|
|
|
JSValue ret = JS_Call(ctx, method, frame->slots[obj_reg], nargs, &ctx->value_stack[vs_base]);
|
|
|
|
|
ctx->value_stack_top = vs_base;
|
|
|
|
|
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
|
|
|
|
@@ -37747,7 +37729,7 @@ static JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
|
|
|
|
|
ctx->value_stack[vs_base + 1] = frame->slots[dest];
|
|
|
|
|
ctx->value_stack_top = vs_base + 2;
|
|
|
|
|
ctx->reg_current_frame = frame_ref.val;
|
|
|
|
|
ctx->rt->current_register_pc = pc > 0 ? pc - 1 : 0;
|
|
|
|
|
ctx->current_register_pc = pc > 0 ? pc - 1 : 0;
|
|
|
|
|
JSValue ret = JS_CallInternal(ctx, frame->slots[obj_reg], JS_NULL, 2, &ctx->value_stack[vs_base], 0);
|
|
|
|
|
ctx->value_stack_top = vs_base;
|
|
|
|
|
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
|
|
|
|
@@ -37797,7 +37779,7 @@ static JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
|
|
|
|
|
}
|
|
|
|
|
ctx->value_stack_top = vs_base + nargs;
|
|
|
|
|
ctx->reg_current_frame = frame_ref.val;
|
|
|
|
|
ctx->rt->current_register_pc = pc > 0 ? pc - 1 : 0;
|
|
|
|
|
ctx->current_register_pc = pc > 0 ? pc - 1 : 0;
|
|
|
|
|
JSValue ret = JS_Call(ctx, method, frame->slots[obj_reg], nargs, &ctx->value_stack[vs_base]);
|
|
|
|
|
ctx->value_stack_top = vs_base;
|
|
|
|
|
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
|
|
|
|
@@ -37897,7 +37879,7 @@ static JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
|
|
|
|
|
}
|
|
|
|
|
ctx->value_stack_top = vs_base + len;
|
|
|
|
|
ctx->reg_current_frame = frame_ref.val;
|
|
|
|
|
ctx->rt->current_register_pc = pc > 0 ? pc - 1 : 0;
|
|
|
|
|
ctx->current_register_pc = pc > 0 ? pc - 1 : 0;
|
|
|
|
|
result = JS_Call(ctx, frame->slots[func_slot], JS_NULL, len, &ctx->value_stack[vs_base]);
|
|
|
|
|
ctx->value_stack_top = vs_base;
|
|
|
|
|
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
|
|
|
|
@@ -38091,7 +38073,7 @@ static JSValue mcode_exec(JSContext *ctx, JSMCode *code, JSValue this_obj,
|
|
|
|
|
done:
|
|
|
|
|
if (JS_IsException(result)) {
|
|
|
|
|
ctx->reg_current_frame = frame_ref.val;
|
|
|
|
|
ctx->rt->current_register_pc = pc > 0 ? pc - 1 : 0;
|
|
|
|
|
ctx->current_register_pc = pc > 0 ? pc - 1 : 0;
|
|
|
|
|
}
|
|
|
|
|
JS_DeleteGCRef(ctx, &frame_ref);
|
|
|
|
|
return result;
|
|
|
|
|
@@ -38099,10 +38081,9 @@ done:
|
|
|
|
|
|
|
|
|
|
/* Public API: get stack trace as cJSON array */
|
|
|
|
|
cJSON *JS_GetStack(JSContext *ctx) {
|
|
|
|
|
JSRuntime *rt = ctx->rt;
|
|
|
|
|
if (JS_IsNull(ctx->reg_current_frame)) return NULL;
|
|
|
|
|
JSFrameRegister *frame = (JSFrameRegister *)JS_VALUE_GET_PTR(ctx->reg_current_frame);
|
|
|
|
|
uint32_t cur_pc = rt->current_register_pc;
|
|
|
|
|
uint32_t cur_pc = ctx->current_register_pc;
|
|
|
|
|
|
|
|
|
|
cJSON *arr = cJSON_CreateArray();
|
|
|
|
|
int is_first = 1;
|
|
|
|
|
|