#ifndef ArrayProfile_h
#define ArrayProfile_h
#include "ConcurrentJITLock.h"
#include "JSArray.h"
#include "Structure.h"
#include <wtf/HashMap.h>
#include <wtf/SegmentedVector.h>
namespace JSC {
class CodeBlock;
class LLIntOffsetsExtractor;
typedef unsigned ArrayModes;
#define asArrayModes(type) \
(static_cast<unsigned>(1) << static_cast<unsigned>(type))
#define ALL_NON_ARRAY_ARRAY_MODES \
(asArrayModes(NonArray) \
| asArrayModes(NonArrayWithInt32) \
| asArrayModes(NonArrayWithDouble) \
| asArrayModes(NonArrayWithContiguous) \
| asArrayModes(NonArrayWithArrayStorage) \
| asArrayModes(NonArrayWithSlowPutArrayStorage))
#define ALL_ARRAY_ARRAY_MODES \
(asArrayModes(ArrayClass) \
| asArrayModes(ArrayWithUndecided) \
| asArrayModes(ArrayWithInt32) \
| asArrayModes(ArrayWithDouble) \
| asArrayModes(ArrayWithContiguous) \
| asArrayModes(ArrayWithArrayStorage) \
| asArrayModes(ArrayWithSlowPutArrayStorage))
#define ALL_ARRAY_MODES (ALL_NON_ARRAY_ARRAY_MODES | ALL_ARRAY_ARRAY_MODES)
inline ArrayModes arrayModeFromStructure(Structure* structure)
{
return asArrayModes(structure->indexingType());
}
void dumpArrayModes(PrintStream&, ArrayModes);
MAKE_PRINT_ADAPTOR(ArrayModesDump, ArrayModes, dumpArrayModes);
inline bool mergeArrayModes(ArrayModes& left, ArrayModes right)
{
ArrayModes newModes = left | right;
if (newModes == left)
return false;
left = newModes;
return true;
}
inline bool arrayModesAreClearOrTop(ArrayModes modes)
{
return !modes || modes == ALL_ARRAY_MODES;
}
inline bool arrayModesAlreadyChecked(ArrayModes proven, ArrayModes expected)
{
return (expected | proven) == expected;
}
inline bool arrayModesInclude(ArrayModes arrayModes, IndexingType shape)
{
return !!(arrayModes & (asArrayModes(NonArray | shape) | asArrayModes(ArrayClass | shape)));
}
inline bool shouldUseSlowPutArrayStorage(ArrayModes arrayModes)
{
return arrayModesInclude(arrayModes, SlowPutArrayStorageShape);
}
inline bool shouldUseFastArrayStorage(ArrayModes arrayModes)
{
return arrayModesInclude(arrayModes, ArrayStorageShape);
}
inline bool shouldUseContiguous(ArrayModes arrayModes)
{
return arrayModesInclude(arrayModes, ContiguousShape);
}
inline bool shouldUseDouble(ArrayModes arrayModes)
{
return arrayModesInclude(arrayModes, DoubleShape);
}
inline bool shouldUseInt32(ArrayModes arrayModes)
{
return arrayModesInclude(arrayModes, Int32Shape);
}
inline bool hasSeenArray(ArrayModes arrayModes)
{
return arrayModes & ALL_ARRAY_ARRAY_MODES;
}
inline bool hasSeenNonArray(ArrayModes arrayModes)
{
return arrayModes & ALL_NON_ARRAY_ARRAY_MODES;
}
class ArrayProfile {
public:
ArrayProfile()
: m_bytecodeOffset(std::numeric_limits<unsigned>::max())
, m_lastSeenStructureID(0)
, m_mayStoreToHole(false)
, m_outOfBounds(false)
, m_mayInterceptIndexedAccesses(false)
, m_usesOriginalArrayStructures(true)
, m_didPerformFirstRunPruning(false)
, m_observedArrayModes(0)
{
}
ArrayProfile(unsigned bytecodeOffset)
: m_bytecodeOffset(bytecodeOffset)
, m_lastSeenStructureID(0)
, m_mayStoreToHole(false)
, m_outOfBounds(false)
, m_mayInterceptIndexedAccesses(false)
, m_usesOriginalArrayStructures(true)
, m_didPerformFirstRunPruning(false)
, m_observedArrayModes(0)
{
}
unsigned bytecodeOffset() const { return m_bytecodeOffset; }
StructureID* addressOfLastSeenStructureID() { return &m_lastSeenStructureID; }
ArrayModes* addressOfArrayModes() { return &m_observedArrayModes; }
bool* addressOfMayStoreToHole() { return &m_mayStoreToHole; }
bool* addressOfOutOfBounds() { return &m_outOfBounds; }
void observeStructure(Structure* structure)
{
m_lastSeenStructureID = structure->id();
}
void computeUpdatedPrediction(const ConcurrentJITLocker&, CodeBlock*);
ArrayModes observedArrayModes(const ConcurrentJITLocker&) const { return m_observedArrayModes; }
bool mayInterceptIndexedAccesses(const ConcurrentJITLocker&) const { return m_mayInterceptIndexedAccesses; }
bool mayStoreToHole(const ConcurrentJITLocker&) const { return m_mayStoreToHole; }
bool outOfBounds(const ConcurrentJITLocker&) const { return m_outOfBounds; }
bool usesOriginalArrayStructures(const ConcurrentJITLocker&) const { return m_usesOriginalArrayStructures; }
CString briefDescription(const ConcurrentJITLocker&, CodeBlock*);
CString briefDescriptionWithoutUpdating(const ConcurrentJITLocker&);
private:
friend class LLIntOffsetsExtractor;
static Structure* polymorphicStructure() { return static_cast<Structure*>(reinterpret_cast<void*>(1)); }
unsigned m_bytecodeOffset;
StructureID m_lastSeenStructureID;
bool m_mayStoreToHole; bool m_outOfBounds;
bool m_mayInterceptIndexedAccesses : 1;
bool m_usesOriginalArrayStructures : 1;
bool m_didPerformFirstRunPruning : 1;
ArrayModes m_observedArrayModes;
};
typedef SegmentedVector<ArrayProfile, 4, 0> ArrayProfileVector;
}
#endif // ArrayProfile_h