a571471a66b41e0a634fde0fe5263ffa40e4b4ad
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGPlan.cpp
1 /*
2  * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "DFGPlan.h"
28
29 #if ENABLE(DFG_JIT)
30
31 #include "DFGArgumentsEliminationPhase.h"
32 #include "DFGBackwardsPropagationPhase.h"
33 #include "DFGByteCodeParser.h"
34 #include "DFGCFAPhase.h"
35 #include "DFGCFGSimplificationPhase.h"
36 #include "DFGCPSRethreadingPhase.h"
37 #include "DFGCSEPhase.h"
38 #include "DFGCleanUpPhase.h"
39 #include "DFGConstantFoldingPhase.h"
40 #include "DFGConstantHoistingPhase.h"
41 #include "DFGCriticalEdgeBreakingPhase.h"
42 #include "DFGDCEPhase.h"
43 #include "DFGFailedFinalizer.h"
44 #include "DFGFixupPhase.h"
45 #include "DFGGraphSafepoint.h"
46 #include "DFGIntegerCheckCombiningPhase.h"
47 #include "DFGIntegerRangeOptimizationPhase.h"
48 #include "DFGInvalidationPointInjectionPhase.h"
49 #include "DFGJITCompiler.h"
50 #include "DFGLICMPhase.h"
51 #include "DFGLiveCatchVariablePreservationPhase.h"
52 #include "DFGLivenessAnalysisPhase.h"
53 #include "DFGLoopPreHeaderCreationPhase.h"
54 #include "DFGMaximalFlushInsertionPhase.h"
55 #include "DFGMovHintRemovalPhase.h"
56 #include "DFGOSRAvailabilityAnalysisPhase.h"
57 #include "DFGOSREntrypointCreationPhase.h"
58 #include "DFGObjectAllocationSinkingPhase.h"
59 #include "DFGPhantomInsertionPhase.h"
60 #include "DFGPredictionInjectionPhase.h"
61 #include "DFGPredictionPropagationPhase.h"
62 #include "DFGPutStackSinkingPhase.h"
63 #include "DFGSSAConversionPhase.h"
64 #include "DFGSSALoweringPhase.h"
65 #include "DFGStackLayoutPhase.h"
66 #include "DFGStaticExecutionCountEstimationPhase.h"
67 #include "DFGStoreBarrierClusteringPhase.h"
68 #include "DFGStoreBarrierInsertionPhase.h"
69 #include "DFGStrengthReductionPhase.h"
70 #include "DFGTierUpCheckInjectionPhase.h"
71 #include "DFGTypeCheckHoistingPhase.h"
72 #include "DFGUnificationPhase.h"
73 #include "DFGValidate.h"
74 #include "DFGVarargsForwardingPhase.h"
75 #include "DFGVirtualRegisterAllocationPhase.h"
76 #include "DFGWatchpointCollectionPhase.h"
77 #include "JSCInlines.h"
78 #include "OperandsInlines.h"
79 #include "ProfilerDatabase.h"
80 #include "TrackedReferences.h"
81 #include "VMInlines.h"
82 #include <wtf/CurrentTime.h>
83
84 #if ENABLE(FTL_JIT)
85 #include "FTLCapabilities.h"
86 #include "FTLCompile.h"
87 #include "FTLFail.h"
88 #include "FTLLink.h"
89 #include "FTLLowerDFGToB3.h"
90 #include "FTLState.h"
91 #endif
92
93 namespace JSC {
94
95 extern Seconds totalDFGCompileTime;
96 extern Seconds totalFTLCompileTime;
97 extern Seconds totalFTLDFGCompileTime;
98 extern Seconds totalFTLB3CompileTime;
99
100 }
101
102 namespace JSC { namespace DFG {
103
104 namespace {
105
106 void dumpAndVerifyGraph(Graph& graph, const char* text, bool forceDump = false)
107 {
108     GraphDumpMode modeForFinalValidate = DumpGraph;
109     if (verboseCompilationEnabled(graph.m_plan.mode) || forceDump) {
110         dataLog(text, "\n");
111         graph.dump();
112         modeForFinalValidate = DontDumpGraph;
113     }
114     if (validationEnabled())
115         validate(graph, modeForFinalValidate);
116 }
117
118 Profiler::CompilationKind profilerCompilationKindForMode(CompilationMode mode)
119 {
120     switch (mode) {
121     case InvalidCompilationMode:
122         RELEASE_ASSERT_NOT_REACHED();
123         return Profiler::DFG;
124     case DFGMode:
125         return Profiler::DFG;
126     case FTLMode:
127         return Profiler::FTL;
128     case FTLForOSREntryMode:
129         return Profiler::FTLForOSREntry;
130     }
131     RELEASE_ASSERT_NOT_REACHED();
132     return Profiler::DFG;
133 }
134
135 } // anonymous namespace
136
137 Plan::Plan(CodeBlock* passedCodeBlock, CodeBlock* profiledDFGCodeBlock,
138     CompilationMode mode, unsigned osrEntryBytecodeIndex,
139     const Operands<JSValue>& mustHandleValues)
140     : vm(passedCodeBlock->vm())
141     , codeBlock(passedCodeBlock)
142     , profiledDFGCodeBlock(profiledDFGCodeBlock)
143     , mode(mode)
144     , osrEntryBytecodeIndex(osrEntryBytecodeIndex)
145     , mustHandleValues(mustHandleValues)
146     , compilation(UNLIKELY(vm->m_perBytecodeProfiler) ? adoptRef(new Profiler::Compilation(vm->m_perBytecodeProfiler->ensureBytecodesFor(codeBlock), profilerCompilationKindForMode(mode))) : nullptr)
147     , inlineCallFrames(adoptRef(new InlineCallFrameSet()))
148     , identifiers(codeBlock)
149     , weakReferences(codeBlock)
150     , stage(Preparing)
151 {
152 }
153
154 Plan::~Plan()
155 {
156 }
157
158 bool Plan::computeCompileTimes() const
159 {
160     return reportCompileTimes()
161         || Options::reportTotalCompileTimes()
162         || (vm && vm->m_perBytecodeProfiler);
163 }
164
165 bool Plan::reportCompileTimes() const
166 {
167     return Options::reportCompileTimes()
168         || Options::reportDFGCompileTimes()
169         || (Options::reportFTLCompileTimes() && isFTL(mode));
170 }
171
172 void Plan::compileInThread(ThreadData* threadData)
173 {
174     this->threadData = threadData;
175     
176     MonotonicTime before { };
177     CString codeBlockName;
178     if (UNLIKELY(computeCompileTimes()))
179         before = MonotonicTime::now();
180     if (UNLIKELY(reportCompileTimes()))
181         codeBlockName = toCString(*codeBlock);
182     
183     CompilationScope compilationScope;
184
185     if (logCompilationChanges(mode) || Options::reportDFGPhaseTimes())
186         dataLog("DFG(Plan) compiling ", *codeBlock, " with ", mode, ", number of instructions = ", codeBlock->instructionCount(), "\n");
187
188     CompilationPath path = compileInThreadImpl();
189
190     RELEASE_ASSERT(path == CancelPath || finalizer);
191     RELEASE_ASSERT((path == CancelPath) == (stage == Cancelled));
192     
193     MonotonicTime after { };
194     if (UNLIKELY(computeCompileTimes())) {
195         after = MonotonicTime::now();
196     
197         if (Options::reportTotalCompileTimes()) {
198             if (isFTL(mode)) {
199                 totalFTLCompileTime += after - before;
200                 totalFTLDFGCompileTime += m_timeBeforeFTL - before;
201                 totalFTLB3CompileTime += after - m_timeBeforeFTL;
202             } else
203                 totalDFGCompileTime += after - before;
204         }
205     }
206     const char* pathName = nullptr;
207     switch (path) {
208     case FailPath:
209         pathName = "N/A (fail)";
210         break;
211     case DFGPath:
212         pathName = "DFG";
213         break;
214     case FTLPath:
215         pathName = "FTL";
216         break;
217     case CancelPath:
218         pathName = "Cancelled";
219         break;
220     default:
221         RELEASE_ASSERT_NOT_REACHED();
222         break;
223     }
224     if (codeBlock) { // codeBlock will be null if the compilation was cancelled.
225         if (path == FTLPath)
226             CODEBLOCK_LOG_EVENT(codeBlock, "ftlCompile", ("took ", (after - before).milliseconds(), " ms (DFG: ", (m_timeBeforeFTL - before).milliseconds(), ", B3: ", (after - m_timeBeforeFTL).milliseconds(), ") with ", pathName));
227         else
228             CODEBLOCK_LOG_EVENT(codeBlock, "dfgCompile", ("took ", (after - before).milliseconds(), " ms with ", pathName));
229     }
230     if (UNLIKELY(reportCompileTimes())) {
231         dataLog("Optimized ", codeBlockName, " using ", mode, " with ", pathName, " into ", finalizer ? finalizer->codeSize() : 0, " bytes in ", (after - before).milliseconds(), " ms");
232         if (path == FTLPath)
233             dataLog(" (DFG: ", (m_timeBeforeFTL - before).milliseconds(), ", B3: ", (after - m_timeBeforeFTL).milliseconds(), ")");
234         dataLog(".\n");
235     }
236 }
237
238 Plan::CompilationPath Plan::compileInThreadImpl()
239 {
240     cleanMustHandleValuesIfNecessary();
241     
242     if (verboseCompilationEnabled(mode) && osrEntryBytecodeIndex != UINT_MAX) {
243         dataLog("\n");
244         dataLog("Compiler must handle OSR entry from bc#", osrEntryBytecodeIndex, " with values: ", mustHandleValues, "\n");
245         dataLog("\n");
246     }
247     
248     Graph dfg(*vm, *this);
249     parse(dfg);
250
251     codeBlock->setCalleeSaveRegisters(RegisterSet::dfgCalleeSaveRegisters());
252
253     bool changed = false;
254
255 #define RUN_PHASE(phase)                                         \
256     do {                                                         \
257         if (Options::safepointBeforeEachPhase()) {               \
258             Safepoint::Result safepointResult;                   \
259             {                                                    \
260                 GraphSafepoint safepoint(dfg, safepointResult);  \
261             }                                                    \
262             if (safepointResult.didGetCancelled())               \
263                 return CancelPath;                               \
264         }                                                        \
265         changed |= phase(dfg);                                   \
266     } while (false);                                             \
267
268     
269     // By this point the DFG bytecode parser will have potentially mutated various tables
270     // in the CodeBlock. This is a good time to perform an early shrink, which is more
271     // powerful than a late one. It's safe to do so because we haven't generated any code
272     // that references any of the tables directly, yet.
273     codeBlock->shrinkToFit(CodeBlock::EarlyShrink);
274
275     if (validationEnabled())
276         validate(dfg);
277     
278     if (Options::dumpGraphAfterParsing()) {
279         dataLog("Graph after parsing:\n");
280         dfg.dump();
281     }
282
283     RUN_PHASE(performLiveCatchVariablePreservationPhase);
284
285     if (Options::useMaximalFlushInsertionPhase())
286         RUN_PHASE(performMaximalFlushInsertion);
287     
288     RUN_PHASE(performCPSRethreading);
289     RUN_PHASE(performUnification);
290     RUN_PHASE(performPredictionInjection);
291     
292     RUN_PHASE(performStaticExecutionCountEstimation);
293     
294     if (mode == FTLForOSREntryMode) {
295         bool result = performOSREntrypointCreation(dfg);
296         if (!result) {
297             finalizer = std::make_unique<FailedFinalizer>(*this);
298             return FailPath;
299         }
300         RUN_PHASE(performCPSRethreading);
301     }
302     
303     if (validationEnabled())
304         validate(dfg);
305     
306     RUN_PHASE(performBackwardsPropagation);
307     RUN_PHASE(performPredictionPropagation);
308     RUN_PHASE(performFixup);
309     RUN_PHASE(performInvalidationPointInjection);
310     RUN_PHASE(performTypeCheckHoisting);
311     
312     dfg.m_fixpointState = FixpointNotConverged;
313     
314     // For now we're back to avoiding a fixpoint. Note that we've ping-ponged on this decision
315     // many times. For maximum throughput, it's best to fixpoint. But the throughput benefit is
316     // small and not likely to show up in FTL anyway. On the other hand, not fixpointing means
317     // that the compiler compiles more quickly. We want the third tier to compile quickly, which
318     // not fixpointing accomplishes; and the fourth tier shouldn't need a fixpoint.
319     if (validationEnabled())
320         validate(dfg);
321         
322     RUN_PHASE(performStrengthReduction);
323     RUN_PHASE(performCPSRethreading);
324     RUN_PHASE(performCFA);
325     RUN_PHASE(performConstantFolding);
326     changed = false;
327     RUN_PHASE(performCFGSimplification);
328     RUN_PHASE(performLocalCSE);
329     
330     if (validationEnabled())
331         validate(dfg);
332     
333     RUN_PHASE(performCPSRethreading);
334     if (!isFTL(mode)) {
335         // Only run this if we're not FTLing, because currently for a LoadVarargs that is forwardable and
336         // in a non-varargs inlined call frame, this will generate ForwardVarargs while the FTL
337         // ArgumentsEliminationPhase will create a sequence of GetStack+PutStacks. The GetStack+PutStack
338         // sequence then gets sunk, eliminating anything that looks like an escape for subsequent phases,
339         // while the ForwardVarargs doesn't get simplified until later (or not at all) and looks like an
340         // escape for all of the arguments. This then disables object allocation sinking.
341         //
342         // So, for now, we just disable this phase for the FTL.
343         //
344         // If we wanted to enable it, we'd have to do any of the following:
345         // - Enable ForwardVarargs->GetStack+PutStack strength reduction, and have that run before
346         //   PutStack sinking and object allocation sinking.
347         // - Make VarargsForwarding emit a GetLocal+SetLocal sequence, that we can later turn into
348         //   GetStack+PutStack.
349         //
350         // But, it's not super valuable to enable those optimizations, since the FTL
351         // ArgumentsEliminationPhase does everything that this phase does, and it doesn't introduce this
352         // pathology.
353         
354         RUN_PHASE(performVarargsForwarding); // Do this after CFG simplification and CPS rethreading.
355     }
356     if (changed) {
357         RUN_PHASE(performCFA);
358         RUN_PHASE(performConstantFolding);
359     }
360     
361     // If we're doing validation, then run some analyses, to give them an opportunity
362     // to self-validate. Now is as good a time as any to do this.
363     if (validationEnabled()) {
364         dfg.ensureCPSDominators();
365         dfg.ensureCPSNaturalLoops();
366     }
367
368     switch (mode) {
369     case DFGMode: {
370         dfg.m_fixpointState = FixpointConverged;
371     
372         RUN_PHASE(performTierUpCheckInjection);
373
374         RUN_PHASE(performFastStoreBarrierInsertion);
375         RUN_PHASE(performStoreBarrierClustering);
376         RUN_PHASE(performCleanUp);
377         RUN_PHASE(performCPSRethreading);
378         RUN_PHASE(performDCE);
379         RUN_PHASE(performPhantomInsertion);
380         RUN_PHASE(performStackLayout);
381         RUN_PHASE(performVirtualRegisterAllocation);
382         RUN_PHASE(performWatchpointCollection);
383         dumpAndVerifyGraph(dfg, "Graph after optimization:");
384         
385         JITCompiler dataFlowJIT(dfg);
386         if (codeBlock->codeType() == FunctionCode)
387             dataFlowJIT.compileFunction();
388         else
389             dataFlowJIT.compile();
390         
391         return DFGPath;
392     }
393     
394     case FTLMode:
395     case FTLForOSREntryMode: {
396 #if ENABLE(FTL_JIT)
397         if (FTL::canCompile(dfg) == FTL::CannotCompile) {
398             finalizer = std::make_unique<FailedFinalizer>(*this);
399             return FailPath;
400         }
401         
402         RUN_PHASE(performCleanUp); // Reduce the graph size a bit.
403         RUN_PHASE(performCriticalEdgeBreaking);
404         if (Options::createPreHeaders())
405             RUN_PHASE(performLoopPreHeaderCreation);
406         RUN_PHASE(performCPSRethreading);
407         RUN_PHASE(performSSAConversion);
408         RUN_PHASE(performSSALowering);
409         
410         // Ideally, these would be run to fixpoint with the object allocation sinking phase.
411         RUN_PHASE(performArgumentsElimination);
412         if (Options::usePutStackSinking())
413             RUN_PHASE(performPutStackSinking);
414         
415         RUN_PHASE(performConstantHoisting);
416         RUN_PHASE(performGlobalCSE);
417         RUN_PHASE(performLivenessAnalysis);
418         RUN_PHASE(performCFA);
419         RUN_PHASE(performConstantFolding);
420         RUN_PHASE(performCleanUp); // Reduce the graph size a lot.
421         changed = false;
422         RUN_PHASE(performStrengthReduction);
423         if (Options::useObjectAllocationSinking()) {
424             RUN_PHASE(performCriticalEdgeBreaking);
425             RUN_PHASE(performObjectAllocationSinking);
426         }
427         if (changed) {
428             // State-at-tail and state-at-head will be invalid if we did strength reduction since
429             // it might increase live ranges.
430             RUN_PHASE(performLivenessAnalysis);
431             RUN_PHASE(performCFA);
432             RUN_PHASE(performConstantFolding);
433         }
434         
435         // Currently, this relies on pre-headers still being valid. That precludes running CFG
436         // simplification before it, unless we re-created the pre-headers. There wouldn't be anything
437         // wrong with running LICM earlier, if we wanted to put other CFG transforms above this point.
438         // Alternatively, we could run loop pre-header creation after SSA conversion - but if we did that
439         // then we'd need to do some simple SSA fix-up.
440         RUN_PHASE(performLivenessAnalysis);
441         RUN_PHASE(performCFA);
442         RUN_PHASE(performLICM);
443
444         // FIXME: Currently: IntegerRangeOptimization *must* be run after LICM.
445         //
446         // IntegerRangeOptimization makes changes on nodes based on preceding blocks
447         // and nodes. LICM moves nodes which can invalidates assumptions used
448         // by IntegerRangeOptimization.
449         //
450         // Ideally, the dependencies should be explicit. See https://bugs.webkit.org/show_bug.cgi?id=157534.
451         RUN_PHASE(performLivenessAnalysis);
452         RUN_PHASE(performIntegerRangeOptimization);
453         
454         RUN_PHASE(performCleanUp);
455         RUN_PHASE(performIntegerCheckCombining);
456         RUN_PHASE(performGlobalCSE);
457         
458         // At this point we're not allowed to do any further code motion because our reasoning
459         // about code motion assumes that it's OK to insert GC points in random places.
460         dfg.m_fixpointState = FixpointConverged;
461         
462         RUN_PHASE(performLivenessAnalysis);
463         RUN_PHASE(performCFA);
464         RUN_PHASE(performGlobalStoreBarrierInsertion);
465         RUN_PHASE(performStoreBarrierClustering);
466         if (Options::useMovHintRemoval())
467             RUN_PHASE(performMovHintRemoval);
468         RUN_PHASE(performCleanUp);
469         RUN_PHASE(performDCE); // We rely on this to kill dead code that won't be recognized as dead by B3.
470         RUN_PHASE(performStackLayout);
471         RUN_PHASE(performLivenessAnalysis);
472         RUN_PHASE(performOSRAvailabilityAnalysis);
473         RUN_PHASE(performWatchpointCollection);
474         
475         if (FTL::canCompile(dfg) == FTL::CannotCompile) {
476             finalizer = std::make_unique<FailedFinalizer>(*this);
477             return FailPath;
478         }
479
480         dumpAndVerifyGraph(dfg, "Graph just before FTL lowering:", shouldDumpDisassembly(mode));
481
482         // Flash a safepoint in case the GC wants some action.
483         Safepoint::Result safepointResult;
484         {
485             GraphSafepoint safepoint(dfg, safepointResult);
486         }
487         if (safepointResult.didGetCancelled())
488             return CancelPath;
489
490         FTL::State state(dfg);
491         FTL::lowerDFGToB3(state);
492         
493         if (UNLIKELY(computeCompileTimes()))
494             m_timeBeforeFTL = MonotonicTime::now();
495         
496         if (Options::b3AlwaysFailsBeforeCompile()) {
497             FTL::fail(state);
498             return FTLPath;
499         }
500         
501         FTL::compile(state, safepointResult);
502         if (safepointResult.didGetCancelled())
503             return CancelPath;
504         
505         if (Options::b3AlwaysFailsBeforeLink()) {
506             FTL::fail(state);
507             return FTLPath;
508         }
509         
510         if (state.allocationFailed) {
511             FTL::fail(state);
512             return FTLPath;
513         }
514
515         FTL::link(state);
516         
517         if (state.allocationFailed) {
518             FTL::fail(state);
519             return FTLPath;
520         }
521         
522         return FTLPath;
523 #else
524         RELEASE_ASSERT_NOT_REACHED();
525         return FailPath;
526 #endif // ENABLE(FTL_JIT)
527     }
528         
529     default:
530         RELEASE_ASSERT_NOT_REACHED();
531         return FailPath;
532     }
533
534 #undef RUN_PHASE
535 }
536
537 bool Plan::isStillValid()
538 {
539     CodeBlock* replacement = codeBlock->replacement();
540     if (!replacement)
541         return false;
542     // FIXME: This is almost certainly not necessary. There's no way for the baseline
543     // code to be replaced during a compilation, except if we delete the plan, in which
544     // case we wouldn't be here.
545     // https://bugs.webkit.org/show_bug.cgi?id=132707
546     if (codeBlock->alternative() != replacement->baselineVersion())
547         return false;
548     if (!watchpoints.areStillValid())
549         return false;
550     return true;
551 }
552
553 void Plan::reallyAdd(CommonData* commonData)
554 {
555     watchpoints.reallyAdd(codeBlock, *commonData);
556     identifiers.reallyAdd(*vm, commonData);
557     weakReferences.reallyAdd(*vm, commonData);
558     transitions.reallyAdd(*vm, commonData);
559 }
560
561 void Plan::notifyCompiling()
562 {
563     stage = Compiling;
564 }
565
566 void Plan::notifyReady()
567 {
568     callback->compilationDidBecomeReadyAsynchronously(codeBlock, profiledDFGCodeBlock);
569     stage = Ready;
570 }
571
572 CompilationResult Plan::finalizeWithoutNotifyingCallback()
573 {
574     // We will establish new references from the code block to things. So, we need a barrier.
575     vm->heap.writeBarrier(codeBlock);
576     
577     if (!isStillValid()) {
578         CODEBLOCK_LOG_EVENT(codeBlock, "dfgFinalize", ("invalidated"));
579         return CompilationInvalidated;
580     }
581
582     bool result;
583     if (codeBlock->codeType() == FunctionCode)
584         result = finalizer->finalizeFunction();
585     else
586         result = finalizer->finalize();
587     
588     if (!result) {
589         CODEBLOCK_LOG_EVENT(codeBlock, "dfgFinalize", ("failed"));
590         return CompilationFailed;
591     }
592     
593     reallyAdd(codeBlock->jitCode()->dfgCommon());
594     
595     if (validationEnabled()) {
596         TrackedReferences trackedReferences;
597         
598         for (WriteBarrier<JSCell>& reference : codeBlock->jitCode()->dfgCommon()->weakReferences)
599             trackedReferences.add(reference.get());
600         for (WriteBarrier<Structure>& reference : codeBlock->jitCode()->dfgCommon()->weakStructureReferences)
601             trackedReferences.add(reference.get());
602         for (WriteBarrier<Unknown>& constant : codeBlock->constants())
603             trackedReferences.add(constant.get());
604
605         for (auto* inlineCallFrame : *inlineCallFrames) {
606             ASSERT(inlineCallFrame->baselineCodeBlock.get());
607             trackedReferences.add(inlineCallFrame->baselineCodeBlock.get());
608         }
609         
610         // Check that any other references that we have anywhere in the JITCode are also
611         // tracked either strongly or weakly.
612         codeBlock->jitCode()->validateReferences(trackedReferences);
613     }
614     
615     CODEBLOCK_LOG_EVENT(codeBlock, "dfgFinalize", ("succeeded"));
616     return CompilationSuccessful;
617 }
618
619 void Plan::finalizeAndNotifyCallback()
620 {
621     callback->compilationDidComplete(codeBlock, profiledDFGCodeBlock, finalizeWithoutNotifyingCallback());
622 }
623
624 CompilationKey Plan::key()
625 {
626     return CompilationKey(codeBlock->alternative(), mode);
627 }
628
629 void Plan::checkLivenessAndVisitChildren(SlotVisitor& visitor)
630 {
631     if (!isKnownToBeLiveDuringGC())
632         return;
633
634     cleanMustHandleValuesIfNecessary();
635     for (unsigned i = mustHandleValues.size(); i--;)
636         visitor.appendUnbarriered(mustHandleValues[i]);
637
638     visitor.appendUnbarriered(codeBlock);
639     visitor.appendUnbarriered(codeBlock->alternative());
640     visitor.appendUnbarriered(profiledDFGCodeBlock);
641
642     if (inlineCallFrames) {
643         for (auto* inlineCallFrame : *inlineCallFrames) {
644             ASSERT(inlineCallFrame->baselineCodeBlock.get());
645             visitor.appendUnbarriered(inlineCallFrame->baselineCodeBlock.get());
646         }
647     }
648
649     weakReferences.visitChildren(visitor);
650     transitions.visitChildren(visitor);
651 }
652
653 bool Plan::isKnownToBeLiveDuringGC()
654 {
655     if (stage == Cancelled)
656         return false;
657     if (!Heap::isMarked(codeBlock->ownerExecutable()))
658         return false;
659     if (!Heap::isMarked(codeBlock->alternative()))
660         return false;
661     if (!!profiledDFGCodeBlock && !Heap::isMarked(profiledDFGCodeBlock))
662         return false;
663     return true;
664 }
665
666 void Plan::cancel()
667 {
668     vm = nullptr;
669     codeBlock = nullptr;
670     profiledDFGCodeBlock = nullptr;
671     mustHandleValues.clear();
672     compilation = nullptr;
673     finalizer = nullptr;
674     inlineCallFrames = nullptr;
675     watchpoints = DesiredWatchpoints();
676     identifiers = DesiredIdentifiers();
677     weakReferences = DesiredWeakReferences();
678     transitions = DesiredTransitions();
679     callback = nullptr;
680     stage = Cancelled;
681 }
682
683 void Plan::cleanMustHandleValuesIfNecessary()
684 {
685     LockHolder locker(mustHandleValueCleaningLock);
686     
687     if (!mustHandleValuesMayIncludeGarbage)
688         return;
689     
690     mustHandleValuesMayIncludeGarbage = false;
691     
692     if (!codeBlock)
693         return;
694     
695     if (!mustHandleValues.numberOfLocals())
696         return;
697     
698     CodeBlock* alternative = codeBlock->alternative();
699     FastBitVector liveness = alternative->livenessAnalysis().getLivenessInfoAtBytecodeOffset(alternative, osrEntryBytecodeIndex);
700     
701     for (unsigned local = mustHandleValues.numberOfLocals(); local--;) {
702         if (!liveness[local])
703             mustHandleValues.local(local) = jsUndefined();
704     }
705 }
706
707 } } // namespace JSC::DFG
708
709 #endif // ENABLE(DFG_JIT)
710