CrashTracer: DFG_CRASH beneath JSC::FTL::LowerDFGToLLVM::compileNode
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGPlan.cpp
1 /*
2  * Copyright (C) 2013, 2014 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 "DFGArgumentsSimplificationPhase.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 "DFGConstantFoldingPhase.h"
39 #include "DFGCriticalEdgeBreakingPhase.h"
40 #include "DFGDCEPhase.h"
41 #include "DFGFailedFinalizer.h"
42 #include "DFGFixupPhase.h"
43 #include "DFGGraphSafepoint.h"
44 #include "DFGIntegerCheckCombiningPhase.h"
45 #include "DFGInvalidationPointInjectionPhase.h"
46 #include "DFGJITCompiler.h"
47 #include "DFGLICMPhase.h"
48 #include "DFGLivenessAnalysisPhase.h"
49 #include "DFGLoopPreHeaderCreationPhase.h"
50 #include "DFGOSRAvailabilityAnalysisPhase.h"
51 #include "DFGOSREntrypointCreationPhase.h"
52 #include "DFGObjectAllocationSinkingPhase.h"
53 #include "DFGPhantomCanonicalizationPhase.h"
54 #include "DFGPhantomRemovalPhase.h"
55 #include "DFGPredictionInjectionPhase.h"
56 #include "DFGPredictionPropagationPhase.h"
57 #include "DFGPutLocalSinkingPhase.h"
58 #include "DFGResurrectionForValidationPhase.h"
59 #include "DFGSSAConversionPhase.h"
60 #include "DFGSSALoweringPhase.h"
61 #include "DFGStackLayoutPhase.h"
62 #include "DFGStaticExecutionCountEstimationPhase.h"
63 #include "DFGStoreBarrierElisionPhase.h"
64 #include "DFGStrengthReductionPhase.h"
65 #include "DFGStructureRegistrationPhase.h"
66 #include "DFGTierUpCheckInjectionPhase.h"
67 #include "DFGTypeCheckHoistingPhase.h"
68 #include "DFGUnificationPhase.h"
69 #include "DFGValidate.h"
70 #include "DFGVirtualRegisterAllocationPhase.h"
71 #include "DFGWatchpointCollectionPhase.h"
72 #include "Debugger.h"
73 #include "JSCInlines.h"
74 #include "OperandsInlines.h"
75 #include "ProfilerDatabase.h"
76 #include <wtf/CurrentTime.h>
77
78 #if ENABLE(FTL_JIT)
79 #include "FTLCapabilities.h"
80 #include "FTLCompile.h"
81 #include "FTLFail.h"
82 #include "FTLLink.h"
83 #include "FTLLowerDFGToLLVM.h"
84 #include "FTLState.h"
85 #include "InitializeLLVM.h"
86 #endif
87
88 namespace JSC { namespace DFG {
89
90 static void dumpAndVerifyGraph(Graph& graph, const char* text)
91 {
92     GraphDumpMode modeForFinalValidate = DumpGraph;
93     if (verboseCompilationEnabled(graph.m_plan.mode)) {
94         dataLog(text, "\n");
95         graph.dump();
96         modeForFinalValidate = DontDumpGraph;
97     }
98     if (validationEnabled())
99         validate(graph, modeForFinalValidate);
100 }
101
102 static Profiler::CompilationKind profilerCompilationKindForMode(CompilationMode mode)
103 {
104     switch (mode) {
105     case InvalidCompilationMode:
106         RELEASE_ASSERT_NOT_REACHED();
107         return Profiler::DFG;
108     case DFGMode:
109         return Profiler::DFG;
110     case FTLMode:
111         return Profiler::FTL;
112     case FTLForOSREntryMode:
113         return Profiler::FTLForOSREntry;
114     }
115     RELEASE_ASSERT_NOT_REACHED();
116     return Profiler::DFG;
117 }
118
119 Plan::Plan(PassRefPtr<CodeBlock> passedCodeBlock, CodeBlock* profiledDFGCodeBlock,
120     CompilationMode mode, unsigned osrEntryBytecodeIndex,
121     const Operands<JSValue>& mustHandleValues)
122     : vm(*passedCodeBlock->vm())
123     , codeBlock(passedCodeBlock)
124     , profiledDFGCodeBlock(profiledDFGCodeBlock)
125     , mode(mode)
126     , osrEntryBytecodeIndex(osrEntryBytecodeIndex)
127     , mustHandleValues(mustHandleValues)
128     , compilation(codeBlock->vm()->m_perBytecodeProfiler ? adoptRef(new Profiler::Compilation(codeBlock->vm()->m_perBytecodeProfiler->ensureBytecodesFor(codeBlock.get()), profilerCompilationKindForMode(mode))) : 0)
129     , inlineCallFrames(adoptRef(new InlineCallFrameSet()))
130     , identifiers(codeBlock.get())
131     , weakReferences(codeBlock.get())
132     , willTryToTierUp(false)
133     , stage(Preparing)
134 {
135 }
136
137 Plan::~Plan()
138 {
139 }
140
141 bool Plan::reportCompileTimes() const
142 {
143     return Options::reportCompileTimes()
144         || (Options::reportFTLCompileTimes() && isFTL(mode));
145 }
146
147 void Plan::compileInThread(LongLivedState& longLivedState, ThreadData* threadData)
148 {
149     this->threadData = threadData;
150     
151     double before = 0;
152     CString codeBlockName;
153     if (reportCompileTimes()) {
154         before = monotonicallyIncreasingTime();
155         codeBlockName = toCString(*codeBlock);
156     }
157     
158     SamplingRegion samplingRegion("DFG Compilation (Plan)");
159     CompilationScope compilationScope;
160
161     if (logCompilationChanges(mode))
162         dataLog("DFG(Plan) compiling ", *codeBlock, " with ", mode, ", number of instructions = ", codeBlock->instructionCount(), "\n");
163
164     CompilationPath path = compileInThreadImpl(longLivedState);
165
166     RELEASE_ASSERT(path == CancelPath || finalizer);
167     RELEASE_ASSERT((path == CancelPath) == (stage == Cancelled));
168     
169     if (reportCompileTimes()) {
170         const char* pathName;
171         switch (path) {
172         case FailPath:
173             pathName = "N/A (fail)";
174             break;
175         case DFGPath:
176             pathName = "DFG";
177             break;
178         case FTLPath:
179             pathName = "FTL";
180             break;
181         case CancelPath:
182             pathName = "Cancelled";
183             break;
184         default:
185             RELEASE_ASSERT_NOT_REACHED();
186 #if COMPILER_QUIRK(CONSIDERS_UNREACHABLE_CODE)
187             pathName = "";
188 #endif
189             break;
190         }
191         double now = monotonicallyIncreasingTime();
192         dataLog("Optimized ", codeBlockName, " using ", mode, " with ", pathName, " into ", finalizer ? finalizer->codeSize() : 0, " bytes in ", now - before, " ms");
193         if (path == FTLPath)
194             dataLog(" (DFG: ", m_timeBeforeFTL - before, ", LLVM: ", now - m_timeBeforeFTL, ")");
195         dataLog(".\n");
196     }
197 }
198
199 Plan::CompilationPath Plan::compileInThreadImpl(LongLivedState& longLivedState)
200 {
201     if (verboseCompilationEnabled(mode) && osrEntryBytecodeIndex != UINT_MAX) {
202         dataLog("\n");
203         dataLog("Compiler must handle OSR entry from bc#", osrEntryBytecodeIndex, " with values: ", mustHandleValues, "\n");
204         dataLog("\n");
205     }
206     
207     Graph dfg(vm, *this, longLivedState);
208     
209     if (!parse(dfg)) {
210         finalizer = std::make_unique<FailedFinalizer>(*this);
211         return FailPath;
212     }
213     
214     // By this point the DFG bytecode parser will have potentially mutated various tables
215     // in the CodeBlock. This is a good time to perform an early shrink, which is more
216     // powerful than a late one. It's safe to do so because we haven't generated any code
217     // that references any of the tables directly, yet.
218     codeBlock->shrinkToFit(CodeBlock::EarlyShrink);
219
220     if (validationEnabled())
221         validate(dfg);
222     
223     performCPSRethreading(dfg);
224     performUnification(dfg);
225     performPredictionInjection(dfg);
226     
227     performStaticExecutionCountEstimation(dfg);
228     
229     if (mode == FTLForOSREntryMode) {
230         bool result = performOSREntrypointCreation(dfg);
231         if (!result) {
232             finalizer = std::make_unique<FailedFinalizer>(*this);
233             return FailPath;
234         }
235         performCPSRethreading(dfg);
236     }
237     
238     if (validationEnabled())
239         validate(dfg);
240     
241     performBackwardsPropagation(dfg);
242     performPredictionPropagation(dfg);
243     performFixup(dfg);
244     performStructureRegistration(dfg);
245     performInvalidationPointInjection(dfg);
246     performTypeCheckHoisting(dfg);
247     
248     dfg.m_fixpointState = FixpointNotConverged;
249     
250     // For now we're back to avoiding a fixpoint. Note that we've ping-ponged on this decision
251     // many times. For maximum throughput, it's best to fixpoint. But the throughput benefit is
252     // small and not likely to show up in FTL anyway. On the other hand, not fixpointing means
253     // that the compiler compiles more quickly. We want the third tier to compile quickly, which
254     // not fixpointing accomplishes; and the fourth tier shouldn't need a fixpoint.
255     if (validationEnabled())
256         validate(dfg);
257         
258     performStrengthReduction(dfg);
259     performLocalCSE(dfg);
260     performCPSRethreading(dfg); // Canonicalize PhantomLocal to Phantom
261     performArgumentsSimplification(dfg);
262     performCPSRethreading(dfg); // This should do nothing, if arguments simplification did nothing.
263     performCFA(dfg);
264     performConstantFolding(dfg);
265     bool changed = false;
266     changed |= performCFGSimplification(dfg);
267     changed |= performLocalCSE(dfg);
268     
269     if (validationEnabled())
270         validate(dfg);
271     
272     performCPSRethreading(dfg);
273     if (changed) {
274         performCFA(dfg);
275         performConstantFolding(dfg);
276     }
277     
278     // If we're doing validation, then run some analyses, to give them an opportunity
279     // to self-validate. Now is as good a time as any to do this.
280     if (validationEnabled()) {
281         dfg.m_dominators.computeIfNecessary(dfg);
282         dfg.m_naturalLoops.computeIfNecessary(dfg);
283         dfg.m_prePostNumbering.computeIfNecessary(dfg);
284     }
285
286     switch (mode) {
287     case DFGMode: {
288         dfg.m_fixpointState = FixpointConverged;
289     
290         performTierUpCheckInjection(dfg);
291
292         performStoreBarrierElision(dfg);
293         performPhantomRemoval(dfg);
294         performCPSRethreading(dfg);
295         performDCE(dfg);
296         performStackLayout(dfg);
297         performVirtualRegisterAllocation(dfg);
298         performWatchpointCollection(dfg);
299         dumpAndVerifyGraph(dfg, "Graph after optimization:");
300         
301         JITCompiler dataFlowJIT(dfg);
302         if (codeBlock->codeType() == FunctionCode) {
303             dataFlowJIT.compileFunction();
304             dataFlowJIT.linkFunction();
305         } else {
306             dataFlowJIT.compile();
307             dataFlowJIT.link();
308         }
309         
310         return DFGPath;
311     }
312     
313     case FTLMode:
314     case FTLForOSREntryMode: {
315 #if ENABLE(FTL_JIT)
316         if (FTL::canCompile(dfg) == FTL::CannotCompile) {
317             finalizer = std::make_unique<FailedFinalizer>(*this);
318             return FailPath;
319         }
320         
321         performPhantomRemoval(dfg); // Reduce the graph size a bit.
322         performCriticalEdgeBreaking(dfg);
323         performLoopPreHeaderCreation(dfg);
324         performCPSRethreading(dfg);
325         performSSAConversion(dfg);
326         performSSALowering(dfg);
327         performPutLocalSinking(dfg);
328         performGlobalCSE(dfg);
329         performLivenessAnalysis(dfg);
330         performCFA(dfg);
331         performConstantFolding(dfg);
332         performPhantomCanonicalization(dfg); // Reduce the graph size a lot.
333         changed = false;
334         changed |= performStrengthReduction(dfg);
335         if (Options::enableObjectAllocationSinking()) {
336             changed |= performCriticalEdgeBreaking(dfg);
337             changed |= performObjectAllocationSinking(dfg);
338         }
339         if (changed) {
340             // State-at-tail and state-at-head will be invalid if we did strength reduction since
341             // it might increase live ranges.
342             performLivenessAnalysis(dfg);
343             performCFA(dfg);
344             performConstantFolding(dfg);
345         }
346         performLICM(dfg);
347         performPhantomCanonicalization(dfg);
348         performIntegerCheckCombining(dfg);
349         performGlobalCSE(dfg);
350         
351         // At this point we're not allowed to do any further code motion because our reasoning
352         // about code motion assumes that it's OK to insert GC points in random places.
353         dfg.m_fixpointState = FixpointConverged;
354         
355         performStoreBarrierElision(dfg);
356         performPhantomCanonicalization(dfg);
357         performLivenessAnalysis(dfg);
358         performCFA(dfg);
359         if (Options::validateFTLOSRExitLiveness())
360             performResurrectionForValidation(dfg);
361         performDCE(dfg); // We rely on this to kill dead code that won't be recognized as dead by LLVM.
362         performStackLayout(dfg);
363         performLivenessAnalysis(dfg);
364         performOSRAvailabilityAnalysis(dfg);
365         performWatchpointCollection(dfg);
366         
367         if (FTL::canCompile(dfg) == FTL::CannotCompile) {
368             finalizer = std::make_unique<FailedFinalizer>(*this);
369             return FailPath;
370         }
371
372         dumpAndVerifyGraph(dfg, "Graph just before FTL lowering:");
373         
374         bool haveLLVM;
375         Safepoint::Result safepointResult;
376         {
377             GraphSafepoint safepoint(dfg, safepointResult);
378             haveLLVM = initializeLLVM();
379         }
380         if (safepointResult.didGetCancelled())
381             return CancelPath;
382         
383         if (!haveLLVM) {
384             finalizer = std::make_unique<FailedFinalizer>(*this);
385             return FailPath;
386         }
387
388         FTL::State state(dfg);
389         if (!FTL::lowerDFGToLLVM(state)) {
390             FTL::fail(state);
391             return FTLPath;
392         }
393         
394         if (reportCompileTimes())
395             m_timeBeforeFTL = monotonicallyIncreasingTime();
396         
397         if (Options::llvmAlwaysFailsBeforeCompile()) {
398             FTL::fail(state);
399             return FTLPath;
400         }
401         
402         FTL::compile(state, safepointResult);
403         if (safepointResult.didGetCancelled())
404             return CancelPath;
405         
406         if (Options::llvmAlwaysFailsBeforeLink()) {
407             FTL::fail(state);
408             return FTLPath;
409         }
410
411         if (state.jitCode->stackmaps.stackSize() > Options::llvmMaxStackSize()) {
412             FTL::fail(state);
413             return FTLPath;
414         }
415
416         FTL::link(state);
417         return FTLPath;
418 #else
419         RELEASE_ASSERT_NOT_REACHED();
420         return FailPath;
421 #endif // ENABLE(FTL_JIT)
422     }
423         
424     default:
425         RELEASE_ASSERT_NOT_REACHED();
426         return FailPath;
427     }
428 }
429
430 bool Plan::isStillValid()
431 {
432     CodeBlock* replacement = codeBlock->replacement();
433     if (!replacement)
434         return false;
435     // FIXME: This is almost certainly not necessary. There's no way for the baseline
436     // code to be replaced during a compilation, except if we delete the plan, in which
437     // case we wouldn't be here.
438     // https://bugs.webkit.org/show_bug.cgi?id=132707
439     if (codeBlock->alternative() != replacement->baselineVersion())
440         return false;
441     if (!watchpoints.areStillValid())
442         return false;
443     return true;
444 }
445
446 void Plan::reallyAdd(CommonData* commonData)
447 {
448     watchpoints.reallyAdd(codeBlock.get(), *commonData);
449     identifiers.reallyAdd(vm, commonData);
450     weakReferences.reallyAdd(vm, commonData);
451     transitions.reallyAdd(vm, commonData);
452     writeBarriers.trigger(vm);
453 }
454
455 void Plan::notifyCompiling()
456 {
457     stage = Compiling;
458 }
459
460 void Plan::notifyCompiled()
461 {
462     stage = Compiled;
463 }
464
465 void Plan::notifyReady()
466 {
467     callback->compilationDidBecomeReadyAsynchronously(codeBlock.get());
468     stage = Ready;
469 }
470
471 CompilationResult Plan::finalizeWithoutNotifyingCallback()
472 {
473     if (!isStillValid())
474         return CompilationInvalidated;
475
476     bool result;
477     if (codeBlock->codeType() == FunctionCode)
478         result = finalizer->finalizeFunction();
479     else
480         result = finalizer->finalize();
481     
482     if (!result)
483         return CompilationFailed;
484     
485     reallyAdd(codeBlock->jitCode()->dfgCommon());
486     
487     return CompilationSuccessful;
488 }
489
490 void Plan::finalizeAndNotifyCallback()
491 {
492     callback->compilationDidComplete(codeBlock.get(), finalizeWithoutNotifyingCallback());
493 }
494
495 CompilationKey Plan::key()
496 {
497     return CompilationKey(codeBlock->alternative(), mode);
498 }
499
500 void Plan::checkLivenessAndVisitChildren(SlotVisitor& visitor, CodeBlockSet& codeBlocks)
501 {
502     if (!isKnownToBeLiveDuringGC())
503         return;
504     
505     for (unsigned i = mustHandleValues.size(); i--;)
506         visitor.appendUnbarrieredValue(&mustHandleValues[i]);
507     
508     codeBlocks.mark(codeBlock->alternative());
509     codeBlocks.mark(codeBlock.get());
510     codeBlocks.mark(profiledDFGCodeBlock.get());
511     
512     weakReferences.visitChildren(visitor);
513     writeBarriers.visitChildren(visitor);
514     transitions.visitChildren(visitor);
515 }
516
517 bool Plan::isKnownToBeLiveDuringGC()
518 {
519     if (stage == Cancelled)
520         return false;
521     if (!Heap::isMarked(codeBlock->ownerExecutable()))
522         return false;
523     if (!codeBlock->alternative()->isKnownToBeLiveDuringGC())
524         return false;
525     if (!!profiledDFGCodeBlock && !profiledDFGCodeBlock->isKnownToBeLiveDuringGC())
526         return false;
527     return true;
528 }
529
530 void Plan::cancel()
531 {
532     codeBlock = nullptr;
533     profiledDFGCodeBlock = nullptr;
534     mustHandleValues.clear();
535     compilation = nullptr;
536     finalizer = nullptr;
537     inlineCallFrames = nullptr;
538     watchpoints = DesiredWatchpoints();
539     identifiers = DesiredIdentifiers();
540     weakReferences = DesiredWeakReferences();
541     writeBarriers = DesiredWriteBarriers();
542     transitions = DesiredTransitions();
543     callback = nullptr;
544     stage = Cancelled;
545 }
546
547 } } // namespace JSC::DFG
548
549 #endif // ENABLE(DFG_JIT)
550