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