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