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