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