DFGVariableAccessData.cpp [plain text]
#include "config.h"
#include "DFGVariableAccessData.h"
#if ENABLE(DFG_JIT)
namespace JSC { namespace DFG {
VariableAccessData::VariableAccessData()
: m_local(static_cast<VirtualRegister>(std::numeric_limits<int>::min()))
, m_prediction(SpecNone)
, m_argumentAwarePrediction(SpecNone)
, m_flags(0)
, m_shouldNeverUnbox(false)
, m_structureCheckHoistingFailed(false)
, m_checkArrayHoistingFailed(false)
, m_isProfitableToUnbox(false)
, m_isLoadedFrom(false)
, m_doubleFormatState(EmptyDoubleFormatState)
{
clearVotes();
}
VariableAccessData::VariableAccessData(VirtualRegister local)
: m_local(local)
, m_prediction(SpecNone)
, m_argumentAwarePrediction(SpecNone)
, m_flags(0)
, m_shouldNeverUnbox(false)
, m_structureCheckHoistingFailed(false)
, m_checkArrayHoistingFailed(false)
, m_isProfitableToUnbox(false)
, m_isLoadedFrom(false)
, m_doubleFormatState(EmptyDoubleFormatState)
{
clearVotes();
}
bool VariableAccessData::mergeShouldNeverUnbox(bool shouldNeverUnbox)
{
bool newShouldNeverUnbox = m_shouldNeverUnbox | shouldNeverUnbox;
if (newShouldNeverUnbox == m_shouldNeverUnbox)
return false;
m_shouldNeverUnbox = newShouldNeverUnbox;
return true;
}
bool VariableAccessData::predict(SpeculatedType prediction)
{
VariableAccessData* self = find();
bool result = mergeSpeculation(self->m_prediction, prediction);
if (result)
mergeSpeculation(m_argumentAwarePrediction, m_prediction);
return result;
}
bool VariableAccessData::mergeArgumentAwarePrediction(SpeculatedType prediction)
{
return mergeSpeculation(find()->m_argumentAwarePrediction, prediction);
}
bool VariableAccessData::shouldUseDoubleFormatAccordingToVote()
{
if (local().isArgument())
return false;
if (!isFullNumberSpeculation(prediction())) {
return false;
}
if (isDoubleSpeculation(prediction()))
return true;
if (flags() & NodeBytecodeUsesAsInt)
return false;
if (voteRatio() >= Options::doubleVoteRatioForDoubleFormat())
return true;
return false;
}
bool VariableAccessData::tallyVotesForShouldUseDoubleFormat()
{
ASSERT(isRoot());
if (local().isArgument() || shouldNeverUnbox()
|| (flags() & NodeBytecodeUsesAsArrayIndex))
return DFG::mergeDoubleFormatState(m_doubleFormatState, NotUsingDoubleFormat);
if (m_doubleFormatState == CantUseDoubleFormat)
return false;
bool newValueOfShouldUseDoubleFormat = shouldUseDoubleFormatAccordingToVote();
if (!newValueOfShouldUseDoubleFormat) {
return false;
}
if (m_doubleFormatState == UsingDoubleFormat)
return false;
return DFG::mergeDoubleFormatState(m_doubleFormatState, UsingDoubleFormat);
}
bool VariableAccessData::mergeDoubleFormatState(DoubleFormatState doubleFormatState)
{
return DFG::mergeDoubleFormatState(find()->m_doubleFormatState, doubleFormatState);
}
bool VariableAccessData::makePredictionForDoubleFormat()
{
ASSERT(isRoot());
if (m_doubleFormatState != UsingDoubleFormat)
return false;
SpeculatedType type = m_prediction;
if (type & ~SpecBytecodeNumber)
type |= SpecDoublePureNaN;
if (type & SpecAnyInt)
type |= SpecAnyIntAsDouble;
return checkAndSet(m_prediction, type);
}
bool VariableAccessData::couldRepresentInt52()
{
if (shouldNeverUnbox())
return false;
return couldRepresentInt52Impl();
}
bool VariableAccessData::couldRepresentInt52Impl()
{
if (!enableInt52())
return false;
if (m_local.isArgument())
return false;
return !(argumentAwarePrediction() & ~SpecAnyInt);
}
FlushFormat VariableAccessData::flushFormat()
{
ASSERT(find() == this);
if (!shouldUnboxIfPossible())
return FlushedJSValue;
if (shouldUseDoubleFormat())
return FlushedDouble;
SpeculatedType prediction = argumentAwarePrediction();
if (!prediction)
return FlushedJSValue;
if (isInt32Speculation(prediction))
return FlushedInt32;
if (couldRepresentInt52Impl())
return FlushedInt52;
if (isCellSpeculation(prediction))
return FlushedCell;
if (isBooleanSpeculation(prediction))
return FlushedBoolean;
return FlushedJSValue;
}
} }
#endif // ENABLE(DFG_JIT)