e52a42e047ea1898f2282e7662aa161af5f91f25
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGSpeculativeJIT.cpp
1 /*
2  * Copyright (C) 2011 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 "DFGCallArrayAllocatorSlowPathGenerator.h"
33 #include "DFGSlowPathGenerator.h"
34 #include "LinkBuffer.h"
35
36 namespace JSC { namespace DFG {
37
38 SpeculativeJIT::SpeculativeJIT(JITCompiler& jit)
39     : m_compileOkay(true)
40     , m_jit(jit)
41     , m_compileIndex(0)
42     , m_indexInBlock(0)
43     , m_generationInfo(m_jit.codeBlock()->m_numCalleeRegisters)
44     , m_blockHeads(jit.graph().m_blocks.size())
45     , m_arguments(jit.codeBlock()->numParameters())
46     , m_variables(jit.graph().m_localVars)
47     , m_lastSetOperand(std::numeric_limits<int>::max())
48     , m_state(m_jit.graph())
49     , m_stream(&jit.codeBlock()->variableEventStream())
50     , m_minifiedGraph(&jit.codeBlock()->minifiedDFG())
51     , m_isCheckingArgumentTypes(false)
52 {
53 }
54
55 SpeculativeJIT::~SpeculativeJIT()
56 {
57     WTF::deleteAllValues(m_slowPathGenerators);
58 }
59
60 void SpeculativeJIT::emitAllocateJSArray(Structure* structure, GPRReg resultGPR, GPRReg storageGPR, unsigned numElements)
61 {
62     ASSERT(hasUndecided(structure->indexingType()) || hasInt32(structure->indexingType()) || hasDouble(structure->indexingType()) || hasContiguous(structure->indexingType()));
63     
64     GPRTemporary scratch(this);
65     GPRReg scratchGPR = scratch.gpr();
66     
67     unsigned vectorLength = std::max(BASE_VECTOR_LEN, numElements);
68     
69     JITCompiler::JumpList slowCases;
70     
71     slowCases.append(
72         emitAllocateBasicStorage(TrustedImm32(vectorLength * sizeof(JSValue) + sizeof(IndexingHeader)), storageGPR));
73     m_jit.subPtr(TrustedImm32(vectorLength * sizeof(JSValue)), storageGPR);
74     emitAllocateBasicJSObject<JSArray, MarkedBlock::None>(
75         TrustedImmPtr(structure), resultGPR, scratchGPR,
76         storageGPR, sizeof(JSArray), slowCases);
77     
78     // I'm assuming that two 32-bit stores are better than a 64-bit store.
79     // I have no idea if that's true. And it probably doesn't matter anyway.
80     m_jit.store32(TrustedImm32(numElements), MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
81     m_jit.store32(TrustedImm32(vectorLength), MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
82     
83     if (hasDouble(structure->indexingType()) && numElements < vectorLength) {
84 #if USE(JSVALUE64)
85         m_jit.move(TrustedImm64(bitwise_cast<int64_t>(QNaN)), scratchGPR);
86         for (unsigned i = numElements; i < vectorLength; ++i)
87             m_jit.store64(scratchGPR, MacroAssembler::Address(storageGPR, sizeof(double) * i));
88 #else
89         EncodedValueDescriptor value;
90         value.asInt64 = JSValue::encode(JSValue(JSValue::EncodeAsDouble, QNaN));
91         for (unsigned i = numElements; i < vectorLength; ++i) {
92             m_jit.store32(TrustedImm32(value.asBits.tag), MacroAssembler::Address(storageGPR, sizeof(double) * i + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
93             m_jit.store32(TrustedImm32(value.asBits.payload), MacroAssembler::Address(storageGPR, sizeof(double) * i + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
94         }
95 #endif
96     }
97     
98     // I want a slow path that also loads out the storage pointer, and that's
99     // what this custom CallArrayAllocatorSlowPathGenerator gives me. It's a lot
100     // of work for a very small piece of functionality. :-/
101     addSlowPathGenerator(adoptPtr(
102         new CallArrayAllocatorSlowPathGenerator(
103             slowCases, this, operationNewArrayWithSize, resultGPR, storageGPR,
104             structure, numElements)));
105 }
106
107 void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::Jump jumpToFail)
108 {
109     if (!m_compileOkay)
110         return;
111     ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
112     m_jit.codeBlock()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(nodeIndex), jumpToFail, this, m_stream->size()));
113 }
114
115 void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail)
116 {
117     ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
118     speculationCheck(kind, jsValueSource, nodeUse.index(), jumpToFail);
119 }
120
121 void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, const MacroAssembler::JumpList& jumpsToFail)
122 {
123     ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
124     Vector<MacroAssembler::Jump, 16> jumpVector = jumpsToFail.jumps();
125     for (unsigned i = 0; i < jumpVector.size(); ++i)
126         speculationCheck(kind, jsValueSource, nodeIndex, jumpVector[i]);
127 }
128
129 void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, const MacroAssembler::JumpList& jumpsToFail)
130 {
131     ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
132     speculationCheck(kind, jsValueSource, nodeUse.index(), jumpsToFail);
133 }
134
135 void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery)
136 {
137     if (!m_compileOkay)
138         return;
139     ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
140     m_jit.codeBlock()->appendSpeculationRecovery(recovery);
141     m_jit.codeBlock()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(nodeIndex), jumpToFail, this, m_stream->size(), m_jit.codeBlock()->numberOfSpeculationRecoveries()));
142 }
143
144 void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery)
145 {
146     ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
147     speculationCheck(kind, jsValueSource, nodeUse.index(), jumpToFail, recovery);
148 }
149
150 JumpReplacementWatchpoint* SpeculativeJIT::speculationWatchpoint(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex)
151 {
152     if (!m_compileOkay)
153         return 0;
154     ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
155     OSRExit& exit = m_jit.codeBlock()->osrExit(
156         m_jit.codeBlock()->appendOSRExit(
157             OSRExit(kind, jsValueSource,
158                     m_jit.graph().methodOfGettingAValueProfileFor(nodeIndex),
159                     JITCompiler::Jump(), this, m_stream->size())));
160     exit.m_watchpointIndex = m_jit.codeBlock()->appendWatchpoint(
161         JumpReplacementWatchpoint(m_jit.watchpointLabel()));
162     return &m_jit.codeBlock()->watchpoint(exit.m_watchpointIndex);
163 }
164
165 JumpReplacementWatchpoint* SpeculativeJIT::speculationWatchpoint(ExitKind kind)
166 {
167     return speculationWatchpoint(kind, JSValueSource(), NoNode);
168 }
169
170 void SpeculativeJIT::convertLastOSRExitToForward(const ValueRecovery& valueRecovery)
171 {
172     if (!valueRecovery) {
173         // Check that the preceding node was a SetLocal with the same code origin.
174         Node* setLocal = &at(m_jit.graph().m_blocks[m_block]->at(m_indexInBlock - 1));
175         ASSERT_UNUSED(setLocal, setLocal->op() == SetLocal);
176         ASSERT_UNUSED(setLocal, setLocal->codeOrigin == at(m_compileIndex).codeOrigin);
177         
178         // Find the next node.
179         unsigned indexInBlock = m_indexInBlock + 1;
180         Node* node = 0;
181         for (;;) {
182             if (indexInBlock == m_jit.graph().m_blocks[m_block]->size()) {
183                 // This is an inline return. Give up and do a backwards speculation. This is safe
184                 // because an inline return has its own bytecode index and it's always safe to
185                 // reexecute that bytecode.
186                 ASSERT(node->op() == Jump);
187                 return;
188             }
189             node = &at(m_jit.graph().m_blocks[m_block]->at(indexInBlock));
190             if (node->codeOrigin != at(m_compileIndex).codeOrigin)
191                 break;
192             indexInBlock++;
193         }
194         
195         ASSERT(node->codeOrigin != at(m_compileIndex).codeOrigin);
196         OSRExit& exit = m_jit.codeBlock()->lastOSRExit();
197         exit.m_codeOrigin = node->codeOrigin;
198         return;
199     }
200     
201     unsigned setLocalIndexInBlock = m_indexInBlock + 1;
202     
203     Node* setLocal = &at(m_jit.graph().m_blocks[m_block]->at(setLocalIndexInBlock));
204     bool hadInt32ToDouble = false;
205     
206     if (setLocal->op() == Int32ToDouble) {
207         setLocal = &at(m_jit.graph().m_blocks[m_block]->at(++setLocalIndexInBlock));
208         hadInt32ToDouble = true;
209     }
210     if (setLocal->op() == Flush || setLocal->op() == Phantom)
211         setLocal = &at(m_jit.graph().m_blocks[m_block]->at(++setLocalIndexInBlock));
212         
213     if (hadInt32ToDouble)
214         ASSERT(at(setLocal->child1()).child1() == m_compileIndex);
215     else
216         ASSERT(setLocal->child1() == m_compileIndex);
217     ASSERT(setLocal->op() == SetLocal);
218     ASSERT(setLocal->codeOrigin == at(m_compileIndex).codeOrigin);
219
220     Node* nextNode = &at(m_jit.graph().m_blocks[m_block]->at(setLocalIndexInBlock + 1));
221     if (nextNode->op() == Jump && nextNode->codeOrigin == at(m_compileIndex).codeOrigin) {
222         // We're at an inlined return. Use a backward speculation instead.
223         return;
224     }
225     ASSERT(nextNode->codeOrigin != at(m_compileIndex).codeOrigin);
226         
227     OSRExit& exit = m_jit.codeBlock()->lastOSRExit();
228     exit.m_codeOrigin = nextNode->codeOrigin;
229         
230     exit.m_lastSetOperand = setLocal->local();
231     exit.m_valueRecoveryOverride = adoptRef(
232         new ValueRecoveryOverride(setLocal->local(), valueRecovery));
233 }
234
235 JumpReplacementWatchpoint* SpeculativeJIT::forwardSpeculationWatchpoint(ExitKind kind)
236 {
237     JumpReplacementWatchpoint* result = speculationWatchpoint(kind);
238     convertLastOSRExitToForward();
239     return result;
240 }
241
242 JumpReplacementWatchpoint* SpeculativeJIT::speculationWatchpointWithConditionalDirection(ExitKind kind, bool isForward)
243 {
244     JumpReplacementWatchpoint* result = speculationWatchpoint(kind);
245     if (isForward)
246         convertLastOSRExitToForward();
247     return result;
248 }
249
250 void SpeculativeJIT::forwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::Jump jumpToFail, const ValueRecovery& valueRecovery)
251 {
252     ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
253     speculationCheck(kind, jsValueSource, nodeIndex, jumpToFail);
254     convertLastOSRExitToForward(valueRecovery);
255 }
256
257 void SpeculativeJIT::forwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, const MacroAssembler::JumpList& jumpsToFail, const ValueRecovery& valueRecovery)
258 {
259     ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
260     Vector<MacroAssembler::Jump, 16> jumpVector = jumpsToFail.jumps();
261     for (unsigned i = 0; i < jumpVector.size(); ++i)
262         forwardSpeculationCheck(kind, jsValueSource, nodeIndex, jumpVector[i], valueRecovery);
263 }
264
265 void SpeculativeJIT::speculationCheckWithConditionalDirection(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::Jump jumpToFail, bool isForward)
266 {
267     if (isForward)
268         forwardSpeculationCheck(kind, jsValueSource, nodeIndex, jumpToFail);
269     else
270         speculationCheck(kind, jsValueSource, nodeIndex, jumpToFail);
271 }
272
273 void SpeculativeJIT::terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, NodeIndex nodeIndex)
274 {
275     ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
276 #if DFG_ENABLE(DEBUG_VERBOSE)
277     dataLog("SpeculativeJIT was terminated.\n");
278 #endif
279     if (!m_compileOkay)
280         return;
281     speculationCheck(kind, jsValueRegs, nodeIndex, m_jit.jump());
282     m_compileOkay = false;
283 }
284
285 void SpeculativeJIT::terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, Edge nodeUse)
286 {
287     ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
288     terminateSpeculativeExecution(kind, jsValueRegs, nodeUse.index());
289 }
290
291 void SpeculativeJIT::terminateSpeculativeExecutionWithConditionalDirection(ExitKind kind, JSValueRegs jsValueRegs, NodeIndex nodeIndex, bool isForward)
292 {
293     ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
294 #if DFG_ENABLE(DEBUG_VERBOSE)
295     dataLog("SpeculativeJIT was terminated.\n");
296 #endif
297     if (!m_compileOkay)
298         return;
299     speculationCheckWithConditionalDirection(kind, jsValueRegs, nodeIndex, m_jit.jump(), isForward);
300     m_compileOkay = false;
301 }
302
303 void SpeculativeJIT::addSlowPathGenerator(PassOwnPtr<SlowPathGenerator> slowPathGenerator)
304 {
305     m_slowPathGenerators.append(slowPathGenerator.leakPtr());
306 }
307
308 void SpeculativeJIT::runSlowPathGenerators()
309 {
310 #if DFG_ENABLE(DEBUG_VERBOSE)
311     dataLog("Running %lu slow path generators.\n", m_slowPathGenerators.size());
312 #endif
313     for (unsigned i = 0; i < m_slowPathGenerators.size(); ++i)
314         m_slowPathGenerators[i]->generate(this);
315 }
316
317 // On Windows we need to wrap fmod; on other platforms we can call it directly.
318 // On ARMv7 we assert that all function pointers have to low bit set (point to thumb code).
319 #if CALLING_CONVENTION_IS_STDCALL || CPU(ARM_THUMB2)
320 static double DFG_OPERATION fmodAsDFGOperation(double x, double y)
321 {
322     return fmod(x, y);
323 }
324 #else
325 #define fmodAsDFGOperation fmod
326 #endif
327
328 void SpeculativeJIT::clearGenerationInfo()
329 {
330     for (unsigned i = 0; i < m_generationInfo.size(); ++i)
331         m_generationInfo[i] = GenerationInfo();
332     m_gprs = RegisterBank<GPRInfo>();
333     m_fprs = RegisterBank<FPRInfo>();
334 }
335
336 const TypedArrayDescriptor* SpeculativeJIT::typedArrayDescriptor(ArrayMode arrayMode)
337 {
338     switch (arrayMode.type()) {
339     case Array::Int8Array:
340         return &m_jit.globalData()->int8ArrayDescriptor();
341     case Array::Int16Array:
342         return &m_jit.globalData()->int16ArrayDescriptor();
343     case Array::Int32Array:
344         return &m_jit.globalData()->int32ArrayDescriptor();
345     case Array::Uint8Array:
346         return &m_jit.globalData()->uint8ArrayDescriptor();
347     case Array::Uint8ClampedArray:
348         return &m_jit.globalData()->uint8ClampedArrayDescriptor();
349     case Array::Uint16Array:
350         return &m_jit.globalData()->uint16ArrayDescriptor();
351     case Array::Uint32Array:
352         return &m_jit.globalData()->uint32ArrayDescriptor();
353     case Array::Float32Array:
354         return &m_jit.globalData()->float32ArrayDescriptor();
355     case Array::Float64Array:
356         return &m_jit.globalData()->float64ArrayDescriptor();
357     default:
358         return 0;
359     }
360 }
361
362 JITCompiler::Jump SpeculativeJIT::jumpSlowForUnwantedArrayMode(GPRReg tempGPR, ArrayMode arrayMode, IndexingType shape, bool invert)
363 {
364     switch (arrayMode.arrayClass()) {
365     case Array::OriginalArray: {
366         CRASH();
367         JITCompiler::Jump result; // I already know that VC++ takes unkindly to the expression "return Jump()", so I'm doing it this way in anticipation of someone eventually using VC++ to compile the DFG.
368         return result;
369     }
370         
371     case Array::Array:
372         m_jit.and32(TrustedImm32(IsArray | IndexingShapeMask), tempGPR);
373         return m_jit.branch32(
374             invert ? MacroAssembler::Equal : MacroAssembler::NotEqual, tempGPR, TrustedImm32(IsArray | shape));
375         
376     default:
377         m_jit.and32(TrustedImm32(IndexingShapeMask), tempGPR);
378         return m_jit.branch32(invert ? MacroAssembler::Equal : MacroAssembler::NotEqual, tempGPR, TrustedImm32(shape));
379     }
380 }
381
382 JITCompiler::JumpList SpeculativeJIT::jumpSlowForUnwantedArrayMode(GPRReg tempGPR, ArrayMode arrayMode, bool invert)
383 {
384     JITCompiler::JumpList result;
385     
386     switch (arrayMode.type()) {
387     case Array::Int32:
388         return jumpSlowForUnwantedArrayMode(tempGPR, arrayMode, Int32Shape, invert);
389
390     case Array::Double:
391         return jumpSlowForUnwantedArrayMode(tempGPR, arrayMode, DoubleShape, invert);
392
393     case Array::Contiguous:
394         return jumpSlowForUnwantedArrayMode(tempGPR, arrayMode, ContiguousShape, invert);
395
396     case Array::ArrayStorage:
397     case Array::SlowPutArrayStorage: {
398         ASSERT(!arrayMode.isJSArrayWithOriginalStructure());
399         
400         if (arrayMode.isJSArray()) {
401             if (arrayMode.isSlowPut()) {
402                 if (invert) {
403                     JITCompiler::Jump slow = m_jit.branchTest32(
404                         MacroAssembler::Zero, tempGPR, MacroAssembler::TrustedImm32(IsArray));
405                     m_jit.and32(TrustedImm32(IndexingShapeMask), tempGPR);
406                     m_jit.sub32(TrustedImm32(ArrayStorageShape), tempGPR);
407                     result.append(
408                         m_jit.branch32(
409                             MacroAssembler::BelowOrEqual, tempGPR,
410                             TrustedImm32(SlowPutArrayStorageShape - ArrayStorageShape)));
411                     
412                     slow.link(&m_jit);
413                 }
414                 
415                 result.append(
416                     m_jit.branchTest32(
417                         MacroAssembler::Zero, tempGPR, MacroAssembler::TrustedImm32(IsArray)));
418                 m_jit.and32(TrustedImm32(IndexingShapeMask), tempGPR);
419                 m_jit.sub32(TrustedImm32(ArrayStorageShape), tempGPR);
420                 result.append(
421                     m_jit.branch32(
422                         MacroAssembler::Above, tempGPR,
423                         TrustedImm32(SlowPutArrayStorageShape - ArrayStorageShape)));
424                 break;
425             }
426             m_jit.and32(TrustedImm32(IsArray | IndexingShapeMask), tempGPR);
427             result.append(
428                 m_jit.branch32(invert ? MacroAssembler::Equal : MacroAssembler::NotEqual, tempGPR, TrustedImm32(ArrayStorageShape)));
429             break;
430         }
431         m_jit.and32(TrustedImm32(IndexingShapeMask), tempGPR);
432         if (arrayMode.isSlowPut()) {
433             m_jit.sub32(TrustedImm32(ArrayStorageShape), tempGPR);
434             result.append(
435                 m_jit.branch32(
436                     invert ? MacroAssembler::BelowOrEqual : MacroAssembler::Above, tempGPR,
437                     TrustedImm32(SlowPutArrayStorageShape - ArrayStorageShape)));
438             break;
439         }
440         result.append(
441             m_jit.branch32(invert ? MacroAssembler::Equal : MacroAssembler::NotEqual, tempGPR, TrustedImm32(ArrayStorageShape)));
442         break;
443     }
444     default:
445         CRASH();
446         break;
447     }
448     
449     return result;
450 }
451
452 void SpeculativeJIT::checkArray(Node& node)
453 {
454     ASSERT(node.arrayMode().isSpecific());
455     ASSERT(!node.arrayMode().doesConversion());
456     
457     SpeculateCellOperand base(this, node.child1());
458     GPRReg baseReg = base.gpr();
459     
460     const TypedArrayDescriptor* result = typedArrayDescriptor(node.arrayMode());
461     
462     if (node.arrayMode().alreadyChecked(m_jit.graph(), node, m_state.forNode(node.child1()))) {
463         noResult(m_compileIndex);
464         return;
465     }
466     
467     const ClassInfo* expectedClassInfo = 0;
468     
469     switch (node.arrayMode().type()) {
470     case Array::String:
471         expectedClassInfo = &JSString::s_info;
472         break;
473     case Array::Int32:
474     case Array::Double:
475     case Array::Contiguous:
476     case Array::ArrayStorage:
477     case Array::SlowPutArrayStorage: {
478         GPRTemporary temp(this);
479         GPRReg tempGPR = temp.gpr();
480         m_jit.loadPtr(
481             MacroAssembler::Address(baseReg, JSCell::structureOffset()), tempGPR);
482         m_jit.load8(MacroAssembler::Address(tempGPR, Structure::indexingTypeOffset()), tempGPR);
483         speculationCheck(
484             BadIndexingType, JSValueSource::unboxedCell(baseReg), NoNode,
485             jumpSlowForUnwantedArrayMode(tempGPR, node.arrayMode()));
486         
487         noResult(m_compileIndex);
488         return;
489     }
490     case Array::Arguments:
491         expectedClassInfo = &Arguments::s_info;
492         break;
493     case Array::Int8Array:
494     case Array::Int16Array:
495     case Array::Int32Array:
496     case Array::Uint8Array:
497     case Array::Uint8ClampedArray:
498     case Array::Uint16Array:
499     case Array::Uint32Array:
500     case Array::Float32Array:
501     case Array::Float64Array:
502         expectedClassInfo = result->m_classInfo;
503         break;
504     default:
505         ASSERT_NOT_REACHED();
506         break;
507     }
508     
509     GPRTemporary temp(this);
510     m_jit.loadPtr(
511         MacroAssembler::Address(baseReg, JSCell::structureOffset()), temp.gpr());
512     speculationCheck(
513         Uncountable, JSValueRegs(), NoNode,
514         m_jit.branchPtr(
515             MacroAssembler::NotEqual,
516             MacroAssembler::Address(temp.gpr(), Structure::classInfoOffset()),
517             MacroAssembler::TrustedImmPtr(expectedClassInfo)));
518     
519     noResult(m_compileIndex);
520 }
521
522 void SpeculativeJIT::arrayify(Node& node, GPRReg baseReg, GPRReg propertyReg)
523 {
524     ASSERT(node.arrayMode().doesConversion());
525     
526     GPRTemporary temp(this);
527     GPRTemporary structure;
528     GPRReg tempGPR = temp.gpr();
529     GPRReg structureGPR = InvalidGPRReg;
530     
531     if (node.op() != ArrayifyToStructure) {
532         GPRTemporary realStructure(this);
533         structure.adopt(realStructure);
534         structureGPR = structure.gpr();
535     }
536         
537     // We can skip all that comes next if we already have array storage.
538     MacroAssembler::JumpList done;
539     
540     if (node.op() == ArrayifyToStructure) {
541         done.append(m_jit.branchWeakPtr(
542             JITCompiler::Equal,
543             JITCompiler::Address(baseReg, JSCell::structureOffset()),
544             node.structure()));
545     } else {
546         m_jit.loadPtr(
547             MacroAssembler::Address(baseReg, JSCell::structureOffset()), structureGPR);
548         
549         m_jit.load8(
550             MacroAssembler::Address(structureGPR, Structure::indexingTypeOffset()), tempGPR);
551         
552         done = jumpSlowForUnwantedArrayMode(tempGPR, node.arrayMode(), true);
553
554         // Next check that the object does not intercept indexed accesses. If it does,
555         // then this mode won't work.
556         speculationCheck(
557             BadIndexingType, JSValueSource::unboxedCell(baseReg), NoNode,
558             m_jit.branchTest8(
559                 MacroAssembler::NonZero,
560                 MacroAssembler::Address(structureGPR, Structure::typeInfoFlagsOffset()),
561                 MacroAssembler::TrustedImm32(InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero)));
562     }
563         
564     // If we're allegedly creating contiguous storage and the index is bogus, then
565     // just don't.
566     if (propertyReg != InvalidGPRReg) {
567         switch (node.arrayMode().type()) {
568         case Array::Int32:
569         case Array::Double:
570         case Array::Contiguous:
571             speculationCheck(
572                 Uncountable, JSValueRegs(), NoNode,
573                 m_jit.branch32(
574                     MacroAssembler::AboveOrEqual, propertyReg, TrustedImm32(MIN_SPARSE_ARRAY_INDEX)));
575             break;
576         default:
577             break;
578         }
579     }
580     
581     // Now call out to create the array storage.
582     silentSpillAllRegisters(tempGPR);
583     switch (node.arrayMode().type()) {
584     case Array::Int32:
585         callOperation(operationEnsureInt32, tempGPR, baseReg);
586         break;
587     case Array::Double:
588         callOperation(operationEnsureDouble, tempGPR, baseReg);
589         break;
590     case Array::Contiguous:
591         callOperation(operationEnsureContiguous, tempGPR, baseReg);
592         break;
593     case Array::ArrayStorage:
594     case Array::SlowPutArrayStorage:
595         callOperation(operationEnsureArrayStorage, tempGPR, baseReg);
596         break;
597     default:
598         CRASH();
599         break;
600     }
601     silentFillAllRegisters(tempGPR);
602     
603     if (node.op() == ArrayifyToStructure) {
604         speculationCheck(
605             BadIndexingType, JSValueSource::unboxedCell(baseReg), NoNode,
606             m_jit.branchWeakPtr(
607                 JITCompiler::NotEqual,
608                 JITCompiler::Address(baseReg, JSCell::structureOffset()),
609                 node.structure()));
610     } else {
611         // Alas, we need to reload the structure because silent spilling does not save
612         // temporaries. Nor would it be useful for it to do so. Either way we're talking
613         // about a load.
614         m_jit.loadPtr(
615             MacroAssembler::Address(baseReg, JSCell::structureOffset()), structureGPR);
616     
617         // Finally, check that we have the kind of array storage that we wanted to get.
618         // Note that this is a backwards speculation check, which will result in the 
619         // bytecode operation corresponding to this arrayification being reexecuted.
620         // That's fine, since arrayification is not user-visible.
621         m_jit.load8(
622             MacroAssembler::Address(structureGPR, Structure::indexingTypeOffset()), structureGPR);
623         speculationCheck(
624             BadIndexingType, JSValueSource::unboxedCell(baseReg), NoNode,
625             jumpSlowForUnwantedArrayMode(structureGPR, node.arrayMode()));
626     }
627     
628     done.link(&m_jit);
629     noResult(m_compileIndex);
630 }
631
632 void SpeculativeJIT::arrayify(Node& node)
633 {
634     ASSERT(node.arrayMode().isSpecific());
635     
636     SpeculateCellOperand base(this, node.child1());
637     
638     if (!node.child2()) {
639         arrayify(node, base.gpr(), InvalidGPRReg);
640         return;
641     }
642     
643     SpeculateIntegerOperand property(this, node.child2());
644     
645     arrayify(node, base.gpr(), property.gpr());
646 }
647
648 GPRReg SpeculativeJIT::fillStorage(NodeIndex nodeIndex)
649 {
650     Node& node = m_jit.graph()[nodeIndex];
651     VirtualRegister virtualRegister = node.virtualRegister();
652     GenerationInfo& info = m_generationInfo[virtualRegister];
653     
654     switch (info.registerFormat()) {
655     case DataFormatNone: {
656         if (info.spillFormat() == DataFormatStorage) {
657             GPRReg gpr = allocate();
658             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
659             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
660             info.fillStorage(*m_stream, gpr);
661             return gpr;
662         }
663         
664         // Must be a cell; fill it as a cell and then return the pointer.
665         return fillSpeculateCell(nodeIndex);
666     }
667         
668     case DataFormatStorage: {
669         GPRReg gpr = info.gpr();
670         m_gprs.lock(gpr);
671         return gpr;
672     }
673         
674     default:
675         return fillSpeculateCell(nodeIndex);
676     }
677 }
678
679 void SpeculativeJIT::useChildren(Node& node)
680 {
681     if (node.flags() & NodeHasVarArgs) {
682         for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++) {
683             if (!!m_jit.graph().m_varArgChildren[childIdx])
684                 use(m_jit.graph().m_varArgChildren[childIdx]);
685         }
686     } else {
687         Edge child1 = node.child1();
688         if (!child1) {
689             ASSERT(!node.child2() && !node.child3());
690             return;
691         }
692         use(child1);
693         
694         Edge child2 = node.child2();
695         if (!child2) {
696             ASSERT(!node.child3());
697             return;
698         }
699         use(child2);
700         
701         Edge child3 = node.child3();
702         if (!child3)
703             return;
704         use(child3);
705     }
706 }
707
708 bool SpeculativeJIT::isStrictInt32(NodeIndex nodeIndex)
709 {
710     if (isInt32Constant(nodeIndex))
711         return true;
712     
713     Node& node = m_jit.graph()[nodeIndex];
714     GenerationInfo& info = m_generationInfo[node.virtualRegister()];
715     
716     return info.registerFormat() == DataFormatInteger;
717 }
718
719 bool SpeculativeJIT::isKnownInteger(NodeIndex nodeIndex)
720 {
721     if (isInt32Constant(nodeIndex))
722         return true;
723
724     Node& node = m_jit.graph()[nodeIndex];
725     
726     if (node.hasInt32Result())
727         return true;
728     
729     GenerationInfo& info = m_generationInfo[node.virtualRegister()];
730
731     return info.isJSInteger();
732 }
733
734 bool SpeculativeJIT::isKnownNumeric(NodeIndex nodeIndex)
735 {
736     if (isInt32Constant(nodeIndex) || isNumberConstant(nodeIndex))
737         return true;
738
739     Node& node = m_jit.graph()[nodeIndex];
740     
741     if (node.hasNumberResult())
742         return true;
743     
744     GenerationInfo& info = m_generationInfo[node.virtualRegister()];
745
746     return info.isJSInteger() || info.isJSDouble();
747 }
748
749 bool SpeculativeJIT::isKnownCell(NodeIndex nodeIndex)
750 {
751     return m_generationInfo[m_jit.graph()[nodeIndex].virtualRegister()].isJSCell();
752 }
753
754 bool SpeculativeJIT::isKnownNotCell(NodeIndex nodeIndex)
755 {
756     Node& node = m_jit.graph()[nodeIndex];
757     VirtualRegister virtualRegister = node.virtualRegister();
758     GenerationInfo& info = m_generationInfo[virtualRegister];
759     if (node.hasConstant() && !valueOfJSConstant(nodeIndex).isCell())
760         return true;
761     return !(info.isJSCell() || info.isUnknownJS());
762 }
763
764 bool SpeculativeJIT::isKnownNotInteger(NodeIndex nodeIndex)
765 {
766     Node& node = m_jit.graph()[nodeIndex];
767     VirtualRegister virtualRegister = node.virtualRegister();
768     GenerationInfo& info = m_generationInfo[virtualRegister];
769     
770     return info.isJSDouble() || info.isJSCell() || info.isJSBoolean()
771         || (node.hasConstant() && !valueOfJSConstant(nodeIndex).isInt32());
772 }
773
774 bool SpeculativeJIT::isKnownNotNumber(NodeIndex nodeIndex)
775 {
776     Node& node = m_jit.graph()[nodeIndex];
777     VirtualRegister virtualRegister = node.virtualRegister();
778     GenerationInfo& info = m_generationInfo[virtualRegister];
779     
780     return (!info.isJSDouble() && !info.isJSInteger() && !info.isUnknownJS())
781         || (node.hasConstant() && !isNumberConstant(nodeIndex));
782 }
783
784 void SpeculativeJIT::writeBarrier(MacroAssembler& jit, GPRReg owner, GPRReg scratch1, GPRReg scratch2, WriteBarrierUseKind useKind)
785 {
786     UNUSED_PARAM(jit);
787     UNUSED_PARAM(owner);
788     UNUSED_PARAM(scratch1);
789     UNUSED_PARAM(scratch2);
790     UNUSED_PARAM(useKind);
791     ASSERT(owner != scratch1);
792     ASSERT(owner != scratch2);
793     ASSERT(scratch1 != scratch2);
794
795 #if ENABLE(WRITE_BARRIER_PROFILING)
796     JITCompiler::emitCount(jit, WriteBarrierCounters::jitCounterFor(useKind));
797 #endif
798     markCellCard(jit, owner, scratch1, scratch2);
799 }
800
801 void SpeculativeJIT::markCellCard(MacroAssembler& jit, GPRReg owner, GPRReg scratch1, GPRReg scratch2)
802 {
803     UNUSED_PARAM(jit);
804     UNUSED_PARAM(owner);
805     UNUSED_PARAM(scratch1);
806     UNUSED_PARAM(scratch2);
807     
808 #if ENABLE(GGC)
809     jit.move(owner, scratch1);
810     jit.andPtr(TrustedImm32(static_cast<int32_t>(MarkedBlock::blockMask)), scratch1);
811     jit.move(owner, scratch2);
812     // consume additional 8 bits as we're using an approximate filter
813     jit.rshift32(TrustedImm32(MarkedBlock::atomShift + 8), scratch2);
814     jit.andPtr(TrustedImm32(MarkedBlock::atomMask >> 8), scratch2);
815     MacroAssembler::Jump filter = jit.branchTest8(MacroAssembler::Zero, MacroAssembler::BaseIndex(scratch1, scratch2, MacroAssembler::TimesOne, MarkedBlock::offsetOfMarks()));
816     jit.move(owner, scratch2);
817     jit.rshift32(TrustedImm32(MarkedBlock::cardShift), scratch2);
818     jit.andPtr(TrustedImm32(MarkedBlock::cardMask), scratch2);
819     jit.store8(TrustedImm32(1), MacroAssembler::BaseIndex(scratch1, scratch2, MacroAssembler::TimesOne, MarkedBlock::offsetOfCards()));
820     filter.link(&jit);
821 #endif
822 }
823
824 void SpeculativeJIT::writeBarrier(GPRReg ownerGPR, GPRReg valueGPR, Edge valueUse, WriteBarrierUseKind useKind, GPRReg scratch1, GPRReg scratch2)
825 {
826     UNUSED_PARAM(ownerGPR);
827     UNUSED_PARAM(valueGPR);
828     UNUSED_PARAM(scratch1);
829     UNUSED_PARAM(scratch2);
830     UNUSED_PARAM(useKind);
831
832     if (isKnownNotCell(valueUse.index()))
833         return;
834
835 #if ENABLE(WRITE_BARRIER_PROFILING)
836     JITCompiler::emitCount(m_jit, WriteBarrierCounters::jitCounterFor(useKind));
837 #endif
838
839 #if ENABLE(GGC)
840     GPRTemporary temp1;
841     GPRTemporary temp2;
842     if (scratch1 == InvalidGPRReg) {
843         GPRTemporary scratchGPR(this);
844         temp1.adopt(scratchGPR);
845         scratch1 = temp1.gpr();
846     }
847     if (scratch2 == InvalidGPRReg) {
848         GPRTemporary scratchGPR(this);
849         temp2.adopt(scratchGPR);
850         scratch2 = temp2.gpr();
851     }
852     
853     JITCompiler::Jump rhsNotCell;
854     bool hadCellCheck = false;
855     if (!isKnownCell(valueUse.index()) && !isCellSpeculation(m_jit.getSpeculation(valueUse.index()))) {
856         hadCellCheck = true;
857         rhsNotCell = m_jit.branchIfNotCell(valueGPR);
858     }
859
860     markCellCard(m_jit, ownerGPR, scratch1, scratch2);
861
862     if (hadCellCheck)
863         rhsNotCell.link(&m_jit);
864 #endif
865 }
866
867 void SpeculativeJIT::writeBarrier(GPRReg ownerGPR, JSCell* value, WriteBarrierUseKind useKind, GPRReg scratch1, GPRReg scratch2)
868 {
869     UNUSED_PARAM(ownerGPR);
870     UNUSED_PARAM(value);
871     UNUSED_PARAM(scratch1);
872     UNUSED_PARAM(scratch2);
873     UNUSED_PARAM(useKind);
874     
875     if (Heap::isMarked(value))
876         return;
877
878 #if ENABLE(WRITE_BARRIER_PROFILING)
879     JITCompiler::emitCount(m_jit, WriteBarrierCounters::jitCounterFor(useKind));
880 #endif
881
882 #if ENABLE(GGC)
883     GPRTemporary temp1;
884     GPRTemporary temp2;
885     if (scratch1 == InvalidGPRReg) {
886         GPRTemporary scratchGPR(this);
887         temp1.adopt(scratchGPR);
888         scratch1 = temp1.gpr();
889     }
890     if (scratch2 == InvalidGPRReg) {
891         GPRTemporary scratchGPR(this);
892         temp2.adopt(scratchGPR);
893         scratch2 = temp2.gpr();
894     }
895
896     markCellCard(m_jit, ownerGPR, scratch1, scratch2);
897 #endif
898 }
899
900 void SpeculativeJIT::writeBarrier(JSCell* owner, GPRReg valueGPR, Edge valueUse, WriteBarrierUseKind useKind, GPRReg scratch)
901 {
902     UNUSED_PARAM(owner);
903     UNUSED_PARAM(valueGPR);
904     UNUSED_PARAM(scratch);
905     UNUSED_PARAM(useKind);
906
907     if (isKnownNotCell(valueUse.index()))
908         return;
909
910 #if ENABLE(WRITE_BARRIER_PROFILING)
911     JITCompiler::emitCount(m_jit, WriteBarrierCounters::jitCounterFor(useKind));
912 #endif
913
914 #if ENABLE(GGC)
915     JITCompiler::Jump rhsNotCell;
916     bool hadCellCheck = false;
917     if (!isKnownCell(valueUse.index()) && !isCellSpeculation(m_jit.getSpeculation(valueUse.index()))) {
918         hadCellCheck = true;
919         rhsNotCell = m_jit.branchIfNotCell(valueGPR);
920     }
921     
922     GPRTemporary temp;
923     if (scratch == InvalidGPRReg) {
924         GPRTemporary scratchGPR(this);
925         temp.adopt(scratchGPR);
926         scratch = temp.gpr();
927     }
928
929     uint8_t* cardAddress = Heap::addressOfCardFor(owner);
930     m_jit.move(JITCompiler::TrustedImmPtr(cardAddress), scratch);
931     m_jit.store8(JITCompiler::TrustedImm32(1), JITCompiler::Address(scratch));
932
933     if (hadCellCheck)
934         rhsNotCell.link(&m_jit);
935 #endif
936 }
937
938 bool SpeculativeJIT::nonSpeculativeCompare(Node& node, MacroAssembler::RelationalCondition cond, S_DFGOperation_EJJ helperFunction)
939 {
940     unsigned branchIndexInBlock = detectPeepHoleBranch();
941     if (branchIndexInBlock != UINT_MAX) {
942         NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
943
944         ASSERT(node.adjustedRefCount() == 1);
945         
946         nonSpeculativePeepholeBranch(node, branchNodeIndex, cond, helperFunction);
947     
948         m_indexInBlock = branchIndexInBlock;
949         m_compileIndex = branchNodeIndex;
950         
951         return true;
952     }
953     
954     nonSpeculativeNonPeepholeCompare(node, cond, helperFunction);
955     
956     return false;
957 }
958
959 bool SpeculativeJIT::nonSpeculativeStrictEq(Node& node, bool invert)
960 {
961     unsigned branchIndexInBlock = detectPeepHoleBranch();
962     if (branchIndexInBlock != UINT_MAX) {
963         NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
964
965         ASSERT(node.adjustedRefCount() == 1);
966         
967         nonSpeculativePeepholeStrictEq(node, branchNodeIndex, invert);
968     
969         m_indexInBlock = branchIndexInBlock;
970         m_compileIndex = branchNodeIndex;
971         
972         return true;
973     }
974     
975     nonSpeculativeNonPeepholeStrictEq(node, invert);
976     
977     return false;
978 }
979
980 #ifndef NDEBUG
981 static const char* dataFormatString(DataFormat format)
982 {
983     // These values correspond to the DataFormat enum.
984     const char* strings[] = {
985         "[  ]",
986         "[ i]",
987         "[ d]",
988         "[ c]",
989         "Err!",
990         "Err!",
991         "Err!",
992         "Err!",
993         "[J ]",
994         "[Ji]",
995         "[Jd]",
996         "[Jc]",
997         "Err!",
998         "Err!",
999         "Err!",
1000         "Err!",
1001     };
1002     return strings[format];
1003 }
1004
1005 void SpeculativeJIT::dump(const char* label)
1006 {
1007     if (label)
1008         dataLog("<%s>\n", label);
1009
1010     dataLog("  gprs:\n");
1011     m_gprs.dump();
1012     dataLog("  fprs:\n");
1013     m_fprs.dump();
1014     dataLog("  VirtualRegisters:\n");
1015     for (unsigned i = 0; i < m_generationInfo.size(); ++i) {
1016         GenerationInfo& info = m_generationInfo[i];
1017         if (info.alive())
1018             dataLog("    % 3d:%s%s", i, dataFormatString(info.registerFormat()), dataFormatString(info.spillFormat()));
1019         else
1020             dataLog("    % 3d:[__][__]", i);
1021         if (info.registerFormat() == DataFormatDouble)
1022             dataLog(":fpr%d\n", info.fpr());
1023         else if (info.registerFormat() != DataFormatNone
1024 #if USE(JSVALUE32_64)
1025             && !(info.registerFormat() & DataFormatJS)
1026 #endif
1027             ) {
1028             ASSERT(info.gpr() != InvalidGPRReg);
1029             dataLog(":%s\n", GPRInfo::debugName(info.gpr()));
1030         } else
1031             dataLog("\n");
1032     }
1033     if (label)
1034         dataLog("</%s>\n", label);
1035 }
1036 #endif
1037
1038
1039 #if DFG_ENABLE(CONSISTENCY_CHECK)
1040 void SpeculativeJIT::checkConsistency()
1041 {
1042     bool failed = false;
1043
1044     for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
1045         if (iter.isLocked()) {
1046             dataLog("DFG_CONSISTENCY_CHECK failed: gpr %s is locked.\n", iter.debugName());
1047             failed = true;
1048         }
1049     }
1050     for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
1051         if (iter.isLocked()) {
1052             dataLog("DFG_CONSISTENCY_CHECK failed: fpr %s is locked.\n", iter.debugName());
1053             failed = true;
1054         }
1055     }
1056
1057     for (unsigned i = 0; i < m_generationInfo.size(); ++i) {
1058         VirtualRegister virtualRegister = (VirtualRegister)i;
1059         GenerationInfo& info = m_generationInfo[virtualRegister];
1060         if (!info.alive())
1061             continue;
1062         switch (info.registerFormat()) {
1063         case DataFormatNone:
1064             break;
1065         case DataFormatJS:
1066         case DataFormatJSInteger:
1067         case DataFormatJSDouble:
1068         case DataFormatJSCell:
1069         case DataFormatJSBoolean:
1070 #if USE(JSVALUE32_64)
1071             break;
1072 #endif
1073         case DataFormatInteger:
1074         case DataFormatCell:
1075         case DataFormatBoolean:
1076         case DataFormatStorage: {
1077             GPRReg gpr = info.gpr();
1078             ASSERT(gpr != InvalidGPRReg);
1079             if (m_gprs.name(gpr) != virtualRegister) {
1080                 dataLog("DFG_CONSISTENCY_CHECK failed: name mismatch for virtual register %d (gpr %s).\n", virtualRegister, GPRInfo::debugName(gpr));
1081                 failed = true;
1082             }
1083             break;
1084         }
1085         case DataFormatDouble: {
1086             FPRReg fpr = info.fpr();
1087             ASSERT(fpr != InvalidFPRReg);
1088             if (m_fprs.name(fpr) != virtualRegister) {
1089                 dataLog("DFG_CONSISTENCY_CHECK failed: name mismatch for virtual register %d (fpr %s).\n", virtualRegister, FPRInfo::debugName(fpr));
1090                 failed = true;
1091             }
1092             break;
1093         }
1094         }
1095     }
1096
1097     for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
1098         VirtualRegister virtualRegister = iter.name();
1099         if (virtualRegister == InvalidVirtualRegister)
1100             continue;
1101
1102         GenerationInfo& info = m_generationInfo[virtualRegister];
1103 #if USE(JSVALUE64)
1104         if (iter.regID() != info.gpr()) {
1105             dataLog("DFG_CONSISTENCY_CHECK failed: name mismatch for gpr %s (virtual register %d).\n", iter.debugName(), virtualRegister);
1106             failed = true;
1107         }
1108 #else
1109         if (!(info.registerFormat() & DataFormatJS)) {
1110             if (iter.regID() != info.gpr()) {
1111                 dataLog("DFG_CONSISTENCY_CHECK failed: name mismatch for gpr %s (virtual register %d).\n", iter.debugName(), virtualRegister);
1112                 failed = true;
1113             }
1114         } else {
1115             if (iter.regID() != info.tagGPR() && iter.regID() != info.payloadGPR()) {
1116                 dataLog("DFG_CONSISTENCY_CHECK failed: name mismatch for gpr %s (virtual register %d).\n", iter.debugName(), virtualRegister);
1117                 failed = true;
1118             }
1119         }
1120 #endif
1121     }
1122
1123     for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
1124         VirtualRegister virtualRegister = iter.name();
1125         if (virtualRegister == InvalidVirtualRegister)
1126             continue;
1127
1128         GenerationInfo& info = m_generationInfo[virtualRegister];
1129         if (iter.regID() != info.fpr()) {
1130             dataLog("DFG_CONSISTENCY_CHECK failed: name mismatch for fpr %s (virtual register %d).\n", iter.debugName(), virtualRegister);
1131             failed = true;
1132         }
1133     }
1134
1135     if (failed) {
1136         dump();
1137         CRASH();
1138     }
1139 }
1140 #endif
1141
1142 GPRTemporary::GPRTemporary()
1143     : m_jit(0)
1144     , m_gpr(InvalidGPRReg)
1145 {
1146 }
1147
1148 GPRTemporary::GPRTemporary(SpeculativeJIT* jit)
1149     : m_jit(jit)
1150     , m_gpr(InvalidGPRReg)
1151 {
1152     m_gpr = m_jit->allocate();
1153 }
1154
1155 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, GPRReg specific)
1156     : m_jit(jit)
1157     , m_gpr(InvalidGPRReg)
1158 {
1159     m_gpr = m_jit->allocate(specific);
1160 }
1161
1162 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, SpeculateIntegerOperand& op1)
1163     : m_jit(jit)
1164     , m_gpr(InvalidGPRReg)
1165 {
1166     if (m_jit->canReuse(op1.index()))
1167         m_gpr = m_jit->reuse(op1.gpr());
1168     else
1169         m_gpr = m_jit->allocate();
1170 }
1171
1172 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, SpeculateIntegerOperand& op1, SpeculateIntegerOperand& op2)
1173     : m_jit(jit)
1174     , m_gpr(InvalidGPRReg)
1175 {
1176     if (m_jit->canReuse(op1.index()))
1177         m_gpr = m_jit->reuse(op1.gpr());
1178     else if (m_jit->canReuse(op2.index()))
1179         m_gpr = m_jit->reuse(op2.gpr());
1180     else
1181         m_gpr = m_jit->allocate();
1182 }
1183
1184 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, SpeculateStrictInt32Operand& op1)
1185     : m_jit(jit)
1186     , m_gpr(InvalidGPRReg)
1187 {
1188     if (m_jit->canReuse(op1.index()))
1189         m_gpr = m_jit->reuse(op1.gpr());
1190     else
1191         m_gpr = m_jit->allocate();
1192 }
1193
1194 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, IntegerOperand& op1)
1195     : m_jit(jit)
1196     , m_gpr(InvalidGPRReg)
1197 {
1198     if (m_jit->canReuse(op1.index()))
1199         m_gpr = m_jit->reuse(op1.gpr());
1200     else
1201         m_gpr = m_jit->allocate();
1202 }
1203
1204 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, IntegerOperand& op1, IntegerOperand& op2)
1205     : m_jit(jit)
1206     , m_gpr(InvalidGPRReg)
1207 {
1208     if (m_jit->canReuse(op1.index()))
1209         m_gpr = m_jit->reuse(op1.gpr());
1210     else if (m_jit->canReuse(op2.index()))
1211         m_gpr = m_jit->reuse(op2.gpr());
1212     else
1213         m_gpr = m_jit->allocate();
1214 }
1215
1216 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, SpeculateCellOperand& op1)
1217     : m_jit(jit)
1218     , m_gpr(InvalidGPRReg)
1219 {
1220     if (m_jit->canReuse(op1.index()))
1221         m_gpr = m_jit->reuse(op1.gpr());
1222     else
1223         m_gpr = m_jit->allocate();
1224 }
1225
1226 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, SpeculateBooleanOperand& op1)
1227     : m_jit(jit)
1228     , m_gpr(InvalidGPRReg)
1229 {
1230     if (m_jit->canReuse(op1.index()))
1231         m_gpr = m_jit->reuse(op1.gpr());
1232     else
1233         m_gpr = m_jit->allocate();
1234 }
1235
1236 #if USE(JSVALUE64)
1237 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, JSValueOperand& op1)
1238     : m_jit(jit)
1239     , m_gpr(InvalidGPRReg)
1240 {
1241     if (m_jit->canReuse(op1.index()))
1242         m_gpr = m_jit->reuse(op1.gpr());
1243     else
1244         m_gpr = m_jit->allocate();
1245 }
1246 #else
1247 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, JSValueOperand& op1, bool tag)
1248     : m_jit(jit)
1249     , m_gpr(InvalidGPRReg)
1250 {
1251     if (!op1.isDouble() && m_jit->canReuse(op1.index()))
1252         m_gpr = m_jit->reuse(tag ? op1.tagGPR() : op1.payloadGPR());
1253     else
1254         m_gpr = m_jit->allocate();
1255 }
1256 #endif
1257
1258 GPRTemporary::GPRTemporary(SpeculativeJIT* jit, StorageOperand& op1)
1259     : m_jit(jit)
1260     , m_gpr(InvalidGPRReg)
1261 {
1262     if (m_jit->canReuse(op1.index()))
1263         m_gpr = m_jit->reuse(op1.gpr());
1264     else
1265         m_gpr = m_jit->allocate();
1266 }
1267
1268 void GPRTemporary::adopt(GPRTemporary& other)
1269 {
1270     ASSERT(!m_jit);
1271     ASSERT(m_gpr == InvalidGPRReg);
1272     ASSERT(other.m_jit);
1273     ASSERT(other.m_gpr != InvalidGPRReg);
1274     m_jit = other.m_jit;
1275     m_gpr = other.m_gpr;
1276     other.m_jit = 0;
1277     other.m_gpr = InvalidGPRReg;
1278 }
1279
1280 FPRTemporary::FPRTemporary(SpeculativeJIT* jit)
1281     : m_jit(jit)
1282     , m_fpr(InvalidFPRReg)
1283 {
1284     m_fpr = m_jit->fprAllocate();
1285 }
1286
1287 FPRTemporary::FPRTemporary(SpeculativeJIT* jit, DoubleOperand& op1)
1288     : m_jit(jit)
1289     , m_fpr(InvalidFPRReg)
1290 {
1291     if (m_jit->canReuse(op1.index()))
1292         m_fpr = m_jit->reuse(op1.fpr());
1293     else
1294         m_fpr = m_jit->fprAllocate();
1295 }
1296
1297 FPRTemporary::FPRTemporary(SpeculativeJIT* jit, DoubleOperand& op1, DoubleOperand& op2)
1298     : m_jit(jit)
1299     , m_fpr(InvalidFPRReg)
1300 {
1301     if (m_jit->canReuse(op1.index()))
1302         m_fpr = m_jit->reuse(op1.fpr());
1303     else if (m_jit->canReuse(op2.index()))
1304         m_fpr = m_jit->reuse(op2.fpr());
1305     else
1306         m_fpr = m_jit->fprAllocate();
1307 }
1308
1309 FPRTemporary::FPRTemporary(SpeculativeJIT* jit, SpeculateDoubleOperand& op1)
1310     : m_jit(jit)
1311     , m_fpr(InvalidFPRReg)
1312 {
1313     if (m_jit->canReuse(op1.index()))
1314         m_fpr = m_jit->reuse(op1.fpr());
1315     else
1316         m_fpr = m_jit->fprAllocate();
1317 }
1318
1319 FPRTemporary::FPRTemporary(SpeculativeJIT* jit, SpeculateDoubleOperand& op1, SpeculateDoubleOperand& op2)
1320     : m_jit(jit)
1321     , m_fpr(InvalidFPRReg)
1322 {
1323     if (m_jit->canReuse(op1.index()))
1324         m_fpr = m_jit->reuse(op1.fpr());
1325     else if (m_jit->canReuse(op2.index()))
1326         m_fpr = m_jit->reuse(op2.fpr());
1327     else
1328         m_fpr = m_jit->fprAllocate();
1329 }
1330
1331 #if USE(JSVALUE32_64)
1332 FPRTemporary::FPRTemporary(SpeculativeJIT* jit, JSValueOperand& op1)
1333     : m_jit(jit)
1334     , m_fpr(InvalidFPRReg)
1335 {
1336     if (op1.isDouble() && m_jit->canReuse(op1.index()))
1337         m_fpr = m_jit->reuse(op1.fpr());
1338     else
1339         m_fpr = m_jit->fprAllocate();
1340 }
1341 #endif
1342
1343 void SpeculativeJIT::compilePeepHoleDoubleBranch(Node& node, NodeIndex branchNodeIndex, JITCompiler::DoubleCondition condition)
1344 {
1345     Node& branchNode = at(branchNodeIndex);
1346     BlockIndex taken = branchNode.takenBlockIndex();
1347     BlockIndex notTaken = branchNode.notTakenBlockIndex();
1348     
1349     SpeculateDoubleOperand op1(this, node.child1());
1350     SpeculateDoubleOperand op2(this, node.child2());
1351     
1352     branchDouble(condition, op1.fpr(), op2.fpr(), taken);
1353     jump(notTaken);
1354 }
1355
1356 void SpeculativeJIT::compilePeepHoleObjectEquality(Node& node, NodeIndex branchNodeIndex)
1357 {
1358     Node& branchNode = at(branchNodeIndex);
1359     BlockIndex taken = branchNode.takenBlockIndex();
1360     BlockIndex notTaken = branchNode.notTakenBlockIndex();
1361
1362     MacroAssembler::RelationalCondition condition = MacroAssembler::Equal;
1363     
1364     if (taken == nextBlock()) {
1365         condition = MacroAssembler::NotEqual;
1366         BlockIndex tmp = taken;
1367         taken = notTaken;
1368         notTaken = tmp;
1369     }
1370
1371     SpeculateCellOperand op1(this, node.child1());
1372     SpeculateCellOperand op2(this, node.child2());
1373     
1374     GPRReg op1GPR = op1.gpr();
1375     GPRReg op2GPR = op2.gpr();
1376     
1377     if (m_jit.graph().globalObjectFor(node.codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) {
1378         m_jit.graph().globalObjectFor(node.codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint());
1379         speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node.child1().index(), 
1380             m_jit.branchPtr(
1381                 MacroAssembler::Equal, 
1382                 MacroAssembler::Address(op1GPR, JSCell::structureOffset()), 
1383                 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())));
1384         speculationCheck(BadType, JSValueSource::unboxedCell(op2GPR), node.child2().index(), 
1385             m_jit.branchPtr(
1386                 MacroAssembler::Equal, 
1387                 MacroAssembler::Address(op2GPR, JSCell::structureOffset()), 
1388                 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())));
1389     } else {
1390         GPRTemporary structure(this);
1391         GPRReg structureGPR = structure.gpr();
1392
1393         m_jit.loadPtr(MacroAssembler::Address(op1GPR, JSCell::structureOffset()), structureGPR);
1394         speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node.child1().index(), 
1395             m_jit.branchPtr(
1396                 MacroAssembler::Equal, 
1397                 structureGPR, 
1398                 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())));
1399         speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node.child1().index(), 
1400             m_jit.branchTest8(
1401                 MacroAssembler::NonZero, 
1402                 MacroAssembler::Address(structureGPR, Structure::typeInfoFlagsOffset()), 
1403                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1404
1405         m_jit.loadPtr(MacroAssembler::Address(op2GPR, JSCell::structureOffset()), structureGPR);
1406         speculationCheck(BadType, JSValueSource::unboxedCell(op2GPR), node.child2().index(), 
1407             m_jit.branchPtr(
1408                 MacroAssembler::Equal, 
1409                 structureGPR, 
1410                 MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get())));
1411         speculationCheck(BadType, JSValueSource::unboxedCell(op2GPR), node.child2().index(), 
1412             m_jit.branchTest8(
1413                 MacroAssembler::NonZero, 
1414                 MacroAssembler::Address(structureGPR, Structure::typeInfoFlagsOffset()), 
1415                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1416     }
1417
1418     branchPtr(condition, op1GPR, op2GPR, taken);
1419     jump(notTaken);
1420 }
1421
1422 void SpeculativeJIT::compilePeepHoleIntegerBranch(Node& node, NodeIndex branchNodeIndex, JITCompiler::RelationalCondition condition)
1423 {
1424     Node& branchNode = at(branchNodeIndex);
1425     BlockIndex taken = branchNode.takenBlockIndex();
1426     BlockIndex notTaken = branchNode.notTakenBlockIndex();
1427
1428     // The branch instruction will branch to the taken block.
1429     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
1430     if (taken == nextBlock()) {
1431         condition = JITCompiler::invert(condition);
1432         BlockIndex tmp = taken;
1433         taken = notTaken;
1434         notTaken = tmp;
1435     }
1436
1437     if (isInt32Constant(node.child1().index())) {
1438         int32_t imm = valueOfInt32Constant(node.child1().index());
1439         SpeculateIntegerOperand op2(this, node.child2());
1440         branch32(condition, JITCompiler::Imm32(imm), op2.gpr(), taken);
1441     } else if (isInt32Constant(node.child2().index())) {
1442         SpeculateIntegerOperand op1(this, node.child1());
1443         int32_t imm = valueOfInt32Constant(node.child2().index());
1444         branch32(condition, op1.gpr(), JITCompiler::Imm32(imm), taken);
1445     } else {
1446         SpeculateIntegerOperand op1(this, node.child1());
1447         SpeculateIntegerOperand op2(this, node.child2());
1448         branch32(condition, op1.gpr(), op2.gpr(), taken);
1449     }
1450
1451     jump(notTaken);
1452 }
1453
1454 // Returns true if the compare is fused with a subsequent branch.
1455 bool SpeculativeJIT::compilePeepHoleBranch(Node& node, MacroAssembler::RelationalCondition condition, MacroAssembler::DoubleCondition doubleCondition, S_DFGOperation_EJJ operation)
1456 {
1457     // Fused compare & branch.
1458     unsigned branchIndexInBlock = detectPeepHoleBranch();
1459     if (branchIndexInBlock != UINT_MAX) {
1460         NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
1461
1462         // detectPeepHoleBranch currently only permits the branch to be the very next node,
1463         // so can be no intervening nodes to also reference the compare. 
1464         ASSERT(node.adjustedRefCount() == 1);
1465
1466         if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())))
1467             compilePeepHoleIntegerBranch(node, branchNodeIndex, condition);
1468         else if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2())))
1469             compilePeepHoleDoubleBranch(node, branchNodeIndex, doubleCondition);
1470         else if (node.op() == CompareEq) {
1471             if (at(node.child1()).shouldSpeculateString() || at(node.child2()).shouldSpeculateString()) {
1472                 nonSpeculativePeepholeBranch(node, branchNodeIndex, condition, operation);
1473                 return true;
1474             }
1475             if (at(node.child1()).shouldSpeculateNonStringCell() && at(node.child2()).shouldSpeculateNonStringCellOrOther())
1476                 compilePeepHoleObjectToObjectOrOtherEquality(node.child1(), node.child2(), branchNodeIndex);
1477             else if (at(node.child1()).shouldSpeculateNonStringCellOrOther() && at(node.child2()).shouldSpeculateNonStringCell())
1478                 compilePeepHoleObjectToObjectOrOtherEquality(node.child2(), node.child1(), branchNodeIndex);
1479             else if (at(node.child1()).shouldSpeculateNonStringCell() && at(node.child2()).shouldSpeculateNonStringCell())
1480                 compilePeepHoleObjectEquality(node, branchNodeIndex);
1481             else {
1482                 nonSpeculativePeepholeBranch(node, branchNodeIndex, condition, operation);
1483                 return true;
1484             }
1485         } else {
1486             nonSpeculativePeepholeBranch(node, branchNodeIndex, condition, operation);
1487             return true;
1488         }
1489
1490         use(node.child1());
1491         use(node.child2());
1492         m_indexInBlock = branchIndexInBlock;
1493         m_compileIndex = branchNodeIndex;
1494         return true;
1495     }
1496     return false;
1497 }
1498
1499 void SpeculativeJIT::noticeOSRBirth(NodeIndex nodeIndex, Node& node)
1500 {
1501     if (!node.hasVirtualRegister())
1502         return;
1503     
1504     VirtualRegister virtualRegister = node.virtualRegister();
1505     GenerationInfo& info = m_generationInfo[virtualRegister];
1506     
1507     info.noticeOSRBirth(*m_stream, nodeIndex, virtualRegister);
1508 }
1509
1510 void SpeculativeJIT::compileMovHint(Node& node)
1511 {
1512     ASSERT(node.op() == SetLocal);
1513     
1514     m_lastSetOperand = node.local();
1515     
1516     Node& child = at(node.child1());
1517     noticeOSRBirth(node.child1().index(), child);
1518     
1519     if (child.op() == UInt32ToNumber)
1520         noticeOSRBirth(child.child1().index(), at(child.child1()));
1521     
1522     m_stream->appendAndLog(VariableEvent::movHint(node.child1().index(), node.local()));
1523 }
1524
1525 void SpeculativeJIT::compile(BasicBlock& block)
1526 {
1527     ASSERT(m_compileOkay);
1528     
1529     if (!block.isReachable)
1530         return;
1531     
1532     if (!block.cfaHasVisited) {
1533         // Don't generate code for basic blocks that are unreachable according to CFA.
1534         // But to be sure that nobody has generated a jump to this block, drop in a
1535         // breakpoint here.
1536 #if !ASSERT_DISABLED
1537         m_jit.breakpoint();
1538 #endif
1539         return;
1540     }
1541
1542     m_blockHeads[m_block] = m_jit.label();
1543 #if DFG_ENABLE(JIT_BREAK_ON_EVERY_BLOCK)
1544     m_jit.breakpoint();
1545 #endif
1546     
1547 #if DFG_ENABLE(DEBUG_VERBOSE)
1548     dataLog("Setting up state for block #%u: ", m_block);
1549 #endif
1550     
1551     m_stream->appendAndLog(VariableEvent::reset());
1552     
1553     m_jit.jitAssertHasValidCallFrame();
1554
1555     ASSERT(m_arguments.size() == block.variablesAtHead.numberOfArguments());
1556     for (size_t i = 0; i < m_arguments.size(); ++i) {
1557         ValueSource valueSource = ValueSource(ValueInJSStack);
1558         m_arguments[i] = valueSource;
1559         m_stream->appendAndLog(VariableEvent::setLocal(argumentToOperand(i), valueSource.dataFormat()));
1560     }
1561     
1562     m_state.reset();
1563     m_state.beginBasicBlock(&block);
1564     
1565     ASSERT(m_variables.size() == block.variablesAtHead.numberOfLocals());
1566     for (size_t i = 0; i < m_variables.size(); ++i) {
1567         NodeIndex nodeIndex = block.variablesAtHead.local(i);
1568         ValueSource valueSource;
1569         if (nodeIndex == NoNode)
1570             valueSource = ValueSource(SourceIsDead);
1571         else if (at(nodeIndex).variableAccessData()->isArgumentsAlias())
1572             valueSource = ValueSource(ArgumentsSource);
1573         else if (at(nodeIndex).variableAccessData()->isCaptured())
1574             valueSource = ValueSource(ValueInJSStack);
1575         else if (!at(nodeIndex).refCount())
1576             valueSource = ValueSource(SourceIsDead);
1577         else if (at(nodeIndex).variableAccessData()->shouldUseDoubleFormat())
1578             valueSource = ValueSource(DoubleInJSStack);
1579         else
1580             valueSource = ValueSource::forSpeculation(at(nodeIndex).variableAccessData()->argumentAwarePrediction());
1581         m_variables[i] = valueSource;
1582         m_stream->appendAndLog(VariableEvent::setLocal(i, valueSource.dataFormat()));
1583     }
1584     
1585     m_lastSetOperand = std::numeric_limits<int>::max();
1586     m_codeOriginForOSR = CodeOrigin();
1587     
1588     if (DFG_ENABLE_EDGE_CODE_VERIFICATION) {
1589         JITCompiler::Jump verificationSucceeded =
1590             m_jit.branch32(JITCompiler::Equal, GPRInfo::regT0, TrustedImm32(m_block));
1591         m_jit.breakpoint();
1592         verificationSucceeded.link(&m_jit);
1593     }
1594
1595 #if DFG_ENABLE(DEBUG_VERBOSE)
1596     dataLog("\n");
1597 #endif
1598
1599     for (m_indexInBlock = 0; m_indexInBlock < block.size(); ++m_indexInBlock) {
1600         m_compileIndex = block[m_indexInBlock];
1601         m_jit.setForNode(m_compileIndex);
1602         Node& node = at(m_compileIndex);
1603         m_codeOriginForOSR = node.codeOrigin;
1604         if (!node.shouldGenerate()) {
1605 #if DFG_ENABLE(DEBUG_VERBOSE)
1606             dataLog("SpeculativeJIT skipping Node @%d (bc#%u) at JIT offset 0x%x     ", (int)m_compileIndex, node.codeOrigin.bytecodeIndex, m_jit.debugOffset());
1607 #endif
1608             switch (node.op()) {
1609             case JSConstant:
1610                 m_minifiedGraph->append(MinifiedNode::fromNode(m_compileIndex, node));
1611                 break;
1612                 
1613             case WeakJSConstant:
1614                 m_jit.addWeakReference(node.weakConstant());
1615                 m_minifiedGraph->append(MinifiedNode::fromNode(m_compileIndex, node));
1616                 break;
1617                 
1618             case SetLocal:
1619                 compileMovHint(node);
1620                 break;
1621
1622             case InlineStart: {
1623                 InlineCallFrame* inlineCallFrame = node.codeOrigin.inlineCallFrame;
1624                 int argumentCountIncludingThis = inlineCallFrame->arguments.size();
1625                 unsigned argumentPositionStart = node.argumentPositionStart();
1626                 CodeBlock* codeBlock = baselineCodeBlockForInlineCallFrame(inlineCallFrame);
1627                 for (int i = 0; i < argumentCountIncludingThis; ++i) {
1628                     ValueRecovery recovery;
1629                     if (codeBlock->isCaptured(argumentToOperand(i)))
1630                         recovery = ValueRecovery::alreadyInJSStack();
1631                     else {
1632                         ArgumentPosition& argumentPosition =
1633                             m_jit.graph().m_argumentPositions[argumentPositionStart + i];
1634                         ValueSource valueSource;
1635                         if (argumentPosition.shouldUseDoubleFormat())
1636                             valueSource = ValueSource(DoubleInJSStack);
1637                         else if (isInt32Speculation(argumentPosition.prediction()))
1638                             valueSource = ValueSource(Int32InJSStack);
1639                         else if (isCellSpeculation(argumentPosition.prediction()))
1640                             valueSource = ValueSource(CellInJSStack);
1641                         else if (isBooleanSpeculation(argumentPosition.prediction()))
1642                             valueSource = ValueSource(BooleanInJSStack);
1643                         else
1644                             valueSource = ValueSource(ValueInJSStack);
1645                         recovery = computeValueRecoveryFor(valueSource);
1646                     }
1647                     // The recovery should refer either to something that has already been
1648                     // stored into the stack at the right place, or to a constant,
1649                     // since the Arguments code isn't smart enough to handle anything else.
1650                     // The exception is the this argument, which we don't really need to be
1651                     // able to recover.
1652 #if DFG_ENABLE(DEBUG_VERBOSE)
1653                     dataLog("\nRecovery for argument %d: ", i);
1654                     recovery.dump(WTF::dataFile());
1655 #endif
1656                     inlineCallFrame->arguments[i] = recovery;
1657                 }
1658                 break;
1659             }
1660                 
1661             default:
1662                 if (belongsInMinifiedGraph(node.op()))
1663                     m_minifiedGraph->append(MinifiedNode::fromNode(m_compileIndex, node));
1664                 break;
1665             }
1666         } else {
1667             
1668 #if DFG_ENABLE(DEBUG_VERBOSE)
1669             dataLog("SpeculativeJIT generating Node @%d (bc#%u) at JIT offset 0x%x   ", (int)m_compileIndex, node.codeOrigin.bytecodeIndex, m_jit.debugOffset());
1670 #endif
1671 #if DFG_ENABLE(JIT_BREAK_ON_EVERY_NODE)
1672             m_jit.breakpoint();
1673 #endif
1674 #if DFG_ENABLE(XOR_DEBUG_AID)
1675             m_jit.xorPtr(JITCompiler::TrustedImm32(m_compileIndex), GPRInfo::regT0);
1676             m_jit.xorPtr(JITCompiler::TrustedImm32(m_compileIndex), GPRInfo::regT0);
1677 #endif
1678             checkConsistency();
1679             compile(node);
1680             if (!m_compileOkay) {
1681                 m_compileOkay = true;
1682                 clearGenerationInfo();
1683                 return;
1684             }
1685             
1686             if (belongsInMinifiedGraph(node.op())) {
1687                 m_minifiedGraph->append(MinifiedNode::fromNode(m_compileIndex, node));
1688                 noticeOSRBirth(m_compileIndex, node);
1689             }
1690             
1691 #if DFG_ENABLE(DEBUG_VERBOSE)
1692             if (node.hasResult()) {
1693                 GenerationInfo& info = m_generationInfo[node.virtualRegister()];
1694                 dataLog("-> %s, vr#%d", dataFormatToString(info.registerFormat()), (int)node.virtualRegister());
1695                 if (info.registerFormat() != DataFormatNone) {
1696                     if (info.registerFormat() == DataFormatDouble)
1697                         dataLog(", %s", FPRInfo::debugName(info.fpr()));
1698 #if USE(JSVALUE32_64)
1699                     else if (info.registerFormat() & DataFormatJS)
1700                         dataLog(", %s %s", GPRInfo::debugName(info.tagGPR()), GPRInfo::debugName(info.payloadGPR()));
1701 #endif
1702                     else
1703                         dataLog(", %s", GPRInfo::debugName(info.gpr()));
1704                 }
1705                 dataLog("    ");
1706             } else
1707                 dataLog("    ");
1708 #endif
1709         }
1710         
1711 #if DFG_ENABLE(DEBUG_VERBOSE)
1712         dataLog("\n");
1713 #endif
1714         
1715         // Make sure that the abstract state is rematerialized for the next node.
1716         m_state.execute(m_indexInBlock);
1717         
1718         if (node.shouldGenerate())
1719             checkConsistency();
1720     }
1721     
1722     // Perform the most basic verification that children have been used correctly.
1723 #if !ASSERT_DISABLED
1724     for (unsigned index = 0; index < m_generationInfo.size(); ++index) {
1725         GenerationInfo& info = m_generationInfo[index];
1726         ASSERT(!info.alive());
1727     }
1728 #endif
1729 }
1730
1731 // If we are making type predictions about our arguments then
1732 // we need to check that they are correct on function entry.
1733 void SpeculativeJIT::checkArgumentTypes()
1734 {
1735     ASSERT(!m_compileIndex);
1736     m_isCheckingArgumentTypes = true;
1737     m_codeOriginForOSR = CodeOrigin(0);
1738
1739     for (size_t i = 0; i < m_arguments.size(); ++i)
1740         m_arguments[i] = ValueSource(ValueInJSStack);
1741     for (size_t i = 0; i < m_variables.size(); ++i)
1742         m_variables[i] = ValueSource(ValueInJSStack);
1743     
1744     for (int i = 0; i < m_jit.codeBlock()->numParameters(); ++i) {
1745         NodeIndex nodeIndex = m_jit.graph().m_arguments[i];
1746         Node& node = at(nodeIndex);
1747         ASSERT(node.op() == SetArgument);
1748         if (!node.shouldGenerate()) {
1749             // The argument is dead. We don't do any checks for such arguments.
1750             continue;
1751         }
1752         
1753         VariableAccessData* variableAccessData = node.variableAccessData();
1754         VirtualRegister virtualRegister = variableAccessData->local();
1755         SpeculatedType predictedType = variableAccessData->prediction();
1756
1757         JSValueSource valueSource = JSValueSource(JITCompiler::addressFor(virtualRegister));
1758         
1759 #if USE(JSVALUE64)
1760         if (isInt32Speculation(predictedType))
1761             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch64(MacroAssembler::Below, JITCompiler::addressFor(virtualRegister), GPRInfo::tagTypeNumberRegister));
1762         else if (isBooleanSpeculation(predictedType)) {
1763             GPRTemporary temp(this);
1764             m_jit.load64(JITCompiler::addressFor(virtualRegister), temp.gpr());
1765             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), temp.gpr());
1766             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTest64(MacroAssembler::NonZero, temp.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
1767         } else if (isCellSpeculation(predictedType))
1768             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTest64(MacroAssembler::NonZero, JITCompiler::addressFor(virtualRegister), GPRInfo::tagMaskRegister));
1769 #else
1770         if (isInt32Speculation(predictedType))
1771             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag)));
1772         else if (isBooleanSpeculation(predictedType))
1773             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::BooleanTag)));
1774         else if (isCellSpeculation(predictedType))
1775             speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::CellTag)));
1776 #endif
1777     }
1778     m_isCheckingArgumentTypes = false;
1779 }
1780
1781 bool SpeculativeJIT::compile()
1782 {
1783     checkArgumentTypes();
1784
1785     if (DFG_ENABLE_EDGE_CODE_VERIFICATION)
1786         m_jit.move(TrustedImm32(0), GPRInfo::regT0);
1787
1788     ASSERT(!m_compileIndex);
1789     for (m_block = 0; m_block < m_jit.graph().m_blocks.size(); ++m_block) {
1790         m_jit.setForBlock(m_block);
1791         BasicBlock* block = m_jit.graph().m_blocks[m_block].get();
1792         if (block)
1793             compile(*block);
1794     }
1795     linkBranches();
1796     return true;
1797 }
1798
1799 void SpeculativeJIT::createOSREntries()
1800 {
1801     for (BlockIndex blockIndex = 0; blockIndex < m_jit.graph().m_blocks.size(); ++blockIndex) {
1802         BasicBlock* block = m_jit.graph().m_blocks[blockIndex].get();
1803         if (!block)
1804             continue;
1805         if (!block->isOSRTarget)
1806             continue;
1807
1808         // Currently we only need to create OSR entry trampolines when using edge code
1809         // verification. But in the future, we'll need this for other things as well (like
1810         // when we have global reg alloc).
1811         // If we don't need OSR entry trampolin
1812         if (!DFG_ENABLE_EDGE_CODE_VERIFICATION) {
1813             m_osrEntryHeads.append(m_blockHeads[blockIndex]);
1814             continue;
1815         }
1816         
1817         m_osrEntryHeads.append(m_jit.label());
1818         m_jit.move(TrustedImm32(blockIndex), GPRInfo::regT0);
1819         m_jit.jump().linkTo(m_blockHeads[blockIndex], &m_jit);
1820     }
1821 }
1822
1823 void SpeculativeJIT::linkOSREntries(LinkBuffer& linkBuffer)
1824 {
1825     unsigned osrEntryIndex = 0;
1826     for (BlockIndex blockIndex = 0; blockIndex < m_jit.graph().m_blocks.size(); ++blockIndex) {
1827         BasicBlock* block = m_jit.graph().m_blocks[blockIndex].get();
1828         if (!block)
1829             continue;
1830         if (!block->isOSRTarget)
1831             continue;
1832         m_jit.noticeOSREntry(*block, m_osrEntryHeads[osrEntryIndex++], linkBuffer);
1833     }
1834     ASSERT(osrEntryIndex == m_osrEntryHeads.size());
1835 }
1836
1837 ValueRecovery SpeculativeJIT::computeValueRecoveryFor(const ValueSource& valueSource)
1838 {
1839     if (valueSource.isInJSStack())
1840         return valueSource.valueRecovery();
1841         
1842     ASSERT(valueSource.kind() == HaveNode);
1843     if (isConstant(valueSource.nodeIndex()))
1844         return ValueRecovery::constant(valueOfJSConstant(valueSource.nodeIndex()));
1845     
1846     return ValueRecovery();
1847 }
1848
1849 void SpeculativeJIT::compileDoublePutByVal(Node& node, SpeculateCellOperand& base, SpeculateStrictInt32Operand& property)
1850 {
1851     Edge child3 = m_jit.graph().varArgChild(node, 2);
1852     Edge child4 = m_jit.graph().varArgChild(node, 3);
1853
1854     ArrayMode arrayMode = node.arrayMode();
1855     
1856     GPRReg baseReg = base.gpr();
1857     GPRReg propertyReg = property.gpr();
1858     
1859     SpeculateDoubleOperand value(this, child3);
1860
1861     FPRReg valueReg = value.fpr();
1862     
1863     if (!isRealNumberSpeculation(m_state.forNode(child3).m_type)) {
1864         // FIXME: We need a way of profiling these, and we need to hoist them into
1865         // SpeculateDoubleOperand.
1866         speculationCheck(
1867             BadType, JSValueRegs(), NoNode,
1868             m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, valueReg, valueReg));
1869     }
1870     
1871     if (!m_compileOkay)
1872         return;
1873     
1874     StorageOperand storage(this, child4);
1875     GPRReg storageReg = storage.gpr();
1876
1877     if (node.op() == PutByValAlias) {
1878         // Store the value to the array.
1879         GPRReg propertyReg = property.gpr();
1880         FPRReg valueReg = value.fpr();
1881         m_jit.storeDouble(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
1882         
1883         noResult(m_compileIndex);
1884         return;
1885     }
1886     
1887     GPRTemporary temporary;
1888     GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
1889
1890     MacroAssembler::JumpList slowCases;
1891     
1892     if (arrayMode.isInBounds()) {
1893         speculationCheck(
1894             Uncountable, JSValueRegs(), NoNode,
1895             m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
1896     } else {
1897         MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
1898         
1899         slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfVectorLength())));
1900         
1901         if (!arrayMode.isOutOfBounds())
1902             speculationCheck(Uncountable, JSValueRegs(), NoNode, slowCases);
1903         
1904         m_jit.add32(TrustedImm32(1), propertyReg, temporaryReg);
1905         m_jit.store32(temporaryReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
1906         
1907         inBounds.link(&m_jit);
1908     }
1909     
1910     m_jit.storeDouble(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
1911
1912     base.use();
1913     property.use();
1914     value.use();
1915     storage.use();
1916     
1917     if (arrayMode.isOutOfBounds()) {
1918         addSlowPathGenerator(
1919             slowPathCall(
1920                 slowCases, this,
1921                 m_jit.codeBlock()->isStrictMode() ? operationPutDoubleByValBeyondArrayBoundsStrict : operationPutDoubleByValBeyondArrayBoundsNonStrict,
1922                 NoResult, baseReg, propertyReg, valueReg));
1923     }
1924
1925     noResult(m_compileIndex, UseChildrenCalledExplicitly);
1926 }
1927
1928 void SpeculativeJIT::compileGetCharCodeAt(Node& node)
1929 {
1930     SpeculateCellOperand string(this, node.child1());
1931     SpeculateStrictInt32Operand index(this, node.child2());
1932     StorageOperand storage(this, node.child3());
1933
1934     GPRReg stringReg = string.gpr();
1935     GPRReg indexReg = index.gpr();
1936     GPRReg storageReg = storage.gpr();
1937     
1938     ASSERT(speculationChecked(m_state.forNode(node.child1()).m_type, SpecString));
1939
1940     // unsigned comparison so we can filter out negative indices and indices that are too large
1941     speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, indexReg, MacroAssembler::Address(stringReg, JSString::offsetOfLength())));
1942
1943     GPRTemporary scratch(this);
1944     GPRReg scratchReg = scratch.gpr();
1945
1946     m_jit.loadPtr(MacroAssembler::Address(stringReg, JSString::offsetOfValue()), scratchReg);
1947
1948     // Load the character into scratchReg
1949     JITCompiler::Jump is16Bit = m_jit.branchTest32(MacroAssembler::Zero, MacroAssembler::Address(scratchReg, StringImpl::flagsOffset()), TrustedImm32(StringImpl::flagIs8Bit()));
1950
1951     m_jit.load8(MacroAssembler::BaseIndex(storageReg, indexReg, MacroAssembler::TimesOne, 0), scratchReg);
1952     JITCompiler::Jump cont8Bit = m_jit.jump();
1953
1954     is16Bit.link(&m_jit);
1955
1956     m_jit.load16(MacroAssembler::BaseIndex(storageReg, indexReg, MacroAssembler::TimesTwo, 0), scratchReg);
1957
1958     cont8Bit.link(&m_jit);
1959
1960     integerResult(scratchReg, m_compileIndex);
1961 }
1962
1963 void SpeculativeJIT::compileGetByValOnString(Node& node)
1964 {
1965     SpeculateCellOperand base(this, node.child1());
1966     SpeculateStrictInt32Operand property(this, node.child2());
1967     StorageOperand storage(this, node.child3());
1968     GPRReg baseReg = base.gpr();
1969     GPRReg propertyReg = property.gpr();
1970     GPRReg storageReg = storage.gpr();
1971
1972     ASSERT(ArrayMode(Array::String).alreadyChecked(m_jit.graph(), node, m_state.forNode(node.child1())));
1973
1974     // unsigned comparison so we can filter out negative indices and indices that are too large
1975     speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSString::offsetOfLength())));
1976
1977     GPRTemporary scratch(this);
1978     GPRReg scratchReg = scratch.gpr();
1979
1980     m_jit.loadPtr(MacroAssembler::Address(baseReg, JSString::offsetOfValue()), scratchReg);
1981
1982     // Load the character into scratchReg
1983     JITCompiler::Jump is16Bit = m_jit.branchTest32(MacroAssembler::Zero, MacroAssembler::Address(scratchReg, StringImpl::flagsOffset()), TrustedImm32(StringImpl::flagIs8Bit()));
1984
1985     m_jit.load8(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne, 0), scratchReg);
1986     JITCompiler::Jump cont8Bit = m_jit.jump();
1987
1988     is16Bit.link(&m_jit);
1989
1990     m_jit.load16(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesTwo, 0), scratchReg);
1991
1992     // We only support ascii characters
1993     speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, scratchReg, TrustedImm32(0x100)));
1994
1995     // 8 bit string values don't need the isASCII check.
1996     cont8Bit.link(&m_jit);
1997
1998     GPRTemporary smallStrings(this);
1999     GPRReg smallStringsReg = smallStrings.gpr();
2000     m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.globalData()->smallStrings.singleCharacterStrings()), smallStringsReg);
2001     m_jit.loadPtr(MacroAssembler::BaseIndex(smallStringsReg, scratchReg, MacroAssembler::ScalePtr, 0), scratchReg);
2002     speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTest32(MacroAssembler::Zero, scratchReg));
2003     cellResult(scratchReg, m_compileIndex);
2004 }
2005
2006 GeneratedOperandType SpeculativeJIT::checkGeneratedTypeForToInt32(NodeIndex nodeIndex)
2007 {
2008 #if DFG_ENABLE(DEBUG_VERBOSE)
2009     dataLog("checkGeneratedTypeForToInt32@%d   ", nodeIndex);
2010 #endif
2011     Node& node = at(nodeIndex);
2012     VirtualRegister virtualRegister = node.virtualRegister();
2013     GenerationInfo& info = m_generationInfo[virtualRegister];
2014
2015     if (info.registerFormat() == DataFormatNone) {
2016         if (node.hasConstant()) {
2017             if (isInt32Constant(nodeIndex))
2018                 return GeneratedOperandInteger;
2019
2020             if (isNumberConstant(nodeIndex))
2021                 return GeneratedOperandDouble;
2022
2023             terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
2024             return GeneratedOperandTypeUnknown;
2025         }
2026
2027         if (info.spillFormat() == DataFormatDouble)
2028             return GeneratedOperandDouble;
2029     }
2030
2031     switch (info.registerFormat()) {
2032     case DataFormatBoolean: // This type never occurs.
2033     case DataFormatStorage:
2034         ASSERT_NOT_REACHED();
2035
2036     case DataFormatCell:
2037         terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
2038         return GeneratedOperandTypeUnknown;
2039
2040     case DataFormatNone:
2041     case DataFormatJSCell:
2042     case DataFormatJS:
2043     case DataFormatJSBoolean:
2044         return GeneratedOperandJSValue;
2045
2046     case DataFormatJSInteger:
2047     case DataFormatInteger:
2048         return GeneratedOperandInteger;
2049
2050     case DataFormatJSDouble:
2051     case DataFormatDouble:
2052         return GeneratedOperandDouble;
2053         
2054     default:
2055         ASSERT_NOT_REACHED();
2056         return GeneratedOperandTypeUnknown;
2057     }
2058 }
2059
2060 void SpeculativeJIT::compileValueToInt32(Node& node)
2061 {
2062     if (at(node.child1()).shouldSpeculateInteger()) {
2063         SpeculateIntegerOperand op1(this, node.child1());
2064         GPRTemporary result(this, op1);
2065         m_jit.move(op1.gpr(), result.gpr());
2066         integerResult(result.gpr(), m_compileIndex, op1.format());
2067         return;
2068     }
2069     
2070     if (at(node.child1()).shouldSpeculateNumber()) {
2071         switch (checkGeneratedTypeForToInt32(node.child1().index())) {
2072         case GeneratedOperandInteger: {
2073             SpeculateIntegerOperand op1(this, node.child1());
2074             GPRTemporary result(this, op1);
2075             m_jit.move(op1.gpr(), result.gpr());
2076             integerResult(result.gpr(), m_compileIndex, op1.format());
2077             return;
2078         }
2079         case GeneratedOperandDouble: {
2080             GPRTemporary result(this);
2081             DoubleOperand op1(this, node.child1());
2082             FPRReg fpr = op1.fpr();
2083             GPRReg gpr = result.gpr();
2084             JITCompiler::Jump notTruncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateFailed);
2085             
2086             addSlowPathGenerator(slowPathCall(notTruncatedToInteger, this, toInt32, gpr, fpr));
2087
2088             integerResult(gpr, m_compileIndex);
2089             return;
2090         }
2091         case GeneratedOperandJSValue: {
2092             GPRTemporary result(this);
2093 #if USE(JSVALUE64)
2094             JSValueOperand op1(this, node.child1());
2095
2096             GPRReg gpr = op1.gpr();
2097             GPRReg resultGpr = result.gpr();
2098             FPRTemporary tempFpr(this);
2099             FPRReg fpr = tempFpr.fpr();
2100
2101             JITCompiler::Jump isInteger = m_jit.branch64(MacroAssembler::AboveOrEqual, gpr, GPRInfo::tagTypeNumberRegister);
2102
2103             if (!isNumberSpeculation(m_state.forNode(node.child1()).m_type))
2104                 speculationCheck(BadType, JSValueRegs(gpr), node.child1().index(), m_jit.branchTest64(MacroAssembler::Zero, gpr, GPRInfo::tagTypeNumberRegister));
2105
2106             // First, if we get here we have a double encoded as a JSValue
2107             m_jit.move(gpr, resultGpr);
2108             unboxDouble(resultGpr, fpr);
2109
2110             silentSpillAllRegisters(resultGpr);
2111             callOperation(toInt32, resultGpr, fpr);
2112             silentFillAllRegisters(resultGpr);
2113
2114             JITCompiler::Jump converted = m_jit.jump();
2115
2116             isInteger.link(&m_jit);
2117             m_jit.zeroExtend32ToPtr(gpr, resultGpr);
2118
2119             converted.link(&m_jit);
2120 #else
2121             Node& childNode = at(node.child1().index());
2122             VirtualRegister virtualRegister = childNode.virtualRegister();
2123             GenerationInfo& info = m_generationInfo[virtualRegister];
2124
2125             JSValueOperand op1(this, node.child1());
2126
2127             GPRReg payloadGPR = op1.payloadGPR();
2128             GPRReg resultGpr = result.gpr();
2129
2130             if (info.registerFormat() == DataFormatJSInteger)
2131                 m_jit.move(payloadGPR, resultGpr);
2132             else {
2133                 GPRReg tagGPR = op1.tagGPR();
2134                 FPRTemporary tempFpr(this);
2135                 FPRReg fpr = tempFpr.fpr();
2136                 FPRTemporary scratch(this);
2137
2138                 JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, tagGPR, TrustedImm32(JSValue::Int32Tag));
2139
2140                 if (!isNumberSpeculation(m_state.forNode(node.child1()).m_type))
2141                     speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), node.child1().index(), m_jit.branch32(MacroAssembler::AboveOrEqual, tagGPR, TrustedImm32(JSValue::LowestTag)));
2142
2143                 unboxDouble(tagGPR, payloadGPR, fpr, scratch.fpr());
2144
2145                 silentSpillAllRegisters(resultGpr);
2146                 callOperation(toInt32, resultGpr, fpr);
2147                 silentFillAllRegisters(resultGpr);
2148
2149                 JITCompiler::Jump converted = m_jit.jump();
2150
2151                 isInteger.link(&m_jit);
2152                 m_jit.move(payloadGPR, resultGpr);
2153
2154                 converted.link(&m_jit);
2155             }
2156 #endif
2157             integerResult(resultGpr, m_compileIndex);
2158             return;
2159         }
2160         case GeneratedOperandTypeUnknown:
2161             ASSERT_NOT_REACHED();
2162             break;
2163         }
2164     }
2165     
2166     if (at(node.child1()).shouldSpeculateBoolean()) {
2167         SpeculateBooleanOperand op1(this, node.child1());
2168         GPRTemporary result(this, op1);
2169         
2170         m_jit.move(op1.gpr(), result.gpr());
2171         m_jit.and32(JITCompiler::TrustedImm32(1), result.gpr());
2172         
2173         integerResult(result.gpr(), m_compileIndex);
2174         return;
2175     }
2176     
2177     // Do it the safe way.
2178     nonSpeculativeValueToInt32(node);
2179     return;
2180 }
2181
2182 void SpeculativeJIT::compileUInt32ToNumber(Node& node)
2183 {
2184     if (!nodeCanSpeculateInteger(node.arithNodeFlags())) {
2185         // We know that this sometimes produces doubles. So produce a double every
2186         // time. This at least allows subsequent code to not have weird conditionals.
2187             
2188         IntegerOperand op1(this, node.child1());
2189         FPRTemporary result(this);
2190             
2191         GPRReg inputGPR = op1.gpr();
2192         FPRReg outputFPR = result.fpr();
2193             
2194         m_jit.convertInt32ToDouble(inputGPR, outputFPR);
2195             
2196         JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, inputGPR, TrustedImm32(0));
2197         m_jit.addDouble(JITCompiler::AbsoluteAddress(&AssemblyHelpers::twoToThe32), outputFPR);
2198         positive.link(&m_jit);
2199             
2200         doubleResult(outputFPR, m_compileIndex);
2201         return;
2202     }
2203
2204     IntegerOperand op1(this, node.child1());
2205     GPRTemporary result(this); // For the benefit of OSR exit, force these to be in different registers. In reality the OSR exit compiler could find cases where you have uint32(%r1) followed by int32(%r1) and then use different registers, but that seems like too much effort.
2206
2207     m_jit.move(op1.gpr(), result.gpr());
2208
2209     // Test the operand is positive. This is a very special speculation check - we actually
2210     // use roll-forward speculation here, where if this fails, we jump to the baseline
2211     // instruction that follows us, rather than the one we're executing right now. We have
2212     // to do this because by this point, the original values necessary to compile whatever
2213     // operation the UInt32ToNumber originated from might be dead.
2214     forwardSpeculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, result.gpr(), TrustedImm32(0)), ValueRecovery::uint32InGPR(result.gpr()));
2215
2216     integerResult(result.gpr(), m_compileIndex, op1.format());
2217 }
2218
2219 void SpeculativeJIT::compileDoubleAsInt32(Node& node)
2220 {
2221     SpeculateDoubleOperand op1(this, node.child1());
2222     FPRTemporary scratch(this);
2223     GPRTemporary result(this);
2224     
2225     FPRReg valueFPR = op1.fpr();
2226     FPRReg scratchFPR = scratch.fpr();
2227     GPRReg resultGPR = result.gpr();
2228
2229     JITCompiler::JumpList failureCases;
2230     m_jit.branchConvertDoubleToInt32(valueFPR, resultGPR, failureCases, scratchFPR);
2231     forwardSpeculationCheck(Overflow, JSValueRegs(), NoNode, failureCases, ValueRecovery::inFPR(valueFPR));
2232
2233     integerResult(resultGPR, m_compileIndex);
2234 }
2235
2236 void SpeculativeJIT::compileInt32ToDouble(Node& node)
2237 {
2238 #if USE(JSVALUE64)
2239     // On JSVALUE64 we have a way of loading double constants in a more direct manner
2240     // than a int->double conversion. On 32_64, unfortunately, we currently don't have
2241     // any such mechanism - though we could have it, if we just provisioned some memory
2242     // in CodeBlock for the double form of integer constants.
2243     if (at(node.child1()).hasConstant()) {
2244         ASSERT(isInt32Constant(node.child1().index()));
2245         FPRTemporary result(this);
2246         GPRTemporary temp(this);
2247         m_jit.move(MacroAssembler::Imm64(reinterpretDoubleToInt64(valueOfNumberConstant(node.child1().index()))), temp.gpr());
2248         m_jit.move64ToDouble(temp.gpr(), result.fpr());
2249         doubleResult(result.fpr(), m_compileIndex);
2250         return;
2251     }
2252 #endif
2253     
2254     if (isInt32Speculation(m_state.forNode(node.child1()).m_type)) {
2255         SpeculateIntegerOperand op1(this, node.child1());
2256         FPRTemporary result(this);
2257         m_jit.convertInt32ToDouble(op1.gpr(), result.fpr());
2258         doubleResult(result.fpr(), m_compileIndex);
2259         return;
2260     }
2261     
2262     JSValueOperand op1(this, node.child1());
2263     FPRTemporary result(this);
2264     
2265 #if USE(JSVALUE64)
2266     GPRTemporary temp(this);
2267
2268     GPRReg op1GPR = op1.gpr();
2269     GPRReg tempGPR = temp.gpr();
2270     FPRReg resultFPR = result.fpr();
2271     
2272     JITCompiler::Jump isInteger = m_jit.branch64(
2273         MacroAssembler::AboveOrEqual, op1GPR, GPRInfo::tagTypeNumberRegister);
2274     
2275     if (!isNumberSpeculation(m_state.forNode(node.child1()).m_type)) {
2276         speculationCheck(
2277             BadType, JSValueRegs(op1GPR), node.child1(),
2278             m_jit.branchTest64(MacroAssembler::Zero, op1GPR, GPRInfo::tagTypeNumberRegister));
2279     }
2280     
2281     m_jit.move(op1GPR, tempGPR);
2282     unboxDouble(tempGPR, resultFPR);
2283     JITCompiler::Jump done = m_jit.jump();
2284     
2285     isInteger.link(&m_jit);
2286     m_jit.convertInt32ToDouble(op1GPR, resultFPR);
2287     done.link(&m_jit);
2288 #else
2289     FPRTemporary temp(this);
2290     
2291     GPRReg op1TagGPR = op1.tagGPR();
2292     GPRReg op1PayloadGPR = op1.payloadGPR();
2293     FPRReg tempFPR = temp.fpr();
2294     FPRReg resultFPR = result.fpr();
2295     
2296     JITCompiler::Jump isInteger = m_jit.branch32(
2297         MacroAssembler::Equal, op1TagGPR, TrustedImm32(JSValue::Int32Tag));
2298     
2299     if (!isNumberSpeculation(m_state.forNode(node.child1()).m_type)) {
2300         speculationCheck(
2301             BadType, JSValueRegs(op1TagGPR, op1PayloadGPR), node.child1(),
2302             m_jit.branch32(MacroAssembler::AboveOrEqual, op1TagGPR, TrustedImm32(JSValue::LowestTag)));
2303     }
2304     
2305     unboxDouble(op1TagGPR, op1PayloadGPR, resultFPR, tempFPR);
2306     JITCompiler::Jump done = m_jit.jump();
2307     
2308     isInteger.link(&m_jit);
2309     m_jit.convertInt32ToDouble(op1PayloadGPR, resultFPR);
2310     done.link(&m_jit);
2311 #endif
2312     
2313     doubleResult(resultFPR, m_compileIndex);
2314 }
2315
2316 static double clampDoubleToByte(double d)
2317 {
2318     d += 0.5;
2319     if (!(d > 0))
2320         d = 0;
2321     else if (d > 255)
2322         d = 255;
2323     return d;
2324 }
2325
2326 static void compileClampIntegerToByte(JITCompiler& jit, GPRReg result)
2327 {
2328     MacroAssembler::Jump inBounds = jit.branch32(MacroAssembler::BelowOrEqual, result, JITCompiler::TrustedImm32(0xff));
2329     MacroAssembler::Jump tooBig = jit.branch32(MacroAssembler::GreaterThan, result, JITCompiler::TrustedImm32(0xff));
2330     jit.xorPtr(result, result);
2331     MacroAssembler::Jump clamped = jit.jump();
2332     tooBig.link(&jit);
2333     jit.move(JITCompiler::TrustedImm32(255), result);
2334     clamped.link(&jit);
2335     inBounds.link(&jit);
2336 }
2337
2338 static void compileClampDoubleToByte(JITCompiler& jit, GPRReg result, FPRReg source, FPRReg scratch)
2339 {
2340     // Unordered compare so we pick up NaN
2341     static const double zero = 0;
2342     static const double byteMax = 255;
2343     static const double half = 0.5;
2344     jit.loadDouble(&zero, scratch);
2345     MacroAssembler::Jump tooSmall = jit.branchDouble(MacroAssembler::DoubleLessThanOrEqualOrUnordered, source, scratch);
2346     jit.loadDouble(&byteMax, scratch);
2347     MacroAssembler::Jump tooBig = jit.branchDouble(MacroAssembler::DoubleGreaterThan, source, scratch);
2348     
2349     jit.loadDouble(&half, scratch);
2350     // FIXME: This should probably just use a floating point round!
2351     // https://bugs.webkit.org/show_bug.cgi?id=72054
2352     jit.addDouble(source, scratch);
2353     jit.truncateDoubleToInt32(scratch, result);   
2354     MacroAssembler::Jump truncatedInt = jit.jump();
2355     
2356     tooSmall.link(&jit);
2357     jit.xorPtr(result, result);
2358     MacroAssembler::Jump zeroed = jit.jump();
2359     
2360     tooBig.link(&jit);
2361     jit.move(JITCompiler::TrustedImm32(255), result);
2362     
2363     truncatedInt.link(&jit);
2364     zeroed.link(&jit);
2365
2366 }
2367
2368 void SpeculativeJIT::compileGetByValOnIntTypedArray(const TypedArrayDescriptor& descriptor, Node& node, size_t elementSize, TypedArraySignedness signedness)
2369 {
2370     SpeculateCellOperand base(this, node.child1());
2371     SpeculateStrictInt32Operand property(this, node.child2());
2372     StorageOperand storage(this, node.child3());
2373
2374     GPRReg baseReg = base.gpr();
2375     GPRReg propertyReg = property.gpr();
2376     GPRReg storageReg = storage.gpr();
2377
2378     GPRTemporary result(this);
2379     GPRReg resultReg = result.gpr();
2380
2381     ASSERT(node.arrayMode().alreadyChecked(m_jit.graph(), node, m_state.forNode(node.child1())));
2382
2383     speculationCheck(
2384         Uncountable, JSValueRegs(), NoNode,
2385         m_jit.branch32(
2386             MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, descriptor.m_lengthOffset)));
2387     switch (elementSize) {
2388     case 1:
2389         if (signedness == SignedTypedArray)
2390             m_jit.load8Signed(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne), resultReg);
2391         else
2392             m_jit.load8(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne), resultReg);
2393         break;
2394     case 2:
2395         if (signedness == SignedTypedArray)
2396             m_jit.load16Signed(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesTwo), resultReg);
2397         else
2398             m_jit.load16(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesTwo), resultReg);
2399         break;
2400     case 4:
2401         m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesFour), resultReg);
2402         break;
2403     default:
2404         CRASH();
2405     }
2406     if (elementSize < 4 || signedness == SignedTypedArray) {
2407         integerResult(resultReg, m_compileIndex);
2408         return;
2409     }
2410     
2411     ASSERT(elementSize == 4 && signedness == UnsignedTypedArray);
2412     if (node.shouldSpeculateInteger()) {
2413         forwardSpeculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, resultReg, TrustedImm32(0)), ValueRecovery::uint32InGPR(resultReg));
2414         integerResult(resultReg, m_compileIndex);
2415         return;
2416     }
2417     
2418     FPRTemporary fresult(this);
2419     m_jit.convertInt32ToDouble(resultReg, fresult.fpr());
2420     JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, resultReg, TrustedImm32(0));
2421     m_jit.addDouble(JITCompiler::AbsoluteAddress(&AssemblyHelpers::twoToThe32), fresult.fpr());
2422     positive.link(&m_jit);
2423     doubleResult(fresult.fpr(), m_compileIndex);
2424 }
2425
2426 void SpeculativeJIT::compilePutByValForIntTypedArray(const TypedArrayDescriptor& descriptor, GPRReg base, GPRReg property, Node& node, size_t elementSize, TypedArraySignedness signedness, TypedArrayRounding rounding)
2427 {
2428     StorageOperand storage(this, m_jit.graph().varArgChild(node, 3));
2429     GPRReg storageReg = storage.gpr();
2430     
2431     Edge valueUse = m_jit.graph().varArgChild(node, 2);
2432     
2433     GPRTemporary value;
2434     GPRReg valueGPR;
2435     
2436     if (at(valueUse).isConstant()) {
2437         JSValue jsValue = valueOfJSConstant(valueUse.index());
2438         if (!jsValue.isNumber()) {
2439             terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
2440             noResult(m_compileIndex);
2441             return;
2442         }
2443         double d = jsValue.asNumber();
2444         if (rounding == ClampRounding) {
2445             ASSERT(elementSize == 1);
2446             d = clampDoubleToByte(d);
2447         }
2448         GPRTemporary scratch(this);
2449         GPRReg scratchReg = scratch.gpr();
2450         m_jit.move(Imm32(toInt32(d)), scratchReg);
2451         value.adopt(scratch);
2452         valueGPR = scratchReg;
2453     } else if (at(valueUse).shouldSpeculateInteger()) {
2454         SpeculateIntegerOperand valueOp(this, valueUse);
2455         GPRTemporary scratch(this);
2456         GPRReg scratchReg = scratch.gpr();
2457         m_jit.move(valueOp.gpr(), scratchReg);
2458         if (rounding == ClampRounding) {
2459             ASSERT(elementSize == 1);
2460             compileClampIntegerToByte(m_jit, scratchReg);
2461         }
2462         value.adopt(scratch);
2463         valueGPR = scratchReg;
2464     } else if (rounding == ClampRounding) {
2465         ASSERT(elementSize == 1);
2466         SpeculateDoubleOperand valueOp(this, valueUse);
2467         GPRTemporary result(this);
2468         FPRTemporary floatScratch(this);
2469         FPRReg fpr = valueOp.fpr();
2470         GPRReg gpr = result.gpr();
2471         compileClampDoubleToByte(m_jit, gpr, fpr, floatScratch.fpr());
2472         value.adopt(result);
2473         valueGPR = gpr;
2474     } else {
2475         SpeculateDoubleOperand valueOp(this, valueUse);
2476         GPRTemporary result(this);
2477         FPRReg fpr = valueOp.fpr();
2478         GPRReg gpr = result.gpr();
2479         MacroAssembler::Jump notNaN = m_jit.branchDouble(MacroAssembler::DoubleEqual, fpr, fpr);
2480         m_jit.xorPtr(gpr, gpr);
2481         MacroAssembler::Jump fixed = m_jit.jump();
2482         notNaN.link(&m_jit);
2483
2484         MacroAssembler::Jump failed;
2485         if (signedness == SignedTypedArray)
2486             failed = m_jit.branchTruncateDoubleToInt32(fpr, gpr, MacroAssembler::BranchIfTruncateFailed);
2487         else
2488             failed = m_jit.branchTruncateDoubleToUint32(fpr, gpr, MacroAssembler::BranchIfTruncateFailed);
2489         
2490         addSlowPathGenerator(slowPathCall(failed, this, toInt32, gpr, fpr));
2491
2492         fixed.link(&m_jit);
2493         value.adopt(result);
2494         valueGPR = gpr;
2495     }
2496     ASSERT_UNUSED(valueGPR, valueGPR != property);
2497     ASSERT(valueGPR != base);
2498     ASSERT(valueGPR != storageReg);
2499     MacroAssembler::Jump outOfBounds;
2500     if (node.op() == PutByVal)
2501         outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, property, MacroAssembler::Address(base, descriptor.m_lengthOffset));
2502
2503     switch (elementSize) {
2504     case 1:
2505         m_jit.store8(value.gpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesOne));
2506         break;
2507     case 2:
2508         m_jit.store16(value.gpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesTwo));
2509         break;
2510     case 4:
2511         m_jit.store32(value.gpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesFour));
2512         break;
2513     default:
2514         CRASH();
2515     }
2516     if (node.op() == PutByVal)
2517         outOfBounds.link(&m_jit);
2518     noResult(m_compileIndex);
2519 }
2520
2521 void SpeculativeJIT::compileGetByValOnFloatTypedArray(const TypedArrayDescriptor& descriptor, Node& node, size_t elementSize)
2522 {
2523     SpeculateCellOperand base(this, node.child1());
2524     SpeculateStrictInt32Operand property(this, node.child2());
2525     StorageOperand storage(this, node.child3());
2526
2527     GPRReg baseReg = base.gpr();
2528     GPRReg propertyReg = property.gpr();
2529     GPRReg storageReg = storage.gpr();
2530
2531     ASSERT(node.arrayMode().alreadyChecked(m_jit.graph(), node, m_state.forNode(node.child1())));
2532
2533     FPRTemporary result(this);
2534     FPRReg resultReg = result.fpr();
2535     speculationCheck(
2536         Uncountable, JSValueRegs(), NoNode,
2537         m_jit.branch32(
2538             MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, descriptor.m_lengthOffset)));
2539     switch (elementSize) {
2540     case 4:
2541         m_jit.loadFloat(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesFour), resultReg);
2542         m_jit.convertFloatToDouble(resultReg, resultReg);
2543         break;
2544     case 8: {
2545         m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
2546         MacroAssembler::Jump notNaN = m_jit.branchDouble(MacroAssembler::DoubleEqual, resultReg, resultReg);
2547         static const double NaN = QNaN;
2548         m_jit.loadDouble(&NaN, resultReg);
2549         notNaN.link(&m_jit);
2550         break;
2551     }
2552     default:
2553         ASSERT_NOT_REACHED();
2554     }
2555     doubleResult(resultReg, m_compileIndex);
2556 }
2557
2558 void SpeculativeJIT::compilePutByValForFloatTypedArray(const TypedArrayDescriptor& descriptor, GPRReg base, GPRReg property, Node& node, size_t elementSize)
2559 {
2560     StorageOperand storage(this, m_jit.graph().varArgChild(node, 3));
2561     GPRReg storageReg = storage.gpr();
2562     
2563     Edge baseUse = m_jit.graph().varArgChild(node, 0);
2564     Edge valueUse = m_jit.graph().varArgChild(node, 2);
2565     
2566     SpeculateDoubleOperand valueOp(this, valueUse);
2567     
2568     ASSERT_UNUSED(baseUse, node.arrayMode().alreadyChecked(m_jit.graph(), m_jit.graph()[m_compileIndex], m_state.forNode(baseUse)));
2569     
2570     GPRTemporary result(this);
2571     
2572     MacroAssembler::Jump outOfBounds;
2573     if (node.op() == PutByVal)
2574         outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, property, MacroAssembler::Address(base, descriptor.m_lengthOffset));
2575     
2576     switch (elementSize) {
2577     case 4: {
2578         FPRTemporary scratch(this);
2579         m_jit.moveDouble(valueOp.fpr(), scratch.fpr());
2580         m_jit.convertDoubleToFloat(valueOp.fpr(), scratch.fpr());
2581         m_jit.storeFloat(scratch.fpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesFour));
2582         break;
2583     }
2584     case 8:
2585         m_jit.storeDouble(valueOp.fpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesEight));
2586         break;
2587     default:
2588         ASSERT_NOT_REACHED();
2589     }
2590     if (node.op() == PutByVal)
2591         outOfBounds.link(&m_jit);
2592     noResult(m_compileIndex);
2593 }
2594
2595 void SpeculativeJIT::compileInstanceOfForObject(Node&, GPRReg valueReg, GPRReg prototypeReg, GPRReg scratchReg)
2596 {
2597     // Check that prototype is an object.
2598     m_jit.loadPtr(MacroAssembler::Address(prototypeReg, JSCell::structureOffset()), scratchReg);
2599     speculationCheck(BadType, JSValueRegs(), NoNode, m_jit.branchIfNotObject(scratchReg));
2600     
2601     // Initialize scratchReg with the value being checked.
2602     m_jit.move(valueReg, scratchReg);
2603     
2604     // Walk up the prototype chain of the value (in scratchReg), comparing to prototypeReg.
2605     MacroAssembler::Label loop(&m_jit);
2606     m_jit.loadPtr(MacroAssembler::Address(scratchReg, JSCell::structureOffset()), scratchReg);
2607 #if USE(JSVALUE64)
2608     m_jit.load64(MacroAssembler::Address(scratchReg, Structure::prototypeOffset()), scratchReg);
2609     MacroAssembler::Jump isInstance = m_jit.branch64(MacroAssembler::Equal, scratchReg, prototypeReg);
2610     m_jit.branchTest64(MacroAssembler::Zero, scratchReg, GPRInfo::tagMaskRegister).linkTo(loop, &m_jit);
2611 #else
2612     m_jit.load32(MacroAssembler::Address(scratchReg, Structure::prototypeOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), scratchReg);
2613     MacroAssembler::Jump isInstance = m_jit.branchPtr(MacroAssembler::Equal, scratchReg, prototypeReg);
2614     m_jit.branchTest32(MacroAssembler::NonZero, scratchReg).linkTo(loop, &m_jit);
2615 #endif
2616     
2617     // No match - result is false.
2618 #if USE(JSVALUE64)
2619     m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(false))), scratchReg);
2620 #else
2621     m_jit.move(MacroAssembler::TrustedImm32(0), scratchReg);
2622 #endif
2623     MacroAssembler::Jump putResult = m_jit.jump();
2624     
2625     isInstance.link(&m_jit);
2626 #if USE(JSVALUE64)
2627     m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(true))), scratchReg);
2628 #else
2629     m_jit.move(MacroAssembler::TrustedImm32(1), scratchReg);
2630 #endif
2631     
2632     putResult.link(&m_jit);
2633 }
2634
2635 void SpeculativeJIT::compileInstanceOf(Node& node)
2636 {
2637     if ((!!(at(node.child1()).prediction() & ~SpecCell)
2638          && !!(m_state.forNode(node.child1()).m_type & ~SpecCell))
2639         || at(node.child1()).adjustedRefCount() == 1) {
2640         // It might not be a cell. Speculate less aggressively.
2641         // Or: it might only be used once (i.e. by us), so we get zero benefit
2642         // from speculating any more aggressively than we absolutely need to.
2643         
2644         JSValueOperand value(this, node.child1());
2645         SpeculateCellOperand prototype(this, node.child2());
2646         GPRTemporary scratch(this);
2647         
2648         GPRReg prototypeReg = prototype.gpr();
2649         GPRReg scratchReg = scratch.gpr();
2650         
2651 #if USE(JSVALUE64)
2652         GPRReg valueReg = value.gpr();
2653         MacroAssembler::Jump isCell = m_jit.branchTest64(MacroAssembler::Zero, valueReg, GPRInfo::tagMaskRegister);
2654         m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(false))), scratchReg);
2655 #else
2656         GPRReg valueTagReg = value.tagGPR();
2657         GPRReg valueReg = value.payloadGPR();
2658         MacroAssembler::Jump isCell = m_jit.branch32(MacroAssembler::Equal, valueTagReg, TrustedImm32(JSValue::CellTag));
2659         m_jit.move(MacroAssembler::TrustedImm32(0), scratchReg);
2660 #endif
2661
2662         MacroAssembler::Jump done = m_jit.jump();
2663         
2664         isCell.link(&m_jit);
2665         
2666         compileInstanceOfForObject(node, valueReg, prototypeReg, scratchReg);
2667         
2668         done.link(&m_jit);
2669
2670 #if USE(JSVALUE64)
2671         jsValueResult(scratchReg, m_compileIndex, DataFormatJSBoolean);
2672 #else
2673         booleanResult(scratchReg, m_compileIndex);
2674 #endif
2675         return;
2676     }
2677     
2678     SpeculateCellOperand value(this, node.child1());
2679     SpeculateCellOperand prototype(this, node.child2());
2680     
2681     GPRTemporary scratch(this);
2682     
2683     GPRReg valueReg = value.gpr();
2684     GPRReg prototypeReg = prototype.gpr();
2685     GPRReg scratchReg = scratch.gpr();
2686     
2687     compileInstanceOfForObject(node, valueReg, prototypeReg, scratchReg);
2688
2689 #if USE(JSVALUE64)
2690     jsValueResult(scratchReg, m_compileIndex, DataFormatJSBoolean);
2691 #else
2692     booleanResult(scratchReg, m_compileIndex);
2693 #endif
2694 }
2695
2696 void SpeculativeJIT::compileSoftModulo(Node& node)
2697 {
2698     // In the fast path, the dividend value could be the final result
2699     // (in case of |dividend| < |divisor|), so we speculate it as strict int32.
2700     SpeculateStrictInt32Operand op1(this, node.child1());
2701 #if CPU(X86) || CPU(X86_64)
2702     if (isInt32Constant(node.child2().index())) {
2703         int32_t divisor = valueOfInt32Constant(node.child2().index());
2704         if (divisor) {
2705             GPRReg op1Gpr = op1.gpr();
2706
2707             GPRTemporary eax(this, X86Registers::eax);
2708             GPRTemporary edx(this, X86Registers::edx);
2709             GPRTemporary scratch(this);
2710             GPRReg scratchGPR = scratch.gpr();
2711
2712             GPRReg op1SaveGPR;
2713             if (op1Gpr == X86Registers::eax || op1Gpr == X86Registers::edx) {
2714                 op1SaveGPR = allocate();
2715                 ASSERT(op1Gpr != op1SaveGPR);
2716                 m_jit.move(op1Gpr, op1SaveGPR);
2717             } else
2718                 op1SaveGPR = op1Gpr;
2719             ASSERT(op1SaveGPR != X86Registers::eax);
2720             ASSERT(op1SaveGPR != X86Registers::edx);
2721
2722             m_jit.move(op1Gpr, eax.gpr());
2723             m_jit.move(TrustedImm32(divisor), scratchGPR);
2724             if (divisor == -1)
2725                 speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branch32(JITCompiler::Equal, eax.gpr(), TrustedImm32(-2147483647-1)));
2726             m_jit.assembler().cdq();
2727             m_jit.assembler().idivl_r(scratchGPR);
2728             // Check that we're not about to create negative zero.
2729             // FIXME: if the node use doesn't care about neg zero, we can do this more easily.
2730             JITCompiler::Jump numeratorPositive = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op1SaveGPR, TrustedImm32(0));
2731             speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(JITCompiler::Zero, edx.gpr()));
2732             numeratorPositive.link(&m_jit);
2733             
2734             if (op1SaveGPR != op1Gpr)
2735                 unlock(op1SaveGPR);
2736
2737             integerResult(edx.gpr(), m_compileIndex);
2738             return;
2739         }
2740     }
2741 #endif
2742
2743     SpeculateIntegerOperand op2(this, node.child2());
2744 #if CPU(X86) || CPU(X86_64)
2745     GPRTemporary eax(this, X86Registers::eax);
2746     GPRTemporary edx(this, X86Registers::edx);
2747     GPRReg op1GPR = op1.gpr();
2748     GPRReg op2GPR = op2.gpr();
2749     
2750     GPRReg op2TempGPR;
2751     GPRReg temp;
2752     GPRReg op1SaveGPR;
2753     
2754     if (op2GPR == X86Registers::eax || op2GPR == X86Registers::edx) {
2755         op2TempGPR = allocate();
2756         temp = op2TempGPR;
2757     } else {
2758         op2TempGPR = InvalidGPRReg;
2759         if (op1GPR == X86Registers::eax)
2760             temp = X86Registers::edx;
2761         else
2762             temp = X86Registers::eax;
2763     }
2764     
2765     if (op1GPR == X86Registers::eax || op1GPR == X86Registers::edx) {
2766         op1SaveGPR = allocate();
2767         ASSERT(op1GPR != op1SaveGPR);
2768         m_jit.move(op1GPR, op1SaveGPR);
2769     } else
2770         op1SaveGPR = op1GPR;
2771     
2772     ASSERT(temp != op1GPR);
2773     ASSERT(temp != op2GPR);
2774     ASSERT(op1SaveGPR != X86Registers::eax);
2775     ASSERT(op1SaveGPR != X86Registers::edx);
2776     
2777     m_jit.add32(JITCompiler::TrustedImm32(1), op2GPR, temp);
2778     
2779     JITCompiler::Jump safeDenominator = m_jit.branch32(JITCompiler::Above, temp, JITCompiler::TrustedImm32(1));
2780     
2781     JITCompiler::Jump done;
2782     // FIXME: if the node is not used as number then we can do this more easily.
2783     speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(JITCompiler::Zero, op2GPR));
2784     speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branch32(JITCompiler::Equal, op1GPR, TrustedImm32(-2147483647-1)));
2785     
2786     safeDenominator.link(&m_jit);
2787             
2788     if (op2TempGPR != InvalidGPRReg) {
2789         m_jit.move(op2GPR, op2TempGPR);
2790         op2GPR = op2TempGPR;
2791     }
2792             
2793     m_jit.move(op1GPR, eax.gpr());
2794     m_jit.assembler().cdq();
2795     m_jit.assembler().idivl_r(op2GPR);
2796             
2797     if (op2TempGPR != InvalidGPRReg)
2798         unlock(op2TempGPR);
2799
2800     // Check that we're not about to create negative zero.
2801     // FIXME: if the node use doesn't care about neg zero, we can do this more easily.
2802     JITCompiler::Jump numeratorPositive = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op1SaveGPR, TrustedImm32(0));
2803     speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(JITCompiler::Zero, edx.gpr()));
2804     numeratorPositive.link(&m_jit);
2805     
2806     if (op1SaveGPR != op1GPR)
2807         unlock(op1SaveGPR);
2808             
2809     integerResult(edx.gpr(), m_compileIndex);
2810 #else // CPU(X86) || CPU(X86_64) --> so not X86
2811     // Do this the *safest* way possible: call out to a C function that will do the modulo,
2812     // and then attempt to convert back.
2813     GPRReg op1GPR = op1.gpr();
2814     GPRReg op2GPR = op2.gpr();
2815     
2816     FPRResult result(this);
2817     
2818     flushRegisters();
2819     callOperation(operationFModOnInts, result.fpr(), op1GPR, op2GPR);
2820     
2821     FPRTemporary scratch(this);
2822     GPRTemporary intResult(this);
2823     JITCompiler::JumpList failureCases;
2824     m_jit.branchConvertDoubleToInt32(result.fpr(), intResult.gpr(), failureCases, scratch.fpr());
2825     speculationCheck(Overflow, JSValueRegs(), NoNode, failureCases);
2826     
2827     integerResult(intResult.gpr(), m_compileIndex);
2828 #endif // CPU(X86) || CPU(X86_64)
2829 }
2830
2831 void SpeculativeJIT::compileAdd(Node& node)
2832 {
2833     if (m_jit.graph().addShouldSpeculateInteger(node)) {
2834         if (isNumberConstant(node.child1().index())) {
2835             int32_t imm1 = valueOfNumberConstantAsInt32(node.child1().index());
2836             SpeculateIntegerOperand op2(this, node.child2());
2837             GPRTemporary result(this);
2838
2839             if (nodeCanTruncateInteger(node.arithNodeFlags())) {
2840                 m_jit.move(op2.gpr(), result.gpr());
2841                 m_jit.add32(Imm32(imm1), result.gpr());
2842             } else
2843                 speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchAdd32(MacroAssembler::Overflow, op2.gpr(), Imm32(imm1), result.gpr()));
2844
2845             integerResult(result.gpr(), m_compileIndex);
2846             return;
2847         }
2848                 
2849         if (isNumberConstant(node.child2().index())) {
2850             SpeculateIntegerOperand op1(this, node.child1());
2851             int32_t imm2 = valueOfNumberConstantAsInt32(node.child2().index());
2852             GPRTemporary result(this);
2853                 
2854             if (nodeCanTruncateInteger(node.arithNodeFlags())) {
2855                 m_jit.move(op1.gpr(), result.gpr());
2856                 m_jit.add32(Imm32(imm2), result.gpr());
2857             } else
2858                 speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchAdd32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
2859
2860             integerResult(result.gpr(), m_compileIndex);
2861             return;
2862         }
2863                 
2864         SpeculateIntegerOperand op1(this, node.child1());
2865         SpeculateIntegerOperand op2(this, node.child2());
2866         GPRTemporary result(this, op1, op2);
2867
2868         GPRReg gpr1 = op1.gpr();
2869         GPRReg gpr2 = op2.gpr();
2870         GPRReg gprResult = result.gpr();
2871
2872         if (nodeCanTruncateInteger(node.arithNodeFlags())) {
2873             if (gpr1 == gprResult)
2874                 m_jit.add32(gpr2, gprResult);
2875             else {
2876                 m_jit.move(gpr2, gprResult);
2877                 m_jit.add32(gpr1, gprResult);
2878             }
2879         } else {
2880             MacroAssembler::Jump check = m_jit.branchAdd32(MacroAssembler::Overflow, gpr1, gpr2, gprResult);
2881                 
2882             if (gpr1 == gprResult)
2883                 speculationCheck(Overflow, JSValueRegs(), NoNode, check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr2));
2884             else if (gpr2 == gprResult)
2885                 speculationCheck(Overflow, JSValueRegs(), NoNode, check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr1));
2886             else
2887                 speculationCheck(Overflow, JSValueRegs(), NoNode, check);
2888         }
2889
2890         integerResult(gprResult, m_compileIndex);
2891         return;
2892     }
2893         
2894     if (Node::shouldSpeculateNumberExpectingDefined(at(node.child1()), at(node.child2()))) {
2895         SpeculateDoubleOperand op1(this, node.child1());
2896         SpeculateDoubleOperand op2(this, node.child2());
2897         FPRTemporary result(this, op1, op2);
2898
2899         FPRReg reg1 = op1.fpr();
2900         FPRReg reg2 = op2.fpr();
2901         m_jit.addDouble(reg1, reg2, result.fpr());
2902
2903         doubleResult(result.fpr(), m_compileIndex);
2904         return;
2905     }
2906
2907     if (node.op() == ValueAdd) {
2908         compileValueAdd(node);
2909         return;
2910     }
2911     
2912     // We don't handle this yet. :-(
2913     terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode);
2914 }
2915
2916 void SpeculativeJIT::compileArithSub(Node& node)
2917 {
2918     if (m_jit.graph().addShouldSpeculateInteger(node)) {
2919         if (isNumberConstant(node.child2().index())) {
2920             SpeculateIntegerOperand op1(this, node.child1());
2921             int32_t imm2 = valueOfNumberConstantAsInt32(node.child2().index());
2922             GPRTemporary result(this);
2923
2924             if (nodeCanTruncateInteger(node.arithNodeFlags())) {
2925                 m_jit.move(op1.gpr(), result.gpr());
2926                 m_jit.sub32(Imm32(imm2), result.gpr());
2927             } else {
2928 #if ENABLE(JIT_CONSTANT_BLINDING)
2929                 GPRTemporary scratch(this);
2930                 speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr(), scratch.gpr()));
2931 #else
2932                 speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
2933 #endif
2934             }
2935
2936             integerResult(result.gpr(), m_compileIndex);
2937             return;
2938         }
2939             
2940         if (isNumberConstant(node.child1().index())) {
2941             int32_t imm1 = valueOfNumberConstantAsInt32(node.child1().index());
2942             SpeculateIntegerOperand op2(this, node.child2());
2943             GPRTemporary result(this);
2944                 
2945             m_jit.move(Imm32(imm1), result.gpr());
2946             if (nodeCanTruncateInteger(node.arithNodeFlags()))
2947                 m_jit.sub32(op2.gpr(), result.gpr());
2948             else
2949                 speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchSub32(MacroAssembler::Overflow, op2.gpr(), result.gpr()));
2950                 
2951             integerResult(result.gpr(), m_compileIndex);
2952             return;
2953         }
2954             
2955         SpeculateIntegerOperand op1(this, node.child1());
2956         SpeculateIntegerOperand op2(this, node.child2());
2957         GPRTemporary result(this);
2958
2959         if (nodeCanTruncateInteger(node.arithNodeFlags())) {
2960             m_jit.move(op1.gpr(), result.gpr());
2961             m_jit.sub32(op2.gpr(), result.gpr());
2962         } else
2963             speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), op2.gpr(), result.gpr()));
2964
2965         integerResult(result.gpr(), m_compileIndex);
2966         return;
2967     }
2968         
2969     SpeculateDoubleOperand op1(this, node.child1());
2970     SpeculateDoubleOperand op2(this, node.child2());
2971     FPRTemporary result(this, op1);
2972
2973     FPRReg reg1 = op1.fpr();
2974     FPRReg reg2 = op2.fpr();
2975     m_jit.subDouble(reg1, reg2, result.fpr());
2976
2977     doubleResult(result.fpr(), m_compileIndex);
2978 }
2979
2980 void SpeculativeJIT::compileArithNegate(Node& node)
2981 {
2982     if (m_jit.graph().negateShouldSpeculateInteger(node)) {
2983         SpeculateIntegerOperand op1(this, node.child1());
2984         GPRTemporary result(this);
2985
2986         m_jit.move(op1.gpr(), result.gpr());
2987
2988         if (nodeCanTruncateInteger(node.arithNodeFlags()))
2989             m_jit.neg32(result.gpr());
2990         else {
2991             speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchNeg32(MacroAssembler::Overflow, result.gpr()));
2992             if (!nodeCanIgnoreNegativeZero(node.arithNodeFlags()))
2993                 speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(MacroAssembler::Zero, result.gpr()));
2994         }
2995
2996         integerResult(result.gpr(), m_compileIndex);
2997         return;
2998     }
2999         
3000     SpeculateDoubleOperand op1(this, node.child1());
3001     FPRTemporary result(this);
3002
3003     m_jit.negateDouble(op1.fpr(), result.fpr());
3004
3005     doubleResult(result.fpr(), m_compileIndex);
3006 }
3007
3008 void SpeculativeJIT::compileArithMul(Node& node)
3009 {
3010     if (m_jit.graph().mulShouldSpeculateInteger(node)) {
3011         SpeculateIntegerOperand op1(this, node.child1());
3012         SpeculateIntegerOperand op2(this, node.child2());
3013         GPRTemporary result(this);
3014
3015         GPRReg reg1 = op1.gpr();
3016         GPRReg reg2 = op2.gpr();
3017
3018         // We can perform truncated multiplications if we get to this point, because if the
3019         // fixup phase could not prove that it would be safe, it would have turned us into
3020         // a double multiplication.
3021         if (nodeCanTruncateInteger(node.arithNodeFlags())) {
3022             m_jit.move(reg1, result.gpr());
3023             m_jit.mul32(reg2, result.gpr());
3024         } else {
3025             speculationCheck(
3026                 Overflow, JSValueRegs(), NoNode,
3027                 m_jit.branchMul32(MacroAssembler::Overflow, reg1, reg2, result.gpr()));
3028         }
3029             
3030         // Check for negative zero, if the users of this node care about such things.
3031         if (!nodeCanIgnoreNegativeZero(node.arithNodeFlags())) {
3032             MacroAssembler::Jump resultNonZero = m_jit.branchTest32(MacroAssembler::NonZero, result.gpr());
3033             speculationCheck(NegativeZero, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, reg1, TrustedImm32(0)));
3034             speculationCheck(NegativeZero, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, reg2, TrustedImm32(0)));
3035             resultNonZero.link(&m_jit);
3036         }
3037
3038         integerResult(result.gpr(), m_compileIndex);
3039         return;
3040     }
3041
3042     SpeculateDoubleOperand op1(this, node.child1());
3043     SpeculateDoubleOperand op2(this, node.child2());
3044     FPRTemporary result(this, op1, op2);
3045
3046     FPRReg reg1 = op1.fpr();
3047     FPRReg reg2 = op2.fpr();
3048         
3049     m_jit.mulDouble(reg1, reg2, result.fpr());
3050         
3051     doubleResult(result.fpr(), m_compileIndex);
3052 }
3053
3054 #if CPU(X86) || CPU(X86_64)
3055 void SpeculativeJIT::compileIntegerArithDivForX86(Node& node)
3056 {
3057     SpeculateIntegerOperand op1(this, node.child1());
3058     SpeculateIntegerOperand op2(this, node.child2());
3059     GPRTemporary eax(this, X86Registers::eax);
3060     GPRTemporary edx(this, X86Registers::edx);
3061     GPRReg op1GPR = op1.gpr();
3062     GPRReg op2GPR = op2.gpr();
3063     
3064     GPRReg op2TempGPR;
3065     GPRReg temp;
3066     if (op2GPR == X86Registers::eax || op2GPR == X86Registers::edx) {
3067         op2TempGPR = allocate();
3068         temp = op2TempGPR;
3069     } else {
3070         op2TempGPR = InvalidGPRReg;
3071         if (op1GPR == X86Registers::eax)
3072             temp = X86Registers::edx;
3073         else
3074             temp = X86Registers::eax;
3075     }
3076     
3077     ASSERT(temp != op1GPR);
3078     ASSERT(temp != op2GPR);
3079     
3080     m_jit.add32(JITCompiler::TrustedImm32(1), op2GPR, temp);
3081     
3082     JITCompiler::Jump safeDenominator = m_jit.branch32(JITCompiler::Above, temp, JITCompiler::TrustedImm32(1));
3083     
3084     JITCompiler::Jump done;
3085     if (nodeUsedAsNumber(node.arithNodeFlags())) {
3086         speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(JITCompiler::Zero, op2GPR));
3087         speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branch32(JITCompiler::Equal, op1GPR, TrustedImm32(-2147483647-1)));
3088     } else {
3089         JITCompiler::Jump zero = m_jit.branchTest32(JITCompiler::Zero, op2GPR);
3090         JITCompiler::Jump notNeg2ToThe31 = m_jit.branch32(JITCompiler::Equal, op1GPR, TrustedImm32(-2147483647-1));
3091         zero.link(&m_jit);
3092         m_jit.move(TrustedImm32(0), eax.gpr());
3093         done = m_jit.jump();
3094         notNeg2ToThe31.link(&m_jit);
3095     }
3096     
3097     safeDenominator.link(&m_jit);
3098             
3099     // If the user cares about negative zero, then speculate that we're not about
3100     // to produce negative zero.
3101     if (!nodeCanIgnoreNegativeZero(node.arithNodeFlags())) {
3102         MacroAssembler::Jump numeratorNonZero = m_jit.branchTest32(MacroAssembler::NonZero, op1GPR);
3103         speculationCheck(NegativeZero, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, op2GPR, TrustedImm32(0)));
3104         numeratorNonZero.link(&m_jit);
3105     }
3106     
3107     if (op2TempGPR != InvalidGPRReg) {
3108         m_jit.move(op2GPR, op2TempGPR);
3109         op2GPR = op2TempGPR;
3110     }
3111             
3112     m_jit.move(op1GPR, eax.gpr());
3113     m_jit.assembler().cdq();
3114     m_jit.assembler().idivl_r(op2GPR);
3115             
3116     if (op2TempGPR != InvalidGPRReg)
3117         unlock(op2TempGPR);
3118
3119     // Check that there was no remainder. If there had been, then we'd be obligated to
3120     // produce a double result instead.
3121     if (nodeUsedAsNumber(node.arithNodeFlags()))
3122         speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(JITCompiler::NonZero, edx.gpr()));
3123     else
3124         done.link(&m_jit);
3125             
3126     integerResult(eax.gpr(), m_compileIndex);
3127 }
3128 #endif // CPU(X86) || CPU(X86_64)
3129
3130 void SpeculativeJIT::compileArithMod(Node& node)
3131 {
3132     if (Node::shouldSpeculateIntegerForArithmetic(at(node.child1()), at(node.child2()))
3133         && node.canSpeculateInteger()) {
3134         compileSoftModulo(node);
3135         return;
3136     }
3137         
3138     SpeculateDoubleOperand op1(this, node.child1());
3139     SpeculateDoubleOperand op2(this, node.child2());
3140         
3141     FPRReg op1FPR = op1.fpr();
3142     FPRReg op2FPR = op2.fpr();
3143         
3144     flushRegisters();
3145         
3146     FPRResult result(this);
3147
3148     callOperation(fmodAsDFGOperation, result.fpr(), op1FPR, op2FPR);
3149         
3150     doubleResult(result.fpr(), m_compileIndex);
3151 }
3152
3153 // Returns true if the compare is fused with a subsequent branch.
3154 bool SpeculativeJIT::compare(Node& node, MacroAssembler::RelationalCondition condition, MacroAssembler::DoubleCondition doubleCondition, S_DFGOperation_EJJ operation)
3155 {
3156     if (compilePeepHoleBranch(node, condition, doubleCondition, operation))
3157         return true;
3158
3159     if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2()))) {
3160         compileIntegerCompare(node, condition);
3161         return false;
3162     }
3163     
3164     if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2()))) {
3165         compileDoubleCompare(node, doubleCondition);
3166         return false;
3167     }
3168     
3169     if (node.op() == CompareEq) {
3170         if (at(node.child1()).shouldSpeculateString() || at(node.child2()).shouldSpeculateString()) {
3171             nonSpeculativeNonPeepholeCompare(node, condition, operation);
3172             return false;
3173         }
3174         
3175         if (at(node.child1()).shouldSpeculateNonStringCell() && at(node.child2()).shouldSpeculateNonStringCellOrOther()) {
3176             compileObjectToObjectOrOtherEquality(node.child1(), node.child2());
3177             return false;
3178         }
3179         
3180         if (at(node.child1()).shouldSpeculateNonStringCellOrOther() && at(node.child2()).shouldSpeculateNonStringCell()) {
3181             compileObjectToObjectOrOtherEquality(node.child2(), node.child1());
3182             return false;
3183         }
3184
3185         if (at(node.child1()).shouldSpeculateNonStringCell() && at(node.child2()).shouldSpeculateNonStringCell()) {
3186             compileObjectEquality(node);
3187             return false;
3188         }
3189     }
3190     
3191     nonSpeculativeNonPeepholeCompare(node, condition, operation);
3192     return false;
3193 }
3194
3195 bool SpeculativeJIT::compileStrictEqForConstant(Node& node, Edge value, JSValue constant)
3196 {
3197     JSValueOperand op1(this, value);
3198     
3199     unsigned branchIndexInBlock = detectPeepHoleBranch();
3200     if (branchIndexInBlock != UINT_MAX) {
3201         NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
3202         Node& branchNode = at(branchNodeIndex);
3203         BlockIndex taken = branchNode.takenBlockIndex();
3204         BlockIndex notTaken = branchNode.notTakenBlockIndex();
3205         MacroAssembler::RelationalCondition condition = MacroAssembler::Equal;
3206         
3207         // The branch instruction will branch to the taken block.
3208         // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
3209         if (taken == nextBlock()) {
3210             condition = MacroAssembler::NotEqual;
3211             BlockIndex tmp = taken;
3212             taken = notTaken;
3213             notTaken = tmp;
3214         }
3215
3216 #if USE(JSVALUE64)
3217         branch64(condition, op1.gpr(), MacroAssembler::TrustedImm64(JSValue::encode(constant)), taken);
3218 #else
3219         GPRReg payloadGPR = op1.payloadGPR();
3220         GPRReg tagGPR = op1.tagGPR();
3221         if (condition == MacroAssembler::Equal) {
3222             // Drop down if not equal, go elsewhere if equal.
3223             MacroAssembler::Jump notEqual = m_jit.branch32(MacroAssembler::NotEqual, tagGPR, MacroAssembler::Imm32(constant.tag()));
3224             branch32(MacroAssembler::Equal, payloadGPR, MacroAssembler::Imm32(constant.payload()), taken);
3225             notEqual.link(&m_jit);
3226         } else {
3227             // Drop down if equal, go elsehwere if not equal.
3228             branch32(MacroAssembler::NotEqual, tagGPR, MacroAssembler::Imm32(constant.tag()), taken);
3229             branch32(MacroAssembler::NotEqual, payloadGPR, MacroAssembler::Imm32(constant.payload()), taken);
3230         }
3231 #endif
3232         
3233         jump(notTaken);
3234         
3235         use(node.child1());
3236         use(node.child2());
3237         m_indexInBlock = branchIndexInBlock;
3238         m_compileIndex = branchNodeIndex;
3239         return true;
3240     }
3241     
3242     GPRTemporary result(this);
3243     
3244 #if USE(JSVALUE64)
3245     GPRReg op1GPR = op1.gpr();
3246     GPRReg resultGPR = result.gpr();
3247     m_jit.move(MacroAssembler::TrustedImm64(ValueFalse), resultGPR);
3248     MacroAssembler::Jump notEqual = m_jit.branch64(MacroAssembler::NotEqual, op1GPR, MacroAssembler::TrustedImm64(JSValue::encode(constant)));
3249     m_jit.or32(MacroAssembler::TrustedImm32(1), resultGPR);
3250     notEqual.link(&m_jit);
3251     jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean);
3252 #else
3253     GPRReg op1PayloadGPR = op1.payloadGPR();
3254     GPRReg op1TagGPR = op1.tagGPR();
3255     GPRReg resultGPR = result.gpr();
3256     m_jit.move(TrustedImm32(0), resultGPR);
3257     MacroAssembler::JumpList notEqual;
3258     notEqual.append(m_jit.branch32(MacroAssembler::NotEqual, op1TagGPR, MacroAssembler::Imm32(constant.tag())));
3259     notEqual.append(m_jit.branch32(MacroAssembler::NotEqual, op1PayloadGPR, MacroAssembler::Imm32(constant.payload())));
3260     m_jit.move(TrustedImm32(1), resultGPR);
3261     notEqual.link(&m_jit);
3262     booleanResult(resultGPR, m_compileIndex);
3263 #endif
3264     
3265     return false;
3266 }
3267
3268 bool SpeculativeJIT::compileStrictEq(Node& node)
3269 {
3270     // 1) If either operand is a constant and that constant is not a double, integer,
3271     //    or string, then do a JSValue comparison.
3272     
3273     if (isJSConstant(node.child1().index())) {
3274         JSValue value = valueOfJSConstant(node.child1().index());
3275         if (!value.isNumber() && !value.isString())
3276             return compileStrictEqForConstant(node, node.child2(), value);
3277     }
3278     
3279     if (isJSConstant(node.child2().index())) {
3280         JSValue value = valueOfJSConstant(node.child2().index());
3281         if (!value.isNumber() && !value.isString())
3282             return compileStrictEqForConstant(node, node.child1(), value);
3283     }
3284     
3285     // 2) If the operands are predicted integer, do an integer comparison.
3286     
3287     if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2()))) {
3288         unsigned branchIndexInBlock = detectPeepHoleBranch();
3289         if (branchIndexInBlock != UINT_MAX) {
3290             NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
3291             compilePeepHoleIntegerBranch(node, branchNodeIndex, MacroAssembler::Equal);
3292             use(node.child1());
3293             use(node.child2());
3294             m_indexInBlock = branchIndexInBlock;
3295             m_compileIndex = branchNodeIndex;
3296             return true;
3297         }
3298         compileIntegerCompare(node, MacroAssembler::Equal);
3299         return false;
3300     }
3301     
3302     // 3) If the operands are predicted double, do a double comparison.
3303     
3304     if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2()))) {
3305         unsigned branchIndexInBlock = detectPeepHoleBranch();
3306         if (branchIndexInBlock != UINT_MAX) {
3307             NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
3308             compilePeepHoleDoubleBranch(node, branchNodeIndex, MacroAssembler::DoubleEqual);
3309             use(node.child1());
3310             use(node.child2());
3311             m_indexInBlock = branchIndexInBlock;
3312             m_compileIndex = branchNodeIndex;
3313             return true;
3314         }
3315         compileDoubleCompare(node, MacroAssembler::DoubleEqual);
3316         return false;
3317     }
3318     
3319     if (at(node.child1()).shouldSpeculateString() || at(node.child2()).shouldSpeculateString())
3320         return nonSpeculativeStrictEq(node);
3321     if (at(node.child1()).shouldSpeculateNonStringCell() && at(node.child2()).shouldSpeculateNonStringCell()) {
3322         unsigned branchIndexInBlock = detectPeepHoleBranch();
3323         if (branchIndexInBlock != UINT_MAX) {
3324             NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
3325             compilePeepHoleObjectEquality(node, branchNodeIndex);
3326             use(node.child1());
3327             use(node.child2());
3328             m_indexInBlock = branchIndexInBlock;
3329             m_compileIndex = branchNodeIndex;
3330             return true;
3331         }
3332         compileObjectEquality(node);
3333         return false;
3334     }
3335     
3336     // 5) Fall back to non-speculative strict equality.
3337     
3338     return nonSpeculativeStrictEq(node);
3339 }
3340
3341 void SpeculativeJIT::compileGetIndexedPropertyStorage(Node& node)
3342 {
3343     SpeculateCellOperand base(this, node.child1());
3344     GPRReg baseReg = base.gpr();
3345     
3346     GPRTemporary storage(this);
3347     GPRReg storageReg = storage.gpr();
3348     
3349     const TypedArrayDescriptor* descriptor = typedArrayDescriptor(node.arrayMode());
3350     
3351     switch (node.arrayMode().type()) {
3352     case Array::String:
3353         m_jit.loadPtr(MacroAssembler::Address(baseReg, JSString::offsetOfValue()), storageReg);
3354         
3355         // Speculate that we're not accessing a rope
3356         speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTest32(MacroAssembler::Zero, storageReg));
3357
3358         m_jit.loadPtr(MacroAssembler::Address(storageReg, StringImpl::dataOffset()), storageReg);
3359         break;
3360         
3361     default:
3362         ASSERT(descriptor);
3363         m_jit.loadPtr(MacroAssembler::Address(baseReg, descriptor->m_storageOffset), storageReg);
3364         break;
3365     }
3366     
3367     storageResult(storageReg, m_compileIndex);
3368 }
3369
3370 void SpeculativeJIT::compileGetByValOnArguments(Node& node)
3371 {
3372     SpeculateCellOperand base(this, node.child1());
3373     SpeculateStrictInt32Operand property(this, node.child2());
3374     GPRTemporary result(this);
3375 #if USE(JSVALUE32_64)
3376     GPRTemporary resultTag(this);
3377 #endif
3378     GPRTemporary scratch(this);
3379     
3380     GPRReg baseReg = base.gpr();
3381     GPRReg propertyReg = property.gpr();
3382     GPRReg resultReg = result.gpr();
3383 #if USE(JSVALUE32_64)
3384     GPRReg resultTagReg = resultTag.gpr();
3385 #endif
3386     GPRReg scratchReg = scratch.gpr();
3387     
3388     if (!m_compileOkay)
3389         return;
3390   
3391     ASSERT(ArrayMode(Array::Arguments).alreadyChecked(m_jit.graph(), node, m_state.forNode(node.child1())));
3392     
3393     // Two really lame checks.
3394     speculationCheck(
3395         Uncountable, JSValueSource(), NoNode,
3396         m_jit.branchPtr(
3397             MacroAssembler::AboveOrEqual, propertyReg,
3398             MacroAssembler::Address(baseReg, OBJECT_OFFSETOF(Arguments, m_numArguments))));
3399     speculationCheck(
3400         Uncountable, JSValueSource(), NoNode,
3401         m_jit.branchTestPtr(
3402             MacroAssembler::NonZero,
3403             MacroAssembler::Address(
3404                 baseReg, OBJECT_OFFSETOF(Arguments, m_slowArguments))));
3405     
3406     m_jit.move(propertyReg, resultReg);
3407     m_jit.neg32(resultReg);
3408     m_jit.signExtend32ToPtr(resultReg, resultReg);
3409     m_jit.loadPtr(
3410         MacroAssembler::Address(baseReg, OBJECT_OFFSETOF(Arguments, m_registers)),
3411         scratchReg);
3412     
3413 #if USE(JSVALUE32_64)
3414     m_jit.load32(
3415         MacroAssembler::BaseIndex(
3416             scratchReg, resultReg, MacroAssembler::TimesEight,
3417             CallFrame::thisArgumentOffset() * sizeof(Register) - sizeof(Register) +
3418             OBJECT_OFFSETOF(JSValue, u.asBits.tag)),
3419         resultTagReg);
3420     m_jit.load32(
3421         MacroAssembler::BaseIndex(
3422             scratchReg, resultReg, MacroAssembler::TimesEight,
3423             CallFrame::thisArgumentOffset() * sizeof(Register) - sizeof(Register) +
3424             OBJECT_OFFSETOF(JSValue, u.asBits.payload)),
3425         resultReg);
3426     jsValueResult(resultTagReg, resultReg, m_compileIndex);
3427 #else
3428     m_jit.load64(
3429         MacroAssembler::BaseIndex(
3430             scratchReg, resultReg, MacroAssembler::TimesEight,
3431             CallFrame::thisArgumentOffset() * sizeof(Register) - sizeof(Register)),
3432         resultReg);
3433     jsValueResult(resultReg, m_compileIndex);
3434 #endif
3435 }
3436
3437 void SpeculativeJIT::compileGetArgumentsLength(Node& node)
3438 {
3439     SpeculateCellOperand base(this, node.child1());
3440     GPRTemporary result(this, base);
3441     
3442     GPRReg baseReg = base.gpr();
3443     GPRReg resultReg = result.gpr();
3444     
3445     if (!m_compileOkay)
3446         return;
3447     
3448     ASSERT(ArrayMode(Array::Arguments).alreadyChecked(m_jit.graph(), node, m_state.forNode(node.child1())));
3449     
3450     speculationCheck(
3451         Uncountable, JSValueSource(), NoNode,
3452         m_jit.branchTest8(
3453             MacroAssembler::NonZero,
3454             MacroAssembler::Address(baseReg, OBJECT_OFFSETOF(Arguments, m_overrodeLength))));
3455     
3456     m_jit.load32(
3457         MacroAssembler::Address(baseReg, OBJECT_OFFSETOF(Arguments, m_numArguments)),
3458         resultReg);
3459     integerResult(resultReg, m_compileIndex);
3460 }
3461
3462 void SpeculativeJIT::compileGetArrayLength(Node& node)
3463 {
3464     const TypedArrayDescriptor* descriptor = typedArrayDescriptor(node.arrayMode());
3465
3466     switch (node.arrayMode().type()) {
3467     case Array::Int32:
3468     case Array::Double:
3469     case Array::Contiguous: {
3470         StorageOperand storage(this, node.child2());
3471         GPRTemporary result(this, storage);
3472         GPRReg storageReg = storage.gpr();
3473         GPRReg resultReg = result.gpr();
3474         m_jit.load32(MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()), resultReg);
3475             
3476         integerResult(resultReg, m_compileIndex);
3477         break;
3478     }
3479     case Array::ArrayStorage:
3480     case Array::SlowPutArrayStorage: {
3481         StorageOperand storage(this, node.child2());
3482         GPRTemporary result(this, storage);
3483         GPRReg storageReg = storage.gpr();
3484         GPRReg resultReg = result.gpr();
3485         m_jit.load32(MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()), resultReg);
3486             
3487         speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, resultReg, MacroAssembler::TrustedImm32(0)));
3488             
3489         integerResult(resultReg, m_compileIndex);
3490         break;
3491     }
3492     case Array::String: {
3493         SpeculateCellOperand base(this, node.child1());
3494         GPRTemporary result(this, base);
3495         GPRReg baseGPR = base.gpr();
3496         GPRReg resultGPR = result.gpr();
3497         m_jit.load32(MacroAssembler::Address(baseGPR, JSString::offsetOfLength()), resultGPR);
3498         integerResult(resultGPR, m_compileIndex);
3499         break;
3500     }
3501     case Array::Arguments: {
3502         compileGetArgumentsLength(node);
3503         break;
3504     }
3505     default:
3506         SpeculateCellOperand base(this, node.child1());
3507         GPRTemporary result(this, base);
3508         GPRReg baseGPR = base.gpr();
3509         GPRReg resultGPR = result.gpr();
3510         ASSERT(descriptor);
3511         m_jit.load32(MacroAssembler::Address(baseGPR, descriptor->m_lengthOffset), resultGPR);
3512         integerResult(resultGPR, m_compileIndex);
3513         break;
3514     }
3515 }
3516
3517 void SpeculativeJIT::compileNewFunctionNoCheck(Node& node)
3518 {
3519     GPRResult result(this);
3520     GPRReg resultGPR = result.gpr();
3521     flushRegisters();
3522     callOperation(
3523         operationNewFunction, resultGPR, m_jit.codeBlock()->functionDecl(node.functionDeclIndex()));
3524     cellResult(resultGPR, m_compileIndex);
3525 }
3526
3527 void SpeculativeJIT::compileNewFunctionExpression(Node& node)
3528 {
3529     GPRResult result(this);
3530     GPRReg resultGPR = result.gpr();
3531     flushRegisters();
3532     callOperation(
3533         operationNewFunctionExpression,
3534         resultGPR,
3535         m_jit.codeBlock()->functionExpr(node.functionExprIndex()));
3536     cellResult(resultGPR, m_compileIndex);
3537 }
3538
3539 bool SpeculativeJIT::compileRegExpExec(Node& node)
3540 {
3541     unsigned branchIndexInBlock = detectPeepHoleBranch();
3542     if (branchIndexInBlock == UINT_MAX)
3543         return false;
3544     NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
3545     ASSERT(node.adjustedRefCount() == 1);
3546
3547     Node& branchNode = at(branchNodeIndex);
3548     BlockIndex taken = branchNode.takenBlockIndex();
3549     BlockIndex notTaken = branchNode.notTakenBlockIndex();
3550     
3551     bool invert = false;
3552     if (taken == nextBlock()) {
3553         invert = true;
3554         BlockIndex tmp = taken;
3555         taken = notTaken;
3556         notTaken = tmp;
3557     }
3558
3559     SpeculateCellOperand base(this, node.child1());
3560     SpeculateCellOperand argument(this, node.child2());
3561     GPRReg baseGPR = base.gpr();
3562     GPRReg argumentGPR = argument.gpr();
3563     
3564     flushRegisters();
3565     GPRResult result(this);
3566     callOperation(operationRegExpTest, result.gpr(), baseGPR, argumentGPR);
3567
3568     branchTest32(invert ? JITCompiler::Zero : JITCompiler::NonZero, result.gpr(), taken);
3569     jump(notTaken);
3570
3571     use(node.child1());
3572     use(node.child2());
3573     m_indexInBlock = branchIndexInBlock;
3574     m_compileIndex = branchNodeIndex;
3575
3576     return true;
3577 }
3578
3579 void SpeculativeJIT::compileAllocatePropertyStorage(Node& node)
3580 {
3581     if (hasIndexingHeader(node.structureTransitionData().previousStructure->indexingType())) {
3582         SpeculateCellOperand base(this, node.child1());
3583         
3584         GPRReg baseGPR = base.gpr();
3585         
3586         flushRegisters();
3587
3588         GPRResult result(this);
3589         callOperation(operationReallocateButterflyToHavePropertyStorageWithInitialCapacity, result.gpr(), baseGPR);
3590         
3591         storageResult(result.gpr(), m_compileIndex);
3592         return;
3593     }
3594     
3595     SpeculateCellOperand base(this, node.child1());
3596     GPRTemporary scratch(this);
3597         
3598     GPRReg baseGPR = base.gpr();
3599     GPRReg scratchGPR = scratch.gpr();
3600         
3601     ASSERT(!node.structureTransitionData().previousStructure->outOfLineCapacity());
3602     ASSERT(initialOutOfLineCapacity == node.structureTransitionData().newStructure->outOfLineCapacity());
3603     
3604     JITCompiler::Jump slowPath =
3605         emitAllocateBasicStorage(
3606             TrustedImm32(initialOutOfLineCapacity * sizeof(JSValue)), scratchGPR);
3607
3608     m_jit.addPtr(JITCompiler::TrustedImm32(sizeof(JSValue)), scratchGPR);
3609         
3610     addSlowPathGenerator(
3611         slowPathCall(slowPath, this, operationAllocatePropertyStorageWithInitialCapacity, scratchGPR));
3612         
3613     m_jit.storePtr(scratchGPR, JITCompiler::Address(baseGPR, JSObject::butterflyOffset()));
3614         
3615     storageResult(scratchGPR, m_compileIndex);
3616 }
3617
3618 void SpeculativeJIT::compileReallocatePropertyStorage(Node& node)
3619 {
3620     size_t oldSize = node.structureTransitionData().previousStructure->outOfLineCapacity() * sizeof(JSValue);
3621     size_t newSize = oldSize * outOfLineGrowthFactor;
3622     ASSERT(newSize == node.structureTransitionData().newStructure->outOfLineCapacity() * sizeof(JSValue));
3623
3624     if (hasIndexingHeader(node.structureTransitionData().previousStructure->indexingType())) {
3625         SpeculateCellOperand base(this, node.child1());
3626         
3627         GPRReg baseGPR = base.gpr();
3628         
3629         flushRegisters();
3630
3631         GPRResult result(this);
3632         callOperation(operationReallocateButterflyToGrowPropertyStorage, result.gpr(), baseGPR, newSize / sizeof(JSValue));
3633         
3634         storageResult(result.gpr(), m_compileIndex);
3635         return;
3636     }
3637     
3638     SpeculateCellOperand base(this, node.child1());
3639     StorageOperand oldStorage(this, node.child2());
3640     GPRTemporary scratch1(this);
3641     GPRTemporary scratch2(this);
3642         
3643     GPRReg baseGPR = base.gpr();
3644     GPRReg oldStorageGPR = oldStorage.gpr();
3645     GPRReg scratchGPR1 = scratch1.gpr();
3646     GPRReg scratchGPR2 = scratch2.gpr();
3647         
3648     JITCompiler::Jump slowPath =
3649         emitAllocateBasicStorage(TrustedImm32(newSize), scratchGPR2);
3650
3651     m_jit.addPtr(JITCompiler::TrustedImm32(sizeof(JSValue)), scratchGPR2);
3652         
3653     addSlowPathGenerator(
3654         slowPathCall(slowPath, this, operationAllocatePropertyStorage, scratchGPR2, newSize / sizeof(JSValue)));
3655     // We have scratchGPR2 = new storage, scratchGPR1 = scratch
3656     for (ptrdiff_t offset = 0; offset < static_cast<ptrdiff_t>(oldSize); offset += sizeof(void*)) {
3657         m_jit.loadPtr(JITCompiler::Address(oldStorageGPR, -(offset + sizeof(JSValue) + sizeof(void*))), scratchGPR1);
3658         m_jit.storePtr(scratchGPR1, JITCompiler::Address(scratchGPR2, -(offset + sizeof(JSValue) + sizeof(void*))));
3659     }
3660     m_jit.storePtr(scratchGPR2, JITCompiler::Address(baseGPR, JSObject::butterflyOffset()));
3661     
3662     storageResult(scratchGPR2, m_compileIndex);
3663 }
3664
3665 GPRReg SpeculativeJIT::temporaryRegisterForPutByVal(GPRTemporary& temporary, ArrayMode arrayMode)
3666 {
3667     if (!putByValWillNeedExtraRegister(arrayMode))
3668         return InvalidGPRReg;
3669     
3670     GPRTemporary realTemporary(this);
3671     temporary.adopt(realTemporary);
3672     return temporary.gpr();
3673 }
3674
3675 } } // namespace JSC::DFG
3676
3677 #endif