Commit graph

70 commits

Author SHA1 Message Date
Andreas Kling
b1b2ca1485 LibJS: Add basic monomorphic caching for PutById property access
This patch makes it possible for JS::Object::internal_set() to populate
a CacheablePropertyMetadata, and uses this to implement a basic
monomorphic cache for the most common form of property write access.
2023-11-09 16:02:14 +01:00
Todderod
bb9230bbcd LibJS: Remove redundant Store op
If the property for GetByValue in Generator::load_from_reference
is a calculated value this would be stored in an allocated
register and returned from the function. Not all callers want
this information however, so now only give it out when asked for.

Reduced the instruction count for Kraken/ai-astar.js function
"neighbours" from 214 to 192.
2023-11-08 22:18:28 +01:00
Nick Hawke
67566e5017 LibJS: Migrate DeprecatedString to String
This changes BasicBlock's constructor and create().
2023-11-02 14:55:12 +01:00
Hendiadyoin1
73f347b75c LibJS: Create static unwind mappings for BasicBlocks
This is currently only used in the bytecode dump to annotate to where
unwinds lead per block, but will be hooked up to the virtual machine in
the next commit.
2023-10-30 13:10:08 +01:00
Andreas Kling
2e23f00a2f LibJS/Bytecode: Move environment coordinate caches to Executable
Moving them out of the respective instructions allows the bytecode
stream to be immutable.
2023-10-27 07:26:37 +02:00
Andreas Kling
732b39d120 LibJS: Don't evaluate computed MemberExpression LHS twice in assignments
The following snippet would cause "i" to be incremented twice(!):

    let a = []
    let i = 0
    a[++i] += 0

This patch solves the issue by remembering the base object and property
name for computed MemberExpression LHS in codegen. We the store the
result of the assignment to the same object and property (instead of
computing the LHS again).

3 new passes on test262. :^)
2023-10-04 18:58:29 +02:00
Andreas Kling
c14db6ab12 LibJS: Make Executable ref-counted and let instruction iterator co-own it
This ensures that the instruction stream pointed at by the instruction
iterator remains valid as long as the iterator exists.
2023-10-03 08:23:33 +02:00
Andreas Kling
aeb8b5685f LibJS: Make Bytecode::Generator::emit() return void
There are no callers left that use the return value.
2023-09-28 14:52:03 +02:00
Andreas Kling
84850700a0 LibJS: Make BC::Generator::emit_with_extra_register_slots() return void
Nobody was using the return value.
2023-09-28 14:52:03 +02:00
Andreas Kling
d24e07579f LibJS: Use a Vector<u8> for BasicBlock instruction storage
This reduces the minimum size of a basic block from 4 KiB to 0 bytes.
With this change, memory usage at the end of Speedometer is 1.2 GiB,
down from 1.8 GiB.
2023-09-28 11:25:19 +02:00
Andreas Kling
c833885fb5 LibJS: Keep cached this value in a call frame register
Just moving more things to call frame registers..
2023-09-28 06:09:16 +02:00
Andreas Kling
3887b840a3 LibJS: Keep current exception in a call frame register
Instead of keeping it in a Bytecode::Interpreter member, move it into
a dedicated call frame register.
2023-09-28 06:09:16 +02:00
Andreas Kling
1c06111cbd LibJS: Add file & line number to bytecode VM stack traces :^)
This works by adding source start/end offset to every bytecode
instruction. In the future we can make this more efficient by keeping
a map of bytecode ranges to source ranges in the Executable instead,
but let's just get traces working first.

Co-Authored-By: Andrew Kaster <akaster@serenityos.org>
2023-09-02 15:37:53 +02:00
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