StructureRareData.cpp [plain text]
#include "config.h"
#include "StructureRareData.h"
#include "AdaptiveInferredPropertyValueWatchpointBase.h"
#include "JSPropertyNameEnumerator.h"
#include "JSString.h"
#include "JSCInlines.h"
#include "ObjectPropertyConditionSet.h"
namespace JSC {
const ClassInfo StructureRareData::s_info = { "StructureRareData", 0, 0, CREATE_METHOD_TABLE(StructureRareData) };
Structure* StructureRareData::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
{
return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info());
}
StructureRareData* StructureRareData::create(VM& vm, Structure* previous)
{
StructureRareData* rareData = new (NotNull, allocateCell<StructureRareData>(vm.heap)) StructureRareData(vm, previous);
rareData->finishCreation(vm);
return rareData;
}
void StructureRareData::destroy(JSCell* cell)
{
static_cast<StructureRareData*>(cell)->StructureRareData::~StructureRareData();
}
StructureRareData::StructureRareData(VM& vm, Structure* previous)
: JSCell(vm, vm.structureRareDataStructure.get())
, m_giveUpOnObjectToStringValueCache(false)
{
if (previous)
m_previous.set(vm, this, previous);
}
void StructureRareData::visitChildren(JSCell* cell, SlotVisitor& visitor)
{
StructureRareData* thisObject = jsCast<StructureRareData*>(cell);
ASSERT_GC_OBJECT_INHERITS(thisObject, info());
JSCell::visitChildren(thisObject, visitor);
visitor.append(&thisObject->m_previous);
visitor.append(&thisObject->m_objectToStringValue);
visitor.append(&thisObject->m_cachedPropertyNameEnumerator);
}
JSPropertyNameEnumerator* StructureRareData::cachedPropertyNameEnumerator() const
{
return m_cachedPropertyNameEnumerator.get();
}
void StructureRareData::setCachedPropertyNameEnumerator(VM& vm, JSPropertyNameEnumerator* enumerator)
{
m_cachedPropertyNameEnumerator.set(vm, this, enumerator);
}
class ObjectToStringAdaptiveInferredPropertyValueWatchpoint : public AdaptiveInferredPropertyValueWatchpointBase {
public:
typedef AdaptiveInferredPropertyValueWatchpointBase Base;
ObjectToStringAdaptiveInferredPropertyValueWatchpoint(const ObjectPropertyCondition&, StructureRareData*);
private:
void handleFire(const FireDetail&) override;
StructureRareData* m_structureRareData;
};
class ObjectToStringAdaptiveStructureWatchpoint : public Watchpoint {
public:
ObjectToStringAdaptiveStructureWatchpoint(const ObjectPropertyCondition&, StructureRareData*);
void install();
protected:
void fireInternal(const FireDetail&) override;
private:
ObjectPropertyCondition m_key;
StructureRareData* m_structureRareData;
};
void StructureRareData::setObjectToStringValue(ExecState* exec, VM& vm, Structure* ownStructure, JSString* value, PropertySlot toStringTagSymbolSlot)
{
if (m_giveUpOnObjectToStringValueCache)
return;
ObjectPropertyConditionSet conditionSet;
if (toStringTagSymbolSlot.isValue()) {
if (!toStringTagSymbolSlot.isCacheable() || toStringTagSymbolSlot.slotBase()->structure(vm) == ownStructure)
return;
conditionSet = generateConditionsForPrototypePropertyHit(vm, this, exec, ownStructure, toStringTagSymbolSlot.slotBase(), vm.propertyNames->toStringTagSymbol.impl());
ASSERT(!conditionSet.isValid() || conditionSet.hasOneSlotBaseCondition());
} else if (toStringTagSymbolSlot.isUnset())
conditionSet = generateConditionsForPropertyMiss(vm, this, exec, ownStructure, vm.propertyNames->toStringTagSymbol.impl());
else
return;
if (!conditionSet.isValid()) {
m_giveUpOnObjectToStringValueCache = true;
return;
}
ObjectPropertyCondition equivCondition;
for (const ObjectPropertyCondition& condition : conditionSet) {
if (condition.condition().kind() == PropertyCondition::Presence) {
ASSERT(isValidOffset(condition.offset()));
condition.object()->structure(vm)->startWatchingPropertyForReplacements(vm, condition.offset());
equivCondition = condition.attemptToMakeEquivalenceWithoutBarrier();
if (!equivCondition.isWatchable()) {
m_giveUpOnObjectToStringValueCache = true;
return;
}
} else if (!condition.isWatchable()) {
m_giveUpOnObjectToStringValueCache = true;
return;
}
}
ASSERT(conditionSet.structuresEnsureValidity());
for (ObjectPropertyCondition condition : conditionSet) {
if (condition.condition().kind() == PropertyCondition::Presence) {
m_objectToStringAdaptiveInferredValueWatchpoint = std::make_unique<ObjectToStringAdaptiveInferredPropertyValueWatchpoint>(equivCondition, this);
m_objectToStringAdaptiveInferredValueWatchpoint->install();
} else
m_objectToStringAdaptiveWatchpointSet.add(condition, this)->install();
}
m_objectToStringValue.set(vm, this, value);
}
inline void StructureRareData::clearObjectToStringValue()
{
m_objectToStringAdaptiveWatchpointSet.clear();
m_objectToStringAdaptiveInferredValueWatchpoint.reset();
m_objectToStringValue.clear();
}
ObjectToStringAdaptiveStructureWatchpoint::ObjectToStringAdaptiveStructureWatchpoint(const ObjectPropertyCondition& key, StructureRareData* structureRareData)
: m_key(key)
, m_structureRareData(structureRareData)
{
RELEASE_ASSERT(key.watchingRequiresStructureTransitionWatchpoint());
RELEASE_ASSERT(!key.watchingRequiresReplacementWatchpoint());
}
void ObjectToStringAdaptiveStructureWatchpoint::install()
{
RELEASE_ASSERT(m_key.isWatchable());
m_key.object()->structure()->addTransitionWatchpoint(this);
}
void ObjectToStringAdaptiveStructureWatchpoint::fireInternal(const FireDetail& detail)
{
if (m_key.isWatchable(PropertyCondition::EnsureWatchability)) {
install();
return;
}
StringPrintStream out;
out.print("ObjectToStringValue Adaptation of ", m_key, " failed: ", detail);
StringFireDetail stringDetail(out.toCString().data());
m_structureRareData->clearObjectToStringValue();
}
ObjectToStringAdaptiveInferredPropertyValueWatchpoint::ObjectToStringAdaptiveInferredPropertyValueWatchpoint(const ObjectPropertyCondition& key, StructureRareData* structureRareData)
: Base(key)
, m_structureRareData(structureRareData)
{
}
void ObjectToStringAdaptiveInferredPropertyValueWatchpoint::handleFire(const FireDetail& detail)
{
StringPrintStream out;
out.print("Adaptation of ", key(), " failed: ", detail);
StringFireDetail stringDetail(out.toCString().data());
m_structureRareData->clearObjectToStringValue();
}
}