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()