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