Ver código fonte

LibJS: Let the VM cache an empty ("") PrimitiveString

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.
Andreas Kling 4 anos atrás
pai
commit
69bbf0285b

+ 2 - 0
Libraries/LibJS/Runtime/PrimitiveString.cpp

@@ -41,6 +41,8 @@ PrimitiveString::~PrimitiveString()
 
 
 PrimitiveString* js_string(Heap& heap, String string)
 PrimitiveString* js_string(Heap& heap, String string)
 {
 {
+    if (string.is_empty())
+        return &heap.vm().empty_string();
     return heap.allocate_without_global_object<PrimitiveString>(move(string));
     return heap.allocate_without_global_object<PrimitiveString>(move(string));
 }
 }
 
 

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

@@ -38,6 +38,7 @@ NonnullRefPtr<VM> VM::create()
 VM::VM()
 VM::VM()
     : m_heap(*this)
     : m_heap(*this)
 {
 {
+    m_empty_string = m_heap.allocate_without_global_object<PrimitiveString>(String::empty());
 #define __JS_ENUMERATE(SymbolName, snake_name) \
 #define __JS_ENUMERATE(SymbolName, snake_name) \
     m_well_known_symbol_##snake_name = js_symbol(*this, "Symbol." #SymbolName, false);
     m_well_known_symbol_##snake_name = js_symbol(*this, "Symbol." #SymbolName, false);
     JS_ENUMERATE_WELL_KNOWN_SYMBOLS
     JS_ENUMERATE_WELL_KNOWN_SYMBOLS
@@ -86,6 +87,7 @@ VM::InterpreterExecutionScope::~InterpreterExecutionScope()
 
 
 void VM::gather_roots(HashTable<Cell*>& roots)
 void VM::gather_roots(HashTable<Cell*>& roots)
 {
 {
+    roots.set(m_empty_string);
     if (m_exception)
     if (m_exception)
         roots.set(m_exception);
         roots.set(m_exception);
     for (auto* interpreter : m_interpreters)
     for (auto* interpreter : m_interpreters)

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

@@ -71,6 +71,8 @@ public:
 
 
     Symbol* get_global_symbol(const String& description);
     Symbol* get_global_symbol(const String& description);
 
 
+    PrimitiveString& empty_string() { return *m_empty_string; }
+
 private:
 private:
     VM();
     VM();
 
 
@@ -81,6 +83,8 @@ private:
 
 
     HashMap<String, Symbol*> m_global_symbol_map;
     HashMap<String, Symbol*> m_global_symbol_map;
 
 
+    PrimitiveString* m_empty_string { nullptr };
+
 #define __JS_ENUMERATE(SymbolName, snake_name) \
 #define __JS_ENUMERATE(SymbolName, snake_name) \
     Symbol* m_well_known_symbol_##snake_name { nullptr };
     Symbol* m_well_known_symbol_##snake_name { nullptr };
     JS_ENUMERATE_WELL_KNOWN_SYMBOLS
     JS_ENUMERATE_WELL_KNOWN_SYMBOLS