Title: [247925] trunk
Revision
247925
Author
[email protected]
Date
2019-07-29 15:26:58 -0700 (Mon, 29 Jul 2019)

Log Message

[JSC] Increment bytecode age only when SlotVisitor is first-visit
https://bugs.webkit.org/show_bug.cgi?id=200196

Reviewed by Robin Morisset.

JSTests:

* stress/reparsing-unlinked-codeblock.js:

Source/_javascript_Core:

WriteBarrier can cause multiple visits for the same UnlinkedCodeBlock. But this does not mean that we are having multiple cycles of GC.
We should increment the age of the UnlinkedCodeBlock only when the SlotVisitor is saying that this is the first visit.

In practice,this almost never happens. Multiple visits can happen only when the marked UnlinkedCodeBlock gets a write-barrier. But, mutation
of UnlinkedCodeBlock is rare or none after it is initialized. I ran all the JSTests and I cannot find any tests that get re-visiting of UnlinkedCodeBlock.
This patch extends JSTests/stress/reparsing-unlinked-codeblock.js to ensure that UnlinkedCodeBlockJettisoning feature is working after this change.

* bytecode/UnlinkedCodeBlock.cpp:
(JSC::UnlinkedCodeBlock::visitChildren):
* heap/SlotVisitor.h:
(JSC::SlotVisitor::isFirstVisit const):
* parser/Parser.cpp:
* parser/Parser.h:
(JSC::parse):
(JSC::parseFunctionForFunctionConstructor):
* runtime/Options.h:
* tools/JSDollarVM.cpp:
(JSC::functionParseCount):
(JSC::JSDollarVM::finishCreation):

Modified Paths

Diff

Modified: trunk/JSTests/ChangeLog (247924 => 247925)


--- trunk/JSTests/ChangeLog	2019-07-29 21:57:39 UTC (rev 247924)
+++ trunk/JSTests/ChangeLog	2019-07-29 22:26:58 UTC (rev 247925)
@@ -1,3 +1,12 @@
+2019-07-29  Yusuke Suzuki  <[email protected]>
+
+        [JSC] Increment bytecode age only when SlotVisitor is first-visit
+        https://bugs.webkit.org/show_bug.cgi?id=200196
+
+        Reviewed by Robin Morisset.
+
+        * stress/reparsing-unlinked-codeblock.js:
+
 2019-07-29  Justin Michaud  <[email protected]>
 
         [X86] Emit BT instruction for shift + mask in B3

Modified: trunk/JSTests/stress/reparsing-unlinked-codeblock.js (247924 => 247925)


--- trunk/JSTests/stress/reparsing-unlinked-codeblock.js	2019-07-29 21:57:39 UTC (rev 247924)
+++ trunk/JSTests/stress/reparsing-unlinked-codeblock.js	2019-07-29 22:26:58 UTC (rev 247925)
@@ -1,4 +1,4 @@
-//@ runDefault("--forceCodeBlockToJettisonDueToOldAge=1", "--useUnlinkedCodeBlockJettisoning=1")
+//@ runDefault("--forceCodeBlockToJettisonDueToOldAge=1", "--useUnlinkedCodeBlockJettisoning=1", "--countParseTimes=1", "--useConcurrentJIT=0")
 
 function shouldBe(actual, expected) {
     if (actual !== expected)
@@ -17,8 +17,11 @@
 
 // Compile hello and world function.
 shouldBe(hello(), 42);
+var first = $vm.parseCount();
 // Kick full GC 20 times to make UnlinkedCodeBlock aged and destroyed. Jettison hello CodeBlock, and underlying world UnlinkedCodeBlock.
 for (var i = 0; i < 20; ++i)
     fullGC();
 // Recompile world.
 shouldBe(hello(), 42);
+var second = $vm.parseCount() - first;
+shouldBe(second >= 3, true); // `hello`, `inner`, `world`. Other functions can be destroyed, so using >= here.

Modified: trunk/Source/_javascript_Core/ChangeLog (247924 => 247925)


--- trunk/Source/_javascript_Core/ChangeLog	2019-07-29 21:57:39 UTC (rev 247924)
+++ trunk/Source/_javascript_Core/ChangeLog	2019-07-29 22:26:58 UTC (rev 247925)
@@ -1,3 +1,30 @@
+2019-07-29  Yusuke Suzuki  <[email protected]>
+
+        [JSC] Increment bytecode age only when SlotVisitor is first-visit
+        https://bugs.webkit.org/show_bug.cgi?id=200196
+
+        Reviewed by Robin Morisset.
+
+        WriteBarrier can cause multiple visits for the same UnlinkedCodeBlock. But this does not mean that we are having multiple cycles of GC.
+        We should increment the age of the UnlinkedCodeBlock only when the SlotVisitor is saying that this is the first visit.
+
+        In practice,this almost never happens. Multiple visits can happen only when the marked UnlinkedCodeBlock gets a write-barrier. But, mutation
+        of UnlinkedCodeBlock is rare or none after it is initialized. I ran all the JSTests and I cannot find any tests that get re-visiting of UnlinkedCodeBlock.
+        This patch extends JSTests/stress/reparsing-unlinked-codeblock.js to ensure that UnlinkedCodeBlockJettisoning feature is working after this change.
+
+        * bytecode/UnlinkedCodeBlock.cpp:
+        (JSC::UnlinkedCodeBlock::visitChildren):
+        * heap/SlotVisitor.h:
+        (JSC::SlotVisitor::isFirstVisit const):
+        * parser/Parser.cpp:
+        * parser/Parser.h:
+        (JSC::parse):
+        (JSC::parseFunctionForFunctionConstructor):
+        * runtime/Options.h:
+        * tools/JSDollarVM.cpp:
+        (JSC::functionParseCount):
+        (JSC::JSDollarVM::finishCreation):
+
 2019-07-28  Commit Queue  <[email protected]>
 
         Unreviewed, rolling out r247886.

Modified: trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.cpp (247924 => 247925)


--- trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.cpp	2019-07-29 21:57:39 UTC (rev 247924)
+++ trunk/Source/_javascript_Core/bytecode/UnlinkedCodeBlock.cpp	2019-07-29 22:26:58 UTC (rev 247925)
@@ -89,7 +89,8 @@
     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
     Base::visitChildren(thisObject, visitor);
     auto locker = holdLock(thisObject->cellLock());
-    thisObject->m_age = std::min<unsigned>(static_cast<unsigned>(thisObject->m_age) + 1, maxAge);
+    if (visitor.isFirstVisit())
+        thisObject->m_age = std::min<unsigned>(static_cast<unsigned>(thisObject->m_age) + 1, maxAge);
     for (FunctionExpressionVector::iterator ptr = thisObject->m_functionDecls.begin(), end = thisObject->m_functionDecls.end(); ptr != end; ++ptr)
         visitor.append(*ptr);
     for (FunctionExpressionVector::iterator ptr = thisObject->m_functionExprs.begin(), end = thisObject->m_functionExprs.end(); ptr != end; ++ptr)

Modified: trunk/Source/_javascript_Core/heap/SlotVisitor.h (247924 => 247925)


--- trunk/Source/_javascript_Core/heap/SlotVisitor.h	2019-07-29 21:57:39 UTC (rev 247924)
+++ trunk/Source/_javascript_Core/heap/SlotVisitor.h	2019-07-29 22:26:58 UTC (rev 247925)
@@ -119,6 +119,8 @@
 
     bool isEmpty() { return m_collectorStack.isEmpty() && m_mutatorStack.isEmpty(); }
 
+    bool isFirstVisit() const { return m_isFirstVisit; }
+
     void didStartMarking();
     void reset();
     void clearMarkStacks();

Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (247924 => 247925)


--- trunk/Source/_javascript_Core/parser/Parser.cpp	2019-07-29 21:57:39 UTC (rev 247924)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp	2019-07-29 22:26:58 UTC (rev 247925)
@@ -88,6 +88,8 @@
 
 namespace JSC {
 
+std::atomic<unsigned> globalParseCount { 0 };
+
 ALWAYS_INLINE static SourceParseMode getAsynFunctionBodyParseMode(SourceParseMode parseMode)
 {
     if (isAsyncGeneratorWrapperParseMode(parseMode))

Modified: trunk/Source/_javascript_Core/parser/Parser.h (247924 => 247925)


--- trunk/Source/_javascript_Core/parser/Parser.h	2019-07-29 21:57:39 UTC (rev 247924)
+++ trunk/Source/_javascript_Core/parser/Parser.h	2019-07-29 22:26:58 UTC (rev 247925)
@@ -150,6 +150,8 @@
     return token.m_type >= FirstSafeContextualKeywordToken && token.m_type <= LastSafeContextualKeywordToken;
 }
 
+JS_EXPORT_PRIVATE extern std::atomic<unsigned> globalParseCount;
+
 struct Scope {
     WTF_MAKE_NONCOPYABLE(Scope);
 
@@ -2031,6 +2033,9 @@
             *positionBeforeLastNewline = parser.positionBeforeLastNewline();
     }
 
+    if (UNLIKELY(Options::countParseTimes()))
+        globalParseCount++;
+
     if (UNLIKELY(Options::reportParseTimes())) {
         MonotonicTime after = MonotonicTime::now();
         ParseHash hash(source);
@@ -2063,6 +2068,9 @@
             *positionBeforeLastNewline = parser.positionBeforeLastNewline();
     }
 
+    if (UNLIKELY(Options::countParseTimes()))
+        globalParseCount++;
+
     if (UNLIKELY(Options::reportParseTimes())) {
         MonotonicTime after = MonotonicTime::now();
         ParseHash hash(source);

Modified: trunk/Source/_javascript_Core/runtime/Options.h (247924 => 247925)


--- trunk/Source/_javascript_Core/runtime/Options.h	2019-07-29 21:57:39 UTC (rev 247924)
+++ trunk/Source/_javascript_Core/runtime/Options.h	2019-07-29 22:26:58 UTC (rev 247925)
@@ -198,6 +198,7 @@
     v(bool, reportTotalCompileTimes, false, Normal, nullptr) \
     v(bool, reportParseTimes, false, Normal, "dumps JS function signature and the time it took to parse") \
     v(bool, reportBytecodeCompileTimes, false, Normal, "dumps JS function signature and the time it took to bytecode compile") \
+    v(bool, countParseTimes, false, Normal, "counts parse times") \
     v(bool, verboseExitProfile, false, Normal, nullptr) \
     v(bool, verboseCFA, false, Normal, nullptr) \
     v(bool, verboseDFGFailure, false, Normal, nullptr) \

Modified: trunk/Source/_javascript_Core/tools/JSDollarVM.cpp (247924 => 247925)


--- trunk/Source/_javascript_Core/tools/JSDollarVM.cpp	2019-07-29 21:57:39 UTC (rev 247924)
+++ trunk/Source/_javascript_Core/tools/JSDollarVM.cpp	2019-07-29 22:26:58 UTC (rev 247925)
@@ -40,6 +40,7 @@
 #include "JSONObject.h"
 #include "JSProxy.h"
 #include "JSString.h"
+#include "Parser.h"
 #include "ShadowChicken.h"
 #include "Snippet.h"
 #include "SnippetParams.h"
@@ -2186,6 +2187,11 @@
     return JSValue::encode(jsNumber(vm.heap.totalGCTime().seconds()));
 }
 
+static EncodedJSValue JSC_HOST_CALL functionParseCount(ExecState*)
+{
+    return JSValue::encode(jsNumber(globalParseCount.load()));
+}
+
 void JSDollarVM::finishCreation(VM& vm)
 {
     Base::finishCreation(vm);
@@ -2299,6 +2305,8 @@
     addFunction(vm, "deltaBetweenButterflies", functionDeltaBetweenButterflies, 2);
     
     addFunction(vm, "totalGCTime", functionTotalGCTime, 0);
+
+    addFunction(vm, "parseCount", functionParseCount, 0);
 }
 
 void JSDollarVM::addFunction(VM& vm, JSGlobalObject* globalObject, const char* name, NativeFunction function, unsigned arguments)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to