The Bytecode::Interpreter will push a global call frame if needed,
and it needs to make sure that call frame survives until the end
of the Interpreter::run() function.
Unlike the convoluted unwind-until-scope-type mechanism in the AST
interpreter, "continue" maps to a simple Bytecode::Op::Jump here. :^)
We know where to jump based on a stack of "continuable scopes" that
we now maintain on the Bytecode::Generator as we go.
Note that this only supports bare "continue", not continue-with-label.
This also required making Bytecode::Op::Jump support lazy linking
to a target label.
I left a FIXME here about having the "if" statement return the result
value from the taken branch statement. That's what the AST interpreter
does but I'm not sure if it's actually required.
If there's a current Bytecode::Interpreter in action, ScriptFunction
will now compile itself into bytecode and execute in that context.
This patch also adds the Return bytecode instruction so that we can
actually return values from called functions. :^)
Return values are propagated from callee to caller via the caller's
$0 register. Bytecode::Interpreter now keeps a stack of register
"windows". These are not very efficient, but it should be pretty
straightforward to convert them to e.g a sliding register window
architecture later on.
This is pretty dang cool! :^)
This patch adds the Call bytecode instruction which is emitted for the
CallExpression AST node.
It's pretty barebones and doesn't handle 'this' values properly, etc.
But it can perform basic function calls! :^)
Note that the called function will *not* execute as bytecode, but will
simply fall back into the old codepath and use the AST interpreter.
This is intended to perform the same duties as enter_scope() does in
the AST tree-walk interpreter:
- Hoisted function declaration processing
- Hoisted variable declaration processing
- ... maybe more
This first cut only implements the function declaration processing.
This was quite straightforward using the same label/jump machinery that
we added for while statements.
The main addition here is a new JumpIfTrue bytecode instruction.
This introduces two new instructions: Jump and JumpIfFalse.
Jumps are made to a Bytecode::Label, which is a simple object that
represents a location in the bytecode stream.
Note that you may not always know the target of a jump when adding the
jump instruction itself, but we can just update the instruction later
on during codegen once we know where the jump target is.
The Bytecode::Interpreter now implements jumping via a jump slot that
gets checked after each instruction to see if a jump is pending.
If not, we just increment the PC as usual.
- NewString (allocates a new PrimitiveString from the GC heap)
- GetVariable (retrieves a variable in the current scope)
- SetVariable (assigns a variable in the current scope)
This patch begins the work of implementing JavaScript execution in a
bytecode VM instead of an AST tree-walk interpreter.
It's probably quite naive, but we have to start somewhere.
The basic idea is that you call Bytecode::Generator::generate() on an
AST node and it hands you back a Bytecode::Block filled with
instructions that can then be interpreted by a Bytecode::Interpreter.
This first version only implements two instructions: Load and Add. :^)
Each bytecode block has infinity registers, and the interpreter resizes
its register file to fit the block being executed.
Two new `js` options are added in this patch as well:
`-d` will dump the generated bytecode
`-b` will execute the generated bytecode
Note that unless `-d` and/or `-b` are specified, none of the bytecode
related stuff in LibJS runs at all. This is implemented in parallel
with the existing AST interpreter. :^)
And use them to highlight javascript in HTML source.
This commit also changes how TextDocumentSpan::data is interpreted,
as it used to be an opaque pointer, but everyone stuffed an enum value
inside it, which made the values not unique to each highlighter;
that field is now a u64 serial id.
The syntax highlighters don't need to change their ways of stuffing
token types into that field, but a highlighter that calls another
nested highlighter needs to register the nested types for use with
token pairs.
This patch moves the magnifier rect computation over to the server side
to ensure that the mouse cursor position and the screen image never get
out of sync.
This is just a simple helper that dumps the current VM call stack
to the debug console. I find myself rewriting this function over and
over, so let's just have it in the tree.
There is logic at the end of the constructor that sets m_should_block
to false if we encountered errors. We were missing this step due to the
erroneous early return, the code then ended up waiting and then
asserting on unblock since the WaitBlocker is in a invalid state.
This fix is to not return early, and let normal control flow handle it.
Fixes: #7857
Verified with `stress-ng --yield=10` locally.
This is now a bit closer to the spec's 10.4.2.2 ArrayCreate - it will
throw a RangeError if the requested length exceeds 2^32 - 1, so anyone
passing in a custom value (defaults to zero for same behaviour as
before) will need an exception check at the call site.
4d5cdcc893 partially reverted the changes
from d8c5eeceab, but it reverted too much
and reintroduced the bug.
This commit finally fixes the actual bug.
The author hasn't been in his best committing state today.
This adds the new flag -R for the crash utility which tests what
happens when we dereference a null RefPtr. This is useful for testing
the output of the assertion message.
This implements the dladdr() function which lets the caller look up
the symbol name, symbol address as well as library name and library
base address for an arbitrary address.
We're already keeping it alive via `m_notifier`.
This makes the event loop quitting logic simpler by making less
deferred calls and removes a race condition where the notifier would be
deleted before the second deferred_invoke() would be invoked, leading
to a nullptr dereference.
Fixes#7822.