Changeset 165005 in webkit
- Timestamp:
- Mar 3, 2014 1:39:21 PM (10 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 16 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r164991 r165005 1 2014-03-03 Mark Lam <mark.lam@apple.com> 2 3 ASSERTION FAILED: m_numBreakpoints >= numBreakpoints when deleting breakpoints. 4 <https://webkit.org/b/129393> 5 6 Reviewed by Geoffrey Garen. 7 8 The issue manifests because the debugger will iterate all CodeBlocks in 9 the heap when setting / clearing breakpoints, but it is possible for a 10 CodeBlock to have been instantiate but is not yet registered with the 11 debugger. This can happen because of the following: 12 13 1. DFG worklist compilation is still in progress, and the target 14 codeBlock is not ready for installation in its executable yet. 15 16 2. DFG compilation failed and we have a codeBlock that will never be 17 installed in its executable, and the codeBlock has not been cleaned 18 up by the GC yet. 19 20 The code for installing the codeBlock in its executable is the same code 21 that registers it with the debugger. Hence, these codeBlocks are not 22 registered with the debugger, and any pending breakpoints that would map 23 to that CodeBlock is as yet unset or will never be set. As such, an 24 attempt to remove a breakpoint in that CodeBlock will fail that assertion. 25 26 To fix this, we do the following: 27 28 1. We'll eagerly clean up any zombie CodeBlocks due to failed DFG / FTL 29 compilation. This is achieved by providing a 30 DeferredCompilationCallback::compilationDidComplete() that does this 31 clean up, and have all sub classes call it at the end of their 32 compilationDidComplete() methods. 33 34 2. Before the debugger or profiler iterates CodeBlocks in the heap, they 35 will wait for all compilations to complete before proceeding. This 36 ensures that: 37 1. any zombie CodeBlocks would have been cleaned up, and won't be 38 seen by the debugger or profiler. 39 2. all CodeBlocks that the debugger and profiler needs to operate on 40 will be "ready" for whatever needs to be done to them e.g. 41 jettison'ing of DFG codeBlocks. 42 43 * bytecode/DeferredCompilationCallback.cpp: 44 (JSC::DeferredCompilationCallback::compilationDidComplete): 45 * bytecode/DeferredCompilationCallback.h: 46 - Provide default implementation method to clean up zombie CodeBlocks. 47 48 * debugger/Debugger.cpp: 49 (JSC::Debugger::forEachCodeBlock): 50 - Utility function to iterate CodeBlocks. It ensures that all compilations 51 are complete before proceeding. 52 (JSC::Debugger::setSteppingMode): 53 (JSC::Debugger::toggleBreakpoint): 54 (JSC::Debugger::recompileAllJSFunctions): 55 (JSC::Debugger::clearBreakpoints): 56 (JSC::Debugger::clearDebuggerRequests): 57 - Use the utility iterator function. 58 59 * debugger/Debugger.h: 60 * dfg/DFGOperations.cpp: 61 - Added an assert to ensure that zombie CodeBlocks will be imminently cleaned up. 62 63 * dfg/DFGPlan.cpp: 64 (JSC::DFG::Plan::finalizeWithoutNotifyingCallback): 65 - Remove unneeded code (that was not the best solution anyway) for ensuring 66 that we don't generate new DFG codeBlocks after enabling the debugger or 67 profiler. Now that we wait for compilations to complete before proceeding 68 with debugger and profiler work, this scenario will never happen. 69 70 * dfg/DFGToFTLDeferredCompilationCallback.cpp: 71 (JSC::DFG::ToFTLDeferredCompilationCallback::compilationDidComplete): 72 - Call the super class method to clean up zombie codeBlocks. 73 74 * dfg/DFGToFTLForOSREntryDeferredCompilationCallback.cpp: 75 (JSC::DFG::ToFTLForOSREntryDeferredCompilationCallback::compilationDidComplete): 76 - Call the super class method to clean up zombie codeBlocks. 77 78 * heap/CodeBlockSet.cpp: 79 (JSC::CodeBlockSet::remove): 80 * heap/CodeBlockSet.h: 81 * heap/Heap.h: 82 (JSC::Heap::removeCodeBlock): 83 - New method to remove a codeBlock from the codeBlock set. 84 85 * jit/JITOperations.cpp: 86 - Added an assert to ensure that zombie CodeBlocks will be imminently cleaned up. 87 88 * jit/JITToDFGDeferredCompilationCallback.cpp: 89 (JSC::JITToDFGDeferredCompilationCallback::compilationDidComplete): 90 - Call the super class method to clean up zombie codeBlocks. 91 92 * runtime/VM.cpp: 93 (JSC::VM::waitForCompilationsToComplete): 94 - Renamed from prepareToDiscardCode() to be clearer about what it does. 95 96 (JSC::VM::discardAllCode): 97 (JSC::VM::releaseExecutableMemory): 98 (JSC::VM::setEnabledProfiler): 99 - Wait for compilation to complete before enabling the profiler. 100 101 * runtime/VM.h: 102 1 103 2014-03-03 Brian Burg <bburg@apple.com> 2 104 -
trunk/Source/JavaScriptCore/bytecode/DeferredCompilationCallback.cpp
r154824 r165005 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 27 27 #include "DeferredCompilationCallback.h" 28 28 29 #include "CodeBlock.h" 30 29 31 namespace JSC { 30 32 … … 32 34 DeferredCompilationCallback::~DeferredCompilationCallback() { } 33 35 36 void DeferredCompilationCallback::compilationDidComplete(CodeBlock* codeBlock, CompilationResult result) 37 { 38 switch (result) { 39 case CompilationFailed: 40 case CompilationInvalidated: 41 codeBlock->heap()->removeCodeBlock(codeBlock); 42 break; 43 case CompilationSuccessful: 44 break; 45 case CompilationDeferred: 46 RELEASE_ASSERT_NOT_REACHED(); 47 } 48 } 49 34 50 } // JSC 35 51 -
trunk/Source/JavaScriptCore/bytecode/DeferredCompilationCallback.h
r154824 r165005 42 42 43 43 virtual void compilationDidBecomeReadyAsynchronously(CodeBlock*) = 0; 44 virtual void compilationDidComplete(CodeBlock*, CompilationResult) = 0;44 virtual void compilationDidComplete(CodeBlock*, CompilationResult); 45 45 }; 46 46 -
trunk/Source/JavaScriptCore/debugger/Debugger.cpp
r163844 r165005 139 139 }; 140 140 141 template<typename Functor> 142 void Debugger::forEachCodeBlock(Functor& functor) 143 { 144 m_vm->waitForCompilationsToComplete(); 145 m_vm->heap.forEachCodeBlock(functor); 146 } 147 141 148 Debugger::Debugger(bool isInWorkerThread) 142 149 : m_vm(nullptr) … … 233 240 return; 234 241 SetSteppingModeFunctor functor(this, mode); 235 m_vm->heap.forEachCodeBlock(functor);242 forEachCodeBlock(functor); 236 243 } 237 244 … … 317 324 return; 318 325 ToggleBreakpointFunctor functor(this, breakpoint, enabledOrNot); 319 m_vm->heap.forEachCodeBlock(functor);326 forEachCodeBlock(functor); 320 327 } 321 328 … … 329 336 } 330 337 331 vm-> prepareToDiscardCode();338 vm->waitForCompilationsToComplete(); 332 339 333 340 Recompiler recompiler(this); … … 497 504 return; 498 505 ClearCodeBlockDebuggerRequestsFunctor functor(this); 499 m_vm->heap.forEachCodeBlock(functor);506 forEachCodeBlock(functor); 500 507 } 501 508 … … 522 529 ASSERT(m_vm); 523 530 ClearDebuggerRequestsFunctor functor(globalObject); 524 m_vm->heap.forEachCodeBlock(functor);531 forEachCodeBlock(functor); 525 532 } 526 533 -
trunk/Source/JavaScriptCore/debugger/Debugger.h
r162940 r165005 183 183 void clearDebuggerRequests(JSGlobalObject*); 184 184 185 template<typename Functor> inline void forEachCodeBlock(Functor&); 186 185 187 VM* m_vm; 186 188 HashSet<JSGlobalObject*> m_globalObjects; -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r164764 r165005 1254 1254 jitCode->reconstruct( 1255 1255 exec, codeBlock, CodeOrigin(bytecodeIndex), streamIndex, mustHandleValues); 1256 RefPtr<CodeBlock> replacementCodeBlock = codeBlock->newReplacement(); 1256 1257 CompilationResult forEntryResult = compile( 1257 *vm, codeBlock->newReplacement().get(), codeBlock, FTLForOSREntryMode, bytecodeIndex,1258 *vm, replacementCodeBlock.get(), codeBlock, FTLForOSREntryMode, bytecodeIndex, 1258 1259 mustHandleValues, ToFTLForOSREntryDeferredCompilationCallback::create(codeBlock)); 1259 1260 1260 if (forEntryResult != CompilationSuccessful) 1261 if (forEntryResult != CompilationSuccessful) { 1262 ASSERT(forEntryResult == CompilationDeferred || replacementCodeBlock->hasOneRef()); 1261 1263 return 0; 1262 1264 } 1265 1263 1266 // It's possible that the for-entry compile already succeeded. In that case OSR 1264 1267 // entry will succeed unless we ran out of stack. It's not clear what we should do. -
trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp
r164459 r165005 392 392 return CompilationInvalidated; 393 393 394 if (vm.enabledProfiler())395 return CompilationInvalidated;396 397 Debugger* debugger = codeBlock->globalObject()->debugger();398 if (debugger && (debugger->isStepping() || codeBlock->baselineAlternative()->hasDebuggerRequests()))399 return CompilationInvalidated;400 401 394 bool result; 402 395 if (codeBlock->codeType() == FunctionCode) -
trunk/Source/JavaScriptCore/dfg/DFGToFTLDeferredCompilationCallback.cpp
r164229 r165005 86 86 m_dfgCodeBlock->jitCode()->dfg()->setOptimizationThresholdBasedOnCompilationResult( 87 87 m_dfgCodeBlock.get(), result); 88 89 DeferredCompilationCallback::compilationDidComplete(codeBlock, result); 88 90 } 89 91 -
trunk/Source/JavaScriptCore/dfg/DFGToFTLForOSREntryDeferredCompilationCallback.cpp
r164229 r165005 80 80 case CompilationSuccessful: 81 81 jitCode->osrEntryBlock = codeBlock; 82 return;82 break; 83 83 case CompilationFailed: 84 84 jitCode->osrEntryRetry = 0; 85 85 jitCode->abandonOSREntry = true; 86 return;86 break; 87 87 case CompilationDeferred: 88 return;88 RELEASE_ASSERT_NOT_REACHED(); 89 89 case CompilationInvalidated: 90 90 jitCode->osrEntryRetry = 0; 91 return;91 break; 92 92 } 93 93 94 RELEASE_ASSERT_NOT_REACHED();94 DeferredCompilationCallback::compilationDidComplete(codeBlock, result); 95 95 } 96 96 -
trunk/Source/JavaScriptCore/heap/CodeBlockSet.cpp
r163844 r165005 97 97 } 98 98 99 void CodeBlockSet::remove(CodeBlock* codeBlock) 100 { 101 codeBlock->deref(); 102 m_set.remove(codeBlock); 103 } 104 99 105 void CodeBlockSet::traceMarked(SlotVisitor& visitor) 100 106 { -
trunk/Source/JavaScriptCore/heap/CodeBlockSet.h
r163691 r165005 66 66 void deleteUnmarkedAndUnreferenced(); 67 67 68 void remove(CodeBlock*); 69 68 70 // Trace all marked code blocks. The CodeBlock is free to make use of 69 71 // mayBeExecuting. -
trunk/Source/JavaScriptCore/heap/Heap.h
r164862 r165005 209 209 template<typename T> void releaseSoon(RetainPtr<T>&&); 210 210 #endif 211 212 void removeCodeBlock(CodeBlock* cb) { m_codeBlocks.remove(cb); } 211 213 212 214 private: -
trunk/Source/JavaScriptCore/jit/JITOperations.cpp
r164764 r165005 1200 1200 } 1201 1201 1202 RefPtr<CodeBlock> replacementCodeBlock = codeBlock->newReplacement(); 1202 1203 CompilationResult result = DFG::compile( 1203 vm, codeBlock->newReplacement().get(), 0, DFG::DFGMode, bytecodeIndex,1204 vm, replacementCodeBlock.get(), 0, DFG::DFGMode, bytecodeIndex, 1204 1205 mustHandleValues, JITToDFGDeferredCompilationCallback::create()); 1205 1206 1206 if (result != CompilationSuccessful) 1207 if (result != CompilationSuccessful) { 1208 ASSERT(result == CompilationDeferred || replacementCodeBlock->hasOneRef()); 1207 1209 return encodeResult(0, 0); 1210 } 1208 1211 } 1209 1212 -
trunk/Source/JavaScriptCore/jit/JITToDFGDeferredCompilationCallback.cpp
r163844 r165005 66 66 67 67 codeBlock->alternative()->setOptimizationThresholdBasedOnCompilationResult(result); 68 69 DeferredCompilationCallback::compilationDidComplete(codeBlock, result); 68 70 } 69 71 -
trunk/Source/JavaScriptCore/runtime/VM.cpp
r164683 r165005 513 513 } 514 514 515 void VM:: prepareToDiscardCode()515 void VM::waitForCompilationsToComplete() 516 516 { 517 517 #if ENABLE(DFG_JIT) … … 525 525 void VM::discardAllCode() 526 526 { 527 prepareToDiscardCode();527 waitForCompilationsToComplete(); 528 528 m_codeCache->clear(); 529 529 heap.deleteAllCompiledCode(); … … 567 567 void VM::releaseExecutableMemory() 568 568 { 569 prepareToDiscardCode();569 waitForCompilationsToComplete(); 570 570 571 571 if (entryScope) { … … 873 873 m_enabledProfiler = profiler; 874 874 if (m_enabledProfiler) { 875 waitForCompilationsToComplete(); 875 876 SetEnabledProfilerFunctor functor; 876 877 heap.forEachCodeBlock(functor); -
trunk/Source/JavaScriptCore/runtime/VM.h
r164683 r165005 1 1 /* 2 * Copyright (C) 2008, 2009, 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2008, 2009, 2013, 2014 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 499 499 CodeCache* codeCache() { return m_codeCache.get(); } 500 500 501 void prepareToDiscardCode();501 void waitForCompilationsToComplete(); 502 502 503 503 JS_EXPORT_PRIVATE void discardAllCode();
Note: See TracChangeset
for help on using the changeset viewer.