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