We should support CreateThis in the FTL
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGPlan.cpp
1 /*
2  * Copyright (C) 2013-2018 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
83 #if ENABLE(FTL_JIT)
84 #include "FTLCapabilities.h"
85 #include "FTLCompile.h"
86 #include "FTLFail.h"
87 #include "FTLLink.h"
88 #include "FTLLowerDFGToB3.h"
89 #include "FTLState.h"
90 #endif
91
92 namespace JSC {
93
94 extern Seconds totalDFGCompileTime;
95 extern Seconds totalFTLCompileTime;
96 extern Seconds totalFTLDFGCompileTime;
97 extern Seconds totalFTLB3CompileTime;
98
99 }
100
101 namespace JSC { namespace DFG {
102
103 namespace {
104
105 void dumpAndVerifyGraph(Graph& graph, const char* text, bool forceDump = false)
106 {
107     GraphDumpMode modeForFinalValidate = DumpGraph;
108     if (verboseCompilationEnabled(graph.m_plan.mode) || forceDump) {
109         dataLog(text, "\n");
110         graph.dump();
111         modeForFinalValidate = DontDumpGraph;
112     }
113     if (validationEnabled())
114         validate(graph, modeForFinalValidate);
115 }
116
117 Profiler::CompilationKind profilerCompilationKindForMode(CompilationMode mode)
118 {
119     switch (mode) {
120     case InvalidCompilationMode:
121         RELEASE_ASSERT_NOT_REACHED();
122         return Profiler::DFG;
123     case DFGMode:
124         return Profiler::DFG;
125     case FTLMode:
126         return Profiler::FTL;
127     case FTLForOSREntryMode:
128         return Profiler::FTLForOSREntry;
129     }
130     RELEASE_ASSERT_NOT_REACHED();
131     return Profiler::DFG;
132 }
133
134 } // anonymous namespace
135
136 Plan::Plan(CodeBlock* passedCodeBlock, CodeBlock* profiledDFGCodeBlock,
137     CompilationMode mode, unsigned osrEntryBytecodeIndex,
138     const Operands<JSValue>& mustHandleValues)
139     : vm(passedCodeBlock->vm())
140     , codeBlock(passedCodeBlock)
141     , profiledDFGCodeBlock(profiledDFGCodeBlock)
142     , mode(mode)
143     , osrEntryBytecodeIndex(osrEntryBytecodeIndex)
144     , mustHandleValues(mustHandleValues)
145     , compilation(UNLIKELY(vm->m_perBytecodeProfiler) ? adoptRef(new Profiler::Compilation(vm->m_perBytecodeProfiler->ensureBytecodesFor(codeBlock), profilerCompilationKindForMode(mode))) : nullptr)
146     , inlineCallFrames(adoptRef(new InlineCallFrameSet()))
147     , identifiers(codeBlock)
148     , weakReferences(codeBlock)
149     , stage(Preparing)
150 {
151 }
152
153 Plan::~Plan()
154 {
155 }
156
157 bool Plan::computeCompileTimes() const
158 {
159     return reportCompileTimes()
160         || Options::reportTotalCompileTimes()
161         || (vm && vm->m_perBytecodeProfiler);
162 }
163
164 bool Plan::reportCompileTimes() const
165 {
166     return Options::reportCompileTimes()
167         || Options::reportDFGCompileTimes()
168         || (Options::reportFTLCompileTimes() && isFTL(mode));
169 }
170
171 void Plan::compileInThread(ThreadData* threadData)
172 {
173     this->threadData = threadData;
174     
175     MonotonicTime before { };
176     CString codeBlockName;
177     if (UNLIKELY(computeCompileTimes()))
178         before = MonotonicTime::now();
179     if (UNLIKELY(reportCompileTimes()))
180         codeBlockName = toCString(*codeBlock);
181     
182     CompilationScope compilationScope;
183
184     if (logCompilationChanges(mode) || Options::logPhaseTimes())
185         dataLog("DFG(Plan) compiling ", *codeBlock, " with ", mode, ", number of instructions = ", codeBlock->instructionCount(), "\n");
186
187     CompilationPath path = compileInThreadImpl();
188
189     RELEASE_ASSERT(path == CancelPath || finalizer);
190     RELEASE_ASSERT((path == CancelPath) == (stage == Cancelled));
191     
192     MonotonicTime after { };
193     if (UNLIKELY(computeCompileTimes())) {
194         after = MonotonicTime::now();
195     
196         if (Options::reportTotalCompileTimes()) {
197             if (isFTL(mode)) {
198                 totalFTLCompileTime += after - before;
199                 totalFTLDFGCompileTime += m_timeBeforeFTL - before;
200                 totalFTLB3CompileTime += after - m_timeBeforeFTL;
201             } else
202                 totalDFGCompileTime += after - before;
203         }
204     }
205     const char* pathName = nullptr;
206     switch (path) {
207     case FailPath:
208         pathName = "N/A (fail)";
209         break;
210     case DFGPath:
211         pathName = "DFG";
212         break;
213     case FTLPath:
214         pathName = "FTL";
215         break;
216     case CancelPath:
217         pathName = "Cancelled";
218         break;
219     default:
220         RELEASE_ASSERT_NOT_REACHED();
221         break;
222     }
223     if (codeBlock) { // codeBlock will be null if the compilation was cancelled.
224         if (path == FTLPath)
225             CODEBLOCK_LOG_EVENT(codeBlock, "ftlCompile", ("took ", (after - before).milliseconds(), " ms (DFG: ", (m_timeBeforeFTL - before).milliseconds(), ", B3: ", (after - m_timeBeforeFTL).milliseconds(), ") with ", pathName));
226         else
227             CODEBLOCK_LOG_EVENT(codeBlock, "dfgCompile", ("took ", (after - before).milliseconds(), " ms with ", pathName));
228     }
229     if (UNLIKELY(reportCompileTimes())) {
230         dataLog("Optimized ", codeBlockName, " using ", mode, " with ", pathName, " into ", finalizer ? finalizer->codeSize() : 0, " bytes in ", (after - before).milliseconds(), " ms");
231         if (path == FTLPath)
232             dataLog(" (DFG: ", (m_timeBeforeFTL - before).milliseconds(), ", B3: ", (after - m_timeBeforeFTL).milliseconds(), ")");
233         dataLog(".\n");
234     }
235 }
236
237 Plan::CompilationPath Plan::compileInThreadImpl()
238 {
239     cleanMustHandleValuesIfNecessary();
240     
241     if (verboseCompilationEnabled(mode) && osrEntryBytecodeIndex != UINT_MAX) {
242         dataLog("\n");
243         dataLog("Compiler must handle OSR entry from bc#", osrEntryBytecodeIndex, " with values: ", mustHandleValues, "\n");
244         dataLog("\n");
245     }
246     
247     Graph dfg(*vm, *this);
248     parse(dfg);
249
250     codeBlock->setCalleeSaveRegisters(RegisterSet::dfgCalleeSaveRegisters());
251
252     bool changed = false;
253
254 #define RUN_PHASE(phase)                                         \
255     do {                                                         \
256         if (Options::safepointBeforeEachPhase()) {               \
257             Safepoint::Result safepointResult;                   \
258             {                                                    \
259                 GraphSafepoint safepoint(dfg, safepointResult);  \
260             }                                                    \
261             if (safepointResult.didGetCancelled())               \
262                 return CancelPath;                               \
263         }                                                        \
264         changed |= phase(dfg);                                   \
265     } while (false);                                             \
266
267     
268     // By this point the DFG bytecode parser will have potentially mutated various tables
269     // in the CodeBlock. This is a good time to perform an early shrink, which is more
270     // powerful than a late one. It's safe to do so because we haven't generated any code
271     // that references any of the tables directly, yet.
272     codeBlock->shrinkToFit(CodeBlock::EarlyShrink);
273
274     if (validationEnabled())
275         validate(dfg);
276     
277     if (Options::dumpGraphAfterParsing()) {
278         dataLog("Graph after parsing:\n");
279         dfg.dump();
280     }
281
282     RUN_PHASE(performLiveCatchVariablePreservationPhase);
283
284     if (Options::useMaximalFlushInsertionPhase())
285         RUN_PHASE(performMaximalFlushInsertion);
286     
287     RUN_PHASE(performCPSRethreading);
288     RUN_PHASE(performUnification);
289     RUN_PHASE(performPredictionInjection);
290     
291     RUN_PHASE(performStaticExecutionCountEstimation);
292     
293     if (mode == FTLForOSREntryMode) {
294         bool result = performOSREntrypointCreation(dfg);
295         if (!result) {
296             finalizer = std::make_unique<FailedFinalizer>(*this);
297             return FailPath;
298         }
299         RUN_PHASE(performCPSRethreading);
300     }
301     
302     if (validationEnabled())
303         validate(dfg);
304     
305     RUN_PHASE(performBackwardsPropagation);
306     RUN_PHASE(performPredictionPropagation);
307     RUN_PHASE(performFixup);
308     RUN_PHASE(performInvalidationPointInjection);
309     RUN_PHASE(performTypeCheckHoisting);
310     
311     dfg.m_fixpointState = FixpointNotConverged;
312     
313     // For now we're back to avoiding a fixpoint. Note that we've ping-ponged on this decision
314     // many times. For maximum throughput, it's best to fixpoint. But the throughput benefit is
315     // small and not likely to show up in FTL anyway. On the other hand, not fixpointing means
316     // that the compiler compiles more quickly. We want the third tier to compile quickly, which
317     // not fixpointing accomplishes; and the fourth tier shouldn't need a fixpoint.
318     if (validationEnabled())
319         validate(dfg);
320         
321     RUN_PHASE(performStrengthReduction);
322     RUN_PHASE(performCPSRethreading);
323     RUN_PHASE(performCFA);
324     RUN_PHASE(performConstantFolding);
325     changed = false;
326     RUN_PHASE(performCFGSimplification);
327     RUN_PHASE(performLocalCSE);
328     
329     if (validationEnabled())
330         validate(dfg);
331     
332     RUN_PHASE(performCPSRethreading);
333     if (!isFTL(mode)) {
334         // Only run this if we're not FTLing, because currently for a LoadVarargs that is forwardable and
335         // in a non-varargs inlined call frame, this will generate ForwardVarargs while the FTL
336         // ArgumentsEliminationPhase will create a sequence of GetStack+PutStacks. The GetStack+PutStack
337         // sequence then gets sunk, eliminating anything that looks like an escape for subsequent phases,
338         // while the ForwardVarargs doesn't get simplified until later (or not at all) and looks like an
339         // escape for all of the arguments. This then disables object allocation sinking.
340         //
341         // So, for now, we just disable this phase for the FTL.
342         //
343         // If we wanted to enable it, we'd have to do any of the following:
344         // - Enable ForwardVarargs->GetStack+PutStack strength reduction, and have that run before
345         //   PutStack sinking and object allocation sinking.
346         // - Make VarargsForwarding emit a GetLocal+SetLocal sequence, that we can later turn into
347         //   GetStack+PutStack.
348         //
349         // But, it's not super valuable to enable those optimizations, since the FTL
350         // ArgumentsEliminationPhase does everything that this phase does, and it doesn't introduce this
351         // pathology.
352         
353         RUN_PHASE(performVarargsForwarding); // Do this after CFG simplification and CPS rethreading.
354     }
355     if (changed) {
356         RUN_PHASE(performCFA);
357         RUN_PHASE(performConstantFolding);
358     }
359     
360     // If we're doing validation, then run some analyses, to give them an opportunity
361     // to self-validate. Now is as good a time as any to do this.
362     if (validationEnabled()) {
363         dfg.ensureCPSDominators();
364         dfg.ensureCPSNaturalLoops();
365     }
366
367     switch (mode) {
368     case DFGMode: {
369         dfg.m_fixpointState = FixpointConverged;
370     
371         RUN_PHASE(performTierUpCheckInjection);
372
373         RUN_PHASE(performFastStoreBarrierInsertion);
374         RUN_PHASE(performStoreBarrierClustering);
375         RUN_PHASE(performCleanUp);
376         RUN_PHASE(performCPSRethreading);
377         RUN_PHASE(performDCE);
378         RUN_PHASE(performPhantomInsertion);
379         RUN_PHASE(performStackLayout);
380         RUN_PHASE(performVirtualRegisterAllocation);
381         RUN_PHASE(performWatchpointCollection);
382         dumpAndVerifyGraph(dfg, "Graph after optimization:");
383         
384         JITCompiler dataFlowJIT(dfg);
385         if (codeBlock->codeType() == FunctionCode)
386             dataFlowJIT.compileFunction();
387         else
388             dataFlowJIT.compile();
389         
390         return DFGPath;
391     }
392     
393     case FTLMode:
394     case FTLForOSREntryMode: {
395 #if ENABLE(FTL_JIT)
396         if (FTL::canCompile(dfg) == FTL::CannotCompile) {
397             finalizer = std::make_unique<FailedFinalizer>(*this);
398             return FailPath;
399         }
400         
401         RUN_PHASE(performCleanUp); // Reduce the graph size a bit.
402         RUN_PHASE(performCriticalEdgeBreaking);
403         if (Options::createPreHeaders())
404             RUN_PHASE(performLoopPreHeaderCreation);
405         RUN_PHASE(performCPSRethreading);
406         RUN_PHASE(performSSAConversion);
407         RUN_PHASE(performSSALowering);
408         
409         // Ideally, these would be run to fixpoint with the object allocation sinking phase.
410         RUN_PHASE(performArgumentsElimination);
411         if (Options::usePutStackSinking())
412             RUN_PHASE(performPutStackSinking);
413         
414         RUN_PHASE(performConstantHoisting);
415         RUN_PHASE(performGlobalCSE);
416         RUN_PHASE(performLivenessAnalysis);
417         RUN_PHASE(performCFA);
418         RUN_PHASE(performConstantFolding);
419         RUN_PHASE(performCleanUp); // Reduce the graph size a lot.
420         changed = false;
421         RUN_PHASE(performStrengthReduction);
422         if (Options::useObjectAllocationSinking()) {
423             RUN_PHASE(performCriticalEdgeBreaking);
424             RUN_PHASE(performObjectAllocationSinking);
425         }
426         if (changed) {
427             // State-at-tail and state-at-head will be invalid if we did strength reduction since
428             // it might increase live ranges.
429             RUN_PHASE(performLivenessAnalysis);
430             RUN_PHASE(performCFA);
431             RUN_PHASE(performConstantFolding);
432         }
433         
434         // Currently, this relies on pre-headers still being valid. That precludes running CFG
435         // simplification before it, unless we re-created the pre-headers. There wouldn't be anything
436         // wrong with running LICM earlier, if we wanted to put other CFG transforms above this point.
437         // Alternatively, we could run loop pre-header creation after SSA conversion - but if we did that
438         // then we'd need to do some simple SSA fix-up.
439         RUN_PHASE(performLivenessAnalysis);
440         RUN_PHASE(performCFA);
441         RUN_PHASE(performLICM);
442
443         // FIXME: Currently: IntegerRangeOptimization *must* be run after LICM.
444         //
445         // IntegerRangeOptimization makes changes on nodes based on preceding blocks
446         // and nodes. LICM moves nodes which can invalidates assumptions used
447         // by IntegerRangeOptimization.
448         //
449         // Ideally, the dependencies should be explicit. See https://bugs.webkit.org/show_bug.cgi?id=157534.
450         RUN_PHASE(performLivenessAnalysis);
451         RUN_PHASE(performIntegerRangeOptimization);
452         
453         RUN_PHASE(performCleanUp);
454         RUN_PHASE(performIntegerCheckCombining);
455         RUN_PHASE(performGlobalCSE);
456         
457         // At this point we're not allowed to do any further code motion because our reasoning
458         // about code motion assumes that it's OK to insert GC points in random places.
459         dfg.m_fixpointState = FixpointConverged;
460         
461         RUN_PHASE(performLivenessAnalysis);
462         RUN_PHASE(performCFA);
463         RUN_PHASE(performGlobalStoreBarrierInsertion);
464         RUN_PHASE(performStoreBarrierClustering);
465         if (Options::useMovHintRemoval())
466             RUN_PHASE(performMovHintRemoval);
467         RUN_PHASE(performCleanUp);
468         RUN_PHASE(performDCE); // We rely on this to kill dead code that won't be recognized as dead by B3.
469         RUN_PHASE(performStackLayout);
470         RUN_PHASE(performLivenessAnalysis);
471         RUN_PHASE(performOSRAvailabilityAnalysis);
472         RUN_PHASE(performWatchpointCollection);
473         
474         if (FTL::canCompile(dfg) == FTL::CannotCompile) {
475             finalizer = std::make_unique<FailedFinalizer>(*this);
476             return FailPath;
477         }
478
479         dumpAndVerifyGraph(dfg, "Graph just before FTL lowering:", shouldDumpDisassembly(mode));
480
481         // Flash a safepoint in case the GC wants some action.
482         Safepoint::Result safepointResult;
483         {
484             GraphSafepoint safepoint(dfg, safepointResult);
485         }
486         if (safepointResult.didGetCancelled())
487             return CancelPath;
488
489         FTL::State state(dfg);
490         FTL::lowerDFGToB3(state);
491         
492         if (UNLIKELY(computeCompileTimes()))
493             m_timeBeforeFTL = MonotonicTime::now();
494         
495         if (Options::b3AlwaysFailsBeforeCompile()) {
496             FTL::fail(state);
497             return FTLPath;
498         }
499         
500         FTL::compile(state, safepointResult);
501         if (safepointResult.didGetCancelled())
502             return CancelPath;
503         
504         if (Options::b3AlwaysFailsBeforeLink()) {
505             FTL::fail(state);
506             return FTLPath;
507         }
508         
509         if (state.allocationFailed) {
510             FTL::fail(state);
511             return FTLPath;
512         }
513
514         FTL::link(state);
515         
516         if (state.allocationFailed) {
517             FTL::fail(state);
518             return FTLPath;
519         }
520         
521         return FTLPath;
522 #else
523         RELEASE_ASSERT_NOT_REACHED();
524         return FailPath;
525 #endif // ENABLE(FTL_JIT)
526     }
527         
528     default:
529         RELEASE_ASSERT_NOT_REACHED();
530         return FailPath;
531     }
532
533 #undef RUN_PHASE
534 }
535
536 bool Plan::isStillValid()
537 {
538     CodeBlock* replacement = codeBlock->replacement();
539     if (!replacement)
540         return false;
541     // FIXME: This is almost certainly not necessary. There's no way for the baseline
542     // code to be replaced during a compilation, except if we delete the plan, in which
543     // case we wouldn't be here.
544     // https://bugs.webkit.org/show_bug.cgi?id=132707
545     if (codeBlock->alternative() != replacement->baselineVersion())
546         return false;
547     if (!watchpoints.areStillValid())
548         return false;
549     return true;
550 }
551
552 void Plan::reallyAdd(CommonData* commonData)
553 {
554     watchpoints.reallyAdd(codeBlock, *commonData);
555     identifiers.reallyAdd(*vm, commonData);
556     weakReferences.reallyAdd(*vm, commonData);
557     transitions.reallyAdd(*vm, commonData);
558     commonData->recordedStatuses = WTFMove(recordedStatuses);
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     recordedStatuses.markIfCheap(visitor);
639
640     visitor.appendUnbarriered(codeBlock);
641     visitor.appendUnbarriered(codeBlock->alternative());
642     visitor.appendUnbarriered(profiledDFGCodeBlock);
643
644     if (inlineCallFrames) {
645         for (auto* inlineCallFrame : *inlineCallFrames) {
646             ASSERT(inlineCallFrame->baselineCodeBlock.get());
647             visitor.appendUnbarriered(inlineCallFrame->baselineCodeBlock.get());
648         }
649     }
650
651     weakReferences.visitChildren(visitor);
652     transitions.visitChildren(visitor);
653 }
654
655 void Plan::finalizeInGC()
656 {
657     recordedStatuses.finalizeWithoutDeleting();
658 }
659
660 bool Plan::isKnownToBeLiveDuringGC()
661 {
662     if (stage == Cancelled)
663         return false;
664     if (!Heap::isMarked(codeBlock->ownerExecutable()))
665         return false;
666     if (!Heap::isMarked(codeBlock->alternative()))
667         return false;
668     if (!!profiledDFGCodeBlock && !Heap::isMarked(profiledDFGCodeBlock))
669         return false;
670     return true;
671 }
672
673 void Plan::cancel()
674 {
675     vm = nullptr;
676     codeBlock = nullptr;
677     profiledDFGCodeBlock = nullptr;
678     mustHandleValues.clear();
679     compilation = nullptr;
680     finalizer = nullptr;
681     inlineCallFrames = nullptr;
682     watchpoints = DesiredWatchpoints();
683     identifiers = DesiredIdentifiers();
684     weakReferences = DesiredWeakReferences();
685     transitions = DesiredTransitions();
686     callback = nullptr;
687     stage = Cancelled;
688 }
689
690 void Plan::cleanMustHandleValuesIfNecessary()
691 {
692     LockHolder locker(mustHandleValueCleaningLock);
693     
694     if (!mustHandleValuesMayIncludeGarbage)
695         return;
696     
697     mustHandleValuesMayIncludeGarbage = false;
698     
699     if (!codeBlock)
700         return;
701     
702     if (!mustHandleValues.numberOfLocals())
703         return;
704     
705     CodeBlock* alternative = codeBlock->alternative();
706     FastBitVector liveness = alternative->livenessAnalysis().getLivenessInfoAtBytecodeOffset(alternative, osrEntryBytecodeIndex);
707     
708     for (unsigned local = mustHandleValues.numberOfLocals(); local--;) {
709         if (!liveness[local])
710             mustHandleValues.local(local) = jsUndefined();
711     }
712 }
713
714 } } // namespace JSC::DFG
715
716 #endif // ENABLE(DFG_JIT)
717