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