ffdf13561858b3cb3a155021e65000718d5e771a
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGSpeculativeJIT64.cpp
1 /*
2  * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "DFGSpeculativeJIT.h"
28
29 #if ENABLE(DFG_JIT)
30
31 #include "Arguments.h"
32 #include "ArrayPrototype.h"
33 #include "DFGAbstractInterpreterInlines.h"
34 #include "DFGCallArrayAllocatorSlowPathGenerator.h"
35 #include "DFGSlowPathGenerator.h"
36 #include "JSCJSValueInlines.h"
37 #include "ObjectPrototype.h"
38
39 namespace JSC { namespace DFG {
40
41 #if USE(JSVALUE64)
42
43 void SpeculativeJIT::boxInt52(GPRReg sourceGPR, GPRReg targetGPR, DataFormat format)
44 {
45     GPRReg tempGPR;
46     if (sourceGPR == targetGPR)
47         tempGPR = allocate();
48     else
49         tempGPR = targetGPR;
50     
51     FPRReg fpr = fprAllocate();
52
53     if (format == DataFormatInt52)
54         m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), sourceGPR);
55     else
56         ASSERT(format == DataFormatStrictInt52);
57     
58     m_jit.boxInt52(sourceGPR, targetGPR, tempGPR, fpr);
59     
60     if (tempGPR != targetGPR)
61         unlock(tempGPR);
62     
63     unlock(fpr);
64 }
65
66 GPRReg SpeculativeJIT::fillJSValue(Edge edge)
67 {
68     VirtualRegister virtualRegister = edge->virtualRegister();
69     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
70     
71     switch (info.registerFormat()) {
72     case DataFormatNone: {
73         GPRReg gpr = allocate();
74
75         if (edge->hasConstant()) {
76             if (isInt32Constant(edge.node())) {
77                 info.fillJSValue(*m_stream, gpr, DataFormatJSInt32);
78                 JSValue jsValue = jsNumber(valueOfInt32Constant(edge.node()));
79                 m_jit.move(MacroAssembler::Imm64(JSValue::encode(jsValue)), gpr);
80             } else if (isNumberConstant(edge.node())) {
81                 info.fillJSValue(*m_stream, gpr, DataFormatJSDouble);
82                 JSValue jsValue(JSValue::EncodeAsDouble, valueOfNumberConstant(edge.node()));
83                 m_jit.move(MacroAssembler::Imm64(JSValue::encode(jsValue)), gpr);
84             } else {
85                 ASSERT(isJSConstant(edge.node()));
86                 JSValue jsValue = valueOfJSConstant(edge.node());
87                 m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsValue)), gpr);
88                 info.fillJSValue(*m_stream, gpr, DataFormatJS);
89             }
90
91             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
92         } else {
93             DataFormat spillFormat = info.spillFormat();
94             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
95             switch (spillFormat) {
96             case DataFormatInt32: {
97                 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
98                 m_jit.or64(GPRInfo::tagTypeNumberRegister, gpr);
99                 spillFormat = DataFormatJSInt32;
100                 break;
101             }
102                 
103             case DataFormatInt52:
104             case DataFormatStrictInt52: {
105                 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
106                 boxInt52(gpr, gpr, spillFormat);
107                 return gpr;
108             }
109                 
110             default:
111                 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
112                 if (spillFormat == DataFormatDouble) {
113                     // Need to box the double, since we want a JSValue.
114                     m_jit.sub64(GPRInfo::tagTypeNumberRegister, gpr);
115                     spillFormat = DataFormatJSDouble;
116                 } else
117                     RELEASE_ASSERT(spillFormat & DataFormatJS);
118                 break;
119             }
120             info.fillJSValue(*m_stream, gpr, spillFormat);
121         }
122         return gpr;
123     }
124
125     case DataFormatInt32: {
126         GPRReg gpr = info.gpr();
127         // If the register has already been locked we need to take a copy.
128         // If not, we'll zero extend in place, so mark on the info that this is now type DataFormatInt32, not DataFormatJSInt32.
129         if (m_gprs.isLocked(gpr)) {
130             GPRReg result = allocate();
131             m_jit.or64(GPRInfo::tagTypeNumberRegister, gpr, result);
132             return result;
133         }
134         m_gprs.lock(gpr);
135         m_jit.or64(GPRInfo::tagTypeNumberRegister, gpr);
136         info.fillJSValue(*m_stream, gpr, DataFormatJSInt32);
137         return gpr;
138     }
139
140     case DataFormatDouble: {
141         FPRReg fpr = info.fpr();
142         GPRReg gpr = boxDouble(fpr);
143
144         // Update all info
145         info.fillJSValue(*m_stream, gpr, DataFormatJSDouble);
146         m_fprs.release(fpr);
147         m_gprs.retain(gpr, virtualRegister, SpillOrderJS);
148
149         return gpr;
150     }
151         
152     case DataFormatInt52:
153     case DataFormatStrictInt52: {
154         GPRReg gpr = info.gpr();
155         lock(gpr);
156         GPRReg resultGPR = allocate();
157         boxInt52(gpr, resultGPR, info.registerFormat());
158         unlock(gpr);
159         return resultGPR;
160     }
161
162     case DataFormatCell:
163         // No retag required on JSVALUE64!
164     case DataFormatJS:
165     case DataFormatJSInt32:
166     case DataFormatJSDouble:
167     case DataFormatJSCell:
168     case DataFormatJSBoolean: {
169         GPRReg gpr = info.gpr();
170         m_gprs.lock(gpr);
171         return gpr;
172     }
173         
174     case DataFormatBoolean:
175     case DataFormatStorage:
176         // this type currently never occurs
177         RELEASE_ASSERT_NOT_REACHED();
178         
179     default:
180         RELEASE_ASSERT_NOT_REACHED();
181         return InvalidGPRReg;
182     }
183 }
184
185 void SpeculativeJIT::nonSpeculativeUInt32ToNumber(Node* node)
186 {
187     SpeculateInt32Operand op1(this, node->child1());
188     FPRTemporary boxer(this);
189     GPRTemporary result(this, Reuse, op1);
190     
191     JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, op1.gpr(), TrustedImm32(0));
192     
193     m_jit.convertInt32ToDouble(op1.gpr(), boxer.fpr());
194     m_jit.addDouble(JITCompiler::AbsoluteAddress(&AssemblyHelpers::twoToThe32), boxer.fpr());
195     
196     boxDouble(boxer.fpr(), result.gpr());
197     
198     JITCompiler::Jump done = m_jit.jump();
199     
200     positive.link(&m_jit);
201     
202     m_jit.or64(GPRInfo::tagTypeNumberRegister, op1.gpr(), result.gpr());
203     
204     done.link(&m_jit);
205     
206     jsValueResult(result.gpr(), m_currentNode);
207 }
208
209 void SpeculativeJIT::cachedGetById(CodeOrigin codeOrigin, GPRReg baseGPR, GPRReg resultGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget, SpillRegistersMode spillMode)
210 {
211     JITCompiler::DataLabelPtr structureToCompare;
212     JITCompiler::PatchableJump structureCheck = m_jit.patchableBranchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(unusedPointer)));
213     
214     JITCompiler::ConvertibleLoadLabel propertyStorageLoad =
215         m_jit.convertibleLoadPtr(JITCompiler::Address(baseGPR, JSObject::butterflyOffset()), resultGPR);
216     JITCompiler::DataLabelCompact loadWithPatch = m_jit.load64WithCompactAddressOffsetPatch(JITCompiler::Address(resultGPR, 0), resultGPR);
217     
218     JITCompiler::Label doneLabel = m_jit.label();
219
220     OwnPtr<SlowPathGenerator> slowPath;
221     if (!slowPathTarget.isSet()) {
222         slowPath = slowPathCall(
223             structureCheck.m_jump, this, operationGetByIdOptimize, resultGPR, baseGPR,
224             identifierUID(identifierNumber), spillMode);
225     } else {
226         JITCompiler::JumpList slowCases;
227         slowCases.append(structureCheck.m_jump);
228         slowCases.append(slowPathTarget);
229         slowPath = slowPathCall(
230             slowCases, this, operationGetByIdOptimize, resultGPR, baseGPR,
231             identifierUID(identifierNumber), spillMode);
232     }
233     m_jit.addPropertyAccess(
234         PropertyAccessRecord(
235             codeOrigin, structureToCompare, structureCheck, propertyStorageLoad, loadWithPatch,
236             slowPath.get(), doneLabel, safeCast<int8_t>(baseGPR), safeCast<int8_t>(resultGPR),
237             usedRegisters(),
238             spillMode == NeedToSpill ? PropertyAccessRecord::RegistersInUse : PropertyAccessRecord::RegistersFlushed));
239     addSlowPathGenerator(slowPath.release());
240 }
241
242 void SpeculativeJIT::cachedPutById(CodeOrigin codeOrigin, GPRReg baseGPR, GPRReg valueGPR, Edge valueUse, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget)
243 {
244     
245     JITCompiler::DataLabelPtr structureToCompare;
246     JITCompiler::PatchableJump structureCheck = m_jit.patchableBranchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(unusedPointer)));
247
248     writeBarrier(baseGPR, valueGPR, valueUse, WriteBarrierForPropertyAccess, scratchGPR);
249
250     JITCompiler::ConvertibleLoadLabel propertyStorageLoad =
251         m_jit.convertibleLoadPtr(JITCompiler::Address(baseGPR, JSObject::butterflyOffset()), scratchGPR);
252     JITCompiler::DataLabel32 storeWithPatch = m_jit.store64WithAddressOffsetPatch(valueGPR, JITCompiler::Address(scratchGPR, 0));
253
254     JITCompiler::Label doneLabel = m_jit.label();
255     
256     V_DFGOperation_EJCI optimizedCall;
257     if (m_jit.strictModeFor(m_currentNode->codeOrigin)) {
258         if (putKind == Direct)
259             optimizedCall = operationPutByIdDirectStrictOptimize;
260         else
261             optimizedCall = operationPutByIdStrictOptimize;
262     } else {
263         if (putKind == Direct)
264             optimizedCall = operationPutByIdDirectNonStrictOptimize;
265         else
266             optimizedCall = operationPutByIdNonStrictOptimize;
267     }
268     OwnPtr<SlowPathGenerator> slowPath;
269     if (!slowPathTarget.isSet()) {
270         slowPath = slowPathCall(
271             structureCheck.m_jump, this, optimizedCall, NoResult, valueGPR, baseGPR,
272             identifierUID(identifierNumber));
273     } else {
274         JITCompiler::JumpList slowCases;
275         slowCases.append(structureCheck.m_jump);
276         slowCases.append(slowPathTarget);
277         slowPath = slowPathCall(
278             slowCases, this, optimizedCall, NoResult, valueGPR, baseGPR,
279             identifierUID(identifierNumber));
280     }
281     RegisterSet currentlyUsedRegisters = usedRegisters();
282     currentlyUsedRegisters.clear(scratchGPR);
283     ASSERT(currentlyUsedRegisters.get(baseGPR));
284     ASSERT(currentlyUsedRegisters.get(valueGPR));
285     m_jit.addPropertyAccess(
286         PropertyAccessRecord(
287             codeOrigin, structureToCompare, structureCheck, propertyStorageLoad,
288             JITCompiler::DataLabelCompact(storeWithPatch.label()), slowPath.get(), doneLabel,
289             safeCast<int8_t>(baseGPR), safeCast<int8_t>(valueGPR), currentlyUsedRegisters));
290     addSlowPathGenerator(slowPath.release());
291 }
292
293 void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull(Edge operand, bool invert)
294 {
295     JSValueOperand arg(this, operand);
296     GPRReg argGPR = arg.gpr();
297     
298     GPRTemporary result(this, Reuse, arg);
299     GPRReg resultGPR = result.gpr();
300     
301     JITCompiler::Jump notCell;
302     
303     JITCompiler::Jump notMasqueradesAsUndefined;
304     if (masqueradesAsUndefinedWatchpointIsStillValid()) {
305         if (!isKnownCell(operand.node()))
306             notCell = m_jit.branchTest64(MacroAssembler::NonZero, argGPR, GPRInfo::tagMaskRegister);
307
308         speculationWatchpointForMasqueradesAsUndefined();
309
310         m_jit.move(invert ? TrustedImm32(1) : TrustedImm32(0), resultGPR);
311         notMasqueradesAsUndefined = m_jit.jump();
312     } else {
313         GPRTemporary localGlobalObject(this);
314         GPRTemporary remoteGlobalObject(this);
315
316         if (!isKnownCell(operand.node()))
317             notCell = m_jit.branchTest64(MacroAssembler::NonZero, argGPR, GPRInfo::tagMaskRegister);
318
319         m_jit.loadPtr(JITCompiler::Address(argGPR, JSCell::structureOffset()), resultGPR);
320         JITCompiler::Jump isMasqueradesAsUndefined = m_jit.branchTest8(JITCompiler::NonZero, JITCompiler::Address(resultGPR, Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(MasqueradesAsUndefined));
321
322         m_jit.move(invert ? TrustedImm32(1) : TrustedImm32(0), resultGPR);
323         notMasqueradesAsUndefined = m_jit.jump();
324
325         isMasqueradesAsUndefined.link(&m_jit);
326         GPRReg localGlobalObjectGPR = localGlobalObject.gpr();
327         GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr();
328         m_jit.move(JITCompiler::TrustedImmPtr(m_jit.graph().globalObjectFor(operand->codeOrigin)), localGlobalObjectGPR);
329         m_jit.loadPtr(JITCompiler::Address(resultGPR, Structure::globalObjectOffset()), remoteGlobalObjectGPR);
330         m_jit.comparePtr(invert ? JITCompiler::NotEqual : JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, resultGPR);
331     }
332  
333     if (!isKnownCell(operand.node())) {
334         JITCompiler::Jump done = m_jit.jump();
335         
336         notCell.link(&m_jit);
337         
338         m_jit.move(argGPR, resultGPR);
339         m_jit.and64(JITCompiler::TrustedImm32(~TagBitUndefined), resultGPR);
340         m_jit.compare64(invert ? JITCompiler::NotEqual : JITCompiler::Equal, resultGPR, JITCompiler::TrustedImm32(ValueNull), resultGPR);
341         
342         done.link(&m_jit);
343     }
344    
345     notMasqueradesAsUndefined.link(&m_jit);
346  
347     m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
348     jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean);
349 }
350
351 void SpeculativeJIT::nonSpeculativePeepholeBranchNull(Edge operand, Node* branchNode, bool invert)
352 {
353     BasicBlock* taken = branchNode->takenBlock();
354     BasicBlock* notTaken = branchNode->notTakenBlock();
355     
356     if (taken == nextBlock()) {
357         invert = !invert;
358         BasicBlock* tmp = taken;
359         taken = notTaken;
360         notTaken = tmp;
361     }
362
363     JSValueOperand arg(this, operand);
364     GPRReg argGPR = arg.gpr();
365     
366     GPRTemporary result(this, Reuse, arg);
367     GPRReg resultGPR = result.gpr();
368     
369     JITCompiler::Jump notCell;
370     
371     if (masqueradesAsUndefinedWatchpointIsStillValid()) {
372         if (!isKnownCell(operand.node()))
373             notCell = m_jit.branchTest64(MacroAssembler::NonZero, argGPR, GPRInfo::tagMaskRegister);
374
375         speculationWatchpointForMasqueradesAsUndefined();
376         
377         jump(invert ? taken : notTaken, ForceJump);
378     } else {
379         GPRTemporary localGlobalObject(this);
380         GPRTemporary remoteGlobalObject(this);
381
382         if (!isKnownCell(operand.node()))
383             notCell = m_jit.branchTest64(MacroAssembler::NonZero, argGPR, GPRInfo::tagMaskRegister);
384
385         m_jit.loadPtr(JITCompiler::Address(argGPR, JSCell::structureOffset()), resultGPR);
386         branchTest8(JITCompiler::Zero, JITCompiler::Address(resultGPR, Structure::typeInfoFlagsOffset()), JITCompiler::TrustedImm32(MasqueradesAsUndefined), invert ? taken : notTaken);
387
388         GPRReg localGlobalObjectGPR = localGlobalObject.gpr();
389         GPRReg remoteGlobalObjectGPR = remoteGlobalObject.gpr();
390         m_jit.move(TrustedImmPtr(m_jit.graph().globalObjectFor(operand->codeOrigin)), localGlobalObjectGPR);
391         m_jit.loadPtr(JITCompiler::Address(resultGPR, Structure::globalObjectOffset()), remoteGlobalObjectGPR);
392         branchPtr(JITCompiler::Equal, localGlobalObjectGPR, remoteGlobalObjectGPR, invert ? notTaken : taken);
393     }
394  
395     if (!isKnownCell(operand.node())) {
396         jump(notTaken, ForceJump);
397         
398         notCell.link(&m_jit);
399         
400         m_jit.move(argGPR, resultGPR);
401         m_jit.and64(JITCompiler::TrustedImm32(~TagBitUndefined), resultGPR);
402         branch64(invert ? JITCompiler::NotEqual : JITCompiler::Equal, resultGPR, JITCompiler::TrustedImm64(ValueNull), taken);
403     }
404     
405     jump(notTaken);
406 }
407
408 bool SpeculativeJIT::nonSpeculativeCompareNull(Node* node, Edge operand, bool invert)
409 {
410     unsigned branchIndexInBlock = detectPeepHoleBranch();
411     if (branchIndexInBlock != UINT_MAX) {
412         Node* branchNode = m_block->at(branchIndexInBlock);
413
414         RELEASE_ASSERT(node->adjustedRefCount() == 1);
415         
416         nonSpeculativePeepholeBranchNull(operand, branchNode, invert);
417     
418         use(node->child1());
419         use(node->child2());
420         m_indexInBlock = branchIndexInBlock;
421         m_currentNode = branchNode;
422         
423         return true;
424     }
425     
426     nonSpeculativeNonPeepholeCompareNull(operand, invert);
427     
428     return false;
429 }
430
431 void SpeculativeJIT::nonSpeculativePeepholeBranch(Node* node, Node* branchNode, MacroAssembler::RelationalCondition cond, S_DFGOperation_EJJ helperFunction)
432 {
433     BasicBlock* taken = branchNode->takenBlock();
434     BasicBlock* notTaken = branchNode->notTakenBlock();
435
436     JITCompiler::ResultCondition callResultCondition = JITCompiler::NonZero;
437
438     // The branch instruction will branch to the taken block.
439     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
440     if (taken == nextBlock()) {
441         cond = JITCompiler::invert(cond);
442         callResultCondition = JITCompiler::Zero;
443         BasicBlock* tmp = taken;
444         taken = notTaken;
445         notTaken = tmp;
446     }
447
448     JSValueOperand arg1(this, node->child1());
449     JSValueOperand arg2(this, node->child2());
450     GPRReg arg1GPR = arg1.gpr();
451     GPRReg arg2GPR = arg2.gpr();
452     
453     JITCompiler::JumpList slowPath;
454     
455     if (isKnownNotInteger(node->child1().node()) || isKnownNotInteger(node->child2().node())) {
456         GPRResult result(this);
457         GPRReg resultGPR = result.gpr();
458     
459         arg1.use();
460         arg2.use();
461     
462         flushRegisters();
463         callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);
464
465         branchTest32(callResultCondition, resultGPR, taken);
466     } else {
467         GPRTemporary result(this, Reuse, arg2);
468         GPRReg resultGPR = result.gpr();
469     
470         arg1.use();
471         arg2.use();
472     
473         if (!isKnownInteger(node->child1().node()))
474             slowPath.append(m_jit.branch64(MacroAssembler::Below, arg1GPR, GPRInfo::tagTypeNumberRegister));
475         if (!isKnownInteger(node->child2().node()))
476             slowPath.append(m_jit.branch64(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister));
477     
478         branch32(cond, arg1GPR, arg2GPR, taken);
479     
480         if (!isKnownInteger(node->child1().node()) || !isKnownInteger(node->child2().node())) {
481             jump(notTaken, ForceJump);
482     
483             slowPath.link(&m_jit);
484     
485             silentSpillAllRegisters(resultGPR);
486             callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);
487             silentFillAllRegisters(resultGPR);
488         
489             branchTest32(callResultCondition, resultGPR, taken);
490         }
491     }
492
493     jump(notTaken);
494
495     m_indexInBlock = m_block->size() - 1;
496     m_currentNode = branchNode;
497 }
498
499 template<typename JumpType>
500 class CompareAndBoxBooleanSlowPathGenerator
501     : public CallSlowPathGenerator<JumpType, S_DFGOperation_EJJ, GPRReg> {
502 public:
503     CompareAndBoxBooleanSlowPathGenerator(
504         JumpType from, SpeculativeJIT* jit,
505         S_DFGOperation_EJJ function, GPRReg result, GPRReg arg1, GPRReg arg2)
506         : CallSlowPathGenerator<JumpType, S_DFGOperation_EJJ, GPRReg>(
507             from, jit, function, NeedToSpill, result)
508         , m_arg1(arg1)
509         , m_arg2(arg2)
510     {
511     }
512     
513 protected:
514     virtual void generateInternal(SpeculativeJIT* jit)
515     {
516         this->setUp(jit);
517         this->recordCall(jit->callOperation(this->m_function, this->m_result, m_arg1, m_arg2));
518         jit->m_jit.and32(JITCompiler::TrustedImm32(1), this->m_result);
519         jit->m_jit.or32(JITCompiler::TrustedImm32(ValueFalse), this->m_result);
520         this->tearDown(jit);
521     }
522    
523 private:
524     GPRReg m_arg1;
525     GPRReg m_arg2;
526 };
527
528 void SpeculativeJIT::nonSpeculativeNonPeepholeCompare(Node* node, MacroAssembler::RelationalCondition cond, S_DFGOperation_EJJ helperFunction)
529 {
530     JSValueOperand arg1(this, node->child1());
531     JSValueOperand arg2(this, node->child2());
532     GPRReg arg1GPR = arg1.gpr();
533     GPRReg arg2GPR = arg2.gpr();
534     
535     JITCompiler::JumpList slowPath;
536     
537     if (isKnownNotInteger(node->child1().node()) || isKnownNotInteger(node->child2().node())) {
538         GPRResult result(this);
539         GPRReg resultGPR = result.gpr();
540     
541         arg1.use();
542         arg2.use();
543     
544         flushRegisters();
545         callOperation(helperFunction, resultGPR, arg1GPR, arg2GPR);
546         
547         m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
548         jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean, UseChildrenCalledExplicitly);
549     } else {
550         GPRTemporary result(this, Reuse, arg2);
551         GPRReg resultGPR = result.gpr();
552
553         arg1.use();
554         arg2.use();
555     
556         if (!isKnownInteger(node->child1().node()))
557             slowPath.append(m_jit.branch64(MacroAssembler::Below, arg1GPR, GPRInfo::tagTypeNumberRegister));
558         if (!isKnownInteger(node->child2().node()))
559             slowPath.append(m_jit.branch64(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister));
560     
561         m_jit.compare32(cond, arg1GPR, arg2GPR, resultGPR);
562         m_jit.or32(TrustedImm32(ValueFalse), resultGPR);
563         
564         if (!isKnownInteger(node->child1().node()) || !isKnownInteger(node->child2().node())) {
565             addSlowPathGenerator(adoptPtr(
566                 new CompareAndBoxBooleanSlowPathGenerator<JITCompiler::JumpList>(
567                     slowPath, this, helperFunction, resultGPR, arg1GPR, arg2GPR)));
568         }
569
570         jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean, UseChildrenCalledExplicitly);
571     }
572 }
573
574 void SpeculativeJIT::nonSpeculativePeepholeStrictEq(Node* node, Node* branchNode, bool invert)
575 {
576     BasicBlock* taken = branchNode->takenBlock();
577     BasicBlock* notTaken = branchNode->notTakenBlock();
578
579     // The branch instruction will branch to the taken block.
580     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
581     if (taken == nextBlock()) {
582         invert = !invert;
583         BasicBlock* tmp = taken;
584         taken = notTaken;
585         notTaken = tmp;
586     }
587     
588     JSValueOperand arg1(this, node->child1());
589     JSValueOperand arg2(this, node->child2());
590     GPRReg arg1GPR = arg1.gpr();
591     GPRReg arg2GPR = arg2.gpr();
592     
593     GPRTemporary result(this);
594     GPRReg resultGPR = result.gpr();
595     
596     arg1.use();
597     arg2.use();
598     
599     if (isKnownCell(node->child1().node()) && isKnownCell(node->child2().node())) {
600         // see if we get lucky: if the arguments are cells and they reference the same
601         // cell, then they must be strictly equal.
602         branch64(JITCompiler::Equal, arg1GPR, arg2GPR, invert ? notTaken : taken);
603         
604         silentSpillAllRegisters(resultGPR);
605         callOperation(operationCompareStrictEqCell, resultGPR, arg1GPR, arg2GPR);
606         silentFillAllRegisters(resultGPR);
607         
608         branchTest32(invert ? JITCompiler::Zero : JITCompiler::NonZero, resultGPR, taken);
609     } else {
610         m_jit.or64(arg1GPR, arg2GPR, resultGPR);
611         
612         JITCompiler::Jump twoCellsCase = m_jit.branchTest64(JITCompiler::Zero, resultGPR, GPRInfo::tagMaskRegister);
613         
614         JITCompiler::Jump leftOK = m_jit.branch64(JITCompiler::AboveOrEqual, arg1GPR, GPRInfo::tagTypeNumberRegister);
615         JITCompiler::Jump leftDouble = m_jit.branchTest64(JITCompiler::NonZero, arg1GPR, GPRInfo::tagTypeNumberRegister);
616         leftOK.link(&m_jit);
617         JITCompiler::Jump rightOK = m_jit.branch64(JITCompiler::AboveOrEqual, arg2GPR, GPRInfo::tagTypeNumberRegister);
618         JITCompiler::Jump rightDouble = m_jit.branchTest64(JITCompiler::NonZero, arg2GPR, GPRInfo::tagTypeNumberRegister);
619         rightOK.link(&m_jit);
620         
621         branch64(invert ? JITCompiler::NotEqual : JITCompiler::Equal, arg1GPR, arg2GPR, taken);
622         jump(notTaken, ForceJump);
623         
624         twoCellsCase.link(&m_jit);
625         branch64(JITCompiler::Equal, arg1GPR, arg2GPR, invert ? notTaken : taken);
626         
627         leftDouble.link(&m_jit);
628         rightDouble.link(&m_jit);
629         
630         silentSpillAllRegisters(resultGPR);
631         callOperation(operationCompareStrictEq, resultGPR, arg1GPR, arg2GPR);
632         silentFillAllRegisters(resultGPR);
633         
634         branchTest32(invert ? JITCompiler::Zero : JITCompiler::NonZero, resultGPR, taken);
635     }
636     
637     jump(notTaken);
638 }
639
640 void SpeculativeJIT::nonSpeculativeNonPeepholeStrictEq(Node* node, bool invert)
641 {
642     JSValueOperand arg1(this, node->child1());
643     JSValueOperand arg2(this, node->child2());
644     GPRReg arg1GPR = arg1.gpr();
645     GPRReg arg2GPR = arg2.gpr();
646     
647     GPRTemporary result(this);
648     GPRReg resultGPR = result.gpr();
649     
650     arg1.use();
651     arg2.use();
652     
653     if (isKnownCell(node->child1().node()) && isKnownCell(node->child2().node())) {
654         // see if we get lucky: if the arguments are cells and they reference the same
655         // cell, then they must be strictly equal.
656         // FIXME: this should flush registers instead of silent spill/fill.
657         JITCompiler::Jump notEqualCase = m_jit.branch64(JITCompiler::NotEqual, arg1GPR, arg2GPR);
658         
659         m_jit.move(JITCompiler::TrustedImm64(JSValue::encode(jsBoolean(!invert))), resultGPR);
660         
661         JITCompiler::Jump done = m_jit.jump();
662
663         notEqualCase.link(&m_jit);
664         
665         silentSpillAllRegisters(resultGPR);
666         callOperation(operationCompareStrictEqCell, resultGPR, arg1GPR, arg2GPR);
667         silentFillAllRegisters(resultGPR);
668         
669         m_jit.and64(JITCompiler::TrustedImm32(1), resultGPR);
670         m_jit.or32(JITCompiler::TrustedImm32(ValueFalse), resultGPR);
671         
672         done.link(&m_jit);
673     } else {
674         m_jit.or64(arg1GPR, arg2GPR, resultGPR);
675         
676         JITCompiler::JumpList slowPathCases;
677         
678         JITCompiler::Jump twoCellsCase = m_jit.branchTest64(JITCompiler::Zero, resultGPR, GPRInfo::tagMaskRegister);
679         
680         JITCompiler::Jump leftOK = m_jit.branch64(JITCompiler::AboveOrEqual, arg1GPR, GPRInfo::tagTypeNumberRegister);
681         slowPathCases.append(m_jit.branchTest64(JITCompiler::NonZero, arg1GPR, GPRInfo::tagTypeNumberRegister));
682         leftOK.link(&m_jit);
683         JITCompiler::Jump rightOK = m_jit.branch64(JITCompiler::AboveOrEqual, arg2GPR, GPRInfo::tagTypeNumberRegister);
684         slowPathCases.append(m_jit.branchTest64(JITCompiler::NonZero, arg2GPR, GPRInfo::tagTypeNumberRegister));
685         rightOK.link(&m_jit);
686         
687         m_jit.compare64(invert ? JITCompiler::NotEqual : JITCompiler::Equal, arg1GPR, arg2GPR, resultGPR);
688         m_jit.or32(JITCompiler::TrustedImm32(ValueFalse), resultGPR);
689         
690         JITCompiler::Jump done = m_jit.jump();
691         
692         twoCellsCase.link(&m_jit);
693         slowPathCases.append(m_jit.branch64(JITCompiler::NotEqual, arg1GPR, arg2GPR));
694         
695         m_jit.move(JITCompiler::TrustedImm64(JSValue::encode(jsBoolean(!invert))), resultGPR);
696         
697         addSlowPathGenerator(
698             adoptPtr(
699                 new CompareAndBoxBooleanSlowPathGenerator<MacroAssembler::JumpList>(
700                     slowPathCases, this, operationCompareStrictEq, resultGPR, arg1GPR,
701                     arg2GPR)));
702         
703         done.link(&m_jit);
704     }
705     
706     jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean, UseChildrenCalledExplicitly);
707 }
708
709 void SpeculativeJIT::emitCall(Node* node)
710 {
711     if (node->op() != Call)
712         RELEASE_ASSERT(node->op() == Construct);
713
714     // For constructors, the this argument is not passed but we have to make space
715     // for it.
716     int dummyThisArgument = node->op() == Call ? 0 : 1;
717     
718     CallLinkInfo::CallType callType = node->op() == Call ? CallLinkInfo::Call : CallLinkInfo::Construct;
719     
720     Edge calleeEdge = m_jit.graph().m_varArgChildren[node->firstChild()];
721     JSValueOperand callee(this, calleeEdge);
722     GPRReg calleeGPR = callee.gpr();
723     use(calleeEdge);
724     
725     // The call instruction's first child is the function; the subsequent children are the
726     // arguments.
727     int numPassedArgs = node->numChildren() - 1;
728     
729     m_jit.store32(MacroAssembler::TrustedImm32(numPassedArgs + dummyThisArgument), callFramePayloadSlot(JSStack::ArgumentCount));
730     m_jit.store64(GPRInfo::callFrameRegister, callFrameSlot(JSStack::CallerFrame));
731     m_jit.store64(calleeGPR, callFrameSlot(JSStack::Callee));
732     
733     for (int i = 0; i < numPassedArgs; i++) {
734         Edge argEdge = m_jit.graph().m_varArgChildren[node->firstChild() + 1 + i];
735         JSValueOperand arg(this, argEdge);
736         GPRReg argGPR = arg.gpr();
737         use(argEdge);
738         
739         m_jit.store64(argGPR, argumentSlot(i + dummyThisArgument));
740     }
741
742     flushRegisters();
743
744     GPRResult result(this);
745     GPRReg resultGPR = result.gpr();
746
747     JITCompiler::DataLabelPtr targetToCheck;
748     JITCompiler::JumpList slowPath;
749
750     CallBeginToken token;
751     m_jit.beginCall(node->codeOrigin, token);
752     
753     m_jit.addPtr(TrustedImm32(-(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register))), GPRInfo::callFrameRegister);
754     
755     slowPath.append(m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleeGPR, targetToCheck, MacroAssembler::TrustedImmPtr(0)));
756
757     m_jit.loadPtr(MacroAssembler::Address(calleeGPR, OBJECT_OFFSETOF(JSFunction, m_scope)), resultGPR);
758     m_jit.store64(resultGPR, MacroAssembler::Address(GPRInfo::callFrameRegister, static_cast<ptrdiff_t>(sizeof(Register)) * JSStack::ScopeChain));
759
760     CodeOrigin codeOrigin = m_currentNode->codeOrigin;
761     JITCompiler::Call fastCall = m_jit.nearCall();
762     m_jit.notifyCall(fastCall, codeOrigin, token);
763     
764     JITCompiler::Jump done = m_jit.jump();
765     
766     slowPath.link(&m_jit);
767     
768     m_jit.move(calleeGPR, GPRInfo::nonArgGPR0);
769     m_jit.prepareForExceptionCheck();
770     JITCompiler::Call slowCall = m_jit.nearCall();
771     m_jit.notifyCall(slowCall, codeOrigin, token);
772     
773     done.link(&m_jit);
774     
775     m_jit.move(GPRInfo::returnValueGPR, resultGPR);
776     
777     jsValueResult(resultGPR, m_currentNode, DataFormatJS, UseChildrenCalledExplicitly);
778     
779     m_jit.addJSCall(fastCall, slowCall, targetToCheck, callType, calleeGPR, m_currentNode->codeOrigin);
780 }
781
782 template<bool strict>
783 GPRReg SpeculativeJIT::fillSpeculateInt32Internal(Edge edge, DataFormat& returnFormat)
784 {
785 #if DFG_ENABLE(DEBUG_VERBOSE)
786     dataLogF("SpecInt@%d   ", edge->index());
787 #endif
788     AbstractValue& value = m_state.forNode(edge);
789     SpeculatedType type = value.m_type;
790     ASSERT(edge.useKind() != KnownInt32Use || !(value.m_type & ~SpecInt32));
791     m_interpreter.filter(value, SpecInt32);
792     VirtualRegister virtualRegister = edge->virtualRegister();
793     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
794
795     switch (info.registerFormat()) {
796     case DataFormatNone: {
797         if ((edge->hasConstant() && !isInt32Constant(edge.node())) || info.spillFormat() == DataFormatDouble) {
798             terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
799             returnFormat = DataFormatInt32;
800             return allocate();
801         }
802         
803         GPRReg gpr = allocate();
804
805         if (edge->hasConstant()) {
806             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
807             ASSERT(isInt32Constant(edge.node()));
808             m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(edge.node())), gpr);
809             info.fillInt32(*m_stream, gpr);
810             returnFormat = DataFormatInt32;
811             return gpr;
812         }
813         
814         DataFormat spillFormat = info.spillFormat();
815         
816         RELEASE_ASSERT((spillFormat & DataFormatJS) || spillFormat == DataFormatInt32 || spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52);
817         
818         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
819         
820         if (spillFormat == DataFormatJSInt32 || spillFormat == DataFormatInt32) {
821             // If we know this was spilled as an integer we can fill without checking.
822             if (strict) {
823                 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
824                 info.fillInt32(*m_stream, gpr);
825                 returnFormat = DataFormatInt32;
826                 return gpr;
827             }
828             if (spillFormat == DataFormatInt32) {
829                 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
830                 m_jit.or64(GPRInfo::tagTypeNumberRegister, gpr);
831             } else
832                 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
833             info.fillJSValue(*m_stream, gpr, DataFormatJSInt32);
834             returnFormat = DataFormatJSInt32;
835             return gpr;
836         }
837         if (spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52) {
838             // Generally, this can only happen if we've already proved that the
839             // value is an int32. That's because if a value originated as a JSValue
840             // then we would speculate that it's an int32 before representing it as
841             // an int52. Otherwise, if we knowingly produced an int52, then we would
842             // be boxing it into a value using Int52ToValue. This assertion is valid
843             // only because Int52 is something that we introduce at prediction time.
844             // However: we may have an int32-producing node replaced by an
845             // int52-producing node due to CSE. So we must do a check.
846             RELEASE_ASSERT(!(type & ~SpecMachineInt));
847             if (type & SpecInt52) {
848                 GPRReg temp = allocate();
849                 m_jit.signExtend32ToPtr(gpr, temp);
850                 // Currently, we can't supply value profiling information here. :-/
851                 speculationCheck(
852                     BadType, JSValueRegs(), 0,
853                     m_jit.branch64(MacroAssembler::NotEqual, gpr, temp));
854                 unlock(temp);
855             }
856             if (spillFormat == DataFormatStrictInt52)
857                 m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
858             else {
859                 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
860                 m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
861                 m_jit.zeroExtend32ToPtr(gpr, gpr);
862             }
863             info.fillInt32(*m_stream, gpr);
864             returnFormat = DataFormatInt32;
865             return gpr;
866         }
867         m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
868
869         // Fill as JSValue, and fall through.
870         info.fillJSValue(*m_stream, gpr, DataFormatJSInt32);
871         m_gprs.unlock(gpr);
872     }
873
874     case DataFormatJS: {
875         RELEASE_ASSERT(!(type & SpecInt52));
876         // Check the value is an integer.
877         GPRReg gpr = info.gpr();
878         m_gprs.lock(gpr);
879         if (type & ~SpecInt32)
880             speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branch64(MacroAssembler::Below, gpr, GPRInfo::tagTypeNumberRegister));
881         info.fillJSValue(*m_stream, gpr, DataFormatJSInt32);
882         // If !strict we're done, return.
883         if (!strict) {
884             returnFormat = DataFormatJSInt32;
885             return gpr;
886         }
887         // else fall through & handle as DataFormatJSInt32.
888         m_gprs.unlock(gpr);
889     }
890
891     case DataFormatJSInt32: {
892         // In a strict fill we need to strip off the value tag.
893         if (strict) {
894             GPRReg gpr = info.gpr();
895             GPRReg result;
896             // If the register has already been locked we need to take a copy.
897             // If not, we'll zero extend in place, so mark on the info that this is now type DataFormatInt32, not DataFormatJSInt32.
898             if (m_gprs.isLocked(gpr))
899                 result = allocate();
900             else {
901                 m_gprs.lock(gpr);
902                 info.fillInt32(*m_stream, gpr);
903                 result = gpr;
904             }
905             m_jit.zeroExtend32ToPtr(gpr, result);
906             returnFormat = DataFormatInt32;
907             return result;
908         }
909
910         GPRReg gpr = info.gpr();
911         m_gprs.lock(gpr);
912         returnFormat = DataFormatJSInt32;
913         return gpr;
914     }
915
916     case DataFormatInt32: {
917         GPRReg gpr = info.gpr();
918         m_gprs.lock(gpr);
919         returnFormat = DataFormatInt32;
920         return gpr;
921     }
922         
923     case DataFormatStrictInt52:
924     case DataFormatInt52: {
925         GPRReg gpr = info.gpr();
926         GPRReg result;
927         if (m_gprs.isLocked(gpr)) {
928             result = allocate();
929             m_jit.move(gpr, result);
930         } else {
931             lock(gpr);
932             info.fillInt32(*m_stream, gpr);
933             result = gpr;
934         }
935         RELEASE_ASSERT(!(type & ~SpecMachineInt));
936         if (info.registerFormat() == DataFormatInt52)
937             m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), result);
938         if (type & SpecInt52) {
939             GPRReg temp = allocate();
940             m_jit.signExtend32ToPtr(result, temp);
941             // Currently, we can't supply value profiling information here. :-/
942             speculationCheck(
943                 BadType, JSValueRegs(), 0,
944                 m_jit.branch64(MacroAssembler::NotEqual, result, temp));
945             unlock(temp);
946         }
947         m_jit.zeroExtend32ToPtr(result, result);
948         returnFormat = DataFormatInt32;
949         return gpr;
950     }
951
952     case DataFormatDouble:
953     case DataFormatJSDouble: {
954         if (edge->hasConstant() && isInt32Constant(edge.node())) {
955             GPRReg gpr = allocate();
956             ASSERT(isInt32Constant(edge.node()));
957             m_jit.move(MacroAssembler::Imm32(valueOfInt32Constant(edge.node())), gpr);
958             returnFormat = DataFormatInt32;
959             return gpr;
960         }
961     }
962     case DataFormatCell:
963     case DataFormatBoolean:
964     case DataFormatJSCell:
965     case DataFormatJSBoolean: {
966         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
967         returnFormat = DataFormatInt32;
968         return allocate();
969     }
970
971     case DataFormatStorage:
972         RELEASE_ASSERT_NOT_REACHED();
973         
974     default:
975         RELEASE_ASSERT_NOT_REACHED();
976         return InvalidGPRReg;
977     }
978 }
979
980 GPRReg SpeculativeJIT::fillSpeculateInt32(Edge edge, DataFormat& returnFormat)
981 {
982     return fillSpeculateInt32Internal<false>(edge, returnFormat);
983 }
984
985 GPRReg SpeculativeJIT::fillSpeculateInt32Strict(Edge edge)
986 {
987     DataFormat mustBeDataFormatInt32;
988     GPRReg result = fillSpeculateInt32Internal<true>(edge, mustBeDataFormatInt32);
989     RELEASE_ASSERT(mustBeDataFormatInt32 == DataFormatInt32);
990     return result;
991 }
992
993 GPRReg SpeculativeJIT::fillSpeculateInt52(Edge edge, DataFormat desiredFormat)
994 {
995     ASSERT(desiredFormat == DataFormatInt52 || desiredFormat == DataFormatStrictInt52);
996     AbstractValue& value = m_state.forNode(edge);
997     SpeculatedType type = value.m_type;
998     m_interpreter.filter(value, SpecMachineInt);
999     VirtualRegister virtualRegister = edge->virtualRegister();
1000     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1001
1002     switch (info.registerFormat()) {
1003     case DataFormatNone: {
1004         if ((edge->hasConstant() && !valueOfJSConstant(edge.node()).isMachineInt()) || info.spillFormat() == DataFormatDouble) {
1005             terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1006             return allocate();
1007         }
1008         
1009         GPRReg gpr = allocate();
1010
1011         if (edge->hasConstant()) {
1012             JSValue jsValue = valueOfJSConstant(edge.node());
1013             ASSERT(jsValue.isMachineInt());
1014             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1015             int64_t value = jsValue.asMachineInt();
1016             if (desiredFormat == DataFormatInt52)
1017                 value = value << JSValue::int52ShiftAmount;
1018             m_jit.move(MacroAssembler::Imm64(value), gpr);
1019             info.fillGPR(*m_stream, gpr, desiredFormat);
1020             return gpr;
1021         }
1022         
1023         DataFormat spillFormat = info.spillFormat();
1024         
1025         RELEASE_ASSERT((spillFormat & DataFormatJS) || spillFormat == DataFormatInt32 || spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52);
1026         
1027         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1028         
1029         if (spillFormat == DataFormatJSInt32 || spillFormat == DataFormatInt32) {
1030             // If we know this was spilled as an integer we can fill without checking.
1031             m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
1032             m_jit.signExtend32ToPtr(gpr, gpr);
1033             if (desiredFormat == DataFormatStrictInt52) {
1034                 info.fillStrictInt52(*m_stream, gpr);
1035                 return gpr;
1036             }
1037             m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
1038             info.fillInt52(*m_stream, gpr);
1039             return gpr;
1040         }
1041         if (spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52) {
1042             m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1043             if (desiredFormat == DataFormatStrictInt52) {
1044                 if (spillFormat == DataFormatInt52)
1045                     m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
1046                 info.fillStrictInt52(*m_stream, gpr);
1047                 return gpr;
1048             }
1049             if (spillFormat == DataFormatStrictInt52)
1050                 m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
1051             info.fillInt52(*m_stream, gpr);
1052             return gpr;
1053         }
1054         m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1055
1056         // Fill as JSValue, and fall through.
1057         info.fillJSValue(*m_stream, gpr, DataFormatJSInt32);
1058         m_gprs.unlock(gpr);
1059     }
1060
1061     case DataFormatJS: {
1062         // Check the value is an integer. Note that we would *like* to unbox an Int52
1063         // at this point but this is too costly. We only *prove* that this is an Int52
1064         // even though we check if it's an int32.
1065         GPRReg gpr = info.gpr();
1066         GPRReg result;
1067         if (m_gprs.isLocked(gpr)) {
1068             result = allocate();
1069             m_jit.move(gpr, result);
1070         } else {
1071             m_gprs.lock(gpr);
1072             result = gpr;
1073         }
1074         if (type & ~SpecInt32)
1075             speculationCheck(BadType, JSValueRegs(result), edge, m_jit.branch64(MacroAssembler::Below, result, GPRInfo::tagTypeNumberRegister));
1076         if (result == gpr) // The not-already-locked, so fill in-place, case.
1077             info.fillInt52(*m_stream, gpr, desiredFormat);
1078         m_jit.signExtend32ToPtr(result, result);
1079         if (desiredFormat == DataFormatInt52)
1080             m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), result);
1081         return result;
1082     }
1083
1084     case DataFormatInt32:
1085     case DataFormatJSInt32: {
1086         GPRReg gpr = info.gpr();
1087         GPRReg result;
1088         if (m_gprs.isLocked(gpr)) {
1089             result = allocate();
1090             m_jit.move(gpr, result);
1091         } else {
1092             m_gprs.lock(gpr);
1093             info.fillInt52(*m_stream, gpr, desiredFormat);
1094             result = gpr;
1095         }
1096         m_jit.signExtend32ToPtr(result, result);
1097         if (desiredFormat == DataFormatInt52)
1098             m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), result);
1099         return result;
1100     }
1101
1102     case DataFormatStrictInt52: {
1103         GPRReg gpr = info.gpr();
1104         bool wasLocked = m_gprs.isLocked(gpr);
1105         lock(gpr);
1106         if (desiredFormat == DataFormatStrictInt52)
1107             return gpr;
1108         if (wasLocked) {
1109             GPRReg result = allocate();
1110             m_jit.move(gpr, result);
1111             unlock(gpr);
1112             gpr = result;
1113         } else
1114             info.fillStrictInt52(*m_stream, gpr);
1115         m_jit.lshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
1116         return gpr;
1117     }
1118         
1119     case DataFormatInt52: {
1120         GPRReg gpr = info.gpr();
1121         bool wasLocked = m_gprs.isLocked(gpr);
1122         lock(gpr);
1123         if (desiredFormat == DataFormatInt52)
1124             return gpr;
1125         if (wasLocked) {
1126             GPRReg result = allocate();
1127             m_jit.move(gpr, result);
1128             unlock(gpr);
1129             gpr = result;
1130         } else
1131             info.fillInt52(*m_stream, gpr);
1132         m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), gpr);
1133         return gpr;
1134     }
1135
1136     case DataFormatDouble:
1137     case DataFormatJSDouble:
1138         if (edge->hasConstant()) {
1139             JSValue jsValue = valueOfJSConstant(edge.node());
1140             if (jsValue.isMachineInt()) {
1141                 int64_t value = jsValue.asMachineInt();
1142                 if (desiredFormat == DataFormatInt52)
1143                     value = value << JSValue::int52ShiftAmount;
1144                 GPRReg gpr = allocate();
1145                 m_jit.move(MacroAssembler::Imm64(value), gpr);
1146                 return gpr;
1147             }
1148         }
1149         
1150     case DataFormatCell:
1151     case DataFormatBoolean:
1152     case DataFormatJSCell:
1153     case DataFormatJSBoolean: {
1154         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1155         return allocate();
1156     }
1157
1158     case DataFormatStorage:
1159         RELEASE_ASSERT_NOT_REACHED();
1160         
1161     default:
1162         RELEASE_ASSERT_NOT_REACHED();
1163         return InvalidGPRReg;
1164     }
1165 }
1166
1167 FPRReg SpeculativeJIT::fillSpeculateDouble(Edge edge)
1168 {
1169 #if DFG_ENABLE(DEBUG_VERBOSE)
1170     dataLogF("SpecDouble@%d   ", edge->index());
1171 #endif
1172     AbstractValue& value = m_state.forNode(edge);
1173     SpeculatedType type = value.m_type;
1174     ASSERT(edge.useKind() != KnownNumberUse || !(value.m_type & ~SpecFullNumber));
1175     m_interpreter.filter(value, SpecFullNumber);
1176     VirtualRegister virtualRegister = edge->virtualRegister();
1177     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1178
1179     if (info.registerFormat() == DataFormatNone) {
1180         if (edge->hasConstant()) {
1181             GPRReg gpr = allocate();
1182
1183             if (isInt32Constant(edge.node())) {
1184                 FPRReg fpr = fprAllocate();
1185                 m_jit.move(MacroAssembler::Imm64(reinterpretDoubleToInt64(static_cast<double>(valueOfInt32Constant(edge.node())))), gpr);
1186                 m_jit.move64ToDouble(gpr, fpr);
1187                 unlock(gpr);
1188
1189                 // Don't fill double here since that will lead to confusion: the
1190                 // register allocator will now think that this is a double while
1191                 // everyone else thinks it's an integer.
1192                 return fpr;
1193             }
1194             if (isNumberConstant(edge.node())) {
1195                 FPRReg fpr = fprAllocate();
1196                 m_jit.move(MacroAssembler::Imm64(reinterpretDoubleToInt64(valueOfNumberConstant(edge.node()))), gpr);
1197                 m_jit.move64ToDouble(gpr, fpr);
1198                 unlock(gpr);
1199
1200                 m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
1201                 info.fillDouble(*m_stream, fpr);
1202                 return fpr;
1203             }
1204             terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1205             return fprAllocate();
1206         }
1207         
1208         DataFormat spillFormat = info.spillFormat();
1209         switch (spillFormat) {
1210         case DataFormatDouble: {
1211             FPRReg fpr = fprAllocate();
1212             m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
1213             m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
1214             info.fillDouble(*m_stream, fpr);
1215             return fpr;
1216         }
1217             
1218         case DataFormatInt32: {
1219             GPRReg gpr = allocate();
1220             
1221             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1222             m_jit.load32(JITCompiler::addressFor(virtualRegister), gpr);
1223             info.fillInt32(*m_stream, gpr);
1224             unlock(gpr);
1225             break;
1226         }
1227             
1228         case DataFormatInt52: {
1229             GPRReg gpr = allocate();
1230             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1231             m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1232             info.fillInt52(*m_stream, gpr);
1233             unlock(gpr);
1234             break;
1235         }
1236             
1237         case DataFormatStrictInt52: {
1238             GPRReg gpr = allocate();
1239             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1240             m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1241             info.fillStrictInt52(*m_stream, gpr);
1242             unlock(gpr);
1243             break;
1244         }
1245
1246         default:
1247             GPRReg gpr = allocate();
1248
1249             RELEASE_ASSERT(spillFormat & DataFormatJS);
1250             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1251             m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1252             info.fillJSValue(*m_stream, gpr, spillFormat);
1253             unlock(gpr);
1254             break;
1255         }
1256     }
1257
1258     switch (info.registerFormat()) {
1259     case DataFormatNone: // Should have filled, above.
1260     case DataFormatBoolean: // This type never occurs.
1261     case DataFormatStorage:
1262         RELEASE_ASSERT_NOT_REACHED();
1263
1264     case DataFormatCell:
1265         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1266         return fprAllocate();
1267
1268     case DataFormatJSCell:
1269     case DataFormatJS:
1270     case DataFormatJSBoolean: {
1271         GPRReg jsValueGpr = info.gpr();
1272         m_gprs.lock(jsValueGpr);
1273         FPRReg fpr = fprAllocate();
1274         GPRReg tempGpr = allocate();
1275
1276         JITCompiler::Jump isInteger = m_jit.branch64(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);
1277
1278         if (type & ~SpecFullNumber)
1279             speculationCheck(BadType, JSValueRegs(jsValueGpr), edge, m_jit.branchTest64(MacroAssembler::Zero, jsValueGpr, GPRInfo::tagTypeNumberRegister));
1280
1281         // First, if we get here we have a double encoded as a JSValue
1282         m_jit.move(jsValueGpr, tempGpr);
1283         unboxDouble(tempGpr, fpr);
1284         JITCompiler::Jump hasUnboxedDouble = m_jit.jump();
1285
1286         // Finally, handle integers.
1287         isInteger.link(&m_jit);
1288         m_jit.convertInt32ToDouble(jsValueGpr, fpr);
1289         hasUnboxedDouble.link(&m_jit);
1290
1291         m_gprs.release(jsValueGpr);
1292         m_gprs.unlock(jsValueGpr);
1293         m_gprs.unlock(tempGpr);
1294         m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
1295         info.fillDouble(*m_stream, fpr);
1296         info.killSpilled();
1297         return fpr;
1298     }
1299
1300     case DataFormatJSInt32:
1301     case DataFormatInt32: {
1302         FPRReg fpr = fprAllocate();
1303         GPRReg gpr = info.gpr();
1304         m_gprs.lock(gpr);
1305         m_jit.convertInt32ToDouble(gpr, fpr);
1306         m_gprs.unlock(gpr);
1307         return fpr;
1308     }
1309         
1310     case DataFormatInt52: {
1311         FPRReg fpr = fprAllocate();
1312         GPRReg gpr = info.gpr();
1313         m_gprs.lock(gpr);
1314         GPRReg temp = allocate();
1315         m_jit.move(gpr, temp);
1316         m_jit.rshift64(TrustedImm32(JSValue::int52ShiftAmount), temp);
1317         m_jit.convertInt64ToDouble(temp, fpr);
1318         unlock(temp);
1319         m_gprs.unlock(gpr);
1320         return fpr;
1321     }
1322         
1323     case DataFormatStrictInt52: {
1324         FPRReg fpr = fprAllocate();
1325         GPRReg gpr = info.gpr();
1326         m_gprs.lock(gpr);
1327         m_jit.convertInt64ToDouble(gpr, fpr);
1328         m_gprs.unlock(gpr);
1329         return fpr;
1330     }
1331
1332     // Unbox the double
1333     case DataFormatJSDouble: {
1334         GPRReg gpr = info.gpr();
1335         FPRReg fpr = fprAllocate();
1336         if (m_gprs.isLocked(gpr)) {
1337             // Make sure we don't trample gpr if it is in use.
1338             GPRReg temp = allocate();
1339             m_jit.move(gpr, temp);
1340             unboxDouble(temp, fpr);
1341             unlock(temp);
1342         } else
1343             unboxDouble(gpr, fpr);
1344
1345         m_gprs.release(gpr);
1346         m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
1347
1348         info.fillDouble(*m_stream, fpr);
1349         return fpr;
1350     }
1351
1352     case DataFormatDouble: {
1353         FPRReg fpr = info.fpr();
1354         m_fprs.lock(fpr);
1355         return fpr;
1356     }
1357         
1358     default:
1359         RELEASE_ASSERT_NOT_REACHED();
1360         return InvalidFPRReg;
1361     }
1362 }
1363
1364 GPRReg SpeculativeJIT::fillSpeculateCell(Edge edge)
1365 {
1366 #if DFG_ENABLE(DEBUG_VERBOSE)
1367     dataLogF("SpecCell@%d   ", edge->index());
1368 #endif
1369     AbstractValue& value = m_state.forNode(edge);
1370     SpeculatedType type = value.m_type;
1371     ASSERT((edge.useKind() != KnownCellUse && edge.useKind() != KnownStringUse) || !(value.m_type & ~SpecCell));
1372     m_interpreter.filter(value, SpecCell);
1373     VirtualRegister virtualRegister = edge->virtualRegister();
1374     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1375
1376     switch (info.registerFormat()) {
1377     case DataFormatNone: {
1378         if (info.spillFormat() == DataFormatInt32 || info.spillFormat() == DataFormatDouble) {
1379             terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1380             return allocate();
1381         }
1382         
1383         GPRReg gpr = allocate();
1384
1385         if (edge->hasConstant()) {
1386             JSValue jsValue = valueOfJSConstant(edge.node());
1387             if (jsValue.isCell()) {
1388                 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1389                 m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsValue)), gpr);
1390                 info.fillJSValue(*m_stream, gpr, DataFormatJSCell);
1391                 return gpr;
1392             }
1393             terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1394             return gpr;
1395         }
1396         RELEASE_ASSERT(info.spillFormat() & DataFormatJS);
1397         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1398         m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1399
1400         info.fillJSValue(*m_stream, gpr, DataFormatJS);
1401         if (type & ~SpecCell)
1402             speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchTest64(MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister));
1403         info.fillJSValue(*m_stream, gpr, DataFormatJSCell);
1404         return gpr;
1405     }
1406
1407     case DataFormatCell:
1408     case DataFormatJSCell: {
1409         GPRReg gpr = info.gpr();
1410         m_gprs.lock(gpr);
1411 #if DFG_ENABLE(JIT_ASSERT)
1412         MacroAssembler::Jump checkCell = m_jit.branchTest64(MacroAssembler::Zero, gpr, GPRInfo::tagMaskRegister);
1413         m_jit.breakpoint();
1414         checkCell.link(&m_jit);
1415 #endif
1416         return gpr;
1417     }
1418
1419     case DataFormatJS: {
1420         GPRReg gpr = info.gpr();
1421         m_gprs.lock(gpr);
1422         if (type & ~SpecCell)
1423             speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchTest64(MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister));
1424         info.fillJSValue(*m_stream, gpr, DataFormatJSCell);
1425         return gpr;
1426     }
1427
1428     case DataFormatJSInt32:
1429     case DataFormatInt32:
1430     case DataFormatJSDouble:
1431     case DataFormatDouble:
1432     case DataFormatJSBoolean:
1433     case DataFormatBoolean:
1434     case DataFormatInt52:
1435     case DataFormatStrictInt52: {
1436         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1437         return allocate();
1438     }
1439
1440     case DataFormatStorage:
1441         RELEASE_ASSERT_NOT_REACHED();
1442         
1443     default:
1444         RELEASE_ASSERT_NOT_REACHED();
1445         return InvalidGPRReg;
1446     }
1447 }
1448
1449 GPRReg SpeculativeJIT::fillSpeculateBoolean(Edge edge)
1450 {
1451 #if DFG_ENABLE(DEBUG_VERBOSE)
1452     dataLogF("SpecBool@%d   ", edge->index());
1453 #endif
1454     AbstractValue& value = m_state.forNode(edge);
1455     SpeculatedType type = value.m_type;
1456     m_interpreter.filter(value, SpecBoolean);
1457     VirtualRegister virtualRegister = edge->virtualRegister();
1458     GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
1459
1460     switch (info.registerFormat()) {
1461     case DataFormatNone: {
1462         if (info.spillFormat() == DataFormatInt32 || info.spillFormat() == DataFormatDouble) {
1463             terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1464             return allocate();
1465         }
1466         
1467         GPRReg gpr = allocate();
1468
1469         if (edge->hasConstant()) {
1470             JSValue jsValue = valueOfJSConstant(edge.node());
1471             if (jsValue.isBoolean()) {
1472                 m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
1473                 m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsValue)), gpr);
1474                 info.fillJSValue(*m_stream, gpr, DataFormatJSBoolean);
1475                 return gpr;
1476             }
1477             terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1478             return gpr;
1479         }
1480         RELEASE_ASSERT(info.spillFormat() & DataFormatJS);
1481         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
1482         m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
1483
1484         info.fillJSValue(*m_stream, gpr, DataFormatJS);
1485         if (type & ~SpecBoolean) {
1486             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1487             speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchTest64(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg));
1488             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1489         }
1490         info.fillJSValue(*m_stream, gpr, DataFormatJSBoolean);
1491         return gpr;
1492     }
1493
1494     case DataFormatBoolean:
1495     case DataFormatJSBoolean: {
1496         GPRReg gpr = info.gpr();
1497         m_gprs.lock(gpr);
1498         return gpr;
1499     }
1500
1501     case DataFormatJS: {
1502         GPRReg gpr = info.gpr();
1503         m_gprs.lock(gpr);
1504         if (type & ~SpecBoolean) {
1505             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1506             speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchTest64(MacroAssembler::NonZero, gpr, TrustedImm32(static_cast<int32_t>(~1))), SpeculationRecovery(BooleanSpeculationCheck, gpr, InvalidGPRReg));
1507             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), gpr);
1508         }
1509         info.fillJSValue(*m_stream, gpr, DataFormatJSBoolean);
1510         return gpr;
1511     }
1512
1513     case DataFormatJSInt32:
1514     case DataFormatInt32:
1515     case DataFormatJSDouble:
1516     case DataFormatDouble:
1517     case DataFormatJSCell:
1518     case DataFormatCell:
1519     case DataFormatInt52:
1520     case DataFormatStrictInt52: {
1521         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
1522         return allocate();
1523     }
1524         
1525     case DataFormatStorage:
1526         RELEASE_ASSERT_NOT_REACHED();
1527         
1528     default:
1529         RELEASE_ASSERT_NOT_REACHED();
1530         return InvalidGPRReg;
1531     }
1532 }
1533
1534 JITCompiler::Jump SpeculativeJIT::convertToDouble(GPRReg value, FPRReg result, GPRReg tmp)
1535 {
1536     JITCompiler::Jump isInteger = m_jit.branch64(MacroAssembler::AboveOrEqual, value, GPRInfo::tagTypeNumberRegister);
1537     
1538     JITCompiler::Jump notNumber = m_jit.branchTest64(MacroAssembler::Zero, value, GPRInfo::tagTypeNumberRegister);
1539     
1540     m_jit.move(value, tmp);
1541     unboxDouble(tmp, result);
1542     
1543     JITCompiler::Jump done = m_jit.jump();
1544     
1545     isInteger.link(&m_jit);
1546     
1547     m_jit.convertInt32ToDouble(value, result);
1548     
1549     done.link(&m_jit);
1550
1551     return notNumber;
1552 }
1553
1554 void SpeculativeJIT::compileObjectEquality(Node* node)
1555 {
1556     SpeculateCellOperand op1(this, node->child1());
1557     SpeculateCellOperand op2(this, node->child2());
1558     GPRTemporary result(this, Reuse, op1);
1559     
1560     GPRReg op1GPR = op1.gpr();
1561     GPRReg op2GPR = op2.gpr();
1562     GPRReg resultGPR = result.gpr();
1563    
1564     if (masqueradesAsUndefinedWatchpointIsStillValid()) {
1565         speculationWatchpointForMasqueradesAsUndefined();
1566         DFG_TYPE_CHECK(
1567             JSValueSource::unboxedCell(op1GPR), node->child1(), SpecObject, m_jit.branchPtr(
1568                 MacroAssembler::Equal, 
1569                 MacroAssembler::Address(op1GPR, JSCell::structureOffset()), 
1570                 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1571         DFG_TYPE_CHECK(
1572             JSValueSource::unboxedCell(op2GPR), node->child2(), SpecObject, m_jit.branchPtr(
1573                 MacroAssembler::Equal, 
1574                 MacroAssembler::Address(op2GPR, JSCell::structureOffset()), 
1575                 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1576     } else {
1577         GPRTemporary structure(this);
1578         GPRReg structureGPR = structure.gpr();
1579
1580         m_jit.loadPtr(MacroAssembler::Address(op1GPR, JSCell::structureOffset()), structureGPR);
1581         DFG_TYPE_CHECK(
1582             JSValueSource::unboxedCell(op1GPR), node->child1(), SpecObject, m_jit.branchPtr(
1583                 MacroAssembler::Equal, 
1584                 structureGPR, 
1585                 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1586         speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node->child1(),
1587             m_jit.branchTest8(
1588                 MacroAssembler::NonZero, 
1589                 MacroAssembler::Address(structureGPR, Structure::typeInfoFlagsOffset()), 
1590                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1591
1592         m_jit.loadPtr(MacroAssembler::Address(op2GPR, JSCell::structureOffset()), structureGPR);
1593         DFG_TYPE_CHECK(
1594             JSValueSource::unboxedCell(op2GPR), node->child2(), SpecObject, m_jit.branchPtr(
1595                 MacroAssembler::Equal, 
1596                 structureGPR, 
1597                 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1598         speculationCheck(BadType, JSValueSource::unboxedCell(op2GPR), node->child2(),
1599             m_jit.branchTest8(
1600                 MacroAssembler::NonZero, 
1601                 MacroAssembler::Address(structureGPR, Structure::typeInfoFlagsOffset()), 
1602                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1603     }
1604     
1605     MacroAssembler::Jump falseCase = m_jit.branch64(MacroAssembler::NotEqual, op1GPR, op2GPR);
1606     m_jit.move(TrustedImm32(ValueTrue), resultGPR);
1607     MacroAssembler::Jump done = m_jit.jump();
1608     falseCase.link(&m_jit);
1609     m_jit.move(TrustedImm32(ValueFalse), resultGPR);
1610     done.link(&m_jit);
1611
1612     jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean);
1613 }
1614
1615 void SpeculativeJIT::compileObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild)
1616 {
1617     SpeculateCellOperand op1(this, leftChild);
1618     JSValueOperand op2(this, rightChild, ManualOperandSpeculation);
1619     GPRTemporary result(this);
1620     
1621     GPRReg op1GPR = op1.gpr();
1622     GPRReg op2GPR = op2.gpr();
1623     GPRReg resultGPR = result.gpr();
1624     GPRTemporary structure;
1625     GPRReg structureGPR = InvalidGPRReg;
1626
1627     bool masqueradesAsUndefinedWatchpointValid =
1628         masqueradesAsUndefinedWatchpointIsStillValid();
1629
1630     if (!masqueradesAsUndefinedWatchpointValid) {
1631         // The masquerades as undefined case will use the structure register, so allocate it here.
1632         // Do this at the top of the function to avoid branching around a register allocation.
1633         GPRTemporary realStructure(this);
1634         structure.adopt(realStructure);
1635         structureGPR = structure.gpr();
1636     }
1637
1638     if (masqueradesAsUndefinedWatchpointValid) {
1639         speculationWatchpointForMasqueradesAsUndefined();
1640         DFG_TYPE_CHECK(
1641             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchPtr(
1642                 MacroAssembler::Equal, 
1643                 MacroAssembler::Address(op1GPR, JSCell::structureOffset()), 
1644                 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1645     } else {
1646         m_jit.loadPtr(MacroAssembler::Address(op1GPR, JSCell::structureOffset()), structureGPR);
1647         DFG_TYPE_CHECK(
1648             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchPtr(
1649                 MacroAssembler::Equal,
1650                 structureGPR,
1651                 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1652         speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), leftChild,
1653             m_jit.branchTest8(
1654                 MacroAssembler::NonZero, 
1655                 MacroAssembler::Address(structureGPR, Structure::typeInfoFlagsOffset()), 
1656                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1657     }
1658     
1659     // It seems that most of the time when programs do a == b where b may be either null/undefined
1660     // or an object, b is usually an object. Balance the branches to make that case fast.
1661     MacroAssembler::Jump rightNotCell =
1662         m_jit.branchTest64(MacroAssembler::NonZero, op2GPR, GPRInfo::tagMaskRegister);
1663     
1664     // We know that within this branch, rightChild must be a cell. 
1665     if (masqueradesAsUndefinedWatchpointValid) {
1666         speculationWatchpointForMasqueradesAsUndefined();
1667         DFG_TYPE_CHECK(
1668             JSValueRegs(op2GPR), rightChild, (~SpecCell) | SpecObject, m_jit.branchPtr(
1669                 MacroAssembler::Equal, 
1670                 MacroAssembler::Address(op2GPR, JSCell::structureOffset()), 
1671                 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1672     } else {
1673         m_jit.loadPtr(MacroAssembler::Address(op2GPR, JSCell::structureOffset()), structureGPR);
1674         DFG_TYPE_CHECK(
1675             JSValueRegs(op2GPR), rightChild, (~SpecCell) | SpecObject, m_jit.branchPtr(
1676                 MacroAssembler::Equal,
1677                 structureGPR,
1678                 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1679         speculationCheck(BadType, JSValueRegs(op2GPR), rightChild,
1680             m_jit.branchTest8(
1681                 MacroAssembler::NonZero, 
1682                 MacroAssembler::Address(structureGPR, Structure::typeInfoFlagsOffset()), 
1683                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1684     }
1685     
1686     // At this point we know that we can perform a straight-forward equality comparison on pointer
1687     // values because both left and right are pointers to objects that have no special equality
1688     // protocols.
1689     MacroAssembler::Jump falseCase = m_jit.branch64(MacroAssembler::NotEqual, op1GPR, op2GPR);
1690     MacroAssembler::Jump trueCase = m_jit.jump();
1691     
1692     rightNotCell.link(&m_jit);
1693     
1694     // We know that within this branch, rightChild must not be a cell. Check if that is enough to
1695     // prove that it is either null or undefined.
1696     if (needsTypeCheck(rightChild, SpecCell | SpecOther)) {
1697         m_jit.move(op2GPR, resultGPR);
1698         m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR);
1699         
1700         typeCheck(
1701             JSValueRegs(op2GPR), rightChild, SpecCell | SpecOther,
1702             m_jit.branch64(
1703                 MacroAssembler::NotEqual, resultGPR,
1704                 MacroAssembler::TrustedImm64(ValueNull)));
1705     }
1706     
1707     falseCase.link(&m_jit);
1708     m_jit.move(TrustedImm32(ValueFalse), resultGPR);
1709     MacroAssembler::Jump done = m_jit.jump();
1710     trueCase.link(&m_jit);
1711     m_jit.move(TrustedImm32(ValueTrue), resultGPR);
1712     done.link(&m_jit);
1713     
1714     jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean);
1715 }
1716
1717 void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild, Node* branchNode)
1718 {
1719     BasicBlock* taken = branchNode->takenBlock();
1720     BasicBlock* notTaken = branchNode->notTakenBlock();
1721     
1722     SpeculateCellOperand op1(this, leftChild);
1723     JSValueOperand op2(this, rightChild, ManualOperandSpeculation);
1724     GPRTemporary result(this);
1725     
1726     GPRReg op1GPR = op1.gpr();
1727     GPRReg op2GPR = op2.gpr();
1728     GPRReg resultGPR = result.gpr();
1729     GPRTemporary structure;
1730     GPRReg structureGPR = InvalidGPRReg;
1731     
1732     bool masqueradesAsUndefinedWatchpointValid =
1733         masqueradesAsUndefinedWatchpointIsStillValid();
1734
1735     if (!masqueradesAsUndefinedWatchpointValid) {
1736         // The masquerades as undefined case will use the structure register, so allocate it here.
1737         // Do this at the top of the function to avoid branching around a register allocation.
1738         GPRTemporary realStructure(this);
1739         structure.adopt(realStructure);
1740         structureGPR = structure.gpr();
1741     }
1742
1743     if (masqueradesAsUndefinedWatchpointValid) {
1744         speculationWatchpointForMasqueradesAsUndefined();
1745         DFG_TYPE_CHECK(
1746             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchPtr(
1747                 MacroAssembler::Equal, 
1748                 MacroAssembler::Address(op1GPR, JSCell::structureOffset()), 
1749                 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1750     } else {
1751         m_jit.loadPtr(MacroAssembler::Address(op1GPR, JSCell::structureOffset()), structureGPR);
1752         DFG_TYPE_CHECK(
1753             JSValueSource::unboxedCell(op1GPR), leftChild, SpecObject, m_jit.branchPtr(
1754                 MacroAssembler::Equal, 
1755                 structureGPR, 
1756                 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1757         speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), leftChild, 
1758             m_jit.branchTest8(
1759                 MacroAssembler::NonZero, 
1760                 MacroAssembler::Address(structureGPR, Structure::typeInfoFlagsOffset()), 
1761                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1762     }
1763
1764     // It seems that most of the time when programs do a == b where b may be either null/undefined
1765     // or an object, b is usually an object. Balance the branches to make that case fast.
1766     MacroAssembler::Jump rightNotCell =
1767         m_jit.branchTest64(MacroAssembler::NonZero, op2GPR, GPRInfo::tagMaskRegister);
1768     
1769     // We know that within this branch, rightChild must be a cell. 
1770     if (masqueradesAsUndefinedWatchpointValid) {
1771         speculationWatchpointForMasqueradesAsUndefined();
1772         DFG_TYPE_CHECK(
1773             JSValueRegs(op2GPR), rightChild, (~SpecCell) | SpecObject, m_jit.branchPtr(
1774                 MacroAssembler::Equal, 
1775                 MacroAssembler::Address(op2GPR, JSCell::structureOffset()), 
1776                 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1777     } else {
1778         m_jit.loadPtr(MacroAssembler::Address(op2GPR, JSCell::structureOffset()), structureGPR);
1779         DFG_TYPE_CHECK(
1780             JSValueRegs(op2GPR), rightChild, (~SpecCell) | SpecObject, m_jit.branchPtr(
1781                 MacroAssembler::Equal, 
1782                 structureGPR, 
1783                 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1784         speculationCheck(BadType, JSValueRegs(op2GPR), rightChild,
1785             m_jit.branchTest8(
1786                 MacroAssembler::NonZero, 
1787                 MacroAssembler::Address(structureGPR, Structure::typeInfoFlagsOffset()), 
1788                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1789     }
1790     
1791     // At this point we know that we can perform a straight-forward equality comparison on pointer
1792     // values because both left and right are pointers to objects that have no special equality
1793     // protocols.
1794     branch64(MacroAssembler::Equal, op1GPR, op2GPR, taken);
1795     
1796     // We know that within this branch, rightChild must not be a cell. Check if that is enough to
1797     // prove that it is either null or undefined.
1798     if (!needsTypeCheck(rightChild, SpecCell | SpecOther))
1799         rightNotCell.link(&m_jit);
1800     else {
1801         jump(notTaken, ForceJump);
1802         
1803         rightNotCell.link(&m_jit);
1804         m_jit.move(op2GPR, resultGPR);
1805         m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR);
1806         
1807         typeCheck(
1808             JSValueRegs(op2GPR), rightChild, SpecCell | SpecOther, m_jit.branch64(
1809                 MacroAssembler::NotEqual, resultGPR,
1810                 MacroAssembler::TrustedImm64(ValueNull)));
1811     }
1812     
1813     jump(notTaken);
1814 }
1815
1816 void SpeculativeJIT::compileInt32Compare(Node* node, MacroAssembler::RelationalCondition condition)
1817 {
1818     SpeculateInt32Operand op1(this, node->child1());
1819     SpeculateInt32Operand op2(this, node->child2());
1820     GPRTemporary result(this, Reuse, op1, op2);
1821     
1822     m_jit.compare32(condition, op1.gpr(), op2.gpr(), result.gpr());
1823     
1824     // If we add a DataFormatBool, we should use it here.
1825     m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1826     jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean);
1827 }
1828
1829 void SpeculativeJIT::compileInt52Compare(Node* node, MacroAssembler::RelationalCondition condition)
1830 {
1831     SpeculateWhicheverInt52Operand op1(this, node->child1());
1832     SpeculateWhicheverInt52Operand op2(this, node->child2(), op1);
1833     GPRTemporary result(this, Reuse, op1, op2);
1834     
1835     m_jit.compare64(condition, op1.gpr(), op2.gpr(), result.gpr());
1836     
1837     // If we add a DataFormatBool, we should use it here.
1838     m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1839     jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean);
1840 }
1841
1842 void SpeculativeJIT::compilePeepHoleInt52Branch(Node* node, Node* branchNode, JITCompiler::RelationalCondition condition)
1843 {
1844     BasicBlock* taken = branchNode->takenBlock();
1845     BasicBlock* notTaken = branchNode->notTakenBlock();
1846
1847     // The branch instruction will branch to the taken block.
1848     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
1849     if (taken == nextBlock()) {
1850         condition = JITCompiler::invert(condition);
1851         BasicBlock* tmp = taken;
1852         taken = notTaken;
1853         notTaken = tmp;
1854     }
1855     
1856     SpeculateWhicheverInt52Operand op1(this, node->child1());
1857     SpeculateWhicheverInt52Operand op2(this, node->child2(), op1);
1858     
1859     branch64(condition, op1.gpr(), op2.gpr(), taken);
1860     jump(notTaken);
1861 }
1862
1863 void SpeculativeJIT::compileDoubleCompare(Node* node, MacroAssembler::DoubleCondition condition)
1864 {
1865     SpeculateDoubleOperand op1(this, node->child1());
1866     SpeculateDoubleOperand op2(this, node->child2());
1867     GPRTemporary result(this);
1868     
1869     m_jit.move(TrustedImm32(ValueTrue), result.gpr());
1870     MacroAssembler::Jump trueCase = m_jit.branchDouble(condition, op1.fpr(), op2.fpr());
1871     m_jit.xor64(TrustedImm32(true), result.gpr());
1872     trueCase.link(&m_jit);
1873     
1874     jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1875 }
1876
1877 void SpeculativeJIT::compileValueAdd(Node* node)
1878 {
1879     JSValueOperand op1(this, node->child1());
1880     JSValueOperand op2(this, node->child2());
1881     
1882     GPRReg op1GPR = op1.gpr();
1883     GPRReg op2GPR = op2.gpr();
1884     
1885     flushRegisters();
1886     
1887     GPRResult result(this);
1888     if (isKnownNotNumber(node->child1().node()) || isKnownNotNumber(node->child2().node()))
1889         callOperation(operationValueAddNotNumber, result.gpr(), op1GPR, op2GPR);
1890     else
1891         callOperation(operationValueAdd, result.gpr(), op1GPR, op2GPR);
1892     
1893     jsValueResult(result.gpr(), node);
1894 }
1895
1896 void SpeculativeJIT::compileObjectOrOtherLogicalNot(Edge nodeUse)
1897 {
1898     JSValueOperand value(this, nodeUse, ManualOperandSpeculation);
1899     GPRTemporary result(this);
1900     GPRReg valueGPR = value.gpr();
1901     GPRReg resultGPR = result.gpr();
1902     GPRTemporary structure;
1903     GPRReg structureGPR = InvalidGPRReg;
1904
1905     bool masqueradesAsUndefinedWatchpointValid =
1906         masqueradesAsUndefinedWatchpointIsStillValid();
1907
1908     if (!masqueradesAsUndefinedWatchpointValid) {
1909         // The masquerades as undefined case will use the structure register, so allocate it here.
1910         // Do this at the top of the function to avoid branching around a register allocation.
1911         GPRTemporary realStructure(this);
1912         structure.adopt(realStructure);
1913         structureGPR = structure.gpr();
1914     }
1915
1916     MacroAssembler::Jump notCell = m_jit.branchTest64(MacroAssembler::NonZero, valueGPR, GPRInfo::tagMaskRegister);
1917     if (masqueradesAsUndefinedWatchpointValid) {
1918         speculationWatchpointForMasqueradesAsUndefined();
1919         DFG_TYPE_CHECK(
1920             JSValueRegs(valueGPR), nodeUse, (~SpecCell) | SpecObject, m_jit.branchPtr(
1921                 MacroAssembler::Equal,
1922                 MacroAssembler::Address(valueGPR, JSCell::structureOffset()),
1923                 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1924     } else {
1925         m_jit.loadPtr(MacroAssembler::Address(valueGPR, JSCell::structureOffset()), structureGPR);
1926
1927         DFG_TYPE_CHECK(
1928             JSValueRegs(valueGPR), nodeUse, (~SpecCell) | SpecObject, m_jit.branchPtr(
1929                 MacroAssembler::Equal,
1930                 structureGPR,
1931                 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1932
1933         MacroAssembler::Jump isNotMasqueradesAsUndefined = 
1934             m_jit.branchTest8(
1935                 MacroAssembler::Zero, 
1936                 MacroAssembler::Address(structureGPR, Structure::typeInfoFlagsOffset()), 
1937                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined));
1938
1939         speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse, 
1940             m_jit.branchPtr(
1941                 MacroAssembler::Equal, 
1942                 MacroAssembler::Address(structureGPR, Structure::globalObjectOffset()), 
1943                 MacroAssembler::TrustedImmPtr(m_jit.graph().globalObjectFor(m_currentNode->codeOrigin))));
1944
1945         isNotMasqueradesAsUndefined.link(&m_jit);
1946     }
1947     m_jit.move(TrustedImm32(ValueFalse), resultGPR);
1948     MacroAssembler::Jump done = m_jit.jump();
1949     
1950     notCell.link(&m_jit);
1951
1952     if (needsTypeCheck(nodeUse, SpecCell | SpecOther)) {
1953         m_jit.move(valueGPR, resultGPR);
1954         m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR);
1955         typeCheck(
1956             JSValueRegs(valueGPR), nodeUse, SpecCell | SpecOther, m_jit.branch64(
1957                 MacroAssembler::NotEqual, 
1958                 resultGPR, 
1959                 MacroAssembler::TrustedImm64(ValueNull)));
1960     }
1961     m_jit.move(TrustedImm32(ValueTrue), resultGPR);
1962     
1963     done.link(&m_jit);
1964     
1965     jsValueResult(resultGPR, m_currentNode, DataFormatJSBoolean);
1966 }
1967
1968 void SpeculativeJIT::compileLogicalNot(Node* node)
1969 {
1970     switch (node->child1().useKind()) {
1971     case ObjectOrOtherUse: {
1972         compileObjectOrOtherLogicalNot(node->child1());
1973         return;
1974     }
1975         
1976     case Int32Use: {
1977         SpeculateInt32Operand value(this, node->child1());
1978         GPRTemporary result(this, Reuse, value);
1979         m_jit.compare32(MacroAssembler::Equal, value.gpr(), MacroAssembler::TrustedImm32(0), result.gpr());
1980         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
1981         jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1982         return;
1983     }
1984         
1985     case NumberUse: {
1986         SpeculateDoubleOperand value(this, node->child1());
1987         FPRTemporary scratch(this);
1988         GPRTemporary result(this);
1989         m_jit.move(TrustedImm32(ValueFalse), result.gpr());
1990         MacroAssembler::Jump nonZero = m_jit.branchDoubleNonZero(value.fpr(), scratch.fpr());
1991         m_jit.xor32(TrustedImm32(true), result.gpr());
1992         nonZero.link(&m_jit);
1993         jsValueResult(result.gpr(), node, DataFormatJSBoolean);
1994         return;
1995     }
1996     
1997     case BooleanUse: {
1998         if (!needsTypeCheck(node->child1(), SpecBoolean)) {
1999             SpeculateBooleanOperand value(this, node->child1());
2000             GPRTemporary result(this, Reuse, value);
2001             
2002             m_jit.move(value.gpr(), result.gpr());
2003             m_jit.xor64(TrustedImm32(true), result.gpr());
2004             
2005             jsValueResult(result.gpr(), node, DataFormatJSBoolean);
2006             return;
2007         }
2008         
2009         JSValueOperand value(this, node->child1(), ManualOperandSpeculation);
2010         GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add).
2011         
2012         m_jit.move(value.gpr(), result.gpr());
2013         m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), result.gpr());
2014         typeCheck(
2015             JSValueRegs(value.gpr()), node->child1(), SpecBoolean, m_jit.branchTest64(
2016                 JITCompiler::NonZero, result.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
2017         m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueTrue)), result.gpr());
2018         
2019         // If we add a DataFormatBool, we should use it here.
2020         jsValueResult(result.gpr(), node, DataFormatJSBoolean);
2021         return;
2022     }
2023         
2024     case UntypedUse: {
2025         JSValueOperand arg1(this, node->child1());
2026         GPRTemporary result(this);
2027     
2028         GPRReg arg1GPR = arg1.gpr();
2029         GPRReg resultGPR = result.gpr();
2030     
2031         arg1.use();
2032     
2033         m_jit.move(arg1GPR, resultGPR);
2034         m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), resultGPR);
2035         JITCompiler::Jump slowCase = m_jit.branchTest64(JITCompiler::NonZero, resultGPR, TrustedImm32(static_cast<int32_t>(~1)));
2036     
2037         addSlowPathGenerator(
2038             slowPathCall(slowCase, this, dfgConvertJSValueToBoolean, resultGPR, arg1GPR));
2039     
2040         m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueTrue)), resultGPR);
2041         jsValueResult(resultGPR, node, DataFormatJSBoolean, UseChildrenCalledExplicitly);
2042         return;
2043     }
2044         
2045     default:
2046         RELEASE_ASSERT_NOT_REACHED();
2047         break;
2048     }
2049 }
2050
2051 void SpeculativeJIT::emitObjectOrOtherBranch(Edge nodeUse, BasicBlock* taken, BasicBlock* notTaken)
2052 {
2053     JSValueOperand value(this, nodeUse, ManualOperandSpeculation);
2054     GPRTemporary scratch(this);
2055     GPRReg valueGPR = value.gpr();
2056     GPRReg scratchGPR = scratch.gpr();
2057     
2058     MacroAssembler::Jump notCell = m_jit.branchTest64(MacroAssembler::NonZero, valueGPR, GPRInfo::tagMaskRegister);
2059     if (masqueradesAsUndefinedWatchpointIsStillValid()) {
2060         speculationWatchpointForMasqueradesAsUndefined();
2061
2062         DFG_TYPE_CHECK(
2063             JSValueRegs(valueGPR), nodeUse, (~SpecCell) | SpecObject, m_jit.branchPtr(
2064                 MacroAssembler::Equal, 
2065                 MacroAssembler::Address(valueGPR, JSCell::structureOffset()),
2066                 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
2067     } else {
2068         m_jit.loadPtr(MacroAssembler::Address(valueGPR, JSCell::structureOffset()), scratchGPR);
2069
2070         DFG_TYPE_CHECK(
2071             JSValueRegs(valueGPR), nodeUse, (~SpecCell) | SpecObject, m_jit.branchPtr(
2072                 MacroAssembler::Equal, 
2073                 scratchGPR,
2074                 MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
2075
2076         JITCompiler::Jump isNotMasqueradesAsUndefined = m_jit.branchTest8(JITCompiler::Zero, MacroAssembler::Address(scratchGPR, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined));
2077
2078         speculationCheck(BadType, JSValueRegs(valueGPR), nodeUse,
2079             m_jit.branchPtr(
2080                 MacroAssembler::Equal, 
2081                 MacroAssembler::Address(scratchGPR, Structure::globalObjectOffset()), 
2082                 MacroAssembler::TrustedImmPtr(m_jit.graph().globalObjectFor(m_currentNode->codeOrigin))));
2083
2084         isNotMasqueradesAsUndefined.link(&m_jit);
2085     }
2086     jump(taken, ForceJump);
2087     
2088     notCell.link(&m_jit);
2089     
2090     if (needsTypeCheck(nodeUse, SpecCell | SpecOther)) {
2091         m_jit.move(valueGPR, scratchGPR);
2092         m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), scratchGPR);
2093         typeCheck(
2094             JSValueRegs(valueGPR), nodeUse, SpecCell | SpecOther, m_jit.branch64(
2095                 MacroAssembler::NotEqual, scratchGPR, MacroAssembler::TrustedImm64(ValueNull)));
2096     }
2097     jump(notTaken);
2098     
2099     noResult(m_currentNode);
2100 }
2101
2102 void SpeculativeJIT::emitBranch(Node* node)
2103 {
2104     BasicBlock* taken = node->takenBlock();
2105     BasicBlock* notTaken = node->notTakenBlock();
2106     
2107     switch (node->child1().useKind()) {
2108     case ObjectOrOtherUse: {
2109         emitObjectOrOtherBranch(node->child1(), taken, notTaken);
2110         return;
2111     }
2112         
2113     case Int32Use:
2114     case NumberUse: {
2115         if (node->child1().useKind() == Int32Use) {
2116             bool invert = false;
2117             
2118             if (taken == nextBlock()) {
2119                 invert = true;
2120                 BasicBlock* tmp = taken;
2121                 taken = notTaken;
2122                 notTaken = tmp;
2123             }
2124
2125             SpeculateInt32Operand value(this, node->child1());
2126             branchTest32(invert ? MacroAssembler::Zero : MacroAssembler::NonZero, value.gpr(), taken);
2127         } else {
2128             SpeculateDoubleOperand value(this, node->child1());
2129             FPRTemporary scratch(this);
2130             branchDoubleNonZero(value.fpr(), scratch.fpr(), taken);
2131         }
2132         
2133         jump(notTaken);
2134         
2135         noResult(node);
2136         return;
2137     }
2138
2139     case UntypedUse:
2140     case BooleanUse: {
2141         JSValueOperand value(this, node->child1(), ManualOperandSpeculation);
2142         GPRReg valueGPR = value.gpr();
2143         
2144         if (node->child1().useKind() == BooleanUse) {
2145             if (!needsTypeCheck(node->child1(), SpecBoolean)) {
2146                 MacroAssembler::ResultCondition condition = MacroAssembler::NonZero;
2147                 
2148                 if (taken == nextBlock()) {
2149                     condition = MacroAssembler::Zero;
2150                     BasicBlock* tmp = taken;
2151                     taken = notTaken;
2152                     notTaken = tmp;
2153                 }
2154                 
2155                 branchTest32(condition, valueGPR, TrustedImm32(true), taken);
2156                 jump(notTaken);
2157             } else {
2158                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(false))), notTaken);
2159                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(true))), taken);
2160                 
2161                 typeCheck(JSValueRegs(valueGPR), node->child1(), SpecBoolean, m_jit.jump());
2162             }
2163             value.use();
2164         } else {
2165             GPRTemporary result(this);
2166             GPRReg resultGPR = result.gpr();
2167             
2168             if (node->child1()->prediction() & SpecInt32) {
2169                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsNumber(0))), notTaken);
2170                 branch64(MacroAssembler::AboveOrEqual, valueGPR, GPRInfo::tagTypeNumberRegister, taken);
2171             }
2172     
2173             if (node->child1()->prediction() & SpecBoolean) {
2174                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(false))), notTaken);
2175                 branch64(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(true))), taken);
2176             }
2177     
2178             value.use();
2179     
2180             silentSpillAllRegisters(resultGPR);
2181             callOperation(dfgConvertJSValueToBoolean, resultGPR, valueGPR);
2182             silentFillAllRegisters(resultGPR);
2183     
2184             branchTest32(MacroAssembler::NonZero, resultGPR, taken);
2185             jump(notTaken);
2186         }
2187         
2188         noResult(node, UseChildrenCalledExplicitly);
2189         return;
2190     }
2191         
2192     default:
2193         RELEASE_ASSERT_NOT_REACHED();
2194     }
2195 }
2196
2197 void SpeculativeJIT::compile(Node* node)
2198 {
2199     NodeType op = node->op();
2200     
2201 #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
2202     m_jit.clearRegisterAllocationOffsets();
2203 #endif
2204
2205     switch (op) {
2206     case JSConstant:
2207         initConstantInfo(node);
2208         break;
2209
2210     case PhantomArguments:
2211         initConstantInfo(node);
2212         break;
2213
2214     case WeakJSConstant:
2215         m_jit.addWeakReference(node->weakConstant());
2216         initConstantInfo(node);
2217         break;
2218         
2219     case Identity: {
2220         // CSE should always eliminate this.
2221         RELEASE_ASSERT_NOT_REACHED();
2222         break;
2223     }
2224
2225     case GetLocal: {
2226         SpeculatedType prediction = node->variableAccessData()->prediction();
2227         AbstractValue& value = m_state.variables().operand(node->local());
2228
2229         // If we have no prediction for this local, then don't attempt to compile.
2230         if (prediction == SpecNone) {
2231             terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
2232             break;
2233         }
2234         
2235         // If the CFA is tracking this variable and it found that the variable
2236         // cannot have been assigned, then don't attempt to proceed.
2237         if (value.isClear()) {
2238             // FIXME: We should trap instead.
2239             // https://bugs.webkit.org/show_bug.cgi?id=110383
2240             terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
2241             break;
2242         }
2243         
2244         switch (node->variableAccessData()->flushFormat()) {
2245         case FlushedDouble: {
2246             FPRTemporary result(this);
2247             m_jit.loadDouble(JITCompiler::addressFor(node->local()), result.fpr());
2248             VirtualRegister virtualRegister = node->virtualRegister();
2249             m_fprs.retain(result.fpr(), virtualRegister, SpillOrderDouble);
2250             generationInfoFromVirtualRegister(virtualRegister).initDouble(node, node->refCount(), result.fpr());
2251             break;
2252         }
2253         
2254         case FlushedInt32: {
2255             GPRTemporary result(this);
2256             m_jit.load32(JITCompiler::payloadFor(node->local()), result.gpr());
2257             
2258             // Like int32Result, but don't useChildren - our children are phi nodes,
2259             // and don't represent values within this dataflow with virtual registers.
2260             VirtualRegister virtualRegister = node->virtualRegister();
2261             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderInteger);
2262             generationInfoFromVirtualRegister(virtualRegister).initInt32(node, node->refCount(), result.gpr());
2263             break;
2264         }
2265             
2266         case FlushedInt52: {
2267             GPRTemporary result(this);
2268             m_jit.load64(JITCompiler::addressFor(node->local()), result.gpr());
2269             
2270             VirtualRegister virtualRegister = node->virtualRegister();
2271             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
2272             generationInfoFromVirtualRegister(virtualRegister).initInt52(node, node->refCount(), result.gpr());
2273             break;
2274         }
2275             
2276         default:
2277             GPRTemporary result(this);
2278             m_jit.load64(JITCompiler::addressFor(node->local()), result.gpr());
2279             
2280             // Like jsValueResult, but don't useChildren - our children are phi nodes,
2281             // and don't represent values within this dataflow with virtual registers.
2282             VirtualRegister virtualRegister = node->virtualRegister();
2283             m_gprs.retain(result.gpr(), virtualRegister, SpillOrderJS);
2284             
2285             DataFormat format;
2286             if (isCellSpeculation(value.m_type))
2287                 format = DataFormatJSCell;
2288             else if (isBooleanSpeculation(value.m_type))
2289                 format = DataFormatJSBoolean;
2290             else
2291                 format = DataFormatJS;
2292             
2293             generationInfoFromVirtualRegister(virtualRegister).initJSValue(node, node->refCount(), result.gpr(), format);
2294             break;
2295         }
2296         break;
2297     }
2298
2299     case GetLocalUnlinked: {
2300         GPRTemporary result(this);
2301         
2302         m_jit.load64(JITCompiler::addressFor(node->unlinkedLocal()), result.gpr());
2303         
2304         jsValueResult(result.gpr(), node);
2305         break;
2306     }
2307         
2308     case MovHintAndCheck: {
2309         compileMovHintAndCheck(node);
2310         break;
2311     }
2312         
2313     case InlineStart: {
2314         compileInlineStart(node);
2315         break;
2316     }
2317
2318     case MovHint:
2319     case ZombieHint: {
2320         RELEASE_ASSERT_NOT_REACHED();
2321         break;
2322     }
2323
2324     case SetLocal: {
2325         // SetLocal doubles as a hint as to where a node will be stored and
2326         // as a speculation point. So before we speculate make sure that we
2327         // know where the child of this node needs to go in the virtual
2328         // stack.
2329         compileMovHint(node);
2330         
2331         switch (node->variableAccessData()->flushFormat()) {
2332         case FlushedDouble: {
2333             SpeculateDoubleOperand value(this, node->child1());
2334             m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node->local()));
2335             noResult(node);
2336             // Indicate that it's no longer necessary to retrieve the value of
2337             // this bytecode variable from registers or other locations in the stack,
2338             // but that it is stored as a double.
2339             recordSetLocal(node->local(), ValueSource(DoubleInJSStack));
2340             break;
2341         }
2342             
2343         case FlushedInt32: {
2344             SpeculateInt32Operand value(this, node->child1());
2345             m_jit.store32(value.gpr(), JITCompiler::payloadFor(node->local()));
2346             noResult(node);
2347             recordSetLocal(node->local(), ValueSource(Int32InJSStack));
2348             break;
2349         }
2350             
2351         case FlushedInt52: {
2352             SpeculateInt52Operand value(this, node->child1());
2353             m_jit.store64(value.gpr(), JITCompiler::addressFor(node->local()));
2354             noResult(node);
2355             recordSetLocal(node->local(), ValueSource(Int52InJSStack));
2356             break;
2357         }
2358             
2359         case FlushedCell: {
2360             SpeculateCellOperand cell(this, node->child1());
2361             GPRReg cellGPR = cell.gpr();
2362             m_jit.store64(cellGPR, JITCompiler::addressFor(node->local()));
2363             noResult(node);
2364             recordSetLocal(node->local(), ValueSource(CellInJSStack));
2365             break;
2366         }
2367             
2368         case FlushedBoolean: {
2369             SpeculateBooleanOperand boolean(this, node->child1());
2370             m_jit.store64(boolean.gpr(), JITCompiler::addressFor(node->local()));
2371             noResult(node);
2372             recordSetLocal(node->local(), ValueSource(BooleanInJSStack));
2373             break;
2374         }
2375             
2376         case FlushedJSValue: {
2377             JSValueOperand value(this, node->child1());
2378             m_jit.store64(value.gpr(), JITCompiler::addressFor(node->local()));
2379             noResult(node);
2380             
2381             recordSetLocal(node->local(), ValueSource(ValueInJSStack));
2382             
2383             // If we're storing an arguments object that has been optimized away,
2384             // our variable event stream for OSR exit now reflects the optimized
2385             // value (JSValue()). On the slow path, we want an arguments object
2386             // instead. We add an additional move hint to show OSR exit that it
2387             // needs to reconstruct the arguments object.
2388             if (node->child1()->op() == PhantomArguments)
2389                 compileMovHint(node);
2390             break;
2391         }
2392             
2393         default:
2394             RELEASE_ASSERT_NOT_REACHED();
2395             break;
2396         }
2397
2398         break;
2399     }
2400
2401     case SetArgument:
2402         // This is a no-op; it just marks the fact that the argument is being used.
2403         // But it may be profitable to use this as a hook to run speculation checks
2404         // on arguments, thereby allowing us to trivially eliminate such checks if
2405         // the argument is not used.
2406         break;
2407
2408     case BitAnd:
2409     case BitOr:
2410     case BitXor:
2411         if (isInt32Constant(node->child1().node())) {
2412             SpeculateInt32Operand op2(this, node->child2());
2413             GPRTemporary result(this, Reuse, op2);
2414
2415             bitOp(op, valueOfInt32Constant(node->child1().node()), op2.gpr(), result.gpr());
2416
2417             int32Result(result.gpr(), node);
2418         } else if (isInt32Constant(node->child2().node())) {
2419             SpeculateInt32Operand op1(this, node->child1());
2420             GPRTemporary result(this, Reuse, op1);
2421
2422             bitOp(op, valueOfInt32Constant(node->child2().node()), op1.gpr(), result.gpr());
2423
2424             int32Result(result.gpr(), node);
2425         } else {
2426             SpeculateInt32Operand op1(this, node->child1());
2427             SpeculateInt32Operand op2(this, node->child2());
2428             GPRTemporary result(this, Reuse, op1, op2);
2429
2430             GPRReg reg1 = op1.gpr();
2431             GPRReg reg2 = op2.gpr();
2432             bitOp(op, reg1, reg2, result.gpr());
2433
2434             int32Result(result.gpr(), node);
2435         }
2436         break;
2437
2438     case BitRShift:
2439     case BitLShift:
2440     case BitURShift:
2441         if (isInt32Constant(node->child2().node())) {
2442             SpeculateInt32Operand op1(this, node->child1());
2443             GPRTemporary result(this, Reuse, op1);
2444
2445             shiftOp(op, op1.gpr(), valueOfInt32Constant(node->child2().node()) & 0x1f, result.gpr());
2446
2447             int32Result(result.gpr(), node);
2448         } else {
2449             // Do not allow shift amount to be used as the result, MacroAssembler does not permit this.
2450             SpeculateInt32Operand op1(this, node->child1());
2451             SpeculateInt32Operand op2(this, node->child2());
2452             GPRTemporary result(this, Reuse, op1);
2453
2454             GPRReg reg1 = op1.gpr();
2455             GPRReg reg2 = op2.gpr();
2456             shiftOp(op, reg1, reg2, result.gpr());
2457
2458             int32Result(result.gpr(), node);
2459         }
2460         break;
2461
2462     case UInt32ToNumber: {
2463         compileUInt32ToNumber(node);
2464         break;
2465     }
2466
2467     case DoubleAsInt32: {
2468         compileDoubleAsInt32(node);
2469         break;
2470     }
2471
2472     case ValueToInt32: {
2473         compileValueToInt32(node);
2474         break;
2475     }
2476         
2477     case Int32ToDouble: {
2478         compileInt32ToDouble(node);
2479         break;
2480     }
2481         
2482     case Int52ToValue: {
2483         JSValueOperand operand(this, node->child1());
2484         GPRTemporary result(this, Reuse, operand);
2485         m_jit.move(operand.gpr(), result.gpr());
2486         jsValueResult(result.gpr(), node);
2487         break;
2488     }
2489         
2490     case Int52ToDouble: {
2491         SpeculateDoubleOperand operand(this, node->child1());
2492         FPRTemporary result(this, operand);
2493         m_jit.moveDouble(operand.fpr(), result.fpr());
2494         doubleResult(result.fpr(), node);
2495         break;
2496     }
2497         
2498     case ValueAdd:
2499     case ArithAdd:
2500         compileAdd(node);
2501         break;
2502         
2503     case MakeRope:
2504         compileMakeRope(node);
2505         break;
2506
2507     case ArithSub:
2508         compileArithSub(node);
2509         break;
2510
2511     case ArithNegate:
2512         compileArithNegate(node);
2513         break;
2514
2515     case ArithMul:
2516         compileArithMul(node);
2517         break;
2518
2519     case ArithIMul:
2520         compileArithIMul(node);
2521         break;
2522
2523     case ArithDiv: {
2524         compileArithDiv(node);
2525         break;
2526     }
2527
2528     case ArithMod: {
2529         compileArithMod(node);
2530         break;
2531     }
2532
2533     case ArithAbs: {
2534         switch (node->child1().useKind()) {
2535         case Int32Use: {
2536             SpeculateStrictInt32Operand op1(this, node->child1());
2537             GPRTemporary result(this);
2538             GPRTemporary scratch(this);
2539             
2540             m_jit.move(op1.gpr(), result.gpr());
2541             m_jit.rshift32(result.gpr(), MacroAssembler::TrustedImm32(31), scratch.gpr());
2542             m_jit.add32(scratch.gpr(), result.gpr());
2543             m_jit.xor32(scratch.gpr(), result.gpr());
2544             speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::Equal, result.gpr(), MacroAssembler::TrustedImm32(1 << 31)));
2545             int32Result(result.gpr(), node);
2546             break;
2547         }
2548         
2549         case NumberUse: {
2550             SpeculateDoubleOperand op1(this, node->child1());
2551             FPRTemporary result(this);
2552             
2553             m_jit.absDouble(op1.fpr(), result.fpr());
2554             doubleResult(result.fpr(), node);
2555             break;
2556         }
2557             
2558         default:
2559             RELEASE_ASSERT_NOT_REACHED();
2560             break;
2561         }
2562         break;
2563     }
2564         
2565     case ArithMin:
2566     case ArithMax: {
2567         switch (node->binaryUseKind()) {
2568         case Int32Use: {
2569             SpeculateStrictInt32Operand op1(this, node->child1());
2570             SpeculateStrictInt32Operand op2(this, node->child2());
2571             GPRTemporary result(this, Reuse, op1);
2572             
2573             MacroAssembler::Jump op1Less = m_jit.branch32(op == ArithMin ? MacroAssembler::LessThan : MacroAssembler::GreaterThan, op1.gpr(), op2.gpr());
2574             m_jit.move(op2.gpr(), result.gpr());
2575             if (op1.gpr() != result.gpr()) {
2576                 MacroAssembler::Jump done = m_jit.jump();
2577                 op1Less.link(&m_jit);
2578                 m_jit.move(op1.gpr(), result.gpr());
2579                 done.link(&m_jit);
2580             } else
2581                 op1Less.link(&m_jit);
2582             
2583             int32Result(result.gpr(), node);
2584             break;
2585         }
2586         
2587         case NumberUse: {
2588             SpeculateDoubleOperand op1(this, node->child1());
2589             SpeculateDoubleOperand op2(this, node->child2());
2590             FPRTemporary result(this, op1);
2591             
2592             FPRReg op1FPR = op1.fpr();
2593             FPRReg op2FPR = op2.fpr();
2594             FPRReg resultFPR = result.fpr();
2595         
2596             MacroAssembler::JumpList done;
2597         
2598             MacroAssembler::Jump op1Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleLessThan : MacroAssembler::DoubleGreaterThan, op1FPR, op2FPR);
2599         
2600             // op2 is eather the lesser one or one of then is NaN
2601             MacroAssembler::Jump op2Less = m_jit.branchDouble(op == ArithMin ? MacroAssembler::DoubleGreaterThanOrEqual : MacroAssembler::DoubleLessThanOrEqual, op1FPR, op2FPR);
2602         
2603             // Unordered case. We don't know which of op1, op2 is NaN. Manufacture NaN by adding 
2604             // op1 + op2 and putting it into result.
2605             m_jit.addDouble(op1FPR, op2FPR, resultFPR);
2606             done.append(m_jit.jump());
2607         
2608             op2Less.link(&m_jit);
2609             m_jit.moveDouble(op2FPR, resultFPR);
2610         
2611             if (op1FPR != resultFPR) {
2612                 done.append(m_jit.jump());
2613             
2614                 op1Less.link(&m_jit);
2615                 m_jit.moveDouble(op1FPR, resultFPR);
2616             } else
2617                 op1Less.link(&m_jit);
2618         
2619             done.link(&m_jit);
2620         
2621             doubleResult(resultFPR, node);
2622             break;
2623         }
2624             
2625         default:
2626             RELEASE_ASSERT_NOT_REACHED();
2627             break;
2628         }
2629         break;
2630     }
2631         
2632     case ArithSqrt: {
2633         SpeculateDoubleOperand op1(this, node->child1());
2634         FPRTemporary result(this, op1);
2635         
2636         m_jit.sqrtDouble(op1.fpr(), result.fpr());
2637         
2638         doubleResult(result.fpr(), node);
2639         break;
2640     }
2641
2642     case LogicalNot:
2643         compileLogicalNot(node);
2644         break;
2645
2646     case CompareLess:
2647         if (compare(node, JITCompiler::LessThan, JITCompiler::DoubleLessThan, operationCompareLess))
2648             return;
2649         break;
2650
2651     case CompareLessEq:
2652         if (compare(node, JITCompiler::LessThanOrEqual, JITCompiler::DoubleLessThanOrEqual, operationCompareLessEq))
2653             return;
2654         break;
2655
2656     case CompareGreater:
2657         if (compare(node, JITCompiler::GreaterThan, JITCompiler::DoubleGreaterThan, operationCompareGreater))
2658             return;
2659         break;
2660
2661     case CompareGreaterEq:
2662         if (compare(node, JITCompiler::GreaterThanOrEqual, JITCompiler::DoubleGreaterThanOrEqual, operationCompareGreaterEq))
2663             return;
2664         break;
2665         
2666     case CompareEqConstant:
2667         ASSERT(isNullConstant(node->child2().node()));
2668         if (nonSpeculativeCompareNull(node, node->child1()))
2669             return;
2670         break;
2671
2672     case CompareEq:
2673         if (compare(node, JITCompiler::Equal, JITCompiler::DoubleEqual, operationCompareEq))
2674             return;
2675         break;
2676
2677     case CompareStrictEqConstant:
2678         if (compileStrictEqForConstant(node, node->child1(), valueOfJSConstant(node->child2().node())))
2679             return;
2680         break;
2681
2682     case CompareStrictEq:
2683         if (compileStrictEq(node))
2684             return;
2685         break;
2686
2687     case StringCharCodeAt: {
2688         compileGetCharCodeAt(node);
2689         break;
2690     }
2691
2692     case StringCharAt: {
2693         // Relies on StringCharAt node having same basic layout as GetByVal
2694         compileGetByValOnString(node);
2695         break;
2696     }
2697
2698     case StringFromCharCode: {
2699         compileFromCharCode(node);
2700         break;
2701     }
2702         
2703     case CheckArray: {
2704         checkArray(node);
2705         break;
2706     }
2707         
2708     case Arrayify:
2709     case ArrayifyToStructure: {
2710         arrayify(node);
2711         break;
2712     }
2713
2714     case GetByVal: {
2715         switch (node->arrayMode().type()) {
2716         case Array::SelectUsingPredictions:
2717         case Array::ForceExit:
2718             RELEASE_ASSERT_NOT_REACHED();
2719             terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
2720             break;
2721         case Array::Generic: {
2722             JSValueOperand base(this, node->child1());
2723             JSValueOperand property(this, node->child2());
2724             GPRReg baseGPR = base.gpr();
2725             GPRReg propertyGPR = property.gpr();
2726             
2727             flushRegisters();
2728             GPRResult result(this);
2729             callOperation(operationGetByVal, result.gpr(), baseGPR, propertyGPR);
2730             
2731             jsValueResult(result.gpr(), node);
2732             break;
2733         }
2734         case Array::Int32:
2735         case Array::Contiguous: {
2736             if (node->arrayMode().isInBounds()) {
2737                 SpeculateStrictInt32Operand property(this, node->child2());
2738                 StorageOperand storage(this, node->child3());
2739                 
2740                 GPRReg propertyReg = property.gpr();
2741                 GPRReg storageReg = storage.gpr();
2742                 
2743                 if (!m_compileOkay)
2744                     return;
2745                 
2746                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2747                 
2748                 GPRTemporary result(this);
2749                 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.gpr());
2750                 speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchTest64(MacroAssembler::Zero, result.gpr()));
2751                 jsValueResult(result.gpr(), node, node->arrayMode().type() == Array::Int32 ? DataFormatJSInt32 : DataFormatJS);
2752                 break;
2753             }
2754             
2755             SpeculateCellOperand base(this, node->child1());
2756             SpeculateStrictInt32Operand property(this, node->child2());
2757             StorageOperand storage(this, node->child3());
2758             
2759             GPRReg baseReg = base.gpr();
2760             GPRReg propertyReg = property.gpr();
2761             GPRReg storageReg = storage.gpr();
2762             
2763             if (!m_compileOkay)
2764                 return;
2765             
2766             GPRTemporary result(this);
2767             GPRReg resultReg = result.gpr();
2768             
2769             MacroAssembler::JumpList slowCases;
2770             
2771             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2772             
2773             m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
2774             slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, resultReg));
2775             
2776             addSlowPathGenerator(
2777                 slowPathCall(
2778                     slowCases, this, operationGetByValArrayInt,
2779                     result.gpr(), baseReg, propertyReg));
2780             
2781             jsValueResult(resultReg, node);
2782             break;
2783         }
2784
2785         case Array::Double: {
2786             if (node->arrayMode().isInBounds()) {
2787                 if (node->arrayMode().isSaneChain()) {
2788                     JSGlobalObject* globalObject = m_jit.globalObjectFor(node->codeOrigin);
2789                     ASSERT(globalObject->arrayPrototypeChainIsSane());
2790                     m_jit.addLazily(
2791                         speculationWatchpoint(),
2792                         globalObject->arrayPrototype()->structure()->transitionWatchpointSet());
2793                     m_jit.addLazily(
2794                         speculationWatchpoint(),
2795                         globalObject->objectPrototype()->structure()->transitionWatchpointSet());
2796                 }
2797                 
2798                 SpeculateStrictInt32Operand property(this, node->child2());
2799                 StorageOperand storage(this, node->child3());
2800             
2801                 GPRReg propertyReg = property.gpr();
2802                 GPRReg storageReg = storage.gpr();
2803             
2804                 if (!m_compileOkay)
2805                     return;
2806             
2807                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2808             
2809                 FPRTemporary result(this);
2810                 m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), result.fpr());
2811                 if (!node->arrayMode().isSaneChain())
2812                     speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, result.fpr(), result.fpr()));
2813                 doubleResult(result.fpr(), node);
2814                 break;
2815             }
2816
2817             SpeculateCellOperand base(this, node->child1());
2818             SpeculateStrictInt32Operand property(this, node->child2());
2819             StorageOperand storage(this, node->child3());
2820             
2821             GPRReg baseReg = base.gpr();
2822             GPRReg propertyReg = property.gpr();
2823             GPRReg storageReg = storage.gpr();
2824             
2825             if (!m_compileOkay)
2826                 return;
2827             
2828             GPRTemporary result(this);
2829             FPRTemporary temp(this);
2830             GPRReg resultReg = result.gpr();
2831             FPRReg tempReg = temp.fpr();
2832             
2833             MacroAssembler::JumpList slowCases;
2834             
2835             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
2836             
2837             m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), tempReg);
2838             slowCases.append(m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, tempReg, tempReg));
2839             boxDouble(tempReg, resultReg);
2840             
2841             addSlowPathGenerator(
2842                 slowPathCall(
2843                     slowCases, this, operationGetByValArrayInt,
2844                     result.gpr(), baseReg, propertyReg));
2845             
2846             jsValueResult(resultReg, node);
2847             break;
2848         }
2849
2850         case Array::ArrayStorage:
2851         case Array::SlowPutArrayStorage: {
2852             if (node->arrayMode().isInBounds()) {
2853                 SpeculateStrictInt32Operand property(this, node->child2());
2854                 StorageOperand storage(this, node->child3());
2855             
2856                 GPRReg propertyReg = property.gpr();
2857                 GPRReg storageReg = storage.gpr();
2858             
2859                 if (!m_compileOkay)
2860                     return;
2861             
2862                 speculationCheck(OutOfBounds, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
2863             
2864                 GPRTemporary result(this);
2865                 m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), result.gpr());
2866                 speculationCheck(LoadFromHole, JSValueRegs(), 0, m_jit.branchTest64(MacroAssembler::Zero, result.gpr()));
2867             
2868                 jsValueResult(result.gpr(), node);
2869                 break;
2870             }
2871
2872             SpeculateCellOperand base(this, node->child1());
2873             SpeculateStrictInt32Operand property(this, node->child2());
2874             StorageOperand storage(this, node->child3());
2875             
2876             GPRReg baseReg = base.gpr();
2877             GPRReg propertyReg = property.gpr();
2878             GPRReg storageReg = storage.gpr();
2879             
2880             if (!m_compileOkay)
2881                 return;
2882             
2883             GPRTemporary result(this);
2884             GPRReg resultReg = result.gpr();
2885             
2886             MacroAssembler::JumpList slowCases;
2887             
2888             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset())));
2889     
2890             m_jit.load64(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), resultReg);
2891             slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, resultReg));
2892     
2893             addSlowPathGenerator(
2894                 slowPathCall(
2895                     slowCases, this, operationGetByValArrayInt,
2896                     result.gpr(), baseReg, propertyReg));
2897             
2898             jsValueResult(resultReg, node);
2899             break;
2900         }
2901         case Array::String:
2902             compileGetByValOnString(node);
2903             break;
2904         case Array::Arguments:
2905             compileGetByValOnArguments(node);
2906             break;
2907         default: {
2908             TypedArrayType type = node->arrayMode().typedArrayType();
2909             if (isInt(type))
2910                 compileGetByValOnIntTypedArray(node, type);
2911             else
2912                 compileGetByValOnFloatTypedArray(node, type);
2913         } }
2914         break;
2915     }
2916
2917     case PutByVal:
2918     case PutByValAlias: {
2919         Edge child1 = m_jit.graph().varArgChild(node, 0);
2920         Edge child2 = m_jit.graph().varArgChild(node, 1);
2921         Edge child3 = m_jit.graph().varArgChild(node, 2);
2922         Edge child4 = m_jit.graph().varArgChild(node, 3);
2923         
2924         ArrayMode arrayMode = node->arrayMode().modeForPut();
2925         bool alreadyHandled = false;
2926         
2927         switch (arrayMode.type()) {
2928         case Array::SelectUsingPredictions:
2929         case Array::ForceExit:
2930             RELEASE_ASSERT_NOT_REACHED();
2931             terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
2932             alreadyHandled = true;
2933             break;
2934         case Array::Generic: {
2935             RELEASE_ASSERT(node->op() == PutByVal);
2936             
2937             JSValueOperand arg1(this, child1);
2938             JSValueOperand arg2(this, child2);
2939             JSValueOperand arg3(this, child3);
2940             GPRReg arg1GPR = arg1.gpr();
2941             GPRReg arg2GPR = arg2.gpr();
2942             GPRReg arg3GPR = arg3.gpr();
2943             flushRegisters();
2944             
2945             callOperation(m_jit.strictModeFor(node->codeOrigin) ? operationPutByValStrict : operationPutByValNonStrict, arg1GPR, arg2GPR, arg3GPR);
2946             
2947             noResult(node);
2948             alreadyHandled = true;
2949             break;
2950         }
2951         default:
2952             break;
2953         }
2954         
2955         if (alreadyHandled)
2956             break;
2957         
2958         // FIXME: the base may not be necessary for some array access modes. But we have to
2959         // keep it alive to this point, so it's likely to be in a register anyway. Likely
2960         // no harm in locking it here.
2961         SpeculateCellOperand base(this, child1);
2962         SpeculateStrictInt32Operand property(this, child2);
2963         
2964         GPRReg baseReg = base.gpr();
2965         GPRReg propertyReg = property.gpr();
2966
2967         switch (arrayMode.type()) {
2968         case Array::Int32:
2969         case Array::Contiguous: {
2970             JSValueOperand value(this, child3, ManualOperandSpeculation);
2971
2972             GPRReg valueReg = value.gpr();
2973         
2974             if (!m_compileOkay)
2975                 return;
2976             
2977             if (arrayMode.type() == Array::Int32) {
2978                 DFG_TYPE_CHECK(
2979                     JSValueRegs(valueReg), child3, SpecInt32,
2980                     m_jit.branch64(
2981                         MacroAssembler::Below, valueReg, GPRInfo::tagTypeNumberRegister));
2982             }
2983         
2984             if (arrayMode.type() == Array::Contiguous && Heap::isWriteBarrierEnabled()) {
2985                 GPRTemporary scratch(this);
2986                 writeBarrier(baseReg, value.gpr(), child3, WriteBarrierForPropertyAccess, scratch.gpr());
2987             }
2988
2989             StorageOperand storage(this, child4);
2990             GPRReg storageReg = storage.gpr();
2991
2992             if (node->op() == PutByValAlias) {
2993                 // Store the value to the array.
2994                 GPRReg propertyReg = property.gpr();
2995                 GPRReg valueReg = value.gpr();
2996                 m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
2997                 
2998                 noResult(node);
2999                 break;
3000             }
3001             
3002             GPRTemporary temporary;
3003             GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
3004
3005             MacroAssembler::Jump slowCase;
3006             
3007             if (arrayMode.isInBounds()) {
3008                 speculationCheck(
3009                     StoreToHoleOrOutOfBounds, JSValueRegs(), 0,
3010                     m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
3011             } else {
3012                 MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
3013                 
3014                 slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfVectorLength()));
3015                 
3016                 if (!arrayMode.isOutOfBounds())
3017                     speculationCheck(OutOfBounds, JSValueRegs(), 0, slowCase);
3018                 
3019                 m_jit.add32(TrustedImm32(1), propertyReg, temporaryReg);
3020                 m_jit.store32(temporaryReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
3021                 
3022                 inBounds.link(&m_jit);
3023             }
3024             
3025             m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
3026
3027             base.use();
3028             property.use();
3029             value.use();
3030             storage.use();
3031             
3032             if (arrayMode.isOutOfBounds()) {
3033                 addSlowPathGenerator(
3034                     slowPathCall(
3035                         slowCase, this,
3036                         m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
3037                         NoResult, baseReg, propertyReg, valueReg));
3038             }
3039
3040             noResult(node, UseChildrenCalledExplicitly);
3041             break;
3042         }
3043             
3044         case Array::Double: {
3045             compileDoublePutByVal(node, base, property);
3046             break;
3047         }
3048             
3049         case Array::ArrayStorage:
3050         case Array::SlowPutArrayStorage: {
3051             JSValueOperand value(this, child3);
3052
3053             GPRReg valueReg = value.gpr();
3054         
3055             if (!m_compileOkay)
3056                 return;
3057         
3058             if (Heap::isWriteBarrierEnabled()) {
3059                 GPRTemporary scratch(this);
3060                 writeBarrier(baseReg, value.gpr(), child3, WriteBarrierForPropertyAccess, scratch.gpr());
3061             }
3062
3063             StorageOperand storage(this, child4);
3064             GPRReg storageReg = storage.gpr();
3065
3066             if (node->op() == PutByValAlias) {
3067                 // Store the value to the array.
3068                 GPRReg propertyReg = property.gpr();
3069                 GPRReg valueReg = value.gpr();
3070                 m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
3071                 
3072                 noResult(node);
3073                 break;
3074             }
3075             
3076             GPRTemporary temporary;
3077             GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
3078
3079             MacroAssembler::JumpList slowCases;
3080
3081             MacroAssembler::Jump beyondArrayBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::vectorLengthOffset()));
3082             if (!arrayMode.isOutOfBounds())
3083                 speculationCheck(OutOfBounds, JSValueRegs(), 0, beyondArrayBounds);
3084             else
3085                 slowCases.append(beyondArrayBounds);
3086
3087             // Check if we're writing to a hole; if so increment m_numValuesInVector.
3088             if (arrayMode.isInBounds()) {
3089                 speculationCheck(
3090                     StoreToHole, JSValueRegs(), 0,
3091                     m_jit.branchTest64(MacroAssembler::Zero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]))));
3092             } else {
3093                 MacroAssembler::Jump notHoleValue = m_jit.branchTest64(MacroAssembler::NonZero, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
3094                 if (arrayMode.isSlowPut()) {
3095                     // This is sort of strange. If we wanted to optimize this code path, we would invert
3096                     // the above branch. But it's simply not worth it since this only happens if we're
3097                     // already having a bad time.
3098                     slowCases.append(m_jit.jump());
3099                 } else {
3100                     m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageReg, ArrayStorage::numValuesInVectorOffset()));
3101                 
3102                     // If we're writing to a hole we might be growing the array; 
3103                     MacroAssembler::Jump lengthDoesNotNeedUpdate = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
3104                     m_jit.add32(TrustedImm32(1), propertyReg, temporaryReg);
3105                     m_jit.store32(temporaryReg, MacroAssembler::Address(storageReg, ArrayStorage::lengthOffset()));
3106                 
3107                     lengthDoesNotNeedUpdate.link(&m_jit);
3108                 }
3109                 notHoleValue.link(&m_jit);
3110             }
3111     
3112             // Store the value to the array.
3113             m_jit.store64(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
3114
3115             base.use();
3116             property.use();
3117             value.use();
3118             storage.use();
3119             
3120             if (!slowCases.empty()) {
3121                 addSlowPathGenerator(
3122                     slowPathCall(
3123                         slowCases, this,
3124                         m_jit.codeBlock()->isStrictMode() ? operationPutByValBeyondArrayBoundsStrict : operationPutByValBeyondArrayBoundsNonStrict,
3125                         NoResult, baseReg, propertyReg, valueReg));
3126             }
3127
3128             noResult(node, UseChildrenCalledExplicitly);
3129             break;
3130         }
3131             
3132         case Array::Arguments: {
3133             JSValueOperand value(this, child3);
3134             GPRTemporary scratch(this);
3135             GPRTemporary scratch2(this);
3136             
3137             GPRReg valueReg = value.gpr();
3138             GPRReg scratchReg = scratch.gpr();
3139             GPRReg scratch2Reg = scratch2.gpr();
3140             
3141             if (!m_compileOkay)
3142                 return;
3143
3144             // Two really lame checks.
3145             speculationCheck(
3146                 Uncountable, JSValueSource(), 0,
3147                 m_jit.branch32(
3148                     MacroAssembler::AboveOrEqual, propertyReg,
3149                     MacroAssembler::Address(baseReg, OBJECT_OFFSETOF(Arguments, m_numArguments))));
3150             speculationCheck(
3151                 Uncountable, JSValueSource(), 0,
3152                 m_jit.branchTestPtr(
3153                     MacroAssembler::NonZero,
3154                     MacroAssembler::Address(
3155                         baseReg, OBJECT_OFFSETOF(Arguments, m_slowArguments))));
3156     
3157             m_jit.move(propertyReg, scratch2Reg);
3158             m_jit.signExtend32ToPtr(scratch2Reg, scratch2Reg);
3159             m_jit.loadPtr(
3160                 MacroAssembler::Address(baseReg, OBJECT_OFFSETOF(Arguments, m_registers)),
3161                 scratchReg);
3162             
3163             m_jit.store64(
3164                 valueReg,
3165                 MacroAssembler::BaseIndex(
3166                     scratchReg, scratch2Reg, MacroAssembler::TimesEight,
3167                     CallFrame::thisArgumentOffset() * sizeof(Register) + sizeof(Register)));
3168             
3169             noResult(node);
3170             break;
3171         }
3172             
3173         default: {
3174             TypedArrayType type = arrayMode.typedArrayType();
3175             if (isInt(type))
3176                 compilePutByValForIntTypedArray(base.gpr(), property.gpr(), node, type);
3177             else
3178                 compilePutByValForFloatTypedArray(base.gpr(), property.gpr(), node, type);
3179         } }
3180
3181         break;
3182     }
3183
3184     case RegExpExec: {
3185         if (compileRegExpExec(node))
3186             return;
3187         if (!node->adjustedRefCount()) {
3188             SpeculateCellOperand base(this, node->child1());
3189             SpeculateCellOperand argument(this, node->child2());
3190             GPRReg baseGPR = base.gpr();
3191             GPRReg argumentGPR = argument.gpr();
3192             
3193             flushRegisters();
3194             GPRResult result(this);
3195             callOperation(operationRegExpTest, result.gpr(), baseGPR, argumentGPR);
3196             
3197             // Must use jsValueResult because otherwise we screw up register
3198             // allocation, which thinks that this node has a result.
3199             jsValueResult(result.gpr(), node);
3200             break;
3201         }
3202
3203         SpeculateCellOperand base(this, node->child1());
3204         SpeculateCellOperand argument(this, node->child2());
3205         GPRReg baseGPR = base.gpr();
3206         GPRReg argumentGPR = argument.gpr();
3207         
3208         flushRegisters();
3209         GPRResult result(this);
3210         callOperation(operationRegExpExec, result.gpr(), baseGPR, argumentGPR);
3211         
3212         jsValueResult(result.gpr(), node);
3213         break;
3214     }
3215
3216     case RegExpTest: {
3217         SpeculateCellOperand base(this, node->child1());
3218         SpeculateCellOperand argument(this, node->child2());
3219         GPRReg baseGPR = base.gpr();
3220         GPRReg argumentGPR = argument.gpr();
3221         
3222         flushRegisters();
3223         GPRResult result(this);
3224         callOperation(operationRegExpTest, result.gpr(), baseGPR, argumentGPR);
3225         
3226         // If we add a DataFormatBool, we should use it here.
3227         m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
3228         jsValueResult(result.gpr(), node, DataFormatJSBoolean);
3229         break;
3230     }
3231         
3232     case ArrayPush: {
3233         ASSERT(node->arrayMode().isJSArray());
3234         
3235         SpeculateCellOperand base(this, node->child1());
3236         GPRTemporary storageLength(this);
3237         
3238         GPRReg baseGPR = base.gpr();
3239         GPRReg storageLengthGPR = storageLength.gpr();
3240         
3241         StorageOperand storage(this, node->child3());
3242         GPRReg storageGPR = storage.gpr();
3243
3244         switch (node->arrayMode().type()) {
3245         case Array::Int32:
3246         case Array::Contiguous: {
3247             JSValueOperand value(this, node->child2(), ManualOperandSpeculation);
3248             GPRReg valueGPR = value.gpr();
3249
3250             if (node->arrayMode().type() == Array::Int32) {
3251                 DFG_TYPE_CHECK(
3252                     JSValueRegs(valueGPR), node->child2(), SpecInt32,
3253                     m_jit.branch64(
3254                         MacroAssembler::Below, valueGPR, GPRInfo::tagTypeNumberRegister));
3255             }
3256
3257             if (node->arrayMode().type() != Array::Int32 && Heap::isWriteBarrierEnabled()) {
3258                 GPRTemporary scratch(this);
3259                 writeBarrier(baseGPR, valueGPR, node->child2(), WriteBarrierForPropertyAccess, scratch.gpr(), storageLengthGPR);
3260             }
3261             
3262             m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
3263             MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
3264             m_jit.store64(valueGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
3265             m_jit.add32(TrustedImm32(1), storageLengthGPR);
3266             m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
3267             m_jit.or64(GPRInfo::tagTypeNumberRegister, storageLengthGPR);
3268             
3269             addSlowPathGenerator(
3270                 slowPathCall(
3271                     slowPath, this, operationArrayPush, NoResult, storageLengthGPR,
3272                     valueGPR, baseGPR));
3273         
3274             jsValueResult(storageLengthGPR, node);
3275             break;
3276         }
3277             
3278         case Array::Double: {
3279             SpeculateDoubleOperand value(this, node->child2());
3280             FPRReg valueFPR = value.fpr();
3281
3282             DFG_TYPE_CHECK(
3283                 JSValueRegs(), node->child2(), SpecFullRealNumber,
3284                 m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, valueFPR, valueFPR));
3285             
3286             m_jit.load32(MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
3287             MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
3288             m_jit.storeDouble(valueFPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
3289             m_jit.add32(TrustedImm32(1), storageLengthGPR);
3290             m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
3291             m_jit.or64(GPRInfo::tagTypeNumberRegister, storageLengthGPR);
3292             
3293             addSlowPathGenerator(
3294                 slowPathCall(
3295                     slowPath, this, operationArrayPushDouble, NoResult, storageLengthGPR,
3296                     valueFPR, baseGPR));
3297         
3298             jsValueResult(storageLengthGPR, node);
3299             break;
3300         }
3301             
3302         case Array::ArrayStorage: {
3303             JSValueOperand value(this, node->child2());
3304             GPRReg valueGPR = value.gpr();
3305
3306             if (Heap::isWriteBarrierEnabled()) {
3307                 GPRTemporary scratch(this);
3308                 writeBarrier(baseGPR, valueGPR, node->child2(), WriteBarrierForPropertyAccess, scratch.gpr(), storageLengthGPR);
3309             }
3310
3311             m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
3312         
3313             // Refuse to handle bizarre lengths.
3314             speculationCheck(Uncountable, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::Above, storageLengthGPR, TrustedImm32(0x7ffffffe)));
3315         
3316             MacroAssembler::Jump slowPath = m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset()));
3317         
3318             m_jit.store64(valueGPR, MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
3319         
3320             m_jit.add32(TrustedImm32(1), storageLengthGPR);
3321             m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()));
3322             m_jit.add32(TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
3323             m_jit.or64(GPRInfo::tagTypeNumberRegister, storageLengthGPR);
3324         
3325             addSlowPathGenerator(
3326                 slowPathCall(
3327                     slowPath, this, operationArrayPush, NoResult, storageLengthGPR,
3328                     valueGPR, baseGPR));
3329         
3330             jsValueResult(storageLengthGPR, node);
3331             break;
3332         }
3333             
3334         default:
3335             CRASH();
3336             break;
3337         }
3338         break;
3339     }
3340         
3341     case ArrayPop: {
3342         ASSERT(node->arrayMode().isJSArray());
3343
3344         SpeculateCellOperand base(this, node->child1());
3345         StorageOperand storage(this, node->child2());
3346         GPRTemporary value(this);
3347         GPRTemporary storageLength(this);
3348         FPRTemporary temp(this); // This is kind of lame, since we don't always need it. I'm relying on the fact that we don't have FPR pressure, especially in code that uses pop().
3349         
3350         GPRReg baseGPR = base.gpr();
3351         GPRReg storageGPR = storage.gpr();
3352         GPRReg valueGPR = value.gpr();
3353         GPRReg storageLengthGPR = storageLength.gpr();
3354         FPRReg tempFPR = temp.fpr();
3355         
3356         switch (node->arrayMode().type()) {
3357         case Array::Int32:
3358         case Array::Double:
3359         case Array::Contiguous: {
3360             m_jit.load32(
3361                 MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()), storageLengthGPR);
3362             MacroAssembler::Jump undefinedCase =
3363                 m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR);
3364             m_jit.sub32(TrustedImm32(1), storageLengthGPR);
3365             m_jit.store32(
3366                 storageLengthGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
3367             MacroAssembler::Jump slowCase;
3368             if (node->arrayMode().type() == Array::Double) {
3369                 m_jit.loadDouble(
3370                     MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight),
3371                     tempFPR);
3372                 // FIXME: This would not have to be here if changing the publicLength also zeroed the values between the old
3373                 // length and the new length.
3374                 m_jit.store64(
3375                 MacroAssembler::TrustedImm64((int64_t)0), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
3376                 slowCase = m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, tempFPR, tempFPR);
3377                 boxDouble(tempFPR, valueGPR);
3378             } else {
3379                 m_jit.load64(
3380                     MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight),
3381                     valueGPR);
3382                 // FIXME: This would not have to be here if changing the publicLength also zeroed the values between the old
3383                 // length and the new length.
3384                 m_jit.store64(
3385                 MacroAssembler::TrustedImm64((int64_t)0), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight));
3386                 slowCase = m_jit.branchTest64(MacroAssembler::Zero, valueGPR);
3387             }
3388
3389             addSlowPathGenerator(
3390                 slowPathMove(
3391                     undefinedCase, this,
3392                     MacroAssembler::TrustedImm64(JSValue::encode(jsUndefined())), valueGPR));
3393             addSlowPathGenerator(
3394                 slowPathCall(
3395                     slowCase, this, operationArrayPopAndRecoverLength, valueGPR, baseGPR));
3396             
3397             // We can't know for sure that the result is an int because of the slow paths. :-/
3398             jsValueResult(valueGPR, node);
3399             break;
3400         }
3401             
3402         case Array::ArrayStorage: {
3403             m_jit.load32(MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()), storageLengthGPR);
3404         
3405             JITCompiler::Jump undefinedCase =
3406                 m_jit.branchTest32(MacroAssembler::Zero, storageLengthGPR);
3407         
3408             m_jit.sub32(TrustedImm32(1), storageLengthGPR);
3409         
3410             JITCompiler::JumpList slowCases;
3411             slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset())));
3412         
3413             m_jit.load64(MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])), valueGPR);
3414             slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, valueGPR));
3415         
3416             m_jit.store32(storageLengthGPR, MacroAssembler::Address(storageGPR, ArrayStorage::lengthOffset()));
3417         
3418             m_jit.store64(MacroAssembler::TrustedImm64((int64_t)0), MacroAssembler::BaseIndex(storageGPR, storageLengthGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
3419             m_jit.sub32(MacroAssembler::TrustedImm32(1), MacroAssembler::Address(storageGPR, OBJECT_OFFSETOF(ArrayStorage, m_numValuesInVector)));
3420         
3421             addSlowPathGenerator(
3422                 slowPathMove(
3423                     undefinedCase, this,
3424                     MacroAssembler::TrustedImm64(JSValue::encode(jsUndefined())), valueGPR));
3425         
3426             addSlowPathGenerator(
3427                 slowPathCall(
3428                     slowCases, this, operationArrayPop, valueGPR, baseGPR));
3429
3430             jsValueResult(valueGPR, node);
3431             break;
3432         }
3433             
3434         default:
3435             CRASH();
3436             break;
3437         }
3438         break;
3439     }
3440
3441     case DFG::Jump: {
3442         jump(node->takenBlock());
3443         noResult(node);
3444         break;
3445     }
3446
3447     case Branch:
3448         emitBranch(node);
3449         break;
3450         
3451     case Switch:
3452         emitSwitch(node);
3453         break;
3454
3455     case Return: {
3456         ASSERT(GPRInfo::callFrameRegister != GPRInfo::regT1);
3457         ASSERT(GPRInfo::regT1 != GPRInfo::returnValueGPR);
3458         ASSERT(GPRInfo::returnValueGPR != GPRInfo::callFrameRegister);
3459
3460 #if DFG_ENABLE(SUCCESS_STATS)
3461         static SamplingCounter counter("SpeculativeJIT");
3462         m_jit.emitCount(counter);
3463 #endif
3464
3465         // Return the result in returnValueGPR.
3466         JSValueOperand op1(this, node->child1());
3467         m_jit.move(op1.gpr(), GPRInfo::returnValueGPR);
3468
3469         // Grab the return address.
3470         m_jit.emitGetFromCallFrameHeaderPtr(JSStack::ReturnPC, GPRInfo::regT1);
3471         // Restore our caller's "r".
3472         m_jit.emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, GPRInfo::callFrameRegister);
3473         // Return.
3474         m_jit.restoreReturnAddressBeforeReturn(GPRInfo::regT1);
3475         m_jit.ret();
3476         
3477         noResult(node);
3478         break;
3479     }
3480         
3481     case Throw:
3482     case ThrowReferenceError: {
3483         // We expect that throw statements are rare and are intended to exit the code block
3484         // anyway, so we just OSR back to the old JIT for now.
3485         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
3486         break;
3487     }
3488         
3489     case ToPrimitive: {
3490         RELEASE_ASSERT(node->child1().useKind() == UntypedUse);
3491         JSValueOperand op1(this, node->child1());
3492         GPRTemporary result(this, Reuse, op1);
3493         
3494         GPRReg op1GPR = op1.gpr();
3495         GPRReg resultGPR = result.gpr();
3496         
3497         op1.use();
3498         
3499         if (!(m_state.forNode(node->child1()).m_type & ~(SpecFullNumber | SpecBoolean)))
3500             m_jit.move(op1GPR, resultGPR);
3501         else {
3502             MacroAssembler::Jump alreadyPrimitive = m_jit.branchTest64(MacroAssembler::NonZero, op1GPR, GPRInfo::tagMaskRegister);
3503             MacroAssembler::Jump notPrimitive = m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR, JSCell::structureOffset()), MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get()));
3504             
3505             alreadyPrimitive.link(&m_jit);
3506             m_jit.move(op1GPR, resultGPR);
3507             
3508             addSlowPathGenerator(
3509                 slowPathCall(notPrimitive, this, operationToPrimitive, resultGPR, op1GPR));
3510         }
3511         
3512         jsValueResult(resultGPR, node, UseChildrenCalledExplicitly);
3513         break;
3514     }
3515         
3516     case ToString: {
3517         if (node->child1().useKind() == UntypedUse) {
3518             JSValueOperand op1(this, node->child1());
3519             GPRReg op1GPR = op1.gpr();
3520             
3521             GPRResult result(this);
3522             GPRReg resultGPR = result.gpr();
3523             
3524             flushRegisters();
3525             
3526             JITCompiler::Jump done;
3527             if (node->child1()->prediction() & SpecString) {
3528                 JITCompiler::Jump slowPath1 = m_jit.branchTest64(
3529                     JITCompiler::NonZero, op1GPR, GPRInfo::tagMaskRegister);
3530                 JITCompiler::Jump slowPath2 = m_jit.branchPtr(
3531                     JITCompiler::NotEqual,
3532                     JITCompiler::Address(op1GPR, JSCell::structureOffset()),
3533                     TrustedImmPtr(m_jit.vm()->stringStructure.get()));
3534                 m_jit.move(op1GPR, resultGPR);
3535                 done = m_jit.jump();
3536                 slowPath1.link(&m_jit);
3537                 slowPath2.link(&m_jit);
3538             }
3539             callOperation(operationToString, resultGPR, op1GPR);
3540             if (done.isSet())
3541                 done.link(&m_jit);
3542             cellResult(resultGPR, node);
3543             break;
3544         }
3545         
3546         compileToStringOnCell(node);
3547         break;
3548     }
3549         
3550     case NewStringObject: {
3551         compileNewStringObject(node);
3552         break;
3553     }
3554         
3555     case NewArray: {
3556         JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->codeOrigin);
3557         if (!globalObject->isHavingABadTime() && !hasArrayStorage(node->indexingType())) {
3558             m_jit.addLazily(
3559                 speculationWatchpoint(),
3560                 globalObject->havingABadTimeWatchpoint());
3561             
3562             Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType());
3563             RELEASE_ASSERT(structure->indexingType() == node->indexingType());
3564             ASSERT(
3565                 hasUndecided(structure->indexingType())
3566                 || hasInt32(structure->indexingType())
3567                 || hasDouble(structure->indexingType())
3568                 || hasContiguous(structure->indexingType()));
3569             
3570             unsigned numElements = node->numChildren();
3571             
3572             GPRTemporary result(this);
3573             GPRTemporary storage(this);
3574             
3575             GPRReg resultGPR = result.gpr();
3576             GPRReg storageGPR = storage.gpr();
3577
3578             emitAllocateJSArray(resultGPR, structure, storageGPR, numElements);
3579             
3580             // At this point, one way or another, resultGPR and storageGPR have pointers to
3581             // the JSArray and the Butterfly, respectively.
3582             
3583             ASSERT(!hasUndecided(structure->indexingType()) || !node->numChildren());
3584             
3585             for (unsigned operandIdx = 0; operandIdx < node->numChildren(); ++operandIdx) {
3586                 Edge use = m_jit.graph().m_varArgChildren[node->firstChild() + operandIdx];
3587                 switch (node->indexingType()) {
3588                 case ALL_BLANK_INDEXING_TYPES:
3589                 case ALL_UNDECIDED_INDEXING_TYPES:
3590                     CRASH();
3591                     break;
3592                 case ALL_DOUBLE_INDEXING_TYPES: {
3593                     SpeculateDoubleOperand operand(this, use);
3594                     FPRReg opFPR = operand.fpr();
3595                     DFG_TYPE_CHECK(
3596                         JSValueRegs(), use, SpecFullRealNumber,
3597                         m_jit.branchDouble(
3598                             MacroAssembler::DoubleNotEqualOrUnordered, opFPR, opFPR));
3599                     m_jit.storeDouble(opFPR, MacroAssembler::Address(storageGPR, sizeof(double) * operandIdx));
3600                     break;
3601                 }
3602                 case ALL_INT32_INDEXING_TYPES:
3603                 case ALL_CONTIGUOUS_INDEXING_TYPES: {
3604                     JSValueOperand operand(this, use, ManualOperandSpeculation);
3605                     GPRReg opGPR = operand.gpr();
3606                     if (hasInt32(node->indexingType())) {
3607                         DFG_TYPE_CHECK(
3608                             JSValueRegs(opGPR), use, SpecInt32,
3609                             m_jit.branch64(
3610                                 MacroAssembler::Below, opGPR, GPRInfo::tagTypeNumberRegister));
3611                     }
3612                     m_jit.store64(opGPR, MacroAssembler::Address(storageGPR, sizeof(JSValue) * operandIdx));
3613                     break;
3614                 }
3615                 default:
3616                     CRASH();
3617                     break;
3618                 }
3619             }
3620             
3621             // Yuck, we should *really* have a way of also returning the storageGPR. But
3622             // that's the least of what's wrong with this code. We really shouldn't be
3623             // allocating the array after having computed - and probably spilled to the
3624             // stack - all of the things that will go into the array. The solution to that
3625             // bigger problem will also likely fix the redundancy in reloading the storage
3626             // pointer that we currently have.
3627             
3628             cellResult(resultGPR, node);
3629             break;
3630         }
3631         
3632         if (!node->numChildren()) {
3633             flushRegisters();
3634             GPRResult result(this);
3635             callOperation(operationNewEmptyArray, result.gpr(), globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
3636             cellResult(result.gpr(), node);
3637             break;
3638         }
3639         
3640         size_t scratchSize = sizeof(EncodedJSValue) * node->numChildren();
3641       &