mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 20:27:45 +00:00
LibJS+Clients: Add JS::VM object, separate Heap from 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 commit is contained in:
parent
c6ae0c41d9
commit
1c43442be4
13 changed files with 218 additions and 27 deletions
|
@ -37,9 +37,17 @@
|
||||||
|
|
||||||
namespace Spreadsheet {
|
namespace Spreadsheet {
|
||||||
|
|
||||||
|
static JS::VM& global_vm()
|
||||||
|
{
|
||||||
|
static RefPtr<JS::VM> vm;
|
||||||
|
if (!vm)
|
||||||
|
vm = JS::VM::create();
|
||||||
|
return *vm;
|
||||||
|
}
|
||||||
|
|
||||||
Workbook::Workbook(NonnullRefPtrVector<Sheet>&& sheets)
|
Workbook::Workbook(NonnullRefPtrVector<Sheet>&& sheets)
|
||||||
: m_sheets(move(sheets))
|
: m_sheets(move(sheets))
|
||||||
, m_interpreter(JS::Interpreter::create<JS::GlobalObject>())
|
, m_interpreter(JS::Interpreter::create<JS::GlobalObject>(global_vm()))
|
||||||
{
|
{
|
||||||
m_workbook_object = interpreter().heap().allocate<WorkbookObject>(global_object(), *this);
|
m_workbook_object = interpreter().heap().allocate<WorkbookObject>(global_object(), *this);
|
||||||
global_object().put("workbook", workbook_object());
|
global_object().put("workbook", workbook_object());
|
||||||
|
|
|
@ -72,6 +72,7 @@ set(SOURCES
|
||||||
Runtime/SymbolObject.cpp
|
Runtime/SymbolObject.cpp
|
||||||
Runtime/SymbolPrototype.cpp
|
Runtime/SymbolPrototype.cpp
|
||||||
Runtime/Uint8ClampedArray.cpp
|
Runtime/Uint8ClampedArray.cpp
|
||||||
|
Runtime/VM.cpp
|
||||||
Runtime/Value.cpp
|
Runtime/Value.cpp
|
||||||
Token.cpp
|
Token.cpp
|
||||||
)
|
)
|
||||||
|
|
|
@ -119,6 +119,7 @@ class Statement;
|
||||||
class Symbol;
|
class Symbol;
|
||||||
class Token;
|
class Token;
|
||||||
class Uint8ClampedArray;
|
class Uint8ClampedArray;
|
||||||
|
class VM;
|
||||||
class Value;
|
class Value;
|
||||||
enum class DeclarationKind;
|
enum class DeclarationKind;
|
||||||
|
|
||||||
|
|
|
@ -47,8 +47,8 @@
|
||||||
|
|
||||||
namespace JS {
|
namespace JS {
|
||||||
|
|
||||||
Heap::Heap(Interpreter& interpreter)
|
Heap::Heap(VM& vm)
|
||||||
: m_interpreter(interpreter)
|
: m_vm(vm)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,6 +57,11 @@ Heap::~Heap()
|
||||||
collect_garbage(CollectionType::CollectEverything);
|
collect_garbage(CollectionType::CollectEverything);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Interpreter& Heap::interpreter()
|
||||||
|
{
|
||||||
|
return vm().interpreter();
|
||||||
|
}
|
||||||
|
|
||||||
Cell* Heap::allocate_cell(size_t size)
|
Cell* Heap::allocate_cell(size_t size)
|
||||||
{
|
{
|
||||||
if (should_collect_on_every_allocation()) {
|
if (should_collect_on_every_allocation()) {
|
||||||
|
@ -100,7 +105,8 @@ void Heap::collect_garbage(CollectionType collection_type, bool print_report)
|
||||||
|
|
||||||
void Heap::gather_roots(HashTable<Cell*>& roots)
|
void Heap::gather_roots(HashTable<Cell*>& roots)
|
||||||
{
|
{
|
||||||
m_interpreter.gather_roots({}, roots);
|
if (auto* interpreter = vm().interpreter_if_exists())
|
||||||
|
interpreter->gather_roots({}, roots);
|
||||||
|
|
||||||
gather_conservative_roots(roots);
|
gather_conservative_roots(roots);
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ class Heap {
|
||||||
AK_MAKE_NONMOVABLE(Heap);
|
AK_MAKE_NONMOVABLE(Heap);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Heap(Interpreter&);
|
explicit Heap(VM&);
|
||||||
~Heap();
|
~Heap();
|
||||||
|
|
||||||
template<typename T, typename... Args>
|
template<typename T, typename... Args>
|
||||||
|
@ -71,7 +71,8 @@ public:
|
||||||
|
|
||||||
void collect_garbage(CollectionType = CollectionType::CollectGarbage, bool print_report = false);
|
void collect_garbage(CollectionType = CollectionType::CollectGarbage, bool print_report = false);
|
||||||
|
|
||||||
Interpreter& interpreter() { return m_interpreter; }
|
Interpreter& interpreter();
|
||||||
|
VM& vm() { return m_vm; }
|
||||||
|
|
||||||
bool should_collect_on_every_allocation() const { return m_should_collect_on_every_allocation; }
|
bool should_collect_on_every_allocation() const { return m_should_collect_on_every_allocation; }
|
||||||
void set_should_collect_on_every_allocation(bool b) { m_should_collect_on_every_allocation = b; }
|
void set_should_collect_on_every_allocation(bool b) { m_should_collect_on_every_allocation = b; }
|
||||||
|
@ -100,7 +101,7 @@ private:
|
||||||
|
|
||||||
bool m_should_collect_on_every_allocation { false };
|
bool m_should_collect_on_every_allocation { false };
|
||||||
|
|
||||||
Interpreter& m_interpreter;
|
VM& m_vm;
|
||||||
Vector<NonnullOwnPtr<HeapBlock>> m_blocks;
|
Vector<NonnullOwnPtr<HeapBlock>> m_blocks;
|
||||||
HashTable<HandleImpl*> m_handles;
|
HashTable<HandleImpl*> m_handles;
|
||||||
|
|
||||||
|
|
|
@ -44,8 +44,8 @@
|
||||||
|
|
||||||
namespace JS {
|
namespace JS {
|
||||||
|
|
||||||
Interpreter::Interpreter()
|
Interpreter::Interpreter(VM& vm)
|
||||||
: m_heap(*this)
|
: m_vm(vm)
|
||||||
, m_console(*this)
|
, m_console(*this)
|
||||||
{
|
{
|
||||||
#define __JS_ENUMERATE(SymbolName, snake_name) \
|
#define __JS_ENUMERATE(SymbolName, snake_name) \
|
||||||
|
@ -60,6 +60,8 @@ Interpreter::~Interpreter()
|
||||||
|
|
||||||
Value Interpreter::run(GlobalObject& global_object, const Program& program)
|
Value Interpreter::run(GlobalObject& global_object, const Program& program)
|
||||||
{
|
{
|
||||||
|
VM::InterpreterScope scope(*this);
|
||||||
|
|
||||||
ASSERT(!exception());
|
ASSERT(!exception());
|
||||||
|
|
||||||
if (m_call_stack.is_empty()) {
|
if (m_call_stack.is_empty()) {
|
||||||
|
@ -223,7 +225,6 @@ Symbol* Interpreter::get_global_symbol(const String& description)
|
||||||
|
|
||||||
void Interpreter::gather_roots(Badge<Heap>, HashTable<Cell*>& roots)
|
void Interpreter::gather_roots(Badge<Heap>, HashTable<Cell*>& roots)
|
||||||
{
|
{
|
||||||
roots.set(m_global_object);
|
|
||||||
roots.set(m_exception);
|
roots.set(m_exception);
|
||||||
|
|
||||||
if (m_last_value.is_cell())
|
if (m_last_value.is_cell())
|
||||||
|
@ -252,6 +253,8 @@ Value Interpreter::call_internal(Function& function, Value this_value, Optional<
|
||||||
{
|
{
|
||||||
ASSERT(!exception());
|
ASSERT(!exception());
|
||||||
|
|
||||||
|
VM::InterpreterScope scope(*this);
|
||||||
|
|
||||||
auto& call_frame = push_call_frame();
|
auto& call_frame = push_call_frame();
|
||||||
call_frame.function_name = function.name();
|
call_frame.function_name = function.name();
|
||||||
call_frame.this_value = function.bound_this().value_or(this_value);
|
call_frame.this_value = function.bound_this().value_or(this_value);
|
||||||
|
@ -348,12 +351,12 @@ void Interpreter::throw_exception(Exception* exception)
|
||||||
|
|
||||||
GlobalObject& Interpreter::global_object()
|
GlobalObject& Interpreter::global_object()
|
||||||
{
|
{
|
||||||
return static_cast<GlobalObject&>(*m_global_object);
|
return static_cast<GlobalObject&>(*m_global_object.cell());
|
||||||
}
|
}
|
||||||
|
|
||||||
const GlobalObject& Interpreter::global_object() const
|
const GlobalObject& Interpreter::global_object() const
|
||||||
{
|
{
|
||||||
return static_cast<const GlobalObject&>(*m_global_object);
|
return static_cast<const GlobalObject&>(*m_global_object.cell());
|
||||||
}
|
}
|
||||||
|
|
||||||
String Interpreter::join_arguments() const
|
String Interpreter::join_arguments() const
|
||||||
|
|
|
@ -34,11 +34,13 @@
|
||||||
#include <LibJS/AST.h>
|
#include <LibJS/AST.h>
|
||||||
#include <LibJS/Console.h>
|
#include <LibJS/Console.h>
|
||||||
#include <LibJS/Forward.h>
|
#include <LibJS/Forward.h>
|
||||||
|
#include <LibJS/Heap/DeferGC.h>
|
||||||
#include <LibJS/Heap/Heap.h>
|
#include <LibJS/Heap/Heap.h>
|
||||||
#include <LibJS/Runtime/ErrorTypes.h>
|
#include <LibJS/Runtime/ErrorTypes.h>
|
||||||
#include <LibJS/Runtime/Exception.h>
|
#include <LibJS/Runtime/Exception.h>
|
||||||
#include <LibJS/Runtime/LexicalEnvironment.h>
|
#include <LibJS/Runtime/LexicalEnvironment.h>
|
||||||
#include <LibJS/Runtime/MarkedValueList.h>
|
#include <LibJS/Runtime/MarkedValueList.h>
|
||||||
|
#include <LibJS/Runtime/VM.h>
|
||||||
#include <LibJS/Runtime/Value.h>
|
#include <LibJS/Runtime/Value.h>
|
||||||
|
|
||||||
namespace JS {
|
namespace JS {
|
||||||
|
@ -75,11 +77,13 @@ typedef Vector<Argument, 8> ArgumentVector;
|
||||||
class Interpreter : public Weakable<Interpreter> {
|
class Interpreter : public Weakable<Interpreter> {
|
||||||
public:
|
public:
|
||||||
template<typename GlobalObjectType, typename... Args>
|
template<typename GlobalObjectType, typename... Args>
|
||||||
static NonnullOwnPtr<Interpreter> create(Args&&... args)
|
static NonnullOwnPtr<Interpreter> create(VM& vm, Args&&... args)
|
||||||
{
|
{
|
||||||
auto interpreter = adopt_own(*new Interpreter);
|
DeferGC defer_gc(vm.heap());
|
||||||
interpreter->m_global_object = interpreter->heap().allocate_without_global_object<GlobalObjectType>(forward<Args>(args)...);
|
auto interpreter = adopt_own(*new Interpreter(vm));
|
||||||
static_cast<GlobalObjectType*>(interpreter->m_global_object)->initialize();
|
VM::InterpreterScope scope(*interpreter);
|
||||||
|
interpreter->m_global_object = make_handle(static_cast<Object*>(interpreter->heap().allocate_without_global_object<GlobalObjectType>(forward<Args>(args)...)));
|
||||||
|
static_cast<GlobalObjectType*>(interpreter->m_global_object.cell())->initialize();
|
||||||
return interpreter;
|
return interpreter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +111,8 @@ public:
|
||||||
GlobalObject& global_object();
|
GlobalObject& global_object();
|
||||||
const GlobalObject& global_object() const;
|
const GlobalObject& global_object() const;
|
||||||
|
|
||||||
Heap& heap() { return m_heap; }
|
VM& vm() { return *m_vm; }
|
||||||
|
Heap& heap() { return vm().heap(); }
|
||||||
|
|
||||||
void unwind(ScopeType type, FlyString label = {})
|
void unwind(ScopeType type, FlyString label = {})
|
||||||
{
|
{
|
||||||
|
@ -234,18 +239,18 @@ public:
|
||||||
#undef __JS_ENUMERATE
|
#undef __JS_ENUMERATE
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Interpreter();
|
explicit Interpreter(VM&);
|
||||||
|
|
||||||
[[nodiscard]] Value call_internal(Function&, Value this_value, Optional<MarkedValueList>);
|
[[nodiscard]] Value call_internal(Function&, Value this_value, Optional<MarkedValueList>);
|
||||||
|
|
||||||
Heap m_heap;
|
NonnullRefPtr<VM> m_vm;
|
||||||
|
|
||||||
Value m_last_value;
|
Value m_last_value;
|
||||||
|
|
||||||
Vector<ScopeFrame> m_scope_stack;
|
Vector<ScopeFrame> m_scope_stack;
|
||||||
Vector<CallFrame> m_call_stack;
|
Vector<CallFrame> m_call_stack;
|
||||||
|
|
||||||
Object* m_global_object { nullptr };
|
Handle<Object> m_global_object;
|
||||||
|
|
||||||
Exception* m_exception { nullptr };
|
Exception* m_exception { nullptr };
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <AK/LogStream.h>
|
#include <AK/LogStream.h>
|
||||||
|
#include <LibJS/Heap/DeferGC.h>
|
||||||
#include <LibJS/Interpreter.h>
|
#include <LibJS/Interpreter.h>
|
||||||
#include <LibJS/Runtime/ArrayConstructor.h>
|
#include <LibJS/Runtime/ArrayConstructor.h>
|
||||||
#include <LibJS/Runtime/ArrayIteratorPrototype.h>
|
#include <LibJS/Runtime/ArrayIteratorPrototype.h>
|
||||||
|
@ -87,13 +88,12 @@ void GlobalObject::initialize()
|
||||||
JS_ENUMERATE_BUILTIN_TYPES
|
JS_ENUMERATE_BUILTIN_TYPES
|
||||||
#undef __JS_ENUMERATE
|
#undef __JS_ENUMERATE
|
||||||
|
|
||||||
#define __JS_ENUMERATE(ClassName, snake_name) \
|
#define __JS_ENUMERATE(ClassName, snake_name) \
|
||||||
if (!m_##snake_name##_prototype) \
|
if (!m_##snake_name##_prototype) \
|
||||||
m_##snake_name##_prototype = heap().allocate<ClassName##Prototype>(*this, *this);
|
m_##snake_name##_prototype = heap().allocate<ClassName##Prototype>(*this, *this);
|
||||||
JS_ENUMERATE_ITERATOR_PROTOTYPES
|
JS_ENUMERATE_ITERATOR_PROTOTYPES
|
||||||
#undef __JS_ENUMERATE
|
#undef __JS_ENUMERATE
|
||||||
|
|
||||||
|
|
||||||
u8 attr = Attribute::Writable | Attribute::Configurable;
|
u8 attr = Attribute::Writable | Attribute::Configurable;
|
||||||
define_native_function("gc", gc, 0, attr);
|
define_native_function("gc", gc, 0, attr);
|
||||||
define_native_function("isNaN", is_nan, 1, attr);
|
define_native_function("isNaN", is_nan, 1, attr);
|
||||||
|
|
85
Libraries/LibJS/Runtime/VM.cpp
Normal file
85
Libraries/LibJS/Runtime/VM.cpp
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <LibJS/Interpreter.h>
|
||||||
|
#include <LibJS/Runtime/VM.h>
|
||||||
|
|
||||||
|
namespace JS {
|
||||||
|
|
||||||
|
NonnullRefPtr<VM> VM::create()
|
||||||
|
{
|
||||||
|
return adopt(*new VM);
|
||||||
|
}
|
||||||
|
|
||||||
|
VM::VM()
|
||||||
|
: m_heap(*this)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VM::~VM()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Interpreter& VM::interpreter()
|
||||||
|
{
|
||||||
|
if (m_interpreters.is_empty()) {
|
||||||
|
asm volatile("ud2");
|
||||||
|
}
|
||||||
|
// ASSERT(!m_interpreters.is_empty());
|
||||||
|
return *m_interpreters.last();
|
||||||
|
}
|
||||||
|
|
||||||
|
Interpreter* VM::interpreter_if_exists()
|
||||||
|
{
|
||||||
|
if (m_interpreters.is_empty())
|
||||||
|
return nullptr;
|
||||||
|
return m_interpreters.last();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VM::push_interpreter(Interpreter& interpreter)
|
||||||
|
{
|
||||||
|
m_interpreters.append(&interpreter);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VM::pop_interpreter(Interpreter& interpreter)
|
||||||
|
{
|
||||||
|
ASSERT(!m_interpreters.is_empty());
|
||||||
|
auto* popped_interpreter = m_interpreters.take_last();
|
||||||
|
ASSERT(popped_interpreter == &interpreter);
|
||||||
|
}
|
||||||
|
|
||||||
|
VM::InterpreterScope::InterpreterScope(Interpreter& interpreter)
|
||||||
|
: m_interpreter(interpreter)
|
||||||
|
{
|
||||||
|
m_interpreter.vm().push_interpreter(m_interpreter);
|
||||||
|
}
|
||||||
|
|
||||||
|
VM::InterpreterScope::~InterpreterScope()
|
||||||
|
{
|
||||||
|
m_interpreter.vm().pop_interpreter(m_interpreter);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
63
Libraries/LibJS/Runtime/VM.h
Normal file
63
Libraries/LibJS/Runtime/VM.h
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/RefCounted.h>
|
||||||
|
#include <LibJS/Heap/Heap.h>
|
||||||
|
|
||||||
|
namespace JS {
|
||||||
|
|
||||||
|
class VM : public RefCounted<VM> {
|
||||||
|
public:
|
||||||
|
static NonnullRefPtr<VM> create();
|
||||||
|
~VM();
|
||||||
|
|
||||||
|
Heap& heap() { return m_heap; }
|
||||||
|
const Heap& heap() const { return m_heap; }
|
||||||
|
|
||||||
|
Interpreter& interpreter();
|
||||||
|
Interpreter* interpreter_if_exists();
|
||||||
|
|
||||||
|
void push_interpreter(Interpreter&);
|
||||||
|
void pop_interpreter(Interpreter&);
|
||||||
|
|
||||||
|
class InterpreterScope {
|
||||||
|
public:
|
||||||
|
InterpreterScope(Interpreter&);
|
||||||
|
~InterpreterScope();
|
||||||
|
private:
|
||||||
|
Interpreter& m_interpreter;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
VM();
|
||||||
|
|
||||||
|
Heap m_heap;
|
||||||
|
Vector<Interpreter*> m_interpreters;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -408,10 +408,18 @@ Color Document::visited_link_color() const
|
||||||
return frame()->page().palette().visited_link();
|
return frame()->page().palette().visited_link();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static JS::VM& main_thread_vm()
|
||||||
|
{
|
||||||
|
static RefPtr<JS::VM> vm;
|
||||||
|
if (!vm)
|
||||||
|
vm = JS::VM::create();
|
||||||
|
return *vm;
|
||||||
|
}
|
||||||
|
|
||||||
JS::Interpreter& Document::interpreter()
|
JS::Interpreter& Document::interpreter()
|
||||||
{
|
{
|
||||||
if (!m_interpreter)
|
if (!m_interpreter)
|
||||||
m_interpreter = JS::Interpreter::create<Bindings::WindowObject>(*m_window);
|
m_interpreter = JS::Interpreter::create<Bindings::WindowObject>(main_thread_vm(), *m_window);
|
||||||
return *m_interpreter;
|
return *m_interpreter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -552,6 +552,7 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
bool syntax_highlight = !disable_syntax_highlight;
|
bool syntax_highlight = !disable_syntax_highlight;
|
||||||
|
|
||||||
|
auto vm = JS::VM::create();
|
||||||
OwnPtr<JS::Interpreter> interpreter;
|
OwnPtr<JS::Interpreter> interpreter;
|
||||||
|
|
||||||
interrupt_interpreter = [&] {
|
interrupt_interpreter = [&] {
|
||||||
|
@ -561,7 +562,7 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
if (script_path == nullptr) {
|
if (script_path == nullptr) {
|
||||||
s_print_last_result = true;
|
s_print_last_result = true;
|
||||||
interpreter = JS::Interpreter::create<ReplObject>();
|
interpreter = JS::Interpreter::create<ReplObject>(*vm);
|
||||||
ReplConsoleClient console_client(interpreter->console());
|
ReplConsoleClient console_client(interpreter->console());
|
||||||
interpreter->console().set_client(console_client);
|
interpreter->console().set_client(console_client);
|
||||||
interpreter->heap().set_should_collect_on_every_allocation(gc_on_every_allocation);
|
interpreter->heap().set_should_collect_on_every_allocation(gc_on_every_allocation);
|
||||||
|
@ -842,7 +843,7 @@ int main(int argc, char** argv)
|
||||||
s_editor->on_tab_complete = move(complete);
|
s_editor->on_tab_complete = move(complete);
|
||||||
repl(*interpreter);
|
repl(*interpreter);
|
||||||
} else {
|
} else {
|
||||||
interpreter = JS::Interpreter::create<JS::GlobalObject>();
|
interpreter = JS::Interpreter::create<JS::GlobalObject>(*vm);
|
||||||
ReplConsoleClient console_client(interpreter->console());
|
ReplConsoleClient console_client(interpreter->console());
|
||||||
interpreter->console().set_client(console_client);
|
interpreter->console().set_client(console_client);
|
||||||
interpreter->heap().set_should_collect_on_every_allocation(gc_on_every_allocation);
|
interpreter->heap().set_should_collect_on_every_allocation(gc_on_every_allocation);
|
||||||
|
|
|
@ -43,6 +43,8 @@
|
||||||
|
|
||||||
#define TOP_LEVEL_TEST_NAME "__$$TOP_LEVEL$$__"
|
#define TOP_LEVEL_TEST_NAME "__$$TOP_LEVEL$$__"
|
||||||
|
|
||||||
|
RefPtr<JS::VM> vm;
|
||||||
|
|
||||||
static bool collect_on_every_allocation = false;
|
static bool collect_on_every_allocation = false;
|
||||||
static String currently_running_test;
|
static String currently_running_test;
|
||||||
|
|
||||||
|
@ -273,7 +275,10 @@ JSFileResult TestRunner::run_file_test(const String& test_path)
|
||||||
currently_running_test = test_path;
|
currently_running_test = test_path;
|
||||||
|
|
||||||
double start_time = get_time_in_ms();
|
double start_time = get_time_in_ms();
|
||||||
auto interpreter = JS::Interpreter::create<TestRunnerGlobalObject>();
|
auto interpreter = JS::Interpreter::create<TestRunnerGlobalObject>(*vm);
|
||||||
|
|
||||||
|
// FIXME: This is a hack while we're refactoring Interpreter/VM stuff.
|
||||||
|
JS::VM::InterpreterScope scope(*interpreter);
|
||||||
|
|
||||||
interpreter->heap().set_should_collect_on_every_allocation(collect_on_every_allocation);
|
interpreter->heap().set_should_collect_on_every_allocation(collect_on_every_allocation);
|
||||||
|
|
||||||
|
@ -603,6 +608,8 @@ int main(int argc, char** argv)
|
||||||
DebugLogStream::set_enabled(false);
|
DebugLogStream::set_enabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vm = JS::VM::create();
|
||||||
|
|
||||||
#ifdef __serenity__
|
#ifdef __serenity__
|
||||||
TestRunner("/home/anon/js-tests", print_times).run();
|
TestRunner("/home/anon/js-tests", print_times).run();
|
||||||
#else
|
#else
|
||||||
|
@ -614,5 +621,7 @@ int main(int argc, char** argv)
|
||||||
TestRunner(String::format("%s/Libraries/LibJS/Tests", serenity_root), print_times).run();
|
TestRunner(String::format("%s/Libraries/LibJS/Tests", serenity_root), print_times).run();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
vm = nullptr;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue