fc3946b6dcf19e3abecf93557528ac043ebc580e
[WebKit.git] / JavaScriptCore / VM / CTI.cpp
1 /*
2  * Copyright (C) 2008 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "CTI.h"
28
29 #if ENABLE(CTI)
30
31 #include "CodeBlock.h"
32 #include "JSArray.h"
33 #include "Machine.h"
34 #include "wrec/WREC.h"
35
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(void* value, unsigned name)
153 {
154     m_jit.movl_i32m(reinterpret_cast<intptr_t>(value), name * sizeof(void*), X86::esp);
155 }
156
157 ALWAYS_INLINE void CTI::emitPutCTIParam(X86Assembler::RegisterID from, unsigned name)
158 {
159     m_jit.movl_rm(from, name * sizeof(void*), X86::esp);
160 }
161
162 ALWAYS_INLINE void CTI::emitGetCTIParam(unsigned name, X86Assembler::RegisterID to)
163 {
164     m_jit.movl_mr(name * sizeof(void*), X86::esp, to);
165 }
166
167 ALWAYS_INLINE void CTI::emitPutToCallFrameHeader(X86Assembler::RegisterID from, RegisterFile::CallFrameHeaderEntry entry)
168 {
169     m_jit.movl_rm(from, -((m_codeBlock->numLocals + RegisterFile::CallFrameHeaderSize) - entry) * sizeof(Register), X86::edi);
170 }
171
172 ALWAYS_INLINE void CTI::emitGetFromCallFrameHeader(RegisterFile::CallFrameHeaderEntry entry, X86Assembler::RegisterID to)
173 {
174     m_jit.movl_mr(-((m_codeBlock->numLocals + RegisterFile::CallFrameHeaderSize) - entry) * sizeof(Register), X86::edi, to);
175 }
176
177 ALWAYS_INLINE void CTI::emitPutResult(unsigned dst, X86Assembler::RegisterID from)
178 {
179     m_jit.movl_rm(from, dst * sizeof(Register), X86::edi);
180     // FIXME: #ifndef NDEBUG, Write the correct m_type to the register.
181 }
182
183 ALWAYS_INLINE void CTI::emitInitialiseRegister(unsigned dst)
184 {
185     m_jit.movl_i32m(reinterpret_cast<unsigned>(jsUndefined()), dst * sizeof(Register), X86::edi);
186     // FIXME: #ifndef NDEBUG, Write the correct m_type to the register.
187 }
188
189 #if ENABLE(SAMPLING_TOOL)
190 unsigned inCalledCode = 0;
191 #endif
192
193 void ctiSetReturnAddress(void** where, void* what)
194 {
195     *where = what;
196 }
197
198 void ctiRepatchCallByReturnAddress(void* where, void* what)
199 {
200     (static_cast<void**>(where))[-1] = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(what) - reinterpret_cast<uintptr_t>(where));
201 }
202
203 #ifdef NDEBUG
204
205 ALWAYS_INLINE void CTI::emitDebugExceptionCheck()
206 {
207 }
208
209 #else
210
211 ALWAYS_INLINE void CTI::emitDebugExceptionCheck()
212 {
213     emitGetCTIParam(CTI_ARGS_exec, X86::ecx);
214     m_jit.cmpl_i32m(0, OBJECT_OFFSET(ExecState, m_exception), X86::ecx);
215     X86Assembler::JmpSrc noException = m_jit.emitUnlinkedJe();
216     m_jit.emitInt3();
217     m_jit.link(noException, m_jit.label());
218 }
219
220 void CTI::printOpcodeOperandTypes(unsigned src1, unsigned src2)
221 {
222     char which1 = '*';
223     if (src1 < m_codeBlock->constantRegisters.size()) {
224         JSValue* js = m_codeBlock->constantRegisters[src1].jsValue(m_exec);
225         which1 = 
226             JSImmediate::isImmediate(js) ?
227                 (JSImmediate::isNumber(js) ? 'i' :
228                 JSImmediate::isBoolean(js) ? 'b' :
229                 js->isUndefined() ? 'u' :
230                 js->isNull() ? 'n' : '?')
231                 :
232             (js->isString() ? 's' :
233             js->isObject() ? 'o' :
234             'k');
235     }
236     char which2 = '*';
237     if (src2 < m_codeBlock->constantRegisters.size()) {
238         JSValue* js = m_codeBlock->constantRegisters[src2].jsValue(m_exec);
239         which2 = 
240             JSImmediate::isImmediate(js) ?
241                 (JSImmediate::isNumber(js) ? 'i' :
242                 JSImmediate::isBoolean(js) ? 'b' :
243                 js->isUndefined() ? 'u' :
244                 js->isNull() ? 'n' : '?')
245                 :
246             (js->isString() ? 's' :
247             js->isObject() ? 'o' :
248             'k');
249     }
250     if ((which1 != '*') | (which2 != '*'))
251         fprintf(stderr, "Types %c %c\n", which1, which2);
252 }
253
254 #endif
255
256 ALWAYS_INLINE X86Assembler::JmpSrc CTI::emitCall(unsigned opcodeIndex, CTIHelper_j helper)
257 {
258 #if ENABLE(SAMPLING_TOOL)
259     m_jit.movl_i32m(1, &inCalledCode);
260 #endif
261     X86Assembler::JmpSrc call = m_jit.emitCall();
262     m_calls.append(CallRecord(call, helper, opcodeIndex));
263     emitDebugExceptionCheck();
264 #if ENABLE(SAMPLING_TOOL)
265     m_jit.movl_i32m(0, &inCalledCode);
266 #endif
267
268     return call;
269 }
270
271 ALWAYS_INLINE X86Assembler::JmpSrc CTI::emitCall(unsigned opcodeIndex, CTIHelper_p helper)
272 {
273 #if ENABLE(SAMPLING_TOOL)
274     m_jit.movl_i32m(1, &inCalledCode);
275 #endif
276     X86Assembler::JmpSrc call = m_jit.emitCall();
277     m_calls.append(CallRecord(call, helper, opcodeIndex));
278     emitDebugExceptionCheck();
279 #if ENABLE(SAMPLING_TOOL)
280     m_jit.movl_i32m(0, &inCalledCode);
281 #endif
282
283     return call;
284 }
285
286 ALWAYS_INLINE X86Assembler::JmpSrc CTI::emitCall(unsigned opcodeIndex, CTIHelper_b helper)
287 {
288 #if ENABLE(SAMPLING_TOOL)
289     m_jit.movl_i32m(1, &inCalledCode);
290 #endif
291     X86Assembler::JmpSrc call = m_jit.emitCall();
292     m_calls.append(CallRecord(call, helper, opcodeIndex));
293     emitDebugExceptionCheck();
294 #if ENABLE(SAMPLING_TOOL)
295     m_jit.movl_i32m(0, &inCalledCode);
296 #endif
297
298     return call;
299 }
300
301 ALWAYS_INLINE X86Assembler::JmpSrc CTI::emitCall(unsigned opcodeIndex, CTIHelper_v helper)
302 {
303 #if ENABLE(SAMPLING_TOOL)
304     m_jit.movl_i32m(1, &inCalledCode);
305 #endif
306     X86Assembler::JmpSrc call = m_jit.emitCall();
307     m_calls.append(CallRecord(call, helper, opcodeIndex));
308     emitDebugExceptionCheck();
309 #if ENABLE(SAMPLING_TOOL)
310     m_jit.movl_i32m(0, &inCalledCode);
311 #endif
312
313     return call;
314 }
315
316 ALWAYS_INLINE X86Assembler::JmpSrc CTI::emitCall(unsigned opcodeIndex, CTIHelper_s helper)
317 {
318 #if ENABLE(SAMPLING_TOOL)
319     m_jit.movl_i32m(1, &inCalledCode);
320 #endif
321     X86Assembler::JmpSrc call = m_jit.emitCall();
322     m_calls.append(CallRecord(call, helper, opcodeIndex));
323     emitDebugExceptionCheck();
324 #if ENABLE(SAMPLING_TOOL)
325     m_jit.movl_i32m(0, &inCalledCode);
326 #endif
327
328     return call;
329 }
330
331 ALWAYS_INLINE void CTI::emitJumpSlowCaseIfNotJSCell(X86Assembler::RegisterID reg, unsigned opcodeIndex)
332 {
333     m_jit.testl_i32r(JSImmediate::TagMask, reg);
334     m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), opcodeIndex));
335 }
336
337 ALWAYS_INLINE void CTI::emitJumpSlowCaseIfNotImmNum(X86Assembler::RegisterID reg, unsigned opcodeIndex)
338 {
339     m_jit.testl_i32r(JSImmediate::TagBitTypeInteger, reg);
340     m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJe(), opcodeIndex));
341 }
342
343 ALWAYS_INLINE void CTI::emitJumpSlowCaseIfNotImmNums(X86Assembler::RegisterID reg1, X86Assembler::RegisterID reg2, unsigned opcodeIndex)
344 {
345     m_jit.movl_rr(reg1, X86::ecx);
346     m_jit.andl_rr(reg2, X86::ecx);
347     emitJumpSlowCaseIfNotImmNum(X86::ecx, opcodeIndex);
348 }
349
350 ALWAYS_INLINE unsigned CTI::getDeTaggedConstantImmediate(JSValue* imm)
351 {
352     ASSERT(JSImmediate::isNumber(imm));
353     return reinterpret_cast<unsigned>(imm) & ~JSImmediate::TagBitTypeInteger;
354 }
355
356 ALWAYS_INLINE void CTI::emitFastArithDeTagImmediate(X86Assembler::RegisterID reg)
357 {
358     // op_mod relies on this being a sub - setting zf if result is 0.
359     m_jit.subl_i8r(JSImmediate::TagBitTypeInteger, reg);
360 }
361
362 ALWAYS_INLINE void CTI::emitFastArithReTagImmediate(X86Assembler::RegisterID reg)
363 {
364     m_jit.addl_i8r(JSImmediate::TagBitTypeInteger, reg);
365 }
366
367 ALWAYS_INLINE void CTI::emitFastArithPotentiallyReTagImmediate(X86Assembler::RegisterID reg)
368 {
369     m_jit.orl_i32r(JSImmediate::TagBitTypeInteger, reg);
370 }
371
372 ALWAYS_INLINE void CTI::emitFastArithImmToInt(X86Assembler::RegisterID reg)
373 {
374     m_jit.sarl_i8r(1, reg);
375 }
376
377 ALWAYS_INLINE void CTI::emitFastArithIntToImmOrSlowCase(X86Assembler::RegisterID reg, unsigned opcodeIndex)
378 {
379     m_jit.addl_rr(reg, reg);
380     m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), opcodeIndex));
381     emitFastArithReTagImmediate(reg);
382 }
383
384 ALWAYS_INLINE void CTI::emitFastArithIntToImmNoCheck(X86Assembler::RegisterID reg)
385 {
386     m_jit.addl_rr(reg, reg);
387     emitFastArithReTagImmediate(reg);
388 }
389
390 ALWAYS_INLINE void CTI::emitTagAsBoolImmediate(X86Assembler::RegisterID reg)
391 {
392     m_jit.shl_i8r(JSImmediate::ExtendedPayloadShift, reg);
393     m_jit.orl_i32r(JSImmediate::FullTagTypeBool, reg);
394 }
395
396 CTI::CTI(Machine* machine, ExecState* exec, CodeBlock* codeBlock)
397     : m_jit(machine->jitCodeBuffer())
398     , m_machine(machine)
399     , m_exec(exec)
400     , m_codeBlock(codeBlock)
401     , m_labels(codeBlock ? codeBlock->instructions.size() : 0)
402     , m_structureStubCompilationInfo(codeBlock ? codeBlock->structureIDInstructions.size() : 0)
403 {
404 }
405
406 #define CTI_COMPILE_BINARY_OP(name) \
407     case name: { \
408         emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx); \
409         emitGetPutArg(instruction[i + 3].u.operand, 4, X86::ecx); \
410         emitCall(i, Machine::cti_##name); \
411         emitPutResult(instruction[i + 1].u.operand); \
412         i += 4; \
413         break; \
414     }
415
416 #define CTI_COMPILE_UNARY_OP(name) \
417     case name: { \
418         emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx); \
419         emitCall(i, Machine::cti_##name); \
420         emitPutResult(instruction[i + 1].u.operand); \
421         i += 3; \
422         break; \
423     }
424
425 #if ENABLE(SAMPLING_TOOL)
426 OpcodeID currentOpcodeID = static_cast<OpcodeID>(-1);
427 #endif
428
429 void CTI::compileOpCall(Instruction* instruction, unsigned i, CompileOpCallType type)
430 {
431     int dst = instruction[i + 1].u.operand;
432     int firstArg = instruction[i + 4].u.operand;
433     int argCount = instruction[i + 5].u.operand;
434
435     if (type == OpConstruct) {
436         emitPutArgConstant(reinterpret_cast<unsigned>(instruction + i), 16);
437         emitPutArgConstant(argCount, 12);
438         emitPutArgConstant(firstArg, 8);
439         emitGetPutArg(instruction[i + 3].u.operand, 4, X86::ecx);
440     } else {
441         emitPutArgConstant(reinterpret_cast<unsigned>(instruction + i), 16);
442         emitPutArgConstant(argCount, 12);
443         emitPutArgConstant(firstArg, 8);
444         // FIXME: should this be loaded dynamically off m_exec?
445         int thisVal = instruction[i + 3].u.operand;
446         if (thisVal == missingThisObjectMarker()) {
447             emitPutArgConstant(reinterpret_cast<unsigned>(m_exec->globalThisValue()), 4);
448         } else
449             emitGetPutArg(thisVal, 4, X86::ecx);
450     }
451
452     X86Assembler::JmpSrc wasEval;
453     if (type == OpCallEval) {
454         emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
455         emitCall(i, Machine::cti_op_call_eval);
456         m_jit.emitRestoreArgumentReference();
457
458         emitGetCTIParam(CTI_ARGS_r, X86::edi); // edi := r
459
460         m_jit.cmpl_i32r(reinterpret_cast<unsigned>(JSImmediate::impossibleValue()), X86::eax);
461         wasEval = m_jit.emitUnlinkedJne();
462     
463         // this reloads the first arg into ecx (checked just below).
464         emitGetArg(instruction[i + 2].u.operand, X86::ecx);
465     } else {
466         // this sets up the first arg, and explicitly leaves the value in ecx (checked just below).
467         emitGetArg(instruction[i + 2].u.operand, X86::ecx);
468         emitPutArg(X86::ecx, 0);
469     }
470
471     // initializeCallFrame!
472     m_jit.movl_i32m(reinterpret_cast<unsigned>(m_codeBlock), (firstArg - RegisterFile::CallFrameHeaderSize + RegisterFile::CallerCodeBlock) * sizeof(Register), X86::edi);
473     m_jit.movl_i32m(reinterpret_cast<unsigned>(instruction + i), (firstArg - RegisterFile::CallFrameHeaderSize + RegisterFile::ReturnVPC) * sizeof(Register), X86::edi);
474     emitGetCTIParam(CTI_ARGS_scopeChain, X86::edx);
475     m_jit.movl_rm(X86::edx, (firstArg - RegisterFile::CallFrameHeaderSize + RegisterFile::CallerScopeChain) * sizeof(Register), X86::edi);
476     m_jit.movl_rm(X86::edi, (firstArg - RegisterFile::CallFrameHeaderSize + RegisterFile::CallerRegisters) * sizeof(Register), X86::edi);
477     m_jit.movl_i32m(dst, (firstArg - RegisterFile::CallFrameHeaderSize + RegisterFile::ReturnValueRegister) * sizeof(Register), X86::edi);
478     m_jit.movl_i32m(firstArg, (firstArg - RegisterFile::CallFrameHeaderSize + RegisterFile::ArgumentStartRegister) * sizeof(Register), X86::edi);
479     m_jit.movl_i32m(argCount, (firstArg - RegisterFile::CallFrameHeaderSize + RegisterFile::ArgumentCount) * sizeof(Register), X86::edi);
480     m_jit.movl_rm(X86::ecx, (firstArg - RegisterFile::CallFrameHeaderSize + RegisterFile::Callee) * sizeof(Register), X86::edi);
481     m_jit.movl_i32m(0, (firstArg - RegisterFile::CallFrameHeaderSize + RegisterFile::OptionalCalleeActivation) * sizeof(Register), X86::edi);
482     // CTIReturnEIP (set in callee)
483
484     // Fast check for JS function.
485     m_jit.testl_i32r(JSImmediate::TagMask, X86::ecx);
486     X86Assembler::JmpSrc isNotObject = m_jit.emitUnlinkedJne();
487     m_jit.cmpl_i32m(reinterpret_cast<unsigned>(m_machine->m_jsFunctionVptr), X86::ecx);
488     X86Assembler::JmpSrc isJSFunction = m_jit.emitUnlinkedJe();
489     m_jit.link(isNotObject, m_jit.label());
490
491     // This handles host functions
492     emitCall(i, ((type == OpConstruct) ? Machine::cti_op_construct_NotJSConstruct : Machine::cti_op_call_NotJSFunction));
493     emitGetCTIParam(CTI_ARGS_r, X86::edi); // edi := r
494     
495     X86Assembler::JmpSrc wasNotJSFunction = m_jit.emitUnlinkedJmp();
496     m_jit.link(isJSFunction, m_jit.label());
497
498     // This handles JSFunctions
499     emitCall(i, ((type == OpConstruct) ? Machine::cti_op_construct_JSConstruct : Machine::cti_op_call_JSFunction));
500     // Check the ctiCode has been generated - if not, this is handled in a slow case.
501     m_jit.testl_rr(X86::eax, X86::eax);
502     m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJe(), i));
503     m_jit.call_r(X86::eax);
504     
505     // In the interpreter the following actions are performed by op_ret:
506     
507     // Store the scope chain - returned by op_ret in %edx (see below) - to ExecState::m_scopeChain and CTI_ARGS_scopeChain on the stack.
508     emitGetCTIParam(CTI_ARGS_exec, X86::ecx);
509     emitPutCTIParam(X86::edx, CTI_ARGS_scopeChain);
510     m_jit.movl_rm(X86::edx, OBJECT_OFFSET(ExecState, m_scopeChain), X86::ecx);
511     // Restore ExecState::m_callFrame.
512     m_jit.leal_mr(-(m_codeBlock->numLocals + RegisterFile::CallFrameHeaderSize) * sizeof(Register), X86::edi, X86::edx);
513     m_jit.movl_rm(X86::edx, OBJECT_OFFSET(ExecState, m_callFrame), X86::ecx);
514     // Restore CTI_ARGS_codeBlock.
515     emitPutCTIParam(m_codeBlock, CTI_ARGS_codeBlock);
516
517     X86Assembler::JmpDst end = m_jit.label();
518     m_jit.link(wasNotJSFunction, end);
519     if (type == OpCallEval)
520         m_jit.link(wasEval, end);
521
522     emitPutResult(dst);
523 }
524
525 void CTI::emitSlowScriptCheck(unsigned opcodeIndex)
526 {
527     m_jit.subl_i8r(1, X86::esi);
528     X86Assembler::JmpSrc skipTimeout = m_jit.emitUnlinkedJne();
529     emitCall(opcodeIndex, Machine::cti_timeout_check);
530
531     emitGetCTIParam(CTI_ARGS_exec, X86::ecx);
532     m_jit.movl_mr(OBJECT_OFFSET(ExecState, m_globalData), X86::ecx, X86::ecx);
533     m_jit.movl_mr(OBJECT_OFFSET(JSGlobalData, machine), X86::ecx, X86::ecx);
534     m_jit.movl_mr(OBJECT_OFFSET(Machine, m_ticksUntilNextTimeoutCheck), X86::ecx, X86::esi);
535     m_jit.link(skipTimeout, m_jit.label());
536 }
537
538 void CTI::privateCompileMainPass()
539 {
540     if (m_codeBlock->codeType == FunctionCode) {
541         for (int i = -m_codeBlock->numVars; i < 0; i++)
542             emitInitialiseRegister(i);
543     }
544     for (size_t i = 0; i < m_codeBlock->constantRegisters.size(); ++i)
545         emitInitialiseRegister(i);
546
547     Instruction* instruction = m_codeBlock->instructions.begin();
548     unsigned instructionCount = m_codeBlock->instructions.size();
549
550     unsigned structureIDInstructionIndex = 0;
551
552     for (unsigned i = 0; i < instructionCount; ) {
553         m_labels[i] = m_jit.label();
554
555 #if ENABLE(SAMPLING_TOOL)
556         m_jit.movl_i32m(m_machine->getOpcodeID(instruction[i].u.opcode), &currentOpcodeID);
557 #endif
558
559         ASSERT_WITH_MESSAGE(m_machine->isOpcode(instruction[i].u.opcode), "privateCompileMainPass gone bad @ %d", i);
560         m_jit.emitRestoreArgumentReference();
561         switch (m_machine->getOpcodeID(instruction[i].u.opcode)) {
562         case op_mov: {
563             unsigned src = instruction[i + 2].u.operand;
564             if (src < m_codeBlock->constantRegisters.size())
565                 m_jit.movl_i32r(reinterpret_cast<unsigned>(m_codeBlock->constantRegisters[src].jsValue(m_exec)), X86::edx);
566             else
567                 emitGetArg(src, X86::edx);
568             emitPutResult(instruction[i + 1].u.operand, X86::edx);
569             i += 3;
570             break;
571         }
572         case op_add: {
573             unsigned dst = instruction[i + 1].u.operand;
574             unsigned src1 = instruction[i + 2].u.operand;
575             unsigned src2 = instruction[i + 3].u.operand;
576             if (src2 < m_codeBlock->constantRegisters.size()) {
577                 JSValue* value = m_codeBlock->constantRegisters[src2].jsValue(m_exec);
578                 if (JSImmediate::isNumber(value)) {
579                     emitGetArg(src1, X86::eax);
580                     emitJumpSlowCaseIfNotImmNum(X86::eax, i);
581                     m_jit.addl_i32r(getDeTaggedConstantImmediate(value), X86::eax);
582                     m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
583                     emitPutResult(dst);
584                     i += 4;
585                     break;
586                 }
587             } else if (!(src1 < m_codeBlock->constantRegisters.size())) {
588                 emitGetArg(src1, X86::eax);
589                 emitGetArg(src2, X86::edx);
590                 emitJumpSlowCaseIfNotImmNums(X86::eax, X86::edx, i);
591                 emitFastArithDeTagImmediate(X86::eax);
592                 m_jit.addl_rr(X86::edx, X86::eax);
593                 m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
594                 emitPutResult(dst);
595                 i += 4;
596                 break;
597             }
598             emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
599             emitGetPutArg(instruction[i + 3].u.operand, 4, X86::ecx);
600             emitCall(i, Machine::cti_op_add);
601             emitPutResult(instruction[i + 1].u.operand);
602             i += 4;
603             break;
604         }
605         case op_end: {
606             if (m_codeBlock->needsFullScopeChain)
607                 emitCall(i, Machine::cti_op_end);
608             emitGetArg(instruction[i + 1].u.operand, X86::eax);
609 #if ENABLE(SAMPLING_TOOL)
610             m_jit.movl_i32m(-1, &currentOpcodeID);
611 #endif
612             m_jit.pushl_m(-((m_codeBlock->numLocals + RegisterFile::CallFrameHeaderSize) - RegisterFile::CTIReturnEIP) * sizeof(Register), X86::edi);
613             m_jit.ret();
614             i += 2;
615             break;
616         }
617         case op_jmp: {
618             unsigned target = instruction[i + 1].u.operand;
619             m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJmp(), i + 1 + target));
620             i += 2;
621             break;
622         }
623         case op_pre_inc: {
624             int srcDst = instruction[i + 1].u.operand;
625             emitGetArg(srcDst, X86::eax);
626             emitJumpSlowCaseIfNotImmNum(X86::eax, i);
627             m_jit.addl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), X86::eax);
628             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
629             emitPutResult(srcDst, X86::eax);
630             i += 2;
631             break;
632         }
633         case op_loop: {
634             emitSlowScriptCheck(i);
635
636             unsigned target = instruction[i + 1].u.operand;
637             m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJmp(), i + 1 + target));
638             i += 2;
639             break;
640         }
641         case op_loop_if_less: {
642             emitSlowScriptCheck(i);
643
644             unsigned target = instruction[i + 3].u.operand;
645             JSValue* src2imm = getConstantImmediateNumericArg(instruction[i + 2].u.operand);
646             if (src2imm) {
647                 emitGetArg(instruction[i + 1].u.operand, X86::edx);
648                 emitJumpSlowCaseIfNotImmNum(X86::edx, i);
649                 m_jit.cmpl_i32r(reinterpret_cast<unsigned>(src2imm), X86::edx);
650                 m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJl(), i + 3 + target));
651             } else {
652                 emitGetArg(instruction[i + 1].u.operand, X86::eax);
653                 emitGetArg(instruction[i + 2].u.operand, X86::edx);
654                 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
655                 emitJumpSlowCaseIfNotImmNum(X86::edx, i);
656                 m_jit.cmpl_rr(X86::edx, X86::eax);
657                 m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJl(), i + 3 + target));
658             }
659             i += 4;
660             break;
661         }
662         case op_loop_if_lesseq: {
663             emitSlowScriptCheck(i);
664
665             unsigned target = instruction[i + 3].u.operand;
666             JSValue* src2imm = getConstantImmediateNumericArg(instruction[i + 2].u.operand);
667             if (src2imm) {
668                 emitGetArg(instruction[i + 1].u.operand, X86::edx);
669                 emitJumpSlowCaseIfNotImmNum(X86::edx, i);
670                 m_jit.cmpl_i32r(reinterpret_cast<unsigned>(src2imm), X86::edx);
671                 m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJle(), i + 3 + target));
672             } else {
673                 emitGetArg(instruction[i + 1].u.operand, X86::eax);
674                 emitGetArg(instruction[i + 2].u.operand, X86::edx);
675                 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
676                 emitJumpSlowCaseIfNotImmNum(X86::edx, i);
677                 m_jit.cmpl_rr(X86::edx, X86::eax);
678                 m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJle(), i + 3 + target));
679             }
680             i += 4;
681             break;
682         }
683         case op_new_object: {
684             emitCall(i, Machine::cti_op_new_object);
685             emitPutResult(instruction[i + 1].u.operand);
686             i += 2;
687             break;
688         }
689         case op_put_by_id: {
690             // In order to be able to repatch both the StructureID, and the object offset, we store one pointer,
691             // to just after the arguments have been loaded into registers 'hotPathBegin', and we generate code
692             // such that the StructureID & offset are always at the same distance from this.
693
694             emitGetArg(instruction[i + 1].u.operand, X86::eax);
695             emitGetArg(instruction[i + 3].u.operand, X86::edx);
696
697             ASSERT(m_codeBlock->structureIDInstructions[structureIDInstructionIndex].opcodeIndex == i);
698             X86Assembler::JmpDst hotPathBegin = m_jit.label();
699             m_structureStubCompilationInfo[structureIDInstructionIndex].hotPathBegin = hotPathBegin;
700             ++structureIDInstructionIndex;
701
702             // Jump to a slow case if either the base object is an immediate, or if the StructureID does not match.
703             emitJumpSlowCaseIfNotJSCell(X86::eax, i);
704             // It is important that the following instruction plants a 32bit immediate, in order that it can be patched over.
705             m_jit.cmpl_i32m(repatchGetByIdDefaultStructureID, OBJECT_OFFSET(JSCell, m_structureID), X86::eax);
706             ASSERT(X86Assembler::getDifferenceBetweenLabels(hotPathBegin, m_jit.label()) == repatchOffsetPutByIdStructureID);
707             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
708
709             // Plant a load from a bogus ofset in the object's property map; we will patch this later, if it is to be used.
710             m_jit.movl_mr(OBJECT_OFFSET(JSObject, m_propertyStorage), X86::eax, X86::eax);
711             m_jit.movl_rm(X86::edx, repatchGetByIdDefaultOffset, X86::eax);
712             ASSERT(X86Assembler::getDifferenceBetweenLabels(hotPathBegin, m_jit.label()) == repatchOffsetPutByIdPropertyMapOffset);
713
714             i += 8;
715             break;
716         }
717         case op_get_by_id: {
718             // As for put_by_id, get_by_id requires the offset of the StructureID and the offset of the access to be repatched.
719             // Additionally, for get_by_id we need repatch the offset of the branch to the slow case (we repatch this to jump
720             // to array-length / prototype access tranpolines, and finally we also the the property-map access offset as a label
721             // to jump back to if one of these trampolies finds a match.
722
723             emitGetArg(instruction[i + 2].u.operand, X86::eax);
724
725             ASSERT(m_codeBlock->structureIDInstructions[structureIDInstructionIndex].opcodeIndex == i);
726
727             X86Assembler::JmpDst hotPathBegin = m_jit.label();
728             m_structureStubCompilationInfo[structureIDInstructionIndex].hotPathBegin = hotPathBegin;
729             ++structureIDInstructionIndex;
730
731             emitJumpSlowCaseIfNotJSCell(X86::eax, i);
732             m_jit.cmpl_i32m(repatchGetByIdDefaultStructureID, OBJECT_OFFSET(JSCell, m_structureID), X86::eax);
733             ASSERT(X86Assembler::getDifferenceBetweenLabels(hotPathBegin, m_jit.label()) == repatchOffsetGetByIdStructureID);
734             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
735             ASSERT(X86Assembler::getDifferenceBetweenLabels(hotPathBegin, m_jit.label()) == repatchOffsetGetByIdBranchToSlowCase);
736
737             m_jit.movl_mr(OBJECT_OFFSET(JSObject, m_propertyStorage), X86::eax, X86::eax);
738             m_jit.movl_mr(repatchGetByIdDefaultOffset, X86::eax, X86::ecx);
739             ASSERT(X86Assembler::getDifferenceBetweenLabels(hotPathBegin, m_jit.label()) == repatchOffsetGetByIdPropertyMapOffset);
740             emitPutResult(instruction[i + 1].u.operand, X86::ecx);
741
742             i += 8;
743             break;
744         }
745         case op_instanceof: {
746             emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
747             emitGetPutArg(instruction[i + 3].u.operand, 4, X86::ecx);
748             emitGetPutArg(instruction[i + 4].u.operand, 8, X86::ecx);
749             emitCall(i, Machine::cti_op_instanceof);
750             emitPutResult(instruction[i + 1].u.operand);
751             i += 5;
752             break;
753         }
754         case op_del_by_id: {
755             emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
756             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 3].u.operand]);
757             emitPutArgConstant(reinterpret_cast<unsigned>(ident), 4);
758             emitCall(i, Machine::cti_op_del_by_id);
759             emitPutResult(instruction[i + 1].u.operand);
760             i += 4;
761             break;
762         }
763         case op_mul: {
764             unsigned dst = instruction[i + 1].u.operand;
765             unsigned src1 = instruction[i + 2].u.operand;
766             unsigned src2 = instruction[i + 3].u.operand;
767             if (src1 < m_codeBlock->constantRegisters.size() || src2 < m_codeBlock->constantRegisters.size()) {
768                 unsigned constant = src1;
769                 unsigned nonconstant = src2;
770                 if (!(src1 < m_codeBlock->constantRegisters.size())) {
771                     constant = src2;
772                     nonconstant = src1;
773                 }
774                 JSValue* value = m_codeBlock->constantRegisters[constant].jsValue(m_exec);
775                 if (JSImmediate::isNumber(value)) {
776                     emitGetArg(nonconstant, X86::eax);
777                     emitJumpSlowCaseIfNotImmNum(X86::eax, i);
778                     emitFastArithImmToInt(X86::eax);
779                     m_jit.imull_i32r( X86::eax, getDeTaggedConstantImmediate(value), X86::eax);
780                     m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
781                     emitFastArithPotentiallyReTagImmediate(X86::eax);
782                     emitPutResult(dst);
783                     i += 4;
784                     break;
785                 }
786             }
787
788             emitGetArg(src1, X86::eax);
789             emitGetArg(src2, X86::edx);
790             emitJumpSlowCaseIfNotImmNums(X86::eax, X86::edx, i);
791             emitFastArithDeTagImmediate(X86::eax);
792             emitFastArithImmToInt(X86::edx);
793             m_jit.imull_rr(X86::edx, X86::eax);
794             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
795             emitFastArithPotentiallyReTagImmediate(X86::eax);
796             emitPutResult(dst);
797             i += 4;
798             break;
799         }
800         case op_new_func: {
801             FuncDeclNode* func = (m_codeBlock->functions[instruction[i + 2].u.operand]).get();
802             emitPutArgConstant(reinterpret_cast<unsigned>(func), 0);
803             emitCall(i, Machine::cti_op_new_func);
804             emitPutResult(instruction[i + 1].u.operand);
805             i += 3;
806             break;
807         }
808         case op_call: {
809             compileOpCall(instruction, i);
810             i += 6;
811             break;
812         }
813         case op_get_global_var: {
814             JSVariableObject* globalObject = static_cast<JSVariableObject*>(instruction[i + 2].u.jsCell);
815             m_jit.movl_i32r(reinterpret_cast<unsigned>(globalObject), X86::eax);
816             emitGetVariableObjectRegister(X86::eax, instruction[i + 3].u.operand, X86::eax);
817             emitPutResult(instruction[i + 1].u.operand, X86::eax);
818             i += 4;
819             break;
820         }
821         case op_put_global_var: {
822             JSVariableObject* globalObject = static_cast<JSVariableObject*>(instruction[i + 1].u.jsCell);
823             m_jit.movl_i32r(reinterpret_cast<unsigned>(globalObject), X86::eax);
824             emitGetArg(instruction[i + 3].u.operand, X86::edx);
825             emitPutVariableObjectRegister(X86::edx, X86::eax, instruction[i + 2].u.operand);
826             i += 4;
827             break;
828         }
829         case op_get_scoped_var: {
830             int skip = instruction[i + 3].u.operand + m_codeBlock->needsFullScopeChain;
831
832             emitGetCTIParam(CTI_ARGS_scopeChain, X86::eax);
833             while (skip--)
834                 m_jit.movl_mr(OBJECT_OFFSET(ScopeChainNode, next), X86::eax, X86::eax);
835
836             m_jit.movl_mr(OBJECT_OFFSET(ScopeChainNode, object), X86::eax, X86::eax);
837             emitGetVariableObjectRegister(X86::eax, instruction[i + 2].u.operand, X86::eax);
838             emitPutResult(instruction[i + 1].u.operand);
839             i += 4;
840             break;
841         }
842         case op_put_scoped_var: {
843             int skip = instruction[i + 2].u.operand + m_codeBlock->needsFullScopeChain;
844
845             emitGetCTIParam(CTI_ARGS_scopeChain, X86::edx);
846             emitGetArg(instruction[i + 3].u.operand, X86::eax);
847             while (skip--)
848                 m_jit.movl_mr(OBJECT_OFFSET(ScopeChainNode, next), X86::edx, X86::edx);
849
850             m_jit.movl_mr(OBJECT_OFFSET(ScopeChainNode, object), X86::edx, X86::edx);
851             emitPutVariableObjectRegister(X86::eax, X86::edx, instruction[i + 1].u.operand);
852             i += 4;
853             break;
854         }
855         case op_ret: {
856             // Check for an activation - if there is one, jump to the hook below.
857             m_jit.cmpl_i32m(0, -(m_codeBlock->numLocals + RegisterFile::CallFrameHeaderSize - RegisterFile::OptionalCalleeActivation) * sizeof(Register), X86::edi);
858             X86Assembler::JmpSrc activation = m_jit.emitUnlinkedJne();
859             X86Assembler::JmpDst activated = m_jit.label();
860
861             // Check for a profiler - if there is one, jump to the hook below.
862             emitGetCTIParam(CTI_ARGS_profilerReference, X86::eax);
863             m_jit.cmpl_i32m(0, X86::eax);
864             X86Assembler::JmpSrc profile = m_jit.emitUnlinkedJne();
865             X86Assembler::JmpDst profiled = m_jit.label();
866
867             // We could JIT generate the deref, only calling out to C when the refcount hits zero.
868             if (m_codeBlock->needsFullScopeChain)
869                 emitCall(i, Machine::cti_op_ret_scopeChain);
870
871             // Return the result in %eax, and the caller scope chain in %edx (this is read from the callee call frame,
872             // but is only assigned to ExecState::m_scopeChain if returning to a JSFunction).
873             emitGetArg(instruction[i + 1].u.operand, X86::eax);
874             m_jit.movl_mr(-(m_codeBlock->numLocals + RegisterFile::CallFrameHeaderSize - RegisterFile::CallerScopeChain) * sizeof(Register), X86::edi, X86::edx);
875             // Restore the machine return addess from the callframe, roll the callframe back to the caller callframe,
876             // and preserve a copy of r on the stack at CTI_ARGS_r. 
877             m_jit.movl_mr(-(m_codeBlock->numLocals + RegisterFile::CallFrameHeaderSize - RegisterFile::CTIReturnEIP) * sizeof(Register), X86::edi, X86::ecx);
878             m_jit.movl_mr(-(m_codeBlock->numLocals + RegisterFile::CallFrameHeaderSize - RegisterFile::CallerRegisters) * sizeof(Register), X86::edi, X86::edi);
879             emitPutCTIParam(X86::edi, CTI_ARGS_r);
880
881             m_jit.pushl_r(X86::ecx);
882             m_jit.ret();
883
884             // Activation hook
885             m_jit.link(activation, m_jit.label());
886             emitCall(i, Machine::cti_op_ret_activation);
887             m_jit.link(m_jit.emitUnlinkedJmp(), activated);
888
889             // Profiling hook
890             m_jit.link(profile, m_jit.label());
891             emitCall(i, Machine::cti_op_ret_profiler);
892             m_jit.link(m_jit.emitUnlinkedJmp(), profiled);
893
894             i += 2;
895             break;
896         }
897         case op_new_array: {
898             m_jit.leal_mr(sizeof(Register) * instruction[i + 2].u.operand, X86::edi, X86::edx);
899             emitPutArg(X86::edx, 0);
900             emitPutArgConstant(instruction[i + 3].u.operand, 4);
901             emitCall(i, Machine::cti_op_new_array);
902             emitPutResult(instruction[i + 1].u.operand);
903             i += 4;
904             break;
905         }
906         case op_resolve: {
907             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
908             emitPutArgConstant(reinterpret_cast<unsigned>(ident), 0);
909             emitCall(i, Machine::cti_op_resolve);
910             emitPutResult(instruction[i + 1].u.operand);
911             i += 3;
912             break;
913         }
914         case op_construct: {
915             compileOpCall(instruction, i, OpConstruct);
916             i += 6;
917             break;
918         }
919         case op_construct_verify: {
920             emitGetArg(instruction[i + 1].u.operand, X86::eax);
921             
922             m_jit.testl_i32r(JSImmediate::TagMask, X86::eax);
923             X86Assembler::JmpSrc isImmediate = m_jit.emitUnlinkedJne();
924             m_jit.movl_mr(OBJECT_OFFSET(JSCell, m_structureID), X86::eax, X86::ecx);
925             m_jit.cmpl_i32m(ObjectType, OBJECT_OFFSET(StructureID, m_typeInfo) + OBJECT_OFFSET(TypeInfo, m_type), X86::ecx);
926             X86Assembler::JmpSrc isObject = m_jit.emitUnlinkedJe();
927
928             m_jit.link(isImmediate, m_jit.label());
929             emitGetArg(instruction[i + 2].u.operand, X86::ecx);
930             emitPutResult(instruction[i + 1].u.operand, X86::ecx);
931             m_jit.link(isObject, m_jit.label());
932
933             i += 3;
934             break;
935         }
936         case op_get_by_val: {
937             emitGetArg(instruction[i + 2].u.operand, X86::eax);
938             emitGetArg(instruction[i + 3].u.operand, X86::edx);
939             emitJumpSlowCaseIfNotImmNum(X86::edx, i);
940             emitFastArithImmToInt(X86::edx);
941             m_jit.testl_i32r(JSImmediate::TagMask, X86::eax);
942             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
943             m_jit.cmpl_i32m(reinterpret_cast<unsigned>(m_machine->m_jsArrayVptr), X86::eax);
944             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
945
946             // This is an array; get the m_storage pointer into ecx, then check if the index is below the fast cutoff
947             m_jit.movl_mr(OBJECT_OFFSET(JSArray, m_storage), X86::eax, X86::ecx);
948             m_jit.cmpl_rm(X86::edx, OBJECT_OFFSET(JSArray, m_fastAccessCutoff), X86::eax);
949             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJbe(), i));
950
951             // Get the value from the vector
952             m_jit.movl_mr(OBJECT_OFFSET(ArrayStorage, m_vector[0]), X86::ecx, X86::edx, sizeof(JSValue*), X86::eax);
953             emitPutResult(instruction[i + 1].u.operand);
954             i += 4;
955             break;
956         }
957         case op_resolve_func: {
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_func);
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_sub: {
968             emitGetArg(instruction[i + 2].u.operand, X86::eax);
969             emitGetArg(instruction[i + 3].u.operand, X86::edx);
970             emitJumpSlowCaseIfNotImmNums(X86::eax, X86::edx, i);
971             m_jit.subl_rr(X86::edx, X86::eax);
972             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
973             emitFastArithReTagImmediate(X86::eax);
974             emitPutResult(instruction[i + 1].u.operand);
975             i += 4;
976             break;
977         }
978         case op_put_by_val: {
979             emitGetArg(instruction[i + 1].u.operand, X86::eax);
980             emitGetArg(instruction[i + 2].u.operand, X86::edx);
981             emitJumpSlowCaseIfNotImmNum(X86::edx, i);
982             emitFastArithImmToInt(X86::edx);
983             m_jit.testl_i32r(JSImmediate::TagMask, X86::eax);
984             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
985             m_jit.cmpl_i32m(reinterpret_cast<unsigned>(m_machine->m_jsArrayVptr), X86::eax);
986             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
987
988             // This is an array; get the m_storage pointer into ecx, then check if the index is below the fast cutoff
989             m_jit.movl_mr(OBJECT_OFFSET(JSArray, m_storage), X86::eax, X86::ecx);
990             m_jit.cmpl_rm(X86::edx, OBJECT_OFFSET(JSArray, m_fastAccessCutoff), X86::eax);
991             X86Assembler::JmpSrc inFastVector = m_jit.emitUnlinkedJa();
992             // No; oh well, check if the access if within the vector - if so, we may still be okay.
993             m_jit.cmpl_rm(X86::edx, OBJECT_OFFSET(ArrayStorage, m_vectorLength), X86::ecx);
994             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJbe(), i));
995
996             // This is a write to the slow part of the vector; first, we have to check if this would be the first write to this location.
997             // FIXME: should be able to handle initial write to array; increment the the number of items in the array, and potentially update fast access cutoff. 
998             m_jit.cmpl_i8m(0, OBJECT_OFFSET(ArrayStorage, m_vector[0]), X86::ecx, X86::edx, sizeof(JSValue*));
999             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJe(), i));
1000
1001             // All good - put the value into the array.
1002             m_jit.link(inFastVector, m_jit.label());
1003             emitGetArg(instruction[i + 3].u.operand, X86::eax);
1004             m_jit.movl_rm(X86::eax, OBJECT_OFFSET(ArrayStorage, m_vector[0]), X86::ecx, X86::edx, sizeof(JSValue*));
1005             i += 4;
1006             break;
1007         }
1008         CTI_COMPILE_BINARY_OP(op_lesseq)
1009         case op_loop_if_true: {
1010             emitSlowScriptCheck(i);
1011
1012             unsigned target = instruction[i + 2].u.operand;
1013             emitGetArg(instruction[i + 1].u.operand, X86::eax);
1014
1015             m_jit.cmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::zeroImmediate()), X86::eax);
1016             X86Assembler::JmpSrc isZero = m_jit.emitUnlinkedJe();
1017             m_jit.testl_i32r(JSImmediate::TagBitTypeInteger, X86::eax);
1018             m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJne(), i + 2 + target));
1019
1020             m_jit.cmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::trueImmediate()), X86::eax);
1021             m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJe(), i + 2 + target));
1022             m_jit.cmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::falseImmediate()), X86::eax);
1023             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
1024
1025             m_jit.link(isZero, m_jit.label());
1026             i += 3;
1027             break;
1028         };
1029         case op_resolve_base: {
1030             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
1031             emitPutArgConstant(reinterpret_cast<unsigned>(ident), 0);
1032             emitCall(i, Machine::cti_op_resolve_base);
1033             emitPutResult(instruction[i + 1].u.operand);
1034             i += 3;
1035             break;
1036         }
1037         case op_negate: {
1038             emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
1039             emitCall(i, Machine::cti_op_negate);
1040             emitPutResult(instruction[i + 1].u.operand);
1041             i += 3;
1042             break;
1043         }
1044         case op_resolve_skip: {
1045             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
1046             emitPutArgConstant(reinterpret_cast<unsigned>(ident), 0);
1047             emitPutArgConstant(instruction[i + 3].u.operand + m_codeBlock->needsFullScopeChain, 4);
1048             emitCall(i, Machine::cti_op_resolve_skip);
1049             emitPutResult(instruction[i + 1].u.operand);
1050             i += 4;
1051             break;
1052         }
1053         case op_resolve_global: {
1054             // Fast case
1055             unsigned globalObject = reinterpret_cast<unsigned>(instruction[i + 2].u.jsCell);
1056             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 3].u.operand]);
1057             void* structureIDAddr = reinterpret_cast<void*>(instruction + i + 4);
1058             void* offsetAddr = reinterpret_cast<void*>(instruction + i + 5);
1059
1060             // Check StructureID of global object
1061             m_jit.movl_i32r(globalObject, X86::eax);
1062             m_jit.movl_mr(structureIDAddr, X86::edx);
1063             m_jit.cmpl_rm(X86::edx, OBJECT_OFFSET(JSCell, m_structureID), X86::eax);
1064             X86Assembler::JmpSrc slowCase = m_jit.emitUnlinkedJne(); // StructureIDs don't match
1065             m_slowCases.append(SlowCaseEntry(slowCase, i));
1066
1067             // Load cached property
1068             m_jit.movl_mr(OBJECT_OFFSET(JSGlobalObject, m_propertyStorage), X86::eax, X86::eax);
1069             m_jit.movl_mr(offsetAddr, X86::edx);
1070             m_jit.movl_mr(0, X86::eax, X86::edx, sizeof(JSValue*), X86::eax);
1071             emitPutResult(instruction[i + 1].u.operand);
1072             X86Assembler::JmpSrc end = m_jit.emitUnlinkedJmp();
1073
1074             // Slow case
1075             m_jit.link(slowCase, m_jit.label());
1076             emitPutArgConstant(globalObject, 0);
1077             emitPutArgConstant(reinterpret_cast<unsigned>(ident), 4);
1078             emitPutArgConstant(reinterpret_cast<unsigned>(instruction + i), 8);
1079             emitCall(i, Machine::cti_op_resolve_global);
1080             emitPutResult(instruction[i + 1].u.operand);
1081             m_jit.link(end, m_jit.label());
1082             i += 6;
1083             ++structureIDInstructionIndex;
1084             break;
1085         }
1086         CTI_COMPILE_BINARY_OP(op_div)
1087         case op_pre_dec: {
1088             int srcDst = instruction[i + 1].u.operand;
1089             emitGetArg(srcDst, X86::eax);
1090             emitJumpSlowCaseIfNotImmNum(X86::eax, i);
1091             m_jit.subl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), X86::eax);
1092             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
1093             emitPutResult(srcDst, X86::eax);
1094             i += 2;
1095             break;
1096         }
1097         case op_jnless: {
1098             unsigned target = instruction[i + 3].u.operand;
1099             JSValue* src2imm = getConstantImmediateNumericArg(instruction[i + 2].u.operand);
1100             if (src2imm) {
1101                 emitGetArg(instruction[i + 1].u.operand, X86::edx);
1102                 emitJumpSlowCaseIfNotImmNum(X86::edx, i);
1103                 m_jit.cmpl_i32r(reinterpret_cast<unsigned>(src2imm), X86::edx);
1104                 m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJge(), i + 3 + target));
1105             } else {
1106                 emitGetArg(instruction[i + 1].u.operand, X86::eax);
1107                 emitGetArg(instruction[i + 2].u.operand, X86::edx);
1108                 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
1109                 emitJumpSlowCaseIfNotImmNum(X86::edx, i);
1110                 m_jit.cmpl_rr(X86::edx, X86::eax);
1111                 m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJge(), i + 3 + target));
1112             }
1113             i += 4;
1114             break;
1115         }
1116         case op_not: {
1117             emitGetArg(instruction[i + 2].u.operand, X86::eax);
1118             m_jit.xorl_i8r(JSImmediate::FullTagTypeBool, X86::eax);
1119             m_jit.testl_i32r(JSImmediate::FullTagTypeMask, X86::eax); // i8?
1120             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
1121             m_jit.xorl_i8r((JSImmediate::FullTagTypeBool | JSImmediate::ExtendedPayloadBitBoolValue), X86::eax);
1122             emitPutResult(instruction[i + 1].u.operand);
1123             i += 3;
1124             break;
1125         }
1126         case op_jfalse: {
1127             unsigned target = instruction[i + 2].u.operand;
1128             emitGetArg(instruction[i + 1].u.operand, X86::eax);
1129
1130             m_jit.cmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::zeroImmediate()), X86::eax);
1131             m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJe(), i + 2 + target));
1132             m_jit.testl_i32r(JSImmediate::TagBitTypeInteger, X86::eax);
1133             X86Assembler::JmpSrc isNonZero = m_jit.emitUnlinkedJne();
1134
1135             m_jit.cmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::falseImmediate()), X86::eax);
1136             m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJe(), i + 2 + target));
1137             m_jit.cmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::trueImmediate()), X86::eax);
1138             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
1139
1140             m_jit.link(isNonZero, m_jit.label());
1141             i += 3;
1142             break;
1143         };
1144         case op_post_inc: {
1145             int srcDst = instruction[i + 2].u.operand;
1146             emitGetArg(srcDst, X86::eax);
1147             m_jit.movl_rr(X86::eax, X86::edx);
1148             emitJumpSlowCaseIfNotImmNum(X86::eax, i);
1149             m_jit.addl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), X86::edx);
1150             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
1151             emitPutResult(srcDst, X86::edx);
1152             emitPutResult(instruction[i + 1].u.operand);
1153             i += 3;
1154             break;
1155         }
1156         case op_unexpected_load: {
1157             JSValue* v = m_codeBlock->unexpectedConstants[instruction[i + 2].u.operand];
1158             m_jit.movl_i32r(reinterpret_cast<unsigned>(v), X86::eax);
1159             emitPutResult(instruction[i + 1].u.operand);
1160             i += 3;
1161             break;
1162         }
1163         case op_jsr: {
1164             int retAddrDst = instruction[i + 1].u.operand;
1165             int target = instruction[i + 2].u.operand;
1166             m_jit.movl_i32m(0, sizeof(Register) * retAddrDst, X86::edi);
1167             X86Assembler::JmpDst addrPosition = m_jit.label();
1168             m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJmp(), i + 2 + target));
1169             X86Assembler::JmpDst sretTarget = m_jit.label();
1170             m_jsrSites.append(JSRInfo(addrPosition, sretTarget));
1171             i += 3;
1172             break;
1173         }
1174         case op_sret: {
1175             m_jit.jmp_m(sizeof(Register) * instruction[i + 1].u.operand, X86::edi);
1176             i += 2;
1177             break;
1178         }
1179         case op_eq: {
1180             emitGetArg(instruction[i + 2].u.operand, X86::eax);
1181             emitGetArg(instruction[i + 3].u.operand, X86::edx);
1182             emitJumpSlowCaseIfNotImmNums(X86::eax, X86::edx, i);
1183             m_jit.cmpl_rr(X86::edx, X86::eax);
1184             m_jit.sete_r(X86::eax);
1185             m_jit.movzbl_rr(X86::eax, X86::eax);
1186             emitTagAsBoolImmediate(X86::eax);
1187             emitPutResult(instruction[i + 1].u.operand);
1188             i += 4;
1189             break;
1190         }
1191         case op_lshift: {
1192             emitGetArg(instruction[i + 2].u.operand, X86::eax);
1193             emitGetArg(instruction[i + 3].u.operand, X86::ecx);
1194             emitJumpSlowCaseIfNotImmNum(X86::eax, i);
1195             emitJumpSlowCaseIfNotImmNum(X86::ecx, i);
1196             emitFastArithImmToInt(X86::eax);
1197             emitFastArithImmToInt(X86::ecx);
1198             m_jit.shll_CLr(X86::eax);
1199             emitFastArithIntToImmOrSlowCase(X86::eax, i);
1200             emitPutResult(instruction[i + 1].u.operand);
1201             i += 4;
1202             break;
1203         }
1204         case op_bitand: {
1205             unsigned src1 = instruction[i + 2].u.operand;
1206             unsigned src2 = instruction[i + 3].u.operand;
1207             unsigned dst = instruction[i + 1].u.operand;
1208             if (JSValue* value = getConstantImmediateNumericArg(src1)) {
1209                 emitGetArg(src2, X86::eax);
1210                 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
1211                 m_jit.andl_i32r(reinterpret_cast<unsigned>(value), X86::eax); // FIXME: make it more obvious this is relying on the format of JSImmediate
1212                 emitPutResult(dst);
1213             } else if (JSValue* value = getConstantImmediateNumericArg(src2)) {
1214                 emitGetArg(src1, X86::eax);
1215                 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
1216                 m_jit.andl_i32r(reinterpret_cast<unsigned>(value), X86::eax);
1217                 emitPutResult(dst);
1218             } else {
1219                 emitGetArg(src1, X86::eax);
1220                 emitGetArg(src2, X86::edx);
1221                 m_jit.andl_rr(X86::edx, X86::eax);
1222                 emitJumpSlowCaseIfNotImmNum(X86::eax, i);
1223                 emitPutResult(dst);
1224             }
1225             i += 4;
1226             break;
1227         }
1228         case op_rshift: {
1229             emitGetArg(instruction[i + 2].u.operand, X86::eax);
1230             emitGetArg(instruction[i + 3].u.operand, X86::ecx);
1231             emitJumpSlowCaseIfNotImmNum(X86::eax, i);
1232             emitJumpSlowCaseIfNotImmNum(X86::ecx, i);
1233             emitFastArithImmToInt(X86::ecx);
1234             m_jit.sarl_CLr(X86::eax);
1235             emitFastArithPotentiallyReTagImmediate(X86::eax);
1236             emitPutResult(instruction[i + 1].u.operand);
1237             i += 4;
1238             break;
1239         }
1240         case op_bitnot: {
1241             emitGetArg(instruction[i + 2].u.operand, X86::eax);
1242             emitJumpSlowCaseIfNotImmNum(X86::eax, i);
1243             m_jit.xorl_i8r(~JSImmediate::TagBitTypeInteger, X86::eax);
1244             emitPutResult(instruction[i + 1].u.operand);
1245             i += 3;
1246             break;
1247         }
1248         case op_resolve_with_base: {
1249             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 3].u.operand]);
1250             emitPutArgConstant(reinterpret_cast<unsigned>(ident), 0);
1251             emitCall(i, Machine::cti_op_resolve_with_base);
1252             emitPutResult(instruction[i + 1].u.operand);
1253             emitGetCTIParam(CTI_ARGS_2ndResult, X86::eax);
1254             emitPutResult(instruction[i + 2].u.operand);
1255             i += 4;
1256             break;
1257         }
1258         case op_new_func_exp: {
1259             FuncExprNode* func = (m_codeBlock->functionExpressions[instruction[i + 2].u.operand]).get();
1260             emitPutArgConstant(reinterpret_cast<unsigned>(func), 0);
1261             emitCall(i, Machine::cti_op_new_func_exp);
1262             emitPutResult(instruction[i + 1].u.operand);
1263             i += 3;
1264             break;
1265         }
1266         case op_mod: {
1267             emitGetArg(instruction[i + 2].u.operand, X86::eax);
1268             emitGetArg(instruction[i + 3].u.operand, X86::ecx);
1269             emitJumpSlowCaseIfNotImmNum(X86::eax, i);
1270             emitJumpSlowCaseIfNotImmNum(X86::ecx, i);
1271             emitFastArithDeTagImmediate(X86::eax);
1272             emitFastArithDeTagImmediate(X86::ecx);
1273             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJe(), i)); // This is checking if the last detag resulted in a value 0.
1274             m_jit.cdq();
1275             m_jit.idivl_r(X86::ecx);
1276             emitFastArithReTagImmediate(X86::edx);
1277             m_jit.movl_rr(X86::edx, X86::eax);
1278             emitPutResult(instruction[i + 1].u.operand);
1279             i += 4;
1280             break;
1281         }
1282         case op_jtrue: {
1283             unsigned target = instruction[i + 2].u.operand;
1284             emitGetArg(instruction[i + 1].u.operand, X86::eax);
1285
1286             m_jit.cmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::zeroImmediate()), X86::eax);
1287             X86Assembler::JmpSrc isZero = m_jit.emitUnlinkedJe();
1288             m_jit.testl_i32r(JSImmediate::TagBitTypeInteger, X86::eax);
1289             m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJne(), i + 2 + target));
1290
1291             m_jit.cmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::trueImmediate()), X86::eax);
1292             m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJe(), i + 2 + target));
1293             m_jit.cmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::falseImmediate()), X86::eax);
1294             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
1295
1296             m_jit.link(isZero, m_jit.label());
1297             i += 3;
1298             break;
1299         }
1300         CTI_COMPILE_BINARY_OP(op_less)
1301         CTI_COMPILE_BINARY_OP(op_neq)
1302         case op_post_dec: {
1303             int srcDst = instruction[i + 2].u.operand;
1304             emitGetArg(srcDst, X86::eax);
1305             m_jit.movl_rr(X86::eax, X86::edx);
1306             emitJumpSlowCaseIfNotImmNum(X86::eax, i);
1307             m_jit.subl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), X86::edx);
1308             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJo(), i));
1309             emitPutResult(srcDst, X86::edx);
1310             emitPutResult(instruction[i + 1].u.operand);
1311             i += 3;
1312             break;
1313         }
1314         CTI_COMPILE_BINARY_OP(op_urshift)
1315         case op_bitxor: {
1316             emitGetArg(instruction[i + 2].u.operand, X86::eax);
1317             emitGetArg(instruction[i + 3].u.operand, X86::edx);
1318             emitJumpSlowCaseIfNotImmNums(X86::eax, X86::edx, i);
1319             m_jit.xorl_rr(X86::edx, X86::eax);
1320             emitFastArithReTagImmediate(X86::eax);
1321             emitPutResult(instruction[i + 1].u.operand);
1322             i += 4;
1323             break;
1324         }
1325         case op_new_regexp: {
1326             RegExp* regExp = m_codeBlock->regexps[instruction[i + 2].u.operand].get();
1327             emitPutArgConstant(reinterpret_cast<unsigned>(regExp), 0);
1328             emitCall(i, Machine::cti_op_new_regexp);
1329             emitPutResult(instruction[i + 1].u.operand);
1330             i += 3;
1331             break;
1332         }
1333         case op_bitor: {
1334             emitGetArg(instruction[i + 2].u.operand, X86::eax);
1335             emitGetArg(instruction[i + 3].u.operand, X86::edx);
1336             emitJumpSlowCaseIfNotImmNums(X86::eax, X86::edx, i);
1337             m_jit.orl_rr(X86::edx, X86::eax);
1338             emitPutResult(instruction[i + 1].u.operand);
1339             i += 4;
1340             break;
1341         }
1342         case op_call_eval: {
1343             compileOpCall(instruction, i, OpCallEval);
1344             i += 6;
1345             break;
1346         }
1347         case op_throw: {
1348             emitGetPutArg(instruction[i + 1].u.operand, 0, X86::ecx);
1349             emitCall(i, Machine::cti_op_throw);
1350             m_jit.addl_i8r(0x24, X86::esp);
1351             m_jit.popl_r(X86::edi);
1352             m_jit.popl_r(X86::esi);
1353             m_jit.ret();
1354             i += 2;
1355             break;
1356         }
1357         case op_get_pnames: {
1358             emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
1359             emitCall(i, Machine::cti_op_get_pnames);
1360             emitPutResult(instruction[i + 1].u.operand);
1361             i += 3;
1362             break;
1363         }
1364         case op_next_pname: {
1365             emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
1366             unsigned target = instruction[i + 3].u.operand;
1367             emitCall(i, Machine::cti_op_next_pname);
1368             m_jit.testl_rr(X86::eax, X86::eax);
1369             X86Assembler::JmpSrc endOfIter = m_jit.emitUnlinkedJe();
1370             emitPutResult(instruction[i + 1].u.operand);
1371             m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJmp(), i + 3 + target));
1372             m_jit.link(endOfIter, m_jit.label());
1373             i += 4;
1374             break;
1375         }
1376         case op_push_scope: {
1377             emitGetPutArg(instruction[i + 1].u.operand, 0, X86::ecx);
1378             emitCall(i, Machine::cti_op_push_scope);
1379             i += 2;
1380             break;
1381         }
1382         case op_pop_scope: {
1383             emitCall(i, Machine::cti_op_pop_scope);
1384             i += 1;
1385             break;
1386         }
1387         CTI_COMPILE_UNARY_OP(op_typeof)
1388         CTI_COMPILE_UNARY_OP(op_is_undefined)
1389         CTI_COMPILE_UNARY_OP(op_is_boolean)
1390         CTI_COMPILE_UNARY_OP(op_is_number)
1391         CTI_COMPILE_UNARY_OP(op_is_string)
1392         CTI_COMPILE_UNARY_OP(op_is_object)
1393         CTI_COMPILE_UNARY_OP(op_is_function)
1394         CTI_COMPILE_BINARY_OP(op_nstricteq)
1395         case op_stricteq: {
1396             unsigned dst = instruction[i + 1].u.operand;
1397             unsigned src1 = instruction[i + 2].u.operand;
1398             unsigned src2 = instruction[i + 3].u.operand;
1399
1400             emitGetArg(src1, X86::eax);
1401             emitGetArg(src2, X86::edx);
1402
1403             m_jit.testl_i32r(JSImmediate::TagMask, X86::eax);
1404             X86Assembler::JmpSrc firstNotImmediate = m_jit.emitUnlinkedJe();
1405             m_jit.testl_i32r(JSImmediate::TagMask, X86::edx);
1406             X86Assembler::JmpSrc secondNotImmediate = m_jit.emitUnlinkedJe();
1407
1408             m_jit.cmpl_rr(X86::edx, X86::eax);
1409             m_jit.sete_r(X86::eax);
1410             m_jit.movzbl_rr(X86::eax, X86::eax);
1411             emitTagAsBoolImmediate(X86::eax);
1412             
1413             X86Assembler::JmpSrc bothWereImmediates = m_jit.emitUnlinkedJmp();
1414
1415             m_jit.link(firstNotImmediate, m_jit.label());
1416
1417             // check that edx is immediate but not the zero immediate
1418             
1419             m_jit.testl_i32r(JSImmediate::TagMask, X86::edx);
1420             m_jit.setz_r(X86::ecx);
1421             m_jit.movzbl_rr(X86::ecx, X86::ecx); // ecx is now 1 if edx was nonimmediate
1422             m_jit.cmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::zeroImmediate()), X86::edx);
1423             m_jit.sete_r(X86::edx);
1424             m_jit.movzbl_rr(X86::edx, X86::edx); // edx is now 1 if edx was the 0 immediate
1425             m_jit.orl_rr(X86::ecx, X86::edx);
1426
1427             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJnz(), i));
1428
1429             m_jit.movl_i32r(reinterpret_cast<uint32_t>(jsBoolean(false)), X86::eax);
1430
1431             X86Assembler::JmpSrc firstWasNotImmediate = m_jit.emitUnlinkedJmp();
1432
1433             m_jit.link(secondNotImmediate, m_jit.label());
1434             // check that eax is not the zero immediate (we know it must be immediate)
1435             m_jit.cmpl_i32r(reinterpret_cast<uint32_t>(JSImmediate::zeroImmediate()), X86::eax);
1436             m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJe(), i));
1437
1438             m_jit.movl_i32r(reinterpret_cast<uint32_t>(jsBoolean(false)), X86::eax);
1439
1440             m_jit.link(bothWereImmediates, m_jit.label());
1441             m_jit.link(firstWasNotImmediate, m_jit.label());
1442
1443             emitPutResult(dst);
1444             
1445             i += 4;
1446             break;
1447         }
1448         case op_to_jsnumber: {
1449             emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
1450             emitCall(i, Machine::cti_op_to_jsnumber);
1451             emitPutResult(instruction[i + 1].u.operand);
1452             i += 3;
1453             break;
1454         }
1455         case op_in: {
1456             emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
1457             emitGetPutArg(instruction[i + 3].u.operand, 4, X86::ecx);
1458             emitCall(i, Machine::cti_op_in);
1459             emitPutResult(instruction[i + 1].u.operand);
1460             i += 4;
1461             break;
1462         }
1463         case op_push_new_scope: {
1464             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
1465             emitPutArgConstant(reinterpret_cast<unsigned>(ident), 0);
1466             emitGetPutArg(instruction[i + 3].u.operand, 4, X86::ecx);
1467             emitCall(i, Machine::cti_op_push_new_scope);
1468             emitPutResult(instruction[i + 1].u.operand);
1469             i += 4;
1470             break;
1471         }
1472         case op_catch: {
1473             emitGetCTIParam(CTI_ARGS_r, X86::edi); // edi := r
1474             emitGetCTIParam(CTI_ARGS_exec, X86::ecx);
1475             m_jit.movl_mr(OBJECT_OFFSET(ExecState, m_exception), X86::ecx, X86::eax);
1476             m_jit.movl_i32m(0, OBJECT_OFFSET(ExecState, m_exception), X86::ecx);
1477             emitPutResult(instruction[i + 1].u.operand);
1478             i += 2;
1479             break;
1480         }
1481         case op_jmp_scopes: {
1482             unsigned count = instruction[i + 1].u.operand;
1483             emitPutArgConstant(count, 0);
1484             emitCall(i, Machine::cti_op_jmp_scopes);
1485             unsigned target = instruction[i + 2].u.operand;
1486             m_jmpTable.append(JmpTable(m_jit.emitUnlinkedJmp(), i + 2 + target));
1487             i += 3;
1488             break;
1489         }
1490         case op_put_by_index: {
1491             emitGetPutArg(instruction[i + 1].u.operand, 0, X86::ecx);
1492             emitPutArgConstant(instruction[i + 2].u.operand, 4);
1493             emitGetPutArg(instruction[i + 3].u.operand, 8, X86::ecx);
1494             emitCall(i, Machine::cti_op_put_by_index);
1495             i += 4;
1496             break;
1497         }
1498         case op_switch_imm: {
1499             unsigned tableIndex = instruction[i + 1].u.operand;
1500             unsigned defaultOffset = instruction[i + 2].u.operand;
1501             unsigned scrutinee = instruction[i + 3].u.operand;
1502
1503             // create jump table for switch destinations, track this switch statement.
1504             SimpleJumpTable* jumpTable = &m_codeBlock->immediateSwitchJumpTables[tableIndex];
1505             m_switches.append(SwitchRecord(jumpTable, i, defaultOffset, SwitchRecord::Immediate));
1506             jumpTable->ctiOffsets.grow(jumpTable->branchOffsets.size());
1507
1508             emitGetPutArg(scrutinee, 0, X86::ecx);
1509             emitPutArgConstant(tableIndex, 4);
1510             emitCall(i, Machine::cti_op_switch_imm);
1511             m_jit.jmp_r(X86::eax);
1512             i += 4;
1513             break;
1514         }
1515         case op_switch_char: {
1516             unsigned tableIndex = instruction[i + 1].u.operand;
1517             unsigned defaultOffset = instruction[i + 2].u.operand;
1518             unsigned scrutinee = instruction[i + 3].u.operand;
1519
1520             // create jump table for switch destinations, track this switch statement.
1521             SimpleJumpTable* jumpTable = &m_codeBlock->characterSwitchJumpTables[tableIndex];
1522             m_switches.append(SwitchRecord(jumpTable, i, defaultOffset, SwitchRecord::Character));
1523             jumpTable->ctiOffsets.grow(jumpTable->branchOffsets.size());
1524
1525             emitGetPutArg(scrutinee, 0, X86::ecx);
1526             emitPutArgConstant(tableIndex, 4);
1527             emitCall(i, Machine::cti_op_switch_char);
1528             m_jit.jmp_r(X86::eax);
1529             i += 4;
1530             break;
1531         }
1532         case op_switch_string: {
1533             unsigned tableIndex = instruction[i + 1].u.operand;
1534             unsigned defaultOffset = instruction[i + 2].u.operand;
1535             unsigned scrutinee = instruction[i + 3].u.operand;
1536
1537             // create jump table for switch destinations, track this switch statement.
1538             StringJumpTable* jumpTable = &m_codeBlock->stringSwitchJumpTables[tableIndex];
1539             m_switches.append(SwitchRecord(jumpTable, i, defaultOffset));
1540
1541             emitGetPutArg(scrutinee, 0, X86::ecx);
1542             emitPutArgConstant(tableIndex, 4);
1543             emitCall(i, Machine::cti_op_switch_string);
1544             m_jit.jmp_r(X86::eax);
1545             i += 4;
1546             break;
1547         }
1548         case op_del_by_val: {
1549             emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx);
1550             emitGetPutArg(instruction[i + 3].u.operand, 4, X86::ecx);
1551             emitCall(i, Machine::cti_op_del_by_val);
1552             emitPutResult(instruction[i + 1].u.operand);
1553             i += 4;
1554             break;
1555         }
1556         case op_put_getter: {
1557             emitGetPutArg(instruction[i + 1].u.operand, 0, X86::ecx);
1558             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
1559             emitPutArgConstant(reinterpret_cast<unsigned>(ident), 4);
1560             emitGetPutArg(instruction[i + 3].u.operand, 8, X86::ecx);
1561             emitCall(i, Machine::cti_op_put_getter);
1562             i += 4;
1563             break;
1564         }
1565         case op_put_setter: {
1566             emitGetPutArg(instruction[i + 1].u.operand, 0, X86::ecx);
1567             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
1568             emitPutArgConstant(reinterpret_cast<unsigned>(ident), 4);
1569             emitGetPutArg(instruction[i + 3].u.operand, 8, X86::ecx);
1570             emitCall(i, Machine::cti_op_put_setter);
1571             i += 4;
1572             break;
1573         }
1574         case op_new_error: {
1575             JSValue* message = m_codeBlock->unexpectedConstants[instruction[i + 3].u.operand];
1576             emitPutArgConstant(instruction[i + 2].u.operand, 0);
1577             emitPutArgConstant(reinterpret_cast<unsigned>(message), 4);
1578             emitPutArgConstant(m_codeBlock->lineNumberForVPC(&instruction[i]), 8);
1579             emitCall(i, Machine::cti_op_new_error);
1580             emitPutResult(instruction[i + 1].u.operand);
1581             i += 4;
1582             break;
1583         }
1584         case op_debug: {
1585             emitPutArgConstant(instruction[i + 1].u.operand, 0);
1586             emitPutArgConstant(instruction[i + 2].u.operand, 4);
1587             emitPutArgConstant(instruction[i + 3].u.operand, 8);
1588             emitCall(i, Machine::cti_op_debug);
1589             i += 4;
1590             break;
1591         }
1592         case op_eq_null: {
1593             unsigned dst = instruction[i + 1].u.operand;
1594             unsigned src1 = instruction[i + 2].u.operand;
1595
1596             emitGetArg(src1, X86::eax);
1597             m_jit.testl_i32r(JSImmediate::TagMask, X86::eax);
1598             X86Assembler::JmpSrc isImmediate = m_jit.emitUnlinkedJnz();
1599
1600             m_jit.movl_mr(OBJECT_OFFSET(JSCell, m_structureID), X86::eax, X86::ecx);
1601             m_jit.testl_i32m(MasqueradesAsUndefined, OBJECT_OFFSET(StructureID, m_typeInfo.m_flags), X86::ecx);
1602             m_jit.setnz_r(X86::eax);
1603
1604             X86Assembler::JmpSrc wasNotImmediate = m_jit.emitUnlinkedJmp();
1605
1606             m_jit.link(isImmediate, m_jit.label());
1607
1608             m_jit.movl_i32r(~JSImmediate::ExtendedTagBitUndefined, X86::ecx);
1609             m_jit.andl_rr(X86::eax, X86::ecx);
1610             m_jit.cmpl_i32r(JSImmediate::FullTagTypeNull, X86::ecx);
1611             m_jit.sete_r(X86::eax);
1612
1613             m_jit.link(wasNotImmediate, m_jit.label());
1614
1615             m_jit.movzbl_rr(X86::eax, X86::eax);
1616             emitTagAsBoolImmediate(X86::eax);
1617             emitPutResult(dst);
1618
1619             i += 3;
1620             break;
1621         }
1622         case op_neq_null: {
1623             unsigned dst = instruction[i + 1].u.operand;
1624             unsigned src1 = instruction[i + 2].u.operand;
1625
1626             emitGetArg(src1, X86::eax);
1627             m_jit.testl_i32r(JSImmediate::TagMask, X86::eax);
1628             X86Assembler::JmpSrc isImmediate = m_jit.emitUnlinkedJnz();
1629
1630             m_jit.movl_mr(OBJECT_OFFSET(JSCell, m_structureID), X86::eax, X86::ecx);
1631             m_jit.testl_i32m(MasqueradesAsUndefined, OBJECT_OFFSET(StructureID, m_typeInfo.m_flags), X86::ecx);
1632             m_jit.setz_r(X86::eax);
1633
1634             X86Assembler::JmpSrc wasNotImmediate = m_jit.emitUnlinkedJmp();
1635
1636             m_jit.link(isImmediate, m_jit.label());
1637
1638             m_jit.movl_i32r(~JSImmediate::ExtendedTagBitUndefined, X86::ecx);
1639             m_jit.andl_rr(X86::eax, X86::ecx);
1640             m_jit.cmpl_i32r(JSImmediate::FullTagTypeNull, X86::ecx);
1641             m_jit.setne_r(X86::eax);
1642
1643             m_jit.link(wasNotImmediate, m_jit.label());
1644
1645             m_jit.movzbl_rr(X86::eax, X86::eax);
1646             emitTagAsBoolImmediate(X86::eax);
1647             emitPutResult(dst);
1648
1649             i += 3;
1650             break;
1651         }
1652         case op_initialise_locals: {
1653             i++;
1654             break;
1655         }
1656         case op_get_array_length:
1657         case op_get_by_id_chain:
1658         case op_get_by_id_generic:
1659         case op_get_by_id_proto:
1660         case op_get_by_id_self:
1661         case op_get_string_length:
1662         case op_put_by_id_generic:
1663         case op_put_by_id_replace:
1664         case op_put_by_id_transition:
1665             ASSERT_NOT_REACHED();
1666         }
1667     }
1668
1669     ASSERT(structureIDInstructionIndex == m_codeBlock->structureIDInstructions.size());
1670 }
1671
1672
1673 void CTI::privateCompileLinkPass()
1674 {
1675     unsigned jmpTableCount = m_jmpTable.size();
1676     for (unsigned i = 0; i < jmpTableCount; ++i)
1677         m_jit.link(m_jmpTable[i].from, m_labels[m_jmpTable[i].to]);
1678     m_jmpTable.clear();
1679 }
1680
1681 #define CTI_COMPILE_BINARY_OP_SLOW_CASE(name) \
1682     case name: { \
1683         m_jit.link(iter->from, m_jit.label()); \
1684         emitGetPutArg(instruction[i + 2].u.operand, 0, X86::ecx); \
1685         emitGetPutArg(instruction[i + 3].u.operand, 4, X86::ecx); \
1686         emitCall(i, Machine::cti_##name); \
1687         emitPutResult(instruction[i + 1].u.operand); \
1688         i += 4; \
1689         break; \
1690     }
1691     
1692 void CTI::privateCompileSlowCases()
1693 {
1694     unsigned structureIDInstructionIndex = 0;
1695
1696     Instruction* instruction = m_codeBlock->instructions.begin();
1697     for (Vector<SlowCaseEntry>::iterator iter = m_slowCases.begin(); iter != m_slowCases.end(); ++iter) {
1698         unsigned i = iter->to;
1699         m_jit.emitRestoreArgumentReference();
1700         switch (m_machine->getOpcodeID(instruction[i].u.opcode)) {
1701         case op_add: {
1702             unsigned dst = instruction[i + 1].u.operand;
1703             unsigned src2 = instruction[i + 3].u.operand;
1704             if (src2 < m_codeBlock->constantRegisters.size()) {
1705                 JSValue* value = m_codeBlock->constantRegisters[src2].jsValue(m_exec);
1706                 if (JSImmediate::isNumber(value)) {
1707                     X86Assembler::JmpSrc notImm = iter->from;
1708                     m_jit.link((++iter)->from, m_jit.label());
1709                     m_jit.subl_i32r(getDeTaggedConstantImmediate(value), X86::eax);
1710                     m_jit.link(notImm, m_jit.label());
1711                     emitPutArg(X86::eax, 0);
1712                     emitGetPutArg(src2, 4, X86::ecx);
1713                     emitCall(i, Machine::cti_op_add);
1714                     emitPutResult(dst);
1715                     i += 4;
1716                     break;
1717                 }
1718             }
1719
1720             ASSERT(!(static_cast<unsigned>(instruction[i + 2].u.operand) < m_codeBlock->constantRegisters.size()));
1721
1722             X86Assembler::JmpSrc notImm = iter->from;
1723             m_jit.link((++iter)->from, m_jit.label());
1724             m_jit.subl_rr(X86::edx, X86::eax);
1725             emitFastArithReTagImmediate(X86::eax);
1726             m_jit.link(notImm, m_jit.label());
1727             emitPutArg(X86::eax, 0);
1728             emitPutArg(X86::edx, 4);
1729             emitCall(i, Machine::cti_op_add);
1730             emitPutResult(dst);
1731             i += 4;
1732             break;
1733         }
1734         case op_get_by_val: {
1735             // The slow case that handles accesses to arrays (below) may jump back up to here. 
1736             X86Assembler::JmpDst beginGetByValSlow = m_jit.label();
1737
1738             X86Assembler::JmpSrc notImm = iter->from;
1739             m_jit.link((++iter)->from, m_jit.label());
1740             m_jit.link((++iter)->from, m_jit.label());
1741             emitFastArithIntToImmNoCheck(X86::edx);
1742             m_jit.link(notImm, m_jit.label());
1743             emitPutArg(X86::eax, 0);
1744             emitPutArg(X86::edx, 4);
1745             emitCall(i, Machine::cti_op_get_by_val);
1746             emitPutResult(instruction[i + 1].u.operand);
1747             m_jit.link(m_jit.emitUnlinkedJmp(), m_labels[i + 4]);
1748
1749             // This is slow case that handles accesses to arrays above the fast cut-off.
1750             // First, check if this is an access to the vector
1751             m_jit.link((++iter)->from, m_jit.label());
1752             m_jit.cmpl_rm(X86::edx, OBJECT_OFFSET(ArrayStorage, m_vectorLength), X86::ecx);
1753             m_jit.link(m_jit.emitUnlinkedJbe(), beginGetByValSlow);
1754
1755             // okay, missed the fast region, but it is still in the vector.  Get the value.
1756             m_jit.movl_mr(OBJECT_OFFSET(ArrayStorage, m_vector[0]), X86::ecx, X86::edx, sizeof(JSValue*), X86::ecx);
1757             // Check whether the value loaded is zero; if so we need to return undefined.
1758             m_jit.testl_rr(X86::ecx, X86::ecx);
1759             m_jit.link(m_jit.emitUnlinkedJe(), beginGetByValSlow);
1760             emitPutResult(instruction[i + 1].u.operand, X86::ecx);
1761             
1762             i += 4;
1763             break;
1764         }
1765         case op_sub: {
1766             X86Assembler::JmpSrc notImm = iter->from;
1767             m_jit.link((++iter)->from, m_jit.label());
1768             m_jit.addl_rr(X86::edx, X86::eax);
1769             m_jit.link(notImm, m_jit.label());
1770             emitPutArg(X86::eax, 0);
1771             emitPutArg(X86::edx, 4);
1772             emitCall(i, Machine::cti_op_sub);
1773             emitPutResult(instruction[i + 1].u.operand);
1774             i += 4;
1775             break;
1776         }
1777         case op_rshift: {
1778             m_jit.link(iter->from, m_jit.label());
1779             m_jit.link((++iter)->from, m_jit.label());
1780             emitPutArg(X86::eax, 0);
1781             emitPutArg(X86::ecx, 4);
1782             emitCall(i, Machine::cti_op_rshift);
1783             emitPutResult(instruction[i + 1].u.operand);
1784             i += 4;
1785             break;
1786         }
1787         case op_lshift: {
1788             X86Assembler::JmpSrc notImm1 = iter->from;
1789             X86Assembler::JmpSrc notImm2 = (++iter)->from;
1790             m_jit.link((++iter)->from, m_jit.label());
1791             emitGetArg(instruction[i + 2].u.operand, X86::eax);
1792             emitGetArg(instruction[i + 3].u.operand, X86::ecx);
1793             m_jit.link(notImm1, m_jit.label());
1794             m_jit.link(notImm2, m_jit.label());
1795             emitPutArg(X86::eax, 0);
1796             emitPutArg(X86::ecx, 4);
1797             emitCall(i, Machine::cti_op_lshift);
1798             emitPutResult(instruction[i + 1].u.operand);
1799             i += 4;
1800             break;
1801         }
1802         case op_loop_if_less: {
1803             emitSlowScriptCheck(i);
1804
1805             unsigned target = instruction[i + 3].u.operand;
1806             JSValue* src2imm = getConstantImmediateNumericArg(instruction[i + 2].u.operand);
1807             if (src2imm) {
1808                 m_jit.link(iter->from, m_jit.label());
1809                 emitPutArg(X86::edx, 0);
1810                 emitGetPutArg(instruction[i + 2].u.operand, 4, X86::ecx);
1811                 emitCall(i, Machine::cti_op_loop_if_less);
1812                 m_jit.testl_rr(X86::eax, X86::eax);
1813                 m_jit.link(m_jit.emitUnlinkedJne(), m_labels[i + 3 + target]);
1814             } else {
1815                 m_jit.link(iter->from, m_jit.label());
1816                 m_jit.link((++iter)->from, m_jit.label());
1817                 emitPutArg(X86::eax, 0);
1818                 emitPutArg(X86::edx, 4);
1819                 emitCall(i, Machine::cti_op_loop_if_less);
1820                 m_jit.testl_rr(X86::eax, X86::eax);
1821                 m_jit.link(m_jit.emitUnlinkedJne(), m_labels[i + 3 + target]);
1822             }
1823             i += 4;
1824             break;
1825         }
1826         case op_put_by_id: {
1827             m_jit.link(iter->from, m_jit.label());
1828             m_jit.link((++iter)->from, m_jit.label());
1829
1830             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 2].u.operand]);
1831             emitPutArgConstant(reinterpret_cast<unsigned>(ident), 4);
1832             emitPutArg(X86::eax, 0);
1833             emitPutArg(X86::edx, 8);
1834             X86Assembler::JmpSrc call = emitCall(i, Machine::cti_op_put_by_id);
1835
1836             // Track the location of the call; this will be used to recover repatch information.
1837             ASSERT(m_codeBlock->structureIDInstructions[structureIDInstructionIndex].opcodeIndex == i);
1838             m_structureStubCompilationInfo[structureIDInstructionIndex].callReturnLocation = call;
1839             ++structureIDInstructionIndex;
1840
1841             i += 8;
1842             break;
1843         }
1844         case op_get_by_id: {
1845             // As for the hot path of get_by_id, above, we ensure that we can use an architecture specific offset
1846             // so that we only need track one pointer into the slow case code - we track a pointer to the location
1847             // of the call (which we can use to look up the repatch information), but should a array-length or
1848             // prototype access tramopile fail we want to bail out back to here.  To do so we can subtract back
1849             // the distance from the call to the head of the slow case.
1850
1851             m_jit.link(iter->from, m_jit.label());
1852             m_jit.link((++iter)->from, m_jit.label());
1853
1854 #ifndef NDEBUG
1855             X86Assembler::JmpDst coldPathBegin = m_jit.label();
1856 #endif        
1857             emitPutArg(X86::eax, 0);
1858             Identifier* ident = &(m_codeBlock->identifiers[instruction[i + 3].u.operand]);
1859             emitPutArgConstant(reinterpret_cast<unsigned>(ident), 4);
1860             X86Assembler::JmpSrc call = emitCall(i, Machine::cti_op_get_by_id);
1861             ASSERT(X86Assembler::getDifferenceBetweenLabels(coldPathBegin, call) == repatchOffsetGetByIdSlowCaseCall);
1862             emitPutResult(instruction[i + 1].u.operand);
1863
1864             // Track the location of the call; this will be used to recover repatch information.
1865             ASSERT(m_codeBlock->structureIDInstructions[structureIDInstructionIndex].opcodeIndex == i);
1866             m_structureStubCompilationInfo[structureIDInstructionIndex].callReturnLocation = call;
1867             ++structureIDInstructionIndex;
1868
1869             i += 8;
1870             break;
1871         }
1872         case op_resolve_global: {
1873             ++structureIDInstructionIndex;
1874             i += 6;
1875             break;
1876         }
1877         case op_loop_if_lesseq: {
1878             emitSlowScriptCheck(i);
1879
1880             unsigned target = instruction[i + 3].u.operand;
1881             JSValue* src2imm = getConstantImmediateNumericArg(instruction[i + 2].u.operand);
1882             if (src2imm) {
1883                 m_jit.link(iter->from, m_jit.label());
1884                 emitPutArg(X86::edx, 0);
1885                 emitGetPutArg(instruction[i + 2].u.operand, 4, X86::ecx);
1886                 emitCall(i, Machine::cti_op_loop_if_lesseq);
1887                 m_jit.testl_rr(X86::eax, X86::eax);
1888                 m_jit.link(m_jit.emitUnlinkedJne(), m_labels[i + 3 + target]);
1889             } else {
1890                 m_jit.link(iter->from, m_jit.label());
1891                 m_jit.link((++iter)->from, m_jit.label());
1892                 emitPutArg(X86::eax, 0);
1893                 emitPutArg(X86::edx, 4);
1894                 emitCall(i, Machine::cti_op_loop_if_lesseq);
1895                 m_jit.testl_rr(X86::eax, X86::eax);
1896                 m_jit.link(m_jit.emitUnlinkedJne(), m_labels[i + 3 + target]);
1897             }
1898             i += 4;
1899             break;
1900         }
1901         case op_pre_inc: {
1902             unsigned srcDst = instruction[i + 1].u.operand;
1903             X86Assembler::JmpSrc notImm = iter->from;
1904             m_jit.link((++iter)->from, m_jit.label());
1905             m_jit.subl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), X86::eax);
1906             m_jit.link(notImm, m_jit.label());
1907             emitPutArg(X86::eax, 0);
1908             emitCall(i, Machine::cti_op_pre_inc);
1909             emitPutResult(srcDst);
1910             i += 2;
1911             break;
1912         }
1913         case op_put_by_val: {
1914             // Normal slow cases - either is not an immediate imm, or is an array.
1915             X86Assembler::JmpSrc notImm = iter->from;
1916             m_jit.link((++iter)->from, m_jit.label());
1917             m_jit.link((++iter)->from, m_jit.label());
1918             emitFastArithIntToImmNoCheck(X86::edx);
1919             m_jit.link(notImm, m_jit.label());
1920             emitGetArg(instruction[i + 3].u.operand, X86::ecx);
1921             emitPutArg(X86::eax, 0);
1922             emitPutArg(X86::edx, 4);
1923             emitPutArg(X86::ecx, 8);
1924             emitCall(i, Machine::cti_op_put_by_val);
1925             m_jit.link(m_jit.emitUnlinkedJmp(), m_labels[i + 4]);
1926
1927             // slow cases for immediate int accesses to arrays
1928             m_jit.link((++iter)->from, m_jit.label());
1929             m_jit.link((++iter)->from, m_jit.label());
1930             emitGetArg(instruction[i + 3].u.operand, X86::ecx);
1931             emitPutArg(X86::eax, 0);
1932             emitPutArg(X86::edx, 4);
1933             emitPutArg(X86::ecx, 8);
1934             emitCall(i, Machine::cti_op_put_by_val_array);
1935
1936             i += 4;
1937             break;
1938         }
1939         case op_loop_if_true: {
1940             emitSlowScriptCheck(i);
1941
1942             m_jit.link(iter->from, m_jit.label());
1943             emitPutArg(X86::eax, 0);
1944             emitCall(i, Machine::cti_op_jtrue);
1945             m_jit.testl_rr(X86::eax, X86::eax);
1946             unsigned target = instruction[i + 2].u.operand;
1947             m_jit.link(m_jit.emitUnlinkedJne(), m_labels[i + 2 + target]);
1948             i += 3;
1949             break;
1950         }
1951         case op_pre_dec: {
1952             unsigned srcDst = instruction[i + 1].u.operand;
1953             X86Assembler::JmpSrc notImm = iter->from;
1954             m_jit.link((++iter)->from, m_jit.label());
1955             m_jit.addl_i8r(getDeTaggedConstantImmediate(JSImmediate::oneImmediate()), X86::eax);
1956             m_jit.link(notImm, m_jit.label());
1957             emitPutArg(X86::eax, 0);
1958             emitCall(i, Machine::cti_op_pre_dec);
1959             emitPutResult(srcDst);
1960             i += 2;
1961             break;
1962         }
1963         case op_jnless: {
1964             unsigned target = instruction[i + 3].u.operand;
1965             JSValue* src2imm = getConstantImmediateNumericArg(instruction[i + 2].u.operand);
1966             if (src2imm) {
1967                 m_jit.link(iter->from, m_jit.label());
1968                 emitPutArg(X86::edx, 0);
1969                 emitGetPutArg(instruction[i + 2].u.operand, 4, X86::ecx);
1970                 emitCall(i, Machine::cti_op_jless);
1971                 m_jit.testl_rr(X86::eax, X86::eax);
1972                 m_jit.link(m_jit.emitUnlinkedJe(), m_labels[i + 3 + target]);
1973             } else {
1974                 m_jit.link(iter->from, m_jit.label());
1975                 m_jit.link((++iter)->from, m_jit.label());
1976                 emitPutArg(X86::eax, 0);
1977                 emitPutArg(X86::edx, 4);
1978                 emitCall(i, Machine::cti_op_jless);
1979                 m_jit.testl_rr(X86::eax, X86::eax);
1980                 m_jit.link(m_jit.emitUnlinkedJe(), m_labels[i + 3 + target]);
1981             }
1982             i += 4;
1983             break;
1984         }
1985         case op_not: {
1986             m_jit.link(iter->from, m_jit.label());
1987             m_jit.xorl_i8r(JSImmediate::FullTagTypeBool, X86::eax);
1988             emitPutArg(X86::eax, 0);
1989             emitCall(i, Machine::cti_op_not);
1990             emitPutResult(instruction[i + 1].u.operand);
1991             i += 3;
1992             break;
1993         }
1994         case op_jfalse: {
1995             m_jit.link(iter->from, m_jit.label());
1996             emitPutArg(X86::eax, 0);
1997             emitCall(i, Machine::cti_op_jtrue);
1998             m_jit.testl_rr(X86::eax, X86::eax);
1999             unsigned target = instruction[i + 2].u.operand;
2000             m_jit.link(m_jit.emitUnlinkedJe(), m_labels[i + 2 + target]); // inverted!
2001             i += 3;
2002             break;
2003         }
2004         case op_post_inc: {
2005             unsigned srcDst = instruction[i + 2].u.operand;
2006             m_jit.link(iter->from, m_jit.label());
2007             m_jit.link((++iter)->from, m_jit.label());
2008             emitPutArg(X86::eax, 0);
2009             emitCall(i, Machine::cti_op_post_inc);
2010             emitPutResult(instruction[i + 1].u.operand);
2011             emitGetCTIParam(CTI_ARGS_2ndResult, X86::eax);
2012             emitPutResult(srcDst);
2013             i += 3;
2014             break;
2015         }
2016         case op_bitnot: {
2017             m_jit.link(iter->from, m_jit.label());
2018             emitPutArg(X86::eax, 0);
2019             emitCall(i, Machine::cti_op_bitnot);
2020             emitPutResult(instruction[i + 1].u.operand);
2021             i += 3;
2022             break;
2023         }
2024         case op_bitand: {
2025             unsigned src1 = instruction[i + 2].u.operand;
2026             unsigned src2 = instruction[i + 3].u.operand;
2027             unsigned dst = instruction[i + 1].u.operand;
2028             if (getConstantImmediateNumericArg(src1)) {
2029                 m_jit.link(iter->from, m_jit.label());
2030                 emitGetPutArg(src1, 0, X86::ecx);
2031                 emitPutArg(X86::eax, 4);
2032                 emitCall(i, Machine::cti_op_bitand);
2033                 emitPutResult(dst);
2034             } else if (getConstantImmediateNumericArg(src2)) {
2035                 m_jit.link(iter->from, m_jit.label());
2036                 emitPutArg(X86::eax, 0);
2037                 emitGetPutArg(src2, 4, X86::ecx);
2038                 emitCall(i, Machine::cti_op_bitand);
2039                 emitPutResult(dst);
2040             } else {
2041                 m_jit.link(iter->from, m_jit.label());
2042                 emitGetPutArg(src1, 0, X86::ecx);
2043                 emitPutArg(X86::edx, 4);
2044                 emitCall(i, Machine::cti_op_bitand);
2045                 emitPutResult(dst);
2046             }
2047             i += 4;
2048             break;
2049         }
2050         case op_jtrue: {
2051             m_jit.link(iter->from, m_jit.label());
2052             emitPutArg(X86::eax, 0);
2053             emitCall(i, Machine::cti_op_jtrue);
2054             m_jit.testl_rr(X86::eax, X86::eax);
2055             unsigned target = instruction[i + 2].u.operand;
2056             m_jit.link(m_jit.emitUnlinkedJne(), m_labels[i + 2 + target]);
2057             i += 3;
2058             break;
2059         }
2060         case op_post_dec: {
2061             unsigned srcDst = instruction[i + 2].u.operand;
2062             m_jit.link(iter->from, m_jit.label());
2063             m_jit.link((++iter)->from, m_jit.label());
2064             emitPutArg(X86::eax, 0);
2065             emitCall(i, Machine::cti_op_post_dec);
2066             emitPutResult(instruction[i + 1].u.operand);
2067             emitGetCTIParam(CTI_ARGS_2ndResult, X86::eax);
2068             emitPutResult(srcDst);
2069             i += 3;
2070             break;
2071         }
2072         case op_bitxor: {
2073             m_jit.link(iter->from, m_jit.label());
2074             emitPutArg(X86::eax, 0);
2075             emitPutArg(X86::edx, 4);
2076             emitCall(i, Machine::cti_op_bitxor);
2077             emitPutResult(instruction[i + 1].u.operand);
2078             i += 4;
2079             break;
2080         }
2081         case op_bitor: {
2082             m_jit.link(iter->from, m_jit.label());
2083             emitPutArg(X86::eax, 0);
2084             emitPutArg(X86::edx, 4);
2085             emitCall(i, Machine::cti_op_bitor);
2086             emitPutResult(instruction[i + 1].u.operand);
2087             i += 4;
2088             break;
2089         }
2090         case op_eq:
2091             m_jit.link(iter->from, m_jit.label());
2092             emitPutArg(X86::eax, 0);
2093             emitPutArg(X86::edx, 4);
2094             emitCall(i, Machine::cti_op_eq);
2095             emitPutResult(instruction[i + 1].u.operand);
2096             i += 4;
2097             break;
2098         CTI_COMPILE_BINARY_OP_SLOW_CASE(op_stricteq);
2099
2100         case op_mod: {
2101             X86Assembler::JmpSrc notImm1 = iter->from;
2102             X86Assembler::JmpSrc notImm2 = (++iter)->from;
2103             m_jit.link((++iter)->from, m_jit.label());
2104             emitFastArithReTagImmediate(X86::eax);
2105             emitFastArithReTagImmediate(X86::ecx);
2106             m_jit.link(notImm1, m_jit.label());
2107             m_jit.link(notImm2, m_jit.label());
2108             emitPutArg(X86::eax, 0);
2109             emitPutArg(X86::ecx, 4);
2110             emitCall(i, Machine::cti_op_mod);
2111             emitPutResult(instruction[i + 1].u.operand);
2112             i += 4;
2113             break;
2114         }
2115         CTI_COMPILE_BINARY_OP_SLOW_CASE(op_mul);
2116
2117         case op_call:
2118         case op_call_eval:
2119         case op_construct: {
2120             m_jit.link(iter->from, m_jit.label());
2121             m_jit.emitRestoreArgumentReference();
2122
2123             // We jump to this slow case if the ctiCode for the codeBlock has not yet been generated; compile it now.
2124             emitCall(i, Machine::cti_vm_compile);
2125             m_jit.call_r(X86::eax);
2126             
2127             // Instead of checking for 0 we could initialize the CodeBlock::ctiCode to point to a trampoline that would trigger the translation.
2128
2129             // In the interpreter the following actions are performed by op_ret:
2130             
2131             // Store the scope chain - returned by op_ret in %edx (see below) - to ExecState::m_scopeChain and CTI_ARGS_scopeChain on the stack.
2132             emitGetCTIParam(CTI_ARGS_exec, X86::ecx);
2133             emitPutCTIParam(X86::edx, CTI_ARGS_scopeChain);
2134             m_jit.movl_rm(X86::edx, OBJECT_OFFSET(ExecState, m_scopeChain), X86::ecx);
2135             // Restore ExecState::m_callFrame.
2136             m_jit.leal_mr(-(m_codeBlock->numLocals + RegisterFile::CallFrameHeaderSize) * sizeof(Register), X86::edi, X86::edx);
2137             m_jit.movl_rm(X86::edx, OBJECT_OFFSET(ExecState, m_callFrame), X86::ecx);
2138             // Restore CTI_ARGS_codeBlock.
2139             emitPutCTIParam(m_codeBlock, CTI_ARGS_codeBlock);
2140
2141             emitPutResult(instruction[i + 1].u.operand);
2142             i += 6;
2143             break;
2144         }
2145
2146         default:
2147             ASSERT_NOT_REACHED();
2148             break;
2149         }
2150
2151         m_jit.link(m_jit.emitUnlinkedJmp(), m_labels[i]);
2152     }
2153
2154     ASSERT(structureIDInstructionIndex == m_codeBlock->structureIDInstructions.size());
2155 }
2156
2157 void CTI::privateCompile()
2158 {
2159     // Could use a popl_m, but would need to offset the following instruction if so.
2160     m_jit.popl_r(X86::ecx);
2161     emitGetCTIParam(CTI_ARGS_r, X86::edi); // edi := r
2162     emitPutToCallFrameHeader(X86::ecx, RegisterFile::CTIReturnEIP);
2163
2164     // Lazy copy of the scopeChain
2165     X86Assembler::JmpSrc callToUpdateScopeChain;
2166     if ((m_codeBlock->codeType == FunctionCode) && m_codeBlock->needsFullScopeChain) {
2167         m_jit.emitRestoreArgumentReference();
2168         callToUpdateScopeChain = m_jit.emitCall();
2169     }
2170
2171     privateCompileMainPass();
2172     privateCompileLinkPass();
2173     privateCompileSlowCases();
2174
2175     ASSERT(m_jmpTable.isEmpty());
2176
2177     void* code = m_jit.copy();
2178     ASSERT(code);
2179
2180     // Translate vPC offsets into addresses in JIT generated code, for switch tables.
2181     for (unsigned i = 0; i < m_switches.size(); ++i) {
2182         SwitchRecord record = m_switches[i];
2183         unsigned opcodeIndex = record.m_opcodeIndex;
2184
2185         if (record.m_type != SwitchRecord::String) {
2186             ASSERT(record.m_type == SwitchRecord::Immediate || record.m_type == SwitchRecord::Character); 
2187             ASSERT(record.m_jumpTable.m_simpleJumpTable->branchOffsets.size() == record.m_jumpTable.m_simpleJumpTable->ctiOffsets.size());
2188
2189             record.m_jumpTable.m_simpleJumpTable->ctiDefault = m_jit.getRelocatedAddress(code, m_labels[opcodeIndex + 3 + record.m_defaultOffset]);
2190
2191             for (unsigned j = 0; j < record.m_jumpTable.m_simpleJumpTable->branchOffsets.size(); ++j) {
2192                 unsigned offset = record.m_jumpTable.m_simpleJumpTable->branchOffsets[j];
2193                 record.m_jumpTable.m_simpleJumpTable->ctiOffsets[j] = offset ? m_jit.getRelocatedAddress(code, m_labels[opcodeIndex + 3 + offset]) : record.m_jumpTable.m_simpleJumpTable->ctiDefault;
2194             }
2195         } else {
2196             ASSERT(record.m_type == SwitchRecord::String);
2197
2198             record.m_jumpTable.m_stringJumpTable->ctiDefault = m_jit.getRelocatedAddress(code, m_labels[opcodeIndex + 3 + record.m_defaultOffset]);
2199
2200             StringJumpTable::StringOffsetTable::iterator end = record.m_jumpTable.m_stringJumpTable->offsetTable.end();            
2201             for (StringJumpTable::StringOffsetTable::iterator it = record.m_jumpTable.m_stringJumpTable->offsetTable.begin(); it != end; ++it) {
2202                 unsigned offset = it->second.branchOffset;
2203                 it->second.ctiOffset = offset ? m_jit.getRelocatedAddress(code, m_labels[opcodeIndex + 3 + offset]) : record.m_jumpTable.m_stringJumpTable->ctiDefault;
2204             }
2205         }
2206     }
2207
2208     for (Vector<HandlerInfo>::iterator iter = m_codeBlock->exceptionHandlers.begin(); iter != m_codeBlock->exceptionHandlers.end(); ++iter)
2209          iter->nativeCode = m_jit.getRelocatedAddress(code, m_labels[iter->target]);
2210
2211     // FIXME: There doesn't seem to be a way to hint to a hashmap that it should make a certain capacity available;
2212     // could be faster if we could do something like this:
2213     // m_codeBlock->ctiReturnAddressVPCMap.grow(m_calls.size());
2214     for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
2215         X86Assembler::link(code, iter->from, iter->to);
2216         m_codeBlock->ctiReturnAddressVPCMap.add(m_jit.getRelocatedAddress(code, iter->from), iter->opcodeIndex);
2217     }
2218
2219     if ((m_codeBlock->codeType == FunctionCode) && m_codeBlock->needsFullScopeChain)
2220         X86Assembler::link(code, callToUpdateScopeChain, (void*)Machine::cti_vm_updateScopeChain);
2221
2222     // Link absolute addresses for jsr
2223     for (Vector<JSRInfo>::iterator iter = m_jsrSites.begin(); iter != m_jsrSites.end(); ++iter)
2224         X86Assembler::linkAbsoluteAddress(code, iter->addrPosition, iter->target);
2225
2226     for (unsigned i = 0; i < m_codeBlock->structureIDInstructions.size(); ++i) {
2227         StructureStubInfo& info = m_codeBlock->structureIDInstructions[i];
2228         info.callReturnLocation = X86Assembler::getRelocatedAddress(code, m_structureStubCompilationInfo[i].callReturnLocation);
2229         info.hotPathBegin = X86Assembler::getRelocatedAddress(code, m_structureStubCompilationInfo[i].hotPathBegin);
2230     }
2231
2232     m_codeBlock->ctiCode = code;
2233 }
2234
2235 void CTI::privateCompileGetByIdSelf(StructureID* structureID, size_t cachedOffset, void* returnAddress)
2236 {
2237     // Check eax is an object of the right StructureID.
2238     m_jit.testl_i32r(JSImmediate::TagMask, X86::eax);
2239     X86Assembler::JmpSrc failureCases1 = m_jit.emitUnlinkedJne();
2240     m_jit.cmpl_i32m(reinterpret_cast<uint32_t>(structureID), OBJECT_OFFSET(JSCell, m_structureID), X86::eax);
2241     X86Assembler::JmpSrc failureCases2 = m_jit.emitUnlinkedJne();
2242
2243     // Checks out okay! - getDirectOffset
2244     m_jit.movl_mr(OBJECT_OFFSET(JSObject, m_propertyStorage), X86::eax, X86::eax);
2245     m_jit.movl_mr(cachedOffset * sizeof(JSValue*), X86::eax, X86::eax);
2246     m_jit.ret();
2247
2248     void* code = m_jit.copy();
2249     ASSERT(code);
2250
2251     X86Assembler::link(code, failureCases1, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
2252     X86Assembler::link(code, failureCases2, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
2253     
2254     m_codeBlock->getStubInfo(returnAddress).stubRoutine = code;
2255     
2256     ctiRepatchCallByReturnAddress(returnAddress, code);
2257 }
2258
2259 void CTI::privateCompileGetByIdProto(StructureID* structureID, StructureID* prototypeStructureID, size_t cachedOffset, void* returnAddress)
2260 {
2261 #if USE(CTI_REPATCH_PIC)
2262     StructureStubInfo& info = m_codeBlock->getStubInfo(returnAddress);
2263
2264     // We don't want to repatch more than once - in future go to cti_op_put_by_id_generic.
2265     ctiRepatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
2266
2267     // The prototype object definitely exists (if this stub exists the CodeBlock is referencing a StructureID that is
2268     // referencing the prototype object - let's speculatively load it's table nice and early!)
2269     JSObject* protoObject = static_cast<JSObject*>(structureID->prototypeForLookup(m_exec));
2270     PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage;
2271     m_jit.movl_mr(static_cast<void*>(protoPropertyStorage), X86::edx);
2272
2273     // check eax is an object of the right StructureID.
2274     m_jit.testl_i32r(JSImmediate::TagMask, X86::eax);
2275     X86Assembler::JmpSrc failureCases1 = m_jit.emitUnlinkedJne();
2276     m_jit.cmpl_i32m(reinterpret_cast<uint32_t>(structureID), OBJECT_OFFSET(JSCell, m_structureID), X86::eax);
2277     X86Assembler::JmpSrc failureCases2 = m_jit.emitUnlinkedJne();
2278
2279     // Check the prototype object's StructureID had not changed.
2280     StructureID** protoStructureIDAddress = &(protoObject->m_structureID);
2281     m_jit.cmpl_i32m(reinterpret_cast<uint32_t>(prototypeStructureID), static_cast<void*>(protoStructureIDAddress));
2282     X86Assembler::JmpSrc failureCases3 = m_jit.emitUnlinkedJne();
2283
2284     // Checks out okay! - getDirectOffset
2285     m_jit.movl_mr(cachedOffset * sizeof(JSValue*), X86::edx, X86::ecx);
2286
2287     X86Assembler::JmpSrc success = m_jit.emitUnlinkedJmp();
2288
2289     void* code = m_jit.copy();
2290     ASSERT(code);
2291
2292     // Use the repatch information to link the failure cases back to the original slow case routine.
2293     void* slowCaseBegin = reinterpret_cast<char*>(info.callReturnLocation) - repatchOffsetGetByIdSlowCaseCall;
2294     X86Assembler::link(code, failureCases1, slowCaseBegin);
2295     X86Assembler::link(code, failureCases2, slowCaseBegin);
2296     X86Assembler::link(code, failureCases3, slowCaseBegin);
2297
2298     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
2299     intptr_t successDest = (intptr_t)(info.hotPathBegin) + repatchOffsetGetByIdPropertyMapOffset;
2300     X86Assembler::link(code, success, reinterpret_cast<void*>(successDest));
2301
2302     // Track the stub we have created so that it will be deleted later.
2303     m_codeBlock->getStubInfo(returnAddress).stubRoutine = code;
2304
2305     // Finally repatch the jump to sow case back in the hot path to jump here instead.
2306     // FIXME: should revert this repatching, on failure.
2307     intptr_t jmpLocation = reinterpret_cast<intptr_t>(info.hotPathBegin) + repatchOffsetGetByIdBranchToSlowCase;
2308     X86Assembler::repatchBranchOffset(jmpLocation, code);
2309 #else
2310     // The prototype object definitely exists (if this stub exists the CodeBlock is referencing a StructureID that is
2311     // referencing the prototype object - let's speculatively load it's table nice and early!)
2312     JSObject* protoObject = static_cast<JSObject*>(structureID->prototypeForLookup(m_exec));
2313     PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage;
2314     m_jit.movl_mr(static_cast<void*>(protoPropertyStorage), X86::edx);
2315
2316     // check eax is an object of the right StructureID.
2317     m_jit.testl_i32r(JSImmediate::TagMask, X86::eax);
2318     X86Assembler::JmpSrc failureCases1 = m_jit.emitUnlinkedJne();
2319     m_jit.cmpl_i32m(reinterpret_cast<uint32_t>(structureID), OBJECT_OFFSET(JSCell, m_structureID), X86::eax);
2320     X86Assembler::JmpSrc failureCases2 = m_jit.emitUnlinkedJne();
2321
2322     // Check the prototype object's StructureID had not changed.
2323     StructureID** protoStructureIDAddress = &(protoObject->m_structureID);
2324     m_jit.cmpl_i32m(reinterpret_cast<uint32_t>(prototypeStructureID), static_cast<void*>(protoStructureIDAddress));
2325     X86Assembler::JmpSrc failureCases3 = m_jit.emitUnlinkedJne();
2326
2327     // Checks out okay! - getDirectOffset
2328     m_jit.movl_mr(cachedOffset * sizeof(JSValue*), X86::edx, X86::eax);
2329
2330     m_jit.ret();
2331
2332     void* code = m_jit.copy();
2333     ASSERT(code);
2334
2335     X86Assembler::link(code, failureCases1, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
2336     X86Assembler::link(code, failureCases2, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
2337     X86Assembler::link(code, failureCases3, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
2338
2339     m_codeBlock->getStubInfo(returnAddress).stubRoutine = code;
2340
2341     ctiRepatchCallByReturnAddress(returnAddress, code);
2342 #endif
2343 }
2344
2345 void CTI::privateCompileGetByIdChain(StructureID* structureID, StructureIDChain* chain, size_t count, size_t cachedOffset, void* returnAddress)
2346 {
2347     ASSERT(count);
2348     
2349     Vector<X86Assembler::JmpSrc> bucketsOfFail;
2350
2351     // Check eax is an object of the right StructureID.
2352     m_jit.testl_i32r(JSImmediate::TagMask, X86::eax);
2353     bucketsOfFail.append(m_jit.emitUnlinkedJne());
2354     m_jit.cmpl_i32m(reinterpret_cast<uint32_t>(structureID), OBJECT_OFFSET(JSCell, m_structureID), X86::eax);
2355     bucketsOfFail.append(m_jit.emitUnlinkedJne());
2356
2357     StructureID* currStructureID = structureID;
2358     RefPtr<StructureID>* chainEntries = chain->head();
2359     JSObject* protoObject = 0;
2360     for (unsigned i = 0; i<count; ++i) {
2361         protoObject = static_cast<JSObject*>(currStructureID->prototypeForLookup(m_exec));
2362         currStructureID = chainEntries[i].get();
2363
2364         // Check the prototype object's StructureID had not changed.
2365         StructureID** protoStructureIDAddress = &(protoObject->m_structureID);
2366         m_jit.cmpl_i32m(reinterpret_cast<uint32_t>(currStructureID), static_cast<void*>(protoStructureIDAddress));
2367         bucketsOfFail.append(m_jit.emitUnlinkedJne());
2368     }
2369     ASSERT(protoObject);
2370
2371     PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage;
2372     m_jit.movl_mr(static_cast<void*>(protoPropertyStorage), X86::edx);
2373     m_jit.movl_mr(cachedOffset * sizeof(JSValue*), X86::edx, X86::eax);
2374     m_jit.ret();
2375
2376     bucketsOfFail.append(m_jit.emitUnlinkedJmp());
2377
2378     void* code = m_jit.copy();
2379     ASSERT(code);
2380
2381     for (unsigned i = 0; i < bucketsOfFail.size(); ++i)
2382         X86Assembler::link(code, bucketsOfFail[i], reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
2383
2384     m_codeBlock->getStubInfo(returnAddress).stubRoutine = code;
2385
2386     ctiRepatchCallByReturnAddress(returnAddress, code);
2387 }
2388
2389 void CTI::privateCompilePutByIdReplace(StructureID* structureID, size_t cachedOffset, void* returnAddress)
2390 {
2391     // check eax is an object of the right StructureID.
2392     m_jit.testl_i32r(JSImmediate::TagMask, X86::eax);
2393     X86Assembler::JmpSrc failureCases1 = m_jit.emitUnlinkedJne();
2394     m_jit.cmpl_i32m(reinterpret_cast<uint32_t>(structureID), OBJECT_OFFSET(JSCell, m_structureID), X86::eax);
2395     X86Assembler::JmpSrc failureCases2 = m_jit.emitUnlinkedJne();
2396
2397     // checks out okay! - putDirectOffset
2398     m_jit.movl_mr(OBJECT_OFFSET(JSObject, m_propertyStorage), X86::eax, X86::eax);
2399     m_jit.movl_rm(X86::edx, cachedOffset * sizeof(JSValue*), X86::eax);
2400     m_jit.ret();
2401
2402     void* code = m_jit.copy();
2403     ASSERT(code);
2404     
2405     X86Assembler::link(code, failureCases1, reinterpret_cast<void*>(Machine::cti_op_put_by_id_fail));
2406     X86Assembler::link(code, failureCases2, reinterpret_cast<void*>(Machine::cti_op_put_by_id_fail));
2407
2408     m_codeBlock->getStubInfo(returnAddress).stubRoutine = code;
2409     
2410     ctiRepatchCallByReturnAddress(returnAddress, code);
2411 }
2412
2413 extern "C" {
2414
2415 static JSValue* SFX_CALL transitionObject(StructureID* newStructureID, size_t cachedOffset, JSObject* baseObject, JSValue* value)
2416 {
2417     StructureID* oldStructureID = newStructureID->previousID();
2418
2419     baseObject->transitionTo(newStructureID);
2420
2421     if (oldStructureID->propertyMap().storageSize() == JSObject::inlineStorageCapacity)
2422         baseObject->allocatePropertyStorage(oldStructureID->propertyMap().storageSize(), oldStructureID->propertyMap().size());
2423
2424     baseObject->putDirectOffset(cachedOffset, value);
2425     return baseObject;
2426 }
2427
2428 }
2429
2430 static inline bool transitionWillNeedStorageRealloc(StructureID* oldStructureID, StructureID* newStructureID)
2431 {
2432     if (oldStructureID->propertyMap().storageSize() == JSObject::inlineStorageCapacity)
2433         return true;
2434
2435     if (oldStructureID->propertyMap().storageSize() < JSObject::inlineStorageCapacity)
2436         return false;
2437
2438     if (oldStructureID->propertyMap().size() != newStructureID->propertyMap().size())
2439         return true;
2440
2441     return false;
2442 }
2443
2444 void CTI::privateCompilePutByIdTransition(StructureID* oldStructureID, StructureID* newStructureID, size_t cachedOffset, StructureIDChain* sIDC, void* returnAddress)
2445 {
2446     Vector<X86Assembler::JmpSrc, 16> failureCases;
2447     // check eax is an object of the right StructureID.
2448     m_jit.testl_i32r(JSImmediate::TagMask, X86::eax);
2449     failureCases.append(m_jit.emitUnlinkedJne());
2450     m_jit.cmpl_i32m(reinterpret_cast<uint32_t>(oldStructureID), OBJECT_OFFSET(JSCell, m_structureID), X86::eax);
2451     failureCases.append(m_jit.emitUnlinkedJne());
2452     Vector<X86Assembler::JmpSrc> successCases;
2453
2454     //  ecx = baseObject
2455     m_jit.movl_mr(OBJECT_OFFSET(JSCell, m_structureID), X86::eax, X86::ecx);
2456     // proto(ecx) = baseObject->structureID()->prototype()
2457     m_jit.cmpl_i32m(ObjectType, OBJECT_OFFSET(StructureID, m_typeInfo) + OBJECT_OFFSET(TypeInfo, m_type), X86::ecx);
2458     failureCases.append(m_jit.emitUnlinkedJne());
2459     m_jit.movl_mr(OBJECT_OFFSET(StructureID, m_prototype), X86::ecx, X86::ecx);
2460     
2461     // ecx = baseObject->m_structureID
2462     for (RefPtr<StructureID>* it = sIDC->head(); *it; ++it) {
2463         // null check the prototype
2464         m_jit.cmpl_i32r(reinterpret_cast<intptr_t> (jsNull()), X86::ecx);
2465         successCases.append(m_jit.emitUnlinkedJe());
2466
2467         // Check the structure id
2468         m_jit.cmpl_i32m(reinterpret_cast<uint32_t>(it->get()), OBJECT_OFFSET(JSCell, m_structureID), X86::ecx);
2469         failureCases.append(m_jit.emitUnlinkedJne());
2470         
2471         m_jit.movl_mr(OBJECT_OFFSET(JSCell, m_structureID), X86::ecx, X86::ecx);
2472         m_jit.cmpl_i32m(ObjectType, OBJECT_OFFSET(StructureID, m_typeInfo) + OBJECT_OFFSET(TypeInfo, m_type), X86::ecx);
2473         failureCases.append(m_jit.emitUnlinkedJne());
2474         m_jit.movl_mr(OBJECT_OFFSET(StructureID, m_prototype), X86::ecx, X86::ecx);
2475     }
2476
2477     failureCases.append(m_jit.emitUnlinkedJne());
2478     for (unsigned i = 0; i < successCases.size(); ++i)
2479         m_jit.link(successCases[i], m_jit.label());
2480
2481     X86Assembler::JmpSrc callTarget;
2482     // Fast case, don't need to do any heavy lifting, so don't bother making a call.
2483     if (!transitionWillNeedStorageRealloc(oldStructureID, newStructureID)) {
2484         // Assumes m_refCount can be decremented easily, refcount decrement is safe as 
2485         // codeblock should ensure oldStructureID->m_refCount > 0
2486         m_jit.subl_i8m(1, reinterpret_cast<void*>(oldStructureID));
2487         m_jit.addl_i8m(1, reinterpret_cast<void*>(newStructureID));
2488         m_jit.movl_i32m(reinterpret_cast<uint32_t>(newStructureID), OBJECT_OFFSET(JSCell, m_structureID), X86::eax);
2489
2490         // write the value
2491         m_jit.movl_mr(OBJECT_OFFSET(JSObject, m_propertyStorage), X86::eax, X86::eax);
2492         m_jit.movl_rm(X86::edx, cachedOffset * sizeof(JSValue*), X86::eax);
2493     } else {
2494         // Slow case transition -- we're going to need to quite a bit of work,
2495         // so just make a call
2496         m_jit.pushl_r(X86::edx);
2497         m_jit.pushl_r(X86::eax);
2498         m_jit.movl_i32r(cachedOffset, X86::eax);
2499         m_jit.pushl_r(X86::eax);
2500         m_jit.movl_i32r(reinterpret_cast<uint32_t>(newStructureID), X86::eax);
2501         m_jit.pushl_r(X86::eax);
2502         callTarget = m_jit.emitCall();
2503         m_jit.addl_i32r(4 * sizeof(void*), X86::esp);
2504     }
2505     m_jit.ret();
2506     void* code = m_jit.copy();
2507     ASSERT(code);
2508     
2509     for (unsigned i = 0; i < failureCases.size(); ++i)
2510         X86Assembler::link(code, failureCases[i], reinterpret_cast<void*>(Machine::cti_op_put_by_id_fail));
2511
2512     if (transitionWillNeedStorageRealloc(oldStructureID, newStructureID))
2513         X86Assembler::link(code, callTarget, reinterpret_cast<void*>(transitionObject));
2514     
2515     m_codeBlock->getStubInfo(returnAddress).stubRoutine = code;
2516     
2517     ctiRepatchCallByReturnAddress(returnAddress, code);
2518 }
2519
2520 void* CTI::privateCompileArrayLengthTrampoline()
2521 {
2522     // Check eax is an array
2523     m_jit.testl_i32r(JSImmediate::TagMask, X86::eax);
2524     X86Assembler::JmpSrc failureCases1 = m_jit.emitUnlinkedJne();
2525     m_jit.cmpl_i32m(reinterpret_cast<unsigned>(m_machine->m_jsArrayVptr), X86::eax);
2526     X86Assembler::JmpSrc failureCases2 = m_jit.emitUnlinkedJne();
2527
2528     // Checks out okay! - get the length from the storage
2529     m_jit.movl_mr(OBJECT_OFFSET(JSArray, m_storage), X86::eax, X86::eax);
2530     m_jit.movl_mr(OBJECT_OFFSET(ArrayStorage, m_length), X86::eax, X86::eax);
2531
2532     m_jit.addl_rr(X86::eax, X86::eax);
2533     X86Assembler::JmpSrc failureCases3 = m_jit.emitUnlinkedJo();
2534     m_jit.addl_i8r(1, X86::eax);
2535     
2536     m_jit.ret();
2537
2538     void* code = m_jit.copy();
2539     ASSERT(code);
2540
2541     X86Assembler::link(code, failureCases1, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
2542     X86Assembler::link(code, failureCases2, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
2543     X86Assembler::link(code, failureCases3, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
2544     
2545     return code;
2546 }
2547
2548 void* CTI::privateCompileStringLengthTrampoline()
2549 {
2550     // Check eax is a string
2551     m_jit.testl_i32r(JSImmediate::TagMask, X86::eax);
2552     X86Assembler::JmpSrc failureCases1 = m_jit.emitUnlinkedJne();
2553     m_jit.cmpl_i32m(reinterpret_cast<unsigned>(m_machine->m_jsStringVptr), X86::eax);
2554     X86Assembler::JmpSrc failureCases2 = m_jit.emitUnlinkedJne();
2555
2556     // Checks out okay! - get the length from the Ustring.
2557     m_jit.movl_mr(OBJECT_OFFSET(JSString, m_value) + OBJECT_OFFSET(UString, m_rep), X86::eax, X86::eax);
2558     m_jit.movl_mr(OBJECT_OFFSET(UString::Rep, len), X86::eax, X86::eax);
2559
2560     m_jit.addl_rr(X86::eax, X86::eax);
2561     X86Assembler::JmpSrc failureCases3 = m_jit.emitUnlinkedJo();
2562     m_jit.addl_i8r(1, X86::eax);
2563     
2564     m_jit.ret();
2565
2566     void* code = m_jit.copy();
2567     ASSERT(code);
2568
2569     X86Assembler::link(code, failureCases1, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
2570     X86Assembler::link(code, failureCases2, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
2571     X86Assembler::link(code, failureCases3, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
2572
2573     return code;
2574 }
2575
2576 void CTI::patchGetByIdSelf(CodeBlock* codeBlock, StructureID* structureID, size_t cachedOffset, void* returnAddress)
2577 {
2578     StructureStubInfo& info = codeBlock->getStubInfo(returnAddress);
2579
2580     // We don't want to repatch more than once - in future go to cti_op_get_by_id_generic.
2581     // Should probably go to Machine::cti_op_get_by_id_fail, but that doesn't do anything interesting right now.
2582     ctiRepatchCallByReturnAddress(returnAddress, (void*)(Machine::cti_op_get_by_id_generic));
2583
2584     // Repatch the offset into the propoerty map to load from, then repatch the StructureID to look for.
2585     X86Assembler::repatchDisplacement(reinterpret_cast<intptr_t>(info.hotPathBegin) + repatchOffsetGetByIdPropertyMapOffset, cachedOffset * sizeof(JSValue*));
2586     X86Assembler::repatchImmediate(reinterpret_cast<intptr_t>(info.hotPathBegin) + repatchOffsetGetByIdStructureID, reinterpret_cast<uint32_t>(structureID));
2587 }
2588
2589 void CTI::patchPutByIdReplace(CodeBlock* codeBlock, StructureID* structureID, size_t cachedOffset, void* returnAddress)
2590 {
2591     StructureStubInfo& info = codeBlock->getStubInfo(returnAddress);
2592     
2593     // We don't want to repatch more than once - in future go to cti_op_put_by_id_generic.
2594     // Should probably go to Machine::cti_op_put_by_id_fail, but that doesn't do anything interesting right now.
2595     ctiRepatchCallByReturnAddress(returnAddress, (void*)(Machine::cti_op_put_by_id_generic));
2596
2597     // Repatch the offset into the propoerty map to load from, then repatch the StructureID to look for.
2598     X86Assembler::repatchDisplacement(reinterpret_cast<intptr_t>(info.hotPathBegin) + repatchOffsetPutByIdPropertyMapOffset, cachedOffset * sizeof(JSValue*));
2599     X86Assembler::repatchImmediate(reinterpret_cast<intptr_t>(info.hotPathBegin) + repatchOffsetPutByIdStructureID, reinterpret_cast<uint32_t>(structureID));
2600 }
2601
2602 void CTI::privateCompilePatchGetArrayLength(void* returnAddress)
2603 {
2604     StructureStubInfo& info = m_codeBlock->getStubInfo(returnAddress);
2605
2606     // We don't want to repatch more than once - in future go to cti_op_put_by_id_generic.
2607     ctiRepatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
2608
2609     // Check eax is an array
2610     m_jit.testl_i32r(JSImmediate::TagMask, X86::eax);
2611     X86Assembler::JmpSrc failureCases1 = m_jit.emitUnlinkedJne();
2612     m_jit.cmpl_i32m(reinterpret_cast<unsigned>(m_machine->m_jsArrayVptr), X86::eax);
2613     X86Assembler::JmpSrc failureCases2 = m_jit.emitUnlinkedJne();
2614
2615     // Checks out okay! - get the length from the storage
2616     m_jit.movl_mr(OBJECT_OFFSET(JSArray, m_storage), X86::eax, X86::ecx);
2617     m_jit.movl_mr(OBJECT_OFFSET(ArrayStorage, m_length), X86::ecx, X86::ecx);
2618
2619     m_jit.addl_rr(X86::ecx, X86::ecx);
2620     X86Assembler::JmpSrc failureCases3 = m_jit.emitUnlinkedJo();
2621     m_jit.addl_i8r(1, X86::ecx);
2622
2623     X86Assembler::JmpSrc success = m_jit.emitUnlinkedJmp();
2624
2625     void* code = m_jit.copy();
2626     ASSERT(code);
2627
2628     // Use the repatch information to link the failure cases back to the original slow case routine.
2629     void* slowCaseBegin = reinterpret_cast<char*>(info.callReturnLocation) - repatchOffsetGetByIdSlowCaseCall;
2630     X86Assembler::link(code, failureCases1, slowCaseBegin);
2631     X86Assembler::link(code, failureCases2, slowCaseBegin);
2632     X86Assembler::link(code, failureCases3, slowCaseBegin);
2633
2634     // On success return back to the hot patch code, at a point it will perform the store to dest for us.
2635     intptr_t successDest = (intptr_t)(info.hotPathBegin) + repatchOffsetGetByIdPropertyMapOffset;
2636     X86Assembler::link(code, success, reinterpret_cast<void*>(successDest));
2637
2638     // Track the stub we have created so that it will be deleted later.
2639     m_codeBlock->getStubInfo(returnAddress).stubRoutine = code;
2640
2641     // Finally repatch the jump to sow case back in the hot path to jump here instead.
2642     // FIXME: should revert this repatching, on failure.
2643     intptr_t jmpLocation = reinterpret_cast<intptr_t>(info.hotPathBegin) + repatchOffsetGetByIdBranchToSlowCase;
2644     X86Assembler::repatchBranchOffset(jmpLocation, code);
2645 }
2646
2647 void CTI::emitGetVariableObjectRegister(X86Assembler::RegisterID variableObject, int index, X86Assembler::RegisterID dst)
2648 {
2649     m_jit.movl_mr(JSVariableObject::offsetOf_d(), variableObject, dst);
2650     m_jit.movl_mr(JSVariableObject::offsetOf_Data_registers(), dst, dst);
2651     m_jit.movl_mr(index * sizeof(Register), dst, dst);
2652 }
2653
2654 void CTI::emitPutVariableObjectRegister(X86Assembler::RegisterID src, X86Assembler::RegisterID variableObject, int index)
2655 {
2656     m_jit.movl_mr(JSVariableObject::offsetOf_d(), variableObject, variableObject);
2657     m_jit.movl_mr(JSVariableObject::offsetOf_Data_registers(), variableObject, variableObject);
2658     m_jit.movl_rm(src, index * sizeof(Register), variableObject);
2659 }
2660
2661 #if ENABLE(WREC)
2662
2663 void* CTI::compileRegExp(ExecState* exec, const UString& pattern, unsigned* numSubpatterns_ptr, const char** error_ptr, bool ignoreCase, bool multiline)
2664 {
2665     // TODO: better error messages
2666     if (pattern.size() > MaxPatternSize) {
2667         *error_ptr = "regular expression too large";
2668         return 0;
2669     }
2670
2671     X86Assembler jit(exec->machine()->jitCodeBuffer());
2672     WRECParser parser(pattern, ignoreCase, multiline, jit);
2673     
2674     jit.emitConvertToFastCall();
2675     // (0) Setup:
2676     //     Preserve regs & initialize outputRegister.
2677     jit.pushl_r(WRECGenerator::outputRegister);
2678     jit.pushl_r(WRECGenerator::currentValueRegister);
2679     // push pos onto the stack, both to preserve and as a parameter available to parseDisjunction
2680     jit.pushl_r(WRECGenerator::currentPositionRegister);
2681     // load output pointer
2682     jit.movl_mr(16
2683 #if COMPILER(MSVC)
2684                     + 3 * sizeof(void*)
2685 #endif
2686                     , X86::esp, WRECGenerator::outputRegister);
2687     
2688     // restart point on match fail.
2689     WRECGenerator::JmpDst nextLabel = jit.label();
2690
2691     // (1) Parse Disjunction:
2692     
2693     //     Parsing the disjunction should fully consume the pattern.
2694     JmpSrcVector failures;
2695     parser.parseDisjunction(failures);
2696     if (parser.isEndOfPattern()) {
2697         parser.m_err = WRECParser::Error_malformedPattern;
2698     }
2699     if (parser.m_err) {
2700         // TODO: better error messages
2701         *error_ptr = "TODO: better error messages";
2702         return 0;
2703     }
2704
2705     // (2) Success:
2706     //     Set return value & pop registers from the stack.
2707
2708     jit.testl_rr(WRECGenerator::outputRegister, WRECGenerator::outputRegister);
2709     WRECGenerator::JmpSrc noOutput = jit.emitUnlinkedJe();
2710
2711     jit.movl_rm(WRECGenerator::currentPositionRegister, 4, WRECGenerator::outputRegister);
2712     jit.popl_r(X86::eax);
2713     jit.movl_rm(X86::eax, WRECGenerator::outputRegister);
2714     jit.popl_r(WRECGenerator::currentValueRegister);
2715     jit.popl_r(WRECGenerator::outputRegister);
2716     jit.ret();
2717     
2718     jit.link(noOutput, jit.label());
2719     
2720     jit.popl_r(X86::eax);
2721     jit.movl_rm(X86::eax, WRECGenerator::outputRegister);
2722     jit.popl_r(WRECGenerator::currentValueRegister);
2723     jit.popl_r(WRECGenerator::outputRegister);
2724     jit.ret();
2725
2726     // (3) Failure:
2727     //     All fails link to here.  Progress the start point & if it is within scope, loop.
2728     //     Otherwise, return fail value.
2729     WRECGenerator::JmpDst here = jit.label();
2730     for (unsigned i = 0; i < failures.size(); ++i)
2731         jit.link(failures[i], here);
2732     failures.clear();
2733
2734     jit.movl_mr(X86::esp, WRECGenerator::currentPositionRegister);
2735     jit.addl_i8r(1, WRECGenerator::currentPositionRegister);
2736     jit.movl_rm(WRECGenerator::currentPositionRegister, X86::esp);
2737     jit.cmpl_rr(WRECGenerator::lengthRegister, WRECGenerator::currentPositionRegister);
2738     jit.link(jit.emitUnlinkedJle(), nextLabel);
2739
2740     jit.addl_i8r(4, X86::esp);
2741
2742     jit.movl_i32r(-1, X86::eax);
2743     jit.popl_r(WRECGenerator::currentValueRegister);
2744     jit.popl_r(WRECGenerator::outputRegister);
2745     jit.ret();
2746
2747     *numSubpatterns_ptr = parser.m_numSubpatterns;
2748
2749     void* code = jit.copy();
2750     ASSERT(code);
2751     return code;
2752 }
2753
2754 #endif // ENABLE(WREC)
2755
2756 } // namespace JSC
2757
2758 #endif // ENABLE(CTI)