f26d6387a38fe88ad49cc596dade25fa9b44976e
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGSpeculativeJIT64.cpp
1 /*
2  * Copyright (C) 2011, 2012 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 "Arguments.h"
32 #include "ArrayPrototype.h"
33 #include "DFGCallArrayAllocatorSlowPathGenerator.h"
34 #include "DFGSlowPathGenerator.h"
35 #include "ObjectPrototype.h"
36
37 namespace JSC { namespace DFG {
38
39 #if USE(JSVALUE64)
40
41 GPRReg SpeculativeJIT::fillInteger(NodeIndex nodeIndex, DataFormat& returnFormat)
42 {
43     Node& node = at(nodeIndex);
44     VirtualRegister virtualRegister = node.virtualRegister();
45     GenerationInfo& info = m_generationInfo[virtualRegister];
46
47     if (info.registerFormat() == DataFormatNone) {
48         GPRReg gpr = allocate();
49
50         if (node.hasConstant()) {
51             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
52             if (isInt32Constant(nodeIndex)) {
53                 m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gpr);
54                 info.fillInteger(*m_stream, gpr);
55                 returnFormat = DataFormatInteger;
56                 return gpr;
57             }
58             if (isNumberConstant(nodeIndex)) {
59                 JSValue jsValue = jsNumber(valueOfNumberConstant(nodeIndex));
60                 m_jit.move(MacroAssembler::Imm64(JSValue::encode(jsValue)), gpr);
61             } else {
62                 ASSERT(isJSConstant(nodeIndex));
63                 JSValue jsValue = valueOfJSConstant(nodeIndex);
64                 m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsValue)), gpr);
65             }
66         } else if (info.spillFormat() == DataFormatInteger) {
67             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
68             m_jit.load32(JITCompiler::payloadFor(virtualRegister), gpr);
69             // Tag it, since fillInteger() is used when we want a boxed integer.
70             m_jit.or64(GPRInfo::tagTypeNumberRegister, gpr);
71         } else {
72             ASSERT(info.spillFormat() == DataFormatJS || info.spillFormat() == DataFormatJSInteger);
73             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
74             m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
75         }
76
77         // Since we statically know that we're filling an integer, and values
78         // in the JSStack are boxed, this must be DataFormatJSInteger.
79         // We will check this with a jitAssert below.
80         info.fillJSValue(*m_stream, gpr, DataFormatJSInteger);
81         unlock(gpr);
82     }
83     
84     switch (info.registerFormat()) {
85     case DataFormatNone:
86         // Should have filled, above.
87     case DataFormatJSDouble:
88     case DataFormatDouble:
89     case DataFormatJS:
90     case DataFormatCell:
91     case DataFormatJSCell:
92     case DataFormatBoolean:
93     case DataFormatJSBoolean:
94     case DataFormatStorage:
95         // Should only be calling this function if we know this operand to be integer.
96         ASSERT_NOT_REACHED();
97
98     case DataFormatJSInteger: {
99         GPRReg gpr = info.gpr();
100         m_gprs.lock(gpr);
101         m_jit.jitAssertIsJSInt32(gpr);
102         returnFormat = DataFormatJSInteger;
103         return gpr;
104     }
105
106     case DataFormatInteger: {
107         GPRReg gpr = info.gpr();
108         m_gprs.lock(gpr);
109         m_jit.jitAssertIsInt32(gpr);
110         returnFormat = DataFormatInteger;
111         return gpr;
112     }
113         
114     default:
115         ASSERT_NOT_REACHED();
116         return InvalidGPRReg;
117     }
118 }
119
120 FPRReg SpeculativeJIT::fillDouble(NodeIndex nodeIndex)
121 {
122     Node& node = at(nodeIndex);
123     VirtualRegister virtualRegister = node.virtualRegister();
124     GenerationInfo& info = m_generationInfo[virtualRegister];
125
126     if (info.registerFormat() == DataFormatNone) {
127         if (node.hasConstant()) {
128             GPRReg gpr = allocate();
129         
130             if (isInt32Constant(nodeIndex)) {
131                 // FIXME: should not be reachable?
132                 m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gpr);
133                 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
134                 info.fillInteger(*m_stream, gpr);
135                 unlock(gpr);
136             } else if (isNumberConstant(nodeIndex)) {
137                 FPRReg fpr = fprAllocate();
138                 m_jit.move(MacroAssembler::Imm64(reinterpretDoubleToInt64(valueOfNumberConstant(nodeIndex))), gpr);
139                 m_jit.move64ToDouble(gpr, fpr);
140                 unlock(gpr);
141
142                 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
143                 info.fillDouble(*m_stream, fpr);
144                 return fpr;
145             } else {
146                 // FIXME: should not be reachable?
147                 ASSERT(isJSConstant(nodeIndex));
148                 JSValue jsValue = valueOfJSConstant(nodeIndex);
149                 m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsValue)), gpr);
150                 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
151                 info.fillJSValue(*m_stream, gpr, DataFormatJS);
152                 unlock(gpr);
153             }
154         } else {
155             DataFormat spillFormat = info.spillFormat();
156             switch (spillFormat) {
157             case DataFormatDouble: {
158                 FPRReg fpr = fprAllocate();
159                 m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
160                 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
161                 info.fillDouble(*m_stream, fpr);
162                 return fpr;
163             }
164                 
165             case DataFormatInteger: {
166                 GPRReg gpr = allocate();
167                 
168                 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
169                 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
170                 info.fillInteger(*m_stream, gpr);
171                 unlock(gpr);
172                 break;
173             }
174
175             default:
176                 GPRReg gpr = allocate();
177         
178                 ASSERT(spillFormat & DataFormatJS);
179                 m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
180                 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
181                 info.fillJSValue(*m_stream, gpr, spillFormat);
182                 unlock(gpr);
183                 break;
184             }
185         }
186     }
187
188     switch (info.registerFormat()) {
189     case DataFormatNone:
190         // Should have filled, above.
191     case DataFormatCell:
192     case DataFormatJSCell:
193     case DataFormatBoolean:
194     case DataFormatJSBoolean:
195     case DataFormatStorage:
196         // Should only be calling this function if we know this operand to be numeric.
197         ASSERT_NOT_REACHED();
198
199     case DataFormatJS: {
200         GPRReg jsValueGpr = info.gpr();
201         m_gprs.lock(jsValueGpr);
202         FPRReg fpr = fprAllocate();
203         GPRReg tempGpr = allocate(); // FIXME: can we skip this allocation on the last use of the virtual register?
204
205         JITCompiler::Jump isInteger = m_jit.branch64(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
206
207         m_jit.jitAssertIsJSDouble(jsValueGpr);
208
209         // First, if we get here we have a double encoded as a JSValue
210         m_jit.move(jsValueGpr, tempGpr);
211         unboxDouble(tempGpr, fpr);
212         JITCompiler::Jump hasUnboxedDouble = m_jit.jump();
213
214         // Finally, handle integers.
215         isInteger.link(&m_jit);
216         m_jit.convertInt32ToDouble(jsValueGpr, fpr);
217         hasUnboxedDouble.link(&m_jit);
218
219         m_gprs.release(jsValueGpr);
220         m_gprs.unlock(jsValueGpr);
221         m_gprs.unlock(tempGpr);
222         m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
223         info.fillDouble(*m_stream, fpr);
224         info.killSpilled();
225         return fpr;
226     }
227
228     case DataFormatJSInteger:
229     case DataFormatInteger: {
230         FPRReg fpr = fprAllocate();
231         GPRReg gpr = info.gpr();
232         m_gprs.lock(gpr);
233         m_jit.convertInt32ToDouble(gpr, fpr);
234         m_gprs.unlock(gpr);
235         return fpr;
236     }
237
238     // Unbox the double
239     case DataFormatJSDouble: {
240         GPRReg gpr = info.gpr();
241         FPRReg fpr = fprAllocate();
242         if (m_gprs.isLocked(gpr)) {
243             // Make sure we don't trample gpr if it is in use.
244             GPRReg temp = allocate();
245             m_jit.move(gpr, temp);
246             unboxDouble(temp, fpr);
247             unlock(temp);
248         } else
249             unboxDouble(gpr, fpr);
250
251         m_gprs.release(gpr);
252         m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
253
254         info.fillDouble(*m_stream, fpr);
255         return fpr;
256     }
257
258     case DataFormatDouble: {
259         FPRReg fpr = info.fpr();
260         m_fprs.lock(fpr);
261         return fpr;
262     }
263         
264     default:
265         ASSERT_NOT_REACHED();
266         return InvalidFPRReg;
267     }
268 }
269
270 GPRReg SpeculativeJIT::fillJSValue(NodeIndex nodeIndex)
271 {
272     Node& node = at(nodeIndex);
273     VirtualRegister virtualRegister = node.virtualRegister();
274     GenerationInfo& info = m_generationInfo[virtualRegister];
275     
276     switch (info.registerFormat()) {
277     case DataFormatNone: {
278         GPRReg gpr = allocate();
279
280         if (node.hasConstant()) {
281             if (isInt32Constant(nodeIndex)) {
282                 info.fillJSValue(*m_stream, gpr, DataFormatJSInteger);
283                 JSValue jsValue = jsNumber(valueOfInt32Constant(nodeIndex));
284                 m_jit.move(MacroAssembler::Imm64(JSValue::encode(jsValue)), gpr);
285             } else if (isNumberConstant(nodeIndex)) {
286                 info.fillJSValue(*m_stream, gpr, DataFormatJSDouble);
287                 JSValue jsValue(JSValue::EncodeAsDouble, valueOfNumberConstant(nodeIndex));
288                 m_jit.move(MacroAssembler::Imm64(JSValue::encode(jsValue)), gpr);
289             } else {
290                 ASSERT(isJSConstant(nodeIndex));
291                 JSValue jsValue = valueOfJSConstant(nodeIndex);
292                 m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsValue)), gpr);
293                 info.fillJSValue(*m_stream, gpr, DataFormatJS);
294             }
295
296             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
297         } else {
298             DataFormat spillFormat = info.spillFormat();
299             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
300             if (spillFormat == DataFormatInteger) {
301                 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
302                 m_jit.or64(GPRInfo::tagTypeNumberRegister, gpr);
303                 spillFormat = DataFormatJSInteger;
304             } else {
305                 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
306                 if (spillFormat == DataFormatDouble) {
307                     // Need to box the double, since we want a JSValue.
308                     m_jit.sub64(GPRInfo::tagTypeNumberRegister, gpr);
309                     spillFormat = DataFormatJSDouble;
310                 } else
311                     ASSERT(spillFormat & DataFormatJS);
312             }
313             info.fillJSValue(*m_stream, gpr, spillFormat);
314         }
315         return gpr;
316     }
317
318     case DataFormatInteger: {
319         GPRReg gpr = info.gpr();
320         // If the register has already been locked we need to take a copy.
321         // If not, we'll zero extend in place, so mark on the info that this is now type DataFormatInteger, not DataFormatJSInteger.
322         if (m_gprs.isLocked(gpr)) {
323             GPRReg result = allocate();
324             m_jit.or64(GPRInfo::tagTypeNumberRegister, gpr, result);
325             return result;
326         }
327         m_gprs.lock(gpr);
328         m_jit.or64(GPRInfo::tagTypeNumberRegister, gpr);
329         info.fillJSValue(*m_stream, gpr, DataFormatJSInteger);
330         return gpr;
331     }
332
333     case DataFormatDouble: {
334         FPRReg fpr = info.fpr();
335         GPRReg gpr = boxDouble(fpr);
336
337         // Update all info
338         info.fillJSValue(*m_stream, gpr, DataFormatJSDouble);
339         m_fprs.release(fpr);
340         m_gprs.retain(gpr, virtualRegister, SpillOrderJS);
341
342         return gpr;
343     }
344
345     case DataFormatCell:
346         // No retag required on JSVALUE64!
347     case DataFormatJS:
348     case DataFormatJSInteger:
349     case DataFormatJSDouble:
350     case DataFormatJSCell:
351     case DataFormatJSBoolean: {
352         GPRReg gpr = info.gpr();
353         m_gprs.lock(gpr);
354         return gpr;
355     }
356         
357     case DataFormatBoolean:
358     case DataFormatStorage:
359         // this type currently never occurs
360         ASSERT_NOT_REACHED();
361         
362     default:
363         ASSERT_NOT_REACHED();
364         return InvalidGPRReg;
365     }
366 }
367
368 class ValueToNumberSlowPathGenerator
369     : public CallSlowPathGenerator<MacroAssembler::Jump, D_DFGOperation_EJ, GPRReg> {
370 public:
371     ValueToNumberSlowPathGenerator(
372         MacroAssembler::Jump from, SpeculativeJIT* jit,
373         GPRReg resultGPR, GPRReg jsValueGPR)
374         : CallSlowPathGenerator<MacroAssembler::Jump, D_DFGOperation_EJ, GPRReg>(
375             from, jit, dfgConvertJSValueToNumber, NeedToSpill, resultGPR)
376         , m_jsValueGPR(jsValueGPR)
377     {
378     }
379
380 protected:
381     virtual void generateInternal(SpeculativeJIT* jit)
382     {
383         setUp(jit);
384         recordCall(jit->callOperation(dfgConvertJSValueToNumber, FPRInfo::returnValueFPR, m_jsValueGPR));
385         jit->boxDouble(FPRInfo::returnValueFPR, m_result);
386         tearDown(jit);
387     }
388
389 private:
390     GPRReg m_jsValueGPR;
391 };
392
393 void SpeculativeJIT::nonSpeculativeValueToNumber(Node& node)
394 {
395     if (isKnownNumeric(node.child1().index())) {
396         JSValueOperand op1(this, node.child1());
397         GPRTemporary result(this, op1);
398         m_jit.move(op1.gpr(), result.gpr());
399         jsValueResult(result.gpr(), m_compileIndex);
400         return;
401     }
402
403     JSValueOperand op1(this, node.child1());
404     GPRTemporary result(this);
405     
406     ASSERT(!isInt32Constant(node.child1().index()));
407     ASSERT(!isNumberConstant(node.child1().index()));
408     
409     GPRReg jsValueGpr = op1.gpr();
410     GPRReg gpr = result.gpr();
411     op1.use();
412
413     JITCompiler::Jump isInteger = m_jit.branch64(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
414     JITCompiler::Jump nonNumeric = m_jit.branchTest64(MacroAssembler::Zero, jsValueGpr, GPRInfo::tagTypeNumberRegister);
415
416     // First, if we get here we have a double encoded as a JSValue
417     m_jit.move(jsValueGpr, gpr);
418     JITCompiler::Jump hasUnboxedDouble = m_jit.jump();
419
420     // Finally, handle integers.
421     isInteger.link(&m_jit);
422     m_jit.or64(GPRInfo::tagTypeNumberRegister, jsValueGpr, gpr);
423     hasUnboxedDouble.link(&m_jit);
424     
425     addSlowPathGenerator(adoptPtr(new ValueToNumberSlowPathGenerator(nonNumeric, this, gpr, jsValueGpr)));
426     
427     jsValueResult(result.gpr(), m_compileIndex, UseChildrenCalledExplicitly);
428 }
429
430 void SpeculativeJIT::nonSpeculativeValueToInt32(Node& node)
431 {
432     ASSERT(!isInt32Constant(node.child1().index()));
433     
434     if (isKnownInteger(node.child1().index())) {
435         IntegerOperand op1(this, node.child1());
436         GPRTemporary result(this, op1);
437         m_jit.zeroExtend32ToPtr(op1.gpr(), result.gpr());
438         integerResult(result.gpr(), m_compileIndex);
439         return;
440     }
441     
442     GenerationInfo& childInfo = m_generationInfo[at(node.child1()).virtualRegister()];
443     if (childInfo.isJSDouble()) {
444         DoubleOperand op1(this, node.child1());
445         GPRTemporary result(this);
446         FPRReg fpr = op1.fpr();
447         GPRReg gpr = result.gpr();
448         op1.use();
449         JITCompiler::Jump notTruncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateFailed);
450         
451         addSlowPathGenerator(
452             slowPathCall(notTruncatedToInteger, this, toInt32, gpr, fpr));
453
454         integerResult(gpr, m_compileIndex, UseChildrenCalledExplicitly);
455         return;
456     }
457     
458     JSValueOperand op1(this, node.child1());
459     GPRTemporary result(this, op1);
460     GPRReg jsValueGpr = op1.gpr();
461     GPRReg resultGPR = result.gpr();
462     op1.use();
463
464     JITCompiler::Jump isNotInteger = m_jit.branch64(MacroAssembler::Below, jsValueGpr, GPRInfo::tagTypeNumberRegister);
465
466     m_jit.zeroExtend32ToPtr(jsValueGpr, resultGPR);
467     
468     addSlowPathGenerator(
469         slowPathCall(isNotInteger, this, dfgConvertJSValueToInt32, resultGPR, jsValueGpr));
470
471     integerResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
472 }
473
474 void SpeculativeJIT::nonSpeculativeUInt32ToNumber(Node& node)
475 {
476     IntegerOperand op1(this, node.child1());
477     FPRTemporary boxer(this);
478     GPRTemporary result(this, op1);
479     
480     JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, op1.gpr(), TrustedImm32(0));
481     
482     m_jit.convertInt32ToDouble(op1.gpr(), boxer.fpr());
483     m_jit.addDouble(JITCompiler::AbsoluteAddress(&AssemblyHelpers::twoToThe32), boxer.fpr());
484     
485     boxDouble(boxer.fpr(), result.gpr());
486     
487     JITCompiler::Jump done = m_jit.jump();
488     
489     positive.link(&m_jit);
490     
491     m_jit.or64(GPRInfo::tagTypeNumberRegister, op1.gpr(), result.gpr());
492     
493     done.link(&m_jit);
494     
495     jsValueResult(result.gpr(), m_compileIndex);
496 }
497
498 void SpeculativeJIT::cachedGetById(CodeOrigin codeOrigin, GPRReg baseGPR, GPRReg resultGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget, SpillRegistersMode spillMode)
499 {
500     JITCompiler::DataLabelPtr structureToCompare;
501     JITCompiler::PatchableJump structureCheck = m_jit.patchableBranchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1)));
502     
503     JITCompiler::ConvertibleLoadLabel propertyStorageLoad =
504         m_jit.convertibleLoadPtr(JITCompiler::Address(baseGPR, JSObject::butterflyOffset()), resultGPR);
505     JITCompiler::DataLabelCompact loadWithPatch = m_jit.load64WithCompactAddressOffsetPatch(JITCompiler::Address(resultGPR, 0), resultGPR);
506     
507     JITCompiler::Label doneLabel = m_jit.label();
508
509     OwnPtr<SlowPathGenerator> slowPath;
510     if (!slowPathTarget.isSet()) {
511         slowPath = slowPathCall(
512             structureCheck.m_jump, this, operationGetByIdOptimize, resultGPR, baseGPR,
513             identifier(identifierNumber), spillMode);
514     } else {
515         JITCompiler::JumpList slowCases;
516         slowCases.append(structureCheck.m_jump);
517         slowCases.append(slowPathTarget);
518         slowPath = slowPathCall(
519             slowCases, this, operationGetByIdOptimize, resultGPR, baseGPR,
520             identifier(identifierNumber), spillMode);
521     }
522     m_jit.addPropertyAccess(
523         PropertyAccessRecord(
524             codeOrigin, structureToCompare, structureCheck, propertyStorageLoad, loadWithPatch,
525             slowPath.get(), doneLabel, safeCast<int8_t>(baseGPR), safeCast<int8_t>(resultGPR),
526             usedRegisters(),
527             spillMode == NeedToSpill ? PropertyAccessRecord::RegistersInUse : PropertyAccessRecord::RegistersFlushed));
528     addSlowPathGenerator(slowPath.release());
529 }
530
531 void SpeculativeJIT::cachedPutById(CodeOrigin codeOrigin, GPRReg baseGPR, GPRReg valueGPR, Edge valueUse, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget)
532 {
533     
534     JITCompiler::DataLabelPtr structureToCompare;
535     JITCompiler::PatchableJump structureCheck = m_jit.patchableBranchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1)));
536
537     writeBarrier(baseGPR, valueGPR, valueUse, WriteBarrierForPropertyAccess, scratchGPR);
538
539     JITCompiler::ConvertibleLoadLabel propertyStorageLoad =
540         m_jit.convertibleLoadPtr(JITCompiler::Address(baseGPR, JSObject::butterflyOffset()), scratchGPR);
541     JITCompiler::DataLabel32 storeWithPatch = m_jit.store64WithAddressOffsetPatch(valueGPR, JITCompiler::Address(scratchGPR, 0));
542
543     JITCompiler::Label doneLabel = m_jit.label();
544     
545     V_DFGOperation_EJCI optimizedCall;
546     if (m_jit.strictModeFor(at(m_compileIndex).codeOrigin)) {
547         if (putKind == Direct)
548             optimizedCall = operationPutByIdDirectStrictOptimize;
549         else
550             optimizedCall = operationPutByIdStrictOptimize;
551     } else {
552         if (putKind == Direct)
553             optimizedCall = operationPutByIdDirectNonStrictOptimize;
554         else
555             optimizedCall = operationPutByIdNonStrictOptimize;
556     }
557     OwnPtr<SlowPathGenerator> slowPath;
558     if (!slowPathTarget.isSet()) {
559         slowPath = slowPathCall(
560             structureCheck.m_jump, this, optimizedCall, NoResult, valueGPR, baseGPR,
561             identifier(identifierNumber));
562     } else {
563         JITCompiler::JumpList slowCases;
564         slowCases.append(structureCheck.m_jump);
565         slowCases.append(slowPathTarget);
566         slowPath = slowPathCall(
567             slowCases, this, optimizedCall, NoResult, valueGPR, baseGPR,
568             identifier(identifierNumber));
569     }
570     RegisterSet currentlyUsedRegisters = usedRegisters();
571     currentlyUsedRegisters.clear(scratchGPR);
572     ASSERT(currentlyUsedRegisters.get(baseGPR));
573     ASSERT(currentlyUsedRegisters.get(valueGPR));
574     m_jit.addPropertyAccess(
575         PropertyAccessRecord(
576             codeOrigin, structureToCompare, structureCheck, propertyStorageLoad,
577             JITCompiler::DataLabelCompact(storeWithPatch.label()), slowPath.get(), doneLabel,
578             safeCast<int8_t>(baseGPR), safeCast<int8_t>(valueGPR), currentlyUsedRegisters));
579     addSlowPathGenerator(slowPath.release());
580 }
581
582 void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull(Edge operand, bool invert)
583 {
584     JSValueOperand arg(this, operand);
585     GPRReg argGPR = arg.gpr();
586     
587     GPRTemporary result(this, arg);
588     GPRReg resultGPR = result.gpr();
589     
590     JITCompiler::Jump notCell;
591     
592     if (!isKnownCell(operand.index()))
593         notCell = m_jit.branchTest64(MacroAssembler::NonZero, argGPR, GPRInfo::tagMaskRegister);
594    
595     JITCompiler::Jump notMasqueradesAsUndefined;
596     if (m_jit.graph().globalObjectFor(m_jit.graph()[operand].codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) {
597         m_jit.graph().globalObjectFor(m_jit.graph()[operand].codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint());
598         m_jit.move(invert ? TrustedImm32(1) : TrustedImm32(0), resultGPR);
599         notMasqueradesAsUndefined = m_jit.jump();
600     } else {
601         m_jit.loadPtr(JITCompiler::Address(argGPR, JSCell::structureOffset()), resultGPR);
602         JITCompiler::Jump isMasqueradesAsUndefined = m_jit.branchTest8(JITCompiler::NonZero, JITCompiler::Address(resultGPR, Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(MasqueradesAsUndefined));
603
604         m_jit.move(invert ? TrustedImm32(1) : TrustedImm32(0), resultGPR);
605         notMasqueradesAsUndefined = m_jit.jump();
606
607         isMasqueradesAsUndefined.link(&m_jit);
608         GPRTemporary localGlobalObject(this);
609         GPRTemporary remoteGlobalObject(this);
610         GPRReg localGlobalObjectGPR = localGlobalObject.gpr();
611         GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr();
612         m_jit.move(JITCompiler::TrustedImmPtr(m_jit.graph().globalObjectFor(m_jit.graph()[operand].codeOrigin)), localGlobalObjectGPR);
613         m_jit.loadPtr(JITCompiler::Address(resultGPR, Structure::globalObjectOffset()), remoteGlobalObjectGPR);
614         m_jit.comparePtr(invert ? JITCompiler::NotEqual : JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, resultGPR);
615     }
616  
617     if (!isKnownCell(operand.index())) {
618         JITCompiler::Jump done = m_jit.jump();
619         
620         notCell.link(&m_jit);
621         
622         m_jit.move(argGPR, resultGPR);
623         m_jit.and64(JITCompiler::TrustedImm32(~TagBitUndefined), resultGPR);
624         m_jit.compare64(invert ? JITCompiler::NotEqual : JITCompiler::Equal, resultGPR, JITCompiler::TrustedImm32(ValueNull), resultGPR);
625         
626         done.link(&m_jit);
627     }
628    
629     notMasqueradesAsUndefined.link(&m_jit);
630  
631     m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
632     jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean);
633 }
634
635 void SpeculativeJIT::nonSpeculativePeepholeBranchNull(Edge operand, NodeIndex branchNodeIndex, bool invert)
636 {
637     Node& branchNode = at(branchNodeIndex);
638     BlockIndex taken = branchNode.takenBlockIndex();
639     BlockIndex notTaken = branchNode.notTakenBlockIndex();
640     
641     if (taken == nextBlock()) {
642         invert = !invert;
643         BlockIndex tmp = taken;
644         taken = notTaken;
645         notTaken = tmp;
646     }
647
648     JSValueOperand arg(this, operand);
649     GPRReg argGPR = arg.gpr();
650     
651     GPRTemporary result(this, arg);
652     GPRReg resultGPR = result.gpr();
653     
654     JITCompiler::Jump notCell;
655     
656     if (!isKnownCell(operand.index()))
657         notCell = m_jit.branchTest64(MacroAssembler::NonZero, argGPR, GPRInfo::tagMaskRegister);
658     
659     if (m_jit.graph().globalObjectFor(m_jit.graph()[operand].codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) {
660         m_jit.graph().globalObjectFor(m_jit.graph()[operand].codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint());
661         jump(invert ? taken : notTaken, ForceJump);
662     } else {
663         m_jit.loadPtr(JITCompiler::Address(argGPR, JSCell::structureOffset()), resultGPR);
664         branchTest8(JITCompiler::Zero, JITCompiler::Address(resultGPR, Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(MasqueradesAsUndefined), invert ? taken : notTaken);
665    
666         GPRTemporary localGlobalObject(this);
667         GPRTemporary remoteGlobalObject(this);
668         GPRReg localGlobalObjectGPR = localGlobalObject.gpr();
669         GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr();
670         m_jit.move(TrustedImmPtr(m_jit.graph().globalObjectFor(m_jit.graph()[operand].codeOrigin)), localGlobalObjectGPR);
671         m_jit.loadPtr(JITCompiler::Address(resultGPR, Structure::globalObjectOffset()), remoteGlobalObjectGPR);
672         branchPtr(JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, invert ? notTaken : taken);
673     }
674  
675     if (!isKnownCell(operand.index())) {
676         jump(notTaken, ForceJump);
677         
678         notCell.link(&m_jit);
679         
680         m_jit.move(argGPR, resultGPR);
681         m_jit.and64(JITCompiler::TrustedImm32(~TagBitUndefined), resultGPR);
682         branch64(invert ? JITCompiler::NotEqual : JITCompiler::Equal, resultGPR, JITCompiler::TrustedImm64(ValueNull), taken);
683     }
684     
685     jump(notTaken);
686 }
687
688 bool SpeculativeJIT::nonSpeculativeCompareNull(Node& node, Edge operand, bool invert)
689 {
690     unsigned branchIndexInBlock = detectPeepHoleBranch();
691     if (branchIndexInBlock != UINT_MAX) {
692         NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
693
694         ASSERT(node.adjustedRefCount() == 1);
695         
696         nonSpeculativePeepholeBranchNull(operand, branchNodeIndex, invert);
697     
698         use(node.child1());
699         use(node.child2());
700         m_indexInBlock = branchIndexInBlock;
701         m_compileIndex = branchNodeIndex;
702         
703         return true;
704     }
705     
706     nonSpeculativeNonPeepholeCompareNull(operand, invert);
707     
708     return false;
709 }
710
711 void SpeculativeJIT::nonSpeculativePeepholeBranch(Node& node, NodeIndex branchNodeIndex, MacroAssembler::RelationalCondition cond, S_DFGOperation_EJJ helperFunction)
712 {
713     Node& branchNode = at(branchNodeIndex);
714     BlockIndex taken = branchNode.takenBlockIndex();
715     BlockIndex notTaken = branchNode.notTakenBlockIndex();
716
717     JITCompiler::ResultCondition callResultCondition = JITCompiler::NonZero;
718
719     // The branch instruction will branch to the taken block.
720     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
721     if (taken == nextBlock()) {
722         cond = JITCompiler::invert(cond);
723         callResultCondition = JITCompiler::Zero;
724         BlockIndex tmp = taken;
725         taken = notTaken;
726         notTaken = tmp;
727     }
728
729     JSValueOperand arg1(this, node.child1());
730     JSValueOperand arg2(this, node.child2());
731     GPRReg arg1GPR = arg1.gpr();
732     GPRReg arg2GPR = arg2.gpr();
733     
734     JITCompiler::JumpList slowPath;
735     
736     if (isKnownNotInteger(node.child1().index()) || isKnownNotInteger(node.child2().index())) {
737         GPRResult result(this);
738         GPRReg resultGPR = result.gpr();
739     
740         arg1.use();
741         arg2.use();
742     
743         flushRegisters();
744         callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);
745
746         branchTest32(callResultCondition, resultGPR, taken);
747     } else {
748         GPRTemporary result(this, arg2);
749         GPRReg resultGPR = result.gpr();
750     
751         arg1.use();
752         arg2.use();
753     
754         if (!isKnownInteger(node.child1().index()))
755             slowPath.append(m_jit.branch64(MacroAssembler::Below, arg1GPR, GPRInfo::tagTypeNumberRegister));
756         if (!isKnownInteger(node.child2().index()))
757             slowPath.append(m_jit.branch64(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister));
758     
759         branch32(cond, arg1GPR, arg2GPR, taken);
760     
761         if (!isKnownInteger(node.child1().index()) || !isKnownInteger(node.child2().index())) {
762             jump(notTaken, ForceJump);
763     
764             slowPath.link(&m_jit);
765     
766             silentSpillAllRegisters(resultGPR);
767             callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);
768             silentFillAllRegisters(resultGPR);
769         
770             branchTest32(callResultCondition, resultGPR, taken);
771         }
772     }
773
774     jump(notTaken);
775
776     m_indexInBlock = m_jit.graph().m_blocks[m_block]->size() - 1;
777     m_compileIndex = branchNodeIndex;
778 }
779
780 template<typename JumpType>
781 class CompareAndBoxBooleanSlowPathGenerator
782     : public CallSlowPathGenerator<JumpType, S_DFGOperation_EJJ, GPRReg> {
783 public:
784     CompareAndBoxBooleanSlowPathGenerator(
785         JumpType from, SpeculativeJIT* jit,
786         S_DFGOperation_EJJ function, GPRReg result, GPRReg arg1, GPRReg arg2)
787         : CallSlowPathGenerator<JumpType, S_DFGOperation_EJJ, GPRReg>(
788             from, jit, function, NeedToSpill, result)
789         , m_arg1(arg1)
790         , m_arg2(arg2)
791     {
792     }
793     
794 protected:
795     virtual void generateInternal(SpeculativeJIT* jit)
796     {
797         this->setUp(jit);
798         this->recordCall(jit->callOperation(this->m_function, this->m_result, m_arg1, m_arg2));
799         jit->m_jit.and32(JITCompiler::TrustedImm32(1), this->m_result);
800         jit->m_jit.or32(JITCompiler::TrustedImm32(ValueFalse), this->m_result);
801         this->tearDown(jit);
802     }
803    
804 private:
805     GPRReg m_arg1;
806     GPRReg m_arg2;
807 };
808
809 void SpeculativeJIT::nonSpeculativeNonPeepholeCompare(Node& node, MacroAssembler::RelationalCondition cond, S_DFGOperation_EJJ helperFunction)
810 {
811     JSValueOperand arg1(this, node.child1());
812     JSValueOperand arg2(this, node.child2());
813     GPRReg arg1GPR = arg1.gpr();
814     GPRReg arg2GPR = arg2.gpr();
815     
816     JITCompiler::JumpList slowPath;
817     
818     if (isKnownNotInteger(node.child1().index()) || isKnownNotInteger(node.child2().index())) {
819         GPRResult result(this);
820         GPRReg resultGPR = result.gpr();
821     
822         arg1.use();
823         arg2.use();
824     
825         flushRegisters();
826         callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);
827         
828         m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
829         jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly);
830     } else {
831         GPRTemporary result(this, arg2);
832         GPRReg resultGPR = result.gpr();
833
834         arg1.use();
835         arg2.use();
836     
837         if (!isKnownInteger(node.child1().index()))
838             slowPath.append(m_jit.branch64(MacroAssembler::Below, arg1GPR, GPRInfo::tagTypeNumberRegister));
839         if (!isKnownInteger(node.child2().index()))
840             slowPath.append(m_jit.branch64(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister));
841     
842         m_jit.compare32(cond, arg1GPR, arg2GPR, resultGPR);
843         m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
844         
845         if (!isKnownInteger(node.child1().index()) || !isKnownInteger(node.child2().index())) {
846             addSlowPathGenerator(adoptPtr(
847                 new CompareAndBoxBooleanSlowPathGenerator<JITCompiler::JumpList>(
848                     slowPath, this, helperFunction, resultGPR, arg1GPR, arg2GPR)));
849         }
850
851         jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly);
852     }
853 }
854
855 void SpeculativeJIT::nonSpeculativePeepholeStrictEq(Node& node, NodeIndex branchNodeIndex, bool invert)
856 {
857     Node& branchNode = at(branchNodeIndex);
858     BlockIndex taken = branchNode.takenBlockIndex();
859     BlockIndex notTaken = branchNode.notTakenBlockIndex();
860
861     // The branch instruction will branch to the taken block.
862     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
863     if (taken == nextBlock()) {
864         invert = !invert;
865         BlockIndex tmp = taken;
866         taken = notTaken;
867         notTaken = tmp;
868     }
869     
870     JSValueOperand arg1(this, node.child1());
871     JSValueOperand arg2(this, node.child2());
872     GPRReg arg1GPR = arg1.gpr();
873     GPRReg arg2GPR = arg2.gpr();
874     
875     GPRTemporary result(this);
876     GPRReg resultGPR = result.gpr();
877     
878     arg1.use();
879     arg2.use();
880     
881     if (isKnownCell(node.child1().index()) && isKnownCell(node.child2().index())) {
882         // see if we get lucky: if the arguments are cells and they reference the same
883         // cell, then they must be strictly equal.
884         branch64(JITCompiler::Equal, arg1GPR, arg2GPR, invert ? notTaken : taken);
885         
886         silentSpillAllRegisters(resultGPR);
887         callOperation(operationCompareStrictEqCell, resultGPR, arg1GPR, arg2GPR);
888         silentFillAllRegisters(resultGPR);
889         
890         branchTest32(invert ? JITCompiler::Zero : JITCompiler::NonZero, resultGPR, taken);
891     } else {
892         m_jit.or64(arg1GPR, arg2GPR, resultGPR);
893         
894         JITCompiler::Jump twoCellsCase = m_jit.branchTest64(JITCompiler::Zero, resultGPR, GPRInfo::tagMaskRegister);
895         
896         JITCompiler::Jump leftOK = m_jit.branch64(JITCompiler::AboveOrEqual, arg1GPR, GPRInfo::tagTypeNumberRegister);
897         JITCompiler::Jump leftDouble = m_jit.branchTest64(JITCompiler::NonZero, arg1GPR, GPRInfo::tagTypeNumberRegister);
898         leftOK.link(&m_jit);
899         JITCompiler::Jump rightOK = m_jit.branch64(JITCompiler::AboveOrEqual, arg2GPR, GPRInfo::tagTypeNumberRegister);
900         JITCompiler::Jump rightDouble = m_jit.branchTest64(JITCompiler::NonZero, arg2GPR, GPRInfo::tagTypeNumberRegister);
901         rightOK.link(&m_jit);
902         
903         branch64(invert ? JITCompiler::NotEqual : JITCompiler::Equal, arg1GPR, arg2GPR, taken);
904         jump(notTaken, ForceJump);
905         
906         twoCellsCase.link(&m_jit);
907         branch64(JITCompiler::Equal, arg1GPR, arg2GPR, invert ? notTaken : taken);
908         
909         leftDouble.link(&m_jit);
910         rightDouble.link(&m_jit);
911         
912         silentSpillAllRegisters(resultGPR);
913         callOperation(operationCompareStrictEq, resultGPR, arg1GPR, arg2GPR);
914         silentFillAllRegisters(resultGPR);
915         
916         branchTest32(invert ? JITCompiler::Zero : JITCompiler::NonZero, resultGPR, taken);
917     }
918     
919     jump(notTaken);
920 }
921
922 void SpeculativeJIT::nonSpeculativeNonPeepholeStrictEq(Node& node, bool invert)
923 {
924     JSValueOperand arg1(this, node.child1());
925     JSValueOperand arg2(this, node.child2());
926     GPRReg arg1GPR = arg1.gpr();
927     GPRReg arg2GPR = arg2.gpr();
928     
929     GPRTemporary result(this);
930     GPRReg resultGPR = result.gpr();
931     
932     arg1.use();
933     arg2.use();
934     
935     if (isKnownCell(node.child1().index()) && isKnownCell(node.child2().index())) {
936         // see if we get lucky: if the arguments are cells and they reference the same
937         // cell, then they must be strictly equal.
938         // FIXME: this should flush registers instead of silent spill/fill.
939         JITCompiler::Jump notEqualCase = m_jit.branch64(JITCompiler::NotEqual, arg1GPR, arg2GPR);
940         
941         m_jit.move(JITCompiler::TrustedImm64(JSValue::encode(jsBoolean(!invert))), resultGPR);
942         
943         JITCompiler::Jump done = m_jit.jump();
944
945         notEqualCase.link(&m_jit);
946         
947         silentSpillAllRegisters(resultGPR);
948         callOperation(operationCompareStrictEqCell, resultGPR, arg1GPR, arg2GPR);
949         silentFillAllRegisters(resultGPR);
950         
951         m_jit.and64(JITCompiler::TrustedImm32(1), resultGPR);
952         m_jit.or32(JITCompiler::TrustedImm32(ValueFalse), resultGPR);
953         
954         done.link(&m_jit);
955     } else {
956         m_jit.or64(arg1GPR, arg2GPR, resultGPR);
957         
958         JITCompiler::JumpList slowPathCases;
959         
960         JITCompiler::Jump twoCellsCase = m_jit.branchTest64(JITCompiler::Zero, resultGPR, GPRInfo::tagMaskRegister);
961         
962         JITCompiler::Jump leftOK = m_jit.branch64(JITCompiler::AboveOrEqual, arg1GPR, GPRInfo::tagTypeNumberRegister);
963         slowPathCases.append(m_jit.branchTest64(JITCompiler::NonZero, arg1GPR, GPRInfo::tagTypeNumberRegister));
964         leftOK.link(&m_jit);
965         JITCompiler::Jump rightOK = m_jit.branch64(JITCompiler::AboveOrEqual, arg2GPR, GPRInfo::tagTypeNumberRegister);
966         slowPathCases.append(m_jit.branchTest64(JITCompiler::NonZero, arg2GPR, GPRInfo::tagTypeNumberRegister));
967         rightOK.link(&m_jit);
968         
969         m_jit.compare64(invert ? JITCompiler::NotEqual : JITCompiler::Equal, arg1GPR, arg2GPR, resultGPR);
970         m_jit.or32(JITCompiler::TrustedImm32(ValueFalse), resultGPR);
971         
972         JITCompiler::Jump done = m_jit.jump();
973         
974         twoCellsCase.link(&m_jit);
975         slowPathCases.append(m_jit.branch64(JITCompiler::NotEqual, arg1GPR, arg2GPR));
976         
977         m_jit.move(JITCompiler::TrustedImm64(JSValue::encode(jsBoolean(!invert))), resultGPR);
978         
979         addSlowPathGenerator(
980             adoptPtr(
981                 new CompareAndBoxBooleanSlowPathGenerator<MacroAssembler::JumpList>(
982                     slowPathCases, this, operationCompareStrictEq, resultGPR, arg1GPR,
983                     arg2GPR)));
984         
985         done.link(&m_jit);
986     }
987     
988     jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly);
989 }
990
991 void SpeculativeJIT::emitCall(Node& node)
992 {
993     if (node.op() != Call)
994         ASSERT(node.op() == Construct);
995
996     // For constructors, the this argument is not passed but we have to make space
997     // for it.
998     int dummyThisArgument = node.op() == Call ? 0 : 1;
999     
1000     CallLinkInfo::CallType callType = node.op() == Call ? CallLinkInfo::Call : CallLinkInfo::Construct;
1001     
1002     Edge calleeEdge = m_jit.graph().m_varArgChildren[node.firstChild()];
1003     JSValueOperand callee(this, calleeEdge);
1004     GPRReg calleeGPR = callee.gpr();
1005     use(calleeEdge);
1006     
1007     // The call instruction's first child is the function; the subsequent children are the
1008     // arguments.
1009     int numPassedArgs = node.numChildren() - 1;
1010     
1011     m_jit.store32(MacroAssembler::TrustedImm32(numPassedArgs + dummyThisArgument), callFramePayloadSlot(JSStack::ArgumentCount));
1012     m_jit.store64(GPRInfo::callFrameRegister, callFrameSlot(JSStack::CallerFrame));
1013     m_jit.store64(calleeGPR, callFrameSlot(JSStack::Callee));
1014     
1015     for (int i = 0; i < numPassedArgs; i++) {
1016         Edge argEdge = m_jit.graph().m_varArgChildren[node.firstChild() + 1 + i];
1017         JSValueOperand arg(this, argEdge);
1018         GPRReg argGPR = arg.gpr();
1019         use(argEdge);
1020         
1021         m_jit.store64(argGPR, argumentSlot(i + dummyThisArgument));
1022     }
1023
1024     flushRegisters();
1025
1026     GPRResult result(this);
1027     GPRReg resultGPR = result.gpr();
1028
1029     JITCompiler::DataLabelPtr targetToCheck;
1030     JITCompiler::JumpList slowPath;
1031
1032     CallBeginToken token;
1033     m_jit.beginCall(node.codeOrigin, token);
1034     
1035     m_jit.addPtr(TrustedImm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister);
1036     
1037     slowPath.append(m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleeGPR, targetToCheck, MacroAssembler::TrustedImmPtr(0)));
1038
1039     m_jit.loadPtr(MacroAssembler::Address(calleeGPR, OBJECT_OFFSETOF(JSFunction, m_scope)), resultGPR);
1040     m_jit.store64(resultGPR, MacroAssembler::Address(GPRInfo::callFrameRegister, static_cast<ptrdiff_t>(sizeof(Register)) * JSStack::ScopeChain));
1041
1042     CodeOrigin codeOrigin = at(m_compileIndex).codeOrigin;
1043     JITCompiler::Call fastCall = m_jit.nearCall();
1044     m_jit.notifyCall(fastCall, codeOrigin, token);
1045     
1046     JITCompiler::Jump done = m_jit.jump();
1047     
1048     slowPath.link(&m_jit);
1049     
1050     m_jit.move(calleeGPR, GPRInfo::nonArgGPR0);
1051     m_jit.prepareForExceptionCheck();
1052     JITCompiler::Call slowCall = m_jit.nearCall();
1053     m_jit.notifyCall(slowCall, codeOrigin, token);
1054     
1055     done.link(&m_jit);
1056     
1057     m_jit.move(GPRInfo::returnValueGPR, resultGPR);
1058     
1059     jsValueResult(resultGPR, m_compileIndex, DataFormatJS, UseChildrenCalledExplicitly);
1060     
1061     m_jit.addJSCall(fastCall, slowCall, targetToCheck, callType, calleeGPR, at(m_compileIndex).codeOrigin);
1062 }
1063
1064 template<bool strict>
1065 GPRReg SpeculativeJIT::fillSpeculateIntInternal(NodeIndex nodeIndex, DataFormat& returnFormat)
1066 {
1067 #if DFG_ENABLE(DEBUG_VERBOSE)
1068     dataLog("SpecInt@%d   ", nodeIndex);
1069 #endif
1070     SpeculatedType type = m_state.forNode(nodeIndex).m_type;
1071     Node& node = at(nodeIndex);
1072     VirtualRegister virtualRegister = node.virtualRegister();
1073     GenerationInfo& info = m_generationInfo[virtualRegister];
1074
1075     switch (info.registerFormat()) {
1076     case DataFormatNone: {
1077         if ((node.hasConstant() && !isInt32Constant(nodeIndex)) || info.spillFormat() == DataFormatDouble) {
1078             terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
1079             returnFormat = DataFormatInteger;
1080             return allocate();
1081         }
1082         
1083         GPRReg gpr = allocate();
1084
1085         if (node.hasConstant()) {
1086             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1087             ASSERT(isInt32Constant(nodeIndex));
1088             m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gpr);
1089             info.fillInteger(*m_stream, gpr);
1090             returnFormat = DataFormatInteger;
1091             return gpr;
1092         }
1093         
1094         DataFormat spillFormat = info.spillFormat();
1095         
1096         ASSERT((spillFormat & DataFormatJS) || spillFormat == DataFormatInteger);
1097         
1098         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1099         
1100         if (spillFormat == DataFormatJSInteger || spillFormat == DataFormatInteger) {
1101             // If we know this was spilled as an integer we can fill without checking.
1102             if (strict) {
1103                 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
1104                 info.fillInteger(*m_stream, gpr);
1105                 returnFormat = DataFormatInteger;
1106                 return gpr;
1107             }
1108             if (spillFormat == DataFormatInteger) {
1109                 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
1110                 m_jit.or64(GPRInfo::tagTypeNumberRegister, gpr);
1111             } else
1112                 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1113             info.fillJSValue(*m_stream, gpr, DataFormatJSInteger);
1114             returnFormat = DataFormatJSInteger;
1115             return gpr;
1116         }
1117         m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1118
1119         // Fill as JSValue, and fall through.
1120         info.fillJSValue(*m_stream, gpr, DataFormatJSInteger);
1121         m_gprs.unlock(gpr);
1122     }
1123
1124     case DataFormatJS: {
1125         // Check the value is an integer.
1126         GPRReg gpr = info.gpr();
1127         m_gprs.lock(gpr);
1128         if (!isInt32Speculation(type))
1129             speculationCheck(BadType, JSValueRegs(gpr), nodeIndex, m_jit.branch64(MacroAssembler::Below, gpr, GPRInfo::tagTypeNumberRegister));
1130         info.fillJSValue(*m_stream, gpr, DataFormatJSInteger);
1131         // If !strict we're done, return.
1132         if (!strict) {
1133             returnFormat = DataFormatJSInteger;
1134             return gpr;
1135         }
1136         // else fall through & handle as DataFormatJSInteger.
1137         m_gprs.unlock(gpr);
1138     }
1139
1140     case DataFormatJSInteger: {
1141         // In a strict fill we need to strip off the value tag.
1142         if (strict) {
1143             GPRReg gpr = info.gpr();
1144             GPRReg result;
1145             // If the register has already been locked we need to take a copy.
1146             // If not, we'll zero extend in place, so mark on the info that this is now type DataFormatInteger, not DataFormatJSInteger.
1147             if (m_gprs.isLocked(gpr))
1148                 result = allocate();
1149             else {
1150                 m_gprs.lock(gpr);
1151                 info.fillInteger(*m_stream, gpr);
1152                 result = gpr;
1153             }
1154             m_jit.zeroExtend32ToPtr(gpr, result);
1155             returnFormat = DataFormatInteger;
1156             return result;
1157         }
1158
1159         GPRReg gpr = info.gpr();
1160         m_gprs.lock(gpr);
1161         returnFormat = DataFormatJSInteger;
1162         return gpr;
1163     }
1164
1165     case DataFormatInteger: {
1166         GPRReg gpr = info.gpr();
1167         m_gprs.lock(gpr);
1168         returnFormat = DataFormatInteger;
1169         return gpr;
1170     }
1171
1172     case DataFormatDouble:
1173     case DataFormatJSDouble: {
1174         if (node.hasConstant() && isInt32Constant(nodeIndex)) {
1175             GPRReg gpr = allocate();
1176             ASSERT(isInt32Constant(nodeIndex));
1177             m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(nodeIndex)), gpr);
1178             returnFormat = DataFormatInteger;
1179             return gpr;
1180         }
1181     }
1182     case DataFormatCell:
1183     case DataFormatBoolean:
1184     case DataFormatJSCell:
1185     case DataFormatJSBoolean: {
1186         terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
1187         returnFormat = DataFormatInteger;
1188         return allocate();
1189     }
1190
1191     case DataFormatStorage:
1192         ASSERT_NOT_REACHED();
1193         
1194     default:
1195         ASSERT_NOT_REACHED();
1196         return InvalidGPRReg;
1197     }
1198 }
1199
1200 GPRReg SpeculativeJIT::fillSpeculateInt(NodeIndex nodeIndex, DataFormat& returnFormat)
1201 {
1202     return fillSpeculateIntInternal<false>(nodeIndex, returnFormat);
1203 }
1204
1205 GPRReg SpeculativeJIT::fillSpeculateIntStrict(NodeIndex nodeIndex)
1206 {
1207     DataFormat mustBeDataFormatInteger;
1208     GPRReg result = fillSpeculateIntInternal<true>(nodeIndex, mustBeDataFormatInteger);
1209     ASSERT(mustBeDataFormatInteger == DataFormatInteger);
1210     return result;
1211 }
1212
1213 FPRReg SpeculativeJIT::fillSpeculateDouble(NodeIndex nodeIndex)
1214 {
1215 #if DFG_ENABLE(DEBUG_VERBOSE)
1216     dataLog("SpecDouble@%d   ", nodeIndex);
1217 #endif
1218     SpeculatedType type = m_state.forNode(nodeIndex).m_type;
1219     Node& node = at(nodeIndex);
1220     VirtualRegister virtualRegister = node.virtualRegister();
1221     GenerationInfo& info = m_generationInfo[virtualRegister];
1222
1223     if (info.registerFormat() == DataFormatNone) {
1224         if (node.hasConstant()) {
1225             GPRReg gpr = allocate();
1226
1227             if (isInt32Constant(nodeIndex)) {
1228                 FPRReg fpr = fprAllocate();
1229                 m_jit.move(MacroAssembler::Imm64(reinterpretDoubleToInt64(static_cast<double>(valueOfInt32Constant(nodeIndex)))), gpr);
1230                 m_jit.move64ToDouble(gpr, fpr);
1231                 unlock(gpr);
1232
1233                 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
1234                 info.fillDouble(*m_stream, fpr);
1235                 return fpr;
1236             }
1237             if (isNumberConstant(nodeIndex)) {
1238                 FPRReg fpr = fprAllocate();
1239                 m_jit.move(MacroAssembler::Imm64(reinterpretDoubleToInt64(valueOfNumberConstant(nodeIndex))), gpr);
1240                 m_jit.move64ToDouble(gpr, fpr);
1241                 unlock(gpr);
1242
1243                 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
1244                 info.fillDouble(*m_stream, fpr);
1245                 return fpr;
1246             }
1247             terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
1248             return fprAllocate();
1249         }
1250         
1251         DataFormat spillFormat = info.spillFormat();
1252         switch (spillFormat) {
1253         case DataFormatDouble: {
1254             FPRReg fpr = fprAllocate();
1255             m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
1256             m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
1257             info.fillDouble(*m_stream, fpr);
1258             return fpr;
1259         }
1260             
1261         case DataFormatInteger: {
1262             GPRReg gpr = allocate();
1263             
1264             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1265             m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
1266             info.fillInteger(*m_stream, gpr);
1267             unlock(gpr);
1268             break;
1269         }
1270
1271         default:
1272             GPRReg gpr = allocate();
1273
1274             ASSERT(spillFormat & DataFormatJS);
1275             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1276             m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1277             info.fillJSValue(*m_stream, gpr, spillFormat);
1278             unlock(gpr);
1279             break;
1280         }
1281     }
1282
1283     switch (info.registerFormat()) {
1284     case DataFormatNone: // Should have filled, above.
1285     case DataFormatBoolean: // This type never occurs.
1286     case DataFormatStorage:
1287         ASSERT_NOT_REACHED();
1288
1289     case DataFormatCell:
1290         terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
1291         return fprAllocate();
1292
1293     case DataFormatJSCell:
1294     case DataFormatJS:
1295     case DataFormatJSBoolean: {
1296         GPRReg jsValueGpr = info.gpr();
1297         m_gprs.lock(jsValueGpr);
1298         FPRReg fpr = fprAllocate();
1299         GPRReg tempGpr = allocate();
1300
1301         JITCompiler::Jump isInteger = m_jit.branch64(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
1302
1303         if (!isNumberSpeculation(type))
1304             speculationCheck(BadType, JSValueRegs(jsValueGpr), nodeIndex, m_jit.branchTest64(MacroAssembler::Zero, jsValueGpr, GPRInfo::tagTypeNumberRegister));
1305
1306         // First, if we get here we have a double encoded as a JSValue
1307         m_jit.move(jsValueGpr, tempGpr);
1308         unboxDouble(tempGpr, fpr);
1309         JITCompiler::Jump hasUnboxedDouble = m_jit.jump();
1310
1311         // Finally, handle integers.
1312         isInteger.link(&m_jit);
1313         m_jit.convertInt32ToDouble(jsValueGpr, fpr);
1314         hasUnboxedDouble.link(&m_jit);
1315
1316         m_gprs.release(jsValueGpr);
1317         m_gprs.unlock(jsValueGpr);
1318         m_gprs.unlock(tempGpr);
1319         m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
1320         info.fillDouble(*m_stream, fpr);
1321         info.killSpilled();
1322         return fpr;
1323     }
1324
1325     case DataFormatJSInteger:
1326     case DataFormatInteger: {
1327         FPRReg fpr = fprAllocate();
1328         GPRReg gpr = info.gpr();
1329         m_gprs.lock(gpr);
1330         m_jit.convertInt32ToDouble(gpr, fpr);
1331         m_gprs.unlock(gpr);
1332         return fpr;
1333     }
1334
1335     // Unbox the double
1336     case DataFormatJSDouble: {
1337         GPRReg gpr = info.gpr();
1338         FPRReg fpr = fprAllocate();
1339         if (m_gprs.isLocked(gpr)) {
1340             // Make sure we don't trample gpr if it is in use.
1341             GPRReg temp = allocate();
1342             m_jit.move(gpr, temp);
1343             unboxDouble(temp, fpr);
1344             unlock(temp);
1345         } else
1346             unboxDouble(gpr, fpr);
1347
1348         m_gprs.release(gpr);
1349         m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
1350
1351         info.fillDouble(*m_stream, fpr);
1352         return fpr;
1353     }
1354
1355     case DataFormatDouble: {
1356         FPRReg fpr = info.fpr();
1357         m_fprs.lock(fpr);
1358         return fpr;
1359     }
1360         
1361     default:
1362         ASSERT_NOT_REACHED();
1363         return InvalidFPRReg;
1364     }
1365 }
1366
1367 GPRReg SpeculativeJIT::fillSpeculateCell(NodeIndex nodeIndex, bool isForwardSpeculation)
1368 {
1369 #if DFG_ENABLE(DEBUG_VERBOSE)
1370     dataLog("SpecCell@%d   ", nodeIndex);
1371 #endif
1372     SpeculatedType type = m_state.forNode(nodeIndex).m_type;
1373     Node& node = at(nodeIndex);
1374     VirtualRegister virtualRegister = node.virtualRegister();
1375     GenerationInfo& info = m_generationInfo[virtualRegister];
1376
1377     switch (info.registerFormat()) {
1378     case DataFormatNone: {
1379         if (info.spillFormat() == DataFormatInteger || info.spillFormat() == DataFormatDouble) {
1380             terminateSpeculativeExecutionWithConditionalDirection(Uncountable, JSValueRegs(), NoNode, isForwardSpeculation);
1381             return allocate();
1382         }
1383         
1384         GPRReg gpr = allocate();
1385
1386         if (node.hasConstant()) {
1387             JSValue jsValue = valueOfJSConstant(nodeIndex);
1388             if (jsValue.isCell()) {
1389                 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1390                 m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsValue)), gpr);
1391                 info.fillJSValue(*m_stream, gpr, DataFormatJSCell);
1392                 return gpr;
1393             }
1394             terminateSpeculativeExecutionWithConditionalDirection(Uncountable, JSValueRegs(), NoNode, isForwardSpeculation);
1395             return gpr;
1396         }
1397         ASSERT(info.spillFormat() & DataFormatJS);
1398         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1399         m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1400
1401         info.fillJSValue(*m_stream, gpr, DataFormatJS);
1402         if (!isCellSpeculation(type))
1403             speculationCheckWithConditionalDirection(BadType, JSValueRegs(gpr), nodeIndex, m_jit.branchTest64(MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister), isForwardSpeculation);
1404         info.fillJSValue(*m_stream, gpr, DataFormatJSCell);
1405         return gpr;
1406     }
1407
1408     case DataFormatCell:
1409     case DataFormatJSCell: {
1410         GPRReg gpr = info.gpr();
1411         m_gprs.lock(gpr);
1412         return gpr;
1413     }
1414
1415     case DataFormatJS: {
1416         GPRReg gpr = info.gpr();
1417         m_gprs.lock(gpr);
1418         if (!isCellSpeculation(type))
1419             speculationCheckWithConditionalDirection(BadType, JSValueRegs(gpr), nodeIndex, m_jit.branchTest64(MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister), isForwardSpeculation);
1420         info.fillJSValue(*m_stream, gpr, DataFormatJSCell);
1421         return gpr;
1422     }
1423
1424     case DataFormatJSInteger:
1425     case DataFormatInteger:
1426     case DataFormatJSDouble:
1427     case DataFormatDouble:
1428     case DataFormatJSBoolean:
1429     case DataFormatBoolean: {
1430         terminateSpeculativeExecutionWithConditionalDirection(Uncountable, JSValueRegs(), NoNode, isForwardSpeculation);
1431         return allocate();
1432     }
1433
1434     case DataFormatStorage:
1435         ASSERT_NOT_REACHED();
1436         
1437     default:
1438         ASSERT_NOT_REACHED();
1439         return InvalidGPRReg;
1440     }
1441 }
1442
1443 GPRReg SpeculativeJIT::fillSpeculateBoolean(NodeIndex nodeIndex)
1444 {
1445 #if DFG_ENABLE(DEBUG_VERBOSE)
1446     dataLog("SpecBool@%d   ", nodeIndex);
1447 #endif
1448     SpeculatedType type = m_state.forNode(nodeIndex).m_type;
1449     Node& node = at(nodeIndex);
1450     VirtualRegister virtualRegister = node.virtualRegister();
1451     GenerationInfo& info = m_generationInfo[virtualRegister];
1452
1453     switch (info.registerFormat()) {
1454     case DataFormatNone: {
1455         if (info.spillFormat() == DataFormatInteger || info.spillFormat() == DataFormatDouble) {
1456             terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
1457             return allocate();
1458         }
1459         
1460         GPRReg gpr = allocate();
1461
1462         if (node.hasConstant()) {
1463             JSValue jsValue = valueOfJSConstant(nodeIndex);
1464             if (jsValue.isBoolean()) {
1465                 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1466                 m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsValue)), gpr);
1467                 info.fillJSValue(*m_stream, gpr, DataFormatJSBoolean);
1468                 return gpr;
1469             }
1470             terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
1471             return gpr;
1472         }
1473         ASSERT(info.spillFormat() & DataFormatJS);
1474         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1475         m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1476
1477         info.fillJSValue(*m_stream, gpr, DataFormatJS);
1478         if (!isBooleanSpeculation(type)) {
1479             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1480             speculationCheck(BadType, JSValueRegs(gpr), nodeIndex, m_jit.branchTest64(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg));
1481             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1482         }
1483         info.fillJSValue(*m_stream, gpr, DataFormatJSBoolean);
1484         return gpr;
1485     }
1486
1487     case DataFormatBoolean:
1488     case DataFormatJSBoolean: {
1489         GPRReg gpr = info.gpr();
1490         m_gprs.lock(gpr);
1491         return gpr;
1492     }
1493
1494     case DataFormatJS: {
1495         GPRReg gpr = info.gpr();
1496         m_gprs.lock(gpr);
1497         if (!isBooleanSpeculation(type)) {
1498             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1499             speculationCheck(BadType, JSValueRegs(gpr), nodeIndex, m_jit.branchTest64(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg));
1500             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1501         }
1502         info.fillJSValue(*m_stream, gpr, DataFormatJSBoolean);
1503         return gpr;
1504     }
1505
1506     case DataFormatJSInteger:
1507     case DataFormatInteger:
1508     case DataFormatJSDouble:
1509     case DataFormatDouble:
1510     case DataFormatJSCell:
1511     case DataFormatCell: {
1512         terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
1513         return allocate();
1514     }
1515         
1516     case DataFormatStorage:
1517         ASSERT_NOT_REACHED();
1518         
1519     default:
1520         ASSERT_NOT_REACHED();
1521         return InvalidGPRReg;
1522     }
1523 }
1524
1525 JITCompiler::Jump SpeculativeJIT::convertToDouble(GPRReg value, FPRReg result, GPRReg tmp)
1526 {
1527     JITCompiler::Jump isInteger = m_jit.branch64(MacroAssembler::AboveOrEqual, value, GPRInfo::tagTypeNumberRegister);
1528     
1529     JITCompiler::Jump notNumber = m_jit.branchTest64(MacroAssembler::Zero, value, GPRInfo::tagTypeNumberRegister);
1530     
1531     m_jit.move(value, tmp);
1532     unboxDouble(tmp, result);
1533     
1534     JITCompiler::Jump done = m_jit.jump();
1535     
1536     isInteger.link(&m_jit);
1537     
1538     m_jit.convertInt32ToDouble(value, result);
1539     
1540     done.link(&m_jit);
1541
1542     return notNumber;
1543 }
1544
1545 void SpeculativeJIT::compileObjectEquality(Node& node)
1546 {
1547     SpeculateCellOperand op1(this, node.child1());
1548     SpeculateCellOperand op2(this, node.child2());
1549     GPRTemporary result(this, op1);
1550     
1551     GPRReg op1GPR = op1.gpr();
1552     GPRReg op2GPR = op2.gpr();
1553     GPRReg resultGPR = result.gpr();
1554    
1555     if (m_jit.graph().globalObjectFor(node.codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) {
1556         m_jit.graph().globalObjectFor(node.codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint()); 
1557         speculationCheck(BadType, JSValueRegs(op1GPR), node.child1().index(), 
1558             m_jit.branchPtr(
1559                 MacroAssembler::Equal, 
1560                 MacroAssembler::Address(op1GPR, JSCell::structureOffset()), 
1561                 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())));
1562         speculationCheck(BadType, JSValueRegs(op2GPR), node.child2().index(), 
1563             m_jit.branchPtr(
1564                 MacroAssembler::Equal, 
1565                 MacroAssembler::Address(op2GPR, JSCell::structureOffset()), 
1566                 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())));
1567     } else {
1568         GPRTemporary structure(this);
1569         GPRReg structureGPR = structure.gpr();
1570
1571         m_jit.loadPtr(MacroAssembler::Address(op1GPR, JSCell::structureOffset()), structureGPR);
1572         speculationCheck(BadType, JSValueRegs(op1GPR), node.child1().index(), 
1573             m_jit.branchPtr(
1574                 MacroAssembler::Equal, 
1575                 structureGPR, 
1576                 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())));
1577         speculationCheck(BadType, JSValueRegs(op1GPR), node.child1().index(), 
1578             m_jit.branchTest8(
1579                 MacroAssembler::NonZero, 
1580                 MacroAssembler::Address(structureGPR, Structure::typeInfoFlagsOffset()), 
1581                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1582
1583         m_jit.loadPtr(MacroAssembler::Address(op2GPR, JSCell::structureOffset()), structureGPR);
1584         speculationCheck(BadType, JSValueRegs(op2GPR), node.child2().index(), 
1585             m_jit.branchPtr(
1586                 MacroAssembler::Equal, 
1587                 structureGPR, 
1588                 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())));
1589         speculationCheck(BadType, JSValueRegs(op2GPR), node.child2().index(), 
1590             m_jit.branchTest8(
1591                 MacroAssembler::NonZero, 
1592                 MacroAssembler::Address(structureGPR, Structure::typeInfoFlagsOffset()), 
1593                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1594     }
1595     
1596     MacroAssembler::Jump falseCase = m_jit.branch64(MacroAssembler::NotEqual, op1GPR, op2GPR);
1597     m_jit.move(TrustedImm32(ValueTrue), resultGPR);
1598     MacroAssembler::Jump done = m_jit.jump();
1599     falseCase.link(&m_jit);
1600     m_jit.move(TrustedImm32(ValueFalse), resultGPR);
1601     done.link(&m_jit);
1602
1603     jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean);
1604 }
1605
1606 void SpeculativeJIT::compileObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild)
1607 {
1608     Node& leftNode = m_jit.graph()[leftChild.index()];
1609     SpeculateCellOperand op1(this, leftChild);
1610     JSValueOperand op2(this, rightChild);
1611     GPRTemporary result(this);
1612     
1613     GPRReg op1GPR = op1.gpr();
1614     GPRReg op2GPR = op2.gpr();
1615     GPRReg resultGPR = result.gpr();
1616    
1617     if (m_jit.graph().globalObjectFor(leftNode.codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) { 
1618         m_jit.graph().globalObjectFor(leftNode.codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint());
1619         speculationCheck(BadType, JSValueRegs(op1GPR), leftChild.index(), 
1620             m_jit.branchPtr(
1621                 MacroAssembler::Equal, 
1622                 MacroAssembler::Address(op1GPR, JSCell::structureOffset()), 
1623                 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())));
1624     } else {
1625         GPRTemporary structure(this);
1626         GPRReg structureGPR = structure.gpr();
1627
1628         m_jit.loadPtr(MacroAssembler::Address(op1GPR, JSCell::structureOffset()), structureGPR);
1629         speculationCheck(BadType, JSValueRegs(op1GPR), leftChild.index(), 
1630             m_jit.branchPtr(
1631                 MacroAssembler::Equal,
1632                 structureGPR,
1633                 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())));
1634         speculationCheck(BadType, JSValueRegs(op1GPR), leftChild.index(), 
1635             m_jit.branchTest8(
1636                 MacroAssembler::NonZero, 
1637                 MacroAssembler::Address(structureGPR, Structure::typeInfoFlagsOffset()), 
1638                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1639     }
1640     
1641     // It seems that most of the time when programs do a == b where b may be either null/undefined
1642     // or an object, b is usually an object. Balance the branches to make that case fast.
1643     MacroAssembler::Jump rightNotCell =
1644         m_jit.branchTest64(MacroAssembler::NonZero, op2GPR, GPRInfo::tagMaskRegister);
1645     
1646     // We know that within this branch, rightChild must be a cell. 
1647     if (m_jit.graph().globalObjectFor(leftNode.codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) { 
1648         m_jit.graph().globalObjectFor(leftNode.codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint());
1649         speculationCheck(BadType, JSValueRegs(op2GPR), rightChild.index(), 
1650             m_jit.branchPtr(
1651                 MacroAssembler::Equal, 
1652                 MacroAssembler::Address(op2GPR, JSCell::structureOffset()), 
1653                 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())));
1654     } else {
1655         GPRTemporary structure(this);
1656         GPRReg structureGPR = structure.gpr();
1657
1658         m_jit.loadPtr(MacroAssembler::Address(op2GPR, JSCell::structureOffset()), structureGPR);
1659         speculationCheck(BadType, JSValueRegs(op2GPR), rightChild.index(), 
1660             m_jit.branchPtr(
1661                 MacroAssembler::Equal,
1662                 structureGPR,
1663                 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())));
1664         speculationCheck(BadType, JSValueRegs(op2GPR), rightChild.index(), 
1665             m_jit.branchTest8(
1666                 MacroAssembler::NonZero, 
1667                 MacroAssembler::Address(structureGPR, Structure::typeInfoFlagsOffset()), 
1668                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1669     }
1670     
1671     // At this point we know that we can perform a straight-forward equality comparison on pointer
1672     // values because both left and right are pointers to objects that have no special equality
1673     // protocols.
1674     MacroAssembler::Jump falseCase = m_jit.branch64(MacroAssembler::NotEqual, op1GPR, op2GPR);
1675     MacroAssembler::Jump trueCase = m_jit.jump();
1676     
1677     rightNotCell.link(&m_jit);
1678     
1679     // We know that within this branch, rightChild must not be a cell. Check if that is enough to
1680     // prove that it is either null or undefined.
1681     if (!isOtherOrEmptySpeculation(m_state.forNode(rightChild).m_type & ~SpecCell)) {
1682         m_jit.move(op2GPR, resultGPR);
1683         m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR);
1684         
1685         speculationCheck(
1686             BadType, JSValueRegs(op2GPR), rightChild.index(),
1687             m_jit.branch64(
1688                 MacroAssembler::NotEqual, resultGPR,
1689                 MacroAssembler::TrustedImm64(ValueNull)));
1690     }
1691     
1692     falseCase.link(&m_jit);
1693     m_jit.move(TrustedImm32(ValueFalse), resultGPR);
1694     MacroAssembler::Jump done = m_jit.jump();
1695     trueCase.link(&m_jit);
1696     m_jit.move(TrustedImm32(ValueTrue), resultGPR);
1697     done.link(&m_jit);
1698     
1699     jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean);
1700 }
1701
1702 void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild, NodeIndex branchNodeIndex)
1703 {
1704     Node& branchNode = at(branchNodeIndex);
1705     BlockIndex taken = branchNode.takenBlockIndex();
1706     BlockIndex notTaken = branchNode.notTakenBlockIndex();
1707     
1708     SpeculateCellOperand op1(this, leftChild);
1709     JSValueOperand op2(this, rightChild);
1710     GPRTemporary result(this);
1711     
1712     GPRReg op1GPR = op1.gpr();
1713     GPRReg op2GPR = op2.gpr();
1714     GPRReg resultGPR = result.gpr();
1715     
1716     if (m_jit.graph().globalObjectFor(branchNode.codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) {
1717         m_jit.graph().globalObjectFor(branchNode.codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint());
1718         speculationCheck(BadType, JSValueRegs(op1GPR), leftChild.index(), 
1719             m_jit.branchPtr(
1720                 MacroAssembler::Equal, 
1721                 MacroAssembler::Address(op1GPR, JSCell::structureOffset()), 
1722                 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())));
1723     } else {
1724         GPRTemporary structure(this);
1725         GPRReg structureGPR = structure.gpr();
1726
1727         m_jit.loadPtr(MacroAssembler::Address(op1GPR, JSCell::structureOffset()), structureGPR);
1728         speculationCheck(BadType, JSValueRegs(op1GPR), leftChild.index(), 
1729             m_jit.branchPtr(
1730                 MacroAssembler::Equal, 
1731                 structureGPR, 
1732                 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())));
1733         speculationCheck(BadType, JSValueRegs(op1GPR), leftChild.index(), 
1734             m_jit.branchTest8(
1735                 MacroAssembler::NonZero, 
1736                 MacroAssembler::Address(structureGPR, Structure::typeInfoFlagsOffset()), 
1737                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1738     }
1739     
1740     // It seems that most of the time when programs do a == b where b may be either null/undefined
1741     // or an object, b is usually an object. Balance the branches to make that case fast.
1742     MacroAssembler::Jump rightNotCell =
1743         m_jit.branchTest64(MacroAssembler::NonZero, op2GPR, GPRInfo::tagMaskRegister);
1744     
1745     // We know that within this branch, rightChild must be a cell. 
1746     if (m_jit.graph().globalObjectFor(branchNode.codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) {
1747         m_jit.graph().globalObjectFor(branchNode.codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint());
1748         speculationCheck(BadType, JSValueRegs(op2GPR), rightChild.index(), 
1749             m_jit.branchPtr(
1750                 MacroAssembler::Equal, 
1751                 MacroAssembler::Address(op2GPR, JSCell::structureOffset()), 
1752                 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())));
1753     } else {
1754         GPRTemporary structure(this);
1755         GPRReg structureGPR = structure.gpr();
1756
1757         m_jit.loadPtr(MacroAssembler::Address(op2GPR, JSCell::structureOffset()), structureGPR);
1758         speculationCheck(BadType, JSValueRegs(op2GPR), rightChild.index(), 
1759             m_jit.branchPtr(
1760                 MacroAssembler::Equal, 
1761                 structureGPR, 
1762                 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())));
1763         speculationCheck(BadType, JSValueRegs(op2GPR), rightChild.index(), 
1764             m_jit.branchTest8(
1765                 MacroAssembler::NonZero, 
1766                 MacroAssembler::Address(structureGPR, Structure::typeInfoFlagsOffset()), 
1767                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1768     }
1769     
1770     // At this point we know that we can perform a straight-forward equality comparison on pointer
1771     // values because both left and right are pointers to objects that have no special equality
1772     // protocols.
1773     branch64(MacroAssembler::Equal, op1GPR, op2GPR, taken);
1774     
1775     // We know that within this branch, rightChild must not be a cell. Check if that is enough to
1776     // prove that it is either null or undefined.
1777     if (isOtherOrEmptySpeculation(m_state.forNode(rightChild).m_type & ~SpecCell))
1778         rightNotCell.link(&m_jit);
1779     else {
1780         jump(notTaken, ForceJump);
1781         
1782         rightNotCell.link(&m_jit);
1783         m_jit.move(op2GPR, resultGPR);
1784         m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR);
1785         
1786         speculationCheck(
1787             BadType, JSValueRegs(op2GPR), rightChild.index(),
1788             m_jit.branch64(
1789                 MacroAssembler::NotEqual, resultGPR,
1790                 MacroAssembler::TrustedImm64(ValueNull)));
1791     }
1792     
1793     jump(notTaken);
1794 }
1795
1796 void SpeculativeJIT::compileIntegerCompare(Node& node, MacroAssembler::RelationalCondition condition)
1797 {
1798     SpeculateIntegerOperand op1(this, node.child1());
1799     SpeculateIntegerOperand op2(this, node.child2());
1800     GPRTemporary result(this, op1, op2);
1801     
1802     m_jit.compare32(condition, op1.gpr(), op2.gpr(), result.gpr());
1803     
1804     // If we add a DataFormatBool, we should use it here.
1805     m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1806     jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
1807 }
1808
1809 void SpeculativeJIT::compileDoubleCompare(Node& node, MacroAssembler::DoubleCondition condition)
1810 {
1811     SpeculateDoubleOperand op1(this, node.child1());
1812     SpeculateDoubleOperand op2(this, node.child2());
1813     GPRTemporary result(this);
1814     
1815     m_jit.move(TrustedImm32(ValueTrue), result.gpr());
1816     MacroAssembler::Jump trueCase = m_jit.branchDouble(condition, op1.fpr(), op2.fpr());
1817     m_jit.xor64(TrustedImm32(true), result.gpr());
1818     trueCase.link(&m_jit);
1819     
1820     jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
1821 }
1822
1823 void SpeculativeJIT::compileValueAdd(Node& node)
1824 {
1825     JSValueOperand op1(this, node.child1());
1826     JSValueOperand op2(this, node.child2());
1827     
1828     GPRReg op1GPR = op1.gpr();
1829     GPRReg op2GPR = op2.gpr();
1830     
1831     flushRegisters();
1832     
1833     GPRResult result(this);
1834     if (isKnownNotNumber(node.child1().index()) || isKnownNotNumber(node.child2().index()))
1835         callOperation(operationValueAddNotNumber, result.gpr(), op1GPR, op2GPR);
1836     else
1837         callOperation(operationValueAdd, result.gpr(), op1GPR, op2GPR);
1838     
1839     jsValueResult(result.gpr(), m_compileIndex);
1840 }
1841
1842 void SpeculativeJIT::compileNonStringCellOrOtherLogicalNot(Edge nodeUse, bool needSpeculationCheck)
1843 {
1844     JSValueOperand value(this, nodeUse);
1845     GPRTemporary result(this);
1846     GPRReg valueGPR = value.gpr();
1847     GPRReg resultGPR = result.gpr();
1848     
1849     MacroAssembler::Jump notCell = m_jit.branchTest64(MacroAssembler::NonZero, valueGPR, GPRInfo::tagMaskRegister);
1850     if (m_jit.graph().globalObjectFor(m_jit.graph()[nodeUse.index()].codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) {
1851         m_jit.graph().globalObjectFor(m_jit.graph()[nodeUse.index()].codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint());
1852
1853         if (needSpeculationCheck) {
1854             speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse,
1855                 m_jit.branchPtr(
1856                     MacroAssembler::Equal,
1857                     MacroAssembler::Address(valueGPR, JSCell::structureOffset()),
1858                     MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())));
1859         }
1860     } else {
1861         GPRTemporary structure(this);
1862         GPRReg structureGPR = structure.gpr();
1863
1864         m_jit.loadPtr(MacroAssembler::Address(valueGPR, JSCell::structureOffset()), structureGPR);
1865
1866         if (needSpeculationCheck) {
1867             speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse,
1868                 m_jit.branchPtr(
1869                     MacroAssembler::Equal,
1870                     structureGPR,
1871                     MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())));
1872         }
1873
1874         MacroAssembler::Jump isNotMasqueradesAsUndefined = 
1875             m_jit.branchTest8(
1876                 MacroAssembler::Zero, 
1877                 MacroAssembler::Address(structureGPR, Structure::typeInfoFlagsOffset()), 
1878                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined));
1879
1880         speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse, 
1881             m_jit.branchPtr(
1882                 MacroAssembler::Equal, 
1883                 MacroAssembler::Address(structureGPR, Structure::globalObjectOffset()), 
1884                 MacroAssembler::TrustedImmPtr(m_jit.graph().globalObjectFor(m_jit.graph()[nodeUse.index()].codeOrigin))));
1885
1886         isNotMasqueradesAsUndefined.link(&m_jit);
1887     }
1888     m_jit.move(TrustedImm32(ValueFalse), resultGPR);
1889     MacroAssembler::Jump done = m_jit.jump();
1890     
1891     notCell.link(&m_jit);
1892
1893     if (needSpeculationCheck) {
1894         m_jit.move(valueGPR, resultGPR);
1895         m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR);
1896         speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse, 
1897             m_jit.branch64(
1898                 MacroAssembler::NotEqual, 
1899                 resultGPR, 
1900                 MacroAssembler::TrustedImm64(ValueNull)));
1901     }
1902     m_jit.move(TrustedImm32(ValueTrue), resultGPR);
1903     
1904     done.link(&m_jit);
1905     
1906     jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean);
1907 }
1908
1909 void SpeculativeJIT::compileLogicalNot(Node& node)
1910 {
1911     if (at(node.child1()).shouldSpeculateNonStringCellOrOther()) {
1912         compileNonStringCellOrOtherLogicalNot(node.child1(),
1913             !isNonStringCellOrOtherSpeculation(m_state.forNode(node.child1()).m_type));
1914         return;
1915     }
1916     if (at(node.child1()).shouldSpeculateInteger()) {
1917         SpeculateIntegerOperand value(this, node.child1());
1918         GPRTemporary result(this, value);
1919         m_jit.compare32(MacroAssembler::Equal, value.gpr(), MacroAssembler::TrustedImm32(0), result.gpr());
1920         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1921         jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
1922         return;
1923     }
1924     if (at(node.child1()).shouldSpeculateNumber()) {
1925         SpeculateDoubleOperand value(this, node.child1());
1926         FPRTemporary scratch(this);
1927         GPRTemporary result(this);
1928         m_jit.move(TrustedImm32(ValueFalse), result.gpr());
1929         MacroAssembler::Jump nonZero = m_jit.branchDoubleNonZero(value.fpr(), scratch.fpr());
1930         m_jit.xor32(TrustedImm32(true), result.gpr());
1931         nonZero.link(&m_jit);
1932         jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
1933         return;
1934     }
1935     
1936     SpeculatedType prediction = m_jit.getSpeculation(node.child1());
1937     if (isBooleanSpeculation(prediction)) {
1938         if (isBooleanSpeculation(m_state.forNode(node.child1()).m_type)) {
1939             SpeculateBooleanOperand value(this, node.child1());
1940             GPRTemporary result(this, value);
1941             
1942             m_jit.move(value.gpr(), result.gpr());
1943             m_jit.xor64(TrustedImm32(true), result.gpr());
1944             
1945             jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
1946             return;
1947         }
1948         
1949         JSValueOperand value(this, node.child1());
1950         GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add).
1951         
1952         m_jit.move(value.gpr(), result.gpr());
1953         m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), result.gpr());
1954         speculationCheck(BadType, JSValueRegs(value.gpr()), node.child1(), m_jit.branchTest64(JITCompiler::NonZero, result.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
1955         m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueTrue)), result.gpr());
1956         
1957         // If we add a DataFormatBool, we should use it here.
1958         jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
1959         return;
1960     }
1961     
1962     JSValueOperand arg1(this, node.child1());
1963     GPRTemporary result(this);
1964     
1965     GPRReg arg1GPR = arg1.gpr();
1966     GPRReg resultGPR = result.gpr();
1967     
1968     arg1.use();
1969     
1970     m_jit.move(arg1GPR, resultGPR);
1971     m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), resultGPR);
1972     JITCompiler::Jump slowCase = m_jit.branchTest64(JITCompiler::NonZero, resultGPR, TrustedImm32(static_cast<int32_t>(~1)));
1973     
1974     addSlowPathGenerator(
1975         slowPathCall(slowCase, this, dfgConvertJSValueToBoolean, resultGPR, arg1GPR));
1976     
1977     m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueTrue)), resultGPR);
1978     jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly);
1979 }
1980
1981 void SpeculativeJIT::emitNonStringCellOrOtherBranch(Edge nodeUse, BlockIndex taken, BlockIndex notTaken, bool needSpeculationCheck)
1982 {
1983     JSValueOperand value(this, nodeUse);
1984     GPRTemporary scratch(this);
1985     GPRReg valueGPR = value.gpr();
1986     GPRReg scratchGPR = scratch.gpr();
1987     
1988     MacroAssembler::Jump notCell = m_jit.branchTest64(MacroAssembler::NonZero, valueGPR, GPRInfo::tagMaskRegister);
1989     if (m_jit.graph().globalObjectFor(m_jit.graph()[nodeUse.index()].codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) {
1990         m_jit.graph().globalObjectFor(m_jit.graph()[nodeUse.index()].codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint());
1991
1992         if (needSpeculationCheck) {
1993             speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse.index(), 
1994                 m_jit.branchPtr(
1995                     MacroAssembler::Equal, 
1996                     MacroAssembler::Address(valueGPR, JSCell::structureOffset()),
1997                     MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())));
1998         }
1999     } else {
2000         m_jit.loadPtr(MacroAssembler::Address(valueGPR, JSCell::structureOffset()), scratchGPR);
2001
2002         if (needSpeculationCheck) {
2003             speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse.index(), 
2004                 m_jit.branchPtr(
2005                     MacroAssembler::Equal, 
2006                     scratchGPR,
2007                     MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())));
2008         }
2009
2010         JITCompiler::Jump isNotMasqueradesAsUndefined = m_jit.branchTest8(JITCompiler::Zero, MacroAssembler::Address(scratchGPR, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined));
2011
2012         speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse.index(), 
2013             m_jit.branchPtr(
2014                 MacroAssembler::Equal, 
2015                 MacroAssembler::Address(scratchGPR, Structure::globalObjectOffset()), 
2016                 MacroAssembler::TrustedImmPtr(m_jit.graph().globalObjectFor(m_jit.graph()[nodeUse.index()].codeOrigin))));
2017
2018         isNotMasqueradesAsUndefined.link(&m_jit);
2019     }
2020     jump(taken, ForceJump);
2021     
2022     notCell.link(&m_jit);
2023     
2024     if (needSpeculationCheck) {
2025         m_jit.move(valueGPR, scratchGPR);
2026         m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), scratchGPR);
2027         speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse.index(), m_jit.branch64(MacroAssembler::NotEqual, scratchGPR, MacroAssembler::TrustedImm64(ValueNull)));
2028     }
2029     jump(notTaken);
2030     
2031     noResult(m_compileIndex);
2032 }
2033
2034 void SpeculativeJIT::emitBranch(Node& node)
2035 {
2036     BlockIndex taken = node.takenBlockIndex();
2037     BlockIndex notTaken = node.notTakenBlockIndex();
2038     
2039     if (at(node.child1()).shouldSpeculateNonStringCellOrOther()) {
2040         emitNonStringCellOrOtherBranch(node.child1(), taken, notTaken, 
2041             !isNonStringCellOrOtherSpeculation(m_state.forNode(node.child1()).m_type));
2042     } else if (at(node.child1()).shouldSpeculateNumber()) {
2043         if (at(node.child1()).shouldSpeculateInteger()) {
2044             bool invert = false;
2045             
2046             if (taken == nextBlock()) {
2047                 invert = true;
2048                 BlockIndex tmp = taken;
2049                 taken = notTaken;
2050                 notTaken = tmp;
2051             }
2052
2053             SpeculateIntegerOperand value(this, node.child1());
2054             branchTest32(invert ? MacroAssembler::Zero : MacroAssembler::NonZero, value.gpr(), taken);
2055         } else {
2056             SpeculateDoubleOperand value(this, node.child1());
2057             FPRTemporary scratch(this);
2058             branchDoubleNonZero(value.fpr(), scratch.fpr(), taken);
2059         }
2060         
2061         jump(notTaken);
2062         
2063         noResult(m_compileIndex);
2064     } else {
2065         JSValueOperand value(this, node.child1());
2066         GPRReg valueGPR = value.gpr();
2067         
2068         bool predictBoolean = isBooleanSpeculation(m_jit.getSpeculation(node.child1()));
2069     
2070         if (predictBoolean) {
2071             if (isBooleanSpeculation(m_state.forNode(node.child1()).m_type)) {
2072                 MacroAssembler::ResultCondition condition = MacroAssembler::NonZero;
2073                 
2074                 if (taken == nextBlock()) {
2075                     condition = MacroAssembler::Zero;
2076                     BlockIndex tmp = taken;
2077                     taken = notTaken;
2078                     notTaken = tmp;
2079                 }
2080                 
2081                 branchTest32(condition, valueGPR, TrustedImm32(true), taken);
2082                 jump(notTaken);
2083             } else {
2084                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(false))), notTaken);
2085                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(true))), taken);
2086                 
2087                 speculationCheck(BadType, JSValueRegs(valueGPR), node.child1(), m_jit.jump());
2088             }
2089             value.use();
2090         } else {
2091             GPRTemporary result(this);
2092             GPRReg resultGPR = result.gpr();
2093         
2094             branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsNumber(0))), notTaken);
2095             branch64(MacroAssembler::AboveOrEqual, valueGPR, GPRInfo::tagTypeNumberRegister, taken);
2096     
2097             if (!predictBoolean) {
2098                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(false))), notTaken);
2099                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(true))), taken);
2100             }
2101     
2102             value.use();
2103     
2104             silentSpillAllRegisters(resultGPR);
2105             callOperation(dfgConvertJSValueToBoolean, resultGPR, valueGPR);
2106             silentFillAllRegisters(resultGPR);
2107     
2108             branchTest32(MacroAssembler::NonZero, resultGPR, taken);
2109             jump(notTaken);
2110         }
2111         
2112         noResult(m_compileIndex, UseChildrenCalledExplicitly);
2113     }
2114 }
2115
2116 void SpeculativeJIT::compile(Node& node)
2117 {
2118     NodeType op = node.op();
2119     
2120     switch (op) {
2121     case JSConstant:
2122         initConstantInfo(m_compileIndex);
2123         break;
2124
2125     case PhantomArguments:
2126         initConstantInfo(m_compileIndex);
2127         break;
2128
2129     case WeakJSConstant:
2130         m_jit.addWeakReference(node.weakConstant());
2131         initConstantInfo(m_compileIndex);
2132         break;
2133         
2134     case Identity: {
2135         // This could be done a lot better. We take the cheap way out because Identity
2136         // is only going to stick around after CSE if we had prediction weirdness.
2137         JSValueOperand operand(this, node.child1());
2138         GPRTemporary result(this, operand);
2139         m_jit.move(operand.gpr(), result.gpr());
2140         jsValueResult(result.gpr(), m_compileIndex);
2141         break;
2142     }
2143
2144     case GetLocal: {
2145         SpeculatedType prediction = node.variableAccessData()->prediction();
2146         AbstractValue& value = block()->valuesAtHead.operand(node.local());
2147
2148         // If we have no prediction for this local, then don't attempt to compile.
2149         if (prediction == SpecNone) {
2150             terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode);
2151             break;
2152         }
2153         
2154         if (!node.variableAccessData()->isCaptured()) {
2155             // If the CFA is tracking this variable and it found that the variable
2156             // cannot have been assigned, then don't attempt to proceed.
2157             if (value.isClear()) {
2158                 terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode);
2159                 break;
2160             }
2161             
2162             if (node.variableAccessData()->shouldUseDoubleFormat()) {
2163                 FPRTemporary result(this);
2164                 m_jit.loadDouble(JITCompiler::addressFor(node.local()), result.fpr());
2165                 VirtualRegister virtualRegister = node.virtualRegister();
2166                 m_fprs.retain(result.fpr(), virtualRegister, SpillOrderDouble);
2167                 m_generationInfo[virtualRegister].initDouble(m_compileIndex, node.refCount(), result.fpr());
2168                 break;
2169             }
2170             
2171             if (isInt32Speculation(value.m_type)) {
2172                 GPRTemporary result(this);
2173                 m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr());
2174                 
2175                 // Like integerResult, but don't useChildren - our children are phi nodes,
2176                 // and don't represent values within this dataflow with virtual registers.
2177                 VirtualRegister virtualRegister = node.virtualRegister();
2178                 m_gprs.retain(result.gpr(), virtualRegister, SpillOrderInteger);
2179                 m_generationInfo[virtualRegister].initInteger(m_compileIndex, node.refCount(), result.gpr());
2180                 break;
2181             }
2182         }
2183
2184         GPRTemporary result(this);
2185         m_jit.load64(JITCompiler::addressFor(node.local()), result.gpr());
2186
2187         // Like jsValueResult, but don't useChildren - our children are phi nodes,
2188         // and don't represent values within this dataflow with virtual registers.
2189         VirtualRegister virtualRegister = node.virtualRegister();
2190         m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
2191
2192         DataFormat format;
2193         if (node.variableAccessData()->isCaptured())
2194             format = DataFormatJS;
2195         else if (isCellSpeculation(value.m_type))
2196             format = DataFormatJSCell;
2197         else if (isBooleanSpeculation(value.m_type))
2198             format = DataFormatJSBoolean;
2199         else
2200             format = DataFormatJS;
2201
2202         m_generationInfo[virtualRegister].initJSValue(m_compileIndex, node.refCount(), result.gpr(), format);
2203         break;
2204     }
2205
2206     case GetLocalUnlinked: {
2207         GPRTemporary result(this);
2208         
2209         m_jit.load64(JITCompiler::addressFor(node.unlinkedLocal()), result.gpr());
2210         
2211         jsValueResult(result.gpr(), m_compileIndex);
2212         break;
2213     }
2214
2215     case SetLocal: {
2216         // SetLocal doubles as a hint as to where a node will be stored and
2217         // as a speculation point. So before we speculate make sure that we
2218         // know where the child of this node needs to go in the virtual
2219         // stack.
2220         compileMovHint(node);
2221         
2222         // As far as OSR is concerned, we're on the bytecode index corresponding
2223         // to the *next* instruction, since we've already "executed" the
2224         // SetLocal and whatever other DFG Nodes are associated with the same
2225         // bytecode index as the SetLocal.
2226         ASSERT(m_codeOriginForOSR == node.codeOrigin);
2227         Node* nextNode = &at(block()->at(m_indexInBlock + 1));
2228
2229         // But even more oddly, we need to be super careful about the following
2230         // sequence:
2231         //
2232         // a: Foo()
2233         // b: SetLocal(@a)
2234         // c: Flush(@b)
2235         //
2236         // This next piece of crazy takes care of this.
2237         if (nextNode->op() == Flush && nextNode->child1() == m_compileIndex)
2238             nextNode = &at(block()->at(m_indexInBlock + 2));
2239         
2240         // Oddly, it's possible for the bytecode index for the next node to be
2241         // equal to ours. This will happen for op_post_inc. And, even more oddly,
2242         // this is just fine. Ordinarily, this wouldn't be fine, since if the
2243         // next node failed OSR then we'd be OSR-ing with this SetLocal's local
2244         // variable already set even though from the standpoint of the old JIT,
2245         // this SetLocal should not have executed. But for op_post_inc, it's just
2246         // fine, because this SetLocal's local (i.e. the LHS in a x = y++
2247         // statement) would be dead anyway - so the fact that DFG would have
2248         // already made the assignment, and baked it into the stack during
2249         // OSR exit, would not be visible to the old JIT in any way.
2250         m_codeOriginForOSR = nextNode->codeOrigin;
2251         
2252         if (!node.variableAccessData()->isCaptured() && !m_jit.graph().isCreatedThisArgument(node.local())) {
2253             if (node.variableAccessData()->shouldUseDoubleFormat()) {
2254                 SpeculateDoubleOperand value(this, node.child1());
2255                 m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node.local()));
2256                 noResult(m_compileIndex);
2257                 // Indicate that it's no longer necessary to retrieve the value of
2258                 // this bytecode variable from registers or other locations in the stack,
2259                 // but that it is stored as a double.
2260                 recordSetLocal(node.local(), ValueSource(DoubleInJSStack));
2261                 break;
2262             }
2263         
2264             SpeculatedType predictedType = node.variableAccessData()->argumentAwarePrediction();
2265             if (isInt32Speculation(predictedType)) {
2266                 SpeculateIntegerOperand value(this, node.child1());
2267                 m_jit.store32(value.gpr(), JITCompiler::payloadFor(node.local()));
2268                 noResult(m_compileIndex);
2269                 recordSetLocal(node.local(), ValueSource(Int32InJSStack));
2270                 break;
2271             }
2272             if (isCellSpeculation(predictedType)) {
2273                 SpeculateCellOperand cell(this, node.child1());
2274                 GPRReg cellGPR = cell.gpr();
2275                 m_jit.store64(cellGPR, JITCompiler::addressFor(node.local()));
2276                 noResult(m_compileIndex);
2277                 recordSetLocal(node.local(), ValueSource(CellInJSStack));
2278                 break;
2279             }
2280             if (isBooleanSpeculation(predictedType)) {
2281                 SpeculateBooleanOperand boolean(this, node.child1());
2282                 m_jit.store64(boolean.gpr(), JITCompiler::addressFor(node.local()));
2283                 noResult(m_compileIndex);
2284                 recordSetLocal(node.local(), ValueSource(BooleanInJSStack));
2285                 break;
2286             }
2287         }
2288         
2289         JSValueOperand value(this, node.child1());
2290         m_jit.store64(value.gpr(), JITCompiler::addressFor(node.local()));
2291         noResult(m_compileIndex);
2292
2293         recordSetLocal(node.local(), ValueSource(ValueInJSStack));
2294
2295         // If we're storing an arguments object that has been optimized away,
2296         // our variable event stream for OSR exit now reflects the optimized
2297         // value (JSValue()). On the slow path, we want an arguments object
2298         // instead. We add an additional move hint to show OSR exit that it
2299         // needs to reconstruct the arguments object.
2300         if (at(node.child1()).op() == PhantomArguments)
2301             compileMovHint(node);
2302
2303         break;
2304     }
2305
2306     case SetArgument:
2307         // This is a no-op; it just marks the fact that the argument is being used.
2308         // But it may be profitable to use this as a hook to run speculation checks
2309         // on arguments, thereby allowing us to trivially eliminate such checks if
2310         // the argument is not used.
2311         break;
2312
2313     case BitAnd:
2314     case BitOr:
2315     case BitXor:
2316         if (isInt32Constant(node.child1().index())) {
2317             SpeculateIntegerOperand op2(this, node.child2());
2318             GPRTemporary result(this, op2);
2319
2320             bitOp(op, valueOfInt32Constant(node.child1().index()), op2.gpr(), result.gpr());
2321
2322             integerResult(result.gpr(), m_compileIndex);
2323         } else if (isInt32Constant(node.child2().index())) {
2324             SpeculateIntegerOperand op1(this, node.child1());
2325             GPRTemporary result(this, op1);
2326
2327             bitOp(op, valueOfInt32Constant(node.child2().index()), op1.gpr(), result.gpr());
2328
2329             integerResult(result.gpr(), m_compileIndex);
2330         } else {
2331             SpeculateIntegerOperand op1(this, node.child1());
2332             SpeculateIntegerOperand op2(this, node.child2());
2333             GPRTemporary result(this, op1, op2);
2334
2335             GPRReg reg1 = op1.gpr();
2336             GPRReg reg2 = op2.gpr();
2337             bitOp(op, reg1, reg2, result.gpr());
2338
2339             integerResult(result.gpr(), m_compileIndex);
2340         }
2341         break;
2342
2343     case BitRShift:
2344     case BitLShift:
2345     case BitURShift:
2346         if (isInt32Constant(node.child2().index())) {
2347             SpeculateIntegerOperand op1(this, node.child1());
2348             GPRTemporary result(this, op1);
2349
2350             shiftOp(op, op1.gpr(), valueOfInt32Constant(node.child2().index()) & 0x1f, result.gpr());
2351
2352             integerResult(result.gpr(), m_compileIndex);
2353         } else {
2354             // Do not allow shift amount to be used as the result, MacroAssembler does not permit this.
2355             SpeculateIntegerOperand op1(this, node.child1());
2356             SpeculateIntegerOperand op2(this, node.child2());
2357             GPRTemporary result(this, op1);
2358
2359             GPRReg reg1 = op1.gpr();
2360             GPRReg reg2 = op2.gpr();
2361             shiftOp(op, reg1, reg2, result.gpr());
2362
2363             integerResult(result.gpr(), m_compileIndex);
2364         }
2365         break;
2366
2367     case UInt32ToNumber: {
2368         compileUInt32ToNumber(node);
2369         break;
2370     }
2371
2372     case DoubleAsInt32: {
2373         compileDoubleAsInt32(node);
2374         break;
2375     }
2376
2377     case ValueToInt32: {
2378         compileValueToInt32(node);
2379         break;
2380     }
2381         
2382     case Int32ToDouble: {
2383         compileInt32ToDouble(node);
2384         break;
2385     }
2386         
2387     case CheckNumber: {
2388         if (!isNumberSpeculation(m_state.forNode(node.child1()).m_type)) {
2389             JSValueOperand op1(this, node.child1());
2390             JITCompiler::Jump isInteger = m_jit.branch64(MacroAssembler::AboveOrEqual, op1.gpr(), GPRInfo::tagTypeNumberRegister);
2391             speculationCheck(
2392                 BadType, JSValueRegs(op1.gpr()), node.child1().index(),
2393                 m_jit.branchTest64(MacroAssembler::Zero, op1.gpr(), GPRInfo::tagTypeNumberRegister));
2394             isInteger.link(&m_jit);
2395         }
2396         noResult(m_compileIndex);
2397         break;
2398     }
2399
2400     case ValueAdd:
2401     case ArithAdd:
2402         compileAdd(node);
2403         break;
2404
2405     case ArithSub:
2406         compileArithSub(node);
2407         break;
2408
2409     case ArithNegate:
2410         compileArithNegate(node);
2411         break;
2412
2413     case ArithMul:
2414         compileArithMul(node);
2415         break;
2416
2417     case ArithDiv: {
2418         if (Node::shouldSpeculateIntegerForArithmetic(at(node.child1()), at(node.child2()))
2419             && node.canSpeculateInteger()) {
2420             compileIntegerArithDivForX86(node);
2421             break;
2422         }
2423         
2424         SpeculateDoubleOperand op1(this, node.child1());
2425         SpeculateDoubleOperand op2(this, node.child2());
2426         FPRTemporary result(this, op1);
2427
2428         FPRReg reg1 = op1.fpr();
2429         FPRReg reg2 = op2.fpr();
2430         m_jit.divDouble(reg1, reg2, result.fpr());
2431
2432         doubleResult(result.fpr(), m_compileIndex);
2433         break;
2434     }
2435
2436     case ArithMod: {
2437         compileArithMod(node);
2438         break;
2439     }
2440
2441     case ArithAbs: {
2442         if (at(node.child1()).shouldSpeculateIntegerForArithmetic()
2443             && node.canSpeculateInteger()) {
2444             SpeculateIntegerOperand op1(this, node.child1());
2445             GPRTemporary result(this);
2446             GPRTemporary scratch(this);
2447             
2448             m_jit.zeroExtend32ToPtr(op1.gpr(), result.gpr());
2449             m_jit.rshift32(result.gpr(), MacroAssembler::TrustedImm32(31), scratch.gpr());
2450             m_jit.add32(scratch.gpr(), result.gpr());
2451             m_jit.xor32(scratch.gpr(), result.gpr());
2452             speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::Equal, result.gpr(), MacroAssembler::TrustedImm32(1 << 31)));
2453             integerResult(result.gpr(), m_compileIndex);
2454             break;
2455         }
2456         
2457         SpeculateDoubleOperand op1(this, node.child1());
2458         FPRTemporary result(this);
2459         
2460         m_jit.absDouble(op1.fpr(), result.fpr());
2461         doubleResult(result.fpr(), m_compileIndex);
2462         break;
2463     }
2464         
2465     case ArithMin:
2466     case ArithMax: {
2467         if (Node::shouldSpeculateIntegerForArithmetic(at(node.child1()), at(node.child2()))
2468             && node.canSpeculateInteger()) {
2469             SpeculateStrictInt32Operand op1(this, node.child1());
2470             SpeculateStrictInt32Operand op2(this, node.child2());
2471             GPRTemporary result(this, op1);
2472             
2473             MacroAssembler::Jump op1Less = m_jit.branch32(op == ArithMin ? MacroAssembler::LessThan : MacroAssembler::GreaterThan, op1.gpr(), op2.gpr());
2474             m_jit.move(op2.gpr(), result.gpr());
2475             if (op1.gpr() != result.gpr()) {
2476                 MacroAssembler::Jump done = m_jit.jump();
2477                 op1Less.link(&m_jit);
2478                 m_jit.move(op1.gpr(), result.gpr());
2479                 done.link(&m_jit);
2480             } else
2481                 op1Less.link(&m_jit);
2482             
2483             integerResult(result.gpr(), m_compileIndex);
2484             break;
2485         }
2486         
2487         SpeculateDoubleOperand op1(this, node.child1());
2488         SpeculateDoubleOperand op2(this, node.child2());
2489         FPRTemporary result(this, op1);
2490         
2491         MacroAssembler::JumpList done;
2492         
2493         MacroAssembler::Jump op1Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleLessThan : MacroAssembler::DoubleGreaterThan, op1.fpr(), op2.fpr());
2494         
2495         // op2 is eather the lesser one or one of then is NaN
2496         MacroAssembler::Jump op2Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleGreaterThanOrEqual : MacroAssembler::DoubleLessThanOrEqual, op1.fpr(), op2.fpr());
2497         
2498         // Unordered case. We don't know which of op1, op2 is NaN. Manufacture NaN by adding 
2499         // op1 + op2 and putting it into result.
2500         m_jit.addDouble(op1.fpr(), op2.fpr(), result.fpr());
2501         done.append(m_jit.jump());
2502         
2503         op2Less.link(&m_jit);
2504         m_jit.moveDouble(op2.fpr(), result.fpr());
2505         
2506         if (op1.fpr() != result.fpr()) {
2507             done.append(m_jit.jump());
2508             
2509             op1Less.link(&m_jit);
2510             m_jit.moveDouble(op1.fpr(), result.fpr());
2511         } else
2512             op1Less.link(&m_jit);
2513         
2514         done.link(&m_jit);
2515         
2516         doubleResult(result.fpr(), m_compileIndex);
2517         break;
2518     }
2519         
2520     case ArithSqrt: {
2521         SpeculateDoubleOperand op1(this, node.child1());
2522         FPRTemporary result(this, op1);
2523         
2524         m_jit.sqrtDouble(op1.fpr(), result.fpr());
2525         
2526         doubleResult(result.fpr(), m_compileIndex);
2527         break;
2528     }
2529
2530     case LogicalNot:
2531         compileLogicalNot(node);
2532         break;
2533
2534     case CompareLess:
2535         if (compare(node, JITCompiler::LessThan, JITCompiler::DoubleLessThan, operationCompareLess))
2536             return;
2537         break;
2538
2539     case CompareLessEq:
2540         if (compare(node, JITCompiler::LessThanOrEqual, JITCompiler::DoubleLessThanOrEqual, operationCompareLessEq))
2541             return;
2542         break;
2543
2544     case CompareGreater:
2545         if (compare(node, JITCompiler::GreaterThan, JITCompiler::DoubleGreaterThan, operationCompareGreater))
2546             return;
2547         break;
2548
2549     case CompareGreaterEq:
2550         if (compare(node, JITCompiler::GreaterThanOrEqual, JITCompiler::DoubleGreaterThanOrEqual, operationCompareGreaterEq))
2551             return;
2552         break;
2553
2554     case CompareEq:
2555         if (isNullConstant(node.child1().index())) {
2556             if (nonSpeculativeCompareNull(node, node.child2()))
2557                 return;
2558             break;
2559         }
2560         if (isNullConstant(node.child2().index())) {
2561             if (nonSpeculativeCompareNull(node, node.child1()))
2562                 return;
2563             break;
2564         }
2565         if (compare(node, JITCompiler::Equal, JITCompiler::DoubleEqual, operationCompareEq))
2566             return;
2567         break;
2568
2569     case CompareStrictEq:
2570         if (compileStrictEq(node))
2571             return;
2572         break;
2573
2574     case StringCharCodeAt: {
2575         compileGetCharCodeAt(node);
2576         break;
2577     }
2578
2579     case StringCharAt: {
2580         // Relies on StringCharAt node having same basic layout as GetByVal
2581         compileGetByValOnString(node);
2582         break;
2583     }
2584         
2585     case CheckArray: {
2586         checkArray(node);
2587         break;
2588     }
2589         
2590     case Arrayify:
2591     case ArrayifyToStructure: {
2592         arrayify(node);
2593         break;
2594     }
2595
2596     case GetByVal: {
2597         switch (node.arrayMode().type()) {
2598         case Array::SelectUsingPredictions:
2599         case Array::ForceExit:
2600             ASSERT_NOT_REACHED();
2601             terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode);
2602             break;
2603         case Array::Generic: {
2604             JSValueOperand base(this, node.child1());
2605             JSValueOperand property(this, node.child2());
2606             GPRReg baseGPR = base.gpr();
2607             GPRReg propertyGPR = property.gpr();
2608             
2609             flushRegisters();
2610             GPRResult result(this);
2611             callOperation(operationGetByVal, result.gpr(), baseGPR, propertyGPR);
2612             
2613             jsValueResult(result.gpr(), m_compileIndex);
2614             break;
2615         }
2616         case Array::Int32:
2617         case Array::Contiguous: {
2618             if (node.arrayMode().isInBounds()) {
2619                 SpeculateStrictInt32Operand property(this, node.child2());
2620                 StorageOperand storage(this, node.child3());
2621                 
2622                 GPRReg propertyReg = property.gpr();
2623                 GPRReg storageReg = storage.gpr();
2624                 
2625                 if (!m_compileOkay)
2626                     return;
2627                 
2628                 speculationCheck(OutOfBounds, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2629                 
2630                 GPRTemporary result(this);
2631                 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.gpr());
2632                 speculationCheck(OutOfBounds, JSValueRegs(), NoNode, m_jit.branchTest64(MacroAssembler::Zero, result.gpr()));
2633                 jsValueResult(result.gpr(), m_compileIndex, node.arrayMode().type() == Array::Int32 ? DataFormatJSInteger : DataFormatJS);
2634                 break;
2635             }
2636             
2637             SpeculateCellOperand base(this, node.child1());
2638             SpeculateStrictInt32Operand property(this, node.child2());
2639             StorageOperand storage(this, node.child3());
2640             
2641             GPRReg baseReg = base.gpr();
2642             GPRReg propertyReg = property.gpr();
2643             GPRReg storageReg = storage.gpr();
2644             
2645             if (!m_compileOkay)
2646                 return;
2647             
2648             GPRTemporary result(this);
2649             GPRReg resultReg = result.gpr();
2650             
2651             MacroAssembler::JumpList slowCases;
2652             
2653             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2654             
2655             m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
2656             slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, resultReg));
2657             
2658             addSlowPathGenerator(
2659                 slowPathCall(
2660                     slowCases, this, operationGetByValArrayInt,
2661                     result.gpr(), baseReg, propertyReg));
2662             
2663             jsValueResult(resultReg, m_compileIndex);
2664             break;
2665         }
2666
2667         case Array::Double: {
2668             if (node.arrayMode().isInBounds()) {
2669                 if (node.arrayMode().isSaneChain()) {
2670                     JSGlobalObject* globalObject = m_jit.globalObjectFor(node.codeOrigin);
2671                     ASSERT(globalObject->arrayPrototypeChainIsSane());
2672                     globalObject->arrayPrototype()->structure()->addTransitionWatchpoint(speculationWatchpoint());
2673                     globalObject->objectPrototype()->structure()->addTransitionWatchpoint(speculationWatchpoint());
2674                 }
2675                 
2676                 SpeculateStrictInt32Operand property(this, node.child2());
2677                 StorageOperand storage(this, node.child3());
2678             
2679                 GPRReg propertyReg = property.gpr();
2680                 GPRReg storageReg = storage.gpr();
2681             
2682                 if (!m_compileOkay)
2683                     return;
2684             
2685                 speculationCheck(OutOfBounds, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2686             
2687                 FPRTemporary result(this);
2688                 m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.fpr());
2689                 if (!node.arrayMode().isSaneChain())
2690                     speculationCheck(OutOfBounds, JSValueRegs(), NoNode, m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, result.fpr(), result.fpr()));
2691                 doubleResult(result.fpr(), m_compileIndex);
2692                 break;
2693             }
2694
2695             SpeculateCellOperand base(this, node.child1());
2696             SpeculateStrictInt32Operand property(this, node.child2());
2697             StorageOperand storage(this, node.child3());
2698             
2699             GPRReg baseReg = base.gpr();
2700             GPRReg propertyReg = property.gpr();
2701             GPRReg storageReg = storage.gpr();
2702             
2703             if (!m_compileOkay)
2704                 return;
2705             
2706             GPRTemporary result(this);
2707             FPRTemporary temp(this);
2708             GPRReg resultReg = result.gpr();
2709             FPRReg tempReg = temp.fpr();
2710             
2711             MacroAssembler::JumpList slowCases;
2712             
2713             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2714             
2715             m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), tempReg);
2716             slowCases.append(m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, tempReg, tempReg));
2717             boxDouble(tempReg, resultReg);
2718             
2719             addSlowPathGenerator(
2720                 slowPathCall(
2721                     slowCases, this, operationGetByValArrayInt,
2722                     result.gpr(), baseReg, propertyReg));
2723             
2724             jsValueResult(resultReg, m_compileIndex);
2725             break;
2726         }
2727
2728         case Array::ArrayStorage:
2729         case Array::SlowPutArrayStorage: {
2730             if (node.arrayMode().isInBounds()) {
2731                 SpeculateStrictInt32Operand property(this, node.child2());
2732                 StorageOperand storage(this, node.child3());
2733             
2734                 GPRReg propertyReg = property.gpr();
2735                 GPRReg storageReg = storage.gpr();
2736             
2737                 if (!m_compileOkay)
2738                     return;
2739             
2740                 speculationCheck(OutOfBounds, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
2741             
2742                 GPRTemporary result(this);
2743                 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), result.gpr());
2744                 speculationCheck(OutOfBounds, JSValueRegs(), NoNode, m_jit.branchTest64(MacroAssembler::Zero, result.gpr()));
2745             
2746                 jsValueResult(result.gpr(), m_compileIndex);
2747                 break;
2748             }
2749
2750             SpeculateCellOperand base(this, node.child1());
2751             SpeculateStrictInt32Operand property(this, node.child2());
2752             StorageOperand storage(this, node.child3());
2753             
2754             GPRReg baseReg = base.gpr();
2755             GPRReg propertyReg = property.gpr();
2756             GPRReg storageReg = storage.gpr();
2757             
2758             if (!m_compileOkay)
2759                 return;
2760             
2761             GPRTemporary result(this);
2762             GPRReg resultReg = result.gpr();
2763             
2764             MacroAssembler::JumpList slowCases;
2765             
2766             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
2767     
2768             m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), resultReg);
2769             slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, resultReg));
2770     
2771             addSlowPathGenerator(
2772                 slowPathCall(
2773                     slowCases, this, operationGetByValArrayInt,
2774                     result.gpr(), baseReg, propertyReg));
2775             
2776             jsValueResult(resultReg, m_compileIndex);
2777             break;
2778         }
2779         case Array::String:
2780             compileGetByValOnString(node);
2781             break;
2782         case Array::Arguments:
2783             compileGetByValOnArguments(node);
2784             break;
2785         case Array::Int8Array:
2786             compileGetByValOnIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), node, sizeof(int8_t), SignedTypedArray);
2787             break;
2788         case Array::Int16Array:
2789             compileGetByValOnIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), node, sizeof(int16_t), SignedTypedArray);
2790             break;
2791         case Array::Int32Array:
2792             compileGetByValOnIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), node, sizeof(int32_t), SignedTypedArray);
2793             break;
2794         case Array::Uint8Array:
2795             compileGetByValOnIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), node, sizeof(uint8_t), UnsignedTypedArray);
2796             break;
2797         case Array::Uint8ClampedArray:
2798             compileGetByValOnIntTypedArray(m_jit.globalData()->uint8ClampedArrayDescriptor(), node, sizeof(uint8_t), UnsignedTypedArray);
2799             break;
2800         case Array::Uint16Array:
2801             compileGetByValOnIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), node, sizeof(uint16_t), UnsignedTypedArray);
2802             break;
2803         case Array::Uint32Array:
2804             compileGetByValOnIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), node, sizeof(uint32_t), UnsignedTypedArray);
2805             break;
2806         case Array::Float32Array:
2807             compileGetByValOnFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), node, sizeof(float));
2808             break;
2809         case Array::Float64Array:
2810             compileGetByValOnFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), node, sizeof(double));
2811             break;
2812         default:
2813             ASSERT_NOT_REACHED();
2814             break;
2815         }
2816         break;
2817     }
2818
2819     case PutByVal:
2820     case PutByValAlias: {
2821         Edge child1 = m_jit.graph().varArgChild(node, 0);
2822         Edge child2 = m_jit.graph().varArgChild(node, 1);
2823         Edge child3 = m_jit.graph().varArgChild(node, 2);
2824         Edge child4 = m_jit.graph().varArgChild(node, 3);
2825         
2826         ArrayMode arrayMode = node.arrayMode().modeForPut();
2827         bool alreadyHandled = false;
2828         
2829         switch (arrayMode.type()) {
2830         case Array::SelectUsingPredictions:
2831         case Array::ForceExit:
2832             ASSERT_NOT_REACHED();
2833             terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode);
2834             alreadyHandled = true;
2835             break;
2836         case Array::Generic: {
2837             ASSERT(node.op() == PutByVal);
2838             
2839             JSValueOperand arg1(this, child1);
2840             JSValueOperand arg2(this, child2);
2841             JSValueOperand arg3(this, child3);
2842             GPRReg arg1GPR = arg1.gpr();
2843             GPRReg arg2GPR = arg2.gpr();
2844             GPRReg arg3GPR = arg3.gpr();
2845             flushRegisters();
2846             
2847             callOperation(m_jit.strictModeFor(node.codeOrigin) ? operationPutByValStrict : operationPutByValNonStrict, arg1GPR, arg2GPR, arg3GPR);
2848             
2849             noResult(m_compileIndex);
2850             alreadyHandled = true;
2851             break;
2852         }
2853         default:
2854             break;
2855         }
2856         
2857         if (alreadyHandled)
2858             break;
2859         
2860         // FIXME: the base may not be necessary for some array access modes. But we have to
2861         // keep it alive to this point, so it's likely to be in a register anyway. Likely
2862         // no harm in locking it here.
2863         SpeculateCellOperand base(this, child1);
2864         SpeculateStrictInt32Operand property(this, child2);
2865         
2866         GPRReg baseReg = base.gpr();
2867         GPRReg propertyReg = property.gpr();
2868
2869         switch (arrayMode.type()) {
2870         case Array::Int32:
2871         case Array::Contiguous: {
2872             JSValueOperand value(this, child3);
2873
2874             GPRReg valueReg = value.gpr();
2875         
2876             if (!m_compileOkay)
2877                 return;
2878             
2879             if (arrayMode.type() == Array::Int32
2880                 && !isInt32Speculation(m_state.forNode(child3).m_type)) {
2881                 speculationCheck(
2882                     BadType, JSValueRegs(valueReg), child3,
2883                     m_jit.branch64(MacroAssembler::Below, valueReg, GPRInfo::tagTypeNumberRegister));
2884             }
2885         
2886             if (arrayMode.type() == Array::Contiguous && Heap::isWriteBarrierEnabled()) {
2887                 GPRTemporary scratch(this);
2888                 writeBarrier(baseReg, value.gpr(), child3, WriteBarrierForPropertyAccess, scratch.gpr());
2889             }
2890
2891             StorageOperand storage(this, child4);
2892             GPRReg storageReg = storage.gpr();
2893
2894             if (node.op() == PutByValAlias) {
2895                 // Store the value to the array.
2896                 GPRReg propertyReg = property.gpr();
2897                 GPRReg valueReg = value.gpr();
2898                 m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
2899                 
2900                 noResult(m_compileIndex);
2901                 break;
2902             }
2903             
2904             GPRTemporary temporary;
2905             GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
2906
2907             MacroAssembler::JumpList slowCases;
2908             
2909             if (arrayMode.isInBounds()) {
2910                 speculationCheck(
2911                     Uncountable, JSValueRegs(), NoNode,
2912                     m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2913             } else {
2914                 MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
2915                 
2916                 slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfVectorLength())));
2917                 
2918                 if (!arrayMode.isOutOfBounds())
2919                     speculationCheck(Uncountable, JSValueRegs(), NoNode, slowCases);
2920                 
2921                 m_jit.add32(TrustedImm32(1), propertyReg, temporaryReg);
2922                 m_jit.store32(temporaryReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
2923                 
2924                 inBounds.link(&m_jit);
2925             }
2926             
2927             m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
2928
2929             base.use();
2930             property.use();
2931             value.use();
2932             storage.use();
2933             
2934             if (arrayMode.isOutOfBounds()) {
2935                 addSlowPathGenerator(
2936                     slowPathCall(
2937                         slowCases, this,
2938                         m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
2939                         NoResult, baseReg, propertyReg, valueReg));
2940             }
2941
2942             noResult(m_compileIndex, UseChildrenCalledExplicitly);
2943             break;
2944         }
2945             
2946         case Array::Double: {
2947             compileDoublePutByVal(node, base, property);
2948             break;
2949         }
2950             
2951         case Array::ArrayStorage:
2952         case Array::SlowPutArrayStorage: {
2953             JSValueOperand value(this, child3);
2954
2955             GPRReg valueReg = value.gpr();
2956         
2957             if (!m_compileOkay)
2958                 return;
2959         
2960             if (Heap::isWriteBarrierEnabled()) {
2961                 GPRTemporary scratch(this);
2962                 writeBarrier(baseReg, value.gpr(), child3, WriteBarrierForPropertyAccess, scratch.gpr());
2963             }
2964
2965             StorageOperand storage(this, child4);
2966             GPRReg storageReg = storage.gpr();
2967
2968             if (node.op() == PutByValAlias) {
2969                 // Store the value to the array.
2970                 GPRReg propertyReg = property.gpr();
2971                 GPRReg valueReg = value.gpr();
2972                 m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
2973                 
2974                 noResult(m_compileIndex);
2975                 break;
2976             }
2977             
2978             GPRTemporary temporary;
2979             GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
2980
2981             MacroAssembler::JumpList slowCases;
2982
2983             MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
2984             if (!arrayMode.isOutOfBounds())
2985                 speculationCheck(OutOfBounds, JSValueRegs(), NoNode, beyondArrayBounds);
2986             else
2987                 slowCases.append(beyondArrayBounds);
2988
2989             // Check if we're writing to a hole; if so increment m_numValuesInVector.
2990             if (arrayMode.isInBounds()) {
2991                 // This is uncountable because if we take this exit, then the baseline JIT
2992                 // will immediately count the hole store. So there is no need for exit
2993                 // profiling.
2994                 speculationCheck(
2995                     Uncountable, JSValueRegs(), NoNode,
2996                     m_jit.branchTest64(MacroAssembler::Zero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]))));
2997             } else {
2998                 MacroAssembler::Jump notHoleValue = m_jit.branchTest64(MacroAssembler::NonZero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
2999                 if (arrayMode.isSlowPut()) {
3000                     // This is sort of strange. If we wanted to optimize this code path, we would invert
3001                     // the above branch. But it's simply not worth it since this only happens if we're
3002                     // already having a bad time.
3003                     slowCases.append(m_jit.jump());
3004                 } else {
3005                     m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, ArrayStorage::numValuesInVectorOffset()));
3006                 
3007                     // If we're writing to a hole we might be growing the array; 
3008                     MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
3009                     m_jit.add32(TrustedImm32(1), propertyReg, temporaryReg);
3010                     m_jit.store32(temporaryReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
3011                 
3012                     lengthDoesNotNeedUpdate.link(&m_jit);
3013                 }
3014                 notHoleValue.link(&m_jit);
3015             }
3016     
3017             // Store the value to the array.
3018             m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
3019
3020             base.use();
3021             property.use();
3022             value.use();
3023             storage.use();
3024             
3025             if (!slowCases.empty()) {
3026                 addSlowPathGenerator(
3027                     slowPathCall(
3028                         slowCases, this,
3029                         m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
3030                         NoResult, baseReg, propertyReg, valueReg));
3031             }
3032
3033             noResult(m_compileIndex, UseChildrenCalledExplicitly);
3034             break;
3035         }
3036             
3037         case Array::Arguments: {
3038             JSValueOperand value(this, child3);
3039             GPRTemporary scratch(this);
3040             GPRTemporary scratch2(this);
3041             
3042             GPRReg valueReg = value.gpr();
3043             GPRReg scratchReg = scratch.gpr();
3044             GPRReg scratch2Reg = scratch2.gpr();
3045             
3046             if (!m_compileOkay)
3047                 return;
3048
3049             // Two really lame checks.
3050             speculationCheck(
3051                 Uncountable, JSValueSource(), NoNode,
3052                 m_jit.branchPtr(
3053                     MacroAssembler::AboveOrEqual, propertyReg,
3054                     MacroAssembler::Address(baseReg, OBJECT_OFFSETOF(Arguments, m_numArguments))));
3055             speculationCheck(
3056                 Uncountable, JSValueSource(), NoNode,
3057                 m_jit.branchTestPtr(
3058                     MacroAssembler::NonZero,
3059                     MacroAssembler::Address(
3060                         baseReg, OBJECT_OFFSETOF(Arguments, m_slowArguments))));
3061     
3062             m_jit.move(propertyReg, scratch2Reg);
3063             m_jit.neg32(scratch2Reg);
3064             m_jit.signExtend32ToPtr(scratch2Reg, scratch2Reg);
3065             m_jit.loadPtr(
3066                 MacroAssembler::Address(baseReg, OBJECT_OFFSETOF(Arguments, m_registers)),
3067                 scratchReg);
3068             
3069             m_jit.store64(
3070                 valueReg,
3071                 MacroAssembler::BaseIndex(
3072                     scratchReg, scratch2Reg, MacroAssembler::TimesEight,
3073                     CallFrame::thisArgumentOffset() * sizeof(Register) - sizeof(Register)));
3074             
3075             noResult(m_compileIndex);
3076             break;
3077         }
3078             
3079         case Array::Int8Array:
3080             compilePutByValForIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int8_t), SignedTypedArray);
3081             break;
3082             
3083         case Array::Int16Array:
3084             compilePutByValForIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int16_t), SignedTypedArray);
3085             break;
3086             
3087         case Array::Int32Array:
3088             compilePutByValForIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int32_t), SignedTypedArray);
3089             break;
3090             
3091         case Array::Uint8Array:
3092             compilePutByValForIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), UnsignedTypedArray);
3093             break;
3094             
3095         case Array::Uint8ClampedArray:
3096             compilePutByValForIntTypedArray(m_jit.globalData()->uint8ClampedArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), UnsignedTypedArray, ClampRounding);
3097             break;
3098             
3099         case Array::Uint16Array:
3100             compilePutByValForIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint16_t), UnsignedTypedArray);
3101             break;
3102             
3103         case Array::Uint32Array:
3104             compilePutByValForIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint32_t), UnsignedTypedArray);
3105             break;
3106             
3107         case Array::Float32Array:
3108             compilePutByValForFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(float));
3109             break;
3110             
3111         case Array::Float64Array:
3112             compilePutByValForFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(double));
3113             break;
3114             
3115         default:
3116             ASSERT_NOT_REACHED();
3117             break;
3118         }
3119
3120         break;
3121     }
3122
3123     case RegExpExec: {
3124         if (compileRegExpExec(node))
3125             return;
3126         if (!node.adjustedRefCount()) {
3127             SpeculateCellOperand base(this, node.child1());
3128             SpeculateCellOperand argument(this, node.child2());
3129             GPRReg baseGPR = base.gpr();
3130             GPRReg argumentGPR = argument.gpr();
3131             
3132             flushRegisters();
3133             GPRResult result(this);
3134             callOperation(operationRegExpTest, result.gpr(), baseGPR, argumentGPR);
3135             
3136             // Must use jsValueResult because otherwise we screw up register
3137             // allocation, which thinks that this node has a result.
3138             jsValueResult(result.gpr(), m_compileIndex);
3139             break;
3140         }
3141
3142         SpeculateCellOperand base(this, node.child1());
3143         SpeculateCellOperand argument(this, node.child2());
3144         GPRReg baseGPR = base.gpr();
3145         GPRReg argumentGPR = argument.gpr();
3146         
3147         flushRegisters();
3148         GPRResult result(this);
3149         callOperation(operationRegExpExec, result.gpr(), baseGPR, argumentGPR);
3150         
3151         jsValueResult(result.gpr(), m_compileIndex);
3152         break;
3153     }
3154
3155     case RegExpTest: {
3156         SpeculateCellOperand base(this, node.child1());
3157         SpeculateCellOperand argument(this, node.child2());
3158         GPRReg baseGPR = base.gpr();
3159         GPRReg argumentGPR = argument.gpr();
3160         
3161         flushRegisters();
3162         GPRResult result(this);
3163         callOperation(operationRegExpTest, result.gpr(), baseGPR, argumentGPR);
3164         
3165         // If we add a DataFormatBool, we should use it here.
3166         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
3167         jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
3168         break;
3169     }
3170         
3171     case ArrayPush: {
3172         ASSERT(node.arrayMode().isJSArray());
3173         
3174         SpeculateCellOperand base(this, node.child1());
3175         GPRTemporary storageLength(this);
3176         
3177         GPRReg baseGPR = base.gpr();
3178         GPRReg storageLengthGPR = storageLength.gpr();
3179         
3180         StorageOperand storage(this, node.child3());
3181         GPRReg storageGPR = storage.gpr();
3182
3183         switch (node.arrayMode().type()) {
3184         case Array::Int32:
3185         case Array::Contiguous: {
3186             JSValueOperand value(this, node.child2());
3187             GPRReg valueGPR = value.gpr();
3188
3189             if (node.arrayMode().type() == Array::Int32 && !isInt32Speculation(m_state.forNode(node.child2()).m_type)) {
3190                 speculationCheck(
3191                     BadType, JSValueRegs(valueGPR), node.child2(),
3192                     m_jit.branch64(MacroAssembler::Below, valueGPR, GPRInfo::tagTypeNumberRegister));
3193             }
3194
3195             if (node.arrayMode().type() != Array::Int32 && Heap::isWriteBarrierEnabled()) {
3196                 GPRTemporary scratch(this);
3197                 writeBarrier(baseGPR, valueGPR, node.child2(), WriteBarrierForPropertyAccess, scratch.gpr(), storageLengthGPR);
3198             }
3199             
3200             m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
3201             MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
3202             m_jit.store64(valueGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
3203             m_jit.add32(TrustedImm32(1), storageLengthGPR);
3204             m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
3205             m_jit.or64(GPRInfo::tagTypeNumberRegister, storageLengthGPR);
3206             
3207             addSlowPathGenerator(
3208                 slowPathCall(
3209                     slowPath, this, operationArrayPush, NoResult, storageLengthGPR,
3210                     valueGPR, baseGPR));
3211         
3212             jsValueResult(storageLengthGPR, m_compileIndex);
3213             break;
3214         }
3215             
3216         case Array::Double: {
3217             SpeculateDoubleOperand value(this, node.child2());
3218             FPRReg valueFPR = value.fpr();
3219
3220             if (!isRealNumberSpeculation(m_state.forNode(node.child2()).m_type)) {
3221                 // FIXME: We need a way of profiling these, and we need to hoist them into
3222                 // SpeculateDoubleOperand.
3223                 speculationCheck(
3224                     BadType, JSValueRegs(), NoNode,
3225                     m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, valueFPR, valueFPR));
3226             }
3227             
3228             m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
3229             MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
3230             m_jit.storeDouble(valueFPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
3231             m_jit.add32(TrustedImm32(1), storageLengthGPR);
3232             m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
3233             m_jit.or64(GPRInfo::tagTypeNumberRegister, storageLengthGPR);
3234             
3235             addSlowPathGenerator(
3236                 slowPathCall(
3237                     slowPath, this, operationArrayPushDouble, NoResult, storageLengthGPR,
3238                     valueFPR, baseGPR));
3239         
3240             jsValueResult(storageLengthGPR, m_compileIndex);
3241             break;
3242         }
3243             
3244         case Array::ArrayStorage: {
3245             JSValueOperand value(this, node.child2());
3246             GPRReg valueGPR = value.gpr();
3247
3248             if (Heap::isWriteBarrierEnabled()) {
3249                 GPRTemporary scratch(this);
3250                 writeBarrier(baseGPR, valueGPR, node.child2(), WriteBarrierForPropertyAccess, scratch.gpr(), storageLengthGPR);
3251             }
3252
3253             m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
3254         
3255             // Refuse to handle bizarre lengths.
3256             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::Above, storageLengthGPR, TrustedImm32(0x7ffffffe)));
3257         
3258             MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset()));
3259         
3260             m_jit.store64(valueGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
3261         
3262             m_jit.add32(TrustedImm32(1), storageLengthGPR);
3263             m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()));
3264             m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
3265             m_jit.or64(GPRInfo::tagTypeNumberRegister, storageLengthGPR);
3266         
3267             addSlowPathGenerator(
3268                 slowPathCall(
3269                     slowPath, this, operationArrayPush, NoResult, storageLengthGPR,
3270                     valueGPR, baseGPR));
3271         
3272             jsValueResult(storageLengthGPR, m_compileIndex);
3273             break;
3274         }
3275             
3276         default:
3277             CRASH();
3278             break;
3279         }
3280         break;
3281     }
3282         
3283     case ArrayPop: {
3284         ASSERT(node.arrayMode().isJSArray());
3285
3286         SpeculateCellOperand base(this, node.child1());
3287         StorageOperand storage(this, node.child2());
3288         GPRTemporary value(this);
3289         GPRTemporary storageLength(this);
3290         FPRTemporary temp(this); // This is kind of lame, since we don't always need it. I'm relying on the fact that we don't have FPR pressure, especially in code that uses pop().
3291         
3292         GPRReg baseGPR = base.gpr();
3293         GPRReg storageGPR = storage.gpr();
3294         GPRReg valueGPR = value.gpr();
3295         GPRReg storageLengthGPR = storageLength.gpr();
3296         FPRReg tempFPR = temp.fpr();
3297         
3298         switch (node.arrayMode().type()) {
3299         case Array::Int32:
3300         case Array::Double:
3301         case Array::Contiguous: {
3302             m_jit.load32(
3303                 MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
3304             MacroAssembler::Jump undefinedCase =
3305                 m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR);
3306             m_jit.sub32(TrustedImm32(1), storageLengthGPR);
3307             m_jit.store32(
3308                 storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
3309             MacroAssembler::Jump slowCase;
3310             if (node.arrayMode().type() == Array::Double) {
3311                 m_jit.loadDouble(
3312                     MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight),
3313                     tempFPR);
3314                 // FIXME: This would not have to be here if changing the publicLength also zeroed the values between the old
3315                 // length and the new length.
3316                 m_jit.store64(
3317                 MacroAssembler::TrustedImm64((int64_t)0), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
3318                 slowCase = m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, tempFPR, tempFPR);
3319                 boxDouble(tempFPR, valueGPR);
3320             } else {
3321                 m_jit.load64(
3322                     MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight),
3323                     valueGPR);
3324                 // FIXME: This would not have to be here if changing the publicLength also zeroed the values between the old
3325                 // length and the new length.
3326                 m_jit.store64(
3327                 MacroAssembler::TrustedImm64((int64_t)0), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
3328                 slowCase = m_jit.branchTest64(MacroAssembler::Zero, valueGPR);
3329             }
3330
3331             addSlowPathGenerator(
3332                 slowPathMove(
3333                     undefinedCase, this,
3334                     MacroAssembler::TrustedImm64(JSValue::encode(jsUndefined())), valueGPR));
3335             addSlowPathGenerator(
3336                 slowPathCall(
3337                     slowCase, this, operationArrayPopAndRecoverLength, valueGPR, baseGPR));
3338             
3339             // We can't know for sure that the result is an int because of the slow paths. :-/
3340             jsValueResult(valueGPR, m_compileIndex);
3341             break;
3342         }
3343             
3344         case Array::ArrayStorage: {
3345             m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
3346         
3347             JITCompiler::Jump undefinedCase =
3348                 m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR);
3349         
3350             m_jit.sub32(TrustedImm32(1), storageLengthGPR);
3351         
3352             JITCompiler::JumpList slowCases;
3353             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset())));
3354         
3355             m_jit.load64(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), valueGPR);
3356             slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, valueGPR));
3357         
3358             m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()));
3359         
3360             m_jit.store64(MacroAssembler::TrustedImm64((int64_t)0), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
3361             m_jit.sub32(MacroAssembler::TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
3362         
3363             addSlowPathGenerator(
3364                 slowPathMove(
3365                     undefinedCase, this,
3366                     MacroAssembler::TrustedImm64(JSValue::encode(jsUndefined())), valueGPR));
3367         
3368             addSlowPathGenerator(
3369                 slowPathCall(
3370                     slowCases, this, operationArrayPop, valueGPR, baseGPR));
3371
3372             jsValueResult(valueGPR, m_compileIndex);
3373             break;
3374         }
3375             
3376         default:
3377             CRASH();
3378             break;
3379         }
3380         break;
3381     }
3382
3383     case DFG::Jump: {
3384         BlockIndex taken = node.takenBlockIndex();
3385         jump(taken);
3386         noResult(m_compileIndex);
3387         break;
3388     }
3389
3390     case Branch:
3391         if (at(node.child1()).shouldSpeculateInteger()) {
3392             SpeculateIntegerOperand op(this, node.child1());
3393             
3394             BlockIndex taken = node.takenBlockIndex();
3395             BlockIndex notTaken = node.notTakenBlockIndex();
3396             
3397             MacroAssembler::ResultCondition condition = MacroAssembler::NonZero;
3398             
3399             if (taken == nextBlock()) {
3400                 condition = MacroAssembler::Zero;
3401                 BlockIndex tmp = taken;
3402                 taken = notTaken;
3403                 notTaken = tmp;
3404             }
3405             
3406             branchTest32(condition, op.gpr(), taken);
3407             jump(notTaken);
3408             
3409             noResult(m_compileIndex);
3410             break;
3411         }
3412         emitBranch(node);
3413         break;
3414
3415     case Return: {
3416         ASSERT(GPRInfo::callFrameRegister != GPRInfo::regT1);
3417         ASSERT(GPRInfo::regT1 != GPRInfo::returnValueGPR);
3418         ASSERT(GPRInfo::returnValueGPR != GPRInfo::callFrameRegister);
3419
3420 #if DFG_ENABLE(SUCCESS_STATS)
3421         static SamplingCounter counter("SpeculativeJIT");
3422         m_jit.emitCount(counter);
3423 #endif
3424
3425         // Return the result in returnValueGPR.
3426         JSValueOperand op1(this, node.child1());
3427         m_jit.move(op1.gpr(), GPRInfo::returnValueGPR);
3428
3429         // Grab the return address.
3430         m_jit.emitGetFromCallFrameHeaderPtr(JSStack::ReturnPC, GPRInfo::regT1);
3431         // Restore our caller's "r".
3432         m_jit.emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, GPRInfo::callFrameRegister);
3433         // Return.
3434         m_jit.restoreReturnAddressBeforeReturn(GPRInfo::regT1);
3435         m_jit.ret();
3436         
3437         noResult(m_compileIndex);
3438         break;
3439     }
3440         
3441     case Throw:
3442     case ThrowReferenceError: {
3443         // We expect that throw statements are rare and are intended to exit the code block
3444         // anyway, so we just OSR back to the old JIT for now.
3445         terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
3446         break;
3447     }
3448         
3449     case ToPrimitive: {
3450         if (at(node.child1()).shouldSpeculateInteger()) {
3451             // It's really profitable to speculate integer, since it's really cheap,
3452             // it means we don't have to do any real work, and we emit a lot less code.
3453             
3454             SpeculateIntegerOperand op1(this, node.child1());
3455             GPRTemporary result(this, op1);
3456             
3457             m_jit.move(op1.gpr(), result.gpr());
3458             if (op1.format() == DataFormatInteger)
3459                 m_jit.or64(GPRInfo::tagTypeNumberRegister, result.gpr());
3460             
3461             jsValueResult(result.gpr(), m_compileIndex);
3462             break;
3463         }
3464         
3465         // FIXME: Add string speculation here.
3466         
3467         JSValueOperand op1(this, node.child1());
3468         GPRTemporary result(this, op1);
3469         
3470         GPRReg op1GPR = op1.gpr();
3471         GPRReg resultGPR = result.gpr();
3472         
3473         op1.use();
3474         
3475         if (!(m_state.forNode(node.child1()).m_type & ~(SpecNumber | SpecBoolean)))
3476             m_jit.move(op1GPR, resultGPR);
3477         else {
3478             MacroAssembler::Jump alreadyPrimitive = m_jit.branchTest64(MacroAssembler::NonZero, op1GPR, GPRInfo::tagMaskRegister);
3479             MacroAssembler::Jump notPrimitive = m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR, JSCell::structureOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()));
3480             
3481             alreadyPrimitive.link(&m_jit);
3482             m_jit.move(op1GPR, resultGPR);
3483             
3484             addSlowPathGenerator(
3485                 slowPathCall(notPrimitive, this, operationToPrimitive, resultGPR, op1GPR));
3486         }
3487         
3488         jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
3489         break;
3490     }
3491         
3492     case NewArray: {
3493         JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node.codeOrigin);
3494         if (!globalObject->isHavingABadTime() && !hasArrayStorage(node.indexingType())) {
3495             globalObject->havingABadTimeWatchpoint()->add(speculationWatchpoint());
3496             
3497             Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(node.indexingType());
3498             ASSERT(structure->indexingType() == node.indexingType());
3499             ASSERT(
3500                 hasUndecided(structure->indexingType())
3501                 || hasInt32(structure->indexingType())
3502                 || hasDouble(structure->indexingType())
3503                 || hasContiguous(structure->indexingType()));
3504             
3505             unsigned numElements = node.numChildren();
3506             
3507             GPRTemporary result(this);
3508             GPRTemporary storage(this);
3509             
3510             GPRReg resultGPR = result.gpr();
3511             GPRReg storageGPR = storage.gpr();
3512
3513             emitAllocateJSArray(structure, resultGPR, storageGPR, numElements);
3514             
3515             // At this point, one way or another, resultGPR and storageGPR have pointers to
3516             // the JSArray and the Butterfly, respectively.
3517             
3518             ASSERT(!hasUndecided(structure->indexingType()) || !node.numChildren());
3519             
3520             for (unsigned operandIdx = 0; operandIdx < node.numChildren(); ++operandIdx) {
3521                 Edge use = m_jit.graph().m_varArgChildren[node.firstChild() + operandIdx];
3522                 switch (node.indexingType()) {
3523                 case ALL_BLANK_INDEXING_TYPES:
3524                 case ALL_UNDECIDED_INDEXING_TYPES:
3525                     CRASH();
3526                     break;
3527                 case ALL_DOUBLE_INDEXING_TYPES: {
3528                     SpeculateDoubleOperand operand(this, use);
3529                     FPRReg opFPR = operand.fpr();
3530                     if (!isRealNumberSpeculation(m_state.forNode(use).m_type)) {
3531                         // FIXME: We need a way of profiling these, and we need to hoist them into
3532                         // SpeculateDoubleOperand.
3533                         speculationCheck(
3534                             BadType, JSValueRegs(), NoNode,
3535                             m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, opFPR, opFPR));
3536                     }
3537         
3538                     m_jit.storeDouble(opFPR, MacroAssembler::Address(storageGPR, sizeof(double) * operandIdx));
3539                     break;
3540                 }
3541                 case ALL_INT32_INDEXING_TYPES:
3542                 case ALL_CONTIGUOUS_INDEXING_TYPES: {
3543                     JSValueOperand operand(this, use);
3544                     GPRReg opGPR = operand.gpr();
3545                     if (hasInt32(node.indexingType()) && !isInt32Speculation(m_state.forNode(use).m_type)) {
3546                         speculationCheck(
3547                             BadType, JSValueRegs(opGPR), use.index(),
3548                             m_jit.branch64(MacroAssembler::Below, opGPR, GPRInfo::tagTypeNumberRegister));
3549                     }
3550                     m_jit.store64(opGPR, MacroAssembler::Address(storageGPR, sizeof(JSValue) * operandIdx));
3551                     break;
3552                 }
3553                 default:
3554                     CRASH();
3555                     break;
3556                 }
3557             }
3558             
3559             // Yuck, we should *really* have a way of also returning the storageGPR. But
3560             // that's the least of what's wrong with this code. We really shouldn't be
3561             // allocating the array after having computed - and probably spilled to the
3562             // stack - all of the things that will go into the array. The solution to that
3563             // bigger problem will also likely fix the redundancy in reloading the storage
3564             // pointer that we currently have.
3565             
3566             cellResult(resultGPR, m_compileIndex);
3567             break;
3568         }
3569         
3570         if (!node.numChildren()) {
3571             flushRegisters();
3572             GPRResult result(this);
3573             callOperation(operationNewEmptyArray, result.gpr(), globalObject->arrayStructureForIndexingTypeDuringAllocation(node.indexingType()));
3574             cellResult(result.gpr(), m_compileIndex);
3575             break;
3576         }
3577         
3578         size_t scratchSize = sizeof(EncodedJSValue) * node.numChildren();
3579         ScratchBuffer* scratchBuffer = m_jit.globalData()->scratchBufferForSize(scratchSize);
3580         EncodedJSValue* buffer = scratchBuffer ? static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) : 0;
3581         
3582         for (unsigned operandIdx = 0; operandIdx < node.numChildren(); ++operandIdx) {
3583             // Need to perform the speculations that this node promises to perform. If we're
3584             // emitting code here and the indexing type is not array storage then there is
3585             // probably something hilarious going on and we're already failing at all the
3586             // things, but at least we're going to be sound.
3587             Edge use = m_jit.graph().m_varArgChildren[node.firstChild() + operandIdx];
3588             switch (node.indexingType()) {
3589             case ALL_BLANK_INDEXING_TYPES:
3590             case ALL_UNDECIDED_INDEXING_TYPES:
3591                 CRASH();
3592                 break;
3593             case ALL_DOUBLE_INDEXING_TYPES: {
3594                 SpeculateDoubleOperand operand(this, use);
3595                 GPRTemporary scratch(this);
3596                 FPRReg opFPR = operand.fpr();
3597                 GPRReg scratchGPR = scratch.gpr();
3598                 if (!isRealNumberSpeculation(m_state.forNode(use).m_type)) {
3599                     // FIXME: We need a way of profiling these, and we need to hoist them into
3600                     // SpeculateDoubleOperand.
3601                     speculationCheck(
3602                         BadType, JSValueRegs(), NoNode,
3603                         m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, opFPR, opFPR));
3604                 }
3605                 
3606                 m_jit.boxDouble(opFPR, scratchGPR);
3607                 m_jit.store64(scratchGPR, buffer + operandIdx);
3608                 break;
3609             }
3610             case ALL_INT32_INDEXING_TYPES: {
3611                 JSValueOperand operand(this, use);
3612                 GPRReg opGPR = operand.gpr();
3613                 if (hasInt32(node.indexingType()) && !isInt32Speculation(m_state.forNode(use).m_type)) {
3614                     speculationCheck(
3615                         BadType, JSValueRegs(opGPR), use.index(),