Title: [153120] trunk/Source/_javascript_Core
Revision
153120
Author
[email protected]
Date
2013-07-24 20:58:27 -0700 (Wed, 24 Jul 2013)

Log Message

fourthTier: DFG should be able to query Structure without modifying it
https://bugs.webkit.org/show_bug.cgi?id=114708

Reviewed by Oliver Hunt.

This is work towards allowing the DFG, and FTL, to run on a separate thread.
The idea is that the most evil thing that the DFG does that has thread-safety
issues is fiddling with Structures by calling Structure::get(). This can lead
to rematerialization of property tables, which is definitely not thread-safe
due to how StringImpl works. So, this patch completely side-steps the problem
by creating a new version of Structure::get, called
Structure::getWithoutMaterializing, which may choose to do an O(n) search if
necessary to avoid materialization. I believe this should be fine - the DFG
does't call into these code path often enough for this to matter, and most of
the time, the Structure that we call this on will already have a property
table because some inline cache would have already called ::get() on that
Structure.

Also cleaned up the materialization logic: we can stop the search as soon as
we find any Structure with a property table rather than searching all the way
for a pinned one.

* bytecode/GetByIdStatus.cpp:
(JSC::GetByIdStatus::computeFor):
* bytecode/PutByIdStatus.cpp:
(JSC::PutByIdStatus::computeFromLLInt):
(JSC::PutByIdStatus::computeFor):
* runtime/Structure.cpp:
(JSC::Structure::findStructuresAndMapForMaterialization):
(JSC::Structure::materializePropertyMap):
(JSC::Structure::getWithoutMaterializing):
(JSC):
* runtime/Structure.h:
(Structure):
* runtime/StructureInlines.h:
(JSC::Structure::getWithoutMaterializing):
(JSC):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (153119 => 153120)


--- trunk/Source/_javascript_Core/ChangeLog	2013-07-25 03:58:26 UTC (rev 153119)
+++ trunk/Source/_javascript_Core/ChangeLog	2013-07-25 03:58:27 UTC (rev 153120)
@@ -1,3 +1,47 @@
+2013-07-16  Oliver Hunt  <[email protected]>
+
+        Merged dfgFourthTier r148570
+
+    2013-04-16  Filip Pizlo  <[email protected]>
+
+        fourthTier: DFG should be able to query Structure without modifying it
+        https://bugs.webkit.org/show_bug.cgi?id=114708
+
+        Reviewed by Oliver Hunt.
+        
+        This is work towards allowing the DFG, and FTL, to run on a separate thread.
+        The idea is that the most evil thing that the DFG does that has thread-safety
+        issues is fiddling with Structures by calling Structure::get(). This can lead
+        to rematerialization of property tables, which is definitely not thread-safe
+        due to how StringImpl works. So, this patch completely side-steps the problem
+        by creating a new version of Structure::get, called
+        Structure::getWithoutMaterializing, which may choose to do an O(n) search if
+        necessary to avoid materialization. I believe this should be fine - the DFG
+        does't call into these code path often enough for this to matter, and most of
+        the time, the Structure that we call this on will already have a property
+        table because some inline cache would have already called ::get() on that
+        Structure.
+        
+        Also cleaned up the materialization logic: we can stop the search as soon as
+        we find any Structure with a property table rather than searching all the way
+        for a pinned one.
+
+        * bytecode/GetByIdStatus.cpp:
+        (JSC::GetByIdStatus::computeFor):
+        * bytecode/PutByIdStatus.cpp:
+        (JSC::PutByIdStatus::computeFromLLInt):
+        (JSC::PutByIdStatus::computeFor):
+        * runtime/Structure.cpp:
+        (JSC::Structure::findStructuresAndMapForMaterialization):
+        (JSC::Structure::materializePropertyMap):
+        (JSC::Structure::getWithoutMaterializing):
+        (JSC):
+        * runtime/Structure.h:
+        (Structure):
+        * runtime/StructureInlines.h:
+        (JSC::Structure::getWithoutMaterializing):
+        (JSC):
+
 2013-07-15  Oliver Hunt  <[email protected]>
 
         Merged dfgFourthTier r148047

Modified: trunk/Source/_javascript_Core/bytecode/GetByIdStatus.cpp (153119 => 153120)


--- trunk/Source/_javascript_Core/bytecode/GetByIdStatus.cpp	2013-07-25 03:58:26 UTC (rev 153119)
+++ trunk/Source/_javascript_Core/bytecode/GetByIdStatus.cpp	2013-07-25 03:58:27 UTC (rev 153120)
@@ -164,7 +164,7 @@
         Structure* structure = stubInfo.u.getByIdSelf.baseObjectStructure.get();
         unsigned attributesIgnored;
         JSCell* specificValue;
-        result.m_offset = structure->get(
+        result.m_offset = structure->getWithoutMaterializing(
             *profiledBlock->vm(), ident, attributesIgnored, specificValue);
         if (structure->isDictionary())
             specificValue = 0;
@@ -189,7 +189,7 @@
             
             unsigned attributesIgnored;
             JSCell* specificValue;
-            PropertyOffset myOffset = structure->get(
+            PropertyOffset myOffset = structure->getWithoutMaterializing(
                 *profiledBlock->vm(), ident, attributesIgnored, specificValue);
             if (structure->isDictionary())
                 specificValue = 0;
@@ -274,7 +274,7 @@
     result.m_wasSeenInJIT = false; // To my knowledge nobody that uses computeFor(VM&, Structure*, Identifier&) reads this field, but I might as well be honest: no, it wasn't seen in the JIT, since I computed it statically.
     unsigned attributes;
     JSCell* specificValue;
-    result.m_offset = structure->get(vm, ident, attributes, specificValue);
+    result.m_offset = structure->getWithoutMaterializing(vm, ident, attributes, specificValue);
     if (!isValidOffset(result.m_offset))
         return GetByIdStatus(TakesSlowPath); // It's probably a prototype lookup. Give up on life for now, even though we could totally be way smarter about it.
     if (attributes & Accessor)

Modified: trunk/Source/_javascript_Core/bytecode/PutByIdStatus.cpp (153119 => 153120)


--- trunk/Source/_javascript_Core/bytecode/PutByIdStatus.cpp	2013-07-25 03:58:26 UTC (rev 153119)
+++ trunk/Source/_javascript_Core/bytecode/PutByIdStatus.cpp	2013-07-25 03:58:27 UTC (rev 153120)
@@ -49,7 +49,7 @@
     
     if (instruction[0].u.opcode == LLInt::getOpcode(llint_op_put_by_id)
         || instruction[0].u.opcode == LLInt::getOpcode(llint_op_put_by_id_out_of_line)) {
-        PropertyOffset offset = structure->get(*profiledBlock->vm(), ident);
+        PropertyOffset offset = structure->getWithoutMaterializing(*profiledBlock->vm(), ident);
         if (!isValidOffset(offset))
             return PutByIdStatus(NoInformation, 0, 0, 0, invalidOffset);
         
@@ -68,7 +68,7 @@
     ASSERT(newStructure);
     ASSERT(chain);
     
-    PropertyOffset offset = newStructure->get(*profiledBlock->vm(), ident);
+    PropertyOffset offset = newStructure->getWithoutMaterializing(*profiledBlock->vm(), ident);
     if (!isValidOffset(offset))
         return PutByIdStatus(NoInformation, 0, 0, 0, invalidOffset);
     
@@ -103,8 +103,9 @@
         return PutByIdStatus(TakesSlowPath, 0, 0, 0, invalidOffset);
         
     case access_put_by_id_replace: {
-        PropertyOffset offset = stubInfo.u.putByIdReplace.baseObjectStructure->get(
-            *profiledBlock->vm(), ident);
+        PropertyOffset offset =
+            stubInfo.u.putByIdReplace.baseObjectStructure->getWithoutMaterializing(
+                *profiledBlock->vm(), ident);
         if (isValidOffset(offset)) {
             return PutByIdStatus(
                 SimpleReplace,
@@ -118,8 +119,9 @@
     case access_put_by_id_transition_normal:
     case access_put_by_id_transition_direct: {
         ASSERT(stubInfo.u.putByIdTransition.previousStructure->transitionWatchpointSetHasBeenInvalidated());
-        PropertyOffset offset = stubInfo.u.putByIdTransition.structure->get(
-            *profiledBlock->vm(), ident);
+        PropertyOffset offset = 
+            stubInfo.u.putByIdTransition.structure->getWithoutMaterializing(
+                *profiledBlock->vm(), ident);
         if (isValidOffset(offset)) {
             return PutByIdStatus(
                 SimpleTransition,
@@ -152,7 +154,8 @@
     
     unsigned attributes;
     JSCell* specificValue;
-    PropertyOffset offset = structure->get(vm, ident, attributes, specificValue);
+    PropertyOffset offset = structure->getWithoutMaterializing(
+        vm, ident, attributes, specificValue);
     if (isValidOffset(offset)) {
         if (attributes & (Accessor | ReadOnly))
             return PutByIdStatus(TakesSlowPath);

Modified: trunk/Source/_javascript_Core/runtime/Structure.cpp (153119 => 153120)


--- trunk/Source/_javascript_Core/runtime/Structure.cpp	2013-07-25 03:58:26 UTC (rev 153119)
+++ trunk/Source/_javascript_Core/runtime/Structure.cpp	2013-07-25 03:58:27 UTC (rev 153120)
@@ -236,34 +236,38 @@
     static_cast<Structure*>(cell)->Structure::~Structure();
 }
 
+void Structure::findStructuresAndMapForMaterialization(Vector<Structure*, 8>& structures, PropertyTable*& table)
+{
+    ASSERT(structures.isEmpty());
+    table = 0;
+
+    for (Structure* structure = this; structure; structure = structure->previousID()) {
+        if (structure->propertyTable()) {
+            table = structure->propertyTable().get();
+            return;
+        }
+        
+        structures.append(structure);
+    }
+}
+
 void Structure::materializePropertyMap(VM& vm)
 {
     ASSERT(structure()->classInfo() == &s_info);
     ASSERT(!propertyTable());
 
     Vector<Structure*, 8> structures;
-    structures.append(this);
-
-    Structure* structure = this;
-
-    // Search for the last Structure with a property table.
-    while ((structure = structure->previousID())) {
-        if (structure->m_isPinnedPropertyTable) {
-            ASSERT(structure->propertyTable());
-            ASSERT(!structure->previousID());
-
-            propertyTable().set(vm, this, structure->propertyTable()->copy(vm, 0, numberOfSlotsForLastOffset(m_offset, m_inlineCapacity)));
-            break;
-        }
-
-        structures.append(structure);
-    }
-
-    if (!propertyTable())
+    PropertyTable* table;
+    
+    findStructuresAndMapForMaterialization(structures, table);
+    
+    if (!table)
         createPropertyMap(vm, numberOfSlotsForLastOffset(m_offset, m_inlineCapacity));
+    else
+        propertyTable().set(vm, this, table->copy(vm, 0, numberOfSlotsForLastOffset(m_offset, m_inlineCapacity)));
 
-    for (ptrdiff_t i = structures.size() - 1; i >= 0; --i) {
-        structure = structures[i];
+    for (size_t i = structures.size(); i--;) {
+        Structure* structure = structures[i];
         if (!structure->m_nameInPrevious)
             continue;
         PropertyMapEntry entry(vm, this, structure->m_nameInPrevious.get(), structure->m_offset, structure->m_attributesInPrevious, structure->m_specificValueInPrevious.get());
@@ -743,6 +747,35 @@
     return PropertyTable::create(vm, numberOfSlotsForLastOffset(m_offset, m_inlineCapacity));
 }
 
+PropertyOffset Structure::getWithoutMaterializing(VM&, PropertyName propertyName, unsigned& attributes, JSCell*& specificValue)
+{
+    Vector<Structure*, 8> structures;
+    PropertyTable* table;
+    
+    findStructuresAndMapForMaterialization(structures, table);
+    
+    if (table) {
+        PropertyMapEntry* entry = table->find(propertyName.uid()).first;
+        if (entry) {
+            attributes = entry->attributes;
+            specificValue = entry->specificValue.get();
+            return entry->offset;
+        }
+    }
+    
+    for (unsigned i = structures.size(); i--;) {
+        Structure* structure = structures[i];
+        if (structure->m_nameInPrevious.get() != propertyName.uid())
+            continue;
+        
+        attributes = structure->m_attributesInPrevious;
+        specificValue = structure->m_specificValueInPrevious.get();
+        return structure->m_offset;
+    }
+    
+    return invalidOffset;
+}
+
 PropertyOffset Structure::get(VM& vm, PropertyName propertyName, unsigned& attributes, JSCell*& specificValue)
 {
     ASSERT(structure()->classInfo() == &s_info);

Modified: trunk/Source/_javascript_Core/runtime/Structure.h (153119 => 153120)


--- trunk/Source/_javascript_Core/runtime/Structure.h	2013-07-25 03:58:26 UTC (rev 153119)
+++ trunk/Source/_javascript_Core/runtime/Structure.h	2013-07-25 03:58:27 UTC (rev 153120)
@@ -235,6 +235,9 @@
     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);
+
     bool hasGetterSetterProperties() const { return m_hasGetterSetterProperties; }
     bool hasReadOnlyOrGetterSetterPropertiesExcludingProto() const { return m_hasReadOnlyOrGetterSetterPropertiesExcludingProto; }
     void setHasGetterSetterProperties(bool is__proto__)
@@ -353,6 +356,8 @@
 
     static Structure* create(VM&, const Structure*);
         
+    void findStructuresAndMapForMaterialization(Vector<Structure*, 8>& structures, PropertyTable*&);
+    
     typedef enum { 
         NoneDictionaryKind = 0,
         CachedDictionaryKind = 1,

Modified: trunk/Source/_javascript_Core/runtime/StructureInlines.h (153119 => 153120)


--- trunk/Source/_javascript_Core/runtime/StructureInlines.h	2013-07-25 03:58:26 UTC (rev 153119)
+++ trunk/Source/_javascript_Core/runtime/StructureInlines.h	2013-07-25 03:58:27 UTC (rev 153120)
@@ -78,6 +78,14 @@
     return entry ? entry->offset : invalidOffset;
 }
     
+inline PropertyOffset Structure::getWithoutMaterializing(VM& vm, PropertyName propertyName)
+{
+    unsigned attributesIgnored;
+    JSCell* specificValueIgnored;
+    return getWithoutMaterializing(
+        vm, propertyName, attributesIgnored, specificValueIgnored);
+}
+
 inline bool Structure::masqueradesAsUndefined(JSGlobalObject* lexicalGlobalObject)
 {
     return typeInfo().masqueradesAsUndefined() && globalObject() == lexicalGlobalObject;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to