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