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