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