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