mirror of
https://github.com/DoneJS-Runtime/quickjs-done-nextgen.git
synced 2025-01-09 17:43:15 +00:00
Handle bytecode without IC state
Deserialized bytecode does not have IC state, i.e., `bc->ic == NULL`. That may or may not be bug (IMO, it is and we should rebuild the IC state during deserialization) but, either way, don't segfault. DRY add_ic_slot() and its call sites in a hopefully NFC manner.
This commit is contained in:
parent
0a79b84ef9
commit
caa1bf544d
3 changed files with 37 additions and 24 deletions
|
@ -832,11 +832,12 @@ static JSValue js_evalScript(JSContext *ctx, JSValue this_val,
|
||||||
{
|
{
|
||||||
JSRuntime *rt = JS_GetRuntime(ctx);
|
JSRuntime *rt = JS_GetRuntime(ctx);
|
||||||
JSThreadState *ts = JS_GetRuntimeOpaque(rt);
|
JSThreadState *ts = JS_GetRuntimeOpaque(rt);
|
||||||
const char *str;
|
const char *str = NULL;
|
||||||
size_t len;
|
size_t len;
|
||||||
JSValue ret;
|
JSValue ret, obj;
|
||||||
JSValue options_obj;
|
JSValue options_obj;
|
||||||
BOOL backtrace_barrier = FALSE;
|
BOOL backtrace_barrier = FALSE;
|
||||||
|
BOOL eval_function = FALSE;
|
||||||
BOOL compile_only = FALSE;
|
BOOL compile_only = FALSE;
|
||||||
BOOL is_async = FALSE;
|
BOOL is_async = FALSE;
|
||||||
int flags;
|
int flags;
|
||||||
|
@ -846,6 +847,9 @@ static JSValue js_evalScript(JSContext *ctx, JSValue this_val,
|
||||||
if (get_bool_option(ctx, &backtrace_barrier, options_obj,
|
if (get_bool_option(ctx, &backtrace_barrier, options_obj,
|
||||||
"backtrace_barrier"))
|
"backtrace_barrier"))
|
||||||
return JS_EXCEPTION;
|
return JS_EXCEPTION;
|
||||||
|
if (get_bool_option(ctx, &eval_function, options_obj,
|
||||||
|
"eval_function"))
|
||||||
|
return JS_EXCEPTION;
|
||||||
if (get_bool_option(ctx, &compile_only, options_obj,
|
if (get_bool_option(ctx, &compile_only, options_obj,
|
||||||
"compile_only"))
|
"compile_only"))
|
||||||
return JS_EXCEPTION;
|
return JS_EXCEPTION;
|
||||||
|
@ -854,9 +858,11 @@ static JSValue js_evalScript(JSContext *ctx, JSValue this_val,
|
||||||
return JS_EXCEPTION;
|
return JS_EXCEPTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
str = JS_ToCStringLen(ctx, &len, argv[0]);
|
if (!eval_function) {
|
||||||
if (!str)
|
str = JS_ToCStringLen(ctx, &len, argv[0]);
|
||||||
return JS_EXCEPTION;
|
if (!str)
|
||||||
|
return JS_EXCEPTION;
|
||||||
|
}
|
||||||
if (!ts->recv_pipe && ++ts->eval_script_recurse == 1) {
|
if (!ts->recv_pipe && ++ts->eval_script_recurse == 1) {
|
||||||
/* install the interrupt handler */
|
/* install the interrupt handler */
|
||||||
JS_SetInterruptHandler(JS_GetRuntime(ctx), interrupt_handler, NULL);
|
JS_SetInterruptHandler(JS_GetRuntime(ctx), interrupt_handler, NULL);
|
||||||
|
@ -868,7 +874,12 @@ static JSValue js_evalScript(JSContext *ctx, JSValue this_val,
|
||||||
flags |= JS_EVAL_FLAG_COMPILE_ONLY;
|
flags |= JS_EVAL_FLAG_COMPILE_ONLY;
|
||||||
if (is_async)
|
if (is_async)
|
||||||
flags |= JS_EVAL_FLAG_ASYNC;
|
flags |= JS_EVAL_FLAG_ASYNC;
|
||||||
ret = JS_Eval(ctx, str, len, "<evalScript>", flags);
|
if (eval_function) {
|
||||||
|
obj = JS_DupValue(ctx, argv[0]);
|
||||||
|
ret = JS_EvalFunction(ctx, obj); // takes ownership of |obj|
|
||||||
|
} else {
|
||||||
|
ret = JS_Eval(ctx, str, len, "<evalScript>", flags);
|
||||||
|
}
|
||||||
JS_FreeCString(ctx, str);
|
JS_FreeCString(ctx, str);
|
||||||
if (!ts->recv_pipe && --ts->eval_script_recurse == 0) {
|
if (!ts->recv_pipe && --ts->eval_script_recurse == 0) {
|
||||||
/* remove the interrupt handler */
|
/* remove the interrupt handler */
|
||||||
|
|
32
quickjs.c
32
quickjs.c
|
@ -7362,9 +7362,8 @@ static JSValue JS_GetPropertyInternal2(JSContext *ctx, JSValue obj,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (icu && proto_depth == 0 && p->shape->is_hashed) {
|
if (proto_depth == 0)
|
||||||
add_ic_slot(ctx, icu, prop, p, offset);
|
add_ic_slot(ctx, icu, prop, p, offset);
|
||||||
}
|
|
||||||
return js_dup(pr->u.value);
|
return js_dup(pr->u.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8658,9 +8657,7 @@ retry:
|
||||||
if (likely((prs->flags & (JS_PROP_TMASK | JS_PROP_WRITABLE |
|
if (likely((prs->flags & (JS_PROP_TMASK | JS_PROP_WRITABLE |
|
||||||
JS_PROP_LENGTH)) == JS_PROP_WRITABLE)) {
|
JS_PROP_LENGTH)) == JS_PROP_WRITABLE)) {
|
||||||
/* fast case */
|
/* fast case */
|
||||||
if (icu && p->shape->is_hashed) {
|
add_ic_slot(ctx, icu, prop, p, offset);
|
||||||
add_ic_slot(ctx, icu, prop, p, offset);
|
|
||||||
}
|
|
||||||
set_value(ctx, &pr->u.value, val);
|
set_value(ctx, &pr->u.value, val);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
} else if (prs->flags & JS_PROP_LENGTH) {
|
} else if (prs->flags & JS_PROP_LENGTH) {
|
||||||
|
@ -54516,10 +54513,19 @@ static void add_ic_slot(JSContext *ctx, JSInlineCacheUpdate *icu,
|
||||||
{
|
{
|
||||||
int32_t i;
|
int32_t i;
|
||||||
uint32_t h;
|
uint32_t h;
|
||||||
JSInlineCache *ic = icu->ic;
|
|
||||||
JSInlineCacheHashSlot *ch;
|
JSInlineCacheHashSlot *ch;
|
||||||
JSInlineCacheRingSlot *cr;
|
JSInlineCacheRingSlot *cr;
|
||||||
|
JSInlineCache *ic;
|
||||||
JSShape *sh;
|
JSShape *sh;
|
||||||
|
|
||||||
|
if (!icu)
|
||||||
|
return;
|
||||||
|
ic = icu->ic;
|
||||||
|
if (!ic)
|
||||||
|
return;
|
||||||
|
sh = object->shape;
|
||||||
|
if (!sh->is_hashed)
|
||||||
|
return;
|
||||||
cr = NULL;
|
cr = NULL;
|
||||||
h = get_index_hash(atom, ic->hash_bits);
|
h = get_index_hash(atom, ic->hash_bits);
|
||||||
for (ch = ic->hash[h]; ch != NULL; ch = ch->next) {
|
for (ch = ic->hash[h]; ch != NULL; ch = ch->next) {
|
||||||
|
@ -54528,21 +54534,17 @@ static void add_ic_slot(JSContext *ctx, JSInlineCacheUpdate *icu,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(cr != NULL);
|
assert(cr != NULL);
|
||||||
i = cr->index;
|
i = cr->index;
|
||||||
for (;;) {
|
do {
|
||||||
if (object->shape == cr->shape[i]) {
|
if (sh == cr->shape[i]) {
|
||||||
cr->prop_offset[i] = prop_offset;
|
cr->prop_offset[i] = prop_offset;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
i = (i + 1) % countof(cr->shape);
|
i = (i + 1) % countof(cr->shape);
|
||||||
if (unlikely(i == cr->index))
|
} while (i != cr->index);
|
||||||
break;
|
js_free_shape_null(ctx->rt, cr->shape[i]);
|
||||||
}
|
cr->shape[i] = js_dup_shape(sh);
|
||||||
sh = cr->shape[i];
|
|
||||||
cr->shape[i] = js_dup_shape(object->shape);
|
|
||||||
js_free_shape_null(ctx->rt, sh);
|
|
||||||
cr->prop_offset[i] = prop_offset;
|
cr->prop_offset[i] = prop_offset;
|
||||||
end:
|
end:
|
||||||
icu->offset = ch->index;
|
icu->offset = ch->index;
|
||||||
|
|
|
@ -230,7 +230,7 @@ function bjson_test_symbol()
|
||||||
|
|
||||||
function bjson_test_bytecode()
|
function bjson_test_bytecode()
|
||||||
{
|
{
|
||||||
var buf, o, r, e;
|
var buf, o, r, e, i;
|
||||||
|
|
||||||
o = std.evalScript(";(function f(o){ return o.i })", {compile_only: true});
|
o = std.evalScript(";(function f(o){ return o.i })", {compile_only: true});
|
||||||
buf = bjson.write(o, /*JS_WRITE_OBJ_BYTECODE*/(1 << 0));
|
buf = bjson.write(o, /*JS_WRITE_OBJ_BYTECODE*/(1 << 0));
|
||||||
|
@ -241,10 +241,10 @@ function bjson_test_bytecode()
|
||||||
}
|
}
|
||||||
assert(String(e), "SyntaxError: no bytecode allowed");
|
assert(String(e), "SyntaxError: no bytecode allowed");
|
||||||
|
|
||||||
// can't really do anything with |o| at the moment,
|
|
||||||
// no way to pass it to JS_EvalFunction
|
|
||||||
o = bjson.read(buf, 0, buf.byteLength, /*JS_READ_OBJ_BYTECODE*/(1 << 0));
|
o = bjson.read(buf, 0, buf.byteLength, /*JS_READ_OBJ_BYTECODE*/(1 << 0));
|
||||||
assert(String(o), "[function bytecode]");
|
assert(String(o), "[function bytecode]");
|
||||||
|
o = std.evalScript(o, {eval_function: true});
|
||||||
|
for (i = 0; i < 42; i++) o({i}); // exercise o.i IC
|
||||||
}
|
}
|
||||||
|
|
||||||
function bjson_test_fuzz()
|
function bjson_test_fuzz()
|
||||||
|
|
Loading…
Reference in a new issue