DFG should be able to emit code on control flow edges
[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 #include "JSByteArray.h"
32 #include "LinkBuffer.h"
33
34 namespace JSC { namespace DFG {
35
36 // On Windows we need to wrap fmod; on other platforms we can call it directly.
37 // On ARMv7 we assert that all function pointers have to low bit set (point to thumb code).
38 #if CALLING_CONVENTION_IS_STDCALL || CPU(ARM_THUMB2)
39 static double DFG_OPERATION fmodAsDFGOperation(double x, double y)
40 {
41     return fmod(x, y);
42 }
43 #else
44 #define fmodAsDFGOperation fmod
45 #endif
46
47 void SpeculativeJIT::clearGenerationInfo()
48 {
49     for (unsigned i = 0; i < m_generationInfo.size(); ++i)
50         m_generationInfo[i] = GenerationInfo();
51     m_gprs = RegisterBank<GPRInfo>();
52     m_fprs = RegisterBank<FPRInfo>();
53 }
54
55 GPRReg SpeculativeJIT::fillStorage(NodeIndex nodeIndex)
56 {
57     Node& node = m_jit.graph()[nodeIndex];
58     VirtualRegister virtualRegister = node.virtualRegister();
59     GenerationInfo& info = m_generationInfo[virtualRegister];
60     
61     switch (info.registerFormat()) {
62     case DataFormatNone: {
63         GPRReg gpr = allocate();
64         ASSERT(info.spillFormat() == DataFormatStorage);
65         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
66         m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
67         info.fillStorage(gpr);
68         return gpr;
69     }
70         
71     case DataFormatStorage: {
72         GPRReg gpr = info.gpr();
73         m_gprs.lock(gpr);
74         return gpr;
75     }
76         
77     default:
78         ASSERT_NOT_REACHED();
79     }
80     
81     return InvalidGPRReg;
82 }
83
84 void SpeculativeJIT::useChildren(Node& node)
85 {
86     if (node.op & NodeHasVarArgs) {
87         for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++)
88             use(m_jit.graph().m_varArgChildren[childIdx]);
89     } else {
90         NodeUse child1 = node.child1();
91         if (!child1) {
92             ASSERT(!node.child2() && !node.child3());
93             return;
94         }
95         use(child1);
96         
97         NodeUse child2 = node.child2();
98         if (!child2) {
99             ASSERT(!node.child3());
100             return;
101         }
102         use(child2);
103         
104         NodeUse child3 = node.child3();
105         if (!child3)
106             return;
107         use(child3);
108     }
109 }
110
111 bool SpeculativeJIT::isStrictInt32(NodeIndex nodeIndex)
112 {
113     if (isInt32Constant(nodeIndex))
114         return true;
115     
116     Node& node = m_jit.graph()[nodeIndex];
117     GenerationInfo& info = m_generationInfo[node.virtualRegister()];
118     
119     return info.registerFormat() == DataFormatInteger;
120 }
121
122 bool SpeculativeJIT::isKnownInteger(NodeIndex nodeIndex)
123 {
124     if (isInt32Constant(nodeIndex))
125         return true;
126
127     Node& node = m_jit.graph()[nodeIndex];
128     
129     if (node.hasInt32Result())
130         return true;
131     
132     GenerationInfo& info = m_generationInfo[node.virtualRegister()];
133
134     return info.isJSInteger();
135 }
136
137 bool SpeculativeJIT::isKnownNumeric(NodeIndex nodeIndex)
138 {
139     if (isInt32Constant(nodeIndex) || isNumberConstant(nodeIndex))
140         return true;
141
142     Node& node = m_jit.graph()[nodeIndex];
143     
144     if (node.hasNumberResult())
145         return true;
146     
147     GenerationInfo& info = m_generationInfo[node.virtualRegister()];
148
149     return info.isJSInteger() || info.isJSDouble();
150 }
151
152 bool SpeculativeJIT::isKnownCell(NodeIndex nodeIndex)
153 {
154     return m_generationInfo[m_jit.graph()[nodeIndex].virtualRegister()].isJSCell();
155 }
156
157 bool SpeculativeJIT::isKnownNotCell(NodeIndex nodeIndex)
158 {
159     Node& node = m_jit.graph()[nodeIndex];
160     VirtualRegister virtualRegister = node.virtualRegister();
161     GenerationInfo& info = m_generationInfo[virtualRegister];
162     if (node.hasConstant() && !valueOfJSConstant(nodeIndex).isCell())
163         return true;
164     return !(info.isJSCell() || info.isUnknownJS());
165 }
166
167 bool SpeculativeJIT::isKnownNotInteger(NodeIndex nodeIndex)
168 {
169     Node& node = m_jit.graph()[nodeIndex];
170     VirtualRegister virtualRegister = node.virtualRegister();
171     GenerationInfo& info = m_generationInfo[virtualRegister];
172     
173     return info.isJSDouble() || info.isJSCell() || info.isJSBoolean()
174         || (node.hasConstant() && !valueOfJSConstant(nodeIndex).isInt32());
175 }
176
177 bool SpeculativeJIT::isKnownNotNumber(NodeIndex nodeIndex)
178 {
179     Node& node = m_jit.graph()[nodeIndex];
180     VirtualRegister virtualRegister = node.virtualRegister();
181     GenerationInfo& info = m_generationInfo[virtualRegister];
182     
183     return (!info.isJSDouble() && !info.isJSInteger() && !info.isUnknownJS())
184         || (node.hasConstant() && !isNumberConstant(nodeIndex));
185 }
186
187 bool SpeculativeJIT::isKnownBoolean(NodeIndex nodeIndex)
188 {
189     Node& node = m_jit.graph()[nodeIndex];
190     if (node.hasBooleanResult())
191         return true;
192     
193     if (isBooleanConstant(nodeIndex))
194         return true;
195     
196     VirtualRegister virtualRegister = node.virtualRegister();
197     GenerationInfo& info = m_generationInfo[virtualRegister];
198     
199     return info.isJSBoolean();
200 }
201
202 bool SpeculativeJIT::isKnownNotBoolean(NodeIndex nodeIndex)
203 {
204     Node& node = m_jit.graph()[nodeIndex];
205     VirtualRegister virtualRegister = node.virtualRegister();
206     GenerationInfo& info = m_generationInfo[virtualRegister];
207     if (node.hasConstant() && !valueOfJSConstant(nodeIndex).isBoolean())
208         return true;
209     return !(info.isJSBoolean() || info.isUnknownJS());
210 }
211
212 void SpeculativeJIT::writeBarrier(MacroAssembler& jit, GPRReg owner, GPRReg scratch1, GPRReg scratch2, WriteBarrierUseKind useKind)
213 {
214     UNUSED_PARAM(jit);
215     UNUSED_PARAM(owner);
216     UNUSED_PARAM(scratch1);
217     UNUSED_PARAM(scratch2);
218     UNUSED_PARAM(useKind);
219     ASSERT(owner != scratch1);
220     ASSERT(owner != scratch2);
221     ASSERT(scratch1 != scratch2);
222
223 #if ENABLE(WRITE_BARRIER_PROFILING)
224     JITCompiler::emitCount(jit, WriteBarrierCounters::jitCounterFor(useKind));
225 #endif
226     markCellCard(jit, owner, scratch1, scratch2);
227 }
228
229 void SpeculativeJIT::markCellCard(MacroAssembler& jit, GPRReg owner, GPRReg scratch1, GPRReg scratch2)
230 {
231     UNUSED_PARAM(jit);
232     UNUSED_PARAM(owner);
233     UNUSED_PARAM(scratch1);
234     UNUSED_PARAM(scratch2);
235     
236 #if ENABLE(GGC)
237     jit.move(owner, scratch1);
238     jit.andPtr(TrustedImm32(static_cast<int32_t>(MarkedBlock::blockMask)), scratch1);
239     jit.move(owner, scratch2);
240     // consume additional 8 bits as we're using an approximate filter
241     jit.rshift32(TrustedImm32(MarkedBlock::atomShift + 8), scratch2);
242     jit.andPtr(TrustedImm32(MarkedBlock::atomMask >> 8), scratch2);
243     MacroAssembler::Jump filter = jit.branchTest8(MacroAssembler::Zero, MacroAssembler::BaseIndex(scratch1, scratch2, MacroAssembler::TimesOne, MarkedBlock::offsetOfMarks()));
244     jit.move(owner, scratch2);
245     jit.rshift32(TrustedImm32(MarkedBlock::cardShift), scratch2);
246     jit.andPtr(TrustedImm32(MarkedBlock::cardMask), scratch2);
247     jit.store8(TrustedImm32(1), MacroAssembler::BaseIndex(scratch1, scratch2, MacroAssembler::TimesOne, MarkedBlock::offsetOfCards()));
248     filter.link(&jit);
249 #endif
250 }
251
252 void SpeculativeJIT::writeBarrier(GPRReg ownerGPR, GPRReg valueGPR, NodeUse valueUse, WriteBarrierUseKind useKind, GPRReg scratch1, GPRReg scratch2)
253 {
254     UNUSED_PARAM(ownerGPR);
255     UNUSED_PARAM(valueGPR);
256     UNUSED_PARAM(scratch1);
257     UNUSED_PARAM(scratch2);
258     UNUSED_PARAM(useKind);
259
260     if (isKnownNotCell(valueUse.index()))
261         return;
262
263 #if ENABLE(WRITE_BARRIER_PROFILING)
264     JITCompiler::emitCount(m_jit, WriteBarrierCounters::jitCounterFor(useKind));
265 #endif
266
267 #if ENABLE(GGC)
268     GPRTemporary temp1;
269     GPRTemporary temp2;
270     if (scratch1 == InvalidGPRReg) {
271         GPRTemporary scratchGPR(this);
272         temp1.adopt(scratchGPR);
273         scratch1 = temp1.gpr();
274     }
275     if (scratch2 == InvalidGPRReg) {
276         GPRTemporary scratchGPR(this);
277         temp2.adopt(scratchGPR);
278         scratch2 = temp2.gpr();
279     }
280     
281     JITCompiler::Jump rhsNotCell;
282     bool hadCellCheck = false;
283     if (!isKnownCell(valueUse.index()) && !isCellPrediction(m_jit.getPrediction(valueUse.index()))) {
284         hadCellCheck = true;
285         rhsNotCell = m_jit.branchIfNotCell(valueGPR);
286     }
287
288     markCellCard(m_jit, ownerGPR, scratch1, scratch2);
289
290     if (hadCellCheck)
291         rhsNotCell.link(&m_jit);
292 #endif
293 }
294
295 void SpeculativeJIT::writeBarrier(GPRReg ownerGPR, JSCell* value, WriteBarrierUseKind useKind, GPRReg scratch1, GPRReg scratch2)
296 {
297     UNUSED_PARAM(ownerGPR);
298     UNUSED_PARAM(value);
299     UNUSED_PARAM(scratch1);
300     UNUSED_PARAM(scratch2);
301     UNUSED_PARAM(useKind);
302     
303     if (Heap::isMarked(value))
304         return;
305
306 #if ENABLE(WRITE_BARRIER_PROFILING)
307     JITCompiler::emitCount(m_jit, WriteBarrierCounters::jitCounterFor(useKind));
308 #endif
309
310 #if ENABLE(GGC)
311     GPRTemporary temp1;
312     GPRTemporary temp2;
313     if (scratch1 == InvalidGPRReg) {
314         GPRTemporary scratchGPR(this);
315         temp1.adopt(scratchGPR);
316         scratch1 = temp1.gpr();
317     }
318     if (scratch2 == InvalidGPRReg) {
319         GPRTemporary scratchGPR(this);
320         temp2.adopt(scratchGPR);
321         scratch2 = temp2.gpr();
322     }
323
324     markCellCard(m_jit, ownerGPR, scratch1, scratch2);
325 #endif
326 }
327
328 void SpeculativeJIT::writeBarrier(JSCell* owner, GPRReg valueGPR, NodeUse valueUse, WriteBarrierUseKind useKind, GPRReg scratch)
329 {
330     UNUSED_PARAM(owner);
331     UNUSED_PARAM(valueGPR);
332     UNUSED_PARAM(scratch);
333     UNUSED_PARAM(useKind);
334
335     if (isKnownNotCell(valueUse.index()))
336         return;
337
338 #if ENABLE(WRITE_BARRIER_PROFILING)
339     JITCompiler::emitCount(m_jit, WriteBarrierCounters::jitCounterFor(useKind));
340 #endif
341
342 #if ENABLE(GGC)
343     JITCompiler::Jump rhsNotCell;
344     bool hadCellCheck = false;
345     if (!isKnownCell(valueUse.index()) && !isCellPrediction(m_jit.getPrediction(valueUse.index()))) {
346         hadCellCheck = true;
347         rhsNotCell = m_jit.branchIfNotCell(valueGPR);
348     }
349     
350     GPRTemporary temp;
351     if (scratch == InvalidGPRReg) {
352         GPRTemporary scratchGPR(this);
353         temp.adopt(scratchGPR);
354         scratch = temp.gpr();
355     }
356
357     uint8_t* cardAddress = Heap::addressOfCardFor(owner);
358     m_jit.move(JITCompiler::TrustedImmPtr(cardAddress), scratch);
359     m_jit.store8(JITCompiler::TrustedImm32(1), JITCompiler::Address(scratch));
360
361     if (hadCellCheck)
362         rhsNotCell.link(&m_jit);
363 #endif
364 }
365
366 bool SpeculativeJIT::nonSpeculativeCompare(Node& node, MacroAssembler::RelationalCondition cond, S_DFGOperation_EJJ helperFunction)
367 {
368     NodeIndex branchNodeIndex = detectPeepHoleBranch();
369     if (branchNodeIndex != NoNode) {
370         ASSERT(node.adjustedRefCount() == 1);
371         
372         nonSpeculativePeepholeBranch(node, branchNodeIndex, cond, helperFunction);
373     
374         m_compileIndex = branchNodeIndex;
375         
376         return true;
377     }
378     
379     nonSpeculativeNonPeepholeCompare(node, cond, helperFunction);
380     
381     return false;
382 }
383
384 bool SpeculativeJIT::nonSpeculativeStrictEq(Node& node, bool invert)
385 {
386     if (!invert && (isKnownNumeric(node.child1().index()) || isKnownNumeric(node.child2().index())))
387         return nonSpeculativeCompare(node, MacroAssembler::Equal, operationCompareStrictEq);
388     
389     NodeIndex branchNodeIndex = detectPeepHoleBranch();
390     if (branchNodeIndex != NoNode) {
391         ASSERT(node.adjustedRefCount() == 1);
392         
393         nonSpeculativePeepholeStrictEq(node, branchNodeIndex, invert);
394     
395         m_compileIndex = branchNodeIndex;
396         
397         return true;
398     }
399     
400     nonSpeculativeNonPeepholeStrictEq(node, invert);
401     
402     return false;
403 }
404
405 #ifndef NDEBUG
406 static const char* dataFormatString(DataFormat format)
407 {
408     // These values correspond to the DataFormat enum.
409     const char* strings[] = {
410         "[  ]",
411         "[ i]",
412         "[ d]",
413         "[ c]",
414         "Err!",
415         "Err!",
416         "Err!",
417         "Err!",
418         "[J ]",
419         "[Ji]",
420         "[Jd]",
421         "[Jc]",
422         "Err!",
423         "Err!",
424         "Err!",
425         "Err!",
426     };
427     return strings[format];
428 }
429
430 void SpeculativeJIT::dump(const char* label)
431 {
432     if (label)
433         dataLog("<%s>\n", label);
434
435     dataLog("  gprs:\n");
436     m_gprs.dump();
437     dataLog("  fprs:\n");
438     m_fprs.dump();
439     dataLog("  VirtualRegisters:\n");
440     for (unsigned i = 0; i < m_generationInfo.size(); ++i) {
441         GenerationInfo& info = m_generationInfo[i];
442         if (info.alive())
443             dataLog("    % 3d:%s%s", i, dataFormatString(info.registerFormat()), dataFormatString(info.spillFormat()));
444         else
445             dataLog("    % 3d:[__][__]", i);
446         if (info.registerFormat() == DataFormatDouble)
447             dataLog(":fpr%d\n", info.fpr());
448         else if (info.registerFormat() != DataFormatNone
449 #if USE(JSVALUE32_64)
450             && !(info.registerFormat() & DataFormatJS)
451 #endif
452             ) {
453             ASSERT(info.gpr() != InvalidGPRReg);
454             dataLog(":%s\n", GPRInfo::debugName(info.gpr()));
455         } else
456             dataLog("\n");
457     }
458     if (label)
459         dataLog("</%s>\n", label);
460 }
461 #endif
462
463
464 #if DFG_ENABLE(CONSISTENCY_CHECK)
465 void SpeculativeJIT::checkConsistency()
466 {
467     bool failed = false;
468
469     for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
470         if (iter.isLocked()) {
471             dataLog("DFG_CONSISTENCY_CHECK failed: gpr %s is locked.\n", iter.debugName());
472             failed = true;
473         }
474     }
475     for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
476         if (iter.isLocked()) {
477             dataLog("DFG_CONSISTENCY_CHECK failed: fpr %s is locked.\n", iter.debugName());
478             failed = true;
479         }
480     }
481
482     for (unsigned i = 0; i < m_generationInfo.size(); ++i) {
483         VirtualRegister virtualRegister = (VirtualRegister)i;
484         GenerationInfo& info = m_generationInfo[virtualRegister];
485         if (!info.alive())
486             continue;
487         switch (info.registerFormat()) {
488         case DataFormatNone:
489             break;
490         case DataFormatJS:
491         case DataFormatJSInteger:
492         case DataFormatJSDouble:
493         case DataFormatJSCell:
494         case DataFormatJSBoolean:
495 #if USE(JSVALUE32_64)
496             break;
497 #endif
498         case DataFormatInteger:
499         case DataFormatCell:
500         case DataFormatBoolean:
501         case DataFormatStorage: {
502             GPRReg gpr = info.gpr();
503             ASSERT(gpr != InvalidGPRReg);
504             if (m_gprs.name(gpr) != virtualRegister) {
505                 dataLog("DFG_CONSISTENCY_CHECK failed: name mismatch for virtual register %d (gpr %s).\n", virtualRegister, GPRInfo::debugName(gpr));
506                 failed = true;
507             }
508             break;
509         }
510         case DataFormatDouble: {
511             FPRReg fpr = info.fpr();
512             ASSERT(fpr != InvalidFPRReg);
513             if (m_fprs.name(fpr) != virtualRegister) {
514                 dataLog("DFG_CONSISTENCY_CHECK failed: name mismatch for virtual register %d (fpr %s).\n", virtualRegister, FPRInfo::debugName(fpr));
515                 failed = true;
516             }
517             break;
518         }
519         }
520     }
521
522     for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
523         VirtualRegister virtualRegister = iter.name();
524         if (virtualRegister == InvalidVirtualRegister)
525             continue;
526
527         GenerationInfo& info = m_generationInfo[virtualRegister];
528 #if USE(JSVALUE64)
529         if (iter.regID() != info.gpr()) {
530             dataLog("DFG_CONSISTENCY_CHECK failed: name mismatch for gpr %s (virtual register %d).\n", iter.debugName(), virtualRegister);
531             failed = true;
532         }
533 #else
534         if (!(info.registerFormat() & DataFormatJS)) {
535             if (iter.regID() != info.gpr()) {
536                 dataLog("DFG_CONSISTENCY_CHECK failed: name mismatch for gpr %s (virtual register %d).\n", iter.debugName(), virtualRegister);
537                 failed = true;
538             }
539         } else {
540             if (iter.regID() != info.tagGPR() && iter.regID() != info.payloadGPR()) {
541                 dataLog("DFG_CONSISTENCY_CHECK failed: name mismatch for gpr %s (virtual register %d).\n", iter.debugName(), virtualRegister);
542                 failed = true;
543             }
544         }
545 #endif
546     }
547
548     for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
549         VirtualRegister virtualRegister = iter.name();
550         if (virtualRegister == InvalidVirtualRegister)
551             continue;
552
553         GenerationInfo& info = m_generationInfo[virtualRegister];
554         if (iter.regID() != info.fpr()) {
555             dataLog("DFG_CONSISTENCY_CHECK failed: name mismatch for fpr %s (virtual register %d).\n", iter.debugName(), virtualRegister);
556             failed = true;
557         }
558     }
559
560     if (failed) {
561         dump();
562         CRASH();
563     }
564 }
565 #endif
566
567 GPRTemporary::GPRTemporary()
568     : m_jit(0)
569     , m_gpr(InvalidGPRReg)
570 {
571 }
572
573 GPRTemporary::GPRTemporary(SpeculativeJIT* jit)
574     : m_jit(jit)
575     , m_gpr(InvalidGPRReg)
576 {
577     m_gpr = m_jit->allocate();
578 }
579
580 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, GPRReg specific)
581     : m_jit(jit)
582     , m_gpr(InvalidGPRReg)
583 {
584     m_gpr = m_jit->allocate(specific);
585 }
586
587 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, SpeculateIntegerOperand& op1)
588     : m_jit(jit)
589     , m_gpr(InvalidGPRReg)
590 {
591     if (m_jit->canReuse(op1.index()))
592         m_gpr = m_jit->reuse(op1.gpr());
593     else
594         m_gpr = m_jit->allocate();
595 }
596
597 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, SpeculateIntegerOperand& op1, SpeculateIntegerOperand& op2)
598     : m_jit(jit)
599     , m_gpr(InvalidGPRReg)
600 {
601     if (m_jit->canReuse(op1.index()))
602         m_gpr = m_jit->reuse(op1.gpr());
603     else if (m_jit->canReuse(op2.index()))
604         m_gpr = m_jit->reuse(op2.gpr());
605     else
606         m_gpr = m_jit->allocate();
607 }
608
609 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, SpeculateStrictInt32Operand& op1)
610     : m_jit(jit)
611     , m_gpr(InvalidGPRReg)
612 {
613     if (m_jit->canReuse(op1.index()))
614         m_gpr = m_jit->reuse(op1.gpr());
615     else
616         m_gpr = m_jit->allocate();
617 }
618
619 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, IntegerOperand& op1)
620     : m_jit(jit)
621     , m_gpr(InvalidGPRReg)
622 {
623     if (m_jit->canReuse(op1.index()))
624         m_gpr = m_jit->reuse(op1.gpr());
625     else
626         m_gpr = m_jit->allocate();
627 }
628
629 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, IntegerOperand& op1, IntegerOperand& op2)
630     : m_jit(jit)
631     , m_gpr(InvalidGPRReg)
632 {
633     if (m_jit->canReuse(op1.index()))
634         m_gpr = m_jit->reuse(op1.gpr());
635     else if (m_jit->canReuse(op2.index()))
636         m_gpr = m_jit->reuse(op2.gpr());
637     else
638         m_gpr = m_jit->allocate();
639 }
640
641 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, SpeculateCellOperand& op1)
642     : m_jit(jit)
643     , m_gpr(InvalidGPRReg)
644 {
645     if (m_jit->canReuse(op1.index()))
646         m_gpr = m_jit->reuse(op1.gpr());
647     else
648         m_gpr = m_jit->allocate();
649 }
650
651 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, SpeculateBooleanOperand& op1)
652     : m_jit(jit)
653     , m_gpr(InvalidGPRReg)
654 {
655     if (m_jit->canReuse(op1.index()))
656         m_gpr = m_jit->reuse(op1.gpr());
657     else
658         m_gpr = m_jit->allocate();
659 }
660
661 #if USE(JSVALUE64)
662 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, JSValueOperand& op1)
663     : m_jit(jit)
664     , m_gpr(InvalidGPRReg)
665 {
666     if (m_jit->canReuse(op1.index()))
667         m_gpr = m_jit->reuse(op1.gpr());
668     else
669         m_gpr = m_jit->allocate();
670 }
671 #else
672 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, JSValueOperand& op1, bool tag)
673     : m_jit(jit)
674     , m_gpr(InvalidGPRReg)
675 {
676     if (!op1.isDouble() && m_jit->canReuse(op1.index()))
677         m_gpr = m_jit->reuse(tag ? op1.tagGPR() : op1.payloadGPR());
678     else
679         m_gpr = m_jit->allocate();
680 }
681 #endif
682
683 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, StorageOperand& op1)
684     : m_jit(jit)
685     , m_gpr(InvalidGPRReg)
686 {
687     if (m_jit->canReuse(op1.index()))
688         m_gpr = m_jit->reuse(op1.gpr());
689     else
690         m_gpr = m_jit->allocate();
691 }
692
693 void GPRTemporary::adopt(GPRTemporary& other)
694 {
695     ASSERT(!m_jit);
696     ASSERT(m_gpr == InvalidGPRReg);
697     ASSERT(other.m_jit);
698     ASSERT(other.m_gpr != InvalidGPRReg);
699     m_jit = other.m_jit;
700     m_gpr = other.m_gpr;
701     other.m_jit = 0;
702     other.m_gpr = InvalidGPRReg;
703 }
704
705 FPRTemporary::FPRTemporary(SpeculativeJIT* jit)
706     : m_jit(jit)
707     , m_fpr(InvalidFPRReg)
708 {
709     m_fpr = m_jit->fprAllocate();
710 }
711
712 FPRTemporary::FPRTemporary(SpeculativeJIT* jit, DoubleOperand& op1)
713     : m_jit(jit)
714     , m_fpr(InvalidFPRReg)
715 {
716     if (m_jit->canReuse(op1.index()))
717         m_fpr = m_jit->reuse(op1.fpr());
718     else
719         m_fpr = m_jit->fprAllocate();
720 }
721
722 FPRTemporary::FPRTemporary(SpeculativeJIT* jit, DoubleOperand& op1, DoubleOperand& op2)
723     : m_jit(jit)
724     , m_fpr(InvalidFPRReg)
725 {
726     if (m_jit->canReuse(op1.index()))
727         m_fpr = m_jit->reuse(op1.fpr());
728     else if (m_jit->canReuse(op2.index()))
729         m_fpr = m_jit->reuse(op2.fpr());
730     else
731         m_fpr = m_jit->fprAllocate();
732 }
733
734 FPRTemporary::FPRTemporary(SpeculativeJIT* jit, SpeculateDoubleOperand& op1)
735     : m_jit(jit)
736     , m_fpr(InvalidFPRReg)
737 {
738     if (m_jit->canReuse(op1.index()))
739         m_fpr = m_jit->reuse(op1.fpr());
740     else
741         m_fpr = m_jit->fprAllocate();
742 }
743
744 FPRTemporary::FPRTemporary(SpeculativeJIT* jit, SpeculateDoubleOperand& op1, SpeculateDoubleOperand& op2)
745     : m_jit(jit)
746     , m_fpr(InvalidFPRReg)
747 {
748     if (m_jit->canReuse(op1.index()))
749         m_fpr = m_jit->reuse(op1.fpr());
750     else if (m_jit->canReuse(op2.index()))
751         m_fpr = m_jit->reuse(op2.fpr());
752     else
753         m_fpr = m_jit->fprAllocate();
754 }
755
756 #if USE(JSVALUE32_64)
757 FPRTemporary::FPRTemporary(SpeculativeJIT* jit, JSValueOperand& op1)
758     : m_jit(jit)
759     , m_fpr(InvalidFPRReg)
760 {
761     if (op1.isDouble() && m_jit->canReuse(op1.index()))
762         m_fpr = m_jit->reuse(op1.fpr());
763     else
764         m_fpr = m_jit->fprAllocate();
765 }
766 #endif
767
768 #ifndef NDEBUG
769 void ValueSource::dump(FILE* out) const
770 {
771     switch (kind()) {
772     case SourceNotSet:
773         fprintf(out, "NotSet");
774         break;
775     case ValueInRegisterFile:
776         fprintf(out, "InRegFile");
777         break;
778     case Int32InRegisterFile:
779         fprintf(out, "Int32");
780         break;
781     case CellInRegisterFile:
782         fprintf(out, "Cell");
783         break;
784     case BooleanInRegisterFile:
785         fprintf(out, "Bool");
786         break;
787     case DoubleInRegisterFile:
788         fprintf(out, "Double");
789         break;
790     case HaveNode:
791         fprintf(out, "Node(%d)", m_nodeIndex);
792         break;
793     }
794 }
795 #endif
796
797 void SpeculativeJIT::compilePeepHoleDoubleBranch(Node& node, NodeIndex branchNodeIndex, JITCompiler::DoubleCondition condition)
798 {
799     Node& branchNode = at(branchNodeIndex);
800     BlockIndex taken = branchNode.takenBlockIndex();
801     BlockIndex notTaken = branchNode.notTakenBlockIndex();
802     
803     SpeculateDoubleOperand op1(this, node.child1());
804     SpeculateDoubleOperand op2(this, node.child2());
805     
806     branchDouble(condition, op1.fpr(), op2.fpr(), taken);
807     jump(notTaken);
808 }
809
810 void SpeculativeJIT::compilePeepHoleObjectEquality(Node& node, NodeIndex branchNodeIndex, const ClassInfo* classInfo, PredictionChecker predictionCheck)
811 {
812     Node& branchNode = at(branchNodeIndex);
813     BlockIndex taken = branchNode.takenBlockIndex();
814     BlockIndex notTaken = branchNode.notTakenBlockIndex();
815
816     MacroAssembler::RelationalCondition condition = MacroAssembler::Equal;
817     
818     if (taken == (m_block + 1)) {
819         condition = MacroAssembler::NotEqual;
820         BlockIndex tmp = taken;
821         taken = notTaken;
822         notTaken = tmp;
823     }
824
825     SpeculateCellOperand op1(this, node.child1());
826     SpeculateCellOperand op2(this, node.child2());
827     
828     GPRReg op1GPR = op1.gpr();
829     GPRReg op2GPR = op2.gpr();
830     
831     if (!predictionCheck(m_state.forNode(node.child1()).m_type))
832         speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node.child1().index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
833     if (!predictionCheck(m_state.forNode(node.child2()).m_type))
834         speculationCheck(BadType, JSValueSource::unboxedCell(op2GPR), node.child2().index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
835     
836     branchPtr(condition, op1GPR, op2GPR, taken);
837     jump(notTaken);
838 }
839
840 void SpeculativeJIT::compilePeepHoleIntegerBranch(Node& node, NodeIndex branchNodeIndex, JITCompiler::RelationalCondition condition)
841 {
842     Node& branchNode = at(branchNodeIndex);
843     BlockIndex taken = branchNode.takenBlockIndex();
844     BlockIndex notTaken = branchNode.notTakenBlockIndex();
845
846     // The branch instruction will branch to the taken block.
847     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
848     if (taken == (m_block + 1)) {
849         condition = JITCompiler::invert(condition);
850         BlockIndex tmp = taken;
851         taken = notTaken;
852         notTaken = tmp;
853     }
854
855     if (isInt32Constant(node.child1().index())) {
856         int32_t imm = valueOfInt32Constant(node.child1().index());
857         SpeculateIntegerOperand op2(this, node.child2());
858         branch32(condition, JITCompiler::Imm32(imm), op2.gpr(), taken);
859     } else if (isInt32Constant(node.child2().index())) {
860         SpeculateIntegerOperand op1(this, node.child1());
861         int32_t imm = valueOfInt32Constant(node.child2().index());
862         branch32(condition, op1.gpr(), JITCompiler::Imm32(imm), taken);
863     } else {
864         SpeculateIntegerOperand op1(this, node.child1());
865         SpeculateIntegerOperand op2(this, node.child2());
866         branch32(condition, op1.gpr(), op2.gpr(), taken);
867     }
868
869     jump(notTaken);
870 }
871
872 // Returns true if the compare is fused with a subsequent branch.
873 bool SpeculativeJIT::compilePeepHoleBranch(Node& node, MacroAssembler::RelationalCondition condition, MacroAssembler::DoubleCondition doubleCondition, S_DFGOperation_EJJ operation)
874 {
875     // Fused compare & branch.
876     NodeIndex branchNodeIndex = detectPeepHoleBranch();
877     if (branchNodeIndex != NoNode) {
878         // detectPeepHoleBranch currently only permits the branch to be the very next node,
879         // so can be no intervening nodes to also reference the compare. 
880         ASSERT(node.adjustedRefCount() == 1);
881
882         if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2()))) {
883             compilePeepHoleIntegerBranch(node, branchNodeIndex, condition);
884             use(node.child1());
885             use(node.child2());
886         } else if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2()))) {
887             compilePeepHoleDoubleBranch(node, branchNodeIndex, doubleCondition);
888             use(node.child1());
889             use(node.child2());
890         } else if (node.op == CompareEq && Node::shouldSpeculateFinalObject(at(node.child1()), at(node.child2()))) {
891             compilePeepHoleObjectEquality(node, branchNodeIndex, &JSFinalObject::s_info, isFinalObjectPrediction);
892             use(node.child1());
893             use(node.child2());
894         } else if (node.op == CompareEq && Node::shouldSpeculateArray(at(node.child1()), at(node.child2()))) {
895             compilePeepHoleObjectEquality(node, branchNodeIndex, &JSArray::s_info, isArrayPrediction);
896             use(node.child1());
897             use(node.child2());
898         } else
899             nonSpeculativePeepholeBranch(node, branchNodeIndex, condition, operation);
900
901         m_compileIndex = branchNodeIndex;
902         return true;
903     }
904     return false;
905 }
906
907 void SpeculativeJIT::compileMovHint(Node& node)
908 {
909     ASSERT(node.op == SetLocal);
910     
911     setNodeIndexForOperand(node.child1().index(), node.local());
912     m_lastSetOperand = node.local();
913 }
914
915 void SpeculativeJIT::compile(BasicBlock& block)
916 {
917     ASSERT(m_compileOkay);
918     ASSERT(m_compileIndex == block.begin);
919     
920     if (!block.isReachable) {
921         m_compileIndex = block.end;
922         return;
923     }
924
925     m_blockHeads[m_block] = m_jit.label();
926 #if DFG_ENABLE(JIT_BREAK_ON_EVERY_BLOCK)
927     m_jit.breakpoint();
928 #endif
929
930     ASSERT(m_arguments.size() == block.variablesAtHead.numberOfArguments());
931     for (size_t i = 0; i < m_arguments.size(); ++i) {
932         NodeIndex nodeIndex = block.variablesAtHead.argument(i);
933         if (nodeIndex == NoNode)
934             m_arguments[i] = ValueSource(ValueInRegisterFile);
935         else
936             m_arguments[i] = ValueSource::forPrediction(at(nodeIndex).variableAccessData()->prediction());
937     }
938     
939     m_state.reset();
940     m_state.beginBasicBlock(&block);
941     
942     ASSERT(m_variables.size() == block.variablesAtHead.numberOfLocals());
943     for (size_t i = 0; i < m_variables.size(); ++i) {
944         NodeIndex nodeIndex = block.variablesAtHead.local(i);
945         if (nodeIndex == NoNode)
946             m_variables[i] = ValueSource(ValueInRegisterFile);
947         else if (at(nodeIndex).variableAccessData()->shouldUseDoubleFormat())
948             m_variables[i] = ValueSource(DoubleInRegisterFile);
949         else
950             m_variables[i] = ValueSource::forPrediction(at(nodeIndex).variableAccessData()->prediction());
951     }
952     
953     m_lastSetOperand = std::numeric_limits<int>::max();
954     m_codeOriginForOSR = CodeOrigin();
955     
956     if (DFG_ENABLE_EDGE_CODE_VERIFICATION) {
957         JITCompiler::Jump verificationSucceeded =
958             m_jit.branch32(JITCompiler::Equal, GPRInfo::regT0, Imm32(m_block));
959         m_jit.breakpoint();
960         verificationSucceeded.link(&m_jit);
961     }
962
963     for (; m_compileIndex < block.end; ++m_compileIndex) {
964         Node& node = at(m_compileIndex);
965         m_codeOriginForOSR = node.codeOrigin;
966         if (!node.shouldGenerate()) {
967 #if DFG_ENABLE(DEBUG_VERBOSE)
968             dataLog("SpeculativeJIT skipping Node @%d (bc#%u) at JIT offset 0x%x     ", (int)m_compileIndex, node.codeOrigin.bytecodeIndex, m_jit.debugOffset());
969 #endif
970             switch (node.op) {
971             case SetLocal:
972                 compileMovHint(node);
973                 break;
974
975             case InlineStart: {
976                 InlineCallFrame* inlineCallFrame = node.codeOrigin.inlineCallFrame;
977                 int argumentCountIncludingThis = inlineCallFrame->arguments.size();
978                 for (int i = 0; i < argumentCountIncludingThis; ++i) {
979                     ValueRecovery recovery = computeValueRecoveryFor(m_variables[inlineCallFrame->stackOffset + CallFrame::argumentOffsetIncludingThis(i)]);
980                     // The recovery cannot point to registers, since the call frame reification isn't
981                     // as smart as OSR, so it can't handle that. The exception is the this argument,
982                     // which we don't really need to be able to recover.
983                     ASSERT(!i || !recovery.isInRegisters());
984                     inlineCallFrame->arguments[i] = recovery;
985                 }
986                 break;
987             }
988                 
989             default:
990                 break;
991             }
992         } else {
993             
994 #if DFG_ENABLE(DEBUG_VERBOSE)
995             dataLog("SpeculativeJIT generating Node @%d (bc#%u) at JIT offset 0x%x   ", (int)m_compileIndex, node.codeOrigin.bytecodeIndex, m_jit.debugOffset());
996 #endif
997 #if DFG_ENABLE(JIT_BREAK_ON_EVERY_NODE)
998             m_jit.breakpoint();
999 #endif
1000 #if DFG_ENABLE(XOR_DEBUG_AID)
1001             m_jit.xorPtr(JITCompiler::TrustedImm32(m_compileIndex), GPRInfo::regT0);
1002             m_jit.xorPtr(JITCompiler::TrustedImm32(m_compileIndex), GPRInfo::regT0);
1003 #endif
1004             checkConsistency();
1005             compile(node);
1006             if (!m_compileOkay) {
1007                 m_compileOkay = true;
1008                 m_compileIndex = block.end;
1009                 clearGenerationInfo();
1010                 return;
1011             }
1012             
1013 #if DFG_ENABLE(DEBUG_VERBOSE)
1014             if (node.hasResult()) {
1015                 GenerationInfo& info = m_generationInfo[node.virtualRegister()];
1016                 dataLog("-> %s, vr#%d", dataFormatToString(info.registerFormat()), (int)node.virtualRegister());
1017                 if (info.registerFormat() != DataFormatNone) {
1018                     if (info.registerFormat() == DataFormatDouble)
1019                         dataLog(", %s", FPRInfo::debugName(info.fpr()));
1020 #if USE(JSVALUE32_64)
1021                     else if (info.registerFormat() & DataFormatJS)
1022                         dataLog(", %s %s", GPRInfo::debugName(info.tagGPR()), GPRInfo::debugName(info.payloadGPR()));
1023 #endif
1024                     else
1025                         dataLog(", %s", GPRInfo::debugName(info.gpr()));
1026                 }
1027                 dataLog("    ");
1028             } else
1029                 dataLog("    ");
1030 #endif
1031         }
1032         
1033 #if DFG_ENABLE(VERBOSE_VALUE_RECOVERIES)
1034         for (size_t i = 0; i < m_arguments.size(); ++i)
1035             computeValueRecoveryFor(argumentToOperand(i)).dump(stderr);
1036         
1037         dataLog(" : ");
1038         
1039         for (int operand = 0; operand < (int)m_variables.size(); ++operand)
1040             computeValueRecoveryFor(operand).dump(stderr);
1041 #endif
1042
1043 #if DFG_ENABLE(DEBUG_VERBOSE)
1044         dataLog("\n");
1045 #endif
1046         
1047         // Make sure that the abstract state is rematerialized for the next node.
1048         m_state.execute(m_compileIndex);
1049         
1050         if (node.shouldGenerate())
1051             checkConsistency();
1052     }
1053     
1054     // Perform the most basic verification that children have been used correctly.
1055 #if !ASSERT_DISABLED
1056     for (unsigned index = 0; index < m_generationInfo.size(); ++index) {
1057         GenerationInfo& info = m_generationInfo[index];
1058         ASSERT(!info.alive());
1059     }
1060 #endif
1061 }
1062
1063 // If we are making type predictions about our arguments then
1064 // we need to check that they are correct on function entry.
1065 void SpeculativeJIT::checkArgumentTypes()
1066 {
1067     ASSERT(!m_compileIndex);
1068     m_codeOriginForOSR = CodeOrigin(0);
1069
1070     for (size_t i = 0; i < m_arguments.size(); ++i)
1071         m_arguments[i] = ValueSource(ValueInRegisterFile);
1072     for (size_t i = 0; i < m_variables.size(); ++i)
1073         m_variables[i] = ValueSource(ValueInRegisterFile);
1074     
1075     for (int i = 0; i < m_jit.codeBlock()->numParameters(); ++i) {
1076         VariableAccessData* variableAccessData = at(m_jit.graph().m_arguments[i]).variableAccessData();
1077         VirtualRegister virtualRegister = variableAccessData->local();
1078         PredictedType predictedType = variableAccessData->prediction();
1079 #if USE(JSVALUE64)
1080         if (isInt32Prediction(predictedType))
1081             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::Below, JITCompiler::addressFor(virtualRegister), GPRInfo::tagTypeNumberRegister));
1082         else if (isArrayPrediction(predictedType)) {
1083             GPRTemporary temp(this);
1084             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1085             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
1086             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
1087         } else if (isByteArrayPrediction(predictedType)) {
1088             GPRTemporary temp(this);
1089             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1090             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
1091             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info)));
1092         } else if (isBooleanPrediction(predictedType)) {
1093             GPRTemporary temp(this);
1094             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1095             m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), temp.gpr());
1096             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
1097         } else if (isInt8ArrayPrediction(predictedType)) {
1098             GPRTemporary temp(this);
1099             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1100             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
1101             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int8ArrayDescriptor().m_classInfo)));
1102         } else if (isInt16ArrayPrediction(predictedType)) {
1103             GPRTemporary temp(this);
1104             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1105             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
1106             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int16ArrayDescriptor().m_classInfo)));
1107         } else if (isInt32ArrayPrediction(predictedType)) {
1108             GPRTemporary temp(this);
1109             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1110             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
1111             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int32ArrayDescriptor().m_classInfo)));
1112         } else if (isUint8ArrayPrediction(predictedType)) {
1113             GPRTemporary temp(this);
1114             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1115             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
1116             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ArrayDescriptor().m_classInfo)));
1117         } else if (isUint8ClampedArrayPrediction(predictedType)) {
1118             GPRTemporary temp(this);
1119             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1120             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
1121             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ClampedArrayDescriptor().m_classInfo)));
1122         } else if (isUint16ArrayPrediction(predictedType)) {
1123             GPRTemporary temp(this);
1124             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1125             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
1126             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint16ArrayDescriptor().m_classInfo)));
1127         } else if (isUint32ArrayPrediction(predictedType)) {
1128             GPRTemporary temp(this);
1129             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1130             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
1131             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint32ArrayDescriptor().m_classInfo)));
1132         } else if (isFloat32ArrayPrediction(predictedType)) {
1133             GPRTemporary temp(this);
1134             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1135             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
1136             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float32ArrayDescriptor().m_classInfo)));
1137         } else if (isFloat64ArrayPrediction(predictedType)) {
1138             GPRTemporary temp(this);
1139             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1140             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
1141             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float64ArrayDescriptor().m_classInfo)));
1142         }
1143 #else
1144         if (isInt32Prediction(predictedType))
1145             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag)));
1146         else if (isArrayPrediction(predictedType)) {
1147             GPRTemporary temp(this);
1148             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
1149             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
1150             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
1151             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
1152         } else if (isByteArrayPrediction(predictedType)) {
1153             GPRTemporary temp(this);
1154             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
1155             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
1156             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
1157             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info)));
1158         } else if (isBooleanPrediction(predictedType))
1159             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::BooleanTag)));
1160         else if (isInt8ArrayPrediction(predictedType)) {
1161             GPRTemporary temp(this);
1162             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
1163             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
1164             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
1165             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int8ArrayDescriptor().m_classInfo)));
1166         } else if (isInt16ArrayPrediction(predictedType)) {
1167             GPRTemporary temp(this);
1168             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
1169             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
1170             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
1171             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int16ArrayDescriptor().m_classInfo)));
1172         } else if (isInt32ArrayPrediction(predictedType)) {
1173             GPRTemporary temp(this);
1174             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
1175             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
1176             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
1177             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int32ArrayDescriptor().m_classInfo)));
1178         } else if (isUint8ArrayPrediction(predictedType)) {
1179             GPRTemporary temp(this);
1180             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
1181             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
1182             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
1183             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ArrayDescriptor().m_classInfo)));
1184         } else if (isUint8ClampedArrayPrediction(predictedType)) {
1185             GPRTemporary temp(this);
1186             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
1187             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
1188             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
1189             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ClampedArrayDescriptor().m_classInfo)));
1190         } else if (isUint16ArrayPrediction(predictedType)) {
1191             GPRTemporary temp(this);
1192             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
1193             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
1194             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
1195             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint16ArrayDescriptor().m_classInfo)));
1196         }  else if (isUint32ArrayPrediction(predictedType)) {
1197             GPRTemporary temp(this);
1198             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
1199             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
1200             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
1201             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint32ArrayDescriptor().m_classInfo)));
1202         }  else if (isFloat32ArrayPrediction(predictedType)) {
1203             GPRTemporary temp(this);
1204             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
1205             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
1206             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
1207             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float32ArrayDescriptor().m_classInfo)));
1208         }   else if (isFloat64ArrayPrediction(predictedType)) {
1209             GPRTemporary temp(this);
1210             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
1211             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
1212             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
1213             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float64ArrayDescriptor().m_classInfo)));
1214         } 
1215 #endif
1216     }
1217 }
1218
1219 bool SpeculativeJIT::compile()
1220 {
1221     checkArgumentTypes();
1222
1223     if (DFG_ENABLE_EDGE_CODE_VERIFICATION)
1224         m_jit.move(Imm32(0), GPRInfo::regT0);
1225
1226     ASSERT(!m_compileIndex);
1227     for (m_block = 0; m_block < m_jit.graph().m_blocks.size(); ++m_block)
1228         compile(*m_jit.graph().m_blocks[m_block]);
1229     linkBranches();
1230     return true;
1231 }
1232
1233 void SpeculativeJIT::createOSREntries()
1234 {
1235     for (BlockIndex blockIndex = 0; blockIndex < m_jit.graph().m_blocks.size(); ++blockIndex) {
1236         BasicBlock& block = *m_jit.graph().m_blocks[blockIndex];
1237         if (!block.isOSRTarget)
1238             continue;
1239
1240         // Currently we only need to create OSR entry trampolines when using edge code
1241         // verification. But in the future, we'll need this for other things as well (like
1242         // when we have global reg alloc).
1243         // If we don't need OSR entry trampolin
1244         if (!DFG_ENABLE_EDGE_CODE_VERIFICATION) {
1245             m_osrEntryHeads.append(m_blockHeads[blockIndex]);
1246             continue;
1247         }
1248         
1249         m_osrEntryHeads.append(m_jit.label());
1250         m_jit.move(Imm32(blockIndex), GPRInfo::regT0);
1251         m_jit.jump().linkTo(m_blockHeads[blockIndex], &m_jit);
1252     }
1253 }
1254
1255 void SpeculativeJIT::linkOSREntries(LinkBuffer& linkBuffer)
1256 {
1257     unsigned osrEntryIndex = 0;
1258     for (BlockIndex blockIndex = 0; blockIndex < m_jit.graph().m_blocks.size(); ++blockIndex) {
1259         BasicBlock& block = *m_jit.graph().m_blocks[blockIndex];
1260         if (block.isOSRTarget)
1261             m_jit.noticeOSREntry(block, m_osrEntryHeads[osrEntryIndex++], linkBuffer);
1262     }
1263     ASSERT(osrEntryIndex == m_osrEntryHeads.size());
1264 }
1265
1266 ValueRecovery SpeculativeJIT::computeValueRecoveryFor(const ValueSource& valueSource)
1267 {
1268     switch (valueSource.kind()) {
1269     case ValueInRegisterFile:
1270         return ValueRecovery::alreadyInRegisterFile();
1271         
1272     case Int32InRegisterFile:
1273         return ValueRecovery::alreadyInRegisterFileAsUnboxedInt32();
1274
1275     case CellInRegisterFile:
1276         return ValueRecovery::alreadyInRegisterFileAsUnboxedCell();
1277
1278     case BooleanInRegisterFile:
1279         return ValueRecovery::alreadyInRegisterFileAsUnboxedBoolean();
1280         
1281     case DoubleInRegisterFile:
1282         return ValueRecovery::alreadyInRegisterFileAsUnboxedDouble();
1283
1284     case HaveNode: {
1285         if (m_jit.isConstant(valueSource.nodeIndex()))
1286             return ValueRecovery::constant(m_jit.valueOfJSConstant(valueSource.nodeIndex()));
1287     
1288         Node* nodePtr = &at(valueSource.nodeIndex());
1289         if (!nodePtr->shouldGenerate()) {
1290             // It's legitimately dead. As in, nobody will ever use this node, or operand,
1291             // ever. Set it to Undefined to make the GC happy after the OSR.
1292             return ValueRecovery::constant(jsUndefined());
1293         }
1294     
1295         GenerationInfo* infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
1296         if (!infoPtr->alive() || infoPtr->nodeIndex() != valueSource.nodeIndex()) {
1297             // Try to see if there is an alternate node that would contain the value we want.
1298             // There are four possibilities:
1299             //
1300             // ValueToInt32: If the only remaining live version of the value is
1301             //    ValueToInt32, then we can use it.
1302             //
1303             // UInt32ToNumber: If the only live version of the value is a UInt32ToNumber
1304             //    then the only remaining uses are ones that want a properly formed number
1305             //    rather than a UInt32 intermediate.
1306             //
1307             // The reverse of the above: This node could be a UInt32ToNumber, but its
1308             //    alternative is still alive. This means that the only remaining uses of
1309             //    the number would be fine with a UInt32 intermediate.
1310         
1311             bool found = false;
1312         
1313             if (nodePtr->op == UInt32ToNumber) {
1314                 NodeIndex nodeIndex = nodePtr->child1().index();
1315                 nodePtr = &at(nodeIndex);
1316                 infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
1317                 if (infoPtr->alive() && infoPtr->nodeIndex() == nodeIndex)
1318                     found = true;
1319             }
1320         
1321             if (!found) {
1322                 NodeIndex valueToInt32Index = NoNode;
1323                 NodeIndex uint32ToNumberIndex = NoNode;
1324             
1325                 for (unsigned virtualRegister = 0; virtualRegister < m_generationInfo.size(); ++virtualRegister) {
1326                     GenerationInfo& info = m_generationInfo[virtualRegister];
1327                     if (!info.alive())
1328                         continue;
1329                     if (info.nodeIndex() == NoNode)
1330                         continue;
1331                     Node& node = at(info.nodeIndex());
1332                     if (node.child1Unchecked() != valueSource.nodeIndex())
1333                         continue;
1334                     switch (node.op) {
1335                     case ValueToInt32:
1336                         valueToInt32Index = info.nodeIndex();
1337                         break;
1338                     case UInt32ToNumber:
1339                         uint32ToNumberIndex = info.nodeIndex();
1340                         break;
1341                     default:
1342                         break;
1343                     }
1344                 }
1345             
1346                 NodeIndex nodeIndexToUse;
1347                 if (valueToInt32Index != NoNode)
1348                     nodeIndexToUse = valueToInt32Index;
1349                 else if (uint32ToNumberIndex != NoNode)
1350                     nodeIndexToUse = uint32ToNumberIndex;
1351                 else
1352                     nodeIndexToUse = NoNode;
1353             
1354                 if (nodeIndexToUse != NoNode) {
1355                     nodePtr = &at(nodeIndexToUse);
1356                     infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
1357                     ASSERT(infoPtr->alive() && infoPtr->nodeIndex() == nodeIndexToUse);
1358                     found = true;
1359                 }
1360             }
1361         
1362             if (!found)
1363                 return ValueRecovery::constant(jsUndefined());
1364         }
1365     
1366         ASSERT(infoPtr->alive());
1367
1368         if (infoPtr->registerFormat() != DataFormatNone) {
1369             if (infoPtr->registerFormat() == DataFormatDouble)
1370                 return ValueRecovery::inFPR(infoPtr->fpr());
1371 #if USE(JSVALUE32_64)
1372             if (infoPtr->registerFormat() & DataFormatJS)
1373                 return ValueRecovery::inPair(infoPtr->tagGPR(), infoPtr->payloadGPR());
1374 #endif
1375             return ValueRecovery::inGPR(infoPtr->gpr(), infoPtr->registerFormat());
1376         }
1377         if (infoPtr->spillFormat() != DataFormatNone)
1378             return ValueRecovery::displacedInRegisterFile(static_cast<VirtualRegister>(nodePtr->virtualRegister()), infoPtr->spillFormat());
1379     
1380         ASSERT_NOT_REACHED();
1381         return ValueRecovery();
1382     }
1383         
1384     default:
1385         ASSERT_NOT_REACHED();
1386         return ValueRecovery();
1387     }
1388 }
1389
1390 void SpeculativeJIT::compileGetCharCodeAt(Node& node)
1391 {
1392     ASSERT(node.child3() == NoNode);
1393     SpeculateCellOperand string(this, node.child1());
1394     SpeculateStrictInt32Operand index(this, node.child2());
1395     StorageOperand storage(this, node.child3());
1396
1397     GPRReg stringReg = string.gpr();
1398     GPRReg indexReg = index.gpr();
1399     GPRReg storageReg = storage.gpr();
1400     
1401     if (!isStringPrediction(m_state.forNode(node.child1()).m_type)) {
1402         ASSERT(!(at(node.child1()).prediction() & PredictString));
1403         terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
1404         noResult(m_compileIndex);
1405         return;
1406     }
1407
1408     // unsigned comparison so we can filter out negative indices and indices that are too large
1409     speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, indexReg, MacroAssembler::Address(stringReg, JSString::offsetOfLength())));
1410
1411     GPRTemporary scratch(this);
1412     GPRReg scratchReg = scratch.gpr();
1413
1414     m_jit.loadPtr(MacroAssembler::Address(stringReg, JSString::offsetOfValue()), scratchReg);
1415
1416     // Load the character into scratchReg
1417     JITCompiler::Jump is16Bit = m_jit.branchTest32(MacroAssembler::Zero, MacroAssembler::Address(scratchReg, StringImpl::flagsOffset()), TrustedImm32(StringImpl::flagIs8Bit()));
1418
1419     m_jit.load8(MacroAssembler::BaseIndex(storageReg, indexReg, MacroAssembler::TimesOne, 0), scratchReg);
1420     JITCompiler::Jump cont8Bit = m_jit.jump();
1421
1422     is16Bit.link(&m_jit);
1423
1424     m_jit.load16(MacroAssembler::BaseIndex(storageReg, indexReg, MacroAssembler::TimesTwo, 0), scratchReg);
1425
1426     cont8Bit.link(&m_jit);
1427
1428     integerResult(scratchReg, m_compileIndex);
1429 }
1430
1431 void SpeculativeJIT::compileGetByValOnString(Node& node)
1432 {
1433     SpeculateCellOperand base(this, node.child1());
1434     SpeculateStrictInt32Operand property(this, node.child2());
1435     StorageOperand storage(this, node.child3());
1436     GPRReg baseReg = base.gpr();
1437     GPRReg propertyReg = property.gpr();
1438     GPRReg storageReg = storage.gpr();
1439
1440     if (!isStringPrediction(m_state.forNode(node.child1()).m_type)) {
1441         ASSERT(!(at(node.child1()).prediction() & PredictString));
1442         terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
1443         noResult(m_compileIndex);
1444         return;
1445     }
1446
1447     // unsigned comparison so we can filter out negative indices and indices that are too large
1448     speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSString::offsetOfLength())));
1449
1450     GPRTemporary scratch(this);
1451     GPRReg scratchReg = scratch.gpr();
1452
1453     m_jit.loadPtr(MacroAssembler::Address(baseReg, JSString::offsetOfValue()), scratchReg);
1454
1455     // Load the character into scratchReg
1456     JITCompiler::Jump is16Bit = m_jit.branchTest32(MacroAssembler::Zero, MacroAssembler::Address(scratchReg, StringImpl::flagsOffset()), TrustedImm32(StringImpl::flagIs8Bit()));
1457
1458     m_jit.load8(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne, 0), scratchReg);
1459     JITCompiler::Jump cont8Bit = m_jit.jump();
1460
1461     is16Bit.link(&m_jit);
1462
1463     m_jit.load16(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesTwo, 0), scratchReg);
1464
1465     // We only support ascii characters
1466     speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, scratchReg, TrustedImm32(0x100)));
1467
1468     // 8 bit string values don't need the isASCII check.
1469     cont8Bit.link(&m_jit);
1470
1471     GPRTemporary smallStrings(this);
1472     GPRReg smallStringsReg = smallStrings.gpr();
1473     m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.globalData()->smallStrings.singleCharacterStrings()), smallStringsReg);
1474     m_jit.loadPtr(MacroAssembler::BaseIndex(smallStringsReg, scratchReg, MacroAssembler::ScalePtr, 0), scratchReg);
1475     speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTest32(MacroAssembler::Zero, scratchReg));
1476     cellResult(scratchReg, m_compileIndex);
1477 }
1478
1479 void SpeculativeJIT::compileValueToInt32(Node& node)
1480 {
1481     if (at(node.child1()).shouldNotSpeculateInteger()) {
1482         if (at(node.child1()).shouldSpeculateDouble()) {
1483             SpeculateDoubleOperand op1(this, node.child1());
1484             GPRTemporary result(this);
1485             FPRReg fpr = op1.fpr();
1486             GPRReg gpr = result.gpr();
1487             JITCompiler::Jump truncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateSuccessful);
1488             
1489             silentSpillAllRegisters(gpr);
1490             callOperation(toInt32, gpr, fpr);
1491             silentFillAllRegisters(gpr);
1492             
1493             truncatedToInteger.link(&m_jit);
1494             integerResult(gpr, m_compileIndex);
1495             return;
1496         }
1497         // Do it the safe way.
1498         nonSpeculativeValueToInt32(node);
1499         return;
1500     }
1501     
1502     SpeculateIntegerOperand op1(this, node.child1());
1503     GPRTemporary result(this, op1);
1504     m_jit.move(op1.gpr(), result.gpr());
1505     integerResult(result.gpr(), m_compileIndex, op1.format());
1506 }
1507
1508 void SpeculativeJIT::compileUInt32ToNumber(Node& node)
1509 {
1510     if (!nodeCanSpeculateInteger(node.arithNodeFlags())) {
1511         // We know that this sometimes produces doubles. So produce a double every
1512         // time. This at least allows subsequent code to not have weird conditionals.
1513             
1514         IntegerOperand op1(this, node.child1());
1515         FPRTemporary result(this);
1516             
1517         GPRReg inputGPR = op1.gpr();
1518         FPRReg outputFPR = result.fpr();
1519             
1520         m_jit.convertInt32ToDouble(inputGPR, outputFPR);
1521             
1522         JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, inputGPR, TrustedImm32(0));
1523         m_jit.addDouble(JITCompiler::AbsoluteAddress(&AssemblyHelpers::twoToThe32), outputFPR);
1524         positive.link(&m_jit);
1525             
1526         doubleResult(outputFPR, m_compileIndex);
1527         return;
1528     }
1529
1530     IntegerOperand op1(this, node.child1());
1531     GPRTemporary result(this, op1);
1532
1533     // Test the operand is positive. This is a very special speculation check - we actually
1534     // use roll-forward speculation here, where if this fails, we jump to the baseline
1535     // instruction that follows us, rather than the one we're executing right now. We have
1536     // to do this because by this point, the original values necessary to compile whatever
1537     // operation the UInt32ToNumber originated from might be dead.
1538     speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, op1.gpr(), TrustedImm32(0)));
1539         
1540     // Verify that we can do roll forward.
1541     ASSERT(at(m_compileIndex + 1).op == SetLocal);
1542     ASSERT(at(m_compileIndex + 1).codeOrigin == node.codeOrigin);
1543     ASSERT(at(m_compileIndex + 2).codeOrigin != node.codeOrigin);
1544         
1545     // Now do the magic.
1546     OSRExit& exit = m_jit.codeBlock()->lastOSRExit();
1547     Node& setLocal = at(m_compileIndex + 1);
1548     exit.m_codeOrigin = at(m_compileIndex + 2).codeOrigin;
1549     exit.m_lastSetOperand = setLocal.local();
1550         
1551     // Create the value recovery, and stuff it into the right place.
1552     exit.valueRecoveryForOperand(setLocal.local()) = ValueRecovery::uint32InGPR(op1.gpr());
1553
1554     m_jit.move(op1.gpr(), result.gpr());
1555     integerResult(result.gpr(), m_compileIndex, op1.format());
1556 }
1557
1558 static double clampDoubleToByte(double d)
1559 {
1560     d += 0.5;
1561     if (!(d > 0))
1562         d = 0;
1563     else if (d > 255)
1564         d = 255;
1565     return d;
1566 }
1567
1568 static void compileClampIntegerToByte(JITCompiler& jit, GPRReg result)
1569 {
1570     MacroAssembler::Jump inBounds = jit.branch32(MacroAssembler::BelowOrEqual, result, JITCompiler::TrustedImm32(0xff));
1571     MacroAssembler::Jump tooBig = jit.branch32(MacroAssembler::GreaterThan, result, JITCompiler::TrustedImm32(0xff));
1572     jit.xorPtr(result, result);
1573     MacroAssembler::Jump clamped = jit.jump();
1574     tooBig.link(&jit);
1575     jit.move(JITCompiler::TrustedImm32(255), result);
1576     clamped.link(&jit);
1577     inBounds.link(&jit);
1578 }
1579
1580 static void compileClampDoubleToByte(JITCompiler& jit, GPRReg result, FPRReg source, FPRReg scratch)
1581 {
1582     // Unordered compare so we pick up NaN
1583     static const double zero = 0;
1584     static const double byteMax = 255;
1585     static const double half = 0.5;
1586     jit.loadDouble(&zero, scratch);
1587     MacroAssembler::Jump tooSmall = jit.branchDouble(MacroAssembler::DoubleLessThanOrEqualOrUnordered, source, scratch);
1588     jit.loadDouble(&byteMax, scratch);
1589     MacroAssembler::Jump tooBig = jit.branchDouble(MacroAssembler::DoubleGreaterThan, source, scratch);
1590     
1591     jit.loadDouble(&half, scratch);
1592     // FIXME: This should probably just use a floating point round!
1593     // https://bugs.webkit.org/show_bug.cgi?id=72054
1594     jit.addDouble(source, scratch);
1595     jit.truncateDoubleToInt32(scratch, result);   
1596     MacroAssembler::Jump truncatedInt = jit.jump();
1597     
1598     tooSmall.link(&jit);
1599     jit.xorPtr(result, result);
1600     MacroAssembler::Jump zeroed = jit.jump();
1601     
1602     tooBig.link(&jit);
1603     jit.move(JITCompiler::TrustedImm32(255), result);
1604     
1605     truncatedInt.link(&jit);
1606     zeroed.link(&jit);
1607
1608 }
1609
1610 void SpeculativeJIT::compilePutByValForByteArray(GPRReg base, GPRReg property, Node& node)
1611 {
1612     NodeUse baseUse = node.child1();
1613     NodeUse valueUse = node.child3();
1614     
1615     if (!isByteArrayPrediction(m_state.forNode(baseUse).m_type))
1616         speculationCheck(BadType, JSValueSource::unboxedCell(base), baseUse.index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info)));
1617     GPRTemporary value;
1618     GPRReg valueGPR;
1619
1620     if (at(valueUse).isConstant()) {
1621         JSValue jsValue = valueOfJSConstant(valueUse.index());
1622         if (!jsValue.isNumber()) {
1623             terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
1624             noResult(m_compileIndex);
1625             return;
1626         }
1627         int clampedValue = clampDoubleToByte(jsValue.asNumber());
1628         GPRTemporary scratch(this);
1629         GPRReg scratchReg = scratch.gpr();
1630         m_jit.move(Imm32(clampedValue), scratchReg);
1631         value.adopt(scratch);
1632         valueGPR = scratchReg;
1633     } else if (!at(valueUse).shouldNotSpeculateInteger()) {
1634         SpeculateIntegerOperand valueOp(this, valueUse);
1635         GPRTemporary scratch(this);
1636         GPRReg scratchReg = scratch.gpr();
1637         m_jit.move(valueOp.gpr(), scratchReg);
1638         compileClampIntegerToByte(m_jit, scratchReg);
1639         value.adopt(scratch);
1640         valueGPR = scratchReg;
1641     } else {
1642         SpeculateDoubleOperand valueOp(this, valueUse);
1643         GPRTemporary result(this);
1644         FPRTemporary floatScratch(this);
1645         FPRReg fpr = valueOp.fpr();
1646         GPRReg gpr = result.gpr();
1647         compileClampDoubleToByte(m_jit, gpr, fpr, floatScratch.fpr());
1648         value.adopt(result);
1649         valueGPR = gpr;
1650     }
1651     ASSERT_UNUSED(valueGPR, valueGPR != property);
1652     ASSERT(valueGPR != base);
1653     GPRTemporary storage(this);
1654     GPRReg storageReg = storage.gpr();
1655     ASSERT(valueGPR != storageReg);
1656     m_jit.loadPtr(MacroAssembler::Address(base, JSByteArray::offsetOfStorage()), storageReg);
1657     MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, property, MacroAssembler::Address(storageReg, ByteArray::offsetOfSize()));
1658     m_jit.store8(value.gpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesOne, ByteArray::offsetOfData()));
1659     outOfBounds.link(&m_jit);
1660     noResult(m_compileIndex);
1661 }
1662
1663 void SpeculativeJIT::compileGetByValOnByteArray(Node& node)
1664 {
1665     SpeculateCellOperand base(this, node.child1());
1666     SpeculateStrictInt32Operand property(this, node.child2());
1667
1668     GPRReg baseReg = base.gpr();
1669     GPRReg propertyReg = property.gpr();
1670
1671     if (!isByteArrayPrediction(m_state.forNode(node.child1()).m_type)) {
1672         terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
1673         noResult(m_compileIndex);
1674         return;
1675     }
1676
1677     // Load the character into scratchReg
1678     GPRTemporary storage(this);
1679     GPRReg storageReg = storage.gpr();
1680     m_jit.loadPtr(MacroAssembler::Address(baseReg, JSByteArray::offsetOfStorage()), storageReg);
1681     
1682     // unsigned comparison so we can filter out negative indices and indices that are too large
1683     speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ByteArray::offsetOfSize())));
1684
1685     m_jit.load8(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne, ByteArray::offsetOfData()), storageReg);
1686     integerResult(storageReg, m_compileIndex);
1687 }
1688
1689 void SpeculativeJIT::compileGetTypedArrayLength(const TypedArrayDescriptor& descriptor, Node& node, bool needsSpeculationCheck)
1690 {
1691     SpeculateCellOperand base(this, node.child1());
1692     GPRTemporary result(this);
1693     
1694     GPRReg baseGPR = base.gpr();
1695     GPRReg resultGPR = result.gpr();
1696     
1697     if (needsSpeculationCheck)
1698         speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
1699     
1700     m_jit.load32(MacroAssembler::Address(baseGPR, descriptor.m_lengthOffset), resultGPR);
1701     
1702     integerResult(resultGPR, m_compileIndex);
1703 }
1704
1705 void SpeculativeJIT::compileGetByValOnIntTypedArray(const TypedArrayDescriptor& descriptor, Node& node, size_t elementSize, TypedArraySpeculationRequirements speculationRequirements, TypedArraySignedness signedness)
1706 {
1707     SpeculateCellOperand base(this, node.child1());
1708     SpeculateStrictInt32Operand property(this, node.child2());
1709     StorageOperand storage(this, node.child3());
1710
1711     GPRReg baseReg = base.gpr();
1712     GPRReg propertyReg = property.gpr();
1713     GPRReg storageReg = storage.gpr();
1714
1715     GPRTemporary result(this);
1716     GPRReg resultReg = result.gpr();
1717
1718     if (speculationRequirements != NoTypedArrayTypeSpecCheck) {
1719         ASSERT_NOT_REACHED();
1720         terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
1721         noResult(m_compileIndex);
1722         return;
1723     }
1724
1725     MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(baseReg, descriptor.m_lengthOffset));
1726     m_jit.xorPtr(resultReg, resultReg);
1727     MacroAssembler::Jump outOfBounds = m_jit.jump();
1728     inBounds.link(&m_jit);
1729     switch (elementSize) {
1730     case 1:
1731         if (signedness == SignedTypedArray)
1732             m_jit.load8Signed(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne), resultReg);
1733         else
1734             m_jit.load8(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne), resultReg);
1735         break;
1736     case 2:
1737         if (signedness == SignedTypedArray)
1738             m_jit.load16Signed(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesTwo), resultReg);
1739         else
1740             m_jit.load16(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesTwo), resultReg);
1741         break;
1742     case 4:
1743         m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesFour), resultReg);
1744         break;
1745     default:
1746         ASSERT_NOT_REACHED();
1747     }
1748     outOfBounds.link(&m_jit);
1749     if (elementSize < 4 || signedness == SignedTypedArray)
1750         integerResult(resultReg, m_compileIndex);
1751     else {
1752         FPRTemporary fresult(this);
1753         m_jit.convertInt32ToDouble(resultReg, fresult.fpr());
1754         JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, resultReg, TrustedImm32(0));
1755         m_jit.addDouble(JITCompiler::AbsoluteAddress(&AssemblyHelpers::twoToThe32), fresult.fpr());
1756         positive.link(&m_jit);
1757         doubleResult(fresult.fpr(), m_compileIndex);
1758     }
1759 }
1760
1761 void SpeculativeJIT::compilePutByValForIntTypedArray(const TypedArrayDescriptor& descriptor, GPRReg base, GPRReg property, Node& node, size_t elementSize, TypedArraySpeculationRequirements speculationRequirements, TypedArraySignedness signedness, TypedArrayRounding rounding)
1762 {
1763     NodeUse baseUse = node.child1();
1764     NodeUse valueUse = node.child3();
1765     
1766     if (speculationRequirements != NoTypedArrayTypeSpecCheck)
1767         speculationCheck(BadType, JSValueSource::unboxedCell(base), baseUse, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
1768     GPRTemporary value;
1769     GPRReg valueGPR;
1770     
1771     if (at(valueUse).isConstant()) {
1772         JSValue jsValue = valueOfJSConstant(valueUse.index());
1773         if (!jsValue.isNumber()) {
1774             terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
1775             noResult(m_compileIndex);
1776             return;
1777         }
1778         double d = jsValue.asNumber();
1779         if (rounding == ClampRounding) {
1780             ASSERT(elementSize == 1);
1781             d = clampDoubleToByte(d);
1782         }
1783         GPRTemporary scratch(this);
1784         GPRReg scratchReg = scratch.gpr();
1785         m_jit.move(Imm32(static_cast<int>(d)), scratchReg);
1786         value.adopt(scratch);
1787         valueGPR = scratchReg;
1788     } else if (!at(valueUse).shouldNotSpeculateInteger()) {
1789         SpeculateIntegerOperand valueOp(this, valueUse);
1790         GPRTemporary scratch(this);
1791         GPRReg scratchReg = scratch.gpr();
1792         m_jit.move(valueOp.gpr(), scratchReg);
1793         if (rounding == ClampRounding) {
1794             ASSERT(elementSize == 1);
1795             compileClampIntegerToByte(m_jit, scratchReg);
1796         }
1797         value.adopt(scratch);
1798         valueGPR = scratchReg;
1799     } else if (rounding == ClampRounding) {
1800         ASSERT(elementSize == 1);
1801         SpeculateDoubleOperand valueOp(this, valueUse);
1802         GPRTemporary result(this);
1803         FPRTemporary floatScratch(this);
1804         FPRReg fpr = valueOp.fpr();
1805         GPRReg gpr = result.gpr();
1806         compileClampDoubleToByte(m_jit, gpr, fpr, floatScratch.fpr());
1807         value.adopt(result);
1808         valueGPR = gpr;
1809     } else {
1810         SpeculateDoubleOperand valueOp(this, valueUse);
1811         GPRTemporary result(this);
1812         FPRReg fpr = valueOp.fpr();
1813         GPRReg gpr = result.gpr();
1814         MacroAssembler::Jump notNaN = m_jit.branchDouble(MacroAssembler::DoubleEqual, fpr, fpr);
1815         m_jit.xorPtr(gpr, gpr);
1816         MacroAssembler::Jump fixed = m_jit.jump();
1817         notNaN.link(&m_jit);
1818
1819         MacroAssembler::Jump done;
1820         if (signedness == SignedTypedArray)
1821             done = m_jit.branchTruncateDoubleToInt32(fpr, gpr, MacroAssembler::BranchIfTruncateSuccessful);
1822         else
1823             done = m_jit.branchTruncateDoubleToUint32(fpr, gpr, MacroAssembler::BranchIfTruncateSuccessful);
1824
1825         silentSpillAllRegisters(gpr);
1826         callOperation(toInt32, gpr, fpr);
1827         silentFillAllRegisters(gpr);
1828
1829         done.link(&m_jit);
1830         fixed.link(&m_jit);
1831         value.adopt(result);
1832         valueGPR = gpr;
1833     }
1834     ASSERT_UNUSED(valueGPR, valueGPR != property);
1835     ASSERT(valueGPR != base);
1836     GPRTemporary storage(this);
1837     GPRReg storageReg = storage.gpr();
1838     ASSERT(valueGPR != storageReg);
1839     m_jit.loadPtr(MacroAssembler::Address(base, descriptor.m_storageOffset), storageReg);
1840     MacroAssembler::Jump outOfBounds;
1841     if (speculationRequirements != NoTypedArraySpecCheck)
1842         outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, property, MacroAssembler::Address(base, descriptor.m_lengthOffset));
1843
1844     switch (elementSize) {
1845     case 1:
1846         m_jit.store8(value.gpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesOne));
1847         break;
1848     case 2:
1849         m_jit.store16(value.gpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesTwo));
1850         break;
1851     case 4:
1852         m_jit.store32(value.gpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesFour));
1853         break;
1854     default:
1855         ASSERT_NOT_REACHED();
1856     }
1857     if (speculationRequirements != NoTypedArraySpecCheck)
1858         outOfBounds.link(&m_jit);
1859     noResult(m_compileIndex);
1860 }
1861
1862 void SpeculativeJIT::compileGetByValOnFloatTypedArray(const TypedArrayDescriptor& descriptor, Node& node, size_t elementSize, TypedArraySpeculationRequirements speculationRequirements)
1863 {
1864     SpeculateCellOperand base(this, node.child1());
1865     SpeculateStrictInt32Operand property(this, node.child2());
1866     StorageOperand storage(this, node.child3());
1867
1868     GPRReg baseReg = base.gpr();
1869     GPRReg propertyReg = property.gpr();
1870     GPRReg storageReg = storage.gpr();
1871     
1872     if (speculationRequirements != NoTypedArrayTypeSpecCheck) {
1873         ASSERT_NOT_REACHED();
1874         terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
1875         noResult(m_compileIndex);
1876         return;
1877     }
1878
1879     FPRTemporary result(this);
1880     FPRReg resultReg = result.fpr();
1881     ASSERT(speculationRequirements != NoTypedArraySpecCheck);
1882     MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(baseReg, descriptor.m_lengthOffset));
1883     static const double zero = 0;
1884     m_jit.loadDouble(&zero, resultReg);
1885     MacroAssembler::Jump outOfBounds = m_jit.jump();
1886     inBounds.link(&m_jit);
1887     switch (elementSize) {
1888     case 4:
1889         m_jit.loadFloat(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesFour), resultReg);
1890         m_jit.convertFloatToDouble(resultReg, resultReg);
1891         break;
1892     case 8: {
1893         m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
1894         MacroAssembler::Jump notNaN = m_jit.branchDouble(MacroAssembler::DoubleEqual, resultReg, resultReg);
1895         static const double NaN = std::numeric_limits<double>::quiet_NaN();
1896         m_jit.loadDouble(&NaN, resultReg);
1897         notNaN.link(&m_jit);
1898         break;
1899     }
1900     default:
1901         ASSERT_NOT_REACHED();
1902     }
1903     outOfBounds.link(&m_jit);
1904     doubleResult(resultReg, m_compileIndex);
1905 }
1906
1907 void SpeculativeJIT::compilePutByValForFloatTypedArray(const TypedArrayDescriptor& descriptor, GPRReg base, GPRReg property, Node& node, size_t elementSize, TypedArraySpeculationRequirements speculationRequirements)
1908 {
1909     NodeUse baseUse = node.child1();
1910     NodeUse valueUse = node.child3();
1911     
1912     SpeculateDoubleOperand valueOp(this, valueUse);
1913     
1914     if (speculationRequirements != NoTypedArrayTypeSpecCheck)
1915         speculationCheck(BadType, JSValueSource::unboxedCell(base), baseUse.index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
1916     
1917     GPRTemporary result(this);
1918     
1919     GPRTemporary storage(this);
1920     GPRReg storageReg = storage.gpr();
1921     
1922     m_jit.loadPtr(MacroAssembler::Address(base, descriptor.m_storageOffset), storageReg);
1923     MacroAssembler::Jump outOfBounds;
1924     if (speculationRequirements != NoTypedArraySpecCheck)
1925         outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, property, MacroAssembler::Address(base, descriptor.m_lengthOffset));
1926     
1927     switch (elementSize) {
1928     case 4: {
1929         FPRTemporary scratch(this);
1930         m_jit.moveDouble(valueOp.fpr(), scratch.fpr());
1931         m_jit.convertDoubleToFloat(valueOp.fpr(), scratch.fpr());
1932         m_jit.storeFloat(scratch.fpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesFour));
1933         break;
1934     }
1935     case 8:
1936         m_jit.storeDouble(valueOp.fpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesEight));
1937         break;
1938     default:
1939         ASSERT_NOT_REACHED();
1940     }
1941     if (speculationRequirements != NoTypedArraySpecCheck)
1942         outOfBounds.link(&m_jit);
1943     noResult(m_compileIndex);
1944 }
1945
1946 void SpeculativeJIT::compileInstanceOfForObject(Node&, GPRReg valueReg, GPRReg prototypeReg, GPRReg scratchReg)
1947 {
1948     // Check that prototype is an object.
1949     m_jit.loadPtr(MacroAssembler::Address(prototypeReg, JSCell::structureOffset()), scratchReg);
1950     speculationCheck(BadType, JSValueRegs(), NoNode, m_jit.branchIfNotObject(scratchReg));
1951     
1952     // Initialize scratchReg with the value being checked.
1953     m_jit.move(valueReg, scratchReg);
1954     
1955     // Walk up the prototype chain of the value (in scratchReg), comparing to prototypeReg.
1956     MacroAssembler::Label loop(&m_jit);
1957     m_jit.loadPtr(MacroAssembler::Address(scratchReg, JSCell::structureOffset()), scratchReg);
1958 #if USE(JSVALUE64)
1959     m_jit.loadPtr(MacroAssembler::Address(scratchReg, Structure::prototypeOffset()), scratchReg);
1960 #else
1961     m_jit.load32(MacroAssembler::Address(scratchReg, Structure::prototypeOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), scratchReg);
1962 #endif
1963     MacroAssembler::Jump isInstance = m_jit.branchPtr(MacroAssembler::Equal, scratchReg, prototypeReg);
1964 #if USE(JSVALUE64)
1965     m_jit.branchTestPtr(MacroAssembler::Zero, scratchReg, GPRInfo::tagMaskRegister).linkTo(loop, &m_jit);
1966 #else
1967     m_jit.branchTest32(MacroAssembler::NonZero, scratchReg).linkTo(loop, &m_jit);
1968 #endif
1969     
1970     // No match - result is false.
1971 #if USE(JSVALUE64)
1972     m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(false))), scratchReg);
1973 #else
1974     m_jit.move(MacroAssembler::TrustedImm32(0), scratchReg);
1975 #endif
1976     MacroAssembler::Jump putResult = m_jit.jump();
1977     
1978     isInstance.link(&m_jit);
1979 #if USE(JSVALUE64)
1980     m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(true))), scratchReg);
1981 #else
1982     m_jit.move(MacroAssembler::TrustedImm32(1), scratchReg);
1983 #endif
1984     
1985     putResult.link(&m_jit);
1986 }
1987
1988 void SpeculativeJIT::compileInstanceOf(Node& node)
1989 {
1990     if (!!(at(node.child1()).prediction() & ~PredictCell) && !!(m_state.forNode(node.child1()).m_type & ~PredictCell)) {
1991         // It might not be a cell. Speculate less aggressively.
1992         
1993         JSValueOperand value(this, node.child1());
1994         SpeculateCellOperand prototype(this, node.child3());
1995         GPRTemporary scratch(this);
1996         
1997         GPRReg prototypeReg = prototype.gpr();
1998         GPRReg scratchReg = scratch.gpr();
1999         
2000 #if USE(JSVALUE64)
2001         GPRReg valueReg = value.gpr();
2002         MacroAssembler::Jump isCell = m_jit.branchTestPtr(MacroAssembler::Zero, valueReg, GPRInfo::tagMaskRegister);
2003         m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(false))), scratchReg);
2004 #else
2005         GPRReg valueTagReg = value.tagGPR();
2006         GPRReg valueReg = value.payloadGPR();
2007         MacroAssembler::Jump isCell = m_jit.branch32(MacroAssembler::Equal, valueTagReg, TrustedImm32(JSValue::CellTag));
2008         m_jit.move(MacroAssembler::TrustedImm32(0), scratchReg);
2009 #endif
2010
2011         MacroAssembler::Jump done = m_jit.jump();
2012         
2013         isCell.link(&m_jit);
2014         
2015         compileInstanceOfForObject(node, valueReg, prototypeReg, scratchReg);
2016         
2017         done.link(&m_jit);
2018
2019 #if USE(JSVALUE64)
2020         jsValueResult(scratchReg, m_compileIndex, DataFormatJSBoolean);
2021 #else
2022         booleanResult(scratchReg, m_compileIndex);
2023 #endif
2024         return;
2025     }
2026     
2027     SpeculateCellOperand value(this, node.child1());
2028     // Base unused since we speculate default InstanceOf behaviour in CheckHasInstance.
2029     SpeculateCellOperand prototype(this, node.child3());
2030     
2031     GPRTemporary scratch(this);
2032     
2033     GPRReg valueReg = value.gpr();
2034     GPRReg prototypeReg = prototype.gpr();
2035     GPRReg scratchReg = scratch.gpr();
2036     
2037     compileInstanceOfForObject(node, valueReg, prototypeReg, scratchReg);
2038
2039 #if USE(JSVALUE64)
2040     jsValueResult(scratchReg, m_compileIndex, DataFormatJSBoolean);
2041 #else
2042     booleanResult(scratchReg, m_compileIndex);
2043 #endif
2044 }
2045
2046 static bool isPowerOfTwo(int32_t num)
2047 {
2048     return num && !(num & (num - 1));
2049 }
2050
2051 void SpeculativeJIT::compileSoftModulo(Node& node)
2052 {
2053     bool shouldGeneratePowerOfTwoCheck = true;
2054
2055     // In the fast path, the dividend value could be the final result
2056     // (in case of |dividend| < |divisor|), so we speculate it as strict int32.
2057     SpeculateStrictInt32Operand op1(this, node.child1());
2058     GPRReg op1Gpr = op1.gpr();
2059
2060     if (isInt32Constant(node.child2().index())) {
2061         int32_t divisor = valueOfInt32Constant(node.child2().index());
2062         if (divisor < 0)
2063             divisor = -divisor;
2064
2065         if (isPowerOfTwo(divisor)) {
2066             GPRTemporary result(this);
2067             GPRReg resultGPR = result.gpr();
2068             m_jit.move(op1Gpr, resultGPR);
2069             JITCompiler::Jump positiveDividend = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op1Gpr, TrustedImm32(0));
2070             m_jit.neg32(resultGPR);
2071             m_jit.and32(TrustedImm32(divisor - 1), resultGPR);
2072             m_jit.neg32(resultGPR);
2073             JITCompiler::Jump done = m_jit.jump();
2074
2075             positiveDividend.link(&m_jit);
2076             m_jit.and32(TrustedImm32(divisor - 1), resultGPR);
2077
2078             done.link(&m_jit);
2079             integerResult(resultGPR, m_compileIndex);
2080             return;
2081         }
2082 #if CPU(X86) || CPU(X86_64)
2083         if (divisor) {
2084             GPRTemporary eax(this, X86Registers::eax);
2085             GPRTemporary edx(this, X86Registers::edx);
2086             GPRTemporary scratch(this);
2087             GPRReg scratchGPR = scratch.gpr();
2088
2089             m_jit.move(op1Gpr, eax.gpr());
2090             m_jit.move(TrustedImm32(divisor), scratchGPR);
2091             m_jit.assembler().cdq();
2092             m_jit.assembler().idivl_r(scratchGPR);
2093             integerResult(edx.gpr(), m_compileIndex);
2094             return;
2095         }
2096 #endif
2097         // Fallback to non-constant case but avoid unnecessary checks.
2098         shouldGeneratePowerOfTwoCheck = false;
2099     }
2100
2101     SpeculateIntegerOperand op2(this, node.child2());
2102     GPRReg op2Gpr = op2.gpr();
2103
2104     speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(JITCompiler::Zero, op2Gpr));
2105
2106 #if CPU(X86) || CPU(X86_64)
2107     GPRTemporary eax(this, X86Registers::eax);
2108     GPRTemporary edx(this, X86Registers::edx);
2109     GPRReg temp2 = InvalidGPRReg;
2110     if (op2Gpr == X86Registers::eax || op2Gpr == X86Registers::edx) {
2111         temp2 = allocate();
2112         m_jit.move(op2Gpr, temp2);
2113         op2Gpr = temp2;
2114     }
2115     GPRReg resultGPR = edx.gpr();
2116     GPRReg scratchGPR = eax.gpr();
2117 #else
2118     GPRTemporary result(this);
2119     GPRTemporary scratch(this);
2120     GPRTemporary scratch3(this);
2121     GPRReg scratchGPR3 = scratch3.gpr();
2122     GPRReg resultGPR = result.gpr();
2123     GPRReg scratchGPR = scratch.gpr();
2124 #endif
2125
2126     GPRTemporary scratch2(this);
2127     GPRReg scratchGPR2 = scratch2.gpr();
2128     JITCompiler::JumpList exitBranch;
2129
2130     // resultGPR is to hold the ABS value of the dividend before final result is produced
2131     m_jit.move(op1Gpr, resultGPR);
2132     // scratchGPR2 is to hold the ABS value of the divisor
2133     m_jit.move(op2Gpr, scratchGPR2);
2134
2135     // Check for negative result remainder
2136     // According to ECMA-262, the sign of the result equals the sign of the dividend
2137     JITCompiler::Jump positiveDividend = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op1Gpr, TrustedImm32(0));
2138     m_jit.neg32(resultGPR);
2139     m_jit.move(TrustedImm32(1), scratchGPR);
2140     JITCompiler::Jump saveCondition = m_jit.jump();
2141
2142     positiveDividend.link(&m_jit);
2143     m_jit.move(TrustedImm32(0), scratchGPR);
2144
2145     // Save the condition for negative remainder
2146     saveCondition.link(&m_jit);
2147     m_jit.push(scratchGPR);
2148
2149     JITCompiler::Jump positiveDivisor = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op2Gpr, TrustedImm32(0));
2150     m_jit.neg32(scratchGPR2);
2151
2152     positiveDivisor.link(&m_jit);
2153     exitBranch.append(m_jit.branch32(JITCompiler::LessThan, resultGPR, scratchGPR2));
2154
2155     // Power of two fast case
2156     if (shouldGeneratePowerOfTwoCheck) {
2157         m_jit.move(scratchGPR2, scratchGPR);
2158         m_jit.sub32(TrustedImm32(1), scratchGPR);
2159         JITCompiler::Jump notPowerOfTwo = m_jit.branchTest32(JITCompiler::NonZero, scratchGPR, scratchGPR2);
2160         m_jit.and32(scratchGPR, resultGPR);
2161         exitBranch.append(m_jit.jump());
2162
2163         notPowerOfTwo.link(&m_jit);
2164     }
2165
2166 #if CPU(X86) || CPU(X86_64)
2167     m_jit.move(resultGPR, eax.gpr());
2168     m_jit.assembler().cdq();
2169     m_jit.assembler().idivl_r(scratchGPR2);
2170 #elif CPU(ARM_THUMB2)
2171     m_jit.countLeadingZeros32(scratchGPR2, scratchGPR);
2172     m_jit.countLeadingZeros32(resultGPR, scratchGPR3);
2173     m_jit.sub32(scratchGPR3, scratchGPR);
2174
2175     JITCompiler::Jump useFullTable = m_jit.branch32(JITCompiler::Equal, scratchGPR, TrustedImm32(31));
2176
2177     m_jit.neg32(scratchGPR);
2178     m_jit.add32(TrustedImm32(31), scratchGPR);
2179
2180     int elementSizeByShift = -1;
2181     elementSizeByShift = 3;
2182     m_jit.relativeTableJump(scratchGPR, elementSizeByShift);
2183
2184     useFullTable.link(&m_jit);
2185     // Modulo table
2186     for (int i = 31; i > 0; --i) {
2187         ShiftTypeAndAmount shift(SRType_LSL, i);
2188         m_jit.assembler().sub_S(scratchGPR, resultGPR, scratchGPR2, shift);
2189         m_jit.assembler().it(ARMv7Assembler::ConditionCS);
2190         m_jit.assembler().mov(resultGPR, scratchGPR);
2191     }
2192
2193     JITCompiler::Jump lower = m_jit.branch32(JITCompiler::Below, resultGPR, scratchGPR2);
2194     m_jit.sub32(scratchGPR2, resultGPR);
2195     lower.link(&m_jit);
2196 #endif // CPU(X86) || CPU(X86_64)
2197
2198     exitBranch.link(&m_jit);
2199
2200     // Check for negative remainder
2201     m_jit.pop(scratchGPR);
2202     JITCompiler::Jump positiveResult = m_jit.branch32(JITCompiler::Equal, scratchGPR, TrustedImm32(0));
2203     m_jit.neg32(resultGPR);
2204     positiveResult.link(&m_jit);
2205
2206     integerResult(resultGPR, m_compileIndex);
2207
2208 #if CPU(X86) || CPU(X86_64)
2209     if (temp2 != InvalidGPRReg)
2210         unlock(temp2);
2211 #endif
2212 }
2213
2214 void SpeculativeJIT::compileAdd(Node& node)
2215 {
2216     if (m_jit.graph().addShouldSpeculateInteger(node, m_jit.codeBlock())) {
2217         if (isNumberConstant(node.child1().index())) {
2218             int32_t imm1 = valueOfNumberConstantAsInt32(node.child1().index());
2219             SpeculateIntegerOperand op2(this, node.child2());
2220             GPRTemporary result(this);
2221
2222             if (nodeCanTruncateInteger(node.arithNodeFlags())) {
2223                 m_jit.move(op2.gpr(), result.gpr());
2224                 m_jit.add32(Imm32(imm1), result.gpr());
2225             } else
2226                 speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchAdd32(MacroAssembler::Overflow, op2.gpr(), Imm32(imm1), result.gpr()));
2227
2228             integerResult(result.gpr(), m_compileIndex);
2229             return;
2230         }
2231                 
2232         if (isNumberConstant(node.child2().index())) {
2233             SpeculateIntegerOperand op1(this, node.child1());
2234             int32_t imm2 = valueOfNumberConstantAsInt32(node.child2().index());
2235             GPRTemporary result(this);
2236                 
2237             if (nodeCanTruncateInteger(node.arithNodeFlags())) {
2238                 m_jit.move(op1.gpr(), result.gpr());
2239                 m_jit.add32(Imm32(imm2), result.gpr());
2240             } else
2241                 speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchAdd32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
2242
2243             integerResult(result.gpr(), m_compileIndex);
2244             return;
2245         }
2246                 
2247         SpeculateIntegerOperand op1(this, node.child1());
2248         SpeculateIntegerOperand op2(this, node.child2());
2249         GPRTemporary result(this, op1, op2);
2250
2251         GPRReg gpr1 = op1.gpr();
2252         GPRReg gpr2 = op2.gpr();
2253         GPRReg gprResult = result.gpr();
2254
2255         if (nodeCanTruncateInteger(node.arithNodeFlags())) {
2256             if (gpr1 == gprResult)
2257                 m_jit.add32(gpr2, gprResult);
2258             else {
2259                 m_jit.move(gpr2, gprResult);
2260                 m_jit.add32(gpr1, gprResult);
2261             }
2262         } else {
2263             MacroAssembler::Jump check = m_jit.branchAdd32(MacroAssembler::Overflow, gpr1, gpr2, gprResult);
2264                 
2265             if (gpr1 == gprResult)
2266                 speculationCheck(Overflow, JSValueRegs(), NoNode, check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr2));
2267             else if (gpr2 == gprResult)
2268                 speculationCheck(Overflow, JSValueRegs(), NoNode, check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr1));
2269             else
2270                 speculationCheck(Overflow, JSValueRegs(), NoNode, check);
2271         }
2272
2273         integerResult(gprResult, m_compileIndex);
2274         return;
2275     }
2276         
2277     if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2()))) {
2278         SpeculateDoubleOperand op1(this, node.child1());
2279         SpeculateDoubleOperand op2(this, node.child2());
2280         FPRTemporary result(this, op1, op2);
2281
2282         FPRReg reg1 = op1.fpr();
2283         FPRReg reg2 = op2.fpr();
2284         m_jit.addDouble(reg1, reg2, result.fpr());
2285
2286         doubleResult(result.fpr(), m_compileIndex);
2287         return;
2288     }
2289
2290     if (node.op == ValueAdd) {
2291         compileValueAdd(node);
2292         return;
2293     }
2294     
2295     // We don't handle this yet. :-(
2296     terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
2297 }
2298
2299 void SpeculativeJIT::compileArithSub(Node& node)
2300 {
2301     if (m_jit.graph().addShouldSpeculateInteger(node, m_jit.codeBlock())) {
2302         if (isNumberConstant(node.child2().index())) {
2303             SpeculateIntegerOperand op1(this, node.child1());
2304             int32_t imm2 = valueOfNumberConstantAsInt32(node.child2().index());
2305             GPRTemporary result(this);
2306
2307             if (nodeCanTruncateInteger(node.arithNodeFlags())) {
2308                 m_jit.move(op1.gpr(), result.gpr());
2309                 m_jit.sub32(Imm32(imm2), result.gpr());
2310             } else
2311                 speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
2312
2313             integerResult(result.gpr(), m_compileIndex);
2314             return;
2315         }
2316             
2317         if (isNumberConstant(node.child1().index())) {
2318             int32_t imm1 = valueOfNumberConstantAsInt32(node.child1().index());
2319             SpeculateIntegerOperand op2(this, node.child2());
2320             GPRTemporary result(this);
2321                 
2322             m_jit.move(Imm32(imm1), result.gpr());
2323             if (nodeCanTruncateInteger(node.arithNodeFlags()))
2324                 m_jit.sub32(op2.gpr(), result.gpr());
2325             else
2326                 speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchSub32(MacroAssembler::Overflow, op2.gpr(), result.gpr()));
2327                 
2328             integerResult(result.gpr(), m_compileIndex);
2329             return;
2330         }
2331             
2332         SpeculateIntegerOperand op1(this, node.child1());
2333         SpeculateIntegerOperand op2(this, node.child2());
2334         GPRTemporary result(this);
2335
2336         if (nodeCanTruncateInteger(node.arithNodeFlags())) {
2337             m_jit.move(op1.gpr(), result.gpr());
2338             m_jit.sub32(op2.gpr(), result.gpr());
2339         } else
2340             speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), op2.gpr(), result.gpr()));
2341
2342         integerResult(result.gpr(), m_compileIndex);
2343         return;
2344     }
2345         
2346     SpeculateDoubleOperand op1(this, node.child1());
2347     SpeculateDoubleOperand op2(this, node.child2());
2348     FPRTemporary result(this, op1);
2349
2350     FPRReg reg1 = op1.fpr();
2351     FPRReg reg2 = op2.fpr();
2352     m_jit.subDouble(reg1, reg2, result.fpr());
2353
2354     doubleResult(result.fpr(), m_compileIndex);
2355 }
2356
2357 void SpeculativeJIT::compileArithMul(Node& node)
2358 {
2359     if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) {
2360         SpeculateIntegerOperand op1(this, node.child1());
2361         SpeculateIntegerOperand op2(this, node.child2());
2362         GPRTemporary result(this);
2363
2364         GPRReg reg1 = op1.gpr();
2365         GPRReg reg2 = op2.gpr();
2366
2367         // What is unfortunate is that we cannot take advantage of nodeCanTruncateInteger()
2368         // here. A multiply on integers performed in the double domain and then truncated to
2369         // an integer will give a different result than a multiply performed in the integer
2370         // domain and then truncated, if the integer domain result would have resulted in
2371         // something bigger than what a 32-bit integer can hold. JavaScript mandates that
2372         // the semantics are always as if the multiply had been performed in the double
2373         // domain.
2374             
2375         speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchMul32(MacroAssembler::Overflow, reg1, reg2, result.gpr()));
2376             
2377         // Check for negative zero, if the users of this node care about such things.
2378         if (!nodeCanIgnoreNegativeZero(node.arithNodeFlags())) {
2379             MacroAssembler::Jump resultNonZero = m_jit.branchTest32(MacroAssembler::NonZero, result.gpr());
2380             speculationCheck(NegativeZero, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, reg1, TrustedImm32(0)));
2381             speculationCheck(NegativeZero, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, reg2, TrustedImm32(0)));
2382             resultNonZero.link(&m_jit);
2383         }
2384
2385         integerResult(result.gpr(), m_compileIndex);
2386         return;
2387     }
2388
2389     SpeculateDoubleOperand op1(this, node.child1());
2390     SpeculateDoubleOperand op2(this, node.child2());
2391     FPRTemporary result(this, op1, op2);
2392
2393     FPRReg reg1 = op1.fpr();
2394     FPRReg reg2 = op2.fpr();
2395         
2396     m_jit.mulDouble(reg1, reg2, result.fpr());
2397         
2398     doubleResult(result.fpr(), m_compileIndex);
2399 }
2400
2401 void SpeculativeJIT::compileArithMod(Node& node)
2402 {
2403     if (!at(node.child1()).shouldNotSpeculateInteger() && !at(node.child2()).shouldNotSpeculateInteger()
2404         && node.canSpeculateInteger()) {
2405         compileSoftModulo(node);
2406         return;
2407     }
2408         
2409     SpeculateDoubleOperand op1(this, node.child1());
2410     SpeculateDoubleOperand op2(this, node.child2());
2411         
2412     FPRReg op1FPR = op1.fpr();
2413     FPRReg op2FPR = op2.fpr();
2414         
2415     flushRegisters();
2416         
2417     FPRResult result(this);
2418
2419     callOperation(fmodAsDFGOperation, result.fpr(), op1FPR, op2FPR);
2420         
2421     doubleResult(result.fpr(), m_compileIndex);
2422 }
2423
2424 // Returns true if the compare is fused with a subsequent branch.
2425 bool SpeculativeJIT::compare(Node& node, MacroAssembler::RelationalCondition condition, MacroAssembler::DoubleCondition doubleCondition, S_DFGOperation_EJJ operation)
2426 {
2427     if (compilePeepHoleBranch(node, condition, doubleCondition, operation))
2428         return true;
2429
2430     if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())))
2431         compileIntegerCompare(node, condition);
2432     else if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2())))
2433         compileDoubleCompare(node, doubleCondition);
2434     else if (node.op == CompareEq && Node::shouldSpeculateFinalObject(at(node.child1()), at(node.child2())))
2435         compileObjectEquality(node, &JSFinalObject::s_info, isFinalObjectPrediction);
2436     else if (node.op == CompareEq && Node::shouldSpeculateArray(at(node.child1()), at(node.child2())))
2437         compileObjectEquality(node, &JSArray::s_info, isArrayPrediction);
2438     else
2439         nonSpeculativeNonPeepholeCompare(node, condition, operation);
2440     
2441     return false;
2442 }
2443
2444 bool SpeculativeJIT::compileStrictEqForConstant(Node& node, NodeUse value, JSValue constant)
2445 {
2446     JSValueOperand op1(this, value);
2447     
2448     NodeIndex branchNodeIndex = detectPeepHoleBranch();
2449     if (branchNodeIndex != NoNode) {
2450         Node& branchNode = at(branchNodeIndex);
2451         BlockIndex taken = branchNode.takenBlockIndex();
2452         BlockIndex notTaken = branchNode.notTakenBlockIndex();
2453         MacroAssembler::RelationalCondition condition = MacroAssembler::Equal;
2454         
2455         // The branch instruction will branch to the taken block.
2456         // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
2457         if (taken == (m_block + 1)) {
2458             condition = MacroAssembler::NotEqual;
2459             BlockIndex tmp = taken;
2460             taken = notTaken;
2461             notTaken = tmp;
2462         }
2463
2464 #if USE(JSVALUE64)
2465         branchPtr(condition, op1.gpr(), MacroAssembler::TrustedImmPtr(bitwise_cast<void*>(JSValue::encode(constant))), taken);
2466 #else
2467         GPRReg payloadGPR = op1.payloadGPR();
2468         GPRReg tagGPR = op1.tagGPR();
2469         if (condition == MacroAssembler::Equal) {
2470             // Drop down if not equal, go elsewhere if equal.
2471             MacroAssembler::Jump notEqual = m_jit.branch32(MacroAssembler::NotEqual, tagGPR, MacroAssembler::Imm32(constant.tag()));
2472             branch32(MacroAssembler::Equal, payloadGPR, MacroAssembler::Imm32(constant.payload()), taken);
2473             notEqual.link(&m_jit);
2474         } else {
2475             // Drop down if equal, go elsehwere if not equal.
2476             branch32(MacroAssembler::NotEqual, tagGPR, MacroAssembler::Imm32(constant.tag()), taken);
2477             branch32(MacroAssembler::NotEqual, payloadGPR, MacroAssembler::Imm32(constant.payload()), taken);
2478         }
2479 #endif
2480         
2481         jump(notTaken);
2482         
2483         use(node.child1());
2484         use(node.child2());
2485         m_compileIndex = branchNodeIndex;
2486         return true;
2487     }
2488     
2489     GPRTemporary result(this);
2490     
2491 #if USE(JSVALUE64)
2492     GPRReg op1GPR = op1.gpr();
2493     GPRReg resultGPR = result.gpr();
2494     m_jit.move(MacroAssembler::TrustedImmPtr(bitwise_cast<void*>(ValueFalse)), resultGPR);
2495     MacroAssembler::Jump notEqual = m_jit.branchPtr(MacroAssembler::NotEqual, op1GPR, MacroAssembler::TrustedImmPtr(bitwise_cast<void*>(JSValue::encode(constant))));
2496     m_jit.or32(MacroAssembler::Imm32(1), resultGPR);
2497     notEqual.link(&m_jit);
2498     jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean);
2499 #else
2500     GPRReg op1PayloadGPR = op1.payloadGPR();
2501     GPRReg op1TagGPR = op1.tagGPR();
2502     GPRReg resultGPR = result.gpr();
2503     m_jit.move(Imm32(0), resultGPR);
2504     MacroAssembler::JumpList notEqual;
2505     notEqual.append(m_jit.branch32(MacroAssembler::NotEqual, op1TagGPR, MacroAssembler::Imm32(constant.tag())));
2506     notEqual.append(m_jit.branch32(MacroAssembler::NotEqual, op1PayloadGPR, MacroAssembler::Imm32(constant.payload())));
2507     m_jit.move(Imm32(1), resultGPR);
2508     notEqual.link(&m_jit);
2509     booleanResult(resultGPR, m_compileIndex);
2510 #endif
2511     
2512     return false;
2513 }
2514
2515 bool SpeculativeJIT::compileStrictEq(Node& node)
2516 {
2517     // 1) If either operand is a constant and that constant is not a double, integer,
2518     //    or string, then do a JSValue comparison.
2519     
2520     if (isJSConstant(node.child1().index())) {
2521         JSValue value = valueOfJSConstant(node.child1().index());
2522         if (!value.isNumber() && !value.isString())
2523             return compileStrictEqForConstant(node, node.child2(), value);
2524     }
2525     
2526     if (isJSConstant(node.child2().index())) {
2527         JSValue value = valueOfJSConstant(node.child2().index());
2528         if (!value.isNumber() && !value.isString())
2529             return compileStrictEqForConstant(node, node.child1(), value);
2530     }
2531     
2532     // 2) If the operands are predicted integer, do an integer comparison.
2533     
2534     if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2()))) {
2535         NodeIndex branchNodeIndex = detectPeepHoleBranch();
2536         if (branchNodeIndex != NoNode) {
2537             compilePeepHoleIntegerBranch(node, branchNodeIndex, MacroAssembler::Equal);
2538             use(node.child1());
2539             use(node.child2());
2540             m_compileIndex = branchNodeIndex;
2541             return true;
2542         }
2543         compileIntegerCompare(node, MacroAssembler::Equal);
2544         return false;
2545     }
2546     
2547     // 3) If the operands are predicted double, do a double comparison.
2548     
2549     if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2()))) {
2550         NodeIndex branchNodeIndex = detectPeepHoleBranch();
2551         if (branchNodeIndex != NoNode) {
2552             compilePeepHoleDoubleBranch(node, branchNodeIndex, MacroAssembler::DoubleEqual);
2553             use(node.child1());
2554             use(node.child2());
2555             m_compileIndex = branchNodeIndex;
2556             return true;
2557         }
2558         compileDoubleCompare(node, MacroAssembler::DoubleEqual);
2559         return false;
2560     }
2561     
2562     // 4) If the operands are predicted final object or array, then do a final object
2563     //    or array comparison.
2564     
2565     if (Node::shouldSpeculateFinalObject(at(node.child1()), at(node.child2()))) {
2566         NodeIndex branchNodeIndex = detectPeepHoleBranch();
2567         if (branchNodeIndex != NoNode) {
2568             compilePeepHoleObjectEquality(node, branchNodeIndex, &JSFinalObject::s_info, isFinalObjectPrediction);
2569             use(node.child1());
2570             use(node.child2());
2571             m_compileIndex = branchNodeIndex;
2572             return true;
2573         }
2574         compileObjectEquality(node, &JSFinalObject::s_info, isFinalObjectPrediction);
2575         return false;
2576     }
2577     
2578     if (Node::shouldSpeculateArray(at(node.child1()), at(node.child2()))) {
2579         NodeIndex branchNodeIndex = detectPeepHoleBranch();
2580         if (branchNodeIndex != NoNode) {
2581             compilePeepHoleObjectEquality(node, branchNodeIndex, &JSArray::s_info, isArrayPrediction);
2582             use(node.child1());
2583             use(node.child2());
2584             m_compileIndex = branchNodeIndex;
2585             return true;
2586         }
2587         compileObjectEquality(node, &JSArray::s_info, isArrayPrediction);
2588         return false;
2589     }
2590     
2591     // 5) Fall back to non-speculative strict equality.
2592     
2593     return nonSpeculativeStrictEq(node);
2594 }
2595
2596 void SpeculativeJIT::compileGetIndexedPropertyStorage(Node& node)
2597 {
2598     if (!node.prediction() || !at(node.child1()).prediction() || !at(node.child2()).prediction()) {
2599         terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
2600         return;
2601     }
2602         
2603     SpeculateCellOperand base(this, node.child1());
2604     GPRReg baseReg = base.gpr();
2605     
2606     PredictedType basePrediction = at(node.child2()).prediction();
2607     if (!(basePrediction & PredictInt32) && basePrediction) {
2608         ASSERT_NOT_REACHED();
2609         terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
2610         noResult(m_compileIndex);
2611         return;
2612     }
2613     
2614     GPRTemporary storage(this);
2615     GPRReg storageReg = storage.gpr();
2616     if (at(node.child1()).prediction() == PredictString) {
2617         if (!isStringPrediction(m_state.forNode(node.child1()).m_type))
2618             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSString::s_info)));
2619
2620         m_jit.loadPtr(MacroAssembler::Address(baseReg, JSString::offsetOfValue()), storageReg);
2621         
2622         // Speculate that we're not accessing a rope
2623         speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTest32(MacroAssembler::Zero, storageReg));
2624
2625         m_jit.loadPtr(MacroAssembler::Address(storageReg, StringImpl::dataOffset()), storageReg);
2626     } else if (at(node.child1()).shouldSpeculateByteArray()) {
2627         if (!isByteArrayPrediction(m_state.forNode(node.child1()).m_type))
2628             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info)));
2629         m_jit.loadPtr(MacroAssembler::Address(baseReg, JSByteArray::offsetOfStorage()), storageReg);
2630     } else if (at(node.child1()).shouldSpeculateInt8Array()) {
2631         const TypedArrayDescriptor& descriptor = m_jit.globalData()->int8ArrayDescriptor();
2632         if (!isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type))
2633             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
2634         m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
2635     } else if (at(node.child1()).shouldSpeculateInt16Array()) {
2636         const TypedArrayDescriptor& descriptor = m_jit.globalData()->int16ArrayDescriptor();
2637         if (!isInt16ArrayPrediction(m_state.forNode(node.child1()).m_type))
2638             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
2639         m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
2640     } else if (at(node.child1()).shouldSpeculateInt32Array()) {
2641         const TypedArrayDescriptor& descriptor = m_jit.globalData()->int32ArrayDescriptor();
2642         if (!isInt32ArrayPrediction(m_state.forNode(node.child1()).m_type))
2643             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
2644         m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
2645     } else if (at(node.child1()).shouldSpeculateUint8Array()) {
2646         const TypedArrayDescriptor& descriptor = m_jit.globalData()->uint8ArrayDescriptor();
2647         if (!isUint8ArrayPrediction(m_state.forNode(node.child1()).m_type))
2648             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
2649         m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
2650     } else if (at(node.child1()).shouldSpeculateUint8ClampedArray()) {
2651         const TypedArrayDescriptor& descriptor = m_jit.globalData()->uint8ClampedArrayDescriptor();
2652         if (!isUint8ClampedArrayPrediction(m_state.forNode(node.child1()).m_type))
2653             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
2654         m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
2655     } else if (at(node.child1()).shouldSpeculateUint16Array()) {
2656         const TypedArrayDescriptor& descriptor = m_jit.globalData()->uint16ArrayDescriptor();
2657         if (!isUint16ArrayPrediction(m_state.forNode(node.child1()).m_type))
2658             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
2659         m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
2660     } else if (at(node.child1()).shouldSpeculateUint32Array()) {
2661         const TypedArrayDescriptor& descriptor = m_jit.globalData()->uint32ArrayDescriptor();
2662         if (!isUint32ArrayPrediction(m_state.forNode(node.child1()).m_type))
2663             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
2664         m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
2665     } else if (at(node.child1()).shouldSpeculateFloat32Array()) {
2666         const TypedArrayDescriptor& descriptor = m_jit.globalData()->float32ArrayDescriptor();
2667         if (!isFloat32ArrayPrediction(m_state.forNode(node.child1()).m_type))
2668             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
2669         m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
2670     } else if (at(node.child1()).shouldSpeculateFloat64Array()) {
2671         const TypedArrayDescriptor& descriptor = m_jit.globalData()->float64ArrayDescriptor();
2672         if (!isFloat64ArrayPrediction(m_state.forNode(node.child1()).m_type))
2673             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
2674         m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
2675     } else {
2676         if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
2677             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
2678         m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
2679     }
2680     storageResult(storageReg, m_compileIndex);
2681 }
2682
2683 } } // namespace JSC::DFG
2684
2685 #endif