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