Changeset 226667 in webkit
- Timestamp:
- Jan 9, 2018, 4:30:38 PM (8 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 66 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r226658 r226667 1 2018-01-04 Filip Pizlo <[email protected]> 2 3 CodeBlocks should be in IsoSubspaces 4 https://bugs.webkit.org/show_bug.cgi?id=180884 5 6 Reviewed by Saam Barati. 7 8 This moves CodeBlocks into IsoSubspaces. Doing so means that we no longer need to have the 9 special CodeBlockSet HashSets of new and old CodeBlocks. We also no longer use 10 WeakReferenceHarvester or UnconditionalFinalizer. Instead: 11 12 - Code block sweeping is now just eager sweeping. This means that it automatically takes 13 advantage of our unswept set, which roughly corresponds to what CodeBlockSet used to use 14 its eden set for. 15 16 - Those idea of Executable "weakly visiting" the CodeBlock is replaced by Executable 17 marking a ExecutableToCodeBlockEdge object. That object being marked corresponds to what 18 we used to call CodeBlock "having been weakly visited". This means that CodeBlockSet no 19 longer has to clear the set of weakly visited code blocks. This also means that 20 determining CodeBlock liveness, propagating CodeBlock transitions, and jettisoning 21 CodeBlocks during GC are now the edge's job. The edge is also in an IsoSubspace and it 22 has IsoCellSets to tell us which edges have output constraints (what we used to call 23 CodeBlock's weak reference harvester) and which have unconditional finalizers. 24 25 - CodeBlock now uses an IsoCellSet to tell if it has an unconditional finalizer. 26 27 - CodeBlockSet still exists! It has one unified HashSet of CodeBlocks that we use to 28 handle requests from the sampler, debugger, and other facilities. They may want to ask 29 if some pointer corresponds to a CodeBlock during stages of execution during which the 30 GC is unable to answer isLive() queries. The trickiest is the sampling profiler thread. 31 There is no way that the GC's isLive could tell us of a CodeBlock that had already been 32 allocated has now been full constructed. 33 34 * JavaScriptCore.xcodeproj/project.pbxproj: 35 * Sources.txt: 36 * bytecode/CodeBlock.cpp: 37 (JSC::CodeBlock::CodeBlock): 38 (JSC::CodeBlock::finishCreation): 39 (JSC::CodeBlock::finishCreationCommon): 40 (JSC::CodeBlock::~CodeBlock): 41 (JSC::CodeBlock::visitChildren): 42 (JSC::CodeBlock::propagateTransitions): 43 (JSC::CodeBlock::determineLiveness): 44 (JSC::CodeBlock::finalizeUnconditionally): 45 (JSC::CodeBlock::stronglyVisitStrongReferences): 46 (JSC::CodeBlock::hasInstalledVMTrapBreakpoints const): 47 (JSC::CodeBlock::installVMTrapBreakpoints): 48 (JSC::CodeBlock::dumpMathICStats): 49 (JSC::CodeBlock::visitWeakly): Deleted. 50 (JSC::CodeBlock::WeakReferenceHarvester::visitWeakReferences): Deleted. 51 (JSC::CodeBlock::UnconditionalFinalizer::finalizeUnconditionally): Deleted. 52 * bytecode/CodeBlock.h: 53 (JSC::CodeBlock::subspaceFor): 54 (JSC::CodeBlock::ownerEdge const): 55 (JSC::CodeBlock::clearVisitWeaklyHasBeenCalled): Deleted. 56 * bytecode/EvalCodeBlock.h: 57 (JSC::EvalCodeBlock::create): Deleted. 58 (JSC::EvalCodeBlock::createStructure): Deleted. 59 (JSC::EvalCodeBlock::variable): Deleted. 60 (JSC::EvalCodeBlock::numVariables): Deleted. 61 (JSC::EvalCodeBlock::functionHoistingCandidate): Deleted. 62 (JSC::EvalCodeBlock::numFunctionHoistingCandidates): Deleted. 63 (JSC::EvalCodeBlock::EvalCodeBlock): Deleted. 64 (JSC::EvalCodeBlock::unlinkedEvalCodeBlock const): Deleted. 65 * bytecode/ExecutableToCodeBlockEdge.cpp: Added. 66 (JSC::ExecutableToCodeBlockEdge::createStructure): 67 (JSC::ExecutableToCodeBlockEdge::create): 68 (JSC::ExecutableToCodeBlockEdge::visitChildren): 69 (JSC::ExecutableToCodeBlockEdge::visitOutputConstraints): 70 (JSC::ExecutableToCodeBlockEdge::finalizeUnconditionally): 71 (JSC::ExecutableToCodeBlockEdge::activate): 72 (JSC::ExecutableToCodeBlockEdge::deactivate): 73 (JSC::ExecutableToCodeBlockEdge::deactivateAndUnwrap): 74 (JSC::ExecutableToCodeBlockEdge::wrap): 75 (JSC::ExecutableToCodeBlockEdge::wrapAndActivate): 76 (JSC::ExecutableToCodeBlockEdge::ExecutableToCodeBlockEdge): 77 (JSC::ExecutableToCodeBlockEdge::runConstraint): 78 * bytecode/ExecutableToCodeBlockEdge.h: Added. 79 (JSC::ExecutableToCodeBlockEdge::subspaceFor): 80 (JSC::ExecutableToCodeBlockEdge::codeBlock const): 81 (JSC::ExecutableToCodeBlockEdge::unwrap): 82 * bytecode/FunctionCodeBlock.h: 83 (JSC::FunctionCodeBlock::subspaceFor): 84 (JSC::FunctionCodeBlock::createStructure): 85 * bytecode/ModuleProgramCodeBlock.h: 86 (JSC::ModuleProgramCodeBlock::create): Deleted. 87 (JSC::ModuleProgramCodeBlock::createStructure): Deleted. 88 (JSC::ModuleProgramCodeBlock::ModuleProgramCodeBlock): Deleted. 89 * bytecode/ProgramCodeBlock.h: 90 (JSC::ProgramCodeBlock::create): Deleted. 91 (JSC::ProgramCodeBlock::createStructure): Deleted. 92 (JSC::ProgramCodeBlock::ProgramCodeBlock): Deleted. 93 * debugger/Debugger.cpp: 94 (JSC::Debugger::SetSteppingModeFunctor::operator() const): 95 (JSC::Debugger::ToggleBreakpointFunctor::operator() const): 96 (JSC::Debugger::ClearCodeBlockDebuggerRequestsFunctor::operator() const): 97 (JSC::Debugger::ClearDebuggerRequestsFunctor::operator() const): 98 * heap/CodeBlockSet.cpp: 99 (JSC::CodeBlockSet::contains): 100 (JSC::CodeBlockSet::dump const): 101 (JSC::CodeBlockSet::add): 102 (JSC::CodeBlockSet::remove): 103 (JSC::CodeBlockSet::promoteYoungCodeBlocks): Deleted. 104 (JSC::CodeBlockSet::clearMarksForFullCollection): Deleted. 105 (JSC::CodeBlockSet::lastChanceToFinalize): Deleted. 106 (JSC::CodeBlockSet::deleteUnmarkedAndUnreferenced): Deleted. 107 * heap/CodeBlockSet.h: 108 * heap/CodeBlockSetInlines.h: 109 (JSC::CodeBlockSet::iterate): 110 (JSC::CodeBlockSet::iterateViaSubspaces): 111 * heap/ConservativeRoots.cpp: 112 (JSC::ConservativeRoots::genericAddPointer): 113 (JSC::DummyMarkHook::markKnownJSCell): 114 (JSC::CompositeMarkHook::mark): 115 (JSC::CompositeMarkHook::markKnownJSCell): 116 * heap/ConservativeRoots.h: 117 * heap/Heap.cpp: 118 (JSC::Heap::lastChanceToFinalize): 119 (JSC::Heap::finalizeMarkedUnconditionalFinalizers): 120 (JSC::Heap::finalizeUnconditionalFinalizers): 121 (JSC::Heap::beginMarking): 122 (JSC::Heap::deleteUnmarkedCompiledCode): 123 (JSC::Heap::sweepInFinalize): 124 (JSC::Heap::forEachCodeBlockImpl): 125 (JSC::Heap::forEachCodeBlockIgnoringJITPlansImpl): 126 (JSC::Heap::addCoreConstraints): 127 (JSC::Heap::finalizeUnconditionalFinalizersInIsoSubspace): Deleted. 128 * heap/Heap.h: 129 * heap/HeapCell.h: 130 * heap/HeapCellInlines.h: 131 (JSC::HeapCell::subspace const): 132 * heap/HeapInlines.h: 133 (JSC::Heap::forEachCodeBlock): 134 (JSC::Heap::forEachCodeBlockIgnoringJITPlans): 135 * heap/HeapUtil.h: 136 (JSC::HeapUtil::findGCObjectPointersForMarking): 137 * heap/IsoCellSet.cpp: 138 (JSC::IsoCellSet::parallelNotEmptyMarkedBlockSource): 139 * heap/IsoCellSet.h: 140 * heap/IsoCellSetInlines.h: 141 (JSC::IsoCellSet::forEachMarkedCellInParallel): 142 (JSC::IsoCellSet::forEachLiveCell): 143 * heap/LargeAllocation.h: 144 (JSC::LargeAllocation::subspace const): 145 * heap/MarkStackMergingConstraint.cpp: 146 (JSC::MarkStackMergingConstraint::executeImpl): 147 * heap/MarkStackMergingConstraint.h: 148 * heap/MarkedAllocator.cpp: 149 (JSC::MarkedAllocator::parallelNotEmptyBlockSource): 150 * heap/MarkedBlock.cpp: 151 (JSC::MarkedBlock::Handle::didAddToAllocator): 152 (JSC::MarkedBlock::Handle::didRemoveFromAllocator): 153 * heap/MarkedBlock.h: 154 (JSC::MarkedBlock::subspace const): 155 * heap/MarkedBlockInlines.h: 156 (JSC::MarkedBlock::Handle::forEachLiveCell): 157 * heap/MarkedSpaceInlines.h: 158 (JSC::MarkedSpace::forEachLiveCell): 159 * heap/MarkingConstraint.cpp: 160 (JSC::MarkingConstraint::execute): 161 (JSC::MarkingConstraint::doParallelWork): 162 (JSC::MarkingConstraint::finishParallelWork): Deleted. 163 (JSC::MarkingConstraint::doParallelWorkImpl): Deleted. 164 (JSC::MarkingConstraint::finishParallelWorkImpl): Deleted. 165 * heap/MarkingConstraint.h: 166 * heap/MarkingConstraintSet.cpp: 167 (JSC::MarkingConstraintSet::add): 168 * heap/MarkingConstraintSet.h: 169 (JSC::MarkingConstraintSet::add): 170 * heap/MarkingConstraintSolver.cpp: 171 (JSC::MarkingConstraintSolver::execute): 172 (JSC::MarkingConstraintSolver::addParallelTask): 173 (JSC::MarkingConstraintSolver::runExecutionThread): 174 (JSC::MarkingConstraintSolver::didExecute): Deleted. 175 * heap/MarkingConstraintSolver.h: 176 (JSC::MarkingConstraintSolver::TaskWithConstraint::TaskWithConstraint): 177 (JSC::MarkingConstraintSolver::TaskWithConstraint::operator== const): 178 * heap/SimpleMarkingConstraint.cpp: 179 (JSC::SimpleMarkingConstraint::SimpleMarkingConstraint): 180 (JSC::SimpleMarkingConstraint::executeImpl): 181 * heap/SimpleMarkingConstraint.h: 182 (JSC::SimpleMarkingConstraint::SimpleMarkingConstraint): 183 * heap/SlotVisitor.cpp: 184 (JSC::SlotVisitor::addParallelConstraintTask): 185 * heap/SlotVisitor.h: 186 * heap/Subspace.cpp: 187 (JSC::Subspace::sweep): 188 * heap/Subspace.h: 189 * heap/SubspaceInlines.h: 190 (JSC::Subspace::forEachLiveCell): 191 * llint/LowLevelInterpreter.asm: 192 * runtime/EvalExecutable.cpp: 193 (JSC::EvalExecutable::visitChildren): 194 * runtime/EvalExecutable.h: 195 (JSC::EvalExecutable::codeBlock): 196 * runtime/FunctionExecutable.cpp: 197 (JSC::FunctionExecutable::baselineCodeBlockFor): 198 (JSC::FunctionExecutable::visitChildren): 199 * runtime/FunctionExecutable.h: 200 * runtime/JSType.h: 201 * runtime/ModuleProgramExecutable.cpp: 202 (JSC::ModuleProgramExecutable::visitChildren): 203 * runtime/ModuleProgramExecutable.h: 204 * runtime/ProgramExecutable.cpp: 205 (JSC::ProgramExecutable::visitChildren): 206 * runtime/ProgramExecutable.h: 207 * runtime/ScriptExecutable.cpp: 208 (JSC::ScriptExecutable::installCode): 209 (JSC::ScriptExecutable::newReplacementCodeBlockFor): 210 * runtime/VM.cpp: 211 (JSC::VM::VM): 212 * runtime/VM.h: 213 (JSC::VM::SpaceAndFinalizerSet::SpaceAndFinalizerSet): 214 (JSC::VM::SpaceAndFinalizerSet::finalizerSetFor): 215 (JSC::VM::forEachCodeBlockSpace): 216 * runtime/VMTraps.cpp: 217 (JSC::VMTraps::handleTraps): 218 * tools/VMInspector.cpp: 219 (JSC::VMInspector::codeBlockForMachinePC): 220 (JSC::VMInspector::isValidCodeBlock): 221 1 222 2018-01-09 Michael Saboff <[email protected]> 2 223 -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r226407 r226667 344 344 0F5EF91F16878F7D003E5C25 /* JITThunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5EF91C16878F78003E5C25 /* JITThunks.h */; settings = {ATTRIBUTES = (Private, ); }; }; 345 345 0F5F08CF146C7633000472A9 /* UnconditionalFinalizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5F08CE146C762F000472A9 /* UnconditionalFinalizer.h */; settings = {ATTRIBUTES = (Private, ); }; }; 346 0F60FE901FFC37020003320A /* ExecutableToCodeBlockEdge.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F60FE8E1FFC36FD0003320A /* ExecutableToCodeBlockEdge.h */; settings = {ATTRIBUTES = (Private, ); }; }; 346 347 0F61832A1C45BF070072450B /* AirCCallingConvention.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6183211C45BF070072450B /* AirCCallingConvention.h */; }; 347 348 0F61832D1C45BF070072450B /* AirEmitShuffle.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6183241C45BF070072450B /* AirEmitShuffle.h */; }; … … 2339 2340 0F5EF91C16878F78003E5C25 /* JITThunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITThunks.h; sourceTree = "<group>"; }; 2340 2341 0F5F08CE146C762F000472A9 /* UnconditionalFinalizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnconditionalFinalizer.h; sourceTree = "<group>"; }; 2342 0F60FE8D1FFC36FC0003320A /* ExecutableToCodeBlockEdge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExecutableToCodeBlockEdge.cpp; sourceTree = "<group>"; }; 2343 0F60FE8E1FFC36FD0003320A /* ExecutableToCodeBlockEdge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExecutableToCodeBlockEdge.h; sourceTree = "<group>"; }; 2341 2344 0F6183201C45BF070072450B /* AirCCallingConvention.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirCCallingConvention.cpp; path = b3/air/AirCCallingConvention.cpp; sourceTree = "<group>"; }; 2342 2345 0F6183211C45BF070072450B /* AirCCallingConvention.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirCCallingConvention.h; path = b3/air/AirCCallingConvention.h; sourceTree = "<group>"; }; … … 7523 7526 14AD91061DCA92940014F9FE /* EvalCodeBlock.h */, 7524 7527 14142E521B796EDD00F4BF4B /* ExecutableInfo.h */, 7528 0F60FE8D1FFC36FC0003320A /* ExecutableToCodeBlockEdge.cpp */, 7529 0F60FE8E1FFC36FD0003320A /* ExecutableToCodeBlockEdge.h */, 7525 7530 0F56A1D415001CF2002992B1 /* ExecutionCounter.cpp */, 7526 7531 0F56A1D115000F31002992B1 /* ExecutionCounter.h */, … … 8319 8324 BC18C3F30E16F5CD00B34460 /* CommonIdentifiers.h in Headers */, 8320 8325 0F15F15F14B7A73E005DE37D /* CommonSlowPaths.h in Headers */, 8326 0F60FE901FFC37020003320A /* ExecutableToCodeBlockEdge.h in Headers */, 8321 8327 6553A33217A1F1EE008CF6F3 /* CommonSlowPathsExceptions.h in Headers */, 8322 8328 0FD82E39141AB14D00179C94 /* CompactJITCodeMap.h in Headers */, -
trunk/Source/JavaScriptCore/Sources.txt
r226407 r226667 211 211 bytecode/DirectEvalCodeCache.cpp 212 212 bytecode/EvalCodeBlock.cpp 213 bytecode/ExecutableToCodeBlockEdge.cpp 213 214 bytecode/ExecutionCounter.cpp 214 215 bytecode/ExitKind.cpp -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r226556 r226667 52 52 #include "InlineCallFrame.h" 53 53 #include "InterpreterInlines.h" 54 #include "IsoCellSetInlines.h" 54 55 #include "JIT.h" 55 56 #include "JITMathIC.h" … … 330 331 , m_reoptimizationRetryCounter(0) 331 332 , m_creationTime(MonotonicTime::now()) 332 , m_unconditionalFinalizer(makePoisonedUnique<UnconditionalFinalizer>(*this)) 333 , m_weakReferenceHarvester(makePoisonedUnique<WeakReferenceHarvester>(*this)) 334 { 335 m_visitWeaklyHasBeenCalled = false; 336 333 { 337 334 ASSERT(heap()->isDeferred()); 338 335 ASSERT(m_scopeRegister.isLocal()); 339 336 340 337 setNumParameters(other.numParameters()); 338 339 vm->heap.codeBlockSet().add(this); 341 340 } 342 341 … … 344 343 { 345 344 Base::finishCreation(vm); 345 finishCreationCommon(vm); 346 346 347 347 optimizeAfterWarmUp(); … … 355 355 m_rareData->m_stringSwitchJumpTables = other.m_rareData->m_stringSwitchJumpTables; 356 356 } 357 358 heap()->m_codeBlocks->add(this);359 357 } 360 358 … … 390 388 , m_reoptimizationRetryCounter(0) 391 389 , m_creationTime(MonotonicTime::now()) 392 , m_unconditionalFinalizer(makePoisonedUnique<UnconditionalFinalizer>(*this)) 393 , m_weakReferenceHarvester(makePoisonedUnique<WeakReferenceHarvester>(*this)) 394 { 395 m_visitWeaklyHasBeenCalled = false; 396 390 { 397 391 ASSERT(heap()->isDeferred()); 398 392 ASSERT(m_scopeRegister.isLocal()); … … 400 394 ASSERT(m_source); 401 395 setNumParameters(unlinkedCodeBlock->numParameters()); 396 397 vm->heap.codeBlockSet().add(this); 402 398 } 403 399 … … 414 410 { 415 411 Base::finishCreation(vm); 412 finishCreationCommon(vm); 416 413 417 414 auto throwScope = DECLARE_THROW_SCOPE(vm); … … 850 847 dumpBytecode(); 851 848 852 heap()->m_codeBlocks->add(this);853 849 heap()->reportExtraMemoryAllocated(m_instructions.size() * sizeof(Instruction)); 854 850 … … 856 852 } 857 853 854 void CodeBlock::finishCreationCommon(VM& vm) 855 { 856 m_ownerEdge.set(vm, this, ExecutableToCodeBlockEdge::create(vm, this)); 857 } 858 858 859 CodeBlock::~CodeBlock() 859 860 { 860 861 VM& vm = *m_poisonedVM; 862 863 vm.heap.codeBlockSet().remove(this); 864 861 865 if (UNLIKELY(vm.m_perBytecodeProfiler)) 862 866 vm.m_perBytecodeProfiler->notifyDestruction(this); 863 867 864 if ( unlinkedCodeBlock()->didOptimize() == MixedTriState)868 if (!vm.heap.isShuttingDown() && unlinkedCodeBlock()->didOptimize() == MixedTriState) 865 869 unlinkedCodeBlock()->setDidOptimize(FalseTriState); 866 870 … … 976 980 } 977 981 978 void CodeBlock::visitWeakly(SlotVisitor& visitor)979 {980 ConcurrentJSLocker locker(m_lock);981 if (m_visitWeaklyHasBeenCalled)982 return;983 984 m_visitWeaklyHasBeenCalled = true;985 986 if (Heap::isMarked(this))987 return;988 989 if (shouldVisitStrongly(locker)) {990 visitor.appendUnbarriered(this);991 return;992 }993 994 // There are two things that may use unconditional finalizers: inline cache clearing995 // and jettisoning. The probability of us wanting to do at least one of those things996 // is probably quite close to 1. So we add one no matter what and when it runs, it997 // figures out whether it has any work to do.998 visitor.addUnconditionalFinalizer(m_unconditionalFinalizer.get());999 1000 if (!JITCode::isOptimizingJIT(jitType()))1001 return;1002 1003 // If we jettison ourselves we'll install our alternative, so make sure that it1004 // survives GC even if we don't.1005 visitor.append(m_alternative);1006 1007 // There are two things that we use weak reference harvesters for: DFG fixpoint for1008 // jettisoning, and trying to find structures that would be live based on some1009 // inline cache. So it makes sense to register them regardless.1010 visitor.addWeakReferenceHarvester(m_weakReferenceHarvester.get());1011 1012 #if ENABLE(DFG_JIT)1013 // We get here if we're live in the sense that our owner executable is live,1014 // but we're not yet live for sure in another sense: we may yet decide that this1015 // code block should be jettisoned based on its outgoing weak references being1016 // stale. Set a flag to indicate that we're still assuming that we're dead, and1017 // perform one round of determining if we're live. The GC may determine, based on1018 // either us marking additional objects, or by other objects being marked for1019 // other reasons, that this iteration should run again; it will notify us of this1020 // decision by calling harvestWeakReferences().1021 1022 m_allTransitionsHaveBeenMarked = false;1023 propagateTransitions(locker, visitor);1024 1025 m_jitCode->dfgCommon()->livenessHasBeenProved = false;1026 determineLiveness(locker, visitor);1027 #endif // ENABLE(DFG_JIT)1028 }1029 1030 982 size_t CodeBlock::estimatedSize(JSCell* cell) 1031 983 { … … 1042 994 ASSERT_GC_OBJECT_INHERITS(thisObject, info()); 1043 995 JSCell::visitChildren(thisObject, visitor); 996 visitor.append(thisObject->m_ownerEdge); 1044 997 thisObject->visitChildren(visitor); 1045 998 } … … 1048 1001 { 1049 1002 ConcurrentJSLocker locker(m_lock); 1050 // There are two things that may use unconditional finalizers: inline cache clearing1051 // and jettisoning. The probability of us wanting to do at least one of those things1052 // is probably quite close to 1. So we add one no matter what and when it runs, it1053 // figures out whether it has any work to do.1054 visitor.addUnconditionalFinalizer(m_unconditionalFinalizer.get());1055 1056 1003 if (CodeBlock* otherBlock = specialOSREntryBlockOrNull()) 1057 1004 visitor.appendUnbarriered(otherBlock); … … 1072 1019 stronglyVisitStrongReferences(locker, visitor); 1073 1020 stronglyVisitWeakReferences(locker, visitor); 1074 1075 m_allTransitionsHaveBeenMarked = false; 1076 propagateTransitions(locker, visitor); 1021 1022 VM::SpaceAndFinalizerSet::finalizerSetFor(*subspace()).add(this); 1077 1023 } 1078 1024 … … 1165 1111 UNUSED_PARAM(visitor); 1166 1112 1167 if (m_allTransitionsHaveBeenMarked)1168 return;1169 1170 1113 VM& vm = *m_poisonedVM; 1171 bool allAreMarkedSoFar = true; 1172 1114 1173 1115 if (jitType() == JITCode::InterpreterThunk) { 1174 1116 const Vector<unsigned>& propertyAccessInstructions = m_unlinkedCode->propertyAccessInstructions(); … … 1187 1129 if (Heap::isMarked(oldStructure)) 1188 1130 visitor.appendUnbarriered(newStructure); 1189 else1190 allAreMarkedSoFar = false;1191 1131 break; 1192 1132 } … … 1200 1140 if (JITCode::isJIT(jitType())) { 1201 1141 for (auto iter = m_stubInfos.begin(); !!iter; ++iter) 1202 allAreMarkedSoFar &=(*iter)->propagateTransitions(visitor);1142 (*iter)->propagateTransitions(visitor); 1203 1143 } 1204 1144 #endif // ENABLE(JIT) … … 1208 1148 DFG::CommonData* dfgCommon = m_jitCode->dfgCommon(); 1209 1149 for (auto& weakReference : dfgCommon->weakStructureReferences) 1210 allAreMarkedSoFar &=weakReference->markIfCheap(visitor);1150 weakReference->markIfCheap(visitor); 1211 1151 1212 1152 for (auto& transition : dfgCommon->transitions) { … … 1232 1172 1233 1173 visitor.append(transition.m_to); 1234 } else 1235 allAreMarkedSoFar = false; 1174 } 1236 1175 } 1237 1176 } 1238 1177 #endif // ENABLE(DFG_JIT) 1239 1240 if (allAreMarkedSoFar)1241 m_allTransitionsHaveBeenMarked = true;1242 1178 } 1243 1179 … … 1247 1183 1248 1184 #if ENABLE(DFG_JIT) 1249 // Check if we have any remaining work to do. 1185 if (Heap::isMarked(this)) 1186 return; 1187 1188 // In rare and weird cases, this could be called on a baseline CodeBlock. One that I found was 1189 // that we might decide that the CodeBlock should be jettisoned due to old age, so the 1190 // isMarked check doesn't protect us. 1191 if (!JITCode::isOptimizingJIT(jitType())) 1192 return; 1193 1250 1194 DFG::CommonData* dfgCommon = m_jitCode->dfgCommon(); 1251 if (dfgCommon->livenessHasBeenProved)1252 return;1253 1254 1195 // Now check all of our weak references. If all of them are live, then we 1255 1196 // have proved liveness and so we scan our strong references. If at end of … … 1280 1221 // All weak references are live. Record this information so we don't 1281 1222 // come back here again, and scan the strong references. 1282 dfgCommon->livenessHasBeenProved = true;1283 1223 visitor.appendUnbarriered(this); 1284 1224 #endif // ENABLE(DFG_JIT) 1285 }1286 1287 void CodeBlock::WeakReferenceHarvester::visitWeakReferences(SlotVisitor& visitor)1288 {1289 codeBlock.propagateTransitions(NoLockingNecessary, visitor);1290 codeBlock.determineLiveness(NoLockingNecessary, visitor);1291 1225 } 1292 1226 … … 1422 1356 } 1423 1357 1424 void CodeBlock::UnconditionalFinalizer::finalizeUnconditionally() 1425 { 1426 codeBlock.updateAllPredictions(); 1427 1428 if (!Heap::isMarked(&codeBlock)) { 1429 if (codeBlock.shouldJettisonDueToWeakReference()) 1430 codeBlock.jettison(Profiler::JettisonDueToWeakReference); 1431 else 1432 codeBlock.jettison(Profiler::JettisonDueToOldAge); 1433 return; 1434 } 1435 1436 if (JITCode::couldBeInterpreted(codeBlock.jitType())) 1437 codeBlock.finalizeLLIntInlineCaches(); 1358 void CodeBlock::finalizeUnconditionally(VM&) 1359 { 1360 updateAllPredictions(); 1361 1362 if (JITCode::couldBeInterpreted(jitType())) 1363 finalizeLLIntInlineCaches(); 1438 1364 1439 1365 #if ENABLE(JIT) 1440 if (!!codeBlock.jitCode()) 1441 codeBlock.finalizeBaselineJITInlineCaches(); 1442 #endif 1366 if (!!jitCode()) 1367 finalizeBaselineJITInlineCaches(); 1368 #endif 1369 1370 VM::SpaceAndFinalizerSet::finalizerSetFor(*subspace()).remove(this); 1443 1371 } 1444 1372 … … 1594 1522 1595 1523 visitor.append(m_globalObject); 1596 visitor.append(m_ownerExecutable); 1524 visitor.append(m_ownerExecutable); // This is extra important since it causes the ExecutableToCodeBlockEdge to be marked. 1597 1525 visitor.append(m_unlinkedCode); 1598 1526 if (m_rareData) … … 3133 3061 { 3134 3062 #if ENABLE(SIGNAL_BASED_VM_TRAPS) 3135 3136 3063 // This function may be called from a signal handler. We need to be 3137 3064 // careful to not call anything that is not signal handler safe, e.g. … … 3153 3080 if (!JITCode::isOptimizingJIT(jitType())) 3154 3081 return false; 3155 m_jitCode->dfgCommon()->installVMTrapBreakpoints(this); 3082 auto& commonData = *m_jitCode->dfgCommon(); 3083 commonData.installVMTrapBreakpoints(this); 3156 3084 return true; 3157 3085 #else … … 3193 3121 totalSubSize += subIC->codeSize(); 3194 3122 } 3195 3196 return false;3197 3123 }; 3198 3124 heap()->forEachCodeBlock(countICs); -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.h
r226556 r226667 88 88 class CodeBlockSet; 89 89 class ExecState; 90 class ExecutableToCodeBlockEdge; 90 91 class JSModuleEnvironment; 91 92 class LLIntOffsetsExtractor; … … 108 109 friend class LLIntOffsetsExtractor; 109 110 110 struct UnconditionalFinalizer : public JSC::UnconditionalFinalizer {111 UnconditionalFinalizer(CodeBlock& codeBlock)112 : codeBlock(codeBlock)113 { }114 void finalizeUnconditionally() override;115 CodeBlock& codeBlock;116 };117 118 struct WeakReferenceHarvester : public JSC::WeakReferenceHarvester {119 WeakReferenceHarvester(CodeBlock& codeBlock)120 : codeBlock(codeBlock)121 { }122 void visitWeakReferences(SlotVisitor&) override;123 CodeBlock& codeBlock;124 };125 126 111 public: 127 112 … … 129 114 130 115 static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal; 116 static const bool needsDestruction = true; 117 118 template<typename> 119 static void subspaceFor(VM&) { } 131 120 132 121 DECLARE_INFO; … … 138 127 void finishCreation(VM&, CopyParsedBlockTag, CodeBlock& other); 139 128 bool finishCreation(VM&, ScriptExecutable* ownerExecutable, UnlinkedCodeBlock*, JSScope*); 129 130 void finishCreationCommon(VM&); 140 131 141 132 WriteBarrier<JSGlobalObject> m_globalObject; … … 201 192 static void visitChildren(JSCell*, SlotVisitor&); 202 193 void visitChildren(SlotVisitor&); 203 void visitWeakly(SlotVisitor&); 204 void clearVisitWeaklyHasBeenCalled(); 194 void finalizeUnconditionally(VM&); 205 195 206 196 void dumpSource(); … … 370 360 ExecutableBase* ownerExecutable() const { return m_ownerExecutable.get(); } 371 361 ScriptExecutable* ownerScriptExecutable() const { return jsCast<ScriptExecutable*>(m_ownerExecutable.get()); } 362 363 ExecutableToCodeBlockEdge* ownerEdge() const { return m_ownerEdge.get(); } 372 364 373 365 VM* vm() const { return m_poisonedVM.unpoisoned(); } … … 830 822 mutable ConcurrentJSLock m_lock; 831 823 832 bool m_visitWeaklyHasBeenCalled;833 834 824 bool m_shouldAlwaysBeInlined; // Not a bitfield because the JIT wants to store to it. 835 825 … … 919 909 private: 920 910 friend class CodeBlockSet; 911 friend class ExecutableToCodeBlockEdge; 921 912 922 913 BytecodeLivenessAnalysis& livenessAnalysisSlow(); … … 983 974 }; 984 975 WriteBarrier<ExecutableBase> m_ownerExecutable; 976 WriteBarrier<ExecutableToCodeBlockEdge> m_ownerEdge; 985 977 ConstExprPoisoned<CodeBlockPoison, VM*> m_poisonedVM; 986 978 … … 1047 1039 1048 1040 std::unique_ptr<RareData> m_rareData; 1049 1050 PoisonedUniquePtr<CodeBlockPoison, UnconditionalFinalizer> m_unconditionalFinalizer;1051 PoisonedUniquePtr<CodeBlockPoison, WeakReferenceHarvester> m_weakReferenceHarvester;1052 1041 }; 1053 1042 … … 1074 1063 { 1075 1064 return uncheckedR(reg.offset()); 1076 }1077 1078 inline void CodeBlock::clearVisitWeaklyHasBeenCalled()1079 {1080 m_visitWeaklyHasBeenCalled = false;1081 1065 } 1082 1066 -
trunk/Source/JavaScriptCore/bytecode/EvalCodeBlock.h
r215984 r226667 34 34 namespace JSC { 35 35 36 class EvalCodeBlock : public GlobalCodeBlock {36 class EvalCodeBlock final : public GlobalCodeBlock { 37 37 public: 38 38 typedef GlobalCodeBlock Base; 39 39 DECLARE_INFO; 40 41 template<typename> 42 static IsoSubspace* subspaceFor(VM& vm) 43 { 44 return &vm.evalCodeBlockSpace.space; 45 } 40 46 41 47 static EvalCodeBlock* create(VM* vm, CopyParsedBlockTag, EvalCodeBlock& other) … … 59 65 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) 60 66 { 61 return Structure::create(vm, globalObject, prototype, TypeInfo(C ellType, StructureFlags), info());67 return Structure::create(vm, globalObject, prototype, TypeInfo(CodeBlockType, StructureFlags), info()); 62 68 } 63 69 -
trunk/Source/JavaScriptCore/bytecode/FunctionCodeBlock.h
r213697 r226667 40 40 DECLARE_INFO; 41 41 42 template<typename> 43 static IsoSubspace* subspaceFor(VM& vm) 44 { 45 return &vm.functionCodeBlockSpace.space; 46 } 47 42 48 static FunctionCodeBlock* create(VM* vm, CopyParsedBlockTag, FunctionCodeBlock& other) 43 49 { … … 60 66 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) 61 67 { 62 return Structure::create(vm, globalObject, prototype, TypeInfo(C ellType, StructureFlags), info());68 return Structure::create(vm, globalObject, prototype, TypeInfo(CodeBlockType, StructureFlags), info()); 63 69 } 64 70 -
trunk/Source/JavaScriptCore/bytecode/ModuleProgramCodeBlock.h
r213697 r226667 35 35 namespace JSC { 36 36 37 class ModuleProgramCodeBlock : public GlobalCodeBlock {37 class ModuleProgramCodeBlock final : public GlobalCodeBlock { 38 38 public: 39 39 typedef GlobalCodeBlock Base; 40 40 DECLARE_INFO; 41 42 template<typename> 43 static IsoSubspace* subspaceFor(VM& vm) 44 { 45 return &vm.moduleProgramCodeBlockSpace.space; 46 } 41 47 42 48 static ModuleProgramCodeBlock* create(VM* vm, CopyParsedBlockTag, ModuleProgramCodeBlock& other) … … 60 66 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) 61 67 { 62 return Structure::create(vm, globalObject, prototype, TypeInfo(C ellType, StructureFlags), info());68 return Structure::create(vm, globalObject, prototype, TypeInfo(CodeBlockType, StructureFlags), info()); 63 69 } 64 70 -
trunk/Source/JavaScriptCore/bytecode/ProgramCodeBlock.h
r213697 r226667 35 35 namespace JSC { 36 36 37 class ProgramCodeBlock : public GlobalCodeBlock {37 class ProgramCodeBlock final : public GlobalCodeBlock { 38 38 public: 39 39 typedef GlobalCodeBlock Base; 40 40 DECLARE_INFO; 41 42 template<typename> 43 static IsoSubspace* subspaceFor(VM& vm) 44 { 45 return &vm.programCodeBlockSpace.space; 46 } 41 47 42 48 static ProgramCodeBlock* create(VM* vm, CopyParsedBlockTag, ProgramCodeBlock& other) … … 60 66 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) 61 67 { 62 return Structure::create(vm, globalObject, prototype, TypeInfo(C ellType, StructureFlags), info());68 return Structure::create(vm, globalObject, prototype, TypeInfo(CodeBlockType, StructureFlags), info()); 63 69 } 64 70 -
trunk/Source/JavaScriptCore/debugger/Debugger.cpp
r223738 r226667 208 208 } 209 209 210 booloperator()(CodeBlock* codeBlock) const210 void operator()(CodeBlock* codeBlock) const 211 211 { 212 212 if (m_debugger == codeBlock->globalObject()->debugger()) { … … 216 216 codeBlock->setSteppingMode(CodeBlock::SteppingModeDisabled); 217 217 } 218 return false;219 218 } 220 219 … … 316 315 } 317 316 318 booloperator()(CodeBlock* codeBlock) const317 void operator()(CodeBlock* codeBlock) const 319 318 { 320 319 if (m_debugger == codeBlock->globalObject()->debugger()) 321 320 m_debugger->toggleBreakpoint(codeBlock, m_breakpoint, m_enabledOrNot); 322 return false;323 321 } 324 322 … … 529 527 } 530 528 531 booloperator()(CodeBlock* codeBlock) const529 void operator()(CodeBlock* codeBlock) const 532 530 { 533 531 if (codeBlock->hasDebuggerRequests() && m_debugger == codeBlock->globalObject()->debugger()) 534 532 codeBlock->clearDebuggerRequests(); 535 return false;536 533 } 537 534 … … 559 556 } 560 557 561 booloperator()(CodeBlock* codeBlock) const558 void operator()(CodeBlock* codeBlock) const 562 559 { 563 560 if (codeBlock->hasDebuggerRequests() && m_globalObject == codeBlock->globalObject()) 564 561 codeBlock->clearDebuggerRequests(); 565 return false;566 562 } 567 563 -
trunk/Source/JavaScriptCore/heap/CodeBlockSet.cpp
r225315 r226667 42 42 } 43 43 44 void CodeBlockSet::add(CodeBlock* codeBlock)45 {46 LockHolder locker(&m_lock);47 bool isNewEntry = m_newCodeBlocks.add(codeBlock).isNewEntry;48 ASSERT_UNUSED(isNewEntry, isNewEntry);49 }50 51 void CodeBlockSet::promoteYoungCodeBlocks(const AbstractLocker&)52 {53 ASSERT(m_lock.isLocked());54 m_oldCodeBlocks.add(m_newCodeBlocks.begin(), m_newCodeBlocks.end());55 m_newCodeBlocks.clear();56 }57 58 void CodeBlockSet::clearMarksForFullCollection()59 {60 LockHolder locker(&m_lock);61 for (CodeBlock* codeBlock : m_oldCodeBlocks)62 codeBlock->clearVisitWeaklyHasBeenCalled();63 }64 65 void CodeBlockSet::lastChanceToFinalize(VM& vm)66 {67 LockHolder locker(&m_lock);68 for (CodeBlock* codeBlock : m_newCodeBlocks)69 codeBlock->structure(vm)->classInfo()->methodTable.destroy(codeBlock);70 71 for (CodeBlock* codeBlock : m_oldCodeBlocks)72 codeBlock->structure(vm)->classInfo()->methodTable.destroy(codeBlock);73 }74 75 void CodeBlockSet::deleteUnmarkedAndUnreferenced(VM& vm, CollectionScope scope)76 {77 LockHolder locker(&m_lock);78 79 // Destroying a CodeBlock takes about 1us on average in Speedometer. Full collections in Speedometer80 // usually have ~2000 CodeBlocks to process. The time it takes to process the whole list varies a81 // lot. In one extreme case I saw 18ms (on my fast MBP).82 //83 // FIXME: use Subspace instead of HashSet and adopt Subspace-based constraint solving. This may84 // remove the need to eagerly destruct CodeBlocks.85 // https://bugs.webkit.org/show_bug.cgi?id=18008986 //87 // FIXME: make CodeBlock::~CodeBlock a lot faster. It seems insane for that to take 1us or more.88 // https://bugs.webkit.org/show_bug.cgi?id=18010989 90 auto consider = [&] (HashSet<CodeBlock*>& set) {91 set.removeIf(92 [&] (CodeBlock* codeBlock) -> bool {93 if (Heap::isMarked(codeBlock))94 return false;95 codeBlock->structure(vm)->classInfo()->methodTable.destroy(codeBlock);96 return true;97 });98 };99 100 switch (scope) {101 case CollectionScope::Eden:102 consider(m_newCodeBlocks);103 break;104 case CollectionScope::Full:105 consider(m_oldCodeBlocks);106 consider(m_newCodeBlocks);107 break;108 }109 110 // Any remaining young CodeBlocks are live and need to be promoted to the set of old CodeBlocks.111 promoteYoungCodeBlocks(locker);112 }113 114 44 bool CodeBlockSet::contains(const AbstractLocker&, void* candidateCodeBlock) 115 45 { … … 118 48 if (!HashSet<CodeBlock*>::isValidValue(codeBlock)) 119 49 return false; 120 return m_ oldCodeBlocks.contains(codeBlock) || m_newCodeBlocks.contains(codeBlock) || m_currentlyExecuting.contains(codeBlock);50 return m_codeBlocks.contains(codeBlock); 121 51 } 122 52 … … 129 59 { 130 60 CommaPrinter comma; 131 out.print("{old = ["); 132 for (CodeBlock* codeBlock : m_oldCodeBlocks) 133 out.print(comma, pointerDump(codeBlock)); 134 out.print("], new = ["); 135 comma = CommaPrinter(); 136 for (CodeBlock* codeBlock : m_newCodeBlocks) 61 out.print("{codeBlocks = ["); 62 for (CodeBlock* codeBlock : m_codeBlocks) 137 63 out.print(comma, pointerDump(codeBlock)); 138 64 out.print("], currentlyExecuting = ["); … … 143 69 } 144 70 71 void CodeBlockSet::add(CodeBlock* codeBlock) 72 { 73 auto locker = holdLock(m_lock); 74 auto result = m_codeBlocks.add(codeBlock); 75 RELEASE_ASSERT(result); 76 } 77 78 void CodeBlockSet::remove(CodeBlock* codeBlock) 79 { 80 auto locker = holdLock(m_lock); 81 bool result = m_codeBlocks.remove(codeBlock); 82 RELEASE_ASSERT(result); 83 } 84 145 85 } // namespace JSC 146 86 -
trunk/Source/JavaScriptCore/heap/CodeBlockSet.h
r218794 r226667 50 50 ~CodeBlockSet(); 51 51 52 void lastChanceToFinalize(VM&);53 54 // Add a CodeBlock. This is only called by CodeBlock constructors.55 void add(CodeBlock*);56 57 // Clear all mark bits for all CodeBlocks.58 void clearMarksForFullCollection();59 60 // Mark a pointer that may be a CodeBlock that belongs to the set of DFG61 // blocks. This is defined in CodeBlock.h.62 private:63 52 void mark(const AbstractLocker&, CodeBlock* candidateCodeBlock); 64 public:65 void mark(const AbstractLocker&, void* candidateCodeBlock);66 67 // Delete all code blocks that are only referenced by this set (i.e. owned68 // by this set), and that have not been marked.69 void deleteUnmarkedAndUnreferenced(VM&, CollectionScope);70 53 71 54 void clearCurrentlyExecuting(); … … 79 62 template<typename Functor> void iterate(const Functor&); 80 63 template<typename Functor> void iterate(const AbstractLocker&, const Functor&); 64 65 template<typename Functor> void iterateViaSubspaces(VM&, const Functor&); 81 66 82 67 template<typename Functor> void iterateCurrentlyExecuting(const Functor&); 83 68 84 69 void dump(PrintStream&) const; 70 71 void add(CodeBlock*); 72 void remove(CodeBlock*); 85 73 86 74 private: 87 void promoteYoungCodeBlocks(const AbstractLocker&); 88 89 HashSet<CodeBlock*> m_oldCodeBlocks; 90 HashSet<CodeBlock*> m_newCodeBlocks; 75 HashSet<CodeBlock*> m_codeBlocks; 91 76 HashSet<CodeBlock*> m_currentlyExecuting; 92 77 Lock m_lock; -
trunk/Source/JavaScriptCore/heap/CodeBlockSetInlines.h
r213657 r226667 34 34 namespace JSC { 35 35 36 inline void CodeBlockSet::mark(const AbstractLocker& locker, void* candidateCodeBlock)37 {38 ASSERT(m_lock.isLocked());39 // We have to check for 0 and -1 because those are used by the HashMap as markers.40 uintptr_t value = reinterpret_cast<uintptr_t>(candidateCodeBlock);41 42 // This checks for both of those nasty cases in one go.43 // 0 + 1 = 144 // -1 + 1 = 045 if (value + 1 <= 1)46 return;47 48 CodeBlock* codeBlock = static_cast<CodeBlock*>(candidateCodeBlock);49 if (!m_oldCodeBlocks.contains(codeBlock) && !m_newCodeBlocks.contains(codeBlock))50 return;51 52 mark(locker, codeBlock);53 }54 55 36 inline void CodeBlockSet::mark(const AbstractLocker&, CodeBlock* codeBlock) 56 37 { … … 71 52 void CodeBlockSet::iterate(const AbstractLocker&, const Functor& functor) 72 53 { 73 for (auto& codeBlock : m_oldCodeBlocks) { 74 bool done = functor(codeBlock); 75 if (done) 76 return; 77 } 78 79 for (auto& codeBlock : m_newCodeBlocks) { 80 bool done = functor(codeBlock); 81 if (done) 82 return; 83 } 54 for (CodeBlock* codeBlock : m_codeBlocks) 55 functor(codeBlock); 56 } 57 58 template<typename Functor> 59 void CodeBlockSet::iterateViaSubspaces(VM& vm, const Functor& functor) 60 { 61 vm.forEachCodeBlockSpace( 62 [&] (IsoSubspace& space) { 63 space.forEachLiveCell( 64 [&] (HeapCell* cell, HeapCell::Kind) { 65 functor(jsCast<CodeBlock*>(static_cast<JSCell*>(cell))); 66 }); 67 }); 84 68 } 85 69 -
trunk/Source/JavaScriptCore/heap/ConservativeRoots.cpp
r225524 r226667 73 73 HeapUtil::findGCObjectPointersForMarking( 74 74 m_heap, markingVersion, newlyAllocatedVersion, filter, p, 75 [&] (void* p) { 75 [&] (void* p, HeapCell::Kind cellKind) { 76 if (cellKind == HeapCell::JSCell) 77 markHook.markKnownJSCell(static_cast<JSCell*>(p)); 78 76 79 if (m_size == m_capacity) 77 80 grow(); … … 104 107 public: 105 108 void mark(void*) { } 109 void markKnownJSCell(JSCell*) { } 106 110 }; 107 111 … … 110 114 DummyMarkHook dummy; 111 115 genericAddSpan(begin, end, dummy); 112 }113 114 void ConservativeRoots::add(void* begin, void* end, JITStubRoutineSet& jitStubRoutines)115 {116 genericAddSpan(begin, end, jitStubRoutines);117 116 } 118 117 … … 129 128 { 130 129 m_stubRoutines.mark(address); 131 m_codeBlocks.mark(m_codeBlocksLocker, address); 130 } 131 132 void markKnownJSCell(JSCell* cell) 133 { 134 if (cell->type() == CodeBlockType) 135 m_codeBlocks.mark(m_codeBlocksLocker, jsCast<CodeBlock*>(cell)); 132 136 } 133 137 -
trunk/Source/JavaScriptCore/heap/ConservativeRoots.h
r225524 r226667 40 40 41 41 void add(void* begin, void* end); 42 void add(void* begin, void* end, JITStubRoutineSet&);43 42 void add(void* begin, void* end, JITStubRoutineSet&, CodeBlockSet&); 44 43 -
trunk/Source/JavaScriptCore/heap/Heap.cpp
r226437 r226667 1 1 /* 2 * Copyright (C) 2003-201 7Apple Inc. All rights reserved.2 * Copyright (C) 2003-2018 Apple Inc. All rights reserved. 3 3 * Copyright (C) 2007 Eric Seidel <[email protected]> 4 4 * … … 368 368 } 369 369 370 m_isShuttingDown = true; 371 370 372 RELEASE_ASSERT(!m_vm->entryScope); 371 373 RELEASE_ASSERT(m_mutatorState == MutatorState::Running); … … 437 439 438 440 m_arrayBuffers.lastChanceToFinalize(); 439 m_codeBlocks->lastChanceToFinalize(*m_vm);440 441 m_objectSpace.stopAllocating(); 441 442 m_objectSpace.lastChanceToFinalize(); … … 559 560 560 561 template<typename CellType, typename CellSet> 561 void Heap::finalize UnconditionalFinalizers(CellSet& cellSet)562 void Heap::finalizeMarkedUnconditionalFinalizers(CellSet& cellSet) 562 563 { 563 564 cellSet.forEachMarkedCell( … … 567 568 } 568 569 569 template<typename CellType> 570 void Heap::finalizeUnconditionalFinalizersInIsoSubspace() 571 { 572 JSC::subspaceFor<CellType>(*vm())->forEachMarkedCell( 573 [&] (HeapCell* cell, HeapCell::Kind) { 574 static_cast<CellType*>(cell)->finalizeUnconditionally(*vm()); 570 void Heap::finalizeUnconditionalFinalizers() 571 { 572 finalizeMarkedUnconditionalFinalizers<InferredType>(vm()->inferredTypesWithFinalizers); 573 finalizeMarkedUnconditionalFinalizers<InferredValue>(vm()->inferredValuesWithFinalizers); 574 vm()->forEachCodeBlockSpace( 575 [&] (auto& space) { 576 this->finalizeMarkedUnconditionalFinalizers<CodeBlock>(space.finalizerSet); 575 577 }); 576 } 577 578 void Heap::finalizeUnconditionalFinalizers() 579 { 580 finalizeUnconditionalFinalizers<InferredType>(vm()->inferredTypesWithFinalizers); 581 finalizeUnconditionalFinalizers<InferredValue>(vm()->inferredValuesWithFinalizers); 582 finalizeUnconditionalFinalizersInIsoSubspace<JSWeakSet>(); 583 finalizeUnconditionalFinalizersInIsoSubspace<JSWeakMap>(); 578 finalizeMarkedUnconditionalFinalizers<ExecutableToCodeBlockEdge>(vm()->executableToCodeBlockEdgesWithFinalizers); 579 finalizeMarkedUnconditionalFinalizers<JSWeakSet>(vm()->weakSetSpace); 580 finalizeMarkedUnconditionalFinalizers<JSWeakMap>(vm()->weakMapSpace); 584 581 585 582 while (m_unconditionalFinalizers.hasNext()) { … … 678 675 { 679 676 TimingScope timingScope(*this, "Heap::beginMarking"); 680 if (m_collectionScope == CollectionScope::Full)681 m_codeBlocks->clearMarksForFullCollection();682 677 m_jitStubRoutines->clearMarks(); 683 678 m_objectSpace.beginMarking(); … … 940 935 { 941 936 clearUnmarkedExecutables(); 942 m_codeBlocks->deleteUnmarkedAndUnreferenced(*m_vm, *m_lastCollectionScope);943 937 m_jitStubRoutines->deleteUnmarkedJettisonedStubRoutines(); 944 938 } … … 2089 2083 { 2090 2084 m_objectSpace.sweepLargeAllocations(); 2091 2092 auto sweepBlock = [&] (MarkedBlock::Handle* handle) { 2093 handle->sweep(nullptr); 2094 }; 2095 2096 vm()->eagerlySweptDestructibleObjectSpace.forEachMarkedBlock(sweepBlock); 2085 vm()->forEachCodeBlockSpace([] (auto& space) { space.space.sweep(); }); 2086 vm()->eagerlySweptDestructibleObjectSpace.sweep(); 2097 2087 } 2098 2088 … … 2469 2459 } 2470 2460 2471 void Heap::forEachCodeBlockImpl(const ScopedLambda< bool(CodeBlock*)>& func)2461 void Heap::forEachCodeBlockImpl(const ScopedLambda<void(CodeBlock*)>& func) 2472 2462 { 2473 2463 // We don't know the full set of CodeBlocks until compilation has terminated. … … 2477 2467 } 2478 2468 2479 void Heap::forEachCodeBlockIgnoringJITPlansImpl(const AbstractLocker& locker, const ScopedLambda< bool(CodeBlock*)>& func)2469 void Heap::forEachCodeBlockIgnoringJITPlansImpl(const AbstractLocker& locker, const ScopedLambda<void(CodeBlock*)>& func) 2480 2470 { 2481 2471 return m_codeBlocks->iterate(locker, func); … … 2713 2703 }, 2714 2704 ConstraintVolatility::GreyedByMarking); 2705 2706 m_constraintSet->add( 2707 "O", "Output", 2708 [this] (SlotVisitor& slotVisitor) { 2709 VM& vm = slotVisitor.vm(); 2710 2711 auto callOutputConstraint = [] (SlotVisitor& slotVisitor, HeapCell* heapCell, HeapCell::Kind) { 2712 VM& vm = slotVisitor.vm(); 2713 JSCell* cell = static_cast<JSCell*>(heapCell); 2714 cell->methodTable(vm)->visitOutputConstraints(cell, slotVisitor); 2715 }; 2716 2717 auto add = [&] (auto& set) { 2718 slotVisitor.addParallelConstraintTask(set.forEachMarkedCellInParallel(callOutputConstraint)); 2719 }; 2720 2721 add(vm.executableToCodeBlockEdgesWithConstraints); 2722 }, 2723 ConstraintVolatility::GreyedByMarking, 2724 ConstraintParallelism::Parallel); 2715 2725 2716 2726 #if ENABLE(DFG_JIT) -
trunk/Source/JavaScriptCore/heap/Heap.h
r226437 r226667 168 168 void notifyIsSafeToCollect(); 169 169 bool isSafeToCollect() const { return m_isSafeToCollect; } 170 171 bool isShuttingDown() const { return m_isShuttingDown; } 170 172 171 173 JS_EXPORT_PRIVATE bool isHeapSnapshotting() const; … … 497 499 498 500 template<typename CellType, typename CellSet> 499 void finalizeUnconditionalFinalizers(CellSet&); 500 501 template<typename CellType> 502 void finalizeUnconditionalFinalizersInIsoSubspace(); 503 501 void finalizeMarkedUnconditionalFinalizers(CellSet&); 502 504 503 void finalizeUnconditionalFinalizers(); 505 504 … … 528 527 size_t bytesVisited(); 529 528 530 void forEachCodeBlockImpl(const ScopedLambda< bool(CodeBlock*)>&);531 void forEachCodeBlockIgnoringJITPlansImpl(const AbstractLocker& codeBlockSetLocker, const ScopedLambda< bool(CodeBlock*)>&);529 void forEachCodeBlockImpl(const ScopedLambda<void(CodeBlock*)>&); 530 void forEachCodeBlockIgnoringJITPlansImpl(const AbstractLocker& codeBlockSetLocker, const ScopedLambda<void(CodeBlock*)>&); 532 531 533 532 void setMutatorShouldBeFenced(bool value); … … 610 609 611 610 bool m_isSafeToCollect; 611 bool m_isShuttingDown { false }; 612 612 613 613 bool m_mutatorShouldBeFenced { Options::forceFencedBarrier() }; -
trunk/Source/JavaScriptCore/heap/HeapCell.h
r217429 r226667 34 34 class LargeAllocation; 35 35 class MarkedBlock; 36 class Subspace; 36 37 class VM; 37 38 struct AllocatorAttributes; … … 69 70 DestructionMode destructionMode() const; 70 71 Kind cellKind() const; 72 Subspace* subspace() const; 71 73 72 74 // Call use() after the last point where you need `this` pointer to be kept alive. You usually don't -
trunk/Source/JavaScriptCore/heap/HeapCellInlines.h
r220322 r226667 91 91 } 92 92 93 ALWAYS_INLINE Subspace* HeapCell::subspace() const 94 { 95 if (isLargeAllocation()) 96 return largeAllocation().subspace(); 97 return markedBlock().subspace(); 98 } 99 93 100 } // namespace JSC 94 101 -
trunk/Source/JavaScriptCore/heap/HeapInlines.h
r226437 r226667 145 145 template<typename Functor> inline void Heap::forEachCodeBlock(const Functor& func) 146 146 { 147 forEachCodeBlockImpl(scopedLambdaRef< bool(CodeBlock*)>(func));147 forEachCodeBlockImpl(scopedLambdaRef<void(CodeBlock*)>(func)); 148 148 } 149 149 150 150 template<typename Functor> inline void Heap::forEachCodeBlockIgnoringJITPlans(const AbstractLocker& codeBlockSetLocker, const Functor& func) 151 151 { 152 forEachCodeBlockIgnoringJITPlansImpl(codeBlockSetLocker, scopedLambdaRef< bool(CodeBlock*)>(func));152 forEachCodeBlockIgnoringJITPlansImpl(codeBlockSetLocker, scopedLambdaRef<void(CodeBlock*)>(func)); 153 153 } 154 154 -
trunk/Source/JavaScriptCore/heap/HeapUtil.h
r225524 r226667 67 67 [] (LargeAllocation** ptr) -> LargeAllocation* { return *ptr; }); 68 68 if (result) { 69 if (result > heap.objectSpace().largeAllocationsForThisCollectionBegin() 70 && result[-1]->contains(pointer)) 71 func(result[-1]->cell()); 72 if (result[0]->contains(pointer)) 73 func(result[0]->cell()); 74 if (result + 1 < heap.objectSpace().largeAllocationsForThisCollectionEnd() 75 && result[1]->contains(pointer)) 76 func(result[1]->cell()); 69 auto attemptLarge = [&] (LargeAllocation* allocation) { 70 if (allocation->contains(pointer)) 71 func(allocation->cell(), allocation->attributes().cellKind); 72 }; 73 74 if (result > heap.objectSpace().largeAllocationsForThisCollectionBegin()) 75 attemptLarge(result[-1]); 76 attemptLarge(result[0]); 77 if (result + 1 < heap.objectSpace().largeAllocationsForThisCollectionEnd()) 78 attemptLarge(result[1]); 77 79 } 78 80 } … … 90 92 previousPointer = static_cast<char*>(previousCandidate->handle().cellAlign(previousPointer)); 91 93 if (previousCandidate->handle().isLiveCell(markingVersion, newlyAllocatedVersion, isMarking, previousPointer)) 92 func(previousPointer );94 func(previousPointer, previousCandidate->handle().cellKind()); 93 95 } 94 96 } … … 101 103 if (!set.contains(candidate)) 102 104 return; 105 106 HeapCell::Kind cellKind = candidate->handle().cellKind(); 103 107 104 108 auto tryPointer = [&] (void* pointer) { 105 109 if (candidate->handle().isLiveCell(markingVersion, newlyAllocatedVersion, isMarking, pointer)) 106 func(pointer );110 func(pointer, cellKind); 107 111 }; 108 112 -
trunk/Source/JavaScriptCore/heap/IsoCellSet.cpp
r225831 r226667 45 45 if (isOnList()) 46 46 BasicRawSentinelNode<IsoCellSet>::remove(); 47 } 48 49 RefPtr<SharedTask<MarkedBlock::Handle*()>> IsoCellSet::parallelNotEmptyMarkedBlockSource() 50 { 51 class Task : public SharedTask<MarkedBlock::Handle*()> { 52 public: 53 Task(IsoCellSet& set) 54 : m_set(set) 55 , m_allocator(set.m_subspace.m_allocator) 56 { 57 } 58 59 MarkedBlock::Handle* run() override 60 { 61 if (m_done) 62 return nullptr; 63 auto locker = holdLock(m_lock); 64 auto bits = m_allocator.m_markingNotEmpty & m_set.m_blocksWithBits; 65 m_index = bits.findBit(m_index, true); 66 if (m_index >= m_allocator.m_blocks.size()) { 67 m_done = true; 68 return nullptr; 69 } 70 return m_allocator.m_blocks[m_index++]; 71 } 72 73 private: 74 IsoCellSet& m_set; 75 MarkedAllocator& m_allocator; 76 size_t m_index { 0 }; 77 Lock m_lock; 78 bool m_done { false }; 79 }; 80 81 return adoptRef(new Task(*this)); 47 82 } 48 83 -
trunk/Source/JavaScriptCore/heap/IsoCellSet.h
r225831 r226667 49 49 bool contains(HeapCell* cell) const; 50 50 51 JS_EXPORT_PRIVATE RefPtr<SharedTask<MarkedBlock::Handle*()>> parallelNotEmptyMarkedBlockSource(); 52 51 53 // This will have to do a combined search over whatever Subspace::forEachMarkedCell uses and 52 54 // our m_blocksWithBits. 53 55 template<typename Func> 54 56 void forEachMarkedCell(const Func&); 57 58 template<typename Func> 59 RefPtr<SharedTask<void(SlotVisitor&)>> forEachMarkedCellInParallel(const Func&); 60 61 template<typename Func> 62 void forEachLiveCell(const Func&); 55 63 56 64 private: -
trunk/Source/JavaScriptCore/heap/IsoCellSetInlines.h
r225831 r226667 79 79 } 80 80 81 template<typename Func> 82 RefPtr<SharedTask<void(SlotVisitor&)>> IsoCellSet::forEachMarkedCellInParallel(const Func& func) 83 { 84 class Task : public SharedTask<void(SlotVisitor&)> { 85 public: 86 Task(IsoCellSet& set, const Func& func) 87 : m_set(set) 88 , m_blockSource(set.parallelNotEmptyMarkedBlockSource()) 89 , m_func(func) 90 { 91 } 92 93 void run(SlotVisitor& visitor) override 94 { 95 while (MarkedBlock::Handle* handle = m_blockSource->run()) { 96 size_t blockIndex = handle->index(); 97 auto* bits = m_set.m_bits[blockIndex].get(); 98 handle->forEachMarkedCell( 99 [&] (size_t atomNumber, HeapCell* cell, HeapCell::Kind kind) -> IterationStatus { 100 if (bits->get(atomNumber)) 101 m_func(visitor, cell, kind); 102 return IterationStatus::Continue; 103 }); 104 } 105 } 106 107 private: 108 IsoCellSet& m_set; 109 RefPtr<SharedTask<MarkedBlock::Handle*()>> m_blockSource; 110 Func m_func; 111 Lock m_lock; 112 }; 113 114 return adoptRef(new Task(*this, func)); 115 } 116 117 template<typename Func> 118 void IsoCellSet::forEachLiveCell(const Func& func) 119 { 120 MarkedAllocator& allocator = m_subspace.m_allocator; 121 m_blocksWithBits.forEachSetBit( 122 [&] (size_t blockIndex) { 123 MarkedBlock::Handle* block = allocator.m_blocks[blockIndex]; 124 125 // FIXME: We could optimize this by checking our bits before querying isLive. 126 // OOPS! (need bug URL) 127 auto* bits = m_bits[blockIndex].get(); 128 block->forEachLiveCell( 129 [&] (size_t atomNumber, HeapCell* cell, HeapCell::Kind kind) -> IterationStatus { 130 if (bits->get(atomNumber)) 131 func(cell, kind); 132 return IterationStatus::Continue; 133 }); 134 }); 135 } 136 81 137 } // namespace JSC 82 138 -
trunk/Source/JavaScriptCore/heap/LargeAllocation.h
r225524 r226667 58 58 return bitwise_cast<uintptr_t>(cell) & halfAlignment; 59 59 } 60 61 Subspace* subspace() const { return m_subspace; } 60 62 61 63 void lastChanceToFinalize(); -
trunk/Source/JavaScriptCore/heap/MarkStackMergingConstraint.cpp
r225524 r226667 55 55 } 56 56 57 ConstraintParallelismMarkStackMergingConstraint::executeImpl(SlotVisitor& visitor)57 void MarkStackMergingConstraint::executeImpl(SlotVisitor& visitor) 58 58 { 59 59 m_heap.m_mutatorMarkStack->transferTo(visitor.mutatorMarkStack()); 60 60 m_heap.m_raceMarkStack->transferTo(visitor.mutatorMarkStack()); 61 return ConstraintParallelism::Sequential;62 61 } 63 62 -
trunk/Source/JavaScriptCore/heap/MarkStackMergingConstraint.h
r225524 r226667 39 39 protected: 40 40 void prepareToExecuteImpl(const AbstractLocker& constraintSolvingLocker, SlotVisitor&) override; 41 ConstraintParallelismexecuteImpl(SlotVisitor&) override;41 void executeImpl(SlotVisitor&) override; 42 42 43 43 private: -
trunk/Source/JavaScriptCore/heap/MarkedAllocator.cpp
r225831 r226667 459 459 MarkedBlock::Handle* run() override 460 460 { 461 if (m_done) 462 return nullptr; 461 463 auto locker = holdLock(m_lock); 462 464 m_index = m_allocator.m_markingNotEmpty.findBit(m_index, true); 463 if (m_index >= m_allocator.m_blocks.size()) 465 if (m_index >= m_allocator.m_blocks.size()) { 466 m_done = true; 464 467 return nullptr; 468 } 465 469 return m_allocator.m_blocks[m_index++]; 466 470 } … … 470 474 size_t m_index { 0 }; 471 475 Lock m_lock; 476 bool m_done { false }; 472 477 }; 473 478 -
trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp
r225831 r226667 330 330 m_index = index; 331 331 m_allocator = allocator; 332 m_block->m_subspace = allocator->subspace(); 332 333 333 334 size_t cellSize = allocator->cellSize(); … … 357 358 m_index = std::numeric_limits<size_t>::max(); 358 359 m_allocator = nullptr; 360 m_block->m_subspace = nullptr; 359 361 } 360 362 -
trunk/Source/JavaScriptCore/heap/MarkedBlock.h
r225831 r226667 301 301 302 302 CountingLock& lock() { return m_lock; } 303 304 Subspace* subspace() const { return m_subspace; } 303 305 304 306 private: … … 320 322 Handle& m_handle; 321 323 VM* m_vm; 324 Subspace* m_subspace; 322 325 323 326 CountingLock m_lock; -
trunk/Source/JavaScriptCore/heap/MarkedBlockInlines.h
r225831 r226667 484 484 // a race ought to mean that it just returns false when it should have returned true - but this is 485 485 // something that would have to be verified carefully. 486 // 487 // NOTE: Some users of forEachLiveCell require that their callback is called exactly once for 488 // each live cell. We could optimize this function for those users by using a slow loop if the 489 // block is in marks-mean-live mode. That would only affect blocks that had partial survivors 490 // during the last collection and no survivors (yet) during this collection. 491 // 486 492 // https://bugs.webkit.org/show_bug.cgi?id=180315 487 493 … … 492 498 continue; 493 499 494 if (functor( cell, kind) == IterationStatus::Done)500 if (functor(i, cell, kind) == IterationStatus::Done) 495 501 return IterationStatus::Done; 496 502 } -
trunk/Source/JavaScriptCore/heap/MarkedSpaceInlines.h
r213883 r226667 41 41 BlockIterator end = m_blocks.set().end(); 42 42 for (BlockIterator it = m_blocks.set().begin(); it != end; ++it) { 43 if ((*it)->handle().forEachLiveCell(functor) == IterationStatus::Done) 43 IterationStatus result = (*it)->handle().forEachLiveCell( 44 [&] (size_t, HeapCell* cell, HeapCell::Kind kind) -> IterationStatus { 45 return functor(cell, kind); 46 }); 47 if (result == IterationStatus::Done) 44 48 return; 45 49 } -
trunk/Source/JavaScriptCore/heap/MarkingConstraint.cpp
r225524 r226667 52 52 } 53 53 54 ConstraintParallelismMarkingConstraint::execute(SlotVisitor& visitor)54 void MarkingConstraint::execute(SlotVisitor& visitor) 55 55 { 56 56 VisitCounter visitCounter(visitor); 57 ConstraintParallelism result =executeImpl(visitor);57 executeImpl(visitor); 58 58 m_lastVisitCount += visitCounter.visitCount(); 59 59 if (verboseMarkingConstraint && visitCounter.visitCount()) 60 60 dataLog("(", abbreviatedName(), " visited ", visitCounter.visitCount(), " in execute)"); 61 if (result == ConstraintParallelism::Parallel) {62 // It's illegal to produce parallel work if you haven't advertised it upfront because the solver63 // has optimizations for constraints that promise to never produce parallel work.64 RELEASE_ASSERT(m_parallelism == ConstraintParallelism::Parallel);65 }66 return result;67 61 } 68 62 … … 88 82 } 89 83 90 void MarkingConstraint::doParallelWork(SlotVisitor& visitor )84 void MarkingConstraint::doParallelWork(SlotVisitor& visitor, SharedTask<void(SlotVisitor&)>& task) 91 85 { 92 86 VisitCounter visitCounter(visitor); 93 doParallelWorkImpl(visitor);87 task.run(visitor); 94 88 if (verboseMarkingConstraint && visitCounter.visitCount()) 95 89 dataLog("(", abbreviatedName(), " visited ", visitCounter.visitCount(), " in doParallelWork)"); … … 100 94 } 101 95 102 void MarkingConstraint::finishParallelWork(SlotVisitor& visitor)103 {104 VisitCounter visitCounter(visitor);105 finishParallelWorkImpl(visitor);106 m_lastVisitCount += visitCounter.visitCount();107 if (verboseMarkingConstraint && visitCounter.visitCount())108 dataLog("(", abbreviatedName(), " visited ", visitCounter.visitCount(), " in finishParallelWork)");109 }110 111 96 void MarkingConstraint::prepareToExecuteImpl(const AbstractLocker&, SlotVisitor&) 112 {113 }114 115 void MarkingConstraint::doParallelWorkImpl(SlotVisitor&)116 {117 UNREACHABLE_FOR_PLATFORM();118 }119 120 void MarkingConstraint::finishParallelWorkImpl(SlotVisitor&)121 97 { 122 98 } -
trunk/Source/JavaScriptCore/heap/MarkingConstraint.h
r225524 r226667 33 33 #include <wtf/Lock.h> 34 34 #include <wtf/Noncopyable.h> 35 #include <wtf/SharedTask.h> 35 36 #include <wtf/text/CString.h> 36 37 … … 60 61 size_t lastVisitCount() const { return m_lastVisitCount; } 61 62 62 ConstraintParallelismexecute(SlotVisitor&);63 void execute(SlotVisitor&); 63 64 64 65 JS_EXPORT_PRIVATE virtual double quickWorkEstimate(SlotVisitor& visitor); … … 68 69 void prepareToExecute(const AbstractLocker& constraintSolvingLocker, SlotVisitor&); 69 70 70 void doParallelWork(SlotVisitor&); 71 void finishParallelWork(SlotVisitor&); 71 void doParallelWork(SlotVisitor&, SharedTask<void(SlotVisitor&)>&); 72 72 73 73 ConstraintVolatility volatility() const { return m_volatility; } … … 77 77 78 78 protected: 79 virtual ConstraintParallelismexecuteImpl(SlotVisitor&) = 0;79 virtual void executeImpl(SlotVisitor&) = 0; 80 80 JS_EXPORT_PRIVATE virtual void prepareToExecuteImpl(const AbstractLocker& constraintSolvingLocker, SlotVisitor&); 81 virtual void doParallelWorkImpl(SlotVisitor&);82 virtual void finishParallelWorkImpl(SlotVisitor&);83 81 84 82 private: -
trunk/Source/JavaScriptCore/heap/MarkingConstraintSet.cpp
r225524 r226667 66 66 } 67 67 68 void MarkingConstraintSet::add(CString abbreviatedName, CString name, ::Function<void(SlotVisitor&)> function, ConstraintVolatility volatility, ConstraintConcurrency concurrency )68 void MarkingConstraintSet::add(CString abbreviatedName, CString name, ::Function<void(SlotVisitor&)> function, ConstraintVolatility volatility, ConstraintConcurrency concurrency, ConstraintParallelism parallelism) 69 69 { 70 add(std::make_unique<SimpleMarkingConstraint>(WTFMove(abbreviatedName), WTFMove(name), WTFMove(function), volatility, concurrency ));70 add(std::make_unique<SimpleMarkingConstraint>(WTFMove(abbreviatedName), WTFMove(name), WTFMove(function), volatility, concurrency, parallelism)); 71 71 } 72 72 -
trunk/Source/JavaScriptCore/heap/MarkingConstraintSet.h
r226010 r226667 47 47 ::Function<void(SlotVisitor&)>, 48 48 ConstraintVolatility, 49 ConstraintConcurrency = ConstraintConcurrency::Concurrent); 49 ConstraintConcurrency = ConstraintConcurrency::Concurrent, 50 ConstraintParallelism = ConstraintParallelism::Sequential); 51 52 void add( 53 CString abbreviatedName, CString name, 54 ::Function<void(SlotVisitor&)> func, 55 ConstraintVolatility volatility, 56 ConstraintParallelism parallelism) 57 { 58 add(abbreviatedName, name, WTFMove(func), volatility, ConstraintConcurrency::Concurrent, parallelism); 59 } 50 60 51 61 void add(std::unique_ptr<MarkingConstraint>); -
trunk/Source/JavaScriptCore/heap/MarkingConstraintSolver.cpp
r226437 r226667 79 79 RELEASE_ASSERT(!m_numThreadsThatMayProduceWork); 80 80 81 for (unsigned indexToRun : m_didExecuteInParallel)82 m_set.m_set[indexToRun]->finishParallelWork(m_mainVisitor);83 m_didExecuteInParallel.clear();84 85 81 if (!m_toExecuteSequentially.isEmpty()) { 86 82 for (unsigned indexToRun : m_toExecuteSequentially) … … 90 86 91 87 RELEASE_ASSERT(m_toExecuteInParallel.isEmpty()); 92 RELEASE_ASSERT(!m_toExecuteInParallelSet.bitCount());93 88 } 94 89 … … 157 152 158 153 constraint.prepareToExecute(NoLockingNecessary, m_mainVisitor); 159 ConstraintParallelism parallelism = constraint.execute(m_mainVisitor); 160 didExecute(parallelism, constraint.index()); 154 constraint.execute(m_mainVisitor); 155 m_executed.set(constraint.index()); 156 } 157 158 void MarkingConstraintSolver::addParallelTask(RefPtr<SharedTask<void(SlotVisitor&)>> task, MarkingConstraint& constraint) 159 { 160 auto locker = holdLock(m_lock); 161 m_toExecuteInParallel.append(TaskWithConstraint(WTFMove(task), &constraint)); 161 162 } 162 163 … … 165 166 for (;;) { 166 167 bool doParallelWorkMode; 167 unsigned indexToRun; 168 MarkingConstraint* constraint = nullptr; 169 unsigned indexToRun = UINT_MAX; 170 TaskWithConstraint task; 168 171 { 169 172 auto locker = holdLock(m_lock); … … 174 177 return false; 175 178 176 indexToRun = m_toExecuteInParallel.first(); 179 task = m_toExecuteInParallel.first(); 180 constraint = task.constraint; 177 181 doParallelWorkMode = true; 178 182 return true; 179 183 }; 180 184 181 185 auto tryNextConstraint = [&] () -> bool { 182 186 if (!m_pickNextIsStillActive) … … 193 197 continue; 194 198 195 MarkingConstraint& c onstraint = *m_set.m_set[*pickResult];196 if (c onstraint.concurrency() == ConstraintConcurrency::Sequential) {199 MarkingConstraint& candidateConstraint = *m_set.m_set[*pickResult]; 200 if (candidateConstraint.concurrency() == ConstraintConcurrency::Sequential) { 197 201 m_toExecuteSequentially.append(*pickResult); 198 202 continue; 199 203 } 200 if (c onstraint.parallelism() == ConstraintParallelism::Parallel)204 if (candidateConstraint.parallelism() == ConstraintParallelism::Parallel) 201 205 m_numThreadsThatMayProduceWork++; 202 206 indexToRun = *pickResult; 207 constraint = &candidateConstraint; 203 208 doParallelWorkMode = false; 204 constraint .prepareToExecute(locker, visitor);209 constraint->prepareToExecute(locker, visitor); 205 210 return true; 206 211 } … … 227 232 } 228 233 229 ConstraintParallelism parallelism = ConstraintParallelism::Sequential;230 231 MarkingConstraint& constraint = *m_set.m_set[indexToRun];232 233 234 if (doParallelWorkMode) 234 constraint.doParallelWork(visitor); 235 else 236 parallelism = constraint.execute(visitor); 237 235 constraint->doParallelWork(visitor, *task.task); 236 else { 237 if (constraint->parallelism() == ConstraintParallelism::Parallel) { 238 visitor.m_currentConstraint = constraint; 239 visitor.m_currentSolver = this; 240 } 241 242 constraint->execute(visitor); 243 244 visitor.m_currentConstraint = nullptr; 245 visitor.m_currentSolver = nullptr; 246 } 247 238 248 { 239 249 auto locker = holdLock(m_lock); 240 250 241 251 if (doParallelWorkMode) { 242 if (m_toExecuteInParallelSet.get(indexToRun)) { 243 m_didExecuteInParallel.append(indexToRun); 244 245 m_toExecuteInParallel.takeFirst( 246 [&] (unsigned value) { return value == indexToRun; }); 247 m_toExecuteInParallelSet.clear(indexToRun); 248 } 252 if (!m_toExecuteInParallel.isEmpty() 253 && task == m_toExecuteInParallel.first()) 254 m_toExecuteInParallel.takeFirst(); 255 else 256 ASSERT(!m_toExecuteInParallel.contains(task)); 249 257 } else { 250 if (constraint .parallelism() == ConstraintParallelism::Parallel)258 if (constraint->parallelism() == ConstraintParallelism::Parallel) 251 259 m_numThreadsThatMayProduceWork--; 252 260 m_executed.set(indexToRun); 253 if (parallelism == ConstraintParallelism::Parallel) {254 m_toExecuteInParallel.append(indexToRun);255 m_toExecuteInParallelSet.set(indexToRun);256 }257 261 } 258 262 … … 262 266 } 263 267 264 void MarkingConstraintSolver::didExecute(ConstraintParallelism parallelism, unsigned index)265 {266 m_executed.set(index);267 if (parallelism == ConstraintParallelism::Parallel) {268 m_toExecuteInParallel.append(index);269 m_toExecuteInParallelSet.set(index);270 }271 }272 273 268 } // namespace JSC 274 269 -
trunk/Source/JavaScriptCore/heap/MarkingConstraintSolver.h
r225524 r226667 65 65 void execute(MarkingConstraint&); 66 66 67 // Parallel constraints can add parallel tasks. 68 void addParallelTask(RefPtr<SharedTask<void(SlotVisitor&)>>, MarkingConstraint&); 69 67 70 private: 68 71 void runExecutionThread(SlotVisitor&, SchedulerPreference, ScopedLambda<std::optional<unsigned>()> pickNext); 69 72 70 void didExecute(ConstraintParallelism, unsigned index); 71 73 struct TaskWithConstraint { 74 TaskWithConstraint() { } 75 76 TaskWithConstraint(RefPtr<SharedTask<void(SlotVisitor&)>> task, MarkingConstraint* constraint) 77 : task(WTFMove(task)) 78 , constraint(constraint) 79 { 80 } 81 82 bool operator==(const TaskWithConstraint& other) const 83 { 84 return task == other.task 85 && constraint == other.constraint; 86 } 87 88 RefPtr<SharedTask<void(SlotVisitor&)>> task; 89 MarkingConstraint* constraint { nullptr }; 90 }; 91 72 92 Heap& m_heap; 73 93 SlotVisitor& m_mainVisitor; 74 94 MarkingConstraintSet& m_set; 75 95 BitVector m_executed; 76 Deque<unsigned, 32> m_toExecuteInParallel; 77 BitVector m_toExecuteInParallelSet; 78 Vector<unsigned, 32> m_didExecuteInParallel; 96 Deque<TaskWithConstraint, 32> m_toExecuteInParallel; 79 97 Vector<unsigned, 32> m_toExecuteSequentially; 80 98 Lock m_lock; -
trunk/Source/JavaScriptCore/heap/SimpleMarkingConstraint.cpp
r225524 r226667 32 32 CString abbreviatedName, CString name, 33 33 ::Function<void(SlotVisitor&)> executeFunction, 34 ConstraintVolatility volatility, ConstraintConcurrency concurrency) 35 : MarkingConstraint(WTFMove(abbreviatedName), WTFMove(name), volatility, concurrency, ConstraintParallelism::Sequential) 34 ConstraintVolatility volatility, ConstraintConcurrency concurrency, 35 ConstraintParallelism parallelism) 36 : MarkingConstraint(WTFMove(abbreviatedName), WTFMove(name), volatility, concurrency, parallelism) 36 37 , m_executeFunction(WTFMove(executeFunction)) 37 38 { … … 42 43 } 43 44 44 ConstraintParallelismSimpleMarkingConstraint::executeImpl(SlotVisitor& visitor)45 void SimpleMarkingConstraint::executeImpl(SlotVisitor& visitor) 45 46 { 46 47 m_executeFunction(visitor); 47 return ConstraintParallelism::Sequential;48 48 } 49 49 -
trunk/Source/JavaScriptCore/heap/SimpleMarkingConstraint.h
r225524 r226667 32 32 33 33 // This allows for an informal way to define constraints. Just pass a lambda to the constructor. The only 34 // downside is that this makes it hard for constraints to be stateful, which is necessary for them to be35 // parallel. In those cases, it's easier tojust subclass MarkingConstraint.34 // downside is that this makes it hard for constraints to override any functions in MarkingConstraint 35 // other than executeImpl. In those cases, just subclass MarkingConstraint. 36 36 class SimpleMarkingConstraint : public MarkingConstraint { 37 37 public: … … 40 40 ::Function<void(SlotVisitor&)>, 41 41 ConstraintVolatility, 42 ConstraintConcurrency = ConstraintConcurrency::Concurrent); 42 ConstraintConcurrency = ConstraintConcurrency::Concurrent, 43 ConstraintParallelism = ConstraintParallelism::Sequential); 44 45 SimpleMarkingConstraint( 46 CString abbreviatedName, CString name, 47 ::Function<void(SlotVisitor&)> func, 48 ConstraintVolatility volatility, 49 ConstraintParallelism parallelism) 50 : SimpleMarkingConstraint(abbreviatedName, name, WTFMove(func), volatility, ConstraintConcurrency::Concurrent, parallelism) 51 { 52 } 43 53 44 54 JS_EXPORT_PRIVATE ~SimpleMarkingConstraint(); 45 55 46 56 private: 47 ConstraintParallelismexecuteImpl(SlotVisitor&) override;57 void executeImpl(SlotVisitor&) override; 48 58 49 59 ::Function<void(SlotVisitor&)> m_executeFunction; -
trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp
r225524 r226667 787 787 } 788 788 789 void SlotVisitor::addParallelConstraintTask(RefPtr<SharedTask<void(SlotVisitor&)>> task) 790 { 791 RELEASE_ASSERT(m_currentSolver); 792 RELEASE_ASSERT(m_currentConstraint); 793 RELEASE_ASSERT(task); 794 795 m_currentSolver->addParallelTask(task, *m_currentConstraint); 796 } 797 789 798 } // namespace JSC -
trunk/Source/JavaScriptCore/heap/SlotVisitor.h
r225524 r226667 41 41 class HeapSnapshotBuilder; 42 42 class MarkedBlock; 43 class MarkingConstraintSolver; 43 44 class UnconditionalFinalizer; 44 45 template<typename T> class Weak; … … 171 172 172 173 const char* codeName() const { return m_codeName.data(); } 174 175 JS_EXPORT_PRIVATE void addParallelConstraintTask(RefPtr<SharedTask<void(SlotVisitor&)>>); 173 176 174 177 private: 175 178 friend class ParallelModeEnabler; 179 friend class MarkingConstraintSolver; 176 180 177 181 void appendJSCellOrAuxiliary(HeapCell*); … … 229 233 230 234 CString m_codeName; 235 236 MarkingConstraint* m_currentConstraint { nullptr }; 237 MarkingConstraintSolver* m_currentSolver { nullptr }; 231 238 232 239 public: -
trunk/Source/JavaScriptCore/heap/Subspace.cpp
r225831 r226667 127 127 } 128 128 129 void Subspace::sweep() 130 { 131 forEachAllocator( 132 [&] (MarkedAllocator& allocator) { 133 allocator.sweep(); 134 }); 135 } 136 129 137 void Subspace::didResizeBits(size_t) 130 138 { -
trunk/Source/JavaScriptCore/heap/Subspace.h
r225831 r226667 92 92 void forEachLiveCell(const Func&); 93 93 94 void sweep(); 95 94 96 Subspace* nextSubspaceInAlignedMemoryAllocator() const { return m_nextSubspaceInAlignedMemoryAllocator; } 95 97 void setNextSubspaceInAlignedMemoryAllocator(Subspace* subspace) { m_nextSubspaceInAlignedMemoryAllocator = subspace; } -
trunk/Source/JavaScriptCore/heap/SubspaceInlines.h
r225831 r226667 137 137 [&] (MarkedBlock::Handle* handle) { 138 138 handle->forEachLiveCell( 139 [&] ( HeapCell* cell, HeapCell::Kind kind) -> IterationStatus {139 [&] (size_t, HeapCell* cell, HeapCell::Kind kind) -> IterationStatus { 140 140 func(cell, kind); 141 141 return IterationStatus::Continue; -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm
r226556 r226667 948 948 loadp JSFunction::m_executable[targetRegister], targetRegister 949 949 loadp FunctionExecutable::m_codeBlockForCall[targetRegister], targetRegister 950 loadp ExecutableToCodeBlockEdge::m_codeBlock[targetRegister], targetRegister 950 951 end 951 952 … … 958 959 loadp JSFunction::m_executable[targetRegister], targetRegister 959 960 loadp FunctionExecutable::m_codeBlockForConstruct[targetRegister], targetRegister 961 loadp ExecutableToCodeBlockEdge::m_codeBlock[targetRegister], targetRegister 960 962 end 961 963 -
trunk/Source/JavaScriptCore/runtime/EvalExecutable.cpp
r217108 r226667 51 51 ScriptExecutable::visitChildren(thisObject, visitor); 52 52 visitor.append(thisObject->m_unlinkedEvalCodeBlock); 53 if (EvalCodeBlock* evalCodeBlock = thisObject->m_evalCodeBlock.get()) 54 evalCodeBlock->visitWeakly(visitor); 53 visitor.append(thisObject->m_evalCodeBlock); 55 54 } 56 55 -
trunk/Source/JavaScriptCore/runtime/EvalExecutable.h
r225314 r226667 26 26 #pragma once 27 27 28 #include "ExecutableToCodeBlockEdge.h" 28 29 #include "ScriptExecutable.h" 29 30 #include "UnlinkedEvalCodeBlock.h" … … 41 42 EvalCodeBlock* codeBlock() 42 43 { 43 return m_evalCodeBlock.get();44 return bitwise_cast<EvalCodeBlock*>(ExecutableToCodeBlockEdge::unwrap(m_evalCodeBlock.get())); 44 45 } 45 46 … … 71 72 static void visitChildren(JSCell*, SlotVisitor&); 72 73 73 WriteBarrier<E valCodeBlock> m_evalCodeBlock;74 WriteBarrier<ExecutableToCodeBlockEdge> m_evalCodeBlock; 74 75 WriteBarrier<UnlinkedEvalCodeBlock> m_unlinkedEvalCodeBlock; 75 76 }; -
trunk/Source/JavaScriptCore/runtime/FunctionExecutable.cpp
r222827 r226667 1 1 /* 2 * Copyright (C) 2009 , 2010, 2013, 2015-2016Apple Inc. All rights reserved.2 * Copyright (C) 2009-2018 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 69 69 FunctionCodeBlock* FunctionExecutable::baselineCodeBlockFor(CodeSpecializationKind kind) 70 70 { 71 FunctionCodeBlock* result;71 ExecutableToCodeBlockEdge* edge; 72 72 if (kind == CodeForCall) 73 result= m_codeBlockForCall.get();73 edge = m_codeBlockForCall.get(); 74 74 else { 75 75 RELEASE_ASSERT(kind == CodeForConstruct); 76 result= m_codeBlockForConstruct.get();76 edge = m_codeBlockForConstruct.get(); 77 77 } 78 if (! result)78 if (!edge) 79 79 return 0; 80 return static_cast<FunctionCodeBlock*>( result->baselineAlternative());80 return static_cast<FunctionCodeBlock*>(edge->codeBlock()->baselineAlternative()); 81 81 } 82 82 … … 86 86 ASSERT_GC_OBJECT_INHERITS(thisObject, info()); 87 87 ScriptExecutable::visitChildren(thisObject, visitor); 88 if (FunctionCodeBlock* codeBlockForCall = thisObject->m_codeBlockForCall.get()) 89 codeBlockForCall->visitWeakly(visitor); 90 if (FunctionCodeBlock* codeBlockForConstruct = thisObject->m_codeBlockForConstruct.get()) 91 codeBlockForConstruct->visitWeakly(visitor); 88 visitor.append(thisObject->m_codeBlockForCall); 89 visitor.append(thisObject->m_codeBlockForConstruct); 92 90 visitor.append(thisObject->m_unlinkedExecutable); 93 91 visitor.append(thisObject->m_singletonFunction); -
trunk/Source/JavaScriptCore/runtime/FunctionExecutable.h
r225314 r226667 1 1 /* 2 * Copyright (C) 2009-201 7Apple Inc. All rights reserved.2 * Copyright (C) 2009-2018 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 "ExecutableToCodeBlockEdge.h" 28 29 #include "ScriptExecutable.h" 29 30 #include "SourceCode.h" … … 69 70 FunctionCodeBlock* eitherCodeBlock() 70 71 { 72 ExecutableToCodeBlockEdge* edge; 71 73 if (m_codeBlockForCall) 72 return m_codeBlockForCall.get(); 73 return m_codeBlockForConstruct.get(); 74 edge = m_codeBlockForCall.get(); 75 else 76 edge = m_codeBlockForConstruct.get(); 77 return bitwise_cast<FunctionCodeBlock*>(ExecutableToCodeBlockEdge::unwrap(edge)); 74 78 } 75 79 … … 81 85 FunctionCodeBlock* codeBlockForCall() 82 86 { 83 return m_codeBlockForCall.get();87 return bitwise_cast<FunctionCodeBlock*>(ExecutableToCodeBlockEdge::unwrap(m_codeBlockForCall.get())); 84 88 } 85 89 86 90 bool isGeneratedForConstruct() const 87 91 { 88 return m_codeBlockForConstruct.get();92 return !!m_codeBlockForConstruct; 89 93 } 90 94 91 95 FunctionCodeBlock* codeBlockForConstruct() 92 96 { 93 return m_codeBlockForConstruct.get();97 return bitwise_cast<FunctionCodeBlock*>(ExecutableToCodeBlockEdge::unwrap(m_codeBlockForConstruct.get())); 94 98 } 95 99 … … 205 209 unsigned m_parametersStartOffset; 206 210 WriteBarrier<UnlinkedFunctionExecutable> m_unlinkedExecutable; 207 WriteBarrier< FunctionCodeBlock> m_codeBlockForCall;208 WriteBarrier< FunctionCodeBlock> m_codeBlockForConstruct;211 WriteBarrier<ExecutableToCodeBlockEdge> m_codeBlockForCall; 212 WriteBarrier<ExecutableToCodeBlockEdge> m_codeBlockForConstruct; 209 213 RefPtr<TypeSet> m_returnStatementTypeSet; 210 214 WriteBarrier<InferredValue> m_singletonFunction; -
trunk/Source/JavaScriptCore/runtime/JSType.h
r226311 r226667 44 44 UnlinkedEvalCodeBlockType, 45 45 UnlinkedFunctionCodeBlockType, 46 47 CodeBlockType, 46 48 47 49 JSFixedArrayType, -
trunk/Source/JavaScriptCore/runtime/ModuleProgramExecutable.cpp
r221822 r226667 94 94 visitor.append(thisObject->m_unlinkedModuleProgramCodeBlock); 95 95 visitor.append(thisObject->m_moduleEnvironmentSymbolTable); 96 if (ModuleProgramCodeBlock* moduleProgramCodeBlock = thisObject->m_moduleProgramCodeBlock.get()) 97 moduleProgramCodeBlock->visitWeakly(visitor); 96 visitor.append(thisObject->m_moduleProgramCodeBlock); 98 97 } 99 98 -
trunk/Source/JavaScriptCore/runtime/ModuleProgramExecutable.h
r225314 r226667 1 1 /* 2 * Copyright (C) 2009 , 2010, 2013-2016Apple Inc. All rights reserved.2 * Copyright (C) 2009-2017 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 "ExecutableToCodeBlockEdge.h" 28 29 #include "ScriptExecutable.h" 29 30 … … 48 49 ModuleProgramCodeBlock* codeBlock() 49 50 { 50 return m_moduleProgramCodeBlock.get();51 return bitwise_cast<ModuleProgramCodeBlock*>(ExecutableToCodeBlockEdge::unwrap(m_moduleProgramCodeBlock.get())); 51 52 } 52 53 … … 79 80 WriteBarrier<UnlinkedModuleProgramCodeBlock> m_unlinkedModuleProgramCodeBlock; 80 81 WriteBarrier<SymbolTable> m_moduleEnvironmentSymbolTable; 81 WriteBarrier< ModuleProgramCodeBlock> m_moduleProgramCodeBlock;82 WriteBarrier<ExecutableToCodeBlockEdge> m_moduleProgramCodeBlock; 82 83 }; 83 84 -
trunk/Source/JavaScriptCore/runtime/ProgramExecutable.cpp
r223746 r226667 210 210 ScriptExecutable::visitChildren(thisObject, visitor); 211 211 visitor.append(thisObject->m_unlinkedProgramCodeBlock); 212 if (ProgramCodeBlock* programCodeBlock = thisObject->m_programCodeBlock.get()) 213 programCodeBlock->visitWeakly(visitor); 212 visitor.append(thisObject->m_programCodeBlock); 214 213 } 215 214 -
trunk/Source/JavaScriptCore/runtime/ProgramExecutable.h
r225314 r226667 1 1 /* 2 * Copyright (C) 2009 , 2010, 2013-2016Apple Inc. All rights reserved.2 * Copyright (C) 2009-2017 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 "ExecutableToCodeBlockEdge.h" 28 29 #include "ScriptExecutable.h" 29 30 … … 56 57 ProgramCodeBlock* codeBlock() 57 58 { 58 return m_programCodeBlock.get();59 return bitwise_cast<ProgramCodeBlock*>(ExecutableToCodeBlockEdge::unwrap(m_programCodeBlock.get())); 59 60 } 60 61 … … 84 85 85 86 WriteBarrier<UnlinkedProgramCodeBlock> m_unlinkedProgramCodeBlock; 86 WriteBarrier< ProgramCodeBlock> m_programCodeBlock;87 WriteBarrier<ExecutableToCodeBlockEdge> m_programCodeBlock; 87 88 }; 88 89 -
trunk/Source/JavaScriptCore/runtime/ScriptExecutable.cpp
r221849 r226667 90 90 ASSERT(kind == CodeForCall); 91 91 92 oldCodeBlock = executable->m_programCodeBlock.get();93 executable->m_programCodeBlock.setMayBeNull(vm, this, codeBlock);92 oldCodeBlock = ExecutableToCodeBlockEdge::deactivateAndUnwrap(executable->m_programCodeBlock.get()); 93 executable->m_programCodeBlock.setMayBeNull(vm, this, ExecutableToCodeBlockEdge::wrapAndActivate(codeBlock)); 94 94 break; 95 95 } … … 101 101 ASSERT(kind == CodeForCall); 102 102 103 oldCodeBlock = executable->m_moduleProgramCodeBlock.get();104 executable->m_moduleProgramCodeBlock.setMayBeNull(vm, this, codeBlock);103 oldCodeBlock = ExecutableToCodeBlockEdge::deactivateAndUnwrap(executable->m_moduleProgramCodeBlock.get()); 104 executable->m_moduleProgramCodeBlock.setMayBeNull(vm, this, ExecutableToCodeBlockEdge::wrapAndActivate(codeBlock)); 105 105 break; 106 106 } … … 112 112 ASSERT(kind == CodeForCall); 113 113 114 oldCodeBlock = executable->m_evalCodeBlock.get();115 executable->m_evalCodeBlock.setMayBeNull(vm, this, codeBlock);114 oldCodeBlock = ExecutableToCodeBlockEdge::deactivateAndUnwrap(executable->m_evalCodeBlock.get()); 115 executable->m_evalCodeBlock.setMayBeNull(vm, this, ExecutableToCodeBlockEdge::wrapAndActivate(codeBlock)); 116 116 break; 117 117 } … … 123 123 switch (kind) { 124 124 case CodeForCall: 125 oldCodeBlock = executable->m_codeBlockForCall.get();126 executable->m_codeBlockForCall.setMayBeNull(vm, this, codeBlock);125 oldCodeBlock = ExecutableToCodeBlockEdge::deactivateAndUnwrap(executable->m_codeBlockForCall.get()); 126 executable->m_codeBlockForCall.setMayBeNull(vm, this, ExecutableToCodeBlockEdge::wrapAndActivate(codeBlock)); 127 127 break; 128 128 case CodeForConstruct: 129 oldCodeBlock = executable->m_codeBlockForConstruct.get();130 executable->m_codeBlockForConstruct.setMayBeNull(vm, this, codeBlock);129 oldCodeBlock = ExecutableToCodeBlockEdge::deactivateAndUnwrap(executable->m_codeBlockForConstruct.get()); 130 executable->m_codeBlockForConstruct.setMayBeNull(vm, this, ExecutableToCodeBlockEdge::wrapAndActivate(codeBlock)); 131 131 break; 132 132 } … … 269 269 EvalExecutable* executable = jsCast<EvalExecutable*>(this); 270 270 EvalCodeBlock* baseline = static_cast<EvalCodeBlock*>( 271 executable-> m_evalCodeBlock->baselineVersion());271 executable->codeBlock()->baselineVersion()); 272 272 EvalCodeBlock* result = EvalCodeBlock::create(&vm, 273 273 CodeBlock::CopyParsedBlock, *baseline); … … 280 280 ProgramExecutable* executable = jsCast<ProgramExecutable*>(this); 281 281 ProgramCodeBlock* baseline = static_cast<ProgramCodeBlock*>( 282 executable-> m_programCodeBlock->baselineVersion());282 executable->codeBlock()->baselineVersion()); 283 283 ProgramCodeBlock* result = ProgramCodeBlock::create(&vm, 284 284 CodeBlock::CopyParsedBlock, *baseline); … … 291 291 ModuleProgramExecutable* executable = jsCast<ModuleProgramExecutable*>(this); 292 292 ModuleProgramCodeBlock* baseline = static_cast<ModuleProgramCodeBlock*>( 293 executable-> m_moduleProgramCodeBlock->baselineVersion());293 executable->codeBlock()->baselineVersion()); 294 294 ModuleProgramCodeBlock* result = ModuleProgramCodeBlock::create(&vm, 295 295 CodeBlock::CopyParsedBlock, *baseline); -
trunk/Source/JavaScriptCore/runtime/VM.cpp
r226295 r226667 45 45 #include "EvalCodeBlock.h" 46 46 #include "Exception.h" 47 #include "ExecutableToCodeBlockEdge.h" 47 48 #include "FTLThunks.h" 48 49 #include "FastMallocAlignedMemoryAllocator.h" … … 250 251 #endif 251 252 , directEvalExecutableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), DirectEvalExecutable) 253 , executableToCodeBlockEdgeSpace ISO_SUBSPACE_INIT(heap, cellHeapCellType.get(), ExecutableToCodeBlockEdge) 252 254 , functionExecutableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), FunctionExecutable) 253 255 , indirectEvalExecutableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), IndirectEvalExecutable) … … 262 264 , weakSetSpace ISO_SUBSPACE_INIT(heap, destructibleObjectHeapCellType.get(), JSWeakSet) 263 265 , weakMapSpace ISO_SUBSPACE_INIT(heap, destructibleObjectHeapCellType.get(), JSWeakMap) 266 , executableToCodeBlockEdgesWithConstraints(executableToCodeBlockEdgeSpace) 267 , executableToCodeBlockEdgesWithFinalizers(executableToCodeBlockEdgeSpace) 264 268 , inferredTypesWithFinalizers(inferredTypeSpace) 265 269 , inferredValuesWithFinalizers(inferredValueSpace) 270 , evalCodeBlockSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), EvalCodeBlock) 271 , functionCodeBlockSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), FunctionCodeBlock) 272 , moduleProgramCodeBlockSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), ModuleProgramCodeBlock) 273 , programCodeBlockSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), ProgramCodeBlock) 266 274 , vmType(vmType) 267 275 , clientData(0) … … 353 361 mapIteratorStructure.set(*this, JSMapIterator::createStructure(*this, 0, jsNull())); 354 362 bigIntStructure.set(*this, JSBigInt::createStructure(*this, 0, jsNull())); 363 executableToCodeBlockEdgeStructure.set(*this, ExecutableToCodeBlockEdge::createStructure(*this, nullptr, jsNull())); 355 364 356 365 sentinelSetBucket.set(*this, JSSet::BucketType::createSentinel(*this)); -
trunk/Source/JavaScriptCore/runtime/VM.h
r226017 r226667 1 1 /* 2 * Copyright (C) 2008-201 7Apple Inc. All rights reserved.2 * Copyright (C) 2008-2018 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 340 340 341 341 IsoSubspace directEvalExecutableSpace; 342 IsoSubspace executableToCodeBlockEdgeSpace; 342 343 IsoSubspace functionExecutableSpace; 343 344 IsoSubspace indirectEvalExecutableSpace; … … 353 354 IsoSubspace weakMapSpace; 354 355 356 IsoCellSet executableToCodeBlockEdgesWithConstraints; 357 IsoCellSet executableToCodeBlockEdgesWithFinalizers; 355 358 IsoCellSet inferredTypesWithFinalizers; 356 359 IsoCellSet inferredValuesWithFinalizers; 357 360 361 struct SpaceAndFinalizerSet { 362 IsoSubspace space; 363 IsoCellSet finalizerSet; 364 365 template<typename... Arguments> 366 SpaceAndFinalizerSet(Arguments&&... arguments) 367 : space(std::forward<Arguments>(arguments)...) 368 , finalizerSet(space) 369 { 370 } 371 372 static IsoCellSet& finalizerSetFor(Subspace& space) 373 { 374 return *bitwise_cast<IsoCellSet*>( 375 bitwise_cast<char*>(&space) - 376 OBJECT_OFFSETOF(SpaceAndFinalizerSet, space) + 377 OBJECT_OFFSETOF(SpaceAndFinalizerSet, finalizerSet)); 378 } 379 }; 380 381 SpaceAndFinalizerSet evalCodeBlockSpace; 382 SpaceAndFinalizerSet functionCodeBlockSpace; 383 SpaceAndFinalizerSet moduleProgramCodeBlockSpace; 384 SpaceAndFinalizerSet programCodeBlockSpace; 385 386 template<typename Func> 387 void forEachCodeBlockSpace(const Func& func) 388 { 389 // This should not include webAssemblyCodeBlockSpace because this is about subsclasses of 390 // JSC::CodeBlock. 391 func(evalCodeBlockSpace); 392 func(functionCodeBlockSpace); 393 func(moduleProgramCodeBlockSpace); 394 func(programCodeBlockSpace); 395 } 396 358 397 VMType vmType; 359 398 ClientData* clientData; … … 419 458 Strong<Structure> mapIteratorStructure; 420 459 Strong<Structure> bigIntStructure; 460 Strong<Structure> executableToCodeBlockEdgeStructure; 421 461 422 462 Strong<JSCell> emptyPropertyNameEnumerator; -
trunk/Source/JavaScriptCore/runtime/VMTraps.cpp
r223738 r226667 231 231 codeBlock->jettison(Profiler::JettisonDueToVMTraps); 232 232 } 233 return false;234 233 }); 235 234 RELEASE_ASSERT(sawCurrentCodeBlock); … … 342 341 if (codeBlock->hasInstalledVMTrapBreakpoints()) 343 342 codeBlock->jettison(Profiler::JettisonDueToVMTraps); 344 return false;345 343 }); 346 344 } -
trunk/Source/JavaScriptCore/tools/VMInspector.cpp
r224838 r226667 172 172 // compiled, its jitCode will be null, and we can disregard it as a match for 173 173 // the machinePC we're searching for. 174 return false;174 return; 175 175 } 176 176 177 177 if (!JITCode::isJIT(jitCode->jitType())) 178 return false;178 return; 179 179 180 180 if (jitCode->contains(machinePC)) { 181 181 codeBlock = cb; 182 return true;182 return; 183 183 } 184 return false;185 184 }); 186 185 if (codeBlock) … … 277 276 } 278 277 279 booloperator()(CodeBlock* codeBlock) const278 void operator()(CodeBlock* codeBlock) const 280 279 { 281 280 if (codeBlock == candidate) 282 281 found = true; 283 return found;284 282 } 285 283 -
trunk/Source/WTF/ChangeLog
r226601 r226667 1 2018-01-04 Filip Pizlo <[email protected]> 2 3 CodeBlocks should be in IsoSubspaces 4 https://bugs.webkit.org/show_bug.cgi?id=180884 5 6 Reviewed by Saam Barati. 7 8 Deque<>::contains() is helpful for a debug ASSERT. 9 10 * wtf/Deque.h: 11 (WTF::inlineCapacity>::contains): 12 1 13 2018-01-08 Don Olmstead <[email protected]> 2 14 -
trunk/Source/WTF/wtf/Deque.h
r225524 r226667 76 76 const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } 77 77 const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } 78 79 template<typename U> bool contains(const U&); 78 80 79 81 T& first() { ASSERT(m_start != m_end); return m_buffer.buffer()[m_start]; } … … 439 441 440 442 template<typename T, size_t inlineCapacity> 443 template<typename U> 444 bool Deque<T, inlineCapacity>::contains(const U& searchValue) 445 { 446 for (auto& value : *this) { 447 if (value == searchValue) 448 return true; 449 } 450 return false; 451 } 452 453 template<typename T, size_t inlineCapacity> 441 454 inline auto Deque<T, inlineCapacity>::takeFirst() -> T 442 455 { -
trunk/Source/WebCore/ChangeLog
r226666 r226667 1 2018-01-04 Filip Pizlo <[email protected]> 2 3 CodeBlocks should be in IsoSubspaces 4 https://bugs.webkit.org/show_bug.cgi?id=180884 5 6 Reviewed by Saam Barati. 7 8 No new tests because no new behavior. 9 10 Adopting new parallel constraint API, so that more of the logic of doing parallel 11 constraint solving is shared between the DOM's output constraints and JSC's output 12 constraints. 13 14 * bindings/js/DOMGCOutputConstraint.cpp: 15 (WebCore::DOMGCOutputConstraint::executeImpl): 16 (WebCore::DOMGCOutputConstraint::doParallelWorkImpl): Deleted. 17 (WebCore::DOMGCOutputConstraint::finishParallelWorkImpl): Deleted. 18 * bindings/js/DOMGCOutputConstraint.h: 19 1 20 2018-01-08 Simon Fraser <[email protected]> 2 21 -
trunk/Source/WebCore/bindings/js/DOMGCOutputConstraint.cpp
r225524 r226667 1 1 /* 2 * Copyright (C) 2017 Apple Inc. All rights reserved.2 * Copyright (C) 2017-2018 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 50 50 } 51 51 52 ConstraintParallelism DOMGCOutputConstraint::executeImpl(SlotVisitor&)52 void DOMGCOutputConstraint::executeImpl(SlotVisitor& visitor) 53 53 { 54 54 Heap& heap = m_vm.heap; 55 55 56 56 if (heap.mutatorExecutionVersion() == m_lastExecutionVersion) 57 return ConstraintParallelism::Sequential;57 return; 58 58 59 59 m_lastExecutionVersion = heap.mutatorExecutionVersion(); 60 60 61 RELEASE_ASSERT(m_tasks.isEmpty());62 61 m_clientData.forEachOutputConstraintSpace( 63 62 [&] (Subspace& subspace) { … … 67 66 }; 68 67 69 m_tasks.append(subspace.forEachMarkedCellInParallel(func));68 visitor.addParallelConstraintTask(subspace.forEachMarkedCellInParallel(func)); 70 69 }); 71 72 return ConstraintParallelism::Parallel;73 70 } 74 71 75 void DOMGCOutputConstraint::doParallelWorkImpl(SlotVisitor& visitor)76 {77 for (auto& task : m_tasks)78 task->run(visitor);79 }80 81 void DOMGCOutputConstraint::finishParallelWorkImpl(SlotVisitor&)82 {83 m_tasks.clear();84 }85 86 72 } // namespace WebCore 87 73 -
trunk/Source/WebCore/bindings/js/DOMGCOutputConstraint.h
r225524 r226667 1 1 /* 2 * Copyright (C) 2017 Apple Inc. All rights reserved.2 * Copyright (C) 2017-2018 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 40 40 41 41 protected: 42 JSC::ConstraintParallelism executeImpl(JSC::SlotVisitor&) override; 43 void doParallelWorkImpl(JSC::SlotVisitor&) override; 44 void finishParallelWorkImpl(JSC::SlotVisitor&) override; 42 void executeImpl(JSC::SlotVisitor&) override; 45 43 46 44 private: … … 48 46 JSVMClientData& m_clientData; 49 47 uint64_t m_lastExecutionVersion; 50 Vector<RefPtr<SharedTask<void(SlotVisitor&)>>> m_tasks;51 48 }; 52 49 -
trunk/Tools/Scripts/run-jsc-benchmarks
r225524 r226667 217 217 $quantum=1000 218 218 $includeSunSpider=true 219 $includeLongSpider= true219 $includeLongSpider=false 220 220 $includeV8=true 221 221 $includeKraken=true … … 227 227 $includeBrowsermarkDOM=false 228 228 $includeOctane=true 229 $includeCompressionBench = true230 $includeSixSpeed = true229 $includeCompressionBench = false 230 $includeSixSpeed = false 231 231 $includeTailBench = true 232 232 $measureGC=false
Note:
See TracChangeset
for help on using the changeset viewer.