Title: [270870] trunk/Source/_javascript_Core
Revision
270870
Author
sbar...@apple.com
Date
2020-12-15 15:18:33 -0800 (Tue, 15 Dec 2020)

Log Message

Switch to using a linked list for the TDZ environment instead of a Vector
https://bugs.webkit.org/show_bug.cgi?id=219909
<rdar://71441753>

Reviewed by Tadeu Zagallo.

Before, we'd represent the TDZ stack in terms of a Vector. While the entries
in the Vector were reference counted, the spine of the Vector itself would
match the length of the TDZ scope stack. It turns out this spine itself can
use non-trivial amounts of memory. We are seeing about a 0.5% regression from
this inside RAMification. This change makes it so that we now use a tree-like
data structure for scope stack entries. The data structure is a tree with only
parent pointers. Any field that used to be a vector of entries is now a
pointer to a node in this tree. So any pointer into this tree will have a
linked-list window into the tree, where the linked-list represents the same
data as the previous vector-as-stack data structure.

Initial testing shows this might be up to a 0.5% progression on RAMification.

* builtins/BuiltinExecutables.cpp:
(JSC::BuiltinExecutables::createExecutable):
* bytecode/UnlinkedFunctionExecutable.cpp:
(JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
* bytecode/UnlinkedFunctionExecutable.h:
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator):
(JSC::BytecodeGenerator::popLexicalScopeInternal):
(JSC::BytecodeGenerator::needsTDZCheck):
(JSC::BytecodeGenerator::liftTDZCheckIfPossible):
(JSC::BytecodeGenerator::pushTDZVariables):
(JSC::BytecodeGenerator::getVariablesUnderTDZ):
(JSC::BytecodeGenerator::preserveTDZStack):
(JSC::BytecodeGenerator::restoreTDZStack):
* bytecompiler/BytecodeGenerator.h:
(JSC::BytecodeGenerator::generate):
* parser/VariableEnvironment.h:
(JSC::TDZEnvironmentLink::TDZEnvironmentLink):
(JSC::TDZEnvironmentLink::create):
(JSC::TDZEnvironmentLink::contains const):
(JSC::TDZEnvironmentLink::parent):
* runtime/CachedTypes.cpp:
(JSC::CachedTDZEnvironmentLink::encode):
(JSC::CachedTDZEnvironmentLink::decode const):
* runtime/CodeCache.cpp:
(JSC::generateUnlinkedCodeBlockImpl):
(JSC::CodeCache::getUnlinkedGlobalFunctionExecutable):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (270869 => 270870)


--- trunk/Source/_javascript_Core/ChangeLog	2020-12-15 23:09:07 UTC (rev 270869)
+++ trunk/Source/_javascript_Core/ChangeLog	2020-12-15 23:18:33 UTC (rev 270870)
@@ -1,3 +1,52 @@
+2020-12-15  Saam Barati  <sbar...@apple.com>
+
+        Switch to using a linked list for the TDZ environment instead of a Vector
+        https://bugs.webkit.org/show_bug.cgi?id=219909
+        <rdar://71441753>
+
+        Reviewed by Tadeu Zagallo.
+
+        Before, we'd represent the TDZ stack in terms of a Vector. While the entries
+        in the Vector were reference counted, the spine of the Vector itself would
+        match the length of the TDZ scope stack. It turns out this spine itself can
+        use non-trivial amounts of memory. We are seeing about a 0.5% regression from
+        this inside RAMification. This change makes it so that we now use a tree-like
+        data structure for scope stack entries. The data structure is a tree with only
+        parent pointers. Any field that used to be a vector of entries is now a
+        pointer to a node in this tree. So any pointer into this tree will have a
+        linked-list window into the tree, where the linked-list represents the same
+        data as the previous vector-as-stack data structure.
+        
+        Initial testing shows this might be up to a 0.5% progression on RAMification.
+
+        * builtins/BuiltinExecutables.cpp:
+        (JSC::BuiltinExecutables::createExecutable):
+        * bytecode/UnlinkedFunctionExecutable.cpp:
+        (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
+        * bytecode/UnlinkedFunctionExecutable.h:
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::BytecodeGenerator):
+        (JSC::BytecodeGenerator::popLexicalScopeInternal):
+        (JSC::BytecodeGenerator::needsTDZCheck):
+        (JSC::BytecodeGenerator::liftTDZCheckIfPossible):
+        (JSC::BytecodeGenerator::pushTDZVariables):
+        (JSC::BytecodeGenerator::getVariablesUnderTDZ):
+        (JSC::BytecodeGenerator::preserveTDZStack):
+        (JSC::BytecodeGenerator::restoreTDZStack):
+        * bytecompiler/BytecodeGenerator.h:
+        (JSC::BytecodeGenerator::generate):
+        * parser/VariableEnvironment.h:
+        (JSC::TDZEnvironmentLink::TDZEnvironmentLink):
+        (JSC::TDZEnvironmentLink::create):
+        (JSC::TDZEnvironmentLink::contains const):
+        (JSC::TDZEnvironmentLink::parent):
+        * runtime/CachedTypes.cpp:
+        (JSC::CachedTDZEnvironmentLink::encode):
+        (JSC::CachedTDZEnvironmentLink::decode const):
+        * runtime/CodeCache.cpp:
+        (JSC::generateUnlinkedCodeBlockImpl):
+        (JSC::CodeCache::getUnlinkedGlobalFunctionExecutable):
+
 2020-12-15  Commit Queue  <commit-qu...@webkit.org>
 
         Unreviewed, reverting r270860.

Modified: trunk/Source/_javascript_Core/builtins/BuiltinExecutables.cpp (270869 => 270870)


--- trunk/Source/_javascript_Core/builtins/BuiltinExecutables.cpp	2020-12-15 23:09:07 UTC (rev 270869)
+++ trunk/Source/_javascript_Core/builtins/BuiltinExecutables.cpp	2020-12-15 23:18:33 UTC (rev 270870)
@@ -251,7 +251,7 @@
         }
     }
 
-    UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(vm, source, &metadata, kind, constructAbility, JSParserScriptMode::Classic, WTF::nullopt, DerivedContextType::None, needsClassFieldInitializer, isBuiltinDefaultClassConstructor);
+    UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(vm, source, &metadata, kind, constructAbility, JSParserScriptMode::Classic, nullptr, DerivedContextType::None, needsClassFieldInitializer, isBuiltinDefaultClassConstructor);
     return functionExecutable;
 }
 

Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.cpp (270869 => 270870)


--- trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.cpp	2020-12-15 23:09:07 UTC (rev 270869)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.cpp	2020-12-15 23:18:33 UTC (rev 270870)
@@ -82,7 +82,7 @@
     return result;
 }
 
-UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM& vm, Structure* structure, const SourceCode& parentSource, FunctionMetadataNode* node, UnlinkedFunctionKind kind, ConstructAbility constructAbility, JSParserScriptMode scriptMode, Optional<Vector<CompactTDZEnvironmentMap::Handle>> parentScopeTDZVariables, DerivedContextType derivedContextType, NeedsClassFieldInitializer needsClassFieldInitializer, bool isBuiltinDefaultClassConstructor)
+UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM& vm, Structure* structure, const SourceCode& parentSource, FunctionMetadataNode* node, UnlinkedFunctionKind kind, ConstructAbility constructAbility, JSParserScriptMode scriptMode, RefPtr<TDZEnvironmentLink> parentScopeTDZVariables, DerivedContextType derivedContextType, NeedsClassFieldInitializer needsClassFieldInitializer, bool isBuiltinDefaultClassConstructor)
     : Base(vm, structure)
     , m_firstLineOffset(node->firstLine() - parentSource.firstLine().oneBasedInt())
     , m_isInStrictContext(node->isInStrictContext())
@@ -127,7 +127,7 @@
     if (!node->classSource().isNull())
         setClassSource(node->classSource());
     if (parentScopeTDZVariables)
-        ensureRareData().m_parentScopeTDZVariables = WTFMove(*parentScopeTDZVariables);
+        ensureRareData().m_parentScopeTDZVariables = WTFMove(parentScopeTDZVariables);
 }
 
 UnlinkedFunctionExecutable::~UnlinkedFunctionExecutable()

Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.h (270869 => 270870)


--- trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.h	2020-12-15 23:09:07 UTC (rev 270869)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedFunctionExecutable.h	2020-12-15 23:18:33 UTC (rev 270870)
@@ -70,7 +70,7 @@
         return &vm.unlinkedFunctionExecutableSpace.space;
     }
 
-    static UnlinkedFunctionExecutable* create(VM& vm, const SourceCode& source, FunctionMetadataNode* node, UnlinkedFunctionKind unlinkedFunctionKind, ConstructAbility constructAbility, JSParserScriptMode scriptMode, Optional<Vector<CompactTDZEnvironmentMap::Handle>> parentScopeTDZVariables, DerivedContextType derivedContextType, NeedsClassFieldInitializer needsClassFieldInitializer, bool isBuiltinDefaultClassConstructor = false)
+    static UnlinkedFunctionExecutable* create(VM& vm, const SourceCode& source, FunctionMetadataNode* node, UnlinkedFunctionKind unlinkedFunctionKind, ConstructAbility constructAbility, JSParserScriptMode scriptMode, RefPtr<TDZEnvironmentLink> parentScopeTDZVariables, DerivedContextType derivedContextType, NeedsClassFieldInitializer needsClassFieldInitializer, bool isBuiltinDefaultClassConstructor = false)
     {
         UnlinkedFunctionExecutable* instance = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(vm.heap))
             UnlinkedFunctionExecutable(vm, vm.unlinkedFunctionExecutableStructure.get(), source, node, unlinkedFunctionKind, constructAbility, scriptMode, WTFMove(parentScopeTDZVariables), derivedContextType, needsClassFieldInitializer, isBuiltinDefaultClassConstructor);
@@ -168,10 +168,10 @@
         return !m_rareData->m_classSource.isNull();
     }
 
-    Vector<CompactTDZEnvironmentMap::Handle> parentScopeTDZVariables() const
+    RefPtr<TDZEnvironmentLink> parentScopeTDZVariables() const
     {
-        if (!m_rareData || m_rareData->m_parentScopeTDZVariables.isEmpty())
-            return { };
+        if (!m_rareData)
+            return nullptr;
         return m_rareData->m_parentScopeTDZVariables;
     }
     
@@ -208,7 +208,7 @@
         SourceCode m_classSource;
         String m_sourceURLDirective;
         String m_sourceMappingURLDirective;
-        Vector<CompactTDZEnvironmentMap::Handle> m_parentScopeTDZVariables;
+        RefPtr<TDZEnvironmentLink> m_parentScopeTDZVariables;
         Vector<JSTextPosition> m_classFieldLocations;
     };
 
@@ -229,7 +229,7 @@
     }
 
 private:
-    UnlinkedFunctionExecutable(VM&, Structure*, const SourceCode&, FunctionMetadataNode*, UnlinkedFunctionKind, ConstructAbility, JSParserScriptMode, Optional<Vector<CompactTDZEnvironmentMap::Handle>>,  JSC::DerivedContextType, JSC::NeedsClassFieldInitializer, bool isBuiltinDefaultClassConstructor);
+    UnlinkedFunctionExecutable(VM&, Structure*, const SourceCode&, FunctionMetadataNode*, UnlinkedFunctionKind, ConstructAbility, JSParserScriptMode, RefPtr<TDZEnvironmentLink>,  JSC::DerivedContextType, JSC::NeedsClassFieldInitializer, bool isBuiltinDefaultClassConstructor);
     UnlinkedFunctionExecutable(Decoder&, const CachedFunctionExecutable&);
 
     static void visitChildren(JSCell*, SlotVisitor&);

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (270869 => 270870)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2020-12-15 23:09:07 UTC (rev 270869)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2020-12-15 23:18:33 UTC (rev 270870)
@@ -289,7 +289,7 @@
     return ParserError(ParserError::ErrorNone);
 }
 
-BytecodeGenerator::BytecodeGenerator(VM& vm, ProgramNode* programNode, UnlinkedProgramCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const CachedTDZStack& parentScopeTDZVariables, ECMAMode ecmaMode)
+BytecodeGenerator::BytecodeGenerator(VM& vm, ProgramNode* programNode, UnlinkedProgramCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const RefPtr<TDZEnvironmentLink>& parentScopeTDZVariables, ECMAMode ecmaMode)
     : BytecodeGeneratorBase(makeUnique<UnlinkedCodeBlockGenerator>(vm, codeBlock), CodeBlock::llintBaselineCalleeSaveSpaceAsVirtualRegisters())
     , m_codeGenerationMode(codeGenerationMode)
     , m_scopeNode(programNode)
@@ -304,7 +304,7 @@
     , m_needsToUpdateArrowFunctionContext(programNode->usesArrowFunction() || programNode->usesEval())
     , m_ecmaMode(ecmaMode)
 {
-    ASSERT_UNUSED(parentScopeTDZVariables, !parentScopeTDZVariables.size());
+    ASSERT_UNUSED(parentScopeTDZVariables, !parentScopeTDZVariables);
 
     m_codeBlock->setNumParameters(1); // Allocate space for "this"
 
@@ -336,7 +336,7 @@
     }
 }
 
-BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionNode* functionNode, UnlinkedFunctionCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const CachedTDZStack& parentScopeTDZVariables, ECMAMode ecmaMode)
+BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionNode* functionNode, UnlinkedFunctionCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const RefPtr<TDZEnvironmentLink>& parentScopeTDZVariables, ECMAMode ecmaMode)
     : BytecodeGeneratorBase(makeUnique<UnlinkedCodeBlockGenerator>(vm, codeBlock), CodeBlock::llintBaselineCalleeSaveSpaceAsVirtualRegisters())
     , m_codeGenerationMode(codeGenerationMode)
     , m_scopeNode(functionNode)
@@ -363,8 +363,7 @@
     functionSymbolTable->setUsesNonStrictEval(m_usesNonStrictEval);
     int symbolTableConstantIndex = 0;
 
-    m_parentScopeTDZStackSize = parentScopeTDZVariables.size();
-    m_cachedVariablesUnderTDZ = parentScopeTDZVariables;
+    m_cachedParentTDZ = parentScopeTDZVariables;
 
     FunctionParameters& parameters = *functionNode->parameters(); 
     // http://www.ecma-international.org/ecma-262/6.0/index.html#sec-functiondeclarationinstantiation
@@ -839,7 +838,7 @@
     pushLexicalScope(m_scopeNode, TDZCheckOptimization::Optimize, NestedScopeType::IsNotNested, nullptr, shouldInitializeBlockScopedFunctions);
 }
 
-BytecodeGenerator::BytecodeGenerator(VM& vm, EvalNode* evalNode, UnlinkedEvalCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const CachedTDZStack& parentScopeTDZVariables, ECMAMode ecmaMode)
+BytecodeGenerator::BytecodeGenerator(VM& vm, EvalNode* evalNode, UnlinkedEvalCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const RefPtr<TDZEnvironmentLink>& parentScopeTDZVariables, ECMAMode ecmaMode)
     : BytecodeGeneratorBase(makeUnique<UnlinkedCodeBlockGenerator>(vm, codeBlock), CodeBlock::llintBaselineCalleeSaveSpaceAsVirtualRegisters())
     , m_codeGenerationMode(codeGenerationMode)
     , m_scopeNode(evalNode)
@@ -857,8 +856,7 @@
 {
     m_codeBlock->setNumParameters(1);
 
-    m_parentScopeTDZStackSize = parentScopeTDZVariables.size();
-    m_cachedVariablesUnderTDZ = parentScopeTDZVariables;
+    m_cachedParentTDZ = parentScopeTDZVariables;
 
     emitEnter();
 
@@ -903,7 +901,7 @@
     pushLexicalScope(m_scopeNode, TDZCheckOptimization::Optimize, NestedScopeType::IsNotNested, nullptr, shouldInitializeBlockScopedFunctions);
 }
 
-BytecodeGenerator::BytecodeGenerator(VM& vm, ModuleProgramNode* moduleProgramNode, UnlinkedModuleProgramCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const CachedTDZStack& parentScopeTDZVariables, ECMAMode ecmaMode)
+BytecodeGenerator::BytecodeGenerator(VM& vm, ModuleProgramNode* moduleProgramNode, UnlinkedModuleProgramCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const RefPtr<TDZEnvironmentLink>& parentScopeTDZVariables, ECMAMode ecmaMode)
     : BytecodeGeneratorBase(makeUnique<UnlinkedCodeBlockGenerator>(vm, codeBlock), CodeBlock::llintBaselineCalleeSaveSpaceAsVirtualRegisters())
     , m_codeGenerationMode(codeGenerationMode)
     , m_scopeNode(moduleProgramNode)
@@ -918,7 +916,7 @@
     , m_needsToUpdateArrowFunctionContext(moduleProgramNode->usesArrowFunction() || moduleProgramNode->usesEval())
     , m_ecmaMode(ecmaMode)
 {
-    ASSERT_UNUSED(parentScopeTDZVariables, !parentScopeTDZVariables.size());
+    ASSERT_UNUSED(parentScopeTDZVariables, !parentScopeTDZVariables);
 
     SymbolTable* moduleEnvironmentSymbolTable = SymbolTable::create(m_vm);
     moduleEnvironmentSymbolTable->setUsesNonStrictEval(m_usesNonStrictEval);
@@ -2168,7 +2166,6 @@
     }
 
     m_TDZStack.removeLast();
-    m_cachedVariablesUnderTDZ.removeLast();
 }
 
 void BytecodeGenerator::prepareLexicalScopeForNextForLoopIteration(VariableEnvironmentNode* node, RegisterID* loopSymbolTable)
@@ -2850,17 +2847,20 @@
 bool BytecodeGenerator::needsTDZCheck(const Variable& variable)
 {
     for (unsigned i = m_TDZStack.size(); i--;) {
-        auto iter = m_TDZStack[i].find(variable.ident().impl());
-        if (iter == m_TDZStack[i].end())
+        auto iter = m_TDZStack[i].first.find(variable.ident().impl());
+        if (iter == m_TDZStack[i].first.end())
             continue;
         return iter->value != TDZNecessityLevel::NotNeeded;
     }
 
-    for (unsigned i = m_parentScopeTDZStackSize; i--;) {
-        if (m_cachedVariablesUnderTDZ[i].environment().toTDZEnvironment().contains(variable.ident().impl()))
-            return true;
+    {
+        TDZEnvironmentLink* environment = m_cachedParentTDZ.get();
+        while (environment) {
+            if (environment->contains(variable.ident().impl()))
+                return true;
+            environment = environment->parent();
+        }
     }
-
     return false;
 }
 
@@ -2881,8 +2881,8 @@
 {
     RefPtr<UniquedStringImpl> identifier(variable.ident().impl());
     for (unsigned i = m_TDZStack.size(); i--;) {
-        auto iter = m_TDZStack[i].find(identifier);
-        if (iter != m_TDZStack[i].end()) {
+        auto iter = m_TDZStack[i].first.find(identifier);
+        if (iter != m_TDZStack[i].first.end()) {
             if (iter->value == TDZNecessityLevel::Optimize)
                 iter->value = TDZNecessityLevel::NotNeeded;
             break;
@@ -2908,56 +2908,57 @@
     for (const auto& entry : environment)
         map.add(entry.key, entry.value.isFunction() ? TDZNecessityLevel::NotNeeded : level);
 
-    m_TDZStack.append(WTFMove(map));
-    m_cachedVariablesUnderTDZ.append({ });
+    m_TDZStack.append(TDZStackEntry { WTFMove(map), nullptr });
 }
 
-Optional<BytecodeGenerator::CachedTDZStack> BytecodeGenerator::getVariablesUnderTDZ()
+RefPtr<TDZEnvironmentLink> BytecodeGenerator::getVariablesUnderTDZ()
 {
+    RefPtr<TDZEnvironmentLink> parent = m_cachedParentTDZ;
+    if (!m_TDZStack.size())
+        return parent;
+
     auto assertCacheIsCoherent = [&] {
 #if ASSERT_ENABLED
-        for (size_t i = 0; i < m_cachedVariablesUnderTDZ.size(); ++i)
-            ASSERT(!!m_cachedVariablesUnderTDZ[i]);
+        TDZEnvironmentLink* parent = m_cachedParentTDZ.get();
+        for (auto& entry : m_TDZStack) {
+            ASSERT(entry.second);
+            ASSERT(entry.second->parent() == parent);
+            parent = entry.second.get();
+        }
 #endif
     };
 
-    RELEASE_ASSERT(m_TDZStack.size() + m_parentScopeTDZStackSize == m_cachedVariablesUnderTDZ.size());
-
-    if (m_cachedVariablesUnderTDZ.isEmpty())
-        return WTF::nullopt;
-
-    if (m_cachedVariablesUnderTDZ.last()) {
+    if (m_TDZStack.last().second) {
         assertCacheIsCoherent();
-        return m_cachedVariablesUnderTDZ;
+        return m_TDZStack.last().second;
     }
 
-    for (size_t i = m_TDZStack.size(); i--;) {
-        if (m_cachedVariablesUnderTDZ[i + m_parentScopeTDZStackSize])
-            break;
-
-        auto& map = m_TDZStack[i];
-        TDZEnvironment environment;
-        for (auto& entry : map) {
-            if (entry.value != TDZNecessityLevel::NotNeeded)
-                environment.add(entry.key.get());
+    for (auto& entry : m_TDZStack) {
+        if (!entry.second) {
+            auto& map = entry.first;
+            TDZEnvironment environment;
+            for (auto& entry : map) {
+                if (entry.value != TDZNecessityLevel::NotNeeded)
+                    environment.add(entry.key.get());
+            }
+            entry.second = TDZEnvironmentLink::create(m_vm.m_compactVariableMap->get(environment), parent);
         }
-        m_cachedVariablesUnderTDZ[i + m_parentScopeTDZStackSize] = m_vm.m_compactVariableMap->get(environment);
+        parent = entry.second;
     }
 
     assertCacheIsCoherent();
-    return m_cachedVariablesUnderTDZ;
+
+    return parent;
 }
 
 void BytecodeGenerator::preserveTDZStack(BytecodeGenerator::PreservedTDZStack& preservedStack)
 {
     preservedStack.m_preservedTDZStack = m_TDZStack;
-    preservedStack.m_cachedTDZStack = m_cachedVariablesUnderTDZ;
 }
 
 void BytecodeGenerator::restoreTDZStack(const BytecodeGenerator::PreservedTDZStack& preservedStack)
 {
     m_TDZStack = preservedStack.m_preservedTDZStack;
-    m_cachedVariablesUnderTDZ = preservedStack.m_cachedTDZStack;
 }
 
 RegisterID* BytecodeGenerator::emitNewObject(RegisterID* dst)

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (270869 => 270870)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2020-12-15 23:09:07 UTC (rev 270869)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2020-12-15 23:18:33 UTC (rev 270870)
@@ -407,12 +407,11 @@
 
     public:
         typedef DeclarationStacks::FunctionStack FunctionStack;
-        using CachedTDZStack = Vector<CompactTDZEnvironmentMap::Handle>;
 
-        BytecodeGenerator(VM&, ProgramNode*, UnlinkedProgramCodeBlock*, OptionSet<CodeGenerationMode>, const CachedTDZStack&, ECMAMode);
-        BytecodeGenerator(VM&, FunctionNode*, UnlinkedFunctionCodeBlock*, OptionSet<CodeGenerationMode>, const CachedTDZStack&, ECMAMode);
-        BytecodeGenerator(VM&, EvalNode*, UnlinkedEvalCodeBlock*, OptionSet<CodeGenerationMode>, const CachedTDZStack&, ECMAMode);
-        BytecodeGenerator(VM&, ModuleProgramNode*, UnlinkedModuleProgramCodeBlock*, OptionSet<CodeGenerationMode>, const CachedTDZStack&, ECMAMode);
+        BytecodeGenerator(VM&, ProgramNode*, UnlinkedProgramCodeBlock*, OptionSet<CodeGenerationMode>, const RefPtr<TDZEnvironmentLink>&, ECMAMode);
+        BytecodeGenerator(VM&, FunctionNode*, UnlinkedFunctionCodeBlock*, OptionSet<CodeGenerationMode>, const RefPtr<TDZEnvironmentLink>&, ECMAMode);
+        BytecodeGenerator(VM&, EvalNode*, UnlinkedEvalCodeBlock*, OptionSet<CodeGenerationMode>, const RefPtr<TDZEnvironmentLink>&, ECMAMode);
+        BytecodeGenerator(VM&, ModuleProgramNode*, UnlinkedModuleProgramCodeBlock*, OptionSet<CodeGenerationMode>, const RefPtr<TDZEnvironmentLink>&, ECMAMode);
 
         ~BytecodeGenerator();
         
@@ -432,7 +431,7 @@
         NeedsClassFieldInitializer needsClassFieldInitializer() const { return m_codeBlock->needsClassFieldInitializer(); }
 
         template<typename Node, typename UnlinkedCodeBlock>
-        static ParserError generate(VM& vm, Node* node, const SourceCode& sourceCode, UnlinkedCodeBlock* unlinkedCodeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const CachedTDZStack& parentScopeTDZVariables, ECMAMode ecmaMode)
+        static ParserError generate(VM& vm, Node* node, const SourceCode& sourceCode, UnlinkedCodeBlock* unlinkedCodeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const RefPtr<TDZEnvironmentLink>& parentScopeTDZVariables, ECMAMode ecmaMode)
         {
             MonotonicTime before;
             if (UNLIKELY(Options::reportBytecodeCompileTimes()))
@@ -1198,7 +1197,7 @@
             return UnlinkedFunctionExecutable::create(m_vm, m_scopeNode->source(), metadata, isBuiltinFunction() ? UnlinkedBuiltinFunction : UnlinkedNormalFunction, constructAbility, scriptMode(), WTFMove(optionalVariablesUnderTDZ), newDerivedContextType, needsClassFieldInitializer);
         }
 
-        Optional<CachedTDZStack> getVariablesUnderTDZ();
+        RefPtr<TDZEnvironmentLink> getVariablesUnderTDZ();
 
         RegisterID* emitConstructVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd, DebuggableCall);
         template<typename CallOp>
@@ -1229,10 +1228,11 @@
 
         RegisterID* emitThrowExpressionTooDeepException();
 
+        using TDZStackEntry = std::pair<TDZMap, RefPtr<TDZEnvironmentLink>>;
+
         class PreservedTDZStack {
         private:
-            Vector<TDZMap> m_preservedTDZStack;
-            CachedTDZStack m_cachedTDZStack;
+            Vector<TDZStackEntry> m_preservedTDZStack;
             friend class BytecodeGenerator;
         };
 
@@ -1264,9 +1264,8 @@
         };
         Vector<LexicalScopeStackEntry> m_lexicalScopeStack;
 
-        size_t m_parentScopeTDZStackSize { 0 };
-        Vector<TDZMap> m_TDZStack;
-        CachedTDZStack m_cachedVariablesUnderTDZ;
+        RefPtr<TDZEnvironmentLink> m_cachedParentTDZ;
+        Vector<TDZStackEntry> m_TDZStack;
         Optional<size_t> m_varScopeLexicalScopeStackIndex;
         void pushTDZVariables(const VariableEnvironment&, TDZCheckOptimization, TDZRequirement);
 

Modified: trunk/Source/_javascript_Core/parser/VariableEnvironment.h (270869 => 270870)


--- trunk/Source/_javascript_Core/parser/VariableEnvironment.h	2020-12-15 23:09:07 UTC (rev 270869)
+++ trunk/Source/_javascript_Core/parser/VariableEnvironment.h	2020-12-15 23:18:33 UTC (rev 270870)
@@ -419,4 +419,26 @@
     HashMap<CompactTDZEnvironmentKey, unsigned> m_map;
 };
 
+class TDZEnvironmentLink : public RefCounted<TDZEnvironmentLink> {
+    TDZEnvironmentLink(CompactTDZEnvironmentMap::Handle handle, RefPtr<TDZEnvironmentLink> parent)
+        : m_handle(WTFMove(handle))
+        , m_parent(WTFMove(parent))
+    { }
+
+public:
+    static RefPtr<TDZEnvironmentLink> create(CompactTDZEnvironmentMap::Handle handle, RefPtr<TDZEnvironmentLink> parent)
+    {
+        return adoptRef(new TDZEnvironmentLink(WTFMove(handle), WTFMove(parent)));
+    }
+
+    bool contains(UniquedStringImpl* impl) const { return m_handle.environment().toTDZEnvironment().contains(impl); }
+    TDZEnvironmentLink* parent() { return m_parent.get(); }
+
+private:
+    friend class CachedTDZEnvironmentLink;
+
+    CompactTDZEnvironmentMap::Handle m_handle;
+    RefPtr<TDZEnvironmentLink> m_parent;
+};
+
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/CachedTypes.cpp (270869 => 270870)


--- trunk/Source/_javascript_Core/runtime/CachedTypes.cpp	2020-12-15 23:09:07 UTC (rev 270869)
+++ trunk/Source/_javascript_Core/runtime/CachedTypes.cpp	2020-12-15 23:18:33 UTC (rev 270870)
@@ -1763,6 +1763,26 @@
     int m_startColumn;
 };
 
+class CachedTDZEnvironmentLink : public CachedObject<TDZEnvironmentLink> {
+public:
+    void encode(Encoder& encoder, const TDZEnvironmentLink& environment)
+    {
+        m_handle.encode(encoder, environment.m_handle);
+        m_parent.encode(encoder, environment.m_parent);
+    }
+
+    TDZEnvironmentLink* decode(Decoder& decoder) const
+    {
+        CompactTDZEnvironmentMap::Handle handle = m_handle.decode(decoder);
+        RefPtr<TDZEnvironmentLink> parent = m_parent.decode(decoder);
+        return new TDZEnvironmentLink(WTFMove(handle), WTFMove(parent));
+    }
+
+private:
+    CachedCompactTDZEnvironmentMapHandle m_handle;
+    CachedRefPtr<CachedTDZEnvironmentLink> m_parent;
+};
+
 class CachedFunctionExecutableRareData : public CachedObject<UnlinkedFunctionExecutable::RareData> {
 public:
     void encode(Encoder& encoder, const UnlinkedFunctionExecutable::RareData& rareData)
@@ -1781,7 +1801,7 @@
 
 private:
     CachedSourceCodeWithoutProvider m_classSource;
-    CachedVector<CachedCompactTDZEnvironmentMapHandle> m_parentScopeTDZVariables;
+    CachedRefPtr<CachedTDZEnvironmentLink> m_parentScopeTDZVariables;
 };
 
 class CachedFunctionExecutable : public CachedObject<UnlinkedFunctionExecutable> {

Modified: trunk/Source/_javascript_Core/runtime/CodeCache.cpp (270869 => 270870)


--- trunk/Source/_javascript_Core/runtime/CodeCache.cpp	2020-12-15 23:09:07 UTC (rev 270869)
+++ trunk/Source/_javascript_Core/runtime/CodeCache.cpp	2020-12-15 23:18:33 UTC (rev 270870)
@@ -105,9 +105,9 @@
     if (!source.provider()->sourceMappingURLDirective().isNull())
         unlinkedCodeBlock->setSourceMappingURLDirective(source.provider()->sourceMappingURLDirective());
 
-    Vector<CompactTDZEnvironmentMap::Handle> parentVariablesUnderTDZ;
+    RefPtr<TDZEnvironmentLink> parentVariablesUnderTDZ;
     if (variablesUnderTDZ)
-        parentVariablesUnderTDZ.append(vm.m_compactVariableMap->get(*variablesUnderTDZ));
+        parentVariablesUnderTDZ = TDZEnvironmentLink::create(vm.m_compactVariableMap->get(*variablesUnderTDZ), nullptr);
     error = BytecodeGenerator::generate(vm, rootNode.get(), source, unlinkedCodeBlock, codeGenerationMode, parentVariablesUnderTDZ, ecmaMode);
 
     if (error.isValid())
@@ -248,7 +248,7 @@
     // The Function constructor only has access to global variables, so no variables will be under TDZ unless they're
     // in the global lexical environment, which we always TDZ check accesses from.
     ConstructAbility constructAbility = constructAbilityForParseMode(metadata->parseMode());
-    UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(vm, source, metadata, UnlinkedNormalFunction, constructAbility, JSParserScriptMode::Classic, WTF::nullopt, DerivedContextType::None, NeedsClassFieldInitializer::No);
+    UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(vm, source, metadata, UnlinkedNormalFunction, constructAbility, JSParserScriptMode::Classic, nullptr, DerivedContextType::None, NeedsClassFieldInitializer::No);
 
     if (!source.provider()->sourceURLDirective().isNull())
         functionExecutable->setSourceURLDirective(source.provider()->sourceURLDirective());
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to