650f985e0428b910a77f8fbd162f19b2130d6b45
[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 & ~SpecInt32Only));
905
906     m_interpreter.filter(value, SpecInt32Only);
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                 info.fillInt32(*m_stream, gpr);
946                 returnFormat = DataFormatInt32;
947             } else {
948                 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
949                 info.fillJSValue(*m_stream, gpr, DataFormatJSInt32);
950                 returnFormat = DataFormatJSInt32;
951             }
952             return gpr;
953         }
954         m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
955
956         // Fill as JSValue, and fall through.
957         info.fillJSValue(*m_stream, gpr, DataFormatJSInt32);
958         m_gprs.unlock(gpr);
959         FALLTHROUGH;
960     }
961
962     case DataFormatJS: {
963         DFG_ASSERT(m_jit.graph(), m_currentNode, !(type & SpecInt52Only));
964         // Check the value is an integer.
965         GPRReg gpr = info.gpr();
966         m_gprs.lock(gpr);
967         if (type & ~SpecInt32Only)
968             speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branch64(MacroAssembler::Below, gpr, GPRInfo::tagTypeNumberRegister));
969         info.fillJSValue(*m_stream, gpr, DataFormatJSInt32);
970         // If !strict we're done, return.
971         if (!strict) {
972             returnFormat = DataFormatJSInt32;
973             return gpr;
974         }
975         // else fall through & handle as DataFormatJSInt32.
976         m_gprs.unlock(gpr);
977         FALLTHROUGH;
978     }
979
980     case DataFormatJSInt32: {
981         // In a strict fill we need to strip off the value tag.
982         if (strict) {
983             GPRReg gpr = info.gpr();
984             GPRReg result;
985             // If the register has already been locked we need to take a copy.
986             // If not, we'll zero extend in place, so mark on the info that this is now type DataFormatInt32, not DataFormatJSInt32.
987             if (m_gprs.isLocked(gpr))
988                 result = allocate();
989             else {
990                 m_gprs.lock(gpr);
991                 info.fillInt32(*m_stream, gpr);
992                 result = gpr;
993             }
994             m_jit.zeroExtend32ToPtr(gpr, result);
995             returnFormat = DataFormatInt32;
996             return result;
997         }
998
999         GPRReg gpr = info.gpr();
1000         m_gprs.lock(gpr);
1001         returnFormat = DataFormatJSInt32;
1002         return gpr;
1003     }
1004
1005     case DataFormatInt32: {
1006         GPRReg gpr = info.gpr();
1007         m_gprs.lock(gpr);
1008         returnFormat = DataFormatInt32;
1009         return gpr;
1010     }
1011         
1012     case DataFormatJSDouble:
1013     case DataFormatCell:
1014     case DataFormatBoolean:
1015     case DataFormatJSCell:
1016     case DataFormatJSBoolean:
1017     case DataFormatDouble:
1018     case DataFormatStorage:
1019     case DataFormatInt52:
1020     case DataFormatStrictInt52:
1021         DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
1022         
1023     default:
1024         DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");
1025         return InvalidGPRReg;
1026     }
1027 }
1028 #if COMPILER(CLANG) && defined(__has_warning)
1029 #pragma clang diagnostic pop
1030 #endif
1031
1032 GPRReg SpeculativeJIT::fillSpeculateInt32(Edge edge, DataFormat& returnFormat)
1033 {
1034     return fillSpeculateInt32Internal<false>(edge, returnFormat);
1035 }
1036
1037 GPRReg SpeculativeJIT::fillSpeculateInt32Strict(Edge edge)
1038 {
1039     DataFormat mustBeDataFormatInt32;
1040     GPRReg result = fillSpeculateInt32Internal<true>(edge, mustBeDataFormatInt32);
1041     DFG_ASSERT(m_jit.graph(), m_currentNode, mustBeDataFormatInt32 == DataFormatInt32);
1042     return result;
1043 }
1044
1045 GPRReg SpeculativeJIT::fillSpeculateInt52(Edge edge, DataFormat desiredFormat)
1046 {
1047     ASSERT(desiredFormat == DataFormatInt52 || desiredFormat == DataFormatStrictInt52);
1048     AbstractValue& value = m_state.forNode(edge);
1049
1050     m_interpreter.filter(value, SpecAnyInt);
1051     if (value.isClear()) {
1052         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1053         return allocate();
1054     }
1055
1056     VirtualRegister virtualRegister = edge->virtualRegister();
1057     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1058
1059     switch (info.registerFormat()) {
1060     case DataFormatNone: {
1061         GPRReg gpr = allocate();
1062
1063         if (edge->hasConstant()) {
1064             JSValue jsValue = edge->asJSValue();
1065             ASSERT(jsValue.isAnyInt());
1066             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1067             int64_t value = jsValue.asAnyInt();
1068             if (desiredFormat == DataFormatInt52)
1069                 value = value << JSValue::int52ShiftAmount;
1070             m_jit.move(MacroAssembler::Imm64(value), gpr);
1071             info.fillGPR(*m_stream, gpr, desiredFormat);
1072             return gpr;
1073         }
1074         
1075         DataFormat spillFormat = info.spillFormat();
1076         
1077         DFG_ASSERT(m_jit.graph(), m_currentNode, spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52);
1078         
1079         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1080         
1081         m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1082         if (desiredFormat == DataFormatStrictInt52) {
1083             if (spillFormat == DataFormatInt52)
1084                 m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
1085             info.fillStrictInt52(*m_stream, gpr);
1086             return gpr;
1087         }
1088         if (spillFormat == DataFormatStrictInt52)
1089             m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
1090         info.fillInt52(*m_stream, gpr);
1091         return gpr;
1092     }
1093
1094     case DataFormatStrictInt52: {
1095         GPRReg gpr = info.gpr();
1096         bool wasLocked = m_gprs.isLocked(gpr);
1097         lock(gpr);
1098         if (desiredFormat == DataFormatStrictInt52)
1099             return gpr;
1100         if (wasLocked) {
1101             GPRReg result = allocate();
1102             m_jit.move(gpr, result);
1103             unlock(gpr);
1104             gpr = result;
1105         } else
1106             info.fillInt52(*m_stream, gpr);
1107         m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
1108         return gpr;
1109     }
1110         
1111     case DataFormatInt52: {
1112         GPRReg gpr = info.gpr();
1113         bool wasLocked = m_gprs.isLocked(gpr);
1114         lock(gpr);
1115         if (desiredFormat == DataFormatInt52)
1116             return gpr;
1117         if (wasLocked) {
1118             GPRReg result = allocate();
1119             m_jit.move(gpr, result);
1120             unlock(gpr);
1121             gpr = result;
1122         } else
1123             info.fillStrictInt52(*m_stream, gpr);
1124         m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
1125         return gpr;
1126     }
1127
1128     default:
1129         DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
1130         return InvalidGPRReg;
1131     }
1132 }
1133
1134 FPRReg SpeculativeJIT::fillSpeculateDouble(Edge edge)
1135 {
1136     ASSERT(edge.useKind() == DoubleRepUse || edge.useKind() == DoubleRepRealUse || edge.useKind() == DoubleRepAnyIntUse);
1137     ASSERT(edge->hasDoubleResult());
1138     VirtualRegister virtualRegister = edge->virtualRegister();
1139     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1140
1141     if (info.registerFormat() == DataFormatNone) {
1142         if (edge->hasConstant()) {
1143             if (edge->isNumberConstant()) {
1144                 FPRReg fpr = fprAllocate();
1145                 int64_t doubleAsInt = reinterpretDoubleToInt64(edge->asNumber());
1146                 if (!doubleAsInt)
1147                     m_jit.moveZeroToDouble(fpr);
1148                 else {
1149                     GPRReg gpr = allocate();
1150                     m_jit.move(MacroAssembler::Imm64(doubleAsInt), gpr);
1151                     m_jit.move64ToDouble(gpr, fpr);
1152                     unlock(gpr);
1153                 }
1154
1155                 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
1156                 info.fillDouble(*m_stream, fpr);
1157                 return fpr;
1158             }
1159             terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1160             return fprAllocate();
1161         }
1162         
1163         DataFormat spillFormat = info.spillFormat();
1164         if (spillFormat != DataFormatDouble) {
1165             DFG_CRASH(
1166                 m_jit.graph(), m_currentNode, toCString(
1167                     "Expected ", edge, " to have double format but instead it is spilled as ",
1168                     dataFormatToString(spillFormat)).data());
1169         }
1170         DFG_ASSERT(m_jit.graph(), m_currentNode, spillFormat == DataFormatDouble);
1171         FPRReg fpr = fprAllocate();
1172         m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
1173         m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
1174         info.fillDouble(*m_stream, fpr);
1175         return fpr;
1176     }
1177
1178     DFG_ASSERT(m_jit.graph(), m_currentNode, info.registerFormat() == DataFormatDouble);
1179     FPRReg fpr = info.fpr();
1180     m_fprs.lock(fpr);
1181     return fpr;
1182 }
1183
1184 GPRReg SpeculativeJIT::fillSpeculateCell(Edge edge)
1185 {
1186     AbstractValue& value = m_state.forNode(edge);
1187     SpeculatedType type = value.m_type;
1188     ASSERT((edge.useKind() != KnownCellUse && edge.useKind() != KnownStringUse) || !(value.m_type & ~SpecCell));
1189
1190     m_interpreter.filter(value, SpecCell);
1191     if (value.isClear()) {
1192         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1193         return allocate();
1194     }
1195
1196     VirtualRegister virtualRegister = edge->virtualRegister();
1197     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1198
1199     switch (info.registerFormat()) {
1200     case DataFormatNone: {
1201         GPRReg gpr = allocate();
1202
1203         if (edge->hasConstant()) {
1204             JSValue jsValue = edge->asJSValue();
1205             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1206             m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsValue)), gpr);
1207             info.fillJSValue(*m_stream, gpr, DataFormatJSCell);
1208             return gpr;
1209         }
1210
1211         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1212         m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1213
1214         info.fillJSValue(*m_stream, gpr, DataFormatJS);
1215         if (type & ~SpecCell)
1216             speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchIfNotCell(JSValueRegs(gpr)));
1217         info.fillJSValue(*m_stream, gpr, DataFormatJSCell);
1218         return gpr;
1219     }
1220
1221     case DataFormatCell:
1222     case DataFormatJSCell: {
1223         GPRReg gpr = info.gpr();
1224         m_gprs.lock(gpr);
1225         if (!ASSERT_DISABLED) {
1226             MacroAssembler::Jump checkCell = m_jit.branchIfCell(JSValueRegs(gpr));
1227             m_jit.abortWithReason(DFGIsNotCell);
1228             checkCell.link(&m_jit);
1229         }
1230         return gpr;
1231     }
1232
1233     case DataFormatJS: {
1234         GPRReg gpr = info.gpr();
1235         m_gprs.lock(gpr);
1236         if (type & ~SpecCell)
1237             speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchIfNotCell(JSValueRegs(gpr)));
1238         info.fillJSValue(*m_stream, gpr, DataFormatJSCell);
1239         return gpr;
1240     }
1241
1242     case DataFormatJSInt32:
1243     case DataFormatInt32:
1244     case DataFormatJSDouble:
1245     case DataFormatJSBoolean:
1246     case DataFormatBoolean:
1247     case DataFormatDouble:
1248     case DataFormatStorage:
1249     case DataFormatInt52:
1250     case DataFormatStrictInt52:
1251         DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
1252         
1253     default:
1254         DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");
1255         return InvalidGPRReg;
1256     }
1257 }
1258
1259 GPRReg SpeculativeJIT::fillSpeculateBoolean(Edge edge)
1260 {
1261     AbstractValue& value = m_state.forNode(edge);
1262     SpeculatedType type = value.m_type;
1263     ASSERT(edge.useKind() != KnownBooleanUse || !(value.m_type & ~SpecBoolean));
1264
1265     m_interpreter.filter(value, SpecBoolean);
1266     if (value.isClear()) {
1267         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1268         return allocate();
1269     }
1270
1271     VirtualRegister virtualRegister = edge->virtualRegister();
1272     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1273
1274     switch (info.registerFormat()) {
1275     case DataFormatNone: {
1276         GPRReg gpr = allocate();
1277
1278         if (edge->hasConstant()) {
1279             JSValue jsValue = edge->asJSValue();
1280             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1281             m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsValue)), gpr);
1282             info.fillJSValue(*m_stream, gpr, DataFormatJSBoolean);
1283             return gpr;
1284         }
1285         DFG_ASSERT(m_jit.graph(), m_currentNode, info.spillFormat() & DataFormatJS);
1286         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1287         m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1288
1289         info.fillJSValue(*m_stream, gpr, DataFormatJS);
1290         if (type & ~SpecBoolean) {
1291             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1292             speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchTest64(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg));
1293             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1294         }
1295         info.fillJSValue(*m_stream, gpr, DataFormatJSBoolean);
1296         return gpr;
1297     }
1298
1299     case DataFormatBoolean:
1300     case DataFormatJSBoolean: {
1301         GPRReg gpr = info.gpr();
1302         m_gprs.lock(gpr);
1303         return gpr;
1304     }
1305
1306     case DataFormatJS: {
1307         GPRReg gpr = info.gpr();
1308         m_gprs.lock(gpr);
1309         if (type & ~SpecBoolean) {
1310             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1311             speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchTest64(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg));
1312             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1313         }
1314         info.fillJSValue(*m_stream, gpr, DataFormatJSBoolean);
1315         return gpr;
1316     }
1317
1318     case DataFormatJSInt32:
1319     case DataFormatInt32:
1320     case DataFormatJSDouble:
1321     case DataFormatJSCell:
1322     case DataFormatCell:
1323     case DataFormatDouble:
1324     case DataFormatStorage:
1325     case DataFormatInt52:
1326     case DataFormatStrictInt52:
1327         DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
1328         
1329     default:
1330         DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");
1331         return InvalidGPRReg;
1332     }
1333 }
1334
1335 void SpeculativeJIT::compileBaseValueStoreBarrier(Edge& baseEdge, Edge& valueEdge)
1336 {
1337     ASSERT(!isKnownNotCell(valueEdge.node()));
1338
1339     SpeculateCellOperand base(this, baseEdge);
1340     JSValueOperand value(this, valueEdge);
1341     GPRTemporary scratch1(this);
1342     GPRTemporary scratch2(this);
1343
1344     writeBarrier(base.gpr(), value.gpr(), valueEdge, scratch1.gpr(), scratch2.gpr());
1345 }
1346
1347 void SpeculativeJIT::compileObjectEquality(Node* node)
1348 {
1349     SpeculateCellOperand op1(this, node->child1());
1350     SpeculateCellOperand op2(this, node->child2());
1351     GPRTemporary result(this, Reuse, op1);
1352     
1353     GPRReg op1GPR = op1.gpr();
1354     GPRReg op2GPR = op2.gpr();
1355     GPRReg resultGPR = result.gpr();
1356    
1357     if (masqueradesAsUndefinedWatchpointIsStillValid()) {
1358         DFG_TYPE_CHECK(
1359             JSValueSource::unboxedCell(op1GPR), node->child1(), SpecObject, m_jit.branchIfNotObject(op1GPR));
1360         DFG_TYPE_CHECK(
1361             JSValueSource::unboxedCell(op2GPR), node->child2(), SpecObject, m_jit.branchIfNotObject(op2GPR));
1362     } else {
1363         DFG_TYPE_CHECK(
1364             JSValueSource::unboxedCell(op1GPR), node->child1(), SpecObject, m_jit.branchIfNotObject(op1GPR));
1365         speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node->child1(),
1366             m_jit.branchTest8(
1367                 MacroAssembler::NonZero, 
1368                 MacroAssembler::Address(op1GPR, JSCell::typeInfoFlagsOffset()), 
1369                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1370
1371         DFG_TYPE_CHECK(
1372             JSValueSource::unboxedCell(op2GPR), node->child2(), SpecObject, m_jit.branchIfNotObject(op2GPR));
1373         speculationCheck(BadType, JSValueSource::unboxedCell(op2GPR), node->child2(),
1374             m_jit.branchTest8(
1375                 MacroAssembler::NonZero, 
1376                 MacroAssembler::Address(op2GPR, JSCell::typeInfoFlagsOffset()), 
1377                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1378     }
1379
1380     m_jit.compare64(MacroAssembler::Equal, op1GPR, op2GPR, resultGPR);
1381     m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
1382     jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean);
1383 }
1384
1385 void SpeculativeJIT::compileObjectStrictEquality(Edge objectChild, Edge otherChild)
1386 {
1387     SpeculateCellOperand op1(this, objectChild);
1388     JSValueOperand op2(this, otherChild);
1389     GPRTemporary result(this);
1390
1391     GPRReg op1GPR = op1.gpr();
1392     GPRReg op2GPR = op2.gpr();
1393     GPRReg resultGPR = result.gpr();
1394
1395     DFG_TYPE_CHECK(JSValueSource::unboxedCell(op1GPR), objectChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1396
1397     // At this point we know that we can perform a straight-forward equality comparison on pointer
1398     // values because we are doing strict equality.
1399     m_jit.compare64(MacroAssembler::Equal, op1GPR, op2GPR, resultGPR);
1400     m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
1401     jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean);
1402 }
1403     
1404 void SpeculativeJIT::compilePeepHoleObjectStrictEquality(Edge objectChild, Edge otherChild, Node* branchNode)
1405 {
1406     BasicBlock* taken = branchNode->branchData()->taken.block;
1407     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
1408     
1409     SpeculateCellOperand op1(this, objectChild);
1410     JSValueOperand op2(this, otherChild);
1411     
1412     GPRReg op1GPR = op1.gpr();
1413     GPRReg op2GPR = op2.gpr();
1414     
1415     DFG_TYPE_CHECK(JSValueSource::unboxedCell(op1GPR), objectChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1416
1417     if (taken == nextBlock()) {
1418         branchPtr(MacroAssembler::NotEqual, op1GPR, op2GPR, notTaken);
1419         jump(taken);
1420     } else {
1421         branchPtr(MacroAssembler::Equal, op1GPR, op2GPR, taken);
1422         jump(notTaken);
1423     }
1424 }
1425
1426 void SpeculativeJIT::compileObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild)
1427 {
1428     SpeculateCellOperand op1(this, leftChild);
1429     JSValueOperand op2(this, rightChild, ManualOperandSpeculation);
1430     GPRTemporary result(this);
1431     
1432     GPRReg op1GPR = op1.gpr();
1433     GPRReg op2GPR = op2.gpr();
1434     GPRReg resultGPR = result.gpr();
1435
1436     bool masqueradesAsUndefinedWatchpointValid =
1437         masqueradesAsUndefinedWatchpointIsStillValid();
1438
1439     if (masqueradesAsUndefinedWatchpointValid) {
1440         DFG_TYPE_CHECK(
1441             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1442     } else {
1443         DFG_TYPE_CHECK(
1444             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1445         speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), leftChild,
1446             m_jit.branchTest8(
1447                 MacroAssembler::NonZero, 
1448                 MacroAssembler::Address(op1GPR, JSCell::typeInfoFlagsOffset()), 
1449                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1450     }
1451     
1452     // It seems that most of the time when programs do a == b where b may be either null/undefined
1453     // or an object, b is usually an object. Balance the branches to make that case fast.
1454     MacroAssembler::Jump rightNotCell = m_jit.branchIfNotCell(JSValueRegs(op2GPR));
1455     
1456     // We know that within this branch, rightChild must be a cell. 
1457     if (masqueradesAsUndefinedWatchpointValid) {
1458         DFG_TYPE_CHECK(
1459             JSValueRegs(op2GPR), rightChild, (~SpecCell) | SpecObject, m_jit.branchIfNotObject(op2GPR));
1460     } else {
1461         DFG_TYPE_CHECK(
1462             JSValueRegs(op2GPR), rightChild, (~SpecCell) | SpecObject, m_jit.branchIfNotObject(op2GPR));
1463         speculationCheck(BadType, JSValueRegs(op2GPR), rightChild,
1464             m_jit.branchTest8(
1465                 MacroAssembler::NonZero, 
1466                 MacroAssembler::Address(op2GPR, JSCell::typeInfoFlagsOffset()), 
1467                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1468     }
1469     
1470     // At this point we know that we can perform a straight-forward equality comparison on pointer
1471     // values because both left and right are pointers to objects that have no special equality
1472     // protocols.
1473     m_jit.compare64(MacroAssembler::Equal, op1GPR, op2GPR, resultGPR);
1474     MacroAssembler::Jump done = m_jit.jump();
1475     
1476     rightNotCell.link(&m_jit);
1477     
1478     // We know that within this branch, rightChild must not be a cell. Check if that is enough to
1479     // prove that it is either null or undefined.
1480     if (needsTypeCheck(rightChild, SpecCell | SpecOther)) {
1481         m_jit.move(op2GPR, resultGPR);
1482         m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR);
1483         
1484         typeCheck(
1485             JSValueRegs(op2GPR), rightChild, SpecCell | SpecOther,
1486             m_jit.branch64(
1487                 MacroAssembler::NotEqual, resultGPR,
1488                 MacroAssembler::TrustedImm64(ValueNull)));
1489     }
1490     m_jit.move(TrustedImm32(0), result.gpr());
1491
1492     done.link(&m_jit);
1493     m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
1494     jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean);
1495 }
1496
1497 void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild, Node* branchNode)
1498 {
1499     BasicBlock* taken = branchNode->branchData()->taken.block;
1500     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
1501     
1502     SpeculateCellOperand op1(this, leftChild);
1503     JSValueOperand op2(this, rightChild, ManualOperandSpeculation);
1504     GPRTemporary result(this);
1505     
1506     GPRReg op1GPR = op1.gpr();
1507     GPRReg op2GPR = op2.gpr();
1508     GPRReg resultGPR = result.gpr();
1509     
1510     bool masqueradesAsUndefinedWatchpointValid = 
1511         masqueradesAsUndefinedWatchpointIsStillValid();
1512
1513     if (masqueradesAsUndefinedWatchpointValid) {
1514         DFG_TYPE_CHECK(
1515             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1516     } else {
1517         DFG_TYPE_CHECK(
1518             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1519         speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), leftChild, 
1520             m_jit.branchTest8(
1521                 MacroAssembler::NonZero, 
1522                 MacroAssembler::Address(op1GPR, JSCell::typeInfoFlagsOffset()), 
1523                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1524     }
1525
1526     // It seems that most of the time when programs do a == b where b may be either null/undefined
1527     // or an object, b is usually an object. Balance the branches to make that case fast.
1528     MacroAssembler::Jump rightNotCell = m_jit.branchIfNotCell(JSValueRegs(op2GPR));
1529     
1530     // We know that within this branch, rightChild must be a cell. 
1531     if (masqueradesAsUndefinedWatchpointValid) {
1532         DFG_TYPE_CHECK(
1533             JSValueRegs(op2GPR), rightChild, (~SpecCell) | SpecObject, m_jit.branchIfNotObject(op2GPR));
1534     } else {
1535         DFG_TYPE_CHECK(
1536             JSValueRegs(op2GPR), rightChild, (~SpecCell) | SpecObject, m_jit.branchIfNotObject(op2GPR));
1537         speculationCheck(BadType, JSValueRegs(op2GPR), rightChild,
1538             m_jit.branchTest8(
1539                 MacroAssembler::NonZero, 
1540                 MacroAssembler::Address(op2GPR, JSCell::typeInfoFlagsOffset()), 
1541                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1542     }
1543     
1544     // At this point we know that we can perform a straight-forward equality comparison on pointer
1545     // values because both left and right are pointers to objects that have no special equality
1546     // protocols.
1547     branch64(MacroAssembler::Equal, op1GPR, op2GPR, taken);
1548     
1549     // We know that within this branch, rightChild must not be a cell. Check if that is enough to
1550     // prove that it is either null or undefined.
1551     if (!needsTypeCheck(rightChild, SpecCell | SpecOther))
1552         rightNotCell.link(&m_jit);
1553     else {
1554         jump(notTaken, ForceJump);
1555         
1556         rightNotCell.link(&m_jit);
1557         m_jit.move(op2GPR, resultGPR);
1558         m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR);
1559         
1560         typeCheck(
1561             JSValueRegs(op2GPR), rightChild, SpecCell | SpecOther, m_jit.branch64(
1562                 MacroAssembler::NotEqual, resultGPR,
1563                 MacroAssembler::TrustedImm64(ValueNull)));
1564     }
1565     
1566     jump(notTaken);
1567 }
1568
1569 void SpeculativeJIT::compileInt32Compare(Node* node, MacroAssembler::RelationalCondition condition)
1570 {
1571     if (node->child1()->isInt32Constant()) {
1572         SpeculateInt32Operand op2(this, node->child2());
1573         GPRTemporary result(this, Reuse, op2);
1574         int32_t imm = node->child1()->asInt32();
1575         m_jit.compare32(condition, JITCompiler::Imm32(imm), op2.gpr(), result.gpr());
1576
1577         // If we add a DataFormatBool, we should use it here.
1578         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1579         jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean);
1580     } else if (node->child2()->isInt32Constant()) {
1581         SpeculateInt32Operand op1(this, node->child1());
1582         GPRTemporary result(this, Reuse, op1);
1583         int32_t imm = node->child2()->asInt32();
1584         m_jit.compare32(condition, op1.gpr(), JITCompiler::Imm32(imm), result.gpr());
1585
1586         // If we add a DataFormatBool, we should use it here.
1587         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1588         jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean);
1589     } else {
1590         SpeculateInt32Operand op1(this, node->child1());
1591         SpeculateInt32Operand op2(this, node->child2());
1592         GPRTemporary result(this, Reuse, op1, op2);
1593         m_jit.compare32(condition, op1.gpr(), op2.gpr(), result.gpr());
1594
1595         // If we add a DataFormatBool, we should use it here.
1596         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1597         jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean);
1598     }
1599 }
1600
1601 void SpeculativeJIT::compileInt52Compare(Node* node, MacroAssembler::RelationalCondition condition)
1602 {
1603     SpeculateWhicheverInt52Operand op1(this, node->child1());
1604     SpeculateWhicheverInt52Operand op2(this, node->child2(), op1);
1605     GPRTemporary result(this, Reuse, op1, op2);
1606     
1607     m_jit.compare64(condition, op1.gpr(), op2.gpr(), result.gpr());
1608     
1609     // If we add a DataFormatBool, we should use it here.
1610     m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1611     jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean);
1612 }
1613
1614 void SpeculativeJIT::compilePeepHoleInt52Branch(Node* node, Node* branchNode, JITCompiler::RelationalCondition condition)
1615 {
1616     BasicBlock* taken = branchNode->branchData()->taken.block;
1617     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
1618
1619     // The branch instruction will branch to the taken block.
1620     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
1621     if (taken == nextBlock()) {
1622         condition = JITCompiler::invert(condition);
1623         BasicBlock* tmp = taken;
1624         taken = notTaken;
1625         notTaken = tmp;
1626     }
1627     
1628     SpeculateWhicheverInt52Operand op1(this, node->child1());
1629     SpeculateWhicheverInt52Operand op2(this, node->child2(), op1);
1630     
1631     branch64(condition, op1.gpr(), op2.gpr(), taken);
1632     jump(notTaken);
1633 }
1634
1635 void SpeculativeJIT::compileDoubleCompare(Node* node, MacroAssembler::DoubleCondition condition)
1636 {
1637     SpeculateDoubleOperand op1(this, node->child1());
1638     SpeculateDoubleOperand op2(this, node->child2());
1639     GPRTemporary result(this);
1640     
1641     m_jit.move(TrustedImm32(ValueTrue), result.gpr());
1642     MacroAssembler::Jump trueCase = m_jit.branchDouble(condition, op1.fpr(), op2.fpr());
1643     m_jit.xor64(TrustedImm32(true), result.gpr());
1644     trueCase.link(&m_jit);
1645     
1646     jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1647 }
1648
1649 void SpeculativeJIT::compileObjectOrOtherLogicalNot(Edge nodeUse)
1650 {
1651     JSValueOperand value(this, nodeUse, ManualOperandSpeculation);
1652     GPRTemporary result(this);
1653     GPRReg valueGPR = value.gpr();
1654     GPRReg resultGPR = result.gpr();
1655     GPRTemporary structure;
1656     GPRReg structureGPR = InvalidGPRReg;
1657     GPRTemporary scratch;
1658     GPRReg scratchGPR = InvalidGPRReg;
1659
1660     bool masqueradesAsUndefinedWatchpointValid =
1661         masqueradesAsUndefinedWatchpointIsStillValid();
1662
1663     if (!masqueradesAsUndefinedWatchpointValid) {
1664         // The masquerades as undefined case will use the structure register, so allocate it here.
1665         // Do this at the top of the function to avoid branching around a register allocation.
1666         GPRTemporary realStructure(this);
1667         GPRTemporary realScratch(this);
1668         structure.adopt(realStructure);
1669         scratch.adopt(realScratch);
1670         structureGPR = structure.gpr();
1671         scratchGPR = scratch.gpr();
1672     }
1673
1674     MacroAssembler::Jump notCell = m_jit.branchIfNotCell(JSValueRegs(valueGPR));
1675     if (masqueradesAsUndefinedWatchpointValid) {
1676         DFG_TYPE_CHECK(
1677             JSValueRegs(valueGPR), nodeUse, (~SpecCell) | SpecObject, m_jit.branchIfNotObject(valueGPR));
1678     } else {
1679         DFG_TYPE_CHECK(
1680             JSValueRegs(valueGPR), nodeUse, (~SpecCell) | SpecObject, m_jit.branchIfNotObject(valueGPR));
1681
1682         MacroAssembler::Jump isNotMasqueradesAsUndefined = 
1683             m_jit.branchTest8(
1684                 MacroAssembler::Zero, 
1685                 MacroAssembler::Address(valueGPR, JSCell::typeInfoFlagsOffset()), 
1686                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined));
1687
1688         m_jit.emitLoadStructure(valueGPR, structureGPR, scratchGPR);
1689         speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse, 
1690             m_jit.branchPtr(
1691                 MacroAssembler::Equal, 
1692                 MacroAssembler::Address(structureGPR, Structure::globalObjectOffset()), 
1693                 MacroAssembler::TrustedImmPtr(m_jit.graph().globalObjectFor(m_currentNode->origin.semantic))));
1694
1695         isNotMasqueradesAsUndefined.link(&m_jit);
1696     }
1697     m_jit.move(TrustedImm32(ValueFalse), resultGPR);
1698     MacroAssembler::Jump done = m_jit.jump();
1699     
1700     notCell.link(&m_jit);
1701
1702     if (needsTypeCheck(nodeUse, SpecCell | SpecOther)) {
1703         m_jit.move(valueGPR, resultGPR);
1704         m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR);
1705         typeCheck(
1706             JSValueRegs(valueGPR), nodeUse, SpecCell | SpecOther, m_jit.branch64(
1707                 MacroAssembler::NotEqual, 
1708                 resultGPR, 
1709                 MacroAssembler::TrustedImm64(ValueNull)));
1710     }
1711     m_jit.move(TrustedImm32(ValueTrue), resultGPR);
1712     
1713     done.link(&m_jit);
1714     
1715     jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean);
1716 }
1717
1718 void SpeculativeJIT::compileLogicalNot(Node* node)
1719 {
1720     switch (node->child1().useKind()) {
1721     case ObjectOrOtherUse: {
1722         compileObjectOrOtherLogicalNot(node->child1());
1723         return;
1724     }
1725         
1726     case Int32Use: {
1727         SpeculateInt32Operand value(this, node->child1());
1728         GPRTemporary result(this, Reuse, value);
1729         m_jit.compare32(MacroAssembler::Equal, value.gpr(), MacroAssembler::TrustedImm32(0), result.gpr());
1730         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1731         jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1732         return;
1733     }
1734         
1735     case DoubleRepUse: {
1736         SpeculateDoubleOperand value(this, node->child1());
1737         FPRTemporary scratch(this);
1738         GPRTemporary result(this);
1739         m_jit.move(TrustedImm32(ValueFalse), result.gpr());
1740         MacroAssembler::Jump nonZero = m_jit.branchDoubleNonZero(value.fpr(), scratch.fpr());
1741         m_jit.xor32(TrustedImm32(true), result.gpr());
1742         nonZero.link(&m_jit);
1743         jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1744         return;
1745     }
1746     
1747     case BooleanUse:
1748     case KnownBooleanUse: {
1749         if (!needsTypeCheck(node->child1(), SpecBoolean)) {
1750             SpeculateBooleanOperand value(this, node->child1());
1751             GPRTemporary result(this, Reuse, value);
1752             
1753             m_jit.move(value.gpr(), result.gpr());
1754             m_jit.xor64(TrustedImm32(true), result.gpr());
1755             
1756             jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1757             return;
1758         }
1759         
1760         JSValueOperand value(this, node->child1(), ManualOperandSpeculation);
1761         GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add).
1762         
1763         m_jit.move(value.gpr(), result.gpr());
1764         m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), result.gpr());
1765         typeCheck(
1766             JSValueRegs(value.gpr()), node->child1(), SpecBoolean, m_jit.branchTest64(
1767                 JITCompiler::NonZero, result.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
1768         m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueTrue)), result.gpr());
1769         
1770         // If we add a DataFormatBool, we should use it here.
1771         jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1772         return;
1773     }
1774         
1775     case UntypedUse: {
1776         JSValueOperand arg1(this, node->child1());
1777         GPRTemporary result(this);
1778     
1779         GPRReg arg1GPR = arg1.gpr();
1780         GPRReg resultGPR = result.gpr();
1781     
1782         arg1.use();
1783     
1784         m_jit.move(arg1GPR, resultGPR);
1785         m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), resultGPR);
1786         JITCompiler::Jump slowCase = m_jit.branchTest64(JITCompiler::NonZero, resultGPR, TrustedImm32(static_cast<int32_t>(~1)));
1787     
1788         addSlowPathGenerator(
1789             slowPathCall(slowCase, this, operationConvertJSValueToBoolean, resultGPR, arg1GPR, NeedToSpill, ExceptionCheckRequirement::CheckNotNeeded));
1790     
1791         m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueTrue)), resultGPR);
1792         jsValueResult(resultGPR, node, DataFormatJSBoolean, UseChildrenCalledExplicitly);
1793         return;
1794     }
1795     case StringUse:
1796         return compileStringZeroLength(node);
1797
1798     case StringOrOtherUse:
1799         return compileLogicalNotStringOrOther(node);
1800
1801     default:
1802         DFG_CRASH(m_jit.graph(), node, "Bad use kind");
1803         break;
1804     }
1805 }
1806
1807 void SpeculativeJIT::emitObjectOrOtherBranch(Edge nodeUse, BasicBlock* taken, BasicBlock* notTaken)
1808 {
1809     JSValueOperand value(this, nodeUse, ManualOperandSpeculation);
1810     GPRTemporary scratch(this);
1811     GPRTemporary structure;
1812     GPRReg valueGPR = value.gpr();
1813     GPRReg scratchGPR = scratch.gpr();
1814     GPRReg structureGPR = InvalidGPRReg;
1815
1816     if (!masqueradesAsUndefinedWatchpointIsStillValid()) {
1817         GPRTemporary realStructure(this);
1818         structure.adopt(realStructure);
1819         structureGPR = structure.gpr();
1820     }
1821
1822     MacroAssembler::Jump notCell = m_jit.branchIfNotCell(JSValueRegs(valueGPR));
1823     if (masqueradesAsUndefinedWatchpointIsStillValid()) {
1824         DFG_TYPE_CHECK(
1825             JSValueRegs(valueGPR), nodeUse, (~SpecCell) | SpecObject, m_jit.branchIfNotObject(valueGPR));
1826     } else {
1827         DFG_TYPE_CHECK(
1828             JSValueRegs(valueGPR), nodeUse, (~SpecCell) | SpecObject, m_jit.branchIfNotObject(valueGPR));
1829
1830         JITCompiler::Jump isNotMasqueradesAsUndefined = m_jit.branchTest8(
1831             JITCompiler::Zero, 
1832             MacroAssembler::Address(valueGPR, JSCell::typeInfoFlagsOffset()), 
1833             TrustedImm32(MasqueradesAsUndefined));
1834
1835         m_jit.emitLoadStructure(valueGPR, structureGPR, scratchGPR);
1836         speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse,
1837             m_jit.branchPtr(
1838                 MacroAssembler::Equal, 
1839                 MacroAssembler::Address(structureGPR, Structure::globalObjectOffset()), 
1840                 MacroAssembler::TrustedImmPtr(m_jit.graph().globalObjectFor(m_currentNode->origin.semantic))));
1841
1842         isNotMasqueradesAsUndefined.link(&m_jit);
1843     }
1844     jump(taken, ForceJump);
1845     
1846     notCell.link(&m_jit);
1847     
1848     if (needsTypeCheck(nodeUse, SpecCell | SpecOther)) {
1849         m_jit.move(valueGPR, scratchGPR);
1850         m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), scratchGPR);
1851         typeCheck(
1852             JSValueRegs(valueGPR), nodeUse, SpecCell | SpecOther, m_jit.branch64(
1853                 MacroAssembler::NotEqual, scratchGPR, MacroAssembler::TrustedImm64(ValueNull)));
1854     }
1855     jump(notTaken);
1856     
1857     noResult(m_currentNode);
1858 }
1859
1860 void SpeculativeJIT::emitBranch(Node* node)
1861 {
1862     BasicBlock* taken = node->branchData()->taken.block;
1863     BasicBlock* notTaken = node->branchData()->notTaken.block;
1864     
1865     switch (node->child1().useKind()) {
1866     case ObjectOrOtherUse: {
1867         emitObjectOrOtherBranch(node->child1(), taken, notTaken);
1868         return;
1869     }
1870         
1871     case Int32Use:
1872     case DoubleRepUse: {
1873         if (node->child1().useKind() == Int32Use) {
1874             bool invert = false;
1875             
1876             if (taken == nextBlock()) {
1877                 invert = true;
1878                 BasicBlock* tmp = taken;
1879                 taken = notTaken;
1880                 notTaken = tmp;
1881             }
1882
1883             SpeculateInt32Operand value(this, node->child1());
1884             branchTest32(invert ? MacroAssembler::Zero : MacroAssembler::NonZero, value.gpr(), taken);
1885         } else {
1886             SpeculateDoubleOperand value(this, node->child1());
1887             FPRTemporary scratch(this);
1888             branchDoubleNonZero(value.fpr(), scratch.fpr(), taken);
1889         }
1890         
1891         jump(notTaken);
1892         
1893         noResult(node);
1894         return;
1895     }
1896
1897     case StringUse: {
1898         emitStringBranch(node->child1(), taken, notTaken);
1899         return;
1900     }
1901
1902     case StringOrOtherUse: {
1903         emitStringOrOtherBranch(node->child1(), taken, notTaken);
1904         return;
1905     }
1906
1907     case UntypedUse:
1908     case BooleanUse:
1909     case KnownBooleanUse: {
1910         JSValueOperand value(this, node->child1(), ManualOperandSpeculation);
1911         GPRReg valueGPR = value.gpr();
1912         
1913         if (node->child1().useKind() == BooleanUse || node->child1().useKind() == KnownBooleanUse) {
1914             if (!needsTypeCheck(node->child1(), SpecBoolean)) {
1915                 MacroAssembler::ResultCondition condition = MacroAssembler::NonZero;
1916                 
1917                 if (taken == nextBlock()) {
1918                     condition = MacroAssembler::Zero;
1919                     BasicBlock* tmp = taken;
1920                     taken = notTaken;
1921                     notTaken = tmp;
1922                 }
1923                 
1924                 branchTest32(condition, valueGPR, TrustedImm32(true), taken);
1925                 jump(notTaken);
1926             } else {
1927                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(false))), notTaken);
1928                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(true))), taken);
1929                 
1930                 typeCheck(JSValueRegs(valueGPR), node->child1(), SpecBoolean, m_jit.jump());
1931             }
1932             value.use();
1933         } else {
1934             GPRTemporary result(this);
1935             GPRReg resultGPR = result.gpr();
1936             
1937             if (node->child1()->prediction() & SpecInt32Only) {
1938                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsNumber(0))), notTaken);
1939                 branch64(MacroAssembler::AboveOrEqual, valueGPR, GPRInfo::tagTypeNumberRegister, taken);
1940             }
1941     
1942             if (node->child1()->prediction() & SpecBoolean) {
1943                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(false))), notTaken);
1944                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(true))), taken);
1945             }
1946     
1947             value.use();
1948     
1949             silentSpillAllRegisters(resultGPR);
1950             callOperation(operationConvertJSValueToBoolean, resultGPR, valueGPR);
1951             silentFillAllRegisters(resultGPR);
1952     
1953             branchTest32(MacroAssembler::NonZero, resultGPR, taken);
1954             jump(notTaken);
1955         }
1956         
1957         noResult(node, UseChildrenCalledExplicitly);
1958         return;
1959     }
1960         
1961     default:
1962         DFG_CRASH(m_jit.graph(), m_currentNode, "Bad use kind");
1963     }
1964 }
1965
1966 void SpeculativeJIT::compile(Node* node)
1967 {
1968     NodeType op = node->op();
1969     
1970 #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
1971     m_jit.clearRegisterAllocationOffsets();
1972 #endif
1973
1974     switch (op) {
1975     case JSConstant:
1976     case DoubleConstant:
1977     case Int52Constant:
1978     case PhantomDirectArguments:
1979     case PhantomClonedArguments:
1980         initConstantInfo(node);
1981         break;
1982
1983     case LazyJSConstant:
1984         compileLazyJSConstant(node);
1985         break;
1986
1987     case Identity: {
1988         speculate(node, node->child1());
1989         switch (node->child1().useKind()) {
1990         case DoubleRepUse:
1991         case DoubleRepRealUse:
1992         case DoubleRepAnyIntUse: {
1993             SpeculateDoubleOperand op(this, node->child1());
1994             FPRTemporary scratch(this, op);
1995             m_jit.moveDouble(op.fpr(), scratch.fpr());
1996             doubleResult(scratch.fpr(), node);
1997             break;
1998         }
1999         case Int52RepUse: {
2000             SpeculateInt52Operand op(this, node->child1());
2001             GPRTemporary result(this, Reuse, op);
2002             m_jit.move(op.gpr(), result.gpr());
2003             int52Result(result.gpr(), node);
2004             break;
2005         }
2006         default: {
2007             JSValueOperand op(this, node->child1());
2008             GPRTemporary result(this, Reuse, op);
2009             m_jit.move(op.gpr(), result.gpr());
2010             jsValueResult(result.gpr(), node);
2011             break;
2012         }
2013         } // switch
2014         break;
2015     }
2016
2017     case GetLocal: {
2018         AbstractValue& value = m_state.variables().operand(node->local());
2019
2020         // If the CFA is tracking this variable and it found that the variable
2021         // cannot have been assigned, then don't attempt to proceed.
2022         if (value.isClear()) {
2023             m_compileOkay = false;
2024             break;
2025         }
2026         
2027         switch (node->variableAccessData()->flushFormat()) {
2028         case FlushedDouble: {
2029             FPRTemporary result(this);
2030             m_jit.loadDouble(JITCompiler::addressFor(node->machineLocal()), result.fpr());
2031             VirtualRegister virtualRegister = node->virtualRegister();
2032             m_fprs.retain(result.fpr(), virtualRegister, SpillOrderDouble);
2033             generationInfoFromVirtualRegister(virtualRegister).initDouble(node, node->refCount(), result.fpr());
2034             break;
2035         }
2036         
2037         case FlushedInt32: {
2038             GPRTemporary result(this);
2039             m_jit.load32(JITCompiler::payloadFor(node->machineLocal()), result.gpr());
2040             
2041             // Like int32Result, but don't useChildren - our children are phi nodes,
2042             // and don't represent values within this dataflow with virtual registers.
2043             VirtualRegister virtualRegister = node->virtualRegister();
2044             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderInteger);
2045             generationInfoFromVirtualRegister(virtualRegister).initInt32(node, node->refCount(), result.gpr());
2046             break;
2047         }
2048             
2049         case FlushedInt52: {
2050             GPRTemporary result(this);
2051             m_jit.load64(JITCompiler::addressFor(node->machineLocal()), result.gpr());
2052             
2053             VirtualRegister virtualRegister = node->virtualRegister();
2054             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
2055             generationInfoFromVirtualRegister(virtualRegister).initInt52(node, node->refCount(), result.gpr());
2056             break;
2057         }
2058             
2059         default:
2060             GPRTemporary result(this);
2061             m_jit.load64(JITCompiler::addressFor(node->machineLocal()), result.gpr());
2062             
2063             // Like jsValueResult, but don't useChildren - our children are phi nodes,
2064             // and don't represent values within this dataflow with virtual registers.
2065             VirtualRegister virtualRegister = node->virtualRegister();
2066             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
2067             
2068             DataFormat format;
2069             if (isCellSpeculation(value.m_type))
2070                 format = DataFormatJSCell;
2071             else if (isBooleanSpeculation(value.m_type))
2072                 format = DataFormatJSBoolean;
2073             else
2074                 format = DataFormatJS;
2075             
2076             generationInfoFromVirtualRegister(virtualRegister).initJSValue(node, node->refCount(), result.gpr(), format);
2077             break;
2078         }
2079         break;
2080     }
2081
2082     case GetLocalUnlinked: {
2083         GPRTemporary result(this);
2084         
2085         m_jit.load64(JITCompiler::addressFor(node->unlinkedMachineLocal()), result.gpr());
2086         
2087         jsValueResult(result.gpr(), node);
2088         break;
2089     }
2090         
2091     case MovHint: {
2092         compileMovHint(m_currentNode);
2093         noResult(node);
2094         break;
2095     }
2096         
2097     case ZombieHint: {
2098         recordSetLocal(m_currentNode->unlinkedLocal(), VirtualRegister(), DataFormatDead);
2099         noResult(node);
2100         break;
2101     }
2102         
2103     case ExitOK: {
2104         noResult(node);
2105         break;
2106     }
2107         
2108     case SetLocal: {
2109         switch (node->variableAccessData()->flushFormat()) {
2110         case FlushedDouble: {
2111             SpeculateDoubleOperand value(this, node->child1());
2112             m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node->machineLocal()));
2113             noResult(node);
2114             // Indicate that it's no longer necessary to retrieve the value of
2115             // this bytecode variable from registers or other locations in the stack,
2116             // but that it is stored as a double.
2117             recordSetLocal(DataFormatDouble);
2118             break;
2119         }
2120             
2121         case FlushedInt32: {
2122             SpeculateInt32Operand value(this, node->child1());
2123             m_jit.store32(value.gpr(), JITCompiler::payloadFor(node->machineLocal()));
2124             noResult(node);
2125             recordSetLocal(DataFormatInt32);
2126             break;
2127         }
2128             
2129         case FlushedInt52: {
2130             SpeculateInt52Operand value(this, node->child1());
2131             m_jit.store64(value.gpr(), JITCompiler::addressFor(node->machineLocal()));
2132             noResult(node);
2133             recordSetLocal(DataFormatInt52);
2134             break;
2135         }
2136             
2137         case FlushedCell: {
2138             SpeculateCellOperand cell(this, node->child1());
2139             GPRReg cellGPR = cell.gpr();
2140             m_jit.store64(cellGPR, JITCompiler::addressFor(node->machineLocal()));
2141             noResult(node);
2142             recordSetLocal(DataFormatCell);
2143             break;
2144         }
2145             
2146         case FlushedBoolean: {
2147             SpeculateBooleanOperand boolean(this, node->child1());
2148             m_jit.store64(boolean.gpr(), JITCompiler::addressFor(node->machineLocal()));
2149             noResult(node);
2150             recordSetLocal(DataFormatBoolean);
2151             break;
2152         }
2153             
2154         case FlushedJSValue: {
2155             JSValueOperand value(this, node->child1());
2156             m_jit.store64(value.gpr(), JITCompiler::addressFor(node->machineLocal()));
2157             noResult(node);
2158             recordSetLocal(dataFormatFor(node->variableAccessData()->flushFormat()));
2159             break;
2160         }
2161             
2162         default:
2163             DFG_CRASH(m_jit.graph(), node, "Bad flush format");
2164             break;
2165         }
2166
2167         break;
2168     }
2169
2170     case SetArgument:
2171         // This is a no-op; it just marks the fact that the argument is being used.
2172         // But it may be profitable to use this as a hook to run speculation checks
2173         // on arguments, thereby allowing us to trivially eliminate such checks if
2174         // the argument is not used.
2175         recordSetLocal(dataFormatFor(node->variableAccessData()->flushFormat()));
2176         break;
2177
2178     case BitAnd:
2179     case BitOr:
2180     case BitXor:
2181         compileBitwiseOp(node);
2182         break;
2183
2184     case BitRShift:
2185     case BitLShift:
2186     case BitURShift:
2187         compileShiftOp(node);
2188         break;
2189
2190     case UInt32ToNumber: {
2191         compileUInt32ToNumber(node);
2192         break;
2193     }
2194
2195     case DoubleAsInt32: {
2196         compileDoubleAsInt32(node);
2197         break;
2198     }
2199
2200     case ValueToInt32: {
2201         compileValueToInt32(node);
2202         break;
2203     }
2204         
2205     case DoubleRep: {
2206         compileDoubleRep(node);
2207         break;
2208     }
2209         
2210     case ValueRep: {
2211         compileValueRep(node);
2212         break;
2213     }
2214         
2215     case Int52Rep: {
2216         switch (node->child1().useKind()) {
2217         case Int32Use: {
2218             SpeculateInt32Operand operand(this, node->child1());
2219             GPRTemporary result(this, Reuse, operand);
2220             
2221             m_jit.signExtend32ToPtr(operand.gpr(), result.gpr());
2222             
2223             strictInt52Result(result.gpr(), node);
2224             break;
2225         }
2226             
2227         case AnyIntUse: {
2228             GPRTemporary result(this);
2229             GPRReg resultGPR = result.gpr();
2230             
2231             convertAnyInt(node->child1(), resultGPR);
2232             
2233             strictInt52Result(resultGPR, node);
2234             break;
2235         }
2236             
2237         case DoubleRepAnyIntUse: {
2238             SpeculateDoubleOperand value(this, node->child1());
2239             FPRReg valueFPR = value.fpr();
2240             
2241             GPRFlushedCallResult result(this);
2242             GPRReg resultGPR = result.gpr();
2243             
2244             flushRegisters();
2245             
2246             callOperation(operationConvertDoubleToInt52, resultGPR, valueFPR);
2247             
2248             DFG_TYPE_CHECK_WITH_EXIT_KIND(Int52Overflow,
2249                 JSValueRegs(), node->child1(), SpecAnyIntAsDouble,
2250                 m_jit.branch64(
2251                     JITCompiler::Equal, resultGPR,
2252                     JITCompiler::TrustedImm64(JSValue::notInt52)));
2253             
2254             strictInt52Result(resultGPR, node);
2255             break;
2256         }
2257             
2258         default:
2259             DFG_CRASH(m_jit.graph(), node, "Bad use kind");
2260         }
2261         break;
2262     }
2263
2264     case ValueAdd:
2265         compileValueAdd(node);
2266         break;
2267
2268     case StrCat: {
2269         JSValueOperand op1(this, node->child1(), ManualOperandSpeculation);
2270         JSValueOperand op2(this, node->child2(), ManualOperandSpeculation);
2271         JSValueOperand op3(this, node->child3(), ManualOperandSpeculation);
2272         
2273         GPRReg op1GPR = op1.gpr();
2274         GPRReg op2GPR = op2.gpr();
2275         GPRReg op3GPR;
2276         if (node->child3())
2277             op3GPR = op3.gpr();
2278         else
2279             op3GPR = InvalidGPRReg;
2280         
2281         flushRegisters();
2282
2283         GPRFlushedCallResult result(this);
2284         if (node->child3())
2285             callOperation(operationStrCat3, result.gpr(), op1GPR, op2GPR, op3GPR);
2286         else
2287             callOperation(operationStrCat2, result.gpr(), op1GPR, op2GPR);
2288         m_jit.exceptionCheck();
2289         
2290         cellResult(result.gpr(), node);
2291         break;
2292     }
2293
2294     case ArithAdd:
2295         compileArithAdd(node);
2296         break;
2297
2298     case ArithClz32:
2299         compileArithClz32(node);
2300         break;
2301         
2302     case MakeRope:
2303         compileMakeRope(node);
2304         break;
2305
2306     case ArithSub:
2307         compileArithSub(node);
2308         break;
2309
2310     case ArithNegate:
2311         compileArithNegate(node);
2312         break;
2313
2314     case ArithMul:
2315         compileArithMul(node);
2316         break;
2317
2318     case ArithDiv: {
2319         compileArithDiv(node);
2320         break;
2321     }
2322
2323     case ArithMod: {
2324         compileArithMod(node);
2325         break;
2326     }
2327
2328     case ArithAbs: {
2329         switch (node->child1().useKind()) {
2330         case Int32Use: {
2331             SpeculateStrictInt32Operand op1(this, node->child1());
2332             GPRTemporary result(this);
2333             GPRTemporary scratch(this);
2334             
2335             m_jit.move(op1.gpr(), result.gpr());
2336             m_jit.rshift32(result.gpr(), MacroAssembler::TrustedImm32(31), scratch.gpr());
2337             m_jit.add32(scratch.gpr(), result.gpr());
2338             m_jit.xor32(scratch.gpr(), result.gpr());
2339             if (shouldCheckOverflow(node->arithMode()))
2340                 speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchTest32(MacroAssembler::Signed, result.gpr()));
2341             int32Result(result.gpr(), node);
2342             break;
2343         }
2344         
2345         case DoubleRepUse: {
2346             SpeculateDoubleOperand op1(this, node->child1());
2347             FPRTemporary result(this);
2348             
2349             m_jit.absDouble(op1.fpr(), result.fpr());
2350             doubleResult(result.fpr(), node);
2351             break;
2352         }
2353             
2354         default:
2355             DFG_CRASH(m_jit.graph(), node, "Bad use kind");
2356             break;
2357         }
2358         break;
2359     }
2360         
2361     case ArithMin:
2362     case ArithMax: {
2363         switch (node->binaryUseKind()) {
2364         case Int32Use: {
2365             SpeculateStrictInt32Operand op1(this, node->child1());
2366             SpeculateStrictInt32Operand op2(this, node->child2());
2367             GPRTemporary result(this, Reuse, op1);
2368             
2369             MacroAssembler::Jump op1Less = m_jit.branch32(op == ArithMin ? MacroAssembler::LessThan : MacroAssembler::GreaterThan, op1.gpr(), op2.gpr());
2370             m_jit.move(op2.gpr(), result.gpr());
2371             if (op1.gpr() != result.gpr()) {
2372                 MacroAssembler::Jump done = m_jit.jump();
2373                 op1Less.link(&m_jit);
2374                 m_jit.move(op1.gpr(), result.gpr());
2375                 done.link(&m_jit);
2376             } else
2377                 op1Less.link(&m_jit);
2378             
2379             int32Result(result.gpr(), node);
2380             break;
2381         }
2382         
2383         case DoubleRepUse: {
2384             SpeculateDoubleOperand op1(this, node->child1());
2385             SpeculateDoubleOperand op2(this, node->child2());
2386             FPRTemporary result(this, op1);
2387             
2388             FPRReg op1FPR = op1.fpr();
2389             FPRReg op2FPR = op2.fpr();
2390             FPRReg resultFPR = result.fpr();
2391         
2392             MacroAssembler::JumpList done;
2393         
2394             MacroAssembler::Jump op1Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleLessThan : MacroAssembler::DoubleGreaterThan, op1FPR, op2FPR);
2395         
2396             // op2 is eather the lesser one or one of then is NaN
2397             MacroAssembler::Jump op2Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleGreaterThanOrEqual : MacroAssembler::DoubleLessThanOrEqual, op1FPR, op2FPR);
2398         
2399             // Unordered case. We don't know which of op1, op2 is NaN. Manufacture NaN by adding 
2400             // op1 + op2 and putting it into result.
2401             m_jit.addDouble(op1FPR, op2FPR, resultFPR);
2402             done.append(m_jit.jump());
2403         
2404             op2Less.link(&m_jit);
2405             m_jit.moveDouble(op2FPR, resultFPR);
2406         
2407             if (op1FPR != resultFPR) {
2408                 done.append(m_jit.jump());
2409             
2410                 op1Less.link(&m_jit);
2411                 m_jit.moveDouble(op1FPR, resultFPR);
2412             } else
2413                 op1Less.link(&m_jit);
2414         
2415             done.link(&m_jit);
2416         
2417             doubleResult(resultFPR, node);
2418             break;
2419         }
2420             
2421         default:
2422             DFG_CRASH(m_jit.graph(), node, "Bad use kind");
2423             break;
2424         }
2425         break;
2426     }
2427
2428     case ArithPow:
2429         compileArithPow(node);
2430         break;
2431
2432     case ArithSqrt:
2433         compileArithSqrt(node);
2434         break;
2435
2436     case ArithFRound: {
2437         SpeculateDoubleOperand op1(this, node->child1());
2438         FPRTemporary result(this, op1);
2439         
2440         m_jit.convertDoubleToFloat(op1.fpr(), result.fpr());
2441         m_jit.convertFloatToDouble(result.fpr(), result.fpr());
2442         
2443         doubleResult(result.fpr(), node);
2444         break;
2445     }
2446
2447     case ArithRandom:
2448         compileArithRandom(node);
2449         break;
2450
2451     case ArithRound:
2452     case ArithFloor:
2453     case ArithCeil:
2454     case ArithTrunc:
2455         compileArithRounding(node);
2456         break;
2457
2458     case ArithSin: {
2459         SpeculateDoubleOperand op1(this, node->child1());
2460         FPRReg op1FPR = op1.fpr();
2461
2462         flushRegisters();
2463         
2464         FPRResult result(this);
2465         callOperation(sin, result.fpr(), op1FPR);
2466         doubleResult(result.fpr(), node);
2467         break;
2468     }
2469
2470     case ArithCos: {
2471         SpeculateDoubleOperand op1(this, node->child1());
2472         FPRReg op1FPR = op1.fpr();
2473
2474         flushRegisters();
2475         
2476         FPRResult result(this);
2477         callOperation(cos, result.fpr(), op1FPR);
2478         doubleResult(result.fpr(), node);
2479         break;
2480     }
2481
2482     case ArithLog:
2483         compileArithLog(node);
2484         break;
2485
2486     case LogicalNot:
2487         compileLogicalNot(node);
2488         break;
2489
2490     case CompareLess:
2491         if (compare(node, JITCompiler::LessThan, JITCompiler::DoubleLessThan, operationCompareLess))
2492             return;
2493         break;
2494
2495     case CompareLessEq:
2496         if (compare(node, JITCompiler::LessThanOrEqual, JITCompiler::DoubleLessThanOrEqual, operationCompareLessEq))
2497             return;
2498         break;
2499
2500     case CompareGreater:
2501         if (compare(node, JITCompiler::GreaterThan, JITCompiler::DoubleGreaterThan, operationCompareGreater))
2502             return;
2503         break;
2504
2505     case CompareGreaterEq:
2506         if (compare(node, JITCompiler::GreaterThanOrEqual, JITCompiler::DoubleGreaterThanOrEqual, operationCompareGreaterEq))
2507             return;
2508         break;
2509
2510     case CompareEq:
2511         if (compare(node, JITCompiler::Equal, JITCompiler::DoubleEqual, operationCompareEq))
2512             return;
2513         break;
2514
2515     case CompareStrictEq:
2516         if (compileStrictEq(node))
2517             return;
2518         break;
2519
2520     case StringCharCodeAt: {
2521         compileGetCharCodeAt(node);
2522         break;
2523     }
2524
2525     case StringCharAt: {
2526         // Relies on StringCharAt node having same basic layout as GetByVal
2527         compileGetByValOnString(node);
2528         break;
2529     }
2530
2531     case StringFromCharCode: {
2532         compileFromCharCode(node);
2533         break;
2534     }
2535         
2536     case CheckArray: {
2537         checkArray(node);
2538         break;
2539     }
2540         
2541     case Arrayify:
2542     case ArrayifyToStructure: {
2543         arrayify(node);
2544         break;
2545     }
2546
2547     case GetByVal: {
2548         switch (node->arrayMode().type()) {
2549         case Array::SelectUsingPredictions:
2550         case Array::ForceExit:
2551             DFG_CRASH(m_jit.graph(), node, "Bad array mode type");
2552             break;
2553         case Array::Undecided: {
2554             SpeculateStrictInt32Operand index(this, node->child2());
2555             GPRTemporary result(this, Reuse, index);
2556             GPRReg indexGPR = index.gpr();
2557             GPRReg resultGPR = result.gpr();
2558
2559             speculationCheck(OutOfBounds, JSValueRegs(), node,
2560                 m_jit.branch32(MacroAssembler::LessThan, indexGPR, MacroAssembler::TrustedImm32(0)));
2561
2562             use(node->child1());
2563             index.use();
2564
2565             m_jit.move(MacroAssembler::TrustedImm64(ValueUndefined), resultGPR);
2566             jsValueResult(resultGPR, node, UseChildrenCalledExplicitly);
2567             break;
2568         }
2569         case Array::Generic: {
2570             JSValueOperand base(this, node->child1());
2571             JSValueOperand property(this, node->child2());
2572             GPRReg baseGPR = base.gpr();
2573             GPRReg propertyGPR = property.gpr();
2574             
2575             flushRegisters();
2576             GPRFlushedCallResult result(this);
2577             callOperation(operationGetByVal, result.gpr(), baseGPR, propertyGPR);
2578             m_jit.exceptionCheck();
2579             
2580             jsValueResult(result.gpr(), node);
2581             break;
2582         }
2583         case Array::Int32:
2584         case Array::Contiguous: {
2585             if (node->arrayMode().isInBounds()) {
2586                 SpeculateStrictInt32Operand property(this, node->child2());
2587                 StorageOperand storage(this, node->child3());
2588                 
2589                 GPRReg propertyReg = property.gpr();
2590                 GPRReg storageReg = storage.gpr();
2591                 
2592                 if (!m_compileOkay)
2593                     return;
2594                 
2595                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2596                 
2597                 GPRTemporary result(this);
2598                 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.gpr());
2599                 if (node->arrayMode().isSaneChain()) {
2600                     ASSERT(node->arrayMode().type() == Array::Contiguous);
2601                     JITCompiler::Jump notHole = m_jit.branchTest64(
2602                         MacroAssembler::NonZero, result.gpr());
2603                     m_jit.move(TrustedImm64(JSValue::encode(jsUndefined())), result.gpr());
2604                     notHole.link(&m_jit);
2605                 } else {
2606                     speculationCheck(
2607                         LoadFromHole, JSValueRegs(), 0,
2608                         m_jit.branchTest64(MacroAssembler::Zero, result.gpr()));
2609                 }
2610                 jsValueResult(result.gpr(), node, node->arrayMode().type() == Array::Int32 ? DataFormatJSInt32 : DataFormatJS);
2611                 break;
2612             }
2613             
2614             SpeculateCellOperand base(this, node->child1());
2615             SpeculateStrictInt32Operand property(this, node->child2());
2616             StorageOperand storage(this, node->child3());
2617             
2618             GPRReg baseReg = base.gpr();
2619             GPRReg propertyReg = property.gpr();
2620             GPRReg storageReg = storage.gpr();
2621             
2622             if (!m_compileOkay)
2623                 return;
2624             
2625             GPRTemporary result(this);
2626             GPRReg resultReg = result.gpr();
2627             
2628             MacroAssembler::JumpList slowCases;
2629             
2630             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2631             
2632             m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
2633             slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, resultReg));
2634             
2635             addSlowPathGenerator(
2636                 slowPathCall(
2637                     slowCases, this, operationGetByValArrayInt,
2638                     result.gpr(), baseReg, propertyReg));
2639             
2640             jsValueResult(resultReg, node);
2641             break;
2642         }
2643
2644         case Array::Double: {
2645             if (node->arrayMode().isInBounds()) {
2646                 SpeculateStrictInt32Operand property(this, node->child2());
2647                 StorageOperand storage(this, node->child3());
2648             
2649                 GPRReg propertyReg = property.gpr();
2650                 GPRReg storageReg = storage.gpr();
2651             
2652                 if (!m_compileOkay)
2653                     return;
2654             
2655                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2656             
2657                 FPRTemporary result(this);
2658                 m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.fpr());
2659                 if (!node->arrayMode().isSaneChain())
2660                     speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, result.fpr(), result.fpr()));
2661                 doubleResult(result.fpr(), node);
2662                 break;
2663             }
2664
2665             SpeculateCellOperand base(this, node->child1());
2666             SpeculateStrictInt32Operand property(this, node->child2());
2667             StorageOperand storage(this, node->child3());
2668             
2669             GPRReg baseReg = base.gpr();
2670             GPRReg propertyReg = property.gpr();
2671             GPRReg storageReg = storage.gpr();
2672             
2673             if (!m_compileOkay)
2674                 return;
2675             
2676             GPRTemporary result(this);
2677             FPRTemporary temp(this);
2678             GPRReg resultReg = result.gpr();
2679             FPRReg tempReg = temp.fpr();
2680             
2681             MacroAssembler::JumpList slowCases;
2682             
2683             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2684             
2685             m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), tempReg);
2686             slowCases.append(m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, tempReg, tempReg));
2687             boxDouble(tempReg, resultReg);
2688             
2689             addSlowPathGenerator(
2690                 slowPathCall(
2691                     slowCases, this, operationGetByValArrayInt,
2692                     result.gpr(), baseReg, propertyReg));
2693             
2694             jsValueResult(resultReg, node);
2695             break;
2696         }
2697
2698         case Array::ArrayStorage:
2699         case Array::SlowPutArrayStorage: {
2700             if (node->arrayMode().isInBounds()) {
2701                 SpeculateStrictInt32Operand property(this, node->child2());
2702                 StorageOperand storage(this, node->child3());
2703             
2704                 GPRReg propertyReg = property.gpr();
2705                 GPRReg storageReg = storage.gpr();
2706             
2707                 if (!m_compileOkay)
2708                     return;
2709             
2710                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
2711             
2712                 GPRTemporary result(this);
2713                 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), result.gpr());
2714                 speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchTest64(MacroAssembler::Zero, result.gpr()));
2715             
2716                 jsValueResult(result.gpr(), node);
2717                 break;
2718             }
2719
2720             SpeculateCellOperand base(this, node->child1());
2721             SpeculateStrictInt32Operand property(this, node->child2());
2722             StorageOperand storage(this, node->child3());
2723             
2724             GPRReg baseReg = base.gpr();
2725             GPRReg propertyReg = property.gpr();
2726             GPRReg storageReg = storage.gpr();
2727             
2728             if (!m_compileOkay)
2729                 return;
2730             
2731             GPRTemporary result(this);
2732             GPRReg resultReg = result.gpr();
2733             
2734             MacroAssembler::JumpList slowCases;
2735             
2736             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
2737     
2738             m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), resultReg);
2739             slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, resultReg));
2740     
2741             addSlowPathGenerator(
2742                 slowPathCall(
2743                     slowCases, this, operationGetByValArrayInt,
2744                     result.gpr(), baseReg, propertyReg));
2745             
2746             jsValueResult(resultReg, node);
2747             break;
2748         }
2749         case Array::String:
2750             compileGetByValOnString(node);
2751             break;
2752         case Array::DirectArguments:
2753             compileGetByValOnDirectArguments(node);
2754             break;
2755         case Array::ScopedArguments:
2756             compileGetByValOnScopedArguments(node);
2757             break;
2758         default: {
2759             TypedArrayType type = node->arrayMode().typedArrayType();
2760             if (isInt(type))
2761                 compileGetByValOnIntTypedArray(node, type);
2762             else
2763                 compileGetByValOnFloatTypedArray(node, type);
2764         } }
2765         break;
2766     }
2767
2768     case GetByValWithThis: {
2769         JSValueOperand base(this, node->child1());
2770         GPRReg baseGPR = base.gpr();
2771         JSValueOperand thisValue(this, node->child2());
2772         GPRReg thisValueGPR = thisValue.gpr();
2773         JSValueOperand subscript(this, node->child3());
2774         GPRReg subscriptGPR = subscript.gpr();
2775
2776         GPRFlushedCallResult result(this);
2777         GPRReg resultGPR = result.gpr();
2778
2779         flushRegisters();
2780         callOperation(operationGetByValWithThis, resultGPR, baseGPR, thisValueGPR, subscriptGPR);
2781         m_jit.exceptionCheck();
2782
2783         jsValueResult(resultGPR, node);
2784         break;
2785     }
2786
2787     case PutByValDirect:
2788     case PutByVal:
2789     case PutByValAlias: {
2790         Edge child1 = m_jit.graph().varArgChild(node, 0);
2791         Edge child2 = m_jit.graph().varArgChild(node, 1);
2792         Edge child3 = m_jit.graph().varArgChild(node, 2);
2793         Edge child4 = m_jit.graph().varArgChild(node, 3);
2794         
2795         ArrayMode arrayMode = node->arrayMode().modeForPut();
2796         bool alreadyHandled = false;
2797         
2798         switch (arrayMode.type()) {
2799         case Array::SelectUsingPredictions:
2800         case Array::ForceExit:
2801             DFG_CRASH(m_jit.graph(), node, "Bad array mode type");
2802             break;
2803         case Array::Generic: {
2804             DFG_ASSERT(m_jit.graph(), node, node->op() == PutByVal || node->op() == PutByValDirect);
2805             
2806             JSValueOperand arg1(this, child1);
2807             JSValueOperand arg2(this, child2);
2808             JSValueOperand arg3(this, child3);
2809             GPRReg arg1GPR = arg1.gpr();
2810             GPRReg arg2GPR = arg2.gpr();
2811             GPRReg arg3GPR = arg3.gpr();
2812             flushRegisters();
2813             if (node->op() == PutByValDirect)
2814                 callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValDirectStrict : operationPutByValDirectNonStrict, arg1GPR, arg2GPR, arg3GPR);
2815             else
2816                 callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValStrict : operationPutByValNonStrict, arg1GPR, arg2GPR, arg3GPR);
2817             m_jit.exceptionCheck();
2818             
2819             noResult(node);
2820             alreadyHandled = true;
2821             break;
2822         }
2823         default:
2824             break;
2825         }
2826         
2827         if (alreadyHandled)
2828             break;
2829         
2830         // FIXME: the base may not be necessary for some array access modes. But we have to
2831         // keep it alive to this point, so it's likely to be in a register anyway. Likely
2832         // no harm in locking it here.
2833         SpeculateCellOperand base(this, child1);
2834         SpeculateStrictInt32Operand property(this, child2);
2835         
2836         GPRReg baseReg = base.gpr();
2837         GPRReg propertyReg = property.gpr();
2838
2839         switch (arrayMode.type()) {
2840         case Array::Int32:
2841         case Array::Contiguous: {
2842             JSValueOperand value(this, child3, ManualOperandSpeculation);
2843
2844             GPRReg valueReg = value.gpr();
2845         
2846             if (!m_compileOkay)
2847                 return;
2848             
2849             if (arrayMode.type() == Array::Int32) {
2850                 DFG_TYPE_CHECK(
2851                     JSValueRegs(valueReg), child3, SpecInt32Only,
2852                     m_jit.branch64(
2853                         MacroAssembler::Below, valueReg, GPRInfo::tagTypeNumberRegister));
2854             }
2855
2856             StorageOperand storage(this, child4);
2857             GPRReg storageReg = storage.gpr();
2858
2859             if (node->op() == PutByValAlias) {
2860                 // Store the value to the array.
2861                 GPRReg propertyReg = property.gpr();
2862                 GPRReg valueReg = value.gpr();
2863                 m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
2864                 
2865                 noResult(node);
2866                 break;
2867             }
2868             
2869             GPRTemporary temporary;
2870             GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
2871
2872             MacroAssembler::Jump slowCase;
2873             
2874             if (arrayMode.isInBounds()) {
2875                 speculationCheck(
2876                     OutOfBounds, JSValueRegs(), 0,
2877                     m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2878             } else {
2879                 MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
2880                 
2881                 slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfVectorLength()));
2882                 
2883                 if (!arrayMode.isOutOfBounds())
2884                     speculationCheck(OutOfBounds, JSValueRegs(), 0, slowCase);
2885                 
2886                 m_jit.add32(TrustedImm32(1), propertyReg, temporaryReg);
2887                 m_jit.store32(temporaryReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
2888                 
2889                 inBounds.link(&m_jit);
2890             }
2891             
2892             m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
2893
2894             base.use();
2895             property.use();
2896             value.use();
2897             storage.use();
2898             
2899             if (arrayMode.isOutOfBounds()) {
2900                 if (node->op() == PutByValDirect) {
2901                     addSlowPathGenerator(slowPathCall(
2902                         slowCase, this,
2903                         m_jit.codeBlock()->isStrictMode() ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValDirectBeyondArrayBoundsNonStrict,
2904                         NoResult, baseReg, propertyReg, valueReg));
2905                 } else {
2906                     addSlowPathGenerator(slowPathCall(
2907                         slowCase, this,
2908                         m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
2909                         NoResult, baseReg, propertyReg, valueReg));
2910                 }
2911             }
2912
2913             noResult(node, UseChildrenCalledExplicitly);
2914             break;
2915         }
2916             
2917         case Array::Double: {
2918             compileDoublePutByVal(node, base, property);
2919             break;
2920         }
2921             
2922         case Array::ArrayStorage:
2923         case Array::SlowPutArrayStorage: {
2924             JSValueOperand value(this, child3);
2925
2926             GPRReg valueReg = value.gpr();
2927         
2928             if (!m_compileOkay)
2929                 return;
2930
2931             StorageOperand storage(this, child4);
2932             GPRReg storageReg = storage.gpr();
2933
2934             if (node->op() == PutByValAlias) {
2935                 // Store the value to the array.
2936                 GPRReg propertyReg = property.gpr();
2937                 GPRReg valueReg = value.gpr();
2938                 m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
2939                 
2940                 noResult(node);
2941                 break;
2942             }
2943             
2944             GPRTemporary temporary;
2945             GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
2946
2947             MacroAssembler::JumpList slowCases;
2948
2949             MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
2950             if (!arrayMode.isOutOfBounds())
2951                 speculationCheck(OutOfBounds, JSValueRegs(), 0, beyondArrayBounds);
2952             else
2953                 slowCases.append(beyondArrayBounds);
2954
2955             // Check if we're writing to a hole; if so increment m_numValuesInVector.
2956             if (arrayMode.isInBounds()) {
2957                 speculationCheck(
2958                     StoreToHole, JSValueRegs(), 0,
2959                     m_jit.branchTest64(MacroAssembler::Zero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]))));
2960             } else {
2961                 MacroAssembler::Jump notHoleValue = m_jit.branchTest64(MacroAssembler::NonZero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
2962                 if (arrayMode.isSlowPut()) {
2963                     // This is sort of strange. If we wanted to optimize this code path, we would invert
2964                     // the above branch. But it's simply not worth it since this only happens if we're
2965                     // already having a bad time.
2966                     slowCases.append(m_jit.jump());
2967                 } else {
2968                     m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, ArrayStorage::numValuesInVectorOffset()));
2969                 
2970                     // If we're writing to a hole we might be growing the array; 
2971                     MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
2972                     m_jit.add32(TrustedImm32(1), propertyReg, temporaryReg);
2973                     m_jit.store32(temporaryReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
2974                 
2975                     lengthDoesNotNeedUpdate.link(&m_jit);
2976                 }
2977                 notHoleValue.link(&m_jit);
2978             }
2979     
2980             // Store the value to the array.
2981             m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
2982
2983             base.use();
2984             property.use();
2985             value.use();
2986             storage.use();
2987             
2988             if (!slowCases.empty()) {
2989                 if (node->op() == PutByValDirect) {
2990                     addSlowPathGenerator(slowPathCall(
2991                         slowCases, this,
2992                         m_jit.codeBlock()->isStrictMode() ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValDirectBeyondArrayBoundsNonStrict,
2993                         NoResult, baseReg, propertyReg, valueReg));
2994                 } else {
2995                     addSlowPathGenerator(slowPathCall(
2996                         slowCases, this,
2997                         m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
2998                         NoResult, baseReg, propertyReg, valueReg));
2999                 }
3000             }
3001
3002             noResult(node, UseChildrenCalledExplicitly);
3003             break;
3004         }
3005             
3006         default: {
3007             TypedArrayType type = arrayMode.typedArrayType();
3008             if (isInt(type))
3009                 compilePutByValForIntTypedArray(base.gpr(), property.gpr(), node, type);
3010             else
3011                 compilePutByValForFloatTypedArray(base.gpr(), property.gpr(), node, type);
3012         } }
3013
3014         break;
3015     }
3016
3017     case RegExpExec: {
3018         bool sample = false;
3019
3020         if (sample)
3021             m_jit.incrementSuperSamplerCount();
3022         
3023         SpeculateCellOperand globalObject(this, node->child1());
3024         GPRReg globalObjectGPR = globalObject.gpr();
3025         
3026         if (node->child2().useKind() == RegExpObjectUse) {
3027             if (node->child3().useKind() == StringUse) {
3028                 SpeculateCellOperand base(this, node->child2());
3029                 SpeculateCellOperand argument(this, node->child3());
3030                 GPRReg baseGPR = base.gpr();
3031                 GPRReg argumentGPR = argument.gpr();
3032                 speculateRegExpObject(node->child2(), baseGPR);
3033                 speculateString(node->child3(), argumentGPR);
3034                 
3035                 flushRegisters();
3036                 GPRFlushedCallResult result(this);
3037                 callOperation(operationRegExpExecString, result.gpr(), globalObjectGPR, baseGPR, argumentGPR);
3038                 m_jit.exceptionCheck();
3039                 
3040                 jsValueResult(result.gpr(), node);
3041
3042                 if (sample)
3043                     m_jit.decrementSuperSamplerCount();
3044                 break;
3045             }
3046             
3047             SpeculateCellOperand base(this, node->child2());
3048             JSValueOperand argument(this, node->child3());
3049             GPRReg baseGPR = base.gpr();
3050             GPRReg argumentGPR = argument.gpr();
3051             speculateRegExpObject(node->child2(), baseGPR);
3052         
3053             flushRegisters();
3054             GPRFlushedCallResult result(this);
3055             callOperation(operationRegExpExec, result.gpr(), globalObjectGPR, baseGPR, argumentGPR);
3056             m_jit.exceptionCheck();
3057         
3058             jsValueResult(result.gpr(), node);
3059
3060             if (sample)
3061                 m_jit.decrementSuperSamplerCount();
3062             break;
3063         }
3064         
3065         JSValueOperand base(this, node->child2());
3066         JSValueOperand argument(this, node->child3());
3067         GPRReg baseGPR = base.gpr();
3068         GPRReg argumentGPR = argument.gpr();
3069         
3070         flushRegisters();
3071         GPRFlushedCallResult result(this);
3072         callOperation(operationRegExpExecGeneric, result.gpr(), globalObjectGPR, baseGPR, argumentGPR);
3073         m_jit.exceptionCheck();
3074         
3075         jsValueResult(result.gpr(), node);
3076
3077         if (sample)
3078             m_jit.decrementSuperSamplerCount();
3079         break;
3080     }
3081
3082     case RegExpTest: {
3083         SpeculateCellOperand globalObject(this, node->child1());
3084         GPRReg globalObjectGPR = globalObject.gpr();
3085         
3086         if (node->child2().useKind() == RegExpObjectUse) {
3087             if (node->child3().useKind() == StringUse) {
3088                 SpeculateCellOperand base(this, node->child2());
3089                 SpeculateCellOperand argument(this, node->child3());
3090                 GPRReg baseGPR = base.gpr();
3091                 GPRReg argumentGPR = argument.gpr();
3092                 speculateRegExpObject(node->child2(), baseGPR);
3093                 speculateString(node->child3(), argumentGPR);
3094                 
3095                 flushRegisters();
3096                 GPRFlushedCallResult result(this);
3097                 callOperation(operationRegExpTestString, result.gpr(), globalObjectGPR, baseGPR, argumentGPR);
3098                 m_jit.exceptionCheck();
3099                 
3100                 m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
3101                 jsValueResult(result.gpr(), node);
3102                 break;
3103             }
3104             
3105             SpeculateCellOperand base(this, node->child2());
3106             JSValueOperand argument(this, node->child3());
3107             GPRReg baseGPR = base.gpr();
3108             GPRReg argumentGPR = argument.gpr();
3109             speculateRegExpObject(node->child2(), baseGPR);
3110         
3111             flushRegisters();
3112             GPRFlushedCallResult result(this);
3113             callOperation(operationRegExpTest, result.gpr(), globalObjectGPR, baseGPR, argumentGPR);
3114             m_jit.exceptionCheck();
3115         
3116             m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
3117             jsValueResult(result.gpr(), node);
3118             break;
3119         }
3120         
3121         JSValueOperand base(this, node->child2());
3122         JSValueOperand argument(this, node->child3());
3123         GPRReg baseGPR = base.gpr();
3124         GPRReg argumentGPR = argument.gpr();
3125         
3126         flushRegisters();
3127         GPRFlushedCallResult result(this);
3128         callOperation(operationRegExpTestGeneric, result.gpr(), globalObjectGPR, baseGPR, argumentGPR);
3129         m_jit.exceptionCheck();
3130         
3131         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
3132         jsValueResult(result.gpr(), node, DataFormatJSBoolean);
3133         break;
3134     }
3135
3136     case StringReplace:
3137     case StringReplaceRegExp: {
3138         bool sample = false;
3139
3140         if (sample)
3141             m_jit.incrementSuperSamplerCount();
3142         
3143         if (node->child1().useKind() == StringUse
3144             && node->child2().useKind() == RegExpObjectUse
3145             && node->child3().useKind() == StringUse) {
3146             if (JSString* replace = node->child3()->dynamicCastConstant<JSString*>()) {
3147                 if (!replace->length()) {
3148                     SpeculateCellOperand string(this, node->child1());
3149                     SpeculateCellOperand regExp(this, node->child2());
3150                     GPRReg stringGPR = string.gpr();
3151                     GPRReg regExpGPR = regExp.gpr();
3152                     speculateString(node->child1(), stringGPR);
3153                     speculateRegExpObject(node->child2(), regExpGPR);
3154
3155                     flushRegisters();
3156                     GPRFlushedCallResult result(this);
3157                     callOperation(
3158                         operationStringProtoFuncReplaceRegExpEmptyStr, result.gpr(), stringGPR,
3159                         regExpGPR);
3160                     m_jit.exceptionCheck();
3161                     cellResult(result.gpr(), node);
3162                     if (sample)
3163                         m_jit.decrementSuperSamplerCount();
3164                     break;
3165                 }
3166             }
3167             
3168             SpeculateCellOperand string(this, node->child1());
3169             SpeculateCellOperand regExp(this, node->child2());
3170             SpeculateCellOperand replace(this, node->child3());
3171             GPRReg stringGPR = string.gpr();
3172             GPRReg regExpGPR = regExp.gpr();
3173             GPRReg replaceGPR = replace.gpr();
3174             speculateString(node->child1(), stringGPR);
3175             speculateRegExpObject(node->child2(), regExpGPR);
3176             speculateString(node->child3(), replaceGPR);
3177             
3178             flushRegisters();
3179             GPRFlushedCallResult result(this);
3180             callOperation(
3181                 operationStringProtoFuncReplaceRegExpString, result.gpr(), stringGPR, regExpGPR,
3182                 replaceGPR);
3183             m_jit.exceptionCheck();
3184             cellResult(result.gpr(), node);
3185             if (sample)
3186                 m_jit.decrementSuperSamplerCount();
3187             break;
3188         }
3189
3190         // If we fixed up the edge of child2, we inserted a Check(@child2, String).
3191         OperandSpeculationMode child2SpeculationMode = AutomaticOperandSpeculation;
3192         if (node->child2().useKind() == StringUse)
3193             child2SpeculationMode = ManualOperandSpeculation;
3194
3195         JSValueOperand string(this, node->child1());
3196         JSValueOperand search(this, node->child2(), child2SpeculationMode);
3197         JSValueOperand replace(this, node->child3());
3198         GPRReg stringGPR = string.gpr();
3199         GPRReg searchGPR = search.gpr();
3200         GPRReg replaceGPR = replace.gpr();
3201         
3202         flushRegisters();
3203         GPRFlushedCallResult result(this);
3204         callOperation(
3205             operationStringProtoFuncReplaceGeneric, result.gpr(), stringGPR, searchGPR,
3206             replaceGPR);
3207         m_jit.exceptionCheck();
3208         cellResult(result.gpr(), node);
3209         if (sample)
3210             m_jit.decrementSuperSamplerCount();
3211         break;
3212     }
3213         
3214     case GetRegExpObjectLastIndex: {
3215         compileGetRegExpObjectLastIndex(node);
3216         break;
3217     }
3218         
3219     case SetRegExpObjectLastIndex: {
3220         compileSetRegExpObjectLastIndex(node);
3221         break;
3222     }
3223
3224     case RecordRegExpCachedResult: {
3225         compileRecordRegExpCachedResult(node);
3226         break;
3227     }
3228         
3229     case ArrayPush: {
3230         ASSERT(node->arrayMode().isJSArray());
3231         
3232         SpeculateCellOperand base(this, node->child1());
3233         GPRTemporary storageLength(this);
3234         
3235         GPRReg baseGPR = base.gpr();
3236         GPRReg storageLengthGPR = storageLength.gpr();
3237         
3238         StorageOperand storage(this, node->child3());
3239         GPRReg storageGPR = storage.gpr();
3240
3241         switch (node->arrayMode().type()) {
3242         case Array::Int32:
3243         case Array::Contiguous: {
3244             JSValueOperand value(this, node->child2(), ManualOperandSpeculation);
3245             GPRReg valueGPR = value.gpr();
3246
3247             if (node->arrayMode().type() == Array::Int32) {
3248                 DFG_TYPE_CHECK(
3249                     JSValueRegs(valueGPR), node->child2(), SpecInt32Only,
3250                     m_jit.branch64(
3251                         MacroAssembler::Below, valueGPR, GPRInfo::tagTypeNumberRegister));
3252             }
3253
3254             m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
3255             MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
3256             m_jit.store64(valueGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
3257             m_jit.add32(TrustedImm32(1), storageLengthGPR);
3258             m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
3259             m_jit.or64(GPRInfo::tagTypeNumberRegister, storageLengthGPR);
3260             
3261             addSlowPathGenerator(
3262                 slowPathCall(
3263                     slowPath, this, operationArrayPush, storageLengthGPR,
3264                     valueGPR, baseGPR));
3265         
3266             jsValueResult(storageLengthGPR, node);
3267             break;
3268         }
3269             
3270         case Array::Double: {
3271             SpeculateDoubleOperand value(this, node->child2());
3272             FPRReg valueFPR = value.fpr();
3273
3274             DFG_TYPE_CHECK(
3275                 JSValueRegs(), node->child2(), SpecDoubleReal,
3276                 m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, valueFPR, valueFPR));
3277             
3278             m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
3279             MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
3280             m_jit.storeDouble(valueFPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
3281             m_jit.add32(TrustedImm32(1), storageLengthGPR);
3282             m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
3283             m_jit.or64(GPRInfo::tagTypeNumberRegister, storageLengthGPR);
3284             
3285             addSlowPathGenerator(
3286                 slowPathCall(
3287                     slowPath, this, operationArrayPushDouble, storageLengthGPR,
3288                     valueFPR, baseGPR));
3289         
3290             jsValueResult(storageLengthGPR, node);
3291             break;
3292         }
3293             
3294         case Array::ArrayStorage: {
3295             JSValueOperand value(this, node->child2());
3296             GPRReg valueGPR = value.gpr();
3297
3298             m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
3299         
3300             // Refuse to handle bizarre lengths.
3301             speculationCheck(Uncountable, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::Above, storageLengthGPR, TrustedImm32(0x7ffffffe)));
3302         
3303             MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset()));
3304         
3305             m_jit.store64(valueGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
3306         
3307             m_jit.add32(TrustedImm32(1), storageLengthGPR);
3308             m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()));
3309             m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
3310             m_jit.or64(GPRInfo::tagTypeNumberRegister, storageLengthGPR);
3311         
3312             addSlowPathGenerator(
3313                 slowPathCall(
3314                     slowPath, this, operationArrayPush, NoResult, storageLengthGPR,
3315                     valueGPR, baseGPR));
3316         
3317             jsValueResult(storageLengthGPR, node);
3318             break;
3319         }
3320             
3321         default:
3322             CRASH();
3323             break;
3324         }
3325         break;
3326     }
3327         
3328     case ArrayPop: {
3329         ASSERT(node->arrayMode().isJSArray());
3330
3331         SpeculateCellOperand base(this, node->child1());
3332         StorageOperand storage(this, node->child2());
3333         GPRTemporary value(this);
3334         GPRTemporary storageLength(this);
3335         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().
3336         
3337         GPRReg baseGPR = base.gpr();
3338         GPRReg storageGPR = storage.gpr();
3339         GPRReg valueGPR = value.gpr();
3340         GPRReg storageLengthGPR = storageLength.gpr();
3341         FPRReg tempFPR = temp.fpr();
3342         
3343         switch (node->arrayMode().type()) {
3344         case Array::Int32:
3345         case Array::Double:
3346         case Array::Contiguous: {
3347             m_jit.load32(
3348                 MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
3349             MacroAssembler::Jump undefinedCase =
3350                 m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR);
3351             m_jit.sub32(TrustedImm32(1), storageLengthGPR);
3352             m_jit.store32(
3353                 storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
3354             MacroAssembler::Jump slowCase;
3355             if (node->arrayMode().type() == Array::Double) {
3356                 m_jit.loadDouble(
3357                     MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight),
3358                     tempFPR);
3359                 // FIXME: This would not have to be here if changing the publicLength also zeroed the values between the old
3360                 // length and the new length.
3361                 m_jit.store64(
3362                     MacroAssembler::TrustedImm64(bitwise_cast<int64_t>(PNaN)), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
3363                 slowCase = m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, tempFPR, tempFPR);
3364                 boxDouble(tempFPR, valueGPR);
3365             } else {
3366                 m_jit.load64(
3367                     MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight),
3368                     valueGPR);
3369                 // FIXME: This would not have to be here if changing the publicLength also zeroed the values between the old
3370                 // length and the new length.
3371                 m_jit.store64(
3372                 MacroAssembler::TrustedImm64((int64_t)0), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
3373                 slowCase = m_jit.branchTest64(MacroAssembler::Zero, valueGPR);
3374             }
3375
3376             addSlowPathGenerator(
3377                 slowPathMove(
3378                     undefinedCase, this,
3379                     MacroAssembler::TrustedImm64(JSValue::encode(jsUndefined())), valueGPR));
3380             addSlowPathGenerator(
3381                 slowPathCall(
3382                     slowCase, this, operationArrayPopAndRecoverLength, valueGPR, baseGPR));
3383             
3384             // We can't know for sure that the result is an int because of the slow paths. :-/
3385             jsValueResult(valueGPR, node);
3386             break;
3387         }
3388             
3389         case Array::ArrayStorage: {
3390             m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
3391         
3392             JITCompiler::Jump undefinedCase =
3393                 m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR);
3394         
3395             m_jit.sub32(TrustedImm32(1), storageLengthGPR);
3396         
3397             JITCompiler::JumpList slowCases;
3398             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset())));
3399         
3400             m_jit.load64(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), valueGPR);
3401             slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, valueGPR));
3402         
3403             m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()));
3404         
3405             m_jit.store64(MacroAssembler::TrustedImm64((int64_t)0), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
3406             m_jit.sub32(MacroAssembler::TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
3407         
3408             addSlowPathGenerator(
3409                 slowPathMove(
3410                     undefinedCase, this,
3411                     MacroAssembler::TrustedImm64(JSValue::encode(jsUndefined())), valueGPR));
3412         
3413             addSlowPathGenerator(
3414                 slowPathCall(
3415                     slowCases, this, operationArrayPop, valueGPR, baseGPR));
3416
3417             jsValueResult(valueGPR, node);
3418             break;
3419         }
3420             
3421         default:
3422             CRASH();
3423             break;
3424         }
3425         break;
3426     }
3427
3428     case DFG::Jump: {
3429         jump(node->targetBlock());
3430         noResult(node);
3431         break;
3432     }
3433
3434     case Branch:
3435         emitBranch(node);
3436         break;
3437         
3438     case Switch:
3439         emitSwitch(node);
3440         break;
3441
3442     case Return: {
3443         ASSERT(GPRInfo::callFrameRegister != GPRInfo::regT1);
3444         ASSERT(GPRInfo::regT1 != GPRInfo::returnValueGPR);
3445         ASSERT(GPRInfo::returnValueGPR != GPRInfo::callFrameRegister);
3446
3447         // Return the result in returnValueGPR.
3448         JSValueOperand op1(this, node->child1());
3449         m_jit.move(op1.gpr(), GPRInfo::returnValueGPR);
3450
3451         m_jit.emitRestoreCalleeSaves();
3452         m_jit.emitFunctionEpilogue();
3453         m_jit.ret();
3454         
3455         noResult(node);
3456         break;
3457     }
3458         
3459     case Throw:
3460     case ThrowReferenceError: {
3461         // We expect that throw statements are rare and are intended to exit the code block
3462         // anyway, so we just OSR back to the old JIT for now.
3463         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
3464         break;
3465     }
3466         
3467     case BooleanToNumber: {
3468         switch (node->child1().useKind()) {
3469         case BooleanUse: {
3470             JSValueOperand value(this, node->child1(), ManualOperandSpeculation);
3471             GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add).
3472             
3473             m_jit.move(value.gpr(), result.gpr());
3474             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), result.gpr());
3475             DFG_TYPE_CHECK(
3476                 JSValueRegs(value.gpr()), node->child1(), SpecBoolean, m_jit.branchTest64(
3477                     JITCompiler::NonZero, result.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
3478
3479             int32Result(result.gpr(), node);
3480             break;
3481         }
3482             
3483         case UntypedUse: {
3484             JSValueOperand value(this, node->child1());
3485             GPRTemporary result(this);
3486             
3487             if (!m_interpreter.needsTypeCheck(node->child1(), SpecBoolInt32 | SpecBoolean)) {
3488                 m_jit.move(value.gpr(), result.gpr());
3489                 m_jit.and32(TrustedImm32(1), result.gpr());
3490                 int32Result(result.gpr(), node);
3491                 break;
3492             }
3493             
3494             m_jit.move(value.gpr(), result.gpr());
3495             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), result.gpr());
3496             JITCompiler::Jump isBoolean = m_jit.branchTest64(
3497                 JITCompiler::Zero, result.gpr(), TrustedImm32(static_cast<int32_t>(~1)));
3498             m_jit.move(value.gpr(), result.gpr());
3499             JITCompiler::Jump done = m_jit.jump();
3500             isBoolean.link(&m_jit);
3501             m_jit.or64(GPRInfo::tagTypeNumberRegister, result.gpr());
3502             done.link(&m_jit);
3503             
3504             jsValueResult(result.gpr(), node);
3505             break;
3506         }
3507             
3508         default:
3509             DFG_CRASH(m_jit.graph(), node, "Bad use kind");
3510             break;
3511         }
3512         break;
3513     }
3514         
3515     case ToPrimitive: {
3516         DFG_ASSERT(m_jit.graph(), node, node->child1().useKind() == UntypedUse);
3517         JSValueOperand op1(this, node->child1());
3518         GPRTemporary result(this, Reuse, op1);
3519         
3520         GPRReg op1GPR = op1.gpr();
3521         GPRReg resultGPR = result.gpr();
3522         
3523         op1.use();
3524         
3525         MacroAssembler::Jump alreadyPrimitive = m_jit.branchIfNotCell(JSValueRegs(op1GPR));
3526         MacroAssembler::Jump notPrimitive = m_jit.branchIfObject(op1GPR);
3527         
3528         alreadyPrimitive.link(&m_jit);
3529         m_jit.move(op1GPR, resultGPR);
3530         
3531         addSlowPathGenerator(
3532             slowPathCall(notPrimitive, this, operationToPrimitive, resultGPR, op1GPR));
3533         
3534         jsValueResult(resultGPR, node, UseChildrenCalledExplicitly);
3535         break;
3536     }
3537         
3538     case ToString:
3539     case CallStringConstructor: {
3540         if (node->child1().useKind() == UntypedUse) {
3541             JSValueOperand op1(this, node->child1());
3542             GPRReg op1GPR = op1.gpr();
3543             
3544             GPRFlushedCallResult result(this);
3545             GPRReg resultGPR = result.gpr();
3546             
3547             flushRegisters();
3548             
3549             JITCompiler::Jump done;
3550             if (node->child1()->prediction() & SpecString) {
3551                 JITCompiler::Jump slowPath1 = m_jit.branchIfNotCell(JSValueRegs(op1GPR));
3552                 JITCompiler::Jump slowPath2 = m_jit.branchIfNotString(op1GPR);
3553                 m_jit.move(op1GPR, resultGPR);
3554                 done = m_jit.jump();
3555                 slowPath1.link(&m_jit);
3556                 slowPath2.link(&m_jit);
3557             }
3558             if (op == ToString)
3559                 callOperation(operationToString, resultGPR, op1GPR);
3560             else {
3561                 ASSERT(op == CallStringConstructor);
3562                 callOperation(operationCallStringConstructor, resultGPR, op1GPR);
3563             }
3564             m_jit.exceptionCheck();
3565             if (done.isSet())
3566                 done.link(&m_jit);
3567             cellResult(resultGPR, node);
3568             break;
3569         }
3570         
3571         compileToStringOrCallStringConstructorOnCell(node);
3572         break;
3573     }
3574         
3575     case NewStringObject: {
3576         compileNewStringObject(node);
3577         break;
3578     }
3579         
3580     case NewArray: {
3581         JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
3582         if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(node->indexingType())) {
3583             Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType());
3584             DFG_ASSERT(m_jit.graph(), node, structure->indexingType() == node->indexingType());
3585             ASSERT(
3586                 hasUndecided(structure->indexingType())
3587                 || hasInt32(structure->indexingType())
3588                 || hasDouble(structure->indexingType())
3589                 || hasContiguous(structure->indexingType()));
3590             
3591             unsigned numElements = node->numChildren();
3592             
3593             GPRTemporary result(this);
3594             GPRTemporary storage(this);
3595             
3596             GPRReg resultGPR = result.gpr();
3597             GPRReg storageGPR = storage.gpr();
3598
3599             emitAllocateRawObject(resultGPR, structure, storageGPR, numElements, numElements);
3600             
3601             // At this point, one way or another, resultGPR and storageGPR have pointers to
3602             // the JSArray and the Butterfly, respectively.
3603             
3604             ASSERT(!hasUndecided(structure->indexingType()) || !node->numChildren());
3605             
3606             for (unsigned operandIdx = 0; operandIdx < node->numChildren(); ++operandIdx) {
3607                 Edge use = m_jit.graph().m_varArgChildren[node->firstChild() + operandIdx];
3608                 switch (node->indexingType()) {
3609                 case ALL_BLANK_INDEXING_TYPES:
3610                 case ALL_UNDECIDED_INDEXING_TYPES:
3611                     CRASH();
3612                     break;
3613                 case ALL_DOUBLE_INDEXING_TYPES: {
3614                     SpeculateDoubleOperand operand(this, use);
3615                     FPRReg opFPR = operand.fpr();
3616                     DFG_TYPE_CHECK(
3617                         JSValueRegs(), use, SpecDoubleReal,
3618                         m_jit.branchDouble(
3619                             MacroAssembler::DoubleNotEqualOrUnordered, opFPR, opFPR));
3620                     m_jit.storeDouble(opFPR, MacroAssembler::Address(storageGPR, sizeof(double) * operandIdx));
3621                     break;
3622                 }
3623                 case ALL_INT32_INDEXING_TYPES:
3624                 case ALL_CONTIGUOUS_INDEXING_TYPES: {
3625                     JSValueOperand operand(this, use, ManualOperandSpeculation);
3626                     GPRReg opGPR = operand.gpr();
3627                     if (hasInt32(node->indexingType())) {
3628                         DFG_TYPE_CHECK(
3629                             JSValueRegs(opGPR), use, SpecInt32Only,
3630                             m_jit.branch64(
3631                                 MacroAssembler::Below, opGPR, GPRInfo::tagTypeNumberRegister));
3632                     }
3633                     m_jit.store64(opGPR, MacroAssembler::Address(storageGPR, sizeof(JSValue) * operandIdx));
3634                     break;
3635                 }
3636                 default:
3637                     CRASH();
3638                     break;
3639                 }
3640             }
3641             
3642             // Yuck, we should *really* have a way of also returning the storageGPR. But
3643             // that's the least of what's wrong with this code. We really shouldn't be
3644             // allocating the array after having computed - and probably spilled to the
3645             // stack - all of the things that will go into the array. The solution to that
3646             // bigger problem will also likely fix the redundancy in reloading the storage
3647             // pointer that we currently have.
3648             
3649             cellResult(resultGPR, node);
3650             break;
3651         }
3652         
3653         if (!node->numChildre