[dart2js] Enable core lints.
Change-Id: Id5a14797e3e5eb8b68bd009d65b474748902fbe0 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/400162 Reviewed-by: Nate Biggs <natebiggs@google.com>
This commit is contained in:
committed by
Commit Queue
parent
49076fe6f4
commit
017bda44cf
@@ -12,6 +12,8 @@ analyzer:
|
||||
strict-inference: true
|
||||
strict-raw-types: true
|
||||
|
||||
include: package:lints/core.yaml
|
||||
|
||||
linter:
|
||||
rules:
|
||||
- always_declare_return_types
|
||||
|
||||
@@ -272,12 +272,6 @@ class ClosureRepresentationInfo extends ScopeInfo {
|
||||
/// The signature method for [callMethod] if needed.
|
||||
FunctionEntity? get signatureMethod => null;
|
||||
|
||||
/// List of locals that this closure class has created corresponding field
|
||||
/// entities for.
|
||||
@deprecated
|
||||
List<Local> getCreatedFieldEntities(KernelToLocalsMap localsMap) =>
|
||||
const <Local>[];
|
||||
|
||||
/// As shown in the example in the comments at the top of this class, we
|
||||
/// create fields in the closure class for each captured variable. This is an
|
||||
/// accessor the [local] for which [field] was created.
|
||||
|
||||
@@ -308,7 +308,7 @@ class CodegenRegistry {
|
||||
@override
|
||||
String toString() => 'CodegenRegistry for $_currentElement';
|
||||
|
||||
@deprecated
|
||||
@Deprecated("Use StaticUse for precise registration of statically known use")
|
||||
void registerInstantiatedClass(ClassEntity element) {
|
||||
registerInstantiation(_elementEnvironment.getRawType(element));
|
||||
}
|
||||
|
||||
@@ -97,67 +97,67 @@ abstract class CommonElements {
|
||||
|
||||
/// The dart:core library.
|
||||
late final LibraryEntity coreLibrary =
|
||||
_env.lookupLibrary(Uris.dart_core, required: true)!;
|
||||
_env.lookupLibrary(Uris.dartCore, required: true)!;
|
||||
|
||||
/// The dart:async library.
|
||||
late final LibraryEntity? asyncLibrary = _env.lookupLibrary(Uris.dart_async);
|
||||
late final LibraryEntity? asyncLibrary = _env.lookupLibrary(Uris.dartAsync);
|
||||
|
||||
/// The dart:collection library.
|
||||
late final LibraryEntity? collectionLibrary =
|
||||
_env.lookupLibrary(Uris.dart_collection);
|
||||
_env.lookupLibrary(Uris.dartCollection);
|
||||
|
||||
/// The dart:mirrors library.
|
||||
/// Null if the program doesn't access dart:mirrors.
|
||||
late final LibraryEntity? mirrorsLibrary =
|
||||
_env.lookupLibrary(Uris.dart_mirrors);
|
||||
_env.lookupLibrary(Uris.dartMirrors);
|
||||
|
||||
/// The dart:typed_data library.
|
||||
late final LibraryEntity typedDataLibrary =
|
||||
_env.lookupLibrary(Uris.dart__native_typed_data, required: true)!;
|
||||
_env.lookupLibrary(Uris.dartNativeTypedData, required: true)!;
|
||||
|
||||
/// The dart:_js_shared_embedded_names library.
|
||||
late final LibraryEntity sharedEmbeddedNamesLibrary =
|
||||
_env.lookupLibrary(Uris.dart__js_shared_embedded_names, required: true)!;
|
||||
_env.lookupLibrary(Uris.dartJSSharedEmbeddedNames, required: true)!;
|
||||
|
||||
/// The dart:_js_helper library.
|
||||
late final LibraryEntity? jsHelperLibrary =
|
||||
_env.lookupLibrary(Uris.dart__js_helper);
|
||||
_env.lookupLibrary(Uris.dartJSHelper);
|
||||
|
||||
/// The dart:_late_helper library
|
||||
late final LibraryEntity? lateHelperLibrary =
|
||||
_env.lookupLibrary(Uris.dart__late_helper);
|
||||
_env.lookupLibrary(Uris.dartLateHelper);
|
||||
|
||||
/// The dart:_interceptors library.
|
||||
late final LibraryEntity? interceptorsLibrary =
|
||||
_env.lookupLibrary(Uris.dart__interceptors);
|
||||
_env.lookupLibrary(Uris.dartInterceptors);
|
||||
|
||||
/// The dart:_foreign_helper library.
|
||||
late final LibraryEntity? foreignLibrary =
|
||||
_env.lookupLibrary(Uris.dart__foreign_helper);
|
||||
_env.lookupLibrary(Uris.dartForeignHelper);
|
||||
|
||||
/// The dart:_rti library.
|
||||
late final LibraryEntity rtiLibrary =
|
||||
_env.lookupLibrary(Uris.dart__rti, required: true)!;
|
||||
_env.lookupLibrary(Uris.dartRti, required: true)!;
|
||||
|
||||
/// The dart:_internal library.
|
||||
late final LibraryEntity internalLibrary =
|
||||
_env.lookupLibrary(Uris.dart__internal, required: true)!;
|
||||
_env.lookupLibrary(Uris.dartInternal, required: true)!;
|
||||
|
||||
/// The dart:js_util library.
|
||||
late final LibraryEntity? dartJsUtilLibrary =
|
||||
_env.lookupLibrary(Uris.dart_js_util);
|
||||
_env.lookupLibrary(Uris.dartJSUtil);
|
||||
|
||||
/// The package:js library.
|
||||
late final LibraryEntity? packageJsLibrary =
|
||||
_env.lookupLibrary(Uris.package_js);
|
||||
_env.lookupLibrary(Uris.packageJS);
|
||||
|
||||
/// The dart:_js_annotations library.
|
||||
late final LibraryEntity? dartJsAnnotationsLibrary =
|
||||
_env.lookupLibrary(Uris.dart__js_annotations);
|
||||
_env.lookupLibrary(Uris.dartJSAnnotations);
|
||||
|
||||
/// The dart:js_interop library.
|
||||
late final LibraryEntity? dartJsInteropLibrary =
|
||||
_env.lookupLibrary(Uris.dart__js_interop);
|
||||
_env.lookupLibrary(Uris.dartJSInterop);
|
||||
|
||||
/// The `NativeTypedData` class from dart:typed_data.
|
||||
ClassEntity get typedDataClass =>
|
||||
|
||||
@@ -159,7 +159,7 @@ class Selectors {
|
||||
///
|
||||
/// These objects are shared between different runs in batch-mode and must
|
||||
/// thus remain in the [Selector.canonicalizedValues] map.
|
||||
static final List<Selector> ALL = <Selector>[
|
||||
static final List<Selector> all = <Selector>[
|
||||
cancel,
|
||||
current,
|
||||
iterator,
|
||||
@@ -189,94 +189,93 @@ class Selectors {
|
||||
/// [Uri]s commonly used.
|
||||
class Uris {
|
||||
/// The URI for 'dart:async'.
|
||||
static final Uri dart_async = Uri(scheme: 'dart', path: 'async');
|
||||
static final Uri dartAsync = Uri(scheme: 'dart', path: 'async');
|
||||
|
||||
/// The URI for 'dart:collection'.
|
||||
static final Uri dart_collection = Uri(scheme: 'dart', path: 'collection');
|
||||
static final Uri dartCollection = Uri(scheme: 'dart', path: 'collection');
|
||||
|
||||
/// The URI for 'dart:core'.
|
||||
static final Uri dart_core = Uri(scheme: 'dart', path: 'core');
|
||||
static final Uri dartCore = Uri(scheme: 'dart', path: 'core');
|
||||
|
||||
/// The URI for 'dart:html'.
|
||||
static final Uri dart_html = Uri(scheme: 'dart', path: 'html');
|
||||
static final Uri dartHtml = Uri(scheme: 'dart', path: 'html');
|
||||
|
||||
/// The URI for 'dart:html_common'.
|
||||
static final Uri dart_html_common = Uri(scheme: 'dart', path: 'html_common');
|
||||
static final Uri dartHtmlCommon = Uri(scheme: 'dart', path: 'html_common');
|
||||
|
||||
/// The URI for 'dart:indexed_db'.
|
||||
static final Uri dart_indexed_db = Uri(scheme: 'dart', path: 'indexed_db');
|
||||
static final Uri dartIndexedDB = Uri(scheme: 'dart', path: 'indexed_db');
|
||||
|
||||
/// The URI for 'dart:isolate'.
|
||||
static final Uri dart_isolate = Uri(scheme: 'dart', path: 'isolate');
|
||||
static final Uri dartIsolate = Uri(scheme: 'dart', path: 'isolate');
|
||||
|
||||
/// The URI for 'dart:math'.
|
||||
static final Uri dart_math = Uri(scheme: 'dart', path: 'math');
|
||||
static final Uri dartMath = Uri(scheme: 'dart', path: 'math');
|
||||
|
||||
/// The URI for 'dart:mirrors'.
|
||||
static final Uri dart_mirrors = Uri(scheme: 'dart', path: 'mirrors');
|
||||
static final Uri dartMirrors = Uri(scheme: 'dart', path: 'mirrors');
|
||||
|
||||
/// The URI for 'dart:_internal'.
|
||||
static final Uri dart__internal = Uri(scheme: 'dart', path: '_internal');
|
||||
static final Uri dartInternal = Uri(scheme: 'dart', path: '_internal');
|
||||
|
||||
/// The URI for 'dart:_native_typed_data'.
|
||||
static final Uri dart__native_typed_data =
|
||||
static final Uri dartNativeTypedData =
|
||||
Uri(scheme: 'dart', path: '_native_typed_data');
|
||||
|
||||
/// The URI for 'dart:typed_data'.
|
||||
static final Uri dart_typed_data = Uri(scheme: 'dart', path: 'typed_data');
|
||||
static final Uri dartTypedData = Uri(scheme: 'dart', path: 'typed_data');
|
||||
|
||||
/// The URI for 'dart:svg'.
|
||||
static final Uri dart_svg = Uri(scheme: 'dart', path: 'svg');
|
||||
static final Uri dartSvg = Uri(scheme: 'dart', path: 'svg');
|
||||
|
||||
/// The URI for 'dart:web_audio'.
|
||||
static final Uri dart_web_audio = Uri(scheme: 'dart', path: 'web_audio');
|
||||
static final Uri dartWebAudio = Uri(scheme: 'dart', path: 'web_audio');
|
||||
|
||||
/// The URI for 'dart:web_gl'.
|
||||
static final Uri dart_web_gl = Uri(scheme: 'dart', path: 'web_gl');
|
||||
static final Uri dartWebGL = Uri(scheme: 'dart', path: 'web_gl');
|
||||
|
||||
/// The URI for 'dart:_js_helper'.
|
||||
static final Uri dart__js_helper = Uri(scheme: 'dart', path: '_js_helper');
|
||||
static final Uri dartJSHelper = Uri(scheme: 'dart', path: '_js_helper');
|
||||
|
||||
/// The URI for 'dart:_late_helper'.
|
||||
static final Uri dart__late_helper =
|
||||
Uri(scheme: 'dart', path: '_late_helper');
|
||||
static final Uri dartLateHelper = Uri(scheme: 'dart', path: '_late_helper');
|
||||
|
||||
/// The URI for 'dart:_rti'.
|
||||
static final Uri dart__rti = Uri(scheme: 'dart', path: '_rti');
|
||||
static final Uri dartRti = Uri(scheme: 'dart', path: '_rti');
|
||||
|
||||
/// The URI for 'dart:_interceptors'.
|
||||
static final Uri dart__interceptors =
|
||||
static final Uri dartInterceptors =
|
||||
Uri(scheme: 'dart', path: '_interceptors');
|
||||
|
||||
/// The URI for 'dart:_foreign_helper'.
|
||||
static final Uri dart__foreign_helper =
|
||||
static final Uri dartForeignHelper =
|
||||
Uri(scheme: 'dart', path: '_foreign_helper');
|
||||
|
||||
/// The URI for 'dart:_js_names'.
|
||||
static final Uri dart__js_names = Uri(scheme: 'dart', path: '_js_names');
|
||||
static final Uri dartJSNames = Uri(scheme: 'dart', path: '_js_names');
|
||||
|
||||
/// The URI for 'dart:_js_embedded_names'.
|
||||
static final Uri dart__js_embedded_names =
|
||||
static final Uri dartJSEmbeddedNames =
|
||||
Uri(scheme: 'dart', path: '_js_embedded_names');
|
||||
|
||||
/// The URI for 'dart:_js_shared_embedded_names'.
|
||||
static final Uri dart__js_shared_embedded_names =
|
||||
static final Uri dartJSSharedEmbeddedNames =
|
||||
Uri(scheme: 'dart', path: '_js_shared_embedded_names');
|
||||
|
||||
/// The URI for 'dart:js_util'.
|
||||
static final Uri dart_js_util = Uri(scheme: 'dart', path: 'js_util');
|
||||
static final Uri dartJSUtil = Uri(scheme: 'dart', path: 'js_util');
|
||||
|
||||
/// The URI for 'package:js'.
|
||||
static final Uri package_js = Uri(scheme: 'package', path: 'js/js.dart');
|
||||
static final Uri packageJS = Uri(scheme: 'package', path: 'js/js.dart');
|
||||
|
||||
/// The URI for 'dart:_js_annotations'.
|
||||
static final Uri dart__js_annotations =
|
||||
static final Uri dartJSAnnotations =
|
||||
Uri(scheme: 'dart', path: '_js_annotations');
|
||||
|
||||
/// The URI for 'dart:js_interop'.
|
||||
static final Uri dart__js_interop = Uri(scheme: 'dart', path: 'js_interop');
|
||||
static final Uri dartJSInterop = Uri(scheme: 'dart', path: 'js_interop');
|
||||
|
||||
/// The URI for 'package:meta/dart2js.dart'.
|
||||
static final Uri package_meta_dart2js =
|
||||
static final Uri packageMetaDart2js =
|
||||
Uri(scheme: 'package', path: 'meta/dart2js.dart');
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
/// number may have a lot more variability depending on system conditions.
|
||||
/// Our goal with this number is not so much to be exact, but to have a good
|
||||
/// metric we can track overtime and use to detect improvements and regressions.
|
||||
library;
|
||||
|
||||
import 'dart:developer';
|
||||
import 'package:vm_service/vm_service_io.dart' as vm_service_io;
|
||||
|
||||
|
||||
@@ -245,9 +245,13 @@ class Measurer {
|
||||
final bool enableTaskMeasurements;
|
||||
|
||||
static int _hashCodeGenerator = 197;
|
||||
|
||||
@override
|
||||
final int hashCode = _hashCodeGenerator++;
|
||||
|
||||
@override
|
||||
bool operator ==(other) => identical(this, other);
|
||||
|
||||
Measurer({this.enableTaskMeasurements = false});
|
||||
|
||||
/// The currently running task, that is, the task whose [Stopwatch] is
|
||||
|
||||
@@ -328,7 +328,7 @@ class Compiler {
|
||||
StaticUse.clearCache();
|
||||
|
||||
// The selector objects held in static fields must remain canonical.
|
||||
for (Selector selector in Selectors.ALL) {
|
||||
for (Selector selector in Selectors.all) {
|
||||
Selector.canonicalizedValues
|
||||
.putIfAbsent(selector.hashCode, () => <Selector>[])
|
||||
.add(selector);
|
||||
|
||||
@@ -30,7 +30,7 @@ const String OUTPUT_LANGUAGE_DART = 'Dart';
|
||||
/// an aid in reproducing bug reports.
|
||||
///
|
||||
/// The actual string is rewritten by a wrapper script when included in the sdk.
|
||||
String? BUILD_ID;
|
||||
String? buildID;
|
||||
|
||||
/// The data passed to the [HandleOption] callback is either a single
|
||||
/// string argument, or the arguments iterator for multiple arguments
|
||||
@@ -165,8 +165,8 @@ Future<api.CompilationResult> compile(List<String> argv,
|
||||
void passThrough(String argument) => options.add(argument);
|
||||
void ignoreOption(String argument) {}
|
||||
|
||||
if (BUILD_ID != null) {
|
||||
passThrough("--build-id=$BUILD_ID");
|
||||
if (buildID != null) {
|
||||
passThrough("--build-id=$buildID");
|
||||
}
|
||||
|
||||
Uri extractResolvedFileUri(String argument) {
|
||||
@@ -1177,7 +1177,7 @@ be removed in a future version:
|
||||
|
||||
void helpAndExit(bool wantHelp, bool wantVersion, bool verbose) {
|
||||
if (wantVersion) {
|
||||
var version = (BUILD_ID == null) ? '<non-SDK build>' : BUILD_ID;
|
||||
var version = (buildID == null) ? '<non-SDK build>' : buildID;
|
||||
print('Dart-to-JavaScript compiler (dart2js) version: $version');
|
||||
}
|
||||
if (wantHelp) {
|
||||
@@ -1212,14 +1212,14 @@ Future<void> main(List<String> arguments) async {
|
||||
// file and expanding them into the resulting argument list.
|
||||
//
|
||||
// TODO: Remove when internal tooling targets bazelMain instead of this.
|
||||
if (arguments.length > 0 && arguments.last.startsWith('@')) {
|
||||
if (arguments.isNotEmpty && arguments.last.startsWith('@')) {
|
||||
var extra = _readLines(arguments.last.substring(1));
|
||||
arguments = arguments.take(arguments.length - 1).followedBy(extra).toList();
|
||||
}
|
||||
|
||||
// Since the sdk/bin/dart2js script adds its own arguments in front of
|
||||
// user-supplied arguments we search for '--batch' at the end of the list.
|
||||
if (arguments.length > 0 && arguments.last == "--batch") {
|
||||
if (arguments.isNotEmpty && arguments.last == "--batch") {
|
||||
batchMain(arguments.sublist(0, arguments.length - 1));
|
||||
return;
|
||||
}
|
||||
@@ -1227,7 +1227,7 @@ Future<void> main(List<String> arguments) async {
|
||||
}
|
||||
|
||||
Future<String?> bazelMain(List<String> arguments) async {
|
||||
if (arguments.length > 0 && arguments.last.startsWith('@')) {
|
||||
if (arguments.isNotEmpty && arguments.last.startsWith('@')) {
|
||||
var extra = _readLines(arguments.last.substring(1));
|
||||
arguments = arguments.take(arguments.length - 1).followedBy(extra).toList();
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ class MemberEntityData extends EntityData<MemberEntity> {
|
||||
|
||||
class LocalFunctionEntityData extends EntityData<Local> {
|
||||
@override
|
||||
void accept(EntityDataVisitor) {}
|
||||
void accept(EntityDataVisitor _) {}
|
||||
|
||||
// Note: local functions are not updated recursively because the
|
||||
// dependencies are already visited as dependencies of the enclosing member.
|
||||
|
||||
@@ -407,8 +407,8 @@ class ImportDescription {
|
||||
|
||||
/// Returns the filename for the output-unit named [name].
|
||||
///
|
||||
/// The filename is of the form "<main output file>_<name>.part.js".
|
||||
/// If [addExtension] is false, the ".part.js" suffix is left out.
|
||||
/// The filename is of the form `<main output file>_<name>.part.js`.
|
||||
/// If [addExtension] is false, the `.part.js` suffix is left out.
|
||||
String deferredPartFileName(CompilerOptions options, String name,
|
||||
{bool addExtension = true}) {
|
||||
assert(name != "");
|
||||
|
||||
@@ -11,12 +11,12 @@ import 'spannable.dart';
|
||||
///
|
||||
/// This flag is automatically set to true if helper methods like, [debugPrint],
|
||||
/// [debugWrapPrint], [trace], and [reportHere] are called.
|
||||
bool DEBUG_MODE = false;
|
||||
bool debugMode = false;
|
||||
|
||||
/// Assert that [DEBUG_MODE] is `true` and provide [message] as part of the
|
||||
/// Assert that [debugMode] is `true` and provide [message] as part of the
|
||||
/// error message.
|
||||
void assertDebugMode(String message) {
|
||||
assert(DEBUG_MODE,
|
||||
assert(debugMode,
|
||||
failedAt(NO_LOCATION_SPANNABLE, 'Debug mode is not enabled: $message'));
|
||||
}
|
||||
|
||||
|
||||
@@ -85,8 +85,8 @@ class DumpInfoJsAstRegistry {
|
||||
|
||||
void registerConstantAst(ConstantValue constant, jsAst.Node code) {
|
||||
if (_disabled) return;
|
||||
assert(!_constantRegistry.containsKey(constant) ||
|
||||
_constantRegistry[constant] == code);
|
||||
assert(!_constantRegistry.containsValue(constant) ||
|
||||
_constantRegistry[code] == constant);
|
||||
_constantRegistry[code] = constant;
|
||||
}
|
||||
|
||||
@@ -854,8 +854,9 @@ class KernelInfoCollector {
|
||||
}
|
||||
|
||||
ClassInfo? visitClass(ir.Class clazz, {required ClassEntity classEntity}) {
|
||||
if (state.entityToInfo[classEntity] != null)
|
||||
if (state.entityToInfo[classEntity] != null) {
|
||||
return state.entityToInfo[classEntity] as ClassInfo?;
|
||||
}
|
||||
|
||||
final supers = <ClassInfo>[];
|
||||
clazz.supers.forEach((supertype) {
|
||||
@@ -979,10 +980,10 @@ class KernelInfoCollector {
|
||||
type: functionType.toStringInternal());
|
||||
|
||||
final functionParent = function.parent;
|
||||
if (functionParent is ir.Member)
|
||||
if (functionParent is ir.Member) {
|
||||
_addClosureInfo(info, functionParent,
|
||||
libraryEntity: functionEntity.library, memberEntity: functionEntity);
|
||||
else {
|
||||
} else {
|
||||
// This branch is only reached when function is a 'call' method.
|
||||
// TODO(markzipan): Ensure call methods never have children.
|
||||
info.closures = [];
|
||||
@@ -1349,7 +1350,7 @@ class DumpInfoAnnotator {
|
||||
kFunctionInfos.length <= 1,
|
||||
'Ambiguous function resolution. '
|
||||
'Expected single or none, found $kFunctionInfos');
|
||||
if (kFunctionInfos.length == 0) return null;
|
||||
if (kFunctionInfos.isEmpty) return null;
|
||||
final kFunctionInfo = kFunctionInfos.first;
|
||||
kernelInfo.state.entityToInfo[function] = kFunctionInfo;
|
||||
|
||||
@@ -1861,8 +1862,9 @@ class LocalFunctionInfoCollector extends ir.RecursiveVisitor {
|
||||
|
||||
@override
|
||||
void visitLocalFunctionInvocation(ir.LocalFunctionInvocation node) {
|
||||
if (localFunctions[node.localFunction] == null)
|
||||
if (localFunctions[node.localFunction] == null) {
|
||||
visitFunctionDeclaration(node.localFunction);
|
||||
}
|
||||
localFunctions[node.localFunction]!.isInvoked = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,8 +156,9 @@ String? constructOperatorNameOrNull(String op, bool isUnary) {
|
||||
|
||||
String constructOperatorName(String op, bool isUnary) {
|
||||
String? operatorName = constructOperatorNameOrNull(op, isUnary);
|
||||
if (operatorName == null)
|
||||
if (operatorName == null) {
|
||||
throw 'Unhandled operator: $op';
|
||||
else
|
||||
} else {
|
||||
return operatorName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ abstract class Name {
|
||||
Uri? get uri;
|
||||
|
||||
/// Returns `true` when [s] is private if used as an identifier.
|
||||
static bool isPrivateName(String s) => !s.isEmpty && s.codeUnitAt(0) == $_;
|
||||
static bool isPrivateName(String s) => s.isNotEmpty && s.codeUnitAt(0) == $_;
|
||||
|
||||
/// Returns `true` when [s] is public if used as an identifier.
|
||||
static bool isPublicName(String s) => !isPrivateName(s);
|
||||
|
||||
@@ -17,12 +17,12 @@ import 'entities.dart';
|
||||
/// This hierarchy is a super hierarchy of the use-case specific hierarchies
|
||||
/// used in different parts of the compiler. This hierarchy abstracts details
|
||||
/// not generally needed or required for the Dart type hierarchy. For instance,
|
||||
/// the hierarchy in 'resolution_types.dart' has properties supporting lazy
|
||||
/// computation (like computeAlias) and distinctions between 'Foo' and
|
||||
/// 'Foo<dynamic>', features that are not needed for code generation and not
|
||||
/// the hierarchy in `resolution_types.dart` has properties supporting lazy
|
||||
/// computation (like computeAlias) and distinctions between `Foo` and
|
||||
/// `Foo<dynamic>`, features that are not needed for code generation and not
|
||||
/// supported from kernel.
|
||||
///
|
||||
/// Current only 'resolution_types.dart' implement this hierarchy but when the
|
||||
/// Current only `resolution_types.dart` implement this hierarchy but when the
|
||||
/// compiler moves to use [Entity] instead of [Element] this hierarchy can be
|
||||
/// implemented directly but other entity systems, for instance based directly
|
||||
/// on kernel ir without the need for [Element].
|
||||
@@ -348,12 +348,11 @@ class InterfaceType extends DartType {
|
||||
|
||||
@override
|
||||
bool get isObject =>
|
||||
element.name == 'Object' &&
|
||||
element.library.canonicalUri == Uris.dart_core;
|
||||
element.name == 'Object' && element.library.canonicalUri == Uris.dartCore;
|
||||
|
||||
@override
|
||||
bool get isNull =>
|
||||
element.name == 'Null' && element.library.canonicalUri == Uris.dart_core;
|
||||
element.name == 'Null' && element.library.canonicalUri == Uris.dartCore;
|
||||
|
||||
@override
|
||||
bool get containsTypeVariables =>
|
||||
@@ -515,7 +514,7 @@ class TypeVariableType extends DartType {
|
||||
/// A type variable declared on a function type.
|
||||
///
|
||||
/// For instance `T` in
|
||||
/// void Function<T>(T t)
|
||||
/// `void Function<T>(T t)`
|
||||
///
|
||||
/// Such a type variable is different from a [TypeVariableType] because it
|
||||
/// doesn't have a unique identity; is equal to any other
|
||||
@@ -554,6 +553,9 @@ class FunctionTypeVariable extends DartType {
|
||||
@override
|
||||
int get hashCode => index * 113; // ignore bound which can have cycles.
|
||||
|
||||
@override
|
||||
bool operator ==(other) => identical(this, other);
|
||||
|
||||
@override
|
||||
bool _equals(DartType other, _Assumptions? assumptions) {
|
||||
if (identical(this, other)) return true;
|
||||
@@ -1074,7 +1076,9 @@ class _LegacyErasureVisitor extends DartTypeVisitor<DartType, Null> {
|
||||
identical(parameterTypes, type.parameterTypes) &&
|
||||
identical(optionalParameterTypes, type.optionalParameterTypes) &&
|
||||
identical(namedParameterTypes, type.namedParameterTypes) &&
|
||||
erasableTypeVariables.isEmpty) return type;
|
||||
erasableTypeVariables.isEmpty) {
|
||||
return type;
|
||||
}
|
||||
|
||||
// TODO(48820): Can we avoid the cast?
|
||||
return _dartTypes.subst(
|
||||
@@ -2025,7 +2029,9 @@ abstract class DartTypes {
|
||||
if (env != null &&
|
||||
s is FunctionTypeVariable &&
|
||||
t is FunctionTypeVariable &&
|
||||
env.isAssumed(s, t)) return true;
|
||||
env.isAssumed(s, t)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (s is AnyType) return true;
|
||||
|
||||
@@ -2221,8 +2227,9 @@ abstract class DartTypes {
|
||||
!useLegacySubtyping && tRequiredNamed.contains(tName);
|
||||
if (sIsRequired && !tIsRequired) return false;
|
||||
if (!_isSubtype(
|
||||
tNamedTypes[tIndex], sNamedTypes[sIndex - 1], env))
|
||||
tNamedTypes[tIndex], sNamedTypes[sIndex - 1], env)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2261,7 +2268,9 @@ abstract class DartTypes {
|
||||
break;
|
||||
case Variance.invariant:
|
||||
if (!_isSubtype(sArgs[i], tArgs[i], env) ||
|
||||
!_isSubtype(tArgs[i], sArgs[i], env)) return false;
|
||||
!_isSubtype(tArgs[i], sArgs[i], env)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1350,7 +1350,7 @@ class KernelTypeGraphBuilder extends ir.VisitorDefault<TypeInformation?>
|
||||
/// Returns `true` for constructors of typed arrays.
|
||||
bool _isConstructorOfTypedArraySubclass(ConstructorEntity constructor) {
|
||||
ClassEntity cls = constructor.enclosingClass;
|
||||
return cls.library.canonicalUri == Uris.dart__native_typed_data &&
|
||||
return cls.library.canonicalUri == Uris.dartNativeTypedData &&
|
||||
_closedWorld.nativeData.isNativeClass(cls) &&
|
||||
_closedWorld.classHierarchy
|
||||
.isSubtypeOf(cls, _closedWorld.commonElements.typedDataClass) &&
|
||||
|
||||
@@ -8,5 +8,5 @@ library compiler.src.inferrer.debug;
|
||||
const bool VERBOSE = false;
|
||||
const bool PRINT_SUMMARY = false;
|
||||
const bool ANOMALY_WARN = false;
|
||||
bool PRINT_GRAPH = false;
|
||||
bool PRINT_GRAPH_ALL_NODES = false; // Include useless nodes?
|
||||
bool printGraph = false;
|
||||
bool printGraphAllNodes = false; // Include useless nodes?
|
||||
|
||||
@@ -133,7 +133,7 @@ class InferrerEngine {
|
||||
memberHierarchyBuilder = MemberHierarchyBuilder(closedWorld),
|
||||
// Ensure `_MAX_CHANGE_COUNT` conforms to TypeInformation flag encoding.
|
||||
assert(_MAX_CHANGE_COUNT.bitLength <
|
||||
64 - TypeInformation.NUM_TYPE_INFO_FLAGS);
|
||||
64 - TypeInformation.numTypeInfoFlags);
|
||||
|
||||
/// Applies [f] to all elements in the universe that match [selector] and
|
||||
/// [mask]. If [f] returns false, aborts the iteration.
|
||||
@@ -340,8 +340,7 @@ class InferrerEngine {
|
||||
_initMemberHierarchy();
|
||||
|
||||
metrics.analyze.measure(_analyzeAllElements);
|
||||
final dump =
|
||||
debug.PRINT_GRAPH ? TypeGraphDump(_compilerOutput, this) : null;
|
||||
final dump = debug.printGraph ? TypeGraphDump(_compilerOutput, this) : null;
|
||||
|
||||
dump?.beforeAnalysis();
|
||||
_buildWorkQueue();
|
||||
|
||||
@@ -161,7 +161,7 @@ abstract class TracerVisitor implements TypeInformationVisitor<void> {
|
||||
// Collect the [TypeInformation] where the list can flow in,
|
||||
// as well as the operations done on all these [TypeInformation]s.
|
||||
addNewEscapeInformation(tracedType);
|
||||
while (!workList.isEmpty) {
|
||||
while (workList.isNotEmpty) {
|
||||
final user = currentUser = workList.removeLast();
|
||||
if (_wouldBeTooManyUsers(user.users)) {
|
||||
bailout('Too many users');
|
||||
@@ -171,16 +171,16 @@ abstract class TracerVisitor implements TypeInformationVisitor<void> {
|
||||
analyzedElements.add(info.owner);
|
||||
info.accept(this);
|
||||
}
|
||||
while (!listsToAnalyze.isEmpty) {
|
||||
while (listsToAnalyze.isNotEmpty) {
|
||||
analyzeStoredIntoList(listsToAnalyze.removeLast());
|
||||
}
|
||||
while (setsToAnalyze.isNotEmpty) {
|
||||
analyzeStoredIntoSet(setsToAnalyze.removeLast());
|
||||
}
|
||||
while (!mapsToAnalyze.isEmpty) {
|
||||
while (mapsToAnalyze.isNotEmpty) {
|
||||
analyzeStoredIntoMap(mapsToAnalyze.removeLast());
|
||||
}
|
||||
while (!recordsToAnalyze.isEmpty) {
|
||||
while (recordsToAnalyze.isNotEmpty) {
|
||||
analyzeStoredIntoRecord(recordsToAnalyze.removeLast());
|
||||
}
|
||||
if (!continueAnalyzing) break;
|
||||
|
||||
@@ -307,8 +307,9 @@ class PowersetBitsDomain {
|
||||
AbstractBool isExact(int value) => AbstractBool.Maybe;
|
||||
|
||||
AbstractBool isEmpty(int value) {
|
||||
if (value & interceptorDomainMask == powersetBottom)
|
||||
if (value & interceptorDomainMask == powersetBottom) {
|
||||
return AbstractBool.True;
|
||||
}
|
||||
if (value & boolNullOtherMask == powersetBottom) return AbstractBool.True;
|
||||
if (isPrecise(value)) return AbstractBool.False;
|
||||
return AbstractBool.Maybe;
|
||||
|
||||
@@ -46,7 +46,7 @@ class TypeGraphDump {
|
||||
void beforeAnalysis() {
|
||||
for (TypeInformation node in inferrer.types.allTypes) {
|
||||
Set<TypeInformation> copy = node.inputs.toSet();
|
||||
if (!copy.isEmpty) {
|
||||
if (copy.isNotEmpty) {
|
||||
assignmentsBeforeAnalysis[node] = copy;
|
||||
}
|
||||
}
|
||||
@@ -56,7 +56,7 @@ class TypeGraphDump {
|
||||
void beforeTracing() {
|
||||
for (TypeInformation node in inferrer.types.allTypes) {
|
||||
Set<TypeInformation> copy = node.inputs.toSet();
|
||||
if (!copy.isEmpty) {
|
||||
if (copy.isNotEmpty) {
|
||||
assignmentsBeforeTracing[node] = copy;
|
||||
}
|
||||
}
|
||||
@@ -310,7 +310,7 @@ class _GraphGenerator extends TypeInformationVisitor<void> {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (PRINT_GRAPH_ALL_NODES) {
|
||||
if (printGraphAllNodes) {
|
||||
for (TypeInformation user in node.users) {
|
||||
if (!isExternal(user)) {
|
||||
visit(user);
|
||||
@@ -322,7 +322,7 @@ class _GraphGenerator extends TypeInformationVisitor<void> {
|
||||
@override
|
||||
void visitNarrowTypeInformation(NarrowTypeInformation info) {
|
||||
// Omit unused Narrows.
|
||||
if (!PRINT_GRAPH_ALL_NODES && info.users.isEmpty) return;
|
||||
if (!printGraphAllNodes && info.users.isEmpty) return;
|
||||
addNode(info, 'Narrow\n${formatType(info.typeAnnotation)}',
|
||||
color: narrowColor);
|
||||
}
|
||||
@@ -330,7 +330,7 @@ class _GraphGenerator extends TypeInformationVisitor<void> {
|
||||
@override
|
||||
void visitPhiElementTypeInformation(PhiElementTypeInformation info) {
|
||||
// Omit unused Phis.
|
||||
if (!PRINT_GRAPH_ALL_NODES && info.users.isEmpty) return;
|
||||
if (!printGraphAllNodes && info.users.isEmpty) return;
|
||||
addNode(info, 'Phi ${info.variable?.name ?? ''}', color: phiColor);
|
||||
}
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ enum _Flag {
|
||||
/// changes.
|
||||
abstract class TypeInformation {
|
||||
// This will be treated as effectively constant by the VM.
|
||||
static final int NUM_TYPE_INFO_FLAGS = _Flag.values.length;
|
||||
static final int numTypeInfoFlags = _Flag.values.length;
|
||||
|
||||
Set<TypeInformation> users;
|
||||
ParameterInputs _inputs;
|
||||
@@ -117,9 +117,9 @@ abstract class TypeInformation {
|
||||
/// We abandon inference in certain cases (complex cyclic flow, native
|
||||
/// behaviours, etc.). In some case, we might resume inference in the
|
||||
/// closure tracer, which is handled by checking whether [inputs] has
|
||||
/// been set to [STOP_TRACKING_INPUTS_MARKER].
|
||||
/// been set to [stopTrackingInputsMarker].
|
||||
bool get abandonInferencing => _flags.contains(_Flag.abandonInferencing);
|
||||
bool get mightResume => !identical(inputs, STOP_TRACKING_INPUTS_MARKER);
|
||||
bool get mightResume => !identical(inputs, stopTrackingInputsMarker);
|
||||
|
||||
/// Whether this [TypeInformation] is currently in the inferrer's
|
||||
/// work queue.
|
||||
@@ -160,13 +160,13 @@ abstract class TypeInformation {
|
||||
EnumSet<_Flag> _flags = EnumSet.empty();
|
||||
|
||||
/// Number of times this [TypeInformation] has changed type.
|
||||
int get refineCount => _flags.mask.bits >> NUM_TYPE_INFO_FLAGS;
|
||||
int get refineCount => _flags.mask.bits >> numTypeInfoFlags;
|
||||
|
||||
void incrementRefineCount() => _flags =
|
||||
EnumSet.fromRawBits(_flags.mask.bits + (1 << NUM_TYPE_INFO_FLAGS));
|
||||
void incrementRefineCount() =>
|
||||
_flags = EnumSet.fromRawBits(_flags.mask.bits + (1 << numTypeInfoFlags));
|
||||
|
||||
void clearRefineCount() => _flags =
|
||||
EnumSet.fromRawBits(_flags.mask.bits & ((1 << NUM_TYPE_INFO_FLAGS) - 1));
|
||||
EnumSet.fromRawBits(_flags.mask.bits & ((1 << numTypeInfoFlags) - 1));
|
||||
|
||||
void addUser(TypeInformation user) {
|
||||
assert(!user.isConcrete);
|
||||
@@ -184,11 +184,10 @@ abstract class TypeInformation {
|
||||
|
||||
// The below is not a compile time constant to make it differentiable
|
||||
// from other empty lists of [TypeInformation].
|
||||
static final STOP_TRACKING_INPUTS_MARKER =
|
||||
_BasicParameterInputs(List.empty());
|
||||
static final stopTrackingInputsMarker = _BasicParameterInputs(List.empty());
|
||||
|
||||
bool areInputsTracked() {
|
||||
return inputs != STOP_TRACKING_INPUTS_MARKER;
|
||||
return inputs != stopTrackingInputsMarker;
|
||||
}
|
||||
|
||||
void addInput(TypeInformation input) {
|
||||
@@ -232,13 +231,13 @@ abstract class TypeInformation {
|
||||
// Do not remove [this] as a user of nodes in [inputs],
|
||||
// because our tracing analysis could be interested in tracing
|
||||
// this node.
|
||||
if (clearInputs) _inputs = STOP_TRACKING_INPUTS_MARKER;
|
||||
if (clearInputs) _inputs = stopTrackingInputsMarker;
|
||||
// Do not remove users because our tracing analysis could be
|
||||
// interested in tracing the users of this node.
|
||||
}
|
||||
|
||||
void clear() {
|
||||
_inputs = STOP_TRACKING_INPUTS_MARKER;
|
||||
_inputs = stopTrackingInputsMarker;
|
||||
users = const {};
|
||||
}
|
||||
|
||||
@@ -274,7 +273,7 @@ abstract class TypeInformation {
|
||||
removeAndClearReferences(inferrer);
|
||||
// Do not remove users because the tracing analysis could be interested
|
||||
// in tracing the users of this node.
|
||||
_inputs = STOP_TRACKING_INPUTS_MARKER;
|
||||
_inputs = stopTrackingInputsMarker;
|
||||
_flags = _flags.add(_Flag.abandonInferencing);
|
||||
_flags = _flags.add(_Flag.isStable);
|
||||
}
|
||||
@@ -742,11 +741,6 @@ class FactoryConstructorTypeInformation extends MemberTypeInformation {
|
||||
AbstractValue mask, InferrerEngine inferrer) {
|
||||
return _narrowType(inferrer.abstractValueDomain, mask, _type);
|
||||
}
|
||||
|
||||
@override
|
||||
bool hasStableType(InferrerEngine inferrer) {
|
||||
return super.hasStableType(inferrer);
|
||||
}
|
||||
}
|
||||
|
||||
class GenerativeConstructorTypeInformation extends MemberTypeInformation {
|
||||
@@ -1258,7 +1252,7 @@ class DynamicCallSiteTypeInformation<T extends ir.Node>
|
||||
}
|
||||
if (!selector.isCall && !selector.isOperator) return null;
|
||||
final args = arguments!;
|
||||
if (!args.named.isEmpty) return null;
|
||||
if (args.named.isNotEmpty) return null;
|
||||
if (args.positional.length > 1) return null;
|
||||
|
||||
bool isInt(TypeInformation info) =>
|
||||
@@ -1489,7 +1483,7 @@ class DynamicCallSiteTypeInformation<T extends ir.Node>
|
||||
String toString() => 'Call site $debugName on ${receiver.type} $type';
|
||||
|
||||
@override
|
||||
T accept<T>(TypeInformationVisitor<T> visitor) {
|
||||
S accept<S>(TypeInformationVisitor<S> visitor) {
|
||||
return visitor.visitDynamicCallSiteTypeInformation(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// 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.
|
||||
|
||||
part of masks;
|
||||
part of 'masks.dart';
|
||||
|
||||
/// A [TypeMask] for a specific allocation site of a container (currently only
|
||||
/// List) that will get specialized once the [TypeGraphInferrer] phase finds an
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// 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.
|
||||
|
||||
part of masks;
|
||||
part of 'masks.dart';
|
||||
|
||||
/// A [DictionaryTypeMask] is a [TypeMask] for a specific allocation
|
||||
/// site of a map (currently only internal Map class) that is used as
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// 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.
|
||||
|
||||
part of masks;
|
||||
part of 'masks.dart';
|
||||
|
||||
enum FlatTypeMaskKind { empty, exact, subclass, subtype }
|
||||
|
||||
@@ -293,8 +293,9 @@ class FlatTypeMask extends TypeMask {
|
||||
// TODO(herhut): Add check whether flatOther.base is superclass of
|
||||
// all subclasses of this.base.
|
||||
if (flatOther.isSubclass) {
|
||||
if (isSubtype)
|
||||
if (isSubtype) {
|
||||
return (otherBase == closedWorld.commonElements.objectClass);
|
||||
}
|
||||
return closedWorld.classHierarchy.isSubclassOf(base!, otherBase!);
|
||||
}
|
||||
assert(flatOther.isSubtype);
|
||||
@@ -718,8 +719,9 @@ class FlatTypeMask extends TypeMask {
|
||||
MemberEntity? locateSingleMember(Selector selector, CommonMasks domain) {
|
||||
if (isEmptyOrSpecial) return null;
|
||||
JClosedWorld closedWorld = domain._closedWorld;
|
||||
if (closedWorld.includesClosureCallInDomain(selector, this, domain))
|
||||
if (closedWorld.includesClosureCallInDomain(selector, this, domain)) {
|
||||
return null;
|
||||
}
|
||||
Iterable<MemberEntity> targets =
|
||||
closedWorld.locateMembersInDomain(selector, this, domain);
|
||||
if (targets.length != 1) return null;
|
||||
@@ -742,8 +744,9 @@ class FlatTypeMask extends TypeMask {
|
||||
if (closedWorld.classHierarchy.isSubclassOf(thisBase, enclosing)) {
|
||||
return result;
|
||||
}
|
||||
if (closedWorld.isSubclassOfMixinUseOf(thisBase, enclosing))
|
||||
if (closedWorld.isSubclassOfMixinUseOf(thisBase, enclosing)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// 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.
|
||||
|
||||
part of masks;
|
||||
part of 'masks.dart';
|
||||
|
||||
/// A type mask that wraps another one, and delegates all its
|
||||
/// implementation methods to it.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// 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.
|
||||
|
||||
part of masks;
|
||||
part of 'masks.dart';
|
||||
|
||||
/// A [MapTypeMask] is a [TypeMask] for a specific allocation
|
||||
/// site of a map (currently only internal Map class) that will get specialized
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// 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.
|
||||
|
||||
part of masks;
|
||||
part of 'masks.dart';
|
||||
|
||||
/// A [TypeMask] representing the type of a record or the union of multiple
|
||||
/// records with the same shape.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// 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.
|
||||
|
||||
part of masks;
|
||||
part of 'masks.dart';
|
||||
|
||||
/// A [SetTypeMask] is a [TypeMask] for a specific allocation site of a set
|
||||
/// (currently only the internal Set class) that will get specialized once the
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// 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.
|
||||
|
||||
part of masks;
|
||||
part of 'masks.dart';
|
||||
|
||||
/// An implementation of a [UniverseSelectorConstraints] that is consists if an
|
||||
/// only increasing set of [TypeMask]s, that is, once a mask is added it cannot
|
||||
@@ -395,13 +395,6 @@ abstract class TypeMask implements AbstractValue {
|
||||
bool containsOnlyString(JClosedWorld closedWorld);
|
||||
bool containsOnly(ClassEntity cls);
|
||||
|
||||
/// Compares two [TypeMask] objects for structural equality.
|
||||
///
|
||||
/// Note: This may differ from semantic equality in the set containment sense.
|
||||
/// Use [containsMask] and [isInMask] for that, instead.
|
||||
@override
|
||||
bool operator ==(other);
|
||||
|
||||
/// If this returns `true`, [other] is guaranteed to be a supertype of this
|
||||
/// mask, i.e., this mask is in [other]. However, the inverse does not hold.
|
||||
/// Enable [UnionTypeMask.PERFORM_EXTRA_CONTAINS_CHECK] to be notified of
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// 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.
|
||||
|
||||
part of masks;
|
||||
part of 'masks.dart';
|
||||
|
||||
class UnionTypeMask extends TypeMask {
|
||||
/// Tag used for identifying serialized [UnionTypeMask] objects in a
|
||||
@@ -74,17 +74,19 @@ class UnionTypeMask extends TypeMask {
|
||||
bool isNullable = masks.any((TypeMask mask) => mask.isNullable);
|
||||
bool hasLateSentinel = masks.any((TypeMask mask) => mask.hasLateSentinel);
|
||||
unionOfHelper(masks, disjoint, domain);
|
||||
if (disjoint.isEmpty)
|
||||
if (disjoint.isEmpty) {
|
||||
return isNullable
|
||||
? TypeMask.empty(hasLateSentinel: hasLateSentinel)
|
||||
: TypeMask.nonNullEmpty(hasLateSentinel: hasLateSentinel);
|
||||
}
|
||||
if (disjoint.length > MAX_UNION_LENGTH) {
|
||||
return flatten(disjoint, domain,
|
||||
includeNull: isNullable, includeLateSentinel: hasLateSentinel);
|
||||
}
|
||||
if (disjoint.length == 1)
|
||||
if (disjoint.length == 1) {
|
||||
return disjoint.single.withSpecialValues(
|
||||
isNullable: isNullable, hasLateSentinel: hasLateSentinel);
|
||||
}
|
||||
UnionTypeMask union = UnionTypeMask._compose(
|
||||
disjoint,
|
||||
isNullable: isNullable,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// 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.
|
||||
|
||||
part of masks;
|
||||
part of 'masks.dart';
|
||||
|
||||
class ValueTypeMask extends ForwardingTypeMask {
|
||||
/// Tag used for identifying serialized [ValueTypeMask] objects in a
|
||||
|
||||
@@ -312,11 +312,11 @@ class WrappedAbstractValueDomain with AbstractValueDomain {
|
||||
|
||||
@override
|
||||
AbstractValue unionOfMany(covariant Iterable<AbstractValue> values) {
|
||||
List<AbstractValue> unwrapped_Values = values
|
||||
List<AbstractValue> unwrappedValues = values
|
||||
.map((element) => (element as WrappedAbstractValue)._abstractValue)
|
||||
.toList();
|
||||
return WrappedAbstractValue(
|
||||
_abstractValueDomain.unionOfMany(unwrapped_Values));
|
||||
_abstractValueDomain.unionOfMany(unwrappedValues));
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -115,14 +115,14 @@ class _SourceLocationsImpl implements SourceLocations {
|
||||
assert(name == other.name);
|
||||
if (_closed) throw UnsupportedError('SourceLocations already closed.');
|
||||
int length = codeOutput.length;
|
||||
if (other.markers.length > 0) {
|
||||
if (other.markers.isNotEmpty) {
|
||||
other.markers
|
||||
.forEach((int targetOffset, List<SourceLocation> sourceLocations) {
|
||||
(markers[length + targetOffset] ??= []).addAll(sourceLocations);
|
||||
});
|
||||
}
|
||||
|
||||
if (other.frameMarkers.length > 0) {
|
||||
if (other.frameMarkers.isNotEmpty) {
|
||||
other.frameMarkers.forEach((int targetOffset, List<FrameEntry> frames) {
|
||||
(frameMarkers[length + targetOffset] ??= []).addAll(frames);
|
||||
});
|
||||
|
||||
@@ -145,7 +145,7 @@ class SourceInformationBuilder {
|
||||
null;
|
||||
|
||||
/// Generate [SourceInformation] for the generic [node].
|
||||
@deprecated
|
||||
@Deprecated("Use SourceInformationFactory")
|
||||
SourceInformation? buildGeneric(ir.Node node) => null;
|
||||
|
||||
/// Generate [SourceInformation] for an instantiation of a class using [node]
|
||||
|
||||
@@ -237,7 +237,7 @@ String? _getNativeClassName(ir.Constant constant) {
|
||||
// TODO(johnniwinther): Add an IrCommonElements for these queries; i.e.
|
||||
// `commonElements.isNativeAnnotationClass(constant.classNode)`.
|
||||
if (constant.classNode.name == 'Native' &&
|
||||
constant.classNode.enclosingLibrary.importUri == Uris.dart__js_helper) {
|
||||
constant.classNode.enclosingLibrary.importUri == Uris.dartJSHelper) {
|
||||
if (constant.fieldValues.length == 1) {
|
||||
ir.Constant fieldValue = constant.fieldValues.values.single;
|
||||
String? name;
|
||||
@@ -256,13 +256,13 @@ String? _getNativeClassName(ir.Constant constant) {
|
||||
bool _isNativeMember(ir.Constant constant) {
|
||||
return constant is ir.InstanceConstant &&
|
||||
constant.classNode.name == 'ExternalName' &&
|
||||
constant.classNode.enclosingLibrary.importUri == Uris.dart__internal;
|
||||
constant.classNode.enclosingLibrary.importUri == Uris.dartInternal;
|
||||
}
|
||||
|
||||
String? _getNativeMemberName(ir.Constant constant) {
|
||||
if (constant is ir.InstanceConstant &&
|
||||
constant.classNode.name == 'JSName' &&
|
||||
constant.classNode.enclosingLibrary.importUri == Uris.dart__js_helper) {
|
||||
constant.classNode.enclosingLibrary.importUri == Uris.dartJSHelper) {
|
||||
assert(constant.fieldValues.length == 1);
|
||||
ir.Constant fieldValue = constant.fieldValues.values.single;
|
||||
if (fieldValue is ir.StringConstant) {
|
||||
@@ -275,7 +275,7 @@ String? _getNativeMemberName(ir.Constant constant) {
|
||||
String? _getCreatesAnnotation(ir.Constant constant) {
|
||||
if (constant is ir.InstanceConstant &&
|
||||
constant.classNode.name == 'Creates' &&
|
||||
constant.classNode.enclosingLibrary.importUri == Uris.dart__js_helper) {
|
||||
constant.classNode.enclosingLibrary.importUri == Uris.dartJSHelper) {
|
||||
assert(constant.fieldValues.length == 1);
|
||||
ir.Constant fieldValue = constant.fieldValues.values.single;
|
||||
if (fieldValue is ir.StringConstant) {
|
||||
@@ -288,7 +288,7 @@ String? _getCreatesAnnotation(ir.Constant constant) {
|
||||
String? _getReturnsAnnotation(ir.Constant constant) {
|
||||
if (constant is ir.InstanceConstant &&
|
||||
constant.classNode.name == 'Returns' &&
|
||||
constant.classNode.enclosingLibrary.importUri == Uris.dart__js_helper) {
|
||||
constant.classNode.enclosingLibrary.importUri == Uris.dartJSHelper) {
|
||||
assert(constant.fieldValues.length == 1);
|
||||
ir.Constant fieldValue = constant.fieldValues.values.single;
|
||||
if (fieldValue is ir.StringConstant) {
|
||||
@@ -301,11 +301,11 @@ String? _getReturnsAnnotation(ir.Constant constant) {
|
||||
String? _getJsInteropName(ir.Constant constant) {
|
||||
if (constant is ir.InstanceConstant &&
|
||||
constant.classNode.name == 'JS' &&
|
||||
(constant.classNode.enclosingLibrary.importUri == Uris.package_js ||
|
||||
(constant.classNode.enclosingLibrary.importUri == Uris.packageJS ||
|
||||
constant.classNode.enclosingLibrary.importUri ==
|
||||
Uris.dart__js_annotations ||
|
||||
Uris.dartJSAnnotations ||
|
||||
constant.classNode.enclosingLibrary.importUri ==
|
||||
Uris.dart__js_interop)) {
|
||||
Uris.dartJSInterop)) {
|
||||
assert(constant.fieldValues.length == 1);
|
||||
ir.Constant fieldValue = constant.fieldValues.values.single;
|
||||
if (fieldValue is ir.NullConstant) {
|
||||
@@ -320,17 +320,17 @@ String? _getJsInteropName(ir.Constant constant) {
|
||||
bool _isAnonymousJsInterop(ir.Constant constant) {
|
||||
return constant is ir.InstanceConstant &&
|
||||
constant.classNode.name == '_Anonymous' &&
|
||||
(constant.classNode.enclosingLibrary.importUri == Uris.package_js ||
|
||||
(constant.classNode.enclosingLibrary.importUri == Uris.packageJS ||
|
||||
constant.classNode.enclosingLibrary.importUri ==
|
||||
Uris.dart__js_annotations);
|
||||
Uris.dartJSAnnotations);
|
||||
}
|
||||
|
||||
bool _isStaticInterop(ir.Constant constant) {
|
||||
return constant is ir.InstanceConstant &&
|
||||
constant.classNode.name == '_StaticInterop' &&
|
||||
(constant.classNode.enclosingLibrary.importUri == Uris.package_js ||
|
||||
(constant.classNode.enclosingLibrary.importUri == Uris.packageJS ||
|
||||
constant.classNode.enclosingLibrary.importUri ==
|
||||
Uris.dart__js_annotations);
|
||||
Uris.dartJSAnnotations);
|
||||
}
|
||||
|
||||
class PragmaAnnotationData {
|
||||
@@ -347,6 +347,9 @@ class PragmaAnnotationData {
|
||||
@override
|
||||
String toString() => 'PragmaAnnotationData($name)';
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(suffix, options);
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (identical(this, other)) return true;
|
||||
@@ -360,13 +363,13 @@ PragmaAnnotationData? _getPragmaAnnotation(ir.Constant constant) {
|
||||
ir.InstanceConstant value = constant;
|
||||
ir.Class cls = value.classNode;
|
||||
Uri uri = cls.enclosingLibrary.importUri;
|
||||
if (uri == Uris.package_meta_dart2js) {
|
||||
if (uri == Uris.packageMetaDart2js) {
|
||||
if (cls.name == '_NoInline') {
|
||||
return const PragmaAnnotationData('noInline');
|
||||
} else if (cls.name == '_TryInline') {
|
||||
return const PragmaAnnotationData('tryInline');
|
||||
}
|
||||
} else if (uri == Uris.dart_core && cls.name == 'pragma') {
|
||||
} else if (uri == Uris.dartCore && cls.name == 'pragma') {
|
||||
ir.Constant? nameValue;
|
||||
ir.Constant? optionsValue;
|
||||
value.fieldValues.forEach((ir.Reference reference, ir.Constant fieldValue) {
|
||||
|
||||
@@ -115,8 +115,8 @@ class KernelCapturedScope extends KernelScopeInfo {
|
||||
_empty,
|
||||
null,
|
||||
_empty,
|
||||
Set.of(scope.freeVariables.where(
|
||||
(ir.Node variable) => variable is TypeVariableTypeWithContext)),
|
||||
Set.of(
|
||||
scope.freeVariables.whereType<TypeVariableTypeWithContext>()),
|
||||
scope.freeVariablesForRti,
|
||||
scope.thisUsedAsFreeVariable,
|
||||
scope.thisUsedAsFreeVariableIfNeedsRti,
|
||||
|
||||
@@ -515,7 +515,7 @@ class ImpactBuilder extends ir.RecursiveVisitor implements ImpactRegistry {
|
||||
// additional unnecessary work.
|
||||
final name = node.target.name.text;
|
||||
if (node.target.enclosingClass == null &&
|
||||
node.target.enclosingLibrary.importUri == Uris.dart__foreign_helper &&
|
||||
node.target.enclosingLibrary.importUri == Uris.dartForeignHelper &&
|
||||
getForeignKindFromName(name) != ForeignKind.NONE) {
|
||||
registerForeignStaticInvocationNode(node);
|
||||
}
|
||||
|
||||
@@ -196,7 +196,7 @@ class ScopeModelBuilder extends ir.VisitorDefault<EvaluationComplexity>
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!capturedVariablesForScope.isEmpty) {
|
||||
if (capturedVariablesForScope.isNotEmpty) {
|
||||
assert(_model.scopeInfo != null);
|
||||
KernelScopeInfo from = _model.scopeInfo!;
|
||||
|
||||
|
||||
@@ -437,12 +437,16 @@ abstract class AsyncRewriterBase extends js.NodeVisitor<Object?> {
|
||||
/// temporary.
|
||||
///
|
||||
/// We cannot rewrite `<receiver>.m()` to:
|
||||
///
|
||||
/// temp = <receiver>.m;
|
||||
/// temp();
|
||||
///
|
||||
/// Because this leaves `this` unbound in the call. But because of dart
|
||||
/// evaluation order we can write:
|
||||
///
|
||||
/// temp = <receiver>;
|
||||
/// temp.m();
|
||||
///
|
||||
js.Expression withCallTargetExpression(
|
||||
js.Expression node, js.Expression fn(js.Expression result),
|
||||
{required bool store}) {
|
||||
|
||||
@@ -86,7 +86,7 @@ class SizeEstimator implements NodeVisitor<void> {
|
||||
}
|
||||
|
||||
void out(String s) {
|
||||
if (s.length > 0) {
|
||||
if (s.isNotEmpty) {
|
||||
// We can elide a semicolon in some cases, but for simplicity we
|
||||
// assume a semicolon is needed here.
|
||||
if (pendingSemicolon) {
|
||||
@@ -357,7 +357,7 @@ class SizeEstimator implements NodeVisitor<void> {
|
||||
visitNestedExpression(node.expression, Precedence.expression,
|
||||
newInForInit: false, newAtStatementBegin: false);
|
||||
out(':'); // ':'
|
||||
if (!node.body.statements.isEmpty) {
|
||||
if (node.body.statements.isNotEmpty) {
|
||||
blockOutWithoutBraces(node.body);
|
||||
}
|
||||
}
|
||||
@@ -365,7 +365,7 @@ class SizeEstimator implements NodeVisitor<void> {
|
||||
@override
|
||||
void visitDefault(Default node) {
|
||||
out('default:'); // 'default:'
|
||||
if (!node.body.statements.isEmpty) {
|
||||
if (node.body.statements.isNotEmpty) {
|
||||
blockOutWithoutBraces(node.body);
|
||||
}
|
||||
}
|
||||
@@ -734,7 +734,7 @@ class SizeEstimator implements NodeVisitor<void> {
|
||||
}
|
||||
|
||||
bool isValidJavaScriptId(String field) {
|
||||
if (field.length == 0) return false;
|
||||
if (field.isEmpty) return false;
|
||||
// Ignore the leading and trailing string-delimiter.
|
||||
for (int i = 0; i < field.length; i++) {
|
||||
// TODO(floitsch): allow more characters.
|
||||
|
||||
@@ -223,7 +223,7 @@ class ModularConstantEmitter
|
||||
class ConstantEmitter extends ModularConstantEmitter {
|
||||
// Matches blank lines, comment lines and trailing comments that can't be part
|
||||
// of a string.
|
||||
static final RegExp COMMENT_RE =
|
||||
static final RegExp commentRE =
|
||||
RegExp(r'''^ *(//.*)?\n| *//[^''"\n]*$''', multiLine: true);
|
||||
|
||||
final JCommonElements _commonElements;
|
||||
@@ -488,7 +488,7 @@ class ConstantEmitter extends ModularConstantEmitter {
|
||||
}
|
||||
|
||||
String stripComments(String rawJavaScript) {
|
||||
return rawJavaScript.replaceAll(COMMENT_RE, '');
|
||||
return rawJavaScript.replaceAll(commentRE, '');
|
||||
}
|
||||
|
||||
jsAst.Expression maybeAddListTypeArgumentsNewRti(
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// 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.
|
||||
|
||||
part of js_backend.namer;
|
||||
part of 'namer.dart';
|
||||
|
||||
mixin _MinifiedFieldNamer implements Namer {
|
||||
_FieldNamingRegistry get fieldRegistry;
|
||||
|
||||
@@ -139,7 +139,9 @@ class _Pool {
|
||||
List<_Pool> pools = [];
|
||||
for (var name in names) {
|
||||
int length = name.length;
|
||||
while (pools.length < length) pools.add(_Pool());
|
||||
while (pools.length < length) {
|
||||
pools.add(_Pool());
|
||||
}
|
||||
_Pool pool = pools[length - 1];
|
||||
pool._availableSlots[pool._names.length] = true;
|
||||
pool._names.add(name);
|
||||
@@ -183,7 +185,9 @@ class _Cohort {
|
||||
|
||||
_Cohort? skipEmpty() {
|
||||
_Cohort? cohort = this;
|
||||
while (cohort != null && cohort.remaining == 0) cohort = cohort.next;
|
||||
while (cohort != null && cohort.remaining == 0) {
|
||||
cohort = cohort.next;
|
||||
}
|
||||
return cohort;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// 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.
|
||||
|
||||
part of js_backend.namer;
|
||||
part of 'namer.dart';
|
||||
|
||||
class FrequencyBasedNamer extends Namer
|
||||
with _MinifiedFieldNamer, _MinifiedOneShotInterceptorNamer
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// 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.
|
||||
|
||||
part of js_backend.namer;
|
||||
part of 'namer.dart';
|
||||
|
||||
/// Assigns JavaScript identifiers to Dart variables, class-names and members.
|
||||
class MinifyNamer extends Namer
|
||||
@@ -20,8 +20,8 @@ class MinifyNamer extends Namer
|
||||
@override
|
||||
String get genericInstantiationPrefix => r'$I';
|
||||
|
||||
final ALPHABET_CHARACTERS = 52; // a-zA-Z.
|
||||
final ALPHANUMERIC_CHARACTERS = 62; // a-zA-Z0-9.
|
||||
static const ALPHABET_CHARACTERS = 52; // a-zA-Z.
|
||||
static const ALPHANUMERIC_CHARACTERS = 62; // a-zA-Z0-9.
|
||||
|
||||
/// You can pass an invalid identifier to this and unlike its non-minifying
|
||||
/// counterpart it will never return the proposedName as the new fresh name.
|
||||
|
||||
@@ -17,7 +17,7 @@ import '../common/names.dart' show Identifiers, Names, Selectors;
|
||||
import '../constants/constant_system.dart' as constant_system;
|
||||
import '../constants/values.dart';
|
||||
import '../common/elements.dart' show CommonElements, ElementEnvironment;
|
||||
import '../diagnostics/invariant.dart' show DEBUG_MODE;
|
||||
import '../diagnostics/invariant.dart' show debugMode;
|
||||
import '../elements/entities.dart';
|
||||
import '../elements/entity_utils.dart' as utils;
|
||||
import '../elements/jumps.dart';
|
||||
@@ -97,7 +97,7 @@ part 'namer_names.dart';
|
||||
/// JavaScript property such as `__proto__`.
|
||||
///
|
||||
/// The following annotated names are generated for instance members, where
|
||||
/// <NAME> denotes the disambiguated name.
|
||||
/// `<NAME>` denotes the disambiguated name.
|
||||
///
|
||||
/// 0. The disambiguated name can itself be seen as an annotated name.
|
||||
///
|
||||
@@ -670,7 +670,7 @@ class Namer extends ModularNamer {
|
||||
jsAst.Name? newName = userInstanceMembers[key];
|
||||
if (newName == null) {
|
||||
String proposedName = privateName(originalName);
|
||||
if (!suffixes.isEmpty) {
|
||||
if (suffixes.isNotEmpty) {
|
||||
// In the proposed name, separate the name parts by '$', because the
|
||||
// proposed name must be a valid identifier, but not necessarily unique.
|
||||
proposedName += r'$' + suffixes.join(r'$');
|
||||
@@ -906,15 +906,15 @@ class Namer extends ModularNamer {
|
||||
}
|
||||
// The filename based name can contain all kinds of nasty characters. Make
|
||||
// sure it is an identifier.
|
||||
if (!IDENTIFIER.hasMatch(name)) {
|
||||
if (!identifier.hasMatch(name)) {
|
||||
String replacer(Match match) {
|
||||
String s = match[0]!;
|
||||
if (s == '.') return '_';
|
||||
return s.codeUnitAt(0).toRadixString(16);
|
||||
}
|
||||
|
||||
name = name.replaceAllMapped(NON_IDENTIFIER_CHAR, replacer);
|
||||
if (!IDENTIFIER.hasMatch(name)) {
|
||||
name = name.replaceAllMapped(nonIdentifierChar, replacer);
|
||||
if (!identifier.hasMatch(name)) {
|
||||
// e.g. starts with digit.
|
||||
name = 'lib_$name';
|
||||
}
|
||||
@@ -1206,7 +1206,7 @@ class ConstantNamingVisitor implements ConstantValueVisitor<void, Null> {
|
||||
}
|
||||
|
||||
void add(String fragment) {
|
||||
assert(fragment.length > 0);
|
||||
assert(fragment.isNotEmpty);
|
||||
fragments.add(fragment);
|
||||
length += fragment.length;
|
||||
if (fragments.length > MAX_FRAGMENTS) failed = true;
|
||||
@@ -1216,7 +1216,7 @@ class ConstantNamingVisitor implements ConstantValueVisitor<void, Null> {
|
||||
}
|
||||
|
||||
void addIdentifier(String fragment) {
|
||||
if (fragment.length <= MAX_EXTRA_LENGTH && IDENTIFIER.hasMatch(fragment)) {
|
||||
if (fragment.length <= MAX_EXTRA_LENGTH && identifier.hasMatch(fragment)) {
|
||||
add(fragment);
|
||||
} else {
|
||||
failed = true;
|
||||
@@ -2157,8 +2157,8 @@ String suffixForGetInterceptor(CommonElements commonElements,
|
||||
///
|
||||
/// $<T>$<N>$namedParam1...$namedParam<M>
|
||||
///
|
||||
/// Where <T> is the number of type arguments, <N> is the number of positional
|
||||
/// arguments and <M> is the number of named arguments.
|
||||
/// Where `<T>` is the number of type arguments, `<N>` is the number of
|
||||
/// positional arguments and `<M>` is the number of named arguments.
|
||||
///
|
||||
/// If there are no type arguments the `$<T>` is omitted.
|
||||
///
|
||||
@@ -2602,8 +2602,8 @@ final Set<String> jsReserved = {
|
||||
...reservedPropertySymbols
|
||||
};
|
||||
|
||||
final RegExp IDENTIFIER = RegExp(r'^[A-Za-z_$][A-Za-z0-9_$]*$');
|
||||
final RegExp NON_IDENTIFIER_CHAR = RegExp(r'[^A-Za-z_0-9$]');
|
||||
final RegExp identifier = RegExp(r'^[A-Za-z_$][A-Za-z0-9_$]*$');
|
||||
final RegExp nonIdentifierChar = RegExp(r'[^A-Za-z_0-9$]');
|
||||
const MAX_FRAGMENTS = 5;
|
||||
const MAX_EXTRA_LENGTH = 30;
|
||||
const DEFAULT_TAG_LENGTH = 3;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// 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.
|
||||
|
||||
part of js_backend.namer;
|
||||
part of 'namer.dart';
|
||||
|
||||
abstract class _NamerName extends jsAst.Name {
|
||||
int get _kind;
|
||||
@@ -20,7 +20,7 @@ abstract class _NamerName extends jsAst.Name {
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
if (DEBUG_MODE) {
|
||||
if (debugMode) {
|
||||
return 'Name($key)';
|
||||
}
|
||||
throw UnsupportedError("Cannot convert a name to a string");
|
||||
@@ -223,15 +223,13 @@ class TokenName extends _NamerName implements jsAst.ReferenceCountedAstNode {
|
||||
void markSeen(jsAst.TokenCounter counter) => _rc++;
|
||||
|
||||
@override
|
||||
// ignore: hash_and_equals
|
||||
bool operator ==(Object other) {
|
||||
if (other is _NameReference) return this == other._target;
|
||||
if (identical(this, other)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => super.hashCode;
|
||||
|
||||
void finalize() {
|
||||
assert(
|
||||
!isFinalized,
|
||||
|
||||
@@ -36,6 +36,9 @@ class TypeCheck {
|
||||
|
||||
TypeCheck(this.cls, this.substitution, {this.needsIs = true});
|
||||
|
||||
@override
|
||||
bool operator ==(other) => identical(this, other);
|
||||
|
||||
@override
|
||||
String toString() =>
|
||||
'TypeCheck(cls=$cls,needsIs=$needsIs,substitution=$substitution)';
|
||||
|
||||
@@ -707,11 +707,13 @@ abstract class RuntimeTypesNeed {
|
||||
///
|
||||
/// This is for instance the case for generic classes used in a type test:
|
||||
///
|
||||
/// ```
|
||||
/// class C<T> {}
|
||||
/// main() {
|
||||
/// C<int>() is C<int>;
|
||||
/// C<String>() is C<String>;
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
bool classNeedsTypeArguments(ClassEntity cls);
|
||||
|
||||
@@ -723,11 +725,13 @@ abstract class RuntimeTypesNeed {
|
||||
///
|
||||
/// This is for instance the case for generic methods that use type tests:
|
||||
///
|
||||
/// ```
|
||||
/// method<T>(T t) => t is T;
|
||||
/// main() {
|
||||
/// method<int>(0);
|
||||
/// method<String>('');
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
bool methodNeedsTypeArguments(FunctionEntity method);
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ void _partition(
|
||||
List<_Node> nodes, int minLength, List<String> path, int index) {
|
||||
while (true) {
|
||||
// Handle trivial partitions.
|
||||
if (nodes.length == 0) return;
|
||||
if (nodes.isEmpty) return;
|
||||
if (nodes.length == 1 && path.length >= minLength) {
|
||||
String name = path.join();
|
||||
assert(name.isNotEmpty);
|
||||
@@ -49,7 +49,7 @@ void _partition(
|
||||
|
||||
for (final node in nodes) {
|
||||
String string = node.string;
|
||||
assert(string.length > 0);
|
||||
assert(string.isNotEmpty);
|
||||
if (index < string.length) {
|
||||
int codeUnit = string.codeUnitAt(index);
|
||||
(partition[codeUnit] ??= []).add(node);
|
||||
@@ -63,7 +63,7 @@ void _partition(
|
||||
terminating.assignment = path.join();
|
||||
}
|
||||
|
||||
if (partition.length == 0) return;
|
||||
if (partition.isEmpty) return;
|
||||
|
||||
if (partition.length > 1) {
|
||||
var keys = partition.keys.toList();
|
||||
|
||||
@@ -589,8 +589,8 @@ class _TypeReferenceCollectorVisitor extends js.BaseVisitorVoid {
|
||||
/// interface types with the same name (i.e. from different libraries), or types
|
||||
/// with names that contain underscores or dollar signs. There is also some
|
||||
/// ambiguity in the generated names in the interest of keeping most names
|
||||
/// short, e.g. "FutureOr_int_Function" could be "FutureOr<int> Function()" or
|
||||
/// "FutureOr<int Function()>".
|
||||
/// short, e.g. `"FutureOr_int_Function"` could be `"FutureOr<int> Function()"`
|
||||
/// or `"FutureOr<int Function()>"`.
|
||||
class _RecipeToIdentifier extends DartTypeVisitor<void, Null> {
|
||||
final Map<DartType, int> _backrefs = Map.identity();
|
||||
final List<String> _fragments = [];
|
||||
|
||||
@@ -188,7 +188,7 @@ class ClassStubGenerator {
|
||||
'internalName': js.quoteName(internalName),
|
||||
'type': js.number(type),
|
||||
'arguments': jsAst.ArrayInitializer(
|
||||
parameterNames.map<jsAst.Expression>(js).toList()),
|
||||
parameterNames.map<jsAst.Expression>(js.call).toList()),
|
||||
'namedArguments': jsAst.ArrayInitializer(argNames),
|
||||
'typeArgumentCount': js.number(selector.typeArgumentCount)
|
||||
});
|
||||
|
||||
@@ -146,8 +146,9 @@ class InstantiationStubGenerator {
|
||||
late FieldEntity functionField;
|
||||
_elementEnvironment.forEachInstanceField(instantiationClass,
|
||||
(ClassEntity enclosing, FieldEntity field) {
|
||||
if (_closedWorld.fieldAnalysis.getFieldData(field as JField).isElided)
|
||||
if (_closedWorld.fieldAnalysis.getFieldData(field as JField).isElided) {
|
||||
return;
|
||||
}
|
||||
if (field.name == '_genericClosure') functionField = field;
|
||||
});
|
||||
|
||||
|
||||
@@ -105,29 +105,29 @@ class InterceptorStubGenerator {
|
||||
if (cls == _commonElements.jsArrayClass ||
|
||||
cls == _commonElements.jsMutableArrayClass ||
|
||||
cls == _commonElements.jsFixedArrayClass ||
|
||||
cls == _commonElements.jsExtendableArrayClass)
|
||||
cls == _commonElements.jsExtendableArrayClass) {
|
||||
hasArray = true;
|
||||
else if (cls == _commonElements.jsBoolClass)
|
||||
} else if (cls == _commonElements.jsBoolClass) {
|
||||
hasBool = true;
|
||||
else if (cls == _commonElements.jsNumNotIntClass)
|
||||
} else if (cls == _commonElements.jsNumNotIntClass) {
|
||||
hasNumNotInt = true;
|
||||
else if (cls == _commonElements.jsIntClass)
|
||||
} else if (cls == _commonElements.jsIntClass) {
|
||||
hasInt = true;
|
||||
else if (cls == _commonElements.jsNullClass)
|
||||
} else if (cls == _commonElements.jsNullClass) {
|
||||
hasNull = true;
|
||||
else if (cls == _commonElements.jsNumberClass)
|
||||
} else if (cls == _commonElements.jsNumberClass) {
|
||||
hasNumber = true;
|
||||
else if (cls == _commonElements.jsStringClass)
|
||||
} else if (cls == _commonElements.jsStringClass) {
|
||||
hasString = true;
|
||||
else if (cls == _commonElements.jsJavaScriptBigIntClass)
|
||||
} else if (cls == _commonElements.jsJavaScriptBigIntClass) {
|
||||
hasJavaScriptBigInt = true;
|
||||
else if (cls == _commonElements.jsJavaScriptFunctionClass)
|
||||
} else if (cls == _commonElements.jsJavaScriptFunctionClass) {
|
||||
hasJavaScriptFunction = true;
|
||||
else if (cls == _commonElements.jsJavaScriptSymbolClass)
|
||||
} else if (cls == _commonElements.jsJavaScriptSymbolClass) {
|
||||
hasJavaScriptSymbol = true;
|
||||
else if (cls == _commonElements.jsJavaScriptObjectClass)
|
||||
} else if (cls == _commonElements.jsJavaScriptObjectClass) {
|
||||
hasJavaScriptObject = true;
|
||||
else {
|
||||
} else {
|
||||
// The set of classes includes classes mixed-in to interceptor classes
|
||||
// and user extensions of native classes.
|
||||
//
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// 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.
|
||||
|
||||
part of dart2js.js_emitter.program_builder;
|
||||
part of 'program_builder.dart';
|
||||
|
||||
/// Generates the code for all used classes in the program. Static fields (even
|
||||
/// in classes) are ignored, since they can be treated as non-class elements.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// 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.
|
||||
|
||||
part of dart2js.js_emitter.program_builder;
|
||||
part of 'program_builder.dart';
|
||||
|
||||
/// [member] is an instance field.
|
||||
///
|
||||
|
||||
@@ -442,7 +442,7 @@ class ProgramBuilder {
|
||||
if (member.isGetter || member is FieldEntity || member.isFunction) {
|
||||
final selectors =
|
||||
_codegenWorld.getterInvocationsByName(member.name!);
|
||||
if (selectors != null && !selectors.isEmpty) {
|
||||
if (selectors != null && selectors.isNotEmpty) {
|
||||
for (Selector selector in selectors) {
|
||||
js.Name stubName = _namer.invocationName(selector);
|
||||
if (stubNames.add(stubName.key)) {
|
||||
@@ -462,7 +462,7 @@ class ProgramBuilder {
|
||||
if (member.isSetter || (member is FieldEntity && !member.isConst)) {
|
||||
final selectors =
|
||||
_codegenWorld.setterInvocationsByName(member.name!);
|
||||
if (selectors != null && !selectors.isEmpty) {
|
||||
if (selectors != null && selectors.isNotEmpty) {
|
||||
var stubName = _namer.setterForMember(member);
|
||||
if (stubNames.add(stubName.key)) {
|
||||
interceptorClass!.callStubs.add(_buildStubMethod(stubName,
|
||||
@@ -498,7 +498,7 @@ class ProgramBuilder {
|
||||
// Named arguments are not yet supported. In the future we
|
||||
// may want to map named arguments to an object literal containing
|
||||
// all named arguments.
|
||||
if (selectors != null && !selectors.isEmpty) {
|
||||
if (selectors != null && selectors.isNotEmpty) {
|
||||
for (var selector in selectors.keys) {
|
||||
// Check whether the arity matches this member.
|
||||
var argumentCount = selector.argumentCount;
|
||||
@@ -624,7 +624,7 @@ class ProgramBuilder {
|
||||
if (member.isGetter || member is FieldEntity) {
|
||||
Map<Selector, SelectorConstraints>? selectors =
|
||||
_codegenWorld.invocationsByName(member.name!);
|
||||
if (selectors != null && !selectors.isEmpty) {
|
||||
if (selectors != null && selectors.isNotEmpty) {
|
||||
Map<js.Name, js.Expression> callStubsForMember =
|
||||
classStubGenerator.generateCallStubsForGetter(member, selectors);
|
||||
callStubsForMember.forEach((js.Name name, js.Expression code) {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// 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.
|
||||
|
||||
part of dart2js.js_emitter.program_builder;
|
||||
part of 'program_builder.dart';
|
||||
|
||||
class LibraryContents {
|
||||
final List<ClassEntity> classes = [];
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// 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.
|
||||
|
||||
part of dart2js.js_emitter.startup_emitter.model_emitter;
|
||||
part of 'model_emitter.dart';
|
||||
|
||||
/// The fast startup emitter's goal is to minimize the amount of work that the
|
||||
/// JavaScript engine has to do before it can start running user code.
|
||||
|
||||
@@ -646,14 +646,14 @@ class FragmentMerger {
|
||||
///
|
||||
/// Where
|
||||
///
|
||||
/// - <library uri> is the import uri of the library making a deferred
|
||||
/// - library uri is the import uri of the library making a deferred
|
||||
/// import.
|
||||
/// - <library name> is the name of the library, or "<unnamed>" if it is
|
||||
/// - library name is the name of the library, or `"<unnamed>"` if it is
|
||||
/// unnamed.
|
||||
/// - <prefix> is the `as` prefix used for a given deferred import.
|
||||
/// - <loadId> is the unique ID assigned by the compiler for each
|
||||
/// <library uri>/<prefix> pair.
|
||||
/// - <list of files> is a list of the filenames the must be loaded when that
|
||||
/// - prefix is the `as` prefix used for a given deferred import.
|
||||
/// - loadId is the unique ID assigned by the compiler for each
|
||||
/// library uri/prefix pair.
|
||||
/// - list of files is a list of the filenames the must be loaded when that
|
||||
/// import is loaded.
|
||||
/// TODO(joshualitt): the library name is unused and should be removed. This
|
||||
/// will be a breaking change.
|
||||
|
||||
@@ -847,12 +847,6 @@ class JsClosureClassInfo extends JsScopeInfo
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
List<Local> getCreatedFieldEntities(KernelToLocalsMap localsMap) {
|
||||
_ensureFieldToLocalsMap(localsMap);
|
||||
return _fieldToLocalsMap!.values.toList();
|
||||
}
|
||||
|
||||
@override
|
||||
Local getLocalForField(KernelToLocalsMap localsMap, FieldEntity field) {
|
||||
_ensureFieldToLocalsMap(localsMap);
|
||||
|
||||
@@ -1189,22 +1189,22 @@ class JsKernelToElementMap implements JsToElementMap, IrToElementMap {
|
||||
if (cachedMayLookupInMain!) {
|
||||
type ??= findInLibrary(elementEnvironment.mainLibrary);
|
||||
}
|
||||
type ??= findIn(Uris.dart_core);
|
||||
type ??= findIn(Uris.dart__js_helper);
|
||||
type ??= findIn(Uris.dart__late_helper);
|
||||
type ??= findIn(Uris.dart__interceptors);
|
||||
type ??= findIn(Uris.dart__native_typed_data);
|
||||
type ??= findIn(Uris.dart_collection);
|
||||
type ??= findIn(Uris.dart_math);
|
||||
type ??= findIn(Uris.dart_html);
|
||||
type ??= findIn(Uris.dart_html_common);
|
||||
type ??= findIn(Uris.dart_svg);
|
||||
type ??= findIn(Uris.dart_web_audio);
|
||||
type ??= findIn(Uris.dart_web_gl);
|
||||
type ??= findIn(Uris.dart_indexed_db);
|
||||
type ??= findIn(Uris.dart_typed_data);
|
||||
type ??= findIn(Uris.dart__rti);
|
||||
type ??= findIn(Uris.dart_mirrors);
|
||||
type ??= findIn(Uris.dartCore);
|
||||
type ??= findIn(Uris.dartJSHelper);
|
||||
type ??= findIn(Uris.dartLateHelper);
|
||||
type ??= findIn(Uris.dartInterceptors);
|
||||
type ??= findIn(Uris.dartNativeTypedData);
|
||||
type ??= findIn(Uris.dartCollection);
|
||||
type ??= findIn(Uris.dartMath);
|
||||
type ??= findIn(Uris.dartHtml);
|
||||
type ??= findIn(Uris.dartHtmlCommon);
|
||||
type ??= findIn(Uris.dartSvg);
|
||||
type ??= findIn(Uris.dartWebAudio);
|
||||
type ??= findIn(Uris.dartWebGL);
|
||||
type ??= findIn(Uris.dartIndexedDB);
|
||||
type ??= findIn(Uris.dartTypedData);
|
||||
type ??= findIn(Uris.dartRti);
|
||||
type ??= findIn(Uris.dartMirrors);
|
||||
if (type == null && required) {
|
||||
reporter.reportErrorMessage(CURRENT_ELEMENT_SPANNABLE,
|
||||
MessageKind.GENERIC, {'text': "Type '$typeName' not found."});
|
||||
@@ -1254,7 +1254,7 @@ class JsKernelToElementMap implements JsToElementMap, IrToElementMap {
|
||||
// TODO(johnniwinther): Cache this for later use.
|
||||
@override
|
||||
NativeBehavior getNativeBehaviorForJsBuiltinCall(ir.StaticInvocation node) {
|
||||
if (node.arguments.positional.length < 1) {
|
||||
if (node.arguments.positional.isEmpty) {
|
||||
reporter.internalError(
|
||||
CURRENT_ELEMENT_SPANNABLE, "JS builtin expression has no type.");
|
||||
}
|
||||
@@ -1279,7 +1279,7 @@ class JsKernelToElementMap implements JsToElementMap, IrToElementMap {
|
||||
@override
|
||||
NativeBehavior getNativeBehaviorForJsEmbeddedGlobalCall(
|
||||
ir.StaticInvocation node) {
|
||||
if (node.arguments.positional.length < 1) {
|
||||
if (node.arguments.positional.isEmpty) {
|
||||
reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
|
||||
"JS embedded global expression has no type.");
|
||||
}
|
||||
|
||||
@@ -296,7 +296,7 @@ class JClosedWorld implements World {
|
||||
|
||||
/// Returns `true` if [cls] is mixed into a live class.
|
||||
bool isUsedAsMixin(ClassEntity cls) {
|
||||
return !mixinUsesOf(cls).isEmpty;
|
||||
return mixinUsesOf(cls).isNotEmpty;
|
||||
}
|
||||
|
||||
/// Returns `true` if any live class that mixes in [cls] implements [type].
|
||||
@@ -390,7 +390,7 @@ class JClosedWorld implements World {
|
||||
// Stop fast - we found a need for noSuchMethod handling.
|
||||
return IterationStep.STOP;
|
||||
}
|
||||
}, ClassHierarchyNode.EXPLICITLY_INSTANTIATED, strict: true);
|
||||
}, ClassHierarchyNode.explicitlyInstantiated, strict: true);
|
||||
// We stopped fast so we need noSuchMethod handling.
|
||||
return result == IterationStep.STOP;
|
||||
}
|
||||
@@ -439,7 +439,7 @@ class JClosedWorld implements World {
|
||||
link = link.tail!) {
|
||||
ClassEntity cls = link.head.element;
|
||||
for (Link<OrderedTypeSet> link = otherTypeSets;
|
||||
!link.isEmpty;
|
||||
link.isNotEmpty;
|
||||
link = link.tail!) {
|
||||
if (link.head.asInstanceOf(
|
||||
cls, elementMap.getHierarchyDepth(cls as JClass)) ==
|
||||
|
||||
@@ -111,7 +111,7 @@ class JClosedWorldBuilder {
|
||||
.forEachSubclass((ClassEntity cls) {
|
||||
convertClassSet(closedWorld.classHierarchy.getClassSet(cls));
|
||||
return IterationStep.CONTINUE;
|
||||
}, ClassHierarchyNode.ALL);
|
||||
}, ClassHierarchyNode.all);
|
||||
|
||||
Set<MemberEntity> liveInstanceMembers =
|
||||
map.toBackendMemberSet(closedWorld.liveInstanceMembers);
|
||||
|
||||
@@ -151,11 +151,6 @@ abstract class TypeRecipe {
|
||||
|
||||
TypeRecipe();
|
||||
|
||||
@override
|
||||
late final hashCode = _computeHashCode();
|
||||
|
||||
int _computeHashCode();
|
||||
|
||||
factory TypeRecipe.readFromDataSource(DataSourceReader source) {
|
||||
TypeRecipe recipe;
|
||||
source.begin(tag);
|
||||
@@ -225,7 +220,7 @@ class TypeExpressionRecipe extends TypeRecipe {
|
||||
}
|
||||
|
||||
@override
|
||||
int _computeHashCode() => type.hashCode * 7;
|
||||
late final int hashCode = type.hashCode * 7;
|
||||
|
||||
@override
|
||||
bool operator ==(other) {
|
||||
@@ -260,7 +255,7 @@ class SingletonTypeEnvironmentRecipe extends TypeEnvironmentRecipe {
|
||||
}
|
||||
|
||||
@override
|
||||
int _computeHashCode() => type.hashCode * 11;
|
||||
late final int hashCode = type.hashCode * 11;
|
||||
|
||||
@override
|
||||
bool operator ==(other) {
|
||||
@@ -304,9 +299,8 @@ class FullTypeEnvironmentRecipe extends TypeEnvironmentRecipe {
|
||||
}
|
||||
|
||||
@override
|
||||
int _computeHashCode() {
|
||||
return Hashing.listHash(types, Hashing.objectHash(classType, 0));
|
||||
}
|
||||
late final int hashCode =
|
||||
Hashing.listHash(types, Hashing.objectHash(classType, 0));
|
||||
|
||||
@override
|
||||
bool operator ==(other) {
|
||||
|
||||
@@ -209,7 +209,7 @@ class Dart2jsTarget extends Target {
|
||||
arg.value)
|
||||
..fileOffset = arg.fileOffset;
|
||||
})), keyType: coreTypes.stringNonNullableRawType)
|
||||
..isConst = (arguments.named.length == 0)
|
||||
..isConst = (arguments.named.isEmpty)
|
||||
..fileOffset = arguments.fileOffset,
|
||||
ir.IntLiteral(kind.value)..fileOffset = offset,
|
||||
]))
|
||||
|
||||
@@ -922,22 +922,22 @@ class KernelToElementMap implements IrToElementMap {
|
||||
if (cachedMayLookupInMain!) {
|
||||
type ??= findInLibrary(elementEnvironment.mainLibrary);
|
||||
}
|
||||
type ??= findIn(Uris.dart_core);
|
||||
type ??= findIn(Uris.dart__js_helper);
|
||||
type ??= findIn(Uris.dart__late_helper);
|
||||
type ??= findIn(Uris.dart__interceptors);
|
||||
type ??= findIn(Uris.dart__native_typed_data);
|
||||
type ??= findIn(Uris.dart_collection);
|
||||
type ??= findIn(Uris.dart_math);
|
||||
type ??= findIn(Uris.dart_html);
|
||||
type ??= findIn(Uris.dart_html_common);
|
||||
type ??= findIn(Uris.dart_svg);
|
||||
type ??= findIn(Uris.dart_web_audio);
|
||||
type ??= findIn(Uris.dart_web_gl);
|
||||
type ??= findIn(Uris.dart_indexed_db);
|
||||
type ??= findIn(Uris.dart_typed_data);
|
||||
type ??= findIn(Uris.dart__rti);
|
||||
type ??= findIn(Uris.dart_mirrors);
|
||||
type ??= findIn(Uris.dartCore);
|
||||
type ??= findIn(Uris.dartJSHelper);
|
||||
type ??= findIn(Uris.dartLateHelper);
|
||||
type ??= findIn(Uris.dartInterceptors);
|
||||
type ??= findIn(Uris.dartNativeTypedData);
|
||||
type ??= findIn(Uris.dartCollection);
|
||||
type ??= findIn(Uris.dartMath);
|
||||
type ??= findIn(Uris.dartHtml);
|
||||
type ??= findIn(Uris.dartHtmlCommon);
|
||||
type ??= findIn(Uris.dartSvg);
|
||||
type ??= findIn(Uris.dartWebAudio);
|
||||
type ??= findIn(Uris.dartWebGL);
|
||||
type ??= findIn(Uris.dartIndexedDB);
|
||||
type ??= findIn(Uris.dartTypedData);
|
||||
type ??= findIn(Uris.dartRti);
|
||||
type ??= findIn(Uris.dartMirrors);
|
||||
if (type == null && required!) {
|
||||
reporter.reportErrorMessage(CURRENT_ELEMENT_SPANNABLE,
|
||||
MessageKind.GENERIC, {'text': "Type '$typeName' not found."});
|
||||
@@ -988,7 +988,7 @@ class KernelToElementMap implements IrToElementMap {
|
||||
/// Computes the [NativeBehavior] for a call to the [JS_BUILTIN]
|
||||
/// function.
|
||||
NativeBehavior getNativeBehaviorForJsBuiltinCall(ir.StaticInvocation node) {
|
||||
if (node.arguments.positional.length < 1) {
|
||||
if (node.arguments.positional.isEmpty) {
|
||||
reporter.internalError(
|
||||
CURRENT_ELEMENT_SPANNABLE, "JS builtin expression has no type.");
|
||||
}
|
||||
@@ -1014,7 +1014,7 @@ class KernelToElementMap implements IrToElementMap {
|
||||
/// TODO(johnniwinther): Cache this for later use.
|
||||
NativeBehavior getNativeBehaviorForJsEmbeddedGlobalCall(
|
||||
ir.StaticInvocation node) {
|
||||
if (node.arguments.positional.length < 1) {
|
||||
if (node.arguments.positional.isEmpty) {
|
||||
reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
|
||||
"JS embedded global expression has no type.");
|
||||
}
|
||||
|
||||
@@ -179,7 +179,7 @@ class ListFactorySpecializer extends BaseSpecializer {
|
||||
/// Returns constant value of the first argument in [args], or null if it is
|
||||
/// not a constant.
|
||||
int? _getLengthArgument(Arguments args) {
|
||||
if (args.positional.length < 1) return null;
|
||||
if (args.positional.isEmpty) return null;
|
||||
final value = args.positional.first;
|
||||
if (value is IntLiteral) {
|
||||
return value.value;
|
||||
|
||||
@@ -29,6 +29,10 @@ class SpecialType {
|
||||
/// The type Object, but no subtypes:
|
||||
static const JsObject = SpecialType._('=Object');
|
||||
|
||||
@override
|
||||
bool operator ==(other) =>
|
||||
identical(this, other) || other is SpecialType && name == other.name;
|
||||
|
||||
@override
|
||||
int get hashCode => name.hashCode;
|
||||
|
||||
@@ -99,11 +103,11 @@ class NativeBehavior {
|
||||
|
||||
// TODO(sra): Make NativeBehavior immutable so PURE and PURE_ALLOCATION can be
|
||||
// final constant-like objects.
|
||||
static NativeBehavior get PURE => NativeBehavior._makePure();
|
||||
static NativeBehavior get PURE_ALLOCATION =>
|
||||
static NativeBehavior get pure => NativeBehavior._makePure();
|
||||
static NativeBehavior get pureAllocation =>
|
||||
NativeBehavior._makePure(isAllocation: true);
|
||||
static NativeBehavior get CHANGES_OTHER => NativeBehavior._makeChangesOther();
|
||||
static NativeBehavior get DEPENDS_OTHER => NativeBehavior._makeDependsOther();
|
||||
static NativeBehavior get changesOther => NativeBehavior._makeChangesOther();
|
||||
static NativeBehavior get dependsOther => NativeBehavior._makeDependsOther();
|
||||
|
||||
NativeBehavior() : sideEffects = SideEffects.empty();
|
||||
|
||||
@@ -229,7 +233,7 @@ class NativeBehavior {
|
||||
/// The types Ti are non-nullable, so add class `Null` to specify a
|
||||
/// nullable type, e.g `'String|Null'`.
|
||||
///
|
||||
/// 2) A sequence of <tag>:<value> pairs of the following kinds
|
||||
/// 2) A sequence of `<tag>:<value>` pairs of the following kinds
|
||||
///
|
||||
/// <type-tag>:<type-string>
|
||||
/// <effect-tag>:<effect-string>
|
||||
|
||||
@@ -20,7 +20,7 @@ abstract class NativeEnqueuer {
|
||||
final Set<ClassEntity> _unusedClasses = {};
|
||||
|
||||
/// Returns whether native classes are being used.
|
||||
bool get hasInstantiatedNativeClasses => !_registeredClasses.isEmpty;
|
||||
bool get hasInstantiatedNativeClasses => _registeredClasses.isNotEmpty;
|
||||
|
||||
/// Log message reported if all native types are used.
|
||||
String? _allUsedMessage;
|
||||
|
||||
@@ -292,8 +292,9 @@ class ThrowBehaviorVisitor extends js.BaseVisitor<NativeThrowBehavior> {
|
||||
|
||||
@override
|
||||
NativeThrowBehavior visitPrefix(js.Prefix node) {
|
||||
if (node.op == 'typeof' && node.argument is js.VariableUse)
|
||||
if (node.op == 'typeof' && node.argument is js.VariableUse) {
|
||||
return NativeThrowBehavior.never;
|
||||
}
|
||||
NativeThrowBehavior result = visit(node.argument);
|
||||
switch (node.op) {
|
||||
case '+':
|
||||
|
||||
@@ -129,9 +129,10 @@ void _simplifyConstConditionals(ir.Component component, CompilerOptions options,
|
||||
if (node is! ir.Annotatable) {
|
||||
return false;
|
||||
}
|
||||
return computePragmaAnnotationDataFromIr(node).any((pragma) =>
|
||||
pragma == const PragmaAnnotationData('noInline') ||
|
||||
pragma == const PragmaAnnotationData('never-inline'));
|
||||
return computePragmaAnnotationDataFromIr(node).any(
|
||||
(PragmaAnnotationData pragma) =>
|
||||
pragma == const PragmaAnnotationData('noInline') ||
|
||||
pragma == const PragmaAnnotationData('never-inline'));
|
||||
}
|
||||
|
||||
fe.ConstConditionalSimplifier(
|
||||
|
||||
@@ -33,6 +33,7 @@ import 'package:compiler/src/serialization/serialization.dart';
|
||||
///
|
||||
/// Example class before:
|
||||
///
|
||||
/// ```
|
||||
/// class Foo {
|
||||
/// final Bar bar;
|
||||
/// final String name;
|
||||
@@ -45,9 +46,11 @@ import 'package:compiler/src/serialization/serialization.dart';
|
||||
/// return Foo(bar, name);
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// After:
|
||||
///
|
||||
/// ```
|
||||
/// class Foo {
|
||||
/// Bar get bar => _bar.loaded();
|
||||
/// final Deferrable<Bar> _bar;
|
||||
@@ -67,6 +70,7 @@ import 'package:compiler/src/serialization/serialization.dart';
|
||||
/// return Foo._deserialized(bar, name);
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
abstract class Deferrable<E> {
|
||||
E loaded();
|
||||
|
||||
@@ -119,7 +123,7 @@ class _DeferredCacheWithArg<E, A> extends Deferrable<E> {
|
||||
E _loadData() {
|
||||
final reader = _reader!;
|
||||
final dataLoader = _dataLoader!;
|
||||
final arg = _arg!;
|
||||
final arg = _arg as A;
|
||||
_reader = null;
|
||||
_dataLoader = null;
|
||||
_arg = null;
|
||||
|
||||
@@ -188,8 +188,9 @@ class FormattingDiagnosticHandler implements api.CompilerDiagnostics {
|
||||
api.Diagnostic? lastKind = null;
|
||||
int fatalCount = 0;
|
||||
|
||||
final int FATAL = api.Diagnostic.crash.ordinal | api.Diagnostic.error.ordinal;
|
||||
final int INFO =
|
||||
final int fatalCode =
|
||||
api.Diagnostic.crash.ordinal | api.Diagnostic.error.ordinal;
|
||||
final int infoCode =
|
||||
api.Diagnostic.info.ordinal | api.Diagnostic.verboseInfo.ordinal;
|
||||
|
||||
FormattingDiagnosticHandler();
|
||||
@@ -232,8 +233,8 @@ class FormattingDiagnosticHandler implements api.CompilerDiagnostics {
|
||||
if (isAborting) return;
|
||||
isAborting = (kind == api.Diagnostic.crash);
|
||||
|
||||
bool fatal = (kind.ordinal & FATAL) != 0;
|
||||
bool isInfo = (kind.ordinal & INFO) != 0;
|
||||
bool fatal = (kind.ordinal & fatalCode) != 0;
|
||||
bool isInfo = (kind.ordinal & infoCode) != 0;
|
||||
if (isInfo && uri == null && kind != api.Diagnostic.info) {
|
||||
info(message, kind);
|
||||
return;
|
||||
|
||||
@@ -210,7 +210,7 @@ class SsaBranchBuilder {
|
||||
|
||||
HBasicBlock? joinBlock;
|
||||
// If at least one branch did not abort, open the joinBranch.
|
||||
if (!joinBranch.block.predecessors.isEmpty) {
|
||||
if (joinBranch.block.predecessors.isNotEmpty) {
|
||||
startBranch(joinBranch);
|
||||
joinBlock = joinBranch.block;
|
||||
}
|
||||
|
||||
@@ -1321,7 +1321,7 @@ class KernelSsaGraphBuilder extends ir.VisitorDefault<void>
|
||||
final targetTypeArguments =
|
||||
closedWorld.elementEnvironment.getFunctionTypeVariables(stubTarget);
|
||||
|
||||
if (targetTypeArguments.length > 0) {
|
||||
if (targetTypeArguments.isNotEmpty) {
|
||||
if (stubParameterStructure.typeParameters == 0) {
|
||||
// This stub does not include type parameters so use RTI to make the
|
||||
// appropriate defaults.
|
||||
@@ -1498,7 +1498,7 @@ class KernelSsaGraphBuilder extends ir.VisitorDefault<void>
|
||||
_abstractValueDomain
|
||||
.isEmpty(parameter.instructionType)
|
||||
.isDefinitelyTrue);
|
||||
if (emptyParameters.length > 0) {
|
||||
if (emptyParameters.isNotEmpty) {
|
||||
_addComment('${emptyParameters} inferred as [empty]');
|
||||
add(HInvokeStatic(_commonElements.assertUnreachableMethod, [],
|
||||
_abstractValueDomain.dynamicType, const []));
|
||||
@@ -2025,8 +2025,9 @@ class KernelSsaGraphBuilder extends ir.VisitorDefault<void>
|
||||
// check. The null check is added before the argument type checks since in
|
||||
// strong mode, the parameter type might be non-nullable.
|
||||
if (member is FunctionEntity && member.name == '==') {
|
||||
if (functionNode == null)
|
||||
if (functionNode == null) {
|
||||
throw StateError("'==' should have functionNode");
|
||||
}
|
||||
if (!_commonElements.operatorEqHandlesNullArgument(member)) {
|
||||
_handleIf(
|
||||
visitCondition: () {
|
||||
@@ -2688,7 +2689,7 @@ class KernelSsaGraphBuilder extends ir.VisitorDefault<void>
|
||||
bodyExitBlock.addSuccessor(conditionBlock);
|
||||
}
|
||||
|
||||
if (!continueHandlers.isEmpty) {
|
||||
if (continueHandlers.isNotEmpty) {
|
||||
if (!isAbortingBody) continueHandlers.add(localsHandler);
|
||||
localsHandler =
|
||||
savedLocals.mergeMultiple(continueHandlers, conditionBlock);
|
||||
@@ -2697,7 +2698,7 @@ class KernelSsaGraphBuilder extends ir.VisitorDefault<void>
|
||||
HSubGraphBlockInformation bodyInfo =
|
||||
HSubGraphBlockInformation(bodyGraph);
|
||||
HLabeledBlockInformation info;
|
||||
if (!labels.isEmpty) {
|
||||
if (labels.isNotEmpty) {
|
||||
info = HLabeledBlockInformation(bodyInfo, labels, isContinue: true);
|
||||
} else {
|
||||
info = HLabeledBlockInformation.implicit(bodyInfo, target,
|
||||
@@ -3297,7 +3298,7 @@ class KernelSsaGraphBuilder extends ir.VisitorDefault<void>
|
||||
js.Template code = js.js.parseForeignJS('#');
|
||||
push(HForeignCode(code, _abstractValueDomain.boolType,
|
||||
[localsHandler.readLocal(switchTarget)],
|
||||
nativeBehavior: NativeBehavior.PURE));
|
||||
nativeBehavior: NativeBehavior.pure));
|
||||
}
|
||||
|
||||
_handleIf(
|
||||
@@ -5035,7 +5036,7 @@ class KernelSsaGraphBuilder extends ir.VisitorDefault<void>
|
||||
ConstantValue constant, ClassEntity classElement) {
|
||||
if (constant is ConstructedConstantValue &&
|
||||
constant.type.element == classElement) {
|
||||
assert(constant.fields.length >= 1);
|
||||
assert(constant.fields.isNotEmpty);
|
||||
for (var field in constant.fields.keys) {
|
||||
if (field.memberName.text == "index") {
|
||||
final indexConstant = constant.fields[field];
|
||||
|
||||
@@ -763,7 +763,7 @@ class SsaCodeGenerator implements HVisitor<void>, HBlockInformationVisitor {
|
||||
void visitStatement(HInstruction node) {
|
||||
assert(!isGeneratingExpression);
|
||||
visit(node);
|
||||
if (!expressionStack.isEmpty) {
|
||||
if (expressionStack.isNotEmpty) {
|
||||
assert(expressionStack.length == 1);
|
||||
js.Expression expression = pop();
|
||||
pushExpressionAsStatement(expression, node.sourceInformation);
|
||||
@@ -962,7 +962,7 @@ class SsaCodeGenerator implements HVisitor<void>, HBlockInformationVisitor {
|
||||
js.Block avoidContainer = js.Block.empty();
|
||||
currentContainer = avoidContainer;
|
||||
assignPhisOfSuccessors(condition!.end.successors.last);
|
||||
bool hasPhiUpdates = !avoidContainer.statements.isEmpty;
|
||||
bool hasPhiUpdates = avoidContainer.statements.isNotEmpty;
|
||||
currentContainer = oldContainer;
|
||||
|
||||
if (isConditionExpression &&
|
||||
@@ -1079,7 +1079,7 @@ class SsaCodeGenerator implements HVisitor<void>, HBlockInformationVisitor {
|
||||
js.Block exitAvoidContainer = js.Block.empty();
|
||||
currentContainer = exitAvoidContainer;
|
||||
assignPhisOfSuccessors(condition!.end.successors.last);
|
||||
bool hasExitPhiUpdates = !exitAvoidContainer.statements.isEmpty;
|
||||
bool hasExitPhiUpdates = exitAvoidContainer.statements.isNotEmpty;
|
||||
currentContainer = oldContainer;
|
||||
|
||||
oldContainer = currentContainer;
|
||||
@@ -1099,7 +1099,7 @@ class SsaCodeGenerator implements HVisitor<void>, HBlockInformationVisitor {
|
||||
js.Block updateBody = js.Block.empty();
|
||||
currentContainer = updateBody;
|
||||
assignPhisOfSuccessors(avoidEdge);
|
||||
bool hasPhiUpdates = !updateBody.statements.isEmpty;
|
||||
bool hasPhiUpdates = updateBody.statements.isNotEmpty;
|
||||
currentContainer = body;
|
||||
visitBodyIgnoreLabels(info);
|
||||
if (info.updates != null) {
|
||||
@@ -1206,7 +1206,7 @@ class SsaCodeGenerator implements HVisitor<void>, HBlockInformationVisitor {
|
||||
generateStatements(labeledBlockInfo.body);
|
||||
|
||||
if (labeledBlockInfo.isContinue) {
|
||||
while (!continueOverrides.isEmpty) {
|
||||
while (continueOverrides.isNotEmpty) {
|
||||
continueAction.remove(continueOverrides.head);
|
||||
implicitContinueAction.remove(continueOverrides.head);
|
||||
continueOverrides = continueOverrides.tail!;
|
||||
@@ -1367,8 +1367,8 @@ class SsaCodeGenerator implements HVisitor<void>, HBlockInformationVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
while (!worklist.isEmpty) {
|
||||
while (!ready.isEmpty) {
|
||||
while (worklist.isNotEmpty) {
|
||||
while (ready.isNotEmpty) {
|
||||
String destination = ready.removeLast();
|
||||
String source = initialValue[destination]!;
|
||||
// Since [source] might have been updated, use the current
|
||||
@@ -2156,7 +2156,9 @@ class SsaCodeGenerator implements HVisitor<void>, HBlockInformationVisitor {
|
||||
List<HInstruction> arguments,
|
||||
SourceInformation? sourceInformation) {
|
||||
ConstantValue? findConstant(HInstruction node) {
|
||||
while (node is HLateValue) node = node.target;
|
||||
while (node is HLateValue) {
|
||||
node = node.target;
|
||||
}
|
||||
return node is HConstant ? node.constant : null;
|
||||
}
|
||||
|
||||
|
||||
@@ -872,7 +872,7 @@ class SsaInstructionMerger extends HBaseVisitor<void> implements CodegenPhase {
|
||||
// entry.
|
||||
int initializingAssignmentCount = (local is HParameterValue) ? 0 : 1;
|
||||
return local.usedBy
|
||||
.where((user) => user is HLocalSet)
|
||||
.whereType<HLocalSet>()
|
||||
.skip(initializingAssignmentCount)
|
||||
.isNotEmpty;
|
||||
}
|
||||
@@ -1090,7 +1090,7 @@ class SsaInstructionMerger extends HBaseVisitor<void> implements CodegenPhase {
|
||||
// Return true if it is found, or false if not.
|
||||
bool findInInputsAndPopNonMatching(HInstruction instruction) {
|
||||
assert(!isEffectivelyPure(instruction));
|
||||
while (!expectedInputs!.isEmpty) {
|
||||
while (expectedInputs!.isNotEmpty) {
|
||||
HInstruction nextInput = expectedInputs!.removeLast();
|
||||
assert(!generateAtUseSite.contains(nextInput));
|
||||
assert(nextInput.usedBy.length == 1);
|
||||
@@ -1232,7 +1232,9 @@ class SsaConditionMerger extends HGraphVisitor implements CodegenPhase {
|
||||
// before the control flow instruction, or the last instruction,
|
||||
// then we will have to emit a statement for that last instruction.
|
||||
if (instruction != block.last &&
|
||||
!identical(instruction, block.last!.previous)) return true;
|
||||
!identical(instruction, block.last!.previous)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If one of the instructions in the block until [instruction] is
|
||||
// not generated at use site, then we will have to emit a
|
||||
@@ -1535,8 +1537,9 @@ class SsaPhiConditioning extends HGraphVisitor implements CodegenPhase {
|
||||
void _markHandled(HPhi phi, HBasicBlock dominator) {
|
||||
if (_handled.add(phi)) {
|
||||
for (final input in phi.inputs) {
|
||||
if (input is HPhi && dominator.dominates(input.block!))
|
||||
if (input is HPhi && dominator.dominates(input.block!)) {
|
||||
_markHandled(input, dominator);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,7 +208,9 @@ class SsaSimplifyInterceptors extends HBaseVisitor<bool>
|
||||
instructions.where((i) => i.block == bestBlock).toSet();
|
||||
HInstruction? current =
|
||||
(dominator?.block == bestBlock) ? dominator : bestBlock.first;
|
||||
while (current != null && !set.contains(current)) current = current.next;
|
||||
while (current != null && !set.contains(current)) {
|
||||
current = current.next;
|
||||
}
|
||||
assert(current != null);
|
||||
return current;
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ class InvokeDynamicSpecializer {
|
||||
return const InvokeDynamicSpecializer();
|
||||
}
|
||||
if (selector.isCall) {
|
||||
if (selector.namedArguments.length == 0) {
|
||||
if (selector.namedArguments.isEmpty) {
|
||||
int argumentCount = selector.argumentCount;
|
||||
if (argumentCount == 0) {
|
||||
if (name == 'abs') return const AbsSpecializer();
|
||||
|
||||
@@ -492,15 +492,16 @@ class LocalsHandler {
|
||||
/// for (var i = 0; i < 2; i++) fs[i]();
|
||||
///
|
||||
/// We solve this by emitting the following code (only for [ast.For] loops):
|
||||
/// <Create box> <== move the first box creation outside the loop.
|
||||
/// <initializer>;
|
||||
/// loop-entry:
|
||||
/// if (!<condition>) goto loop-exit;
|
||||
/// <body>
|
||||
/// <update box> // create a new box and copy the captured loop-variables.
|
||||
/// <updates>
|
||||
/// goto loop-entry;
|
||||
/// loop-exit:
|
||||
///
|
||||
/// <Create box> <== move the first box creation outside the loop.
|
||||
/// <initializer>;
|
||||
/// loop-entry:
|
||||
/// if (!<condition>) goto loop-exit;
|
||||
/// <body>
|
||||
/// <update box> // create a new box and copy the captured loop-variables.
|
||||
/// <updates>
|
||||
/// goto loop-entry;
|
||||
/// loop-exit:
|
||||
void startLoop(
|
||||
CapturedLoopScope loopInfo, SourceInformation? sourceInformation) {
|
||||
if (loopInfo.hasBoxedLoopVariables) {
|
||||
@@ -609,7 +610,7 @@ class LocalsHandler {
|
||||
/// exclude local values from the result when they are no longer in scope.
|
||||
LocalsHandler mergeMultiple(
|
||||
List<LocalsHandler> localsHandlers, HBasicBlock joinBlock) {
|
||||
assert(localsHandlers.length > 0);
|
||||
assert(localsHandlers.isNotEmpty);
|
||||
if (localsHandlers.length == 1) return localsHandlers.single;
|
||||
Map<Local, HInstruction> joinedLocals = {};
|
||||
HInstruction? thisValue = null;
|
||||
@@ -708,6 +709,9 @@ class SyntheticLocal extends Local {
|
||||
|
||||
SyntheticLocal(this.name, this.executableContext, this.memberContext);
|
||||
|
||||
@override
|
||||
bool operator ==(other) => identical(this, other);
|
||||
|
||||
@override
|
||||
String toString() => 'SyntheticLocal($name)';
|
||||
}
|
||||
|
||||
@@ -267,7 +267,7 @@ abstract class LoopHandler {
|
||||
builder.open(loopExitBlock);
|
||||
|
||||
// Create a new localsHandler for the loopExitBlock with the correct phis.
|
||||
if (!breakHandlers.isEmpty) {
|
||||
if (breakHandlers.isNotEmpty) {
|
||||
if (branchExitBlock != null) {
|
||||
// Add the values of the locals at the end of the condition block to
|
||||
// the phis. These are the values that flow to the exit if the
|
||||
|
||||
@@ -807,6 +807,10 @@ class HBasicBlock extends HInstructionList {
|
||||
@override
|
||||
int get hashCode => id;
|
||||
|
||||
@override
|
||||
bool operator ==(other) =>
|
||||
identical(this, other) || other is HBasicBlock && id == other.id;
|
||||
|
||||
bool get isNew => _status == _BasicBlockStatus.new_;
|
||||
bool get isOpen => _status == _BasicBlockStatus.open;
|
||||
bool get isClosed => _status == _BasicBlockStatus.closed;
|
||||
@@ -870,7 +874,7 @@ class HBasicBlock extends HInstructionList {
|
||||
}
|
||||
|
||||
void addPhi(HPhi phi) {
|
||||
assert(phi.inputs.length == 0 || phi.inputs.length == predecessors.length);
|
||||
assert(phi.inputs.isEmpty || phi.inputs.length == predecessors.length);
|
||||
assert(phi.block == null);
|
||||
phis.internalAddAfter(phis.last, phi);
|
||||
phi.notifyAddedToBlock(this);
|
||||
@@ -1163,9 +1167,10 @@ abstract class HInstruction implements SpannableWithEntity {
|
||||
: inputs = [...initialInputs];
|
||||
|
||||
// Convenience constructors that avoid an intermediate list.
|
||||
HInstruction._0(this.instructionType) : inputs = [];
|
||||
HInstruction._1(HInstruction input, this.instructionType) : inputs = [input];
|
||||
HInstruction._2(
|
||||
HInstruction._noInput(this.instructionType) : inputs = [];
|
||||
HInstruction._oneInput(HInstruction input, this.instructionType)
|
||||
: inputs = [input];
|
||||
HInstruction._twoInputs(
|
||||
HInstruction input1, HInstruction input2, this.instructionType)
|
||||
: inputs = [input1, input2];
|
||||
|
||||
@@ -1180,6 +1185,9 @@ abstract class HInstruction implements SpannableWithEntity {
|
||||
@override
|
||||
int get hashCode => id;
|
||||
|
||||
@override
|
||||
bool operator ==(other) => identical(this, other);
|
||||
|
||||
bool useGvn() => _useGvn;
|
||||
void setUseGvn() {
|
||||
_useGvn = true;
|
||||
@@ -1657,7 +1665,7 @@ class DominatedUses {
|
||||
/// This used for attaching source information to reads of locals.
|
||||
class HRef extends HInstruction {
|
||||
HRef(HInstruction value, SourceInformation sourceInformation)
|
||||
: super._1(value, value.instructionType) {
|
||||
: super._oneInput(value, value.instructionType) {
|
||||
this.sourceInformation = sourceInformation;
|
||||
}
|
||||
|
||||
@@ -1693,10 +1701,11 @@ abstract class HCheck extends HInstruction
|
||||
HCheck(super.inputs, super.type) {
|
||||
setUseGvn();
|
||||
}
|
||||
HCheck._1(super.input, super.type) : super._1() {
|
||||
HCheck._oneInput(super.input, super.type) : super._oneInput() {
|
||||
setUseGvn();
|
||||
}
|
||||
HCheck._2(super.input1, super.input2, super.type) : super._2() {
|
||||
HCheck._twoInputs(super.input1, super.input2, super.type)
|
||||
: super._twoInputs() {
|
||||
setUseGvn();
|
||||
}
|
||||
|
||||
@@ -1813,7 +1822,7 @@ class HCreate extends HInstruction {
|
||||
|
||||
// Allocates a box to hold mutated captured variables.
|
||||
class HCreateBox extends HInstruction {
|
||||
HCreateBox(super.type) : super._0();
|
||||
HCreateBox(super.type) : super._noInput();
|
||||
|
||||
@override
|
||||
bool isAllocation(AbstractValueDomain domain) => true;
|
||||
@@ -2276,7 +2285,7 @@ class HFieldSet extends HFieldAccess {
|
||||
// Raw reference to a function.
|
||||
class HFunctionReference extends HInstruction {
|
||||
FunctionEntity element;
|
||||
HFunctionReference(this.element, super.type) : super._0() {
|
||||
HFunctionReference(this.element, super.type) : super._noInput() {
|
||||
sideEffects.clearAllSideEffects();
|
||||
sideEffects.clearAllDependencies();
|
||||
setUseGvn();
|
||||
@@ -2298,7 +2307,7 @@ class HFunctionReference extends HInstruction {
|
||||
class HGetLength extends HInstruction {
|
||||
final bool isAssignable;
|
||||
HGetLength(super.receiver, super.type, {required this.isAssignable})
|
||||
: super._1() {
|
||||
: super._oneInput() {
|
||||
sideEffects.clearAllSideEffects();
|
||||
sideEffects.clearAllDependencies();
|
||||
setUseGvn();
|
||||
@@ -2485,7 +2494,7 @@ class HInvokeExternal extends HInvoke {
|
||||
@override
|
||||
bool canThrow(AbstractValueDomain domain) {
|
||||
if (element.isInstanceMember) {
|
||||
if (inputs.length > 0) {
|
||||
if (inputs.isNotEmpty) {
|
||||
return inputs.first.isNull(domain).isPotentiallyTrue
|
||||
? throwBehavior.canThrow
|
||||
: throwBehavior.onNonNull.canThrow;
|
||||
@@ -2507,7 +2516,7 @@ class HInvokeExternal extends HInvoke {
|
||||
/// is `null` before having any other side-effects.
|
||||
bool isNullGuardFor(HInstruction receiver) {
|
||||
if (!element.isInstanceMember) return false;
|
||||
if (inputs.length < 1) return false;
|
||||
if (inputs.isEmpty) return false;
|
||||
if (inputs.first.nonCheck() != receiver.nonCheck()) return false;
|
||||
return true;
|
||||
}
|
||||
@@ -2581,7 +2590,7 @@ class HForeignCode extends HForeign {
|
||||
bool isJsStatement() => isStatement;
|
||||
@override
|
||||
bool canThrow(AbstractValueDomain domain) {
|
||||
if (inputs.length > 0) {
|
||||
if (inputs.isNotEmpty) {
|
||||
return inputs.first.isNull(domain).isPotentiallyTrue
|
||||
? throwBehavior.canThrow
|
||||
: throwBehavior.onNonNull.canThrow;
|
||||
@@ -2602,7 +2611,7 @@ class HForeignCode extends HForeign {
|
||||
/// [receiver] is `null` before having any other side-effects.
|
||||
bool isNullGuardFor(HInstruction? receiver) {
|
||||
if (!throwBehavior.isNullNSMGuard) return false;
|
||||
if (inputs.length < 1) return false;
|
||||
if (inputs.isEmpty) return false;
|
||||
if (inputs.first.nonCheck() != receiver!.nonCheck()) return false;
|
||||
return true;
|
||||
}
|
||||
@@ -2622,7 +2631,7 @@ class HForeignCode extends HForeign {
|
||||
}
|
||||
|
||||
abstract class HInvokeBinary extends HInstruction {
|
||||
HInvokeBinary(super.left, super.right, super.type) : super._2() {
|
||||
HInvokeBinary(super.left, super.right, super.type) : super._twoInputs() {
|
||||
sideEffects.clearAllSideEffects();
|
||||
sideEffects.clearAllDependencies();
|
||||
setUseGvn();
|
||||
@@ -2854,7 +2863,7 @@ class HBitXor extends HBinaryBitOp {
|
||||
}
|
||||
|
||||
abstract class HInvokeUnary extends HInstruction {
|
||||
HInvokeUnary(super.input, super.type) : super._1() {
|
||||
HInvokeUnary(super.input, super.type) : super._oneInput() {
|
||||
sideEffects.clearAllSideEffects();
|
||||
sideEffects.clearAllDependencies();
|
||||
setUseGvn();
|
||||
@@ -3034,7 +3043,7 @@ class HLoopBranch extends HConditionalBranch {
|
||||
|
||||
class HConstant extends HInstruction {
|
||||
final ConstantValue constant;
|
||||
HConstant._internal(this.constant, super.constantType) : super._0();
|
||||
HConstant._internal(this.constant, super.constantType) : super._noInput();
|
||||
|
||||
@override
|
||||
String toString() => 'literal: ${constant.toStructuredText(null)}';
|
||||
@@ -3075,7 +3084,7 @@ class HConstant extends HInstruction {
|
||||
}
|
||||
|
||||
class HNot extends HInstruction {
|
||||
HNot(super.value, super.type) : super._1() {
|
||||
HNot(super.value, super.type) : super._oneInput() {
|
||||
setUseGvn();
|
||||
}
|
||||
|
||||
@@ -3093,7 +3102,7 @@ class HNot extends HInstruction {
|
||||
/// first use must be in an HLocalSet. That is, [HParameterValue]s have a
|
||||
/// value from the start, whereas [HLocalValue]s need to be initialized first.
|
||||
class HLocalValue extends HInstruction {
|
||||
HLocalValue(Entity? variable, super.type) : super._0() {
|
||||
HLocalValue(Entity? variable, super.type) : super._noInput() {
|
||||
sourceElement = variable;
|
||||
}
|
||||
|
||||
@@ -3299,7 +3308,7 @@ class HReturn extends HControlFlow {
|
||||
class HThrowExpression extends HInstruction {
|
||||
HThrowExpression(
|
||||
super.value, super.type, SourceInformation? sourceInformation)
|
||||
: super._1() {
|
||||
: super._oneInput() {
|
||||
this.sourceInformation = sourceInformation;
|
||||
}
|
||||
@override
|
||||
@@ -3311,7 +3320,7 @@ class HThrowExpression extends HInstruction {
|
||||
}
|
||||
|
||||
class HAwait extends HInstruction {
|
||||
HAwait(super.value, super.type) : super._1();
|
||||
HAwait(super.value, super.type) : super._oneInput();
|
||||
@override
|
||||
String toString() => 'await';
|
||||
@override
|
||||
@@ -3326,7 +3335,7 @@ class HAwait extends HInstruction {
|
||||
class HYield extends HInstruction {
|
||||
HYield(super.value, this.hasStar, super.type,
|
||||
SourceInformation? sourceInformation)
|
||||
: super._1() {
|
||||
: super._oneInput() {
|
||||
this.sourceInformation = sourceInformation;
|
||||
}
|
||||
bool hasStar;
|
||||
@@ -3360,7 +3369,7 @@ class HStatic extends HInstruction {
|
||||
final MemberEntity element;
|
||||
|
||||
HStatic(this.element, super.type, SourceInformation? sourceInformation)
|
||||
: super._0() {
|
||||
: super._noInput() {
|
||||
sideEffects.clearAllSideEffects();
|
||||
sideEffects.clearAllDependencies();
|
||||
if (element.isAssignable) {
|
||||
@@ -3400,7 +3409,7 @@ class HInterceptor extends HInstruction {
|
||||
// (a && C.JSArray_methods).get$first(a)
|
||||
//
|
||||
|
||||
HInterceptor(super.receiver, super.type) : super._1() {
|
||||
HInterceptor(super.receiver, super.type) : super._oneInput() {
|
||||
this.sourceInformation = receiver.sourceInformation;
|
||||
sideEffects.clearAllSideEffects();
|
||||
sideEffects.clearAllDependencies();
|
||||
@@ -3473,7 +3482,7 @@ class HLazyStatic extends HInstruction {
|
||||
final FieldEntity element;
|
||||
|
||||
HLazyStatic(this.element, super.type, SourceInformation? sourceInformation)
|
||||
: super._0() {
|
||||
: super._noInput() {
|
||||
// TODO(4931): The first access has side-effects, but we afterwards we
|
||||
// should be able to GVN.
|
||||
sideEffects.setAllSideEffects();
|
||||
@@ -3497,7 +3506,7 @@ class HLazyStatic extends HInstruction {
|
||||
class HStaticStore extends HInstruction {
|
||||
FieldEntity element;
|
||||
HStaticStore(this.element, HInstruction value)
|
||||
: super._1(value, value.instructionType) {
|
||||
: super._oneInput(value, value.instructionType) {
|
||||
sideEffects.clearAllSideEffects();
|
||||
sideEffects.clearAllDependencies();
|
||||
sideEffects.setChangesStaticProperty();
|
||||
@@ -3534,7 +3543,7 @@ class HLiteralList extends HInstruction {
|
||||
/// The primitive array indexing operation. Note that this instruction
|
||||
/// does not throw because we generate the checks explicitly.
|
||||
class HIndex extends HInstruction {
|
||||
HIndex(super.receiver, super.index, super.type) : super._2() {
|
||||
HIndex(super.receiver, super.index, super.type) : super._twoInputs() {
|
||||
sideEffects.clearAllSideEffects();
|
||||
sideEffects.clearAllDependencies();
|
||||
sideEffects.setDependsOnIndexStore();
|
||||
@@ -3604,7 +3613,7 @@ class HIndexAssign extends HInstruction {
|
||||
}
|
||||
|
||||
class HCharCodeAt extends HInstruction {
|
||||
HCharCodeAt(super.receiver, super.index, super.type) : super._2();
|
||||
HCharCodeAt(super.receiver, super.index, super.type) : super._twoInputs();
|
||||
|
||||
@override
|
||||
String toString() => 'HCharCodeAt';
|
||||
@@ -3644,7 +3653,8 @@ class HCharCodeAt extends HInstruction {
|
||||
/// 'this' with HLateValue(HThis) will have the effect of copying 'this' to a
|
||||
/// temporary which will reduce the size of minified code.
|
||||
class HLateValue extends HInstruction implements HLateInstruction {
|
||||
HLateValue(HInstruction target) : super._1(target, target.instructionType);
|
||||
HLateValue(HInstruction target)
|
||||
: super._oneInput(target, target.instructionType);
|
||||
|
||||
HInstruction get target => inputs.single;
|
||||
|
||||
@@ -3684,7 +3694,7 @@ class HPrimitiveCheck extends HCheck {
|
||||
HInstruction input, SourceInformation? sourceInformation,
|
||||
{this.receiverTypeCheckSelector})
|
||||
: checkedType = type,
|
||||
super._1(input, type) {
|
||||
super._oneInput(input, type) {
|
||||
assert(isReceiverTypeCheck == (receiverTypeCheckSelector != null));
|
||||
this.sourceElement = input.sourceElement;
|
||||
this.sourceInformation = sourceInformation;
|
||||
@@ -3738,7 +3748,7 @@ class HPrimitiveCheck extends HCheck {
|
||||
// bool!` checks and the backend checks them correctly, this instruction will
|
||||
// become unnecessary and should be removed.
|
||||
class HBoolConversion extends HCheck {
|
||||
HBoolConversion(super.input, super.type) : super._1();
|
||||
HBoolConversion(super.input, super.type) : super._oneInput();
|
||||
|
||||
@override
|
||||
bool isJsStatement() => false;
|
||||
@@ -3780,7 +3790,8 @@ class HNullCheck extends HCheck {
|
||||
Selector? selector;
|
||||
FieldEntity? field;
|
||||
|
||||
HNullCheck(super.input, super.type, {this.sticky = false}) : super._1();
|
||||
HNullCheck(super.input, super.type, {this.sticky = false})
|
||||
: super._oneInput();
|
||||
|
||||
@override
|
||||
bool isControlFlow() => true;
|
||||
@@ -3949,11 +3960,11 @@ class HTypeKnown extends HCheck {
|
||||
|
||||
HTypeKnown.pinned(this.knownType, HInstruction input)
|
||||
: this._isMovable = false,
|
||||
super._1(input, knownType);
|
||||
super._oneInput(input, knownType);
|
||||
|
||||
HTypeKnown.witnessed(this.knownType, HInstruction input, HInstruction witness)
|
||||
: this._isMovable = true,
|
||||
super._2(input, witness, knownType);
|
||||
super._twoInputs(input, witness, knownType);
|
||||
|
||||
@override
|
||||
String toString() => 'TypeKnown $knownType';
|
||||
@@ -3997,7 +4008,7 @@ class HTypeKnown extends HCheck {
|
||||
}
|
||||
|
||||
class HRangeConversion extends HCheck {
|
||||
HRangeConversion(super.input, super.type) : super._1() {
|
||||
HRangeConversion(super.input, super.type) : super._oneInput() {
|
||||
sourceElement = checkedInput.sourceElement;
|
||||
}
|
||||
|
||||
@@ -4009,7 +4020,7 @@ class HRangeConversion extends HCheck {
|
||||
}
|
||||
|
||||
class HStringConcat extends HInstruction {
|
||||
HStringConcat(super.left, super.right, super.type) : super._2() {
|
||||
HStringConcat(super.left, super.right, super.type) : super._twoInputs() {
|
||||
setUseGvn();
|
||||
}
|
||||
|
||||
@@ -4033,7 +4044,7 @@ class HStringConcat extends HInstruction {
|
||||
/// into a String value.
|
||||
class HStringify extends HInstruction {
|
||||
bool _isPure = false; // Some special cases are pure, e.g. int argument.
|
||||
HStringify(super.input, super.resultType) : super._1() {
|
||||
HStringify(super.input, super.resultType) : super._oneInput() {
|
||||
sideEffects.setAllSideEffects();
|
||||
sideEffects.setDependsOnSomething();
|
||||
}
|
||||
@@ -4080,7 +4091,7 @@ class HLoopInformation {
|
||||
do {
|
||||
HBasicBlock current = workQueue.removeLast();
|
||||
addBlock(current, workQueue);
|
||||
} while (!workQueue.isEmpty);
|
||||
} while (workQueue.isNotEmpty);
|
||||
}
|
||||
|
||||
// Adds a block and transitively all its predecessors in the loop as
|
||||
@@ -4330,7 +4341,7 @@ class HSwitchBlockInformation implements HStatementInformation {
|
||||
@override
|
||||
HBasicBlock get end {
|
||||
// We don't create a switch block if there are no cases.
|
||||
assert(!statements.isEmpty);
|
||||
assert(statements.isNotEmpty);
|
||||
return statements.last.end;
|
||||
}
|
||||
|
||||
@@ -4352,7 +4363,7 @@ class HIsTest extends HInstruction {
|
||||
|
||||
HIsTest(this.dartType, this.checkedAbstractValue, super.rti, super.checked,
|
||||
super.instructionType)
|
||||
: super._2() {
|
||||
: super._twoInputs() {
|
||||
setUseGvn();
|
||||
}
|
||||
|
||||
@@ -4390,7 +4401,7 @@ class HIsTestSimple extends HInstruction {
|
||||
|
||||
HIsTestSimple(this.dartType, this.checkedAbstractValue, this.specialization,
|
||||
super.checked, super.type)
|
||||
: super._1() {
|
||||
: super._oneInput() {
|
||||
setUseGvn();
|
||||
}
|
||||
|
||||
@@ -4541,7 +4552,7 @@ class HAsCheck extends HCheck {
|
||||
|
||||
HAsCheck(this.checkedType, this.checkedTypeExpression, this.isTypeError,
|
||||
super.rti, super.checked, super.instructionType)
|
||||
: super._2();
|
||||
: super._twoInputs();
|
||||
|
||||
// The type input is first to facilitate the `type.as(value)` codegen pattern.
|
||||
HInstruction get typeInput => inputs[0];
|
||||
@@ -4588,7 +4599,7 @@ class HAsCheckSimple extends HCheck {
|
||||
|
||||
HAsCheckSimple(super.checked, this.dartType, this.checkedType,
|
||||
this.isTypeError, this.method, super.type)
|
||||
: super._1();
|
||||
: super._oneInput();
|
||||
|
||||
@override
|
||||
HInstruction get checkedInput => inputs[0];
|
||||
@@ -4624,7 +4635,8 @@ class HAsCheckSimple extends HCheck {
|
||||
|
||||
/// Subtype check comparing two Rti types.
|
||||
class HSubtypeCheck extends HCheck {
|
||||
HSubtypeCheck(super.subtype, super.supertype, super.type) : super._2() {
|
||||
HSubtypeCheck(super.subtype, super.supertype, super.type)
|
||||
: super._twoInputs() {
|
||||
setUseGvn();
|
||||
}
|
||||
|
||||
@@ -4653,7 +4665,7 @@ abstract interface class HRtiInstruction {}
|
||||
class HLoadType extends HInstruction implements HRtiInstruction {
|
||||
TypeRecipe typeExpression;
|
||||
|
||||
HLoadType(this.typeExpression, super.instructionType) : super._0() {
|
||||
HLoadType(this.typeExpression, super.instructionType) : super._noInput() {
|
||||
setUseGvn();
|
||||
}
|
||||
|
||||
@@ -4682,11 +4694,11 @@ class HLoadType extends HInstruction implements HRtiInstruction {
|
||||
///
|
||||
/// Classes with reified type arguments have the type environment stored on the
|
||||
/// instance. The reified environment is typically stored as the instance type,
|
||||
/// e.g. "UnmodifiableListView<int>".
|
||||
/// e.g. `UnmodifiableListView<int>`.
|
||||
class HInstanceEnvironment extends HInstruction implements HRtiInstruction {
|
||||
late AbstractValue codegenInputType; // Assigned in SsaTypeKnownRemover
|
||||
|
||||
HInstanceEnvironment(super.instance, super.type) : super._1() {
|
||||
HInstanceEnvironment(super.instance, super.type) : super._oneInput() {
|
||||
setUseGvn();
|
||||
}
|
||||
|
||||
@@ -4713,7 +4725,7 @@ class HTypeEval extends HInstruction implements HRtiInstruction {
|
||||
|
||||
HTypeEval(
|
||||
super.environment, this.envStructure, this.typeExpression, super.type)
|
||||
: super._1() {
|
||||
: super._oneInput() {
|
||||
setUseGvn();
|
||||
}
|
||||
|
||||
@@ -4738,7 +4750,8 @@ class HTypeEval extends HInstruction implements HRtiInstruction {
|
||||
|
||||
/// Extends an Rti type environment with generic function types.
|
||||
class HTypeBind extends HInstruction implements HRtiInstruction {
|
||||
HTypeBind(super.environment, super.typeArguments, super.type) : super._2() {
|
||||
HTypeBind(super.environment, super.typeArguments, super.type)
|
||||
: super._twoInputs() {
|
||||
setUseGvn();
|
||||
}
|
||||
|
||||
@@ -4891,7 +4904,7 @@ class HArrayFlagsSet extends HInstruction
|
||||
}
|
||||
|
||||
class HIsLateSentinel extends HInstruction {
|
||||
HIsLateSentinel(super.value, super.type) : super._1() {
|
||||
HIsLateSentinel(super.value, super.type) : super._oneInput() {
|
||||
setUseGvn();
|
||||
}
|
||||
|
||||
|
||||
@@ -1234,11 +1234,6 @@ class SsaInstructionSimplifier extends HBaseVisitor<HInstruction>
|
||||
return node;
|
||||
}
|
||||
|
||||
@override
|
||||
HInstruction visitRelational(HRelational node) {
|
||||
return super.visitRelational(node);
|
||||
}
|
||||
|
||||
HInstruction? handleIdentityCheck(HRelational node) {
|
||||
HInstruction left = node.left;
|
||||
HInstruction right = node.right;
|
||||
@@ -2055,13 +2050,13 @@ class SsaInstructionSimplifier extends HBaseVisitor<HInstruction>
|
||||
final left = node.left;
|
||||
final right = node.right;
|
||||
StringConstantValue? leftString = getString(left);
|
||||
if (leftString != null && leftString.stringValue.length == 0) {
|
||||
if (leftString != null && leftString.stringValue.isEmpty) {
|
||||
return right;
|
||||
}
|
||||
|
||||
final rightString = getString(right);
|
||||
if (rightString == null) return node;
|
||||
if (rightString.stringValue.length == 0) return left;
|
||||
if (rightString.stringValue.isEmpty) return left;
|
||||
|
||||
HInstruction? prefix;
|
||||
if (leftString == null) {
|
||||
@@ -2398,7 +2393,7 @@ class SsaInstructionSimplifier extends HBaseVisitor<HInstruction>
|
||||
}
|
||||
InterfaceType instanceType =
|
||||
_closedWorld.elementEnvironment.getThisType(instance.element);
|
||||
if (instanceType.typeArguments.length == 0) {
|
||||
if (instanceType.typeArguments.isEmpty) {
|
||||
instance.instantiatedTypes?.forEach(_registry.registerInstantiation);
|
||||
return HLoadType.type(instanceType, instance.instructionType);
|
||||
}
|
||||
@@ -2902,7 +2897,7 @@ class SsaDeadCodeEliminator extends HGraphVisitor implements OptimizationPhase {
|
||||
}
|
||||
|
||||
bool isDeadCode(HInstruction instruction) {
|
||||
if (!instruction.usedBy.isEmpty) return false;
|
||||
if (instruction.usedBy.isNotEmpty) return false;
|
||||
if (isTrivialDeadStore(instruction)) return true;
|
||||
if (instruction.sideEffects.hasSideEffects()) return false;
|
||||
if (instruction.canThrow(_abstractValueDomain)) {
|
||||
@@ -3164,7 +3159,7 @@ class SsaLiveBlockAnalyzer extends HBaseVisitor<void> {
|
||||
|
||||
void analyze() {
|
||||
markBlockLive(graph.entry);
|
||||
while (!worklist.isEmpty) {
|
||||
while (worklist.isNotEmpty) {
|
||||
HBasicBlock live = worklist.removeLast();
|
||||
live.last!.accept(this);
|
||||
}
|
||||
@@ -3259,7 +3254,7 @@ class SsaDeadPhiEliminator implements OptimizationPhase {
|
||||
}
|
||||
|
||||
// Process the worklist by propagating liveness to phi inputs.
|
||||
while (!worklist.isEmpty) {
|
||||
while (worklist.isNotEmpty) {
|
||||
HPhi phi = worklist.removeLast();
|
||||
for (final input in phi.inputs) {
|
||||
if (input is HPhi && !livePhis.contains(input)) {
|
||||
@@ -3312,7 +3307,7 @@ class SsaRedundantPhiEliminator implements OptimizationPhase {
|
||||
block.forEachPhi((HPhi phi) => worklist.add(phi));
|
||||
}
|
||||
|
||||
while (!worklist.isEmpty) {
|
||||
while (worklist.isNotEmpty) {
|
||||
HPhi phi = worklist.removeLast();
|
||||
|
||||
// If the phi has already been processed, continue.
|
||||
@@ -3382,7 +3377,7 @@ class SsaGlobalValueNumberer implements OptimizationPhase {
|
||||
do {
|
||||
GvnWorkItem item = workQueue.removeLast();
|
||||
visitBasicBlock(item.block, item.valueSet, workQueue);
|
||||
} while (!workQueue.isEmpty);
|
||||
} while (workQueue.isNotEmpty);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -3422,7 +3417,7 @@ class SsaGlobalValueNumberer implements OptimizationPhase {
|
||||
bool firstInstructionInLoop = block == loopHeader
|
||||
// Compensate for lack of code motion.
|
||||
||
|
||||
(blockChangesFlags[loopHeader.id] == 0 &&
|
||||
(blockChangesFlags[loopHeader.id].isEmpty &&
|
||||
isLoopAlwaysTaken() &&
|
||||
loopHeader.successors[0] == block);
|
||||
while (instruction != null) {
|
||||
@@ -3474,7 +3469,7 @@ class SsaGlobalValueNumberer implements OptimizationPhase {
|
||||
while (instruction != null) {
|
||||
final next = instruction.next;
|
||||
final flags = instruction.sideEffects.getChangesFlags();
|
||||
assert(flags == 0 || !instruction.useGvn());
|
||||
assert(flags.isEmpty || !instruction.useGvn());
|
||||
// TODO(sra): Is the above assertion too strong? We should be able to
|
||||
// reuse the values generated by idempotent operations that have
|
||||
// effects. Would it be correct to make the kill below be conditional on
|
||||
@@ -3512,7 +3507,7 @@ class SsaGlobalValueNumberer implements OptimizationPhase {
|
||||
HBasicBlock current = workQueue.removeLast();
|
||||
changesFlags = changesFlags.union(
|
||||
getChangesFlagsForDominatedBlock(block, current, workQueue));
|
||||
} while (!workQueue.isEmpty);
|
||||
} while (workQueue.isNotEmpty);
|
||||
successorValues.kill(changesFlags);
|
||||
}
|
||||
workQueue.add(GvnWorkItem(dominated, successorValues));
|
||||
@@ -4551,7 +4546,9 @@ class MemorySet {
|
||||
}
|
||||
if (use is HInvokeStatic) {
|
||||
if (closedWorld.commonElements
|
||||
.isCheckConcurrentModificationError(use.element)) return true;
|
||||
.isCheckConcurrentModificationError(use.element)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
library ssa.tracer;
|
||||
|
||||
import '../../compiler_api.dart' as api show OutputSink;
|
||||
import '../diagnostics/invariant.dart' show DEBUG_MODE;
|
||||
import '../diagnostics/invariant.dart' show debugMode;
|
||||
import '../inferrer/abstract_value_domain.dart';
|
||||
import '../js_backend/namer.dart' show suffixForGetInterceptor;
|
||||
import '../js_model/js_world.dart' show JClosedWorld;
|
||||
@@ -23,7 +23,7 @@ class HTracer extends HGraphVisitor with TracerUtil {
|
||||
HTracer(this.output, this.closedWorld);
|
||||
|
||||
void traceGraph(String name, HGraph graph) {
|
||||
DEBUG_MODE = true;
|
||||
debugMode = true;
|
||||
tag("cfg", () {
|
||||
printProperty("name", name);
|
||||
visitDominatorTree(graph);
|
||||
@@ -31,7 +31,7 @@ class HTracer extends HGraphVisitor with TracerUtil {
|
||||
}
|
||||
|
||||
void traceJavaScriptText(String name, String data) {
|
||||
DEBUG_MODE = true;
|
||||
debugMode = true;
|
||||
tag("cfg", () {
|
||||
printProperty("name", name);
|
||||
// Emit a fake basic block, with one 'instruction' per line of text.
|
||||
|
||||
@@ -107,7 +107,7 @@ class SsaTypePropagator extends HBaseVisitor<AbstractValue>
|
||||
|
||||
void processWorklist() {
|
||||
do {
|
||||
while (!worklist.isEmpty) {
|
||||
while (worklist.isNotEmpty) {
|
||||
int id = worklist.removeLast();
|
||||
HInstruction instruction = workmap[id]!;
|
||||
workmap.remove(id);
|
||||
@@ -120,7 +120,7 @@ class SsaTypePropagator extends HBaseVisitor<AbstractValue>
|
||||
// replaced operands, so we may need to take another stab at
|
||||
// emptying the worklist afterwards.
|
||||
processPendingOptimizations();
|
||||
} while (!worklist.isEmpty);
|
||||
} while (worklist.isNotEmpty);
|
||||
}
|
||||
|
||||
void addToWorkList(HInstruction instruction) {
|
||||
|
||||
@@ -59,7 +59,7 @@ class HValidator extends HInstructionVisitor {
|
||||
markInvalid("Return or throw node with > 1 successor "
|
||||
"or not going to exit-block");
|
||||
}
|
||||
if (block.last is HExit && !block.successors.isEmpty) {
|
||||
if (block.last is HExit && block.successors.isNotEmpty) {
|
||||
markInvalid("Exit block with successor");
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import '../tracer.dart';
|
||||
import 'nodes.dart';
|
||||
import 'optimize.dart' show OptimizationPhase, SsaOptimizerTask;
|
||||
|
||||
bool _DEBUG = false;
|
||||
bool _debug = false;
|
||||
|
||||
class ValueRangeInfo {
|
||||
late final IntValue intZero;
|
||||
@@ -332,6 +332,9 @@ class MarkerValue extends VariableValue {
|
||||
|
||||
MarkerValue(this.isLower, this.isPositive, super.info);
|
||||
|
||||
@override
|
||||
int get hashCode => isLower.hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(other) {
|
||||
return other is MarkerValue && isLower == other.isLower;
|
||||
@@ -606,20 +609,22 @@ class Range {
|
||||
// If we could not compute max or min, pick a value in the two
|
||||
// ranges, with priority to [IntValue]s because they are simpler.
|
||||
if (low == info.unknownValue) {
|
||||
if (lower is IntValue)
|
||||
if (lower is IntValue) {
|
||||
low = lower;
|
||||
else if (other.lower is IntValue)
|
||||
} else if (other.lower is IntValue) {
|
||||
low = other.lower;
|
||||
else
|
||||
} else {
|
||||
low = lower;
|
||||
}
|
||||
}
|
||||
if (up == info.unknownValue) {
|
||||
if (upper is IntValue)
|
||||
if (upper is IntValue) {
|
||||
up = upper;
|
||||
else if (other.upper is IntValue)
|
||||
} else if (other.upper is IntValue) {
|
||||
up = other.upper;
|
||||
else
|
||||
} else {
|
||||
up = upper;
|
||||
}
|
||||
}
|
||||
return info.newNormalizedRange(low, up);
|
||||
}
|
||||
@@ -1081,8 +1086,9 @@ class SsaValueRangeAnalyzer extends HBaseVisitor<Range>
|
||||
|
||||
@override
|
||||
Range visitInvokeDynamicMethod(HInvokeDynamicMethod invoke) {
|
||||
if ((invoke.inputs.length == 3) && (invoke.selector.name == "%"))
|
||||
if ((invoke.inputs.length == 3) && (invoke.selector.name == "%")) {
|
||||
return handleInvokeModulo(invoke);
|
||||
}
|
||||
return super.visitInvokeDynamicMethod(invoke);
|
||||
}
|
||||
|
||||
@@ -1329,7 +1335,7 @@ class LoopUpdateRecognizer extends HBaseVisitor<Range?> {
|
||||
final widened = updateRange.replaceMarkers(lowerBound, upperBound);
|
||||
final result = startRange.union(widened);
|
||||
|
||||
if (_DEBUG) {
|
||||
if (_debug) {
|
||||
print('------- ${loopPhi.sourceElement}'
|
||||
'\n marker $markerRange'
|
||||
'\n update $updateRange'
|
||||
|
||||
@@ -164,4 +164,8 @@ class ValueSetNode {
|
||||
int get hashCode => hash;
|
||||
ValueSetNode? next;
|
||||
ValueSetNode(this.value, this.hash, this.next);
|
||||
|
||||
@override
|
||||
bool operator ==(other) =>
|
||||
identical(this, other) || other is ValueSetNode && hash == other.hash;
|
||||
}
|
||||
|
||||
@@ -62,7 +62,9 @@ class LiveInterval {
|
||||
@override
|
||||
String toString() {
|
||||
List<String> res = [];
|
||||
for (final interval in ranges) res.add(interval.toString());
|
||||
for (final interval in ranges) {
|
||||
res.add(interval.toString());
|
||||
}
|
||||
return '(${res.join(", ")})';
|
||||
}
|
||||
}
|
||||
@@ -474,12 +476,14 @@ class VariableNamer {
|
||||
}
|
||||
|
||||
String allocateTemporary() {
|
||||
while (!freeTemporaryNames.isEmpty) {
|
||||
while (freeTemporaryNames.isNotEmpty) {
|
||||
String name = freeTemporaryNames.removeLast();
|
||||
if (!usedNames.contains(name)) return name;
|
||||
}
|
||||
String name = 't${temporaryIndex++}';
|
||||
while (usedNames.contains(name)) name = 't${temporaryIndex++}';
|
||||
while (usedNames.contains(name)) {
|
||||
name = 't${temporaryIndex++}';
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
@@ -653,7 +657,9 @@ class SsaVariableAllocator extends HBaseVisitor<void> implements CodegenPhase {
|
||||
// A [HTypeKnown] instruction never has a name, but its checked
|
||||
// input might, therefore we need to do a copy instead of an
|
||||
// assignment.
|
||||
while (input is HTypeKnown) input = input.inputs[0];
|
||||
while (input is HTypeKnown) {
|
||||
input = input.inputs[0];
|
||||
}
|
||||
if (!needsName(input)) {
|
||||
names.addAssignment(predecessor, input, phi);
|
||||
} else {
|
||||
|
||||
@@ -12,7 +12,7 @@ import 'options.dart' show CompilerOptions;
|
||||
import 'ssa/nodes.dart' as ssa show HGraph;
|
||||
import 'ssa/tracer.dart' show HTracer;
|
||||
|
||||
String? TRACE_FILTER_PATTERN_FOR_TEST;
|
||||
String? traceFilterPatternForTest;
|
||||
|
||||
/// Dumps the intermediate representation after each phase in a format
|
||||
/// readable by IR Hydra.
|
||||
@@ -27,7 +27,7 @@ class Tracer with TracerUtil {
|
||||
|
||||
factory Tracer(JClosedWorld closedWorld, CompilerOptions options,
|
||||
api.CompilerOutput compilerOutput) {
|
||||
String? pattern = options.dumpSsaPattern ?? TRACE_FILTER_PATTERN_FOR_TEST;
|
||||
String? pattern = options.dumpSsaPattern ?? traceFilterPatternForTest;
|
||||
if (pattern == null) return Tracer._(closedWorld, null, null);
|
||||
var traceFilter = RegExp(pattern);
|
||||
var output =
|
||||
|
||||
@@ -200,8 +200,9 @@ class CallStructure {
|
||||
if (positionalArgumentCount > requiredParameterCount) return false;
|
||||
assert(positionalArgumentCount == requiredParameterCount);
|
||||
if (namedArgumentCount >
|
||||
optionalParameterCount + parameters.requiredNamedParameters.length)
|
||||
optionalParameterCount + parameters.requiredNamedParameters.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int nameIndex = 0;
|
||||
List<String> namedParameters = parameters.namedParameters;
|
||||
@@ -213,8 +214,9 @@ class CallStructure {
|
||||
while (nameIndex < namedParameters.length) {
|
||||
String parameterName = namedParameters[nameIndex];
|
||||
if (name == parameterName) {
|
||||
if (parameters.requiredNamedParameters.contains(name))
|
||||
if (parameters.requiredNamedParameters.contains(name)) {
|
||||
seenRequiredNamedParameters++;
|
||||
}
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -201,12 +201,12 @@ class ClassHierarchyImpl implements ClassHierarchy {
|
||||
node.forEachSubclass((ClassEntity cls) {
|
||||
getClassHierarchyNode(cls).writeToDataSink(sink);
|
||||
return IterationStep.CONTINUE;
|
||||
}, ClassHierarchyNode.ALL);
|
||||
}, ClassHierarchyNode.all);
|
||||
ClassSet set = getClassSet(_commonElements.objectClass);
|
||||
set.forEachSubclass((ClassEntity cls) {
|
||||
getClassSet(cls).writeToDataSink(sink);
|
||||
return IterationStep.CONTINUE;
|
||||
}, ClassHierarchyNode.ALL);
|
||||
}, ClassHierarchyNode.all);
|
||||
sink.end(tag);
|
||||
}
|
||||
|
||||
@@ -262,7 +262,7 @@ class ClassHierarchyImpl implements ClassHierarchy {
|
||||
ClassHierarchyNode? hierarchy = _classHierarchyNodes[cls];
|
||||
if (hierarchy == null) return const [];
|
||||
return hierarchy
|
||||
.subclassesByMask(ClassHierarchyNode.EXPLICITLY_INSTANTIATED);
|
||||
.subclassesByMask(ClassHierarchyNode.explicitlyInstantiated);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -270,7 +270,7 @@ class ClassHierarchyImpl implements ClassHierarchy {
|
||||
ClassHierarchyNode? subclasses = _classHierarchyNodes[cls];
|
||||
if (subclasses == null) return const [];
|
||||
return subclasses.subclassesByMask(
|
||||
ClassHierarchyNode.EXPLICITLY_INSTANTIATED,
|
||||
ClassHierarchyNode.explicitlyInstantiated,
|
||||
strict: true);
|
||||
}
|
||||
|
||||
@@ -286,7 +286,7 @@ class ClassHierarchyImpl implements ClassHierarchy {
|
||||
ClassEntity cls, IterationStep f(ClassEntity cls)) {
|
||||
ClassHierarchyNode? subclasses = _classHierarchyNodes[cls];
|
||||
if (subclasses == null) return;
|
||||
subclasses.forEachSubclass(f, ClassHierarchyNode.EXPLICITLY_INSTANTIATED,
|
||||
subclasses.forEachSubclass(f, ClassHierarchyNode.explicitlyInstantiated,
|
||||
strict: true);
|
||||
}
|
||||
|
||||
@@ -295,7 +295,7 @@ class ClassHierarchyImpl implements ClassHierarchy {
|
||||
ClassHierarchyNode? subclasses = _classHierarchyNodes[cls];
|
||||
if (subclasses == null) return false;
|
||||
return subclasses.anySubclass(
|
||||
predicate, ClassHierarchyNode.EXPLICITLY_INSTANTIATED,
|
||||
predicate, ClassHierarchyNode.explicitlyInstantiated,
|
||||
strict: true);
|
||||
}
|
||||
|
||||
@@ -305,8 +305,7 @@ class ClassHierarchyImpl implements ClassHierarchy {
|
||||
if (classSet == null) {
|
||||
return const [];
|
||||
} else {
|
||||
return classSet
|
||||
.subtypesByMask(ClassHierarchyNode.EXPLICITLY_INSTANTIATED);
|
||||
return classSet.subtypesByMask(ClassHierarchyNode.explicitlyInstantiated);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -316,7 +315,7 @@ class ClassHierarchyImpl implements ClassHierarchy {
|
||||
if (classSet == null) {
|
||||
return const [];
|
||||
} else {
|
||||
return classSet.subtypesByMask(ClassHierarchyNode.EXPLICITLY_INSTANTIATED,
|
||||
return classSet.subtypesByMask(ClassHierarchyNode.explicitlyInstantiated,
|
||||
strict: true);
|
||||
}
|
||||
}
|
||||
@@ -327,7 +326,7 @@ class ClassHierarchyImpl implements ClassHierarchy {
|
||||
if (classSet == null) {
|
||||
return const [];
|
||||
} else {
|
||||
return classSet.subtypesByMask(ClassHierarchyNode.ALL);
|
||||
return classSet.subtypesByMask(ClassHierarchyNode.all);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -343,7 +342,7 @@ class ClassHierarchyImpl implements ClassHierarchy {
|
||||
ClassEntity cls, IterationStep f(ClassEntity cls)) {
|
||||
ClassSet? classSet = _classSets[cls];
|
||||
if (classSet == null) return;
|
||||
classSet.forEachSubtype(f, ClassHierarchyNode.EXPLICITLY_INSTANTIATED,
|
||||
classSet.forEachSubtype(f, ClassHierarchyNode.explicitlyInstantiated,
|
||||
strict: true);
|
||||
}
|
||||
|
||||
@@ -352,7 +351,7 @@ class ClassHierarchyImpl implements ClassHierarchy {
|
||||
ClassSet? classSet = _classSets[cls];
|
||||
if (classSet == null) return false;
|
||||
return classSet.anySubtype(
|
||||
predicate, ClassHierarchyNode.EXPLICITLY_INSTANTIATED,
|
||||
predicate, ClassHierarchyNode.explicitlyInstantiated,
|
||||
strict: true);
|
||||
}
|
||||
|
||||
@@ -779,11 +778,11 @@ class _InheritedInThisClassCache {
|
||||
if (_inheritingClasses == null) {
|
||||
_inheritingClasses = {};
|
||||
_inheritingClasses!.addAll(memberHoldingClassNode
|
||||
.subclassesByMask(ClassHierarchyNode.ALL, strict: false));
|
||||
.subclassesByMask(ClassHierarchyNode.all, strict: false));
|
||||
for (ClassHierarchyNode mixinApplication
|
||||
in builder._classSets[memberHoldingClass]!.mixinApplicationNodes) {
|
||||
_inheritingClasses!.addAll(mixinApplication
|
||||
.subclassesByMask(ClassHierarchyNode.ALL, strict: false));
|
||||
.subclassesByMask(ClassHierarchyNode.all, strict: false));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -861,7 +860,7 @@ class _InheritedInSubtypeCache {
|
||||
classes.add(z);
|
||||
}
|
||||
return IterationStep.CONTINUE;
|
||||
}, ClassHierarchyNode.ALL, strict: strict);
|
||||
}, ClassHierarchyNode.all, strict: strict);
|
||||
}
|
||||
|
||||
// A subclasses of [x] that implement [y].
|
||||
|
||||
@@ -51,7 +51,7 @@ class ClassHierarchyNode {
|
||||
/// Enum set for selecting instantiated classes in
|
||||
/// [ClassHierarchyNode.subclassesByMask],
|
||||
/// [ClassHierarchyNode.subclassesByMask] and [ClassSet.subtypesByMask].
|
||||
static final EnumSet<Instantiation> INSTANTIATED = EnumSet.fromValues(const [
|
||||
static final EnumSet<Instantiation> instantiated = EnumSet.fromValues(const [
|
||||
Instantiation.DIRECTLY_INSTANTIATED,
|
||||
Instantiation.INDIRECTLY_INSTANTIATED,
|
||||
Instantiation.ABSTRACTLY_INSTANTIATED,
|
||||
@@ -60,7 +60,7 @@ class ClassHierarchyNode {
|
||||
/// Enum set for selecting directly and abstractly instantiated classes in
|
||||
/// [ClassHierarchyNode.subclassesByMask],
|
||||
/// [ClassHierarchyNode.subclassesByMask] and [ClassSet.subtypesByMask].
|
||||
static final EnumSet<Instantiation> EXPLICITLY_INSTANTIATED =
|
||||
static final EnumSet<Instantiation> explicitlyInstantiated =
|
||||
EnumSet.fromValues(const [
|
||||
Instantiation.DIRECTLY_INSTANTIATED,
|
||||
Instantiation.ABSTRACTLY_INSTANTIATED,
|
||||
@@ -69,7 +69,7 @@ class ClassHierarchyNode {
|
||||
/// Enum set for selecting all classes in
|
||||
/// [ClassHierarchyNode.subclassesByMask],
|
||||
/// [ClassHierarchyNode.subclassesByMask] and [ClassSet.subtypesByMask].
|
||||
static final EnumSet<Instantiation> ALL =
|
||||
static final EnumSet<Instantiation> all =
|
||||
EnumSet.allValues(Instantiation.values);
|
||||
|
||||
/// Creates an enum set for selecting the returned classes in
|
||||
@@ -404,7 +404,7 @@ class ClassHierarchyNode {
|
||||
continue;
|
||||
}
|
||||
if (withRespectTo != null &&
|
||||
!child.anySubclass(isRelatedTo, ClassHierarchyNode.ALL)) {
|
||||
!child.anySubclass(isRelatedTo, ClassHierarchyNode.all)) {
|
||||
continue;
|
||||
}
|
||||
if (needsComma) {
|
||||
@@ -655,7 +655,7 @@ class ClassSet {
|
||||
return node.subclassesByMask(mask, strict: strict);
|
||||
}
|
||||
|
||||
return SubtypesIterable.SubtypesIterator(this, mask, includeRoot: !strict);
|
||||
return SubtypesIterable.subtypesIterator(this, mask, includeRoot: !strict);
|
||||
}
|
||||
|
||||
/// Applies [predicate] to each subclass of [cls] matching the criteria
|
||||
@@ -951,7 +951,7 @@ class SubtypesIterable extends IterableBase<ClassEntity> {
|
||||
final EnumSet<Instantiation> mask;
|
||||
final bool includeRoot;
|
||||
|
||||
SubtypesIterable.SubtypesIterator(this.subtypeSet, this.mask,
|
||||
SubtypesIterable.subtypesIterator(this.subtypeSet, this.mask,
|
||||
{this.includeRoot = true});
|
||||
|
||||
@override
|
||||
|
||||
@@ -154,7 +154,7 @@ class FunctionSetNode {
|
||||
final set = elements as Set<MemberEntity>;
|
||||
set.add(element);
|
||||
}
|
||||
if (!cache.isEmpty) cache.clear();
|
||||
if (cache.isNotEmpty) cache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,14 +167,14 @@ class FunctionSetNode {
|
||||
if (index != list.length) {
|
||||
list[index] = last;
|
||||
}
|
||||
if (!cache.isEmpty) cache.clear();
|
||||
if (cache.isNotEmpty) cache.clear();
|
||||
} else {
|
||||
final set = elements as List<MemberEntity>;
|
||||
if (set.remove(element)) {
|
||||
// To avoid wobbling between the two representations, we do
|
||||
// not transition back to the list representation even if we
|
||||
// end up with few enough elements at this point.
|
||||
if (!cache.isEmpty) cache.clear();
|
||||
if (cache.isNotEmpty) cache.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -214,7 +214,7 @@ class FunctionSetNode {
|
||||
// have been provided.
|
||||
FunctionSetQuery noSuchMethodQuery =
|
||||
noSuchMethods.query(noSuchMethodMask!, domain);
|
||||
if (!noSuchMethodQuery.functions.isEmpty) {
|
||||
if (noSuchMethodQuery.functions.isNotEmpty) {
|
||||
functions ??= Setlet();
|
||||
functions.addAll(noSuchMethodQuery.functions);
|
||||
}
|
||||
|
||||
@@ -398,7 +398,7 @@ class MemberHierarchyBuilder {
|
||||
final override = elementEnv.lookupClassMember(subtype, name);
|
||||
if (override != null) addParent(override, member);
|
||||
return IterationStep.CONTINUE;
|
||||
}, ClassHierarchyNode.INSTANTIATED, strict: true);
|
||||
}, ClassHierarchyNode.instantiated, strict: true);
|
||||
|
||||
if (!foundSuperclass) {
|
||||
(_dynamicRoots[selector] ??= Setlet()).add(member);
|
||||
|
||||
@@ -747,7 +747,7 @@ class ParameterUsage {
|
||||
_parameterStructure.requiredPositionalParameters
|
||||
? null
|
||||
: 0;
|
||||
if (!_parameterStructure.namedParameters.isEmpty) {
|
||||
if (_parameterStructure.namedParameters.isNotEmpty) {
|
||||
_unprovidedNamedParameters =
|
||||
Set<String>.from(_parameterStructure.namedParameters);
|
||||
}
|
||||
|
||||
@@ -43,6 +43,10 @@ class Selector {
|
||||
@override
|
||||
final int hashCode;
|
||||
|
||||
@override
|
||||
bool operator ==(other) =>
|
||||
identical(this, other) || other is Selector && hashCode == other.hashCode;
|
||||
|
||||
int get argumentCount => callStructure.argumentCount;
|
||||
int get namedArgumentCount => callStructure.namedArgumentCount;
|
||||
int get positionalArgumentCount => callStructure.positionalArgumentCount;
|
||||
@@ -253,7 +257,9 @@ class Selector {
|
||||
(name == "hashCode" ||
|
||||
name == "runtimeType" ||
|
||||
name == "toString" ||
|
||||
name == "noSuchMethod")) return true;
|
||||
name == "noSuchMethod")) {
|
||||
return true;
|
||||
}
|
||||
// Calling toString always succeeds, calls to `noSuchMethod` (even well
|
||||
// formed calls) always throw.
|
||||
if (isCall &&
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user