fourthTier: Create an equivalent of Structure::get() that can work from a compilation thread
https://bugs.webkit.org/show_bug.cgi?id=114987

Reviewed by Geoffrey Garen.

This completes the work started by r148570. That patch made it possible to do
Structure::get() without modifying Structure. This patch takes this further, and
makes this thread-safe (for non-uncacheable-dictionaries) via
Structure::getConcurrently(). This method not only doesn't modify Structure, but
also ensures that any concurrent attempts to add to, remove from, or steal the
table from that structure doesn't mess up the result of the call. The call may
return invalidOffset even if a property is *just* about to be added, but it will
never do the reverse: if it returns a property then you can be sure that the
structure really does have that property and always will have it.

* bytecode/GetByIdStatus.cpp:
(JSC::GetByIdStatus::computeFromLLInt):
(JSC::GetByIdStatus::computeForChain):
(JSC::GetByIdStatus::computeFor):
* bytecode/PutByIdStatus.cpp:
(JSC::PutByIdStatus::computeFromLLInt):
(JSC::PutByIdStatus::computeFor):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::isStringPrototypeMethodSane):
* runtime/PropertyMapHashTable.h:
(PropertyTable):
(JSC::PropertyTable::findConcurrently):
(JSC):
(JSC::PropertyTable::add):
(JSC::PropertyTable::remove):
(JSC::PropertyTable::reinsert):
(JSC::PropertyTable::rehash):
* runtime/PropertyTable.cpp:
(JSC::PropertyTable::PropertyTable):
* runtime/Structure.cpp:
(JSC::Structure::findStructuresAndMapForMaterialization):
(JSC::Structure::getConcurrently):
* runtime/Structure.h:
(Structure):
* runtime/StructureInlines.h:
(JSC::Structure::getConcurrently):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@153128 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/runtime/Structure.h b/Source/JavaScriptCore/runtime/Structure.h
index 3d5ea4b..655c0bd 100644
--- a/Source/JavaScriptCore/runtime/Structure.h
+++ b/Source/JavaScriptCore/runtime/Structure.h
@@ -39,6 +39,8 @@
 #include "StructureTransitionTable.h"
 #include "JSTypeInfo.h"
 #include "Watchpoint.h"
+#include "Weak.h"
+#include <wtf/ByteSpinLock.h>
 #include <wtf/PassRefPtr.h>
 #include <wtf/RefCounted.h>
 #include <wtf/text/StringImpl.h>
@@ -68,6 +70,9 @@
     friend class StructureTransitionTable;
 
     typedef JSCell Base;
+    
+    typedef ByteSpinLock Lock;
+    typedef ByteSpinLocker Locker;
 
     static Structure* create(VM&, JSGlobalObject*, JSValue prototype, const TypeInfo&, const ClassInfo*, IndexingType = NonArray, unsigned inlineCapacity = 0);
 
@@ -235,8 +240,8 @@
     PropertyOffset get(VM&, const WTF::String& name);
     JS_EXPORT_PRIVATE PropertyOffset get(VM&, PropertyName, unsigned& attributes, JSCell*& specificValue);
 
-    PropertyOffset getWithoutMaterializing(VM&, PropertyName);
-    PropertyOffset getWithoutMaterializing(VM&, PropertyName, unsigned& attributes, JSCell*& specificValue);
+    PropertyOffset getConcurrently(VM&, PropertyName);
+    PropertyOffset getConcurrently(VM&, PropertyName, unsigned& attributes, JSCell*& specificValue);
 
     bool hasGetterSetterProperties() const { return m_hasGetterSetterProperties; }
     bool hasReadOnlyOrGetterSetterPropertiesExcludingProto() const { return m_hasReadOnlyOrGetterSetterPropertiesExcludingProto; }
@@ -360,8 +365,12 @@
     Structure(VM&, const Structure*);
 
     static Structure* create(VM&, const Structure*);
-        
-    void findStructuresAndMapForMaterialization(Vector<Structure*, 8>& structures, PropertyTable*&);
+    
+    // This will return the structure that has a usable property table, that property table,
+    // and the list of structures that we visited before we got to it. If it returns a
+    // non-null structure, it will also lock the structure that it returns; it is your job
+    // to unlock it.
+    void findStructuresAndMapForMaterialization(Vector<Structure*, 8>& structures, Structure*&, PropertyTable*&);
     
     typedef enum { 
         NoneDictionaryKind = 0,
@@ -373,7 +382,7 @@
     PropertyOffset putSpecificValue(VM&, PropertyName, unsigned attributes, JSCell* specificValue);
     PropertyOffset remove(PropertyName);
 
-    void createPropertyMap(VM&, unsigned keyCount = 0);
+    void createPropertyMap(const Locker&, VM&, unsigned keyCount = 0);
     void checkConsistency();
 
     bool despecifyFunction(VM&, PropertyName);
@@ -472,8 +481,10 @@
 
     TypeInfo m_typeInfo;
     IndexingType m_indexingType;
-
     uint8_t m_inlineCapacity;
+    
+    Lock m_lock;
+    
     unsigned m_dictionaryKind : 2;
     bool m_isPinnedPropertyTable : 1;
     bool m_hasGetterSetterProperties : 1;