DFG should support activations and nested functions
[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 void ValueSource::dump(FILE* out) const
769 {
770     switch (kind()) {
771     case SourceNotSet:
772         fprintf(out, "NotSet");
773         break;
774     case ValueInRegisterFile:
775         fprintf(out, "InRegFile");
776         break;
777     case Int32InRegisterFile:
778         fprintf(out, "Int32");
779         break;
780     case CellInRegisterFile:
781         fprintf(out, "Cell");
782         break;
783     case BooleanInRegisterFile:
784         fprintf(out, "Bool");
785         break;
786     case DoubleInRegisterFile:
787         fprintf(out, "Double");
788         break;
789     case HaveNode:
790         fprintf(out, "Node(%d)", m_nodeIndex);
791         break;
792     }
793 }
794
795 void SpeculativeJIT::compilePeepHoleDoubleBranch(Node& node, NodeIndex branchNodeIndex, JITCompiler::DoubleCondition condition)
796 {
797     Node& branchNode = at(branchNodeIndex);
798     BlockIndex taken = branchNode.takenBlockIndex();
799     BlockIndex notTaken = branchNode.notTakenBlockIndex();
800     
801     SpeculateDoubleOperand op1(this, node.child1());
802     SpeculateDoubleOperand op2(this, node.child2());
803     
804     branchDouble(condition, op1.fpr(), op2.fpr(), taken);
805     jump(notTaken);
806 }
807
808 void SpeculativeJIT::compilePeepHoleObjectEquality(Node& node, NodeIndex branchNodeIndex, const ClassInfo* classInfo, PredictionChecker predictionCheck)
809 {
810     Node& branchNode = at(branchNodeIndex);
811     BlockIndex taken = branchNode.takenBlockIndex();
812     BlockIndex notTaken = branchNode.notTakenBlockIndex();
813
814     MacroAssembler::RelationalCondition condition = MacroAssembler::Equal;
815     
816     if (taken == (m_block + 1)) {
817         condition = MacroAssembler::NotEqual;
818         BlockIndex tmp = taken;
819         taken = notTaken;
820         notTaken = tmp;
821     }
822
823     SpeculateCellOperand op1(this, node.child1());
824     SpeculateCellOperand op2(this, node.child2());
825     
826     GPRReg op1GPR = op1.gpr();
827     GPRReg op2GPR = op2.gpr();
828     
829     if (!predictionCheck(m_state.forNode(node.child1()).m_type))
830         speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node.child1().index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
831     if (!predictionCheck(m_state.forNode(node.child2()).m_type))
832         speculationCheck(BadType, JSValueSource::unboxedCell(op2GPR), node.child2().index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(classInfo)));
833     
834     branchPtr(condition, op1GPR, op2GPR, taken);
835     jump(notTaken);
836 }
837
838 void SpeculativeJIT::compilePeepHoleIntegerBranch(Node& node, NodeIndex branchNodeIndex, JITCompiler::RelationalCondition condition)
839 {
840     Node& branchNode = at(branchNodeIndex);
841     BlockIndex taken = branchNode.takenBlockIndex();
842     BlockIndex notTaken = branchNode.notTakenBlockIndex();
843
844     // The branch instruction will branch to the taken block.
845     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
846     if (taken == (m_block + 1)) {
847         condition = JITCompiler::invert(condition);
848         BlockIndex tmp = taken;
849         taken = notTaken;
850         notTaken = tmp;
851     }
852
853     if (isInt32Constant(node.child1().index())) {
854         int32_t imm = valueOfInt32Constant(node.child1().index());
855         SpeculateIntegerOperand op2(this, node.child2());
856         branch32(condition, JITCompiler::Imm32(imm), op2.gpr(), taken);
857     } else if (isInt32Constant(node.child2().index())) {
858         SpeculateIntegerOperand op1(this, node.child1());
859         int32_t imm = valueOfInt32Constant(node.child2().index());
860         branch32(condition, op1.gpr(), JITCompiler::Imm32(imm), taken);
861     } else {
862         SpeculateIntegerOperand op1(this, node.child1());
863         SpeculateIntegerOperand op2(this, node.child2());
864         branch32(condition, op1.gpr(), op2.gpr(), taken);
865     }
866
867     jump(notTaken);
868 }
869
870 // Returns true if the compare is fused with a subsequent branch.
871 bool SpeculativeJIT::compilePeepHoleBranch(Node& node, MacroAssembler::RelationalCondition condition, MacroAssembler::DoubleCondition doubleCondition, S_DFGOperation_EJJ operation)
872 {
873     // Fused compare & branch.
874     NodeIndex branchNodeIndex = detectPeepHoleBranch();
875     if (branchNodeIndex != NoNode) {
876         // detectPeepHoleBranch currently only permits the branch to be the very next node,
877         // so can be no intervening nodes to also reference the compare. 
878         ASSERT(node.adjustedRefCount() == 1);
879
880         if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2()))) {
881             compilePeepHoleIntegerBranch(node, branchNodeIndex, condition);
882             use(node.child1());
883             use(node.child2());
884         } else if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2()))) {
885             compilePeepHoleDoubleBranch(node, branchNodeIndex, doubleCondition);
886             use(node.child1());
887             use(node.child2());
888         } else if (node.op == CompareEq && Node::shouldSpeculateFinalObject(at(node.child1()), at(node.child2()))) {
889             compilePeepHoleObjectEquality(node, branchNodeIndex, &JSFinalObject::s_info, isFinalObjectPrediction);
890             use(node.child1());
891             use(node.child2());
892         } else if (node.op == CompareEq && Node::shouldSpeculateArray(at(node.child1()), at(node.child2()))) {
893             compilePeepHoleObjectEquality(node, branchNodeIndex, &JSArray::s_info, isArrayPrediction);
894             use(node.child1());
895             use(node.child2());
896         } else
897             nonSpeculativePeepholeBranch(node, branchNodeIndex, condition, operation);
898
899         m_compileIndex = branchNodeIndex;
900         return true;
901     }
902     return false;
903 }
904
905 void SpeculativeJIT::compileMovHint(Node& node)
906 {
907     ASSERT(node.op == SetLocal);
908     
909     setNodeIndexForOperand(node.child1().index(), node.local());
910     m_lastSetOperand = node.local();
911 }
912
913 void SpeculativeJIT::compile(BasicBlock& block)
914 {
915     ASSERT(m_compileOkay);
916     ASSERT(m_compileIndex == block.begin);
917     
918     if (!block.isReachable) {
919         m_compileIndex = block.end;
920         return;
921     }
922
923     m_blockHeads[m_block] = m_jit.label();
924 #if DFG_ENABLE(JIT_BREAK_ON_EVERY_BLOCK)
925     m_jit.breakpoint();
926 #endif
927
928     ASSERT(m_arguments.size() == block.variablesAtHead.numberOfArguments());
929     for (size_t i = 0; i < m_arguments.size(); ++i) {
930         NodeIndex nodeIndex = block.variablesAtHead.argument(i);
931         if (nodeIndex == NoNode || m_jit.graph().argumentIsCaptured(i))
932             m_arguments[i] = ValueSource(ValueInRegisterFile);
933         else
934             m_arguments[i] = ValueSource::forPrediction(at(nodeIndex).variableAccessData()->prediction());
935     }
936     
937     m_state.reset();
938     m_state.beginBasicBlock(&block);
939     
940     ASSERT(m_variables.size() == block.variablesAtHead.numberOfLocals());
941     for (size_t i = 0; i < m_variables.size(); ++i) {
942         NodeIndex nodeIndex = block.variablesAtHead.local(i);
943         if (nodeIndex == NoNode || m_jit.graph().localIsCaptured(i))
944             m_variables[i] = ValueSource(ValueInRegisterFile);
945         else if (at(nodeIndex).variableAccessData()->shouldUseDoubleFormat())
946             m_variables[i] = ValueSource(DoubleInRegisterFile);
947         else
948             m_variables[i] = ValueSource::forPrediction(at(nodeIndex).variableAccessData()->prediction());
949     }
950     
951     m_lastSetOperand = std::numeric_limits<int>::max();
952     m_codeOriginForOSR = CodeOrigin();
953     
954     if (DFG_ENABLE_EDGE_CODE_VERIFICATION) {
955         JITCompiler::Jump verificationSucceeded =
956             m_jit.branch32(JITCompiler::Equal, GPRInfo::regT0, Imm32(m_block));
957         m_jit.breakpoint();
958         verificationSucceeded.link(&m_jit);
959     }
960
961     for (; m_compileIndex < block.end; ++m_compileIndex) {
962         Node& node = at(m_compileIndex);
963         m_codeOriginForOSR = node.codeOrigin;
964         if (!node.shouldGenerate()) {
965 #if DFG_ENABLE(DEBUG_VERBOSE)
966             dataLog("SpeculativeJIT skipping Node @%d (bc#%u) at JIT offset 0x%x     ", (int)m_compileIndex, node.codeOrigin.bytecodeIndex, m_jit.debugOffset());
967 #endif
968             switch (node.op) {
969             case SetLocal:
970                 compileMovHint(node);
971                 break;
972
973             case InlineStart: {
974                 InlineCallFrame* inlineCallFrame = node.codeOrigin.inlineCallFrame;
975                 int argumentCountIncludingThis = inlineCallFrame->arguments.size();
976                 for (int i = 0; i < argumentCountIncludingThis; ++i) {
977                     ValueRecovery recovery = computeValueRecoveryFor(m_variables[inlineCallFrame->stackOffset + CallFrame::argumentOffsetIncludingThis(i)]);
978                     // The recovery cannot point to registers, since the call frame reification isn't
979                     // as smart as OSR, so it can't handle that. The exception is the this argument,
980                     // which we don't really need to be able to recover.
981                     ASSERT(!i || !recovery.isInRegisters());
982                     inlineCallFrame->arguments[i] = recovery;
983                 }
984                 break;
985             }
986                 
987             default:
988                 break;
989             }
990         } else {
991             
992 #if DFG_ENABLE(DEBUG_VERBOSE)
993             dataLog("SpeculativeJIT generating Node @%d (bc#%u) at JIT offset 0x%x   ", (int)m_compileIndex, node.codeOrigin.bytecodeIndex, m_jit.debugOffset());
994 #endif
995 #if DFG_ENABLE(JIT_BREAK_ON_EVERY_NODE)
996             m_jit.breakpoint();
997 #endif
998 #if DFG_ENABLE(XOR_DEBUG_AID)
999             m_jit.xorPtr(JITCompiler::TrustedImm32(m_compileIndex), GPRInfo::regT0);
1000             m_jit.xorPtr(JITCompiler::TrustedImm32(m_compileIndex), GPRInfo::regT0);
1001 #endif
1002             checkConsistency();
1003             compile(node);
1004             if (!m_compileOkay) {
1005                 m_compileOkay = true;
1006                 m_compileIndex = block.end;
1007                 clearGenerationInfo();
1008                 return;
1009             }
1010             
1011 #if DFG_ENABLE(DEBUG_VERBOSE)
1012             if (node.hasResult()) {
1013                 GenerationInfo& info = m_generationInfo[node.virtualRegister()];
1014                 dataLog("-> %s, vr#%d", dataFormatToString(info.registerFormat()), (int)node.virtualRegister());
1015                 if (info.registerFormat() != DataFormatNone) {
1016                     if (info.registerFormat() == DataFormatDouble)
1017                         dataLog(", %s", FPRInfo::debugName(info.fpr()));
1018 #if USE(JSVALUE32_64)
1019                     else if (info.registerFormat() & DataFormatJS)
1020                         dataLog(", %s %s", GPRInfo::debugName(info.tagGPR()), GPRInfo::debugName(info.payloadGPR()));
1021 #endif
1022                     else
1023                         dataLog(", %s", GPRInfo::debugName(info.gpr()));
1024                 }
1025                 dataLog("    ");
1026             } else
1027                 dataLog("    ");
1028 #endif
1029         }
1030         
1031 #if DFG_ENABLE(VERBOSE_VALUE_RECOVERIES)
1032         for (size_t i = 0; i < m_arguments.size(); ++i)
1033             computeValueRecoveryFor(argumentToOperand(i)).dump(stderr);
1034         
1035         dataLog(" : ");
1036         
1037         for (int operand = 0; operand < (int)m_variables.size(); ++operand)
1038             computeValueRecoveryFor(operand).dump(stderr);
1039 #endif
1040
1041 #if DFG_ENABLE(DEBUG_VERBOSE)
1042         dataLog("\n");
1043 #endif
1044         
1045         // Make sure that the abstract state is rematerialized for the next node.
1046         m_state.execute(m_compileIndex);
1047         
1048         if (node.shouldGenerate())
1049             checkConsistency();
1050     }
1051     
1052     // Perform the most basic verification that children have been used correctly.
1053 #if !ASSERT_DISABLED
1054     for (unsigned index = 0; index < m_generationInfo.size(); ++index) {
1055         GenerationInfo& info = m_generationInfo[index];
1056         ASSERT(!info.alive());
1057     }
1058 #endif
1059 }
1060
1061 // If we are making type predictions about our arguments then
1062 // we need to check that they are correct on function entry.
1063 void SpeculativeJIT::checkArgumentTypes()
1064 {
1065     ASSERT(!m_compileIndex);
1066     m_codeOriginForOSR = CodeOrigin(0);
1067
1068     for (size_t i = 0; i < m_arguments.size(); ++i)
1069         m_arguments[i] = ValueSource(ValueInRegisterFile);
1070     for (size_t i = 0; i < m_variables.size(); ++i)
1071         m_variables[i] = ValueSource(ValueInRegisterFile);
1072     
1073     for (int i = 0; i < m_jit.codeBlock()->numParameters(); ++i) {
1074         NodeIndex nodeIndex = m_jit.graph().m_arguments[i];
1075         Node& node = at(nodeIndex);
1076         ASSERT(node.op == SetArgument);
1077         if (!node.shouldGenerate()) {
1078             // The argument is dead. We don't do any checks for such arguments.
1079             continue;
1080         }
1081         
1082         VariableAccessData* variableAccessData = node.variableAccessData();
1083         VirtualRegister virtualRegister = variableAccessData->local();
1084         PredictedType predictedType = variableAccessData->prediction();
1085
1086         JSValueSource valueSource = JSValueSource(JITCompiler::addressFor(virtualRegister));
1087         
1088 #if USE(JSVALUE64)
1089         if (isInt32Prediction(predictedType))
1090             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::Below, JITCompiler::addressFor(virtualRegister), GPRInfo::tagTypeNumberRegister));
1091         else if (isArrayPrediction(predictedType)) {
1092             GPRTemporary temp(this);
1093             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1094             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
1095             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
1096         } else if (isByteArrayPrediction(predictedType)) {
1097             GPRTemporary temp(this);
1098             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1099             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
1100             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info)));
1101         } else if (isBooleanPrediction(predictedType)) {
1102             GPRTemporary temp(this);
1103             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1104             m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), temp.gpr());
1105             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
1106         } else if (isInt8ArrayPrediction(predictedType)) {
1107             GPRTemporary temp(this);
1108             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1109             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
1110             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int8ArrayDescriptor().m_classInfo)));
1111         } else if (isInt16ArrayPrediction(predictedType)) {
1112             GPRTemporary temp(this);
1113             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1114             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
1115             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int16ArrayDescriptor().m_classInfo)));
1116         } else if (isInt32ArrayPrediction(predictedType)) {
1117             GPRTemporary temp(this);
1118             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1119             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
1120             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int32ArrayDescriptor().m_classInfo)));
1121         } else if (isUint8ArrayPrediction(predictedType)) {
1122             GPRTemporary temp(this);
1123             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1124             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
1125             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ArrayDescriptor().m_classInfo)));
1126         } else if (isUint8ClampedArrayPrediction(predictedType)) {
1127             GPRTemporary temp(this);
1128             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1129             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
1130             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ClampedArrayDescriptor().m_classInfo)));
1131         } else if (isUint16ArrayPrediction(predictedType)) {
1132             GPRTemporary temp(this);
1133             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1134             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
1135             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint16ArrayDescriptor().m_classInfo)));
1136         } else if (isUint32ArrayPrediction(predictedType)) {
1137             GPRTemporary temp(this);
1138             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1139             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
1140             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint32ArrayDescriptor().m_classInfo)));
1141         } else if (isFloat32ArrayPrediction(predictedType)) {
1142             GPRTemporary temp(this);
1143             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1144             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
1145             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float32ArrayDescriptor().m_classInfo)));
1146         } else if (isFloat64ArrayPrediction(predictedType)) {
1147             GPRTemporary temp(this);
1148             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
1149             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
1150             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float64ArrayDescriptor().m_classInfo)));
1151         }
1152 #else
1153         if (isInt32Prediction(predictedType))
1154             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag)));
1155         else if (isArrayPrediction(predictedType)) {
1156             GPRTemporary temp(this);
1157             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
1158             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
1159             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
1160             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
1161         } else if (isByteArrayPrediction(predictedType)) {
1162             GPRTemporary temp(this);
1163             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
1164             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
1165             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
1166             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info)));
1167         } else if (isBooleanPrediction(predictedType))
1168             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::BooleanTag)));
1169         else if (isInt8ArrayPrediction(predictedType)) {
1170             GPRTemporary temp(this);
1171             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
1172             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
1173             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
1174             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int8ArrayDescriptor().m_classInfo)));
1175         } else if (isInt16ArrayPrediction(predictedType)) {
1176             GPRTemporary temp(this);
1177             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
1178             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
1179             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
1180             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int16ArrayDescriptor().m_classInfo)));
1181         } else if (isInt32ArrayPrediction(predictedType)) {
1182             GPRTemporary temp(this);
1183             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
1184             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
1185             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
1186             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->int32ArrayDescriptor().m_classInfo)));
1187         } else if (isUint8ArrayPrediction(predictedType)) {
1188             GPRTemporary temp(this);
1189             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
1190             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
1191             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
1192             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ArrayDescriptor().m_classInfo)));
1193         } else if (isUint8ClampedArrayPrediction(predictedType)) {
1194             GPRTemporary temp(this);
1195             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
1196             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
1197             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
1198             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint8ClampedArrayDescriptor().m_classInfo)));
1199         } else if (isUint16ArrayPrediction(predictedType)) {
1200             GPRTemporary temp(this);
1201             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
1202             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
1203             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
1204             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint16ArrayDescriptor().m_classInfo)));
1205         }  else if (isUint32ArrayPrediction(predictedType)) {
1206             GPRTemporary temp(this);
1207             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
1208             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
1209             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
1210             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->uint32ArrayDescriptor().m_classInfo)));
1211         }  else if (isFloat32ArrayPrediction(predictedType)) {
1212             GPRTemporary temp(this);
1213             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
1214             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
1215             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
1216             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float32ArrayDescriptor().m_classInfo)));
1217         }   else if (isFloat64ArrayPrediction(predictedType)) {
1218             GPRTemporary temp(this);
1219             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
1220             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
1221             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
1222             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->float64ArrayDescriptor().m_classInfo)));
1223         } 
1224 #endif
1225     }
1226 }
1227
1228 bool SpeculativeJIT::compile()
1229 {
1230     checkArgumentTypes();
1231
1232     if (DFG_ENABLE_EDGE_CODE_VERIFICATION)
1233         m_jit.move(Imm32(0), GPRInfo::regT0);
1234
1235     ASSERT(!m_compileIndex);
1236     for (m_block = 0; m_block < m_jit.graph().m_blocks.size(); ++m_block)
1237         compile(*m_jit.graph().m_blocks[m_block]);
1238     linkBranches();
1239     return true;
1240 }
1241
1242 void SpeculativeJIT::createOSREntries()
1243 {
1244     for (BlockIndex blockIndex = 0; blockIndex < m_jit.graph().m_blocks.size(); ++blockIndex) {
1245         BasicBlock& block = *m_jit.graph().m_blocks[blockIndex];
1246         if (!block.isOSRTarget)
1247             continue;
1248
1249         // Currently we only need to create OSR entry trampolines when using edge code
1250         // verification. But in the future, we'll need this for other things as well (like
1251         // when we have global reg alloc).
1252         // If we don't need OSR entry trampolin
1253         if (!DFG_ENABLE_EDGE_CODE_VERIFICATION) {
1254             m_osrEntryHeads.append(m_blockHeads[blockIndex]);
1255             continue;
1256         }
1257         
1258         m_osrEntryHeads.append(m_jit.label());
1259         m_jit.move(Imm32(blockIndex), GPRInfo::regT0);
1260         m_jit.jump().linkTo(m_blockHeads[blockIndex], &m_jit);
1261     }
1262 }
1263
1264 void SpeculativeJIT::linkOSREntries(LinkBuffer& linkBuffer)
1265 {
1266     unsigned osrEntryIndex = 0;
1267     for (BlockIndex blockIndex = 0; blockIndex < m_jit.graph().m_blocks.size(); ++blockIndex) {
1268         BasicBlock& block = *m_jit.graph().m_blocks[blockIndex];
1269         if (block.isOSRTarget)
1270             m_jit.noticeOSREntry(block, m_osrEntryHeads[osrEntryIndex++], linkBuffer);
1271     }
1272     ASSERT(osrEntryIndex == m_osrEntryHeads.size());
1273 }
1274
1275 ValueRecovery SpeculativeJIT::computeValueRecoveryFor(const ValueSource& valueSource)
1276 {
1277     switch (valueSource.kind()) {
1278     case ValueInRegisterFile:
1279         return ValueRecovery::alreadyInRegisterFile();
1280         
1281     case Int32InRegisterFile:
1282         return ValueRecovery::alreadyInRegisterFileAsUnboxedInt32();
1283
1284     case CellInRegisterFile:
1285         return ValueRecovery::alreadyInRegisterFileAsUnboxedCell();
1286
1287     case BooleanInRegisterFile:
1288         return ValueRecovery::alreadyInRegisterFileAsUnboxedBoolean();
1289         
1290     case DoubleInRegisterFile:
1291         return ValueRecovery::alreadyInRegisterFileAsUnboxedDouble();
1292
1293     case HaveNode: {
1294         if (isConstant(valueSource.nodeIndex()))
1295             return ValueRecovery::constant(valueOfJSConstant(valueSource.nodeIndex()));
1296     
1297         Node* nodePtr = &at(valueSource.nodeIndex());
1298         if (!nodePtr->shouldGenerate()) {
1299             // It's legitimately dead. As in, nobody will ever use this node, or operand,
1300             // ever. Set it to Undefined to make the GC happy after the OSR.
1301             return ValueRecovery::constant(jsUndefined());
1302         }
1303     
1304         GenerationInfo* infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
1305         if (!infoPtr->alive() || infoPtr->nodeIndex() != valueSource.nodeIndex()) {
1306             // Try to see if there is an alternate node that would contain the value we want.
1307             // There are four possibilities:
1308             //
1309             // ValueToInt32: If the only remaining live version of the value is
1310             //    ValueToInt32, then we can use it.
1311             //
1312             // UInt32ToNumber: If the only live version of the value is a UInt32ToNumber
1313             //    then the only remaining uses are ones that want a properly formed number
1314             //    rather than a UInt32 intermediate.
1315             //
1316             // The reverse of the above: This node could be a UInt32ToNumber, but its
1317             //    alternative is still alive. This means that the only remaining uses of
1318             //    the number would be fine with a UInt32 intermediate.
1319         
1320             bool found = false;
1321         
1322             if (nodePtr->op == UInt32ToNumber) {
1323                 NodeIndex nodeIndex = nodePtr->child1().index();
1324                 nodePtr = &at(nodeIndex);
1325                 infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
1326                 if (infoPtr->alive() && infoPtr->nodeIndex() == nodeIndex)
1327                     found = true;
1328             }
1329         
1330             if (!found) {
1331                 NodeIndex valueToInt32Index = NoNode;
1332                 NodeIndex uint32ToNumberIndex = NoNode;
1333             
1334                 for (unsigned virtualRegister = 0; virtualRegister < m_generationInfo.size(); ++virtualRegister) {
1335                     GenerationInfo& info = m_generationInfo[virtualRegister];
1336                     if (!info.alive())
1337                         continue;
1338                     if (info.nodeIndex() == NoNode)
1339                         continue;
1340                     Node& node = at(info.nodeIndex());
1341                     if (node.child1Unchecked() != valueSource.nodeIndex())
1342                         continue;
1343                     switch (node.op) {
1344                     case ValueToInt32:
1345                         valueToInt32Index = info.nodeIndex();
1346                         break;
1347                     case UInt32ToNumber:
1348                         uint32ToNumberIndex = info.nodeIndex();
1349                         break;
1350                     default:
1351                         break;
1352                     }
1353                 }
1354             
1355                 NodeIndex nodeIndexToUse;
1356                 if (valueToInt32Index != NoNode)
1357                     nodeIndexToUse = valueToInt32Index;
1358                 else if (uint32ToNumberIndex != NoNode)
1359                     nodeIndexToUse = uint32ToNumberIndex;
1360                 else
1361                     nodeIndexToUse = NoNode;
1362             
1363                 if (nodeIndexToUse != NoNode) {
1364                     nodePtr = &at(nodeIndexToUse);
1365                     infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
1366                     ASSERT(infoPtr->alive() && infoPtr->nodeIndex() == nodeIndexToUse);
1367                     found = true;
1368                 }
1369             }
1370         
1371             if (!found)
1372                 return ValueRecovery::constant(jsUndefined());
1373         }
1374     
1375         ASSERT(infoPtr->alive());
1376
1377         if (infoPtr->registerFormat() != DataFormatNone) {
1378             if (infoPtr->registerFormat() == DataFormatDouble)
1379                 return ValueRecovery::inFPR(infoPtr->fpr());
1380 #if USE(JSVALUE32_64)
1381             if (infoPtr->registerFormat() & DataFormatJS)
1382                 return ValueRecovery::inPair(infoPtr->tagGPR(), infoPtr->payloadGPR());
1383 #endif
1384             return ValueRecovery::inGPR(infoPtr->gpr(), infoPtr->registerFormat());
1385         }
1386         if (infoPtr->spillFormat() != DataFormatNone)
1387             return ValueRecovery::displacedInRegisterFile(static_cast<VirtualRegister>(nodePtr->virtualRegister()), infoPtr->spillFormat());
1388     
1389         ASSERT_NOT_REACHED();
1390         return ValueRecovery();
1391     }
1392         
1393     default:
1394         ASSERT_NOT_REACHED();
1395         return ValueRecovery();
1396     }
1397 }
1398
1399 void SpeculativeJIT::compileGetCharCodeAt(Node& node)
1400 {
1401     ASSERT(node.child3() == NoNode);
1402     SpeculateCellOperand string(this, node.child1());
1403     SpeculateStrictInt32Operand index(this, node.child2());
1404     StorageOperand storage(this, node.child3());
1405
1406     GPRReg stringReg = string.gpr();
1407     GPRReg indexReg = index.gpr();
1408     GPRReg storageReg = storage.gpr();
1409     
1410     if (!isStringPrediction(m_state.forNode(node.child1()).m_type)) {
1411         ASSERT(!(at(node.child1()).prediction() & PredictString));
1412         terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
1413         noResult(m_compileIndex);
1414         return;
1415     }
1416
1417     // unsigned comparison so we can filter out negative indices and indices that are too large
1418     speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, indexReg, MacroAssembler::Address(stringReg, JSString::offsetOfLength())));
1419
1420     GPRTemporary scratch(this);
1421     GPRReg scratchReg = scratch.gpr();
1422
1423     m_jit.loadPtr(MacroAssembler::Address(stringReg, JSString::offsetOfValue()), scratchReg);
1424
1425     // Load the character into scratchReg
1426     JITCompiler::Jump is16Bit = m_jit.branchTest32(MacroAssembler::Zero, MacroAssembler::Address(scratchReg, StringImpl::flagsOffset()), TrustedImm32(StringImpl::flagIs8Bit()));
1427
1428     m_jit.load8(MacroAssembler::BaseIndex(storageReg, indexReg, MacroAssembler::TimesOne, 0), scratchReg);
1429     JITCompiler::Jump cont8Bit = m_jit.jump();
1430
1431     is16Bit.link(&m_jit);
1432
1433     m_jit.load16(MacroAssembler::BaseIndex(storageReg, indexReg, MacroAssembler::TimesTwo, 0), scratchReg);
1434
1435     cont8Bit.link(&m_jit);
1436
1437     integerResult(scratchReg, m_compileIndex);
1438 }
1439
1440 void SpeculativeJIT::compileGetByValOnString(Node& node)
1441 {
1442     SpeculateCellOperand base(this, node.child1());
1443     SpeculateStrictInt32Operand property(this, node.child2());
1444     StorageOperand storage(this, node.child3());
1445     GPRReg baseReg = base.gpr();
1446     GPRReg propertyReg = property.gpr();
1447     GPRReg storageReg = storage.gpr();
1448
1449     if (!isStringPrediction(m_state.forNode(node.child1()).m_type)) {
1450         ASSERT(!(at(node.child1()).prediction() & PredictString));
1451         terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
1452         noResult(m_compileIndex);
1453         return;
1454     }
1455
1456     // unsigned comparison so we can filter out negative indices and indices that are too large
1457     speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSString::offsetOfLength())));
1458
1459     GPRTemporary scratch(this);
1460     GPRReg scratchReg = scratch.gpr();
1461
1462     m_jit.loadPtr(MacroAssembler::Address(baseReg, JSString::offsetOfValue()), scratchReg);
1463
1464     // Load the character into scratchReg
1465     JITCompiler::Jump is16Bit = m_jit.branchTest32(MacroAssembler::Zero, MacroAssembler::Address(scratchReg, StringImpl::flagsOffset()), TrustedImm32(StringImpl::flagIs8Bit()));
1466
1467     m_jit.load8(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne, 0), scratchReg);
1468     JITCompiler::Jump cont8Bit = m_jit.jump();
1469
1470     is16Bit.link(&m_jit);
1471
1472     m_jit.load16(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesTwo, 0), scratchReg);
1473
1474     // We only support ascii characters
1475     speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, scratchReg, TrustedImm32(0x100)));
1476
1477     // 8 bit string values don't need the isASCII check.
1478     cont8Bit.link(&m_jit);
1479
1480     GPRTemporary smallStrings(this);
1481     GPRReg smallStringsReg = smallStrings.gpr();
1482     m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.globalData()->smallStrings.singleCharacterStrings()), smallStringsReg);
1483     m_jit.loadPtr(MacroAssembler::BaseIndex(smallStringsReg, scratchReg, MacroAssembler::ScalePtr, 0), scratchReg);
1484     speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTest32(MacroAssembler::Zero, scratchReg));
1485     cellResult(scratchReg, m_compileIndex);
1486 }
1487
1488 void SpeculativeJIT::compileValueToInt32(Node& node)
1489 {
1490     if (at(node.child1()).shouldNotSpeculateInteger()) {
1491         if (at(node.child1()).shouldSpeculateDouble()) {
1492             SpeculateDoubleOperand op1(this, node.child1());
1493             GPRTemporary result(this);
1494             FPRReg fpr = op1.fpr();
1495             GPRReg gpr = result.gpr();
1496             JITCompiler::Jump truncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateSuccessful);
1497             
1498             silentSpillAllRegisters(gpr);
1499             callOperation(toInt32, gpr, fpr);
1500             silentFillAllRegisters(gpr);
1501             
1502             truncatedToInteger.link(&m_jit);
1503             integerResult(gpr, m_compileIndex);
1504             return;
1505         }
1506         // Do it the safe way.
1507         nonSpeculativeValueToInt32(node);
1508         return;
1509     }
1510     
1511     SpeculateIntegerOperand op1(this, node.child1());
1512     GPRTemporary result(this, op1);
1513     m_jit.move(op1.gpr(), result.gpr());
1514     integerResult(result.gpr(), m_compileIndex, op1.format());
1515 }
1516
1517 void SpeculativeJIT::compileUInt32ToNumber(Node& node)
1518 {
1519     if (!nodeCanSpeculateInteger(node.arithNodeFlags())) {
1520         // We know that this sometimes produces doubles. So produce a double every
1521         // time. This at least allows subsequent code to not have weird conditionals.
1522             
1523         IntegerOperand op1(this, node.child1());
1524         FPRTemporary result(this);
1525             
1526         GPRReg inputGPR = op1.gpr();
1527         FPRReg outputFPR = result.fpr();
1528             
1529         m_jit.convertInt32ToDouble(inputGPR, outputFPR);
1530             
1531         JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, inputGPR, TrustedImm32(0));
1532         m_jit.addDouble(JITCompiler::AbsoluteAddress(&AssemblyHelpers::twoToThe32), outputFPR);
1533         positive.link(&m_jit);
1534             
1535         doubleResult(outputFPR, m_compileIndex);
1536         return;
1537     }
1538
1539     IntegerOperand op1(this, node.child1());
1540     GPRTemporary result(this, op1);
1541
1542     // Test the operand is positive. This is a very special speculation check - we actually
1543     // use roll-forward speculation here, where if this fails, we jump to the baseline
1544     // instruction that follows us, rather than the one we're executing right now. We have
1545     // to do this because by this point, the original values necessary to compile whatever
1546     // operation the UInt32ToNumber originated from might be dead.
1547     speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, op1.gpr(), TrustedImm32(0)));
1548         
1549     // Verify that we can do roll forward.
1550     ASSERT(at(m_compileIndex + 1).op == SetLocal);
1551     ASSERT(at(m_compileIndex + 1).codeOrigin == node.codeOrigin);
1552     ASSERT(at(m_compileIndex + 2).codeOrigin != node.codeOrigin);
1553         
1554     // Now do the magic.
1555     OSRExit& exit = m_jit.codeBlock()->lastOSRExit();
1556     Node& setLocal = at(m_compileIndex + 1);
1557     exit.m_codeOrigin = at(m_compileIndex + 2).codeOrigin;
1558     exit.m_lastSetOperand = setLocal.local();
1559         
1560     // Create the value recovery, and stuff it into the right place.
1561     exit.valueRecoveryForOperand(setLocal.local()) = ValueRecovery::uint32InGPR(op1.gpr());
1562
1563     m_jit.move(op1.gpr(), result.gpr());
1564     integerResult(result.gpr(), m_compileIndex, op1.format());
1565 }
1566
1567 static double clampDoubleToByte(double d)
1568 {
1569     d += 0.5;
1570     if (!(d > 0))
1571         d = 0;
1572     else if (d > 255)
1573         d = 255;
1574     return d;
1575 }
1576
1577 static void compileClampIntegerToByte(JITCompiler& jit, GPRReg result)
1578 {
1579     MacroAssembler::Jump inBounds = jit.branch32(MacroAssembler::BelowOrEqual, result, JITCompiler::TrustedImm32(0xff));
1580     MacroAssembler::Jump tooBig = jit.branch32(MacroAssembler::GreaterThan, result, JITCompiler::TrustedImm32(0xff));
1581     jit.xorPtr(result, result);
1582     MacroAssembler::Jump clamped = jit.jump();
1583     tooBig.link(&jit);
1584     jit.move(JITCompiler::TrustedImm32(255), result);
1585     clamped.link(&jit);
1586     inBounds.link(&jit);
1587 }
1588
1589 static void compileClampDoubleToByte(JITCompiler& jit, GPRReg result, FPRReg source, FPRReg scratch)
1590 {
1591     // Unordered compare so we pick up NaN
1592     static const double zero = 0;
1593     static const double byteMax = 255;
1594     static const double half = 0.5;
1595     jit.loadDouble(&zero, scratch);
1596     MacroAssembler::Jump tooSmall = jit.branchDouble(MacroAssembler::DoubleLessThanOrEqualOrUnordered, source, scratch);
1597     jit.loadDouble(&byteMax, scratch);
1598     MacroAssembler::Jump tooBig = jit.branchDouble(MacroAssembler::DoubleGreaterThan, source, scratch);
1599     
1600     jit.loadDouble(&half, scratch);
1601     // FIXME: This should probably just use a floating point round!
1602     // https://bugs.webkit.org/show_bug.cgi?id=72054
1603     jit.addDouble(source, scratch);
1604     jit.truncateDoubleToInt32(scratch, result);   
1605     MacroAssembler::Jump truncatedInt = jit.jump();
1606     
1607     tooSmall.link(&jit);
1608     jit.xorPtr(result, result);
1609     MacroAssembler::Jump zeroed = jit.jump();
1610     
1611     tooBig.link(&jit);
1612     jit.move(JITCompiler::TrustedImm32(255), result);
1613     
1614     truncatedInt.link(&jit);
1615     zeroed.link(&jit);
1616
1617 }
1618
1619 void SpeculativeJIT::compilePutByValForByteArray(GPRReg base, GPRReg property, Node& node)
1620 {
1621     NodeUse baseUse = node.child1();
1622     NodeUse valueUse = node.child3();
1623     
1624     if (!isByteArrayPrediction(m_state.forNode(baseUse).m_type))
1625         speculationCheck(BadType, JSValueSource::unboxedCell(base), baseUse.index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info)));
1626     GPRTemporary value;
1627     GPRReg valueGPR;
1628
1629     if (at(valueUse).isConstant()) {
1630         JSValue jsValue = valueOfJSConstant(valueUse.index());
1631         if (!jsValue.isNumber()) {
1632             terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
1633             noResult(m_compileIndex);
1634             return;
1635         }
1636         int clampedValue = clampDoubleToByte(jsValue.asNumber());
1637         GPRTemporary scratch(this);
1638         GPRReg scratchReg = scratch.gpr();
1639         m_jit.move(Imm32(clampedValue), scratchReg);
1640         value.adopt(scratch);
1641         valueGPR = scratchReg;
1642     } else if (!at(valueUse).shouldNotSpeculateInteger()) {
1643         SpeculateIntegerOperand valueOp(this, valueUse);
1644         GPRTemporary scratch(this);
1645         GPRReg scratchReg = scratch.gpr();
1646         m_jit.move(valueOp.gpr(), scratchReg);
1647         compileClampIntegerToByte(m_jit, scratchReg);
1648         value.adopt(scratch);
1649         valueGPR = scratchReg;
1650     } else {
1651         SpeculateDoubleOperand valueOp(this, valueUse);
1652         GPRTemporary result(this);
1653         FPRTemporary floatScratch(this);
1654         FPRReg fpr = valueOp.fpr();
1655         GPRReg gpr = result.gpr();
1656         compileClampDoubleToByte(m_jit, gpr, fpr, floatScratch.fpr());
1657         value.adopt(result);
1658         valueGPR = gpr;
1659     }
1660     ASSERT_UNUSED(valueGPR, valueGPR != property);
1661     ASSERT(valueGPR != base);
1662     GPRTemporary storage(this);
1663     GPRReg storageReg = storage.gpr();
1664     ASSERT(valueGPR != storageReg);
1665     m_jit.loadPtr(MacroAssembler::Address(base, JSByteArray::offsetOfStorage()), storageReg);
1666     MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, property, MacroAssembler::Address(storageReg, ByteArray::offsetOfSize()));
1667     m_jit.store8(value.gpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesOne, ByteArray::offsetOfData()));
1668     outOfBounds.link(&m_jit);
1669     noResult(m_compileIndex);
1670 }
1671
1672 void SpeculativeJIT::compileGetByValOnByteArray(Node& node)
1673 {
1674     SpeculateCellOperand base(this, node.child1());
1675     SpeculateStrictInt32Operand property(this, node.child2());
1676
1677     GPRReg baseReg = base.gpr();
1678     GPRReg propertyReg = property.gpr();
1679
1680     if (!isByteArrayPrediction(m_state.forNode(node.child1()).m_type)) {
1681         terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
1682         noResult(m_compileIndex);
1683         return;
1684     }
1685
1686     // Load the character into scratchReg
1687     GPRTemporary storage(this);
1688     GPRReg storageReg = storage.gpr();
1689     m_jit.loadPtr(MacroAssembler::Address(baseReg, JSByteArray::offsetOfStorage()), storageReg);
1690     
1691     // unsigned comparison so we can filter out negative indices and indices that are too large
1692     speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ByteArray::offsetOfSize())));
1693
1694     m_jit.load8(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne, ByteArray::offsetOfData()), storageReg);
1695     integerResult(storageReg, m_compileIndex);
1696 }
1697
1698 void SpeculativeJIT::compileGetTypedArrayLength(const TypedArrayDescriptor& descriptor, Node& node, bool needsSpeculationCheck)
1699 {
1700     SpeculateCellOperand base(this, node.child1());
1701     GPRTemporary result(this);
1702     
1703     GPRReg baseGPR = base.gpr();
1704     GPRReg resultGPR = result.gpr();
1705     
1706     if (needsSpeculationCheck)
1707         speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
1708     
1709     m_jit.load32(MacroAssembler::Address(baseGPR, descriptor.m_lengthOffset), resultGPR);
1710     
1711     integerResult(resultGPR, m_compileIndex);
1712 }
1713
1714 void SpeculativeJIT::compileGetByValOnIntTypedArray(const TypedArrayDescriptor& descriptor, Node& node, size_t elementSize, TypedArraySpeculationRequirements speculationRequirements, TypedArraySignedness signedness)
1715 {
1716     SpeculateCellOperand base(this, node.child1());
1717     SpeculateStrictInt32Operand property(this, node.child2());
1718     StorageOperand storage(this, node.child3());
1719
1720     GPRReg baseReg = base.gpr();
1721     GPRReg propertyReg = property.gpr();
1722     GPRReg storageReg = storage.gpr();
1723
1724     GPRTemporary result(this);
1725     GPRReg resultReg = result.gpr();
1726
1727     if (speculationRequirements != NoTypedArrayTypeSpecCheck) {
1728         ASSERT_NOT_REACHED();
1729         terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
1730         noResult(m_compileIndex);
1731         return;
1732     }
1733
1734     MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(baseReg, descriptor.m_lengthOffset));
1735     m_jit.xorPtr(resultReg, resultReg);
1736     MacroAssembler::Jump outOfBounds = m_jit.jump();
1737     inBounds.link(&m_jit);
1738     switch (elementSize) {
1739     case 1:
1740         if (signedness == SignedTypedArray)
1741             m_jit.load8Signed(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne), resultReg);
1742         else
1743             m_jit.load8(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne), resultReg);
1744         break;
1745     case 2:
1746         if (signedness == SignedTypedArray)
1747             m_jit.load16Signed(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesTwo), resultReg);
1748         else
1749             m_jit.load16(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesTwo), resultReg);
1750         break;
1751     case 4:
1752         m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesFour), resultReg);
1753         break;
1754     default:
1755         ASSERT_NOT_REACHED();
1756     }
1757     outOfBounds.link(&m_jit);
1758     if (elementSize < 4 || signedness == SignedTypedArray)
1759         integerResult(resultReg, m_compileIndex);
1760     else {
1761         FPRTemporary fresult(this);
1762         m_jit.convertInt32ToDouble(resultReg, fresult.fpr());
1763         JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, resultReg, TrustedImm32(0));
1764         m_jit.addDouble(JITCompiler::AbsoluteAddress(&AssemblyHelpers::twoToThe32), fresult.fpr());
1765         positive.link(&m_jit);
1766         doubleResult(fresult.fpr(), m_compileIndex);
1767     }
1768 }
1769
1770 void SpeculativeJIT::compilePutByValForIntTypedArray(const TypedArrayDescriptor& descriptor, GPRReg base, GPRReg property, Node& node, size_t elementSize, TypedArraySpeculationRequirements speculationRequirements, TypedArraySignedness signedness, TypedArrayRounding rounding)
1771 {
1772     NodeUse baseUse = node.child1();
1773     NodeUse valueUse = node.child3();
1774     
1775     if (speculationRequirements != NoTypedArrayTypeSpecCheck)
1776         speculationCheck(BadType, JSValueSource::unboxedCell(base), baseUse, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
1777     GPRTemporary value;
1778     GPRReg valueGPR;
1779     
1780     if (at(valueUse).isConstant()) {
1781         JSValue jsValue = valueOfJSConstant(valueUse.index());
1782         if (!jsValue.isNumber()) {
1783             terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
1784             noResult(m_compileIndex);
1785             return;
1786         }
1787         double d = jsValue.asNumber();
1788         if (rounding == ClampRounding) {
1789             ASSERT(elementSize == 1);
1790             d = clampDoubleToByte(d);
1791         }
1792         GPRTemporary scratch(this);
1793         GPRReg scratchReg = scratch.gpr();
1794         m_jit.move(Imm32(static_cast<int>(d)), scratchReg);
1795         value.adopt(scratch);
1796         valueGPR = scratchReg;
1797     } else if (!at(valueUse).shouldNotSpeculateInteger()) {
1798         SpeculateIntegerOperand valueOp(this, valueUse);
1799         GPRTemporary scratch(this);
1800         GPRReg scratchReg = scratch.gpr();
1801         m_jit.move(valueOp.gpr(), scratchReg);
1802         if (rounding == ClampRounding) {
1803             ASSERT(elementSize == 1);
1804             compileClampIntegerToByte(m_jit, scratchReg);
1805         }
1806         value.adopt(scratch);
1807         valueGPR = scratchReg;
1808     } else if (rounding == ClampRounding) {
1809         ASSERT(elementSize == 1);
1810         SpeculateDoubleOperand valueOp(this, valueUse);
1811         GPRTemporary result(this);
1812         FPRTemporary floatScratch(this);
1813         FPRReg fpr = valueOp.fpr();
1814         GPRReg gpr = result.gpr();
1815         compileClampDoubleToByte(m_jit, gpr, fpr, floatScratch.fpr());
1816         value.adopt(result);
1817         valueGPR = gpr;
1818     } else {
1819         SpeculateDoubleOperand valueOp(this, valueUse);
1820         GPRTemporary result(this);
1821         FPRReg fpr = valueOp.fpr();
1822         GPRReg gpr = result.gpr();
1823         MacroAssembler::Jump notNaN = m_jit.branchDouble(MacroAssembler::DoubleEqual, fpr, fpr);
1824         m_jit.xorPtr(gpr, gpr);
1825         MacroAssembler::Jump fixed = m_jit.jump();
1826         notNaN.link(&m_jit);
1827
1828         MacroAssembler::Jump done;
1829         if (signedness == SignedTypedArray)
1830             done = m_jit.branchTruncateDoubleToInt32(fpr, gpr, MacroAssembler::BranchIfTruncateSuccessful);
1831         else
1832             done = m_jit.branchTruncateDoubleToUint32(fpr, gpr, MacroAssembler::BranchIfTruncateSuccessful);
1833
1834         silentSpillAllRegisters(gpr);
1835         callOperation(toInt32, gpr, fpr);
1836         silentFillAllRegisters(gpr);
1837
1838         done.link(&m_jit);
1839         fixed.link(&m_jit);
1840         value.adopt(result);
1841         valueGPR = gpr;
1842     }
1843     ASSERT_UNUSED(valueGPR, valueGPR != property);
1844     ASSERT(valueGPR != base);
1845     GPRTemporary storage(this);
1846     GPRReg storageReg = storage.gpr();
1847     ASSERT(valueGPR != storageReg);
1848     m_jit.loadPtr(MacroAssembler::Address(base, descriptor.m_storageOffset), storageReg);
1849     MacroAssembler::Jump outOfBounds;
1850     if (speculationRequirements != NoTypedArraySpecCheck)
1851         outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, property, MacroAssembler::Address(base, descriptor.m_lengthOffset));
1852
1853     switch (elementSize) {
1854     case 1:
1855         m_jit.store8(value.gpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesOne));
1856         break;
1857     case 2:
1858         m_jit.store16(value.gpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesTwo));
1859         break;
1860     case 4:
1861         m_jit.store32(value.gpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesFour));
1862         break;
1863     default:
1864         ASSERT_NOT_REACHED();
1865     }
1866     if (speculationRequirements != NoTypedArraySpecCheck)
1867         outOfBounds.link(&m_jit);
1868     noResult(m_compileIndex);
1869 }
1870
1871 void SpeculativeJIT::compileGetByValOnFloatTypedArray(const TypedArrayDescriptor& descriptor, Node& node, size_t elementSize, TypedArraySpeculationRequirements speculationRequirements)
1872 {
1873     SpeculateCellOperand base(this, node.child1());
1874     SpeculateStrictInt32Operand property(this, node.child2());
1875     StorageOperand storage(this, node.child3());
1876
1877     GPRReg baseReg = base.gpr();
1878     GPRReg propertyReg = property.gpr();
1879     GPRReg storageReg = storage.gpr();
1880     
1881     if (speculationRequirements != NoTypedArrayTypeSpecCheck) {
1882         ASSERT_NOT_REACHED();
1883         terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
1884         noResult(m_compileIndex);
1885         return;
1886     }
1887
1888     FPRTemporary result(this);
1889     FPRReg resultReg = result.fpr();
1890     ASSERT(speculationRequirements != NoTypedArraySpecCheck);
1891     MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(baseReg, descriptor.m_lengthOffset));
1892     static const double zero = 0;
1893     m_jit.loadDouble(&zero, resultReg);
1894     MacroAssembler::Jump outOfBounds = m_jit.jump();
1895     inBounds.link(&m_jit);
1896     switch (elementSize) {
1897     case 4:
1898         m_jit.loadFloat(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesFour), resultReg);
1899         m_jit.convertFloatToDouble(resultReg, resultReg);
1900         break;
1901     case 8: {
1902         m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
1903         MacroAssembler::Jump notNaN = m_jit.branchDouble(MacroAssembler::DoubleEqual, resultReg, resultReg);
1904         static const double NaN = std::numeric_limits<double>::quiet_NaN();
1905         m_jit.loadDouble(&NaN, resultReg);
1906         notNaN.link(&m_jit);
1907         break;
1908     }
1909     default:
1910         ASSERT_NOT_REACHED();
1911     }
1912     outOfBounds.link(&m_jit);
1913     doubleResult(resultReg, m_compileIndex);
1914 }
1915
1916 void SpeculativeJIT::compilePutByValForFloatTypedArray(const TypedArrayDescriptor& descriptor, GPRReg base, GPRReg property, Node& node, size_t elementSize, TypedArraySpeculationRequirements speculationRequirements)
1917 {
1918     NodeUse baseUse = node.child1();
1919     NodeUse valueUse = node.child3();
1920     
1921     SpeculateDoubleOperand valueOp(this, valueUse);
1922     
1923     if (speculationRequirements != NoTypedArrayTypeSpecCheck)
1924         speculationCheck(BadType, JSValueSource::unboxedCell(base), baseUse.index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
1925     
1926     GPRTemporary result(this);
1927     
1928     GPRTemporary storage(this);
1929     GPRReg storageReg = storage.gpr();
1930     
1931     m_jit.loadPtr(MacroAssembler::Address(base, descriptor.m_storageOffset), storageReg);
1932     MacroAssembler::Jump outOfBounds;
1933     if (speculationRequirements != NoTypedArraySpecCheck)
1934         outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, property, MacroAssembler::Address(base, descriptor.m_lengthOffset));
1935     
1936     switch (elementSize) {
1937     case 4: {
1938         FPRTemporary scratch(this);
1939         m_jit.moveDouble(valueOp.fpr(), scratch.fpr());
1940         m_jit.convertDoubleToFloat(valueOp.fpr(), scratch.fpr());
1941         m_jit.storeFloat(scratch.fpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesFour));
1942         break;
1943     }
1944     case 8:
1945         m_jit.storeDouble(valueOp.fpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesEight));
1946         break;
1947     default:
1948         ASSERT_NOT_REACHED();
1949     }
1950     if (speculationRequirements != NoTypedArraySpecCheck)
1951         outOfBounds.link(&m_jit);
1952     noResult(m_compileIndex);
1953 }
1954
1955 void SpeculativeJIT::compileInstanceOfForObject(Node&, GPRReg valueReg, GPRReg prototypeReg, GPRReg scratchReg)
1956 {
1957     // Check that prototype is an object.
1958     m_jit.loadPtr(MacroAssembler::Address(prototypeReg, JSCell::structureOffset()), scratchReg);
1959     speculationCheck(BadType, JSValueRegs(), NoNode, m_jit.branchIfNotObject(scratchReg));
1960     
1961     // Initialize scratchReg with the value being checked.
1962     m_jit.move(valueReg, scratchReg);
1963     
1964     // Walk up the prototype chain of the value (in scratchReg), comparing to prototypeReg.
1965     MacroAssembler::Label loop(&m_jit);
1966     m_jit.loadPtr(MacroAssembler::Address(scratchReg, JSCell::structureOffset()), scratchReg);
1967 #if USE(JSVALUE64)
1968     m_jit.loadPtr(MacroAssembler::Address(scratchReg, Structure::prototypeOffset()), scratchReg);
1969 #else
1970     m_jit.load32(MacroAssembler::Address(scratchReg, Structure::prototypeOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), scratchReg);
1971 #endif
1972     MacroAssembler::Jump isInstance = m_jit.branchPtr(MacroAssembler::Equal, scratchReg, prototypeReg);
1973 #if USE(JSVALUE64)
1974     m_jit.branchTestPtr(MacroAssembler::Zero, scratchReg, GPRInfo::tagMaskRegister).linkTo(loop, &m_jit);
1975 #else
1976     m_jit.branchTest32(MacroAssembler::NonZero, scratchReg).linkTo(loop, &m_jit);
1977 #endif
1978     
1979     // No match - result is false.
1980 #if USE(JSVALUE64)
1981     m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(false))), scratchReg);
1982 #else
1983     m_jit.move(MacroAssembler::TrustedImm32(0), scratchReg);
1984 #endif
1985     MacroAssembler::Jump putResult = m_jit.jump();
1986     
1987     isInstance.link(&m_jit);
1988 #if USE(JSVALUE64)
1989     m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(true))), scratchReg);
1990 #else
1991     m_jit.move(MacroAssembler::TrustedImm32(1), scratchReg);
1992 #endif
1993     
1994     putResult.link(&m_jit);
1995 }
1996
1997 void SpeculativeJIT::compileInstanceOf(Node& node)
1998 {
1999     if (!!(at(node.child1()).prediction() & ~PredictCell) && !!(m_state.forNode(node.child1()).m_type & ~PredictCell)) {
2000         // It might not be a cell. Speculate less aggressively.
2001         
2002         JSValueOperand value(this, node.child1());
2003         SpeculateCellOperand prototype(this, node.child3());
2004         GPRTemporary scratch(this);
2005         
2006         GPRReg prototypeReg = prototype.gpr();
2007         GPRReg scratchReg = scratch.gpr();
2008         
2009 #if USE(JSVALUE64)
2010         GPRReg valueReg = value.gpr();
2011         MacroAssembler::Jump isCell = m_jit.branchTestPtr(MacroAssembler::Zero, valueReg, GPRInfo::tagMaskRegister);
2012         m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(false))), scratchReg);
2013 #else
2014         GPRReg valueTagReg = value.tagGPR();
2015         GPRReg valueReg = value.payloadGPR();
2016         MacroAssembler::Jump isCell = m_jit.branch32(MacroAssembler::Equal, valueTagReg, TrustedImm32(JSValue::CellTag));
2017         m_jit.move(MacroAssembler::TrustedImm32(0), scratchReg);
2018 #endif
2019
2020         MacroAssembler::Jump done = m_jit.jump();
2021         
2022         isCell.link(&m_jit);
2023         
2024         compileInstanceOfForObject(node, valueReg, prototypeReg, scratchReg);
2025         
2026         done.link(&m_jit);
2027
2028 #if USE(JSVALUE64)
2029         jsValueResult(scratchReg, m_compileIndex, DataFormatJSBoolean);
2030 #else
2031         booleanResult(scratchReg, m_compileIndex);
2032 #endif
2033         return;
2034     }
2035     
2036     SpeculateCellOperand value(this, node.child1());
2037     // Base unused since we speculate default InstanceOf behaviour in CheckHasInstance.
2038     SpeculateCellOperand prototype(this, node.child3());
2039     
2040     GPRTemporary scratch(this);
2041     
2042     GPRReg valueReg = value.gpr();
2043     GPRReg prototypeReg = prototype.gpr();
2044     GPRReg scratchReg = scratch.gpr();
2045     
2046     compileInstanceOfForObject(node, valueReg, prototypeReg, scratchReg);
2047
2048 #if USE(JSVALUE64)
2049     jsValueResult(scratchReg, m_compileIndex, DataFormatJSBoolean);
2050 #else
2051     booleanResult(scratchReg, m_compileIndex);
2052 #endif
2053 }
2054
2055 static bool isPowerOfTwo(int32_t num)
2056 {
2057     return num && !(num & (num - 1));
2058 }
2059
2060 void SpeculativeJIT::compileSoftModulo(Node& node)
2061 {
2062     bool shouldGeneratePowerOfTwoCheck = true;
2063
2064     // In the fast path, the dividend value could be the final result
2065     // (in case of |dividend| < |divisor|), so we speculate it as strict int32.
2066     SpeculateStrictInt32Operand op1(this, node.child1());
2067     GPRReg op1Gpr = op1.gpr();
2068
2069     if (isInt32Constant(node.child2().index())) {
2070         int32_t divisor = valueOfInt32Constant(node.child2().index());
2071         if (divisor < 0)
2072             divisor = -divisor;
2073
2074         if (isPowerOfTwo(divisor)) {
2075             GPRTemporary result(this);
2076             GPRReg resultGPR = result.gpr();
2077             m_jit.move(op1Gpr, resultGPR);
2078             JITCompiler::Jump positiveDividend = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op1Gpr, TrustedImm32(0));
2079             m_jit.neg32(resultGPR);
2080             m_jit.and32(TrustedImm32(divisor - 1), resultGPR);
2081             m_jit.neg32(resultGPR);
2082             JITCompiler::Jump done = m_jit.jump();
2083
2084             positiveDividend.link(&m_jit);
2085             m_jit.and32(TrustedImm32(divisor - 1), resultGPR);
2086
2087             done.link(&m_jit);
2088             integerResult(resultGPR, m_compileIndex);
2089             return;
2090         }
2091 #if CPU(X86) || CPU(X86_64)
2092         if (divisor) {
2093             GPRTemporary eax(this, X86Registers::eax);
2094             GPRTemporary edx(this, X86Registers::edx);
2095             GPRTemporary scratch(this);
2096             GPRReg scratchGPR = scratch.gpr();
2097
2098             m_jit.move(op1Gpr, eax.gpr());
2099             m_jit.move(TrustedImm32(divisor), scratchGPR);
2100             m_jit.assembler().cdq();
2101             m_jit.assembler().idivl_r(scratchGPR);
2102             integerResult(edx.gpr(), m_compileIndex);
2103             return;
2104         }
2105 #endif
2106         // Fallback to non-constant case but avoid unnecessary checks.
2107         shouldGeneratePowerOfTwoCheck = false;
2108     }
2109
2110     SpeculateIntegerOperand op2(this, node.child2());
2111     GPRReg op2Gpr = op2.gpr();
2112
2113     speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(JITCompiler::Zero, op2Gpr));
2114
2115 #if CPU(X86) || CPU(X86_64)
2116     GPRTemporary eax(this, X86Registers::eax);
2117     GPRTemporary edx(this, X86Registers::edx);
2118     GPRReg temp2 = InvalidGPRReg;
2119     if (op2Gpr == X86Registers::eax || op2Gpr == X86Registers::edx) {
2120         temp2 = allocate();
2121         m_jit.move(op2Gpr, temp2);
2122         op2Gpr = temp2;
2123     }
2124     GPRReg resultGPR = edx.gpr();
2125     GPRReg scratchGPR = eax.gpr();
2126 #else
2127     GPRTemporary result(this);
2128     GPRTemporary scratch(this);
2129     GPRTemporary scratch3(this);
2130     GPRReg scratchGPR3 = scratch3.gpr();
2131     GPRReg resultGPR = result.gpr();
2132     GPRReg scratchGPR = scratch.gpr();
2133 #endif
2134
2135     GPRTemporary scratch2(this);
2136     GPRReg scratchGPR2 = scratch2.gpr();
2137     JITCompiler::JumpList exitBranch;
2138
2139     // resultGPR is to hold the ABS value of the dividend before final result is produced
2140     m_jit.move(op1Gpr, resultGPR);
2141     // scratchGPR2 is to hold the ABS value of the divisor
2142     m_jit.move(op2Gpr, scratchGPR2);
2143
2144     // Check for negative result remainder
2145     // According to ECMA-262, the sign of the result equals the sign of the dividend
2146     JITCompiler::Jump positiveDividend = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op1Gpr, TrustedImm32(0));
2147     m_jit.neg32(resultGPR);
2148     m_jit.move(TrustedImm32(1), scratchGPR);
2149     JITCompiler::Jump saveCondition = m_jit.jump();
2150
2151     positiveDividend.link(&m_jit);
2152     m_jit.move(TrustedImm32(0), scratchGPR);
2153
2154     // Save the condition for negative remainder
2155     saveCondition.link(&m_jit);
2156     m_jit.push(scratchGPR);
2157
2158     JITCompiler::Jump positiveDivisor = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op2Gpr, TrustedImm32(0));
2159     m_jit.neg32(scratchGPR2);
2160
2161     positiveDivisor.link(&m_jit);
2162     exitBranch.append(m_jit.branch32(JITCompiler::LessThan, resultGPR, scratchGPR2));
2163
2164     // Power of two fast case
2165     if (shouldGeneratePowerOfTwoCheck) {
2166         m_jit.move(scratchGPR2, scratchGPR);
2167         m_jit.sub32(TrustedImm32(1), scratchGPR);
2168         JITCompiler::Jump notPowerOfTwo = m_jit.branchTest32(JITCompiler::NonZero, scratchGPR, scratchGPR2);
2169         m_jit.and32(scratchGPR, resultGPR);
2170         exitBranch.append(m_jit.jump());
2171
2172         notPowerOfTwo.link(&m_jit);
2173     }
2174
2175 #if CPU(X86) || CPU(X86_64)
2176     m_jit.move(resultGPR, eax.gpr());
2177     m_jit.assembler().cdq();
2178     m_jit.assembler().idivl_r(scratchGPR2);
2179 #elif CPU(ARM_THUMB2)
2180     m_jit.countLeadingZeros32(scratchGPR2, scratchGPR);
2181     m_jit.countLeadingZeros32(resultGPR, scratchGPR3);
2182     m_jit.sub32(scratchGPR3, scratchGPR);
2183
2184     JITCompiler::Jump useFullTable = m_jit.branch32(JITCompiler::Equal, scratchGPR, TrustedImm32(31));
2185
2186     m_jit.neg32(scratchGPR);
2187     m_jit.add32(TrustedImm32(31), scratchGPR);
2188
2189     int elementSizeByShift = -1;
2190     elementSizeByShift = 3;
2191     m_jit.relativeTableJump(scratchGPR, elementSizeByShift);
2192
2193     useFullTable.link(&m_jit);
2194     // Modulo table
2195     for (int i = 31; i > 0; --i) {
2196         ShiftTypeAndAmount shift(SRType_LSL, i);
2197         m_jit.assembler().sub_S(scratchGPR, resultGPR, scratchGPR2, shift);
2198         m_jit.assembler().it(ARMv7Assembler::ConditionCS);
2199         m_jit.assembler().mov(resultGPR, scratchGPR);
2200     }
2201
2202     JITCompiler::Jump lower = m_jit.branch32(JITCompiler::Below, resultGPR, scratchGPR2);
2203     m_jit.sub32(scratchGPR2, resultGPR);
2204     lower.link(&m_jit);
2205 #endif // CPU(X86) || CPU(X86_64)
2206
2207     exitBranch.link(&m_jit);
2208
2209     // Check for negative remainder
2210     m_jit.pop(scratchGPR);
2211     JITCompiler::Jump positiveResult = m_jit.branch32(JITCompiler::Equal, scratchGPR, TrustedImm32(0));
2212     m_jit.neg32(resultGPR);
2213     positiveResult.link(&m_jit);
2214
2215     integerResult(resultGPR, m_compileIndex);
2216
2217 #if CPU(X86) || CPU(X86_64)
2218     if (temp2 != InvalidGPRReg)
2219         unlock(temp2);
2220 #endif
2221 }
2222
2223 void SpeculativeJIT::compileAdd(Node& node)
2224 {
2225     if (m_jit.graph().addShouldSpeculateInteger(node)) {
2226         if (isNumberConstant(node.child1().index())) {
2227             int32_t imm1 = valueOfNumberConstantAsInt32(node.child1().index());
2228             SpeculateIntegerOperand op2(this, node.child2());
2229             GPRTemporary result(this);
2230
2231             if (nodeCanTruncateInteger(node.arithNodeFlags())) {
2232                 m_jit.move(op2.gpr(), result.gpr());
2233                 m_jit.add32(Imm32(imm1), result.gpr());
2234             } else
2235                 speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchAdd32(MacroAssembler::Overflow, op2.gpr(), Imm32(imm1), result.gpr()));
2236
2237             integerResult(result.gpr(), m_compileIndex);
2238             return;
2239         }
2240                 
2241         if (isNumberConstant(node.child2().index())) {
2242             SpeculateIntegerOperand op1(this, node.child1());
2243             int32_t imm2 = valueOfNumberConstantAsInt32(node.child2().index());
2244             GPRTemporary result(this);
2245                 
2246             if (nodeCanTruncateInteger(node.arithNodeFlags())) {
2247                 m_jit.move(op1.gpr(), result.gpr());
2248                 m_jit.add32(Imm32(imm2), result.gpr());
2249             } else
2250                 speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchAdd32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
2251
2252             integerResult(result.gpr(), m_compileIndex);
2253             return;
2254         }
2255                 
2256         SpeculateIntegerOperand op1(this, node.child1());
2257         SpeculateIntegerOperand op2(this, node.child2());
2258         GPRTemporary result(this, op1, op2);
2259
2260         GPRReg gpr1 = op1.gpr();
2261         GPRReg gpr2 = op2.gpr();
2262         GPRReg gprResult = result.gpr();
2263
2264         if (nodeCanTruncateInteger(node.arithNodeFlags())) {
2265             if (gpr1 == gprResult)
2266                 m_jit.add32(gpr2, gprResult);
2267             else {
2268                 m_jit.move(gpr2, gprResult);
2269                 m_jit.add32(gpr1, gprResult);
2270             }
2271         } else {
2272             MacroAssembler::Jump check = m_jit.branchAdd32(MacroAssembler::Overflow, gpr1, gpr2, gprResult);
2273                 
2274             if (gpr1 == gprResult)
2275                 speculationCheck(Overflow, JSValueRegs(), NoNode, check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr2));
2276             else if (gpr2 == gprResult)
2277                 speculationCheck(Overflow, JSValueRegs(), NoNode, check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr1));
2278             else
2279                 speculationCheck(Overflow, JSValueRegs(), NoNode, check);
2280         }
2281
2282         integerResult(gprResult, m_compileIndex);
2283         return;
2284     }
2285         
2286     if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2()))) {
2287         SpeculateDoubleOperand op1(this, node.child1());
2288         SpeculateDoubleOperand op2(this, node.child2());
2289         FPRTemporary result(this, op1, op2);
2290
2291         FPRReg reg1 = op1.fpr();
2292         FPRReg reg2 = op2.fpr();
2293         m_jit.addDouble(reg1, reg2, result.fpr());
2294
2295         doubleResult(result.fpr(), m_compileIndex);
2296         return;
2297     }
2298
2299     if (node.op == ValueAdd) {
2300         compileValueAdd(node);
2301         return;
2302     }
2303     
2304     // We don't handle this yet. :-(
2305     terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
2306 }
2307
2308 void SpeculativeJIT::compileArithSub(Node& node)
2309 {
2310     if (m_jit.graph().addShouldSpeculateInteger(node)) {
2311         if (isNumberConstant(node.child2().index())) {
2312             SpeculateIntegerOperand op1(this, node.child1());
2313             int32_t imm2 = valueOfNumberConstantAsInt32(node.child2().index());
2314             GPRTemporary result(this);
2315
2316             if (nodeCanTruncateInteger(node.arithNodeFlags())) {
2317                 m_jit.move(op1.gpr(), result.gpr());
2318                 m_jit.sub32(Imm32(imm2), result.gpr());
2319             } else
2320                 speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
2321
2322             integerResult(result.gpr(), m_compileIndex);
2323             return;
2324         }
2325             
2326         if (isNumberConstant(node.child1().index())) {
2327             int32_t imm1 = valueOfNumberConstantAsInt32(node.child1().index());
2328             SpeculateIntegerOperand op2(this, node.child2());
2329             GPRTemporary result(this);
2330                 
2331             m_jit.move(Imm32(imm1), result.gpr());
2332             if (nodeCanTruncateInteger(node.arithNodeFlags()))
2333                 m_jit.sub32(op2.gpr(), result.gpr());
2334             else
2335                 speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchSub32(MacroAssembler::Overflow, op2.gpr(), result.gpr()));
2336                 
2337             integerResult(result.gpr(), m_compileIndex);
2338             return;
2339         }
2340             
2341         SpeculateIntegerOperand op1(this, node.child1());
2342         SpeculateIntegerOperand op2(this, node.child2());
2343         GPRTemporary result(this);
2344
2345         if (nodeCanTruncateInteger(node.arithNodeFlags())) {
2346             m_jit.move(op1.gpr(), result.gpr());
2347             m_jit.sub32(op2.gpr(), result.gpr());
2348         } else
2349             speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), op2.gpr(), result.gpr()));
2350
2351         integerResult(result.gpr(), m_compileIndex);
2352         return;
2353     }
2354         
2355     SpeculateDoubleOperand op1(this, node.child1());
2356     SpeculateDoubleOperand op2(this, node.child2());
2357     FPRTemporary result(this, op1);
2358
2359     FPRReg reg1 = op1.fpr();
2360     FPRReg reg2 = op2.fpr();
2361     m_jit.subDouble(reg1, reg2, result.fpr());
2362
2363     doubleResult(result.fpr(), m_compileIndex);
2364 }
2365
2366 void SpeculativeJIT::compileArithMul(Node& node)
2367 {
2368     if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) {
2369         SpeculateIntegerOperand op1(this, node.child1());
2370         SpeculateIntegerOperand op2(this, node.child2());
2371         GPRTemporary result(this);
2372
2373         GPRReg reg1 = op1.gpr();
2374         GPRReg reg2 = op2.gpr();
2375
2376         // What is unfortunate is that we cannot take advantage of nodeCanTruncateInteger()
2377         // here. A multiply on integers performed in the double domain and then truncated to
2378         // an integer will give a different result than a multiply performed in the integer
2379         // domain and then truncated, if the integer domain result would have resulted in
2380         // something bigger than what a 32-bit integer can hold. JavaScript mandates that
2381         // the semantics are always as if the multiply had been performed in the double
2382         // domain.
2383             
2384         speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchMul32(MacroAssembler::Overflow, reg1, reg2, result.gpr()));
2385             
2386         // Check for negative zero, if the users of this node care about such things.
2387         if (!nodeCanIgnoreNegativeZero(node.arithNodeFlags())) {
2388             MacroAssembler::Jump resultNonZero = m_jit.branchTest32(MacroAssembler::NonZero, result.gpr());
2389             speculationCheck(NegativeZero, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, reg1, TrustedImm32(0)));
2390             speculationCheck(NegativeZero, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, reg2, TrustedImm32(0)));
2391             resultNonZero.link(&m_jit);
2392         }
2393
2394         integerResult(result.gpr(), m_compileIndex);
2395         return;
2396     }
2397
2398     SpeculateDoubleOperand op1(this, node.child1());
2399     SpeculateDoubleOperand op2(this, node.child2());
2400     FPRTemporary result(this, op1, op2);
2401
2402     FPRReg reg1 = op1.fpr();
2403     FPRReg reg2 = op2.fpr();
2404         
2405     m_jit.mulDouble(reg1, reg2, result.fpr());
2406         
2407     doubleResult(result.fpr(), m_compileIndex);
2408 }
2409
2410 void SpeculativeJIT::compileArithMod(Node& node)
2411 {
2412     if (!at(node.child1()).shouldNotSpeculateInteger() && !at(node.child2()).shouldNotSpeculateInteger()
2413         && node.canSpeculateInteger()) {
2414         compileSoftModulo(node);
2415         return;
2416     }
2417         
2418     SpeculateDoubleOperand op1(this, node.child1());
2419     SpeculateDoubleOperand op2(this, node.child2());
2420         
2421     FPRReg op1FPR = op1.fpr();
2422     FPRReg op2FPR = op2.fpr();
2423         
2424     flushRegisters();
2425         
2426     FPRResult result(this);
2427
2428     callOperation(fmodAsDFGOperation, result.fpr(), op1FPR, op2FPR);
2429         
2430     doubleResult(result.fpr(), m_compileIndex);
2431 }
2432
2433 // Returns true if the compare is fused with a subsequent branch.
2434 bool SpeculativeJIT::compare(Node& node, MacroAssembler::RelationalCondition condition, MacroAssembler::DoubleCondition doubleCondition, S_DFGOperation_EJJ operation)
2435 {
2436     if (compilePeepHoleBranch(node, condition, doubleCondition, operation))
2437         return true;
2438
2439     if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())))
2440         compileIntegerCompare(node, condition);
2441     else if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2())))
2442         compileDoubleCompare(node, doubleCondition);
2443     else if (node.op == CompareEq && Node::shouldSpeculateFinalObject(at(node.child1()), at(node.child2())))
2444         compileObjectEquality(node, &JSFinalObject::s_info, isFinalObjectPrediction);
2445     else if (node.op == CompareEq && Node::shouldSpeculateArray(at(node.child1()), at(node.child2())))
2446         compileObjectEquality(node, &JSArray::s_info, isArrayPrediction);
2447     else
2448         nonSpeculativeNonPeepholeCompare(node, condition, operation);
2449     
2450     return false;
2451 }
2452
2453 bool SpeculativeJIT::compileStrictEqForConstant(Node& node, NodeUse value, JSValue constant)
2454 {
2455     JSValueOperand op1(this, value);
2456     
2457     NodeIndex branchNodeIndex = detectPeepHoleBranch();
2458     if (branchNodeIndex != NoNode) {
2459         Node& branchNode = at(branchNodeIndex);
2460         BlockIndex taken = branchNode.takenBlockIndex();
2461         BlockIndex notTaken = branchNode.notTakenBlockIndex();
2462         MacroAssembler::RelationalCondition condition = MacroAssembler::Equal;
2463         
2464         // The branch instruction will branch to the taken block.
2465         // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
2466         if (taken == (m_block + 1)) {
2467             condition = MacroAssembler::NotEqual;
2468             BlockIndex tmp = taken;
2469             taken = notTaken;
2470             notTaken = tmp;
2471         }
2472
2473 #if USE(JSVALUE64)
2474         branchPtr(condition, op1.gpr(), MacroAssembler::TrustedImmPtr(bitwise_cast<void*>(JSValue::encode(constant))), taken);
2475 #else
2476         GPRReg payloadGPR = op1.payloadGPR();
2477         GPRReg tagGPR = op1.tagGPR();
2478         if (condition == MacroAssembler::Equal) {
2479             // Drop down if not equal, go elsewhere if equal.
2480             MacroAssembler::Jump notEqual = m_jit.branch32(MacroAssembler::NotEqual, tagGPR, MacroAssembler::Imm32(constant.tag()));
2481             branch32(MacroAssembler::Equal, payloadGPR, MacroAssembler::Imm32(constant.payload()), taken);
2482             notEqual.link(&m_jit);
2483         } else {
2484             // Drop down if equal, go elsehwere if not equal.
2485             branch32(MacroAssembler::NotEqual, tagGPR, MacroAssembler::Imm32(constant.tag()), taken);
2486             branch32(MacroAssembler::NotEqual, payloadGPR, MacroAssembler::Imm32(constant.payload()), taken);
2487         }
2488 #endif
2489         
2490         jump(notTaken);
2491         
2492         use(node.child1());
2493         use(node.child2());
2494         m_compileIndex = branchNodeIndex;
2495         return true;
2496     }
2497     
2498     GPRTemporary result(this);
2499     
2500 #if USE(JSVALUE64)
2501     GPRReg op1GPR = op1.gpr();
2502     GPRReg resultGPR = result.gpr();
2503     m_jit.move(MacroAssembler::TrustedImmPtr(bitwise_cast<void*>(ValueFalse)), resultGPR);
2504     MacroAssembler::Jump notEqual = m_jit.branchPtr(MacroAssembler::NotEqual, op1GPR, MacroAssembler::TrustedImmPtr(bitwise_cast<void*>(JSValue::encode(constant))));
2505     m_jit.or32(MacroAssembler::Imm32(1), resultGPR);
2506     notEqual.link(&m_jit);
2507     jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean);
2508 #else
2509     GPRReg op1PayloadGPR = op1.payloadGPR();
2510     GPRReg op1TagGPR = op1.tagGPR();
2511     GPRReg resultGPR = result.gpr();
2512     m_jit.move(Imm32(0), resultGPR);
2513     MacroAssembler::JumpList notEqual;
2514     notEqual.append(m_jit.branch32(MacroAssembler::NotEqual, op1TagGPR, MacroAssembler::Imm32(constant.tag())));
2515     notEqual.append(m_jit.branch32(MacroAssembler::NotEqual, op1PayloadGPR, MacroAssembler::Imm32(constant.payload())));
2516     m_jit.move(Imm32(1), resultGPR);
2517     notEqual.link(&m_jit);
2518     booleanResult(resultGPR, m_compileIndex);
2519 #endif
2520     
2521     return false;
2522 }
2523
2524 bool SpeculativeJIT::compileStrictEq(Node& node)
2525 {
2526     // 1) If either operand is a constant and that constant is not a double, integer,
2527     //    or string, then do a JSValue comparison.
2528     
2529     if (isJSConstant(node.child1().index())) {
2530         JSValue value = valueOfJSConstant(node.child1().index());
2531         if (!value.isNumber() && !value.isString())
2532             return compileStrictEqForConstant(node, node.child2(), value);
2533     }
2534     
2535     if (isJSConstant(node.child2().index())) {
2536         JSValue value = valueOfJSConstant(node.child2().index());
2537         if (!value.isNumber() && !value.isString())
2538             return compileStrictEqForConstant(node, node.child1(), value);
2539     }
2540     
2541     // 2) If the operands are predicted integer, do an integer comparison.
2542     
2543     if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2()))) {
2544         NodeIndex branchNodeIndex = detectPeepHoleBranch();
2545         if (branchNodeIndex != NoNode) {
2546             compilePeepHoleIntegerBranch(node, branchNodeIndex, MacroAssembler::Equal);
2547             use(node.child1());
2548             use(node.child2());
2549             m_compileIndex = branchNodeIndex;
2550             return true;
2551         }
2552         compileIntegerCompare(node, MacroAssembler::Equal);
2553         return false;
2554     }
2555     
2556     // 3) If the operands are predicted double, do a double comparison.
2557     
2558     if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2()))) {
2559         NodeIndex branchNodeIndex = detectPeepHoleBranch();
2560         if (branchNodeIndex != NoNode) {
2561             compilePeepHoleDoubleBranch(node, branchNodeIndex, MacroAssembler::DoubleEqual);
2562             use(node.child1());
2563             use(node.child2());
2564             m_compileIndex = branchNodeIndex;
2565             return true;
2566         }
2567         compileDoubleCompare(node, MacroAssembler::DoubleEqual);
2568         return false;
2569     }
2570     
2571     // 4) If the operands are predicted final object or array, then do a final object
2572     //    or array comparison.
2573     
2574     if (Node::shouldSpeculateFinalObject(at(node.child1()), at(node.child2()))) {
2575         NodeIndex branchNodeIndex = detectPeepHoleBranch();
2576         if (branchNodeIndex != NoNode) {
2577             compilePeepHoleObjectEquality(node, branchNodeIndex, &JSFinalObject::s_info, isFinalObjectPrediction);
2578             use(node.child1());
2579             use(node.child2());
2580             m_compileIndex = branchNodeIndex;
2581             return true;
2582         }
2583         compileObjectEquality(node, &JSFinalObject::s_info, isFinalObjectPrediction);
2584         return false;
2585     }
2586     
2587     if (Node::shouldSpeculateArray(at(node.child1()), at(node.child2()))) {
2588         NodeIndex branchNodeIndex = detectPeepHoleBranch();
2589         if (branchNodeIndex != NoNode) {
2590             compilePeepHoleObjectEquality(node, branchNodeIndex, &JSArray::s_info, isArrayPrediction);
2591             use(node.child1());
2592             use(node.child2());
2593             m_compileIndex = branchNodeIndex;
2594             return true;
2595         }
2596         compileObjectEquality(node, &JSArray::s_info, isArrayPrediction);
2597         return false;
2598     }
2599     
2600     // 5) Fall back to non-speculative strict equality.
2601     
2602     return nonSpeculativeStrictEq(node);
2603 }
2604
2605 void SpeculativeJIT::compileGetIndexedPropertyStorage(Node& node)
2606 {
2607     if (!node.prediction() || !at(node.child1()).prediction() || !at(node.child2()).prediction()) {
2608         terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
2609         return;
2610     }
2611         
2612     SpeculateCellOperand base(this, node.child1());
2613     GPRReg baseReg = base.gpr();
2614     
2615     PredictedType basePrediction = at(node.child2()).prediction();
2616     if (!(basePrediction & PredictInt32) && basePrediction) {
2617         ASSERT_NOT_REACHED();
2618         terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
2619         noResult(m_compileIndex);
2620         return;
2621     }
2622     
2623     GPRTemporary storage(this);
2624     GPRReg storageReg = storage.gpr();
2625     if (at(node.child1()).prediction() == PredictString) {
2626         if (!isStringPrediction(m_state.forNode(node.child1()).m_type))
2627             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSString::s_info)));
2628
2629         m_jit.loadPtr(MacroAssembler::Address(baseReg, JSString::offsetOfValue()), storageReg);
2630         
2631         // Speculate that we're not accessing a rope
2632         speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTest32(MacroAssembler::Zero, storageReg));
2633
2634         m_jit.loadPtr(MacroAssembler::Address(storageReg, StringImpl::dataOffset()), storageReg);
2635     } else if (at(node.child1()).shouldSpeculateByteArray()) {
2636         if (!isByteArrayPrediction(m_state.forNode(node.child1()).m_type))
2637             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info)));
2638         m_jit.loadPtr(MacroAssembler::Address(baseReg, JSByteArray::offsetOfStorage()), storageReg);
2639     } else if (at(node.child1()).shouldSpeculateInt8Array()) {
2640         const TypedArrayDescriptor& descriptor = m_jit.globalData()->int8ArrayDescriptor();
2641         if (!isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type))
2642             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
2643         m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
2644     } else if (at(node.child1()).shouldSpeculateInt16Array()) {
2645         const TypedArrayDescriptor& descriptor = m_jit.globalData()->int16ArrayDescriptor();
2646         if (!isInt16ArrayPrediction(m_state.forNode(node.child1()).m_type))
2647             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
2648         m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
2649     } else if (at(node.child1()).shouldSpeculateInt32Array()) {
2650         const TypedArrayDescriptor& descriptor = m_jit.globalData()->int32ArrayDescriptor();
2651         if (!isInt32ArrayPrediction(m_state.forNode(node.child1()).m_type))
2652             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
2653         m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
2654     } else if (at(node.child1()).shouldSpeculateUint8Array()) {
2655         const TypedArrayDescriptor& descriptor = m_jit.globalData()->uint8ArrayDescriptor();
2656         if (!isUint8ArrayPrediction(m_state.forNode(node.child1()).m_type))
2657             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
2658         m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
2659     } else if (at(node.child1()).shouldSpeculateUint8ClampedArray()) {
2660         const TypedArrayDescriptor& descriptor = m_jit.globalData()->uint8ClampedArrayDescriptor();
2661         if (!isUint8ClampedArrayPrediction(m_state.forNode(node.child1()).m_type))
2662             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
2663         m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
2664     } else if (at(node.child1()).shouldSpeculateUint16Array()) {
2665         const TypedArrayDescriptor& descriptor = m_jit.globalData()->uint16ArrayDescriptor();
2666         if (!isUint16ArrayPrediction(m_state.forNode(node.child1()).m_type))
2667             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
2668         m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
2669     } else if (at(node.child1()).shouldSpeculateUint32Array()) {
2670         const TypedArrayDescriptor& descriptor = m_jit.globalData()->uint32ArrayDescriptor();
2671         if (!isUint32ArrayPrediction(m_state.forNode(node.child1()).m_type))
2672             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
2673         m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
2674     } else if (at(node.child1()).shouldSpeculateFloat32Array()) {
2675         const TypedArrayDescriptor& descriptor = m_jit.globalData()->float32ArrayDescriptor();
2676         if (!isFloat32ArrayPrediction(m_state.forNode(node.child1()).m_type))
2677             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
2678         m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
2679     } else if (at(node.child1()).shouldSpeculateFloat64Array()) {
2680         const TypedArrayDescriptor& descriptor = m_jit.globalData()->float64ArrayDescriptor();
2681         if (!isFloat64ArrayPrediction(m_state.forNode(node.child1()).m_type))
2682             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo)));
2683         m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor.m_storageOffset), storageReg);
2684     } else {
2685         if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
2686             speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
2687         m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
2688     }
2689     storageResult(storageReg, m_compileIndex);
2690 }
2691
2692 void SpeculativeJIT::compileNewFunctionNoCheck(Node& node)
2693 {
2694     GPRResult result(this);
2695     GPRReg resultGPR = result.gpr();
2696     flushRegisters();
2697     callOperation(
2698         operationNewFunction, resultGPR, m_jit.codeBlock()->functionDecl(node.functionDeclIndex()));
2699     cellResult(resultGPR, m_compileIndex);
2700 }
2701
2702 void SpeculativeJIT::compileNewFunctionExpression(Node& node)
2703 {
2704     GPRResult result(this);
2705     GPRReg resultGPR = result.gpr();
2706     flushRegisters();
2707     callOperation(
2708         operationNewFunctionExpression,
2709         resultGPR,
2710         m_jit.codeBlock()->functionExpr(node.functionExprIndex()));
2711     cellResult(resultGPR, m_compileIndex);
2712 }
2713
2714 } } // namespace JSC::DFG
2715
2716 #endif