Age | Commit message (Collapse) | Author |
|
|
|
Mostly in comments, but sprintf() now prints "August" instead of
"Auguest" so that's something.
|
|
When scanning for potential heap pointers during conservative GC,
we look for any value that is an address somewhere inside a heap cell.
However, we were failing to account for the slack at the end of a
block (which occurs whenever the block storage size isn't an exact
multiple of the cell size.) Pointers inside the trailing slack were
misidentified as pointers into "last_cell+1".
Instead of skipping over them, we would treat this garbage data as a
live cell and try to mark it. I believe this is the test-js crash that
has been terrorizing Travis for a while. :^)
|
|
Each JS global object has its own "console", so it makes more sense to
store it in GlobalObject.
We'll need some smartness later to bundle up console messages from all
the different frames that make up a page later, but this works for now.
|
|
|
|
|
|
|
|
No behaviour change; also patches use of `String::TrimMode` in LibJS.
|
|
|
|
|
|
We'll want to get rid of all uses of this, to free up the engine from
the old assumption that there's always an Interpreter available.
|
|
|
|
|
|
|
|
|
|
|
|
We don't need the Interpreter& for anything here, the GlobalObject is
enough for getting to the VM and possibly throwing exceptions.
|
|
|
|
|
|
This is no longer needed, we can get everything we need from the VM.
|
|
More work on decoupling the general runtime from Interpreter. The goal
is becoming clearer. Interpreter should be one possible way to execute
code inside a VM. In the future we might have other ways :^)
|
|
This makes a difference inside ScriptFunction::call(), which will now
instantiate a temporary Interpreter if one is not attached to the VM.
|
|
Okay, my vision here is improving. Interpreter should be a thing that
executes an AST. The scope stack is irrelevant to the VM proper,
so we can move that to the Interpreter. Same with execute_statement().
|
|
This patch moves the exception state, call stack and scope stack from
Interpreter to VM. I'm doing this to help myself discover what the
split between Interpreter and VM should be, by shuffling things around
and seeing what falls where.
With these changes, we no longer have a persistent lexical environment
for the current global object on the Interpreter's call stack. Instead,
we push/pop that environment on Interpreter::run() enter/exit.
Since it should only be used to find the global "this", and not for
variable storage (that goes directly into the global object instead!),
I had to insert some short-circuiting when walking the environment
parent chain during variable lookup.
Note that this is a "stepping stone" commit, not a final design.
|
|
|
|
|
|
|
|
Empty string is extremely common and we can avoid a lot of heap churn
by simply caching one in the VM. Primitive strings are immutable anyway
so there is no observable behavior change outside of fewer collections.
|
|
No need to instantiate unique symbols for each Interpreter; they can
be VM-global. This reduces the memory cost and startup time anyway.
|
|
There's a lot more of these things to fix. We'll also want to move from
passing Interpreter& around to VM& instead wherever that is enough.
|
|
|
|
This will allow us to throw exceptions even when there is no active
interpreter in the VM.
|
|
I accidentally committed some code here to force a crash, but this
should just assert.
|
|
We can't GC while we're already in GC. Assert if this happens.
|
|
To make it a little clearer what this is for. (This is an RAII helper
class for adding and removing an Interpreter to a VM's list of the
currently active (executing code) Interpreters.)
|
|
If we are in a nested execution context, we shouldn't only mark things
used by the active interpreter.
|
|
Taking a big step towards a world of multiple global object, this patch
adds a new JS::VM object that houses the JS::Heap.
This means that the Heap moves out of Interpreter, and the same Heap
can now be used by multiple Interpreters, and can also outlive them.
The VM keeps a stack of Interpreter pointers. We push/pop on this
stack when entering/exiting execution with a given Interpreter.
This allows us to make this change without disturbing too much of
the existing code.
There is still a 1-to-1 relationship between Interpreter and the
global object. This will change in the future.
Ultimately, the goal here is to make Interpreter a transient object
that only needs to exist while you execute some code. Getting there
will take a lot more work though. :^)
Note that in LibWeb, the global JS::VM is called main_thread_vm(),
to distinguish it from future worker VM's.
|
|
|
|
This one is a little weird. I don't know why it's okay for this
function to assume that there is a current scope on the scope stack
when it can be called during global object initialization etc.
For now, just make it say "we are in strict mode" when there is no
currently active scope.
|
|
Shape was allocating property tables inside visit_children(), which
could cause garbage collection to happen. It's not very good to start
a new garbage collection while you are in the middle of one already.
|
|
|
|
In the case of an exception in a property getter function we would not
return early, and a subsequent attempt to call the replacer function
would crash the interpreter due to call_internal() asserting.
Fixes #3548.
|
|
Fixes #3471, adds a test.
|
|
|
|
The parser considers it a syntax error at the moment, other engines
throw a ReferenceError during runtime for ++foo(), --foo(), foo()++ and
foo()--, so I assume the spec defines this.
|
|
|
|
This fixes two cases obj[expr] and obj[expr]() (MemberExpression and
CallExpression respectively) when expr throws an exception and results
in an empty value, causing a crash by passing the invalid PropertyName
created by computed_property_name() to Object::get() without checking it
first.
Fixes #3459.
|
|
This fixes two issues with running a TryStatement finalizer:
- Temporarily store and clear the exception, if any, so we can run the
finalizer block statement without it getting in our way, which could
have unexpected side effects otherwise (and will likely return early
somewhere).
- Stop unwinding so more than one child node of the finalizer
BlockStatement is executed if an exception has been thrown previously
(which would have called unwind(ScopeType::Try)). Re-throwing as
described above ensures we still unwind after the finalizer, if
necessary.
Also add some tests specifically for try/catch/finally blocks, we
didn't have any!
|
|
Interpreter::run() was so far being used both as the "public API entry
point" for running a JS::Program as well as internally to execute
JS::Statement|s of all kinds - this is now more distinctly separated.
A program as returned by the parser is still going through run(), which
is responsible for creating the initial global call frame, but all other
statements are executed via execute_statement() directly.
Fixes #3437, a regression introduced by adding ASSERT(!exception()) to
run() without considering the effects that would have on internal usage.
|
|
This broke in case of unterminated regular expressions, causing goofy location
numbers, and 'source_location_hint' to eat up all memory:
Unexpected token UnterminatedRegexLiteral. Expected statement (line: 2, column: 4294967292)
|