9c655516f57ddfe439ec90e41d96d2c9048c6974
[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     BlockIndex taken = node.takenBlockIndex();
1666     BlockIndex notTaken = node.notTakenBlockIndex();
1667     
1668     if (at(node.child1()).shouldSpeculateFinalObjectOrOther()) {
1669         emitObjectOrOtherBranch(node.child1(), taken, notTaken, &JSFinalObject::s_info, !isFinalObjectOrOtherPrediction(m_state.forNode(node.child1()).m_type));
1670     } else if (at(node.child1()).shouldSpeculateArrayOrOther()) {
1671         emitObjectOrOtherBranch(node.child1(), taken, notTaken, &JSArray::s_info, !isArrayOrOtherPrediction(m_state.forNode(node.child1()).m_type));
1672     } else if (at(node.child1()).shouldSpeculateNumber()) {
1673         if (at(node.child1()).shouldSpeculateInteger()) {
1674             bool invert = false;
1675             
1676             if (taken == (m_block + 1)) {
1677                 invert = true;
1678                 BlockIndex tmp = taken;
1679                 taken = notTaken;
1680                 notTaken = tmp;
1681             }
1682
1683             SpeculateIntegerOperand value(this, node.child1());
1684             branchTest32(invert ? MacroAssembler::Zero : MacroAssembler::NonZero, value.gpr(), taken);
1685         } else {
1686             SpeculateDoubleOperand value(this, node.child1());
1687             FPRTemporary scratch(this);
1688             branchDoubleNonZero(value.fpr(), scratch.fpr(), taken);
1689         }
1690         
1691         jump(notTaken);
1692         
1693         noResult(m_compileIndex);
1694     } else {
1695         JSValueOperand value(this, node.child1());
1696         GPRReg valueGPR = value.gpr();
1697         
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 Int32ToDouble: {
1970         compileInt32ToDouble(node);
1971         break;
1972     }
1973
1974     case ValueAdd:
1975     case ArithAdd:
1976         compileAdd(node);
1977         break;
1978
1979     case ArithSub:
1980         compileArithSub(node);
1981         break;
1982
1983     case ArithNegate:
1984         compileArithNegate(node);
1985         break;
1986
1987     case ArithMul:
1988         compileArithMul(node);
1989         break;
1990
1991     case ArithDiv: {
1992         if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) {
1993             compileIntegerArithDivForX86(node);
1994             break;
1995         }
1996         
1997         SpeculateDoubleOperand op1(this, node.child1());
1998         SpeculateDoubleOperand op2(this, node.child2());
1999         FPRTemporary result(this, op1);
2000
2001         FPRReg reg1 = op1.fpr();
2002         FPRReg reg2 = op2.fpr();
2003         m_jit.divDouble(reg1, reg2, result.fpr());
2004
2005         doubleResult(result.fpr(), m_compileIndex);
2006         break;
2007     }
2008
2009     case ArithMod: {
2010         compileArithMod(node);
2011         break;
2012     }
2013
2014     case ArithAbs: {
2015         if (at(node.child1()).shouldSpeculateInteger() && node.canSpeculateInteger()) {
2016             SpeculateIntegerOperand op1(this, node.child1());
2017             GPRTemporary result(this);
2018             GPRTemporary scratch(this);
2019             
2020             m_jit.zeroExtend32ToPtr(op1.gpr(), result.gpr());
2021             m_jit.rshift32(result.gpr(), MacroAssembler::TrustedImm32(31), scratch.gpr());
2022             m_jit.add32(scratch.gpr(), result.gpr());
2023             m_jit.xor32(scratch.gpr(), result.gpr());
2024             speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::Equal, result.gpr(), MacroAssembler::TrustedImm32(1 << 31)));
2025             integerResult(result.gpr(), m_compileIndex);
2026             break;
2027         }
2028         
2029         SpeculateDoubleOperand op1(this, node.child1());
2030         FPRTemporary result(this);
2031         
2032         m_jit.absDouble(op1.fpr(), result.fpr());
2033         doubleResult(result.fpr(), m_compileIndex);
2034         break;
2035     }
2036         
2037     case ArithMin:
2038     case ArithMax: {
2039         if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) {
2040             SpeculateStrictInt32Operand op1(this, node.child1());
2041             SpeculateStrictInt32Operand op2(this, node.child2());
2042             GPRTemporary result(this, op1);
2043             
2044             MacroAssembler::Jump op1Less = m_jit.branch32(op == ArithMin ? MacroAssembler::LessThan : MacroAssembler::GreaterThan, op1.gpr(), op2.gpr());
2045             m_jit.move(op2.gpr(), result.gpr());
2046             if (op1.gpr() != result.gpr()) {
2047                 MacroAssembler::Jump done = m_jit.jump();
2048                 op1Less.link(&m_jit);
2049                 m_jit.move(op1.gpr(), result.gpr());
2050                 done.link(&m_jit);
2051             } else
2052                 op1Less.link(&m_jit);
2053             
2054             integerResult(result.gpr(), m_compileIndex);
2055             break;
2056         }
2057         
2058         SpeculateDoubleOperand op1(this, node.child1());
2059         SpeculateDoubleOperand op2(this, node.child2());
2060         FPRTemporary result(this, op1);
2061         
2062         MacroAssembler::JumpList done;
2063         
2064         MacroAssembler::Jump op1Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleLessThan : MacroAssembler::DoubleGreaterThan, op1.fpr(), op2.fpr());
2065         
2066         // op2 is eather the lesser one or one of then is NaN
2067         MacroAssembler::Jump op2Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleGreaterThanOrEqual : MacroAssembler::DoubleLessThanOrEqual, op1.fpr(), op2.fpr());
2068         
2069         // Unordered case. We don't know which of op1, op2 is NaN. Manufacture NaN by adding 
2070         // op1 + op2 and putting it into result.
2071         m_jit.addDouble(op1.fpr(), op2.fpr(), result.fpr());
2072         done.append(m_jit.jump());
2073         
2074         op2Less.link(&m_jit);
2075         m_jit.moveDouble(op2.fpr(), result.fpr());
2076         
2077         if (op1.fpr() != result.fpr()) {
2078             done.append(m_jit.jump());
2079             
2080             op1Less.link(&m_jit);
2081             m_jit.moveDouble(op1.fpr(), result.fpr());
2082         } else
2083             op1Less.link(&m_jit);
2084         
2085         done.link(&m_jit);
2086         
2087         doubleResult(result.fpr(), m_compileIndex);
2088         break;
2089     }
2090         
2091     case ArithSqrt: {
2092         SpeculateDoubleOperand op1(this, node.child1());
2093         FPRTemporary result(this, op1);
2094         
2095         m_jit.sqrtDouble(op1.fpr(), result.fpr());
2096         
2097         doubleResult(result.fpr(), m_compileIndex);
2098         break;
2099     }
2100
2101     case LogicalNot:
2102         compileLogicalNot(node);
2103         break;
2104
2105     case CompareLess:
2106         if (compare(node, JITCompiler::LessThan, JITCompiler::DoubleLessThan, operationCompareLess))
2107             return;
2108         break;
2109
2110     case CompareLessEq:
2111         if (compare(node, JITCompiler::LessThanOrEqual, JITCompiler::DoubleLessThanOrEqual, operationCompareLessEq))
2112             return;
2113         break;
2114
2115     case CompareGreater:
2116         if (compare(node, JITCompiler::GreaterThan, JITCompiler::DoubleGreaterThan, operationCompareGreater))
2117             return;
2118         break;
2119
2120     case CompareGreaterEq:
2121         if (compare(node, JITCompiler::GreaterThanOrEqual, JITCompiler::DoubleGreaterThanOrEqual, operationCompareGreaterEq))
2122             return;
2123         break;
2124
2125     case CompareEq:
2126         if (isNullConstant(node.child1().index())) {
2127             if (nonSpeculativeCompareNull(node, node.child2()))
2128                 return;
2129             break;
2130         }
2131         if (isNullConstant(node.child2().index())) {
2132             if (nonSpeculativeCompareNull(node, node.child1()))
2133                 return;
2134             break;
2135         }
2136         if (compare(node, JITCompiler::Equal, JITCompiler::DoubleEqual, operationCompareEq))
2137             return;
2138         break;
2139
2140     case CompareStrictEq:
2141         if (compileStrictEq(node))
2142             return;
2143         break;
2144
2145     case StringCharCodeAt: {
2146         compileGetCharCodeAt(node);
2147         break;
2148     }
2149
2150     case StringCharAt: {
2151         // Relies on StringCharAt node having same basic layout as GetByVal
2152         compileGetByValOnString(node);
2153         break;
2154     }
2155
2156     case GetByVal: {
2157         if (!node.prediction() || !at(node.child1()).prediction() || !at(node.child2()).prediction()) {
2158             terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
2159             break;
2160         }
2161         
2162         if (!at(node.child2()).shouldSpeculateInteger() || !isActionableArrayPrediction(at(node.child1()).prediction())) {
2163             JSValueOperand base(this, node.child1());
2164             JSValueOperand property(this, node.child2());
2165             GPRReg baseGPR = base.gpr();
2166             GPRReg propertyGPR = property.gpr();
2167             
2168             flushRegisters();
2169             GPRResult result(this);
2170             callOperation(operationGetByVal, result.gpr(), baseGPR, propertyGPR);
2171             
2172             jsValueResult(result.gpr(), m_compileIndex);
2173             break;
2174         }
2175         
2176         if (at(node.child1()).prediction() == PredictString) {
2177             compileGetByValOnString(node);
2178             if (!m_compileOkay)
2179                 return;
2180             break;
2181         }
2182
2183         if (at(node.child1()).shouldSpeculateByteArray()) {
2184             compileGetByValOnByteArray(node);
2185             if (!m_compileOkay)
2186                 return;
2187             break;            
2188         }
2189         
2190         if (at(node.child1()).shouldSpeculateInt8Array()) {
2191             compileGetByValOnIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), node, sizeof(int8_t), isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
2192             if (!m_compileOkay)
2193                 return;
2194             break;            
2195         }
2196         
2197         if (at(node.child1()).shouldSpeculateInt16Array()) {
2198             compileGetByValOnIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), node, sizeof(int16_t), isInt16ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
2199             if (!m_compileOkay)
2200                 return;
2201             break;            
2202         }
2203         
2204         if (at(node.child1()).shouldSpeculateInt32Array()) {
2205             compileGetByValOnIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), node, sizeof(int32_t), isInt32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
2206             if (!m_compileOkay)
2207                 return;
2208             break;            
2209         }
2210
2211         if (at(node.child1()).shouldSpeculateUint8Array()) {
2212             compileGetByValOnIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), node, sizeof(uint8_t), isUint8ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
2213             if (!m_compileOkay)
2214                 return;
2215             break;            
2216         }
2217
2218         if (at(node.child1()).shouldSpeculateUint8ClampedArray()) {
2219             compileGetByValOnIntTypedArray(m_jit.globalData()->uint8ClampedArrayDescriptor(), node, sizeof(uint8_t), isUint8ClampedArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
2220             if (!m_compileOkay)
2221                 return;
2222             break;
2223         }
2224
2225         if (at(node.child1()).shouldSpeculateUint16Array()) {
2226             compileGetByValOnIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), node, sizeof(uint16_t), isUint16ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
2227             if (!m_compileOkay)
2228                 return;
2229             break;            
2230         }
2231         
2232         if (at(node.child1()).shouldSpeculateUint32Array()) {
2233             compileGetByValOnIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), node, sizeof(uint32_t), isUint32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
2234             if (!m_compileOkay)
2235                 return;
2236             break;            
2237         }
2238         
2239         if (at(node.child1()).shouldSpeculateFloat32Array()) {
2240             compileGetByValOnFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), node, sizeof(float), isFloat32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
2241             if (!m_compileOkay)
2242                 return;
2243             break;            
2244         }
2245         
2246         if (at(node.child1()).shouldSpeculateFloat64Array()) {
2247             compileGetByValOnFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), node, sizeof(double), isFloat64ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
2248             if (!m_compileOkay)
2249                 return;
2250             break;            
2251         }
2252         
2253         ASSERT(at(node.child1()).shouldSpeculateArray());
2254
2255         SpeculateCellOperand base(this, node.child1());
2256         SpeculateStrictInt32Operand property(this, node.child2());
2257         StorageOperand storage(this, node.child3());
2258
2259         GPRReg baseReg = base.gpr();
2260         GPRReg propertyReg = property.gpr();
2261         GPRReg storageReg = storage.gpr();
2262         
2263         if (!m_compileOkay)
2264             return;
2265
2266         if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
2267             speculationCheck(BadType, JSValueRegs(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
2268         speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset())));
2269
2270         // FIXME: In cases where there are subsequent by_val accesses to the same base it might help to cache
2271         // the storage pointer - especially if there happens to be another register free right now. If we do so,
2272         // then we'll need to allocate a new temporary for result.
2273         GPRTemporary result(this);
2274         m_jit.loadPtr(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), result.gpr());
2275         speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::Zero, result.gpr()));
2276
2277         jsValueResult(result.gpr(), m_compileIndex);
2278         break;
2279     }
2280
2281     case PutByVal: {
2282         if (!at(node.child1()).prediction() || !at(node.child2()).prediction()) {
2283             terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
2284             break;
2285         }
2286         
2287         if (!at(node.child2()).shouldSpeculateInteger() || !isActionableMutableArrayPrediction(at(node.child1()).prediction())) {
2288             JSValueOperand arg1(this, node.child1());
2289             JSValueOperand arg2(this, node.child2());
2290             JSValueOperand arg3(this, node.child3());
2291             GPRReg arg1GPR = arg1.gpr();
2292             GPRReg arg2GPR = arg2.gpr();
2293             GPRReg arg3GPR = arg3.gpr();
2294             flushRegisters();
2295             
2296             callOperation(m_jit.strictModeFor(node.codeOrigin) ? operationPutByValStrict : operationPutByValNonStrict, arg1GPR, arg2GPR, arg3GPR);
2297             
2298             noResult(m_compileIndex);
2299             break;
2300         }
2301
2302         SpeculateCellOperand base(this, node.child1());
2303         SpeculateStrictInt32Operand property(this, node.child2());
2304         if (at(node.child1()).shouldSpeculateByteArray()) {
2305             compilePutByValForByteArray(base.gpr(), property.gpr(), node);
2306             break;
2307         }
2308         
2309         if (at(node.child1()).shouldSpeculateInt8Array()) {
2310             compilePutByValForIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int8_t), isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
2311             if (!m_compileOkay)
2312                 return;
2313             break;            
2314         }
2315         
2316         if (at(node.child1()).shouldSpeculateInt16Array()) {
2317             compilePutByValForIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int16_t), isInt16ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
2318             if (!m_compileOkay)
2319                 return;
2320             break;            
2321         }
2322
2323         if (at(node.child1()).shouldSpeculateInt32Array()) {
2324             compilePutByValForIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int32_t), isInt32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray);
2325             if (!m_compileOkay)
2326                 return;
2327             break;            
2328         }
2329         
2330         if (at(node.child1()).shouldSpeculateUint8Array()) {
2331             compilePutByValForIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), isUint8ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
2332             if (!m_compileOkay)
2333                 return;
2334             break;            
2335         }
2336
2337         if (at(node.child1()).shouldSpeculateUint8ClampedArray()) {
2338             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);
2339             break;
2340         }
2341
2342         if (at(node.child1()).shouldSpeculateUint16Array()) {
2343             compilePutByValForIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint16_t), isUint16ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
2344             if (!m_compileOkay)
2345                 return;
2346             break;            
2347         }
2348         
2349         if (at(node.child1()).shouldSpeculateUint32Array()) {
2350             compilePutByValForIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint32_t), isUint32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, UnsignedTypedArray);
2351             if (!m_compileOkay)
2352                 return;
2353             break;            
2354         }
2355         
2356         if (at(node.child1()).shouldSpeculateFloat32Array()) {
2357             compilePutByValForFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(float), isFloat32ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
2358             if (!m_compileOkay)
2359                 return;
2360             break;            
2361         }
2362         
2363         if (at(node.child1()).shouldSpeculateFloat64Array()) {
2364             compilePutByValForFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(double), isFloat64ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks);
2365             if (!m_compileOkay)
2366                 return;
2367             break;            
2368         }
2369             
2370         ASSERT(at(node.child1()).shouldSpeculateArray());
2371
2372         JSValueOperand value(this, node.child3());
2373         GPRTemporary scratch(this);
2374
2375         // Map base, property & value into registers, allocate a scratch register.
2376         GPRReg baseReg = base.gpr();
2377         GPRReg propertyReg = property.gpr();
2378         GPRReg valueReg = value.gpr();
2379         GPRReg scratchReg = scratch.gpr();
2380         
2381         if (!m_compileOkay)
2382             return;
2383         
2384         writeBarrier(baseReg, value.gpr(), node.child3(), WriteBarrierForPropertyAccess, scratchReg);
2385
2386         // Check that base is an array, and that property is contained within m_vector (< m_vectorLength).
2387         // If we have predicted the base to be type array, we can skip the check.
2388         if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
2389             speculationCheck(BadType, JSValueRegs(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
2390
2391         base.use();
2392         property.use();
2393         value.use();
2394         
2395         MacroAssembler::Jump withinArrayBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset()));
2396
2397         // Code to handle put beyond array bounds.
2398         silentSpillAllRegisters(scratchReg);
2399         callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict, baseReg, propertyReg, valueReg);
2400         silentFillAllRegisters(scratchReg);
2401         JITCompiler::Jump wasBeyondArrayBounds = m_jit.jump();
2402
2403         withinArrayBounds.link(&m_jit);
2404
2405         // Get the array storage.
2406         GPRReg storageReg = scratchReg;
2407         m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
2408
2409         // Check if we're writing to a hole; if so increment m_numValuesInVector.
2410         MacroAssembler::Jump notHoleValue = m_jit.branchTestPtr(MacroAssembler::NonZero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
2411         m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
2412
2413         // If we're writing to a hole we might be growing the array; 
2414         MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, OBJECT_OFFSETOF(ArrayStorage, m_length)));
2415         m_jit.add32(TrustedImm32(1), propertyReg);
2416         m_jit.store32(propertyReg, MacroAssembler::Address(storageReg, OBJECT_OFFSETOF(ArrayStorage, m_length)));
2417         m_jit.sub32(TrustedImm32(1), propertyReg);
2418
2419         lengthDoesNotNeedUpdate.link(&m_jit);
2420         notHoleValue.link(&m_jit);
2421
2422         // Store the value to the array.
2423         m_jit.storePtr(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
2424
2425         wasBeyondArrayBounds.link(&m_jit);
2426
2427         noResult(m_compileIndex, UseChildrenCalledExplicitly);
2428         break;
2429     }
2430
2431     case PutByValAlias: {
2432         if (!at(node.child1()).prediction() || !at(node.child2()).prediction()) {
2433             terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
2434             break;
2435         }
2436         
2437         ASSERT(isActionableMutableArrayPrediction(at(node.child1()).prediction()));
2438         ASSERT(at(node.child2()).shouldSpeculateInteger());
2439
2440         SpeculateCellOperand base(this, node.child1());
2441         SpeculateStrictInt32Operand property(this, node.child2());
2442         if (at(node.child1()).shouldSpeculateByteArray()) {
2443             compilePutByValForByteArray(base.gpr(), property.gpr(), node);
2444             break;
2445         }
2446
2447         if (at(node.child1()).shouldSpeculateInt8Array()) {
2448             compilePutByValForIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int8_t), NoTypedArraySpecCheck, SignedTypedArray);
2449             if (!m_compileOkay)
2450                 return;
2451             break;            
2452         }
2453         
2454         if (at(node.child1()).shouldSpeculateInt16Array()) {
2455             compilePutByValForIntTypedArray(m_jit.globalData()->int16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int16_t), NoTypedArraySpecCheck, SignedTypedArray);
2456             if (!m_compileOkay)
2457                 return;
2458             break;            
2459         }
2460         
2461         if (at(node.child1()).shouldSpeculateInt32Array()) {
2462             compilePutByValForIntTypedArray(m_jit.globalData()->int32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int32_t), NoTypedArraySpecCheck, SignedTypedArray);
2463             if (!m_compileOkay)
2464                 return;
2465             break;            
2466         }
2467         
2468         if (at(node.child1()).shouldSpeculateUint8Array()) {
2469             compilePutByValForIntTypedArray(m_jit.globalData()->uint8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), NoTypedArraySpecCheck, UnsignedTypedArray);
2470             if (!m_compileOkay)
2471                 return;
2472             break;            
2473         }
2474
2475         if (at(node.child1()).shouldSpeculateUint8ClampedArray()) {
2476             compilePutByValForIntTypedArray(m_jit.globalData()->uint8ClampedArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), NoTypedArraySpecCheck, UnsignedTypedArray, ClampRounding);
2477             if (!m_compileOkay)
2478                 return;
2479             break;
2480         }
2481
2482         if (at(node.child1()).shouldSpeculateUint16Array()) {
2483             compilePutByValForIntTypedArray(m_jit.globalData()->uint16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint16_t), NoTypedArraySpecCheck, UnsignedTypedArray);
2484             if (!m_compileOkay)
2485                 return;
2486             break;            
2487         }
2488         
2489         if (at(node.child1()).shouldSpeculateUint32Array()) {
2490             compilePutByValForIntTypedArray(m_jit.globalData()->uint32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint32_t), NoTypedArraySpecCheck, UnsignedTypedArray);
2491             if (!m_compileOkay)
2492                 return;
2493             break;            
2494         }
2495         
2496         if (at(node.child1()).shouldSpeculateFloat32Array()) {
2497             compilePutByValForFloatTypedArray(m_jit.globalData()->float32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(float), NoTypedArraySpecCheck);
2498             if (!m_compileOkay)
2499                 return;
2500             break;            
2501         }
2502         
2503         if (at(node.child1()).shouldSpeculateFloat64Array()) {
2504             compilePutByValForFloatTypedArray(m_jit.globalData()->float64ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(double), NoTypedArraySpecCheck);
2505             if (!m_compileOkay)
2506                 return;
2507             break;            
2508         }
2509         
2510         ASSERT(at(node.child1()).shouldSpeculateArray());
2511
2512         JSValueOperand value(this, node.child3());
2513         GPRTemporary scratch(this);
2514         
2515         GPRReg baseReg = base.gpr();
2516         GPRReg scratchReg = scratch.gpr();
2517
2518         writeBarrier(base.gpr(), value.gpr(), node.child3(), WriteBarrierForPropertyAccess, scratchReg);
2519
2520         // Get the array storage.
2521         GPRReg storageReg = scratchReg;
2522         m_jit.loadPtr(MacroAssembler::Address(baseReg, JSArray::storageOffset()), storageReg);
2523
2524         // Store the value to the array.
2525         GPRReg propertyReg = property.gpr();
2526         GPRReg valueReg = value.gpr();
2527         m_jit.storePtr(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
2528
2529         noResult(m_compileIndex);
2530         break;
2531     }
2532         
2533     case RegExpExec: {
2534         if (compileRegExpExec(node))
2535             return;
2536         if (!node.adjustedRefCount()) {
2537             SpeculateCellOperand base(this, node.child1());
2538             SpeculateCellOperand argument(this, node.child2());
2539             GPRReg baseGPR = base.gpr();
2540             GPRReg argumentGPR = argument.gpr();
2541             
2542             flushRegisters();
2543             GPRResult result(this);
2544             callOperation(operationRegExpTest, result.gpr(), baseGPR, argumentGPR);
2545             
2546             // Must use jsValueResult because otherwise we screw up register
2547             // allocation, which thinks that this node has a result.
2548             jsValueResult(result.gpr(), m_compileIndex);
2549             break;
2550         }
2551
2552         SpeculateCellOperand base(this, node.child1());
2553         SpeculateCellOperand argument(this, node.child2());
2554         GPRReg baseGPR = base.gpr();
2555         GPRReg argumentGPR = argument.gpr();
2556         
2557         flushRegisters();
2558         GPRResult result(this);
2559         callOperation(operationRegExpExec, result.gpr(), baseGPR, argumentGPR);
2560         
2561         jsValueResult(result.gpr(), m_compileIndex);
2562         break;
2563     }
2564
2565     case RegExpTest: {
2566         SpeculateCellOperand base(this, node.child1());
2567         SpeculateCellOperand argument(this, node.child2());
2568         GPRReg baseGPR = base.gpr();
2569         GPRReg argumentGPR = argument.gpr();
2570         
2571         flushRegisters();
2572         GPRResult result(this);
2573         callOperation(operationRegExpTest, result.gpr(), baseGPR, argumentGPR);
2574         
2575         // If we add a DataFormatBool, we should use it here.
2576         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
2577         jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
2578         break;
2579     }
2580         
2581     case ArrayPush: {
2582         SpeculateCellOperand base(this, node.child1());
2583         JSValueOperand value(this, node.child2());
2584         GPRTemporary storage(this);
2585         GPRTemporary storageLength(this);
2586         
2587         GPRReg baseGPR = base.gpr();
2588         GPRReg valueGPR = value.gpr();
2589         GPRReg storageGPR = storage.gpr();
2590         GPRReg storageLengthGPR = storageLength.gpr();
2591         
2592         writeBarrier(baseGPR, valueGPR, node.child2(), WriteBarrierForPropertyAccess, storageGPR, storageLengthGPR);
2593
2594         if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
2595             speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
2596         
2597         m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);
2598         m_jit.load32(MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), storageLengthGPR);
2599         
2600         // Refuse to handle bizarre lengths.
2601         speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::Above, storageLengthGPR, TrustedImm32(0x7ffffffe)));
2602         
2603         MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(baseGPR, JSArray::vectorLengthOffset()));
2604         
2605         m_jit.storePtr(valueGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
2606         
2607         m_jit.add32(TrustedImm32(1), storageLengthGPR);
2608         m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)));
2609         m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
2610         m_jit.orPtr(GPRInfo::tagTypeNumberRegister, storageLengthGPR);
2611         
2612         MacroAssembler::Jump done = m_jit.jump();
2613         
2614         slowPath.link(&m_jit);
2615         
2616         silentSpillAllRegisters(storageLengthGPR);
2617         callOperation(operationArrayPush, storageLengthGPR, valueGPR, baseGPR);
2618         silentFillAllRegisters(storageLengthGPR);
2619         
2620         done.link(&m_jit);
2621         
2622         jsValueResult(storageLengthGPR, m_compileIndex);
2623         break;
2624     }
2625         
2626     case ArrayPop: {
2627         SpeculateCellOperand base(this, node.child1());
2628         GPRTemporary value(this);
2629         GPRTemporary storage(this);
2630         GPRTemporary storageLength(this);
2631         
2632         GPRReg baseGPR = base.gpr();
2633         GPRReg valueGPR = value.gpr();
2634         GPRReg storageGPR = storage.gpr();
2635         GPRReg storageLengthGPR = storageLength.gpr();
2636         
2637         if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
2638             speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
2639         
2640         m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), storageGPR);
2641         m_jit.load32(MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), storageLengthGPR);
2642         
2643         MacroAssembler::Jump emptyArrayCase = m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR);
2644         
2645         m_jit.sub32(TrustedImm32(1), storageLengthGPR);
2646         
2647         MacroAssembler::Jump slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(baseGPR, JSArray::vectorLengthOffset()));
2648         
2649         m_jit.loadPtr(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), valueGPR);
2650         
2651         m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)));
2652
2653         MacroAssembler::Jump holeCase = m_jit.branchTestPtr(MacroAssembler::Zero, valueGPR);
2654         
2655         m_jit.storePtr(MacroAssembler::TrustedImmPtr(0), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::ScalePtr, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
2656         m_jit.sub32(MacroAssembler::TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
2657         
2658         MacroAssembler::JumpList done;
2659         
2660         done.append(m_jit.jump());
2661         
2662         holeCase.link(&m_jit);
2663         emptyArrayCase.link(&m_jit);
2664         m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsUndefined())), valueGPR);
2665         done.append(m_jit.jump());
2666         
2667         slowCase.link(&m_jit);
2668         
2669         silentSpillAllRegisters(valueGPR);
2670         callOperation(operationArrayPop, valueGPR, baseGPR);
2671         silentFillAllRegisters(valueGPR);
2672         
2673         done.link(&m_jit);
2674         
2675         jsValueResult(valueGPR, m_compileIndex);
2676         break;
2677     }
2678
2679     case DFG::Jump: {
2680         BlockIndex taken = node.takenBlockIndex();
2681         jump(taken);
2682         noResult(m_compileIndex);
2683         break;
2684     }
2685
2686     case Branch:
2687         if (isStrictInt32(node.child1().index()) || at(node.child1()).shouldSpeculateInteger()) {
2688             SpeculateIntegerOperand op(this, node.child1());
2689             
2690             BlockIndex taken = node.takenBlockIndex();
2691             BlockIndex notTaken = node.notTakenBlockIndex();
2692             
2693             MacroAssembler::ResultCondition condition = MacroAssembler::NonZero;
2694             
2695             if (taken == (m_block + 1)) {
2696                 condition = MacroAssembler::Zero;
2697                 BlockIndex tmp = taken;
2698                 taken = notTaken;
2699                 notTaken = tmp;
2700             }
2701             
2702             branchTest32(condition, op.gpr(), taken);
2703             jump(notTaken);
2704             
2705             noResult(m_compileIndex);
2706             break;
2707         }
2708         emitBranch(node);
2709         break;
2710
2711     case Return: {
2712         ASSERT(GPRInfo::callFrameRegister != GPRInfo::regT1);
2713         ASSERT(GPRInfo::regT1 != GPRInfo::returnValueGPR);
2714         ASSERT(GPRInfo::returnValueGPR != GPRInfo::callFrameRegister);
2715
2716 #if DFG_ENABLE(SUCCESS_STATS)
2717         static SamplingCounter counter("SpeculativeJIT");
2718         m_jit.emitCount(counter);
2719 #endif
2720
2721         // Return the result in returnValueGPR.
2722         JSValueOperand op1(this, node.child1());
2723         m_jit.move(op1.gpr(), GPRInfo::returnValueGPR);
2724
2725         // Grab the return address.
2726         m_jit.emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, GPRInfo::regT1);
2727         // Restore our caller's "r".
2728         m_jit.emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, GPRInfo::callFrameRegister);
2729         // Return.
2730         m_jit.restoreReturnAddressBeforeReturn(GPRInfo::regT1);
2731         m_jit.ret();
2732         
2733         noResult(m_compileIndex);
2734         break;
2735     }
2736         
2737     case Throw:
2738     case ThrowReferenceError: {
2739         // We expect that throw statements are rare and are intended to exit the code block
2740         // anyway, so we just OSR back to the old JIT for now.
2741         terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
2742         break;
2743     }
2744         
2745     case ToPrimitive: {
2746         if (at(node.child1()).shouldSpeculateInteger()) {
2747             // It's really profitable to speculate integer, since it's really cheap,
2748             // it means we don't have to do any real work, and we emit a lot less code.
2749             
2750             SpeculateIntegerOperand op1(this, node.child1());
2751             GPRTemporary result(this, op1);
2752             
2753             m_jit.move(op1.gpr(), result.gpr());
2754             if (op1.format() == DataFormatInteger)
2755                 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, result.gpr());
2756             
2757             jsValueResult(result.gpr(), m_compileIndex);
2758             break;
2759         }
2760         
2761         // FIXME: Add string speculation here.
2762         
2763         JSValueOperand op1(this, node.child1());
2764         GPRTemporary result(this, op1);
2765         
2766         GPRReg op1GPR = op1.gpr();
2767         GPRReg resultGPR = result.gpr();
2768         
2769         op1.use();
2770         
2771         if (!(m_state.forNode(node.child1()).m_type & ~(PredictNumber | PredictBoolean)))
2772             m_jit.move(op1GPR, resultGPR);
2773         else {
2774             MacroAssembler::JumpList alreadyPrimitive;
2775             
2776             alreadyPrimitive.append(m_jit.branchTestPtr(MacroAssembler::NonZero, op1GPR, GPRInfo::tagMaskRegister));
2777             alreadyPrimitive.append(m_jit.branchPtr(MacroAssembler::Equal, MacroAssembler::Address(op1GPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSString::s_info)));
2778             
2779             silentSpillAllRegisters(resultGPR);
2780             callOperation(operationToPrimitive, resultGPR, op1GPR);
2781             silentFillAllRegisters(resultGPR);
2782             
2783             MacroAssembler::Jump done = m_jit.jump();
2784             
2785             alreadyPrimitive.link(&m_jit);
2786             m_jit.move(op1GPR, resultGPR);
2787             
2788             done.link(&m_jit);
2789         }
2790         
2791         jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
2792         break;
2793     }
2794         
2795     case StrCat:
2796     case NewArray: {
2797         // We really don't want to grow the register file just to do a StrCat or NewArray.
2798         // Say we have 50 functions on the stack that all have a StrCat in them that has
2799         // upwards of 10 operands. In the DFG this would mean that each one gets
2800         // some random virtual register, and then to do the StrCat we'd need a second
2801         // span of 10 operands just to have somewhere to copy the 10 operands to, where
2802         // they'd be contiguous and we could easily tell the C code how to find them.
2803         // Ugly! So instead we use the scratchBuffer infrastructure in JSGlobalData. That
2804         // way, those 50 functions will share the same scratchBuffer for offloading their
2805         // StrCat operands. It's about as good as we can do, unless we start doing
2806         // virtual register coalescing to ensure that operands to StrCat get spilled
2807         // in exactly the place where StrCat wants them, or else have the StrCat
2808         // refer to those operands' SetLocal instructions to force them to spill in
2809         // the right place. Basically, any way you cut it, the current approach
2810         // probably has the best balance of performance and sensibility in the sense
2811         // that it does not increase the complexity of the DFG JIT just to make StrCat
2812         // fast and pretty.
2813         
2814         EncodedJSValue* buffer = static_cast<EncodedJSValue*>(m_jit.globalData()->scratchBufferForSize(sizeof(EncodedJSValue) * node.numChildren()));
2815         
2816         for (unsigned operandIdx = 0; operandIdx < node.numChildren(); ++operandIdx) {
2817             JSValueOperand operand(this, m_jit.graph().m_varArgChildren[node.firstChild() + operandIdx]);
2818             GPRReg opGPR = operand.gpr();
2819             operand.use();
2820             
2821             m_jit.storePtr(opGPR, buffer + operandIdx);
2822         }
2823         
2824         flushRegisters();
2825         
2826         GPRResult result(this);
2827         
2828         callOperation(op == StrCat ? operationStrCat : operationNewArray, result.gpr(), buffer, node.numChildren());
2829         
2830         cellResult(result.gpr(), m_compileIndex, UseChildrenCalledExplicitly);
2831         break;
2832     }
2833         
2834     case NewArrayBuffer: {
2835         flushRegisters();
2836         GPRResult result(this);
2837         
2838         callOperation(operationNewArrayBuffer, result.gpr(), node.startConstant(), node.numConstants());
2839         
2840         cellResult(result.gpr(), m_compileIndex);
2841         break;
2842     }
2843         
2844     case NewRegexp: {
2845         flushRegisters();
2846         GPRResult result(this);
2847         
2848         callOperation(operationNewRegexp, result.gpr(), m_jit.codeBlock()->regexp(node.regexpIndex()));
2849         
2850         cellResult(result.gpr(), m_compileIndex);
2851         break;
2852     }
2853         
2854     case ConvertThis: {
2855         if (isObjectPrediction(m_state.forNode(node.child1()).m_type)) {
2856             SpeculateCellOperand thisValue(this, node.child1());
2857             GPRTemporary result(this, thisValue);
2858             m_jit.move(thisValue.gpr(), result.gpr());
2859             cellResult(result.gpr(), m_compileIndex);
2860             break;
2861         }
2862         
2863         if (isOtherPrediction(at(node.child1()).prediction())) {
2864             JSValueOperand thisValue(this, node.child1());
2865             GPRTemporary scratch(this, thisValue);
2866             GPRReg thisValueGPR = thisValue.gpr();
2867             GPRReg scratchGPR = scratch.gpr();
2868             
2869             if (!isOtherPrediction(m_state.forNode(node.child1()).m_type)) {
2870                 m_jit.move(thisValueGPR, scratchGPR);
2871                 m_jit.andPtr(MacroAssembler::TrustedImm32(~TagBitUndefined), scratchGPR);
2872                 speculationCheck(BadType, JSValueRegs(thisValueGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, scratchGPR, MacroAssembler::TrustedImmPtr(reinterpret_cast<void*>(ValueNull))));
2873             }
2874             
2875             m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.globalThisObjectFor(node.codeOrigin)), scratchGPR);
2876             cellResult(scratchGPR, m_compileIndex);
2877             break;
2878         }
2879         
2880         if (isObjectPrediction(at(node.child1()).prediction())) {
2881             SpeculateCellOperand thisValue(this, node.child1());
2882             GPRTemporary result(this, thisValue);
2883             GPRReg thisValueGPR = thisValue.gpr();
2884             GPRReg resultGPR = result.gpr();
2885             
2886             if (!isObjectPrediction(m_state.forNode(node.child1()).m_type))
2887                 speculationCheck(BadType, JSValueRegs(thisValueGPR), node.child1(), m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(thisValueGPR, JSCell::classInfoOffset()), JITCompiler::TrustedImmPtr(&JSString::s_info)));
2888             
2889             m_jit.move(thisValueGPR, resultGPR);
2890             
2891             cellResult(resultGPR, m_compileIndex);
2892             break;
2893         }
2894         
2895         JSValueOperand thisValue(this, node.child1());
2896         GPRReg thisValueGPR = thisValue.gpr();
2897         
2898         flushRegisters();
2899         
2900         GPRResult result(this);
2901         callOperation(operationConvertThis, result.gpr(), thisValueGPR);
2902         
2903         cellResult(result.gpr(), m_compileIndex);
2904         break;
2905     }
2906
2907     case CreateThis: {
2908         // Note that there is not so much profit to speculate here. The only things we
2909         // speculate on are (1) that it's a cell, since that eliminates cell checks
2910         // later if the proto is reused, and (2) if we have a FinalObject prediction
2911         // then we speculate because we want to get recompiled if it isn't (since
2912         // otherwise we'd start taking slow path a lot).
2913         
2914         SpeculateCellOperand proto(this, node.child1());
2915         GPRTemporary result(this);
2916         GPRTemporary scratch(this);
2917         
2918         GPRReg protoGPR = proto.gpr();
2919         GPRReg resultGPR = result.gpr();
2920         GPRReg scratchGPR = scratch.gpr();
2921         
2922         proto.use();
2923         
2924         MacroAssembler::JumpList slowPath;
2925         
2926         // Need to verify that the prototype is an object. If we have reason to believe
2927         // that it's a FinalObject then we speculate on that directly. Otherwise we
2928         // do the slow (structure-based) check.
2929         if (at(node.child1()).shouldSpeculateFinalObject()) {
2930             if (!isFinalObjectPrediction(m_state.forNode(node.child1()).m_type))
2931                 speculationCheck(BadType, JSValueRegs(protoGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(protoGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSFinalObject::s_info)));
2932         } else {
2933             m_jit.loadPtr(MacroAssembler::Address(protoGPR, JSCell::structureOffset()), scratchGPR);
2934             slowPath.append(m_jit.branch8(MacroAssembler::Below, MacroAssembler::Address(scratchGPR, Structure::typeInfoTypeOffset()), MacroAssembler::TrustedImm32(ObjectType)));
2935         }
2936         
2937         // Load the inheritorID (the Structure that objects who have protoGPR as the prototype
2938         // use to refer to that prototype). If the inheritorID is not set, go to slow path.
2939         m_jit.loadPtr(MacroAssembler::Address(protoGPR, JSObject::offsetOfInheritorID()), scratchGPR);
2940         slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, scratchGPR));
2941         
2942         emitAllocateJSFinalObject(scratchGPR, resultGPR, scratchGPR, slowPath);
2943         
2944         MacroAssembler::Jump done = m_jit.jump();
2945         
2946         slowPath.link(&m_jit);
2947         
2948         silentSpillAllRegisters(resultGPR);
2949         if (node.codeOrigin.inlineCallFrame)
2950             callOperation(operationCreateThisInlined, resultGPR, protoGPR, node.codeOrigin.inlineCallFrame->callee.get());
2951         else
2952             callOperation(operationCreateThis, resultGPR, protoGPR);
2953         silentFillAllRegisters(resultGPR);
2954         
2955         done.link(&m_jit);
2956         
2957         cellResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
2958         break;
2959     }
2960
2961     case NewObject: {
2962         GPRTemporary result(this);
2963         GPRTemporary scratch(this);
2964         
2965         GPRReg resultGPR = result.gpr();
2966         GPRReg scratchGPR = scratch.gpr();
2967         
2968         MacroAssembler::JumpList slowPath;
2969         
2970         emitAllocateJSFinalObject(MacroAssembler::TrustedImmPtr(m_jit.globalObjectFor(node.codeOrigin)->emptyObjectStructure()), resultGPR, scratchGPR, slowPath);
2971         
2972         MacroAssembler::Jump done = m_jit.jump();
2973         
2974         slowPath.link(&m_jit);
2975         
2976         silentSpillAllRegisters(resultGPR);
2977         callOperation(operationNewObject, resultGPR);
2978         silentFillAllRegisters(resultGPR);
2979         
2980         done.link(&m_jit);
2981         
2982         cellResult(resultGPR, m_compileIndex);
2983         break;
2984     }
2985
2986     case GetCallee: {
2987         GPRTemporary result(this);
2988         m_jit.loadPtr(JITCompiler::addressFor(static_cast<VirtualRegister>(RegisterFile::Callee)), result.gpr());
2989         cellResult(result.gpr(), m_compileIndex);
2990         break;
2991     }
2992
2993     case GetScopeChain: {
2994         GPRTemporary result(this);
2995         GPRReg resultGPR = result.gpr();
2996
2997         m_jit.loadPtr(JITCompiler::addressFor(static_cast<VirtualRegister>(RegisterFile::ScopeChain)), resultGPR);
2998         bool checkTopLevel = m_jit.codeBlock()->codeType() == FunctionCode && m_jit.codeBlock()->needsFullScopeChain();
2999         int skip = node.scopeChainDepth();
3000         ASSERT(skip || !checkTopLevel);
3001         if (checkTopLevel && skip--) {
3002             JITCompiler::Jump activationNotCreated;
3003             if (checkTopLevel)
3004                 activationNotCreated = m_jit.branchTestPtr(JITCompiler::Zero, JITCompiler::addressFor(static_cast<VirtualRegister>(m_jit.codeBlock()->activationRegister())));
3005             m_jit.loadPtr(JITCompiler::Address(resultGPR, OBJECT_OFFSETOF(ScopeChainNode, next)), resultGPR);
3006             activationNotCreated.link(&m_jit);
3007         }
3008         while (skip--)
3009             m_jit.loadPtr(JITCompiler::Address(resultGPR, OBJECT_OFFSETOF(ScopeChainNode, next)), resultGPR);
3010         
3011         m_jit.loadPtr(JITCompiler::Address(resultGPR, OBJECT_OFFSETOF(ScopeChainNode, object)), resultGPR);
3012
3013         cellResult(resultGPR, m_compileIndex);
3014         break;
3015     }
3016     case GetScopedVar: {
3017         SpeculateCellOperand scopeChain(this, node.child1());
3018         GPRTemporary result(this);
3019         GPRReg resultGPR = result.gpr();
3020         m_jit.loadPtr(JITCompiler::Address(scopeChain.gpr(), JSVariableObject::offsetOfRegisters()), resultGPR);
3021         m_jit.loadPtr(JITCompiler::Address(resultGPR, node.varNumber() * sizeof(Register)), resultGPR);
3022         jsValueResult(resultGPR, m_compileIndex);
3023         break;
3024     }
3025     case PutScopedVar: {
3026         SpeculateCellOperand scopeChain(this, node.child1());
3027         GPRTemporary scratchRegister(this);
3028         GPRReg scratchGPR = scratchRegister.gpr();
3029         m_jit.loadPtr(JITCompiler::Address(scopeChain.gpr(), JSVariableObject::offsetOfRegisters()), scratchGPR);
3030         JSValueOperand value(this, node.child2());
3031         m_jit.storePtr(value.gpr(), JITCompiler::Address(scratchGPR, node.varNumber() * sizeof(Register)));
3032         writeBarrier(scopeChain.gpr(), value.gpr(), node.child2(), WriteBarrierForVariableAccess, scratchGPR);
3033         noResult(m_compileIndex);
3034         break;
3035     }
3036     case GetById: {
3037         if (!node.prediction()) {
3038             terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
3039             break;
3040         }
3041         
3042         if (isCellPrediction(at(node.child1()).prediction())) {
3043             SpeculateCellOperand base(this, node.child1());
3044             GPRTemporary result(this, base);
3045             
3046             GPRReg baseGPR = base.gpr();
3047             GPRReg resultGPR = result.gpr();
3048             GPRReg scratchGPR;
3049             
3050             if (resultGPR == baseGPR)
3051                 scratchGPR = tryAllocate();
3052             else
3053                 scratchGPR = resultGPR;
3054             
3055             base.use();
3056             
3057             cachedGetById(node.codeOrigin, baseGPR, resultGPR, scratchGPR, node.identifierNumber());
3058             
3059             jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
3060             break;
3061         }
3062         
3063         JSValueOperand base(this, node.child1());
3064         GPRTemporary result(this, base);
3065         
3066         GPRReg baseGPR = base.gpr();
3067         GPRReg resultGPR = result.gpr();
3068         GPRReg scratchGPR;
3069         
3070         if (resultGPR == baseGPR)
3071             scratchGPR = tryAllocate();
3072         else
3073             scratchGPR = resultGPR;
3074         
3075         base.use();
3076         
3077         JITCompiler::Jump notCell = m_jit.branchTestPtr(JITCompiler::NonZero, baseGPR, GPRInfo::tagMaskRegister);
3078         
3079         cachedGetById(node.codeOrigin, baseGPR, resultGPR, scratchGPR, node.identifierNumber(), notCell);
3080         
3081         jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
3082         
3083         break;
3084     }
3085
3086     case GetByIdFlush: {
3087         if (!node.prediction()) {
3088             terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
3089             break;
3090         }
3091         
3092         if (isCellPrediction(at(node.child1()).prediction())) {
3093             SpeculateCellOperand base(this, node.child1());
3094             GPRReg baseGPR = base.gpr();
3095
3096             GPRResult result(this);
3097             
3098             GPRReg resultGPR = result.gpr();
3099             
3100             GPRReg scratchGPR = selectScratchGPR(baseGPR, resultGPR);
3101             
3102             base.use();
3103             
3104             flushRegisters();
3105             
3106             cachedGetById(node.codeOrigin, baseGPR, resultGPR, scratchGPR, node.identifierNumber(), JITCompiler::Jump(), DontSpill);
3107             
3108             jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
3109             break;
3110         }
3111         
3112         JSValueOperand base(this, node.child1());
3113         GPRReg baseGPR = base.gpr();
3114
3115         GPRResult result(this);
3116         GPRReg resultGPR = result.gpr();
3117         
3118         GPRReg scratchGPR = selectScratchGPR(baseGPR, resultGPR);
3119         
3120         base.use();
3121         flushRegisters();
3122         
3123         JITCompiler::Jump notCell = m_jit.branchTestPtr(JITCompiler::NonZero, baseGPR, GPRInfo::tagMaskRegister);
3124         
3125         cachedGetById(node.codeOrigin, baseGPR, resultGPR, scratchGPR, node.identifierNumber(), notCell, DontSpill);
3126         
3127         jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);
3128         
3129         break;
3130     }
3131
3132     case GetArrayLength: {
3133         SpeculateCellOperand base(this, node.child1());
3134         GPRTemporary result(this);
3135         
3136         GPRReg baseGPR = base.gpr();
3137         GPRReg resultGPR = result.gpr();
3138         
3139         if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
3140             speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info)));
3141         
3142         m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArray::storageOffset()), resultGPR);
3143         m_jit.load32(MacroAssembler::Address(resultGPR, OBJECT_OFFSETOF(ArrayStorage, m_length)), resultGPR);
3144         
3145         speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, resultGPR, MacroAssembler::TrustedImm32(0)));
3146         
3147         integerResult(resultGPR, m_compileIndex);
3148         break;
3149     }
3150
3151     case GetStringLength: {
3152         SpeculateCellOperand base(this, node.child1());
3153         GPRTemporary result(this);
3154         
3155         GPRReg baseGPR = base.gpr();
3156         GPRReg resultGPR = result.gpr();
3157         
3158         if (!isStringPrediction(m_state.forNode(node.child1()).m_type))
3159             speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSString::s_info)));
3160         
3161         m_jit.load32(MacroAssembler::Address(baseGPR, JSString::offsetOfLength()), resultGPR);
3162
3163         integerResult(resultGPR, m_compileIndex);
3164         break;
3165     }
3166
3167     case GetByteArrayLength: {
3168         SpeculateCellOperand base(this, node.child1());
3169         GPRTemporary result(this);
3170         
3171         GPRReg baseGPR = base.gpr();
3172         GPRReg resultGPR = result.gpr();
3173         
3174         if (!isByteArrayPrediction(m_state.forNode(node.child1()).m_type))
3175             speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info)));
3176         
3177         m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSByteArray::offsetOfStorage()), resultGPR);
3178         m_jit.load32(MacroAssembler::Address(resultGPR, ByteArray::offsetOfSize()), resultGPR);
3179
3180         integerResult(resultGPR, m_compileIndex);
3181         break;
3182     }
3183     case GetInt8ArrayLength: {
3184         compileGetTypedArrayLength(m_jit.globalData()->int8ArrayDescriptor(), node, !isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type));
3185         break;
3186     }
3187     case GetInt16ArrayLength: {
3188         compileGetTypedArrayLength(m_jit.globalData()->int16ArrayDescriptor(), node, !isInt16ArrayPrediction(m_state.forNode(node.child1()).m_type));
3189         break;
3190     }
3191     case GetInt32ArrayLength: {
3192         compileGetTypedArrayLength(m_jit.globalData()->int32ArrayDescriptor(), node, !isInt32ArrayPrediction(m_state.forNode(node.child1()).m_type));
3193         break;
3194     }
3195     case GetUint8ArrayLength: {
3196         compileGetTypedArrayLength(m_jit.globalData()->uint8ArrayDescriptor(), node, !isUint8ArrayPrediction(m_state.forNode(node.child1()).m_type));
3197         break;
3198     }
3199     case GetUint8ClampedArrayLength: {
3200         compileGetTypedArrayLength(m_jit.globalData()->uint8ClampedArrayDescriptor(), node, !isUint8ClampedArrayPrediction(m_state.forNode(node.child1()).m_type));
3201         break;
3202     }
3203     case GetUint16ArrayLength: {
3204         compileGetTypedArrayLength(m_jit.globalData()->uint16ArrayDescriptor(), node, !isUint16ArrayPrediction(m_state.forNode(node.child1()).m_type));
3205         break;
3206     }
3207     case GetUint32ArrayLength: {
3208         compileGetTypedArrayLength(m_jit.globalData()->uint32ArrayDescriptor(), node, !isUint32ArrayPrediction(m_state.forNode(node.child1()).m_type));
3209         break;
3210     }
3211     case GetFloat32ArrayLength: {
3212         compileGetTypedArrayLength(m_jit.globalData()->float32ArrayDescriptor(), node, !isFloat32ArrayPrediction(m_state.forNode(node.child1()).m_type));
3213         break;
3214     }
3215     case GetFloat64ArrayLength: {
3216         compileGetTypedArrayLength(m_jit.globalData()->float64ArrayDescriptor(), node, !isFloat64ArrayPrediction(m_state.forNode(node.child1()).m_type));
3217         break;
3218     }
3219     case CheckFunction: {
3220         SpeculateCellOperand function(this, node.child1());
3221         speculationCheck(BadCache, JSValueRegs(), NoNode, m_jit.branchWeakPtr(JITCompiler::NotEqual, function.gpr(), node.function()));
3222         noResult(m_compileIndex);
3223         break;
3224     }
3225     case CheckStructure: {
3226         if (m_state.forNode(node.child1()).m_structure.isSubsetOf(node.structureSet())) {
3227             noResult(m_compileIndex);
3228             break;
3229         }
3230         
3231         SpeculateCellOperand base(this, node.child1());
3232         
3233         ASSERT(node.structureSet().size());
3234         
3235         if (node.structureSet().size() == 1)
3236             speculationCheck(BadCache, JSValueRegs(), NoNode, m_jit.branchWeakPtr(JITCompiler::NotEqual, JITCompiler::Address(base.gpr(), JSCell::structureOffset()), node.structureSet()[0]));
3237         else {
3238             GPRTemporary structure(this);
3239             
3240             m_jit.loadPtr(JITCompiler::Address(base.gpr(), JSCell::structureOffset()), structure.gpr());
3241             
3242             JITCompiler::JumpList done;
3243             
3244             for (size_t i = 0; i < node.structureSet().size() - 1; ++i)
3245                 done.append(m_jit.branchWeakPtr(JITCompiler::Equal, structure.gpr(), node.structureSet()[i]));
3246             
3247             speculationCheck(BadCache, JSValueRegs(), NoNode, m_jit.branchWeakPtr(JITCompiler::NotEqual, structure.gpr(), node.structureSet().last()));
3248             
3249             done.link(&m_jit);
3250         }
3251         
3252         noResult(m_compileIndex);
3253         break;
3254     }
3255         
3256     case PutStructure: {
3257         SpeculateCellOperand base(this, node.child1());
3258         GPRReg baseGPR = base.gpr();
3259         
3260         m_jit.addWeakReferenceTransition(
3261             node.codeOrigin.codeOriginOwner(),
3262             node.structureTransitionData().previousStructure,
3263             node.structureTransitionData().newStructure);
3264         
3265 #if ENABLE(GGC) || ENABLE(WRITE_BARRIER_PROFILING)
3266         // Must always emit this write barrier as the structure transition itself requires it
3267         writeBarrier(baseGPR, node.structureTransitionData().newStructure, WriteBarrierForGenericAccess);
3268 #endif
3269         
3270         m_jit.storePtr(MacroAssembler::TrustedImmPtr(node.structureTransitionData().newStructure), MacroAssembler::Address(baseGPR, JSCell::structureOffset()));
3271         
3272         noResult(m_compileIndex);
3273         break;
3274     }
3275         
3276     case GetPropertyStorage: {
3277         SpeculateCellOperand base(this, node.child1());
3278         GPRTemporary result(this, base);
3279         
3280         GPRReg baseGPR = base.gpr();
3281         GPRReg resultGPR = result.gpr();
3282         
3283         m_jit.loadPtr(JITCompiler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), resultGPR);
3284         
3285         storageResult(resultGPR, m_compileIndex);
3286         break;
3287     }
3288
3289     case GetIndexedPropertyStorage: {
3290         compileGetIndexedPropertyStorage(node);
3291         break;
3292     }
3293         
3294     case GetByOffset: {
3295         StorageOperand storage(this, node.child1());
3296         GPRTemporary result(this, storage);
3297         
3298         GPRReg storageGPR = storage.gpr();
3299         GPRReg resultGPR = result.gpr();
3300         
3301         StorageAccessData& storageAccessData = m_jit.graph().m_storageAccessData[node.storageAccessDataIndex()];
3302         
3303         m_jit.loadPtr(JITCompiler::Address(storageGPR, storageAccessData.offset * sizeof(EncodedJSValue)), resultGPR);
3304         
3305         jsValueResult(resultGPR, m_compileIndex);
3306         break;
3307     }
3308         
3309     case PutByOffset: {
3310 #if ENABLE(GGC) || ENABLE(WRITE_BARRIER_PROFILING)
3311         SpeculateCellOperand base(this, node.child1());
3312 #endif
3313         StorageOperand storage(this, node.child2());
3314         JSValueOperand value(this, node.child3());
3315
3316         GPRReg storageGPR = storage.gpr();
3317         GPRReg valueGPR = value.gpr();
3318         
3319 #if ENABLE(GGC) || ENABLE(WRITE_BARRIER_PROFILING)
3320         writeBarrier(base.gpr(), value.gpr(), node.child3(), WriteBarrierForPropertyAccess);
3321 #endif
3322
3323         StorageAccessData& storageAccessData = m_jit.graph().m_storageAccessData[node.storageAccessDataIndex()];
3324         
3325         m_jit.storePtr(valueGPR, JITCompiler::Address(storageGPR, storageAccessData.offset * sizeof(EncodedJSValue)));
3326         
3327         noResult(m_compileIndex);
3328         break;
3329     }
3330         
3331     case PutById: {
3332         SpeculateCellOperand base(this, node.child1());
3333         JSValueOperand value(this, node.child2());
3334         GPRTemporary scratch(this);
3335         
3336         GPRReg baseGPR = base.gpr();
3337         GPRReg valueGPR = value.gpr();
3338         GPRReg scratchGPR = scratch.gpr();
3339         
3340         base.use();
3341         value.use();
3342
3343         cachedPutById(node.codeOrigin, baseGPR, valueGPR, node.child2(), scratchGPR, node.identifierNumber(), NotDirect);
3344         
3345         noResult(m_compileIndex, UseChildrenCalledExplicitly);
3346         break;
3347     }
3348
3349     case PutByIdDirect: {
3350         SpeculateCellOperand base(this, node.child1());
3351         JSValueOperand value(this, node.child2());
3352         GPRTemporary scratch(this);
3353         
3354         GPRReg baseGPR = base.gpr();
3355         GPRReg valueGPR = value.gpr();
3356         GPRReg scratchGPR = scratch.gpr();
3357         
3358         base.use();
3359         value.use();
3360
3361         cachedPutById(node.codeOrigin, baseGPR, valueGPR, node.child2(), scratchGPR, node.identifierNumber(), Direct);
3362
3363         noResult(m_compileIndex, UseChildrenCalledExplicitly);
3364         break;
3365     }
3366
3367     case GetGlobalVar: {
3368         GPRTemporary result(this);
3369
3370         JSVariableObject* globalObject = m_jit.globalObjectFor(node.codeOrigin);
3371         m_jit.loadPtr(globalObject->addressOfRegisters(), result.gpr());
3372         m_jit.loadPtr(JITCompiler::addressForGlobalVar(result.gpr(), node.varNumber()), result.gpr());
3373
3374         jsValueResult(result.gpr(), m_compileIndex);
3375         break;
3376     }
3377
3378     case PutGlobalVar: {
3379         JSValueOperand value(this, node.child1());
3380         GPRTemporary globalObject(this);
3381         GPRTemporary scratch(this);
3382         
3383         GPRReg globalObjectReg = globalObject.gpr();
3384         GPRReg scratchReg = scratch.gpr();
3385
3386         m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.globalObjectFor(node.codeOrigin)), globalObjectReg);
3387
3388         writeBarrier(m_jit.globalObjectFor(node.codeOrigin), value.gpr(), node.child1(), WriteBarrierForVariableAccess, scratchReg);
3389
3390         m_jit.loadPtr(MacroAssembler::Address(globalObjectReg, JSVariableObject::offsetOfRegisters()), scratchReg);
3391         m_jit.storePtr(value.gpr(), JITCompiler::addressForGlobalVar(scratchReg, node.varNumber()));
3392
3393         noResult(m_compileIndex);
3394         break;
3395     }
3396
3397     case CheckHasInstance: {
3398         SpeculateCellOperand base(this, node.child1());
3399         GPRTemporary structure(this);
3400
3401         // Speculate that base 'ImplementsDefaultHasInstance'.
3402         m_jit.loadPtr(MacroAssembler::Address(base.gpr(), JSCell::structureOffset()), structure.gpr());
3403         speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTest8(MacroAssembler::Zero, MacroAssembler::Address(structure.gpr(), Structure::typeInfoFlagsOffset()), MacroAssembler::TrustedImm32(ImplementsDefaultHasInstance)));
3404
3405         noResult(m_compileIndex);
3406         break;
3407     }
3408
3409     case InstanceOf: {
3410         compileInstanceOf(node);
3411         break;
3412     }
3413
3414     case Flush:
3415     case Phi:
3416         break;
3417
3418     case Breakpoint:
3419 #if ENABLE(DEBUG_WITH_BREAKPOINT)
3420         m_jit.breakpoint();
3421 #else
3422         ASSERT_NOT_REACHED();
3423 #endif
3424         break;
3425         
3426     case Call:
3427     case Construct:
3428         emitCall(node);
3429         break;
3430
3431     case Resolve: {
3432         flushRegisters();
3433         GPRResult result(this);
3434         callOperation(operationResolve, result.gpr(), identifier(node.identifierNumber()));
3435         jsValueResult(result.gpr(), m_compileIndex);
3436         break;
3437     }
3438
3439     case ResolveBase: {
3440         flushRegisters();
3441         GPRResult result(this);
3442         callOperation(operationResolveBase, result.gpr(), identifier(node.identifierNumber()));
3443         jsValueResult(result.gpr(), m_compileIndex);
3444         break;
3445     }
3446
3447     case ResolveBaseStrictPut: {
3448         flushRegisters();
3449         GPRResult result(this);
3450         callOperation(operationResolveBaseStrictPut, result.gpr(), identifier(node.identifierNumber()));
3451         jsValueResult(result.gpr(), m_compileIndex);
3452         break;
3453     }
3454
3455     case ResolveGlobal: {
3456         GPRTemporary globalObject(this);
3457         GPRTemporary resolveInfo(this);
3458         GPRTemporary result(this);
3459
3460         GPRReg globalObjectGPR = globalObject.gpr();
3461         GPRReg resolveInfoGPR = resolveInfo.gpr();
3462         GPRReg resultGPR = result.gpr();
3463
3464         ResolveGlobalData& data = m_jit.graph().m_resolveGlobalData[node.resolveGlobalDataIndex()];
3465         GlobalResolveInfo* resolveInfoAddress = &(m_jit.codeBlock()->globalResolveInfo(data.resolveInfoIndex));
3466
3467         // Check Structure of global object
3468         m_jit.move(JITCompiler::TrustedImmPtr(m_jit.globalObjectFor(node.codeOrigin)), globalObjectGPR);
3469         m_jit.move(JITCompiler::TrustedImmPtr(resolveInfoAddress), resolveInfoGPR);
3470         m_jit.loadPtr(JITCompiler::Address(resolveInfoGPR, OBJECT_OFFSETOF(GlobalResolveInfo, structure)), resultGPR);
3471         JITCompiler::Jump structuresMatch = m_jit.branchPtr(JITCompiler::Equal, resultGPR, JITCompiler::Address(globalObjectGPR, JSCell::structureOffset()));
3472
3473         silentSpillAllRegisters(resultGPR);
3474         callOperation(operationResolveGlobal, resultGPR, resolveInfoGPR, &m_jit.codeBlock()->identifier(data.identifierNumber));
3475         silentFillAllRegisters(resultGPR);
3476
3477         JITCompiler::Jump wasSlow = m_jit.jump();
3478
3479         // Fast case
3480         structuresMatch.link(&m_jit);
3481         m_jit.loadPtr(JITCompiler::Address(globalObjectGPR, JSObject::offsetOfPropertyStorage()), resultGPR);
3482         m_jit.load32(JITCompiler::Address(resolveInfoGPR, OBJECT_OFFSETOF(GlobalResolveInfo, offset)), resolveInfoGPR);
3483         m_jit.loadPtr(JITCompiler::BaseIndex(resultGPR, resolveInfoGPR, JITCompiler::ScalePtr), resultGPR);
3484
3485         wasSlow.link(&m_jit);
3486
3487         jsValueResult(resultGPR, m_compileIndex);
3488         break;
3489     }
3490         
3491     case CreateActivation: {
3492         JSValueOperand value(this, node.child1());
3493         GPRTemporary result(this, value);
3494         
3495         GPRReg valueGPR = value.gpr();
3496         GPRReg resultGPR = result.gpr();
3497         
3498         m_jit.move(valueGPR, resultGPR);
3499         
3500         JITCompiler::Jump alreadyCreated = m_jit.branchTestPtr(JITCompiler::NonZero, resultGPR);
3501         
3502         silentSpillAllRegisters(resultGPR);
3503         callOperation(operationCreateActivation, resultGPR);
3504         silentFillAllRegisters(resultGPR);
3505         
3506         alreadyCreated.link(&m_jit);
3507         
3508         cellResult(resultGPR, m_compileIndex);
3509         break;
3510     }
3511         
3512     case TearOffActivation: {
3513         JSValueOperand value(this, node.child1());
3514         GPRReg valueGPR = value.gpr();
3515         
3516         JITCompiler::Jump notCreated = m_jit.branchTestPtr(JITCompiler::Zero, valueGPR);
3517         
3518         silentSpillAllRegisters(InvalidGPRReg);
3519         callOperation(operationTearOffActivation, valueGPR);
3520         silentFillAllRegisters(InvalidGPRReg);
3521         
3522         notCreated.link(&m_jit);
3523         
3524         noResult(m_compileIndex);
3525         break;
3526     }
3527         
3528     case NewFunctionNoCheck:
3529         compileNewFunctionNoCheck(node);
3530         break;
3531         
3532     case NewFunction: {
3533         JSValueOperand value(this, node.child1());
3534         GPRTemporary result(this, value);
3535         
3536         GPRReg valueGPR = value.gpr();
3537         GPRReg resultGPR = result.gpr();
3538         
3539         m_jit.move(valueGPR, resultGPR);
3540         
3541         JITCompiler::Jump alreadyCreated = m_jit.branchTestPtr(JITCompiler::NonZero, resultGPR);
3542         
3543         silentSpillAllRegisters(resultGPR);
3544         callOperation(
3545             operationNewFunction, resultGPR, m_jit.codeBlock()->functionDecl(node.functionDeclIndex()));
3546         silentFillAllRegisters(resultGPR);
3547         
3548         alreadyCreated.link(&m_jit);
3549         
3550         cellResult(resultGPR, m_compileIndex);
3551         break;
3552     }
3553         
3554     case NewFunctionExpression:
3555         compileNewFunctionExpression(node);
3556         break;
3557
3558     case ForceOSRExit: {
3559         terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
3560         break;
3561     }
3562
3563     case Phantom:
3564         // This is a no-op.
3565         noResult(m_compileIndex);
3566         break;
3567         
3568     case InlineStart:
3569     case Nop:
3570         ASSERT_NOT_REACHED();
3571         break;
3572         
3573     case LastNodeType:
3574         ASSERT_NOT_REACHED();
3575         break;
3576     }
3577
3578     if (!m_compileOkay)
3579         return;
3580     
3581     if (node.hasResult() && node.mustGenerate())
3582         use(m_compileIndex);
3583 }
3584
3585 #endif
3586
3587 } } // namespace JSC::DFG
3588
3589 #endif