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