mirror of
https://github.com/dart-lang/sdk
synced 2024-10-06 14:18:06 +00:00
Implement inlining heuristics on conditional expression.
Change-Id: I183b6345e29d6c00f140dcbd1ffff05faf0e781f Reviewed-on: https://dart-review.googlesource.com/30442 Reviewed-by: Sigmund Cherem <sigmund@google.com>
This commit is contained in:
parent
72736aff0d
commit
12ee4edbb8
|
@ -4838,6 +4838,7 @@ class InlineWeeder extends ir.Visitor {
|
|||
return true;
|
||||
}
|
||||
|
||||
@override
|
||||
defaultNode(ir.Node node) {
|
||||
if (tooDifficult) return;
|
||||
if (!registerNode()) return;
|
||||
|
@ -4848,6 +4849,7 @@ class InlineWeeder extends ir.Visitor {
|
|||
node.visitChildren(this);
|
||||
}
|
||||
|
||||
@override
|
||||
visitReturnStatement(ir.ReturnStatement node) {
|
||||
if (!registerNode()) return;
|
||||
if (seenReturn) {
|
||||
|
@ -4858,6 +4860,7 @@ class InlineWeeder extends ir.Visitor {
|
|||
seenReturn = true;
|
||||
}
|
||||
|
||||
@override
|
||||
visitThrow(ir.Throw node) {
|
||||
if (!registerNode()) return;
|
||||
if (seenReturn) {
|
||||
|
@ -4876,42 +4879,51 @@ class InlineWeeder extends ir.Visitor {
|
|||
// isn't in the AST based inline weeder.
|
||||
}
|
||||
|
||||
@override
|
||||
visitForStatement(ir.ForStatement node) {
|
||||
_handleLoop();
|
||||
}
|
||||
|
||||
@override
|
||||
visitForInStatement(ir.ForInStatement node) {
|
||||
_handleLoop();
|
||||
}
|
||||
|
||||
@override
|
||||
visitWhileStatement(ir.WhileStatement node) {
|
||||
_handleLoop();
|
||||
}
|
||||
|
||||
@override
|
||||
visitDoStatement(ir.DoStatement node) {
|
||||
_handleLoop();
|
||||
}
|
||||
|
||||
@override
|
||||
visitTryCatch(ir.TryCatch node) {
|
||||
if (tooDifficult) return;
|
||||
tooDifficultReason = 'try';
|
||||
}
|
||||
|
||||
@override
|
||||
visitTryFinally(ir.TryFinally node) {
|
||||
if (tooDifficult) return;
|
||||
tooDifficultReason = 'try';
|
||||
}
|
||||
|
||||
@override
|
||||
visitFunctionExpression(ir.FunctionExpression node) {
|
||||
if (!registerNode()) return;
|
||||
tooDifficultReason = 'closure';
|
||||
}
|
||||
|
||||
@override
|
||||
visitFunctionDeclaration(ir.FunctionDeclaration node) {
|
||||
if (!registerNode()) return;
|
||||
tooDifficultReason = 'closure';
|
||||
}
|
||||
|
||||
@override
|
||||
visitFunctionNode(ir.FunctionNode node) {
|
||||
if (node.asyncMarker != ir.AsyncMarker.Sync) {
|
||||
tooDifficultReason = 'async/await';
|
||||
|
@ -4919,6 +4931,36 @@ class InlineWeeder extends ir.Visitor {
|
|||
}
|
||||
node.visitChildren(this);
|
||||
}
|
||||
|
||||
@override
|
||||
visitConditionalExpression(ir.ConditionalExpression node) {
|
||||
// Heuristic: In "parameter ? A : B" there is a high probability that
|
||||
// parameter is a constant. Assuming the parameter is constant, we can
|
||||
// compute a count that is bounded by the largest arm rather than the sum of
|
||||
// both arms.
|
||||
ir.Expression condition = node.condition;
|
||||
condition.accept(this);
|
||||
if (tooDifficult) return;
|
||||
int commonPrefixCount = nodeCount;
|
||||
|
||||
node.then.accept(this);
|
||||
if (tooDifficult) return;
|
||||
int thenCount = nodeCount - commonPrefixCount;
|
||||
|
||||
nodeCount = commonPrefixCount;
|
||||
node.otherwise.accept(this);
|
||||
if (tooDifficult) return;
|
||||
int elseCount = nodeCount - commonPrefixCount;
|
||||
|
||||
nodeCount = commonPrefixCount + thenCount + elseCount;
|
||||
if (condition is ir.VariableGet &&
|
||||
condition.variable.parent is ir.FunctionNode) {
|
||||
nodeCount =
|
||||
commonPrefixCount + (thenCount > elseCount ? thenCount : elseCount);
|
||||
}
|
||||
// This is last so that [tooDifficult] is always updated.
|
||||
if (!registerNode()) return;
|
||||
}
|
||||
}
|
||||
|
||||
/// Class in charge of building try, catch and/or finally blocks. This handles
|
||||
|
|
63
tests/compiler/dart2js/inlining/data/conditional.dart
Normal file
63
tests/compiler/dart2js/inlining/data/conditional.dart
Normal file
|
@ -0,0 +1,63 @@
|
|||
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
// Tests for the heuristics on conditional expression whose condition is a
|
||||
// parameter for which the max, instead of the sum, of the branch sizes is used.
|
||||
|
||||
// ignore: IMPORT_INTERNAL_LIBRARY
|
||||
import 'dart:_js_helper';
|
||||
|
||||
/*element: main:[]*/
|
||||
main() {
|
||||
conditionalField();
|
||||
conditionalParameter();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Conditional expression on a non-parameter (here a top-level field). The
|
||||
// size of the condition is the sum of the nodes in the conditional expression.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*element: _method1:[_conditionalField]*/
|
||||
_method1() => 42;
|
||||
|
||||
var _field1;
|
||||
|
||||
/*element: _conditionalField:[]*/
|
||||
_conditionalField() {
|
||||
return _field1
|
||||
? _method1() + _method1() + _method1()
|
||||
: _method1() + _method1() + _method1();
|
||||
}
|
||||
|
||||
/*element: conditionalField:[]*/
|
||||
@NoInline()
|
||||
conditionalField() {
|
||||
_field1 = false;
|
||||
_conditionalField();
|
||||
_field1 = true;
|
||||
_conditionalField();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Conditional expression on a parameter. The size of the condition is the
|
||||
// max of the branches + the condition itself.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*element: _method2:[conditionalParameter]*/
|
||||
_method2() => 42;
|
||||
|
||||
/*element: _conditionalParameter:[conditionalParameter]*/
|
||||
_conditionalParameter(o) {
|
||||
return o
|
||||
? _method2() + _method2() + _method2()
|
||||
: _method2() + _method2() + _method2();
|
||||
}
|
||||
|
||||
/*element: conditionalParameter:[]*/
|
||||
@NoInline()
|
||||
conditionalParameter() {
|
||||
_conditionalParameter(true);
|
||||
_conditionalParameter(false);
|
||||
}
|
Loading…
Reference in a new issue