fourthTier: Landing the initial FTL logic in a single commit to avoid spurious
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGSpeculativeJIT.cpp
1 /*
2  * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "DFGSpeculativeJIT.h"
28
29 #if ENABLE(DFG_JIT)
30
31 #include "Arguments.h"
32 #include "DFGArrayifySlowPathGenerator.h"
33 #include "DFGCallArrayAllocatorSlowPathGenerator.h"
34 #include "DFGSlowPathGenerator.h"
35 #include "JSCJSValueInlines.h"
36 #include "LinkBuffer.h"
37
38 namespace JSC { namespace DFG {
39
40 SpeculativeJIT::SpeculativeJIT(JITCompiler& jit)
41     : m_compileOkay(true)
42     , m_jit(jit)
43     , m_currentNode(0)
44     , m_indexInBlock(0)
45     , m_generationInfo(m_jit.codeBlock()->m_numCalleeRegisters)
46     , m_blockHeads(jit.graph().m_blocks.size())
47     , m_arguments(jit.codeBlock()->numParameters())
48     , m_variables(jit.graph().m_localVars)
49     , m_lastSetOperand(std::numeric_limits<int>::max())
50     , m_state(m_jit.graph())
51     , m_stream(&jit.jitCode()->variableEventStream)
52     , m_minifiedGraph(&jit.jitCode()->minifiedDFG)
53     , m_isCheckingArgumentTypes(false)
54 {
55 }
56
57 SpeculativeJIT::~SpeculativeJIT()
58 {
59 }
60
61 void SpeculativeJIT::emitAllocateJSArray(GPRReg resultGPR, Structure* structure, GPRReg storageGPR, unsigned numElements)
62 {
63     ASSERT(hasUndecided(structure->indexingType()) || hasInt32(structure->indexingType()) || hasDouble(structure->indexingType()) || hasContiguous(structure->indexingType()));
64     
65     GPRTemporary scratch(this);
66     GPRTemporary scratch2(this);
67     GPRReg scratchGPR = scratch.gpr();
68     GPRReg scratch2GPR = scratch2.gpr();
69     
70     unsigned vectorLength = std::max(BASE_VECTOR_LEN, numElements);
71     
72     JITCompiler::JumpList slowCases;
73     
74     slowCases.append(
75         emitAllocateBasicStorage(TrustedImm32(vectorLength * sizeof(JSValue) + sizeof(IndexingHeader)), storageGPR));
76     m_jit.subPtr(TrustedImm32(vectorLength * sizeof(JSValue)), storageGPR);
77     emitAllocateJSObject<JSArray>(resultGPR, TrustedImmPtr(structure), storageGPR, scratchGPR, scratch2GPR, slowCases);
78     
79     m_jit.store32(TrustedImm32(numElements), MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
80     m_jit.store32(TrustedImm32(vectorLength), MacroAssembler::Address(storageGPR, Butterfly::offsetOfVectorLength()));
81     
82     if (hasDouble(structure->indexingType()) && numElements < vectorLength) {
83 #if USE(JSVALUE64)
84         m_jit.move(TrustedImm64(bitwise_cast<int64_t>(QNaN)), scratchGPR);
85         for (unsigned i = numElements; i < vectorLength; ++i)
86             m_jit.store64(scratchGPR, MacroAssembler::Address(storageGPR, sizeof(double) * i));
87 #else
88         EncodedValueDescriptor value;
89         value.asInt64 = JSValue::encode(JSValue(JSValue::EncodeAsDouble, QNaN));
90         for (unsigned i = numElements; i < vectorLength; ++i) {
91             m_jit.store32(TrustedImm32(value.asBits.tag), MacroAssembler::Address(storageGPR, sizeof(double) * i + OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
92             m_jit.store32(TrustedImm32(value.asBits.payload), MacroAssembler::Address(storageGPR, sizeof(double) * i + OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
93         }
94 #endif
95     }
96     
97     // I want a slow path that also loads out the storage pointer, and that's
98     // what this custom CallArrayAllocatorSlowPathGenerator gives me. It's a lot
99     // of work for a very small piece of functionality. :-/
100     addSlowPathGenerator(adoptPtr(
101         new CallArrayAllocatorSlowPathGenerator(
102             slowCases, this, operationNewArrayWithSize, resultGPR, storageGPR,
103             structure, numElements)));
104 }
105
106 void SpeculativeJIT::backwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, MacroAssembler::Jump jumpToFail)
107 {
108     if (!m_compileOkay)
109         return;
110     ASSERT(m_isCheckingArgumentTypes || m_canExit);
111     m_jit.appendExitInfo(jumpToFail);
112     m_jit.jitCode()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(node), this, m_stream->size()));
113 }
114
115 void SpeculativeJIT::backwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, const MacroAssembler::JumpList& jumpsToFail)
116 {
117     if (!m_compileOkay)
118         return;
119     ASSERT(m_isCheckingArgumentTypes || m_canExit);
120     m_jit.appendExitInfo(jumpsToFail);
121     m_jit.jitCode()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(node), this, m_stream->size()));
122 }
123
124 void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, MacroAssembler::Jump jumpToFail)
125 {
126     if (!m_compileOkay)
127         return;
128     backwardSpeculationCheck(kind, jsValueSource, node, jumpToFail);
129     if (m_speculationDirection == ForwardSpeculation)
130         convertLastOSRExitToForward();
131 }
132
133 void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail)
134 {
135     ASSERT(m_isCheckingArgumentTypes || m_canExit);
136     speculationCheck(kind, jsValueSource, nodeUse.node(), jumpToFail);
137 }
138
139 OSRExitJumpPlaceholder SpeculativeJIT::backwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node)
140 {
141     if (!m_compileOkay)
142         return OSRExitJumpPlaceholder();
143     ASSERT(m_isCheckingArgumentTypes || m_canExit);
144     unsigned index = m_jit.jitCode()->osrExit.size();
145     m_jit.appendExitInfo();
146     m_jit.jitCode()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(node), this, m_stream->size()));
147     return OSRExitJumpPlaceholder(index);
148 }
149
150 OSRExitJumpPlaceholder SpeculativeJIT::backwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse)
151 {
152     ASSERT(m_isCheckingArgumentTypes || m_canExit);
153     return backwardSpeculationCheck(kind, jsValueSource, nodeUse.node());
154 }
155
156 void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, const MacroAssembler::JumpList& jumpsToFail)
157 {
158     if (!m_compileOkay)
159         return;
160     backwardSpeculationCheck(kind, jsValueSource, node, jumpsToFail);
161     if (m_speculationDirection == ForwardSpeculation)
162         convertLastOSRExitToForward();
163 }
164
165 void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, const MacroAssembler::JumpList& jumpsToFail)
166 {
167     ASSERT(m_isCheckingArgumentTypes || m_canExit);
168     speculationCheck(kind, jsValueSource, nodeUse.node(), jumpsToFail);
169 }
170
171 void SpeculativeJIT::backwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery)
172 {
173     if (!m_compileOkay)
174         return;
175     ASSERT(m_isCheckingArgumentTypes || m_canExit);
176     unsigned recoveryIndex = m_jit.jitCode()->appendSpeculationRecovery(recovery);
177     m_jit.appendExitInfo(jumpToFail);
178     m_jit.jitCode()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(node), this, m_stream->size(), recoveryIndex));
179 }
180
181 void SpeculativeJIT::backwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery)
182 {
183     ASSERT(m_isCheckingArgumentTypes || m_canExit);
184     backwardSpeculationCheck(kind, jsValueSource, nodeUse.node(), jumpToFail, recovery);
185 }
186
187 void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery)
188 {
189     if (!m_compileOkay)
190         return;
191     backwardSpeculationCheck(kind, jsValueSource, node, jumpToFail, recovery);
192     if (m_speculationDirection == ForwardSpeculation)
193         convertLastOSRExitToForward();
194 }
195
196 void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge edge, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery)
197 {
198     speculationCheck(kind, jsValueSource, edge.node(), jumpToFail, recovery);
199 }
200
201 JumpReplacementWatchpoint* SpeculativeJIT::speculationWatchpoint(ExitKind kind, JSValueSource jsValueSource, Node* node)
202 {
203     if (!m_compileOkay)
204         return 0;
205     ASSERT(m_isCheckingArgumentTypes || m_canExit);
206     m_jit.appendExitInfo(JITCompiler::JumpList());
207     OSRExit& exit = m_jit.jitCode()->osrExit[
208         m_jit.jitCode()->appendOSRExit(OSRExit(
209             kind, jsValueSource,
210             m_jit.graph().methodOfGettingAValueProfileFor(node),
211             this, m_stream->size()))];
212     exit.m_watchpointIndex = m_jit.jitCode()->appendWatchpoint(
213         JumpReplacementWatchpoint(m_jit.watchpointLabel()));
214     if (m_speculationDirection == ForwardSpeculation)
215         convertLastOSRExitToForward();
216     return &m_jit.jitCode()->watchpoints[exit.m_watchpointIndex];
217 }
218
219 JumpReplacementWatchpoint* SpeculativeJIT::speculationWatchpoint(ExitKind kind)
220 {
221     return speculationWatchpoint(kind, JSValueSource(), 0);
222 }
223
224 void SpeculativeJIT::convertLastOSRExitToForward(const ValueRecovery& valueRecovery)
225 {
226     m_jit.jitCode()->lastOSRExit().convertToForward(
227         m_jit.graph().m_blocks[m_block].get(), m_currentNode, m_indexInBlock, valueRecovery);
228 }
229
230 void SpeculativeJIT::forwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, MacroAssembler::Jump jumpToFail, const ValueRecovery& valueRecovery)
231 {
232     ASSERT(m_isCheckingArgumentTypes || m_canExit);
233     backwardSpeculationCheck(kind, jsValueSource, node, jumpToFail);
234     convertLastOSRExitToForward(valueRecovery);
235 }
236
237 void SpeculativeJIT::forwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, const MacroAssembler::JumpList& jumpsToFail, const ValueRecovery& valueRecovery)
238 {
239     ASSERT(m_isCheckingArgumentTypes || m_canExit);
240     backwardSpeculationCheck(kind, jsValueSource, node, jumpsToFail);
241     convertLastOSRExitToForward(valueRecovery);
242 }
243
244 void SpeculativeJIT::terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, Node* node)
245 {
246     ASSERT(m_isCheckingArgumentTypes || m_canExit);
247 #if DFG_ENABLE(DEBUG_VERBOSE)
248     dataLogF("SpeculativeJIT was terminated.\n");
249 #endif
250     if (!m_compileOkay)
251         return;
252     speculationCheck(kind, jsValueRegs, node, m_jit.jump());
253     m_compileOkay = false;
254 }
255
256 void SpeculativeJIT::terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, Edge nodeUse)
257 {
258     ASSERT(m_isCheckingArgumentTypes || m_canExit);
259     terminateSpeculativeExecution(kind, jsValueRegs, nodeUse.node());
260 }
261
262 void SpeculativeJIT::backwardTypeCheck(JSValueSource source, Edge edge, SpeculatedType typesPassedThrough, MacroAssembler::Jump jumpToFail)
263 {
264     ASSERT(needsTypeCheck(edge, typesPassedThrough));
265     m_state.forNode(edge).filter(typesPassedThrough);
266     backwardSpeculationCheck(BadType, source, edge.node(), jumpToFail);
267 }
268
269 void SpeculativeJIT::typeCheck(JSValueSource source, Edge edge, SpeculatedType typesPassedThrough, MacroAssembler::Jump jumpToFail)
270 {
271     backwardTypeCheck(source, edge, typesPassedThrough, jumpToFail);
272     if (m_speculationDirection == ForwardSpeculation)
273         convertLastOSRExitToForward();
274 }
275
276 void SpeculativeJIT::forwardTypeCheck(JSValueSource source, Edge edge, SpeculatedType typesPassedThrough, MacroAssembler::Jump jumpToFail, const ValueRecovery& valueRecovery)
277 {
278     backwardTypeCheck(source, edge, typesPassedThrough, jumpToFail);
279     convertLastOSRExitToForward(valueRecovery);
280 }
281
282 void SpeculativeJIT::addSlowPathGenerator(PassOwnPtr<SlowPathGenerator> slowPathGenerator)
283 {
284     m_slowPathGenerators.append(slowPathGenerator);
285 }
286
287 void SpeculativeJIT::runSlowPathGenerators()
288 {
289 #if DFG_ENABLE(DEBUG_VERBOSE)
290     dataLogF("Running %lu slow path generators.\n", m_slowPathGenerators.size());
291 #endif
292     for (unsigned i = 0; i < m_slowPathGenerators.size(); ++i)
293         m_slowPathGenerators[i]->generate(this);
294 }
295
296 // On Windows we need to wrap fmod; on other platforms we can call it directly.
297 // On ARMv7 we assert that all function pointers have to low bit set (point to thumb code).
298 #if CALLING_CONVENTION_IS_STDCALL || CPU(ARM_THUMB2)
299 static double DFG_OPERATION fmodAsDFGOperation(double x, double y)
300 {
301     return fmod(x, y);
302 }
303 #else
304 #define fmodAsDFGOperation fmod
305 #endif
306
307 void SpeculativeJIT::clearGenerationInfo()
308 {
309     for (unsigned i = 0; i < m_generationInfo.size(); ++i)
310         m_generationInfo[i] = GenerationInfo();
311     m_gprs = RegisterBank<GPRInfo>();
312     m_fprs = RegisterBank<FPRInfo>();
313 }
314
315 SilentRegisterSavePlan SpeculativeJIT::silentSavePlanForGPR(VirtualRegister spillMe, GPRReg source)
316 {
317     GenerationInfo& info = m_generationInfo[spillMe];
318     Node* node = info.node();
319     DataFormat registerFormat = info.registerFormat();
320     ASSERT(registerFormat != DataFormatNone);
321     ASSERT(registerFormat != DataFormatDouble);
322         
323     SilentSpillAction spillAction;
324     SilentFillAction fillAction;
325         
326     if (!info.needsSpill())
327         spillAction = DoNothingForSpill;
328     else {
329 #if USE(JSVALUE64)
330         ASSERT(info.gpr() == source);
331         if (registerFormat == DataFormatInteger)
332             spillAction = Store32Payload;
333         else if (registerFormat == DataFormatCell || registerFormat == DataFormatStorage)
334             spillAction = StorePtr;
335         else {
336             ASSERT(registerFormat & DataFormatJS);
337             spillAction = Store64;
338         }
339 #elif USE(JSVALUE32_64)
340         if (registerFormat & DataFormatJS) {
341             ASSERT(info.tagGPR() == source || info.payloadGPR() == source);
342             spillAction = source == info.tagGPR() ? Store32Tag : Store32Payload;
343         } else {
344             ASSERT(info.gpr() == source);
345             spillAction = Store32Payload;
346         }
347 #endif
348     }
349         
350     if (registerFormat == DataFormatInteger) {
351         ASSERT(info.gpr() == source);
352         ASSERT(isJSInteger(info.registerFormat()));
353         if (node->hasConstant()) {
354             ASSERT(isInt32Constant(node));
355             fillAction = SetInt32Constant;
356         } else
357             fillAction = Load32Payload;
358     } else if (registerFormat == DataFormatBoolean) {
359 #if USE(JSVALUE64)
360         RELEASE_ASSERT_NOT_REACHED();
361         fillAction = DoNothingForFill;
362 #elif USE(JSVALUE32_64)
363         ASSERT(info.gpr() == source);
364         if (node->hasConstant()) {
365             ASSERT(isBooleanConstant(node));
366             fillAction = SetBooleanConstant;
367         } else
368             fillAction = Load32Payload;
369 #endif
370     } else if (registerFormat == DataFormatCell) {
371         ASSERT(info.gpr() == source);
372         if (node->hasConstant()) {
373             JSValue value = valueOfJSConstant(node);
374             ASSERT_UNUSED(value, value.isCell());
375             fillAction = SetCellConstant;
376         } else {
377 #if USE(JSVALUE64)
378             fillAction = LoadPtr;
379 #else
380             fillAction = Load32Payload;
381 #endif
382         }
383     } else if (registerFormat == DataFormatStorage) {
384         ASSERT(info.gpr() == source);
385         fillAction = LoadPtr;
386     } else {
387         ASSERT(registerFormat & DataFormatJS);
388 #if USE(JSVALUE64)
389         ASSERT(info.gpr() == source);
390         if (node->hasConstant()) {
391             if (valueOfJSConstant(node).isCell())
392                 fillAction = SetTrustedJSConstant;
393             else
394                 fillAction = SetJSConstant;
395         } else if (info.spillFormat() == DataFormatInteger) {
396             ASSERT(registerFormat == DataFormatJSInteger);
397             fillAction = Load32PayloadBoxInt;
398         } else if (info.spillFormat() == DataFormatDouble) {
399             ASSERT(registerFormat == DataFormatJSDouble);
400             fillAction = LoadDoubleBoxDouble;
401         } else
402             fillAction = Load64;
403 #else
404         ASSERT(info.tagGPR() == source || info.payloadGPR() == source);
405         if (node->hasConstant())
406             fillAction = info.tagGPR() == source ? SetJSConstantTag : SetJSConstantPayload;
407         else if (info.payloadGPR() == source)
408             fillAction = Load32Payload;
409         else { // Fill the Tag
410             switch (info.spillFormat()) {
411             case DataFormatInteger:
412                 ASSERT(registerFormat == DataFormatJSInteger);
413                 fillAction = SetInt32Tag;
414                 break;
415             case DataFormatCell:
416                 ASSERT(registerFormat == DataFormatJSCell);
417                 fillAction = SetCellTag;
418                 break;
419             case DataFormatBoolean:
420                 ASSERT(registerFormat == DataFormatJSBoolean);
421                 fillAction = SetBooleanTag;
422                 break;
423             default:
424                 fillAction = Load32Tag;
425                 break;
426             }
427         }
428 #endif
429     }
430         
431     return SilentRegisterSavePlan(spillAction, fillAction, node, source);
432 }
433     
434 SilentRegisterSavePlan SpeculativeJIT::silentSavePlanForFPR(VirtualRegister spillMe, FPRReg source)
435 {
436     GenerationInfo& info = m_generationInfo[spillMe];
437     Node* node = info.node();
438     ASSERT(info.registerFormat() == DataFormatDouble);
439
440     SilentSpillAction spillAction;
441     SilentFillAction fillAction;
442         
443     if (!info.needsSpill())
444         spillAction = DoNothingForSpill;
445     else {
446         ASSERT(!node->hasConstant());
447         ASSERT(info.spillFormat() == DataFormatNone);
448         ASSERT(info.fpr() == source);
449         spillAction = StoreDouble;
450     }
451         
452 #if USE(JSVALUE64)
453     if (node->hasConstant()) {
454         ASSERT(isNumberConstant(node));
455         fillAction = SetDoubleConstant;
456     } else if (info.spillFormat() != DataFormatNone && info.spillFormat() != DataFormatDouble) {
457         // it was already spilled previously and not as a double, which means we need unboxing.
458         ASSERT(info.spillFormat() & DataFormatJS);
459         fillAction = LoadJSUnboxDouble;
460     } else
461         fillAction = LoadDouble;
462 #elif USE(JSVALUE32_64)
463     ASSERT(info.registerFormat() == DataFormatDouble || info.registerFormat() == DataFormatJSDouble);
464     if (node->hasConstant()) {
465         ASSERT(isNumberConstant(node));
466         fillAction = SetDoubleConstant;
467     } else
468         fillAction = LoadDouble;
469 #endif
470
471     return SilentRegisterSavePlan(spillAction, fillAction, node, source);
472 }
473     
474 void SpeculativeJIT::silentSpill(const SilentRegisterSavePlan& plan)
475 {
476     switch (plan.spillAction()) {
477     case DoNothingForSpill:
478         break;
479     case Store32Tag:
480         m_jit.store32(plan.gpr(), JITCompiler::tagFor(plan.node()->virtualRegister()));
481         break;
482     case Store32Payload:
483         m_jit.store32(plan.gpr(), JITCompiler::payloadFor(plan.node()->virtualRegister()));
484         break;
485     case StorePtr:
486         m_jit.storePtr(plan.gpr(), JITCompiler::addressFor(plan.node()->virtualRegister()));
487         break;
488 #if USE(JSVALUE64)
489     case Store64:
490         m_jit.store64(plan.gpr(), JITCompiler::addressFor(plan.node()->virtualRegister()));
491         break;
492 #endif
493     case StoreDouble:
494         m_jit.storeDouble(plan.fpr(), JITCompiler::addressFor(plan.node()->virtualRegister()));
495         break;
496     default:
497         RELEASE_ASSERT_NOT_REACHED();
498     }
499 }
500     
501 void SpeculativeJIT::silentFill(const SilentRegisterSavePlan& plan, GPRReg canTrample)
502 {
503 #if USE(JSVALUE32_64)
504     UNUSED_PARAM(canTrample);
505 #endif
506     switch (plan.fillAction()) {
507     case DoNothingForFill:
508         break;
509     case SetInt32Constant:
510         m_jit.move(Imm32(valueOfInt32Constant(plan.node())), plan.gpr());
511         break;
512     case SetBooleanConstant:
513         m_jit.move(TrustedImm32(valueOfBooleanConstant(plan.node())), plan.gpr());
514         break;
515     case SetCellConstant:
516         m_jit.move(TrustedImmPtr(valueOfJSConstant(plan.node()).asCell()), plan.gpr());
517         break;
518 #if USE(JSVALUE64)
519     case SetTrustedJSConstant:
520         m_jit.move(valueOfJSConstantAsImm64(plan.node()).asTrustedImm64(), plan.gpr());
521         break;
522     case SetJSConstant:
523         m_jit.move(valueOfJSConstantAsImm64(plan.node()), plan.gpr());
524         break;
525     case SetDoubleConstant:
526         m_jit.move(Imm64(reinterpretDoubleToInt64(valueOfNumberConstant(plan.node()))), canTrample);
527         m_jit.move64ToDouble(canTrample, plan.fpr());
528         break;
529     case Load32PayloadBoxInt:
530         m_jit.load32(JITCompiler::payloadFor(plan.node()->virtualRegister()), plan.gpr());
531         m_jit.or64(GPRInfo::tagTypeNumberRegister, plan.gpr());
532         break;
533     case LoadDoubleBoxDouble:
534         m_jit.load64(JITCompiler::addressFor(plan.node()->virtualRegister()), plan.gpr());
535         m_jit.sub64(GPRInfo::tagTypeNumberRegister, plan.gpr());
536         break;
537     case LoadJSUnboxDouble:
538         m_jit.load64(JITCompiler::addressFor(plan.node()->virtualRegister()), canTrample);
539         unboxDouble(canTrample, plan.fpr());
540         break;
541 #else
542     case SetJSConstantTag:
543         m_jit.move(Imm32(valueOfJSConstant(plan.node()).tag()), plan.gpr());
544         break;
545     case SetJSConstantPayload:
546         m_jit.move(Imm32(valueOfJSConstant(plan.node()).payload()), plan.gpr());
547         break;
548     case SetInt32Tag:
549         m_jit.move(TrustedImm32(JSValue::Int32Tag), plan.gpr());
550         break;
551     case SetCellTag:
552         m_jit.move(TrustedImm32(JSValue::CellTag), plan.gpr());
553         break;
554     case SetBooleanTag:
555         m_jit.move(TrustedImm32(JSValue::BooleanTag), plan.gpr());
556         break;
557     case SetDoubleConstant:
558         m_jit.loadDouble(addressOfDoubleConstant(plan.node()), plan.fpr());
559         break;
560 #endif
561     case Load32Tag:
562         m_jit.load32(JITCompiler::tagFor(plan.node()->virtualRegister()), plan.gpr());
563         break;
564     case Load32Payload:
565         m_jit.load32(JITCompiler::payloadFor(plan.node()->virtualRegister()), plan.gpr());
566         break;
567     case LoadPtr:
568         m_jit.loadPtr(JITCompiler::addressFor(plan.node()->virtualRegister()), plan.gpr());
569         break;
570 #if USE(JSVALUE64)
571     case Load64:
572         m_jit.load64(JITCompiler::addressFor(plan.node()->virtualRegister()), plan.gpr());
573         break;
574 #endif
575     case LoadDouble:
576         m_jit.loadDouble(JITCompiler::addressFor(plan.node()->virtualRegister()), plan.fpr());
577         break;
578     default:
579         RELEASE_ASSERT_NOT_REACHED();
580     }
581 }
582     
583 const TypedArrayDescriptor* SpeculativeJIT::typedArrayDescriptor(ArrayMode arrayMode)
584 {
585     switch (arrayMode.type()) {
586     case Array::Int8Array:
587         return &m_jit.vm()->int8ArrayDescriptor();
588     case Array::Int16Array:
589         return &m_jit.vm()->int16ArrayDescriptor();
590     case Array::Int32Array:
591         return &m_jit.vm()->int32ArrayDescriptor();
592     case Array::Uint8Array:
593         return &m_jit.vm()->uint8ArrayDescriptor();
594     case Array::Uint8ClampedArray:
595         return &m_jit.vm()->uint8ClampedArrayDescriptor();
596     case Array::Uint16Array:
597         return &m_jit.vm()->uint16ArrayDescriptor();
598     case Array::Uint32Array:
599         return &m_jit.vm()->uint32ArrayDescriptor();
600     case Array::Float32Array:
601         return &m_jit.vm()->float32ArrayDescriptor();
602     case Array::Float64Array:
603         return &m_jit.vm()->float64ArrayDescriptor();
604     default:
605         return 0;
606     }
607 }
608
609 JITCompiler::Jump SpeculativeJIT::jumpSlowForUnwantedArrayMode(GPRReg tempGPR, ArrayMode arrayMode, IndexingType shape)
610 {
611     switch (arrayMode.arrayClass()) {
612     case Array::OriginalArray: {
613         CRASH();
614         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.
615         return result;
616     }
617         
618     case Array::Array:
619         m_jit.and32(TrustedImm32(IsArray | IndexingShapeMask), tempGPR);
620         return m_jit.branch32(
621             MacroAssembler::NotEqual, tempGPR, TrustedImm32(IsArray | shape));
622         
623     default:
624         m_jit.and32(TrustedImm32(IndexingShapeMask), tempGPR);
625         return m_jit.branch32(MacroAssembler::NotEqual, tempGPR, TrustedImm32(shape));
626     }
627 }
628
629 JITCompiler::JumpList SpeculativeJIT::jumpSlowForUnwantedArrayMode(GPRReg tempGPR, ArrayMode arrayMode)
630 {
631     JITCompiler::JumpList result;
632     
633     switch (arrayMode.type()) {
634     case Array::Int32:
635         return jumpSlowForUnwantedArrayMode(tempGPR, arrayMode, Int32Shape);
636
637     case Array::Double:
638         return jumpSlowForUnwantedArrayMode(tempGPR, arrayMode, DoubleShape);
639
640     case Array::Contiguous:
641         return jumpSlowForUnwantedArrayMode(tempGPR, arrayMode, ContiguousShape);
642
643     case Array::ArrayStorage:
644     case Array::SlowPutArrayStorage: {
645         ASSERT(!arrayMode.isJSArrayWithOriginalStructure());
646         
647         if (arrayMode.isJSArray()) {
648             if (arrayMode.isSlowPut()) {
649                 result.append(
650                     m_jit.branchTest32(
651                         MacroAssembler::Zero, tempGPR, MacroAssembler::TrustedImm32(IsArray)));
652                 m_jit.and32(TrustedImm32(IndexingShapeMask), tempGPR);
653                 m_jit.sub32(TrustedImm32(ArrayStorageShape), tempGPR);
654                 result.append(
655                     m_jit.branch32(
656                         MacroAssembler::Above, tempGPR,
657                         TrustedImm32(SlowPutArrayStorageShape - ArrayStorageShape)));
658                 break;
659             }
660             m_jit.and32(TrustedImm32(IsArray | IndexingShapeMask), tempGPR);
661             result.append(
662                 m_jit.branch32(MacroAssembler::NotEqual, tempGPR, TrustedImm32(IsArray | ArrayStorageShape)));
663             break;
664         }
665         m_jit.and32(TrustedImm32(IndexingShapeMask), tempGPR);
666         if (arrayMode.isSlowPut()) {
667             m_jit.sub32(TrustedImm32(ArrayStorageShape), tempGPR);
668             result.append(
669                 m_jit.branch32(
670                     MacroAssembler::Above, tempGPR,
671                     TrustedImm32(SlowPutArrayStorageShape - ArrayStorageShape)));
672             break;
673         }
674         result.append(
675             m_jit.branch32(MacroAssembler::NotEqual, tempGPR, TrustedImm32(ArrayStorageShape)));
676         break;
677     }
678     default:
679         CRASH();
680         break;
681     }
682     
683     return result;
684 }
685
686 void SpeculativeJIT::checkArray(Node* node)
687 {
688     ASSERT(node->arrayMode().isSpecific());
689     ASSERT(!node->arrayMode().doesConversion());
690     
691     SpeculateCellOperand base(this, node->child1());
692     GPRReg baseReg = base.gpr();
693     
694     const TypedArrayDescriptor* result = typedArrayDescriptor(node->arrayMode());
695     
696     if (node->arrayMode().alreadyChecked(m_jit.graph(), node, m_state.forNode(node->child1()))) {
697         noResult(m_currentNode);
698         return;
699     }
700     
701     const ClassInfo* expectedClassInfo = 0;
702     
703     switch (node->arrayMode().type()) {
704     case Array::String:
705         expectedClassInfo = &JSString::s_info;
706         break;
707     case Array::Int32:
708     case Array::Double:
709     case Array::Contiguous:
710     case Array::ArrayStorage:
711     case Array::SlowPutArrayStorage: {
712         GPRTemporary temp(this);
713         GPRReg tempGPR = temp.gpr();
714         m_jit.loadPtr(
715             MacroAssembler::Address(baseReg, JSCell::structureOffset()), tempGPR);
716         m_jit.load8(MacroAssembler::Address(tempGPR, Structure::indexingTypeOffset()), tempGPR);
717         speculationCheck(
718             BadIndexingType, JSValueSource::unboxedCell(baseReg), 0,
719             jumpSlowForUnwantedArrayMode(tempGPR, node->arrayMode()));
720         
721         noResult(m_currentNode);
722         return;
723     }
724     case Array::Arguments:
725         expectedClassInfo = &Arguments::s_info;
726         break;
727     case Array::Int8Array:
728     case Array::Int16Array:
729     case Array::Int32Array:
730     case Array::Uint8Array:
731     case Array::Uint8ClampedArray:
732     case Array::Uint16Array:
733     case Array::Uint32Array:
734     case Array::Float32Array:
735     case Array::Float64Array:
736         expectedClassInfo = result->m_classInfo;
737         break;
738     default:
739         RELEASE_ASSERT_NOT_REACHED();
740         break;
741     }
742     
743     GPRTemporary temp(this);
744     m_jit.loadPtr(
745         MacroAssembler::Address(baseReg, JSCell::structureOffset()), temp.gpr());
746     speculationCheck(
747         Uncountable, JSValueRegs(), 0,
748         m_jit.branchPtr(
749             MacroAssembler::NotEqual,
750             MacroAssembler::Address(temp.gpr(), Structure::classInfoOffset()),
751             MacroAssembler::TrustedImmPtr(expectedClassInfo)));
752     
753     noResult(m_currentNode);
754 }
755
756 void SpeculativeJIT::arrayify(Node* node, GPRReg baseReg, GPRReg propertyReg)
757 {
758     ASSERT(node->arrayMode().doesConversion());
759     
760     GPRTemporary temp(this);
761     GPRTemporary structure;
762     GPRReg tempGPR = temp.gpr();
763     GPRReg structureGPR = InvalidGPRReg;
764     
765     if (node->op() != ArrayifyToStructure) {
766         GPRTemporary realStructure(this);
767         structure.adopt(realStructure);
768         structureGPR = structure.gpr();
769     }
770         
771     // We can skip all that comes next if we already have array storage.
772     MacroAssembler::JumpList slowPath;
773     
774     if (node->op() == ArrayifyToStructure) {
775         slowPath.append(m_jit.branchWeakPtr(
776             JITCompiler::NotEqual,
777             JITCompiler::Address(baseReg, JSCell::structureOffset()),
778             node->structure()));
779     } else {
780         m_jit.loadPtr(
781             MacroAssembler::Address(baseReg, JSCell::structureOffset()), structureGPR);
782         
783         m_jit.load8(
784             MacroAssembler::Address(structureGPR, Structure::indexingTypeOffset()), tempGPR);
785         
786         slowPath.append(jumpSlowForUnwantedArrayMode(tempGPR, node->arrayMode()));
787     }
788     
789     addSlowPathGenerator(adoptPtr(new ArrayifySlowPathGenerator(
790         slowPath, this, node, baseReg, propertyReg, tempGPR, structureGPR)));
791     
792     noResult(m_currentNode);
793 }
794
795 void SpeculativeJIT::arrayify(Node* node)
796 {
797     ASSERT(node->arrayMode().isSpecific());
798     
799     SpeculateCellOperand base(this, node->child1());
800     
801     if (!node->child2()) {
802         arrayify(node, base.gpr(), InvalidGPRReg);
803         return;
804     }
805     
806     SpeculateIntegerOperand property(this, node->child2());
807     
808     arrayify(node, base.gpr(), property.gpr());
809 }
810
811 GPRReg SpeculativeJIT::fillStorage(Edge edge)
812 {
813     VirtualRegister virtualRegister = edge->virtualRegister();
814     GenerationInfo& info = m_generationInfo[virtualRegister];
815     
816     switch (info.registerFormat()) {
817     case DataFormatNone: {
818         if (info.spillFormat() == DataFormatStorage) {
819             GPRReg gpr = allocate();
820             m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
821             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr);
822             info.fillStorage(*m_stream, gpr);
823             return gpr;
824         }
825         
826         // Must be a cell; fill it as a cell and then return the pointer.
827         return fillSpeculateCell(edge);
828     }
829         
830     case DataFormatStorage: {
831         GPRReg gpr = info.gpr();
832         m_gprs.lock(gpr);
833         return gpr;
834     }
835         
836     default:
837         return fillSpeculateCell(edge);
838     }
839 }
840
841 void SpeculativeJIT::useChildren(Node* node)
842 {
843     if (node->flags() & NodeHasVarArgs) {
844         for (unsigned childIdx = node->firstChild(); childIdx < node->firstChild() + node->numChildren(); childIdx++) {
845             if (!!m_jit.graph().m_varArgChildren[childIdx])
846                 use(m_jit.graph().m_varArgChildren[childIdx]);
847         }
848     } else {
849         Edge child1 = node->child1();
850         if (!child1) {
851             ASSERT(!node->child2() && !node->child3());
852             return;
853         }
854         use(child1);
855         
856         Edge child2 = node->child2();
857         if (!child2) {
858             ASSERT(!node->child3());
859             return;
860         }
861         use(child2);
862         
863         Edge child3 = node->child3();
864         if (!child3)
865             return;
866         use(child3);
867     }
868 }
869
870 void SpeculativeJIT::writeBarrier(MacroAssembler& jit, GPRReg owner, GPRReg scratch1, GPRReg scratch2, WriteBarrierUseKind useKind)
871 {
872     UNUSED_PARAM(jit);
873     UNUSED_PARAM(owner);
874     UNUSED_PARAM(scratch1);
875     UNUSED_PARAM(scratch2);
876     UNUSED_PARAM(useKind);
877     ASSERT(owner != scratch1);
878     ASSERT(owner != scratch2);
879     ASSERT(scratch1 != scratch2);
880
881 #if ENABLE(WRITE_BARRIER_PROFILING)
882     JITCompiler::emitCount(jit, WriteBarrierCounters::jitCounterFor(useKind));
883 #endif
884 }
885
886 void SpeculativeJIT::writeBarrier(GPRReg ownerGPR, GPRReg valueGPR, Edge valueUse, WriteBarrierUseKind useKind, GPRReg scratch1, GPRReg scratch2)
887 {
888     UNUSED_PARAM(ownerGPR);
889     UNUSED_PARAM(valueGPR);
890     UNUSED_PARAM(scratch1);
891     UNUSED_PARAM(scratch2);
892     UNUSED_PARAM(useKind);
893
894     if (isKnownNotCell(valueUse.node()))
895         return;
896
897 #if ENABLE(WRITE_BARRIER_PROFILING)
898     JITCompiler::emitCount(m_jit, WriteBarrierCounters::jitCounterFor(useKind));
899 #endif
900 }
901
902 void SpeculativeJIT::writeBarrier(GPRReg ownerGPR, JSCell* value, WriteBarrierUseKind useKind, GPRReg scratch1, GPRReg scratch2)
903 {
904     UNUSED_PARAM(ownerGPR);
905     UNUSED_PARAM(value);
906     UNUSED_PARAM(scratch1);
907     UNUSED_PARAM(scratch2);
908     UNUSED_PARAM(useKind);
909     
910     if (Heap::isMarked(value))
911         return;
912
913 #if ENABLE(WRITE_BARRIER_PROFILING)
914     JITCompiler::emitCount(m_jit, WriteBarrierCounters::jitCounterFor(useKind));
915 #endif
916 }
917
918 void SpeculativeJIT::writeBarrier(JSCell* owner, GPRReg valueGPR, Edge valueUse, WriteBarrierUseKind useKind, GPRReg scratch)
919 {
920     UNUSED_PARAM(owner);
921     UNUSED_PARAM(valueGPR);
922     UNUSED_PARAM(scratch);
923     UNUSED_PARAM(useKind);
924
925     if (isKnownNotCell(valueUse.node()))
926         return;
927
928 #if ENABLE(WRITE_BARRIER_PROFILING)
929     JITCompiler::emitCount(m_jit, WriteBarrierCounters::jitCounterFor(useKind));
930 #endif
931 }
932
933 bool SpeculativeJIT::nonSpeculativeCompare(Node* node, MacroAssembler::RelationalCondition cond, S_DFGOperation_EJJ helperFunction)
934 {
935     unsigned branchIndexInBlock = detectPeepHoleBranch();
936     if (branchIndexInBlock != UINT_MAX) {
937         Node* branchNode = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
938
939         ASSERT(node->adjustedRefCount() == 1);
940         
941         nonSpeculativePeepholeBranch(node, branchNode, cond, helperFunction);
942     
943         m_indexInBlock = branchIndexInBlock;
944         m_currentNode = branchNode;
945         
946         return true;
947     }
948     
949     nonSpeculativeNonPeepholeCompare(node, cond, helperFunction);
950     
951     return false;
952 }
953
954 bool SpeculativeJIT::nonSpeculativeStrictEq(Node* node, bool invert)
955 {
956     unsigned branchIndexInBlock = detectPeepHoleBranch();
957     if (branchIndexInBlock != UINT_MAX) {
958         Node* branchNode = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
959
960         ASSERT(node->adjustedRefCount() == 1);
961         
962         nonSpeculativePeepholeStrictEq(node, branchNode, invert);
963     
964         m_indexInBlock = branchIndexInBlock;
965         m_currentNode = branchNode;
966         
967         return true;
968     }
969     
970     nonSpeculativeNonPeepholeStrictEq(node, invert);
971     
972     return false;
973 }
974
975 #ifndef NDEBUG
976 static const char* dataFormatString(DataFormat format)
977 {
978     // These values correspond to the DataFormat enum.
979     const char* strings[] = {
980         "[  ]",
981         "[ i]",
982         "[ d]",
983         "[ c]",
984         "Err!",
985         "Err!",
986         "Err!",
987         "Err!",
988         "[J ]",
989         "[Ji]",
990         "[Jd]",
991         "[Jc]",
992         "Err!",
993         "Err!",
994         "Err!",
995         "Err!",
996     };
997     return strings[format];
998 }
999
1000 void SpeculativeJIT::dump(const char* label)
1001 {
1002     if (label)
1003         dataLogF("<%s>\n", label);
1004
1005     dataLogF("  gprs:\n");
1006     m_gprs.dump();
1007     dataLogF("  fprs:\n");
1008     m_fprs.dump();
1009     dataLogF("  VirtualRegisters:\n");
1010     for (unsigned i = 0; i < m_generationInfo.size(); ++i) {
1011         GenerationInfo& info = m_generationInfo[i];
1012         if (info.alive())
1013             dataLogF("    % 3d:%s%s", i, dataFormatString(info.registerFormat()), dataFormatString(info.spillFormat()));
1014         else
1015             dataLogF("    % 3d:[__][__]", i);
1016         if (info.registerFormat() == DataFormatDouble)
1017             dataLogF(":fpr%d\n", info.fpr());
1018         else if (info.registerFormat() != DataFormatNone
1019 #if USE(JSVALUE32_64)
1020             && !(info.registerFormat() & DataFormatJS)
1021 #endif
1022             ) {
1023             ASSERT(info.gpr() != InvalidGPRReg);
1024             dataLogF(":%s\n", GPRInfo::debugName(info.gpr()));
1025         } else
1026             dataLogF("\n");
1027     }
1028     if (label)
1029         dataLogF("</%s>\n", label);
1030 }
1031 #endif
1032
1033
1034 #if DFG_ENABLE(CONSISTENCY_CHECK)
1035 void SpeculativeJIT::checkConsistency()
1036 {
1037     bool failed = false;
1038
1039     for (gpr_iterator iter = m_gprs.begin(); iter != m_gprs.end(); ++iter) {
1040         if (iter.isLocked()) {
1041             dataLogF("DFG_CONSISTENCY_CHECK failed: gpr %s is locked.\n", iter.debugName());
1042             failed = true;
1043         }
1044     }
1045     for (fpr_iterator iter = m_fprs.begin(); iter != m_fprs.end(); ++iter) {
1046         if (iter.isLocked()) {
1047             dataLogF("DFG_CONSISTENCY_CHECK failed: fpr %s is locked.\n", iter.debugName());
1048             failed = true;
1049         }
1050     }
1051
1052     for (unsigned i = 0; i < m_generationInfo.size(); ++i) {
1053         VirtualRegister virtualRegister = (VirtualRegister)i;
1054         GenerationInfo& info = m_generationInfo[virtualRegister];
1055         if (!info.alive())
1056             continue;
1057         switch (info.registerFormat()) {
1058         case DataFormatNone:
1059             break;
1060         case DataFormatJS:
1061         case DataFormatJSInteger:
1062         case DataFormatJSDouble:
1063         case DataFormatJSCell:
1064         case DataFormatJSBoolean:
1065 #if USE(JSVALUE32_64)
1066             break;
1067 #endif
1068         case DataFormatInteger:
1069         case DataFormatCell:
1070         case DataFormatBoolean:
1071         case DataFormatStorage: {
1072             GPRReg gpr = info.gpr();
1073             ASSERT(gpr != InvalidGPRReg);
1074             if (m_gprs.name(gpr) != virtualRegister) {
1075                 dataLogF("DFG_CONSISTENCY_CHECK failed: name mismatch for virtual register %d (gpr %s).\n", virtualRegister, GPRInfo::debugName(gpr));
1076                 failed = true;
1077             }
1078             break;
1079         }
1080         case DataFormatDouble: {
1081             FPRReg fpr = info.fpr();
1082             ASSERT(fpr != InvalidFPRReg);
1083             if (m_fprs.name(fpr) != virtualRegister) {
1084                 dataLogF("DFG_CONSISTENCY_CHECK failed: name mismatch for virtual register %d (fpr %s).\n", virtualRegister, FPRInfo::debugName(fpr));
1085                 failed = true;
1086             }
1087             break;
1088         }
1089         case DataFormatOSRMarker:
1090         case DataFormatDead:
1091         case DataFormatArguments:
1092             RELEASE_ASSERT_NOT_REACHED();
1093             break;
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             dataLogF("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                 dataLogF("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                 dataLogF("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             dataLogF("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.node()))
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.node()))
1177         m_gpr = m_jit->reuse(op1.gpr());
1178     else if (m_jit->canReuse(op2.node()))
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.node()))
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.node()))
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.node()))
1209         m_gpr = m_jit->reuse(op1.gpr());
1210     else if (m_jit->canReuse(op2.node()))
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.node()))
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.node()))
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.node()))
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.node()))
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.node()))
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, SpeculateDoubleOperand& op1)
1288     : m_jit(jit)
1289     , m_fpr(InvalidFPRReg)
1290 {
1291     if (m_jit->canReuse(op1.node()))
1292         m_fpr = m_jit->reuse(op1.fpr());
1293     else
1294         m_fpr = m_jit->fprAllocate();
1295 }
1296
1297 FPRTemporary::FPRTemporary(SpeculativeJIT* jit, SpeculateDoubleOperand& op1, SpeculateDoubleOperand& op2)
1298     : m_jit(jit)
1299     , m_fpr(InvalidFPRReg)
1300 {
1301     if (m_jit->canReuse(op1.node()))
1302         m_fpr = m_jit->reuse(op1.fpr());
1303     else if (m_jit->canReuse(op2.node()))
1304         m_fpr = m_jit->reuse(op2.fpr());
1305     else
1306         m_fpr = m_jit->fprAllocate();
1307 }
1308
1309 #if USE(JSVALUE32_64)
1310 FPRTemporary::FPRTemporary(SpeculativeJIT* jit, JSValueOperand& op1)
1311     : m_jit(jit)
1312     , m_fpr(InvalidFPRReg)
1313 {
1314     if (op1.isDouble() && m_jit->canReuse(op1.node()))
1315         m_fpr = m_jit->reuse(op1.fpr());
1316     else
1317         m_fpr = m_jit->fprAllocate();
1318 }
1319 #endif
1320
1321 void SpeculativeJIT::compilePeepHoleDoubleBranch(Node* node, Node* branchNode, JITCompiler::DoubleCondition condition)
1322 {
1323     BlockIndex taken = branchNode->takenBlockIndex();
1324     BlockIndex notTaken = branchNode->notTakenBlockIndex();
1325     
1326     SpeculateDoubleOperand op1(this, node->child1());
1327     SpeculateDoubleOperand op2(this, node->child2());
1328     
1329     branchDouble(condition, op1.fpr(), op2.fpr(), taken);
1330     jump(notTaken);
1331 }
1332
1333 void SpeculativeJIT::compilePeepHoleObjectEquality(Node* node, Node* branchNode)
1334 {
1335     BlockIndex taken = branchNode->takenBlockIndex();
1336     BlockIndex notTaken = branchNode->notTakenBlockIndex();
1337
1338     MacroAssembler::RelationalCondition condition = MacroAssembler::Equal;
1339     
1340     if (taken == nextBlock()) {
1341         condition = MacroAssembler::NotEqual;
1342         BlockIndex tmp = taken;
1343         taken = notTaken;
1344         notTaken = tmp;
1345     }
1346
1347     SpeculateCellOperand op1(this, node->child1());
1348     SpeculateCellOperand op2(this, node->child2());
1349     
1350     GPRReg op1GPR = op1.gpr();
1351     GPRReg op2GPR = op2.gpr();
1352     
1353     if (m_jit.graph().globalObjectFor(node->codeOrigin)->masqueradesAsUndefinedWatchpoint()->isStillValid()) {
1354         m_jit.graph().globalObjectFor(node->codeOrigin)->masqueradesAsUndefinedWatchpoint()->add(speculationWatchpoint());
1355         if (m_state.forNode(node->child1()).m_type & ~SpecObject) {
1356             speculationCheck(
1357                 BadType, JSValueSource::unboxedCell(op1GPR), node->child1(), 
1358                 m_jit.branchPtr(
1359                     MacroAssembler::Equal, 
1360                     MacroAssembler::Address(op1GPR, JSCell::structureOffset()), 
1361                     MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1362         }
1363         if (m_state.forNode(node->child2()).m_type & ~SpecObject) {
1364             speculationCheck(
1365                 BadType, JSValueSource::unboxedCell(op2GPR), node->child2(),
1366                 m_jit.branchPtr(
1367                     MacroAssembler::Equal, 
1368                     MacroAssembler::Address(op2GPR, JSCell::structureOffset()), 
1369                     MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1370         }
1371     } else {
1372         GPRTemporary structure(this);
1373         GPRReg structureGPR = structure.gpr();
1374
1375         m_jit.loadPtr(MacroAssembler::Address(op1GPR, JSCell::structureOffset()), structureGPR);
1376         if (m_state.forNode(node->child1()).m_type & ~SpecObject) {
1377             speculationCheck(
1378                 BadType, JSValueSource::unboxedCell(op1GPR), node->child1(),
1379                 m_jit.branchPtr(
1380                     MacroAssembler::Equal, 
1381                     structureGPR, 
1382                     MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1383         }
1384         speculationCheck(BadType, JSValueSource::unboxedCell(op1GPR), node->child1(),
1385             m_jit.branchTest8(
1386                 MacroAssembler::NonZero, 
1387                 MacroAssembler::Address(structureGPR, Structure::typeInfoFlagsOffset()), 
1388                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1389
1390         m_jit.loadPtr(MacroAssembler::Address(op2GPR, JSCell::structureOffset()), structureGPR);
1391         if (m_state.forNode(node->child2()).m_type & ~SpecObject) {
1392             speculationCheck(
1393                 BadType, JSValueSource::unboxedCell(op2GPR), node->child2(),
1394                 m_jit.branchPtr(
1395                     MacroAssembler::Equal, 
1396                     structureGPR, 
1397                     MacroAssembler::TrustedImmPtr(m_jit.vm()->stringStructure.get())));
1398         }
1399         speculationCheck(BadType, JSValueSource::unboxedCell(op2GPR), node->child2(),
1400             m_jit.branchTest8(
1401                 MacroAssembler::NonZero, 
1402                 MacroAssembler::Address(structureGPR, Structure::typeInfoFlagsOffset()), 
1403                 MacroAssembler::TrustedImm32(MasqueradesAsUndefined)));
1404     }
1405
1406     branchPtr(condition, op1GPR, op2GPR, taken);
1407     jump(notTaken);
1408 }
1409
1410 void SpeculativeJIT::compilePeepHoleBooleanBranch(Node* node, Node* branchNode, JITCompiler::RelationalCondition condition)
1411 {
1412     BlockIndex taken = branchNode->takenBlockIndex();
1413     BlockIndex notTaken = branchNode->notTakenBlockIndex();
1414
1415     // The branch instruction will branch to the taken block.
1416     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
1417     if (taken == nextBlock()) {
1418         condition = JITCompiler::invert(condition);
1419         BlockIndex tmp = taken;
1420         taken = notTaken;
1421         notTaken = tmp;
1422     }
1423
1424     if (isBooleanConstant(node->child1().node())) {
1425         bool imm = valueOfBooleanConstant(node->child1().node());
1426         SpeculateBooleanOperand op2(this, node->child2());
1427         branch32(condition, JITCompiler::Imm32(static_cast<int32_t>(JSValue::encode(jsBoolean(imm)))), op2.gpr(), taken);
1428     } else if (isBooleanConstant(node->child2().node())) {
1429         SpeculateBooleanOperand op1(this, node->child1());
1430         bool imm = valueOfBooleanConstant(node->child2().node());
1431         branch32(condition, op1.gpr(), JITCompiler::Imm32(static_cast<int32_t>(JSValue::encode(jsBoolean(imm)))), taken);
1432     } else {
1433         SpeculateBooleanOperand op1(this, node->child1());
1434         SpeculateBooleanOperand op2(this, node->child2());
1435         branch32(condition, op1.gpr(), op2.gpr(), taken);
1436     }
1437
1438     jump(notTaken);
1439 }
1440
1441 void SpeculativeJIT::compilePeepHoleIntegerBranch(Node* node, Node* branchNode, JITCompiler::RelationalCondition condition)
1442 {
1443     BlockIndex taken = branchNode->takenBlockIndex();
1444     BlockIndex notTaken = branchNode->notTakenBlockIndex();
1445
1446     // The branch instruction will branch to the taken block.
1447     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
1448     if (taken == nextBlock()) {
1449         condition = JITCompiler::invert(condition);
1450         BlockIndex tmp = taken;
1451         taken = notTaken;
1452         notTaken = tmp;
1453     }
1454
1455     if (isInt32Constant(node->child1().node())) {
1456         int32_t imm = valueOfInt32Constant(node->child1().node());
1457         SpeculateIntegerOperand op2(this, node->child2());
1458         branch32(condition, JITCompiler::Imm32(imm), op2.gpr(), taken);
1459     } else if (isInt32Constant(node->child2().node())) {
1460         SpeculateIntegerOperand op1(this, node->child1());
1461         int32_t imm = valueOfInt32Constant(node->child2().node());
1462         branch32(condition, op1.gpr(), JITCompiler::Imm32(imm), taken);
1463     } else {
1464         SpeculateIntegerOperand op1(this, node->child1());
1465         SpeculateIntegerOperand op2(this, node->child2());
1466         branch32(condition, op1.gpr(), op2.gpr(), taken);
1467     }
1468
1469     jump(notTaken);
1470 }
1471
1472 // Returns true if the compare is fused with a subsequent branch.
1473 bool SpeculativeJIT::compilePeepHoleBranch(Node* node, MacroAssembler::RelationalCondition condition, MacroAssembler::DoubleCondition doubleCondition, S_DFGOperation_EJJ operation)
1474 {
1475     // Fused compare & branch.
1476     unsigned branchIndexInBlock = detectPeepHoleBranch();
1477     if (branchIndexInBlock != UINT_MAX) {
1478         Node* branchNode = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock);
1479
1480         // detectPeepHoleBranch currently only permits the branch to be the very next node,
1481         // so can be no intervening nodes to also reference the compare. 
1482         ASSERT(node->adjustedRefCount() == 1);
1483
1484         if (node->isBinaryUseKind(Int32Use))
1485             compilePeepHoleIntegerBranch(node, branchNode, condition);
1486         else if (node->isBinaryUseKind(NumberUse))
1487             compilePeepHoleDoubleBranch(node, branchNode, doubleCondition);
1488         else if (node->op() == CompareEq) {
1489             if (node->isBinaryUseKind(StringUse)) {
1490                 // Use non-peephole comparison, for now.
1491                 return false;
1492             }
1493             if (node->isBinaryUseKind(BooleanUse))
1494                 compilePeepHoleBooleanBranch(node, branchNode, condition);
1495             else if (node->isBinaryUseKind(ObjectUse))
1496                 compilePeepHoleObjectEquality(node, branchNode);
1497             else if (node->child1().useKind() == ObjectUse && node->child2().useKind() == ObjectOrOtherUse)
1498                 compilePeepHoleObjectToObjectOrOtherEquality(node->child1(), node->child2(), branchNode);
1499             else if (node->child1().useKind() == ObjectOrOtherUse && node->child2().useKind() == ObjectUse)
1500                 compilePeepHoleObjectToObjectOrOtherEquality(node->child2(), node->child1(), branchNode);
1501             else {
1502                 nonSpeculativePeepholeBranch(node, branchNode, condition, operation);
1503                 return true;
1504             }
1505         } else {
1506             nonSpeculativePeepholeBranch(node, branchNode, condition, operation);
1507             return true;
1508         }
1509
1510         use(node->child1());
1511         use(node->child2());
1512         m_indexInBlock = branchIndexInBlock;
1513         m_currentNode = branchNode;
1514         return true;
1515     }
1516     return false;
1517 }
1518
1519 void SpeculativeJIT::noticeOSRBirth(Node* node)
1520 {
1521     if (!node->hasVirtualRegister())
1522         return;
1523     
1524     VirtualRegister virtualRegister = node->virtualRegister();
1525     GenerationInfo& info = m_generationInfo[virtualRegister];
1526     
1527     info.noticeOSRBirth(*m_stream, node, virtualRegister);
1528 }
1529
1530 void SpeculativeJIT::compileMovHint(Node* node)
1531 {
1532     ASSERT(node->containsMovHint() && node->op() != ZombieHint);
1533     
1534     m_lastSetOperand = node->local();
1535
1536     Node* child = node->child1().node();
1537     noticeOSRBirth(child);
1538     
1539     if (child->op() == UInt32ToNumber)
1540         noticeOSRBirth(child->child1().node());
1541     
1542     m_stream->appendAndLog(VariableEvent::movHint(MinifiedID(child), node->local()));
1543 }
1544
1545 void SpeculativeJIT::compileMovHintAndCheck(Node* node)
1546 {
1547     compileMovHint(node);
1548     speculate(node, node->child1());
1549     noResult(node);
1550 }
1551
1552 void SpeculativeJIT::compileInlineStart(Node* node)
1553 {
1554     InlineCallFrame* inlineCallFrame = node->codeOrigin.inlineCallFrame;
1555     int argumentCountIncludingThis = inlineCallFrame->arguments.size();
1556     unsigned argumentPositionStart = node->argumentPositionStart();
1557     CodeBlock* codeBlock = baselineCodeBlockForInlineCallFrame(inlineCallFrame);
1558     for (int i = 0; i < argumentCountIncludingThis; ++i) {
1559         ValueRecovery recovery;
1560         if (codeBlock->isCaptured(argumentToOperand(i)))
1561             recovery = ValueRecovery::alreadyInJSStack();
1562         else {
1563             ArgumentPosition& argumentPosition =
1564                 m_jit.graph().m_argumentPositions[argumentPositionStart + i];
1565             ValueSource valueSource;
1566             if (!argumentPosition.shouldUnboxIfPossible())
1567                 valueSource = ValueSource(ValueInJSStack);
1568             else if (argumentPosition.shouldUseDoubleFormat())
1569                 valueSource = ValueSource(DoubleInJSStack);
1570             else if (isInt32Speculation(argumentPosition.prediction()))
1571                 valueSource = ValueSource(Int32InJSStack);
1572             else if (isCellSpeculation(argumentPosition.prediction()))
1573                 valueSource = ValueSource(CellInJSStack);
1574             else if (isBooleanSpeculation(argumentPosition.prediction()))
1575                 valueSource = ValueSource(BooleanInJSStack);
1576             else
1577                 valueSource = ValueSource(ValueInJSStack);
1578             recovery = computeValueRecoveryFor(valueSource);
1579         }
1580         // The recovery should refer either to something that has already been
1581         // stored into the stack at the right place, or to a constant,
1582         // since the Arguments code isn't smart enough to handle anything else.
1583         // The exception is the this argument, which we don't really need to be
1584         // able to recover.
1585 #if DFG_ENABLE(DEBUG_VERBOSE)
1586         dataLogF("\nRecovery for argument %d: ", i);
1587         recovery.dump(WTF::dataFile());
1588 #endif
1589         inlineCallFrame->arguments[i] = recovery;
1590     }
1591 }
1592
1593 void SpeculativeJIT::compile(BasicBlock& block)
1594 {
1595     ASSERT(m_compileOkay);
1596     
1597     if (!block.isReachable)
1598         return;
1599     
1600     if (!block.cfaHasVisited) {
1601         // Don't generate code for basic blocks that are unreachable according to CFA.
1602         // But to be sure that nobody has generated a jump to this block, drop in a
1603         // breakpoint here.
1604 #if !ASSERT_DISABLED
1605         m_jit.breakpoint();
1606 #endif
1607         return;
1608     }
1609
1610     m_blockHeads[m_block] = m_jit.label();
1611 #if DFG_ENABLE(JIT_BREAK_ON_EVERY_BLOCK)
1612     m_jit.breakpoint();
1613 #endif
1614     
1615 #if DFG_ENABLE(DEBUG_VERBOSE)
1616     dataLogF("Setting up state for block #%u: ", m_block);
1617 #endif
1618     
1619     m_stream->appendAndLog(VariableEvent::reset());
1620     
1621     m_jit.jitAssertHasValidCallFrame();
1622
1623     ASSERT(m_arguments.size() == block.variablesAtHead.numberOfArguments());
1624     for (size_t i = 0; i < m_arguments.size(); ++i) {
1625         ValueSource valueSource = ValueSource(ValueInJSStack);
1626         m_arguments[i] = valueSource;
1627         m_stream->appendAndLog(VariableEvent::setLocal(argumentToOperand(i), valueSource.dataFormat()));
1628     }
1629     
1630     m_state.reset();
1631     m_state.beginBasicBlock(&block);
1632     
1633     ASSERT(m_variables.size() == block.variablesAtHead.numberOfLocals());
1634     for (size_t i = 0; i < m_variables.size(); ++i) {
1635         Node* node = block.variablesAtHead.local(i);
1636         ValueSource valueSource;
1637         if (!node)
1638             valueSource = ValueSource(SourceIsDead);
1639         else if (node->variableAccessData()->isArgumentsAlias())
1640             valueSource = ValueSource(ArgumentsSource);
1641         else if (!node->refCount())
1642             valueSource = ValueSource(SourceIsDead);
1643         else if (!node->variableAccessData()->shouldUnboxIfPossible())
1644             valueSource = ValueSource(ValueInJSStack);
1645         else if (node->variableAccessData()->shouldUseDoubleFormat())
1646             valueSource = ValueSource(DoubleInJSStack);
1647         else
1648             valueSource = ValueSource::forSpeculation(node->variableAccessData()->argumentAwarePrediction());
1649         m_variables[i] = valueSource;
1650         // FIXME: Don't emit SetLocal(Dead). https://bugs.webkit.org/show_bug.cgi?id=108019
1651         m_stream->appendAndLog(VariableEvent::setLocal(i, valueSource.dataFormat()));
1652     }
1653     
1654     m_lastSetOperand = std::numeric_limits<int>::max();
1655     m_codeOriginForOSR = CodeOrigin();
1656     
1657     if (DFG_ENABLE_EDGE_CODE_VERIFICATION) {
1658         JITCompiler::Jump verificationSucceeded =
1659             m_jit.branch32(JITCompiler::Equal, GPRInfo::regT0, TrustedImm32(m_block));
1660         m_jit.breakpoint();
1661         verificationSucceeded.link(&m_jit);
1662     }
1663
1664 #if DFG_ENABLE(DEBUG_VERBOSE)
1665     dataLogF("\n");
1666 #endif
1667
1668     for (m_indexInBlock = 0; m_indexInBlock < block.size(); ++m_indexInBlock) {
1669         m_currentNode = block[m_indexInBlock];
1670 #if !ASSERT_DISABLED
1671         m_canExit = m_currentNode->canExit();
1672 #endif
1673         bool shouldExecuteEffects = m_state.startExecuting(m_currentNode);
1674         m_jit.setForNode(m_currentNode);
1675         m_codeOriginForOSR = m_currentNode->codeOrigin;
1676         if (!m_currentNode->shouldGenerate()) {
1677 #if DFG_ENABLE(DEBUG_VERBOSE)
1678             dataLogF("SpeculativeJIT skipping Node @%d (bc#%u) at JIT offset 0x%x     ", m_currentNode->index(), m_currentNode->codeOrigin.bytecodeIndex, m_jit.debugOffset());
1679 #endif
1680             switch (m_currentNode->op()) {
1681             case JSConstant:
1682                 m_minifiedGraph->append(MinifiedNode::fromNode(m_currentNode));
1683                 break;
1684                 
1685             case WeakJSConstant:
1686                 m_jit.addWeakReference(m_currentNode->weakConstant());
1687                 m_minifiedGraph->append(MinifiedNode::fromNode(m_currentNode));
1688                 break;
1689                 
1690             case SetLocal:
1691                 RELEASE_ASSERT_NOT_REACHED();
1692                 break;
1693                 
1694             case MovHint:
1695                 compileMovHint(m_currentNode);
1696                 break;
1697                 
1698             case ZombieHint: {
1699                 m_lastSetOperand = m_currentNode->local();
1700                 m_stream->appendAndLog(VariableEvent::setLocal(m_currentNode->local(), DataFormatDead));
1701                 break;
1702             }
1703
1704             default:
1705                 if (belongsInMinifiedGraph(m_currentNode->op()))
1706                     m_minifiedGraph->append(MinifiedNode::fromNode(m_currentNode));
1707                 break;
1708             }
1709         } else {
1710             
1711             if (verboseCompilationEnabled()) {
1712                 dataLogF(
1713                     "SpeculativeJIT generating Node @%d (bc#%u) at JIT offset 0x%x",
1714                     (int)m_currentNode->index(),
1715                     m_currentNode->codeOrigin.bytecodeIndex, m_jit.debugOffset());
1716 #if DFG_ENABLE(DEBUG_VERBOSE)
1717                 dataLog("   ");
1718 #else
1719                 dataLog("\n");
1720 #endif
1721             }
1722 #if DFG_ENABLE(JIT_BREAK_ON_EVERY_NODE)
1723             m_jit.breakpoint();
1724 #endif
1725 #if DFG_ENABLE(XOR_DEBUG_AID)
1726             m_jit.xorPtr(JITCompiler::TrustedImm32(m_currentNode->index()), GPRInfo::regT0);
1727             m_jit.xorPtr(JITCompiler::TrustedImm32(m_currentNode->index()), GPRInfo::regT0);
1728 #endif
1729             checkConsistency();
1730             
1731             m_speculationDirection = (m_currentNode->flags() & NodeExitsForward) ? ForwardSpeculation : BackwardSpeculation;
1732             
1733             compile(m_currentNode);
1734             if (!m_compileOkay) {
1735                 m_compileOkay = true;
1736                 clearGenerationInfo();
1737                 return;
1738             }
1739             
1740             if (belongsInMinifiedGraph(m_currentNode->op())) {
1741                 m_minifiedGraph->append(MinifiedNode::fromNode(m_currentNode));
1742                 noticeOSRBirth(m_currentNode);
1743             }
1744             
1745 #if DFG_ENABLE(DEBUG_VERBOSE)
1746             if (m_currentNode->hasResult()) {
1747                 GenerationInfo& info = m_generationInfo[m_currentNode->virtualRegister()];
1748                 dataLogF("-> %s, vr#%d", dataFormatToString(info.registerFormat()), (int)m_currentNode->virtualRegister());
1749                 if (info.registerFormat() != DataFormatNone) {
1750                     if (info.registerFormat() == DataFormatDouble)
1751                         dataLogF(", %s", FPRInfo::debugName(info.fpr()));
1752 #if USE(JSVALUE32_64)
1753                     else if (info.registerFormat() & DataFormatJS)
1754                         dataLogF(", %s %s", GPRInfo::debugName(info.tagGPR()), GPRInfo::debugName(info.payloadGPR()));
1755 #endif
1756                     else
1757                         dataLogF(", %s", GPRInfo::debugName(info.gpr()));
1758                 }
1759                 dataLogF("    ");
1760             } else
1761                 dataLogF("    ");
1762 #endif
1763         }
1764         
1765 #if DFG_ENABLE(DEBUG_VERBOSE)
1766         dataLogF("\n");
1767 #endif
1768         
1769         // Make sure that the abstract state is rematerialized for the next node.
1770         if (shouldExecuteEffects)
1771             m_state.executeEffects(m_indexInBlock);
1772         
1773         if (m_currentNode->shouldGenerate())
1774             checkConsistency();
1775     }
1776     
1777     // Perform the most basic verification that children have been used correctly.
1778 #if !ASSERT_DISABLED
1779     for (unsigned index = 0; index < m_generationInfo.size(); ++index) {
1780         GenerationInfo& info = m_generationInfo[index];
1781         ASSERT(!info.alive());
1782     }
1783 #endif
1784 }
1785
1786 // If we are making type predictions about our arguments then
1787 // we need to check that they are correct on function entry.
1788 void SpeculativeJIT::checkArgumentTypes()
1789 {
1790     ASSERT(!m_currentNode);
1791     m_isCheckingArgumentTypes = true;
1792     m_speculationDirection = BackwardSpeculation;
1793     m_codeOriginForOSR = CodeOrigin(0);
1794
1795     for (size_t i = 0; i < m_arguments.size(); ++i)
1796         m_arguments[i] = ValueSource(ValueInJSStack);
1797     for (size_t i = 0; i < m_variables.size(); ++i)
1798         m_variables[i] = ValueSource(ValueInJSStack);
1799     
1800     for (int i = 0; i < m_jit.codeBlock()->numParameters(); ++i) {
1801         Node* node = m_jit.graph().m_arguments[i];
1802         ASSERT(node->op() == SetArgument);
1803         if (!node->shouldGenerate()) {
1804             // The argument is dead. We don't do any checks for such arguments.
1805             continue;
1806         }
1807         
1808         VariableAccessData* variableAccessData = node->variableAccessData();
1809         if (!variableAccessData->shouldUnboxIfPossible())
1810             continue;
1811         
1812         VirtualRegister virtualRegister = variableAccessData->local();
1813         SpeculatedType predictedType = variableAccessData->argumentAwarePrediction();
1814
1815         JSValueSource valueSource = JSValueSource(JITCompiler::addressFor(virtualRegister));
1816         
1817 #if USE(JSVALUE64)
1818         if (isInt32Speculation(predictedType))
1819             speculationCheck(BadType, valueSource, node, m_jit.branch64(MacroAssembler::Below, JITCompiler::addressFor(virtualRegister), GPRInfo::tagTypeNumberRegister));
1820         else if (isBooleanSpeculation(predictedType)) {
1821             GPRTemporary temp(this);
1822             m_jit.load64(JITCompiler::addressFor(virtualRegister), temp.gpr());
1823             m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), temp.gpr());
1824             speculationCheck(BadType, valueSource, node, m_jit.branchTest64(MacroAssembler::NonZero, temp.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
1825         } else if (isCellSpeculation(predictedType))
1826             speculationCheck(BadType, valueSource, node, m_jit.branchTest64(MacroAssembler::NonZero, JITCompiler::addressFor(virtualRegister), GPRInfo::tagMaskRegister));
1827 #else
1828         if (isInt32Speculation(predictedType))
1829             speculationCheck(BadType, valueSource, node, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag)));
1830         else if (isBooleanSpeculation(predictedType))
1831             speculationCheck(BadType, valueSource, node, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::BooleanTag)));
1832         else if (isCellSpeculation(predictedType))
1833             speculationCheck(BadType, valueSource, node, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::CellTag)));
1834 #endif
1835     }
1836     m_isCheckingArgumentTypes = false;
1837 }
1838
1839 bool SpeculativeJIT::compile()
1840 {
1841     checkArgumentTypes();
1842
1843     if (DFG_ENABLE_EDGE_CODE_VERIFICATION)
1844         m_jit.move(TrustedImm32(0), GPRInfo::regT0);
1845
1846     ASSERT(!m_currentNode);
1847     for (m_block = 0; m_block < m_jit.graph().m_blocks.size(); ++m_block) {
1848         m_jit.setForBlock(m_block);
1849         BasicBlock* block = m_jit.graph().m_blocks[m_block].get();
1850         if (block)
1851             compile(*block);
1852     }
1853     linkBranches();
1854     return true;
1855 }
1856
1857 void SpeculativeJIT::createOSREntries()
1858 {
1859     for (BlockIndex blockIndex = 0; blockIndex < m_jit.graph().m_blocks.size(); ++blockIndex) {
1860         BasicBlock* block = m_jit.graph().m_blocks[blockIndex].get();
1861         if (!block)
1862             continue;
1863         if (!block->isOSRTarget)
1864             continue;
1865
1866         // Currently we only need to create OSR entry trampolines when using edge code
1867         // verification. But in the future, we'll need this for other things as well (like
1868         // when we have global reg alloc).
1869         // If we don't need OSR entry trampolin
1870         if (!DFG_ENABLE_EDGE_CODE_VERIFICATION) {
1871             m_osrEntryHeads.append(m_blockHeads[blockIndex]);
1872             continue;
1873         }
1874         
1875         m_osrEntryHeads.append(m_jit.label());
1876         m_jit.move(TrustedImm32(blockIndex), GPRInfo::regT0);
1877         m_jit.jump().linkTo(m_blockHeads[blockIndex], &m_jit);
1878     }
1879 }
1880
1881 void SpeculativeJIT::linkOSREntries(LinkBuffer& linkBuffer)
1882 {
1883     unsigned osrEntryIndex = 0;
1884     for (BlockIndex blockIndex = 0; blockIndex < m_jit.graph().m_blocks.size(); ++blockIndex) {
1885         BasicBlock* block = m_jit.graph().m_blocks[blockIndex].get();
1886         if (!block)
1887             continue;
1888         if (!block->isOSRTarget)
1889             continue;
1890         m_jit.noticeOSREntry(*block, m_osrEntryHeads[osrEntryIndex++], linkBuffer);
1891     }
1892     ASSERT(osrEntryIndex == m_osrEntryHeads.size());
1893 }
1894
1895 ValueRecovery SpeculativeJIT::computeValueRecoveryFor(const ValueSource& valueSource)
1896 {
1897     if (valueSource.isInJSStack())
1898         return valueSource.valueRecovery();
1899         
1900     ASSERT(valueSource.kind() == HaveNode);
1901     Node* node = valueSource.id().node(m_jit.graph());
1902     if (isConstant(node))
1903         return ValueRecovery::constant(valueOfJSConstant(node));
1904     
1905     return ValueRecovery();
1906 }
1907
1908 void SpeculativeJIT::compileDoublePutByVal(Node* node, SpeculateCellOperand& base, SpeculateStrictInt32Operand& property)
1909 {
1910     Edge child3 = m_jit.graph().varArgChild(node, 2);
1911     Edge child4 = m_jit.graph().varArgChild(node, 3);
1912
1913     ArrayMode arrayMode = node->arrayMode();
1914     
1915     GPRReg baseReg = base.gpr();
1916     GPRReg propertyReg = property.gpr();
1917     
1918     SpeculateDoubleOperand value(this, child3);
1919
1920     FPRReg valueReg = value.fpr();
1921     
1922     DFG_TYPE_CHECK(
1923         JSValueRegs(), child3, SpecRealNumber,
1924         m_jit.branchDouble(
1925             MacroAssembler::DoubleNotEqualOrUnordered, valueReg, valueReg));
1926     
1927     if (!m_compileOkay)
1928         return;
1929     
1930     StorageOperand storage(this, child4);
1931     GPRReg storageReg = storage.gpr();
1932
1933     if (node->op() == PutByValAlias) {
1934         // Store the value to the array.
1935         GPRReg propertyReg = property.gpr();
1936         FPRReg valueReg = value.fpr();
1937         m_jit.storeDouble(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
1938         
1939         noResult(m_currentNode);
1940         return;
1941     }
1942     
1943     GPRTemporary temporary;
1944     GPRReg temporaryReg = temporaryRegisterForPutByVal(temporary, node);
1945
1946     MacroAssembler::Jump slowCase;
1947     
1948     if (arrayMode.isInBounds()) {
1949         speculationCheck(
1950             StoreToHoleOrOutOfBounds, JSValueRegs(), 0,
1951             m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength())));
1952     } else {
1953         MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
1954         
1955         slowCase = m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfVectorLength()));
1956         
1957         if (!arrayMode.isOutOfBounds())
1958             speculationCheck(OutOfBounds, JSValueRegs(), 0, slowCase);
1959         
1960         m_jit.add32(TrustedImm32(1), propertyReg, temporaryReg);
1961         m_jit.store32(temporaryReg, MacroAssembler::Address(storageReg, Butterfly::offsetOfPublicLength()));
1962         
1963         inBounds.link(&m_jit);
1964     }
1965     
1966     m_jit.storeDouble(valueReg, MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight));
1967
1968     base.use();
1969     property.use();
1970     value.use();
1971     storage.use();
1972     
1973     if (arrayMode.isOutOfBounds()) {
1974         addSlowPathGenerator(
1975             slowPathCall(
1976                 slowCase, this,
1977                 m_jit.codeBlock()->isStrictMode() ? operationPutDoubleByValBeyondArrayBoundsStrict : operationPutDoubleByValBeyondArrayBoundsNonStrict,
1978                 NoResult, baseReg, propertyReg, valueReg));
1979     }
1980
1981     noResult(m_currentNode, UseChildrenCalledExplicitly);
1982 }
1983
1984 void SpeculativeJIT::compileGetCharCodeAt(Node* node)
1985 {
1986     SpeculateCellOperand string(this, node->child1());
1987     SpeculateStrictInt32Operand index(this, node->child2());
1988     StorageOperand storage(this, node->child3());
1989
1990     GPRReg stringReg = string.gpr();
1991     GPRReg indexReg = index.gpr();
1992     GPRReg storageReg = storage.gpr();
1993     
1994     ASSERT(speculationChecked(m_state.forNode(node->child1()).m_type, SpecString));
1995
1996     // unsigned comparison so we can filter out negative indices and indices that are too large
1997     speculationCheck(Uncountable, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, indexReg, MacroAssembler::Address(stringReg, JSString::offsetOfLength())));
1998
1999     GPRTemporary scratch(this);
2000     GPRReg scratchReg = scratch.gpr();
2001
2002     m_jit.loadPtr(MacroAssembler::Address(stringReg, JSString::offsetOfValue()), scratchReg);
2003
2004     // Load the character into scratchReg
2005     JITCompiler::Jump is16Bit = m_jit.branchTest32(MacroAssembler::Zero, MacroAssembler::Address(scratchReg, StringImpl::flagsOffset()), TrustedImm32(StringImpl::flagIs8Bit()));
2006
2007     m_jit.load8(MacroAssembler::BaseIndex(storageReg, indexReg, MacroAssembler::TimesOne, 0), scratchReg);
2008     JITCompiler::Jump cont8Bit = m_jit.jump();
2009
2010     is16Bit.link(&m_jit);
2011
2012     m_jit.load16(MacroAssembler::BaseIndex(storageReg, indexReg, MacroAssembler::TimesTwo, 0), scratchReg);
2013
2014     cont8Bit.link(&m_jit);
2015
2016     integerResult(scratchReg, m_currentNode);
2017 }
2018
2019 void SpeculativeJIT::compileGetByValOnString(Node* node)
2020 {
2021     SpeculateCellOperand base(this, node->child1());
2022     SpeculateStrictInt32Operand property(this, node->child2());
2023     StorageOperand storage(this, node->child3());
2024     GPRReg baseReg = base.gpr();
2025     GPRReg propertyReg = property.gpr();
2026     GPRReg storageReg = storage.gpr();
2027
2028     ASSERT(ArrayMode(Array::String).alreadyChecked(m_jit.graph(), node, m_state.forNode(node->child1())));
2029
2030     // unsigned comparison so we can filter out negative indices and indices that are too large
2031     speculationCheck(Uncountable, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSString::offsetOfLength())));
2032
2033     GPRTemporary scratch(this);
2034     GPRReg scratchReg = scratch.gpr();
2035
2036     m_jit.loadPtr(MacroAssembler::Address(baseReg, JSString::offsetOfValue()), scratchReg);
2037
2038     // Load the character into scratchReg
2039     JITCompiler::Jump is16Bit = m_jit.branchTest32(MacroAssembler::Zero, MacroAssembler::Address(scratchReg, StringImpl::flagsOffset()), TrustedImm32(StringImpl::flagIs8Bit()));
2040
2041     m_jit.load8(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne, 0), scratchReg);
2042     JITCompiler::Jump cont8Bit = m_jit.jump();
2043
2044     is16Bit.link(&m_jit);
2045
2046     m_jit.load16(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesTwo, 0), scratchReg);
2047
2048     // We only support ascii characters
2049     speculationCheck(Uncountable, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::AboveOrEqual, scratchReg, TrustedImm32(0x100)));
2050
2051     // 8 bit string values don't need the isASCII check.
2052     cont8Bit.link(&m_jit);
2053
2054     GPRTemporary smallStrings(this);
2055     GPRReg smallStringsReg = smallStrings.gpr();
2056     m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.vm()->smallStrings.singleCharacterStrings()), smallStringsReg);
2057     m_jit.loadPtr(MacroAssembler::BaseIndex(smallStringsReg, scratchReg, MacroAssembler::ScalePtr, 0), scratchReg);
2058     speculationCheck(Uncountable, JSValueRegs(), 0, m_jit.branchTest32(MacroAssembler::Zero, scratchReg));
2059     cellResult(scratchReg, m_currentNode);
2060 }
2061
2062 void SpeculativeJIT::compileFromCharCode(Node* node)
2063 {
2064     SpeculateStrictInt32Operand property(this, node->child1());
2065     GPRReg propertyReg = property.gpr();
2066     GPRTemporary smallStrings(this);
2067     GPRTemporary scratch(this);
2068     GPRReg scratchReg = scratch.gpr();
2069     GPRReg smallStringsReg = smallStrings.gpr();
2070
2071     JITCompiler::JumpList slowCases;
2072     slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, TrustedImm32(0xff)));
2073     m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.vm()->smallStrings.singleCharacterStrings()), smallStringsReg);
2074     m_jit.loadPtr(MacroAssembler::BaseIndex(smallStringsReg, propertyReg, MacroAssembler::ScalePtr, 0), scratchReg);
2075
2076     slowCases.append(m_jit.branchTest32(MacroAssembler::Zero, scratchReg));
2077     addSlowPathGenerator(slowPathCall(slowCases, this, operationStringFromCharCode, scratchReg, propertyReg));
2078     cellResult(scratchReg, m_currentNode);
2079 }
2080
2081 GeneratedOperandType SpeculativeJIT::checkGeneratedTypeForToInt32(Node* node)
2082 {
2083 #if DFG_ENABLE(DEBUG_VERBOSE)
2084     dataLogF("checkGeneratedTypeForToInt32@%d   ", node->index());
2085 #endif
2086     VirtualRegister virtualRegister = node->virtualRegister();
2087     GenerationInfo& info = m_generationInfo[virtualRegister];
2088
2089     switch (info.registerFormat()) {
2090     case DataFormatStorage:
2091         RELEASE_ASSERT_NOT_REACHED();
2092
2093     case DataFormatBoolean:
2094     case DataFormatCell:
2095         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
2096         return GeneratedOperandTypeUnknown;
2097
2098     case DataFormatNone:
2099     case DataFormatJSCell:
2100     case DataFormatJS:
2101     case DataFormatJSBoolean:
2102         return GeneratedOperandJSValue;
2103
2104     case DataFormatJSInteger:
2105     case DataFormatInteger:
2106         return GeneratedOperandInteger;
2107
2108     case DataFormatJSDouble:
2109     case DataFormatDouble:
2110         return GeneratedOperandDouble;
2111         
2112     default:
2113         RELEASE_ASSERT_NOT_REACHED();
2114         return GeneratedOperandTypeUnknown;
2115     }
2116 }
2117
2118 void SpeculativeJIT::compileValueToInt32(Node* node)
2119 {
2120     switch (node->child1().useKind()) {
2121     case Int32Use: {
2122         SpeculateIntegerOperand op1(this, node->child1());
2123         GPRTemporary result(this, op1);
2124         m_jit.move(op1.gpr(), result.gpr());
2125         integerResult(result.gpr(), node, op1.format());
2126         return;
2127     }
2128     
2129     case NumberUse:
2130     case NotCellUse: {
2131         switch (checkGeneratedTypeForToInt32(node->child1().node())) {
2132         case GeneratedOperandInteger: {
2133             SpeculateIntegerOperand op1(this, node->child1(), ManualOperandSpeculation);
2134             GPRTemporary result(this, op1);
2135             m_jit.move(op1.gpr(), result.gpr());
2136             integerResult(result.gpr(), node, op1.format());
2137             return;
2138         }
2139         case GeneratedOperandDouble: {
2140             GPRTemporary result(this);
2141             SpeculateDoubleOperand op1(this, node->child1(), ManualOperandSpeculation);
2142             FPRReg fpr = op1.fpr();
2143             GPRReg gpr = result.gpr();
2144             JITCompiler::Jump notTruncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateFailed);
2145             
2146             addSlowPathGenerator(slowPathCall(notTruncatedToInteger, this, toInt32, gpr, fpr));
2147
2148             integerResult(gpr, node);
2149             return;
2150         }
2151         case GeneratedOperandJSValue: {
2152             GPRTemporary result(this);
2153 #if USE(JSVALUE64)
2154             JSValueOperand op1(this, node->child1(), ManualOperandSpeculation);
2155
2156             GPRReg gpr = op1.gpr();
2157             GPRReg resultGpr = result.gpr();
2158             FPRTemporary tempFpr(this);
2159             FPRReg fpr = tempFpr.fpr();
2160
2161             JITCompiler::Jump isInteger = m_jit.branch64(MacroAssembler::AboveOrEqual, gpr, GPRInfo::tagTypeNumberRegister);
2162             JITCompiler::JumpList converted;
2163
2164             if (node->child1().useKind() == NumberUse) {
2165                 DFG_TYPE_CHECK(
2166                     JSValueRegs(gpr), node->child1(), SpecNumber,
2167                     m_jit.branchTest64(
2168                         MacroAssembler::Zero, gpr, GPRInfo::tagTypeNumberRegister));
2169             } else {
2170                 JITCompiler::Jump isNumber = m_jit.branchTest64(MacroAssembler::NonZero, gpr, GPRInfo::tagTypeNumberRegister);
2171                 
2172                 DFG_TYPE_CHECK(
2173                     JSValueRegs(gpr), node->child1(), ~SpecCell,
2174                     m_jit.branchTest64(
2175                         JITCompiler::Zero, gpr, GPRInfo::tagMaskRegister));
2176                 
2177                 // It's not a cell: so true turns into 1 and all else turns into 0.
2178                 m_jit.compare64(JITCompiler::Equal, gpr, TrustedImm32(ValueTrue), resultGpr);
2179                 converted.append(m_jit.jump());
2180                 
2181                 isNumber.link(&m_jit);
2182             }
2183
2184             // First, if we get here we have a double encoded as a JSValue
2185             m_jit.move(gpr, resultGpr);
2186             unboxDouble(resultGpr, fpr);
2187
2188             silentSpillAllRegisters(resultGpr);
2189             callOperation(toInt32, resultGpr, fpr);
2190             silentFillAllRegisters(resultGpr);
2191
2192             converted.append(m_jit.jump());
2193
2194             isInteger.link(&m_jit);
2195             m_jit.zeroExtend32ToPtr(gpr, resultGpr);
2196
2197             converted.link(&m_jit);
2198 #else
2199             Node* childNode = node->child1().node();
2200             VirtualRegister virtualRegister = childNode->virtualRegister();
2201             GenerationInfo& info = m_generationInfo[virtualRegister];
2202
2203             JSValueOperand op1(this, node->child1(), ManualOperandSpeculation);
2204
2205             GPRReg payloadGPR = op1.payloadGPR();
2206             GPRReg resultGpr = result.gpr();
2207         
2208             JITCompiler::JumpList converted;
2209
2210             if (info.registerFormat() == DataFormatJSInteger)
2211                 m_jit.move(payloadGPR, resultGpr);
2212             else {
2213                 GPRReg tagGPR = op1.tagGPR();
2214                 FPRTemporary tempFpr(this);
2215                 FPRReg fpr = tempFpr.fpr();
2216                 FPRTemporary scratch(this);
2217
2218                 JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, tagGPR, TrustedImm32(JSValue::Int32Tag));
2219
2220                 if (node->child1().useKind() == NumberUse) {
2221                     DFG_TYPE_CHECK(
2222                         JSValueRegs(tagGPR, payloadGPR), node->child1(), SpecNumber,
2223                         m_jit.branch32(
2224                             MacroAssembler::AboveOrEqual, tagGPR,
2225                             TrustedImm32(JSValue::LowestTag)));
2226                 } else {
2227                     JITCompiler::Jump isNumber = m_jit.branch32(MacroAssembler::Below, tagGPR, TrustedImm32(JSValue::LowestTag));
2228                     
2229                     DFG_TYPE_CHECK(
2230                         JSValueRegs(tagGPR, payloadGPR), node->child1(), ~SpecCell,
2231                         m_jit.branch32(
2232                             JITCompiler::Equal, tagGPR, TrustedImm32(JSValue::CellTag)));
2233                     
2234                     // It's not a cell: so true turns into 1 and all else turns into 0.
2235                     JITCompiler::Jump isBoolean = m_jit.branch32(JITCompiler::Equal, tagGPR, TrustedImm32(JSValue::BooleanTag));
2236                     m_jit.move(TrustedImm32(0), resultGpr);
2237                     converted.append(m_jit.jump());
2238                     
2239                     isBoolean.link(&m_jit);
2240                     m_jit.move(payloadGPR, resultGpr);
2241                     converted.append(m_jit.jump());
2242                     
2243                     isNumber.link(&m_jit);
2244                 }
2245
2246                 unboxDouble(tagGPR, payloadGPR, fpr, scratch.fpr());
2247
2248                 silentSpillAllRegisters(resultGpr);
2249                 callOperation(toInt32, resultGpr, fpr);
2250                 silentFillAllRegisters(resultGpr);
2251
2252                 converted.append(m_jit.jump());
2253
2254                 isInteger.link(&m_jit);
2255                 m_jit.move(payloadGPR, resultGpr);
2256
2257                 converted.link(&m_jit);
2258             }
2259 #endif
2260             integerResult(resultGpr, node);
2261             return;
2262         }
2263         case GeneratedOperandTypeUnknown:
2264             RELEASE_ASSERT(!m_compileOkay);
2265             return;
2266         }
2267         RELEASE_ASSERT_NOT_REACHED();
2268         return;
2269     }
2270     
2271     case BooleanUse: {
2272         SpeculateBooleanOperand op1(this, node->child1());
2273         GPRTemporary result(this, op1);
2274         
2275         m_jit.move(op1.gpr(), result.gpr());
2276         m_jit.and32(JITCompiler::TrustedImm32(1), result.gpr());
2277         
2278         integerResult(result.gpr(), node);
2279         return;
2280     }
2281
2282     default:
2283         ASSERT(!m_compileOkay);
2284         return;
2285     }
2286 }
2287
2288 void SpeculativeJIT::compileUInt32ToNumber(Node* node)
2289 {
2290     if (!nodeCanSpeculateInteger(node->arithNodeFlags())) {
2291         // We know that this sometimes produces doubles. So produce a double every
2292         // time. This at least allows subsequent code to not have weird conditionals.
2293             
2294         IntegerOperand op1(this, node->child1());
2295         FPRTemporary result(this);
2296             
2297         GPRReg inputGPR = op1.gpr();
2298         FPRReg outputFPR = result.fpr();
2299             
2300         m_jit.convertInt32ToDouble(inputGPR, outputFPR);
2301             
2302         JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, inputGPR, TrustedImm32(0));
2303         m_jit.addDouble(JITCompiler::AbsoluteAddress(&AssemblyHelpers::twoToThe32), outputFPR);
2304         positive.link(&m_jit);
2305             
2306         doubleResult(outputFPR, node);
2307         return;
2308     }
2309
2310     IntegerOperand op1(this, node->child1());
2311     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.
2312
2313     m_jit.move(op1.gpr(), result.gpr());
2314
2315     // Test the operand is positive. This is a very special speculation check - we actually
2316     // use roll-forward speculation here, where if this fails, we jump to the baseline
2317     // instruction that follows us, rather than the one we're executing right now. We have
2318     // to do this because by this point, the original values necessary to compile whatever
2319     // operation the UInt32ToNumber originated from might be dead.
2320     forwardSpeculationCheck(Overflow, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::LessThan, result.gpr(), TrustedImm32(0)), ValueRecovery::uint32InGPR(result.gpr()));
2321
2322     integerResult(result.gpr(), node, op1.format());
2323 }
2324
2325 void SpeculativeJIT::compileDoubleAsInt32(Node* node)
2326 {
2327     SpeculateDoubleOperand op1(this, node->child1());
2328     FPRTemporary scratch(this);
2329     GPRTemporary result(this);
2330     
2331     FPRReg valueFPR = op1.fpr();
2332     FPRReg scratchFPR = scratch.fpr();
2333     GPRReg resultGPR = result.gpr();
2334
2335     JITCompiler::JumpList failureCases;
2336     bool negZeroCheck = !nodeCanIgnoreNegativeZero(node->arithNodeFlags());
2337     m_jit.branchConvertDoubleToInt32(valueFPR, resultGPR, failureCases, scratchFPR, negZeroCheck);
2338     forwardSpeculationCheck(Overflow, JSValueRegs(), 0, failureCases, ValueRecovery::inFPR(valueFPR));
2339
2340     integerResult(resultGPR, node);
2341 }
2342
2343 void SpeculativeJIT::compileInt32ToDouble(Node* node)
2344 {
2345     ASSERT(!isInt32Constant(node->child1().node())); // This should have been constant folded.
2346     
2347     if (isInt32Speculation(m_state.forNode(node->child1()).m_type)) {
2348         SpeculateIntegerOperand op1(this, node->child1(), ManualOperandSpeculation);
2349         FPRTemporary result(this);
2350         m_jit.convertInt32ToDouble(op1.gpr(), result.fpr());
2351         doubleResult(result.fpr(), node);
2352         return;
2353     }
2354     
2355     JSValueOperand op1(this, node->child1(), ManualOperandSpeculation);
2356     FPRTemporary result(this);
2357     
2358 #if USE(JSVALUE64)
2359     GPRTemporary temp(this);
2360
2361     GPRReg op1GPR = op1.gpr();
2362     GPRReg tempGPR = temp.gpr();
2363     FPRReg resultFPR = result.fpr();
2364     
2365     JITCompiler::Jump isInteger = m_jit.branch64(
2366         MacroAssembler::AboveOrEqual, op1GPR, GPRInfo::tagTypeNumberRegister);
2367     
2368     if (needsTypeCheck(node->child1(), SpecNumber)) {
2369         if (node->op() == ForwardInt32ToDouble) {
2370             forwardTypeCheck(
2371                 JSValueRegs(op1GPR), node->child1(), SpecNumber,
2372                 m_jit.branchTest64(MacroAssembler::Zero, op1GPR, GPRInfo::tagTypeNumberRegister),
2373                 ValueRecovery::inGPR(op1GPR, DataFormatJS));
2374         } else {
2375             backwardTypeCheck(
2376                 JSValueRegs(op1GPR), node->child1(), SpecNumber,
2377                 m_jit.branchTest64(MacroAssembler::Zero, op1GPR, GPRInfo::tagTypeNumberRegister));
2378         }
2379     }
2380     
2381     m_jit.move(op1GPR, tempGPR);
2382     unboxDouble(tempGPR, resultFPR);
2383     JITCompiler::Jump done = m_jit.jump();
2384     
2385     isInteger.link(&m_jit);
2386     m_jit.convertInt32ToDouble(op1GPR, resultFPR);
2387     done.link(&m_jit);
2388 #else
2389     FPRTemporary temp(this);
2390     
2391     GPRReg op1TagGPR = op1.tagGPR();
2392     GPRReg op1PayloadGPR = op1.payloadGPR();
2393     FPRReg tempFPR = temp.fpr();
2394     FPRReg resultFPR = result.fpr();
2395     
2396     JITCompiler::Jump isInteger = m_jit.branch32(
2397         MacroAssembler::Equal, op1TagGPR, TrustedImm32(JSValue::Int32Tag));
2398     
2399     if (needsTypeCheck(node->child1(), SpecNumber)) {
2400         if (node->op() == ForwardInt32ToDouble) {
2401             forwardTypeCheck(
2402                 JSValueRegs(op1TagGPR, op1PayloadGPR), node->child1(), SpecNumber,
2403                 m_jit.branch32(MacroAssembler::AboveOrEqual, op1TagGPR, TrustedImm32(JSValue::LowestTag)),
2404                 ValueRecovery::inPair(op1TagGPR, op1PayloadGPR));
2405         } else {
2406             backwardTypeCheck(
2407                 JSValueRegs(op1TagGPR, op1PayloadGPR), node->child1(), SpecNumber,
2408                 m_jit.branch32(MacroAssembler::AboveOrEqual, op1TagGPR, TrustedImm32(JSValue::LowestTag)));
2409         }
2410     }
2411     
2412     unboxDouble(op1TagGPR, op1PayloadGPR, resultFPR, tempFPR);
2413     JITCompiler::Jump done = m_jit.jump();
2414     
2415     isInteger.link(&m_jit);
2416     m_jit.convertInt32ToDouble(op1PayloadGPR, resultFPR);
2417     done.link(&m_jit);
2418 #endif
2419     
2420     doubleResult(resultFPR, node);
2421 }
2422
2423 static double clampDoubleToByte(double d)
2424 {
2425     d += 0.5;
2426     if (!(d > 0))
2427         d = 0;
2428     else if (d > 255)
2429         d = 255;
2430     return d;
2431 }
2432
2433 static void compileClampIntegerToByte(JITCompiler& jit, GPRReg result)
2434 {
2435     MacroAssembler::Jump inBounds = jit.branch32(MacroAssembler::BelowOrEqual, result, JITCompiler::TrustedImm32(0xff));
2436     MacroAssembler::Jump tooBig = jit.branch32(MacroAssembler::GreaterThan, result, JITCompiler::TrustedImm32(0xff));
2437     jit.xorPtr(result, result);
2438     MacroAssembler::Jump clamped = jit.jump();
2439     tooBig.link(&jit);
2440     jit.move(JITCompiler::TrustedImm32(255), result);
2441     clamped.link(&jit);
2442     inBounds.link(&jit);
2443 }
2444
2445 static void compileClampDoubleToByte(JITCompiler& jit, GPRReg result, FPRReg source, FPRReg scratch)
2446 {
2447     // Unordered compare so we pick up NaN
2448     static const double zero = 0;
2449     static const double byteMax = 255;
2450     static const double half = 0.5;
2451     jit.loadDouble(&zero, scratch);
2452     MacroAssembler::Jump tooSmall = jit.branchDouble(MacroAssembler::DoubleLessThanOrEqualOrUnordered, source, scratch);
2453     jit.loadDouble(&byteMax, scratch);
2454     MacroAssembler::Jump tooBig = jit.branchDouble(MacroAssembler::DoubleGreaterThan, source, scratch);
2455     
2456     jit.loadDouble(&half, scratch);
2457     // FIXME: This should probably just use a floating point round!
2458     // https://bugs.webkit.org/show_bug.cgi?id=72054
2459     jit.addDouble(source, scratch);
2460     jit.truncateDoubleToInt32(scratch, result);   
2461     MacroAssembler::Jump truncatedInt = jit.jump();
2462     
2463     tooSmall.link(&jit);
2464     jit.xorPtr(result, result);
2465     MacroAssembler::Jump zeroed = jit.jump();
2466     
2467     tooBig.link(&jit);
2468     jit.move(JITCompiler::TrustedImm32(255), result);
2469     
2470     truncatedInt.link(&jit);
2471     zeroed.link(&jit);
2472
2473 }
2474
2475 void SpeculativeJIT::compileGetByValOnIntTypedArray(const TypedArrayDescriptor& descriptor, Node* node, size_t elementSize, TypedArraySignedness signedness)
2476 {
2477     SpeculateCellOperand base(this, node->child1());
2478     SpeculateStrictInt32Operand property(this, node->child2());
2479     StorageOperand storage(this, node->child3());
2480
2481     GPRReg baseReg = base.gpr();
2482     GPRReg propertyReg = property.gpr();
2483     GPRReg storageReg = storage.gpr();
2484
2485     GPRTemporary result(this);
2486     GPRReg resultReg = result.gpr();
2487
2488     ASSERT(node->arrayMode().alreadyChecked(m_jit.graph(), node, m_state.forNode(node->child1())));
2489
2490     speculationCheck(
2491         Uncountable, JSValueRegs(), 0,
2492         m_jit.branch32(
2493             MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, descriptor.m_lengthOffset)));
2494     switch (elementSize) {
2495     case 1:
2496         if (signedness == SignedTypedArray)
2497             m_jit.load8Signed(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne), resultReg);
2498         else
2499             m_jit.load8(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne), resultReg);
2500         break;
2501     case 2:
2502         if (signedness == SignedTypedArray)
2503             m_jit.load16Signed(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesTwo), resultReg);
2504         else
2505             m_jit.load16(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesTwo), resultReg);
2506         break;
2507     case 4:
2508         m_jit.load32(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesFour), resultReg);
2509         break;
2510     default:
2511         CRASH();
2512     }
2513     if (elementSize < 4 || signedness == SignedTypedArray) {
2514         integerResult(resultReg, node);
2515         return;
2516     }
2517     
2518     ASSERT(elementSize == 4 && signedness == UnsignedTypedArray);
2519     if (node->shouldSpeculateInteger()) {
2520         forwardSpeculationCheck(Overflow, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::LessThan, resultReg, TrustedImm32(0)), ValueRecovery::uint32InGPR(resultReg));
2521         integerResult(resultReg, node);
2522         return;
2523     }
2524     
2525     FPRTemporary fresult(this);
2526     m_jit.convertInt32ToDouble(resultReg, fresult.fpr());
2527     JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, resultReg, TrustedImm32(0));
2528     m_jit.addDouble(JITCompiler::AbsoluteAddress(&AssemblyHelpers::twoToThe32), fresult.fpr());
2529     positive.link(&m_jit);
2530     doubleResult(fresult.fpr(), node);
2531 }
2532
2533 void SpeculativeJIT::compilePutByValForIntTypedArray(const TypedArrayDescriptor& descriptor, GPRReg base, GPRReg property, Node* node, size_t elementSize, TypedArraySignedness signedness, TypedArrayRounding rounding)
2534 {
2535     StorageOperand storage(this, m_jit.graph().varArgChild(node, 3));
2536     GPRReg storageReg = storage.gpr();
2537     
2538     Edge valueUse = m_jit.graph().varArgChild(node, 2);
2539     
2540     GPRTemporary value;
2541     GPRReg valueGPR = InvalidGPRReg;
2542     
2543     if (valueUse->isConstant()) {
2544         JSValue jsValue = valueOfJSConstant(valueUse.node());
2545         if (!jsValue.isNumber()) {
2546             terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
2547             noResult(node);
2548             return;
2549         }
2550         double d = jsValue.asNumber();
2551         if (rounding == ClampRounding) {
2552             ASSERT(elementSize == 1);
2553             d = clampDoubleToByte(d);
2554         }
2555         GPRTemporary scratch(this);
2556         GPRReg scratchReg = scratch.gpr();
2557         m_jit.move(Imm32(toInt32(d)), scratchReg);
2558         value.adopt(scratch);
2559         valueGPR = scratchReg;
2560     } else {
2561         switch (valueUse.useKind()) {
2562         case Int32Use: {
2563             SpeculateIntegerOperand valueOp(this, valueUse);
2564             GPRTemporary scratch(this);
2565             GPRReg scratchReg = scratch.gpr();
2566             m_jit.move(valueOp.gpr(), scratchReg);
2567             if (rounding == ClampRounding) {
2568                 ASSERT(elementSize == 1);
2569                 compileClampIntegerToByte(m_jit, scratchReg);
2570             }
2571             value.adopt(scratch);
2572             valueGPR = scratchReg;
2573             break;
2574         }
2575             
2576         case NumberUse: {
2577             if (rounding == ClampRounding) {
2578                 ASSERT(elementSize == 1);
2579                 SpeculateDoubleOperand valueOp(this, valueUse);
2580                 GPRTemporary result(this);
2581                 FPRTemporary floatScratch(this);
2582                 FPRReg fpr = valueOp.fpr();
2583                 GPRReg gpr = result.gpr();
2584                 compileClampDoubleToByte(m_jit, gpr, fpr, floatScratch.fpr());
2585                 value.adopt(result);
2586                 valueGPR = gpr;
2587             } else {
2588                 SpeculateDoubleOperand valueOp(this, valueUse);
2589                 GPRTemporary result(this);
2590                 FPRReg fpr = valueOp.fpr();
2591                 GPRReg gpr = result.gpr();
2592                 MacroAssembler::Jump notNaN = m_jit.branchDouble(MacroAssembler::DoubleEqual, fpr, fpr);
2593                 m_jit.xorPtr(gpr, gpr);
2594                 MacroAssembler::Jump fixed = m_jit.jump();
2595                 notNaN.link(&m_jit);
2596                 
2597                 MacroAssembler::Jump failed;
2598                 if (signedness == SignedTypedArray)
2599                     failed = m_jit.branchTruncateDoubleToInt32(fpr, gpr, MacroAssembler::BranchIfTruncateFailed);
2600                 else
2601                     failed = m_jit.branchTruncateDoubleToUint32(fpr, gpr, MacroAssembler::BranchIfTruncateFailed);
2602                 
2603                 addSlowPathGenerator(slowPathCall(failed, this, toInt32, gpr, fpr));
2604                 
2605                 fixed.link(&m_jit);
2606                 value.adopt(result);
2607                 valueGPR = gpr;
2608             }
2609             break;
2610         }
2611             
2612         default:
2613             RELEASE_ASSERT_NOT_REACHED();
2614             break;
2615         }
2616     }
2617     
2618     ASSERT_UNUSED(valueGPR, valueGPR != property);
2619     ASSERT(valueGPR != base);
2620     ASSERT(valueGPR != storageReg);
2621     MacroAssembler::Jump outOfBounds;
2622     if (node->op() == PutByVal)
2623         outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, property, MacroAssembler::Address(base, descriptor.m_lengthOffset));
2624
2625     switch (elementSize) {
2626     case 1:
2627         m_jit.store8(value.gpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesOne));
2628         break;
2629     case 2:
2630         m_jit.store16(value.gpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesTwo));
2631         break;
2632     case 4:
2633         m_jit.store32(value.gpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesFour));
2634         break;
2635     default:
2636         CRASH();
2637     }
2638     if (node->op() == PutByVal)
2639         outOfBounds.link(&m_jit);
2640     noResult(node);
2641 }
2642
2643 void SpeculativeJIT::compileGetByValOnFloatTypedArray(const TypedArrayDescriptor& descriptor, Node* node, size_t elementSize)
2644 {
2645     SpeculateCellOperand base(this, node->child1());
2646     SpeculateStrictInt32Operand property(this, node->child2());
2647     StorageOperand storage(this, node->child3());
2648
2649     GPRReg baseReg = base.gpr();
2650     GPRReg propertyReg = property.gpr();
2651     GPRReg storageReg = storage.gpr();
2652
2653     ASSERT(node->arrayMode().alreadyChecked(m_jit.graph(), node, m_state.forNode(node->child1())));
2654
2655     FPRTemporary result(this);
2656     FPRReg resultReg = result.fpr();
2657     speculationCheck(
2658         Uncountable, JSValueRegs(), 0,
2659         m_jit.branch32(
2660             MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, descriptor.m_lengthOffset)));
2661     switch (elementSize) {
2662     case 4:
2663         m_jit.loadFloat(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesFour), resultReg);
2664         m_jit.convertFloatToDouble(resultReg, resultReg);
2665         break;
2666     case 8: {
2667         m_jit.loadDouble(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesEight), resultReg);
2668         break;
2669     }
2670     default:
2671         RELEASE_ASSERT_NOT_REACHED();
2672     }
2673     
2674     MacroAssembler::Jump notNaN = m_jit.branchDouble(MacroAssembler::DoubleEqual, resultReg, resultReg);
2675     static const double NaN = QNaN;
2676     m_jit.loadDouble(&NaN, resultReg);
2677     notNaN.link(&m_jit);
2678     
2679     doubleResult(resultReg, node);
2680 }
2681
2682 void SpeculativeJIT::compilePutByValForFloatTypedArray(const TypedArrayDescriptor& descriptor, GPRReg base, GPRReg property, Node* node, size_t elementSize)
2683 {
2684     StorageOperand storage(this, m_jit.graph().varArgChild(node, 3));
2685     GPRReg storageReg = storage.gpr();
2686     
2687     Edge baseUse = m_jit.graph().varArgChild(node, 0);
2688     Edge valueUse = m_jit.graph().varArgChild(node, 2);
2689
2690     SpeculateDoubleOperand valueOp(this, valueUse);
2691     FPRTemporary scratch(this);
2692     FPRReg valueFPR = valueOp.fpr();
2693     FPRReg scratchFPR = scratch.fpr();
2694
2695     ASSERT_UNUSED(baseUse, node->arrayMode().alreadyChecked(m_jit.graph(), node, m_state.forNode(baseUse)));
2696     
2697     MacroAssembler::Jump outOfBounds;
2698     if (node->op() == PutByVal)
2699         outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, property, MacroAssembler::Address(base, descriptor.m_lengthOffset));
2700     
2701     switch (elementSize) {
2702     case 4: {
2703         m_jit.moveDouble(valueFPR, scratchFPR);
2704         m_jit.convertDoubleToFloat(valueFPR, scratchFPR);
2705         m_jit.storeFloat(scratchFPR, MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesFour));
2706         break;
2707     }
2708     case 8:
2709         m_jit.storeDouble(valueFPR, MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesEight));
2710         break;
2711     default:
2712         RELEASE_ASSERT_NOT_REACHED();
2713     }
2714     if (node->op() == PutByVal)
2715         outOfBounds.link(&m_jit);
2716     noResult(node);
2717 }
2718
2719 void SpeculativeJIT::compileInstanceOfForObject(Node*, GPRReg valueReg, GPRReg prototypeReg, GPRReg scratchReg)
2720 {
2721     // Check that prototype is an object.
2722     m_jit.loadPtr(MacroAssembler::Address(prototypeReg, JSCell::structureOffset()), scratchReg);
2723     speculationCheck(BadType, JSValueRegs(), 0, m_jit.branchIfNotObject(scratchReg));
2724     
2725     // Initialize scratchReg with the value being checked.
2726     m_jit.move(valueReg, scratchReg);
2727     
2728     // Walk up the prototype chain of the value (in scratchReg), comparing to prototypeReg.
2729     MacroAssembler::Label loop(&m_jit);
2730     m_jit.loadPtr(MacroAssembler::Address(scratchReg, JSCell::structureOffset()), scratchReg);
2731 #if USE(JSVALUE64)
2732     m_jit.load64(MacroAssembler::Address(scratchReg, Structure::prototypeOffset()), scratchReg);
2733     MacroAssembler::Jump isInstance = m_jit.branch64(MacroAssembler::Equal, scratchReg, prototypeReg);
2734     m_jit.branchTest64(MacroAssembler::Zero, scratchReg, GPRInfo::tagMaskRegister).linkTo(loop, &m_jit);
2735 #else
2736     m_jit.load32(MacroAssembler::Address(scratchReg, Structure::prototypeOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), scratchReg);
2737     MacroAssembler::Jump isInstance = m_jit.branchPtr(MacroAssembler::Equal, scratchReg, prototypeReg);
2738     m_jit.branchTest32(MacroAssembler::NonZero, scratchReg).linkTo(loop, &m_jit);
2739 #endif
2740     
2741     // No match - result is false.
2742 #if USE(JSVALUE64)
2743     m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(false))), scratchReg);
2744 #else
2745     m_jit.move(MacroAssembler::TrustedImm32(0), scratchReg);
2746 #endif
2747     MacroAssembler::Jump putResult = m_jit.jump();
2748     
2749     isInstance.link(&m_jit);
2750 #if USE(JSVALUE64)
2751     m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(true))), scratchReg);
2752 #else
2753     m_jit.move(MacroAssembler::TrustedImm32(1), scratchReg);
2754 #endif
2755     
2756     putResult.link(&m_jit);
2757 }
2758
2759 void SpeculativeJIT::compileInstanceOf(Node* node)
2760 {
2761     if (node->child1().useKind() == UntypedUse) {
2762         // It might not be a cell. Speculate less aggressively.
2763         // Or: it might only be used once (i.e. by us), so we get zero benefit
2764         // from speculating any more aggressively than we absolutely need to.
2765         
2766         JSValueOperand value(this, node->child1());
2767         SpeculateCellOperand prototype(this, node->child2());
2768         GPRTemporary scratch(this);
2769         
2770         GPRReg prototypeReg = prototype.gpr();
2771         GPRReg scratchReg = scratch.gpr();
2772         
2773 #if USE(JSVALUE64)
2774         GPRReg valueReg = value.gpr();
2775         MacroAssembler::Jump isCell = m_jit.branchTest64(MacroAssembler::Zero, valueReg, GPRInfo::tagMaskRegister);
2776         m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(false))), scratchReg);
2777 #else
2778         GPRReg valueTagReg = value.tagGPR();
2779         GPRReg valueReg = value.payloadGPR();
2780         MacroAssembler::Jump isCell = m_jit.branch32(MacroAssembler::Equal, valueTagReg, TrustedImm32(JSValue::CellTag));
2781         m_jit.move(MacroAssembler::TrustedImm32(0), scratchReg);
2782 #endif
2783
2784         MacroAssembler::Jump done = m_jit.jump();
2785         
2786         isCell.link(&m_jit);
2787         
2788         compileInstanceOfForObject(node, valueReg, prototypeReg, scratchReg);
2789         
2790         done.link(&m_jit);
2791
2792 #if USE(JSVALUE64)
2793         jsValueResult(scratchReg, node, DataFormatJSBoolean);
2794 #else
2795         booleanResult(scratchReg, node);
2796 #endif
2797         return;
2798     }
2799     
2800     SpeculateCellOperand value(this, node->child1());
2801     SpeculateCellOperand prototype(this, node->child2());
2802     
2803     GPRTemporary scratch(this);
2804     
2805     GPRReg valueReg = value.gpr();
2806     GPRReg prototypeReg = prototype.gpr();
2807     GPRReg scratchReg = scratch.gpr();
2808     
2809     compileInstanceOfForObject(node, valueReg, prototypeReg, scratchReg);
2810
2811 #if USE(JSVALUE64)
2812     jsValueResult(scratchReg, node, DataFormatJSBoolean);
2813 #else
2814     booleanResult(scratchReg, node);
2815 #endif
2816 }
2817
2818 void SpeculativeJIT::compileSoftModulo(Node* node)
2819 {
2820     // In the fast path, the dividend value could be the final result
2821     // (in case of |dividend| < |divisor|), so we speculate it as strict int32.
2822     SpeculateStrictInt32Operand op1(this, node->child1());
2823 #if CPU(X86) || CPU(X86_64)
2824     if (isInt32Constant(node->child2().node())) {
2825         int32_t divisor = valueOfInt32Constant(node->child2().node());
2826         if (divisor) {
2827             GPRReg op1Gpr = op1.gpr();
2828
2829             GPRTemporary eax(this, X86Registers::eax);
2830             GPRTemporary edx(this, X86Registers::edx);
2831             GPRTemporary scratch(this);
2832             GPRReg scratchGPR = scratch.gpr();
2833
2834             GPRReg op1SaveGPR;
2835             if (op1Gpr == X86Registers::eax || op1Gpr == X86Registers::edx) {
2836                 op1SaveGPR = allocate();
2837                 ASSERT(op1Gpr != op1SaveGPR);
2838                 m_jit.move(op1Gpr, op1SaveGPR);
2839             } else
2840                 op1SaveGPR = op1Gpr;
2841             ASSERT(op1SaveGPR != X86Registers::eax);
2842             ASSERT(op1SaveGPR != X86Registers::edx);
2843
2844             m_jit.move(op1Gpr, eax.gpr());
2845             m_jit.move(TrustedImm32(divisor), scratchGPR);
2846             if (divisor == -1)
2847                 speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branch32(JITCompiler::Equal, eax.gpr(), TrustedImm32(-2147483647-1)));
2848             m_jit.assembler().cdq();
2849             m_jit.assembler().idivl_r(scratchGPR);
2850             if (!nodeCanIgnoreNegativeZero(node->arithNodeFlags())) {
2851                 // Check that we're not about to create negative zero.
2852                 JITCompiler::Jump numeratorPositive = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op1SaveGPR, TrustedImm32(0));
2853                 speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::Zero, edx.gpr()));
2854                 numeratorPositive.link(&m_jit);
2855             }
2856             if (op1SaveGPR != op1Gpr)
2857                 unlock(op1SaveGPR);
2858
2859             integerResult(edx.gpr(), node);
2860             return;
2861         }
2862     }
2863 #elif CPU(APPLE_ARMV7S) || CPU(ARM_THUMB2)
2864     if (isInt32Constant(node->child2().node())) {
2865         int32_t divisor = valueOfInt32Constant(node->child2().node());
2866         if (divisor > 0 && hasOneBitSet(divisor)) { // If power of 2 then just mask
2867             GPRReg dividendGPR = op1.gpr();
2868             GPRTemporary result(this);
2869             GPRReg resultGPR = result.gpr();
2870
2871             m_jit.assembler().cmp(dividendGPR, ARMThumbImmediate::makeEncodedImm(0));
2872             m_jit.assembler().it(ARMv7Assembler::ConditionLT, false);
2873             m_jit.assembler().neg(resultGPR, dividendGPR);
2874             m_jit.assembler().mov(resultGPR, dividendGPR);
2875             m_jit.and32(TrustedImm32(divisor - 1), resultGPR);
2876             m_jit.assembler().it(ARMv7Assembler::ConditionLT);
2877             m_jit.assembler().neg(resultGPR, resultGPR);
2878
2879             if (!nodeCanIgnoreNegativeZero(node->arithNodeFlags())) {
2880                 // Check that we're not about to create negative zero.
2881                 JITCompiler::Jump numeratorPositive = m_jit.branch32(JITCompiler::GreaterThanOrEqual, dividendGPR, TrustedImm32(0));
2882                 speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::Zero, resultGPR));
2883                 numeratorPositive.link(&m_jit);
2884             }
2885             integerResult(resultGPR, node);
2886             return;
2887         }
2888     }
2889 #endif
2890
2891     SpeculateIntegerOperand op2(this, node->child2());
2892 #if CPU(X86) || CPU(X86_64)
2893     GPRTemporary eax(this, X86Registers::eax);
2894     GPRTemporary edx(this, X86Registers::edx);
2895     GPRReg op1GPR = op1.gpr();
2896     GPRReg op2GPR = op2.gpr();
2897     
2898     GPRReg op2TempGPR;
2899     GPRReg temp;
2900     GPRReg op1SaveGPR;
2901     
2902     if (op2GPR == X86Registers::eax || op2GPR == X86Registers::edx) {
2903         op2TempGPR = allocate();
2904         temp = op2TempGPR;
2905     } else {
2906         op2TempGPR = InvalidGPRReg;
2907         if (op1GPR == X86Registers::eax)
2908             temp = X86Registers::edx;
2909         else
2910             temp = X86Registers::eax;
2911     }
2912     
2913     if (op1GPR == X86Registers::eax || op1GPR == X86Registers::edx) {
2914         op1SaveGPR = allocate();
2915         ASSERT(op1GPR != op1SaveGPR);
2916         m_jit.move(op1GPR, op1SaveGPR);
2917     } else
2918         op1SaveGPR = op1GPR;
2919     
2920     ASSERT(temp != op1GPR);
2921     ASSERT(temp != op2GPR);
2922     ASSERT(op1SaveGPR != X86Registers::eax);
2923     ASSERT(op1SaveGPR != X86Registers::edx);
2924     
2925     m_jit.add32(JITCompiler::TrustedImm32(1), op2GPR, temp);
2926     
2927     JITCompiler::Jump safeDenominator = m_jit.branch32(JITCompiler::Above, temp, JITCompiler::TrustedImm32(1));
2928     
2929     JITCompiler::Jump done;
2930     // FIXME: if the node is not used as number then we can do this more easily.
2931     speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::Zero, op2GPR));
2932     speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branch32(JITCompiler::Equal, op1GPR, TrustedImm32(-2147483647-1)));
2933     
2934     safeDenominator.link(&m_jit);
2935             
2936     if (op2TempGPR != InvalidGPRReg) {
2937         m_jit.move(op2GPR, op2TempGPR);
2938         op2GPR = op2TempGPR;
2939     }
2940             
2941     m_jit.move(op1GPR, eax.gpr());
2942     m_jit.assembler().cdq();
2943     m_jit.assembler().idivl_r(op2GPR);
2944             
2945     if (op2TempGPR != InvalidGPRReg)
2946         unlock(op2TempGPR);
2947
2948     if (!nodeCanIgnoreNegativeZero(node->arithNodeFlags())) {
2949         // Check that we're not about to create negative zero.
2950         JITCompiler::Jump numeratorPositive = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op1SaveGPR, TrustedImm32(0));
2951         speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::Zero, edx.gpr()));
2952         numeratorPositive.link(&m_jit);
2953     }
2954     
2955     if (op1SaveGPR != op1GPR)
2956         unlock(op1SaveGPR);
2957             
2958     integerResult(edx.gpr(), node);
2959
2960 #elif CPU(APPLE_ARMV7S)
2961     GPRTemporary temp(this);
2962     GPRTemporary quotientThenRemainder(this);
2963     GPRTemporary multiplyAnswer(this);
2964     GPRReg dividendGPR = op1.gpr();
2965     GPRReg divisorGPR = op2.gpr();
2966     GPRReg quotientThenRemainderGPR = quotientThenRemainder.gpr();
2967     GPRReg multiplyAnswerGPR = multiplyAnswer.gpr();
2968
2969     m_jit.assembler().sdiv(quotientThenRemainderGPR, dividendGPR, divisorGPR);
2970     speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchMul32(JITCompiler::Overflow, quotientThenRemainderGPR, divisorGPR, multiplyAnswerGPR));
2971     m_jit.assembler().sub(quotientThenRemainderGPR, dividendGPR, multiplyAnswerGPR);
2972
2973     // If the user cares about negative zero, then speculate that we're not about
2974     // to produce negative zero.
2975     if (!nodeCanIgnoreNegativeZero(node->arithNodeFlags())) {
2976         // Check that we're not about to create negative zero.
2977         JITCompiler::Jump numeratorPositive = m_jit.branch32(JITCompiler::GreaterThanOrEqual, dividendGPR, TrustedImm32(0));
2978         speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::Zero, quotientThenRemainderGPR));
2979         numeratorPositive.link(&m_jit);
2980     }
2981
2982     integerResult(quotientThenRemainderGPR, node);
2983 #else // not architecture that can do integer division
2984     // Do this the *safest* way possible: call out to a C function that will do the modulo,
2985     // and then attempt to convert back.
2986     GPRReg op1GPR = op1.gpr();
2987     GPRReg op2GPR = op2.gpr();
2988     
2989     FPRResult result(this);
2990     
2991     flushRegisters();
2992     callOperation(operationFModOnInts, result.fpr(), op1GPR, op2GPR);
2993     
2994     FPRTemporary scratch(this);
2995     GPRTemporary intResult(this);
2996     JITCompiler::JumpList failureCases;
2997     m_jit.branchConvertDoubleToInt32(result.fpr(), intResult.gpr(), failureCases, scratch.fpr(), false);
2998     speculationCheck(Overflow, JSValueRegs(), 0, failureCases);
2999     if (!nodeCanIgnoreNegativeZero(node->arithNodeFlags())) {
3000         // Check that we're not about to create negative zero.
3001         JITCompiler::Jump numeratorPositive = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op1GPR, TrustedImm32(0));
3002         speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branchTest32(JITCompiler::Zero, intResult.gpr()));
3003         numeratorPositive.link(&m_jit);
3004     }
3005     
3006     integerResult(intResult.gpr(), node);
3007 #endif // CPU(X86) || CPU(X86_64)
3008 }
3009
3010 void SpeculativeJIT::compileAdd(Node* node)
3011 {
3012     switch (node->binaryUseKind()) {
3013     case Int32Use: {
3014         if (isNumberConstant(node->child1().node())) {
3015             int32_t imm1 = valueOfInt32Constant(node->child1().node());
3016             SpeculateIntegerOperand op2(this, node->child2());
3017             GPRTemporary result(this);
3018
3019             if (nodeCanTruncateInteger(node->arithNodeFlags())) {
3020                 m_jit.move(op2.gpr(), result.gpr());
3021                 m_jit.add32(Imm32(imm1), result.gpr());
3022             } else
3023                 speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchAdd32(MacroAssembler::Overflow, op2.gpr(), Imm32(imm1), result.gpr()));
3024
3025             integerResult(result.gpr(), node);
3026             return;
3027         }
3028                 
3029         if (isNumberConstant(node->child2().node())) {
3030             SpeculateIntegerOperand op1(this, node->child1());
3031             int32_t imm2 = valueOfInt32Constant(node->child2().node());
3032             GPRTemporary result(this);
3033                 
3034             if (nodeCanTruncateInteger(node->arithNodeFlags())) {
3035                 m_jit.move(op1.gpr(), result.gpr());
3036                 m_jit.add32(Imm32(imm2), result.gpr());
3037             } else
3038                 speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchAdd32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
3039
3040             integerResult(result.gpr(), node);
3041             return;
3042         }
3043                 
3044         SpeculateIntegerOperand op1(this, node->child1());
3045         SpeculateIntegerOperand op2(this, node->child2());
3046         GPRTemporary result(this, op1, op2);
3047
3048         GPRReg gpr1 = op1.gpr();
3049         GPRReg gpr2 = op2.gpr();
3050         GPRReg gprResult = result.gpr();
3051
3052         if (nodeCanTruncateInteger(node->arithNodeFlags())) {
3053             if (gpr1 == gprResult)
3054                 m_jit.add32(gpr2, gprResult);
3055             else {
3056                 m_jit.move(gpr2, gprResult);
3057                 m_jit.add32(gpr1, gprResult);
3058             }
3059         } else {
3060             MacroAssembler::Jump check = m_jit.branchAdd32(MacroAssembler::Overflow, gpr1, gpr2, gprResult);
3061                 
3062             if (gpr1 == gprResult)
3063                 speculationCheck(Overflow, JSValueRegs(), 0, check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr2));
3064             else if (gpr2 == gprResult)
3065                 speculationCheck(Overflow, JSValueRegs(), 0, check, SpeculationRecovery(SpeculativeAdd, gprResult, gpr1));
3066             else
3067                 speculationCheck(Overflow, JSValueRegs(), 0, check);
3068         }
3069
3070         integerResult(gprResult, node);
3071         return;
3072     }
3073     
3074     case NumberUse: {
3075         SpeculateDoubleOperand op1(this, node->child1());
3076         SpeculateDoubleOperand op2(this, node->child2());
3077         FPRTemporary result(this, op1, op2);
3078
3079         FPRReg reg1 = op1.fpr();
3080         FPRReg reg2 = op2.fpr();
3081         m_jit.addDouble(reg1, reg2, result.fpr());
3082
3083         doubleResult(result.fpr(), node);
3084         return;
3085     }
3086         
3087     case UntypedUse: {
3088         RELEASE_ASSERT(node->op() == ValueAdd);
3089         compileValueAdd(node);
3090         return;
3091     }
3092         
3093     default:
3094         RELEASE_ASSERT_NOT_REACHED();
3095         break;
3096     }
3097 }
3098
3099 void SpeculativeJIT::compileMakeRope(Node* node)
3100 {
3101     ASSERT(node->child1().useKind() == KnownStringUse);
3102     ASSERT(node->child2().useKind() == KnownStringUse);
3103     ASSERT(!node->child3() || node->child3().useKind() == KnownStringUse);
3104     
3105     SpeculateCellOperand op1(this, node->child1());
3106     SpeculateCellOperand op2(this, node->child2());
3107     SpeculateCellOperand op3(this, node->child3());
3108     GPRTemporary result(this);
3109     GPRTemporary allocator(this);
3110     GPRTemporary scratch(this);
3111     
3112     GPRReg opGPRs[3];
3113     unsigned numOpGPRs;
3114     opGPRs[0] = op1.gpr();
3115     opGPRs[1] = op2.gpr();
3116     if (node->child3()) {
3117         opGPRs[2] = op3.gpr();
3118         numOpGPRs = 3;
3119     } else {
3120         opGPRs[2] = InvalidGPRReg;
3121         numOpGPRs = 2;
3122     }
3123     GPRReg resultGPR = result.gpr();
3124     GPRReg allocatorGPR = allocator.gpr();
3125     GPRReg scratchGPR = scratch.gpr();
3126     
3127     JITCompiler::JumpList slowPath;
3128     MarkedAllocator& markedAllocator = m_jit.vm()->heap.allocatorForObjectWithImmortalStructureDestructor(sizeof(JSRopeString));
3129     m_jit.move(TrustedImmPtr(&markedAllocator), allocatorGPR);
3130     emitAllocateJSCell(resultGPR, allocatorGPR, TrustedImmPtr(m_jit.vm()->stringStructure.get()), scratchGPR, slowPath);
3131         
3132     m_jit.storePtr(TrustedImmPtr(0), JITCompiler::Address(resultGPR, JSString::offsetOfValue()));
3133     for (unsigned i = 0; i < numOpGPRs; ++i)
3134         m_jit.storePtr(opGPRs[i], JITCompiler::Address(resultGPR, JSRopeString::offsetOfFibers() + sizeof(WriteBarrier<JSString>) * i));
3135     for (unsigned i = numOpGPRs; i < JSRopeString::s_maxInternalRopeLength; ++i)
3136         m_jit.storePtr(TrustedImmPtr(0), JITCompiler::Address(resultGPR, JSRopeString::offsetOfFibers() + sizeof(WriteBarrier<JSString>) * i));
3137     m_jit.load32(JITCompiler::Address(opGPRs[0], JSString::offsetOfFlags()), scratchGPR);
3138     m_jit.load32(JITCompiler::Address(opGPRs[0], JSString::offsetOfLength()), allocatorGPR);
3139     for (unsigned i = 1; i < numOpGPRs; ++i) {
3140         m_jit.and32(JITCompiler::Address(opGPRs[i], JSString::offsetOfFlags()), scratchGPR);
3141         m_jit.add32(JITCompiler::Address(opGPRs[i], JSString::offsetOfLength()), allocatorGPR);
3142     }
3143     m_jit.and32(JITCompiler::TrustedImm32(JSString::Is8Bit), scratchGPR);
3144     m_jit.store32(scratchGPR, JITCompiler::Address(resultGPR, JSString::offsetOfFlags()));
3145     m_jit.store32(allocatorGPR, JITCompiler::Address(resultGPR, JSString::offsetOfLength()));
3146     
3147     switch (numOpGPRs) {
3148     case 2:
3149         addSlowPathGenerator(slowPathCall(
3150             slowPath, this, operationMakeRope2, resultGPR, opGPRs[0], opGPRs[1]));
3151         break;
3152     case 3:
3153         addSlowPathGenerator(slowPathCall(
3154             slowPath, this, operationMakeRope3, resultGPR, opGPRs[0], opGPRs[1], opGPRs[2]));
3155         break;
3156     default:
3157         RELEASE_ASSERT_NOT_REACHED();
3158         break;
3159     }
3160         
3161     cellResult(resultGPR, node);
3162 }
3163
3164 void SpeculativeJIT::compileArithSub(Node* node)
3165 {
3166     switch (node->binaryUseKind()) {
3167     case Int32Use: {
3168         if (isNumberConstant(node->child2().node())) {
3169             SpeculateIntegerOperand op1(this, node->child1());
3170             int32_t imm2 = valueOfInt32Constant(node->child2().node());
3171             GPRTemporary result(this);
3172
3173             if (nodeCanTruncateInteger(node->arithNodeFlags())) {
3174                 m_jit.move(op1.gpr(), result.gpr());
3175                 m_jit.sub32(Imm32(imm2), result.gpr());
3176             } else {
3177 #if ENABLE(JIT_CONSTANT_BLINDING)
3178                 GPRTemporary scratch(this);
3179                 speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr(), scratch.gpr()));
3180 #else
3181                 speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), Imm32(imm2), result.gpr()));
3182 #endif
3183             }
3184
3185             integerResult(result.gpr(), node);
3186             return;
3187         }
3188             
3189         if (isNumberConstant(node->child1().node())) {
3190             int32_t imm1 = valueOfInt32Constant(node->child1().node());
3191             SpeculateIntegerOperand op2(this, node->child2());
3192             GPRTemporary result(this);
3193                 
3194             m_jit.move(Imm32(imm1), result.gpr());
3195             if (nodeCanTruncateInteger(node->arithNodeFlags()))
3196                 m_jit.sub32(op2.gpr(), result.gpr());
3197             else
3198                 speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchSub32(MacroAssembler::Overflow, op2.gpr(), result.gpr()));
3199                 
3200             integerResult(result.gpr(), node);
3201             return;
3202         }
3203             
3204         SpeculateIntegerOperand op1(this, node->child1());
3205         SpeculateIntegerOperand op2(this, node->child2());
3206         GPRTemporary result(this);
3207
3208         if (nodeCanTruncateInteger(node->arithNodeFlags())) {
3209             m_jit.move(op1.gpr(), result.gpr());
3210             m_jit.sub32(op2.gpr(), result.gpr());
3211         } else
3212             speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchSub32(MacroAssembler::Overflow, op1.gpr(), op2.gpr(), result.gpr()));
3213
3214         integerResult(result.gpr(), node);
3215         return;
3216     }
3217         
3218     case NumberUse: {
3219         SpeculateDoubleOperand op1(this, node->child1());
3220         SpeculateDoubleOperand op2(this, node->child2());
3221         FPRTemporary result(this, op1);
3222
3223         FPRReg reg1 = op1.fpr();
3224         FPRReg reg2 = op2.fpr();
3225         m_jit.subDouble(reg1, reg2, result.fpr());
3226
3227         doubleResult(result.fpr(), node);
3228         return;
3229     }
3230         
3231     default:
3232         RELEASE_ASSERT_NOT_REACHED();
3233         return;
3234     }
3235 }
3236
3237 void SpeculativeJIT::compileArithNegate(Node* node)
3238 {
3239     switch (node->child1().useKind()) {
3240     case Int32Use: {
3241         SpeculateIntegerOperand op1(this, node->child1());
3242         GPRTemporary result(this);
3243
3244         m_jit.move(op1.gpr(), result.gpr());
3245
3246         if (nodeCanTruncateInteger(node->arithNodeFlags()))
3247             m_jit.neg32(result.gpr());
3248         else {
3249             speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branchNeg32(MacroAssembler::Overflow, result.gpr()));
3250             if (!nodeCanIgnoreNegativeZero(node->arithNodeFlags()))
3251                 speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branchTest32(MacroAssembler::Zero, result.gpr()));
3252         }
3253
3254         integerResult(result.gpr(), node);
3255         return;
3256     }
3257         
3258     case NumberUse: {
3259         SpeculateDoubleOperand op1(this, node->child1());
3260         FPRTemporary result(this);
3261         
3262         m_jit.negateDouble(op1.fpr(), result.fpr());
3263         
3264         doubleResult(result.fpr(), node);
3265         return;
3266     }
3267         
3268     default:
3269         RELEASE_ASSERT_NOT_REACHED();
3270         return;
3271     }
3272 }
3273 void SpeculativeJIT::compileArithIMul(Node* node)
3274 {
3275     SpeculateIntegerOperand op1(this, node->child1());
3276     SpeculateIntegerOperand op2(this, node->child2());
3277     GPRTemporary result(this);
3278
3279     GPRReg reg1 = op1.gpr();
3280     GPRReg reg2 = op2.gpr();
3281
3282     m_jit.move(reg1, result.gpr());
3283     m_jit.mul32(reg2, result.gpr());
3284     integerResult(result.gpr(), node);
3285     return;
3286 }
3287
3288 void SpeculativeJIT::compileArithMul(Node* node)
3289 {
3290     switch (node->binaryUseKind()) {
3291     case Int32Use: {
3292         SpeculateIntegerOperand op1(this, node->child1());
3293         SpeculateIntegerOperand op2(this, node->child2());
3294         GPRTemporary result(this);
3295
3296         GPRReg reg1 = op1.gpr();
3297         GPRReg reg2 = op2.gpr();
3298
3299         // We can perform truncated multiplications if we get to this point, because if the
3300         // fixup phase could not prove that it would be safe, it would have turned us into
3301         // a double multiplication.
3302         if (nodeCanTruncateInteger(node->arithNodeFlags())) {
3303             m_jit.move(reg1, result.gpr());
3304             m_jit.mul32(reg2, result.gpr());
3305         } else {
3306             speculationCheck(
3307                 Overflow, JSValueRegs(), 0,
3308                 m_jit.branchMul32(MacroAssembler::Overflow, reg1, reg2, result.gpr()));
3309         }