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