fourthTier: Decouple the way that CFA stores its state from the way it does abstract...
[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
1111         if (edge->hasConstant()) {
1112             JSValue jsValue = valueOfJSConstant(edge.node());
1113             GPRReg gpr = allocate();
1114             if (jsValue.isCell()) {
1115                 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1116                 m_jit.move(MacroAssembler::TrustedImmPtr(jsValue.asCell()), gpr);
1117                 info.fillCell(*m_stream, gpr);
1118                 return gpr;
1119             }
1120             terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1121             return gpr;
1122         }
1123
1124         ASSERT((info.spillFormat() & DataFormatJS) || info.spillFormat() == DataFormatCell);
1125         if (type & ~SpecCell)
1126             speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), edge, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::CellTag)));
1127         GPRReg gpr = allocate();
1128         m_jit.load32(JITCompiler::payloadFor(virtualRegister), gpr);
1129         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1130         info.fillCell(*m_stream, gpr);
1131         return gpr;
1132     }
1133
1134     case DataFormatCell: {
1135         GPRReg gpr = info.gpr();
1136         m_gprs.lock(gpr);
1137         return gpr;
1138     }
1139
1140     case DataFormatJSCell:
1141     case DataFormatJS: {
1142         GPRReg tagGPR = info.tagGPR();
1143         GPRReg payloadGPR = info.payloadGPR();
1144         m_gprs.lock(tagGPR);
1145         m_gprs.lock(payloadGPR);
1146         if (type & ~SpecCell)
1147             speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), edge, m_jit.branch32(MacroAssembler::NotEqual, tagGPR, TrustedImm32(JSValue::CellTag)));
1148         m_gprs.unlock(tagGPR);
1149         m_gprs.release(tagGPR);
1150         m_gprs.release(payloadGPR);
1151         m_gprs.retain(payloadGPR, virtualRegister, SpillOrderCell);
1152         info.fillCell(*m_stream, payloadGPR);
1153         return payloadGPR;
1154     }
1155
1156     case DataFormatJSInteger:
1157     case DataFormatInteger:
1158     case DataFormatJSDouble:
1159     case DataFormatDouble:
1160     case DataFormatJSBoolean:
1161     case DataFormatBoolean:
1162         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1163         return allocate();
1164
1165     case DataFormatStorage:
1166         RELEASE_ASSERT_NOT_REACHED();
1167
1168     default:
1169         RELEASE_ASSERT_NOT_REACHED();
1170         return InvalidGPRReg;
1171     }
1172 }
1173
1174 GPRReg SpeculativeJIT::fillSpeculateBoolean(Edge edge)
1175 {
1176 #if DFG_ENABLE(DEBUG_VERBOSE)
1177     dataLogF("SpecBool@%d   ", edge.node()->index());
1178 #endif
1179     AbstractValue& value = m_state.forNode(edge);
1180     SpeculatedType type = value.m_type;
1181     m_interpreter.filter(value, SpecBoolean);
1182     VirtualRegister virtualRegister = edge->virtualRegister();
1183     GenerationInfo& info = m_generationInfo[virtualRegister];
1184
1185     switch (info.registerFormat()) {
1186     case DataFormatNone: {
1187         if (info.spillFormat() == DataFormatInteger || info.spillFormat() == DataFormatDouble) {
1188             terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1189             return allocate();
1190         }
1191         
1192         if (edge->hasConstant()) {
1193             JSValue jsValue = valueOfJSConstant(edge.node());
1194             GPRReg gpr = allocate();
1195             if (jsValue.isBoolean()) {
1196                 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1197                 m_jit.move(MacroAssembler::TrustedImm32(jsValue.asBoolean()), gpr);
1198                 info.fillBoolean(*m_stream, gpr);
1199                 return gpr;
1200             }
1201             terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1202             return gpr;
1203         }
1204
1205         ASSERT((info.spillFormat() & DataFormatJS) || info.spillFormat() == DataFormatBoolean);
1206
1207         if (type & ~SpecBoolean)
1208             speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), edge, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::BooleanTag)));
1209
1210         GPRReg gpr = allocate();
1211         m_jit.load32(JITCompiler::payloadFor(virtualRegister), gpr);
1212         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1213         info.fillBoolean(*m_stream, gpr);
1214         return gpr;
1215     }
1216
1217     case DataFormatBoolean: {
1218         GPRReg gpr = info.gpr();
1219         m_gprs.lock(gpr);
1220         return gpr;
1221     }
1222
1223     case DataFormatJSBoolean:
1224     case DataFormatJS: {
1225         GPRReg tagGPR = info.tagGPR();
1226         GPRReg payloadGPR = info.payloadGPR();
1227         m_gprs.lock(tagGPR);
1228         m_gprs.lock(payloadGPR);
1229         if (type & ~SpecBoolean)
1230             speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), edge, m_jit.branch32(MacroAssembler::NotEqual, tagGPR, TrustedImm32(JSValue::BooleanTag)));
1231
1232         m_gprs.unlock(tagGPR);
1233         m_gprs.release(tagGPR);
1234         m_gprs.release(payloadGPR);
1235         m_gprs.retain(payloadGPR, virtualRegister, SpillOrderBoolean);
1236         info.fillBoolean(*m_stream, payloadGPR);
1237         return payloadGPR;
1238     }
1239
1240     case DataFormatJSInteger:
1241     case DataFormatInteger:
1242     case DataFormatJSDouble:
1243     case DataFormatDouble:
1244     case DataFormatJSCell:
1245     case DataFormatCell:
1246         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1247         return allocate();
1248
1249     case DataFormatStorage:
1250         RELEASE_ASSERT_NOT_REACHED();
1251
1252     default:
1253         RELEASE_ASSERT_NOT_REACHED();
1254         return InvalidGPRReg;
1255     }
1256 }
1257
1258 JITCompiler::Jump SpeculativeJIT::convertToDouble(JSValueOperand& op, FPRReg result)
1259 {
1260     FPRTemporary scratch(this);
1261
1262     GPRReg opPayloadGPR = op.payloadGPR();
1263     GPRReg opTagGPR = op.tagGPR();
1264     FPRReg scratchFPR = scratch.fpr();
1265
1266     JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, opTagGPR, TrustedImm32(JSValue::Int32Tag));
1267     JITCompiler::Jump notNumber = m_jit.branch32(MacroAssembler::AboveOrEqual, opPayloadGPR, TrustedImm32(JSValue::LowestTag));
1268
1269     unboxDouble(opTagGPR, opPayloadGPR, result, scratchFPR);
1270     JITCompiler::Jump done = m_jit.jump();
1271
1272     isInteger.link(&m_jit);
1273     m_jit.convertInt32ToDouble(opPayloadGPR, result);
1274
1275     done.link(&m_jit);
1276
1277     return notNumber;
1278 }
1279
1280 void SpeculativeJIT::compileObjectEquality(Node* node)
1281 {
1282     SpeculateCellOperand op1(this, node->child1());
1283     SpeculateCellOperand op2(this, node->child2());
1284     GPRReg op1GPR = op1.gpr();
1285     GPRReg op2GPR = op2.gpr();
1286     
1287     if (masqueradesAsUndefinedWatchpointIsStillValid()) {
1288         speculationWatchpointForMasqueradesAsUndefined();
1289         DFG_TYPE_CHECK(
1290             JSValueSource::unboxedCell(op1GPR), node->child1(), SpecObject, m_jit.branchPtr(
1291                 MacroAssembler::Equal, 
1292                 MacroAssembler::Address(op1GPR, JSCell::structureOffset()), 
1293                 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1294         DFG_TYPE_CHECK(
1295             JSValueSource::unboxedCell(op2GPR), node->child2(), SpecObject, m_jit.branchPtr(
1296                 MacroAssembler::Equal, 
1297                 MacroAssembler::Address(op2GPR, JSCell::structureOffset()), 
1298                 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1299     } else {
1300         GPRTemporary structure(this);
1301         GPRReg structureGPR = structure.gpr();
1302
1303         m_jit.loadPtr(MacroAssembler::Address(op1GPR, JSCell::structureOffset()), structureGPR);
1304         DFG_TYPE_CHECK(
1305             JSValueSource::unboxedCell(op1GPR), node->child1(), SpecObject, m_jit.branchPtr(
1306                 MacroAssembler::Equal, 
1307                 structureGPR, 
1308                 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1309         speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node->child1(), 
1310             m_jit.branchTest8(
1311                 MacroAssembler::NonZero, 
1312                 MacroAssembler::Address(structureGPR, Structure::typeInfoFlagsOffset()), 
1313                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1314
1315         m_jit.loadPtr(MacroAssembler::Address(op2GPR, JSCell::structureOffset()), structureGPR);
1316         DFG_TYPE_CHECK(
1317             JSValueSource::unboxedCell(op2GPR), node->child2(), SpecObject, m_jit.branchPtr(
1318                 MacroAssembler::Equal, 
1319                 structureGPR, 
1320                 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1321         speculationCheck(BadType, JSValueSource::unboxedCell(op2GPR), node->child2(), 
1322             m_jit.branchTest8(
1323                 MacroAssembler::NonZero, 
1324                 MacroAssembler::Address(structureGPR, Structure::typeInfoFlagsOffset()), 
1325                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1326     }
1327     
1328     GPRTemporary resultPayload(this, op2);
1329     GPRReg resultPayloadGPR = resultPayload.gpr();
1330     
1331     MacroAssembler::Jump falseCase = m_jit.branchPtr(MacroAssembler::NotEqual, op1GPR, op2GPR);
1332     m_jit.move(TrustedImm32(1), resultPayloadGPR);
1333     MacroAssembler::Jump done = m_jit.jump();
1334     falseCase.link(&m_jit);
1335     m_jit.move(TrustedImm32(0), resultPayloadGPR);
1336     done.link(&m_jit);
1337
1338     booleanResult(resultPayloadGPR, node);
1339 }
1340
1341 void SpeculativeJIT::compileObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild)
1342 {
1343     SpeculateCellOperand op1(this, leftChild);
1344     JSValueOperand op2(this, rightChild, ManualOperandSpeculation);
1345     GPRTemporary result(this);
1346     
1347     GPRReg op1GPR = op1.gpr();
1348     GPRReg op2TagGPR = op2.tagGPR();
1349     GPRReg op2PayloadGPR = op2.payloadGPR();
1350     GPRReg resultGPR = result.gpr();
1351     GPRTemporary structure;
1352     GPRReg structureGPR = InvalidGPRReg;
1353
1354     bool masqueradesAsUndefinedWatchpointValid =
1355         masqueradesAsUndefinedWatchpointIsStillValid();
1356
1357     if (!masqueradesAsUndefinedWatchpointValid) {
1358         // The masquerades as undefined case will use the structure register, so allocate it here.
1359         // Do this at the top of the function to avoid branching around a register allocation.
1360         GPRTemporary realStructure(this);
1361         structure.adopt(realStructure);
1362         structureGPR = structure.gpr();
1363     }
1364
1365     if (masqueradesAsUndefinedWatchpointValid) {
1366         speculationWatchpointForMasqueradesAsUndefined();
1367         DFG_TYPE_CHECK(
1368             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchPtr(
1369                 MacroAssembler::Equal, 
1370                 MacroAssembler::Address(op1GPR, JSCell::structureOffset()), 
1371                 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1372     } else {
1373         m_jit.loadPtr(MacroAssembler::Address(op1GPR, JSCell::structureOffset()), structureGPR);
1374         DFG_TYPE_CHECK(
1375             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchPtr(
1376                 MacroAssembler::Equal,
1377                 structureGPR,
1378                 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1379         speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), leftChild, 
1380             m_jit.branchTest8(
1381                 MacroAssembler::NonZero, 
1382                 MacroAssembler::Address(structureGPR, Structure::typeInfoFlagsOffset()), 
1383                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1384     }
1385     
1386     
1387     // It seems that most of the time when programs do a == b where b may be either null/undefined
1388     // or an object, b is usually an object. Balance the branches to make that case fast.
1389     MacroAssembler::Jump rightNotCell =
1390         m_jit.branch32(MacroAssembler::NotEqual, op2TagGPR, TrustedImm32(JSValue::CellTag));
1391     
1392     // We know that within this branch, rightChild must be a cell.
1393     if (masqueradesAsUndefinedWatchpointValid) {
1394         speculationWatchpointForMasqueradesAsUndefined();
1395         DFG_TYPE_CHECK(
1396             JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, (~SpecCell) | SpecObject,
1397             m_jit.branchPtr(
1398                 MacroAssembler::Equal, 
1399                 MacroAssembler::Address(op2PayloadGPR, JSCell::structureOffset()), 
1400                 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1401     } else {
1402         m_jit.loadPtr(MacroAssembler::Address(op2PayloadGPR, JSCell::structureOffset()), structureGPR);
1403         DFG_TYPE_CHECK(
1404             JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, (~SpecCell) | SpecObject,
1405             m_jit.branchPtr(
1406                 MacroAssembler::Equal,
1407                 structureGPR,
1408                 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1409         speculationCheck(BadType, JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, 
1410             m_jit.branchTest8(
1411                 MacroAssembler::NonZero, 
1412                 MacroAssembler::Address(structureGPR, Structure::typeInfoFlagsOffset()), 
1413                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1414     }
1415     
1416     // At this point we know that we can perform a straight-forward equality comparison on pointer
1417     // values because both left and right are pointers to objects that have no special equality
1418     // protocols.
1419     MacroAssembler::Jump falseCase = m_jit.branchPtr(MacroAssembler::NotEqual, op1GPR, op2PayloadGPR);
1420     MacroAssembler::Jump trueCase = m_jit.jump();
1421     
1422     rightNotCell.link(&m_jit);
1423     
1424     // We know that within this branch, rightChild must not be a cell. Check if that is enough to
1425     // prove that it is either null or undefined.
1426     if (needsTypeCheck(rightChild, SpecCell | SpecOther)) {
1427         m_jit.move(op2TagGPR, resultGPR);
1428         m_jit.or32(TrustedImm32(1), resultGPR);
1429         
1430         typeCheck(
1431             JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, SpecCell | SpecOther,
1432             m_jit.branch32(
1433                 MacroAssembler::NotEqual, resultGPR,
1434                 MacroAssembler::TrustedImm32(JSValue::NullTag)));
1435     }
1436     
1437     falseCase.link(&m_jit);
1438     m_jit.move(TrustedImm32(0), resultGPR);
1439     MacroAssembler::Jump done = m_jit.jump();
1440     trueCase.link(&m_jit);
1441     m_jit.move(TrustedImm32(1), resultGPR);
1442     done.link(&m_jit);
1443     
1444     booleanResult(resultGPR, m_currentNode);
1445 }
1446
1447 void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild, Node* branchNode)
1448 {
1449     BasicBlock* taken = branchNode->takenBlock();
1450     BasicBlock* notTaken = branchNode->notTakenBlock();
1451     
1452     SpeculateCellOperand op1(this, leftChild);
1453     JSValueOperand op2(this, rightChild, ManualOperandSpeculation);
1454     GPRTemporary result(this);
1455     
1456     GPRReg op1GPR = op1.gpr();
1457     GPRReg op2TagGPR = op2.tagGPR();
1458     GPRReg op2PayloadGPR = op2.payloadGPR();
1459     GPRReg resultGPR = result.gpr();
1460     GPRTemporary structure;
1461     GPRReg structureGPR = InvalidGPRReg;
1462
1463     bool masqueradesAsUndefinedWatchpointValid =
1464         masqueradesAsUndefinedWatchpointIsStillValid();
1465
1466     if (!masqueradesAsUndefinedWatchpointValid) {
1467         // The masquerades as undefined case will use the structure register, so allocate it here.
1468         // Do this at the top of the function to avoid branching around a register allocation.
1469         GPRTemporary realStructure(this);
1470         structure.adopt(realStructure);
1471         structureGPR = structure.gpr();
1472     }
1473
1474     if (masqueradesAsUndefinedWatchpointValid) {
1475         speculationWatchpointForMasqueradesAsUndefined();
1476         DFG_TYPE_CHECK(
1477             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchPtr(
1478                 MacroAssembler::Equal, 
1479                 MacroAssembler::Address(op1GPR, JSCell::structureOffset()), 
1480                 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1481     } else {
1482         m_jit.loadPtr(MacroAssembler::Address(op1GPR, JSCell::structureOffset()), structureGPR);
1483         DFG_TYPE_CHECK(
1484             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchPtr(
1485                 MacroAssembler::Equal, 
1486                 structureGPR, 
1487                 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1488         speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), leftChild,
1489             m_jit.branchTest8(
1490                 MacroAssembler::NonZero, 
1491                 MacroAssembler::Address(structureGPR, Structure::typeInfoFlagsOffset()), 
1492                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1493     }
1494     
1495     // It seems that most of the time when programs do a == b where b may be either null/undefined
1496     // or an object, b is usually an object. Balance the branches to make that case fast.
1497     MacroAssembler::Jump rightNotCell =
1498         m_jit.branch32(MacroAssembler::NotEqual, op2TagGPR, TrustedImm32(JSValue::CellTag));
1499     
1500     // We know that within this branch, rightChild must be a cell.
1501     if (masqueradesAsUndefinedWatchpointValid) {
1502         speculationWatchpointForMasqueradesAsUndefined();
1503         DFG_TYPE_CHECK(
1504             JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, (~SpecCell) | SpecObject,
1505             m_jit.branchPtr(
1506                 MacroAssembler::Equal, 
1507                 MacroAssembler::Address(op2PayloadGPR, JSCell::structureOffset()), 
1508                 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1509     } else {
1510         m_jit.loadPtr(MacroAssembler::Address(op2PayloadGPR, JSCell::structureOffset()), structureGPR);
1511         DFG_TYPE_CHECK(
1512             JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, (~SpecCell) | SpecObject,
1513             m_jit.branchPtr(
1514                 MacroAssembler::Equal, 
1515                 structureGPR, 
1516                 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1517         speculationCheck(BadType, JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild,
1518             m_jit.branchTest8(
1519                 MacroAssembler::NonZero, 
1520                 MacroAssembler::Address(structureGPR, Structure::typeInfoFlagsOffset()), 
1521                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1522     }
1523     
1524     // At this point we know that we can perform a straight-forward equality comparison on pointer
1525     // values because both left and right are pointers to objects that have no special equality
1526     // protocols.
1527     branch32(MacroAssembler::Equal, op1GPR, op2PayloadGPR, taken);
1528     
1529     // We know that within this branch, rightChild must not be a cell. Check if that is enough to
1530     // prove that it is either null or undefined.
1531     if (!needsTypeCheck(rightChild, SpecCell | SpecOther))
1532         rightNotCell.link(&m_jit);
1533     else {
1534         jump(notTaken, ForceJump);
1535         
1536         rightNotCell.link(&m_jit);
1537         m_jit.move(op2TagGPR, resultGPR);
1538         m_jit.or32(TrustedImm32(1), resultGPR);
1539         
1540         typeCheck(
1541             JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, SpecCell | SpecOther,
1542             m_jit.branch32(
1543                 MacroAssembler::NotEqual, resultGPR,
1544                 MacroAssembler::TrustedImm32(JSValue::NullTag)));
1545     }
1546     
1547     jump(notTaken);
1548 }
1549
1550 void SpeculativeJIT::compileIntegerCompare(Node* node, MacroAssembler::RelationalCondition condition)
1551 {
1552     SpeculateIntegerOperand op1(this, node->child1());
1553     SpeculateIntegerOperand op2(this, node->child2());
1554     GPRTemporary resultPayload(this);
1555     
1556     m_jit.compare32(condition, op1.gpr(), op2.gpr(), resultPayload.gpr());
1557     
1558     // If we add a DataFormatBool, we should use it here.
1559     booleanResult(resultPayload.gpr(), node);
1560 }
1561
1562 void SpeculativeJIT::compileDoubleCompare(Node* node, MacroAssembler::DoubleCondition condition)
1563 {
1564     SpeculateDoubleOperand op1(this, node->child1());
1565     SpeculateDoubleOperand op2(this, node->child2());
1566     GPRTemporary resultPayload(this);
1567     
1568     m_jit.move(TrustedImm32(1), resultPayload.gpr());
1569     MacroAssembler::Jump trueCase = m_jit.branchDouble(condition, op1.fpr(), op2.fpr());
1570     m_jit.move(TrustedImm32(0), resultPayload.gpr());
1571     trueCase.link(&m_jit);
1572     
1573     booleanResult(resultPayload.gpr(), node);
1574 }
1575
1576 void SpeculativeJIT::compileValueAdd(Node* node)
1577 {
1578     JSValueOperand op1(this, node->child1());
1579     JSValueOperand op2(this, node->child2());
1580
1581     GPRReg op1TagGPR = op1.tagGPR();
1582     GPRReg op1PayloadGPR = op1.payloadGPR();
1583     GPRReg op2TagGPR = op2.tagGPR();
1584     GPRReg op2PayloadGPR = op2.payloadGPR();
1585
1586     flushRegisters();
1587     
1588     GPRResult2 resultTag(this);
1589     GPRResult resultPayload(this);
1590     if (isKnownNotNumber(node->child1().node()) || isKnownNotNumber(node->child2().node()))
1591         callOperation(operationValueAddNotNumber, resultTag.gpr(), resultPayload.gpr(), op1TagGPR, op1PayloadGPR, op2TagGPR, op2PayloadGPR);
1592     else
1593         callOperation(operationValueAdd, resultTag.gpr(), resultPayload.gpr(), op1TagGPR, op1PayloadGPR, op2TagGPR, op2PayloadGPR);
1594     
1595     jsValueResult(resultTag.gpr(), resultPayload.gpr(), node);
1596 }
1597
1598 void SpeculativeJIT::compileObjectOrOtherLogicalNot(Edge nodeUse)
1599 {
1600     JSValueOperand value(this, nodeUse, ManualOperandSpeculation);
1601     GPRTemporary resultPayload(this);
1602     GPRReg valueTagGPR = value.tagGPR();
1603     GPRReg valuePayloadGPR = value.payloadGPR();
1604     GPRReg resultPayloadGPR = resultPayload.gpr();
1605     GPRTemporary structure;
1606     GPRReg structureGPR = InvalidGPRReg;
1607
1608     bool masqueradesAsUndefinedWatchpointValid =
1609         masqueradesAsUndefinedWatchpointIsStillValid();
1610
1611     if (!masqueradesAsUndefinedWatchpointValid) {
1612         // The masquerades as undefined case will use the structure register, so allocate it here.
1613         // Do this at the top of the function to avoid branching around a register allocation.
1614         GPRTemporary realStructure(this);
1615         structure.adopt(realStructure);
1616         structureGPR = structure.gpr();
1617     }
1618
1619     MacroAssembler::Jump notCell = m_jit.branch32(MacroAssembler::NotEqual, valueTagGPR, TrustedImm32(JSValue::CellTag));
1620     if (masqueradesAsUndefinedWatchpointValid) {
1621         speculationWatchpointForMasqueradesAsUndefined();
1622
1623         DFG_TYPE_CHECK(
1624             JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, (~SpecCell) | SpecObject,
1625             m_jit.branchPtr(
1626                 MacroAssembler::Equal,
1627                 MacroAssembler::Address(valuePayloadGPR, JSCell::structureOffset()),
1628                 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1629     } else {
1630         m_jit.loadPtr(MacroAssembler::Address(valuePayloadGPR, JSCell::structureOffset()), structureGPR);
1631
1632         DFG_TYPE_CHECK(
1633             JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, (~SpecCell) | SpecObject,
1634             m_jit.branchPtr(
1635                 MacroAssembler::Equal,
1636                 structureGPR,
1637                 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1638
1639         MacroAssembler::Jump isNotMasqueradesAsUndefined = 
1640             m_jit.branchTest8(
1641                 MacroAssembler::Zero, 
1642                 MacroAssembler::Address(structureGPR, Structure::typeInfoFlagsOffset()), 
1643                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined));
1644
1645         speculationCheck(BadType, JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, 
1646             m_jit.branchPtr(
1647                 MacroAssembler::Equal, 
1648                 MacroAssembler::Address(structureGPR, Structure::globalObjectOffset()), 
1649                 MacroAssembler::TrustedImmPtr(m_jit.graph().globalObjectFor(m_currentNode->codeOrigin))));
1650
1651         isNotMasqueradesAsUndefined.link(&m_jit);
1652     }
1653     m_jit.move(TrustedImm32(0), resultPayloadGPR);
1654     MacroAssembler::Jump done = m_jit.jump();
1655     
1656     notCell.link(&m_jit);
1657  
1658     COMPILE_ASSERT((JSValue::UndefinedTag | 1) == JSValue::NullTag, UndefinedTag_OR_1_EQUALS_NullTag);
1659     if (needsTypeCheck(nodeUse, SpecCell | SpecOther)) {
1660         m_jit.move(valueTagGPR, resultPayloadGPR);
1661         m_jit.or32(TrustedImm32(1), resultPayloadGPR);
1662         typeCheck(
1663             JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, SpecCell | SpecOther,
1664             m_jit.branch32(
1665                 MacroAssembler::NotEqual, 
1666                 resultPayloadGPR, 
1667                 TrustedImm32(JSValue::NullTag)));
1668     }
1669     m_jit.move(TrustedImm32(1), resultPayloadGPR);
1670     
1671     done.link(&m_jit);
1672     
1673     booleanResult(resultPayloadGPR, m_currentNode);
1674 }
1675
1676 void SpeculativeJIT::compileLogicalNot(Node* node)
1677 {
1678     switch (node->child1().useKind()) {
1679     case BooleanUse: {
1680         SpeculateBooleanOperand value(this, node->child1());
1681         GPRTemporary result(this, value);
1682         m_jit.xor32(TrustedImm32(1), value.gpr(), result.gpr());
1683         booleanResult(result.gpr(), node);
1684         return;
1685     }
1686         
1687     case ObjectOrOtherUse: {
1688         compileObjectOrOtherLogicalNot(node->child1());
1689         return;
1690     }
1691         
1692     case Int32Use: {
1693         SpeculateIntegerOperand value(this, node->child1());
1694         GPRTemporary resultPayload(this, value);
1695         m_jit.compare32(MacroAssembler::Equal, value.gpr(), MacroAssembler::TrustedImm32(0), resultPayload.gpr());
1696         booleanResult(resultPayload.gpr(), node);
1697         return;
1698     }
1699         
1700     case NumberUse: {
1701         SpeculateDoubleOperand value(this, node->child1());
1702         FPRTemporary scratch(this);
1703         GPRTemporary resultPayload(this);
1704         m_jit.move(TrustedImm32(0), resultPayload.gpr());
1705         MacroAssembler::Jump nonZero = m_jit.branchDoubleNonZero(value.fpr(), scratch.fpr());
1706         m_jit.move(TrustedImm32(1), resultPayload.gpr());
1707         nonZero.link(&m_jit);
1708         booleanResult(resultPayload.gpr(), node);
1709         return;
1710     }
1711
1712     case UntypedUse: {
1713         JSValueOperand arg1(this, node->child1());
1714         GPRTemporary resultPayload(this, arg1, false);
1715         GPRReg arg1TagGPR = arg1.tagGPR();
1716         GPRReg arg1PayloadGPR = arg1.payloadGPR();
1717         GPRReg resultPayloadGPR = resultPayload.gpr();
1718         
1719         arg1.use();
1720
1721         JITCompiler::Jump slowCase = m_jit.branch32(JITCompiler::NotEqual, arg1TagGPR, TrustedImm32(JSValue::BooleanTag));
1722     
1723         m_jit.move(arg1PayloadGPR, resultPayloadGPR);
1724
1725         addSlowPathGenerator(
1726             slowPathCall(
1727                 slowCase, this, dfgConvertJSValueToBoolean, resultPayloadGPR, arg1TagGPR,
1728                 arg1PayloadGPR));
1729     
1730         m_jit.xor32(TrustedImm32(1), resultPayloadGPR);
1731         booleanResult(resultPayloadGPR, node, UseChildrenCalledExplicitly);
1732         return;
1733     }
1734         
1735     default:
1736         RELEASE_ASSERT_NOT_REACHED();
1737         break;
1738     }
1739 }
1740
1741 void SpeculativeJIT::emitObjectOrOtherBranch(Edge nodeUse, BasicBlock* taken, BasicBlock* notTaken)
1742 {
1743     JSValueOperand value(this, nodeUse, ManualOperandSpeculation);
1744     GPRTemporary scratch(this);
1745     GPRReg valueTagGPR = value.tagGPR();
1746     GPRReg valuePayloadGPR = value.payloadGPR();
1747     GPRReg scratchGPR = scratch.gpr();
1748     
1749     MacroAssembler::Jump notCell = m_jit.branch32(MacroAssembler::NotEqual, valueTagGPR, TrustedImm32(JSValue::CellTag));
1750     if (masqueradesAsUndefinedWatchpointIsStillValid()) {
1751         speculationWatchpointForMasqueradesAsUndefined();
1752         DFG_TYPE_CHECK(
1753             JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, (~SpecCell) | SpecObject,
1754             m_jit.branchPtr(
1755                 MacroAssembler::Equal, 
1756                 MacroAssembler::Address(valuePayloadGPR, JSCell::structureOffset()), 
1757                 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1758     } else {
1759         m_jit.loadPtr(MacroAssembler::Address(valuePayloadGPR, JSCell::structureOffset()), scratchGPR);
1760
1761         DFG_TYPE_CHECK(
1762             JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, (~SpecCell) | SpecObject,
1763             m_jit.branchPtr(
1764                 MacroAssembler::Equal, 
1765                 scratchGPR,
1766                 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1767
1768         JITCompiler::Jump isNotMasqueradesAsUndefined = m_jit.branchTest8(JITCompiler::Zero, MacroAssembler::Address(scratchGPR, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined));
1769
1770         speculationCheck(BadType, JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse,
1771             m_jit.branchPtr(
1772                 MacroAssembler::Equal, 
1773                 MacroAssembler::Address(scratchGPR, Structure::globalObjectOffset()), 
1774                 MacroAssembler::TrustedImmPtr(m_jit.graph().globalObjectFor(m_currentNode->codeOrigin))));
1775
1776         isNotMasqueradesAsUndefined.link(&m_jit);
1777     }
1778     jump(taken, ForceJump);
1779     
1780     notCell.link(&m_jit);
1781     
1782     COMPILE_ASSERT((JSValue::UndefinedTag | 1) == JSValue::NullTag, UndefinedTag_OR_1_EQUALS_NullTag);
1783     if (needsTypeCheck(nodeUse, SpecCell | SpecOther)) {
1784         m_jit.move(valueTagGPR, scratchGPR);
1785         m_jit.or32(TrustedImm32(1), scratchGPR);
1786         typeCheck(
1787             JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, SpecCell | SpecOther,
1788             m_jit.branch32(MacroAssembler::NotEqual, scratchGPR, TrustedImm32(JSValue::NullTag)));
1789     }
1790
1791     jump(notTaken);
1792     
1793     noResult(m_currentNode);
1794 }
1795
1796 void SpeculativeJIT::emitBranch(Node* node)
1797 {
1798     BasicBlock* taken = node->takenBlock();
1799     BasicBlock* notTaken = node->notTakenBlock();
1800
1801     switch (node->child1().useKind()) {
1802     case BooleanUse: {
1803         SpeculateBooleanOperand value(this, node->child1());
1804         MacroAssembler::ResultCondition condition = MacroAssembler::NonZero;
1805
1806         if (taken == nextBlock()) {
1807             condition = MacroAssembler::Zero;
1808             BasicBlock* tmp = taken;
1809             taken = notTaken;
1810             notTaken = tmp;
1811         }
1812
1813         branchTest32(condition, value.gpr(), TrustedImm32(1), taken);
1814         jump(notTaken);
1815
1816         noResult(node);
1817         return;
1818     }
1819     
1820     case ObjectOrOtherUse: {
1821         emitObjectOrOtherBranch(node->child1(), taken, notTaken);
1822         return;
1823     }
1824     
1825     case NumberUse:
1826     case Int32Use: {
1827         if (node->child1().useKind() == Int32Use) {
1828             bool invert = false;
1829             
1830             if (taken == nextBlock()) {
1831                 invert = true;
1832                 BasicBlock* tmp = taken;
1833                 taken = notTaken;
1834                 notTaken = tmp;
1835             }
1836
1837             SpeculateIntegerOperand value(this, node->child1());
1838             branchTest32(invert ? MacroAssembler::Zero : MacroAssembler::NonZero, value.gpr(), taken);
1839         } else {
1840             SpeculateDoubleOperand value(this, node->child1());
1841             FPRTemporary scratch(this);
1842             branchDoubleNonZero(value.fpr(), scratch.fpr(), taken);
1843         }
1844         
1845         jump(notTaken);
1846         
1847         noResult(node);
1848         return;
1849     }
1850     
1851     case UntypedUse: {
1852         JSValueOperand value(this, node->child1());
1853         value.fill();
1854         GPRReg valueTagGPR = value.tagGPR();
1855         GPRReg valuePayloadGPR = value.payloadGPR();
1856
1857         GPRTemporary result(this);
1858         GPRReg resultGPR = result.gpr();
1859     
1860         use(node->child1());
1861     
1862         JITCompiler::Jump fastPath = m_jit.branch32(JITCompiler::Equal, valueTagGPR, JITCompiler::TrustedImm32(JSValue::Int32Tag));
1863         JITCompiler::Jump slowPath = m_jit.branch32(JITCompiler::NotEqual, valueTagGPR, JITCompiler::TrustedImm32(JSValue::BooleanTag));
1864
1865         fastPath.link(&m_jit);
1866         branchTest32(JITCompiler::Zero, valuePayloadGPR, notTaken);
1867         jump(taken, ForceJump);
1868
1869         slowPath.link(&m_jit);
1870         silentSpillAllRegisters(resultGPR);
1871         callOperation(dfgConvertJSValueToBoolean, resultGPR, valueTagGPR, valuePayloadGPR);
1872         silentFillAllRegisters(resultGPR);
1873     
1874         branchTest32(JITCompiler::NonZero, resultGPR, taken);
1875         jump(notTaken);
1876     
1877         noResult(node, UseChildrenCalledExplicitly);
1878         return;
1879     }
1880         
1881     default:
1882         RELEASE_ASSERT_NOT_REACHED();
1883         break;
1884     }
1885 }
1886
1887 template<typename BaseOperandType, typename PropertyOperandType, typename ValueOperandType, typename TagType>
1888 void SpeculativeJIT::compileContiguousPutByVal(Node* node, BaseOperandType& base, PropertyOperandType& property, ValueOperandType& value, GPRReg valuePayloadReg, TagType valueTag)
1889 {
1890     Edge child4 = m_jit.graph().varArgChild(node, 3);
1891
1892     ArrayMode arrayMode = node->arrayMode();
1893     
1894     GPRReg baseReg = base.gpr();
1895     GPRReg propertyReg = property.gpr();
1896     
1897     StorageOperand storage(this, child4);
1898     GPRReg storageReg = storage.gpr();
1899
1900     if (node->op() == PutByValAlias) {
1901         // Store the value to the array.
1902         GPRReg propertyReg = property.gpr();
1903         m_jit.store32(valueTag, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
1904         m_jit.store32(valuePayloadReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
1905         
1906         noResult(node);
1907         return;
1908     }
1909     
1910     MacroAssembler::Jump slowCase;
1911
1912     if (arrayMode.isInBounds()) {
1913         speculationCheck(
1914             StoreToHoleOrOutOfBounds, JSValueRegs(), 0,
1915             m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
1916     } else {
1917         MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
1918         
1919         slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfVectorLength()));
1920         
1921         if (!arrayMode.isOutOfBounds())
1922             speculationCheck(OutOfBounds, JSValueRegs(), 0, slowCase);
1923         
1924         m_jit.add32(TrustedImm32(1), propertyReg);
1925         m_jit.store32(propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
1926         m_jit.sub32(TrustedImm32(1), propertyReg);
1927         
1928         inBounds.link(&m_jit);
1929     }
1930     
1931     m_jit.store32(valueTag, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
1932     m_jit.store32(valuePayloadReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
1933     
1934     base.use();
1935     property.use();
1936     value.use();
1937     storage.use();
1938     
1939     if (arrayMode.isOutOfBounds()) {
1940         addSlowPathGenerator(
1941             slowPathCall(
1942                 slowCase, this,
1943                 m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
1944                 NoResult, baseReg, propertyReg, valueTag, valuePayloadReg));
1945     }
1946
1947     noResult(node, UseChildrenCalledExplicitly);    
1948 }
1949
1950 void SpeculativeJIT::compile(Node* node)
1951 {
1952     NodeType op = node->op();
1953
1954 #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
1955     m_jit.clearRegisterAllocationOffsets();
1956 #endif
1957
1958     switch (op) {
1959     case JSConstant:
1960         initConstantInfo(node);
1961         break;
1962
1963     case PhantomArguments:
1964         initConstantInfo(node);
1965         break;
1966
1967     case WeakJSConstant:
1968         m_jit.addWeakReference(node->weakConstant());
1969         initConstantInfo(node);
1970         break;
1971
1972     case Identity: {
1973         RELEASE_ASSERT_NOT_REACHED();
1974         break;
1975     }
1976
1977     case GetLocal: {
1978         SpeculatedType prediction = node->variableAccessData()->prediction();
1979         AbstractValue& value = m_state.variables().operand(node->local());
1980
1981         // If we have no prediction for this local, then don't attempt to compile.
1982         if (prediction == SpecNone) {
1983             terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
1984             break;
1985         }
1986         
1987         // If the CFA is tracking this variable and it found that the variable
1988         // cannot have been assigned, then don't attempt to proceed.
1989         if (value.isClear()) {
1990             // FIXME: We should trap instead.
1991             // https://bugs.webkit.org/show_bug.cgi?id=110383
1992             terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
1993             break;
1994         }
1995         
1996         if (node->variableAccessData()->shouldUseDoubleFormat()) {
1997             FPRTemporary result(this);
1998             m_jit.loadDouble(JITCompiler::addressFor(node->local()), result.fpr());
1999             VirtualRegister virtualRegister = node->virtualRegister();
2000             m_fprs.retain(result.fpr(), virtualRegister, SpillOrderDouble);
2001             m_generationInfo[virtualRegister].initDouble(node, node->refCount(), result.fpr());
2002             break;
2003         }
2004         
2005         if (isInt32Speculation(value.m_type)) {
2006             GPRTemporary result(this);
2007             m_jit.load32(JITCompiler::payloadFor(node->local()), result.gpr());
2008             
2009             // Like integerResult, but don't useChildren - our children are phi nodes,
2010             // and don't represent values within this dataflow with virtual registers.
2011             VirtualRegister virtualRegister = node->virtualRegister();
2012             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderInteger);
2013             m_generationInfo[virtualRegister].initInteger(node, node->refCount(), result.gpr());
2014             break;
2015         }
2016         
2017         if (isCellSpeculation(value.m_type)) {
2018             GPRTemporary result(this);
2019             m_jit.load32(JITCompiler::payloadFor(node->local()), result.gpr());
2020             
2021             // Like cellResult, but don't useChildren - our children are phi nodes,
2022             // and don't represent values within this dataflow with virtual registers.
2023             VirtualRegister virtualRegister = node->virtualRegister();
2024             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderCell);
2025             m_generationInfo[virtualRegister].initCell(node, node->refCount(), result.gpr());
2026             break;
2027         }
2028         
2029         if (isBooleanSpeculation(value.m_type)) {
2030             GPRTemporary result(this);
2031             m_jit.load32(JITCompiler::payloadFor(node->local()), result.gpr());
2032             
2033             // Like booleanResult, but don't useChildren - our children are phi nodes,
2034             // and don't represent values within this dataflow with virtual registers.
2035             VirtualRegister virtualRegister = node->virtualRegister();
2036             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderBoolean);
2037             m_generationInfo[virtualRegister].initBoolean(node, node->refCount(), result.gpr());
2038             break;
2039         }
2040
2041         GPRTemporary result(this);
2042         GPRTemporary tag(this);
2043         m_jit.load32(JITCompiler::payloadFor(node->local()), result.gpr());
2044         m_jit.load32(JITCompiler::tagFor(node->local()), tag.gpr());
2045
2046         // Like jsValueResult, but don't useChildren - our children are phi nodes,
2047         // and don't represent values within this dataflow with virtual registers.
2048         VirtualRegister virtualRegister = node->virtualRegister();
2049         m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
2050         m_gprs.retain(tag.gpr(), virtualRegister, SpillOrderJS);
2051
2052         m_generationInfo[virtualRegister].initJSValue(node, node->refCount(), tag.gpr(), result.gpr(), DataFormatJS);
2053         break;
2054     }
2055         
2056     case GetLocalUnlinked: {
2057         GPRTemporary payload(this);
2058         GPRTemporary tag(this);
2059         m_jit.load32(JITCompiler::payloadFor(node->unlinkedLocal()), payload.gpr());
2060         m_jit.load32(JITCompiler::tagFor(node->unlinkedLocal()), tag.gpr());
2061         jsValueResult(tag.gpr(), payload.gpr(), node);
2062         break;
2063     }
2064
2065     case MovHintAndCheck: {
2066         compileMovHintAndCheck(node);
2067         break;
2068     }
2069         
2070     case InlineStart: {
2071         compileInlineStart(node);
2072         break;
2073     }
2074
2075     case MovHint:
2076     case ZombieHint: {
2077         RELEASE_ASSERT_NOT_REACHED();
2078         break;
2079     }
2080
2081     case SetLocal: {
2082         // SetLocal doubles as a hint as to where a node will be stored and
2083         // as a speculation point. So before we speculate make sure that we
2084         // know where the child of this node needs to go in the virtual
2085         // stack.
2086         compileMovHint(node);
2087         
2088         if (node->variableAccessData()->shouldUnboxIfPossible()) {
2089             if (node->variableAccessData()->shouldUseDoubleFormat()) {
2090                 SpeculateDoubleOperand value(this, node->child1());
2091                 m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node->local()));
2092                 noResult(node);
2093                 // Indicate that it's no longer necessary to retrieve the value of
2094                 // this bytecode variable from registers or other locations in the stack,
2095                 // but that it is stored as a double.
2096                 recordSetLocal(node->local(), ValueSource(DoubleInJSStack));
2097                 break;
2098             }
2099             SpeculatedType predictedType = node->variableAccessData()->argumentAwarePrediction();
2100             if (m_generationInfo[node->child1()->virtualRegister()].registerFormat() == DataFormatDouble) {
2101                 SpeculateDoubleOperand value(this, node->child1(), ManualOperandSpeculation);
2102                 m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node->local()));
2103                 noResult(node);
2104                 recordSetLocal(node->local(), ValueSource(DoubleInJSStack));
2105                 break;
2106             }
2107             if (isInt32Speculation(predictedType)) {
2108                 SpeculateIntegerOperand value(this, node->child1());
2109                 m_jit.store32(value.gpr(), JITCompiler::payloadFor(node->local()));
2110                 noResult(node);
2111                 recordSetLocal(node->local(), ValueSource(Int32InJSStack));
2112                 break;
2113             }
2114             if (isCellSpeculation(predictedType)) {
2115                 SpeculateCellOperand cell(this, node->child1());
2116                 GPRReg cellGPR = cell.gpr();
2117                 m_jit.storePtr(cellGPR, JITCompiler::payloadFor(node->local()));
2118                 noResult(node);
2119                 recordSetLocal(node->local(), ValueSource(CellInJSStack));
2120                 break;
2121             }
2122             if (isBooleanSpeculation(predictedType)) {
2123                 SpeculateBooleanOperand value(this, node->child1());
2124                 m_jit.store32(value.gpr(), JITCompiler::payloadFor(node->local()));
2125                 noResult(node);
2126                 recordSetLocal(node->local(), ValueSource(BooleanInJSStack));
2127                 break;
2128             }
2129         }
2130         JSValueOperand value(this, node->child1());
2131         m_jit.store32(value.payloadGPR(), JITCompiler::payloadFor(node->local()));
2132         m_jit.store32(value.tagGPR(), JITCompiler::tagFor(node->local()));
2133         noResult(node);
2134         recordSetLocal(node->local(), ValueSource(ValueInJSStack));
2135
2136         // If we're storing an arguments object that has been optimized away,
2137         // our variable event stream for OSR exit now reflects the optimized
2138         // value (JSValue()). On the slow path, we want an arguments object
2139         // instead. We add an additional move hint to show OSR exit that it
2140         // needs to reconstruct the arguments object.
2141         if (node->child1()->op() == PhantomArguments)
2142             compileMovHint(node);
2143
2144         break;
2145     }
2146
2147     case SetArgument:
2148         // This is a no-op; it just marks the fact that the argument is being used.
2149         // But it may be profitable to use this as a hook to run speculation checks
2150         // on arguments, thereby allowing us to trivially eliminate such checks if
2151         // the argument is not used.
2152         break;
2153
2154     case BitAnd:
2155     case BitOr:
2156     case BitXor:
2157         if (isInt32Constant(node->child1().node())) {
2158             SpeculateIntegerOperand op2(this, node->child2());
2159             GPRTemporary result(this, op2);
2160
2161             bitOp(op, valueOfInt32Constant(node->child1().node()), op2.gpr(), result.gpr());
2162
2163             integerResult(result.gpr(), node);
2164         } else if (isInt32Constant(node->child2().node())) {
2165             SpeculateIntegerOperand op1(this, node->child1());
2166             GPRTemporary result(this, op1);
2167
2168             bitOp(op, valueOfInt32Constant(node->child2().node()), op1.gpr(), result.gpr());
2169
2170             integerResult(result.gpr(), node);
2171         } else {
2172             SpeculateIntegerOperand op1(this, node->child1());
2173             SpeculateIntegerOperand op2(this, node->child2());
2174             GPRTemporary result(this, op1, op2);
2175
2176             GPRReg reg1 = op1.gpr();
2177             GPRReg reg2 = op2.gpr();
2178             bitOp(op, reg1, reg2, result.gpr());
2179
2180             integerResult(result.gpr(), node);
2181         }
2182         break;
2183
2184     case BitRShift:
2185     case BitLShift:
2186     case BitURShift:
2187         if (isInt32Constant(node->child2().node())) {
2188             SpeculateIntegerOperand op1(this, node->child1());
2189             GPRTemporary result(this, op1);
2190
2191             shiftOp(op, op1.gpr(), valueOfInt32Constant(node->child2().node()) & 0x1f, result.gpr());
2192
2193             integerResult(result.gpr(), node);
2194         } else {
2195             // Do not allow shift amount to be used as the result, MacroAssembler does not permit this.
2196             SpeculateIntegerOperand op1(this, node->child1());
2197             SpeculateIntegerOperand op2(this, node->child2());
2198             GPRTemporary result(this, op1);
2199
2200             GPRReg reg1 = op1.gpr();
2201             GPRReg reg2 = op2.gpr();
2202             shiftOp(op, reg1, reg2, result.gpr());
2203
2204             integerResult(result.gpr(), node);
2205         }
2206         break;
2207
2208     case UInt32ToNumber: {
2209         compileUInt32ToNumber(node);
2210         break;
2211     }
2212         
2213     case DoubleAsInt32: {
2214         compileDoubleAsInt32(node);
2215         break;
2216     }
2217
2218     case ValueToInt32: {
2219         compileValueToInt32(node);
2220         break;
2221     }
2222         
2223     case Int32ToDouble:
2224     case ForwardInt32ToDouble: {
2225         compileInt32ToDouble(node);
2226         break;
2227     }
2228         
2229     case ValueAdd:
2230     case ArithAdd:
2231         compileAdd(node);
2232         break;
2233
2234     case MakeRope:
2235         compileMakeRope(node);
2236         break;
2237
2238     case ArithSub:
2239         compileArithSub(node);
2240         break;
2241
2242     case ArithNegate:
2243         compileArithNegate(node);
2244         break;
2245
2246     case ArithMul:
2247         compileArithMul(node);
2248         break;
2249
2250     case ArithIMul:
2251         compileArithIMul(node);
2252         break;
2253
2254     case ArithDiv: {
2255         compileArithDiv(node);
2256         break;
2257     }
2258
2259     case ArithMod: {
2260         compileArithMod(node);
2261         break;
2262     }
2263
2264     case ArithAbs: {
2265         switch (node->child1().useKind()) {
2266         case Int32Use: {
2267             SpeculateStrictInt32Operand op1(this, node->child1());
2268             GPRTemporary result(this, op1);
2269             GPRTemporary scratch(this);
2270             
2271             m_jit.move(op1.gpr(), result.gpr());
2272             m_jit.rshift32(result.gpr(), MacroAssembler::TrustedImm32(31), scratch.gpr());
2273             m_jit.add32(scratch.gpr(), result.gpr());
2274             m_jit.xor32(scratch.gpr(), result.gpr());
2275             speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::Equal, result.gpr(), MacroAssembler::TrustedImm32(1 << 31)));
2276             integerResult(result.gpr(), node);
2277             break;
2278         }
2279         
2280             
2281         case NumberUse: {
2282             SpeculateDoubleOperand op1(this, node->child1());
2283             FPRTemporary result(this);
2284             
2285             m_jit.absDouble(op1.fpr(), result.fpr());
2286             doubleResult(result.fpr(), node);
2287             break;
2288         }
2289             
2290         default:
2291             RELEASE_ASSERT_NOT_REACHED();
2292             break;
2293         }
2294         break;
2295     }
2296         
2297     case ArithMin:
2298     case ArithMax: {
2299         switch (node->binaryUseKind()) {
2300         case Int32Use: {
2301             SpeculateStrictInt32Operand op1(this, node->child1());
2302             SpeculateStrictInt32Operand op2(this, node->child2());
2303             GPRTemporary result(this, op1);
2304
2305             GPRReg op1GPR = op1.gpr();
2306             GPRReg op2GPR = op2.gpr();
2307             GPRReg resultGPR = result.gpr();
2308
2309             MacroAssembler::Jump op1Less = m_jit.branch32(op == ArithMin ? MacroAssembler::LessThan : MacroAssembler::GreaterThan, op1GPR, op2GPR);
2310             m_jit.move(op2GPR, resultGPR);
2311             if (op1GPR != resultGPR) {
2312                 MacroAssembler::Jump done = m_jit.jump();
2313                 op1Less.link(&m_jit);
2314                 m_jit.move(op1GPR, resultGPR);
2315                 done.link(&m_jit);
2316             } else
2317                 op1Less.link(&m_jit);
2318             
2319             integerResult(resultGPR, node);
2320             break;
2321         }
2322         
2323         case NumberUse: {
2324             SpeculateDoubleOperand op1(this, node->child1());
2325             SpeculateDoubleOperand op2(this, node->child2());
2326             FPRTemporary result(this, op1);
2327
2328             FPRReg op1FPR = op1.fpr();
2329             FPRReg op2FPR = op2.fpr();
2330             FPRReg resultFPR = result.fpr();
2331
2332             MacroAssembler::JumpList done;
2333         
2334             MacroAssembler::Jump op1Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleLessThan : MacroAssembler::DoubleGreaterThan, op1FPR, op2FPR);
2335         
2336             // op2 is eather the lesser one or one of then is NaN
2337             MacroAssembler::Jump op2Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleGreaterThanOrEqual : MacroAssembler::DoubleLessThanOrEqual, op1FPR, op2FPR);
2338         
2339             // Unordered case. We don't know which of op1, op2 is NaN. Manufacture NaN by adding 
2340             // op1 + op2 and putting it into result.
2341             m_jit.addDouble(op1FPR, op2FPR, resultFPR);
2342             done.append(m_jit.jump());
2343         
2344             op2Less.link(&m_jit);
2345             m_jit.moveDouble(op2FPR, resultFPR);
2346         
2347             if (op1FPR != resultFPR) {
2348                 done.append(m_jit.jump());
2349             
2350                 op1Less.link(&m_jit);
2351                 m_jit.moveDouble(op1FPR, resultFPR);
2352             } else
2353                 op1Less.link(&m_jit);
2354         
2355             done.link(&m_jit);
2356         
2357             doubleResult(resultFPR, node);
2358             break;
2359         }
2360             
2361         default:
2362             RELEASE_ASSERT_NOT_REACHED();
2363             break;
2364         }
2365         break;
2366     }
2367         
2368     case ArithSqrt: {
2369         SpeculateDoubleOperand op1(this, node->child1());
2370         FPRTemporary result(this, op1);
2371         
2372         m_jit.sqrtDouble(op1.fpr(), result.fpr());
2373         
2374         doubleResult(result.fpr(), node);
2375         break;
2376     }
2377
2378     case LogicalNot:
2379         compileLogicalNot(node);
2380         break;
2381
2382     case CompareLess:
2383         if (compare(node, JITCompiler::LessThan, JITCompiler::DoubleLessThan, operationCompareLess))
2384             return;
2385         break;
2386
2387     case CompareLessEq:
2388         if (compare(node, JITCompiler::LessThanOrEqual, JITCompiler::DoubleLessThanOrEqual, operationCompareLessEq))
2389             return;
2390         break;
2391
2392     case CompareGreater:
2393         if (compare(node, JITCompiler::GreaterThan, JITCompiler::DoubleGreaterThan, operationCompareGreater))
2394             return;
2395         break;
2396
2397     case CompareGreaterEq:
2398         if (compare(node, JITCompiler::GreaterThanOrEqual, JITCompiler::DoubleGreaterThanOrEqual, operationCompareGreaterEq))
2399             return;
2400         break;
2401         
2402     case CompareEqConstant:
2403         ASSERT(isNullConstant(node->child2().node()));
2404         if (nonSpeculativeCompareNull(node, node->child1()))
2405             return;
2406         break;
2407
2408     case CompareEq:
2409         if (compare(node, JITCompiler::Equal, JITCompiler::DoubleEqual, operationCompareEq))
2410             return;
2411         break;
2412
2413     case CompareStrictEqConstant:
2414         if (compileStrictEqForConstant(node, node->child1(), valueOfJSConstant(node->child2().node())))
2415             return;
2416         break;
2417
2418     case CompareStrictEq:
2419         if (compileStrictEq(node))
2420             return;
2421         break;
2422
2423     case StringCharCodeAt: {
2424         compileGetCharCodeAt(node);
2425         break;
2426     }
2427
2428     case StringCharAt: {
2429         // Relies on StringCharAt node having same basic layout as GetByVal
2430         compileGetByValOnString(node);
2431         break;
2432     }
2433
2434     case StringFromCharCode: {
2435         compileFromCharCode(node);
2436         break;
2437     }
2438         
2439     case ForwardCheckArray:
2440     case CheckArray: {
2441         checkArray(node);
2442         break;
2443     }
2444         
2445     case Arrayify:
2446     case ArrayifyToStructure: {
2447         arrayify(node);
2448         break;
2449     }
2450
2451     case GetByVal: {
2452         switch (node->arrayMode().type()) {
2453         case Array::SelectUsingPredictions:
2454         case Array::ForceExit:
2455             RELEASE_ASSERT_NOT_REACHED();
2456             terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
2457             break;
2458         case Array::Generic: {
2459             SpeculateCellOperand base(this, node->child1()); // Save a register, speculate cell. We'll probably be right.
2460             JSValueOperand property(this, node->child2());
2461             GPRReg baseGPR = base.gpr();
2462             GPRReg propertyTagGPR = property.tagGPR();
2463             GPRReg propertyPayloadGPR = property.payloadGPR();
2464             
2465             flushRegisters();
2466             GPRResult2 resultTag(this);
2467             GPRResult resultPayload(this);
2468             callOperation(operationGetByValCell, resultTag.gpr(), resultPayload.gpr(), baseGPR, propertyTagGPR, propertyPayloadGPR);
2469             
2470             jsValueResult(resultTag.gpr(), resultPayload.gpr(), node);
2471             break;
2472         }
2473         case Array::Int32:
2474         case Array::Contiguous: {
2475             if (node->arrayMode().isInBounds()) {
2476                 SpeculateStrictInt32Operand property(this, node->child2());
2477                 StorageOperand storage(this, node->child3());
2478             
2479                 GPRReg propertyReg = property.gpr();
2480                 GPRReg storageReg = storage.gpr();
2481             
2482                 if (!m_compileOkay)
2483                     return;
2484             
2485                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2486             
2487                 GPRTemporary resultPayload(this);
2488                 if (node->arrayMode().type() == Array::Int32) {
2489                     speculationCheck(
2490                         OutOfBounds, JSValueRegs(), 0,
2491                         m_jit.branch32(
2492                             MacroAssembler::Equal,
2493                             MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)),
2494                             TrustedImm32(JSValue::EmptyValueTag)));
2495                     m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload.gpr());
2496                     integerResult(resultPayload.gpr(), node);
2497                     break;
2498                 }
2499                 
2500                 GPRTemporary resultTag(this);
2501                 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag.gpr());
2502                 speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::Equal, resultTag.gpr(), TrustedImm32(JSValue::EmptyValueTag)));
2503                 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload.gpr());
2504                 jsValueResult(resultTag.gpr(), resultPayload.gpr(), node);
2505                 break;
2506             }
2507
2508             SpeculateCellOperand base(this, node->child1());
2509             SpeculateStrictInt32Operand property(this, node->child2());
2510             StorageOperand storage(this, node->child3());
2511             
2512             GPRReg baseReg = base.gpr();
2513             GPRReg propertyReg = property.gpr();
2514             GPRReg storageReg = storage.gpr();
2515             
2516             if (!m_compileOkay)
2517                 return;
2518             
2519             GPRTemporary resultTag(this);
2520             GPRTemporary resultPayload(this);
2521             GPRReg resultTagReg = resultTag.gpr();
2522             GPRReg resultPayloadReg = resultPayload.gpr();
2523             
2524             MacroAssembler::JumpList slowCases;
2525
2526             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2527             
2528             m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTagReg);
2529             m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayloadReg);
2530             slowCases.append(m_jit.branch32(MacroAssembler::Equal, resultTagReg, TrustedImm32(JSValue::EmptyValueTag)));
2531             
2532             addSlowPathGenerator(
2533                 slowPathCall(
2534                     slowCases, this, operationGetByValArrayInt,
2535                     JSValueRegs(resultTagReg, resultPayloadReg), baseReg, propertyReg));
2536             
2537             jsValueResult(resultTagReg, resultPayloadReg, node);
2538             break;
2539         }
2540         case Array::Double: {
2541             if (node->arrayMode().isInBounds()) {
2542                 if (node->arrayMode().isSaneChain()) {
2543                     JSGlobalObject* globalObject = m_jit.globalObjectFor(node->codeOrigin);
2544                     ASSERT(globalObject->arrayPrototypeChainIsSane());
2545                     m_jit.addLazily(
2546                         speculationWatchpoint(),
2547                         globalObject->arrayPrototype()->structure()->transitionWatchpointSet());
2548                     m_jit.addLazily(
2549                         speculationWatchpoint(),
2550                         globalObject->objectPrototype()->structure()->transitionWatchpointSet());
2551                 }
2552                 
2553                 SpeculateStrictInt32Operand property(this, node->child2());
2554                 StorageOperand storage(this, node->child3());
2555             
2556                 GPRReg propertyReg = property.gpr();
2557                 GPRReg storageReg = storage.gpr();
2558             
2559                 if (!m_compileOkay)
2560                     return;
2561             
2562                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2563             
2564                 FPRTemporary result(this);
2565                 m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.fpr());
2566                 if (!node->arrayMode().isSaneChain())
2567                     speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, result.fpr(), result.fpr()));
2568                 doubleResult(result.fpr(), node);
2569                 break;
2570             }
2571
2572             SpeculateCellOperand base(this, node->child1());
2573             SpeculateStrictInt32Operand property(this, node->child2());
2574             StorageOperand storage(this, node->child3());
2575             
2576             GPRReg baseReg = base.gpr();
2577             GPRReg propertyReg = property.gpr();
2578             GPRReg storageReg = storage.gpr();
2579             
2580             if (!m_compileOkay)
2581                 return;
2582             
2583             GPRTemporary resultTag(this);
2584             GPRTemporary resultPayload(this);
2585             FPRTemporary temp(this);
2586             GPRReg resultTagReg = resultTag.gpr();
2587             GPRReg resultPayloadReg = resultPayload.gpr();
2588             FPRReg tempReg = temp.fpr();
2589             
2590             MacroAssembler::JumpList slowCases;
2591             
2592             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2593             
2594             m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), tempReg);
2595             slowCases.append(m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, tempReg, tempReg));
2596             boxDouble(tempReg, resultTagReg, resultPayloadReg);
2597
2598             addSlowPathGenerator(
2599                 slowPathCall(
2600                     slowCases, this, operationGetByValArrayInt,
2601                     JSValueRegs(resultTagReg, resultPayloadReg), baseReg, propertyReg));
2602             
2603             jsValueResult(resultTagReg, resultPayloadReg, node);
2604             break;
2605         }
2606         case Array::ArrayStorage:
2607         case Array::SlowPutArrayStorage: {
2608             if (node->arrayMode().isInBounds()) {
2609                 SpeculateStrictInt32Operand property(this, node->child2());
2610                 StorageOperand storage(this, node->child3());
2611                 GPRReg propertyReg = property.gpr();
2612                 GPRReg storageReg = storage.gpr();
2613         
2614                 if (!m_compileOkay)
2615                     return;
2616
2617                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
2618
2619                 GPRTemporary resultTag(this);
2620                 GPRTemporary resultPayload(this);
2621
2622                 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag.gpr());
2623                 speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::Equal, resultTag.gpr(), TrustedImm32(JSValue::EmptyValueTag)));
2624                 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload.gpr());
2625             
2626                 jsValueResult(resultTag.gpr(), resultPayload.gpr(), node);
2627                 break;
2628             }
2629
2630             SpeculateCellOperand base(this, node->child1());
2631             SpeculateStrictInt32Operand property(this, node->child2());
2632             StorageOperand storage(this, node->child3());
2633             GPRReg propertyReg = property.gpr();
2634             GPRReg storageReg = storage.gpr();
2635             GPRReg baseReg = base.gpr();
2636
2637             if (!m_compileOkay)
2638                 return;
2639
2640             GPRTemporary resultTag(this);
2641             GPRTemporary resultPayload(this);
2642             GPRReg resultTagReg = resultTag.gpr();
2643             GPRReg resultPayloadReg = resultPayload.gpr();
2644
2645             JITCompiler::Jump outOfBounds = m_jit.branch32(
2646                 MacroAssembler::AboveOrEqual, propertyReg,
2647                 MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
2648
2649             m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTagReg);
2650             JITCompiler::Jump hole = m_jit.branch32(
2651                 MacroAssembler::Equal, resultTag.gpr(), TrustedImm32(JSValue::EmptyValueTag));
2652             m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayloadReg);
2653             
2654             JITCompiler::JumpList slowCases;
2655             slowCases.append(outOfBounds);
2656             slowCases.append(hole);
2657             addSlowPathGenerator(
2658                 slowPathCall(
2659                     slowCases, this, operationGetByValArrayInt,
2660                     JSValueRegs(resultTagReg, resultPayloadReg),
2661                     baseReg, propertyReg));
2662
2663             jsValueResult(resultTagReg, resultPayloadReg, node);
2664             break;
2665         }
2666         case Array::String:
2667             compileGetByValOnString(node);
2668             break;
2669         case Array::Arguments:
2670             compileGetByValOnArguments(node);
2671             break;
2672         case Array::Int8Array:
2673             compileGetByValOnIntTypedArray(m_jit.vm()->int8ArrayDescriptor(), node, sizeof(int8_t), SignedTypedArray);
2674             break;
2675         case Array::Int16Array:
2676             compileGetByValOnIntTypedArray(m_jit.vm()->int16ArrayDescriptor(), node, sizeof(int16_t), SignedTypedArray);
2677             break;
2678         case Array::Int32Array:
2679             compileGetByValOnIntTypedArray(m_jit.vm()->int32ArrayDescriptor(), node, sizeof(int32_t), SignedTypedArray);
2680             break;
2681         case Array::Uint8Array:
2682             compileGetByValOnIntTypedArray(m_jit.vm()->uint8ArrayDescriptor(), node, sizeof(uint8_t), UnsignedTypedArray);
2683             break;
2684         case Array::Uint8ClampedArray:
2685             compileGetByValOnIntTypedArray(m_jit.vm()->uint8ClampedArrayDescriptor(), node, sizeof(uint8_t), UnsignedTypedArray);
2686             break;
2687         case Array::Uint16Array:
2688             compileGetByValOnIntTypedArray(m_jit.vm()->uint16ArrayDescriptor(), node, sizeof(uint16_t), UnsignedTypedArray);
2689             break;
2690         case Array::Uint32Array:
2691             compileGetByValOnIntTypedArray(m_jit.vm()->uint32ArrayDescriptor(), node, sizeof(uint32_t), UnsignedTypedArray);
2692             break;
2693         case Array::Float32Array:
2694             compileGetByValOnFloatTypedArray(m_jit.vm()->float32ArrayDescriptor(), node, sizeof(float));
2695             break;
2696         case Array::Float64Array:
2697             compileGetByValOnFloatTypedArray(m_jit.vm()->float64ArrayDescriptor(), node, sizeof(double));
2698             break;
2699         default:
2700             RELEASE_ASSERT_NOT_REACHED();
2701             break;
2702         }
2703         break;
2704     }
2705
2706     case PutByVal:
2707     case PutByValAlias: {
2708         Edge child1 = m_jit.graph().varArgChild(node, 0);
2709         Edge child2 = m_jit.graph().varArgChild(node, 1);
2710         Edge child3 = m_jit.graph().varArgChild(node, 2);
2711         Edge child4 = m_jit.graph().varArgChild(node, 3);
2712         
2713         ArrayMode arrayMode = node->arrayMode().modeForPut();
2714         bool alreadyHandled = false;
2715         
2716         switch (arrayMode.type()) {
2717         case Array::SelectUsingPredictions:
2718         case Array::ForceExit:
2719             RELEASE_ASSERT_NOT_REACHED();
2720             terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
2721             alreadyHandled = true;
2722             break;
2723         case Array::Generic: {
2724             ASSERT(node->op() == PutByVal);
2725             
2726             SpeculateCellOperand base(this, child1); // Save a register, speculate cell. We'll probably be right.
2727             JSValueOperand property(this, child2);
2728             JSValueOperand value(this, child3);
2729             GPRReg baseGPR = base.gpr();
2730             GPRReg propertyTagGPR = property.tagGPR();
2731             GPRReg propertyPayloadGPR = property.payloadGPR();
2732             GPRReg valueTagGPR = value.tagGPR();
2733             GPRReg valuePayloadGPR = value.payloadGPR();
2734             
2735             flushRegisters();
2736             callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByValCellStrict : operationPutByValCellNonStrict, baseGPR, propertyTagGPR, propertyPayloadGPR, valueTagGPR, valuePayloadGPR);
2737             
2738             noResult(node);
2739             alreadyHandled = true;
2740             break;
2741         }
2742         default:
2743             break;
2744         }
2745         
2746         if (alreadyHandled)
2747             break;
2748         
2749         SpeculateCellOperand base(this, child1);
2750         SpeculateStrictInt32Operand property(this, child2);
2751         
2752         GPRReg baseReg = base.gpr();
2753         GPRReg propertyReg = property.gpr();
2754
2755         switch (arrayMode.type()) {
2756         case Array::Int32: {
2757             SpeculateIntegerOperand value(this, child3);
2758
2759             GPRReg valuePayloadReg = value.gpr();
2760         
2761             if (!m_compileOkay)
2762                 return;
2763             
2764             compileContiguousPutByVal(node, base, property, value, valuePayloadReg, TrustedImm32(JSValue::Int32Tag));
2765             break;
2766         }
2767         case Array::Contiguous: {
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             if (Heap::isWriteBarrierEnabled()) {
2777                 GPRTemporary scratch(this);
2778                 writeBarrier(baseReg, valueTagReg, child3, WriteBarrierForPropertyAccess, scratch.gpr());
2779             }
2780             
2781             compileContiguousPutByVal(node, base, property, value, valuePayloadReg, valueTagReg);
2782             break;
2783         }
2784         case Array::Double: {
2785             compileDoublePutByVal(node, base, property);
2786             break;
2787         }
2788         case Array::ArrayStorage:
2789         case Array::SlowPutArrayStorage: {
2790             JSValueOperand value(this, child3);
2791
2792             GPRReg valueTagReg = value.tagGPR();
2793             GPRReg valuePayloadReg = value.payloadGPR();
2794             
2795             if (!m_compileOkay)
2796                 return;
2797             
2798             {
2799                 GPRTemporary scratch(this);
2800                 GPRReg scratchReg = scratch.gpr();
2801                 writeBarrier(baseReg, valueTagReg, child3, WriteBarrierForPropertyAccess, scratchReg);
2802             }
2803             
2804             StorageOperand storage(this, child4);
2805             GPRReg storageReg = storage.gpr();
2806
2807             if (node->op() == PutByValAlias) {
2808                 // Store the value to the array.
2809                 GPRReg propertyReg = property.gpr();
2810                 m_jit.store32(value.tagGPR(), MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
2811                 m_jit.store32(value.payloadGPR(), MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
2812                 
2813                 noResult(node);
2814                 break;
2815             }
2816
2817             MacroAssembler::JumpList slowCases;
2818
2819             MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
2820             if (!arrayMode.isOutOfBounds())
2821                 speculationCheck(OutOfBounds, JSValueRegs(), 0, beyondArrayBounds);
2822             else
2823                 slowCases.append(beyondArrayBounds);
2824
2825             // Check if we're writing to a hole; if so increment m_numValuesInVector.
2826             if (arrayMode.isInBounds()) {
2827                 speculationCheck(
2828                     StoreToHole, JSValueRegs(), 0,
2829                     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)));
2830             } else {
2831                 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));
2832                 if (arrayMode.isSlowPut()) {
2833                     // This is sort of strange. If we wanted to optimize this code path, we would invert
2834                     // the above branch. But it's simply not worth it since this only happens if we're
2835                     // already having a bad time.
2836                     slowCases.append(m_jit.jump());
2837                 } else {
2838                     m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, ArrayStorage::numValuesInVectorOffset()));
2839                 
2840                     // If we're writing to a hole we might be growing the array; 
2841                     MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
2842                     m_jit.add32(TrustedImm32(1), propertyReg);
2843                     m_jit.store32(propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
2844                     m_jit.sub32(TrustedImm32(1), propertyReg);
2845                 
2846                     lengthDoesNotNeedUpdate.link(&m_jit);
2847                 }
2848                 notHoleValue.link(&m_jit);
2849             }
2850     
2851             // Store the value to the array.
2852             m_jit.store32(valueTagReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
2853             m_jit.store32(valuePayloadReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
2854
2855             base.use();
2856             property.use();
2857             value.use();
2858             storage.use();
2859             
2860             if (!slowCases.empty()) {
2861                 addSlowPathGenerator(
2862                     slowPathCall(
2863                         slowCases, this,
2864                         m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
2865                         NoResult, baseReg, propertyReg, valueTagReg, valuePayloadReg));
2866             }
2867
2868             noResult(node, UseChildrenCalledExplicitly);
2869             break;
2870         }
2871             
2872         case Array::Arguments:
2873             // FIXME: we could at some point make this work. Right now we're assuming that the register
2874             // pressure would be too great.
2875             RELEASE_ASSERT_NOT_REACHED();
2876             break;
2877             
2878         case Array::Int8Array:
2879             compilePutByValForIntTypedArray(m_jit.vm()->int8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int8_t), SignedTypedArray);
2880             break;
2881             
2882         case Array::Int16Array:
2883             compilePutByValForIntTypedArray(m_jit.vm()->int16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int16_t), SignedTypedArray);
2884             break;
2885             
2886         case Array::Int32Array:
2887             compilePutByValForIntTypedArray(m_jit.vm()->int32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int32_t), SignedTypedArray);
2888             break;
2889             
2890         case Array::Uint8Array:
2891             compilePutByValForIntTypedArray(m_jit.vm()->uint8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), UnsignedTypedArray);
2892             break;
2893             
2894         case Array::Uint8ClampedArray:
2895             compilePutByValForIntTypedArray(m_jit.vm()->uint8ClampedArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint8_t), UnsignedTypedArray, ClampRounding);
2896             break;
2897             
2898         case Array::Uint16Array:
2899             compilePutByValForIntTypedArray(m_jit.vm()->uint16ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint16_t), UnsignedTypedArray);
2900             break;
2901             
2902         case Array::Uint32Array:
2903             compilePutByValForIntTypedArray(m_jit.vm()->uint32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(uint32_t), UnsignedTypedArray);
2904             break;
2905             
2906         case Array::Float32Array:
2907             compilePutByValForFloatTypedArray(m_jit.vm()->float32ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(float));
2908             break;
2909             
2910         case Array::Float64Array:
2911             compilePutByValForFloatTypedArray(m_jit.vm()->float64ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(double));
2912             break;
2913             
2914         default:
2915             RELEASE_ASSERT_NOT_REACHED();
2916             break;
2917         }
2918         break;
2919     }
2920
2921     case RegExpExec: {
2922         if (compileRegExpExec(node))
2923             return;
2924
2925         if (!node->adjustedRefCount()) {
2926             SpeculateCellOperand base(this, node->child1());
2927             SpeculateCellOperand argument(this, node->child2());
2928             GPRReg baseGPR = base.gpr();
2929             GPRReg argumentGPR = argument.gpr();
2930             
2931             flushRegisters();
2932             GPRResult result(this);
2933             callOperation(operationRegExpTest, result.gpr(), baseGPR, argumentGPR);
2934             
2935             // Must use jsValueResult because otherwise we screw up register
2936             // allocation, which thinks that this node has a result.
2937             booleanResult(result.gpr(), node);
2938             break;
2939         }
2940
2941         SpeculateCellOperand base(this, node->child1());
2942         SpeculateCellOperand argument(this, node->child2());
2943         GPRReg baseGPR = base.gpr();
2944         GPRReg argumentGPR = argument.gpr();
2945         
2946         flushRegisters();
2947         GPRResult2 resultTag(this);
2948         GPRResult resultPayload(this);
2949         callOperation(operationRegExpExec, resultTag.gpr(), resultPayload.gpr(), baseGPR, argumentGPR);
2950         
2951         jsValueResult(resultTag.gpr(), resultPayload.gpr(), node);
2952         break;
2953     }
2954         
2955     case RegExpTest: {
2956         SpeculateCellOperand base(this, node->child1());
2957         SpeculateCellOperand argument(this, node->child2());
2958         GPRReg baseGPR = base.gpr();
2959         GPRReg argumentGPR = argument.gpr();
2960         
2961         flushRegisters();
2962         GPRResult result(this);
2963         callOperation(operationRegExpTest, result.gpr(), baseGPR, argumentGPR);
2964         
2965         // If we add a DataFormatBool, we should use it here.
2966         booleanResult(result.gpr(), node);
2967         break;
2968     }
2969         
2970     case ArrayPush: {
2971         ASSERT(node->arrayMode().isJSArray());
2972         
2973         SpeculateCellOperand base(this, node->child1());
2974         GPRTemporary storageLength(this);
2975         
2976         GPRReg baseGPR = base.gpr();
2977         GPRReg storageLengthGPR = storageLength.gpr();
2978         
2979         StorageOperand storage(this, node->child3());
2980         GPRReg storageGPR = storage.gpr();
2981         
2982         switch (node->arrayMode().type()) {
2983         case Array::Int32: {
2984             SpeculateIntegerOperand value(this, node->child2());
2985             GPRReg valuePayloadGPR = value.gpr();
2986             
2987             m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
2988             MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
2989             m_jit.store32(TrustedImm32(JSValue::Int32Tag), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
2990             m_jit.store32(valuePayloadGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
2991             m_jit.add32(TrustedImm32(1), storageLengthGPR);
2992             m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
2993             m_jit.move(TrustedImm32(JSValue::Int32Tag), storageGPR);
2994             
2995             addSlowPathGenerator(
2996                 slowPathCall(
2997                     slowPath, this, operationArrayPush,
2998                     JSValueRegs(storageGPR, storageLengthGPR),
2999                     TrustedImm32(JSValue::Int32Tag), valuePayloadGPR, baseGPR));
3000         
3001             jsValueResult(storageGPR, storageLengthGPR, node);
3002             break;
3003         }
3004             
3005         case Array::Contiguous: {
3006             JSValueOperand value(this, node->child2());
3007             GPRReg valueTagGPR = value.tagGPR();
3008             GPRReg valuePayloadGPR = value.payloadGPR();
3009
3010             if (Heap::isWriteBarrierEnabled()) {
3011                 GPRTemporary scratch(this);
3012                 writeBarrier(baseGPR, valueTagGPR, node->child2(), WriteBarrierForPropertyAccess, scratch.gpr(), storageLengthGPR);
3013             }
3014
3015             m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
3016             MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
3017             m_jit.store32(valueTagGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
3018             m_jit.store32(valuePayloadGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
3019             m_jit.add32(TrustedImm32(1), storageLengthGPR);
3020             m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
3021             m_jit.move(TrustedImm32(JSValue::Int32Tag), storageGPR);
3022             
3023             addSlowPathGenerator(
3024                 slowPathCall(
3025                     slowPath, this, operationArrayPush,
3026                     JSValueRegs(storageGPR, storageLengthGPR),
3027                     valueTagGPR, valuePayloadGPR, baseGPR));
3028         
3029             jsValueResult(storageGPR, storageLengthGPR, node);
3030             break;
3031         }
3032             
3033         case Array::Double: {
3034             SpeculateDoubleOperand value(this, node->child2());
3035             FPRReg valueFPR = value.fpr();
3036
3037             DFG_TYPE_CHECK(
3038                 JSValueRegs(), node->child2(), SpecRealNumber,
3039                 m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, valueFPR, valueFPR));
3040             
3041             m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
3042             MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
3043             m_jit.storeDouble(valueFPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
3044             m_jit.add32(TrustedImm32(1), storageLengthGPR);
3045             m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
3046             m_jit.move(TrustedImm32(JSValue::Int32Tag), storageGPR);
3047             
3048             addSlowPathGenerator(
3049                 slowPathCall(
3050                     slowPath, this, operationArrayPushDouble,
3051                     JSValueRegs(storageGPR, storageLengthGPR),
3052                     valueFPR, baseGPR));
3053         
3054             jsValueResult(storageGPR, storageLengthGPR, node);
3055             break;
3056         }
3057             
3058         case Array::ArrayStorage: {
3059             JSValueOperand value(this, node->child2());
3060             GPRReg valueTagGPR = value.tagGPR();
3061             GPRReg valuePayloadGPR = value.payloadGPR();
3062
3063             if (Heap::isWriteBarrierEnabled()) {
3064                 GPRTemporary scratch(this);
3065                 writeBarrier(baseGPR, valueTagGPR, node->child2(), WriteBarrierForPropertyAccess, scratch.gpr(), storageLengthGPR);
3066             }
3067
3068             m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
3069         
3070             // Refuse to handle bizarre lengths.
3071             speculationCheck(Uncountable, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::Above, storageLengthGPR, TrustedImm32(0x7ffffffe)));
3072         
3073             MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset()));
3074         
3075             m_jit.store32(valueTagGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
3076             m_jit.store32(valuePayloadGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
3077         
3078             m_jit.add32(TrustedImm32(1), storageLengthGPR);
3079             m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()));
3080             m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
3081             m_jit.move(TrustedImm32(JSValue::Int32Tag), storageGPR);
3082         
3083             addSlowPathGenerator(slowPathCall(slowPath, this, operationArrayPush, JSValueRegs(storageGPR, storageLengthGPR), valueTagGPR, valuePayloadGPR, baseGPR));
3084         
3085             jsValueResult(storageGPR, storageLengthGPR, node);
3086             break;
3087         }
3088             
3089         default:
3090             CRASH();
3091             break;
3092         }
3093         break;
3094     }
3095         
3096     case ArrayPop: {
3097         ASSERT(node->arrayMode().isJSArray());
3098         
3099         SpeculateCellOperand base(this, node->child1());
3100         StorageOperand storage(this, node->child2());
3101         GPRTemporary valueTag(this);
3102         GPRTemporary valuePayload(this);
3103         
3104         GPRReg baseGPR = base.gpr();
3105         GPRReg valueTagGPR = valueTag.gpr();
3106         GPRReg valuePayloadGPR = valuePayload.gpr();
3107         GPRReg storageGPR = storage.gpr();
3108         
3109         switch (node->arrayMode().type()) {
3110         case Array::Int32:
3111         case Array::Contiguous: {
3112             m_jit.load32(
3113                 MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), valuePayloadGPR);
3114             MacroAssembler::Jump undefinedCase =
3115                 m_jit.branchTest32(MacroAssembler::Zero, valuePayloadGPR);
3116             m_jit.sub32(TrustedImm32(1), valuePayloadGPR);
3117             m_jit.store32(
3118                 valuePayloadGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
3119             m_jit.load32(
3120                 MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)),
3121                 valueTagGPR);
3122             MacroAssembler::Jump slowCase = m_jit.branch32(MacroAssembler::Equal, valueTagGPR, TrustedImm32(JSValue::EmptyValueTag));
3123             m_jit.store32(
3124                 MacroAssembler::TrustedImm32(JSValue::EmptyValueTag),
3125                 MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
3126             m_jit.load32(
3127                 MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)),
3128                 valuePayloadGPR);
3129
3130             addSlowPathGenerator(
3131                 slowPathMove(
3132                     undefinedCase, this,