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