Changeset 269115 in webkit
- Timestamp:
- Oct 28, 2020 12:25:14 PM (3 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 24 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r269107 r269115 1 2020-10-28 Saam Barati <sbarati@apple.com> 2 3 Better cache our serialization of the outer TDZ environment when creating FunctionExecutables during bytecode generation 4 https://bugs.webkit.org/show_bug.cgi?id=199866 5 <rdar://problem/53333108> 6 7 Reviewed by Tadeu Zagallo. 8 9 * microbenchmarks/let-const-tdz-environment-parsing-and-hash-consing-speed.js: Added. 10 1 11 2020-10-28 Robin Morisset <rmorisset@apple.com> 2 12 -
trunk/Source/JavaScriptCore/ChangeLog
r269107 r269115 1 2020-10-28 Saam Barati <sbarati@apple.com> 2 3 Better cache our serialization of the outer TDZ environment when creating FunctionExecutables during bytecode generation 4 https://bugs.webkit.org/show_bug.cgi?id=199866 5 <rdar://problem/53333108> 6 7 Reviewed by Tadeu Zagallo. 8 9 This patch removes performance pathologies regarding programs with 10 many variables under TDZ (let/const). We had an algorithm for caching 11 the results of gathering all variables under TDZ, but that algorithm 12 wasn't nearly aggressive enough in its caching. This lead us to worst 13 case quadratic runtime, which could happens in practice for large functions. 14 15 There are a few fixes here: 16 - Instead of flattening the entire TDZ stack, and caching that result, 17 we now cache each stack entry individually. So as you push/pop to the 18 TDZ environment stack, we no longer invalidate everything. Instead, we 19 will just need to cache the newly pushed entry. We also no longer invalidate 20 the cache for lifting a TDZ check. The compromise here is we may emit 21 more runtime TDZ checks for closure variables. This is better than N^2 22 bytecode compile time perf, since a well predicted branch for a TDZ 23 check is essentially free. 24 - We no longer transform the CompactTDZEnvironment (formerly CompactVariableEnvironment) 25 from a Vector into a HashSet each time we generate code for an inner function. Instead, 26 CompactTDZEnvironment can be in two modes: compact and inflated. It starts life off in 27 compact mode (a vector), and will turn into an inflated mode if it's ever needed. Once 28 inflated, it'll stay this way until it's destructed. This improves our algorithm from being 29 O(EnvSize * NumFunctions) to O(EnvSize) at the cost of using more space in a HashTable versus a 30 Vector. In the future, we could consider just binary searching through this Vector, and never using 31 a hash table. 32 33 * bytecode/UnlinkedFunctionExecutable.cpp: 34 (JSC::generateUnlinkedFunctionCodeBlock): 35 (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable): 36 * bytecode/UnlinkedFunctionExecutable.h: 37 * bytecompiler/BytecodeGenerator.cpp: 38 (JSC::BytecodeGenerator::BytecodeGenerator): 39 (JSC::BytecodeGenerator::popLexicalScopeInternal): 40 (JSC::BytecodeGenerator::needsTDZCheck): 41 (JSC::BytecodeGenerator::liftTDZCheckIfPossible): 42 (JSC::BytecodeGenerator::pushTDZVariables): 43 (JSC::BytecodeGenerator::getVariablesUnderTDZ): 44 (JSC::BytecodeGenerator::preserveTDZStack): 45 (JSC::BytecodeGenerator::restoreTDZStack): 46 (JSC::BytecodeGenerator::emitNewInstanceFieldInitializerFunction): 47 * bytecompiler/BytecodeGenerator.h: 48 (JSC::BytecodeGenerator::generate): 49 (JSC::BytecodeGenerator::makeFunction): 50 * debugger/DebuggerCallFrame.cpp: 51 (JSC::DebuggerCallFrame::evaluateWithScopeExtension): 52 * interpreter/Interpreter.cpp: 53 (JSC::eval): 54 * parser/Parser.h: 55 (JSC::Parser<LexerType>::parse): 56 (JSC::parse): 57 * parser/VariableEnvironment.cpp: 58 (JSC::CompactTDZEnvironment::sortCompact): 59 (JSC::CompactTDZEnvironment::CompactTDZEnvironment): 60 (JSC::CompactTDZEnvironment::operator== const): 61 (JSC::CompactTDZEnvironment::toTDZEnvironmentSlow const): 62 (JSC::CompactTDZEnvironmentMap::get): 63 (JSC::CompactTDZEnvironmentMap::Handle::~Handle): 64 (JSC::CompactTDZEnvironmentMap::Handle::Handle): 65 (JSC::CompactVariableEnvironment::CompactVariableEnvironment): Deleted. 66 (JSC::CompactVariableEnvironment::operator== const): Deleted. 67 (JSC::CompactVariableEnvironment::toVariableEnvironment const): Deleted. 68 (JSC::CompactVariableMap::get): Deleted. 69 (JSC::CompactVariableMap::Handle::~Handle): Deleted. 70 (JSC::CompactVariableMap::Handle::Handle): Deleted. 71 * parser/VariableEnvironment.h: 72 (JSC::CompactTDZEnvironment::toTDZEnvironment const): 73 (JSC::CompactTDZEnvironmentKey::CompactTDZEnvironmentKey): 74 (JSC::CompactTDZEnvironmentKey::hash): 75 (JSC::CompactTDZEnvironmentKey::equal): 76 (JSC::CompactTDZEnvironmentKey::makeDeletedValue): 77 (JSC::CompactTDZEnvironmentKey::isHashTableDeletedValue const): 78 (JSC::CompactTDZEnvironmentKey::environment): 79 (WTF::HashTraits<JSC::CompactTDZEnvironmentKey>::emptyValue): 80 (WTF::HashTraits<JSC::CompactTDZEnvironmentKey>::isEmptyValue): 81 (WTF::HashTraits<JSC::CompactTDZEnvironmentKey>::constructDeletedValue): 82 (WTF::HashTraits<JSC::CompactTDZEnvironmentKey>::isDeletedValue): 83 (JSC::CompactTDZEnvironmentMap::Handle::environment const): 84 (JSC::CompactVariableEnvironment::hash const): Deleted. 85 (JSC::CompactVariableMapKey::CompactVariableMapKey): Deleted. 86 (JSC::CompactVariableMapKey::hash): Deleted. 87 (JSC::CompactVariableMapKey::equal): Deleted. 88 (JSC::CompactVariableMapKey::makeDeletedValue): Deleted. 89 (JSC::CompactVariableMapKey::isHashTableDeletedValue const): Deleted. 90 (JSC::CompactVariableMapKey::isHashTableEmptyValue const): Deleted. 91 (JSC::CompactVariableMapKey::environment): Deleted. 92 (WTF::HashTraits<JSC::CompactVariableMapKey>::emptyValue): Deleted. 93 (WTF::HashTraits<JSC::CompactVariableMapKey>::isEmptyValue): Deleted. 94 (WTF::HashTraits<JSC::CompactVariableMapKey>::constructDeletedValue): Deleted. 95 (WTF::HashTraits<JSC::CompactVariableMapKey>::isDeletedValue): Deleted. 96 (JSC::CompactVariableMap::Handle::Handle): Deleted. 97 (JSC::CompactVariableMap::Handle::operator=): Deleted. 98 (JSC::CompactVariableMap::Handle::operator bool const): Deleted. 99 (JSC::CompactVariableMap::Handle::environment const): Deleted. 100 (JSC::CompactVariableMap::Handle::swap): Deleted. 101 * runtime/CachedTypes.cpp: 102 (JSC::Decoder::handleForTDZEnvironment const): 103 (JSC::Decoder::setHandleForTDZEnvironment): 104 (JSC::CachedCompactTDZEnvironment::encode): 105 (JSC::CachedCompactTDZEnvironment::decode const): 106 (JSC::CachedCompactTDZEnvironmentMapHandle::encode): 107 (JSC::CachedCompactTDZEnvironmentMapHandle::decode const): 108 (JSC::CachedFunctionExecutableRareData::decode const): 109 (JSC::Decoder::handleForEnvironment const): Deleted. 110 (JSC::Decoder::setHandleForEnvironment): Deleted. 111 (JSC::CachedCompactVariableEnvironment::encode): Deleted. 112 (JSC::CachedCompactVariableEnvironment::decode const): Deleted. 113 (JSC::CachedCompactVariableMapHandle::encode): Deleted. 114 (JSC::CachedCompactVariableMapHandle::decode const): Deleted. 115 * runtime/CachedTypes.h: 116 * runtime/CodeCache.cpp: 117 (JSC::generateUnlinkedCodeBlockImpl): 118 (JSC::generateUnlinkedCodeBlock): 119 (JSC::generateUnlinkedCodeBlockForDirectEval): 120 (JSC::recursivelyGenerateUnlinkedCodeBlockForProgram): 121 (JSC::recursivelyGenerateUnlinkedCodeBlockForModuleProgram): 122 (JSC::CodeCache::getUnlinkedGlobalCodeBlock): 123 * runtime/CodeCache.h: 124 * runtime/Completion.cpp: 125 (JSC::generateProgramBytecode): 126 (JSC::generateModuleBytecode): 127 * runtime/DirectEvalExecutable.cpp: 128 (JSC::DirectEvalExecutable::create): 129 * runtime/DirectEvalExecutable.h: 130 * runtime/JSScope.cpp: 131 (JSC::JSScope::collectClosureVariablesUnderTDZ): 132 * runtime/JSScope.h: 133 * runtime/VM.cpp: 134 (JSC::VM::VM): 135 * runtime/VM.h: 136 1 137 2020-10-28 Robin Morisset <rmorisset@apple.com> 2 138 -
trunk/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp
r262613 r269115 73 73 UnlinkedFunctionCodeBlock* result = UnlinkedFunctionCodeBlock::create(vm, FunctionCode, ExecutableInfo(function->usesEval(), kind == CodeForConstruct, functionKind == UnlinkedBuiltinFunction, executable->constructorKind(), scriptMode, executable->superBinding(), parseMode, executable->derivedContextType(), executable->needsClassFieldInitializer(), false, isClassContext, EvalContextType::FunctionEvalContext), codeGenerationMode); 74 74 75 VariableEnvironmentparentScopeTDZVariables = executable->parentScopeTDZVariables();75 auto parentScopeTDZVariables = executable->parentScopeTDZVariables(); 76 76 ECMAMode ecmaMode = executable->isInStrictContext() ? ECMAMode::strict() : ECMAMode::sloppy(); 77 error = BytecodeGenerator::generate(vm, function.get(), source, result, codeGenerationMode, &parentScopeTDZVariables, ecmaMode);77 error = BytecodeGenerator::generate(vm, function.get(), source, result, codeGenerationMode, parentScopeTDZVariables, ecmaMode); 78 78 79 79 if (error.isValid()) … … 83 83 } 84 84 85 UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM& vm, Structure* structure, const SourceCode& parentSource, FunctionMetadataNode* node, UnlinkedFunctionKind kind, ConstructAbility constructAbility, JSParserScriptMode scriptMode, Optional< CompactVariableMap::Handle> parentScopeTDZVariables, DerivedContextType derivedContextType, NeedsClassFieldInitializer needsClassFieldInitializer, bool isBuiltinDefaultClassConstructor)85 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) 86 86 : Base(vm, structure) 87 87 , m_firstLineOffset(node->firstLine() - parentSource.firstLine().oneBasedInt()) -
trunk/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h
r260415 r269115 71 71 } 72 72 73 static UnlinkedFunctionExecutable* create(VM& vm, const SourceCode& source, FunctionMetadataNode* node, UnlinkedFunctionKind unlinkedFunctionKind, ConstructAbility constructAbility, JSParserScriptMode scriptMode, Optional< CompactVariableMap::Handle> parentScopeTDZVariables, DerivedContextType derivedContextType, NeedsClassFieldInitializer needsClassFieldInitializer, bool isBuiltinDefaultClassConstructor = false)73 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) 74 74 { 75 75 UnlinkedFunctionExecutable* instance = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(vm.heap)) … … 169 169 } 170 170 171 V ariableEnvironmentparentScopeTDZVariables() const172 { 173 if (!m_rareData || !m_rareData->m_parentScopeTDZVariables)174 return VariableEnvironment();175 return m_rareData->m_parentScopeTDZVariables .environment().toVariableEnvironment();171 Vector<CompactTDZEnvironmentMap::Handle> parentScopeTDZVariables() const 172 { 173 if (!m_rareData || m_rareData->m_parentScopeTDZVariables.isEmpty()) 174 return { }; 175 return m_rareData->m_parentScopeTDZVariables; 176 176 } 177 177 … … 209 209 String m_sourceURLDirective; 210 210 String m_sourceMappingURLDirective; 211 CompactVariableMap::Handlem_parentScopeTDZVariables;211 Vector<CompactTDZEnvironmentMap::Handle> m_parentScopeTDZVariables; 212 212 Vector<JSTextPosition> m_instanceFieldLocations; 213 213 }; … … 230 230 231 231 private: 232 UnlinkedFunctionExecutable(VM&, Structure*, const SourceCode&, FunctionMetadataNode*, UnlinkedFunctionKind, ConstructAbility, JSParserScriptMode, Optional< CompactVariableMap::Handle>, JSC::DerivedContextType, JSC::NeedsClassFieldInitializer, bool isBuiltinDefaultClassConstructor);232 UnlinkedFunctionExecutable(VM&, Structure*, const SourceCode&, FunctionMetadataNode*, UnlinkedFunctionKind, ConstructAbility, JSParserScriptMode, Optional<Vector<CompactTDZEnvironmentMap::Handle>>, JSC::DerivedContextType, JSC::NeedsClassFieldInitializer, bool isBuiltinDefaultClassConstructor); 233 233 UnlinkedFunctionExecutable(Decoder&, const CachedFunctionExecutable&); 234 234 -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r268593 r269115 49 49 #include "PrivateFieldPutKind.h" 50 50 #include "StrongInlines.h" 51 #include "SuperSampler.h" 51 52 #include "UnlinkedCodeBlock.h" 52 53 #include "UnlinkedEvalCodeBlock.h" … … 289 290 } 290 291 291 BytecodeGenerator::BytecodeGenerator(VM& vm, ProgramNode* programNode, UnlinkedProgramCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const VariableEnvironment*parentScopeTDZVariables, ECMAMode ecmaMode)292 BytecodeGenerator::BytecodeGenerator(VM& vm, ProgramNode* programNode, UnlinkedProgramCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const CachedTDZStack& parentScopeTDZVariables, ECMAMode ecmaMode) 292 293 : BytecodeGeneratorBase(makeUnique<UnlinkedCodeBlockGenerator>(vm, codeBlock), CodeBlock::llintBaselineCalleeSaveSpaceAsVirtualRegisters()) 293 294 , m_codeGenerationMode(codeGenerationMode) … … 301 302 , m_usesNonStrictEval(false) 302 303 , m_inTailPosition(false) 303 , m_hasCachedVariablesUnderTDZ(false)304 304 , m_needsToUpdateArrowFunctionContext(programNode->usesArrowFunction() || programNode->usesEval()) 305 305 , m_ecmaMode(ecmaMode) 306 306 { 307 ASSERT_UNUSED(parentScopeTDZVariables, !parentScopeTDZVariables ->size());307 ASSERT_UNUSED(parentScopeTDZVariables, !parentScopeTDZVariables.size()); 308 308 309 309 m_codeBlock->setNumParameters(1); // Allocate space for "this" … … 337 337 } 338 338 339 BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionNode* functionNode, UnlinkedFunctionCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const VariableEnvironment*parentScopeTDZVariables, ECMAMode ecmaMode)339 BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionNode* functionNode, UnlinkedFunctionCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const CachedTDZStack& parentScopeTDZVariables, ECMAMode ecmaMode) 340 340 : BytecodeGeneratorBase(makeUnique<UnlinkedCodeBlockGenerator>(vm, codeBlock), CodeBlock::llintBaselineCalleeSaveSpaceAsVirtualRegisters()) 341 341 , m_codeGenerationMode(codeGenerationMode) … … 356 356 // Note that we intentionally enable tail call for naked constructors since it does not have special code for "return". 357 357 , m_inTailPosition(Options::useTailCalls() && !isConstructor() && constructorKind() == ConstructorKind::None && ecmaMode.isStrict()) 358 , m_hasCachedVariablesUnderTDZ(false)359 358 , m_needsToUpdateArrowFunctionContext(functionNode->usesArrowFunction() || functionNode->usesEval()) 360 359 , m_ecmaMode(ecmaMode) … … 364 363 functionSymbolTable->setUsesNonStrictEval(m_usesNonStrictEval); 365 364 int symbolTableConstantIndex = 0; 365 366 m_parentScopeTDZStackSize = parentScopeTDZVariables.size(); 367 m_cachedVariablesUnderTDZ = parentScopeTDZVariables; 366 368 367 369 FunctionParameters& parameters = *functionNode->parameters(); … … 771 773 } 772 774 773 // All "addVar()"s needs to happen before "initializeDefaultParameterValuesAndSetupFunctionScopeStack()" is called774 // because a function's default parameter ExpressionNodes will use temporary registers.775 pushTDZVariables(*parentScopeTDZVariables, TDZCheckOptimization::DoNotOptimize, TDZRequirement::UnderTDZ);776 777 775 Ref<Label> catchLabel = newLabel(); 778 776 TryData* tryFormalParametersData = nullptr; … … 783 781 } 784 782 783 // All "addVar()"s needs to happen before "initializeDefaultParameterValuesAndSetupFunctionScopeStack()" is called 784 // because a function's default parameter ExpressionNodes will use temporary registers. 785 785 initializeDefaultParameterValuesAndSetupFunctionScopeStack(parameters, isSimpleParameterList, functionNode, functionSymbolTable, symbolTableConstantIndex, captures, shouldCreateArgumentsVariableInParameterScope); 786 786 … … 841 841 } 842 842 843 BytecodeGenerator::BytecodeGenerator(VM& vm, EvalNode* evalNode, UnlinkedEvalCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const VariableEnvironment*parentScopeTDZVariables, ECMAMode ecmaMode)843 BytecodeGenerator::BytecodeGenerator(VM& vm, EvalNode* evalNode, UnlinkedEvalCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const CachedTDZStack& parentScopeTDZVariables, ECMAMode ecmaMode) 844 844 : BytecodeGeneratorBase(makeUnique<UnlinkedCodeBlockGenerator>(vm, codeBlock), CodeBlock::llintBaselineCalleeSaveSpaceAsVirtualRegisters()) 845 845 , m_codeGenerationMode(codeGenerationMode) … … 853 853 , m_usesNonStrictEval(codeBlock->usesEval() && !ecmaMode.isStrict()) 854 854 , m_inTailPosition(false) 855 , m_hasCachedVariablesUnderTDZ(false)856 855 , m_needsToUpdateArrowFunctionContext(evalNode->usesArrowFunction() || evalNode->usesEval()) 857 856 , m_ecmaMode(ecmaMode) … … 860 859 m_codeBlock->setNumParameters(1); 861 860 862 pushTDZVariables(*parentScopeTDZVariables, TDZCheckOptimization::DoNotOptimize, TDZRequirement::UnderTDZ); 861 m_parentScopeTDZStackSize = parentScopeTDZVariables.size(); 862 m_cachedVariablesUnderTDZ = parentScopeTDZVariables; 863 863 864 864 emitEnter(); … … 905 905 } 906 906 907 BytecodeGenerator::BytecodeGenerator(VM& vm, ModuleProgramNode* moduleProgramNode, UnlinkedModuleProgramCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const VariableEnvironment*parentScopeTDZVariables, ECMAMode ecmaMode)907 BytecodeGenerator::BytecodeGenerator(VM& vm, ModuleProgramNode* moduleProgramNode, UnlinkedModuleProgramCodeBlock* codeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const CachedTDZStack& parentScopeTDZVariables, ECMAMode ecmaMode) 908 908 : BytecodeGeneratorBase(makeUnique<UnlinkedCodeBlockGenerator>(vm, codeBlock), CodeBlock::llintBaselineCalleeSaveSpaceAsVirtualRegisters()) 909 909 , m_codeGenerationMode(codeGenerationMode) … … 917 917 , m_usesNonStrictEval(false) 918 918 , m_inTailPosition(false) 919 , m_hasCachedVariablesUnderTDZ(false)920 919 , m_needsToUpdateArrowFunctionContext(moduleProgramNode->usesArrowFunction() || moduleProgramNode->usesEval()) 921 920 , m_ecmaMode(ecmaMode) 922 921 { 923 ASSERT_UNUSED(parentScopeTDZVariables, !parentScopeTDZVariables ->size());922 ASSERT_UNUSED(parentScopeTDZVariables, !parentScopeTDZVariables.size()); 924 923 925 924 SymbolTable* moduleEnvironmentSymbolTable = SymbolTable::create(m_vm); … … 2171 2170 2172 2171 m_TDZStack.removeLast(); 2173 m_cachedVariablesUnderTDZ = { };2172 m_cachedVariablesUnderTDZ.removeLast(); 2174 2173 } 2175 2174 … … 2859 2858 } 2860 2859 2860 for (unsigned i = m_parentScopeTDZStackSize; i--;) { 2861 if (m_cachedVariablesUnderTDZ[i].environment().toTDZEnvironment().contains(variable.ident().impl())) 2862 return true; 2863 } 2864 2861 2865 return false; 2862 2866 } … … 2881 2885 auto iter = m_TDZStack[i].find(identifier); 2882 2886 if (iter != m_TDZStack[i].end()) { 2883 if (iter->value == TDZNecessityLevel::Optimize) { 2884 m_cachedVariablesUnderTDZ = { }; 2887 if (iter->value == TDZNecessityLevel::Optimize) 2885 2888 iter->value = TDZNecessityLevel::NotNeeded; 2886 }2887 2889 break; 2888 2890 } … … 2909 2911 2910 2912 m_TDZStack.append(WTFMove(map)); 2911 m_cachedVariablesUnderTDZ = { }; 2912 } 2913 2914 Optional<CompactVariableMap::Handle> BytecodeGenerator::getVariablesUnderTDZ() 2915 { 2916 if (m_cachedVariablesUnderTDZ) { 2917 if (!m_hasCachedVariablesUnderTDZ) { 2918 ASSERT(m_cachedVariablesUnderTDZ.environment().toVariableEnvironment().isEmpty()); 2919 return WTF::nullopt; 2920 } 2913 m_cachedVariablesUnderTDZ.append({ }); 2914 } 2915 2916 Optional<BytecodeGenerator::CachedTDZStack> BytecodeGenerator::getVariablesUnderTDZ() 2917 { 2918 auto assertCacheIsCoherent = [&] { 2919 #if ASSERT_ENABLED 2920 for (size_t i = 0; i < m_cachedVariablesUnderTDZ.size(); ++i) 2921 ASSERT(!!m_cachedVariablesUnderTDZ[i]); 2922 #endif 2923 }; 2924 2925 RELEASE_ASSERT(m_TDZStack.size() + m_parentScopeTDZStackSize == m_cachedVariablesUnderTDZ.size()); 2926 2927 if (m_cachedVariablesUnderTDZ.isEmpty()) 2928 return WTF::nullopt; 2929 2930 if (m_cachedVariablesUnderTDZ.last()) { 2931 assertCacheIsCoherent(); 2921 2932 return m_cachedVariablesUnderTDZ; 2922 2933 } 2923 2934 2924 // We keep track of variablesThatDontNeedTDZ in this algorithm to prevent 2925 // reporting that "x" is under TDZ if this function is called at "...". 2926 // 2927 // { 2928 // { 2929 // let x; 2930 // ... 2931 // } 2932 // let x; 2933 // } 2934 SmallPtrSet<UniquedStringImpl*, 16> variablesThatDontNeedTDZ; 2935 VariableEnvironment environment; 2936 for (unsigned i = m_TDZStack.size(); i--; ) { 2935 for (size_t i = m_TDZStack.size(); i--;) { 2936 if (m_cachedVariablesUnderTDZ[i + m_parentScopeTDZStackSize]) 2937 break; 2938 2937 2939 auto& map = m_TDZStack[i]; 2938 for (auto& entry : map) { 2939 if (entry.value != TDZNecessityLevel::NotNeeded) { 2940 if (!variablesThatDontNeedTDZ.contains(entry.key.get())) 2941 environment.add(entry.key.get()); 2942 } else 2943 variablesThatDontNeedTDZ.add(entry.key.get()); 2944 } 2945 } 2946 2947 m_cachedVariablesUnderTDZ = m_vm.m_compactVariableMap->get(environment); 2948 m_hasCachedVariablesUnderTDZ = !environment.isEmpty(); 2949 if (!m_hasCachedVariablesUnderTDZ) 2950 return WTF::nullopt; 2951 2940 TDZEnvironment environment; 2941 for (auto& entry : map) { 2942 if (entry.value != TDZNecessityLevel::NotNeeded) 2943 environment.add(entry.key.get()); 2944 } 2945 m_cachedVariablesUnderTDZ[i + m_parentScopeTDZStackSize] = m_vm.m_compactVariableMap->get(environment); 2946 } 2947 2948 assertCacheIsCoherent(); 2952 2949 return m_cachedVariablesUnderTDZ; 2953 2950 } … … 2956 2953 { 2957 2954 preservedStack.m_preservedTDZStack = m_TDZStack; 2955 preservedStack.m_cachedTDZStack = m_cachedVariablesUnderTDZ; 2958 2956 } 2959 2957 … … 2961 2959 { 2962 2960 m_TDZStack = preservedStack.m_preservedTDZStack; 2963 m_cachedVariablesUnderTDZ = { };2961 m_cachedVariablesUnderTDZ = preservedStack.m_cachedTDZStack; 2964 2962 } 2965 2963 … … 3148 3146 } 3149 3147 3150 Optional<CompactVariableMap::Handle>variablesUnderTDZ = getVariablesUnderTDZ();3148 auto variablesUnderTDZ = getVariablesUnderTDZ(); 3151 3149 SourceParseMode parseMode = SourceParseMode::InstanceFieldInitializerMode; 3152 3150 ConstructAbility constructAbility = ConstructAbility::CannotConstruct; -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
r266264 r269115 408 408 public: 409 409 typedef DeclarationStacks::FunctionStack FunctionStack; 410 411 BytecodeGenerator(VM&, ProgramNode*, UnlinkedProgramCodeBlock*, OptionSet<CodeGenerationMode>, const VariableEnvironment*, ECMAMode); 412 BytecodeGenerator(VM&, FunctionNode*, UnlinkedFunctionCodeBlock*, OptionSet<CodeGenerationMode>, const VariableEnvironment*, ECMAMode); 413 BytecodeGenerator(VM&, EvalNode*, UnlinkedEvalCodeBlock*, OptionSet<CodeGenerationMode>, const VariableEnvironment*, ECMAMode); 414 BytecodeGenerator(VM&, ModuleProgramNode*, UnlinkedModuleProgramCodeBlock*, OptionSet<CodeGenerationMode>, const VariableEnvironment*, ECMAMode); 410 using CachedTDZStack = Vector<CompactTDZEnvironmentMap::Handle>; 411 412 BytecodeGenerator(VM&, ProgramNode*, UnlinkedProgramCodeBlock*, OptionSet<CodeGenerationMode>, const CachedTDZStack&, ECMAMode); 413 BytecodeGenerator(VM&, FunctionNode*, UnlinkedFunctionCodeBlock*, OptionSet<CodeGenerationMode>, const CachedTDZStack&, ECMAMode); 414 BytecodeGenerator(VM&, EvalNode*, UnlinkedEvalCodeBlock*, OptionSet<CodeGenerationMode>, const CachedTDZStack&, ECMAMode); 415 BytecodeGenerator(VM&, ModuleProgramNode*, UnlinkedModuleProgramCodeBlock*, OptionSet<CodeGenerationMode>, const CachedTDZStack&, ECMAMode); 415 416 416 417 ~BytecodeGenerator(); … … 432 433 433 434 template<typename Node, typename UnlinkedCodeBlock> 434 static ParserError generate(VM& vm, Node* node, const SourceCode& sourceCode, UnlinkedCodeBlock* unlinkedCodeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const VariableEnvironment* environment, ECMAMode ecmaMode)435 static ParserError generate(VM& vm, Node* node, const SourceCode& sourceCode, UnlinkedCodeBlock* unlinkedCodeBlock, OptionSet<CodeGenerationMode> codeGenerationMode, const CachedTDZStack& parentScopeTDZVariables, ECMAMode ecmaMode) 435 436 { 436 437 MonotonicTime before; … … 439 440 440 441 DeferGC deferGC(vm.heap); 441 auto bytecodeGenerator = makeUnique<BytecodeGenerator>(vm, node, unlinkedCodeBlock, codeGenerationMode, environment, ecmaMode);442 auto bytecodeGenerator = makeUnique<BytecodeGenerator>(vm, node, unlinkedCodeBlock, codeGenerationMode, parentScopeTDZVariables, ecmaMode); 442 443 auto result = bytecodeGenerator->generate(); 443 444 … … 1186 1187 } 1187 1188 1188 Optional<CompactVariableMap::Handle>optionalVariablesUnderTDZ = getVariablesUnderTDZ();1189 auto optionalVariablesUnderTDZ = getVariablesUnderTDZ(); 1189 1190 1190 1191 // FIXME: These flags, ParserModes and propagation to XXXCodeBlocks should be reorganized. … … 1198 1199 } 1199 1200 1200 Optional<C ompactVariableMap::Handle> getVariablesUnderTDZ();1201 Optional<CachedTDZStack> getVariablesUnderTDZ(); 1201 1202 1202 1203 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); … … 1232 1233 private: 1233 1234 Vector<TDZMap> m_preservedTDZStack; 1235 CachedTDZStack m_cachedTDZStack; 1234 1236 friend class BytecodeGenerator; 1235 1237 }; … … 1263 1265 Vector<LexicalScopeStackEntry> m_lexicalScopeStack; 1264 1266 1267 size_t m_parentScopeTDZStackSize { 0 }; 1265 1268 Vector<TDZMap> m_TDZStack; 1269 CachedTDZStack m_cachedVariablesUnderTDZ; 1266 1270 Optional<size_t> m_varScopeLexicalScopeStackIndex; 1267 1271 void pushTDZVariables(const VariableEnvironment&, TDZCheckOptimization, TDZRequirement); … … 1345 1349 bool m_usesNonStrictEval { false }; 1346 1350 bool m_inTailPosition { false }; 1347 bool m_hasCachedVariablesUnderTDZ { false };1348 1351 bool m_needsToUpdateArrowFunctionContext : 1; 1349 1352 ECMAMode m_ecmaMode; 1350 1353 DerivedContextType m_derivedContextType { DerivedContextType::None }; 1351 1352 CompactVariableMap::Handle m_cachedVariablesUnderTDZ;1353 1354 1354 1355 struct CatchEntry { -
trunk/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp
r266534 r269115 259 259 evalContextType = EvalContextType::None; 260 260 261 VariableEnvironment variablesUnderTDZ; 262 JSScope::collectClosureVariablesUnderTDZ(scope()->jsScope(), variablesUnderTDZ); 261 TDZEnvironment variablesUnderTDZ; 262 VariableEnvironment privateNames; 263 JSScope::collectClosureVariablesUnderTDZ(scope()->jsScope(), variablesUnderTDZ, privateNames); 263 264 264 265 ECMAMode ecmaMode = codeBlock->ownerExecutable()->isInStrictContext() ? ECMAMode::strict() : ECMAMode::sloppy(); 265 auto* eval = DirectEvalExecutable::create(globalObject, makeSource(script, callFrame->callerSourceOrigin(vm)), codeBlock->unlinkedCodeBlock()->derivedContextType(), codeBlock->unlinkedCodeBlock()->needsClassFieldInitializer(), codeBlock->unlinkedCodeBlock()->isArrowFunction(), codeBlock->ownerExecutable()->isInsideOrdinaryFunction(), evalContextType, &variablesUnderTDZ, ecmaMode);266 auto* eval = DirectEvalExecutable::create(globalObject, makeSource(script, callFrame->callerSourceOrigin(vm)), codeBlock->unlinkedCodeBlock()->derivedContextType(), codeBlock->unlinkedCodeBlock()->needsClassFieldInitializer(), codeBlock->unlinkedCodeBlock()->isArrowFunction(), codeBlock->ownerExecutable()->isInsideOrdinaryFunction(), evalContextType, &variablesUnderTDZ, &privateNames, ecmaMode); 266 267 if (UNLIKELY(catchScope.exception())) { 267 268 exception = catchScope.exception(); -
trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp
r268004 r269115 144 144 } 145 145 146 VariableEnvironment variablesUnderTDZ; 147 JSScope::collectClosureVariablesUnderTDZ(callerScopeChain, variablesUnderTDZ); 148 eval = DirectEvalExecutable::create(globalObject, makeSource(programSource, callerCodeBlock->source().provider()->sourceOrigin()), derivedContextType, callerUnlinkedCodeBlock->needsClassFieldInitializer(), isArrowFunctionContext, callerCodeBlock->ownerExecutable()->isInsideOrdinaryFunction(), evalContextType, &variablesUnderTDZ, ecmaMode); 146 TDZEnvironment variablesUnderTDZ; 147 VariableEnvironment privateNames; 148 JSScope::collectClosureVariablesUnderTDZ(callerScopeChain, variablesUnderTDZ, privateNames); 149 eval = DirectEvalExecutable::create(globalObject, makeSource(programSource, callerCodeBlock->source().provider()->sourceOrigin()), derivedContextType, callerUnlinkedCodeBlock->needsClassFieldInitializer(), isArrowFunctionContext, callerCodeBlock->ownerExecutable()->isInsideOrdinaryFunction(), evalContextType, &variablesUnderTDZ, &privateNames, ecmaMode); 149 150 EXCEPTION_ASSERT(!!scope.exception() == !eval); 150 151 if (!eval) -
trunk/Source/JavaScriptCore/parser/Parser.h
r267306 r269115 2054 2054 template <typename LexerType> 2055 2055 template <class ParsedNode> 2056 std::unique_ptr<ParsedNode> Parser<LexerType>::parse(ParserError& error, const Identifier& calleeName, SourceParseMode parseMode, ParsingContext parsingContext, Optional<int> functionConstructorParametersEndPosition, const VariableEnvironment* variablesUnderTDZ, const Vector<JSTextPosition>* instanceFieldLocations)2056 std::unique_ptr<ParsedNode> Parser<LexerType>::parse(ParserError& error, const Identifier& calleeName, SourceParseMode parseMode, ParsingContext parsingContext, Optional<int> functionConstructorParametersEndPosition, const VariableEnvironment* parentScopePrivateNames, const Vector<JSTextPosition>* instanceFieldLocations) 2057 2057 { 2058 2058 int errLine; … … 2069 2069 unsigned startColumn = m_source->startColumn().zeroBasedInt(); 2070 2070 2071 if (isEvalNode<ParsedNode>() && variablesUnderTDZ && variablesUnderTDZ->privateNamesSize()) {2071 if (isEvalNode<ParsedNode>() && parentScopePrivateNames && parentScopePrivateNames->privateNamesSize()) { 2072 2072 currentScope()->setIsPrivateNameScope(); 2073 variablesUnderTDZ->copyPrivateNamesTo(currentScope()->lexicalVariables());2073 parentScopePrivateNames->copyPrivateNamesTo(currentScope()->lexicalVariables()); 2074 2074 } 2075 2075 … … 2158 2158 EvalContextType evalContextType = EvalContextType::None, 2159 2159 DebuggerParseData* debuggerParseData = nullptr, 2160 const VariableEnvironment* variablesUnderTDZ= nullptr,2160 const VariableEnvironment* parentScopePrivateNames = nullptr, 2161 2161 const Vector<JSTextPosition>* instanceFieldLocations = nullptr, 2162 2162 bool isInsideOrdinaryFunction = false) … … 2171 2171 if (source.provider()->source().is8Bit()) { 2172 2172 Parser<Lexer<LChar>> parser(vm, source, builtinMode, strictMode, scriptMode, parseMode, superBinding, defaultConstructorKindForTopLevelFunction, derivedContextType, isEvalNode<ParsedNode>(), evalContextType, debuggerParseData, isInsideOrdinaryFunction); 2173 result = parser.parse<ParsedNode>(error, name, parseMode, isEvalNode<ParsedNode>() ? ParsingContext::Eval : ParsingContext::Program, WTF::nullopt, variablesUnderTDZ, instanceFieldLocations);2173 result = parser.parse<ParsedNode>(error, name, parseMode, isEvalNode<ParsedNode>() ? ParsingContext::Eval : ParsingContext::Program, WTF::nullopt, parentScopePrivateNames, instanceFieldLocations); 2174 2174 if (positionBeforeLastNewline) 2175 2175 *positionBeforeLastNewline = parser.positionBeforeLastNewline(); … … 2184 2184 ASSERT_WITH_MESSAGE(defaultConstructorKindForTopLevelFunction == ConstructorKind::None, "BuiltinExecutables's special constructors should always use a 8-bit string"); 2185 2185 Parser<Lexer<UChar>> parser(vm, source, builtinMode, strictMode, scriptMode, parseMode, superBinding, defaultConstructorKindForTopLevelFunction, derivedContextType, isEvalNode<ParsedNode>(), evalContextType, debuggerParseData, isInsideOrdinaryFunction); 2186 result = parser.parse<ParsedNode>(error, name, parseMode, isEvalNode<ParsedNode>() ? ParsingContext::Eval : ParsingContext::Program, WTF::nullopt, variablesUnderTDZ, instanceFieldLocations);2186 result = parser.parse<ParsedNode>(error, name, parseMode, isEvalNode<ParsedNode>() ? ParsingContext::Eval : ParsingContext::Program, WTF::nullopt, parentScopePrivateNames, instanceFieldLocations); 2187 2187 if (positionBeforeLastNewline) 2188 2188 *positionBeforeLastNewline = parser.positionBeforeLastNewline(); -
trunk/Source/JavaScriptCore/parser/VariableEnvironment.cpp
r262613 r269115 105 105 } 106 106 107 CompactVariableEnvironment::CompactVariableEnvironment(const VariableEnvironment& env) 108 : m_isEverythingCaptured(env.isEverythingCaptured()) 109 { 110 Vector<std::pair<UniquedStringImpl*, VariableEnvironmentEntry>, 32> sortedEntries; 111 sortedEntries.reserveInitialCapacity(env.mapSize()); 112 for (auto& pair : env) 113 sortedEntries.append({ pair.key.get(), pair.value }); 114 115 std::sort(sortedEntries.begin(), sortedEntries.end(), [] (const auto& a, const auto& b) { 116 return a.first < b.first; 107 108 void CompactTDZEnvironment::sortCompact(Compact& compact) 109 { 110 std::sort(compact.begin(), compact.end(), [] (auto& a, auto& b) { 111 return a.get() < b.get(); 117 112 }); 118 119 m_hash = 0; 120 m_variables.reserveInitialCapacity(sortedEntries.size()); 121 m_variableMetadata.reserveInitialCapacity(sortedEntries.size()); 122 for (const auto& pair : sortedEntries) { 123 m_variables.append(pair.first); 124 m_variableMetadata.append(pair.second); 125 m_hash ^= pair.first->hash(); 126 m_hash += pair.second.bits(); 127 } 128 129 if (m_isEverythingCaptured) 130 m_hash *= 2; 131 } 132 133 bool CompactVariableEnvironment::operator==(const CompactVariableEnvironment& other) const 113 } 114 115 CompactTDZEnvironment::CompactTDZEnvironment(const TDZEnvironment& env) 116 { 117 Compact compactVariables; 118 compactVariables.reserveCapacity(env.size()); 119 120 m_hash = 0; // Note: XOR is commutative so order doesn't matter here. 121 for (auto& key : env) { 122 compactVariables.append(key.get()); 123 m_hash ^= key->hash(); 124 } 125 126 sortCompact(compactVariables); 127 m_variables = WTFMove(compactVariables); 128 } 129 130 bool CompactTDZEnvironment::operator==(const CompactTDZEnvironment& other) const 134 131 { 135 132 if (this == &other) 136 133 return true; 137 if (m_isEverythingCaptured != other.m_isEverythingCaptured) 134 135 if (m_hash != other.m_hash) 138 136 return false; 139 if (m_variables != other.m_variables) 140 return false; 141 if (m_variableMetadata != other.m_variableMetadata) 142 return false; 143 return true; 144 } 145 146 VariableEnvironment CompactVariableEnvironment::toVariableEnvironment() const 147 { 148 VariableEnvironment result; 149 ASSERT(m_variables.size() == m_variableMetadata.size()); 150 for (size_t i = 0; i < m_variables.size(); ++i) { 151 auto addResult = result.add(m_variables[i]); 152 ASSERT(addResult.isNewEntry); 153 addResult.iterator->value = m_variableMetadata[i]; 154 } 155 156 if (m_isEverythingCaptured) 157 result.markAllVariablesAsCaptured(); 137 138 auto equal = [&] (const Compact& compact, const Inflated& inflated) { 139 if (compact.size() != inflated.size()) 140 return false; 141 for (auto& ident : compact) { 142 if (!inflated.contains(ident)) 143 return false; 144 } 145 return true; 146 }; 147 148 bool result; 149 WTF::switchOn(m_variables, 150 [&] (const Compact& compact) { 151 WTF::switchOn(other.m_variables, 152 [&] (const Compact& otherCompact) { 153 result = compact == otherCompact; 154 }, 155 [&] (const Inflated& otherInflated) { 156 result = equal(compact, otherInflated); 157 }); 158 }, 159 [&] (const Inflated& inflated) { 160 WTF::switchOn(other.m_variables, 161 [&] (const Compact& otherCompact) { 162 result = equal(otherCompact, inflated); 163 }, 164 [&] (const Inflated& otherInflated) { 165 result = inflated == otherInflated; 166 }); 167 }); 158 168 159 169 return result; 160 170 } 161 171 162 CompactVariableMap::Handle CompactVariableMap::get(const VariableEnvironment& env) 163 { 164 auto* environment = new CompactVariableEnvironment(env); 172 TDZEnvironment& CompactTDZEnvironment::toTDZEnvironmentSlow() const 173 { 174 Inflated inflated; 175 { 176 auto& compact = WTF::get<Compact>(m_variables); 177 for (size_t i = 0; i < compact.size(); ++i) { 178 auto addResult = inflated.add(compact[i]); 179 ASSERT_UNUSED(addResult, addResult.isNewEntry); 180 } 181 } 182 m_variables = Variables(WTFMove(inflated)); 183 return const_cast<Inflated&>(WTF::get<Inflated>(m_variables)); 184 } 185 186 CompactTDZEnvironmentMap::Handle CompactTDZEnvironmentMap::get(const TDZEnvironment& env) 187 { 188 auto* environment = new CompactTDZEnvironment(env); 165 189 bool isNewEntry; 166 190 auto handle = get(environment, isNewEntry); … … 170 194 } 171 195 172 Compact VariableMap::Handle CompactVariableMap::get(CompactVariableEnvironment* environment, bool& isNewEntry)173 { 174 Compact VariableMapKey key { *environment };196 CompactTDZEnvironmentMap::Handle CompactTDZEnvironmentMap::get(CompactTDZEnvironment* environment, bool& isNewEntry) 197 { 198 CompactTDZEnvironmentKey key { *environment }; 175 199 auto addResult = m_map.add(key, 1); 176 200 isNewEntry = addResult.isNewEntry; 177 201 if (addResult.isNewEntry) 178 return Compact VariableMap::Handle(*environment, *this);202 return CompactTDZEnvironmentMap::Handle(*environment, *this); 179 203 180 204 ++addResult.iterator->value; 181 return Compact VariableMap::Handle(addResult.iterator->key.environment(), *this);182 } 183 184 Compact VariableMap::Handle::~Handle()205 return CompactTDZEnvironmentMap::Handle(addResult.iterator->key.environment(), *this); 206 } 207 208 CompactTDZEnvironmentMap::Handle::~Handle() 185 209 { 186 210 if (!m_map) { … … 191 215 192 216 RELEASE_ASSERT(m_environment); 193 auto iter = m_map->m_map.find(Compact VariableMapKey { *m_environment });217 auto iter = m_map->m_map.find(CompactTDZEnvironmentKey { *m_environment }); 194 218 RELEASE_ASSERT(iter != m_map->m_map.end()); 195 219 --iter->value; … … 201 225 } 202 226 203 Compact VariableMap::Handle::Handle(const CompactVariableMap::Handle& other)227 CompactTDZEnvironmentMap::Handle::Handle(const CompactTDZEnvironmentMap::Handle& other) 204 228 : m_environment(other.m_environment) 205 229 , m_map(other.m_map) 206 230 { 207 231 if (m_map) { 208 auto iter = m_map->m_map.find(Compact VariableMapKey { *m_environment });232 auto iter = m_map->m_map.find(CompactTDZEnvironmentKey { *m_environment }); 209 233 RELEASE_ASSERT(iter != m_map->m_map.end()); 210 234 ++iter->value; … … 212 236 } 213 237 214 Compact VariableMap::Handle::Handle(CompactVariableEnvironment& environment, CompactVariableMap& map)238 CompactTDZEnvironmentMap::Handle::Handle(CompactTDZEnvironment& environment, CompactTDZEnvironmentMap& map) 215 239 : m_environment(&environment) 216 240 , m_map(&map) -
trunk/Source/JavaScriptCore/parser/VariableEnvironment.h
r264488 r269115 30 30 #include <wtf/HashSet.h> 31 31 #include <wtf/IteratorRange.h> 32 #include <wtf/Variant.h> 32 33 33 34 namespace JSC { … … 120 121 121 122 class VariableEnvironment { 123 WTF_MAKE_FAST_ALLOCATED; 122 124 private: 123 125 typedef HashMap<PackedRefPtr<UniquedStringImpl>, VariableEnvironmentEntry, IdentifierRepHash, HashTraits<RefPtr<UniquedStringImpl>>, VariableEnvironmentEntryHashTraits> Map; … … 263 265 }; 264 266 265 class CompactVariableEnvironment { 267 using TDZEnvironment = HashSet<RefPtr<UniquedStringImpl>, IdentifierRepHash>; 268 269 class CompactTDZEnvironment { 266 270 WTF_MAKE_FAST_ALLOCATED; 267 WTF_MAKE_NONCOPYABLE(CompactVariableEnvironment); 268 269 friend class CachedCompactVariableEnvironment; 271 WTF_MAKE_NONCOPYABLE(CompactTDZEnvironment); 272 273 friend class CachedCompactTDZEnvironment; 274 275 using Compact = Vector<PackedRefPtr<UniquedStringImpl>>; 276 using Inflated = TDZEnvironment; 277 using Variables = Variant<Compact, Inflated>; 270 278 271 279 public: 272 CompactVariableEnvironment(const VariableEnvironment&); 273 VariableEnvironment toVariableEnvironment() const; 274 275 bool operator==(const CompactVariableEnvironment&) const; 280 CompactTDZEnvironment(const TDZEnvironment&); 281 282 bool operator==(const CompactTDZEnvironment&) const; 276 283 unsigned hash() const { return m_hash; } 277 284 278 private: 279 CompactVariableEnvironment() = default; 280 281 Vector<PackedRefPtr<UniquedStringImpl>> m_variables; 282 Vector<VariableEnvironmentEntry> m_variableMetadata; 285 static void sortCompact(Compact&); 286 287 TDZEnvironment& toTDZEnvironment() const 288 { 289 if (WTF::holds_alternative<Inflated>(m_variables)) 290 return const_cast<TDZEnvironment&>(WTF::get<Inflated>(m_variables)); 291 return toTDZEnvironmentSlow(); 292 } 293 294 private: 295 CompactTDZEnvironment() = default; 296 TDZEnvironment& toTDZEnvironmentSlow() const; 297 298 mutable Variables m_variables; 283 299 unsigned m_hash; 284 bool m_isEverythingCaptured; 285 }; 286 287 struct CompactVariableMapKey { 288 CompactVariableMapKey() 300 }; 301 302 struct CompactTDZEnvironmentKey { 303 CompactTDZEnvironmentKey() 289 304 : m_environment(nullptr) 290 305 { … … 292 307 } 293 308 294 Compact VariableMapKey(CompactVariableEnvironment& environment)309 CompactTDZEnvironmentKey(CompactTDZEnvironment& environment) 295 310 : m_environment(&environment) 296 311 { } 297 312 298 static unsigned hash(const Compact VariableMapKey& key) { return key.m_environment->hash(); }299 static bool equal(const Compact VariableMapKey& a, const CompactVariableMapKey& b) { return *a.m_environment == *b.m_environment; }313 static unsigned hash(const CompactTDZEnvironmentKey& key) { return key.m_environment->hash(); } 314 static bool equal(const CompactTDZEnvironmentKey& a, const CompactTDZEnvironmentKey& b) { return *a.m_environment == *b.m_environment; } 300 315 static constexpr bool safeToCompareToEmptyOrDeleted = false; 301 static void makeDeletedValue(Compact VariableMapKey& key)302 { 303 key.m_environment = reinterpret_cast<Compact VariableEnvironment*>(1);316 static void makeDeletedValue(CompactTDZEnvironmentKey& key) 317 { 318 key.m_environment = reinterpret_cast<CompactTDZEnvironment*>(1); 304 319 } 305 320 bool isHashTableDeletedValue() const 306 321 { 307 return m_environment == reinterpret_cast<Compact VariableEnvironment*>(1);322 return m_environment == reinterpret_cast<CompactTDZEnvironment*>(1); 308 323 } 309 324 bool isHashTableEmptyValue() const … … 312 327 } 313 328 314 Compact VariableEnvironment& environment()329 CompactTDZEnvironment& environment() 315 330 { 316 331 RELEASE_ASSERT(!isHashTableDeletedValue()); … … 320 335 321 336 private: 322 Compact VariableEnvironment* m_environment;337 CompactTDZEnvironment* m_environment; 323 338 }; 324 339 … … 328 343 329 344 template<typename T> struct DefaultHash; 330 template<> struct DefaultHash<JSC::Compact VariableMapKey> : JSC::CompactVariableMapKey { };331 332 template<> struct HashTraits<JSC::Compact VariableMapKey> : GenericHashTraits<JSC::CompactVariableMapKey> {345 template<> struct DefaultHash<JSC::CompactTDZEnvironmentKey> : JSC::CompactTDZEnvironmentKey { }; 346 347 template<> struct HashTraits<JSC::CompactTDZEnvironmentKey> : GenericHashTraits<JSC::CompactTDZEnvironmentKey> { 333 348 static constexpr bool emptyValueIsZero = true; 334 static JSC::Compact VariableMapKey emptyValue() { return JSC::CompactVariableMapKey(); }349 static JSC::CompactTDZEnvironmentKey emptyValue() { return JSC::CompactTDZEnvironmentKey(); } 335 350 336 351 static constexpr bool hasIsEmptyValueFunction = true; 337 static bool isEmptyValue(JSC::Compact VariableMapKey key) { return key.isHashTableEmptyValue(); }338 339 static void constructDeletedValue(JSC::Compact VariableMapKey& key) { JSC::CompactVariableMapKey::makeDeletedValue(key); }340 static bool isDeletedValue(JSC::Compact VariableMapKey key) { return key.isHashTableDeletedValue(); }352 static bool isEmptyValue(JSC::CompactTDZEnvironmentKey key) { return key.isHashTableEmptyValue(); } 353 354 static void constructDeletedValue(JSC::CompactTDZEnvironmentKey& key) { JSC::CompactTDZEnvironmentKey::makeDeletedValue(key); } 355 static bool isDeletedValue(JSC::CompactTDZEnvironmentKey key) { return key.isHashTableDeletedValue(); } 341 356 }; 342 357 … … 345 360 namespace JSC { 346 361 347 class Compact VariableMap : public RefCounted<CompactVariableMap> {362 class CompactTDZEnvironmentMap : public RefCounted<CompactTDZEnvironmentMap> { 348 363 public: 349 364 class Handle { 350 friend class CachedCompact VariableMapHandle;365 friend class CachedCompactTDZEnvironmentMapHandle; 351 366 352 367 public: 353 368 Handle() = default; 354 369 355 Handle(Compact VariableEnvironment&, CompactVariableMap&);370 Handle(CompactTDZEnvironment&, CompactTDZEnvironmentMap&); 356 371 357 372 Handle(Handle&& other) … … 378 393 explicit operator bool() const { return !!m_map; } 379 394 380 const Compact VariableEnvironment& environment() const395 const CompactTDZEnvironment& environment() const 381 396 { 382 397 return *m_environment; … … 390 405 } 391 406 392 Compact VariableEnvironment* m_environment { nullptr };393 RefPtr<Compact VariableMap> m_map;407 CompactTDZEnvironment* m_environment { nullptr }; 408 RefPtr<CompactTDZEnvironmentMap> m_map; 394 409 }; 395 410 396 Handle get(const VariableEnvironment&);411 Handle get(const TDZEnvironment&); 397 412 398 413 private: 399 414 friend class Handle; 400 friend class CachedCompact VariableMapHandle;401 402 Handle get(Compact VariableEnvironment*, bool& isNewEntry);403 404 HashMap<Compact VariableMapKey, unsigned> m_map;415 friend class CachedCompactTDZEnvironmentMapHandle; 416 417 Handle get(CompactTDZEnvironment*, bool& isNewEntry); 418 419 HashMap<CompactTDZEnvironmentKey, unsigned> m_map; 405 420 }; 406 421 -
trunk/Source/JavaScriptCore/runtime/CachedTypes.cpp
r268993 r269115 328 328 } 329 329 330 Compact VariableMap::Handle Decoder::handleForEnvironment(CompactVariableEnvironment* environment) const330 CompactTDZEnvironmentMap::Handle Decoder::handleForTDZEnvironment(CompactTDZEnvironment* environment) const 331 331 { 332 332 auto it = m_environmentToHandleMap.find(environment); … … 335 335 } 336 336 337 void Decoder::setHandleFor Environment(CompactVariableEnvironment* environment, const CompactVariableMap::Handle& handle)337 void Decoder::setHandleForTDZEnvironment(CompactTDZEnvironment* environment, const CompactTDZEnvironmentMap::Handle& handle) 338 338 { 339 339 auto addResult = m_environmentToHandleMap.add(environment, handle); … … 1051 1051 }; 1052 1052 1053 class CachedCompactVariableEnvironment : public CachedObject<CompactVariableEnvironment> { 1054 public: 1055 void encode(Encoder& encoder, const CompactVariableEnvironment& env) 1056 { 1057 m_variables.encode(encoder, env.m_variables); 1058 m_variableMetadata.encode(encoder, env.m_variableMetadata); 1053 class CachedCompactTDZEnvironment : public CachedObject<CompactTDZEnvironment> { 1054 public: 1055 void encode(Encoder& encoder, const CompactTDZEnvironment& env) 1056 { 1057 if (WTF::holds_alternative<CompactTDZEnvironment::Compact>(env.m_variables)) 1058 m_variables.encode(encoder, WTF::get<CompactTDZEnvironment::Compact>(env.m_variables)); 1059 else { 1060 CompactTDZEnvironment::Compact compact; 1061 for (auto& key : WTF::get<CompactTDZEnvironment::Inflated>(env.m_variables)) 1062 compact.append(key); 1063 m_variables.encode(encoder, compact); 1064 } 1059 1065 m_hash = env.m_hash; 1060 m_isEverythingCaptured = env.m_isEverythingCaptured; 1061 } 1062 1063 void decode(Decoder& decoder, CompactVariableEnvironment& env) const 1064 { 1065 m_variables.decode(decoder, env.m_variables); 1066 m_variableMetadata.decode(decoder, env.m_variableMetadata); 1066 } 1067 1068 void decode(Decoder& decoder, CompactTDZEnvironment& env) const 1069 { 1070 { 1071 CompactTDZEnvironment::Compact compact; 1072 m_variables.decode(decoder, compact); 1073 CompactTDZEnvironment::sortCompact(compact); 1074 env.m_variables = CompactTDZEnvironment::Variables(WTFMove(compact)); 1075 } 1067 1076 env.m_hash = m_hash; 1068 env.m_isEverythingCaptured = m_isEverythingCaptured; 1069 } 1070 1071 CompactVariableEnvironment* decode(Decoder& decoder) const 1072 { 1073 CompactVariableEnvironment* env = new CompactVariableEnvironment; 1077 } 1078 1079 CompactTDZEnvironment* decode(Decoder& decoder) const 1080 { 1081 CompactTDZEnvironment* env = new CompactTDZEnvironment; 1074 1082 decode(decoder, *env); 1075 1083 return env; … … 1078 1086 private: 1079 1087 CachedVector<CachedRefPtr<CachedUniquedStringImpl, UniquedStringImpl, WTF::PackedPtrTraits<UniquedStringImpl>>> m_variables; 1080 CachedVector<VariableEnvironmentEntry> m_variableMetadata;1081 1088 unsigned m_hash; 1082 bool m_isEverythingCaptured; 1083 }; 1084 1085 class CachedCompactVariableMapHandle : public CachedObject<CompactVariableMap::Handle> { 1086 public: 1087 void encode(Encoder& encoder, const CompactVariableMap::Handle& handle) 1089 }; 1090 1091 class CachedCompactTDZEnvironmentMapHandle : public CachedObject<CompactTDZEnvironmentMap::Handle> { 1092 public: 1093 void encode(Encoder& encoder, const CompactTDZEnvironmentMap::Handle& handle) 1088 1094 { 1089 1095 m_environment.encode(encoder, handle.m_environment); 1090 1096 } 1091 1097 1092 Compact VariableMap::Handle decode(Decoder& decoder) const1098 CompactTDZEnvironmentMap::Handle decode(Decoder& decoder) const 1093 1099 { 1094 1100 bool isNewAllocation; 1095 Compact VariableEnvironment* environment = m_environment.decode(decoder, isNewAllocation);1101 CompactTDZEnvironment* environment = m_environment.decode(decoder, isNewAllocation); 1096 1102 if (!environment) { 1097 1103 ASSERT(!isNewAllocation); 1098 return Compact VariableMap::Handle();1104 return CompactTDZEnvironmentMap::Handle(); 1099 1105 } 1100 1106 1101 1107 if (!isNewAllocation) 1102 return decoder.handleFor Environment(environment);1108 return decoder.handleForTDZEnvironment(environment); 1103 1109 bool isNewEntry; 1104 Compact VariableMap::Handle handle = decoder.vm().m_compactVariableMap->get(environment, isNewEntry);1110 CompactTDZEnvironmentMap::Handle handle = decoder.vm().m_compactVariableMap->get(environment, isNewEntry); 1105 1111 if (!isNewEntry) { 1106 1112 decoder.addFinalizer([=] { … … 1108 1114 }); 1109 1115 } 1110 decoder.setHandleFor Environment(environment, handle);1116 decoder.setHandleForTDZEnvironment(environment, handle); 1111 1117 return handle; 1112 1118 } 1113 1119 1114 private: 1115 CachedPtr<CachedCompactVariableEnvironment> m_environment; 1120 void decode(Decoder& decoder, CompactTDZEnvironmentMap::Handle& handle) const 1121 { 1122 handle = decode(decoder); 1123 } 1124 1125 private: 1126 CachedPtr<CachedCompactTDZEnvironment> m_environment; 1116 1127 }; 1117 1128 … … 1752 1763 UnlinkedFunctionExecutable::RareData* rareData = new UnlinkedFunctionExecutable::RareData { }; 1753 1764 m_classSource.decode(decoder, rareData->m_classSource); 1754 auto parentScopeTDZVariables = m_parentScopeTDZVariables.decode(decoder); 1755 rareData->m_parentScopeTDZVariables = WTFMove(parentScopeTDZVariables); 1765 m_parentScopeTDZVariables.decode(decoder, rareData->m_parentScopeTDZVariables); 1756 1766 return rareData; 1757 1767 } … … 1759 1769 private: 1760 1770 CachedSourceCodeWithoutProvider m_classSource; 1761 Cached CompactVariableMapHandlem_parentScopeTDZVariables;1771 CachedVector<CachedCompactTDZEnvironmentMapHandle> m_parentScopeTDZVariables; 1762 1772 }; 1763 1773 -
trunk/Source/JavaScriptCore/runtime/CachedTypes.h
r247705 r269115 91 91 WTF::Optional<void*> cachedPtrForOffset(ptrdiff_t); 92 92 const void* ptrForOffsetFromBase(ptrdiff_t); 93 Compact VariableMap::Handle handleForEnvironment(CompactVariableEnvironment*) const;94 void setHandleFor Environment(CompactVariableEnvironment*, const CompactVariableMap::Handle&);93 CompactTDZEnvironmentMap::Handle handleForTDZEnvironment(CompactTDZEnvironment*) const; 94 void setHandleForTDZEnvironment(CompactTDZEnvironment*, const CompactTDZEnvironmentMap::Handle&); 95 95 void addLeafExecutable(const UnlinkedFunctionExecutable*, ptrdiff_t); 96 96 RefPtr<SourceProvider> provider() const; … … 106 106 HashMap<ptrdiff_t, void*> m_offsetToPtrMap; 107 107 Vector<std::function<void()>> m_finalizers; 108 HashMap<Compact VariableEnvironment*, CompactVariableMap::Handle> m_environmentToHandleMap;108 HashMap<CompactTDZEnvironment*, CompactTDZEnvironmentMap::Handle> m_environmentToHandleMap; 109 109 RefPtr<SourceProvider> m_provider; 110 110 }; -
trunk/Source/JavaScriptCore/runtime/CodeCache.cpp
r262613 r269115 72 72 73 73 template <class UnlinkedCodeBlockType, class ExecutableType = ScriptExecutable> 74 UnlinkedCodeBlockType* generateUnlinkedCodeBlockImpl(VM& vm, const SourceCode& source, JSParserStrictMode strictMode, JSParserScriptMode scriptMode, OptionSet<CodeGenerationMode> codeGenerationMode, ParserError& error, EvalContextType evalContextType, DerivedContextType derivedContextType, bool isArrowFunctionContext, const VariableEnvironment* variablesUnderTDZ, ExecutableType* executable = nullptr)74 UnlinkedCodeBlockType* generateUnlinkedCodeBlockImpl(VM& vm, const SourceCode& source, JSParserStrictMode strictMode, JSParserScriptMode scriptMode, OptionSet<CodeGenerationMode> codeGenerationMode, ParserError& error, EvalContextType evalContextType, DerivedContextType derivedContextType, bool isArrowFunctionContext, const TDZEnvironment* variablesUnderTDZ = nullptr, const VariableEnvironment* parentScopePrivateNames = nullptr, ExecutableType* executable = nullptr) 75 75 { 76 76 typedef typename CacheTypes<UnlinkedCodeBlockType>::RootNode RootNode; 77 77 bool isInsideOrdinaryFunction = executable && executable->isInsideOrdinaryFunction(); 78 78 79 std::unique_ptr<RootNode> rootNode = parse<RootNode>( 79 vm, source, Identifier(), JSParserBuiltinMode::NotBuiltin, strictMode, scriptMode, CacheTypes<UnlinkedCodeBlockType>::parseMode, SuperBinding::NotNeeded, error, nullptr, ConstructorKind::None, derivedContextType, evalContextType, nullptr, variablesUnderTDZ, nullptr, isInsideOrdinaryFunction); 80 vm, source, Identifier(), JSParserBuiltinMode::NotBuiltin, strictMode, scriptMode, CacheTypes<UnlinkedCodeBlockType>::parseMode, SuperBinding::NotNeeded, error, nullptr, ConstructorKind::None, derivedContextType, evalContextType, nullptr, parentScopePrivateNames, nullptr, isInsideOrdinaryFunction); 81 80 82 if (!rootNode) 81 83 return nullptr; … … 104 106 unlinkedCodeBlock->setSourceMappingURLDirective(source.provider()->sourceMappingURLDirective()); 105 107 106 error = BytecodeGenerator::generate(vm, rootNode.get(), source, unlinkedCodeBlock, codeGenerationMode, variablesUnderTDZ, ecmaMode); 108 Vector<CompactTDZEnvironmentMap::Handle> parentVariablesUnderTDZ; 109 if (variablesUnderTDZ) 110 parentVariablesUnderTDZ.append(vm.m_compactVariableMap->get(*variablesUnderTDZ)); 111 error = BytecodeGenerator::generate(vm, rootNode.get(), source, unlinkedCodeBlock, codeGenerationMode, parentVariablesUnderTDZ, ecmaMode); 107 112 108 113 if (error.isValid()) … … 113 118 114 119 template <class UnlinkedCodeBlockType, class ExecutableType> 115 UnlinkedCodeBlockType* generateUnlinkedCodeBlock(VM& vm, ExecutableType* executable, const SourceCode& source, JSParserStrictMode strictMode, JSParserScriptMode scriptMode, OptionSet<CodeGenerationMode> codeGenerationMode, ParserError& error, EvalContextType evalContextType, const VariableEnvironment* variablesUnderTDZ)116 { 117 return generateUnlinkedCodeBlockImpl<UnlinkedCodeBlockType, ExecutableType>(vm, source, strictMode, scriptMode, codeGenerationMode, error, evalContextType, executable->derivedContextType(), executable->isArrowFunctionContext(), variablesUnderTDZ, executable);118 } 119 120 UnlinkedEvalCodeBlock* generateUnlinkedCodeBlockForDirectEval(VM& vm, DirectEvalExecutable* executable, const SourceCode& source, JSParserStrictMode strictMode, JSParserScriptMode scriptMode, OptionSet<CodeGenerationMode> codeGenerationMode, ParserError& error, EvalContextType evalContextType, const VariableEnvironment* variablesUnderTDZ)121 { 122 return generateUnlinkedCodeBlock<UnlinkedEvalCodeBlock>(vm, executable, source, strictMode, scriptMode, codeGenerationMode, error, evalContextType, variablesUnderTDZ );120 UnlinkedCodeBlockType* generateUnlinkedCodeBlock(VM& vm, ExecutableType* executable, const SourceCode& source, JSParserStrictMode strictMode, JSParserScriptMode scriptMode, OptionSet<CodeGenerationMode> codeGenerationMode, ParserError& error, EvalContextType evalContextType, const TDZEnvironment* variablesUnderTDZ = nullptr, const VariableEnvironment* parentScopePrivateNames = nullptr) 121 { 122 return generateUnlinkedCodeBlockImpl<UnlinkedCodeBlockType, ExecutableType>(vm, source, strictMode, scriptMode, codeGenerationMode, error, evalContextType, executable->derivedContextType(), executable->isArrowFunctionContext(), variablesUnderTDZ, parentScopePrivateNames, executable); 123 } 124 125 UnlinkedEvalCodeBlock* generateUnlinkedCodeBlockForDirectEval(VM& vm, DirectEvalExecutable* executable, const SourceCode& source, JSParserStrictMode strictMode, JSParserScriptMode scriptMode, OptionSet<CodeGenerationMode> codeGenerationMode, ParserError& error, EvalContextType evalContextType, const TDZEnvironment* variablesUnderTDZ, const VariableEnvironment* parentScopePrivateNames) 126 { 127 return generateUnlinkedCodeBlock<UnlinkedEvalCodeBlock>(vm, executable, source, strictMode, scriptMode, codeGenerationMode, error, evalContextType, variablesUnderTDZ, parentScopePrivateNames); 123 128 } 124 129 125 130 template <class UnlinkedCodeBlockType> 126 131 std::enable_if_t<!std::is_same<UnlinkedCodeBlockType, UnlinkedEvalCodeBlock>::value, UnlinkedCodeBlockType*> 127 recursivelyGenerateUnlinkedCodeBlock(VM& vm, const SourceCode& source, JSParserStrictMode strictMode, JSParserScriptMode scriptMode, OptionSet<CodeGenerationMode> codeGenerationMode, ParserError& error, EvalContextType evalContextType , const VariableEnvironment* variablesUnderTDZ)132 recursivelyGenerateUnlinkedCodeBlock(VM& vm, const SourceCode& source, JSParserStrictMode strictMode, JSParserScriptMode scriptMode, OptionSet<CodeGenerationMode> codeGenerationMode, ParserError& error, EvalContextType evalContextType) 128 133 { 129 134 bool isArrowFunctionContext = false; 130 UnlinkedCodeBlockType* unlinkedCodeBlock = generateUnlinkedCodeBlockImpl<UnlinkedCodeBlockType>(vm, source, strictMode, scriptMode, codeGenerationMode, error, evalContextType, DerivedContextType::None, isArrowFunctionContext , variablesUnderTDZ);135 UnlinkedCodeBlockType* unlinkedCodeBlock = generateUnlinkedCodeBlockImpl<UnlinkedCodeBlockType>(vm, source, strictMode, scriptMode, codeGenerationMode, error, evalContextType, DerivedContextType::None, isArrowFunctionContext); 131 136 if (!unlinkedCodeBlock) 132 137 return nullptr; … … 136 141 } 137 142 138 UnlinkedProgramCodeBlock* recursivelyGenerateUnlinkedCodeBlockForProgram(VM& vm, const SourceCode& source, JSParserStrictMode strictMode, JSParserScriptMode scriptMode, OptionSet<CodeGenerationMode> codeGenerationMode, ParserError& error, EvalContextType evalContextType , const VariableEnvironment* variablesUnderTDZ)139 { 140 return recursivelyGenerateUnlinkedCodeBlock<UnlinkedProgramCodeBlock>(vm, source, strictMode, scriptMode, codeGenerationMode, error, evalContextType , variablesUnderTDZ);141 } 142 143 UnlinkedModuleProgramCodeBlock* recursivelyGenerateUnlinkedCodeBlockForModuleProgram(VM& vm, const SourceCode& source, JSParserStrictMode strictMode, JSParserScriptMode scriptMode, OptionSet<CodeGenerationMode> codeGenerationMode, ParserError& error, EvalContextType evalContextType , const VariableEnvironment* variablesUnderTDZ)144 { 145 return recursivelyGenerateUnlinkedCodeBlock<UnlinkedModuleProgramCodeBlock>(vm, source, strictMode, scriptMode, codeGenerationMode, error, evalContextType , variablesUnderTDZ);143 UnlinkedProgramCodeBlock* recursivelyGenerateUnlinkedCodeBlockForProgram(VM& vm, const SourceCode& source, JSParserStrictMode strictMode, JSParserScriptMode scriptMode, OptionSet<CodeGenerationMode> codeGenerationMode, ParserError& error, EvalContextType evalContextType) 144 { 145 return recursivelyGenerateUnlinkedCodeBlock<UnlinkedProgramCodeBlock>(vm, source, strictMode, scriptMode, codeGenerationMode, error, evalContextType); 146 } 147 148 UnlinkedModuleProgramCodeBlock* recursivelyGenerateUnlinkedCodeBlockForModuleProgram(VM& vm, const SourceCode& source, JSParserStrictMode strictMode, JSParserScriptMode scriptMode, OptionSet<CodeGenerationMode> codeGenerationMode, ParserError& error, EvalContextType evalContextType) 149 { 150 return recursivelyGenerateUnlinkedCodeBlock<UnlinkedModuleProgramCodeBlock>(vm, source, strictMode, scriptMode, codeGenerationMode, error, evalContextType); 146 151 } 147 152 … … 169 174 } 170 175 171 VariableEnvironment variablesUnderTDZ; 172 unlinkedCodeBlock = generateUnlinkedCodeBlock<UnlinkedCodeBlockType, ExecutableType>(vm, executable, source, strictMode, scriptMode, codeGenerationMode, error, evalContextType, &variablesUnderTDZ); 176 unlinkedCodeBlock = generateUnlinkedCodeBlock<UnlinkedCodeBlockType, ExecutableType>(vm, executable, source, strictMode, scriptMode, codeGenerationMode, error, evalContextType); 173 177 174 178 if (unlinkedCodeBlock && Options::useCodeCache()) { -
trunk/Source/JavaScriptCore/runtime/CodeCache.h
r255321 r269115 51 51 class SourceCode; 52 52 class VM; 53 class VariableEnvironment; 53 54 using TDZEnvironment = HashSet<RefPtr<UniquedStringImpl>, IdentifierRepHash>; 54 55 55 56 namespace CodeCacheInternal { … … 254 255 }; 255 256 256 UnlinkedEvalCodeBlock* generateUnlinkedCodeBlockForDirectEval(VM&, DirectEvalExecutable*, const SourceCode&, JSParserStrictMode, JSParserScriptMode, OptionSet<CodeGenerationMode>, ParserError&, EvalContextType, const VariableEnvironment* variablesUnderTDZ);257 UnlinkedProgramCodeBlock* recursivelyGenerateUnlinkedCodeBlockForProgram(VM&, const SourceCode&, JSParserStrictMode, JSParserScriptMode, OptionSet<CodeGenerationMode>, ParserError&, EvalContextType , const VariableEnvironment* variablesUnderTDZ);258 UnlinkedModuleProgramCodeBlock* recursivelyGenerateUnlinkedCodeBlockForModuleProgram(VM&, const SourceCode&, JSParserStrictMode, JSParserScriptMode, OptionSet<CodeGenerationMode>, ParserError&, EvalContextType , const VariableEnvironment* variablesUnderTDZ);257 UnlinkedEvalCodeBlock* generateUnlinkedCodeBlockForDirectEval(VM&, DirectEvalExecutable*, const SourceCode&, JSParserStrictMode, JSParserScriptMode, OptionSet<CodeGenerationMode>, ParserError&, EvalContextType, const TDZEnvironment* variablesUnderTDZ, const VariableEnvironment* parentScopePrivateNames); 258 UnlinkedProgramCodeBlock* recursivelyGenerateUnlinkedCodeBlockForProgram(VM&, const SourceCode&, JSParserStrictMode, JSParserScriptMode, OptionSet<CodeGenerationMode>, ParserError&, EvalContextType); 259 UnlinkedModuleProgramCodeBlock* recursivelyGenerateUnlinkedCodeBlockForModuleProgram(VM&, const SourceCode&, JSParserStrictMode, JSParserScriptMode, OptionSet<CodeGenerationMode>, ParserError&, EvalContextType); 259 260 260 261 void writeCodeBlock(VM&, const SourceCodeKey&, const SourceCodeValue&); -
trunk/Source/JavaScriptCore/runtime/Completion.cpp
r261755 r269115 92 92 RELEASE_ASSERT(vm.atomStringTable() == Thread::current().atomStringTable()); 93 93 94 VariableEnvironment variablesUnderTDZ;95 94 JSParserStrictMode strictMode = JSParserStrictMode::NotStrict; 96 95 JSParserScriptMode scriptMode = JSParserScriptMode::Classic; … … 98 97 99 98 ParserError parserError; 100 UnlinkedCodeBlock* unlinkedCodeBlock = recursivelyGenerateUnlinkedCodeBlockForProgram(vm, source, strictMode, scriptMode, { }, parserError, evalContextType , &variablesUnderTDZ);99 UnlinkedCodeBlock* unlinkedCodeBlock = recursivelyGenerateUnlinkedCodeBlockForProgram(vm, source, strictMode, scriptMode, { }, parserError, evalContextType); 101 100 if (parserError.isValid()) 102 101 error = parserError; … … 112 111 RELEASE_ASSERT(vm.atomStringTable() == Thread::current().atomStringTable()); 113 112 114 VariableEnvironment variablesUnderTDZ;115 113 JSParserStrictMode strictMode = JSParserStrictMode::Strict; 116 114 JSParserScriptMode scriptMode = JSParserScriptMode::Module; … … 118 116 119 117 ParserError parserError; 120 UnlinkedCodeBlock* unlinkedCodeBlock = recursivelyGenerateUnlinkedCodeBlockForModuleProgram(vm, source, strictMode, scriptMode, { }, parserError, evalContextType , &variablesUnderTDZ);118 UnlinkedCodeBlock* unlinkedCodeBlock = recursivelyGenerateUnlinkedCodeBlockForModuleProgram(vm, source, strictMode, scriptMode, { }, parserError, evalContextType); 121 119 if (parserError.isValid()) 122 120 error = parserError; -
trunk/Source/JavaScriptCore/runtime/DirectEvalExecutable.cpp
r261755 r269115 35 35 namespace JSC { 36 36 37 DirectEvalExecutable* DirectEvalExecutable::create(JSGlobalObject* globalObject, const SourceCode& source, DerivedContextType derivedContextType, NeedsClassFieldInitializer needsClassFieldInitializer, bool isArrowFunctionContext, bool isInsideOrdinaryFunction, EvalContextType evalContextType, const VariableEnvironment* variablesUnderTDZ, ECMAMode ecmaMode)37 DirectEvalExecutable* DirectEvalExecutable::create(JSGlobalObject* globalObject, const SourceCode& source, DerivedContextType derivedContextType, NeedsClassFieldInitializer needsClassFieldInitializer, bool isArrowFunctionContext, bool isInsideOrdinaryFunction, EvalContextType evalContextType, const TDZEnvironment* variablesUnderTDZ, const VariableEnvironment* privateNames, ECMAMode ecmaMode) 38 38 { 39 39 VM& vm = globalObject->vm(); … … 53 53 54 54 // We don't bother with CodeCache here because direct eval uses a specialized DirectEvalCodeCache. 55 UnlinkedEvalCodeBlock* unlinkedEvalCode = generateUnlinkedCodeBlockForDirectEval(vm, executable, executable->source(), strictMode, JSParserScriptMode::Classic, codeGenerationMode, error, evalContextType, variablesUnderTDZ );55 UnlinkedEvalCodeBlock* unlinkedEvalCode = generateUnlinkedCodeBlockForDirectEval(vm, executable, executable->source(), strictMode, JSParserScriptMode::Classic, codeGenerationMode, error, evalContextType, variablesUnderTDZ, privateNames); 56 56 57 57 if (globalObject->hasDebugger()) -
trunk/Source/JavaScriptCore/runtime/DirectEvalExecutable.h
r259676 r269115 32 32 class DirectEvalExecutable final : public EvalExecutable { 33 33 public: 34 static DirectEvalExecutable* create(JSGlobalObject*, const SourceCode&, DerivedContextType, NeedsClassFieldInitializer, bool isArrowFunctionContext, bool isInsideOrdinaryFunction, EvalContextType, const VariableEnvironment*, ECMAMode);34 static DirectEvalExecutable* create(JSGlobalObject*, const SourceCode&, DerivedContextType, NeedsClassFieldInitializer, bool isArrowFunctionContext, bool isInsideOrdinaryFunction, EvalContextType, const TDZEnvironment* parentScopeTDZVariables, const VariableEnvironment* privateNames, ECMAMode); 35 35 private: 36 36 DirectEvalExecutable(JSGlobalObject*, const SourceCode&, bool inStrictContext, DerivedContextType, NeedsClassFieldInitializer, bool isArrowFunctionContext, bool isInsideOrdinaryFunction, EvalContextType); -
trunk/Source/JavaScriptCore/runtime/JSScope.cpp
r264736 r269115 322 322 } 323 323 324 void JSScope::collectClosureVariablesUnderTDZ(JSScope* scope, VariableEnvironment& result)324 void JSScope::collectClosureVariablesUnderTDZ(JSScope* scope, TDZEnvironment& result, VariableEnvironment& privateNames) 325 325 { 326 326 for (; scope; scope = scope->next()) { … … 339 339 for (auto end = symbolTable->end(locker), iter = symbolTable->begin(locker); iter != end; ++iter) 340 340 result.add(iter->key); 341 341 342 if (symbolTable->hasPrivateNames()) { 342 343 for (auto name : symbolTable->privateNames()) 343 result.usePrivateName(name);344 privateNames.usePrivateName(name); 344 345 } 345 346 } -
trunk/Source/JavaScriptCore/runtime/JSScope.h
r261464 r269115 36 36 class WatchpointSet; 37 37 38 using TDZEnvironment = HashSet<RefPtr<UniquedStringImpl>, IdentifierRepHash>; 39 38 40 class JSScope : public JSNonFinalObject { 39 41 public: … … 61 63 static JSScope* constantScopeForCodeBlock(ResolveType, CodeBlock*); 62 64 63 static void collectClosureVariablesUnderTDZ(JSScope*, VariableEnvironment& result);65 static void collectClosureVariablesUnderTDZ(JSScope*, TDZEnvironment& result, VariableEnvironment& privateNames); 64 66 65 67 static void visitChildren(JSCell*, SlotVisitor&); -
trunk/Source/JavaScriptCore/runtime/VM.cpp
r268956 r269115 393 393 , entryScope(nullptr) 394 394 , m_regExpCache(new RegExpCache(this)) 395 , m_compactVariableMap(adoptRef(*(new Compact VariableMap)))395 , m_compactVariableMap(adoptRef(*(new CompactTDZEnvironmentMap))) 396 396 #if ENABLE(REGEXP_TRACING) 397 397 , m_rtTraceList(new RTTraceList()) -
trunk/Source/JavaScriptCore/runtime/VM.h
r268956 r269115 109 109 class CodeCache; 110 110 class CommonIdentifiers; 111 class Compact VariableMap;111 class CompactTDZEnvironmentMap; 112 112 class ConservativeRoots; 113 113 class ControlFlowProfiler; … … 1008 1008 #endif 1009 1009 1010 Ref<Compact VariableMap> m_compactVariableMap;1010 Ref<CompactTDZEnvironmentMap> m_compactVariableMap; 1011 1011 1012 1012 std::unique_ptr<HasOwnPropertyCache> m_hasOwnPropertyCache; -
trunk/Source/WTF/ChangeLog
r269111 r269115 1 2020-10-28 Saam Barati <sbarati@apple.com> 2 3 Better cache our serialization of the outer TDZ environment when creating FunctionExecutables during bytecode generation 4 https://bugs.webkit.org/show_bug.cgi?id=199866 5 <rdar://problem/53333108> 6 7 Reviewed by Tadeu Zagallo. 8 9 * wtf/RefPtr.h: 10 (WTF::swap): Deleted. 11 This function is no longer necessary, and causes ADL (https://en.cppreference.com/w/cpp/language/adl) 12 compile errors when not using DumbPtrTraits and calling sort on a vector of that type. 13 1 14 2020-10-28 Sam Weinig <weinig@apple.com> 2 15 -
trunk/Source/WTF/wtf/RefPtr.h
r268993 r269115 194 194 } 195 195 196 template<typename T, typename U, typename V, typename X, typename Y, typename Z, typename = std::enable_if_t<!std::is_same<U, RawPtrTraits<T>>::value || !std::is_same<Y, RawPtrTraits<X>>::value>>197 inline void swap(RefPtr<T, U, V>& a, RefPtr<X, Y, Z>& b)198 {199 a.swap(b);200 }201 202 196 template<typename T, typename U, typename V, typename X, typename Y, typename Z> 203 197 inline bool operator==(const RefPtr<T, U, V>& a, const RefPtr<X, Y, Z>& b)
Note: See TracChangeset
for help on using the changeset viewer.