Skip to content

Commit 063b3c1

Browse files
rakudramaCommit Queue
authored andcommitted
[dart2js] Add missing case of updating call attributes
When an indirect call is replaced by a direct call, the direct call (HInvokeStatic) should have the correct attributes for the target. Change-Id: I950b6ed4f1537e2420905ac45d89a2bd6f2fa2c8 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/448442 Commit-Queue: Stephen Adams <[email protected]> Reviewed-by: Nate Biggs <[email protected]>
1 parent 20b6cd1 commit 063b3c1

File tree

2 files changed

+67
-1
lines changed

2 files changed

+67
-1
lines changed

pkg/compiler/lib/src/ssa/optimize.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2219,12 +2219,14 @@ class SsaInstructionSimplifier extends HBaseVisitor<HInstruction>
22192219
if (parameterStructure.callStructure == node.selector.callStructure) {
22202220
// TODO(sra): Handle adding optional arguments default values.
22212221
assert(!node.isInterceptedCall);
2222-
return HInvokeStatic(
2222+
final replacement = HInvokeStatic(
22232223
target,
22242224
node.inputs.skip(1).toList(),
22252225
node.instructionType,
22262226
node.typeArguments,
22272227
)..sourceInformation = node.sourceInformation;
2228+
_updateInvocationAttributes(replacement, target);
2229+
return replacement;
22282230
}
22292231
}
22302232
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Copyright (c) 2025, 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+
/*member: main:ignore*/
6+
void main() {
7+
for (final f in [test1, test2, test3, test4]) {
8+
f();
9+
print([sink1, sink2]);
10+
}
11+
}
12+
13+
Object? sink1;
14+
Object? sink2;
15+
16+
@pragma('dart2js:never-inline')
17+
@pragma('dart2js:allow-cse')
18+
/*member: foo:ignore*/
19+
int foo(int n) => n;
20+
21+
/*member: test1:function() {
22+
$.sink2 = $.sink1 = A.foo(1);
23+
}*/
24+
void test1() {
25+
// Expect one call that is reused.
26+
sink1 = foo(1);
27+
sink2 = foo(1);
28+
}
29+
30+
/*member: test2:function() {
31+
$.sink2 = $.sink1 = A.foo(2);
32+
}*/
33+
void test2() {
34+
// Expect one direct call that is reused.
35+
36+
// The optimizer replaces the indirect (closure) call `(fa)(2)` with a direct
37+
// call `foo(2)`. If the call attributes on the direct call are set correctly
38+
// for the known target, allow-cse will be enabled.
39+
40+
final fa = foo;
41+
sink1 = fa(2);
42+
final fb = foo;
43+
sink2 = fb(2);
44+
}
45+
46+
/*member: test3:function() {
47+
$.sink2 = $.sink1 = A.foo(3);
48+
}*/
49+
void test3() {
50+
// Variation on test2.
51+
sink1 = foo(3);
52+
final fb = foo;
53+
sink2 = fb(3);
54+
}
55+
56+
/*member: test4:function() {
57+
$.sink2 = $.sink1 = A.foo(4);
58+
}*/
59+
void test4() {
60+
// Variation on test2.
61+
final fa = foo;
62+
sink1 = fa(4);
63+
sink2 = foo(4);
64+
}

0 commit comments

Comments
 (0)