diff --git a/quickjs-libc.c b/quickjs-libc.c index 3dcb4eb..ae82f3a 100644 --- a/quickjs-libc.c +++ b/quickjs-libc.c @@ -832,11 +832,12 @@ 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; @@ -846,6 +847,9 @@ 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; @@ -854,9 +858,11 @@ static JSValue js_evalScript(JSContext *ctx, JSValue this_val, 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); @@ -868,7 +874,12 @@ static JSValue js_evalScript(JSContext *ctx, JSValue this_val, flags |= JS_EVAL_FLAG_COMPILE_ONLY; if (is_async) flags |= JS_EVAL_FLAG_ASYNC; - ret = JS_Eval(ctx, str, len, "", 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, "", flags); + } JS_FreeCString(ctx, str); if (!ts->recv_pipe && --ts->eval_script_recurse == 0) { /* remove the interrupt handler */ diff --git a/quickjs.c b/quickjs.c index a998afe..ce6d85a 100644 --- a/quickjs.c +++ b/quickjs.c @@ -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); } } @@ -8658,9 +8657,7 @@ retry: 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) { @@ -54516,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) { @@ -54528,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; diff --git a/tests/test_bjson.js b/tests/test_bjson.js index 989310d..a957cee 100644 --- a/tests/test_bjson.js +++ b/tests/test_bjson.js @@ -230,7 +230,7 @@ function bjson_test_symbol() 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}); 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"); - // 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)); 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()