1 /*
2  * Copyright (C) 2009 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 "JIT.h"
28 
29 #if ENABLE(JIT)
30 
31 #include "JITInlineMethods.h"
32 #include "JITStubCall.h"
33 #include "JSArray.h"
34 #include "JSCell.h"
35 #include "JSFunction.h"
36 #include "JSPropertyNameIterator.h"
37 #include "LinkBuffer.h"
38 
39 namespace JSC {
40 
41 #if USE(JSVALUE32_64)
42 
privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool> * executablePool,JSGlobalData * globalData,CodePtr * ctiStringLengthTrampoline,CodePtr * ctiVirtualCallLink,CodePtr * ctiVirtualCall,CodePtr * ctiNativeCallThunk)43 void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executablePool, JSGlobalData* globalData, CodePtr* ctiStringLengthTrampoline, CodePtr* ctiVirtualCallLink, CodePtr* ctiVirtualCall, CodePtr* ctiNativeCallThunk)
44 {
45 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
46     // (1) This function provides fast property access for string length
47     Label stringLengthBegin = align();
48 
49     // regT0 holds payload, regT1 holds tag
50 
51     Jump string_failureCases1 = branch32(NotEqual, regT1, Imm32(JSValue::CellTag));
52     Jump string_failureCases2 = branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr));
53 
54     // Checks out okay! - get the length from the Ustring.
55     load32(Address(regT0, OBJECT_OFFSETOF(JSString, m_stringLength)), regT2);
56 
57     Jump string_failureCases3 = branch32(Above, regT2, Imm32(INT_MAX));
58     move(regT2, regT0);
59     move(Imm32(JSValue::Int32Tag), regT1);
60 
61     ret();
62 #endif
63 
64     // (2) Trampolines for the slow cases of op_call / op_call_eval / op_construct.
65 
66 #if ENABLE(JIT_OPTIMIZE_CALL)
67     // VirtualCallLink Trampoline
68     // regT0 holds callee, regT1 holds argCount.  regT2 will hold the FunctionExecutable.
69     Label virtualCallLinkBegin = align();
70     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
71 
72     Jump isNativeFunc2 = branch32(Equal, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParameters)), Imm32(0));
73 
74     Jump hasCodeBlock2 = branch32(GreaterThan, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParameters)), Imm32(0));
75     preserveReturnAddressAfterCall(regT3);
76     restoreArgumentReference();
77     Call callJSFunction2 = call();
78     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
79     emitGetJITStubArg(2, regT1); // argCount
80     restoreReturnAddressBeforeReturn(regT3);
81     hasCodeBlock2.link(this);
82 
83     // Check argCount matches callee arity.
84     Jump arityCheckOkay2 = branch32(Equal, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParameters)), regT1);
85     preserveReturnAddressAfterCall(regT3);
86     emitPutJITStubArg(regT3, 1); // return address
87     restoreArgumentReference();
88     Call callArityCheck2 = call();
89     move(regT1, callFrameRegister);
90     emitGetJITStubArg(2, regT1); // argCount
91     restoreReturnAddressBeforeReturn(regT3);
92     arityCheckOkay2.link(this);
93 
94     isNativeFunc2.link(this);
95 
96     compileOpCallInitializeCallFrame();
97 
98     preserveReturnAddressAfterCall(regT3);
99     emitPutJITStubArg(regT3, 1); // return address
100     restoreArgumentReference();
101     Call callLazyLinkCall = call();
102     restoreReturnAddressBeforeReturn(regT3);
103     jump(regT0);
104 #endif // ENABLE(JIT_OPTIMIZE_CALL)
105 
106     // VirtualCall Trampoline
107     // regT0 holds callee, regT1 holds argCount.  regT2 will hold the FunctionExecutable.
108     Label virtualCallBegin = align();
109     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
110 
111     Jump isNativeFunc3 = branch32(Equal, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParameters)), Imm32(0));
112 
113     Jump hasCodeBlock3 = branch32(GreaterThan, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParameters)), Imm32(0));
114     preserveReturnAddressAfterCall(regT3);
115     restoreArgumentReference();
116     Call callJSFunction1 = call();
117     emitGetJITStubArg(2, regT1); // argCount
118     restoreReturnAddressBeforeReturn(regT3);
119     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
120     hasCodeBlock3.link(this);
121 
122     // Check argCount matches callee arity.
123     Jump arityCheckOkay3 = branch32(Equal, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParameters)), regT1);
124     preserveReturnAddressAfterCall(regT3);
125     emitPutJITStubArg(regT3, 1); // return address
126     restoreArgumentReference();
127     Call callArityCheck1 = call();
128     move(regT1, callFrameRegister);
129     emitGetJITStubArg(2, regT1); // argCount
130     restoreReturnAddressBeforeReturn(regT3);
131     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
132     arityCheckOkay3.link(this);
133 
134     isNativeFunc3.link(this);
135 
136     compileOpCallInitializeCallFrame();
137     loadPtr(Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_jitCode)), regT0);
138     jump(regT0);
139 
140 #if CPU(X86) || CPU(ARM_TRADITIONAL)
141     Label nativeCallThunk = align();
142     preserveReturnAddressAfterCall(regT0);
143     emitPutToCallFrameHeader(regT0, RegisterFile::ReturnPC); // Push return address
144 
145     // Load caller frame's scope chain into this callframe so that whatever we call can
146     // get to its global data.
147     emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT1);
148     emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT1);
149     emitPutToCallFrameHeader(regT1, RegisterFile::ScopeChain);
150 
151 #if CPU(X86)
152     emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0);
153 
154     /* We have two structs that we use to describe the stackframe we set up for our
155      * call to native code.  NativeCallFrameStructure describes the how we set up the stack
156      * in advance of the call.  NativeFunctionCalleeSignature describes the callframe
157      * as the native code expects it.  We do this as we are using the fastcall calling
158      * convention which results in the callee popping its arguments off the stack, but
159      * not the rest of the callframe so we need a nice way to ensure we increment the
160      * stack pointer by the right amount after the call.
161      */
162 
163 #if COMPILER(MSVC) || OS(LINUX)
164 #if COMPILER(MSVC)
165 #pragma pack(push)
166 #pragma pack(4)
167 #endif // COMPILER(MSVC)
168     struct NativeCallFrameStructure {
169       //  CallFrame* callFrame; // passed in EDX
170         JSObject* callee;
171         JSValue thisValue;
172         ArgList* argPointer;
173         ArgList args;
174         JSValue result;
175     };
176     struct NativeFunctionCalleeSignature {
177         JSObject* callee;
178         JSValue thisValue;
179         ArgList* argPointer;
180     };
181 #if COMPILER(MSVC)
182 #pragma pack(pop)
183 #endif // COMPILER(MSVC)
184 #else
185     struct NativeCallFrameStructure {
186       //  CallFrame* callFrame; // passed in ECX
187       //  JSObject* callee; // passed in EDX
188         JSValue thisValue;
189         ArgList* argPointer;
190         ArgList args;
191     };
192     struct NativeFunctionCalleeSignature {
193         JSValue thisValue;
194         ArgList* argPointer;
195     };
196 #endif
197 
198     const int NativeCallFrameSize = (sizeof(NativeCallFrameStructure) + 15) & ~15;
199     // Allocate system stack frame
200     subPtr(Imm32(NativeCallFrameSize), stackPointerRegister);
201 
202     // Set up arguments
203     subPtr(Imm32(1), regT0); // Don't include 'this' in argcount
204 
205     // push argcount
206     storePtr(regT0, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, args) + OBJECT_OFFSETOF(ArgList, m_argCount)));
207 
208     // Calculate the start of the callframe header, and store in regT1
209     addPtr(Imm32(-RegisterFile::CallFrameHeaderSize * (int)sizeof(Register)), callFrameRegister, regT1);
210 
211     // Calculate start of arguments as callframe header - sizeof(Register) * argcount (regT0)
212     mul32(Imm32(sizeof(Register)), regT0, regT0);
213     subPtr(regT0, regT1);
214     storePtr(regT1, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, args) + OBJECT_OFFSETOF(ArgList, m_args)));
215 
216     // ArgList is passed by reference so is stackPointerRegister + 4 * sizeof(Register)
217     addPtr(Imm32(OBJECT_OFFSETOF(NativeCallFrameStructure, args)), stackPointerRegister, regT0);
218     storePtr(regT0, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, argPointer)));
219 
220     // regT1 currently points to the first argument, regT1 - sizeof(Register) points to 'this'
221     loadPtr(Address(regT1, -(int)sizeof(Register) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT2);
222     loadPtr(Address(regT1, -(int)sizeof(Register) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT3);
223     storePtr(regT2, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, thisValue) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
224     storePtr(regT3, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, thisValue) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
225 
226 #if COMPILER(MSVC) || OS(LINUX)
227     // ArgList is passed by reference so is stackPointerRegister + 4 * sizeof(Register)
228     addPtr(Imm32(OBJECT_OFFSETOF(NativeCallFrameStructure, result)), stackPointerRegister, X86Registers::ecx);
229 
230     // Plant callee
231     emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, X86Registers::eax);
232     storePtr(X86Registers::eax, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, callee)));
233 
234     // Plant callframe
235     move(callFrameRegister, X86Registers::edx);
236 
237     call(Address(X86Registers::eax, OBJECT_OFFSETOF(JSFunction, m_data)));
238 
239     // JSValue is a non-POD type, so eax points to it
240     emitLoad(0, regT1, regT0, X86Registers::eax);
241 #else
242     emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, X86Registers::edx); // callee
243     move(callFrameRegister, X86Registers::ecx); // callFrame
244     call(Address(X86Registers::edx, OBJECT_OFFSETOF(JSFunction, m_data)));
245 #endif
246 
247     // We've put a few temporaries on the stack in addition to the actual arguments
248     // so pull them off now
249     addPtr(Imm32(NativeCallFrameSize - sizeof(NativeFunctionCalleeSignature)), stackPointerRegister);
250 
251 #elif CPU(ARM_TRADITIONAL)
252     emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0);
253 
254     // Allocate stack space for our arglist
255     COMPILE_ASSERT((sizeof(ArgList) & 0x7) == 0 && sizeof(JSValue) == 8 && sizeof(Register) == 8, ArgList_should_by_8byte_aligned);
256     subPtr(Imm32(sizeof(ArgList)), stackPointerRegister);
257 
258     // Set up arguments
259     subPtr(Imm32(1), regT0); // Don't include 'this' in argcount
260 
261     // Push argcount
262     storePtr(regT0, Address(stackPointerRegister, OBJECT_OFFSETOF(ArgList, m_argCount)));
263 
264     // Calculate the start of the callframe header, and store in regT1
265     move(callFrameRegister, regT1);
266     sub32(Imm32(RegisterFile::CallFrameHeaderSize * (int32_t)sizeof(Register)), regT1);
267 
268     // Calculate start of arguments as callframe header - sizeof(Register) * argcount (regT1)
269     mul32(Imm32(sizeof(Register)), regT0, regT0);
270     subPtr(regT0, regT1);
271 
272     // push pointer to arguments
273     storePtr(regT1, Address(stackPointerRegister, OBJECT_OFFSETOF(ArgList, m_args)));
274 
275     // Argument passing method:
276     // r0 - points to return value
277     // r1 - callFrame
278     // r2 - callee
279     // stack: this(JSValue) and a pointer to ArgList
280 
281     move(stackPointerRegister, regT3);
282     subPtr(Imm32(8), stackPointerRegister);
283     move(stackPointerRegister, regT0);
284     subPtr(Imm32(8 + 4 + 4 /* padding */), stackPointerRegister);
285 
286     // Setup arg4:
287     storePtr(regT3, Address(stackPointerRegister, 8));
288 
289     // Setup arg3
290     // regT1 currently points to the first argument, regT1-sizeof(Register) points to 'this'
291     load32(Address(regT1, -(int32_t)sizeof(void*) * 2), regT3);
292     storePtr(regT3, Address(stackPointerRegister, 0));
293     load32(Address(regT1, -(int32_t)sizeof(void*)), regT3);
294     storePtr(regT3, Address(stackPointerRegister, 4));
295 
296     // Setup arg2:
297     emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, regT2);
298 
299     // Setup arg1:
300     move(callFrameRegister, regT1);
301 
302     call(Address(regT2, OBJECT_OFFSETOF(JSFunction, m_data)));
303 
304     // Load return value
305     load32(Address(stackPointerRegister, 16), regT0);
306     load32(Address(stackPointerRegister, 20), regT1);
307 
308     addPtr(Imm32(sizeof(ArgList) + 16 + 8), stackPointerRegister);
309 #endif
310 
311     // Check for an exception
312     move(ImmPtr(&globalData->exception), regT2);
313     Jump sawException = branch32(NotEqual, tagFor(0, regT2), Imm32(JSValue::EmptyValueTag));
314 
315     // Grab the return address.
316     emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT3);
317 
318     // Restore our caller's "r".
319     emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
320 
321     // Return.
322     restoreReturnAddressBeforeReturn(regT3);
323     ret();
324 
325     // Handle an exception
326     sawException.link(this);
327     // Grab the return address.
328     emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1);
329     move(ImmPtr(&globalData->exceptionLocation), regT2);
330     storePtr(regT1, regT2);
331     move(ImmPtr(FunctionPtr(ctiVMThrowTrampoline).value()), regT2);
332     emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
333     poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof (void*));
334     restoreReturnAddressBeforeReturn(regT2);
335     ret();
336 
337 #elif ENABLE(JIT_OPTIMIZE_NATIVE_CALL)
338 #error "JIT_OPTIMIZE_NATIVE_CALL not yet supported on this platform."
339 #else
340     breakpoint();
341 #endif
342 
343 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
344     Call string_failureCases1Call = makeTailRecursiveCall(string_failureCases1);
345     Call string_failureCases2Call = makeTailRecursiveCall(string_failureCases2);
346     Call string_failureCases3Call = makeTailRecursiveCall(string_failureCases3);
347 #endif
348 
349     // All trampolines constructed! copy the code, link up calls, and set the pointers on the Machine object.
350     LinkBuffer patchBuffer(this, m_globalData->executableAllocator.poolForSize(m_assembler.size()));
351 
352 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
353     patchBuffer.link(string_failureCases1Call, FunctionPtr(cti_op_get_by_id_string_fail));
354     patchBuffer.link(string_failureCases2Call, FunctionPtr(cti_op_get_by_id_string_fail));
355     patchBuffer.link(string_failureCases3Call, FunctionPtr(cti_op_get_by_id_string_fail));
356 #endif
357     patchBuffer.link(callArityCheck1, FunctionPtr(cti_op_call_arityCheck));
358     patchBuffer.link(callJSFunction1, FunctionPtr(cti_op_call_JSFunction));
359 #if ENABLE(JIT_OPTIMIZE_CALL)
360     patchBuffer.link(callArityCheck2, FunctionPtr(cti_op_call_arityCheck));
361     patchBuffer.link(callJSFunction2, FunctionPtr(cti_op_call_JSFunction));
362     patchBuffer.link(callLazyLinkCall, FunctionPtr(cti_vm_lazyLinkCall));
363 #endif
364 
365     CodeRef finalCode = patchBuffer.finalizeCode();
366     *executablePool = finalCode.m_executablePool;
367 
368     *ctiVirtualCall = trampolineAt(finalCode, virtualCallBegin);
369     *ctiNativeCallThunk = trampolineAt(finalCode, nativeCallThunk);
370 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
371     *ctiStringLengthTrampoline = trampolineAt(finalCode, stringLengthBegin);
372 #else
373     UNUSED_PARAM(ctiStringLengthTrampoline);
374 #endif
375 #if ENABLE(JIT_OPTIMIZE_CALL)
376     *ctiVirtualCallLink = trampolineAt(finalCode, virtualCallLinkBegin);
377 #else
378     UNUSED_PARAM(ctiVirtualCallLink);
379 #endif
380 }
381 
emit_op_mov(Instruction * currentInstruction)382 void JIT::emit_op_mov(Instruction* currentInstruction)
383 {
384     unsigned dst = currentInstruction[1].u.operand;
385     unsigned src = currentInstruction[2].u.operand;
386 
387     if (m_codeBlock->isConstantRegisterIndex(src))
388         emitStore(dst, getConstantOperand(src));
389     else {
390         emitLoad(src, regT1, regT0);
391         emitStore(dst, regT1, regT0);
392         map(m_bytecodeIndex + OPCODE_LENGTH(op_mov), dst, regT1, regT0);
393     }
394 }
395 
emit_op_end(Instruction * currentInstruction)396 void JIT::emit_op_end(Instruction* currentInstruction)
397 {
398     if (m_codeBlock->needsFullScopeChain())
399         JITStubCall(this, cti_op_end).call();
400     ASSERT(returnValueRegister != callFrameRegister);
401     emitLoad(currentInstruction[1].u.operand, regT1, regT0);
402     restoreReturnAddressBeforeReturn(Address(callFrameRegister, RegisterFile::ReturnPC * static_cast<int>(sizeof(Register))));
403     ret();
404 }
405 
emit_op_jmp(Instruction * currentInstruction)406 void JIT::emit_op_jmp(Instruction* currentInstruction)
407 {
408     unsigned target = currentInstruction[1].u.operand;
409     addJump(jump(), target);
410 }
411 
emit_op_loop_if_lesseq(Instruction * currentInstruction)412 void JIT::emit_op_loop_if_lesseq(Instruction* currentInstruction)
413 {
414     unsigned op1 = currentInstruction[1].u.operand;
415     unsigned op2 = currentInstruction[2].u.operand;
416     unsigned target = currentInstruction[3].u.operand;
417 
418     emitTimeoutCheck();
419 
420     if (isOperandConstantImmediateInt(op1)) {
421         emitLoad(op2, regT1, regT0);
422         addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
423         addJump(branch32(GreaterThanOrEqual, regT0, Imm32(getConstantOperand(op1).asInt32())), target);
424         return;
425     }
426 
427     if (isOperandConstantImmediateInt(op2)) {
428         emitLoad(op1, regT1, regT0);
429         addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
430         addJump(branch32(LessThanOrEqual, regT0, Imm32(getConstantOperand(op2).asInt32())), target);
431         return;
432     }
433 
434     emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
435     addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
436     addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
437     addJump(branch32(LessThanOrEqual, regT0, regT2), target);
438 }
439 
emitSlow_op_loop_if_lesseq(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)440 void JIT::emitSlow_op_loop_if_lesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
441 {
442     unsigned op1 = currentInstruction[1].u.operand;
443     unsigned op2 = currentInstruction[2].u.operand;
444     unsigned target = currentInstruction[3].u.operand;
445 
446     if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2))
447         linkSlowCase(iter); // int32 check
448     linkSlowCase(iter); // int32 check
449 
450     JITStubCall stubCall(this, cti_op_loop_if_lesseq);
451     stubCall.addArgument(op1);
452     stubCall.addArgument(op2);
453     stubCall.call();
454     emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
455 }
456 
emit_op_new_object(Instruction * currentInstruction)457 void JIT::emit_op_new_object(Instruction* currentInstruction)
458 {
459     JITStubCall(this, cti_op_new_object).call(currentInstruction[1].u.operand);
460 }
461 
emit_op_instanceof(Instruction * currentInstruction)462 void JIT::emit_op_instanceof(Instruction* currentInstruction)
463 {
464     unsigned dst = currentInstruction[1].u.operand;
465     unsigned value = currentInstruction[2].u.operand;
466     unsigned baseVal = currentInstruction[3].u.operand;
467     unsigned proto = currentInstruction[4].u.operand;
468 
469     // Load the operands into registers.
470     // We use regT0 for baseVal since we will be done with this first, and we can then use it for the result.
471     emitLoadPayload(value, regT2);
472     emitLoadPayload(baseVal, regT0);
473     emitLoadPayload(proto, regT1);
474 
475     // Check that value, baseVal, and proto are cells.
476     emitJumpSlowCaseIfNotJSCell(value);
477     emitJumpSlowCaseIfNotJSCell(baseVal);
478     emitJumpSlowCaseIfNotJSCell(proto);
479 
480     // Check that baseVal 'ImplementsDefaultHasInstance'.
481     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT0);
482     addSlowCase(branchTest32(Zero, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(ImplementsDefaultHasInstance)));
483 
484     // Optimistically load the result true, and start looping.
485     // Initially, regT1 still contains proto and regT2 still contains value.
486     // As we loop regT2 will be updated with its prototype, recursively walking the prototype chain.
487     move(Imm32(JSValue::TrueTag), regT0);
488     Label loop(this);
489 
490     // Load the prototype of the cell in regT2.  If this is equal to regT1 - WIN!
491     // Otherwise, check if we've hit null - if we have then drop out of the loop, if not go again.
492     loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
493     load32(Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT2);
494     Jump isInstance = branchPtr(Equal, regT2, regT1);
495     branchTest32(NonZero, regT2).linkTo(loop, this);
496 
497     // We get here either by dropping out of the loop, or if value was not an Object.  Result is false.
498     move(Imm32(JSValue::FalseTag), regT0);
499 
500     // isInstance jumps right down to here, to skip setting the result to false (it has already set true).
501     isInstance.link(this);
502     emitStoreBool(dst, regT0);
503 }
504 
emitSlow_op_instanceof(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)505 void JIT::emitSlow_op_instanceof(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
506 {
507     unsigned dst = currentInstruction[1].u.operand;
508     unsigned value = currentInstruction[2].u.operand;
509     unsigned baseVal = currentInstruction[3].u.operand;
510     unsigned proto = currentInstruction[4].u.operand;
511 
512     linkSlowCaseIfNotJSCell(iter, value);
513     linkSlowCaseIfNotJSCell(iter, baseVal);
514     linkSlowCaseIfNotJSCell(iter, proto);
515     linkSlowCase(iter);
516 
517     JITStubCall stubCall(this, cti_op_instanceof);
518     stubCall.addArgument(value);
519     stubCall.addArgument(baseVal);
520     stubCall.addArgument(proto);
521     stubCall.call(dst);
522 }
523 
emit_op_new_func(Instruction * currentInstruction)524 void JIT::emit_op_new_func(Instruction* currentInstruction)
525 {
526     JITStubCall stubCall(this, cti_op_new_func);
527     stubCall.addArgument(ImmPtr(m_codeBlock->functionDecl(currentInstruction[2].u.operand)));
528     stubCall.call(currentInstruction[1].u.operand);
529 }
530 
emit_op_get_global_var(Instruction * currentInstruction)531 void JIT::emit_op_get_global_var(Instruction* currentInstruction)
532 {
533     int dst = currentInstruction[1].u.operand;
534     JSGlobalObject* globalObject = static_cast<JSGlobalObject*>(currentInstruction[2].u.jsCell);
535     ASSERT(globalObject->isGlobalObject());
536     int index = currentInstruction[3].u.operand;
537 
538     loadPtr(&globalObject->d()->registers, regT2);
539 
540     emitLoad(index, regT1, regT0, regT2);
541     emitStore(dst, regT1, regT0);
542     map(m_bytecodeIndex + OPCODE_LENGTH(op_get_global_var), dst, regT1, regT0);
543 }
544 
emit_op_put_global_var(Instruction * currentInstruction)545 void JIT::emit_op_put_global_var(Instruction* currentInstruction)
546 {
547     JSGlobalObject* globalObject = static_cast<JSGlobalObject*>(currentInstruction[1].u.jsCell);
548     ASSERT(globalObject->isGlobalObject());
549     int index = currentInstruction[2].u.operand;
550     int value = currentInstruction[3].u.operand;
551 
552     emitLoad(value, regT1, regT0);
553 
554     loadPtr(&globalObject->d()->registers, regT2);
555     emitStore(index, regT1, regT0, regT2);
556     map(m_bytecodeIndex + OPCODE_LENGTH(op_put_global_var), value, regT1, regT0);
557 }
558 
emit_op_get_scoped_var(Instruction * currentInstruction)559 void JIT::emit_op_get_scoped_var(Instruction* currentInstruction)
560 {
561     int dst = currentInstruction[1].u.operand;
562     int index = currentInstruction[2].u.operand;
563     int skip = currentInstruction[3].u.operand + m_codeBlock->needsFullScopeChain();
564 
565     emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT2);
566     while (skip--)
567         loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2);
568 
569     loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, object)), regT2);
570     loadPtr(Address(regT2, OBJECT_OFFSETOF(JSVariableObject, d)), regT2);
571     loadPtr(Address(regT2, OBJECT_OFFSETOF(JSVariableObject::JSVariableObjectData, registers)), regT2);
572 
573     emitLoad(index, regT1, regT0, regT2);
574     emitStore(dst, regT1, regT0);
575     map(m_bytecodeIndex + OPCODE_LENGTH(op_get_scoped_var), dst, regT1, regT0);
576 }
577 
emit_op_put_scoped_var(Instruction * currentInstruction)578 void JIT::emit_op_put_scoped_var(Instruction* currentInstruction)
579 {
580     int index = currentInstruction[1].u.operand;
581     int skip = currentInstruction[2].u.operand + m_codeBlock->needsFullScopeChain();
582     int value = currentInstruction[3].u.operand;
583 
584     emitLoad(value, regT1, regT0);
585 
586     emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT2);
587     while (skip--)
588         loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2);
589 
590     loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, object)), regT2);
591     loadPtr(Address(regT2, OBJECT_OFFSETOF(JSVariableObject, d)), regT2);
592     loadPtr(Address(regT2, OBJECT_OFFSETOF(JSVariableObject::JSVariableObjectData, registers)), regT2);
593 
594     emitStore(index, regT1, regT0, regT2);
595     map(m_bytecodeIndex + OPCODE_LENGTH(op_put_scoped_var), value, regT1, regT0);
596 }
597 
emit_op_tear_off_activation(Instruction * currentInstruction)598 void JIT::emit_op_tear_off_activation(Instruction* currentInstruction)
599 {
600     JITStubCall stubCall(this, cti_op_tear_off_activation);
601     stubCall.addArgument(currentInstruction[1].u.operand);
602     stubCall.call();
603 }
604 
emit_op_tear_off_arguments(Instruction *)605 void JIT::emit_op_tear_off_arguments(Instruction*)
606 {
607     JITStubCall(this, cti_op_tear_off_arguments).call();
608 }
609 
emit_op_new_array(Instruction * currentInstruction)610 void JIT::emit_op_new_array(Instruction* currentInstruction)
611 {
612     JITStubCall stubCall(this, cti_op_new_array);
613     stubCall.addArgument(Imm32(currentInstruction[2].u.operand));
614     stubCall.addArgument(Imm32(currentInstruction[3].u.operand));
615     stubCall.call(currentInstruction[1].u.operand);
616 }
617 
emit_op_resolve(Instruction * currentInstruction)618 void JIT::emit_op_resolve(Instruction* currentInstruction)
619 {
620     JITStubCall stubCall(this, cti_op_resolve);
621     stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
622     stubCall.call(currentInstruction[1].u.operand);
623 }
624 
emit_op_to_primitive(Instruction * currentInstruction)625 void JIT::emit_op_to_primitive(Instruction* currentInstruction)
626 {
627     int dst = currentInstruction[1].u.operand;
628     int src = currentInstruction[2].u.operand;
629 
630     emitLoad(src, regT1, regT0);
631 
632     Jump isImm = branch32(NotEqual, regT1, Imm32(JSValue::CellTag));
633     addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr)));
634     isImm.link(this);
635 
636     if (dst != src)
637         emitStore(dst, regT1, regT0);
638     map(m_bytecodeIndex + OPCODE_LENGTH(op_to_primitive), dst, regT1, regT0);
639 }
640 
emitSlow_op_to_primitive(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)641 void JIT::emitSlow_op_to_primitive(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
642 {
643     int dst = currentInstruction[1].u.operand;
644 
645     linkSlowCase(iter);
646 
647     JITStubCall stubCall(this, cti_op_to_primitive);
648     stubCall.addArgument(regT1, regT0);
649     stubCall.call(dst);
650 }
651 
emit_op_strcat(Instruction * currentInstruction)652 void JIT::emit_op_strcat(Instruction* currentInstruction)
653 {
654     JITStubCall stubCall(this, cti_op_strcat);
655     stubCall.addArgument(Imm32(currentInstruction[2].u.operand));
656     stubCall.addArgument(Imm32(currentInstruction[3].u.operand));
657     stubCall.call(currentInstruction[1].u.operand);
658 }
659 
emit_op_resolve_base(Instruction * currentInstruction)660 void JIT::emit_op_resolve_base(Instruction* currentInstruction)
661 {
662     JITStubCall stubCall(this, cti_op_resolve_base);
663     stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
664     stubCall.call(currentInstruction[1].u.operand);
665 }
666 
emit_op_resolve_skip(Instruction * currentInstruction)667 void JIT::emit_op_resolve_skip(Instruction* currentInstruction)
668 {
669     JITStubCall stubCall(this, cti_op_resolve_skip);
670     stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
671     stubCall.addArgument(Imm32(currentInstruction[3].u.operand + m_codeBlock->needsFullScopeChain()));
672     stubCall.call(currentInstruction[1].u.operand);
673 }
674 
emit_op_resolve_global(Instruction * currentInstruction)675 void JIT::emit_op_resolve_global(Instruction* currentInstruction)
676 {
677     // FIXME: Optimize to use patching instead of so many memory accesses.
678 
679     unsigned dst = currentInstruction[1].u.operand;
680     void* globalObject = currentInstruction[2].u.jsCell;
681 
682     unsigned currentIndex = m_globalResolveInfoIndex++;
683     void* structureAddress = &(m_codeBlock->globalResolveInfo(currentIndex).structure);
684     void* offsetAddr = &(m_codeBlock->globalResolveInfo(currentIndex).offset);
685 
686     // Verify structure.
687     move(ImmPtr(globalObject), regT0);
688     loadPtr(structureAddress, regT1);
689     addSlowCase(branchPtr(NotEqual, regT1, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure))));
690 
691     // Load property.
692     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSGlobalObject, m_externalStorage)), regT2);
693     load32(offsetAddr, regT3);
694     load32(BaseIndex(regT2, regT3, TimesEight), regT0); // payload
695     load32(BaseIndex(regT2, regT3, TimesEight, 4), regT1); // tag
696     emitStore(dst, regT1, regT0);
697     map(m_bytecodeIndex + OPCODE_LENGTH(op_resolve_global), dst, regT1, regT0);
698 }
699 
emitSlow_op_resolve_global(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)700 void JIT::emitSlow_op_resolve_global(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
701 {
702     unsigned dst = currentInstruction[1].u.operand;
703     void* globalObject = currentInstruction[2].u.jsCell;
704     Identifier* ident = &m_codeBlock->identifier(currentInstruction[3].u.operand);
705 
706     unsigned currentIndex = m_globalResolveInfoIndex++;
707 
708     linkSlowCase(iter);
709     JITStubCall stubCall(this, cti_op_resolve_global);
710     stubCall.addArgument(ImmPtr(globalObject));
711     stubCall.addArgument(ImmPtr(ident));
712     stubCall.addArgument(Imm32(currentIndex));
713     stubCall.call(dst);
714 }
715 
emit_op_not(Instruction * currentInstruction)716 void JIT::emit_op_not(Instruction* currentInstruction)
717 {
718     unsigned dst = currentInstruction[1].u.operand;
719     unsigned src = currentInstruction[2].u.operand;
720 
721     emitLoadTag(src, regT0);
722 
723     xor32(Imm32(JSValue::FalseTag), regT0);
724     addSlowCase(branchTest32(NonZero, regT0, Imm32(~1)));
725     xor32(Imm32(JSValue::TrueTag), regT0);
726 
727     emitStoreBool(dst, regT0, (dst == src));
728 }
729 
emitSlow_op_not(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)730 void JIT::emitSlow_op_not(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
731 {
732     unsigned dst = currentInstruction[1].u.operand;
733     unsigned src = currentInstruction[2].u.operand;
734 
735     linkSlowCase(iter);
736 
737     JITStubCall stubCall(this, cti_op_not);
738     stubCall.addArgument(src);
739     stubCall.call(dst);
740 }
741 
emit_op_jfalse(Instruction * currentInstruction)742 void JIT::emit_op_jfalse(Instruction* currentInstruction)
743 {
744     unsigned cond = currentInstruction[1].u.operand;
745     unsigned target = currentInstruction[2].u.operand;
746 
747     emitLoad(cond, regT1, regT0);
748 
749     Jump isTrue = branch32(Equal, regT1, Imm32(JSValue::TrueTag));
750     addJump(branch32(Equal, regT1, Imm32(JSValue::FalseTag)), target);
751 
752     Jump isNotInteger = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag));
753     Jump isTrue2 = branch32(NotEqual, regT0, Imm32(0));
754     addJump(jump(), target);
755 
756     if (supportsFloatingPoint()) {
757         isNotInteger.link(this);
758 
759         addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag)));
760 
761         zeroDouble(fpRegT0);
762         emitLoadDouble(cond, fpRegT1);
763         addJump(branchDouble(DoubleEqualOrUnordered, fpRegT0, fpRegT1), target);
764     } else
765         addSlowCase(isNotInteger);
766 
767     isTrue.link(this);
768     isTrue2.link(this);
769 }
770 
emitSlow_op_jfalse(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)771 void JIT::emitSlow_op_jfalse(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
772 {
773     unsigned cond = currentInstruction[1].u.operand;
774     unsigned target = currentInstruction[2].u.operand;
775 
776     linkSlowCase(iter);
777     JITStubCall stubCall(this, cti_op_jtrue);
778     stubCall.addArgument(cond);
779     stubCall.call();
780     emitJumpSlowToHot(branchTest32(Zero, regT0), target); // Inverted.
781 }
782 
emit_op_jtrue(Instruction * currentInstruction)783 void JIT::emit_op_jtrue(Instruction* currentInstruction)
784 {
785     unsigned cond = currentInstruction[1].u.operand;
786     unsigned target = currentInstruction[2].u.operand;
787 
788     emitLoad(cond, regT1, regT0);
789 
790     Jump isFalse = branch32(Equal, regT1, Imm32(JSValue::FalseTag));
791     addJump(branch32(Equal, regT1, Imm32(JSValue::TrueTag)), target);
792 
793     Jump isNotInteger = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag));
794     Jump isFalse2 = branch32(Equal, regT0, Imm32(0));
795     addJump(jump(), target);
796 
797     if (supportsFloatingPoint()) {
798         isNotInteger.link(this);
799 
800         addSlowCase(branch32(Above, regT1, Imm32(JSValue::LowestTag)));
801 
802         zeroDouble(fpRegT0);
803         emitLoadDouble(cond, fpRegT1);
804         addJump(branchDouble(DoubleNotEqual, fpRegT0, fpRegT1), target);
805     } else
806         addSlowCase(isNotInteger);
807 
808     isFalse.link(this);
809     isFalse2.link(this);
810 }
811 
emitSlow_op_jtrue(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)812 void JIT::emitSlow_op_jtrue(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
813 {
814     unsigned cond = currentInstruction[1].u.operand;
815     unsigned target = currentInstruction[2].u.operand;
816 
817     linkSlowCase(iter);
818     JITStubCall stubCall(this, cti_op_jtrue);
819     stubCall.addArgument(cond);
820     stubCall.call();
821     emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
822 }
823 
emit_op_jeq_null(Instruction * currentInstruction)824 void JIT::emit_op_jeq_null(Instruction* currentInstruction)
825 {
826     unsigned src = currentInstruction[1].u.operand;
827     unsigned target = currentInstruction[2].u.operand;
828 
829     emitLoad(src, regT1, regT0);
830 
831     Jump isImmediate = branch32(NotEqual, regT1, Imm32(JSValue::CellTag));
832 
833     // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure.
834     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
835     addJump(branchTest32(NonZero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target);
836 
837     Jump wasNotImmediate = jump();
838 
839     // Now handle the immediate cases - undefined & null
840     isImmediate.link(this);
841 
842     set32(Equal, regT1, Imm32(JSValue::NullTag), regT2);
843     set32(Equal, regT1, Imm32(JSValue::UndefinedTag), regT1);
844     or32(regT2, regT1);
845 
846     addJump(branchTest32(NonZero, regT1), target);
847 
848     wasNotImmediate.link(this);
849 }
850 
emit_op_jneq_null(Instruction * currentInstruction)851 void JIT::emit_op_jneq_null(Instruction* currentInstruction)
852 {
853     unsigned src = currentInstruction[1].u.operand;
854     unsigned target = currentInstruction[2].u.operand;
855 
856     emitLoad(src, regT1, regT0);
857 
858     Jump isImmediate = branch32(NotEqual, regT1, Imm32(JSValue::CellTag));
859 
860     // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure.
861     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
862     addJump(branchTest32(Zero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target);
863 
864     Jump wasNotImmediate = jump();
865 
866     // Now handle the immediate cases - undefined & null
867     isImmediate.link(this);
868 
869     set32(Equal, regT1, Imm32(JSValue::NullTag), regT2);
870     set32(Equal, regT1, Imm32(JSValue::UndefinedTag), regT1);
871     or32(regT2, regT1);
872 
873     addJump(branchTest32(Zero, regT1), target);
874 
875     wasNotImmediate.link(this);
876 }
877 
emit_op_jneq_ptr(Instruction * currentInstruction)878 void JIT::emit_op_jneq_ptr(Instruction* currentInstruction)
879 {
880     unsigned src = currentInstruction[1].u.operand;
881     JSCell* ptr = currentInstruction[2].u.jsCell;
882     unsigned target = currentInstruction[3].u.operand;
883 
884     emitLoad(src, regT1, regT0);
885     addJump(branch32(NotEqual, regT1, Imm32(JSValue::CellTag)), target);
886     addJump(branchPtr(NotEqual, regT0, ImmPtr(ptr)), target);
887 }
888 
emit_op_jsr(Instruction * currentInstruction)889 void JIT::emit_op_jsr(Instruction* currentInstruction)
890 {
891     int retAddrDst = currentInstruction[1].u.operand;
892     int target = currentInstruction[2].u.operand;
893     DataLabelPtr storeLocation = storePtrWithPatch(ImmPtr(0), Address(callFrameRegister, sizeof(Register) * retAddrDst));
894     addJump(jump(), target);
895     m_jsrSites.append(JSRInfo(storeLocation, label()));
896 }
897 
emit_op_sret(Instruction * currentInstruction)898 void JIT::emit_op_sret(Instruction* currentInstruction)
899 {
900     jump(Address(callFrameRegister, sizeof(Register) * currentInstruction[1].u.operand));
901 }
902 
emit_op_eq(Instruction * currentInstruction)903 void JIT::emit_op_eq(Instruction* currentInstruction)
904 {
905     unsigned dst = currentInstruction[1].u.operand;
906     unsigned src1 = currentInstruction[2].u.operand;
907     unsigned src2 = currentInstruction[3].u.operand;
908 
909     emitLoad2(src1, regT1, regT0, src2, regT3, regT2);
910     addSlowCase(branch32(NotEqual, regT1, regT3));
911     addSlowCase(branch32(Equal, regT1, Imm32(JSValue::CellTag)));
912     addSlowCase(branch32(Below, regT1, Imm32(JSValue::LowestTag)));
913 
914     set8(Equal, regT0, regT2, regT0);
915     or32(Imm32(JSValue::FalseTag), regT0);
916 
917     emitStoreBool(dst, regT0);
918 }
919 
emitSlow_op_eq(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)920 void JIT::emitSlow_op_eq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
921 {
922     unsigned dst = currentInstruction[1].u.operand;
923     unsigned op1 = currentInstruction[2].u.operand;
924     unsigned op2 = currentInstruction[3].u.operand;
925 
926     JumpList storeResult;
927     JumpList genericCase;
928 
929     genericCase.append(getSlowCase(iter)); // tags not equal
930 
931     linkSlowCase(iter); // tags equal and JSCell
932     genericCase.append(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr)));
933     genericCase.append(branchPtr(NotEqual, Address(regT2), ImmPtr(m_globalData->jsStringVPtr)));
934 
935     // String case.
936     JITStubCall stubCallEqStrings(this, cti_op_eq_strings);
937     stubCallEqStrings.addArgument(regT0);
938     stubCallEqStrings.addArgument(regT2);
939     stubCallEqStrings.call();
940     storeResult.append(jump());
941 
942     // Generic case.
943     genericCase.append(getSlowCase(iter)); // doubles
944     genericCase.link(this);
945     JITStubCall stubCallEq(this, cti_op_eq);
946     stubCallEq.addArgument(op1);
947     stubCallEq.addArgument(op2);
948     stubCallEq.call(regT0);
949 
950     storeResult.link(this);
951     or32(Imm32(JSValue::FalseTag), regT0);
952     emitStoreBool(dst, regT0);
953 }
954 
emit_op_neq(Instruction * currentInstruction)955 void JIT::emit_op_neq(Instruction* currentInstruction)
956 {
957     unsigned dst = currentInstruction[1].u.operand;
958     unsigned src1 = currentInstruction[2].u.operand;
959     unsigned src2 = currentInstruction[3].u.operand;
960 
961     emitLoad2(src1, regT1, regT0, src2, regT3, regT2);
962     addSlowCase(branch32(NotEqual, regT1, regT3));
963     addSlowCase(branch32(Equal, regT1, Imm32(JSValue::CellTag)));
964     addSlowCase(branch32(Below, regT1, Imm32(JSValue::LowestTag)));
965 
966     set8(NotEqual, regT0, regT2, regT0);
967     or32(Imm32(JSValue::FalseTag), regT0);
968 
969     emitStoreBool(dst, regT0);
970 }
971 
emitSlow_op_neq(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)972 void JIT::emitSlow_op_neq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
973 {
974     unsigned dst = currentInstruction[1].u.operand;
975 
976     JumpList storeResult;
977     JumpList genericCase;
978 
979     genericCase.append(getSlowCase(iter)); // tags not equal
980 
981     linkSlowCase(iter); // tags equal and JSCell
982     genericCase.append(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr)));
983     genericCase.append(branchPtr(NotEqual, Address(regT2), ImmPtr(m_globalData->jsStringVPtr)));
984 
985     // String case.
986     JITStubCall stubCallEqStrings(this, cti_op_eq_strings);
987     stubCallEqStrings.addArgument(regT0);
988     stubCallEqStrings.addArgument(regT2);
989     stubCallEqStrings.call(regT0);
990     storeResult.append(jump());
991 
992     // Generic case.
993     genericCase.append(getSlowCase(iter)); // doubles
994     genericCase.link(this);
995     JITStubCall stubCallEq(this, cti_op_eq);
996     stubCallEq.addArgument(regT1, regT0);
997     stubCallEq.addArgument(regT3, regT2);
998     stubCallEq.call(regT0);
999 
1000     storeResult.link(this);
1001     xor32(Imm32(0x1), regT0);
1002     or32(Imm32(JSValue::FalseTag), regT0);
1003     emitStoreBool(dst, regT0);
1004 }
1005 
compileOpStrictEq(Instruction * currentInstruction,CompileOpStrictEqType type)1006 void JIT::compileOpStrictEq(Instruction* currentInstruction, CompileOpStrictEqType type)
1007 {
1008     unsigned dst = currentInstruction[1].u.operand;
1009     unsigned src1 = currentInstruction[2].u.operand;
1010     unsigned src2 = currentInstruction[3].u.operand;
1011 
1012     emitLoadTag(src1, regT0);
1013     emitLoadTag(src2, regT1);
1014 
1015     // Jump to a slow case if either operand is double, or if both operands are
1016     // cells and/or Int32s.
1017     move(regT0, regT2);
1018     and32(regT1, regT2);
1019     addSlowCase(branch32(Below, regT2, Imm32(JSValue::LowestTag)));
1020     addSlowCase(branch32(AboveOrEqual, regT2, Imm32(JSValue::CellTag)));
1021 
1022     if (type == OpStrictEq)
1023         set8(Equal, regT0, regT1, regT0);
1024     else
1025         set8(NotEqual, regT0, regT1, regT0);
1026 
1027     or32(Imm32(JSValue::FalseTag), regT0);
1028 
1029     emitStoreBool(dst, regT0);
1030 }
1031 
emit_op_stricteq(Instruction * currentInstruction)1032 void JIT::emit_op_stricteq(Instruction* currentInstruction)
1033 {
1034     compileOpStrictEq(currentInstruction, OpStrictEq);
1035 }
1036 
emitSlow_op_stricteq(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)1037 void JIT::emitSlow_op_stricteq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1038 {
1039     unsigned dst = currentInstruction[1].u.operand;
1040     unsigned src1 = currentInstruction[2].u.operand;
1041     unsigned src2 = currentInstruction[3].u.operand;
1042 
1043     linkSlowCase(iter);
1044     linkSlowCase(iter);
1045 
1046     JITStubCall stubCall(this, cti_op_stricteq);
1047     stubCall.addArgument(src1);
1048     stubCall.addArgument(src2);
1049     stubCall.call(dst);
1050 }
1051 
emit_op_nstricteq(Instruction * currentInstruction)1052 void JIT::emit_op_nstricteq(Instruction* currentInstruction)
1053 {
1054     compileOpStrictEq(currentInstruction, OpNStrictEq);
1055 }
1056 
emitSlow_op_nstricteq(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)1057 void JIT::emitSlow_op_nstricteq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1058 {
1059     unsigned dst = currentInstruction[1].u.operand;
1060     unsigned src1 = currentInstruction[2].u.operand;
1061     unsigned src2 = currentInstruction[3].u.operand;
1062 
1063     linkSlowCase(iter);
1064     linkSlowCase(iter);
1065 
1066     JITStubCall stubCall(this, cti_op_nstricteq);
1067     stubCall.addArgument(src1);
1068     stubCall.addArgument(src2);
1069     stubCall.call(dst);
1070 }
1071 
emit_op_eq_null(Instruction * currentInstruction)1072 void JIT::emit_op_eq_null(Instruction* currentInstruction)
1073 {
1074     unsigned dst = currentInstruction[1].u.operand;
1075     unsigned src = currentInstruction[2].u.operand;
1076 
1077     emitLoad(src, regT1, regT0);
1078     Jump isImmediate = branch32(NotEqual, regT1, Imm32(JSValue::CellTag));
1079 
1080     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT1);
1081     setTest8(NonZero, Address(regT1, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined), regT1);
1082 
1083     Jump wasNotImmediate = jump();
1084 
1085     isImmediate.link(this);
1086 
1087     set8(Equal, regT1, Imm32(JSValue::NullTag), regT2);
1088     set8(Equal, regT1, Imm32(JSValue::UndefinedTag), regT1);
1089     or32(regT2, regT1);
1090 
1091     wasNotImmediate.link(this);
1092 
1093     or32(Imm32(JSValue::FalseTag), regT1);
1094 
1095     emitStoreBool(dst, regT1);
1096 }
1097 
emit_op_neq_null(Instruction * currentInstruction)1098 void JIT::emit_op_neq_null(Instruction* currentInstruction)
1099 {
1100     unsigned dst = currentInstruction[1].u.operand;
1101     unsigned src = currentInstruction[2].u.operand;
1102 
1103     emitLoad(src, regT1, regT0);
1104     Jump isImmediate = branch32(NotEqual, regT1, Imm32(JSValue::CellTag));
1105 
1106     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT1);
1107     setTest8(Zero, Address(regT1, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined), regT1);
1108 
1109     Jump wasNotImmediate = jump();
1110 
1111     isImmediate.link(this);
1112 
1113     set8(NotEqual, regT1, Imm32(JSValue::NullTag), regT2);
1114     set8(NotEqual, regT1, Imm32(JSValue::UndefinedTag), regT1);
1115     and32(regT2, regT1);
1116 
1117     wasNotImmediate.link(this);
1118 
1119     or32(Imm32(JSValue::FalseTag), regT1);
1120 
1121     emitStoreBool(dst, regT1);
1122 }
1123 
emit_op_resolve_with_base(Instruction * currentInstruction)1124 void JIT::emit_op_resolve_with_base(Instruction* currentInstruction)
1125 {
1126     JITStubCall stubCall(this, cti_op_resolve_with_base);
1127     stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand)));
1128     stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
1129     stubCall.call(currentInstruction[2].u.operand);
1130 }
1131 
emit_op_new_func_exp(Instruction * currentInstruction)1132 void JIT::emit_op_new_func_exp(Instruction* currentInstruction)
1133 {
1134     JITStubCall stubCall(this, cti_op_new_func_exp);
1135     stubCall.addArgument(ImmPtr(m_codeBlock->functionExpr(currentInstruction[2].u.operand)));
1136     stubCall.call(currentInstruction[1].u.operand);
1137 }
1138 
emit_op_new_regexp(Instruction * currentInstruction)1139 void JIT::emit_op_new_regexp(Instruction* currentInstruction)
1140 {
1141     JITStubCall stubCall(this, cti_op_new_regexp);
1142     stubCall.addArgument(ImmPtr(m_codeBlock->regexp(currentInstruction[2].u.operand)));
1143     stubCall.call(currentInstruction[1].u.operand);
1144 }
1145 
emit_op_throw(Instruction * currentInstruction)1146 void JIT::emit_op_throw(Instruction* currentInstruction)
1147 {
1148     unsigned exception = currentInstruction[1].u.operand;
1149     JITStubCall stubCall(this, cti_op_throw);
1150     stubCall.addArgument(exception);
1151     stubCall.call();
1152 
1153 #ifndef NDEBUG
1154     // cti_op_throw always changes it's return address,
1155     // this point in the code should never be reached.
1156     breakpoint();
1157 #endif
1158 }
1159 
emit_op_get_pnames(Instruction * currentInstruction)1160 void JIT::emit_op_get_pnames(Instruction* currentInstruction)
1161 {
1162     int dst = currentInstruction[1].u.operand;
1163     int base = currentInstruction[2].u.operand;
1164     int i = currentInstruction[3].u.operand;
1165     int size = currentInstruction[4].u.operand;
1166     int breakTarget = currentInstruction[5].u.operand;
1167 
1168     JumpList isNotObject;
1169 
1170     emitLoad(base, regT1, regT0);
1171     if (!m_codeBlock->isKnownNotImmediate(base))
1172         isNotObject.append(branch32(NotEqual, regT1, Imm32(JSValue::CellTag)));
1173     if (base != m_codeBlock->thisRegister()) {
1174         loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
1175         isNotObject.append(branch32(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType)));
1176     }
1177 
1178     // We could inline the case where you have a valid cache, but
1179     // this call doesn't seem to be hot.
1180     Label isObject(this);
1181     JITStubCall getPnamesStubCall(this, cti_op_get_pnames);
1182     getPnamesStubCall.addArgument(regT0);
1183     getPnamesStubCall.call(dst);
1184     load32(Address(regT0, OBJECT_OFFSETOF(JSPropertyNameIterator, m_jsStringsSize)), regT3);
1185     store32(Imm32(0), addressFor(i));
1186     store32(regT3, addressFor(size));
1187     Jump end = jump();
1188 
1189     isNotObject.link(this);
1190     addJump(branch32(Equal, regT1, Imm32(JSValue::NullTag)), breakTarget);
1191     addJump(branch32(Equal, regT1, Imm32(JSValue::UndefinedTag)), breakTarget);
1192     JITStubCall toObjectStubCall(this, cti_to_object);
1193     toObjectStubCall.addArgument(regT1, regT0);
1194     toObjectStubCall.call(base);
1195     jump().linkTo(isObject, this);
1196 
1197     end.link(this);
1198 }
1199 
emit_op_next_pname(Instruction * currentInstruction)1200 void JIT::emit_op_next_pname(Instruction* currentInstruction)
1201 {
1202     int dst = currentInstruction[1].u.operand;
1203     int base = currentInstruction[2].u.operand;
1204     int i = currentInstruction[3].u.operand;
1205     int size = currentInstruction[4].u.operand;
1206     int it = currentInstruction[5].u.operand;
1207     int target = currentInstruction[6].u.operand;
1208 
1209     JumpList callHasProperty;
1210 
1211     Label begin(this);
1212     load32(addressFor(i), regT0);
1213     Jump end = branch32(Equal, regT0, addressFor(size));
1214 
1215     // Grab key @ i
1216     loadPtr(addressFor(it), regT1);
1217     loadPtr(Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_jsStrings)), regT2);
1218     load32(BaseIndex(regT2, regT0, TimesEight), regT2);
1219     store32(Imm32(JSValue::CellTag), tagFor(dst));
1220     store32(regT2, payloadFor(dst));
1221 
1222     // Increment i
1223     add32(Imm32(1), regT0);
1224     store32(regT0, addressFor(i));
1225 
1226     // Verify that i is valid:
1227     loadPtr(addressFor(base), regT0);
1228 
1229     // Test base's structure
1230     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
1231     callHasProperty.append(branchPtr(NotEqual, regT2, Address(Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_cachedStructure)))));
1232 
1233     // Test base's prototype chain
1234     loadPtr(Address(Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_cachedPrototypeChain))), regT3);
1235     loadPtr(Address(regT3, OBJECT_OFFSETOF(StructureChain, m_vector)), regT3);
1236     addJump(branchTestPtr(Zero, Address(regT3)), target);
1237 
1238     Label checkPrototype(this);
1239     callHasProperty.append(branch32(Equal, Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), Imm32(JSValue::NullTag)));
1240     loadPtr(Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT2);
1241     loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
1242     callHasProperty.append(branchPtr(NotEqual, regT2, Address(regT3)));
1243     addPtr(Imm32(sizeof(Structure*)), regT3);
1244     branchTestPtr(NonZero, Address(regT3)).linkTo(checkPrototype, this);
1245 
1246     // Continue loop.
1247     addJump(jump(), target);
1248 
1249     // Slow case: Ask the object if i is valid.
1250     callHasProperty.link(this);
1251     loadPtr(addressFor(dst), regT1);
1252     JITStubCall stubCall(this, cti_has_property);
1253     stubCall.addArgument(regT0);
1254     stubCall.addArgument(regT1);
1255     stubCall.call();
1256 
1257     // Test for valid key.
1258     addJump(branchTest32(NonZero, regT0), target);
1259     jump().linkTo(begin, this);
1260 
1261     // End of loop.
1262     end.link(this);
1263 }
1264 
emit_op_push_scope(Instruction * currentInstruction)1265 void JIT::emit_op_push_scope(Instruction* currentInstruction)
1266 {
1267     JITStubCall stubCall(this, cti_op_push_scope);
1268     stubCall.addArgument(currentInstruction[1].u.operand);
1269     stubCall.call(currentInstruction[1].u.operand);
1270 }
1271 
emit_op_pop_scope(Instruction *)1272 void JIT::emit_op_pop_scope(Instruction*)
1273 {
1274     JITStubCall(this, cti_op_pop_scope).call();
1275 }
1276 
emit_op_to_jsnumber(Instruction * currentInstruction)1277 void JIT::emit_op_to_jsnumber(Instruction* currentInstruction)
1278 {
1279     int dst = currentInstruction[1].u.operand;
1280     int src = currentInstruction[2].u.operand;
1281 
1282     emitLoad(src, regT1, regT0);
1283 
1284     Jump isInt32 = branch32(Equal, regT1, Imm32(JSValue::Int32Tag));
1285     addSlowCase(branch32(AboveOrEqual, regT1, Imm32(JSValue::EmptyValueTag)));
1286     isInt32.link(this);
1287 
1288     if (src != dst)
1289         emitStore(dst, regT1, regT0);
1290     map(m_bytecodeIndex + OPCODE_LENGTH(op_to_jsnumber), dst, regT1, regT0);
1291 }
1292 
emitSlow_op_to_jsnumber(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)1293 void JIT::emitSlow_op_to_jsnumber(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1294 {
1295     int dst = currentInstruction[1].u.operand;
1296 
1297     linkSlowCase(iter);
1298 
1299     JITStubCall stubCall(this, cti_op_to_jsnumber);
1300     stubCall.addArgument(regT1, regT0);
1301     stubCall.call(dst);
1302 }
1303 
emit_op_push_new_scope(Instruction * currentInstruction)1304 void JIT::emit_op_push_new_scope(Instruction* currentInstruction)
1305 {
1306     JITStubCall stubCall(this, cti_op_push_new_scope);
1307     stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
1308     stubCall.addArgument(currentInstruction[3].u.operand);
1309     stubCall.call(currentInstruction[1].u.operand);
1310 }
1311 
emit_op_catch(Instruction * currentInstruction)1312 void JIT::emit_op_catch(Instruction* currentInstruction)
1313 {
1314     unsigned exception = currentInstruction[1].u.operand;
1315 
1316     // This opcode only executes after a return from cti_op_throw.
1317 
1318     // cti_op_throw may have taken us to a call frame further up the stack; reload
1319     // the call frame pointer to adjust.
1320     peek(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof (void*));
1321 
1322     // Now store the exception returned by cti_op_throw.
1323     emitStore(exception, regT1, regT0);
1324     map(m_bytecodeIndex + OPCODE_LENGTH(op_catch), exception, regT1, regT0);
1325 #ifdef QT_BUILD_SCRIPT_LIB
1326     JITStubCall stubCall(this, cti_op_debug_catch);
1327     stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
1328     stubCall.call();
1329 #endif
1330 }
1331 
emit_op_jmp_scopes(Instruction * currentInstruction)1332 void JIT::emit_op_jmp_scopes(Instruction* currentInstruction)
1333 {
1334     JITStubCall stubCall(this, cti_op_jmp_scopes);
1335     stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
1336     stubCall.call();
1337     addJump(jump(), currentInstruction[2].u.operand);
1338 }
1339 
emit_op_switch_imm(Instruction * currentInstruction)1340 void JIT::emit_op_switch_imm(Instruction* currentInstruction)
1341 {
1342     unsigned tableIndex = currentInstruction[1].u.operand;
1343     unsigned defaultOffset = currentInstruction[2].u.operand;
1344     unsigned scrutinee = currentInstruction[3].u.operand;
1345 
1346     // create jump table for switch destinations, track this switch statement.
1347     SimpleJumpTable* jumpTable = &m_codeBlock->immediateSwitchJumpTable(tableIndex);
1348     m_switches.append(SwitchRecord(jumpTable, m_bytecodeIndex, defaultOffset, SwitchRecord::Immediate));
1349     jumpTable->ctiOffsets.grow(jumpTable->branchOffsets.size());
1350 
1351     JITStubCall stubCall(this, cti_op_switch_imm);
1352     stubCall.addArgument(scrutinee);
1353     stubCall.addArgument(Imm32(tableIndex));
1354     stubCall.call();
1355     jump(regT0);
1356 }
1357 
emit_op_switch_char(Instruction * currentInstruction)1358 void JIT::emit_op_switch_char(Instruction* currentInstruction)
1359 {
1360     unsigned tableIndex = currentInstruction[1].u.operand;
1361     unsigned defaultOffset = currentInstruction[2].u.operand;
1362     unsigned scrutinee = currentInstruction[3].u.operand;
1363 
1364     // create jump table for switch destinations, track this switch statement.
1365     SimpleJumpTable* jumpTable = &m_codeBlock->characterSwitchJumpTable(tableIndex);
1366     m_switches.append(SwitchRecord(jumpTable, m_bytecodeIndex, defaultOffset, SwitchRecord::Character));
1367     jumpTable->ctiOffsets.grow(jumpTable->branchOffsets.size());
1368 
1369     JITStubCall stubCall(this, cti_op_switch_char);
1370     stubCall.addArgument(scrutinee);
1371     stubCall.addArgument(Imm32(tableIndex));
1372     stubCall.call();
1373     jump(regT0);
1374 }
1375 
emit_op_switch_string(Instruction * currentInstruction)1376 void JIT::emit_op_switch_string(Instruction* currentInstruction)
1377 {
1378     unsigned tableIndex = currentInstruction[1].u.operand;
1379     unsigned defaultOffset = currentInstruction[2].u.operand;
1380     unsigned scrutinee = currentInstruction[3].u.operand;
1381 
1382     // create jump table for switch destinations, track this switch statement.
1383     StringJumpTable* jumpTable = &m_codeBlock->stringSwitchJumpTable(tableIndex);
1384     m_switches.append(SwitchRecord(jumpTable, m_bytecodeIndex, defaultOffset));
1385 
1386     JITStubCall stubCall(this, cti_op_switch_string);
1387     stubCall.addArgument(scrutinee);
1388     stubCall.addArgument(Imm32(tableIndex));
1389     stubCall.call();
1390     jump(regT0);
1391 }
1392 
emit_op_new_error(Instruction * currentInstruction)1393 void JIT::emit_op_new_error(Instruction* currentInstruction)
1394 {
1395     unsigned dst = currentInstruction[1].u.operand;
1396     unsigned type = currentInstruction[2].u.operand;
1397     unsigned message = currentInstruction[3].u.operand;
1398 
1399     JITStubCall stubCall(this, cti_op_new_error);
1400     stubCall.addArgument(Imm32(type));
1401     stubCall.addArgument(m_codeBlock->getConstant(message));
1402     stubCall.addArgument(Imm32(m_bytecodeIndex));
1403     stubCall.call(dst);
1404 }
1405 
emit_op_debug(Instruction * currentInstruction)1406 void JIT::emit_op_debug(Instruction* currentInstruction)
1407 {
1408     JITStubCall stubCall(this, cti_op_debug);
1409     stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
1410     stubCall.addArgument(Imm32(currentInstruction[2].u.operand));
1411     stubCall.addArgument(Imm32(currentInstruction[3].u.operand));
1412     stubCall.call();
1413 }
1414 
1415 
emit_op_enter(Instruction *)1416 void JIT::emit_op_enter(Instruction*)
1417 {
1418     // Even though JIT code doesn't use them, we initialize our constant
1419     // registers to zap stale pointers, to avoid unnecessarily prolonging
1420     // object lifetime and increasing GC pressure.
1421     for (int i = 0; i < m_codeBlock->m_numVars; ++i)
1422         emitStore(i, jsUndefined());
1423 }
1424 
emit_op_enter_with_activation(Instruction * currentInstruction)1425 void JIT::emit_op_enter_with_activation(Instruction* currentInstruction)
1426 {
1427     emit_op_enter(currentInstruction);
1428 
1429     JITStubCall(this, cti_op_push_activation).call(currentInstruction[1].u.operand);
1430 }
1431 
emit_op_create_arguments(Instruction *)1432 void JIT::emit_op_create_arguments(Instruction*)
1433 {
1434     Jump argsCreated = branch32(NotEqual, tagFor(RegisterFile::ArgumentsRegister, callFrameRegister), Imm32(JSValue::EmptyValueTag));
1435 
1436     // If we get here the arguments pointer is a null cell - i.e. arguments need lazy creation.
1437     if (m_codeBlock->m_numParameters == 1)
1438         JITStubCall(this, cti_op_create_arguments_no_params).call();
1439     else
1440         JITStubCall(this, cti_op_create_arguments).call();
1441 
1442     argsCreated.link(this);
1443 }
1444 
emit_op_init_arguments(Instruction *)1445 void JIT::emit_op_init_arguments(Instruction*)
1446 {
1447     emitStore(RegisterFile::ArgumentsRegister, JSValue(), callFrameRegister);
1448 }
1449 
emit_op_convert_this(Instruction * currentInstruction)1450 void JIT::emit_op_convert_this(Instruction* currentInstruction)
1451 {
1452     unsigned thisRegister = currentInstruction[1].u.operand;
1453 
1454     emitLoad(thisRegister, regT1, regT0);
1455 
1456     addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::CellTag)));
1457 
1458     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
1459     addSlowCase(branchTest32(NonZero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(NeedsThisConversion)));
1460 
1461     map(m_bytecodeIndex + OPCODE_LENGTH(op_convert_this), thisRegister, regT1, regT0);
1462 }
1463 
emitSlow_op_convert_this(Instruction * currentInstruction,Vector<SlowCaseEntry>::iterator & iter)1464 void JIT::emitSlow_op_convert_this(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1465 {
1466     unsigned thisRegister = currentInstruction[1].u.operand;
1467 
1468     linkSlowCase(iter);
1469     linkSlowCase(iter);
1470 
1471     JITStubCall stubCall(this, cti_op_convert_this);
1472     stubCall.addArgument(regT1, regT0);
1473     stubCall.call(thisRegister);
1474 }
1475 
emit_op_profile_will_call(Instruction * currentInstruction)1476 void JIT::emit_op_profile_will_call(Instruction* currentInstruction)
1477 {
1478     peek(regT2, OBJECT_OFFSETOF(JITStackFrame, enabledProfilerReference) / sizeof (void*));
1479     Jump noProfiler = branchTestPtr(Zero, Address(regT2));
1480 
1481     JITStubCall stubCall(this, cti_op_profile_will_call);
1482     stubCall.addArgument(currentInstruction[1].u.operand);
1483     stubCall.call();
1484     noProfiler.link(this);
1485 }
1486 
emit_op_profile_did_call(Instruction * currentInstruction)1487 void JIT::emit_op_profile_did_call(Instruction* currentInstruction)
1488 {
1489     peek(regT2, OBJECT_OFFSETOF(JITStackFrame, enabledProfilerReference) / sizeof (void*));
1490     Jump noProfiler = branchTestPtr(Zero, Address(regT2));
1491 
1492     JITStubCall stubCall(this, cti_op_profile_did_call);
1493     stubCall.addArgument(currentInstruction[1].u.operand);
1494     stubCall.call();
1495     noProfiler.link(this);
1496 }
1497 
1498 #else // USE(JSVALUE32_64)
1499 
1500 #define RECORD_JUMP_TARGET(targetOffset) \
1501    do { m_labels[m_bytecodeIndex + (targetOffset)].used(); } while (false)
1502 
1503 void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executablePool, JSGlobalData* globalData, CodePtr* ctiStringLengthTrampoline, CodePtr* ctiVirtualCallLink, CodePtr* ctiVirtualCall, CodePtr* ctiNativeCallThunk)
1504 {
1505 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
1506     // (2) The second function provides fast property access for string length
1507     Label stringLengthBegin = align();
1508 
1509     // Check eax is a string
1510     Jump string_failureCases1 = emitJumpIfNotJSCell(regT0);
1511     Jump string_failureCases2 = branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr));
1512 
1513     // Checks out okay! - get the length from the Ustring.
1514     load32(Address(regT0, OBJECT_OFFSETOF(JSString, m_stringLength)), regT0);
1515 
1516     Jump string_failureCases3 = branch32(Above, regT0, Imm32(JSImmediate::maxImmediateInt));
1517 
1518     // regT0 contains a 64 bit value (is positive, is zero extended) so we don't need sign extend here.
1519     emitFastArithIntToImmNoCheck(regT0, regT0);
1520 
1521     ret();
1522 #endif
1523 
1524     // (3) Trampolines for the slow cases of op_call / op_call_eval / op_construct.
1525     COMPILE_ASSERT(sizeof(CodeType) == 4, CodeTypeEnumMustBe32Bit);
1526 
1527     // VirtualCallLink Trampoline
1528     // regT0 holds callee, regT1 holds argCount.  regT2 will hold the FunctionExecutable.
1529     Label virtualCallLinkBegin = align();
1530     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
1531 
1532     Jump isNativeFunc2 = branch32(Equal, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParameters)), Imm32(0));
1533 
1534     Jump hasCodeBlock2 = branch32(GreaterThan, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParameters)), Imm32(0));
1535     preserveReturnAddressAfterCall(regT3);
1536     restoreArgumentReference();
1537     Call callJSFunction2 = call();
1538     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
1539     emitGetJITStubArg(2, regT1); // argCount
1540     restoreReturnAddressBeforeReturn(regT3);
1541     hasCodeBlock2.link(this);
1542 
1543     // Check argCount matches callee arity.
1544     Jump arityCheckOkay2 = branch32(Equal, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParameters)), regT1);
1545     preserveReturnAddressAfterCall(regT3);
1546     emitPutJITStubArg(regT3, 1); // return address
1547     restoreArgumentReference();
1548     Call callArityCheck2 = call();
1549     move(regT1, callFrameRegister);
1550     emitGetJITStubArg(2, regT1); // argCount
1551     restoreReturnAddressBeforeReturn(regT3);
1552     arityCheckOkay2.link(this);
1553 
1554     isNativeFunc2.link(this);
1555 
1556     compileOpCallInitializeCallFrame();
1557     preserveReturnAddressAfterCall(regT3);
1558     emitPutJITStubArg(regT3, 1); // return address
1559     restoreArgumentReference();
1560     Call callLazyLinkCall = call();
1561     restoreReturnAddressBeforeReturn(regT3);
1562     jump(regT0);
1563 
1564     // VirtualCall Trampoline
1565     // regT0 holds callee, regT1 holds argCount.  regT2 will hold the FunctionExecutable.
1566     Label virtualCallBegin = align();
1567     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
1568 
1569     Jump isNativeFunc3 = branch32(Equal, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParameters)), Imm32(0));
1570 
1571     Jump hasCodeBlock3 = branch32(GreaterThan, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParameters)), Imm32(0));
1572     preserveReturnAddressAfterCall(regT3);
1573     restoreArgumentReference();
1574     Call callJSFunction1 = call();
1575     emitGetJITStubArg(2, regT1); // argCount
1576     restoreReturnAddressBeforeReturn(regT3);
1577     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
1578     hasCodeBlock3.link(this);
1579 
1580     // Check argCount matches callee arity.
1581     Jump arityCheckOkay3 = branch32(Equal, Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_numParameters)), regT1);
1582     preserveReturnAddressAfterCall(regT3);
1583     emitPutJITStubArg(regT3, 1); // return address
1584     restoreArgumentReference();
1585     Call callArityCheck1 = call();
1586     move(regT1, callFrameRegister);
1587     emitGetJITStubArg(2, regT1); // argCount
1588     restoreReturnAddressBeforeReturn(regT3);
1589     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
1590     arityCheckOkay3.link(this);
1591 
1592     isNativeFunc3.link(this);
1593 
1594     compileOpCallInitializeCallFrame();
1595     loadPtr(Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_jitCode)), regT0);
1596     jump(regT0);
1597 
1598     Label nativeCallThunk = align();
1599     preserveReturnAddressAfterCall(regT0);
1600     emitPutToCallFrameHeader(regT0, RegisterFile::ReturnPC); // Push return address
1601 
1602     // Load caller frame's scope chain into this callframe so that whatever we call can
1603     // get to its global data.
1604     emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT1);
1605     emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT1);
1606     emitPutToCallFrameHeader(regT1, RegisterFile::ScopeChain);
1607 
1608 
1609 #if CPU(X86_64)
1610     emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, X86Registers::ecx);
1611 
1612     // Allocate stack space for our arglist
1613     subPtr(Imm32(sizeof(ArgList)), stackPointerRegister);
1614     COMPILE_ASSERT((sizeof(ArgList) & 0xf) == 0, ArgList_should_by_16byte_aligned);
1615 
1616     // Set up arguments
1617     subPtr(Imm32(1), X86Registers::ecx); // Don't include 'this' in argcount
1618 
1619     // Push argcount
1620     storePtr(X86Registers::ecx, Address(stackPointerRegister, OBJECT_OFFSETOF(ArgList, m_argCount)));
1621 
1622     // Calculate the start of the callframe header, and store in edx
1623     addPtr(Imm32(-RegisterFile::CallFrameHeaderSize * (int32_t)sizeof(Register)), callFrameRegister, X86Registers::edx);
1624 
1625     // Calculate start of arguments as callframe header - sizeof(Register) * argcount (ecx)
1626     mul32(Imm32(sizeof(Register)), X86Registers::ecx, X86Registers::ecx);
1627     subPtr(X86Registers::ecx, X86Registers::edx);
1628 
1629     // push pointer to arguments
1630     storePtr(X86Registers::edx, Address(stackPointerRegister, OBJECT_OFFSETOF(ArgList, m_args)));
1631 
1632     // ArgList is passed by reference so is stackPointerRegister
1633     move(stackPointerRegister, X86Registers::ecx);
1634 
1635     // edx currently points to the first argument, edx-sizeof(Register) points to 'this'
1636     loadPtr(Address(X86Registers::edx, -(int32_t)sizeof(Register)), X86Registers::edx);
1637 
1638     emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, X86Registers::esi);
1639 
1640     move(callFrameRegister, X86Registers::edi);
1641 
1642     call(Address(X86Registers::esi, OBJECT_OFFSETOF(JSFunction, m_data)));
1643 
1644     addPtr(Imm32(sizeof(ArgList)), stackPointerRegister);
1645 #elif CPU(X86)
1646     emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0);
1647 
1648     /* We have two structs that we use to describe the stackframe we set up for our
1649      * call to native code.  NativeCallFrameStructure describes the how we set up the stack
1650      * in advance of the call.  NativeFunctionCalleeSignature describes the callframe
1651      * as the native code expects it.  We do this as we are using the fastcall calling
1652      * convention which results in the callee popping its arguments off the stack, but
1653      * not the rest of the callframe so we need a nice way to ensure we increment the
1654      * stack pointer by the right amount after the call.
1655      */
1656 #if COMPILER(MSVC) || OS(LINUX)
1657     struct NativeCallFrameStructure {
1658       //  CallFrame* callFrame; // passed in EDX
1659         JSObject* callee;
1660         JSValue thisValue;
1661         ArgList* argPointer;
1662         ArgList args;
1663         JSValue result;
1664     };
1665     struct NativeFunctionCalleeSignature {
1666         JSObject* callee;
1667         JSValue thisValue;
1668         ArgList* argPointer;
1669     };
1670 #else
1671     struct NativeCallFrameStructure {
1672       //  CallFrame* callFrame; // passed in ECX
1673       //  JSObject* callee; // passed in EDX
1674         JSValue thisValue;
1675         ArgList* argPointer;
1676         ArgList args;
1677     };
1678     struct NativeFunctionCalleeSignature {
1679         JSValue thisValue;
1680         ArgList* argPointer;
1681     };
1682 #endif
1683     const int NativeCallFrameSize = (sizeof(NativeCallFrameStructure) + 15) & ~15;
1684     // Allocate system stack frame
1685     subPtr(Imm32(NativeCallFrameSize), stackPointerRegister);
1686 
1687     // Set up arguments
1688     subPtr(Imm32(1), regT0); // Don't include 'this' in argcount
1689 
1690     // push argcount
1691     storePtr(regT0, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, args) + OBJECT_OFFSETOF(ArgList, m_argCount)));
1692 
1693     // Calculate the start of the callframe header, and store in regT1
1694     addPtr(Imm32(-RegisterFile::CallFrameHeaderSize * (int)sizeof(Register)), callFrameRegister, regT1);
1695 
1696     // Calculate start of arguments as callframe header - sizeof(Register) * argcount (regT0)
1697     mul32(Imm32(sizeof(Register)), regT0, regT0);
1698     subPtr(regT0, regT1);
1699     storePtr(regT1, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, args) + OBJECT_OFFSETOF(ArgList, m_args)));
1700 
1701     // ArgList is passed by reference so is stackPointerRegister + 4 * sizeof(Register)
1702     addPtr(Imm32(OBJECT_OFFSETOF(NativeCallFrameStructure, args)), stackPointerRegister, regT0);
1703     storePtr(regT0, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, argPointer)));
1704 
1705     // regT1 currently points to the first argument, regT1 - sizeof(Register) points to 'this'
1706     loadPtr(Address(regT1, -(int)sizeof(Register)), regT1);
1707     storePtr(regT1, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, thisValue)));
1708 
1709 #if COMPILER(MSVC) || OS(LINUX)
1710     // ArgList is passed by reference so is stackPointerRegister + 4 * sizeof(Register)
1711     addPtr(Imm32(OBJECT_OFFSETOF(NativeCallFrameStructure, result)), stackPointerRegister, X86Registers::ecx);
1712 
1713     // Plant callee
1714     emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, X86Registers::eax);
1715     storePtr(X86Registers::eax, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, callee)));
1716 
1717     // Plant callframe
1718     move(callFrameRegister, X86Registers::edx);
1719 
1720     call(Address(X86Registers::eax, OBJECT_OFFSETOF(JSFunction, m_data)));
1721 
1722     // JSValue is a non-POD type
1723     loadPtr(Address(X86Registers::eax), X86Registers::eax);
1724 #else
1725     // Plant callee
1726     emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, X86Registers::edx);
1727 
1728     // Plant callframe
1729     move(callFrameRegister, X86Registers::ecx);
1730     call(Address(X86Registers::edx, OBJECT_OFFSETOF(JSFunction, m_data)));
1731 #endif
1732 
1733     // We've put a few temporaries on the stack in addition to the actual arguments
1734     // so pull them off now
1735     addPtr(Imm32(NativeCallFrameSize - sizeof(NativeFunctionCalleeSignature)), stackPointerRegister);
1736 
1737 #elif CPU(ARM)
1738     emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0);
1739 
1740     // Allocate stack space for our arglist
1741     COMPILE_ASSERT((sizeof(ArgList) & 0x7) == 0, ArgList_should_by_8byte_aligned);
1742     subPtr(Imm32(sizeof(ArgList)), stackPointerRegister);
1743 
1744     // Set up arguments
1745     subPtr(Imm32(1), regT0); // Don't include 'this' in argcount
1746 
1747     // Push argcount
1748     storePtr(regT0, Address(stackPointerRegister, OBJECT_OFFSETOF(ArgList, m_argCount)));
1749 
1750     // Calculate the start of the callframe header, and store in regT1
1751     move(callFrameRegister, regT1);
1752     sub32(Imm32(RegisterFile::CallFrameHeaderSize * (int32_t)sizeof(Register)), regT1);
1753 
1754     // Calculate start of arguments as callframe header - sizeof(Register) * argcount (regT1)
1755     mul32(Imm32(sizeof(Register)), regT0, regT0);
1756     subPtr(regT0, regT1);
1757 
1758     // push pointer to arguments
1759     storePtr(regT1, Address(stackPointerRegister, OBJECT_OFFSETOF(ArgList, m_args)));
1760 
1761     // Setup arg3: regT1 currently points to the first argument, regT1-sizeof(Register) points to 'this'
1762     loadPtr(Address(regT1, -(int32_t)sizeof(Register)), regT2);
1763 
1764     // Setup arg2:
1765     emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, regT1);
1766 
1767     // Setup arg1:
1768     move(callFrameRegister, regT0);
1769 
1770     // Setup arg4: This is a plain hack
1771     move(stackPointerRegister, ARMRegisters::r3);
1772 
1773     call(Address(regT1, OBJECT_OFFSETOF(JSFunction, m_data)));
1774 
1775     addPtr(Imm32(sizeof(ArgList)), stackPointerRegister);
1776 
1777 #elif ENABLE(JIT_OPTIMIZE_NATIVE_CALL)
1778 #error "JIT_OPTIMIZE_NATIVE_CALL not yet supported on this platform."
1779 #else
1780     breakpoint();
1781 #endif
1782 
1783     // Check for an exception
1784     loadPtr(&(globalData->exception), regT2);
1785     Jump exceptionHandler = branchTestPtr(NonZero, regT2);
1786 
1787     // Grab the return address.
1788     emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1);
1789 
1790     // Restore our caller's "r".
1791     emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
1792 
1793     // Return.
1794     restoreReturnAddressBeforeReturn(regT1);
1795     ret();
1796 
1797     // Handle an exception
1798     exceptionHandler.link(this);
1799     // Grab the return address.
1800     emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1);
1801     move(ImmPtr(&globalData->exceptionLocation), regT2);
1802     storePtr(regT1, regT2);
1803     move(ImmPtr(FunctionPtr(ctiVMThrowTrampoline).value()), regT2);
1804     emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
1805     poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof (void*));
1806     restoreReturnAddressBeforeReturn(regT2);
1807     ret();
1808 
1809 
1810 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
1811     Call string_failureCases1Call = makeTailRecursiveCall(string_failureCases1);
1812     Call string_failureCases2Call = makeTailRecursiveCall(string_failureCases2);
1813     Call string_failureCases3Call = makeTailRecursiveCall(string_failureCases3);
1814 #endif
1815 
1816     // All trampolines constructed! copy the code, link up calls, and set the pointers on the Machine object.
1817     LinkBuffer patchBuffer(this, m_globalData->executableAllocator.poolForSize(m_assembler.size()));
1818 
1819 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
1820     patchBuffer.link(string_failureCases1Call, FunctionPtr(cti_op_get_by_id_string_fail));
1821     patchBuffer.link(string_failureCases2Call, FunctionPtr(cti_op_get_by_id_string_fail));
1822     patchBuffer.link(string_failureCases3Call, FunctionPtr(cti_op_get_by_id_string_fail));
1823 #endif
1824     patchBuffer.link(callArityCheck1, FunctionPtr(cti_op_call_arityCheck));
1825     patchBuffer.link(callJSFunction1, FunctionPtr(cti_op_call_JSFunction));
1826 #if ENABLE(JIT_OPTIMIZE_CALL)
1827     patchBuffer.link(callArityCheck2, FunctionPtr(cti_op_call_arityCheck));
1828     patchBuffer.link(callJSFunction2, FunctionPtr(cti_op_call_JSFunction));
1829     patchBuffer.link(callLazyLinkCall, FunctionPtr(cti_vm_lazyLinkCall));
1830 #endif
1831 
1832     CodeRef finalCode = patchBuffer.finalizeCode();
1833     *executablePool = finalCode.m_executablePool;
1834 
1835     *ctiVirtualCallLink = trampolineAt(finalCode, virtualCallLinkBegin);
1836     *ctiVirtualCall = trampolineAt(finalCode, virtualCallBegin);
1837     *ctiNativeCallThunk = trampolineAt(finalCode, nativeCallThunk);
1838 #if ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS)
1839     *ctiStringLengthTrampoline = trampolineAt(finalCode, stringLengthBegin);
1840 #else
1841     UNUSED_PARAM(ctiStringLengthTrampoline);
1842 #endif
1843 }
1844 
1845 void JIT::emit_op_mov(Instruction* currentInstruction)
1846 {
1847     int dst = currentInstruction[1].u.operand;
1848     int src = currentInstruction[2].u.operand;
1849 
1850     if (m_codeBlock->isConstantRegisterIndex(src)) {
1851         storePtr(ImmPtr(JSValue::encode(getConstantOperand(src))), Address(callFrameRegister, dst * sizeof(Register)));
1852         if (dst == m_lastResultBytecodeRegister)
1853             killLastResultRegister();
1854     } else if ((src == m_lastResultBytecodeRegister) || (dst == m_lastResultBytecodeRegister)) {
1855         // If either the src or dst is the cached register go though
1856         // get/put registers to make sure we track this correctly.
1857         emitGetVirtualRegister(src, regT0);
1858         emitPutVirtualRegister(dst);
1859     } else {
1860         // Perform the copy via regT1; do not disturb any mapping in regT0.
1861         loadPtr(Address(callFrameRegister, src * sizeof(Register)), regT1);
1862         storePtr(regT1, Address(callFrameRegister, dst * sizeof(Register)));
1863     }
1864 }
1865 
1866 void JIT::emit_op_end(Instruction* currentInstruction)
1867 {
1868     if (m_codeBlock->needsFullScopeChain())
1869         JITStubCall(this, cti_op_end).call();
1870     ASSERT(returnValueRegister != callFrameRegister);
1871     emitGetVirtualRegister(currentInstruction[1].u.operand, returnValueRegister);
1872     restoreReturnAddressBeforeReturn(Address(callFrameRegister, RegisterFile::ReturnPC * static_cast<int>(sizeof(Register))));
1873     ret();
1874 }
1875 
1876 void JIT::emit_op_jmp(Instruction* currentInstruction)
1877 {
1878     unsigned target = currentInstruction[1].u.operand;
1879     addJump(jump(), target);
1880     RECORD_JUMP_TARGET(target);
1881 }
1882 
1883 void JIT::emit_op_loop_if_lesseq(Instruction* currentInstruction)
1884 {
1885     emitTimeoutCheck();
1886 
1887     unsigned op1 = currentInstruction[1].u.operand;
1888     unsigned op2 = currentInstruction[2].u.operand;
1889     unsigned target = currentInstruction[3].u.operand;
1890     if (isOperandConstantImmediateInt(op2)) {
1891         emitGetVirtualRegister(op1, regT0);
1892         emitJumpSlowCaseIfNotImmediateInteger(regT0);
1893 #if USE(JSVALUE64)
1894         int32_t op2imm = getConstantOperandImmediateInt(op2);
1895 #else
1896         int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2)));
1897 #endif
1898         addJump(branch32(LessThanOrEqual, regT0, Imm32(op2imm)), target);
1899     } else {
1900         emitGetVirtualRegisters(op1, regT0, op2, regT1);
1901         emitJumpSlowCaseIfNotImmediateInteger(regT0);
1902         emitJumpSlowCaseIfNotImmediateInteger(regT1);
1903         addJump(branch32(LessThanOrEqual, regT0, regT1), target);
1904     }
1905 }
1906 
1907 void JIT::emit_op_new_object(Instruction* currentInstruction)
1908 {
1909     JITStubCall(this, cti_op_new_object).call(currentInstruction[1].u.operand);
1910 }
1911 
1912 void JIT::emit_op_instanceof(Instruction* currentInstruction)
1913 {
1914     unsigned dst = currentInstruction[1].u.operand;
1915     unsigned value = currentInstruction[2].u.operand;
1916     unsigned baseVal = currentInstruction[3].u.operand;
1917     unsigned proto = currentInstruction[4].u.operand;
1918 
1919     // Load the operands (baseVal, proto, and value respectively) into registers.
1920     // We use regT0 for baseVal since we will be done with this first, and we can then use it for the result.
1921     emitGetVirtualRegister(value, regT2);
1922     emitGetVirtualRegister(baseVal, regT0);
1923     emitGetVirtualRegister(proto, regT1);
1924 
1925     // Check that baseVal & proto are cells.
1926     emitJumpSlowCaseIfNotJSCell(regT2, value);
1927     emitJumpSlowCaseIfNotJSCell(regT0, baseVal);
1928     emitJumpSlowCaseIfNotJSCell(regT1, proto);
1929 
1930     // Check that baseVal 'ImplementsDefaultHasInstance'.
1931     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT0);
1932     addSlowCase(branchTest32(Zero, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(ImplementsDefaultHasInstance)));
1933 
1934     // Optimistically load the result true, and start looping.
1935     // Initially, regT1 still contains proto and regT2 still contains value.
1936     // As we loop regT2 will be updated with its prototype, recursively walking the prototype chain.
1937     move(ImmPtr(JSValue::encode(jsBoolean(true))), regT0);
1938     Label loop(this);
1939 
1940     // Load the prototype of the object in regT2.  If this is equal to regT1 - WIN!
1941     // Otherwise, check if we've hit null - if we have then drop out of the loop, if not go again.
1942     loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
1943     loadPtr(Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype)), regT2);
1944     Jump isInstance = branchPtr(Equal, regT2, regT1);
1945     emitJumpIfJSCell(regT2).linkTo(loop, this);
1946 
1947     // We get here either by dropping out of the loop, or if value was not an Object.  Result is false.
1948     move(ImmPtr(JSValue::encode(jsBoolean(false))), regT0);
1949 
1950     // isInstance jumps right down to here, to skip setting the result to false (it has already set true).
1951     isInstance.link(this);
1952     emitPutVirtualRegister(dst);
1953 }
1954 
1955 void JIT::emit_op_new_func(Instruction* currentInstruction)
1956 {
1957     JITStubCall stubCall(this, cti_op_new_func);
1958     stubCall.addArgument(ImmPtr(m_codeBlock->functionDecl(currentInstruction[2].u.operand)));
1959     stubCall.call(currentInstruction[1].u.operand);
1960 }
1961 
1962 void JIT::emit_op_call(Instruction* currentInstruction)
1963 {
1964     compileOpCall(op_call, currentInstruction, m_callLinkInfoIndex++);
1965 }
1966 
1967 void JIT::emit_op_call_eval(Instruction* currentInstruction)
1968 {
1969     compileOpCall(op_call_eval, currentInstruction, m_callLinkInfoIndex++);
1970 }
1971 
1972 void JIT::emit_op_load_varargs(Instruction* currentInstruction)
1973 {
1974     int argCountDst = currentInstruction[1].u.operand;
1975     int argsOffset = currentInstruction[2].u.operand;
1976 
1977     JITStubCall stubCall(this, cti_op_load_varargs);
1978     stubCall.addArgument(Imm32(argsOffset));
1979     stubCall.call();
1980     // Stores a naked int32 in the register file.
1981     store32(returnValueRegister, Address(callFrameRegister, argCountDst * sizeof(Register)));
1982 }
1983 
1984 void JIT::emit_op_call_varargs(Instruction* currentInstruction)
1985 {
1986     compileOpCallVarargs(currentInstruction);
1987 }
1988 
1989 void JIT::emit_op_construct(Instruction* currentInstruction)
1990 {
1991     compileOpCall(op_construct, currentInstruction, m_callLinkInfoIndex++);
1992 }
1993 
1994 void JIT::emit_op_get_global_var(Instruction* currentInstruction)
1995 {
1996     JSVariableObject* globalObject = static_cast<JSVariableObject*>(currentInstruction[2].u.jsCell);
1997     move(ImmPtr(globalObject), regT0);
1998     emitGetVariableObjectRegister(regT0, currentInstruction[3].u.operand, regT0);
1999     emitPutVirtualRegister(currentInstruction[1].u.operand);
2000 }
2001 
2002 void JIT::emit_op_put_global_var(Instruction* currentInstruction)
2003 {
2004     emitGetVirtualRegister(currentInstruction[3].u.operand, regT1);
2005     JSVariableObject* globalObject = static_cast<JSVariableObject*>(currentInstruction[1].u.jsCell);
2006     move(ImmPtr(globalObject), regT0);
2007     emitPutVariableObjectRegister(regT1, regT0, currentInstruction[2].u.operand);
2008 }
2009 
2010 void JIT::emit_op_get_scoped_var(Instruction* currentInstruction)
2011 {
2012     int skip = currentInstruction[3].u.operand + m_codeBlock->needsFullScopeChain();
2013 
2014     emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT0);
2015     while (skip--)
2016         loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, next)), regT0);
2017 
2018     loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, object)), regT0);
2019     emitGetVariableObjectRegister(regT0, currentInstruction[2].u.operand, regT0);
2020     emitPutVirtualRegister(currentInstruction[1].u.operand);
2021 }
2022 
2023 void JIT::emit_op_put_scoped_var(Instruction* currentInstruction)
2024 {
2025     int skip = currentInstruction[2].u.operand + m_codeBlock->needsFullScopeChain();
2026 
2027     emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1);
2028     emitGetVirtualRegister(currentInstruction[3].u.operand, regT0);
2029     while (skip--)
2030         loadPtr(Address(regT1, OBJECT_OFFSETOF(ScopeChainNode, next)), regT1);
2031 
2032     loadPtr(Address(regT1, OBJECT_OFFSETOF(ScopeChainNode, object)), regT1);
2033     emitPutVariableObjectRegister(regT0, regT1, currentInstruction[1].u.operand);
2034 }
2035 
2036 void JIT::emit_op_tear_off_activation(Instruction* currentInstruction)
2037 {
2038     JITStubCall stubCall(this, cti_op_tear_off_activation);
2039     stubCall.addArgument(currentInstruction[1].u.operand, regT2);
2040     stubCall.call();
2041 }
2042 
2043 void JIT::emit_op_tear_off_arguments(Instruction*)
2044 {
2045     JITStubCall(this, cti_op_tear_off_arguments).call();
2046 }
2047 
2048 void JIT::emit_op_ret(Instruction* currentInstruction)
2049 {
2050 #ifdef QT_BUILD_SCRIPT_LIB
2051     JITStubCall stubCall(this, cti_op_debug_return);
2052     stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
2053     stubCall.call();
2054 #endif
2055     // We could JIT generate the deref, only calling out to C when the refcount hits zero.
2056     if (m_codeBlock->needsFullScopeChain())
2057         JITStubCall(this, cti_op_ret_scopeChain).call();
2058 
2059     ASSERT(callFrameRegister != regT1);
2060     ASSERT(regT1 != returnValueRegister);
2061     ASSERT(returnValueRegister != callFrameRegister);
2062 
2063     // Return the result in %eax.
2064     emitGetVirtualRegister(currentInstruction[1].u.operand, returnValueRegister);
2065 
2066     // Grab the return address.
2067     emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1);
2068 
2069     // Restore our caller's "r".
2070     emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister);
2071 
2072     // Return.
2073     restoreReturnAddressBeforeReturn(regT1);
2074     ret();
2075 }
2076 
2077 void JIT::emit_op_new_array(Instruction* currentInstruction)
2078 {
2079     JITStubCall stubCall(this, cti_op_new_array);
2080     stubCall.addArgument(Imm32(currentInstruction[2].u.operand));
2081     stubCall.addArgument(Imm32(currentInstruction[3].u.operand));
2082     stubCall.call(currentInstruction[1].u.operand);
2083 }
2084 
2085 void JIT::emit_op_resolve(Instruction* currentInstruction)
2086 {
2087     JITStubCall stubCall(this, cti_op_resolve);
2088     stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
2089     stubCall.call(currentInstruction[1].u.operand);
2090 }
2091 
2092 void JIT::emit_op_construct_verify(Instruction* currentInstruction)
2093 {
2094     emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);
2095 
2096     emitJumpSlowCaseIfNotJSCell(regT0);
2097     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
2098     addSlowCase(branch32(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo) + OBJECT_OFFSETOF(TypeInfo, m_type)), Imm32(ObjectType)));
2099 
2100 }
2101 
2102 void JIT::emit_op_to_primitive(Instruction* currentInstruction)
2103 {
2104     int dst = currentInstruction[1].u.operand;
2105     int src = currentInstruction[2].u.operand;
2106 
2107     emitGetVirtualRegister(src, regT0);
2108 
2109     Jump isImm = emitJumpIfNotJSCell(regT0);
2110     addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr)));
2111     isImm.link(this);
2112 
2113     if (dst != src)
2114         emitPutVirtualRegister(dst);
2115 
2116 }
2117 
2118 void JIT::emit_op_strcat(Instruction* currentInstruction)
2119 {
2120     JITStubCall stubCall(this, cti_op_strcat);
2121     stubCall.addArgument(Imm32(currentInstruction[2].u.operand));
2122     stubCall.addArgument(Imm32(currentInstruction[3].u.operand));
2123     stubCall.call(currentInstruction[1].u.operand);
2124 }
2125 
2126 void JIT::emit_op_resolve_base(Instruction* currentInstruction)
2127 {
2128     JITStubCall stubCall(this, cti_op_resolve_base);
2129     stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
2130     stubCall.call(currentInstruction[1].u.operand);
2131 }
2132 
2133 void JIT::emit_op_resolve_skip(Instruction* currentInstruction)
2134 {
2135     JITStubCall stubCall(this, cti_op_resolve_skip);
2136     stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
2137     stubCall.addArgument(Imm32(currentInstruction[3].u.operand + m_codeBlock->needsFullScopeChain()));
2138     stubCall.call(currentInstruction[1].u.operand);
2139 }
2140 
2141 void JIT::emit_op_resolve_global(Instruction* currentInstruction)
2142 {
2143     // Fast case
2144     void* globalObject = currentInstruction[2].u.jsCell;
2145     Identifier* ident = &m_codeBlock->identifier(currentInstruction[3].u.operand);
2146 
2147     unsigned currentIndex = m_globalResolveInfoIndex++;
2148     void* structureAddress = &(m_codeBlock->globalResolveInfo(currentIndex).structure);
2149     void* offsetAddr = &(m_codeBlock->globalResolveInfo(currentIndex).offset);
2150 
2151     // Check Structure of global object
2152     move(ImmPtr(globalObject), regT0);
2153     loadPtr(structureAddress, regT1);
2154     Jump noMatch = branchPtr(NotEqual, regT1, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure))); // Structures don't match
2155 
2156     // Load cached property
2157     // Assume that the global object always uses external storage.
2158     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSGlobalObject, m_externalStorage)), regT0);
2159     load32(offsetAddr, regT1);
2160     loadPtr(BaseIndex(regT0, regT1, ScalePtr), regT0);
2161     emitPutVirtualRegister(currentInstruction[1].u.operand);
2162     Jump end = jump();
2163 
2164     // Slow case
2165     noMatch.link(this);
2166     JITStubCall stubCall(this, cti_op_resolve_global);
2167     stubCall.addArgument(ImmPtr(globalObject));
2168     stubCall.addArgument(ImmPtr(ident));
2169     stubCall.addArgument(Imm32(currentIndex));
2170     stubCall.call(currentInstruction[1].u.operand);
2171     end.link(this);
2172 }
2173 
2174 void JIT::emit_op_not(Instruction* currentInstruction)
2175 {
2176     emitGetVirtualRegister(currentInstruction[2].u.operand, regT0);
2177     xorPtr(Imm32(static_cast<int32_t>(JSImmediate::FullTagTypeBool)), regT0);
2178     addSlowCase(branchTestPtr(NonZero, regT0, Imm32(static_cast<int32_t>(~JSImmediate::ExtendedPayloadBitBoolValue))));
2179     xorPtr(Imm32(static_cast<int32_t>(JSImmediate::FullTagTypeBool | JSImmediate::ExtendedPayloadBitBoolValue)), regT0);
2180     emitPutVirtualRegister(currentInstruction[1].u.operand);
2181 }
2182 
2183 void JIT::emit_op_jfalse(Instruction* currentInstruction)
2184 {
2185     unsigned target = currentInstruction[2].u.operand;
2186     emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);
2187 
2188     addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsNumber(m_globalData, 0)))), target);
2189     Jump isNonZero = emitJumpIfImmediateInteger(regT0);
2190 
2191     addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsBoolean(false)))), target);
2192     addSlowCase(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(jsBoolean(true)))));
2193 
2194     isNonZero.link(this);
2195     RECORD_JUMP_TARGET(target);
2196 };
2197 void JIT::emit_op_jeq_null(Instruction* currentInstruction)
2198 {
2199     unsigned src = currentInstruction[1].u.operand;
2200     unsigned target = currentInstruction[2].u.operand;
2201 
2202     emitGetVirtualRegister(src, regT0);
2203     Jump isImmediate = emitJumpIfNotJSCell(regT0);
2204 
2205     // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure.
2206     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
2207     addJump(branchTest32(NonZero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target);
2208     Jump wasNotImmediate = jump();
2209 
2210     // Now handle the immediate cases - undefined & null
2211     isImmediate.link(this);
2212     andPtr(Imm32(~JSImmediate::ExtendedTagBitUndefined), regT0);
2213     addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsNull()))), target);
2214 
2215     wasNotImmediate.link(this);
2216     RECORD_JUMP_TARGET(target);
2217 };
2218 void JIT::emit_op_jneq_null(Instruction* currentInstruction)
2219 {
2220     unsigned src = currentInstruction[1].u.operand;
2221     unsigned target = currentInstruction[2].u.operand;
2222 
2223     emitGetVirtualRegister(src, regT0);
2224     Jump isImmediate = emitJumpIfNotJSCell(regT0);
2225 
2226     // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure.
2227     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
2228     addJump(branchTest32(Zero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target);
2229     Jump wasNotImmediate = jump();
2230 
2231     // Now handle the immediate cases - undefined & null
2232     isImmediate.link(this);
2233     andPtr(Imm32(~JSImmediate::ExtendedTagBitUndefined), regT0);
2234     addJump(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(jsNull()))), target);
2235 
2236     wasNotImmediate.link(this);
2237     RECORD_JUMP_TARGET(target);
2238 }
2239 
2240 void JIT::emit_op_jneq_ptr(Instruction* currentInstruction)
2241 {
2242     unsigned src = currentInstruction[1].u.operand;
2243     JSCell* ptr = currentInstruction[2].u.jsCell;
2244     unsigned target = currentInstruction[3].u.operand;
2245 
2246     emitGetVirtualRegister(src, regT0);
2247     addJump(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(JSValue(ptr)))), target);
2248 
2249     RECORD_JUMP_TARGET(target);
2250 }
2251 
2252 void JIT::emit_op_jsr(Instruction* currentInstruction)
2253 {
2254     int retAddrDst = currentInstruction[1].u.operand;
2255     int target = currentInstruction[2].u.operand;
2256     DataLabelPtr storeLocation = storePtrWithPatch(ImmPtr(0), Address(callFrameRegister, sizeof(Register) * retAddrDst));
2257     addJump(jump(), target);
2258     m_jsrSites.append(JSRInfo(storeLocation, label()));
2259     killLastResultRegister();
2260     RECORD_JUMP_TARGET(target);
2261 }
2262 
2263 void JIT::emit_op_sret(Instruction* currentInstruction)
2264 {
2265     jump(Address(callFrameRegister, sizeof(Register) * currentInstruction[1].u.operand));
2266     killLastResultRegister();
2267 }
2268 
2269 void JIT::emit_op_eq(Instruction* currentInstruction)
2270 {
2271     emitGetVirtualRegisters(currentInstruction[2].u.operand, regT0, currentInstruction[3].u.operand, regT1);
2272     emitJumpSlowCaseIfNotImmediateIntegers(regT0, regT1, regT2);
2273     set32(Equal, regT1, regT0, regT0);
2274     emitTagAsBoolImmediate(regT0);
2275     emitPutVirtualRegister(currentInstruction[1].u.operand);
2276 }
2277 
2278 void JIT::emit_op_bitnot(Instruction* currentInstruction)
2279 {
2280     emitGetVirtualRegister(currentInstruction[2].u.operand, regT0);
2281     emitJumpSlowCaseIfNotImmediateInteger(regT0);
2282 #if USE(JSVALUE64)
2283     not32(regT0);
2284     emitFastArithIntToImmNoCheck(regT0, regT0);
2285 #else
2286     xorPtr(Imm32(~JSImmediate::TagTypeNumber), regT0);
2287 #endif
2288     emitPutVirtualRegister(currentInstruction[1].u.operand);
2289 }
2290 
2291 void JIT::emit_op_resolve_with_base(Instruction* currentInstruction)
2292 {
2293     JITStubCall stubCall(this, cti_op_resolve_with_base);
2294     stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[3].u.operand)));
2295     stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
2296     stubCall.call(currentInstruction[2].u.operand);
2297 }
2298 
2299 void JIT::emit_op_new_func_exp(Instruction* currentInstruction)
2300 {
2301     JITStubCall stubCall(this, cti_op_new_func_exp);
2302     stubCall.addArgument(ImmPtr(m_codeBlock->functionExpr(currentInstruction[2].u.operand)));
2303     stubCall.call(currentInstruction[1].u.operand);
2304 }
2305 
2306 void JIT::emit_op_jtrue(Instruction* currentInstruction)
2307 {
2308     unsigned target = currentInstruction[2].u.operand;
2309     emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);
2310 
2311     Jump isZero = branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsNumber(m_globalData, 0))));
2312     addJump(emitJumpIfImmediateInteger(regT0), target);
2313 
2314     addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsBoolean(true)))), target);
2315     addSlowCase(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(jsBoolean(false)))));
2316 
2317     isZero.link(this);
2318     RECORD_JUMP_TARGET(target);
2319 }
2320 
2321 void JIT::emit_op_neq(Instruction* currentInstruction)
2322 {
2323     emitGetVirtualRegisters(currentInstruction[2].u.operand, regT0, currentInstruction[3].u.operand, regT1);
2324     emitJumpSlowCaseIfNotImmediateIntegers(regT0, regT1, regT2);
2325     set32(NotEqual, regT1, regT0, regT0);
2326     emitTagAsBoolImmediate(regT0);
2327 
2328     emitPutVirtualRegister(currentInstruction[1].u.operand);
2329 
2330 }
2331 
2332 void JIT::emit_op_bitxor(Instruction* currentInstruction)
2333 {
2334     emitGetVirtualRegisters(currentInstruction[2].u.operand, regT0, currentInstruction[3].u.operand, regT1);
2335     emitJumpSlowCaseIfNotImmediateIntegers(regT0, regT1, regT2);
2336     xorPtr(regT1, regT0);
2337     emitFastArithReTagImmediate(regT0, regT0);
2338     emitPutVirtualRegister(currentInstruction[1].u.operand);
2339 }
2340 
2341 void JIT::emit_op_new_regexp(Instruction* currentInstruction)
2342 {
2343     JITStubCall stubCall(this, cti_op_new_regexp);
2344     stubCall.addArgument(ImmPtr(m_codeBlock->regexp(currentInstruction[2].u.operand)));
2345     stubCall.call(currentInstruction[1].u.operand);
2346 }
2347 
2348 void JIT::emit_op_bitor(Instruction* currentInstruction)
2349 {
2350     emitGetVirtualRegisters(currentInstruction[2].u.operand, regT0, currentInstruction[3].u.operand, regT1);
2351     emitJumpSlowCaseIfNotImmediateIntegers(regT0, regT1, regT2);
2352     orPtr(regT1, regT0);
2353     emitPutVirtualRegister(currentInstruction[1].u.operand);
2354 }
2355 
2356 void JIT::emit_op_throw(Instruction* currentInstruction)
2357 {
2358     JITStubCall stubCall(this, cti_op_throw);
2359     stubCall.addArgument(currentInstruction[1].u.operand, regT2);
2360     stubCall.call();
2361     ASSERT(regT0 == returnValueRegister);
2362 #ifndef NDEBUG
2363     // cti_op_throw always changes it's return address,
2364     // this point in the code should never be reached.
2365     breakpoint();
2366 #endif
2367 }
2368 
2369 void JIT::emit_op_get_pnames(Instruction* currentInstruction)
2370 {
2371     int dst = currentInstruction[1].u.operand;
2372     int base = currentInstruction[2].u.operand;
2373     int i = currentInstruction[3].u.operand;
2374     int size = currentInstruction[4].u.operand;
2375     int breakTarget = currentInstruction[5].u.operand;
2376 
2377     JumpList isNotObject;
2378 
2379     emitGetVirtualRegister(base, regT0);
2380     if (!m_codeBlock->isKnownNotImmediate(base))
2381         isNotObject.append(emitJumpIfNotJSCell(regT0));
2382     if (base != m_codeBlock->thisRegister()) {
2383         loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
2384         isNotObject.append(branch32(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType)));
2385     }
2386 
2387     // We could inline the case where you have a valid cache, but
2388     // this call doesn't seem to be hot.
2389     Label isObject(this);
2390     JITStubCall getPnamesStubCall(this, cti_op_get_pnames);
2391     getPnamesStubCall.addArgument(regT0);
2392     getPnamesStubCall.call(dst);
2393     load32(Address(regT0, OBJECT_OFFSETOF(JSPropertyNameIterator, m_jsStringsSize)), regT3);
2394     store32(Imm32(0), addressFor(i));
2395     store32(regT3, addressFor(size));
2396     Jump end = jump();
2397 
2398     isNotObject.link(this);
2399     move(regT0, regT1);
2400     and32(Imm32(~JSImmediate::ExtendedTagBitUndefined), regT1);
2401     addJump(branch32(Equal, regT1, Imm32(JSImmediate::FullTagTypeNull)), breakTarget);
2402 
2403     JITStubCall toObjectStubCall(this, cti_to_object);
2404     toObjectStubCall.addArgument(regT0);
2405     toObjectStubCall.call(base);
2406     jump().linkTo(isObject, this);
2407 
2408     end.link(this);
2409 }
2410 
2411 void JIT::emit_op_next_pname(Instruction* currentInstruction)
2412 {
2413     int dst = currentInstruction[1].u.operand;
2414     int base = currentInstruction[2].u.operand;
2415     int i = currentInstruction[3].u.operand;
2416     int size = currentInstruction[4].u.operand;
2417     int it = currentInstruction[5].u.operand;
2418     int target = currentInstruction[6].u.operand;
2419 
2420     JumpList callHasProperty;
2421 
2422     Label begin(this);
2423     load32(addressFor(i), regT0);
2424     Jump end = branch32(Equal, regT0, addressFor(size));
2425 
2426     // Grab key @ i
2427     loadPtr(addressFor(it), regT1);
2428     loadPtr(Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_jsStrings)), regT2);
2429 
2430 #if USE(JSVALUE64)
2431     loadPtr(BaseIndex(regT2, regT0, TimesEight), regT2);
2432 #else
2433     loadPtr(BaseIndex(regT2, regT0, TimesFour), regT2);
2434 #endif
2435 
2436     emitPutVirtualRegister(dst, regT2);
2437 
2438     // Increment i
2439     add32(Imm32(1), regT0);
2440     store32(regT0, addressFor(i));
2441 
2442     // Verify that i is valid:
2443     emitGetVirtualRegister(base, regT0);
2444 
2445     // Test base's structure
2446     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
2447     callHasProperty.append(branchPtr(NotEqual, regT2, Address(Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_cachedStructure)))));
2448 
2449     // Test base's prototype chain
2450     loadPtr(Address(Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_cachedPrototypeChain))), regT3);
2451     loadPtr(Address(regT3, OBJECT_OFFSETOF(StructureChain, m_vector)), regT3);
2452     addJump(branchTestPtr(Zero, Address(regT3)), target);
2453 
2454     Label checkPrototype(this);
2455     loadPtr(Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype)), regT2);
2456     callHasProperty.append(emitJumpIfNotJSCell(regT2));
2457     loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
2458     callHasProperty.append(branchPtr(NotEqual, regT2, Address(regT3)));
2459     addPtr(Imm32(sizeof(Structure*)), regT3);
2460     branchTestPtr(NonZero, Address(regT3)).linkTo(checkPrototype, this);
2461 
2462     // Continue loop.
2463     addJump(jump(), target);
2464 
2465     // Slow case: Ask the object if i is valid.
2466     callHasProperty.link(this);
2467     emitGetVirtualRegister(dst, regT1);
2468     JITStubCall stubCall(this, cti_has_property);
2469     stubCall.addArgument(regT0);
2470     stubCall.addArgument(regT1);
2471     stubCall.call();
2472 
2473     // Test for valid key.
2474     addJump(branchTest32(NonZero, regT0), target);
2475     jump().linkTo(begin, this);
2476 
2477     // End of loop.
2478     end.link(this);
2479 }
2480 
2481 void JIT::emit_op_push_scope(Instruction* currentInstruction)
2482 {
2483     JITStubCall stubCall(this, cti_op_push_scope);
2484     stubCall.addArgument(currentInstruction[1].u.operand, regT2);
2485     stubCall.call(currentInstruction[1].u.operand);
2486 }
2487 
2488 void JIT::emit_op_pop_scope(Instruction*)
2489 {
2490     JITStubCall(this, cti_op_pop_scope).call();
2491 }
2492 
2493 void JIT::compileOpStrictEq(Instruction* currentInstruction, CompileOpStrictEqType type)
2494 {
2495     unsigned dst = currentInstruction[1].u.operand;
2496     unsigned src1 = currentInstruction[2].u.operand;
2497     unsigned src2 = currentInstruction[3].u.operand;
2498 
2499     emitGetVirtualRegisters(src1, regT0, src2, regT1);
2500 
2501     // Jump to a slow case if either operand is a number, or if both are JSCell*s.
2502     move(regT0, regT2);
2503     orPtr(regT1, regT2);
2504     addSlowCase(emitJumpIfJSCell(regT2));
2505     addSlowCase(emitJumpIfImmediateNumber(regT2));
2506 
2507     if (type == OpStrictEq)
2508         set32(Equal, regT1, regT0, regT0);
2509     else
2510         set32(NotEqual, regT1, regT0, regT0);
2511     emitTagAsBoolImmediate(regT0);
2512 
2513     emitPutVirtualRegister(dst);
2514 }
2515 
2516 void JIT::emit_op_stricteq(Instruction* currentInstruction)
2517 {
2518     compileOpStrictEq(currentInstruction, OpStrictEq);
2519 }
2520 
2521 void JIT::emit_op_nstricteq(Instruction* currentInstruction)
2522 {
2523     compileOpStrictEq(currentInstruction, OpNStrictEq);
2524 }
2525 
2526 void JIT::emit_op_to_jsnumber(Instruction* currentInstruction)
2527 {
2528     int srcVReg = currentInstruction[2].u.operand;
2529     emitGetVirtualRegister(srcVReg, regT0);
2530 
2531     Jump wasImmediate = emitJumpIfImmediateInteger(regT0);
2532 
2533     emitJumpSlowCaseIfNotJSCell(regT0, srcVReg);
2534     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
2535     addSlowCase(branch32(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(NumberType)));
2536 
2537     wasImmediate.link(this);
2538 
2539     emitPutVirtualRegister(currentInstruction[1].u.operand);
2540 }
2541 
2542 void JIT::emit_op_push_new_scope(Instruction* currentInstruction)
2543 {
2544     JITStubCall stubCall(this, cti_op_push_new_scope);
2545     stubCall.addArgument(ImmPtr(&m_codeBlock->identifier(currentInstruction[2].u.operand)));
2546     stubCall.addArgument(currentInstruction[3].u.operand, regT2);
2547     stubCall.call(currentInstruction[1].u.operand);
2548 }
2549 
2550 void JIT::emit_op_catch(Instruction* currentInstruction)
2551 {
2552     killLastResultRegister(); // FIXME: Implicitly treat op_catch as a labeled statement, and remove this line of code.
2553     peek(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof (void*));
2554     emitPutVirtualRegister(currentInstruction[1].u.operand);
2555 #ifdef QT_BUILD_SCRIPT_LIB
2556     JITStubCall stubCall(this, cti_op_debug_catch);
2557     stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
2558     stubCall.call();
2559 #endif
2560 }
2561 
2562 void JIT::emit_op_jmp_scopes(Instruction* currentInstruction)
2563 {
2564     JITStubCall stubCall(this, cti_op_jmp_scopes);
2565     stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
2566     stubCall.call();
2567     addJump(jump(), currentInstruction[2].u.operand);
2568     RECORD_JUMP_TARGET(currentInstruction[2].u.operand);
2569 }
2570 
2571 void JIT::emit_op_switch_imm(Instruction* currentInstruction)
2572 {
2573     unsigned tableIndex = currentInstruction[1].u.operand;
2574     unsigned defaultOffset = currentInstruction[2].u.operand;
2575     unsigned scrutinee = currentInstruction[3].u.operand;
2576 
2577     // create jump table for switch destinations, track this switch statement.
2578     SimpleJumpTable* jumpTable = &m_codeBlock->immediateSwitchJumpTable(tableIndex);
2579     m_switches.append(SwitchRecord(jumpTable, m_bytecodeIndex, defaultOffset, SwitchRecord::Immediate));
2580     jumpTable->ctiOffsets.grow(jumpTable->branchOffsets.size());
2581 
2582     JITStubCall stubCall(this, cti_op_switch_imm);
2583     stubCall.addArgument(scrutinee, regT2);
2584     stubCall.addArgument(Imm32(tableIndex));
2585     stubCall.call();
2586     jump(regT0);
2587 }
2588 
2589 void JIT::emit_op_switch_char(Instruction* currentInstruction)
2590 {
2591     unsigned tableIndex = currentInstruction[1].u.operand;
2592     unsigned defaultOffset = currentInstruction[2].u.operand;
2593     unsigned scrutinee = currentInstruction[3].u.operand;
2594 
2595     // create jump table for switch destinations, track this switch statement.
2596     SimpleJumpTable* jumpTable = &m_codeBlock->characterSwitchJumpTable(tableIndex);
2597     m_switches.append(SwitchRecord(jumpTable, m_bytecodeIndex, defaultOffset, SwitchRecord::Character));
2598     jumpTable->ctiOffsets.grow(jumpTable->branchOffsets.size());
2599 
2600     JITStubCall stubCall(this, cti_op_switch_char);
2601     stubCall.addArgument(scrutinee, regT2);
2602     stubCall.addArgument(Imm32(tableIndex));
2603     stubCall.call();
2604     jump(regT0);
2605 }
2606 
2607 void JIT::emit_op_switch_string(Instruction* currentInstruction)
2608 {
2609     unsigned tableIndex = currentInstruction[1].u.operand;
2610     unsigned defaultOffset = currentInstruction[2].u.operand;
2611     unsigned scrutinee = currentInstruction[3].u.operand;
2612 
2613     // create jump table for switch destinations, track this switch statement.
2614     StringJumpTable* jumpTable = &m_codeBlock->stringSwitchJumpTable(tableIndex);
2615     m_switches.append(SwitchRecord(jumpTable, m_bytecodeIndex, defaultOffset));
2616 
2617     JITStubCall stubCall(this, cti_op_switch_string);
2618     stubCall.addArgument(scrutinee, regT2);
2619     stubCall.addArgument(Imm32(tableIndex));
2620     stubCall.call();
2621     jump(regT0);
2622 }
2623 
2624 void JIT::emit_op_new_error(Instruction* currentInstruction)
2625 {
2626     JITStubCall stubCall(this, cti_op_new_error);
2627     stubCall.addArgument(Imm32(currentInstruction[2].u.operand));
2628     stubCall.addArgument(ImmPtr(JSValue::encode(m_codeBlock->getConstant(currentInstruction[3].u.operand))));
2629     stubCall.addArgument(Imm32(m_bytecodeIndex));
2630     stubCall.call(currentInstruction[1].u.operand);
2631 }
2632 
2633 void JIT::emit_op_debug(Instruction* currentInstruction)
2634 {
2635     JITStubCall stubCall(this, cti_op_debug);
2636     stubCall.addArgument(Imm32(currentInstruction[1].u.operand));
2637     stubCall.addArgument(Imm32(currentInstruction[2].u.operand));
2638     stubCall.addArgument(Imm32(currentInstruction[3].u.operand));
2639     stubCall.call();
2640 }
2641 
2642 void JIT::emit_op_eq_null(Instruction* currentInstruction)
2643 {
2644     unsigned dst = currentInstruction[1].u.operand;
2645     unsigned src1 = currentInstruction[2].u.operand;
2646 
2647     emitGetVirtualRegister(src1, regT0);
2648     Jump isImmediate = emitJumpIfNotJSCell(regT0);
2649 
2650     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
2651     setTest32(NonZero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined), regT0);
2652 
2653     Jump wasNotImmediate = jump();
2654 
2655     isImmediate.link(this);
2656 
2657     andPtr(Imm32(~JSImmediate::ExtendedTagBitUndefined), regT0);
2658     setPtr(Equal, regT0, Imm32(JSImmediate::FullTagTypeNull), regT0);
2659 
2660     wasNotImmediate.link(this);
2661 
2662     emitTagAsBoolImmediate(regT0);
2663     emitPutVirtualRegister(dst);
2664 
2665 }
2666 
2667 void JIT::emit_op_neq_null(Instruction* currentInstruction)
2668 {
2669     unsigned dst = currentInstruction[1].u.operand;
2670     unsigned src1 = currentInstruction[2].u.operand;
2671 
2672     emitGetVirtualRegister(src1, regT0);
2673     Jump isImmediate = emitJumpIfNotJSCell(regT0);
2674 
2675     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2);
2676     setTest32(Zero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined), regT0);
2677 
2678     Jump wasNotImmediate = jump();
2679 
2680     isImmediate.link(this);
2681 
2682     andPtr(Imm32(~JSImmediate::ExtendedTagBitUndefined), regT0);
2683     setPtr(NotEqual, regT0, Imm32(JSImmediate::FullTagTypeNull), regT0);
2684 
2685     wasNotImmediate.link(this);
2686 
2687     emitTagAsBoolImmediate(regT0);
2688     emitPutVirtualRegister(dst);
2689 
2690 }
2691 
2692 void JIT::emit_op_enter(Instruction*)
2693 {
2694     // Even though CTI doesn't use them, we initialize our constant
2695     // registers to zap stale pointers, to avoid unnecessarily prolonging
2696     // object lifetime and increasing GC pressure.
2697     size_t count = m_codeBlock->m_numVars;
2698     for (size_t j = 0; j < count; ++j)
2699         emitInitRegister(j);
2700 
2701 }
2702 
2703 void JIT::emit_op_enter_with_activation(Instruction* currentInstruction)
2704 {
2705     // Even though CTI doesn't use them, we initialize our constant
2706     // registers to zap stale pointers, to avoid unnecessarily prolonging
2707     // object lifetime and increasing GC pressure.
2708     size_t count = m_codeBlock->m_numVars;
2709     for (size_t j = 0; j < count; ++j)
2710         emitInitRegister(j);
2711 
2712     JITStubCall(this, cti_op_push_activation).call(currentInstruction[1].u.operand);
2713 }
2714 
2715 void JIT::emit_op_create_arguments(Instruction*)
2716 {
2717     Jump argsCreated = branchTestPtr(NonZero, Address(callFrameRegister, sizeof(Register) * RegisterFile::ArgumentsRegister));
2718     if (m_codeBlock->m_numParameters == 1)
2719         JITStubCall(this, cti_op_create_arguments_no_params).call();
2720     else
2721         JITStubCall(this, cti_op_create_arguments).call();
2722     argsCreated.link(this);
2723 }
2724 
2725 void JIT::emit_op_init_arguments(Instruction*)
2726 {
2727     storePtr(ImmPtr(0), Address(callFrameRegister, sizeof(Register) * RegisterFile::ArgumentsRegister));
2728 }
2729 
2730 void JIT::emit_op_convert_this(Instruction* currentInstruction)
2731 {
2732     emitGetVirtualRegister(currentInstruction[1].u.operand, regT0);
2733 
2734     emitJumpSlowCaseIfNotJSCell(regT0);
2735     loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT1);
2736     addSlowCase(branchTest32(NonZero, Address(regT1, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(NeedsThisConversion)));
2737 
2738 }
2739 
2740 void JIT::emit_op_profile_will_call(Instruction* currentInstruction)
2741 {
2742     peek(regT1, OBJECT_OFFSETOF(JITStackFrame, enabledProfilerReference) / sizeof (void*));
2743     Jump noProfiler = branchTestPtr(Zero, Address(regT1));
2744 
2745     JITStubCall stubCall(this, cti_op_profile_will_call);
2746     stubCall.addArgument(currentInstruction[1].u.operand, regT1);
2747     stubCall.call();
2748     noProfiler.link(this);
2749 
2750 }
2751 
2752 void JIT::emit_op_profile_did_call(Instruction* currentInstruction)
2753 {
2754     peek(regT1, OBJECT_OFFSETOF(JITStackFrame, enabledProfilerReference) / sizeof (void*));
2755     Jump noProfiler = branchTestPtr(Zero, Address(regT1));
2756 
2757     JITStubCall stubCall(this, cti_op_profile_did_call);
2758     stubCall.addArgument(currentInstruction[1].u.operand, regT1);
2759     stubCall.call();
2760     noProfiler.link(this);
2761 }
2762 
2763 
2764 // Slow cases
2765 
2766 void JIT::emitSlow_op_convert_this(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2767 {
2768     linkSlowCase(iter);
2769     linkSlowCase(iter);
2770     JITStubCall stubCall(this, cti_op_convert_this);
2771     stubCall.addArgument(regT0);
2772     stubCall.call(currentInstruction[1].u.operand);
2773 }
2774 
2775 void JIT::emitSlow_op_construct_verify(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2776 {
2777     linkSlowCase(iter);
2778     linkSlowCase(iter);
2779     emitGetVirtualRegister(currentInstruction[2].u.operand, regT0);
2780     emitPutVirtualRegister(currentInstruction[1].u.operand);
2781 }
2782 
2783 void JIT::emitSlow_op_to_primitive(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2784 {
2785     linkSlowCase(iter);
2786 
2787     JITStubCall stubCall(this, cti_op_to_primitive);
2788     stubCall.addArgument(regT0);
2789     stubCall.call(currentInstruction[1].u.operand);
2790 }
2791 
2792 void JIT::emitSlow_op_get_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2793 {
2794     unsigned dst = currentInstruction[1].u.operand;
2795     unsigned base = currentInstruction[2].u.operand;
2796     unsigned property = currentInstruction[3].u.operand;
2797 
2798     linkSlowCase(iter); // property int32 check
2799     linkSlowCaseIfNotJSCell(iter, base); // base cell check
2800     linkSlowCase(iter); // base array check
2801     linkSlowCase(iter); // vector length check
2802     linkSlowCase(iter); // empty value
2803 
2804     JITStubCall stubCall(this, cti_op_get_by_val);
2805     stubCall.addArgument(base, regT2);
2806     stubCall.addArgument(property, regT2);
2807     stubCall.call(dst);
2808 }
2809 
2810 void JIT::emitSlow_op_loop_if_lesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2811 {
2812     unsigned op2 = currentInstruction[2].u.operand;
2813     unsigned target = currentInstruction[3].u.operand;
2814     if (isOperandConstantImmediateInt(op2)) {
2815         linkSlowCase(iter);
2816         JITStubCall stubCall(this, cti_op_loop_if_lesseq);
2817         stubCall.addArgument(regT0);
2818         stubCall.addArgument(currentInstruction[2].u.operand, regT2);
2819         stubCall.call();
2820         emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
2821     } else {
2822         linkSlowCase(iter);
2823         linkSlowCase(iter);
2824         JITStubCall stubCall(this, cti_op_loop_if_lesseq);
2825         stubCall.addArgument(regT0);
2826         stubCall.addArgument(regT1);
2827         stubCall.call();
2828         emitJumpSlowToHot(branchTest32(NonZero, regT0), target);
2829     }
2830 }
2831 
2832 void JIT::emitSlow_op_put_by_val(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2833 {
2834     unsigned base = currentInstruction[1].u.operand;
2835     unsigned property = currentInstruction[2].u.operand;
2836     unsigned value = currentInstruction[3].u.operand;
2837 
2838     linkSlowCase(iter); // property int32 check
2839     linkSlowCaseIfNotJSCell(iter, base); // base cell check
2840     linkSlowCase(iter); // base not array check
2841     linkSlowCase(iter); // in vector check
2842 
2843     JITStubCall stubPutByValCall(this, cti_op_put_by_val);
2844     stubPutByValCall.addArgument(regT0);
2845     stubPutByValCall.addArgument(property, regT2);
2846     stubPutByValCall.addArgument(value, regT2);
2847     stubPutByValCall.call();
2848 }
2849 
2850 void JIT::emitSlow_op_not(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2851 {
2852     linkSlowCase(iter);
2853     xorPtr(Imm32(static_cast<int32_t>(JSImmediate::FullTagTypeBool)), regT0);
2854     JITStubCall stubCall(this, cti_op_not);
2855     stubCall.addArgument(regT0);
2856     stubCall.call(currentInstruction[1].u.operand);
2857 }
2858 
2859 void JIT::emitSlow_op_jfalse(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2860 {
2861     linkSlowCase(iter);
2862     JITStubCall stubCall(this, cti_op_jtrue);
2863     stubCall.addArgument(regT0);
2864     stubCall.call();
2865     emitJumpSlowToHot(branchTest32(Zero, regT0), currentInstruction[2].u.operand); // inverted!
2866 }
2867 
2868 void JIT::emitSlow_op_bitnot(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2869 {
2870     linkSlowCase(iter);
2871     JITStubCall stubCall(this, cti_op_bitnot);
2872     stubCall.addArgument(regT0);
2873     stubCall.call(currentInstruction[1].u.operand);
2874 }
2875 
2876 void JIT::emitSlow_op_jtrue(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2877 {
2878     linkSlowCase(iter);
2879     JITStubCall stubCall(this, cti_op_jtrue);
2880     stubCall.addArgument(regT0);
2881     stubCall.call();
2882     emitJumpSlowToHot(branchTest32(NonZero, regT0), currentInstruction[2].u.operand);
2883 }
2884 
2885 void JIT::emitSlow_op_bitxor(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2886 {
2887     linkSlowCase(iter);
2888     JITStubCall stubCall(this, cti_op_bitxor);
2889     stubCall.addArgument(regT0);
2890     stubCall.addArgument(regT1);
2891     stubCall.call(currentInstruction[1].u.operand);
2892 }
2893 
2894 void JIT::emitSlow_op_bitor(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2895 {
2896     linkSlowCase(iter);
2897     JITStubCall stubCall(this, cti_op_bitor);
2898     stubCall.addArgument(regT0);
2899     stubCall.addArgument(regT1);
2900     stubCall.call(currentInstruction[1].u.operand);
2901 }
2902 
2903 void JIT::emitSlow_op_eq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2904 {
2905     linkSlowCase(iter);
2906     JITStubCall stubCall(this, cti_op_eq);
2907     stubCall.addArgument(regT0);
2908     stubCall.addArgument(regT1);
2909     stubCall.call();
2910     emitTagAsBoolImmediate(regT0);
2911     emitPutVirtualRegister(currentInstruction[1].u.operand);
2912 }
2913 
2914 void JIT::emitSlow_op_neq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2915 {
2916     linkSlowCase(iter);
2917     JITStubCall stubCall(this, cti_op_eq);
2918     stubCall.addArgument(regT0);
2919     stubCall.addArgument(regT1);
2920     stubCall.call();
2921     xor32(Imm32(0x1), regT0);
2922     emitTagAsBoolImmediate(regT0);
2923     emitPutVirtualRegister(currentInstruction[1].u.operand);
2924 }
2925 
2926 void JIT::emitSlow_op_stricteq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2927 {
2928     linkSlowCase(iter);
2929     linkSlowCase(iter);
2930     JITStubCall stubCall(this, cti_op_stricteq);
2931     stubCall.addArgument(regT0);
2932     stubCall.addArgument(regT1);
2933     stubCall.call(currentInstruction[1].u.operand);
2934 }
2935 
2936 void JIT::emitSlow_op_nstricteq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2937 {
2938     linkSlowCase(iter);
2939     linkSlowCase(iter);
2940     JITStubCall stubCall(this, cti_op_nstricteq);
2941     stubCall.addArgument(regT0);
2942     stubCall.addArgument(regT1);
2943     stubCall.call(currentInstruction[1].u.operand);
2944 }
2945 
2946 void JIT::emitSlow_op_instanceof(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2947 {
2948     unsigned dst = currentInstruction[1].u.operand;
2949     unsigned value = currentInstruction[2].u.operand;
2950     unsigned baseVal = currentInstruction[3].u.operand;
2951     unsigned proto = currentInstruction[4].u.operand;
2952 
2953     linkSlowCaseIfNotJSCell(iter, value);
2954     linkSlowCaseIfNotJSCell(iter, baseVal);
2955     linkSlowCaseIfNotJSCell(iter, proto);
2956     linkSlowCase(iter);
2957     JITStubCall stubCall(this, cti_op_instanceof);
2958     stubCall.addArgument(value, regT2);
2959     stubCall.addArgument(baseVal, regT2);
2960     stubCall.addArgument(proto, regT2);
2961     stubCall.call(dst);
2962 }
2963 
2964 void JIT::emitSlow_op_call(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2965 {
2966     compileOpCallSlowCase(currentInstruction, iter, m_callLinkInfoIndex++, op_call);
2967 }
2968 
2969 void JIT::emitSlow_op_call_eval(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2970 {
2971     compileOpCallSlowCase(currentInstruction, iter, m_callLinkInfoIndex++, op_call_eval);
2972 }
2973 
2974 void JIT::emitSlow_op_call_varargs(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2975 {
2976     compileOpCallVarargsSlowCase(currentInstruction, iter);
2977 }
2978 
2979 void JIT::emitSlow_op_construct(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2980 {
2981     compileOpCallSlowCase(currentInstruction, iter, m_callLinkInfoIndex++, op_construct);
2982 }
2983 
2984 void JIT::emitSlow_op_to_jsnumber(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
2985 {
2986     linkSlowCaseIfNotJSCell(iter, currentInstruction[2].u.operand);
2987     linkSlowCase(iter);
2988 
2989     JITStubCall stubCall(this, cti_op_to_jsnumber);
2990     stubCall.addArgument(regT0);
2991     stubCall.call(currentInstruction[1].u.operand);
2992 }
2993 
2994 #endif // USE(JSVALUE32_64)
2995 
2996 } // namespace JSC
2997 
2998 #endif // ENABLE(JIT)
2999