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