This makes the behavior of `Symbol` correct in strict mode, wherein if
the receiver is a symbol primitive, assigning new properties should
throw a TypeError.
This avoids the overhead of allocating a new Array on every function
call, saving a substantial amount of time and avoiding GC thrash.
This patch only makes use of Op::Call in CallExpression. There are other
places we should codegen this op. We should also do the same for super
expression calls.
~5% speed-up on Kraken/stanford-crypto-ccm.js
Forcing every function call to allocate a new Array just to accommodate
spread parameters is not very nice, so let's start moving towards making
this a special case rather than the general (and only) case.
The var environments will unwind as needed with the ExecutionContext
and there's no need to include it in the unwind info.
We still need to do this for lexical environments though, since they
can have short local lifetimes inside a function.
Since the relationship between VM and Bytecode::Interpreter is now
clear, we can have VM ask the Interpreter for roots in the GC marking
pass. This avoids having to register and unregister handles and
MarkedVectors over and over.
Since GeneratorObject can also own a RegisterWindow, we share the code
in a RegisterWindow::visit_edges() helper.
~4% speed-up on Kraken/stanford-crypto-ccm.js :^)
While the completion value of a variable declaration is specified to be
empty, we might already have a completion value in the accumulator from
a previous statement. Preserve it so as to avoid clobbering it.
This fixes 6 tests on test262.
This makes them trivially copyable, which is an assumption multiple
optimizations use when rebuilding the instruction stream.
This fixes most optimized crashes in the test262 suite.
We do this by moving the `LoadImmediate undefined` instruction to a
separate basic block which jumps to the case's block unconditionally.
We enter a case initially using this wrapper, but when falling through,
we directly jump to the next case's block.
This adds support for exporting class expressions, which was previously
TODO'd.
We now correctly set the binding name of exports to `"*default*"` if
they are unnamed. I'm not sure what the difference between the
`InitializationMode` kinds is, but using `Initialize` fixes a bunch of
tests.
Note that some export tests (e.g. `eval-export-dflt-expr-cls-named.js`)
still fail, as we don't set the "name" property of exported classes
correctly.
176 new passes on test262
While this would be useful in the future for implementing a multi-tiered
optimization strategy, currently a binary on/off is enough for us. This
removes the confusingly on-by-default `OptimizationLevel::None` option
which made the optimization pipeline a no-op even if
`Bytecode::Interpreter::set_optimizations_enabled` had been called.
Fixes#15982
This is in preparation for an upcoming implementation of the Iterator
Helpers proposal. That proposal will require a JS::Object type named
"Iterator", so this rename is to avoid conflicts.
The fact that side effects clobbers the accumulator isn't just annoying
inside the instruction handler, but also really counter-intuitive in
the bytecode program itself.
17 new passes on test262. :^)
Instead of assuming that there's an active AST interpreter, this code
now takes VM& everywhere and invokes the appropriate interpreter.
92 new passes on test262. :^)
The JS::VM now owns the one Bytecode::Interpreter. We no longer have
multiple bytecode interpreters, and there is no concept of a "current"
bytecode interpreter.
If you ask for VM::bytecode_interpreter_if_exists(), it will return null
if we're not running the program in "bytecode enabled" mode.
If you ask for VM::bytecode_interpreter(), it will return a bytecode
interpreter in all modes. This is used for situations where even the AST
interpreter switches to bytecode mode (generators, etc.)