Unreviewed, revert http://trac.webkit.org/changeset/156235. It won't work on Windows.
[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.fillInt52(*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.fillStrictInt52(*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