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