#ifndef DFGOSRExit_h
#define DFGOSRExit_h
#include <wtf/Platform.h>
#if ENABLE(DFG_JIT)
#include "CodeOrigin.h"
#include "DFGCommon.h"
#include "DFGCorrectableJumpPoint.h"
#include "DFGExitProfile.h"
#include "DFGGPRInfo.h"
#include "MacroAssembler.h"
#include "MethodOfGettingAValueProfile.h"
#include "Operands.h"
#include "ValueProfile.h"
#include "ValueRecovery.h"
#include <wtf/Vector.h>
namespace JSC { namespace DFG {
class SpeculativeJIT;
enum SpeculationRecoveryType {
SpeculativeAdd,
BooleanSpeculationCheck
};
class SpeculationRecovery {
public:
SpeculationRecovery(SpeculationRecoveryType type, GPRReg dest, GPRReg src)
: m_type(type)
, m_dest(dest)
, m_src(src)
{
}
SpeculationRecoveryType type() { return m_type; }
GPRReg dest() { return m_dest; }
GPRReg src() { return m_src; }
private:
SpeculationRecoveryType m_type;
GPRReg m_dest;
GPRReg m_src;
};
struct OSRExit {
OSRExit(ExitKind, JSValueSource, MethodOfGettingAValueProfile, MacroAssembler::Jump, SpeculativeJIT*, unsigned recoveryIndex = 0);
MacroAssemblerCodeRef m_code;
JSValueSource m_jsValueSource;
MethodOfGettingAValueProfile m_valueProfile;
CorrectableJumpPoint m_check;
NodeIndex m_nodeIndex;
CodeOrigin m_codeOrigin;
CodeOrigin m_codeOriginForExitProfile;
unsigned m_recoveryIndex;
ExitKind m_kind;
uint32_t m_count;
int numberOfRecoveries() const { return m_arguments.size() + m_variables.size(); }
const ValueRecovery& valueRecovery(int index) const
{
if (index < (int)m_arguments.size())
return m_arguments[index];
return m_variables[index - m_arguments.size()];
}
ValueRecovery& valueRecoveryForOperand(int operand)
{
if (operandIsArgument(operand))
return m_arguments[operandToArgument(operand)];
return m_variables[operand];
}
bool isArgument(int index) const { return index < (int)m_arguments.size(); }
bool isVariable(int index) const { return !isArgument(index); }
int argumentForIndex(int index) const
{
return index;
}
int variableForIndex(int index) const
{
return index - m_arguments.size();
}
int operandForIndex(int index) const
{
if (index < (int)m_arguments.size())
return operandToArgument(index);
return index - m_arguments.size();
}
bool considerAddingAsFrequentExitSite(CodeBlock* dfgCodeBlock, CodeBlock* profiledCodeBlock)
{
if (!m_count || !exitKindIsCountable(m_kind))
return false;
return considerAddingAsFrequentExitSiteSlow(dfgCodeBlock, profiledCodeBlock);
}
void dump(FILE* out) const;
Vector<ValueRecovery, 0> m_arguments;
Vector<ValueRecovery, 0> m_variables;
int m_lastSetOperand;
private:
bool considerAddingAsFrequentExitSiteSlow(CodeBlock* dfgCodeBlock, CodeBlock* profiledCodeBlock);
};
#if DFG_ENABLE(VERBOSE_SPECULATION_FAILURE)
struct SpeculationFailureDebugInfo {
CodeBlock* codeBlock;
NodeIndex nodeIndex;
};
#endif
} }
#endif // ENABLE(DFG_JIT)
#endif // DFGOSRExit_h