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