Title: [284576] trunk/Source/_javascript_Core
Revision
284576
Author
[email protected]
Date
2021-10-20 15:08:45 -0700 (Wed, 20 Oct 2021)

Log Message

We should watch isHavingABadTime if we read from the structureCache
https://bugs.webkit.org/show_bug.cgi?id=232019

Reviewed by Yusuke Suzuki.

We should lock the structure cache when we clear it, and the compiler thread should
watch isHavingABadTime in the case that the cache might get cleared.

* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGConstantFoldingPhase.cpp:
(JSC::DFG::ConstantFoldingPhase::foldConstants):
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::haveABadTime):
* runtime/StructureCache.cpp:
(JSC::StructureCache::clear):
* runtime/StructureCache.h:
(JSC::StructureCache::clear): Deleted.

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (284575 => 284576)


--- trunk/Source/_javascript_Core/ChangeLog	2021-10-20 21:50:18 UTC (rev 284575)
+++ trunk/Source/_javascript_Core/ChangeLog	2021-10-20 22:08:45 UTC (rev 284576)
@@ -1,3 +1,24 @@
+2021-10-20  Justin Michaud  <[email protected]>
+
+        We should watch isHavingABadTime if we read from the structureCache
+        https://bugs.webkit.org/show_bug.cgi?id=232019
+
+        Reviewed by Yusuke Suzuki.
+
+        We should lock the structure cache when we clear it, and the compiler thread should
+        watch isHavingABadTime in the case that the cache might get cleared.
+
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+        * dfg/DFGConstantFoldingPhase.cpp:
+        (JSC::DFG::ConstantFoldingPhase::foldConstants):
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::haveABadTime):
+        * runtime/StructureCache.cpp:
+        (JSC::StructureCache::clear):
+        * runtime/StructureCache.h:
+        (JSC::StructureCache::clear): Deleted.
+
 2021-10-20  Michael Saboff  <[email protected]>
 
         Add missing overflow checks to DFGIntegerRangeOptimizationPhase::isEquivalentTo()

Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (284575 => 284576)


--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2021-10-20 21:50:18 UTC (rev 284575)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2021-10-20 22:08:45 UTC (rev 284576)
@@ -3126,8 +3126,19 @@
             Structure* structure = nullptr;
             if (base.isNull())
                 structure = globalObject->nullPrototypeObjectStructure();
-            else if (base.isObject())
-                structure = m_vm.structureCache.emptyObjectStructureConcurrently(globalObject, base.getObject(), JSFinalObject::defaultInlineCapacity());
+            else if (base.isObject()) {
+                // Having a bad time clears the structureCache, and so it should invalidate this structure.
+                bool isHavingABadTime = globalObject->isHavingABadTime();
+                WTF::loadLoadFence();
+                if (!isHavingABadTime)
+                    m_graph.watchpoints().addLazily(globalObject->havingABadTimeWatchpoint());
+                // Normally, we would always install a watchpoint. In this case, however, if we haveABadTime, we
+                // still want to optimize. There is no watchpoint for that case though, so we need to make sure this load
+                // does not get hoisted above the check.
+                WTF::loadLoadFence();
+                structure = m_vm.structureCache
+                    .emptyObjectStructureConcurrently(globalObject, base.getObject(), JSFinalObject::defaultInlineCapacity());
+            }
             
             if (structure) {
                 m_state.setShouldTryConstantFolding(true);

Modified: trunk/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp (284575 => 284576)


--- trunk/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp	2021-10-20 21:50:18 UTC (rev 284575)
+++ trunk/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp	2021-10-20 22:08:45 UTC (rev 284576)
@@ -841,8 +841,19 @@
                     Structure* structure = nullptr;
                     if (base.isNull())
                         structure = globalObject->nullPrototypeObjectStructure();
-                    else if (base.isObject())
-                        structure = globalObject->vm().structureCache.emptyObjectStructureConcurrently(globalObject, base.getObject(), JSFinalObject::defaultInlineCapacity());
+                    else if (base.isObject()) {
+                        // Having a bad time clears the structureCache, and so it should invalidate this structure.
+                        bool isHavingABadTime = globalObject->isHavingABadTime();
+                        WTF::loadLoadFence();
+                        if (!isHavingABadTime)
+                            m_graph.watchpoints().addLazily(globalObject->havingABadTimeWatchpoint());
+                        // Normally, we would always install a watchpoint. In this case, however, if we haveABadTime, we
+                        // still want to optimize. There is no watchpoint for that case though, so we need to make sure this load
+                        // does not get hoisted above the check.
+                        WTF::loadLoadFence();
+                        structure = globalObject->vm().structureCache
+                            .emptyObjectStructureConcurrently(globalObject, base.getObject(), JSFinalObject::defaultInlineCapacity());
+                    }
                     
                     if (structure) {
                         node->convertToNewObject(m_graph.registerStructure(structure));

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (284575 => 284576)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2021-10-20 21:50:18 UTC (rev 284575)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2021-10-20 22:08:45 UTC (rev 284576)
@@ -1984,6 +1984,15 @@
     if (isHavingABadTime())
         return;
 
+    // This must happen first, because the compiler thread may race with haveABadTime.
+    // Let R_BT, W_BT <- Read/Fire the watchpoint, R_SC, W_SC <- Read/clear the structure cache.
+    // The possible interleavings are:
+    // R_BT, R_SC, W_SC, W_BT: Compiler thread installs a watchpoint, and the code is discarded.
+    // R_BT, W_SC, R_SC, W_BT: ^ Same
+    // R_BT, W_SC, W_BT, W_SC: ^ Same
+    // W_SC, R_BT, R_SC, W_BT: ^ Same
+    // W_SC, R_BT, W_BT, R_SC: ^ Same
+    // W_SC, W_BT, R_BT, R_SC: No watchpoint is installed, but we could not see old structures from the cache.
     vm.structureCache.clear(); // We may be caching array structures in here.
 
     DeferGC deferGC(vm.heap);

Modified: trunk/Source/_javascript_Core/runtime/StructureCache.cpp (284575 => 284576)


--- trunk/Source/_javascript_Core/runtime/StructureCache.cpp	2021-10-20 21:50:18 UTC (rev 284575)
+++ trunk/Source/_javascript_Core/runtime/StructureCache.cpp	2021-10-20 22:08:45 UTC (rev 284576)
@@ -31,6 +31,12 @@
 
 namespace JSC {
 
+void StructureCache::clear()
+{
+    Locker locker { m_lock };
+    m_structures.clear();
+}
+
 inline Structure* StructureCache::createEmptyStructure(JSGlobalObject* globalObject, JSObject* prototype, const TypeInfo& typeInfo, const ClassInfo* classInfo, IndexingType indexingType, unsigned inlineCapacity, bool makePolyProtoStructure, FunctionExecutable* executable)
 {
     RELEASE_ASSERT(!!prototype); // We use nullptr inside the HashMap for prototype to mean poly proto, so user's of this API must provide non-null prototypes.

Modified: trunk/Source/_javascript_Core/runtime/StructureCache.h (284575 => 284576)


--- trunk/Source/_javascript_Core/runtime/StructureCache.h	2021-10-20 21:50:18 UTC (rev 284575)
+++ trunk/Source/_javascript_Core/runtime/StructureCache.h	2021-10-20 22:08:45 UTC (rev 284576)
@@ -48,7 +48,7 @@
     {
     }
 
-    void clear() { m_structures.clear(); }
+    JS_EXPORT_PRIVATE void clear();
 
     JS_EXPORT_PRIVATE Structure* emptyObjectStructureForPrototype(JSGlobalObject*, JSObject*, unsigned inlineCapacity, bool makePolyProtoStructure = false, FunctionExecutable* = nullptr);
     JS_EXPORT_PRIVATE Structure* emptyStructureForPrototypeFromBaseStructure(JSGlobalObject*, JSObject*, Structure*);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to