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