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