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