Commit graph

167 commits

Author SHA1 Message Date
Andreas Kling
bea6e31ddc LibJS: Add a NewObject bytecode instruction for ObjectExpression :^) 2021-06-07 18:11:59 +02:00
Andreas Kling
f2863b5a89 LibJS: Generate bytecode for do...while statements :^)
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.
2021-06-07 18:11:59 +02:00
Andreas Kling
6ae9346cd3 LibJS: Add basic support for while loops in the bytecode engine
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.
2021-06-07 18:11:59 +02:00
Andreas Kling
37cb70836b LibJS: Some more opcodes for the bytecode VM
- 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)
2021-06-07 18:11:59 +02:00
Andreas Kling
69dddd4ef5 LibJS: Start fleshing out a bytecode for the JavaScript engine :^)
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. :^)
2021-06-07 18:11:59 +02:00
Ali Mohammad Pur
7a00d6d9c8 LibJS: Implement destructuring assignments and function parameters 2021-05-29 23:02:23 +04:30
Linus Groh
c93c2dc72c LibJS: Rename RegExpLiteral m_content to m_pattern
This is what we call it elsewhere, let's be consistent.
2021-05-10 11:57:35 +01:00
Andreas Kling
b91c49364d AK: Rename adopt() to adopt_ref()
This makes it more symmetrical with adopt_own() (which is used to
create a NonnullOwnPtr from the result of a naked new.)
2021-04-23 16:46:57 +02:00
Linus Groh
ebdeed087c Everywhere: Use linusg@serenityos.org for my copyright headers 2021-04-22 22:51:19 +02:00
Brian Gianforcaro
1682f0b760 Everything: Move to SPDX license identifiers in all files.
SPDX License Identifiers are a more compact / standardized
way of representing file license information.

See: https://spdx.dev/resources/use/#identifiers

This was done with the `ambr` search and replace tool.

 ambr --no-parent-ignore --key-from-file --rep-from-file key.txt rep.txt *
2021-04-22 11:22:27 +02:00
Andreas Kling
0255c8d976 Only apply auto-naming of function expressions based on syntax
The auto naming of function expressions is a purely syntactic
decision, so shouldn't be decided based on the dynamic type of
an assignment. This moves the decision making into the parser.

One icky hack is that we add a field to FunctionExpression to
indicate whether we can autoname. The real solution is to actually
generate a CompoundExpression node so that the parser can make
the correct decision, however this would have a potentially
significant run time cost.

This does not correct the behaviour for class expressions.

Patch from Anonymous.
2021-03-22 12:44:07 +01:00
Andreas Kling
c8382c32e9 LibJS: Split Value::Type::Number into Int32 and Double
We now store 32-bit integers as 32-bit integers directly which avoids
having to convert them from doubles when they're only used as 32-bit
integers anyway. :^)

This patch feels a bit incomplete and there's a lot of opportunities
to take advantage of this information. We'll have to find and exploit
them eventually.
2021-03-21 21:39:39 +01:00
Linus Groh
47645fc976 LibJS: Ensure SequenceExpression has two or more expressions
Just a sanity check, as we should be able to make this assumption
elsewhere - this way we can catch silly mistakes early.
2021-03-16 22:12:56 +01:00
Linus Groh
c499239137 LibJS: Implement non-value-producing statements properly
For various statements the spec states:

    Return NormalCompletion(empty).

In those cases we have been returning undefined so far, which is
incorrect.

In other cases it states:

    Return Completion(UpdateEmpty(stmtCompletion, undefined)).

Which essentially means a statement is evaluated and its completion
value returned if non-empty, and undefined otherwise.

While not actually noticeable in normal scripts as the VM's "last value"
can't be accessed from JS code directly (with the exception of eval(),
see below), it provided an inconsistent experience in the REPL:

    > if (true) 42;
    42
    > if (true) { 42; }
    undefined

This also fixes the case where eval() would return undefined if the last
executed statement is not a value-producing one:

    eval("1;;;;;")
    eval("1;{}")
    eval("1;var a;")

As a consequence of the changes outlined above, these now all correctly
return 1.

See https://tc39.es/ecma262/#sec-block-runtime-semantics-evaluation,
"NOTE 2".

Fixes #3609.
2021-03-16 10:08:07 +01:00
Andreas Kling
5d180d1f99 Everywhere: Rename ASSERT => VERIFY
(...and ASSERT_NOT_REACHED => VERIFY_NOT_REACHED)

Since all of these checks are done in release builds as well,
let's rename them to VERIFY to prevent confusion, as everyone is
used to assertions being compiled out in release.

We can introduce a new ASSERT macro that is specifically for debug
checks, but I'm doing this wholesale conversion first since we've
accumulated thousands of these already, and it's not immediately
obvious which ones are suitable for ASSERT.
2021-02-23 20:56:54 +01:00
Andreas Kling
4da913bfab LibJS: Replace ASTNode::class_name() with RTTI
This is only used for debugging anyway, so performance doesn't matter
too much.
2021-01-17 14:36:53 +01:00
Andreas Kling
13d7c09125 Libraries: Move to Userland/Libraries/ 2021-01-12 12:17:46 +01:00
Renamed from Libraries/LibJS/AST.h (Browse further)