Title: [225151] trunk
Revision
225151
Author
[email protected]
Date
2017-11-26 17:46:59 -0800 (Sun, 26 Nov 2017)

Log Message

[DFG] Introduce {Set,Map,WeakMap}Fields
https://bugs.webkit.org/show_bug.cgi?id=179925

Reviewed by Saam Barati.

JSTests:

* stress/map-set-clobber-map-get.js: Added.
(shouldBe):
(test):
* stress/map-set-does-not-clobber-set-has.js: Added.
(shouldBe):
* stress/map-set-does-not-clobber-weak-map-get.js: Added.
(shouldBe):
(test):
* stress/set-add-clobber-set-has.js: Added.
(shouldBe):
* stress/set-add-does-not-clobber-map-get.js: Added.
(shouldBe):

Source/_javascript_Core:

SetAdd and MapSet uses `write(MiscFields)`, but it is not correct. It accidentally
writes readonly MiscFields which is used by various nodes and make optimization
conservative.

We introduce JSSetFields, JSMapFields, and JSWeakMapFields to precisely model clobberizing of Map, Set, and WeakMap.

* dfg/DFGAbstractHeap.h:
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::handleIntrinsicCall):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGHeapLocation.cpp:
(WTF::printInternal):
* dfg/DFGHeapLocation.h:
* dfg/DFGNode.h:
(JSC::DFG::Node::hasBucketOwnerType):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (225150 => 225151)


--- trunk/JSTests/ChangeLog	2017-11-27 01:22:43 UTC (rev 225150)
+++ trunk/JSTests/ChangeLog	2017-11-27 01:46:59 UTC (rev 225151)
@@ -1,3 +1,23 @@
+2017-11-26  Yusuke Suzuki  <[email protected]>
+
+        [DFG] Introduce {Set,Map,WeakMap}Fields
+        https://bugs.webkit.org/show_bug.cgi?id=179925
+
+        Reviewed by Saam Barati.
+
+        * stress/map-set-clobber-map-get.js: Added.
+        (shouldBe):
+        (test):
+        * stress/map-set-does-not-clobber-set-has.js: Added.
+        (shouldBe):
+        * stress/map-set-does-not-clobber-weak-map-get.js: Added.
+        (shouldBe):
+        (test):
+        * stress/set-add-clobber-set-has.js: Added.
+        (shouldBe):
+        * stress/set-add-does-not-clobber-map-get.js: Added.
+        (shouldBe):
+
 2017-11-24  Mark Lam  <[email protected]>
 
         Move unsafe jsc shell test functions to the $vm object.

Added: trunk/JSTests/stress/map-set-clobber-map-get.js (0 => 225151)


--- trunk/JSTests/stress/map-set-clobber-map-get.js	                        (rev 0)
+++ trunk/JSTests/stress/map-set-clobber-map-get.js	2017-11-27 01:46:59 UTC (rev 225151)
@@ -0,0 +1,18 @@
+function shouldBe(actual, expected)
+{
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function test()
+{
+    var map = new Map();
+    map.set(42, 42);
+    var res1 = map.get(42);
+    map.set(42, 100);
+    var res2 = map.get(42);
+    return res1 + res2;
+}
+
+for (var i = 0; i < 1e6; ++i)
+    shouldBe(test(), 142);

Added: trunk/JSTests/stress/map-set-does-not-clobber-set-has.js (0 => 225151)


--- trunk/JSTests/stress/map-set-does-not-clobber-set-has.js	                        (rev 0)
+++ trunk/JSTests/stress/map-set-does-not-clobber-set-has.js	2017-11-27 01:46:59 UTC (rev 225151)
@@ -0,0 +1,19 @@
+function shouldBe(actual, expected)
+{
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function test()
+{
+    var map = new Map();
+    var set = new Set();
+    set.add(42);
+    var res1 = set.has(42);
+    map.set(42, 42);
+    var res2 = set.has(42);
+    return res1 + res2;
+}
+
+for (var i = 0; i < 1e6; ++i)
+    shouldBe(test(), 2);

Added: trunk/JSTests/stress/map-set-does-not-clobber-weak-map-get.js (0 => 225151)


--- trunk/JSTests/stress/map-set-does-not-clobber-weak-map-get.js	                        (rev 0)
+++ trunk/JSTests/stress/map-set-does-not-clobber-weak-map-get.js	2017-11-27 01:46:59 UTC (rev 225151)
@@ -0,0 +1,26 @@
+function shouldBe(actual, expected)
+{
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function test()
+{
+    var map = new Map();
+    var weakMap = new WeakMap();
+    var key = {};
+
+    var res1 = weakMap.get(key);
+    map.set(key, key);
+    var res2 = weakMap.get(key);
+    weakMap.set(key, 42);
+    var res3 = weakMap.get(key);
+    return [undefined, undefined, 42];
+}
+
+for (var i = 0; i < 1e5; ++i) {
+    var [res1, res2, res3] = test();
+    shouldBe(res1, undefined);
+    shouldBe(res2, undefined);
+    shouldBe(res3, 42);
+}

Added: trunk/JSTests/stress/set-add-clobber-set-has.js (0 => 225151)


--- trunk/JSTests/stress/set-add-clobber-set-has.js	                        (rev 0)
+++ trunk/JSTests/stress/set-add-clobber-set-has.js	2017-11-27 01:46:59 UTC (rev 225151)
@@ -0,0 +1,20 @@
+function shouldBe(actual, expected)
+{
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function test()
+{
+    var set = new Set();
+    var res1 = set.has(42);
+    set.add(42);
+    var res2 = set.has(42);
+    return [res1, res2];
+}
+
+for (var i = 0; i < 1e6; ++i) {
+    var [res1, res2] = test();
+    shouldBe(res1, false);
+    shouldBe(res2, true);
+}

Added: trunk/JSTests/stress/set-add-does-not-clobber-map-get.js (0 => 225151)


--- trunk/JSTests/stress/set-add-does-not-clobber-map-get.js	                        (rev 0)
+++ trunk/JSTests/stress/set-add-does-not-clobber-map-get.js	2017-11-27 01:46:59 UTC (rev 225151)
@@ -0,0 +1,19 @@
+function shouldBe(actual, expected)
+{
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function test()
+{
+    var map = new Map();
+    var set = new Set();
+    map.set(42, 42);
+    var res1 = map.get(42);
+    set.add(42);
+    var res2 = map.get(42);
+    return res1 + res2;
+}
+
+for (var i = 0; i < 1e6; ++i)
+    shouldBe(test(), 84);

Modified: trunk/Source/_javascript_Core/ChangeLog (225150 => 225151)


--- trunk/Source/_javascript_Core/ChangeLog	2017-11-27 01:22:43 UTC (rev 225150)
+++ trunk/Source/_javascript_Core/ChangeLog	2017-11-27 01:46:59 UTC (rev 225151)
@@ -1,5 +1,29 @@
 2017-11-26  Yusuke Suzuki  <[email protected]>
 
+        [DFG] Introduce {Set,Map,WeakMap}Fields
+        https://bugs.webkit.org/show_bug.cgi?id=179925
+
+        Reviewed by Saam Barati.
+
+        SetAdd and MapSet uses `write(MiscFields)`, but it is not correct. It accidentally
+        writes readonly MiscFields which is used by various nodes and make optimization
+        conservative.
+
+        We introduce JSSetFields, JSMapFields, and JSWeakMapFields to precisely model clobberizing of Map, Set, and WeakMap.
+
+        * dfg/DFGAbstractHeap.h:
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::handleIntrinsicCall):
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        * dfg/DFGHeapLocation.cpp:
+        (WTF::printInternal):
+        * dfg/DFGHeapLocation.h:
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::hasBucketOwnerType):
+
+2017-11-26  Yusuke Suzuki  <[email protected]>
+
         [JSC] Remove JSStringBuilder
         https://bugs.webkit.org/show_bug.cgi?id=180016
 

Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractHeap.h (225150 => 225151)


--- trunk/Source/_javascript_Core/dfg/DFGAbstractHeap.h	2017-11-27 01:22:43 UTC (rev 225150)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractHeap.h	2017-11-27 01:46:59 UTC (rev 225151)
@@ -72,6 +72,9 @@
     macro(HeapObjectCount) /* Used to reflect the fact that some allocations reveal object identity */\
     macro(RegExpState) \
     macro(MathDotRandomState) \
+    macro(JSMapFields) \
+    macro(JSSetFields) \
+    macro(JSWeakMapFields) \
     macro(InternalState) \
     macro(Absolute) \
     /* DOMJIT tells the heap range with the pair of integers. */\

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (225150 => 225151)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2017-11-27 01:22:43 UTC (rev 225150)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2017-11-27 01:46:59 UTC (rev 225151)
@@ -2875,7 +2875,7 @@
         Node* key = get(virtualRegisterForArgument(1, registerOffset));
         Node* hash = addToGraph(MapHash, key);
         Node* bucket = addToGraph(GetMapBucket, Edge(map, MapObjectUse), Edge(key), Edge(hash));
-        Node* result = addToGraph(LoadValueFromMapBucket, OpInfo(), OpInfo(prediction), bucket);
+        Node* result = addToGraph(LoadValueFromMapBucket, OpInfo(BucketOwnerType::Map), OpInfo(prediction), bucket);
         set(VirtualRegister(resultOperand), result);
         return true;
     }
@@ -2966,7 +2966,8 @@
 
         insertChecks();
         Node* bucket = get(virtualRegisterForArgument(1, registerOffset));
-        Node* result = addToGraph(LoadKeyFromMapBucket, OpInfo(), OpInfo(prediction), bucket);
+        BucketOwnerType type = intrinsic == JSSetBucketKeyIntrinsic ? BucketOwnerType::Set : BucketOwnerType::Map;
+        Node* result = addToGraph(LoadKeyFromMapBucket, OpInfo(type), OpInfo(prediction), bucket);
         set(VirtualRegister(resultOperand), result);
         return true;
     }
@@ -2976,7 +2977,7 @@
 
         insertChecks();
         Node* bucket = get(virtualRegisterForArgument(1, registerOffset));
-        Node* result = addToGraph(LoadValueFromMapBucket, OpInfo(), OpInfo(prediction), bucket);
+        Node* result = addToGraph(LoadValueFromMapBucket, OpInfo(BucketOwnerType::Map), OpInfo(prediction), bucket);
         set(VirtualRegister(resultOperand), result);
         return true;
     }

Modified: trunk/Source/_javascript_Core/dfg/DFGClobberize.h (225150 => 225151)


--- trunk/Source/_javascript_Core/dfg/DFGClobberize.h	2017-11-27 01:22:43 UTC (rev 225150)
+++ trunk/Source/_javascript_Core/dfg/DFGClobberize.h	2017-11-27 01:46:59 UTC (rev 225151)
@@ -1592,57 +1592,65 @@
         return;
 
     case GetMapBucket: {
-        read(MiscFields);
         Edge& mapEdge = node->child1();
         Edge& keyEdge = node->child2();
-        def(HeapLocation(MapBucketLoc, MiscFields, mapEdge, keyEdge), LazyNode(node));
+        AbstractHeapKind heap = (mapEdge.useKind() == MapObjectUse) ? JSMapFields : JSSetFields;
+        read(heap);
+        def(HeapLocation(MapBucketLoc, heap, mapEdge, keyEdge), LazyNode(node));
         return;
     }
 
     case GetMapBucketHead: {
-        read(MiscFields);
         Edge& mapEdge = node->child1();
-        def(HeapLocation(MapBucketHeadLoc, MiscFields, mapEdge), LazyNode(node));
+        AbstractHeapKind heap = (mapEdge.useKind() == MapObjectUse) ? JSMapFields : JSSetFields;
+        read(heap);
+        def(HeapLocation(MapBucketHeadLoc, heap, mapEdge), LazyNode(node));
         return;
     }
 
     case GetMapBucketNext: {
-        read(MiscFields);
-        LocationKind locationKind = MapBucketMapNextLoc;
-        if (node->bucketOwnerType() == BucketOwnerType::Set)
-            locationKind = MapBucketSetNextLoc;
+        AbstractHeapKind heap = (node->bucketOwnerType() == BucketOwnerType::Map) ? JSMapFields : JSSetFields;
+        read(heap);
         Edge& bucketEdge = node->child1();
-        def(HeapLocation(locationKind, MiscFields, bucketEdge), LazyNode(node));
+        def(HeapLocation(MapBucketNextLoc, heap, bucketEdge), LazyNode(node));
         return;
     }
 
     case LoadKeyFromMapBucket: {
-        read(MiscFields);
+        AbstractHeapKind heap = (node->bucketOwnerType() == BucketOwnerType::Map) ? JSMapFields : JSSetFields;
+        read(heap);
         Edge& bucketEdge = node->child1();
-        def(HeapLocation(MapBucketKeyLoc, MiscFields, bucketEdge), LazyNode(node));
+        def(HeapLocation(MapBucketKeyLoc, heap, bucketEdge), LazyNode(node));
         return;
     }
 
     case LoadValueFromMapBucket: {
-        read(MiscFields);
+        AbstractHeapKind heap = (node->bucketOwnerType() == BucketOwnerType::Map) ? JSMapFields : JSSetFields;
+        read(heap);
         Edge& bucketEdge = node->child1();
-        def(HeapLocation(MapBucketValueLoc, MiscFields, bucketEdge), LazyNode(node));
+        def(HeapLocation(MapBucketValueLoc, heap, bucketEdge), LazyNode(node));
         return;
     }
 
     case WeakMapGet: {
-        read(MiscFields);
         Edge& mapEdge = node->child1();
         Edge& keyEdge = node->child2();
-        def(HeapLocation(WeakMapGetLoc, MiscFields, mapEdge, keyEdge), LazyNode(node));
+        read(JSWeakMapFields);
+        def(HeapLocation(WeakMapGetLoc, JSWeakMapFields, mapEdge, keyEdge), LazyNode(node));
         return;
     }
 
-    case SetAdd:
+    case SetAdd: {
+        // FIXME: Define defs for them to participate in CSE.
+        // https://bugs.webkit.org/show_bug.cgi?id=179911
+        write(JSSetFields);
+        return;
+    }
+
     case MapSet: {
         // FIXME: Define defs for them to participate in CSE.
         // https://bugs.webkit.org/show_bug.cgi?id=179911
-        write(MiscFields);
+        write(JSMapFields);
         return;
     }
 

Modified: trunk/Source/_javascript_Core/dfg/DFGHeapLocation.cpp (225150 => 225151)


--- trunk/Source/_javascript_Core/dfg/DFGHeapLocation.cpp	2017-11-27 01:22:43 UTC (rev 225150)
+++ trunk/Source/_javascript_Core/dfg/DFGHeapLocation.cpp	2017-11-27 01:46:59 UTC (rev 225151)
@@ -180,14 +180,10 @@
         out.print("MapBucketValueLoc");
         return;
 
-    case MapBucketMapNextLoc:
-        out.print("MapBucketMapNextLoc");
+    case MapBucketNextLoc:
+        out.print("MapBucketNextLoc");
         return;
 
-    case MapBucketSetNextLoc:
-        out.print("MapBucketSetNextLoc");
-        return;
-
     case WeakMapGetLoc:
         out.print("WeakMapGetLoc");
         return;

Modified: trunk/Source/_javascript_Core/dfg/DFGHeapLocation.h (225150 => 225151)


--- trunk/Source/_javascript_Core/dfg/DFGHeapLocation.h	2017-11-27 01:22:43 UTC (rev 225150)
+++ trunk/Source/_javascript_Core/dfg/DFGHeapLocation.h	2017-11-27 01:46:59 UTC (rev 225151)
@@ -67,8 +67,7 @@
     MapBucketHeadLoc,
     MapBucketValueLoc,
     MapBucketKeyLoc,
-    MapBucketMapNextLoc,
-    MapBucketSetNextLoc,
+    MapBucketNextLoc,
     WeakMapGetLoc,
     DOMStateLoc,
 };

Modified: trunk/Source/_javascript_Core/dfg/DFGNode.h (225150 => 225151)


--- trunk/Source/_javascript_Core/dfg/DFGNode.h	2017-11-27 01:22:43 UTC (rev 225150)
+++ trunk/Source/_javascript_Core/dfg/DFGNode.h	2017-11-27 01:46:59 UTC (rev 225151)
@@ -2633,7 +2633,7 @@
 
     bool hasBucketOwnerType()
     {
-        return op() == GetMapBucketNext;
+        return op() == GetMapBucketNext || op() == LoadKeyFromMapBucket || op() == LoadValueFromMapBucket;
     }
 
     BucketOwnerType bucketOwnerType()
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to