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