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.)
The intent of the spec is that the output of console.dir is interactable
within the console. Our Printer implementation currently just prints the
provided object as a string, and doesn't check the provided `options`
argument. But having console.dir defined prevents exceptions from being
thrown on real websites.
Many operations in JavaScript may incur side effects, including calling
arbitrary user code. Since the user code will clobber the accumulator,
we have to take care to extract anything we need from the accumulator
before doing anything that may have side effects.
Fixes 3 test262 tests. :^)
The fix for this was to port the "don't create unnecessary FooObject
for property access on primitives" optimization from Reference,
which also brings us the correct behavior.
Since we no longer need to create or leave var environments directly
in bytecode, we can streamline the two instructions by making them
always operate on the lexical environment.
Instead of implementing this AO in bytecode, we now have an instruction
for it that simply invokes the C++ implementation.
This allows us to simplify Bytecode::Generator quite a bit by removing
all the variable scope tracking.
Don't try to implement this AO in bytecode. Instead, the bytecode
Interpreter class now has a run() API with the same inputs as the AST
interpreter. It sets up the necessary environments etc, including
invoking the GlobalDeclarationInstantiation AO.
Instead of trying to implement this AO in bytecode, we can just let it
be a C++ thing. Once we implement fast uncaptured locals, we won't even
be calling it super often.
Note that this does not change cycle-detection.
This is also was an unnecessary copy, since there is an easier, less
memory-intense way to do cycle detection than copying the entire
visited_set all the time.
In GlobalEnvironment::get_binding_value(), we can avoid an extra walk
of the declarative environment record if has_binding() returns a
cacheable environment coordinate.
Most JS::Objects don't have lazily-allocated intrinsic properties,
so let's avoid doing hash lookups by putting a flag on JS::Object that
tells us whether it's present in s_intrinsics.
Takes CPU time spent in those hash lookups from 1-2.5% to nothing on
various JS heavy pages.
Previously we were unable to parse code like `yield/2` because `/2`
was parsed as a regex. At the same time `for (a in / b/)` was parsed
as a division.
This is solved by defaulting to division in the lexer, but calling
`force_slash_as_regex()` from the parser whenever an IdentifierName
is parsed as a ReservedWord.
This fixes an issue where private element values were not always
protected from GC. I found two instances where this was happening:
- ECMAScriptFunctionObject did not mark m_private_methods
- ClassDefinitionEvaluation had two Vector<PrivateElement> that were
opaque to the garbage collector, and so if GC occurred while
constructing a class instance, some or all of its private elements
could get incorrectly collected.
Made a slight logic error in 95d69fc which meant the dummy range would
be returned even if the source_range_storage contained an actual source
range. This corrects that by resolving the null unrealized range to a
dummy range, and storing that. It then can be treated as a normal source
range.
Previously, source_range() could crash attempting to read from a null
unrealized->source_code pointer. It looks like the previous behaviour
here was to return a dummy source range, so this commit restores that.
With this loading https://github.com/SerenityOS/serenity works again.
Instead of eagerly populating the stack trace with a textual
representation of every call frame, just store the raw source code range
(code, start offset, end offset). From that, we can generate the full
rich backtrace when requested, and save ourselves the trouble otherwise.
This makes test-wasm take ~7 seconds on my machine instead of ~60. :^)