mirror of
https://github.com/DoneJS-Runtime/quickjs-done-nextgen.git
synced 2025-01-09 17:43:15 +00:00
Optimize derived class construction (#753)
We were emitting gobs of inefficient bytecode that created an arguments array on the stack, then applied it to the parent constructor. Add a new opcode for initializing a derived class. Speeds up construction by 500%, although sadly that is not visible in the web-tooling-benchmark, only in micro-benchmarks. Fixes: https://github.com/quickjs-ng/quickjs/issues/752
This commit is contained in:
parent
6e434008f5
commit
5b609f15af
8 changed files with 22 additions and 33 deletions
Binary file not shown.
BIN
gen/hello.c
BIN
gen/hello.c
Binary file not shown.
Binary file not shown.
BIN
gen/repl.c
BIN
gen/repl.c
Binary file not shown.
BIN
gen/standalone.c
BIN
gen/standalone.c
Binary file not shown.
BIN
gen/test_fib.c
BIN
gen/test_fib.c
Binary file not shown.
|
@ -111,6 +111,7 @@ DEF( return, 1, 1, 0, none)
|
|||
DEF( return_undef, 1, 0, 0, none)
|
||||
DEF(check_ctor_return, 1, 1, 2, none)
|
||||
DEF( check_ctor, 1, 0, 0, none)
|
||||
DEF( init_ctor, 1, 0, 1, none)
|
||||
DEF( check_brand, 1, 2, 2, none) /* this_obj func -> this_obj func */
|
||||
DEF( add_brand, 1, 2, 0, none) /* this_obj home_obj -> */
|
||||
DEF( return_async, 1, 1, 0, none)
|
||||
|
|
54
quickjs.c
54
quickjs.c
|
@ -15412,10 +15412,27 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValue func_obj,
|
|||
BREAK;
|
||||
CASE(OP_check_ctor):
|
||||
if (JS_IsUndefined(new_target)) {
|
||||
non_ctor_call:
|
||||
JS_ThrowTypeError(ctx, "class constructors must be invoked with 'new'");
|
||||
goto exception;
|
||||
}
|
||||
BREAK;
|
||||
CASE(OP_init_ctor):
|
||||
{
|
||||
JSValue super, ret;
|
||||
sf->cur_pc = pc;
|
||||
if (JS_IsUndefined(new_target))
|
||||
goto non_ctor_call;
|
||||
super = JS_GetPrototype(ctx, func_obj);
|
||||
if (JS_IsException(super))
|
||||
goto exception;
|
||||
ret = JS_CallConstructor2(ctx, super, new_target, argc, argv);
|
||||
JS_FreeValue(ctx, super);
|
||||
if (JS_IsException(ret))
|
||||
goto exception;
|
||||
*sp++ = ret;
|
||||
}
|
||||
BREAK;
|
||||
CASE(OP_check_brand):
|
||||
{
|
||||
int ret = JS_CheckBrand(ctx, sp[-2], sp[-1]);
|
||||
|
@ -21896,9 +21913,6 @@ static __exception int js_parse_class_default_ctor(JSParseState *s,
|
|||
fd->has_this_binding = TRUE;
|
||||
fd->new_target_allowed = TRUE;
|
||||
|
||||
/* error if not invoked as a constructor */
|
||||
emit_op(s, OP_check_ctor);
|
||||
|
||||
push_scope(s); /* enter body scope */
|
||||
fd->body_scope = fd->scope_level;
|
||||
if (has_super) {
|
||||
|
@ -21906,43 +21920,17 @@ static __exception int js_parse_class_default_ctor(JSParseState *s,
|
|||
fd->super_call_allowed = TRUE;
|
||||
fd->arguments_allowed = TRUE;
|
||||
fd->has_arguments_binding = TRUE;
|
||||
|
||||
func_type = JS_PARSE_FUNC_DERIVED_CLASS_CONSTRUCTOR;
|
||||
/* super */
|
||||
emit_op(s, OP_scope_get_var);
|
||||
emit_atom(s, JS_ATOM_this_active_func);
|
||||
emit_u16(s, 0);
|
||||
|
||||
emit_op(s, OP_get_super);
|
||||
|
||||
emit_op(s, OP_scope_get_var);
|
||||
emit_atom(s, JS_ATOM_new_target);
|
||||
emit_u16(s, 0);
|
||||
|
||||
emit_op(s, OP_array_from);
|
||||
emit_u16(s, 0);
|
||||
emit_op(s, OP_push_i32);
|
||||
emit_u32(s, 0);
|
||||
|
||||
/* arguments */
|
||||
emit_op(s, OP_scope_get_var);
|
||||
emit_atom(s, JS_ATOM_arguments);
|
||||
emit_u16(s, 0);
|
||||
|
||||
emit_op(s, OP_append);
|
||||
/* drop the index */
|
||||
emit_op(s, OP_drop);
|
||||
|
||||
emit_op(s, OP_apply);
|
||||
emit_u16(s, 1);
|
||||
/* set the 'this' value */
|
||||
emit_op(s, OP_dup);
|
||||
emit_op(s, OP_init_ctor);
|
||||
// TODO(bnoordhuis) roll into OP_init_ctor
|
||||
emit_op(s, OP_scope_put_var_init);
|
||||
emit_atom(s, JS_ATOM_this);
|
||||
emit_u16(s, 0);
|
||||
emit_class_field_init(s);
|
||||
} else {
|
||||
func_type = JS_PARSE_FUNC_CLASS_CONSTRUCTOR;
|
||||
/* error if not invoked as a constructor */
|
||||
emit_op(s, OP_check_ctor);
|
||||
emit_class_field_init(s);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue