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