#include "config.h"
#include "ArrayProfile.h"
#include "CodeBlock.h"
#include <wtf/StringExtras.h>
#include <wtf/StringPrintStream.h>
namespace JSC {
void dumpArrayModes(PrintStream& out, ArrayModes arrayModes)
{
if (!arrayModes) {
out.print("0:<empty>");
return;
}
if (arrayModes == ALL_ARRAY_MODES) {
out.print("TOP");
return;
}
out.print(arrayModes, ":");
if (arrayModes & asArrayModes(NonArray))
out.print("NonArray");
if (arrayModes & asArrayModes(NonArrayWithInt32))
out.print("NonArrayWithInt32");
if (arrayModes & asArrayModes(NonArrayWithDouble))
out.print("NonArrayWithDouble");
if (arrayModes & asArrayModes(NonArrayWithContiguous))
out.print("NonArrayWithContiguous");
if (arrayModes & asArrayModes(NonArrayWithArrayStorage))
out.print("NonArrayWithArrayStorage");
if (arrayModes & asArrayModes(NonArrayWithSlowPutArrayStorage))
out.print("NonArrayWithSlowPutArrayStorage");
if (arrayModes & asArrayModes(ArrayClass))
out.print("ArrayClass");
if (arrayModes & asArrayModes(ArrayWithUndecided))
out.print("ArrayWithUndecided");
if (arrayModes & asArrayModes(ArrayWithInt32))
out.print("ArrayWithInt32");
if (arrayModes & asArrayModes(ArrayWithDouble))
out.print("ArrayWithDouble");
if (arrayModes & asArrayModes(ArrayWithContiguous))
out.print("ArrayWithContiguous");
if (arrayModes & asArrayModes(ArrayWithArrayStorage))
out.print("ArrayWithArrayStorage");
if (arrayModes & asArrayModes(ArrayWithSlowPutArrayStorage))
out.print("ArrayWithSlowPutArrayStorage");
}
ArrayModes ArrayProfile::updatedObservedArrayModes() const
{
if (m_lastSeenStructure)
return m_observedArrayModes | arrayModeFromStructure(m_lastSeenStructure);
return m_observedArrayModes;
}
void ArrayProfile::computeUpdatedPrediction(CodeBlock* codeBlock, OperationInProgress operation)
{
const bool verbose = false;
if (m_lastSeenStructure) {
m_observedArrayModes |= arrayModeFromStructure(m_lastSeenStructure);
m_mayInterceptIndexedAccesses |=
m_lastSeenStructure->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero();
if (!codeBlock->globalObject()->isOriginalArrayStructure(m_lastSeenStructure))
m_usesOriginalArrayStructures = false;
if (!structureIsPolymorphic()) {
if (!m_expectedStructure)
m_expectedStructure = m_lastSeenStructure;
else if (m_expectedStructure != m_lastSeenStructure) {
if (verbose)
dataLog(*codeBlock, " bc#", m_bytecodeOffset, ": making structure polymorphic because ", RawPointer(m_expectedStructure), " (", m_expectedStructure->classInfo()->className, ") != ", RawPointer(m_lastSeenStructure), " (", m_lastSeenStructure->classInfo()->className, ")\n");
m_expectedStructure = polymorphicStructure();
}
}
m_lastSeenStructure = 0;
}
if (hasTwoOrMoreBitsSet(m_observedArrayModes)) {
if (verbose)
dataLog(*codeBlock, " bc#", m_bytecodeOffset, ": making structure polymorphic because two or more bits are set in m_observedArrayModes\n");
m_expectedStructure = polymorphicStructure();
}
if (operation == Collection
&& expectedStructure()
&& !Heap::isMarked(m_expectedStructure)) {
if (verbose)
dataLog(*codeBlock, " bc#", m_bytecodeOffset, ": making structure during GC\n");
m_expectedStructure = polymorphicStructure();
}
}
CString ArrayProfile::briefDescription(CodeBlock* codeBlock)
{
computeUpdatedPrediction(codeBlock);
StringPrintStream out;
bool hasPrinted = false;
if (m_observedArrayModes) {
if (hasPrinted)
out.print(", ");
out.print(ArrayModesDump(m_observedArrayModes));
hasPrinted = true;
}
if (structureIsPolymorphic()) {
if (hasPrinted)
out.print(", ");
out.print("struct = TOP");
hasPrinted = true;
} else if (m_expectedStructure) {
if (hasPrinted)
out.print(", ");
out.print("struct = ", RawPointer(m_expectedStructure));
hasPrinted = true;
}
if (m_mayStoreToHole) {
if (hasPrinted)
out.print(", ");
out.print("Hole");
hasPrinted = true;
}
if (m_outOfBounds) {
if (hasPrinted)
out.print(", ");
out.print("OutOfBounds");
hasPrinted = true;
}
if (m_mayInterceptIndexedAccesses) {
if (hasPrinted)
out.print(", ");
out.print("Intercept");
hasPrinted = true;
}
if (m_usesOriginalArrayStructures) {
if (hasPrinted)
out.print(", ");
out.print("Original");
hasPrinted = true;
}
UNUSED_PARAM(hasPrinted);
return out.toCString();
}
}