summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/runtime/StructureInlines.h
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/runtime/StructureInlines.h')
-rw-r--r--Source/JavaScriptCore/runtime/StructureInlines.h200
1 files changed, 146 insertions, 54 deletions
diff --git a/Source/JavaScriptCore/runtime/StructureInlines.h b/Source/JavaScriptCore/runtime/StructureInlines.h
index 8407ca791..21bcaa517 100644
--- a/Source/JavaScriptCore/runtime/StructureInlines.h
+++ b/Source/JavaScriptCore/runtime/StructureInlines.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -26,9 +26,12 @@
#ifndef StructureInlines_h
#define StructureInlines_h
+#include "JSArrayBufferView.h"
+#include "JSCJSValueInlines.h"
#include "JSGlobalObject.h"
#include "PropertyMapHashTable.h"
#include "Structure.h"
+#include "StructureChain.h"
namespace JSC {
@@ -49,90 +52,128 @@ inline Structure* Structure::createStructure(VM& vm)
return structure;
}
-inline Structure* Structure::create(VM& vm, const Structure* structure)
+inline Structure* Structure::create(VM& vm, Structure* structure, DeferredStructureTransitionWatchpointFire* deferred)
{
ASSERT(vm.structureStructure);
- Structure* newStructure = new (NotNull, allocateCell<Structure>(vm.heap)) Structure(vm, structure);
+ Structure* newStructure = new (NotNull, allocateCell<Structure>(vm.heap)) Structure(vm, structure, deferred);
newStructure->finishCreation(vm);
return newStructure;
}
-inline PropertyOffset Structure::get(VM& vm, PropertyName propertyName)
+inline JSObject* Structure::storedPrototypeObject() const
{
- ASSERT(structure()->classInfo() == &s_info);
- materializePropertyMapIfNecessary(vm);
- if (!propertyTable())
- return invalidOffset;
-
- PropertyMapEntry* entry = propertyTable()->find(propertyName.uid()).first;
- return entry ? entry->offset : invalidOffset;
+ JSValue value = m_prototype.get();
+ if (value.isNull())
+ return nullptr;
+ return asObject(value);
}
-inline PropertyOffset Structure::get(VM& vm, const WTF::String& name)
+inline Structure* Structure::storedPrototypeStructure() const
{
- ASSERT(structure()->classInfo() == &s_info);
- materializePropertyMapIfNecessary(vm);
- if (!propertyTable())
- return invalidOffset;
+ JSObject* object = storedPrototypeObject();
+ if (!object)
+ return nullptr;
+ return object->structure();
+}
- PropertyMapEntry* entry = propertyTable()->findWithString(name.impl()).first;
- return entry ? entry->offset : invalidOffset;
+ALWAYS_INLINE PropertyOffset Structure::get(VM& vm, PropertyName propertyName)
+{
+ unsigned attributes;
+ bool hasInferredType;
+ return get(vm, propertyName, attributes, hasInferredType);
}
-inline bool Structure::masqueradesAsUndefined(JSGlobalObject* lexicalGlobalObject)
+ALWAYS_INLINE PropertyOffset Structure::get(VM& vm, PropertyName propertyName, unsigned& attributes)
{
- return typeInfo().masqueradesAsUndefined() && globalObject() == lexicalGlobalObject;
+ bool hasInferredType;
+ return get(vm, propertyName, attributes, hasInferredType);
}
-ALWAYS_INLINE void SlotVisitor::internalAppend(JSCell* cell)
+ALWAYS_INLINE PropertyOffset Structure::get(VM& vm, PropertyName propertyName, unsigned& attributes, bool& hasInferredType)
{
- ASSERT(!m_isCheckingForDefaultMarkViolation);
- if (!cell)
- return;
-#if ENABLE(GC_VALIDATION)
- validate(cell);
-#endif
- if (Heap::testAndSetMarked(cell) || !cell->structure())
- return;
+ ASSERT(!isCompilationThread());
+ ASSERT(structure()->classInfo() == info());
- m_visitCount++;
-
- MARK_LOG_CHILD(*this, cell);
+ PropertyTable* propertyTable;
+ materializePropertyMapIfNecessary(vm, propertyTable);
+ if (!propertyTable)
+ return invalidOffset;
- // Should never attempt to mark something that is zapped.
- ASSERT(!cell->isZapped());
-
- m_stack.append(cell);
+ PropertyMapEntry* entry = propertyTable->get(propertyName.uid());
+ if (!entry)
+ return invalidOffset;
+
+ attributes = entry->attributes;
+ hasInferredType = entry->hasInferredType;
+ return entry->offset;
}
-inline bool Structure::transitivelyTransitionedFrom(Structure* structureToFind)
+template<typename Functor>
+void Structure::forEachPropertyConcurrently(const Functor& functor)
{
- for (Structure* current = this; current; current = current->previousID()) {
- if (current == structureToFind)
- return true;
+ Vector<Structure*, 8> structures;
+ Structure* structure;
+ PropertyTable* table;
+
+ findStructuresAndMapForMaterialization(structures, structure, table);
+
+ if (table) {
+ for (auto& entry : *table) {
+ if (!functor(entry)) {
+ structure->m_lock.unlock();
+ return;
+ }
+ }
+ structure->m_lock.unlock();
+ }
+
+ for (unsigned i = structures.size(); i--;) {
+ structure = structures[i];
+ if (!structure->m_nameInPrevious)
+ continue;
+
+ if (!functor(PropertyMapEntry(structure->m_nameInPrevious.get(), structure->m_offset, structure->attributesInPrevious())))
+ return;
}
- return false;
}
-inline void Structure::setEnumerationCache(VM& vm, JSPropertyNameIterator* enumerationCache)
+inline PropertyOffset Structure::getConcurrently(UniquedStringImpl* uid)
{
- ASSERT(!isDictionary());
- if (!typeInfo().structureHasRareData())
- allocateRareData(vm);
- rareData()->setEnumerationCache(vm, this, enumerationCache);
+ unsigned attributesIgnored;
+ return getConcurrently(uid, attributesIgnored);
+}
+
+inline bool Structure::hasIndexingHeader(const JSCell* cell) const
+{
+ if (hasIndexedProperties(indexingType()))
+ return true;
+
+ if (!isTypedView(m_classInfo->typedArrayStorageType))
+ return false;
+
+ return jsCast<const JSArrayBufferView*>(cell)->mode() == WastefulTypedArray;
}
-inline JSPropertyNameIterator* Structure::enumerationCache()
+inline bool Structure::masqueradesAsUndefined(JSGlobalObject* lexicalGlobalObject)
+{
+ return typeInfo().masqueradesAsUndefined() && globalObject() == lexicalGlobalObject;
+}
+
+inline bool Structure::transitivelyTransitionedFrom(Structure* structureToFind)
{
- if (!typeInfo().structureHasRareData())
- return 0;
- return rareData()->enumerationCache();
+ for (Structure* current = this; current; current = current->previousID()) {
+ if (current == structureToFind)
+ return true;
+ }
+ return false;
}
inline JSValue Structure::prototypeForLookup(JSGlobalObject* globalObject) const
{
if (isObject())
return m_prototype.get();
+ if (typeInfo().type() == SymbolType)
+ return globalObject->symbolPrototype();
ASSERT(typeInfo().type() == StringType);
return globalObject->stringPrototype();
@@ -201,19 +242,51 @@ inline bool Structure::putWillGrowOutOfLineStorage()
ALWAYS_INLINE WriteBarrier<PropertyTable>& Structure::propertyTable()
{
- ASSERT(!globalObject() || !globalObject()->vm().heap.isBusy());
+ ASSERT(!globalObject() || !globalObject()->vm().heap.isCollecting());
return m_propertyTableUnsafe;
}
+inline void Structure::didReplaceProperty(PropertyOffset offset)
+{
+ if (LIKELY(!hasRareData()))
+ return;
+ StructureRareData::PropertyWatchpointMap* map = rareData()->m_replacementWatchpointSets.get();
+ if (LIKELY(!map))
+ return;
+ WatchpointSet* set = map->get(offset);
+ if (LIKELY(!set))
+ return;
+ set->fireAll("Property did get replaced");
+}
+
+inline WatchpointSet* Structure::propertyReplacementWatchpointSet(PropertyOffset offset)
+{
+ ConcurrentJITLocker locker(m_lock);
+ if (!hasRareData())
+ return nullptr;
+ WTF::loadLoadFence();
+ StructureRareData::PropertyWatchpointMap* map = rareData()->m_replacementWatchpointSets.get();
+ if (!map)
+ return nullptr;
+ return map->get(offset);
+}
+
ALWAYS_INLINE bool Structure::checkOffsetConsistency() const
{
PropertyTable* propertyTable = m_propertyTableUnsafe.get();
if (!propertyTable) {
- ASSERT(!m_isPinnedPropertyTable);
+ ASSERT(!isPinnedPropertyTable());
return true;
}
+ // We cannot reliably assert things about the property table in the concurrent
+ // compilation thread. It is possible for the table to be stolen and then have
+ // things added to it, which leads to the offsets being all messed up. We could
+ // get around this by grabbing a lock here, but I think that would be overkill.
+ if (isCompilationThread())
+ return true;
+
RELEASE_ASSERT(numberOfSlotsForLastOffset(m_offset, m_inlineCapacity) == propertyTable->propertyStorageSize());
unsigned totalSize = propertyTable->propertyStorageSize();
RELEASE_ASSERT((totalSize < inlineCapacity() ? 0 : totalSize - inlineCapacity()) == numberOfOutOfLineSlotsForLastOffset(m_offset));
@@ -221,6 +294,25 @@ ALWAYS_INLINE bool Structure::checkOffsetConsistency() const
return true;
}
+inline size_t nextOutOfLineStorageCapacity(size_t currentCapacity)
+{
+ if (!currentCapacity)
+ return initialOutOfLineCapacity;
+ return currentCapacity * outOfLineGrowthFactor;
+}
+
+inline size_t Structure::suggestedNewOutOfLineStorageCapacity()
+{
+ return nextOutOfLineStorageCapacity(outOfLineCapacity());
+}
+
+inline void Structure::setObjectToStringValue(ExecState* exec, VM& vm, JSString* value, PropertySlot toStringTagSymbolSlot)
+{
+ if (!hasRareData())
+ allocateRareData(vm);
+ rareData()->setObjectToStringValue(exec, vm, this, value, toStringTagSymbolSlot);
+}
+
} // namespace JSC
#endif // StructureInlines_h