summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/runtime/StructureRareData.cpp
diff options
context:
space:
mode:
authorKonstantin Tokarev <annulen@yandex.ru>2016-08-25 19:20:41 +0300
committerKonstantin Tokarev <annulen@yandex.ru>2017-02-02 12:30:55 +0000
commit6882a04fb36642862b11efe514251d32070c3d65 (patch)
treeb7959826000b061fd5ccc7512035c7478742f7b0 /Source/JavaScriptCore/runtime/StructureRareData.cpp
parentab6df191029eeeb0b0f16f127d553265659f739e (diff)
downloadqtwebkit-6882a04fb36642862b11efe514251d32070c3d65.tar.gz
Imported QtWebKit TP3 (git b57bc6801f1876c3220d5a4bfea33d620d477443)
Change-Id: I3b1d8a2808782c9f34d50240000e20cb38d3680f Reviewed-by: Konstantin Tokarev <annulen@yandex.ru>
Diffstat (limited to 'Source/JavaScriptCore/runtime/StructureRareData.cpp')
-rw-r--r--Source/JavaScriptCore/runtime/StructureRareData.cpp180
1 files changed, 161 insertions, 19 deletions
diff --git a/Source/JavaScriptCore/runtime/StructureRareData.cpp b/Source/JavaScriptCore/runtime/StructureRareData.cpp
index 00880d32c..add963ce4 100644
--- a/Source/JavaScriptCore/runtime/StructureRareData.cpp
+++ b/Source/JavaScriptCore/runtime/StructureRareData.cpp
@@ -26,16 +26,19 @@
#include "config.h"
#include "StructureRareData.h"
+#include "AdaptiveInferredPropertyValueWatchpointBase.h"
+#include "JSPropertyNameEnumerator.h"
#include "JSString.h"
-#include "Operations.h"
+#include "JSCInlines.h"
+#include "ObjectPropertyConditionSet.h"
namespace JSC {
-const ClassInfo StructureRareData::s_info = { "StructureRareData", 0, 0, 0, CREATE_METHOD_TABLE(StructureRareData) };
+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(CompoundType, StructureFlags), &s_info);
+ return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info());
}
StructureRareData* StructureRareData::create(VM& vm, Structure* previous)
@@ -45,39 +48,178 @@ StructureRareData* StructureRareData::create(VM& vm, Structure* previous)
return rareData;
}
-StructureRareData* StructureRareData::clone(VM& vm, const StructureRareData* other)
+void StructureRareData::destroy(JSCell* cell)
{
- StructureRareData* newRareData = new (NotNull, allocateCell<StructureRareData>(vm.heap)) StructureRareData(vm, other);
- newRareData->finishCreation(vm);
- return newRareData;
+ 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);
}
-StructureRareData::StructureRareData(VM& vm, const StructureRareData* other)
- : JSCell(vm, other->structure())
-{
- if (other->previousID())
- m_previous.set(vm, this, other->previousID());
- if (other->objectToStringValue())
- m_objectToStringValue.set(vm, this, other->objectToStringValue());
-}
-
void StructureRareData::visitChildren(JSCell* cell, SlotVisitor& visitor)
{
StructureRareData* thisObject = jsCast<StructureRareData*>(cell);
- ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
- ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
+ ASSERT_GC_OBJECT_INHERITS(thisObject, info());
JSCell::visitChildren(thisObject, visitor);
visitor.append(&thisObject->m_previous);
visitor.append(&thisObject->m_objectToStringValue);
- visitor.append(&thisObject->m_enumerationCache);
+ 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);
+}
+
+// ----------- Object.prototype.toString() helper watchpoint classes -----------
+
+class ObjectToStringAdaptiveInferredPropertyValueWatchpoint : public AdaptiveInferredPropertyValueWatchpointBase {
+public:
+ typedef AdaptiveInferredPropertyValueWatchpointBase Base;
+ ObjectToStringAdaptiveInferredPropertyValueWatchpoint(const ObjectPropertyCondition&, StructureRareData*);
+
+private:
+ virtual void handleFire(const FireDetail&) override;
+
+ StructureRareData* m_structureRareData;
+};
+
+class ObjectToStringAdaptiveStructureWatchpoint : public Watchpoint {
+public:
+ ObjectToStringAdaptiveStructureWatchpoint(const ObjectPropertyCondition&, StructureRareData*);
+
+ void install();
+
+protected:
+ virtual 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()) {
+ // We don't handle the own property case of Symbol.toStringTag because we would never know if a new
+ // object transitioning to the same structure had the same value stored in Symbol.toStringTag.
+ // Additionally, this is a super unlikely case anyway.
+ if (!toStringTagSymbolSlot.isCacheable() || toStringTagSymbolSlot.slotBase()->structure(vm) == ownStructure)
+ return;
+
+
+ // This will not create a condition for the current structure but that is good because we know the Symbol.toStringTag
+ // is not on the ownStructure so we will transisition if one is added and this cache will no longer be used.
+ conditionSet = generateConditionsForPrototypePropertyHit(vm, this, exec, ownStructure, toStringTagSymbolSlot.slotBase(), vm.propertyNames->toStringTagSymbol.impl());
+ ASSERT(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();
+
+ // The equivalence condition won't be watchable if we have already seen a replacement.
+ 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();
+}
+
+// ------------- Methods for Object.prototype.toString() helper watchpoint classes --------------
+
+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();
}
} // namespace JSC