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