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>
DFG JIT Construct opcode takes a this argument even though it's
......@@ -1999,7 +1999,7 @@ bool CodeBlock::shouldOptimizeNow()
#endif
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;
m_optimizationDelayCounter++;
......@@ -2026,7 +2026,7 @@ void CodeBlock::dumpValueProfiles()
ValueProfile* profile = valueProfile(i);
if (profile->m_bytecodeOffset < 0) {
ASSERT(profile->m_bytecodeOffset == -1);
fprintf(stderr, " arg = %u: ", i + 1);
fprintf(stderr, " arg = %u: ", i);
} else
fprintf(stderr, " bc = %d: ", profile->m_bytecodeOffset);
if (!profile->numberOfSamples() && profile->m_prediction == PredictNone) {
......
......@@ -498,10 +498,10 @@ namespace JSC {
}
ValueProfile* valueProfileForArgument(int argumentIndex)
{
int index = argumentIndex - 1;
int index = argumentIndex;
if (static_cast<unsigned>(index) >= m_valueProfiles.size())
return 0;
ValueProfile* result = valueProfile(argumentIndex - 1);
ValueProfile* result = valueProfile(argumentIndex);
if (result->m_bytecodeOffset != -1)
return 0;
return result;
......
......@@ -37,13 +37,13 @@ namespace JSC {
#ifndef NDEBUG
const char* predictionToString(PredictedType value)
{
if (value == PredictNone)
return "None";
static const int size = 96;
static char description[size];
BoundsCheckedPointer<char> ptr(description, size);
if (!(value & StrongPredictionTag))
ptr.strcat("Weak");
if (value & PredictObjectUnknown) {
ASSERT(!(value & (PredictObjectMask & ~PredictObjectUnknown)));
ptr.strcat("Object");
......
......@@ -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 PredictOther = 0x4000; // It's definitely none 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)
{
return !!(value & PredictCell) && !(value & ~(PredictCell | PredictionTagMask));
return !!(value & PredictCell) && !(value & ~PredictCell);
}
inline bool isObjectPrediction(PredictedType value)
{
return !!(value & PredictObjectMask) && !(value & ~(PredictObjectMask | PredictionTagMask));
return !!(value & PredictObjectMask) && !(value & ~PredictObjectMask);
}
inline bool isFinalObjectPrediction(PredictedType value)
{
return (value & ~PredictionTagMask) == PredictFinalObject;
return value == PredictFinalObject;
}
inline bool isStringPrediction(PredictedType value)
{
return (value & ~PredictionTagMask) == PredictString;
return value == PredictString;
}
inline bool isArrayPrediction(PredictedType value)
{
return (value & ~PredictionTagMask) == PredictArray;
return value == PredictArray;
}
inline bool isInt32Prediction(PredictedType value)
{
return (value & ~PredictionTagMask) == PredictInt32;
return value == PredictInt32;
}
inline bool isDoublePrediction(PredictedType value)
{
return (value & ~PredictionTagMask) == PredictDouble;
return value == PredictDouble;
}
inline bool isNumberPrediction(PredictedType value)
{
return !!(value & PredictNumber) && !(value & ~(PredictNumber | PredictionTagMask));
return !!(value & PredictNumber) && !(value & ~PredictNumber);
}
inline bool isBooleanPrediction(PredictedType value)
{
return (value & ~PredictionTagMask) == PredictBoolean;
}
inline bool isStrongPrediction(PredictedType value)
{
ASSERT(value != (PredictNone | StrongPredictionTag));
return !!(value & StrongPredictionTag);
return value == PredictBoolean;
}
#ifndef NDEBUG
......@@ -113,25 +103,16 @@ const char* predictionToString(PredictedType value);
inline PredictedType mergePredictions(PredictedType left, PredictedType right)
{
if (isStrongPrediction(left) == isStrongPrediction(right)) {
if (left & PredictObjectUnknown) {
ASSERT(!(left & (PredictObjectMask & ~PredictObjectUnknown)));
if (right & PredictObjectMask)
return (left & ~PredictObjectUnknown) | right;
} else if (right & PredictObjectUnknown) {
ASSERT(!(right & (PredictObjectMask & ~PredictObjectUnknown)));
if (left & PredictObjectMask)
return (right & ~PredictObjectUnknown) | left;
}
return left | right;
if (left & PredictObjectUnknown) {
ASSERT(!(left & (PredictObjectMask & ~PredictObjectUnknown)));
if (right & PredictObjectMask)
return (left & ~PredictObjectUnknown) | right;
} else if (right & PredictObjectUnknown) {
ASSERT(!(right & (PredictObjectMask & ~PredictObjectUnknown)));
if (left & PredictObjectMask)
return (right & ~PredictObjectUnknown) | left;
}
if (isStrongPrediction(left)) {
ASSERT(!isStrongPrediction(right));
return left;
}
ASSERT(!isStrongPrediction(left));
ASSERT(isStrongPrediction(right));
return right;
return left | right;
}
template<typename T>
......@@ -143,15 +124,6 @@ inline bool mergePrediction(T& left, PredictedType right)
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 predictionFromStructure(Structure*);
PredictedType predictionFromCell(JSCell*);
......
......@@ -73,33 +73,33 @@ public:
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))
return predictArgument(argumentIndexForOperand(operand), prediction, source);
return predictArgument(argumentIndexForOperand(operand), prediction);
if ((unsigned)operand >= m_variables.size()) {
ASSERT(operand >= 0);
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);
if (iter == m_globalVars.end()) {
PredictionSlot predictionSlot;
bool result = mergePrediction(predictionSlot.m_value, makePrediction(prediction, source));
bool result = mergePrediction(predictionSlot.m_value, prediction);
m_globalVars.add(varNumber + 1, predictionSlot);
return result;
}
return mergePrediction(iter->second.m_value, makePrediction(prediction, source));
return mergePrediction(iter->second.m_value, prediction);
}
PredictedType getArgumentPrediction(unsigned argument)
......
......@@ -94,25 +94,25 @@ PredictedType ValueProfile::computeUpdatedPrediction()
if (!statistics.samples)
prediction = PredictNone;
else if (statistics.int32s == statistics.samples)
prediction = StrongPredictionTag | PredictInt32;
prediction = PredictInt32;
else if (statistics.doubles == statistics.samples)
prediction = StrongPredictionTag | PredictDouble;
prediction = PredictDouble;
else if (statistics.int32s + statistics.doubles == statistics.samples)
prediction = StrongPredictionTag | PredictNumber;
prediction = PredictNumber;
else if (statistics.arrays == statistics.samples)
prediction = StrongPredictionTag | PredictArray;
prediction = PredictArray;
else if (statistics.finalObjects == statistics.samples)
prediction = StrongPredictionTag | PredictFinalObject;
prediction = PredictFinalObject;
else if (statistics.strings == statistics.samples)
prediction = StrongPredictionTag | PredictString;
prediction = PredictString;
else if (statistics.objects == statistics.samples)
prediction = StrongPredictionTag | PredictObjectOther;
prediction = PredictObjectOther;
else if (statistics.cells == statistics.samples)
prediction = StrongPredictionTag | PredictCellOther;
prediction = PredictCellOther;
else if (statistics.booleans == statistics.samples)
prediction = StrongPredictionTag | PredictBoolean;
prediction = PredictBoolean;
else
prediction = StrongPredictionTag | PredictOther;
prediction = PredictOther;
m_numberOfSamplesInPrediction += statistics.samples;
mergePrediction(m_prediction, prediction);
......
......@@ -101,10 +101,8 @@ private:
// Must be a local.
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?
if (operandIsArgument(operand)) {
setArgument(operand, value);
......@@ -436,7 +434,7 @@ private:
PredictedType prediction = PredictNone;
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));
int argCount = currentInstruction[2].u.operand;
......@@ -452,42 +450,7 @@ private:
return call;
}
void weaklyPredictArray(NodeIndex nodeIndex)
{
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)
PredictedType getPrediction(NodeIndex nodeIndex, unsigned bytecodeIndex)
{
UNUSED_PARAM(nodeIndex);
......@@ -507,9 +470,9 @@ private:
return prediction;
}
PredictedType getStrongPrediction()
PredictedType getPrediction()
{
return getStrongPrediction(m_graph.size(), m_currentIndex);
return getPrediction(m_graph.size(), m_currentIndex);
}
NodeIndex makeSafe(NodeIndex nodeIndex)
......@@ -771,65 +734,53 @@ bool ByteCodeParser::parseBlock(unsigned limit)
case op_bitand: {
NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
weaklyPredictInt32(op1);
weaklyPredictInt32(op2);
set(currentInstruction[1].u.operand, addToGraph(BitAnd, op1, op2), PredictInt32);
set(currentInstruction[1].u.operand, addToGraph(BitAnd, op1, op2));
NEXT_OPCODE(op_bitand);
}
case op_bitor: {
NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
weaklyPredictInt32(op1);
weaklyPredictInt32(op2);
set(currentInstruction[1].u.operand, addToGraph(BitOr, op1, op2), PredictInt32);
set(currentInstruction[1].u.operand, addToGraph(BitOr, op1, op2));
NEXT_OPCODE(op_bitor);
}
case op_bitxor: {
NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
weaklyPredictInt32(op1);
weaklyPredictInt32(op2);
set(currentInstruction[1].u.operand, addToGraph(BitXor, op1, op2), PredictInt32);
set(currentInstruction[1].u.operand, addToGraph(BitXor, op1, op2));
NEXT_OPCODE(op_bitxor);
}
case op_rshift: {
NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
weaklyPredictInt32(op1);
weaklyPredictInt32(op2);
NodeIndex result;
// Optimize out shifts by zero.
if (isInt32Constant(op2) && !(valueOfInt32Constant(op2) & 0x1f))
result = op1;
else
result = addToGraph(BitRShift, op1, op2);
set(currentInstruction[1].u.operand, result, PredictInt32);
set(currentInstruction[1].u.operand, result);
NEXT_OPCODE(op_rshift);
}
case op_lshift: {
NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
weaklyPredictInt32(op1);
weaklyPredictInt32(op2);
NodeIndex result;
// Optimize out shifts by zero.
if (isInt32Constant(op2) && !(valueOfInt32Constant(op2) & 0x1f))
result = op1;
else
result = addToGraph(BitLShift, op1, op2);
set(currentInstruction[1].u.operand, result, PredictInt32);
set(currentInstruction[1].u.operand, result);
NEXT_OPCODE(op_lshift);
}
case op_urshift: {
NodeIndex op1 = getToInt32(currentInstruction[2].u.operand);
NodeIndex op2 = getToInt32(currentInstruction[3].u.operand);
weaklyPredictInt32(op1);
weaklyPredictInt32(op2);
NodeIndex result;
// The result of a zero-extending right shift is treated as an unsigned value.
// This means that if the top bit is set, the result is not in the int32 range,
......@@ -850,7 +801,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
result = addToGraph(BitURShift, op1, op2);
result = makeSafe(addToGraph(UInt32ToNumber, OpInfo(NodeUseBottom), result));
}
set(currentInstruction[1].u.operand, result, PredictInt32);
set(currentInstruction[1].u.operand, result);
NEXT_OPCODE(op_urshift);
}
......@@ -859,7 +810,6 @@ bool ByteCodeParser::parseBlock(unsigned limit)
case op_pre_inc: {
unsigned srcDst = currentInstruction[1].u.operand;
NodeIndex op = getToNumber(srcDst);
weaklyPredictInt32(op);
set(srcDst, makeSafe(addToGraph(ArithAdd, OpInfo(NodeUseBottom), op, one())));
NEXT_OPCODE(op_pre_inc);
}
......@@ -868,7 +818,6 @@ bool ByteCodeParser::parseBlock(unsigned limit)
unsigned result = currentInstruction[1].u.operand;
unsigned srcDst = currentInstruction[2].u.operand;
NodeIndex op = getToNumber(srcDst);
weaklyPredictInt32(op);
set(result, op);
set(srcDst, makeSafe(addToGraph(ArithAdd, OpInfo(NodeUseBottom), op, one())));
NEXT_OPCODE(op_post_inc);
......@@ -877,7 +826,6 @@ bool ByteCodeParser::parseBlock(unsigned limit)
case op_pre_dec: {
unsigned srcDst = currentInstruction[1].u.operand;
NodeIndex op = getToNumber(srcDst);
weaklyPredictInt32(op);
set(srcDst, makeSafe(addToGraph(ArithSub, OpInfo(NodeUseBottom), op, one())));
NEXT_OPCODE(op_pre_dec);
}
......@@ -886,7 +834,6 @@ bool ByteCodeParser::parseBlock(unsigned limit)
unsigned result = currentInstruction[1].u.operand;
unsigned srcDst = currentInstruction[2].u.operand;
NodeIndex op = getToNumber(srcDst);
weaklyPredictInt32(op);
set(result, op);
set(srcDst, makeSafe(addToGraph(ArithSub, OpInfo(NodeUseBottom), op, one())));
NEXT_OPCODE(op_post_dec);
......@@ -897,13 +844,6 @@ bool ByteCodeParser::parseBlock(unsigned limit)
case op_add: {
NodeIndex op1 = get(currentInstruction[2].u.operand);
NodeIndex op2 = get(currentInstruction[3].u.operand);
// If both operands can statically be determined to the numbers, then this is an arithmetic add.
// Otherwise, we must assume this may be performing a concatenation to a string.
if (isSmallInt32Constant(op1) || isSmallInt32Constant(op2)) {
weaklyPredictInt32(op1);
weaklyPredictInt32(op2);
}
if (m_graph[op1].hasNumberResult() && m_graph[op2].hasNumberResult())
set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithAdd, OpInfo(NodeUseBottom), toNumber(op1), toNumber(op2))));
else
......@@ -914,11 +854,6 @@ bool ByteCodeParser::parseBlock(unsigned limit)
case op_sub: {
NodeIndex op1 = getToNumber(currentInstruction[2].u.operand);
NodeIndex op2 = getToNumber(currentInstruction[3].u.operand);
if (isSmallInt32Constant(op1) || isSmallInt32Constant(op2)) {
weaklyPredictInt32(op1);
weaklyPredictInt32(op2);
}
set(currentInstruction[1].u.operand, makeSafe(addToGraph(ArithSub, OpInfo(NodeUseBottom), op1, op2)));
NEXT_OPCODE(op_sub);
}
......@@ -1062,12 +997,10 @@ bool ByteCodeParser::parseBlock(unsigned limit)
// === Property access operations ===
case op_get_by_val: {
PredictedType prediction = getStrongPrediction();
PredictedType prediction = getPrediction();
NodeIndex base = get(currentInstruction[2].u.operand);
NodeIndex property = get(currentInstruction[3].u.operand);
weaklyPredictArray(base);
weaklyPredictInt32(property);
NodeIndex getByVal = addToGraph(GetByVal, OpInfo(0), OpInfo(prediction), base, property);
set(currentInstruction[1].u.operand, getByVal);
......@@ -1079,8 +1012,6 @@ bool ByteCodeParser::parseBlock(unsigned limit)
NodeIndex base = get(currentInstruction[1].u.operand);
NodeIndex property = get(currentInstruction[2].u.operand);
NodeIndex value = get(currentInstruction[3].u.operand);
weaklyPredictArray(base);
weaklyPredictInt32(property);
addToGraph(PutByVal, base, property, value);
......@@ -1090,7 +1021,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
case op_method_check: {
Instruction* getInstruction = currentInstruction + OPCODE_LENGTH(op_method_check);
PredictedType prediction = getStrongPrediction();
PredictedType prediction = getPrediction();
ASSERT(interpreter->getOpcodeID(getInstruction->u.opcode) == op_get_by_id);
......@@ -1124,7 +1055,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
continue;
}
case op_get_scoped_var: {
PredictedType prediction = getStrongPrediction();
PredictedType prediction = getPrediction();
int dst = currentInstruction[1].u.operand;
int slot = currentInstruction[2].u.operand;
int depth = currentInstruction[3].u.operand;
......@@ -1142,7 +1073,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
NEXT_OPCODE(op_put_scoped_var);
}
case op_get_by_id: {
PredictedType prediction = getStrongPrediction();
PredictedType prediction = getPrediction();
NodeIndex base = get(currentInstruction[2].u.operand);
unsigned identifierNumber = currentInstruction[3].u.operand;
......@@ -1188,11 +1119,11 @@ bool ByteCodeParser::parseBlock(unsigned limit)
}
case op_get_global_var: {
PredictedType prediction = getStrongPrediction();
PredictedType prediction = getPrediction();
NodeIndex getGlobalVar = addToGraph(GetGlobalVar, OpInfo(currentInstruction[2].u.operand));
set(currentInstruction[1].u.operand, getGlobalVar);
m_graph.predictGlobalVar(currentInstruction[2].u.operand, prediction & ~PredictionTagMask, StrongPrediction);
m_graph.predictGlobalVar(curre