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