• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 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 #ifndef JIT_h
27 #define JIT_h
28 
29 #include <wtf/Platform.h>
30 #include <bytecode/SamplingTool.h>
31 
32 #if ENABLE(JIT)
33 
34 #define WTF_USE_CTI_REPATCH_PIC 1
35 
36 #include "Interpreter.h"
37 #include "Opcode.h"
38 #include "RegisterFile.h"
39 #include "MacroAssembler.h"
40 #include "Profiler.h"
41 #include <wtf/AlwaysInline.h>
42 #include <wtf/Vector.h>
43 
44 #if PLATFORM(X86_64)
45 #define STUB_ARGS_offset 0x10
46 #else
47 #define STUB_ARGS_offset 0x0C
48 #endif
49 
50 #define STUB_ARGS_code (STUB_ARGS_offset)
51 #define STUB_ARGS_registerFile (STUB_ARGS_offset + 1)
52 #define STUB_ARGS_callFrame (STUB_ARGS_offset + 2)
53 #define STUB_ARGS_exception (STUB_ARGS_offset + 3)
54 #define STUB_ARGS_profilerReference (STUB_ARGS_offset + 4)
55 #define STUB_ARGS_globalData (STUB_ARGS_offset + 5)
56 
57 #define ARG_callFrame static_cast<CallFrame*>(ARGS[STUB_ARGS_callFrame])
58 #define ARG_registerFile static_cast<RegisterFile*>(ARGS[STUB_ARGS_registerFile])
59 #define ARG_exception static_cast<JSValuePtr*>(ARGS[STUB_ARGS_exception])
60 #define ARG_profilerReference static_cast<Profiler**>(ARGS[STUB_ARGS_profilerReference])
61 #define ARG_globalData static_cast<JSGlobalData*>(ARGS[STUB_ARGS_globalData])
62 
63 #define ARG_setCallFrame(newCallFrame) (ARGS[STUB_ARGS_callFrame] = (newCallFrame))
64 
65 #define ARG_src1 JSValuePtr::decode(static_cast<JSValueEncodedAsPointer*>(ARGS[1]))
66 #define ARG_src2 JSValuePtr::decode(static_cast<JSValueEncodedAsPointer*>(ARGS[2]))
67 #define ARG_src3 JSValuePtr::decode(static_cast<JSValueEncodedAsPointer*>(ARGS[3]))
68 #define ARG_src4 JSValuePtr::decode(static_cast<JSValueEncodedAsPointer*>(ARGS[4]))
69 #define ARG_src5 JSValuePtr::decode(static_cast<JSValueEncodedAsPointer*>(ARGS[5]))
70 #define ARG_id1 static_cast<Identifier*>(ARGS[1])
71 #define ARG_id2 static_cast<Identifier*>(ARGS[2])
72 #define ARG_id3 static_cast<Identifier*>(ARGS[3])
73 #define ARG_id4 static_cast<Identifier*>(ARGS[4])
74 #define ARG_int1 static_cast<int32_t>(reinterpret_cast<intptr_t>(ARGS[1]))
75 #define ARG_int2 static_cast<int32_t>(reinterpret_cast<intptr_t>(ARGS[2]))
76 #define ARG_int3 static_cast<int32_t>(reinterpret_cast<intptr_t>(ARGS[3]))
77 #define ARG_int4 static_cast<int32_t>(reinterpret_cast<intptr_t>(ARGS[4]))
78 #define ARG_int5 static_cast<int32_t>(reinterpret_cast<intptr_t>(ARGS[5]))
79 #define ARG_int6 static_cast<int32_t>(reinterpret_cast<intptr_t>(ARGS[6]))
80 #define ARG_func1 static_cast<FuncDeclNode*>(ARGS[1])
81 #define ARG_funcexp1 static_cast<FuncExprNode*>(ARGS[1])
82 #define ARG_regexp1 static_cast<RegExp*>(ARGS[1])
83 #define ARG_pni1 static_cast<JSPropertyNameIterator*>(ARGS[1])
84 #define ARG_returnAddress2 static_cast<void*>(ARGS[2])
85 #define ARG_codeBlock4 static_cast<CodeBlock*>(ARGS[4])
86 
87 #define STUB_RETURN_ADDRESS_SLOT (ARGS[-1])
88 
89 namespace JSC {
90 
91     class CodeBlock;
92     class JSPropertyNameIterator;
93     class Interpreter;
94     class Register;
95     class RegisterFile;
96     class ScopeChainNode;
97     class SimpleJumpTable;
98     class StringJumpTable;
99     class StructureChain;
100 
101     struct CallLinkInfo;
102     struct Instruction;
103     struct OperandTypes;
104     struct PolymorphicAccessStructureList;
105     struct StructureStubInfo;
106 
107     typedef JSValueEncodedAsPointer* (JIT_STUB *CTIHelper_j)(STUB_ARGS);
108     typedef JSObject* (JIT_STUB *CTIHelper_o)(STUB_ARGS);
109     typedef JSPropertyNameIterator* (JIT_STUB *CTIHelper_p)(STUB_ARGS);
110     typedef void (JIT_STUB *CTIHelper_v)(STUB_ARGS);
111     typedef void* (JIT_STUB *CTIHelper_s)(STUB_ARGS);
112     typedef int (JIT_STUB *CTIHelper_b)(STUB_ARGS);
113     typedef VoidPtrPair (JIT_STUB *CTIHelper_2)(STUB_ARGS);
114 
115     struct CallRecord {
116         MacroAssembler::Jump from;
117         unsigned bytecodeIndex;
118         void* to;
119 
CallRecordCallRecord120         CallRecord()
121         {
122         }
123 
124         CallRecord(MacroAssembler::Jump from, unsigned bytecodeIndex, void* to = 0)
fromCallRecord125             : from(from)
126             , bytecodeIndex(bytecodeIndex)
127             , to(to)
128         {
129         }
130     };
131 
132     struct JumpTable {
133         MacroAssembler::Jump from;
134         unsigned toBytecodeIndex;
135 
JumpTableJumpTable136         JumpTable(MacroAssembler::Jump f, unsigned t)
137             : from(f)
138             , toBytecodeIndex(t)
139         {
140         }
141     };
142 
143     struct SlowCaseEntry {
144         MacroAssembler::Jump from;
145         unsigned to;
146         unsigned hint;
147 
148         SlowCaseEntry(MacroAssembler::Jump f, unsigned t, unsigned h = 0)
fromSlowCaseEntry149             : from(f)
150             , to(t)
151             , hint(h)
152         {
153         }
154     };
155 
156     struct SwitchRecord {
157         enum Type {
158             Immediate,
159             Character,
160             String
161         };
162 
163         Type type;
164 
165         union {
166             SimpleJumpTable* simpleJumpTable;
167             StringJumpTable* stringJumpTable;
168         } jumpTable;
169 
170         unsigned bytecodeIndex;
171         unsigned defaultOffset;
172 
SwitchRecordSwitchRecord173         SwitchRecord(SimpleJumpTable* jumpTable, unsigned bytecodeIndex, unsigned defaultOffset, Type type)
174             : type(type)
175             , bytecodeIndex(bytecodeIndex)
176             , defaultOffset(defaultOffset)
177         {
178             this->jumpTable.simpleJumpTable = jumpTable;
179         }
180 
SwitchRecordSwitchRecord181         SwitchRecord(StringJumpTable* jumpTable, unsigned bytecodeIndex, unsigned defaultOffset)
182             : type(String)
183             , bytecodeIndex(bytecodeIndex)
184             , defaultOffset(defaultOffset)
185         {
186             this->jumpTable.stringJumpTable = jumpTable;
187         }
188     };
189 
190     struct PropertyStubCompilationInfo {
191         MacroAssembler::Jump callReturnLocation;
192         MacroAssembler::Label hotPathBegin;
193     };
194 
195     struct StructureStubCompilationInfo {
196         MacroAssembler::DataLabelPtr hotPathBegin;
197         MacroAssembler::Jump hotPathOther;
198         MacroAssembler::Jump callReturnLocation;
199         MacroAssembler::Label coldPathOther;
200     };
201 
202     extern "C" {
203         JSValueEncodedAsPointer* ctiTrampoline(
204 #if PLATFORM(X86_64)
205             // FIXME: (bug #22910) this will force all arguments onto the stack (regparm(0) does not appear to have any effect).
206             // We can allow register passing here, and move the writes of these values into the trampoline.
207             void*, void*, void*, void*, void*, void*,
208 #endif
209             void* code, RegisterFile*, CallFrame*, JSValuePtr* exception, Profiler**, JSGlobalData*);
210         void ctiVMThrowTrampoline();
211     };
212 
213     void ctiSetReturnAddress(void** where, void* what);
214     void ctiPatchCallByReturnAddress(void* where, void* what);
215 
216     class JIT : private MacroAssembler {
217         using MacroAssembler::Jump;
218         using MacroAssembler::JumpList;
219         using MacroAssembler::Label;
220 
221 #if PLATFORM(X86_64)
222         static const RegisterID timeoutCheckRegister = X86::r12;
223         static const RegisterID callFrameRegister = X86::r13;
224         static const RegisterID tagTypeNumberRegister = X86::r14;
225         static const RegisterID tagMaskRegister = X86::r15;
226 #else
227         static const RegisterID timeoutCheckRegister = X86::esi;
228         static const RegisterID callFrameRegister = X86::edi;
229 #endif
230 
231         static const int patchGetByIdDefaultStructure = -1;
232         // Magic number - initial offset cannot be representable as a signed 8bit value, or the X86Assembler
233         // will compress the displacement, and we may not be able to fit a patched offset.
234         static const int patchGetByIdDefaultOffset = 256;
235 
236 #if USE(JIT_STUB_ARGUMENT_REGISTER)
237 #if PLATFORM(X86_64)
238         static const int ctiArgumentInitSize = 6;
239 #else
240         static const int ctiArgumentInitSize = 2;
241 #endif
242 #elif USE(JIT_STUB_ARGUMENT_STACK)
243         static const int ctiArgumentInitSize = 4;
244 #else // JIT_STUB_ARGUMENT_VA_LIST
245         static const int ctiArgumentInitSize = 0;
246 #endif
247 
248 #if PLATFORM(X86_64)
249         // These architecture specific value are used to enable patching - see comment on op_put_by_id.
250         static const int patchOffsetPutByIdStructure = 10;
251         static const int patchOffsetPutByIdPropertyMapOffset = 31;
252         // These architecture specific value are used to enable patching - see comment on op_get_by_id.
253         static const int patchOffsetGetByIdStructure = 10;
254         static const int patchOffsetGetByIdBranchToSlowCase = 20;
255         static const int patchOffsetGetByIdPropertyMapOffset = 31;
256         static const int patchOffsetGetByIdPutResult = 31;
257 #if ENABLE(OPCODE_SAMPLING)
258         static const int patchOffsetGetByIdSlowCaseCall = 53 + ctiArgumentInitSize;
259 #else
260         static const int patchOffsetGetByIdSlowCaseCall = 30 + ctiArgumentInitSize;
261 #endif
262         static const int patchOffsetOpCallCompareToJump = 9;
263 #else
264         // These architecture specific value are used to enable patching - see comment on op_put_by_id.
265         static const int patchOffsetPutByIdStructure = 7;
266         static const int patchOffsetPutByIdPropertyMapOffset = 22;
267         // These architecture specific value are used to enable patching - see comment on op_get_by_id.
268         static const int patchOffsetGetByIdStructure = 7;
269         static const int patchOffsetGetByIdBranchToSlowCase = 13;
270         static const int patchOffsetGetByIdPropertyMapOffset = 22;
271         static const int patchOffsetGetByIdPutResult = 22;
272 #if ENABLE(OPCODE_SAMPLING)
273         static const int patchOffsetGetByIdSlowCaseCall = 31 + ctiArgumentInitSize;
274 #else
275         static const int patchOffsetGetByIdSlowCaseCall = 21 + ctiArgumentInitSize;
276 #endif
277         static const int patchOffsetOpCallCompareToJump = 6;
278 #endif
279 
280     public:
compile(JSGlobalData * globalData,CodeBlock * codeBlock)281         static void compile(JSGlobalData* globalData, CodeBlock* codeBlock)
282         {
283             JIT jit(globalData, codeBlock);
284             jit.privateCompile();
285         }
286 
compileGetByIdSelf(JSGlobalData * globalData,CodeBlock * codeBlock,StructureStubInfo * stubInfo,Structure * structure,size_t cachedOffset,void * returnAddress)287         static void compileGetByIdSelf(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, void* returnAddress)
288         {
289             JIT jit(globalData, codeBlock);
290             jit.privateCompileGetByIdSelf(stubInfo, structure, cachedOffset, returnAddress);
291         }
292 
compileGetByIdProto(JSGlobalData * globalData,CallFrame * callFrame,CodeBlock * codeBlock,StructureStubInfo * stubInfo,Structure * structure,Structure * prototypeStructure,size_t cachedOffset,void * returnAddress)293         static void compileGetByIdProto(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, size_t cachedOffset, void* returnAddress)
294         {
295             JIT jit(globalData, codeBlock);
296             jit.privateCompileGetByIdProto(stubInfo, structure, prototypeStructure, cachedOffset, returnAddress, callFrame);
297         }
298 
299 #if USE(CTI_REPATCH_PIC)
compileGetByIdSelfList(JSGlobalData * globalData,CodeBlock * codeBlock,StructureStubInfo * stubInfo,PolymorphicAccessStructureList * polymorphicStructures,int currentIndex,Structure * structure,size_t cachedOffset)300         static void compileGetByIdSelfList(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* polymorphicStructures, int currentIndex, Structure* structure, size_t cachedOffset)
301         {
302             JIT jit(globalData, codeBlock);
303             jit.privateCompileGetByIdSelfList(stubInfo, polymorphicStructures, currentIndex, structure, cachedOffset);
304         }
compileGetByIdProtoList(JSGlobalData * globalData,CallFrame * callFrame,CodeBlock * codeBlock,StructureStubInfo * stubInfo,PolymorphicAccessStructureList * prototypeStructureList,int currentIndex,Structure * structure,Structure * prototypeStructure,size_t cachedOffset)305         static void compileGetByIdProtoList(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructureList, int currentIndex, Structure* structure, Structure* prototypeStructure, size_t cachedOffset)
306         {
307             JIT jit(globalData, codeBlock);
308             jit.privateCompileGetByIdProtoList(stubInfo, prototypeStructureList, currentIndex, structure, prototypeStructure, cachedOffset, callFrame);
309         }
compileGetByIdChainList(JSGlobalData * globalData,CallFrame * callFrame,CodeBlock * codeBlock,StructureStubInfo * stubInfo,PolymorphicAccessStructureList * prototypeStructureList,int currentIndex,Structure * structure,StructureChain * chain,size_t count,size_t cachedOffset)310         static void compileGetByIdChainList(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructureList, int currentIndex, Structure* structure, StructureChain* chain, size_t count, size_t cachedOffset)
311         {
312             JIT jit(globalData, codeBlock);
313             jit.privateCompileGetByIdChainList(stubInfo, prototypeStructureList, currentIndex, structure, chain, count, cachedOffset, callFrame);
314         }
315 #endif
316 
compileGetByIdChain(JSGlobalData * globalData,CallFrame * callFrame,CodeBlock * codeBlock,StructureStubInfo * stubInfo,Structure * structure,StructureChain * chain,size_t count,size_t cachedOffset,void * returnAddress)317         static void compileGetByIdChain(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, size_t cachedOffset, void* returnAddress)
318         {
319             JIT jit(globalData, codeBlock);
320             jit.privateCompileGetByIdChain(stubInfo, structure, chain, count, cachedOffset, returnAddress, callFrame);
321         }
322 
compilePutByIdReplace(JSGlobalData * globalData,CodeBlock * codeBlock,StructureStubInfo * stubInfo,Structure * structure,size_t cachedOffset,void * returnAddress)323         static void compilePutByIdReplace(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, void* returnAddress)
324         {
325             JIT jit(globalData, codeBlock);
326             jit.privateCompilePutByIdReplace(stubInfo, structure, cachedOffset, returnAddress);
327         }
328 
compilePutByIdTransition(JSGlobalData * globalData,CodeBlock * codeBlock,StructureStubInfo * stubInfo,Structure * oldStructure,Structure * newStructure,size_t cachedOffset,StructureChain * chain,void * returnAddress)329         static void compilePutByIdTransition(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, void* returnAddress)
330         {
331             JIT jit(globalData, codeBlock);
332             jit.privateCompilePutByIdTransition(stubInfo, oldStructure, newStructure, cachedOffset, chain, returnAddress);
333         }
334 
compileCTIMachineTrampolines(JSGlobalData * globalData)335         static void compileCTIMachineTrampolines(JSGlobalData* globalData)
336         {
337             JIT jit(globalData);
338             jit.privateCompileCTIMachineTrampolines();
339         }
340 
341         static void patchGetByIdSelf(StructureStubInfo*, Structure*, size_t cachedOffset, void* returnAddress);
342         static void patchPutByIdReplace(StructureStubInfo*, Structure*, size_t cachedOffset, void* returnAddress);
343 
compilePatchGetArrayLength(JSGlobalData * globalData,CodeBlock * codeBlock,void * returnAddress)344         static void compilePatchGetArrayLength(JSGlobalData* globalData, CodeBlock* codeBlock, void* returnAddress)
345         {
346             JIT jit(globalData, codeBlock);
347             return jit.privateCompilePatchGetArrayLength(returnAddress);
348         }
349 
350         static void linkCall(JSFunction* callee, CodeBlock* calleeCodeBlock, void* ctiCode, CallLinkInfo* callLinkInfo, int callerArgCount);
351         static void unlinkCall(CallLinkInfo*);
352 
execute(void * code,RegisterFile * registerFile,CallFrame * callFrame,JSGlobalData * globalData,JSValuePtr * exception)353         inline static JSValuePtr execute(void* code, RegisterFile* registerFile, CallFrame* callFrame, JSGlobalData* globalData, JSValuePtr* exception)
354         {
355             return JSValuePtr::decode(ctiTrampoline(
356 #if PLATFORM(X86_64)
357                 0, 0, 0, 0, 0, 0,
358 #endif
359                 code, registerFile, callFrame, exception, Profiler::enabledProfilerReference(), globalData));
360         }
361 
362     private:
363         JIT(JSGlobalData*, CodeBlock* = 0);
364 
365         void privateCompileMainPass();
366         void privateCompileLinkPass();
367         void privateCompileSlowCases();
368         void privateCompile();
369         void privateCompileGetByIdSelf(StructureStubInfo*, Structure*, size_t cachedOffset, void* returnAddress);
370         void privateCompileGetByIdProto(StructureStubInfo*, Structure*, Structure* prototypeStructure, size_t cachedOffset, void* returnAddress, CallFrame* callFrame);
371 #if USE(CTI_REPATCH_PIC)
372         void privateCompileGetByIdSelfList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, size_t cachedOffset);
373         void privateCompileGetByIdProtoList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, Structure* prototypeStructure, size_t cachedOffset, CallFrame* callFrame);
374         void privateCompileGetByIdChainList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, StructureChain* chain, size_t count, size_t cachedOffset, CallFrame* callFrame);
375 #endif
376         void privateCompileGetByIdChain(StructureStubInfo*, Structure*, StructureChain*, size_t count, size_t cachedOffset, void* returnAddress, CallFrame* callFrame);
377         void privateCompilePutByIdReplace(StructureStubInfo*, Structure*, size_t cachedOffset, void* returnAddress);
378         void privateCompilePutByIdTransition(StructureStubInfo*, Structure*, Structure*, size_t cachedOffset, StructureChain*, void* returnAddress);
379 
380         void privateCompileCTIMachineTrampolines();
381         void privateCompilePatchGetArrayLength(void* returnAddress);
382 
383         void addSlowCase(Jump);
384         void addJump(Jump, int);
385         void emitJumpSlowToHot(Jump, int);
386 
387         void compileGetByIdHotPath(int resultVReg, int baseVReg, Identifier* ident, unsigned propertyAccessInstructionIndex);
388         void compileGetByIdSlowCase(int resultVReg, int baseVReg, Identifier* ident, Vector<SlowCaseEntry>::iterator& iter, unsigned propertyAccessInstructionIndex);
389         void compilePutByIdHotPath(int baseVReg, Identifier* ident, int valueVReg, unsigned propertyAccessInstructionIndex);
390         void compilePutByIdSlowCase(int baseVReg, Identifier* ident, int valueVReg, Vector<SlowCaseEntry>::iterator& iter, unsigned propertyAccessInstructionIndex);
391         void compileOpCall(OpcodeID, Instruction* instruction, unsigned callLinkInfoIndex);
392         void compileOpCallInitializeCallFrame();
393         void compileOpCallSetupArgs(Instruction*);
394         void compileOpCallEvalSetupArgs(Instruction*);
395         void compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter, unsigned callLinkInfoIndex, OpcodeID opcodeID);
396         void compileOpConstructSetupArgs(Instruction*);
397         enum CompileOpStrictEqType { OpStrictEq, OpNStrictEq };
398         void compileOpStrictEq(Instruction* instruction, CompileOpStrictEqType type);
399         void putDoubleResultToJSNumberCellOrJSImmediate(X86Assembler::XMMRegisterID xmmSource, RegisterID jsNumberCell, unsigned dst, X86Assembler::JmpSrc* wroteJSNumberCell, X86Assembler::XMMRegisterID tempXmm, RegisterID tempReg1, RegisterID tempReg2);
400 
401         void compileFastArith_op_add(Instruction*);
402         void compileFastArith_op_sub(Instruction*);
403         void compileFastArith_op_mul(Instruction*);
404         void compileFastArith_op_mod(unsigned result, unsigned op1, unsigned op2);
405         void compileFastArith_op_bitand(unsigned result, unsigned op1, unsigned op2);
406         void compileFastArith_op_lshift(unsigned result, unsigned op1, unsigned op2);
407         void compileFastArith_op_rshift(unsigned result, unsigned op1, unsigned op2);
408         void compileFastArith_op_pre_inc(unsigned srcDst);
409         void compileFastArith_op_pre_dec(unsigned srcDst);
410         void compileFastArith_op_post_inc(unsigned result, unsigned srcDst);
411         void compileFastArith_op_post_dec(unsigned result, unsigned srcDst);
412         void compileFastArithSlow_op_add(Instruction*, Vector<SlowCaseEntry>::iterator&);
413         void compileFastArithSlow_op_sub(Instruction*, Vector<SlowCaseEntry>::iterator&);
414         void compileFastArithSlow_op_mul(Instruction*, Vector<SlowCaseEntry>::iterator&);
415         void compileFastArithSlow_op_mod(unsigned result, unsigned op1, unsigned op2, Vector<SlowCaseEntry>::iterator&);
416         void compileFastArithSlow_op_bitand(unsigned result, unsigned op1, unsigned op2, Vector<SlowCaseEntry>::iterator&);
417         void compileFastArithSlow_op_lshift(unsigned result, unsigned op1, unsigned op2, Vector<SlowCaseEntry>::iterator&);
418         void compileFastArithSlow_op_rshift(unsigned result, unsigned op1, unsigned op2, Vector<SlowCaseEntry>::iterator&);
419         void compileFastArithSlow_op_pre_inc(unsigned srcDst, Vector<SlowCaseEntry>::iterator&);
420         void compileFastArithSlow_op_pre_dec(unsigned srcDst, Vector<SlowCaseEntry>::iterator&);
421         void compileFastArithSlow_op_post_inc(unsigned result, unsigned srcDst, Vector<SlowCaseEntry>::iterator&);
422         void compileFastArithSlow_op_post_dec(unsigned result, unsigned srcDst, Vector<SlowCaseEntry>::iterator&);
423 #if ENABLE(JIT_OPTIMIZE_ARITHMETIC)
424         void compileBinaryArithOp(OpcodeID, unsigned dst, unsigned src1, unsigned src2, OperandTypes opi);
425         void compileBinaryArithOpSlowCase(OpcodeID, Vector<SlowCaseEntry>::iterator&, unsigned dst, unsigned src1, unsigned src2, OperandTypes opi);
426 #endif
427 
428         void emitGetVirtualRegister(int src, RegisterID dst);
429         void emitGetVirtualRegisters(int src1, RegisterID dst1, int src2, RegisterID dst2);
430         void emitPutVirtualRegister(unsigned dst, RegisterID from = X86::eax);
431 
432         void emitPutJITStubArg(RegisterID src, unsigned argumentNumber);
433         void emitPutJITStubArgFromVirtualRegister(unsigned src, unsigned argumentNumber, RegisterID scratch);
434         void emitPutJITStubArgConstant(unsigned value, unsigned argumentNumber);
435         void emitPutJITStubArgConstant(void* value, unsigned argumentNumber);
436         void emitGetJITStubArg(unsigned argumentNumber, RegisterID dst);
437 
438         void emitInitRegister(unsigned dst);
439 
440         void emitPutCTIParam(void* value, unsigned name);
441         void emitPutCTIParam(RegisterID from, unsigned name);
442         void emitGetCTIParam(unsigned name, RegisterID to);
443 
444         void emitPutToCallFrameHeader(RegisterID from, RegisterFile::CallFrameHeaderEntry entry);
445         void emitPutImmediateToCallFrameHeader(void* value, RegisterFile::CallFrameHeaderEntry entry);
446         void emitGetFromCallFrameHeader(RegisterFile::CallFrameHeaderEntry entry, RegisterID to);
447 
448         JSValuePtr getConstantOperand(unsigned src);
449         int32_t getConstantOperandImmediateInt(unsigned src);
450         bool isOperandConstantImmediateInt(unsigned src);
451 
452         Jump emitJumpIfJSCell(RegisterID);
453         Jump emitJumpIfBothJSCells(RegisterID, RegisterID, RegisterID);
454         void emitJumpSlowCaseIfJSCell(RegisterID);
455         Jump emitJumpIfNotJSCell(RegisterID);
456         void emitJumpSlowCaseIfNotJSCell(RegisterID);
457         void emitJumpSlowCaseIfNotJSCell(RegisterID, int VReg);
458 #if USE(ALTERNATE_JSIMMEDIATE)
459         JIT::Jump emitJumpIfImmediateNumber(RegisterID);
460         JIT::Jump emitJumpIfNotImmediateNumber(RegisterID);
461 #endif
462 
getSlowCase(Vector<SlowCaseEntry>::iterator & iter)463         Jump getSlowCase(Vector<SlowCaseEntry>::iterator& iter)
464         {
465             return iter++->from;
466         }
linkSlowCase(Vector<SlowCaseEntry>::iterator & iter)467         void linkSlowCase(Vector<SlowCaseEntry>::iterator& iter)
468         {
469             iter->from.link(this);
470             ++iter;
471         }
472         void linkSlowCaseIfNotJSCell(Vector<SlowCaseEntry>::iterator&, int vReg);
473 
474         JIT::Jump emitJumpIfImmediateInteger(RegisterID);
475         JIT::Jump emitJumpIfNotImmediateInteger(RegisterID);
476         JIT::Jump emitJumpIfNotImmediateIntegers(RegisterID, RegisterID, RegisterID);
477         void emitJumpSlowCaseIfNotImmediateInteger(RegisterID);
478         void emitJumpSlowCaseIfNotImmediateIntegers(RegisterID, RegisterID, RegisterID);
479 
480         Jump checkStructure(RegisterID reg, Structure* structure);
481 
482 #if !USE(ALTERNATE_JSIMMEDIATE)
483         void emitFastArithDeTagImmediate(RegisterID);
484         Jump emitFastArithDeTagImmediateJumpIfZero(RegisterID);
485 #endif
486         void emitFastArithReTagImmediate(RegisterID src, RegisterID dest);
487         void emitFastArithImmToInt(RegisterID);
488         void emitFastArithIntToImmNoCheck(RegisterID src, RegisterID dest);
489 
490         void emitTagAsBoolImmediate(RegisterID reg);
491 
492         void restoreArgumentReference();
493         void restoreArgumentReferenceForTrampoline();
494 
495         Jump emitNakedCall(RegisterID);
496         Jump emitNakedCall(void* function);
497         Jump emitCTICall_internal(void*);
emitCTICall(CTIHelper_j helper)498         Jump emitCTICall(CTIHelper_j helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); }
emitCTICall(CTIHelper_o helper)499         Jump emitCTICall(CTIHelper_o helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); }
emitCTICall(CTIHelper_p helper)500         Jump emitCTICall(CTIHelper_p helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); }
emitCTICall(CTIHelper_v helper)501         Jump emitCTICall(CTIHelper_v helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); }
emitCTICall(CTIHelper_s helper)502         Jump emitCTICall(CTIHelper_s helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); }
emitCTICall(CTIHelper_b helper)503         Jump emitCTICall(CTIHelper_b helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); }
emitCTICall(CTIHelper_2 helper)504         Jump emitCTICall(CTIHelper_2 helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); }
505 
506         void emitGetVariableObjectRegister(RegisterID variableObject, int index, RegisterID dst);
507         void emitPutVariableObjectRegister(RegisterID src, RegisterID variableObject, int index);
508 
509         void emitSlowScriptCheck();
510 #ifndef NDEBUG
511         void printBytecodeOperandTypes(unsigned src1, unsigned src2);
512 #endif
513 
514         void killLastResultRegister();
515 
516 #if ENABLE(CODEBLOCK_SAMPLING)
sampleCodeBlock(CodeBlock * codeBlock)517         void sampleCodeBlock(CodeBlock* codeBlock)
518         {
519 #if PLATFORM(X86_64)
520             move(ImmPtr(m_interpreter->sampler()->codeBlockSlot()), X86::ecx);
521             storePtr(ImmPtr(codeBlock), X86::ecx);
522 #else
523             storePtr(ImmPtr(codeBlock), m_interpreter->sampler()->codeBlockSlot());
524 #endif
525         }
526 #else
sampleCodeBlock(CodeBlock *)527         void sampleCodeBlock(CodeBlock*) {}
528 #endif
529 
530 #if ENABLE(OPCODE_SAMPLING)
531         void sampleInstruction(Instruction* instruction, bool inHostFunction=false)
532         {
533 #if PLATFORM(X86_64)
534             move(ImmPtr(m_interpreter->sampler()->sampleSlot()), X86::ecx);
535             storePtr(ImmPtr(m_interpreter->sampler()->encodeSample(instruction, inHostFunction)), X86::ecx);
536 #else
537             storePtr(ImmPtr(m_interpreter->sampler()->encodeSample(instruction, inHostFunction)), m_interpreter->sampler()->sampleSlot());
538 #endif
539         }
540 #else
sampleInstruction(Instruction *,bool)541         void sampleInstruction(Instruction*, bool) {}
542 #endif
543 
544         Interpreter* m_interpreter;
545         JSGlobalData* m_globalData;
546         CodeBlock* m_codeBlock;
547 
548         Vector<CallRecord> m_calls;
549         Vector<Label> m_labels;
550         Vector<PropertyStubCompilationInfo> m_propertyAccessCompilationInfo;
551         Vector<StructureStubCompilationInfo> m_callStructureStubCompilationInfo;
552         Vector<JumpTable> m_jmpTable;
553 
554         struct JSRInfo {
555             DataLabelPtr storeLocation;
556             Label target;
557 
JSRInfoJSRInfo558             JSRInfo(DataLabelPtr storeLocation, Label targetLocation)
559                 : storeLocation(storeLocation)
560                 , target(targetLocation)
561             {
562             }
563         };
564 
565         unsigned m_bytecodeIndex;
566         Vector<JSRInfo> m_jsrSites;
567         Vector<SlowCaseEntry> m_slowCases;
568         Vector<SwitchRecord> m_switches;
569 
570         int m_lastResultBytecodeRegister;
571         unsigned m_jumpTargetsPosition;
572     };
573 }
574 
575 #endif // ENABLE(JIT)
576 
577 #endif // JIT_h
578