Browse Source

LibJS: Move well-known symbols to the VM

No need to instantiate unique symbols for each Interpreter; they can
be VM-global. This reduces the memory cost and startup time anyway.
Andreas Kling 4 years ago
parent
commit
d1b58ee9ad

+ 0 - 23
Libraries/LibJS/Interpreter.cpp

@@ -48,10 +48,6 @@ Interpreter::Interpreter(VM& vm)
     : m_vm(vm)
     , m_console(*this)
 {
-#define __JS_ENUMERATE(SymbolName, snake_name) \
-    m_well_known_symbol_##snake_name = js_symbol(*this, "Symbol." #SymbolName, false);
-    JS_ENUMERATE_WELL_KNOWN_SYMBOLS
-#undef __JS_ENUMERATE
 }
 
 Interpreter::~Interpreter()
@@ -212,17 +208,6 @@ Reference Interpreter::get_reference(const FlyString& name)
     return { Reference::GlobalVariable, name };
 }
 
-Symbol* Interpreter::get_global_symbol(const String& description)
-{
-    auto result = m_global_symbol_map.get(description);
-    if (result.has_value())
-        return result.value();
-
-    auto new_global_symbol = js_symbol(*this, description, true);
-    m_global_symbol_map.set(description, new_global_symbol);
-    return new_global_symbol;
-}
-
 void Interpreter::gather_roots(HashTable<Cell*>& roots)
 {
     if (m_last_value.is_cell())
@@ -237,14 +222,6 @@ void Interpreter::gather_roots(HashTable<Cell*>& roots)
         }
         roots.set(call_frame.environment);
     }
-
-#define __JS_ENUMERATE(SymbolName, snake_name) \
-    roots.set(well_known_symbol_##snake_name());
-    JS_ENUMERATE_WELL_KNOWN_SYMBOLS
-#undef __JS_ENUMERATE
-
-    for (auto& symbol : m_global_symbol_map)
-        roots.set(symbol.value);
 }
 
 Value Interpreter::call_internal(Function& function, Value this_value, Optional<MarkedValueList> arguments)

+ 0 - 14
Libraries/LibJS/Interpreter.h

@@ -134,8 +134,6 @@ public:
 
     Reference get_reference(const FlyString& name);
 
-    Symbol* get_global_symbol(const String& description);
-
     void gather_roots(HashTable<Cell*>&);
 
     void enter_scope(const ScopeNode&, ArgumentVector, ScopeType, GlobalObject&);
@@ -228,11 +226,6 @@ public:
     const LexicalEnvironment* get_this_environment() const;
     Value get_new_target() const;
 
-#define __JS_ENUMERATE(SymbolName, snake_name) \
-    Symbol* well_known_symbol_##snake_name() const { return m_well_known_symbol_##snake_name; }
-    JS_ENUMERATE_WELL_KNOWN_SYMBOLS
-#undef __JS_ENUMERATE
-
 private:
     explicit Interpreter(VM&);
 
@@ -253,13 +246,6 @@ private:
     bool m_underscore_is_last_value { false };
 
     Console m_console;
-
-    HashMap<String, Symbol*> m_global_symbol_map;
-
-#define __JS_ENUMERATE(SymbolName, snake_name) \
-    Symbol* m_well_known_symbol_##snake_name { nullptr };
-    JS_ENUMERATE_WELL_KNOWN_SYMBOLS
-#undef __JS_ENUMERATE
 };
 
 template<>

+ 1 - 1
Libraries/LibJS/Runtime/ArrayIteratorPrototype.cpp

@@ -43,7 +43,7 @@ void ArrayIteratorPrototype::initialize(GlobalObject& global_object)
     Object::initialize(global_object);
 
     define_native_function("next", next, 0, Attribute::Configurable | Attribute::Writable);
-    define_property(global_object.interpreter().well_known_symbol_to_string_tag(), js_string(global_object.heap(), "Array Iterator"), Attribute::Configurable);
+    define_property(global_object.vm().well_known_symbol_to_string_tag(), js_string(global_object.heap(), "Array Iterator"), Attribute::Configurable);
 }
 
 ArrayIteratorPrototype::~ArrayIteratorPrototype()

+ 1 - 1
Libraries/LibJS/Runtime/ArrayPrototype.cpp

@@ -80,7 +80,7 @@ void ArrayPrototype::initialize(GlobalObject& global_object)
     // Use define_property here instead of define_native_function so that
     // Object.is(Array.prototype[Symbol.iterator], Array.prototype.values)
     // evaluates to true
-    define_property(global_object.interpreter().well_known_symbol_iterator(), get("values"), attr);
+    define_property(global_object.vm().well_known_symbol_iterator(), get("values"), attr);
 }
 
 ArrayPrototype::~ArrayPrototype()

+ 1 - 1
Libraries/LibJS/Runtime/BigIntPrototype.cpp

@@ -45,7 +45,7 @@ void BigIntPrototype::initialize(GlobalObject& global_object)
     define_native_function("toLocaleString", to_locale_string, 0, attr);
     define_native_function("valueOf", value_of, 0, attr);
 
-    define_property(global_object.interpreter().well_known_symbol_to_string_tag(), js_string(global_object.heap(), "BigInt"), Attribute::Configurable);
+    define_property(global_object.vm().well_known_symbol_to_string_tag(), js_string(global_object.heap(), "BigInt"), Attribute::Configurable);
 }
 
 BigIntPrototype::~BigIntPrototype()

+ 1 - 1
Libraries/LibJS/Runtime/FunctionPrototype.cpp

@@ -51,7 +51,7 @@ void FunctionPrototype::initialize(GlobalObject& global_object)
     define_native_function("bind", bind, 1, attr);
     define_native_function("call", call, 1, attr);
     define_native_function("toString", to_string, 0, attr);
-    define_native_function(global_object.interpreter().well_known_symbol_has_instance(), symbol_has_instance, 1, 0);
+    define_native_function(global_object.vm().well_known_symbol_has_instance(), symbol_has_instance, 1, 0);
     define_property("length", Value(0), Attribute::Configurable);
     define_property("name", js_string(heap(), ""), Attribute::Configurable);
 }

+ 1 - 1
Libraries/LibJS/Runtime/IteratorOperations.cpp

@@ -41,7 +41,7 @@ Object* get_iterator(GlobalObject& global_object, Value value, String hint, Valu
         auto object = value.to_object(interpreter, global_object);
         if (!object)
             return {};
-        method = object->get(interpreter.well_known_symbol_iterator());
+        method = object->get(global_object.vm().well_known_symbol_iterator());
         if (interpreter.exception())
             return {};
     }

+ 1 - 1
Libraries/LibJS/Runtime/IteratorPrototype.cpp

@@ -37,7 +37,7 @@ IteratorPrototype::IteratorPrototype(GlobalObject& global_object)
 void IteratorPrototype::initialize(GlobalObject& global_object)
 {
     Object::initialize(global_object);
-    define_native_function(global_object.interpreter().well_known_symbol_iterator(), symbol_iterator, 0, Attribute::Writable | Attribute::Enumerable);
+    define_native_function(global_object.vm().well_known_symbol_iterator(), symbol_iterator, 0, Attribute::Writable | Attribute::Enumerable);
 }
 
 IteratorPrototype::~IteratorPrototype()

+ 1 - 1
Libraries/LibJS/Runtime/JSONObject.cpp

@@ -49,7 +49,7 @@ void JSONObject::initialize(GlobalObject& global_object)
     define_native_function("stringify", stringify, 3, attr);
     define_native_function("parse", parse, 2, attr);
 
-    define_property(global_object.interpreter().well_known_symbol_to_string_tag(), js_string(global_object.heap(), "JSON"), Attribute::Configurable);
+    define_property(global_object.vm().well_known_symbol_to_string_tag(), js_string(global_object.heap(), "JSON"), Attribute::Configurable);
 }
 
 JSONObject::~JSONObject()

+ 1 - 1
Libraries/LibJS/Runtime/MathObject.cpp

@@ -75,7 +75,7 @@ void MathObject::initialize(GlobalObject& global_object)
     define_property("SQRT1_2", Value(M_SQRT1_2), 0);
     define_property("SQRT2", Value(M_SQRT2), 0);
 
-    define_property(global_object.interpreter().well_known_symbol_to_string_tag(), js_string(global_object.heap(), "Math"), Attribute::Configurable);
+    define_property(global_object.vm().well_known_symbol_to_string_tag(), js_string(global_object.heap(), "Math"), Attribute::Configurable);
 }
 
 MathObject::~MathObject()

+ 1 - 1
Libraries/LibJS/Runtime/ObjectPrototype.cpp

@@ -80,7 +80,7 @@ JS_DEFINE_NATIVE_FUNCTION(ObjectPrototype::to_string)
         return {};
 
     String tag;
-    auto to_string_tag = this_object->get(global_object.interpreter().well_known_symbol_to_string_tag());
+    auto to_string_tag = this_object->get(global_object.vm().well_known_symbol_to_string_tag());
     
     if (to_string_tag.is_string()) {
         tag = to_string_tag.as_string().string();

+ 1 - 1
Libraries/LibJS/Runtime/StringIteratorPrototype.cpp

@@ -43,7 +43,7 @@ void StringIteratorPrototype::initialize(GlobalObject& global_object)
     Object::initialize(global_object);
 
     define_native_function("next", next, 0, Attribute::Configurable | Attribute::Writable);
-    define_property(global_object.interpreter().well_known_symbol_to_string_tag(), js_string(global_object.heap(), "String Iterator"), Attribute::Configurable);
+    define_property(global_object.vm().well_known_symbol_to_string_tag(), js_string(global_object.heap(), "String Iterator"), Attribute::Configurable);
 }
 
 StringIteratorPrototype::~StringIteratorPrototype()

+ 1 - 1
Libraries/LibJS/Runtime/StringPrototype.cpp

@@ -89,7 +89,7 @@ void StringPrototype::initialize(GlobalObject& global_object)
     define_native_function("includes", includes, 1, attr);
     define_native_function("slice", slice, 2, attr);
     define_native_function("lastIndexOf", last_index_of, 1, attr);
-    define_native_function(global_object.interpreter().well_known_symbol_iterator(), symbol_iterator, 0, attr);
+    define_native_function(global_object.vm().well_known_symbol_iterator(), symbol_iterator, 0, attr);
 }
 
 StringPrototype::~StringPrototype()

+ 5 - 0
Libraries/LibJS/Runtime/Symbol.cpp

@@ -45,6 +45,11 @@ Symbol* js_symbol(Heap& heap, String description, bool is_global)
     return heap.allocate_without_global_object<Symbol>(move(description), is_global);
 }
 
+Symbol* js_symbol(VM& vm, String description, bool is_global)
+{
+    return js_symbol(vm.heap(), move(description), is_global);
+}
+
 Symbol* js_symbol(Interpreter& interpreter, String description, bool is_global)
 {
     return js_symbol(interpreter.heap(), description, is_global);

+ 1 - 0
Libraries/LibJS/Runtime/Symbol.h

@@ -52,5 +52,6 @@ private:
 
 Symbol* js_symbol(Heap&, String description, bool is_global);
 Symbol* js_symbol(Interpreter&, String description, bool is_global);
+Symbol* js_symbol(VM&, String description, bool is_global);
 
 }

+ 2 - 2
Libraries/LibJS/Runtime/SymbolConstructor.cpp

@@ -47,7 +47,7 @@ void SymbolConstructor::initialize(GlobalObject& global_object)
     define_native_function("keyFor", key_for, 1, Attribute::Writable | Attribute::Configurable);
 
 #define __JS_ENUMERATE(SymbolName, snake_name) \
-    define_property(#SymbolName, global_object.interpreter().well_known_symbol_##snake_name(), 0);
+    define_property(#SymbolName, global_object.vm().well_known_symbol_##snake_name(), 0);
     JS_ENUMERATE_WELL_KNOWN_SYMBOLS
 #undef __JS_ENUMERATE
 }
@@ -78,7 +78,7 @@ JS_DEFINE_NATIVE_FUNCTION(SymbolConstructor::for_)
         description = interpreter.argument(0).to_string(interpreter);
     }
 
-    return interpreter.get_global_symbol(description);
+    return global_object.vm().get_global_symbol(description);
 }
 
 JS_DEFINE_NATIVE_FUNCTION(SymbolConstructor::key_for)

+ 1 - 1
Libraries/LibJS/Runtime/SymbolPrototype.cpp

@@ -51,7 +51,7 @@ void SymbolPrototype::initialize(GlobalObject& global_object)
     define_native_function("toString", to_string, 0, Attribute::Writable | Attribute::Configurable);
     define_native_function("valueOf", value_of, 0, Attribute::Writable | Attribute::Configurable);
 
-    define_property(global_object.interpreter().well_known_symbol_to_string_tag(), js_string(global_object.heap(), "Symbol"), Attribute::Configurable);
+    define_property(global_object.vm().well_known_symbol_to_string_tag(), js_string(global_object.heap(), "Symbol"), Attribute::Configurable);
 }
 
 SymbolPrototype::~SymbolPrototype()

+ 24 - 0
Libraries/LibJS/Runtime/VM.cpp

@@ -25,6 +25,7 @@
  */
 
 #include <LibJS/Interpreter.h>
+#include <LibJS/Runtime/Symbol.h>
 #include <LibJS/Runtime/VM.h>
 
 namespace JS {
@@ -37,6 +38,10 @@ NonnullRefPtr<VM> VM::create()
 VM::VM()
     : m_heap(*this)
 {
+#define __JS_ENUMERATE(SymbolName, snake_name) \
+    m_well_known_symbol_##snake_name = js_symbol(*this, "Symbol." #SymbolName, false);
+    JS_ENUMERATE_WELL_KNOWN_SYMBOLS
+#undef __JS_ENUMERATE
 }
 
 VM::~VM()
@@ -85,6 +90,25 @@ void VM::gather_roots(HashTable<Cell*>& roots)
         roots.set(m_exception);
     for (auto* interpreter : m_interpreters)
         interpreter->gather_roots(roots);
+
+#define __JS_ENUMERATE(SymbolName, snake_name) \
+    roots.set(well_known_symbol_##snake_name());
+    JS_ENUMERATE_WELL_KNOWN_SYMBOLS
+#undef __JS_ENUMERATE
+
+    for (auto& symbol : m_global_symbol_map)
+        roots.set(symbol.value);
+}
+
+Symbol* VM::get_global_symbol(const String& description)
+{
+    auto result = m_global_symbol_map.get(description);
+    if (result.has_value())
+        return result.value();
+
+    auto new_global_symbol = js_symbol(*this, description, true);
+    m_global_symbol_map.set(description, new_global_symbol);
+    return new_global_symbol;
 }
 
 }

+ 15 - 0
Libraries/LibJS/Runtime/VM.h

@@ -26,6 +26,7 @@
 
 #pragma once
 
+#include <AK/HashMap.h>
 #include <AK/RefCounted.h>
 #include <LibJS/Heap/Heap.h>
 
@@ -63,6 +64,13 @@ public:
 
     void gather_roots(HashTable<Cell*>&);
 
+#define __JS_ENUMERATE(SymbolName, snake_name) \
+    Symbol* well_known_symbol_##snake_name() const { return m_well_known_symbol_##snake_name; }
+    JS_ENUMERATE_WELL_KNOWN_SYMBOLS
+#undef __JS_ENUMERATE
+
+    Symbol* get_global_symbol(const String& description);
+
 private:
     VM();
 
@@ -70,6 +78,13 @@ private:
 
     Heap m_heap;
     Vector<Interpreter*> m_interpreters;
+
+    HashMap<String, Symbol*> m_global_symbol_map;
+
+#define __JS_ENUMERATE(SymbolName, snake_name) \
+    Symbol* m_well_known_symbol_##snake_name { nullptr };
+    JS_ENUMERATE_WELL_KNOWN_SYMBOLS
+#undef __JS_ENUMERATE
 };
 
 }

+ 1 - 1
Libraries/LibJS/Runtime/Value.cpp

@@ -702,7 +702,7 @@ Value instance_of(Interpreter& interpreter, Value lhs, Value rhs)
         interpreter.throw_exception<TypeError>(ErrorType::NotAnObject, rhs.to_string_without_side_effects().characters());
         return {};
     }
-    auto has_instance_method = rhs.as_object().get(interpreter.well_known_symbol_has_instance());
+    auto has_instance_method = rhs.as_object().get(interpreter.vm().well_known_symbol_has_instance());
     if (!has_instance_method.is_empty()) {
         if (!has_instance_method.is_function()) {
             interpreter.throw_exception<TypeError>(ErrorType::NotAFunction, has_instance_method.to_string_without_side_effects().characters());