diff options
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGPlan.cpp')
| -rw-r--r-- | Source/JavaScriptCore/dfg/DFGPlan.cpp | 475 |
1 files changed, 383 insertions, 92 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGPlan.cpp b/Source/JavaScriptCore/dfg/DFGPlan.cpp index 735f5ffa2..a4a269808 100644 --- a/Source/JavaScriptCore/dfg/DFGPlan.cpp +++ b/Source/JavaScriptCore/dfg/DFGPlan.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Apple Inc. All rights reserved. + * Copyright (C) 2013-2015 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,43 +28,58 @@ #if ENABLE(DFG_JIT) -#include "DFGArgumentsSimplificationPhase.h" +#include "DFGArgumentsEliminationPhase.h" #include "DFGBackwardsPropagationPhase.h" #include "DFGByteCodeParser.h" #include "DFGCFAPhase.h" #include "DFGCFGSimplificationPhase.h" #include "DFGCPSRethreadingPhase.h" #include "DFGCSEPhase.h" +#include "DFGCleanUpPhase.h" #include "DFGConstantFoldingPhase.h" +#include "DFGConstantHoistingPhase.h" +#include "DFGCopyBarrierOptimizationPhase.h" #include "DFGCriticalEdgeBreakingPhase.h" #include "DFGDCEPhase.h" #include "DFGFailedFinalizer.h" -#include "DFGFlushLivenessAnalysisPhase.h" #include "DFGFixupPhase.h" +#include "DFGGraphSafepoint.h" +#include "DFGIntegerCheckCombiningPhase.h" +#include "DFGIntegerRangeOptimizationPhase.h" #include "DFGInvalidationPointInjectionPhase.h" #include "DFGJITCompiler.h" #include "DFGLICMPhase.h" +#include "DFGLiveCatchVariablePreservationPhase.h" #include "DFGLivenessAnalysisPhase.h" #include "DFGLoopPreHeaderCreationPhase.h" +#include "DFGMaximalFlushInsertionPhase.h" +#include "DFGMovHintRemovalPhase.h" #include "DFGOSRAvailabilityAnalysisPhase.h" #include "DFGOSREntrypointCreationPhase.h" +#include "DFGObjectAllocationSinkingPhase.h" +#include "DFGPhantomInsertionPhase.h" #include "DFGPredictionInjectionPhase.h" #include "DFGPredictionPropagationPhase.h" -#include "DFGResurrectionForValidationPhase.h" +#include "DFGPutStackSinkingPhase.h" #include "DFGSSAConversionPhase.h" #include "DFGSSALoweringPhase.h" #include "DFGStackLayoutPhase.h" -#include "DFGStoreBarrierElisionPhase.h" +#include "DFGStaticExecutionCountEstimationPhase.h" +#include "DFGStoreBarrierInsertionPhase.h" #include "DFGStrengthReductionPhase.h" +#include "DFGStructureRegistrationPhase.h" #include "DFGTierUpCheckInjectionPhase.h" #include "DFGTypeCheckHoistingPhase.h" #include "DFGUnificationPhase.h" #include "DFGValidate.h" +#include "DFGVarargsForwardingPhase.h" #include "DFGVirtualRegisterAllocationPhase.h" #include "DFGWatchpointCollectionPhase.h" #include "Debugger.h" +#include "JSCInlines.h" #include "OperandsInlines.h" -#include "Operations.h" +#include "ProfilerDatabase.h" +#include "TrackedReferences.h" #include <wtf/CurrentTime.h> #if ENABLE(FTL_JIT) @@ -72,17 +87,23 @@ #include "FTLCompile.h" #include "FTLFail.h" #include "FTLLink.h" -#include "FTLLowerDFGToLLVM.h" +#include "FTLLowerDFGToB3.h" #include "FTLState.h" -#include "InitializeLLVM.h" #endif namespace JSC { namespace DFG { -static void dumpAndVerifyGraph(Graph& graph, const char* text) +namespace { + +double totalDFGCompileTime; +double totalFTLCompileTime; +double totalFTLDFGCompileTime; +double totalFTLB3CompileTime; + +void dumpAndVerifyGraph(Graph& graph, const char* text, bool forceDump = false) { GraphDumpMode modeForFinalValidate = DumpGraph; - if (verboseCompilationEnabled()) { + if (verboseCompilationEnabled(graph.m_plan.mode) || forceDump) { dataLog(text, "\n"); graph.dump(); modeForFinalValidate = DontDumpGraph; @@ -91,18 +112,39 @@ static void dumpAndVerifyGraph(Graph& graph, const char* text) validate(graph, modeForFinalValidate); } -Plan::Plan( - PassRefPtr<CodeBlock> passedCodeBlock, CompilationMode mode, - unsigned osrEntryBytecodeIndex, const Operands<JSValue>& mustHandleValues) +Profiler::CompilationKind profilerCompilationKindForMode(CompilationMode mode) +{ + switch (mode) { + case InvalidCompilationMode: + RELEASE_ASSERT_NOT_REACHED(); + return Profiler::DFG; + case DFGMode: + return Profiler::DFG; + case FTLMode: + return Profiler::FTL; + case FTLForOSREntryMode: + return Profiler::FTLForOSREntry; + } + RELEASE_ASSERT_NOT_REACHED(); + return Profiler::DFG; +} + +} // anonymous namespace + +Plan::Plan(CodeBlock* passedCodeBlock, CodeBlock* profiledDFGCodeBlock, + CompilationMode mode, unsigned osrEntryBytecodeIndex, + const Operands<JSValue>& mustHandleValues) : vm(*passedCodeBlock->vm()) , codeBlock(passedCodeBlock) + , profiledDFGCodeBlock(profiledDFGCodeBlock) , mode(mode) , osrEntryBytecodeIndex(osrEntryBytecodeIndex) , mustHandleValues(mustHandleValues) - , compilation(codeBlock->vm()->m_perBytecodeProfiler ? adoptRef(new Profiler::Compilation(codeBlock->vm()->m_perBytecodeProfiler->ensureBytecodesFor(codeBlock.get()), Profiler::DFG)) : 0) - , identifiers(codeBlock.get()) - , weakReferences(codeBlock.get()) - , isCompiled(false) + , compilation(codeBlock->vm()->m_perBytecodeProfiler ? adoptRef(new Profiler::Compilation(codeBlock->vm()->m_perBytecodeProfiler->ensureBytecodesFor(codeBlock), profilerCompilationKindForMode(mode))) : 0) + , inlineCallFrames(adoptRef(new InlineCallFrameSet())) + , identifiers(codeBlock) + , weakReferences(codeBlock) + , stage(Preparing) { } @@ -110,23 +152,54 @@ Plan::~Plan() { } -void Plan::compileInThread(LongLivedState& longLivedState) +bool Plan::computeCompileTimes() const { + return reportCompileTimes() + || Options::reportTotalCompileTimes(); +} + +bool Plan::reportCompileTimes() const +{ + return Options::reportCompileTimes() + || (Options::reportFTLCompileTimes() && isFTL(mode)); +} + +void Plan::compileInThread(LongLivedState& longLivedState, ThreadData* threadData) +{ + this->threadData = threadData; + double before = 0; - if (Options::reportCompileTimes()) - before = currentTimeMS(); + CString codeBlockName; + if (computeCompileTimes()) + before = monotonicallyIncreasingTimeMS(); + if (reportCompileTimes()) + codeBlockName = toCString(*codeBlock); SamplingRegion samplingRegion("DFG Compilation (Plan)"); CompilationScope compilationScope; - if (logCompilationChanges()) + if (logCompilationChanges(mode)) dataLog("DFG(Plan) compiling ", *codeBlock, " with ", mode, ", number of instructions = ", codeBlock->instructionCount(), "\n"); CompilationPath path = compileInThreadImpl(longLivedState); - RELEASE_ASSERT(finalizer); + RELEASE_ASSERT(path == CancelPath || finalizer); + RELEASE_ASSERT((path == CancelPath) == (stage == Cancelled)); - if (Options::reportCompileTimes()) { + double after = 0; + if (computeCompileTimes()) + after = monotonicallyIncreasingTimeMS(); + + if (Options::reportTotalCompileTimes()) { + if (isFTL(mode)) { + totalFTLCompileTime += after - before; + totalFTLDFGCompileTime += m_timeBeforeFTL - before; + totalFTLB3CompileTime += after - m_timeBeforeFTL; + } else + totalDFGCompileTime += after - before; + } + + if (reportCompileTimes()) { const char* pathName; switch (path) { case FailPath: @@ -138,22 +211,26 @@ void Plan::compileInThread(LongLivedState& longLivedState) case FTLPath: pathName = "FTL"; break; + case CancelPath: + pathName = "Cancelled"; + break; default: RELEASE_ASSERT_NOT_REACHED(); +#if COMPILER_QUIRK(CONSIDERS_UNREACHABLE_CODE) pathName = ""; +#endif break; } - double now = currentTimeMS(); - dataLog("Optimized ", *codeBlock->alternative(), " using ", mode, " with ", pathName, " in ", now - before, " ms"); + dataLog("Optimized ", codeBlockName, " using ", mode, " with ", pathName, " into ", finalizer ? finalizer->codeSize() : 0, " bytes in ", after - before, " ms"); if (path == FTLPath) - dataLog(" (DFG: ", beforeFTL - before, ", LLVM: ", now - beforeFTL, ")"); + dataLog(" (DFG: ", m_timeBeforeFTL - before, ", B3: ", after - m_timeBeforeFTL, ")"); dataLog(".\n"); } } Plan::CompilationPath Plan::compileInThreadImpl(LongLivedState& longLivedState) { - if (verboseCompilationEnabled() && osrEntryBytecodeIndex != UINT_MAX) { + if (verboseCompilationEnabled(mode) && osrEntryBytecodeIndex != UINT_MAX) { dataLog("\n"); dataLog("Compiler must handle OSR entry from bc#", osrEntryBytecodeIndex, " with values: ", mustHandleValues, "\n"); dataLog("\n"); @@ -162,9 +239,11 @@ Plan::CompilationPath Plan::compileInThreadImpl(LongLivedState& longLivedState) Graph dfg(vm, *this, longLivedState); if (!parse(dfg)) { - finalizer = adoptPtr(new FailedFinalizer(*this)); + finalizer = std::make_unique<FailedFinalizer>(*this); return FailPath; } + + codeBlock->setCalleeSaveRegisters(RegisterSet::dfgCalleeSaveRegisters()); // By this point the DFG bytecode parser will have potentially mutated various tables // in the CodeBlock. This is a good time to perform an early shrink, which is more @@ -175,14 +254,26 @@ Plan::CompilationPath Plan::compileInThreadImpl(LongLivedState& longLivedState) if (validationEnabled()) validate(dfg); + if (Options::dumpGraphAfterParsing()) { + dataLog("Graph after parsing:\n"); + dfg.dump(); + } + + performLiveCatchVariablePreservationPhase(dfg); + + if (Options::useMaximalFlushInsertionPhase()) + performMaximalFlushInsertion(dfg); + performCPSRethreading(dfg); performUnification(dfg); performPredictionInjection(dfg); + performStaticExecutionCountEstimation(dfg); + if (mode == FTLForOSREntryMode) { bool result = performOSREntrypointCreation(dfg); if (!result) { - finalizer = adoptPtr(new FailedFinalizer(*this)); + finalizer = std::make_unique<FailedFinalizer>(*this); return FailPath; } performCPSRethreading(dfg); @@ -194,66 +285,91 @@ Plan::CompilationPath Plan::compileInThreadImpl(LongLivedState& longLivedState) performBackwardsPropagation(dfg); performPredictionPropagation(dfg); performFixup(dfg); + performStructureRegistration(dfg); performInvalidationPointInjection(dfg); performTypeCheckHoisting(dfg); - unsigned count = 1; dfg.m_fixpointState = FixpointNotConverged; - for (;; ++count) { - if (logCompilationChanges()) - dataLogF("DFG beginning optimization fixpoint iteration #%u.\n", count); - bool changed = false; + + // For now we're back to avoiding a fixpoint. Note that we've ping-ponged on this decision + // many times. For maximum throughput, it's best to fixpoint. But the throughput benefit is + // small and not likely to show up in FTL anyway. On the other hand, not fixpointing means + // that the compiler compiles more quickly. We want the third tier to compile quickly, which + // not fixpointing accomplishes; and the fourth tier shouldn't need a fixpoint. + if (validationEnabled()) + validate(dfg); - if (validationEnabled()) - validate(dfg); + performStrengthReduction(dfg); + performLocalCSE(dfg); + performCPSRethreading(dfg); + performCFA(dfg); + performConstantFolding(dfg); + bool changed = false; + changed |= performCFGSimplification(dfg); + changed |= performLocalCSE(dfg); + + if (validationEnabled()) + validate(dfg); + + performCPSRethreading(dfg); + if (!isFTL(mode)) { + // Only run this if we're not FTLing, because currently for a LoadVarargs that is forwardable and + // in a non-varargs inlined call frame, this will generate ForwardVarargs while the FTL + // ArgumentsEliminationPhase will create a sequence of GetStack+PutStacks. The GetStack+PutStack + // sequence then gets sunk, eliminating anything that looks like an escape for subsequent phases, + // while the ForwardVarargs doesn't get simplified until later (or not at all) and looks like an + // escape for all of the arguments. This then disables object allocation sinking. + // + // So, for now, we just disable this phase for the FTL. + // + // If we wanted to enable it, we'd have to do any of the following: + // - Enable ForwardVarargs->GetStack+PutStack strength reduction, and have that run before + // PutStack sinking and object allocation sinking. + // - Make VarargsForwarding emit a GetLocal+SetLocal sequence, that we can later turn into + // GetStack+PutStack. + // + // But, it's not super valuable to enable those optimizations, since the FTL + // ArgumentsEliminationPhase does everything that this phase does, and it doesn't introduce this + // pathology. - changed |= performStrengthReduction(dfg); + changed |= performVarargsForwarding(dfg); // Do this after CFG simplification and CPS rethreading. + } + if (changed) { performCFA(dfg); - changed |= performConstantFolding(dfg); - changed |= performArgumentsSimplification(dfg); - changed |= performCFGSimplification(dfg); - changed |= performCSE(dfg); - - if (!changed) - break; - - performCPSRethreading(dfg); + performConstantFolding(dfg); } - if (logCompilationChanges()) - dataLogF("DFG optimization fixpoint converged in %u iterations.\n", count); - - dfg.m_fixpointState = FixpointConverged; - - performStoreBarrierElision(dfg); - performStoreElimination(dfg); - // If we're doing validation, then run some analyses, to give them an opportunity // to self-validate. Now is as good a time as any to do this. if (validationEnabled()) { - dfg.m_dominators.computeIfNecessary(dfg); - dfg.m_naturalLoops.computeIfNecessary(dfg); + dfg.ensureDominators(); + dfg.ensureNaturalLoops(); + dfg.ensurePrePostNumbering(); } switch (mode) { case DFGMode: { + dfg.m_fixpointState = FixpointConverged; + performTierUpCheckInjection(dfg); + performFastStoreBarrierInsertion(dfg); + performCleanUp(dfg); performCPSRethreading(dfg); performDCE(dfg); + if (Options::useCopyBarrierOptimization()) + performCopyBarrierOptimization(dfg); + performPhantomInsertion(dfg); performStackLayout(dfg); performVirtualRegisterAllocation(dfg); performWatchpointCollection(dfg); dumpAndVerifyGraph(dfg, "Graph after optimization:"); JITCompiler dataFlowJIT(dfg); - if (codeBlock->codeType() == FunctionCode) { + if (codeBlock->codeType() == FunctionCode) dataFlowJIT.compileFunction(); - dataFlowJIT.linkFunction(); - } else { + else dataFlowJIT.compile(); - dataFlowJIT.link(); - } return DFGPath; } @@ -262,53 +378,121 @@ Plan::CompilationPath Plan::compileInThreadImpl(LongLivedState& longLivedState) case FTLForOSREntryMode: { #if ENABLE(FTL_JIT) if (FTL::canCompile(dfg) == FTL::CannotCompile) { - finalizer = adoptPtr(new FailedFinalizer(*this)); + finalizer = std::make_unique<FailedFinalizer>(*this); return FailPath; } + performCleanUp(dfg); // Reduce the graph size a bit. performCriticalEdgeBreaking(dfg); - performLoopPreHeaderCreation(dfg); + if (Options::createPreHeaders()) + performLoopPreHeaderCreation(dfg); performCPSRethreading(dfg); performSSAConversion(dfg); performSSALowering(dfg); + + // Ideally, these would be run to fixpoint with the object allocation sinking phase. + performArgumentsElimination(dfg); + if (Options::usePutStackSinking()) + performPutStackSinking(dfg); + + performConstantHoisting(dfg); + performGlobalCSE(dfg); + performLivenessAnalysis(dfg); + performIntegerRangeOptimization(dfg); performLivenessAnalysis(dfg); performCFA(dfg); + performConstantFolding(dfg); + performCleanUp(dfg); // Reduce the graph size a lot. + changed = false; + changed |= performStrengthReduction(dfg); + if (Options::useObjectAllocationSinking()) { + changed |= performCriticalEdgeBreaking(dfg); + changed |= performObjectAllocationSinking(dfg); + } + if (changed) { + // State-at-tail and state-at-head will be invalid if we did strength reduction since + // it might increase live ranges. + performLivenessAnalysis(dfg); + performCFA(dfg); + performConstantFolding(dfg); + } + + // Currently, this relies on pre-headers still being valid. That precludes running CFG + // simplification before it, unless we re-created the pre-headers. There wouldn't be anything + // wrong with running LICM earlier, if we wanted to put other CFG transforms above this point. + // Alternatively, we could run loop pre-header creation after SSA conversion - but if we did that + // then we'd need to do some simple SSA fix-up. performLICM(dfg); - performCSE(dfg); + + performCleanUp(dfg); + performIntegerCheckCombining(dfg); + performGlobalCSE(dfg); + + // At this point we're not allowed to do any further code motion because our reasoning + // about code motion assumes that it's OK to insert GC points in random places. + dfg.m_fixpointState = FixpointConverged; + performLivenessAnalysis(dfg); performCFA(dfg); - if (Options::validateFTLOSRExitLiveness()) - performResurrectionForValidation(dfg); - performDCE(dfg); // We rely on this to convert dead SetLocals into the appropriate hint, and to kill dead code that won't be recognized as dead by LLVM. + performGlobalStoreBarrierInsertion(dfg); + if (Options::useMovHintRemoval()) + performMovHintRemoval(dfg); + performCleanUp(dfg); + performDCE(dfg); // We rely on this to kill dead code that won't be recognized as dead by B3. + if (Options::useCopyBarrierOptimization()) + performCopyBarrierOptimization(dfg); performStackLayout(dfg); performLivenessAnalysis(dfg); - performFlushLivenessAnalysis(dfg); performOSRAvailabilityAnalysis(dfg); performWatchpointCollection(dfg); - dumpAndVerifyGraph(dfg, "Graph just before FTL lowering:"); + if (FTL::canCompile(dfg) == FTL::CannotCompile) { + finalizer = std::make_unique<FailedFinalizer>(*this); + return FailPath; + } + + dumpAndVerifyGraph(dfg, "Graph just before FTL lowering:", shouldDumpDisassembly(mode)); + + // Flash a safepoint in case the GC wants some action. + Safepoint::Result safepointResult; + { + GraphSafepoint safepoint(dfg, safepointResult); + } + if (safepointResult.didGetCancelled()) + return CancelPath; + + FTL::State state(dfg); + FTL::lowerDFGToB3(state); - initializeLLVM(); + if (computeCompileTimes()) + m_timeBeforeFTL = monotonicallyIncreasingTimeMS(); - FTL::State state(dfg); - FTL::lowerDFGToLLVM(state); + if (Options::b3AlwaysFailsBeforeCompile()) { + FTL::fail(state); + return FTLPath; + } - if (Options::reportCompileTimes()) - beforeFTL = currentTimeMS(); + FTL::compile(state, safepointResult); + if (safepointResult.didGetCancelled()) + return CancelPath; - if (Options::llvmAlwaysFailsBeforeCompile()) { + if (Options::b3AlwaysFailsBeforeLink()) { FTL::fail(state); return FTLPath; } - FTL::compile(state); + if (state.allocationFailed) { + FTL::fail(state); + return FTLPath; + } - if (Options::llvmAlwaysFailsBeforeLink()) { + FTL::link(state); + + if (state.allocationFailed) { FTL::fail(state); return FTLPath; } - FTL::link(state); return FTLPath; #else RELEASE_ASSERT_NOT_REACHED(); @@ -324,37 +508,52 @@ Plan::CompilationPath Plan::compileInThreadImpl(LongLivedState& longLivedState) bool Plan::isStillValid() { - return watchpoints.areStillValid() - && chains.areStillValid(); + CodeBlock* replacement = codeBlock->replacement(); + if (!replacement) + return false; + // FIXME: This is almost certainly not necessary. There's no way for the baseline + // code to be replaced during a compilation, except if we delete the plan, in which + // case we wouldn't be here. + // https://bugs.webkit.org/show_bug.cgi?id=132707 + if (codeBlock->alternative() != replacement->baselineVersion()) + return false; + if (!watchpoints.areStillValid()) + return false; + return true; } void Plan::reallyAdd(CommonData* commonData) { - watchpoints.reallyAdd(codeBlock.get(), *commonData); + watchpoints.reallyAdd(codeBlock, *commonData); identifiers.reallyAdd(vm, commonData); weakReferences.reallyAdd(vm, commonData); transitions.reallyAdd(vm, commonData); - writeBarriers.trigger(vm); +} + +void Plan::notifyCompiling() +{ + stage = Compiling; +} + +void Plan::notifyCompiled() +{ + stage = Compiled; } void Plan::notifyReady() { - callback->compilationDidBecomeReadyAsynchronously(codeBlock.get()); - isCompiled = true; + callback->compilationDidBecomeReadyAsynchronously(codeBlock, profiledDFGCodeBlock); + stage = Ready; } CompilationResult Plan::finalizeWithoutNotifyingCallback() { + // We will establish new references from the code block to things. So, we need a barrier. + vm.heap.writeBarrier(codeBlock); + if (!isStillValid()) return CompilationInvalidated; - if (vm.enabledProfiler()) - return CompilationInvalidated; - - Debugger* debugger = codeBlock->globalObject()->debugger(); - if (debugger && (debugger->isStepping() || codeBlock->baselineAlternative()->hasDebuggerRequests())) - return CompilationInvalidated; - bool result; if (codeBlock->codeType() == FunctionCode) result = finalizer->finalizeFunction(); @@ -366,12 +565,27 @@ CompilationResult Plan::finalizeWithoutNotifyingCallback() reallyAdd(codeBlock->jitCode()->dfgCommon()); + if (validationEnabled()) { + TrackedReferences trackedReferences; + + for (WriteBarrier<JSCell>& reference : codeBlock->jitCode()->dfgCommon()->weakReferences) + trackedReferences.add(reference.get()); + for (WriteBarrier<Structure>& reference : codeBlock->jitCode()->dfgCommon()->weakStructureReferences) + trackedReferences.add(reference.get()); + for (WriteBarrier<Unknown>& constant : codeBlock->constants()) + trackedReferences.add(constant.get()); + + // Check that any other references that we have anywhere in the JITCode are also + // tracked either strongly or weakly. + codeBlock->jitCode()->validateReferences(trackedReferences); + } + return CompilationSuccessful; } void Plan::finalizeAndNotifyCallback() { - callback->compilationDidComplete(codeBlock.get(), finalizeWithoutNotifyingCallback()); + callback->compilationDidComplete(codeBlock, profiledDFGCodeBlock, finalizeWithoutNotifyingCallback()); } CompilationKey Plan::key() @@ -379,6 +593,83 @@ CompilationKey Plan::key() return CompilationKey(codeBlock->alternative(), mode); } +void Plan::rememberCodeBlocks() +{ + // Compilation writes lots of values to a CodeBlock without performing + // an explicit barrier. So, we need to be pessimistic and assume that + // all our CodeBlocks must be visited during GC. + + Heap::heap(codeBlock)->writeBarrier(codeBlock); + Heap::heap(codeBlock)->writeBarrier(codeBlock->alternative()); + if (profiledDFGCodeBlock) + Heap::heap(profiledDFGCodeBlock)->writeBarrier(profiledDFGCodeBlock); +} + +void Plan::checkLivenessAndVisitChildren(SlotVisitor& visitor) +{ + if (!isKnownToBeLiveDuringGC()) + return; + + for (unsigned i = mustHandleValues.size(); i--;) + visitor.appendUnbarrieredValue(&mustHandleValues[i]); + + visitor.appendUnbarrieredReadOnlyPointer(codeBlock); + visitor.appendUnbarrieredReadOnlyPointer(codeBlock->alternative()); + visitor.appendUnbarrieredReadOnlyPointer(profiledDFGCodeBlock); + + if (inlineCallFrames) { + for (auto* inlineCallFrame : *inlineCallFrames) { + ASSERT(inlineCallFrame->baselineCodeBlock.get()); + visitor.appendUnbarrieredReadOnlyPointer(inlineCallFrame->baselineCodeBlock.get()); + } + } + + weakReferences.visitChildren(visitor); + transitions.visitChildren(visitor); +} + +bool Plan::isKnownToBeLiveDuringGC() +{ + if (stage == Cancelled) + return false; + if (!Heap::isMarked(codeBlock->ownerExecutable())) + return false; + if (!Heap::isMarked(codeBlock->alternative())) + return false; + if (!!profiledDFGCodeBlock && !Heap::isMarked(profiledDFGCodeBlock)) + return false; + return true; +} + +void Plan::cancel() +{ + codeBlock = nullptr; + profiledDFGCodeBlock = nullptr; + mustHandleValues.clear(); + compilation = nullptr; + finalizer = nullptr; + inlineCallFrames = nullptr; + watchpoints = DesiredWatchpoints(); + identifiers = DesiredIdentifiers(); + weakReferences = DesiredWeakReferences(); + transitions = DesiredTransitions(); + callback = nullptr; + stage = Cancelled; +} + +HashMap<CString, double> Plan::compileTimeStats() +{ + HashMap<CString, double> result; + if (Options::reportTotalCompileTimes()) { + result.add("Compile Time", totalDFGCompileTime + totalFTLCompileTime); + result.add("DFG Compile Time", totalDFGCompileTime); + result.add("FTL Compile Time", totalFTLCompileTime); + result.add("FTL (DFG) Compile Time", totalFTLDFGCompileTime); + result.add("FTL (B3) Compile Time", totalFTLB3CompileTime); + } + return result; +} + } } // namespace JSC::DFG #endif // ENABLE(DFG_JIT) |
