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