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