Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Handle bytecode without IC state #617

Merged
merged 3 commits into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 23 additions & 6 deletions quickjs-libc.c
Original file line number Diff line number Diff line change
Expand Up @@ -832,11 +832,13 @@ static JSValue js_evalScript(JSContext *ctx, JSValue this_val,
{
JSRuntime *rt = JS_GetRuntime(ctx);
JSThreadState *ts = JS_GetRuntimeOpaque(rt);
const char *str;
const char *str = NULL;
size_t len;
JSValue ret;
JSValue ret, obj;
JSValue options_obj;
BOOL backtrace_barrier = FALSE;
BOOL eval_function = FALSE;
BOOL compile_only = FALSE;
BOOL is_async = FALSE;
int flags;

Expand All @@ -845,24 +847,39 @@ static JSValue js_evalScript(JSContext *ctx, JSValue this_val,
if (get_bool_option(ctx, &backtrace_barrier, options_obj,
"backtrace_barrier"))
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,
"compile_only"))
return JS_EXCEPTION;
if (get_bool_option(ctx, &is_async, options_obj,
"async"))
return JS_EXCEPTION;
}

str = JS_ToCStringLen(ctx, &len, argv[0]);
if (!str)
return JS_EXCEPTION;
if (!eval_function) {
str = JS_ToCStringLen(ctx, &len, argv[0]);
if (!str)
return JS_EXCEPTION;
}
if (!ts->recv_pipe && ++ts->eval_script_recurse == 1) {
/* install the interrupt handler */
JS_SetInterruptHandler(JS_GetRuntime(ctx), interrupt_handler, NULL);
}
flags = JS_EVAL_TYPE_GLOBAL;
if (backtrace_barrier)
flags |= JS_EVAL_FLAG_BACKTRACE_BARRIER;
if (compile_only)
flags |= JS_EVAL_FLAG_COMPILE_ONLY;
if (is_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);
if (!ts->recv_pipe && --ts->eval_script_recurse == 0) {
/* remove the interrupt handler */
Expand Down
43 changes: 24 additions & 19 deletions quickjs.c
Original file line number Diff line number Diff line change
Expand Up @@ -7362,9 +7362,8 @@ static JSValue JS_GetPropertyInternal2(JSContext *ctx, JSValue obj,
continue;
}
} else {
if (icu && proto_depth == 0 && p->shape->is_hashed) {
if (proto_depth == 0)
add_ic_slot(ctx, icu, prop, p, offset);
}
return js_dup(pr->u.value);
}
}
Expand Down Expand Up @@ -8658,9 +8657,7 @@ static int JS_SetPropertyInternal2(JSContext *ctx, JSValue obj, JSAtom prop,
if (likely((prs->flags & (JS_PROP_TMASK | JS_PROP_WRITABLE |
JS_PROP_LENGTH)) == JS_PROP_WRITABLE)) {
/* 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);
return TRUE;
} else if (prs->flags & JS_PROP_LENGTH) {
Expand Down Expand Up @@ -35019,7 +35016,8 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s)
goto fail;
if (b->source_len) {
bc_read_trace(s, "source: %d bytes\n", b->source_len);
s->ptr_last += b->source_len; // omit source code hex dump
if (s->ptr_last)
s->ptr_last += b->source_len; // omit source code hex dump
/* b->source is a UTF-8 encoded null terminated C string */
b->source = js_mallocz(ctx, b->source_len + 1);
if (!b->source)
Expand Down Expand Up @@ -35472,12 +35470,14 @@ static JSValue JS_ReadObjectRec(BCReaderState *s)
break;
case BC_TAG_FUNCTION_BYTECODE:
if (!s->allow_bytecode)
goto invalid_tag;
goto no_allow_bytecode;
obj = JS_ReadFunctionTag(s);
break;
case BC_TAG_MODULE:
if (!s->allow_bytecode)
goto invalid_tag;
if (!s->allow_bytecode) {
no_allow_bytecode:
return JS_ThrowSyntaxError(ctx, "no bytecode allowed");
}
obj = JS_ReadModule(s);
break;
case BC_TAG_OBJECT:
Expand Down Expand Up @@ -54513,10 +54513,19 @@ static void add_ic_slot(JSContext *ctx, JSInlineCacheUpdate *icu,
{
int32_t i;
uint32_t h;
JSInlineCache *ic = icu->ic;
JSInlineCacheHashSlot *ch;
JSInlineCacheRingSlot *cr;
JSInlineCache *ic;
JSShape *sh;

if (!icu)
return;
ic = icu->ic;
if (!ic)
return;
sh = object->shape;
if (!sh->is_hashed)
return;
cr = NULL;
h = get_index_hash(atom, ic->hash_bits);
for (ch = ic->hash[h]; ch != NULL; ch = ch->next) {
Expand All @@ -54525,21 +54534,17 @@ static void add_ic_slot(JSContext *ctx, JSInlineCacheUpdate *icu,
break;
}
}

assert(cr != NULL);
i = cr->index;
for (;;) {
if (object->shape == cr->shape[i]) {
do {
if (sh == cr->shape[i]) {
cr->prop_offset[i] = prop_offset;
goto end;
}
i = (i + 1) % countof(cr->shape);
if (unlikely(i == cr->index))
break;
}
sh = cr->shape[i];
cr->shape[i] = js_dup_shape(object->shape);
js_free_shape_null(ctx->rt, sh);
} while (i != cr->index);
js_free_shape_null(ctx->rt, cr->shape[i]);
cr->shape[i] = js_dup_shape(sh);
cr->prop_offset[i] = prop_offset;
end:
icu->offset = ch->index;
Expand Down
21 changes: 21 additions & 0 deletions tests/test_bjson.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import * as std from "std";
import * as bjson from "bjson";
import { assert } from "./assert.js";

Expand Down Expand Up @@ -227,6 +228,25 @@ function bjson_test_symbol()
assert(o, r);
}

function bjson_test_bytecode()
{
var buf, o, r, e, i;

o = std.evalScript(";(function f(o){ return o.i })", {compile_only: true});
buf = bjson.write(o, /*JS_WRITE_OBJ_BYTECODE*/(1 << 0));
try {
bjson.read(buf, 0, buf.byteLength);
} catch (_e) {
e = _e;
}
assert(String(e), "SyntaxError: no bytecode allowed");

o = bjson.read(buf, 0, buf.byteLength, /*JS_READ_OBJ_BYTECODE*/(1 << 0));
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()
{
var corpus = [
Expand Down Expand Up @@ -277,6 +297,7 @@ function bjson_test_all()
bjson_test_map();
bjson_test_set();
bjson_test_symbol();
bjson_test_bytecode();
bjson_test_fuzz();
}

Expand Down
Loading