98cf2c7e4a3bc808854cc125a7e144320ceeac2c
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGSpeculativeJIT32_64.cpp
1 /*
2  * Copyright (C) 2011-2017 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 "DirectArguments.h"
39 #include "GetterSetter.h"
40 #include "HasOwnPropertyCache.h"
41 #include "HashMapImpl.h"
42 #include "JSLexicalEnvironment.h"
43 #include "JSPropertyNameEnumerator.h"
44 #include "ObjectPrototype.h"
45 #include "JSCInlines.h"
46 #include "SetupVarargsFrame.h"
47 #include "SuperSampler.h"
48 #include "Watchdog.h"
49
50 namespace JSC { namespace DFG {
51
52 #if USE(JSVALUE32_64)
53
54 static_assert(SpecCellCheck == SpecCell, "This is strongly assumed in the 32-bit DFG backend.");
55
56 bool SpeculativeJIT::fillJSValue(Edge edge, GPRReg& tagGPR, GPRReg& payloadGPR, FPRReg& fpr)
57 {
58     // FIXME: For double we could fill with a FPR.
59     UNUSED_PARAM(fpr);
60
61     VirtualRegister virtualRegister = edge->virtualRegister();
62     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
63
64     switch (info.registerFormat()) {
65     case DataFormatNone: {
66
67         if (edge->hasConstant()) {
68             tagGPR = allocate();
69             payloadGPR = allocate();
70             JSValue value = edge->asJSValue();
71             m_jit.move(Imm32(value.tag()), tagGPR);
72             m_jit.move(Imm32(value.payload()), payloadGPR);
73             m_gprs.retain(tagGPR, virtualRegister, SpillOrderConstant);
74             m_gprs.retain(payloadGPR, virtualRegister, SpillOrderConstant);
75             info.fillJSValue(*m_stream, tagGPR, payloadGPR, DataFormatJS);
76         } else {
77             DataFormat spillFormat = info.spillFormat();
78             ASSERT(spillFormat != DataFormatNone && spillFormat != DataFormatStorage);
79             tagGPR = allocate();
80             payloadGPR = allocate();
81             switch (spillFormat) {
82             case DataFormatInt32:
83                 m_jit.move(TrustedImm32(JSValue::Int32Tag), tagGPR);
84                 spillFormat = DataFormatJSInt32; // This will be used as the new register format.
85                 break;
86             case DataFormatCell:
87                 m_jit.move(TrustedImm32(JSValue::CellTag), tagGPR);
88                 spillFormat = DataFormatJSCell; // This will be used as the new register format.
89                 break;
90             case DataFormatBoolean:
91                 m_jit.move(TrustedImm32(JSValue::BooleanTag), tagGPR);
92                 spillFormat = DataFormatJSBoolean; // This will be used as the new register format.
93                 break;
94             default:
95                 m_jit.load32(JITCompiler::tagFor(virtualRegister), tagGPR);
96                 break;
97             }
98             m_jit.load32(JITCompiler::payloadFor(virtualRegister), payloadGPR);
99             m_gprs.retain(tagGPR, virtualRegister, SpillOrderSpilled);
100             m_gprs.retain(payloadGPR, virtualRegister, SpillOrderSpilled);
101             info.fillJSValue(*m_stream, tagGPR, payloadGPR, spillFormat == DataFormatJSDouble ? DataFormatJS : spillFormat);
102         }
103
104         return true;
105     }
106
107     case DataFormatInt32:
108     case DataFormatCell:
109     case DataFormatBoolean: {
110         GPRReg gpr = info.gpr();
111         // If the register has already been locked we need to take a copy.
112         if (m_gprs.isLocked(gpr)) {
113             payloadGPR = allocate();
114             m_jit.move(gpr, payloadGPR);
115         } else {
116             payloadGPR = gpr;
117             m_gprs.lock(gpr);
118         }
119         tagGPR = allocate();
120         int32_t tag = JSValue::EmptyValueTag;
121         DataFormat fillFormat = DataFormatJS;
122         switch (info.registerFormat()) {
123         case DataFormatInt32:
124             tag = JSValue::Int32Tag;
125             fillFormat = DataFormatJSInt32;
126             break;
127         case DataFormatCell:
128             tag = JSValue::CellTag;
129             fillFormat = DataFormatJSCell;
130             break;
131         case DataFormatBoolean:
132             tag = JSValue::BooleanTag;
133             fillFormat = DataFormatJSBoolean;
134             break;
135         default:
136             RELEASE_ASSERT_NOT_REACHED();
137             break;
138         }
139         m_jit.move(TrustedImm32(tag), tagGPR);
140         m_gprs.release(gpr);
141         m_gprs.retain(tagGPR, virtualRegister, SpillOrderJS);
142         m_gprs.retain(payloadGPR, virtualRegister, SpillOrderJS);
143         info.fillJSValue(*m_stream, tagGPR, payloadGPR, fillFormat);
144         return true;
145     }
146
147     case DataFormatJSDouble:
148     case DataFormatJS:
149     case DataFormatJSInt32:
150     case DataFormatJSCell:
151     case DataFormatJSBoolean: {
152         tagGPR = info.tagGPR();
153         payloadGPR = info.payloadGPR();
154         m_gprs.lock(tagGPR);
155         m_gprs.lock(payloadGPR);
156         return true;
157     }
158         
159     case DataFormatStorage:
160     case DataFormatDouble:
161         // this type currently never occurs
162         RELEASE_ASSERT_NOT_REACHED();
163
164     default:
165         RELEASE_ASSERT_NOT_REACHED();
166         return true;
167     }
168 }
169
170 void SpeculativeJIT::cachedGetById(CodeOrigin origin, JSValueRegs base, JSValueRegs result, unsigned identifierNumber, JITCompiler::Jump slowPathTarget , SpillRegistersMode mode, AccessType type)
171 {
172     cachedGetById(origin, base.tagGPR(), base.payloadGPR(), result.tagGPR(), result.payloadGPR(), identifierNumber, slowPathTarget, mode, type);
173 }
174
175 void SpeculativeJIT::cachedGetById(
176     CodeOrigin codeOrigin, GPRReg baseTagGPROrNone, GPRReg basePayloadGPR, GPRReg resultTagGPR, GPRReg resultPayloadGPR,
177     unsigned identifierNumber, JITCompiler::Jump slowPathTarget, SpillRegistersMode spillMode, AccessType type)
178 {
179     // This is a hacky fix for when the register allocator decides to alias the base payload with the result tag. This only happens
180     // in the case of GetByIdFlush/GetByIdDirectFlush, which has a relatively expensive register allocation story already so we probably don't need to
181     // trip over one move instruction.
182     if (basePayloadGPR == resultTagGPR) {
183         RELEASE_ASSERT(basePayloadGPR != resultPayloadGPR);
184         
185         if (baseTagGPROrNone == resultPayloadGPR) {
186             m_jit.swap(basePayloadGPR, baseTagGPROrNone);
187             baseTagGPROrNone = resultTagGPR;
188         } else
189             m_jit.move(basePayloadGPR, resultPayloadGPR);
190         basePayloadGPR = resultPayloadGPR;
191     }
192     
193     RegisterSet usedRegisters = this->usedRegisters();
194     if (spillMode == DontSpill) {
195         // We've already flushed registers to the stack, we don't need to spill these.
196         usedRegisters.set(JSValueRegs(baseTagGPROrNone, basePayloadGPR), false);
197         usedRegisters.set(JSValueRegs(resultTagGPR, resultPayloadGPR), false);
198     }
199     
200     CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream->size());
201     JITGetByIdGenerator gen(
202         m_jit.codeBlock(), codeOrigin, callSite, usedRegisters, identifierUID(identifierNumber),
203         JSValueRegs(baseTagGPROrNone, basePayloadGPR), JSValueRegs(resultTagGPR, resultPayloadGPR), type);
204     
205     gen.generateFastPath(m_jit);
206     
207     JITCompiler::JumpList slowCases;
208     if (slowPathTarget.isSet())
209         slowCases.append(slowPathTarget);
210     slowCases.append(gen.slowPathJump());
211
212     std::unique_ptr<SlowPathGenerator> slowPath;
213     if (baseTagGPROrNone == InvalidGPRReg) {
214         slowPath = slowPathCall(
215             slowCases, this, appropriateOptimizingGetByIdFunction(type),
216             JSValueRegs(resultTagGPR, resultPayloadGPR), gen.stubInfo(),
217             CCallHelpers::CellValue(basePayloadGPR),
218             identifierUID(identifierNumber));
219     } else {
220         slowPath = slowPathCall(
221             slowCases, this, appropriateOptimizingGetByIdFunction(type),
222             JSValueRegs(resultTagGPR, resultPayloadGPR), gen.stubInfo(), JSValueRegs(baseTagGPROrNone, basePayloadGPR), identifierUID(identifierNumber));
223     }
224
225     m_jit.addGetById(gen, slowPath.get());
226     addSlowPathGenerator(WTFMove(slowPath));
227 }
228
229 void SpeculativeJIT::cachedGetByIdWithThis(
230     CodeOrigin codeOrigin, GPRReg baseTagGPROrNone, GPRReg basePayloadGPR, GPRReg thisTagGPR, GPRReg thisPayloadGPR, GPRReg resultTagGPR, GPRReg resultPayloadGPR,
231     unsigned identifierNumber, const JITCompiler::JumpList& slowPathTarget)
232 {
233     RegisterSet usedRegisters = this->usedRegisters();
234     
235     CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(codeOrigin, m_stream->size());
236     JITGetByIdWithThisGenerator gen(
237         m_jit.codeBlock(), codeOrigin, callSite, usedRegisters, identifierUID(identifierNumber),
238         JSValueRegs(resultTagGPR, resultPayloadGPR), JSValueRegs(baseTagGPROrNone, basePayloadGPR), JSValueRegs(thisTagGPR, thisPayloadGPR), AccessType::GetWithThis);
239     
240     gen.generateFastPath(m_jit);
241     
242     JITCompiler::JumpList slowCases;
243     if (!slowPathTarget.empty())
244         slowCases.append(slowPathTarget);
245     slowCases.append(gen.slowPathJump());
246
247     std::unique_ptr<SlowPathGenerator> slowPath;
248     if (baseTagGPROrNone == InvalidGPRReg && thisTagGPR == InvalidGPRReg) {
249         slowPath = slowPathCall(
250             slowCases, this, operationGetByIdWithThisOptimize,
251             JSValueRegs(resultTagGPR, resultPayloadGPR), gen.stubInfo(),
252             CCallHelpers::CellValue(basePayloadGPR),
253             CCallHelpers::CellValue(thisPayloadGPR),
254             identifierUID(identifierNumber));
255     } else {
256         ASSERT(baseTagGPROrNone != InvalidGPRReg);
257         ASSERT(thisTagGPR != InvalidGPRReg);
258         
259         slowPath = slowPathCall(
260             slowCases, this, operationGetByIdWithThisOptimize,
261             JSValueRegs(resultTagGPR, resultPayloadGPR), gen.stubInfo(), JSValueRegs(baseTagGPROrNone, basePayloadGPR), JSValueRegs(thisTagGPR, thisPayloadGPR), identifierUID(identifierNumber));
262     }
263
264     m_jit.addGetByIdWithThis(gen, slowPath.get());
265     addSlowPathGenerator(WTFMove(slowPath));
266 }
267
268 void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNullOrUndefined(Edge operand)
269 {
270     JSValueOperand arg(this, operand, ManualOperandSpeculation);
271     GPRReg argTagGPR = arg.tagGPR();
272     GPRReg argPayloadGPR = arg.payloadGPR();
273
274     GPRTemporary resultPayload(this, Reuse, arg, PayloadWord);
275     GPRReg resultPayloadGPR = resultPayload.gpr();
276
277     JITCompiler::Jump notCell;
278     JITCompiler::Jump notMasqueradesAsUndefined;   
279     if (masqueradesAsUndefinedWatchpointIsStillValid()) {
280         if (!isKnownCell(operand.node()))
281             notCell = m_jit.branchIfNotCell(arg.jsValueRegs());
282         
283         m_jit.move(TrustedImm32(0), resultPayloadGPR);
284         notMasqueradesAsUndefined = m_jit.jump();
285     } else {
286         GPRTemporary localGlobalObject(this);
287         GPRTemporary remoteGlobalObject(this);
288
289         if (!isKnownCell(operand.node()))
290             notCell = m_jit.branchIfNotCell(arg.jsValueRegs());
291         
292         JITCompiler::Jump isMasqueradesAsUndefined = m_jit.branchTest8(
293             JITCompiler::NonZero, 
294             JITCompiler::Address(argPayloadGPR, JSCell::typeInfoFlagsOffset()), 
295             JITCompiler::TrustedImm32(MasqueradesAsUndefined));
296         
297         m_jit.move(TrustedImm32(0), resultPayloadGPR);
298         notMasqueradesAsUndefined = m_jit.jump();
299
300         isMasqueradesAsUndefined.link(&m_jit);
301         GPRReg localGlobalObjectGPR = localGlobalObject.gpr();
302         GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr();
303         m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.graph().globalObjectFor(m_currentNode->origin.semantic)), localGlobalObjectGPR);
304         m_jit.loadPtr(JITCompiler::Address(argPayloadGPR, JSCell::structureIDOffset()), resultPayloadGPR);
305         m_jit.loadPtr(JITCompiler::Address(resultPayloadGPR, Structure::globalObjectOffset()), remoteGlobalObjectGPR);
306         m_jit.compare32(JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, resultPayloadGPR);
307     }
308  
309     if (!isKnownCell(operand.node())) {
310         JITCompiler::Jump done = m_jit.jump();
311         
312         notCell.link(&m_jit);
313         // null or undefined?
314         COMPILE_ASSERT((JSValue::UndefinedTag | 1) == JSValue::NullTag, UndefinedTag_OR_1_EQUALS_NullTag);
315         m_jit.or32(TrustedImm32(1), argTagGPR, resultPayloadGPR);
316         m_jit.compare32(JITCompiler::Equal, resultPayloadGPR, TrustedImm32(JSValue::NullTag), resultPayloadGPR);
317
318         done.link(&m_jit);
319     }
320     
321     notMasqueradesAsUndefined.link(&m_jit);
322  
323     booleanResult(resultPayloadGPR, m_currentNode);
324 }
325
326 void SpeculativeJIT::nonSpeculativePeepholeBranchNullOrUndefined(Edge operand, Node* branchNode)
327 {
328     BasicBlock* taken = branchNode->branchData()->taken.block;
329     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
330
331     bool invert = false;
332     if (taken == nextBlock()) {
333         invert = !invert;
334         BasicBlock* tmp = taken;
335         taken = notTaken;
336         notTaken = tmp;
337     }
338
339     JSValueOperand arg(this, operand, ManualOperandSpeculation);
340     GPRReg argTagGPR = arg.tagGPR();
341     GPRReg argPayloadGPR = arg.payloadGPR();
342     
343     GPRTemporary result(this, Reuse, arg, TagWord);
344     GPRReg resultGPR = result.gpr();
345
346     JITCompiler::Jump notCell;
347
348     if (masqueradesAsUndefinedWatchpointIsStillValid()) {
349         if (!isKnownCell(operand.node()))
350             notCell = m_jit.branchIfNotCell(arg.jsValueRegs());
351         
352         jump(invert ? taken : notTaken, ForceJump);
353     } else {
354         GPRTemporary localGlobalObject(this);
355         GPRTemporary remoteGlobalObject(this);
356
357         if (!isKnownCell(operand.node()))
358             notCell = m_jit.branchIfNotCell(arg.jsValueRegs());
359         
360         branchTest8(JITCompiler::Zero, 
361             JITCompiler::Address(argPayloadGPR, JSCell::typeInfoFlagsOffset()), 
362             JITCompiler::TrustedImm32(MasqueradesAsUndefined), 
363             invert ? taken : notTaken);
364    
365         GPRReg localGlobalObjectGPR = localGlobalObject.gpr();
366         GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr();
367         m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.graph().globalObjectFor(m_currentNode->origin.semantic)), localGlobalObjectGPR);
368         m_jit.loadPtr(JITCompiler::Address(argPayloadGPR, JSCell::structureIDOffset()), resultGPR);
369         m_jit.loadPtr(JITCompiler::Address(resultGPR, Structure::globalObjectOffset()), remoteGlobalObjectGPR);
370         branchPtr(JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, invert ? notTaken : taken);
371     }
372  
373     if (!isKnownCell(operand.node())) {
374         jump(notTaken, ForceJump);
375         
376         notCell.link(&m_jit);
377         // null or undefined?
378         COMPILE_ASSERT((JSValue::UndefinedTag | 1) == JSValue::NullTag, UndefinedTag_OR_1_EQUALS_NullTag);
379         m_jit.or32(TrustedImm32(1), argTagGPR, resultGPR);
380         branch32(invert ? JITCompiler::NotEqual : JITCompiler::Equal, resultGPR, JITCompiler::TrustedImm32(JSValue::NullTag), taken);
381     }
382     
383     jump(notTaken);
384 }
385
386 void SpeculativeJIT::nonSpeculativePeepholeStrictEq(Node* node, Node* branchNode, bool invert)
387 {
388     BasicBlock* taken = branchNode->branchData()->taken.block;
389     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
390
391     // The branch instruction will branch to the taken block.
392     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
393     if (taken == nextBlock()) {
394         invert = !invert;
395         BasicBlock* tmp = taken;
396         taken = notTaken;
397         notTaken = tmp;
398     }
399     
400     JSValueOperand arg1(this, node->child1());
401     JSValueOperand arg2(this, node->child2());
402     GPRReg arg1PayloadGPR = arg1.payloadGPR();
403     GPRReg arg2PayloadGPR = arg2.payloadGPR();
404     JSValueRegs arg1Regs = arg1.jsValueRegs();
405     JSValueRegs arg2Regs = arg2.jsValueRegs();
406     
407     GPRTemporary resultPayload(this, Reuse, arg1, PayloadWord);
408     GPRReg resultPayloadGPR = resultPayload.gpr();
409     
410     arg1.use();
411     arg2.use();
412     
413     if (isKnownCell(node->child1().node()) && isKnownCell(node->child2().node())) {
414         // see if we get lucky: if the arguments are cells and they reference the same
415         // cell, then they must be strictly equal.
416         branchPtr(JITCompiler::Equal, arg1PayloadGPR, arg2PayloadGPR, invert ? notTaken : taken);
417         
418         silentSpillAllRegisters(resultPayloadGPR);
419         callOperation(operationCompareStrictEqCell, resultPayloadGPR, arg1PayloadGPR, arg2PayloadGPR);
420         m_jit.exceptionCheck();
421         silentFillAllRegisters();
422
423         branchTest32(invert ? JITCompiler::Zero : JITCompiler::NonZero, resultPayloadGPR, taken);
424     } else {
425         // FIXME: Add fast paths for twoCells, number etc.
426
427         silentSpillAllRegisters(resultPayloadGPR);
428         callOperation(operationCompareStrictEq, resultPayloadGPR, arg1Regs, arg2Regs);
429         m_jit.exceptionCheck();
430         silentFillAllRegisters();
431
432         branchTest32(invert ? JITCompiler::Zero : JITCompiler::NonZero, resultPayloadGPR, taken);
433     }
434     
435     jump(notTaken);
436 }
437
438 void SpeculativeJIT::nonSpeculativeNonPeepholeStrictEq(Node* node, bool invert)
439 {
440     JSValueOperand arg1(this, node->child1());
441     JSValueOperand arg2(this, node->child2());
442     GPRReg arg1PayloadGPR = arg1.payloadGPR();
443     GPRReg arg2PayloadGPR = arg2.payloadGPR();
444     JSValueRegs arg1Regs = arg1.jsValueRegs();
445     JSValueRegs arg2Regs = arg2.jsValueRegs();
446     
447     GPRTemporary resultPayload(this, Reuse, arg1, PayloadWord);
448     GPRReg resultPayloadGPR = resultPayload.gpr();
449     
450     arg1.use();
451     arg2.use();
452     
453     if (isKnownCell(node->child1().node()) && isKnownCell(node->child2().node())) {
454         // see if we get lucky: if the arguments are cells and they reference the same
455         // cell, then they must be strictly equal.
456         // FIXME: this should flush registers instead of silent spill/fill.
457         JITCompiler::Jump notEqualCase = m_jit.branchPtr(JITCompiler::NotEqual, arg1PayloadGPR, arg2PayloadGPR);
458         
459         m_jit.move(JITCompiler::TrustedImm32(!invert), resultPayloadGPR);
460         JITCompiler::Jump done = m_jit.jump();
461
462         notEqualCase.link(&m_jit);
463         
464         silentSpillAllRegisters(resultPayloadGPR);
465         callOperation(operationCompareStrictEqCell, resultPayloadGPR, arg1PayloadGPR, arg2PayloadGPR);
466         m_jit.exceptionCheck();
467         silentFillAllRegisters();
468
469         m_jit.andPtr(JITCompiler::TrustedImm32(1), resultPayloadGPR);
470         
471         done.link(&m_jit);
472     } else {
473         // FIXME: Add fast paths.
474
475         silentSpillAllRegisters(resultPayloadGPR);
476         callOperation(operationCompareStrictEq, resultPayloadGPR, arg1Regs, arg2Regs);
477         silentFillAllRegisters();
478         m_jit.exceptionCheck();
479         
480         m_jit.andPtr(JITCompiler::TrustedImm32(1), resultPayloadGPR);
481     }
482
483     booleanResult(resultPayloadGPR, node, UseChildrenCalledExplicitly);
484 }
485
486 void SpeculativeJIT::compileCompareEqPtr(Node* node)
487 {
488     JSValueOperand operand(this, node->child1());
489     GPRTemporary result(this);
490     JSValueRegs regs = operand.jsValueRegs();
491     GPRReg resultGPR = result.gpr();
492     m_jit.boxBooleanPayload(false, resultGPR);
493     JITCompiler::JumpList notEqual = m_jit.branchIfNotEqual(regs, node->cellOperand()->value());
494     m_jit.boxBooleanPayload(true, resultGPR);
495     notEqual.link(&m_jit);
496     blessedBooleanResult(resultGPR, node);
497 }
498
499 void SpeculativeJIT::emitCall(Node* node)
500 {
501     CallLinkInfo::CallType callType;
502     bool isVarargs = false;
503     bool isForwardVarargs = false;
504     bool isTail = false;
505     bool isDirect = false;
506     bool isEmulatedTail = false;
507     switch (node->op()) {
508     case Call:
509     case CallEval:
510         callType = CallLinkInfo::Call;
511         break;
512     case TailCall:
513         callType = CallLinkInfo::TailCall;
514         isTail = true;
515         break;
516     case TailCallInlinedCaller:
517         callType = CallLinkInfo::Call;
518         isEmulatedTail = true;
519         break;
520     case Construct:
521         callType = CallLinkInfo::Construct;
522         break;
523     case CallVarargs:
524         callType = CallLinkInfo::CallVarargs;
525         isVarargs = true;
526         break;
527     case TailCallVarargs:
528         callType = CallLinkInfo::TailCallVarargs;
529         isVarargs = true;
530         isTail = true;
531         break;
532     case TailCallVarargsInlinedCaller:
533         callType = CallLinkInfo::CallVarargs;
534         isVarargs = true;
535         isEmulatedTail = true;
536         break;
537     case ConstructVarargs:
538         callType = CallLinkInfo::ConstructVarargs;
539         isVarargs = true;
540         break;
541     case CallForwardVarargs:
542         callType = CallLinkInfo::CallVarargs;
543         isForwardVarargs = true;
544         break;
545     case TailCallForwardVarargs:
546         callType = CallLinkInfo::TailCallVarargs;
547         isTail = true;
548         isForwardVarargs = true;
549         break;
550     case TailCallForwardVarargsInlinedCaller:
551         callType = CallLinkInfo::CallVarargs;
552         isEmulatedTail = true;
553         isForwardVarargs = true;
554         break;
555     case ConstructForwardVarargs:
556         callType = CallLinkInfo::ConstructVarargs;
557         isForwardVarargs = true;
558         break;
559     case DirectCall:
560         callType = CallLinkInfo::DirectCall;
561         isDirect = true;
562         break;
563     case DirectConstruct:
564         callType = CallLinkInfo::DirectConstruct;
565         isDirect = true;
566         break;
567     case DirectTailCall:
568         callType = CallLinkInfo::DirectTailCall;
569         isTail = true;
570         isDirect = true;
571         break;
572     case DirectTailCallInlinedCaller:
573         callType = CallLinkInfo::DirectCall;
574         isEmulatedTail = true;
575         isDirect = true;
576         break;
577     default:
578         DFG_CRASH(m_jit.graph(), node, "bad node type");
579         break;
580     }
581
582     Edge calleeEdge = m_jit.graph().child(node, 0);
583     GPRReg calleeTagGPR = InvalidGPRReg;
584     GPRReg calleePayloadGPR = InvalidGPRReg;
585     CallFrameShuffleData shuffleData;
586     
587     ExecutableBase* executable = nullptr;
588     FunctionExecutable* functionExecutable = nullptr;
589     if (isDirect) {
590         executable = node->castOperand<ExecutableBase*>();
591         functionExecutable = jsDynamicCast<FunctionExecutable*>(*m_jit.vm(), executable);
592     }
593     
594     unsigned numPassedArgs = 0;
595     unsigned numAllocatedArgs = 0;
596     
597     // Gotta load the arguments somehow. Varargs is trickier.
598     if (isVarargs || isForwardVarargs) {
599         RELEASE_ASSERT(!isDirect);
600         CallVarargsData* data = node->callVarargsData();
601
602         int numUsedStackSlots = m_jit.graph().m_nextMachineLocal;
603         
604         if (isForwardVarargs) {
605             flushRegisters();
606             if (node->child3())
607                 use(node->child3());
608             
609             GPRReg scratchGPR1;
610             GPRReg scratchGPR2;
611             GPRReg scratchGPR3;
612             
613             scratchGPR1 = JITCompiler::selectScratchGPR();
614             scratchGPR2 = JITCompiler::selectScratchGPR(scratchGPR1);
615             scratchGPR3 = JITCompiler::selectScratchGPR(scratchGPR1, scratchGPR2);
616             
617             m_jit.move(TrustedImm32(numUsedStackSlots), scratchGPR2);
618             JITCompiler::JumpList slowCase;
619             InlineCallFrame* inlineCallFrame;
620             if (node->child3())
621                 inlineCallFrame = node->child3()->origin.semantic.inlineCallFrame;
622             else
623                 inlineCallFrame = node->origin.semantic.inlineCallFrame;
624             // emitSetupVarargsFrameFastCase modifies the stack pointer if it succeeds.
625             emitSetupVarargsFrameFastCase(*m_jit.vm(), m_jit, scratchGPR2, scratchGPR1, scratchGPR2, scratchGPR3, inlineCallFrame, data->firstVarArgOffset, slowCase);
626             JITCompiler::Jump done = m_jit.jump();
627             slowCase.link(&m_jit);
628             callOperation(operationThrowStackOverflowForVarargs);
629             m_jit.exceptionCheck();
630             m_jit.abortWithReason(DFGVarargsThrowingPathDidNotThrow);
631             done.link(&m_jit);
632         } else {
633             GPRReg argumentsPayloadGPR;
634             GPRReg argumentsTagGPR;
635             GPRReg scratchGPR1;
636             GPRReg scratchGPR2;
637             GPRReg scratchGPR3;
638         
639             auto loadArgumentsGPR = [&] (GPRReg reservedGPR) {
640                 if (reservedGPR != InvalidGPRReg)
641                     lock(reservedGPR);
642                 JSValueOperand arguments(this, node->child3());
643                 argumentsTagGPR = arguments.tagGPR();
644                 argumentsPayloadGPR = arguments.payloadGPR();
645                 if (reservedGPR != InvalidGPRReg)
646                     unlock(reservedGPR);
647                 flushRegisters();
648                 
649                 scratchGPR1 = JITCompiler::selectScratchGPR(argumentsPayloadGPR, argumentsTagGPR, reservedGPR);
650                 scratchGPR2 = JITCompiler::selectScratchGPR(argumentsPayloadGPR, argumentsTagGPR, scratchGPR1, reservedGPR);
651                 scratchGPR3 = JITCompiler::selectScratchGPR(argumentsPayloadGPR, argumentsTagGPR, scratchGPR1, scratchGPR2, reservedGPR);
652             };
653             
654             loadArgumentsGPR(InvalidGPRReg);
655         
656             DFG_ASSERT(m_jit.graph(), node, isFlushed());
657
658             // Right now, arguments is in argumentsTagGPR/argumentsPayloadGPR and the register file is
659             // flushed.
660             callOperation(operationSizeFrameForVarargs, GPRInfo::returnValueGPR, JSValueRegs(argumentsTagGPR, argumentsPayloadGPR), numUsedStackSlots, data->firstVarArgOffset);
661             m_jit.exceptionCheck();
662             
663             // Now we have the argument count of the callee frame, but we've lost the arguments operand.
664             // Reconstruct the arguments operand while preserving the callee frame.
665             loadArgumentsGPR(GPRInfo::returnValueGPR);
666             m_jit.move(TrustedImm32(numUsedStackSlots), scratchGPR1);
667             emitSetVarargsFrame(m_jit, GPRInfo::returnValueGPR, false, scratchGPR1, scratchGPR1);
668             m_jit.addPtr(TrustedImm32(-(sizeof(CallerFrameAndPC) + WTF::roundUpToMultipleOf(stackAlignmentBytes(), 6 * sizeof(void*)))), scratchGPR1, JITCompiler::stackPointerRegister);
669             
670             callOperation(operationSetupVarargsFrame, GPRInfo::returnValueGPR, scratchGPR1, JSValueRegs(argumentsTagGPR, argumentsPayloadGPR), data->firstVarArgOffset, GPRInfo::returnValueGPR);
671             m_jit.exceptionCheck();
672             m_jit.addPtr(TrustedImm32(sizeof(CallerFrameAndPC)), GPRInfo::returnValueGPR, JITCompiler::stackPointerRegister);
673         }
674         
675         DFG_ASSERT(m_jit.graph(), node, isFlushed());
676         
677         // We don't need the arguments array anymore.
678         if (isVarargs)
679             use(node->child3());
680
681         // Now set up the "this" argument.
682         JSValueOperand thisArgument(this, node->child2());
683         GPRReg thisArgumentTagGPR = thisArgument.tagGPR();
684         GPRReg thisArgumentPayloadGPR = thisArgument.payloadGPR();
685         thisArgument.use();
686         
687         m_jit.store32(thisArgumentTagGPR, JITCompiler::calleeArgumentTagSlot(0));
688         m_jit.store32(thisArgumentPayloadGPR, JITCompiler::calleeArgumentPayloadSlot(0));
689     } else {        
690         // The call instruction's first child is either the function (normal call) or the
691         // receiver (method call). subsequent children are the arguments.
692         numPassedArgs = node->numChildren() - 1;
693         numAllocatedArgs = numPassedArgs;
694         
695         if (functionExecutable) {
696             // Allocate more args if this would let us avoid arity checks. This is throttled by
697             // CallLinkInfo's limit. It's probably good to throttle it - if the callee wants a
698             // ginormous amount of argument space then it's better for them to do it so that when we
699             // make calls to other things, we don't waste space.
700             unsigned desiredNumAllocatedArgs = static_cast<unsigned>(functionExecutable->parameterCount()) + 1;
701             if (desiredNumAllocatedArgs <= Options::maximumDirectCallStackSize()) {
702                 numAllocatedArgs = std::max(numAllocatedArgs, desiredNumAllocatedArgs);
703                 
704                 // Whoever converts to DirectCall should do this adjustment. It's too late for us to
705                 // do this adjustment now since we will have already emitted code that relied on the
706                 // value of m_parameterSlots.
707                 DFG_ASSERT(
708                     m_jit.graph(), node,
709                     Graph::parameterSlotsForArgCount(numAllocatedArgs)
710                     <= m_jit.graph().m_parameterSlots);
711             }
712         }
713
714         if (isTail) {
715             JSValueOperand callee(this, calleeEdge);
716             calleeTagGPR = callee.tagGPR();
717             calleePayloadGPR = callee.payloadGPR();
718             if (!isDirect)
719                 use(calleeEdge);
720
721             shuffleData.numLocals = m_jit.graph().frameRegisterCount();
722             shuffleData.callee = ValueRecovery::inPair(calleeTagGPR, calleePayloadGPR);
723             shuffleData.args.resize(numAllocatedArgs);
724             shuffleData.numPassedArgs = numPassedArgs;
725
726             for (unsigned i = 0; i < numPassedArgs; ++i) {
727                 Edge argEdge = m_jit.graph().varArgChild(node, i + 1);
728                 GenerationInfo& info = generationInfo(argEdge.node());
729                 if (!isDirect)
730                     use(argEdge);
731                 shuffleData.args[i] = info.recovery(argEdge->virtualRegister());
732             }
733             
734             for (unsigned i = numPassedArgs; i < numAllocatedArgs; ++i)
735                 shuffleData.args[i] = ValueRecovery::constant(jsUndefined());
736         } else {
737             m_jit.store32(MacroAssembler::TrustedImm32(numPassedArgs), m_jit.calleeFramePayloadSlot(CallFrameSlot::argumentCount));
738         
739             for (unsigned i = 0; i < numPassedArgs; i++) {
740                 Edge argEdge = m_jit.graph().m_varArgChildren[node->firstChild() + 1 + i];
741                 JSValueOperand arg(this, argEdge);
742                 GPRReg argTagGPR = arg.tagGPR();
743                 GPRReg argPayloadGPR = arg.payloadGPR();
744                 use(argEdge);
745             
746                 m_jit.store32(argTagGPR, m_jit.calleeArgumentTagSlot(i));
747                 m_jit.store32(argPayloadGPR, m_jit.calleeArgumentPayloadSlot(i));
748             }
749             
750             for (unsigned i = numPassedArgs; i < numAllocatedArgs; ++i)
751                 m_jit.storeTrustedValue(jsUndefined(), JITCompiler::calleeArgumentSlot(i));
752         }
753     }
754
755     if (!isTail || isVarargs || isForwardVarargs) {
756         JSValueOperand callee(this, calleeEdge);
757         calleeTagGPR = callee.tagGPR();
758         calleePayloadGPR = callee.payloadGPR();
759         use(calleeEdge);
760         m_jit.store32(calleePayloadGPR, m_jit.calleeFramePayloadSlot(CallFrameSlot::callee));
761         m_jit.store32(calleeTagGPR, m_jit.calleeFrameTagSlot(CallFrameSlot::callee));
762
763         if (!isTail)
764             flushRegisters();
765     }
766
767     JITCompiler::DataLabelPtr targetToCheck;
768     JITCompiler::JumpList slowPath;
769
770     CodeOrigin staticOrigin = node->origin.semantic;
771     ASSERT(!isTail || !staticOrigin.inlineCallFrame || !staticOrigin.inlineCallFrame->getCallerSkippingTailCalls());
772     ASSERT(!isEmulatedTail || (staticOrigin.inlineCallFrame && staticOrigin.inlineCallFrame->getCallerSkippingTailCalls()));
773     CodeOrigin dynamicOrigin =
774         isEmulatedTail ? *staticOrigin.inlineCallFrame->getCallerSkippingTailCalls() : staticOrigin;
775     CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(dynamicOrigin, m_stream->size());
776     
777     CallLinkInfo* info = m_jit.codeBlock()->addCallLinkInfo();
778     info->setUpCall(callType, node->origin.semantic, calleePayloadGPR);
779     
780     auto setResultAndResetStack = [&] () {
781         JSValueRegsFlushedCallResult result(this);
782         JSValueRegs resultRegs = result.regs();
783
784         m_jit.setupResults(resultRegs);
785
786         jsValueResult(resultRegs, node, DataFormatJS, UseChildrenCalledExplicitly);
787         // After the calls are done, we need to reestablish our stack
788         // pointer. We rely on this for varargs calls, calls with arity
789         // mismatch (the callframe is slided) and tail calls.
790         m_jit.addPtr(TrustedImm32(m_jit.graph().stackPointerOffset() * sizeof(Register)), GPRInfo::callFrameRegister, JITCompiler::stackPointerRegister);
791     };
792     
793     if (node->op() == CallEval) {
794         // We want to call operationCallEval but we don't want to overwrite the parameter area in
795         // which we have created a prototypical eval call frame. This means that we have to
796         // subtract stack to make room for the call. Lucky for us, at this point we have the whole
797         // register file to ourselves.
798         
799         m_jit.emitStoreCallSiteIndex(callSite);
800         m_jit.addPtr(TrustedImm32(-static_cast<ptrdiff_t>(sizeof(CallerFrameAndPC))), JITCompiler::stackPointerRegister, GPRInfo::regT0);
801         m_jit.storePtr(GPRInfo::callFrameRegister, JITCompiler::Address(GPRInfo::regT0, CallFrame::callerFrameOffset()));
802         
803         // Now we need to make room for:
804         // - The caller frame and PC of a call to operationCallEval.
805         // - Potentially two arguments on the stack.
806         unsigned requiredBytes = sizeof(CallerFrameAndPC) + sizeof(ExecState*) * 2;
807         requiredBytes = WTF::roundUpToMultipleOf(stackAlignmentBytes(), requiredBytes);
808         m_jit.subPtr(TrustedImm32(requiredBytes), JITCompiler::stackPointerRegister);
809         m_jit.setupArguments<decltype(operationCallEval)>(GPRInfo::regT0);
810         prepareForExternalCall();
811         m_jit.appendCall(operationCallEval);
812         m_jit.exceptionCheck();
813         JITCompiler::Jump done = m_jit.branchIfNotEmpty(GPRInfo::returnValueGPR2);
814         
815         // This is the part where we meant to make a normal call. Oops.
816         m_jit.addPtr(TrustedImm32(requiredBytes), JITCompiler::stackPointerRegister);
817         m_jit.load32(JITCompiler::calleeFrameSlot(CallFrameSlot::callee).withOffset(PayloadOffset), GPRInfo::regT0);
818         m_jit.load32(JITCompiler::calleeFrameSlot(CallFrameSlot::callee).withOffset(TagOffset), GPRInfo::regT1);
819         m_jit.emitDumbVirtualCall(*m_jit.vm(), info);
820         
821         done.link(&m_jit);
822         setResultAndResetStack();
823         return;
824     }
825
826     if (isDirect) {
827         info->setExecutableDuringCompilation(executable);
828         info->setMaxNumArguments(numAllocatedArgs);
829
830         if (isTail) {
831             RELEASE_ASSERT(node->op() == DirectTailCall);
832             
833             JITCompiler::PatchableJump patchableJump = m_jit.patchableJump();
834             JITCompiler::Label mainPath = m_jit.label();
835             
836             m_jit.emitStoreCallSiteIndex(callSite);
837             
838             info->setFrameShuffleData(shuffleData);
839             CallFrameShuffler(m_jit, shuffleData).prepareForTailCall();
840             
841             JITCompiler::Call call = m_jit.nearTailCall();
842             
843             JITCompiler::Label slowPath = m_jit.label();
844             patchableJump.m_jump.linkTo(slowPath, &m_jit);
845             
846             silentSpillAllRegisters(InvalidGPRReg);
847             callOperation(operationLinkDirectCall, info, calleePayloadGPR);
848             silentFillAllRegisters();
849             m_jit.exceptionCheck();
850             m_jit.jump().linkTo(mainPath, &m_jit);
851             
852             useChildren(node);
853             
854             m_jit.addJSDirectTailCall(patchableJump, call, slowPath, info);
855             return;
856         }
857         
858         JITCompiler::Label mainPath = m_jit.label();
859         
860         m_jit.emitStoreCallSiteIndex(callSite);
861         
862         JITCompiler::Call call = m_jit.nearCall();
863         JITCompiler::Jump done = m_jit.jump();
864         
865         JITCompiler::Label slowPath = m_jit.label();
866         if (isX86())
867             m_jit.pop(JITCompiler::selectScratchGPR(calleePayloadGPR));
868
869         callOperation(operationLinkDirectCall, info, calleePayloadGPR);
870         m_jit.exceptionCheck();
871         m_jit.jump().linkTo(mainPath, &m_jit);
872         
873         done.link(&m_jit);
874         
875         setResultAndResetStack();
876         
877         m_jit.addJSDirectCall(call, slowPath, info);
878         return;
879     }
880     
881     m_jit.emitStoreCallSiteIndex(callSite);
882     
883     slowPath.append(m_jit.branchIfNotCell(JSValueRegs(calleeTagGPR, calleePayloadGPR)));
884     slowPath.append(m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleePayloadGPR, targetToCheck));
885
886     if (isTail) {
887         if (node->op() == TailCall) {
888             info->setFrameShuffleData(shuffleData);
889             CallFrameShuffler(m_jit, shuffleData).prepareForTailCall();
890         } else {
891             m_jit.emitRestoreCalleeSaves();
892             m_jit.prepareForTailCallSlow();
893         }
894     }
895
896     JITCompiler::Call fastCall = isTail ? m_jit.nearTailCall() : m_jit.nearCall();
897
898     JITCompiler::Jump done = m_jit.jump();
899
900     slowPath.link(&m_jit);
901
902     if (node->op() == TailCall) {
903         CallFrameShuffler callFrameShuffler(m_jit, shuffleData);
904         callFrameShuffler.setCalleeJSValueRegs(JSValueRegs(
905             GPRInfo::regT1, GPRInfo::regT0));
906         callFrameShuffler.prepareForSlowPath();
907     } else {
908         // Callee payload needs to be in regT0, tag in regT1
909         if (calleeTagGPR == GPRInfo::regT0) {
910             if (calleePayloadGPR == GPRInfo::regT1)
911                 m_jit.swap(GPRInfo::regT1, GPRInfo::regT0);
912             else {
913                 m_jit.move(calleeTagGPR, GPRInfo::regT1);
914                 m_jit.move(calleePayloadGPR, GPRInfo::regT0);
915             }
916         } else {
917             m_jit.move(calleePayloadGPR, GPRInfo::regT0);
918             m_jit.move(calleeTagGPR, GPRInfo::regT1);
919         }
920
921         if (isTail)
922             m_jit.emitRestoreCalleeSaves();
923     }
924
925     m_jit.move(TrustedImmPtr(info), GPRInfo::regT2);
926     JITCompiler::Call slowCall = m_jit.nearCall();
927
928     done.link(&m_jit);
929
930     if (isTail)
931         m_jit.abortWithReason(JITDidReturnFromTailCall);
932     else
933         setResultAndResetStack();
934
935     m_jit.addJSCall(fastCall, slowCall, targetToCheck, info);
936 }
937
938 template<bool strict>
939 GPRReg SpeculativeJIT::fillSpeculateInt32Internal(Edge edge, DataFormat& returnFormat)
940 {
941     AbstractValue& value = m_state.forNode(edge);
942     SpeculatedType type = value.m_type;
943     ASSERT(edge.useKind() != KnownInt32Use || !(value.m_type & ~SpecInt32Only));
944
945     m_interpreter.filter(value, SpecInt32Only);
946     if (value.isClear()) {
947         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
948         returnFormat = DataFormatInt32;
949         return allocate();
950     }
951
952     VirtualRegister virtualRegister = edge->virtualRegister();
953     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
954
955     switch (info.registerFormat()) {
956     case DataFormatNone: {
957         if (edge->hasConstant()) {
958             ASSERT(edge->isInt32Constant());
959             GPRReg gpr = allocate();
960             m_jit.move(MacroAssembler::Imm32(edge->asInt32()), gpr);
961             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
962             info.fillInt32(*m_stream, gpr);
963             returnFormat = DataFormatInt32;
964             return gpr;
965         }
966
967         DataFormat spillFormat = info.spillFormat();
968
969         ASSERT_UNUSED(spillFormat, (spillFormat & DataFormatJS) || spillFormat == DataFormatInt32);
970
971         // If we know this was spilled as an integer we can fill without checking.
972         if (type & ~SpecInt32Only)
973             speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), edge, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag)));
974
975         GPRReg gpr = allocate();
976         m_jit.load32(JITCompiler::payloadFor(virtualRegister), gpr);
977         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
978         info.fillInt32(*m_stream, gpr);
979         returnFormat = DataFormatInt32;
980         return gpr;
981     }
982
983     case DataFormatJSInt32:
984     case DataFormatJS: {
985         // Check the value is an integer.
986         GPRReg tagGPR = info.tagGPR();
987         GPRReg payloadGPR = info.payloadGPR();
988         m_gprs.lock(tagGPR);
989         m_gprs.lock(payloadGPR);
990         if (type & ~SpecInt32Only)
991             speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), edge, m_jit.branchIfNotInt32(tagGPR));
992         m_gprs.unlock(tagGPR);
993         m_gprs.release(tagGPR);
994         m_gprs.release(payloadGPR);
995         m_gprs.retain(payloadGPR, virtualRegister, SpillOrderInteger);
996         info.fillInt32(*m_stream, payloadGPR);
997         // If !strict we're done, return.
998         returnFormat = DataFormatInt32;
999         return payloadGPR;
1000     }
1001
1002     case DataFormatInt32: {
1003         GPRReg gpr = info.gpr();
1004         m_gprs.lock(gpr);
1005         returnFormat = DataFormatInt32;
1006         return gpr;
1007     }
1008
1009     case DataFormatCell:
1010     case DataFormatBoolean:
1011     case DataFormatJSDouble:
1012     case DataFormatJSCell:
1013     case DataFormatJSBoolean:
1014     case DataFormatDouble:
1015     case DataFormatStorage:
1016     default:
1017         RELEASE_ASSERT_NOT_REACHED();
1018         return InvalidGPRReg;
1019     }
1020 }
1021
1022 GPRReg SpeculativeJIT::fillSpeculateInt32(Edge edge, DataFormat& returnFormat)
1023 {
1024     return fillSpeculateInt32Internal<false>(edge, returnFormat);
1025 }
1026
1027 GPRReg SpeculativeJIT::fillSpeculateInt32Strict(Edge edge)
1028 {
1029     DataFormat mustBeDataFormatInt32;
1030     GPRReg result = fillSpeculateInt32Internal<true>(edge, mustBeDataFormatInt32);
1031     ASSERT(mustBeDataFormatInt32 == DataFormatInt32);
1032     return result;
1033 }
1034
1035 FPRReg SpeculativeJIT::fillSpeculateDouble(Edge edge)
1036 {
1037     ASSERT(isDouble(edge.useKind()));
1038     ASSERT(edge->hasDoubleResult());
1039     VirtualRegister virtualRegister = edge->virtualRegister();
1040     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1041
1042     if (info.registerFormat() == DataFormatNone) {
1043
1044         if (edge->hasConstant()) {
1045             RELEASE_ASSERT(edge->isNumberConstant());
1046             FPRReg fpr = fprAllocate();
1047             m_jit.loadDouble(TrustedImmPtr(m_jit.addressOfDoubleConstant(edge.node())), fpr);
1048             m_fprs.retain(fpr, virtualRegister, SpillOrderConstant);
1049             info.fillDouble(*m_stream, fpr);
1050             return fpr;
1051         }
1052         
1053         RELEASE_ASSERT(info.spillFormat() == DataFormatDouble);
1054         FPRReg fpr = fprAllocate();
1055         m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
1056         m_fprs.retain(fpr, virtualRegister, SpillOrderSpilled);
1057         info.fillDouble(*m_stream, fpr);
1058         return fpr;
1059     }
1060
1061     RELEASE_ASSERT(info.registerFormat() == DataFormatDouble);
1062     FPRReg fpr = info.fpr();
1063     m_fprs.lock(fpr);
1064     return fpr;
1065 }
1066
1067 GPRReg SpeculativeJIT::fillSpeculateCell(Edge edge)
1068 {
1069     AbstractValue& value = m_state.forNode(edge);
1070     SpeculatedType type = value.m_type;
1071     ASSERT((edge.useKind() != KnownCellUse && edge.useKind() != KnownStringUse) || !(value.m_type & ~SpecCell));
1072
1073     m_interpreter.filter(value, SpecCell);
1074     if (value.isClear()) {
1075         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1076         return allocate();
1077     }
1078
1079     VirtualRegister virtualRegister = edge->virtualRegister();
1080     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1081
1082     switch (info.registerFormat()) {
1083     case DataFormatNone: {
1084         if (edge->hasConstant()) {
1085             GPRReg gpr = allocate();
1086             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1087             m_jit.move(TrustedImmPtr(edge->constant()), gpr);
1088             info.fillCell(*m_stream, gpr);
1089             return gpr;
1090         }
1091
1092         ASSERT((info.spillFormat() & DataFormatJS) || info.spillFormat() == DataFormatCell);
1093         if (type & ~SpecCell) {
1094             speculationCheck(
1095                 BadType,
1096                 JSValueSource(JITCompiler::addressFor(virtualRegister)),
1097                 edge,
1098                 m_jit.branch32(
1099                     MacroAssembler::NotEqual,
1100                     JITCompiler::tagFor(virtualRegister),
1101                     TrustedImm32(JSValue::CellTag)));
1102         }
1103         GPRReg gpr = allocate();
1104         m_jit.load32(JITCompiler::payloadFor(virtualRegister), gpr);
1105         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1106         info.fillCell(*m_stream, gpr);
1107         return gpr;
1108     }
1109
1110     case DataFormatCell: {
1111         GPRReg gpr = info.gpr();
1112         m_gprs.lock(gpr);
1113         return gpr;
1114     }
1115
1116     case DataFormatJSCell:
1117     case DataFormatJS: {
1118         GPRReg tagGPR = info.tagGPR();
1119         GPRReg payloadGPR = info.payloadGPR();
1120         m_gprs.lock(tagGPR);
1121         m_gprs.lock(payloadGPR);
1122         if (type & ~SpecCell) {
1123             speculationCheck(
1124                 BadType, JSValueRegs(tagGPR, payloadGPR), edge,
1125                 m_jit.branchIfNotCell(info.jsValueRegs()));
1126         }
1127         m_gprs.unlock(tagGPR);
1128         m_gprs.release(tagGPR);
1129         m_gprs.release(payloadGPR);
1130         m_gprs.retain(payloadGPR, virtualRegister, SpillOrderCell);
1131         info.fillCell(*m_stream, payloadGPR);
1132         return payloadGPR;
1133     }
1134
1135     case DataFormatJSInt32:
1136     case DataFormatInt32:
1137     case DataFormatJSDouble:
1138     case DataFormatJSBoolean:
1139     case DataFormatBoolean:
1140     case DataFormatDouble:
1141     case DataFormatStorage:
1142         RELEASE_ASSERT_NOT_REACHED();
1143
1144     default:
1145         RELEASE_ASSERT_NOT_REACHED();
1146         return InvalidGPRReg;
1147     }
1148 }
1149
1150 GPRReg SpeculativeJIT::fillSpeculateBoolean(Edge edge)
1151 {
1152     AbstractValue& value = m_state.forNode(edge);
1153     SpeculatedType type = value.m_type;
1154     ASSERT(edge.useKind() != KnownBooleanUse || !(value.m_type & ~SpecBoolean));
1155
1156     m_interpreter.filter(value, SpecBoolean);
1157     if (value.isClear()) {
1158         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1159         return allocate();
1160     }
1161
1162     VirtualRegister virtualRegister = edge->virtualRegister();
1163     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1164
1165     switch (info.registerFormat()) {
1166     case DataFormatNone: {
1167         if (edge->hasConstant()) {
1168             JSValue jsValue = edge->asJSValue();
1169             GPRReg gpr = allocate();
1170             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1171             m_jit.move(MacroAssembler::TrustedImm32(jsValue.asBoolean()), gpr);
1172             info.fillBoolean(*m_stream, gpr);
1173             return gpr;
1174         }
1175
1176         ASSERT((info.spillFormat() & DataFormatJS) || info.spillFormat() == DataFormatBoolean);
1177
1178         if (type & ~SpecBoolean)
1179             speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), edge, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::BooleanTag)));
1180
1181         GPRReg gpr = allocate();
1182         m_jit.load32(JITCompiler::payloadFor(virtualRegister), gpr);
1183         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1184         info.fillBoolean(*m_stream, gpr);
1185         return gpr;
1186     }
1187
1188     case DataFormatBoolean: {
1189         GPRReg gpr = info.gpr();
1190         m_gprs.lock(gpr);
1191         return gpr;
1192     }
1193
1194     case DataFormatJSBoolean:
1195     case DataFormatJS: {
1196         GPRReg tagGPR = info.tagGPR();
1197         GPRReg payloadGPR = info.payloadGPR();
1198         m_gprs.lock(tagGPR);
1199         m_gprs.lock(payloadGPR);
1200         if (type & ~SpecBoolean)
1201             speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), edge, m_jit.branchIfNotBoolean(tagGPR, InvalidGPRReg));
1202
1203         m_gprs.unlock(tagGPR);
1204         m_gprs.release(tagGPR);
1205         m_gprs.release(payloadGPR);
1206         m_gprs.retain(payloadGPR, virtualRegister, SpillOrderBoolean);
1207         info.fillBoolean(*m_stream, payloadGPR);
1208         return payloadGPR;
1209     }
1210
1211     case DataFormatJSInt32:
1212     case DataFormatInt32:
1213     case DataFormatJSDouble:
1214     case DataFormatJSCell:
1215     case DataFormatCell:
1216     case DataFormatDouble:
1217     case DataFormatStorage:
1218         RELEASE_ASSERT_NOT_REACHED();
1219
1220     default:
1221         RELEASE_ASSERT_NOT_REACHED();
1222         return InvalidGPRReg;
1223     }
1224 }
1225
1226 void SpeculativeJIT::compileObjectStrictEquality(Edge objectChild, Edge otherChild)
1227 {
1228     SpeculateCellOperand op1(this, objectChild);
1229     JSValueOperand op2(this, otherChild);
1230
1231     GPRReg op1GPR = op1.gpr();
1232     GPRReg op2GPR = op2.payloadGPR();
1233
1234     DFG_TYPE_CHECK(JSValueSource::unboxedCell(op1GPR), objectChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1235
1236     GPRTemporary resultPayload(this, Reuse, op1);
1237     GPRReg resultPayloadGPR = resultPayload.gpr();
1238     
1239     MacroAssembler::Jump op2CellJump = m_jit.branchIfCell(op2.jsValueRegs());
1240     
1241     m_jit.move(TrustedImm32(0), resultPayloadGPR);
1242     MacroAssembler::Jump op2NotCellJump = m_jit.jump();
1243     
1244     // At this point we know that we can perform a straight-forward equality comparison on pointer
1245     // values because we are doing strict equality.
1246     op2CellJump.link(&m_jit);
1247     m_jit.compare32(MacroAssembler::Equal, op1GPR, op2GPR, resultPayloadGPR);
1248     
1249     op2NotCellJump.link(&m_jit);
1250     booleanResult(resultPayloadGPR, m_currentNode);
1251 }
1252     
1253 void SpeculativeJIT::compilePeepHoleObjectStrictEquality(Edge objectChild, Edge otherChild, Node* branchNode)
1254 {
1255     BasicBlock* taken = branchNode->branchData()->taken.block;
1256     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
1257
1258     SpeculateCellOperand op1(this, objectChild);
1259     JSValueOperand op2(this, otherChild);
1260     
1261     GPRReg op1GPR = op1.gpr();
1262     GPRReg op2GPR = op2.payloadGPR();
1263
1264     DFG_TYPE_CHECK(JSValueSource::unboxedCell(op1GPR), objectChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1265
1266     branch32(MacroAssembler::NotEqual, op2.tagGPR(), TrustedImm32(JSValue::CellTag), notTaken);
1267     
1268     if (taken == nextBlock()) {
1269         branch32(MacroAssembler::NotEqual, op1GPR, op2GPR, notTaken);
1270         jump(taken);
1271     } else {
1272         branch32(MacroAssembler::Equal, op1GPR, op2GPR, taken);
1273         jump(notTaken);
1274     }
1275 }
1276
1277 void SpeculativeJIT::compileObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild)
1278 {
1279     SpeculateCellOperand op1(this, leftChild);
1280     JSValueOperand op2(this, rightChild, ManualOperandSpeculation);
1281     GPRTemporary result(this);
1282     
1283     GPRReg op1GPR = op1.gpr();
1284     GPRReg op2TagGPR = op2.tagGPR();
1285     GPRReg op2PayloadGPR = op2.payloadGPR();
1286     GPRReg resultGPR = result.gpr();
1287
1288     bool masqueradesAsUndefinedWatchpointValid =
1289         masqueradesAsUndefinedWatchpointIsStillValid();
1290
1291     if (masqueradesAsUndefinedWatchpointValid) {
1292         DFG_TYPE_CHECK(
1293             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1294     } else {
1295         DFG_TYPE_CHECK(
1296             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1297         speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), leftChild, 
1298             m_jit.branchTest8(
1299                 MacroAssembler::NonZero, 
1300                 MacroAssembler::Address(op1GPR, JSCell::typeInfoFlagsOffset()), 
1301                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1302     }
1303     
1304     
1305     // It seems that most of the time when programs do a == b where b may be either null/undefined
1306     // or an object, b is usually an object. Balance the branches to make that case fast.
1307     MacroAssembler::Jump rightNotCell = m_jit.branchIfNotCell(op2.jsValueRegs());
1308     
1309     // We know that within this branch, rightChild must be a cell.
1310     if (masqueradesAsUndefinedWatchpointValid) {
1311         DFG_TYPE_CHECK(
1312             JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, (~SpecCell) | SpecObject, m_jit.branchIfNotObject(op2PayloadGPR));
1313     } else {
1314         DFG_TYPE_CHECK(
1315             JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, (~SpecCell) | SpecObject, m_jit.branchIfNotObject(op2PayloadGPR));
1316         speculationCheck(BadType, JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, 
1317             m_jit.branchTest8(
1318                 MacroAssembler::NonZero, 
1319                 MacroAssembler::Address(op2PayloadGPR, JSCell::typeInfoFlagsOffset()), 
1320                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1321     }
1322     
1323     // At this point we know that we can perform a straight-forward equality comparison on pointer
1324     // values because both left and right are pointers to objects that have no special equality
1325     // protocols.
1326     MacroAssembler::Jump falseCase = m_jit.branchPtr(MacroAssembler::NotEqual, op1GPR, op2PayloadGPR);
1327     MacroAssembler::Jump trueCase = m_jit.jump();
1328     
1329     rightNotCell.link(&m_jit);
1330     
1331     // We know that within this branch, rightChild must not be a cell. Check if that is enough to
1332     // prove that it is either null or undefined.
1333     if (needsTypeCheck(rightChild, SpecCell | SpecOther)) {
1334         m_jit.or32(TrustedImm32(1), op2TagGPR, resultGPR);
1335         
1336         typeCheck(
1337             JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, SpecCell | SpecOther,
1338             m_jit.branch32(
1339                 MacroAssembler::NotEqual, resultGPR,
1340                 MacroAssembler::TrustedImm32(JSValue::NullTag)));
1341     }
1342     
1343     falseCase.link(&m_jit);
1344     m_jit.move(TrustedImm32(0), resultGPR);
1345     MacroAssembler::Jump done = m_jit.jump();
1346     trueCase.link(&m_jit);
1347     m_jit.move(TrustedImm32(1), resultGPR);
1348     done.link(&m_jit);
1349     
1350     booleanResult(resultGPR, m_currentNode);
1351 }
1352
1353 void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild, Node* branchNode)
1354 {
1355     BasicBlock* taken = branchNode->branchData()->taken.block;
1356     BasicBlock* notTaken = branchNode->branchData()->notTaken.block;
1357     
1358     SpeculateCellOperand op1(this, leftChild);
1359     JSValueOperand op2(this, rightChild, ManualOperandSpeculation);
1360     GPRTemporary result(this);
1361     
1362     GPRReg op1GPR = op1.gpr();
1363     GPRReg op2TagGPR = op2.tagGPR();
1364     GPRReg op2PayloadGPR = op2.payloadGPR();
1365     GPRReg resultGPR = result.gpr();
1366
1367     bool masqueradesAsUndefinedWatchpointValid =
1368         masqueradesAsUndefinedWatchpointIsStillValid();
1369
1370     if (masqueradesAsUndefinedWatchpointValid) {
1371         DFG_TYPE_CHECK(
1372             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1373     } else {
1374         DFG_TYPE_CHECK(
1375             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchIfNotObject(op1GPR));
1376         speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), leftChild,
1377             m_jit.branchTest8(
1378                 MacroAssembler::NonZero, 
1379                 MacroAssembler::Address(op1GPR, JSCell::typeInfoFlagsOffset()), 
1380                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1381     }
1382     
1383     // It seems that most of the time when programs do a == b where b may be either null/undefined
1384     // or an object, b is usually an object. Balance the branches to make that case fast.
1385     MacroAssembler::Jump rightNotCell = m_jit.branchIfNotCell(op2.jsValueRegs());
1386     
1387     // We know that within this branch, rightChild must be a cell.
1388     if (masqueradesAsUndefinedWatchpointValid) {
1389         DFG_TYPE_CHECK(
1390             JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, (~SpecCell) | SpecObject,
1391             m_jit.branchIfNotObject(op2PayloadGPR));
1392     } else {
1393         DFG_TYPE_CHECK(
1394             JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, (~SpecCell) | SpecObject,
1395             m_jit.branchIfNotObject(op2PayloadGPR));
1396         speculationCheck(BadType, JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild,
1397             m_jit.branchTest8(
1398                 MacroAssembler::NonZero, 
1399                 MacroAssembler::Address(op2PayloadGPR, JSCell::typeInfoFlagsOffset()), 
1400                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1401     }
1402     
1403     // At this point we know that we can perform a straight-forward equality comparison on pointer
1404     // values because both left and right are pointers to objects that have no special equality
1405     // protocols.
1406     branch32(MacroAssembler::Equal, op1GPR, op2PayloadGPR, taken);
1407     
1408     // We know that within this branch, rightChild must not be a cell. Check if that is enough to
1409     // prove that it is either null or undefined.
1410     if (!needsTypeCheck(rightChild, SpecCell | SpecOther))
1411         rightNotCell.link(&m_jit);
1412     else {
1413         jump(notTaken, ForceJump);
1414         
1415         rightNotCell.link(&m_jit);
1416         m_jit.or32(TrustedImm32(1), op2TagGPR, resultGPR);
1417         
1418         typeCheck(
1419             JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild, SpecCell | SpecOther,
1420             m_jit.branch32(
1421                 MacroAssembler::NotEqual, resultGPR,
1422                 MacroAssembler::TrustedImm32(JSValue::NullTag)));
1423     }
1424     
1425     jump(notTaken);
1426 }
1427
1428 void SpeculativeJIT::compileSymbolUntypedEquality(Node* node, Edge symbolEdge, Edge untypedEdge)
1429 {
1430     SpeculateCellOperand symbol(this, symbolEdge);
1431     JSValueOperand untyped(this, untypedEdge);
1432
1433     GPRReg symbolGPR = symbol.gpr();
1434     GPRReg untypedGPR = untyped.payloadGPR();
1435
1436     speculateSymbol(symbolEdge, symbolGPR);
1437
1438     GPRTemporary resultPayload(this, Reuse, symbol);
1439     GPRReg resultPayloadGPR = resultPayload.gpr();
1440
1441     MacroAssembler::Jump untypedCellJump = m_jit.branchIfCell(untyped.jsValueRegs());
1442
1443     m_jit.move(TrustedImm32(0), resultPayloadGPR);
1444     MacroAssembler::Jump untypedNotCellJump = m_jit.jump();
1445
1446     // At this point we know that we can perform a straight-forward equality comparison on pointer
1447     // values because we are doing strict equality.
1448     untypedCellJump.link(&m_jit);
1449     m_jit.compare32(MacroAssembler::Equal, symbolGPR, untypedGPR, resultPayloadGPR);
1450
1451     untypedNotCellJump.link(&m_jit);
1452     booleanResult(resultPayloadGPR, node);
1453 }
1454
1455 void SpeculativeJIT::compileObjectOrOtherLogicalNot(Edge nodeUse)
1456 {
1457     JSValueOperand value(this, nodeUse, ManualOperandSpeculation);
1458     GPRTemporary resultPayload(this);
1459     GPRReg valueTagGPR = value.tagGPR();
1460     GPRReg valuePayloadGPR = value.payloadGPR();
1461     GPRReg resultPayloadGPR = resultPayload.gpr();
1462     GPRTemporary structure;
1463     GPRReg structureGPR = InvalidGPRReg;
1464
1465     bool masqueradesAsUndefinedWatchpointValid =
1466         masqueradesAsUndefinedWatchpointIsStillValid();
1467
1468     if (!masqueradesAsUndefinedWatchpointValid) {
1469         // The masquerades as undefined case will use the structure register, so allocate it here.
1470         // Do this at the top of the function to avoid branching around a register allocation.
1471         GPRTemporary realStructure(this);
1472         structure.adopt(realStructure);
1473         structureGPR = structure.gpr();
1474     }
1475
1476     MacroAssembler::Jump notCell = m_jit.branchIfNotCell(value.jsValueRegs());
1477     if (masqueradesAsUndefinedWatchpointValid) {
1478         DFG_TYPE_CHECK(
1479             JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, (~SpecCell) | SpecObject,
1480             m_jit.branchIfNotObject(valuePayloadGPR));
1481     } else {
1482         DFG_TYPE_CHECK(
1483             JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, (~SpecCell) | SpecObject,
1484             m_jit.branchIfNotObject(valuePayloadGPR));
1485
1486         MacroAssembler::Jump isNotMasqueradesAsUndefined = 
1487             m_jit.branchTest8(
1488                 MacroAssembler::Zero, 
1489                 MacroAssembler::Address(valuePayloadGPR, JSCell::typeInfoFlagsOffset()), 
1490                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined));
1491
1492         m_jit.loadPtr(MacroAssembler::Address(valuePayloadGPR, JSCell::structureIDOffset()), structureGPR);
1493         speculationCheck(BadType, JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, 
1494             m_jit.branchPtr(
1495                 MacroAssembler::Equal, 
1496                 MacroAssembler::Address(structureGPR, Structure::globalObjectOffset()), 
1497                 TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.graph().globalObjectFor(m_currentNode->origin.semantic))));
1498
1499         isNotMasqueradesAsUndefined.link(&m_jit);
1500     }
1501     m_jit.move(TrustedImm32(0), resultPayloadGPR);
1502     MacroAssembler::Jump done = m_jit.jump();
1503     
1504     notCell.link(&m_jit);
1505  
1506     COMPILE_ASSERT((JSValue::UndefinedTag | 1) == JSValue::NullTag, UndefinedTag_OR_1_EQUALS_NullTag);
1507     if (needsTypeCheck(nodeUse, SpecCell | SpecOther)) {
1508         m_jit.or32(TrustedImm32(1), valueTagGPR, resultPayloadGPR);
1509         typeCheck(
1510             JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, SpecCell | SpecOther,
1511             m_jit.branch32(
1512                 MacroAssembler::NotEqual, 
1513                 resultPayloadGPR, 
1514                 TrustedImm32(JSValue::NullTag)));
1515     }
1516     m_jit.move(TrustedImm32(1), resultPayloadGPR);
1517     
1518     done.link(&m_jit);
1519     
1520     booleanResult(resultPayloadGPR, m_currentNode);
1521 }
1522
1523 void SpeculativeJIT::compileLogicalNot(Node* node)
1524 {
1525     switch (node->child1().useKind()) {
1526     case BooleanUse:
1527     case KnownBooleanUse: {
1528         SpeculateBooleanOperand value(this, node->child1());
1529         GPRTemporary result(this, Reuse, value);
1530         m_jit.xor32(TrustedImm32(1), value.gpr(), result.gpr());
1531         booleanResult(result.gpr(), node);
1532         return;
1533     }
1534         
1535     case ObjectOrOtherUse: {
1536         compileObjectOrOtherLogicalNot(node->child1());
1537         return;
1538     }
1539         
1540     case Int32Use: {
1541         SpeculateInt32Operand value(this, node->child1());
1542         GPRTemporary resultPayload(this, Reuse, value);
1543         m_jit.compare32(MacroAssembler::Equal, value.gpr(), MacroAssembler::TrustedImm32(0), resultPayload.gpr());
1544         booleanResult(resultPayload.gpr(), node);
1545         return;
1546     }
1547         
1548     case DoubleRepUse: {
1549         SpeculateDoubleOperand value(this, node->child1());
1550         FPRTemporary scratch(this);
1551         GPRTemporary resultPayload(this);
1552         m_jit.move(TrustedImm32(0), resultPayload.gpr());
1553         MacroAssembler::Jump nonZero = m_jit.branchDoubleNonZero(value.fpr(), scratch.fpr());
1554         m_jit.move(TrustedImm32(1), resultPayload.gpr());
1555         nonZero.link(&m_jit);
1556         booleanResult(resultPayload.gpr(), node);
1557         return;
1558     }
1559
1560     case UntypedUse: {
1561         JSValueOperand arg1(this, node->child1());
1562         GPRTemporary result(this);
1563         GPRTemporary temp(this);
1564         FPRTemporary valueFPR(this);
1565         FPRTemporary tempFPR(this);
1566
1567         GPRReg resultGPR = result.gpr();
1568
1569         bool shouldCheckMasqueradesAsUndefined = !masqueradesAsUndefinedWatchpointIsStillValid();
1570         JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
1571         bool negateResult = true;
1572         m_jit.emitConvertValueToBoolean(*m_jit.vm(), arg1.jsValueRegs(), resultGPR, temp.gpr(), valueFPR.fpr(), tempFPR.fpr(), shouldCheckMasqueradesAsUndefined, globalObject, negateResult);
1573         booleanResult(resultGPR, node);
1574         return;
1575     }
1576     case StringUse:
1577         return compileStringZeroLength(node);
1578
1579     case StringOrOtherUse:
1580         return compileLogicalNotStringOrOther(node);
1581
1582     default:
1583         RELEASE_ASSERT_NOT_REACHED();
1584         break;
1585     }
1586 }
1587
1588 void SpeculativeJIT::emitObjectOrOtherBranch(Edge nodeUse, BasicBlock* taken, BasicBlock* notTaken)
1589 {
1590     JSValueOperand value(this, nodeUse, ManualOperandSpeculation);
1591     GPRTemporary scratch(this);
1592     GPRReg valueTagGPR = value.tagGPR();
1593     GPRReg valuePayloadGPR = value.payloadGPR();
1594     GPRReg scratchGPR = scratch.gpr();
1595     
1596     MacroAssembler::Jump notCell = m_jit.branchIfNotCell(value.jsValueRegs());
1597     if (masqueradesAsUndefinedWatchpointIsStillValid()) {
1598         DFG_TYPE_CHECK(
1599             JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, (~SpecCell) | SpecObject,
1600             m_jit.branchIfNotObject(valuePayloadGPR));
1601     } else {
1602         DFG_TYPE_CHECK(
1603             JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, (~SpecCell) | SpecObject,
1604             m_jit.branchIfNotObject(valuePayloadGPR));
1605
1606         JITCompiler::Jump isNotMasqueradesAsUndefined = m_jit.branchTest8(
1607             JITCompiler::Zero, 
1608             MacroAssembler::Address(valuePayloadGPR, JSCell::typeInfoFlagsOffset()), 
1609             TrustedImm32(MasqueradesAsUndefined));
1610
1611         m_jit.loadPtr(MacroAssembler::Address(valuePayloadGPR, JSCell::structureIDOffset()), scratchGPR);
1612         speculationCheck(BadType, JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse,
1613             m_jit.branchPtr(
1614                 MacroAssembler::Equal, 
1615                 MacroAssembler::Address(scratchGPR, Structure::globalObjectOffset()), 
1616                 TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.graph().globalObjectFor(m_currentNode->origin.semantic))));
1617
1618         isNotMasqueradesAsUndefined.link(&m_jit);
1619     }
1620     jump(taken, ForceJump);
1621     
1622     notCell.link(&m_jit);
1623     
1624     COMPILE_ASSERT((JSValue::UndefinedTag | 1) == JSValue::NullTag, UndefinedTag_OR_1_EQUALS_NullTag);
1625     if (needsTypeCheck(nodeUse, SpecCell | SpecOther)) {
1626         m_jit.or32(TrustedImm32(1), valueTagGPR, scratchGPR);
1627         typeCheck(
1628             JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, SpecCell | SpecOther,
1629             m_jit.branch32(MacroAssembler::NotEqual, scratchGPR, TrustedImm32(JSValue::NullTag)));
1630     }
1631
1632     jump(notTaken);
1633     
1634     noResult(m_currentNode);
1635 }
1636
1637 void SpeculativeJIT::emitBranch(Node* node)
1638 {
1639     BasicBlock* taken = node->branchData()->taken.block;
1640     BasicBlock* notTaken = node->branchData()->notTaken.block;
1641
1642     switch (node->child1().useKind()) {
1643     case BooleanUse:
1644     case KnownBooleanUse: {
1645         SpeculateBooleanOperand value(this, node->child1());
1646         MacroAssembler::ResultCondition condition = MacroAssembler::NonZero;
1647
1648         if (taken == nextBlock()) {
1649             condition = MacroAssembler::Zero;
1650             BasicBlock* tmp = taken;
1651             taken = notTaken;
1652             notTaken = tmp;
1653         }
1654
1655         branchTest32(condition, value.gpr(), TrustedImm32(1), taken);
1656         jump(notTaken);
1657
1658         noResult(node);
1659         return;
1660     }
1661     
1662     case ObjectOrOtherUse: {
1663         emitObjectOrOtherBranch(node->child1(), taken, notTaken);
1664         return;
1665     }
1666
1667     case StringUse: {
1668         emitStringBranch(node->child1(), taken, notTaken);
1669         return;
1670     }
1671
1672     case StringOrOtherUse: {
1673         emitStringOrOtherBranch(node->child1(), taken, notTaken);
1674         return;
1675     }
1676
1677     case DoubleRepUse:
1678     case Int32Use: {
1679         if (node->child1().useKind() == Int32Use) {
1680             bool invert = false;
1681             
1682             if (taken == nextBlock()) {
1683                 invert = true;
1684                 BasicBlock* tmp = taken;
1685                 taken = notTaken;
1686                 notTaken = tmp;
1687             }
1688
1689             SpeculateInt32Operand value(this, node->child1());
1690             branchTest32(invert ? MacroAssembler::Zero : MacroAssembler::NonZero, value.gpr(), taken);
1691         } else {
1692             SpeculateDoubleOperand value(this, node->child1());
1693             FPRTemporary scratch(this);
1694             branchDoubleNonZero(value.fpr(), scratch.fpr(), taken);
1695         }
1696         
1697         jump(notTaken);
1698         
1699         noResult(node);
1700         return;
1701     }
1702     
1703     case UntypedUse: {
1704         JSValueOperand value(this, node->child1());
1705         FPRTemporary valueFPR(this);
1706         FPRTemporary tempFPR(this);
1707         GPRTemporary result(this);
1708         GPRTemporary temp(this);
1709
1710         JSValueRegs valueRegs = value.jsValueRegs();
1711         GPRReg resultGPR = result.gpr();
1712     
1713         use(node->child1());
1714
1715         bool shouldCheckMasqueradesAsUndefined = !masqueradesAsUndefinedWatchpointIsStillValid();
1716         JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
1717         auto falsey = m_jit.branchIfFalsey(*m_jit.vm(), valueRegs, resultGPR, temp.gpr(), valueFPR.fpr(), tempFPR.fpr(), shouldCheckMasqueradesAsUndefined, globalObject);
1718         addBranch(falsey, notTaken);
1719         jump(taken, ForceJump);
1720
1721         noResult(node, UseChildrenCalledExplicitly);
1722         return;
1723     }
1724         
1725     default:
1726         RELEASE_ASSERT_NOT_REACHED();
1727         break;
1728     }
1729 }
1730
1731 template<typename BaseOperandType, typename PropertyOperandType, typename ValueOperandType, typename TagType>
1732 void SpeculativeJIT::compileContiguousPutByVal(Node* node, BaseOperandType& base, PropertyOperandType& property, ValueOperandType& value, GPRReg valuePayloadReg, TagType valueTag)
1733 {
1734     Edge child4 = m_jit.graph().varArgChild(node, 3);
1735
1736     ArrayMode arrayMode = node->arrayMode();
1737     
1738     GPRReg baseReg = base.gpr();
1739     GPRReg propertyReg = property.gpr();
1740     
1741     StorageOperand storage(this, child4);
1742     GPRReg storageReg = storage.gpr();
1743
1744     if (node->op() == PutByValAlias) {
1745         // Store the value to the array.
1746         GPRReg propertyReg = property.gpr();
1747         m_jit.store32(valueTag, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
1748         m_jit.store32(valuePayloadReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
1749         
1750         noResult(node);
1751         return;
1752     }
1753     
1754     MacroAssembler::Jump slowCase;
1755
1756     if (arrayMode.isInBounds()) {
1757         speculationCheck(
1758             OutOfBounds, JSValueRegs(), 0,
1759             m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
1760     } else {
1761         MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
1762         
1763         slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfVectorLength()));
1764         
1765         if (!arrayMode.isOutOfBounds())
1766             speculationCheck(OutOfBounds, JSValueRegs(), 0, slowCase);
1767         
1768         m_jit.add32(TrustedImm32(1), propertyReg);
1769         m_jit.store32(propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
1770         m_jit.sub32(TrustedImm32(1), propertyReg);
1771         
1772         inBounds.link(&m_jit);
1773     }
1774     
1775     m_jit.store32(valueTag, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
1776     m_jit.store32(valuePayloadReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
1777     
1778     base.use();
1779     property.use();
1780     value.use();
1781     storage.use();
1782     
1783     if (arrayMode.isOutOfBounds()) {
1784         if (node->op() == PutByValDirect) {
1785             addSlowPathGenerator(slowPathCall(
1786                 slowCase, this,
1787                 m_jit.codeBlock()->isStrictMode() ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValDirectBeyondArrayBoundsNonStrict,
1788                 NoResult, baseReg, propertyReg, JSValueRegs(valueTag, valuePayloadReg)));
1789         } else {
1790             addSlowPathGenerator(slowPathCall(
1791                 slowCase, this,
1792                 m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
1793                 NoResult, baseReg, propertyReg, JSValueRegs(valueTag, valuePayloadReg)));
1794         }
1795     }
1796
1797     noResult(node, UseChildrenCalledExplicitly);    
1798 }
1799
1800 void SpeculativeJIT::compile(Node* node)
1801 {
1802     NodeType op = node->op();
1803
1804 #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
1805     m_jit.clearRegisterAllocationOffsets();
1806 #endif
1807
1808     switch (op) {
1809     case JSConstant:
1810     case DoubleConstant:
1811     case PhantomDirectArguments:
1812     case PhantomClonedArguments:
1813         initConstantInfo(node);
1814         break;
1815
1816     case LazyJSConstant:
1817         compileLazyJSConstant(node);
1818         break;
1819
1820     case Identity: {
1821         compileIdentity(node);
1822         break;
1823     }
1824
1825     case GetLocal: {
1826         AbstractValue& value = m_state.operand(node->local());
1827
1828         // If the CFA is tracking this variable and it found that the variable
1829         // cannot have been assigned, then don't attempt to proceed.
1830         if (value.isClear()) {
1831             m_compileOkay = false;
1832             break;
1833         }
1834         
1835         switch (node->variableAccessData()->flushFormat()) {
1836         case FlushedDouble: {
1837             FPRTemporary result(this);
1838             m_jit.loadDouble(JITCompiler::addressFor(node->machineLocal()), result.fpr());
1839             VirtualRegister virtualRegister = node->virtualRegister();
1840             m_fprs.retain(result.fpr(), virtualRegister, SpillOrderDouble);
1841             generationInfoFromVirtualRegister(virtualRegister).initDouble(node, node->refCount(), result.fpr());
1842             break;
1843         }
1844         
1845         case FlushedInt32: {
1846             GPRTemporary result(this);
1847             m_jit.load32(JITCompiler::payloadFor(node->machineLocal()), result.gpr());
1848             
1849             // Like int32Result, but don't useChildren - our children are phi nodes,
1850             // and don't represent values within this dataflow with virtual registers.
1851             VirtualRegister virtualRegister = node->virtualRegister();
1852             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderInteger);
1853             generationInfoFromVirtualRegister(virtualRegister).initInt32(node, node->refCount(), result.gpr());
1854             break;
1855         }
1856         
1857         case FlushedCell: {
1858             GPRTemporary result(this);
1859             m_jit.load32(JITCompiler::payloadFor(node->machineLocal()), result.gpr());
1860             
1861             // Like cellResult, but don't useChildren - our children are phi nodes,
1862             // and don't represent values within this dataflow with virtual registers.
1863             VirtualRegister virtualRegister = node->virtualRegister();
1864             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderCell);
1865             generationInfoFromVirtualRegister(virtualRegister).initCell(node, node->refCount(), result.gpr());
1866             break;
1867         }
1868             
1869         case FlushedBoolean: {
1870             GPRTemporary result(this);
1871             m_jit.load32(JITCompiler::payloadFor(node->machineLocal()), result.gpr());
1872             
1873             // Like booleanResult, but don't useChildren - our children are phi nodes,
1874             // and don't represent values within this dataflow with virtual registers.
1875             VirtualRegister virtualRegister = node->virtualRegister();
1876             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderBoolean);
1877             generationInfoFromVirtualRegister(virtualRegister).initBoolean(node, node->refCount(), result.gpr());
1878             break;
1879         }
1880             
1881         case FlushedJSValue: {
1882             GPRTemporary result(this);
1883             GPRTemporary tag(this);
1884             m_jit.load32(JITCompiler::payloadFor(node->machineLocal()), result.gpr());
1885             m_jit.load32(JITCompiler::tagFor(node->machineLocal()), tag.gpr());
1886             
1887             // Like jsValueResult, but don't useChildren - our children are phi nodes,
1888             // and don't represent values within this dataflow with virtual registers.
1889             VirtualRegister virtualRegister = node->virtualRegister();
1890             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
1891             m_gprs.retain(tag.gpr(), virtualRegister, SpillOrderJS);
1892             
1893             generationInfoFromVirtualRegister(virtualRegister).initJSValue(node, node->refCount(), tag.gpr(), result.gpr(), DataFormatJS);
1894             break;
1895         }
1896             
1897         default:
1898             RELEASE_ASSERT_NOT_REACHED();
1899         }
1900         break;
1901     }
1902
1903     case MovHint: {
1904         compileMovHint(m_currentNode);
1905         noResult(node);
1906         break;
1907     }
1908         
1909     case ZombieHint: {
1910         recordSetLocal(m_currentNode->unlinkedLocal(), VirtualRegister(), DataFormatDead);
1911         noResult(node);
1912         break;
1913     }
1914
1915     case ExitOK: {
1916         noResult(node);
1917         break;
1918     }
1919         
1920     case SetLocal: {
1921         switch (node->variableAccessData()->flushFormat()) {
1922         case FlushedDouble: {
1923             SpeculateDoubleOperand value(this, node->child1());
1924             m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node->machineLocal()));
1925             noResult(node);
1926             // Indicate that it's no longer necessary to retrieve the value of
1927             // this bytecode variable from registers or other locations in the stack,
1928             // but that it is stored as a double.
1929             recordSetLocal(DataFormatDouble);
1930             break;
1931         }
1932             
1933         case FlushedInt32: {
1934             SpeculateInt32Operand value(this, node->child1());
1935             m_jit.store32(value.gpr(), JITCompiler::payloadFor(node->machineLocal()));
1936             noResult(node);
1937             recordSetLocal(DataFormatInt32);
1938             break;
1939         }
1940             
1941         case FlushedCell: {
1942             SpeculateCellOperand cell(this, node->child1());
1943             GPRReg cellGPR = cell.gpr();
1944             m_jit.storePtr(cellGPR, JITCompiler::payloadFor(node->machineLocal()));
1945             noResult(node);
1946             recordSetLocal(DataFormatCell);
1947             break;
1948         }
1949             
1950         case FlushedBoolean: {
1951             SpeculateBooleanOperand value(this, node->child1());
1952             m_jit.store32(value.gpr(), JITCompiler::payloadFor(node->machineLocal()));
1953             noResult(node);
1954             recordSetLocal(DataFormatBoolean);
1955             break;
1956         }
1957             
1958         case FlushedJSValue: {
1959             JSValueOperand value(this, node->child1());
1960             m_jit.store32(value.payloadGPR(), JITCompiler::payloadFor(node->machineLocal()));
1961             m_jit.store32(value.tagGPR(), JITCompiler::tagFor(node->machineLocal()));
1962             noResult(node);
1963             recordSetLocal(dataFormatFor(node->variableAccessData()->flushFormat()));
1964             break;
1965         }
1966             
1967         default:
1968             RELEASE_ASSERT_NOT_REACHED();
1969             break;
1970         }
1971         break;
1972     }
1973
1974     case SetArgument:
1975         // This is a no-op; it just marks the fact that the argument is being used.
1976         // But it may be profitable to use this as a hook to run speculation checks
1977         // on arguments, thereby allowing us to trivially eliminate such checks if
1978         // the argument is not used.
1979         recordSetLocal(dataFormatFor(node->variableAccessData()->flushFormat()));
1980         break;
1981
1982     case ValueBitOr:
1983     case ValueBitAnd:
1984     case ValueBitXor:
1985         compileValueBitwiseOp(node);
1986         break;
1987
1988     case ArithBitAnd:
1989     case ArithBitOr:
1990     case ArithBitXor:
1991         compileBitwiseOp(node);
1992         break;
1993
1994     case ArithBitNot:
1995         compileBitwiseNot(node);
1996         break;
1997
1998     case BitRShift:
1999     case BitLShift:
2000     case BitURShift:
2001         compileShiftOp(node);
2002         break;
2003
2004     case UInt32ToNumber: {
2005         compileUInt32ToNumber(node);
2006         break;
2007     }
2008         
2009     case DoubleAsInt32: {
2010         compileDoubleAsInt32(node);
2011         break;
2012     }
2013
2014     case ValueToInt32: {
2015         compileValueToInt32(node);
2016         break;
2017     }
2018         
2019     case DoubleRep: {
2020         compileDoubleRep(node);
2021         break;
2022     }
2023         
2024     case ValueRep: {
2025         compileValueRep(node);
2026         break;
2027     }
2028
2029     case ValueNegate:
2030         compileValueNegate(node);
2031         break;
2032
2033     case ValueAdd:
2034         compileValueAdd(node);
2035         break;
2036
2037     case ValueSub:
2038         compileValueSub(node);
2039         break;
2040
2041     case StrCat: {
2042         compileStrCat(node);
2043         break;
2044     }
2045
2046     case ArithAdd:
2047         compileArithAdd(node);
2048         break;
2049
2050     case ArithClz32:
2051         compileArithClz32(node);
2052         break;
2053
2054     case MakeRope:
2055         compileMakeRope(node);
2056         break;
2057
2058     case ArithSub:
2059         compileArithSub(node);
2060         break;
2061
2062     case ArithNegate:
2063         compileArithNegate(node);
2064         break;
2065
2066     case ArithMul:
2067         compileArithMul(node);
2068         break;
2069
2070     case ValueMul:
2071         compileValueMul(node);
2072         break;
2073             
2074     case ValueDiv: {
2075         compileValueDiv(node);
2076         break;
2077     }
2078
2079     case ArithDiv: {
2080         compileArithDiv(node);
2081         break;
2082     }
2083
2084     case ArithMod: {
2085         compileArithMod(node);
2086         break;
2087     }
2088
2089     case ArithPow: {
2090         compileArithPow(node);
2091         break;
2092     }
2093
2094     case ArithAbs:
2095         compileArithAbs(node);
2096         break;
2097
2098     case ArithMin:
2099     case ArithMax: {
2100         compileArithMinMax(node);
2101         break;
2102     }
2103
2104     case ArithSqrt:
2105         compileArithSqrt(node);
2106         break;
2107
2108     case ArithFRound:
2109         compileArithFRound(node);
2110         break;
2111
2112     case ArithRandom:
2113         compileArithRandom(node);
2114         break;
2115
2116     case ArithRound:
2117     case ArithFloor:
2118     case ArithCeil:
2119     case ArithTrunc:
2120         compileArithRounding(node);
2121         break;
2122
2123     case ArithUnary:
2124         compileArithUnary(node);
2125         break;
2126
2127     case LogicalNot:
2128         compileLogicalNot(node);
2129         break;
2130
2131     case CompareLess:
2132         if (compare(node, JITCompiler::LessThan, JITCompiler::DoubleLessThan, operationCompareLess))
2133             return;
2134         break;
2135
2136     case CompareLessEq:
2137         if (compare(node, JITCompiler::LessThanOrEqual, JITCompiler::DoubleLessThanOrEqual, operationCompareLessEq))
2138             return;
2139         break;
2140
2141     case CompareGreater:
2142         if (compare(node, JITCompiler::GreaterThan, JITCompiler::DoubleGreaterThan, operationCompareGreater))
2143             return;
2144         break;
2145
2146     case CompareGreaterEq:
2147         if (compare(node, JITCompiler::GreaterThanOrEqual, JITCompiler::DoubleGreaterThanOrEqual, operationCompareGreaterEq))
2148             return;
2149         break;
2150
2151     case CompareBelow:
2152         compileCompareUnsigned(node, JITCompiler::Below);
2153         break;
2154
2155     case CompareBelowEq:
2156         compileCompareUnsigned(node, JITCompiler::BelowOrEqual);
2157         break;
2158
2159     case CompareEq:
2160         if (compare(node, JITCompiler::Equal, JITCompiler::DoubleEqual, operationCompareEq))
2161             return;
2162         break;
2163
2164     case CompareStrictEq:
2165         if (compileStrictEq(node))
2166             return;
2167         break;
2168         
2169     case CompareEqPtr:
2170         compileCompareEqPtr(node);
2171         break;
2172
2173     case SameValue:
2174         compileSameValue(node);
2175         break;
2176
2177     case StringCharCodeAt: {
2178         compileGetCharCodeAt(node);
2179         break;
2180     }
2181
2182     case StringCharAt: {
2183         // Relies on StringCharAt node having same basic layout as GetByVal
2184         compileGetByValOnString(node);
2185         break;
2186     }
2187
2188     case StringFromCharCode: {
2189         compileFromCharCode(node);
2190         break;
2191     }
2192         
2193     case CheckArray: {
2194         checkArray(node);
2195         break;
2196     }
2197         
2198     case Arrayify:
2199     case ArrayifyToStructure: {
2200         arrayify(node);
2201         break;
2202     }
2203
2204     case GetByVal: {
2205         switch (node->arrayMode().type()) {
2206         case Array::SelectUsingPredictions:
2207         case Array::ForceExit:
2208             RELEASE_ASSERT_NOT_REACHED();
2209 #if COMPILER_QUIRK(CONSIDERS_UNREACHABLE_CODE)
2210             terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
2211 #endif
2212             break;
2213         case Array::Undecided: {
2214             SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 1));
2215             GPRTemporary resultTag(this, Reuse, index);
2216             GPRTemporary resultPayload(this);
2217
2218             GPRReg indexGPR = index.gpr();
2219             GPRReg resultTagGPR = resultTag.gpr();
2220             GPRReg resultPayloadGPR = resultPayload.gpr();
2221
2222             speculationCheck(OutOfBounds, JSValueRegs(), node,
2223                 m_jit.branch32(MacroAssembler::LessThan, indexGPR, MacroAssembler::TrustedImm32(0)));
2224
2225             use(m_graph.varArgChild(node, 0));
2226             index.use();
2227
2228             m_jit.move(MacroAssembler::TrustedImm32(JSValue::UndefinedTag), resultTagGPR);
2229             m_jit.move(MacroAssembler::TrustedImm32(0), resultPayloadGPR);
2230             jsValueResult(resultTagGPR, resultPayloadGPR, node, UseChildrenCalledExplicitly);
2231             break;
2232         }
2233         case Array::Generic: {
2234             if (m_graph.varArgChild(node, 0).useKind() == ObjectUse) {
2235                 if (m_graph.varArgChild(node, 1).useKind() == StringUse) {
2236                     compileGetByValForObjectWithString(node);
2237                     break;
2238                 }
2239
2240                 if (m_graph.varArgChild(node, 1).useKind() == SymbolUse) {
2241                     compileGetByValForObjectWithSymbol(node);
2242                     break;
2243                 }
2244             }
2245
2246             SpeculateCellOperand base(this, m_graph.varArgChild(node, 0)); // Save a register, speculate cell. We'll probably be right.
2247             JSValueOperand property(this, m_graph.varArgChild(node, 1));
2248             GPRReg baseGPR = base.gpr();
2249             JSValueRegs propertyRegs = property.jsValueRegs();
2250             
2251             flushRegisters();
2252             JSValueRegsFlushedCallResult result(this);
2253             JSValueRegs resultRegs = result.regs();
2254             callOperation(operationGetByValCell, resultRegs, baseGPR, propertyRegs);
2255             m_jit.exceptionCheck();
2256             
2257             jsValueResult(resultRegs, node);
2258             break;
2259         }
2260         case Array::Int32:
2261         case Array::Contiguous: {
2262             if (node->arrayMode().isInBounds()) {
2263                 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2264                 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2265             
2266                 GPRReg propertyReg = property.gpr();
2267                 GPRReg storageReg = storage.gpr();
2268             
2269                 if (!m_compileOkay)
2270                     return;
2271             
2272                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2273             
2274                 GPRTemporary resultPayload(this);
2275                 if (node->arrayMode().type() == Array::Int32) {
2276                     ASSERT(!node->arrayMode().isSaneChain());
2277                     
2278                     speculationCheck(
2279                         OutOfBounds, JSValueRegs(), 0,
2280                         m_jit.branch32(
2281                             MacroAssembler::Equal,
2282                             MacroAssembler::BaseIndex(
2283                                 storageReg, propertyReg, MacroAssembler::TimesEight, TagOffset),
2284                             TrustedImm32(JSValue::EmptyValueTag)));
2285                     m_jit.load32(
2286                         MacroAssembler::BaseIndex(
2287                             storageReg, propertyReg, MacroAssembler::TimesEight, PayloadOffset),
2288                         resultPayload.gpr());
2289                     int32Result(resultPayload.gpr(), node);
2290                     break;
2291                 }
2292                 
2293                 GPRTemporary resultTag(this);
2294                 m_jit.load32(
2295                     MacroAssembler::BaseIndex(
2296                         storageReg, propertyReg, MacroAssembler::TimesEight, TagOffset),
2297                     resultTag.gpr());
2298                 m_jit.load32(
2299                     MacroAssembler::BaseIndex(
2300                         storageReg, propertyReg, MacroAssembler::TimesEight, PayloadOffset),
2301                     resultPayload.gpr());
2302                 if (node->arrayMode().isSaneChain()) {
2303                     JITCompiler::Jump notHole = m_jit.branchIfNotEmpty(resultTag.gpr());
2304                     m_jit.move(TrustedImm32(JSValue::UndefinedTag), resultTag.gpr());
2305                     m_jit.move(TrustedImm32(0), resultPayload.gpr());
2306                     notHole.link(&m_jit);
2307                 } else {
2308                     speculationCheck(
2309                         LoadFromHole, JSValueRegs(), 0,
2310                         m_jit.branchIfEmpty(resultTag.gpr()));
2311                 }
2312                 jsValueResult(resultTag.gpr(), resultPayload.gpr(), node);
2313                 break;
2314             }
2315
2316             SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
2317             SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2318             StorageOperand storage(this, m_graph.varArgChild(node, 2));
2319             
2320             GPRReg baseReg = base.gpr();
2321             GPRReg propertyReg = property.gpr();
2322             GPRReg storageReg = storage.gpr();
2323             
2324             if (!m_compileOkay)
2325                 return;
2326             
2327             GPRTemporary resultTag(this);
2328             GPRTemporary resultPayload(this);
2329             GPRReg resultTagReg = resultTag.gpr();
2330             GPRReg resultPayloadReg = resultPayload.gpr();
2331             
2332             MacroAssembler::JumpList slowCases;
2333
2334             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2335             
2336             m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTagReg);
2337             m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayloadReg);
2338             slowCases.append(m_jit.branchIfEmpty(resultTagReg));
2339             
2340             addSlowPathGenerator(
2341                 slowPathCall(
2342                     slowCases, this, operationGetByValObjectInt,
2343                     JSValueRegs(resultTagReg, resultPayloadReg), baseReg, propertyReg));
2344             
2345             jsValueResult(resultTagReg, resultPayloadReg, node);
2346             break;
2347         }
2348         case Array::Double: {
2349             if (node->arrayMode().isInBounds()) {
2350                 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2351                 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2352             
2353                 GPRReg propertyReg = property.gpr();
2354                 GPRReg storageReg = storage.gpr();
2355             
2356                 if (!m_compileOkay)
2357                     return;
2358             
2359                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2360             
2361                 FPRTemporary result(this);
2362                 m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.fpr());
2363                 if (!node->arrayMode().isSaneChain())
2364                     speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchIfNaN(result.fpr()));
2365                 doubleResult(result.fpr(), node);
2366                 break;
2367             }
2368
2369             SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
2370             SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2371             StorageOperand storage(this, m_graph.varArgChild(node, 2));
2372             
2373             GPRReg baseReg = base.gpr();
2374             GPRReg propertyReg = property.gpr();
2375             GPRReg storageReg = storage.gpr();
2376             
2377             if (!m_compileOkay)
2378                 return;
2379             
2380             GPRTemporary resultTag(this);
2381             GPRTemporary resultPayload(this);
2382             FPRTemporary temp(this);
2383             GPRReg resultTagReg = resultTag.gpr();
2384             GPRReg resultPayloadReg = resultPayload.gpr();
2385             FPRReg tempReg = temp.fpr();
2386             
2387             MacroAssembler::JumpList slowCases;
2388             
2389             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2390             
2391             m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), tempReg);
2392             slowCases.append(m_jit.branchIfNaN(tempReg));
2393             boxDouble(tempReg, resultTagReg, resultPayloadReg);
2394
2395             addSlowPathGenerator(
2396                 slowPathCall(
2397                     slowCases, this, operationGetByValObjectInt,
2398                     JSValueRegs(resultTagReg, resultPayloadReg), baseReg, propertyReg));
2399             
2400             jsValueResult(resultTagReg, resultPayloadReg, node);
2401             break;
2402         }
2403         case Array::ArrayStorage:
2404         case Array::SlowPutArrayStorage: {
2405             if (node->arrayMode().isInBounds()) {
2406                 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2407                 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2408                 GPRReg propertyReg = property.gpr();
2409                 GPRReg storageReg = storage.gpr();
2410         
2411                 if (!m_compileOkay)
2412                     return;
2413
2414                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
2415
2416                 GPRTemporary resultTag(this);
2417                 GPRTemporary resultPayload(this);
2418
2419                 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag.gpr());
2420                 speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchIfEmpty(resultTag.gpr()));
2421                 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload.gpr());
2422             
2423                 jsValueResult(resultTag.gpr(), resultPayload.gpr(), node);
2424                 break;
2425             }
2426
2427             SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
2428             SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2429             StorageOperand storage(this, m_graph.varArgChild(node, 2));
2430             GPRReg propertyReg = property.gpr();
2431             GPRReg storageReg = storage.gpr();
2432             GPRReg baseReg = base.gpr();
2433
2434             if (!m_compileOkay)
2435                 return;
2436
2437             GPRTemporary resultTag(this);
2438             GPRTemporary resultPayload(this);
2439             GPRReg resultTagReg = resultTag.gpr();
2440             GPRReg resultPayloadReg = resultPayload.gpr();
2441
2442             JITCompiler::Jump outOfBounds = m_jit.branch32(
2443                 MacroAssembler::AboveOrEqual, propertyReg,
2444                 MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
2445
2446             m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTagReg);
2447             JITCompiler::Jump hole = m_jit.branchIfEmpty(resultTag.gpr());
2448             m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayloadReg);
2449             
2450             JITCompiler::JumpList slowCases;
2451             slowCases.append(outOfBounds);
2452             slowCases.append(hole);
2453             addSlowPathGenerator(
2454                 slowPathCall(
2455                     slowCases, this, operationGetByValObjectInt,
2456                     JSValueRegs(resultTagReg, resultPayloadReg),
2457                     baseReg, propertyReg));
2458
2459             jsValueResult(resultTagReg, resultPayloadReg, node);
2460             break;
2461         }
2462         case Array::String:
2463             compileGetByValOnString(node);
2464             break;
2465         case Array::DirectArguments:
2466             compileGetByValOnDirectArguments(node);
2467             break;
2468         case Array::ScopedArguments:
2469             compileGetByValOnScopedArguments(node);
2470             break;
2471         default: {
2472             TypedArrayType type = node->arrayMode().typedArrayType();
2473             if (isInt(type))
2474                 compileGetByValOnIntTypedArray(node, type);
2475             else
2476                 compileGetByValOnFloatTypedArray(node, type);
2477         } }
2478         break;
2479     }
2480     
2481     case StringSlice: {
2482         compileStringSlice(node);
2483         break;
2484     }
2485
2486     case ToLowerCase: {
2487         compileToLowerCase(node);
2488         break;
2489     }
2490
2491     case NumberToStringWithRadix: {
2492         compileNumberToStringWithRadix(node);
2493         break;
2494     }
2495
2496     case NumberToStringWithValidRadixConstant: {
2497         compileNumberToStringWithValidRadixConstant(node);
2498         break;
2499     }
2500
2501     case GetByValWithThis: {
2502         compileGetByValWithThis(node);
2503         break;
2504     }
2505
2506     case PutByValDirect:
2507     case PutByVal:
2508     case PutByValAlias: {
2509         Edge child1 = m_jit.graph().varArgChild(node, 0);
2510         Edge child2 = m_jit.graph().varArgChild(node, 1);
2511         Edge child3 = m_jit.graph().varArgChild(node, 2);
2512         Edge child4 = m_jit.graph().varArgChild(node, 3);
2513         
2514         ArrayMode arrayMode = node->arrayMode().modeForPut();
2515         bool alreadyHandled = false;
2516         
2517         switch (arrayMode.type()) {
2518         case Array::SelectUsingPredictions:
2519         case Array::ForceExit:
2520             RELEASE_ASSERT_NOT_REACHED();
2521 #if COMPILER_QUIRK(CONSIDERS_UNREACHABLE_CODE)
2522             terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
2523             alreadyHandled = true;
2524 #endif
2525             break;
2526         case Array::Generic: {
2527             ASSERT(node->op() == PutByVal || node->op() == PutByValDirect);
2528
2529             if (child1.useKind() == CellUse) {
2530                 if (child2.useKind() == StringUse) {
2531                     compilePutByValForCellWithString(node, child1, child2, child3);
2532                     alreadyHandled = true;
2533                     break;
2534                 }
2535
2536                 if (child2.useKind() == SymbolUse) {
2537                     compilePutByValForCellWithSymbol(node, child1, child2, child3);
2538                     alreadyHandled = true;
2539                     break;
2540                 }
2541             }
2542             
2543             SpeculateCellOperand base(this, child1); // Save a register, speculate cell. We'll probably be right.
2544             JSValueOperand property(this, child2);
2545             JSValueOperand value(this, child3);
2546             GPRReg baseGPR = base.gpr();
2547             JSValueRegs propertyRegs = property.jsValueRegs();
2548             JSValueRegs valueRegs = value.jsValueRegs();
2549             
2550             flushRegisters();
2551             if (node->op() == PutByValDirect)
2552                 callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByValDirectCellStrict : operationPutByValDirectCellNonStrict, baseGPR, propertyRegs, valueRegs);
2553             else
2554                 callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByValCellStrict : operationPutByValCellNonStrict, baseGPR, propertyRegs, valueRegs);
2555             m_jit.exceptionCheck();
2556             
2557             noResult(node);
2558             alreadyHandled = true;
2559             break;
2560         }
2561         default:
2562             break;
2563         }
2564         
2565         if (alreadyHandled)
2566             break;
2567         
2568         SpeculateCellOperand base(this, child1);
2569         SpeculateStrictInt32Operand property(this, child2);
2570         
2571         GPRReg baseReg = base.gpr();
2572         GPRReg propertyReg = property.gpr();
2573
2574         switch (arrayMode.type()) {
2575         case Array::Int32: {
2576             speculateInt32(child3);
2577             FALLTHROUGH;
2578         }
2579         case Array::Contiguous: {
2580             JSValueOperand value(this, child3, ManualOperandSpeculation);
2581
2582             GPRReg valueTagReg = value.tagGPR();
2583             GPRReg valuePayloadReg = value.payloadGPR();
2584         
2585             if (!m_compileOkay)
2586                 return;
2587
2588             compileContiguousPutByVal(node, base, property, value, valuePayloadReg, valueTagReg);
2589             break;
2590         }
2591         case Array::Double: {
2592             compileDoublePutByVal(node, base, property);
2593             break;
2594         }
2595         case Array::ArrayStorage:
2596         case Array::SlowPutArrayStorage: {
2597             JSValueOperand value(this, child3);
2598
2599             GPRReg valueTagReg = value.tagGPR();
2600             GPRReg valuePayloadReg = value.payloadGPR();
2601             
2602             if (!m_compileOkay)
2603                 return;
2604
2605             StorageOperand storage(this, child4);
2606             GPRReg storageReg = storage.gpr();
2607
2608             if (node->op() == PutByValAlias) {
2609                 // Store the value to the array.
2610                 GPRReg propertyReg = property.gpr();
2611                 m_jit.store32(value.tagGPR(), MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
2612                 m_jit.store32(value.payloadGPR(), MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
2613                 
2614                 noResult(node);
2615                 break;
2616             }
2617
2618             MacroAssembler::JumpList slowCases;
2619
2620             MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
2621             if (!arrayMode.isOutOfBounds())
2622                 speculationCheck(OutOfBounds, JSValueRegs(), 0, beyondArrayBounds);
2623             else
2624                 slowCases.append(beyondArrayBounds);
2625
2626             // Check if we're writing to a hole; if so increment m_numValuesInVector.
2627             if (arrayMode.isInBounds()) {
2628                 speculationCheck(
2629                     StoreToHole, JSValueRegs(), 0,
2630                     m_jit.branch32(MacroAssembler::Equal, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag)));
2631             } else {
2632                 MacroAssembler::Jump notHoleValue = m_jit.branch32(MacroAssembler::NotEqual, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag));
2633                 if (arrayMode.isSlowPut()) {
2634                     // This is sort of strange. If we wanted to optimize this code path, we would invert
2635                     // the above branch. But it's simply not worth it since this only happens if we're
2636                     // already having a bad time.
2637                     slowCases.append(m_jit.jump());
2638                 } else {
2639                     m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, ArrayStorage::numValuesInVectorOffset()));
2640                 
2641                     // If we're writing to a hole we might be growing the array; 
2642                     MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
2643                     m_jit.add32(TrustedImm32(1), propertyReg);
2644                     m_jit.store32(propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
2645                     m_jit.sub32(TrustedImm32(1), propertyReg);
2646                 
2647                     lengthDoesNotNeedUpdate.link(&m_jit);
2648                 }
2649                 notHoleValue.link(&m_jit);
2650             }
2651     
2652             // Store the value to the array.
2653             m_jit.store32(valueTagReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
2654             m_jit.store32(valuePayloadReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
2655
2656             base.use();
2657             property.use();
2658             value.use();
2659             storage.use();
2660             
2661             if (!slowCases.empty()) {
2662                 if (node->op() == PutByValDirect) {
2663                     addSlowPathGenerator(slowPathCall(
2664                         slowCases, this,
2665                         m_jit.codeBlock()->isStrictMode() ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValDirectBeyondArrayBoundsNonStrict,
2666                         NoResult, baseReg, propertyReg, JSValueRegs(valueTagReg, valuePayloadReg)));
2667                 } else {
2668                     addSlowPathGenerator(slowPathCall(
2669                         slowCases, this,
2670                         m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
2671                         NoResult, baseReg, propertyReg, JSValueRegs(valueTagReg, valuePayloadReg)));
2672                 }
2673             }
2674
2675             noResult(node, UseChildrenCalledExplicitly);
2676             break;
2677         }
2678             
2679         default: {
2680             TypedArrayType type = arrayMode.typedArrayType();
2681             if (isInt(type))
2682                 compilePutByValForIntTypedArray(base.gpr(), property.gpr(), node, type);
2683             else
2684                 compilePutByValForFloatTypedArray(base.gpr(), property.gpr(), node, type);
2685         } }
2686         break;
2687     }
2688
2689     case PutByValWithThis: {
2690 #if CPU(X86)
2691         // We don't have enough registers on X86 to do this
2692         // without setting up the call frame incrementally.
2693         unsigned index = 0;
2694         m_jit.poke(GPRInfo::callFrameRegister, index++);
2695
2696         {
2697             JSValueOperand base(this, m_jit.graph().varArgChild(node, 0));
2698             GPRReg baseTag = base.tagGPR();
2699             GPRReg basePayload = base.payloadGPR();
2700
2701             JSValueOperand thisValue(this, m_jit.graph().varArgChild(node, 1));
2702             GPRReg thisValueTag = thisValue.tagGPR();
2703             GPRReg thisValuePayload = thisValue.payloadGPR();
2704
2705             JSValueOperand property(this, m_jit.graph().varArgChild(node, 2));
2706             GPRReg propertyTag = property.tagGPR();
2707             GPRReg propertyPayload = property.payloadGPR();
2708
2709             m_jit.poke(basePayload, index++);
2710             m_jit.poke(baseTag, index++);
2711
2712             m_jit.poke(thisValuePayload, index++);
2713             m_jit.poke(thisValueTag, index++);
2714
2715             m_jit.poke(propertyPayload, index++);
2716             m_jit.poke(propertyTag, index++);
2717
2718             flushRegisters();
2719         }
2720
2721         JSValueOperand value(this, m_jit.graph().varArgChild(node, 3));
2722         GPRReg valueTag = value.tagGPR();
2723         GPRReg valuePayload = value.payloadGPR();
2724         m_jit.poke(valuePayload, index++);
2725         m_jit.poke(valueTag, index++);
2726
2727         flushRegisters();
2728         appendCall(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValWithThisStrict : operationPutByValWithThis);
2729         m_jit.exceptionCheck();
2730 #else
2731         static_assert(GPRInfo::numberOfRegisters >= 8, "We are assuming we have enough registers to make this call without incrementally setting up the arguments.");
2732
2733         JSValueOperand base(this, m_jit.graph().varArgChild(node, 0));
2734         JSValueRegs baseRegs = base.jsValueRegs();
2735
2736         JSValueOperand thisValue(this, m_jit.graph().varArgChild(node, 1));
2737         JSValueRegs thisRegs = thisValue.jsValueRegs();
2738
2739         JSValueOperand property(this, m_jit.graph().varArgChild(node, 2));
2740         JSValueRegs propertyRegs = property.jsValueRegs();
2741
2742         JSValueOperand value(this, m_jit.graph().varArgChild(node, 3));
2743         JSValueRegs valueRegs = value.jsValueRegs();
2744
2745         flushRegisters();
2746         callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValWithThisStrict : operationPutByValWithThis,
2747             NoResult, baseRegs, thisRegs, propertyRegs, valueRegs);
2748         m_jit.exceptionCheck();
2749 #endif // CPU(X86)
2750
2751         noResult(node);
2752         break;
2753     }
2754
2755     case RegExpExec: {
2756         compileRegExpExec(node);
2757         break;
2758     }
2759
2760     case RegExpExecNonGlobalOrSticky: {
2761         compileRegExpExecNonGlobalOrSticky(node);
2762         break;
2763     }
2764
2765     case RegExpMatchFastGlobal: {
2766         compileRegExpMatchFastGlobal(node);
2767         break;
2768     }
2769         
2770     case RegExpTest: {
2771         compileRegExpTest(node);
2772         break;
2773     }
2774
2775     case RegExpMatchFast: {
2776         compileRegExpMatchFast(node);
2777         break;
2778     }
2779
2780     case StringReplace:
2781     case StringReplaceRegExp: {
2782         compileStringReplace(node);
2783         break;
2784     }
2785
2786     case GetRegExpObjectLastIndex: {
2787         compileGetRegExpObjectLastIndex(node);
2788         break;
2789     }
2790         
2791     case SetRegExpObjectLastIndex: {
2792         compileSetRegExpObjectLastIndex(node);
2793         break;
2794     }
2795         
2796     case RecordRegExpCachedResult: {
2797         compileRecordRegExpCachedResult(node);
2798         break;
2799     }
2800         
2801     case ArrayPush: {
2802         compileArrayPush(node);
2803         break;
2804     }
2805         
2806     case ArrayPop: {
2807         ASSERT(node->arrayMode().isJSArray());
2808         
2809         SpeculateCellOperand base(this, node->child1());
2810         StorageOperand storage(this, node->child2());
2811         GPRTemporary valueTag(this);
2812         GPRTemporary valuePayload(this);
2813         
2814         GPRReg baseGPR = base.gpr();
2815         GPRReg valueTagGPR = valueTag.gpr();
2816         GPRReg valuePayloadGPR = valuePayload.gpr();
2817         GPRReg storageGPR = storage.gpr();
2818         
2819         switch (node->arrayMode().type()) {
2820         case Array::Int32:
2821         case Array::Contiguous: {
2822             m_jit.load32(
2823                 MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), valuePayloadGPR);
2824             MacroAssembler::Jump undefinedCase =
2825                 m_jit.branchTest32(MacroAssembler::Zero, valuePayloadGPR);
2826             m_jit.sub32(TrustedImm32(1), valuePayloadGPR);
2827             m_jit.store32(
2828                 valuePayloadGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
2829             m_jit.load32(
2830                 MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)),
2831                 valueTagGPR);
2832             MacroAssembler::Jump slowCase = m_jit.branchIfEmpty(valueTagGPR);
2833             m_jit.store32(
2834                 MacroAssembler::TrustedImm32(JSValue::EmptyValueTag),
2835                 MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
2836             m_jit.load32(
2837                 MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)),
2838                 valuePayloadGPR);
2839
2840             addSlowPathGenerator(
2841                 slowPathMove(
2842                     undefinedCase, this,
2843                     MacroAssembler::TrustedImm32(jsUndefined().tag()), valueTagGPR,
2844                     MacroAssembler::TrustedImm32(jsUndefined().payload()), valuePayloadGPR));
2845             addSlowPathGenerator(
2846                 slowPathCall(
2847                     slowCase, this, operationArrayPopAndRecoverLength,
2848                     JSValueRegs(valueTagGPR, valuePayloadGPR), baseGPR));
2849             
2850             jsValueResult(valueTagGPR, valuePayloadGPR, node);
2851             break;
2852         }
2853             
2854         case Array::Double: {
2855             FPRTemporary temp(this);
2856             FPRReg tempFPR = temp.fpr();
2857             
2858             m_jit.load32(
2859                 MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), valuePayloadGPR);
2860             MacroAssembler::Jump undefinedCase =
2861                 m_jit.branchTest32(MacroAssembler::Zero, valuePayloadGPR);
2862             m_jit.sub32(TrustedImm32(1), valuePayloadGPR);
2863             m_jit.store32(
2864                 valuePayloadGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
2865             m_jit.loadDouble(
2866                 MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight),
2867                 tempFPR);
2868             MacroAssembler::Jump slowCase = m_jit.branchIfNaN(tempFPR);
2869             JSValue nan = JSValue(JSValue::EncodeAsDouble, PNaN);
2870             m_jit.store32(
2871                 MacroAssembler::TrustedImm32(nan.u.asBits.tag),
2872                 MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
2873             m_jit.store32(
2874                 MacroAssembler::TrustedImm32(nan.u.asBits.payload),
2875                 MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
2876             boxDouble(tempFPR, valueTagGPR, valuePayloadGPR);
2877
2878             addSlowPathGenerator(
2879                 slowPathMove(
2880                     undefinedCase, this,
2881                     MacroAssembler::TrustedImm32(jsUndefined().tag()), valueTagGPR,
2882                     MacroAssembler::TrustedImm32(jsUndefined().payload()), valuePayloadGPR));
2883             addSlowPathGenerator(
2884                 slowPathCall(
2885                     slowCase, this, operationArrayPopAndRecoverLength,
2886                     JSValueRegs(valueTagGPR, valuePayloadGPR), baseGPR));
2887             
2888             jsValueResult(valueTagGPR, valuePayloadGPR, node);
2889             break;
2890         }
2891
2892         case Array::ArrayStorage: {
2893             GPRTemporary storageLength(this);
2894             GPRReg storageLengthGPR = storageLength.gpr();
2895
2896             m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
2897         
2898             JITCompiler::JumpList setUndefinedCases;
2899             setUndefinedCases.append(m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR));
2900         
2901             m_jit.sub32(TrustedImm32(1), storageLengthGPR);
2902         
2903             MacroAssembler::Jump slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset()));
2904         
2905             m_jit.load32(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), valueTagGPR);
2906             m_jit.load32(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), valuePayloadGPR);
2907         
2908             m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()));
2909
2910             setUndefinedCases.append(m_jit.branchIfEmpty(valueTagGPR));
2911         
2912             m_jit.store32(TrustedImm32(JSValue::EmptyValueTag), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
2913
2914             m_jit.sub32(TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
2915         
2916             addSlowPathGenerator(
2917                 slowPathMove(
2918                     setUndefinedCases, this,
2919                     MacroAssembler::TrustedImm32(jsUndefined().tag()), valueTagGPR,
2920                     MacroAssembler::TrustedImm32(jsUndefined().payload()), valuePayloadGPR));
2921         
2922             addSlowPathGenerator(
2923                 slowPathCall(
2924                     slowCase, this, operationArrayPop,
2925                     JSValueRegs(valueTagGPR, valuePayloadGPR), baseGPR));
2926
2927             jsValueResult(valueTagGPR, valuePayloadGPR, node);
2928             break;
2929         }
2930             
2931         default:
2932             CRASH();
2933             break;
2934         }
2935         break;
2936     }
2937
2938     case ArraySlice: {
2939         compileArraySlice(node);
2940         break;
2941     }
2942
2943     case ArrayIndexOf: {
2944         compileArrayIndexOf(node);
2945         break;
2946     }
2947
2948     case DFG::Jump: {
2949         jump(node->targetBlock());
2950         noResult(node);
2951         break;
2952     }
2953
2954     case Branch:
2955         emitBranch(node);
2956         break;
2957         
2958     case Switch:
2959         emitSwitch(node);
2960         break;
2961
2962     case Return: {
2963         ASSERT(GPRInfo::callFrameRegister != GPRInfo::regT2);
2964         ASSERT(GPRInfo::regT1 != GPRInfo::returnValueGPR);
2965         ASSERT(GPRInfo::returnValueGPR != GPRInfo::callFrameRegister);
2966
2967         // Return the result in returnValueGPR.
2968         JSValueOperand op1(this, node->child1());
2969         op1.fill();
2970         if (op1.isDouble())
2971             boxDouble(op1.fpr(), GPRInfo::returnValueGPR2, GPRInfo::returnValueGPR);
2972         else {
2973             if (op1.payloadGPR() == GPRInfo::returnValueGPR2 && op1.tagGPR() == GPRInfo::returnValueGPR)
2974                 m_jit.swap(GPRInfo::returnValueGPR, GPRInfo::returnValueGPR2);
2975             else if (op1.payloadGPR() == GPRInfo::returnValueGPR2) {
2976                 m_jit.move(op1.payloadGPR(), GPRInfo::returnValueGPR);
2977                 m_jit.move(op1.tagGPR(), GPRInfo::returnValueGPR2);
2978             } else {
2979                 m_jit.move(op1.tagGPR(), GPRInfo::returnValueGPR2);
2980                 m_jit.move(op1.payloadGPR(), GPRInfo::returnValueGPR);
2981             }
2982         }
2983
2984         m_jit.emitRestoreCalleeSaves();
2985         m_jit.emitFunctionEpilogue();
2986         m_jit.ret();
2987         
2988         noResult(node);
2989         break;
2990     }
2991         
2992     case Throw: {
2993         compileThrow(node);
2994         break;
2995     }
2996
2997     case ThrowStaticError: {
2998         compileThrowStaticError(node);
2999         break;
3000     }
3001
3002     case BooleanToNumber: {
3003         switch (node->child1().useKind()) {
3004         case BooleanUse: {
3005             SpeculateBooleanOperand value(this, node->child1());
3006             GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add).
3007             
3008             m_jit.move(value.gpr(), result.gpr());
3009
3010             int32Result(result.gpr(), node);
3011             break;
3012         }
3013             
3014         case UntypedUse: {
3015             JSValueOperand value(this, node->child1());
3016             
3017             if (!m_interpreter.needsTypeCheck(node->child1(), SpecBoolInt32 | SpecBoolean)) {
3018                 GPRTemporary result(this);
3019                 
3020                 GPRReg valueGPR = value.payloadGPR();
3021                 GPRReg resultGPR = result.gpr();
3022                 
3023                 m_jit.move(valueGPR, resultGPR);
3024                 int32Result(result.gpr(), node);
3025                 break;
3026             }
3027             
3028             GPRTemporary resultTag(this);
3029             GPRTemporary resultPayload(this);
3030             
3031             GPRReg valueTagGPR = value.tagGPR();
3032             GPRReg valuePayloadGPR = value.payloadGPR();
3033             GPRReg resultTagGPR = resultTag.gpr();
3034             GPRReg resultPayloadGPR = resultPayload.gpr();
3035             
3036             m_jit.move(valuePayloadGPR, resultPayloadGPR);
3037             JITCompiler::Jump isBoolean = m_jit.branchIfBoolean(valueTagGPR, InvalidGPRReg);
3038             m_jit.move(valueTagGPR, resultTagGPR);
3039             JITCompiler::Jump done = m_jit.jump();
3040             isBoolean.link(&m_jit);
3041             m_jit.move(TrustedImm32(JSValue::Int32Tag), resultTagGPR);
3042             done.link(&m_jit);
3043             
3044             jsValueResult(resultTagGPR, resultPayloadGPR, node);
3045             break;
3046         }
3047             
3048         default:
3049             RELEASE_ASSERT_NOT_REACHED();
3050             break;
3051         }
3052         break;
3053     }
3054         
3055     case ToPrimitive: {
3056         compileToPrimitive(node);
3057         break;
3058     }
3059
3060     case ToNumber: {
3061         JSValueOperand argument(this, node->child1());
3062         GPRTemporary resultTag(this, Reuse, argument, TagWord);
3063         GPRTemporary resultPayload(this, Reuse, argument, PayloadWord);
3064
3065         GPRReg argumentPayloadGPR = argument.payloadGPR();
3066         GPRReg argumentTagGPR = argument.tagGPR();
3067         JSValueRegs argumentRegs = argument.jsValueRegs();
3068         JSValueRegs resultRegs(resultTag.gpr(), resultPayload.gpr());
3069
3070         argument.use();
3071
3072         // We have several attempts to remove ToNumber. But ToNumber still exists.
3073         // It means that converting non-numbers to numbers by this ToNumber is not rare.
3074         // Instead of the slow path generator, we emit callOperation here.
3075         if (!(m_state.forNode(node->child1()).m_type & SpecBytecodeNumber)) {
3076             flushRegisters();
3077             callOperation(operationToNumber, resultRegs, argumentRegs);
3078             m_jit.exceptionCheck();
3079         } else {
3080             MacroAssembler::Jump notNumber;
3081             {
3082                 GPRTemporary scratch(this);
3083                 notNumber = m_jit.branchIfNotNumber(argument.jsValueRegs(), scratch.gpr());
3084             }
3085             m_jit.move(argumentTagGPR, resultRegs.tagGPR());
3086             m_jit.move(argumentPayloadGPR, resultRegs.payloadGPR());
3087             MacroAssembler::Jump done = m_jit.jump();
3088
3089             notNumber.link(&m_jit);
3090             silentSpillAllRegisters(resultRegs);
3091             callOperation(operationToNumber, resultRegs, argumentRegs);
3092             silentFillAllRegisters();
3093             m_jit.exceptionCheck();
3094
3095             done.link(&m_jit);
3096         }
3097
3098         jsValueResult(resultRegs.tagGPR(), resultRegs.payloadGPR(), node, UseChildrenCalledExplicitly);
3099         break;
3100     }
3101         
3102     case ToString:
3103     case CallStringConstructor:
3104     case StringValueOf: {
3105         compileToStringOrCallStringConstructorOrStringValueOf(node);
3106         break;
3107     }
3108         
3109     case NewStringObject: {
3110         compileNewStringObject(node);
3111         break;
3112     }
3113
3114     case NewSymbol: {
3115         compileNewSymbol(node);
3116         break;
3117     }
3118         
3119     case NewArray: {
3120         compileNewArray(node);
3121         break;
3122     }
3123
3124     case NewArrayWithSpread: {
3125         compileNewArrayWithSpread(node);
3126         break;
3127     }
3128
3129     case Spread: {
3130         compileSpread(node);
3131         break;
3132     }
3133
3134     case NewArrayWithSize: {
3135         compileNewArrayWithSize(node);
3136         break;
3137     }
3138         
3139     case NewArrayBuffer: {
3140         compileNewArrayBuffer(node);
3141         break;
3142     }
3143         
3144     case NewTypedArray: {
3145         compileNewTypedArray(node);
3146         break;
3147     }
3148         
3149     case NewRegexp: {
3150         compileNewRegexp(node);
3151         break;
3152     }
3153
3154     case ToObject:
3155     case CallObjectConstructor: {
3156         compileToObjectOrCallObjectConstructor(node);
3157         break;
3158     }
3159         
3160     case ToThis: {
3161         compileToThis(node);
3162         break;
3163     }
3164
3165     case ObjectCreate: {
3166         compileObjectCreate(node);
3167         break;
3168     }
3169
3170     case ObjectKeys: {
3171         compileObjectKeys(node);
3172         break;
3173     }
3174
3175     case CreateThis: {
3176         compileCreateThis(node);
3177         break;
3178     }
3179
3180     case NewObject: {
3181         compileNewObject(node);
3182         break;
3183     }
3184
3185     case GetCallee: {
3186         compileGetCallee(node);
3187         break;
3188     }
3189
3190     case SetCallee: {
3191         compileSetCallee(node);
3192         break;
3193     }
3194         
3195     case GetArgumentCountIncludingThis: {
3196         compileGetArgumentCountIncludingThis(node);
3197         break;
3198     }
3199
3200     case SetArgumentCountIncludingThis:
3201         compileSetArgumentCountIncludingThis(node);
3202         break;
3203         
3204     case GetScope:
3205         compileGetScope(node);
3206         break;
3207             
3208     case SkipScope:
3209         compileSkipScope(node);
3210         break;
3211         
3212     case GetGlobalObject:
3213         compileGetGlobalObject(node);
3214         break;
3215
3216     case GetGlobalThis:
3217         compileGetGlobalThis(node);
3218         break;
3219         
3220     case GetClosureVar: {
3221         compileGetClosureVar(node);
3222         break;
3223     }
3224     
3225     case PutClosureVar: {
3226         compilePutClosureVar(node);
3227         break;
3228     }
3229
3230     case TryGetById: {
3231         compileGetById(node, AccessType::TryGet);
3232         break;
3233     }
3234
3235     case GetByIdDirect: {
3236         compileGetById(node, AccessType::GetDirect);
3237         break;
3238     }
3239
3240     case GetByIdDirectFlush: {
3241         compileGetByIdFlush(node, AccessType::GetDirect);
3242         break;
3243     }
3244
3245     case GetById: {
3246         compileGetById(node, AccessType::Get);
3247         break;
3248     }
3249
3250     case GetByIdFlush: {
3251         compileGetByIdFlush(node, AccessType::Get);
3252         break;
3253     }
3254
3255     case GetByIdWithThis: {
3256         if (node->child1().useKind() == CellUse && node->child2().useKind() == CellUse) {
3257             SpeculateCellOperand base(this, node->child1());
3258             SpeculateCellOperand thisValue(this, node->child2());
3259             GPRTemporary resultTag(this);
3260             GPRTemporary resultPayload(this);
3261             
3262             GPRReg baseGPR = base.gpr();
3263             GPRReg thisGPR = thisValue.gpr();
3264             GPRReg resultTagGPR = resultTag.gpr();
3265             GPRReg resultPayloadGPR = resultPayload.gpr();
3266             
3267             cachedGetByIdWithThis(node->origin.semantic, InvalidGPRReg, baseGPR, InvalidGPRReg, thisGPR, resultTagGPR, resultPayloadGPR, node->identifierNumber());
3268             
3269             jsValueResult(resultTagGPR, resultPayloadGPR, node);
3270         } else {
3271             JSValueOperand base(this, node->child1());
3272             JSValueOperand thisValue(this, node->child2());
3273             GPRTemporary resultTag(this);
3274             GPRTemporary resultPayload(this);
3275             
3276             GPRReg baseTagGPR = base.tagGPR();
3277             GPRReg basePayloadGPR = base.payloadGPR();
3278             GPRReg thisTagGPR = thisValue.tagGPR();
3279             GPRReg thisPayloadGPR = thisValue.payloadGPR();
3280             GPRReg resultTagGPR = resultTag.gpr();
3281             GPRReg resultPayloadGPR = resultPayload.gpr();
3282             
3283             JITCompiler::JumpList notCellList;
3284             notCellList.append(m_jit.branchIfNotCell(base.jsValueRegs()));
3285             notCellList.append(m_jit.branchIfNotCell(thisValue.jsValueRegs()));
3286             
3287             cachedGetByIdWithThis(node->origin.semantic, baseTagGPR, basePayloadGPR, thisTagGPR, thisPayloadGPR, resultTagGPR, resultPayloadGPR, node->identifierNumber(), notCellList);
3288             
3289             jsValueResult(resultTagGPR, resultPayloadGPR, node);
3290         }
3291         
3292         break;
3293     }
3294
3295     case GetArrayLength:
3296         compileGetArrayLength(node);
3297         break;
3298
3299     case DeleteById: {
3300         compileDeleteById(node);
3301         break;
3302     }
3303
3304     case DeleteByVal: {
3305         compileDeleteByVal(node);
3306         break;
3307     }
3308         
3309     case CheckCell: {
3310         compileCheckCell(node);
3311         break;
3312     }
3313
3314     case CheckNotEmpty: {
3315         compileCheckNotEmpty(node);
3316         break;
3317     }
3318
3319     case CheckStringIdent:
3320         compileCheckStringIdent(node);
3321         break;
3322
3323     case GetExecutable: {
3324         compileGetExecutable(node);
3325         break;
3326     }
3327         
3328     case CheckStructure: {
3329         compileCheckStructure(node);
3330         break;
3331     }
3332         
3333     case PutStructure: {
3334         RegisteredStructure oldStructure = node->transition()->previous;
3335         RegisteredStructure newStructure = node->transition()->next;
3336
3337         m_jit.jitCode()->common.notifyCompilingStructureTransition(m_jit.graph().m_plan, m_jit.codeBlock(), node);
3338
3339         SpeculateCellOperand base(this, node->child1());
3340         GPRReg baseGPR = base.gpr();
3341         
3342         ASSERT_UNUSED(oldStructure, oldStructure->indexingMode() == newStructure->indexingMode());
3343         ASSERT(oldStructure->typeInfo().type() == newStructure->typeInfo().type());
3344         ASSERT(oldStructure->typeInfo().inlineTypeFlags() == newStructure->typeInfo().inlineTypeFlags());
3345         m_jit.storePtr(TrustedImmPtr(newStructure), MacroAssembler::Address(baseGPR, JSCell::structureIDOffset()));
3346         
3347         noResult(node);
3348         break;
3349     }
3350         
3351     case AllocatePropertyStorage:
3352         compileAllocatePropertyStorage(node);
3353         break;
3354         
3355     case ReallocatePropertyStorage:
3356         compileReallocatePropertyStorage(node);
3357         break;
3358         
3359     case NukeStructureAndSetButterfly:
3360         compileNukeStructureAndSetButterfly(node);
3361         break;
3362         
3363     case GetButterfly:
3364         compileGetButterfly(node);
3365         break;
3366
3367     case GetIndexedPropertyStorage: {
3368         compileGetIndexedPropertyStorage(node);
3369         break;
3370     }
3371
3372     case ConstantStoragePointer: {
3373         compileConstantStoragePointer(node);
3374         break;
3375     }
3376         
3377     case GetTypedArrayByteOffset: {
3378         compileGetTypedArrayByteOffset(node);
3379         break;
3380     }
3381
3382     case GetPrototypeOf: {
3383         compileGetPrototypeOf(node);
3384         break;
3385     }
3386         
3387     case GetByOffset: {
3388         compileGetByOffset(node);
3389         break;
3390     }
3391         
3392     case GetGetterSetterByOffset: {
3393         StorageOperand storage(this, node->child1());
3394         GPRTemporary resultPayload(this);
3395         
3396         GPRReg storageGPR = storage.gpr();
3397         GPRReg resultPayloadGPR = resultPayload.gpr();
3398         
3399         StorageAccessData& storageAccessData = node->storageAccessData();
3400         
3401         m_jit.load32(JITCompiler::Address(storageGPR, offsetRelativeToBase(storageAccessData.offset) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), resultPayloadGPR);
3402         
3403         cellResult(resultPayloadGPR, node);
3404         break;
3405     }
3406         
3407     case MatchStructure: {
3408         compileMatchStructure(node);
3409         break;
3410     }
3411         
3412     case GetGetter: {
3413         compileGetGetter(node);
3414         break;
3415     }
3416         
3417     case GetSetter: {
3418         compileGetSetter(node);
3419         break;
3420     }
3421         
3422     case PutByOffset: {
3423         compilePutByOffset(node);
3424         break;
3425     }
3426
3427     case PutByIdFlush: {
3428         compilePutByIdFlush(node);
3429         break;
3430     }
3431
3432     case PutById: {
3433         compilePutById(node);
3434         break;
3435     }
3436
3437     case PutByIdDirect: {
3438         compilePutByIdDirect(node);
3439         break;
3440     }
3441
3442     case PutByIdWithThis: {
3443         compilePutByIdWithThis(node);
3444         break;
3445     }
3446
3447     case PutGetterById:
3448     case PutSetterById: {
3449         compilePutAccessorById(node);
3450         break;
3451     }
3452
3453     case PutGetterSetterById: {
3454         compilePutGetterSetterById(node);
3455         break;
3456     }
3457
3458     case PutGetterByVal:
3459     case PutSetterByVal: {
3460         compilePutAccessorByVal(node);
3461         break;
3462     }
3463
3464     case DefineDataProperty: {
3465         compileDefineDataProperty(node);
3466         break;
3467     }
3468
3469     case DefineAccessorProperty: {
3470         compileDefineAccessorProperty(node);
3471         break;
3472     }
3473
3474     case GetGlobalLexicalVariable:
3475     case GetGlobalVar: {
3476         compileGetGlobalVariable(node);
3477         break;
3478     }
3479
3480     case PutGlobalVariable: {
3481         compilePutGlobalVariable(node);
3482         break;
3483     }
3484
3485     case NotifyWrite: {
3486         compileNotifyWrite(node);
3487         break;
3488     }
3489
3490     case ParseInt: {
3491         compileParseInt(node);
3492         break;
3493     }
3494
3495     case CheckTypeInfoFlags: {
3496         compileCheckTypeInfoFlags(node);
3497         break;
3498     }
3499
3500     case OverridesHasInstance: {
3501         compileOverridesHasInstance(node);
3502         break;
3503     }
3504
3505     case InstanceOf: {
3506         compileInstanceOf(node);
3507         break;
3508     }
3509
3510     case InstanceOfCustom: {
3511         compileInstanceOfCustom(node);
3512         break;
3513     }
3514
3515     case IsEmpty: {        
3516         JSValueOperand value(this, node->child1());
3517         GPRTemporary result(this, Reuse, value, TagWord);
3518         m_jit.comparePtr(JITCompiler::Equal, value.tagGPR(), TrustedImm32(JSValue::EmptyValueTag), result.gpr());
3519         booleanResult(result.gpr(), node);
3520         break;
3521     }
3522
3523     case IsUndefined: {
3524         JSValueOperand value(this, node->child1());
3525         GPRTemporary result(this);
3526         GPRTemporary localGlobalObject(this);
3527         GPRTemporary remoteGlobalObject(this);
3528
3529         JITCompiler::Jump isCell = m_jit.branchIfCell(value.jsValueRegs());
3530         
3531         m_jit.compare32(JITCompiler::Equal, value.tagGPR(), TrustedImm32(JSValue::UndefinedTag), result.gpr());
3532         JITCompiler::Jump done = m_jit.jump();
3533         
3534         isCell.link(&m_jit);
3535         JITCompiler::Jump notMasqueradesAsUndefined;
3536         if (masqueradesAsUndefinedWatchpointIsStillValid()) {
3537             m_jit.move(TrustedImm32(0), result.gpr());
3538             notMasqueradesAsUndefined = m_jit.jump();
3539         } else {
3540             JITCompiler::Jump isMasqueradesAsUndefined = m_jit.branchTest8(
3541                 JITCompiler::NonZero, 
3542                 JITCompiler::Address(value.payloadGPR(), JSCell::typeInfoFlagsOffset()), 
3543                 TrustedImm32(MasqueradesAsUndefined));
3544             m_jit.move(TrustedImm32(0), result.gpr());
3545             notMasqueradesAsUndefined = m_jit.jump();
3546             
3547             isMasqueradesAsUndefined.link(&m_jit);
3548             GPRReg localGlobalObjectGPR = localGlobalObject.gpr();
3549             GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr();
3550             m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.globalObjectFor(node->origin.semantic)), localGlobalObjectGPR);
3551             m_jit.loadPtr(JITCompiler::Address(value.payloadGPR(), JSCell::structureIDOffset()), result.gpr());
3552             m_jit.loadPtr(JITCompiler::Address(result.gpr(), Structure::globalObjectOffset()), remoteGlobalObjectGPR); 
3553             m_jit.compare32(JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, result.gpr());
3554         }
3555
3556         notMasqueradesAsUndefined.link(&m_jit);
3557         done.link(&m_jit);
3558         booleanResult(result.gpr(), node);
3559         break;
3560     }
3561
3562     case IsUndefinedOrNull: {
3563         JSValueOperand value(this, node->child1());
3564         GPRTemporary result(this, Reuse, value, TagWord);
3565
3566         GPRReg valueTagGPR = value.tagGPR();
3567         GPRReg resultGPR = result.gpr();
3568
3569         m_jit.move(valueTagGPR, resultGPR);
3570         static_assert((JSValue::UndefinedTag + 1 == JSValue::NullTag) && (JSValue::NullTag & 0x1), "");
3571         m_jit.or32(CCallHelpers::TrustedImm32(1), resultGPR);
3572         m_jit.compare32(CCallHelpers::Equal, resultGPR, CCallHelpers::TrustedImm32(JSValue::NullTag), resultGPR);
3573
3574         booleanResult(resultGPR, node);
3575         break;
3576     }
3577
3578
3579     case IsBoolean: {
3580         JSValueOperand value(this, node->child1());
3581         GPRTemporary result(this, Reuse, value, TagWord);
3582         
3583         m_jit.compare32(JITCompiler::Equal, value.tagGPR(), JITCompiler::TrustedImm32(JSValue::BooleanTag), result.gpr());
3584         booleanResult(result.gpr(), node);
3585         break;
3586     }
3587
3588     case IsNumber: {
3589         JSValueOperand value(this, node->child1());
3590         GPRTemporary result(this, Reuse, value, TagWord);
3591         
3592         m_jit.add32(TrustedImm32(1), value.tagGPR(), result.gpr());
3593         m_jit.compare32(JITCompiler::Below, result.gpr(), JITCompiler::TrustedImm32(JSValue::LowestTag + 1), result.gpr());
3594         booleanResult(result.gpr(), node);
3595         break;
3596     }
3597
3598     case NumberIsInteger: {
3599         JSValueOperand input(this, node->child1());
3600         JSValueRegs inputRegs = input.jsValueRegs();
3601         flushRegisters();
3602         GPRFlushedCallResult result(this);
3603         GPRReg resultGPR = result.gpr();
3604         callOperation(operationNumberIsInteger, resultGPR, inputRegs);
3605         booleanResult(resultGPR, node);
3606         break;
3607     }
3608
3609     case IsObject: {
3610         compileIsObject(node);
3611         break;
3612     }
3613
3614     case IsObjectOrNull: {
3615         compileIsObjectOrNull(node);
3616         break;
3617     }
3618
3619     case IsFunction: {
3620         compileIsFunction(node);
3621         break;
3622     }
3623
3624     case IsCellWithType: {
3625         compileIsCellWithType(node);
3626         break;
3627     }
3628
3629     case IsTypedArrayView: {
3630         compileIsTypedArrayView(node);
3631         break;
3632     }
3633
3634     case TypeOf: {
3635         compileTypeOf(node);
3636         break;
3637     }
3638
3639     case MapHash: {
3640         JSValueOperand input(this, node->child1());
3641
3642         JSValueRegs inputRegs = input.jsValueRegs();
3643
3644         flushRegisters();
3645         GPRFlushedCallResult result(this);
3646         GPRReg resultGPR = result.gpr();
3647         callOperation(operationMapHash, resultGPR, inputRegs);
3648         m_jit.exceptionCheck();
3649         int32Result(resultGPR, node);
3650         break;
3651     }
3652
3653     case NormalizeMapKey: {
3654         compileNormalizeMapKey(node);
3655         break;
3656     }
3657
3658     case GetMapBucket: {
3659         SpeculateCellOperand map(this, node->child1());
3660         JSValueOperand key(this, node->child2());
3661         SpeculateInt32Operand hash(this, node->child3());
3662
3663         GPRReg mapGPR = map.gpr();
3664         JSValueRegs keyRegs = key.jsValueRegs();
3665         GPRReg hashGPR = hash.gpr();
3666
3667         if (node->child1().useKind() == MapObjectUse)
3668             speculateMapObject(node->child1(), mapGPR);
3669         else if (node->child1().useKind() == SetObjectUse)
3670             speculateSetObject(node->child1(), mapGPR);
3671         else
3672             RELEASE_ASSERT_NOT_REACHED();
3673
3674         flushRegisters();
3675         GPRFlushedCallResult result(this);
3676         GPRReg resultGPR = result.gpr();
3677         if (node->child1().useKind() == MapObjectUse)
3678             callOperation(operationJSMapFindBucket, resultGPR, mapGPR, keyRegs, hashGPR);
3679         else
3680             callOperation(operationJSSetFindBucket, resultGPR, mapGPR, keyRegs, hashGPR);
3681         m_jit.exceptionCheck();
3682         cellResult(resultGPR, node);
3683         break;
3684     }
3685
3686     case GetMapBucketHead:
3687         compileGetMapBucketHead(node);
3688         break;
3689
3690     case GetMapBucketNext:
3691         compileGetMapBucketNext(node);
3692         break;
3693
3694     case LoadKeyFromMapBucket:
3695         compileLoadKeyFromMapBucket(node);
3696         break;
3697
3698     case LoadValueFromMapBucket:
3699         compileLoadValueFromMapBucket(node);
3700         break;
3701
3702     case ExtractValueFromWeakMapGet:
3703         compileExtractValueFromWeakMapGet(node);
3704         break;
3705
3706     case SetAdd: