- Revision
- 229520
- Author
- utatane....@gmail.com
- Date
- 2018-03-11 20:25:39 -0700 (Sun, 11 Mar 2018)
Log Message
[DFG] AI should convert CreateThis to NewObject if the prototype object is proved
https://bugs.webkit.org/show_bug.cgi?id=183310
Reviewed by Filip Pizlo.
JSTests:
* stress/ai-create-this-to-new-object-fire.js: Added.
(assert):
(test):
(func):
(check):
(test.body.A):
(test.body.B):
(test.body):
* stress/ai-create-this-to-new-object.js: Added.
(assert):
(test):
(func):
(check):
(test.body.A):
(test.body.B):
(test.body):
Source/_javascript_Core:
This patch implements CreateThis -> NewObject conversion in AI if the given function is constant.
This contributes to 6% win in Octane/raytrace.
baseline patched
raytrace x2 1.19915+-0.01862 ^ 1.13156+-0.01589 ^ definitely 1.0597x faster
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGConstantFoldingPhase.cpp:
(JSC::DFG::ConstantFoldingPhase::foldConstants):
Modified Paths
Added Paths
Diff
Modified: trunk/JSTests/ChangeLog (229519 => 229520)
--- trunk/JSTests/ChangeLog 2018-03-11 22:05:21 UTC (rev 229519)
+++ trunk/JSTests/ChangeLog 2018-03-12 03:25:39 UTC (rev 229520)
@@ -1,3 +1,27 @@
+2018-03-11 Yusuke Suzuki <utatane....@gmail.com>
+
+ [DFG] AI should convert CreateThis to NewObject if the prototype object is proved
+ https://bugs.webkit.org/show_bug.cgi?id=183310
+
+ Reviewed by Filip Pizlo.
+
+ * stress/ai-create-this-to-new-object-fire.js: Added.
+ (assert):
+ (test):
+ (func):
+ (check):
+ (test.body.A):
+ (test.body.B):
+ (test.body):
+ * stress/ai-create-this-to-new-object.js: Added.
+ (assert):
+ (test):
+ (func):
+ (check):
+ (test.body.A):
+ (test.body.B):
+ (test.body):
+
2018-03-10 Yusuke Suzuki <utatane....@gmail.com>
[FTL] Drop NewRegexp for String.prototype.match with RegExp + global flag
Added: trunk/JSTests/stress/ai-create-this-to-new-object-fire.js (0 => 229520)
--- trunk/JSTests/stress/ai-create-this-to-new-object-fire.js (rev 0)
+++ trunk/JSTests/stress/ai-create-this-to-new-object-fire.js 2018-03-12 03:25:39 UTC (rev 229520)
@@ -0,0 +1,61 @@
+function assert(b, m = "Bad!") {
+ if (!b) {
+ throw new Error(m);
+ }
+}
+
+function test(f, iters = 1000) {
+ for (let i = 0; i < iters; i++)
+ f(i);
+}
+
+function func(x) {
+ return x;
+}
+noInline(func);
+
+var n = 2;
+var prototype = {};
+function prep(index, i, A, B)
+{
+ if (index === (n - 1) && i === 5000) {
+ // Fire watchpoint!
+ A.prototype = prototype;
+ }
+}
+
+function check(index, arr, A, B, originalPrototype)
+{
+ if (index === (n - 1)) {
+ assert(originalPrototype !== prototype);
+ for (let i = 0; i < 5000; i++)
+ assert(arr[i].__proto__ === originalPrototype);
+ for (let i = 5000; i < 10000; i++)
+ assert(arr[i].__proto__ === prototype);
+ } else {
+ for (let i = 0; i < 10000; i++)
+ assert(arr[i].__proto__ === originalPrototype);
+ }
+}
+noInline(check);
+
+test(function body(index) {
+ function A(x, f = func) {
+ this._value = x;
+ this._func = f;
+ }
+
+ function B(n)
+ {
+ return new A(n);
+ }
+
+ var originalPrototype = A.prototype;
+ let arr = [];
+ for (let i = 0; i < 10000; i++) {
+ prep(index, i, A, B);
+ arr.push(B(20));
+ }
+
+ check(index, arr, A, B, originalPrototype);
+}, n);
Added: trunk/JSTests/stress/ai-create-this-to-new-object.js (0 => 229520)
--- trunk/JSTests/stress/ai-create-this-to-new-object.js (rev 0)
+++ trunk/JSTests/stress/ai-create-this-to-new-object.js 2018-03-12 03:25:39 UTC (rev 229520)
@@ -0,0 +1,41 @@
+function assert(b, m = "Bad!") {
+ if (!b) {
+ throw new Error(m);
+ }
+}
+
+function test(f, iters = 1000) {
+ for (let i = 0; i < iters; i++)
+ f(i);
+}
+
+function func(x) {
+ return x;
+}
+noInline(func);
+
+function check(index, arr, B)
+{
+ for (let i = 0; i < 1000; i++)
+ assert(arr[i] instanceof B);
+}
+noInline(check);
+
+test(function body(index) {
+ class A {
+ constructor(x, f = func)
+ {
+ this._value = x;
+ this._func = f;
+ }
+ }
+
+ class B extends A {
+ }
+
+ let arr = [];
+ for (let i = 0; i < 1000; i++)
+ arr.push(new B(20));
+
+ check(index, arr, B);
+}, 8);
Modified: trunk/Source/_javascript_Core/ChangeLog (229519 => 229520)
--- trunk/Source/_javascript_Core/ChangeLog 2018-03-11 22:05:21 UTC (rev 229519)
+++ trunk/Source/_javascript_Core/ChangeLog 2018-03-12 03:25:39 UTC (rev 229520)
@@ -1,3 +1,22 @@
+2018-03-11 Yusuke Suzuki <utatane....@gmail.com>
+
+ [DFG] AI should convert CreateThis to NewObject if the prototype object is proved
+ https://bugs.webkit.org/show_bug.cgi?id=183310
+
+ Reviewed by Filip Pizlo.
+
+ This patch implements CreateThis -> NewObject conversion in AI if the given function is constant.
+ This contributes to 6% win in Octane/raytrace.
+
+ baseline patched
+
+ raytrace x2 1.19915+-0.01862 ^ 1.13156+-0.01589 ^ definitely 1.0597x faster
+
+ * dfg/DFGAbstractInterpreterInlines.h:
+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+ * dfg/DFGConstantFoldingPhase.cpp:
+ (JSC::DFG::ConstantFoldingPhase::foldConstants):
+
2018-03-11 Wenson Hsieh <wenson_hs...@apple.com>
Disable Sigill crash analyzer on watchOS
Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (229519 => 229520)
--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2018-03-11 22:05:21 UTC (rev 229519)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2018-03-12 03:25:39 UTC (rev 229520)
@@ -2257,7 +2257,23 @@
}
case CreateThis: {
- // FIXME: We can fold this to NewObject if the incoming callee is a constant.
+ if (JSValue base = forNode(node->child1()).m_value) {
+ if (auto* function = jsDynamicCast<JSFunction*>(m_vm, base)) {
+ if (FunctionRareData* rareData = function->rareData()) {
+ if (Structure* structure = rareData->objectAllocationStructure()) {
+ // FIXME: we should be able to allocate a poly proto object here:
+ // https://bugs.webkit.org/show_bug.cgi?id=177517
+ if (structure->hasMonoProto()) {
+ m_graph.freeze(rareData);
+ m_graph.watchpoints().addLazily(rareData->allocationProfileWatchpointSet());
+ m_state.setFoundConstants(true);
+ forNode(node).set(m_graph, structure);
+ break;
+ }
+ }
+ }
+ }
+ }
forNode(node).setType(m_graph, SpecFinalObject);
break;
}
Modified: trunk/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp (229519 => 229520)
--- trunk/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp 2018-03-11 22:05:21 UTC (rev 229519)
+++ trunk/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp 2018-03-12 03:25:39 UTC (rev 229520)
@@ -636,6 +636,27 @@
break;
}
+ case CreateThis: {
+ if (JSValue base = m_state.forNode(node->child1()).m_value) {
+ if (auto* function = jsDynamicCast<JSFunction*>(m_graph.m_vm, base)) {
+ if (FunctionRareData* rareData = function->rareData()) {
+ if (Structure* structure = rareData->objectAllocationStructure()) {
+ // FIXME: we should be able to allocate a poly proto object here:
+ // https://bugs.webkit.org/show_bug.cgi?id=177517
+ if (structure->hasMonoProto()) {
+ m_graph.freeze(rareData);
+ m_graph.watchpoints().addLazily(rareData->allocationProfileWatchpointSet());
+ node->convertToNewObject(m_graph.registerStructure(structure));
+ changed = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ break;
+ }
+
case ToNumber: {
if (m_state.forNode(node->child1()).m_type & ~SpecBytecodeNumber)
break;