f46a07e931345f8d68fe05b28098389cc63734fd
[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 "JSArray.h"
33 #include "JSFunction.h"
34 #include "Interpreter.h"
35 #include "ResultType.h"
36 #include "SamplingTool.h"
37
38 #ifndef NDEBUG
39 #include <stdio.h>
40 #endif
41
42 #define __ m_assembler. 
43
44 #if PLATFORM(WIN)
45 #undef FIELD_OFFSET // Fix conflict with winnt.h.
46 #endif
47
48 // FIELD_OFFSET: Like the C++ offsetof macro, but you can use it with classes.
49 // The magic number 0x4000 is insignificant. We use it to avoid using NULL, since
50 // NULL can cause compiler problems, especially in cases of multiple inheritance.
51 #define FIELD_OFFSET(class, field) (reinterpret_cast<ptrdiff_t>(&(reinterpret_cast<class*>(0x4000)->field)) - 0x4000)
52
53 using namespace std;
54
55 namespace JSC {
56
57 typedef X86Assembler::JmpSrc JmpSrc;
58
59 #if PLATFORM(MAC)
60
61 static inline bool isSSE2Present()
62 {
63     return true; // All X86 Macs are guaranteed to support at least SSE2
64 }
65
66 #else
67
68 static bool isSSE2Present()
69 {
70     static const int SSE2FeatureBit = 1 << 26;
71     struct SSE2Check {
72         SSE2Check()
73         {
74             int flags;
75 #if COMPILER(MSVC)
76             _asm {
77                 mov eax, 1 // cpuid function 1 gives us the standard feature set
78                 cpuid;
79                 mov flags, edx;
80             }
81 #else
82             flags = 0;
83             // FIXME: Add GCC code to do above asm
84 #endif
85             present = (flags & SSE2FeatureBit) != 0;
86         }
87         bool present;
88     };
89     static SSE2Check check;
90     return check.present;
91 }
92
93 #endif
94
95 COMPILE_ASSERT(CTI_ARGS_code == 0xC, CTI_ARGS_code_is_C);
96 COMPILE_ASSERT(CTI_ARGS_callFrame == 0xE, CTI_ARGS_callFrame_is_E);
97
98 #if COMPILER(GCC) && PLATFORM(X86)
99
100 #if PLATFORM(DARWIN)
101 #define SYMBOL_STRING(name) "_" #name
102 #else
103 #define SYMBOL_STRING(name) #name
104 #endif
105
106 asm(
107 ".globl " SYMBOL_STRING(ctiTrampoline) "\n"
108 SYMBOL_STRING(ctiTrampoline) ":" "\n"
109     "pushl %esi" "\n"
110     "pushl %edi" "\n"
111     "pushl %ebx" "\n"
112     "subl $0x20, %esp" "\n"
113     "movl $512, %esi" "\n"
114     "movl 0x38(%esp), %edi" "\n" // Ox38 = 0x0E * 4, 0x0E = CTI_ARGS_callFrame (see assertion above)
115     "call *0x30(%esp)" "\n" // Ox30 = 0x0C * 4, 0x0C = CTI_ARGS_code (see assertion above)
116     "addl $0x20, %esp" "\n"
117     "popl %ebx" "\n"
118     "popl %edi" "\n"
119     "popl %esi" "\n"
120     "ret" "\n"
121 );
122
123 asm(
124 ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
125 SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
126 #if USE(CTI_ARGUMENT)
127 #if USE(FAST_CALL_CTI_ARGUMENT)
128     "movl %esp, %ecx" "\n"
129 #else
130     "movl %esp, 0(%esp)" "\n"
131 #endif
132     "call " SYMBOL_STRING(_ZN3JSC11Interpreter12cti_vm_throwEPPv) "\n"
133 #else
134     "call " SYMBOL_STRING(_ZN3JSC11Interpreter12cti_vm_throwEPvz) "\n"
135 #endif
136     "addl $0x20, %esp" "\n"
137     "popl %ebx" "\n"
138     "popl %edi" "\n"
139     "popl %esi" "\n"
140     "ret" "\n"
141 );
142     
143 #elif COMPILER(MSVC)
144
145 extern "C" {
146     
147     __declspec(naked) JSValue* ctiTrampoline(void* code, RegisterFile*, CallFrame*, JSValue** exception, Profiler**, JSGlobalData*)
148     {
149         __asm {
150             push esi;
151             push edi;
152             push ebx;
153             sub esp, 0x20;
154             mov esi, 512;
155             mov ecx, esp;
156             mov edi, [esp + 0x38];
157             call [esp + 0x30]; // Ox30 = 0x0C * 4, 0x0C = CTI_ARGS_code (see assertion above)
158             add esp, 0x20;
159             pop ebx;
160             pop edi;
161             pop esi;
162             ret;
163         }
164     }
165     
166     __declspec(naked) void ctiVMThrowTrampoline()
167     {
168         __asm {
169             mov ecx, esp;
170             call JSC::Interpreter::cti_vm_throw;
171             add esp, 0x20;
172             pop ebx;
173             pop edi;
174             pop esi;
175             ret;
176         }
177     }
178     
179 }
180
181 #endif
182
183 static ALWAYS_INLINE uintptr_t asInteger(JSValue* value)
184 {
185     return reinterpret_cast<uintptr_t>(value);
186 }
187
188 ALWAYS_INLINE void JIT::killLastResultRegister()
189 {
190     m_lastResultBytecodeRegister = std::numeric_limits<int>::max();
191 }
192
193 // get arg puts an arg from the SF register array into a h/w register
194 ALWAYS_INLINE void JIT::emitGetVirtualRegister(int src, RegisterID dst, unsigned currentInstructionIndex)
195 {
196     // TODO: we want to reuse values that are already in registers if we can - add a register allocator!
197     if (m_codeBlock->isConstantRegisterIndex(src)) {
198         JSValue* value = m_codeBlock->getConstant(src);
199         __ movl_i32r(asInteger(value), dst);
200         killLastResultRegister();
201         return;
202     }
203
204     if (src == m_lastResultBytecodeRegister && m_codeBlock->isTemporaryRegisterIndex(src)) {
205         bool atJumpTarget = false;
206         while (m_jumpTargetsPosition < m_codeBlock->jumpTargets.size() && m_codeBlock->jumpTargets[m_jumpTargetsPosition] <= currentInstructionIndex) {
207             if (m_codeBlock->jumpTargets[m_jumpTargetsPosition] == currentInstructionIndex)
208                 atJumpTarget = true;
209             ++m_jumpTargetsPosition;
210         }
211
212         if (!atJumpTarget) {
213             // The argument we want is already stored in eax
214             if (dst != X86::eax)
215                 __ movl_rr(X86::eax, dst);
216             killLastResultRegister();
217             return;
218         }
219     }
220
221     __ movl_mr(src * sizeof(Register), X86::edi, dst);
222     killLastResultRegister();
223 }
224
225 ALWAYS_INLINE void JIT::emitGetVirtualRegisters(int src1, RegisterID dst1, int src2, RegisterID dst2, unsigned i)
226 {
227     if (src2 == m_lastResultBytecodeRegister) {
228         emitGetVirtualRegister(src2, dst2, i);
229         emitGetVirtualRegister(src1, dst1, i);
230     } else {
231         emitGetVirtualRegister(src1, dst1, i);
232         emitGetVirtualRegister(src2, dst2, i);
233     }
234 }
235
236 // get arg puts an arg from the SF register array onto the stack, as an arg to a context threaded function.
237 ALWAYS_INLINE void JIT::emitPutCTIArgFromVirtualRegister(unsigned src, unsigned offset, RegisterID scratch)
238 {
239     if (m_codeBlock->isConstantRegisterIndex(src)) {
240         JSValue* value = m_codeBlock->getConstant(src);
241         __ movl_i32m(asInteger(value), offset + sizeof(void*), X86::esp);
242     } else {
243         __ movl_mr(src * sizeof(Register), X86::edi, scratch);
244         __ movl_rm(scratch, offset + sizeof(void*), X86::esp);
245     }
246
247     killLastResultRegister();
248 }
249
250 // puts an arg onto the stack, as an arg to a context threaded function.
251 ALWAYS_INLINE void JIT::emitPutCTIArg(RegisterID src, unsigned offset)
252 {
253     __ movl_rm(src, offset + sizeof(void*), X86::esp);
254 }
255
256 ALWAYS_INLINE void JIT::emitGetCTIArg(unsigned offset, RegisterID dst)
257 {
258     __ movl_mr(offset + sizeof(void*), X86::esp, dst);
259 }
260
261
262 ALWAYS_INLINE void JIT::emitPutCTIArgConstant(unsigned value, unsigned offset)
263 {
264     __ movl_i32m(value, offset + sizeof(void*), X86::esp);
265 }
266
267 ALWAYS_INLINE JSValue* JIT::getConstantImmediateNumericArg(unsigned src)
268 {
269     if (m_codeBlock->isConstantRegisterIndex(src)) {
270         JSValue* value = m_codeBlock->getConstant(src);
271         return JSImmediate::isNumber(value) ? value : noValue();
272     }
273     return noValue();
274 }
275
276 ALWAYS_INLINE void JIT::emitPutCTIParam(void* value, unsigned name)
277 {
278     __ movl_i32m(reinterpret_cast<intptr_t>(value), name * sizeof(void*), X86::esp);
279 }
280
281 ALWAYS_INLINE void JIT::emitPutCTIParam(RegisterID from, unsigned name)
282 {
283     __ movl_rm(from, name * sizeof(void*), X86::esp);
284 }
285
286 ALWAYS_INLINE void JIT::emitGetCTIParam(unsigned name, RegisterID to)
287 {
288     __ movl_mr(name * sizeof(void*), X86::esp, to);
289     killLastResultRegister();
290 }
291
292 ALWAYS_INLINE void JIT::emitPutToCallFrameHeader(RegisterID from, RegisterFile::CallFrameHeaderEntry entry)
293 {
294     __ movl_rm(from, entry * sizeof(Register), X86::edi);
295 }
296
297 ALWAYS_INLINE void JIT::emitGetFromCallFrameHeader(RegisterFile::CallFrameHeaderEntry entry, RegisterID to)
298 {
299     __ movl_mr(entry * sizeof(Register), X86::edi, to);
300     killLastResultRegister();
301 }
302
303 ALWAYS_INLINE void JIT::emitPutVirtualRegister(unsigned dst, RegisterID from)
304 {
305     __ movl_rm(from, dst * sizeof(Register), X86::edi);
306     m_lastResultBytecodeRegister = (from == X86::eax) ? dst : std::numeric_limits<int>::max();
307     // FIXME: #ifndef NDEBUG, Write the correct m_type to the register.
308 }
309
310 ALWAYS_INLINE void JIT::emitInitRegister(unsigned dst)
311 {
312     __ movl_i32m(asInteger(jsUndefined()), dst * sizeof(Register), X86::edi);
313     // FIXME: #ifndef NDEBUG, Write the correct m_type to the register.
314 }
315
316 void ctiSetReturnAddress(void** where, void* what)
317 {
318     *where = what;
319 }
320
321 void ctiRepatchCallByReturnAddress(void* where, void* what)
322 {
323     (static_cast<void**>(where))[-1] = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(what) - reinterpret_cast<uintptr_t>(where));
324 }
325
326 #ifndef NDEBUG
327
328 void JIT::printBytecodeOperandTypes(unsigned src1, unsigned src2)
329 {
330     char which1 = '*';
331     if (m_codeBlock->isConstantRegisterIndex(src1)) {
332         JSValue* value = m_codeBlock->getConstant(src1);
333         which1 = 
334             JSImmediate::isImmediate(value) ?
335                 (JSImmediate::isNumber(value) ? 'i' :
336                 JSImmediate::isBoolean(value) ? 'b' :
337                 value->isUndefined() ? 'u' :
338                 value->isNull() ? 'n' : '?')
339                 :
340             (value->isString() ? 's' :
341             value->isObject() ? 'o' :
342             'k');
343     }
344     char which2 = '*';
345     if (m_codeBlock->isConstantRegisterIndex(src2)) {
346         JSValue* value = m_codeBlock->getConstant(src2);
347         which2 = 
348             JSImmediate::isImmediate(value) ?
349                 (JSImmediate::isNumber(value) ? 'i' :
350                 JSImmediate::isBoolean(value) ? 'b' :
351                 value->isUndefined() ? 'u' :
352                 value->isNull() ? 'n' : '?')
353                 :
354             (value->isString() ? 's' :
355             value->isObject() ? 'o' :
356             'k');
357     }
358     if ((which1 != '*') | (which2 != '*'))
359         fprintf(stderr, "Types %c %c\n", which1, which2);
360 }
361
362 #endif
363
364 extern "C" {
365     static JSValue* FASTCALL allocateNumber(JSGlobalData* globalData) {
366         JSValue* result = new (globalData) JSNumberCell(globalData);
367         ASSERT(result);
368         return result;
369     }
370 }
371
372 ALWAYS_INLINE void JIT::emitAllocateNumber(JSGlobalData* globalData, unsigned bytecodeIndex)
373 {
374     __ movl_i32r(reinterpret_cast<intptr_t>(globalData), X86::ecx);
375     emitNakedFastCall(bytecodeIndex, (void*)allocateNumber);
376 }
377
378 ALWAYS_INLINE JmpSrc JIT::emitNakedCall(unsigned bytecodeIndex, X86::RegisterID r)
379 {
380     JmpSrc call = __ call(r);
381     m_calls.append(CallRecord(call, bytecodeIndex));
382
383     return call;
384 }
385
386 ALWAYS_INLINE  JmpSrc JIT::emitNakedCall(unsigned bytecodeIndex, void* function)
387 {
388     JmpSrc call = __ call();
389     m_calls.append(CallRecord(call, reinterpret_cast<CTIHelper_v>(function), bytecodeIndex));
390     return call;
391 }
392
393 ALWAYS_INLINE  JmpSrc JIT::emitNakedFastCall(unsigned bytecodeIndex, void* function)
394 {
395     JmpSrc call = __ call();
396     m_calls.append(CallRecord(call, reinterpret_cast<CTIHelper_v>(function), bytecodeIndex));
397     return call;
398 }
399
400 ALWAYS_INLINE JmpSrc JIT::emitCTICall(unsigned bytecodeIndex, CTIHelper_j helper)
401 {
402 #if ENABLE(OPCODE_SAMPLING)
403     __ movl_i32m(m_interpreter->sampler()->encodeSample(m_codeBlock->instructions.begin() + bytecodeIndex, true), m_interpreter->sampler()->sampleSlot());
404 #endif
405     __ restoreArgumentReference();
406     emitPutCTIParam(X86::edi, CTI_ARGS_callFrame);
407     JmpSrc call = __ call();
408     m_calls.append(CallRecord(call, helper, bytecodeIndex));
409 #if ENABLE(OPCODE_SAMPLING)
410     __ movl_i32m(m_interpreter->sampler()->encodeSample(m_codeBlock->instructions.begin() + bytecodeIndex, false), m_interpreter->sampler()->sampleSlot());
411 #endif
412     killLastResultRegister();
413
414     return call;
415 }
416
417 ALWAYS_INLINE JmpSrc JIT::emitCTICall(unsigned bytecodeIndex, CTIHelper_o helper)
418 {
419 #if ENABLE(OPCODE_SAMPLING)
420     __ movl_i32m(m_interpreter->sampler()->encodeSample(m_codeBlock->instructions.begin() + bytecodeIndex, true), m_interpreter->sampler()->sampleSlot());
421 #endif
422     __ restoreArgumentReference();
423     emitPutCTIParam(X86::edi, CTI_ARGS_callFrame);
424     JmpSrc call = __ call();
425     m_calls.append(CallRecord(call, helper, bytecodeIndex));
426 #if ENABLE(OPCODE_SAMPLING)
427     __ movl_i32m(m_interpreter->sampler()->encodeSample(m_codeBlock->instructions.begin() + bytecodeIndex, false), m_interpreter->sampler()->sampleSlot());
428 #endif
429     killLastResultRegister();
430
431     return call;
432 }
433
434 ALWAYS_INLINE JmpSrc JIT::emitCTICall(unsigned bytecodeIndex, CTIHelper_p helper)
435 {
436 #if ENABLE(OPCODE_SAMPLING)
437     __ movl_i32m(m_interpreter->sampler()->encodeSample(m_codeBlock->instructions.begin() + bytecodeIndex, true), m_interpreter->sampler()->sampleSlot());
438 #endif
439     __ restoreArgumentReference();
440     emitPutCTIParam(X86::edi, CTI_ARGS_callFrame);
441     JmpSrc call = __ call();
442     m_calls.append(CallRecord(call, helper, bytecodeIndex));
443 #if ENABLE(OPCODE_SAMPLING)
444     __ movl_i32m(m_interpreter->sampler()->encodeSample(m_codeBlock->instructions.begin() + bytecodeIndex, false), m_interpreter->sampler()->sampleSlot());
445 #endif
446     killLastResultRegister();
447
448     return call;
449 }
450
451 ALWAYS_INLINE JmpSrc JIT::emitCTICall(unsigned bytecodeIndex, CTIHelper_b helper)
452 {
453 #if ENABLE(OPCODE_SAMPLING)
454     __ movl_i32m(m_interpreter->sampler()->encodeSample(m_codeBlock->instructions.begin() + bytecodeIndex, true), m_interpreter->sampler()->sampleSlot());
455 #endif
456     __ restoreArgumentReference();
457     emitPutCTIParam(X86::edi, CTI_ARGS_callFrame);
458     JmpSrc call = __ call();
459     m_calls.append(CallRecord(call, helper, bytecodeIndex));
460 #if ENABLE(OPCODE_SAMPLING)
461     __ movl_i32m(m_interpreter->sampler()->encodeSample(m_codeBlock->instructions.begin() + bytecodeIndex, false), m_interpreter->sampler()->sampleSlot());
462 #endif
463     killLastResultRegister();
464
465     return call;
466 }
467
468 ALWAYS_INLINE JmpSrc JIT::emitCTICall(unsigned bytecodeIndex, CTIHelper_v helper)
469 {
470 #if ENABLE(OPCODE_SAMPLING)
471     __ movl_i32m(m_interpreter->sampler()->encodeSample(m_codeBlock->instructions.begin() + bytecodeIndex, true), m_interpreter->sampler()->sampleSlot());
472 #endif
473     __ restoreArgumentReference();
474     emitPutCTIParam(X86::edi, CTI_ARGS_callFrame);
475     JmpSrc call = __ call();
476     m_calls.append(CallRecord(call, helper, bytecodeIndex));
477 #if ENABLE(OPCODE_SAMPLING)
478     __ movl_i32m(m_interpreter->sampler()->encodeSample(m_codeBlock->instructions.begin() + bytecodeIndex, false), m_interpreter->sampler()->sampleSlot());
479 #endif
480     killLastResultRegister();
481
482     return call;
483 }
484
485 ALWAYS_INLINE JmpSrc JIT::emitCTICall(unsigned bytecodeIndex, CTIHelper_s helper)
486 {
487 #if ENABLE(OPCODE_SAMPLING)
488     __ movl_i32m(m_interpreter->sampler()->encodeSample(m_codeBlock->instructions.begin() + bytecodeIndex, true), m_interpreter->sampler()->sampleSlot());
489 #endif
490     __ restoreArgumentReference();
491     emitPutCTIParam(X86::edi, CTI_ARGS_callFrame);
492     JmpSrc call = __ call();
493     m_calls.append(CallRecord(call, helper, bytecodeIndex));
494 #if ENABLE(OPCODE_SAMPLING)
495     __ movl_i32m(m_interpreter->sampler()->encodeSample(m_codeBlock->instructions.begin() + bytecodeIndex, false), m_interpreter->sampler()->sampleSlot());
496 #endif
497     killLastResultRegister();
498
499     return call;
500 }
501
502 ALWAYS_INLINE JmpSrc JIT::emitCTICall(unsigned bytecodeIndex, CTIHelper_2 helper)
503 {
504 #if ENABLE(OPCODE_SAMPLING)
505     __ movl_i32m(m_interpreter->sampler()->encodeSample(m_codeBlock->instructions.begin() + bytecodeIndex, true), m_interpreter->sampler()->sampleSlot());
506 #endif
507     __ restoreArgumentReference();
508     emitPutCTIParam(X86::edi, CTI_ARGS_callFrame);
509     JmpSrc call = __ call();
510     m_calls.append(CallRecord(call, helper, bytecodeIndex));
511 #if ENABLE(OPCODE_SAMPLING)
512     __ movl_i32m(m_interpreter->sampler()->encodeSample(m_codeBlock->instructions.begin() + bytecodeIndex, false), m_interpreter->sampler()->sampleSlot());
513 #endif
514     killLastResultRegister();
515
516     return call;
517 }
518
519 JmpSrc JIT::checkStructure(RegisterID reg, Structure* structure)
520 {
521     __ cmpl_i32m(reinterpret_cast<uint32_t>(structure), FIELD_OFFSET(JSCell, m_structure), reg);
522     return __ jne();
523 }
524
525 ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotJSCell(RegisterID reg, unsigned bytecodeIndex)
526 {
527     __ testl_i32r(JSImmediate::TagMask, reg);
528     m_slowCases.append(SlowCaseEntry(__ jne(), bytecodeIndex));
529 }
530
531 ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotJSCell(RegisterID reg, unsigned bytecodeIndex, int vReg)
532 {
533     if (m_codeBlock->isKnownNotImmediate(vReg))
534         return;
535
536     emitJumpSlowCaseIfNotJSCell(reg, bytecodeIndex);
537 }
538
539 ALWAYS_INLINE bool JIT::linkSlowCaseIfNotJSCell(const Vector<SlowCaseEntry>::iterator& iter, int vReg)
540 {
541     if (m_codeBlock->isKnownNotImmediate(vReg))
542         return false;
543     
544     __ link(iter->from, __ label());
545     return true;
546 }
547
548 ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotImmNum(RegisterID reg, unsigned bytecodeIndex)
549 {
550     __ testl_i32r(JSImmediate::TagBitTypeInteger, reg);
551     m_slowCases.append(SlowCaseEntry(__ je(), bytecodeIndex));
552 }
553
554 ALWAYS_INLINE void JIT::emitJumpSlowCaseIfNotImmNums(RegisterID reg1, RegisterID reg2, unsigned bytecodeIndex)
555 {
556     __ movl_rr(reg1, X86::ecx);
557     __ andl_rr(reg2, X86::ecx);
558     emitJumpSlowCaseIfNotImmNum(X86::ecx, bytecodeIndex);
559 }
560
561 ALWAYS_INLINE unsigned JIT::getDeTaggedConstantImmediate(JSValue* imm)
562 {
563     ASSERT(JSImmediate::isNumber(imm));
564     return asInteger(imm) & ~JSImmediate::TagBitTypeInteger;
565 }
566
567 ALWAYS_INLINE void JIT::emitFastArithDeTagImmediate(RegisterID reg)
568 {
569     __ subl_i8r(JSImmediate::TagBitTypeInteger, reg);
570 }
571
572 ALWAYS_INLINE JmpSrc JIT::emitFastArithDeTagImmediateJumpIfZero(RegisterID reg)
573 {
574     __ subl_i8r(JSImmediate::TagBitTypeInteger, reg);
575     return __ je();
576 }
577
578 ALWAYS_INLINE void JIT::emitFastArithReTagImmediate(RegisterID reg)
579 {
580     __ addl_i8r(JSImmediate::TagBitTypeInteger, reg);
581 }
582
583 ALWAYS_INLINE void JIT::emitFastArithPotentiallyReTagImmediate(RegisterID reg)
584 {
585     __ orl_i32r(JSImmediate::TagBitTypeInteger, reg);
586 }
587
588 ALWAYS_INLINE void JIT::emitFastArithImmToInt(RegisterID reg)
589 {
590     __ sarl_i8r(1, reg);
591 }
592
593 ALWAYS_INLINE void JIT::emitFastArithIntToImmOrSlowCase(RegisterID reg, unsigned bytecodeIndex)
594 {
595     __ addl_rr(reg, reg);
596     m_slowCases.append(SlowCaseEntry(__ jo(), bytecodeIndex));
597     emitFastArithReTagImmediate(reg);
598 }
599
600 ALWAYS_INLINE void JIT::emitFastArithIntToImmNoCheck(RegisterID reg)
601 {
602     __ addl_rr(reg, reg);
603     emitFastArithReTagImmediate(reg);
604 }
605
606 ALWAYS_INLINE JmpSrc JIT::emitArithIntToImmWithJump(RegisterID reg)
607 {
608     __ addl_rr(reg, reg);
609     JmpSrc jmp = __ jo();
610     emitFastArithReTagImmediate(reg);
611     return jmp;
612 }
613
614 ALWAYS_INLINE void JIT::emitTagAsBoolImmediate(RegisterID reg)
615 {
616     __ shl_i8r(JSImmediate::ExtendedPayloadShift, reg);
617     __ orl_i32r(JSImmediate::FullTagTypeBool, reg);
618 }
619
620 JIT::JIT(JSGlobalData* globalData, CodeBlock* codeBlock)
621     : m_assembler(globalData->interpreter->assemblerBuffer())
622     , m_interpreter(globalData->interpreter)
623     , m_globalData(globalData)
624     , m_codeBlock(codeBlock)
625     , m_labels(codeBlock ? codeBlock->instructions.size() : 0)
626     , m_propertyAccessCompilationInfo(codeBlock ? codeBlock->propertyAccessInstructions.size() : 0)
627     , m_callStructureStubCompilationInfo(codeBlock ? codeBlock->callLinkInfos.size() : 0)
628     , m_lastResultBytecodeRegister(std::numeric_limits<int>::max())
629     , m_jumpTargetsPosition(0)
630 {
631 }
632
633 #define CTI_COMPILE_BINARY_OP(name) \
634     case name: { \
635         emitPutCTIArgFromVirtualRegister(instruction[i + 2].u.operand, 0, X86::ecx); \
636         emitPutCTIArgFromVirtualRegister(instruction[i + 3].u.operand, 4, X86::ecx); \
637         emitCTICall(i, Interpreter::cti_##name); \
638         emitPutVirtualRegister(instruction[i + 1].u.operand); \
639         i += 4; \
640         break; \
641     }
642
643 #define CTI_COMPILE_UNARY_OP(name) \
644     case name: { \
645         emitPutCTIArgFromVirtualRegister(instruction[i + 2].u.operand, 0, X86::ecx); \
646         emitCTICall(i, Interpreter::cti_##name); \
647         emitPutVirtualRegister(instruction[i + 1].u.operand); \
648         i += 3; \
649         break; \
650     }
651
652 static void unreachable()
653 {
654     ASSERT_NOT_REACHED();
655     exit(1);
656 }
657
658 void JIT::compileOpCallInitializeCallFrame()
659 {
660     __ movl_rm(X86::edx, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register)), X86::edi);
661
662     __ movl_mr(FIELD_OFFSET(JSFunction, m_scopeChain) + FIELD_OFFSET(ScopeChain, m_node), X86::ecx, X86::edx); // newScopeChain
663
664     __ movl_i32m(asInteger(noValue()), RegisterFile::OptionalCalleeArguments * static_cast<int>(sizeof(Register)), X86::edi);
665     __ movl_rm(X86::ecx, RegisterFile::Callee * static_cast<int>(sizeof(Register)), X86::edi);
666     __ movl_rm(X86::edx, RegisterFile::ScopeChain * static_cast<int>(sizeof(Register)), X86::edi);
667 }
668
669 void JIT::compileOpCallSetupArgs(Instruction* instruction)
670 {
671     int argCount = instruction[3].u.operand;
672     int registerOffset = instruction[4].u.operand;
673
674     // ecx holds func
675     emitPutCTIArg(X86::ecx, 0);
676     emitPutCTIArgConstant(registerOffset, 4);
677     emitPutCTIArgConstant(argCount, 8);
678     emitPutCTIArgConstant(reinterpret_cast<unsigned>(instruction), 12);
679 }
680
681 void JIT::compileOpCallEvalSetupArgs(Instruction* instruction)
682 {
683     int argCount = instruction[3].u.operand;
684     int registerOffset = instruction[4].u.operand;
685
686     // ecx holds func
687     emitPutCTIArg(X86::ecx, 0);
688     emitPutCTIArgConstant(registerOffset, 4);
689     emitPutCTIArgConstant(argCount, 8);
690     emitPutCTIArgConstant(reinterpret_cast<unsigned>(instruction), 12);
691 }
692
693 void JIT::compileOpConstructSetupArgs(Instruction* instruction)
694 {
695     int argCount = instruction[3].u.operand;
696     int registerOffset = instruction[4].u.operand;
697     int proto = instruction[5].u.operand;
698     int thisRegister = instruction[6].u.operand;
699
700     // ecx holds func
701     emitPutCTIArg(X86::ecx, 0);
702     emitPutCTIArgConstant(registerOffset, 4);
703     emitPutCTIArgConstant(argCount, 8);
704     emitPutCTIArgFromVirtualRegister(proto, 12, X86::eax);
705     emitPutCTIArgConstant(thisRegister, 16);
706     emitPutCTIArgConstant(reinterpret_cast<unsigned>(instruction), 20);
707 }
708
709 void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned i, unsigned callLinkInfoIndex)
710 {
711     int dst = instruction[1].u.operand;
712     int callee = instruction[2].u.operand;
713     int argCount = instruction[3].u.operand;
714     int registerOffset = instruction[4].u.operand;
715
716     // Handle eval
717     JmpSrc wasEval;
718     if (opcodeID == op_call_eval) {
719         emitGetVirtualRegister(callee, X86::ecx, i);
720         compileOpCallEvalSetupArgs(instruction);
721
722         emitCTICall(i, Interpreter::cti_op_call_eval);
723         __ cmpl_i32r(asInteger(JSImmediate::impossibleValue()), X86::eax);
724         wasEval = __ jne();
725     }
726
727     // This plants a check for a cached JSFunction value, so we can plant a fast link to the callee.
728     // This deliberately leaves the callee in ecx, used when setting up the stack frame below
729     emitGetVirtualRegister(callee, X86::ecx, i);
730     __ cmpl_i32r(asInteger(JSImmediate::impossibleValue()), X86::ecx);
731     JmpDst addressOfLinkedFunctionCheck = __ label();
732     m_slowCases.append(SlowCaseEntry(__ jne(), i));
733     ASSERT(X86Assembler::getDifferenceBetweenLabels(addressOfLinkedFunctionCheck, __ label()) == repatchOffsetOpCallCall);
734     m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathBegin = addressOfLinkedFunctionCheck;
735
736     // The following is the fast case, only used whan a callee can be linked.
737
738     // In the case of OpConstruct, call out to a cti_ function to create the new object.
739     if (opcodeID == op_construct) {
740         int proto = instruction[5].u.operand;
741         int thisRegister = instruction[6].u.operand;
742
743         emitPutCTIArg(X86::ecx, 0);
744         emitPutCTIArgFromVirtualRegister(proto, 12, X86::eax);
745         emitCTICall(i, Interpreter::cti_op_construct_JSConstruct);
746         emitPutVirtualRegister(thisRegister);
747         emitGetVirtualRegister(callee, X86::ecx, i);
748     }
749
750     // Fast version of stack frame initialization, directly relative to edi.
751     // Note that this omits to set up RegisterFile::CodeBlock, which is set in the callee
752     __ movl_i32m(asInteger(noValue()), (registerOffset + RegisterFile::OptionalCalleeArguments) * static_cast<int>(sizeof(Register)), X86::edi);
753     __ movl_rm(X86::ecx, (registerOffset + RegisterFile::Callee) * static_cast<int>(sizeof(Register)), X86::edi);
754     __ movl_mr(FIELD_OFFSET(JSFunction, m_scopeChain) + FIELD_OFFSET(ScopeChain, m_node), X86::ecx, X86::edx); // newScopeChain
755     __ movl_i32m(argCount, (registerOffset + RegisterFile::ArgumentCount) * static_cast<int>(sizeof(Register)), X86::edi);
756     __ movl_rm(X86::edi, (registerOffset + RegisterFile::CallerFrame) * static_cast<int>(sizeof(Register)), X86::edi);
757     __ movl_rm(X86::edx, (registerOffset + RegisterFile::ScopeChain) * static_cast<int>(sizeof(Register)), X86::edi);
758     __ addl_i32r(registerOffset * sizeof(Register), X86::edi);
759
760     // Call to the callee
761     m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedCall(i, reinterpret_cast<void*>(unreachable));
762     
763     if (opcodeID == op_call_eval)
764         __ link(wasEval, __ label());
765
766     // Put the return value in dst. In the interpreter, op_ret does this.
767     emitPutVirtualRegister(dst);
768
769 #if ENABLE(CODEBLOCK_SAMPLING)
770         __ movl_i32m(reinterpret_cast<unsigned>(m_codeBlock), m_interpreter->sampler()->codeBlockSlot());
771 #endif
772 }
773
774 void JIT::compileOpStrictEq(Instruction* instruction, unsigned i, CompileOpStrictEqType type)
775 {
776     bool negated = (type == OpNStrictEq);
777
778     unsigned dst = instruction[1].u.operand;
779     unsigned src1 = instruction[2].u.operand;
780     unsigned src2 = instruction[3].u.operand;
781
782     emitGetVirtualRegisters(src1, X86::eax, src2, X86::edx, i);
783
784     __ testl_i32r(JSImmediate::TagMask, X86::eax);
785     JmpSrc firstNotImmediate = __ je();
786     __ testl_i32r(JSImmediate::TagMask, X86::edx);
787     JmpSrc secondNotImmediate = __ je();
788
789     __ cmpl_rr(X86::edx, X86::eax);
790     if (negated)
791         __ setne_r(X86::eax);
792     else
793         __ sete_r(X86::eax);
794     __ movzbl_rr(X86::eax, X86::eax);
795     emitTagAsBoolImmediate(X86::eax);
796             
797     JmpSrc bothWereImmediates = __ jmp();
798
799     __ link(firstNotImmediate, __ label());
800
801     // check that edx is immediate but not the zero immediate
802     __ testl_i32r(JSImmediate::TagMask, X86::edx);
803     __ setz_r(X86::ecx);
804     __ movzbl_rr(X86::ecx, X86::ecx); // ecx is now 1 if edx was nonimmediate
805     __ cmpl_i32r(asInteger(JSImmediate::zeroImmediate()), X86::edx);
806     __ sete_r(X86::edx);
807     __ movzbl_rr(X86::edx, X86::edx); // edx is now 1 if edx was the 0 immediate
808     __ orl_rr(X86::ecx, X86::edx);
809
810     m_slowCases.append(SlowCaseEntry(__ jnz(), i));
811
812     __ movl_i32r(asInteger(jsBoolean(negated)), X86::eax);
813
814     JmpSrc firstWasNotImmediate = __ jmp();
815
816     __ link(secondNotImmediate, __ label());
817     // check that eax is not the zero immediate (we know it must be immediate)
818     __ cmpl_i32r(asInteger(JSImmediate::zeroImmediate()), X86::eax);
819     m_slowCases.append(SlowCaseEntry(__ je(), i));
820
821     __ movl_i32r(asInteger(jsBoolean(negated)), X86::eax);
822
823     __ link(bothWereImmediates, __ label());
824     __ link(firstWasNotImmediate, __ label());
825
826     emitPutVirtualRegister(dst);
827 }
828
829 void JIT::emitSlowScriptCheck(unsigned bytecodeIndex)
830 {
831     __ subl_i8r(1, X86::esi);
832     JmpSrc skipTimeout = __ jne();
833     emitCTICall(bytecodeIndex, Interpreter::cti_timeout_check);
834
835     emitGetCTIParam(CTI_ARGS_globalData, X86::ecx);
836     __ movl_mr(FIELD_OFFSET(JSGlobalData, interpreter), X86::ecx, X86::ecx);
837     __ movl_mr(FIELD_OFFSET(Interpreter, m_ticksUntilNextTimeoutCheck), X86::ecx, X86::esi);
838     __ link(skipTimeout, __ label());
839
840     killLastResultRegister();
841 }
842
843 /*
844   This is required since number representation is canonical - values representable as a JSImmediate should not be stored in a JSNumberCell.
845   
846   In the common case, the double value from 'xmmSource' is written to the reusable JSNumberCell pointed to by 'jsNumberCell', then 'jsNumberCell'
847   is written to the output SF Register 'dst', and then a jump is planted (stored into *wroteJSNumberCell).
848   
849   However if the value from xmmSource is representable as a JSImmediate, then the JSImmediate value will be written to the output, and flow
850   control will fall through from the code planted.
851 */
852 void JIT::putDoubleResultToJSNumberCellOrJSImmediate(X86::XMMRegisterID xmmSource, X86::RegisterID jsNumberCell, unsigned dst, JmpSrc* wroteJSNumberCell,  X86::XMMRegisterID tempXmm, X86::RegisterID tempReg1, X86::RegisterID tempReg2)
853 {
854     // convert (double -> JSImmediate -> double), and check if the value is unchanged - in which case the value is representable as a JSImmediate.
855     __ cvttsd2si_rr(xmmSource, tempReg1);
856     __ addl_rr(tempReg1, tempReg1);
857     __ sarl_i8r(1, tempReg1);
858     __ cvtsi2sd_rr(tempReg1, tempXmm);
859     // Compare & branch if immediate. 
860     __ ucomis_rr(tempXmm, xmmSource);
861     JmpSrc resultIsImm = __ je();
862     JmpDst resultLookedLikeImmButActuallyIsnt = __ label();
863     
864     // Store the result to the JSNumberCell and jump.
865     __ movsd_rm(xmmSource, FIELD_OFFSET(JSNumberCell, m_value), jsNumberCell);
866     if (jsNumberCell != X86::eax)
867         __ movl_rr(jsNumberCell, X86::eax);
868     emitPutVirtualRegister(dst);
869     *wroteJSNumberCell = __ jmp();
870
871     __ link(resultIsImm, __ label());
872     // value == (double)(JSImmediate)value... or at least, it looks that way...
873     // ucomi will report that (0 == -0), and will report true if either input in NaN (result is unordered).
874     __ link(__ jp(), resultLookedLikeImmButActuallyIsnt); // Actually was a NaN
875     __ pextrw_irr(3, xmmSource, tempReg2);
876     __ cmpl_i32r(0x8000, tempReg2);
877     __ link(__ je(), resultLookedLikeImmButActuallyIsnt); // Actually was -0
878     // Yes it really really really is representable as a JSImmediate.
879     emitFastArithIntToImmNoCheck(tempReg1);
880     if (tempReg1 != X86::eax)
881         __ movl_rr(tempReg1, X86::eax);
882     emitPutVirtualRegister(dst);
883 }
884
885 void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned dst, unsigned src1, unsigned src2, OperandTypes types, unsigned i)
886 {
887     Structure* numberStructure = m_globalData->numberStructure.get();
888     JmpSrc wasJSNumberCell1;
889     JmpSrc wasJSNumberCell1b;
890     JmpSrc wasJSNumberCell2;
891     JmpSrc wasJSNumberCell2b;
892
893     emitGetVirtualRegisters(src1, X86::eax, src2, X86::edx, i);
894
895     if (types.second().isReusable() && isSSE2Present()) {
896         ASSERT(types.second().mightBeNumber());
897
898         // Check op2 is a number
899         __ testl_i32r(JSImmediate::TagBitTypeInteger, X86::edx);
900         JmpSrc op2imm = __ jne();
901         if (!types.second().definitelyIsNumber()) {
902             emitJumpSlowCaseIfNotJSCell(X86::edx, i, src2);
903             __ cmpl_i32m(reinterpret_cast<unsigned>(numberStructure), FIELD_OFFSET(JSCell, m_structure), X86::edx);
904             m_slowCases.append(SlowCaseEntry(__ jne(), i));
905         }
906
907         // (1) In this case src2 is a reusable number cell.
908         //     Slow case if src1 is not a number type.
909         __ testl_i32r(JSImmediate::TagBitTypeInteger, X86::eax);
910         JmpSrc op1imm = __ jne();
911         if (!types.first().definitelyIsNumber()) {
912             emitJumpSlowCaseIfNotJSCell(X86::eax, i, src1);
913             __ cmpl_i32m(reinterpret_cast<unsigned>(numberStructure), FIELD_OFFSET(JSCell, m_structure), X86::eax);
914             m_slowCases.append(SlowCaseEntry(__ jne(), i));
915         }
916
917         // (1a) if we get here, src1 is also a number cell
918         __ movsd_mr(FIELD_OFFSET(JSNumberCell, m_value), X86::eax, X86::xmm0);
919         JmpSrc loadedDouble = __ jmp();
920         // (1b) if we get here, src1 is an immediate
921         __ link(op1imm, __ label());
922         emitFastArithImmToInt(X86::eax);
923         __ cvtsi2sd_rr(X86::eax, X86::xmm0);
924         // (1c) 
925         __ link(loadedDouble, __ label());
926         if (opcodeID == op_add)
927             __ addsd_mr(FIELD_OFFSET(JSNumberCell, m_value), X86::edx, X86::xmm0);
928         else if (opcodeID == op_sub)
929             __ subsd_mr(FIELD_OFFSET(JSNumberCell, m_value), X86::edx, X86::xmm0);
930         else {
931             ASSERT(opcodeID == op_mul);
932             __ mulsd_mr(FIELD_OFFSET(JSNumberCell, m_value), X86::edx, X86::xmm0);
933         }
934
935         putDoubleResultToJSNumberCellOrJSImmediate(X86::xmm0, X86::edx, dst, &wasJSNumberCell2, X86::xmm1, X86::ecx, X86::eax);
936         wasJSNumberCell2b = __ jmp();
937
938         // (2) This handles cases where src2 is an immediate number.
939         //     Two slow cases - either src1 isn't an immediate, or the subtract overflows.
940         __ link(op2imm, __ label());
941         emitJumpSlowCaseIfNotImmNum(X86::eax, i);
942     } else if (types.first().isReusable() && isSSE2Present()) {
943         ASSERT(types.first().mightBeNumber());
944
945         // Check op1 is a number
946         __ testl_i32r(JSImmediate::TagBitTypeInteger, X86::eax);
947         JmpSrc op1imm = __ jne();
948         if (!types.first().definitelyIsNumber()) {
949             emitJumpSlowCaseIfNotJSCell(X86::eax, i, src1);
950             __ cmpl_i32m(reinterpret_cast<unsigned>(numberStructure), FIELD_OFFSET(JSCell, m_structure), X86::eax);
951             m_slowCases.append(SlowCaseEntry(__ jne(), i));
952         }
953
954         // (1) In this case src1 is a reusable number cell.
955         //     Slow case if src2 is not a number type.
956         __ testl_i32r(JSImmediate::TagBitTypeInteger, X86::edx);
957         JmpSrc op2imm = __ jne();
958         if (!types.second().definitelyIsNumber()) {
959             emitJumpSlowCaseIfNotJSCell(X86::edx, i, src2);
960             __ cmpl_i32m(reinterpret_cast<unsigned>(numberStructure), FIELD_OFFSET(JSCell, m_structure), X86::edx);
961             m_slowCases.append(SlowCaseEntry(__ jne(), i));
962         }
963
964         // (1a) if we get here, src2 is also a number cell
965         __ movsd_mr(FIELD_OFFSET(JSNumberCell, m_value), X86::edx, X86::xmm1);
966         JmpSrc loadedDouble = __ jmp();
967         // (1b) if we get here, src2 is an immediate
968         __ link(op2imm, __ label());
969         emitFastArithImmToInt(X86::edx);
970         __ cvtsi2sd_rr(X86::edx, X86::xmm1);
971         // (1c) 
972         __ link(loadedDouble, __ label());
973         __ movsd_mr(FIELD_OFFSET(JSNumberCell, m_value), X86::eax, X86::xmm0);
974         if (opcodeID == op_add)
975             __ addsd_rr(X86::xmm1, X86::xmm0);
976         else if (opcodeID == op_sub)
977             __ subsd_rr(X86::xmm1, X86::xmm0);
978         else {
979             ASSERT(opcodeID == op_mul);
980             __ mulsd_rr(X86::xmm1, X86::xmm0);
981         }
982         __ movsd_rm(X86::xmm0, FIELD_OFFSET(JSNumberCell, m_value), X86::eax);
983         emitPutVirtualRegister(dst);
984
985         putDoubleResultToJSNumberCellOrJSImmediate(X86::xmm0, X86::eax, dst, &wasJSNumberCell1, X86::xmm1, X86::ecx, X86::edx);
986         wasJSNumberCell1b = __ jmp();
987
988         // (2) This handles cases where src1 is an immediate number.
989         //     Two slow cases - either src2 isn't an immediate, or the subtract overflows.
990         __ link(op1imm, __ label());
991         emitJumpSlowCaseIfNotImmNum(X86::edx, i);
992     } else
993         emitJumpSlowCaseIfNotImmNums(X86::eax, X86::edx, i);
994
995     if (opcodeID == op_add) {
996         emitFastArithDeTagImmediate(X86::eax);
997         __ addl_rr(X86::edx, X86::eax);
998         m_slowCases.append(SlowCaseEntry(__ jo(), i));
999     } else  if (opcodeID == op_sub) {
1000         __ subl_rr(X86::edx, X86::eax);
1001         m_slowCases.append(SlowCaseEntry(__ jo(), i));
1002         emitFastArithReTagImmediate(X86::eax);
1003     } else {
1004         ASSERT(opcodeID == op_mul);
1005         // convert eax & edx from JSImmediates to ints, and check if either are zero
1006         emitFastArithImmToInt(X86::edx);
1007         JmpSrc op1Zero = emitFastArithDeTagImmediateJumpIfZero(X86::eax);
1008         __ testl_rr(X86::edx, X86::edx);
1009         JmpSrc op2NonZero = __ jne();
1010         __ link(op1Zero, __ label());
1011         // if either input is zero, add the two together, and check if the result is < 0.
1012         // If it is, we have a problem (N < 0), (N * 0) == -0, not representatble as a JSImmediate. 
1013         __ movl_rr(X86::eax, X86::ecx);
1014         __ addl_rr(X86::edx, X86::ecx);
1015         m_slowCases.append(SlowCaseEntry(__ js(), i));
1016         // Skip the above check if neither input is zero
1017         __ link(op2NonZero, __ label());
1018         __ imull_rr(X86::edx, X86::eax);
1019         m_slowCases.append(SlowCaseEntry(__ jo(), i));
1020         emitFastArithReTagImmediate(X86::eax);
1021     }
1022     emitPutVirtualRegister(dst);
1023
1024     if (types.second().isReusable() && isSSE2Present()) {
1025         __ link(wasJSNumberCell2, __ label());
1026         __ link(wasJSNumberCell2b, __ label());
1027     }
1028     else if (types.first().isReusable() && isSSE2Present()) {
1029         __ link(wasJSNumberCell1, __ label());
1030         __ link(wasJSNumberCell1b, __ label());
1031     }
1032 }
1033
1034 void JIT::compileBinaryArithOpSlowCase(OpcodeID opcodeID, Vector<SlowCaseEntry>::iterator& iter, unsigned dst, unsigned src1, unsigned src2, OperandTypes types, unsigned i)
1035 {
1036     JmpDst here = __ label();
1037     __ link(iter->from, here);
1038     if (types.second().isReusable() && isSSE2Present()) {
1039         if (!types.first().definitelyIsNumber()) {
1040             if (linkSlowCaseIfNotJSCell(++iter, src1))
1041                 ++iter;
1042             __ link(iter->from, here);
1043         }
1044         if (!types.second().definitelyIsNumber()) {
1045             if (linkSlowCaseIfNotJSCell(++iter, src2))
1046                 ++iter;
1047             __ link(iter->from, here);
1048         }
1049         __ link((++iter)->from, here);
1050     } else if (types.first().isReusable() && isSSE2Present()) {
1051         if (!types.first().definitelyIsNumber()) {
1052             if (linkSlowCaseIfNotJSCell(++iter, src1))
1053                 ++iter;
1054             __ link(iter->from, here);
1055         }
1056         if (!types.second().definitelyIsNumber()) {
1057             if (linkSlowCaseIfNotJSCell(++iter, src2))
1058                 ++iter;
1059             __ link(iter->from, here);
1060         }
1061         __ link((++iter)->from, here);
1062     } else
1063         __ link((++iter)->from, here);
1064
1065     // additional entry point to handle -0 cases.
1066     if (opcodeID == op_mul)
1067         __ link((++iter)->from, here);
1068
1069     emitPutCTIArgFromVirtualRegister(src1, 0, X86::ecx);
1070     emitPutCTIArgFromVirtualRegister(src2, 4, X86::ecx);
1071     if (opcodeID == op_add)
1072         emitCTICall(i, Interpreter::cti_op_add);
1073     else if (opcodeID == op_sub)
1074         emitCTICall(i, Interpreter::cti_op_sub);
1075     else {
1076         ASSERT(opcodeID == op_mul);
1077         emitCTICall(i, Interpreter::cti_op_mul);
1078     }
1079     emitPutVirtualRegister(dst);
1080 }
1081
1082 void JIT::privateCompileMainPass()
1083 {
1084     Instruction* instruction = m_codeBlock->instructions.begin();
1085     unsigned instructionCount = m_codeBlock->instructions.size();
1086
1087     unsigned propertyAccessInstructionIndex = 0;
1088     unsigned callLinkInfoIndex = 0;
1089
1090     for (unsigned i = 0; i < instructionCount; ) {
1091         ASSERT_WITH_MESSAGE(m_interpreter->isOpcode(instruction[i].u.opcode), "privateCompileMainPass gone bad @ %d", i);
1092
1093 #if ENABLE(OPCODE_SAMPLING)
1094         if (i > 0) // Avoid the overhead of sampling op_enter twice.
1095             __ movl_i32m(m_interpreter->sampler()->encodeSample(instruction + i), m_interpreter->sampler()->sampleSlot());
1096 #endif
1097
1098         m_labels[i] = __ label();
1099         OpcodeID opcodeID = m_interpreter->getOpcodeID(instruction[i].u.opcode);
1100         switch (opcodeID) {
1101         case op_mov: {
1102             unsigned src = instruction[i + 2].u.operand;
1103             if (m_codeBlock->isConstantRegisterIndex(src))
1104                 __ movl_i32r(asInteger(m_codeBlock->getConstant(src)), X86::eax);
1105             else
1106                 emitGetVirtualRegister(src, X86::eax, i);
1107             emitPutVirtualRegister(instruction[i + 1].u.operand);
1108             i += 3;
1109             break;
1110         }
1111         case op_add: {
1112             unsigned dst = instruction[i + 1].u.operand;
1113             unsigned src1 = instruction[i + 2].u.operand;
1114             unsigned src2 = instruction[i + 3].u.operand;
1115
1116             if (JSValue* value = getConstantImmediateNumericArg(src1)) {
1117                 emitGetVirtualRegister(src2, X86::eax, i);
1118                 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
1119                 __ addl_i32r(getDeTaggedConstantImmediate(value), X86::eax);
1120                 m_slowCases.append(SlowCaseEntry(__ jo(), i));
1121                 emitPutVirtualRegister(dst);
1122             } else if (JSValue* value = getConstantImmediateNumericArg(src2)) {
1123                 emitGetVirtualRegister(src1, X86::eax, i);
1124                 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
1125                 __ addl_i32r(getDeTaggedConstantImmediate(value), X86::eax);
1126                 m_slowCases.append(SlowCaseEntry(__ jo(), i));
1127                 emitPutVirtualRegister(dst);
1128             } else {
1129                 OperandTypes types = OperandTypes::fromInt(instruction[i + 4].u.operand);
1130                 if (types.first().mightBeNumber() && types.second().mightBeNumber())
1131                     compileBinaryArithOp(op_add, instruction[i + 1].u.operand, instruction[i + 2].u.operand, instruction[i + 3].u.operand, OperandTypes::fromInt(instruction[i + 4].u.operand), i);
1132                 else {
1133                     emitPutCTIArgFromVirtualRegister(instruction[i + 2].u.operand, 0, X86::ecx);
1134                     emitPutCTIArgFromVirtualRegister(instruction[i + 3].u.operand, 4, X86::ecx);
1135                     emitCTICall(i, Interpreter::cti_op_add);
1136                     emitPutVirtualRegister(instruction[i + 1].u.operand);
1137                 }
1138             }
1139
1140             i += 5;
1141             break;
1142         }
1143         case op_end: {
1144             if (m_codeBlock->needsFullScopeChain)
1145                 emitCTICall(i, Interpreter::cti_op_end);
1146             emitGetVirtualRegister(instruction[i + 1].u.operand, X86::eax, i);
1147             __ pushl_m(RegisterFile::ReturnPC * static_cast<int>(sizeof(Register)), X86::edi);
1148             __ ret();
1149             i += 2;
1150             break;
1151         }
1152         case op_jmp: {
1153             unsigned target = instruction[i + 1].u.operand;
1154             m_jmpTable.append(JmpTable(__ jmp(), i + 1 + target));
1155             i += 2;
1156             break;
1157         }
1158         case op_pre_inc: {
1159             int srcDst = instruction[i + 1].u.operand;
1160             emitGetVirtualRegister(srcDst, X86::eax, i);
1161             emitJumpSlowCaseIfNotImmNum(X86::eax, i);
1162             __ addl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), X86::eax);
1163             m_slowCases.append(SlowCaseEntry(__ jo(), i));
1164             emitPutVirtualRegister(srcDst);
1165             i += 2;
1166             break;
1167         }
1168         case op_loop: {
1169             emitSlowScriptCheck(i);
1170
1171             unsigned target = instruction[i + 1].u.operand;
1172             m_jmpTable.append(JmpTable(__ jmp(), i + 1 + target));
1173             i += 2;
1174             break;
1175         }
1176         case op_loop_if_less: {
1177             emitSlowScriptCheck(i);
1178
1179             unsigned target = instruction[i + 3].u.operand;
1180             JSValue* src2imm = getConstantImmediateNumericArg(instruction[i + 2].u.operand);
1181             if (src2imm) {
1182                 emitGetVirtualRegister(instruction[i + 1].u.operand, X86::edx, i);
1183                 emitJumpSlowCaseIfNotImmNum(X86::edx, i);
1184                 __ cmpl_i32r(asInteger(src2imm), X86::edx);
1185                 m_jmpTable.append(JmpTable(__ jl(), i + 3 + target));
1186             } else {
1187                 emitGetVirtualRegisters(instruction[i + 1].u.operand, X86::eax, instruction[i + 2].u.operand, X86::edx, i);
1188                 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
1189                 emitJumpSlowCaseIfNotImmNum(X86::edx, i);
1190                 __ cmpl_rr(X86::edx, X86::eax);
1191                 m_jmpTable.append(JmpTable(__ jl(), i + 3 + target));
1192             }
1193             i += 4;
1194             break;
1195         }
1196         case op_loop_if_lesseq: {
1197             emitSlowScriptCheck(i);
1198
1199             unsigned target = instruction[i + 3].u.operand;
1200             JSValue* src2imm = getConstantImmediateNumericArg(instruction[i + 2].u.operand);
1201             if (src2imm) {
1202                 emitGetVirtualRegister(instruction[i + 1].u.operand, X86::edx, i);
1203                 emitJumpSlowCaseIfNotImmNum(X86::edx, i);
1204                 __ cmpl_i32r(asInteger(src2imm), X86::edx);
1205                 m_jmpTable.append(JmpTable(__ jle(), i + 3 + target));
1206             } else {
1207                 emitGetVirtualRegisters(instruction[i + 1].u.operand, X86::eax, instruction[i + 2].u.operand, X86::edx, i);
1208                 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
1209                 emitJumpSlowCaseIfNotImmNum(X86::edx, i);
1210                 __ cmpl_rr(X86::edx, X86::eax);
1211                 m_jmpTable.append(JmpTable(__ jle(), i + 3 + target));
1212             }
1213             i += 4;
1214             break;
1215         }
1216         case op_new_object: {
1217             emitCTICall(i, Interpreter::cti_op_new_object);
1218             emitPutVirtualRegister(instruction[i + 1].u.operand);
1219             i += 2;
1220             break;
1221         }
1222         case op_put_by_id: {
1223             // In order to be able to repatch both the Structure, and the object offset, we store one pointer,
1224             // to just after the arguments have been loaded into registers 'hotPathBegin', and we generate code
1225             // such that the Structure & offset are always at the same distance from this.
1226
1227             int baseVReg = instruction[i + 1].u.operand;
1228             emitGetVirtualRegisters(baseVReg, X86::eax, instruction[i + 3].u.operand, X86::edx, i);
1229
1230             ASSERT(m_codeBlock->propertyAccessInstructions[propertyAccessInstructionIndex].bytecodeIndex == i);
1231
1232             // Jump to a slow case if either the base object is an immediate, or if the Structure does not match.
1233             emitJumpSlowCaseIfNotJSCell(X86::eax, i, baseVReg);
1234
1235             JmpDst hotPathBegin = __ label();
1236             m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].hotPathBegin = hotPathBegin;
1237             ++propertyAccessInstructionIndex;
1238
1239             // It is important that the following instruction plants a 32bit immediate, in order that it can be patched over.
1240             __ cmpl_i32m(repatchGetByIdDefaultStructure, FIELD_OFFSET(JSCell, m_structure), X86::eax);
1241             ASSERT(X86Assembler::getDifferenceBetweenLabels(hotPathBegin, __ label()) == repatchOffsetPutByIdStructure);
1242             m_slowCases.append(SlowCaseEntry(__ jne(), i));
1243
1244             // Plant a load from a bogus ofset in the object's property map; we will patch this later, if it is to be used.
1245             __ movl_mr(FIELD_OFFSET(JSObject, m_propertyStorage), X86::eax, X86::eax);
1246             __ movl_rm(X86::edx, repatchGetByIdDefaultOffset, X86::eax);
1247             ASSERT(X86Assembler::getDifferenceBetweenLabels(hotPathBegin, __ label()) == repatchOffsetPutByIdPropertyMapOffset);
1248
1249             i += 8;
1250             break;
1251         }
1252         case op_get_by_id: {
1253             // As for put_by_id, get_by_id requires the offset of the Structure and the offset of the access to be repatched.
1254             // Additionally, for get_by_id we need repatch the offset of the branch to the slow case (we repatch this to jump
1255             // to array-length / prototype access tranpolines, and finally we also the the property-map access offset as a label
1256             // to jump back to if one of these trampolies finds a match.
1257
1258             int baseVReg = instruction[i + 2].u.operand;
1259             emitGetVirtualRegister(baseVReg, X86::eax, i);
1260
1261             ASSERT(m_codeBlock->propertyAccessInstructions[propertyAccessInstructionIndex].bytecodeIndex == i);
1262
1263             emitJumpSlowCaseIfNotJSCell(X86::eax, i, baseVReg);
1264
1265             JmpDst hotPathBegin = __ label();
1266             m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].hotPathBegin = hotPathBegin;
1267             ++propertyAccessInstructionIndex;
1268
1269             __ cmpl_i32m(repatchGetByIdDefaultStructure, FIELD_OFFSET(JSCell, m_structure), X86::eax);
1270             ASSERT(X86Assembler::getDifferenceBetweenLabels(hotPathBegin, __ label()) == repatchOffsetGetByIdStructure);
1271             m_slowCases.append(SlowCaseEntry(__ jne(), i));
1272             ASSERT(X86Assembler::getDifferenceBetweenLabels(hotPathBegin, __ label()) == repatchOffsetGetByIdBranchToSlowCase);
1273
1274             __ movl_mr(FIELD_OFFSET(JSObject, m_propertyStorage), X86::eax, X86::eax);
1275             __ movl_mr(repatchGetByIdDefaultOffset, X86::eax, X86::eax);
1276             ASSERT(X86Assembler::getDifferenceBetweenLabels(hotPathBegin, __ label()) == repatchOffsetGetByIdPropertyMapOffset);
1277             emitPutVirtualRegister(instruction[i + 1].u.operand);
1278
1279             i += 8;
1280             break;
1281         }
1282         case op_instanceof: {
1283             emitGetVirtualRegister(instruction[i + 2].u.operand, X86::eax, i); // value
1284             emitGetVirtualRegister(instruction[i + 3].u.operand, X86::ecx, i); // baseVal
1285             emitGetVirtualRegister(instruction[i + 4].u.operand, X86::edx, i); // proto
1286
1287             // check if any are immediates
1288             __ orl_rr(X86::eax, X86::ecx);
1289             __ orl_rr(X86::edx, X86::ecx);
1290             __ testl_i32r(JSImmediate::TagMask, X86::ecx);
1291
1292             m_slowCases.append(SlowCaseEntry(__ jnz(), i));
1293
1294             // check that all are object type - this is a bit of a bithack to avoid excess branching;
1295             // we check that the sum of the three type codes from Structures is exactly 3 * ObjectType,
1296             // this works because NumberType and StringType are smaller
1297             __ movl_i32r(3 * ObjectType, X86::ecx);
1298             __ movl_mr(FIELD_OFFSET(JSCell, m_structure), X86::eax, X86::eax);
1299             __ movl_mr(FIELD_OFFSET(JSCell, m_structure), X86::edx, X86::edx);
1300             __ subl_mr(FIELD_OFFSET(Structure, m_typeInfo.m_type), X86::eax, X86::ecx);
1301             __ subl_mr(FIELD_OFFSET(Structure, m_typeInfo.m_type), X86::edx, X86::ecx);
1302             emitGetVirtualRegister(instruction[i + 3].u.operand, X86::edx, i); // reload baseVal
1303             __ movl_mr(FIELD_OFFSET(JSCell, m_structure), X86::edx, X86::edx);
1304             __ cmpl_rm(X86::ecx, FIELD_OFFSET(Structure, m_typeInfo.m_type), X86::edx);
1305
1306             m_slowCases.append(SlowCaseEntry(__ jne(), i));
1307
1308             // check that baseVal's flags include ImplementsHasInstance but not OverridesHasInstance
1309             __ movl_mr(FIELD_OFFSET(Structure, m_typeInfo.m_flags), X86::edx, X86::ecx);
1310             __ andl_i32r(ImplementsHasInstance | OverridesHasInstance, X86::ecx);
1311             __ cmpl_i32r(ImplementsHasInstance, X86::ecx);
1312
1313             m_slowCases.append(SlowCaseEntry(__ jne(), i));
1314
1315             emitGetVirtualRegister(instruction[i + 2].u.operand, X86::ecx, i); // reload value
1316             emitGetVirtualRegister(instruction[i + 4].u.operand, X86::edx, i); // reload proto
1317
1318             // optimistically load true result
1319             __ movl_i32r(asInteger(jsBoolean(true)), X86::eax);
1320
1321             JmpDst loop = __ label();
1322
1323             // load value's prototype
1324             __ movl_mr(FIELD_OFFSET(JSCell, m_structure), X86::ecx, X86::ecx);
1325             __ movl_mr(FIELD_OFFSET(Structure, m_prototype), X86::ecx, X86::ecx);
1326             
1327             __ cmpl_rr(X86::ecx, X86::edx);
1328             JmpSrc exit = __ je();
1329
1330             __ cmpl_i32r(asInteger(jsNull()), X86::ecx);
1331             JmpSrc goToLoop = __ jne();
1332             __ link(goToLoop, loop);
1333
1334             __ movl_i32r(asInteger(jsBoolean(false)), X86::eax);
1335
1336             __ link(exit, __ label());
1337
1338             emitPutVirtualRegister(instruction[i + 1].u.operand);
1339
1340             i += 5;
1341             break;
1342         }
1343         case op_del_by_id: {
1344             emitPutCTIArgFromVirtualRegister(instruction[i + 2].u.operand, 0, X86::ecx);
1345             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 3].u.operand]);
1346             emitPutCTIArgConstant(reinterpret_cast<unsigned>(ident), 4);
1347             emitCTICall(i, Interpreter::cti_op_del_by_id);
1348             emitPutVirtualRegister(instruction[i + 1].u.operand);
1349             i += 4;
1350             break;
1351         }
1352         case op_mul: {
1353             unsigned dst = instruction[i + 1].u.operand;
1354             unsigned src1 = instruction[i + 2].u.operand;
1355             unsigned src2 = instruction[i + 3].u.operand;
1356
1357             // For now, only plant a fast int case if the constant operand is greater than zero.
1358             JSValue* src1Value = getConstantImmediateNumericArg(src1);
1359             JSValue* src2Value = getConstantImmediateNumericArg(src2);
1360             int32_t value;
1361             if (src1Value && ((value = JSImmediate::intValue(src1Value)) > 0)) {
1362                 emitGetVirtualRegister(src2, X86::eax, i);
1363                 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
1364                 emitFastArithDeTagImmediate(X86::eax);
1365                 __ imull_i32r(X86::eax, value, X86::eax);
1366                 m_slowCases.append(SlowCaseEntry(__ jo(), i));
1367                 emitFastArithReTagImmediate(X86::eax);
1368                 emitPutVirtualRegister(dst);
1369             } else if (src2Value && ((value = JSImmediate::intValue(src2Value)) > 0)) {
1370                 emitGetVirtualRegister(src1, X86::eax, i);
1371                 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
1372                 emitFastArithDeTagImmediate(X86::eax);
1373                 __ imull_i32r(X86::eax, value, X86::eax);
1374                 m_slowCases.append(SlowCaseEntry(__ jo(), i));
1375                 emitFastArithReTagImmediate(X86::eax);
1376                 emitPutVirtualRegister(dst);
1377             } else
1378                 compileBinaryArithOp(op_mul, instruction[i + 1].u.operand, instruction[i + 2].u.operand, instruction[i + 3].u.operand, OperandTypes::fromInt(instruction[i + 4].u.operand), i);
1379
1380             i += 5;
1381             break;
1382         }
1383         case op_new_func: {
1384             FuncDeclNode* func = (m_codeBlock->functions[instruction[i + 2].u.operand]).get();
1385             emitPutCTIArgConstant(reinterpret_cast<unsigned>(func), 0);
1386             emitCTICall(i, Interpreter::cti_op_new_func);
1387             emitPutVirtualRegister(instruction[i + 1].u.operand);
1388             i += 3;
1389             break;
1390         }
1391         case op_call:
1392         case op_call_eval:
1393         case op_construct: {
1394             compileOpCall(opcodeID, instruction + i, i, callLinkInfoIndex++);
1395             i += (opcodeID == op_construct ? 7 : 5);
1396             break;
1397         }
1398         case op_get_global_var: {
1399             JSVariableObject* globalObject = static_cast<JSVariableObject*>(instruction[i + 2].u.jsCell);
1400             __ movl_i32r(asInteger(globalObject), X86::eax);
1401             emitGetVariableObjectRegister(X86::eax, instruction[i + 3].u.operand, X86::eax);
1402             emitPutVirtualRegister(instruction[i + 1].u.operand);
1403             i += 4;
1404             break;
1405         }
1406         case op_put_global_var: {
1407             emitGetVirtualRegister(instruction[i + 3].u.operand, X86::edx, i);
1408             JSVariableObject* globalObject = static_cast<JSVariableObject*>(instruction[i + 1].u.jsCell);
1409             __ movl_i32r(asInteger(globalObject), X86::eax);
1410             emitPutVariableObjectRegister(X86::edx, X86::eax, instruction[i + 2].u.operand);
1411             i += 4;
1412             break;
1413         }
1414         case op_get_scoped_var: {
1415             int skip = instruction[i + 3].u.operand + m_codeBlock->needsFullScopeChain;
1416
1417             emitGetVirtualRegister(RegisterFile::ScopeChain, X86::eax, i);
1418             while (skip--)
1419                 __ movl_mr(FIELD_OFFSET(ScopeChainNode, next), X86::eax, X86::eax);
1420
1421             __ movl_mr(FIELD_OFFSET(ScopeChainNode, object), X86::eax, X86::eax);
1422             emitGetVariableObjectRegister(X86::eax, instruction[i + 2].u.operand, X86::eax);
1423             emitPutVirtualRegister(instruction[i + 1].u.operand);
1424             i += 4;
1425             break;
1426         }
1427         case op_put_scoped_var: {
1428             int skip = instruction[i + 2].u.operand + m_codeBlock->needsFullScopeChain;
1429
1430             emitGetVirtualRegister(RegisterFile::ScopeChain, X86::edx, i);
1431             emitGetVirtualRegister(instruction[i + 3].u.operand, X86::eax, i);
1432             while (skip--)
1433                 __ movl_mr(FIELD_OFFSET(ScopeChainNode, next), X86::edx, X86::edx);
1434
1435             __ movl_mr(FIELD_OFFSET(ScopeChainNode, object), X86::edx, X86::edx);
1436             emitPutVariableObjectRegister(X86::eax, X86::edx, instruction[i + 1].u.operand);
1437             i += 4;
1438             break;
1439         }
1440         case op_tear_off_activation: {
1441             emitPutCTIArgFromVirtualRegister(instruction[i + 1].u.operand, 0, X86::ecx);
1442             emitCTICall(i, Interpreter::cti_op_tear_off_activation);
1443             i += 2;
1444             break;
1445         }
1446         case op_tear_off_arguments: {
1447             emitCTICall(i, Interpreter::cti_op_tear_off_arguments);
1448             i += 1;
1449             break;
1450         }
1451         case op_ret: {
1452             // We could JIT generate the deref, only calling out to C when the refcount hits zero.
1453             if (m_codeBlock->needsFullScopeChain)
1454                 emitCTICall(i, Interpreter::cti_op_ret_scopeChain);
1455
1456             // Return the result in %eax.
1457             emitGetVirtualRegister(instruction[i + 1].u.operand, X86::eax, i);
1458
1459             // Grab the return address.
1460             emitGetVirtualRegister(RegisterFile::ReturnPC, X86::edx, i);
1461
1462             // Restore our caller's "r".
1463             emitGetVirtualRegister(RegisterFile::CallerFrame, X86::edi, i);
1464
1465             // Return.
1466             __ pushl_r(X86::edx);
1467             __ ret();
1468
1469             i += 2;
1470             break;
1471         }
1472         case op_new_array: {
1473             __ leal_mr(sizeof(Register) * instruction[i + 2].u.operand, X86::edi, X86::edx);
1474             emitPutCTIArg(X86::edx, 0);
1475             emitPutCTIArgConstant(instruction[i + 3].u.operand, 4);
1476             emitCTICall(i, Interpreter::cti_op_new_array);
1477             emitPutVirtualRegister(instruction[i + 1].u.operand);
1478             i += 4;
1479             break;
1480         }
1481         case op_resolve: {
1482             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
1483             emitPutCTIArgConstant(reinterpret_cast<unsigned>(ident), 0);
1484             emitCTICall(i, Interpreter::cti_op_resolve);
1485             emitPutVirtualRegister(instruction[i + 1].u.operand);
1486             i += 3;
1487             break;
1488         }
1489         case op_construct_verify: {
1490             emitGetVirtualRegister(instruction[i + 1].u.operand, X86::eax, i);
1491
1492             __ testl_i32r(JSImmediate::TagMask, X86::eax);
1493             JmpSrc isImmediate = __ jne();
1494             __ movl_mr(FIELD_OFFSET(JSCell, m_structure), X86::eax, X86::ecx);
1495             __ cmpl_i32m(ObjectType, FIELD_OFFSET(Structure, m_typeInfo) + FIELD_OFFSET(TypeInfo, m_type), X86::ecx);
1496             JmpSrc isObject = __ je();
1497
1498             __ link(isImmediate, __ label());
1499             emitGetVirtualRegister(instruction[i + 2].u.operand, X86::eax, i);
1500             emitPutVirtualRegister(instruction[i + 1].u.operand);
1501             __ link(isObject, __ label());
1502
1503             i += 3;
1504             break;
1505         }
1506         case op_get_by_val: {
1507             emitGetVirtualRegisters(instruction[i + 2].u.operand, X86::eax, instruction[i + 3].u.operand, X86::edx, i);
1508             emitJumpSlowCaseIfNotImmNum(X86::edx, i);
1509             emitFastArithImmToInt(X86::edx);
1510             __ testl_i32r(JSImmediate::TagMask, X86::eax);
1511             m_slowCases.append(SlowCaseEntry(__ jne(), i));
1512             __ cmpl_i32m(reinterpret_cast<unsigned>(m_interpreter->m_jsArrayVptr), X86::eax);
1513             m_slowCases.append(SlowCaseEntry(__ jne(), i));
1514
1515             // This is an array; get the m_storage pointer into ecx, then check if the index is below the fast cutoff
1516             __ movl_mr(FIELD_OFFSET(JSArray, m_storage), X86::eax, X86::ecx);
1517             __ cmpl_rm(X86::edx, FIELD_OFFSET(JSArray, m_fastAccessCutoff), X86::eax);
1518             m_slowCases.append(SlowCaseEntry(__ jbe(), i));
1519
1520             // Get the value from the vector
1521             __ movl_mr(FIELD_OFFSET(ArrayStorage, m_vector[0]), X86::ecx, X86::edx, sizeof(JSValue*), X86::eax);
1522             emitPutVirtualRegister(instruction[i + 1].u.operand);
1523             i += 4;
1524             break;
1525         }
1526         case op_resolve_func: {
1527             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 3].u.operand]);
1528             emitPutCTIArgConstant(reinterpret_cast<unsigned>(ident), 0);
1529             emitCTICall(i, Interpreter::cti_op_resolve_func);
1530             emitPutVirtualRegister(instruction[i + 2].u.operand, X86::edx);
1531             emitPutVirtualRegister(instruction[i + 1].u.operand);
1532             i += 4;
1533             break;
1534         }
1535         case op_sub: {
1536             compileBinaryArithOp(op_sub, instruction[i + 1].u.operand, instruction[i + 2].u.operand, instruction[i + 3].u.operand, OperandTypes::fromInt(instruction[i + 4].u.operand), i);
1537             i += 5;
1538             break;
1539         }
1540         case op_put_by_val: {
1541             emitGetVirtualRegisters(instruction[i + 1].u.operand, X86::eax, instruction[i + 2].u.operand, X86::edx, i);
1542             emitJumpSlowCaseIfNotImmNum(X86::edx, i);
1543             emitFastArithImmToInt(X86::edx);
1544             __ testl_i32r(JSImmediate::TagMask, X86::eax);
1545             m_slowCases.append(SlowCaseEntry(__ jne(), i));
1546             __ cmpl_i32m(reinterpret_cast<unsigned>(m_interpreter->m_jsArrayVptr), X86::eax);
1547             m_slowCases.append(SlowCaseEntry(__ jne(), i));
1548
1549             // This is an array; get the m_storage pointer into ecx, then check if the index is below the fast cutoff
1550             __ movl_mr(FIELD_OFFSET(JSArray, m_storage), X86::eax, X86::ecx);
1551             __ cmpl_rm(X86::edx, FIELD_OFFSET(JSArray, m_fastAccessCutoff), X86::eax);
1552             JmpSrc inFastVector = __ ja();
1553             // No; oh well, check if the access if within the vector - if so, we may still be okay.
1554             __ cmpl_rm(X86::edx, FIELD_OFFSET(ArrayStorage, m_vectorLength), X86::ecx);
1555             m_slowCases.append(SlowCaseEntry(__ jbe(), i));
1556
1557             // 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.
1558             // 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. 
1559             __ cmpl_i8m(0, FIELD_OFFSET(ArrayStorage, m_vector[0]), X86::ecx, X86::edx, sizeof(JSValue*));
1560             m_slowCases.append(SlowCaseEntry(__ je(), i));
1561
1562             // All good - put the value into the array.
1563             __ link(inFastVector, __ label());
1564             emitGetVirtualRegister(instruction[i + 3].u.operand, X86::eax, i);
1565             __ movl_rm(X86::eax, FIELD_OFFSET(ArrayStorage, m_vector[0]), X86::ecx, X86::edx, sizeof(JSValue*));
1566             i += 4;
1567             break;
1568         }
1569         CTI_COMPILE_BINARY_OP(op_lesseq)
1570         case op_loop_if_true: {
1571             emitSlowScriptCheck(i);
1572
1573             unsigned target = instruction[i + 2].u.operand;
1574             emitGetVirtualRegister(instruction[i + 1].u.operand, X86::eax, i);
1575
1576             __ cmpl_i32r(asInteger(JSImmediate::zeroImmediate()), X86::eax);
1577             JmpSrc isZero = __ je();
1578             __ testl_i32r(JSImmediate::TagBitTypeInteger, X86::eax);
1579             m_jmpTable.append(JmpTable(__ jne(), i + 2 + target));
1580
1581             __ cmpl_i32r(asInteger(JSImmediate::trueImmediate()), X86::eax);
1582             m_jmpTable.append(JmpTable(__ je(), i + 2 + target));
1583             __ cmpl_i32r(asInteger(JSImmediate::falseImmediate()), X86::eax);
1584             m_slowCases.append(SlowCaseEntry(__ jne(), i));
1585
1586             __ link(isZero, __ label());
1587             i += 3;
1588             break;
1589         };
1590         case op_resolve_base: {
1591             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
1592             emitPutCTIArgConstant(reinterpret_cast<unsigned>(ident), 0);
1593             emitCTICall(i, Interpreter::cti_op_resolve_base);
1594             emitPutVirtualRegister(instruction[i + 1].u.operand);
1595             i += 3;
1596             break;
1597         }
1598         case op_negate: {
1599             int srcVReg = instruction[i + 2].u.operand;
1600             emitGetVirtualRegister(srcVReg, X86::eax, i);
1601
1602             __ testl_i32r(JSImmediate::TagBitTypeInteger, X86::eax);
1603             JmpSrc notImmediate = __ je();
1604
1605             __ cmpl_i32r(JSImmediate::TagBitTypeInteger, X86::eax);
1606             JmpSrc zeroImmediate = __ je();
1607             emitFastArithImmToInt(X86::eax);
1608             __ negl_r(X86::eax); // This can't overflow as we only have a 31bit int at this point
1609             JmpSrc overflow = emitArithIntToImmWithJump(X86::eax);
1610             emitPutVirtualRegister(instruction[i + 1].u.operand);
1611             JmpSrc immediateNegateSuccess = __ jmp();
1612
1613             if (!isSSE2Present()) {
1614                 __ link(zeroImmediate, __ label());
1615                 __ link(overflow, __ label());
1616                 __ link(notImmediate, __ label());
1617                 emitPutCTIArgFromVirtualRegister(instruction[i + 2].u.operand, 0, X86::ecx);
1618                 emitCTICall(i, Interpreter::cti_op_negate);
1619                 emitPutVirtualRegister(instruction[i + 1].u.operand);
1620             } else {
1621                 // Slow case immediates
1622                 m_slowCases.append(SlowCaseEntry(zeroImmediate, i));
1623                 m_slowCases.append(SlowCaseEntry(overflow, i));
1624                 __ link(notImmediate, __ label());
1625                 ResultType resultType(instruction[i + 3].u.resultType);
1626                 if (!resultType.definitelyIsNumber()) {
1627                     emitJumpSlowCaseIfNotJSCell(X86::eax, i, srcVReg);
1628                     Structure* numberStructure = m_globalData->numberStructure.get();
1629                     __ cmpl_i32m(reinterpret_cast<unsigned>(numberStructure), FIELD_OFFSET(JSCell, m_structure), X86::eax);
1630                     m_slowCases.append(SlowCaseEntry(__ jne(), i));
1631                 }
1632                 __ movsd_mr(FIELD_OFFSET(JSNumberCell, m_value), X86::eax, X86::xmm0);
1633                 // We need 3 copies of the sign bit mask so we can assure alignment and pad for the 128bit load
1634                 static double doubleSignBit[] = { -0.0, -0.0, -0.0 };
1635                 __ xorpd_mr((void*)((((uintptr_t)doubleSignBit)+15)&~15), X86::xmm0);
1636                 JmpSrc wasCell;
1637                 if (!resultType.isReusableNumber())
1638                     emitAllocateNumber(m_globalData, i);
1639
1640                 putDoubleResultToJSNumberCellOrJSImmediate(X86::xmm0, X86::eax, instruction[i + 1].u.operand, &wasCell,
1641                                                            X86::xmm1, X86::ecx, X86::edx);
1642                 __ link(wasCell, __ label());
1643             }
1644             __ link(immediateNegateSuccess, __ label());
1645             i += 4;
1646             break;
1647         }
1648         case op_resolve_skip: {
1649             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
1650             emitPutCTIArgConstant(reinterpret_cast<unsigned>(ident), 0);
1651             emitPutCTIArgConstant(instruction[i + 3].u.operand + m_codeBlock->needsFullScopeChain, 4);
1652             emitCTICall(i, Interpreter::cti_op_resolve_skip);
1653             emitPutVirtualRegister(instruction[i + 1].u.operand);
1654             i += 4;
1655             break;
1656         }
1657         case op_resolve_global: {
1658             // Fast case
1659             unsigned globalObject = asInteger(instruction[i + 2].u.jsCell);
1660             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 3].u.operand]);
1661             void* structureAddress = reinterpret_cast<void*>(instruction + i + 4);
1662             void* offsetAddr = reinterpret_cast<void*>(instruction + i + 5);
1663
1664             // Check Structure of global object
1665             __ movl_i32r(globalObject, X86::eax);
1666             __ movl_mr(structureAddress, X86::edx);
1667             __ cmpl_rm(X86::edx, FIELD_OFFSET(JSCell, m_structure), X86::eax);
1668             JmpSrc noMatch = __ jne(); // Structures don't match
1669
1670             // Load cached property
1671             __ movl_mr(FIELD_OFFSET(JSGlobalObject, m_propertyStorage), X86::eax, X86::eax);
1672             __ movl_mr(offsetAddr, X86::edx);
1673             __ movl_mr(0, X86::eax, X86::edx, sizeof(JSValue*), X86::eax);
1674             emitPutVirtualRegister(instruction[i + 1].u.operand);
1675             JmpSrc end = __ jmp();
1676
1677             // Slow case
1678             __ link(noMatch, __ label());
1679             emitPutCTIArgConstant(globalObject, 0);
1680             emitPutCTIArgConstant(reinterpret_cast<unsigned>(ident), 4);
1681             emitPutCTIArgConstant(reinterpret_cast<unsigned>(instruction + i), 8);
1682             emitCTICall(i, Interpreter::cti_op_resolve_global);
1683             emitPutVirtualRegister(instruction[i + 1].u.operand);
1684             __ link(end, __ label());
1685             i += 6;
1686             break;
1687         }
1688         CTI_COMPILE_BINARY_OP(op_div)
1689         case op_pre_dec: {
1690             int srcDst = instruction[i + 1].u.operand;
1691             emitGetVirtualRegister(srcDst, X86::eax, i);
1692             emitJumpSlowCaseIfNotImmNum(X86::eax, i);
1693             __ subl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), X86::eax);
1694             m_slowCases.append(SlowCaseEntry(__ jo(), i));
1695             emitPutVirtualRegister(srcDst);
1696             i += 2;
1697             break;
1698         }
1699         case op_jnless: {
1700             unsigned target = instruction[i + 3].u.operand;
1701             JSValue* src2imm = getConstantImmediateNumericArg(instruction[i + 2].u.operand);
1702             if (src2imm) {
1703                 emitGetVirtualRegister(instruction[i + 1].u.operand, X86::edx, i);
1704                 emitJumpSlowCaseIfNotImmNum(X86::edx, i);
1705                 __ cmpl_i32r(asInteger(src2imm), X86::edx);
1706                 m_jmpTable.append(JmpTable(__ jge(), i + 3 + target));
1707             } else {
1708                 emitGetVirtualRegisters(instruction[i + 1].u.operand, X86::eax, instruction[i + 2].u.operand, X86::edx, i);
1709                 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
1710                 emitJumpSlowCaseIfNotImmNum(X86::edx, i);
1711                 __ cmpl_rr(X86::edx, X86::eax);
1712                 m_jmpTable.append(JmpTable(__ jge(), i + 3 + target));
1713             }
1714             i += 4;
1715             break;
1716         }
1717         case op_not: {
1718             emitGetVirtualRegister(instruction[i + 2].u.operand, X86::eax, i);
1719             __ xorl_i8r(JSImmediate::FullTagTypeBool, X86::eax);
1720             __ testl_i32r(JSImmediate::FullTagTypeMask, X86::eax); // i8?
1721             m_slowCases.append(SlowCaseEntry(__ jne(), i));
1722             __ xorl_i8r((JSImmediate::FullTagTypeBool | JSImmediate::ExtendedPayloadBitBoolValue), X86::eax);
1723             emitPutVirtualRegister(instruction[i + 1].u.operand);
1724             i += 3;
1725             break;
1726         }
1727         case op_jfalse: {
1728             unsigned target = instruction[i + 2].u.operand;
1729             emitGetVirtualRegister(instruction[i + 1].u.operand, X86::eax, i);
1730
1731             __ cmpl_i32r(asInteger(JSImmediate::zeroImmediate()), X86::eax);
1732             m_jmpTable.append(JmpTable(__ je(), i + 2 + target));
1733             __ testl_i32r(JSImmediate::TagBitTypeInteger, X86::eax);
1734             JmpSrc isNonZero = __ jne();
1735
1736             __ cmpl_i32r(asInteger(JSImmediate::falseImmediate()), X86::eax);
1737             m_jmpTable.append(JmpTable(__ je(), i + 2 + target));
1738             __ cmpl_i32r(asInteger(JSImmediate::trueImmediate()), X86::eax);
1739             m_slowCases.append(SlowCaseEntry(__ jne(), i));
1740
1741             __ link(isNonZero, __ label());
1742             i += 3;
1743             break;
1744         };
1745         case op_jeq_null: {
1746             unsigned src = instruction[i + 1].u.operand;
1747             unsigned target = instruction[i + 2].u.operand;
1748
1749             emitGetVirtualRegister(src, X86::eax, i);
1750             __ testl_i32r(JSImmediate::TagMask, X86::eax);
1751             JmpSrc isImmediate = __ jnz();
1752
1753             __ movl_mr(FIELD_OFFSET(JSCell, m_structure), X86::eax, X86::ecx);
1754             __ testl_i32m(MasqueradesAsUndefined, FIELD_OFFSET(Structure, m_typeInfo.m_flags), X86::ecx);
1755             __ setnz_r(X86::eax);
1756
1757             JmpSrc wasNotImmediate = __ jmp();
1758
1759             __ link(isImmediate, __ label());
1760
1761             __ movl_i32r(~JSImmediate::ExtendedTagBitUndefined, X86::ecx);
1762             __ andl_rr(X86::eax, X86::ecx);
1763             __ cmpl_i32r(JSImmediate::FullTagTypeNull, X86::ecx);
1764             __ sete_r(X86::eax);
1765
1766             __ link(wasNotImmediate, __ label());
1767
1768             __ movzbl_rr(X86::eax, X86::eax);
1769             __ cmpl_i32r(0, X86::eax);
1770             m_jmpTable.append(JmpTable(__ jnz(), i + 2 + target));            
1771
1772             i += 3;
1773             break;
1774         };
1775         case op_jneq_null: {
1776             unsigned src = instruction[i + 1].u.operand;
1777             unsigned target = instruction[i + 2].u.operand;
1778
1779             emitGetVirtualRegister(src, X86::eax, i);
1780             __ testl_i32r(JSImmediate::TagMask, X86::eax);
1781             JmpSrc isImmediate = __ jnz();
1782
1783             __ movl_mr(FIELD_OFFSET(JSCell, m_structure), X86::eax, X86::ecx);
1784             __ testl_i32m(MasqueradesAsUndefined, FIELD_OFFSET(Structure, m_typeInfo.m_flags), X86::ecx);
1785             __ setz_r(X86::eax);
1786
1787             JmpSrc wasNotImmediate = __ jmp();
1788
1789             __ link(isImmediate, __ label());
1790
1791             __ movl_i32r(~JSImmediate::ExtendedTagBitUndefined, X86::ecx);
1792             __ andl_rr(X86::eax, X86::ecx);
1793             __ cmpl_i32r(JSImmediate::FullTagTypeNull, X86::ecx);
1794             __ setne_r(X86::eax);
1795
1796             __ link(wasNotImmediate, __ label());
1797
1798             __ movzbl_rr(X86::eax, X86::eax);
1799             __ cmpl_i32r(0, X86::eax);
1800             m_jmpTable.append(JmpTable(__ jnz(), i + 2 + target));            
1801
1802             i += 3;
1803             break;
1804         }
1805         case op_post_inc: {
1806             int srcDst = instruction[i + 2].u.operand;
1807             emitGetVirtualRegister(srcDst, X86::eax, i);
1808             __ movl_rr(X86::eax, X86::edx);
1809             emitJumpSlowCaseIfNotImmNum(X86::eax, i);
1810             __ addl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), X86::edx);
1811             m_slowCases.append(SlowCaseEntry(__ jo(), i));
1812             emitPutVirtualRegister(srcDst, X86::edx);
1813             emitPutVirtualRegister(instruction[i + 1].u.operand);
1814             i += 3;
1815             break;
1816         }
1817         case op_unexpected_load: {
1818             JSValue* v = m_codeBlock->unexpectedConstants[instruction[i + 2].u.operand];
1819             __ movl_i32r(asInteger(v), X86::eax);
1820             emitPutVirtualRegister(instruction[i + 1].u.operand);
1821             i += 3;
1822             break;
1823         }
1824         case op_jsr: {
1825             int retAddrDst = instruction[i + 1].u.operand;
1826             int target = instruction[i + 2].u.operand;
1827             __ movl_i32m(0, sizeof(Register) * retAddrDst, X86::edi);
1828             JmpDst addrPosition = __ label();
1829             m_jmpTable.append(JmpTable(__ jmp(), i + 2 + target));
1830             JmpDst sretTarget = __ label();
1831             m_jsrSites.append(JSRInfo(addrPosition, sretTarget));
1832             i += 3;
1833             break;
1834         }
1835         case op_sret: {
1836             __ jmp_m(sizeof(Register) * instruction[i + 1].u.operand, X86::edi);
1837             i += 2;
1838             break;
1839         }
1840         case op_eq: {
1841             emitGetVirtualRegisters(instruction[i + 2].u.operand, X86::eax, instruction[i + 3].u.operand, X86::edx, i);
1842             emitJumpSlowCaseIfNotImmNums(X86::eax, X86::edx, i);
1843             __ cmpl_rr(X86::edx, X86::eax);
1844             __ sete_r(X86::eax);
1845             __ movzbl_rr(X86::eax, X86::eax);
1846             emitTagAsBoolImmediate(X86::eax);
1847             emitPutVirtualRegister(instruction[i + 1].u.operand);
1848             i += 4;
1849             break;
1850         }
1851         case op_lshift: {
1852             emitGetVirtualRegisters(instruction[i + 2].u.operand, X86::eax, instruction[i + 3].u.operand, X86::ecx, i);
1853             emitJumpSlowCaseIfNotImmNum(X86::eax, i);
1854             emitJumpSlowCaseIfNotImmNum(X86::ecx, i);
1855             emitFastArithImmToInt(X86::eax);
1856             emitFastArithImmToInt(X86::ecx);
1857             __ shll_CLr(X86::eax);
1858             emitFastArithIntToImmOrSlowCase(X86::eax, i);
1859             emitPutVirtualRegister(instruction[i + 1].u.operand);
1860             i += 4;
1861             break;
1862         }
1863         case op_bitand: {
1864             unsigned src1 = instruction[i + 2].u.operand;
1865             unsigned src2 = instruction[i + 3].u.operand;
1866             unsigned dst = instruction[i + 1].u.operand;
1867             if (JSValue* value = getConstantImmediateNumericArg(src1)) {
1868                 emitGetVirtualRegister(src2, X86::eax, i);
1869                 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
1870                 __ andl_i32r(asInteger(value), X86::eax); // FIXME: make it more obvious this is relying on the format of JSImmediate
1871                 emitPutVirtualRegister(dst);
1872             } else if (JSValue* value = getConstantImmediateNumericArg(src2)) {
1873                 emitGetVirtualRegister(src1, X86::eax, i);
1874                 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
1875                 __ andl_i32r(asInteger(value), X86::eax);
1876                 emitPutVirtualRegister(dst);
1877             } else {
1878                 emitGetVirtualRegisters(src1, X86::eax, src2, X86::edx, i);
1879                 __ andl_rr(X86::edx, X86::eax);
1880                 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
1881                 emitPutVirtualRegister(dst);
1882             }
1883             i += 5;
1884             break;
1885         }
1886         case op_rshift: {
1887             emitGetVirtualRegisters(instruction[i + 2].u.operand, X86::eax, instruction[i + 3].u.operand, X86::ecx, i);
1888             emitJumpSlowCaseIfNotImmNum(X86::eax, i);
1889             emitJumpSlowCaseIfNotImmNum(X86::ecx, i);
1890             emitFastArithImmToInt(X86::ecx);
1891             __ sarl_CLr(X86::eax);
1892             emitFastArithPotentiallyReTagImmediate(X86::eax);
1893             emitPutVirtualRegister(instruction[i + 1].u.operand);
1894             i += 4;
1895             break;
1896         }
1897         case op_bitnot: {
1898             emitGetVirtualRegister(instruction[i + 2].u.operand, X86::eax, i);
1899             emitJumpSlowCaseIfNotImmNum(X86::eax, i);
1900             __ xorl_i8r(~JSImmediate::TagBitTypeInteger, X86::eax);
1901             emitPutVirtualRegister(instruction[i + 1].u.operand);
1902             i += 3;
1903             break;
1904         }
1905         case op_resolve_with_base: {
1906             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 3].u.operand]);
1907             emitPutCTIArgConstant(reinterpret_cast<unsigned>(ident), 0);
1908             emitCTICall(i, Interpreter::cti_op_resolve_with_base);
1909             emitPutVirtualRegister(instruction[i + 2].u.operand, X86::edx);
1910             emitPutVirtualRegister(instruction[i + 1].u.operand);
1911             i += 4;
1912             break;
1913         }
1914         case op_new_func_exp: {
1915             FuncExprNode* func = (m_codeBlock->functionExpressions[instruction[i + 2].u.operand]).get();
1916             emitPutCTIArgConstant(reinterpret_cast<unsigned>(func), 0);
1917             emitCTICall(i, Interpreter::cti_op_new_func_exp);
1918             emitPutVirtualRegister(instruction[i + 1].u.operand);
1919             i += 3;
1920             break;
1921         }
1922         case op_mod: {
1923             emitGetVirtualRegisters(instruction[i + 2].u.operand, X86::eax, instruction[i + 3].u.operand, X86::ecx, i);
1924             emitJumpSlowCaseIfNotImmNum(X86::eax, i);
1925             emitJumpSlowCaseIfNotImmNum(X86::ecx, i);
1926             emitFastArithDeTagImmediate(X86::eax);
1927             m_slowCases.append(SlowCaseEntry(emitFastArithDeTagImmediateJumpIfZero(X86::ecx), i));
1928             __ cdq();
1929             __ idivl_r(X86::ecx);
1930             emitFastArithReTagImmediate(X86::edx);
1931             __ movl_rr(X86::edx, X86::eax);
1932             emitPutVirtualRegister(instruction[i + 1].u.operand);
1933             i += 4;
1934             break;
1935         }
1936         case op_jtrue: {
1937             unsigned target = instruction[i + 2].u.operand;
1938             emitGetVirtualRegister(instruction[i + 1].u.operand, X86::eax, i);
1939
1940             __ cmpl_i32r(asInteger(JSImmediate::zeroImmediate()), X86::eax);
1941             JmpSrc isZero = __ je();
1942             __ testl_i32r(JSImmediate::TagBitTypeInteger, X86::eax);
1943             m_jmpTable.append(JmpTable(__ jne(), i + 2 + target));
1944
1945             __ cmpl_i32r(asInteger(JSImmediate::trueImmediate()), X86::eax);
1946             m_jmpTable.append(JmpTable(__ je(), i + 2 + target));
1947             __ cmpl_i32r(asInteger(JSImmediate::falseImmediate()), X86::eax);
1948             m_slowCases.append(SlowCaseEntry(__ jne(), i));
1949
1950             __ link(isZero, __ label());
1951             i += 3;
1952             break;
1953         }
1954         CTI_COMPILE_BINARY_OP(op_less)
1955         case op_neq: {
1956             emitGetVirtualRegisters(instruction[i + 2].u.operand, X86::eax, instruction[i + 3].u.operand, X86::edx, i);
1957             emitJumpSlowCaseIfNotImmNums(X86::eax, X86::edx, i);
1958             __ cmpl_rr(X86::eax, X86::edx);
1959
1960             __ setne_r(X86::eax);
1961             __ movzbl_rr(X86::eax, X86::eax);
1962             emitTagAsBoolImmediate(X86::eax);
1963
1964             emitPutVirtualRegister(instruction[i + 1].u.operand);
1965
1966             i += 4;
1967             break;
1968         }
1969         case op_post_dec: {
1970             int srcDst = instruction[i + 2].u.operand;
1971             emitGetVirtualRegister(srcDst, X86::eax, i);
1972             __ movl_rr(X86::eax, X86::edx);
1973             emitJumpSlowCaseIfNotImmNum(X86::eax, i);
1974             __ subl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), X86::edx);
1975             m_slowCases.append(SlowCaseEntry(__ jo(), i));
1976             emitPutVirtualRegister(srcDst, X86::edx);
1977             emitPutVirtualRegister(instruction[i + 1].u.operand);
1978             i += 3;
1979             break;
1980         }
1981         CTI_COMPILE_BINARY_OP(op_urshift)
1982         case op_bitxor: {
1983             emitGetVirtualRegisters(instruction[i + 2].u.operand, X86::eax, instruction[i + 3].u.operand, X86::edx, i);
1984             emitJumpSlowCaseIfNotImmNums(X86::eax, X86::edx, i);
1985             __ xorl_rr(X86::edx, X86::eax);
1986             emitFastArithReTagImmediate(X86::eax);
1987             emitPutVirtualRegister(instruction[i + 1].u.operand);
1988             i += 5;
1989             break;
1990         }
1991         case op_new_regexp: {
1992             RegExp* regExp = m_codeBlock->regexps[instruction[i + 2].u.operand].get();
1993             emitPutCTIArgConstant(reinterpret_cast<unsigned>(regExp), 0);
1994             emitCTICall(i, Interpreter::cti_op_new_regexp);
1995             emitPutVirtualRegister(instruction[i + 1].u.operand);
1996             i += 3;
1997             break;
1998         }
1999         case op_bitor: {
2000             emitGetVirtualRegisters(instruction[i + 2].u.operand, X86::eax, instruction[i + 3].u.operand, X86::edx, i);
2001             emitJumpSlowCaseIfNotImmNums(X86::eax, X86::edx, i);
2002             __ orl_rr(X86::edx, X86::eax);
2003             emitPutVirtualRegister(instruction[i + 1].u.operand);
2004             i += 5;
2005             break;
2006         }
2007         case op_throw: {
2008             emitPutCTIArgFromVirtualRegister(instruction[i + 1].u.operand, 0, X86::ecx);
2009             emitCTICall(i, Interpreter::cti_op_throw);
2010             __ addl_i8r(0x20, X86::esp);
2011             __ popl_r(X86::ebx);
2012             __ popl_r(X86::edi);
2013             __ popl_r(X86::esi);
2014             __ ret();
2015             i += 2;
2016             break;
2017         }
2018         case op_get_pnames: {
2019             emitPutCTIArgFromVirtualRegister(instruction[i + 2].u.operand, 0, X86::ecx);
2020             emitCTICall(i, Interpreter::cti_op_get_pnames);
2021             emitPutVirtualRegister(instruction[i + 1].u.operand);
2022             i += 3;
2023             break;
2024         }
2025         case op_next_pname: {
2026             emitPutCTIArgFromVirtualRegister(instruction[i + 2].u.operand, 0, X86::ecx);
2027             unsigned target = instruction[i + 3].u.operand;
2028             emitCTICall(i, Interpreter::cti_op_next_pname);
2029             __ testl_rr(X86::eax, X86::eax);
2030             JmpSrc endOfIter = __ je();
2031             emitPutVirtualRegister(instruction[i + 1].u.operand);
2032             m_jmpTable.append(JmpTable(__ jmp(), i + 3 + target));
2033             __ link(endOfIter, __ label());
2034             i += 4;
2035             break;
2036         }
2037         case op_push_scope: {
2038             emitPutCTIArgFromVirtualRegister(instruction[i + 1].u.operand, 0, X86::ecx);
2039             emitCTICall(i, Interpreter::cti_op_push_scope);
2040             i += 2;
2041             break;
2042         }
2043         case op_pop_scope: {
2044             emitCTICall(i, Interpreter::cti_op_pop_scope);
2045             i += 1;
2046             break;
2047         }
2048         CTI_COMPILE_UNARY_OP(op_typeof)
2049         CTI_COMPILE_UNARY_OP(op_is_undefined)
2050         CTI_COMPILE_UNARY_OP(op_is_boolean)
2051         CTI_COMPILE_UNARY_OP(op_is_number)
2052         CTI_COMPILE_UNARY_OP(op_is_string)
2053         CTI_COMPILE_UNARY_OP(op_is_object)
2054         CTI_COMPILE_UNARY_OP(op_is_function)
2055         case op_stricteq: {
2056             compileOpStrictEq(instruction + i, i, OpStrictEq);
2057             i += 4;
2058             break;
2059         }
2060         case op_nstricteq: {
2061             compileOpStrictEq(instruction + i, i, OpNStrictEq);
2062             i += 4;
2063             break;
2064         }
2065         case op_to_jsnumber: {
2066             int srcVReg = instruction[i + 2].u.operand;
2067             emitGetVirtualRegister(srcVReg, X86::eax, i);
2068             
2069             __ testl_i32r(JSImmediate::TagBitTypeInteger, X86::eax);
2070             JmpSrc wasImmediate = __ jnz();
2071
2072             emitJumpSlowCaseIfNotJSCell(X86::eax, i, srcVReg);
2073
2074             __ movl_mr(FIELD_OFFSET(JSCell, m_structure), X86::eax, X86::ecx);
2075             __ cmpl_i32m(NumberType, FIELD_OFFSET(Structure, m_typeInfo.m_type), X86::ecx);
2076             
2077             m_slowCases.append(SlowCaseEntry(__ jne(), i));
2078             
2079             __ link(wasImmediate, __ label());
2080
2081             emitPutVirtualRegister(instruction[i + 1].u.operand);
2082             i += 3;
2083             break;
2084         }
2085         case op_in: {
2086             emitPutCTIArgFromVirtualRegister(instruction[i + 2].u.operand, 0, X86::ecx);
2087             emitPutCTIArgFromVirtualRegister(instruction[i + 3].u.operand, 4, X86::ecx);
2088             emitCTICall(i, Interpreter::cti_op_in);
2089             emitPutVirtualRegister(instruction[i + 1].u.operand);
2090             i += 4;
2091             break;
2092         }
2093         case op_push_new_scope: {
2094             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
2095             emitPutCTIArgConstant(reinterpret_cast<unsigned>(ident), 0);
2096             emitPutCTIArgFromVirtualRegister(instruction[i + 3].u.operand, 4, X86::ecx);
2097             emitCTICall(i, Interpreter::cti_op_push_new_scope);
2098             emitPutVirtualRegister(instruction[i + 1].u.operand);
2099             i += 4;
2100             break;
2101         }
2102         case op_catch: {
2103             emitGetCTIParam(CTI_ARGS_callFrame, X86::edi); // edi := r
2104             emitPutVirtualRegister(instruction[i + 1].u.operand);
2105             i += 2;
2106             break;
2107         }
2108         case op_jmp_scopes: {
2109             unsigned count = instruction[i + 1].u.operand;
2110             emitPutCTIArgConstant(count, 0);
2111             emitCTICall(i, Interpreter::cti_op_jmp_scopes);
2112             unsigned target = instruction[i + 2].u.operand;
2113             m_jmpTable.append(JmpTable(__ jmp(), i + 2 + target));
2114             i += 3;
2115             break;
2116         }
2117         case op_put_by_index: {
2118             emitPutCTIArgFromVirtualRegister(instruction[i + 1].u.operand, 0, X86::ecx);
2119             emitPutCTIArgConstant(instruction[i + 2].u.operand, 4);
2120             emitPutCTIArgFromVirtualRegister(instruction[i + 3].u.operand, 8, X86::ecx);
2121             emitCTICall(i, Interpreter::cti_op_put_by_index);
2122             i += 4;
2123             break;
2124         }
2125         case op_switch_imm: {
2126             unsigned tableIndex = instruction[i + 1].u.operand;
2127             unsigned defaultOffset = instruction[i + 2].u.operand;
2128             unsigned scrutinee = instruction[i + 3].u.operand;
2129
2130             // create jump table for switch destinations, track this switch statement.
2131             SimpleJumpTable* jumpTable = &m_codeBlock->immediateSwitchJumpTables[tableIndex];
2132             m_switches.append(SwitchRecord(jumpTable, i, defaultOffset, SwitchRecord::Immediate));
2133             jumpTable->ctiOffsets.grow(jumpTable->branchOffsets.size());
2134
2135             emitPutCTIArgFromVirtualRegister(scrutinee, 0, X86::ecx);
2136             emitPutCTIArgConstant(tableIndex, 4);
2137             emitCTICall(i, Interpreter::cti_op_switch_imm);
2138             __ jmp_r(X86::eax);
2139             i += 4;
2140             break;
2141         }
2142         case op_switch_char: {
2143             unsigned tableIndex = instruction[i + 1].u.operand;
2144             unsigned defaultOffset = instruction[i + 2].u.operand;
2145             unsigned scrutinee = instruction[i + 3].u.operand;
2146
2147             // create jump table for switch destinations, track this switch statement.
2148             SimpleJumpTable* jumpTable = &m_codeBlock->characterSwitchJumpTables[tableIndex];
2149             m_switches.append(SwitchRecord(jumpTable, i, defaultOffset, SwitchRecord::Character));
2150             jumpTable->ctiOffsets.grow(jumpTable->branchOffsets.size());
2151
2152             emitPutCTIArgFromVirtualRegister(scrutinee, 0, X86::ecx);
2153             emitPutCTIArgConstant(tableIndex, 4);
2154             emitCTICall(i, Interpreter::cti_op_switch_char);
2155             __ jmp_r(X86::eax);
2156             i += 4;
2157             break;
2158         }
2159         case op_switch_string: {
2160             unsigned tableIndex = instruction[i + 1].u.operand;
2161             unsigned defaultOffset = instruction[i + 2].u.operand;
2162             unsigned scrutinee = instruction[i + 3].u.operand;
2163
2164             // create jump table for switch destinations, track this switch statement.
2165             StringJumpTable* jumpTable = &m_codeBlock->stringSwitchJumpTables[tableIndex];
2166             m_switches.append(SwitchRecord(jumpTable, i, defaultOffset));
2167
2168             emitPutCTIArgFromVirtualRegister(scrutinee, 0, X86::ecx);
2169             emitPutCTIArgConstant(tableIndex, 4);
2170             emitCTICall(i, Interpreter::cti_op_switch_string);
2171             __ jmp_r(X86::eax);
2172             i += 4;
2173             break;
2174         }
2175         case op_del_by_val: {
2176             emitPutCTIArgFromVirtualRegister(instruction[i + 2].u.operand, 0, X86::ecx);
2177             emitPutCTIArgFromVirtualRegister(instruction[i + 3].u.operand, 4, X86::ecx);
2178             emitCTICall(i, Interpreter::cti_op_del_by_val);
2179             emitPutVirtualRegister(instruction[i + 1].u.operand);
2180             i += 4;
2181             break;
2182         }
2183         case op_put_getter: {
2184             emitPutCTIArgFromVirtualRegister(instruction[i + 1].u.operand, 0, X86::ecx);
2185             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
2186             emitPutCTIArgConstant(reinterpret_cast<unsigned>(ident), 4);
2187             emitPutCTIArgFromVirtualRegister(instruction[i + 3].u.operand, 8, X86::ecx);
2188             emitCTICall(i, Interpreter::cti_op_put_getter);
2189             i += 4;
2190             break;
2191         }
2192         case op_put_setter: {
2193             emitPutCTIArgFromVirtualRegister(instruction[i + 1].u.operand, 0, X86::ecx);
2194             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
2195             emitPutCTIArgConstant(reinterpret_cast<unsigned>(ident), 4);
2196             emitPutCTIArgFromVirtualRegister(instruction[i + 3].u.operand, 8, X86::ecx);
2197             emitCTICall(i, Interpreter::cti_op_put_setter);
2198             i += 4;
2199             break;
2200         }
2201         case op_new_error: {
2202             JSValue* message = m_codeBlock->unexpectedConstants[instruction[i + 3].u.operand];
2203             emitPutCTIArgConstant(instruction[i + 2].u.operand, 0);
2204             emitPutCTIArgConstant(asInteger(message), 4);
2205             emitPutCTIArgConstant(m_codeBlock->lineNumberForVPC(&instruction[i]), 8);
2206             emitCTICall(i, Interpreter::cti_op_new_error);
2207             emitPutVirtualRegister(instruction[i + 1].u.operand);
2208             i += 4;
2209             break;
2210         }
2211         case op_debug: {
2212             emitPutCTIArgConstant(instruction[i + 1].u.operand, 0);
2213             emitPutCTIArgConstant(instruction[i + 2].u.operand, 4);
2214             emitPutCTIArgConstant(instruction[i + 3].u.operand, 8);
2215             emitCTICall(i, Interpreter::cti_op_debug);
2216             i += 4;
2217             break;
2218         }
2219         case op_eq_null: {
2220             unsigned dst = instruction[i + 1].u.operand;
2221             unsigned src1 = instruction[i + 2].u.operand;
2222
2223             emitGetVirtualRegister(src1, X86::eax, i);
2224             __ testl_i32r(JSImmediate::TagMask, X86::eax);
2225             JmpSrc isImmediate = __ jnz();
2226
2227             __ movl_mr(FIELD_OFFSET(JSCell, m_structure), X86::eax, X86::ecx);
2228             __ testl_i32m(MasqueradesAsUndefined, FIELD_OFFSET(Structure, m_typeInfo.m_flags), X86::ecx);
2229             __ setnz_r(X86::eax);
2230
2231             JmpSrc wasNotImmediate = __ jmp();
2232
2233             __ link(isImmediate, __ label());
2234
2235             __ movl_i32r(~JSImmediate::ExtendedTagBitUndefined, X86::ecx);
2236             __ andl_rr(X86::eax, X86::ecx);
2237             __ cmpl_i32r(JSImmediate::FullTagTypeNull, X86::ecx);
2238             __ sete_r(X86::eax);
2239
2240             __ link(wasNotImmediate, __ label());
2241
2242             __ movzbl_rr(X86::eax, X86::eax);
2243             emitTagAsBoolImmediate(X86::eax);
2244             emitPutVirtualRegister(dst);
2245
2246             i += 3;
2247             break;
2248         }
2249         case op_neq_null: {
2250             unsigned dst = instruction[i + 1].u.operand;
2251             unsigned src1 = instruction[i + 2].u.operand;
2252
2253             emitGetVirtualRegister(src1, X86::eax, i);
2254             __ testl_i32r(JSImmediate::TagMask, X86::eax);
2255             JmpSrc isImmediate = __ jnz();
2256
2257             __ movl_mr(FIELD_OFFSET(JSCell, m_structure), X86::eax, X86::ecx);
2258             __ testl_i32m(MasqueradesAsUndefined, FIELD_OFFSET(Structure, m_typeInfo.m_flags), X86::ecx);
2259             __ setz_r(X86::eax);
2260
2261             JmpSrc wasNotImmediate = __ jmp();
2262
2263             __ link(isImmediate, __ label());
2264
2265             __ movl_i32r(~JSImmediate::ExtendedTagBitUndefined, X86::ecx);
2266             __ andl_rr(X86::eax, X86::ecx);
2267             __ cmpl_i32r(JSImmediate::FullTagTypeNull, X86::ecx);
2268             __ setne_r(X86::eax);
2269
2270             __ link(wasNotImmediate, __ label());
2271
2272             __ movzbl_rr(X86::eax, X86::eax);
2273             emitTagAsBoolImmediate(X86::eax);
2274             emitPutVirtualRegister(dst);
2275
2276             i += 3;
2277             break;
2278         }
2279         case op_enter: {
2280             // Even though CTI doesn't use them, we initialize our constant
2281             // registers to zap stale pointers, to avoid unnecessarily prolonging
2282             // object lifetime and increasing GC pressure.
2283             size_t count = m_codeBlock->numVars + m_codeBlock->constantRegisters.size();
2284             for (size_t j = 0; j < count; ++j)
2285                 emitInitRegister(j);
2286
2287             i+= 1;
2288             break;
2289         }
2290         case op_enter_with_activation: {
2291             // Even though CTI doesn't use them, we initialize our constant
2292             // registers to zap stale pointers, to avoid unnecessarily prolonging
2293             // object lifetime and increasing GC pressure.
2294             size_t count = m_codeBlock->numVars + m_codeBlock->constantRegisters.size();
2295             for (size_t j = 0; j < count; ++j)
2296                 emitInitRegister(j);
2297
2298             emitCTICall(i, Interpreter::cti_op_push_activation);
2299             emitPutVirtualRegister(instruction[i + 1].u.operand);
2300
2301             i+= 2;
2302             break;
2303         }
2304         case op_create_arguments: {
2305             emitCTICall(i, (m_codeBlock->numParameters == 1) ? Interpreter::cti_op_create_arguments_no_params : Interpreter::cti_op_create_arguments);
2306             i += 1;
2307             break;
2308         }
2309         case op_convert_this: {
2310             emitGetVirtualRegister(instruction[i + 1].u.operand, X86::eax, i);
2311
2312             emitJumpSlowCaseIfNotJSCell(X86::eax, i);
2313             __ movl_mr(FIELD_OFFSET(JSCell, m_structure), X86::eax, X86::edx);
2314             __ testl_i32m(NeedsThisConversion, FIELD_OFFSET(Structure, m_typeInfo.m_flags), X86::edx);
2315             m_slowCases.append(SlowCaseEntry(__ jnz(), i));
2316
2317             i += 2;
2318             break;
2319         }
2320         case op_profile_will_call: {
2321             emitGetCTIParam(CTI_ARGS_profilerReference, X86::eax);
2322             __ cmpl_i32m(0, X86::eax);
2323             JmpSrc noProfiler = __ je();
2324             emitPutCTIArgFromVirtualRegister(instruction[i + 1].u.operand, 0, X86::eax);
2325             emitCTICall(i, Interpreter::cti_op_profile_will_call);
2326             __ link(noProfiler, __ label());
2327
2328             i += 2;
2329             break;
2330         }
2331         case op_profile_did_call: {
2332             emitGetCTIParam(CTI_ARGS_profilerReference, X86::eax);
2333             __ cmpl_i32m(0, X86::eax);
2334             JmpSrc noProfiler = __ je();
2335             emitPutCTIArgFromVirtualRegister(instruction[i + 1].u.operand, 0, X86::eax);
2336             emitCTICall(i, Interpreter::cti_op_profile_did_call);
2337             __ link(noProfiler, __ label());
2338
2339             i += 2;
2340             break;
2341         }
2342         case op_get_array_length:
2343         case op_get_by_id_chain:
2344         case op_get_by_id_generic:
2345         case op_get_by_id_proto:
2346         case op_get_by_id_proto_list:
2347         case op_get_by_id_self:
2348         case op_get_by_id_self_list:
2349         case op_get_string_length:
2350         case op_put_by_id_generic:
2351         case op_put_by_id_replace:
2352         case op_put_by_id_transition:
2353             ASSERT_NOT_REACHED();
2354         }
2355     }
2356
2357     ASSERT(propertyAccessInstructionIndex == m_codeBlock->propertyAccessInstructions.size());
2358     ASSERT(callLinkInfoIndex == m_codeBlock->callLinkInfos.size());
2359 }
2360
2361
2362 void JIT::privateCompileLinkPass()
2363 {
2364     unsigned jmpTableCount = m_jmpTable.size();
2365     for (unsigned i = 0; i < jmpTableCount; ++i)
2366         __ link(m_jmpTable[i].from, m_labels[m_jmpTable[i].to]);
2367     m_jmpTable.clear();
2368 }
2369
2370 #define CTI_COMPILE_BINARY_OP_SLOW_CASE(name) \
2371     case name: { \
2372         __ link(iter->from, __ label()); \
2373         emitPutCTIArgFromVirtualRegister(instruction[i + 2].u.operand, 0, X86::ecx); \
2374         emitPutCTIArgFromVirtualRegister(instruction[i + 3].u.operand, 4, X86::ecx); \
2375         emitCTICall(i, Interpreter::cti_##name); \
2376         emitPutVirtualRegister(instruction[i + 1].u.operand); \
2377         i += 4; \
2378         break; \
2379     }
2380
2381 #define CTI_COMPILE_BINARY_OP_SLOW_CASE_DOUBLE_ENTRY(name) \
2382     case name: { \
2383         __ link(iter->from, __ label()); \
2384         __ link((++iter)->from, __ label());                \
2385         emitPutCTIArgFromVirtualRegister(instruction[i + 2].u.operand, 0, X86::ecx); \
2386         emitPutCTIArgFromVirtualRegister(instruction[i + 3].u.operand, 4, X86::ecx); \
2387         emitCTICall(i, Interpreter::cti_##name); \
2388         emitPutVirtualRegister(instruction[i + 1].u.operand); \
2389         i += 4; \
2390         break; \
2391     }
2392     
2393 void JIT::privateCompileSlowCases()
2394 {
2395     unsigned propertyAccessInstructionIndex = 0;
2396     unsigned callLinkInfoIndex = 0;
2397
2398     Instruction* instruction = m_codeBlock->instructions.begin();
2399     for (Vector<SlowCaseEntry>::iterator iter = m_slowCases.begin(); iter != m_slowCases.end(); ++iter) {
2400         // FIXME: enable peephole optimizations for slow cases when applicable
2401         killLastResultRegister();
2402
2403         unsigned i = iter->to;
2404 #ifndef NDEBUG
2405         unsigned firstTo = i;
2406 #endif
2407
2408         switch (OpcodeID opcodeID = m_interpreter->getOpcodeID(instruction[i].u.opcode)) {
2409         case op_convert_this: {
2410             __ link(iter->from, __ label());
2411             __ link((++iter)->from, __ label());
2412             emitPutCTIArg(X86::eax, 0);
2413             emitCTICall(i, Interpreter::cti_op_convert_this);
2414             emitPutVirtualRegister(instruction[i + 1].u.operand);
2415             i += 2;
2416             break;
2417         }
2418         case op_add: {
2419             unsigned dst = instruction[i + 1].u.operand;
2420             unsigned src1 = instruction[i + 2].u.operand;
2421             unsigned src2 = instruction[i + 3].u.operand;
2422             if (JSValue* value = getConstantImmediateNumericArg(src1)) {
2423                 JmpSrc notImm = iter->from;
2424                 __ link((++iter)->from, __ label());
2425                 __ subl_i32r(getDeTaggedConstantImmediate(value), X86::eax);
2426                 __ link(notImm, __ label());
2427                 emitPutCTIArgFromVirtualRegister(src1, 0, X86::ecx);
2428                 emitPutCTIArg(X86::eax, 4);
2429                 emitCTICall(i, Interpreter::cti_op_add);
2430                 emitPutVirtualRegister(dst);
2431             } else if (JSValue* value = getConstantImmediateNumericArg(src2)) {
2432                 JmpSrc notImm = iter->from;
2433                 __ link((++iter)->from, __ label());
2434                 __ subl_i32r(getDeTaggedConstantImmediate(value), X86::eax);
2435                 __ link(notImm, __ label());
2436                 emitPutCTIArg(X86::eax, 0);
2437                 emitPutCTIArgFromVirtualRegister(src2, 4, X86::ecx);
2438                 emitCTICall(i, Interpreter::cti_op_add);
2439                 emitPutVirtualRegister(dst);
2440             } else {
2441                 OperandTypes types = OperandTypes::fromInt(instruction[i + 4].u.operand);
2442                 if (types.first().mightBeNumber() && types.second().mightBeNumber())
2443                     compileBinaryArithOpSlowCase(op_add, iter, dst, src1, src2, types, i);
2444                 else
2445                     ASSERT_NOT_REACHED();
2446             }
2447
2448             i += 5;
2449             break;
2450         }
2451         case op_get_by_val: {
2452             // The slow case that handles accesses to arrays (below) may jump back up to here. 
2453             JmpDst beginGetByValSlow = __ label();
2454
2455             JmpSrc notImm = iter->from;
2456             __ link((++iter)->from, __ label());
2457             __ link((++iter)->from, __ label());
2458             emitFastArithIntToImmNoCheck(X86::edx);
2459             __ link(notImm, __ label());
2460             emitPutCTIArg(X86::eax, 0);
2461             emitPutCTIArg(X86::edx, 4);
2462             emitCTICall(i, Interpreter::cti_op_get_by_val);
2463             emitPutVirtualRegister(instruction[i + 1].u.operand);
2464             __ link(__ jmp(), m_labels[i + 4]);
2465
2466             // This is slow case that handles accesses to arrays above the fast cut-off.
2467             // First, check if this is an access to the vector
2468             __ link((++iter)->from, __ label());
2469             __ cmpl_rm(X86::edx, FIELD_OFFSET(ArrayStorage, m_vectorLength), X86::ecx);
2470             __ link(__ jbe(), beginGetByValSlow);
2471
2472             // okay, missed the fast region, but it is still in the vector.  Get the value.
2473             __ movl_mr(FIELD_OFFSET(ArrayStorage, m_vector[0]), X86::ecx, X86::edx, sizeof(JSValue*), X86::ecx);
2474             // Check whether the value loaded is zero; if so we need to return undefined.
2475             __ testl_rr(X86::ecx, X86::ecx);
2476             __ link(__ je(), beginGetByValSlow);
2477             __ movl_rr(X86::ecx, X86::eax);
2478             emitPutVirtualRegister(instruction[i + 1].u.operand, X86::eax);
2479
2480             i += 4;
2481             break;
2482         }
2483         case op_sub: {
2484             compileBinaryArithOpSlowCase(op_sub, iter, instruction[i + 1].u.operand, instruction[i + 2].u.operand, instruction[i + 3].u.operand, OperandTypes::fromInt(instruction[i + 4].u.operand), i);
2485             i += 5;
2486             break;
2487         }
2488         case op_negate: {
2489             __ link(iter->from, __ label());
2490             __ link((++iter)->from, __ label());
2491             ResultType resultType(instruction[i + 3].u.resultType);
2492             if (!resultType.definitelyIsNumber()) {
2493                 if (linkSlowCaseIfNotJSCell(++iter, instruction[i + 2].u.operand))
2494                     ++iter;
2495                 __ link(iter->from, __ label());
2496             }
2497
2498             emitPutCTIArgFromVirtualRegister(instruction[i + 2].u.operand, 0, X86::ecx);
2499             emitCTICall(i, Interpreter::cti_op_negate);
2500             emitPutVirtualRegister(instruction[i + 1].u.operand);
2501             i += 4;
2502             break;
2503         }
2504         case op_rshift: {
2505             __ link(iter->from, __ label());
2506             __ link((++iter)->from, __ label());
2507             emitPutCTIArg(X86::eax, 0);
2508             emitPutCTIArg(X86::ecx, 4);
2509             emitCTICall(i, Interpreter::cti_op_rshift);
2510             emitPutVirtualRegister(instruction[i + 1].u.operand);
2511             i += 4;
2512             break;
2513         }
2514         case op_lshift: {
2515             JmpSrc notImm1 = iter->from;
2516             JmpSrc notImm2 = (++iter)->from;
2517             __ link((++iter)->from, __ label());
2518             emitGetVirtualRegisters(instruction[i + 2].u.operand, X86::eax, instruction[i + 3].u.operand, X86::ecx, i);
2519             __ link(notImm1, __ label());
2520             __ link(notImm2, __ label());
2521             emitPutCTIArg(X86::eax, 0);
2522             emitPutCTIArg(X86::ecx, 4);
2523             emitCTICall(i, Interpreter::cti_op_lshift);
2524             emitPutVirtualRegister(instruction[i + 1].u.operand);
2525             i += 4;
2526             break;
2527         }
2528         case op_loop_if_less: {
2529             emitSlowScriptCheck(i);
2530
2531             unsigned target = instruction[i + 3].u.operand;
2532             JSValue* src2imm = getConstantImmediateNumericArg(instruction[i + 2].u.operand);
2533             if (src2imm) {
2534                 __ link(iter->from, __ label());
2535                 emitPutCTIArg(X86::edx, 0);
2536                 emitPutCTIArgFromVirtualRegister(instruction[i + 2].u.operand, 4, X86::ecx);
2537                 emitCTICall(i, Interpreter::cti_op_loop_if_less);
2538                 __ testl_rr(X86::eax, X86::eax);
2539                 __ link(__ jne(), m_labels[i + 3 + target]);
2540             } else {
2541                 __ link(iter->from, __ label());
2542                 __ link((++iter)->from, __ label());
2543                 emitPutCTIArg(X86::eax, 0);
2544                 emitPutCTIArg(X86::edx, 4);
2545                 emitCTICall(i, Interpreter::cti_op_loop_if_less);
2546                 __ testl_rr(X86::eax, X86::eax);
2547                 __ link(__ jne(), m_labels[i + 3 + target]);
2548             }
2549             i += 4;
2550             break;
2551         }
2552         case op_put_by_id: {
2553             if (linkSlowCaseIfNotJSCell(iter, instruction[i + 1].u.operand))
2554                 ++iter;
2555             __ link(iter->from, __ label());
2556
2557             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
2558             emitPutCTIArgConstant(reinterpret_cast<unsigned>(ident), 4);
2559             emitPutCTIArg(X86::eax, 0);
2560             emitPutCTIArg(X86::edx, 8);
2561             JmpSrc call = emitCTICall(i, Interpreter::cti_op_put_by_id);
2562
2563             // Track the location of the call; this will be used to recover repatch information.
2564             ASSERT(m_codeBlock->propertyAccessInstructions[propertyAccessInstructionIndex].bytecodeIndex == i);
2565             m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].callReturnLocation = call;
2566             ++propertyAccessInstructionIndex;
2567
2568             i += 8;
2569             break;
2570         }
2571         case op_get_by_id: {
2572             // As for the hot path of get_by_id, above, we ensure that we can use an architecture specific offset
2573             // so that we only need track one pointer into the slow case code - we track a pointer to the location
2574             // of the call (which we can use to look up the repatch information), but should a array-length or
2575             // prototype access trampoline fail we want to bail out back to here.  To do so we can subtract back
2576             // the distance from the call to the head of the slow case.
2577
2578             if (linkSlowCaseIfNotJSCell(iter, instruction[i + 2].u.operand))
2579                 ++iter;
2580             __ link(iter->from, __ label());
2581
2582 #ifndef NDEBUG
2583             JmpDst coldPathBegin = __ label();
2584 #endif        
2585             emitPutCTIArg(X86::eax, 0);
2586             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 3].u.operand]);
2587             emitPutCTIArgConstant(reinterpret_cast<unsigned>(ident), 4);
2588             JmpSrc call = emitCTICall(i, Interpreter::cti_op_get_by_id);
2589             ASSERT(X86Assembler::getDifferenceBetweenLabels(coldPathBegin, call) == repatchOffsetGetByIdSlowCaseCall);
2590             emitPutVirtualRegister(instruction[i + 1].u.operand);
2591
2592             // Track the location of the call; this will be used to recover repatch information.
2593             ASSERT(m_codeBlock->propertyAccessInstructions[propertyAccessInstructionIndex].bytecodeIndex == i);
2594             m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].callReturnLocation = call;
2595             ++propertyAccessInstructionIndex;
2596
2597             i += 8;
2598             break;
2599         }
2600         case op_loop_if_lesseq: {
2601             emitSlowScriptCheck(i);
2602
2603             unsigned target = instruction[i + 3].u.operand;
2604             JSValue* src2imm = getConstantImmediateNumericArg(instruction[i + 2].u.operand);
2605             if (src2imm) {
2606                 __ link(iter->from, __ label());
2607                 emitPutCTIArg(X86::edx, 0);
2608                 emitPutCTIArgFromVirtualRegister(instruction[i + 2].u.operand, 4, X86::ecx);
2609                 emitCTICall(i, Interpreter::cti_op_loop_if_lesseq);
2610                 __ testl_rr(X86::eax, X86::eax);
2611                 __ link(__ jne(), m_labels[i + 3 + target]);
2612             } else {
2613                 __ link(iter->from, __ label());
2614                 __ link((++iter)->from, __ label());
2615                 emitPutCTIArg(X86::eax, 0);
2616                 emitPutCTIArg(X86::edx, 4);
2617                 emitCTICall(i, Interpreter::cti_op_loop_if_lesseq);
2618                 __ testl_rr(X86::eax, X86::eax);
2619                 __ link(__ jne(), m_labels[i + 3 + target]);
2620             }
2621             i += 4;
2622             break;
2623         }
2624         case op_pre_inc: {
2625             unsigned srcDst = instruction[i + 1].u.operand;
2626             JmpSrc notImm = iter->from;
2627             __ link((++iter)->from, __ label());
2628             __ subl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), X86::eax);
2629             __ link(notImm, __ label());
2630             emitPutCTIArg(X86::eax, 0);
2631             emitCTICall(i, Interpreter::cti_op_pre_inc);
2632             emitPutVirtualRegister(srcDst);
2633             i += 2;
2634             break;
2635         }
2636         case op_put_by_val: {
2637             // Normal slow cases - either is not an immediate imm, or is an array.
2638             JmpSrc notImm = iter->from;
2639             __ link((++iter)->from, __ label());
2640             __ link((++iter)->from, __ label());
2641             emitFastArithIntToImmNoCheck(X86::edx);
2642             __ link(notImm, __ label());
2643             emitGetVirtualRegister(instruction[i + 3].u.operand, X86::ecx, i);
2644             emitPutCTIArg(X86::eax, 0);
2645             emitPutCTIArg(X86::edx, 4);
2646             emitPutCTIArg(X86::ecx, 8);
2647             emitCTICall(i, Interpreter::cti_op_put_by_val);
2648             __ link(__ jmp(), m_labels[i + 4]);
2649
2650             // slow cases for immediate int accesses to arrays
2651             __ link((++iter)->from, __ label());
2652             __ link((++iter)->from, __ label());
2653             emitGetVirtualRegister(instruction[i + 3].u.operand, X86::ecx, i);
2654             emitPutCTIArg(X86::eax, 0);
2655             emitPutCTIArg(X86::edx, 4);
2656             emitPutCTIArg(X86::ecx, 8);
2657             emitCTICall(i, Interpreter::cti_op_put_by_val_array);
2658
2659             i += 4;
2660             break;
2661         }
2662         case op_loop_if_true: {
2663             emitSlowScriptCheck(i);
2664
2665             __ link(iter->from, __ label());
2666             emitPutCTIArg(X86::eax, 0);
2667             emitCTICall(i, Interpreter::cti_op_jtrue);
2668             __ testl_rr(X86::eax, X86::eax);
2669             unsigned target = instruction[i + 2].u.operand;
2670             __ link(__ jne(), m_labels[i + 2 + target]);
2671             i += 3;
2672             break;
2673         }
2674         case op_pre_dec: {
2675             unsigned srcDst = instruction[i + 1].u.operand;
2676             JmpSrc notImm = iter->from;
2677             __ link((++iter)->from, __ label());
2678             __ addl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), X86::eax);
2679             __ link(notImm, __ label());
2680             emitPutCTIArg(X86::eax, 0);
2681             emitCTICall(i, Interpreter::cti_op_pre_dec);
2682             emitPutVirtualRegister(srcDst);
2683             i += 2;
2684             break;
2685         }
2686         case op_jnless: {
2687             unsigned target = instruction[i + 3].u.operand;
2688             JSValue* src2imm = getConstantImmediateNumericArg(instruction[i + 2].u.operand);
2689             if (src2imm) {
2690                 __ link(iter->from, __ label());
2691                 emitPutCTIArg(X86::edx, 0);
2692                 emitPutCTIArgFromVirtualRegister(instruction[i + 2].u.operand, 4, X86::ecx);
2693                 emitCTICall(i, Interpreter::cti_op_jless);
2694                 __ testl_rr(X86::eax, X86::eax);
2695                 __ link(__ je(), m_labels[i + 3 + target]);
2696             } else {
2697                 __ link(iter->from, __ label());
2698                 __ link((++iter)->from, __ label());
2699                 emitPutCTIArg(X86::eax, 0);
2700                 emitPutCTIArg(X86::edx, 4);
2701                 emitCTICall(i, Interpreter::cti_op_jless);
2702                 __ testl_rr(X86::eax, X86::eax);
2703                 __ link(__ je(), m_labels[i + 3 + target]);
2704             }
2705             i += 4;
2706             break;
2707         }
2708         case op_not: {
2709             __ link(iter->from, __ label());
2710             __ xorl_i8r(JSImmediate::FullTagTypeBool, X86::eax);
2711             emitPutCTIArg(X86::eax, 0);
2712             emitCTICall(i, Interpreter::cti_op_not);
2713             emitPutVirtualRegister(instruction[i + 1].u.operand);
2714             i += 3;
2715             break;
2716         }
2717         case op_jfalse: {
2718             __ link(iter->from, __ label());
2719             emitPutCTIArg(X86::eax, 0);
2720             emitCTICall(i, Interpreter::cti_op_jtrue);
2721             __ testl_rr(X86::eax, X86::eax);
2722             unsigned target = instruction[i + 2].u.operand;
2723             __ link(__ je(), m_labels[i + 2 + target]); // inverted!
2724             i += 3;
2725             break;
2726         }
2727         case op_post_inc: {
2728             unsigned srcDst = instruction[i + 2].u.operand;
2729             __ link(iter->from, __ label());
2730             __ link((++iter)->from, __ label());
2731             emitPutCTIArg(X86::eax, 0);
2732             emitCTICall(i, Interpreter::cti_op_post_inc);
2733             emitPutVirtualRegister(srcDst, X86::edx);
2734             emitPutVirtualRegister(instruction[i + 1].u.operand);
2735             i += 3;
2736             break;
2737         }
2738         case op_bitnot: {
2739             __ link(iter->from, __ label());
2740             emitPutCTIArg(X86::eax, 0);
2741             emitCTICall(i, Interpreter::cti_op_bitnot);
2742             emitPutVirtualRegister(instruction[i + 1].u.operand);
2743             i += 3;
2744             break;
2745         }
2746         case op_bitand: {
2747             unsigned src1 = instruction[i + 2].u.operand;
2748             unsigned src2 = instruction[i + 3].u.operand;
2749             unsigned dst = instruction[i + 1].u.operand;
2750             if (getConstantImmediateNumericArg(src1)) {
2751                 __ link(iter->from, __ label());
2752                 emitPutCTIArgFromVirtualRegister(src1, 0, X86::ecx);
2753                 emitPutCTIArg(X86::eax, 4);
2754                 emitCTICall(i, Interpreter::cti_op_bitand);
2755                 emitPutVirtualRegister(dst);
2756             } else if (getConstantImmediateNumericArg(src2)) {
2757                 __ link(iter->from, __ label());
2758                 emitPutCTIArg(X86::eax, 0);
2759                 emitPutCTIArgFromVirtualRegister(src2, 4, X86::ecx);
2760                 emitCTICall(i, Interpreter::cti_op_bitand);
2761                 emitPutVirtualRegister(dst);
2762             } else {
2763                 __ link(iter->from, __ label());
2764                 emitPutCTIArgFromVirtualRegister(src1, 0, X86::ecx);
2765                 emitPutCTIArg(X86::edx, 4);
2766                 emitCTICall(i, Interpreter::cti_op_bitand);
2767                 emitPutVirtualRegister(dst);
2768             }
2769             i += 5;
2770             break;
2771         }
2772         case op_jtrue: {
2773             __ link(iter->from, __ label());
2774             emitPutCTIArg(X86::eax, 0);
2775             emitCTICall(i, Interpreter::cti_op_jtrue);
2776             __ testl_rr(X86::eax, X86::eax);
2777             unsigned target = instruction[i + 2].u.operand;
2778             __ link(__ jne(), m_labels[i + 2 + target]);
2779             i += 3;
2780             break;
2781         }
2782         case op_post_dec: {
2783             unsigned srcDst = instruction[i + 2].u.operand;
2784             __ link(iter->from, __ label());
2785             __ link((++iter)->from, __ label());
2786             emitPutCTIArg(X86::eax, 0);
2787             emitCTICall(i, Interpreter::cti_op_post_dec);
2788             emitPutVirtualRegister(srcDst, X86::edx);
2789             emitPutVirtualRegister(instruction[i + 1].u.operand);
2790             i += 3;
2791             break;
2792         }
2793         case op_bitxor: {
2794             __ link(iter->from, __ label());
2795             emitPutCTIArg(X86::eax, 0);
2796             emitPutCTIArg(X86::edx, 4);
2797             emitCTICall(i, Interpreter::cti_op_bitxor);
2798             emitPutVirtualRegister(instruction[i + 1].u.operand);
2799             i += 5;
2800             break;
2801         }
2802         case op_bitor: {
2803             __ link(iter->from, __ label());
2804             emitPutCTIArg(X86::eax, 0);
2805             emitPutCTIArg(X86::edx, 4);
2806             emitCTICall(i, Interpreter::cti_op_bitor);
2807             emitPutVirtualRegister(instruction[i + 1].u.operand);
2808             i += 5;
2809             break;
2810         }
2811         case op_eq: {
2812             __ link(iter->from, __ label());
2813             emitPutCTIArg(X86::eax, 0);
2814             emitPutCTIArg(X86::edx, 4);
2815             emitCTICall(i, Interpreter::cti_op_eq);
2816             emitPutVirtualRegister(instruction[i + 1].u.operand);
2817             i += 4;
2818             break;
2819         }
2820         case op_neq: {
2821             __ link(iter->from, __ label());
2822             emitPutCTIArg(X86::eax, 0);
2823             emitPutCTIArg(X86::edx, 4);
2824             emitCTICall(i, Interpreter::cti_op_neq);
2825             emitPutVirtualRegister(instruction[i + 1].u.operand);
2826             i += 4;
2827             break;
2828         }
2829         CTI_COMPILE_BINARY_OP_SLOW_CASE_DOUBLE_ENTRY(op_stricteq);
2830         CTI_COMPILE_BINARY_OP_SLOW_CASE_DOUBLE_ENTRY(op_nstricteq);
2831         case op_instanceof: {
2832             __ link(iter->from, __ label());
2833             __ link((++iter)->from, __ label());
2834             __ link((++iter)->from, __ label());
2835             emitPutCTIArgFromVirtualRegister(instruction[i + 2].u.operand, 0, X86::ecx);
2836             emitPutCTIArgFromVirtualRegister(instruction[i + 3].u.operand, 4, X86::ecx);
2837             emitPutCTIArgFromVirtualRegister(instruction[i + 4].u.operand, 8, X86::ecx);
2838             emitCTICall(i, Interpreter::cti_op_instanceof);
2839             emitPutVirtualRegister(instruction[i + 1].u.operand);
2840             i += 5;
2841             break;
2842         }
2843         case op_mod: {
2844             JmpSrc notImm1 = iter->from;
2845             JmpSrc notImm2 = (++iter)->from;
2846             __ link((++iter)->from, __ label());
2847             emitFastArithReTagImmediate(X86::eax);
2848             emitFastArithReTagImmediate(X86::ecx);
2849             __ link(notImm1, __ label());
2850             __ link(notImm2, __ label());
2851             emitPutCTIArg(X86::eax, 0);
2852             emitPutCTIArg(X86::ecx, 4);
2853             emitCTICall(i, Interpreter::cti_op_mod);
2854             emitPutVirtualRegister(instruction[i + 1].u.operand);
2855             i += 4;
2856             break;
2857         }
2858         case op_mul: {
2859             int dst = instruction[i + 1].u.operand;
2860             int src1 = instruction[i + 2].u.operand;
2861             int src2 = instruction[i + 3].u.operand;
2862             JSValue* src1Value = getConstantImmediateNumericArg(src1);
2863             JSValue* src2Value = getConstantImmediateNumericArg(src2);
2864             int32_t value;
2865             if (src1Value && ((value = JSImmediate::intValue(src1Value)) > 0)) {
2866                 __ link(iter->from, __ label());
2867                 __ link((++iter)->from, __ label());
2868                 // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0.
2869                 emitPutCTIArgFromVirtualRegister(src1, 0, X86::ecx);
2870                 emitPutCTIArgFromVirtualRegister(src2, 4, X86::ecx);
2871                 emitCTICall(i, Interpreter::cti_op_mul);
2872                 emitPutVirtualRegister(dst);
2873             } else if (src2Value && ((value = JSImmediate::intValue(src2Value)) > 0)) {
2874                 __ link(iter->from, __ label());
2875                 __ link((++iter)->from, __ label());
2876                 // There is an extra slow case for (op1 * -N) or (-N * op2), to check for 0 since this should produce a result of -0.
2877                 emitPutCTIArgFromVirtualRegister(src1, 0, X86::ecx);
2878                 emitPutCTIArgFromVirtualRegister(src2, 4, X86::ecx);
2879                 emitCTICall(i, Interpreter::cti_op_mul);
2880                 emitPutVirtualRegister(dst);
2881             } else
2882                 compileBinaryArithOpSlowCase(op_mul, iter, dst, src1, src2, OperandTypes::fromInt(instruction[i + 4].u.operand), i);
2883             i += 5;
2884             break;
2885         }
2886
2887         case op_call:
2888         case op_call_eval:
2889         case op_construct: {
2890             int dst = instruction[i + 1].u.operand;
2891             int callee = instruction[i + 2].u.operand;
2892             int argCount = instruction[i + 3].u.operand;
2893             int registerOffset = instruction[i + 4].u.operand;
2894
2895             __ link(iter->from, __ label());
2896
2897             // The arguments have been set up on the hot path for op_call_eval
2898             if (opcodeID == op_call)
2899                 compileOpCallSetupArgs(instruction + i);
2900             else if (opcodeID == op_construct)
2901                 compileOpConstructSetupArgs(instruction + i);
2902
2903             // Fast check for JS function.
2904             __ testl_i32r(JSImmediate::TagMask, X86::ecx);
2905             JmpSrc callLinkFailNotObject = __ jne();
2906             __ cmpl_i32m(reinterpret_cast<unsigned>(m_interpreter->m_jsFunctionVptr), X86::ecx);
2907             JmpSrc callLinkFailNotJSFunction = __ jne();
2908
2909             // First, in the case of a construct, allocate the new object.
2910             if (opcodeID == op_construct) {
2911                 emitCTICall(i, Interpreter::cti_op_construct_JSConstruct);
2912                 emitPutVirtualRegister(registerOffset - RegisterFile::CallFrameHeaderSize - argCount);
2913                 emitGetVirtualRegister(callee, X86::ecx, i);
2914             }
2915
2916             __ movl_i32r(argCount, X86::edx);
2917
2918             // Speculatively roll the callframe, assuming argCount will match the arity.
2919             __ movl_rm(X86::edi, (RegisterFile::CallerFrame + registerOffset) * static_cast<int>(sizeof(Register)), X86::edi);
2920             __ addl_i32r(registerOffset * static_cast<int>(sizeof(Register)), X86::edi);
2921
2922             m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLocation =
2923                 emitNakedCall(i, m_interpreter->m_ctiVirtualCallPreLink);
2924
2925             JmpSrc storeResultForFirstRun = __ jmp();
2926
2927             // This is the address for the cold path *after* the first run (which tries to link the call).
2928             m_callStructureStubCompilationInfo[callLinkInfoIndex].coldPathOther = __ label();
2929
2930             // The arguments have been set up on the hot path for op_call_eval
2931             if (opcodeID == op_call)
2932                 compileOpCallSetupArgs(instruction + i);
2933             else if (opcodeID == op_construct)
2934                 compileOpConstructSetupArgs(instruction + i);
2935
2936             // Check for JSFunctions.
2937             __ testl_i32r(JSImmediate::TagMask, X86::ecx);
2938             JmpSrc isNotObject = __ jne();
2939             __ cmpl_i32m(reinterpret_cast<unsigned>(m_interpreter->m_jsFunctionVptr), X86::ecx);
2940             JmpSrc isJSFunction = __ je();
2941
2942             // This handles host functions
2943             JmpDst notJSFunctionlabel = __ label();
2944             __ link(isNotObject, notJSFunctionlabel);
2945             __ link(callLinkFailNotObject, notJSFunctionlabel);
2946             __ link(callLinkFailNotJSFunction, notJSFunctionlabel);
2947             emitCTICall(i, ((opcodeID == op_construct) ? Interpreter::cti_op_construct_NotJSConstruct : Interpreter::cti_op_call_NotJSFunction));
2948             JmpSrc wasNotJSFunction = __ jmp();
2949
2950             // Next, handle JSFunctions...
2951             __ link(isJSFunction, __ label());
2952
2953             // First, in the case of a construct, allocate the new object.
2954             if (opcodeID == op_construct) {
2955                 emitCTICall(i, Interpreter::cti_op_construct_JSConstruct);
2956                 emitPutVirtualRegister(registerOffset - RegisterFile::CallFrameHeaderSize - argCount);
2957                 emitGetVirtualRegister(callee, X86::ecx, i);
2958             }
2959
2960             // Speculatively roll the callframe, assuming argCount will match the arity.
2961             __ movl_rm(X86::edi, (RegisterFile::CallerFrame + registerOffset) * static_cast<int>(sizeof(Register)), X86::edi);
2962             __ addl_i32r(registerOffset * static_cast<int>(sizeof(Register)), X86::edi);
2963             __ movl_i32r(argCount, X86::edx);
2964
2965             emitNakedCall(i, m_interpreter->m_ctiVirtualCall);
2966
2967             // Put the return value in dst. In the interpreter, op_ret does this.
2968             JmpDst storeResult = __ label();
2969             __ link(wasNotJSFunction, storeResult);
2970             __ link(storeResultForFirstRun, storeResult);
2971             emitPutVirtualRegister(dst);
2972
2973 #if ENABLE(CODEBLOCK_SAMPLING)
2974             __ movl_i32m(reinterpret_cast<unsigned>(m_codeBlock), m_interpreter->sampler()->codeBlockSlot());
2975 #endif
2976             ++callLinkInfoIndex;
2977
2978             i += (opcodeID == op_construct ? 7 : 5);
2979             break;
2980         }
2981         case op_to_jsnumber: {
2982             if (linkSlowCaseIfNotJSCell(iter, instruction[i + 2].u.operand))
2983                 ++iter;
2984             __ link(iter->from, __ label());
2985
2986             emitPutCTIArg(X86::eax, 0);
2987             emitCTICall(i, Interpreter::cti_op_to_jsnumber);
2988
2989             emitPutVirtualRegister(instruction[i + 1].u.operand);
2990             i += 3;
2991             break;
2992         }
2993
2994         default:
2995             ASSERT_NOT_REACHED();
2996             break;
2997         }
2998
2999         ASSERT_WITH_MESSAGE((iter + 1) == m_slowCases.end() || firstTo != (iter + 1)->to,"Not enough jumps linked in slow case codegen.");
3000         ASSERT_WITH_MESSAGE(firstTo == iter->to, "Too many jumps linked in slow case codegen.");
3001
3002         __ link(__ jmp(), m_labels[i]);
3003     }
3004
3005     ASSERT(propertyAccessInstructionIndex == m_codeBlock->propertyAccessInstructions.size());
3006     ASSERT(callLinkInfoIndex == m_codeBlock->callLinkInfos.size());
3007 }
3008
3009 void JIT::privateCompile()
3010 {
3011 #if ENABLE(CODEBLOCK_SAMPLING)
3012         __ movl_i32m(reinterpret_cast<unsigned>(m_codeBlock), m_interpreter->sampler()->codeBlockSlot());
3013 #endif
3014 #if ENABLE(OPCODE_SAMPLING)
3015         __ movl_i32m(m_interpreter->sampler()->encodeSample(m_codeBlock->instructions.begin()), m_interpreter->sampler()->sampleSlot());
3016 #endif
3017
3018     // Could use a popl_m, but would need to offset the following instruction if so.
3019     __ popl_r(X86::ecx);
3020     emitPutToCallFrameHeader(X86::ecx, RegisterFile::ReturnPC);
3021
3022     JmpSrc slowRegisterFileCheck;
3023     JmpDst afterRegisterFileCheck;
3024     if (m_codeBlock->codeType == FunctionCode) {
3025         // In the case of a fast linked call, we do not set this up in the caller.
3026         __ movl_i32m(reinterpret_cast<unsigned>(m_codeBlock), RegisterFile::CodeBlock * static_cast<int>(sizeof(Register)), X86::edi);
3027
3028         emitGetCTIParam(CTI_ARGS_registerFile, X86::eax);
3029         __ leal_mr(m_codeBlock->numCalleeRegisters * sizeof(Register), X86::edi, X86::edx);
3030         __ cmpl_mr(FIELD_OFFSET(RegisterFile, m_end), X86::eax, X86::edx);
3031         slowRegisterFileCheck = __ jg();
3032         afterRegisterFileCheck = __ label();
3033     }
3034
3035     privateCompileMainPass();
3036     privateCompileLinkPass();
3037     privateCompileSlowCases();
3038
3039     if (m_codeBlock->codeType == FunctionCode) {
3040         __ link(slowRegisterFileCheck, __ label());
3041         emitCTICall(0, Interpreter::cti_register_file_check);
3042         JmpSrc backToBody = __ jmp();
3043         __ link(backToBody, afterRegisterFileCheck);
3044     }
3045
3046     ASSERT(m_jmpTable.isEmpty());
3047
3048     void* code = __ executableCopy();
3049
3050     // Translate vPC offsets into addresses in JIT generated code, for switch tables.
3051     for (unsigned i = 0; i < m_switches.size(); ++i) {
3052         SwitchRecord record = m_switches[i];
3053         unsigned bytecodeIndex = record.bytecodeIndex;
3054
3055         if (record.type != SwitchRecord::String) {
3056             ASSERT(record.type == SwitchRecord::Immediate || record.type == SwitchRecord::Character); 
3057             ASSERT(record.jumpTable.simpleJumpTable->branchOffsets.size() == record.jumpTable.simpleJumpTable->ctiOffsets.size());
3058
3059             record.jumpTable.simpleJumpTable->ctiDefault = __ getRelocatedAddress(code, m_labels[bytecodeIndex + 3 + record.defaultOffset]);
3060
3061             for (unsigned j = 0; j < record.jumpTable.simpleJumpTable->branchOffsets.size(); ++j) {
3062                 unsigned offset = record.jumpTable.simpleJumpTable->branchOffsets[j];
3063                 record.jumpTable.simpleJumpTable->ctiOffsets[j] = offset ? __ getRelocatedAddress(code, m_labels[bytecodeIndex + 3 + offset]) : record.jumpTable.simpleJumpTable->ctiDefault;
3064             }
3065         } else {
3066             ASSERT(record.type == SwitchRecord::String);
3067
3068             record.jumpTable.stringJumpTable->ctiDefault = __ getRelocatedAddress(code, m_labels[bytecodeIndex + 3 + record.defaultOffset]);
3069
3070             StringJumpTable::StringOffsetTable::iterator end = record.jumpTable.stringJumpTable->offsetTable.end();            
3071             for (StringJumpTable::StringOffsetTable::iterator it = record.jumpTable.stringJumpTable->offsetTable.begin(); it != end; ++it) {
3072                 unsigned offset = it->second.branchOffset;
3073                 it->second.ctiOffset = offset ? __ getRelocatedAddress(code, m_labels[bytecodeIndex + 3 + offset]) : record.jumpTable.stringJumpTable->ctiDefault;
3074             }
3075         }
3076     }
3077
3078     for (Vector<HandlerInfo>::iterator iter = m_codeBlock->exceptionHandlers.begin(); iter != m_codeBlock->exceptionHandlers.end(); ++iter)
3079          iter->nativeCode = __ getRelocatedAddress(code, m_labels[iter->target]);
3080
3081     for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
3082         if (iter->to)
3083             X86Assembler::link(code, iter->from, iter->to);
3084         m_codeBlock->ctiReturnAddressVPCMap.add(__ getRelocatedAddress(code, iter->from), iter->bytecodeIndex);
3085     }
3086
3087     // Link absolute addresses for jsr
3088     for (Vector<JSRInfo>::iterator iter = m_jsrSites.begin(); iter != m_jsrSites.end(); ++iter)
3089         X86Assembler::linkAbsoluteAddress(code, iter->addrPosition, iter->target);
3090
3091     for (unsigned i = 0; i < m_codeBlock->propertyAccessInstructions.size(); ++i) {
3092         StructureStubInfo& info = m_codeBlock->propertyAccessInstructions[i];
3093         info.callReturnLocation = X86Assembler::getRelocatedAddress(code, m_propertyAccessCompilationInfo[i].callReturnLocation);
3094         info.hotPathBegin = X86Assembler::getRelocatedAddress(code, m_propertyAccessCompilationInfo[i].hotPathBegin);
3095     }
3096     for (unsigned i = 0; i < m_codeBlock->callLinkInfos.size(); ++i) {
3097         CallLinkInfo& info = m_codeBlock->callLinkInfos[i];
3098         info.callReturnLocation = X86Assembler::getRelocatedAddress(code, m_callStructureStubCompilationInfo[i].callReturnLocation);
3099         info.hotPathBegin = X86Assembler::getRelocatedAddress(code, m_callStructureStubCompilationInfo[i].hotPathBegin);
3100         info.hotPathOther = X86Assembler::getRelocatedAddress(code, m_callStructureStubCompilationInfo[i].hotPathOther);
3101         info.coldPathOther = X86Assembler::getRelocatedAddress(code, m_callStructureStubCompilationInfo[i].coldPathOther);
3102     }
3103
3104     m_codeBlock->ctiCode = code;
3105 }
3106
3107 void JIT::privateCompileGetByIdSelf(Structure* structure, size_t cachedOffset, void* returnAddress)
3108 {
3109     // Check eax is an object of the right Structure.
3110     __ testl_i32r(JSImmediate::TagMask, X86::eax);
3111     JmpSrc failureCases1 = __ jne();
3112     JmpSrc failureCases2 = checkStructure(X86::eax, structure);
3113
3114     // Checks out okay! - getDirectOffset
3115     __ movl_mr(FIELD_OFFSET(JSObject, m_propertyStorage), X86::eax, X86::eax);
3116     __ movl_mr(cachedOffset * sizeof(JSValue*), X86::eax, X86::eax);
3117     __ ret();
3118
3119     void* code = __ executableCopy();
3120
3121     X86Assembler::link(code, failureCases1, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_self_fail));
3122     X86Assembler::link(code, failureCases2, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_self_fail));
3123     
3124     m_codeBlock->getStubInfo(returnAddress).stubRoutine = code;
3125     
3126     ctiRepatchCallByReturnAddress(returnAddress, code);
3127 }
3128
3129 void JIT::privateCompileGetByIdProto(Structure* structure, Structure* prototypeStructure, size_t cachedOffset, void* returnAddress, CallFrame* callFrame)
3130 {
3131 #if USE(CTI_REPATCH_PIC)
3132     StructureStubInfo& info = m_codeBlock->getStubInfo(returnAddress);
3133
3134     // We don't want to repatch more than once - in future go to cti_op_put_by_id_generic.
3135     ctiRepatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_proto_list));
3136
3137     // The prototype object definitely exists (if this stub exists the CodeBlock is referencing a Structure that is
3138     // referencing the prototype object - let's speculatively load it's table nice and early!)
3139     JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame));
3140     PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage;
3141     __ movl_mr(static_cast<void*>(protoPropertyStorage), X86::edx);
3142
3143     // Check eax is an object of the right Structure.
3144     JmpSrc failureCases1 = checkStructure(X86::eax, structure);
3145
3146     // Check the prototype object's Structure had not changed.
3147     Structure** prototypeStructureAddress = &(protoObject->m_structure);
3148     __ cmpl_i32m(reinterpret_cast<uint32_t>(prototypeStructure), prototypeStructureAddress);
3149     JmpSrc failureCases2 = __ jne();
3150
3151     // Checks out okay! - getDirectOffset
3152     __ movl_mr(cachedOffset * sizeof(JSValue*), X86::edx, X86::eax);
3153
3154     JmpSrc success = __ jmp();
3155
3156     void* code = __ executableCopy();
3157
3158     // Use the repatch information to link the failure cases back to the original slow case routine.
3159     void* slowCaseBegin = reinterpret_cast<char*>(info.callReturnLocation) - repatchOffsetGetByIdSlowCaseCall;
3160     X86Assembler::link(code, failureCases1, slowCaseBegin);
3161     X86Assembler::link(code, failureCases2, slowCaseBegin);
3162
3163     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
3164     intptr_t successDest = reinterpret_cast<intptr_t>(info.hotPathBegin) + repatchOffsetGetByIdPropertyMapOffset;
3165     X86Assembler::link(code, success, reinterpret_cast<void*>(successDest));
3166
3167     // Track the stub we have created so that it will be deleted later.
3168     info.stubRoutine = code;
3169
3170     // Finally repatch the jump to slow case back in the hot path to jump here instead.
3171     intptr_t jmpLocation = reinterpret_cast<intptr_t>(info.hotPathBegin) + repatchOffsetGetByIdBranchToSlowCase;
3172     X86Assembler::repatchBranchOffset(jmpLocation, code);
3173 #else
3174     // The prototype object definitely exists (if this stub exists the CodeBlock is referencing a Structure that is
3175     // referencing the prototype object - let's speculatively load it's table nice and early!)
3176     JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame));
3177     PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage;
3178     __ movl_mr(static_cast<void*>(protoPropertyStorage), X86::edx);
3179
3180     // Check eax is an object of the right Structure.
3181     __ testl_i32r(JSImmediate::TagMask, X86::eax);
3182     JmpSrc failureCases1 = __ jne();
3183     JmpSrc failureCases2 = checkStructure(X86::eax, structure);
3184
3185     // Check the prototype object's Structure had not changed.
3186     Structure** prototypeStructureAddress = &(protoObject->m_structure);
3187     __ cmpl_i32m(reinterpret_cast<uint32_t>(prototypeStructure), prototypeStructureAddress);
3188     JmpSrc failureCases3 = __ jne();
3189
3190     // Checks out okay! - getDirectOffset
3191     __ movl_mr(cachedOffset * sizeof(JSValue*), X86::edx, X86::eax);
3192
3193     __ ret();
3194
3195     void* code = __ executableCopy();
3196
3197     X86Assembler::link(code, failureCases1, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_proto_fail));
3198     X86Assembler::link(code, failureCases2, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_proto_fail));
3199     X86Assembler::link(code, failureCases3, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_proto_fail));
3200
3201     m_codeBlock->getStubInfo(returnAddress).stubRoutine = code;
3202
3203     ctiRepatchCallByReturnAddress(returnAddress, code);
3204 #endif
3205 }
3206
3207 #if USE(CTI_REPATCH_PIC)
3208 void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* polymorphicStructures, int currentIndex, Structure* structure, size_t cachedOffset)
3209 {
3210     JmpSrc failureCase = checkStructure(X86::eax, structure);
3211     __ movl_mr(FIELD_OFFSET(JSObject, m_propertyStorage), X86::eax, X86::eax);
3212     __ movl_mr(cachedOffset * sizeof(JSValue*), X86::eax, X86::eax);
3213     JmpSrc success = __ jmp();
3214
3215     void* code = __ executableCopy();
3216     ASSERT(code);
3217
3218     // Use the repatch information to link the failure cases back to the original slow case routine.
3219     void* lastProtoBegin = polymorphicStructures->list[currentIndex - 1].stubRoutine;
3220     if (!lastProtoBegin)
3221         lastProtoBegin = reinterpret_cast<char*>(stubInfo->callReturnLocation) - repatchOffsetGetByIdSlowCaseCall;
3222
3223     X86Assembler::link(code, failureCase, lastProtoBegin);
3224
3225     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
3226     intptr_t successDest = reinterpret_cast<intptr_t>(stubInfo->hotPathBegin) + repatchOffsetGetByIdPropertyMapOffset;
3227     X86Assembler::link(code, success, reinterpret_cast<void*>(successDest));
3228
3229     structure->ref();
3230     polymorphicStructures->list[currentIndex].set(cachedOffset, code, structure);
3231
3232     // Finally repatch the jump to slow case back in the hot path to jump here instead.
3233     intptr_t jmpLocation = reinterpret_cast<intptr_t>(stubInfo->hotPathBegin) + repatchOffsetGetByIdBranchToSlowCase;
3234     X86Assembler::repatchBranchOffset(jmpLocation, code);
3235 }
3236
3237 void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, Structure* prototypeStructure, size_t cachedOffset, CallFrame* callFrame)
3238 {
3239     // The prototype object definitely exists (if this stub exists the CodeBlock is referencing a Structure that is
3240     // referencing the prototype object - let's speculatively load it's table nice and early!)
3241     JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame));
3242     PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage;
3243     __ movl_mr(static_cast<void*>(protoPropertyStorage), X86::edx);
3244
3245     // Check eax is an object of the right Structure.
3246     JmpSrc failureCases1 = checkStructure(X86::eax, structure);
3247
3248     // Check the prototype object's Structure had not changed.
3249     Structure** prototypeStructureAddress = &(protoObject->m_structure);
3250     __ cmpl_i32m(reinterpret_cast<uint32_t>(prototypeStructure), prototypeStructureAddress);
3251     JmpSrc failureCases2 = __ jne();
3252
3253     // Checks out okay! - getDirectOffset
3254     __ movl_mr(cachedOffset * sizeof(JSValue*), X86::edx, X86::eax);
3255
3256     JmpSrc success = __ jmp();
3257
3258     void* code = __ executableCopy();
3259
3260     // Use the repatch information to link the failure cases back to the original slow case routine.
3261     void* lastProtoBegin = prototypeStructures->list[currentIndex - 1].stubRoutine;
3262     X86Assembler::link(code, failureCases1, lastProtoBegin);
3263     X86Assembler::link(code, failureCases2, lastProtoBegin);
3264
3265     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
3266     intptr_t successDest = reinterpret_cast<intptr_t>(stubInfo->hotPathBegin) + repatchOffsetGetByIdPropertyMapOffset;
3267     X86Assembler::link(code, success, reinterpret_cast<void*>(successDest));
3268
3269     structure->ref();
3270     prototypeStructure->ref();
3271     prototypeStructures->list[currentIndex].set(cachedOffset, code, structure, prototypeStructure);
3272
3273     // Finally repatch the jump to slow case back in the hot path to jump here instead.
3274     intptr_t jmpLocation = reinterpret_cast<intptr_t>(stubInfo->hotPathBegin) + repatchOffsetGetByIdBranchToSlowCase;
3275     X86Assembler::repatchBranchOffset(jmpLocation, code);
3276 }
3277
3278 void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, StructureChain* chain, size_t count, size_t cachedOffset, CallFrame* callFrame)
3279 {
3280     ASSERT(count);
3281     
3282     Vector<JmpSrc> bucketsOfFail;
3283
3284     // Check eax is an object of the right Structure.
3285     bucketsOfFail.append(checkStructure(X86::eax, structure));
3286
3287     Structure* currStructure = structure;
3288     RefPtr<Structure>* chainEntries = chain->head();
3289     JSObject* protoObject = 0;
3290     for (unsigned i = 0; i < count; ++i) {
3291         protoObject = asObject(currStructure->prototypeForLookup(callFrame));
3292         currStructure = chainEntries[i].get();
3293
3294         // Check the prototype object's Structure had not changed.
3295         Structure** prototypeStructureAddress = &(protoObject->m_structure);
3296         __ cmpl_i32m(reinterpret_cast<uint32_t>(currStructure), prototypeStructureAddress);
3297         bucketsOfFail.append(__ jne());
3298     }
3299     ASSERT(protoObject);
3300
3301     PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage;
3302     __ movl_mr(static_cast<void*>(protoPropertyStorage), X86::edx);
3303     __ movl_mr(cachedOffset * sizeof(JSValue*), X86::edx, X86::eax);
3304     JmpSrc success = __ jmp();
3305
3306     void* code = __ executableCopy();
3307
3308     // Use the repatch information to link the failure cases back to the original slow case routine.
3309     void* lastProtoBegin = prototypeStructures->list[currentIndex - 1].stubRoutine;
3310
3311     for (unsigned i = 0; i < bucketsOfFail.size(); ++i)
3312         X86Assembler::link(code, bucketsOfFail[i], lastProtoBegin);
3313
3314     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
3315     intptr_t successDest = reinterpret_cast<intptr_t>(stubInfo->hotPathBegin) + repatchOffsetGetByIdPropertyMapOffset;
3316     X86Assembler::link(code, success, reinterpret_cast<void*>(successDest));
3317
3318     // Track the stub we have created so that it will be deleted later.
3319     structure->ref();
3320     chain->ref();
3321     prototypeStructures->list[currentIndex].set(cachedOffset, code, structure, chain);
3322
3323     // Finally repatch the jump to slow case back in the hot path to jump here instead.
3324     intptr_t jmpLocation = reinterpret_cast<intptr_t>(stubInfo->hotPathBegin) + repatchOffsetGetByIdBranchToSlowCase;
3325     X86Assembler::repatchBranchOffset(jmpLocation, code);
3326 }
3327 #endif
3328
3329 void JIT::privateCompileGetByIdChain(Structure* structure, StructureChain* chain, size_t count, size_t cachedOffset, void* returnAddress, CallFrame* callFrame)
3330 {
3331 #if USE(CTI_REPATCH_PIC)
3332     StructureStubInfo& info = m_codeBlock->getStubInfo(returnAddress);
3333
3334     // We don't want to repatch more than once - in future go to cti_op_put_by_id_generic.
3335     ctiRepatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_proto_list));
3336
3337     ASSERT(count);
3338     
3339     Vector<JmpSrc> bucketsOfFail;
3340
3341     // Check eax is an object of the right Structure.
3342     bucketsOfFail.append(checkStructure(X86::eax, structure));
3343
3344     Structure* currStructure = structure;
3345     RefPtr<Structure>* chainEntries = chain->head();
3346     JSObject* protoObject = 0;
3347     for (unsigned i = 0; i < count; ++i) {
3348         protoObject = asObject(currStructure->prototypeForLookup(callFrame));
3349         currStructure = chainEntries[i].get();
3350
3351         // Check the prototype object's Structure had not changed.
3352         Structure** prototypeStructureAddress = &(protoObject->m_structure);
3353         __ cmpl_i32m(reinterpret_cast<uint32_t>(currStructure), prototypeStructureAddress);
3354         bucketsOfFail.append(__ jne());
3355     }
3356     ASSERT(protoObject);
3357
3358     PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage;
3359     __ movl_mr(static_cast<void*>(protoPropertyStorage), X86::edx);
3360     __ movl_mr(cachedOffset * sizeof(JSValue*), X86::edx, X86::eax);
3361     JmpSrc success = __ jmp();
3362
3363     void* code = __ executableCopy();
3364
3365     // Use the repatch information to link the failure cases back to the original slow case routine.
3366     void* slowCaseBegin = reinterpret_cast<char*>(info.callReturnLocation) - repatchOffsetGetByIdSlowCaseCall;
3367
3368     for (unsigned i = 0; i < bucketsOfFail.size(); ++i)
3369         X86Assembler::link(code, bucketsOfFail[i], slowCaseBegin);
3370
3371     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
3372     intptr_t successDest = reinterpret_cast<intptr_t>(info.hotPathBegin) + repatchOffsetGetByIdPropertyMapOffset;
3373     X86Assembler::link(code, success, reinterpret_cast<void*>(successDest));
3374
3375     // Track the stub we have created so that it will be deleted later.
3376     info.stubRoutine = code;
3377
3378     // Finally repatch the jump to slow case back in the hot path to jump here instead.
3379     intptr_t jmpLocation = reinterpret_cast<intptr_t>(info.hotPathBegin) + repatchOffsetGetByIdBranchToSlowCase;
3380     X86Assembler::repatchBranchOffset(jmpLocation, code);
3381 #else
3382     ASSERT(count);
3383     
3384     Vector<JmpSrc> bucketsOfFail;
3385
3386     // Check eax is an object of the right Structure.
3387     __ testl_i32r(JSImmediate::TagMask, X86::eax);
3388     bucketsOfFail.append(__ jne());
3389     bucketsOfFail.append(checkStructure(X86::eax, structure));
3390
3391     Structure* currStructure = structure;
3392     RefPtr<Structure>* chainEntries = chain->head();
3393     JSObject* protoObject = 0;
3394     for (unsigned i = 0; i < count; ++i) {
3395         protoObject = asObject(currStructure->prototypeForLookup(callFrame));
3396         currStructure = chainEntries[i].get();
3397
3398         // Check the prototype object's Structure had not changed.
3399         Structure** prototypeStructureAddress = &(protoObject->m_structure);
3400         __ cmpl_i32m(reinterpret_cast<uint32_t>(currStructure), prototypeStructureAddress);
3401         bucketsOfFail.append(__ jne());
3402     }
3403     ASSERT(protoObject);
3404
3405     PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage;
3406     __ movl_mr(static_cast<void*>(protoPropertyStorage), X86::edx);
3407     __ movl_mr(cachedOffset * sizeof(JSValue*), X86::edx, X86::eax);
3408     __ ret();
3409
3410     void* code = __ executableCopy();
3411
3412     for (unsigned i = 0; i < bucketsOfFail.size(); ++i)
3413         X86Assembler::link(code, bucketsOfFail[i], reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_proto_fail));
3414
3415     m_codeBlock->getStubInfo(returnAddress).stubRoutine = code;
3416
3417     ctiRepatchCallByReturnAddress(returnAddress, code);
3418 #endif
3419 }
3420
3421 void JIT::privateCompilePutByIdReplace(Structure* structure, size_t cachedOffset, void* returnAddress)
3422 {
3423     // Check eax is an object of the right Structure.
3424     __ testl_i32r(JSImmediate::TagMask, X86::eax);
3425     JmpSrc failureCases1 = __ jne();
3426     JmpSrc failureCases2 = checkStructure(X86::eax, structure);
3427
3428     // checks out okay! - putDirectOffset
3429     __ movl_mr(FIELD_OFFSET(JSObject, m_propertyStorage), X86::eax, X86::eax);
3430     __ movl_rm(X86::edx, cachedOffset * sizeof(JSValue*), X86::eax);
3431     __ ret();
3432
3433     void* code = __ executableCopy();
3434     
3435     X86Assembler::link(code, failureCases1, reinterpret_cast<void*>(Interpreter::cti_op_put_by_id_fail));
3436     X86Assembler::link(code, failureCases2, reinterpret_cast<void*>(Interpreter::cti_op_put_by_id_fail));
3437
3438     m_codeBlock->getStubInfo(returnAddress).stubRoutine = code;
3439     
3440     ctiRepatchCallByReturnAddress(returnAddress, code);
3441 }
3442
3443 extern "C" {
3444
3445     static JSObject* resizePropertyStorage(JSObject* baseObject, size_t oldSize, size_t newSize)
3446     {
3447         baseObject->allocatePropertyStorageInline(oldSize, newSize);
3448         return baseObject;
3449     }
3450
3451 }
3452
3453 static inline bool transitionWillNeedStorageRealloc(Structure* oldStructure, Structure* newStructure)
3454 {
3455     return oldStructure->propertyStorageCapacity() != newStructure->propertyStorageCapacity();
3456 }
3457
3458 void JIT::privateCompilePutByIdTransition(Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, void* returnAddress)
3459 {
3460     Vector<JmpSrc, 16> failureCases;
3461     // Check eax is an object of the right Structure.
3462     __ testl_i32r(JSImmediate::TagMask, X86::eax);
3463     failureCases.append(__ jne());
3464     __ cmpl_i32m(reinterpret_cast<uint32_t>(oldStructure), FIELD_OFFSET(JSCell, m_structure), X86::eax);
3465     failureCases.append(__ jne());
3466     Vector<JmpSrc> successCases;
3467
3468     //  ecx = baseObject
3469     __ movl_mr(FIELD_OFFSET(JSCell, m_structure), X86::eax, X86::ecx);
3470     // proto(ecx) = baseObject->structure()->prototype()
3471     __ cmpl_i32m(ObjectType, FIELD_OFFSET(Structure, m_typeInfo) + FIELD_OFFSET(TypeInfo, m_type), X86::ecx);
3472     failureCases.append(__ jne());
3473     __ movl_mr(FIELD_OFFSET(Structure, m_prototype), X86::ecx, X86::ecx);
3474     
3475     // ecx = baseObject->m_structure
3476     for (RefPtr<Structure>* it = chain->head(); *it; ++it) {
3477         // null check the prototype
3478         __ cmpl_i32r(asInteger(jsNull()), X86::ecx);
3479         successCases.append(__ je());
3480
3481         // Check the structure id
3482         __ cmpl_i32m(reinterpret_cast<uint32_t>(it->get()), FIELD_OFFSET(JSCell, m_structure), X86::ecx);
3483         failureCases.append(__ jne());
3484         
3485         __ movl_mr(FIELD_OFFSET(JSCell, m_structure), X86::ecx, X86::ecx);
3486         __ cmpl_i32m(ObjectType, FIELD_OFFSET(Structure, m_typeInfo) + FIELD_OFFSET(TypeInfo, m_type), X86::ecx);
3487         failureCases.append(__ jne());
3488         __ movl_mr(FIELD_OFFSET(Structure, m_prototype), X86::ecx, X86::ecx);
3489     }
3490
3491     failureCases.append(__ jne());
3492     for (unsigned i = 0; i < successCases.size(); ++i)
3493         __ link(successCases[i], __ label());
3494
3495     JmpSrc callTarget;
3496
3497     // emit a call only if storage realloc is needed
3498     if (transitionWillNeedStorageRealloc(oldStructure, newStructure)) {
3499         __ pushl_r(X86::edx);
3500         __ pushl_i32(newStructure->propertyStorageCapacity());
3501         __ pushl_i32(oldStructure->propertyStorageCapacity());
3502         __ pushl_r(X86::eax);
3503         callTarget = __ call();
3504         __ addl_i32r(3 * sizeof(void*), X86::esp);
3505         __ popl_r(X86::edx);
3506     }
3507
3508     // Assumes m_refCount can be decremented easily, refcount decrement is safe as 
3509     // codeblock should ensure oldStructure->m_refCount > 0
3510     __ subl_i8m(1, reinterpret_cast<void*>(oldStructure));
3511     __ addl_i8m(1, reinterpret_cast<void*>(newStructure));
3512     __ movl_i32m(reinterpret_cast<uint32_t>(newStructure), FIELD_OFFSET(JSCell, m_structure), X86::eax);
3513
3514     // write the value
3515     __ movl_mr(FIELD_OFFSET(JSObject, m_propertyStorage), X86::eax, X86::eax);
3516     __ movl_rm(X86::edx, cachedOffset * sizeof(JSValue*), X86::eax);
3517
3518     __ ret();
3519     
3520     JmpSrc failureJump;
3521     if (failureCases.size()) {
3522         for (unsigned i = 0; i < failureCases.size(); ++i)
3523             __ link(failureCases[i], __ label());
3524         __ restoreArgumentReferenceForTrampoline();
3525         failureJump = __ jmp();
3526     }
3527
3528     void* code = __ executableCopy();
3529
3530     if (failureCases.size())
3531         X86Assembler::link(code, failureJump, reinterpret_cast<void*>(Interpreter::cti_op_put_by_id_fail));
3532
3533     if (transitionWillNeedStorageRealloc(oldStructure, newStructure))
3534         X86Assembler::link(code, callTarget, reinterpret_cast<void*>(resizePropertyStorage));
3535     
3536     m_codeBlock->getStubInfo(returnAddress).stubRoutine = code;
3537     
3538     ctiRepatchCallByReturnAddress(returnAddress, code);
3539 }
3540
3541 void JIT::unlinkCall(CallLinkInfo* callLinkInfo)
3542 {
3543     // When the JSFunction is deleted the pointer embedded in the instruction stream will no longer be valid
3544     // (and, if a new JSFunction happened to be constructed at the same location, we could get a false positive
3545     // match).  Reset the check so it no longer matches.
3546     reinterpret_cast<void**>(callLinkInfo->hotPathBegin)[-1] = asPointer(JSImmediate::impossibleValue());
3547 }
3548
3549 void JIT::linkCall(JSFunction* callee, CodeBlock* calleeCodeBlock, void* ctiCode, CallLinkInfo* callLinkInfo, int callerArgCount)
3550 {
3551     // Currently we only link calls with the exact number of arguments.
3552     if (callerArgCount == calleeCodeBlock->numParameters) {
3553         ASSERT(!callLinkInfo->isLinked());
3554     
3555         calleeCodeBlock->addCaller(callLinkInfo);
3556     
3557         reinterpret_cast<void**>(callLinkInfo->hotPathBegin)[-1] = callee;
3558         ctiRepatchCallByReturnAddress(callLinkInfo->hotPathOther, ctiCode);
3559     }
3560
3561     // repatch the instruction that jumps out to the cold path, so that we only try to link once.
3562     void* repatchCheck = reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(callLinkInfo->hotPathBegin) + repatchOffsetOpCallCall);
3563     ctiRepatchCallByReturnAddress(repatchCheck, callLinkInfo->coldPathOther);
3564 }
3565
3566 void JIT::privateCompileCTIMachineTrampolines()
3567 {
3568     // (1) The first function provides fast property access for array length
3569     
3570     // Check eax is an array
3571     __ testl_i32r(JSImmediate::TagMask, X86::eax);
3572     JmpSrc array_failureCases1 = __ jne();
3573     __ cmpl_i32m(reinterpret_cast<unsigned>(m_interpreter->m_jsArrayVptr), X86::eax);
3574     JmpSrc array_failureCases2 = __ jne();
3575
3576     // Checks out okay! - get the length from the storage
3577     __ movl_mr(FIELD_OFFSET(JSArray, m_storage), X86::eax, X86::eax);
3578     __ movl_mr(FIELD_OFFSET(ArrayStorage, m_length), X86::eax, X86::eax);
3579
3580     __ cmpl_i32r(JSImmediate::maxImmediateInt, X86::eax);
3581     JmpSrc array_failureCases3 = __ ja();
3582
3583     __ addl_rr(X86::eax, X86::eax);
3584     __ addl_i8r(1, X86::eax);
3585     
3586     __ ret();
3587
3588     // (2) The second function provides fast property access for string length
3589     
3590     JmpDst stringLengthBegin = __ align(16);
3591
3592     // Check eax is a string
3593     __ testl_i32r(JSImmediate::TagMask, X86::eax);
3594     JmpSrc string_failureCases1 = __ jne();
3595     __ cmpl_i32m(reinterpret_cast<unsigned>(m_interpreter->m_jsStringVptr), X86::eax);
3596     JmpSrc string_failureCases2 = __ jne();
3597
3598     // Checks out okay! - get the length from the Ustring.
3599     __ movl_mr(FIELD_OFFSET(JSString, m_value) + FIELD_OFFSET(UString, m_rep), X86::eax, X86::eax);
3600     __ movl_mr(FIELD_OFFSET(UString::Rep, len), X86::eax, X86::eax);
3601
3602     __ cmpl_i32r(JSImmediate::maxImmediateInt, X86::eax);
3603     JmpSrc string_failureCases3 = __ ja();
3604
3605     __ addl_rr(X86::eax, X86::eax);
3606     __ addl_i8r(1, X86::eax);
3607     
3608     __ ret();
3609
3610     // (3) Trampolines for the slow cases of op_call / op_call_eval / op_construct.
3611     
3612     JmpDst virtualCallPreLinkBegin = __ align(16);
3613
3614     // Load the callee CodeBlock* into eax
3615     __ movl_mr(FIELD_OFFSET(JSFunction, m_body), X86::ecx, X86::eax);
3616     __ movl_mr(FIELD_OFFSET(FunctionBodyNode, m_code), X86::eax, X86::eax);
3617     __ testl_rr(X86::eax, X86::eax);
3618     JmpSrc hasCodeBlock1 = __ jne();
3619     __ popl_r(X86::ebx);
3620     __ restoreArgumentReference();
3621     emitPutCTIParam(X86::edi, CTI_ARGS_callFrame);
3622     JmpSrc callJSFunction1 = __ call();
3623     emitGetCTIArg(0, X86::ecx);
3624     emitGetCTIArg(8, X86::edx);
3625     __ pushl_r(X86::ebx);
3626     __ link(hasCodeBlock1, __ label());
3627
3628     // Check argCount matches callee arity.
3629     __ cmpl_rm(X86::edx, FIELD_OFFSET(CodeBlock, numParameters), X86::eax);
3630     JmpSrc arityCheckOkay1 = __ je();
3631     __ popl_r(X86::ebx);
3632     emitPutCTIArg(X86::ebx, 4);
3633     emitPutCTIArg(X86::eax, 12);
3634     __ restoreArgumentReference();
3635     emitPutCTIParam(X86::edi, CTI_ARGS_callFrame);
3636     JmpSrc callArityCheck1 = __ call();
3637     __ movl_rr(X86::edx, X86::edi);
3638     emitGetCTIArg(0, X86::ecx);
3639     emitGetCTIArg(8, X86::edx);
3640     __ pushl_r(X86::ebx);
3641     __ link(arityCheckOkay1, __ label());
3642
3643     compileOpCallInitializeCallFrame();
3644
3645     __ popl_r(X86::ebx);
3646     emitPutCTIArg(X86::ebx, 4);
3647     __ restoreArgumentReference();
3648     emitPutCTIParam(X86::edi, CTI_ARGS_callFrame);
3649     JmpSrc callDontLazyLinkCall = __ call();
3650     __ pushl_r(X86::ebx);
3651
3652     __ jmp_r(X86::eax);
3653
3654     JmpDst virtualCallLinkBegin = __ align(16);
3655
3656     // Load the callee CodeBlock* into eax
3657     __ movl_mr(FIELD_OFFSET(JSFunction, m_body), X86::ecx, X86::eax);
3658     __ movl_mr(FIELD_OFFSET(FunctionBodyNode, m_code), X86::eax, X86::eax);
3659     __ testl_rr(X86::eax, X86::eax);
3660     JmpSrc hasCodeBlock2 = __ jne();
3661     __ popl_r(X86::ebx);
3662     __ restoreArgumentReference();
3663     emitPutCTIParam(X86::edi, CTI_ARGS_callFrame);
3664     JmpSrc callJSFunction2 = __ call();
3665     emitGetCTIArg(0, X86::ecx);
3666     emitGetCTIArg(8, X86::edx);
3667     __ pushl_r(X86::ebx);
3668     __ link(hasCodeBlock2, __ label());
3669
3670     // Check argCount matches callee arity.
3671     __ cmpl_rm(X86::edx, FIELD_OFFSET(CodeBlock, numParameters), X86::eax);
3672     JmpSrc arityCheckOkay2 = __ je();
3673     __ popl_r(X86::ebx);
3674     emitPutCTIArg(X86::ebx, 4);
3675     emitPutCTIArg(X86::eax, 12);
3676     __ restoreArgumentReference();
3677     emitPutCTIParam(X86::edi, CTI_ARGS_callFrame);
3678     JmpSrc callArityCheck2 = __ call();
3679     __ movl_rr(X86::edx, X86::edi);
3680     emitGetCTIArg(0, X86::ecx);
3681     emitGetCTIArg(8, X86::edx);
3682     __ pushl_r(X86::ebx);
3683     __ link(arityCheckOkay2, __ label());
3684
3685     compileOpCallInitializeCallFrame();
3686
3687     __ popl_r(X86::ebx);
3688     emitPutCTIArg(X86::ebx, 4);
3689     __ restoreArgumentReference();
3690     emitPutCTIParam(X86::edi, CTI_ARGS_callFrame);
3691     JmpSrc callLazyLinkCall = __ call();
3692     __ pushl_r(X86::ebx);
3693
3694     __ jmp_r(X86::eax);
3695
3696     JmpDst virtualCallBegin = __ align(16);
3697
3698     // Load the callee CodeBlock* into eax
3699     __ movl_mr(FIELD_OFFSET(JSFunction, m_body), X86::ecx, X86::eax);
3700     __ movl_mr(FIELD_OFFSET(FunctionBodyNode, m_code), X86::eax, X86::eax);
3701     __ testl_rr(X86::eax, X86::eax);
3702     JmpSrc hasCodeBlock3 = __ jne();
3703     __ popl_r(X86::ebx);
3704     __ restoreArgumentReference();
3705     emitPutCTIParam(X86::edi, CTI_ARGS_callFrame);
3706     JmpSrc callJSFunction3 = __ call();
3707     emitGetCTIArg(0, X86::ecx);
3708     emitGetCTIArg(8, X86::edx);
3709     __ pushl_r(X86::ebx);
3710     __ link(hasCodeBlock3, __ label());
3711
3712     // Check argCount matches callee arity.
3713     __ cmpl_rm(X86::edx, FIELD_OFFSET(CodeBlock, numParameters), X86::eax);
3714     JmpSrc arityCheckOkay3 = __ je();
3715     __ popl_r(X86::ebx);
3716     emitPutCTIArg(X86::ebx, 4);
3717     emitPutCTIArg(X86::eax, 12);
3718     __ restoreArgumentReference();
3719     emitPutCTIParam(X86::edi, CTI_ARGS_callFrame);
3720     JmpSrc callArityCheck3 = __ call();
3721     __ movl_rr(X86::edx, X86::edi);
3722     emitGetCTIArg(0, X86::ecx);
3723     emitGetCTIArg(8, X86::edx);
3724     __ pushl_r(X86::ebx);
3725     __ link(arityCheckOkay3, __ label());
3726
3727     compileOpCallInitializeCallFrame();
3728
3729     // load ctiCode from the new codeBlock.
3730     __ movl_mr(FIELD_OFFSET(CodeBlock, ctiCode), X86::eax, X86::eax);
3731
3732     __ jmp_r(X86::eax);
3733
3734     // All trampolines constructed! copy the code, link up calls, and set the pointers on the Machine object.
3735
3736     void* code = __ executableCopy();
3737
3738     X86Assembler::link(code, array_failureCases1, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_array_fail));
3739     X86Assembler::link(code, array_failureCases2, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_array_fail));
3740     X86Assembler::link(code, array_failureCases3, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_array_fail));
3741     X86Assembler::link(code, string_failureCases1, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_string_fail));
3742     X86Assembler::link(code, string_failureCases2, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_string_fail));
3743     X86Assembler::link(code, string_failureCases3, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_string_fail));
3744     X86Assembler::link(code, callArityCheck1, reinterpret_cast<void*>(Interpreter::cti_op_call_arityCheck));
3745     X86Assembler::link(code, callArityCheck2, reinterpret_cast<void*>(Interpreter::cti_op_call_arityCheck));
3746     X86Assembler::link(code, callArityCheck3, reinterpret_cast<void*>(Interpreter::cti_op_call_arityCheck));
3747     X86Assembler::link(code, callJSFunction1, reinterpret_cast<void*>(Interpreter::cti_op_call_JSFunction));
3748     X86Assembler::link(code, callJSFunction2, reinterpret_cast<void*>(Interpreter::cti_op_call_JSFunction));
3749     X86Assembler::link(code, callJSFunction3, reinterpret_cast<void*>(Interpreter::cti_op_call_JSFunction));
3750     X86Assembler::link(code, callDontLazyLinkCall, reinterpret_cast<void*>(Interpreter::cti_vm_dontLazyLinkCall));
3751     X86Assembler::link(code, callLazyLinkCall, reinterpret_cast<void*>(Interpreter::cti_vm_lazyLinkCall));
3752
3753     m_interpreter->m_ctiArrayLengthTrampoline = code;
3754     m_interpreter->m_ctiStringLengthTrampoline = X86Assembler::getRelocatedAddress(code, stringLengthBegin);
3755     m_interpreter->m_ctiVirtualCallPreLink = X86Assembler::getRelocatedAddress(code, virtualCallPreLinkBegin);
3756     m_interpreter->m_ctiVirtualCallLink = X86Assembler::getRelocatedAddress(code, virtualCallLinkBegin);
3757     m_interpreter->m_ctiVirtualCall = X86Assembler::getRelocatedAddress(code, virtualCallBegin);
3758 }
3759
3760 void JIT::freeCTIMachineTrampolines(Interpreter* interpreter)
3761 {
3762     WTF::fastFreeExecutable(interpreter->m_ctiArrayLengthTrampoline);
3763 }
3764
3765 void JIT::patchGetByIdSelf(CodeBlock* codeBlock, Structure* structure, size_t cachedOffset, void* returnAddress)
3766 {
3767     StructureStubInfo& info = codeBlock->getStubInfo(returnAddress);
3768
3769     // We don't want to repatch more than once - in future go to cti_op_get_by_id_generic.
3770     // Should probably go to Interpreter::cti_op_get_by_id_fail, but that doesn't do anything interesting right now.
3771     ctiRepatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_self_fail));
3772
3773     // Repatch the offset into the propoerty map to load from, then repatch the Structure to look for.
3774     X86Assembler::repatchDisplacement(reinterpret_cast<intptr_t>(info.hotPathBegin) + repatchOffsetGetByIdPropertyMapOffset, cachedOffset * sizeof(JSValue*));
3775     X86Assembler::repatchImmediate(reinterpret_cast<intptr_t>(info.hotPathBegin) + repatchOffsetGetByIdStructure, reinterpret_cast<uint32_t>(structure));
3776 }
3777
3778 void JIT::patchPutByIdReplace(CodeBlock* codeBlock, Structure* structure, size_t cachedOffset, void* returnAddress)
3779 {
3780     StructureStubInfo& info = codeBlock->getStubInfo(returnAddress);
3781     
3782     // We don't want to repatch more than once - in future go to cti_op_put_by_id_generic.
3783     // Should probably go to Interpreter::cti_op_put_by_id_fail, but that doesn't do anything interesting right now.
3784     ctiRepatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(Interpreter::cti_op_put_by_id_generic));
3785
3786     // Repatch the offset into the propoerty map to load from, then repatch the Structure to look for.
3787     X86Assembler::repatchDisplacement(reinterpret_cast<intptr_t>(info.hotPathBegin) + repatchOffsetPutByIdPropertyMapOffset, cachedOffset * sizeof(JSValue*));
3788     X86Assembler::repatchImmediate(reinterpret_cast<intptr_t>(info.hotPathBegin) + repatchOffsetPutByIdStructure, reinterpret_cast<uint32_t>(structure));
3789 }
3790
3791 void JIT::privateCompilePatchGetArrayLength(void* returnAddress)
3792 {
3793     StructureStubInfo& info = m_codeBlock->getStubInfo(returnAddress);
3794
3795     // We don't want to repatch more than once - in future go to cti_op_put_by_id_generic.
3796     ctiRepatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_array_fail));
3797
3798     // Check eax is an array
3799     __ cmpl_i32m(reinterpret_cast<unsigned>(m_interpreter->m_jsArrayVptr), X86::eax);
3800     JmpSrc failureCases1 = __ jne();
3801
3802     // Checks out okay! - get the length from the storage
3803     __ movl_mr(FIELD_OFFSET(JSArray, m_storage), X86::eax, X86::ecx);
3804     __ movl_mr(FIELD_OFFSET(ArrayStorage, m_length), X86::ecx, X86::ecx);
3805
3806     __ cmpl_i32r(JSImmediate::maxImmediateInt, X86::ecx);
3807     JmpSrc failureCases2 = __ ja();
3808
3809     __ addl_rr(X86::ecx, X86::ecx);
3810     __ addl_i8r(1, X86::ecx);
3811     __ movl_rr(X86::ecx, X86::eax);
3812     JmpSrc success = __ jmp();
3813
3814     void* code = __ executableCopy();
3815
3816     // Use the repatch information to link the failure cases back to the original slow case routine.
3817     void* slowCaseBegin = reinterpret_cast<char*>(info.callReturnLocation) - repatchOffsetGetByIdSlowCaseCall;
3818     X86Assembler::link(code, failureCases1, slowCaseBegin);
3819     X86Assembler::link(code, failureCases2, slowCaseBegin);
3820
3821     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
3822     intptr_t successDest = reinterpret_cast<intptr_t>(info.hotPathBegin) + repatchOffsetGetByIdPropertyMapOffset;
3823     X86Assembler::link(code, success, reinterpret_cast<void*>(successDest));
3824
3825     // Track the stub we have created so that it will be deleted later.
3826     m_codeBlock->getStubInfo(returnAddress).stubRoutine = code;
3827
3828     // Finally repatch the jump to sow case back in the hot path to jump here instead.
3829     intptr_t jmpLocation = reinterpret_cast<intptr_t>(info.hotPathBegin) + repatchOffsetGetByIdBranchToSlowCase;
3830     X86Assembler::repatchBranchOffset(jmpLocation, code);
3831 }
3832
3833 void JIT::emitGetVariableObjectRegister(RegisterID variableObject, int index, RegisterID dst)
3834 {
3835     __ movl_mr(FIELD_OFFSET(JSVariableObject, d), variableObject, dst);
3836     __ movl_mr(FIELD_OFFSET(JSVariableObject::JSVariableObjectData, registers), dst, dst);
3837     __ movl_mr(index * sizeof(Register), dst, dst);
3838 }
3839
3840 void JIT::emitPutVariableObjectRegister(RegisterID src, RegisterID variableObject, int index)
3841 {
3842     __ movl_mr(FIELD_OFFSET(JSVariableObject, d), variableObject, variableObject);
3843     __ movl_mr(FIELD_OFFSET(JSVariableObject::JSVariableObjectData, registers), variableObject, variableObject);
3844     __ movl_rm(src, index * sizeof(Register), variableObject);
3845 }
3846
3847 } // namespace JSC
3848
3849 #endif // ENABLE(JIT)