#ifndef ArrayProfile_h
#define ArrayProfile_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 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_lastSeenStructure(0)
, m_expectedStructure(0)
, m_mayStoreToHole(false)
, m_outOfBounds(false)
, m_mayInterceptIndexedAccesses(false)
, m_usesOriginalArrayStructures(true)
, m_observedArrayModes(0)
{
}
ArrayProfile(unsigned bytecodeOffset)
: m_bytecodeOffset(bytecodeOffset)
, m_lastSeenStructure(0)
, m_expectedStructure(0)
, m_mayStoreToHole(false)
, m_outOfBounds(false)
, m_mayInterceptIndexedAccesses(false)
, m_usesOriginalArrayStructures(true)
, m_observedArrayModes(0)
{
}
unsigned bytecodeOffset() const { return m_bytecodeOffset; }
Structure** addressOfLastSeenStructure() { return &m_lastSeenStructure; }
ArrayModes* addressOfArrayModes() { return &m_observedArrayModes; }
bool* addressOfMayStoreToHole() { return &m_mayStoreToHole; }
bool* addressOfOutOfBounds() { return &m_outOfBounds; }
void observeStructure(Structure* structure)
{
m_lastSeenStructure = structure;
}
void computeUpdatedPrediction(CodeBlock*, OperationInProgress = NoOperation);
Structure* expectedStructure() const
{
if (structureIsPolymorphic())
return 0;
return m_expectedStructure;
}
bool structureIsPolymorphic() const
{
return m_expectedStructure == polymorphicStructure();
}
bool hasDefiniteStructure() const
{
return !structureIsPolymorphic() && m_expectedStructure;
}
ArrayModes observedArrayModes() const { return m_observedArrayModes; }
ArrayModes updatedObservedArrayModes() const; bool mayInterceptIndexedAccesses() const { return m_mayInterceptIndexedAccesses; }
bool mayStoreToHole() const { return m_mayStoreToHole; }
bool outOfBounds() const { return m_outOfBounds; }
bool usesOriginalArrayStructures() const { return m_usesOriginalArrayStructures; }
CString briefDescription(CodeBlock*);
private:
friend class LLIntOffsetsExtractor;
static Structure* polymorphicStructure() { return static_cast<Structure*>(reinterpret_cast<void*>(1)); }
unsigned m_bytecodeOffset;
Structure* m_lastSeenStructure;
Structure* m_expectedStructure;
bool m_mayStoreToHole; bool m_outOfBounds;
bool m_mayInterceptIndexedAccesses;
bool m_usesOriginalArrayStructures;
ArrayModes m_observedArrayModes;
};
typedef SegmentedVector<ArrayProfile, 4, 0> ArrayProfileVector;
}
#endif // ArrayProfile_h