]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - runtime/StructureInlines.h
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / runtime / StructureInlines.h
index 75ca40dd7a134d82fb24db509728e86ac4221da9..5c3aed77151a9b237b676aaadec5bc01162cf74e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *    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,6 +26,7 @@
 #ifndef StructureInlines_h
 #define StructureInlines_h
 
+#include "JSArrayBufferView.h"
 #include "PropertyMapHashTable.h"
 #include "Structure.h"
 
@@ -48,7 +49,7 @@ 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)
 {
     ASSERT(vm.structureStructure);
     Structure* newStructure = new (NotNull, allocateCell<Structure>(vm.heap)) Structure(vm, structure);
@@ -56,82 +57,119 @@ inline Structure* Structure::create(VM& vm, const Structure* structure)
     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;
+    JSValue value = m_prototype.get();
+    if (value.isNull())
+        return nullptr;
+    return asObject(value);
+}
 
-    PropertyMapEntry* entry = propertyTable()->find(propertyName.uid()).first;
-    return entry ? entry->offset : invalidOffset;
+inline Structure* Structure::storedPrototypeStructure() const
+{
+    JSObject* object = storedPrototypeObject();
+    if (!object)
+        return nullptr;
+    return object->structure();
 }
 
-inline PropertyOffset Structure::get(VM& vm, const WTF::String& name)
+ALWAYS_INLINE PropertyOffset Structure::get(VM& vm, PropertyName propertyName)
 {
-    ASSERT(structure()->classInfo() == &s_info);
-    materializePropertyMapIfNecessary(vm);
-    if (!propertyTable())
+    ASSERT(!isCompilationThread());
+    ASSERT(structure()->classInfo() == info());
+    PropertyTable* propertyTable;
+    materializePropertyMapIfNecessary(vm, propertyTable);
+    if (!propertyTable)
         return invalidOffset;
 
-    PropertyMapEntry* entry = propertyTable()->findWithString(name.impl()).first;
+    PropertyMapEntry* entry = propertyTable->get(propertyName.uid());
     return entry ? entry->offset : invalidOffset;
 }
     
-inline bool Structure::masqueradesAsUndefined(JSGlobalObject* lexicalGlobalObject)
+ALWAYS_INLINE PropertyOffset Structure::get(VM& vm, PropertyName propertyName, unsigned& attributes)
 {
-    return typeInfo().masqueradesAsUndefined() && globalObject() == lexicalGlobalObject;
+    ASSERT(!isCompilationThread());
+    ASSERT(structure()->classInfo() == info());
+
+    PropertyTable* propertyTable;
+    materializePropertyMapIfNecessary(vm, propertyTable);
+    if (!propertyTable)
+        return invalidOffset;
+
+    PropertyMapEntry* entry = propertyTable->get(propertyName.uid());
+    if (!entry)
+        return invalidOffset;
+
+    attributes = entry->attributes;
+    return entry->offset;
 }
 
-ALWAYS_INLINE void SlotVisitor::internalAppend(JSCell* cell)
+template<typename Functor>
+void Structure::forEachPropertyConcurrently(const Functor& functor)
 {
-    ASSERT(!m_isCheckingForDefaultMarkViolation);
-    if (!cell)
-        return;
-#if ENABLE(GC_VALIDATION)
-    validate(cell);
-#endif
-    if (Heap::testAndSetMarked(cell) || !cell->structure())
-        return;
-
-    m_visitCount++;
+    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;
         
-    MARK_LOG_CHILD(*this, cell);
+        if (!functor(PropertyMapEntry(structure->m_nameInPrevious.get(), structure->m_offset, structure->attributesInPrevious())))
+            return;
+    }
+}
 
-    // Should never attempt to mark something that is zapped.
-    ASSERT(!cell->isZapped());
-        
-    m_stack.append(cell);
+inline PropertyOffset Structure::getConcurrently(UniquedStringImpl* uid)
+{
+    unsigned attributesIgnored;
+    return getConcurrently(uid, attributesIgnored);
 }
 
-inline bool Structure::transitivelyTransitionedFrom(Structure* structureToFind)
+inline bool Structure::hasIndexingHeader(const JSCell* cell) const
 {
-    for (Structure* current = this; current; current = current->previousID()) {
-        if (current == structureToFind)
-            return true;
-    }
-    return false;
+    if (hasIndexedProperties(indexingType()))
+        return true;
+    
+    if (!isTypedView(m_classInfo->typedArrayStorageType))
+        return false;
+    
+    return jsCast<const JSArrayBufferView*>(cell)->mode() == WastefulTypedArray;
 }
 
-inline void Structure::setEnumerationCache(VM& vm, JSPropertyNameIterator* enumerationCache)
+inline bool Structure::masqueradesAsUndefined(JSGlobalObject* lexicalGlobalObject)
 {
-    ASSERT(!isDictionary());
-    if (!typeInfo().structureHasRareData())
-        allocateRareData(vm);
-    rareData()->setEnumerationCache(vm, this, enumerationCache);
+    return typeInfo().masqueradesAsUndefined() && globalObject() == lexicalGlobalObject;
 }
 
-inline JSPropertyNameIterator* Structure::enumerationCache()
+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();
@@ -200,19 +238,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));
@@ -220,6 +290,18 @@ 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());
+}
+
 } // namespace JSC
 
 #endif // StructureInlines_h