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