Changeset 241571 in webkit
- Timestamp:
- Feb 14, 2019 4:06:30 PM (5 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r241233 r241571 1 2019-02-14 Saam Barati <sbarati@apple.com> 2 3 Cache the results of BytecodeGenerator::getVariablesUnderTDZ 4 https://bugs.webkit.org/show_bug.cgi?id=194583 5 <rdar://problem/48028140> 6 7 Reviewed by Yusuke Suzuki. 8 9 * microbenchmarks/cache-get-variables-under-tdz-in-bytecode-generator.js: Added. 10 1 11 2019-02-08 Yusuke Suzuki <ysuzuki@apple.com> 2 12 -
trunk/Source/JavaScriptCore/ChangeLog
r241560 r241571 1 2019-02-14 Saam Barati <sbarati@apple.com> 2 3 Cache the results of BytecodeGenerator::getVariablesUnderTDZ 4 https://bugs.webkit.org/show_bug.cgi?id=194583 5 <rdar://problem/48028140> 6 7 Reviewed by Yusuke Suzuki. 8 9 This patch makes it so that getVariablesUnderTDZ caches a result of 10 CompactVariableMap::Handle. getVariablesUnderTDZ is costly when 11 it's called in an environment where there are a lot of variables. 12 This patch makes it so we cache its results. This is profitable when 13 getVariablesUnderTDZ is called repeatedly with the same environment 14 state. This is common since we call this every time we encounter a 15 function definition/expression node. 16 17 * builtins/BuiltinExecutables.cpp: 18 (JSC::BuiltinExecutables::createExecutable): 19 * bytecode/UnlinkedFunctionExecutable.cpp: 20 (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable): 21 * bytecode/UnlinkedFunctionExecutable.h: 22 * bytecompiler/BytecodeGenerator.cpp: 23 (JSC::BytecodeGenerator::popLexicalScopeInternal): 24 (JSC::BytecodeGenerator::liftTDZCheckIfPossible): 25 (JSC::BytecodeGenerator::pushTDZVariables): 26 (JSC::BytecodeGenerator::getVariablesUnderTDZ): 27 (JSC::BytecodeGenerator::restoreTDZStack): 28 * bytecompiler/BytecodeGenerator.h: 29 (JSC::BytecodeGenerator::makeFunction): 30 * parser/VariableEnvironment.cpp: 31 (JSC::CompactVariableMap::Handle::Handle): 32 (JSC::CompactVariableMap::Handle::operator=): 33 * parser/VariableEnvironment.h: 34 (JSC::CompactVariableMap::Handle::operator bool const): 35 * runtime/CodeCache.cpp: 36 (JSC::CodeCache::getUnlinkedGlobalFunctionExecutable): 37 1 38 2019-02-14 Yusuke Suzuki <ysuzuki@apple.com> 2 39 -
trunk/Source/JavaScriptCore/builtins/BuiltinExecutables.cpp
r240228 r241571 259 259 260 260 VariableEnvironment dummyTDZVariables; 261 UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&vm, source, &metadata, kind, constructAbility, JSParserScriptMode::Classic, dummyTDZVariables, DerivedContextType::None, isBuiltinDefaultClassConstructor);261 UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&vm, source, &metadata, kind, constructAbility, JSParserScriptMode::Classic, vm.m_compactVariableMap->get(dummyTDZVariables), DerivedContextType::None, isBuiltinDefaultClassConstructor); 262 262 return functionExecutable; 263 263 } -
trunk/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp
r241552 r241571 79 79 } 80 80 81 UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM* vm, Structure* structure, const SourceCode& parentSource, FunctionMetadataNode* node, UnlinkedFunctionKind kind, ConstructAbility constructAbility, JSParserScriptMode scriptMode, VariableEnvironment&parentScopeTDZVariables, DerivedContextType derivedContextType, bool isBuiltinDefaultClassConstructor)81 UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM* vm, Structure* structure, const SourceCode& parentSource, FunctionMetadataNode* node, UnlinkedFunctionKind kind, ConstructAbility constructAbility, JSParserScriptMode scriptMode, CompactVariableMap::Handle parentScopeTDZVariables, DerivedContextType derivedContextType, bool isBuiltinDefaultClassConstructor) 82 82 : Base(*vm, structure) 83 83 , m_firstLineOffset(node->firstLine() - parentSource.firstLine().oneBasedInt()) … … 108 108 , m_inferredName(node->inferredName()) 109 109 , m_classSource(node->classSource()) 110 , m_parentScopeTDZVariables( vm->m_compactVariableMap->get(parentScopeTDZVariables))110 , m_parentScopeTDZVariables(WTFMove(parentScopeTDZVariables)) 111 111 { 112 112 // Make sure these bitfields are adequately wide. -
trunk/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h
r241552 r241571 68 68 } 69 69 70 static UnlinkedFunctionExecutable* create(VM* vm, const SourceCode& source, FunctionMetadataNode* node, UnlinkedFunctionKind unlinkedFunctionKind, ConstructAbility constructAbility, JSParserScriptMode scriptMode, VariableEnvironment&parentScopeTDZVariables, DerivedContextType derivedContextType, bool isBuiltinDefaultClassConstructor = false)70 static UnlinkedFunctionExecutable* create(VM* vm, const SourceCode& source, FunctionMetadataNode* node, UnlinkedFunctionKind unlinkedFunctionKind, ConstructAbility constructAbility, JSParserScriptMode scriptMode, CompactVariableMap::Handle parentScopeTDZVariables, DerivedContextType derivedContextType, bool isBuiltinDefaultClassConstructor = false) 71 71 { 72 72 UnlinkedFunctionExecutable* instance = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(vm->heap)) … … 153 153 154 154 private: 155 UnlinkedFunctionExecutable(VM*, Structure*, const SourceCode&, FunctionMetadataNode*, UnlinkedFunctionKind, ConstructAbility, JSParserScriptMode, VariableEnvironment&, JSC::DerivedContextType, bool isBuiltinDefaultClassConstructor);155 UnlinkedFunctionExecutable(VM*, Structure*, const SourceCode&, FunctionMetadataNode*, UnlinkedFunctionKind, ConstructAbility, JSParserScriptMode, CompactVariableMap::Handle, JSC::DerivedContextType, bool isBuiltinDefaultClassConstructor); 156 156 UnlinkedFunctionExecutable(Decoder&, VariableEnvironment&, const CachedFunctionExecutable&); 157 157 -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r240981 r241571 2196 2196 2197 2197 m_TDZStack.removeLast(); 2198 m_cachedVariablesUnderTDZ = { }; 2198 2199 } 2199 2200 … … 2815 2816 auto iter = m_TDZStack[i].find(identifier); 2816 2817 if (iter != m_TDZStack[i].end()) { 2817 if (iter->value == TDZNecessityLevel::Optimize) 2818 if (iter->value == TDZNecessityLevel::Optimize) { 2819 m_cachedVariablesUnderTDZ = { }; 2818 2820 iter->value = TDZNecessityLevel::NotNeeded; 2821 } 2819 2822 break; 2820 2823 } … … 2841 2844 2842 2845 m_TDZStack.append(WTFMove(map)); 2843 } 2844 2845 void BytecodeGenerator::getVariablesUnderTDZ(VariableEnvironment& result) 2846 { 2846 m_cachedVariablesUnderTDZ = { }; 2847 } 2848 2849 CompactVariableMap::Handle BytecodeGenerator::getVariablesUnderTDZ() 2850 { 2851 if (m_cachedVariablesUnderTDZ) 2852 return m_cachedVariablesUnderTDZ; 2853 2847 2854 // We keep track of variablesThatDontNeedTDZ in this algorithm to prevent 2848 2855 // reporting that "x" is under TDZ if this function is called at "...". … … 2855 2862 // let x; 2856 2863 // } 2857 //2858 2864 SmallPtrSet<UniquedStringImpl*, 16> variablesThatDontNeedTDZ; 2865 VariableEnvironment environment; 2859 2866 for (unsigned i = m_TDZStack.size(); i--; ) { 2860 2867 auto& map = m_TDZStack[i]; … … 2862 2869 if (entry.value != TDZNecessityLevel::NotNeeded) { 2863 2870 if (!variablesThatDontNeedTDZ.contains(entry.key.get())) 2864 result.add(entry.key.get());2871 environment.add(entry.key.get()); 2865 2872 } else 2866 2873 variablesThatDontNeedTDZ.add(entry.key.get()); 2867 2874 } 2868 2875 } 2876 2877 m_cachedVariablesUnderTDZ = m_vm->m_compactVariableMap->get(environment); 2878 return m_cachedVariablesUnderTDZ; 2869 2879 } 2870 2880 … … 2877 2887 { 2878 2888 m_TDZStack = preservedStack.m_preservedTDZStack; 2889 m_cachedVariablesUnderTDZ = { }; 2879 2890 } 2880 2891 -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
r240981 r241571 1138 1138 } 1139 1139 1140 VariableEnvironment variablesUnderTDZ; 1141 getVariablesUnderTDZ(variablesUnderTDZ); 1140 CompactVariableMap::Handle variablesUnderTDZ = getVariablesUnderTDZ(); 1142 1141 1143 1142 // FIXME: These flags, ParserModes and propagation to XXXCodeBlocks should be reorganized. … … 1148 1147 constructAbility = ConstructAbility::CanConstruct; 1149 1148 1150 return UnlinkedFunctionExecutable::create(m_vm, m_scopeNode->source(), metadata, isBuiltinFunction() ? UnlinkedBuiltinFunction : UnlinkedNormalFunction, constructAbility, scriptMode(), variablesUnderTDZ, newDerivedContextType);1151 } 1152 1153 void getVariablesUnderTDZ(VariableEnvironment&);1149 return UnlinkedFunctionExecutable::create(m_vm, m_scopeNode->source(), metadata, isBuiltinFunction() ? UnlinkedBuiltinFunction : UnlinkedNormalFunction, constructAbility, scriptMode(), WTFMove(variablesUnderTDZ), newDerivedContextType); 1150 } 1151 1152 CompactVariableMap::Handle getVariablesUnderTDZ(); 1154 1153 1155 1154 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); … … 1314 1313 DerivedContextType m_derivedContextType { DerivedContextType::None }; 1315 1314 1315 CompactVariableMap::Handle m_cachedVariablesUnderTDZ; 1316 1316 1317 using CatchEntry = std::tuple<TryData*, VirtualRegister, VirtualRegister>; 1317 1318 Vector<CatchEntry> m_catchesToEmit; -
trunk/Source/JavaScriptCore/parser/VariableEnvironment.cpp
r239755 r241571 184 184 } 185 185 186 CompactVariableMap::Handle::Handle(const CompactVariableMap::Handle& other) 187 { 188 *this = other; 189 } 190 191 CompactVariableMap::Handle& CompactVariableMap::Handle::operator=(const Handle& other) 192 { 193 m_map = other.m_map; 194 m_environment = other.m_environment; 195 196 if (!m_map) { 197 ASSERT(!m_environment); 198 // This happens if `other` were moved into a different handle. 199 return *this; 200 } 201 202 auto iter = m_map->m_map.find(CompactVariableMapKey { *m_environment }); 203 RELEASE_ASSERT(iter != m_map->m_map.end()); 204 ++iter->value; 205 206 return *this; 207 } 208 186 209 } // namespace JSC -
trunk/Source/JavaScriptCore/parser/VariableEnvironment.h
r240255 r241571 205 205 public: 206 206 class Handle { 207 WTF_MAKE_NONCOPYABLE(Handle); // If we wanted to make this copyable, we'd need to do a hashtable lookup and bump the reference count of the map entry.208 207 public: 208 Handle() = default; 209 209 210 Handle(CompactVariableEnvironment& environment, CompactVariableMap& map) 210 211 : m_environment(&environment) … … 219 220 other.m_environment = nullptr; 220 221 } 222 223 Handle(const Handle&); 224 Handle& operator=(const Handle&); 225 221 226 ~Handle(); 227 228 explicit operator bool() const { return !!m_map; } 222 229 223 230 const CompactVariableEnvironment& environment() const … … 227 234 228 235 private: 229 CompactVariableEnvironment* m_environment ;236 CompactVariableEnvironment* m_environment { nullptr }; 230 237 RefPtr<CompactVariableMap> m_map; 231 238 }; -
trunk/Source/JavaScriptCore/runtime/CodeCache.cpp
r241552 r241571 148 148 VariableEnvironment emptyTDZVariables; 149 149 ConstructAbility constructAbility = constructAbilityForParseMode(metadata->parseMode()); 150 UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&vm, source, metadata, UnlinkedNormalFunction, constructAbility, JSParserScriptMode::Classic, emptyTDZVariables, DerivedContextType::None);150 UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&vm, source, metadata, UnlinkedNormalFunction, constructAbility, JSParserScriptMode::Classic, vm.m_compactVariableMap->get(emptyTDZVariables), DerivedContextType::None); 151 151 152 152 functionExecutable->setSourceURLDirective(source.provider()->sourceURL());
Note: See TracChangeset
for help on using the changeset viewer.