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