AssemblyHelpers should not have a VM field
[WebKit.git] / Source / JavaScriptCore / jit / JITOpcodes32_64.cpp
1 /*
2  * Copyright (C) 2009, 2012-2016 Apple Inc. All rights reserved.
3  * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28
29 #if ENABLE(JIT)
30 #if USE(JSVALUE32_64)
31 #include "JIT.h"
32
33 #include "CCallHelpers.h"
34 #include "Exception.h"
35 #include "JITInlines.h"
36 #include "JSArray.h"
37 #include "JSCell.h"
38 #include "JSFunction.h"
39 #include "JSPropertyNameEnumerator.h"
40 #include "LinkBuffer.h"
41 #include "MaxFrameExtentForSlowPathCall.h"
42 #include "Opcode.h"
43 #include "SlowPathCall.h"
44 #include "TypeProfilerLog.h"
45 #include "VirtualRegister.h"
46
47 namespace JSC {
48
49 JIT::CodeRef JIT::privateCompileCTINativeCall(VM* vm, NativeFunction func)
50 {
51     // FIXME: This should be able to log ShadowChicken prologue packets.
52     // https://bugs.webkit.org/show_bug.cgi?id=155689
53     
54     Call nativeCall;
55
56     emitFunctionPrologue();
57     emitPutToCallFrameHeader(0, CallFrameSlot::codeBlock);
58     storePtr(callFrameRegister, &vm->topCallFrame);
59
60 #if CPU(X86)
61     // Calling convention:      f(ecx, edx, ...);
62     // Host function signature: f(ExecState*);
63     move(callFrameRegister, X86Registers::ecx);
64
65     subPtr(TrustedImm32(8), stackPointerRegister); // Align stack for call.
66     storePtr(X86Registers::ecx, Address(stackPointerRegister));
67
68     // call the function
69     nativeCall = call();
70
71     addPtr(TrustedImm32(8), stackPointerRegister);
72
73 #elif CPU(ARM) || CPU(MIPS)
74 #if CPU(MIPS)
75     // Allocate stack space for (unused) 16 bytes (8-byte aligned) for 4 arguments.
76     subPtr(TrustedImm32(16), stackPointerRegister);
77 #endif
78
79     // Calling convention is f(argumentGPR0, argumentGPR1, ...).
80     // Host function signature is f(ExecState*).
81     move(callFrameRegister, argumentGPR0);
82
83     emitGetFromCallFrameHeaderPtr(CallFrameSlot::callee, argumentGPR1);
84     loadPtr(Address(argumentGPR1, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
85
86     // call the function
87     nativeCall = call();
88
89 #if CPU(MIPS)
90     // Restore stack space
91     addPtr(TrustedImm32(16), stackPointerRegister);
92 #endif
93
94     restoreReturnAddressBeforeReturn(regT3);
95 #else
96 #error "JIT not supported on this platform."
97     abortWithReason(JITNotSupported);
98 #endif // CPU(X86)
99
100     // Check for an exception
101     Jump sawException = branch32(NotEqual, AbsoluteAddress(vm->addressOfException()), TrustedImm32(0));
102
103     emitFunctionEpilogue();
104     // Return.
105     ret();
106
107     // Handle an exception
108     sawException.link(this);
109
110     storePtr(callFrameRegister, &vm->topCallFrame);
111
112 #if CPU(X86)
113     addPtr(TrustedImm32(-4), stackPointerRegister);
114     move(callFrameRegister, X86Registers::ecx);
115     push(X86Registers::ecx);
116 #else
117     move(callFrameRegister, argumentGPR0);
118 #endif
119     move(TrustedImmPtr(FunctionPtr(operationVMHandleException).value()), regT3);
120     call(regT3);
121
122 #if CPU(X86)
123     addPtr(TrustedImm32(8), stackPointerRegister);
124 #endif
125
126     jumpToExceptionHandler(*vm);
127
128     // All trampolines constructed! copy the code, link up calls, and set the pointers on the Machine object.
129     LinkBuffer patchBuffer(*vm, *this, GLOBAL_THUNK_ID);
130
131     patchBuffer.link(nativeCall, FunctionPtr(func));
132     return FINALIZE_CODE(patchBuffer, ("JIT CTI native call"));
133 }
134
135 void JIT::emit_op_mov(Instruction* currentInstruction)
136 {
137     int dst = currentInstruction[1].u.operand;
138     int src = currentInstruction[2].u.operand;
139     
140     if (m_codeBlock->isConstantRegisterIndex(src))
141         emitStore(dst, getConstantOperand(src));
142     else {
143         emitLoad(src, regT1, regT0);
144         emitStore(dst, regT1, regT0);
145     }
146 }
147
148 void JIT::emit_op_end(Instruction* currentInstruction)
149 {
150     ASSERT(returnValueGPR != callFrameRegister);
151     emitLoad(currentInstruction[1].u.operand, regT1, returnValueGPR);
152     emitRestoreCalleeSaves();
153     emitFunctionEpilogue();
154     ret();
155 }
156
157 void JIT::emit_op_jmp(Instruction* currentInstruction)
158 {
159     unsigned target = currentInstruction[1].u.operand;
160     addJump(jump(), target);
161 }
162
163 void JIT::emit_op_new_object(Instruction* currentInstruction)
164 {
165     Structure* structure = currentInstruction[3].u.objectAllocationProfile->structure();
166     size_t allocationSize = JSFinalObject::allocationSize(structure->inlineCapacity());
167     MarkedAllocator* allocator = subspaceFor<JSFinalObject>(*m_vm)->allocatorFor(allocationSize);
168
169     RegisterID resultReg = returnValueGPR;
170     RegisterID allocatorReg = regT1;
171     RegisterID scratchReg = regT3;
172
173     move(TrustedImmPtr(allocator), allocatorReg);
174     if (allocator)
175         addSlowCase(Jump());
176     JumpList slowCases;
177     emitAllocateJSObject(resultReg, allocator, allocatorReg, TrustedImmPtr(structure), TrustedImmPtr(0), scratchReg, slowCases);
178     emitInitializeInlineStorage(resultReg, structure->inlineCapacity());
179     addSlowCase(slowCases);
180     emitStoreCell(currentInstruction[1].u.operand, resultReg);
181 }
182
183 void JIT::emitSlow_op_new_object(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
184 {
185     linkSlowCase(iter);
186     linkSlowCase(iter);
187     int dst = currentInstruction[1].u.operand;
188     Structure* structure = currentInstruction[3].u.objectAllocationProfile->structure();
189     callOperation(operationNewObject, structure);
190     emitStoreCell(dst, returnValueGPR);
191 }
192
193 void JIT::emit_op_overrides_has_instance(Instruction* currentInstruction)
194 {
195     int dst = currentInstruction[1].u.operand;
196     int constructor = currentInstruction[2].u.operand;
197     int hasInstanceValue = currentInstruction[3].u.operand;
198
199     emitLoadPayload(hasInstanceValue, regT0);
200     // We don't jump if we know what Symbol.hasInstance would do.
201     Jump hasInstanceValueNotCell = emitJumpIfNotJSCell(hasInstanceValue);
202     Jump customhasInstanceValue = branchPtr(NotEqual, regT0, TrustedImmPtr(m_codeBlock->globalObject()->functionProtoHasInstanceSymbolFunction()));
203
204     // We know that constructor is an object from the way bytecode is emitted for instanceof expressions.
205     emitLoadPayload(constructor, regT0);
206
207     // Check that constructor 'ImplementsDefaultHasInstance' i.e. the object is not a C-API user nor a bound function.
208     test8(Zero, Address(regT0, JSCell::typeInfoFlagsOffset()), TrustedImm32(ImplementsDefaultHasInstance), regT0);
209     Jump done = jump();
210
211     hasInstanceValueNotCell.link(this);
212     customhasInstanceValue.link(this);
213     move(TrustedImm32(1), regT0);
214
215     done.link(this);
216     emitStoreBool(dst, regT0);
217
218 }
219
220 void JIT::emit_op_instanceof(Instruction* currentInstruction)
221 {
222     int dst = currentInstruction[1].u.operand;
223     int value = currentInstruction[2].u.operand;
224     int proto = currentInstruction[3].u.operand;
225
226     // Load the operands into registers.
227     // We use regT0 for baseVal since we will be done with this first, and we can then use it for the result.
228     emitLoadPayload(value, regT2);
229     emitLoadPayload(proto, regT1);
230
231     // Check that proto are cells. baseVal must be a cell - this is checked by the get_by_id for Symbol.hasInstance.
232     emitJumpSlowCaseIfNotJSCell(value);
233     emitJumpSlowCaseIfNotJSCell(proto);
234     
235     // Check that prototype is an object
236     addSlowCase(emitJumpIfCellNotObject(regT1));
237
238     // Optimistically load the result true, and start looping.
239     // Initially, regT1 still contains proto and regT2 still contains value.
240     // As we loop regT2 will be updated with its prototype, recursively walking the prototype chain.
241     move(TrustedImm32(1), regT0);
242     Label loop(this);
243
244     addSlowCase(branch8(Equal, Address(regT2, JSCell::typeInfoTypeOffset()), TrustedImm32(ProxyObjectType)));
245
246     // Load the prototype of the cell in regT2.  If this is equal to regT1 - WIN!
247     // Otherwise, check if we've hit null - if we have then drop out of the loop, if not go again.
248     loadPtr(Address(regT2, JSCell::structureIDOffset()), regT2);
249     load32(Address(regT2, Structure::prototypeOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT2);
250     Jump isInstance = branchPtr(Equal, regT2, regT1);
251     branchTest32(NonZero, regT2).linkTo(loop, this);
252
253     // We get here either by dropping out of the loop, or if value was not an Object.  Result is false.
254     move(TrustedImm32(0), regT0);
255
256     // isInstance jumps right down to here, to skip setting the result to false (it has already set true).
257     isInstance.link(this);
258     emitStoreBool(dst, regT0);
259 }
260
261 void JIT::emit_op_instanceof_custom(Instruction*)
262 {
263     // This always goes to slow path since we expect it to be rare.
264     addSlowCase(jump());
265 }
266
267 void JIT::emitSlow_op_instanceof(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
268 {
269     int dst = currentInstruction[1].u.operand;
270     int value = currentInstruction[2].u.operand;
271     int proto = currentInstruction[3].u.operand;
272
273     linkSlowCaseIfNotJSCell(iter, value);
274     linkSlowCaseIfNotJSCell(iter, proto);
275     linkSlowCase(iter);
276     linkSlowCase(iter);
277
278     emitLoad(value, regT1, regT0);
279     emitLoad(proto, regT3, regT2);
280     callOperation(operationInstanceOf, dst, regT1, regT0, regT3, regT2);
281 }
282
283 void JIT::emitSlow_op_instanceof_custom(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
284 {
285     int dst = currentInstruction[1].u.operand;
286     int value = currentInstruction[2].u.operand;
287     int constructor = currentInstruction[3].u.operand;
288     int hasInstanceValue = currentInstruction[4].u.operand;
289
290     linkSlowCase(iter);
291
292     emitLoad(value, regT1, regT0);
293     emitLoadPayload(constructor, regT2);
294     emitLoad(hasInstanceValue, regT4, regT3);
295     callOperation(operationInstanceOfCustom, regT1, regT0, regT2, regT4, regT3);
296     emitStoreBool(dst, returnValueGPR);
297 }
298     
299 void JIT::emit_op_is_empty(Instruction* currentInstruction)
300 {
301     int dst = currentInstruction[1].u.operand;
302     int value = currentInstruction[2].u.operand;
303     
304     emitLoad(value, regT1, regT0);
305     compare32(Equal, regT1, TrustedImm32(JSValue::EmptyValueTag), regT0);
306
307     emitStoreBool(dst, regT0);
308 }
309
310 void JIT::emit_op_is_undefined(Instruction* currentInstruction)
311 {
312     int dst = currentInstruction[1].u.operand;
313     int value = currentInstruction[2].u.operand;
314     
315     emitLoad(value, regT1, regT0);
316     Jump isCell = branch32(Equal, regT1, TrustedImm32(JSValue::CellTag));
317
318     compare32(Equal, regT1, TrustedImm32(JSValue::UndefinedTag), regT0);
319     Jump done = jump();
320     
321     isCell.link(this);
322     Jump isMasqueradesAsUndefined = branchTest8(NonZero, Address(regT0, JSCell::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined));
323     move(TrustedImm32(0), regT0);
324     Jump notMasqueradesAsUndefined = jump();
325     
326     isMasqueradesAsUndefined.link(this);
327     loadPtr(Address(regT0, JSCell::structureIDOffset()), regT1);
328     move(TrustedImmPtr(m_codeBlock->globalObject()), regT0);
329     loadPtr(Address(regT1, Structure::globalObjectOffset()), regT1);
330     compare32(Equal, regT0, regT1, regT0);
331
332     notMasqueradesAsUndefined.link(this);
333     done.link(this);
334     emitStoreBool(dst, regT0);
335 }
336
337 void JIT::emit_op_is_boolean(Instruction* currentInstruction)
338 {
339     int dst = currentInstruction[1].u.operand;
340     int value = currentInstruction[2].u.operand;
341     
342     emitLoadTag(value, regT0);
343     compare32(Equal, regT0, TrustedImm32(JSValue::BooleanTag), regT0);
344     emitStoreBool(dst, regT0);
345 }
346
347 void JIT::emit_op_is_number(Instruction* currentInstruction)
348 {
349     int dst = currentInstruction[1].u.operand;
350     int value = currentInstruction[2].u.operand;
351     
352     emitLoadTag(value, regT0);
353     add32(TrustedImm32(1), regT0);
354     compare32(Below, regT0, TrustedImm32(JSValue::LowestTag + 1), regT0);
355     emitStoreBool(dst, regT0);
356 }
357
358 void JIT::emit_op_is_cell_with_type(Instruction* currentInstruction)
359 {
360     int dst = currentInstruction[1].u.operand;
361     int value = currentInstruction[2].u.operand;
362     int type = currentInstruction[3].u.operand;
363
364     emitLoad(value, regT1, regT0);
365     Jump isNotCell = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag));
366
367     compare8(Equal, Address(regT0, JSCell::typeInfoTypeOffset()), TrustedImm32(type), regT0);
368     Jump done = jump();
369
370     isNotCell.link(this);
371     move(TrustedImm32(0), regT0);
372
373     done.link(this);
374     emitStoreBool(dst, regT0);
375 }
376
377 void JIT::emit_op_is_object(Instruction* currentInstruction)
378 {
379     int dst = currentInstruction[1].u.operand;
380     int value = currentInstruction[2].u.operand;
381
382     emitLoad(value, regT1, regT0);
383     Jump isNotCell = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag));
384
385     compare8(AboveOrEqual, Address(regT0, JSCell::typeInfoTypeOffset()), TrustedImm32(ObjectType), regT0);
386     Jump done = jump();
387
388     isNotCell.link(this);
389     move(TrustedImm32(0), regT0);
390
391     done.link(this);
392     emitStoreBool(dst, regT0);
393 }
394
395 void JIT::emit_op_to_primitive(Instruction* currentInstruction)
396 {
397     int dst = currentInstruction[1].u.operand;
398     int src = currentInstruction[2].u.operand;
399
400     emitLoad(src, regT1, regT0);
401
402     Jump isImm = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag));
403     addSlowCase(emitJumpIfCellObject(regT0));
404     isImm.link(this);
405
406     if (dst != src)
407         emitStore(dst, regT1, regT0);
408 }
409
410 void JIT::emitSlow_op_to_primitive(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
411 {
412     linkSlowCase(iter);
413
414     JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_to_primitive);
415     slowPathCall.call();
416 }
417
418 void JIT::emit_op_set_function_name(Instruction* currentInstruction)
419 {
420     int func = currentInstruction[1].u.operand;
421     int name = currentInstruction[2].u.operand;
422     emitLoadPayload(func, regT1);
423     emitLoad(name, regT3, regT2);
424     callOperation(operationSetFunctionName, regT1, regT3, regT2);
425 }
426
427 void JIT::emit_op_strcat(Instruction* currentInstruction)
428 {
429     JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_strcat);
430     slowPathCall.call();
431 }
432
433 void JIT::emit_op_not(Instruction* currentInstruction)
434 {
435     int dst = currentInstruction[1].u.operand;
436     int src = currentInstruction[2].u.operand;
437
438     emitLoadTag(src, regT0);
439
440     emitLoad(src, regT1, regT0);
441     addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::BooleanTag)));
442     xor32(TrustedImm32(1), regT0);
443
444     emitStoreBool(dst, regT0, (dst == src));
445 }
446
447 void JIT::emitSlow_op_not(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
448 {
449     linkSlowCase(iter);
450
451     JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_not);
452     slowPathCall.call();
453 }
454
455 void JIT::emit_op_jfalse(Instruction* currentInstruction)
456 {
457     int cond = currentInstruction[1].u.operand;
458     unsigned target = currentInstruction[2].u.operand;
459
460     emitLoad(cond, regT1, regT0);
461
462     JSValueRegs value(regT1, regT0);
463     GPRReg scratch = regT2;
464     GPRReg result = regT3;
465     bool shouldCheckMasqueradesAsUndefined = true;
466     emitConvertValueToBoolean(*vm(), value, result, scratch, fpRegT0, fpRegT1, shouldCheckMasqueradesAsUndefined, m_codeBlock->globalObject());
467
468     addJump(branchTest32(Zero, result), target);
469 }
470
471 void JIT::emit_op_jtrue(Instruction* currentInstruction)
472 {
473     int cond = currentInstruction[1].u.operand;
474     unsigned target = currentInstruction[2].u.operand;
475
476     emitLoad(cond, regT1, regT0);
477     bool shouldCheckMasqueradesAsUndefined = true;
478     JSValueRegs value(regT1, regT0);
479     GPRReg scratch = regT2;
480     GPRReg result = regT3;
481     emitConvertValueToBoolean(*vm(), value, result, scratch, fpRegT0, fpRegT1, shouldCheckMasqueradesAsUndefined, m_codeBlock->globalObject());
482
483     addJump(branchTest32(NonZero, result), target);
484 }
485
486 void JIT::emit_op_jeq_null(Instruction* currentInstruction)
487 {
488     int src = currentInstruction[1].u.operand;
489     unsigned target = currentInstruction[2].u.operand;
490
491     emitLoad(src, regT1, regT0);
492
493     Jump isImmediate = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag));
494
495     Jump isNotMasqueradesAsUndefined = branchTest8(Zero, Address(regT0, JSCell::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined));
496     loadPtr(Address(regT0, JSCell::structureIDOffset()), regT2);
497     move(TrustedImmPtr(m_codeBlock->globalObject()), regT0);
498     addJump(branchPtr(Equal, Address(regT2, Structure::globalObjectOffset()), regT0), target);
499     Jump masqueradesGlobalObjectIsForeign = jump();
500
501     // Now handle the immediate cases - undefined & null
502     isImmediate.link(this);
503     ASSERT((JSValue::UndefinedTag + 1 == JSValue::NullTag) && (JSValue::NullTag & 0x1));
504     or32(TrustedImm32(1), regT1);
505     addJump(branch32(Equal, regT1, TrustedImm32(JSValue::NullTag)), target);
506
507     isNotMasqueradesAsUndefined.link(this);
508     masqueradesGlobalObjectIsForeign.link(this);
509 }
510
511 void JIT::emit_op_jneq_null(Instruction* currentInstruction)
512 {
513     int src = currentInstruction[1].u.operand;
514     unsigned target = currentInstruction[2].u.operand;
515
516     emitLoad(src, regT1, regT0);
517
518     Jump isImmediate = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag));
519
520     addJump(branchTest8(Zero, Address(regT0, JSCell::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined)), target);
521     loadPtr(Address(regT0, JSCell::structureIDOffset()), regT2);
522     move(TrustedImmPtr(m_codeBlock->globalObject()), regT0);
523     addJump(branchPtr(NotEqual, Address(regT2, Structure::globalObjectOffset()), regT0), target);
524     Jump wasNotImmediate = jump();
525
526     // Now handle the immediate cases - undefined & null
527     isImmediate.link(this);
528
529     ASSERT((JSValue::UndefinedTag + 1 == JSValue::NullTag) && (JSValue::NullTag & 0x1));
530     or32(TrustedImm32(1), regT1);
531     addJump(branch32(NotEqual, regT1, TrustedImm32(JSValue::NullTag)), target);
532
533     wasNotImmediate.link(this);
534 }
535
536 void JIT::emit_op_jneq_ptr(Instruction* currentInstruction)
537 {
538     int src = currentInstruction[1].u.operand;
539     Special::Pointer ptr = currentInstruction[2].u.specialPointer;
540     unsigned target = currentInstruction[3].u.operand;
541
542     emitLoad(src, regT1, regT0);
543     CCallHelpers::Jump notCell = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag));
544     CCallHelpers::Jump equal = branchPtr(Equal, regT0, TrustedImmPtr(actualPointerFor(m_codeBlock, ptr)));
545     notCell.link(this);
546     store32(TrustedImm32(1), &currentInstruction[4].u.operand);
547     addJump(jump(), target);
548     equal.link(this);
549 }
550
551 void JIT::emit_op_eq(Instruction* currentInstruction)
552 {
553     int dst = currentInstruction[1].u.operand;
554     int src1 = currentInstruction[2].u.operand;
555     int src2 = currentInstruction[3].u.operand;
556
557     emitLoad2(src1, regT1, regT0, src2, regT3, regT2);
558     addSlowCase(branch32(NotEqual, regT1, regT3));
559     addSlowCase(branch32(Equal, regT1, TrustedImm32(JSValue::CellTag)));
560     addSlowCase(branch32(Below, regT1, TrustedImm32(JSValue::LowestTag)));
561
562     compare32(Equal, regT0, regT2, regT0);
563
564     emitStoreBool(dst, regT0);
565 }
566
567 void JIT::emitSlow_op_eq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
568 {
569     int dst = currentInstruction[1].u.operand;
570     int op1 = currentInstruction[2].u.operand;
571     int op2 = currentInstruction[3].u.operand;
572
573     JumpList storeResult;
574     JumpList genericCase;
575
576     genericCase.append(getSlowCase(iter)); // tags not equal
577
578     linkSlowCase(iter); // tags equal and JSCell
579     genericCase.append(branchPtr(NotEqual, Address(regT0, JSCell::structureIDOffset()), TrustedImmPtr(m_vm->stringStructure.get())));
580     genericCase.append(branchPtr(NotEqual, Address(regT2, JSCell::structureIDOffset()), TrustedImmPtr(m_vm->stringStructure.get())));
581
582     // String case.
583     callOperation(operationCompareStringEq, regT0, regT2);
584     storeResult.append(jump());
585
586     // Generic case.
587     genericCase.append(getSlowCase(iter)); // doubles
588     genericCase.link(this);
589     emitLoad(op1, regT1, regT0);
590     emitLoad(op2, regT3, regT2);
591     callOperation(operationCompareEq, regT1, regT0, regT3, regT2);
592
593     storeResult.link(this);
594     emitStoreBool(dst, returnValueGPR);
595 }
596
597 void JIT::emit_op_neq(Instruction* currentInstruction)
598 {
599     int dst = currentInstruction[1].u.operand;
600     int src1 = currentInstruction[2].u.operand;
601     int src2 = currentInstruction[3].u.operand;
602
603     emitLoad2(src1, regT1, regT0, src2, regT3, regT2);
604     addSlowCase(branch32(NotEqual, regT1, regT3));
605     addSlowCase(branch32(Equal, regT1, TrustedImm32(JSValue::CellTag)));
606     addSlowCase(branch32(Below, regT1, TrustedImm32(JSValue::LowestTag)));
607
608     compare32(NotEqual, regT0, regT2, regT0);
609
610     emitStoreBool(dst, regT0);
611 }
612
613 void JIT::emitSlow_op_neq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
614 {
615     int dst = currentInstruction[1].u.operand;
616
617     JumpList storeResult;
618     JumpList genericCase;
619
620     genericCase.append(getSlowCase(iter)); // tags not equal
621
622     linkSlowCase(iter); // tags equal and JSCell
623     genericCase.append(branchPtr(NotEqual, Address(regT0, JSCell::structureIDOffset()), TrustedImmPtr(m_vm->stringStructure.get())));
624     genericCase.append(branchPtr(NotEqual, Address(regT2, JSCell::structureIDOffset()), TrustedImmPtr(m_vm->stringStructure.get())));
625
626     // String case.
627     callOperation(operationCompareStringEq, regT0, regT2);
628     storeResult.append(jump());
629
630     // Generic case.
631     genericCase.append(getSlowCase(iter)); // doubles
632     genericCase.link(this);
633     callOperation(operationCompareEq, regT1, regT0, regT3, regT2);
634
635     storeResult.link(this);
636     xor32(TrustedImm32(0x1), returnValueGPR);
637     emitStoreBool(dst, returnValueGPR);
638 }
639
640 void JIT::compileOpStrictEq(Instruction* currentInstruction, CompileOpStrictEqType type)
641 {
642     int dst = currentInstruction[1].u.operand;
643     int src1 = currentInstruction[2].u.operand;
644     int src2 = currentInstruction[3].u.operand;
645
646     emitLoad2(src1, regT1, regT0, src2, regT3, regT2);
647
648     // Bail if the tags differ, or are double.
649     addSlowCase(branch32(NotEqual, regT1, regT3));
650     addSlowCase(branch32(Below, regT1, TrustedImm32(JSValue::LowestTag)));
651
652     // Jump to a slow case if both are strings or symbols (non object).
653     Jump notCell = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag));
654     Jump firstIsObject = emitJumpIfCellObject(regT0);
655     addSlowCase(emitJumpIfCellNotObject(regT2));
656     notCell.link(this);
657     firstIsObject.link(this);
658
659     // Simply compare the payloads.
660     if (type == OpStrictEq)
661         compare32(Equal, regT0, regT2, regT0);
662     else
663         compare32(NotEqual, regT0, regT2, regT0);
664
665     emitStoreBool(dst, regT0);
666 }
667
668 void JIT::emit_op_stricteq(Instruction* currentInstruction)
669 {
670     compileOpStrictEq(currentInstruction, OpStrictEq);
671 }
672
673 void JIT::emitSlow_op_stricteq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
674 {
675     linkSlowCase(iter);
676     linkSlowCase(iter);
677     linkSlowCase(iter);
678
679     JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_stricteq);
680     slowPathCall.call();
681 }
682
683 void JIT::emit_op_nstricteq(Instruction* currentInstruction)
684 {
685     compileOpStrictEq(currentInstruction, OpNStrictEq);
686 }
687
688 void JIT::emitSlow_op_nstricteq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
689 {
690     linkSlowCase(iter);
691     linkSlowCase(iter);
692     linkSlowCase(iter);
693
694     JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_nstricteq);
695     slowPathCall.call();
696 }
697
698 void JIT::emit_op_eq_null(Instruction* currentInstruction)
699 {
700     int dst = currentInstruction[1].u.operand;
701     int src = currentInstruction[2].u.operand;
702
703     emitLoad(src, regT1, regT0);
704     Jump isImmediate = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag));
705
706     Jump isMasqueradesAsUndefined = branchTest8(NonZero, Address(regT0, JSCell::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined));
707     move(TrustedImm32(0), regT1);
708     Jump wasNotMasqueradesAsUndefined = jump();
709
710     isMasqueradesAsUndefined.link(this);
711     loadPtr(Address(regT0, JSCell::structureIDOffset()), regT2);
712     move(TrustedImmPtr(m_codeBlock->globalObject()), regT0);
713     loadPtr(Address(regT2, Structure::globalObjectOffset()), regT2);
714     compare32(Equal, regT0, regT2, regT1);
715     Jump wasNotImmediate = jump();
716
717     isImmediate.link(this);
718
719     compare32(Equal, regT1, TrustedImm32(JSValue::NullTag), regT2);
720     compare32(Equal, regT1, TrustedImm32(JSValue::UndefinedTag), regT1);
721     or32(regT2, regT1);
722
723     wasNotImmediate.link(this);
724     wasNotMasqueradesAsUndefined.link(this);
725
726     emitStoreBool(dst, regT1);
727 }
728
729 void JIT::emit_op_neq_null(Instruction* currentInstruction)
730 {
731     int dst = currentInstruction[1].u.operand;
732     int src = currentInstruction[2].u.operand;
733
734     emitLoad(src, regT1, regT0);
735     Jump isImmediate = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag));
736
737     Jump isMasqueradesAsUndefined = branchTest8(NonZero, Address(regT0, JSCell::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined));
738     move(TrustedImm32(1), regT1);
739     Jump wasNotMasqueradesAsUndefined = jump();
740
741     isMasqueradesAsUndefined.link(this);
742     loadPtr(Address(regT0, JSCell::structureIDOffset()), regT2);
743     move(TrustedImmPtr(m_codeBlock->globalObject()), regT0);
744     loadPtr(Address(regT2, Structure::globalObjectOffset()), regT2);
745     compare32(NotEqual, regT0, regT2, regT1);
746     Jump wasNotImmediate = jump();
747
748     isImmediate.link(this);
749
750     compare32(NotEqual, regT1, TrustedImm32(JSValue::NullTag), regT2);
751     compare32(NotEqual, regT1, TrustedImm32(JSValue::UndefinedTag), regT1);
752     and32(regT2, regT1);
753
754     wasNotImmediate.link(this);
755     wasNotMasqueradesAsUndefined.link(this);
756
757     emitStoreBool(dst, regT1);
758 }
759
760 void JIT::emit_op_throw(Instruction* currentInstruction)
761 {
762     ASSERT(regT0 == returnValueGPR);
763     copyCalleeSavesToVMEntryFrameCalleeSavesBuffer(*vm());
764     emitLoad(currentInstruction[1].u.operand, regT1, regT0);
765     callOperationNoExceptionCheck(operationThrow, regT1, regT0);
766     jumpToExceptionHandler(*vm());
767 }
768
769 void JIT::emit_op_push_with_scope(Instruction* currentInstruction)
770 {
771     JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_push_with_scope);
772     slowPathCall.call();
773 }
774
775 void JIT::emit_op_to_number(Instruction* currentInstruction)
776 {
777     int dst = currentInstruction[1].u.operand;
778     int src = currentInstruction[2].u.operand;
779
780     emitLoad(src, regT1, regT0);
781
782     Jump isInt32 = branch32(Equal, regT1, TrustedImm32(JSValue::Int32Tag));
783     addSlowCase(branch32(AboveOrEqual, regT1, TrustedImm32(JSValue::LowestTag)));
784     isInt32.link(this);
785
786     emitValueProfilingSite();
787     if (src != dst)
788         emitStore(dst, regT1, regT0);
789 }
790
791 void JIT::emitSlow_op_to_number(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
792 {
793     linkSlowCase(iter);
794
795     JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_to_number);
796     slowPathCall.call();
797 }
798
799 void JIT::emit_op_to_string(Instruction* currentInstruction)
800 {
801     int dst = currentInstruction[1].u.operand;
802     int src = currentInstruction[2].u.operand;
803
804     emitLoad(src, regT1, regT0);
805
806     addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)));
807     addSlowCase(branch8(NotEqual, Address(regT0, JSCell::typeInfoTypeOffset()), TrustedImm32(StringType)));
808
809     if (src != dst)
810         emitStore(dst, regT1, regT0);
811 }
812
813 void JIT::emitSlow_op_to_string(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
814 {
815     linkSlowCase(iter); // Not JSCell.
816     linkSlowCase(iter); // Not JSString.
817
818     JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_to_string);
819     slowPathCall.call();
820 }
821
822 void JIT::emit_op_catch(Instruction* currentInstruction)
823 {
824     restoreCalleeSavesFromVMEntryFrameCalleeSavesBuffer(*vm());
825
826     move(TrustedImmPtr(m_vm), regT3);
827     // operationThrow returns the callFrame for the handler.
828     load32(Address(regT3, VM::callFrameForCatchOffset()), callFrameRegister);
829     storePtr(TrustedImmPtr(nullptr), Address(regT3, VM::callFrameForCatchOffset()));
830
831     addPtr(TrustedImm32(stackPointerOffsetFor(codeBlock()) * sizeof(Register)), callFrameRegister, stackPointerRegister);
832
833     callOperationNoExceptionCheck(operationCheckIfExceptionIsUncatchableAndNotifyProfiler);
834     Jump isCatchableException = branchTest32(Zero, returnValueGPR);
835     jumpToExceptionHandler(*vm());
836     isCatchableException.link(this);
837
838     move(TrustedImmPtr(m_vm), regT3);
839
840     // Now store the exception returned by operationThrow.
841     load32(Address(regT3, VM::exceptionOffset()), regT2);
842     move(TrustedImm32(JSValue::CellTag), regT1);
843
844     store32(TrustedImm32(0), Address(regT3, VM::exceptionOffset()));
845
846     unsigned exception = currentInstruction[1].u.operand;
847     emitStore(exception, regT1, regT2);
848
849     load32(Address(regT2, Exception::valueOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0);
850     load32(Address(regT2, Exception::valueOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1);
851
852     unsigned thrownValue = currentInstruction[2].u.operand;
853     emitStore(thrownValue, regT1, regT0);
854 }
855
856 void JIT::emit_op_assert(Instruction* currentInstruction)
857 {
858     JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_assert);
859     slowPathCall.call();
860 }
861
862 void JIT::emit_op_create_lexical_environment(Instruction* currentInstruction)
863 {
864     JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_create_lexical_environment);
865     slowPathCall.call();
866 }
867
868 void JIT::emit_op_get_parent_scope(Instruction* currentInstruction)
869 {
870     int currentScope = currentInstruction[2].u.operand;
871     emitLoadPayload(currentScope, regT0);
872     loadPtr(Address(regT0, JSScope::offsetOfNext()), regT0);
873     emitStoreCell(currentInstruction[1].u.operand, regT0);
874 }
875
876 void JIT::emit_op_switch_imm(Instruction* currentInstruction)
877 {
878     size_t tableIndex = currentInstruction[1].u.operand;
879     unsigned defaultOffset = currentInstruction[2].u.operand;
880     unsigned scrutinee = currentInstruction[3].u.operand;
881
882     // create jump table for switch destinations, track this switch statement.
883     SimpleJumpTable* jumpTable = &m_codeBlock->switchJumpTable(tableIndex);
884     m_switches.append(SwitchRecord(jumpTable, m_bytecodeOffset, defaultOffset, SwitchRecord::Immediate));
885     jumpTable->ensureCTITable();
886
887     emitLoad(scrutinee, regT1, regT0);
888     callOperation(operationSwitchImmWithUnknownKeyType, regT1, regT0, tableIndex);
889     jump(returnValueGPR);
890 }
891
892 void JIT::emit_op_switch_char(Instruction* currentInstruction)
893 {
894     size_t tableIndex = currentInstruction[1].u.operand;
895     unsigned defaultOffset = currentInstruction[2].u.operand;
896     unsigned scrutinee = currentInstruction[3].u.operand;
897
898     // create jump table for switch destinations, track this switch statement.
899     SimpleJumpTable* jumpTable = &m_codeBlock->switchJumpTable(tableIndex);
900     m_switches.append(SwitchRecord(jumpTable, m_bytecodeOffset, defaultOffset, SwitchRecord::Character));
901     jumpTable->ensureCTITable();
902
903     emitLoad(scrutinee, regT1, regT0);
904     callOperation(operationSwitchCharWithUnknownKeyType, regT1, regT0, tableIndex);
905     jump(returnValueGPR);
906 }
907
908 void JIT::emit_op_switch_string(Instruction* currentInstruction)
909 {
910     size_t tableIndex = currentInstruction[1].u.operand;
911     unsigned defaultOffset = currentInstruction[2].u.operand;
912     unsigned scrutinee = currentInstruction[3].u.operand;
913
914     // create jump table for switch destinations, track this switch statement.
915     StringJumpTable* jumpTable = &m_codeBlock->stringSwitchJumpTable(tableIndex);
916     m_switches.append(SwitchRecord(jumpTable, m_bytecodeOffset, defaultOffset));
917
918     emitLoad(scrutinee, regT1, regT0);
919     callOperation(operationSwitchStringWithUnknownKeyType, regT1, regT0, tableIndex);
920     jump(returnValueGPR);
921 }
922
923 void JIT::emit_op_debug(Instruction* currentInstruction)
924 {
925     load32(codeBlock()->debuggerRequestsAddress(), regT0);
926     Jump noDebuggerRequests = branchTest32(Zero, regT0);
927     callOperation(operationDebug, currentInstruction[1].u.operand);
928     noDebuggerRequests.link(this);
929 }
930
931
932 void JIT::emit_op_enter(Instruction* currentInstruction)
933 {
934     emitEnterOptimizationCheck();
935     
936     // Even though JIT code doesn't use them, we initialize our constant
937     // registers to zap stale pointers, to avoid unnecessarily prolonging
938     // object lifetime and increasing GC pressure.
939     for (int i = 0; i < m_codeBlock->m_numVars; ++i)
940         emitStore(virtualRegisterForLocal(i).offset(), jsUndefined());
941
942     JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_enter);
943     slowPathCall.call();
944 }
945
946 void JIT::emit_op_get_scope(Instruction* currentInstruction)
947 {
948     int dst = currentInstruction[1].u.operand;
949     emitGetFromCallFrameHeaderPtr(CallFrameSlot::callee, regT0);
950     loadPtr(Address(regT0, JSFunction::offsetOfScopeChain()), regT0);
951     emitStoreCell(dst, regT0);
952 }
953
954 void JIT::emit_op_create_this(Instruction* currentInstruction)
955 {
956     int callee = currentInstruction[2].u.operand;
957     WriteBarrierBase<JSCell>* cachedFunction = &currentInstruction[4].u.jsCell;
958     RegisterID calleeReg = regT0;
959     RegisterID rareDataReg = regT4;
960     RegisterID resultReg = regT0;
961     RegisterID allocatorReg = regT1;
962     RegisterID structureReg = regT2;
963     RegisterID cachedFunctionReg = regT4;
964     RegisterID scratchReg = regT3;
965
966     emitLoadPayload(callee, calleeReg);
967     addSlowCase(branch8(NotEqual, Address(calleeReg, JSCell::typeInfoTypeOffset()), TrustedImm32(JSFunctionType)));
968     loadPtr(Address(calleeReg, JSFunction::offsetOfRareData()), rareDataReg);
969     addSlowCase(branchTestPtr(Zero, rareDataReg));
970     loadPtr(Address(rareDataReg, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfile::offsetOfAllocator()), allocatorReg);
971     loadPtr(Address(rareDataReg, FunctionRareData::offsetOfObjectAllocationProfile() + ObjectAllocationProfile::offsetOfStructure()), structureReg);
972     addSlowCase(branchTestPtr(Zero, allocatorReg));
973
974     loadPtr(cachedFunction, cachedFunctionReg);
975     Jump hasSeenMultipleCallees = branchPtr(Equal, cachedFunctionReg, TrustedImmPtr(JSCell::seenMultipleCalleeObjects()));
976     addSlowCase(branchPtr(NotEqual, calleeReg, cachedFunctionReg));
977     hasSeenMultipleCallees.link(this);
978
979     JumpList slowCases;
980     emitAllocateJSObject(resultReg, nullptr, allocatorReg, structureReg, TrustedImmPtr(0), scratchReg, slowCases);
981     addSlowCase(slowCases);
982     emitStoreCell(currentInstruction[1].u.operand, resultReg);
983 }
984
985 void JIT::emitSlow_op_create_this(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
986 {
987     linkSlowCase(iter); // Callee::m_type != JSFunctionType.
988     linkSlowCase(iter); // doesn't have rare data
989     linkSlowCase(iter); // doesn't have an allocation profile
990     linkSlowCase(iter); // allocation failed (no allocator)
991     linkSlowCase(iter); // allocation failed (allocator empty)
992     linkSlowCase(iter); // cached function didn't match
993
994     JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_create_this);
995     slowPathCall.call();
996 }
997
998 void JIT::emit_op_to_this(Instruction* currentInstruction)
999 {
1000     WriteBarrierBase<Structure>* cachedStructure = &currentInstruction[2].u.structure;
1001     int thisRegister = currentInstruction[1].u.operand;
1002
1003     emitLoad(thisRegister, regT3, regT2);
1004
1005     addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::CellTag)));
1006     addSlowCase(branch8(NotEqual, Address(regT2, JSCell::typeInfoTypeOffset()), TrustedImm32(FinalObjectType)));
1007     loadPtr(Address(regT2, JSCell::structureIDOffset()), regT0);
1008     loadPtr(cachedStructure, regT2);
1009     addSlowCase(branchPtr(NotEqual, regT0, regT2));
1010 }
1011
1012 void JIT::emitSlow_op_to_this(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1013 {
1014     linkSlowCase(iter);
1015     linkSlowCase(iter);
1016     linkSlowCase(iter);
1017     JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_to_this);
1018     slowPathCall.call();
1019 }
1020
1021 void JIT::emit_op_check_tdz(Instruction* currentInstruction)
1022 {
1023     emitLoadTag(currentInstruction[1].u.operand, regT0);
1024     addSlowCase(branch32(Equal, regT0, TrustedImm32(JSValue::EmptyValueTag)));
1025 }
1026
1027 void JIT::emitSlow_op_check_tdz(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1028 {
1029     linkSlowCase(iter);
1030     JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_throw_tdz_error);
1031     slowPathCall.call();
1032 }
1033
1034 void JIT::emit_op_has_structure_property(Instruction* currentInstruction)
1035 {
1036     int dst = currentInstruction[1].u.operand;
1037     int base = currentInstruction[2].u.operand;
1038     int enumerator = currentInstruction[4].u.operand;
1039
1040     emitLoadPayload(base, regT0);
1041     emitJumpSlowCaseIfNotJSCell(base);
1042
1043     emitLoadPayload(enumerator, regT1);
1044
1045     load32(Address(regT0, JSCell::structureIDOffset()), regT0);
1046     addSlowCase(branch32(NotEqual, regT0, Address(regT1, JSPropertyNameEnumerator::cachedStructureIDOffset())));
1047     
1048     move(TrustedImm32(1), regT0);
1049     emitStoreBool(dst, regT0);
1050 }
1051
1052 void JIT::privateCompileHasIndexedProperty(ByValInfo* byValInfo, ReturnAddressPtr returnAddress, JITArrayMode arrayMode)
1053 {
1054     Instruction* currentInstruction = m_codeBlock->instructions().begin() + byValInfo->bytecodeIndex;
1055     
1056     PatchableJump badType;
1057     
1058     // FIXME: Add support for other types like TypedArrays and Arguments.
1059     // See https://bugs.webkit.org/show_bug.cgi?id=135033 and https://bugs.webkit.org/show_bug.cgi?id=135034.
1060     JumpList slowCases = emitLoadForArrayMode(currentInstruction, arrayMode, badType);
1061     move(TrustedImm32(1), regT0);
1062     Jump done = jump();
1063
1064     LinkBuffer patchBuffer(*m_vm, *this, m_codeBlock);
1065     
1066     patchBuffer.link(badType, CodeLocationLabel(MacroAssemblerCodePtr::createFromExecutableAddress(returnAddress.value())).labelAtOffset(byValInfo->returnAddressToSlowPath));
1067     patchBuffer.link(slowCases, CodeLocationLabel(MacroAssemblerCodePtr::createFromExecutableAddress(returnAddress.value())).labelAtOffset(byValInfo->returnAddressToSlowPath));
1068     
1069     patchBuffer.link(done, byValInfo->badTypeJump.labelAtOffset(byValInfo->badTypeJumpToDone));
1070     
1071     byValInfo->stubRoutine = FINALIZE_CODE_FOR_STUB(
1072         m_codeBlock, patchBuffer,
1073         ("Baseline has_indexed_property stub for %s, return point %p", toCString(*m_codeBlock).data(), returnAddress.value()));
1074     
1075     MacroAssembler::repatchJump(byValInfo->badTypeJump, CodeLocationLabel(byValInfo->stubRoutine->code().code()));
1076     MacroAssembler::repatchCall(CodeLocationCall(MacroAssemblerCodePtr(returnAddress)), FunctionPtr(operationHasIndexedPropertyGeneric));
1077 }
1078
1079 void JIT::emit_op_has_indexed_property(Instruction* currentInstruction)
1080 {
1081     int dst = currentInstruction[1].u.operand;
1082     int base = currentInstruction[2].u.operand;
1083     int property = currentInstruction[3].u.operand;
1084     ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
1085     ByValInfo* byValInfo = m_codeBlock->addByValInfo();
1086     
1087     emitLoadPayload(base, regT0);
1088     emitJumpSlowCaseIfNotJSCell(base);
1089
1090     emitLoadPayload(property, regT1);
1091
1092     // This is technically incorrect - we're zero-extending an int32. On the hot path this doesn't matter.
1093     // We check the value as if it was a uint32 against the m_vectorLength - which will always fail if
1094     // number was signed since m_vectorLength is always less than intmax (since the total allocation
1095     // size is always less than 4Gb). As such zero extending will have been correct (and extending the value
1096     // to 64-bits is necessary since it's used in the address calculation. We zero extend rather than sign
1097     // extending since it makes it easier to re-tag the value in the slow case.
1098     zeroExtend32ToPtr(regT1, regT1);
1099
1100     emitArrayProfilingSiteWithCell(regT0, regT2, profile);
1101     and32(TrustedImm32(IndexingShapeMask), regT2);
1102
1103     JITArrayMode mode = chooseArrayMode(profile);
1104     PatchableJump badType;
1105
1106     // FIXME: Add support for other types like TypedArrays and Arguments.
1107     // See https://bugs.webkit.org/show_bug.cgi?id=135033 and https://bugs.webkit.org/show_bug.cgi?id=135034.
1108     JumpList slowCases = emitLoadForArrayMode(currentInstruction, mode, badType);
1109     move(TrustedImm32(1), regT0);
1110
1111     addSlowCase(badType);
1112     addSlowCase(slowCases);
1113     
1114     Label done = label();
1115     
1116     emitStoreBool(dst, regT0);
1117
1118     Label nextHotPath = label();
1119     
1120     m_byValCompilationInfo.append(ByValCompilationInfo(byValInfo, m_bytecodeOffset, PatchableJump(), badType, mode, profile, done, nextHotPath));
1121 }
1122
1123 void JIT::emitSlow_op_has_indexed_property(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1124 {
1125     int dst = currentInstruction[1].u.operand;
1126     int base = currentInstruction[2].u.operand;
1127     int property = currentInstruction[3].u.operand;
1128     ByValInfo* byValInfo = m_byValCompilationInfo[m_byValInstructionIndex].byValInfo;
1129     
1130     linkSlowCaseIfNotJSCell(iter, base); // base cell check
1131     linkSlowCase(iter); // base array check
1132     linkSlowCase(iter); // vector length check
1133     linkSlowCase(iter); // empty value
1134
1135     Label slowPath = label();
1136     
1137     emitLoad(base, regT1, regT0);
1138     emitLoad(property, regT3, regT2);
1139     Call call = callOperation(operationHasIndexedPropertyDefault, dst, regT1, regT0, regT3, regT2, byValInfo);
1140
1141     m_byValCompilationInfo[m_byValInstructionIndex].slowPathTarget = slowPath;
1142     m_byValCompilationInfo[m_byValInstructionIndex].returnAddress = call;
1143     m_byValInstructionIndex++;
1144 }
1145
1146 void JIT::emit_op_get_direct_pname(Instruction* currentInstruction)
1147 {
1148     int dst = currentInstruction[1].u.operand;
1149     int base = currentInstruction[2].u.operand;
1150     int index = currentInstruction[4].u.operand;
1151     int enumerator = currentInstruction[5].u.operand;
1152
1153     // Check that base is a cell
1154     emitLoadPayload(base, regT0);
1155     emitJumpSlowCaseIfNotJSCell(base);
1156
1157     // Check the structure
1158     emitLoadPayload(enumerator, regT1);
1159     load32(Address(regT0, JSCell::structureIDOffset()), regT2);
1160     addSlowCase(branch32(NotEqual, regT2, Address(regT1, JSPropertyNameEnumerator::cachedStructureIDOffset())));
1161
1162     // Compute the offset
1163     emitLoadPayload(index, regT2);
1164     // If index is less than the enumerator's cached inline storage, then it's an inline access
1165     Jump outOfLineAccess = branch32(AboveOrEqual, regT2, Address(regT1, JSPropertyNameEnumerator::cachedInlineCapacityOffset()));
1166     addPtr(TrustedImm32(JSObject::offsetOfInlineStorage()), regT0);
1167     load32(BaseIndex(regT0, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1);
1168     load32(BaseIndex(regT0, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0);
1169     
1170     Jump done = jump();
1171
1172     // Otherwise it's out of line
1173     outOfLineAccess.link(this);
1174     loadPtr(Address(regT0, JSObject::butterflyOffset()), regT0);
1175     sub32(Address(regT1, JSPropertyNameEnumerator::cachedInlineCapacityOffset()), regT2);
1176     neg32(regT2);
1177     int32_t offsetOfFirstProperty = static_cast<int32_t>(offsetInButterfly(firstOutOfLineOffset)) * sizeof(EncodedJSValue);
1178     load32(BaseIndex(regT0, regT2, TimesEight, offsetOfFirstProperty + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1);
1179     load32(BaseIndex(regT0, regT2, TimesEight, offsetOfFirstProperty + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0);
1180     
1181     done.link(this);
1182     emitValueProfilingSite();
1183     emitStore(dst, regT1, regT0);
1184 }
1185
1186 void JIT::emitSlow_op_get_direct_pname(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
1187 {
1188     int base = currentInstruction[2].u.operand;
1189     linkSlowCaseIfNotJSCell(iter, base);
1190     linkSlowCase(iter);
1191
1192     JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_get_direct_pname);
1193     slowPathCall.call();
1194 }
1195
1196 void JIT::emit_op_enumerator_structure_pname(Instruction* currentInstruction)
1197 {
1198     int dst = currentInstruction[1].u.operand;
1199     int enumerator = currentInstruction[2].u.operand;
1200     int index = currentInstruction[3].u.operand;
1201
1202     emitLoadPayload(index, regT0);
1203     emitLoadPayload(enumerator, regT1);
1204     Jump inBounds = branch32(Below, regT0, Address(regT1, JSPropertyNameEnumerator::endStructurePropertyIndexOffset()));
1205
1206     move(TrustedImm32(JSValue::NullTag), regT2);
1207     move(TrustedImm32(0), regT0);
1208
1209     Jump done = jump();
1210     inBounds.link(this);
1211
1212     loadPtr(Address(regT1, JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset()), regT1);
1213     loadPtr(BaseIndex(regT1, regT0, timesPtr()), regT0);
1214     move(TrustedImm32(JSValue::CellTag), regT2);
1215
1216     done.link(this);
1217     emitStore(dst, regT2, regT0);
1218 }
1219
1220 void JIT::emit_op_enumerator_generic_pname(Instruction* currentInstruction)
1221 {
1222     int dst = currentInstruction[1].u.operand;
1223     int enumerator = currentInstruction[2].u.operand;
1224     int index = currentInstruction[3].u.operand;
1225
1226     emitLoadPayload(index, regT0);
1227     emitLoadPayload(enumerator, regT1);
1228     Jump inBounds = branch32(Below, regT0, Address(regT1, JSPropertyNameEnumerator::endGenericPropertyIndexOffset()));
1229
1230     move(TrustedImm32(JSValue::NullTag), regT2);
1231     move(TrustedImm32(0), regT0);
1232
1233     Jump done = jump();
1234     inBounds.link(this);
1235
1236     loadPtr(Address(regT1, JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset()), regT1);
1237     loadPtr(BaseIndex(regT1, regT0, timesPtr()), regT0);
1238     move(TrustedImm32(JSValue::CellTag), regT2);
1239     
1240     done.link(this);
1241     emitStore(dst, regT2, regT0);
1242 }
1243
1244 void JIT::emit_op_profile_type(Instruction* currentInstruction)
1245 {
1246     TypeLocation* cachedTypeLocation = currentInstruction[2].u.location;
1247     int valueToProfile = currentInstruction[1].u.operand;
1248
1249     // Load payload in T0. Load tag in T3.
1250     emitLoadPayload(valueToProfile, regT0);
1251     emitLoadTag(valueToProfile, regT3);
1252
1253     JumpList jumpToEnd;
1254
1255     jumpToEnd.append(branch32(Equal, regT3, TrustedImm32(JSValue::EmptyValueTag)));
1256
1257     // Compile in a predictive type check, if possible, to see if we can skip writing to the log.
1258     // These typechecks are inlined to match those of the 32-bit JSValue type checks.
1259     if (cachedTypeLocation->m_lastSeenType == TypeUndefined)
1260         jumpToEnd.append(branch32(Equal, regT3, TrustedImm32(JSValue::UndefinedTag)));
1261     else if (cachedTypeLocation->m_lastSeenType == TypeNull)
1262         jumpToEnd.append(branch32(Equal, regT3, TrustedImm32(JSValue::NullTag)));
1263     else if (cachedTypeLocation->m_lastSeenType == TypeBoolean)
1264         jumpToEnd.append(branch32(Equal, regT3, TrustedImm32(JSValue::BooleanTag)));
1265     else if (cachedTypeLocation->m_lastSeenType == TypeAnyInt)
1266         jumpToEnd.append(branch32(Equal, regT3, TrustedImm32(JSValue::Int32Tag)));
1267     else if (cachedTypeLocation->m_lastSeenType == TypeNumber) {
1268         jumpToEnd.append(branch32(Below, regT3, TrustedImm32(JSValue::LowestTag)));
1269         jumpToEnd.append(branch32(Equal, regT3, TrustedImm32(JSValue::Int32Tag)));
1270     } else if (cachedTypeLocation->m_lastSeenType == TypeString) {
1271         Jump isNotCell = branch32(NotEqual, regT3, TrustedImm32(JSValue::CellTag));
1272         jumpToEnd.append(branch8(Equal, Address(regT0, JSCell::typeInfoTypeOffset()), TrustedImm32(StringType)));
1273         isNotCell.link(this);
1274     }
1275
1276     // Load the type profiling log into T2.
1277     TypeProfilerLog* cachedTypeProfilerLog = m_vm->typeProfilerLog();
1278     move(TrustedImmPtr(cachedTypeProfilerLog), regT2);
1279
1280     // Load the next log entry into T1.
1281     loadPtr(Address(regT2, TypeProfilerLog::currentLogEntryOffset()), regT1);
1282
1283     // Store the JSValue onto the log entry.
1284     store32(regT0, Address(regT1, TypeProfilerLog::LogEntry::valueOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
1285     store32(regT3, Address(regT1, TypeProfilerLog::LogEntry::valueOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
1286
1287     // Store the structureID of the cell if argument is a cell, otherwise, store 0 on the log entry.
1288     Jump notCell = branch32(NotEqual, regT3, TrustedImm32(JSValue::CellTag));
1289     load32(Address(regT0, JSCell::structureIDOffset()), regT0);
1290     store32(regT0, Address(regT1, TypeProfilerLog::LogEntry::structureIDOffset()));
1291     Jump skipNotCell = jump();
1292     notCell.link(this);
1293     store32(TrustedImm32(0), Address(regT1, TypeProfilerLog::LogEntry::structureIDOffset()));
1294     skipNotCell.link(this);
1295
1296     // Store the typeLocation on the log entry.
1297     move(TrustedImmPtr(cachedTypeLocation), regT0);
1298     store32(regT0, Address(regT1, TypeProfilerLog::LogEntry::locationOffset()));
1299
1300     // Increment the current log entry.
1301     addPtr(TrustedImm32(sizeof(TypeProfilerLog::LogEntry)), regT1);
1302     store32(regT1, Address(regT2, TypeProfilerLog::currentLogEntryOffset()));
1303     jumpToEnd.append(branchPtr(NotEqual, regT1, TrustedImmPtr(cachedTypeProfilerLog->logEndPtr())));
1304     // Clear the log if we're at the end of the log.
1305     callOperation(operationProcessTypeProfilerLog);
1306
1307     jumpToEnd.link(this);
1308 }
1309
1310 void JIT::emit_op_log_shadow_chicken_prologue(Instruction* currentInstruction)
1311 {
1312     updateTopCallFrame();
1313     static_assert(nonArgGPR0 != regT0 && nonArgGPR0 != regT2, "we will have problems if this is true.");
1314     GPRReg shadowPacketReg = regT0;
1315     GPRReg scratch1Reg = nonArgGPR0; // This must be a non-argument register.
1316     GPRReg scratch2Reg = regT2;
1317     ensureShadowChickenPacket(*vm(), shadowPacketReg, scratch1Reg, scratch2Reg);
1318
1319     scratch1Reg = regT4;
1320     emitLoadPayload(currentInstruction[1].u.operand, regT3);
1321     logShadowChickenProloguePacket(shadowPacketReg, scratch1Reg, regT3);
1322 }
1323
1324 void JIT::emit_op_log_shadow_chicken_tail(Instruction* currentInstruction)
1325 {
1326     updateTopCallFrame();
1327     static_assert(nonArgGPR0 != regT0 && nonArgGPR0 != regT2, "we will have problems if this is true.");
1328     GPRReg shadowPacketReg = regT0;
1329     GPRReg scratch1Reg = nonArgGPR0; // This must be a non-argument register.
1330     GPRReg scratch2Reg = regT2;
1331     ensureShadowChickenPacket(*vm(), shadowPacketReg, scratch1Reg, scratch2Reg);
1332
1333     emitLoadPayload(currentInstruction[1].u.operand, regT2);
1334     emitLoadTag(currentInstruction[1].u.operand, regT1);
1335     JSValueRegs thisRegs(regT1, regT2);
1336     emitLoadPayload(currentInstruction[2].u.operand, regT3);
1337     logShadowChickenTailPacket(shadowPacketReg, thisRegs, regT3, m_codeBlock, CallSiteIndex(currentInstruction));
1338 }
1339
1340 } // namespace JSC
1341
1342 #endif // USE(JSVALUE32_64)
1343 #endif // ENABLE(JIT)