OSR entry: delay outer-loop compilation when at inner-loop
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGJITCode.h
1 /*
2  * Copyright (C) 2013-2015 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 #pragma once
27
28 #if ENABLE(DFG_JIT)
29
30 #include "CodeBlock.h"
31 #include "CompilationResult.h"
32 #include "DFGCommonData.h"
33 #include "DFGMinifiedGraph.h"
34 #include "DFGOSREntry.h"
35 #include "DFGOSRExit.h"
36 #include "DFGTierUpEntryTrigger.h"
37 #include "DFGVariableEventStream.h"
38 #include "ExecutionCounter.h"
39 #include "JITCode.h"
40 #include <wtf/SegmentedVector.h>
41
42 namespace JSC {
43
44 class TrackedReferences;
45
46 namespace DFG {
47
48 class JITCompiler;
49
50 class JITCode : public DirectJITCode {
51 public:
52     JITCode();
53     virtual ~JITCode();
54     
55     CommonData* dfgCommon() override;
56     JITCode* dfg() override;
57     
58     OSREntryData* appendOSREntryData(unsigned bytecodeIndex, unsigned machineCodeOffset)
59     {
60         DFG::OSREntryData entry;
61         entry.m_bytecodeIndex = bytecodeIndex;
62         entry.m_machineCodeOffset = machineCodeOffset;
63         osrEntry.append(entry);
64         return &osrEntry.last();
65     }
66     
67     OSREntryData* osrEntryDataForBytecodeIndex(unsigned bytecodeIndex)
68     {
69         return tryBinarySearch<OSREntryData, unsigned>(
70             osrEntry, osrEntry.size(), bytecodeIndex,
71             getOSREntryDataBytecodeIndex);
72     }
73     
74     unsigned appendOSRExit(const OSRExit& exit)
75     {
76         unsigned result = osrExit.size();
77         osrExit.append(exit);
78         return result;
79     }
80     
81     OSRExit& lastOSRExit()
82     {
83         return osrExit.last();
84     }
85     
86     unsigned appendSpeculationRecovery(const SpeculationRecovery& recovery)
87     {
88         unsigned result = speculationRecovery.size();
89         speculationRecovery.append(recovery);
90         return result;
91     }
92     
93     void reconstruct(
94         CodeBlock*, CodeOrigin, unsigned streamIndex, Operands<ValueRecovery>& result);
95     
96     // This is only applicable if we're at a point where all values are spilled to the
97     // stack. Currently, it also has the restriction that the values must be in their
98     // bytecode-designated stack slots.
99     void reconstruct(
100         ExecState*, CodeBlock*, CodeOrigin, unsigned streamIndex, Operands<JSValue>& result);
101
102 #if ENABLE(FTL_JIT)
103     // NB. All of these methods take CodeBlock* because they may want to use
104     // CodeBlock's logic about scaling thresholds. It should be a DFG CodeBlock.
105     
106     bool checkIfOptimizationThresholdReached(CodeBlock*);
107     void optimizeNextInvocation(CodeBlock*);
108     void dontOptimizeAnytimeSoon(CodeBlock*);
109     void optimizeAfterWarmUp(CodeBlock*);
110     void optimizeSoon(CodeBlock*);
111     void forceOptimizationSlowPathConcurrently(CodeBlock*);
112     void setOptimizationThresholdBasedOnCompilationResult(CodeBlock*, CompilationResult);
113 #endif // ENABLE(FTL_JIT)
114     
115     void validateReferences(const TrackedReferences&) override;
116     
117     void shrinkToFit();
118
119     RegisterSet liveRegistersToPreserveAtExceptionHandlingCallSite(CodeBlock*, CallSiteIndex) override;
120 #if ENABLE(FTL_JIT)
121     CodeBlock* osrEntryBlock() { return m_osrEntryBlock.get(); }
122     void setOSREntryBlock(VM& vm, const JSCell* owner, CodeBlock* osrEntryBlock) { m_osrEntryBlock.set(vm, owner, osrEntryBlock); }
123     void clearOSREntryBlock() { m_osrEntryBlock.clear(); }
124 #endif
125
126     static ptrdiff_t commonDataOffset() { return OBJECT_OFFSETOF(JITCode, common); }
127
128     std::optional<CodeOrigin> findPC(CodeBlock*, void* pc) override;
129     
130 private:
131     friend class JITCompiler; // Allow JITCompiler to call setCodeRef().
132
133 public:
134     CommonData common;
135     Vector<DFG::OSREntryData> osrEntry;
136     SegmentedVector<DFG::OSRExit, 8> osrExit;
137     Vector<DFG::SpeculationRecovery> speculationRecovery;
138     DFG::VariableEventStream variableEventStream;
139     DFG::MinifiedGraph minifiedDFG;
140 #if ENABLE(FTL_JIT)
141     uint8_t neverExecutedEntry { 1 };
142
143     UpperTierExecutionCounter tierUpCounter;
144
145     // For osrEntryPoint that are in inner loop, this maps their bytecode to the bytecode
146     // of the outerloop entry points in order (from innermost to outermost).
147     //
148     // The key may not always be a target for OSR Entry but the list in the value is guaranteed
149     // to be usable for OSR Entry.
150     HashMap<unsigned, Vector<unsigned>> tierUpInLoopHierarchy;
151
152     // Map each bytecode of CheckTierUpAndOSREnter to its stream index.
153     HashMap<unsigned, unsigned, WTF::IntHash<unsigned>, WTF::UnsignedWithZeroKeyHashTraits<unsigned>> bytecodeIndexToStreamIndex;
154
155     // Map each bytecode of CheckTierUpAndOSREnter to its trigger forcing OSR Entry.
156     // This can never be modified after it has been initialized since the addresses of the triggers
157     // are used by the JIT.
158     HashMap<unsigned, TierUpEntryTrigger> tierUpEntryTriggers;
159
160     // Set of bytecode that were the target of a TierUp operation.
161     HashSet<unsigned, WTF::IntHash<unsigned>, WTF::UnsignedWithZeroKeyHashTraits<unsigned>> tierUpEntrySeen;
162
163     WriteBarrier<CodeBlock> m_osrEntryBlock;
164     unsigned osrEntryRetry;
165     bool abandonOSREntry;
166 #endif // ENABLE(FTL_JIT)
167 };
168
169 } } // namespace JSC::DFG
170
171 #endif // ENABLE(DFG_JIT)