Enable the DFG JIT on x86-64 Linux platforms
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGSpeculativeJIT.cpp
1 /*
2  * Copyright (C) 2011 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27
28 #include "DFGSpeculativeJIT.h"
29 #include "JSByteArray.h"
30
31 #if ENABLE(DFG_JIT)
32
33 #if USE(JSVALUE32_64)
34 #include "DFGJITCompilerInlineMethods.h"
35 #endif
36
37 namespace JSC { namespace DFG {
38
39 #ifndef NDEBUG
40 void ValueSource::dump(FILE* out) const
41 {
42     switch (kind()) {
43     case SourceNotSet:
44         fprintf(out, "NotSet");
45         break;
46     case ValueInRegisterFile:
47         fprintf(out, "InRegFile");
48         break;
49     case Int32InRegisterFile:
50         fprintf(out, "Int32");
51         break;
52     case CellInRegisterFile:
53         fprintf(out, "Cell");
54         break;
55     case BooleanInRegisterFile:
56         fprintf(out, "Bool");
57         break;
58     case HaveNode:
59         fprintf(out, "Node(%d)", m_nodeIndex);
60         break;
61     }
62 }
63 #endif
64
65 OSRExit::OSRExit(JSValueSource jsValueSource, ValueProfile* valueProfile, MacroAssembler::Jump check, SpeculativeJIT* jit, unsigned recoveryIndex)
66     : m_jsValueSource(jsValueSource)
67     , m_valueProfile(valueProfile)
68     , m_check(check)
69     , m_nodeIndex(jit->m_compileIndex)
70     , m_codeOrigin(jit->m_codeOriginForOSR)
71     , m_recoveryIndex(recoveryIndex)
72     , m_arguments(jit->m_arguments.size())
73     , m_variables(jit->m_variables.size())
74     , m_lastSetOperand(jit->m_lastSetOperand)
75 {
76     ASSERT(m_codeOrigin.isSet());
77     for (unsigned argument = 0; argument < m_arguments.size(); ++argument)
78         m_arguments[argument] = jit->computeValueRecoveryFor(jit->m_arguments[argument]);
79     for (unsigned variable = 0; variable < m_variables.size(); ++variable)
80         m_variables[variable] = jit->computeValueRecoveryFor(jit->m_variables[variable]);
81 }
82
83 #ifndef NDEBUG
84 void OSRExit::dump(FILE* out) const
85 {
86     for (unsigned argument = 0; argument < m_arguments.size(); ++argument)
87         m_arguments[argument].dump(out);
88     fprintf(out, " : ");
89     for (unsigned variable = 0; variable < m_variables.size(); ++variable)
90         m_variables[variable].dump(out);
91 }
92 #endif
93
94 void SpeculativeJIT::compilePeepHoleDoubleBranch(Node& node, NodeIndex branchNodeIndex, JITCompiler::DoubleCondition condition)
95 {
96     Node& branchNode = at(branchNodeIndex);
97     BlockIndex taken = branchNode.takenBlockIndex();
98     BlockIndex notTaken = branchNode.notTakenBlockIndex();
99     
100     SpeculateDoubleOperand op1(this, node.child1());
101     SpeculateDoubleOperand op2(this, node.child2());
102     
103     addBranch(m_jit.branchDouble(condition, op1.fpr(), op2.fpr()), taken);
104     
105     if (notTaken != (m_block + 1))
106         addBranch(m_jit.jump(), notTaken);
107 }
108
109 void SpeculativeJIT::compilePeepHoleObjectEquality(Node& node, NodeIndex branchNodeIndex, void* vptr, PredictionChecker predictionCheck)
110 {
111     Node& branchNode = at(branchNodeIndex);
112     BlockIndex taken = branchNode.takenBlockIndex();
113     BlockIndex notTaken = branchNode.notTakenBlockIndex();
114
115     MacroAssembler::RelationalCondition condition = MacroAssembler::Equal;
116     
117     if (taken == (m_block + 1)) {
118         condition = MacroAssembler::NotEqual;
119         BlockIndex tmp = taken;
120         taken = notTaken;
121         notTaken = tmp;
122     }
123
124     SpeculateCellOperand op1(this, node.child1());
125     SpeculateCellOperand op2(this, node.child2());
126     
127     GPRReg op1GPR = op1.gpr();
128     GPRReg op2GPR = op2.gpr();
129     
130     if (!predictionCheck(m_state.forNode(node.child1()).m_type))
131         speculationCheck(JSValueSource::unboxedCell(op1GPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR), MacroAssembler::TrustedImmPtr(vptr)));
132     if (!predictionCheck(m_state.forNode(node.child2()).m_type))
133         speculationCheck(JSValueSource::unboxedCell(op2GPR), node.child2(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR), MacroAssembler::TrustedImmPtr(vptr)));
134     
135     addBranch(m_jit.branchPtr(condition, op1GPR, op2GPR), taken);
136     if (notTaken != (m_block + 1))
137         addBranch(m_jit.jump(), notTaken);
138 }
139
140 void SpeculativeJIT::compilePeepHoleIntegerBranch(Node& node, NodeIndex branchNodeIndex, JITCompiler::RelationalCondition condition)
141 {
142     Node& branchNode = at(branchNodeIndex);
143     BlockIndex taken = branchNode.takenBlockIndex();
144     BlockIndex notTaken = branchNode.notTakenBlockIndex();
145
146     // The branch instruction will branch to the taken block.
147     // If taken is next, switch taken with notTaken & invert the branch condition so we can fall through.
148     if (taken == (m_block + 1)) {
149         condition = JITCompiler::invert(condition);
150         BlockIndex tmp = taken;
151         taken = notTaken;
152         notTaken = tmp;
153     }
154
155     if (isInt32Constant(node.child1())) {
156         int32_t imm = valueOfInt32Constant(node.child1());
157         SpeculateIntegerOperand op2(this, node.child2());
158         addBranch(m_jit.branch32(condition, JITCompiler::Imm32(imm), op2.gpr()), taken);
159     } else if (isInt32Constant(node.child2())) {
160         SpeculateIntegerOperand op1(this, node.child1());
161         int32_t imm = valueOfInt32Constant(node.child2());
162         addBranch(m_jit.branch32(condition, op1.gpr(), JITCompiler::Imm32(imm)), taken);
163     } else {
164         SpeculateIntegerOperand op1(this, node.child1());
165         SpeculateIntegerOperand op2(this, node.child2());
166         addBranch(m_jit.branch32(condition, op1.gpr(), op2.gpr()), taken);
167     }
168
169     // Check for fall through, otherwise we need to jump.
170     if (notTaken != (m_block + 1))
171         addBranch(m_jit.jump(), notTaken);
172 }
173
174 // Returns true if the compare is fused with a subsequent branch.
175 bool SpeculativeJIT::compilePeepHoleBranch(Node& node, MacroAssembler::RelationalCondition condition, MacroAssembler::DoubleCondition doubleCondition, S_DFGOperation_EJJ operation)
176 {
177     // Fused compare & branch.
178     NodeIndex branchNodeIndex = detectPeepHoleBranch();
179     if (branchNodeIndex != NoNode) {
180         // detectPeepHoleBranch currently only permits the branch to be the very next node,
181         // so can be no intervening nodes to also reference the compare. 
182         ASSERT(node.adjustedRefCount() == 1);
183
184         if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2()))) {
185             compilePeepHoleIntegerBranch(node, branchNodeIndex, condition);
186             use(node.child1());
187             use(node.child2());
188         } else if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2()))) {
189             compilePeepHoleDoubleBranch(node, branchNodeIndex, doubleCondition);
190             use(node.child1());
191             use(node.child2());
192         } else if (node.op == CompareEq && Node::shouldSpeculateFinalObject(at(node.child1()), at(node.child2()))) {
193             compilePeepHoleObjectEquality(node, branchNodeIndex, m_jit.globalData()->jsFinalObjectVPtr, isFinalObjectPrediction);
194             use(node.child1());
195             use(node.child2());
196         } else if (node.op == CompareEq && Node::shouldSpeculateArray(at(node.child1()), at(node.child2()))) {
197             compilePeepHoleObjectEquality(node, branchNodeIndex, m_jit.globalData()->jsArrayVPtr, isArrayPrediction);
198             use(node.child1());
199             use(node.child2());
200         } else
201             nonSpeculativePeepholeBranch(node, branchNodeIndex, condition, operation);
202
203         m_compileIndex = branchNodeIndex;
204         return true;
205     }
206     return false;
207 }
208
209 void SpeculativeJIT::compileMovHint(Node& node)
210 {
211     ASSERT(node.op == SetLocal);
212     
213     setNodeIndexForOperand(node.child1(), node.local());
214     m_lastSetOperand = node.local();
215 }
216
217 void SpeculativeJIT::compile(BasicBlock& block)
218 {
219     ASSERT(m_compileOkay);
220     ASSERT(m_compileIndex == block.begin);
221     
222     if (!block.isReachable) {
223         m_compileIndex = block.end;
224         return;
225     }
226
227     m_blockHeads[m_block] = m_jit.label();
228 #if DFG_ENABLE(JIT_BREAK_ON_EVERY_BLOCK)
229     m_jit.breakpoint();
230 #endif
231
232     ASSERT(m_arguments.size() == block.variablesAtHead.numberOfArguments());
233     for (size_t i = 0; i < m_arguments.size(); ++i) {
234         NodeIndex nodeIndex = block.variablesAtHead.argument(i);
235         if (nodeIndex == NoNode)
236             m_arguments[i] = ValueSource(ValueInRegisterFile);
237         else
238             m_arguments[i] = ValueSource::forPrediction(at(nodeIndex).variableAccessData()->prediction());
239     }
240     
241     m_state.reset();
242     m_state.beginBasicBlock(&block);
243     
244     ASSERT(m_variables.size() == block.variablesAtHead.numberOfLocals());
245     for (size_t i = 0; i < m_variables.size(); ++i) {
246         NodeIndex nodeIndex = block.variablesAtHead.local(i);
247         if (nodeIndex == NoNode)
248             m_variables[i] = ValueSource(ValueInRegisterFile);
249         else
250             m_variables[i] = ValueSource::forPrediction(at(nodeIndex).variableAccessData()->prediction());
251     }
252     
253     m_lastSetOperand = std::numeric_limits<int>::max();
254     m_codeOriginForOSR = CodeOrigin();
255
256     for (; m_compileIndex < block.end; ++m_compileIndex) {
257         Node& node = at(m_compileIndex);
258         m_codeOriginForOSR = node.codeOrigin;
259         if (!node.shouldGenerate()) {
260 #if DFG_ENABLE(DEBUG_VERBOSE)
261             fprintf(stderr, "SpeculativeJIT skipping Node @%d (bc#%u) at JIT offset 0x%x     ", (int)m_compileIndex, node.codeOrigin.bytecodeIndex, m_jit.debugOffset());
262 #endif
263             switch (node.op) {
264             case SetLocal:
265                 compileMovHint(node);
266                 break;
267
268             case InlineStart: {
269                 InlineCallFrame* inlineCallFrame = node.codeOrigin.inlineCallFrame;
270                 unsigned argumentsStart = inlineCallFrame->stackOffset - RegisterFile::CallFrameHeaderSize - inlineCallFrame->arguments.size();
271                 for (unsigned i = 0; i < inlineCallFrame->arguments.size(); ++i) {
272                     ValueRecovery recovery = computeValueRecoveryFor(m_variables[argumentsStart + i]);
273                     // The recovery cannot point to registers, since the call frame reification isn't
274                     // as smart as OSR, so it can't handle that. The exception is the this argument,
275                     // which we don't really need to be able to recover.
276                     ASSERT(!i || !recovery.isInRegisters());
277                     inlineCallFrame->arguments[i] = recovery;
278                 }
279                 break;
280             }
281                 
282             default:
283                 break;
284             }
285         } else {
286             
287 #if DFG_ENABLE(DEBUG_VERBOSE)
288             fprintf(stderr, "SpeculativeJIT generating Node @%d (bc#%u) at JIT offset 0x%x   ", (int)m_compileIndex, node.codeOrigin.bytecodeIndex, m_jit.debugOffset());
289 #endif
290 #if DFG_ENABLE(JIT_BREAK_ON_EVERY_NODE)
291             m_jit.breakpoint();
292 #endif
293             checkConsistency();
294             compile(node);
295             if (!m_compileOkay) {
296                 m_compileOkay = true;
297                 m_compileIndex = block.end;
298                 clearGenerationInfo();
299                 return;
300             }
301             
302 #if DFG_ENABLE(DEBUG_VERBOSE)
303             if (node.hasResult()) {
304                 GenerationInfo& info = m_generationInfo[node.virtualRegister()];
305                 fprintf(stderr, "-> %s, vr#%d", dataFormatToString(info.registerFormat()), (int)node.virtualRegister());
306                 if (info.registerFormat() != DataFormatNone) {
307                     if (info.registerFormat() == DataFormatDouble)
308                         fprintf(stderr, ", %s", FPRInfo::debugName(info.fpr()));
309 #if USE(JSVALUE32_64)
310                     else if (info.registerFormat() & DataFormatJS)
311                         fprintf(stderr, ", %s %s", GPRInfo::debugName(info.tagGPR()), GPRInfo::debugName(info.payloadGPR()));
312 #endif
313                     else
314                         fprintf(stderr, ", %s", GPRInfo::debugName(info.gpr()));
315                 }
316                 fprintf(stderr, "    ");
317             } else
318                 fprintf(stderr, "    ");
319 #endif
320         }
321         
322 #if DFG_ENABLE(VERBOSE_VALUE_RECOVERIES)
323         for (int operand = -m_arguments.size() - RegisterFile::CallFrameHeaderSize; operand < -RegisterFile::CallFrameHeaderSize; ++operand)
324             computeValueRecoveryFor(operand).dump(stderr);
325         
326         fprintf(stderr, " : ");
327         
328         for (int operand = 0; operand < (int)m_variables.size(); ++operand)
329             computeValueRecoveryFor(operand).dump(stderr);
330 #endif
331
332 #if DFG_ENABLE(DEBUG_VERBOSE)
333         fprintf(stderr, "\n");
334 #endif
335         
336         // Make sure that the abstract state is rematerialized for the next node.
337         m_state.execute(m_compileIndex);
338         
339         if (node.shouldGenerate())
340             checkConsistency();
341     }
342 }
343
344 // If we are making type predictions about our arguments then
345 // we need to check that they are correct on function entry.
346 void SpeculativeJIT::checkArgumentTypes()
347 {
348     ASSERT(!m_compileIndex);
349     m_codeOriginForOSR = CodeOrigin(0);
350
351     for (size_t i = 0; i < m_arguments.size(); ++i)
352         m_arguments[i] = ValueSource(ValueInRegisterFile);
353     for (size_t i = 0; i < m_variables.size(); ++i)
354         m_variables[i] = ValueSource(ValueInRegisterFile);
355     
356     for (int i = 0; i < m_jit.codeBlock()->m_numParameters; ++i) {
357         VirtualRegister virtualRegister = (VirtualRegister)(m_jit.codeBlock()->thisRegister() + i);
358         PredictedType predictedType = at(m_jit.graph().m_arguments[i]).variableAccessData()->prediction();
359 #if USE(JSVALUE64)
360         if (isInt32Prediction(predictedType))
361             speculationCheck(JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::Below, JITCompiler::addressFor(virtualRegister), GPRInfo::tagTypeNumberRegister));
362         else if (isArrayPrediction(predictedType)) {
363             GPRTemporary temp(this);
364             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
365             speculationCheck(JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
366             speculationCheck(JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
367         } else if (isByteArrayPrediction(predictedType)) {
368             GPRTemporary temp(this);
369             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
370             speculationCheck(JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister));
371             speculationCheck(JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsByteArrayVPtr)));
372         } else if (isBooleanPrediction(predictedType)) {
373             GPRTemporary temp(this);
374             m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr());
375             m_jit.xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), temp.gpr());
376             speculationCheck(JSValueRegs(), NoNode, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
377         }
378 #else
379         if (isInt32Prediction(predictedType))
380             speculationCheck(JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag)));
381         else if (isArrayPrediction(predictedType)) {
382             GPRTemporary temp(this);
383             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
384             speculationCheck(JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
385             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
386             speculationCheck(JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
387         } else if (isByteArrayPrediction(predictedType)) {
388             GPRTemporary temp(this);
389             m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr());
390             speculationCheck(JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag)));
391             m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr());
392             speculationCheck(JSValueRegs(), NoNode, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsByteArrayVPtr)));
393         } else if (isBooleanPrediction(predictedType))
394             speculationCheck(JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::BooleanTag)));
395 #endif
396     }
397 }
398
399 bool SpeculativeJIT::compile()
400 {
401     checkArgumentTypes();
402
403     ASSERT(!m_compileIndex);
404     for (m_block = 0; m_block < m_jit.graph().m_blocks.size(); ++m_block)
405         compile(*m_jit.graph().m_blocks[m_block]);
406     linkBranches();
407     return true;
408 }
409
410 void SpeculativeJIT::linkOSREntries(LinkBuffer& linkBuffer)
411 {
412     for (BlockIndex blockIndex = 0; blockIndex < m_jit.graph().m_blocks.size(); ++blockIndex) {
413         BasicBlock& block = *m_jit.graph().m_blocks[blockIndex];
414         if (block.isOSRTarget)
415             m_jit.noticeOSREntry(block, m_blockHeads[blockIndex], linkBuffer);
416     }
417 }
418
419 ValueRecovery SpeculativeJIT::computeValueRecoveryFor(const ValueSource& valueSource)
420 {
421     switch (valueSource.kind()) {
422     case ValueInRegisterFile:
423         return ValueRecovery::alreadyInRegisterFile();
424         
425     case Int32InRegisterFile:
426         return ValueRecovery::alreadyInRegisterFileAsUnboxedInt32();
427
428     case CellInRegisterFile:
429         return ValueRecovery::alreadyInRegisterFileAsUnboxedCell();
430
431     case BooleanInRegisterFile:
432         return ValueRecovery::alreadyInRegisterFileAsUnboxedBoolean();
433
434     case HaveNode: {
435         if (m_jit.isConstant(valueSource.nodeIndex()))
436             return ValueRecovery::constant(m_jit.valueOfJSConstant(valueSource.nodeIndex()));
437     
438         Node* nodePtr = &at(valueSource.nodeIndex());
439         if (!nodePtr->shouldGenerate()) {
440             // It's legitimately dead. As in, nobody will ever use this node, or operand,
441             // ever. Set it to Undefined to make the GC happy after the OSR.
442             return ValueRecovery::constant(jsUndefined());
443         }
444     
445         GenerationInfo* infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
446         if (!infoPtr->alive() || infoPtr->nodeIndex() != valueSource.nodeIndex()) {
447             // Try to see if there is an alternate node that would contain the value we want.
448             // There are four possibilities:
449             //
450             // ValueToNumber: If the only live version of the value is a ValueToNumber node
451             //    then it means that all remaining uses of the value would have performed a
452             //    ValueToNumber conversion anyway. Thus, we can substitute ValueToNumber.
453             //
454             // ValueToInt32: Likewise, if the only remaining live version of the value is
455             //    ValueToInt32, then we can use it. But if there is both a ValueToInt32
456             //    and a ValueToNumber, then we better go with ValueToNumber because it
457             //    means that some remaining uses would have converted to number while
458             //    others would have converted to Int32.
459             //
460             // UInt32ToNumber: If the only live version of the value is a UInt32ToNumber
461             //    then the only remaining uses are ones that want a properly formed number
462             //    rather than a UInt32 intermediate.
463             //
464             // The reverse of the above: This node could be a UInt32ToNumber, but its
465             //    alternative is still alive. This means that the only remaining uses of
466             //    the number would be fine with a UInt32 intermediate.
467         
468             bool found = false;
469         
470             if (nodePtr->op == UInt32ToNumber) {
471                 NodeIndex nodeIndex = nodePtr->child1();
472                 nodePtr = &at(nodeIndex);
473                 infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
474                 if (infoPtr->alive() && infoPtr->nodeIndex() == nodeIndex)
475                     found = true;
476             }
477         
478             if (!found) {
479                 NodeIndex valueToNumberIndex = NoNode;
480                 NodeIndex valueToInt32Index = NoNode;
481                 NodeIndex uint32ToNumberIndex = NoNode;
482             
483                 for (unsigned virtualRegister = 0; virtualRegister < m_generationInfo.size(); ++virtualRegister) {
484                     GenerationInfo& info = m_generationInfo[virtualRegister];
485                     if (!info.alive())
486                         continue;
487                     if (info.nodeIndex() == NoNode)
488                         continue;
489                     Node& node = at(info.nodeIndex());
490                     if (node.child1Unchecked() != valueSource.nodeIndex())
491                         continue;
492                     switch (node.op) {
493                     case ValueToNumber:
494                     case ValueToDouble:
495                         valueToNumberIndex = info.nodeIndex();
496                         break;
497                     case ValueToInt32:
498                         valueToInt32Index = info.nodeIndex();
499                         break;
500                     case UInt32ToNumber:
501                         uint32ToNumberIndex = info.nodeIndex();
502                         break;
503                     default:
504                         break;
505                     }
506                 }
507             
508                 NodeIndex nodeIndexToUse;
509                 if (valueToNumberIndex != NoNode)
510                     nodeIndexToUse = valueToNumberIndex;
511                 else if (valueToInt32Index != NoNode)
512                     nodeIndexToUse = valueToInt32Index;
513                 else if (uint32ToNumberIndex != NoNode)
514                     nodeIndexToUse = uint32ToNumberIndex;
515                 else
516                     nodeIndexToUse = NoNode;
517             
518                 if (nodeIndexToUse != NoNode) {
519                     nodePtr = &at(nodeIndexToUse);
520                     infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
521                     ASSERT(infoPtr->alive() && infoPtr->nodeIndex() == nodeIndexToUse);
522                     found = true;
523                 }
524             }
525         
526             if (!found)
527                 return ValueRecovery::constant(jsUndefined());
528         }
529     
530         ASSERT(infoPtr->alive());
531
532         if (infoPtr->registerFormat() != DataFormatNone) {
533             if (infoPtr->registerFormat() == DataFormatDouble)
534                 return ValueRecovery::inFPR(infoPtr->fpr());
535 #if USE(JSVALUE32_64)
536             if (infoPtr->registerFormat() & DataFormatJS)
537                 return ValueRecovery::inPair(infoPtr->tagGPR(), infoPtr->payloadGPR());
538 #endif
539             return ValueRecovery::inGPR(infoPtr->gpr(), infoPtr->registerFormat());
540         }
541         if (infoPtr->spillFormat() != DataFormatNone)
542             return ValueRecovery::displacedInRegisterFile(static_cast<VirtualRegister>(nodePtr->virtualRegister()), infoPtr->spillFormat());
543     
544         ASSERT_NOT_REACHED();
545         return ValueRecovery();
546     }
547         
548     default:
549         ASSERT_NOT_REACHED();
550         return ValueRecovery();
551     }
552 }
553
554 void SpeculativeJIT::compileGetCharCodeAt(Node& node)
555 {
556     ASSERT(node.child3() == NoNode);
557     SpeculateCellOperand string(this, node.child1());
558     SpeculateStrictInt32Operand index(this, node.child2());
559
560     GPRReg stringReg = string.gpr();
561     GPRReg indexReg = index.gpr();
562
563     if (!isStringPrediction(m_state.forNode(node.child1()).m_type))
564         speculationCheck(JSValueSource::unboxedCell(stringReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(stringReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsStringVPtr)));
565
566     // unsigned comparison so we can filter out negative indices and indices that are too large
567     speculationCheck(JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, indexReg, MacroAssembler::Address(stringReg, JSString::offsetOfLength())));
568
569     GPRTemporary scratch(this);
570     GPRReg scratchReg = scratch.gpr();
571
572     m_jit.loadPtr(MacroAssembler::Address(stringReg, JSString::offsetOfValue()), scratchReg);
573
574     // Speculate that we're not accessing a rope
575     speculationCheck(JSValueRegs(), NoNode, m_jit.branchTest32(MacroAssembler::Zero, scratchReg));
576
577     // Load the character into scratchReg
578     JITCompiler::Jump is16Bit = m_jit.branchTest32(MacroAssembler::Zero, MacroAssembler::Address(scratchReg, StringImpl::flagsOffset()), TrustedImm32(StringImpl::flagIs8Bit()));
579
580     m_jit.loadPtr(MacroAssembler::Address(scratchReg, StringImpl::dataOffset()), scratchReg);
581     m_jit.load8(MacroAssembler::BaseIndex(scratchReg, indexReg, MacroAssembler::TimesOne, 0), scratchReg);
582     JITCompiler::Jump cont8Bit = m_jit.jump();
583
584     is16Bit.link(&m_jit);
585
586     m_jit.loadPtr(MacroAssembler::Address(scratchReg, StringImpl::dataOffset()), scratchReg);
587     m_jit.load16(MacroAssembler::BaseIndex(scratchReg, indexReg, MacroAssembler::TimesTwo, 0), scratchReg);
588
589     cont8Bit.link(&m_jit);
590
591     integerResult(scratchReg, m_compileIndex);
592 }
593
594 void SpeculativeJIT::compileGetByValOnString(Node& node)
595 {
596     ASSERT(node.child3() == NoNode);
597     SpeculateCellOperand base(this, node.child1());
598     SpeculateStrictInt32Operand property(this, node.child2());
599
600     GPRReg baseReg = base.gpr();
601     GPRReg propertyReg = property.gpr();
602
603     if (!isStringPrediction(m_state.forNode(node.child1()).m_type))
604         speculationCheck(JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsStringVPtr)));
605
606     // unsigned comparison so we can filter out negative indices and indices that are too large
607     speculationCheck(JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSString::offsetOfLength())));
608
609     GPRTemporary scratch(this);
610     GPRReg scratchReg = scratch.gpr();
611
612     m_jit.loadPtr(MacroAssembler::Address(baseReg, JSString::offsetOfValue()), scratchReg);
613
614     // Speculate that we're not accessing a rope
615     speculationCheck(JSValueRegs(), NoNode, m_jit.branchTest32(MacroAssembler::Zero, scratchReg));
616
617     // Load the character into scratchReg
618     JITCompiler::Jump is16Bit = m_jit.branchTest32(MacroAssembler::Zero, MacroAssembler::Address(scratchReg, StringImpl::flagsOffset()), TrustedImm32(StringImpl::flagIs8Bit()));
619
620     m_jit.loadPtr(MacroAssembler::Address(scratchReg, StringImpl::dataOffset()), scratchReg);
621     m_jit.load8(MacroAssembler::BaseIndex(scratchReg, propertyReg, MacroAssembler::TimesOne, 0), scratchReg);
622     JITCompiler::Jump cont8Bit = m_jit.jump();
623
624     is16Bit.link(&m_jit);
625
626     m_jit.loadPtr(MacroAssembler::Address(scratchReg, StringImpl::dataOffset()), scratchReg);
627     m_jit.load16(MacroAssembler::BaseIndex(scratchReg, propertyReg, MacroAssembler::TimesTwo, 0), scratchReg);
628
629     // We only support ascii characters
630     speculationCheck(JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, scratchReg, TrustedImm32(0x100)));
631
632     // 8 bit string values don't need the isASCII check.
633     cont8Bit.link(&m_jit);
634
635     GPRTemporary smallStrings(this);
636     GPRReg smallStringsReg = smallStrings.gpr();
637     m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.globalData()->smallStrings.singleCharacterStrings()), smallStringsReg);
638     m_jit.loadPtr(MacroAssembler::BaseIndex(smallStringsReg, scratchReg, MacroAssembler::ScalePtr, 0), scratchReg);
639     speculationCheck(JSValueRegs(), NoNode, m_jit.branchTest32(MacroAssembler::Zero, scratchReg));
640     cellResult(scratchReg, m_compileIndex);
641 }
642
643 void SpeculativeJIT::compileValueToInt32(Node& node)
644 {
645     if (at(node.child1()).shouldNotSpeculateInteger()) {
646         if (at(node.child1()).shouldSpeculateDouble()) {
647             SpeculateDoubleOperand op1(this, node.child1());
648             GPRTemporary result(this);
649             FPRReg fpr = op1.fpr();
650             GPRReg gpr = result.gpr();
651             JITCompiler::Jump truncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateSuccessful);
652             
653             silentSpillAllRegisters(gpr);
654             callOperation(toInt32, gpr, fpr);
655             silentFillAllRegisters(gpr);
656             
657             truncatedToInteger.link(&m_jit);
658             integerResult(gpr, m_compileIndex);
659             return;
660         }
661         // Do it the safe way.
662         nonSpeculativeValueToInt32(node);
663         return;
664     }
665     
666     SpeculateIntegerOperand op1(this, node.child1());
667     GPRTemporary result(this, op1);
668     m_jit.move(op1.gpr(), result.gpr());
669     integerResult(result.gpr(), m_compileIndex, op1.format());
670 }
671
672 static void compileClampDoubleToByte(JITCompiler& jit, GPRReg result, FPRReg source, FPRReg scratch)
673 {
674     // Unordered compare so we pick up NaN
675     static const double zero = 0;
676     static const double byteMax = 255;
677     static const double half = 0.5;
678     jit.loadDouble(&zero, scratch);
679     MacroAssembler::Jump tooSmall = jit.branchDouble(MacroAssembler::DoubleLessThanOrEqualOrUnordered, source, scratch);
680     jit.loadDouble(&byteMax, scratch);
681     MacroAssembler::Jump tooBig = jit.branchDouble(MacroAssembler::DoubleGreaterThan, source, scratch);
682     
683     jit.loadDouble(&half, scratch);
684     jit.addDouble(source, scratch);
685     jit.truncateDoubleToInt32(scratch, result);   
686     MacroAssembler::Jump truncatedInt = jit.jump();
687     
688     tooSmall.link(&jit);
689     jit.xorPtr(result, result);
690     MacroAssembler::Jump zeroed = jit.jump();
691     
692     tooBig.link(&jit);
693     jit.move(JITCompiler::TrustedImm32(255), result);
694     
695     truncatedInt.link(&jit);
696     zeroed.link(&jit);
697
698 }
699
700 void SpeculativeJIT::compilePutByValForByteArray(GPRReg base, GPRReg property, Node& node)
701 {
702     NodeIndex baseIndex = node.child1();
703     NodeIndex valueIndex = node.child3();
704     
705     if (!isByteArrayPrediction(m_state.forNode(baseIndex).m_type))
706         speculationCheck(JSValueSource::unboxedCell(base), baseIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsByteArrayVPtr)));
707     GPRTemporary value;
708     GPRReg valueGPR;
709
710     if (at(valueIndex).isConstant()) {
711         JSValue jsValue = valueOfJSConstant(valueIndex);
712         if (!jsValue.isNumber()) {
713             terminateSpeculativeExecution(JSValueRegs(), NoNode);
714             noResult(m_compileIndex);
715             return;
716         }
717         double d = jsValue.asNumber();
718         d += 0.5;
719         if (!(d > 0))
720             d = 0;
721         else if (d > 255)
722             d = 255;
723         GPRTemporary scratch(this);
724         GPRReg scratchReg = scratch.gpr();
725         m_jit.move(Imm32((int)d), scratchReg);
726         value.adopt(scratch);
727         valueGPR = scratchReg;
728     } else if (!at(valueIndex).shouldNotSpeculateInteger()) {
729         SpeculateIntegerOperand valueOp(this, valueIndex);
730         GPRTemporary scratch(this);
731         GPRReg scratchReg = scratch.gpr();
732         m_jit.move(valueOp.gpr(), scratchReg);
733         MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::BelowOrEqual, scratchReg, TrustedImm32(0xff));
734         m_jit.branch32(MacroAssembler::GreaterThan, scratchReg, TrustedImm32(0xff));
735         m_jit.xorPtr(scratchReg, scratchReg);
736         MacroAssembler::Jump clamped = m_jit.jump();
737         m_jit.move(TrustedImm32(255), scratchReg);
738         clamped.link(&m_jit);
739         inBounds.link(&m_jit);
740         value.adopt(scratch);
741         valueGPR = scratchReg;
742     } else {
743         SpeculateDoubleOperand valueOp(this, valueIndex);
744         GPRTemporary result(this);
745         FPRTemporary floatScratch(this);
746         FPRReg fpr = valueOp.fpr();
747         GPRReg gpr = result.gpr();
748         compileClampDoubleToByte(m_jit, gpr, fpr, floatScratch.fpr());
749         value.adopt(result);
750         valueGPR = gpr;
751     }
752     ASSERT_UNUSED(valueGPR, valueGPR != property);
753     ASSERT(valueGPR != base);
754     GPRTemporary storage(this);
755     GPRReg storageReg = storage.gpr();
756     ASSERT(valueGPR != storageReg);
757     m_jit.loadPtr(MacroAssembler::Address(base, JSByteArray::offsetOfStorage()), storageReg);
758     MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, property, MacroAssembler::Address(storageReg, ByteArray::offsetOfSize()));
759     m_jit.store8(value.gpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesOne, ByteArray::offsetOfData()));
760     outOfBounds.link(&m_jit);
761     noResult(m_compileIndex);
762 }
763
764 void SpeculativeJIT::compileGetByValOnByteArray(Node& node)
765 {
766     ASSERT(node.child3() == NoNode);
767     SpeculateCellOperand base(this, node.child1());
768     SpeculateStrictInt32Operand property(this, node.child2());
769     
770     GPRReg baseReg = base.gpr();
771     GPRReg propertyReg = property.gpr();
772     
773     if (!isByteArrayPrediction(m_state.forNode(node.child1()).m_type))
774         speculationCheck(JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsByteArrayVPtr)));
775
776     // Load the character into scratchReg
777     GPRTemporary storage(this);
778     GPRReg storageReg = storage.gpr();
779     m_jit.loadPtr(MacroAssembler::Address(baseReg, JSByteArray::offsetOfStorage()), storageReg);
780     
781     // unsigned comparison so we can filter out negative indices and indices that are too large
782     speculationCheck(JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ByteArray::offsetOfSize())));
783
784     m_jit.load8(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne, ByteArray::offsetOfData()), storageReg);
785     integerResult(storageReg, m_compileIndex);
786 }
787
788 } } // namespace JSC::DFG
789
790 #endif