]> git.saurik.com Git - apple/javascriptcore.git/blame - dfg/DFGJITCompiler.h
JavaScriptCore-7600.1.4.15.12.tar.gz
[apple/javascriptcore.git] / dfg / DFGJITCompiler.h
CommitLineData
14957cd0 1/*
81345200 2 * Copyright (C) 2011, 2013, 2014 Apple Inc. All rights reserved.
14957cd0
A
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#ifndef DFGJITCompiler_h
27#define DFGJITCompiler_h
28
29#if ENABLE(DFG_JIT)
30
81345200 31#include "CCallHelpers.h"
93a37866 32#include "CodeBlock.h"
93a37866 33#include "DFGDisassembler.h"
93a37866 34#include "DFGGraph.h"
81345200
A
35#include "DFGInlineCacheWrapper.h"
36#include "DFGJITCode.h"
93a37866
A
37#include "DFGOSRExitCompilationInfo.h"
38#include "DFGRegisterBank.h"
81345200
A
39#include "FPRInfo.h"
40#include "GPRInfo.h"
93a37866 41#include "JITCode.h"
81345200 42#include "JITInlineCacheGenerator.h"
93a37866
A
43#include "LinkBuffer.h"
44#include "MacroAssembler.h"
81345200 45#include "TempRegisterSet.h"
14957cd0 46
14957cd0
A
47namespace JSC {
48
49class AbstractSamplingCounter;
50class CodeBlock;
93a37866 51class VM;
14957cd0
A
52
53namespace DFG {
54
55class JITCodeGenerator;
6fe7ccc8 56class NodeToRegisterMap;
93a37866
A
57class OSRExitJumpPlaceholder;
58class SlowPathGenerator;
14957cd0
A
59class SpeculativeJIT;
60class SpeculationRecovery;
61
62struct EntryLocation;
6fe7ccc8 63struct OSRExit;
14957cd0 64
6fe7ccc8 65// === CallLinkRecord ===
14957cd0 66//
6fe7ccc8
A
67// A record of a call out from JIT code that needs linking to a helper function.
68// Every CallLinkRecord contains a reference to the call instruction & the function
69// that it needs to be linked to.
70struct CallLinkRecord {
71 CallLinkRecord(MacroAssembler::Call call, FunctionPtr function)
14957cd0
A
72 : m_call(call)
73 , m_function(function)
74 {
75 }
76
6fe7ccc8
A
77 MacroAssembler::Call m_call;
78 FunctionPtr m_function;
79};
80
81345200
A
81struct InRecord {
82 InRecord(
83 MacroAssembler::PatchableJump jump, MacroAssembler::Label done,
84 SlowPathGenerator* slowPathGenerator, StructureStubInfo* stubInfo)
85 : m_jump(jump)
93a37866 86 , m_done(done)
81345200
A
87 , m_slowPathGenerator(slowPathGenerator)
88 , m_stubInfo(stubInfo)
6fe7ccc8
A
89 {
90 }
81345200
A
91
92 MacroAssembler::PatchableJump m_jump;
93a37866 93 MacroAssembler::Label m_done;
81345200
A
94 SlowPathGenerator* m_slowPathGenerator;
95 StructureStubInfo* m_stubInfo;
14957cd0
A
96};
97
98// === JITCompiler ===
99//
100// DFG::JITCompiler is responsible for generating JIT code from the dataflow graph.
101// It does so by delegating to the speculative & non-speculative JITs, which
102// generate to a MacroAssembler (which the JITCompiler owns through an inheritance
103// relationship). The JITCompiler holds references to information required during
104// compilation, and also records information used in linking (e.g. a list of all
105// call to be linked).
6fe7ccc8 106class JITCompiler : public CCallHelpers {
14957cd0 107public:
93a37866 108 JITCompiler(Graph& dfg);
81345200 109 ~JITCompiler();
93a37866 110
81345200
A
111 void compile();
112 void compileFunction();
113
114 void link();
115 void linkFunction();
14957cd0
A
116
117 // Accessors for properties.
118 Graph& graph() { return m_graph; }
6fe7ccc8 119
93a37866
A
120 // Methods to set labels for the disassembler.
121 void setStartOfCode()
122 {
123 if (LIKELY(!m_disassembler))
124 return;
125 m_disassembler->setStartOfCode(labelIgnoringWatchpoints());
126 }
127
81345200 128 void setForBlockIndex(BlockIndex blockIndex)
93a37866
A
129 {
130 if (LIKELY(!m_disassembler))
131 return;
81345200 132 m_disassembler->setForBlockIndex(blockIndex, labelIgnoringWatchpoints());
93a37866
A
133 }
134
135 void setForNode(Node* node)
136 {
137 if (LIKELY(!m_disassembler))
138 return;
139 m_disassembler->setForNode(node, labelIgnoringWatchpoints());
140 }
141
142 void setEndOfMainPath()
143 {
144 if (LIKELY(!m_disassembler))
145 return;
146 m_disassembler->setEndOfMainPath(labelIgnoringWatchpoints());
147 }
148
149 void setEndOfCode()
150 {
151 if (LIKELY(!m_disassembler))
152 return;
153 m_disassembler->setEndOfCode(labelIgnoringWatchpoints());
154 }
155
81345200 156 void emitStoreCodeOrigin(CodeOrigin codeOrigin)
14957cd0 157 {
81345200
A
158 unsigned index = m_jitCode->common.addCodeOrigin(codeOrigin);
159 unsigned locationBits = CallFrame::Location::encodeAsCodeOriginIndex(index);
160 store32(TrustedImm32(locationBits), tagFor(static_cast<VirtualRegister>(JSStack::ArgumentCount)));
14957cd0
A
161 }
162
6fe7ccc8
A
163 // Add a call out from JIT code, without an exception check.
164 Call appendCall(const FunctionPtr& function)
14957cd0 165 {
6fe7ccc8
A
166 Call functionCall = call();
167 m_calls.append(CallLinkRecord(functionCall, function));
168 return functionCall;
14957cd0 169 }
93a37866 170
81345200 171 void exceptionCheck(Jump jumpToHandler)
93a37866 172 {
81345200
A
173 m_exceptionChecks.append(jumpToHandler);
174 }
175
176 void exceptionCheck()
177 {
178 m_exceptionChecks.append(emitExceptionCheck());
93a37866 179 }
14957cd0 180
81345200 181 void exceptionCheckWithCallFrameRollback()
14957cd0 182 {
81345200 183 m_exceptionChecksWithCallFrameRollback.append(emitExceptionCheck());
14957cd0 184 }
81345200 185
6fe7ccc8 186 // Add a call out from JIT code, with a fast exception check that tests if the return value is zero.
81345200 187 void fastExceptionCheck()
14957cd0 188 {
81345200
A
189 callExceptionFuzz();
190 m_exceptionChecks.append(branchTestPtr(Zero, GPRInfo::returnValueGPR));
14957cd0 191 }
6fe7ccc8 192
81345200 193 OSRExitCompilationInfo& appendExitInfo(MacroAssembler::JumpList jumpsToFail = MacroAssembler::JumpList())
93a37866
A
194 {
195 OSRExitCompilationInfo info;
196 info.m_failureJumps = jumpsToFail;
197 m_exitCompilationInfo.append(info);
81345200 198 return m_exitCompilationInfo.last();
93a37866 199 }
6fe7ccc8
A
200
201#if USE(JSVALUE32_64)
81345200
A
202 void* addressOfDoubleConstant(Node*);
203#endif
204
205 void addGetById(const JITGetByIdGenerator& gen, SlowPathGenerator* slowPath)
14957cd0 206 {
81345200
A
207 m_getByIds.append(InlineCacheWrapper<JITGetByIdGenerator>(gen, slowPath));
208 }
209
210 void addPutById(const JITPutByIdGenerator& gen, SlowPathGenerator* slowPath)
211 {
212 m_putByIds.append(InlineCacheWrapper<JITPutByIdGenerator>(gen, slowPath));
14957cd0 213 }
14957cd0 214
81345200 215 void addIn(const InRecord& record)
14957cd0 216 {
81345200
A
217 m_ins.append(record);
218 }
219
220 unsigned currentJSCallIndex() const
221 {
222 return m_jsCalls.size();
14957cd0
A
223 }
224
81345200 225 void addJSCall(Call fastCall, Call slowCall, DataLabelPtr targetToCheck, CallLinkInfo* info)
14957cd0 226 {
81345200 227 m_jsCalls.append(JSCallRecord(fastCall, slowCall, targetToCheck, info));
14957cd0 228 }
6fe7ccc8
A
229
230 void addWeakReference(JSCell* target)
14957cd0 231 {
81345200 232 m_graph.m_plan.weakReferences.addLazily(target);
14957cd0 233 }
6fe7ccc8 234
93a37866
A
235 void addWeakReferences(const StructureSet& structureSet)
236 {
237 for (unsigned i = structureSet.size(); i--;)
238 addWeakReference(structureSet[i]);
239 }
240
6fe7ccc8
A
241 template<typename T>
242 Jump branchWeakPtr(RelationalCondition cond, T left, JSCell* weakPtr)
14957cd0 243 {
6fe7ccc8
A
244 Jump result = branchPtr(cond, left, TrustedImmPtr(weakPtr));
245 addWeakReference(weakPtr);
246 return result;
14957cd0 247 }
81345200
A
248
249 template<typename T>
250 Jump branchWeakStructure(RelationalCondition cond, T left, Structure* weakStructure)
251 {
252#if USE(JSVALUE64)
253 Jump result = branch32(cond, left, TrustedImm32(weakStructure->id()));
254 addWeakReference(weakStructure);
255 return result;
256#else
257 return branchWeakPtr(cond, left, weakStructure);
258#endif
259 }
260
261 template<typename T>
262 Jump branchStructurePtr(RelationalCondition cond, T left, Structure* structure)
263 {
264#if USE(JSVALUE64)
265 return branch32(cond, left, TrustedImm32(structure->id()));
266#else
267 return branchPtr(cond, left, TrustedImmPtr(structure));
268#endif
269 }
270
6fe7ccc8 271 void noticeOSREntry(BasicBlock& basicBlock, JITCompiler::Label blockHead, LinkBuffer& linkBuffer)
14957cd0 272 {
93a37866
A
273 // OSR entry is not allowed into blocks deemed unreachable by control flow analysis.
274 if (!basicBlock.cfaHasVisited)
275 return;
276
81345200 277 OSREntryData* entry = m_jitCode->appendOSREntryData(basicBlock.bytecodeBegin, linkBuffer.offsetOf(blockHead));
6fe7ccc8
A
278
279 entry->m_expectedValues = basicBlock.valuesAtHead;
280
281 // Fix the expected values: in our protocol, a dead variable will have an expected
282 // value of (None, []). But the old JIT may stash some values there. So we really
283 // need (Top, TOP).
284 for (size_t argument = 0; argument < basicBlock.variablesAtHead.numberOfArguments(); ++argument) {
93a37866
A
285 Node* node = basicBlock.variablesAtHead.argument(argument);
286 if (!node || !node->shouldGenerate())
81345200 287 entry->m_expectedValues.argument(argument).makeHeapTop();
6fe7ccc8
A
288 }
289 for (size_t local = 0; local < basicBlock.variablesAtHead.numberOfLocals(); ++local) {
93a37866
A
290 Node* node = basicBlock.variablesAtHead.local(local);
291 if (!node || !node->shouldGenerate())
81345200
A
292 entry->m_expectedValues.local(local).makeHeapTop();
293 else {
294 VariableAccessData* variable = node->variableAccessData();
295 entry->m_machineStackUsed.set(variable->machineLocal().toLocal());
296
297 switch (variable->flushFormat()) {
298 case FlushedDouble:
299 entry->m_localsForcedDouble.set(local);
300 break;
301 case FlushedInt52:
302 entry->m_localsForcedMachineInt.set(local);
303 break;
304 default:
305 break;
306 }
307
308 if (variable->local() != variable->machineLocal()) {
309 entry->m_reshufflings.append(
310 OSREntryReshuffling(
311 variable->local().offset(), variable->machineLocal().offset()));
312 }
313 }
6fe7ccc8 314 }
81345200
A
315
316 entry->m_reshufflings.shrinkToFit();
6fe7ccc8 317 }
81345200
A
318
319 PassRefPtr<JITCode> jitCode() { return m_jitCode; }
320
321 Vector<Label>& blockHeads() { return m_blockHeads; }
14957cd0
A
322
323private:
93a37866
A
324 friend class OSRExitJumpPlaceholder;
325
6fe7ccc8
A
326 // Internal implementation to compile.
327 void compileEntry();
81345200 328 void compileBody();
6fe7ccc8 329 void link(LinkBuffer&);
81345200 330
6fe7ccc8 331 void exitSpeculativeWithOSR(const OSRExit&, SpeculationRecovery*);
93a37866 332 void compileExceptionHandlers();
6fe7ccc8 333 void linkOSRExits();
81345200 334 void disassemble(LinkBuffer&);
6fe7ccc8 335
14957cd0
A
336 // The dataflow graph currently being generated.
337 Graph& m_graph;
338
93a37866
A
339 OwnPtr<Disassembler> m_disassembler;
340
81345200
A
341 RefPtr<JITCode> m_jitCode;
342
14957cd0 343 // Vector of calls out from JIT code, including exception handler information.
6fe7ccc8
A
344 // Count of the number of CallRecords with exception handlers.
345 Vector<CallLinkRecord> m_calls;
81345200
A
346 JumpList m_exceptionChecks;
347 JumpList m_exceptionChecksWithCallFrameRollback;
6fe7ccc8 348
81345200
A
349 Vector<Label> m_blockHeads;
350
6fe7ccc8 351 struct JSCallRecord {
81345200 352 JSCallRecord(Call fastCall, Call slowCall, DataLabelPtr targetToCheck, CallLinkInfo* info)
6fe7ccc8
A
353 : m_fastCall(fastCall)
354 , m_slowCall(slowCall)
355 , m_targetToCheck(targetToCheck)
81345200 356 , m_info(info)
6fe7ccc8
A
357 {
358 }
359
360 Call m_fastCall;
361 Call m_slowCall;
362 DataLabelPtr m_targetToCheck;
81345200 363 CallLinkInfo* m_info;
6fe7ccc8
A
364 };
365
81345200
A
366 Vector<InlineCacheWrapper<JITGetByIdGenerator>, 4> m_getByIds;
367 Vector<InlineCacheWrapper<JITPutByIdGenerator>, 4> m_putByIds;
368 Vector<InRecord, 4> m_ins;
6fe7ccc8 369 Vector<JSCallRecord, 4> m_jsCalls;
81345200
A
370 SegmentedVector<OSRExitCompilationInfo, 4> m_exitCompilationInfo;
371 Vector<Vector<Label>> m_exitSiteLabels;
372
373 Call m_callArityFixup;
374 Label m_arityCheck;
375 OwnPtr<SpeculativeJIT> m_speculative;
14957cd0
A
376};
377
378} } // namespace JSC::DFG
379
380#endif
381#endif
382