]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - runtime/StructureTransitionTable.h
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / runtime / StructureTransitionTable.h
index adebad28480c24db39a5015da6cdad4add0747d3..7fd3c77581ef39096c84eaa1153495282e532325 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009, 2013 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
 #ifndef StructureTransitionTable_h
 #define StructureTransitionTable_h
 
-#include "UString.h"
+#include "IndexingType.h"
 #include "WeakGCMap.h"
 #include <wtf/HashFunctions.h>
-#include <wtf/HashTraits.h>
-#include <wtf/OwnPtr.h>
-#include <wtf/RefPtr.h>
+#include <wtf/text/UniquedStringImpl.h>
 
 namespace JSC {
 
+class JSCell;
 class Structure;
 
+static const unsigned FirstInternalAttribute = 1 << 6; // Use for transitions that don't have to do with property additions.
+
+// Support for attributes used to indicate transitions not related to properties.
+// If any of these are used, the string portion of the key should be 0.
+enum NonPropertyTransition {
+    AllocateUndecided,
+    AllocateInt32,
+    AllocateDouble,
+    AllocateContiguous,
+    AllocateArrayStorage,
+    AllocateSlowPutArrayStorage,
+    SwitchToSlowPutArrayStorage,
+    AddIndexedAccessors
+};
+
+inline unsigned toAttributes(NonPropertyTransition transition)
+{
+    return transition + FirstInternalAttribute;
+}
+
+inline IndexingType newIndexingType(IndexingType oldType, NonPropertyTransition transition)
+{
+    switch (transition) {
+    case AllocateUndecided:
+        ASSERT(!hasIndexedProperties(oldType));
+        return oldType | UndecidedShape;
+    case AllocateInt32:
+        ASSERT(!hasIndexedProperties(oldType) || hasUndecided(oldType));
+        return (oldType & ~IndexingShapeMask) | Int32Shape;
+    case AllocateDouble:
+        ASSERT(!hasIndexedProperties(oldType) || hasUndecided(oldType) || hasInt32(oldType));
+        return (oldType & ~IndexingShapeMask) | DoubleShape;
+    case AllocateContiguous:
+        ASSERT(!hasIndexedProperties(oldType) || hasUndecided(oldType) || hasInt32(oldType) || hasDouble(oldType));
+        return (oldType & ~IndexingShapeMask) | ContiguousShape;
+    case AllocateArrayStorage:
+        ASSERT(!hasIndexedProperties(oldType) || hasUndecided(oldType) || hasInt32(oldType) || hasDouble(oldType) || hasContiguous(oldType));
+        return (oldType & ~IndexingShapeMask) | ArrayStorageShape;
+    case AllocateSlowPutArrayStorage:
+        ASSERT(!hasIndexedProperties(oldType) || hasUndecided(oldType) || hasInt32(oldType) || hasDouble(oldType) || hasContiguous(oldType) || hasContiguous(oldType));
+        return (oldType & ~IndexingShapeMask) | SlowPutArrayStorageShape;
+    case SwitchToSlowPutArrayStorage:
+        ASSERT(hasArrayStorage(oldType));
+        return (oldType & ~IndexingShapeMask) | SlowPutArrayStorageShape;
+    case AddIndexedAccessors:
+        return oldType | MayHaveIndexedAccessors;
+    default:
+        RELEASE_ASSERT_NOT_REACHED();
+        return oldType;
+    }
+}
+
 class StructureTransitionTable {
     static const intptr_t UsingSingleSlotFlag = 1;
 
+    
     struct Hash {
-        typedef std::pair<RefPtr<StringImpl>, unsigned> Key;
+        typedef std::pair<UniquedStringImpl*, unsigned> Key;
+        
         static unsigned hash(const Key& p)
         {
-            return p.first->existingHash();
+            return PtrHash<UniquedStringImpl*>::hash(p.first) + p.second;
         }
 
         static bool equal(const Key& a, const Key& b)
@@ -55,35 +108,7 @@ class StructureTransitionTable {
         static const bool safeToCompareToEmptyOrDeleted = true;
     };
 
-    struct HashTraits {
-        typedef WTF::HashTraits<RefPtr<StringImpl> > FirstTraits;
-        typedef WTF::GenericHashTraits<unsigned> SecondTraits;
-        typedef std::pair<FirstTraits::TraitType, SecondTraits::TraitType > TraitType;
-
-        static const bool emptyValueIsZero = FirstTraits::emptyValueIsZero && SecondTraits::emptyValueIsZero;
-        static TraitType emptyValue() { return std::make_pair(FirstTraits::emptyValue(), SecondTraits::emptyValue()); }
-
-        static const bool needsDestruction = FirstTraits::needsDestruction || SecondTraits::needsDestruction;
-
-        static void constructDeletedValue(TraitType& slot) { FirstTraits::constructDeletedValue(slot.first); }
-        static bool isDeletedValue(const TraitType& value) { return FirstTraits::isDeletedValue(value.first); }
-    };
-
-    struct WeakGCMapFinalizerCallback {
-        static void* finalizerContextFor(Hash::Key)
-        {
-            return 0;
-        }
-
-        static inline Hash::Key keyForFinalizer(void* context, Structure* structure)
-        {
-            return keyForWeakGCMapFinalizer(context, structure);
-        }
-    };
-
-    typedef WeakGCMap<Hash::Key, Structure, WeakGCMapFinalizerCallback, Hash, HashTraits> TransitionMap;
-
-    static Hash::Key keyForWeakGCMapFinalizer(void* context, Structure*);
+    typedef WeakGCMap<Hash::Key, Structure, Hash> TransitionMap;
 
 public:
     StructureTransitionTable()
@@ -93,16 +118,20 @@ public:
 
     ~StructureTransitionTable()
     {
-        if (!isUsingSingleSlot())
+        if (!isUsingSingleSlot()) {
             delete map();
-        else
-            clearSingleTransition();
+            return;
+        }
+
+        WeakImpl* impl = this->weakImpl();
+        if (!impl)
+            return;
+        WeakSet::deallocate(impl);
     }
 
-    inline void add(JSGlobalData&, Structure*);
-    inline void remove(Structure*);
-    inline bool contains(StringImpl* rep, unsigned attributes) const;
-    inline Structure* get(StringImpl* rep, unsigned attributes) const;
+    void add(VM&, Structure*);
+    bool contains(UniquedStringImpl*, unsigned attributes) const;
+    Structure* get(UniquedStringImpl*, unsigned attributes) const;
 
 private:
     bool isUsingSingleSlot() const
@@ -116,18 +145,18 @@ private:
         return reinterpret_cast<TransitionMap*>(m_data);
     }
 
-    HandleSlot slot() const
+    WeakImpl* weakImpl() const
     {
         ASSERT(isUsingSingleSlot());
-        return reinterpret_cast<HandleSlot>(m_data & ~UsingSingleSlotFlag);
+        return reinterpret_cast<WeakImpl*>(m_data & ~UsingSingleSlotFlag);
     }
 
     void setMap(TransitionMap* map)
     {
         ASSERT(isUsingSingleSlot());
         
-        if (HandleSlot slot = this->slot())
-            HandleHeap::heapFor(slot)->deallocate(slot);
+        if (WeakImpl* impl = this->weakImpl())
+            WeakSet::deallocate(impl);
 
         // This implicitly clears the flag that indicates we're using a single transition
         m_data = reinterpret_cast<intptr_t>(map);
@@ -138,31 +167,20 @@ private:
     Structure* singleTransition() const
     {
         ASSERT(isUsingSingleSlot());
-        if (HandleSlot slot = this->slot()) {
-            if (*slot)
-                return reinterpret_cast<Structure*>(slot->asCell());
+        if (WeakImpl* impl = this->weakImpl()) {
+            if (impl->state() == WeakImpl::Live)
+                return reinterpret_cast<Structure*>(impl->jsValue().asCell());
         }
         return 0;
     }
     
-    void clearSingleTransition()
-    {
-        ASSERT(isUsingSingleSlot());
-        if (HandleSlot slot = this->slot())
-            HandleHeap::heapFor(slot)->deallocate(slot);
-    }
-    
-    void setSingleTransition(JSGlobalData& globalData, Structure* structure)
+    void setSingleTransition(VM&, Structure* structure)
     {
         ASSERT(isUsingSingleSlot());
-        HandleSlot slot = this->slot();
-        if (!slot) {
-            slot = globalData.allocateGlobalHandle();
-            HandleHeap::heapFor(slot)->makeWeak(slot, 0, 0);
-            m_data = reinterpret_cast<intptr_t>(slot) | UsingSingleSlotFlag;
-        }
-        HandleHeap::heapFor(slot)->writeBarrier(slot, reinterpret_cast<JSCell*>(structure));
-        *slot = reinterpret_cast<JSCell*>(structure);
+        if (WeakImpl* impl = this->weakImpl())
+            WeakSet::deallocate(impl);
+        WeakImpl* impl = WeakSet::allocate(reinterpret_cast<JSCell*>(structure));
+        m_data = reinterpret_cast<intptr_t>(impl) | UsingSingleSlotFlag;
     }
 
     intptr_t m_data;