Harden how the compiler references GC objects
[WebKit.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 double totalDFGCompileTime;
96 extern double totalFTLCompileTime;
97 extern double totalFTLDFGCompileTime;
98 extern double 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(vm->m_perBytecodeProfiler ? adoptRef(new Profiler::Compilation(vm->m_perBytecodeProfiler->ensureBytecodesFor(codeBlock), profilerCompilationKindForMode(mode))) : 0)
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(LongLivedState& longLivedState, ThreadData* threadData)
173 {
174     this->threadData = threadData;
175     
176     double before = 0;
177     CString codeBlockName;
178     if (UNLIKELY(computeCompileTimes()))
179         before = monotonicallyIncreasingTimeMS();
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(longLivedState);
189
190     RELEASE_ASSERT(path == CancelPath || finalizer);
191     RELEASE_ASSERT((path == CancelPath) == (stage == Cancelled));
192     
193     double after = 0;
194     if (UNLIKELY(computeCompileTimes())) {
195         after = monotonicallyIncreasingTimeMS();
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, " ms (DFG: ", m_timeBeforeFTL - before, ", B3: ", after - m_timeBeforeFTL, ") with ", pathName));
227         else
228             CODEBLOCK_LOG_EVENT(codeBlock, "dfgCompile", ("took ", after - before, " 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, " ms");
232         if (path == FTLPath)
233             dataLog(" (DFG: ", m_timeBeforeFTL - before, ", B3: ", after - m_timeBeforeFTL, ")");
234         dataLog(".\n");
235     }
236 }
237
238 Plan::CompilationPath Plan::compileInThreadImpl(LongLivedState& longLivedState)
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, longLivedState);
249     
250     if (!parse(dfg)) {
251         finalizer = std::make_unique<FailedFinalizer>(*this);
252         return FailPath;
253     }
254
255     codeBlock->setCalleeSaveRegisters(RegisterSet::dfgCalleeSaveRegisters());
256
257     bool changed = false;
258
259 #define RUN_PHASE(phase)                                         \
260     do {                                                         \
261         if (Options::safepointBeforeEachPhase()) {               \
262             Safepoint::Result safepointResult;                   \
263             {                                                    \
264                 GraphSafepoint safepoint(dfg, safepointResult);  \
265             }                                                    \
266             if (safepointResult.didGetCancelled())               \
267                 return CancelPath;                               \
268         }                                                        \
269         changed |= phase(dfg);                                   \
270     } while (false);                                             \
271
272     
273     // By this point the DFG bytecode parser will have potentially mutated various tables
274     // in the CodeBlock. This is a good time to perform an early shrink, which is more
275     // powerful than a late one. It's safe to do so because we haven't generated any code
276     // that references any of the tables directly, yet.
277     codeBlock->shrinkToFit(CodeBlock::EarlyShrink);
278
279     if (validationEnabled())
280         validate(dfg);
281     
282     if (Options::dumpGraphAfterParsing()) {
283         dataLog("Graph after parsing:\n");
284         dfg.dump();
285     }
286
287     RUN_PHASE(performLiveCatchVariablePreservationPhase);
288
289     if (Options::useMaximalFlushInsertionPhase())
290         RUN_PHASE(performMaximalFlushInsertion);
291     
292     RUN_PHASE(performCPSRethreading);
293     RUN_PHASE(performUnification);
294     RUN_PHASE(performPredictionInjection);
295     
296     RUN_PHASE(performStaticExecutionCountEstimation);
297     
298     if (mode == FTLForOSREntryMode) {
299         bool result = performOSREntrypointCreation(dfg);
300         if (!result) {
301             finalizer = std::make_unique<FailedFinalizer>(*this);
302             return FailPath;
303         }
304         RUN_PHASE(performCPSRethreading);
305     }
306     
307     if (validationEnabled())
308         validate(dfg);
309     
310     RUN_PHASE(performBackwardsPropagation);
311     RUN_PHASE(performPredictionPropagation);
312     RUN_PHASE(performFixup);
313     RUN_PHASE(performInvalidationPointInjection);
314     RUN_PHASE(performTypeCheckHoisting);
315     
316     dfg.m_fixpointState = FixpointNotConverged;
317     
318     // For now we're back to avoiding a fixpoint. Note that we've ping-ponged on this decision
319     // many times. For maximum throughput, it's best to fixpoint. But the throughput benefit is
320     // small and not likely to show up in FTL anyway. On the other hand, not fixpointing means
321     // that the compiler compiles more quickly. We want the third tier to compile quickly, which
322     // not fixpointing accomplishes; and the fourth tier shouldn't need a fixpoint.
323     if (validationEnabled())
324         validate(dfg);
325         
326     RUN_PHASE(performStrengthReduction);
327     RUN_PHASE(performCPSRethreading);
328     RUN_PHASE(performCFA);
329     RUN_PHASE(performConstantFolding);
330     changed = false;
331     RUN_PHASE(performCFGSimplification);
332     RUN_PHASE(performLocalCSE);
333     
334     if (validationEnabled())
335         validate(dfg);
336     
337     RUN_PHASE(performCPSRethreading);
338     if (!isFTL(mode)) {
339         // Only run this if we're not FTLing, because currently for a LoadVarargs that is forwardable and
340         // in a non-varargs inlined call frame, this will generate ForwardVarargs while the FTL
341         // ArgumentsEliminationPhase will create a sequence of GetStack+PutStacks. The GetStack+PutStack
342         // sequence then gets sunk, eliminating anything that looks like an escape for subsequent phases,
343         // while the ForwardVarargs doesn't get simplified until later (or not at all) and looks like an
344         // escape for all of the arguments. This then disables object allocation sinking.
345         //
346         // So, for now, we just disable this phase for the FTL.
347         //
348         // If we wanted to enable it, we'd have to do any of the following:
349         // - Enable ForwardVarargs->GetStack+PutStack strength reduction, and have that run before
350         //   PutStack sinking and object allocation sinking.
351         // - Make VarargsForwarding emit a GetLocal+SetLocal sequence, that we can later turn into
352         //   GetStack+PutStack.
353         //
354         // But, it's not super valuable to enable those optimizations, since the FTL
355         // ArgumentsEliminationPhase does everything that this phase does, and it doesn't introduce this
356         // pathology.
357         
358         RUN_PHASE(performVarargsForwarding); // Do this after CFG simplification and CPS rethreading.
359     }
360     if (changed) {
361         RUN_PHASE(performCFA);
362         RUN_PHASE(performConstantFolding);
363     }
364     
365     // If we're doing validation, then run some analyses, to give them an opportunity
366     // to self-validate. Now is as good a time as any to do this.
367     if (validationEnabled()) {
368         dfg.ensureDominators();
369         dfg.ensureNaturalLoops();
370         dfg.ensurePrePostNumbering();
371     }
372
373     switch (mode) {
374     case DFGMode: {
375         dfg.m_fixpointState = FixpointConverged;
376     
377         RUN_PHASE(performTierUpCheckInjection);
378
379         RUN_PHASE(performFastStoreBarrierInsertion);
380         RUN_PHASE(performStoreBarrierClustering);
381         RUN_PHASE(performCleanUp);
382         RUN_PHASE(performCPSRethreading);
383         RUN_PHASE(performDCE);
384         RUN_PHASE(performPhantomInsertion);
385         RUN_PHASE(performStackLayout);
386         RUN_PHASE(performVirtualRegisterAllocation);
387         RUN_PHASE(performWatchpointCollection);
388         dumpAndVerifyGraph(dfg, "Graph after optimization:");
389         
390         JITCompiler dataFlowJIT(dfg);
391         if (codeBlock->codeType() == FunctionCode)
392             dataFlowJIT.compileFunction();
393         else
394             dataFlowJIT.compile();
395         
396         return DFGPath;
397     }
398     
399     case FTLMode:
400     case FTLForOSREntryMode: {
401 #if ENABLE(FTL_JIT)
402         if (FTL::canCompile(dfg) == FTL::CannotCompile) {
403             finalizer = std::make_unique<FailedFinalizer>(*this);
404             return FailPath;
405         }
406         
407         RUN_PHASE(performCleanUp); // Reduce the graph size a bit.
408         RUN_PHASE(performCriticalEdgeBreaking);
409         if (Options::createPreHeaders())
410             RUN_PHASE(performLoopPreHeaderCreation);
411         RUN_PHASE(performCPSRethreading);
412         RUN_PHASE(performSSAConversion);
413         RUN_PHASE(performSSALowering);
414         
415         // Ideally, these would be run to fixpoint with the object allocation sinking phase.
416         RUN_PHASE(performArgumentsElimination);
417         if (Options::usePutStackSinking())
418             RUN_PHASE(performPutStackSinking);
419         
420         RUN_PHASE(performConstantHoisting);
421         RUN_PHASE(performGlobalCSE);
422         RUN_PHASE(performLivenessAnalysis);
423         RUN_PHASE(performCFA);
424         RUN_PHASE(performConstantFolding);
425         RUN_PHASE(performCleanUp); // Reduce the graph size a lot.
426         changed = false;
427         RUN_PHASE(performStrengthReduction);
428         if (Options::useObjectAllocationSinking()) {
429             RUN_PHASE(performCriticalEdgeBreaking);
430             RUN_PHASE(performObjectAllocationSinking);
431         }
432         if (changed) {
433             // State-at-tail and state-at-head will be invalid if we did strength reduction since
434             // it might increase live ranges.
435             RUN_PHASE(performLivenessAnalysis);
436             RUN_PHASE(performCFA);
437             RUN_PHASE(performConstantFolding);
438         }
439         
440         // Currently, this relies on pre-headers still being valid. That precludes running CFG
441         // simplification before it, unless we re-created the pre-headers. There wouldn't be anything
442         // wrong with running LICM earlier, if we wanted to put other CFG transforms above this point.
443         // Alternatively, we could run loop pre-header creation after SSA conversion - but if we did that
444         // then we'd need to do some simple SSA fix-up.
445         RUN_PHASE(performLivenessAnalysis);
446         RUN_PHASE(performCFA);
447         RUN_PHASE(performLICM);
448
449         // FIXME: Currently: IntegerRangeOptimization *must* be run after LICM.
450         //
451         // IntegerRangeOptimization makes changes on nodes based on preceding blocks
452         // and nodes. LICM moves nodes which can invalidates assumptions used
453         // by IntegerRangeOptimization.
454         //
455         // Ideally, the dependencies should be explicit. See https://bugs.webkit.org/show_bug.cgi?id=157534.
456         RUN_PHASE(performLivenessAnalysis);
457         RUN_PHASE(performIntegerRangeOptimization);
458         
459         RUN_PHASE(performCleanUp);
460         RUN_PHASE(performIntegerCheckCombining);
461         RUN_PHASE(performGlobalCSE);
462         
463         // At this point we're not allowed to do any further code motion because our reasoning
464         // about code motion assumes that it's OK to insert GC points in random places.
465         dfg.m_fixpointState = FixpointConverged;
466         
467         RUN_PHASE(performLivenessAnalysis);
468         RUN_PHASE(performCFA);
469         RUN_PHASE(performGlobalStoreBarrierInsertion);
470         RUN_PHASE(performStoreBarrierClustering);
471         if (Options::useMovHintRemoval())
472             RUN_PHASE(performMovHintRemoval);
473         RUN_PHASE(performCleanUp);
474         RUN_PHASE(performDCE); // We rely on this to kill dead code that won't be recognized as dead by B3.
475         RUN_PHASE(performStackLayout);
476         RUN_PHASE(performLivenessAnalysis);
477         RUN_PHASE(performOSRAvailabilityAnalysis);
478         RUN_PHASE(performWatchpointCollection);
479         
480         if (FTL::canCompile(dfg) == FTL::CannotCompile) {
481             finalizer = std::make_unique<FailedFinalizer>(*this);
482             return FailPath;
483         }
484
485         dumpAndVerifyGraph(dfg, "Graph just before FTL lowering:", shouldDumpDisassembly(mode));
486
487         // Flash a safepoint in case the GC wants some action.
488         Safepoint::Result safepointResult;
489         {
490             GraphSafepoint safepoint(dfg, safepointResult);
491         }
492         if (safepointResult.didGetCancelled())
493             return CancelPath;
494
495         FTL::State state(dfg);
496         FTL::lowerDFGToB3(state);
497         
498         if (UNLIKELY(computeCompileTimes()))
499             m_timeBeforeFTL = monotonicallyIncreasingTimeMS();
500         
501         if (Options::b3AlwaysFailsBeforeCompile()) {
502             FTL::fail(state);
503             return FTLPath;
504         }
505         
506         FTL::compile(state, safepointResult);
507         if (safepointResult.didGetCancelled())
508             return CancelPath;
509         
510         if (Options::b3AlwaysFailsBeforeLink()) {
511             FTL::fail(state);
512             return FTLPath;
513         }
514         
515         if (state.allocationFailed) {
516             FTL::fail(state);
517             return FTLPath;
518         }
519
520         FTL::link(state);
521         
522         if (state.allocationFailed) {
523             FTL::fail(state);
524             return FTLPath;
525         }
526         
527         return FTLPath;
528 #else
529         RELEASE_ASSERT_NOT_REACHED();
530         return FailPath;
531 #endif // ENABLE(FTL_JIT)
532     }
533         
534     default:
535         RELEASE_ASSERT_NOT_REACHED();
536         return FailPath;
537     }
538
539 #undef RUN_PHASE
540 }
541
542 bool Plan::isStillValid()
543 {
544     CodeBlock* replacement = codeBlock->replacement();
545     if (!replacement)
546         return false;
547     // FIXME: This is almost certainly not necessary. There's no way for the baseline
548     // code to be replaced during a compilation, except if we delete the plan, in which
549     // case we wouldn't be here.
550     // https://bugs.webkit.org/show_bug.cgi?id=132707
551     if (codeBlock->alternative() != replacement->baselineVersion())
552         return false;
553     if (!watchpoints.areStillValid())
554         return false;
555     return true;
556 }
557
558 void Plan::reallyAdd(CommonData* commonData)
559 {
560     watchpoints.reallyAdd(codeBlock, *commonData);
561     identifiers.reallyAdd(*vm, commonData);
562     weakReferences.reallyAdd(*vm, commonData);
563     transitions.reallyAdd(*vm, commonData);
564 }
565
566 void Plan::notifyCompiling()
567 {
568     stage = Compiling;
569 }
570
571 void Plan::notifyReady()
572 {
573     callback->compilationDidBecomeReadyAsynchronously(codeBlock, profiledDFGCodeBlock);
574     stage = Ready;
575 }
576
577 CompilationResult Plan::finalizeWithoutNotifyingCallback()
578 {
579     // We will establish new references from the code block to things. So, we need a barrier.
580     vm->heap.writeBarrier(codeBlock);
581     
582     if (!isStillValid()) {
583         CODEBLOCK_LOG_EVENT(codeBlock, "dfgFinalize", ("invalidated"));
584         return CompilationInvalidated;
585     }
586
587     bool result;
588     if (codeBlock->codeType() == FunctionCode)
589         result = finalizer->finalizeFunction();
590     else
591         result = finalizer->finalize();
592     
593     if (!result) {
594         CODEBLOCK_LOG_EVENT(codeBlock, "dfgFinalize", ("failed"));
595         return CompilationFailed;
596     }
597     
598     reallyAdd(codeBlock->jitCode()->dfgCommon());
599     
600     if (validationEnabled()) {
601         TrackedReferences trackedReferences;
602         
603         for (WriteBarrier<JSCell>& reference : codeBlock->jitCode()->dfgCommon()->weakReferences)
604             trackedReferences.add(reference.get());
605         for (WriteBarrier<Structure>& reference : codeBlock->jitCode()->dfgCommon()->weakStructureReferences)
606             trackedReferences.add(reference.get());
607         for (WriteBarrier<Unknown>& constant : codeBlock->constants())
608             trackedReferences.add(constant.get());
609
610         for (auto* inlineCallFrame : *inlineCallFrames) {
611             ASSERT(inlineCallFrame->baselineCodeBlock.get());
612             trackedReferences.add(inlineCallFrame->baselineCodeBlock.get());
613         }
614         
615         // Check that any other references that we have anywhere in the JITCode are also
616         // tracked either strongly or weakly.
617         codeBlock->jitCode()->validateReferences(trackedReferences);
618     }
619     
620     CODEBLOCK_LOG_EVENT(codeBlock, "dfgFinalize", ("succeeded"));
621     return CompilationSuccessful;
622 }
623
624 void Plan::finalizeAndNotifyCallback()
625 {
626     callback->compilationDidComplete(codeBlock, profiledDFGCodeBlock, finalizeWithoutNotifyingCallback());
627 }
628
629 CompilationKey Plan::key()
630 {
631     return CompilationKey(codeBlock->alternative(), mode);
632 }
633
634 void Plan::checkLivenessAndVisitChildren(SlotVisitor& visitor)
635 {
636     if (!isKnownToBeLiveDuringGC())
637         return;
638
639     cleanMustHandleValuesIfNecessary();
640     for (unsigned i = mustHandleValues.size(); i--;)
641         visitor.appendUnbarriered(mustHandleValues[i]);
642
643     visitor.appendUnbarriered(codeBlock);
644     visitor.appendUnbarriered(codeBlock->alternative());
645     visitor.appendUnbarriered(profiledDFGCodeBlock);
646
647     if (inlineCallFrames) {
648         for (auto* inlineCallFrame : *inlineCallFrames) {
649             ASSERT(inlineCallFrame->baselineCodeBlock.get());
650             visitor.appendUnbarriered(inlineCallFrame->baselineCodeBlock.get());
651         }
652     }
653
654     weakReferences.visitChildren(visitor);
655     transitions.visitChildren(visitor);
656 }
657
658 bool Plan::isKnownToBeLiveDuringGC()
659 {
660     if (stage == Cancelled)
661         return false;
662     if (!Heap::isMarked(codeBlock->ownerExecutable()))
663         return false;
664     if (!Heap::isMarked(codeBlock->alternative()))
665         return false;
666     if (!!profiledDFGCodeBlock && !Heap::isMarked(profiledDFGCodeBlock))
667         return false;
668     return true;
669 }
670
671 void Plan::cancel()
672 {
673     vm = nullptr;
674     codeBlock = nullptr;
675     profiledDFGCodeBlock = nullptr;
676     mustHandleValues.clear();
677     compilation = nullptr;
678     finalizer = nullptr;
679     inlineCallFrames = nullptr;
680     watchpoints = DesiredWatchpoints();
681     identifiers = DesiredIdentifiers();
682     weakReferences = DesiredWeakReferences();
683     transitions = DesiredTransitions();
684     callback = nullptr;
685     stage = Cancelled;
686 }
687
688 void Plan::cleanMustHandleValuesIfNecessary()
689 {
690     LockHolder locker(mustHandleValueCleaningLock);
691     
692     if (!mustHandleValuesMayIncludeGarbage)
693         return;
694     
695     mustHandleValuesMayIncludeGarbage = false;
696     
697     if (!codeBlock)
698         return;
699     
700     if (!mustHandleValues.numberOfLocals())
701         return;
702     
703     FastBitVector liveness = codeBlock->alternative()->livenessAnalysis().getLivenessInfoAtBytecodeOffset(osrEntryBytecodeIndex);
704     
705     for (unsigned local = mustHandleValues.numberOfLocals(); local--;) {
706         if (!liveness[local])
707             mustHandleValues.local(local) = jsUndefined();
708     }
709 }
710
711 } } // namespace JSC::DFG
712
713 #endif // ENABLE(DFG_JIT)
714