|  | /* | 
|  | * Copyright (C) 2013-2020 Apple Inc. All rights reserved. | 
|  | * | 
|  | * Redistribution and use in source and binary forms, with or without | 
|  | * modification, are permitted provided that the following conditions | 
|  | * are met: | 
|  | * 1. Redistributions of source code must retain the above copyright | 
|  | *    notice, this list of conditions and the following disclaimer. | 
|  | * 2. Redistributions in binary form must reproduce the above copyright | 
|  | *    notice, this list of conditions and the following disclaimer in the | 
|  | *    documentation and/or other materials provided with the distribution. | 
|  | * | 
|  | * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY | 
|  | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
|  | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 
|  | * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR | 
|  | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 
|  | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 
|  | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 
|  | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | 
|  | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
|  | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
|  | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
|  | */ | 
|  |  | 
|  | #pragma once | 
|  |  | 
|  | #include "CompilationResult.h" | 
|  | #include "DFGCompilationKey.h" | 
|  | #include "DFGCompilationMode.h" | 
|  | #include "DFGDesiredGlobalProperties.h" | 
|  | #include "DFGDesiredIdentifiers.h" | 
|  | #include "DFGDesiredTransitions.h" | 
|  | #include "DFGDesiredWatchpoints.h" | 
|  | #include "DFGDesiredWeakReferences.h" | 
|  | #include "DFGFinalizer.h" | 
|  | #include "DeferredCompilationCallback.h" | 
|  | #include "Operands.h" | 
|  | #include "ProfilerCompilation.h" | 
|  | #include "RecordedStatuses.h" | 
|  | #include <wtf/HashMap.h> | 
|  | #include <wtf/ThreadSafeRefCounted.h> | 
|  |  | 
|  | namespace JSC { | 
|  |  | 
|  | class CodeBlock; | 
|  | class SlotVisitor; | 
|  |  | 
|  | namespace DFG { | 
|  |  | 
|  | class ThreadData; | 
|  |  | 
|  | #if ENABLE(DFG_JIT) | 
|  |  | 
|  | class Plan : public ThreadSafeRefCounted<Plan> { | 
|  | public: | 
|  | Plan( | 
|  | CodeBlock* codeBlockToCompile, CodeBlock* profiledDFGCodeBlock, | 
|  | CompilationMode, BytecodeIndex osrEntryBytecodeIndex, | 
|  | const Operands<Optional<JSValue>>& mustHandleValues); | 
|  | ~Plan(); | 
|  |  | 
|  | void compileInThread(ThreadData*); | 
|  |  | 
|  | CompilationResult finalizeWithoutNotifyingCallback(); | 
|  | void finalizeAndNotifyCallback(); | 
|  |  | 
|  | void notifyCompiling(); | 
|  | void notifyReady(); | 
|  |  | 
|  | CompilationKey key(); | 
|  |  | 
|  | template<typename Func> | 
|  | void iterateCodeBlocksForGC(const Func&); | 
|  | void checkLivenessAndVisitChildren(SlotVisitor&); | 
|  | bool isKnownToBeLiveDuringGC(); | 
|  | void finalizeInGC(); | 
|  | void cancel(); | 
|  |  | 
|  | bool canTierUpAndOSREnter() const { return !m_tierUpAndOSREnterBytecodes.isEmpty(); } | 
|  |  | 
|  | void cleanMustHandleValuesIfNecessary(); | 
|  |  | 
|  | VM* vm() const { return m_vm; } | 
|  |  | 
|  | CodeBlock* codeBlock() { return m_codeBlock; } | 
|  |  | 
|  | bool isFTL() const { return DFG::isFTL(m_mode); } | 
|  | CompilationMode mode() const { return m_mode; } | 
|  | BytecodeIndex osrEntryBytecodeIndex() const { return m_osrEntryBytecodeIndex; } | 
|  | const Operands<Optional<JSValue>>& mustHandleValues() const { return m_mustHandleValues; } | 
|  | ThreadData* threadData() const { return m_threadData; } | 
|  | Profiler::Compilation* compilation() const { return m_compilation.get(); } | 
|  |  | 
|  | Finalizer* finalizer() const { return m_finalizer.get(); } | 
|  | void setFinalizer(std::unique_ptr<Finalizer>&& finalizer) { m_finalizer = WTFMove(finalizer); } | 
|  |  | 
|  | RefPtr<InlineCallFrameSet> inlineCallFrames() const { return m_inlineCallFrames; } | 
|  | DesiredWatchpoints& watchpoints() { return m_watchpoints; } | 
|  | DesiredIdentifiers& identifiers() { return m_identifiers; } | 
|  | DesiredWeakReferences& weakReferences() { return m_weakReferences; } | 
|  | DesiredTransitions& transitions() { return m_transitions; } | 
|  | DesiredGlobalProperties& globalProperties() { return m_globalProperties; } | 
|  | RecordedStatuses& recordedStatuses() { return m_recordedStatuses; } | 
|  |  | 
|  | bool willTryToTierUp() const { return m_willTryToTierUp; } | 
|  | void setWillTryToTierUp(bool willTryToTierUp) { m_willTryToTierUp = willTryToTierUp; } | 
|  |  | 
|  | HashMap<BytecodeIndex, Vector<BytecodeIndex>>& tierUpInLoopHierarchy() { return m_tierUpInLoopHierarchy; } | 
|  | Vector<BytecodeIndex>& tierUpAndOSREnterBytecodes() { return m_tierUpAndOSREnterBytecodes; } | 
|  |  | 
|  | enum Stage { Preparing, Compiling, Ready, Cancelled }; | 
|  | Stage stage() const { return m_stage; } | 
|  |  | 
|  | DeferredCompilationCallback* callback() const { return m_callback.get(); } | 
|  | void setCallback(Ref<DeferredCompilationCallback>&& callback) { m_callback = WTFMove(callback); } | 
|  |  | 
|  | private: | 
|  | bool computeCompileTimes() const; | 
|  | bool reportCompileTimes() const; | 
|  |  | 
|  | enum CompilationPath { FailPath, DFGPath, FTLPath, CancelPath }; | 
|  | CompilationPath compileInThreadImpl(); | 
|  |  | 
|  | bool isStillValidOnMainThread(); | 
|  | bool isStillValid(); | 
|  | void reallyAdd(CommonData*); | 
|  |  | 
|  | // Warning: pretty much all of the pointer fields in this object get nulled by cancel(). So, if | 
|  | // you're writing code that is callable on the cancel path, be sure to null check everything! | 
|  |  | 
|  | CompilationMode m_mode; | 
|  |  | 
|  | VM* m_vm; | 
|  |  | 
|  | // These can be raw pointers because we visit them during every GC in checkLivenessAndVisitChildren. | 
|  | CodeBlock* m_codeBlock; | 
|  | CodeBlock* m_profiledDFGCodeBlock; | 
|  |  | 
|  | Operands<Optional<JSValue>> m_mustHandleValues; | 
|  | bool m_mustHandleValuesMayIncludeGarbage { true }; | 
|  | Lock m_mustHandleValueCleaningLock; | 
|  |  | 
|  | bool m_willTryToTierUp { false }; | 
|  |  | 
|  | const BytecodeIndex m_osrEntryBytecodeIndex; | 
|  |  | 
|  | ThreadData* m_threadData; | 
|  |  | 
|  | RefPtr<Profiler::Compilation> m_compilation; | 
|  |  | 
|  | std::unique_ptr<Finalizer> m_finalizer; | 
|  |  | 
|  | RefPtr<InlineCallFrameSet> m_inlineCallFrames; | 
|  | DesiredWatchpoints m_watchpoints; | 
|  | DesiredIdentifiers m_identifiers; | 
|  | DesiredWeakReferences m_weakReferences; | 
|  | DesiredTransitions m_transitions; | 
|  | DesiredGlobalProperties m_globalProperties; | 
|  | RecordedStatuses m_recordedStatuses; | 
|  |  | 
|  | HashMap<BytecodeIndex, Vector<BytecodeIndex>> m_tierUpInLoopHierarchy; | 
|  | Vector<BytecodeIndex> m_tierUpAndOSREnterBytecodes; | 
|  |  | 
|  | Stage m_stage; | 
|  |  | 
|  | RefPtr<DeferredCompilationCallback> m_callback; | 
|  |  | 
|  | MonotonicTime m_timeBeforeFTL; | 
|  | }; | 
|  |  | 
|  | #endif // ENABLE(DFG_JIT) | 
|  |  | 
|  | } } // namespace JSC::DFG |