Skip to content

Commit b096839

Browse files
aartbikcommit-bot@chromium.org
authored andcommitted
[vm/compiler] Minor heuristic change to reduce code size
Rationale: Inlining constant constructors/mixin is practically always profitable. So the heuristics have been changed to at least consider these even at higher depth (note that they are of course still subject to actual heuristics while inlining). This brings back flutter gallery size to where it was before mixins were introduced. head: VMIsolate(CodeSize): 4737 Isolate(CodeSize): 2005123 101% ReadOnlyData(CodeSize): 2212408 103% Instructions(CodeSize): 7006928 100% Total(CodeSize): 11229196 101% improved heuristic: VMIsolate(CodeSize): 4737 Isolate(CodeSize): 1985691 ReadOnlyData(CodeSize): 2152880 Instructions(CodeSize): 6987616 Total(CodeSize): 11130924 #37126 Change-Id: I28de0fa6c92a785bbc47e9fa09ed55ae68593c0a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/112758 Commit-Queue: Aart Bik <[email protected]> Reviewed-by: Alexander Markov <[email protected]>
1 parent 762f049 commit b096839

File tree

2 files changed

+59
-13
lines changed

2 files changed

+59
-13
lines changed

runtime/vm/compiler/backend/inliner.cc

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -433,10 +433,10 @@ class CallSites : public ValueObject {
433433
return;
434434
}
435435

436-
// Recognized methods are not treated as normal calls. They don't have
437-
// calls in themselves, so we keep adding those even when at the threshold.
438-
const bool inline_only_recognized_methods =
439-
(depth == inlining_depth_threshold_);
436+
// At the maximum inlining depth, only profitable methods
437+
// are further considered for inlining.
438+
const bool inline_only_profitable_methods =
439+
(depth >= inlining_depth_threshold_);
440440

441441
// In AOT, compute loop hierarchy.
442442
if (FLAG_precompiled_mode) {
@@ -454,13 +454,15 @@ class CallSites : public ValueObject {
454454
if (current->IsPolymorphicInstanceCall()) {
455455
PolymorphicInstanceCallInstr* instance_call =
456456
current->AsPolymorphicInstanceCall();
457-
if (!inline_only_recognized_methods ||
457+
if (!inline_only_profitable_methods ||
458458
instance_call->IsSureToCallSingleRecognizedTarget() ||
459459
instance_call->HasOnlyDispatcherOrImplicitAccessorTargets()) {
460+
// Consider instance call for further inlining. Note that it will
461+
// still be subject to all the inlining heuristics.
460462
instance_calls_.Add(InstanceCallInfo(instance_call, graph, depth));
461463
} else {
462-
// Method not inlined because inlining too deep and method
463-
// not recognized.
464+
// No longer consider the instance call because inlining is too
465+
// deep and the method is not deemed profitable by other criteria.
464466
if (FLAG_print_inlining_tree) {
465467
const Function* caller = &graph->function();
466468
const Function* target = &instance_call->targets().FirstTarget();
@@ -470,13 +472,16 @@ class CallSites : public ValueObject {
470472
}
471473
} else if (current->IsStaticCall()) {
472474
StaticCallInstr* static_call = current->AsStaticCall();
473-
if (!inline_only_recognized_methods ||
474-
static_call->function().IsRecognized() ||
475-
static_call->function().IsDispatcherOrImplicitAccessor()) {
475+
const Function& function = static_call->function();
476+
if (!inline_only_profitable_methods || function.IsRecognized() ||
477+
function.IsDispatcherOrImplicitAccessor() ||
478+
(function.is_const() && function.IsGenerativeConstructor())) {
479+
// Consider static call for further inlining. Note that it will
480+
// still be subject to all the inlining heuristics.
476481
static_calls_.Add(StaticCallInfo(static_call, graph, depth));
477482
} else {
478-
// Method not inlined because inlining too deep and method
479-
// not recognized.
483+
// No longer consider the static call because inlining is too
484+
// deep and the method is not deemed profitable by other criteria.
480485
if (FLAG_print_inlining_tree) {
481486
const Function* caller = &graph->function();
482487
const Function* target = &static_call->function();
@@ -485,9 +490,13 @@ class CallSites : public ValueObject {
485490
}
486491
}
487492
} else if (current->IsClosureCall()) {
488-
if (!inline_only_recognized_methods) {
493+
if (!inline_only_profitable_methods) {
494+
// Consider closure for further inlining. Note that it will
495+
// still be subject to all the inlining heuristics.
489496
ClosureCallInstr* closure_call = current->AsClosureCall();
490497
closure_calls_.Add(ClosureCallInfo(closure_call, graph));
498+
} else {
499+
// No longer consider the closure because inlining is too deep.
491500
}
492501
}
493502
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
// Illustrates inlining heuristic issue of
6+
// https://github.com/dart-lang/sdk/issues/37126
7+
// (mixins introduce one extra depth of inlining).
8+
9+
// VMOptions=--deterministic
10+
11+
import "package:expect/expect.dart";
12+
13+
class X {
14+
const X();
15+
int foo() {
16+
return 1;
17+
}
18+
}
19+
20+
mixin YMixin {
21+
int bar() {
22+
return 2;
23+
}
24+
}
25+
26+
class Y with YMixin {
27+
const Y();
28+
}
29+
30+
@pragma("vm:never-inline")
31+
int foobar() {
32+
return new X().foo() + new Y().bar();
33+
}
34+
35+
main() {
36+
Expect.equals(3, foobar());
37+
}

0 commit comments

Comments
 (0)