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