Bug 20821: Cache property transitions to speed up object initialization
[WebKit-https.git] / JavaScriptCore / VM / CTI.cpp
1 /*
2  * Copyright (C) 2008 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "CTI.h"
28
29 #if ENABLE(CTI)
30
31 #include "CodeBlock.h"
32 #include "JSArray.h"
33 #include "Machine.h"
34 #include "wrec/WREC.h"
35
36 using namespace std;
37
38 namespace JSC {
39
40 #if COMPILER(GCC) && PLATFORM(X86)
41 asm(
42 ".globl _ctiTrampoline" "\n"
43 "_ctiTrampoline:" "\n"
44     "pushl %esi" "\n"
45     "pushl %edi" "\n"
46     "subl $0x24, %esp" "\n"
47     "movl $512, %esi" "\n"
48     "call *0x30(%esp)" "\n" //Ox30 = 0x0C * 4, 0x0C = CTI_ARGS_code
49     "addl $0x24, %esp" "\n"
50     "popl %edi" "\n"
51     "popl %esi" "\n"
52     "ret" "\n"
53 );
54
55 asm(
56 ".globl _ctiVMThrowTrampoline" "\n"
57 "_ctiVMThrowTrampoline:" "\n"
58 #ifndef NDEBUG
59     "movl 0x34(%esp), %ecx" "\n" //Ox34 = 0x0D * 4, 0x0D = CTI_ARGS_exec
60     "cmpl $0, 8(%ecx)" "\n"
61     "jne 1f" "\n"
62     "int3" "\n"
63     "1:" "\n"
64 #endif
65     "call __ZN3JSC7Machine12cti_vm_throwEPv" "\n"
66     "addl $0x24, %esp" "\n"
67     "popl %edi" "\n"
68     "popl %esi" "\n"
69     "ret" "\n"
70 );
71     
72 #elif COMPILER(MSVC)
73 extern "C"
74 {
75     
76     __declspec(naked) JSValue* ctiTrampoline(void* code, ExecState* exec, RegisterFile* registerFile, Register* r, ScopeChainNode* scopeChain, CodeBlock* codeBlock, JSValue** exception, Profiler**)
77     {
78         __asm {
79             push esi;
80             push edi;
81             sub esp, 0x24;
82             mov esi, 512;
83             mov [esp], esp;
84             call [esp + 0x30];
85             add esp, 0x24;
86             pop edi;
87             pop esi;
88             ret;
89         }
90     }
91     
92     __declspec(naked) void ctiVMThrowTrampoline()
93     {
94         __asm {
95            mov [esp], esp;
96             call JSC::Machine::cti_vm_throw;
97             add esp, 0x24;
98             pop edi;
99             pop esi;
100             ret;
101         }
102     }
103     
104 }
105
106 #endif
107
108
109 // get arg puts an arg from the SF register array into a h/w register
110 ALWAYS_INLINE void CTI::emitGetArg(unsigned src, X86Assembler::RegisterID dst)
111 {
112     // TODO: we want to reuse values that are already in registers if we can - add a register allocator!
113     if (src < m_codeBlock->constantRegisters.size()) {
114         JSValue* js = m_codeBlock->constantRegisters[src].jsValue(m_exec);
115         m_jit.movl_i32r(reinterpret_cast<unsigned>(js), dst);
116     } else
117         m_jit.movl_mr(src * sizeof(Register), X86::edi, dst);
118 }
119
120 // get arg puts an arg from the SF register array onto the stack, as an arg to a context threaded function.
121 ALWAYS_INLINE void CTI::emitGetPutArg(unsigned src, unsigned offset, X86Assembler::RegisterID scratch)
122 {
123     if (src < m_codeBlock->constantRegisters.size()) {
124         JSValue* js = m_codeBlock->constantRegisters[src].jsValue(m_exec);
125         m_jit.movl_i32m(reinterpret_cast<unsigned>(js), offset + sizeof(void*), X86::esp);
126     } else {
127         m_jit.movl_mr(src * sizeof(Register), X86::edi, scratch);
128         m_jit.movl_rm(scratch, offset + sizeof(void*), X86::esp);
129     }
130 }
131
132 // puts an arg onto the stack, as an arg to a context threaded function.
133 ALWAYS_INLINE void CTI::emitPutArg(X86Assembler::RegisterID src, unsigned offset)
134 {
135     m_jit.movl_rm(src, offset + sizeof(void*), X86::esp);
136 }
137
138 ALWAYS_INLINE void CTI::emitPutArgConstant(unsigned value, unsigned offset)
139 {
140     m_jit.movl_i32m(value, offset + sizeof(void*), X86::esp);
141 }
142
143 ALWAYS_INLINE JSValue* CTI::getConstantImmediateNumericArg(unsigned src)
144 {
145     if (src < m_codeBlock->constantRegisters.size()) {
146         JSValue* js = m_codeBlock->constantRegisters[src].jsValue(m_exec);
147         return JSImmediate::isNumber(js) ? js : 0;
148     }
149     return 0;
150 }
151
152 ALWAYS_INLINE void CTI::emitPutCTIParam(X86Assembler::RegisterID from, unsigned name)
153 {
154     m_jit.movl_rm(from, name * sizeof(void*), X86::esp);
155 }
156
157 ALWAYS_INLINE void CTI::emitGetCTIParam(unsigned name, X86Assembler::RegisterID to)
158 {
159     m_jit.movl_mr(name * sizeof(void*), X86::esp, to);
160 }
161
162 ALWAYS_INLINE void CTI::emitPutToCallFrameHeader(X86Assembler::RegisterID from, RegisterFile::CallFrameHeaderEntry entry)
163 {
164     m_jit.movl_rm(from, -((m_codeBlock->numLocals + RegisterFile::CallFrameHeaderSize) - entry) * sizeof(Register), X86::edi);
165 }
166
167 ALWAYS_INLINE void CTI::emitGetFromCallFrameHeader(RegisterFile::CallFrameHeaderEntry entry, X86Assembler::RegisterID to)
168 {
169     m_jit.movl_mr(-((m_codeBlock->numLocals + RegisterFile::CallFrameHeaderSize) - entry) * sizeof(Register), X86::edi, to);
170 }
171
172 ALWAYS_INLINE void CTI::emitPutResult(unsigned dst, X86Assembler::RegisterID from)
173 {
174     m_jit.movl_rm(from, dst * sizeof(Register), X86::edi);
175     // FIXME: #ifndef NDEBUG, Write the correct m_type to the register.
176 }
177
178 #if ENABLE(SAMPLING_TOOL)
179 unsigned incall = 0;
180 #endif
181
182 void ctiSetReturnAddress(void** where, void* what)
183 {
184     *where = what;
185 }
186
187 void ctiRepatchCallByReturnAddress(void* where, void* what)
188 {
189     (static_cast<void**>(where))[-1] = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(what) - reinterpret_cast<uintptr_t>(where));
190 }
191
192 #ifdef NDEBUG
193
194 ALWAYS_INLINE void CTI::emitDebugExceptionCheck()
195 {
196 }
197
198 #else
199
200 ALWAYS_INLINE void CTI::emitDebugExceptionCheck()
201 {
202     emitGetCTIParam(CTI_ARGS_exec, X86::ecx);
203     m_jit.cmpl_i32m(0, OBJECT_OFFSET(ExecState, m_exception), X86::ecx);
204     X86Assembler::JmpSrc noException = m_jit.emitUnlinkedJe();
205     m_jit.emitInt3();
206     m_jit.link(noException, m_jit.label());
207 }
208
209 void CTI::printOpcodeOperandTypes(unsigned src1, unsigned src2)
210 {
211     char which1 = '*';
212     if (src1 < m_codeBlock->constantRegisters.size()) {
213         JSValue* js = m_codeBlock->constantRegisters[src1].jsValue(m_exec);
214         which1 = 
215             JSImmediate::isImmediate(js) ?
216                 (JSImmediate::isNumber(js) ? 'i' :
217                 JSImmediate::isBoolean(js) ? 'b' :
218                 js->isUndefined() ? 'u' :
219                 js->isNull() ? 'n' : '?')
220                 :
221             (js->isString() ? 's' :
222             js->isObject() ? 'o' :
223             'k');
224     }
225     char which2 = '*';
226     if (src2 < m_codeBlock->constantRegisters.size()) {
227         JSValue* js = m_codeBlock->constantRegisters[src2].jsValue(m_exec);
228         which2 = 
229             JSImmediate::isImmediate(js) ?
230                 (JSImmediate::isNumber(js) ? 'i' :
231                 JSImmediate::isBoolean(js) ? 'b' :
232                 js->isUndefined() ? 'u' :
233                 js->isNull() ? 'n' : '?')
234                 :
235             (js->isString() ? 's' :
236             js->isObject() ? 'o' :
237             'k');
238     }
239     if ((which1 != '*') | (which2 != '*'))
240         fprintf(stderr, "Types %c %c\n", which1, which2);
241 }
242
243 #endif
244
245 ALWAYS_INLINE void CTI::emitCall(unsigned opcodeIndex, CTIHelper_j helper)
246 {
247 #if ENABLE(SAMPLING_TOOL)
248     m_jit.movl_i32m(1, &incall);
249 #endif
250     m_calls.append(CallRecord(m_jit.emitCall(), helper, opcodeIndex));
251     emitDebugExceptionCheck();
252 #if ENABLE(SAMPLING_TOOL)
253     m_jit.movl_i32m(0, &incall);
254 #endif
255 }
256
257 ALWAYS_INLINE void CTI::emitCall(unsigned opcodeIndex, CTIHelper_p helper)
258 {
259 #if ENABLE(SAMPLING_TOOL)
260     m_jit.movl_i32m(1, &incall);
261 #endif
262     m_calls.append(CallRecord(m_jit.emitCall(), helper, opcodeIndex));
263     emitDebugExceptionCheck();
264 #if ENABLE(SAMPLING_TOOL)
265     m_jit.movl_i32m(0, &incall);
266 #endif
267 }
268
269 ALWAYS_INLINE void CTI::emitCall(unsigned opcodeIndex, CTIHelper_b helper)
270 {
271 #if ENABLE(SAMPLING_TOOL)
272     m_jit.movl_i32m(1, &incall);
273 #endif
274     m_calls.append(CallRecord(m_jit.emitCall(), helper, opcodeIndex));
275     emitDebugExceptionCheck();
276 #if ENABLE(SAMPLING_TOOL)
277     m_jit.movl_i32m(0, &incall);
278 #endif
279 }
280
281 ALWAYS_INLINE void CTI::emitCall(unsigned opcodeIndex, CTIHelper_v helper)
282 {
283 #if ENABLE(SAMPLING_TOOL)
284     m_jit.movl_i32m(1, &incall);
285 #endif
286     m_calls.append(CallRecord(m_jit.emitCall(), helper, opcodeIndex));
287     emitDebugExceptionCheck();
288 #if ENABLE(SAMPLING_TOOL)
289     m_jit.movl_i32m(0, &incall);
290 #endif
291 }
292
293 ALWAYS_INLINE void CTI::emitCall(unsigned opcodeIndex, CTIHelper_s helper)
294 {
295 #if ENABLE(SAMPLING_TOOL)
296     m_jit.movl_i32m(1, &incall);
297 #endif
298     m_calls.append(CallRecord(m_jit.emitCall(), helper, opcodeIndex));
299     emitDebugExceptionCheck();
300 #if ENABLE(SAMPLING_TOOL)
301     m_jit.movl_i32m(0, &incall);
302 #endif
303 }
304
305 ALWAYS_INLINE void CTI::emitJumpSlowCaseIfNotImm(X86Assembler::RegisterID reg, unsigned opcodeIndex)
306 {
307     m_jit.testl_i32r(JSImmediate::TagBitTypeInteger, reg);
308     m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJe(), opcodeIndex));
309 }
310
311 ALWAYS_INLINE void CTI::emitJumpSlowCaseIfNotImms(X86Assembler::RegisterID reg1, X86Assembler::RegisterID reg2, unsigned opcodeIndex)
312 {
313     m_jit.movl_rr(reg1, X86::ecx);
314     m_jit.andl_rr(reg2, X86::ecx);
315     emitJumpSlowCaseIfNotImm(X86::ecx, opcodeIndex);
316 }
317
318 ALWAYS_INLINE unsigned CTI::getDeTaggedConstantImmediate(JSValue* imm)
319 {
320     ASSERT(JSImmediate::isNumber(imm));
321     return reinterpret_cast<unsigned>(imm) & ~JSImmediate::TagBitTypeInteger;
322 }
323
324 ALWAYS_INLINE void CTI::emitFastArithDeTagImmediate(X86Assembler::RegisterID reg)
325 {
326     // op_mod relies on this being a sub - setting zf if result is 0.
327     m_jit.subl_i8r(JSImmediate::TagBitTypeInteger, reg);
328 }
329
330 ALWAYS_INLINE void CTI::emitFastArithReTagImmediate(X86Assembler::RegisterID reg)
331 {
332     m_jit.addl_i8r(JSImmediate::TagBitTypeInteger, reg);
333 }
334
335 ALWAYS_INLINE void CTI::emitFastArithPotentiallyReTagImmediate(X86Assembler::RegisterID reg)
336 {
337     m_jit.orl_i32r(JSImmediate::TagBitTypeInteger, reg);
338 }
339
340 ALWAYS_INLINE void CTI::emitFastArithImmToInt(X86Assembler::RegisterID reg)
341 {
342     m_jit.sarl_i8r(1, reg);
343 }
344
345 ALWAYS_INLINE void CTI::emitFastArithIntToImmOrSlowCase(X86Assembler::RegisterID reg, unsigned opcodeIndex)
346 {
347     m_jit.addl_rr(reg, reg);
348     m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), opcodeIndex));
349     emitFastArithReTagImmediate(reg);
350 }
351
352 ALWAYS_INLINE void CTI::emitFastArithIntToImmNoCheck(X86Assembler::RegisterID reg)
353 {
354     m_jit.addl_rr(reg, reg);
355     emitFastArithReTagImmediate(reg);
356 }
357
358 CTI::CTI(Machine* machine, ExecState* exec, CodeBlock* codeBlock)
359     : m_jit(machine->jitCodeBuffer())
360     , m_machine(machine)
361     , m_exec(exec)
362     , m_codeBlock(codeBlock)
363     , m_labels(codeBlock ? codeBlock->instructions.size() : 0)
364 {
365 }
366
367 #define CTI_COMPILE_BINARY_OP(name) \
368     case name: { \
369         emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx); \
370         emitGetPutArg(instruction[i + 3].u.operand, 4, X86::ecx); \
371         emitCall(i, Machine::cti_##name); \
372         emitPutResult(instruction[i + 1].u.operand); \
373         i += 4; \
374         break; \
375     }
376
377 #if ENABLE(SAMPLING_TOOL)
378 OpcodeID what = (OpcodeID)-1;
379 #endif
380
381 void CTI::compileOpCall(Instruction* instruction, unsigned i, CompileOpCallType type)
382 {
383     if (type == OpConstruct) {
384         emitPutArgConstant(reinterpret_cast<unsigned>(instruction + i), 12);
385         emitPutArgConstant(instruction[i + 4].u.operand, 8);
386         emitPutArgConstant(instruction[i + 3].u.operand, 4);
387     } else {
388         emitPutArgConstant(reinterpret_cast<unsigned>(instruction + i), 16);
389         emitPutArgConstant(instruction[i + 5].u.operand, 12);
390         emitPutArgConstant(instruction[i + 4].u.operand, 8);
391         // FIXME: should this be loaded dynamically off m_exec?
392         int thisVal = instruction[i + 3].u.operand;
393         if (thisVal == missingThisObjectMarker()) {
394             emitPutArgConstant(reinterpret_cast<unsigned>(m_exec->globalThisValue()), 4);
395         } else
396             emitGetPutArg(thisVal, 4, X86::ecx);
397     }
398
399     X86Assembler::JmpSrc wasEval;
400     if (type == OpCallEval) {
401         emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
402         emitCall(i, Machine::cti_op_call_eval);
403         m_jit.emitRestoreArgumentReference();
404
405        emitGetCTIParam(CTI_ARGS_r, X86::edi); // edi := r
406
407         m_jit.cmpl_i32r(reinterpret_cast<unsigned>(JSImmediate::impossibleValue()), X86::eax);
408         wasEval = m_jit.emitUnlinkedJne();
409     
410         // this reloads the first arg into ecx (checked just below).
411         emitGetArg(instruction[i + 2].u.operand, X86::ecx);
412     } else {
413         // this sets up the first arg, and explicitly leaves the value in ecx (checked just below).
414         emitGetArg(instruction[i + 2].u.operand, X86::ecx);
415         emitPutArg(X86::ecx, 0);
416     }
417
418     // Fast check for JS function.
419     m_jit.testl_i32r(JSImmediate::TagMask, X86::ecx);
420     X86Assembler::JmpSrc isNotObject = m_jit.emitUnlinkedJne();
421     m_jit.cmpl_i32m(reinterpret_cast<unsigned>(m_machine->m_jsFunctionVptr), X86::ecx);
422     X86Assembler::JmpSrc isJSFunction = m_jit.emitUnlinkedJe();
423     m_jit.link(isNotObject, m_jit.label());
424
425     // This handles host functions
426     emitCall(i, ((type == OpConstruct) ? Machine::cti_op_construct_NotJSConstruct : Machine::cti_op_call_NotJSFunction));
427     emitGetCTIParam(CTI_ARGS_r, X86::edi); // edi := r
428     
429     X86Assembler::JmpSrc wasNotJSFunction = m_jit.emitUnlinkedJmp();
430     m_jit.link(isJSFunction, m_jit.label());
431
432     // This handles JSFunctions
433     emitCall(i, ((type == OpConstruct) ? Machine::cti_op_construct_JSConstruct : Machine::cti_op_call_JSFunction));
434     m_jit.call_r(X86::eax);
435     emitGetCTIParam(CTI_ARGS_r, X86::edi); // edi := r
436
437     X86Assembler::JmpDst end = m_jit.label();
438     m_jit.link(wasNotJSFunction, end);
439     if (type == OpCallEval)
440         m_jit.link(wasEval, end);
441
442     emitPutResult(instruction[i + 1].u.operand);
443 }
444
445 void CTI::emitSlowScriptCheck(unsigned opcodeIndex)
446 {
447     m_jit.subl_i8r(1, X86::esi);
448     X86Assembler::JmpSrc skipTimeout = m_jit.emitUnlinkedJne();
449     emitCall(opcodeIndex, Machine::cti_timeout_check);
450
451     emitGetCTIParam(CTI_ARGS_exec, X86::ecx);
452     m_jit.movl_mr(OBJECT_OFFSET(ExecState, m_globalData), X86::ecx, X86::ecx);
453     m_jit.movl_mr(OBJECT_OFFSET(JSGlobalData, machine), X86::ecx, X86::ecx);
454     m_jit.movl_mr(OBJECT_OFFSET(Machine, m_ticksUntilNextTimeoutCheck), X86::ecx, X86::esi);
455     m_jit.link(skipTimeout, m_jit.label());
456 }
457
458 void CTI::privateCompileMainPass()
459 {
460     Instruction* instruction = m_codeBlock->instructions.begin();
461     unsigned instructionCount = m_codeBlock->instructions.size();
462
463     for (unsigned i = 0; i < instructionCount; ) {
464         m_labels[i] = m_jit.label();
465
466 #if ENABLE(SAMPLING_TOOL)
467         m_jit.movl_i32m(m_machine->getOpcodeID(instruction[i].u.opcode), &what);
468 #endif
469
470         ASSERT_WITH_MESSAGE(m_machine->isOpcode(instruction[i].u.opcode), "privateCompileMainPass gone bad @ %d", i);
471         m_jit.emitRestoreArgumentReference();
472         switch (m_machine->getOpcodeID(instruction[i].u.opcode)) {
473         case op_mov: {
474             unsigned src = instruction[i + 2].u.operand;
475             if (src < m_codeBlock->constantRegisters.size())
476                 m_jit.movl_i32r(reinterpret_cast<unsigned>(m_codeBlock->constantRegisters[src].jsValue(m_exec)), X86::edx);
477             else
478                 emitGetArg(src, X86::edx);
479             emitPutResult(instruction[i + 1].u.operand, X86::edx);
480             i += 3;
481             break;
482         }
483         case op_add: {
484             unsigned dst = instruction[i + 1].u.operand;
485             unsigned src1 = instruction[i + 2].u.operand;
486             unsigned src2 = instruction[i + 3].u.operand;
487             if (src2 < m_codeBlock->constantRegisters.size()) {
488                 JSValue* value = m_codeBlock->constantRegisters[src2].jsValue(m_exec);
489                 if (JSImmediate::isNumber(value)) {
490                     emitGetArg(src1, X86::eax);
491                     emitJumpSlowCaseIfNotImm(X86::eax, i);
492                     m_jit.addl_i32r(getDeTaggedConstantImmediate(value), X86::eax);
493                     m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
494                     emitPutResult(dst);
495                     i += 4;
496                     break;
497                 }
498             } else if (!(src1 < m_codeBlock->constantRegisters.size())) {
499                 emitGetArg(src1, X86::eax);
500                 emitGetArg(src2, X86::edx);
501                 emitJumpSlowCaseIfNotImms(X86::eax, X86::edx, i);
502                 emitFastArithDeTagImmediate(X86::eax);
503                 m_jit.addl_rr(X86::edx, X86::eax);
504                 m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
505                 emitPutResult(dst);
506                 i += 4;
507                 break;
508             }
509             emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
510             emitGetPutArg(instruction[i + 3].u.operand, 4, X86::ecx);
511             emitCall(i, Machine::cti_op_add);
512             emitPutResult(instruction[i + 1].u.operand);
513             i += 4;
514             break;
515         }
516         case op_end: {
517             if (m_codeBlock->needsFullScopeChain)
518                 emitCall(i, Machine::cti_op_end);
519             emitGetArg(instruction[i + 1].u.operand, X86::eax);
520 #if ENABLE(SAMPLING_TOOL)
521             m_jit.movl_i32m(-1, &what);
522 #endif
523             m_jit.pushl_m(-((m_codeBlock->numLocals + RegisterFile::CallFrameHeaderSize) - RegisterFile::CTIReturnEIP) * sizeof(Register), X86::edi);
524             m_jit.ret();
525             i += 2;
526             break;
527         }
528         case op_jmp: {
529             unsigned target = instruction[i + 1].u.operand;
530             m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJmp(), i + 1 + target));
531             i += 2;
532             break;
533         }
534         case op_pre_inc: {
535             int srcDst = instruction[i + 1].u.operand;
536             emitGetArg(srcDst, X86::eax);
537             emitJumpSlowCaseIfNotImm(X86::eax, i);
538             m_jit.addl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), X86::eax);
539             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
540             emitPutResult(srcDst, X86::eax);
541             i += 2;
542             break;
543         }
544         case op_loop: {
545             emitSlowScriptCheck(i);
546
547             unsigned target = instruction[i + 1].u.operand;
548             m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJmp(), i + 1 + target));
549             i += 2;
550             break;
551         }
552         case op_loop_if_less: {
553             emitSlowScriptCheck(i);
554
555             unsigned target = instruction[i + 3].u.operand;
556             JSValue* src2imm = getConstantImmediateNumericArg(instruction[i + 2].u.operand);
557             if (src2imm) {
558                 emitGetArg(instruction[i + 1].u.operand, X86::edx);
559                 emitJumpSlowCaseIfNotImm(X86::edx, i);
560                 m_jit.cmpl_i32r(reinterpret_cast<unsigned>(src2imm), X86::edx);
561                 m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJl(), i + 3 + target));
562             } else {
563                 emitGetArg(instruction[i + 1].u.operand, X86::eax);
564                 emitGetArg(instruction[i + 2].u.operand, X86::edx);
565                 emitJumpSlowCaseIfNotImm(X86::eax, i);
566                 emitJumpSlowCaseIfNotImm(X86::edx, i);
567                 m_jit.cmpl_rr(X86::edx, X86::eax);
568                 m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJl(), i + 3 + target));
569             }
570             i += 4;
571             break;
572         }
573         case op_new_object: {
574             emitCall(i, Machine::cti_op_new_object);
575             emitPutResult(instruction[i + 1].u.operand);
576             i += 2;
577             break;
578         }
579         case op_put_by_id: {
580             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
581             emitPutArgConstant(reinterpret_cast<unsigned>(ident), 4);
582             emitGetArg(instruction[i + 1].u.operand, X86::eax);
583             emitGetArg(instruction[i + 3].u.operand, X86::edx);
584             emitPutArg(X86::eax, 0); // leave the base in eax
585             emitPutArg(X86::edx, 8); // leave the base in edx
586             emitCall(i, Machine::cti_op_put_by_id);
587             i += 8;
588             break;
589         }
590         case op_get_by_id: {
591             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 3].u.operand]);
592             emitPutArgConstant(reinterpret_cast<unsigned>(ident), 4);
593             emitGetArg(instruction[i + 2].u.operand, X86::eax);
594             emitPutArg(X86::eax, 0); // leave the base in eax
595             emitCall(i, Machine::cti_op_get_by_id);
596             emitPutResult(instruction[i + 1].u.operand);
597             i += 8;
598             break;
599         }
600         case op_instanceof: {
601             emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
602             emitGetPutArg(instruction[i + 3].u.operand, 4, X86::ecx);
603             emitCall(i, Machine::cti_op_instanceof);
604             emitPutResult(instruction[i + 1].u.operand);
605             i += 4;
606             break;
607         }
608         case op_del_by_id: {
609             emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
610             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 3].u.operand]);
611             emitPutArgConstant(reinterpret_cast<unsigned>(ident), 4);
612             emitCall(i, Machine::cti_op_del_by_id);
613             emitPutResult(instruction[i + 1].u.operand);
614             i += 4;
615             break;
616         }
617         case op_mul: {
618             unsigned dst = instruction[i + 1].u.operand;
619             unsigned src1 = instruction[i + 2].u.operand;
620             unsigned src2 = instruction[i + 3].u.operand;
621             if (src1 < m_codeBlock->constantRegisters.size() || src2 < m_codeBlock->constantRegisters.size()) {
622                 unsigned constant = src1;
623                 unsigned nonconstant = src2;
624                 if (!(src1 < m_codeBlock->constantRegisters.size())) {
625                     constant = src2;
626                     nonconstant = src1;
627                 }
628                 JSValue* value = m_codeBlock->constantRegisters[constant].jsValue(m_exec);
629                 if (JSImmediate::isNumber(value)) {
630                     emitGetArg(nonconstant, X86::eax);
631                     emitJumpSlowCaseIfNotImm(X86::eax, i);
632                     emitFastArithImmToInt(X86::eax);
633                     m_jit.imull_i32r( X86::eax, getDeTaggedConstantImmediate(value), X86::eax);
634                     m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
635                     emitFastArithPotentiallyReTagImmediate(X86::eax);
636                     emitPutResult(dst);
637                     i += 4;
638                     break;
639                 }
640             }
641
642             emitGetArg(src1, X86::eax);
643             emitGetArg(src2, X86::edx);
644             emitJumpSlowCaseIfNotImms(X86::eax, X86::edx, i);
645             emitFastArithDeTagImmediate(X86::eax);
646             emitFastArithImmToInt(X86::edx);
647             m_jit.imull_rr(X86::edx, X86::eax);
648             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
649             emitFastArithPotentiallyReTagImmediate(X86::eax);
650             emitPutResult(dst);
651             i += 4;
652             break;
653         }
654         case op_new_func: {
655             FuncDeclNode* func = (m_codeBlock->functions[instruction[i + 2].u.operand]).get();
656             emitPutArgConstant(reinterpret_cast<unsigned>(func), 0);
657             emitCall(i, Machine::cti_op_new_func);
658             emitPutResult(instruction[i + 1].u.operand);
659             i += 3;
660             break;
661         }
662         case op_call: {
663             compileOpCall(instruction, i);
664             i += 6;
665             break;
666         }
667         case op_get_global_var: {
668             JSVariableObject* globalObject = static_cast<JSVariableObject*>(instruction[i + 2].u.jsCell);
669             m_jit.movl_i32r(reinterpret_cast<unsigned>(globalObject), X86::eax);
670             emitGetVariableObjectRegister(X86::eax, instruction[i + 3].u.operand, X86::eax);
671             emitPutResult(instruction[i + 1].u.operand, X86::eax);
672             i += 4;
673             break;
674         }
675         case op_put_global_var: {
676             JSVariableObject* globalObject = static_cast<JSVariableObject*>(instruction[i + 1].u.jsCell);
677             m_jit.movl_i32r(reinterpret_cast<unsigned>(globalObject), X86::eax);
678             emitGetArg(instruction[i + 3].u.operand, X86::edx);
679             emitPutVariableObjectRegister(X86::edx, X86::eax, instruction[i + 2].u.operand);
680             i += 4;
681             break;
682         }
683         case op_get_scoped_var: {
684             int skip = instruction[i + 3].u.operand + m_codeBlock->needsFullScopeChain;
685
686             emitGetCTIParam(CTI_ARGS_scopeChain, X86::eax);
687             while (skip--)
688                 m_jit.movl_mr(OBJECT_OFFSET(ScopeChainNode, next), X86::eax, X86::eax);
689
690             m_jit.movl_mr(OBJECT_OFFSET(ScopeChainNode, object), X86::eax, X86::eax);
691             emitGetVariableObjectRegister(X86::eax, instruction[i + 2].u.operand, X86::eax);
692             emitPutResult(instruction[i + 1].u.operand);
693             i += 4;
694             break;
695         }
696         case op_put_scoped_var: {
697             int skip = instruction[i + 2].u.operand + m_codeBlock->needsFullScopeChain;
698
699             emitGetCTIParam(CTI_ARGS_scopeChain, X86::edx);
700             emitGetArg(instruction[i + 3].u.operand, X86::eax);
701             while (skip--)
702                 m_jit.movl_mr(OBJECT_OFFSET(ScopeChainNode, next), X86::edx, X86::edx);
703
704             m_jit.movl_mr(OBJECT_OFFSET(ScopeChainNode, object), X86::edx, X86::edx);
705             emitPutVariableObjectRegister(X86::eax, X86::edx, instruction[i + 1].u.operand);
706             i += 4;
707             break;
708         }
709         case op_ret: {
710             emitGetPutArg(instruction[i + 1].u.operand, 0, X86::ecx);
711             emitCall(i, Machine::cti_op_ret);
712
713             m_jit.pushl_m(-((m_codeBlock->numLocals + RegisterFile::CallFrameHeaderSize) - RegisterFile::CTIReturnEIP) * sizeof(Register), X86::edi);
714             m_jit.ret();
715             i += 2;
716             break;
717         }
718         case op_new_array: {
719             m_jit.leal_mr(sizeof(Register) * instruction[i + 2].u.operand, X86::edi, X86::edx);
720             emitPutArg(X86::edx, 0);
721             emitPutArgConstant(instruction[i + 3].u.operand, 4);
722             emitCall(i, Machine::cti_op_new_array);
723             emitPutResult(instruction[i + 1].u.operand);
724             i += 4;
725             break;
726         }
727         case op_resolve: {
728             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
729             emitPutArgConstant(reinterpret_cast<unsigned>(ident), 0);
730             emitCall(i, Machine::cti_op_resolve);
731             emitPutResult(instruction[i + 1].u.operand);
732             i += 3;
733             break;
734         }
735         case op_construct: {
736             compileOpCall(instruction, i, OpConstruct);
737             i += 5;
738             break;
739         }
740         case op_get_by_val: {
741             emitGetArg(instruction[i + 2].u.operand, X86::eax);
742             emitGetArg(instruction[i + 3].u.operand, X86::edx);
743             emitJumpSlowCaseIfNotImm(X86::edx, i);
744             emitFastArithImmToInt(X86::edx);
745             m_jit.testl_i32r(JSImmediate::TagMask, X86::eax);
746             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
747             m_jit.cmpl_i32m(reinterpret_cast<unsigned>(m_machine->m_jsArrayVptr), X86::eax);
748             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
749             m_jit.cmpl_rm(X86::edx, OBJECT_OFFSET(JSArray, m_fastAccessCutoff), X86::eax);
750             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJbe(), i));
751
752             m_jit.movl_mr(OBJECT_OFFSET(JSArray, m_storage), X86::eax, X86::eax);
753             m_jit.movl_mr(OBJECT_OFFSET(ArrayStorage, m_vector[0]), X86::eax, X86::edx, sizeof(JSValue*), X86::eax);
754             emitPutResult(instruction[i + 1].u.operand);
755             i += 4;
756             break;
757         }
758         case op_resolve_func: {
759             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 3].u.operand]);
760             emitPutArgConstant(reinterpret_cast<unsigned>(ident), 0);
761             emitCall(i, Machine::cti_op_resolve_func);
762             emitPutResult(instruction[i + 1].u.operand);
763             emitGetCTIParam(CTI_ARGS_2ndResult, X86::eax);
764             emitPutResult(instruction[i + 2].u.operand);
765             i += 4;
766             break;
767         }
768         case op_sub: {
769             emitGetArg(instruction[i + 2].u.operand, X86::eax);
770             emitGetArg(instruction[i + 3].u.operand, X86::edx);
771             emitJumpSlowCaseIfNotImms(X86::eax, X86::edx, i);
772             m_jit.subl_rr(X86::edx, X86::eax);
773             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
774             emitFastArithReTagImmediate(X86::eax);
775             emitPutResult(instruction[i + 1].u.operand);
776             i += 4;
777             break;
778         }
779         case op_put_by_val: {
780             emitGetArg(instruction[i + 1].u.operand, X86::eax);
781             emitGetArg(instruction[i + 2].u.operand, X86::edx);
782             emitGetArg(instruction[i + 3].u.operand, X86::ecx);
783             emitJumpSlowCaseIfNotImm(X86::edx, i);
784             emitFastArithImmToInt(X86::edx);
785             m_jit.testl_i32r(JSImmediate::TagMask, X86::eax);
786             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
787             m_jit.cmpl_i32m(reinterpret_cast<unsigned>(m_machine->m_jsArrayVptr), X86::eax);
788             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
789             m_jit.cmpl_rm(X86::edx, OBJECT_OFFSET(JSArray, m_fastAccessCutoff), X86::eax);
790             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJbe(), i));
791
792             m_jit.movl_mr(OBJECT_OFFSET(JSArray, m_storage), X86::eax, X86::eax);
793             m_jit.movl_rm(X86::ecx, OBJECT_OFFSET(ArrayStorage, m_vector[0]), X86::eax, X86::edx, sizeof(JSValue*));
794             i += 4;
795             break;
796         }
797         CTI_COMPILE_BINARY_OP(op_lesseq)
798         case op_loop_if_true: {
799             emitSlowScriptCheck(i);
800
801             unsigned target = instruction[i + 2].u.operand;
802             emitGetArg(instruction[i + 1].u.operand, X86::eax);
803
804             m_jit.cmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::zeroImmediate()), X86::eax);
805             X86Assembler::JmpSrc isZero = m_jit.emitUnlinkedJe();
806             m_jit.testl_i32r(JSImmediate::TagBitTypeInteger, X86::eax);
807             m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJne(), i + 2 + target));
808
809             m_jit.cmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::trueImmediate()), X86::eax);
810             m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJe(), i + 2 + target));
811             m_jit.cmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::falseImmediate()), X86::eax);
812             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
813
814             m_jit.link(isZero, m_jit.label());
815             i += 3;
816             break;
817         };
818         case op_resolve_base: {
819             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
820             emitPutArgConstant(reinterpret_cast<unsigned>(ident), 0);
821             emitCall(i, Machine::cti_op_resolve_base);
822             emitPutResult(instruction[i + 1].u.operand);
823             i += 3;
824             break;
825         }
826         case op_negate: {
827             emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
828             emitCall(i, Machine::cti_op_negate);
829             emitPutResult(instruction[i + 1].u.operand);
830             i += 3;
831             break;
832         }
833         case op_resolve_skip: {
834             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
835             emitPutArgConstant(reinterpret_cast<unsigned>(ident), 0);
836             emitPutArgConstant(instruction[i + 3].u.operand + m_codeBlock->needsFullScopeChain, 4);
837             emitCall(i, Machine::cti_op_resolve_skip);
838             emitPutResult(instruction[i + 1].u.operand);
839             i += 4;
840             break;
841         }
842         CTI_COMPILE_BINARY_OP(op_div)
843         case op_pre_dec: {
844             int srcDst = instruction[i + 1].u.operand;
845             emitGetArg(srcDst, X86::eax);
846             emitJumpSlowCaseIfNotImm(X86::eax, i);
847             m_jit.subl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), X86::eax);
848             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
849             emitPutResult(srcDst, X86::eax);
850             i += 2;
851             break;
852         }
853         case op_jnless: {
854             unsigned target = instruction[i + 3].u.operand;
855             JSValue* src2imm = getConstantImmediateNumericArg(instruction[i + 2].u.operand);
856             if (src2imm) {
857                 emitGetArg(instruction[i + 1].u.operand, X86::edx);
858                 emitJumpSlowCaseIfNotImm(X86::edx, i);
859                 m_jit.cmpl_i32r(reinterpret_cast<unsigned>(src2imm), X86::edx);
860                 m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJge(), i + 3 + target));
861             } else {
862                 emitGetArg(instruction[i + 1].u.operand, X86::eax);
863                 emitGetArg(instruction[i + 2].u.operand, X86::edx);
864                 emitJumpSlowCaseIfNotImm(X86::eax, i);
865                 emitJumpSlowCaseIfNotImm(X86::edx, i);
866                 m_jit.cmpl_rr(X86::edx, X86::eax);
867                 m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJge(), i + 3 + target));
868             }
869             i += 4;
870             break;
871         }
872         case op_not: {
873             emitGetArg(instruction[i + 2].u.operand, X86::eax);
874             m_jit.xorl_i8r(JSImmediate::FullTagTypeBool, X86::eax);
875             m_jit.testl_i32r(JSImmediate::FullTagTypeMask, X86::eax); // i8?
876             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
877             m_jit.xorl_i8r((JSImmediate::FullTagTypeBool | JSImmediate::ExtendedPayloadBitBoolValue), X86::eax);
878             emitPutResult(instruction[i + 1].u.operand);
879             i += 3;
880             break;
881         }
882         case op_jfalse: {
883             unsigned target = instruction[i + 2].u.operand;
884             emitGetArg(instruction[i + 1].u.operand, X86::eax);
885
886             m_jit.cmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::zeroImmediate()), X86::eax);
887             m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJe(), i + 2 + target));
888             m_jit.testl_i32r(JSImmediate::TagBitTypeInteger, X86::eax);
889             X86Assembler::JmpSrc isNonZero = m_jit.emitUnlinkedJne();
890
891             m_jit.cmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::falseImmediate()), X86::eax);
892             m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJe(), i + 2 + target));
893             m_jit.cmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::trueImmediate()), X86::eax);
894             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
895
896             m_jit.link(isNonZero, m_jit.label());
897             i += 3;
898             break;
899         };
900         case op_post_inc: {
901             int srcDst = instruction[i + 2].u.operand;
902             emitGetArg(srcDst, X86::eax);
903             m_jit.movl_rr(X86::eax, X86::edx);
904             emitJumpSlowCaseIfNotImm(X86::eax, i);
905             m_jit.addl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), X86::edx);
906             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
907             emitPutResult(srcDst, X86::edx);
908             emitPutResult(instruction[i + 1].u.operand);
909             i += 3;
910             break;
911         }
912         case op_unexpected_load: {
913             JSValue* v = m_codeBlock->unexpectedConstants[instruction[i + 2].u.operand];
914             m_jit.movl_i32r(reinterpret_cast<unsigned>(v), X86::eax);
915             emitPutResult(instruction[i + 1].u.operand);
916             i += 3;
917             break;
918         }
919         case op_jsr: {
920             int retAddrDst = instruction[i + 1].u.operand;
921             int target = instruction[i + 2].u.operand;
922             m_jit.movl_i32m(0, sizeof(Register) * retAddrDst, X86::edi);
923             X86Assembler::JmpDst addrPosition = m_jit.label();
924             m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJmp(), i + 2 + target));
925             X86Assembler::JmpDst sretTarget = m_jit.label();
926             m_jsrSites.append(JSRInfo(addrPosition, sretTarget));
927             i += 3;
928             break;
929         }
930         case op_sret: {
931             m_jit.jmp_m(sizeof(Register) * instruction[i + 1].u.operand, X86::edi);
932             i += 2;
933             break;
934         }
935         CTI_COMPILE_BINARY_OP(op_eq)
936         case op_lshift: {
937             emitGetArg(instruction[i + 2].u.operand, X86::eax);
938             emitGetArg(instruction[i + 3].u.operand, X86::ecx);
939             emitJumpSlowCaseIfNotImm(X86::eax, i);
940             emitJumpSlowCaseIfNotImm(X86::ecx, i);
941             emitFastArithImmToInt(X86::eax);
942             emitFastArithImmToInt(X86::ecx);
943             m_jit.shll_CLr(X86::eax);
944             emitFastArithIntToImmOrSlowCase(X86::eax, i);
945             emitPutResult(instruction[i + 1].u.operand);
946             i += 4;
947             break;
948         }
949         case op_bitand: {
950             unsigned src1 = instruction[i + 2].u.operand;
951             unsigned src2 = instruction[i + 3].u.operand;
952             unsigned dst = instruction[i + 1].u.operand;
953             if (JSValue* value = getConstantImmediateNumericArg(src1)) {
954                 emitGetArg(src2, X86::eax);
955                 emitJumpSlowCaseIfNotImm(X86::eax, i);
956                 m_jit.andl_i32r(reinterpret_cast<unsigned>(value), X86::eax); // FIXME: make it more obvious this is relying on the format of JSImmediate
957                 emitPutResult(dst);
958             } else if (JSValue* value = getConstantImmediateNumericArg(src2)) {
959                 emitGetArg(src1, X86::eax);
960                 emitJumpSlowCaseIfNotImm(X86::eax, i);
961                 m_jit.andl_i32r(reinterpret_cast<unsigned>(value), X86::eax);
962                 emitPutResult(dst);
963             } else {
964                 emitGetArg(src1, X86::eax);
965                 emitGetArg(src2, X86::edx);
966                 m_jit.andl_rr(X86::edx, X86::eax);
967                 emitJumpSlowCaseIfNotImm(X86::eax, i);
968                 emitPutResult(dst);
969             }
970             i += 4;
971             break;
972         }
973         case op_rshift: {
974             emitGetArg(instruction[i + 2].u.operand, X86::eax);
975             emitGetArg(instruction[i + 3].u.operand, X86::ecx);
976             emitJumpSlowCaseIfNotImm(X86::eax, i);
977             emitJumpSlowCaseIfNotImm(X86::ecx, i);
978             emitFastArithImmToInt(X86::ecx);
979             m_jit.sarl_CLr(X86::eax);
980             emitFastArithPotentiallyReTagImmediate(X86::eax);
981             emitPutResult(instruction[i + 1].u.operand);
982             i += 4;
983             break;
984         }
985         case op_bitnot: {
986             emitGetArg(instruction[i + 2].u.operand, X86::eax);
987             emitJumpSlowCaseIfNotImm(X86::eax, i);
988             m_jit.xorl_i8r(~JSImmediate::TagBitTypeInteger, X86::eax);
989             emitPutResult(instruction[i + 1].u.operand);
990             i += 3;
991             break;
992         }
993         case op_resolve_with_base: {
994             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 3].u.operand]);
995             emitPutArgConstant(reinterpret_cast<unsigned>(ident), 0);
996             emitCall(i, Machine::cti_op_resolve_with_base);
997             emitPutResult(instruction[i + 1].u.operand);
998             emitGetCTIParam(CTI_ARGS_2ndResult, X86::eax);
999             emitPutResult(instruction[i + 2].u.operand);
1000             i += 4;
1001             break;
1002         }
1003         case op_new_func_exp: {
1004             FuncExprNode* func = (m_codeBlock->functionExpressions[instruction[i + 2].u.operand]).get();
1005             emitPutArgConstant(reinterpret_cast<unsigned>(func), 0);
1006             emitCall(i, Machine::cti_op_new_func_exp);
1007             emitPutResult(instruction[i + 1].u.operand);
1008             i += 3;
1009             break;
1010         }
1011         case op_mod: {
1012             emitGetArg(instruction[i + 2].u.operand, X86::eax);
1013             emitGetArg(instruction[i + 3].u.operand, X86::ecx);
1014             emitJumpSlowCaseIfNotImm(X86::eax, i);
1015             emitJumpSlowCaseIfNotImm(X86::ecx, i);
1016             emitFastArithDeTagImmediate(X86::eax);
1017             emitFastArithDeTagImmediate(X86::ecx);
1018             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJe(), i)); // This is checking if the last detag resulted in a value 0.
1019             m_jit.cdq();
1020             m_jit.idivl_r(X86::ecx);
1021             emitFastArithReTagImmediate(X86::edx);
1022             m_jit.movl_rr(X86::edx, X86::eax);
1023             emitPutResult(instruction[i + 1].u.operand);
1024             i += 4;
1025             break;
1026         }
1027         case op_jtrue: {
1028             unsigned target = instruction[i + 2].u.operand;
1029             emitGetArg(instruction[i + 1].u.operand, X86::eax);
1030
1031             m_jit.cmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::zeroImmediate()), X86::eax);
1032             X86Assembler::JmpSrc isZero = m_jit.emitUnlinkedJe();
1033             m_jit.testl_i32r(JSImmediate::TagBitTypeInteger, X86::eax);
1034             m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJne(), i + 2 + target));
1035
1036             m_jit.cmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::trueImmediate()), X86::eax);
1037             m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJe(), i + 2 + target));
1038             m_jit.cmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::falseImmediate()), X86::eax);
1039             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
1040
1041             m_jit.link(isZero, m_jit.label());
1042             i += 3;
1043             break;
1044         }
1045         CTI_COMPILE_BINARY_OP(op_less)
1046         CTI_COMPILE_BINARY_OP(op_neq)
1047         case op_post_dec: {
1048             int srcDst = instruction[i + 2].u.operand;
1049             emitGetArg(srcDst, X86::eax);
1050             m_jit.movl_rr(X86::eax, X86::edx);
1051             emitJumpSlowCaseIfNotImm(X86::eax, i);
1052             m_jit.subl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), X86::edx);
1053             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
1054             emitPutResult(srcDst, X86::edx);
1055             emitPutResult(instruction[i + 1].u.operand);
1056             i += 3;
1057             break;
1058         }
1059         CTI_COMPILE_BINARY_OP(op_urshift)
1060         case op_bitxor: {
1061             emitGetArg(instruction[i + 2].u.operand, X86::eax);
1062             emitGetArg(instruction[i + 3].u.operand, X86::edx);
1063             emitJumpSlowCaseIfNotImms(X86::eax, X86::edx, i);
1064             m_jit.xorl_rr(X86::edx, X86::eax);
1065             emitFastArithReTagImmediate(X86::eax);
1066             emitPutResult(instruction[i + 1].u.operand);
1067             i += 4;
1068             break;
1069         }
1070         case op_new_regexp: {
1071             RegExp* regExp = m_codeBlock->regexps[instruction[i + 2].u.operand].get();
1072             emitPutArgConstant(reinterpret_cast<unsigned>(regExp), 0);
1073             emitCall(i, Machine::cti_op_new_regexp);
1074             emitPutResult(instruction[i + 1].u.operand);
1075             i += 3;
1076             break;
1077         }
1078         case op_bitor: {
1079             emitGetArg(instruction[i + 2].u.operand, X86::eax);
1080             emitGetArg(instruction[i + 3].u.operand, X86::edx);
1081             emitJumpSlowCaseIfNotImms(X86::eax, X86::edx, i);
1082             m_jit.orl_rr(X86::edx, X86::eax);
1083             emitPutResult(instruction[i + 1].u.operand);
1084             i += 4;
1085             break;
1086         }
1087         case op_call_eval: {
1088             compileOpCall(instruction, i, OpCallEval);
1089             i += 6;
1090             break;
1091         }
1092         case op_throw: {
1093             emitGetPutArg(instruction[i + 1].u.operand, 0, X86::ecx);
1094             emitCall(i, Machine::cti_op_throw);
1095             m_jit.addl_i8r(0x24, X86::esp);
1096             m_jit.popl_r(X86::edi);
1097             m_jit.popl_r(X86::esi);
1098             m_jit.ret();
1099             i += 2;
1100             break;
1101         }
1102         case op_get_pnames: {
1103             emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
1104             emitCall(i, Machine::cti_op_get_pnames);
1105             emitPutResult(instruction[i + 1].u.operand);
1106             i += 3;
1107             break;
1108         }
1109         case op_next_pname: {
1110             emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
1111             unsigned target = instruction[i + 3].u.operand;
1112             emitCall(i, Machine::cti_op_next_pname);
1113             m_jit.testl_rr(X86::eax, X86::eax);
1114             X86Assembler::JmpSrc endOfIter = m_jit.emitUnlinkedJe();
1115             emitPutResult(instruction[i + 1].u.operand);
1116             m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJmp(), i + 3 + target));
1117             m_jit.link(endOfIter, m_jit.label());
1118             i += 4;
1119             break;
1120         }
1121         case op_push_scope: {
1122             emitGetPutArg(instruction[i + 1].u.operand, 0, X86::ecx);
1123             emitCall(i, Machine::cti_op_push_scope);
1124             i += 2;
1125             break;
1126         }
1127         case op_pop_scope: {
1128             emitCall(i, Machine::cti_op_pop_scope);
1129             i += 1;
1130             break;
1131         }
1132         case op_typeof: {
1133             emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
1134             emitCall(i, Machine::cti_op_typeof);
1135             emitPutResult(instruction[i + 1].u.operand);
1136             i += 3;
1137             break;
1138         }
1139         CTI_COMPILE_BINARY_OP(op_stricteq)
1140         CTI_COMPILE_BINARY_OP(op_nstricteq)
1141         case op_to_jsnumber: {
1142             emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
1143             emitCall(i, Machine::cti_op_to_jsnumber);
1144             emitPutResult(instruction[i + 1].u.operand);
1145             i += 3;
1146             break;
1147         }
1148         case op_in: {
1149             emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
1150             emitGetPutArg(instruction[i + 3].u.operand, 4, X86::ecx);
1151             emitCall(i, Machine::cti_op_in);
1152             emitPutResult(instruction[i + 1].u.operand);
1153             i += 4;
1154             break;
1155         }
1156         case op_push_new_scope: {
1157             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
1158             emitPutArgConstant(reinterpret_cast<unsigned>(ident), 0);
1159             emitGetPutArg(instruction[i + 3].u.operand, 4, X86::ecx);
1160             emitCall(i, Machine::cti_op_push_new_scope);
1161             emitPutResult(instruction[i + 1].u.operand);
1162             i += 4;
1163             break;
1164         }
1165         case op_catch: {
1166             emitGetCTIParam(CTI_ARGS_r, X86::edi); // edi := r
1167             emitGetCTIParam(CTI_ARGS_exec, X86::ecx);
1168             m_jit.movl_mr(OBJECT_OFFSET(ExecState, m_exception), X86::ecx, X86::eax);
1169             m_jit.movl_i32m(0, OBJECT_OFFSET(ExecState, m_exception), X86::ecx);
1170             emitPutResult(instruction[i + 1].u.operand);
1171             i += 2;
1172             break;
1173         }
1174         case op_jmp_scopes: {
1175             unsigned count = instruction[i + 1].u.operand;
1176             emitPutArgConstant(count, 0);
1177             emitCall(i, Machine::cti_op_jmp_scopes);
1178             unsigned target = instruction[i + 2].u.operand;
1179             m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJmp(), i + 2 + target));
1180             i += 3;
1181             break;
1182         }
1183         case op_put_by_index: {
1184             emitGetPutArg(instruction[i + 1].u.operand, 0, X86::ecx);
1185             emitPutArgConstant(instruction[i + 2].u.operand, 4);
1186             emitGetPutArg(instruction[i + 3].u.operand, 8, X86::ecx);
1187             emitCall(i, Machine::cti_op_put_by_index);
1188             i += 4;
1189             break;
1190         }
1191         case op_switch_imm: {
1192             unsigned tableIndex = instruction[i + 1].u.operand;
1193             unsigned defaultOffset = instruction[i + 2].u.operand;
1194             unsigned scrutinee = instruction[i + 3].u.operand;
1195
1196             // create jump table for switch destinations, track this switch statement.
1197             SimpleJumpTable* jumpTable = &m_codeBlock->immediateSwitchJumpTables[tableIndex];
1198             m_switches.append(SwitchRecord(jumpTable, i, defaultOffset, SwitchRecord::Immediate));
1199             jumpTable->ctiOffsets.grow(jumpTable->branchOffsets.size());
1200
1201             emitGetPutArg(scrutinee, 0, X86::ecx);
1202             emitPutArgConstant(tableIndex, 4);
1203             emitCall(i, Machine::cti_op_switch_imm);
1204             m_jit.jmp_r(X86::eax);
1205             i += 4;
1206             break;
1207         }
1208         case op_switch_char: {
1209             unsigned tableIndex = instruction[i + 1].u.operand;
1210             unsigned defaultOffset = instruction[i + 2].u.operand;
1211             unsigned scrutinee = instruction[i + 3].u.operand;
1212
1213             // create jump table for switch destinations, track this switch statement.
1214             SimpleJumpTable* jumpTable = &m_codeBlock->characterSwitchJumpTables[tableIndex];
1215             m_switches.append(SwitchRecord(jumpTable, i, defaultOffset, SwitchRecord::Character));
1216             jumpTable->ctiOffsets.grow(jumpTable->branchOffsets.size());
1217
1218             emitGetPutArg(scrutinee, 0, X86::ecx);
1219             emitPutArgConstant(tableIndex, 4);
1220             emitCall(i, Machine::cti_op_switch_char);
1221             m_jit.jmp_r(X86::eax);
1222             i += 4;
1223             break;
1224         }
1225         case op_switch_string: {
1226             unsigned tableIndex = instruction[i + 1].u.operand;
1227             unsigned defaultOffset = instruction[i + 2].u.operand;
1228             unsigned scrutinee = instruction[i + 3].u.operand;
1229
1230             // create jump table for switch destinations, track this switch statement.
1231             StringJumpTable* jumpTable = &m_codeBlock->stringSwitchJumpTables[tableIndex];
1232             m_switches.append(SwitchRecord(jumpTable, i, defaultOffset));
1233
1234             emitGetPutArg(scrutinee, 0, X86::ecx);
1235             emitPutArgConstant(tableIndex, 4);
1236             emitCall(i, Machine::cti_op_switch_string);
1237             m_jit.jmp_r(X86::eax);
1238             i += 4;
1239             break;
1240         }
1241         case op_del_by_val: {
1242             emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
1243             emitGetPutArg(instruction[i + 3].u.operand, 4, X86::ecx);
1244             emitCall(i, Machine::cti_op_del_by_val);
1245             emitPutResult(instruction[i + 1].u.operand);
1246             i += 4;
1247             break;
1248         }
1249         case op_put_getter: {
1250             emitGetPutArg(instruction[i + 1].u.operand, 0, X86::ecx);
1251             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
1252             emitPutArgConstant(reinterpret_cast<unsigned>(ident), 4);
1253             emitGetPutArg(instruction[i + 3].u.operand, 8, X86::ecx);
1254             emitCall(i, Machine::cti_op_put_getter);
1255             i += 4;
1256             break;
1257         }
1258         case op_put_setter: {
1259             emitGetPutArg(instruction[i + 1].u.operand, 0, X86::ecx);
1260             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
1261             emitPutArgConstant(reinterpret_cast<unsigned>(ident), 4);
1262             emitGetPutArg(instruction[i + 3].u.operand, 8, X86::ecx);
1263             emitCall(i, Machine::cti_op_put_setter);
1264             i += 4;
1265             break;
1266         }
1267         case op_new_error: {
1268             JSValue* message = m_codeBlock->unexpectedConstants[instruction[i + 3].u.operand];
1269             emitPutArgConstant(instruction[i + 2].u.operand, 0);
1270             emitPutArgConstant(reinterpret_cast<unsigned>(message), 4);
1271             emitPutArgConstant(m_codeBlock->lineNumberForVPC(&instruction[i]), 8);
1272             emitCall(i, Machine::cti_op_new_error);
1273             emitPutResult(instruction[i + 1].u.operand);
1274             i += 4;
1275             break;
1276         }
1277         case op_debug: {
1278             emitPutArgConstant(instruction[i + 1].u.operand, 0);
1279             emitPutArgConstant(instruction[i + 2].u.operand, 4);
1280             emitPutArgConstant(instruction[i + 3].u.operand, 8);
1281             emitCall(i, Machine::cti_op_debug);
1282             i += 4;
1283             break;
1284         }
1285         case op_eq_null: {
1286             emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
1287             emitCall(i, Machine::cti_op_eq_null);
1288             emitPutResult(instruction[i + 1].u.operand);
1289             i += 3;
1290             break;
1291         }
1292         case op_neq_null: {
1293             emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
1294             emitCall(i, Machine::cti_op_neq_null);
1295             emitPutResult(instruction[i + 1].u.operand);
1296             i += 3;
1297             break;
1298         }
1299         case op_get_array_length:
1300         case op_get_by_id_chain:
1301         case op_get_by_id_generic:
1302         case op_get_by_id_proto:
1303         case op_get_by_id_self:
1304         case op_get_string_length:
1305         case op_put_by_id_generic:
1306         case op_put_by_id_replace:
1307         case op_put_by_id_transition:
1308             ASSERT_NOT_REACHED();
1309         }
1310     }
1311 }
1312
1313
1314 void CTI::privateCompileLinkPass()
1315 {
1316     unsigned jmpTableCount = m_jmpTable.size();
1317     for (unsigned i = 0; i < jmpTableCount; ++i)
1318         m_jit.link(m_jmpTable[i].from, m_labels[m_jmpTable[i].to]);
1319     m_jmpTable.clear();
1320 }
1321
1322 #define CTI_COMPILE_BINARY_OP_SLOW_CASE(name) \
1323     case name: { \
1324         m_jit.link(iter->from, m_jit.label()); \
1325         emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx); \
1326         emitGetPutArg(instruction[i + 3].u.operand, 4, X86::ecx); \
1327         emitCall(i, Machine::cti_##name); \
1328         emitPutResult(instruction[i + 1].u.operand); \
1329         i += 4; \
1330         break; \
1331     }
1332     
1333 void CTI::privateCompileSlowCases()
1334 {
1335     Instruction* instruction = m_codeBlock->instructions.begin();
1336     for (Vector<SlowCaseEntry>::iterator iter = m_slowCases.begin(); iter != m_slowCases.end(); ++iter) {
1337         int i = iter->to;
1338         m_jit.emitRestoreArgumentReference();
1339         switch (m_machine->getOpcodeID(instruction[i].u.opcode)) {
1340         case op_add: {
1341             unsigned dst = instruction[i + 1].u.operand;
1342             unsigned src2 = instruction[i + 3].u.operand;
1343             if (src2 < m_codeBlock->constantRegisters.size()) {
1344                 JSValue* value = m_codeBlock->constantRegisters[src2].jsValue(m_exec);
1345                 if (JSImmediate::isNumber(value)) {
1346                     X86Assembler::JmpSrc notImm = iter->from;
1347                     m_jit.link((++iter)->from, m_jit.label());
1348                     m_jit.subl_i32r(getDeTaggedConstantImmediate(value), X86::eax);
1349                     m_jit.link(notImm, m_jit.label());
1350                     emitPutArg(X86::eax, 0);
1351                     emitGetPutArg(src2, 4, X86::ecx);
1352                     emitCall(i, Machine::cti_op_add);
1353                     emitPutResult(dst);
1354                     i += 4;
1355                     break;
1356                 }
1357             }
1358
1359             ASSERT(!(static_cast<unsigned>(instruction[i + 2].u.operand) < m_codeBlock->constantRegisters.size()));
1360
1361             X86Assembler::JmpSrc notImm = iter->from;
1362             m_jit.link((++iter)->from, m_jit.label());
1363             m_jit.subl_rr(X86::edx, X86::eax);
1364             emitFastArithReTagImmediate(X86::eax);
1365             m_jit.link(notImm, m_jit.label());
1366             emitPutArg(X86::eax, 0);
1367             emitPutArg(X86::edx, 4);
1368             emitCall(i, Machine::cti_op_add);
1369             emitPutResult(dst);
1370             i += 4;
1371             break;
1372         }
1373         case op_get_by_val: {
1374             X86Assembler::JmpSrc notImm = iter->from;
1375             m_jit.link((++iter)->from, m_jit.label());
1376             m_jit.link((++iter)->from, m_jit.label());
1377             m_jit.link((++iter)->from, m_jit.label());
1378             emitFastArithIntToImmNoCheck(X86::edx);
1379             m_jit.link(notImm, m_jit.label());
1380             emitPutArg(X86::eax, 0);
1381             emitPutArg(X86::edx, 4);
1382             emitCall(i, Machine::cti_op_get_by_val);
1383             emitPutResult(instruction[i + 1].u.operand);
1384             i += 4;
1385             break;
1386         }
1387         case op_sub: {
1388             X86Assembler::JmpSrc notImm = iter->from;
1389             m_jit.link((++iter)->from, m_jit.label());
1390             m_jit.addl_rr(X86::edx, X86::eax);
1391             m_jit.link(notImm, m_jit.label());
1392             emitPutArg(X86::eax, 0);
1393             emitPutArg(X86::edx, 4);
1394             emitCall(i, Machine::cti_op_sub);
1395             emitPutResult(instruction[i + 1].u.operand);
1396             i += 4;
1397             break;
1398         }
1399         case op_rshift: {
1400             m_jit.link(iter->from, m_jit.label());
1401             m_jit.link((++iter)->from, m_jit.label());
1402             emitPutArg(X86::eax, 0);
1403             emitPutArg(X86::ecx, 4);
1404             emitCall(i, Machine::cti_op_rshift);
1405             emitPutResult(instruction[i + 1].u.operand);
1406             i += 4;
1407             break;
1408         }
1409         case op_lshift: {
1410             X86Assembler::JmpSrc notImm1 = iter->from;
1411             X86Assembler::JmpSrc notImm2 = (++iter)->from;
1412             m_jit.link((++iter)->from, m_jit.label());
1413             emitGetArg(instruction[i + 2].u.operand, X86::eax);
1414             emitGetArg(instruction[i + 3].u.operand, X86::ecx);
1415             m_jit.link(notImm1, m_jit.label());
1416             m_jit.link(notImm2, m_jit.label());
1417             emitPutArg(X86::eax, 0);
1418             emitPutArg(X86::ecx, 4);
1419             emitCall(i, Machine::cti_op_lshift);
1420             emitPutResult(instruction[i + 1].u.operand);
1421             i += 4;
1422             break;
1423         }
1424         case op_loop_if_less: {
1425             emitSlowScriptCheck(i);
1426
1427             unsigned target = instruction[i + 3].u.operand;
1428             JSValue* src2imm = getConstantImmediateNumericArg(instruction[i + 2].u.operand);
1429             if (src2imm) {
1430                 m_jit.link(iter->from, m_jit.label());
1431                 emitPutArg(X86::edx, 0);
1432                 emitGetPutArg(instruction[i + 2].u.operand, 4, X86::ecx);
1433                 emitCall(i, Machine::cti_op_loop_if_less);
1434                 m_jit.testl_rr(X86::eax, X86::eax);
1435                 m_jit.link(m_jit.emitUnlinkedJne(), m_labels[i + 3 + target]);
1436             } else {
1437                 m_jit.link(iter->from, m_jit.label());
1438                 m_jit.link((++iter)->from, m_jit.label());
1439                 emitPutArg(X86::eax, 0);
1440                 emitPutArg(X86::edx, 4);
1441                 emitCall(i, Machine::cti_op_loop_if_less);
1442                 m_jit.testl_rr(X86::eax, X86::eax);
1443                 m_jit.link(m_jit.emitUnlinkedJne(), m_labels[i + 3 + target]);
1444             }
1445             i += 4;
1446             break;
1447         }
1448         case op_pre_inc: {
1449             unsigned srcDst = instruction[i + 1].u.operand;
1450             X86Assembler::JmpSrc notImm = iter->from;
1451             m_jit.link((++iter)->from, m_jit.label());
1452             m_jit.subl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), X86::eax);
1453             m_jit.link(notImm, m_jit.label());
1454             emitPutArg(X86::eax, 0);
1455             emitCall(i, Machine::cti_op_pre_inc);
1456             emitPutResult(srcDst);
1457             i += 2;
1458             break;
1459         }
1460         case op_put_by_val: {
1461             X86Assembler::JmpSrc notImm = iter->from;
1462             m_jit.link((++iter)->from, m_jit.label());
1463             m_jit.link((++iter)->from, m_jit.label());
1464             m_jit.link((++iter)->from, m_jit.label());
1465             emitFastArithIntToImmNoCheck(X86::edx);
1466             m_jit.link(notImm, m_jit.label());
1467             emitPutArg(X86::eax, 0);
1468             emitPutArg(X86::edx, 4);
1469             emitPutArg(X86::ecx, 8);
1470             emitCall(i, Machine::cti_op_put_by_val);
1471             i += 4;
1472             break;
1473         }
1474         case op_loop_if_true: {
1475             emitSlowScriptCheck(i);
1476
1477             m_jit.link(iter->from, m_jit.label());
1478             emitPutArg(X86::eax, 0);
1479             emitCall(i, Machine::cti_op_jtrue);
1480             m_jit.testl_rr(X86::eax, X86::eax);
1481             unsigned target = instruction[i + 2].u.operand;
1482             m_jit.link(m_jit.emitUnlinkedJne(), m_labels[i + 2 + target]);
1483             i += 3;
1484             break;
1485         }
1486         case op_pre_dec: {
1487             unsigned srcDst = instruction[i + 1].u.operand;
1488             X86Assembler::JmpSrc notImm = iter->from;
1489             m_jit.link((++iter)->from, m_jit.label());
1490             m_jit.addl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), X86::eax);
1491             m_jit.link(notImm, m_jit.label());
1492             emitPutArg(X86::eax, 0);
1493             emitCall(i, Machine::cti_op_pre_dec);
1494             emitPutResult(srcDst);
1495             i += 2;
1496             break;
1497         }
1498         case op_jnless: {
1499             unsigned target = instruction[i + 3].u.operand;
1500             JSValue* src2imm = getConstantImmediateNumericArg(instruction[i + 2].u.operand);
1501             if (src2imm) {
1502                 m_jit.link(iter->from, m_jit.label());
1503                 emitPutArg(X86::edx, 0);
1504                 emitGetPutArg(instruction[i + 2].u.operand, 4, X86::ecx);
1505                 emitCall(i, Machine::cti_op_jless);
1506                 m_jit.testl_rr(X86::eax, X86::eax);
1507                 m_jit.link(m_jit.emitUnlinkedJe(), m_labels[i + 3 + target]);
1508             } else {
1509                 m_jit.link(iter->from, m_jit.label());
1510                 m_jit.link((++iter)->from, m_jit.label());
1511                 emitPutArg(X86::eax, 0);
1512                 emitPutArg(X86::edx, 4);
1513                 emitCall(i, Machine::cti_op_jless);
1514                 m_jit.testl_rr(X86::eax, X86::eax);
1515                 m_jit.link(m_jit.emitUnlinkedJe(), m_labels[i + 3 + target]);
1516             }
1517             i += 4;
1518             break;
1519         }
1520         case op_not: {
1521             m_jit.link(iter->from, m_jit.label());
1522             m_jit.xorl_i8r(JSImmediate::FullTagTypeBool, X86::eax);
1523             emitPutArg(X86::eax, 0);
1524             emitCall(i, Machine::cti_op_not);
1525             emitPutResult(instruction[i + 1].u.operand);
1526             i += 3;
1527             break;
1528         }
1529         case op_jfalse: {
1530             m_jit.link(iter->from, m_jit.label());
1531             emitPutArg(X86::eax, 0);
1532             emitCall(i, Machine::cti_op_jtrue);
1533             m_jit.testl_rr(X86::eax, X86::eax);
1534             unsigned target = instruction[i + 2].u.operand;
1535             m_jit.link(m_jit.emitUnlinkedJe(), m_labels[i + 2 + target]); // inverted!
1536             i += 3;
1537             break;
1538         }
1539         case op_post_inc: {
1540             unsigned srcDst = instruction[i + 2].u.operand;
1541             m_jit.link(iter->from, m_jit.label());
1542             m_jit.link((++iter)->from, m_jit.label());
1543             emitPutArg(X86::eax, 0);
1544             emitCall(i, Machine::cti_op_post_inc);
1545             emitPutResult(instruction[i + 1].u.operand);
1546             emitGetCTIParam(CTI_ARGS_2ndResult, X86::eax);
1547             emitPutResult(srcDst);
1548             i += 3;
1549             break;
1550         }
1551         case op_bitnot: {
1552             m_jit.link(iter->from, m_jit.label());
1553             emitPutArg(X86::eax, 0);
1554             emitCall(i, Machine::cti_op_bitnot);
1555             emitPutResult(instruction[i + 1].u.operand);
1556             i += 3;
1557             break;
1558         }
1559         case op_bitand: {
1560             unsigned src1 = instruction[i + 2].u.operand;
1561             unsigned src2 = instruction[i + 3].u.operand;
1562             unsigned dst = instruction[i + 1].u.operand;
1563             if (getConstantImmediateNumericArg(src1)) {
1564                 m_jit.link(iter->from, m_jit.label());
1565                 emitGetPutArg(src1, 0, X86::ecx);
1566                 emitPutArg(X86::eax, 4);
1567                 emitCall(i, Machine::cti_op_bitand);
1568                 emitPutResult(dst);
1569             } else if (getConstantImmediateNumericArg(src2)) {
1570                 m_jit.link(iter->from, m_jit.label());
1571                 emitPutArg(X86::eax, 0);
1572                 emitGetPutArg(src2, 4, X86::ecx);
1573                 emitCall(i, Machine::cti_op_bitand);
1574                 emitPutResult(dst);
1575             } else {
1576                 m_jit.link(iter->from, m_jit.label());
1577                 emitGetPutArg(src1, 0, X86::ecx);
1578                 emitPutArg(X86::edx, 4);
1579                 emitCall(i, Machine::cti_op_bitand);
1580                 emitPutResult(dst);
1581             }
1582             i += 4;
1583             break;
1584         }
1585         case op_jtrue: {
1586             m_jit.link(iter->from, m_jit.label());
1587             emitPutArg(X86::eax, 0);
1588             emitCall(i, Machine::cti_op_jtrue);
1589             m_jit.testl_rr(X86::eax, X86::eax);
1590             unsigned target = instruction[i + 2].u.operand;
1591             m_jit.link(m_jit.emitUnlinkedJne(), m_labels[i + 2 + target]);
1592             i += 3;
1593             break;
1594         }
1595         case op_post_dec: {
1596             unsigned srcDst = instruction[i + 2].u.operand;
1597             m_jit.link(iter->from, m_jit.label());
1598             m_jit.link((++iter)->from, m_jit.label());
1599             emitPutArg(X86::eax, 0);
1600             emitCall(i, Machine::cti_op_post_dec);
1601             emitPutResult(instruction[i + 1].u.operand);
1602             emitGetCTIParam(CTI_ARGS_2ndResult, X86::eax);
1603             emitPutResult(srcDst);
1604             i += 3;
1605             break;
1606         }
1607         case op_bitxor: {
1608             m_jit.link(iter->from, m_jit.label());
1609             emitPutArg(X86::eax, 0);
1610             emitPutArg(X86::edx, 4);
1611             emitCall(i, Machine::cti_op_bitxor);
1612             emitPutResult(instruction[i + 1].u.operand);
1613             i += 4;
1614             break;
1615         }
1616         case op_bitor: {
1617             m_jit.link(iter->from, m_jit.label());
1618             emitPutArg(X86::eax, 0);
1619             emitPutArg(X86::edx, 4);
1620             emitCall(i, Machine::cti_op_bitor);
1621             emitPutResult(instruction[i + 1].u.operand);
1622             i += 4;
1623             break;
1624         }
1625         case op_mod: {
1626             X86Assembler::JmpSrc notImm1 = iter->from;
1627             X86Assembler::JmpSrc notImm2 = (++iter)->from;
1628             m_jit.link((++iter)->from, m_jit.label());
1629             emitFastArithReTagImmediate(X86::eax);
1630             emitFastArithReTagImmediate(X86::ecx);
1631             m_jit.link(notImm1, m_jit.label());
1632             m_jit.link(notImm2, m_jit.label());
1633             emitPutArg(X86::eax, 0);
1634             emitPutArg(X86::ecx, 4);
1635             emitCall(i, Machine::cti_op_mod);
1636             emitPutResult(instruction[i + 1].u.operand);
1637             i += 4;
1638             break;
1639         }
1640         CTI_COMPILE_BINARY_OP_SLOW_CASE(op_mul);
1641         default:
1642             ASSERT_NOT_REACHED();
1643             break;
1644         }
1645
1646         m_jit.link(m_jit.emitUnlinkedJmp(), m_labels[i]);
1647     }
1648 }
1649
1650 void CTI::privateCompile()
1651 {
1652     // Could use a popl_m, but would need to offset the following instruction if so.
1653     m_jit.popl_r(X86::ecx);
1654     emitGetCTIParam(CTI_ARGS_r, X86::edi); // edi := r
1655     emitPutToCallFrameHeader(X86::ecx, RegisterFile::CTIReturnEIP);
1656
1657     privateCompileMainPass();
1658     privateCompileLinkPass();
1659     privateCompileSlowCases();
1660
1661     ASSERT(m_jmpTable.isEmpty());
1662
1663     void* code = m_jit.copy();
1664     ASSERT(code);
1665
1666     // Translate vPC offsets into addresses in JIT generated code, for switch tables.
1667     for (unsigned i = 0; i < m_switches.size(); ++i) {
1668         SwitchRecord record = m_switches[i];
1669         unsigned opcodeIndex = record.m_opcodeIndex;
1670
1671         if (record.m_type != SwitchRecord::String) {
1672             ASSERT(record.m_type == SwitchRecord::Immediate || record.m_type == SwitchRecord::Character); 
1673             ASSERT(record.m_jumpTable.m_simpleJumpTable->branchOffsets.size() == record.m_jumpTable.m_simpleJumpTable->ctiOffsets.size());
1674
1675             record.m_jumpTable.m_simpleJumpTable->ctiDefault = m_jit.getRelocatedAddress(code, m_labels[opcodeIndex + 3 + record.m_defaultOffset]);
1676
1677             for (unsigned j = 0; j < record.m_jumpTable.m_simpleJumpTable->branchOffsets.size(); ++j) {
1678                 unsigned offset = record.m_jumpTable.m_simpleJumpTable->branchOffsets[j];
1679                 record.m_jumpTable.m_simpleJumpTable->ctiOffsets[j] = offset ? m_jit.getRelocatedAddress(code, m_labels[opcodeIndex + 3 + offset]) : record.m_jumpTable.m_simpleJumpTable->ctiDefault;
1680             }
1681         } else {
1682             ASSERT(record.m_type == SwitchRecord::String);
1683
1684             record.m_jumpTable.m_stringJumpTable->ctiDefault = m_jit.getRelocatedAddress(code, m_labels[opcodeIndex + 3 + record.m_defaultOffset]);
1685
1686             StringJumpTable::StringOffsetTable::iterator end = record.m_jumpTable.m_stringJumpTable->offsetTable.end();            
1687             for (StringJumpTable::StringOffsetTable::iterator it = record.m_jumpTable.m_stringJumpTable->offsetTable.begin(); it != end; ++it) {
1688                 unsigned offset = it->second.branchOffset;
1689                 it->second.ctiOffset = offset ? m_jit.getRelocatedAddress(code, m_labels[opcodeIndex + 3 + offset]) : record.m_jumpTable.m_stringJumpTable->ctiDefault;
1690             }
1691         }
1692     }
1693
1694     for (Vector<HandlerInfo>::iterator iter = m_codeBlock->exceptionHandlers.begin(); iter != m_codeBlock->exceptionHandlers.end(); ++iter)
1695          iter->nativeCode = m_jit.getRelocatedAddress(code, m_labels[iter->target]);
1696
1697     // FIXME: There doesn't seem to be a way to hint to a hashmap that it should make a certain capacity available;
1698     // could be faster if we could do something like this:
1699     // m_codeBlock->ctiReturnAddressVPCMap.grow(m_calls.size());
1700     for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
1701         X86Assembler::link(code, iter->from, iter->to);
1702         m_codeBlock->ctiReturnAddressVPCMap.add(m_jit.getRelocatedAddress(code, iter->from), iter->opcodeIndex);
1703     }
1704
1705     // Link absolute addresses for jsr
1706     for (Vector<JSRInfo>::iterator iter = m_jsrSites.begin(); iter != m_jsrSites.end(); ++iter)
1707         X86Assembler::linkAbsoluteAddress(code, iter->addrPosition, iter->target);
1708
1709     m_codeBlock->ctiCode = code;
1710 }
1711
1712 void* CTI::privateCompileGetByIdSelf(StructureID* structureID, size_t cachedOffset)
1713 {
1714     // Check eax is an object of the right StructureID.
1715     m_jit.testl_i32r(JSImmediate::TagMask, X86::eax);
1716     X86Assembler::JmpSrc failureCases1 = m_jit.emitUnlinkedJne();
1717     m_jit.cmpl_i32m(reinterpret_cast<uint32_t>(structureID), OBJECT_OFFSET(JSCell, m_structureID), X86::eax);
1718     X86Assembler::JmpSrc failureCases2 = m_jit.emitUnlinkedJne();
1719
1720     // Checks out okay! - getDirectOffset
1721     m_jit.movl_mr(OBJECT_OFFSET(JSObject, m_propertyStorage), X86::eax, X86::eax);
1722     m_jit.movl_mr(cachedOffset * sizeof(JSValue*), X86::eax, X86::eax);
1723     m_jit.ret();
1724
1725     void* code = m_jit.copy();
1726     ASSERT(code);
1727
1728     X86Assembler::link(code, failureCases1, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
1729     X86Assembler::link(code, failureCases2, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
1730     
1731     m_codeBlock->structureIDAccessStubs.append(code);
1732     
1733     return code;
1734 }
1735
1736 void* CTI::privateCompileGetByIdProto(ExecState* exec, StructureID* structureID, StructureID* prototypeStructureID, size_t cachedOffset)
1737 {
1738     // The prototype object definitely exists (if this stub exists the CodeBlock is referencing a StructureID that is
1739     // referencing the prototype object - let's speculatively load it's table nice and early!)
1740     JSObject* protoObject = static_cast<JSObject*>(structureID->prototypeForLookup(exec));
1741     PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage;
1742     m_jit.movl_mr(static_cast<void*>(protoPropertyStorage), X86::edx);
1743
1744     // check eax is an object of the right StructureID.
1745     m_jit.testl_i32r(JSImmediate::TagMask, X86::eax);
1746     X86Assembler::JmpSrc failureCases1 = m_jit.emitUnlinkedJne();
1747     m_jit.cmpl_i32m(reinterpret_cast<uint32_t>(structureID), OBJECT_OFFSET(JSCell, m_structureID), X86::eax);
1748     X86Assembler::JmpSrc failureCases2 = m_jit.emitUnlinkedJne();
1749
1750     // Check the prototype object's StructureID had not changed.
1751     StructureID** protoStructureIDAddress = &(protoObject->m_structureID);
1752     m_jit.cmpl_i32m(reinterpret_cast<uint32_t>(prototypeStructureID), static_cast<void*>(protoStructureIDAddress));
1753     X86Assembler::JmpSrc failureCases3 = m_jit.emitUnlinkedJne();
1754
1755     // Checks out okay! - getDirectOffset
1756     m_jit.movl_mr(cachedOffset * sizeof(JSValue*), X86::edx, X86::eax);
1757
1758     m_jit.ret();
1759
1760     void* code = m_jit.copy();
1761     ASSERT(code);
1762
1763     X86Assembler::link(code, failureCases1, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
1764     X86Assembler::link(code, failureCases2, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
1765     X86Assembler::link(code, failureCases3, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
1766
1767     m_codeBlock->structureIDAccessStubs.append(code);
1768
1769     return code;
1770 }
1771
1772 void* CTI::privateCompileGetByIdChain(ExecState* exec, StructureID* structureID, StructureIDChain* chain, size_t count, size_t cachedOffset)
1773 {
1774     ASSERT(count);
1775     
1776     Vector<X86Assembler::JmpSrc> bucketsOfFail;
1777
1778     // Check eax is an object of the right StructureID.
1779     m_jit.testl_i32r(JSImmediate::TagMask, X86::eax);
1780     bucketsOfFail.append(m_jit.emitUnlinkedJne());
1781     m_jit.cmpl_i32m(reinterpret_cast<uint32_t>(structureID), OBJECT_OFFSET(JSCell, m_structureID), X86::eax);
1782     bucketsOfFail.append(m_jit.emitUnlinkedJne());
1783
1784     StructureID* currStructureID = structureID;
1785     RefPtr<StructureID>* chainEntries = chain->head();
1786     JSObject* protoObject = 0;
1787     for (unsigned i = 0; i<count; ++i) {
1788         protoObject = static_cast<JSObject*>(currStructureID->prototypeForLookup(exec));
1789         currStructureID = chainEntries[i].get();
1790
1791         // Check the prototype object's StructureID had not changed.
1792         StructureID** protoStructureIDAddress = &(protoObject->m_structureID);
1793         m_jit.cmpl_i32m(reinterpret_cast<uint32_t>(currStructureID), static_cast<void*>(protoStructureIDAddress));
1794         bucketsOfFail.append(m_jit.emitUnlinkedJne());
1795     }
1796     ASSERT(protoObject);
1797
1798     PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage;
1799     m_jit.movl_mr(static_cast<void*>(protoPropertyStorage), X86::edx);
1800     m_jit.movl_mr(cachedOffset * sizeof(JSValue*), X86::edx, X86::eax);
1801     m_jit.ret();
1802
1803     bucketsOfFail.append(m_jit.emitUnlinkedJmp());
1804
1805     void* code = m_jit.copy();
1806     ASSERT(code);
1807
1808     for (unsigned i = 0; i < bucketsOfFail.size(); ++i)
1809         X86Assembler::link(code, bucketsOfFail[i], reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
1810     m_codeBlock->structureIDAccessStubs.append(code);
1811     return code;
1812 }
1813
1814 void* CTI::privateCompilePutByIdReplace(StructureID* structureID, size_t cachedOffset)
1815 {
1816     // check eax is an object of the right StructureID.
1817     m_jit.testl_i32r(JSImmediate::TagMask, X86::eax);
1818     X86Assembler::JmpSrc failureCases1 = m_jit.emitUnlinkedJne();
1819     m_jit.cmpl_i32m(reinterpret_cast<uint32_t>(structureID), OBJECT_OFFSET(JSCell, m_structureID), X86::eax);
1820     X86Assembler::JmpSrc failureCases2 = m_jit.emitUnlinkedJne();
1821
1822     // checks out okay! - putDirectOffset
1823     m_jit.movl_mr(OBJECT_OFFSET(JSObject, m_propertyStorage), X86::eax, X86::eax);
1824     m_jit.movl_rm(X86::edx, cachedOffset * sizeof(JSValue*), X86::eax);
1825     m_jit.ret();
1826
1827     void* code = m_jit.copy();
1828     ASSERT(code);
1829     
1830     X86Assembler::link(code, failureCases1, reinterpret_cast<void*>(Machine::cti_op_put_by_id_fail));
1831     X86Assembler::link(code, failureCases2, reinterpret_cast<void*>(Machine::cti_op_put_by_id_fail));
1832
1833     m_codeBlock->structureIDAccessStubs.append(code);
1834     
1835     return code;
1836 }
1837
1838 extern "C" {
1839
1840 static JSValue* SFX_CALL transitionObject(StructureID* newStructureID, size_t cachedOffset, JSObject* baseObject, JSValue* value)
1841 {
1842     StructureID* oldStructureID = newStructureID->previousID();
1843
1844     baseObject->transitionTo(newStructureID);
1845
1846     if (oldStructureID->propertyMap().storageSize() == JSObject::inlineStorageCapacity)
1847         baseObject->allocatePropertyStorage(oldStructureID->propertyMap().storageSize(), oldStructureID->propertyMap().size());
1848
1849     baseObject->putDirectOffset(cachedOffset, value);
1850     return baseObject;
1851 }
1852
1853 }
1854
1855 static inline bool transitionWillNeedStorageRealloc(StructureID* oldStructureID, StructureID* newStructureID)
1856 {
1857     if (oldStructureID->propertyMap().storageSize() == JSObject::inlineStorageCapacity)
1858         return true;
1859
1860     if (oldStructureID->propertyMap().storageSize() < JSObject::inlineStorageCapacity)
1861         return false;
1862
1863     if (oldStructureID->propertyMap().size() != newStructureID->propertyMap().size())
1864         return true;
1865
1866     return false;
1867 }
1868
1869 void* CTI::privateCompilePutByIdTransition(StructureID* oldStructureID, StructureID* newStructureID, size_t cachedOffset, StructureIDChain* sIDC)
1870 {
1871     Vector<X86Assembler::JmpSrc, 16> failureCases;
1872     // check eax is an object of the right StructureID.
1873     m_jit.testl_i32r(JSImmediate::TagMask, X86::eax);
1874     failureCases.append(m_jit.emitUnlinkedJne());
1875     m_jit.cmpl_i32m(reinterpret_cast<uint32_t>(oldStructureID), OBJECT_OFFSET(JSCell, m_structureID), X86::eax);
1876     failureCases.append(m_jit.emitUnlinkedJne());
1877     Vector<X86Assembler::JmpSrc> successCases;
1878
1879     //  ecx = baseObject
1880     m_jit.movl_mr(OBJECT_OFFSET(JSCell, m_structureID), X86::eax, X86::ecx);
1881     // proto(ecx) = baseObject->structureID()->prototype()
1882     m_jit.cmpl_i32m(ObjectType, OBJECT_OFFSET(StructureID, m_type), X86::ecx);
1883     failureCases.append(m_jit.emitUnlinkedJne());
1884     m_jit.movl_mr(OBJECT_OFFSET(StructureID, m_prototype), X86::ecx, X86::ecx);
1885     
1886     // ecx = baseObject->m_structureID
1887     for (RefPtr<StructureID>* it = sIDC->head(); *it; ++it) {
1888         // null check the prototype
1889         m_jit.cmpl_i32r(reinterpret_cast<intptr_t> (jsNull()), X86::ecx);
1890         successCases.append(m_jit.emitUnlinkedJe());
1891
1892         // Check the structure id
1893         m_jit.cmpl_i32m(reinterpret_cast<uint32_t>(it->get()), OBJECT_OFFSET(JSCell, m_structureID), X86::ecx);
1894         failureCases.append(m_jit.emitUnlinkedJne());
1895         
1896         m_jit.movl_mr(OBJECT_OFFSET(JSCell, m_structureID), X86::ecx, X86::ecx);
1897         m_jit.cmpl_i32m(ObjectType, OBJECT_OFFSET(StructureID, m_type), X86::ecx);
1898         failureCases.append(m_jit.emitUnlinkedJne());
1899         m_jit.movl_mr(OBJECT_OFFSET(StructureID, m_prototype), X86::ecx, X86::ecx);
1900     }
1901
1902     failureCases.append(m_jit.emitUnlinkedJne());
1903     for (unsigned i = 0; i < successCases.size(); ++i)
1904         m_jit.link(successCases[i], m_jit.label());
1905
1906     X86Assembler::JmpSrc callTarget;
1907     // Fast case, don't need to do any heavy lifting, so don't bother making a call.
1908     if (!transitionWillNeedStorageRealloc(oldStructureID, newStructureID)) {
1909         // Assumes m_refCount can be decremented easily, refcount decrement is safe as 
1910         // codeblock should ensure oldStructureID->m_refCount > 0
1911         m_jit.subl_i8m(1, reinterpret_cast<void*>(oldStructureID));
1912         m_jit.addl_i8m(1, reinterpret_cast<void*>(newStructureID));
1913         m_jit.movl_i32m(reinterpret_cast<uint32_t>(newStructureID), OBJECT_OFFSET(JSCell, m_structureID), X86::eax);
1914
1915         // write the value
1916         m_jit.movl_mr(OBJECT_OFFSET(JSObject, m_propertyStorage), X86::eax, X86::eax);
1917         m_jit.movl_rm(X86::edx, cachedOffset * sizeof(JSValue*), X86::eax);
1918     } else {
1919         // Slow case transition -- we're going to need to quite a bit of work,
1920         // so just make a call
1921         m_jit.pushl_r(X86::edx);
1922         m_jit.pushl_r(X86::eax);
1923         m_jit.movl_i32r(cachedOffset, X86::eax);
1924         m_jit.pushl_r(X86::eax);
1925         m_jit.movl_i32r(reinterpret_cast<uint32_t>(newStructureID), X86::eax);
1926         m_jit.pushl_r(X86::eax);
1927         callTarget = m_jit.emitCall();
1928         m_jit.addl_i32r(4 * sizeof(void*), X86::esp);
1929     }
1930     m_jit.ret();
1931     void* code = m_jit.copy();
1932     ASSERT(code);
1933     
1934     for (unsigned i = 0; i < failureCases.size(); ++i)
1935         X86Assembler::link(code, failureCases[i], reinterpret_cast<void*>(Machine::cti_op_put_by_id_fail));
1936
1937     if (transitionWillNeedStorageRealloc(oldStructureID, newStructureID))
1938         X86Assembler::link(code, callTarget, reinterpret_cast<void*>(transitionObject));
1939     
1940     m_codeBlock->structureIDAccessStubs.append(code);
1941     
1942     return code;
1943 }
1944
1945 void* CTI::privateArrayLengthTrampoline()
1946 {
1947     // Check eax is an array
1948     m_jit.testl_i32r(JSImmediate::TagMask, X86::eax);
1949     X86Assembler::JmpSrc failureCases1 = m_jit.emitUnlinkedJne();
1950     m_jit.cmpl_i32m(reinterpret_cast<unsigned>(m_machine->m_jsArrayVptr), X86::eax);
1951     X86Assembler::JmpSrc failureCases2 = m_jit.emitUnlinkedJne();
1952
1953     // Checks out okay! - get the length from the storage
1954     m_jit.movl_mr(OBJECT_OFFSET(JSArray, m_storage), X86::eax, X86::eax);
1955     m_jit.movl_mr(OBJECT_OFFSET(ArrayStorage, m_length), X86::eax, X86::eax);
1956
1957     m_jit.addl_rr(X86::eax, X86::eax);
1958     X86Assembler::JmpSrc failureCases3 = m_jit.emitUnlinkedJo();
1959     m_jit.addl_i8r(1, X86::eax);
1960     
1961     m_jit.ret();
1962
1963     void* code = m_jit.copy();
1964     ASSERT(code);
1965
1966     X86Assembler::link(code, failureCases1, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
1967     X86Assembler::link(code, failureCases2, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
1968     X86Assembler::link(code, failureCases3, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
1969     
1970     return code;
1971 }
1972
1973 void* CTI::privateStringLengthTrampoline()
1974 {
1975     // Check eax is a string
1976     m_jit.testl_i32r(JSImmediate::TagMask, X86::eax);
1977     X86Assembler::JmpSrc failureCases1 = m_jit.emitUnlinkedJne();
1978     m_jit.cmpl_i32m(reinterpret_cast<unsigned>(m_machine->m_jsStringVptr), X86::eax);
1979     X86Assembler::JmpSrc failureCases2 = m_jit.emitUnlinkedJne();
1980
1981     // Checks out okay! - get the length from the Ustring.
1982     m_jit.movl_mr(OBJECT_OFFSET(JSString, m_value) + OBJECT_OFFSET(UString, m_rep), X86::eax, X86::eax);
1983     m_jit.movl_mr(OBJECT_OFFSET(UString::Rep, len), X86::eax, X86::eax);
1984
1985     m_jit.addl_rr(X86::eax, X86::eax);
1986     X86Assembler::JmpSrc failureCases3 = m_jit.emitUnlinkedJo();
1987     m_jit.addl_i8r(1, X86::eax);
1988     
1989     m_jit.ret();
1990
1991     void* code = m_jit.copy();
1992     ASSERT(code);
1993
1994     X86Assembler::link(code, failureCases1, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
1995     X86Assembler::link(code, failureCases2, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
1996     X86Assembler::link(code, failureCases3, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
1997
1998     return code;
1999 }
2000
2001 void CTI::emitGetVariableObjectRegister(X86Assembler::RegisterID variableObject, int index, X86Assembler::RegisterID dst)
2002 {
2003     m_jit.movl_mr(JSVariableObject::offsetOf_d(), variableObject, dst);
2004     m_jit.movl_mr(JSVariableObject::offsetOf_Data_registers(), dst, dst);
2005     m_jit.movl_mr(index * sizeof(Register), dst, dst);
2006 }
2007
2008 void CTI::emitPutVariableObjectRegister(X86Assembler::RegisterID src, X86Assembler::RegisterID variableObject, int index)
2009 {
2010     m_jit.movl_mr(JSVariableObject::offsetOf_d(), variableObject, variableObject);
2011     m_jit.movl_mr(JSVariableObject::offsetOf_Data_registers(), variableObject, variableObject);
2012     m_jit.movl_rm(src, index * sizeof(Register), variableObject);
2013 }
2014
2015 #if ENABLE(WREC)
2016
2017 void* CTI::compileRegExp(ExecState* exec, const UString& pattern, unsigned* numSubpatterns_ptr, const char** error_ptr, bool ignoreCase, bool multiline)
2018 {
2019     // TODO: better error messages
2020     if (pattern.size() > MaxPatternSize) {
2021         *error_ptr = "regular expression too large";
2022         return 0;
2023     }
2024
2025     X86Assembler jit(exec->machine()->jitCodeBuffer());
2026     WRECParser parser(pattern, ignoreCase, multiline, jit);
2027     
2028     jit.emitConvertToFastCall();
2029     // (0) Setup:
2030     //     Preserve regs & initialize outputRegister.
2031     jit.pushl_r(WRECGenerator::outputRegister);
2032     jit.pushl_r(WRECGenerator::currentValueRegister);
2033     // push pos onto the stack, both to preserve and as a parameter available to parseDisjunction
2034     jit.pushl_r(WRECGenerator::currentPositionRegister);
2035     // load output pointer
2036     jit.movl_mr(16
2037 #if COMPILER(MSVC)
2038                     + 3 * sizeof(void*)
2039 #endif
2040                     , X86::esp, WRECGenerator::outputRegister);
2041     
2042     // restart point on match fail.
2043     WRECGenerator::JmpDst nextLabel = jit.label();
2044
2045     // (1) Parse Disjunction:
2046     
2047     //     Parsing the disjunction should fully consume the pattern.
2048     JmpSrcVector failures;
2049     parser.parseDisjunction(failures);
2050     if (parser.isEndOfPattern()) {
2051         parser.m_err = WRECParser::Error_malformedPattern;
2052     }
2053     if (parser.m_err) {
2054         // TODO: better error messages
2055         *error_ptr = "TODO: better error messages";
2056         return 0;
2057     }
2058
2059     // (2) Success:
2060     //     Set return value & pop registers from the stack.
2061
2062     jit.testl_rr(WRECGenerator::outputRegister, WRECGenerator::outputRegister);
2063     WRECGenerator::JmpSrc noOutput = jit.emitUnlinkedJe();
2064
2065     jit.movl_rm(WRECGenerator::currentPositionRegister, 4, WRECGenerator::outputRegister);
2066     jit.popl_r(X86::eax);
2067     jit.movl_rm(X86::eax, WRECGenerator::outputRegister);
2068     jit.popl_r(WRECGenerator::currentValueRegister);
2069     jit.popl_r(WRECGenerator::outputRegister);
2070     jit.ret();
2071     
2072     jit.link(noOutput, jit.label());
2073     
2074     jit.popl_r(X86::eax);
2075     jit.movl_rm(X86::eax, WRECGenerator::outputRegister);
2076     jit.popl_r(WRECGenerator::currentValueRegister);
2077     jit.popl_r(WRECGenerator::outputRegister);
2078     jit.ret();
2079
2080     // (3) Failure:
2081     //     All fails link to here.  Progress the start point & if it is within scope, loop.
2082     //     Otherwise, return fail value.
2083     WRECGenerator::JmpDst here = jit.label();
2084     for (unsigned i = 0; i < failures.size(); ++i)
2085         jit.link(failures[i], here);
2086     failures.clear();
2087
2088     jit.movl_mr(X86::esp, WRECGenerator::currentPositionRegister);
2089     jit.addl_i8r(1, WRECGenerator::currentPositionRegister);
2090     jit.movl_rm(WRECGenerator::currentPositionRegister, X86::esp);
2091     jit.cmpl_rr(WRECGenerator::lengthRegister, WRECGenerator::currentPositionRegister);
2092     jit.link(jit.emitUnlinkedJle(), nextLabel);
2093
2094     jit.addl_i8r(4, X86::esp);
2095
2096     jit.movl_i32r(-1, X86::eax);
2097     jit.popl_r(WRECGenerator::currentValueRegister);
2098     jit.popl_r(WRECGenerator::outputRegister);
2099     jit.ret();
2100
2101     *numSubpatterns_ptr = parser.m_numSubpatterns;
2102
2103     void* code = jit.copy();
2104     ASSERT(code);
2105     return code;
2106 }
2107
2108 #endif // ENABLE(WREC)
2109
2110 } // namespace JSC
2111
2112 #endif // ENABLE(CTI)