Commit d93c9ad2 authored by fpizlo@apple.com's avatar fpizlo@apple.com

DFG static prediction code is no longer needed and should be removed

https://bugs.webkit.org/show_bug.cgi?id=68784

Reviewed by Oliver Hunt.
        
This gets rid of static prediction code, and ensures that we do not
try to compile code where dynamic predictions are not available.
This is accomplished by immediately performing an OSR exit wherever
a value is retrieved for which no predictions exist.
        
This also adds value profiling for this on functions used for calls.
        
The heuristics for deciding when to optimize code are also tweaked,
since it is now profitable to optimize sooner. This may need to be
tweaked further, but this patch only makes minimal changes.
        
This results in a 16% speed-up on Kraken/ai-astar, leading to a 3%
overall win on Kraken.  It's neutral elsewhere.

* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::shouldOptimizeNow):
(JSC::CodeBlock::dumpValueProfiles):
* bytecode/CodeBlock.h:
* bytecode/PredictedType.cpp:
(JSC::predictionToString):
* bytecode/PredictedType.h:
(JSC::isCellPrediction):
(JSC::isObjectPrediction):
(JSC::isFinalObjectPrediction):
(JSC::isStringPrediction):
(JSC::isArrayPrediction):
(JSC::isInt32Prediction):
(JSC::isDoublePrediction):
(JSC::isNumberPrediction):
(JSC::isBooleanPrediction):
(JSC::mergePredictions):
* bytecode/PredictionTracker.h:
(JSC::PredictionTracker::predictArgument):
(JSC::PredictionTracker::predict):
(JSC::PredictionTracker::predictGlobalVar):
* bytecode/ValueProfile.cpp:
(JSC::ValueProfile::computeUpdatedPrediction):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::set):
(JSC::DFG::ByteCodeParser::addCall):
(JSC::DFG::ByteCodeParser::getPrediction):
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::predictArgumentTypes):
* dfg/DFGGraph.h:
(JSC::DFG::Graph::predict):
(JSC::DFG::Graph::predictGlobalVar):
(JSC::DFG::Graph::getMethodCheckPrediction):
(JSC::DFG::Graph::getJSConstantPrediction):
(JSC::DFG::Graph::getPrediction):
* dfg/DFGJITCodeGenerator.cpp:
(JSC::DFG::JITCodeGenerator::writeBarrier):
(JSC::DFG::JITCodeGenerator::emitBranch):
* dfg/DFGJITCompiler.h:
(JSC::DFG::JITCompiler::getPrediction):
* dfg/DFGNode.h:
(JSC::DFG::Node::valueOfJSConstantNode):
(JSC::DFG::Node::isInt32Constant):
(JSC::DFG::Node::isDoubleConstant):
(JSC::DFG::Node::isNumberConstant):
(JSC::DFG::Node::isBooleanConstant):
(JSC::DFG::Node::predict):
* dfg/DFGPropagator.cpp:
(JSC::DFG::Propagator::Propagator):
(JSC::DFG::Propagator::propagateNodePredictions):
(JSC::DFG::Propagator::fixupNode):
(JSC::DFG::Propagator::isPredictedNumerical):
(JSC::DFG::Propagator::logicalNotIsPure):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::shouldSpeculateInteger):
(JSC::DFG::SpeculativeJIT::shouldSpeculateDouble):
(JSC::DFG::SpeculativeJIT::shouldSpeculateNumber):
(JSC::DFG::SpeculativeJIT::shouldNotSpeculateInteger):
(JSC::DFG::SpeculativeJIT::shouldSpeculateFinalObject):
(JSC::DFG::SpeculativeJIT::shouldSpeculateArray):
(JSC::DFG::SpeculativeJIT::shouldSpeculateObject):
(JSC::DFG::SpeculativeJIT::shouldSpeculateCell):
* jit/JIT.cpp:
(JSC::JIT::privateCompile):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@95930 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 245b8e62
2011-09-25 Filip Pizlo <fpizlo@apple.com>
DFG static prediction code is no longer needed and should be removed
https://bugs.webkit.org/show_bug.cgi?id=68784
Reviewed by Oliver Hunt.
This gets rid of static prediction code, and ensures that we do not
try to compile code where dynamic predictions are not available.
This is accomplished by immediately performing an OSR exit wherever
a value is retrieved for which no predictions exist.
This also adds value profiling for this on functions used for calls.
The heuristics for deciding when to optimize code are also tweaked,
since it is now profitable to optimize sooner. This may need to be
tweaked further, but this patch only makes minimal changes.
This results in a 16% speed-up on Kraken/ai-astar, leading to a 3%
overall win on Kraken. It's neutral elsewhere.
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::shouldOptimizeNow):
(JSC::CodeBlock::dumpValueProfiles):
* bytecode/CodeBlock.h:
* bytecode/PredictedType.cpp:
(JSC::predictionToString):
* bytecode/PredictedType.h:
(JSC::isCellPrediction):
(JSC::isObjectPrediction):
(JSC::isFinalObjectPrediction):
(JSC::isStringPrediction):
(JSC::isArrayPrediction):
(JSC::isInt32Prediction):
(JSC::isDoublePrediction):
(JSC::isNumberPrediction):
(JSC::isBooleanPrediction):
(JSC::mergePredictions):
* bytecode/PredictionTracker.h:
(JSC::PredictionTracker::predictArgument):
(JSC::PredictionTracker::predict):
(JSC::PredictionTracker::predictGlobalVar):
* bytecode/ValueProfile.cpp:
(JSC::ValueProfile::computeUpdatedPrediction):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::set):
(JSC::DFG::ByteCodeParser::addCall):
(JSC::DFG::ByteCodeParser::getPrediction):
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::predictArgumentTypes):
* dfg/DFGGraph.h:
(JSC::DFG::Graph::predict):
(JSC::DFG::Graph::predictGlobalVar):
(JSC::DFG::Graph::getMethodCheckPrediction):
(JSC::DFG::Graph::getJSConstantPrediction):
(JSC::DFG::Graph::getPrediction):
* dfg/DFGJITCodeGenerator.cpp:
(JSC::DFG::JITCodeGenerator::writeBarrier):
(JSC::DFG::JITCodeGenerator::emitBranch):
* dfg/DFGJITCompiler.h:
(JSC::DFG::JITCompiler::getPrediction):
* dfg/DFGNode.h:
(JSC::DFG::Node::valueOfJSConstantNode):
(JSC::DFG::Node::isInt32Constant):
(JSC::DFG::Node::isDoubleConstant):
(JSC::DFG::Node::isNumberConstant):
(JSC::DFG::Node::isBooleanConstant):
(JSC::DFG::Node::predict):
* dfg/DFGPropagator.cpp:
(JSC::DFG::Propagator::Propagator):
(JSC::DFG::Propagator::propagateNodePredictions):
(JSC::DFG::Propagator::fixupNode):
(JSC::DFG::Propagator::isPredictedNumerical):
(JSC::DFG::Propagator::logicalNotIsPure):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::shouldSpeculateInteger):
(JSC::DFG::SpeculativeJIT::shouldSpeculateDouble):
(JSC::DFG::SpeculativeJIT::shouldSpeculateNumber):
(JSC::DFG::SpeculativeJIT::shouldNotSpeculateInteger):
(JSC::DFG::SpeculativeJIT::shouldSpeculateFinalObject):
(JSC::DFG::SpeculativeJIT::shouldSpeculateArray):
(JSC::DFG::SpeculativeJIT::shouldSpeculateObject):
(JSC::DFG::SpeculativeJIT::shouldSpeculateCell):
* jit/JIT.cpp:
(JSC::JIT::privateCompile):
2011-09-25 Filip Pizlo <fpizlo@apple.com> 2011-09-25 Filip Pizlo <fpizlo@apple.com>
DFG JIT Construct opcode takes a this argument even though it's DFG JIT Construct opcode takes a this argument even though it's
...@@ -1999,7 +1999,7 @@ bool CodeBlock::shouldOptimizeNow() ...@@ -1999,7 +1999,7 @@ bool CodeBlock::shouldOptimizeNow()
#endif #endif
if ((!numberOfNonArgumentValueProfiles || (double)numberOfLiveNonArgumentValueProfiles / numberOfNonArgumentValueProfiles >= 0.75) if ((!numberOfNonArgumentValueProfiles || (double)numberOfLiveNonArgumentValueProfiles / numberOfNonArgumentValueProfiles >= 0.75)
&& (!numberOfValueProfiles() || (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / numberOfValueProfiles() >= 0.5)) && (!numberOfValueProfiles() || (double)numberOfSamplesInProfiles / ValueProfile::numberOfBuckets / numberOfValueProfiles() >= 0.25))
return true; return true;
m_optimizationDelayCounter++; m_optimizationDelayCounter++;
...@@ -2026,7 +2026,7 @@ void CodeBlock::dumpValueProfiles() ...@@ -2026,7 +2026,7 @@ void CodeBlock::dumpValueProfiles()
ValueProfile* profile = valueProfile(i); ValueProfile* profile = valueProfile(i);
if (profile->m_bytecodeOffset < 0) { if (profile->m_bytecodeOffset < 0) {
ASSERT(profile->m_bytecodeOffset == -1); ASSERT(profile->m_bytecodeOffset == -1);
fprintf(stderr, " arg = %u: ", i + 1); fprintf(stderr, " arg = %u: ", i);
} else } else
fprintf(stderr, " bc = %d: ", profile->m_bytecodeOffset); fprintf(stderr, " bc = %d: ", profile->m_bytecodeOffset);
if (!profile->numberOfSamples() && profile->m_prediction == PredictNone) { if (!profile->numberOfSamples() && profile->m_prediction == PredictNone) {
......
...@@ -498,10 +498,10 @@ namespace JSC { ...@@ -498,10 +498,10 @@ namespace JSC {
} }
ValueProfile* valueProfileForArgument(int argumentIndex) ValueProfile* valueProfileForArgument(int argumentIndex)
{ {
int index = argumentIndex - 1; int index = argumentIndex;
if (static_cast<unsigned>(index) >= m_valueProfiles.size()) if (static_cast<unsigned>(index) >= m_valueProfiles.size())
return 0; return 0;
ValueProfile* result = valueProfile(argumentIndex - 1); ValueProfile* result = valueProfile(argumentIndex);
if (result->m_bytecodeOffset != -1) if (result->m_bytecodeOffset != -1)
return 0; return 0;
return result; return result;
......
...@@ -37,13 +37,13 @@ namespace JSC { ...@@ -37,13 +37,13 @@ namespace JSC {
#ifndef NDEBUG #ifndef NDEBUG
const char* predictionToString(PredictedType value) const char* predictionToString(PredictedType value)
{ {
if (value == PredictNone)
return "None";
static const int size = 96; static const int size = 96;
static char description[size]; static char description[size];
BoundsCheckedPointer<char> ptr(description, size); BoundsCheckedPointer<char> ptr(description, size);
if (!(value & StrongPredictionTag))
ptr.strcat("Weak");
if (value & PredictObjectUnknown) { if (value & PredictObjectUnknown) {
ASSERT(!(value & (PredictObjectMask & ~PredictObjectUnknown))); ASSERT(!(value & (PredictObjectMask & ~PredictObjectUnknown)));
ptr.strcat("Object"); ptr.strcat("Object");
......
...@@ -51,60 +51,50 @@ static const PredictedType PredictNumber = 0x0300; // It's either an Int3 ...@@ -51,60 +51,50 @@ static const PredictedType PredictNumber = 0x0300; // It's either an Int3
static const PredictedType PredictBoolean = 0x0400; // It's definitely a Boolean. static const PredictedType PredictBoolean = 0x0400; // It's definitely a Boolean.
static const PredictedType PredictOther = 0x4000; // It's definitely none of the above. static const PredictedType PredictOther = 0x4000; // It's definitely none of the above.
static const PredictedType PredictTop = 0x7fff; // It can be any of the above. static const PredictedType PredictTop = 0x7fff; // It can be any of the above.
static const PredictedType StrongPredictionTag = 0x8000; // It's a strong prediction (all strong predictions trump all weak ones).
static const PredictedType PredictionTagMask = 0x8000;
enum PredictionSource { WeakPrediction, StrongPrediction };
inline bool isCellPrediction(PredictedType value) inline bool isCellPrediction(PredictedType value)
{ {
return !!(value & PredictCell) && !(value & ~(PredictCell | PredictionTagMask)); return !!(value & PredictCell) && !(value & ~PredictCell);
} }
inline bool isObjectPrediction(PredictedType value) inline bool isObjectPrediction(PredictedType value)
{ {
return !!(value & PredictObjectMask) && !(value & ~(PredictObjectMask | PredictionTagMask)); return !!(value & PredictObjectMask) && !(value & ~PredictObjectMask);
} }
inline bool isFinalObjectPrediction(PredictedType value) inline bool isFinalObjectPrediction(PredictedType value)
{ {
return (value & ~PredictionTagMask) == PredictFinalObject; return value == PredictFinalObject;
} }
inline bool isStringPrediction(PredictedType value) inline bool isStringPrediction(PredictedType value)
{ {
return (value & ~PredictionTagMask) == PredictString; return value == PredictString;
} }
inline bool isArrayPrediction(PredictedType value) inline bool isArrayPrediction(PredictedType value)
{ {
return (value & ~PredictionTagMask) == PredictArray; return value == PredictArray;
} }
inline bool isInt32Prediction(PredictedType value) inline bool isInt32Prediction(PredictedType value)
{ {
return (value & ~PredictionTagMask) == PredictInt32; return value == PredictInt32;
} }
inline bool isDoublePrediction(PredictedType value) inline bool isDoublePrediction(PredictedType value)
{ {
return (value & ~PredictionTagMask) == PredictDouble; return value == PredictDouble;
} }
inline bool isNumberPrediction(PredictedType value) inline bool isNumberPrediction(PredictedType value)
{ {
return !!(value & PredictNumber) && !(value & ~(PredictNumber | PredictionTagMask)); return !!(value & PredictNumber) && !(value & ~PredictNumber);
} }
inline bool isBooleanPrediction(PredictedType value) inline bool isBooleanPrediction(PredictedType value)
{ {
return (value & ~PredictionTagMask) == PredictBoolean; return value == PredictBoolean;
}
inline bool isStrongPrediction(PredictedType value)
{
ASSERT(value != (PredictNone | StrongPredictionTag));
return !!(value & StrongPredictionTag);
} }
#ifndef NDEBUG #ifndef NDEBUG
...@@ -113,25 +103,16 @@ const char* predictionToString(PredictedType value); ...@@ -113,25 +103,16 @@ const char* predictionToString(PredictedType value);
inline PredictedType mergePredictions(PredictedType left, PredictedType right) inline PredictedType mergePredictions(PredictedType left, PredictedType right)
{ {
if (isStrongPrediction(left) == isStrongPrediction(right)) { if (left & PredictObjectUnknown) {
if (left & PredictObjectUnknown) { ASSERT(!(left & (PredictObjectMask & ~PredictObjectUnknown)));
ASSERT(!(left & (PredictObjectMask & ~PredictObjectUnknown))); if (right & PredictObjectMask)
if (right & PredictObjectMask) return (left & ~PredictObjectUnknown) | right;
return (left & ~PredictObjectUnknown) | right; } else if (right & PredictObjectUnknown) {
} else if (right & PredictObjectUnknown) { ASSERT(!(right & (PredictObjectMask & ~PredictObjectUnknown)));
ASSERT(!(right & (PredictObjectMask & ~PredictObjectUnknown))); if (left & PredictObjectMask)
if (left & PredictObjectMask) return (right & ~PredictObjectUnknown) | left;
return (right & ~PredictObjectUnknown) | left;
}
return left | right;
} }
if (isStrongPrediction(left)) { return left | right;
ASSERT(!isStrongPrediction(right));
return left;
}
ASSERT(!isStrongPrediction(left));
ASSERT(isStrongPrediction(right));
return right;
} }
template<typename T> template<typename T>
...@@ -143,15 +124,6 @@ inline bool mergePrediction(T& left, PredictedType right) ...@@ -143,15 +124,6 @@ inline bool mergePrediction(T& left, PredictedType right)
return result; return result;
} }
inline PredictedType makePrediction(PredictedType type, PredictionSource source)
{
ASSERT(!(type & StrongPredictionTag));
ASSERT(source == StrongPrediction || source == WeakPrediction);
if (type == PredictNone)
return PredictNone;
return type | (source == StrongPrediction ? StrongPredictionTag : 0);
}
PredictedType predictionFromClassInfo(const ClassInfo*); PredictedType predictionFromClassInfo(const ClassInfo*);
PredictedType predictionFromStructure(Structure*); PredictedType predictionFromStructure(Structure*);
PredictedType predictionFromCell(JSCell*); PredictedType predictionFromCell(JSCell*);
......
...@@ -73,33 +73,33 @@ public: ...@@ -73,33 +73,33 @@ public:
unsigned argumentIndexForOperand(int operand) const { return operand + m_arguments.size() + RegisterFile::CallFrameHeaderSize; } unsigned argumentIndexForOperand(int operand) const { return operand + m_arguments.size() + RegisterFile::CallFrameHeaderSize; }
bool predictArgument(unsigned argument, PredictedType prediction, PredictionSource source) bool predictArgument(unsigned argument, PredictedType prediction)
{ {
return mergePrediction(m_arguments[argument].m_value, makePrediction(prediction, source)); return mergePrediction(m_arguments[argument].m_value, prediction);
} }
bool predict(int operand, PredictedType prediction, PredictionSource source) bool predict(int operand, PredictedType prediction)
{ {
if (operandIsArgument(operand)) if (operandIsArgument(operand))
return predictArgument(argumentIndexForOperand(operand), prediction, source); return predictArgument(argumentIndexForOperand(operand), prediction);
if ((unsigned)operand >= m_variables.size()) { if ((unsigned)operand >= m_variables.size()) {
ASSERT(operand >= 0); ASSERT(operand >= 0);
m_variables.resize(operand + 1); m_variables.resize(operand + 1);
} }
return mergePrediction(m_variables[operand].m_value, makePrediction(prediction, source)); return mergePrediction(m_variables[operand].m_value, prediction);
} }
bool predictGlobalVar(unsigned varNumber, PredictedType prediction, PredictionSource source) bool predictGlobalVar(unsigned varNumber, PredictedType prediction)
{ {
HashMap<unsigned, PredictionSlot>::iterator iter = m_globalVars.find(varNumber + 1); HashMap<unsigned, PredictionSlot>::iterator iter = m_globalVars.find(varNumber + 1);
if (iter == m_globalVars.end()) { if (iter == m_globalVars.end()) {
PredictionSlot predictionSlot; PredictionSlot predictionSlot;
bool result = mergePrediction(predictionSlot.m_value, makePrediction(prediction, source)); bool result = mergePrediction(predictionSlot.m_value, prediction);
m_globalVars.add(varNumber + 1, predictionSlot); m_globalVars.add(varNumber + 1, predictionSlot);
return result; return result;
} }
return mergePrediction(iter->second.m_value, makePrediction(prediction, source)); return mergePrediction(iter->second.m_value, prediction);
} }
PredictedType getArgumentPrediction(unsigned argument) PredictedType getArgumentPrediction(unsigned argument)
......
...@@ -94,25 +94,25 @@ PredictedType ValueProfile::computeUpdatedPrediction() ...@@ -94,25 +94,25 @@ PredictedType ValueProfile::computeUpdatedPrediction()
if (!statistics.samples) if (!statistics.samples)
prediction = PredictNone; prediction = PredictNone;
else if (statistics.int32s == statistics.samples) else if (statistics.int32s == statistics.samples)
prediction = StrongPredictionTag | PredictInt32; prediction = PredictInt32;
else if (statistics.doubles == statistics.samples) else if (statistics.doubles == statistics.samples)
prediction = StrongPredictionTag | PredictDouble; prediction = PredictDouble;
else if (statistics.int32s + statistics.doubles == statistics.samples) else if (statistics.int32s + statistics.doubles == statistics.samples)
prediction = StrongPredictionTag | PredictNumber; prediction = PredictNumber;
else if (statistics.arrays == statistics.samples) else if (statistics.arrays == statistics.samples)
prediction = StrongPredictionTag | PredictArray; prediction = PredictArray;
else if (statistics.finalObjects == statistics.samples) else if (statistics.finalObjects == statistics.samples)
prediction = StrongPredictionTag | PredictFinalObject; prediction = PredictFinalObject;
else if (statistics.strings == statistics.samples) else if (statistics.strings == statistics.samples)
prediction = StrongPredictionTag | PredictString; prediction = PredictString;
else if (statistics.objects == statistics.samples) else if (statistics.objects == statistics.samples)
prediction = StrongPredictionTag | PredictObjectOther; prediction = PredictObjectOther;
else if (statistics.cells == statistics.samples) else if (statistics.cells == statistics.samples)
prediction = StrongPredictionTag | PredictCellOther; prediction = PredictCellOther;
else if (statistics.booleans == statistics.samples) else if (statistics.booleans == statistics.samples)
prediction = StrongPredictionTag | PredictBoolean; prediction = PredictBoolean;
else else
prediction = StrongPredictionTag | PredictOther; prediction = PredictOther;
m_numberOfSamplesInPrediction += statistics.samples; m_numberOfSamplesInPrediction += statistics.samples;
mergePrediction(m_prediction, prediction); mergePrediction(m_prediction, prediction);
......
...@@ -101,10 +101,8 @@ private: ...@@ -101,10 +101,8 @@ private:
// Must be a local. // Must be a local.
return getLocal((unsigned)operand); return getLocal((unsigned)operand);
} }
void set(int operand, NodeIndex value, PredictedType weakPrediction = PredictNone) void set(int operand, NodeIndex value)
{ {
m_graph.predict(operand, weakPrediction, WeakPrediction);
// Is this an argument? // Is this an argument?
if (operandIsArgument(operand)) { if (operandIsArgument(operand)) {
setArgument(operand, value); setArgument(operand, value);
...@@ -436,7 +434,7 @@ private: ...@@ -436,7 +434,7 @@ private:
PredictedType prediction = PredictNone; PredictedType prediction = PredictNone;
if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result) if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result)
prediction = getStrongPrediction(m_graph.size(), m_currentIndex + OPCODE_LENGTH(op_call)); prediction = getPrediction(m_graph.size(), m_currentIndex + OPCODE_LENGTH(op_call));
addVarArgChild(get(currentInstruction[1].u.operand)); addVarArgChild(get(currentInstruction[1].u.operand));
int argCount = currentInstruction[2].u.operand; int argCount = currentInstruction[2].u.operand;
...@@ -452,42 +450,7 @@ private: ...@@ -452,42 +450,7 @@ private:
return call; return call;
} }
void weaklyPredictArray(NodeIndex nodeIndex) PredictedType getPrediction(NodeIndex nodeIndex, unsigned bytecodeIndex)
{
m_graph.predict(m_graph[nodeIndex], PredictArray, WeakPrediction);
}
void weaklyPredictInt32(NodeIndex nodeIndex)
{
ASSERT(m_reusableNodeStack.isEmpty());
m_reusableNodeStack.append(&m_graph[nodeIndex]);
do {
Node* nodePtr = m_reusableNodeStack.last();
m_reusableNodeStack.removeLast();
if (nodePtr->op == ValueToNumber)
nodePtr = &m_graph[nodePtr->child1()];
if (nodePtr->op == ValueToInt32)
nodePtr = &m_graph[nodePtr->child1()];
switch (nodePtr->op) {
case ArithAdd:
case ArithSub:
case ArithMul:
case ValueAdd:
m_reusableNodeStack.append(&m_graph[nodePtr->child1()]);
m_reusableNodeStack.append(&m_graph[nodePtr->child2()]);
break;
default:
m_graph.predict(*nodePtr, PredictInt32, WeakPrediction);
break;
}
} while (!m_reusableNodeStack.isEmpty());
}
PredictedType getStrongPrediction(NodeIndex nodeIndex, unsigned bytecodeIndex)
{ {
UNUSED_PARAM(nodeIndex); UNUSED_PARAM(nodeIndex);
...@@ -507,9 +470,9 @@ private: ...@@ -507,9 +470,9 @@ private:
return prediction; return prediction;
} }
PredictedType getStrongPrediction() PredictedType getPrediction()
{ {
return getStrongPrediction(m_graph.size(), m_currentIndex); return getPrediction(m_graph.size(), m_currentIndex);
} }
NodeIndex makeSafe(NodeIndex nodeIndex) NodeIndex makeSafe(NodeIndex nodeIndex)
...@@ -771,65 +734,53 @@ bool ByteCodeParser::parseBlock(unsigned limit) ...@@ -771,65 +734,53 @@ bool ByteCodeParser::parseBlock(unsigned limit)
case op_bitand: { case op_bitand: {
NodeIndex op1 = getToInt32(currentInstruction[2].u.operand); NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
NodeIndex op2 = getToInt32(currentInstruction[3].u.operand); NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
weaklyPredictInt32(op1); set(currentInstruction[1].u.operand, addToGraph(BitAnd, op1, op2));
weaklyPredictInt32(op2);
set(currentInstruction[1].u.operand, addToGraph(BitAnd, op1, op2), PredictInt32);
NEXT_OPCODE(op_bitand); NEXT_OPCODE(op_bitand);
} }
case op_bitor: { case op_bitor: {
NodeIndex op1 = getToInt32(currentInstruction[2].u.operand); NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
NodeIndex op2 = getToInt32(currentInstruction[3].u.operand); NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
weaklyPredictInt32(op1); set(currentInstruction[1].u.operand, addToGraph(BitOr, op1, op2));
weaklyPredictInt32(op2);
set(currentInstruction[1].u.operand, addToGraph(BitOr, op1, op2), PredictInt32);
NEXT_OPCODE(op_bitor); NEXT_OPCODE(op_bitor);
} }
case op_bitxor: { case op_bitxor: {
NodeIndex op1 = getToInt32(currentInstruction[2].u.operand); NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
NodeIndex op2 = getToInt32(currentInstruction[3].u.operand); NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
weaklyPredictInt32(op1); set(currentInstruction[1].u.operand, addToGraph(BitXor, op1, op2));
weaklyPredictInt32(op2);
set(currentInstruction[1].u.operand, addToGraph(BitXor, op1, op2), PredictInt32);
NEXT_OPCODE(op_bitxor); NEXT_OPCODE(op_bitxor);
} }
case op_rshift: { case op_rshift: {
NodeIndex op1 = getToInt32(currentInstruction[2].u.operand); NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
NodeIndex op2 = getToInt32(currentInstruction[3].u.operand); NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
weaklyPredictInt32(op1);
weaklyPredictInt32(op2);
NodeIndex result; NodeIndex result;
// Optimize out shifts by zero. // Optimize out shifts by zero.
if (isInt32Constant(op2) && !(valueOfInt32Constant(op2) & 0x1f)) if (isInt32Constant(op2) && !(valueOfInt32Constant(op2) & 0x1f))
result = op1; result = op1;
else else
result = addToGraph(BitRShift, op1, op2); result = addToGraph(BitRShift, op1, op2);
set(currentInstruction[1].u.operand, result, PredictInt32); set(currentInstruction[1].u.operand, result);
NEXT_OPCODE(op_rshift); NEXT_OPCODE(op_rshift);
} }
case op_lshift: { case op_lshift: {
NodeIndex op1 = getToInt32(currentInstruction[2].u.operand); NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);