This patch triggers the collector when allocated memory doubles instead
of every 100k allocations. Which can almost half (reduce by ~48%) the
time spent on collection when loading google-maps.
This dynamic approach is inspired by some other GCs like Golang's and
Lua's and improves performance in memory heavy applications because
marking must visit old objects which will dominate the marking phase if
the GC is invoked too often.
This commit also improves the Octane Splay benchmark and almost
doubles it :^)
This makes it easy to set up a realm, global object and root execution
context with a single call to LibJS. It will be useful to basically
everyone except LibWeb.
When determining the precedence of the + and - operators, the parser
always returned the precedence using these operators in a binary
expression (lower than division!). The context of whether the operator
is used in a unary or binary expression must be taken into account.
This invariant is enforced by the fact that `NonnullGCPtr` can only be
constructed from references.
This commit fixes an instance where we compared a pointer to null after
we have already dereferenced it.
The compiler-generated copy constructor and copy assignment operator
already do the right thing (which is to simply copy the underlying
pointer).
The [Itanium C++ ABI][1] treats any class with non-trivial copy/move
constructors and destructors as non-trivial for the purposes of calls --
even if they are functionally identical to the compiler-generated ones.
If a class is non-trivial, it cannot be passed or returned in registers,
only via an invisible reference, which is worse for codegen. This commit
makes `{Nonnull,}GCPtr` trivial.
As the compiler can be sure that capturing a `GCPtr` by value has no
side effects, a few `-Wunused-lambda-capture` warnings had to be
addressed in LibWeb.
GCC seems to have a bug that prevents `ExceptionOr<Variant<GCPtr<T>>>`
from being implicitly constructed from `GCPtr<T>` after this change. A
non-invasive workaround is to explicitly construct the inner Variant
type.
[1]: https://itanium-cxx-abi.github.io/cxx-abi/abi.html#non-trivial
This loosens the connection to the AST interpreter and will allow us to
generate SourceRanges for the Bytecode interpreter in the future as well
Moves UnrealizedSourceRanges from TracebackFrame to the JS namespace for
this
If we're inside of a `with` statement scope, we have to take care to
extract the correct `this` value for use in calls when calling a method
on the binding object via an Identifier instead of a MemberExpression.
This makes Vue.js work way better in the bytecode VM. :^)
Also, 1 new pass on test262.
The first test crashes in AST, and fails in bytecode, so the best thing
which we can do here without complicated test setup logic is to just
skip this test for now. Interestinglny, this crashing test is very
similar to the existing thenable test case, and only differs in the way
that the thenable is given to the async function.
The next two tests are effectively the same as the above two mentioned
tests, with the only different being that the thenable calls the fulfill
function. For the test case that crashes in AST mode, doing that appears
to fix the test case for AST mode (but both still fail in bytecode).
Because "this" value cannot be changed during function execution it is
safe to compute it once and then use for future access.
This optimization makes ai-astar.js run 8% faster.
To allow us to add tests that are failing now, but can be enabled as
soon as a change is made to make it pass (without any opportunity to
forget about enabling it).
Additionally, support is added for `xfailIf`, for tests that are
expected to fail given a certain condition, but are expected to pass
otherwise. This is intended to be used for tests that fail in bytecode
mode, but pass in AST (and vice versa).
This is a normative change in the ECMA-402 spec. See:
https://github.com/tc39/ecma402/commit/02bd03a
This is observable just due to reading the properties one less time. It
would have been possible for e.g. the property values to change between
those invocations.
This fixes an issue where returning inside a `try` block and then
calling a function inside `finally` would clobber the saved return
value from the `try` block.
Note that we didn't need to change the base of register allocation,
since it was already 1 too high.
With this fixed, https://microsoft.com/edge loads in bytecode mode. :^)
Thanks to Luke for reducing the issue!
These passes have not been shown to actually optimize any JS, and tests
have become very flaky with optimizations enabled. Until some measurable
benefit is shown, remove the optimization passes to reduce overhead of
maintaining bytecode operations and to reduce CI churn. The framework
for optimizations will live on in git history, and can be restored once
proven useful.
The Heap::uproot_cell() API was used to implement markAsGarbage() which
was used in 3 tests to forcibly destroy a value, even if it had
references on the stack or elsewhere.
This patch rewrites the 3 tests that used this mechanism to be
structured in a way that allows garbage collection to collect the values
as intended without hacks. And now that the uprooting mechanism is no
longer needed, it's uprooted as well.
This fixes 3 test-js tests in bytecode mode. :^)
We had an edge case where calls to eval() left the environment untainted
*if* `eval` had also been declared as a local variable in the same
parsing context.
This broke the expected direct eval behavior when the variable `eval`
was still pointing at the global `eval` function.
This patch fixes the issue by simply always tainting the environment
when a call to something named `eval` is encountered. It doesn't seem
worth worrying about optimizing the case where someone is calling their
own function named `eval`..
Fixes 1 test-js test in bytecode mode. :^)
GetByValue now shares code with GetById to elide the synthetic wrapper
objects for primitive values in strict mode.
Fixes 2 test-js tests in bytecode mode. :^)
This is just something I spotted looking around the code, previously
the PassPipelineExecutable was passed by value to
generate_cfg_for_block, which generated the CFG then just dropped it on
the floor. Making this a reference results in the CFG actually getting
generated.