3efb7b7e45081e68e5ad8a0e4c5bdb2a418ad36b
[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         m_jit.emitConvertValueToBoolean(*m_jit.vm(), valueRegs, resultGPR, temp.gpr(), valueFPR.fpr(), tempFPR.fpr(), shouldCheckMasqueradesAsUndefined, globalObject);
1717         branchTest32(JITCompiler::Zero, resultGPR, 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 ValueAdd:
2019         compileValueAdd(node);
2020         break;
2021
2022     case StrCat: {
2023         compileStrCat(node);
2024         break;
2025     }
2026
2027     case ArithAdd:
2028         compileArithAdd(node);
2029         break;
2030
2031     case ArithClz32:
2032         compileArithClz32(node);
2033         break;
2034
2035     case MakeRope:
2036         compileMakeRope(node);
2037         break;
2038
2039     case ArithSub:
2040         compileArithSub(node);
2041         break;
2042
2043     case ArithNegate:
2044         compileArithNegate(node);
2045         break;
2046
2047     case ArithMul:
2048         compileArithMul(node);
2049         break;
2050
2051     case ArithDiv: {
2052         compileArithDiv(node);
2053         break;
2054     }
2055
2056     case ArithMod: {
2057         compileArithMod(node);
2058         break;
2059     }
2060
2061     case ArithPow: {
2062         compileArithPow(node);
2063         break;
2064     }
2065
2066     case ArithAbs:
2067         compileArithAbs(node);
2068         break;
2069
2070     case ArithMin:
2071     case ArithMax: {
2072         compileArithMinMax(node);
2073         break;
2074     }
2075
2076     case ArithSqrt:
2077         compileArithSqrt(node);
2078         break;
2079
2080     case ArithFRound:
2081         compileArithFRound(node);
2082         break;
2083
2084     case ArithRandom:
2085         compileArithRandom(node);
2086         break;
2087
2088     case ArithRound:
2089     case ArithFloor:
2090     case ArithCeil:
2091     case ArithTrunc:
2092         compileArithRounding(node);
2093         break;
2094
2095     case ArithUnary:
2096         compileArithUnary(node);
2097         break;
2098
2099     case LogicalNot:
2100         compileLogicalNot(node);
2101         break;
2102
2103     case CompareLess:
2104         if (compare(node, JITCompiler::LessThan, JITCompiler::DoubleLessThan, operationCompareLess))
2105             return;
2106         break;
2107
2108     case CompareLessEq:
2109         if (compare(node, JITCompiler::LessThanOrEqual, JITCompiler::DoubleLessThanOrEqual, operationCompareLessEq))
2110             return;
2111         break;
2112
2113     case CompareGreater:
2114         if (compare(node, JITCompiler::GreaterThan, JITCompiler::DoubleGreaterThan, operationCompareGreater))
2115             return;
2116         break;
2117
2118     case CompareGreaterEq:
2119         if (compare(node, JITCompiler::GreaterThanOrEqual, JITCompiler::DoubleGreaterThanOrEqual, operationCompareGreaterEq))
2120             return;
2121         break;
2122
2123     case CompareBelow:
2124         compileCompareUnsigned(node, JITCompiler::Below);
2125         break;
2126
2127     case CompareBelowEq:
2128         compileCompareUnsigned(node, JITCompiler::BelowOrEqual);
2129         break;
2130
2131     case CompareEq:
2132         if (compare(node, JITCompiler::Equal, JITCompiler::DoubleEqual, operationCompareEq))
2133             return;
2134         break;
2135
2136     case CompareStrictEq:
2137         if (compileStrictEq(node))
2138             return;
2139         break;
2140         
2141     case CompareEqPtr:
2142         compileCompareEqPtr(node);
2143         break;
2144
2145     case SameValue:
2146         compileSameValue(node);
2147         break;
2148
2149     case StringCharCodeAt: {
2150         compileGetCharCodeAt(node);
2151         break;
2152     }
2153
2154     case StringCharAt: {
2155         // Relies on StringCharAt node having same basic layout as GetByVal
2156         compileGetByValOnString(node);
2157         break;
2158     }
2159
2160     case StringFromCharCode: {
2161         compileFromCharCode(node);
2162         break;
2163     }
2164         
2165     case CheckArray: {
2166         checkArray(node);
2167         break;
2168     }
2169         
2170     case Arrayify:
2171     case ArrayifyToStructure: {
2172         arrayify(node);
2173         break;
2174     }
2175
2176     case GetByVal: {
2177         switch (node->arrayMode().type()) {
2178         case Array::SelectUsingPredictions:
2179         case Array::ForceExit:
2180             RELEASE_ASSERT_NOT_REACHED();
2181 #if COMPILER_QUIRK(CONSIDERS_UNREACHABLE_CODE)
2182             terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
2183 #endif
2184             break;
2185         case Array::Undecided: {
2186             SpeculateStrictInt32Operand index(this, m_graph.varArgChild(node, 1));
2187             GPRTemporary resultTag(this, Reuse, index);
2188             GPRTemporary resultPayload(this);
2189
2190             GPRReg indexGPR = index.gpr();
2191             GPRReg resultTagGPR = resultTag.gpr();
2192             GPRReg resultPayloadGPR = resultPayload.gpr();
2193
2194             speculationCheck(OutOfBounds, JSValueRegs(), node,
2195                 m_jit.branch32(MacroAssembler::LessThan, indexGPR, MacroAssembler::TrustedImm32(0)));
2196
2197             use(m_graph.varArgChild(node, 0));
2198             index.use();
2199
2200             m_jit.move(MacroAssembler::TrustedImm32(JSValue::UndefinedTag), resultTagGPR);
2201             m_jit.move(MacroAssembler::TrustedImm32(0), resultPayloadGPR);
2202             jsValueResult(resultTagGPR, resultPayloadGPR, node, UseChildrenCalledExplicitly);
2203             break;
2204         }
2205         case Array::Generic: {
2206             if (m_graph.varArgChild(node, 0).useKind() == ObjectUse) {
2207                 if (m_graph.varArgChild(node, 1).useKind() == StringUse) {
2208                     compileGetByValForObjectWithString(node);
2209                     break;
2210                 }
2211
2212                 if (m_graph.varArgChild(node, 1).useKind() == SymbolUse) {
2213                     compileGetByValForObjectWithSymbol(node);
2214                     break;
2215                 }
2216             }
2217
2218             SpeculateCellOperand base(this, m_graph.varArgChild(node, 0)); // Save a register, speculate cell. We'll probably be right.
2219             JSValueOperand property(this, m_graph.varArgChild(node, 1));
2220             GPRReg baseGPR = base.gpr();
2221             JSValueRegs propertyRegs = property.jsValueRegs();
2222             
2223             flushRegisters();
2224             JSValueRegsFlushedCallResult result(this);
2225             JSValueRegs resultRegs = result.regs();
2226             callOperation(operationGetByValCell, resultRegs, baseGPR, propertyRegs);
2227             m_jit.exceptionCheck();
2228             
2229             jsValueResult(resultRegs, node);
2230             break;
2231         }
2232         case Array::Int32:
2233         case Array::Contiguous: {
2234             if (node->arrayMode().isInBounds()) {
2235                 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2236                 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2237             
2238                 GPRReg propertyReg = property.gpr();
2239                 GPRReg storageReg = storage.gpr();
2240             
2241                 if (!m_compileOkay)
2242                     return;
2243             
2244                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2245             
2246                 GPRTemporary resultPayload(this);
2247                 if (node->arrayMode().type() == Array::Int32) {
2248                     ASSERT(!node->arrayMode().isSaneChain());
2249                     
2250                     speculationCheck(
2251                         OutOfBounds, JSValueRegs(), 0,
2252                         m_jit.branch32(
2253                             MacroAssembler::Equal,
2254                             MacroAssembler::BaseIndex(
2255                                 storageReg, propertyReg, MacroAssembler::TimesEight, TagOffset),
2256                             TrustedImm32(JSValue::EmptyValueTag)));
2257                     m_jit.load32(
2258                         MacroAssembler::BaseIndex(
2259                             storageReg, propertyReg, MacroAssembler::TimesEight, PayloadOffset),
2260                         resultPayload.gpr());
2261                     int32Result(resultPayload.gpr(), node);
2262                     break;
2263                 }
2264                 
2265                 GPRTemporary resultTag(this);
2266                 m_jit.load32(
2267                     MacroAssembler::BaseIndex(
2268                         storageReg, propertyReg, MacroAssembler::TimesEight, TagOffset),
2269                     resultTag.gpr());
2270                 m_jit.load32(
2271                     MacroAssembler::BaseIndex(
2272                         storageReg, propertyReg, MacroAssembler::TimesEight, PayloadOffset),
2273                     resultPayload.gpr());
2274                 if (node->arrayMode().isSaneChain()) {
2275                     JITCompiler::Jump notHole = m_jit.branchIfNotEmpty(resultTag.gpr());
2276                     m_jit.move(TrustedImm32(JSValue::UndefinedTag), resultTag.gpr());
2277                     m_jit.move(TrustedImm32(0), resultPayload.gpr());
2278                     notHole.link(&m_jit);
2279                 } else {
2280                     speculationCheck(
2281                         LoadFromHole, JSValueRegs(), 0,
2282                         m_jit.branchIfEmpty(resultTag.gpr()));
2283                 }
2284                 jsValueResult(resultTag.gpr(), resultPayload.gpr(), node);
2285                 break;
2286             }
2287
2288             SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
2289             SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2290             StorageOperand storage(this, m_graph.varArgChild(node, 2));
2291             
2292             GPRReg baseReg = base.gpr();
2293             GPRReg propertyReg = property.gpr();
2294             GPRReg storageReg = storage.gpr();
2295             
2296             if (!m_compileOkay)
2297                 return;
2298             
2299             GPRTemporary resultTag(this);
2300             GPRTemporary resultPayload(this);
2301             GPRReg resultTagReg = resultTag.gpr();
2302             GPRReg resultPayloadReg = resultPayload.gpr();
2303             
2304             MacroAssembler::JumpList slowCases;
2305
2306             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2307             
2308             m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTagReg);
2309             m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayloadReg);
2310             slowCases.append(m_jit.branchIfEmpty(resultTagReg));
2311             
2312             addSlowPathGenerator(
2313                 slowPathCall(
2314                     slowCases, this, operationGetByValObjectInt,
2315                     JSValueRegs(resultTagReg, resultPayloadReg), baseReg, propertyReg));
2316             
2317             jsValueResult(resultTagReg, resultPayloadReg, node);
2318             break;
2319         }
2320         case Array::Double: {
2321             if (node->arrayMode().isInBounds()) {
2322                 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2323                 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2324             
2325                 GPRReg propertyReg = property.gpr();
2326                 GPRReg storageReg = storage.gpr();
2327             
2328                 if (!m_compileOkay)
2329                     return;
2330             
2331                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2332             
2333                 FPRTemporary result(this);
2334                 m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.fpr());
2335                 if (!node->arrayMode().isSaneChain())
2336                     speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, result.fpr(), result.fpr()));
2337                 doubleResult(result.fpr(), node);
2338                 break;
2339             }
2340
2341             SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
2342             SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2343             StorageOperand storage(this, m_graph.varArgChild(node, 2));
2344             
2345             GPRReg baseReg = base.gpr();
2346             GPRReg propertyReg = property.gpr();
2347             GPRReg storageReg = storage.gpr();
2348             
2349             if (!m_compileOkay)
2350                 return;
2351             
2352             GPRTemporary resultTag(this);
2353             GPRTemporary resultPayload(this);
2354             FPRTemporary temp(this);
2355             GPRReg resultTagReg = resultTag.gpr();
2356             GPRReg resultPayloadReg = resultPayload.gpr();
2357             FPRReg tempReg = temp.fpr();
2358             
2359             MacroAssembler::JumpList slowCases;
2360             
2361             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2362             
2363             m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), tempReg);
2364             slowCases.append(m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, tempReg, tempReg));
2365             boxDouble(tempReg, resultTagReg, resultPayloadReg);
2366
2367             addSlowPathGenerator(
2368                 slowPathCall(
2369                     slowCases, this, operationGetByValObjectInt,
2370                     JSValueRegs(resultTagReg, resultPayloadReg), baseReg, propertyReg));
2371             
2372             jsValueResult(resultTagReg, resultPayloadReg, node);
2373             break;
2374         }
2375         case Array::ArrayStorage:
2376         case Array::SlowPutArrayStorage: {
2377             if (node->arrayMode().isInBounds()) {
2378                 SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2379                 StorageOperand storage(this, m_graph.varArgChild(node, 2));
2380                 GPRReg propertyReg = property.gpr();
2381                 GPRReg storageReg = storage.gpr();
2382         
2383                 if (!m_compileOkay)
2384                     return;
2385
2386                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
2387
2388                 GPRTemporary resultTag(this);
2389                 GPRTemporary resultPayload(this);
2390
2391                 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag.gpr());
2392                 speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchIfEmpty(resultTag.gpr()));
2393                 m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload.gpr());
2394             
2395                 jsValueResult(resultTag.gpr(), resultPayload.gpr(), node);
2396                 break;
2397             }
2398
2399             SpeculateCellOperand base(this, m_graph.varArgChild(node, 0));
2400             SpeculateStrictInt32Operand property(this, m_graph.varArgChild(node, 1));
2401             StorageOperand storage(this, m_graph.varArgChild(node, 2));
2402             GPRReg propertyReg = property.gpr();
2403             GPRReg storageReg = storage.gpr();
2404             GPRReg baseReg = base.gpr();
2405
2406             if (!m_compileOkay)
2407                 return;
2408
2409             GPRTemporary resultTag(this);
2410             GPRTemporary resultPayload(this);
2411             GPRReg resultTagReg = resultTag.gpr();
2412             GPRReg resultPayloadReg = resultPayload.gpr();
2413
2414             JITCompiler::Jump outOfBounds = m_jit.branch32(
2415                 MacroAssembler::AboveOrEqual, propertyReg,
2416                 MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
2417
2418             m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTagReg);
2419             JITCompiler::Jump hole = m_jit.branchIfEmpty(resultTag.gpr());
2420             m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayloadReg);
2421             
2422             JITCompiler::JumpList slowCases;
2423             slowCases.append(outOfBounds);
2424             slowCases.append(hole);
2425             addSlowPathGenerator(
2426                 slowPathCall(
2427                     slowCases, this, operationGetByValObjectInt,
2428                     JSValueRegs(resultTagReg, resultPayloadReg),
2429                     baseReg, propertyReg));
2430
2431             jsValueResult(resultTagReg, resultPayloadReg, node);
2432             break;
2433         }
2434         case Array::String:
2435             compileGetByValOnString(node);
2436             break;
2437         case Array::DirectArguments:
2438             compileGetByValOnDirectArguments(node);
2439             break;
2440         case Array::ScopedArguments:
2441             compileGetByValOnScopedArguments(node);
2442             break;
2443         default: {
2444             TypedArrayType type = node->arrayMode().typedArrayType();
2445             if (isInt(type))
2446                 compileGetByValOnIntTypedArray(node, type);
2447             else
2448                 compileGetByValOnFloatTypedArray(node, type);
2449         } }
2450         break;
2451     }
2452     
2453     case StringSlice: {
2454         compileStringSlice(node);
2455         break;
2456     }
2457
2458     case ToLowerCase: {
2459         compileToLowerCase(node);
2460         break;
2461     }
2462
2463     case NumberToStringWithRadix: {
2464         compileNumberToStringWithRadix(node);
2465         break;
2466     }
2467
2468     case NumberToStringWithValidRadixConstant: {
2469         compileNumberToStringWithValidRadixConstant(node);
2470         break;
2471     }
2472
2473     case GetByValWithThis: {
2474         compileGetByValWithThis(node);
2475         break;
2476     }
2477
2478     case PutByValDirect:
2479     case PutByVal:
2480     case PutByValAlias: {
2481         Edge child1 = m_jit.graph().varArgChild(node, 0);
2482         Edge child2 = m_jit.graph().varArgChild(node, 1);
2483         Edge child3 = m_jit.graph().varArgChild(node, 2);
2484         Edge child4 = m_jit.graph().varArgChild(node, 3);
2485         
2486         ArrayMode arrayMode = node->arrayMode().modeForPut();
2487         bool alreadyHandled = false;
2488         
2489         switch (arrayMode.type()) {
2490         case Array::SelectUsingPredictions:
2491         case Array::ForceExit:
2492             RELEASE_ASSERT_NOT_REACHED();
2493 #if COMPILER_QUIRK(CONSIDERS_UNREACHABLE_CODE)
2494             terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
2495             alreadyHandled = true;
2496 #endif
2497             break;
2498         case Array::Generic: {
2499             ASSERT(node->op() == PutByVal || node->op() == PutByValDirect);
2500
2501             if (child1.useKind() == CellUse) {
2502                 if (child2.useKind() == StringUse) {
2503                     compilePutByValForCellWithString(node, child1, child2, child3);
2504                     alreadyHandled = true;
2505                     break;
2506                 }
2507
2508                 if (child2.useKind() == SymbolUse) {
2509                     compilePutByValForCellWithSymbol(node, child1, child2, child3);
2510                     alreadyHandled = true;
2511                     break;
2512                 }
2513             }
2514             
2515             SpeculateCellOperand base(this, child1); // Save a register, speculate cell. We'll probably be right.
2516             JSValueOperand property(this, child2);
2517             JSValueOperand value(this, child3);
2518             GPRReg baseGPR = base.gpr();
2519             JSValueRegs propertyRegs = property.jsValueRegs();
2520             JSValueRegs valueRegs = value.jsValueRegs();
2521             
2522             flushRegisters();
2523             if (node->op() == PutByValDirect)
2524                 callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByValDirectCellStrict : operationPutByValDirectCellNonStrict, baseGPR, propertyRegs, valueRegs);
2525             else
2526                 callOperation(m_jit.codeBlock()->isStrictMode() ? operationPutByValCellStrict : operationPutByValCellNonStrict, baseGPR, propertyRegs, valueRegs);
2527             m_jit.exceptionCheck();
2528             
2529             noResult(node);
2530             alreadyHandled = true;
2531             break;
2532         }
2533         default:
2534             break;
2535         }
2536         
2537         if (alreadyHandled)
2538             break;
2539         
2540         SpeculateCellOperand base(this, child1);
2541         SpeculateStrictInt32Operand property(this, child2);
2542         
2543         GPRReg baseReg = base.gpr();
2544         GPRReg propertyReg = property.gpr();
2545
2546         switch (arrayMode.type()) {
2547         case Array::Int32: {
2548             speculateInt32(child3);
2549             FALLTHROUGH;
2550         }
2551         case Array::Contiguous: {
2552             JSValueOperand value(this, child3, ManualOperandSpeculation);
2553
2554             GPRReg valueTagReg = value.tagGPR();
2555             GPRReg valuePayloadReg = value.payloadGPR();
2556         
2557             if (!m_compileOkay)
2558                 return;
2559
2560             compileContiguousPutByVal(node, base, property, value, valuePayloadReg, valueTagReg);
2561             break;
2562         }
2563         case Array::Double: {
2564             compileDoublePutByVal(node, base, property);
2565             break;
2566         }
2567         case Array::ArrayStorage:
2568         case Array::SlowPutArrayStorage: {
2569             JSValueOperand value(this, child3);
2570
2571             GPRReg valueTagReg = value.tagGPR();
2572             GPRReg valuePayloadReg = value.payloadGPR();
2573             
2574             if (!m_compileOkay)
2575                 return;
2576
2577             StorageOperand storage(this, child4);
2578             GPRReg storageReg = storage.gpr();
2579
2580             if (node->op() == PutByValAlias) {
2581                 // Store the value to the array.
2582                 GPRReg propertyReg = property.gpr();
2583                 m_jit.store32(value.tagGPR(), MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
2584                 m_jit.store32(value.payloadGPR(), MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
2585                 
2586                 noResult(node);
2587                 break;
2588             }
2589
2590             MacroAssembler::JumpList slowCases;
2591
2592             MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
2593             if (!arrayMode.isOutOfBounds())
2594                 speculationCheck(OutOfBounds, JSValueRegs(), 0, beyondArrayBounds);
2595             else
2596                 slowCases.append(beyondArrayBounds);
2597
2598             // Check if we're writing to a hole; if so increment m_numValuesInVector.
2599             if (arrayMode.isInBounds()) {
2600                 speculationCheck(
2601                     StoreToHole, JSValueRegs(), 0,
2602                     m_jit.branch32(MacroAssembler::Equal, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), TrustedImm32(JSValue::EmptyValueTag)));
2603             } else {
2604                 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));
2605                 if (arrayMode.isSlowPut()) {
2606                     // This is sort of strange. If we wanted to optimize this code path, we would invert
2607                     // the above branch. But it's simply not worth it since this only happens if we're
2608                     // already having a bad time.
2609                     slowCases.append(m_jit.jump());
2610                 } else {
2611                     m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, ArrayStorage::numValuesInVectorOffset()));
2612                 
2613                     // If we're writing to a hole we might be growing the array; 
2614                     MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
2615                     m_jit.add32(TrustedImm32(1), propertyReg);
2616                     m_jit.store32(propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
2617                     m_jit.sub32(TrustedImm32(1), propertyReg);
2618                 
2619                     lengthDoesNotNeedUpdate.link(&m_jit);
2620                 }
2621                 notHoleValue.link(&m_jit);
2622             }
2623     
2624             // Store the value to the array.
2625             m_jit.store32(valueTagReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
2626             m_jit.store32(valuePayloadReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
2627
2628             base.use();
2629             property.use();
2630             value.use();
2631             storage.use();
2632             
2633             if (!slowCases.empty()) {
2634                 if (node->op() == PutByValDirect) {
2635                     addSlowPathGenerator(slowPathCall(
2636                         slowCases, this,
2637                         m_jit.codeBlock()->isStrictMode() ? operationPutByValDirectBeyondArrayBoundsStrict : operationPutByValDirectBeyondArrayBoundsNonStrict,
2638                         NoResult, baseReg, propertyReg, JSValueRegs(valueTagReg, valuePayloadReg)));
2639                 } else {
2640                     addSlowPathGenerator(slowPathCall(
2641                         slowCases, this,
2642                         m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
2643                         NoResult, baseReg, propertyReg, JSValueRegs(valueTagReg, valuePayloadReg)));
2644                 }
2645             }
2646
2647             noResult(node, UseChildrenCalledExplicitly);
2648             break;
2649         }
2650             
2651         default: {
2652             TypedArrayType type = arrayMode.typedArrayType();
2653             if (isInt(type))
2654                 compilePutByValForIntTypedArray(base.gpr(), property.gpr(), node, type);
2655             else
2656                 compilePutByValForFloatTypedArray(base.gpr(), property.gpr(), node, type);
2657         } }
2658         break;
2659     }
2660
2661     case PutByValWithThis: {
2662 #if CPU(X86)
2663         // We don't have enough registers on X86 to do this
2664         // without setting up the call frame incrementally.
2665         unsigned index = 0;
2666         m_jit.poke(GPRInfo::callFrameRegister, index++);
2667
2668         {
2669             JSValueOperand base(this, m_jit.graph().varArgChild(node, 0));
2670             GPRReg baseTag = base.tagGPR();
2671             GPRReg basePayload = base.payloadGPR();
2672
2673             JSValueOperand thisValue(this, m_jit.graph().varArgChild(node, 1));
2674             GPRReg thisValueTag = thisValue.tagGPR();
2675             GPRReg thisValuePayload = thisValue.payloadGPR();
2676
2677             JSValueOperand property(this, m_jit.graph().varArgChild(node, 2));
2678             GPRReg propertyTag = property.tagGPR();
2679             GPRReg propertyPayload = property.payloadGPR();
2680
2681             m_jit.poke(basePayload, index++);
2682             m_jit.poke(baseTag, index++);
2683
2684             m_jit.poke(thisValuePayload, index++);
2685             m_jit.poke(thisValueTag, index++);
2686
2687             m_jit.poke(propertyPayload, index++);
2688             m_jit.poke(propertyTag, index++);
2689
2690             flushRegisters();
2691         }
2692
2693         JSValueOperand value(this, m_jit.graph().varArgChild(node, 3));
2694         GPRReg valueTag = value.tagGPR();
2695         GPRReg valuePayload = value.payloadGPR();
2696         m_jit.poke(valuePayload, index++);
2697         m_jit.poke(valueTag, index++);
2698
2699         flushRegisters();
2700         appendCall(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValWithThisStrict : operationPutByValWithThis);
2701         m_jit.exceptionCheck();
2702 #else
2703         static_assert(GPRInfo::numberOfRegisters >= 8, "We are assuming we have enough registers to make this call without incrementally setting up the arguments.");
2704
2705         JSValueOperand base(this, m_jit.graph().varArgChild(node, 0));
2706         JSValueRegs baseRegs = base.jsValueRegs();
2707
2708         JSValueOperand thisValue(this, m_jit.graph().varArgChild(node, 1));
2709         JSValueRegs thisRegs = thisValue.jsValueRegs();
2710
2711         JSValueOperand property(this, m_jit.graph().varArgChild(node, 2));
2712         JSValueRegs propertyRegs = property.jsValueRegs();
2713
2714         JSValueOperand value(this, m_jit.graph().varArgChild(node, 3));
2715         JSValueRegs valueRegs = value.jsValueRegs();
2716
2717         flushRegisters();
2718         callOperation(m_jit.isStrictModeFor(node->origin.semantic) ? operationPutByValWithThisStrict : operationPutByValWithThis,
2719             NoResult, baseRegs, thisRegs, propertyRegs, valueRegs);
2720         m_jit.exceptionCheck();
2721 #endif // CPU(X86)
2722
2723         noResult(node);
2724         break;
2725     }
2726
2727     case RegExpExec: {
2728         compileRegExpExec(node);
2729         break;
2730     }
2731
2732     case RegExpExecNonGlobalOrSticky: {
2733         compileRegExpExecNonGlobalOrSticky(node);
2734         break;
2735     }
2736
2737     case RegExpMatchFastGlobal: {
2738         compileRegExpMatchFastGlobal(node);
2739         break;
2740     }
2741         
2742     case RegExpTest: {
2743         compileRegExpTest(node);
2744         break;
2745     }
2746
2747     case RegExpMatchFast: {
2748         compileRegExpMatchFast(node);
2749         break;
2750     }
2751
2752     case StringReplace:
2753     case StringReplaceRegExp: {
2754         compileStringReplace(node);
2755         break;
2756     }
2757
2758     case GetRegExpObjectLastIndex: {
2759         compileGetRegExpObjectLastIndex(node);
2760         break;
2761     }
2762         
2763     case SetRegExpObjectLastIndex: {
2764         compileSetRegExpObjectLastIndex(node);
2765         break;
2766     }
2767         
2768     case RecordRegExpCachedResult: {
2769         compileRecordRegExpCachedResult(node);
2770         break;
2771     }
2772         
2773     case ArrayPush: {
2774         compileArrayPush(node);
2775         break;
2776     }
2777         
2778     case ArrayPop: {
2779         ASSERT(node->arrayMode().isJSArray());
2780         
2781         SpeculateCellOperand base(this, node->child1());
2782         StorageOperand storage(this, node->child2());
2783         GPRTemporary valueTag(this);
2784         GPRTemporary valuePayload(this);
2785         
2786         GPRReg baseGPR = base.gpr();
2787         GPRReg valueTagGPR = valueTag.gpr();
2788         GPRReg valuePayloadGPR = valuePayload.gpr();
2789         GPRReg storageGPR = storage.gpr();
2790         
2791         switch (node->arrayMode().type()) {
2792         case Array::Int32:
2793         case Array::Contiguous: {
2794             m_jit.load32(
2795                 MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), valuePayloadGPR);
2796             MacroAssembler::Jump undefinedCase =
2797                 m_jit.branchTest32(MacroAssembler::Zero, valuePayloadGPR);
2798             m_jit.sub32(TrustedImm32(1), valuePayloadGPR);
2799             m_jit.store32(
2800                 valuePayloadGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
2801             m_jit.load32(
2802                 MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)),
2803                 valueTagGPR);
2804             MacroAssembler::Jump slowCase = m_jit.branchIfEmpty(valueTagGPR);
2805             m_jit.store32(
2806                 MacroAssembler::TrustedImm32(JSValue::EmptyValueTag),
2807                 MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
2808             m_jit.load32(
2809                 MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)),
2810                 valuePayloadGPR);
2811
2812             addSlowPathGenerator(
2813                 slowPathMove(
2814                     undefinedCase, this,
2815                     MacroAssembler::TrustedImm32(jsUndefined().tag()), valueTagGPR,
2816                     MacroAssembler::TrustedImm32(jsUndefined().payload()), valuePayloadGPR));
2817             addSlowPathGenerator(
2818                 slowPathCall(
2819                     slowCase, this, operationArrayPopAndRecoverLength,
2820                     JSValueRegs(valueTagGPR, valuePayloadGPR), baseGPR));
2821             
2822             jsValueResult(valueTagGPR, valuePayloadGPR, node);
2823             break;
2824         }
2825             
2826         case Array::Double: {
2827             FPRTemporary temp(this);
2828             FPRReg tempFPR = temp.fpr();
2829             
2830             m_jit.load32(
2831                 MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), valuePayloadGPR);
2832             MacroAssembler::Jump undefinedCase =
2833                 m_jit.branchTest32(MacroAssembler::Zero, valuePayloadGPR);
2834             m_jit.sub32(TrustedImm32(1), valuePayloadGPR);
2835             m_jit.store32(
2836                 valuePayloadGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
2837             m_jit.loadDouble(
2838                 MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight),
2839                 tempFPR);
2840             MacroAssembler::Jump slowCase = m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, tempFPR, tempFPR);
2841             JSValue nan = JSValue(JSValue::EncodeAsDouble, PNaN);
2842             m_jit.store32(
2843                 MacroAssembler::TrustedImm32(nan.u.asBits.tag),
2844                 MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
2845             m_jit.store32(
2846                 MacroAssembler::TrustedImm32(nan.u.asBits.payload),
2847                 MacroAssembler::BaseIndex(storageGPR, valuePayloadGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
2848             boxDouble(tempFPR, valueTagGPR, valuePayloadGPR);
2849
2850             addSlowPathGenerator(
2851                 slowPathMove(
2852                     undefinedCase, this,
2853                     MacroAssembler::TrustedImm32(jsUndefined().tag()), valueTagGPR,
2854                     MacroAssembler::TrustedImm32(jsUndefined().payload()), valuePayloadGPR));
2855             addSlowPathGenerator(
2856                 slowPathCall(
2857                     slowCase, this, operationArrayPopAndRecoverLength,
2858                     JSValueRegs(valueTagGPR, valuePayloadGPR), baseGPR));
2859             
2860             jsValueResult(valueTagGPR, valuePayloadGPR, node);
2861             break;
2862         }
2863
2864         case Array::ArrayStorage: {
2865             GPRTemporary storageLength(this);
2866             GPRReg storageLengthGPR = storageLength.gpr();
2867
2868             m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
2869         
2870             JITCompiler::JumpList setUndefinedCases;
2871             setUndefinedCases.append(m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR));
2872         
2873             m_jit.sub32(TrustedImm32(1), storageLengthGPR);
2874         
2875             MacroAssembler::Jump slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset()));
2876         
2877             m_jit.load32(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), valueTagGPR);
2878             m_jit.load32(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), valuePayloadGPR);
2879         
2880             m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()));
2881
2882             setUndefinedCases.append(m_jit.branchIfEmpty(valueTagGPR));
2883         
2884             m_jit.store32(TrustedImm32(JSValue::EmptyValueTag), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
2885
2886             m_jit.sub32(TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
2887         
2888             addSlowPathGenerator(
2889                 slowPathMove(
2890                     setUndefinedCases, this,
2891                     MacroAssembler::TrustedImm32(jsUndefined().tag()), valueTagGPR,
2892                     MacroAssembler::TrustedImm32(jsUndefined().payload()), valuePayloadGPR));
2893         
2894             addSlowPathGenerator(
2895                 slowPathCall(
2896                     slowCase, this, operationArrayPop,
2897                     JSValueRegs(valueTagGPR, valuePayloadGPR), baseGPR));
2898
2899             jsValueResult(valueTagGPR, valuePayloadGPR, node);
2900             break;
2901         }
2902             
2903         default:
2904             CRASH();
2905             break;
2906         }
2907         break;
2908     }
2909
2910     case ArraySlice: {
2911         compileArraySlice(node);
2912         break;
2913     }
2914
2915     case ArrayIndexOf: {
2916         compileArrayIndexOf(node);
2917         break;
2918     }
2919
2920     case DFG::Jump: {
2921         jump(node->targetBlock());
2922         noResult(node);
2923         break;
2924     }
2925
2926     case Branch:
2927         emitBranch(node);
2928         break;
2929         
2930     case Switch:
2931         emitSwitch(node);
2932         break;
2933
2934     case Return: {
2935         ASSERT(GPRInfo::callFrameRegister != GPRInfo::regT2);
2936         ASSERT(GPRInfo::regT1 != GPRInfo::returnValueGPR);
2937         ASSERT(GPRInfo::returnValueGPR != GPRInfo::callFrameRegister);
2938
2939         // Return the result in returnValueGPR.
2940         JSValueOperand op1(this, node->child1());
2941         op1.fill();
2942         if (op1.isDouble())
2943             boxDouble(op1.fpr(), GPRInfo::returnValueGPR2, GPRInfo::returnValueGPR);
2944         else {
2945             if (op1.payloadGPR() == GPRInfo::returnValueGPR2 && op1.tagGPR() == GPRInfo::returnValueGPR)
2946                 m_jit.swap(GPRInfo::returnValueGPR, GPRInfo::returnValueGPR2);
2947             else if (op1.payloadGPR() == GPRInfo::returnValueGPR2) {
2948                 m_jit.move(op1.payloadGPR(), GPRInfo::returnValueGPR);
2949                 m_jit.move(op1.tagGPR(), GPRInfo::returnValueGPR2);
2950             } else {
2951                 m_jit.move(op1.tagGPR(), GPRInfo::returnValueGPR2);
2952                 m_jit.move(op1.payloadGPR(), GPRInfo::returnValueGPR);
2953             }
2954         }
2955
2956         m_jit.emitRestoreCalleeSaves();
2957         m_jit.emitFunctionEpilogue();
2958         m_jit.ret();
2959         
2960         noResult(node);
2961         break;
2962     }
2963         
2964     case Throw: {
2965         compileThrow(node);
2966         break;
2967     }
2968
2969     case ThrowStaticError: {
2970         compileThrowStaticError(node);
2971         break;
2972     }
2973
2974     case BooleanToNumber: {
2975         switch (node->child1().useKind()) {
2976         case BooleanUse: {
2977             SpeculateBooleanOperand value(this, node->child1());
2978             GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add).
2979             
2980             m_jit.move(value.gpr(), result.gpr());
2981
2982             int32Result(result.gpr(), node);
2983             break;
2984         }
2985             
2986         case UntypedUse: {
2987             JSValueOperand value(this, node->child1());
2988             
2989             if (!m_interpreter.needsTypeCheck(node->child1(), SpecBoolInt32 | SpecBoolean)) {
2990                 GPRTemporary result(this);
2991                 
2992                 GPRReg valueGPR = value.payloadGPR();
2993                 GPRReg resultGPR = result.gpr();
2994                 
2995                 m_jit.move(valueGPR, resultGPR);
2996                 int32Result(result.gpr(), node);
2997                 break;
2998             }
2999             
3000             GPRTemporary resultTag(this);
3001             GPRTemporary resultPayload(this);
3002             
3003             GPRReg valueTagGPR = value.tagGPR();
3004             GPRReg valuePayloadGPR = value.payloadGPR();
3005             GPRReg resultTagGPR = resultTag.gpr();
3006             GPRReg resultPayloadGPR = resultPayload.gpr();
3007             
3008             m_jit.move(valuePayloadGPR, resultPayloadGPR);
3009             JITCompiler::Jump isBoolean = m_jit.branchIfBoolean(valueTagGPR, InvalidGPRReg);
3010             m_jit.move(valueTagGPR, resultTagGPR);
3011             JITCompiler::Jump done = m_jit.jump();
3012             isBoolean.link(&m_jit);
3013             m_jit.move(TrustedImm32(JSValue::Int32Tag), resultTagGPR);
3014             done.link(&m_jit);
3015             
3016             jsValueResult(resultTagGPR, resultPayloadGPR, node);
3017             break;
3018         }
3019             
3020         default:
3021             RELEASE_ASSERT_NOT_REACHED();
3022             break;
3023         }
3024         break;
3025     }
3026         
3027     case ToPrimitive: {
3028         compileToPrimitive(node);
3029         break;
3030     }
3031
3032     case ToNumber: {
3033         JSValueOperand argument(this, node->child1());
3034         GPRTemporary resultTag(this, Reuse, argument, TagWord);
3035         GPRTemporary resultPayload(this, Reuse, argument, PayloadWord);
3036
3037         GPRReg argumentPayloadGPR = argument.payloadGPR();
3038         GPRReg argumentTagGPR = argument.tagGPR();
3039         JSValueRegs argumentRegs = argument.jsValueRegs();
3040         JSValueRegs resultRegs(resultTag.gpr(), resultPayload.gpr());
3041
3042         argument.use();
3043
3044         // We have several attempts to remove ToNumber. But ToNumber still exists.
3045         // It means that converting non-numbers to numbers by this ToNumber is not rare.
3046         // Instead of the slow path generator, we emit callOperation here.
3047         if (!(m_state.forNode(node->child1()).m_type & SpecBytecodeNumber)) {
3048             flushRegisters();
3049             callOperation(operationToNumber, resultRegs, argumentRegs);
3050             m_jit.exceptionCheck();
3051         } else {
3052             MacroAssembler::Jump notNumber;
3053             {
3054                 GPRTemporary scratch(this);
3055                 notNumber = m_jit.branchIfNotNumber(argument.jsValueRegs(), scratch.gpr());
3056             }
3057             m_jit.move(argumentTagGPR, resultRegs.tagGPR());
3058             m_jit.move(argumentPayloadGPR, resultRegs.payloadGPR());
3059             MacroAssembler::Jump done = m_jit.jump();
3060
3061             notNumber.link(&m_jit);
3062             silentSpillAllRegisters(resultRegs);
3063             callOperation(operationToNumber, resultRegs, argumentRegs);
3064             silentFillAllRegisters();
3065             m_jit.exceptionCheck();
3066
3067             done.link(&m_jit);
3068         }
3069
3070         jsValueResult(resultRegs.tagGPR(), resultRegs.payloadGPR(), node, UseChildrenCalledExplicitly);
3071         break;
3072     }
3073         
3074     case ToString:
3075     case CallStringConstructor: {
3076         compileToStringOrCallStringConstructor(node);
3077         break;
3078     }
3079         
3080     case NewStringObject: {
3081         compileNewStringObject(node);
3082         break;
3083     }
3084         
3085     case NewArray: {
3086         compileNewArray(node);
3087         break;
3088     }
3089
3090     case NewArrayWithSpread: {
3091         compileNewArrayWithSpread(node);
3092         break;
3093     }
3094
3095     case Spread: {
3096         compileSpread(node);
3097         break;
3098     }
3099
3100     case NewArrayWithSize: {
3101         compileNewArrayWithSize(node);
3102         break;
3103     }
3104         
3105     case NewArrayBuffer: {
3106         compileNewArrayBuffer(node);
3107         break;
3108     }
3109         
3110     case NewTypedArray: {
3111         compileNewTypedArray(node);
3112         break;
3113     }
3114         
3115     case NewRegexp: {
3116         compileNewRegexp(node);
3117         break;
3118     }
3119
3120     case ToObject:
3121     case CallObjectConstructor: {
3122         compileToObjectOrCallObjectConstructor(node);
3123         break;
3124     }
3125         
3126     case ToThis: {
3127         compileToThis(node);
3128         break;
3129     }
3130
3131     case CreateThis: {
3132         compileCreateThis(node);
3133         break;
3134     }
3135
3136     case NewObject: {
3137         compileNewObject(node);
3138         break;
3139     }
3140
3141     case GetCallee: {
3142         compileGetCallee(node);
3143         break;
3144     }
3145
3146     case SetCallee: {
3147         compileSetCallee(node);
3148         break;
3149     }
3150         
3151     case GetArgumentCountIncludingThis: {
3152         compileGetArgumentCountIncludingThis(node);
3153         break;
3154     }
3155
3156     case SetArgumentCountIncludingThis:
3157         compileSetArgumentCountIncludingThis(node);
3158         break;
3159         
3160     case GetScope:
3161         compileGetScope(node);
3162         break;
3163             
3164     case SkipScope:
3165         compileSkipScope(node);
3166         break;
3167         
3168     case GetGlobalObject:
3169         compileGetGlobalObject(node);
3170         break;
3171
3172     case GetGlobalThis:
3173         compileGetGlobalThis(node);
3174         break;
3175         
3176     case GetClosureVar: {
3177         compileGetClosureVar(node);
3178         break;
3179     }
3180     
3181     case PutClosureVar: {
3182         compilePutClosureVar(node);
3183         break;
3184     }
3185
3186     case TryGetById: {
3187         compileGetById(node, AccessType::TryGet);
3188         break;
3189     }
3190
3191     case GetByIdDirect: {
3192         compileGetById(node, AccessType::GetDirect);
3193         break;
3194     }
3195
3196     case GetByIdDirectFlush: {
3197         compileGetByIdFlush(node, AccessType::GetDirect);
3198         break;
3199     }
3200
3201     case GetById: {
3202         compileGetById(node, AccessType::Get);
3203         break;
3204     }
3205
3206     case GetByIdFlush: {
3207         compileGetByIdFlush(node, AccessType::Get);
3208         break;
3209     }
3210
3211     case GetByIdWithThis: {
3212         if (node->child1().useKind() == CellUse && node->child2().useKind() == CellUse) {
3213             SpeculateCellOperand base(this, node->child1());
3214             SpeculateCellOperand thisValue(this, node->child2());
3215             GPRTemporary resultTag(this);
3216             GPRTemporary resultPayload(this);
3217             
3218             GPRReg baseGPR = base.gpr();
3219             GPRReg thisGPR = thisValue.gpr();
3220             GPRReg resultTagGPR = resultTag.gpr();
3221             GPRReg resultPayloadGPR = resultPayload.gpr();
3222             
3223             cachedGetByIdWithThis(node->origin.semantic, InvalidGPRReg, baseGPR, InvalidGPRReg, thisGPR, resultTagGPR, resultPayloadGPR, node->identifierNumber());
3224             
3225             jsValueResult(resultTagGPR, resultPayloadGPR, node);
3226         } else {
3227             JSValueOperand base(this, node->child1());
3228             JSValueOperand thisValue(this, node->child2());
3229             GPRTemporary resultTag(this);
3230             GPRTemporary resultPayload(this);
3231             
3232             GPRReg baseTagGPR = base.tagGPR();
3233             GPRReg basePayloadGPR = base.payloadGPR();
3234             GPRReg thisTagGPR = thisValue.tagGPR();
3235             GPRReg thisPayloadGPR = thisValue.payloadGPR();
3236             GPRReg resultTagGPR = resultTag.gpr();
3237             GPRReg resultPayloadGPR = resultPayload.gpr();
3238             
3239             JITCompiler::JumpList notCellList;
3240             notCellList.append(m_jit.branchIfNotCell(base.jsValueRegs()));
3241             notCellList.append(m_jit.branchIfNotCell(thisValue.jsValueRegs()));
3242             
3243             cachedGetByIdWithThis(node->origin.semantic, baseTagGPR, basePayloadGPR, thisTagGPR, thisPayloadGPR, resultTagGPR, resultPayloadGPR, node->identifierNumber(), notCellList);
3244             
3245             jsValueResult(resultTagGPR, resultPayloadGPR, node);
3246         }
3247         
3248         break;
3249     }
3250
3251     case GetArrayLength:
3252         compileGetArrayLength(node);
3253         break;
3254
3255     case DeleteById: {
3256         compileDeleteById(node);
3257         break;
3258     }
3259
3260     case DeleteByVal: {
3261         compileDeleteByVal(node);
3262         break;
3263     }
3264         
3265     case CheckCell: {
3266         compileCheckCell(node);
3267         break;
3268     }
3269
3270     case CheckNotEmpty: {
3271         compileCheckNotEmpty(node);
3272         break;
3273     }
3274
3275     case CheckStringIdent:
3276         compileCheckStringIdent(node);
3277         break;
3278
3279     case GetExecutable: {
3280         compileGetExecutable(node);
3281         break;
3282     }
3283         
3284     case CheckStructure: {
3285         compileCheckStructure(node);
3286         break;
3287     }
3288         
3289     case PutStructure: {
3290         RegisteredStructure oldStructure = node->transition()->previous;
3291         RegisteredStructure newStructure = node->transition()->next;
3292
3293         m_jit.jitCode()->common.notifyCompilingStructureTransition(m_jit.graph().m_plan, m_jit.codeBlock(), node);
3294
3295         SpeculateCellOperand base(this, node->child1());
3296         GPRReg baseGPR = base.gpr();
3297         
3298         ASSERT_UNUSED(oldStructure, oldStructure->indexingType() == newStructure->indexingType());
3299         ASSERT(oldStructure->typeInfo().type() == newStructure->typeInfo().type());
3300         ASSERT(oldStructure->typeInfo().inlineTypeFlags() == newStructure->typeInfo().inlineTypeFlags());
3301         m_jit.storePtr(TrustedImmPtr(newStructure), MacroAssembler::Address(baseGPR, JSCell::structureIDOffset()));
3302         
3303         noResult(node);
3304         break;
3305     }
3306         
3307     case AllocatePropertyStorage:
3308         compileAllocatePropertyStorage(node);
3309         break;
3310         
3311     case ReallocatePropertyStorage:
3312         compileReallocatePropertyStorage(node);
3313         break;
3314         
3315     case NukeStructureAndSetButterfly:
3316         compileNukeStructureAndSetButterfly(node);
3317         break;
3318         
3319     case GetButterfly:
3320         compileGetButterfly(node);
3321         break;
3322
3323     case GetIndexedPropertyStorage: {
3324         compileGetIndexedPropertyStorage(node);
3325         break;
3326     }
3327
3328     case ConstantStoragePointer: {
3329         compileConstantStoragePointer(node);
3330         break;
3331     }
3332         
3333     case GetTypedArrayByteOffset: {
3334         compileGetTypedArrayByteOffset(node);
3335         break;
3336     }
3337
3338     case GetPrototypeOf: {
3339         compileGetPrototypeOf(node);
3340         break;
3341     }
3342         
3343     case GetByOffset: {
3344         compileGetByOffset(node);
3345         break;
3346     }
3347         
3348     case GetGetterSetterByOffset: {
3349         StorageOperand storage(this, node->child1());
3350         GPRTemporary resultPayload(this);
3351         
3352         GPRReg storageGPR = storage.gpr();
3353         GPRReg resultPayloadGPR = resultPayload.gpr();
3354         
3355         StorageAccessData& storageAccessData = node->storageAccessData();
3356         
3357         m_jit.load32(JITCompiler::Address(storageGPR, offsetRelativeToBase(storageAccessData.offset) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)), resultPayloadGPR);
3358         
3359         cellResult(resultPayloadGPR, node);
3360         break;
3361     }
3362         
3363     case GetGetter: {
3364         compileGetGetter(node);
3365         break;
3366     }
3367         
3368     case GetSetter: {
3369         compileGetSetter(node);
3370         break;
3371     }
3372         
3373     case PutByOffset: {
3374         compilePutByOffset(node);
3375         break;
3376     }
3377
3378     case PutByIdFlush: {
3379         compilePutByIdFlush(node);
3380         break;
3381     }
3382
3383     case PutById: {
3384         compilePutById(node);
3385         break;
3386     }
3387
3388     case PutByIdDirect: {
3389         compilePutByIdDirect(node);
3390         break;
3391     }
3392
3393     case PutByIdWithThis: {
3394         compilePutByIdWithThis(node);
3395         break;
3396     }
3397
3398     case PutGetterById:
3399     case PutSetterById: {
3400         compilePutAccessorById(node);
3401         break;
3402     }
3403
3404     case PutGetterSetterById: {
3405         compilePutGetterSetterById(node);
3406         break;
3407     }
3408
3409     case PutGetterByVal:
3410     case PutSetterByVal: {
3411         compilePutAccessorByVal(node);
3412         break;
3413     }
3414
3415     case DefineDataProperty: {
3416         compileDefineDataProperty(node);
3417         break;
3418     }
3419
3420     case DefineAccessorProperty: {
3421         compileDefineAccessorProperty(node);
3422         break;
3423     }
3424
3425     case GetGlobalLexicalVariable:
3426     case GetGlobalVar: {
3427         compileGetGlobalVariable(node);
3428         break;
3429     }
3430
3431     case PutGlobalVariable: {
3432         compilePutGlobalVariable(node);
3433         break;
3434     }
3435
3436     case NotifyWrite: {
3437         compileNotifyWrite(node);
3438         break;
3439     }
3440
3441     case ParseInt: {
3442         compileParseInt(node);
3443         break;
3444     }
3445
3446     case CheckTypeInfoFlags: {
3447         compileCheckTypeInfoFlags(node);
3448         break;
3449     }
3450
3451     case OverridesHasInstance: {
3452         compileOverridesHasInstance(node);
3453         break;
3454     }
3455
3456     case InstanceOf: {
3457         compileInstanceOf(node);
3458         break;
3459     }
3460
3461     case InstanceOfCustom: {
3462         compileInstanceOfCustom(node);
3463         break;
3464     }
3465
3466     case IsEmpty: {        
3467         JSValueOperand value(this, node->child1());
3468         GPRTemporary result(this, Reuse, value, TagWord);
3469         m_jit.comparePtr(JITCompiler::Equal, value.tagGPR(), TrustedImm32(JSValue::EmptyValueTag), result.gpr());
3470         booleanResult(result.gpr(), node);
3471         break;
3472     }
3473
3474     case IsUndefined: {
3475         JSValueOperand value(this, node->child1());
3476         GPRTemporary result(this);
3477         GPRTemporary localGlobalObject(this);
3478         GPRTemporary remoteGlobalObject(this);
3479
3480         JITCompiler::Jump isCell = m_jit.branchIfCell(value.jsValueRegs());
3481         
3482         m_jit.compare32(JITCompiler::Equal, value.tagGPR(), TrustedImm32(JSValue::UndefinedTag), result.gpr());
3483         JITCompiler::Jump done = m_jit.jump();
3484         
3485         isCell.link(&m_jit);
3486         JITCompiler::Jump notMasqueradesAsUndefined;
3487         if (masqueradesAsUndefinedWatchpointIsStillValid()) {
3488             m_jit.move(TrustedImm32(0), result.gpr());
3489             notMasqueradesAsUndefined = m_jit.jump();
3490         } else {
3491             JITCompiler::Jump isMasqueradesAsUndefined = m_jit.branchTest8(
3492                 JITCompiler::NonZero, 
3493                 JITCompiler::Address(value.payloadGPR(), JSCell::typeInfoFlagsOffset()), 
3494                 TrustedImm32(MasqueradesAsUndefined));
3495             m_jit.move(TrustedImm32(0), result.gpr());
3496             notMasqueradesAsUndefined = m_jit.jump();
3497             
3498             isMasqueradesAsUndefined.link(&m_jit);
3499             GPRReg localGlobalObjectGPR = localGlobalObject.gpr();
3500             GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr();
3501             m_jit.move(TrustedImmPtr::weakPointer(m_jit.graph(), m_jit.globalObjectFor(node->origin.semantic)), localGlobalObjectGPR);
3502             m_jit.loadPtr(JITCompiler::Address(value.payloadGPR(), JSCell::structureIDOffset()), result.gpr());
3503             m_jit.loadPtr(JITCompiler::Address(result.gpr(), Structure::globalObjectOffset()), remoteGlobalObjectGPR); 
3504             m_jit.compare32(JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, result.gpr());
3505         }
3506
3507         notMasqueradesAsUndefined.link(&m_jit);
3508         done.link(&m_jit);
3509         booleanResult(result.gpr(), node);
3510         break;
3511     }
3512
3513     case IsBoolean: {
3514         JSValueOperand value(this, node->child1());
3515         GPRTemporary result(this, Reuse, value, TagWord);
3516         
3517         m_jit.compare32(JITCompiler::Equal, value.tagGPR(), JITCompiler::TrustedImm32(JSValue::BooleanTag), result.gpr());
3518         booleanResult(result.gpr(), node);
3519         break;
3520     }
3521
3522     case IsNumber: {
3523         JSValueOperand value(this, node->child1());
3524         GPRTemporary result(this, Reuse, value, TagWord);
3525         
3526         m_jit.add32(TrustedImm32(1), value.tagGPR(), result.gpr());
3527         m_jit.compare32(JITCompiler::Below, result.gpr(), JITCompiler::TrustedImm32(JSValue::LowestTag + 1), result.gpr());
3528         booleanResult(result.gpr(), node);
3529         break;
3530     }
3531
3532     case NumberIsInteger: {
3533         JSValueOperand input(this, node->child1());
3534         JSValueRegs inputRegs = input.jsValueRegs();
3535         flushRegisters();
3536         GPRFlushedCallResult result(this);
3537         GPRReg resultGPR = result.gpr();
3538         callOperation(operationNumberIsInteger, resultGPR, inputRegs);
3539         booleanResult(resultGPR, node);
3540         break;
3541     }
3542
3543     case IsObject: {
3544         compileIsObject(node);
3545         break;
3546     }
3547
3548     case IsObjectOrNull: {
3549         compileIsObjectOrNull(node);
3550         break;
3551     }
3552
3553     case IsFunction: {
3554         compileIsFunction(node);
3555         break;
3556     }
3557
3558     case IsCellWithType: {
3559         compileIsCellWithType(node);
3560         break;
3561     }
3562
3563     case IsTypedArrayView: {
3564         compileIsTypedArrayView(node);
3565         break;
3566     }
3567
3568     case TypeOf: {
3569         compileTypeOf(node);
3570         break;
3571     }
3572
3573     case MapHash: {
3574         JSValueOperand input(this, node->child1());
3575
3576         JSValueRegs inputRegs = input.jsValueRegs();
3577
3578         flushRegisters();
3579         GPRFlushedCallResult result(this);
3580         GPRReg resultGPR = result.gpr();
3581         callOperation(operationMapHash, resultGPR, inputRegs);
3582         m_jit.exceptionCheck();
3583         int32Result(resultGPR, node);
3584         break;
3585     }
3586
3587     case NormalizeMapKey: {
3588         compileNormalizeMapKey(node);
3589         break;
3590     }
3591
3592     case GetMapBucket: {
3593         SpeculateCellOperand map(this, node->child1());
3594         JSValueOperand key(this, node->child2());
3595         SpeculateInt32Operand hash(this, node->child3());
3596
3597         GPRReg mapGPR = map.gpr();
3598         JSValueRegs keyRegs = key.jsValueRegs();
3599         GPRReg hashGPR = hash.gpr();
3600
3601         if (node->child1().useKind() == MapObjectUse)
3602             speculateMapObject(node->child1(), mapGPR);
3603         else if (node->child1().useKind() == SetObjectUse)
3604             speculateSetObject(node->child1(), mapGPR);
3605         else
3606             RELEASE_ASSERT_NOT_REACHED();
3607
3608         flushRegisters();
3609         GPRFlushedCallResult result(this);
3610         GPRReg resultGPR = result.gpr();
3611         if (node->child1().useKind() == MapObjectUse)
3612             callOperation(operationJSMapFindBucket, resultGPR, mapGPR, keyRegs, hashGPR);
3613         else
3614             callOperation(operationJSSetFindBucket, resultGPR, mapGPR, keyRegs, hashGPR);
3615         m_jit.exceptionCheck();
3616         cellResult(resultGPR, node);
3617         break;
3618     }
3619
3620     case GetMapBucketHead:
3621         compileGetMapBucketHead(node);
3622         break;
3623
3624     case GetMapBucketNext:
3625         compileGetMapBucketNext(node);
3626         break;
3627
3628     case LoadKeyFromMapBucket:
3629         compileLoadKeyFromMapBucket(node);
3630         break;
3631
3632     case LoadValueFromMapBucket:
3633         compileLoadValueFromMapBucket(node);
3634         break;
3635
3636     case ExtractValueFromWeakMapGet:
3637         compileExtractValueFromWeakMapGet(node);
3638         break;
3639
3640     case SetAdd:
3641         compileSetAdd(node);
3642         break;
3643
3644     case MapSet:
3645         compileMapSet(node);
3646         break;
3647
3648     case WeakMapGet:
3649         compileWeakMapGet(node);
3650         break;
3651
3652     case WeakSetAdd:
3653         compileWeakSetAdd(node);
3654         break;
3655
3656     case WeakMapSet:
3657         compileWeakMapSet(node);
3658         break;
3659
3660     case Flush:
3661         break;
3662
3663     case Call:
3664     case TailCall:
3665     case TailCallInlinedCaller:
3666     case Construct:
3667     case CallVarargs:
3668     case TailCallVarargs:
3669     case TailCallVarargsInlinedCaller:
3670     case ConstructVarargs:
3671     case CallForwardVarargs:
3672     case TailCallForwardVarargs:
3673     case TailCallForwardVarargsInlinedCaller:
3674     case ConstructForwardVarargs:
3675     case CallEval:
3676     case DirectCall:
3677     case DirectConstruct:
3678     case DirectTailCall:
3679     case DirectTailCallInlinedCaller:
3680         emitCall(node);
3681         break;
3682
3683     case LoadVarargs: {
3684         compileLoadVarargs(node);
3685         break;
3686     }
3687         
3688     case ForwardVarargs: {
3689         compileForwardVarargs(node);
3690         break;
3691     }
3692         
3693     case CreateActivation: {
3694         compileCreateActivation(node);
3695         break;
3696     }
3697
3698     case PushWithScope: {
3699         compilePushWithScope(node);
3700         break;
3701     }
3702         
3703     case CreateDirectArguments: {
3704         compileCreateDirectArguments(node);
3705         break;
3706     }
3707