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