Changeset 200933 in webkit
- Timestamp:
- May 15, 2016, 4:08:21 PM (9 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r200928 r200933 1 2016-05-15 Filip Pizlo <fpizlo@apple.com> 2 3 DFG::Plan shouldn't read from its VM once it's been cancelled 4 https://bugs.webkit.org/show_bug.cgi?id=157726 5 6 Reviewed by Saam Barati. 7 8 Plan::vm was a reference, not a pointer, and so wasn't nulled by Plan::cancel(). So, a 9 cancelled plan may have a dangling pointer to a VM: we could delete the VM after cancelling 10 the plan. 11 12 Prior to http://trac.webkit.org/changeset/200705, this was probably fine because nobody 13 would read Plan::vm if the plan was cancelled. But r200705 changed that. It was a hard 14 regression to spot because usually a cancelled plan will still refer to a valid VM. 15 16 This change fixes the regression and makes it a lot easier to spot the regression in the 17 future. Plan::vm is now a pointer and we null it in Plan::cancel(). Now if you make this 18 mistake, you will get a crash anytime the Plan is cancelled, not just anytime the plan is 19 cancelled and the VM gets deleted. Also, it's now very clear what to do when you want to 20 use Plan::vm on the cancel path: you can null-check vm; if it's null, assume the worst. 21 22 Because we null the VM of a cancelled plan, we cannot have Safepoint::vm() return the 23 plan's VM anymore. That's because when we cancel a plan that is at a safepoint, we use the 24 safepoint's VM to determine whether this is one of our safepoints *after* the plan is 25 already cancelled. So, Safepoint now has its own copy of m_vm, and that copy gets nulled 26 when the Safepoint is cancelled. The Safepoint's m_vm will be nulled moments after Plan's 27 vm gets nulled (see Worklist::removeDeadPlans(), which has a cancel path for Plans in one 28 loop and a cancel path for Safepoints in the loop after it). 29 30 * dfg/DFGJITFinalizer.cpp: 31 (JSC::DFG::JITFinalizer::finalizeCommon): 32 * dfg/DFGPlan.cpp: 33 (JSC::DFG::Plan::Plan): 34 (JSC::DFG::Plan::computeCompileTimes): 35 (JSC::DFG::Plan::reportCompileTimes): 36 (JSC::DFG::Plan::compileInThreadImpl): 37 (JSC::DFG::Plan::reallyAdd): 38 (JSC::DFG::Plan::notifyCompiling): 39 (JSC::DFG::Plan::finalizeWithoutNotifyingCallback): 40 (JSC::DFG::Plan::cancel): 41 * dfg/DFGPlan.h: 42 (JSC::DFG::Plan::canTierUpAndOSREnter): 43 * dfg/DFGSafepoint.cpp: 44 (JSC::DFG::Safepoint::cancel): 45 (JSC::DFG::Safepoint::vm): 46 * dfg/DFGSafepoint.h: 47 * dfg/DFGWorklist.cpp: 48 (JSC::DFG::Worklist::isActiveForVM): 49 (JSC::DFG::Worklist::waitUntilAllPlansForVMAreReady): 50 (JSC::DFG::Worklist::removeAllReadyPlansForVM): 51 (JSC::DFG::Worklist::rememberCodeBlocks): 52 (JSC::DFG::Worklist::visitWeakReferences): 53 (JSC::DFG::Worklist::removeDeadPlans): 54 (JSC::DFG::Worklist::runThread): 55 * ftl/FTLJITFinalizer.cpp: 56 (JSC::FTL::JITFinalizer::finalizeFunction): 57 1 58 2016-05-15 Yusuke Suzuki <utatane.tea@gmail.com> 2 59 -
trunk/Source/JavaScriptCore/dfg/DFGJITFinalizer.cpp
r200658 r200933 92 92 93 93 if (m_plan.compilation) 94 m_plan.vm .m_perBytecodeProfiler->addCompilation(m_plan.codeBlock, m_plan.compilation);94 m_plan.vm->m_perBytecodeProfiler->addCompilation(m_plan.codeBlock, m_plan.compilation); 95 95 96 96 if (!m_plan.willTryToTierUp) -
trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp
r200705 r200933 139 139 CompilationMode mode, unsigned osrEntryBytecodeIndex, 140 140 const Operands<JSValue>& mustHandleValues) 141 : vm( *passedCodeBlock->vm())141 : vm(passedCodeBlock->vm()) 142 142 , codeBlock(passedCodeBlock) 143 143 , profiledDFGCodeBlock(profiledDFGCodeBlock) … … 145 145 , osrEntryBytecodeIndex(osrEntryBytecodeIndex) 146 146 , mustHandleValues(mustHandleValues) 147 , compilation( codeBlock->vm()->m_perBytecodeProfiler ? adoptRef(new Profiler::Compilation(codeBlock->vm()->m_perBytecodeProfiler->ensureBytecodesFor(codeBlock), profilerCompilationKindForMode(mode))) : 0)147 , compilation(vm->m_perBytecodeProfiler ? adoptRef(new Profiler::Compilation(vm->m_perBytecodeProfiler->ensureBytecodesFor(codeBlock), profilerCompilationKindForMode(mode))) : 0) 148 148 , inlineCallFrames(adoptRef(new InlineCallFrameSet())) 149 149 , identifiers(codeBlock) … … 161 161 return reportCompileTimes() 162 162 || Options::reportTotalCompileTimes() 163 || vm.m_perBytecodeProfiler;163 || (vm && vm->m_perBytecodeProfiler); 164 164 } 165 165 … … 245 245 } 246 246 247 Graph dfg( vm, *this, longLivedState);247 Graph dfg(*vm, *this, longLivedState); 248 248 249 249 if (!parse(dfg)) { … … 538 538 { 539 539 watchpoints.reallyAdd(codeBlock, *commonData); 540 identifiers.reallyAdd( vm, commonData);541 weakReferences.reallyAdd( vm, commonData);542 transitions.reallyAdd( vm, commonData);540 identifiers.reallyAdd(*vm, commonData); 541 weakReferences.reallyAdd(*vm, commonData); 542 transitions.reallyAdd(*vm, commonData); 543 543 } 544 544 … … 562 562 { 563 563 // We will establish new references from the code block to things. So, we need a barrier. 564 vm .heap.writeBarrier(codeBlock);564 vm->heap.writeBarrier(codeBlock); 565 565 566 566 if (!isStillValid()) { … … 661 661 void Plan::cancel() 662 662 { 663 vm = nullptr; 663 664 codeBlock = nullptr; 664 665 profiledDFGCodeBlock = nullptr; -
trunk/Source/JavaScriptCore/dfg/DFGPlan.h
r200531 r200933 1 1 /* 2 * Copyright (C) 2013-201 5Apple Inc. All rights reserved.2 * Copyright (C) 2013-2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 79 79 bool canTierUpAndOSREnter() const { return !tierUpAndOSREnterBytecodes.isEmpty(); } 80 80 81 VM& vm; 81 // Warning: pretty much all of the pointer fields in this object get nulled by cancel(). So, if 82 // you're writing code that is callable on the cancel path, be sure to null check everything! 83 84 VM* vm; 82 85 83 86 // These can be raw pointers because we visit them during every GC in checkLivenessAndVisitChildren. -
trunk/Source/JavaScriptCore/dfg/DFGSafepoint.cpp
r169595 r200933 1 1 /* 2 * Copyright (C) 2014 Apple Inc. All rights reserved.2 * Copyright (C) 2014, 2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 48 48 49 49 Safepoint::Safepoint(Plan& plan, Result& result) 50 : m_plan(plan) 50 : m_vm(plan.vm) 51 , m_plan(plan) 51 52 , m_didCallBegin(false) 52 53 , m_result(result) … … 115 116 m_plan.cancel(); 116 117 m_result.m_didGetCancelled = true; 118 m_vm = nullptr; 117 119 } 118 120 119 VM &Safepoint::vm() const121 VM* Safepoint::vm() const 120 122 { 121 return m_ plan.vm;123 return m_vm; 122 124 } 123 125 -
trunk/Source/JavaScriptCore/dfg/DFGSafepoint.h
r167897 r200933 1 1 /* 2 * Copyright (C) 2014 Apple Inc. All rights reserved.2 * Copyright (C) 2014, 2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 73 73 void cancel(); 74 74 75 VM & vm() const;75 VM* vm() const; // May return null if we've been cancelled. 76 76 77 77 private: 78 VM* m_vm; 78 79 Plan& m_plan; 79 80 Vector<Scannable*> m_scannables; -
trunk/Source/JavaScriptCore/dfg/DFGWorklist.cpp
r198477 r200933 1 1 /* 2 * Copyright (C) 2013 , 2014Apple Inc. All rights reserved.2 * Copyright (C) 2013-2014, 2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 81 81 PlanMap::const_iterator end = m_plans.end(); 82 82 for (PlanMap::const_iterator iter = m_plans.begin(); iter != end; ++iter) { 83 if ( &iter->value->vm == &vm)83 if (iter->value->vm == &vm) 84 84 return true; 85 85 } … … 130 130 PlanMap::iterator end = m_plans.end(); 131 131 for (PlanMap::iterator iter = m_plans.begin(); iter != end; ++iter) { 132 if ( &iter->value->vm != &vm)132 if (iter->value->vm != &vm) 133 133 continue; 134 134 if (iter->value->stage != Plan::Ready) { … … 151 151 for (size_t i = 0; i < m_readyPlans.size(); ++i) { 152 152 RefPtr<Plan> plan = m_readyPlans[i]; 153 if ( &plan->vm != &vm)153 if (plan->vm != &vm) 154 154 continue; 155 155 if (plan->stage != Plan::Ready) … … 213 213 for (PlanMap::iterator iter = m_plans.begin(); iter != m_plans.end(); ++iter) { 214 214 Plan* plan = iter->value.get(); 215 if ( &plan->vm != &vm)215 if (plan->vm != &vm) 216 216 continue; 217 217 plan->rememberCodeBlocks(); … … 240 240 for (PlanMap::iterator iter = m_plans.begin(); iter != m_plans.end(); ++iter) { 241 241 Plan* plan = iter->value.get(); 242 if ( &plan->vm != vm)242 if (plan->vm != vm) 243 243 continue; 244 244 plan->checkLivenessAndVisitChildren(visitor); … … 252 252 ThreadData* data = m_threads[i].get(); 253 253 Safepoint* safepoint = data->m_safepoint; 254 if (safepoint && &safepoint->vm() == vm)254 if (safepoint && safepoint->vm() == vm) 255 255 safepoint->checkLivenessAndVisitChildren(visitor); 256 256 } … … 264 264 for (PlanMap::iterator iter = m_plans.begin(); iter != m_plans.end(); ++iter) { 265 265 Plan* plan = iter->value.get(); 266 if ( &plan->vm != &vm)266 if (plan->vm != &vm) 267 267 continue; 268 268 if (plan->isKnownToBeLiveDuringGC()) … … 297 297 if (!safepoint) 298 298 continue; 299 if ( &safepoint->vm() != &vm)299 if (safepoint->vm() != &vm) 300 300 continue; 301 301 if (safepoint->isKnownToBeLiveDuringGC()) … … 366 366 dataLog(*this, ": Compiling ", plan->key(), " asynchronously\n"); 367 367 368 RELEASE_ASSERT(!plan->vm .heap.isCollecting());368 RELEASE_ASSERT(!plan->vm->heap.isCollecting()); 369 369 plan->compileInThread(longLivedState, data); 370 RELEASE_ASSERT(plan->stage == Plan::Cancelled || !plan->vm .heap.isCollecting());370 RELEASE_ASSERT(plan->stage == Plan::Cancelled || !plan->vm->heap.isCollecting()); 371 371 372 372 { … … 378 378 plan->notifyCompiled(); 379 379 } 380 RELEASE_ASSERT(!plan->vm .heap.isCollecting());380 RELEASE_ASSERT(!plan->vm->heap.isCollecting()); 381 381 } 382 382 -
trunk/Source/JavaScriptCore/ftl/FTLJITFinalizer.cpp
r200658 r200933 84 84 85 85 if (m_plan.compilation) 86 m_plan.vm .m_perBytecodeProfiler->addCompilation(m_plan.codeBlock, m_plan.compilation);86 m_plan.vm->m_perBytecodeProfiler->addCompilation(m_plan.codeBlock, m_plan.compilation); 87 87 88 88 return true;
Note:
See TracChangeset
for help on using the changeset viewer.