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