4ee6a66270
The change in [0] increased the language version of pkg/dart2wasm. That in return changes how the package is formatted by the autoformatter. This CL runs now the formatter to re-format the code. Unfortunately this makes blame lists worse. But not doing it will make us have to disable auto-formatting before saving files which is very annoying. [0] https://dart-review.googlesource.com/c/sdk/+/487944 Change-Id: I6953fe0d6a824b2b79a26bbadb0bb977cec70b7a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/490821 Reviewed-by: Slava Egorov <vegorov@google.com> Commit-Queue: Martin Kustermann <kustermann@google.com>
90 lines
3.4 KiB
Dart
90 lines
3.4 KiB
Dart
// Copyright (c) 2025, 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.
|
|
|
|
import 'package:kernel/kernel.dart';
|
|
import 'package:vm/metadata/direct_call.dart';
|
|
import 'package:vm/metadata/procedure_attributes.dart';
|
|
import 'package:vm/metadata/table_selector.dart';
|
|
|
|
/// Oracle that knows whether instance members will be always called directly
|
|
/// (i.e. all call sites are devirtualized direct calls instead of instance
|
|
/// calls).
|
|
class DevirtualizionOracle {
|
|
final Map<TreeNode, DirectCallMetadata> _directCallMetadata;
|
|
final Map<TreeNode, ProcedureAttributesMetadata> _procedureAttributeMetadata;
|
|
final List<TableSelectorInfo> _selectorMetadata;
|
|
|
|
DevirtualizionOracle(
|
|
this._directCallMetadata,
|
|
this._procedureAttributeMetadata,
|
|
this._selectorMetadata,
|
|
);
|
|
|
|
/// Whether all call sites are guaranteed to be devirtualized.
|
|
bool isAlwaysStaticallyDispatchedTo(Reference reference) {
|
|
final member = reference.asMember;
|
|
assert(member.isInstanceMember);
|
|
final metadata = _procedureAttributeMetadata[member]!;
|
|
|
|
final bool isGetter =
|
|
member is Field && reference == member.getterReference ||
|
|
member is Procedure && member.isGetter;
|
|
|
|
if (isGetter) {
|
|
if (metadata.getterCalledDynamically) return false;
|
|
|
|
final getterId = metadata.getterSelectorId;
|
|
if (getterId != ProcedureAttributesMetadata.kInvalidSelectorId) {
|
|
final selector = _selectorMetadata[getterId];
|
|
if (selector.callCount != 0 || selector.tornOff) {
|
|
return false;
|
|
}
|
|
}
|
|
} else {
|
|
if (metadata.methodOrSetterCalledDynamically) return false;
|
|
// This method may be dynamically torn off.
|
|
if (metadata.getterCalledDynamically) return false;
|
|
|
|
final methodOrSetterId = metadata.methodOrSetterSelectorId;
|
|
if (methodOrSetterId != ProcedureAttributesMetadata.kInvalidSelectorId) {
|
|
final selector = _selectorMetadata[methodOrSetterId];
|
|
if (selector.callCount != 0 || selector.tornOff) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
// All uses of this [member] will be devirtualized uses. The deferred
|
|
// loading partitioning algorithm will - on all call sites (which are
|
|
// guaranteed to be devirtualized) - make this target a direct dependency
|
|
// (via calling `staticDispatchTargetFor*` methods below) instead of
|
|
// conservatively enquing this method whenever the class is allocated.
|
|
return true;
|
|
}
|
|
|
|
Reference? staticDispatchTargetForGet(InstanceGet node) {
|
|
final devirtualizedTarget = _directCallMetadata[node]?.targetMember;
|
|
if (devirtualizedTarget == null) return null;
|
|
if (devirtualizedTarget is Field) {
|
|
return devirtualizedTarget.getterReference;
|
|
}
|
|
return (devirtualizedTarget as Procedure).reference;
|
|
}
|
|
|
|
Reference? staticDispatchTargetForSet(InstanceSet node) {
|
|
final devirtualizedTarget = _directCallMetadata[node]?.targetMember;
|
|
if (devirtualizedTarget == null) return null;
|
|
if (devirtualizedTarget is Field) {
|
|
return devirtualizedTarget.setterReference;
|
|
}
|
|
return (devirtualizedTarget as Procedure).reference;
|
|
}
|
|
|
|
Reference? staticDispatchTargetForCall(InstanceInvocation node) {
|
|
final devirtualizedTarget = _directCallMetadata[node]?.targetMember;
|
|
if (devirtualizedTarget == null) return null;
|
|
return (devirtualizedTarget as Procedure).reference;
|
|
}
|
|
}
|