Commit graph

57 commits

Author SHA1 Message Date
Shannon Booth
a0d1ef34e2 LibJS: Deduplicate labelled continue & break bytecode generation
Similar to the scoped continue and break, the only two differences
between these functions is the scope that is scanned for a matching
label, and the specific handling of a continue/break boundary.
2023-07-20 07:24:31 +02:00
Shannon Booth
663e4507ea LibJS: Deduplicate scoped continue & break bytecode generation
The only two differences between these two functions are the name of the
block that is created and the specific jump/break handling per boundary.
2023-07-20 07:24:31 +02:00
Luke Wilde
265a9b5ffc LibJS/Bytecode: Add function to determine if we're in an async generator 2023-07-15 01:08:52 +02:00
Luke Wilde
c37ef5694b LibJS/Bytecode: Class async generators as async functions 2023-07-15 01:08:52 +02:00
Andreas Kling
c0f985ffcf LibJS/Bytecode: Don't reparse regular expressions on instantiation
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.
2023-07-13 13:30:49 +02:00
Aliaksandr Kalenik
3661d674ae LibJS: Add optimized GetGlobal instruction to access global variables
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.
2023-07-12 16:03:16 +02:00
Andreas Kling
de8e4b1853 LibJS/Bytecode: Cache object own property accesses
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 :^)
2023-07-09 12:54:06 +02:00
Timothy Flynn
0d50e5eeee LibJS/Bytecode: Extract code to generate a super reference to a helper
This code is already repeated twice, and would be repeated a third time
for the `delete` operator.
2023-07-07 18:11:51 +02:00
Aliaksandr Kalenik
ae3a7fd4b8 LibJS: Update bytecode generator to use local variables
- 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
2023-07-05 21:03:01 +02:00
Hendiadyoin1
37067cf3ca LibJS: Use the IdentifierTable for NewFunction and NewClass lhs names
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.
2023-06-29 05:32:08 +02:00
Andreas Kling
85a3a1c085 LibJS/Bytecode: Add codegen for "named evaluation if anonymous function"
This gives anonymous functions the name from the LHS they are being
assigned to.

171 new passes on test262. :^)
2023-06-23 16:09:33 +02:00
Andreas Kling
dbfe1311ef LibJS/Bytecode: Simplify creating/leaving lexical environment
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.
2023-06-16 21:46:43 +02:00
Andreas Kling
12ce0789da LibJS/Bytecode: Remove BlockBoundaryType::LeaveVariableEnvironment
We never need to manually exit a var environment from bytecode anymore.
2023-06-16 21:46:43 +02:00
Andreas Kling
ac246d764d LibJS/Bytecode: Leave BlockDeclarationInstantiation in C++
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.
2023-06-16 21:46:43 +02:00
Andreas Kling
c9bd324369 LibJS/Bytecode: Set "home object" of functions within object expression
We manage this by having a stack of home objects in Generator, and then
adding an optional home object parameter to the NewFunction instruction.
2023-06-16 12:56:39 +02:00
Andreas Kling
21db2b7b90 Everywhere: Remove NonnullOwnPtr.h includes 2023-03-06 23:46:35 +01:00
Andreas Kling
359d6e7b0b Everywhere: Stop using NonnullOwnPtrVector
Same as NonnullRefPtrVector: weird semantics, questionable benefits.
2023-03-06 23:46:35 +01:00
Hendiadyoin1
088dc1b24b LibJS: Simplify Generator::perform_needed_unwinds
This does not need to cater to the needs of `break` and `continue
anymore, which allows us to simplify it a bit.
2023-02-26 19:40:09 +01:00
Hendiadyoin1
d65488b80c LibJS: Generate unwind chains for continue in Bytecode
This works similar to `break`
The `try-finally-continue` still do not pass with this, likely because
of binding issues.
2023-02-26 19:40:09 +01:00
Hendiadyoin1
f5376cb282 LibJS: Generate unwind chains for break in Bytecode
This uses a newly added instruction `ScheduleJump`
This instruction tells the finally proceeding it, that instead of
jumping to it's next block it should jump to the designated block.
2023-02-26 19:40:09 +01:00
Timothy Flynn
f3db548a3d AK+Everywhere: Rename FlyString to DeprecatedFlyString
DeprecatedFlyString relies heavily on DeprecatedString's StringImpl, so
let's rename it to A) match the name of DeprecatedString, B) write a new
FlyString class that is tied to String.
2023-01-09 23:00:24 +00:00
Hendiadyoin1
fcc3348bc8 LibJS: Intercept returns through finally blocks in Bytecode
This is still not perfect, as we now actually crash in the
`try-finally-continue` tests, while we now succeed all
`try-catch-finally-*` tests.

Note that we do not yet go through the finally block when exiting the
unwind context through a break or continue.
2022-12-06 16:09:24 +03:30
Linus Groh
6e19ab2bbc AK+Everywhere: Rename String to DeprecatedString
We have a new, improved string type coming up in AK (OOM aware, no null
state), and while it's going to use UTF-8, the name UTF8String is a
mouthful - so let's free up the String name by renaming the existing
class.
Making the old one have an annoying name will hopefully also help with
quick adoption :^)
2022-12-06 08:54:33 +01:00
Linus Groh
d26aabff04 Everywhere: Run clang-format 2022-12-03 23:52:23 +00:00
Hendiadyoin1
192897c269 LibJS: Remeber which instruction terminated a block 2022-12-03 17:07:30 +03:30
Hendiadyoin1
911506af9f LibJS: Align Instructions as void* and roundup variably sized ones sizes
Both is indeed needed,
the standard alignment would have been 4, but some Instructions, like
Jumps need an alignment of 8

Fixes #12127.
2022-10-01 00:04:02 +01:00
Luke Wilde
3a48c7fdaf LibJS/Bytecode: Check for lexical bindings only in current scope
BlockDeclarationInstantiation takes as input the new lexical
environment that was created and checks if there is a binding for the
current name only in this new scope.

This allows shadowing lexical variables and prevents us crashing due to
an already initialized lexical variable in this case:
```js
let x = 1;
{
    let x = 1;
}
```
2022-07-18 09:00:21 +01:00
Luke Wilde
c0fadfb9b7 LibJS/Bytecode: Implement break/continue labels
This is done by keeping track of all the labels that apply to a given
break/continue scope alongside their bytecode target. When a
break/continue with a label is generated, we scan from the most inner
scope to the most outer scope looking for the label, performing any
necessary unwinds on the way. Once the label is found, it is then
jumped to.
2022-06-13 07:13:03 +04:30
Luke Wilde
7cc53b7ef1 LibJS/Bytecode: Implement the delete unary expression
`delete` has to operate directly on Reference Records, so this
introduces a new set of operations called DeleteByValue, DeleteVariable
and DeleteById. They operate similarly to their Get counterparts,
except they end in creating a (temporary) Reference and calling delete_
on it.
2022-03-28 14:05:33 +02:00
Lenny Maiorani
d00b79568f Libraries: Use default constructors/destructors in LibJS
https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#cother-other-default-operation-rules

"The compiler is more likely to get the default semantics right and
you cannot implement these functions better than the compiler."
2022-03-16 16:19:40 +00:00
Luke Wilde
9f4cc6435d LibJS/Bytecode: Unwind to closest unwind boundary on Throw
This will leave any lexical/variable environments on the way to the
closest unwind context boundary.

This will not leave the closest unwind context, as we still need the
unwind context to perform the Throw instruction correctly.
2022-03-14 21:15:27 +03:30
Luke Wilde
858bcac4c7 LibJS/Bytecode: Unwind environments before block terminating instruction
When we reach a block terminating instruction (e.g. Break, Throw),
we cannot generate anymore instructions after it. This would not allow
us to leave any lexical/variable environments.

This uses the mechanism introduced in ba9c49 to unwind environments
when we encounter these instructions.
2022-03-14 21:15:27 +03:30
Ali Mohammad Pur
ba9c4959d6 LibJS: Leave the unwind context on break/continue/return in bytecode
Otherwise we'd keep the old unwind context, and end up never invoking
the other handlers up the stack.
2022-03-13 17:50:21 +01:00
Ali Mohammad Pur
1bbfaf8627 LibJS: More properly implement scoping rules in bytecode codegen
Now we emit CreateVariable and SetVariable with the appropriate
initialization/environment modes, much closer to the spec.
This makes a whole lot of things like let/const variables, function
and variable hoisting and some other things work :^)
2022-02-13 14:41:33 +00:00
Ali Mohammad Pur
75aa900b83 LibJS: Make ASTNode::generate_bytecode() fallible
Instead of crashing on the spot, return a descriptive error that will
eventually continue its days as a javascript "InternalError" exception.
This should make random crashes with BC less likely.
2022-02-13 14:41:33 +00:00
Andreas Kling
7a742b17da LibJS: Store ECMAScriptFunctionObject bytecode in an OwnPtr
Using an Optional was extremely wasteful for function objects that don't
even have a bytecode executable.

This allows ECMAScriptFunctionObject to fit in a smaller size class.
2022-01-31 16:19:23 +01:00
Linus Groh
0c73fbbba5 LibJS: Rename FunctionKind::{Regular => Normal}
This is what CreateDynamicFunction calls it.
2022-01-16 01:54:48 +01:00
Ali Mohammad Pur
3b0bf05fa5 LibJS: Implement async functions as generator functions in BC mode
This applies a simple transformation, and adds a simple wrapper that
translates the generator interface to the async function interface.
2021-11-12 13:01:59 +00:00
Andreas Kling
1dc60b028f LibJS: Add BytecodeGenerator helpers for reference get/put
This allows code sharing between all AST nodes that want to get and/or
put through a reference.
2021-10-25 15:16:22 +02:00
Andreas Kling
da98212001 LibJS: Add a separate "identifier table" to bytecode executables
This is a specialized string table for storing identifiers only.
Identifiers are always FlyStrings, which makes many common operations
faster by allowing O(1) comparison.
2021-10-24 17:18:07 +02:00
Andreas Kling
13f04e37e5 LibJS: Use String and move semantics in Bytecode::StringTable
Avoid creating new AK::String objects when we already have one.
2021-10-24 17:18:07 +02:00
Andreas Kling
da77e2aa4f LibJS: Add Bytecode::Executable::dump()
Let's have a helper for producing a consistent executable dump instead
of repeating the logic in multiple places.
2021-10-24 17:18:05 +02:00
Ali Mohammad Pur
3234697eca LibJS: Implement generator functions (only in bytecode mode) 2021-06-11 00:30:09 +02:00
Ali Mohammad Pur
4cfdfb6a88 LibJS: Automatically split linear bytecode into multiple blocks
...instead of crashing :^)
2021-06-11 00:30:09 +02:00
Andreas Kling
22c803d8e5 LibJS: Always keep the global object in bytecode VM register $1 2021-06-10 21:59:49 +02:00
Gunnar Beutner
67cc31a74f LibJS: Implement bytecode generation for try..catch..finally
EnterUnwindContext pushes an unwind context (exception handler and/or
finalizer) onto a stack.

LeaveUnwindContext pops the unwind context from that stack.

Upon return to the interpreter loop we check whether the VM has an
exception pending. If no unwind context is available we return from the
loop. If an exception handler is available we clear the VM's exception,
put the exception value into the accumulator register, clear the unwind
context's handler and jump to the handler. If no handler is available
but a finalizer is available we save the exception value + metadata (for
 later use by ContinuePendingUnwind), clear the VM's exception, pop the
unwind context and jump to the finalizer.

ContinuePendingUnwind checks whether a saved exception is available. If
no saved exception is available it jumps to the resume label. Otherwise
it stores the exception into the VM.

The Jump after LeaveUnwindContext could be integrated into the
LeaveUnwindContext instruction. I've kept them separate for now to make
the bytecode more readable.

> try { 1; throw "x" } catch (e) { 2 } finally { 3 }; 4
1:
[   0] EnterScope
[  10] EnterUnwindContext handler:@4 finalizer:@3
[  38] EnterScope
[  48] LoadImmediate 1
[  60] NewString 1 ("x")
[  70] Throw
<for non-terminated blocks: insert LeaveUnwindContext + Jump @3 here>
2:
[   0] LoadImmediate 4
3:
[   0] EnterScope
[  10] LoadImmediate 3
[  28] ContinuePendingUnwind resume:@2
4:
[   0] SetVariable 0 (e)
[  10] EnterScope
[  20] LoadImmediate 2
[  38] LeaveUnwindContext
[  3c] Jump @3

String Table:
0: e
1: x
2021-06-10 21:59:46 +02:00
xyanrch
a0412e0d5e LibJS: Implement bytecode generation for BreakStatement 2021-06-10 21:48:20 +04:30
Gunnar Beutner
6a0d1fa259 LibJS: Store strings in a string table
Instead of using Strings in the bytecode ops this adds a global string
table to the Executable struct which individual operations can refer
to using indices. This brings bytecode ops one step closer to being
pointer free.
2021-06-09 17:42:52 +02:00
Andreas Kling
b61f198d22 LibJS: Rename Bytecode::ExecutionUnit => Bytecode::Executable 2021-06-09 09:24:32 +02:00
Ali Mohammad Pur
01e8f0889a LibJS: Generate bytecode in basic blocks instead of one big block
This limits the size of each block (currently set to 1K), and gets us
closer to a canonical, more easily analysable bytecode format.
As a result of this, "Labels" are now simply entries to basic blocks.
Since there is no more 'conditional' jump (as all jumps are always
taken), JumpIf{True,False} are unified to JumpConditional, and
JumpIfNullish is renamed to JumpNullish.
Also fixes #7914 as a result of reimplementing the loop logic.
2021-06-09 09:07:29 +02:00