ObjectAllocationProfile.h [plain text]
#pragma once
#include "VM.h"
#include "JSGlobalObject.h"
#include "ObjectPrototype.h"
#include "SlotVisitor.h"
#include "WriteBarrier.h"
namespace JSC {
class ObjectAllocationProfile {
friend class LLIntOffsetsExtractor;
public:
static ptrdiff_t offsetOfAllocator() { return OBJECT_OFFSETOF(ObjectAllocationProfile, m_allocator); }
static ptrdiff_t offsetOfStructure() { return OBJECT_OFFSETOF(ObjectAllocationProfile, m_structure); }
static ptrdiff_t offsetOfInlineCapacity() { return OBJECT_OFFSETOF(ObjectAllocationProfile, m_inlineCapacity); }
ObjectAllocationProfile()
: m_allocator(0)
, m_inlineCapacity(0)
{
}
bool isNull() { return !m_structure; }
void initialize(VM& vm, JSGlobalObject* globalObject, JSCell* owner, JSObject* prototype, unsigned inferredInlineCapacity)
{
ASSERT(!m_allocator);
ASSERT(!m_structure);
ASSERT(!m_inlineCapacity);
unsigned inlineCapacity = 0;
if (inferredInlineCapacity < JSFinalObject::defaultInlineCapacity()) {
inferredInlineCapacity += possibleDefaultPropertyCount(vm, prototype);
if (!inferredInlineCapacity) {
inferredInlineCapacity = JSFinalObject::defaultInlineCapacity();
} else if (inferredInlineCapacity > JSFinalObject::defaultInlineCapacity()) {
inferredInlineCapacity = JSFinalObject::defaultInlineCapacity();
}
inlineCapacity = inferredInlineCapacity;
ASSERT(inlineCapacity < JSFinalObject::maxInlineCapacity());
} else {
inlineCapacity = inferredInlineCapacity;
if (inlineCapacity > JSFinalObject::maxInlineCapacity())
inlineCapacity = JSFinalObject::maxInlineCapacity();
}
ASSERT(inlineCapacity > 0);
ASSERT(inlineCapacity <= JSFinalObject::maxInlineCapacity());
size_t allocationSize = JSFinalObject::allocationSize(inlineCapacity);
MarkedAllocator* allocator = vm.cellSpace.allocatorFor(allocationSize);
if (allocator) {
size_t slop = (allocator->cellSize() - allocationSize) / sizeof(WriteBarrier<Unknown>);
inlineCapacity += slop;
if (inlineCapacity > JSFinalObject::maxInlineCapacity())
inlineCapacity = JSFinalObject::maxInlineCapacity();
}
Structure* structure = vm.prototypeMap.emptyObjectStructureForPrototype(globalObject, prototype, inlineCapacity);
WTF::storeStoreFence();
m_allocator = allocator;
m_structure.set(vm, owner, structure);
m_inlineCapacity = inlineCapacity;
}
Structure* structure()
{
Structure* structure = m_structure.get();
WTF::loadLoadFence();
return structure;
}
unsigned inlineCapacity() { return m_inlineCapacity; }
void clear()
{
m_allocator = 0;
m_structure.clear();
m_inlineCapacity = 0;
ASSERT(isNull());
}
void visitAggregate(SlotVisitor& visitor)
{
visitor.append(m_structure);
}
private:
unsigned possibleDefaultPropertyCount(VM& vm, JSObject* prototype)
{
if (prototype == prototype->globalObject()->objectPrototype())
return 0;
size_t count = 0;
PropertyNameArray propertyNameArray(&vm, PropertyNameMode::StringsAndSymbols);
prototype->structure()->getPropertyNamesFromStructure(vm, propertyNameArray, EnumerationMode());
PropertyNameArrayData::PropertyNameVector& propertyNameVector = propertyNameArray.data()->propertyNameVector();
for (size_t i = 0; i < propertyNameVector.size(); ++i) {
JSValue value = prototype->getDirect(vm, propertyNameVector[i]);
if (jsDynamicCast<JSFunction*>(vm, value))
continue;
++count;
}
return count;
}
MarkedAllocator* m_allocator; WriteBarrier<Structure> m_structure;
unsigned m_inlineCapacity;
};
}