1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-25 18:25:09 +00:00
Commit graph

1022 commits

Author SHA1 Message Date
Idan Horowitz
bc95201aaf LibJS: Dont mask non-RangeError exceptions in ArrayBuffer construction
Non-RangeError exceptions can be thrown by user implementations of
valueOf (which are called by to_index), and the specification disallows
changing the type of the thrown error.
2021-06-10 22:44:26 +01:00
Idan Horowitz
8dc86c6aad LibJS: Bring ArrayBuffer.prototype.slice closer to spec
The exception order was incorrect in the old implementation, and it
did not use the Symbol.species constructor as required by the spec.
2021-06-10 22:44:26 +01:00
Idan Horowitz
b041108a1e LibJS: Explicitly return and accept a Function* in species_constructor
The second argument (the default constructor) and the return value have
to be constructors (as a result functions), so we can require that
explicitly by using appropriate types.
2021-06-10 22:44:26 +01:00
Andreas Kling
93a07ba962 LibJS: Remove GlobalObject& argument from VM::construct()
We can just get the global object from the constructor function.
2021-06-10 23:17:29 +02:00
Andreas Kling
f5feb1d2cd LibJS: Very basic support for "new" construction in bytecode VM
This patch adds a CallType to the Bytecode::Op::Call instruction,
which can be either Call or Construct. We then generate Construct
calls for the NewExpression AST node.

When executed, these get fed into VM::construct().
2021-06-10 23:01:49 +02:00
Andreas Kling
c3c68399b5 LibJS: Generate bytecode for entering nested lexical environments
This adds a new PushLexicalEnvironment instruction that creates a new
LexicalEnvironment and pushes it on the VM's scope stack.

There is no corresponding PopLexicalEnvironment instruction yet,
so this will behave incorrectly with let/const scopes for example.
2021-06-10 22:20:23 +02:00
Andreas Kling
d560ee118d LibJS: Allocate 4 KiB for Bytecode::BasicBlock
There's no reason not to, since we're using mmap() for these anyway
and that gives us memory in 4 KiB increments. :^)
2021-06-10 21:59:49 +02:00
Andreas Kling
22c803d8e5 LibJS: Always keep the global object in bytecode VM register $1 2021-06-10 21:59:49 +02:00
Andreas Kling
b3e6a6c1cd LibJS: Perform function instantiation in bytecode
This replaces Bytecode::Op::EnterScope with a new NewFunction op that
instantiates a ScriptFunction from a given FunctionNode (AST).

This is then used to instantiate the local functions directly from
bytecode when entering a ScopeNode. :^)
2021-06-10 21:59:49 +02:00
Andreas Kling
941be2dcc2 LibJS: Add empty bytecode generation for VariableDeclaration
These will be partly handled by the relevant ScopeNode due to
hoisting, same basic idea as function declarations.

VariableDeclaration needs to do some work, but let's stub it out
first and start empty.
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
Gunnar Beutner
319a60043b LibJS: Let the bytecode interpreter set the VM's last value 2021-06-10 21:47:25 +02:00
xyanrch
a0412e0d5e LibJS: Implement bytecode generation for BreakStatement 2021-06-10 21:48:20 +04:30
Luke
00a83a2957 LibJS: Make removed elements in Array.prototype.splice spec compliant
It wasn't using has_property, was directly appending to indexed
properties and wasn't setting the length.
2021-06-10 10:04:06 +01:00
Luke
bc540de0af LibJS: Pass in actual_delete_count to removed array creation in splice
More specifically, Array.prototype.splice. Additionally adds a missing
exception check to the array creation and a link to the spec.

Fixes create-non-array-invalid-len.js in the splice tests in test262.
This test timed out instead of throwing an "Invalid array length"
exception.
2021-06-10 10:04:06 +01:00
Idan Horowitz
f63ef4f196 LibJS: Stop asserting in {Set,Test}IntegrityLevel on missing descriptor
As per the specification (7.3.15 SetIntegrityLevel):
i. Let currentDesc be ? O.[[GetOwnProperty]](k).
ii. If currentDesc is not undefined, then...
2021-06-10 09:20:05 +01:00
Linus Groh
b639bf64f2 LibJS: Use create_list_from_array_like() in Function.prototype.apply() 2021-06-09 23:46:37 +01:00
Linus Groh
f932da095e LibJS: Use create_list_from_array_like() in Reflect.{apply,construct}() 2021-06-09 23:46:37 +01:00
Linus Groh
ad7aa05cc6 LibJS: Implement the CreateListFromArrayLike() abstract operation
We already have two separate implementations of this, so let's do it
properly. The optional value type check is done by a callback function
that returns Result<void, ErrorType> - value type accepted or message
for TypeError, that is.
2021-06-09 23:46:37 +01:00
Luke
5da94b30eb LibJS: Add logical assignment bytecode generation 2021-06-10 00:28:34 +02:00
Andreas Kling
4bc98fd39f LibJS: Only "var" declarations go in the global object at program level
"let" and "const" go in the lexical environment.

This fixes one part of #4001 (Lexically declared variables are mixed up
with global object properties)
2021-06-09 23:25:16 +02:00
Idan Horowitz
a00d154522 LibJS: Notify WeakSets when heap cells are sweeped
This is an implementation of the following optional optimization:
https://tc39.es/ecma262/#sec-weakref-execution
2021-06-09 21:52:25 +01:00
Idan Horowitz
fb63aeae4d LibJS: Add all of the WeakSet.prototype methods (add, delete, has) 2021-06-09 21:52:25 +01:00
Idan Horowitz
8b6beac5ce LibJS: Add the WeakSet built-in object 2021-06-09 21:52:25 +01:00
Gunnar Beutner
9dc9ddbf82 LibJS: Fix evaluation order for tagged template literals
This ensures that the tag function is evaluated first.
2021-06-09 22:26:27 +02:00
Gunnar Beutner
2d48fe894f LibJS: Generate bytecode for tagged template literals 2021-06-09 21:54:31 +02:00
Gunnar Beutner
25ab31219c LibJS: Fix the return value for TemplateLiteral
This ensures that the bytecode generated for TemplateLiterals returns
the correct value.
2021-06-09 21:50:39 +02:00
Andreas Kling
d69cd3f5bf LibJS: Don't create lexical environment for native (C++) function calls
This was creating a ton of pointless busywork for the garbage collector
and can be avoided simply by tolerating that the current call frame has
a null scope object for the duration of a NativeFunction activation.
2021-06-09 20:54:01 +02:00
Gunnar Beutner
6af7e74a25 LibJS: Don't generate code after we've encountered a terminating op 2021-06-09 20:04:11 +02:00
Gunnar Beutner
d198e41f74 LibJS: Stop bytecode execution after we've encountered an exception 2021-06-09 20:04:11 +02:00
Gunnar Beutner
b78f1c1261 LibJS: Generate bytecode for throw statements 2021-06-09 20:04:11 +02:00
Idan Horowitz
f437793788 LibJS: Stop inheriting from Set in SetPrototype
This makes sure that is<Set> checks done on the Set prototype instead of
on Set instances return false, thereby emulating the behaviour of the
RequireInternalSlot abstract operation.
2021-06-09 18:01:19 +01:00
Idan Horowitz
ad0e3c0e54 LibJS: Mark heap cell values stored in Set instances
This makes sure they dont get garbage collected while stored in a Set.
2021-06-09 17:05:53 +01:00
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
Idan Horowitz
2a3090d292 LibJS: Add the SetIterator built-in and Set.prototype.{values, entries}
While this implementation should be complete it is based on HashTable's
iterator, which currently follows bucket-order instead of the required
insertion order. This can be simply fixed by replacing the underlying
HashTable member in Set with an enhanced one that maintains a linked
list in insertion order.
2021-06-09 11:48:04 +01:00
Idan Horowitz
0b0f1eda05 LibJS: Add most of the Set.prototype methods
Specifically all aside from "values" and "entries" which require an
implementation of the SetIterator object.
2021-06-09 11:48:04 +01:00
Idan Horowitz
670be04c81 LibJS: Add the Set built-in object 2021-06-09 11:48:04 +01:00
Andreas Kling
59eedd6de0 LibJS: Implement bytecode generation for UpdateExpression :^)
Added Increment and Decrement bytecode ops to support this. Postfix
updates use a temporary register to preserve the original value.

Note that this patch only implements Identifier updates. Member
expression updates are a TODO.
2021-06-09 11:40:38 +02:00
Andreas Kling
5c98f979c6 LibJS: Simplify the way we stringify bytecode instructions
For instructions that only have a single operand, omit the operand
name since it's implied anyway.
2021-06-09 11:06:11 +02:00
Andreas Kling
99ffcc28c2 LibJS: Print the name of AST nodes that are missing generate_bytecode()
This way you know which one it is right away. :^)
2021-06-09 09:32:09 +02:00
Andreas Kling
a8ccc9580d LibJS: Move Instruction::length() to the Op.h header
Make sure this gets inlined as well, as it's used by the bytecode
stream iterator and thus extremely hot.
2021-06-09 09:24:32 +02:00
Andreas Kling
48a8022cf6 LibJS: Move Bytecode::Instruction::execute() to the Op.h header
..and make sure it always gets inlined in the interpreter loop.
2021-06-09 09:24:32 +02:00
Andreas Kling
b61f198d22 LibJS: Rename Bytecode::ExecutionUnit => Bytecode::Executable 2021-06-09 09:24:32 +02:00
Luke
597e0d95fe LibJS: Only set element in array literal to an empty value if it's null
This avoids an unnecessary empty load that immediately gets overridden.

For example, `[1,,]` would appear as:
[   0] EnterScope
[  10] LoadImmediate value:<empty>
[  28] LoadImmediate value:1
[  40] Store dst:$1
[  48] LoadImmediate value:<empty>
[  60] Store dst:$2
[  68] NewArray, elements:[$1,$2]

But now appears as:
[   0] EnterScope
[  10] LoadImmediate value:1
[  28] Store dst:$1
[  30] LoadImmediate value:<empty>
[  48] Store dst:$2
[  50] NewArray, elements:[$1,$2]
2021-06-09 09:14:40 +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
Matthew Olsson
f286cf1792 LibJS: Fix not executing the expression of a return statement 2021-06-09 01:33:38 +02:00
Gunnar Beutner
a1e5711a27 LibJS: Generate bytecode for array expressions 2021-06-09 01:27:18 +02:00
Andreas Kling
b8a5ea1f8d Revert "LibJS: Add bytecode instruction handles"
This reverts commit a01bd35c67.

This broke simple programs like:

function sum(a, b) { return a + b; }
console.log(sum(1, 2));
2021-06-09 00:50:42 +02:00
Matthew Olsson
a01bd35c67 LibJS: Add bytecode instruction handles
This change removes the mmap inside of Block in favor of a growing
vector of bytes. This is favorable for two reasons:
  - We don't take more space than we need
  - There is no limit to the growth of the vector (previously, if
    the Block overstepped its 64kb boundary, it would just crash)

However, if that vector happens to resize, any pointer pointing into
that vector would become invalid. To avoid this, this commit adds an
InstructionHandle<Op> class which just stores a block and an offset
into that block.
2021-06-09 00:37:17 +02:00
Linus Groh
83be39c91a LibJS: Handle Proxy with Array target in IsArray() abstract operation
This was missing from Value::is_array(), which is equivalent to the
spec's IsArray() abstract operation - it treats a Proxy value with an
Array target object as being an Array.
It can throw, so needs both the global object and an exception check
now.
2021-06-08 23:53:13 +02:00