blob: 2d3e78360c9d96e2f4c4e4f9a4c3a3baeb61ef27 [file] [log] [blame]
// Copyright (c) 2024, 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.
// Regression test for https://github.com/dart-lang/sdk/issues/55343.
// Verifies that AOT runtime doesn't crash when resolving target of
// a dynamic call when corresponding UnlinkedCall objects are de-duplicated
// and origin function of the UnlinkedCall is not included into the snapshot.
class A {
@pragma('vm:never-inline')
void foo() {}
@pragma('vm:never-inline')
void bar() {}
}
class B {
@pragma('vm:never-inline')
void foo() {
f1();
}
@pragma('vm:never-inline')
void bar() {}
}
@pragma('vm:entry-point')
dynamic v;
@pragma('vm:never-inline')
void f1() {
v.bar();
}
@pragma('vm:never-inline')
void f2() {
v.bar();
}
class G {
final i;
const G(this.i);
@pragma('vm:never-inline')
void call() {
f2();
}
}
void main(List<String> args) {
v = args.contains('A') ? A() : B();
// Make sure [G] is marked allocated by backend by allocating it and
// letting it escape. This will cause [G.call] to be compiled, which
// will cause [f2] to be compiled.
print(G(1));
if (G(1).i != 1) {
// This code will be pruned by the backend, but not by the TFA:
// we want TFA to retain [G.call] method.
G(0).call();
}
// We want [f1] to be compiled after [f2] so we use an indirection
// through a dynamic call.
v.foo();
}