~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/3rdparty/webkit/JavaScriptCore/jit/JIT.h

  • Committer: Bazaar Package Importer
  • Author(s): Alessandro Ghersi
  • Date: 2009-11-02 18:30:08 UTC
  • mfrom: (1.2.2 upstream)
  • mto: (15.2.5 experimental)
  • mto: This revision was merged to the branch mainline in revision 88.
  • Revision ID: james.westby@ubuntu.com-20091102183008-b6a4gcs128mvfb3m
Tags: upstream-4.6.0~beta1
ImportĀ upstreamĀ versionĀ 4.6.0~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
30
30
 
31
31
#if ENABLE(JIT)
32
32
 
33
 
#define WTF_USE_CTI_REPATCH_PIC 1
 
33
// We've run into some problems where changing the size of the class JIT leads to
 
34
// performance fluctuations.  Try forcing alignment in an attempt to stabalize this.
 
35
#if COMPILER(GCC)
 
36
#define JIT_CLASS_ALIGNMENT __attribute__ ((aligned (32)))
 
37
#else
 
38
#define JIT_CLASS_ALIGNMENT
 
39
#endif
34
40
 
 
41
#include "CodeBlock.h"
35
42
#include "Interpreter.h"
 
43
#include "JITCode.h"
 
44
#include "JITStubs.h"
36
45
#include "Opcode.h"
37
46
#include "RegisterFile.h"
38
47
#include "MacroAssembler.h"
39
48
#include "Profiler.h"
 
49
#include <bytecode/SamplingTool.h>
40
50
#include <wtf/AlwaysInline.h>
41
51
#include <wtf/Vector.h>
42
52
 
43
 
#define STUB_ARGS_offset 0x0C
44
 
#define STUB_ARGS_code (STUB_ARGS_offset)
45
 
#define STUB_ARGS_registerFile (STUB_ARGS_offset + 1)
46
 
#define STUB_ARGS_callFrame (STUB_ARGS_offset + 2)
47
 
#define STUB_ARGS_exception (STUB_ARGS_offset + 3)
48
 
#define STUB_ARGS_profilerReference (STUB_ARGS_offset + 4)
49
 
#define STUB_ARGS_globalData (STUB_ARGS_offset + 5)
50
 
 
51
 
#define ARG_callFrame static_cast<CallFrame*>(ARGS[STUB_ARGS_callFrame])
52
 
#define ARG_registerFile static_cast<RegisterFile*>(ARGS[STUB_ARGS_registerFile])
53
 
#define ARG_exception static_cast<JSValuePtr*>(ARGS[STUB_ARGS_exception])
54
 
#define ARG_profilerReference static_cast<Profiler**>(ARGS[STUB_ARGS_profilerReference])
55
 
#define ARG_globalData static_cast<JSGlobalData*>(ARGS[STUB_ARGS_globalData])
56
 
 
57
 
#define ARG_setCallFrame(newCallFrame) (ARGS[STUB_ARGS_callFrame] = (newCallFrame))
58
 
 
59
 
#define ARG_src1 JSValuePtr::decode(static_cast<JSValueEncodedAsPointer*>(ARGS[1]))
60
 
#define ARG_src2 JSValuePtr::decode(static_cast<JSValueEncodedAsPointer*>(ARGS[2]))
61
 
#define ARG_src3 JSValuePtr::decode(static_cast<JSValueEncodedAsPointer*>(ARGS[3]))
62
 
#define ARG_src4 JSValuePtr::decode(static_cast<JSValueEncodedAsPointer*>(ARGS[4]))
63
 
#define ARG_src5 JSValuePtr::decode(static_cast<JSValueEncodedAsPointer*>(ARGS[5]))
64
 
#define ARG_id1 static_cast<Identifier*>(ARGS[1])
65
 
#define ARG_id2 static_cast<Identifier*>(ARGS[2])
66
 
#define ARG_id3 static_cast<Identifier*>(ARGS[3])
67
 
#define ARG_id4 static_cast<Identifier*>(ARGS[4])
68
 
#define ARG_int1 static_cast<int32_t>(reinterpret_cast<intptr_t>(ARGS[1]))
69
 
#define ARG_int2 static_cast<int32_t>(reinterpret_cast<intptr_t>(ARGS[2]))
70
 
#define ARG_int3 static_cast<int32_t>(reinterpret_cast<intptr_t>(ARGS[3]))
71
 
#define ARG_int4 static_cast<int32_t>(reinterpret_cast<intptr_t>(ARGS[4]))
72
 
#define ARG_int5 static_cast<int32_t>(reinterpret_cast<intptr_t>(ARGS[5]))
73
 
#define ARG_int6 static_cast<int32_t>(reinterpret_cast<intptr_t>(ARGS[6]))
74
 
#define ARG_func1 static_cast<FuncDeclNode*>(ARGS[1])
75
 
#define ARG_funcexp1 static_cast<FuncExprNode*>(ARGS[1])
76
 
#define ARG_regexp1 static_cast<RegExp*>(ARGS[1])
77
 
#define ARG_pni1 static_cast<JSPropertyNameIterator*>(ARGS[1])
78
 
#define ARG_returnAddress2 static_cast<void*>(ARGS[2])
79
 
#define ARG_codeBlock4 static_cast<CodeBlock*>(ARGS[4])
80
 
 
81
 
#define STUB_RETURN_ADDRESS_SLOT (ARGS[-1])
82
 
 
83
53
namespace JSC {
84
54
 
85
55
    class CodeBlock;
 
56
    class JIT;
86
57
    class JSPropertyNameIterator;
87
58
    class Interpreter;
88
59
    class Register;
89
60
    class RegisterFile;
90
61
    class ScopeChainNode;
91
 
    class SimpleJumpTable;
92
 
    class StringJumpTable;
93
62
    class StructureChain;
94
63
 
95
64
    struct CallLinkInfo;
96
65
    struct Instruction;
97
66
    struct OperandTypes;
98
67
    struct PolymorphicAccessStructureList;
 
68
    struct SimpleJumpTable;
 
69
    struct StringJumpTable;
99
70
    struct StructureStubInfo;
100
71
 
101
 
    typedef JSValueEncodedAsPointer* (JIT_STUB *CTIHelper_j)(STUB_ARGS);
102
 
    typedef JSObject* (JIT_STUB *CTIHelper_o)(STUB_ARGS);
103
 
    typedef JSPropertyNameIterator* (JIT_STUB *CTIHelper_p)(STUB_ARGS);
104
 
    typedef void (JIT_STUB *CTIHelper_v)(STUB_ARGS);
105
 
    typedef void* (JIT_STUB *CTIHelper_s)(STUB_ARGS);
106
 
    typedef int (JIT_STUB *CTIHelper_b)(STUB_ARGS);
107
 
    typedef VoidPtrPair (JIT_STUB *CTIHelper_2)(STUB_ARGS);
108
 
 
109
72
    struct CallRecord {
110
 
        MacroAssembler::Jump from;
 
73
        MacroAssembler::Call from;
111
74
        unsigned bytecodeIndex;
112
75
        void* to;
113
76
 
115
78
        {
116
79
        }
117
80
 
118
 
        CallRecord(MacroAssembler::Jump from, unsigned bytecodeIndex, void* to = 0)
 
81
        CallRecord(MacroAssembler::Call from, unsigned bytecodeIndex, void* to = 0)
119
82
            : from(from)
120
83
            , bytecodeIndex(bytecodeIndex)
121
84
            , to(to)
182
145
    };
183
146
 
184
147
    struct PropertyStubCompilationInfo {
185
 
        MacroAssembler::Jump callReturnLocation;
 
148
        MacroAssembler::Call callReturnLocation;
186
149
        MacroAssembler::Label hotPathBegin;
187
150
    };
188
151
 
189
152
    struct StructureStubCompilationInfo {
190
153
        MacroAssembler::DataLabelPtr hotPathBegin;
191
 
        MacroAssembler::Jump hotPathOther;
192
 
        MacroAssembler::Jump callReturnLocation;
193
 
        MacroAssembler::Label coldPathOther;
194
 
    };
195
 
 
196
 
    extern "C" {
197
 
        JSValueEncodedAsPointer* ctiTrampoline(
198
 
#if PLATFORM(X86_64)
199
 
            // FIXME: (bug #22910) this will force all arguments onto the stack (regparm(0) does not appear to have any effect).
200
 
            // We can allow register passing here, and move the writes of these values into the trampoline.
201
 
            void*, void*, void*, void*, void*, void*,
202
 
#endif
203
 
            void* code, RegisterFile*, CallFrame*, JSValuePtr* exception, Profiler**, JSGlobalData*);
204
 
        void ctiVMThrowTrampoline();
205
 
    };
206
 
 
207
 
    void ctiSetReturnAddress(void** where, void* what);
208
 
    void ctiPatchCallByReturnAddress(void* where, void* what);
 
154
        MacroAssembler::Call hotPathOther;
 
155
        MacroAssembler::Call callReturnLocation;
 
156
    };
 
157
 
 
158
    struct MethodCallCompilationInfo {
 
159
        MethodCallCompilationInfo(unsigned propertyAccessIndex)
 
160
            : propertyAccessIndex(propertyAccessIndex)
 
161
        {
 
162
        }
 
163
 
 
164
        MacroAssembler::DataLabelPtr structureToCompare;
 
165
        unsigned propertyAccessIndex;
 
166
    };
 
167
 
 
168
    // Near calls can only be patched to other JIT code, regular calls can be patched to JIT code or relinked to stub functions.
 
169
    void ctiPatchNearCallByReturnAddress(CodeBlock* codeblock, ReturnAddressPtr returnAddress, MacroAssemblerCodePtr newCalleeFunction);
 
170
    void ctiPatchCallByReturnAddress(CodeBlock* codeblock, ReturnAddressPtr returnAddress, MacroAssemblerCodePtr newCalleeFunction);
 
171
    void ctiPatchCallByReturnAddress(CodeBlock* codeblock, ReturnAddressPtr returnAddress, FunctionPtr newCalleeFunction);
209
172
 
210
173
    class JIT : private MacroAssembler {
 
174
        friend class JITStubCall;
 
175
 
211
176
        using MacroAssembler::Jump;
212
177
        using MacroAssembler::JumpList;
213
178
        using MacroAssembler::Label;
214
179
 
 
180
        // NOTES:
 
181
        //
 
182
        // regT0 has two special meanings.  The return value from a stub
 
183
        // call will always be in regT0, and by default (unless
 
184
        // a register is specified) emitPutVirtualRegister() will store
 
185
        // the value from regT0.
 
186
        //
 
187
        // regT3 is required to be callee-preserved.
 
188
        //
 
189
        // tempRegister2 is has no such dependencies.  It is important that
 
190
        // on x86/x86-64 it is ecx for performance reasons, since the
 
191
        // MacroAssembler will need to plant register swaps if it is not -
 
192
        // however the code will still function correctly.
215
193
#if PLATFORM(X86_64)
216
 
        static const RegisterID timeoutCheckRegister = X86::r12;
217
 
        static const RegisterID callFrameRegister = X86::r13;
 
194
        static const RegisterID returnValueRegister = X86Registers::eax;
 
195
        static const RegisterID cachedResultRegister = X86Registers::eax;
 
196
        static const RegisterID firstArgumentRegister = X86Registers::edi;
 
197
 
 
198
        static const RegisterID timeoutCheckRegister = X86Registers::r12;
 
199
        static const RegisterID callFrameRegister = X86Registers::r13;
 
200
        static const RegisterID tagTypeNumberRegister = X86Registers::r14;
 
201
        static const RegisterID tagMaskRegister = X86Registers::r15;
 
202
 
 
203
        static const RegisterID regT0 = X86Registers::eax;
 
204
        static const RegisterID regT1 = X86Registers::edx;
 
205
        static const RegisterID regT2 = X86Registers::ecx;
 
206
        static const RegisterID regT3 = X86Registers::ebx;
 
207
 
 
208
        static const FPRegisterID fpRegT0 = X86Registers::xmm0;
 
209
        static const FPRegisterID fpRegT1 = X86Registers::xmm1;
 
210
        static const FPRegisterID fpRegT2 = X86Registers::xmm2;
 
211
#elif PLATFORM(X86)
 
212
        static const RegisterID returnValueRegister = X86Registers::eax;
 
213
        static const RegisterID cachedResultRegister = X86Registers::eax;
 
214
        // On x86 we always use fastcall conventions = but on
 
215
        // OS X if might make more sense to just use regparm.
 
216
        static const RegisterID firstArgumentRegister = X86Registers::ecx;
 
217
 
 
218
        static const RegisterID timeoutCheckRegister = X86Registers::esi;
 
219
        static const RegisterID callFrameRegister = X86Registers::edi;
 
220
 
 
221
        static const RegisterID regT0 = X86Registers::eax;
 
222
        static const RegisterID regT1 = X86Registers::edx;
 
223
        static const RegisterID regT2 = X86Registers::ecx;
 
224
        static const RegisterID regT3 = X86Registers::ebx;
 
225
 
 
226
        static const FPRegisterID fpRegT0 = X86Registers::xmm0;
 
227
        static const FPRegisterID fpRegT1 = X86Registers::xmm1;
 
228
        static const FPRegisterID fpRegT2 = X86Registers::xmm2;
 
229
#elif PLATFORM(ARM_THUMB2)
 
230
        static const RegisterID returnValueRegister = ARMRegisters::r0;
 
231
        static const RegisterID cachedResultRegister = ARMRegisters::r0;
 
232
        static const RegisterID firstArgumentRegister = ARMRegisters::r0;
 
233
 
 
234
        static const RegisterID regT0 = ARMRegisters::r0;
 
235
        static const RegisterID regT1 = ARMRegisters::r1;
 
236
        static const RegisterID regT2 = ARMRegisters::r2;
 
237
        static const RegisterID regT3 = ARMRegisters::r4;
 
238
 
 
239
        static const RegisterID callFrameRegister = ARMRegisters::r5;
 
240
        static const RegisterID timeoutCheckRegister = ARMRegisters::r6;
 
241
 
 
242
        static const FPRegisterID fpRegT0 = ARMRegisters::d0;
 
243
        static const FPRegisterID fpRegT1 = ARMRegisters::d1;
 
244
        static const FPRegisterID fpRegT2 = ARMRegisters::d2;
 
245
#elif PLATFORM(ARM_TRADITIONAL)
 
246
        static const RegisterID returnValueRegister = ARMRegisters::r0;
 
247
        static const RegisterID cachedResultRegister = ARMRegisters::r0;
 
248
        static const RegisterID firstArgumentRegister = ARMRegisters::r0;
 
249
 
 
250
        static const RegisterID timeoutCheckRegister = ARMRegisters::r5;
 
251
        static const RegisterID callFrameRegister = ARMRegisters::r4;
 
252
        static const RegisterID ctiReturnRegister = ARMRegisters::r6;
 
253
 
 
254
        static const RegisterID regT0 = ARMRegisters::r0;
 
255
        static const RegisterID regT1 = ARMRegisters::r1;
 
256
        static const RegisterID regT2 = ARMRegisters::r2;
 
257
        // Callee preserved
 
258
        static const RegisterID regT3 = ARMRegisters::r7;
 
259
 
 
260
        static const RegisterID regS0 = ARMRegisters::S0;
 
261
        // Callee preserved
 
262
        static const RegisterID regS1 = ARMRegisters::S1;
 
263
 
 
264
        static const RegisterID regStackPtr = ARMRegisters::sp;
 
265
        static const RegisterID regLink = ARMRegisters::lr;
 
266
 
 
267
        static const FPRegisterID fpRegT0 = ARMRegisters::d0;
 
268
        static const FPRegisterID fpRegT1 = ARMRegisters::d1;
 
269
        static const FPRegisterID fpRegT2 = ARMRegisters::d2;
218
270
#else
219
 
        static const RegisterID timeoutCheckRegister = X86::esi;
220
 
        static const RegisterID callFrameRegister = X86::edi;
 
271
    #error "JIT not supported on this platform."
221
272
#endif
222
273
 
223
274
        static const int patchGetByIdDefaultStructure = -1;
225
276
        // will compress the displacement, and we may not be able to fit a patched offset.
226
277
        static const int patchGetByIdDefaultOffset = 256;
227
278
 
228
 
#if USE(JIT_STUB_ARGUMENT_REGISTER)
229
 
#if PLATFORM(X86_64)
230
 
        static const int ctiArgumentInitSize = 3;
231
 
#else
232
 
        static const int ctiArgumentInitSize = 2;
233
 
#endif
234
 
#elif USE(JIT_STUB_ARGUMENT_STACK)
235
 
        static const int ctiArgumentInitSize = 4;
236
 
#else // JIT_STUB_ARGUMENT_VA_LIST
237
 
        static const int ctiArgumentInitSize = 0;
238
 
#endif
239
 
 
240
 
#if PLATFORM(X86_64)
241
 
        // These architecture specific value are used to enable patching - see comment on op_put_by_id.
242
 
        static const int patchOffsetPutByIdStructure = 10;
243
 
        static const int patchOffsetPutByIdPropertyMapOffset = 31;
244
 
        // These architecture specific value are used to enable patching - see comment on op_get_by_id.
245
 
        static const int patchOffsetGetByIdStructure = 10;
246
 
        static const int patchOffsetGetByIdBranchToSlowCase = 20;
247
 
        static const int patchOffsetGetByIdPropertyMapOffset = 31;
248
 
        static const int patchOffsetGetByIdPutResult = 31;
249
 
#if ENABLE(OPCODE_SAMPLING)
250
 
        static const int patchOffsetGetByIdSlowCaseCall = 40 + ctiArgumentInitSize;
251
 
#else
252
 
        static const int patchOffsetGetByIdSlowCaseCall = 30 + ctiArgumentInitSize;
253
 
#endif
254
 
        static const int patchOffsetOpCallCompareToJump = 9;
255
 
#else
256
 
        // These architecture specific value are used to enable patching - see comment on op_put_by_id.
257
 
        static const int patchOffsetPutByIdStructure = 7;
258
 
        static const int patchOffsetPutByIdPropertyMapOffset = 22;
259
 
        // These architecture specific value are used to enable patching - see comment on op_get_by_id.
260
 
        static const int patchOffsetGetByIdStructure = 7;
261
 
        static const int patchOffsetGetByIdBranchToSlowCase = 13;
262
 
        static const int patchOffsetGetByIdPropertyMapOffset = 22;
263
 
        static const int patchOffsetGetByIdPutResult = 22;
264
 
#if ENABLE(OPCODE_SAMPLING)
265
 
        static const int patchOffsetGetByIdSlowCaseCall = 31 + ctiArgumentInitSize;
266
 
#else
267
 
        static const int patchOffsetGetByIdSlowCaseCall = 21 + ctiArgumentInitSize;
268
 
#endif
269
 
        static const int patchOffsetOpCallCompareToJump = 6;
270
 
#endif
271
 
 
272
279
    public:
273
 
        static void compile(JSGlobalData* globalData, CodeBlock* codeBlock)
274
 
        {
275
 
            JIT jit(globalData, codeBlock);
276
 
            jit.privateCompile();
277
 
        }
278
 
 
279
 
        static void compileGetByIdSelf(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, void* returnAddress)
280
 
        {
281
 
            JIT jit(globalData, codeBlock);
282
 
            jit.privateCompileGetByIdSelf(stubInfo, structure, cachedOffset, returnAddress);
283
 
        }
284
 
 
285
 
        static void compileGetByIdProto(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, size_t cachedOffset, void* returnAddress)
 
280
        static JITCode compile(JSGlobalData* globalData, CodeBlock* codeBlock)
 
281
        {
 
282
            return JIT(globalData, codeBlock).privateCompile();
 
283
        }
 
284
 
 
285
        static void compileGetByIdProto(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, size_t cachedOffset, ReturnAddressPtr returnAddress)
286
286
        {
287
287
            JIT jit(globalData, codeBlock);
288
288
            jit.privateCompileGetByIdProto(stubInfo, structure, prototypeStructure, cachedOffset, returnAddress, callFrame);
289
289
        }
290
290
 
291
 
#if USE(CTI_REPATCH_PIC)
292
291
        static void compileGetByIdSelfList(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* polymorphicStructures, int currentIndex, Structure* structure, size_t cachedOffset)
293
292
        {
294
293
            JIT jit(globalData, codeBlock);
304
303
            JIT jit(globalData, codeBlock);
305
304
            jit.privateCompileGetByIdChainList(stubInfo, prototypeStructureList, currentIndex, structure, chain, count, cachedOffset, callFrame);
306
305
        }
307
 
#endif
308
306
 
309
 
        static void compileGetByIdChain(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, size_t cachedOffset, void* returnAddress)
 
307
        static void compileGetByIdChain(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, size_t cachedOffset, ReturnAddressPtr returnAddress)
310
308
        {
311
309
            JIT jit(globalData, codeBlock);
312
310
            jit.privateCompileGetByIdChain(stubInfo, structure, chain, count, cachedOffset, returnAddress, callFrame);
313
311
        }
314
 
 
315
 
        static void compilePutByIdReplace(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, void* returnAddress)
316
 
        {
317
 
            JIT jit(globalData, codeBlock);
318
 
            jit.privateCompilePutByIdReplace(stubInfo, structure, cachedOffset, returnAddress);
319
 
        }
320
312
        
321
 
        static void compilePutByIdTransition(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, void* returnAddress)
 
313
        static void compilePutByIdTransition(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, ReturnAddressPtr returnAddress)
322
314
        {
323
315
            JIT jit(globalData, codeBlock);
324
316
            jit.privateCompilePutByIdTransition(stubInfo, oldStructure, newStructure, cachedOffset, chain, returnAddress);
325
317
        }
326
318
 
327
 
        static void compileCTIMachineTrampolines(JSGlobalData* globalData)
 
319
        static void compileCTIMachineTrampolines(JSGlobalData* globalData, RefPtr<ExecutablePool>* executablePool, CodePtr* ctiStringLengthTrampoline, CodePtr* ctiVirtualCallLink, CodePtr* ctiVirtualCall, CodePtr* ctiNativeCallThunk)
328
320
        {
329
321
            JIT jit(globalData);
330
 
            jit.privateCompileCTIMachineTrampolines();
 
322
            jit.privateCompileCTIMachineTrampolines(executablePool, globalData, ctiStringLengthTrampoline, ctiVirtualCallLink, ctiVirtualCall, ctiNativeCallThunk);
331
323
        }
332
324
 
333
 
        static void patchGetByIdSelf(StructureStubInfo*, Structure*, size_t cachedOffset, void* returnAddress);
334
 
        static void patchPutByIdReplace(StructureStubInfo*, Structure*, size_t cachedOffset, void* returnAddress);
 
325
        static void patchGetByIdSelf(CodeBlock* codeblock, StructureStubInfo*, Structure*, size_t cachedOffset, ReturnAddressPtr returnAddress);
 
326
        static void patchPutByIdReplace(CodeBlock* codeblock, StructureStubInfo*, Structure*, size_t cachedOffset, ReturnAddressPtr returnAddress);
 
327
        static void patchMethodCallProto(CodeBlock* codeblock, MethodCallLinkInfo&, JSFunction*, Structure*, JSObject*, ReturnAddressPtr);
335
328
 
336
 
        static void compilePatchGetArrayLength(JSGlobalData* globalData, CodeBlock* codeBlock, void* returnAddress)
 
329
        static void compilePatchGetArrayLength(JSGlobalData* globalData, CodeBlock* codeBlock, ReturnAddressPtr returnAddress)
337
330
        {
338
331
            JIT jit(globalData, codeBlock);
339
332
            return jit.privateCompilePatchGetArrayLength(returnAddress);
340
333
        }
341
334
 
342
 
        static void linkCall(JSFunction* callee, CodeBlock* calleeCodeBlock, void* ctiCode, CallLinkInfo* callLinkInfo, int callerArgCount);
 
335
        static void linkCall(JSFunction* callee, CodeBlock* callerCodeBlock, CodeBlock* calleeCodeBlock, JITCode&, CallLinkInfo*, int callerArgCount, JSGlobalData*);
343
336
        static void unlinkCall(CallLinkInfo*);
344
337
 
345
 
        inline static JSValuePtr execute(void* code, RegisterFile* registerFile, CallFrame* callFrame, JSGlobalData* globalData, JSValuePtr* exception)
346
 
        {
347
 
            return JSValuePtr::decode(ctiTrampoline(
348
 
#if PLATFORM(X86_64)
349
 
                0, 0, 0, 0, 0, 0,
350
 
#endif
351
 
                code, registerFile, callFrame, exception, Profiler::enabledProfilerReference(), globalData));
352
 
        }
353
 
 
354
338
    private:
 
339
        struct JSRInfo {
 
340
            DataLabelPtr storeLocation;
 
341
            Label target;
 
342
 
 
343
            JSRInfo(DataLabelPtr storeLocation, Label targetLocation)
 
344
                : storeLocation(storeLocation)
 
345
                , target(targetLocation)
 
346
            {
 
347
            }
 
348
        };
 
349
 
355
350
        JIT(JSGlobalData*, CodeBlock* = 0);
356
351
 
357
352
        void privateCompileMainPass();
358
353
        void privateCompileLinkPass();
359
354
        void privateCompileSlowCases();
360
 
        void privateCompile();
361
 
        void privateCompileGetByIdSelf(StructureStubInfo*, Structure*, size_t cachedOffset, void* returnAddress);
362
 
        void privateCompileGetByIdProto(StructureStubInfo*, Structure*, Structure* prototypeStructure, size_t cachedOffset, void* returnAddress, CallFrame* callFrame);
363
 
#if USE(CTI_REPATCH_PIC)
 
355
        JITCode privateCompile();
 
356
        void privateCompileGetByIdProto(StructureStubInfo*, Structure*, Structure* prototypeStructure, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame);
364
357
        void privateCompileGetByIdSelfList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, size_t cachedOffset);
365
358
        void privateCompileGetByIdProtoList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, Structure* prototypeStructure, size_t cachedOffset, CallFrame* callFrame);
366
359
        void privateCompileGetByIdChainList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, StructureChain* chain, size_t count, size_t cachedOffset, CallFrame* callFrame);
367
 
#endif
368
 
        void privateCompileGetByIdChain(StructureStubInfo*, Structure*, StructureChain*, size_t count, size_t cachedOffset, void* returnAddress, CallFrame* callFrame);
369
 
        void privateCompilePutByIdReplace(StructureStubInfo*, Structure*, size_t cachedOffset, void* returnAddress);
370
 
        void privateCompilePutByIdTransition(StructureStubInfo*, Structure*, Structure*, size_t cachedOffset, StructureChain*, void* returnAddress);
 
360
        void privateCompileGetByIdChain(StructureStubInfo*, Structure*, StructureChain*, size_t count, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame);
 
361
        void privateCompilePutByIdTransition(StructureStubInfo*, Structure*, Structure*, size_t cachedOffset, StructureChain*, ReturnAddressPtr returnAddress);
371
362
 
372
 
        void privateCompileCTIMachineTrampolines();
373
 
        void privateCompilePatchGetArrayLength(void* returnAddress);
 
363
        void privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executablePool, JSGlobalData* data, CodePtr* ctiStringLengthTrampoline, CodePtr* ctiVirtualCallLink, CodePtr* ctiVirtualCall, CodePtr* ctiNativeCallThunk);
 
364
        void privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress);
374
365
 
375
366
        void addSlowCase(Jump);
 
367
        void addSlowCase(JumpList);
376
368
        void addJump(Jump, int);
377
369
        void emitJumpSlowToHot(Jump, int);
378
370
 
379
 
        void compileGetByIdHotPath(int resultVReg, int baseVReg, Identifier* ident, unsigned propertyAccessInstructionIndex);
380
 
        void compileGetByIdSlowCase(int resultVReg, int baseVReg, Identifier* ident, Vector<SlowCaseEntry>::iterator& iter, unsigned propertyAccessInstructionIndex);
381
 
        void compilePutByIdHotPath(int baseVReg, Identifier* ident, int valueVReg, unsigned propertyAccessInstructionIndex);
382
 
        void compilePutByIdSlowCase(int baseVReg, Identifier* ident, int valueVReg, Vector<SlowCaseEntry>::iterator& iter, unsigned propertyAccessInstructionIndex);
383
371
        void compileOpCall(OpcodeID, Instruction* instruction, unsigned callLinkInfoIndex);
 
372
        void compileOpCallVarargs(Instruction* instruction);
384
373
        void compileOpCallInitializeCallFrame();
385
374
        void compileOpCallSetupArgs(Instruction*);
386
 
        void compileOpCallEvalSetupArgs(Instruction*);
 
375
        void compileOpCallVarargsSetupArgs(Instruction*);
387
376
        void compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter, unsigned callLinkInfoIndex, OpcodeID opcodeID);
 
377
        void compileOpCallVarargsSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter);
388
378
        void compileOpConstructSetupArgs(Instruction*);
 
379
 
389
380
        enum CompileOpStrictEqType { OpStrictEq, OpNStrictEq };
390
381
        void compileOpStrictEq(Instruction* instruction, CompileOpStrictEqType type);
391
 
        void putDoubleResultToJSNumberCellOrJSImmediate(X86Assembler::XMMRegisterID xmmSource, RegisterID jsNumberCell, unsigned dst, X86Assembler::JmpSrc* wroteJSNumberCell, X86Assembler::XMMRegisterID tempXmm, RegisterID tempReg1, RegisterID tempReg2);
392
 
 
393
 
        void compileFastArith_op_add(Instruction*);
394
 
        void compileFastArith_op_mul(Instruction*);
395
 
        void compileFastArith_op_mod(unsigned result, unsigned op1, unsigned op2);
396
 
        void compileFastArith_op_bitand(unsigned result, unsigned op1, unsigned op2);
397
 
        void compileFastArith_op_lshift(unsigned result, unsigned op1, unsigned op2);
398
 
        void compileFastArith_op_rshift(unsigned result, unsigned op1, unsigned op2);
399
 
        void compileFastArith_op_pre_inc(unsigned srcDst);
400
 
        void compileFastArith_op_pre_dec(unsigned srcDst);
401
 
        void compileFastArith_op_post_inc(unsigned result, unsigned srcDst);
402
 
        void compileFastArith_op_post_dec(unsigned result, unsigned srcDst);
403
 
        void compileFastArithSlow_op_add(Instruction*, Vector<SlowCaseEntry>::iterator&);
404
 
        void compileFastArithSlow_op_mul(Instruction*, Vector<SlowCaseEntry>::iterator&);
405
 
        void compileFastArithSlow_op_mod(unsigned result, unsigned op1, unsigned op2, Vector<SlowCaseEntry>::iterator&);
406
 
        void compileFastArithSlow_op_bitand(unsigned result, unsigned op1, unsigned op2, Vector<SlowCaseEntry>::iterator&);
407
 
        void compileFastArithSlow_op_lshift(unsigned result, unsigned op1, unsigned op2, Vector<SlowCaseEntry>::iterator&);
408
 
        void compileFastArithSlow_op_rshift(unsigned result, unsigned op1, unsigned op2, Vector<SlowCaseEntry>::iterator&);
409
 
        void compileFastArithSlow_op_pre_inc(unsigned srcDst, Vector<SlowCaseEntry>::iterator&);
410
 
        void compileFastArithSlow_op_pre_dec(unsigned srcDst, Vector<SlowCaseEntry>::iterator&);
411
 
        void compileFastArithSlow_op_post_inc(unsigned result, unsigned srcDst, Vector<SlowCaseEntry>::iterator&);
412
 
        void compileFastArithSlow_op_post_dec(unsigned result, unsigned srcDst, Vector<SlowCaseEntry>::iterator&);
413
 
        void compileBinaryArithOp(OpcodeID, unsigned dst, unsigned src1, unsigned src2, OperandTypes opi);
414
 
        void compileBinaryArithOpSlowCase(OpcodeID, Vector<SlowCaseEntry>::iterator&, unsigned dst, unsigned src1, unsigned src2, OperandTypes opi);
415
 
 
 
382
        bool isOperandConstantImmediateDouble(unsigned src);
 
383
        
 
384
        void emitLoadDouble(unsigned index, FPRegisterID value);
 
385
        void emitLoadInt32ToDouble(unsigned index, FPRegisterID value);
 
386
 
 
387
        Address addressFor(unsigned index, RegisterID base = callFrameRegister);
 
388
 
 
389
#if USE(JSVALUE32_64)
 
390
        Address tagFor(unsigned index, RegisterID base = callFrameRegister);
 
391
        Address payloadFor(unsigned index, RegisterID base = callFrameRegister);
 
392
 
 
393
        bool getOperandConstantImmediateInt(unsigned op1, unsigned op2, unsigned& op, int32_t& constant);
 
394
 
 
395
        void emitLoadTag(unsigned index, RegisterID tag);
 
396
        void emitLoadPayload(unsigned index, RegisterID payload);
 
397
 
 
398
        void emitLoad(const JSValue& v, RegisterID tag, RegisterID payload);
 
399
        void emitLoad(unsigned index, RegisterID tag, RegisterID payload, RegisterID base = callFrameRegister);
 
400
        void emitLoad2(unsigned index1, RegisterID tag1, RegisterID payload1, unsigned index2, RegisterID tag2, RegisterID payload2);
 
401
 
 
402
        void emitStore(unsigned index, RegisterID tag, RegisterID payload, RegisterID base = callFrameRegister);
 
403
        void emitStore(unsigned index, const JSValue constant, RegisterID base = callFrameRegister);
 
404
        void emitStoreInt32(unsigned index, RegisterID payload, bool indexIsInt32 = false);
 
405
        void emitStoreInt32(unsigned index, Imm32 payload, bool indexIsInt32 = false);
 
406
        void emitStoreCell(unsigned index, RegisterID payload, bool indexIsCell = false);
 
407
        void emitStoreBool(unsigned index, RegisterID tag, bool indexIsBool = false);
 
408
        void emitStoreDouble(unsigned index, FPRegisterID value);
 
409
 
 
410
        bool isLabeled(unsigned bytecodeIndex);
 
411
        void map(unsigned bytecodeIndex, unsigned virtualRegisterIndex, RegisterID tag, RegisterID payload);
 
412
        void unmap(RegisterID);
 
413
        void unmap();
 
414
        bool isMapped(unsigned virtualRegisterIndex);
 
415
        bool getMappedPayload(unsigned virtualRegisterIndex, RegisterID& payload);
 
416
        bool getMappedTag(unsigned virtualRegisterIndex, RegisterID& tag);
 
417
 
 
418
        void emitJumpSlowCaseIfNotJSCell(unsigned virtualRegisterIndex);
 
419
        void emitJumpSlowCaseIfNotJSCell(unsigned virtualRegisterIndex, RegisterID tag);
 
420
        void linkSlowCaseIfNotJSCell(Vector<SlowCaseEntry>::iterator&, unsigned virtualRegisterIndex);
 
421
 
 
422
#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
 
423
        void compileGetByIdHotPath();
 
424
        void compileGetByIdSlowCase(int resultVReg, int baseVReg, Identifier* ident, Vector<SlowCaseEntry>::iterator& iter, bool isMethodCheck = false);
 
425
#endif
 
426
        void compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, Structure* structure, size_t cachedOffset);
 
427
        void compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID resultTag, RegisterID resultPayload, size_t cachedOffset);
 
428
        void compilePutDirectOffset(RegisterID base, RegisterID valueTag, RegisterID valuePayload, Structure* structure, size_t cachedOffset);
 
429
 
 
430
        // Arithmetic opcode helpers
 
431
        void emitAdd32Constant(unsigned dst, unsigned op, int32_t constant, ResultType opType);
 
432
        void emitSub32Constant(unsigned dst, unsigned op, int32_t constant, ResultType opType);
 
433
        void emitBinaryDoubleOp(OpcodeID, unsigned dst, unsigned op1, unsigned op2, OperandTypes, JumpList& notInt32Op1, JumpList& notInt32Op2, bool op1IsInRegisters = true, bool op2IsInRegisters = true);
 
434
 
 
435
#if PLATFORM(X86)
 
436
        // These architecture specific value are used to enable patching - see comment on op_put_by_id.
 
437
        static const int patchOffsetPutByIdStructure = 7;
 
438
        static const int patchOffsetPutByIdExternalLoad = 13;
 
439
        static const int patchLengthPutByIdExternalLoad = 3;
 
440
        static const int patchOffsetPutByIdPropertyMapOffset1 = 22;
 
441
        static const int patchOffsetPutByIdPropertyMapOffset2 = 28;
 
442
        // These architecture specific value are used to enable patching - see comment on op_get_by_id.
 
443
        static const int patchOffsetGetByIdStructure = 7;
 
444
        static const int patchOffsetGetByIdBranchToSlowCase = 13;
 
445
        static const int patchOffsetGetByIdExternalLoad = 13;
 
446
        static const int patchLengthGetByIdExternalLoad = 3;
 
447
        static const int patchOffsetGetByIdPropertyMapOffset1 = 22;
 
448
        static const int patchOffsetGetByIdPropertyMapOffset2 = 28;
 
449
        static const int patchOffsetGetByIdPutResult = 28;
 
450
#if ENABLE(OPCODE_SAMPLING) && USE(JIT_STUB_ARGUMENT_VA_LIST)
 
451
        static const int patchOffsetGetByIdSlowCaseCall = 35;
 
452
#elif ENABLE(OPCODE_SAMPLING)
 
453
        static const int patchOffsetGetByIdSlowCaseCall = 37;
 
454
#elif USE(JIT_STUB_ARGUMENT_VA_LIST)
 
455
        static const int patchOffsetGetByIdSlowCaseCall = 25;
 
456
#else
 
457
        static const int patchOffsetGetByIdSlowCaseCall = 27;
 
458
#endif
 
459
        static const int patchOffsetOpCallCompareToJump = 6;
 
460
 
 
461
        static const int patchOffsetMethodCheckProtoObj = 11;
 
462
        static const int patchOffsetMethodCheckProtoStruct = 18;
 
463
        static const int patchOffsetMethodCheckPutFunction = 29;
 
464
#else
 
465
#error "JSVALUE32_64 not supported on this platform."
 
466
#endif
 
467
 
 
468
#else // USE(JSVALUE32_64)
416
469
        void emitGetVirtualRegister(int src, RegisterID dst);
417
470
        void emitGetVirtualRegisters(int src1, RegisterID dst1, int src2, RegisterID dst2);
418
 
        void emitPutVirtualRegister(unsigned dst, RegisterID from = X86::eax);
419
 
 
 
471
        void emitPutVirtualRegister(unsigned dst, RegisterID from = regT0);
 
472
 
 
473
        int32_t getConstantOperandImmediateInt(unsigned src);
 
474
 
 
475
        void emitGetVariableObjectRegister(RegisterID variableObject, int index, RegisterID dst);
 
476
        void emitPutVariableObjectRegister(RegisterID src, RegisterID variableObject, int index);
 
477
        
 
478
        void killLastResultRegister();
 
479
 
 
480
        Jump emitJumpIfJSCell(RegisterID);
 
481
        Jump emitJumpIfBothJSCells(RegisterID, RegisterID, RegisterID);
 
482
        void emitJumpSlowCaseIfJSCell(RegisterID);
 
483
        Jump emitJumpIfNotJSCell(RegisterID);
 
484
        void emitJumpSlowCaseIfNotJSCell(RegisterID);
 
485
        void emitJumpSlowCaseIfNotJSCell(RegisterID, int VReg);
 
486
#if USE(JSVALUE64)
 
487
        JIT::Jump emitJumpIfImmediateNumber(RegisterID);
 
488
        JIT::Jump emitJumpIfNotImmediateNumber(RegisterID);
 
489
#else
 
490
        JIT::Jump emitJumpIfImmediateNumber(RegisterID reg)
 
491
        {
 
492
            return emitJumpIfImmediateInteger(reg);
 
493
        }
 
494
        
 
495
        JIT::Jump emitJumpIfNotImmediateNumber(RegisterID reg)
 
496
        {
 
497
            return emitJumpIfNotImmediateInteger(reg);
 
498
        }
 
499
#endif
 
500
        JIT::Jump emitJumpIfImmediateInteger(RegisterID);
 
501
        JIT::Jump emitJumpIfNotImmediateInteger(RegisterID);
 
502
        JIT::Jump emitJumpIfNotImmediateIntegers(RegisterID, RegisterID, RegisterID);
 
503
        void emitJumpSlowCaseIfNotImmediateInteger(RegisterID);
 
504
        void emitJumpSlowCaseIfNotImmediateNumber(RegisterID);
 
505
        void emitJumpSlowCaseIfNotImmediateIntegers(RegisterID, RegisterID, RegisterID);
 
506
 
 
507
#if !USE(JSVALUE64)
 
508
        void emitFastArithDeTagImmediate(RegisterID);
 
509
        Jump emitFastArithDeTagImmediateJumpIfZero(RegisterID);
 
510
#endif
 
511
        void emitFastArithReTagImmediate(RegisterID src, RegisterID dest);
 
512
        void emitFastArithImmToInt(RegisterID);
 
513
        void emitFastArithIntToImmNoCheck(RegisterID src, RegisterID dest);
 
514
 
 
515
        void emitTagAsBoolImmediate(RegisterID reg);
 
516
        void compileBinaryArithOp(OpcodeID, unsigned dst, unsigned src1, unsigned src2, OperandTypes opi);
 
517
#if USE(JSVALUE64)
 
518
        void compileBinaryArithOpSlowCase(OpcodeID, Vector<SlowCaseEntry>::iterator&, unsigned dst, unsigned src1, unsigned src2, OperandTypes, bool op1HasImmediateIntFastCase, bool op2HasImmediateIntFastCase);
 
519
#else
 
520
        void compileBinaryArithOpSlowCase(OpcodeID, Vector<SlowCaseEntry>::iterator&, unsigned dst, unsigned src1, unsigned src2, OperandTypes);
 
521
#endif
 
522
 
 
523
#if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
 
524
        void compileGetByIdHotPath(int resultVReg, int baseVReg, Identifier* ident, unsigned propertyAccessInstructionIndex);
 
525
        void compileGetByIdSlowCase(int resultVReg, int baseVReg, Identifier* ident, Vector<SlowCaseEntry>::iterator& iter, bool isMethodCheck = false);
 
526
#endif
 
527
        void compileGetDirectOffset(RegisterID base, RegisterID result, Structure* structure, size_t cachedOffset);
 
528
        void compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID result, size_t cachedOffset);
 
529
        void compilePutDirectOffset(RegisterID base, RegisterID value, Structure* structure, size_t cachedOffset);
 
530
 
 
531
#if PLATFORM(X86_64)
 
532
        // These architecture specific value are used to enable patching - see comment on op_put_by_id.
 
533
        static const int patchOffsetPutByIdStructure = 10;
 
534
        static const int patchOffsetPutByIdExternalLoad = 20;
 
535
        static const int patchLengthPutByIdExternalLoad = 4;
 
536
        static const int patchOffsetPutByIdPropertyMapOffset = 31;
 
537
        // These architecture specific value are used to enable patching - see comment on op_get_by_id.
 
538
        static const int patchOffsetGetByIdStructure = 10;
 
539
        static const int patchOffsetGetByIdBranchToSlowCase = 20;
 
540
        static const int patchOffsetGetByIdExternalLoad = 20;
 
541
        static const int patchLengthGetByIdExternalLoad = 4;
 
542
        static const int patchOffsetGetByIdPropertyMapOffset = 31;
 
543
        static const int patchOffsetGetByIdPutResult = 31;
 
544
#if ENABLE(OPCODE_SAMPLING)
 
545
        static const int patchOffsetGetByIdSlowCaseCall = 64;
 
546
#else
 
547
        static const int patchOffsetGetByIdSlowCaseCall = 41;
 
548
#endif
 
549
        static const int patchOffsetOpCallCompareToJump = 9;
 
550
 
 
551
        static const int patchOffsetMethodCheckProtoObj = 20;
 
552
        static const int patchOffsetMethodCheckProtoStruct = 30;
 
553
        static const int patchOffsetMethodCheckPutFunction = 50;
 
554
#elif PLATFORM(X86)
 
555
        // These architecture specific value are used to enable patching - see comment on op_put_by_id.
 
556
        static const int patchOffsetPutByIdStructure = 7;
 
557
        static const int patchOffsetPutByIdExternalLoad = 13;
 
558
        static const int patchLengthPutByIdExternalLoad = 3;
 
559
        static const int patchOffsetPutByIdPropertyMapOffset = 22;
 
560
        // These architecture specific value are used to enable patching - see comment on op_get_by_id.
 
561
        static const int patchOffsetGetByIdStructure = 7;
 
562
        static const int patchOffsetGetByIdBranchToSlowCase = 13;
 
563
        static const int patchOffsetGetByIdExternalLoad = 13;
 
564
        static const int patchLengthGetByIdExternalLoad = 3;
 
565
        static const int patchOffsetGetByIdPropertyMapOffset = 22;
 
566
        static const int patchOffsetGetByIdPutResult = 22;
 
567
#if ENABLE(OPCODE_SAMPLING) && USE(JIT_STUB_ARGUMENT_VA_LIST)
 
568
        static const int patchOffsetGetByIdSlowCaseCall = 31;
 
569
#elif ENABLE(OPCODE_SAMPLING)
 
570
        static const int patchOffsetGetByIdSlowCaseCall = 33;
 
571
#elif USE(JIT_STUB_ARGUMENT_VA_LIST)
 
572
        static const int patchOffsetGetByIdSlowCaseCall = 21;
 
573
#else
 
574
        static const int patchOffsetGetByIdSlowCaseCall = 23;
 
575
#endif
 
576
        static const int patchOffsetOpCallCompareToJump = 6;
 
577
 
 
578
        static const int patchOffsetMethodCheckProtoObj = 11;
 
579
        static const int patchOffsetMethodCheckProtoStruct = 18;
 
580
        static const int patchOffsetMethodCheckPutFunction = 29;
 
581
#elif PLATFORM(ARM_THUMB2)
 
582
        // These architecture specific value are used to enable patching - see comment on op_put_by_id.
 
583
        static const int patchOffsetPutByIdStructure = 10;
 
584
        static const int patchOffsetPutByIdExternalLoad = 20;
 
585
        static const int patchLengthPutByIdExternalLoad = 12;
 
586
        static const int patchOffsetPutByIdPropertyMapOffset = 40;
 
587
        // These architecture specific value are used to enable patching - see comment on op_get_by_id.
 
588
        static const int patchOffsetGetByIdStructure = 10;
 
589
        static const int patchOffsetGetByIdBranchToSlowCase = 20;
 
590
        static const int patchOffsetGetByIdExternalLoad = 20;
 
591
        static const int patchLengthGetByIdExternalLoad = 12;
 
592
        static const int patchOffsetGetByIdPropertyMapOffset = 40;
 
593
        static const int patchOffsetGetByIdPutResult = 44;
 
594
#if ENABLE(OPCODE_SAMPLING)
 
595
        static const int patchOffsetGetByIdSlowCaseCall = 0; // FIMXE
 
596
#else
 
597
        static const int patchOffsetGetByIdSlowCaseCall = 28;
 
598
#endif
 
599
        static const int patchOffsetOpCallCompareToJump = 10;
 
600
 
 
601
        static const int patchOffsetMethodCheckProtoObj = 18;
 
602
        static const int patchOffsetMethodCheckProtoStruct = 28;
 
603
        static const int patchOffsetMethodCheckPutFunction = 46;
 
604
#elif PLATFORM(ARM_TRADITIONAL)
 
605
        // These architecture specific value are used to enable patching - see comment on op_put_by_id.
 
606
        static const int patchOffsetPutByIdStructure = 4;
 
607
        static const int patchOffsetPutByIdExternalLoad = 16;
 
608
        static const int patchLengthPutByIdExternalLoad = 4;
 
609
        static const int patchOffsetPutByIdPropertyMapOffset = 20;
 
610
        // These architecture specific value are used to enable patching - see comment on op_get_by_id.
 
611
        static const int patchOffsetGetByIdStructure = 4;
 
612
        static const int patchOffsetGetByIdBranchToSlowCase = 16;
 
613
        static const int patchOffsetGetByIdExternalLoad = 16;
 
614
        static const int patchLengthGetByIdExternalLoad = 4;
 
615
        static const int patchOffsetGetByIdPropertyMapOffset = 20;
 
616
        static const int patchOffsetGetByIdPutResult = 28;
 
617
#if ENABLE(OPCODE_SAMPLING)
 
618
        #error "OPCODE_SAMPLING is not yet supported"
 
619
#else
 
620
        static const int patchOffsetGetByIdSlowCaseCall = 36;
 
621
#endif
 
622
        static const int patchOffsetOpCallCompareToJump = 12;
 
623
 
 
624
        static const int patchOffsetMethodCheckProtoObj = 12;
 
625
        static const int patchOffsetMethodCheckProtoStruct = 20;
 
626
        static const int patchOffsetMethodCheckPutFunction = 32;
 
627
#endif
 
628
#endif // USE(JSVALUE32_64)
 
629
 
 
630
#if PLATFORM(ARM_TRADITIONAL)
 
631
        // sequenceOpCall
 
632
        static const int sequenceOpCallInstructionSpace = 12;
 
633
        static const int sequenceOpCallConstantSpace = 2;
 
634
        // sequenceMethodCheck
 
635
        static const int sequenceMethodCheckInstructionSpace = 40;
 
636
        static const int sequenceMethodCheckConstantSpace = 6;
 
637
        // sequenceGetByIdHotPath
 
638
        static const int sequenceGetByIdHotPathInstructionSpace = 28;
 
639
        static const int sequenceGetByIdHotPathConstantSpace = 3;
 
640
        // sequenceGetByIdSlowCase
 
641
        static const int sequenceGetByIdSlowCaseInstructionSpace = 40;
 
642
        static const int sequenceGetByIdSlowCaseConstantSpace = 2;
 
643
        // sequencePutById
 
644
        static const int sequencePutByIdInstructionSpace = 28;
 
645
        static const int sequencePutByIdConstantSpace = 3;
 
646
#endif
 
647
 
 
648
#if defined(ASSEMBLER_HAS_CONSTANT_POOL) && ASSEMBLER_HAS_CONSTANT_POOL
 
649
#define BEGIN_UNINTERRUPTED_SEQUENCE(name) beginUninterruptedSequence(name ## InstructionSpace, name ## ConstantSpace)
 
650
#define END_UNINTERRUPTED_SEQUENCE(name) endUninterruptedSequence(name ## InstructionSpace, name ## ConstantSpace)
 
651
 
 
652
        void beginUninterruptedSequence(int, int);
 
653
        void endUninterruptedSequence(int, int);
 
654
 
 
655
#else
 
656
#define BEGIN_UNINTERRUPTED_SEQUENCE(name)
 
657
#define END_UNINTERRUPTED_SEQUENCE(name)
 
658
#endif
 
659
 
 
660
        void emit_op_add(Instruction*);
 
661
        void emit_op_bitand(Instruction*);
 
662
        void emit_op_bitnot(Instruction*);
 
663
        void emit_op_bitor(Instruction*);
 
664
        void emit_op_bitxor(Instruction*);
 
665
        void emit_op_call(Instruction*);
 
666
        void emit_op_call_eval(Instruction*);
 
667
        void emit_op_call_varargs(Instruction*);
 
668
        void emit_op_catch(Instruction*);
 
669
        void emit_op_construct(Instruction*);
 
670
        void emit_op_construct_verify(Instruction*);
 
671
        void emit_op_convert_this(Instruction*);
 
672
        void emit_op_create_arguments(Instruction*);
 
673
        void emit_op_debug(Instruction*);
 
674
        void emit_op_del_by_id(Instruction*);
 
675
        void emit_op_div(Instruction*);
 
676
        void emit_op_end(Instruction*);
 
677
        void emit_op_enter(Instruction*);
 
678
        void emit_op_enter_with_activation(Instruction*);
 
679
        void emit_op_eq(Instruction*);
 
680
        void emit_op_eq_null(Instruction*);
 
681
        void emit_op_get_by_id(Instruction*);
 
682
        void emit_op_get_by_val(Instruction*);
 
683
        void emit_op_get_global_var(Instruction*);
 
684
        void emit_op_get_scoped_var(Instruction*);
 
685
        void emit_op_init_arguments(Instruction*);
 
686
        void emit_op_instanceof(Instruction*);
 
687
        void emit_op_jeq_null(Instruction*);
 
688
        void emit_op_jfalse(Instruction*);
 
689
        void emit_op_jmp(Instruction*);
 
690
        void emit_op_jmp_scopes(Instruction*);
 
691
        void emit_op_jneq_null(Instruction*);
 
692
        void emit_op_jneq_ptr(Instruction*);
 
693
        void emit_op_jnless(Instruction*);
 
694
        void emit_op_jnlesseq(Instruction*);
 
695
        void emit_op_jsr(Instruction*);
 
696
        void emit_op_jtrue(Instruction*);
 
697
        void emit_op_load_varargs(Instruction*);
 
698
        void emit_op_loop(Instruction*);
 
699
        void emit_op_loop_if_less(Instruction*);
 
700
        void emit_op_loop_if_lesseq(Instruction*);
 
701
        void emit_op_loop_if_true(Instruction*);
 
702
        void emit_op_lshift(Instruction*);
 
703
        void emit_op_method_check(Instruction*);
 
704
        void emit_op_mod(Instruction*);
 
705
        void emit_op_mov(Instruction*);
 
706
        void emit_op_mul(Instruction*);
 
707
        void emit_op_negate(Instruction*);
 
708
        void emit_op_neq(Instruction*);
 
709
        void emit_op_neq_null(Instruction*);
 
710
        void emit_op_new_array(Instruction*);
 
711
        void emit_op_new_error(Instruction*);
 
712
        void emit_op_new_func(Instruction*);
 
713
        void emit_op_new_func_exp(Instruction*);
 
714
        void emit_op_new_object(Instruction*);
 
715
        void emit_op_new_regexp(Instruction*);
 
716
        void emit_op_next_pname(Instruction*);
 
717
        void emit_op_not(Instruction*);
 
718
        void emit_op_nstricteq(Instruction*);
 
719
        void emit_op_pop_scope(Instruction*);
 
720
        void emit_op_post_dec(Instruction*);
 
721
        void emit_op_post_inc(Instruction*);
 
722
        void emit_op_pre_dec(Instruction*);
 
723
        void emit_op_pre_inc(Instruction*);
 
724
        void emit_op_profile_did_call(Instruction*);
 
725
        void emit_op_profile_will_call(Instruction*);
 
726
        void emit_op_push_new_scope(Instruction*);
 
727
        void emit_op_push_scope(Instruction*);
 
728
        void emit_op_put_by_id(Instruction*);
 
729
        void emit_op_put_by_index(Instruction*);
 
730
        void emit_op_put_by_val(Instruction*);
 
731
        void emit_op_put_getter(Instruction*);
 
732
        void emit_op_put_global_var(Instruction*);
 
733
        void emit_op_put_scoped_var(Instruction*);
 
734
        void emit_op_put_setter(Instruction*);
 
735
        void emit_op_resolve(Instruction*);
 
736
        void emit_op_resolve_base(Instruction*);
 
737
        void emit_op_resolve_global(Instruction*);
 
738
        void emit_op_resolve_skip(Instruction*);
 
739
        void emit_op_resolve_with_base(Instruction*);
 
740
        void emit_op_ret(Instruction*);
 
741
        void emit_op_rshift(Instruction*);
 
742
        void emit_op_sret(Instruction*);
 
743
        void emit_op_strcat(Instruction*);
 
744
        void emit_op_stricteq(Instruction*);
 
745
        void emit_op_sub(Instruction*);
 
746
        void emit_op_switch_char(Instruction*);
 
747
        void emit_op_switch_imm(Instruction*);
 
748
        void emit_op_switch_string(Instruction*);
 
749
        void emit_op_tear_off_activation(Instruction*);
 
750
        void emit_op_tear_off_arguments(Instruction*);
 
751
        void emit_op_throw(Instruction*);
 
752
        void emit_op_to_jsnumber(Instruction*);
 
753
        void emit_op_to_primitive(Instruction*);
 
754
        void emit_op_unexpected_load(Instruction*);
 
755
 
 
756
        void emitSlow_op_add(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
757
        void emitSlow_op_bitand(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
758
        void emitSlow_op_bitnot(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
759
        void emitSlow_op_bitor(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
760
        void emitSlow_op_bitxor(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
761
        void emitSlow_op_call(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
762
        void emitSlow_op_call_eval(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
763
        void emitSlow_op_call_varargs(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
764
        void emitSlow_op_construct(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
765
        void emitSlow_op_construct_verify(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
766
        void emitSlow_op_convert_this(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
767
        void emitSlow_op_div(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
768
        void emitSlow_op_eq(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
769
        void emitSlow_op_get_by_id(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
770
        void emitSlow_op_get_by_val(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
771
        void emitSlow_op_instanceof(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
772
        void emitSlow_op_jfalse(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
773
        void emitSlow_op_jnless(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
774
        void emitSlow_op_jnlesseq(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
775
        void emitSlow_op_jtrue(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
776
        void emitSlow_op_loop_if_less(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
777
        void emitSlow_op_loop_if_lesseq(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
778
        void emitSlow_op_loop_if_true(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
779
        void emitSlow_op_lshift(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
780
        void emitSlow_op_method_check(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
781
        void emitSlow_op_mod(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
782
        void emitSlow_op_mul(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
783
        void emitSlow_op_negate(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
784
        void emitSlow_op_neq(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
785
        void emitSlow_op_not(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
786
        void emitSlow_op_nstricteq(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
787
        void emitSlow_op_post_dec(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
788
        void emitSlow_op_post_inc(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
789
        void emitSlow_op_pre_dec(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
790
        void emitSlow_op_pre_inc(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
791
        void emitSlow_op_put_by_id(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
792
        void emitSlow_op_put_by_val(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
793
        void emitSlow_op_resolve_global(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
794
        void emitSlow_op_rshift(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
795
        void emitSlow_op_stricteq(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
796
        void emitSlow_op_sub(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
797
        void emitSlow_op_to_jsnumber(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
798
        void emitSlow_op_to_primitive(Instruction*, Vector<SlowCaseEntry>::iterator&);
 
799
 
 
800
        /* These functions are deprecated: Please use JITStubCall instead. */
420
801
        void emitPutJITStubArg(RegisterID src, unsigned argumentNumber);
 
802
#if USE(JSVALUE32_64)
 
803
        void emitPutJITStubArg(RegisterID tag, RegisterID payload, unsigned argumentNumber);
 
804
        void emitPutJITStubArgFromVirtualRegister(unsigned src, unsigned argumentNumber, RegisterID scratch1, RegisterID scratch2);
 
805
#else
421
806
        void emitPutJITStubArgFromVirtualRegister(unsigned src, unsigned argumentNumber, RegisterID scratch);
 
807
#endif
422
808
        void emitPutJITStubArgConstant(unsigned value, unsigned argumentNumber);
423
809
        void emitPutJITStubArgConstant(void* value, unsigned argumentNumber);
424
810
        void emitGetJITStubArg(unsigned argumentNumber, RegisterID dst);
425
811
 
426
812
        void emitInitRegister(unsigned dst);
427
813
 
428
 
        void emitPutCTIParam(void* value, unsigned name);
429
 
        void emitPutCTIParam(RegisterID from, unsigned name);
430
 
        void emitGetCTIParam(unsigned name, RegisterID to);
431
 
 
432
814
        void emitPutToCallFrameHeader(RegisterID from, RegisterFile::CallFrameHeaderEntry entry);
433
815
        void emitPutImmediateToCallFrameHeader(void* value, RegisterFile::CallFrameHeaderEntry entry);
434
 
        void emitGetFromCallFrameHeader(RegisterFile::CallFrameHeaderEntry entry, RegisterID to);
 
816
        void emitGetFromCallFrameHeaderPtr(RegisterFile::CallFrameHeaderEntry entry, RegisterID to, RegisterID from = callFrameRegister);
 
817
        void emitGetFromCallFrameHeader32(RegisterFile::CallFrameHeaderEntry entry, RegisterID to, RegisterID from = callFrameRegister);
435
818
 
436
 
        JSValuePtr getConstantOperand(unsigned src);
437
 
        int32_t getConstantOperandImmediateInt(unsigned src);
 
819
        JSValue getConstantOperand(unsigned src);
438
820
        bool isOperandConstantImmediateInt(unsigned src);
439
821
 
440
 
        Jump emitJumpIfJSCell(RegisterID);
441
 
        void emitJumpSlowCaseIfJSCell(RegisterID);
442
 
        Jump emitJumpIfNotJSCell(RegisterID);
443
 
        void emitJumpSlowCaseIfNotJSCell(RegisterID);
444
 
        void emitJumpSlowCaseIfNotJSCell(RegisterID, int VReg);
445
 
 
446
822
        Jump getSlowCase(Vector<SlowCaseEntry>::iterator& iter)
447
823
        {
448
824
            return iter++->from;
454
830
        }
455
831
        void linkSlowCaseIfNotJSCell(Vector<SlowCaseEntry>::iterator&, int vReg);
456
832
 
457
 
        JIT::Jump emitJumpIfImmNum(RegisterID);
458
 
        void emitJumpSlowCaseIfNotImmNum(RegisterID);
459
 
        void emitJumpSlowCaseIfNotImmNums(RegisterID, RegisterID, RegisterID);
460
 
 
461
833
        Jump checkStructure(RegisterID reg, Structure* structure);
462
834
 
463
 
#if !USE(ALTERNATE_JSIMMEDIATE)
464
 
        void emitFastArithDeTagImmediate(RegisterID);
465
 
        Jump emitFastArithDeTagImmediateJumpIfZero(RegisterID);
466
 
#endif
467
 
        void emitFastArithReTagImmediate(RegisterID src, RegisterID dest);
468
 
        void emitFastArithImmToInt(RegisterID);
469
 
        void emitFastArithIntToImmNoCheck(RegisterID src, RegisterID dest);
470
 
 
471
 
        void emitTagAsBoolImmediate(RegisterID reg);
472
 
 
473
835
        void restoreArgumentReference();
474
836
        void restoreArgumentReferenceForTrampoline();
475
837
 
476
 
        Jump emitNakedCall(RegisterID);
477
 
        Jump emitNakedCall(void* function);
478
 
        Jump emitCTICall_internal(void*);
479
 
        Jump emitCTICall(CTIHelper_j helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); }
480
 
        Jump emitCTICall(CTIHelper_o helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); }
481
 
        Jump emitCTICall(CTIHelper_p helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); }
482
 
        Jump emitCTICall(CTIHelper_v helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); }
483
 
        Jump emitCTICall(CTIHelper_s helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); }
484
 
        Jump emitCTICall(CTIHelper_b helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); }
485
 
        Jump emitCTICall(CTIHelper_2 helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); }
486
 
 
487
 
        void emitGetVariableObjectRegister(RegisterID variableObject, int index, RegisterID dst);
488
 
        void emitPutVariableObjectRegister(RegisterID src, RegisterID variableObject, int index);
489
 
        
490
 
        void emitSlowScriptCheck();
 
838
        Call emitNakedCall(CodePtr function = CodePtr());
 
839
 
 
840
        void preserveReturnAddressAfterCall(RegisterID);
 
841
        void restoreReturnAddressBeforeReturn(RegisterID);
 
842
        void restoreReturnAddressBeforeReturn(Address);
 
843
 
 
844
        void emitTimeoutCheck();
491
845
#ifndef NDEBUG
492
846
        void printBytecodeOperandTypes(unsigned src1, unsigned src2);
493
847
#endif
494
848
 
495
 
        void killLastResultRegister();
 
849
#if ENABLE(SAMPLING_FLAGS)
 
850
        void setSamplingFlag(int32_t);
 
851
        void clearSamplingFlag(int32_t);
 
852
#endif
 
853
 
 
854
#if ENABLE(SAMPLING_COUNTERS)
 
855
        void emitCount(AbstractSamplingCounter&, uint32_t = 1);
 
856
#endif
 
857
 
 
858
#if ENABLE(OPCODE_SAMPLING)
 
859
        void sampleInstruction(Instruction*, bool = false);
 
860
#endif
 
861
 
 
862
#if ENABLE(CODEBLOCK_SAMPLING)
 
863
        void sampleCodeBlock(CodeBlock*);
 
864
#else
 
865
        void sampleCodeBlock(CodeBlock*) {}
 
866
#endif
496
867
 
497
868
        Interpreter* m_interpreter;
498
869
        JSGlobalData* m_globalData;
502
873
        Vector<Label> m_labels;
503
874
        Vector<PropertyStubCompilationInfo> m_propertyAccessCompilationInfo;
504
875
        Vector<StructureStubCompilationInfo> m_callStructureStubCompilationInfo;
 
876
        Vector<MethodCallCompilationInfo> m_methodCallCompilationInfo;
505
877
        Vector<JumpTable> m_jmpTable;
506
878
 
507
 
        struct JSRInfo {
508
 
            DataLabelPtr storeLocation;
509
 
            Label target;
510
 
 
511
 
            JSRInfo(DataLabelPtr storeLocation, Label targetLocation)
512
 
                : storeLocation(storeLocation)
513
 
                , target(targetLocation)
514
 
            {
515
 
            }
516
 
        };
517
 
 
518
879
        unsigned m_bytecodeIndex;
519
880
        Vector<JSRInfo> m_jsrSites;
520
881
        Vector<SlowCaseEntry> m_slowCases;
521
882
        Vector<SwitchRecord> m_switches;
522
883
 
 
884
        unsigned m_propertyAccessInstructionIndex;
 
885
        unsigned m_globalResolveInfoIndex;
 
886
        unsigned m_callLinkInfoIndex;
 
887
 
 
888
#if USE(JSVALUE32_64)
 
889
        unsigned m_jumpTargetIndex;
 
890
        unsigned m_mappedBytecodeIndex;
 
891
        unsigned m_mappedVirtualRegisterIndex;
 
892
        RegisterID m_mappedTag;
 
893
        RegisterID m_mappedPayload;
 
894
#else
523
895
        int m_lastResultBytecodeRegister;
524
896
        unsigned m_jumpTargetsPosition;
525
 
    };
526
 
}
 
897
#endif
 
898
 
 
899
#ifndef NDEBUG
 
900
#if defined(ASSEMBLER_HAS_CONSTANT_POOL) && ASSEMBLER_HAS_CONSTANT_POOL
 
901
        Label m_uninterruptedInstructionSequenceBegin;
 
902
        int m_uninterruptedConstantSequenceBegin;
 
903
#endif
 
904
#endif
 
905
    } JIT_CLASS_ALIGNMENT;
 
906
} // namespace JSC
527
907
 
528
908
#endif // ENABLE(JIT)
529
909