JIT.h revision 635860845790a19bf50bbc51ba8fb66a96dde068
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
89namespace 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
120        CallRecord()
121        {
122        }
123
124        CallRecord(MacroAssembler::Jump from, unsigned bytecodeIndex, void* to = 0)
125            : from(from)
126            , bytecodeIndex(bytecodeIndex)
127            , to(to)
128        {
129        }
130    };
131
132    struct JumpTable {
133        MacroAssembler::Jump from;
134        unsigned toBytecodeIndex;
135
136        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)
149            : 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
173        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
181        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:
281        static void compile(JSGlobalData* globalData, CodeBlock* codeBlock)
282        {
283            JIT jit(globalData, codeBlock);
284            jit.privateCompile();
285        }
286
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
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)
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        }
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        }
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
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
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
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
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
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
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
463        Jump getSlowCase(Vector<SlowCaseEntry>::iterator& iter)
464        {
465            return iter++->from;
466        }
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*);
498        Jump emitCTICall(CTIHelper_j helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); }
499        Jump emitCTICall(CTIHelper_o helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); }
500        Jump emitCTICall(CTIHelper_p helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); }
501        Jump emitCTICall(CTIHelper_v helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); }
502        Jump emitCTICall(CTIHelper_s helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); }
503        Jump emitCTICall(CTIHelper_b helper) { return emitCTICall_internal(reinterpret_cast<void*>(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)
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
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
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
558            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