Changeset 246073 in webkit
- Timestamp:
- Jun 4, 2019, 11:27:59 AM (7 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 1 deleted
- 25 edited
- 2 copied
-
ChangeLog (modified) (1 diff)
-
JavaScriptCore.xcodeproj/project.pbxproj (modified) (10 diffs)
-
Sources.txt (modified) (1 diff)
-
bytecode/ObjectAllocationProfileInlines.h (modified) (1 diff)
-
bytecode/Watchpoint.h (modified) (1 diff)
-
dfg/DFGAbstractInterpreterInlines.h (modified) (1 diff)
-
dfg/DFGByteCodeParser.cpp (modified) (3 diffs)
-
dfg/DFGClobberize.h (modified) (2 diffs)
-
dfg/DFGClobbersExitState.cpp (modified) (2 diffs)
-
dfg/DFGDesiredWatchpoints.cpp (modified) (5 diffs)
-
dfg/DFGDesiredWatchpoints.h (modified) (5 diffs)
-
dfg/DFGObjectAllocationSinkingPhase.cpp (modified) (4 diffs)
-
dfg/DFGSpeculativeJIT.cpp (modified) (2 diffs)
-
ftl/FTLLowerDFGToB3.cpp (modified) (2 diffs)
-
heap/Heap.cpp (modified) (3 diffs)
-
runtime/FunctionExecutable.cpp (modified) (3 diffs)
-
runtime/FunctionExecutable.h (modified) (3 diffs)
-
runtime/FunctionExecutableInlines.h (copied) (copied from trunk/Source/JavaScriptCore/runtime/InferredValueInlines.h ) (2 diffs)
-
runtime/InferredValue.cpp (deleted)
-
runtime/InferredValue.h (modified) (3 diffs)
-
runtime/InferredValueInlines.h (modified) (2 diffs)
-
runtime/JSFunctionInlines.h (modified) (1 diff)
-
runtime/JSSymbolTableObject.h (modified) (1 diff)
-
runtime/SymbolTable.cpp (modified) (2 diffs)
-
runtime/SymbolTable.h (modified) (4 diffs)
-
runtime/SymbolTableInlines.h (copied) (copied from trunk/Source/JavaScriptCore/runtime/InferredValueInlines.h ) (2 diffs)
-
runtime/VM.cpp (modified) (4 diffs)
-
runtime/VM.h (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r246071 r246073 1 2019-06-04 Yusuke Suzuki <ysuzuki@apple.com> 2 3 [JSC] InferredValue should not be a JSCell 4 https://bugs.webkit.org/show_bug.cgi?id=198407 5 6 Reviewed by Filip Pizlo. 7 8 Allocating InferredValue as a JSCell is too costly in terms of memory. Gmail has 90000 FunctionExecutables. And each gets 9 InferredValue, which takes 32 bytes. So it takes 2.7 MB memory footprint. 10 11 In this patch, we introduce a new container InferredValue<>. Which is similar to WriteBarrier<> container, but it replaces 12 the existing InferredValue cells with one pointer size field. The implementation of InferredValue<> is similar to 13 InlineWatchpointSet. But we encode JSCell* too to the pointer data of InlineWatchpointSet. So sizeof(InferredValue<>) is one 14 pointer size while it keeps Watchpoint feature and JSCell holder feature. 15 16 InferredValue<> needs validation in GC finalize phase. So this patch also makes SymbolTable Iso-allocated. 17 18 * JavaScriptCore.xcodeproj/project.pbxproj: 19 * Sources.txt: 20 * bytecode/ObjectAllocationProfileInlines.h: 21 (JSC::ObjectAllocationProfileBase<Derived>::initializeProfile): 22 * bytecode/Watchpoint.h: 23 * dfg/DFGAbstractInterpreterInlines.h: 24 (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): 25 * dfg/DFGByteCodeParser.cpp: 26 (JSC::DFG::ByteCodeParser::get): 27 (JSC::DFG::ByteCodeParser::parseBlock): 28 * dfg/DFGClobberize.h: 29 (JSC::DFG::clobberize): 30 * dfg/DFGClobbersExitState.cpp: 31 (JSC::DFG::clobbersExitState): 32 * dfg/DFGDesiredWatchpoints.cpp: 33 (JSC::DFG::SymbolTableAdaptor::add): 34 (JSC::DFG::FunctionExecutableAdaptor::add): 35 (JSC::DFG::DesiredWatchpoints::addLazily): 36 (JSC::DFG::DesiredWatchpoints::reallyAdd): 37 (JSC::DFG::DesiredWatchpoints::areStillValid const): 38 (JSC::DFG::DesiredWatchpoints::dumpInContext const): 39 (JSC::DFG::InferredValueAdaptor::add): Deleted. 40 * dfg/DFGDesiredWatchpoints.h: 41 (JSC::DFG::SymbolTableAdaptor::hasBeenInvalidated): 42 (JSC::DFG::SymbolTableAdaptor::dumpInContext): 43 (JSC::DFG::FunctionExecutableAdaptor::hasBeenInvalidated): 44 (JSC::DFG::FunctionExecutableAdaptor::dumpInContext): 45 (JSC::DFG::DesiredWatchpoints::isWatched): 46 (JSC::DFG::InferredValueAdaptor::hasBeenInvalidated): Deleted. 47 (JSC::DFG::InferredValueAdaptor::dumpInContext): Deleted. 48 * dfg/DFGObjectAllocationSinkingPhase.cpp: 49 * dfg/DFGSpeculativeJIT.cpp: 50 (JSC::DFG::SpeculativeJIT::compileNewFunction): 51 (JSC::DFG::SpeculativeJIT::compileCreateActivation): 52 * ftl/FTLLowerDFGToB3.cpp: 53 (JSC::FTL::DFG::LowerDFGToB3::compileCreateActivation): 54 (JSC::FTL::DFG::LowerDFGToB3::compileNewFunction): 55 * heap/Heap.cpp: 56 (JSC::Heap::finalizeUnconditionalFinalizers): 57 * runtime/FunctionExecutable.cpp: 58 (JSC::FunctionExecutable::FunctionExecutable): 59 (JSC::FunctionExecutable::finishCreation): 60 (JSC::FunctionExecutable::visitChildren): 61 * runtime/FunctionExecutable.h: 62 * runtime/FunctionExecutableInlines.h: Copied from Source/JavaScriptCore/runtime/InferredValueInlines.h. 63 (JSC::FunctionExecutable::finalizeUnconditionally): 64 * runtime/InferredValue.cpp: Removed. 65 * runtime/InferredValue.h: 66 (JSC::InferredValue::inferredValue): 67 (JSC::InferredValue::InferredValue): 68 (JSC::InferredValue::~InferredValue): 69 (JSC::InferredValue::stateOnJSThread const): 70 (JSC::InferredValue::state const): 71 (JSC::InferredValue::hasBeenInvalidated const): 72 (JSC::InferredValue::isStillValid const): 73 (JSC::InferredValue::invalidate): 74 (JSC::InferredValue::isBeingWatched const): 75 (JSC::InferredValue::notifyWrite): 76 (JSC::InferredValue::isThin): 77 (JSC::InferredValue::isFat): 78 (JSC::InferredValue::decodeState): 79 (JSC::InferredValue::encodeState): 80 (JSC::InferredValue::isThin const): 81 (JSC::InferredValue::isFat const): 82 (JSC::InferredValue::fat): 83 (JSC::InferredValue::fat const): 84 (JSC::InferredValue::inflate): 85 (JSC::InferredValue<JSCellType>::InferredValueWatchpointSet::notifyWriteSlow): 86 (JSC::InferredValue<JSCellType>::notifyWriteSlow): 87 (JSC::InferredValue<JSCellType>::add): 88 (JSC::InferredValue<JSCellType>::inflateSlow): 89 (JSC::InferredValue<JSCellType>::freeFat): 90 * runtime/InferredValueInlines.h: 91 (JSC::InferredValue<JSCellType>::finalizeUnconditionally): 92 (JSC::InferredValue::finalizeUnconditionally): Deleted. 93 * runtime/JSFunctionInlines.h: 94 (JSC::JSFunction::createWithInvalidatedReallocationWatchpoint): 95 * runtime/JSSymbolTableObject.h: 96 (JSC::JSSymbolTableObject::setSymbolTable): 97 * runtime/SymbolTable.cpp: 98 (JSC::SymbolTable::finishCreation): 99 (JSC::SymbolTable::visitChildren): 100 * runtime/SymbolTable.h: 101 * runtime/SymbolTableInlines.h: Copied from Source/JavaScriptCore/runtime/InferredValueInlines.h. 102 (JSC::SymbolTable::finalizeUnconditionally): 103 * runtime/VM.cpp: 104 (JSC::VM::VM): 105 * runtime/VM.h: 106 1 107 2019-06-04 Tadeu Zagallo <tzagallo@apple.com> 2 108 -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r246060 r246073 1775 1775 E33F50851B8437A000413856 /* JSInternalPromiseDeferred.h in Headers */ = {isa = PBXBuildFile; fileRef = E33F50831B8437A000413856 /* JSInternalPromiseDeferred.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1776 1776 E33F50871B8449EF00413856 /* JSInternalPromiseConstructor.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = E33F50861B8449EF00413856 /* JSInternalPromiseConstructor.lut.h */; }; 1777 E3400EC122A1CC7B009DED54 /* FunctionExecutableInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = E3400EC022A1CC78009DED54 /* FunctionExecutableInlines.h */; }; 1777 1778 E34E657520668EAA00FB81AC /* ParseHash.h in Headers */ = {isa = PBXBuildFile; fileRef = E34E657320668E8D00FB81AC /* ParseHash.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1778 1779 E34EDBF71DB5FFC900DC87A5 /* FrameTracers.h in Headers */ = {isa = PBXBuildFile; fileRef = E34EDBF61DB5FFC100DC87A5 /* FrameTracers.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 1793 1794 E39006212208BFC4001019CF /* SubspaceAccess.h in Headers */ = {isa = PBXBuildFile; fileRef = E39006202208BFC3001019CF /* SubspaceAccess.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1794 1795 E393ADD81FE702D00022D681 /* WeakMapImplInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = E393ADD71FE702CC0022D681 /* WeakMapImplInlines.h */; }; 1796 E39BF39922A2288B00BD183E /* SymbolTableInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = E39BF39822A2288B00BD183E /* SymbolTableInlines.h */; }; 1795 1797 E39D45F51D39005600B3B377 /* InterpreterInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = E39D9D841D39000600667282 /* InterpreterInlines.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1796 1798 E39DA4A71B7E8B7C0084F33A /* JSModuleRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = E39DA4A51B7E8B7C0084F33A /* JSModuleRecord.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 3134 3136 0FF729A1166AD347000F5BA3 /* ProfilerOriginStack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ProfilerOriginStack.cpp; path = profiler/ProfilerOriginStack.cpp; sourceTree = "<group>"; }; 3135 3137 0FF729A2166AD347000F5BA3 /* ProfilerOriginStack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ProfilerOriginStack.h; path = profiler/ProfilerOriginStack.h; sourceTree = "<group>"; }; 3136 0FF8BDE81AD4CF7100DFE884 /* InferredValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InferredValue.cpp; sourceTree = "<group>"; };3137 3138 0FF8BDE91AD4CF7100DFE884 /* InferredValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InferredValue.h; sourceTree = "<group>"; }; 3138 3139 0FF922CF14F46B130041A24E /* JSCLLIntOffsetsExtractor */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = JSCLLIntOffsetsExtractor; sourceTree = BUILT_PRODUCTS_DIR; }; … … 4773 4774 E33F50861B8449EF00413856 /* JSInternalPromiseConstructor.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSInternalPromiseConstructor.lut.h; sourceTree = "<group>"; }; 4774 4775 E33F50881B844A1A00413856 /* InternalPromiseConstructor.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = InternalPromiseConstructor.js; sourceTree = "<group>"; }; 4776 E3400EC022A1CC78009DED54 /* FunctionExecutableInlines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FunctionExecutableInlines.h; sourceTree = "<group>"; }; 4775 4777 E34E657320668E8D00FB81AC /* ParseHash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParseHash.h; sourceTree = "<group>"; }; 4776 4778 E34E657420668E8E00FB81AC /* ParseHash.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParseHash.cpp; sourceTree = "<group>"; }; … … 4805 4807 E393ADD71FE702CC0022D681 /* WeakMapImplInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakMapImplInlines.h; sourceTree = "<group>"; }; 4806 4808 E3963CEC1B73F75000EB4CE5 /* NodesAnalyzeModule.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NodesAnalyzeModule.cpp; sourceTree = "<group>"; }; 4809 E39BF39822A2288B00BD183E /* SymbolTableInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SymbolTableInlines.h; sourceTree = "<group>"; }; 4807 4810 E39D9D841D39000600667282 /* InterpreterInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InterpreterInlines.h; sourceTree = "<group>"; }; 4808 4811 E39DA4A41B7E8B7C0084F33A /* JSModuleRecord.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSModuleRecord.cpp; sourceTree = "<group>"; }; … … 6873 6876 0FB4B52116B6278D003F696B /* FunctionExecutableDump.cpp */, 6874 6877 0FB4B52216B6278D003F696B /* FunctionExecutableDump.h */, 6878 E3400EC022A1CC78009DED54 /* FunctionExecutableInlines.h */, 6875 6879 52B310FC1974AE870080857C /* FunctionHasExecutedCache.cpp */, 6876 6880 52B310FA1974AE610080857C /* FunctionHasExecutedCache.h */, … … 6910 6914 14386A761DD6989C008652C4 /* IndirectEvalExecutable.cpp */, 6911 6915 14386A771DD6989C008652C4 /* IndirectEvalExecutable.h */, 6912 0FF8BDE81AD4CF7100DFE884 /* InferredValue.cpp */,6913 6916 0FF8BDE91AD4CF7100DFE884 /* InferredValue.h */, 6914 6917 0F4AE0421FE0D25400E20839 /* InferredValueInlines.h */, … … 7318 7321 0F919D2715856770004A4E7D /* SymbolTable.cpp */, 7319 7322 14A396A60CD2933100B5B4FF /* SymbolTable.h */, 7323 E39BF39822A2288B00BD183E /* SymbolTableInlines.h */, 7320 7324 E31179A92288385D00514B2C /* SymbolTableOrScopeDepth.h */, 7321 7325 BDB4B5E099CD4C1BB3C1CF05 /* TemplateObjectDescriptor.cpp */, … … 9185 9189 147341D81DC02F9900AA29BA /* FunctionExecutable.h in Headers */, 9186 9190 0FF0F1A016B72A1A005DF95B /* FunctionExecutableDump.h in Headers */, 9191 E3400EC122A1CC7B009DED54 /* FunctionExecutableInlines.h in Headers */, 9187 9192 52B310FB1974AE610080857C /* FunctionHasExecutedCache.h in Headers */, 9188 9193 FE4BFF2C1AD476E700088F87 /* FunctionOverrides.h in Headers */, … … 9881 9886 996B73281BDA08EF00331B84 /* SymbolPrototype.lut.h in Headers */, 9882 9887 BC18C46B0E16F5CD00B34460 /* SymbolTable.h in Headers */, 9888 E39BF39922A2288B00BD183E /* SymbolTableInlines.h in Headers */, 9883 9889 E31179AA2288386100514B2C /* SymbolTableOrScopeDepth.h in Headers */, 9884 9890 0FD79A2D1EBBBDBB00DA88D3 /* Synchronousness.h in Headers */, -
trunk/Source/JavaScriptCore/Sources.txt
r246060 r246073 785 785 runtime/IndexingType.cpp 786 786 runtime/IndirectEvalExecutable.cpp 787 runtime/InferredValue.cpp788 787 runtime/InitializeThreading.cpp 789 788 runtime/InspectorInstrumentationObject.cpp -
trunk/Source/JavaScriptCore/bytecode/ObjectAllocationProfileInlines.h
r245658 r246073 64 64 isPolyProto = true; 65 65 else 66 isPolyProto = executable->ensurePolyProtoWatchpoint().hasBeenInvalidated() && executable->singleton FunctionHasBeenInvalidated();66 isPolyProto = executable->ensurePolyProtoWatchpoint().hasBeenInvalidated() && executable->singleton().hasBeenInvalidated(); 67 67 } 68 68 -
trunk/Source/JavaScriptCore/bytecode/Watchpoint.h
r245214 r246073 162 162 }; 163 163 164 enum WatchpointState { 165 ClearWatchpoint, 166 IsWatched, 167 IsInvalidated 164 // Make sure that the state can be represented in 2 bits. 165 enum WatchpointState : uint8_t { 166 ClearWatchpoint = 0, 167 IsWatched = 1, 168 IsInvalidated = 2 168 169 }; 169 170 -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
r246041 r246073 2763 2763 case GetCallee: 2764 2764 if (FunctionExecutable* executable = jsDynamicCast<FunctionExecutable*>(m_vm, m_codeBlock->ownerExecutable())) { 2765 InferredValue* singleton = executable->singletonFunction(); 2766 if (JSValue value = singleton->inferredValue()) { 2767 m_graph.watchpoints().addLazily(singleton); 2768 JSFunction* function = jsCast<JSFunction*>(value); 2765 if (JSFunction* function = executable->singleton().inferredValue()) { 2766 m_graph.watchpoints().addLazily(executable); 2769 2767 setConstant(node, *m_graph.freeze(function)); 2770 2768 break; -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r246041 r246073 322 322 // case if the function is a singleton then we already know it. 323 323 if (FunctionExecutable* executable = jsDynamicCast<FunctionExecutable*>(*m_vm, m_codeBlock->ownerExecutable())) { 324 InferredValue* singleton = executable->singletonFunction(); 325 if (JSValue value = singleton->inferredValue()) { 326 m_graph.watchpoints().addLazily(singleton); 327 JSFunction* function = jsCast<JSFunction*>(value); 324 if (JSFunction* function = executable->singleton().inferredValue()) { 325 m_graph.watchpoints().addLazily(executable); 328 326 return weakJSConstant(function); 329 327 } … … 6277 6275 // We have various forms of constant folding here. This is necessary to avoid 6278 6276 // spurious recompiles in dead-but-foldable code. 6277 6279 6278 if (symbolTable) { 6280 InferredValue* singleton = symbolTable->singletonScope(); 6281 if (JSValue value = singleton->inferredValue()) { 6282 m_graph.watchpoints().addLazily(singleton); 6283 set(bytecode.m_dst, weakJSConstant(value)); 6279 if (JSScope* scope = symbolTable->singleton().inferredValue()) { 6280 m_graph.watchpoints().addLazily(symbolTable); 6281 set(bytecode.m_dst, weakJSConstant(scope)); 6284 6282 break; 6285 6283 } … … 6312 6310 auto bytecode = currentInstruction->as<OpResolveScopeForHoistingFuncDeclInEval>(); 6313 6311 unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[bytecode.m_property]; 6314 6315 6312 set(bytecode.m_dst, addToGraph(ResolveScopeForHoistingFuncDeclInEval, OpInfo(identifierNumber), get(bytecode.m_scope))); 6316 6313 -
trunk/Source/JavaScriptCore/dfg/DFGClobberize.h
r246041 r246073 515 515 case CreateActivation: { 516 516 SymbolTable* table = node->castOperand<SymbolTable*>(); 517 if (table->singleton Scope()->isStillValid())517 if (table->singleton().isStillValid()) 518 518 write(Watchpoint_fire); 519 519 read(HeapObjectCount); … … 1569 1569 case NewAsyncGeneratorFunction: 1570 1570 case NewAsyncFunction: 1571 if (node->castOperand<FunctionExecutable*>()->singleton Function()->isStillValid())1571 if (node->castOperand<FunctionExecutable*>()->singleton().isStillValid()) 1572 1572 write(Watchpoint_fire); 1573 1573 read(HeapObjectCount); -
trunk/Source/JavaScriptCore/dfg/DFGClobbersExitState.cpp
r239142 r246073 88 88 case CreateActivation: 89 89 // Like above, but with the activation allocation caveat. 90 return node->castOperand<SymbolTable*>()->singleton Scope()->isStillValid();90 return node->castOperand<SymbolTable*>()->singleton().isStillValid(); 91 91 92 92 case NewFunction: … … 95 95 case NewAsyncFunction: 96 96 // Like above, but with the JSFunction allocation caveat. 97 return node->castOperand<FunctionExecutable*>()->singleton Function()->isStillValid();97 return node->castOperand<FunctionExecutable*>()->singleton().isStillValid(); 98 98 99 99 default: -
trunk/Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.cpp
r243560 r246073 49 49 } 50 50 51 void InferredValueAdaptor::add(52 CodeBlock* codeBlock, InferredValue* inferredValue, CommonData& common)51 void SymbolTableAdaptor::add( 52 CodeBlock* codeBlock, SymbolTable* symbolTable, CommonData& common) 53 53 { 54 codeBlock->addConstant(inferredValue); // For common users, it doesn't really matter if it's weak or not. If references to it go away, we go away, too. 55 inferredValue->add(common.watchpoints.add(codeBlock)); 54 codeBlock->addConstant(symbolTable); // For common users, it doesn't really matter if it's weak or not. If references to it go away, we go away, too. 55 symbolTable->singleton().add(common.watchpoints.add(codeBlock)); 56 } 57 58 void FunctionExecutableAdaptor::add( 59 CodeBlock* codeBlock, FunctionExecutable* executable, CommonData& common) 60 { 61 codeBlock->addConstant(executable); // For common users, it doesn't really matter if it's weak or not. If references to it go away, we go away, too. 62 executable->singleton().add(common.watchpoints.add(codeBlock)); 56 63 } 57 64 … … 83 90 } 84 91 85 void DesiredWatchpoints::addLazily( InferredValue* inferredValue)92 void DesiredWatchpoints::addLazily(SymbolTable* symbolTable) 86 93 { 87 m_inferredValues.addLazily(inferredValue); 94 m_symbolTables.addLazily(symbolTable); 95 } 96 97 void DesiredWatchpoints::addLazily(FunctionExecutable* executable) 98 { 99 m_functionExecutables.addLazily(executable); 88 100 } 89 101 … … 110 122 m_sets.reallyAdd(codeBlock, commonData); 111 123 m_inlineSets.reallyAdd(codeBlock, commonData); 112 m_inferredValues.reallyAdd(codeBlock, commonData); 124 m_symbolTables.reallyAdd(codeBlock, commonData); 125 m_functionExecutables.reallyAdd(codeBlock, commonData); 113 126 m_bufferViews.reallyAdd(codeBlock, commonData); 114 127 m_adaptiveStructureSets.reallyAdd(codeBlock, commonData); … … 119 132 return m_sets.areStillValid() 120 133 && m_inlineSets.areStillValid() 121 && m_inferredValues.areStillValid() 134 && m_symbolTables.areStillValid() 135 && m_functionExecutables.areStillValid() 122 136 && m_bufferViews.areStillValid() 123 137 && m_adaptiveStructureSets.areStillValid(); … … 129 143 out.print(" Watchpoint sets: ", inContext(m_sets, context), "\n"); 130 144 out.print(" Inline watchpoint sets: ", inContext(m_inlineSets, context), "\n"); 131 out.print(" Inferred values: ", inContext(m_inferredValues, context), "\n"); 145 out.print(" SymbolTables: ", inContext(m_symbolTables, context), "\n"); 146 out.print(" FunctionExecutables: ", inContext(m_functionExecutables, context), "\n"); 132 147 out.print(" Buffer views: ", inContext(m_bufferViews, context), "\n"); 133 148 out.print(" Object property conditions: ", inContext(m_adaptiveStructureSets, context), "\n"); -
trunk/Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.h
r240023 r246073 29 29 30 30 #include "DFGCommonData.h" 31 #include " InferredValue.h"31 #include "FunctionExecutable.h" 32 32 #include "JSArrayBufferView.h" 33 33 #include "ObjectPropertyCondition.h" 34 #include "SymbolTable.h" 34 35 #include "Watchpoint.h" 35 36 #include <wtf/CommaPrinter.h> … … 56 57 }; 57 58 58 struct InferredValueAdaptor { 59 static void add(CodeBlock*, InferredValue*, CommonData&); 60 static bool hasBeenInvalidated(InferredValue* inferredValue) 61 { 62 return inferredValue->hasBeenInvalidated(); 63 } 64 static void dumpInContext(PrintStream& out, InferredValue* inferredValue, DumpContext*) 65 { 66 out.print(RawPointer(inferredValue)); 59 struct SymbolTableAdaptor { 60 static void add(CodeBlock*, SymbolTable*, CommonData&); 61 static bool hasBeenInvalidated(SymbolTable* symbolTable) 62 { 63 return symbolTable->singleton().hasBeenInvalidated(); 64 } 65 static void dumpInContext(PrintStream& out, SymbolTable* symbolTable, DumpContext*) 66 { 67 out.print(RawPointer(symbolTable)); 68 } 69 }; 70 71 struct FunctionExecutableAdaptor { 72 static void add(CodeBlock*, FunctionExecutable*, CommonData&); 73 static bool hasBeenInvalidated(FunctionExecutable* executable) 74 { 75 return executable->singleton().hasBeenInvalidated(); 76 } 77 static void dumpInContext(PrintStream& out, FunctionExecutable* executable, DumpContext*) 78 { 79 out.print(RawPointer(executable)); 67 80 } 68 81 }; … … 155 168 void addLazily(WatchpointSet*); 156 169 void addLazily(InlineWatchpointSet&); 157 void addLazily(InferredValue*); 170 void addLazily(SymbolTable*); 171 void addLazily(FunctionExecutable*); 158 172 void addLazily(JSArrayBufferView*); 159 173 … … 176 190 return m_inlineSets.isWatched(&set); 177 191 } 178 bool isWatched(InferredValue* inferredValue) 179 { 180 return m_inferredValues.isWatched(inferredValue); 192 bool isWatched(SymbolTable* symbolTable) 193 { 194 return m_symbolTables.isWatched(symbolTable); 195 } 196 bool isWatched(FunctionExecutable* executable) 197 { 198 return m_functionExecutables.isWatched(executable); 181 199 } 182 200 bool isWatched(JSArrayBufferView* view) … … 194 212 GenericDesiredWatchpoints<WatchpointSet*> m_sets; 195 213 GenericDesiredWatchpoints<InlineWatchpointSet*> m_inlineSets; 196 GenericDesiredWatchpoints<InferredValue*, InferredValueAdaptor> m_inferredValues; 214 GenericDesiredWatchpoints<SymbolTable*, SymbolTableAdaptor> m_symbolTables; 215 GenericDesiredWatchpoints<FunctionExecutable*, FunctionExecutableAdaptor> m_functionExecutables; 197 216 GenericDesiredWatchpoints<JSArrayBufferView*, ArrayBufferViewWatchpointAdaptor> m_bufferViews; 198 217 GenericDesiredWatchpoints<ObjectPropertyCondition, AdaptiveStructureWatchpointAdaptor> m_adaptiveStructureSets; -
trunk/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp
r243232 r246073 841 841 case NewAsyncGeneratorFunction: 842 842 case NewAsyncFunction: { 843 if (isStillValid(node->castOperand<FunctionExecutable*>() ->singletonFunction())) {843 if (isStillValid(node->castOperand<FunctionExecutable*>())) { 844 844 m_heap.escape(node->child1().node()); 845 845 break; … … 869 869 870 870 case CreateActivation: { 871 if (isStillValid(node->castOperand<SymbolTable*>() ->singletonScope())) {871 if (isStillValid(node->castOperand<SymbolTable*>())) { 872 872 m_heap.escape(node->child1().node()); 873 873 break; … … 2383 2383 // returns but breaks badly if this changes its mind for any particular InferredValue. This 2384 2384 // method protects us from that. 2385 bool isStillValid(InferredValue* value) 2386 { 2387 return m_validInferredValues.add(value, value->isStillValid()).iterator->value; 2388 } 2385 bool isStillValid(SymbolTable* value) 2386 { 2387 return m_validInferredValues.add(value, value->singleton().isStillValid()).iterator->value; 2388 } 2389 2390 bool isStillValid(FunctionExecutable* value) 2391 { 2392 return m_validInferredValues.add(value, value->singleton().isStillValid()).iterator->value; 2393 } 2394 2389 2395 2390 2396 SSACalculator m_pointerSSA; … … 2398 2404 CombinedLiveness m_combinedLiveness; 2399 2405 2400 HashMap< InferredValue*, bool> m_validInferredValues;2406 HashMap<JSCell*, bool> m_validInferredValues; 2401 2407 2402 2408 HashMap<Node*, Node*> m_materializationToEscapee; -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r246041 r246073 7194 7194 FunctionExecutable* executable = node->castOperand<FunctionExecutable*>(); 7195 7195 7196 if (executable->singleton Function()->isStillValid()) {7196 if (executable->singleton().isStillValid()) { 7197 7197 GPRFlushedCallResult result(this); 7198 7198 GPRReg resultGPR = result.gpr(); … … 7411 7411 ASSERT(initializationValue == jsUndefined() || initializationValue == jsTDZValue()); 7412 7412 7413 if (table->singleton Scope()->isStillValid()) {7413 if (table->singleton().isStillValid()) { 7414 7414 GPRFlushedCallResult result(this); 7415 7415 GPRReg resultGPR = result.gpr(); -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
r246071 r246073 5442 5442 JSValue initializationValue = m_node->initializationValueForActivation(); 5443 5443 ASSERT(initializationValue.isUndefined() || initializationValue == jsTDZValue()); 5444 if (table->singleton Scope()->isStillValid()) {5444 if (table->singleton().isStillValid()) { 5445 5445 LValue callResult = vmCall( 5446 5446 Int64, … … 5503 5503 5504 5504 FunctionExecutable* executable = m_node->castOperand<FunctionExecutable*>(); 5505 if (executable->singleton Function()->isStillValid()) {5505 if (executable->singleton().isStillValid()) { 5506 5506 LValue callResult = 5507 5507 isGeneratorFunction ? vmCall(Int64, m_out.operation(operationNewGeneratorFunction), m_callFrame, scope, weakPointer(executable)) : -
trunk/Source/JavaScriptCore/heap/Heap.cpp
r245808 r246073 32 32 #include "Exception.h" 33 33 #include "FullGCActivityCallback.h" 34 #include "FunctionExecutableInlines.h" 34 35 #include "GCActivityCallback.h" 35 36 #include "GCIncomingRefCountedSetInlines.h" … … 68 69 #include "SuperSampler.h" 69 70 #include "SweepingScope.h" 71 #include "SymbolTableInlines.h" 70 72 #include "SynchronousStopTheWorldMutatorScheduler.h" 71 73 #include "TypeProfiler.h" … … 597 599 { 598 600 vm()->builtinExecutables()->finalizeUnconditionally(); 599 if (vm()->m_inferredValueSpace)600 finalizeMarkedUnconditionalFinalizers<InferredValue>(vm()->m_inferredValueSpace->space);601 finalizeMarkedUnconditionalFinalizers<FunctionExecutable>(vm()->functionExecutableSpace.space); 602 finalizeMarkedUnconditionalFinalizers<SymbolTable>(vm()->symbolTableSpace); 601 603 vm()->forEachCodeBlockSpace( 602 604 [&] (auto& space) { -
trunk/Source/JavaScriptCore/runtime/FunctionExecutable.cpp
r245040 r246073 49 49 RELEASE_ASSERT(!source.isNull()); 50 50 ASSERT(source.length()); 51 if (VM::canUseJIT())52 new (&m_singletonFunction) WriteBarrier<InferredValue>();53 else54 m_singletonFunctionState = ClearWatchpoint;55 51 } 56 52 … … 59 55 Base::finishCreation(vm); 60 56 m_topLevelExecutable.set(vm, this, topLevelExecutable ? topLevelExecutable : this); 61 if (VM::canUseJIT())62 m_singletonFunction.set(vm, this, InferredValue::create(vm));63 57 } 64 58 … … 91 85 visitor.append(thisObject->m_codeBlockForConstruct); 92 86 visitor.append(thisObject->m_unlinkedExecutable); 93 if (VM::canUseJIT())94 visitor.append(thisObject->m_singletonFunction);95 87 if (RareData* rareData = thisObject->m_rareData.get()) { 96 88 visitor.append(rareData->m_cachedPolyProtoStructure); -
trunk/Source/JavaScriptCore/runtime/FunctionExecutable.h
r245288 r246073 249 249 DECLARE_INFO; 250 250 251 InferredValue* singletonFunction() 252 { 253 if (VM::canUseJIT()) 254 return m_singletonFunction.get(); 255 return nullptr; 256 } 257 258 void notifyCreation(VM& vm, JSValue value, const char* reason) 259 { 260 if (VM::canUseJIT()) { 261 singletonFunction()->notifyWrite(vm, value, reason); 262 return; 263 } 264 switch (m_singletonFunctionState) { 265 case ClearWatchpoint: 266 m_singletonFunctionState = IsWatched; 267 return; 268 case IsWatched: 269 m_singletonFunctionState = IsInvalidated; 270 return; 271 case IsInvalidated: 272 return; 273 } 274 } 275 276 bool singletonFunctionHasBeenInvalidated() 277 { 278 if (VM::canUseJIT()) 279 return singletonFunction()->hasBeenInvalidated(); 280 return m_singletonFunctionState == IsInvalidated; 251 InferredValue<JSFunction>& singleton() 252 { 253 return m_singleton; 254 } 255 256 void notifyCreation(VM& vm, JSFunction* function, const char* reason) 257 { 258 m_singleton.notifyWrite(vm, this, function, reason); 281 259 } 282 260 … … 305 283 306 284 TemplateObjectMap& ensureTemplateObjectMap(VM&); 285 286 void finalizeUnconditionally(VM&); 307 287 308 288 private: … … 343 323 WriteBarrier<ExecutableToCodeBlockEdge> m_codeBlockForCall; 344 324 WriteBarrier<ExecutableToCodeBlockEdge> m_codeBlockForConstruct; 345 union { 346 WriteBarrier<InferredValue> m_singletonFunction; 347 WatchpointState m_singletonFunctionState; 348 }; 325 InferredValue<JSFunction> m_singleton; 349 326 Box<InlineWatchpointSet> m_polyProtoWatchpoint; 350 327 }; -
trunk/Source/JavaScriptCore/runtime/FunctionExecutableInlines.h
r246072 r246073 1 1 /* 2 * Copyright (C) 201 7Apple Inc. All rights reserved.2 * Copyright (C) 2019 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 21 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 24 */ 25 25 26 26 #pragma once 27 27 28 #include "InferredValue.h" 28 #include "FunctionExecutable.h" 29 #include "InferredValueInlines.h" 29 30 30 31 namespace JSC { 31 32 32 void InferredValue::finalizeUnconditionally(VM& vm)33 inline void FunctionExecutable::finalizeUnconditionally(VM& vm) 33 34 { 34 JSValue value = m_value.get(); 35 36 if (value && value.isCell()) { 37 if (vm.heap.isMarked(value.asCell())) 38 return; 39 40 invalidate(vm, StringFireDetail("InferredValue clean-up during GC")); 41 } 42 43 VM::SpaceAndSet::setFor(*subspace()).remove(this); 35 m_singleton.finalizeUnconditionally(vm); 44 36 } 45 37 -
trunk/Source/JavaScriptCore/runtime/InferredValue.h
r240965 r246073 1 1 /* 2 * Copyright (C) 2015-201 7Apple Inc. All rights reserved.2 * Copyright (C) 2015-2019 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 26 26 #pragma once 27 27 28 #include "IsoSubspace.h"29 28 #include "JSCast.h" 30 29 #include "VM.h" 31 30 #include "Watchpoint.h" 32 31 #include "WriteBarrier.h" 32 #include <wtf/Nonmovable.h> 33 33 34 34 namespace JSC { 35 35 36 // Allocate one of these if you'd like to infer a constant value. Writes to the value should use 37 // notifyWrite(). So long as exactly one value had ever been written and invalidate() has never been 38 // called, and you register a watchpoint, you can rely on the inferredValue() being the one true 39 // value. 40 // 41 // Commonly used for inferring singletons - in that case each allocation does notifyWrite(). But you 42 // can use it for other things as well. 43 44 class InferredValue final : public JSCell { 36 template<typename JSCellType> 37 class InferredValue { 38 WTF_MAKE_NONCOPYABLE(InferredValue); 39 WTF_MAKE_NONMOVABLE(InferredValue); 45 40 public: 46 typedef JSCell Base;47 48 template<typename CellType, SubspaceAccess mode>49 static IsoSubspace* subspaceFor(VM& vm)50 {51 return vm.inferredValueSpace<mode>();52 }53 54 static InferredValue* create(VM&);55 56 static const bool needsDestruction = true;57 static void destroy(JSCell*);58 59 static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype);60 61 static void visitChildren(JSCell*, SlotVisitor&);62 63 DECLARE_INFO;64 65 41 // For the purpose of deciding whether or not to watch this variable, you only need 66 42 // to inspect inferredValue(). If this returns something other than the empty … … 74 50 // either notice that it's invalidated and not install the watchpoint, or 75 51 // you will have been notified that the watchpoint was fired. 76 JSValue inferredValue() { return m_value.get(); } 77 78 // Forwards some WatchpointSet methods. 79 WatchpointState state() const { return m_set.state(); } 80 bool isStillValid() const { return m_set.isStillValid(); } 81 bool hasBeenInvalidated() const { return m_set.hasBeenInvalidated(); } 82 void add(Watchpoint* watchpoint) { m_set.add(watchpoint); } 83 84 void notifyWrite(VM& vm, JSValue value, const FireDetail& detail) 85 { 86 if (LIKELY(m_set.stateOnJSThread() == IsInvalidated)) 87 return; 88 notifyWriteSlow(vm, value, detail); 89 } 90 91 void notifyWrite(VM& vm, JSValue value, const char* reason) 92 { 93 if (LIKELY(m_set.stateOnJSThread() == IsInvalidated)) 94 return; 95 notifyWriteSlow(vm, value, reason); 96 } 52 JSCellType* inferredValue() 53 { 54 uintptr_t data = m_data; 55 if (isFat(data)) 56 return fat(data)->inferredValue(); 57 return bitwise_cast<JSCellType*>(data & ValueMask); 58 } 59 60 explicit InferredValue() 61 : m_data(encodeState(ClearWatchpoint)) 62 { 63 ASSERT(inferredValue() == nullptr); 64 } 65 66 ~InferredValue() 67 { 68 if (isThin()) 69 return; 70 freeFat(); 71 } 72 73 // Fast way of getting the state, which only works from the main thread. 74 WatchpointState stateOnJSThread() const 75 { 76 uintptr_t data = m_data; 77 if (isFat(data)) 78 return fat(data)->stateOnJSThread(); 79 return decodeState(data); 80 } 81 82 // It is safe to call this from another thread. It may return a prior state, 83 // but that should be fine since you should only perform actions based on the 84 // state if you also add a watchpoint. 85 WatchpointState state() const 86 { 87 WTF::loadLoadFence(); 88 uintptr_t data = m_data; 89 WTF::loadLoadFence(); 90 if (isFat(data)) 91 return fat(data)->state(); 92 return decodeState(data); 93 } 94 95 // It is safe to call this from another thread. It may return false 96 // even if the set actually had been invalidated, but that ought to happen 97 // only in the case of races, and should be rare. 98 bool hasBeenInvalidated() const 99 { 100 return state() == IsInvalidated; 101 } 102 103 // Like hasBeenInvalidated(), may be called from another thread. 104 bool isStillValid() const 105 { 106 return !hasBeenInvalidated(); 107 } 108 109 void add(Watchpoint*); 97 110 98 111 void invalidate(VM& vm, const FireDetail& detail) 99 112 { 100 m_value.clear(); 101 m_set.invalidate(vm, detail); 102 } 103 104 static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal; 113 if (isFat()) 114 fat()->invalidate(vm, detail); 115 else 116 m_data = encodeState(IsInvalidated); 117 } 118 119 bool isBeingWatched() const 120 { 121 if (isFat()) 122 return fat()->isBeingWatched(); 123 return false; 124 } 125 126 void notifyWrite(VM& vm, JSCell* owner, JSCellType* value, const FireDetail& detail) 127 { 128 if (LIKELY(stateOnJSThread() == IsInvalidated)) 129 return; 130 notifyWriteSlow(vm, owner, value, detail); 131 } 132 133 void notifyWrite(VM& vm, JSCell* owner, JSCellType* value, const char* reason) 134 { 135 if (LIKELY(stateOnJSThread() == IsInvalidated)) 136 return; 137 notifyWriteSlow(vm, owner, value, reason); 138 } 105 139 106 140 void finalizeUnconditionally(VM&); 107 141 108 142 private: 109 InferredValue(VM&); 110 ~InferredValue(); 111 112 JS_EXPORT_PRIVATE void notifyWriteSlow(VM&, JSValue, const FireDetail&); 113 JS_EXPORT_PRIVATE void notifyWriteSlow(VM&, JSValue, const char* reason); 114 115 InlineWatchpointSet m_set; 116 WriteBarrier<Unknown> m_value; 143 class InferredValueWatchpointSet final : public WatchpointSet { 144 public: 145 InferredValueWatchpointSet(WatchpointState state, JSCellType* value) 146 : WatchpointSet(state) 147 , m_value(value) 148 { 149 } 150 151 JSCellType* inferredValue() const { return m_value; } 152 153 void invalidate(VM& vm, const FireDetail& detail) 154 { 155 m_value = nullptr; 156 WatchpointSet::invalidate(vm, detail); 157 } 158 159 void notifyWriteSlow(VM&, JSCell* owner, JSCellType*, const FireDetail&); 160 161 private: 162 JSCellType* m_value; 163 }; 164 165 static constexpr uintptr_t IsThinFlag = 1; 166 static constexpr uintptr_t StateMask = 6; 167 static constexpr uintptr_t StateShift = 1; 168 static constexpr uintptr_t ValueMask = ~static_cast<uintptr_t>(IsThinFlag | StateMask); 169 170 static bool isThin(uintptr_t data) { return data & IsThinFlag; } 171 static bool isFat(uintptr_t data) { return !isThin(data); } 172 173 static WatchpointState decodeState(uintptr_t data) 174 { 175 ASSERT(isThin(data)); 176 return static_cast<WatchpointState>((data & StateMask) >> StateShift); 177 } 178 179 static uintptr_t encodeState(WatchpointState state) 180 { 181 return (static_cast<uintptr_t>(state) << StateShift) | IsThinFlag; 182 } 183 184 bool isThin() const { return isThin(m_data); } 185 bool isFat() const { return isFat(m_data); }; 186 187 static InferredValueWatchpointSet* fat(uintptr_t data) 188 { 189 return bitwise_cast<InferredValueWatchpointSet*>(data); 190 } 191 192 InferredValueWatchpointSet* fat() 193 { 194 ASSERT(isFat()); 195 return fat(m_data); 196 } 197 198 const InferredValueWatchpointSet* fat() const 199 { 200 ASSERT(isFat()); 201 return fat(m_data); 202 } 203 204 InferredValueWatchpointSet* inflate() 205 { 206 if (LIKELY(isFat())) 207 return fat(); 208 return inflateSlow(); 209 } 210 211 InferredValueWatchpointSet* inflateSlow(); 212 void freeFat(); 213 214 void notifyWriteSlow(VM&, JSCell* owner, JSCellType*, const FireDetail&); 215 void notifyWriteSlow(VM&, JSCell* owner, JSCellType*, const char* reason); 216 217 uintptr_t m_data; 117 218 }; 118 219 119 // FIXME: We could have an InlineInferredValue, which only allocates the InferredValue object when 120 // a notifyWrite() transitions us towards watching, and then clears the reference (allowing the object 121 // to die) when we get invalidated. 220 template<typename JSCellType> 221 void InferredValue<JSCellType>::InferredValueWatchpointSet::notifyWriteSlow(VM& vm, JSCell* owner, JSCellType* value, const FireDetail& detail) 222 { 223 switch (state()) { 224 case ClearWatchpoint: 225 m_value = value; 226 vm.heap.writeBarrier(owner, value); 227 startWatching(); 228 return; 229 230 case IsWatched: 231 ASSERT(!!m_value); 232 if (m_value == value) 233 return; 234 invalidate(vm, detail); 235 return; 236 237 case IsInvalidated: 238 ASSERT_NOT_REACHED(); 239 return; 240 } 241 242 ASSERT_NOT_REACHED(); 243 } 244 245 template<typename JSCellType> 246 void InferredValue<JSCellType>::notifyWriteSlow(VM& vm, JSCell* owner, JSCellType* value, const FireDetail& detail) 247 { 248 uintptr_t data = m_data; 249 if (isFat(data)) { 250 fat(data)->notifyWriteSlow(vm, owner, value, detail); 251 return; 252 } 253 254 switch (state()) { 255 case ClearWatchpoint: 256 ASSERT(decodeState(m_data) != IsInvalidated); 257 m_data = (bitwise_cast<uintptr_t>(value) & ValueMask) | encodeState(IsWatched); 258 vm.heap.writeBarrier(owner, value); 259 return; 260 261 case IsWatched: 262 ASSERT(!!inferredValue()); 263 if (inferredValue() == value) 264 return; 265 invalidate(vm, detail); 266 return; 267 268 case IsInvalidated: 269 ASSERT_NOT_REACHED(); 270 return; 271 } 272 273 ASSERT_NOT_REACHED(); 274 } 275 276 template<typename JSCellType> 277 void InferredValue<JSCellType>::notifyWriteSlow(VM& vm, JSCell* owner, JSCellType* value, const char* reason) 278 { 279 notifyWriteSlow(vm, owner, value, StringFireDetail(reason)); 280 } 281 282 template<typename JSCellType> 283 void InferredValue<JSCellType>::add(Watchpoint* watchpoint) 284 { 285 inflate()->add(watchpoint); 286 } 287 288 template<typename JSCellType> 289 auto InferredValue<JSCellType>::inflateSlow() -> InferredValueWatchpointSet* 290 { 291 ASSERT(isThin()); 292 ASSERT(!isCompilationThread()); 293 uintptr_t data = m_data; 294 InferredValueWatchpointSet* fat = adoptRef(new InferredValueWatchpointSet(decodeState(m_data), bitwise_cast<JSCellType*>(data & ValueMask))).leakRef(); 295 WTF::storeStoreFence(); 296 m_data = bitwise_cast<uintptr_t>(fat); 297 return fat; 298 } 299 300 template<typename JSCellType> 301 void InferredValue<JSCellType>::freeFat() 302 { 303 ASSERT(isFat()); 304 fat()->deref(); 305 } 122 306 123 307 } // namespace JSC -
trunk/Source/JavaScriptCore/runtime/InferredValueInlines.h
r243467 r246073 21 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 24 */ 25 25 … … 30 30 namespace JSC { 31 31 32 void InferredValue::finalizeUnconditionally(VM& vm) 32 template<typename JSCellType> 33 void InferredValue<JSCellType>::finalizeUnconditionally(VM& vm) 33 34 { 34 JS Value value = m_value.get();35 36 if (value && value.isCell()) {37 if (vm.heap.isMarked(value .asCell()))35 JSCellType* value = inferredValue(); 36 37 if (value) { 38 if (vm.heap.isMarked(value)) 38 39 return; 39 40 40 41 invalidate(vm, StringFireDetail("InferredValue clean-up during GC")); 41 42 } 42 43 VM::SpaceAndSet::setFor(*subspace()).remove(this);44 43 } 45 44 46 45 } // namespace JSC 47 -
trunk/Source/JavaScriptCore/runtime/JSFunctionInlines.h
r240796 r246073 35 35 VM& vm, FunctionExecutable* executable, JSScope* scope) 36 36 { 37 ASSERT(executable->singleton FunctionHasBeenInvalidated());37 ASSERT(executable->singleton().hasBeenInvalidated()); 38 38 return createImpl(vm, executable, scope, selectStructureForNewFuncExp(scope->globalObject(vm), executable)); 39 39 } -
trunk/Source/JavaScriptCore/runtime/JSSymbolTableObject.h
r240796 r246073 67 67 { 68 68 ASSERT(!m_symbolTable); 69 if (auto* singletonScope = symbolTable->singletonScope()) 70 singletonScope->notifyWrite(vm, this, "Allocated a scope"); 69 symbolTable->notifyCreation(vm, this, "Allocated a scope"); 71 70 m_symbolTable.set(vm, this, symbolTable); 72 71 } -
trunk/Source/JavaScriptCore/runtime/SymbolTable.cpp
r241862 r246073 91 91 { 92 92 Base::finishCreation(vm); 93 if (VM::canUseJIT())94 m_singletonScope.set(vm, this, InferredValue::create(vm));95 93 } 96 94 … … 101 99 102 100 visitor.append(thisSymbolTable->m_arguments); 103 visitor.append(thisSymbolTable->m_singletonScope);104 101 105 102 if (thisSymbolTable->m_rareData) -
trunk/Source/JavaScriptCore/runtime/SymbolTable.h
r245064 r246073 346 346 347 347 SymbolTableEntry& copySlow(const SymbolTableEntry&); 348 JS_EXPORT_PRIVATE void notifyWriteSlow(VM&, JSValue, const FireDetail&);349 348 350 349 bool isFat() const … … 451 450 typedef Vector<SymbolTableEntry*> LocalToEntryVec; 452 451 452 template<typename CellType, SubspaceAccess> 453 static IsoSubspace* subspaceFor(VM& vm) 454 { 455 return &vm.symbolTableSpace; 456 } 457 453 458 static SymbolTable* create(VM& vm) 454 459 { … … 688 693 void setRareDataCodeBlock(CodeBlock*); 689 694 690 InferredValue* singletonScope() { return m_singletonScope.get(); } 695 InferredValue<JSScope>& singleton() { return m_singleton; } 696 697 void notifyCreation(VM& vm, JSScope* scope, const char* reason) 698 { 699 m_singleton.notifyWrite(vm, this, scope, reason); 700 } 691 701 692 702 static void visitChildren(JSCell*, SlotVisitor&); 693 703 694 704 DECLARE_EXPORT_INFO; 705 706 void finalizeUnconditionally(VM&); 695 707 696 708 private: … … 718 730 719 731 WriteBarrier<ScopedArgumentsTable> m_arguments; 720 WriteBarrier<InferredValue> m_singletonScope;732 InferredValue<JSScope> m_singleton; 721 733 722 734 std::unique_ptr<LocalToEntryVec> m_localToEntry; -
trunk/Source/JavaScriptCore/runtime/SymbolTableInlines.h
r246072 r246073 1 1 /* 2 * Copyright (C) 201 7Apple Inc. All rights reserved.2 * Copyright (C) 2019 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 21 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 24 */ 25 25 26 26 #pragma once 27 27 28 #include "InferredValue.h" 28 #include "InferredValueInlines.h" 29 #include "SymbolTable.h" 29 30 30 31 namespace JSC { 31 32 32 void InferredValue::finalizeUnconditionally(VM& vm)33 inline void SymbolTable::finalizeUnconditionally(VM& vm) 33 34 { 34 JSValue value = m_value.get(); 35 36 if (value && value.isCell()) { 37 if (vm.heap.isMarked(value.asCell())) 38 return; 39 40 invalidate(vm, StringFireDetail("InferredValue clean-up during GC")); 41 } 42 43 VM::SpaceAndSet::setFor(*subspace()).remove(this); 35 m_singleton.finalizeUnconditionally(vm); 44 36 } 45 37 -
trunk/Source/JavaScriptCore/runtime/VM.cpp
r245646 r246073 65 65 #include "IncrementalSweeper.h" 66 66 #include "IndirectEvalExecutable.h" 67 #include "InferredValue.h"68 67 #include "Interpreter.h" 69 68 #include "IntlCollatorConstructor.h" … … 287 286 , structureRareDataSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), StructureRareData) 288 287 , structureSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), Structure) 288 , symbolTableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), SymbolTable) 289 289 , executableToCodeBlockEdgesWithConstraints(executableToCodeBlockEdgeSpace) 290 290 , executableToCodeBlockEdgesWithFinalizers(executableToCodeBlockEdgeSpace) … … 379 379 unlinkedModuleProgramCodeBlockStructure.set(*this, UnlinkedModuleProgramCodeBlock::createStructure(*this, 0, jsNull())); 380 380 propertyTableStructure.set(*this, PropertyTable::createStructure(*this, 0, jsNull())); 381 if (VM::canUseJIT())382 inferredValueStructure.set(*this, InferredValue::createStructure(*this, 0, jsNull()));383 381 functionRareDataStructure.set(*this, FunctionRareData::createStructure(*this, 0, jsNull())); 384 382 exceptionStructure.set(*this, Exception::createStructure(*this, 0, jsNull())); … … 1278 1276 } 1279 1277 1280 DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER_SLOW(inferredValueSpace, destructibleCellHeapCellType.get(), InferredValue)1281 1278 DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER_SLOW(evalExecutableSpace, destructibleCellHeapCellType.get(), EvalExecutable) 1282 1279 DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER_SLOW(moduleProgramExecutableSpace, destructibleCellHeapCellType.get(), ModuleProgramExecutable) -
trunk/Source/JavaScriptCore/runtime/VM.h
r245765 r246073 381 381 IsoSubspace structureRareDataSpace; 382 382 IsoSubspace structureSpace; 383 IsoSubspace symbolTableSpace; 383 384 384 385 #define DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(name) \ … … 452 453 453 454 SpaceAndSet codeBlockSpace; 454 DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER(inferredValueSpace)455 455 456 456 template<typename Func> … … 528 528 Strong<Structure> unlinkedModuleProgramCodeBlockStructure; 529 529 Strong<Structure> propertyTableStructure; 530 Strong<Structure> inferredValueStructure;531 530 Strong<Structure> functionRareDataStructure; 532 531 Strong<Structure> exceptionStructure;
Note:
See TracChangeset
for help on using the changeset viewer.