Title: [186986] trunk/Source/_javascript_Core
Revision
186986
Author
[email protected]
Date
2015-07-17 22:51:06 -0700 (Fri, 17 Jul 2015)

Log Message

DFG should have some obvious mitigations against watching structures that are unprofitable to watch
https://bugs.webkit.org/show_bug.cgi?id=147034

Reviewed by Mark Lam and Michael Saboff.
        
This implements two guards against the DFG watching structures that are likely to fire
their watchpoints:
        
- Don't watch dictionaries or any structure that had a dictionary in its past. Dictionaries
  can be flattened, and then they can transform back to dictionaries.
        
- Don't watch structures whose past structures were transitioned-away from while their
  transition watchpoints were being watched. This property gives us monotonicity: if we
  recompile because we watched structure S1 of object O, then we won't make the same mistake
  again when object O has structure S2, S3, and so on.
        
This is a 1.5% speed-up on Kraken. It does penalize some Octane tests, but it also seems to
help some of them, so on Octane it's basically neutral.

* bytecode/Watchpoint.h:
(JSC::WatchpointSet::invalidate):
(JSC::WatchpointSet::isBeingWatched):
(JSC::WatchpointSet::addressOfState):
(JSC::WatchpointSet::addressOfSetIsNotEmpty):
(JSC::InlineWatchpointSet::touch):
(JSC::InlineWatchpointSet::isBeingWatched):
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::createStructure):
(JSC::JSGlobalObject::registerWeakMap):
* runtime/Structure.cpp:
(JSC::Structure::Structure):
(JSC::Structure::toDictionaryTransition):
(JSC::Structure::didTransitionFromThisStructure):
* runtime/Structure.h:

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (186985 => 186986)


--- trunk/Source/_javascript_Core/ChangeLog	2015-07-18 05:49:32 UTC (rev 186985)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-07-18 05:51:06 UTC (rev 186986)
@@ -1,3 +1,40 @@
+2015-07-17  Filip Pizlo  <[email protected]>
+
+        DFG should have some obvious mitigations against watching structures that are unprofitable to watch
+        https://bugs.webkit.org/show_bug.cgi?id=147034
+
+        Reviewed by Mark Lam and Michael Saboff.
+        
+        This implements two guards against the DFG watching structures that are likely to fire
+        their watchpoints:
+        
+        - Don't watch dictionaries or any structure that had a dictionary in its past. Dictionaries
+          can be flattened, and then they can transform back to dictionaries.
+        
+        - Don't watch structures whose past structures were transitioned-away from while their
+          transition watchpoints were being watched. This property gives us monotonicity: if we
+          recompile because we watched structure S1 of object O, then we won't make the same mistake
+          again when object O has structure S2, S3, and so on.
+        
+        This is a 1.5% speed-up on Kraken. It does penalize some Octane tests, but it also seems to
+        help some of them, so on Octane it's basically neutral.
+
+        * bytecode/Watchpoint.h:
+        (JSC::WatchpointSet::invalidate):
+        (JSC::WatchpointSet::isBeingWatched):
+        (JSC::WatchpointSet::addressOfState):
+        (JSC::WatchpointSet::addressOfSetIsNotEmpty):
+        (JSC::InlineWatchpointSet::touch):
+        (JSC::InlineWatchpointSet::isBeingWatched):
+        * runtime/JSGlobalObject.h:
+        (JSC::JSGlobalObject::createStructure):
+        (JSC::JSGlobalObject::registerWeakMap):
+        * runtime/Structure.cpp:
+        (JSC::Structure::Structure):
+        (JSC::Structure::toDictionaryTransition):
+        (JSC::Structure::didTransitionFromThisStructure):
+        * runtime/Structure.h:
+
 2015-07-16  Filip Pizlo  <[email protected]>
 
         Remove DFG::DesiredWriteBarriers because it's just a very difficult way of saying "please barrier the machine code block owner"

Modified: trunk/Source/_javascript_Core/bytecode/Watchpoint.h (186985 => 186986)


--- trunk/Source/_javascript_Core/bytecode/Watchpoint.h	2015-07-18 05:49:32 UTC (rev 186985)
+++ trunk/Source/_javascript_Core/bytecode/Watchpoint.h	2015-07-18 05:51:06 UTC (rev 186986)
@@ -188,6 +188,11 @@
         invalidate(StringFireDetail(reason));
     }
     
+    bool isBeingWatched() const
+    {
+        return m_setIsNotEmpty;
+    }
+    
     int8_t* addressOfState() { return &m_state; }
     int8_t* addressOfSetIsNotEmpty() { return &m_setIsNotEmpty; }
     
@@ -331,6 +336,13 @@
         touch(StringFireDetail(reason));
     }
     
+    bool isBeingWatched() const
+    {
+        if (isFat())
+            return fat()->isBeingWatched();
+        return false;
+    }
+    
 private:
     static const uintptr_t IsThinFlag        = 1;
     static const uintptr_t StateMask         = 6;

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.h (186985 => 186986)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.h	2015-07-18 05:49:32 UTC (rev 186985)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.h	2015-07-18 05:51:06 UTC (rev 186986)
@@ -613,7 +613,9 @@
 
     static Structure* createStructure(VM& vm, JSValue prototype)
     {
-        return Structure::create(vm, 0, prototype, TypeInfo(GlobalObjectType, StructureFlags), info());
+        Structure* result = Structure::create(vm, 0, prototype, TypeInfo(GlobalObjectType, StructureFlags), info());
+        result->setTransitionWatchpointIsLikelyToBeFired(true);
+        return result;
     }
 
     void registerWeakMap(OpaqueJSWeakObjectMap* map)

Modified: trunk/Source/_javascript_Core/runtime/Structure.cpp (186985 => 186986)


--- trunk/Source/_javascript_Core/runtime/Structure.cpp	2015-07-18 05:49:32 UTC (rev 186985)
+++ trunk/Source/_javascript_Core/runtime/Structure.cpp	2015-07-18 05:51:06 UTC (rev 186986)
@@ -171,6 +171,7 @@
     setDidTransition(false);
     setStaticFunctionsReified(false);
     setHasRareData(false);
+    setTransitionWatchpointIsLikelyToBeFired(false);
  
     ASSERT(inlineCapacity <= JSFinalObject::maxInlineCapacity());
     ASSERT(static_cast<PropertyOffset>(inlineCapacity) < firstOutOfLineOffset);
@@ -201,6 +202,7 @@
     setDidTransition(false);
     setStaticFunctionsReified(false);
     setHasRareData(false);
+    setTransitionWatchpointIsLikelyToBeFired(false);
  
     TypeInfo typeInfo = TypeInfo(CellType, StructureFlags);
     m_blob = StructureIDBlob(vm.heap.structureIDTable().allocateID(this), 0, typeInfo);
@@ -239,6 +241,10 @@
     setPreviousID(vm, previous);
 
     previous->didTransitionFromThisStructure(deferred);
+    
+    // Copy this bit now, in case previous was being watched.
+    setTransitionWatchpointIsLikelyToBeFired(previous->transitionWatchpointIsLikelyToBeFired());
+
     if (previous->m_globalObject)
         m_globalObject.set(vm, this, previous->m_globalObject.get());
     ASSERT(hasReadOnlyOrGetterSetterPropertiesExcludingProto() || !m_classInfo->hasStaticSetterOrReadonlyProperties());
@@ -495,6 +501,7 @@
     transition->m_offset = structure->m_offset;
     transition->setDictionaryKind(kind);
     transition->pin();
+    transition->setTransitionWatchpointIsLikelyToBeFired(true);
 
     transition->checkOffsetConsistency();
     return transition;
@@ -975,6 +982,12 @@
 
 void Structure::didTransitionFromThisStructure(DeferredStructureTransitionWatchpointFire* deferred) const
 {
+    // If the structure is being watched, and this is the kind of structure that the DFG would
+    // like to watch, then make sure to note for all future versions of this structure that it's
+    // unwise to watch it.
+    if (m_transitionWatchpointSet.isBeingWatched())
+        const_cast<Structure*>(this)->setTransitionWatchpointIsLikelyToBeFired(true);
+    
     if (deferred)
         deferred->add(this);
     else

Modified: trunk/Source/_javascript_Core/runtime/Structure.h (186985 => 186986)


--- trunk/Source/_javascript_Core/runtime/Structure.h	2015-07-18 05:49:32 UTC (rev 186985)
+++ trunk/Source/_javascript_Core/runtime/Structure.h	2015-07-18 05:51:06 UTC (rev 186986)
@@ -413,6 +413,13 @@
         // watching it. We should come up with a comprehensive story for not watching things that
         // aren't profitable to watch.
         // https://bugs.webkit.org/show_bug.cgi?id=133625
+        
+        // - We don't watch Structures that either decided not to be watched, or whose predecessors
+        //   decided not to be watched. This happens either when a transition is fired while being
+        //   watched, or if a dictionary transition occurs.
+        if (transitionWatchpointIsLikelyToBeFired())
+            return false;
+        
         return true;
     }
     
@@ -502,6 +509,7 @@
     DEFINE_BITFIELD(bool, hasBeenFlattenedBefore, HasBeenFlattenedBefore, 1, 24);
     DEFINE_BITFIELD(bool, hasCustomGetterSetterProperties, HasCustomGetterSetterProperties, 1, 25);
     DEFINE_BITFIELD(bool, didWatchInternalProperties, DidWatchInternalProperties, 1, 26);
+    DEFINE_BITFIELD(bool, transitionWatchpointIsLikelyToBeFired, TransitionWatchpointIsLikelyToBeFired, 1, 27);
 
 private:
     friend class LLIntOffsetsExtractor;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to