65fdf5593a7817a8f4dfc35d43c5f54ce9f32d34
[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 void SpeculativeJIT::compile(Node& node)
2050 {
2051     NodeType op = node.op();
2052
2053     switch (op) {
2054     case JSConstant:
2055         initConstantInfo(m_compileIndex);
2056         break;
2057
2058     case PhantomArguments:
2059         initConstantInfo(m_compileIndex);
2060         break;
2061
2062     case WeakJSConstant:
2063         m_jit.addWeakReference(node.weakConstant());
2064         initConstantInfo(m_compileIndex);
2065         break;
2066
2067     case GetLocal: {
2068         SpeculatedType prediction = node.variableAccessData()->prediction();
2069         AbstractValue& value = block()->valuesAtHead.operand(node.local());
2070
2071         // If we have no prediction for this local, then don't attempt to compile.
2072         if (prediction == SpecNone) {
2073             terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode);
2074             break;
2075         }
2076         
2077         if (!node.variableAccessData()->isCaptured()) {
2078             // If the CFA is tracking this variable and it found that the variable
2079             // cannot have been assigned, then don't attempt to proceed.
2080             if (value.isClear()) {
2081                 terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode);
2082                 break;
2083             }
2084             
2085             if (node.variableAccessData()->shouldUseDoubleFormat()) {
2086                 FPRTemporary result(this);
2087                 m_jit.loadDouble(JITCompiler::addressFor(node.local()), result.fpr());
2088                 VirtualRegister virtualRegister = node.virtualRegister();
2089                 m_fprs.retain(result.fpr(), virtualRegister, SpillOrderDouble);
2090                 m_generationInfo[virtualRegister].initDouble(m_compileIndex, node.refCount(), result.fpr());
2091                 break;
2092             }
2093         
2094             if (isInt32Speculation(value.m_type)) {
2095                 GPRTemporary result(this);
2096                 m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr());
2097
2098                 // Like integerResult, but don't useChildren - our children are phi nodes,
2099                 // and don't represent values within this dataflow with virtual registers.
2100                 VirtualRegister virtualRegister = node.virtualRegister();
2101                 m_gprs.retain(result.gpr(), virtualRegister, SpillOrderInteger);
2102                 m_generationInfo[virtualRegister].initInteger(m_compileIndex, node.refCount(), result.gpr());
2103                 break;
2104             }
2105
2106             if (isCellSpeculation(value.m_type)) {
2107                 GPRTemporary result(this);
2108                 m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr());
2109
2110                 // Like cellResult, but don't useChildren - our children are phi nodes,
2111                 // and don't represent values within this dataflow with virtual registers.
2112                 VirtualRegister virtualRegister = node.virtualRegister();
2113                 m_gprs.retain(result.gpr(), virtualRegister, SpillOrderCell);
2114                 m_generationInfo[virtualRegister].initCell(m_compileIndex, node.refCount(), result.gpr());
2115                 break;
2116             }
2117
2118             if (isBooleanSpeculation(value.m_type)) {
2119                 GPRTemporary result(this);
2120                 m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr());
2121
2122                 // Like booleanResult, but don't useChildren - our children are phi nodes,
2123                 // and don't represent values within this dataflow with virtual registers.
2124                 VirtualRegister virtualRegister = node.virtualRegister();
2125                 m_gprs.retain(result.gpr(), virtualRegister, SpillOrderBoolean);
2126                 m_generationInfo[virtualRegister].initBoolean(m_compileIndex, node.refCount(), result.gpr());
2127                 break;
2128             }
2129         }
2130
2131         GPRTemporary result(this);
2132         GPRTemporary tag(this);
2133         m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr());
2134         m_jit.load32(JITCompiler::tagFor(node.local()), tag.gpr());
2135
2136         // Like jsValueResult, but don't useChildren - our children are phi nodes,
2137         // and don't represent values within this dataflow with virtual registers.
2138         VirtualRegister virtualRegister = node.virtualRegister();
2139         m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
2140         m_gprs.retain(tag.gpr(), virtualRegister, SpillOrderJS);
2141
2142         DataFormat format;
2143         if (isCellSpeculation(value.m_type)
2144             && !node.variableAccessData()->isCaptured())
2145             format = DataFormatJSCell;
2146         else
2147             format = DataFormatJS;
2148         m_generationInfo[virtualRegister].initJSValue(m_compileIndex, node.refCount(), tag.gpr(), result.gpr(), format);
2149         break;
2150     }
2151         
2152     case GetLocalUnlinked: {
2153         GPRTemporary payload(this);
2154         GPRTemporary tag(this);
2155         m_jit.load32(JITCompiler::payloadFor(node.unlinkedLocal()), payload.gpr());
2156         m_jit.load32(JITCompiler::tagFor(node.unlinkedLocal()), tag.gpr());
2157         jsValueResult(tag.gpr(), payload.gpr(), m_compileIndex);
2158         break;
2159     }
2160
2161     case SetLocal: {
2162         // SetLocal doubles as a hint as to where a node will be stored and
2163         // as a speculation point. So before we speculate make sure that we
2164         // know where the child of this node needs to go in the virtual
2165         // stack.
2166         compileMovHint(node);
2167         
2168         // As far as OSR is concerned, we're on the bytecode index corresponding
2169         // to the *next* instruction, since we've already "executed" the
2170         // SetLocal and whatever other DFG Nodes are associated with the same
2171         // bytecode index as the SetLocal.
2172         ASSERT(m_codeOriginForOSR == node.codeOrigin);
2173         Node* nextNode = &at(block()->at(m_indexInBlock + 1));
2174
2175         // But even more oddly, we need to be super careful about the following
2176         // sequence:
2177         //
2178         // a: Foo()
2179         // b: SetLocal(@a)
2180         // c: Flush(@b)
2181         //
2182         // This next piece of crazy takes care of this.
2183         if (nextNode->op() == Flush && nextNode->child1() == m_compileIndex)
2184             nextNode = &at(block()->at(m_indexInBlock + 2));
2185         
2186         // Oddly, it's possible for the bytecode index for the next node to be
2187         // equal to ours. This will happen for op_post_inc. And, even more oddly,
2188         // this is just fine. Ordinarily, this wouldn't be fine, since if the
2189         // next node failed OSR then we'd be OSR-ing with this SetLocal's local
2190         // variable already set even though from the standpoint of the old JIT,
2191         // this SetLocal should not have executed. But for op_post_inc, it's just
2192         // fine, because this SetLocal's local (i.e. the LHS in a x = y++
2193         // statement) would be dead anyway - so the fact that DFG would have
2194         // already made the assignment, and baked it into the stack during
2195         // OSR exit, would not be visible to the old JIT in any way.
2196         m_codeOriginForOSR = nextNode->codeOrigin;
2197         
2198         if (!node.variableAccessData()->isCaptured() && !m_jit.graph().isCreatedThisArgument(node.local())) {
2199             if (node.variableAccessData()->shouldUseDoubleFormat()) {
2200                 SpeculateDoubleOperand value(this, node.child1());
2201                 m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node.local()));
2202                 noResult(m_compileIndex);
2203                 // Indicate that it's no longer necessary to retrieve the value of
2204                 // this bytecode variable from registers or other locations in the stack,
2205                 // but that it is stored as a double.
2206                 recordSetLocal(node.local(), ValueSource(DoubleInJSStack));
2207                 break;
2208             }
2209             SpeculatedType predictedType = node.variableAccessData()->argumentAwarePrediction();
2210             if (m_generationInfo[at(node.child1()).virtualRegister()].registerFormat() == DataFormatDouble) {
2211                 DoubleOperand value(this, node.child1());
2212                 m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node.local()));
2213                 noResult(m_compileIndex);
2214                 recordSetLocal(node.local(), ValueSource(DoubleInJSStack));
2215                 break;
2216             }
2217             if (isInt32Speculation(predictedType)) {
2218                 SpeculateIntegerOperand value(this, node.child1());
2219                 m_jit.store32(value.gpr(), JITCompiler::payloadFor(node.local()));
2220                 noResult(m_compileIndex);
2221                 recordSetLocal(node.local(), ValueSource(Int32InJSStack));
2222                 break;
2223             }
2224             if (isCellSpeculation(predictedType)) {
2225                 SpeculateCellOperand cell(this, node.child1());
2226                 GPRReg cellGPR = cell.gpr();
2227                 m_jit.storePtr(cellGPR, JITCompiler::payloadFor(node.local()));
2228                 noResult(m_compileIndex);
2229                 recordSetLocal(node.local(), ValueSource(CellInJSStack));
2230                 break;
2231             }
2232             if (isBooleanSpeculation(predictedType)) {
2233                 SpeculateBooleanOperand value(this, node.child1());
2234                 m_jit.store32(value.gpr(), JITCompiler::payloadFor(node.local()));
2235                 noResult(m_compileIndex);
2236                 recordSetLocal(node.local(), ValueSource(BooleanInJSStack));
2237                 break;
2238             }
2239         }
2240         JSValueOperand value(this, node.child1());
2241         m_jit.store32(value.payloadGPR(), JITCompiler::payloadFor(node.local()));
2242         m_jit.store32(value.tagGPR(), JITCompiler::tagFor(node.local()));
2243         noResult(m_compileIndex);
2244         recordSetLocal(node.local(), ValueSource(ValueInJSStack));
2245
2246         // If we're storing an arguments object that has been optimized away,
2247         // our variable event stream for OSR exit now reflects the optimized
2248         // value (JSValue()). On the slow path, we want an arguments object
2249         // instead. We add an additional move hint to show OSR exit that it
2250         // needs to reconstruct the arguments object.
2251         if (at(node.child1()).op() == PhantomArguments)
2252             compileMovHint(node);
2253
2254         break;
2255     }
2256
2257     case SetArgument:
2258         // This is a no-op; it just marks the fact that the argument is being used.
2259         // But it may be profitable to use this as a hook to run speculation checks
2260         // on arguments, thereby allowing us to trivially eliminate such checks if
2261         // the argument is not used.
2262         break;
2263
2264     case BitAnd:
2265     case BitOr:
2266     case BitXor:
2267         if (isInt32Constant(node.child1().index())) {
2268             SpeculateIntegerOperand op2(this, node.child2());
2269             GPRTemporary result(this, op2);
2270
2271             bitOp(op, valueOfInt32Constant(node.child1().index()), op2.gpr(), result.gpr());
2272
2273             integerResult(result.gpr(), m_compileIndex);
2274         } else if (isInt32Constant(node.child2().index())) {
2275             SpeculateIntegerOperand op1(this, node.child1());
2276             GPRTemporary result(this, op1);
2277
2278             bitOp(op, valueOfInt32Constant(node.child2().index()), op1.gpr(), result.gpr());
2279
2280             integerResult(result.gpr(), m_compileIndex);
2281         } else {
2282             SpeculateIntegerOperand op1(this, node.child1());
2283             SpeculateIntegerOperand op2(this, node.child2());
2284             GPRTemporary result(this, op1, op2);
2285
2286             GPRReg reg1 = op1.gpr();
2287             GPRReg reg2 = op2.gpr();
2288             bitOp(op, reg1, reg2, result.gpr());
2289
2290             integerResult(result.gpr(), m_compileIndex);
2291         }
2292         break;
2293
2294     case BitRShift:
2295     case BitLShift:
2296     case BitURShift:
2297         if (isInt32Constant(node.child2().index())) {
2298             SpeculateIntegerOperand op1(this, node.child1());
2299             GPRTemporary result(this, op1);
2300
2301             shiftOp(op, op1.gpr(), valueOfInt32Constant(node.child2().index()) & 0x1f, result.gpr());
2302
2303             integerResult(result.gpr(), m_compileIndex);
2304         } else {
2305             // Do not allow shift amount to be used as the result, MacroAssembler does not permit this.
2306             SpeculateIntegerOperand op1(this, node.child1());
2307             SpeculateIntegerOperand op2(this, node.child2());
2308             GPRTemporary result(this, op1);
2309
2310             GPRReg reg1 = op1.gpr();
2311             GPRReg reg2 = op2.gpr();
2312             shiftOp(op, reg1, reg2, result.gpr());
2313
2314             integerResult(result.gpr(), m_compileIndex);
2315         }
2316         break;
2317
2318     case UInt32ToNumber: {
2319         compileUInt32ToNumber(node);
2320         break;
2321     }
2322         
2323     case DoubleAsInt32: {
2324         compileDoubleAsInt32(node);
2325         break;
2326     }
2327
2328     case ValueToInt32: {
2329         compileValueToInt32(node);
2330         break;
2331     }
2332         
2333     case Int32ToDouble: {
2334         compileInt32ToDouble(node);
2335         break;
2336     }
2337         
2338     case CheckNumber: {
2339         if (!isNumberSpeculation(m_state.forNode(node.child1()).m_type)) {
2340             JSValueOperand op1(this, node.child1());
2341             JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, op1.tagGPR(), TrustedImm32(JSValue::Int32Tag));
2342             speculationCheck(
2343                 BadType, JSValueRegs(op1.tagGPR(), op1.payloadGPR()), node.child1().index(),
2344                 m_jit.branch32(MacroAssembler::AboveOrEqual, op1.tagGPR(), TrustedImm32(JSValue::LowestTag)));
2345             isInteger.link(&m_jit);
2346         }
2347         noResult(m_compileIndex);
2348         break;
2349     }
2350
2351     case ValueAdd:
2352     case ArithAdd:
2353         compileAdd(node);
2354         break;
2355
2356     case ArithSub:
2357         compileArithSub(node);
2358         break;
2359
2360     case ArithNegate:
2361         compileArithNegate(node);
2362         break;
2363
2364     case ArithMul:
2365         compileArithMul(node);
2366         break;
2367
2368     case ArithDiv: {
2369         if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) {
2370 #if CPU(X86)
2371             compileIntegerArithDivForX86(node);
2372 #else // CPU(X86) -> so non-X86 code follows
2373             ASSERT_NOT_REACHED(); // should have been coverted into a double divide.
2374 #endif // CPU(X86)
2375             break;
2376         }
2377         
2378         SpeculateDoubleOperand op1(this, node.child1());
2379         SpeculateDoubleOperand op2(this, node.child2());
2380         FPRTemporary result(this, op1);
2381
2382         FPRReg reg1 = op1.fpr();
2383         FPRReg reg2 = op2.fpr();
2384         m_jit.divDouble(reg1, reg2, result.fpr());
2385
2386         doubleResult(result.fpr(), m_compileIndex);
2387         break;
2388     }
2389
2390     case ArithMod: {
2391         compileArithMod(node);
2392         break;
2393     }
2394
2395     case ArithAbs: {
2396         if (at(node.child1()).shouldSpeculateInteger() && node.canSpeculateInteger()) {
2397             SpeculateIntegerOperand op1(this, node.child1());
2398             GPRTemporary result(this, op1);
2399             GPRTemporary scratch(this);
2400             
2401             m_jit.zeroExtend32ToPtr(op1.gpr(), result.gpr());
2402             m_jit.rshift32(result.gpr(), MacroAssembler::TrustedImm32(31), scratch.gpr());
2403             m_jit.add32(scratch.gpr(), result.gpr());
2404             m_jit.xor32(scratch.gpr(), result.gpr());
2405             speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::Equal, result.gpr(), MacroAssembler::TrustedImm32(1 << 31)));
2406             integerResult(result.gpr(), m_compileIndex);
2407             break;
2408         }
2409         
2410         SpeculateDoubleOperand op1(this, node.child1());
2411         FPRTemporary result(this);
2412         
2413         m_jit.absDouble(op1.fpr(), result.fpr());
2414         doubleResult(result.fpr(), m_compileIndex);
2415         break;
2416     }
2417         
2418     case ArithMin:
2419     case ArithMax: {
2420         if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) {
2421             SpeculateStrictInt32Operand op1(this, node.child1());
2422             SpeculateStrictInt32Operand op2(this, node.child2());
2423             GPRTemporary result(this, op1);
2424             
2425             MacroAssembler::Jump op1Less = m_jit.branch32(op == ArithMin ? MacroAssembler::LessThan : MacroAssembler::GreaterThan, op1.gpr(), op2.gpr());
2426             m_jit.move(op2.gpr(), result.gpr());
2427             if (op1.gpr() != result.gpr()) {
2428                 MacroAssembler::Jump done = m_jit.jump();
2429                 op1Less.link(&m_jit);
2430                 m_jit.move(op1.gpr(), result.gpr());
2431                 done.link(&m_jit);
2432             } else
2433                 op1Less.link(&m_jit);
2434             
2435             integerResult(result.gpr(), m_compileIndex);
2436             break;
2437         }
2438         
2439         SpeculateDoubleOperand op1(this, node.child1());
2440         SpeculateDoubleOperand op2(this, node.child2());
2441         FPRTemporary result(this, op1);
2442         
2443         MacroAssembler::JumpList done;
2444         
2445         MacroAssembler::Jump op1Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleLessThan : MacroAssembler::DoubleGreaterThan, op1.fpr(), op2.fpr());
2446         
2447         // op2 is eather the lesser one or one of then is NaN
2448         MacroAssembler::Jump op2Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleGreaterThanOrEqual : MacroAssembler::DoubleLessThanOrEqual, op1.fpr(), op2.fpr());
2449         
2450         // Unordered case. We don't know which of op1, op2 is NaN. Manufacture NaN by adding 
2451         // op1 + op2 and putting it into result.
2452         m_jit.addDouble(op1.fpr(), op2.fpr(), result.fpr());
2453         done.append(m_jit.jump());
2454         
2455         op2Less.link(&m_jit);
2456         m_jit.moveDouble(op2.fpr(), result.fpr());
2457         
2458         if (op1.fpr() != result.fpr()) {
2459             done.append(m_jit.jump());
2460             
2461             op1Less.link(&m_jit);
2462             m_jit.moveDouble(op1.fpr(), result.fpr());
2463         } else
2464             op1Less.link(&m_jit);
2465         
2466         done.link(&m_jit);
2467         
2468         doubleResult(result.fpr(), m_compileIndex);
2469         break;
2470     }
2471         
2472     case ArithSqrt: {
2473         SpeculateDoubleOperand op1(this, node.child1());
2474         FPRTemporary result(this, op1);
2475         
2476         m_jit.sqrtDouble(op1.fpr(), result.fpr());
2477         
2478         doubleResult(result.fpr(), m_compileIndex);
2479         break;
2480     }
2481
2482     case LogicalNot:
2483         compileLogicalNot(node);
2484         break;
2485
2486     case CompareLess:
2487         if (compare(node, JITCompiler::LessThan, JITCompiler::DoubleLessThan, operationCompareLess))
2488             return;
2489         break;
2490
2491     case CompareLessEq:
2492         if (compare(node, JITCompiler::LessThanOrEqual, JITCompiler::DoubleLessThanOrEqual, operationCompareLessEq))
2493             return;
2494         break;
2495
2496     case CompareGreater:
2497         if (compare(node, JITCompiler::GreaterThan, JITCompiler::DoubleGreaterThan, operationCompareGreater))
2498             return;
2499         break;
2500
2501     case CompareGreaterEq:
2502         if (compare(node, JITCompiler::GreaterThanOrEqual, JITCompiler::DoubleGreaterThanOrEqual, operationCompareGreaterEq))
2503             return;
2504         break;
2505
2506     case CompareEq:
2507         if (isNullConstant(node.child1().index())) {
2508             if (nonSpeculativeCompareNull(node, node.child2()))
2509                 return;
2510             break;
2511         }
2512         if (isNullConstant(node.child2().index())) {
2513             if (nonSpeculativeCompareNull(node, node.child1()))
2514                 return;
2515             break;
2516         }
2517         if (compare(node, JITCompiler::Equal, JITCompiler::DoubleEqual, operationCompareEq))
2518             return;
2519         break;
2520
2521     case CompareStrictEq:
2522         if (compileStrictEq(node))
2523             return;
2524         break;
2525
2526     case StringCharCodeAt: {
2527         compileGetCharCodeAt(node);
2528         break;
2529     }
2530
2531     case StringCharAt: {
2532         // Relies on StringCharAt node having same basic layout as GetByVal
2533         compileGetByValOnString(node);
2534         break;
2535     }
2536         
2537     case CheckArray: {
2538         checkArray(node);
2539         break;
2540     }
2541         
2542     case Arrayify:
2543     case ArrayifyToStructure: {
2544         arrayify(node);
2545         break;
2546     }
2547
2548     case GetByVal: {
2549         switch (node.arrayMode().type()) {
2550         case Array::SelectUsingPredictions:
2551         case Array::ForceExit:
2552             ASSERT_NOT_REACHED();
2553             terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode);
2554             break;
2555         case Array::Generic: {
2556             SpeculateCellOperand base(this, node.child1()); // Save a register, speculate cell. We'll probably be right.
2557             JSValueOperand property(this, node.child2());
2558             GPRReg baseGPR = base.gpr();
2559             GPRReg propertyTagGPR = property.tagGPR();
2560             GPRReg propertyPayloadGPR = property.payloadGPR();
2561             
2562             flushRegisters();
2563             GPRResult2 resultTag(this);
2564             GPRResult resultPayload(this);
2565             callOperation(operationGetByValCell, resultTag.gpr(), resultPayload.gpr(), baseGPR, propertyTagGPR, propertyPayloadGPR);
2566             
2567             jsValueResult(resultTag.gpr(), resultPayload.gpr(), m_compileIndex);
2568             break;
2569         }
2570         case Array::Contiguous: {
2571             if (node.arrayMode().isInBounds()) {
2572                 SpeculateStrictInt32Operand property(this, node.child2());
2573                 StorageOperand storage(this, node.child3());
2574             
2575                 GPRReg propertyReg = property.gpr();
2576                 GPRReg storageReg = storage.gpr();
2577             
2578                 if (!m_compileOkay)
2579                     return;
2580             
2581                 speculationCheck(OutOfBounds, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2582             
2583                 GPRTemporary resultTag(this);
2584                 GPRTemporary resultPayload(this);
2585                 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag.gpr());
2586                 speculationCheck(OutOfBounds, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::Equal, resultTag.gpr(), TrustedImm32(JSValue::EmptyValueTag)));
2587                 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload.gpr());
2588                 jsValueResult(resultTag.gpr(), resultPayload.gpr(), m_compileIndex);
2589                 break;
2590             }
2591
2592             SpeculateCellOperand base(this, node.child1());
2593             SpeculateStrictInt32Operand property(this, node.child2());
2594             StorageOperand storage(this, node.child3());
2595             
2596             GPRReg baseReg = base.gpr();
2597             GPRReg propertyReg = property.gpr();
2598             GPRReg storageReg = storage.gpr();
2599             
2600             if (!m_compileOkay)
2601                 return;
2602             
2603             GPRTemporary resultTag(this);
2604             GPRTemporary resultPayload(this);
2605             GPRReg resultTagReg = resultTag.gpr();
2606             GPRReg resultPayloadReg = resultPayload.gpr();
2607             
2608             MacroAssembler::JumpList slowCases;
2609
2610             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2611             
2612             m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTagReg);
2613             m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayloadReg);
2614             slowCases.append(m_jit.branch32(MacroAssembler::Equal, resultTagReg, TrustedImm32(JSValue::EmptyValueTag)));
2615             
2616             addSlowPathGenerator(
2617                 slowPathCall(
2618                     slowCases, this, operationGetByValArrayInt,
2619                     JSValueRegs(resultTagReg, resultPayloadReg), baseReg, propertyReg));
2620             
2621             jsValueResult(resultTagReg, resultPayloadReg, m_compileIndex);
2622             break;
2623         }
2624         case Array::ArrayStorage:
2625         case Array::SlowPutArrayStorage: {
2626             if (node.arrayMode().isInBounds()) {
2627                 SpeculateStrictInt32Operand property(this, node.child2());
2628                 StorageOperand storage(this, node.child3());
2629                 GPRReg propertyReg = property.gpr();
2630                 GPRReg storageReg = storage.gpr();
2631         
2632                 if (!m_compileOkay)
2633                     return;
2634
2635                 speculationCheck(OutOfBounds, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
2636
2637                 GPRTemporary resultTag(this);
2638                 GPRTemporary resultPayload(this);
2639
2640                 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag.gpr());
2641                 speculationCheck(OutOfBounds, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::Equal, resultTag.gpr(), TrustedImm32(JSValue::EmptyValueTag)));
2642                 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload.gpr());
2643             
2644                 jsValueResult(resultTag.gpr(), resultPayload.gpr(), m_compileIndex);
2645                 break;
2646             }
2647
2648             SpeculateCellOperand base(this, node.child1());
2649             SpeculateStrictInt32Operand property(this, node.child2());
2650             StorageOperand storage(this, node.child3());
2651             GPRReg propertyReg = property.gpr();
2652             GPRReg storageReg = storage.gpr();
2653             GPRReg baseReg = base.gpr();
2654
2655             if (!m_compileOkay)
2656                 return;
2657
2658             GPRTemporary resultTag(this);
2659             GPRTemporary resultPayload(this);
2660             GPRReg resultTagReg = resultTag.gpr();
2661             GPRReg resultPayloadReg = resultPayload.gpr();
2662
2663             JITCompiler::Jump outOfBounds = m_jit.branch32(
2664                 MacroAssembler::AboveOrEqual, propertyReg,
2665                 MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
2666
2667             m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTagReg);
2668             JITCompiler::Jump hole = m_jit.branch32(
2669                 MacroAssembler::Equal, resultTag.gpr(), TrustedImm32(JSValue::EmptyValueTag));
2670             m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayloadReg);
2671             
2672             JITCompiler::JumpList slowCases;
2673             slowCases.append(outOfBounds);
2674             slowCases.append(hole);
2675             addSlowPathGenerator(
2676                 slowPathCall(
2677                     slowCases, this, operationGetByValArrayInt,
2678                     JSValueRegs(resultTagReg, resultPayloadReg),
2679                     baseReg, propertyReg));
2680
2681             jsValueResult(resultTagReg, resultPayloadReg, m_compileIndex);
2682             break;
2683         }
2684         case Array::String:
2685             compileGetByValOnString(node);
2686             break;
2687         case Array::Arguments:
2688             compileGetByValOnArguments(node);
2689             break;
2690         case Array::Int8Array:
2691             compileGetByValOnIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), node, sizeof(int8_t), SignedTypedArray);
2692             break;
2693         case Array::Int16Array:
2694             compileGetByValOnIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), node, sizeof(int16_t), SignedTypedArray);
2695             break;
2696         case Array::Int32Array:
2697             compileGetByValOnIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), node, sizeof(int32_t), SignedTypedArray);
2698             break;
2699         case Array::Uint8Array:
2700             compileGetByValOnIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), node, sizeof(uint8_t), UnsignedTypedArray);
2701             break;
2702         case Array::Uint8ClampedArray:
2703             compileGetByValOnIntTypedArray(m_jit.globalData()->uint8ClampedArrayDescriptor(), node, sizeof(uint8_t), UnsignedTypedArray);
2704             break;
2705         case Array::Uint16Array:
2706             compileGetByValOnIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), node, sizeof(uint16_t), UnsignedTypedArray);
2707             break;
2708         case Array::Uint32Array:
2709             compileGetByValOnIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), node, sizeof(uint32_t), UnsignedTypedArray);
2710             break;
2711         case Array::Float32Array:
2712             compileGetByValOnFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), node, sizeof(float));
2713             break;
2714         case Array::Float64Array:
2715             compileGetByValOnFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), node, sizeof(double));
2716             break;
2717         default:
2718             ASSERT_NOT_REACHED();
2719             break;
2720         }
2721         break;
2722     }
2723
2724     case PutByVal:
2725     case PutByValAlias: {
2726         Edge child1 = m_jit.graph().varArgChild(node, 0);
2727         Edge child2 = m_jit.graph().varArgChild(node, 1);
2728         Edge child3 = m_jit.graph().varArgChild(node, 2);
2729         Edge child4 = m_jit.graph().varArgChild(node, 3);
2730         
2731         ArrayMode arrayMode = node.arrayMode().modeForPut();
2732         bool alreadyHandled = false;
2733         
2734         switch (arrayMode.type()) {
2735         case Array::SelectUsingPredictions:
2736         case Array::ForceExit:
2737             ASSERT_NOT_REACHED();
2738             terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode);
2739             alreadyHandled = true;
2740             break;
2741         case Array::Generic: {
2742             ASSERT(node.op() == PutByVal);
2743             
2744             SpeculateCellOperand base(this, child1); // Save a register, speculate cell. We'll probably be right.
2745             JSValueOperand property(this, child2);
2746             JSValueOperand value(this, child3);
2747             GPRReg baseGPR = base.gpr();
2748             GPRReg propertyTagGPR = property.tagGPR();
2749             GPRReg propertyPayloadGPR = property.payloadGPR();
2750             GPRReg valueTagGPR = value.tagGPR();
2751             GPRReg valuePayloadGPR = value.payloadGPR();
2752             
2753             flushRegisters();
2754             callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByValCellStrict : operationPutByValCellNonStrict, baseGPR, propertyTagGPR, propertyPayloadGPR, valueTagGPR, valuePayloadGPR);
2755             
2756             noResult(m_compileIndex);
2757             alreadyHandled = true;
2758             break;
2759         }
2760         default:
2761             break;
2762         }
2763         
2764         if (alreadyHandled)
2765             break;
2766         
2767         SpeculateCellOperand base(this, child1);
2768         SpeculateStrictInt32Operand property(this, child2);
2769         
2770         GPRReg baseReg = base.gpr();
2771         GPRReg propertyReg = property.gpr();
2772
2773         switch (arrayMode.type()) {
2774         case Array::Contiguous: {
2775             JSValueOperand value(this, child3);
2776
2777             GPRReg valueTagReg = value.tagGPR();
2778             GPRReg valuePayloadReg = value.payloadGPR();
2779         
2780             if (!m_compileOkay)
2781                 return;
2782         
2783             if (Heap::isWriteBarrierEnabled()) {
2784                 GPRTemporary scratch(this);
2785                 writeBarrier(baseReg, valueTagReg, child3, WriteBarrierForPropertyAccess, scratch.gpr());
2786             }
2787
2788             StorageOperand storage(this, child4);
2789             GPRReg storageReg = storage.gpr();
2790
2791             if (node.op() == PutByValAlias) {
2792                 // Store the value to the array.
2793                 GPRReg propertyReg = property.gpr();
2794                 m_jit.store32(valueTagReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
2795                 m_jit.store32(valuePayloadReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
2796                 
2797                 noResult(m_compileIndex);
2798                 break;
2799             }
2800             
2801             MacroAssembler::JumpList slowCases;
2802
2803             if (arrayMode.isInBounds()) {
2804                 speculationCheck(
2805                     Uncountable, JSValueRegs(), NoNode,
2806                     m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2807             } else {
2808                 MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
2809                 
2810                 slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfVectorLength())));
2811                 
2812                 if (!arrayMode.isOutOfBounds())
2813                     speculationCheck(Uncountable, JSValueRegs(), NoNode, slowCases);
2814                 
2815                 m_jit.add32(TrustedImm32(1), propertyReg);
2816                 m_jit.store32(propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
2817                 m_jit.sub32(TrustedImm32(1), propertyReg);
2818                 
2819                 inBounds.link(&m_jit);
2820             }
2821             
2822             m_jit.store32(valueTagReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
2823             m_jit.store32(valuePayloadReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
2824             
2825             base.use();
2826             property.use();
2827             value.use();
2828             storage.use();
2829             
2830             if (arrayMode.isOutOfBounds()) {
2831                 addSlowPathGenerator(
2832                     slowPathCall(
2833                         slowCases, this,
2834                         m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
2835                         NoResult, baseReg, propertyReg, valueTagReg, valuePayloadReg));
2836             }
2837
2838             noResult(m_compileIndex, UseChildrenCalledExplicitly);
2839             break;
2840         }
2841             
2842         case Array::ArrayStorage:
2843         case Array::SlowPutArrayStorage: {
2844             JSValueOperand value(this, child3);
2845
2846             GPRReg valueTagReg = value.tagGPR();
2847             GPRReg valuePayloadReg = value.payloadGPR();
2848             
2849             if (!m_compileOkay)
2850                 return;
2851             
2852             {
2853                 GPRTemporary scratch(this);
2854                 GPRReg scratchReg = scratch.gpr();
2855                 writeBarrier(baseReg, valueTagReg, child3, WriteBarrierForPropertyAccess, scratchReg);
2856             }
2857             
2858             StorageOperand storage(this, child4);
2859             GPRReg storageReg = storage.gpr();
2860
2861             if (node.op() == PutByValAlias) {
2862                 // Store the value to the array.
2863                 GPRReg propertyReg = property.gpr();
2864                 m_jit.store32(value.tagGPR(), MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
2865                 m_jit.store32(value.payloadGPR(), MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
2866                 
2867                 noResult(m_compileIndex);
2868                 break;
2869             }
2870
2871             MacroAssembler::JumpList slowCases;
2872
2873             MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
2874             if (!arrayMode.isOutOfBounds())
2875                 speculationCheck(OutOfBounds, JSValueRegs(), NoNode, beyondArrayBounds);
2876             else
2877                 slowCases.append(beyondArrayBounds);
2878
2879             // Check if we're writing to a hole; if so increment m_numValuesInVector.
2880             if (arrayMode.isInBounds()) {
2881                 // This is uncountable because if we take this exit, then the baseline JIT
2882                 // will immediately count the hole store. So there is no need for exit
2883                 // profiling.
2884                 speculationCheck(
2885                     Uncountable, JSValueRegs(), NoNode,
2886                     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)));
2887             } else {
2888                 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));
2889                 if (arrayMode.isSlowPut()) {
2890                     // This is sort of strange. If we wanted to optimize this code path, we would invert
2891                     // the above branch. But it's simply not worth it since this only happens if we're
2892                     // already having a bad time.
2893                     slowCases.append(m_jit.jump());
2894                 } else {
2895                     m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, ArrayStorage::numValuesInVectorOffset()));
2896                 
2897                     // If we're writing to a hole we might be growing the array; 
2898                     MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
2899                     m_jit.add32(TrustedImm32(1), propertyReg);
2900                     m_jit.store32(propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
2901                     m_jit.sub32(TrustedImm32(1), propertyReg);
2902                 
2903                     lengthDoesNotNeedUpdate.link(&m_jit);
2904                 }
2905                 notHoleValue.link(&m_jit);
2906             }
2907     
2908             // Store the value to the array.
2909             m_jit.store32(valueTagReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
2910             m_jit.store32(valuePayloadReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
2911
2912             base.use();
2913             property.use();
2914             value.use();
2915             storage.use();
2916             
2917             if (!slowCases.empty()) {
2918                 addSlowPathGenerator(
2919                     slowPathCall(
2920                         slowCases, this,
2921                         m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
2922                         NoResult, baseReg, propertyReg, valueTagReg, valuePayloadReg));
2923             }
2924
2925             noResult(m_compileIndex, UseChildrenCalledExplicitly);
2926             break;
2927         }
2928             
2929         case Array::Arguments:
2930             // FIXME: we could at some point make this work. Right now we're assuming that the register
2931             // pressure would be too great.
2932             ASSERT_NOT_REACHED();
2933             break;
2934             
2935         case Array::Int8Array:
2936             compilePutByValForIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int8_t), SignedTypedArray);
2937             break;
2938             
2939         case Array::Int16Array:
2940             compilePutByValForIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int16_t), SignedTypedArray);
2941             break;
2942             
2943         case Array::Int32Array:
2944             compilePutByValForIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int32_t), SignedTypedArray);
2945             break;
2946             
2947         case Array::Uint8Array:
2948             compilePutByValForIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), UnsignedTypedArray);
2949             break;
2950             
2951         case Array::Uint8ClampedArray:
2952             compilePutByValForIntTypedArray(m_jit.globalData()->uint8ClampedArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), UnsignedTypedArray, ClampRounding);
2953             break;
2954             
2955         case Array::Uint16Array:
2956             compilePutByValForIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint16_t), UnsignedTypedArray);
2957             break;
2958             
2959         case Array::Uint32Array:
2960             compilePutByValForIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint32_t), UnsignedTypedArray);
2961             break;
2962             
2963         case Array::Float32Array:
2964             compilePutByValForFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(float));
2965             break;
2966             
2967         case Array::Float64Array:
2968             compilePutByValForFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(double));
2969             break;
2970             
2971         default:
2972             ASSERT_NOT_REACHED();
2973             break;
2974         }
2975         break;
2976     }
2977
2978     case RegExpExec: {
2979         if (compileRegExpExec(node))
2980             return;
2981
2982         if (!node.adjustedRefCount()) {
2983             SpeculateCellOperand base(this, node.child1());
2984             SpeculateCellOperand argument(this, node.child2());
2985             GPRReg baseGPR = base.gpr();
2986             GPRReg argumentGPR = argument.gpr();
2987             
2988             flushRegisters();
2989             GPRResult result(this);
2990             callOperation(operationRegExpTest, result.gpr(), baseGPR, argumentGPR);
2991             
2992             // Must use jsValueResult because otherwise we screw up register
2993             // allocation, which thinks that this node has a result.
2994             booleanResult(result.gpr(), m_compileIndex);
2995             break;
2996         }
2997
2998         SpeculateCellOperand base(this, node.child1());
2999         SpeculateCellOperand argument(this, node.child2());
3000         GPRReg baseGPR = base.gpr();
3001         GPRReg argumentGPR = argument.gpr();
3002         
3003         flushRegisters();
3004         GPRResult2 resultTag(this);
3005         GPRResult resultPayload(this);
3006         callOperation(operationRegExpExec, resultTag.gpr(), resultPayload.gpr(), baseGPR, argumentGPR);
3007         
3008         jsValueResult(resultTag.gpr(), resultPayload.gpr(), m_compileIndex);
3009         break;
3010     }
3011         
3012     case RegExpTest: {
3013         SpeculateCellOperand base(this, node.child1());
3014         SpeculateCellOperand argument(this, node.child2());
3015         GPRReg baseGPR = base.gpr();
3016         GPRReg argumentGPR = argument.gpr();
3017         
3018         flushRegisters();
3019         GPRResult result(this);
3020         callOperation(operationRegExpTest, result.gpr(), baseGPR, argumentGPR);
3021         
3022         // If we add a DataFormatBool, we should use it here.
3023         booleanResult(result.gpr(), m_compileIndex);
3024         break;
3025     }
3026         
3027     case ArrayPush: {
3028         ASSERT(node.arrayMode().isJSArray());
3029         
3030         SpeculateCellOperand base(this, node.child1());
3031         JSValueOperand value(this, node.child2());
3032         GPRTemporary storageLength(this);
3033         
3034         GPRReg baseGPR = base.gpr();
3035         GPRReg valueTagGPR = value.tagGPR();
3036         GPRReg valuePayloadGPR = value.payloadGPR();
3037         GPRReg storageLengthGPR = storageLength.gpr();
3038         
3039         if (Heap::isWriteBarrierEnabled()) {
3040             GPRTemporary scratch(this);
3041             writeBarrier(baseGPR, valueTagGPR, node.child2(), WriteBarrierForPropertyAccess, scratch.gpr(), storageLengthGPR);
3042         }
3043
3044         StorageOperand storage(this, node.child3());
3045         GPRReg storageGPR = storage.gpr();
3046         
3047         switch (node.arrayMode().type()) {
3048         case Array::Contiguous: {
3049             m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
3050             MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
3051             m_jit.store32(valueTagGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
3052             m_jit.store32(valuePayloadGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
3053             m_jit.add32(TrustedImm32(1), storageLengthGPR);
3054             m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
3055             m_jit.move(TrustedImm32(JSValue::Int32Tag), storageGPR);
3056             
3057             addSlowPathGenerator(
3058                 slowPathCall(
3059                     slowPath, this, operationArrayPush,
3060                     JSValueRegs(storageGPR, storageLengthGPR),
3061                     valueTagGPR, valuePayloadGPR, baseGPR));
3062         
3063             jsValueResult(storageGPR, storageLengthGPR, m_compileIndex);
3064             break;
3065         }
3066             
3067         case Array::ArrayStorage: {
3068             m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
3069         
3070             // Refuse to handle bizarre lengths.
3071             speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::Above, storageLengthGPR, TrustedImm32(0x7ffffffe)));
3072         
3073             MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset()));
3074         
3075             m_jit.store32(valueTagGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
3076             m_jit.store32(valuePayloadGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
3077         
3078             m_jit.add32(TrustedImm32(1), storageLengthGPR);
3079             m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()));
3080             m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
3081             m_jit.move(TrustedImm32(JSValue::Int32Tag), storageGPR);
3082         
3083             addSlowPathGenerator(slowPathCall(slowPath, this, operationArrayPush, JSValueRegs(storageGPR, storageLengthGPR), valueTagGPR, valuePayloadGPR, baseGPR));
3084         
3085             jsValueResult(storageGPR, storageLengthGPR, m_compileIndex);
3086             break;
3087         }
3088             
3089         default:
3090             CRASH();
3091             break;
3092         }
3093         break;
3094     }
3095         
3096     case ArrayPop: {
3097         ASSERT(node.arrayMode().isJSArray());
3098         
3099         SpeculateCellOperand base(this, node.child1());
3100         StorageOperand storage(this, node.child2());
3101         GPRTemporary valueTag(this);
3102         GPRTemporary valuePayload(this);
3103         
3104         GPRReg baseGPR = base.gpr();
3105         GPRReg valueTagGPR = valueTag.gpr();
3106         GPRReg valuePayloadGPR = valuePayload.gpr();
3107         GPRReg storageGPR = storage.gpr();
3108         
3109         switch (node.arrayMode().type()) {
3110         case Array::Contiguous: {
3111             m_jit.load32(
3112                 MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), valuePayloadGPR);
3113             MacroAssembler::Jump undefinedCase =
3114                 m_jit.branchTest32(MacroAssembler::Zero, valuePayloadGPR);
3115             m_jit.sub32(TrustedImm32(1), valuePayloadGPR);
3116             m_jit.store32(
3117                 valuePayloadGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
3118             m_jit.load32(
3119                 MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)),
3120                 valueTagGPR);
3121             MacroAssembler::Jump slowCase = m_jit.branch32(MacroAssembler::Equal, valueTagGPR, TrustedImm32(JSValue::EmptyValueTag));
3122             m_jit.store32(
3123                 MacroAssembler::TrustedImm32(JSValue::EmptyValueTag),
3124                 MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
3125             m_jit.load32(
3126                 MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)),
3127                 valuePayloadGPR);
3128
3129             addSlowPathGenerator(
3130                 slowPathMove(
3131                     undefinedCase, this,
3132                     MacroAssembler::TrustedImm32(jsUndefined().tag()), valueTagGPR,
3133                     MacroAssembler::TrustedImm32(jsUndefined().payload()), valuePayloadGPR));
3134             addSlowPathGenerator(
3135                 slowPathCall(
3136                     slowCase, this, operationArrayPopAndRecoverLength,
3137                     JSValueRegs(valueTagGPR, valuePayloadGPR), baseGPR));
3138             
3139             jsValueResult(valueTagGPR, valuePayloadGPR, m_compileIndex);
3140             break;
3141         }
3142             
3143         case Array::ArrayStorage: {
3144             GPRTemporary storageLength(this);
3145             GPRReg storageLengthGPR = storageLength.gpr();
3146
3147             m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
3148         
3149             JITCompiler::JumpList setUndefinedCases;
3150             setUndefinedCases.append(m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR));
3151         
3152             m_jit.sub32(TrustedImm32(1), storageLengthGPR);
3153         
3154             MacroAssembler::Jump slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset()));
3155         
3156             m_jit.load32(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), valueTagGPR);
3157             m_jit.load32(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), valuePayloadGPR);
3158         
3159             m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()));
3160
3161             setUndefinedCases.append(m_jit.branch32(MacroAssembler::Equal, TrustedImm32(JSValue::EmptyValueTag), valueTagGPR));
3162         
3163             m_jit.store32(TrustedImm32(JSValue::EmptyValueTag), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
3164
3165             m_jit.sub32(TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
3166         
3167             addSlowPathGenerator(
3168                 slowPathMove(
3169                     setUndefinedCases, this,
3170                     MacroAssembler::TrustedImm32(jsUndefined().tag()), valueTagGPR,
3171                     MacroAssembler::TrustedImm32(jsUndefined().payload()), valuePayloadGPR));
3172         
3173             addSlowPathGenerator(
3174                 slowPathCall(
3175                     slowCase, this, operationArrayPop,
3176                     JSValueRegs(valueTagGPR, valuePayloadGPR), baseGPR));
3177
3178             jsValueResult(valueTagGPR, valuePayloadGPR, m_compileIndex);
3179             break;
3180         }
3181             
3182         default:
3183             CRASH();
3184             break;
3185         }
3186         break;
3187     }
3188
3189     case DFG::Jump: {
3190         BlockIndex taken = node.takenBlockIndex();
3191         jump(taken);
3192         noResult(m_compileIndex);
3193         break;
3194     }
3195
3196     case Branch:
3197         if (at(node.child1()).shouldSpeculateInteger()) {
3198             SpeculateIntegerOperand op(this, node.child1());
3199             
3200             BlockIndex taken = node.takenBlockIndex();
3201             BlockIndex notTaken = node.notTakenBlockIndex();
3202             
3203             MacroAssembler::ResultCondition condition = MacroAssembler::NonZero;
3204             
3205             if (taken == nextBlock()) {
3206                 condition = MacroAssembler::Zero;
3207                 BlockIndex tmp = taken;
3208                 taken = notTaken;
3209                 notTaken = tmp;
3210             }
3211             
3212             branchTest32(condition, op.gpr(), taken);
3213             jump(notTaken);
3214             
3215             noResult(m_compileIndex);
3216             break;
3217         }
3218         emitBranch(node);
3219         break;
3220
3221     case Return: {
3222         ASSERT(GPRInfo::callFrameRegister != GPRInfo::regT2);
3223         ASSERT(GPRInfo::regT1 != GPRInfo::returnValueGPR);
3224         ASSERT(GPRInfo::returnValueGPR != GPRInfo::callFrameRegister);
3225
3226 #if DFG_ENABLE(SUCCESS_STATS)
3227         static SamplingCounter counter("SpeculativeJIT");
3228         m_jit.emitCount(counter);
3229 #endif
3230
3231         // Return the result in returnValueGPR.
3232         JSValueOperand op1(this, node.child1());
3233         op1.fill();
3234         if (op1.isDouble())
3235             boxDouble(op1.fpr(), GPRInfo::returnValueGPR2, GPRInfo::returnValueGPR);
3236         else {
3237             if (op1.payloadGPR() == GPRInfo::returnValueGPR2 && op1.tagGPR() == GPRInfo::returnValueGPR)
3238                 m_jit.swap(GPRInfo::returnValueGPR, GPRInfo::returnValueGPR2);
3239             else if (op1.payloadGPR() == GPRInfo::returnValueGPR2) {
3240                 m_jit.move(op1.payloadGPR(), GPRInfo::returnValueGPR);
3241                 m_jit.move(op1.tagGPR(), GPRInfo::returnValueGPR2);
3242             } else {
3243                 m_jit.move(op1.tagGPR(), GPRInfo::returnValueGPR2);
3244                 m_jit.move(op1.payloadGPR(), GPRInfo::returnValueGPR);
3245             }
3246         }
3247
3248         // Grab the return address.
3249         m_jit.emitGetFromCallFrameHeaderPtr(JSStack::ReturnPC, GPRInfo::regT2);
3250         // Restore our caller's "r".
3251         m_jit.emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, GPRInfo::callFrameRegister);
3252         // Return.
3253         m_jit.restoreReturnAddressBeforeReturn(GPRInfo::regT2);
3254         m_jit.ret();
3255         
3256         noResult(m_compileIndex);
3257         break;
3258     }
3259         
3260     case Throw:
3261     case ThrowReferenceError: {
3262         // We expect that throw statements are rare and are intended to exit the code block
3263         // anyway, so we just OSR back to the old JIT for now.
3264         terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
3265         break;
3266     }
3267         
3268     case ToPrimitive: {
3269         if (at(node.child1()).shouldSpeculateInteger()) {
3270             // It's really profitable to speculate integer, since it's really cheap,
3271             // it means we don't have to do any real work, and we emit a lot less code.
3272             
3273             SpeculateIntegerOperand op1(this, node.child1());
3274             GPRTemporary result(this, op1);
3275             
3276             ASSERT(op1.format() == DataFormatInteger);
3277             m_jit.move(op1.gpr(), result.gpr());
3278             
3279             integerResult(result.gpr(), m_compileIndex);
3280             break;
3281         }
3282         
3283         // FIXME: Add string speculation here.
3284         
3285         JSValueOperand op1(this, node.child1());
3286         GPRTemporary resultTag(this, op1);
3287         GPRTemporary resultPayload(this, op1, false);
3288         
3289         GPRReg op1TagGPR = op1.tagGPR();
3290         GPRReg op1PayloadGPR = op1.payloadGPR();
3291         GPRReg resultTagGPR = resultTag.gpr();
3292         GPRReg resultPayloadGPR = resultPayload.gpr();
3293         
3294         op1.use();
3295         
3296         if (!(m_state.forNode(node.child1()).m_type & ~(SpecNumber | SpecBoolean))) {
3297             m_jit.move(op1TagGPR, resultTagGPR);
3298             m_jit.move(op1PayloadGPR, resultPayloadGPR);
3299         } else {
3300             MacroAssembler::Jump alreadyPrimitive = m_jit.branch32(MacroAssembler::NotEqual, op1TagGPR, TrustedImm32(JSValue::CellTag));
3301             MacroAssembler::Jump notPrimitive = m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1PayloadGPR, JSCell::structureOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()));
3302             
3303             alreadyPrimitive.link(&m_jit);
3304             m_jit.move(op1TagGPR, resultTagGPR);
3305             m_jit.move(op1PayloadGPR, resultPayloadGPR);
3306             
3307             addSlowPathGenerator(
3308                 slowPathCall(
3309                     notPrimitive, this, operationToPrimitive,
3310                     JSValueRegs(resultTagGPR, resultPayloadGPR), op1TagGPR, op1PayloadGPR));
3311         }
3312         
3313         jsValueResult(resultTagGPR, resultPayloadGPR, m_compileIndex, UseChildrenCalledExplicitly);
3314         break;
3315     }
3316         
3317     case StrCat: {
3318         size_t scratchSize = sizeof(EncodedJSValue) * node.numChildren();
3319         ScratchBuffer* scratchBuffer = m_jit.globalData()->scratchBufferForSize(scratchSize);
3320         EncodedJSValue* buffer = scratchBuffer ? static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) : 0;
3321         
3322         for (unsigned operandIdx = 0; operandIdx < node.numChildren(); ++operandIdx) {
3323             JSValueOperand operand(this, m_jit.graph().m_varArgChildren[node.firstChild() + operandIdx]);
3324             GPRReg opTagGPR = operand.tagGPR();
3325             GPRReg opPayloadGPR = operand.payloadGPR();
3326             operand.use();
3327             
3328             m_jit.store32(opTagGPR, reinterpret_cast<char*>(buffer + operandIdx) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
3329             m_jit.store32(opPayloadGPR, reinterpret_cast<char*>(buffer + operandIdx) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
3330         }
3331         
3332         flushRegisters();
3333
3334         if (scratchSize) {
3335             GPRTemporary scratch(this);
3336
3337             // Tell GC mark phase how much of the scratch buffer is active during call.
3338             m_jit.move(TrustedImmPtr(scratchBuffer->activeLengthPtr()), scratch.gpr());
3339             m_jit.storePtr(TrustedImmPtr(scratchSize), scratch.gpr());
3340         }
3341
3342         GPRResult resultPayload(this);
3343         GPRResult2 resultTag(this);
3344         
3345         callOperation(operationStrCat, resultTag.gpr(), resultPayload.gpr(), static_cast<void *>(buffer), node.numChildren());
3346
3347         if (scratchSize) {
3348             GPRTemporary scratch(this);
3349
3350             m_jit.move(TrustedImmPtr(scratchBuffer->activeLengthPtr()), scratch.gpr());
3351             m_jit.storePtr(TrustedImmPtr(0), scratch.gpr());
3352         }
3353
3354         // FIXME: make the callOperation above explicitly return a cell result, or jitAssert the tag is a cell tag.
3355         cellResult(resultPayload.gpr(), m_compileIndex, UseChildrenCalledExplicitly);
3356         break;
3357     }
3358
3359     case NewArray: {
3360         JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node.codeOrigin);
3361         if (!globalObject->isHavingABadTime()) {
3362             globalObject->havingABadTimeWatchpoint()->add(speculationWatchpoint());
3363             
3364             ASSERT(hasContiguous(globalObject->arrayStructure()->indexingType()));
3365             
3366             unsigned numElements = node.numChildren();
3367             
3368             GPRTemporary result(this);
3369             GPRTemporary storage(this);
3370             
3371             GPRReg resultGPR = result.gpr();
3372             GPRReg storageGPR = storage.gpr();
3373
3374             emitAllocateJSArray(globalObject->arrayStructure(), resultGPR, storageGPR, numElements);
3375             
3376             // At this point, one way or another, resultGPR and storageGPR have pointers to
3377             // the JSArray and the Butterfly, respectively.
3378             
3379             for (unsigned operandIdx = 0; operandIdx < node.numChildren(); ++operandIdx) {
3380                 JSValueOperand operand(this, m_jit.graph().m_varArgChildren[node.firstChild() + operandIdx]);
3381                 GPRReg opTagGPR = operand.tagGPR();
3382                 GPRReg opPayloadGPR = operand.payloadGPR();
3383                 m_jit.store32(opTagGPR, MacroAssembler::Address(storageGPR, sizeof(JSValue) * operandIdx + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
3384                 m_jit.store32(opPayloadGPR, MacroAssembler::Address(storageGPR, sizeof(JSValue) * operandIdx + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
3385             }
3386             
3387             // Yuck, we should *really* have a way of also returning the storageGPR. But
3388             // that's the least of what's wrong with this code. We really shouldn't be
3389             // allocating the array after having computed - and probably spilled to the
3390             // stack - all of the things that will go into the array. The solution to that
3391             // bigger problem will also likely fix the redundancy in reloading the storage
3392             // pointer that we currently have.
3393             
3394             cellResult(resultGPR, m_compileIndex);
3395             break;
3396         }
3397         
3398         if (!node.numChildren()) {
3399             flushRegisters();
3400             GPRResult result(this);
3401             callOperation(
3402                 operationNewEmptyArray, result.gpr(), globalObject->arrayStructure());
3403             cellResult(result.gpr(), m_compileIndex);
3404             break;
3405         }
3406         
3407         size_t scratchSize = sizeof(EncodedJSValue) * node.numChildren();
3408         ScratchBuffer* scratchBuffer = m_jit.globalData()->scratchBufferForSize(scratchSize);
3409         EncodedJSValue* buffer = scratchBuffer ? static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) : 0;
3410         
3411         for (unsigned operandIdx = 0; operandIdx < node.numChildren(); ++operandIdx) {
3412             JSValueOperand operand(this, m_jit.graph().m_varArgChildren[node.firstChild() + operandIdx]);
3413             GPRReg opTagGPR = operand.tagGPR();
3414             GPRReg opPayloadGPR = operand.payloadGPR();
3415             operand.use();
3416             
3417             m_jit.store32(opTagGPR, reinterpret_cast<char*>(buffer + operandIdx) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
3418             m_jit.store32(opPayloadGPR, reinterpret_cast<char*>(buffer + operandIdx) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
3419         }
3420         
3421         flushRegisters();
3422
3423         if (scratchSize) {
3424             GPRTemporary scratch(this);
3425
3426             // Tell GC mark phase how much of the scratch buffer is active during call.
3427             m_jit.move(TrustedImmPtr(scratchBuffer->activeLengthPtr()), scratch.gpr());
3428             m_jit.storePtr(TrustedImmPtr(scratchSize), scratch.gpr());
3429         }
3430
3431         GPRResult result(this);
3432         
3433         callOperation(
3434             operationNewArray, result.gpr(), globalObject->arrayStructure(),
3435             static_cast<void *>(buffer), node.numChildren());
3436
3437         if (scratchSize) {
3438             GPRTemporary scratch(this);
3439
3440             m_jit.move(TrustedImmPtr(scratchBuffer->activeLengthPtr()), scratch.gpr());
3441             m_jit.storePtr(TrustedImmPtr(0), scratch.gpr());
3442         }
3443
3444         cellResult(result.gpr(), m_compileIndex, UseChildrenCalledExplicitly);
3445         break;
3446     }
3447
3448     case NewArrayWithSize: {
3449         JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node.codeOrigin);
3450         if (!globalObject->isHavingABadTime()) {
3451             globalObject->havingABadTimeWatchpoint()->add(speculationWatchpoint());
3452             
3453             SpeculateStrictInt32Operand size(this, node.child1());
3454             GPRTemporary result(this);
3455             GPRTemporary storage(this);
3456             GPRTemporary scratch(this);
3457             
3458             GPRReg sizeGPR = size.gpr();
3459             GPRReg resultGPR = result.gpr();
3460             GPRReg storageGPR = storage.gpr();
3461             GPRReg scratchGPR = scratch.gpr();
3462             
3463             MacroAssembler::JumpList slowCases;
3464             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, sizeGPR, TrustedImm32(MIN_SPARSE_ARRAY_INDEX)));
3465             
3466             ASSERT((1 << 3) == sizeof(JSValue));
3467             m_jit.move(sizeGPR, scratchGPR);
3468             m_jit.lshift32(TrustedImm32(3), scratchGPR);
3469             m_jit.add32(TrustedImm32(sizeof(IndexingHeader)), scratchGPR, resultGPR);
3470             slowCases.append(
3471                 emitAllocateBasicStorage(resultGPR, storageGPR));
3472             m_jit.subPtr(scratchGPR, storageGPR);
3473             emitAllocateBasicJSObject<JSArray, MarkedBlock::None>(
3474                 TrustedImmPtr(globalObject->arrayStructure()), resultGPR, scratchGPR,
3475                 storageGPR, sizeof(JSArray), slowCases);
3476             
3477             m_jit.store32(sizeGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
3478             m_jit.store32(sizeGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
3479             
3480             addSlowPathGenerator(adoptPtr(
3481                 new CallArrayAllocatorWithVariableSizeSlowPathGenerator(
3482                     slowCases, this, operationNewArrayWithSize, resultGPR,
3483                     globalObject->arrayStructure(),
3484                     globalObject->arrayStructureWithArrayStorage(),
3485                     sizeGPR)));
3486             
3487             cellResult(resultGPR, m_compileIndex);
3488             break;
3489         }
3490         
3491         SpeculateStrictInt32Operand size(this, node.child1());
3492         GPRReg sizeGPR = size.gpr();
3493         flushRegisters();
3494         GPRResult result(this);
3495         callOperation(
3496             operationNewArrayWithSize, result.gpr(), globalObject->arrayStructure(), sizeGPR);
3497         cellResult(result.gpr(), m_compileIndex);
3498         break;
3499     }
3500         
3501     case NewArrayBuffer: {
3502         JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node.codeOrigin);
3503         if (!globalObject->isHavingABadTime()) {
3504             globalObject->havingABadTimeWatchpoint()->add(speculationWatchpoint());
3505             
3506             unsigned numElements = node.numConstants();
3507             
3508             GPRTemporary result(this);
3509             GPRTemporary storage(this);
3510             
3511             GPRReg resultGPR = result.gpr();
3512             GPRReg storageGPR = storage.gpr();
3513
3514             emitAllocateJSArray(globalObject->arrayStructure(), resultGPR, storageGPR, numElements);
3515             
3516             int32_t* data = bitwise_cast<int32_t*>(m_jit.codeBlock()->constantBuffer(node.startConstant()));
3517             for (unsigned index = 0; index < node.numConstants() * 2; ++index) {
3518                 m_jit.store32(
3519                     Imm32(data[index]), MacroAssembler::Address(storageGPR, sizeof(int32_t) * index));
3520             }
3521             
3522             cellResult(resultGPR, m_compileIndex);
3523             break;
3524         }
3525         
3526         flushRegisters();
3527         GPRResult result(this);
3528         
3529         callOperation(operationNewArrayBuffer, result.gpr(), globalObject->arrayStructure(), node.startConstant(), node.numConstants());
3530         
3531         cellResult(result.gpr(), m_compileIndex);
3532         break;
3533     }
3534         
3535     case NewRegexp: {
3536         flushRegisters();
3537         GPRResult resultPayload(this);
3538         GPRResult2 resultTag(this);
3539         
3540         callOperation(operationNewRegexp, resultTag.gpr(), resultPayload.gpr(), m_jit.codeBlock()->regexp(node.regexpIndex()));
3541         
3542         // FIXME: make the callOperation above explicitly return a cell result, or jitAssert the tag is a cell tag.
3543         cellResult(resultPayload.gpr(), m_compileIndex);
3544         break;
3545     }
3546         
3547     case ConvertThis: {
3548         if (isObjectSpeculation(m_state.forNode(node.child1()).m_type)) {
3549             SpeculateCellOperand thisValue(this, node.child1());
3550             GPRTemporary result(this, thisValue);
3551             m_jit.move(thisValue.gpr(), result.gpr());
3552             cellResult(result.gpr(), m_compileIndex);
3553             break;
3554         }
3555         
3556         if (isOtherSpeculation(at(node.child1()).prediction())) {
3557             JSValueOperand thisValue(this, node.child1());
3558             GPRTemporary scratch(this);
3559             
3560             GPRReg thisValueTagGPR = thisValue.tagGPR();
3561             GPRReg scratchGPR = scratch.gpr();
3562             
3563             COMPILE_ASSERT((JSValue::UndefinedTag | 1) == JSValue::NullTag, UndefinedTag_OR_1_EQUALS_NullTag);
3564             m_jit.move(thisValueTagGPR, scratchGPR);
3565             m_jit.or32(TrustedImm32(1), scratchGPR);
3566             // This is hard. It would be better to save the value, but we can't quite do it,
3567             // since this operation does not otherwise get the payload.
3568             speculationCheck(BadType, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, scratchGPR, TrustedImm32(JSValue::NullTag)));
3569             
3570             m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.globalThisObjectFor(node.codeOrigin)), scratchGPR);
3571             cellResult(scratchGPR, m_compileIndex);
3572             break;
3573         }
3574         
3575         if (isObjectSpeculation(at(node.child1()).prediction())) {
3576             SpeculateCellOperand thisValue(this, node.child1());
3577             GPRReg thisValueGPR = thisValue.gpr();
3578             
3579             if (!isObjectSpeculation(m_state.forNode(node.child1()).m_type))
3580                 speculationCheck(BadType, JSValueSource::unboxedCell(thisValueGPR), node.child1(), m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(thisValueGPR, JSCell::structureOffset()), JITCompiler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())));
3581             
3582             GPRTemporary result(this, thisValue);
3583             GPRReg resultGPR = result.gpr();
3584             m_jit.move(thisValueGPR, resultGPR);
3585             cellResult(resultGPR, m_compileIndex);
3586             break;
3587         }