If the exception from the `try` block has already been caught by
`catch`, we need to clear the saved exception before entering `finally`
so that ContinuePendingUnwind will not re-throw it.
9 new passes on test262 :^)
CreateVariable is not needed for locals because they are not stored in
environment and created binding will not be used. Also if all variables
in loop initialization sections are local then CreateLexicalEnvironment
and LeaveLexicalEnvironment can also be ommitted.
The RegExpLiteral AST node already has the parsed regex::Parser::Result
so let's plumb that over to the bytecode executable instead of reparsing
the regex every time NewRegExp is executed.
~12% speed-up on language/literals/regexp/S7.8.5_A2.1_T2.js in test262.
This optimization was no longer helpful after the bug fix for missing
invalidation on global delete was introduced in 331f6a9e6, since we
now have to check bindings for presence in the global environment every
time anyway.
Since the bytecode VM now has fast GetGlobal in most cases, let's not
even worry about this and just remove the unhelpful "optimization".
In fact, removing this is actually an *optimization*, since we avoid
a redundant has_binding() check on every global variable access. :^)
Using mmap was quite punishing on inputs with lots of basic blocks,
such as test262 tests with eval() in a loop that goes 64k times..
~27% speed-up on language/literals/regexp/S7.8.5_A2.1_T2.js but
presumably everything everywhere will benefit from this. :^)
Using a special instruction to access global variables allows skipping
the environment chain traversal for them and going directly to the
module/global environment. Currently, this instruction only caches the
offset for bindings that belong to the global object environment.
However, there is also an opportunity to cache the offset in the global
declarative record.
This change results in a 57% increase in speed for
imaging-gaussian-blur.js in Kraken.
Since we can't rely on shape identity (i.e its pointer address) for
unique shapes, give them a serial number that increments whenever a
mutation occurs.
Inline caches can then compare this serial number against what they
have seen before.
When building an object from an object expression, we don't want to
go through the full property setting machinery. This patch adds a new
PropertyKind::DirectKeyValue for PutById which guarantees that the
property becomes an own property.
This fixes an issue where setting the "__proto__" property in object
expressions wasn't working right.
12 new passes on test262. :^)
The instructions GetById and GetByIdWithThis now remember the last-seen
Shape, and if we see the same object again, we reuse the property offset
from last time without doing a new lookup.
This allows us to use Object::get_direct(), bypassing the entire lookup
machinery and saving lots of time.
~23% speed-up on Kraken/ai-astar.js :^)
Since it is not possible for delete operator to return true when it is
applied to local variable, DeleteVariable can safely always return
false for locals.
This also fixes operators/delete-local-variable.js in test-js.
Converting a base value to an Object is performed by Reference::delete_.
Doing this early in the bytecode operator could be observable, although
it would likely be the first observable step in Reference::delete_
anyways. This will just align these operators with upcoming operators
for super references, where doing this coercion first will be observable
(we need to throw an exception for deleting a super property before this
coercion).
Invariants 5 and 6 of the `EnumerateObjectProperties` AO mean that we
must not include an enumerate property if there is a non-enumerable
property higher up the prototype chain with the same name. The previous
implementation did not adhere to this, as `EnumerableOwnPropertyNames`
does not carry information about present but non-enumerable properties.
This is part of an old normative change that happened soon after
Andreas made `super` closer to spec in 1270df2.
See https://github.com/tc39/ecma262/pull/2267/
This was introduced into bytecode by virtue of copy and paste :^)
Bytecode results:
Summary:
Diff Tests:
+2 ✅ -2 ❌
- Update ECMAScriptFunctionObject::function_declaration_instantiation
to initialize local variables
- Introduce GetLocal, SetLocal, TypeofLocal that will be used to
operate on local variables.
- Update bytecode generator to emit instructions for local variables
Saving vector of local variables names in ECMAScriptFunctionObject
will allow to get a name by index in case message of ReferenceError
needs to contain a variable name.
By using Identifier class to represent the name of a class expression,
it becomes possible to consistently store information within the
identifier object, indicating whether the name refers to a local
variable or not.
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