2008-12-12 Gavin Barraclough <barraclough@apple.com>
[WebKit-https.git] / JavaScriptCore / jit / JIT.cpp
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 #include "config.h"
27 #include "JIT.h"
28
29 #if ENABLE(JIT)
30
31 #include "CodeBlock.h"
32 #include "JITInlineMethods.h"
33 #include "JSArray.h"
34 #include "JSFunction.h"
35 #include "Interpreter.h"
36 #include "ResultType.h"
37 #include "SamplingTool.h"
38
39 #ifndef NDEBUG
40 #include <stdio.h>
41 #endif
42
43 using namespace std;
44
45 namespace JSC {
46
47 COMPILE_ASSERT(CTI_ARGS_code == 0xC, CTI_ARGS_code_is_C);
48 COMPILE_ASSERT(CTI_ARGS_callFrame == 0xE, CTI_ARGS_callFrame_is_E);
49
50 #if COMPILER(GCC) && PLATFORM(X86)
51
52 #if PLATFORM(DARWIN)
53 #define SYMBOL_STRING(name) "_" #name
54 #else
55 #define SYMBOL_STRING(name) #name
56 #endif
57
58 asm(
59 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
60 SYMBOL_STRING(ctiTrampoline) ":" "\n"
61     "pushl %esi" "\n"
62     "pushl %edi" "\n"
63     "pushl %ebx" "\n"
64     "subl $0x20, %esp" "\n"
65     "movl $512, %esi" "\n"
66     "movl 0x38(%esp), %edi" "\n" // Ox38 = 0x0E * 4, 0x0E = CTI_ARGS_callFrame (see assertion above)
67     "call *0x30(%esp)" "\n" // Ox30 = 0x0C * 4, 0x0C = CTI_ARGS_code (see assertion above)
68     "addl $0x20, %esp" "\n"
69     "popl %ebx" "\n"
70     "popl %edi" "\n"
71     "popl %esi" "\n"
72     "ret" "\n"
73 );
74
75 asm(
76 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
77 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
78     "call " SYMBOL_STRING(_ZN3JSC11Interpreter12cti_vm_throwEPvz) "\n"
79     "addl $0x20, %esp" "\n"
80     "popl %ebx" "\n"
81     "popl %edi" "\n"
82     "popl %esi" "\n"
83     "ret" "\n"
84 );
85     
86 #elif COMPILER(MSVC)
87
88 extern "C" {
89     
90     __declspec(naked) JSValue* ctiTrampoline(void* code, RegisterFile*, CallFrame*, JSValue** exception, Profiler**, JSGlobalData*)
91     {
92         __asm {
93             push esi;
94             push edi;
95             push ebx;
96             sub esp, 0x20;
97             mov esi, 512;
98             mov ecx, esp;
99             mov edi, [esp + 0x38];
100             call [esp + 0x30]; // Ox30 = 0x0C * 4, 0x0C = CTI_ARGS_code (see assertion above)
101             add esp, 0x20;
102             pop ebx;
103             pop edi;
104             pop esi;
105             ret;
106         }
107     }
108     
109     __declspec(naked) void ctiVMThrowTrampoline()
110     {
111         __asm {
112             mov ecx, esp;
113             call JSC::Interpreter::cti_vm_throw;
114             add esp, 0x20;
115             pop ebx;
116             pop edi;
117             pop esi;
118             ret;
119         }
120     }
121     
122 }
123
124 #endif
125
126 void ctiSetReturnAddress(void** where, void* what)
127 {
128     *where = what;
129 }
130
131 void ctiRepatchCallByReturnAddress(void* where, void* what)
132 {
133     (static_cast<void**>(where))[-1] = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(what) - reinterpret_cast<uintptr_t>(where));
134 }
135
136 JIT::JIT(JSGlobalData* globalData, CodeBlock* codeBlock)
137     : m_interpreter(globalData->interpreter)
138     , m_globalData(globalData)
139     , m_codeBlock(codeBlock)
140     , m_labels(codeBlock ? codeBlock->instructions().size() : 0)
141     , m_propertyAccessCompilationInfo(codeBlock ? codeBlock->numberOfStructureStubInfos() : 0)
142     , m_callStructureStubCompilationInfo(codeBlock ? codeBlock->numberOfCallLinkInfos() : 0)
143     , m_lastResultBytecodeRegister(std::numeric_limits<int>::max())
144     , m_jumpTargetsPosition(0)
145 {
146 }
147
148 void JIT::compileOpStrictEq(Instruction* currentInstruction, CompileOpStrictEqType type)
149 {
150     bool negated = (type == OpNStrictEq);
151
152     unsigned dst = currentInstruction[1].u.operand;
153     unsigned src1 = currentInstruction[2].u.operand;
154     unsigned src2 = currentInstruction[3].u.operand;
155
156     emitGetVirtualRegisters(src1, X86::eax, src2, X86::edx);
157
158     // Check that bot are immediates, if so check if they're equal
159     Jump firstNotImmediate = emitJumpIfJSCell(X86::eax);
160     Jump secondNotImmediate = emitJumpIfJSCell(X86::edx);
161     Jump bothWereImmediatesButNotEqual = jne32(X86::edx, X86::eax);
162
163     // They are equal - set the result to true. (Or false, if negated).
164     move(Imm32(asInteger(jsBoolean(!negated))), X86::eax);
165     Jump bothWereImmediatesAndEqual = jump();
166
167     // eax was not an immediate, we haven't yet checked edx.
168     // If edx is also a JSCell, or is 0, then jump to a slow case,
169     // otherwise these values are not equal.
170     firstNotImmediate.link(this);
171     emitJumpSlowCaseIfJSCell(X86::edx);
172     addSlowCase(je32(X86::edx, Imm32(asInteger(JSImmediate::zeroImmediate()))));
173     Jump firstWasNotImmediate = jump();
174
175     // eax was an immediate, but edx wasn't.
176     // If eax is 0 jump to a slow case, otherwise these values are not equal.
177     secondNotImmediate.link(this);
178     addSlowCase(je32(X86::eax, Imm32(asInteger(JSImmediate::zeroImmediate()))));
179
180     // We get here if the two values are different immediates, or one is 0 and the other is a JSCell.
181     // Vaelues are not equal, set the result to false.
182     bothWereImmediatesButNotEqual.link(this);
183     firstWasNotImmediate.link(this);
184     move(Imm32(asInteger(jsBoolean(negated))), X86::eax);
185     
186     bothWereImmediatesAndEqual.link(this);
187     emitPutVirtualRegister(dst);
188 }
189
190 void JIT::emitSlowScriptCheck()
191 {
192     Jump skipTimeout = jnzSub32(Imm32(1), X86::esi);
193     emitCTICall(Interpreter::cti_timeout_check);
194     move(X86::eax, X86::esi);
195     skipTimeout.link(this);
196
197     killLastResultRegister();
198 }
199
200
201 #define NEXT_OPCODE(name) \
202     m_bytecodeIndex += OPCODE_LENGTH(name); \
203     break;
204
205 #define CTI_COMPILE_BINARY_OP(name) \
206     case name: { \
207         emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 1, X86::ecx); \
208         emitPutJITStubArgFromVirtualRegister(currentInstruction[3].u.operand, 2, X86::ecx); \
209         emitCTICall(Interpreter::cti_##name); \
210         emitPutVirtualRegister(currentInstruction[1].u.operand); \
211         NEXT_OPCODE(name); \
212     }
213
214 #define CTI_COMPILE_UNARY_OP(name) \
215     case name: { \
216         emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 1, X86::ecx); \
217         emitCTICall(Interpreter::cti_##name); \
218         emitPutVirtualRegister(currentInstruction[1].u.operand); \
219         NEXT_OPCODE(name); \
220     }
221
222 void JIT::privateCompileMainPass()
223 {
224     Instruction* instructionsBegin = m_codeBlock->instructions().begin();
225     unsigned instructionCount = m_codeBlock->instructions().size();
226     unsigned propertyAccessInstructionIndex = 0;
227     unsigned globalResolveInfoIndex = 0;
228     unsigned callLinkInfoIndex = 0;
229
230     for (m_bytecodeIndex = 0; m_bytecodeIndex < instructionCount; ) {
231         Instruction* currentInstruction = instructionsBegin + m_bytecodeIndex;
232         ASSERT_WITH_MESSAGE(m_interpreter->isOpcode(currentInstruction->u.opcode), "privateCompileMainPass gone bad @ %d", m_bytecodeIndex);
233
234 #if ENABLE(OPCODE_SAMPLING)
235         if (m_bytecodeIndex > 0) // Avoid the overhead of sampling op_enter twice.
236             store32(m_interpreter->sampler()->encodeSample(currentInstruction), m_interpreter->sampler()->sampleSlot());
237 #endif
238
239         m_labels[m_bytecodeIndex] = __ label();
240         OpcodeID opcodeID = m_interpreter->getOpcodeID(currentInstruction->u.opcode);
241
242         switch (opcodeID) {
243         case op_mov: {
244             emitGetVirtualRegister(currentInstruction[2].u.operand, X86::eax);
245             emitPutVirtualRegister(currentInstruction[1].u.operand);
246             NEXT_OPCODE(op_mov);
247         }
248         case op_add: {
249             unsigned dst = currentInstruction[1].u.operand;
250             unsigned src1 = currentInstruction[2].u.operand;
251             unsigned src2 = currentInstruction[3].u.operand;
252
253             if (JSValue* value = getConstantImmediateNumericArg(src1)) {
254                 emitGetVirtualRegister(src2, X86::eax);
255                 emitJumpSlowCaseIfNotImmNum(X86::eax);
256                 addSlowCase(joAdd32(Imm32(getDeTaggedConstantImmediate(value)), X86::eax));
257                 emitPutVirtualRegister(dst);
258             } else if (JSValue* value = getConstantImmediateNumericArg(src2)) {
259                 emitGetVirtualRegister(src1, X86::eax);
260                 emitJumpSlowCaseIfNotImmNum(X86::eax);
261                 addSlowCase(joAdd32(Imm32(getDeTaggedConstantImmediate(value)), X86::eax));
262                 emitPutVirtualRegister(dst);
263             } else {
264                 OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
265                 if (types.first().mightBeNumber() && types.second().mightBeNumber())
266                     compileBinaryArithOp(op_add, currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, OperandTypes::fromInt(currentInstruction[4].u.operand));
267                 else {
268                     emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 1, X86::ecx);
269                     emitPutJITStubArgFromVirtualRegister(currentInstruction[3].u.operand, 2, X86::ecx);
270                     emitCTICall(Interpreter::cti_op_add);
271                     emitPutVirtualRegister(currentInstruction[1].u.operand);
272                 }
273             }
274             NEXT_OPCODE(op_add);
275         }
276         case op_end: {
277             if (m_codeBlock->needsFullScopeChain())
278                 emitCTICall(Interpreter::cti_op_end);
279             emitGetVirtualRegister(currentInstruction[1].u.operand, X86::eax);
280             __ pushl_m(RegisterFile::ReturnPC * static_cast<int>(sizeof(Register)), X86::edi);
281             __ ret();
282             NEXT_OPCODE(op_end);
283         }
284         case op_jmp: {
285             unsigned target = currentInstruction[1].u.operand;
286             addJump(jump(), target + 1);
287             NEXT_OPCODE(op_jmp);
288         }
289         case op_pre_inc: {
290             int srcDst = currentInstruction[1].u.operand;
291             emitGetVirtualRegister(srcDst, X86::eax);
292             emitJumpSlowCaseIfNotImmNum(X86::eax);
293             addSlowCase(joAdd32(Imm32(getDeTaggedConstantImmediate(JSImmediate::oneImmediate())), X86::eax));
294             emitPutVirtualRegister(srcDst);
295             NEXT_OPCODE(op_pre_inc);
296         }
297         case op_loop: {
298             emitSlowScriptCheck();
299
300             unsigned target = currentInstruction[1].u.operand;
301             addJump(jump(), target + 1);
302             NEXT_OPCODE(op_end);
303         }
304         case op_loop_if_less: {
305             emitSlowScriptCheck();
306
307             unsigned target = currentInstruction[3].u.operand;
308             JSValue* src2imm = getConstantImmediateNumericArg(currentInstruction[2].u.operand);
309             if (src2imm) {
310                 emitGetVirtualRegister(currentInstruction[1].u.operand, X86::eax);
311                 emitJumpSlowCaseIfNotImmNum(X86::eax);
312                 addJump(jl32(X86::eax, Imm32(asInteger(src2imm))), target + 3);
313             } else {
314                 emitGetVirtualRegisters(currentInstruction[1].u.operand, X86::eax, currentInstruction[2].u.operand, X86::edx);
315                 emitJumpSlowCaseIfNotImmNum(X86::eax);
316                 emitJumpSlowCaseIfNotImmNum(X86::edx);
317                 addJump(jl32(X86::eax, X86::edx), target + 3);
318             }
319             NEXT_OPCODE(op_loop_if_less);
320         }
321         case op_loop_if_lesseq: {
322             emitSlowScriptCheck();
323
324             unsigned target = currentInstruction[3].u.operand;
325             JSValue* src2imm = getConstantImmediateNumericArg(currentInstruction[2].u.operand);
326             if (src2imm) {
327                 emitGetVirtualRegister(currentInstruction[1].u.operand, X86::eax);
328                 emitJumpSlowCaseIfNotImmNum(X86::eax);
329                 addJump(jle32(X86::eax, Imm32(asInteger(src2imm))), target + 3);
330             } else {
331                 emitGetVirtualRegisters(currentInstruction[1].u.operand, X86::eax, currentInstruction[2].u.operand, X86::edx);
332                 emitJumpSlowCaseIfNotImmNum(X86::eax);
333                 emitJumpSlowCaseIfNotImmNum(X86::edx);
334                 addJump(jle32(X86::eax, X86::edx), target + 3);
335             }
336             NEXT_OPCODE(op_loop_if_lesseq);
337         }
338         case op_new_object: {
339             emitCTICall(Interpreter::cti_op_new_object);
340             emitPutVirtualRegister(currentInstruction[1].u.operand);
341             NEXT_OPCODE(op_new_object);
342         }
343         case op_put_by_id: {
344             compilePutByIdHotPath(currentInstruction[1].u.operand, &(m_codeBlock->identifier(currentInstruction[2].u.operand)), currentInstruction[3].u.operand, propertyAccessInstructionIndex++);
345             NEXT_OPCODE(op_put_by_id);
346         }
347         case op_get_by_id: {
348             compileGetByIdHotPath(currentInstruction[1].u.operand, currentInstruction[2].u.operand, &(m_codeBlock->identifier(currentInstruction[3].u.operand)), propertyAccessInstructionIndex++);
349             NEXT_OPCODE(op_get_by_id);
350         }
351         case op_instanceof: {
352             emitGetVirtualRegister(currentInstruction[2].u.operand, X86::eax); // value
353             emitGetVirtualRegister(currentInstruction[3].u.operand, X86::ecx); // baseVal
354             emitGetVirtualRegister(currentInstruction[4].u.operand, X86::edx); // proto
355
356             // check if any are immediates
357             move(X86::eax, X86::ebx);
358             or32(X86::ecx, X86::ebx);
359             or32(X86::edx, X86::ebx);
360             emitJumpSlowCaseIfNotJSCell(X86::ebx);
361
362             // check that all are object type - this is a bit of a bithack to avoid excess branching;
363             // we check that the sum of the three type codes from Structures is exactly 3 * ObjectType,
364             // this works because NumberType and StringType are smaller
365             move(Imm32(3 * ObjectType), X86::ebx);
366             loadPtr(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), X86::eax);
367             loadPtr(Address(X86::ecx, FIELD_OFFSET(JSCell, m_structure)), X86::ecx);
368             loadPtr(Address(X86::edx, FIELD_OFFSET(JSCell, m_structure)), X86::edx);
369             sub32(Address(X86::eax, FIELD_OFFSET(Structure, m_typeInfo.m_type)), X86::ebx);
370             sub32(Address(X86::ecx, FIELD_OFFSET(Structure, m_typeInfo.m_type)), X86::ebx);
371             addSlowCase(jne32(Address(X86::edx, FIELD_OFFSET(Structure, m_typeInfo.m_type)), X86::ebx));
372
373             // check that baseVal's flags include ImplementsHasInstance but not OverridesHasInstance
374             load32(Address(X86::ecx, FIELD_OFFSET(Structure, m_typeInfo.m_flags)), X86::ecx);
375             and32(Imm32(ImplementsHasInstance | OverridesHasInstance), X86::ecx);
376             addSlowCase(jne32(X86::ecx, Imm32(ImplementsHasInstance)));
377
378             emitGetVirtualRegister(currentInstruction[2].u.operand, X86::ecx); // reload value
379             emitGetVirtualRegister(currentInstruction[4].u.operand, X86::edx); // reload proto
380
381             // optimistically load true result
382             move(Imm32(asInteger(jsBoolean(true))), X86::eax);
383
384             Label loop(this);
385
386             // load value's prototype
387             loadPtr(Address(X86::ecx, FIELD_OFFSET(JSCell, m_structure)), X86::ecx);
388             loadPtr(Address(X86::ecx, FIELD_OFFSET(Structure, m_prototype)), X86::ecx);
389
390             Jump exit = jePtr(X86::ecx, X86::edx);
391
392             jne32(X86::ecx, Imm32(asInteger(jsNull())), loop);
393
394             move(Imm32(asInteger(jsBoolean(false))), X86::eax);
395
396             exit.link(this);
397
398             emitPutVirtualRegister(currentInstruction[1].u.operand);
399
400             NEXT_OPCODE(op_instanceof);
401         }
402         case op_del_by_id: {
403             emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 1, X86::ecx);
404             Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
405             emitPutJITStubArgConstant(reinterpret_cast<unsigned>(ident), 2);
406             emitCTICall(Interpreter::cti_op_del_by_id);
407             emitPutVirtualRegister(currentInstruction[1].u.operand);
408             NEXT_OPCODE(op_del_by_id);
409         }
410         case op_mul: {
411             unsigned dst = currentInstruction[1].u.operand;
412             unsigned src1 = currentInstruction[2].u.operand;
413             unsigned src2 = currentInstruction[3].u.operand;
414
415             // For now, only plant a fast int case if the constant operand is greater than zero.
416             JSValue* src1Value = getConstantImmediateNumericArg(src1);
417             JSValue* src2Value = getConstantImmediateNumericArg(src2);
418             int32_t value;
419             if (src1Value && ((value = JSImmediate::intValue(src1Value)) > 0)) {
420                 emitGetVirtualRegister(src2, X86::eax);
421                 emitJumpSlowCaseIfNotImmNum(X86::eax);
422                 emitFastArithDeTagImmediate(X86::eax);
423                 addSlowCase(joMul32(Imm32(value), X86::eax, X86::eax));
424                 emitFastArithReTagImmediate(X86::eax);
425                 emitPutVirtualRegister(dst);
426             } else if (src2Value && ((value = JSImmediate::intValue(src2Value)) > 0)) {
427                 emitGetVirtualRegister(src1, X86::eax);
428                 emitJumpSlowCaseIfNotImmNum(X86::eax);
429                 emitFastArithDeTagImmediate(X86::eax);
430                 addSlowCase(joMul32(Imm32(value), X86::eax, X86::eax));
431                 emitFastArithReTagImmediate(X86::eax);
432                 emitPutVirtualRegister(dst);
433             } else
434                 compileBinaryArithOp(op_mul, currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, OperandTypes::fromInt(currentInstruction[4].u.operand));
435
436             NEXT_OPCODE(op_mul);
437         }
438         case op_new_func: {
439             FuncDeclNode* func = m_codeBlock->function(currentInstruction[2].u.operand);
440             emitPutJITStubArgConstant(reinterpret_cast<unsigned>(func), 1);
441             emitCTICall(Interpreter::cti_op_new_func);
442             emitPutVirtualRegister(currentInstruction[1].u.operand);
443             NEXT_OPCODE(op_new_func);
444         }
445         case op_call: {
446             compileOpCall(opcodeID, currentInstruction, callLinkInfoIndex++);
447             NEXT_OPCODE(op_call);
448         }
449         case op_call_eval: {
450             compileOpCall(opcodeID, currentInstruction, callLinkInfoIndex++);
451             NEXT_OPCODE(op_call_eval);
452         }
453         case op_construct: {
454             compileOpCall(opcodeID, currentInstruction, callLinkInfoIndex++);
455             NEXT_OPCODE(op_construct);
456         }
457         case op_get_global_var: {
458             JSVariableObject* globalObject = static_cast<JSVariableObject*>(currentInstruction[2].u.jsCell);
459             move(ImmPtr(globalObject), X86::eax);
460             emitGetVariableObjectRegister(X86::eax, currentInstruction[3].u.operand, X86::eax);
461             emitPutVirtualRegister(currentInstruction[1].u.operand);
462             NEXT_OPCODE(op_get_global_var);
463         }
464         case op_put_global_var: {
465             emitGetVirtualRegister(currentInstruction[3].u.operand, X86::edx);
466             JSVariableObject* globalObject = static_cast<JSVariableObject*>(currentInstruction[1].u.jsCell);
467             move(ImmPtr(globalObject), X86::eax);
468             emitPutVariableObjectRegister(X86::edx, X86::eax, currentInstruction[2].u.operand);
469             NEXT_OPCODE(op_put_global_var);
470         }
471         case op_get_scoped_var: {
472             int skip = currentInstruction[3].u.operand + m_codeBlock->needsFullScopeChain();
473
474             emitGetFromCallFrameHeader(RegisterFile::ScopeChain, X86::eax);
475             while (skip--)
476                 loadPtr(Address(X86::eax, FIELD_OFFSET(ScopeChainNode, next)), X86::eax);
477
478             loadPtr(Address(X86::eax, FIELD_OFFSET(ScopeChainNode, object)), X86::eax);
479             emitGetVariableObjectRegister(X86::eax, currentInstruction[2].u.operand, X86::eax);
480             emitPutVirtualRegister(currentInstruction[1].u.operand);
481             NEXT_OPCODE(op_get_scoped_var);
482         }
483         case op_put_scoped_var: {
484             int skip = currentInstruction[2].u.operand + m_codeBlock->needsFullScopeChain();
485
486             emitGetFromCallFrameHeader(RegisterFile::ScopeChain, X86::edx);
487             emitGetVirtualRegister(currentInstruction[3].u.operand, X86::eax);
488             while (skip--)
489                 loadPtr(Address(X86::edx, FIELD_OFFSET(ScopeChainNode, next)), X86::edx);
490
491             loadPtr(Address(X86::edx, FIELD_OFFSET(ScopeChainNode, object)), X86::edx);
492             emitPutVariableObjectRegister(X86::eax, X86::edx, currentInstruction[1].u.operand);
493             NEXT_OPCODE(op_put_scoped_var);
494         }
495         case op_tear_off_activation: {
496             emitPutJITStubArgFromVirtualRegister(currentInstruction[1].u.operand, 1, X86::ecx);
497             emitCTICall(Interpreter::cti_op_tear_off_activation);
498             NEXT_OPCODE(op_tear_off_activation);
499         }
500         case op_tear_off_arguments: {
501             emitCTICall(Interpreter::cti_op_tear_off_arguments);
502             NEXT_OPCODE(op_tear_off_arguments);
503         }
504         case op_ret: {
505             // We could JIT generate the deref, only calling out to C when the refcount hits zero.
506             if (m_codeBlock->needsFullScopeChain())
507                 emitCTICall(Interpreter::cti_op_ret_scopeChain);
508
509             // Return the result in %eax.
510             emitGetVirtualRegister(currentInstruction[1].u.operand, X86::eax);
511
512             // Grab the return address.
513             emitGetFromCallFrameHeader(RegisterFile::ReturnPC, X86::edx);
514
515             // Restore our caller's "r".
516             emitGetFromCallFrameHeader(RegisterFile::CallerFrame, X86::edi);
517
518             // Return.
519             __ pushl_r(X86::edx);
520             __ ret();
521
522             NEXT_OPCODE(op_ret);
523         }
524         case op_new_array: {
525             emitPutJITStubArgConstant(currentInstruction[2].u.operand, 1);
526             emitPutJITStubArgConstant(currentInstruction[3].u.operand, 2);
527             emitCTICall(Interpreter::cti_op_new_array);
528             emitPutVirtualRegister(currentInstruction[1].u.operand);
529             NEXT_OPCODE(op_new_array);
530         }
531         case op_resolve: {
532             Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand));
533             emitPutJITStubArgConstant(reinterpret_cast<unsigned>(ident), 1);
534             emitCTICall(Interpreter::cti_op_resolve);
535             emitPutVirtualRegister(currentInstruction[1].u.operand);
536             NEXT_OPCODE(op_resolve);
537         }
538         case op_construct_verify: {
539             emitGetVirtualRegister(currentInstruction[1].u.operand, X86::eax);
540
541             emitJumpSlowCaseIfNotJSCell(X86::eax);
542             loadPtr(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), X86::ecx);
543             addSlowCase(jne32(Address(X86::ecx, FIELD_OFFSET(Structure, m_typeInfo) + FIELD_OFFSET(TypeInfo, m_type)), Imm32(ObjectType)));
544
545             NEXT_OPCODE(op_construct_verify);
546         }
547         case op_get_by_val: {
548             emitGetVirtualRegisters(currentInstruction[2].u.operand, X86::eax, currentInstruction[3].u.operand, X86::edx);
549             emitJumpSlowCaseIfNotImmNum(X86::edx);
550             emitFastArithImmToInt(X86::edx);
551             emitJumpSlowCaseIfNotJSCell(X86::eax);
552             addSlowCase(jnePtr(Address(X86::eax), ImmPtr(m_interpreter->m_jsArrayVptr)));
553
554             // This is an array; get the m_storage pointer into ecx, then check if the index is below the fast cutoff
555             loadPtr(Address(X86::eax, FIELD_OFFSET(JSArray, m_storage)), X86::ecx);
556             addSlowCase(jae32(X86::edx, Address(X86::eax, FIELD_OFFSET(JSArray, m_fastAccessCutoff))));
557
558             // Get the value from the vector
559             loadPtr(BaseIndex(X86::ecx, X86::edx, ScalePtr, FIELD_OFFSET(ArrayStorage, m_vector[0])), X86::eax);
560             emitPutVirtualRegister(currentInstruction[1].u.operand);
561             NEXT_OPCODE(op_get_by_val);
562         }
563         case op_resolve_func: {
564             Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
565             emitPutJITStubArgConstant(reinterpret_cast<unsigned>(ident), 1);
566             emitCTICall(Interpreter::cti_op_resolve_func);
567             emitPutVirtualRegister(currentInstruction[2].u.operand, X86::edx);
568             emitPutVirtualRegister(currentInstruction[1].u.operand);
569             NEXT_OPCODE(op_resolve_func);
570         }
571         case op_sub: {
572             compileBinaryArithOp(op_sub, currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, OperandTypes::fromInt(currentInstruction[4].u.operand));
573             NEXT_OPCODE(op_sub);
574         }
575         case op_put_by_val: {
576             emitGetVirtualRegisters(currentInstruction[1].u.operand, X86::eax, currentInstruction[2].u.operand, X86::edx);
577             emitJumpSlowCaseIfNotImmNum(X86::edx);
578             emitFastArithImmToInt(X86::edx);
579             emitJumpSlowCaseIfNotJSCell(X86::eax);
580             addSlowCase(jnePtr(Address(X86::eax), ImmPtr(m_interpreter->m_jsArrayVptr)));
581
582             // This is an array; get the m_storage pointer into ecx, then check if the index is below the fast cutoff
583             loadPtr(Address(X86::eax, FIELD_OFFSET(JSArray, m_storage)), X86::ecx);
584             Jump inFastVector = jb32(X86::edx, Address(X86::eax, FIELD_OFFSET(JSArray, m_fastAccessCutoff)));
585             // No; oh well, check if the access if within the vector - if so, we may still be okay.
586             addSlowCase(jae32(X86::edx, Address(X86::ecx, FIELD_OFFSET(ArrayStorage, m_vectorLength))));
587
588             // This is a write to the slow part of the vector; first, we have to check if this would be the first write to this location.
589             // FIXME: should be able to handle initial write to array; increment the the number of items in the array, and potentially update fast access cutoff. 
590             addSlowCase(jzPtr(BaseIndex(X86::ecx, X86::edx, ScalePtr, FIELD_OFFSET(ArrayStorage, m_vector[0]))));
591
592             // All good - put the value into the array.
593             inFastVector.link(this);
594             emitGetVirtualRegister(currentInstruction[3].u.operand, X86::eax);
595             storePtr(X86::eax, BaseIndex(X86::ecx, X86::edx, ScalePtr, FIELD_OFFSET(ArrayStorage, m_vector[0])));
596             NEXT_OPCODE(op_put_by_val);
597         }
598         CTI_COMPILE_BINARY_OP(op_lesseq)
599         case op_loop_if_true: {
600             emitSlowScriptCheck();
601
602             unsigned target = currentInstruction[2].u.operand;
603             emitGetVirtualRegister(currentInstruction[1].u.operand, X86::eax);
604
605             Jump isZero = je32(X86::eax, Imm32(asInteger(JSImmediate::zeroImmediate())));
606             addJump(jnz32(X86::eax, Imm32(JSImmediate::TagBitTypeInteger)), target + 2);
607
608             addJump(je32(X86::eax, Imm32(asInteger(JSImmediate::trueImmediate()))), target + 2);
609             addSlowCase(jne32(X86::eax, Imm32(asInteger(JSImmediate::falseImmediate()))));
610
611             isZero.link(this);
612             NEXT_OPCODE(op_loop_if_true);
613         };
614         case op_resolve_base: {
615             Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand));
616             emitPutJITStubArgConstant(reinterpret_cast<unsigned>(ident), 1);
617             emitCTICall(Interpreter::cti_op_resolve_base);
618             emitPutVirtualRegister(currentInstruction[1].u.operand);
619             NEXT_OPCODE(op_resolve_base);
620         }
621         case op_negate: {
622             emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 1, X86::ecx);
623             emitCTICall(Interpreter::cti_op_negate);
624             emitPutVirtualRegister(currentInstruction[1].u.operand);
625             NEXT_OPCODE(op_negate);
626         }
627         case op_resolve_skip: {
628             Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand));
629             emitPutJITStubArgConstant(reinterpret_cast<unsigned>(ident), 1);
630             emitPutJITStubArgConstant(currentInstruction[3].u.operand + m_codeBlock->needsFullScopeChain(), 2);
631             emitCTICall(Interpreter::cti_op_resolve_skip);
632             emitPutVirtualRegister(currentInstruction[1].u.operand);
633             NEXT_OPCODE(op_resolve_skip);
634         }
635         case op_resolve_global: {
636             // Fast case
637             void* globalObject = currentInstruction[2].u.jsCell;
638             Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
639             
640             unsigned currentIndex = globalResolveInfoIndex++;
641             void* structureAddress = &(m_codeBlock->globalResolveInfo(currentIndex).structure);
642             void* offsetAddr = &(m_codeBlock->globalResolveInfo(currentIndex).offset);
643
644             // Check Structure of global object
645             move(ImmPtr(globalObject), X86::eax);
646             loadPtr(structureAddress, X86::edx);
647             Jump noMatch = jnePtr(X86::edx, Address(X86::eax, FIELD_OFFSET(JSCell, m_structure))); // Structures don't match
648
649             // Load cached property
650             loadPtr(Address(X86::eax, FIELD_OFFSET(JSGlobalObject, m_propertyStorage)), X86::eax);
651             load32(offsetAddr, X86::edx);
652             loadPtr(BaseIndex(X86::eax, X86::edx, ScalePtr), X86::eax);
653             emitPutVirtualRegister(currentInstruction[1].u.operand);
654             Jump end = jump();
655
656             // Slow case
657             noMatch.link(this);
658             emitPutJITStubArgConstant(globalObject, 1);
659             emitPutJITStubArgConstant(reinterpret_cast<unsigned>(ident), 2);
660             emitPutJITStubArgConstant(currentIndex, 3);
661             emitCTICall(Interpreter::cti_op_resolve_global);
662             emitPutVirtualRegister(currentInstruction[1].u.operand);
663             end.link(this);
664             NEXT_OPCODE(op_resolve_global);
665         }
666         CTI_COMPILE_BINARY_OP(op_div)
667         case op_pre_dec: {
668             int srcDst = currentInstruction[1].u.operand;
669             emitGetVirtualRegister(srcDst, X86::eax);
670             emitJumpSlowCaseIfNotImmNum(X86::eax);
671             addSlowCase(joSub32(Imm32(getDeTaggedConstantImmediate(JSImmediate::oneImmediate())), X86::eax));
672             emitPutVirtualRegister(srcDst);
673             NEXT_OPCODE(op_pre_dec);
674         }
675         case op_jnless: {
676             unsigned target = currentInstruction[3].u.operand;
677             JSValue* src2imm = getConstantImmediateNumericArg(currentInstruction[2].u.operand);
678             if (src2imm) {
679                 emitGetVirtualRegister(currentInstruction[1].u.operand, X86::edx);
680                 emitJumpSlowCaseIfNotImmNum(X86::edx);
681                 addJump(jge32(X86::edx, Imm32(asInteger(src2imm))), target + 3);
682             } else {
683                 emitGetVirtualRegisters(currentInstruction[1].u.operand, X86::eax, currentInstruction[2].u.operand, X86::edx);
684                 emitJumpSlowCaseIfNotImmNum(X86::eax);
685                 emitJumpSlowCaseIfNotImmNum(X86::edx);
686                 addJump(jge32(X86::eax, X86::edx), target + 3);
687             }
688             NEXT_OPCODE(op_jnless);
689         }
690         case op_not: {
691             emitGetVirtualRegister(currentInstruction[2].u.operand, X86::eax);
692             xor32(Imm32(JSImmediate::FullTagTypeBool), X86::eax);
693             addSlowCase(jnz32(X86::eax, Imm32(JSImmediate::FullTagTypeMask)));
694             xor32(Imm32(JSImmediate::FullTagTypeBool | JSImmediate::ExtendedPayloadBitBoolValue), X86::eax);
695             emitPutVirtualRegister(currentInstruction[1].u.operand);
696             NEXT_OPCODE(op_not);
697         }
698         case op_jfalse: {
699             unsigned target = currentInstruction[2].u.operand;
700             emitGetVirtualRegister(currentInstruction[1].u.operand, X86::eax);
701
702             addJump(je32(X86::eax, Imm32(asInteger(JSImmediate::zeroImmediate()))), target + 2);
703             Jump isNonZero = jnz32(X86::eax, Imm32(JSImmediate::TagBitTypeInteger));
704
705             addJump(je32(X86::eax, Imm32(asInteger(JSImmediate::falseImmediate()))), target + 2);
706             addSlowCase(jne32(X86::eax, Imm32(asInteger(JSImmediate::trueImmediate()))));
707
708             isNonZero.link(this);
709             NEXT_OPCODE(op_jfalse);
710         };
711         case op_jeq_null: {
712             unsigned src = currentInstruction[1].u.operand;
713             unsigned target = currentInstruction[2].u.operand;
714
715             emitGetVirtualRegister(src, X86::eax);
716             Jump isImmediate = emitJumpIfNotJSCell(X86::eax);
717
718             // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure.
719             loadPtr(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), X86::ecx);
720             addJump(jnz32(Address(X86::ecx, FIELD_OFFSET(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target + 2);
721             Jump wasNotImmediate = jump();
722
723             // Now handle the immediate cases - undefined & null
724             isImmediate.link(this);
725             and32(Imm32(~JSImmediate::ExtendedTagBitUndefined), X86::eax);
726             addJump(je32(X86::eax, Imm32(asInteger(jsNull()))), target + 2);            
727
728             wasNotImmediate.link(this);
729             NEXT_OPCODE(op_jeq_null);
730         };
731         case op_jneq_null: {
732             unsigned src = currentInstruction[1].u.operand;
733             unsigned target = currentInstruction[2].u.operand;
734
735             emitGetVirtualRegister(src, X86::eax);
736             Jump isImmediate = emitJumpIfNotJSCell(X86::eax);
737
738             // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure.
739             loadPtr(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), X86::ecx);
740             addJump(jz32(Address(X86::ecx, FIELD_OFFSET(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target + 2);
741             Jump wasNotImmediate = jump();
742
743             // Now handle the immediate cases - undefined & null
744             isImmediate.link(this);
745             and32(Imm32(~JSImmediate::ExtendedTagBitUndefined), X86::eax);
746             addJump(jne32(X86::eax, Imm32(asInteger(jsNull()))), target + 2);            
747
748             wasNotImmediate.link(this);
749             NEXT_OPCODE(op_jneq_null);
750         }
751         case op_post_inc: {
752             int srcDst = currentInstruction[2].u.operand;
753             emitGetVirtualRegister(srcDst, X86::eax);
754             move(X86::eax, X86::edx);
755             emitJumpSlowCaseIfNotImmNum(X86::eax);
756             addSlowCase(joAdd32(Imm32(getDeTaggedConstantImmediate(JSImmediate::oneImmediate())), X86::edx));
757             emitPutVirtualRegister(srcDst, X86::edx);
758             emitPutVirtualRegister(currentInstruction[1].u.operand);
759             NEXT_OPCODE(op_post_inc);
760         }
761         case op_unexpected_load: {
762             JSValue* v = m_codeBlock->unexpectedConstant(currentInstruction[2].u.operand);
763             move(ImmPtr(v), X86::eax);
764             emitPutVirtualRegister(currentInstruction[1].u.operand);
765             NEXT_OPCODE(op_unexpected_load);
766         }
767         case op_jsr: {
768             int retAddrDst = currentInstruction[1].u.operand;
769             int target = currentInstruction[2].u.operand;
770             __ movl_i32m(0, sizeof(Register) * retAddrDst, X86::edi);
771             JmpDst addrPosition = __ label();
772             addJump(__ jmp(), target + 2);
773             JmpDst sretTarget = __ label();
774             m_jsrSites.append(JSRInfo(addrPosition, sretTarget));
775             NEXT_OPCODE(op_jsr);
776         }
777         case op_sret: {
778             __ jmp_m(sizeof(Register) * currentInstruction[1].u.operand, X86::edi);
779             NEXT_OPCODE(op_sret);
780         }
781         case op_eq: {
782             emitGetVirtualRegisters(currentInstruction[2].u.operand, X86::eax, currentInstruction[3].u.operand, X86::edx);
783             emitJumpSlowCaseIfNotImmNums(X86::eax, X86::edx, X86::ecx);
784             sete32(X86::edx, X86::eax);
785             emitTagAsBoolImmediate(X86::eax);
786             emitPutVirtualRegister(currentInstruction[1].u.operand);
787             NEXT_OPCODE(op_eq);
788         }
789         case op_lshift: {
790             emitGetVirtualRegisters(currentInstruction[2].u.operand, X86::eax, currentInstruction[3].u.operand, X86::ecx);
791             emitJumpSlowCaseIfNotImmNum(X86::eax);
792             emitJumpSlowCaseIfNotImmNum(X86::ecx);
793             emitFastArithImmToInt(X86::eax);
794             emitFastArithImmToInt(X86::ecx);
795             __ shll_CLr(X86::eax);
796             emitFastArithIntToImmOrSlowCase(X86::eax);
797             emitPutVirtualRegister(currentInstruction[1].u.operand);
798             NEXT_OPCODE(op_lshift);
799         }
800         case op_bitand: {
801             unsigned src1 = currentInstruction[2].u.operand;
802             unsigned src2 = currentInstruction[3].u.operand;
803             unsigned dst = currentInstruction[1].u.operand;
804             if (JSValue* value = getConstantImmediateNumericArg(src1)) {
805                 emitGetVirtualRegister(src2, X86::eax);
806                 emitJumpSlowCaseIfNotImmNum(X86::eax);
807                 and32(Imm32(asInteger(value)), X86::eax); // FIXME: make it more obvious this is relying on the format of JSImmediate
808                 emitPutVirtualRegister(dst);
809             } else if (JSValue* value = getConstantImmediateNumericArg(src2)) {
810                 emitGetVirtualRegister(src1, X86::eax);
811                 emitJumpSlowCaseIfNotImmNum(X86::eax);
812                 and32(Imm32(asInteger(value)), X86::eax);
813                 emitPutVirtualRegister(dst);
814             } else {
815                 emitGetVirtualRegisters(src1, X86::eax, src2, X86::edx);
816                 and32(X86::edx, X86::eax);
817                 emitJumpSlowCaseIfNotImmNum(X86::eax);
818                 emitPutVirtualRegister(dst);
819             }
820             NEXT_OPCODE(op_bitand);
821         }
822         case op_rshift: {
823             unsigned src1 = currentInstruction[2].u.operand;
824             unsigned src2 = currentInstruction[3].u.operand;
825             if (JSValue* value = getConstantImmediateNumericArg(src2)) {
826                 emitGetVirtualRegister(src1, X86::eax);
827                 emitJumpSlowCaseIfNotImmNum(X86::eax);
828                 // Mask with 0x1f as per ecma-262 11.7.2 step 7.
829                 rshift32(Imm32(JSImmediate::getTruncatedUInt32(value) & 0x1f), X86::eax);
830             } else {
831                 emitGetVirtualRegisters(src1, X86::eax, src2, X86::ecx);
832                 emitJumpSlowCaseIfNotImmNum(X86::eax);
833                 emitJumpSlowCaseIfNotImmNum(X86::ecx);
834                 emitFastArithImmToInt(X86::ecx);
835                 __ sarl_CLr(X86::eax);
836             }
837             emitFastArithPotentiallyReTagImmediate(X86::eax);
838             emitPutVirtualRegister(currentInstruction[1].u.operand);
839             NEXT_OPCODE(op_rshift);
840         }
841         case op_bitnot: {
842             emitGetVirtualRegister(currentInstruction[2].u.operand, X86::eax);
843             emitJumpSlowCaseIfNotImmNum(X86::eax);
844             xor32(Imm32(~JSImmediate::TagBitTypeInteger), X86::eax);
845             emitPutVirtualRegister(currentInstruction[1].u.operand);
846             NEXT_OPCODE(op_bitnot);
847         }
848         case op_resolve_with_base: {
849             Identifier* ident = &(m_codeBlock->identifier(currentInstruction[3].u.operand));
850             emitPutJITStubArgConstant(reinterpret_cast<unsigned>(ident), 1);
851             emitCTICall(Interpreter::cti_op_resolve_with_base);
852             emitPutVirtualRegister(currentInstruction[2].u.operand, X86::edx);
853             emitPutVirtualRegister(currentInstruction[1].u.operand);
854             NEXT_OPCODE(op_resolve_with_base);
855         }
856         case op_new_func_exp: {
857             FuncExprNode* func = m_codeBlock->functionExpression(currentInstruction[2].u.operand);
858             emitPutJITStubArgConstant(reinterpret_cast<unsigned>(func), 1);
859             emitCTICall(Interpreter::cti_op_new_func_exp);
860             emitPutVirtualRegister(currentInstruction[1].u.operand);
861             NEXT_OPCODE(op_new_func_exp);
862         }
863         case op_mod: {
864             emitGetVirtualRegisters(currentInstruction[2].u.operand, X86::eax, currentInstruction[3].u.operand, X86::ecx);
865             emitJumpSlowCaseIfNotImmNum(X86::eax);
866             emitJumpSlowCaseIfNotImmNum(X86::ecx);
867             emitFastArithDeTagImmediate(X86::eax);
868             addSlowCase(emitFastArithDeTagImmediateJumpIfZero(X86::ecx));
869             __ cdq();
870             __ idivl_r(X86::ecx);
871             emitFastArithReTagImmediate(X86::edx);
872             move(X86::edx, X86::eax);
873             emitPutVirtualRegister(currentInstruction[1].u.operand);
874             NEXT_OPCODE(op_mod);
875         }
876         case op_jtrue: {
877             unsigned target = currentInstruction[2].u.operand;
878             emitGetVirtualRegister(currentInstruction[1].u.operand, X86::eax);
879
880             Jump isZero = je32(X86::eax, Imm32(asInteger(JSImmediate::zeroImmediate())));
881             addJump(jnz32(X86::eax, Imm32(JSImmediate::TagBitTypeInteger)), target + 2);
882
883             addJump(je32(X86::eax, Imm32(asInteger(JSImmediate::trueImmediate()))), target + 2);
884             addSlowCase(jne32(X86::eax, Imm32(asInteger(JSImmediate::falseImmediate()))));
885
886             isZero.link(this);
887             NEXT_OPCODE(op_jtrue);
888         }
889         CTI_COMPILE_BINARY_OP(op_less)
890         case op_neq: {
891             emitGetVirtualRegisters(currentInstruction[2].u.operand, X86::eax, currentInstruction[3].u.operand, X86::edx);
892             emitJumpSlowCaseIfNotImmNums(X86::eax, X86::edx, X86::ecx);
893             setne32(X86::edx, X86::eax);
894             emitTagAsBoolImmediate(X86::eax);
895
896             emitPutVirtualRegister(currentInstruction[1].u.operand);
897
898             NEXT_OPCODE(op_neq);
899         }
900         case op_post_dec: {
901             int srcDst = currentInstruction[2].u.operand;
902             emitGetVirtualRegister(srcDst, X86::eax);
903             move(X86::eax, X86::edx);
904             emitJumpSlowCaseIfNotImmNum(X86::eax);
905             addSlowCase(joSub32(Imm32(getDeTaggedConstantImmediate(JSImmediate::oneImmediate())), X86::edx));
906             emitPutVirtualRegister(srcDst, X86::edx);
907             emitPutVirtualRegister(currentInstruction[1].u.operand);
908             NEXT_OPCODE(op_post_dec);
909         }
910         CTI_COMPILE_BINARY_OP(op_urshift)
911         case op_bitxor: {
912             emitGetVirtualRegisters(currentInstruction[2].u.operand, X86::eax, currentInstruction[3].u.operand, X86::edx);
913             emitJumpSlowCaseIfNotImmNums(X86::eax, X86::edx, X86::ecx);
914             xor32(X86::edx, X86::eax);
915             emitFastArithReTagImmediate(X86::eax);
916             emitPutVirtualRegister(currentInstruction[1].u.operand);
917             NEXT_OPCODE(op_bitxor);
918         }
919         case op_new_regexp: {
920             RegExp* regExp = m_codeBlock->regexp(currentInstruction[2].u.operand);
921             emitPutJITStubArgConstant(reinterpret_cast<unsigned>(regExp), 1);
922             emitCTICall(Interpreter::cti_op_new_regexp);
923             emitPutVirtualRegister(currentInstruction[1].u.operand);
924             NEXT_OPCODE(op_new_regexp);
925         }
926         case op_bitor: {
927             emitGetVirtualRegisters(currentInstruction[2].u.operand, X86::eax, currentInstruction[3].u.operand, X86::edx);
928             emitJumpSlowCaseIfNotImmNums(X86::eax, X86::edx, X86::ecx);
929             or32(X86::edx, X86::eax);
930             emitPutVirtualRegister(currentInstruction[1].u.operand);
931             NEXT_OPCODE(op_bitor);
932         }
933         case op_throw: {
934             emitPutJITStubArgFromVirtualRegister(currentInstruction[1].u.operand, 1, X86::ecx);
935             emitCTICall(Interpreter::cti_op_throw);
936             __ addl_i8r(0x20, X86::esp);
937             __ popl_r(X86::ebx);
938             __ popl_r(X86::edi);
939             __ popl_r(X86::esi);
940             __ ret();
941             NEXT_OPCODE(op_throw);
942         }
943         case op_get_pnames: {
944             emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 1, X86::ecx);
945             emitCTICall(Interpreter::cti_op_get_pnames);
946             emitPutVirtualRegister(currentInstruction[1].u.operand);
947             NEXT_OPCODE(op_get_pnames);
948         }
949         case op_next_pname: {
950             emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 1, X86::ecx);
951             unsigned target = currentInstruction[3].u.operand;
952             emitCTICall(Interpreter::cti_op_next_pname);
953             Jump endOfIter = jzPtr(X86::eax);
954             emitPutVirtualRegister(currentInstruction[1].u.operand);
955             addJump(jump(), target + 3);
956             endOfIter.link(this);
957             NEXT_OPCODE(op_next_pname);
958         }
959         case op_push_scope: {
960             emitPutJITStubArgFromVirtualRegister(currentInstruction[1].u.operand, 1, X86::ecx);
961             emitCTICall(Interpreter::cti_op_push_scope);
962             NEXT_OPCODE(op_push_scope);
963         }
964         case op_pop_scope: {
965             emitCTICall(Interpreter::cti_op_pop_scope);
966             NEXT_OPCODE(op_pop_scope);
967         }
968         CTI_COMPILE_UNARY_OP(op_typeof)
969         CTI_COMPILE_UNARY_OP(op_is_undefined)
970         CTI_COMPILE_UNARY_OP(op_is_boolean)
971         CTI_COMPILE_UNARY_OP(op_is_number)
972         CTI_COMPILE_UNARY_OP(op_is_string)
973         CTI_COMPILE_UNARY_OP(op_is_object)
974         CTI_COMPILE_UNARY_OP(op_is_function)
975         case op_stricteq: {
976             compileOpStrictEq(currentInstruction, OpStrictEq);
977             NEXT_OPCODE(op_stricteq);
978         }
979         case op_nstricteq: {
980             compileOpStrictEq(currentInstruction, OpNStrictEq);
981             NEXT_OPCODE(op_nstricteq);
982         }
983         case op_to_jsnumber: {
984             int srcVReg = currentInstruction[2].u.operand;
985             emitGetVirtualRegister(srcVReg, X86::eax);
986             
987             Jump wasImmediate = jnz32(X86::eax, Imm32(JSImmediate::TagBitTypeInteger));
988
989             emitJumpSlowCaseIfNotJSCell(X86::eax, srcVReg);
990             loadPtr(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), X86::ecx);
991             addSlowCase(jne32(Address(X86::ecx, FIELD_OFFSET(Structure, m_typeInfo.m_type)), Imm32(NumberType)));
992             
993             wasImmediate.link(this);
994
995             emitPutVirtualRegister(currentInstruction[1].u.operand);
996             NEXT_OPCODE(op_to_jsnumber);
997         }
998         CTI_COMPILE_BINARY_OP(op_in)
999         case op_push_new_scope: {
1000             Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand));
1001             emitPutJITStubArgConstant(reinterpret_cast<unsigned>(ident), 1);
1002             emitPutJITStubArgFromVirtualRegister(currentInstruction[3].u.operand, 2, X86::ecx);
1003             emitCTICall(Interpreter::cti_op_push_new_scope);
1004             emitPutVirtualRegister(currentInstruction[1].u.operand);
1005             NEXT_OPCODE(op_push_new_scope);
1006         }
1007         case op_catch: {
1008             emitGetCTIParam(CTI_ARGS_callFrame, X86::edi); // edi := r
1009             emitPutVirtualRegister(currentInstruction[1].u.operand);
1010             NEXT_OPCODE(op_catch);
1011         }
1012         case op_jmp_scopes: {
1013             unsigned count = currentInstruction[1].u.operand;
1014             emitPutJITStubArgConstant(count, 1);
1015             emitCTICall(Interpreter::cti_op_jmp_scopes);
1016             unsigned target = currentInstruction[2].u.operand;
1017             addJump(jump(), target + 2);
1018             NEXT_OPCODE(op_jmp_scopes);
1019         }
1020         case op_put_by_index: {
1021             emitPutJITStubArgFromVirtualRegister(currentInstruction[1].u.operand, 1, X86::ecx);
1022             emitPutJITStubArgConstant(currentInstruction[2].u.operand, 2);
1023             emitPutJITStubArgFromVirtualRegister(currentInstruction[3].u.operand, 3, X86::ecx);
1024             emitCTICall(Interpreter::cti_op_put_by_index);
1025             NEXT_OPCODE(op_put_by_index);
1026         }
1027         case op_switch_imm: {
1028             unsigned tableIndex = currentInstruction[1].u.operand;
1029             unsigned defaultOffset = currentInstruction[2].u.operand;
1030             unsigned scrutinee = currentInstruction[3].u.operand;
1031
1032             // create jump table for switch destinations, track this switch statement.
1033             SimpleJumpTable* jumpTable = &m_codeBlock->immediateSwitchJumpTable(tableIndex);
1034             m_switches.append(SwitchRecord(jumpTable, m_bytecodeIndex, defaultOffset, SwitchRecord::Immediate));
1035             jumpTable->ctiOffsets.grow(jumpTable->branchOffsets.size());
1036
1037             emitPutJITStubArgFromVirtualRegister(scrutinee, 1, X86::ecx);
1038             emitPutJITStubArgConstant(tableIndex, 2);
1039             emitCTICall(Interpreter::cti_op_switch_imm);
1040             jump(X86::eax);
1041             NEXT_OPCODE(op_switch_imm);
1042         }
1043         case op_switch_char: {
1044             unsigned tableIndex = currentInstruction[1].u.operand;
1045             unsigned defaultOffset = currentInstruction[2].u.operand;
1046             unsigned scrutinee = currentInstruction[3].u.operand;
1047
1048             // create jump table for switch destinations, track this switch statement.
1049             SimpleJumpTable* jumpTable = &m_codeBlock->characterSwitchJumpTable(tableIndex);
1050             m_switches.append(SwitchRecord(jumpTable, m_bytecodeIndex, defaultOffset, SwitchRecord::Character));
1051             jumpTable->ctiOffsets.grow(jumpTable->branchOffsets.size());
1052
1053             emitPutJITStubArgFromVirtualRegister(scrutinee, 1, X86::ecx);
1054             emitPutJITStubArgConstant(tableIndex, 2);
1055             emitCTICall(Interpreter::cti_op_switch_char);
1056             jump(X86::eax);
1057             NEXT_OPCODE(op_switch_char);
1058         }
1059         case op_switch_string: {
1060             unsigned tableIndex = currentInstruction[1].u.operand;
1061             unsigned defaultOffset = currentInstruction[2].u.operand;
1062             unsigned scrutinee = currentInstruction[3].u.operand;
1063
1064             // create jump table for switch destinations, track this switch statement.
1065             StringJumpTable* jumpTable = &m_codeBlock->stringSwitchJumpTable(tableIndex);
1066             m_switches.append(SwitchRecord(jumpTable, m_bytecodeIndex, defaultOffset));
1067
1068             emitPutJITStubArgFromVirtualRegister(scrutinee, 1, X86::ecx);
1069             emitPutJITStubArgConstant(tableIndex, 2);
1070             emitCTICall(Interpreter::cti_op_switch_string);
1071             jump(X86::eax);
1072             NEXT_OPCODE(op_switch_string);
1073         }
1074         case op_del_by_val: {
1075             emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 1, X86::ecx);
1076             emitPutJITStubArgFromVirtualRegister(currentInstruction[3].u.operand, 2, X86::ecx);
1077             emitCTICall(Interpreter::cti_op_del_by_val);
1078             emitPutVirtualRegister(currentInstruction[1].u.operand);
1079             NEXT_OPCODE(op_del_by_val);
1080         }
1081         case op_put_getter: {
1082             emitPutJITStubArgFromVirtualRegister(currentInstruction[1].u.operand, 1, X86::ecx);
1083             Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand));
1084             emitPutJITStubArgConstant(reinterpret_cast<unsigned>(ident), 2);
1085             emitPutJITStubArgFromVirtualRegister(currentInstruction[3].u.operand, 3, X86::ecx);
1086             emitCTICall(Interpreter::cti_op_put_getter);
1087             NEXT_OPCODE(op_put_getter);
1088         }
1089         case op_put_setter: {
1090             emitPutJITStubArgFromVirtualRegister(currentInstruction[1].u.operand, 1, X86::ecx);
1091             Identifier* ident = &(m_codeBlock->identifier(currentInstruction[2].u.operand));
1092             emitPutJITStubArgConstant(reinterpret_cast<unsigned>(ident), 2);
1093             emitPutJITStubArgFromVirtualRegister(currentInstruction[3].u.operand, 3, X86::ecx);
1094             emitCTICall(Interpreter::cti_op_put_setter);
1095             NEXT_OPCODE(op_put_setter);
1096         }
1097         case op_new_error: {
1098             JSValue* message = m_codeBlock->unexpectedConstant(currentInstruction[3].u.operand);
1099             emitPutJITStubArgConstant(currentInstruction[2].u.operand, 1);
1100             emitPutJITStubArgConstant(asInteger(message), 2);
1101             emitPutJITStubArgConstant(m_codeBlock->lineNumberForBytecodeOffset(m_bytecodeIndex), 3);
1102             emitCTICall(Interpreter::cti_op_new_error);
1103             emitPutVirtualRegister(currentInstruction[1].u.operand);
1104             NEXT_OPCODE(op_new_error);
1105         }
1106         case op_debug: {
1107             emitPutJITStubArgConstant(currentInstruction[1].u.operand, 1);
1108             emitPutJITStubArgConstant(currentInstruction[2].u.operand, 2);
1109             emitPutJITStubArgConstant(currentInstruction[3].u.operand, 3);
1110             emitCTICall(Interpreter::cti_op_debug);
1111             NEXT_OPCODE(op_debug);
1112         }
1113         case op_eq_null: {
1114             unsigned dst = currentInstruction[1].u.operand;
1115             unsigned src1 = currentInstruction[2].u.operand;
1116
1117             emitGetVirtualRegister(src1, X86::eax);
1118             Jump isImmediate = emitJumpIfNotJSCell(X86::eax);
1119
1120             loadPtr(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), X86::ecx);
1121             setnz32(Address(X86::ecx, FIELD_OFFSET(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined), X86::eax);
1122
1123             Jump wasNotImmediate = jump();
1124
1125             isImmediate.link(this);
1126
1127             and32(Imm32(~JSImmediate::ExtendedTagBitUndefined), X86::eax);
1128             sete32(Imm32(JSImmediate::FullTagTypeNull), X86::eax);
1129
1130             wasNotImmediate.link(this);
1131
1132             emitTagAsBoolImmediate(X86::eax);
1133             emitPutVirtualRegister(dst);
1134
1135             NEXT_OPCODE(op_eq_null);
1136         }
1137         case op_neq_null: {
1138             unsigned dst = currentInstruction[1].u.operand;
1139             unsigned src1 = currentInstruction[2].u.operand;
1140
1141             emitGetVirtualRegister(src1, X86::eax);
1142             Jump isImmediate = emitJumpIfNotJSCell(X86::eax);
1143
1144             loadPtr(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), X86::ecx);
1145             setz32(Address(X86::ecx, FIELD_OFFSET(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined), X86::eax);
1146
1147             Jump wasNotImmediate = jump();
1148
1149             isImmediate.link(this);
1150
1151             and32(Imm32(~JSImmediate::ExtendedTagBitUndefined), X86::eax);
1152             setne32(Imm32(JSImmediate::FullTagTypeNull), X86::eax);
1153
1154             wasNotImmediate.link(this);
1155
1156             emitTagAsBoolImmediate(X86::eax);
1157             emitPutVirtualRegister(dst);
1158
1159             NEXT_OPCODE(op_neq_null);
1160         }
1161         case op_enter: {
1162             // Even though CTI doesn't use them, we initialize our constant
1163             // registers to zap stale pointers, to avoid unnecessarily prolonging
1164             // object lifetime and increasing GC pressure.
1165             size_t count = m_codeBlock->m_numVars + m_codeBlock->numberOfConstantRegisters();
1166             for (size_t j = 0; j < count; ++j)
1167                 emitInitRegister(j);
1168
1169             NEXT_OPCODE(op_enter);
1170         }
1171         case op_enter_with_activation: {
1172             // Even though CTI doesn't use them, we initialize our constant
1173             // registers to zap stale pointers, to avoid unnecessarily prolonging
1174             // object lifetime and increasing GC pressure.
1175             size_t count = m_codeBlock->m_numVars + m_codeBlock->numberOfConstantRegisters();
1176             for (size_t j = 0; j < count; ++j)
1177                 emitInitRegister(j);
1178
1179             emitCTICall(Interpreter::cti_op_push_activation);
1180             emitPutVirtualRegister(currentInstruction[1].u.operand);
1181
1182             NEXT_OPCODE(op_enter_with_activation);
1183         }
1184         case op_create_arguments: {
1185             if (m_codeBlock->m_numParameters == 1)
1186                 emitCTICall(Interpreter::cti_op_create_arguments_no_params);
1187             else
1188                 emitCTICall(Interpreter::cti_op_create_arguments);
1189             NEXT_OPCODE(op_create_arguments);
1190         }
1191         case op_convert_this: {
1192             emitGetVirtualRegister(currentInstruction[1].u.operand, X86::eax);
1193
1194             emitJumpSlowCaseIfNotJSCell(X86::eax);
1195             loadPtr(Address(X86::eax, FIELD_OFFSET(JSCell, m_structure)), X86::edx);
1196             addSlowCase(jnz32(Address(X86::edx, FIELD_OFFSET(Structure, m_typeInfo.m_flags)), Imm32(NeedsThisConversion)));
1197
1198             NEXT_OPCODE(op_convert_this);
1199         }
1200         case op_profile_will_call: {
1201             emitGetCTIParam(CTI_ARGS_profilerReference, X86::eax);
1202             __ cmpl_i32m(0, X86::eax);
1203             JmpSrc noProfiler = __ je();
1204             emitPutJITStubArgFromVirtualRegister(currentInstruction[1].u.operand, 1, X86::eax);
1205             emitCTICall(Interpreter::cti_op_profile_will_call);
1206             __ link(noProfiler, __ label());
1207
1208             NEXT_OPCODE(op_profile_will_call);
1209         }
1210         case op_profile_did_call: {
1211             emitGetCTIParam(CTI_ARGS_profilerReference, X86::eax);
1212             __ cmpl_i32m(0, X86::eax);
1213             JmpSrc noProfiler = __ je();
1214             emitPutJITStubArgFromVirtualRegister(currentInstruction[1].u.operand, 1, X86::eax);
1215             emitCTICall(Interpreter::cti_op_profile_did_call);
1216             __ link(noProfiler, __ label());
1217
1218             NEXT_OPCODE(op_profile_did_call);
1219         }
1220         case op_get_array_length:
1221         case op_get_by_id_chain:
1222         case op_get_by_id_generic:
1223         case op_get_by_id_proto:
1224         case op_get_by_id_proto_list:
1225         case op_get_by_id_self:
1226         case op_get_by_id_self_list:
1227         case op_get_string_length:
1228         case op_put_by_id_generic:
1229         case op_put_by_id_replace:
1230         case op_put_by_id_transition:
1231             ASSERT_NOT_REACHED();
1232         }
1233     }
1234
1235     ASSERT(propertyAccessInstructionIndex == m_codeBlock->numberOfStructureStubInfos());
1236     ASSERT(callLinkInfoIndex == m_codeBlock->numberOfCallLinkInfos());
1237
1238 #ifndef NDEBUG
1239     // reset this, in order to guard it's use with asserts
1240     m_bytecodeIndex = (unsigned)-1;
1241 #endif
1242 }
1243
1244
1245 void JIT::privateCompileLinkPass()
1246 {
1247     unsigned jmpTableCount = m_jmpTable.size();
1248     for (unsigned i = 0; i < jmpTableCount; ++i)
1249         __ link(m_jmpTable[i].from, m_labels[m_jmpTable[i].to]);
1250     m_jmpTable.clear();
1251 }
1252
1253 void JIT::privateCompileSlowCases()
1254 {
1255     Instruction* instructionsBegin = m_codeBlock->instructions().begin();
1256     unsigned propertyAccessInstructionIndex = 0;
1257     unsigned callLinkInfoIndex = 0;
1258
1259     for (Vector<SlowCaseEntry>::iterator iter = m_slowCases.begin(); iter != m_slowCases.end();) {
1260         // FIXME: enable peephole optimizations for slow cases when applicable
1261         killLastResultRegister();
1262
1263         m_bytecodeIndex = iter->to;
1264 #ifndef NDEBUG
1265         unsigned firstTo = m_bytecodeIndex;
1266 #endif
1267         Instruction* currentInstruction = instructionsBegin + m_bytecodeIndex;
1268
1269         switch (OpcodeID opcodeID = m_interpreter->getOpcodeID(currentInstruction->u.opcode)) {
1270         case op_convert_this: {
1271             linkSlowCase(iter);
1272             linkSlowCase(iter);
1273             emitPutJITStubArg(X86::eax, 1);
1274             emitCTICall(Interpreter::cti_op_convert_this);
1275             emitPutVirtualRegister(currentInstruction[1].u.operand);
1276             NEXT_OPCODE(op_convert_this);
1277         }
1278         case op_add: {
1279             unsigned dst = currentInstruction[1].u.operand;
1280             unsigned src1 = currentInstruction[2].u.operand;
1281             unsigned src2 = currentInstruction[3].u.operand;
1282             if (JSValue* value = getConstantImmediateNumericArg(src1)) {
1283                 Jump notImm = getSlowCase(iter);
1284                 linkSlowCase(iter);
1285                 sub32(Imm32(getDeTaggedConstantImmediate(value)), X86::eax);
1286                 notImm.link(this);
1287                 emitPutJITStubArgFromVirtualRegister(src1, 1, X86::ecx);
1288                 emitPutJITStubArg(X86::eax, 2);
1289                 emitCTICall(Interpreter::cti_op_add);
1290                 emitPutVirtualRegister(dst);
1291             } else if (JSValue* value = getConstantImmediateNumericArg(src2)) {
1292                 Jump notImm = getSlowCase(iter);
1293                 linkSlowCase(iter);
1294                 sub32(Imm32(getDeTaggedConstantImmediate(value)), X86::eax);
1295                 notImm.link(this);
1296                 emitPutJITStubArg(X86::eax, 1);
1297                 emitPutJITStubArgFromVirtualRegister(src2, 2, X86::ecx);
1298                 emitCTICall(Interpreter::cti_op_add);
1299                 emitPutVirtualRegister(dst);
1300             } else {
1301                 OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
1302                 ASSERT(types.first().mightBeNumber() && types.second().mightBeNumber());
1303                 compileBinaryArithOpSlowCase(op_add, iter, dst, src1, src2, types);
1304             }
1305
1306             NEXT_OPCODE(op_add);
1307         }
1308         case op_construct_verify: {
1309             linkSlowCase(iter);
1310             linkSlowCase(iter);
1311             emitGetVirtualRegister(currentInstruction[2].u.operand, X86::eax);
1312             emitPutVirtualRegister(currentInstruction[1].u.operand);
1313
1314             NEXT_OPCODE(op_construct_verify);
1315         }
1316         case op_get_by_val: {
1317             // The slow case that handles accesses to arrays (below) may jump back up to here. 
1318             Label beginGetByValSlow(this);
1319
1320             Jump notImm = getSlowCase(iter);
1321             linkSlowCase(iter);
1322             linkSlowCase(iter);
1323             emitFastArithIntToImmNoCheck(X86::edx);
1324             notImm.link(this);
1325             emitPutJITStubArg(X86::eax, 1);
1326             emitPutJITStubArg(X86::edx, 2);
1327             emitCTICall(Interpreter::cti_op_get_by_val);
1328             emitPutVirtualRegister(currentInstruction[1].u.operand);
1329             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_get_by_val));
1330
1331             // This is slow case that handles accesses to arrays above the fast cut-off.
1332             // First, check if this is an access to the vector
1333             linkSlowCase(iter);
1334             jae32(X86::edx, Address(X86::ecx, FIELD_OFFSET(ArrayStorage, m_vectorLength)), beginGetByValSlow);
1335
1336             // okay, missed the fast region, but it is still in the vector.  Get the value.
1337             loadPtr(BaseIndex(X86::ecx, X86::edx, ScalePtr, FIELD_OFFSET(ArrayStorage, m_vector[0])), X86::ecx);
1338             // Check whether the value loaded is zero; if so we need to return undefined.
1339             jzPtr(X86::ecx, beginGetByValSlow);
1340             move(X86::ecx, X86::eax);
1341             emitPutVirtualRegister(currentInstruction[1].u.operand, X86::eax);
1342
1343             NEXT_OPCODE(op_get_by_val);
1344         }
1345         case op_sub: {
1346             compileBinaryArithOpSlowCase(op_sub, iter, currentInstruction[1].u.operand, currentInstruction[2].u.operand, currentInstruction[3].u.operand, OperandTypes::fromInt(currentInstruction[4].u.operand));
1347             NEXT_OPCODE(op_sub);
1348         }
1349         case op_rshift: {
1350             unsigned src2 = currentInstruction[3].u.operand;
1351             linkSlowCase(iter);
1352             if (getConstantImmediateNumericArg(src2))
1353                 emitPutJITStubArgFromVirtualRegister(src2, 2, X86::ecx);
1354             else {
1355                 linkSlowCase(iter);
1356                 emitPutJITStubArg(X86::ecx, 2);
1357             }
1358
1359             emitPutJITStubArg(X86::eax, 1);
1360             emitCTICall(Interpreter::cti_op_rshift);
1361             emitPutVirtualRegister(currentInstruction[1].u.operand);
1362             NEXT_OPCODE(op_rshift);
1363         }
1364         case op_lshift: {
1365             Jump notImm1 = getSlowCase(iter);
1366             Jump notImm2 = getSlowCase(iter);
1367             linkSlowCase(iter);
1368             emitGetVirtualRegisters(currentInstruction[2].u.operand, X86::eax, currentInstruction[3].u.operand, X86::ecx);
1369             notImm1.link(this);
1370             notImm2.link(this);
1371             emitPutJITStubArg(X86::eax, 1);
1372             emitPutJITStubArg(X86::ecx, 2);
1373             emitCTICall(Interpreter::cti_op_lshift);
1374             emitPutVirtualRegister(currentInstruction[1].u.operand);
1375             NEXT_OPCODE(op_lshift);
1376         }
1377         case op_loop_if_less: {
1378             unsigned target = currentInstruction[3].u.operand;
1379             JSValue* src2imm = getConstantImmediateNumericArg(currentInstruction[2].u.operand);
1380             if (src2imm) {
1381                 linkSlowCase(iter);
1382                 emitPutJITStubArg(X86::eax, 1);
1383                 emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 2, X86::ecx);
1384                 emitCTICall(Interpreter::cti_op_loop_if_less);
1385                 emitJumpSlowToHot(jnz32(X86::eax), target + 3);
1386             } else {
1387                 linkSlowCase(iter);
1388                 linkSlowCase(iter);
1389                 emitPutJITStubArg(X86::eax, 1);
1390                 emitPutJITStubArg(X86::edx, 2);
1391                 emitCTICall(Interpreter::cti_op_loop_if_less);
1392                 emitJumpSlowToHot(jnz32(X86::eax), target + 3);
1393             }
1394             NEXT_OPCODE(op_loop_if_less);
1395         }
1396         case op_put_by_id: {
1397             compilePutByIdSlowCase(currentInstruction[1].u.operand, &(m_codeBlock->identifier(currentInstruction[2].u.operand)), currentInstruction[3].u.operand, iter, propertyAccessInstructionIndex++);
1398             NEXT_OPCODE(op_put_by_id);
1399         }
1400         case op_get_by_id: {
1401             compileGetByIdSlowCase(currentInstruction[1].u.operand, currentInstruction[2].u.operand, &(m_codeBlock->identifier(currentInstruction[3].u.operand)), iter, propertyAccessInstructionIndex++);
1402             NEXT_OPCODE(op_get_by_id);
1403         }
1404         case op_loop_if_lesseq: {
1405             unsigned target = currentInstruction[3].u.operand;
1406             JSValue* src2imm = getConstantImmediateNumericArg(currentInstruction[2].u.operand);
1407             if (src2imm) {
1408                 linkSlowCase(iter);
1409                 emitPutJITStubArg(X86::eax, 1);
1410                 emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 2, X86::ecx);
1411                 emitCTICall(Interpreter::cti_op_loop_if_lesseq);
1412                 emitJumpSlowToHot(jnz32(X86::eax), target + 3);
1413             } else {
1414                 linkSlowCase(iter);
1415                 linkSlowCase(iter);
1416                 emitPutJITStubArg(X86::eax, 1);
1417                 emitPutJITStubArg(X86::edx, 2);
1418                 emitCTICall(Interpreter::cti_op_loop_if_lesseq);
1419                 emitJumpSlowToHot(jnz32(X86::eax), target + 3);
1420             }
1421             NEXT_OPCODE(op_loop_if_lesseq);
1422         }
1423         case op_pre_inc: {
1424             unsigned srcDst = currentInstruction[1].u.operand;
1425             Jump notImm = getSlowCase(iter);
1426             linkSlowCase(iter);
1427             sub32(Imm32(getDeTaggedConstantImmediate(JSImmediate::oneImmediate())), X86::eax);
1428             notImm.link(this);
1429             emitPutJITStubArg(X86::eax, 1);
1430             emitCTICall(Interpreter::cti_op_pre_inc);
1431             emitPutVirtualRegister(srcDst);
1432             NEXT_OPCODE(op_pre_inc);
1433         }
1434         case op_put_by_val: {
1435             // Normal slow cases - either is not an immediate imm, or is an array.
1436             Jump notImm = getSlowCase(iter);
1437             linkSlowCase(iter);
1438             linkSlowCase(iter);
1439             emitFastArithIntToImmNoCheck(X86::edx);
1440             notImm.link(this);
1441             emitGetVirtualRegister(currentInstruction[3].u.operand, X86::ecx);
1442             emitPutJITStubArg(X86::eax, 1);
1443             emitPutJITStubArg(X86::edx, 2);
1444             emitPutJITStubArg(X86::ecx, 3);
1445             emitCTICall(Interpreter::cti_op_put_by_val);
1446             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_put_by_val));
1447
1448             // slow cases for immediate int accesses to arrays
1449             linkSlowCase(iter);
1450             linkSlowCase(iter);
1451             emitGetVirtualRegister(currentInstruction[3].u.operand, X86::ecx);
1452             emitPutJITStubArg(X86::eax, 1);
1453             emitPutJITStubArg(X86::edx, 2);
1454             emitPutJITStubArg(X86::ecx, 3);
1455             emitCTICall(Interpreter::cti_op_put_by_val_array);
1456
1457             NEXT_OPCODE(op_put_by_val);
1458         }
1459         case op_loop_if_true: {
1460             linkSlowCase(iter);
1461             emitPutJITStubArg(X86::eax, 1);
1462             emitCTICall(Interpreter::cti_op_jtrue);
1463             unsigned target = currentInstruction[2].u.operand;
1464             emitJumpSlowToHot(jnz32(X86::eax), target + 2);
1465             NEXT_OPCODE(op_loop_if_true);
1466         }
1467         case op_pre_dec: {
1468             unsigned srcDst = currentInstruction[1].u.operand;
1469             Jump notImm = getSlowCase(iter);
1470             linkSlowCase(iter);
1471             add32(Imm32(getDeTaggedConstantImmediate(JSImmediate::oneImmediate())), X86::eax);
1472             notImm.link(this);
1473             emitPutJITStubArg(X86::eax, 1);
1474             emitCTICall(Interpreter::cti_op_pre_dec);
1475             emitPutVirtualRegister(srcDst);
1476             NEXT_OPCODE(op_pre_dec);
1477         }
1478         case op_jnless: {
1479             unsigned target = currentInstruction[3].u.operand;
1480             JSValue* src2imm = getConstantImmediateNumericArg(currentInstruction[2].u.operand);
1481             if (src2imm) {
1482                 linkSlowCase(iter);
1483                 emitPutJITStubArg(X86::edx, 1);
1484                 emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 2, X86::ecx);
1485                 emitCTICall(Interpreter::cti_op_jless);
1486                 emitJumpSlowToHot(jz32(X86::eax), target + 3);
1487             } else {
1488                 linkSlowCase(iter);
1489                 linkSlowCase(iter);
1490                 emitPutJITStubArg(X86::eax, 1);
1491                 emitPutJITStubArg(X86::edx, 2);
1492                 emitCTICall(Interpreter::cti_op_jless);
1493                 emitJumpSlowToHot(jz32(X86::eax), target + 3);
1494             }
1495             NEXT_OPCODE(op_jnless);
1496         }
1497         case op_not: {
1498             linkSlowCase(iter);
1499             xor32(Imm32(JSImmediate::FullTagTypeBool), X86::eax);
1500             emitPutJITStubArg(X86::eax, 1);
1501             emitCTICall(Interpreter::cti_op_not);
1502             emitPutVirtualRegister(currentInstruction[1].u.operand);
1503             NEXT_OPCODE(op_not);
1504         }
1505         case op_jfalse: {
1506             linkSlowCase(iter);
1507             emitPutJITStubArg(X86::eax, 1);
1508             emitCTICall(Interpreter::cti_op_jtrue);
1509             unsigned target = currentInstruction[2].u.operand;
1510             emitJumpSlowToHot(jz32(X86::eax), target + 2); // inverted!
1511             NEXT_OPCODE(op_jfalse);
1512         }
1513         case op_post_inc: {
1514             unsigned srcDst = currentInstruction[2].u.operand;
1515             linkSlowCase(iter);
1516             linkSlowCase(iter);
1517             emitPutJITStubArg(X86::eax, 1);
1518             emitCTICall(Interpreter::cti_op_post_inc);
1519             emitPutVirtualRegister(srcDst, X86::edx);
1520             emitPutVirtualRegister(currentInstruction[1].u.operand);
1521             NEXT_OPCODE(op_post_inc);
1522         }
1523         case op_bitnot: {
1524             linkSlowCase(iter);
1525             emitPutJITStubArg(X86::eax, 1);
1526             emitCTICall(Interpreter::cti_op_bitnot);
1527             emitPutVirtualRegister(currentInstruction[1].u.operand);
1528             NEXT_OPCODE(op_bitnot);
1529         }
1530         case op_bitand: {
1531             linkSlowCase(iter);
1532             unsigned src1 = currentInstruction[2].u.operand;
1533             unsigned src2 = currentInstruction[3].u.operand;
1534             unsigned dst = currentInstruction[1].u.operand;
1535             if (getConstantImmediateNumericArg(src1)) {
1536                 emitPutJITStubArgFromVirtualRegister(src1, 1, X86::ecx);
1537                 emitPutJITStubArg(X86::eax, 2);
1538                 emitCTICall(Interpreter::cti_op_bitand);
1539                 emitPutVirtualRegister(dst);
1540             } else if (getConstantImmediateNumericArg(src2)) {
1541                 emitPutJITStubArg(X86::eax, 1);
1542                 emitPutJITStubArgFromVirtualRegister(src2, 2, X86::ecx);
1543                 emitCTICall(Interpreter::cti_op_bitand);
1544                 emitPutVirtualRegister(dst);
1545             } else {
1546                 emitPutJITStubArgFromVirtualRegister(src1, 1, X86::ecx);
1547                 emitPutJITStubArg(X86::edx, 2);
1548                 emitCTICall(Interpreter::cti_op_bitand);
1549                 emitPutVirtualRegister(dst);
1550             }
1551             NEXT_OPCODE(op_bitand);
1552         }
1553         case op_jtrue: {
1554             linkSlowCase(iter);
1555             emitPutJITStubArg(X86::eax, 1);
1556             emitCTICall(Interpreter::cti_op_jtrue);
1557             unsigned target = currentInstruction[2].u.operand;
1558             emitJumpSlowToHot(jnz32(X86::eax), target + 2);
1559             NEXT_OPCODE(op_jtrue);
1560         }
1561         case op_post_dec: {
1562             unsigned srcDst = currentInstruction[2].u.operand;
1563             linkSlowCase(iter);
1564             linkSlowCase(iter);
1565             emitPutJITStubArg(X86::eax, 1);
1566             emitCTICall(Interpreter::cti_op_post_dec);
1567             emitPutVirtualRegister(srcDst, X86::edx);
1568             emitPutVirtualRegister(currentInstruction[1].u.operand);
1569             NEXT_OPCODE(op_post_dec);
1570         }
1571         case op_bitxor: {
1572             linkSlowCase(iter);
1573             emitPutJITStubArg(X86::eax, 1);
1574             emitPutJITStubArg(X86::edx, 2);
1575             emitCTICall(Interpreter::cti_op_bitxor);
1576             emitPutVirtualRegister(currentInstruction[1].u.operand);
1577             NEXT_OPCODE(op_bitxor);
1578         }
1579         case op_bitor: {
1580             linkSlowCase(iter);
1581             emitPutJITStubArg(X86::eax, 1);
1582             emitPutJITStubArg(X86::edx, 2);
1583             emitCTICall(Interpreter::cti_op_bitor);
1584             emitPutVirtualRegister(currentInstruction[1].u.operand);
1585             NEXT_OPCODE(op_bitor);
1586         }
1587         case op_eq: {
1588             linkSlowCase(iter);
1589             emitPutJITStubArg(X86::eax, 1);
1590             emitPutJITStubArg(X86::edx, 2);
1591             emitCTICall(Interpreter::cti_op_eq);
1592             emitPutVirtualRegister(currentInstruction[1].u.operand);
1593             NEXT_OPCODE(op_eq);
1594         }
1595         case op_neq: {
1596             linkSlowCase(iter);
1597             emitPutJITStubArg(X86::eax, 1);
1598             emitPutJITStubArg(X86::edx, 2);
1599             emitCTICall(Interpreter::cti_op_neq);
1600             emitPutVirtualRegister(currentInstruction[1].u.operand);
1601             NEXT_OPCODE(op_neq);
1602         }
1603         case op_stricteq: {
1604             linkSlowCase(iter);
1605             linkSlowCase(iter);
1606             linkSlowCase(iter);
1607             emitPutJITStubArg(X86::eax, 1);
1608             emitPutJITStubArg(X86::edx, 2);
1609             emitCTICall(Interpreter::cti_op_stricteq);
1610             emitPutVirtualRegister(currentInstruction[1].u.operand);
1611             NEXT_OPCODE(op_stricteq);
1612         }
1613         case op_nstricteq: {
1614             linkSlowCase(iter);
1615             linkSlowCase(iter);
1616             linkSlowCase(iter);
1617             emitPutJITStubArg(X86::eax, 1);
1618             emitPutJITStubArg(X86::edx, 2);
1619             emitCTICall(Interpreter::cti_op_nstricteq);
1620             emitPutVirtualRegister(currentInstruction[1].u.operand);
1621             NEXT_OPCODE(op_nstricteq);
1622         }
1623         case op_instanceof: {
1624             linkSlowCase(iter);
1625             linkSlowCase(iter);
1626             linkSlowCase(iter);
1627             emitPutJITStubArgFromVirtualRegister(currentInstruction[2].u.operand, 1, X86::ecx);
1628             emitPutJITStubArgFromVirtualRegister(currentInstruction[3].u.operand, 2, X86::ecx);
1629             emitPutJITStubArgFromVirtualRegister(currentInstruction[4].u.operand, 3, X86::ecx);
1630             emitCTICall(Interpreter::cti_op_instanceof);
1631             emitPutVirtualRegister(currentInstruction[1].u.operand);
1632             NEXT_OPCODE(op_instanceof);
1633         }
1634         case op_mod: {
1635             Jump notImm1 = getSlowCase(iter);
1636             Jump notImm2 = getSlowCase(iter);
1637             linkSlowCase(iter);
1638             emitFastArithReTagImmediate(X86::eax);
1639             emitFastArithReTagImmediate(X86::ecx);
1640             notImm1.link(this);
1641             notImm2.link(this);
1642             emitPutJITStubArg(X86::eax, 1);
1643             emitPutJITStubArg(X86::ecx, 2);
1644             emitCTICall(Interpreter::cti_op_mod);
1645             emitPutVirtualRegister(currentInstruction[1].u.operand);
1646             NEXT_OPCODE(op_mod);
1647         }
1648         case op_mul: {
1649             int dst = currentInstruction[1].u.operand;
1650             int src1 = currentInstruction[2].u.operand;
1651             int src2 = currentInstruction[3].u.operand;
1652             JSValue* src1Value = getConstantImmediateNumericArg(src1);
1653             JSValue* src2Value = getConstantImmediateNumericArg(src2);
1654             int32_t value;
1655             if (src1Value && ((value = JSImmediate::intValue(src1Value)) > 0)) {
1656                 linkSlowCase(iter);
1657                 linkSlowCase(iter);
1658                 // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0.
1659                 emitPutJITStubArgFromVirtualRegister(src1, 1, X86::ecx);
1660                 emitPutJITStubArgFromVirtualRegister(src2, 2, X86::ecx);
1661                 emitCTICall(Interpreter::cti_op_mul);
1662                 emitPutVirtualRegister(dst);
1663             } else if (src2Value && ((value = JSImmediate::intValue(src2Value)) > 0)) {
1664                 linkSlowCase(iter);
1665                 linkSlowCase(iter);
1666                 // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0.
1667                 emitPutJITStubArgFromVirtualRegister(src1, 1, X86::ecx);
1668                 emitPutJITStubArgFromVirtualRegister(src2, 2, X86::ecx);
1669                 emitCTICall(Interpreter::cti_op_mul);
1670                 emitPutVirtualRegister(dst);
1671             } else
1672                 compileBinaryArithOpSlowCase(op_mul, iter, dst, src1, src2, OperandTypes::fromInt(currentInstruction[4].u.operand));
1673             NEXT_OPCODE(op_mul);
1674         }
1675
1676         case op_call: {
1677             compileOpCallSlowCase(currentInstruction, iter, callLinkInfoIndex++, opcodeID);
1678             NEXT_OPCODE(op_call);
1679         }
1680         case op_call_eval: {
1681             compileOpCallSlowCase(currentInstruction, iter, callLinkInfoIndex++, opcodeID);
1682             NEXT_OPCODE(op_call_eval);
1683         }
1684         case op_construct: {
1685             compileOpCallSlowCase(currentInstruction, iter, callLinkInfoIndex++, opcodeID);
1686             NEXT_OPCODE(op_construct);
1687         }
1688         case op_to_jsnumber: {
1689             linkSlowCaseIfNotJSCell(iter, currentInstruction[2].u.operand);
1690             linkSlowCase(iter);
1691
1692             emitPutJITStubArg(X86::eax, 1);
1693             emitCTICall(Interpreter::cti_op_to_jsnumber);
1694
1695             emitPutVirtualRegister(currentInstruction[1].u.operand);
1696             NEXT_OPCODE(op_to_jsnumber);
1697         }
1698
1699         default:
1700             ASSERT_NOT_REACHED();
1701         }
1702
1703         ASSERT_WITH_MESSAGE(iter == m_slowCases.end() || firstTo != iter->to,"Not enough jumps linked in slow case codegen.");
1704         ASSERT_WITH_MESSAGE(firstTo == (iter - 1)->to, "Too many jumps linked in slow case codegen.");
1705
1706         emitJumpSlowToHot(jump(), 0);
1707     }
1708
1709 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
1710     ASSERT(propertyAccessInstructionIndex == m_codeBlock->numberOfStructureStubInfos());
1711 #endif
1712     ASSERT(callLinkInfoIndex == m_codeBlock->numberOfCallLinkInfos());
1713
1714 #ifndef NDEBUG
1715     // reset this, in order to guard it's use with asserts
1716     m_bytecodeIndex = (unsigned)-1;
1717 #endif
1718 }
1719
1720 void JIT::privateCompile()
1721 {
1722 #if ENABLE(CODEBLOCK_SAMPLING)
1723         storePtr(ImmPtr(m_codeBlock), m_interpreter->sampler()->codeBlockSlot());
1724 #endif
1725 #if ENABLE(OPCODE_SAMPLING)
1726         store32(Imm32(m_interpreter->sampler()->encodeSample(m_codeBlock->instructions().begin())), m_interpreter->sampler()->sampleSlot());
1727 #endif
1728
1729     // Could use a popl_m, but would need to offset the following instruction if so.
1730     __ popl_r(X86::ecx);
1731     emitPutToCallFrameHeader(X86::ecx, RegisterFile::ReturnPC);
1732
1733     Jump slowRegisterFileCheck;
1734     Label afterRegisterFileCheck;
1735     if (m_codeBlock->codeType() == FunctionCode) {
1736         // In the case of a fast linked call, we do not set this up in the caller.
1737         emitPutImmediateToCallFrameHeader(m_codeBlock, RegisterFile::CodeBlock);
1738
1739         emitGetCTIParam(CTI_ARGS_registerFile, X86::eax);
1740         __ leal_mr(m_codeBlock->m_numCalleeRegisters * sizeof(Register), X86::edi, X86::edx);
1741         slowRegisterFileCheck = jg32(X86::edx, Address(X86::eax, FIELD_OFFSET(RegisterFile, m_end)));
1742         afterRegisterFileCheck = MacroAssembler::Label(this);
1743     }
1744
1745     privateCompileMainPass();
1746     privateCompileLinkPass();
1747     privateCompileSlowCases();
1748
1749     if (m_codeBlock->codeType() == FunctionCode) {
1750         slowRegisterFileCheck.link(this);
1751         m_bytecodeIndex = 0; // emitCTICall will add to the map, but doesn't actually need this...
1752         emitCTICall(Interpreter::cti_register_file_check);
1753 #ifndef NDEBUG
1754         // reset this, in order to guard it's use with asserts
1755         m_bytecodeIndex = (unsigned)-1;
1756 #endif
1757         jump(afterRegisterFileCheck);
1758     }
1759
1760     ASSERT(m_jmpTable.isEmpty());
1761
1762     RefPtr<ExecutablePool> allocator = m_globalData->poolForSize(__ size());
1763     m_codeBlock->setExecutablePool(allocator.get());
1764     void* code = __ executableCopy(allocator.get());
1765
1766     // Translate vPC offsets into addresses in JIT generated code, for switch tables.
1767     for (unsigned i = 0; i < m_switches.size(); ++i) {
1768         SwitchRecord record = m_switches[i];
1769         unsigned bytecodeIndex = record.bytecodeIndex;
1770
1771         if (record.type != SwitchRecord::String) {
1772             ASSERT(record.type == SwitchRecord::Immediate || record.type == SwitchRecord::Character); 
1773             ASSERT(record.jumpTable.simpleJumpTable->branchOffsets.size() == record.jumpTable.simpleJumpTable->ctiOffsets.size());
1774
1775             record.jumpTable.simpleJumpTable->ctiDefault = __ getRelocatedAddress(code, m_labels[bytecodeIndex + 3 + record.defaultOffset]);
1776
1777             for (unsigned j = 0; j < record.jumpTable.simpleJumpTable->branchOffsets.size(); ++j) {
1778                 unsigned offset = record.jumpTable.simpleJumpTable->branchOffsets[j];
1779                 record.jumpTable.simpleJumpTable->ctiOffsets[j] = offset ? __ getRelocatedAddress(code, m_labels[bytecodeIndex + 3 + offset]) : record.jumpTable.simpleJumpTable->ctiDefault;
1780             }
1781         } else {
1782             ASSERT(record.type == SwitchRecord::String);
1783
1784             record.jumpTable.stringJumpTable->ctiDefault = __ getRelocatedAddress(code, m_labels[bytecodeIndex + 3 + record.defaultOffset]);
1785
1786             StringJumpTable::StringOffsetTable::iterator end = record.jumpTable.stringJumpTable->offsetTable.end();            
1787             for (StringJumpTable::StringOffsetTable::iterator it = record.jumpTable.stringJumpTable->offsetTable.begin(); it != end; ++it) {
1788                 unsigned offset = it->second.branchOffset;
1789                 it->second.ctiOffset = offset ? __ getRelocatedAddress(code, m_labels[bytecodeIndex + 3 + offset]) : record.jumpTable.stringJumpTable->ctiDefault;
1790             }
1791         }
1792     }
1793
1794     for (size_t i = 0; i < m_codeBlock->numberOfExceptionHandlers(); ++i) {
1795         HandlerInfo& handler = m_codeBlock->exceptionHandler(i);
1796         handler.nativeCode = __ getRelocatedAddress(code, m_labels[handler.target]);
1797     }
1798
1799     m_codeBlock->pcVector().reserveCapacity(m_calls.size());
1800     for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
1801         if (iter->to)
1802             X86Assembler::link(code, iter->from, iter->to);
1803         m_codeBlock->pcVector().append(PC(__ getRelocatedAddress(code, iter->from), iter->bytecodeIndex));
1804     }
1805
1806     // Link absolute addresses for jsr
1807     for (Vector<JSRInfo>::iterator iter = m_jsrSites.begin(); iter != m_jsrSites.end(); ++iter)
1808         X86Assembler::linkAbsoluteAddress(code, iter->addrPosition, iter->target);
1809
1810     for (unsigned i = 0; i < m_codeBlock->numberOfStructureStubInfos(); ++i) {
1811         StructureStubInfo& info = m_codeBlock->structureStubInfo(i);
1812         info.callReturnLocation = X86Assembler::getRelocatedAddress(code, m_propertyAccessCompilationInfo[i].callReturnLocation);
1813         info.hotPathBegin = X86Assembler::getRelocatedAddress(code, m_propertyAccessCompilationInfo[i].hotPathBegin);
1814     }
1815     for (unsigned i = 0; i < m_codeBlock->numberOfCallLinkInfos(); ++i) {
1816         CallLinkInfo& info = m_codeBlock->callLinkInfo(i);
1817         info.callReturnLocation = X86Assembler::getRelocatedAddress(code, m_callStructureStubCompilationInfo[i].callReturnLocation);
1818         info.hotPathBegin = X86Assembler::getRelocatedAddress(code, m_callStructureStubCompilationInfo[i].hotPathBegin);
1819         info.hotPathOther = X86Assembler::getRelocatedAddress(code, m_callStructureStubCompilationInfo[i].hotPathOther);
1820         info.coldPathOther = X86Assembler::getRelocatedAddress(code, m_callStructureStubCompilationInfo[i].coldPathOther);
1821     }
1822
1823     m_codeBlock->setJITCode(code);
1824 }
1825
1826 void JIT::privateCompileCTIMachineTrampolines()
1827 {
1828     // (1) The first function provides fast property access for array length
1829     
1830     // Check eax is an array
1831     JmpSrc array_failureCases1 = emitJumpIfNotJSCell(X86::eax);
1832     __ cmpl_i32m(reinterpret_cast<unsigned>(m_interpreter->m_jsArrayVptr), X86::eax);
1833     JmpSrc array_failureCases2 = __ jne();
1834
1835     // Checks out okay! - get the length from the storage
1836     __ movl_mr(FIELD_OFFSET(JSArray, m_storage), X86::eax, X86::eax);
1837     __ movl_mr(FIELD_OFFSET(ArrayStorage, m_length), X86::eax, X86::eax);
1838
1839     __ cmpl_i32r(JSImmediate::maxImmediateInt, X86::eax);
1840     JmpSrc array_failureCases3 = __ ja();
1841
1842     __ addl_rr(X86::eax, X86::eax);
1843     __ addl_i8r(1, X86::eax);
1844     
1845     __ ret();
1846
1847     // (2) The second function provides fast property access for string length
1848     
1849     JmpDst stringLengthBegin = __ align(16);
1850
1851     // Check eax is a string
1852     JmpSrc string_failureCases1 = emitJumpIfNotJSCell(X86::eax);
1853     __ cmpl_i32m(reinterpret_cast<unsigned>(m_interpreter->m_jsStringVptr), X86::eax);
1854     JmpSrc string_failureCases2 = __ jne();
1855
1856     // Checks out okay! - get the length from the Ustring.
1857     __ movl_mr(FIELD_OFFSET(JSString, m_value) + FIELD_OFFSET(UString, m_rep), X86::eax, X86::eax);
1858     __ movl_mr(FIELD_OFFSET(UString::Rep, len), X86::eax, X86::eax);
1859
1860     __ cmpl_i32r(JSImmediate::maxImmediateInt, X86::eax);
1861     JmpSrc string_failureCases3 = __ ja();
1862
1863     __ addl_rr(X86::eax, X86::eax);
1864     __ addl_i8r(1, X86::eax);
1865     
1866     __ ret();
1867
1868     // (3) Trampolines for the slow cases of op_call / op_call_eval / op_construct.
1869     
1870     JmpDst virtualCallPreLinkBegin = __ align(16);
1871
1872     // Load the callee CodeBlock* into eax
1873     __ movl_mr(FIELD_OFFSET(JSFunction, m_body), X86::ecx, X86::eax);
1874     __ movl_mr(FIELD_OFFSET(FunctionBodyNode, m_code), X86::eax, X86::eax);
1875     __ testl_rr(X86::eax, X86::eax);
1876     JmpSrc hasCodeBlock1 = __ jne();
1877     __ popl_r(X86::ebx);
1878     emitPutCTIParam(X86::edi, CTI_ARGS_callFrame);
1879     JmpSrc callJSFunction1 = __ call();
1880     emitGetJITStubArg(1, X86::ecx);
1881     emitGetJITStubArg(3, X86::edx);
1882     __ pushl_r(X86::ebx);
1883     __ link(hasCodeBlock1, __ label());
1884
1885     // Check argCount matches callee arity.
1886     __ cmpl_rm(X86::edx, FIELD_OFFSET(CodeBlock, m_numParameters), X86::eax);
1887     JmpSrc arityCheckOkay1 = __ je();
1888     __ popl_r(X86::ebx);
1889     emitPutJITStubArg(X86::ebx, 2);
1890     emitPutJITStubArg(X86::eax, 4);
1891     emitPutCTIParam(X86::edi, CTI_ARGS_callFrame);
1892     JmpSrc callArityCheck1 = __ call();
1893     __ movl_rr(X86::edx, X86::edi);
1894     emitGetJITStubArg(1, X86::ecx);
1895     emitGetJITStubArg(3, X86::edx);
1896     __ pushl_r(X86::ebx);
1897     __ link(arityCheckOkay1, __ label());
1898
1899     compileOpCallInitializeCallFrame();
1900
1901     __ popl_r(X86::ebx);
1902     emitPutJITStubArg(X86::ebx, 2);
1903     emitPutCTIParam(X86::edi, CTI_ARGS_callFrame);
1904     JmpSrc callDontLazyLinkCall = __ call();
1905     __ pushl_r(X86::ebx);
1906
1907     __ jmp_r(X86::eax);
1908
1909     JmpDst virtualCallLinkBegin = __ align(16);
1910
1911     // Load the callee CodeBlock* into eax
1912     __ movl_mr(FIELD_OFFSET(JSFunction, m_body), X86::ecx, X86::eax);
1913     __ movl_mr(FIELD_OFFSET(FunctionBodyNode, m_code), X86::eax, X86::eax);
1914     __ testl_rr(X86::eax, X86::eax);
1915     JmpSrc hasCodeBlock2 = __ jne();
1916     __ popl_r(X86::ebx);
1917     emitPutCTIParam(X86::edi, CTI_ARGS_callFrame);
1918     JmpSrc callJSFunction2 = __ call();
1919     emitGetJITStubArg(1, X86::ecx);
1920     emitGetJITStubArg(3, X86::edx);
1921     __ pushl_r(X86::ebx);
1922     __ link(hasCodeBlock2, __ label());
1923
1924     // Check argCount matches callee arity.
1925     __ cmpl_rm(X86::edx, FIELD_OFFSET(CodeBlock, m_numParameters), X86::eax);
1926     JmpSrc arityCheckOkay2 = __ je();
1927     __ popl_r(X86::ebx);
1928     emitPutJITStubArg(X86::ebx, 2);
1929     emitPutJITStubArg(X86::eax, 4);
1930     emitPutCTIParam(X86::edi, CTI_ARGS_callFrame);
1931     JmpSrc callArityCheck2 = __ call();
1932     __ movl_rr(X86::edx, X86::edi);
1933     emitGetJITStubArg(1, X86::ecx);
1934     emitGetJITStubArg(3, X86::edx);
1935     __ pushl_r(X86::ebx);
1936     __ link(arityCheckOkay2, __ label());
1937
1938     compileOpCallInitializeCallFrame();
1939
1940     __ popl_r(X86::ebx);
1941     emitPutJITStubArg(X86::ebx, 2);
1942     emitPutCTIParam(X86::edi, CTI_ARGS_callFrame);
1943     JmpSrc callLazyLinkCall = __ call();
1944     __ pushl_r(X86::ebx);
1945
1946     __ jmp_r(X86::eax);
1947
1948     JmpDst virtualCallBegin = __ align(16);
1949
1950     // Load the callee CodeBlock* into eax
1951     __ movl_mr(FIELD_OFFSET(JSFunction, m_body), X86::ecx, X86::eax);
1952     __ movl_mr(FIELD_OFFSET(FunctionBodyNode, m_code), X86::eax, X86::eax);
1953     __ testl_rr(X86::eax, X86::eax);
1954     JmpSrc hasCodeBlock3 = __ jne();
1955     __ popl_r(X86::ebx);
1956     emitPutCTIParam(X86::edi, CTI_ARGS_callFrame);
1957     JmpSrc callJSFunction3 = __ call();
1958     emitGetJITStubArg(1, X86::ecx);
1959     emitGetJITStubArg(3, X86::edx);
1960     __ pushl_r(X86::ebx);
1961     __ link(hasCodeBlock3, __ label());
1962
1963     // Check argCount matches callee arity.
1964     __ cmpl_rm(X86::edx, FIELD_OFFSET(CodeBlock, m_numParameters), X86::eax);
1965     JmpSrc arityCheckOkay3 = __ je();
1966     __ popl_r(X86::ebx);
1967     emitPutJITStubArg(X86::ebx, 2);
1968     emitPutJITStubArg(X86::eax, 4);
1969     emitPutCTIParam(X86::edi, CTI_ARGS_callFrame);
1970     JmpSrc callArityCheck3 = __ call();
1971     __ movl_rr(X86::edx, X86::edi);
1972     emitGetJITStubArg(1, X86::ecx);
1973     emitGetJITStubArg(3, X86::edx);
1974     __ pushl_r(X86::ebx);
1975     __ link(arityCheckOkay3, __ label());
1976
1977     compileOpCallInitializeCallFrame();
1978
1979     // load ctiCode from the new codeBlock.
1980     __ movl_mr(FIELD_OFFSET(CodeBlock, m_jitCode), X86::eax, X86::eax);
1981
1982     __ jmp_r(X86::eax);
1983
1984     // All trampolines constructed! copy the code, link up calls, and set the pointers on the Machine object.
1985     m_interpreter->m_executablePool = m_globalData->poolForSize(__ size());
1986     void* code = __ executableCopy(m_interpreter->m_executablePool.get());
1987
1988     X86Assembler::link(code, array_failureCases1, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_array_fail));
1989     X86Assembler::link(code, array_failureCases2, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_array_fail));
1990     X86Assembler::link(code, array_failureCases3, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_array_fail));
1991     X86Assembler::link(code, string_failureCases1, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_string_fail));
1992     X86Assembler::link(code, string_failureCases2, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_string_fail));
1993     X86Assembler::link(code, string_failureCases3, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_string_fail));
1994     X86Assembler::link(code, callArityCheck1, reinterpret_cast<void*>(Interpreter::cti_op_call_arityCheck));
1995     X86Assembler::link(code, callArityCheck2, reinterpret_cast<void*>(Interpreter::cti_op_call_arityCheck));
1996     X86Assembler::link(code, callArityCheck3, reinterpret_cast<void*>(Interpreter::cti_op_call_arityCheck));
1997     X86Assembler::link(code, callJSFunction1, reinterpret_cast<void*>(Interpreter::cti_op_call_JSFunction));
1998     X86Assembler::link(code, callJSFunction2, reinterpret_cast<void*>(Interpreter::cti_op_call_JSFunction));
1999     X86Assembler::link(code, callJSFunction3, reinterpret_cast<void*>(Interpreter::cti_op_call_JSFunction));
2000     X86Assembler::link(code, callDontLazyLinkCall, reinterpret_cast<void*>(Interpreter::cti_vm_dontLazyLinkCall));
2001     X86Assembler::link(code, callLazyLinkCall, reinterpret_cast<void*>(Interpreter::cti_vm_lazyLinkCall));
2002
2003     m_interpreter->m_ctiArrayLengthTrampoline = code;
2004     m_interpreter->m_ctiStringLengthTrampoline = X86Assembler::getRelocatedAddress(code, stringLengthBegin);
2005     m_interpreter->m_ctiVirtualCallPreLink = X86Assembler::getRelocatedAddress(code, virtualCallPreLinkBegin);
2006     m_interpreter->m_ctiVirtualCallLink = X86Assembler::getRelocatedAddress(code, virtualCallLinkBegin);
2007     m_interpreter->m_ctiVirtualCall = X86Assembler::getRelocatedAddress(code, virtualCallBegin);
2008 }
2009
2010 void JIT::emitGetVariableObjectRegister(RegisterID variableObject, int index, RegisterID dst)
2011 {
2012     loadPtr(Address(variableObject, FIELD_OFFSET(JSVariableObject, d)), dst);
2013     loadPtr(Address(dst, FIELD_OFFSET(JSVariableObject::JSVariableObjectData, registers)), dst);
2014     loadPtr(Address(dst, index * sizeof(Register)), dst);
2015 }
2016
2017 void JIT::emitPutVariableObjectRegister(RegisterID src, RegisterID variableObject, int index)
2018 {
2019     loadPtr(Address(variableObject, FIELD_OFFSET(JSVariableObject, d)), variableObject);
2020     loadPtr(Address(variableObject, FIELD_OFFSET(JSVariableObject::JSVariableObjectData, registers)), variableObject);
2021     storePtr(src, Address(variableObject, index * sizeof(Register)));
2022 }
2023
2024 } // namespace JSC
2025
2026 #endif // ENABLE(JIT)