47def277e1b5ca273dce179741fdb8ec16fe6d9f
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGSpeculativeJIT.cpp
1 /*
2  * Copyright (C) 2011 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "DFGSpeculativeJIT.h"
28
29 #if ENABLE(DFG_JIT)
30
31 namespace JSC { namespace DFG {
32
33 template<bool strict>
34 GPRReg SpeculativeJIT::fillSpeculateIntInternal(NodeIndex nodeIndex, DataFormat& returnFormat)
35 {
36     Node& node = m_jit.graph()[nodeIndex];
37     VirtualRegister virtualRegister = node.virtualRegister();
38     GenerationInfo& info = m_generationInfo[virtualRegister];
39
40     switch (info.registerFormat()) {
41     case DataFormatNone: {
42         GPRReg gpr = allocate();
43
44         if (node.isConstant()) {
45             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
46             if (isInt32Constant(nodeIndex)) {
47                 m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gpr);
48                 info.fillInteger(gpr);
49                 returnFormat = DataFormatInteger;
50                 return gpr;
51             }
52             terminateSpeculativeExecution();
53             returnFormat = DataFormatInteger;
54             return allocate();
55         } else {
56             DataFormat spillFormat = info.spillFormat();
57             ASSERT(spillFormat & DataFormatJS);
58
59             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
60
61             if (spillFormat == DataFormatJSInteger) {
62                 // If we know this was spilled as an integer we can fill without checking.
63                 if (strict) {
64                     m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
65                     info.fillInteger(gpr);
66                     returnFormat = DataFormatInteger;
67                     return gpr;
68                 }
69                 m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
70                 info.fillJSValue(gpr, DataFormatJSInteger);
71                 returnFormat = DataFormatJSInteger;
72                 return gpr;
73             }
74             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
75         }
76
77         // Fill as JSValue, and fall through.
78         info.fillJSValue(gpr, DataFormatJSInteger);
79         m_gprs.unlock(gpr);
80     }
81
82     case DataFormatJS: {
83         // Check the value is an integer.
84         GPRReg gpr = info.gpr();
85         m_gprs.lock(gpr);
86         speculationCheck(m_jit.branchPtr(MacroAssembler::Below, gpr, GPRInfo::tagTypeNumberRegister));
87         info.fillJSValue(gpr, DataFormatJSInteger);
88         // If !strict we're done, return.
89         if (!strict) {
90             returnFormat = DataFormatJSInteger;
91             return gpr;
92         }
93         // else fall through & handle as DataFormatJSInteger.
94         m_gprs.unlock(gpr);
95     }
96
97     case DataFormatJSInteger: {
98         // In a strict fill we need to strip off the value tag.
99         if (strict) {
100             GPRReg gpr = info.gpr();
101             GPRReg result;
102             // If the register has already been locked we need to take a copy.
103             // If not, we'll zero extend in place, so mark on the info that this is now type DataFormatInteger, not DataFormatJSInteger.
104             if (m_gprs.isLocked(gpr))
105                 result = allocate();
106             else {
107                 m_gprs.lock(gpr);
108                 info.fillInteger(gpr);
109                 result = gpr;
110             }
111             m_jit.zeroExtend32ToPtr(gpr, result);
112             returnFormat = DataFormatInteger;
113             return result;
114         }
115
116         GPRReg gpr = info.gpr();
117         m_gprs.lock(gpr);
118         returnFormat = DataFormatJSInteger;
119         return gpr;
120     }
121
122     case DataFormatInteger: {
123         GPRReg gpr = info.gpr();
124         m_gprs.lock(gpr);
125         returnFormat = DataFormatInteger;
126         return gpr;
127     }
128
129     case DataFormatDouble:
130     case DataFormatCell:
131     case DataFormatJSDouble:
132     case DataFormatJSCell: {
133         terminateSpeculativeExecution();
134         returnFormat = DataFormatInteger;
135         return allocate();
136     }
137     }
138
139     ASSERT_NOT_REACHED();
140     return InvalidGPRReg;
141 }
142
143 SpeculationCheck::SpeculationCheck(MacroAssembler::Jump check, SpeculativeJIT* jit, unsigned recoveryIndex)
144     : m_check(check)
145     , m_nodeIndex(jit->m_compileIndex)
146     , m_recoveryIndex(recoveryIndex)
147 {
148     for (gpr_iterator iter = jit->m_gprs.begin(); iter != jit->m_gprs.end(); ++iter) {
149         if (iter.name() != InvalidVirtualRegister) {
150             GenerationInfo& info =  jit->m_generationInfo[iter.name()];
151             m_gprInfo[iter.index()].nodeIndex = info.nodeIndex();
152             m_gprInfo[iter.index()].format = info.registerFormat();
153         } else
154             m_gprInfo[iter.index()].nodeIndex = NoNode;
155     }
156     for (fpr_iterator iter = jit->m_fprs.begin(); iter != jit->m_fprs.end(); ++iter) {
157         if (iter.name() != InvalidVirtualRegister) {
158             GenerationInfo& info =  jit->m_generationInfo[iter.name()];
159             ASSERT(info.registerFormat() == DataFormatDouble);
160             m_fprInfo[iter.index()] = info.nodeIndex();
161         } else
162             m_fprInfo[iter.index()] = NoNode;
163     }
164 }
165
166 GPRReg SpeculativeJIT::fillSpeculateInt(NodeIndex nodeIndex, DataFormat& returnFormat)
167 {
168     return fillSpeculateIntInternal<false>(nodeIndex, returnFormat);
169 }
170
171 GPRReg SpeculativeJIT::fillSpeculateIntStrict(NodeIndex nodeIndex)
172 {
173     DataFormat mustBeDataFormatInteger;
174     GPRReg result = fillSpeculateIntInternal<true>(nodeIndex, mustBeDataFormatInteger);
175     ASSERT(mustBeDataFormatInteger == DataFormatInteger);
176     return result;
177 }
178
179 FPRReg SpeculativeJIT::fillSpeculateDouble(NodeIndex nodeIndex)
180 {
181     Node& node = m_jit.graph()[nodeIndex];
182     VirtualRegister virtualRegister = node.virtualRegister();
183     GenerationInfo& info = m_generationInfo[virtualRegister];
184
185     if (info.registerFormat() == DataFormatNone) {
186         GPRReg gpr = allocate();
187
188         if (node.isConstant()) {
189             if (isInt32Constant(nodeIndex)) {
190                 FPRReg fpr = fprAllocate();
191                 m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(static_cast<double>(valueOfInt32Constant(nodeIndex))))), gpr);
192                 m_jit.movePtrToDouble(gpr, fpr);
193                 unlock(gpr);
194
195                 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
196                 info.fillDouble(fpr);
197                 return fpr;
198             }
199             if (isDoubleConstant(nodeIndex)) {
200                 FPRReg fpr = fprAllocate();
201                 m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(valueOfDoubleConstant(nodeIndex)))), gpr);
202                 m_jit.movePtrToDouble(gpr, fpr);
203                 unlock(gpr);
204
205                 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
206                 info.fillDouble(fpr);
207                 return fpr;
208             }
209             ASSERT(isJSConstant(nodeIndex));
210             JSValue jsValue = valueOfJSConstant(nodeIndex);
211             m_jit.move(MacroAssembler::ImmPtr(JSValue::encode(jsValue)), gpr);
212             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
213             info.fillJSValue(gpr, DataFormatJS);
214             unlock(gpr);
215         } else {
216             DataFormat spillFormat = info.spillFormat();
217             ASSERT(spillFormat & DataFormatJS);
218             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
219             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
220             info.fillJSValue(gpr, spillFormat);
221             unlock(gpr);
222         }
223     }
224
225     switch (info.registerFormat()) {
226     case DataFormatNone:
227         // Should have filled, above.
228         ASSERT_NOT_REACHED();
229         
230     case DataFormatCell:
231     case DataFormatJSCell:
232     case DataFormatJS: {
233         GPRReg jsValueGpr = info.gpr();
234         m_gprs.lock(jsValueGpr);
235         FPRReg fpr = fprAllocate();
236         GPRReg tempGpr = allocate();
237
238         JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
239
240         speculationCheck(m_jit.branchTestPtr(MacroAssembler::Zero, jsValueGpr, GPRInfo::tagTypeNumberRegister));
241
242         // First, if we get here we have a double encoded as a JSValue
243         m_jit.move(jsValueGpr, tempGpr);
244         m_jit.addPtr(GPRInfo::tagTypeNumberRegister, tempGpr);
245         m_jit.movePtrToDouble(tempGpr, fpr);
246         JITCompiler::Jump hasUnboxedDouble = m_jit.jump();
247
248         // Finally, handle integers.
249         isInteger.link(&m_jit);
250         m_jit.convertInt32ToDouble(jsValueGpr, fpr);
251         hasUnboxedDouble.link(&m_jit);
252
253         m_gprs.release(jsValueGpr);
254         m_gprs.unlock(jsValueGpr);
255         m_gprs.unlock(tempGpr);
256         m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
257         info.fillDouble(fpr);
258         return fpr;
259     }
260
261     case DataFormatJSInteger:
262     case DataFormatInteger: {
263         FPRReg fpr = fprAllocate();
264         GPRReg gpr = info.gpr();
265         m_gprs.lock(gpr);
266         m_jit.convertInt32ToDouble(gpr, fpr);
267         m_gprs.unlock(gpr);
268         return fpr;
269     }
270
271     // Unbox the double
272     case DataFormatJSDouble: {
273         GPRReg gpr = info.gpr();
274         FPRReg fpr = unboxDouble(gpr);
275
276         m_gprs.release(gpr);
277         m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
278
279         info.fillDouble(fpr);
280         return fpr;
281     }
282
283     case DataFormatDouble: {
284         FPRReg fpr = info.fpr();
285         m_fprs.lock(fpr);
286         return fpr;
287     }
288     }
289
290     ASSERT_NOT_REACHED();
291     return InvalidFPRReg;
292 }
293
294 GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex)
295 {
296     Node& node = m_jit.graph()[nodeIndex];
297     VirtualRegister virtualRegister = node.virtualRegister();
298     GenerationInfo& info = m_generationInfo[virtualRegister];
299
300     switch (info.registerFormat()) {
301     case DataFormatNone: {
302         GPRReg gpr = allocate();
303
304         if (node.isConstant()) {
305             JSValue jsValue = valueOfJSConstant(nodeIndex);
306             if (jsValue.isCell()) {
307                 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
308                 m_jit.move(MacroAssembler::TrustedImmPtr(jsValue.asCell()), gpr);
309                 info.fillJSValue(gpr, DataFormatJSCell);
310                 return gpr;
311             }
312             terminateSpeculativeExecution();
313             return gpr;
314         }
315         ASSERT(info.spillFormat() & DataFormatJS);
316         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
317         m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
318
319         if (info.spillFormat() != DataFormatJSCell)
320             speculationCheck(m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister));
321         info.fillJSValue(gpr, DataFormatJSCell);
322         return gpr;
323     }
324
325     case DataFormatCell:
326     case DataFormatJSCell: {
327         GPRReg gpr = info.gpr();
328         m_gprs.lock(gpr);
329         return gpr;
330     }
331
332     case DataFormatJS: {
333         GPRReg gpr = info.gpr();
334         m_gprs.lock(gpr);
335         speculationCheck(m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister));
336         info.fillJSValue(gpr, DataFormatJSCell);
337         return gpr;
338     }
339
340     case DataFormatJSInteger:
341     case DataFormatInteger:
342     case DataFormatJSDouble:
343     case DataFormatDouble: {
344         terminateSpeculativeExecution();
345         return allocate();
346     }
347     }
348
349     ASSERT_NOT_REACHED();
350     return InvalidGPRReg;
351 }
352
353 void SpeculativeJIT::compilePeepHoleIntegerBranch(Node& node, NodeIndex branchNodeIndex, JITCompiler::RelationalCondition condition)
354 {
355     Node& branchNode = m_jit.graph()[branchNodeIndex];
356     BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
357     BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
358
359     // The branch instruction will branch to the taken block.
360     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
361     if (taken == (m_block + 1)) {
362         condition = JITCompiler::invert(condition);
363         BlockIndex tmp = taken;
364         taken = notTaken;
365         notTaken = tmp;
366     }
367
368     if (isInt32Constant(node.child1())) {
369         int32_t imm = valueOfInt32Constant(node.child1());
370         SpeculateIntegerOperand op2(this, node.child2());
371         addBranch(m_jit.branch32(condition, JITCompiler::Imm32(imm), op2.gpr()), taken);
372     } else if (isInt32Constant(node.child2())) {
373         SpeculateIntegerOperand op1(this, node.child1());
374         int32_t imm = valueOfInt32Constant(node.child2());
375         addBranch(m_jit.branch32(condition, op1.gpr(), JITCompiler::Imm32(imm)), taken);
376     } else {
377         SpeculateIntegerOperand op1(this, node.child1());
378         SpeculateIntegerOperand op2(this, node.child2());
379         addBranch(m_jit.branch32(condition, op1.gpr(), op2.gpr()), taken);
380     }
381
382     // Check for fall through, otherwise we need to jump.
383     if (notTaken != (m_block + 1))
384         addBranch(m_jit.jump(), notTaken);
385 }
386
387 void SpeculativeJIT::compilePeepHoleCall(Node& node, NodeIndex branchNodeIndex, Z_DFGOperation_EJJ operation)
388 {
389     Node& branchNode = m_jit.graph()[branchNodeIndex];
390     BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
391     BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
392
393     // The branch instruction will branch to the taken block.
394     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
395     JITCompiler::ResultCondition condition = JITCompiler::NonZero;
396     if (taken == (m_block + 1)) {
397         condition = JITCompiler::Zero;
398         BlockIndex tmp = taken;
399         taken = notTaken;
400         notTaken = tmp;
401     }
402
403     JSValueOperand op1(this, node.child1());
404     JSValueOperand op2(this, node.child2());
405     GPRReg op1GPR = op1.gpr();
406     GPRReg op2GPR = op2.gpr();
407     flushRegisters();
408
409     GPRResult result(this);
410     callOperation(operation, result.gpr(), op1GPR, op2GPR);
411     addBranch(m_jit.branchTest8(condition, result.gpr()), taken);
412
413     // Check for fall through, otherwise we need to jump.
414     if (notTaken != (m_block + 1))
415         addBranch(m_jit.jump(), notTaken);
416 }
417
418 // Returns true if the compare is fused with a subsequent branch.
419 bool SpeculativeJIT::compare(Node& node, MacroAssembler::RelationalCondition condition, Z_DFGOperation_EJJ operation)
420 {
421     // Fused compare & branch.
422     NodeIndex branchNodeIndex = detectPeepHoleBranch();
423     if (branchNodeIndex != NoNode) {
424         // detectPeepHoleBranch currently only permits the branch to be the very next node,
425         // so can be no intervening nodes to also reference the compare. 
426         ASSERT(node.adjustedRefCount() == 1);
427
428         if (shouldSpeculateInteger(node.child1(), node.child2()))
429             compilePeepHoleIntegerBranch(node, branchNodeIndex, condition);
430         else
431             compilePeepHoleCall(node, branchNodeIndex, operation);
432
433         use(node.child1());
434         use(node.child2());
435         m_compileIndex = branchNodeIndex;
436         return true;
437     }
438
439     // Normal case, not fused to branch.
440     SpeculateIntegerOperand op1(this, node.child1());
441     SpeculateIntegerOperand op2(this, node.child2());
442     GPRTemporary result(this, op1, op2);
443
444     m_jit.compare32(condition, op1.gpr(), op2.gpr(), result.gpr());
445
446     // If we add a DataFormatBool, we should use it here.
447     m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
448     jsValueResult(result.gpr(), m_compileIndex);
449     return false;
450 }
451
452 void SpeculativeJIT::compile(Node& node)
453 {
454     NodeType op = node.op;
455
456     switch (op) {
457     case JSConstant:
458         initConstantInfo(m_compileIndex);
459         break;
460
461     case GetLocal: {
462         GPRTemporary result(this);
463         PredictedType prediction = m_jit.graph().getPrediction(node.local());
464         if (prediction == PredictInt32) {
465             m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr());
466
467             // Like integerResult, but don't useChildren - our children are phi nodes,
468             // and don't represent values within this dataflow with virtual registers.
469             VirtualRegister virtualRegister = node.virtualRegister();
470             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderInteger);
471             m_generationInfo[virtualRegister].initInteger(m_compileIndex, node.refCount(), result.gpr());
472         } else {
473             m_jit.loadPtr(JITCompiler::addressFor(node.local()), result.gpr());
474
475             // Like jsValueResult, but don't useChildren - our children are phi nodes,
476             // and don't represent values within this dataflow with virtual registers.
477             VirtualRegister virtualRegister = node.virtualRegister();
478             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
479             m_generationInfo[virtualRegister].initJSValue(m_compileIndex, node.refCount(), result.gpr(), (prediction == PredictArray) ? DataFormatJSCell : DataFormatJS);
480         }
481         break;
482     }
483
484     case SetLocal: {
485         switch (m_jit.graph().getPrediction(node.local())) {
486         case PredictInt32: {
487             SpeculateIntegerOperand value(this, node.child1());
488             m_jit.store32(value.gpr(), JITCompiler::payloadFor(node.local()));
489             noResult(m_compileIndex);
490             break;
491         }
492         case PredictArray: {
493             SpeculateCellOperand cell(this, node.child1());
494             GPRReg cellGPR = cell.gpr();
495             speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
496             m_jit.storePtr(cellGPR, JITCompiler::addressFor(node.local()));
497             noResult(m_compileIndex);
498             break;
499         }
500
501         default: {
502             JSValueOperand value(this, node.child1());
503             m_jit.storePtr(value.gpr(), JITCompiler::addressFor(node.local()));
504             noResult(m_compileIndex);
505             break;
506         }
507         }
508         break;
509     }
510
511     case BitAnd:
512     case BitOr:
513     case BitXor:
514         if (isInt32Constant(node.child1())) {
515             SpeculateIntegerOperand op2(this, node.child2());
516             GPRTemporary result(this, op2);
517
518             bitOp(op, valueOfInt32Constant(node.child1()), op2.gpr(), result.gpr());
519
520             integerResult(result.gpr(), m_compileIndex);
521         } else if (isInt32Constant(node.child2())) {
522             SpeculateIntegerOperand op1(this, node.child1());
523             GPRTemporary result(this, op1);
524
525             bitOp(op, valueOfInt32Constant(node.child2()), op1.gpr(), result.gpr());
526
527             integerResult(result.gpr(), m_compileIndex);
528         } else {
529             SpeculateIntegerOperand op1(this, node.child1());
530             SpeculateIntegerOperand op2(this, node.child2());
531             GPRTemporary result(this, op1, op2);
532
533             GPRReg reg1 = op1.gpr();
534             GPRReg reg2 = op2.gpr();
535             bitOp(op, reg1, reg2, result.gpr());
536
537             integerResult(result.gpr(), m_compileIndex);
538         }
539         break;
540
541     case BitRShift:
542     case BitLShift:
543     case BitURShift:
544         if (isInt32Constant(node.child2())) {
545             SpeculateIntegerOperand op1(this, node.child1());
546             GPRTemporary result(this, op1);
547
548             shiftOp(op, op1.gpr(), valueOfInt32Constant(node.child2()) & 0x1f, result.gpr());
549
550             integerResult(result.gpr(), m_compileIndex);
551         } else {
552             // Do not allow shift amount to be used as the result, MacroAssembler does not permit this.
553             SpeculateIntegerOperand op1(this, node.child1());
554             SpeculateIntegerOperand op2(this, node.child2());
555             GPRTemporary result(this, op1);
556
557             GPRReg reg1 = op1.gpr();
558             GPRReg reg2 = op2.gpr();
559             shiftOp(op, reg1, reg2, result.gpr());
560
561             integerResult(result.gpr(), m_compileIndex);
562         }
563         break;
564
565     case UInt32ToNumber: {
566         IntegerOperand op1(this, node.child1());
567         GPRTemporary result(this, op1);
568
569         // Test the operand is positive.
570         speculationCheck(m_jit.branch32(MacroAssembler::LessThan, op1.gpr(), TrustedImm32(0)));
571
572         m_jit.move(op1.gpr(), result.gpr());
573         integerResult(result.gpr(), m_compileIndex, op1.format());
574         break;
575     }
576
577     case ValueToInt32: {
578         SpeculateIntegerOperand op1(this, node.child1());
579         GPRTemporary result(this, op1);
580         m_jit.move(op1.gpr(), result.gpr());
581         integerResult(result.gpr(), m_compileIndex, op1.format());
582         break;
583     }
584
585     case ValueToNumber: {
586         if (isInteger(node.child1())) {
587             SpeculateIntegerOperand op1(this, node.child1());
588             GPRTemporary result(this, op1);
589             m_jit.move(op1.gpr(), result.gpr());
590             integerResult(result.gpr(), m_compileIndex, op1.format());
591             break;
592         }
593         SpeculateDoubleOperand op1(this, node.child1());
594         FPRTemporary result(this, op1);
595         m_jit.moveDouble(op1.fpr(), result.fpr());
596         doubleResult(result.fpr(), m_compileIndex);
597         break;
598     }
599
600     case ValueAdd:
601     case ArithAdd: {
602         if (shouldSpeculateInteger(node.child1(), node.child2())) {
603             if (isInt32Constant(node.child1())) {
604                 int32_t imm1 = valueOfInt32Constant(node.child1());
605                 SpeculateIntegerOperand op2(this, node.child2());
606                 GPRTemporary result(this);
607
608                 speculationCheck(m_jit.branchAdd32(MacroAssembler::Overflow, op2.gpr(), Imm32(imm1), result.gpr()));
609
610                 integerResult(result.gpr(), m_compileIndex);
611                 break;
612             }
613                 
614             if (isInt32Constant(node.child2())) {
615                 SpeculateIntegerOperand op1(this, node.child1());
616                 int32_t imm2 = valueOfInt32Constant(node.child2());
617                 GPRTemporary result(this);
618
619                 speculationCheck(m_jit.branchAdd32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
620
621                 integerResult(result.gpr(), m_compileIndex);
622                 break;
623             }
624                 
625             SpeculateIntegerOperand op1(this, node.child1());
626             SpeculateIntegerOperand op2(this, node.child2());
627             GPRTemporary result(this, op1, op2);
628
629             GPRReg gpr1 = op1.gpr();
630             GPRReg gpr2 = op2.gpr();
631             GPRReg gprResult = result.gpr();
632             MacroAssembler::Jump check = m_jit.branchAdd32(MacroAssembler::Overflow, gpr1, gpr2, gprResult);
633
634             if (gpr1 == gprResult)
635                 speculationCheck(check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr2));
636             else if (gpr2 == gprResult)
637                 speculationCheck(check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr1));
638             else
639                 speculationCheck(check);
640
641             integerResult(gprResult, m_compileIndex);
642             break;
643         }
644
645         SpeculateDoubleOperand op1(this, node.child1());
646         SpeculateDoubleOperand op2(this, node.child2());
647         FPRTemporary result(this, op1, op2);
648
649         FPRReg reg1 = op1.fpr();
650         FPRReg reg2 = op2.fpr();
651         m_jit.addDouble(reg1, reg2, result.fpr());
652
653         doubleResult(result.fpr(), m_compileIndex);
654         break;
655     }
656
657     case ArithSub: {
658         if (shouldSpeculateInteger(node.child1(), node.child2())) {
659             if (isInt32Constant(node.child2())) {
660                 SpeculateIntegerOperand op1(this, node.child1());
661                 int32_t imm2 = valueOfInt32Constant(node.child2());
662                 GPRTemporary result(this);
663
664                 speculationCheck(m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
665
666                 integerResult(result.gpr(), m_compileIndex);
667                 break;
668             }
669                 
670             SpeculateIntegerOperand op1(this, node.child1());
671             SpeculateIntegerOperand op2(this, node.child2());
672             GPRTemporary result(this);
673
674             speculationCheck(m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), op2.gpr(), result.gpr()));
675
676             integerResult(result.gpr(), m_compileIndex);
677             break;
678         }
679
680         SpeculateDoubleOperand op1(this, node.child1());
681         SpeculateDoubleOperand op2(this, node.child2());
682         FPRTemporary result(this, op1);
683
684         FPRReg reg1 = op1.fpr();
685         FPRReg reg2 = op2.fpr();
686         m_jit.subDouble(reg1, reg2, result.fpr());
687
688         doubleResult(result.fpr(), m_compileIndex);
689         break;
690     }
691
692     case ArithMul: {
693         if (shouldSpeculateInteger(node.child1(), node.child2())) {
694             SpeculateIntegerOperand op1(this, node.child1());
695             SpeculateIntegerOperand op2(this, node.child2());
696             GPRTemporary result(this);
697
698             GPRReg reg1 = op1.gpr();
699             GPRReg reg2 = op2.gpr();
700             speculationCheck(m_jit.branchMul32(MacroAssembler::Overflow, reg1, reg2, result.gpr()));
701
702             MacroAssembler::Jump resultNonZero = m_jit.branchTest32(MacroAssembler::NonZero, result.gpr());
703             speculationCheck(m_jit.branch32(MacroAssembler::LessThan, reg1, TrustedImm32(0)));
704             speculationCheck(m_jit.branch32(MacroAssembler::LessThan, reg2, TrustedImm32(0)));
705             resultNonZero.link(&m_jit);
706
707             integerResult(result.gpr(), m_compileIndex);
708             break;
709         }
710
711         SpeculateDoubleOperand op1(this, node.child1());
712         SpeculateDoubleOperand op2(this, node.child2());
713         FPRTemporary result(this, op1, op2);
714
715         FPRReg reg1 = op1.fpr();
716         FPRReg reg2 = op2.fpr();
717         
718         m_jit.mulDouble(reg1, reg2, result.fpr());
719         
720         doubleResult(result.fpr(), m_compileIndex);
721         break;
722     }
723
724     case ArithDiv: {
725         SpeculateDoubleOperand op1(this, node.child1());
726         SpeculateDoubleOperand op2(this, node.child2());
727         FPRTemporary result(this, op1);
728
729         FPRReg reg1 = op1.fpr();
730         FPRReg reg2 = op2.fpr();
731         m_jit.divDouble(reg1, reg2, result.fpr());
732
733         doubleResult(result.fpr(), m_compileIndex);
734         break;
735     }
736
737     case ArithMod: {
738         SpeculateIntegerOperand op1(this, node.child1());
739         SpeculateIntegerOperand op2(this, node.child2());
740         GPRTemporary eax(this, X86Registers::eax);
741         GPRTemporary edx(this, X86Registers::edx);
742         GPRReg op1Gpr = op1.gpr();
743         GPRReg op2Gpr = op2.gpr();
744
745         speculationCheck(m_jit.branchTestPtr(JITCompiler::Zero, op2Gpr));
746
747         GPRReg temp2 = InvalidGPRReg;
748         if (op2Gpr == X86Registers::eax || op2Gpr == X86Registers::edx) {
749             temp2 = allocate();
750             m_jit.move(op2Gpr, temp2);
751             op2Gpr = temp2;
752         }
753
754         m_jit.move(op1Gpr, eax.gpr());
755         m_jit.assembler().cdq();
756         m_jit.assembler().idivl_r(op2Gpr);
757
758         if (temp2 != InvalidGPRReg)
759             unlock(temp2);
760
761         integerResult(edx.gpr(), m_compileIndex);
762         break;
763     }
764
765     case LogicalNot: {
766         JSValueOperand value(this, node.child1());
767         GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add).
768
769         m_jit.move(value.gpr(), result.gpr());
770         m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), result.gpr());
771         speculationCheck(m_jit.branchTestPtr(JITCompiler::NonZero, result.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
772         m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueTrue)), result.gpr());
773
774         // If we add a DataFormatBool, we should use it here.
775         jsValueResult(result.gpr(), m_compileIndex);
776         break;
777     }
778
779     case CompareLess:
780         if (compare(node, JITCompiler::LessThan, operationCompareLess))
781             return;
782         break;
783
784     case CompareLessEq:
785         if (compare(node, JITCompiler::LessThanOrEqual, operationCompareLessEq))
786             return;
787         break;
788
789     case CompareGreater:
790         if (compare(node, JITCompiler::GreaterThan, operationCompareGreater))
791             return;
792         break;
793
794     case CompareGreaterEq:
795         if (compare(node, JITCompiler::GreaterThanOrEqual, operationCompareGreaterEq))
796             return;
797         break;
798
799     case CompareEq:
800         if (compare(node, JITCompiler::Equal, operationCompareEq))
801             return;
802         break;
803
804     case CompareStrictEq: {
805         SpeculateIntegerOperand op1(this, node.child1());
806         SpeculateIntegerOperand op2(this, node.child2());
807         GPRTemporary result(this, op1, op2);
808
809         m_jit.compare32(JITCompiler::Equal, op1.gpr(), op2.gpr(), result.gpr());
810
811         // If we add a DataFormatBool, we should use it here.
812         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
813         jsValueResult(result.gpr(), m_compileIndex);
814         break;
815     }
816
817     case GetByVal: {
818         NodeIndex alias = node.child3();
819         if (alias != NoNode) {
820             // FIXME: result should be able to reuse child1, child2. Should have an 'UnusedOperand' type.
821             JSValueOperand aliasedValue(this, node.child3());
822             GPRTemporary result(this, aliasedValue);
823             m_jit.move(aliasedValue.gpr(), result.gpr());
824             jsValueResult(result.gpr(), m_compileIndex);
825             break;
826         }
827
828         SpeculateCellOperand base(this, node.child1());
829         SpeculateStrictInt32Operand property(this, node.child2());
830         GPRTemporary storage(this);
831
832         GPRReg baseReg = base.gpr();
833         GPRReg propertyReg = property.gpr();
834         GPRReg storageReg = storage.gpr();
835
836         // Get the array storage. We haven't yet checked this is a JSArray, so this is only safe if
837         // an access with offset JSArray::storageOffset() is valid for all JSCells!
838         m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
839
840         // Check that base is an array, and that property is contained within m_vector (< m_vectorLength).
841         // If we have predicted the base to be type array, we can skip the check.
842         Node& baseNode = m_jit.graph()[node.child1()];
843         if (baseNode.op != GetLocal || m_jit.graph().getPrediction(baseNode.local()) != PredictArray)
844             speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
845         speculationCheck(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset())));
846
847         // FIXME: In cases where there are subsequent by_val accesses to the same base it might help to cache
848         // the storage pointer - especially if there happens to be another register free right now. If we do so,
849         // then we'll need to allocate a new temporary for result.
850         GPRTemporary& result = storage;
851         m_jit.loadPtr(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), result.gpr());
852         speculationCheck(m_jit.branchTestPtr(MacroAssembler::Zero, result.gpr()));
853
854         jsValueResult(result.gpr(), m_compileIndex);
855         break;
856     }
857
858     case PutByVal: {
859         SpeculateCellOperand base(this, node.child1());
860         SpeculateStrictInt32Operand property(this, node.child2());
861         JSValueOperand value(this, node.child3());
862         GPRTemporary scratch(this);
863
864         // Map base, property & value into registers, allocate a scratch register.
865         GPRReg baseReg = base.gpr();
866         GPRReg propertyReg = property.gpr();
867         GPRReg valueReg = value.gpr();
868         GPRReg scratchReg = scratch.gpr();
869         
870         if (!m_compileOkay)
871             return;
872
873         writeBarrier(m_jit, baseReg, scratchReg);
874
875         // Check that base is an array, and that property is contained within m_vector (< m_vectorLength).
876         // If we have predicted the base to be type array, we can skip the check.
877         Node& baseNode = m_jit.graph()[node.child1()];
878         if (baseNode.op != GetLocal || m_jit.graph().getPrediction(baseNode.local()) != PredictArray)
879             speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
880         MacroAssembler::Jump withinArrayBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset()));
881
882         // Code to handle put beyond array bounds.
883         silentSpillAllRegisters(scratchReg, baseReg, propertyReg, valueReg);
884         setupStubArguments(baseReg, propertyReg, valueReg);
885         m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
886         JITCompiler::Call functionCall = appendCallWithExceptionCheck(operationPutByValBeyondArrayBounds);
887         silentFillAllRegisters(scratchReg);
888         JITCompiler::Jump wasBeyondArrayBounds = m_jit.jump();
889
890         withinArrayBounds.link(&m_jit);
891
892         // Get the array storage.
893         GPRReg storageReg = scratchReg;
894         m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
895
896         // Check if we're writing to a hole; if so increment m_numValuesInVector.
897         MacroAssembler::Jump notHoleValue = m_jit.branchTestPtr(MacroAssembler::NonZero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
898         m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
899
900         // If we're writing to a hole we might be growing the array; 
901         MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, OBJECT_OFFSETOF(ArrayStorage, m_length)));
902         m_jit.add32(TrustedImm32(1), propertyReg);
903         m_jit.store32(propertyReg, MacroAssembler::Address(storageReg, OBJECT_OFFSETOF(ArrayStorage, m_length)));
904         m_jit.sub32(TrustedImm32(1), propertyReg);
905
906         lengthDoesNotNeedUpdate.link(&m_jit);
907         notHoleValue.link(&m_jit);
908
909         // Store the value to the array.
910         m_jit.storePtr(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
911
912         wasBeyondArrayBounds.link(&m_jit);
913
914         noResult(m_compileIndex);
915         break;
916     }
917
918     case PutByValAlias: {
919         SpeculateCellOperand base(this, node.child1());
920         SpeculateStrictInt32Operand property(this, node.child2());
921         JSValueOperand value(this, node.child3());
922         GPRTemporary scratch(this);
923         
924         GPRReg baseReg = base.gpr();
925         GPRReg scratchReg = scratch.gpr();
926
927         writeBarrier(m_jit, baseReg, scratchReg);
928
929         // Get the array storage.
930         GPRReg storageReg = scratchReg;
931         m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
932
933         // Store the value to the array.
934         GPRReg propertyReg = property.gpr();
935         GPRReg valueReg = value.gpr();
936         m_jit.storePtr(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
937
938         noResult(m_compileIndex);
939         break;
940     }
941
942     case DFG::Jump: {
943         BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());
944         if (taken != (m_block + 1))
945             addBranch(m_jit.jump(), taken);
946         noResult(m_compileIndex);
947         break;
948     }
949
950     case Branch: {
951         JSValueOperand value(this, node.child1());
952         GPRReg valueReg = value.gpr();
953
954         BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());
955         BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(node.notTakenBytecodeOffset());
956
957         // Integers
958         addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueReg, MacroAssembler::ImmPtr(JSValue::encode(jsNumber(0)))), notTaken);
959         MacroAssembler::Jump isNonZeroInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, valueReg, GPRInfo::tagTypeNumberRegister);
960
961         // Booleans
962         addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueReg, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(false)))), notTaken);
963         speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, valueReg, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(true)))));
964
965         if (taken == (m_block + 1))
966             isNonZeroInteger.link(&m_jit);
967         else {
968             addBranch(isNonZeroInteger, taken);
969             addBranch(m_jit.jump(), taken);
970         }
971
972         noResult(m_compileIndex);
973         break;
974     }
975
976     case Return: {
977         ASSERT(GPRInfo::callFrameRegister != GPRInfo::regT1);
978         ASSERT(GPRInfo::regT1 != GPRInfo::returnValueGPR);
979         ASSERT(GPRInfo::returnValueGPR != GPRInfo::callFrameRegister);
980
981 #if DFG_SUCCESS_STATS
982         static SamplingCounter counter("SpeculativeJIT");
983         m_jit.emitCount(counter);
984 #endif
985
986         // Return the result in returnValueGPR.
987         JSValueOperand op1(this, node.child1());
988         m_jit.move(op1.gpr(), GPRInfo::returnValueGPR);
989
990         // Grab the return address.
991         m_jit.emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, GPRInfo::regT1);
992         // Restore our caller's "r".
993         m_jit.emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, GPRInfo::callFrameRegister);
994         // Return.
995         m_jit.restoreReturnAddressBeforeReturn(GPRInfo::regT1);
996         m_jit.ret();
997         
998         noResult(m_compileIndex);
999         break;
1000     }
1001
1002     case ConvertThis: {
1003         SpeculateCellOperand thisValue(this, node.child1());
1004         GPRTemporary temp(this);
1005
1006         m_jit.loadPtr(JITCompiler::Address(thisValue.gpr(), JSCell::structureOffset()), temp.gpr());
1007         speculationCheck(m_jit.branchTest8(JITCompiler::NonZero, JITCompiler::Address(temp.gpr(), Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(NeedsThisConversion)));
1008
1009         cellResult(thisValue.gpr(), m_compileIndex);
1010         break;
1011     }
1012
1013     case GetById: {
1014         SpeculateCellOperand base(this, node.child1());
1015         GPRTemporary result(this, base);
1016
1017         GPRReg resultGPR = result.gpr();
1018
1019         cachedGetById(base.gpr(), resultGPR, node.identifierNumber());
1020
1021         jsValueResult(resultGPR, m_compileIndex);
1022         break;
1023     }
1024         
1025     case GetMethod: {
1026         SpeculateCellOperand base(this, node.child1());
1027         GPRTemporary result(this, base);
1028
1029         GPRReg resultGPR = result.gpr();
1030
1031         cachedGetMethod(base.gpr(), resultGPR, node.identifierNumber());
1032
1033         jsValueResult(resultGPR, m_compileIndex);
1034         break;
1035     }
1036
1037     case PutById: {
1038         SpeculateCellOperand base(this, node.child1());
1039         JSValueOperand value(this, node.child2());
1040         GPRTemporary scratch(this);
1041
1042         cachedPutById(base.gpr(), value.gpr(), scratch.gpr(), node.identifierNumber(), NotDirect);
1043         
1044         noResult(m_compileIndex);
1045         break;
1046     }
1047
1048     case PutByIdDirect: {
1049         SpeculateCellOperand base(this, node.child1());
1050         JSValueOperand value(this, node.child2());
1051         GPRTemporary scratch(this);
1052
1053         cachedPutById(base.gpr(), value.gpr(), scratch.gpr(), node.identifierNumber(), Direct);
1054
1055         noResult(m_compileIndex);
1056         break;
1057     }
1058
1059     case GetGlobalVar: {
1060         GPRTemporary result(this);
1061
1062         JSVariableObject* globalObject = m_jit.codeBlock()->globalObject();
1063         m_jit.loadPtr(globalObject->addressOfRegisters(), result.gpr());
1064         m_jit.loadPtr(JITCompiler::addressForGlobalVar(result.gpr(), node.varNumber()), result.gpr());
1065
1066         jsValueResult(result.gpr(), m_compileIndex);
1067         break;
1068     }
1069
1070     case PutGlobalVar: {
1071         JSValueOperand value(this, node.child1());
1072         GPRTemporary globalObject(this);
1073         GPRTemporary scratch(this);
1074         
1075         GPRReg globalObjectReg = globalObject.gpr();
1076         GPRReg scratchReg = scratch.gpr();
1077
1078         m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.codeBlock()->globalObject()), globalObjectReg);
1079
1080         writeBarrier(m_jit, globalObjectReg, scratchReg);
1081
1082         m_jit.loadPtr(MacroAssembler::Address(globalObjectReg, JSVariableObject::offsetOfRegisters()), scratchReg);
1083         m_jit.storePtr(value.gpr(), JITCompiler::addressForGlobalVar(scratchReg, node.varNumber()));
1084
1085         noResult(m_compileIndex);
1086         break;
1087     }
1088
1089     case CheckHasInstance: {
1090         SpeculateCellOperand base(this, node.child1());
1091         GPRTemporary structure(this);
1092
1093         // Speculate that base 'ImplementsDefaultHasInstance'.
1094         m_jit.loadPtr(MacroAssembler::Address(base.gpr(), JSCell::structureOffset()), structure.gpr());
1095         speculationCheck(m_jit.branchTest8(MacroAssembler::Zero, MacroAssembler::Address(structure.gpr(), Structure::typeInfoFlagsOffset()), MacroAssembler::TrustedImm32(ImplementsDefaultHasInstance)));
1096
1097         noResult(m_compileIndex);
1098         break;
1099     }
1100
1101     case InstanceOf: {
1102         SpeculateCellOperand value(this, node.child1());
1103         // Base unused since we speculate default InstanceOf behaviour in CheckHasInstance.
1104         SpeculateCellOperand prototype(this, node.child3());
1105
1106         GPRTemporary scratch(this);
1107
1108         GPRReg valueReg = value.gpr();
1109         GPRReg prototypeReg = prototype.gpr();
1110         GPRReg scratchReg = scratch.gpr();
1111
1112         // Check that prototype is an object.
1113         m_jit.loadPtr(MacroAssembler::Address(prototypeReg, JSCell::structureOffset()), scratchReg);
1114         speculationCheck(m_jit.branch8(MacroAssembler::NotEqual, MacroAssembler::Address(scratchReg, Structure::typeInfoTypeOffset()), MacroAssembler::TrustedImm32(ObjectType)));
1115
1116         // Initialize scratchReg with the value being checked.
1117         m_jit.move(valueReg, scratchReg);
1118
1119         // Walk up the prototype chain of the value (in scratchReg), comparing to prototypeReg.
1120         MacroAssembler::Label loop(&m_jit);
1121         m_jit.loadPtr(MacroAssembler::Address(scratchReg, JSCell::structureOffset()), scratchReg);
1122         m_jit.loadPtr(MacroAssembler::Address(scratchReg, Structure::prototypeOffset()), scratchReg);
1123         MacroAssembler::Jump isInstance = m_jit.branchPtr(MacroAssembler::Equal, scratchReg, prototypeReg);
1124         m_jit.branchTestPtr(MacroAssembler::Zero, scratchReg, GPRInfo::tagMaskRegister).linkTo(loop, &m_jit);
1125
1126         // No match - result is false.
1127         m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(false))), scratchReg);
1128         MacroAssembler::Jump putResult = m_jit.jump();
1129
1130         isInstance.link(&m_jit);
1131         m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(true))), scratchReg);
1132
1133         putResult.link(&m_jit);
1134         jsValueResult(scratchReg, m_compileIndex);
1135         break;
1136     }
1137
1138     case Phi:
1139         ASSERT_NOT_REACHED();
1140
1141     case Breakpoint:
1142 #if ENABLE(DEBUG_WITH_BREAKPOINT)
1143         m_jit.breakpoint();
1144 #else
1145         ASSERT_NOT_REACHED();
1146 #endif
1147         break;
1148         
1149     case Call:
1150         emitCall(node);
1151         break;
1152     }
1153
1154     if (node.hasResult() && node.mustGenerate())
1155         use(m_compileIndex);
1156 }
1157
1158 void SpeculativeJIT::compile(BasicBlock& block)
1159 {
1160     ASSERT(m_compileIndex == block.begin);
1161     m_blockHeads[m_block] = m_jit.label();
1162 #if DFG_JIT_BREAK_ON_EVERY_BLOCK
1163     m_jit.breakpoint();
1164 #endif
1165
1166     for (; m_compileIndex < block.end; ++m_compileIndex) {
1167         Node& node = m_jit.graph()[m_compileIndex];
1168         if (!node.shouldGenerate())
1169             continue;
1170
1171 #if DFG_DEBUG_VERBOSE
1172         fprintf(stderr, "SpeculativeJIT generating Node @%d at JIT offset 0x%x\n", (int)m_compileIndex, m_jit.debugOffset());
1173 #endif
1174 #if DFG_JIT_BREAK_ON_EVERY_NODE
1175         m_jit.breakpoint();
1176 #endif
1177         checkConsistency();
1178         compile(node);
1179         if (!m_compileOkay)
1180             return;
1181         checkConsistency();
1182     }
1183 }
1184
1185 // If we are making type predictions about our arguments then
1186 // we need to check that they are correct on function entry.
1187 void SpeculativeJIT::checkArgumentTypes()
1188 {
1189     ASSERT(!m_compileIndex);
1190     for (int i = 0; i < m_jit.codeBlock()->m_numParameters; ++i) {
1191         VirtualRegister virtualRegister = (VirtualRegister)(m_jit.codeBlock()->thisRegister() + i);
1192         switch (m_jit.graph().getPrediction(virtualRegister)) {
1193         case PredictInt32:
1194             speculationCheck(m_jit.branchPtr(MacroAssembler::Below, JITCompiler::addressFor(virtualRegister), GPRInfo::tagTypeNumberRegister));
1195             break;
1196
1197         case PredictArray: {
1198             GPRTemporary temp(this);
1199             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1200             speculationCheck(m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
1201             speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
1202             break;
1203         }
1204
1205         default:
1206             break;
1207         }
1208     }
1209 }
1210
1211 // For any vars that we will be treating as numeric, write 0 to
1212 // the var on entry. Throughout the block we will only read/write
1213 // to the payload, by writing the tag now we prevent the GC from
1214 // misinterpreting values as pointers.
1215 void SpeculativeJIT::initializeVariableTypes()
1216 {
1217     ASSERT(!m_compileIndex);
1218     for (int var = 0; var < m_jit.codeBlock()->m_numVars; ++var) {
1219         if (m_jit.graph().getPrediction(var) == PredictInt32)
1220             m_jit.storePtr(GPRInfo::tagTypeNumberRegister, JITCompiler::addressFor((VirtualRegister)var));
1221     }
1222 }
1223
1224 bool SpeculativeJIT::compile()
1225 {
1226     checkArgumentTypes();
1227     initializeVariableTypes();
1228
1229     ASSERT(!m_compileIndex);
1230     for (m_block = 0; m_block < m_jit.graph().m_blocks.size(); ++m_block) {
1231         compile(*m_jit.graph().m_blocks[m_block]);
1232         if (!m_compileOkay)
1233             return false;
1234     }
1235     linkBranches();
1236     return true;
1237 }
1238
1239 } } // namespace JSC::DFG
1240
1241 #endif