dc97fc561809c18d0f2d69a4a965ac97fe115839
[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         if (node.isConstant() && !isInt32Constant(nodeIndex)) {
43             terminateSpeculativeExecution();
44             returnFormat = DataFormatInteger;
45             return allocate();
46         }
47         
48         GPRReg gpr = allocate();
49
50         if (node.isConstant()) {
51             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
52             ASSERT(isInt32Constant(nodeIndex));
53             m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gpr);
54             info.fillInteger(gpr);
55             returnFormat = DataFormatInteger;
56             return gpr;
57         } else {
58             DataFormat spillFormat = info.spillFormat();
59             ASSERT(spillFormat & DataFormatJS);
60
61             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
62
63             if (spillFormat == DataFormatJSInteger) {
64                 // If we know this was spilled as an integer we can fill without checking.
65                 if (strict) {
66                     m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
67                     info.fillInteger(gpr);
68                     returnFormat = DataFormatInteger;
69                     return gpr;
70                 }
71                 m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
72                 info.fillJSValue(gpr, DataFormatJSInteger);
73                 returnFormat = DataFormatJSInteger;
74                 return gpr;
75             }
76             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
77         }
78
79         // Fill as JSValue, and fall through.
80         info.fillJSValue(gpr, DataFormatJSInteger);
81         m_gprs.unlock(gpr);
82     }
83
84     case DataFormatJS: {
85         // Check the value is an integer.
86         GPRReg gpr = info.gpr();
87         m_gprs.lock(gpr);
88         speculationCheck(m_jit.branchPtr(MacroAssembler::Below, gpr, GPRInfo::tagTypeNumberRegister));
89         info.fillJSValue(gpr, DataFormatJSInteger);
90         // If !strict we're done, return.
91         if (!strict) {
92             returnFormat = DataFormatJSInteger;
93             return gpr;
94         }
95         // else fall through & handle as DataFormatJSInteger.
96         m_gprs.unlock(gpr);
97     }
98
99     case DataFormatJSInteger: {
100         // In a strict fill we need to strip off the value tag.
101         if (strict) {
102             GPRReg gpr = info.gpr();
103             GPRReg result;
104             // If the register has already been locked we need to take a copy.
105             // If not, we'll zero extend in place, so mark on the info that this is now type DataFormatInteger, not DataFormatJSInteger.
106             if (m_gprs.isLocked(gpr))
107                 result = allocate();
108             else {
109                 m_gprs.lock(gpr);
110                 info.fillInteger(gpr);
111                 result = gpr;
112             }
113             m_jit.zeroExtend32ToPtr(gpr, result);
114             returnFormat = DataFormatInteger;
115             return result;
116         }
117
118         GPRReg gpr = info.gpr();
119         m_gprs.lock(gpr);
120         returnFormat = DataFormatJSInteger;
121         return gpr;
122     }
123
124     case DataFormatInteger: {
125         GPRReg gpr = info.gpr();
126         m_gprs.lock(gpr);
127         returnFormat = DataFormatInteger;
128         return gpr;
129     }
130
131     case DataFormatDouble:
132     case DataFormatCell:
133     case DataFormatBoolean:
134     case DataFormatJSDouble:
135     case DataFormatJSCell:
136     case DataFormatJSBoolean: {
137         terminateSpeculativeExecution();
138         returnFormat = DataFormatInteger;
139         return allocate();
140     }
141     }
142
143     ASSERT_NOT_REACHED();
144     return InvalidGPRReg;
145 }
146
147 #if !ENABLE(DFG_OSR_EXIT)
148 SpeculationCheck::SpeculationCheck(MacroAssembler::Jump check, SpeculativeJIT* jit, unsigned recoveryIndex)
149     : m_check(check)
150     , m_nodeIndex(jit->m_compileIndex)
151     , m_recoveryIndex(recoveryIndex)
152 {
153     for (gpr_iterator iter = jit->m_gprs.begin(); iter != jit->m_gprs.end(); ++iter) {
154         if (iter.name() != InvalidVirtualRegister) {
155             GenerationInfo& info =  jit->m_generationInfo[iter.name()];
156             m_gprInfo[iter.index()].nodeIndex = info.nodeIndex();
157             m_gprInfo[iter.index()].format = info.registerFormat();
158             ASSERT(m_gprInfo[iter.index()].format != DataFormatNone);
159             m_gprInfo[iter.index()].isSpilled = info.spillFormat() != DataFormatNone;
160         } else
161             m_gprInfo[iter.index()].nodeIndex = NoNode;
162     }
163     for (fpr_iterator iter = jit->m_fprs.begin(); iter != jit->m_fprs.end(); ++iter) {
164         if (iter.name() != InvalidVirtualRegister) {
165             GenerationInfo& info =  jit->m_generationInfo[iter.name()];
166             ASSERT(info.registerFormat() == DataFormatDouble);
167             m_fprInfo[iter.index()].nodeIndex = info.nodeIndex();
168             m_fprInfo[iter.index()].format = DataFormatDouble;
169             m_fprInfo[iter.index()].isSpilled = info.spillFormat() != DataFormatNone;
170         } else
171             m_fprInfo[iter.index()].nodeIndex = NoNode;
172     }
173 }
174 #endif
175
176 #ifndef NDEBUG
177 void ValueSource::dump(FILE* out) const
178 {
179     fprintf(out, "Node(%d)", m_nodeIndex);
180 }
181
182 void ValueRecovery::dump(FILE* out) const
183 {
184     switch (technique()) {
185     case AlreadyInRegisterFile:
186         fprintf(out, "-");
187         break;
188     case InGPR:
189         fprintf(out, "%%%s", GPRInfo::debugName(gpr()));
190         break;
191     case UnboxedInt32InGPR:
192         fprintf(out, "int32(%%%s)", GPRInfo::debugName(gpr()));
193         break;
194     case InFPR:
195         fprintf(out, "%%%s", FPRInfo::debugName(fpr()));
196         break;
197     case DisplacedInRegisterFile:
198         fprintf(out, "*%d", virtualRegister());
199         break;
200     case Constant:
201         fprintf(out, "[%s]", constant().description());
202         break;
203     case DontKnow:
204         fprintf(out, "!");
205         break;
206     default:
207         fprintf(out, "?%d", technique());
208         break;
209     }
210 }
211 #endif
212
213 #if ENABLE(DFG_OSR_EXIT)
214 OSRExit::OSRExit(MacroAssembler::Jump check, SpeculativeJIT* jit, unsigned recoveryIndex)
215     : m_check(check)
216     , m_nodeIndex(jit->m_compileIndex)
217     , m_bytecodeIndex(jit->m_bytecodeIndexForOSR)
218     , m_recoveryIndex(recoveryIndex)
219     , m_arguments(jit->m_arguments.size())
220     , m_variables(jit->m_variables.size())
221     , m_lastSetOperand(jit->m_lastSetOperand)
222 {
223     ASSERT(m_bytecodeIndex != std::numeric_limits<uint32_t>::max());
224     for (unsigned argument = 0; argument < m_arguments.size(); ++argument)
225         m_arguments[argument] = jit->computeValueRecoveryFor(jit->m_arguments[argument]);
226     for (unsigned variable = 0; variable < m_variables.size(); ++variable)
227         m_variables[variable] = jit->computeValueRecoveryFor(jit->m_variables[variable]);
228 }
229
230 #ifndef NDEBUG
231 void OSRExit::dump(FILE* out) const
232 {
233     for (unsigned argument = 0; argument < m_arguments.size(); ++argument)
234         m_arguments[argument].dump(out);
235     fprintf(out, " : ");
236     for (unsigned variable = 0; variable < m_variables.size(); ++variable)
237         m_variables[variable].dump(out);
238 }
239 #endif
240 #endif
241
242 GPRReg SpeculativeJIT::fillSpeculateInt(NodeIndex nodeIndex, DataFormat& returnFormat)
243 {
244     return fillSpeculateIntInternal<false>(nodeIndex, returnFormat);
245 }
246
247 GPRReg SpeculativeJIT::fillSpeculateIntStrict(NodeIndex nodeIndex)
248 {
249     DataFormat mustBeDataFormatInteger;
250     GPRReg result = fillSpeculateIntInternal<true>(nodeIndex, mustBeDataFormatInteger);
251     ASSERT(mustBeDataFormatInteger == DataFormatInteger);
252     return result;
253 }
254
255 FPRReg SpeculativeJIT::fillSpeculateDouble(NodeIndex nodeIndex)
256 {
257     Node& node = m_jit.graph()[nodeIndex];
258     VirtualRegister virtualRegister = node.virtualRegister();
259     GenerationInfo& info = m_generationInfo[virtualRegister];
260
261     if (info.registerFormat() == DataFormatNone) {
262         GPRReg gpr = allocate();
263
264         if (node.isConstant()) {
265             if (isInt32Constant(nodeIndex)) {
266                 FPRReg fpr = fprAllocate();
267                 m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(static_cast<double>(valueOfInt32Constant(nodeIndex))))), gpr);
268                 m_jit.movePtrToDouble(gpr, fpr);
269                 unlock(gpr);
270
271                 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
272                 info.fillDouble(fpr);
273                 return fpr;
274             }
275             if (isNumberConstant(nodeIndex)) {
276                 FPRReg fpr = fprAllocate();
277                 m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(valueOfNumberConstant(nodeIndex)))), gpr);
278                 m_jit.movePtrToDouble(gpr, fpr);
279                 unlock(gpr);
280
281                 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
282                 info.fillDouble(fpr);
283                 return fpr;
284             }
285             terminateSpeculativeExecution();
286             return fprAllocate();
287         } else {
288             DataFormat spillFormat = info.spillFormat();
289             ASSERT(spillFormat & DataFormatJS);
290             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
291             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
292             info.fillJSValue(gpr, spillFormat);
293             unlock(gpr);
294         }
295     }
296
297     switch (info.registerFormat()) {
298     case DataFormatNone: // Should have filled, above.
299     case DataFormatBoolean: // This type never occurs.
300         ASSERT_NOT_REACHED();
301         
302     case DataFormatCell:
303     case DataFormatJSCell:
304     case DataFormatJS:
305     case DataFormatJSBoolean: {
306         GPRReg jsValueGpr = info.gpr();
307         m_gprs.lock(jsValueGpr);
308         FPRReg fpr = fprAllocate();
309         GPRReg tempGpr = allocate();
310
311         JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
312
313         speculationCheck(m_jit.branchTestPtr(MacroAssembler::Zero, jsValueGpr, GPRInfo::tagTypeNumberRegister));
314
315         // First, if we get here we have a double encoded as a JSValue
316         m_jit.move(jsValueGpr, tempGpr);
317         unboxDouble(tempGpr, fpr);
318         JITCompiler::Jump hasUnboxedDouble = m_jit.jump();
319
320         // Finally, handle integers.
321         isInteger.link(&m_jit);
322         m_jit.convertInt32ToDouble(jsValueGpr, fpr);
323         hasUnboxedDouble.link(&m_jit);
324
325         m_gprs.release(jsValueGpr);
326         m_gprs.unlock(jsValueGpr);
327         m_gprs.unlock(tempGpr);
328         m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
329         info.fillDouble(fpr);
330         info.killSpilled();
331         return fpr;
332     }
333
334     case DataFormatJSInteger:
335     case DataFormatInteger: {
336         FPRReg fpr = fprAllocate();
337         GPRReg gpr = info.gpr();
338         m_gprs.lock(gpr);
339         m_jit.convertInt32ToDouble(gpr, fpr);
340         m_gprs.unlock(gpr);
341         return fpr;
342     }
343
344     // Unbox the double
345     case DataFormatJSDouble: {
346         GPRReg gpr = info.gpr();
347         FPRReg fpr = fprAllocate();
348         if (m_gprs.isLocked(gpr)) {
349             // Make sure we don't trample gpr if it is in use.
350             GPRReg temp = allocate();
351             m_jit.move(gpr, temp);
352             unboxDouble(temp, fpr);
353             unlock(temp);
354         } else
355             unboxDouble(gpr, fpr);
356
357         m_gprs.release(gpr);
358         m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
359
360         info.fillDouble(fpr);
361         return fpr;
362     }
363
364     case DataFormatDouble: {
365         FPRReg fpr = info.fpr();
366         m_fprs.lock(fpr);
367         return fpr;
368     }
369     }
370
371     ASSERT_NOT_REACHED();
372     return InvalidFPRReg;
373 }
374
375 GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex)
376 {
377     Node& node = m_jit.graph()[nodeIndex];
378     VirtualRegister virtualRegister = node.virtualRegister();
379     GenerationInfo& info = m_generationInfo[virtualRegister];
380
381     switch (info.registerFormat()) {
382     case DataFormatNone: {
383         GPRReg gpr = allocate();
384
385         if (node.isConstant()) {
386             JSValue jsValue = valueOfJSConstant(nodeIndex);
387             if (jsValue.isCell()) {
388                 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
389                 m_jit.move(MacroAssembler::TrustedImmPtr(jsValue.asCell()), gpr);
390                 info.fillJSValue(gpr, DataFormatJSCell);
391                 return gpr;
392             }
393             terminateSpeculativeExecution();
394             return gpr;
395         }
396         ASSERT(info.spillFormat() & DataFormatJS);
397         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
398         m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
399
400         info.fillJSValue(gpr, DataFormatJS);
401         if (info.spillFormat() != DataFormatJSCell)
402             speculationCheck(m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister));
403         info.fillJSValue(gpr, DataFormatJSCell);
404         return gpr;
405     }
406
407     case DataFormatCell:
408     case DataFormatJSCell: {
409         GPRReg gpr = info.gpr();
410         m_gprs.lock(gpr);
411         return gpr;
412     }
413
414     case DataFormatJS: {
415         GPRReg gpr = info.gpr();
416         m_gprs.lock(gpr);
417         speculationCheck(m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister));
418         info.fillJSValue(gpr, DataFormatJSCell);
419         return gpr;
420     }
421
422     case DataFormatJSInteger:
423     case DataFormatInteger:
424     case DataFormatJSDouble:
425     case DataFormatDouble:
426     case DataFormatJSBoolean:
427     case DataFormatBoolean: {
428         terminateSpeculativeExecution();
429         return allocate();
430     }
431     }
432
433     ASSERT_NOT_REACHED();
434     return InvalidGPRReg;
435 }
436
437 GPRReg SpeculativeJIT::fillSpeculateBoolean(NodeIndex nodeIndex)
438 {
439     Node& node = m_jit.graph()[nodeIndex];
440     VirtualRegister virtualRegister = node.virtualRegister();
441     GenerationInfo& info = m_generationInfo[virtualRegister];
442
443     switch (info.registerFormat()) {
444     case DataFormatNone: {
445         GPRReg gpr = allocate();
446
447         if (node.isConstant()) {
448             JSValue jsValue = valueOfJSConstant(nodeIndex);
449             if (jsValue.isBoolean()) {
450                 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
451                 m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsValue)), gpr);
452                 info.fillJSValue(gpr, DataFormatJSBoolean);
453                 return gpr;
454             }
455             terminateSpeculativeExecution();
456             return gpr;
457         }
458         ASSERT(info.spillFormat() & DataFormatJS);
459         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
460         m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
461
462         info.fillJSValue(gpr, DataFormatJS);
463         if (info.spillFormat() != DataFormatJSBoolean) {
464             m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
465             speculationCheck(m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg));
466             m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
467         }
468         info.fillJSValue(gpr, DataFormatJSBoolean);
469         return gpr;
470     }
471
472     case DataFormatBoolean:
473     case DataFormatJSBoolean: {
474         GPRReg gpr = info.gpr();
475         m_gprs.lock(gpr);
476         return gpr;
477     }
478
479     case DataFormatJS: {
480         GPRReg gpr = info.gpr();
481         m_gprs.lock(gpr);
482         m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
483         speculationCheck(m_jit.branchTestPtr(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg));
484         m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
485         info.fillJSValue(gpr, DataFormatJSBoolean);
486         return gpr;
487     }
488
489     case DataFormatJSInteger:
490     case DataFormatInteger:
491     case DataFormatJSDouble:
492     case DataFormatDouble:
493     case DataFormatJSCell:
494     case DataFormatCell: {
495         terminateSpeculativeExecution();
496         return allocate();
497     }
498     }
499
500     ASSERT_NOT_REACHED();
501     return InvalidGPRReg;
502 }
503
504 void SpeculativeJIT::compilePeepHoleIntegerBranch(Node& node, NodeIndex branchNodeIndex, JITCompiler::RelationalCondition condition)
505 {
506     Node& branchNode = m_jit.graph()[branchNodeIndex];
507     BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
508     BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
509
510     // The branch instruction will branch to the taken block.
511     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
512     if (taken == (m_block + 1)) {
513         condition = JITCompiler::invert(condition);
514         BlockIndex tmp = taken;
515         taken = notTaken;
516         notTaken = tmp;
517     }
518
519     if (isInt32Constant(node.child1())) {
520         int32_t imm = valueOfInt32Constant(node.child1());
521         SpeculateIntegerOperand op2(this, node.child2());
522         addBranch(m_jit.branch32(condition, JITCompiler::Imm32(imm), op2.gpr()), taken);
523     } else if (isInt32Constant(node.child2())) {
524         SpeculateIntegerOperand op1(this, node.child1());
525         int32_t imm = valueOfInt32Constant(node.child2());
526         addBranch(m_jit.branch32(condition, op1.gpr(), JITCompiler::Imm32(imm)), taken);
527     } else {
528         SpeculateIntegerOperand op1(this, node.child1());
529         SpeculateIntegerOperand op2(this, node.child2());
530         addBranch(m_jit.branch32(condition, op1.gpr(), op2.gpr()), taken);
531     }
532
533     // Check for fall through, otherwise we need to jump.
534     if (notTaken != (m_block + 1))
535         addBranch(m_jit.jump(), notTaken);
536 }
537
538 JITCompiler::Jump SpeculativeJIT::convertToDouble(GPRReg value, FPRReg result, GPRReg tmp)
539 {
540     JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, value, GPRInfo::tagTypeNumberRegister);
541     
542     JITCompiler::Jump notNumber = m_jit.branchTestPtr(MacroAssembler::Zero, value, GPRInfo::tagTypeNumberRegister);
543     
544     m_jit.move(value, tmp);
545     unboxDouble(tmp, result);
546     
547     JITCompiler::Jump done = m_jit.jump();
548     
549     isInteger.link(&m_jit);
550     
551     m_jit.convertInt32ToDouble(value, result);
552     
553     done.link(&m_jit);
554
555     return notNumber;
556 }
557
558 void SpeculativeJIT::compilePeepHoleDoubleBranch(Node& node, NodeIndex branchNodeIndex, JITCompiler::DoubleCondition condition, Z_DFGOperation_EJJ operation)
559 {
560     Node& branchNode = m_jit.graph()[branchNodeIndex];
561     BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
562     BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
563     
564     bool op1Numeric = isKnownNumeric(node.child1());
565     bool op2Numeric = isKnownNumeric(node.child2());
566     
567     if (op1Numeric && op2Numeric) {
568         SpeculateDoubleOperand op1(this, node.child1());
569         SpeculateDoubleOperand op2(this, node.child2());
570         
571         addBranch(m_jit.branchDouble(condition, op1.fpr(), op2.fpr()), taken);
572     } else if (op1Numeric) {
573         SpeculateDoubleOperand op1(this, node.child1());
574         JSValueOperand op2(this, node.child2());
575         
576         FPRTemporary fprTmp(this);
577         GPRTemporary gprTmp(this);
578         
579         FPRReg op1FPR = op1.fpr();
580         GPRReg op2GPR = op2.gpr();
581         FPRReg op2FPR = fprTmp.fpr();
582         GPRReg gpr = gprTmp.gpr();
583         
584         JITCompiler::Jump slowPath = convertToDouble(op2GPR, op2FPR, gpr);
585         
586         addBranch(m_jit.branchDouble(condition, op1FPR, op2FPR), taken);
587         addBranch(m_jit.jump(), notTaken);
588         
589         slowPath.link(&m_jit);
590         
591         boxDouble(op1FPR, gpr);
592         
593         silentSpillAllRegisters(gpr);
594         setupStubArguments(gpr, op2GPR);
595         m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
596         appendCallWithExceptionCheck(operation);
597         m_jit.move(GPRInfo::returnValueGPR, gpr);
598         silentFillAllRegisters(gpr);
599         
600         addBranch(m_jit.branchTest8(JITCompiler::NonZero, gpr), taken);
601     } else {
602         JSValueOperand op1(this, node.child1());
603         SpeculateDoubleOperand op2(this, node.child2());
604         
605         FPRTemporary fprTmp(this);
606         GPRTemporary gprTmp(this);
607         
608         FPRReg op2FPR = op2.fpr();
609         GPRReg op1GPR = op1.gpr();
610         FPRReg op1FPR = fprTmp.fpr();
611         GPRReg gpr = gprTmp.gpr();
612         
613         JITCompiler::Jump slowPath = convertToDouble(op1GPR, op1FPR, gpr);
614         
615         addBranch(m_jit.branchDouble(condition, op1FPR, op2FPR), taken);
616         addBranch(m_jit.jump(), notTaken);
617         
618         slowPath.link(&m_jit);
619         
620         boxDouble(op2FPR, gpr);
621         
622         silentSpillAllRegisters(gpr);
623         setupStubArguments(op1GPR, gpr);
624         m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
625         appendCallWithExceptionCheck(operation);
626         m_jit.move(GPRInfo::returnValueGPR, gpr);
627         silentFillAllRegisters(gpr);
628         
629         addBranch(m_jit.branchTest8(JITCompiler::NonZero, gpr), taken);
630     }
631     
632     if (notTaken != (m_block + 1))
633         addBranch(m_jit.jump(), notTaken);
634 }
635
636 // Returns true if the compare is fused with a subsequent branch.
637 bool SpeculativeJIT::compare(Node& node, MacroAssembler::RelationalCondition condition, MacroAssembler::DoubleCondition doubleCondition, Z_DFGOperation_EJJ operation)
638 {
639     // Fused compare & branch.
640     NodeIndex branchNodeIndex = detectPeepHoleBranch();
641     if (branchNodeIndex != NoNode) {
642         // detectPeepHoleBranch currently only permits the branch to be the very next node,
643         // so can be no intervening nodes to also reference the compare. 
644         ASSERT(node.adjustedRefCount() == 1);
645
646         if (shouldSpeculateInteger(node.child1(), node.child2())) {
647             compilePeepHoleIntegerBranch(node, branchNodeIndex, condition);
648             use(node.child1());
649             use(node.child2());
650         } else if (isKnownNumeric(node.child1()) || isKnownNumeric(node.child2())) {
651             compilePeepHoleDoubleBranch(node, branchNodeIndex, doubleCondition, operation);
652             use(node.child1());
653             use(node.child2());
654         } else
655             nonSpeculativePeepholeBranch(node, branchNodeIndex, condition, operation);
656
657         m_compileIndex = branchNodeIndex;
658         return true;
659     }
660
661     if (isKnownNotInteger(node.child1()) || isKnownNotInteger(node.child2()))
662         nonSpeculativeNonPeepholeCompare(node, condition, operation);
663     else {
664         // Normal case, not fused to branch.
665         SpeculateIntegerOperand op1(this, node.child1());
666         SpeculateIntegerOperand op2(this, node.child2());
667         GPRTemporary result(this, op1, op2);
668         
669         m_jit.compare32(condition, op1.gpr(), op2.gpr(), result.gpr());
670         
671         // If we add a DataFormatBool, we should use it here.
672         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
673         jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
674     }
675     
676     return false;
677 }
678
679 void SpeculativeJIT::compile(Node& node)
680 {
681     NodeType op = node.op;
682
683     switch (op) {
684     case JSConstant:
685         initConstantInfo(m_compileIndex);
686         break;
687
688     case GetLocal: {
689         GPRTemporary result(this);
690         PredictedType prediction = m_jit.graph().getPrediction(node.local());
691         if (isInt32Prediction(prediction)) {
692             m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr());
693
694             // Like integerResult, but don't useChildren - our children are phi nodes,
695             // and don't represent values within this dataflow with virtual registers.
696             VirtualRegister virtualRegister = node.virtualRegister();
697             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderInteger);
698             m_generationInfo[virtualRegister].initInteger(m_compileIndex, node.refCount(), result.gpr());
699         } else {
700             m_jit.loadPtr(JITCompiler::addressFor(node.local()), result.gpr());
701
702             // Like jsValueResult, but don't useChildren - our children are phi nodes,
703             // and don't represent values within this dataflow with virtual registers.
704             VirtualRegister virtualRegister = node.virtualRegister();
705             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
706             
707             DataFormat format;
708             if (isArrayPrediction(prediction))
709                 format = DataFormatJSCell;
710             else if (isBooleanPrediction(prediction))
711                 format = DataFormatJSBoolean;
712             else
713                 format = DataFormatJS;
714             
715             m_generationInfo[virtualRegister].initJSValue(m_compileIndex, node.refCount(), result.gpr(), format);
716         }
717         break;
718     }
719
720     case SetLocal: {
721         // SetLocal doubles as a hint as to where a node will be stored and
722         // as a speculation point. So before we speculate make sure that we
723         // know where the child of this node needs to go in the virtual
724         // register file.
725         compileMovHint(node);
726         
727         // As far as OSR is concerned, we're on the bytecode index corresponding
728         // to the *next* instruction, since we've already "executed" the
729         // SetLocal and whatever other DFG Nodes are associated with the same
730         // bytecode index as the SetLocal.
731         ASSERT(m_bytecodeIndexForOSR == node.codeOrigin.bytecodeIndex());
732         Node& nextNode = m_jit.graph()[m_compileIndex+1];
733         
734         // This assertion will fail if we ever emit multiple SetLocal's for
735         // a single bytecode instruction. That's unlikely to happen. But if
736         // it does, the solution is to to have this perform a search until
737         // it finds a Node with a different bytecode index from the one we've
738         // got, and to abstractly execute the SetLocal's along the way. Or,
739         // better yet, handle all of the SetLocal's at once: abstract interpret
740         // all of them, then emit code for all of them, with OSR exiting to
741         // the next non-SetLocal instruction. Note the special case for when
742         // both this SetLocal and the next op have a bytecode index of 0; this
743         // occurs for SetLocal's generated at the top of the code block to
744         // initialize locals to undefined. Ideally, we'd have a way of marking
745         // in the CodeOrigin that a SetLocal is synthetic. This will make the
746         // assertion more sensible-looking. We should then also assert that
747         // synthetic SetLocal's don't have speculation checks, since they
748         // should only be dropping values that we statically know we are
749         // allowed to drop into the variables. DFGPropagator will guarantee
750         // this, since it should have at least an approximation (if not
751         // exact knowledge) of the type of the SetLocal's child node, and
752         // should merge that information into the local that is being set.
753         ASSERT(m_bytecodeIndexForOSR != nextNode.codeOrigin.bytecodeIndex()
754                || (!m_bytecodeIndexForOSR && !nextNode.codeOrigin.bytecodeIndex()));
755         m_bytecodeIndexForOSR = nextNode.codeOrigin.bytecodeIndex();
756         
757         PredictedType predictedType = m_jit.graph().getPrediction(node.local());
758         if (isInt32Prediction(predictedType)) {
759             SpeculateIntegerOperand value(this, node.child1());
760             m_jit.store32(value.gpr(), JITCompiler::payloadFor(node.local()));
761             noResult(m_compileIndex);
762         } else if (isArrayPrediction(predictedType)) {
763             SpeculateCellOperand cell(this, node.child1());
764             GPRReg cellGPR = cell.gpr();
765             speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
766             m_jit.storePtr(cellGPR, JITCompiler::addressFor(node.local()));
767             noResult(m_compileIndex);
768         } else if (isBooleanPrediction(predictedType)) {
769             SpeculateBooleanOperand boolean(this, node.child1());
770             m_jit.storePtr(boolean.gpr(), JITCompiler::addressFor(node.local()));
771             noResult(m_compileIndex);
772         } else {
773             JSValueOperand value(this, node.child1());
774             m_jit.storePtr(value.gpr(), JITCompiler::addressFor(node.local()));
775             noResult(m_compileIndex);
776         }
777         
778         // Indicate that it's no longer necessary to retrieve the value of
779         // this bytecode variable from registers or other locations in the register file.
780         valueSourceReferenceForOperand(node.local()) = ValueSource();
781         break;
782     }
783
784     case BitAnd:
785     case BitOr:
786     case BitXor:
787         if (isInt32Constant(node.child1())) {
788             SpeculateIntegerOperand op2(this, node.child2());
789             GPRTemporary result(this, op2);
790
791             bitOp(op, valueOfInt32Constant(node.child1()), op2.gpr(), result.gpr());
792
793             integerResult(result.gpr(), m_compileIndex);
794         } else if (isInt32Constant(node.child2())) {
795             SpeculateIntegerOperand op1(this, node.child1());
796             GPRTemporary result(this, op1);
797
798             bitOp(op, valueOfInt32Constant(node.child2()), op1.gpr(), result.gpr());
799
800             integerResult(result.gpr(), m_compileIndex);
801         } else {
802             SpeculateIntegerOperand op1(this, node.child1());
803             SpeculateIntegerOperand op2(this, node.child2());
804             GPRTemporary result(this, op1, op2);
805
806             GPRReg reg1 = op1.gpr();
807             GPRReg reg2 = op2.gpr();
808             bitOp(op, reg1, reg2, result.gpr());
809
810             integerResult(result.gpr(), m_compileIndex);
811         }
812         break;
813
814     case BitRShift:
815     case BitLShift:
816     case BitURShift:
817         if (isInt32Constant(node.child2())) {
818             SpeculateIntegerOperand op1(this, node.child1());
819             GPRTemporary result(this, op1);
820
821             shiftOp(op, op1.gpr(), valueOfInt32Constant(node.child2()) & 0x1f, result.gpr());
822
823             integerResult(result.gpr(), m_compileIndex);
824         } else {
825             // Do not allow shift amount to be used as the result, MacroAssembler does not permit this.
826             SpeculateIntegerOperand op1(this, node.child1());
827             SpeculateIntegerOperand op2(this, node.child2());
828             GPRTemporary result(this, op1);
829
830             GPRReg reg1 = op1.gpr();
831             GPRReg reg2 = op2.gpr();
832             shiftOp(op, reg1, reg2, result.gpr());
833
834             integerResult(result.gpr(), m_compileIndex);
835         }
836         break;
837
838     case UInt32ToNumber: {
839         IntegerOperand op1(this, node.child1());
840         GPRTemporary result(this, op1);
841
842         // Test the operand is positive.
843         speculationCheck(m_jit.branch32(MacroAssembler::LessThan, op1.gpr(), TrustedImm32(0)));
844
845         m_jit.move(op1.gpr(), result.gpr());
846         integerResult(result.gpr(), m_compileIndex, op1.format());
847         break;
848     }
849
850     case ValueToInt32: {
851         SpeculateIntegerOperand op1(this, node.child1());
852         GPRTemporary result(this, op1);
853         m_jit.move(op1.gpr(), result.gpr());
854         integerResult(result.gpr(), m_compileIndex, op1.format());
855         break;
856     }
857
858     case ValueToNumber: {
859         if (shouldSpeculateInteger(node.child1())) {
860             SpeculateIntegerOperand op1(this, node.child1());
861             GPRTemporary result(this, op1);
862             m_jit.move(op1.gpr(), result.gpr());
863             integerResult(result.gpr(), m_compileIndex, op1.format());
864             break;
865         }
866         SpeculateDoubleOperand op1(this, node.child1());
867         FPRTemporary result(this, op1);
868         m_jit.moveDouble(op1.fpr(), result.fpr());
869         doubleResult(result.fpr(), m_compileIndex);
870         break;
871     }
872
873     case ValueToDouble: {
874         SpeculateDoubleOperand op1(this, node.child1());
875         FPRTemporary result(this, op1);
876         m_jit.moveDouble(op1.fpr(), result.fpr());
877         doubleResult(result.fpr(), m_compileIndex);
878         break;
879     }
880
881     case ValueAdd:
882     case ArithAdd: {
883         if (shouldSpeculateInteger(node.child1(), node.child2())) {
884             if (isInt32Constant(node.child1())) {
885                 int32_t imm1 = valueOfInt32Constant(node.child1());
886                 SpeculateIntegerOperand op2(this, node.child2());
887                 GPRTemporary result(this);
888
889                 speculationCheck(m_jit.branchAdd32(MacroAssembler::Overflow, op2.gpr(), Imm32(imm1), result.gpr()));
890
891                 integerResult(result.gpr(), m_compileIndex);
892                 break;
893             }
894                 
895             if (isInt32Constant(node.child2())) {
896                 SpeculateIntegerOperand op1(this, node.child1());
897                 int32_t imm2 = valueOfInt32Constant(node.child2());
898                 GPRTemporary result(this);
899                 
900                 speculationCheck(m_jit.branchAdd32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
901
902                 integerResult(result.gpr(), m_compileIndex);
903                 break;
904             }
905                 
906             SpeculateIntegerOperand op1(this, node.child1());
907             SpeculateIntegerOperand op2(this, node.child2());
908             GPRTemporary result(this, op1, op2);
909
910             GPRReg gpr1 = op1.gpr();
911             GPRReg gpr2 = op2.gpr();
912             GPRReg gprResult = result.gpr();
913             MacroAssembler::Jump check = m_jit.branchAdd32(MacroAssembler::Overflow, gpr1, gpr2, gprResult);
914
915             if (gpr1 == gprResult)
916                 speculationCheck(check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr2));
917             else if (gpr2 == gprResult)
918                 speculationCheck(check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr1));
919             else
920                 speculationCheck(check);
921
922             integerResult(gprResult, m_compileIndex);
923             break;
924         }
925
926         if (shouldSpeculateNumber(node.child1(), node.child2())) {
927             SpeculateDoubleOperand op1(this, node.child1());
928             SpeculateDoubleOperand op2(this, node.child2());
929             FPRTemporary result(this, op1, op2);
930             
931             FPRReg reg1 = op1.fpr();
932             FPRReg reg2 = op2.fpr();
933             m_jit.addDouble(reg1, reg2, result.fpr());
934             
935             doubleResult(result.fpr(), m_compileIndex);
936             break;
937         }
938         
939         ASSERT(op == ValueAdd);
940         
941         JSValueOperand op1(this, node.child1());
942         JSValueOperand op2(this, node.child2());
943         
944         GPRReg op1GPR = op1.gpr();
945         GPRReg op2GPR = op2.gpr();
946         
947         flushRegisters();
948         
949         GPRResult result(this);
950         if (isKnownNotNumber(node.child1()) || isKnownNotNumber(node.child2()))
951             callOperation(operationValueAddNotNumber, result.gpr(), op1GPR, op2GPR);
952         else
953             callOperation(operationValueAdd, result.gpr(), op1GPR, op2GPR);
954         
955         jsValueResult(result.gpr(), m_compileIndex);
956         break;
957     }
958
959     case ArithSub: {
960         if (shouldSpeculateInteger(node.child1(), node.child2())) {
961             if (isInt32Constant(node.child2())) {
962                 SpeculateIntegerOperand op1(this, node.child1());
963                 int32_t imm2 = valueOfInt32Constant(node.child2());
964                 GPRTemporary result(this);
965
966                 speculationCheck(m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
967
968                 integerResult(result.gpr(), m_compileIndex);
969                 break;
970             }
971                 
972             SpeculateIntegerOperand op1(this, node.child1());
973             SpeculateIntegerOperand op2(this, node.child2());
974             GPRTemporary result(this);
975
976             speculationCheck(m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), op2.gpr(), result.gpr()));
977
978             integerResult(result.gpr(), m_compileIndex);
979             break;
980         }
981
982         SpeculateDoubleOperand op1(this, node.child1());
983         SpeculateDoubleOperand op2(this, node.child2());
984         FPRTemporary result(this, op1);
985
986         FPRReg reg1 = op1.fpr();
987         FPRReg reg2 = op2.fpr();
988         m_jit.subDouble(reg1, reg2, result.fpr());
989
990         doubleResult(result.fpr(), m_compileIndex);
991         break;
992     }
993
994     case ArithMul: {
995         if (shouldSpeculateInteger(node.child1(), node.child2())) {
996             SpeculateIntegerOperand op1(this, node.child1());
997             SpeculateIntegerOperand op2(this, node.child2());
998             GPRTemporary result(this);
999
1000             GPRReg reg1 = op1.gpr();
1001             GPRReg reg2 = op2.gpr();
1002             speculationCheck(m_jit.branchMul32(MacroAssembler::Overflow, reg1, reg2, result.gpr()));
1003
1004             MacroAssembler::Jump resultNonZero = m_jit.branchTest32(MacroAssembler::NonZero, result.gpr());
1005             speculationCheck(m_jit.branch32(MacroAssembler::LessThan, reg1, TrustedImm32(0)));
1006             speculationCheck(m_jit.branch32(MacroAssembler::LessThan, reg2, TrustedImm32(0)));
1007             resultNonZero.link(&m_jit);
1008
1009             integerResult(result.gpr(), m_compileIndex);
1010             break;
1011         }
1012
1013         SpeculateDoubleOperand op1(this, node.child1());
1014         SpeculateDoubleOperand op2(this, node.child2());
1015         FPRTemporary result(this, op1, op2);
1016
1017         FPRReg reg1 = op1.fpr();
1018         FPRReg reg2 = op2.fpr();
1019         
1020         m_jit.mulDouble(reg1, reg2, result.fpr());
1021         
1022         doubleResult(result.fpr(), m_compileIndex);
1023         break;
1024     }
1025
1026     case ArithDiv: {
1027         SpeculateDoubleOperand op1(this, node.child1());
1028         SpeculateDoubleOperand op2(this, node.child2());
1029         FPRTemporary result(this, op1);
1030
1031         FPRReg reg1 = op1.fpr();
1032         FPRReg reg2 = op2.fpr();
1033         m_jit.divDouble(reg1, reg2, result.fpr());
1034
1035         doubleResult(result.fpr(), m_compileIndex);
1036         break;
1037     }
1038
1039     case ArithMod: {
1040         SpeculateIntegerOperand op1(this, node.child1());
1041         SpeculateIntegerOperand op2(this, node.child2());
1042         GPRTemporary eax(this, X86Registers::eax);
1043         GPRTemporary edx(this, X86Registers::edx);
1044         GPRReg op1Gpr = op1.gpr();
1045         GPRReg op2Gpr = op2.gpr();
1046
1047         speculationCheck(m_jit.branchTest32(JITCompiler::Zero, op2Gpr));
1048
1049         GPRReg temp2 = InvalidGPRReg;
1050         if (op2Gpr == X86Registers::eax || op2Gpr == X86Registers::edx) {
1051             temp2 = allocate();
1052             m_jit.move(op2Gpr, temp2);
1053             op2Gpr = temp2;
1054         }
1055
1056         m_jit.move(op1Gpr, eax.gpr());
1057         m_jit.assembler().cdq();
1058         m_jit.assembler().idivl_r(op2Gpr);
1059
1060         if (temp2 != InvalidGPRReg)
1061             unlock(temp2);
1062
1063         integerResult(edx.gpr(), m_compileIndex);
1064         break;
1065     }
1066
1067     case LogicalNot: {
1068         if (isKnownBoolean(node.child1())) {
1069             SpeculateBooleanOperand value(this, node.child1());
1070             GPRTemporary result(this, value);
1071             
1072             m_jit.move(value.gpr(), result.gpr());
1073             m_jit.xorPtr(TrustedImm32(true), result.gpr());
1074             
1075             jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
1076             break;
1077         }
1078         
1079         PredictedType prediction = m_jit.graph().getPrediction(m_jit.graph()[node.child1()]);
1080         if (isBooleanPrediction(prediction) || !isStrongPrediction(prediction)) {
1081             JSValueOperand value(this, node.child1());
1082             GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add).
1083             
1084             m_jit.move(value.gpr(), result.gpr());
1085             m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), result.gpr());
1086             speculationCheck(m_jit.branchTestPtr(JITCompiler::NonZero, result.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
1087             m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueTrue)), result.gpr());
1088             
1089             // If we add a DataFormatBool, we should use it here.
1090             jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
1091             break;
1092         }
1093         
1094         nonSpeculativeLogicalNot(node);
1095         
1096         break;
1097     }
1098
1099     case CompareLess:
1100         if (compare(node, JITCompiler::LessThan, JITCompiler::DoubleLessThan, operationCompareLess))
1101             return;
1102         break;
1103
1104     case CompareLessEq:
1105         if (compare(node, JITCompiler::LessThanOrEqual, JITCompiler::DoubleLessThanOrEqual, operationCompareLessEq))
1106             return;
1107         break;
1108
1109     case CompareGreater:
1110         if (compare(node, JITCompiler::GreaterThan, JITCompiler::DoubleGreaterThan, operationCompareGreater))
1111             return;
1112         break;
1113
1114     case CompareGreaterEq:
1115         if (compare(node, JITCompiler::GreaterThanOrEqual, JITCompiler::DoubleGreaterThanOrEqual, operationCompareGreaterEq))
1116             return;
1117         break;
1118
1119     case CompareEq:
1120         if (isNullConstant(node.child1())) {
1121             if (nonSpeculativeCompareNull(node, node.child2()))
1122                 return;
1123             break;
1124         }
1125         if (isNullConstant(node.child2())) {
1126             if (nonSpeculativeCompareNull(node, node.child1()))
1127                 return;
1128             break;
1129         }
1130         if (compare(node, JITCompiler::Equal, JITCompiler::DoubleEqual, operationCompareEq))
1131             return;
1132         break;
1133
1134     case CompareStrictEq:
1135         if (nonSpeculativeStrictEq(node))
1136             return;
1137         break;
1138
1139     case GetByVal: {
1140         NodeIndex alias = node.child3();
1141         if (alias != NoNode) {
1142             // FIXME: result should be able to reuse child1, child2. Should have an 'UnusedOperand' type.
1143             JSValueOperand aliasedValue(this, node.child3());
1144             GPRTemporary result(this, aliasedValue);
1145             m_jit.move(aliasedValue.gpr(), result.gpr());
1146             jsValueResult(result.gpr(), m_compileIndex);
1147             break;
1148         }
1149
1150         SpeculateCellOperand base(this, node.child1());
1151         SpeculateStrictInt32Operand property(this, node.child2());
1152         GPRTemporary storage(this);
1153
1154         GPRReg baseReg = base.gpr();
1155         GPRReg propertyReg = property.gpr();
1156         GPRReg storageReg = storage.gpr();
1157         
1158         if (!m_compileOkay)
1159             return;
1160
1161         // Get the array storage. We haven't yet checked this is a JSArray, so this is only safe if
1162         // an access with offset JSArray::storageOffset() is valid for all JSCells!
1163         m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
1164
1165         // Check that base is an array, and that property is contained within m_vector (< m_vectorLength).
1166         // If we have predicted the base to be type array, we can skip the check.
1167         Node& baseNode = m_jit.graph()[node.child1()];
1168         if (baseNode.op != GetLocal || !isArrayPrediction(m_jit.graph().getPrediction(baseNode.local())))
1169             speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
1170         speculationCheck(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset())));
1171
1172         // FIXME: In cases where there are subsequent by_val accesses to the same base it might help to cache
1173         // the storage pointer - especially if there happens to be another register free right now. If we do so,
1174         // then we'll need to allocate a new temporary for result.
1175         GPRTemporary& result = storage;
1176         m_jit.loadPtr(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), result.gpr());
1177         speculationCheck(m_jit.branchTestPtr(MacroAssembler::Zero, result.gpr()));
1178
1179         jsValueResult(result.gpr(), m_compileIndex);
1180         break;
1181     }
1182
1183     case PutByVal: {
1184         SpeculateCellOperand base(this, node.child1());
1185         SpeculateStrictInt32Operand property(this, node.child2());
1186         JSValueOperand value(this, node.child3());
1187         GPRTemporary scratch(this);
1188
1189         // Map base, property & value into registers, allocate a scratch register.
1190         GPRReg baseReg = base.gpr();
1191         GPRReg propertyReg = property.gpr();
1192         GPRReg valueReg = value.gpr();
1193         GPRReg scratchReg = scratch.gpr();
1194         
1195         if (!m_compileOkay)
1196             return;
1197         
1198         writeBarrier(m_jit, baseReg, scratchReg, WriteBarrierForPropertyAccess);
1199
1200         // Check that base is an array, and that property is contained within m_vector (< m_vectorLength).
1201         // If we have predicted the base to be type array, we can skip the check.
1202         Node& baseNode = m_jit.graph()[node.child1()];
1203         if (baseNode.op != GetLocal || !isArrayPrediction(m_jit.graph().getPrediction(baseNode.local())))
1204             speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
1205
1206         base.use();
1207         property.use();
1208         value.use();
1209         
1210         MacroAssembler::Jump withinArrayBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset()));
1211
1212         // Code to handle put beyond array bounds.
1213         silentSpillAllRegisters(scratchReg);
1214         setupStubArguments(baseReg, propertyReg, valueReg);
1215         m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
1216         JITCompiler::Call functionCall = appendCallWithExceptionCheck(operationPutByValBeyondArrayBounds);
1217         silentFillAllRegisters(scratchReg);
1218         JITCompiler::Jump wasBeyondArrayBounds = m_jit.jump();
1219
1220         withinArrayBounds.link(&m_jit);
1221
1222         // Get the array storage.
1223         GPRReg storageReg = scratchReg;
1224         m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
1225
1226         // Check if we're writing to a hole; if so increment m_numValuesInVector.
1227         MacroAssembler::Jump notHoleValue = m_jit.branchTestPtr(MacroAssembler::NonZero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
1228         m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
1229
1230         // If we're writing to a hole we might be growing the array; 
1231         MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, OBJECT_OFFSETOF(ArrayStorage, m_length)));
1232         m_jit.add32(TrustedImm32(1), propertyReg);
1233         m_jit.store32(propertyReg, MacroAssembler::Address(storageReg, OBJECT_OFFSETOF(ArrayStorage, m_length)));
1234         m_jit.sub32(TrustedImm32(1), propertyReg);
1235
1236         lengthDoesNotNeedUpdate.link(&m_jit);
1237         notHoleValue.link(&m_jit);
1238
1239         // Store the value to the array.
1240         m_jit.storePtr(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
1241
1242         wasBeyondArrayBounds.link(&m_jit);
1243
1244         noResult(m_compileIndex, UseChildrenCalledExplicitly);
1245         break;
1246     }
1247
1248     case PutByValAlias: {
1249         SpeculateCellOperand base(this, node.child1());
1250         SpeculateStrictInt32Operand property(this, node.child2());
1251         JSValueOperand value(this, node.child3());
1252         GPRTemporary scratch(this);
1253         
1254         GPRReg baseReg = base.gpr();
1255         GPRReg scratchReg = scratch.gpr();
1256
1257         writeBarrier(m_jit, baseReg, scratchReg, WriteBarrierForPropertyAccess);
1258
1259         // Get the array storage.
1260         GPRReg storageReg = scratchReg;
1261         m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
1262
1263         // Store the value to the array.
1264         GPRReg propertyReg = property.gpr();
1265         GPRReg valueReg = value.gpr();
1266         m_jit.storePtr(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
1267
1268         noResult(m_compileIndex);
1269         break;
1270     }
1271
1272     case DFG::Jump: {
1273         BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());
1274         if (taken != (m_block + 1))
1275             addBranch(m_jit.jump(), taken);
1276         noResult(m_compileIndex);
1277         break;
1278     }
1279
1280     case Branch:
1281         if (isStrictInt32(node.child1())) {
1282             SpeculateStrictInt32Operand op(this, node.child1());
1283             
1284             BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());
1285             BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(node.notTakenBytecodeOffset());
1286             
1287             MacroAssembler::ResultCondition condition = MacroAssembler::NonZero;
1288             
1289             if (taken == (m_block + 1)) {
1290                 condition = MacroAssembler::Zero;
1291                 BlockIndex tmp = taken;
1292                 taken = notTaken;
1293                 notTaken = tmp;
1294             }
1295             
1296             addBranch(m_jit.branchTest32(condition, op.gpr()), taken);
1297             if (notTaken != (m_block + 1))
1298                 addBranch(m_jit.jump(), notTaken);
1299             
1300             noResult(m_compileIndex);
1301             break;
1302         }
1303         if (shouldSpeculateInteger(node.child1())) {
1304             SpeculateIntegerOperand op(this, node.child1());
1305
1306             BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());
1307             BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(node.notTakenBytecodeOffset());
1308             
1309             MacroAssembler::RelationalCondition condition = MacroAssembler::NotEqual;
1310
1311             if (taken == (m_block + 1)) {
1312                 condition = MacroAssembler::Equal;
1313                 BlockIndex tmp = taken;
1314                 taken = notTaken;
1315                 notTaken = tmp;
1316             }
1317             
1318             addBranch(m_jit.branchPtr(condition, op.gpr(), GPRInfo::tagTypeNumberRegister), taken);
1319
1320             if (notTaken != (m_block + 1))
1321                 addBranch(m_jit.jump(), notTaken);
1322             
1323             noResult(m_compileIndex);
1324             break;
1325         }
1326         emitBranch(node);
1327         break;
1328
1329     case Return: {
1330         ASSERT(GPRInfo::callFrameRegister != GPRInfo::regT1);
1331         ASSERT(GPRInfo::regT1 != GPRInfo::returnValueGPR);
1332         ASSERT(GPRInfo::returnValueGPR != GPRInfo::callFrameRegister);
1333
1334 #if ENABLE(DFG_SUCCESS_STATS)
1335         static SamplingCounter counter("SpeculativeJIT");
1336         m_jit.emitCount(counter);
1337 #endif
1338
1339         // Return the result in returnValueGPR.
1340         JSValueOperand op1(this, node.child1());
1341         m_jit.move(op1.gpr(), GPRInfo::returnValueGPR);
1342
1343         // Grab the return address.
1344         m_jit.emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, GPRInfo::regT1);
1345         // Restore our caller's "r".
1346         m_jit.emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, GPRInfo::callFrameRegister);
1347         // Return.
1348         m_jit.restoreReturnAddressBeforeReturn(GPRInfo::regT1);
1349         m_jit.ret();
1350         
1351         noResult(m_compileIndex);
1352         break;
1353     }
1354
1355     case ConvertThis: {
1356         SpeculateCellOperand thisValue(this, node.child1());
1357
1358         speculationCheck(m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(thisValue.gpr()), JITCompiler::TrustedImmPtr(m_jit.globalData()->jsStringVPtr)));
1359
1360         cellResult(thisValue.gpr(), m_compileIndex);
1361         break;
1362     }
1363
1364     case GetById: {
1365         SpeculateCellOperand base(this, node.child1());
1366         GPRTemporary result(this, base);
1367         
1368         GPRReg baseGPR = base.gpr();
1369         GPRReg resultGPR = result.gpr();
1370         GPRReg scratchGPR;
1371         
1372         if (resultGPR == baseGPR)
1373             scratchGPR = tryAllocate();
1374         else
1375             scratchGPR = resultGPR;
1376         
1377         base.use();
1378
1379         cachedGetById(baseGPR, resultGPR, scratchGPR, node.identifierNumber());
1380
1381         jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
1382         break;
1383     }
1384         
1385     case GetMethod: {
1386         SpeculateCellOperand base(this, node.child1());
1387         GPRTemporary result(this, base);
1388
1389         GPRReg baseGPR = base.gpr();
1390         GPRReg resultGPR = result.gpr();
1391         GPRReg scratchGPR;
1392         
1393         if (resultGPR == baseGPR)
1394             scratchGPR = tryAllocate();
1395         else
1396             scratchGPR = resultGPR;
1397         
1398         base.use();
1399
1400         cachedGetMethod(baseGPR, resultGPR, scratchGPR, node.identifierNumber());
1401
1402         jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
1403         break;
1404     }
1405
1406     case PutById: {
1407         SpeculateCellOperand base(this, node.child1());
1408         JSValueOperand value(this, node.child2());
1409         GPRTemporary scratch(this);
1410         
1411         GPRReg baseGPR = base.gpr();
1412         GPRReg valueGPR = value.gpr();
1413         GPRReg scratchGPR = scratch.gpr();
1414         
1415         base.use();
1416         value.use();
1417
1418         cachedPutById(baseGPR, valueGPR, scratchGPR, node.identifierNumber(), NotDirect);
1419         
1420         noResult(m_compileIndex, UseChildrenCalledExplicitly);
1421         break;
1422     }
1423
1424     case PutByIdDirect: {
1425         SpeculateCellOperand base(this, node.child1());
1426         JSValueOperand value(this, node.child2());
1427         GPRTemporary scratch(this);
1428         
1429         GPRReg baseGPR = base.gpr();
1430         GPRReg valueGPR = value.gpr();
1431         GPRReg scratchGPR = scratch.gpr();
1432         
1433         base.use();
1434         value.use();
1435
1436         cachedPutById(baseGPR, valueGPR, scratchGPR, node.identifierNumber(), Direct);
1437
1438         noResult(m_compileIndex, UseChildrenCalledExplicitly);
1439         break;
1440     }
1441
1442     case GetGlobalVar: {
1443         GPRTemporary result(this);
1444
1445         JSVariableObject* globalObject = m_jit.codeBlock()->globalObject();
1446         m_jit.loadPtr(globalObject->addressOfRegisters(), result.gpr());
1447         m_jit.loadPtr(JITCompiler::addressForGlobalVar(result.gpr(), node.varNumber()), result.gpr());
1448
1449         jsValueResult(result.gpr(), m_compileIndex);
1450         break;
1451     }
1452
1453     case PutGlobalVar: {
1454         JSValueOperand value(this, node.child1());
1455         GPRTemporary globalObject(this);
1456         GPRTemporary scratch(this);
1457         
1458         GPRReg globalObjectReg = globalObject.gpr();
1459         GPRReg scratchReg = scratch.gpr();
1460
1461         m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.codeBlock()->globalObject()), globalObjectReg);
1462
1463         writeBarrier(m_jit, globalObjectReg, scratchReg, WriteBarrierForVariableAccess);
1464
1465         m_jit.loadPtr(MacroAssembler::Address(globalObjectReg, JSVariableObject::offsetOfRegisters()), scratchReg);
1466         m_jit.storePtr(value.gpr(), JITCompiler::addressForGlobalVar(scratchReg, node.varNumber()));
1467
1468         noResult(m_compileIndex);
1469         break;
1470     }
1471
1472     case CheckHasInstance: {
1473         SpeculateCellOperand base(this, node.child1());
1474         GPRTemporary structure(this);
1475
1476         // Speculate that base 'ImplementsDefaultHasInstance'.
1477         m_jit.loadPtr(MacroAssembler::Address(base.gpr(), JSCell::structureOffset()), structure.gpr());
1478         speculationCheck(m_jit.branchTest8(MacroAssembler::Zero, MacroAssembler::Address(structure.gpr(), Structure::typeInfoFlagsOffset()), MacroAssembler::TrustedImm32(ImplementsDefaultHasInstance)));
1479
1480         noResult(m_compileIndex);
1481         break;
1482     }
1483
1484     case InstanceOf: {
1485         SpeculateCellOperand value(this, node.child1());
1486         // Base unused since we speculate default InstanceOf behaviour in CheckHasInstance.
1487         SpeculateCellOperand prototype(this, node.child3());
1488
1489         GPRTemporary scratch(this);
1490
1491         GPRReg valueReg = value.gpr();
1492         GPRReg prototypeReg = prototype.gpr();
1493         GPRReg scratchReg = scratch.gpr();
1494
1495         // Check that prototype is an object.
1496         m_jit.loadPtr(MacroAssembler::Address(prototypeReg, JSCell::structureOffset()), scratchReg);
1497         speculationCheck(m_jit.branchIfNotObject(scratchReg));
1498
1499         // Initialize scratchReg with the value being checked.
1500         m_jit.move(valueReg, scratchReg);
1501
1502         // Walk up the prototype chain of the value (in scratchReg), comparing to prototypeReg.
1503         MacroAssembler::Label loop(&m_jit);
1504         m_jit.loadPtr(MacroAssembler::Address(scratchReg, JSCell::structureOffset()), scratchReg);
1505         m_jit.loadPtr(MacroAssembler::Address(scratchReg, Structure::prototypeOffset()), scratchReg);
1506         MacroAssembler::Jump isInstance = m_jit.branchPtr(MacroAssembler::Equal, scratchReg, prototypeReg);
1507         m_jit.branchTestPtr(MacroAssembler::Zero, scratchReg, GPRInfo::tagMaskRegister).linkTo(loop, &m_jit);
1508
1509         // No match - result is false.
1510         m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(false))), scratchReg);
1511         MacroAssembler::Jump putResult = m_jit.jump();
1512
1513         isInstance.link(&m_jit);
1514         m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(true))), scratchReg);
1515
1516         putResult.link(&m_jit);
1517         jsValueResult(scratchReg, m_compileIndex, DataFormatJSBoolean);
1518         break;
1519     }
1520
1521     case Phi:
1522         ASSERT_NOT_REACHED();
1523
1524     case Breakpoint:
1525 #if ENABLE(DEBUG_WITH_BREAKPOINT)
1526         m_jit.breakpoint();
1527 #else
1528         ASSERT_NOT_REACHED();
1529 #endif
1530         break;
1531         
1532     case Call:
1533     case Construct:
1534         emitCall(node);
1535         break;
1536
1537     case Resolve: {
1538         flushRegisters();
1539         GPRResult result(this);
1540         callOperation(operationResolve, result.gpr(), identifier(node.identifierNumber()));
1541         jsValueResult(result.gpr(), m_compileIndex);
1542         break;
1543     }
1544
1545     case ResolveBase: {
1546         flushRegisters();
1547         GPRResult result(this);
1548         callOperation(operationResolveBase, result.gpr(), identifier(node.identifierNumber()));
1549         jsValueResult(result.gpr(), m_compileIndex);
1550         break;
1551     }
1552
1553     case ResolveBaseStrictPut: {
1554         flushRegisters();
1555         GPRResult result(this);
1556         callOperation(operationResolveBaseStrictPut, result.gpr(), identifier(node.identifierNumber()));
1557         jsValueResult(result.gpr(), m_compileIndex);
1558         break;
1559     }
1560     }
1561     
1562     if (node.hasResult() && node.mustGenerate())
1563         use(m_compileIndex);
1564 }
1565
1566 void SpeculativeJIT::compileMovHint(Node& node)
1567 {
1568     ASSERT(node.op == SetLocal);
1569     
1570     setNodeIndexForOperand(node.child1(), node.local());
1571     m_lastSetOperand = node.local();
1572 }
1573
1574 void SpeculativeJIT::compile(BasicBlock& block)
1575 {
1576     ASSERT(m_compileOkay);
1577     ASSERT(m_compileIndex == block.begin);
1578     
1579     if (block.isOSRTarget)
1580         m_jit.noticeOSREntry(block);
1581     
1582     m_blockHeads[m_block] = m_jit.label();
1583 #if ENABLE(DFG_JIT_BREAK_ON_EVERY_BLOCK)
1584     m_jit.breakpoint();
1585 #endif
1586     
1587     for (size_t i = 0; i < m_arguments.size(); ++i)
1588         m_arguments[i] = ValueSource();
1589     for (size_t i = 0; i < m_variables.size(); ++i)
1590         m_variables[i] = ValueSource();
1591     m_lastSetOperand = std::numeric_limits<int>::max();
1592     m_bytecodeIndexForOSR = std::numeric_limits<uint32_t>::max();
1593
1594     for (; m_compileIndex < block.end; ++m_compileIndex) {
1595         Node& node = m_jit.graph()[m_compileIndex];
1596         m_bytecodeIndexForOSR = node.codeOrigin.bytecodeIndex();
1597         if (!node.shouldGenerate()) {
1598 #if ENABLE(DFG_DEBUG_VERBOSE)
1599             fprintf(stderr, "SpeculativeJIT skipping Node @%d (bc#%u) at JIT offset 0x%x     ", (int)m_compileIndex, node.codeOrigin.bytecodeIndex(), m_jit.debugOffset());
1600 #endif
1601             if (node.op == SetLocal)
1602                 compileMovHint(node);
1603         } else {
1604             
1605 #if ENABLE(DFG_DEBUG_VERBOSE)
1606             fprintf(stderr, "SpeculativeJIT generating Node @%d (bc#%u) at JIT offset 0x%x   ", (int)m_compileIndex, node.codeOrigin.bytecodeIndex(), m_jit.debugOffset());
1607 #endif
1608 #if ENABLE(DFG_JIT_BREAK_ON_EVERY_NODE)
1609             m_jit.breakpoint();
1610 #endif
1611             checkConsistency();
1612             compile(node);
1613             if (!m_compileOkay) {
1614 #if ENABLE(DYNAMIC_TERMINATE_SPECULATION)
1615                 m_compileOkay = true;
1616                 m_compileIndex = block.end;
1617                 clearGenerationInfo();
1618 #endif
1619                 return;
1620             }
1621             
1622 #if ENABLE(DFG_DEBUG_VERBOSE)
1623             if (node.hasResult()) {
1624                 GenerationInfo& info = m_generationInfo[node.virtualRegister()];
1625                 fprintf(stderr, "-> %s, vr#%d", dataFormatToString(info.registerFormat()), (int)node.virtualRegister());
1626                 if (info.registerFormat() != DataFormatNone) {
1627                     if (info.registerFormat() == DataFormatDouble)
1628                         fprintf(stderr, ", %s", FPRInfo::debugName(info.fpr()));
1629                     else
1630                         fprintf(stderr, ", %s", GPRInfo::debugName(info.gpr()));
1631                 }
1632                 fprintf(stderr, "    ");
1633             } else
1634                 fprintf(stderr, "    ");
1635 #endif
1636         }
1637         
1638 #if ENABLE(DFG_VERBOSE_VALUE_RECOVERIES)
1639         for (int operand = -m_arguments.size() - RegisterFile::CallFrameHeaderSize; operand < -RegisterFile::CallFrameHeaderSize; ++operand)
1640             computeValueRecoveryFor(operand).dump(stderr);
1641         
1642         fprintf(stderr, " : ");
1643         
1644         for (int operand = 0; operand < (int)m_variables.size(); ++operand)
1645             computeValueRecoveryFor(operand).dump(stderr);
1646 #endif
1647       
1648 #if ENABLE(DFG_DEBUG_VERBOSE)
1649         fprintf(stderr, "\n");
1650 #endif
1651         
1652         if (node.shouldGenerate())
1653             checkConsistency();
1654     }
1655 }
1656
1657 // If we are making type predictions about our arguments then
1658 // we need to check that they are correct on function entry.
1659 void SpeculativeJIT::checkArgumentTypes()
1660 {
1661     ASSERT(!m_compileIndex);
1662     m_bytecodeIndexForOSR = 0;
1663     for (int i = 0; i < m_jit.codeBlock()->m_numParameters; ++i) {
1664         VirtualRegister virtualRegister = (VirtualRegister)(m_jit.codeBlock()->thisRegister() + i);
1665         PredictedType predictedType = m_jit.graph().getPrediction(virtualRegister);
1666         if (isInt32Prediction(predictedType))
1667             speculationCheck(m_jit.branchPtr(MacroAssembler::Below, JITCompiler::addressFor(virtualRegister), GPRInfo::tagTypeNumberRegister));
1668         else if (isArrayPrediction(predictedType)) {
1669             GPRTemporary temp(this);
1670             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1671             speculationCheck(m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
1672             speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
1673         }
1674     }
1675 }
1676
1677 // For any vars that we will be treating as numeric, write 0 to
1678 // the var on entry. Throughout the block we will only read/write
1679 // to the payload, by writing the tag now we prevent the GC from
1680 // misinterpreting values as pointers.
1681 void SpeculativeJIT::initializeVariableTypes()
1682 {
1683     ASSERT(!m_compileIndex);
1684     for (int var = 0; var < (int)m_jit.graph().predictions().numberOfVariables(); ++var) {
1685         if (isInt32Prediction(m_jit.graph().getPrediction(var)))
1686             m_jit.storePtr(GPRInfo::tagTypeNumberRegister, JITCompiler::addressFor((VirtualRegister)var));
1687     }
1688 }
1689
1690 bool SpeculativeJIT::compile()
1691 {
1692     checkArgumentTypes();
1693     initializeVariableTypes();
1694
1695     ASSERT(!m_compileIndex);
1696     for (m_block = 0; m_block < m_jit.graph().m_blocks.size(); ++m_block) {
1697         compile(*m_jit.graph().m_blocks[m_block]);
1698 #if !ENABLE(DYNAMIC_TERMINATE_SPECULATION)
1699         if (!m_compileOkay)
1700             return false;
1701 #endif
1702     }
1703     linkBranches();
1704     return true;
1705 }
1706
1707 ValueRecovery SpeculativeJIT::computeValueRecoveryFor(const ValueSource& valueSource)
1708 {
1709     if (!valueSource.isSet())
1710         return ValueRecovery::alreadyInRegisterFile();
1711
1712     if (m_jit.isConstant(valueSource.nodeIndex()))
1713         return ValueRecovery::constant(m_jit.valueOfJSConstant(valueSource.nodeIndex()));
1714     
1715     Node* nodePtr = &m_jit.graph()[valueSource.nodeIndex()];
1716     if (!nodePtr->shouldGenerate()) {
1717         // It's legitimately dead. As in, nobody will ever use this node, or operand,
1718         // ever. Set it to Undefined to make the GC happy after the OSR.
1719         return ValueRecovery::constant(jsUndefined());
1720     }
1721     
1722     GenerationInfo* infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
1723     if (!infoPtr->alive() || infoPtr->nodeIndex() != valueSource.nodeIndex()) {
1724         // Try to see if there is an alternate node that would contain the value we want.
1725         // There are four possibilities:
1726         //
1727         // ValueToNumber: If the only live version of the value is a ValueToNumber node
1728         //    then it means that all remaining uses of the value would have performed a
1729         //    ValueToNumber conversion anyway. Thus, we can substitute ValueToNumber.
1730         //
1731         // ValueToInt32: Likewise, if the only remaining live version of the value is
1732         //    ValueToInt32, then we can use it. But if there is both a ValueToInt32
1733         //    and a ValueToNumber, then we better go with ValueToNumber because it
1734         //    means that some remaining uses would have converted to number while
1735         //    others would have converted to Int32.
1736         //
1737         // UInt32ToNumber: If the only live version of the value is a UInt32ToNumber
1738         //    then the only remaining uses are ones that want a properly formed number
1739         //    rather than a UInt32 intermediate.
1740         //
1741         // The reverse of the above: This node could be a UInt32ToNumber, but its
1742         //    alternative is still alive. This means that the only remaining uses of
1743         //    the number would be fine with a UInt32 intermediate.
1744         
1745         bool found = false;
1746         
1747         if (nodePtr->op == UInt32ToNumber) {
1748             NodeIndex nodeIndex = nodePtr->child1();
1749             nodePtr = &m_jit.graph()[nodeIndex];
1750             infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
1751             if (infoPtr->alive() && infoPtr->nodeIndex() == nodeIndex)
1752                 found = true;
1753         }
1754         
1755         if (!found) {
1756             NodeIndex valueToNumberIndex = NoNode;
1757             NodeIndex valueToInt32Index = NoNode;
1758             NodeIndex uint32ToNumberIndex = NoNode;
1759             
1760             for (unsigned virtualRegister = 0; virtualRegister < m_generationInfo.size(); ++virtualRegister) {
1761                 GenerationInfo& info = m_generationInfo[virtualRegister];
1762                 if (!info.alive())
1763                     continue;
1764                 if (info.nodeIndex() == NoNode)
1765                     continue;
1766                 Node& node = m_jit.graph()[info.nodeIndex()];
1767                 if (node.child1Unchecked() != valueSource.nodeIndex())
1768                     continue;
1769                 switch (node.op) {
1770                 case ValueToNumber:
1771                 case ValueToDouble:
1772                     valueToNumberIndex = info.nodeIndex();
1773                     break;
1774                 case ValueToInt32:
1775                     valueToInt32Index = info.nodeIndex();
1776                     break;
1777                 case UInt32ToNumber:
1778                     uint32ToNumberIndex = info.nodeIndex();
1779                     break;
1780                 default:
1781                     break;
1782                 }
1783             }
1784             
1785             NodeIndex nodeIndexToUse;
1786             if (valueToNumberIndex != NoNode)
1787                 nodeIndexToUse = valueToNumberIndex;
1788             else if (valueToInt32Index != NoNode)
1789                 nodeIndexToUse = valueToInt32Index;
1790             else if (uint32ToNumberIndex != NoNode)
1791                 nodeIndexToUse = uint32ToNumberIndex;
1792             else
1793                 nodeIndexToUse = NoNode;
1794             
1795             if (nodeIndexToUse != NoNode) {
1796                 nodePtr = &m_jit.graph()[nodeIndexToUse];
1797                 infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
1798                 ASSERT(infoPtr->alive() && infoPtr->nodeIndex() == nodeIndexToUse);
1799                 found = true;
1800             }
1801         }
1802         
1803         if (!found)
1804             return ValueRecovery::constant(jsUndefined());
1805     }
1806     
1807     ASSERT(infoPtr->alive());
1808
1809     if (infoPtr->registerFormat() != DataFormatNone) {
1810         if (infoPtr->registerFormat() == DataFormatDouble)
1811             return ValueRecovery::inFPR(infoPtr->fpr());
1812         return ValueRecovery::inGPR(infoPtr->gpr(), infoPtr->registerFormat());
1813     }
1814     if (infoPtr->spillFormat() != DataFormatNone)
1815         return ValueRecovery::displacedInRegisterFile(static_cast<VirtualRegister>(nodePtr->virtualRegister()));
1816     
1817     ASSERT_NOT_REACHED();
1818     return ValueRecovery();
1819 }
1820
1821 } } // namespace JSC::DFG
1822
1823 #endif