DFG speculative JIT does not initialize integer tags for PredictInt32 temporaries
[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 DataFormatBoolean:
132     case DataFormatJSDouble:
133     case DataFormatJSCell:
134     case DataFormatJSBoolean: {
135         terminateSpeculativeExecution();
136         returnFormat = DataFormatInteger;
137         return allocate();
138     }
139     }
140
141     ASSERT_NOT_REACHED();
142     return InvalidGPRReg;
143 }
144
145 SpeculationCheck::SpeculationCheck(MacroAssembler::Jump check, SpeculativeJIT* jit, unsigned recoveryIndex)
146     : m_check(check)
147     , m_nodeIndex(jit->m_compileIndex)
148     , m_recoveryIndex(recoveryIndex)
149 {
150     for (gpr_iterator iter = jit->m_gprs.begin(); iter != jit->m_gprs.end(); ++iter) {
151         if (iter.name() != InvalidVirtualRegister) {
152             GenerationInfo& info =  jit->m_generationInfo[iter.name()];
153             m_gprInfo[iter.index()].nodeIndex = info.nodeIndex();
154             m_gprInfo[iter.index()].format = info.registerFormat();
155             ASSERT(m_gprInfo[iter.index()].format != DataFormatNone);
156             m_gprInfo[iter.index()].isSpilled = info.spillFormat() != DataFormatNone;
157         } else
158             m_gprInfo[iter.index()].nodeIndex = NoNode;
159     }
160     for (fpr_iterator iter = jit->m_fprs.begin(); iter != jit->m_fprs.end(); ++iter) {
161         if (iter.name() != InvalidVirtualRegister) {
162             GenerationInfo& info =  jit->m_generationInfo[iter.name()];
163             ASSERT(info.registerFormat() == DataFormatDouble);
164             m_fprInfo[iter.index()].nodeIndex = info.nodeIndex();
165             m_fprInfo[iter.index()].format = DataFormatDouble;
166             m_fprInfo[iter.index()].isSpilled = info.spillFormat() != DataFormatNone;
167         } else
168             m_fprInfo[iter.index()].nodeIndex = NoNode;
169     }
170 }
171
172 GPRReg SpeculativeJIT::fillSpeculateInt(NodeIndex nodeIndex, DataFormat& returnFormat)
173 {
174     return fillSpeculateIntInternal<false>(nodeIndex, returnFormat);
175 }
176
177 GPRReg SpeculativeJIT::fillSpeculateIntStrict(NodeIndex nodeIndex)
178 {
179     DataFormat mustBeDataFormatInteger;
180     GPRReg result = fillSpeculateIntInternal<true>(nodeIndex, mustBeDataFormatInteger);
181     ASSERT(mustBeDataFormatInteger == DataFormatInteger);
182     return result;
183 }
184
185 FPRReg SpeculativeJIT::fillSpeculateDouble(NodeIndex nodeIndex)
186 {
187     Node& node = m_jit.graph()[nodeIndex];
188     VirtualRegister virtualRegister = node.virtualRegister();
189     GenerationInfo& info = m_generationInfo[virtualRegister];
190
191     if (info.registerFormat() == DataFormatNone) {
192         GPRReg gpr = allocate();
193
194         if (node.isConstant()) {
195             if (isInt32Constant(nodeIndex)) {
196                 FPRReg fpr = fprAllocate();
197                 m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(static_cast<double>(valueOfInt32Constant(nodeIndex))))), gpr);
198                 m_jit.movePtrToDouble(gpr, fpr);
199                 unlock(gpr);
200
201                 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
202                 info.fillDouble(fpr);
203                 return fpr;
204             }
205             if (isDoubleConstant(nodeIndex)) {
206                 FPRReg fpr = fprAllocate();
207                 m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(valueOfDoubleConstant(nodeIndex)))), gpr);
208                 m_jit.movePtrToDouble(gpr, fpr);
209                 unlock(gpr);
210
211                 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
212                 info.fillDouble(fpr);
213                 return fpr;
214             }
215             terminateSpeculativeExecution();
216             return fprAllocate();
217         } else {
218             DataFormat spillFormat = info.spillFormat();
219             ASSERT(spillFormat & DataFormatJS);
220             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
221             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
222             info.fillJSValue(gpr, spillFormat);
223             unlock(gpr);
224         }
225     }
226
227     switch (info.registerFormat()) {
228     case DataFormatNone: // Should have filled, above.
229     case DataFormatBoolean: // This type never occurs.
230         ASSERT_NOT_REACHED();
231         
232     case DataFormatCell:
233     case DataFormatJSCell:
234     case DataFormatJS:
235     case DataFormatJSBoolean: {
236         GPRReg jsValueGpr = info.gpr();
237         m_gprs.lock(jsValueGpr);
238         FPRReg fpr = fprAllocate();
239         GPRReg tempGpr = allocate();
240
241         JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
242
243         speculationCheck(m_jit.branchTestPtr(MacroAssembler::Zero, jsValueGpr, GPRInfo::tagTypeNumberRegister));
244
245         // First, if we get here we have a double encoded as a JSValue
246         m_jit.move(jsValueGpr, tempGpr);
247         unboxDouble(tempGpr, fpr);
248         JITCompiler::Jump hasUnboxedDouble = m_jit.jump();
249
250         // Finally, handle integers.
251         isInteger.link(&m_jit);
252         m_jit.convertInt32ToDouble(jsValueGpr, fpr);
253         hasUnboxedDouble.link(&m_jit);
254
255         m_gprs.release(jsValueGpr);
256         m_gprs.unlock(jsValueGpr);
257         m_gprs.unlock(tempGpr);
258         m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
259         info.fillDouble(fpr);
260         info.killSpilled();
261         return fpr;
262     }
263
264     case DataFormatJSInteger:
265     case DataFormatInteger: {
266         FPRReg fpr = fprAllocate();
267         GPRReg gpr = info.gpr();
268         m_gprs.lock(gpr);
269         m_jit.convertInt32ToDouble(gpr, fpr);
270         m_gprs.unlock(gpr);
271         return fpr;
272     }
273
274     // Unbox the double
275     case DataFormatJSDouble: {
276         GPRReg gpr = info.gpr();
277         FPRReg fpr = fprAllocate();
278         if (m_gprs.isLocked(gpr)) {
279             // Make sure we don't trample gpr if it is in use.
280             GPRReg temp = allocate();
281             m_jit.move(gpr, temp);
282             unboxDouble(temp, fpr);
283             unlock(temp);
284         } else
285             unboxDouble(gpr, fpr);
286
287         m_gprs.release(gpr);
288         m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
289
290         info.fillDouble(fpr);
291         return fpr;
292     }
293
294     case DataFormatDouble: {
295         FPRReg fpr = info.fpr();
296         m_fprs.lock(fpr);
297         return fpr;
298     }
299     }
300
301     ASSERT_NOT_REACHED();
302     return InvalidFPRReg;
303 }
304
305 GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex)
306 {
307     Node& node = m_jit.graph()[nodeIndex];
308     VirtualRegister virtualRegister = node.virtualRegister();
309     GenerationInfo& info = m_generationInfo[virtualRegister];
310
311     switch (info.registerFormat()) {
312     case DataFormatNone: {
313         GPRReg gpr = allocate();
314
315         if (node.isConstant()) {
316             JSValue jsValue = valueOfJSConstant(nodeIndex);
317             if (jsValue.isCell()) {
318                 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
319                 m_jit.move(MacroAssembler::TrustedImmPtr(jsValue.asCell()), gpr);
320                 info.fillJSValue(gpr, DataFormatJSCell);
321                 return gpr;
322             }
323             terminateSpeculativeExecution();
324             return gpr;
325         }
326         ASSERT(info.spillFormat() & DataFormatJS);
327         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
328         m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
329
330         info.fillJSValue(gpr, DataFormatJS);
331         if (info.spillFormat() != DataFormatJSCell)
332             speculationCheck(m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister));
333         info.fillJSValue(gpr, DataFormatJSCell);
334         return gpr;
335     }
336
337     case DataFormatCell:
338     case DataFormatJSCell: {
339         GPRReg gpr = info.gpr();
340         m_gprs.lock(gpr);
341         return gpr;
342     }
343
344     case DataFormatJS: {
345         GPRReg gpr = info.gpr();
346         m_gprs.lock(gpr);
347         speculationCheck(m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister));
348         info.fillJSValue(gpr, DataFormatJSCell);
349         return gpr;
350     }
351
352     case DataFormatJSInteger:
353     case DataFormatInteger:
354     case DataFormatJSDouble:
355     case DataFormatDouble:
356     case DataFormatJSBoolean:
357     case DataFormatBoolean: {
358         terminateSpeculativeExecution();
359         return allocate();
360     }
361     }
362
363     ASSERT_NOT_REACHED();
364     return InvalidGPRReg;
365 }
366
367 GPRReg SpeculativeJIT::fillSpeculateBoolean(NodeIndex nodeIndex)
368 {
369     Node& node = m_jit.graph()[nodeIndex];
370     VirtualRegister virtualRegister = node.virtualRegister();
371     GenerationInfo& info = m_generationInfo[virtualRegister];
372
373     switch (info.registerFormat()) {
374     case DataFormatNone: {
375         GPRReg gpr = allocate();
376
377         if (node.isConstant()) {
378             JSValue jsValue = valueOfJSConstant(nodeIndex);
379             if (jsValue.isBoolean()) {
380                 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
381                 m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsValue)), gpr);
382                 info.fillJSValue(gpr, DataFormatJSBoolean);
383                 return gpr;
384             }
385             terminateSpeculativeExecution();
386             return gpr;
387         }
388         ASSERT(info.spillFormat() & DataFormatJS);
389         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
390         m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
391
392         info.fillJSValue(gpr, DataFormatJS);
393         if (info.spillFormat() != DataFormatJSBoolean) {
394             m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
395             speculationCheck(m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg));
396             m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
397         }
398         info.fillJSValue(gpr, DataFormatJSBoolean);
399         return gpr;
400     }
401
402     case DataFormatBoolean:
403     case DataFormatJSBoolean: {
404         GPRReg gpr = info.gpr();
405         m_gprs.lock(gpr);
406         return gpr;
407     }
408
409     case DataFormatJS: {
410         GPRReg gpr = info.gpr();
411         m_gprs.lock(gpr);
412         m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
413         speculationCheck(m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg));
414         m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
415         info.fillJSValue(gpr, DataFormatJSBoolean);
416         return gpr;
417     }
418
419     case DataFormatJSInteger:
420     case DataFormatInteger:
421     case DataFormatJSDouble:
422     case DataFormatDouble:
423     case DataFormatJSCell:
424     case DataFormatCell: {
425         terminateSpeculativeExecution();
426         return allocate();
427     }
428     }
429
430     ASSERT_NOT_REACHED();
431     return InvalidGPRReg;
432 }
433
434 void SpeculativeJIT::compilePeepHoleIntegerBranch(Node& node, NodeIndex branchNodeIndex, JITCompiler::RelationalCondition condition)
435 {
436     Node& branchNode = m_jit.graph()[branchNodeIndex];
437     BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
438     BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
439
440     // The branch instruction will branch to the taken block.
441     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
442     if (taken == (m_block + 1)) {
443         condition = JITCompiler::invert(condition);
444         BlockIndex tmp = taken;
445         taken = notTaken;
446         notTaken = tmp;
447     }
448
449     if (isInt32Constant(node.child1())) {
450         int32_t imm = valueOfInt32Constant(node.child1());
451         SpeculateIntegerOperand op2(this, node.child2());
452         addBranch(m_jit.branch32(condition, JITCompiler::Imm32(imm), op2.gpr()), taken);
453     } else if (isInt32Constant(node.child2())) {
454         SpeculateIntegerOperand op1(this, node.child1());
455         int32_t imm = valueOfInt32Constant(node.child2());
456         addBranch(m_jit.branch32(condition, op1.gpr(), JITCompiler::Imm32(imm)), taken);
457     } else {
458         SpeculateIntegerOperand op1(this, node.child1());
459         SpeculateIntegerOperand op2(this, node.child2());
460         addBranch(m_jit.branch32(condition, op1.gpr(), op2.gpr()), taken);
461     }
462
463     // Check for fall through, otherwise we need to jump.
464     if (notTaken != (m_block + 1))
465         addBranch(m_jit.jump(), notTaken);
466 }
467
468 JITCompiler::Jump SpeculativeJIT::convertToDouble(GPRReg value, FPRReg result, GPRReg tmp)
469 {
470     JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, value, GPRInfo::tagTypeNumberRegister);
471     
472     JITCompiler::Jump notNumber = m_jit.branchTestPtr(MacroAssembler::Zero, value, GPRInfo::tagTypeNumberRegister);
473     
474     m_jit.move(value, tmp);
475     unboxDouble(tmp, result);
476     
477     JITCompiler::Jump done = m_jit.jump();
478     
479     isInteger.link(&m_jit);
480     
481     m_jit.convertInt32ToDouble(value, result);
482     
483     done.link(&m_jit);
484
485     return notNumber;
486 }
487
488 void SpeculativeJIT::compilePeepHoleDoubleBranch(Node& node, NodeIndex branchNodeIndex, JITCompiler::DoubleCondition condition, Z_DFGOperation_EJJ operation)
489 {
490     Node& branchNode = m_jit.graph()[branchNodeIndex];
491     BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
492     BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
493     
494     bool op1Numeric = isKnownNumeric(node.child1());
495     bool op2Numeric = isKnownNumeric(node.child2());
496     
497     if (op1Numeric && op2Numeric) {
498         SpeculateDoubleOperand op1(this, node.child1());
499         SpeculateDoubleOperand op2(this, node.child2());
500         
501         addBranch(m_jit.branchDouble(condition, op1.fpr(), op2.fpr()), taken);
502     } else if (op1Numeric) {
503         SpeculateDoubleOperand op1(this, node.child1());
504         JSValueOperand op2(this, node.child2());
505         
506         FPRTemporary fprTmp(this);
507         GPRTemporary gprTmp(this);
508         
509         FPRReg op1FPR = op1.fpr();
510         GPRReg op2GPR = op2.gpr();
511         FPRReg op2FPR = fprTmp.fpr();
512         GPRReg gpr = gprTmp.gpr();
513         
514         JITCompiler::Jump slowPath = convertToDouble(op2GPR, op2FPR, gpr);
515         
516         addBranch(m_jit.branchDouble(condition, op1FPR, op2FPR), taken);
517         addBranch(m_jit.jump(), notTaken);
518         
519         slowPath.link(&m_jit);
520         
521         boxDouble(op1FPR, gpr);
522         
523         silentSpillAllRegisters(gpr);
524         setupStubArguments(gpr, op2GPR);
525         m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
526         appendCallWithExceptionCheck(operation);
527         m_jit.move(GPRInfo::returnValueGPR, gpr);
528         silentFillAllRegisters(gpr);
529         
530         addBranch(m_jit.branchTest8(JITCompiler::NonZero, gpr), taken);
531     } else {
532         JSValueOperand op1(this, node.child1());
533         SpeculateDoubleOperand op2(this, node.child2());
534         
535         FPRTemporary fprTmp(this);
536         GPRTemporary gprTmp(this);
537         
538         FPRReg op2FPR = op2.fpr();
539         GPRReg op1GPR = op1.gpr();
540         FPRReg op1FPR = fprTmp.fpr();
541         GPRReg gpr = gprTmp.gpr();
542         
543         JITCompiler::Jump slowPath = convertToDouble(op1GPR, op1FPR, gpr);
544         
545         addBranch(m_jit.branchDouble(condition, op1FPR, op2FPR), taken);
546         addBranch(m_jit.jump(), notTaken);
547         
548         slowPath.link(&m_jit);
549         
550         boxDouble(op2FPR, gpr);
551         
552         silentSpillAllRegisters(gpr);
553         setupStubArguments(op1GPR, gpr);
554         m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
555         appendCallWithExceptionCheck(operation);
556         m_jit.move(GPRInfo::returnValueGPR, gpr);
557         silentFillAllRegisters(gpr);
558         
559         addBranch(m_jit.branchTest8(JITCompiler::NonZero, gpr), taken);
560     }
561     
562     if (notTaken != (m_block + 1))
563         addBranch(m_jit.jump(), notTaken);
564 }
565
566 // Returns true if the compare is fused with a subsequent branch.
567 bool SpeculativeJIT::compare(Node& node, MacroAssembler::RelationalCondition condition, MacroAssembler::DoubleCondition doubleCondition, Z_DFGOperation_EJJ operation)
568 {
569     // Fused compare & branch.
570     NodeIndex branchNodeIndex = detectPeepHoleBranch();
571     if (branchNodeIndex != NoNode) {
572         // detectPeepHoleBranch currently only permits the branch to be the very next node,
573         // so can be no intervening nodes to also reference the compare. 
574         ASSERT(node.adjustedRefCount() == 1);
575
576         if (shouldSpeculateInteger(node.child1(), node.child2())) {
577             compilePeepHoleIntegerBranch(node, branchNodeIndex, condition);
578             use(node.child1());
579             use(node.child2());
580         } else if (isKnownNumeric(node.child1()) || isKnownNumeric(node.child2())) {
581             compilePeepHoleDoubleBranch(node, branchNodeIndex, doubleCondition, operation);
582             use(node.child1());
583             use(node.child2());
584         } else
585             nonSpeculativePeepholeBranch(node, branchNodeIndex, condition, operation);
586
587         m_compileIndex = branchNodeIndex;
588         return true;
589     }
590
591     if (isKnownNotInteger(node.child1()) || isKnownNotInteger(node.child2()))
592         nonSpeculativeNonPeepholeCompare(node, condition, operation);
593     else {
594         // Normal case, not fused to branch.
595         SpeculateIntegerOperand op1(this, node.child1());
596         SpeculateIntegerOperand op2(this, node.child2());
597         GPRTemporary result(this, op1, op2);
598         
599         m_jit.compare32(condition, op1.gpr(), op2.gpr(), result.gpr());
600         
601         // If we add a DataFormatBool, we should use it here.
602         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
603         jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
604     }
605     
606     return false;
607 }
608
609 void SpeculativeJIT::compile(Node& node)
610 {
611     NodeType op = node.op;
612
613     switch (op) {
614     case JSConstant:
615         initConstantInfo(m_compileIndex);
616         break;
617
618     case GetLocal: {
619         GPRTemporary result(this);
620         PredictedType prediction = m_jit.graph().getPrediction(node.local());
621         if (isInt32Prediction(prediction)) {
622             m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr());
623
624             // Like integerResult, but don't useChildren - our children are phi nodes,
625             // and don't represent values within this dataflow with virtual registers.
626             VirtualRegister virtualRegister = node.virtualRegister();
627             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderInteger);
628             m_generationInfo[virtualRegister].initInteger(m_compileIndex, node.refCount(), result.gpr());
629         } else {
630             m_jit.loadPtr(JITCompiler::addressFor(node.local()), result.gpr());
631
632             // Like jsValueResult, but don't useChildren - our children are phi nodes,
633             // and don't represent values within this dataflow with virtual registers.
634             VirtualRegister virtualRegister = node.virtualRegister();
635             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
636             
637             DataFormat format;
638             if (isArrayPrediction(prediction))
639                 format = DataFormatJSCell;
640             else if (isBooleanPrediction(prediction))
641                 format = DataFormatJSBoolean;
642             else
643                 format = DataFormatJS;
644             
645             m_generationInfo[virtualRegister].initJSValue(m_compileIndex, node.refCount(), result.gpr(), format);
646         }
647         break;
648     }
649
650     case SetLocal: {
651         PredictedType predictedType = m_jit.graph().getPrediction(node.local());
652         if (isInt32Prediction(predictedType)) {
653             SpeculateIntegerOperand value(this, node.child1());
654             m_jit.store32(value.gpr(), JITCompiler::payloadFor(node.local()));
655             noResult(m_compileIndex);
656         } else if (isArrayPrediction(predictedType)) {
657             SpeculateCellOperand cell(this, node.child1());
658             GPRReg cellGPR = cell.gpr();
659             speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
660             m_jit.storePtr(cellGPR, JITCompiler::addressFor(node.local()));
661             noResult(m_compileIndex);
662         } else if (isBooleanPrediction(predictedType)) {
663             SpeculateBooleanOperand boolean(this, node.child1());
664             m_jit.storePtr(boolean.gpr(), JITCompiler::addressFor(node.local()));
665             noResult(m_compileIndex);
666         } else {
667             JSValueOperand value(this, node.child1());
668             m_jit.storePtr(value.gpr(), JITCompiler::addressFor(node.local()));
669             noResult(m_compileIndex);
670         }
671         break;
672     }
673
674     case BitAnd:
675     case BitOr:
676     case BitXor:
677         if (isInt32Constant(node.child1())) {
678             SpeculateIntegerOperand op2(this, node.child2());
679             GPRTemporary result(this, op2);
680
681             bitOp(op, valueOfInt32Constant(node.child1()), op2.gpr(), result.gpr());
682
683             integerResult(result.gpr(), m_compileIndex);
684         } else if (isInt32Constant(node.child2())) {
685             SpeculateIntegerOperand op1(this, node.child1());
686             GPRTemporary result(this, op1);
687
688             bitOp(op, valueOfInt32Constant(node.child2()), op1.gpr(), result.gpr());
689
690             integerResult(result.gpr(), m_compileIndex);
691         } else {
692             SpeculateIntegerOperand op1(this, node.child1());
693             SpeculateIntegerOperand op2(this, node.child2());
694             GPRTemporary result(this, op1, op2);
695
696             GPRReg reg1 = op1.gpr();
697             GPRReg reg2 = op2.gpr();
698             bitOp(op, reg1, reg2, result.gpr());
699
700             integerResult(result.gpr(), m_compileIndex);
701         }
702         break;
703
704     case BitRShift:
705     case BitLShift:
706     case BitURShift:
707         if (isInt32Constant(node.child2())) {
708             SpeculateIntegerOperand op1(this, node.child1());
709             GPRTemporary result(this, op1);
710
711             shiftOp(op, op1.gpr(), valueOfInt32Constant(node.child2()) & 0x1f, result.gpr());
712
713             integerResult(result.gpr(), m_compileIndex);
714         } else {
715             // Do not allow shift amount to be used as the result, MacroAssembler does not permit this.
716             SpeculateIntegerOperand op1(this, node.child1());
717             SpeculateIntegerOperand op2(this, node.child2());
718             GPRTemporary result(this, op1);
719
720             GPRReg reg1 = op1.gpr();
721             GPRReg reg2 = op2.gpr();
722             shiftOp(op, reg1, reg2, result.gpr());
723
724             integerResult(result.gpr(), m_compileIndex);
725         }
726         break;
727
728     case UInt32ToNumber: {
729         IntegerOperand op1(this, node.child1());
730         GPRTemporary result(this, op1);
731
732         // Test the operand is positive.
733         speculationCheck(m_jit.branch32(MacroAssembler::LessThan, op1.gpr(), TrustedImm32(0)));
734
735         m_jit.move(op1.gpr(), result.gpr());
736         integerResult(result.gpr(), m_compileIndex, op1.format());
737         break;
738     }
739
740     case ValueToInt32: {
741         SpeculateIntegerOperand op1(this, node.child1());
742         GPRTemporary result(this, op1);
743         m_jit.move(op1.gpr(), result.gpr());
744         integerResult(result.gpr(), m_compileIndex, op1.format());
745         break;
746     }
747
748     case ValueToNumber: {
749         if (shouldSpeculateInteger(node.child1())) {
750             SpeculateIntegerOperand op1(this, node.child1());
751             GPRTemporary result(this, op1);
752             m_jit.move(op1.gpr(), result.gpr());
753             integerResult(result.gpr(), m_compileIndex, op1.format());
754             break;
755         }
756         SpeculateDoubleOperand op1(this, node.child1());
757         FPRTemporary result(this, op1);
758         m_jit.moveDouble(op1.fpr(), result.fpr());
759         doubleResult(result.fpr(), m_compileIndex);
760         break;
761     }
762
763     case ValueAdd:
764     case ArithAdd: {
765         if (shouldSpeculateInteger(node.child1(), node.child2())) {
766             if (isInt32Constant(node.child1())) {
767                 int32_t imm1 = valueOfInt32Constant(node.child1());
768                 SpeculateIntegerOperand op2(this, node.child2());
769                 GPRTemporary result(this);
770
771                 speculationCheck(m_jit.branchAdd32(MacroAssembler::Overflow, op2.gpr(), Imm32(imm1), result.gpr()));
772
773                 integerResult(result.gpr(), m_compileIndex);
774                 break;
775             }
776                 
777             if (isInt32Constant(node.child2())) {
778                 SpeculateIntegerOperand op1(this, node.child1());
779                 int32_t imm2 = valueOfInt32Constant(node.child2());
780                 GPRTemporary result(this);
781                 
782                 speculationCheck(m_jit.branchAdd32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
783
784                 integerResult(result.gpr(), m_compileIndex);
785                 break;
786             }
787                 
788             SpeculateIntegerOperand op1(this, node.child1());
789             SpeculateIntegerOperand op2(this, node.child2());
790             GPRTemporary result(this, op1, op2);
791
792             GPRReg gpr1 = op1.gpr();
793             GPRReg gpr2 = op2.gpr();
794             GPRReg gprResult = result.gpr();
795             MacroAssembler::Jump check = m_jit.branchAdd32(MacroAssembler::Overflow, gpr1, gpr2, gprResult);
796
797             if (gpr1 == gprResult)
798                 speculationCheck(check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr2));
799             else if (gpr2 == gprResult)
800                 speculationCheck(check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr1));
801             else
802                 speculationCheck(check);
803
804             integerResult(gprResult, m_compileIndex);
805             break;
806         }
807
808         SpeculateDoubleOperand op1(this, node.child1());
809         SpeculateDoubleOperand op2(this, node.child2());
810         FPRTemporary result(this, op1, op2);
811
812         FPRReg reg1 = op1.fpr();
813         FPRReg reg2 = op2.fpr();
814         m_jit.addDouble(reg1, reg2, result.fpr());
815
816         doubleResult(result.fpr(), m_compileIndex);
817         break;
818     }
819
820     case ArithSub: {
821         if (shouldSpeculateInteger(node.child1(), node.child2())) {
822             if (isInt32Constant(node.child2())) {
823                 SpeculateIntegerOperand op1(this, node.child1());
824                 int32_t imm2 = valueOfInt32Constant(node.child2());
825                 GPRTemporary result(this);
826
827                 speculationCheck(m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
828
829                 integerResult(result.gpr(), m_compileIndex);
830                 break;
831             }
832                 
833             SpeculateIntegerOperand op1(this, node.child1());
834             SpeculateIntegerOperand op2(this, node.child2());
835             GPRTemporary result(this);
836
837             speculationCheck(m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), op2.gpr(), result.gpr()));
838
839             integerResult(result.gpr(), m_compileIndex);
840             break;
841         }
842
843         SpeculateDoubleOperand op1(this, node.child1());
844         SpeculateDoubleOperand op2(this, node.child2());
845         FPRTemporary result(this, op1);
846
847         FPRReg reg1 = op1.fpr();
848         FPRReg reg2 = op2.fpr();
849         m_jit.subDouble(reg1, reg2, result.fpr());
850
851         doubleResult(result.fpr(), m_compileIndex);
852         break;
853     }
854
855     case ArithMul: {
856         if (shouldSpeculateInteger(node.child1(), node.child2())) {
857             SpeculateIntegerOperand op1(this, node.child1());
858             SpeculateIntegerOperand op2(this, node.child2());
859             GPRTemporary result(this);
860
861             GPRReg reg1 = op1.gpr();
862             GPRReg reg2 = op2.gpr();
863             speculationCheck(m_jit.branchMul32(MacroAssembler::Overflow, reg1, reg2, result.gpr()));
864
865             MacroAssembler::Jump resultNonZero = m_jit.branchTest32(MacroAssembler::NonZero, result.gpr());
866             speculationCheck(m_jit.branch32(MacroAssembler::LessThan, reg1, TrustedImm32(0)));
867             speculationCheck(m_jit.branch32(MacroAssembler::LessThan, reg2, TrustedImm32(0)));
868             resultNonZero.link(&m_jit);
869
870             integerResult(result.gpr(), m_compileIndex);
871             break;
872         }
873
874         SpeculateDoubleOperand op1(this, node.child1());
875         SpeculateDoubleOperand op2(this, node.child2());
876         FPRTemporary result(this, op1, op2);
877
878         FPRReg reg1 = op1.fpr();
879         FPRReg reg2 = op2.fpr();
880         
881         m_jit.mulDouble(reg1, reg2, result.fpr());
882         
883         doubleResult(result.fpr(), m_compileIndex);
884         break;
885     }
886
887     case ArithDiv: {
888         SpeculateDoubleOperand op1(this, node.child1());
889         SpeculateDoubleOperand op2(this, node.child2());
890         FPRTemporary result(this, op1);
891
892         FPRReg reg1 = op1.fpr();
893         FPRReg reg2 = op2.fpr();
894         m_jit.divDouble(reg1, reg2, result.fpr());
895
896         doubleResult(result.fpr(), m_compileIndex);
897         break;
898     }
899
900     case ArithMod: {
901         SpeculateIntegerOperand op1(this, node.child1());
902         SpeculateIntegerOperand op2(this, node.child2());
903         GPRTemporary eax(this, X86Registers::eax);
904         GPRTemporary edx(this, X86Registers::edx);
905         GPRReg op1Gpr = op1.gpr();
906         GPRReg op2Gpr = op2.gpr();
907
908         speculationCheck(m_jit.branchTest32(JITCompiler::Zero, op2Gpr));
909
910         GPRReg temp2 = InvalidGPRReg;
911         if (op2Gpr == X86Registers::eax || op2Gpr == X86Registers::edx) {
912             temp2 = allocate();
913             m_jit.move(op2Gpr, temp2);
914             op2Gpr = temp2;
915         }
916
917         m_jit.move(op1Gpr, eax.gpr());
918         m_jit.assembler().cdq();
919         m_jit.assembler().idivl_r(op2Gpr);
920
921         if (temp2 != InvalidGPRReg)
922             unlock(temp2);
923
924         integerResult(edx.gpr(), m_compileIndex);
925         break;
926     }
927
928     case LogicalNot: {
929         if (isKnownBoolean(node.child1())) {
930             SpeculateBooleanOperand value(this, node.child1());
931             GPRTemporary result(this, value);
932             
933             m_jit.move(value.gpr(), result.gpr());
934             m_jit.xorPtr(TrustedImm32(true), result.gpr());
935             
936             jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
937             break;
938         }
939         
940         JSValueOperand value(this, node.child1());
941         GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add).
942
943         m_jit.move(value.gpr(), result.gpr());
944         m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), result.gpr());
945         speculationCheck(m_jit.branchTestPtr(JITCompiler::NonZero, result.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
946         m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueTrue)), result.gpr());
947
948         // If we add a DataFormatBool, we should use it here.
949         jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
950         break;
951     }
952
953     case CompareLess:
954         if (compare(node, JITCompiler::LessThan, JITCompiler::DoubleLessThan, operationCompareLess))
955             return;
956         break;
957
958     case CompareLessEq:
959         if (compare(node, JITCompiler::LessThanOrEqual, JITCompiler::DoubleLessThanOrEqual, operationCompareLessEq))
960             return;
961         break;
962
963     case CompareGreater:
964         if (compare(node, JITCompiler::GreaterThan, JITCompiler::DoubleGreaterThan, operationCompareGreater))
965             return;
966         break;
967
968     case CompareGreaterEq:
969         if (compare(node, JITCompiler::GreaterThanOrEqual, JITCompiler::DoubleGreaterThanOrEqual, operationCompareGreaterEq))
970             return;
971         break;
972
973     case CompareEq:
974         if (isNullConstant(node.child1())) {
975             if (nonSpeculativeCompareNull(node, node.child2()))
976                 return;
977             break;
978         }
979         if (isNullConstant(node.child2())) {
980             if (nonSpeculativeCompareNull(node, node.child1()))
981                 return;
982             break;
983         }
984         if (compare(node, JITCompiler::Equal, JITCompiler::DoubleEqual, operationCompareEq))
985             return;
986         break;
987
988     case CompareStrictEq:
989         if (nonSpeculativeStrictEq(node))
990             return;
991         break;
992
993     case GetByVal: {
994         NodeIndex alias = node.child3();
995         if (alias != NoNode) {
996             // FIXME: result should be able to reuse child1, child2. Should have an 'UnusedOperand' type.
997             JSValueOperand aliasedValue(this, node.child3());
998             GPRTemporary result(this, aliasedValue);
999             m_jit.move(aliasedValue.gpr(), result.gpr());
1000             jsValueResult(result.gpr(), m_compileIndex);
1001             break;
1002         }
1003
1004         SpeculateCellOperand base(this, node.child1());
1005         SpeculateStrictInt32Operand property(this, node.child2());
1006         GPRTemporary storage(this);
1007
1008         GPRReg baseReg = base.gpr();
1009         GPRReg propertyReg = property.gpr();
1010         GPRReg storageReg = storage.gpr();
1011         
1012         if (!m_compileOkay)
1013             return;
1014
1015         // Get the array storage. We haven't yet checked this is a JSArray, so this is only safe if
1016         // an access with offset JSArray::storageOffset() is valid for all JSCells!
1017         m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
1018
1019         // Check that base is an array, and that property is contained within m_vector (< m_vectorLength).
1020         // If we have predicted the base to be type array, we can skip the check.
1021         Node& baseNode = m_jit.graph()[node.child1()];
1022         if (baseNode.op != GetLocal || !isArrayPrediction(m_jit.graph().getPrediction(baseNode.local())))
1023             speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
1024         speculationCheck(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset())));
1025
1026         // FIXME: In cases where there are subsequent by_val accesses to the same base it might help to cache
1027         // the storage pointer - especially if there happens to be another register free right now. If we do so,
1028         // then we'll need to allocate a new temporary for result.
1029         GPRTemporary& result = storage;
1030         m_jit.loadPtr(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), result.gpr());
1031         speculationCheck(m_jit.branchTestPtr(MacroAssembler::Zero, result.gpr()));
1032
1033         jsValueResult(result.gpr(), m_compileIndex);
1034         break;
1035     }
1036
1037     case PutByVal: {
1038         SpeculateCellOperand base(this, node.child1());
1039         SpeculateStrictInt32Operand property(this, node.child2());
1040         JSValueOperand value(this, node.child3());
1041         GPRTemporary scratch(this);
1042
1043         // Map base, property & value into registers, allocate a scratch register.
1044         GPRReg baseReg = base.gpr();
1045         GPRReg propertyReg = property.gpr();
1046         GPRReg valueReg = value.gpr();
1047         GPRReg scratchReg = scratch.gpr();
1048         
1049         if (!m_compileOkay)
1050             return;
1051         
1052         writeBarrier(m_jit, baseReg, scratchReg, WriteBarrierForPropertyAccess);
1053
1054         // Check that base is an array, and that property is contained within m_vector (< m_vectorLength).
1055         // If we have predicted the base to be type array, we can skip the check.
1056         Node& baseNode = m_jit.graph()[node.child1()];
1057         if (baseNode.op != GetLocal || !isArrayPrediction(m_jit.graph().getPrediction(baseNode.local())))
1058             speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
1059
1060         base.use();
1061         property.use();
1062         value.use();
1063         
1064         MacroAssembler::Jump withinArrayBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset()));
1065
1066         // Code to handle put beyond array bounds.
1067         silentSpillAllRegisters(scratchReg);
1068         setupStubArguments(baseReg, propertyReg, valueReg);
1069         m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
1070         JITCompiler::Call functionCall = appendCallWithExceptionCheck(operationPutByValBeyondArrayBounds);
1071         silentFillAllRegisters(scratchReg);
1072         JITCompiler::Jump wasBeyondArrayBounds = m_jit.jump();
1073
1074         withinArrayBounds.link(&m_jit);
1075
1076         // Get the array storage.
1077         GPRReg storageReg = scratchReg;
1078         m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
1079
1080         // Check if we're writing to a hole; if so increment m_numValuesInVector.
1081         MacroAssembler::Jump notHoleValue = m_jit.branchTestPtr(MacroAssembler::NonZero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
1082         m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
1083
1084         // If we're writing to a hole we might be growing the array; 
1085         MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, OBJECT_OFFSETOF(ArrayStorage, m_length)));
1086         m_jit.add32(TrustedImm32(1), propertyReg);
1087         m_jit.store32(propertyReg, MacroAssembler::Address(storageReg, OBJECT_OFFSETOF(ArrayStorage, m_length)));
1088         m_jit.sub32(TrustedImm32(1), propertyReg);
1089
1090         lengthDoesNotNeedUpdate.link(&m_jit);
1091         notHoleValue.link(&m_jit);
1092
1093         // Store the value to the array.
1094         m_jit.storePtr(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
1095
1096         wasBeyondArrayBounds.link(&m_jit);
1097
1098         noResult(m_compileIndex, UseChildrenCalledExplicitly);
1099         break;
1100     }
1101
1102     case PutByValAlias: {
1103         SpeculateCellOperand base(this, node.child1());
1104         SpeculateStrictInt32Operand property(this, node.child2());
1105         JSValueOperand value(this, node.child3());
1106         GPRTemporary scratch(this);
1107         
1108         GPRReg baseReg = base.gpr();
1109         GPRReg scratchReg = scratch.gpr();
1110
1111         writeBarrier(m_jit, baseReg, scratchReg, WriteBarrierForPropertyAccess);
1112
1113         // Get the array storage.
1114         GPRReg storageReg = scratchReg;
1115         m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
1116
1117         // Store the value to the array.
1118         GPRReg propertyReg = property.gpr();
1119         GPRReg valueReg = value.gpr();
1120         m_jit.storePtr(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
1121
1122         noResult(m_compileIndex);
1123         break;
1124     }
1125
1126     case DFG::Jump: {
1127         BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());
1128         if (taken != (m_block + 1))
1129             addBranch(m_jit.jump(), taken);
1130         noResult(m_compileIndex);
1131         break;
1132     }
1133
1134     case Branch:
1135         emitBranch(node);
1136         break;
1137
1138     case Return: {
1139         ASSERT(GPRInfo::callFrameRegister != GPRInfo::regT1);
1140         ASSERT(GPRInfo::regT1 != GPRInfo::returnValueGPR);
1141         ASSERT(GPRInfo::returnValueGPR != GPRInfo::callFrameRegister);
1142
1143 #if DFG_SUCCESS_STATS
1144         static SamplingCounter counter("SpeculativeJIT");
1145         m_jit.emitCount(counter);
1146 #endif
1147
1148         // Return the result in returnValueGPR.
1149         JSValueOperand op1(this, node.child1());
1150         m_jit.move(op1.gpr(), GPRInfo::returnValueGPR);
1151
1152         // Grab the return address.
1153         m_jit.emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, GPRInfo::regT1);
1154         // Restore our caller's "r".
1155         m_jit.emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, GPRInfo::callFrameRegister);
1156         // Return.
1157         m_jit.restoreReturnAddressBeforeReturn(GPRInfo::regT1);
1158         m_jit.ret();
1159         
1160         noResult(m_compileIndex);
1161         break;
1162     }
1163
1164     case ConvertThis: {
1165         SpeculateCellOperand thisValue(this, node.child1());
1166
1167         speculationCheck(m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(thisValue.gpr()), JITCompiler::TrustedImmPtr(m_jit.globalData()->jsStringVPtr)));
1168
1169         cellResult(thisValue.gpr(), m_compileIndex);
1170         break;
1171     }
1172
1173     case GetById: {
1174         SpeculateCellOperand base(this, node.child1());
1175         GPRTemporary result(this, base);
1176         
1177         GPRReg baseGPR = base.gpr();
1178         GPRReg resultGPR = result.gpr();
1179         GPRReg scratchGPR;
1180         
1181         if (resultGPR == baseGPR)
1182             scratchGPR = tryAllocate();
1183         else
1184             scratchGPR = resultGPR;
1185         
1186         base.use();
1187
1188         cachedGetById(baseGPR, resultGPR, scratchGPR, node.identifierNumber());
1189
1190         jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
1191         break;
1192     }
1193         
1194     case GetMethod: {
1195         SpeculateCellOperand base(this, node.child1());
1196         GPRTemporary result(this, base);
1197
1198         GPRReg baseGPR = base.gpr();
1199         GPRReg resultGPR = result.gpr();
1200         GPRReg scratchGPR;
1201         
1202         if (resultGPR == baseGPR)
1203             scratchGPR = tryAllocate();
1204         else
1205             scratchGPR = resultGPR;
1206         
1207         base.use();
1208
1209         cachedGetMethod(baseGPR, resultGPR, scratchGPR, node.identifierNumber());
1210
1211         jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
1212         break;
1213     }
1214
1215     case PutById: {
1216         SpeculateCellOperand base(this, node.child1());
1217         JSValueOperand value(this, node.child2());
1218         GPRTemporary scratch(this);
1219         
1220         GPRReg baseGPR = base.gpr();
1221         GPRReg valueGPR = value.gpr();
1222         GPRReg scratchGPR = scratch.gpr();
1223         
1224         base.use();
1225         value.use();
1226
1227         cachedPutById(baseGPR, valueGPR, scratchGPR, node.identifierNumber(), NotDirect);
1228         
1229         noResult(m_compileIndex, UseChildrenCalledExplicitly);
1230         break;
1231     }
1232
1233     case PutByIdDirect: {
1234         SpeculateCellOperand base(this, node.child1());
1235         JSValueOperand value(this, node.child2());
1236         GPRTemporary scratch(this);
1237         
1238         GPRReg baseGPR = base.gpr();
1239         GPRReg valueGPR = value.gpr();
1240         GPRReg scratchGPR = scratch.gpr();
1241         
1242         base.use();
1243         value.use();
1244
1245         cachedPutById(baseGPR, valueGPR, scratchGPR, node.identifierNumber(), Direct);
1246
1247         noResult(m_compileIndex, UseChildrenCalledExplicitly);
1248         break;
1249     }
1250
1251     case GetGlobalVar: {
1252         GPRTemporary result(this);
1253
1254         JSVariableObject* globalObject = m_jit.codeBlock()->globalObject();
1255         m_jit.loadPtr(globalObject->addressOfRegisters(), result.gpr());
1256         m_jit.loadPtr(JITCompiler::addressForGlobalVar(result.gpr(), node.varNumber()), result.gpr());
1257
1258         jsValueResult(result.gpr(), m_compileIndex);
1259         break;
1260     }
1261
1262     case PutGlobalVar: {
1263         JSValueOperand value(this, node.child1());
1264         GPRTemporary globalObject(this);
1265         GPRTemporary scratch(this);
1266         
1267         GPRReg globalObjectReg = globalObject.gpr();
1268         GPRReg scratchReg = scratch.gpr();
1269
1270         m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.codeBlock()->globalObject()), globalObjectReg);
1271
1272         writeBarrier(m_jit, globalObjectReg, scratchReg, WriteBarrierForVariableAccess);
1273
1274         m_jit.loadPtr(MacroAssembler::Address(globalObjectReg, JSVariableObject::offsetOfRegisters()), scratchReg);
1275         m_jit.storePtr(value.gpr(), JITCompiler::addressForGlobalVar(scratchReg, node.varNumber()));
1276
1277         noResult(m_compileIndex);
1278         break;
1279     }
1280
1281     case CheckHasInstance: {
1282         SpeculateCellOperand base(this, node.child1());
1283         GPRTemporary structure(this);
1284
1285         // Speculate that base 'ImplementsDefaultHasInstance'.
1286         m_jit.loadPtr(MacroAssembler::Address(base.gpr(), JSCell::structureOffset()), structure.gpr());
1287         speculationCheck(m_jit.branchTest8(MacroAssembler::Zero, MacroAssembler::Address(structure.gpr(), Structure::typeInfoFlagsOffset()), MacroAssembler::TrustedImm32(ImplementsDefaultHasInstance)));
1288
1289         noResult(m_compileIndex);
1290         break;
1291     }
1292
1293     case InstanceOf: {
1294         SpeculateCellOperand value(this, node.child1());
1295         // Base unused since we speculate default InstanceOf behaviour in CheckHasInstance.
1296         SpeculateCellOperand prototype(this, node.child3());
1297
1298         GPRTemporary scratch(this);
1299
1300         GPRReg valueReg = value.gpr();
1301         GPRReg prototypeReg = prototype.gpr();
1302         GPRReg scratchReg = scratch.gpr();
1303
1304         // Check that prototype is an object.
1305         m_jit.loadPtr(MacroAssembler::Address(prototypeReg, JSCell::structureOffset()), scratchReg);
1306         speculationCheck(m_jit.branchIfNotObject(scratchReg));
1307
1308         // Initialize scratchReg with the value being checked.
1309         m_jit.move(valueReg, scratchReg);
1310
1311         // Walk up the prototype chain of the value (in scratchReg), comparing to prototypeReg.
1312         MacroAssembler::Label loop(&m_jit);
1313         m_jit.loadPtr(MacroAssembler::Address(scratchReg, JSCell::structureOffset()), scratchReg);
1314         m_jit.loadPtr(MacroAssembler::Address(scratchReg, Structure::prototypeOffset()), scratchReg);
1315         MacroAssembler::Jump isInstance = m_jit.branchPtr(MacroAssembler::Equal, scratchReg, prototypeReg);
1316         m_jit.branchTestPtr(MacroAssembler::Zero, scratchReg, GPRInfo::tagMaskRegister).linkTo(loop, &m_jit);
1317
1318         // No match - result is false.
1319         m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(false))), scratchReg);
1320         MacroAssembler::Jump putResult = m_jit.jump();
1321
1322         isInstance.link(&m_jit);
1323         m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(true))), scratchReg);
1324
1325         putResult.link(&m_jit);
1326         jsValueResult(scratchReg, m_compileIndex, DataFormatJSBoolean);
1327         break;
1328     }
1329
1330     case Phi:
1331         ASSERT_NOT_REACHED();
1332
1333     case Breakpoint:
1334 #if ENABLE(DEBUG_WITH_BREAKPOINT)
1335         m_jit.breakpoint();
1336 #else
1337         ASSERT_NOT_REACHED();
1338 #endif
1339         break;
1340         
1341     case Call:
1342     case Construct:
1343         emitCall(node);
1344         break;
1345
1346     case Resolve: {
1347         flushRegisters();
1348         GPRResult result(this);
1349         callOperation(operationResolve, result.gpr(), identifier(node.identifierNumber()));
1350         jsValueResult(result.gpr(), m_compileIndex);
1351         break;
1352     }
1353
1354     case ResolveBase: {
1355         flushRegisters();
1356         GPRResult result(this);
1357         callOperation(operationResolveBase, result.gpr(), identifier(node.identifierNumber()));
1358         jsValueResult(result.gpr(), m_compileIndex);
1359         break;
1360     }
1361
1362     case ResolveBaseStrictPut: {
1363         flushRegisters();
1364         GPRResult result(this);
1365         callOperation(operationResolveBaseStrictPut, result.gpr(), identifier(node.identifierNumber()));
1366         jsValueResult(result.gpr(), m_compileIndex);
1367         break;
1368     }
1369     }
1370
1371     if (node.hasResult() && node.mustGenerate())
1372         use(m_compileIndex);
1373 }
1374
1375 void SpeculativeJIT::compile(BasicBlock& block)
1376 {
1377     ASSERT(m_compileIndex == block.begin);
1378     m_blockHeads[m_block] = m_jit.label();
1379 #if DFG_JIT_BREAK_ON_EVERY_BLOCK
1380     m_jit.breakpoint();
1381 #endif
1382
1383     for (; m_compileIndex < block.end; ++m_compileIndex) {
1384         Node& node = m_jit.graph()[m_compileIndex];
1385         if (!node.shouldGenerate())
1386             continue;
1387
1388 #if DFG_DEBUG_VERBOSE
1389         fprintf(stderr, "SpeculativeJIT generating Node @%d at JIT offset 0x%x   ", (int)m_compileIndex, m_jit.debugOffset());
1390 #endif
1391 #if DFG_JIT_BREAK_ON_EVERY_NODE
1392         m_jit.breakpoint();
1393 #endif
1394         checkConsistency();
1395         compile(node);
1396         if (!m_compileOkay)
1397             return;
1398 #if DFG_DEBUG_VERBOSE
1399         if (node.hasResult())
1400             fprintf(stderr, "-> %s\n", dataFormatToString(m_generationInfo[node.virtualRegister()].registerFormat()));
1401         else
1402             fprintf(stderr, "\n");
1403 #endif
1404         checkConsistency();
1405     }
1406 }
1407
1408 // If we are making type predictions about our arguments then
1409 // we need to check that they are correct on function entry.
1410 void SpeculativeJIT::checkArgumentTypes()
1411 {
1412     ASSERT(!m_compileIndex);
1413     for (int i = 0; i < m_jit.codeBlock()->m_numParameters; ++i) {
1414         VirtualRegister virtualRegister = (VirtualRegister)(m_jit.codeBlock()->thisRegister() + i);
1415         PredictedType predictedType = m_jit.graph().getPrediction(virtualRegister);
1416         if (isInt32Prediction(predictedType))
1417             speculationCheck(m_jit.branchPtr(MacroAssembler::Below, JITCompiler::addressFor(virtualRegister), GPRInfo::tagTypeNumberRegister));
1418         else if (isArrayPrediction(predictedType)) {
1419             GPRTemporary temp(this);
1420             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1421             speculationCheck(m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
1422             speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
1423         }
1424     }
1425 }
1426
1427 // For any vars that we will be treating as numeric, write 0 to
1428 // the var on entry. Throughout the block we will only read/write
1429 // to the payload, by writing the tag now we prevent the GC from
1430 // misinterpreting values as pointers.
1431 void SpeculativeJIT::initializeVariableTypes()
1432 {
1433     ASSERT(!m_compileIndex);
1434     for (int var = 0; var < (int)m_jit.graph().predictions().numberOfVariables(); ++var) {
1435         if (isInt32Prediction(m_jit.graph().getPrediction(var)))
1436             m_jit.storePtr(GPRInfo::tagTypeNumberRegister, JITCompiler::addressFor((VirtualRegister)var));
1437     }
1438 }
1439
1440 bool SpeculativeJIT::compile()
1441 {
1442     checkArgumentTypes();
1443     initializeVariableTypes();
1444
1445     ASSERT(!m_compileIndex);
1446     for (m_block = 0; m_block < m_jit.graph().m_blocks.size(); ++m_block) {
1447         compile(*m_jit.graph().m_blocks[m_block]);
1448         if (!m_compileOkay)
1449             return false;
1450     }
1451     linkBranches();
1452     return true;
1453 }
1454
1455 } } // namespace JSC::DFG
1456
1457 #endif