diff options
Diffstat (limited to 'Source/JavaScriptCore/runtime/StructureInlines.h')
-rw-r--r-- | Source/JavaScriptCore/runtime/StructureInlines.h | 200 |
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 |