Andreas Kling
996ea109b3
LibJS: Allocate context up front when calling with argument array
...
This necessitated splitting CallWithArgumentArray into three variants,
one for each call type (call, construct and direct eval).
2025-08-31 15:24:37 +02:00
Timothy Flynn
70db474cf0
LibJS+LibWeb: Port interned bytecode strings to UTF-16
...
This was almost a no-op, except we intern JS exception messages. So the
bulk of this patch is porting exception messages to UTF-16.
2025-08-14 10:27:08 +02:00
Timothy Flynn
cf61171864
LibJS: Port remaining bytecode identifiers to UTF-16
2025-08-14 10:27:08 +02:00
Timothy Flynn
62d85dd90a
LibJS: Port RegExp flags and patterns to UTF-16
2025-08-13 09:56:13 -04:00
Timothy Flynn
b955c9b2a9
LibJS: Port the Identifier AST (and related) nodes to UTF-16
...
This eliminates quite a lot of UTF-8 / UTF-16 churn.
2025-08-13 09:56:13 -04:00
Aliaksandr Kalenik
a3af7ca1a0
LibJS: Skip PrivateEnvironment allocation if possible
...
If class doesn't have any private fields, we could avoid allocating
PrivateEnvironment for it.
This allows us to skip thousands of unnecessary PrivateEnvironment
allocations on Discord.
2025-07-30 13:01:53 +02:00
Shannon Booth
f2fb86abea
LibJS: Always emit value in emit_named_evaluation_if_anonymous_function
...
There does not appear to be any case that we need to return an
OptionalNone{}.
2025-05-23 03:25:55 +02:00
Shannon Booth
20dba8f1ab
LibJS: Make Op::Return value required
...
It turns out we do not have any scenario where this is not provided.
2025-05-23 03:25:55 +02:00
Daniel Bertalan
456d750539
LibJS: Make generate_labelled_evaluation
non-virtual if possible
...
We don't override anything with definitions of this function in
`SwitchStatement` and `LabelledStatement`. Also, we can make the
`IterationStatement` abstract, there is no need to add a fallback
error-generating stub implementation of this method.
2025-05-12 11:40:45 -06:00
Shannon Booth
19bf897116
LibJS: Avoid roundtrip through Value for comparison bytecode evaluation
...
CI / Lagom (arm64, Sanitizer_CI, false, macos-15, macOS, Clang) (push) Waiting to run
CI / Lagom (x86_64, Fuzzers_CI, false, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, false, ubuntu-24.04, Linux, GNU) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, true, ubuntu-24.04, Linux, Clang) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (arm64, macos-15, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (x86_64, ubuntu-24.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
1.1x speedup on strictly-equals-object.js
2025-05-08 20:39:29 +02:00
Aliaksandr Kalenik
b3713db4ab
LibJS: Emit ThrowIfTDZ for identifiers used in assignment expressions
...
CI / Lagom (x86_64, Fuzzers_CI, false, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, false, ubuntu-24.04, Linux, GNU) (push) Waiting to run
CI / Lagom (arm64, Sanitizer_CI, false, macos-15, macOS, Clang) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, true, ubuntu-24.04, Linux, Clang) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (arm64, macos-15, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (x86_64, ubuntu-24.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
Error about not-initialized `x` variable access should be thrown for:
```js
function foo() {
x = 69;
let x;
}
foo();
```
Progress on test262:
```
Diff Tests:
test/staging/sm/expressions/optional-chain-tdz.js ❌ -> ✅
test/staging/sm/expressions/short-circuit-compound-assignment-tdz.js
❌ -> ✅
```
Fixes https://github.com/LadybirdBrowser/ladybird/issues/4587
2025-05-06 12:06:23 +02:00
Andreas Kling
bf1b754e91
LibJS: Optimize reading known-to-be-initialized var
bindings
...
CI / Lagom (arm64, Sanitizer_CI, false, macos-15, macOS, Clang) (push) Waiting to run
CI / Lagom (x86_64, Fuzzers_CI, false, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, false, ubuntu-24.04, Linux, GNU) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, true, ubuntu-24.04, Linux, Clang) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (arm64, macos-15, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (x86_64, ubuntu-24.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
`var` bindings are never in the temporal dead zone (TDZ), and so we
know accessing them will not throw.
We now take advantage of this by having a specialized environment
binding value getter that doesn't check for exceptional cases.
1.08x speedup on JetStream.
2025-05-04 02:31:18 +02:00
Aliaksandr Kalenik
60bd5012fe
LibJS: Optimize array destructuring assignment for builtin iterators
...
...by avoiding `{ value, done }` iterator result value allocation. This
change applies the same otimization 81b6a11
added for `for..in` and
`for..of`.
Makes following micro benchmark go 22% faster on my computer:
```js
function f() {
const arr = [];
for (let i = 0; i < 10_000_000; i++) {
arr.push([i]);
}
let sum = 0;
for (let [i] of arr) {
sum += i;
}
}
f();
```
2025-05-01 16:57:56 +03:00
Aliaksandr Kalenik
81b6a1100e
LibJS: Skip iterator result object allocation in for..of and for..in
...
Introduce special instruction for `for..of` and `for..in` loop that
skips `{ value, done }` result object allocation if iterator is builtin
(array, map, set, string). This reduces GC pressure significantly and
avoids extracting the `value` and `done` properties.
This change makes this micro benchmark 48% faster on my computer:
```js
const arr = new Array(10_000_000);
let counter = 0;
for (let _ of arr) {
counter++;
}
```
2025-04-30 20:51:39 +02:00
Andreas Kling
7a600e60bc
LibJS: Mark catch
parameter as initialized local when applicable
...
CI / Lagom (arm64, Sanitizer_CI, false, macos-15, macOS, Clang) (push) Waiting to run
CI / Lagom (x86_64, Fuzzers_CI, false, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, false, ubuntu-24.04, Linux, GNU) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, true, ubuntu-24.04, Linux, Clang) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (arm64, macos-15, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (x86_64, ubuntu-24.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
Otherwise we'll emit a TDZ check for every `catch` parameter immediately
after initializing it. This check would never fail, so it's redundant.
2025-04-30 09:38:40 +02:00
Aliaksandr Kalenik
2d732b2251
LibJS: Skip allocating locals for arguments that allowed to be local
...
This allows us to get rid of instructions that move arguments to locals
and allocate smaller JS::Value vector in ExecutionContext by reusing
slots that were already allocated for arguments.
With this change for following function:
```js
function f(x, y) {
return x + y;
}
```
we now produce following bytecode:
```
[ 0] 0: Add dst:reg6, lhs:arg0, rhs:arg1
[ 10] Return value:reg6
```
instead of:
```
[ 0] 0: GetArgument 0, dst:x~1
[ 10] GetArgument 1, dst:y~0
[ 20] Add dst:reg6, lhs:x~1, rhs:y~0
[ 30] Return value:reg6
```
2025-04-26 11:02:29 +02:00
Aliaksandr Kalenik
981e465a04
LibJS: Delete create_variable param in BindingPattern::generate_bytecode
...
CI / Lagom (arm64, Sanitizer_CI, false, macos-15, macOS, Clang) (push) Waiting to run
CI / Lagom (x86_64, Fuzzers_CI, false, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, false, ubuntu-24.04, Linux, GNU) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, true, ubuntu-24.04, Linux, Clang) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (arm64, macos-15, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (x86_64, ubuntu-24.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
Build Dev Container Image / build (push) Has been cancelled
It's no longer used, because we assume that caller of this function has
already taken care of variable creation and initialization.
2025-04-22 21:57:25 +02:00
Aliaksandr Kalenik
7932091e02
LibJS: Allow using local variable for catch parameters
...
Local variables are faster to access and if all catch parameters are
locals we can skip lexical environment allocation.
2025-04-22 21:57:25 +02:00
Aliaksandr Kalenik
0f14c70252
LibJS: Use Identifier to represent CatchClause parameter names
...
By doing that we consistently use Identifier node for identifiers and
also enable mechanism that registers identifiers in a corresponding
ScopePusher for catch parameters, which is necessary for work in the
upcoming changes.
2025-04-22 21:57:25 +02:00
Andreas Kling
9c0b185ab8
LibJS: Don't track "last result" of ScopeNode if we don't need it
...
This prevents unnecessary bytecode register allocation.
2025-04-08 18:52:35 +02:00
Andreas Kling
5cdbb8b140
LibJS: Remove unused this
value from CallConstruct instruction
...
There's no `this` value prior in the caller context, and this was never
actually used by CallConstruct.
2025-04-08 18:52:35 +02:00
Andreas Kling
3cf50539ec
LibJS: Make Value() default-construct the undefined value
...
The special empty value (that we use for array holes, Optional<Value>
when empty and a few other other placeholder/sentinel tasks) still
exists, but you now create one via JS::js_special_empty_value() and
check for it with Value::is_special_empty_value().
The main idea here is to make it very unlikely to accidentally create an
unexpected special empty value.
2025-04-05 11:20:26 +02:00
Andreas Kling
3169747989
LibJS: Emit PutById instead of PutByValue when key is string literal
...
CI / Lagom (arm64, Sanitizer_CI, false, macos-15, macOS, Clang) (push) Waiting to run
CI / Lagom (x86_64, Fuzzers_CI, false, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, false, ubuntu-24.04, Linux, GNU) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, true, ubuntu-24.04, Linux, Clang) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (arm64, macos-15, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (x86_64, ubuntu-24.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
Build Dev Container Image / build (push) Has been cancelled
Basically convert o["foo"]=x into o.foo=x when emitting bytecode.
These are effectively the same thing, and the latter format opts
into using an inline cache for the property lookups.
2025-04-03 18:47:38 +02:00
Andreas Kling
4426c50a18
LibJS: Emit GetById instead of GetByValue when key is string literal
...
Basically convert o["foo"] into o.foo when emitting bytecode. These are
effectively the same thing, and the latter format opts into using an
inline cache for the property lookups.
2025-04-03 18:47:38 +02:00
Andreas Kling
a0bb31f7a0
LibJS: Make async functions & generators faster with helper types
...
Instead of returning internal generator results as ordinary JS::Objects
with properties, we now use GeneratorResult and CompletionCell which
both inherit from Cell directly and allow efficient access to state.
1.59x speedup on JetStream3/lazy-collections.js :^)
2025-04-01 02:30:42 +02:00
Lucien Fiorini
f72d87931f
LibJS: Reduce Mov instructions by using preferred destinations
2025-03-28 11:21:12 +00:00
Lucien Fiorini
5707076b9e
LibJS: Optimize away Mov instructions when the source is the destination
2025-03-28 11:21:12 +00:00
Andreas Kling
5ea45da15f
LibJS: Store NewObject result directly in preferred dst if possible
...
This avoids a Mov after every object literal.
2025-03-27 19:50:13 +00:00
Andreas Kling
202cbe7df6
LibJS: Constant-fold unary expressions
...
!0 and !1 are very common patterns in minified JavaScript, and we should
figure out that they're constants. :^)
2025-03-25 19:14:12 +00:00
Andreas Kling
46a5710238
LibJS: Use FlyString in PropertyKey instead of DeprecatedFlyString
...
This required dealing with *substantial* fallout.
2025-03-24 22:27:17 +00:00
Andreas Kling
b971e1ece0
LibJS: Mark locals as outside TDZ immediately after initializing
...
This avoids emitting TDZ checks for multiple bindings declared and
referenced within one variable declaration, i.e:
var foo = 0, bar = foo;
In the above case, we'd emit an unnecessary TDZ check for the second
reference to `foo`.
2025-03-21 00:58:34 +01:00
Timothy Flynn
85b424464a
AK+Everywhere: Rename verify_cast
to as
...
Follow-up to fc20e61e72
.
2025-01-21 11:34:06 -05:00
Luke Wilde
a588756105
LibJS: Use correct this value for tagged template literals with members
...
Required by creepjs, which does Date().split` `[3] to get the current
year.
2025-01-17 17:15:12 +01:00
Timothy Flynn
93712b24bf
Everywhere: Hoist the Libraries folder to the top-level
2024-11-10 12:50:45 +01:00