1f60a72a924e873c0c336ef6a5f17d446134547e
[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_rr(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 += 6;
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         CTI_COMPILE_BINARY_OP(op_mul);
618         case op_new_func: {
619             FuncDeclNode* func = (m_codeBlock->functions[instruction[i + 2].u.operand]).get();
620             emitPutArgConstant(reinterpret_cast<unsigned>(func), 0);
621             emitCall(i, Machine::cti_op_new_func);
622             emitPutResult(instruction[i + 1].u.operand);
623             i += 3;
624             break;
625         }
626         case op_call: {
627             compileOpCall(instruction, i);
628             i += 6;
629             break;
630         }
631         case op_get_global_var: {
632             JSVariableObject* globalObject = static_cast<JSVariableObject*>(instruction[i + 2].u.jsCell);
633             m_jit.movl_i32r(reinterpret_cast<unsigned>(globalObject), X86::eax);
634             emitGetVariableObjectRegister(X86::eax, instruction[i + 3].u.operand, X86::eax);
635             emitPutResult(instruction[i + 1].u.operand, X86::eax);
636             i += 4;
637             break;
638         }
639         case op_put_global_var: {
640             JSVariableObject* globalObject = static_cast<JSVariableObject*>(instruction[i + 1].u.jsCell);
641             m_jit.movl_i32r(reinterpret_cast<unsigned>(globalObject), X86::eax);
642             emitGetArg(instruction[i + 3].u.operand, X86::edx);
643             emitPutVariableObjectRegister(X86::edx, X86::eax, instruction[i + 2].u.operand);
644             i += 4;
645             break;
646         }
647         case op_get_scoped_var: {
648             int skip = instruction[i + 3].u.operand + m_codeBlock->needsFullScopeChain;
649
650             emitGetCTIParam(CTI_ARGS_scopeChain, X86::eax);
651             while (skip--)
652                 m_jit.movl_mr(OBJECT_OFFSET(ScopeChainNode, next), X86::eax, X86::eax);
653
654             m_jit.movl_mr(OBJECT_OFFSET(ScopeChainNode, object), X86::eax, X86::eax);
655             emitGetVariableObjectRegister(X86::eax, instruction[i + 2].u.operand, X86::eax);
656             emitPutResult(instruction[i + 1].u.operand);
657             i += 4;
658             break;
659         }
660         case op_put_scoped_var: {
661             int skip = instruction[i + 2].u.operand + m_codeBlock->needsFullScopeChain;
662
663             emitGetCTIParam(CTI_ARGS_scopeChain, X86::edx);
664             emitGetArg(instruction[i + 3].u.operand, X86::eax);
665             while (skip--)
666                 m_jit.movl_mr(OBJECT_OFFSET(ScopeChainNode, next), X86::edx, X86::edx);
667
668             m_jit.movl_mr(OBJECT_OFFSET(ScopeChainNode, object), X86::edx, X86::edx);
669             emitPutVariableObjectRegister(X86::eax, X86::edx, instruction[i + 1].u.operand);
670             i += 4;
671             break;
672         }
673         case op_ret: {
674             emitGetPutArg(instruction[i + 1].u.operand, 0, X86::ecx);
675             emitCall(i, Machine::cti_op_ret);
676
677             m_jit.pushl_m(-((m_codeBlock->numLocals + RegisterFile::CallFrameHeaderSize) - RegisterFile::CTIReturnEIP) * sizeof(Register), X86::edi);
678             m_jit.ret();
679             i += 2;
680             break;
681         }
682         case op_new_array: {
683             m_jit.leal_mr(sizeof(Register) * instruction[i + 2].u.operand, X86::edi, X86::edx);
684             emitPutArg(X86::edx, 0);
685             emitPutArgConstant(instruction[i + 3].u.operand, 4);
686             emitCall(i, Machine::cti_op_new_array);
687             emitPutResult(instruction[i + 1].u.operand);
688             i += 4;
689             break;
690         }
691         case op_resolve: {
692             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
693             emitPutArgConstant(reinterpret_cast<unsigned>(ident), 0);
694             emitCall(i, Machine::cti_op_resolve);
695             emitPutResult(instruction[i + 1].u.operand);
696             i += 3;
697             break;
698         }
699         case op_construct: {
700             compileOpCall(instruction, i, OpConstruct);
701             i += 5;
702             break;
703         }
704         case op_get_by_val: {
705             emitGetArg(instruction[i + 2].u.operand, X86::eax);
706             emitGetArg(instruction[i + 3].u.operand, X86::edx);
707             emitJumpSlowCaseIfNotImm(X86::edx, i);
708             emitFastArithImmToInt(X86::edx);
709             m_jit.testl_i32r(JSImmediate::TagMask, X86::eax);
710             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
711             m_jit.cmpl_i32m(reinterpret_cast<unsigned>(m_machine->m_jsArrayVptr), X86::eax);
712             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
713             m_jit.cmpl_rm(X86::edx, OBJECT_OFFSET(JSArray, m_fastAccessCutoff), X86::eax);
714             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJbe(), i));
715
716             m_jit.movl_mr(OBJECT_OFFSET(JSArray, m_storage), X86::eax, X86::eax);
717             m_jit.movl_mr(OBJECT_OFFSET(ArrayStorage, m_vector[0]), X86::eax, X86::edx, sizeof(JSValue*), X86::eax);
718             emitPutResult(instruction[i + 1].u.operand);
719             i += 4;
720             break;
721         }
722         case op_resolve_func: {
723             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 3].u.operand]);
724             emitPutArgConstant(reinterpret_cast<unsigned>(ident), 0);
725             emitCall(i, Machine::cti_op_resolve_func);
726             emitPutResult(instruction[i + 1].u.operand);
727             emitGetCTIParam(CTI_ARGS_2ndResult, X86::eax);
728             emitPutResult(instruction[i + 2].u.operand);
729             i += 4;
730             break;
731         }
732         case op_sub: {
733             emitGetArg(instruction[i + 2].u.operand, X86::eax);
734             emitGetArg(instruction[i + 3].u.operand, X86::edx);
735             emitJumpSlowCaseIfNotImms(X86::eax, X86::edx, i);
736             m_jit.subl_rr(X86::edx, X86::eax);
737             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
738             emitFastArithReTagImmediate(X86::eax);
739             emitPutResult(instruction[i + 1].u.operand);
740             i += 4;
741             break;
742         }
743         case op_put_by_val: {
744             emitGetArg(instruction[i + 1].u.operand, X86::eax);
745             emitGetArg(instruction[i + 2].u.operand, X86::edx);
746             emitGetArg(instruction[i + 3].u.operand, X86::ecx);
747             emitJumpSlowCaseIfNotImm(X86::edx, i);
748             emitFastArithImmToInt(X86::edx);
749             m_jit.testl_i32r(JSImmediate::TagMask, X86::eax);
750             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
751             m_jit.cmpl_i32m(reinterpret_cast<unsigned>(m_machine->m_jsArrayVptr), X86::eax);
752             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
753             m_jit.cmpl_rm(X86::edx, OBJECT_OFFSET(JSArray, m_fastAccessCutoff), X86::eax);
754             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJbe(), i));
755
756             m_jit.movl_mr(OBJECT_OFFSET(JSArray, m_storage), X86::eax, X86::eax);
757             m_jit.movl_rm(X86::ecx, OBJECT_OFFSET(ArrayStorage, m_vector[0]), X86::eax, X86::edx, sizeof(JSValue*));
758             i += 4;
759             break;
760         }
761         CTI_COMPILE_BINARY_OP(op_lesseq)
762         case op_loop_if_true: {
763             emitSlowScriptCheck(i);
764
765             unsigned target = instruction[i + 2].u.operand;
766             emitGetArg(instruction[i + 1].u.operand, X86::eax);
767
768             m_jit.cmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::zeroImmediate()), X86::eax);
769             X86Assembler::JmpSrc isZero = m_jit.emitUnlinkedJe();
770             m_jit.testl_i32r(JSImmediate::TagBitTypeInteger, X86::eax);
771             m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJne(), i + 2 + target));
772
773             m_jit.cmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::trueImmediate()), X86::eax);
774             m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJe(), i + 2 + target));
775             m_jit.cmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::falseImmediate()), X86::eax);
776             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
777
778             m_jit.link(isZero, m_jit.label());
779             i += 3;
780             break;
781         };
782         case op_resolve_base: {
783             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
784             emitPutArgConstant(reinterpret_cast<unsigned>(ident), 0);
785             emitCall(i, Machine::cti_op_resolve_base);
786             emitPutResult(instruction[i + 1].u.operand);
787             i += 3;
788             break;
789         }
790         case op_negate: {
791             emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
792             emitCall(i, Machine::cti_op_negate);
793             emitPutResult(instruction[i + 1].u.operand);
794             i += 3;
795             break;
796         }
797         case op_resolve_skip: {
798             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
799             emitPutArgConstant(reinterpret_cast<unsigned>(ident), 0);
800             emitPutArgConstant(instruction[i + 3].u.operand + m_codeBlock->needsFullScopeChain, 4);
801             emitCall(i, Machine::cti_op_resolve_skip);
802             emitPutResult(instruction[i + 1].u.operand);
803             i += 4;
804             break;
805         }
806         CTI_COMPILE_BINARY_OP(op_div)
807         case op_pre_dec: {
808             int srcDst = instruction[i + 1].u.operand;
809             emitGetArg(srcDst, X86::eax);
810             emitJumpSlowCaseIfNotImm(X86::eax, i);
811             m_jit.subl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), X86::eax);
812             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
813             emitPutResult(srcDst, X86::eax);
814             i += 2;
815             break;
816         }
817         case op_jnless: {
818             unsigned target = instruction[i + 3].u.operand;
819             JSValue* src2imm = getConstantImmediateNumericArg(instruction[i + 2].u.operand);
820             if (src2imm) {
821                 emitGetArg(instruction[i + 1].u.operand, X86::edx);
822                 emitJumpSlowCaseIfNotImm(X86::edx, i);
823                 m_jit.cmpl_i32r(reinterpret_cast<unsigned>(src2imm), X86::edx);
824                 m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJge(), i + 3 + target));
825             } else {
826                 emitGetArg(instruction[i + 1].u.operand, X86::eax);
827                 emitGetArg(instruction[i + 2].u.operand, X86::edx);
828                 emitJumpSlowCaseIfNotImm(X86::eax, i);
829                 emitJumpSlowCaseIfNotImm(X86::edx, i);
830                 m_jit.cmpl_rr(X86::edx, X86::eax);
831                 m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJge(), i + 3 + target));
832             }
833             i += 4;
834             break;
835         }
836         case op_not: {
837             emitGetArg(instruction[i + 2].u.operand, X86::eax);
838             m_jit.xorl_i8r(JSImmediate::FullTagTypeBool, X86::eax);
839             m_jit.testl_i32r(JSImmediate::FullTagTypeMask, X86::eax); // i8?
840             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
841             m_jit.xorl_i8r((JSImmediate::FullTagTypeBool | JSImmediate::ExtendedPayloadBitBoolValue), X86::eax);
842             emitPutResult(instruction[i + 1].u.operand);
843             i += 3;
844             break;
845         }
846         case op_jfalse: {
847             unsigned target = instruction[i + 2].u.operand;
848             emitGetArg(instruction[i + 1].u.operand, X86::eax);
849
850             m_jit.cmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::zeroImmediate()), X86::eax);
851             m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJe(), i + 2 + target));
852             m_jit.testl_i32r(JSImmediate::TagBitTypeInteger, X86::eax);
853             X86Assembler::JmpSrc isNonZero = m_jit.emitUnlinkedJne();
854
855             m_jit.cmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::falseImmediate()), X86::eax);
856             m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJe(), i + 2 + target));
857             m_jit.cmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::trueImmediate()), X86::eax);
858             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
859
860             m_jit.link(isNonZero, m_jit.label());
861             i += 3;
862             break;
863         };
864         case op_post_inc: {
865             int srcDst = instruction[i + 2].u.operand;
866             emitGetArg(srcDst, X86::eax);
867             m_jit.movl_rr(X86::eax, X86::edx);
868             emitJumpSlowCaseIfNotImm(X86::eax, i);
869             m_jit.addl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), X86::edx);
870             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
871             emitPutResult(srcDst, X86::edx);
872             emitPutResult(instruction[i + 1].u.operand);
873             i += 3;
874             break;
875         }
876         case op_unexpected_load: {
877             JSValue* v = m_codeBlock->unexpectedConstants[instruction[i + 2].u.operand];
878             m_jit.movl_i32r(reinterpret_cast<unsigned>(v), X86::eax);
879             emitPutResult(instruction[i + 1].u.operand);
880             i += 3;
881             break;
882         }
883         case op_jsr: {
884             int retAddrDst = instruction[i + 1].u.operand;
885             int target = instruction[i + 2].u.operand;
886             m_jit.movl_i32m(0, sizeof(Register) * retAddrDst, X86::edi);
887             X86Assembler::JmpDst addrPosition = m_jit.label();
888             m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJmp(), i + 2 + target));
889             X86Assembler::JmpDst sretTarget = m_jit.label();
890             m_jsrSites.append(JSRInfo(addrPosition, sretTarget));
891             i += 3;
892             break;
893         }
894         case op_sret: {
895             m_jit.jmp_m(sizeof(Register) * instruction[i + 1].u.operand, X86::edi);
896             i += 2;
897             break;
898         }
899         CTI_COMPILE_BINARY_OP(op_eq)
900         case op_lshift: {
901             emitGetArg(instruction[i + 2].u.operand, X86::eax);
902             emitGetArg(instruction[i + 3].u.operand, X86::ecx);
903             emitJumpSlowCaseIfNotImm(X86::eax, i);
904             emitJumpSlowCaseIfNotImm(X86::ecx, i);
905             emitFastArithImmToInt(X86::eax);
906             emitFastArithImmToInt(X86::ecx);
907             m_jit.shll_CLr(X86::eax);
908             emitFastArithIntToImmOrSlowCase(X86::eax, i);
909             emitPutResult(instruction[i + 1].u.operand);
910             i += 4;
911             break;
912         }
913         case op_bitand: {
914             unsigned src1 = instruction[i + 2].u.operand;
915             unsigned src2 = instruction[i + 3].u.operand;
916             unsigned dst = instruction[i + 1].u.operand;
917             if (JSValue* value = getConstantImmediateNumericArg(src1)) {
918                 emitGetArg(src2, X86::eax);
919                 emitJumpSlowCaseIfNotImm(X86::eax, i);
920                 m_jit.andl_i32r(reinterpret_cast<unsigned>(value), X86::eax); // FIXME: make it more obvious this is relying on the format of JSImmediate
921                 emitPutResult(dst);
922             } else if (JSValue* value = getConstantImmediateNumericArg(src2)) {
923                 emitGetArg(src1, X86::eax);
924                 emitJumpSlowCaseIfNotImm(X86::eax, i);
925                 m_jit.andl_i32r(reinterpret_cast<unsigned>(value), X86::eax);
926                 emitPutResult(dst);
927             } else {
928                 emitGetArg(src1, X86::eax);
929                 emitGetArg(src2, X86::edx);
930                 m_jit.andl_rr(X86::edx, X86::eax);
931                 emitJumpSlowCaseIfNotImm(X86::eax, i);
932                 emitPutResult(dst);
933             }
934             i += 4;
935             break;
936         }
937         case op_rshift: {
938             emitGetArg(instruction[i + 2].u.operand, X86::eax);
939             emitGetArg(instruction[i + 3].u.operand, X86::ecx);
940             emitJumpSlowCaseIfNotImm(X86::eax, i);
941             emitJumpSlowCaseIfNotImm(X86::ecx, i);
942             emitFastArithImmToInt(X86::ecx);
943             m_jit.sarl_CLr(X86::eax);
944             emitFastArithPotentiallyReTagImmediate(X86::eax);
945             emitPutResult(instruction[i + 1].u.operand);
946             i += 4;
947             break;
948         }
949         case op_bitnot: {
950             emitGetArg(instruction[i + 2].u.operand, X86::eax);
951             emitJumpSlowCaseIfNotImm(X86::eax, i);
952             m_jit.xorl_i8r(~JSImmediate::TagBitTypeInteger, X86::eax);
953             emitPutResult(instruction[i + 1].u.operand);
954             i += 3;
955             break;
956         }
957         case op_resolve_with_base: {
958             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 3].u.operand]);
959             emitPutArgConstant(reinterpret_cast<unsigned>(ident), 0);
960             emitCall(i, Machine::cti_op_resolve_with_base);
961             emitPutResult(instruction[i + 1].u.operand);
962             emitGetCTIParam(CTI_ARGS_2ndResult, X86::eax);
963             emitPutResult(instruction[i + 2].u.operand);
964             i += 4;
965             break;
966         }
967         case op_new_func_exp: {
968             FuncExprNode* func = (m_codeBlock->functionExpressions[instruction[i + 2].u.operand]).get();
969             emitPutArgConstant(reinterpret_cast<unsigned>(func), 0);
970             emitCall(i, Machine::cti_op_new_func_exp);
971             emitPutResult(instruction[i + 1].u.operand);
972             i += 3;
973             break;
974         }
975         case op_mod: {
976             emitGetArg(instruction[i + 2].u.operand, X86::eax);
977             emitGetArg(instruction[i + 3].u.operand, X86::ecx);
978             emitJumpSlowCaseIfNotImm(X86::eax, i);
979             emitJumpSlowCaseIfNotImm(X86::ecx, i);
980             emitFastArithDeTagImmediate(X86::eax);
981             emitFastArithDeTagImmediate(X86::ecx);
982             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJe(), i)); // This is checking if the last detag resulted in a value 0.
983             m_jit.cdq();
984             m_jit.idivl_r(X86::ecx);
985             emitFastArithReTagImmediate(X86::edx);
986             m_jit.movl_rr(X86::edx, X86::eax);
987             emitPutResult(instruction[i + 1].u.operand);
988             i += 4;
989             break;
990         }
991         case op_jtrue: {
992             unsigned target = instruction[i + 2].u.operand;
993             emitGetArg(instruction[i + 1].u.operand, X86::eax);
994
995             m_jit.cmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::zeroImmediate()), X86::eax);
996             X86Assembler::JmpSrc isZero = m_jit.emitUnlinkedJe();
997             m_jit.testl_i32r(JSImmediate::TagBitTypeInteger, X86::eax);
998             m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJne(), i + 2 + target));
999
1000             m_jit.cmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::trueImmediate()), X86::eax);
1001             m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJe(), i + 2 + target));
1002             m_jit.cmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::falseImmediate()), X86::eax);
1003             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
1004
1005             m_jit.link(isZero, m_jit.label());
1006             i += 3;
1007             break;
1008         }
1009         CTI_COMPILE_BINARY_OP(op_less)
1010         CTI_COMPILE_BINARY_OP(op_neq)
1011         case op_post_dec: {
1012             int srcDst = instruction[i + 2].u.operand;
1013             emitGetArg(srcDst, X86::eax);
1014             m_jit.movl_rr(X86::eax, X86::edx);
1015             emitJumpSlowCaseIfNotImm(X86::eax, i);
1016             m_jit.subl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), X86::edx);
1017             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
1018             emitPutResult(srcDst, X86::edx);
1019             emitPutResult(instruction[i + 1].u.operand);
1020             i += 3;
1021             break;
1022         }
1023         CTI_COMPILE_BINARY_OP(op_urshift)
1024         case op_bitxor: {
1025             emitGetArg(instruction[i + 2].u.operand, X86::eax);
1026             emitGetArg(instruction[i + 3].u.operand, X86::edx);
1027             emitJumpSlowCaseIfNotImms(X86::eax, X86::edx, i);
1028             m_jit.xorl_rr(X86::edx, X86::eax);
1029             emitFastArithReTagImmediate(X86::eax);
1030             emitPutResult(instruction[i + 1].u.operand);
1031             i += 4;
1032             break;
1033         }
1034         case op_new_regexp: {
1035             RegExp* regExp = m_codeBlock->regexps[instruction[i + 2].u.operand].get();
1036             emitPutArgConstant(reinterpret_cast<unsigned>(regExp), 0);
1037             emitCall(i, Machine::cti_op_new_regexp);
1038             emitPutResult(instruction[i + 1].u.operand);
1039             i += 3;
1040             break;
1041         }
1042         case op_bitor: {
1043             emitGetArg(instruction[i + 2].u.operand, X86::eax);
1044             emitGetArg(instruction[i + 3].u.operand, X86::edx);
1045             emitJumpSlowCaseIfNotImms(X86::eax, X86::edx, i);
1046             m_jit.orl_rr(X86::edx, X86::eax);
1047             emitPutResult(instruction[i + 1].u.operand);
1048             i += 4;
1049             break;
1050         }
1051         case op_call_eval: {
1052             compileOpCall(instruction, i, OpCallEval);
1053             i += 6;
1054             break;
1055         }
1056         case op_throw: {
1057             emitGetPutArg(instruction[i + 1].u.operand, 0, X86::ecx);
1058             emitCall(i, Machine::cti_op_throw);
1059             m_jit.addl_i8r(0x24, X86::esp);
1060             m_jit.popl_r(X86::edi);
1061             m_jit.popl_r(X86::esi);
1062             m_jit.ret();
1063             i += 2;
1064             break;
1065         }
1066         case op_get_pnames: {
1067             emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
1068             emitCall(i, Machine::cti_op_get_pnames);
1069             emitPutResult(instruction[i + 1].u.operand);
1070             i += 3;
1071             break;
1072         }
1073         case op_next_pname: {
1074             emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
1075             unsigned target = instruction[i + 3].u.operand;
1076             emitCall(i, Machine::cti_op_next_pname);
1077             m_jit.testl_rr(X86::eax, X86::eax);
1078             X86Assembler::JmpSrc endOfIter = m_jit.emitUnlinkedJe();
1079             emitPutResult(instruction[i + 1].u.operand);
1080             m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJmp(), i + 3 + target));
1081             m_jit.link(endOfIter, m_jit.label());
1082             i += 4;
1083             break;
1084         }
1085         case op_push_scope: {
1086             emitGetPutArg(instruction[i + 1].u.operand, 0, X86::ecx);
1087             emitCall(i, Machine::cti_op_push_scope);
1088             i += 2;
1089             break;
1090         }
1091         case op_pop_scope: {
1092             emitCall(i, Machine::cti_op_pop_scope);
1093             i += 1;
1094             break;
1095         }
1096         case op_typeof: {
1097             emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
1098             emitCall(i, Machine::cti_op_typeof);
1099             emitPutResult(instruction[i + 1].u.operand);
1100             i += 3;
1101             break;
1102         }
1103         CTI_COMPILE_BINARY_OP(op_stricteq)
1104         CTI_COMPILE_BINARY_OP(op_nstricteq)
1105         case op_to_jsnumber: {
1106             emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
1107             emitCall(i, Machine::cti_op_to_jsnumber);
1108             emitPutResult(instruction[i + 1].u.operand);
1109             i += 3;
1110             break;
1111         }
1112         case op_in: {
1113             emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
1114             emitGetPutArg(instruction[i + 3].u.operand, 4, X86::ecx);
1115             emitCall(i, Machine::cti_op_in);
1116             emitPutResult(instruction[i + 1].u.operand);
1117             i += 4;
1118             break;
1119         }
1120         case op_push_new_scope: {
1121             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
1122             emitPutArgConstant(reinterpret_cast<unsigned>(ident), 0);
1123             emitGetPutArg(instruction[i + 3].u.operand, 4, X86::ecx);
1124             emitCall(i, Machine::cti_op_push_new_scope);
1125             emitPutResult(instruction[i + 1].u.operand);
1126             i += 4;
1127             break;
1128         }
1129         case op_catch: {
1130             emitGetCTIParam(CTI_ARGS_r, X86::edi); // edi := r
1131             emitGetCTIParam(CTI_ARGS_exec, X86::ecx);
1132             m_jit.movl_mr(OBJECT_OFFSET(ExecState, m_exception), X86::ecx, X86::eax);
1133             m_jit.movl_i32m(0, OBJECT_OFFSET(ExecState, m_exception), X86::ecx);
1134             emitPutResult(instruction[i + 1].u.operand);
1135             i += 2;
1136             break;
1137         }
1138         case op_jmp_scopes: {
1139             unsigned count = instruction[i + 1].u.operand;
1140             emitPutArgConstant(count, 0);
1141             emitCall(i, Machine::cti_op_jmp_scopes);
1142             unsigned target = instruction[i + 2].u.operand;
1143             m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJmp(), i + 2 + target));
1144             i += 3;
1145             break;
1146         }
1147         case op_put_by_index: {
1148             emitGetPutArg(instruction[i + 1].u.operand, 0, X86::ecx);
1149             emitPutArgConstant(instruction[i + 2].u.operand, 4);
1150             emitGetPutArg(instruction[i + 3].u.operand, 8, X86::ecx);
1151             emitCall(i, Machine::cti_op_put_by_index);
1152             i += 4;
1153             break;
1154         }
1155         case op_switch_imm: {
1156             unsigned tableIndex = instruction[i + 1].u.operand;
1157             unsigned defaultOffset = instruction[i + 2].u.operand;
1158             unsigned scrutinee = instruction[i + 3].u.operand;
1159
1160             // create jump table for switch destinations, track this switch statement.
1161             SimpleJumpTable* jumpTable = &m_codeBlock->immediateSwitchJumpTables[tableIndex];
1162             m_switches.append(SwitchRecord(jumpTable, i, defaultOffset, SwitchRecord::Immediate));
1163             jumpTable->ctiOffsets.grow(jumpTable->branchOffsets.size());
1164
1165             emitGetPutArg(scrutinee, 0, X86::ecx);
1166             emitPutArgConstant(tableIndex, 4);
1167             emitCall(i, Machine::cti_op_switch_imm);
1168             m_jit.jmp_r(X86::eax);
1169             i += 4;
1170             break;
1171         }
1172         case op_switch_char: {
1173             unsigned tableIndex = instruction[i + 1].u.operand;
1174             unsigned defaultOffset = instruction[i + 2].u.operand;
1175             unsigned scrutinee = instruction[i + 3].u.operand;
1176
1177             // create jump table for switch destinations, track this switch statement.
1178             SimpleJumpTable* jumpTable = &m_codeBlock->characterSwitchJumpTables[tableIndex];
1179             m_switches.append(SwitchRecord(jumpTable, i, defaultOffset, SwitchRecord::Character));
1180             jumpTable->ctiOffsets.grow(jumpTable->branchOffsets.size());
1181
1182             emitGetPutArg(scrutinee, 0, X86::ecx);
1183             emitPutArgConstant(tableIndex, 4);
1184             emitCall(i, Machine::cti_op_switch_char);
1185             m_jit.jmp_r(X86::eax);
1186             i += 4;
1187             break;
1188         }
1189         case op_switch_string: {
1190             unsigned tableIndex = instruction[i + 1].u.operand;
1191             unsigned defaultOffset = instruction[i + 2].u.operand;
1192             unsigned scrutinee = instruction[i + 3].u.operand;
1193
1194             // create jump table for switch destinations, track this switch statement.
1195             StringJumpTable* jumpTable = &m_codeBlock->stringSwitchJumpTables[tableIndex];
1196             m_switches.append(SwitchRecord(jumpTable, i, defaultOffset));
1197
1198             emitGetPutArg(scrutinee, 0, X86::ecx);
1199             emitPutArgConstant(tableIndex, 4);
1200             emitCall(i, Machine::cti_op_switch_string);
1201             m_jit.jmp_r(X86::eax);
1202             i += 4;
1203             break;
1204         }
1205         case op_del_by_val: {
1206             emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
1207             emitGetPutArg(instruction[i + 3].u.operand, 4, X86::ecx);
1208             emitCall(i, Machine::cti_op_del_by_val);
1209             emitPutResult(instruction[i + 1].u.operand);
1210             i += 4;
1211             break;
1212         }
1213         case op_put_getter: {
1214             emitGetPutArg(instruction[i + 1].u.operand, 0, X86::ecx);
1215             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
1216             emitPutArgConstant(reinterpret_cast<unsigned>(ident), 4);
1217             emitGetPutArg(instruction[i + 3].u.operand, 8, X86::ecx);
1218             emitCall(i, Machine::cti_op_put_getter);
1219             i += 4;
1220             break;
1221         }
1222         case op_put_setter: {
1223             emitGetPutArg(instruction[i + 1].u.operand, 0, X86::ecx);
1224             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
1225             emitPutArgConstant(reinterpret_cast<unsigned>(ident), 4);
1226             emitGetPutArg(instruction[i + 3].u.operand, 8, X86::ecx);
1227             emitCall(i, Machine::cti_op_put_setter);
1228             i += 4;
1229             break;
1230         }
1231         case op_new_error: {
1232             JSValue* message = m_codeBlock->unexpectedConstants[instruction[i + 3].u.operand];
1233             emitPutArgConstant(instruction[i + 2].u.operand, 0);
1234             emitPutArgConstant(reinterpret_cast<unsigned>(message), 4);
1235             emitPutArgConstant(m_codeBlock->lineNumberForVPC(&instruction[i]), 8);
1236             emitCall(i, Machine::cti_op_new_error);
1237             emitPutResult(instruction[i + 1].u.operand);
1238             i += 4;
1239             break;
1240         }
1241         case op_debug: {
1242             emitPutArgConstant(instruction[i + 1].u.operand, 0);
1243             emitPutArgConstant(instruction[i + 2].u.operand, 4);
1244             emitPutArgConstant(instruction[i + 3].u.operand, 8);
1245             emitCall(i, Machine::cti_op_debug);
1246             i += 4;
1247             break;
1248         }
1249         case op_eq_null: {
1250             emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
1251             emitCall(i, Machine::cti_op_eq_null);
1252             emitPutResult(instruction[i + 1].u.operand);
1253             i += 3;
1254             break;
1255         }
1256         case op_neq_null: {
1257             emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
1258             emitCall(i, Machine::cti_op_neq_null);
1259             emitPutResult(instruction[i + 1].u.operand);
1260             i += 3;
1261             break;
1262         }
1263         case op_get_array_length:
1264         case op_get_by_id_chain:
1265         case op_get_by_id_generic:
1266         case op_get_by_id_proto:
1267         case op_get_by_id_self:
1268         case op_get_string_length:
1269         case op_put_by_id_generic:
1270         case op_put_by_id_replace:
1271             ASSERT_NOT_REACHED();
1272         }
1273     }
1274 }
1275
1276
1277 void CTI::privateCompileLinkPass()
1278 {
1279     unsigned jmpTableCount = m_jmpTable.size();
1280     for (unsigned i = 0; i < jmpTableCount; ++i)
1281         m_jit.link(m_jmpTable[i].from, m_labels[m_jmpTable[i].to]);
1282     m_jmpTable.clear();
1283 }
1284
1285 void CTI::privateCompileSlowCases()
1286 {
1287     Instruction* instruction = m_codeBlock->instructions.begin();
1288     for (Vector<SlowCaseEntry>::iterator iter = m_slowCases.begin(); iter != m_slowCases.end(); ++iter) {
1289         int i = iter->to;
1290        m_jit.emitRestoreArgumentReference();
1291         switch (m_machine->getOpcodeID(instruction[i].u.opcode)) {
1292         case op_add: {
1293             unsigned dst = instruction[i + 1].u.operand;
1294             unsigned src2 = instruction[i + 3].u.operand;
1295             if (src2 < m_codeBlock->constantRegisters.size()) {
1296                 JSValue* value = m_codeBlock->constantRegisters[src2].jsValue(m_exec);
1297                 if (JSImmediate::isNumber(value)) {
1298                     X86Assembler::JmpSrc notImm = iter->from;
1299                     m_jit.link((++iter)->from, m_jit.label());
1300                     m_jit.subl_i32r(getDeTaggedConstantImmediate(value), X86::eax);
1301                     m_jit.link(notImm, m_jit.label());
1302                     emitPutArg(X86::eax, 0);
1303                     emitGetPutArg(src2, 4, X86::ecx);
1304                     emitCall(i, Machine::cti_op_add);
1305                     emitPutResult(dst);
1306                     i += 4;
1307                     break;
1308                 }
1309             }
1310
1311             ASSERT(!(static_cast<unsigned>(instruction[i + 2].u.operand) < m_codeBlock->constantRegisters.size()));
1312
1313             X86Assembler::JmpSrc notImm = iter->from;
1314             m_jit.link((++iter)->from, m_jit.label());
1315             m_jit.subl_rr(X86::edx, X86::eax);
1316             emitFastArithReTagImmediate(X86::eax);
1317             m_jit.link(notImm, m_jit.label());
1318             emitPutArg(X86::eax, 0);
1319             emitPutArg(X86::edx, 4);
1320             emitCall(i, Machine::cti_op_add);
1321             emitPutResult(dst);
1322             i += 4;
1323             break;
1324         }
1325         case op_get_by_val: {
1326             X86Assembler::JmpSrc notImm = iter->from;
1327             m_jit.link((++iter)->from, m_jit.label());
1328             m_jit.link((++iter)->from, m_jit.label());
1329             m_jit.link((++iter)->from, m_jit.label());
1330             emitFastArithIntToImmNoCheck(X86::edx);
1331             m_jit.link(notImm, m_jit.label());
1332             emitPutArg(X86::eax, 0);
1333             emitPutArg(X86::edx, 4);
1334             emitCall(i, Machine::cti_op_get_by_val);
1335             emitPutResult(instruction[i + 1].u.operand);
1336             i += 4;
1337             break;
1338         }
1339         case op_sub: {
1340             X86Assembler::JmpSrc notImm = iter->from;
1341             m_jit.link((++iter)->from, m_jit.label());
1342             m_jit.addl_rr(X86::edx, X86::eax);
1343             m_jit.link(notImm, m_jit.label());
1344             emitPutArg(X86::eax, 0);
1345             emitPutArg(X86::edx, 4);
1346             emitCall(i, Machine::cti_op_sub);
1347             emitPutResult(instruction[i + 1].u.operand);
1348             i += 4;
1349             break;
1350         }
1351         case op_rshift: {
1352             m_jit.link(iter->from, m_jit.label());
1353             m_jit.link((++iter)->from, m_jit.label());
1354             emitPutArg(X86::eax, 0);
1355             emitPutArg(X86::ecx, 4);
1356             emitCall(i, Machine::cti_op_rshift);
1357             emitPutResult(instruction[i + 1].u.operand);
1358             i += 4;
1359             break;
1360         }
1361         case op_lshift: {
1362             X86Assembler::JmpSrc notImm1 = iter->from;
1363             X86Assembler::JmpSrc notImm2 = (++iter)->from;
1364             m_jit.link((++iter)->from, m_jit.label());
1365             emitGetArg(instruction[i + 2].u.operand, X86::eax);
1366             emitGetArg(instruction[i + 3].u.operand, X86::ecx);
1367             m_jit.link(notImm1, m_jit.label());
1368             m_jit.link(notImm2, m_jit.label());
1369             emitPutArg(X86::eax, 0);
1370             emitPutArg(X86::ecx, 4);
1371             emitCall(i, Machine::cti_op_lshift);
1372             emitPutResult(instruction[i + 1].u.operand);
1373             i += 4;
1374             break;
1375         }
1376         case op_loop_if_less: {
1377             emitSlowScriptCheck(i);
1378
1379             unsigned target = instruction[i + 3].u.operand;
1380             JSValue* src2imm = getConstantImmediateNumericArg(instruction[i + 2].u.operand);
1381             if (src2imm) {
1382                 m_jit.link(iter->from, m_jit.label());
1383                 emitPutArg(X86::edx, 0);
1384                 emitGetPutArg(instruction[i + 2].u.operand, 4, X86::ecx);
1385                 emitCall(i, Machine::cti_op_loop_if_less);
1386                 m_jit.testl_rr(X86::eax, X86::eax);
1387                 m_jit.link(m_jit.emitUnlinkedJne(), m_labels[i + 3 + target]);
1388             } else {
1389                 m_jit.link(iter->from, m_jit.label());
1390                 m_jit.link((++iter)->from, m_jit.label());
1391                 emitPutArg(X86::eax, 0);
1392                 emitPutArg(X86::edx, 4);
1393                 emitCall(i, Machine::cti_op_loop_if_less);
1394                 m_jit.testl_rr(X86::eax, X86::eax);
1395                 m_jit.link(m_jit.emitUnlinkedJne(), m_labels[i + 3 + target]);
1396             }
1397             i += 4;
1398             break;
1399         }
1400         case op_pre_inc: {
1401             unsigned srcDst = instruction[i + 1].u.operand;
1402             X86Assembler::JmpSrc notImm = iter->from;
1403             m_jit.link((++iter)->from, m_jit.label());
1404             m_jit.subl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), X86::eax);
1405             m_jit.link(notImm, m_jit.label());
1406             emitPutArg(X86::eax, 0);
1407             emitCall(i, Machine::cti_op_pre_inc);
1408             emitPutResult(srcDst);
1409             i += 2;
1410             break;
1411         }
1412         case op_put_by_val: {
1413             X86Assembler::JmpSrc notImm = iter->from;
1414             m_jit.link((++iter)->from, m_jit.label());
1415             m_jit.link((++iter)->from, m_jit.label());
1416             m_jit.link((++iter)->from, m_jit.label());
1417             emitFastArithIntToImmNoCheck(X86::edx);
1418             m_jit.link(notImm, m_jit.label());
1419             emitPutArg(X86::eax, 0);
1420             emitPutArg(X86::edx, 4);
1421             emitPutArg(X86::ecx, 8);
1422             emitCall(i, Machine::cti_op_put_by_val);
1423             i += 4;
1424             break;
1425         }
1426         case op_loop_if_true: {
1427             emitSlowScriptCheck(i);
1428
1429             m_jit.link(iter->from, m_jit.label());
1430             emitPutArg(X86::eax, 0);
1431             emitCall(i, Machine::cti_op_jtrue);
1432             m_jit.testl_rr(X86::eax, X86::eax);
1433             unsigned target = instruction[i + 2].u.operand;
1434             m_jit.link(m_jit.emitUnlinkedJne(), m_labels[i + 2 + target]);
1435             i += 3;
1436             break;
1437         }
1438         case op_pre_dec: {
1439             unsigned srcDst = instruction[i + 1].u.operand;
1440             X86Assembler::JmpSrc notImm = iter->from;
1441             m_jit.link((++iter)->from, m_jit.label());
1442             m_jit.addl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), X86::eax);
1443             m_jit.link(notImm, m_jit.label());
1444             emitPutArg(X86::eax, 0);
1445             emitCall(i, Machine::cti_op_pre_dec);
1446             emitPutResult(srcDst);
1447             i += 2;
1448             break;
1449         }
1450         case op_jnless: {
1451             unsigned target = instruction[i + 3].u.operand;
1452             JSValue* src2imm = getConstantImmediateNumericArg(instruction[i + 2].u.operand);
1453             if (src2imm) {
1454                 m_jit.link(iter->from, m_jit.label());
1455                 emitPutArg(X86::edx, 0);
1456                 emitGetPutArg(instruction[i + 2].u.operand, 4, X86::ecx);
1457                 emitCall(i, Machine::cti_op_jless);
1458                 m_jit.testl_rr(X86::eax, X86::eax);
1459                 m_jit.link(m_jit.emitUnlinkedJe(), m_labels[i + 3 + target]);
1460             } else {
1461                 m_jit.link(iter->from, m_jit.label());
1462                 m_jit.link((++iter)->from, m_jit.label());
1463                 emitPutArg(X86::eax, 0);
1464                 emitPutArg(X86::edx, 4);
1465                 emitCall(i, Machine::cti_op_jless);
1466                 m_jit.testl_rr(X86::eax, X86::eax);
1467                 m_jit.link(m_jit.emitUnlinkedJe(), m_labels[i + 3 + target]);
1468             }
1469             i += 4;
1470             break;
1471         }
1472         case op_not: {
1473             m_jit.link(iter->from, m_jit.label());
1474             m_jit.xorl_i8r(JSImmediate::FullTagTypeBool, X86::eax);
1475             emitPutArg(X86::eax, 0);
1476             emitCall(i, Machine::cti_op_not);
1477             emitPutResult(instruction[i + 1].u.operand);
1478             i += 3;
1479             break;
1480         }
1481         case op_jfalse: {
1482             m_jit.link(iter->from, m_jit.label());
1483             emitPutArg(X86::eax, 0);
1484             emitCall(i, Machine::cti_op_jtrue);
1485             m_jit.testl_rr(X86::eax, X86::eax);
1486             unsigned target = instruction[i + 2].u.operand;
1487             m_jit.link(m_jit.emitUnlinkedJe(), m_labels[i + 2 + target]); // inverted!
1488             i += 3;
1489             break;
1490         }
1491         case op_post_inc: {
1492             unsigned srcDst = instruction[i + 2].u.operand;
1493             m_jit.link(iter->from, m_jit.label());
1494             m_jit.link((++iter)->from, m_jit.label());
1495             emitPutArg(X86::eax, 0);
1496             emitCall(i, Machine::cti_op_post_inc);
1497             emitPutResult(instruction[i + 1].u.operand);
1498             emitGetCTIParam(CTI_ARGS_2ndResult, X86::eax);
1499             emitPutResult(srcDst);
1500             i += 3;
1501             break;
1502         }
1503         case op_bitnot: {
1504             m_jit.link(iter->from, m_jit.label());
1505             emitPutArg(X86::eax, 0);
1506             emitCall(i, Machine::cti_op_bitnot);
1507             emitPutResult(instruction[i + 1].u.operand);
1508             i += 3;
1509             break;
1510         }
1511         case op_bitand: {
1512             unsigned src1 = instruction[i + 2].u.operand;
1513             unsigned src2 = instruction[i + 3].u.operand;
1514             unsigned dst = instruction[i + 1].u.operand;
1515             if (getConstantImmediateNumericArg(src1)) {
1516                 m_jit.link(iter->from, m_jit.label());
1517                 emitGetPutArg(src1, 0, X86::ecx);
1518                 emitPutArg(X86::eax, 4);
1519                 emitCall(i, Machine::cti_op_bitand);
1520                 emitPutResult(dst);
1521             } else if (getConstantImmediateNumericArg(src2)) {
1522                 m_jit.link(iter->from, m_jit.label());
1523                 emitPutArg(X86::eax, 0);
1524                 emitGetPutArg(src2, 4, X86::ecx);
1525                 emitCall(i, Machine::cti_op_bitand);
1526                 emitPutResult(dst);
1527             } else {
1528                 m_jit.link(iter->from, m_jit.label());
1529                 emitGetPutArg(src1, 0, X86::ecx);
1530                 emitPutArg(X86::edx, 4);
1531                 emitCall(i, Machine::cti_op_bitand);
1532                 emitPutResult(dst);
1533             }
1534             i += 4;
1535             break;
1536         }
1537         case op_jtrue: {
1538             m_jit.link(iter->from, m_jit.label());
1539             emitPutArg(X86::eax, 0);
1540             emitCall(i, Machine::cti_op_jtrue);
1541             m_jit.testl_rr(X86::eax, X86::eax);
1542             unsigned target = instruction[i + 2].u.operand;
1543             m_jit.link(m_jit.emitUnlinkedJne(), m_labels[i + 2 + target]);
1544             i += 3;
1545             break;
1546         }
1547         case op_post_dec: {
1548             unsigned srcDst = instruction[i + 2].u.operand;
1549             m_jit.link(iter->from, m_jit.label());
1550             m_jit.link((++iter)->from, m_jit.label());
1551             emitPutArg(X86::eax, 0);
1552             emitCall(i, Machine::cti_op_post_dec);
1553             emitPutResult(instruction[i + 1].u.operand);
1554             emitGetCTIParam(CTI_ARGS_2ndResult, X86::eax);
1555             emitPutResult(srcDst);
1556             i += 3;
1557             break;
1558         }
1559         case op_bitxor: {
1560             m_jit.link(iter->from, m_jit.label());
1561             emitPutArg(X86::eax, 0);
1562             emitPutArg(X86::edx, 4);
1563             emitCall(i, Machine::cti_op_bitxor);
1564             emitPutResult(instruction[i + 1].u.operand);
1565             i += 4;
1566             break;
1567         }
1568         case op_bitor: {
1569             m_jit.link(iter->from, m_jit.label());
1570             emitPutArg(X86::eax, 0);
1571             emitPutArg(X86::edx, 4);
1572             emitCall(i, Machine::cti_op_bitor);
1573             emitPutResult(instruction[i + 1].u.operand);
1574             i += 4;
1575             break;
1576         }
1577         case op_mod: {
1578             X86Assembler::JmpSrc notImm1 = iter->from;
1579             X86Assembler::JmpSrc notImm2 = (++iter)->from;
1580             m_jit.link((++iter)->from, m_jit.label());
1581             emitFastArithReTagImmediate(X86::eax);
1582             emitFastArithReTagImmediate(X86::ecx);
1583             m_jit.link(notImm1, m_jit.label());
1584             m_jit.link(notImm2, m_jit.label());
1585             emitPutArg(X86::eax, 0);
1586             emitPutArg(X86::ecx, 4);
1587             emitCall(i, Machine::cti_op_mod);
1588             emitPutResult(instruction[i + 1].u.operand);
1589             i += 4;
1590             break;
1591         }
1592         default:
1593             ASSERT_NOT_REACHED();
1594             break;
1595         }
1596
1597         m_jit.link(m_jit.emitUnlinkedJmp(), m_labels[i]);
1598     }
1599 }
1600
1601 void CTI::privateCompile()
1602 {
1603     // Could use a popl_m, but would need to offset the following instruction if so.
1604     m_jit.popl_r(X86::ecx);
1605     emitGetCTIParam(CTI_ARGS_r, X86::edi); // edi := r
1606     emitPutToCallFrameHeader(X86::ecx, RegisterFile::CTIReturnEIP);
1607
1608     privateCompileMainPass();
1609     privateCompileLinkPass();
1610     privateCompileSlowCases();
1611
1612     ASSERT(m_jmpTable.isEmpty());
1613
1614     void* code = m_jit.copy();
1615     ASSERT(code);
1616
1617     // Translate vPC offsets into addresses in JIT generated code, for switch tables.
1618     for (unsigned i = 0; i < m_switches.size(); ++i) {
1619         SwitchRecord record = m_switches[i];
1620         unsigned opcodeIndex = record.m_opcodeIndex;
1621
1622         if (record.m_type != SwitchRecord::String) {
1623             ASSERT(record.m_type == SwitchRecord::Immediate || record.m_type == SwitchRecord::Character); 
1624             ASSERT(record.m_jumpTable.m_simpleJumpTable->branchOffsets.size() == record.m_jumpTable.m_simpleJumpTable->ctiOffsets.size());
1625
1626             record.m_jumpTable.m_simpleJumpTable->ctiDefault = m_jit.getRelocatedAddress(code, m_labels[opcodeIndex + 3 + record.m_defaultOffset]);
1627
1628             for (unsigned j = 0; j < record.m_jumpTable.m_simpleJumpTable->branchOffsets.size(); ++j) {
1629                 unsigned offset = record.m_jumpTable.m_simpleJumpTable->branchOffsets[j];
1630                 record.m_jumpTable.m_simpleJumpTable->ctiOffsets[j] = offset ? m_jit.getRelocatedAddress(code, m_labels[opcodeIndex + 3 + offset]) : record.m_jumpTable.m_simpleJumpTable->ctiDefault;
1631             }
1632         } else {
1633             ASSERT(record.m_type == SwitchRecord::String);
1634
1635             record.m_jumpTable.m_stringJumpTable->ctiDefault = m_jit.getRelocatedAddress(code, m_labels[opcodeIndex + 3 + record.m_defaultOffset]);
1636
1637             StringJumpTable::StringOffsetTable::iterator end = record.m_jumpTable.m_stringJumpTable->offsetTable.end();            
1638             for (StringJumpTable::StringOffsetTable::iterator it = record.m_jumpTable.m_stringJumpTable->offsetTable.begin(); it != end; ++it) {
1639                 unsigned offset = it->second.branchOffset;
1640                 it->second.ctiOffset = offset ? m_jit.getRelocatedAddress(code, m_labels[opcodeIndex + 3 + offset]) : record.m_jumpTable.m_stringJumpTable->ctiDefault;
1641             }
1642         }
1643     }
1644
1645     for (Vector<HandlerInfo>::iterator iter = m_codeBlock->exceptionHandlers.begin(); iter != m_codeBlock->exceptionHandlers.end(); ++iter)
1646          iter->nativeCode = m_jit.getRelocatedAddress(code, m_labels[iter->target]);
1647
1648     // FIXME: There doesn't seem to be a way to hint to a hashmap that it should make a certain capacity available;
1649     // could be faster if we could do something like this:
1650     // m_codeBlock->ctiReturnAddressVPCMap.grow(m_calls.size());
1651     for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
1652         X86Assembler::link(code, iter->from, iter->to);
1653         m_codeBlock->ctiReturnAddressVPCMap.add(m_jit.getRelocatedAddress(code, iter->from), iter->opcodeIndex);
1654     }
1655
1656     // Link absolute addresses for jsr
1657     for (Vector<JSRInfo>::iterator iter = m_jsrSites.begin(); iter != m_jsrSites.end(); ++iter)
1658         X86Assembler::linkAbsoluteAddress(code, iter->addrPosition, iter->target);
1659
1660     m_codeBlock->ctiCode = code;
1661 }
1662
1663 void* CTI::privateCompileGetByIdSelf(StructureID* structureID, size_t cachedOffset)
1664 {
1665     // Check eax is an object of the right StructureID.
1666     m_jit.testl_i32r(JSImmediate::TagMask, X86::eax);
1667     X86Assembler::JmpSrc failureCases1 = m_jit.emitUnlinkedJne();
1668     m_jit.cmpl_i32m(reinterpret_cast<uint32_t>(structureID), OBJECT_OFFSET(JSCell, m_structureID), X86::eax);
1669     X86Assembler::JmpSrc failureCases2 = m_jit.emitUnlinkedJne();
1670
1671     // Checks out okay! - getDirectOffset
1672     m_jit.movl_mr(OBJECT_OFFSET(JSObject, m_propertyStorage), X86::eax, X86::eax);
1673     m_jit.movl_mr(cachedOffset * sizeof(JSValue*), X86::eax, X86::eax);
1674     m_jit.ret();
1675
1676     void* code = m_jit.copy();
1677     ASSERT(code);
1678
1679     X86Assembler::link(code, failureCases1, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
1680     X86Assembler::link(code, failureCases2, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
1681     
1682     m_codeBlock->structureIDAccessStubs.append(code);
1683     
1684     return code;
1685 }
1686
1687 void* CTI::privateCompileGetByIdProto(ExecState* exec, StructureID* structureID, StructureID* prototypeStructureID, size_t cachedOffset)
1688 {
1689     // The prototype object definitely exists (if this stub exists the CodeBlock is referencing a StructureID that is
1690     // referencing the prototype object - let's speculatively load it's table nice and early!)
1691     JSObject* protoObject = static_cast<JSObject*>(structureID->prototypeForLookup(exec));
1692     OwnArrayPtr<JSValue*>* protoPropertyStorage = &protoObject->m_propertyStorage;
1693     m_jit.movl_mr(static_cast<void*>(protoPropertyStorage), X86::edx);
1694
1695     // check eax is an object of the right StructureID.
1696     m_jit.testl_i32r(JSImmediate::TagMask, X86::eax);
1697     X86Assembler::JmpSrc failureCases1 = m_jit.emitUnlinkedJne();
1698     m_jit.cmpl_i32m(reinterpret_cast<uint32_t>(structureID), OBJECT_OFFSET(JSCell, m_structureID), X86::eax);
1699     X86Assembler::JmpSrc failureCases2 = m_jit.emitUnlinkedJne();
1700
1701     // Check the prototype object's StructureID had not changed.
1702     StructureID** protoStructureIDAddress = &(protoObject->m_structureID);
1703     m_jit.cmpl_i32m(reinterpret_cast<uint32_t>(prototypeStructureID), static_cast<void*>(protoStructureIDAddress));
1704     X86Assembler::JmpSrc failureCases3 = m_jit.emitUnlinkedJne();
1705
1706     // Checks out okay! - getDirectOffset
1707     m_jit.movl_mr(cachedOffset * sizeof(JSValue*), X86::edx, X86::eax);
1708
1709     m_jit.ret();
1710
1711     void* code = m_jit.copy();
1712     ASSERT(code);
1713
1714     X86Assembler::link(code, failureCases1, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
1715     X86Assembler::link(code, failureCases2, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
1716     X86Assembler::link(code, failureCases3, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
1717
1718     m_codeBlock->structureIDAccessStubs.append(code);
1719
1720     return code;
1721 }
1722
1723 void* CTI::privateCompileGetByIdChain(ExecState* exec, StructureID* structureID, StructureIDChain* chain, size_t count, size_t cachedOffset)
1724 {
1725     ASSERT(count);
1726     
1727     Vector<X86Assembler::JmpSrc> bucketsOfFail;
1728
1729     // Check eax is an object of the right StructureID.
1730     m_jit.testl_i32r(JSImmediate::TagMask, X86::eax);
1731     bucketsOfFail.append(m_jit.emitUnlinkedJne());
1732     m_jit.cmpl_i32m(reinterpret_cast<uint32_t>(structureID), OBJECT_OFFSET(JSCell, m_structureID), X86::eax);
1733     bucketsOfFail.append(m_jit.emitUnlinkedJne());
1734
1735     StructureID* currStructureID = structureID;
1736     RefPtr<StructureID>* chainEntries = chain->head();
1737     JSCell* protoObject = 0;
1738     for (unsigned i = 0; i<count; ++i) {
1739         protoObject = static_cast<JSCell*>(currStructureID->prototypeForLookup(exec));
1740         currStructureID = chainEntries[i].get();
1741
1742         // Check the prototype object's StructureID had not changed.
1743         StructureID** protoStructureIDAddress = &(protoObject->m_structureID);
1744         m_jit.cmpl_i32m(reinterpret_cast<uint32_t>(currStructureID), static_cast<void*>(protoStructureIDAddress));
1745         bucketsOfFail.append(m_jit.emitUnlinkedJne());
1746     }
1747     ASSERT(protoObject);
1748  
1749     OwnArrayPtr<JSValue*>* protoPropertyStorage = &static_cast<JSObject*>(protoObject)->m_propertyStorage;
1750     m_jit.movl_mr(static_cast<void*>(protoPropertyStorage), X86::edx);
1751     m_jit.movl_mr(cachedOffset * sizeof(JSValue*), X86::edx, X86::eax);
1752     m_jit.ret();
1753
1754     bucketsOfFail.append(m_jit.emitUnlinkedJmp());
1755
1756     void* code = m_jit.copy();
1757     ASSERT(code);
1758
1759     for (unsigned i = 0; i < bucketsOfFail.size(); ++i)
1760         X86Assembler::link(code, bucketsOfFail[i], reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
1761     m_codeBlock->structureIDAccessStubs.append(code);
1762     return code;
1763 }
1764
1765 void* CTI::privateCompilePutByIdReplace(StructureID* structureID, size_t cachedOffset)
1766 {
1767     // check eax is an object of the right StructureID.
1768     m_jit.testl_i32r(JSImmediate::TagMask, X86::eax);
1769     X86Assembler::JmpSrc failureCases1 = m_jit.emitUnlinkedJne();
1770     m_jit.cmpl_i32m(reinterpret_cast<uint32_t>(structureID), OBJECT_OFFSET(JSCell, m_structureID), X86::eax);
1771     X86Assembler::JmpSrc failureCases2 = m_jit.emitUnlinkedJne();
1772
1773     // checks out okay! - putDirectOffset
1774     m_jit.movl_mr(OBJECT_OFFSET(JSObject, m_propertyStorage), X86::eax, X86::eax);
1775     m_jit.movl_rm(X86::edx, cachedOffset * sizeof(JSValue*), X86::eax);
1776     m_jit.ret();
1777
1778     void* code = m_jit.copy();
1779     ASSERT(code);
1780     
1781     X86Assembler::link(code, failureCases1, reinterpret_cast<void*>(Machine::cti_op_put_by_id_fail));
1782     X86Assembler::link(code, failureCases2, reinterpret_cast<void*>(Machine::cti_op_put_by_id_fail));
1783
1784     m_codeBlock->structureIDAccessStubs.append(code);
1785     
1786     return code;
1787 }
1788
1789 void* CTI::privateArrayLengthTrampoline()
1790 {
1791     // Check eax is an array
1792     m_jit.testl_i32r(JSImmediate::TagMask, X86::eax);
1793     X86Assembler::JmpSrc failureCases1 = m_jit.emitUnlinkedJne();
1794     m_jit.cmpl_i32m(reinterpret_cast<unsigned>(m_machine->m_jsArrayVptr), X86::eax);
1795     X86Assembler::JmpSrc failureCases2 = m_jit.emitUnlinkedJne();
1796
1797     // Checks out okay! - get the length from the storage
1798     m_jit.movl_mr(OBJECT_OFFSET(JSArray, m_storage), X86::eax, X86::eax);
1799     m_jit.movl_mr(OBJECT_OFFSET(ArrayStorage, m_length), X86::eax, X86::eax);
1800
1801     m_jit.addl_rr(X86::eax, X86::eax);
1802     X86Assembler::JmpSrc failureCases3 = m_jit.emitUnlinkedJo();
1803     m_jit.addl_i8r(1, X86::eax);
1804     
1805     m_jit.ret();
1806
1807     void* code = m_jit.copy();
1808     ASSERT(code);
1809
1810     X86Assembler::link(code, failureCases1, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
1811     X86Assembler::link(code, failureCases2, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
1812     X86Assembler::link(code, failureCases3, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
1813     
1814     return code;
1815 }
1816
1817 void* CTI::privateStringLengthTrampoline()
1818 {
1819     // Check eax is a string
1820     m_jit.testl_i32r(JSImmediate::TagMask, X86::eax);
1821     X86Assembler::JmpSrc failureCases1 = m_jit.emitUnlinkedJne();
1822     m_jit.cmpl_i32m(reinterpret_cast<unsigned>(m_machine->m_jsStringVptr), X86::eax);
1823     X86Assembler::JmpSrc failureCases2 = m_jit.emitUnlinkedJne();
1824
1825     // Checks out okay! - get the length from the Ustring.
1826     m_jit.movl_mr(OBJECT_OFFSET(JSString, m_value) + OBJECT_OFFSET(UString, m_rep), X86::eax, X86::eax);
1827     m_jit.movl_mr(OBJECT_OFFSET(UString::Rep, len), X86::eax, X86::eax);
1828
1829     m_jit.addl_rr(X86::eax, X86::eax);
1830     X86Assembler::JmpSrc failureCases3 = m_jit.emitUnlinkedJo();
1831     m_jit.addl_i8r(1, X86::eax);
1832     
1833     m_jit.ret();
1834
1835     void* code = m_jit.copy();
1836     ASSERT(code);
1837
1838     X86Assembler::link(code, failureCases1, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
1839     X86Assembler::link(code, failureCases2, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
1840     X86Assembler::link(code, failureCases3, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
1841
1842     return code;
1843 }
1844
1845 void CTI::emitGetVariableObjectRegister(X86Assembler::RegisterID variableObject, int index, X86Assembler::RegisterID dst)
1846 {
1847     m_jit.movl_mr(JSVariableObject::offsetOf_d(), variableObject, dst);
1848     m_jit.movl_mr(JSVariableObject::offsetOf_Data_registers(), dst, dst);
1849     m_jit.movl_mr(index * sizeof(Register), dst, dst);
1850 }
1851
1852 void CTI::emitPutVariableObjectRegister(X86Assembler::RegisterID src, X86Assembler::RegisterID variableObject, int index)
1853 {
1854     m_jit.movl_mr(JSVariableObject::offsetOf_d(), variableObject, variableObject);
1855     m_jit.movl_mr(JSVariableObject::offsetOf_Data_registers(), variableObject, variableObject);
1856     m_jit.movl_rm(src, index * sizeof(Register), variableObject);
1857 }
1858
1859 #if ENABLE(WREC)
1860
1861 void* CTI::compileRegExp(ExecState* exec, const UString& pattern, unsigned* numSubpatterns_ptr, const char** error_ptr, bool ignoreCase, bool multiline)
1862 {
1863     // TODO: better error messages
1864     if (pattern.size() > MaxPatternSize) {
1865         *error_ptr = "regular expression too large";
1866         return 0;
1867     }
1868
1869     X86Assembler jit(exec->machine()->jitCodeBuffer());
1870     WRECParser parser(pattern, ignoreCase, multiline, jit);
1871     
1872     jit.emitConvertToFastCall();
1873     // (0) Setup:
1874     //     Preserve regs & initialize outputRegister.
1875     jit.pushl_r(WRECGenerator::outputRegister);
1876     jit.pushl_r(WRECGenerator::currentValueRegister);
1877     // push pos onto the stack, both to preserve and as a parameter available to parseDisjunction
1878     jit.pushl_r(WRECGenerator::currentPositionRegister);
1879     // load output pointer
1880     jit.movl_mr(16
1881 #if COMPILER(MSVC)
1882                     + 3 * sizeof(void*)
1883 #endif
1884                     , X86::esp, WRECGenerator::outputRegister);
1885     
1886     // restart point on match fail.
1887     WRECGenerator::JmpDst nextLabel = jit.label();
1888
1889     // (1) Parse Disjunction:
1890     
1891     //     Parsing the disjunction should fully consume the pattern.
1892     JmpSrcVector failures;
1893     parser.parseDisjunction(failures);
1894     if (parser.isEndOfPattern()) {
1895         parser.m_err = WRECParser::Error_malformedPattern;
1896     }
1897     if (parser.m_err) {
1898         // TODO: better error messages
1899         *error_ptr = "TODO: better error messages";
1900         return 0;
1901     }
1902
1903     // (2) Success:
1904     //     Set return value & pop registers from the stack.
1905
1906     jit.testl_rr(WRECGenerator::outputRegister, WRECGenerator::outputRegister);
1907     WRECGenerator::JmpSrc noOutput = jit.emitUnlinkedJe();
1908
1909     jit.movl_rm(WRECGenerator::currentPositionRegister, 4, WRECGenerator::outputRegister);
1910     jit.popl_r(X86::eax);
1911     jit.movl_rm(X86::eax, WRECGenerator::outputRegister);
1912     jit.popl_r(WRECGenerator::currentValueRegister);
1913     jit.popl_r(WRECGenerator::outputRegister);
1914     jit.ret();
1915     
1916     jit.link(noOutput, jit.label());
1917     
1918     jit.popl_r(X86::eax);
1919     jit.movl_rm(X86::eax, WRECGenerator::outputRegister);
1920     jit.popl_r(WRECGenerator::currentValueRegister);
1921     jit.popl_r(WRECGenerator::outputRegister);
1922     jit.ret();
1923
1924     // (3) Failure:
1925     //     All fails link to here.  Progress the start point & if it is within scope, loop.
1926     //     Otherwise, return fail value.
1927     WRECGenerator::JmpDst here = jit.label();
1928     for (unsigned i = 0; i < failures.size(); ++i)
1929         jit.link(failures[i], here);
1930     failures.clear();
1931
1932     jit.movl_mr(X86::esp, WRECGenerator::currentPositionRegister);
1933     jit.addl_i8r(1, WRECGenerator::currentPositionRegister);
1934     jit.movl_rm(WRECGenerator::currentPositionRegister, X86::esp);
1935     jit.cmpl_rr(WRECGenerator::lengthRegister, WRECGenerator::currentPositionRegister);
1936     jit.link(jit.emitUnlinkedJle(), nextLabel);
1937
1938     jit.addl_i8r(4, X86::esp);
1939
1940     jit.movl_i32r(-1, X86::eax);
1941     jit.popl_r(WRECGenerator::currentValueRegister);
1942     jit.popl_r(WRECGenerator::outputRegister);
1943     jit.ret();
1944
1945     *numSubpatterns_ptr = parser.m_numSubpatterns;
1946
1947     void* code = jit.copy();
1948     ASSERT(code);
1949     return code;
1950 }
1951
1952 #endif // ENABLE(WREC)
1953
1954 } // namespace JSC
1955
1956 #endif // ENABLE(CTI)