Version 2.0.0-dev.47.0
Merge commit 'a86b864fa9b113f5cc4669dc3959d3b7c9761922' into dev
diff --git a/.gitattributes b/.gitattributes
index 631de6a..8f4b8ba 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -14,6 +14,7 @@
*.yaml text
# Files that should not be converted.
+tests/compiler/dart2js_extra/eof_line_ending_test.dart -text
tests/compiler/dart2js_extra/string_interpolation_test.dart -text
tests/compiler/dart2js_extra/string_interpolation_dynamic_test.dart -text
tests/compiler/dart2js_extra/literal_string_juxtaposition_test.dart -text
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
new file mode 100644
index 0000000..d8c2687
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE.md
@@ -0,0 +1,21 @@
+Thank you for taking the time to file an issue!
+
+In order to route, prioritize, and act on this, please include:
+
+* Dart SDK Version (`dart --version`)
+* Whether you are using Windows, MacOSX, or Linux (if applicable)
+* Whether you are using Chrome, Safari, Firefox, Edge (if applicable)
+
+Missing some or all of the above might make the issue take longer or be
+impossible to act on.
+
+----
+
+Is it really an issue? For general questions consider starting with Stack
+Overflow:
+https://stackoverflow.com/questions/tagged/dart
+
+Also consider our Gitter channel for light-weight/quick discussions:
+https://gitter.im/dart-lang/sdk
+
+-----
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 46c72ce..4d96f13 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,7 +1,37 @@
+## 2.0.0-dev.47.0
+
+### Tool Changes
+
+#### Analyzer
+
+* The command line analyzer (dartanalyzer) and the analysis server no longer
+ treat directories named `packages` specially. Previously they had ignored
+ these directories - and their contents - from the point of view of analysis. Now
+ they'll be treated just as regular directories. This special-casing of
+ `packages` directories was to support using symlinks for package: resolution;
+ that functionality is now handled by `.packages` files.
+
## 2.0.0-dev.46.0
## 2.0.0-dev.45.0
+### Core library changes
+
+* `dart:async`
+ * Removed the deprecated `defaultValue` parameter on `Stream.firstWhere` and
+ `Stream.lastWhere`.
+
+### Tool Changes
+
+#### Pub
+
+* Fix a bug where the version solver could loop infinitely when resolving a
+ conflict involving pre-release constraints ([issue 1863][pub#1863]).
+
+[pub#1863]: https://github.com/dart-lang/pub/issues/1863
+
+## 2.0.0-dev.45.0
+
### Tool Changes
#### Pub
@@ -11,6 +41,7 @@
[pub#1856]: https://github.com/dart-lang/pub/issues/1856
+
## 2.0.0-dev.44.0
### Tool Changes
diff --git a/DEPS b/DEPS
index fcef030..ebe2a9d 100644
--- a/DEPS
+++ b/DEPS
@@ -67,7 +67,7 @@
"convert_tag": "@2.0.1",
"crypto_tag" : "@2.0.2+1",
"csslib_tag" : "@0.14.1",
- "dart2js_info_tag" : "@0.5.5+1",
+ "dart2js_info_tag" : "@0.5.6",
# Note: updates to dart_style have to be coordinated carefully with
# the infrastructure-team so that the internal formatter in
@@ -99,7 +99,7 @@
"isolate_tag": "@1.1.0",
"jinja2_rev": "@2222b31554f03e62600cd7e383376a7c187967a1",
"json_rpc_2_tag": "@2.0.6",
- "linter_tag": "@0.1.46",
+ "linter_tag": "@0.1.47",
"logging_tag": "@0.11.3+1",
"markdown_tag": "@1.1.1",
"matcher_tag": "@0.12.1+4",
@@ -116,7 +116,7 @@
"pool_tag": "@1.3.4",
"protobuf_tag": "@0.7.1",
"pub_rev": "@4947e0b3cb3ec77e4e8fe0d3141ce4dc60f43256",
- "pub_semver_tag": "@1.3.4",
+ "pub_semver_tag": "@1.3.6",
"quiver_tag": "@5aaa3f58c48608af5b027444d561270b53f15dbf",
"resource_rev":"@af5a5bf65511943398146cf146e466e5f0b95cb9",
"root_certificates_rev": "@16ef64be64c7dfdff2b9f4b910726e635ccc519e",
diff --git a/pkg/analysis_server/lib/protocol/protocol_constants.dart b/pkg/analysis_server/lib/protocol/protocol_constants.dart
index d7651ac..148fc49 100644
--- a/pkg/analysis_server/lib/protocol/protocol_constants.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_constants.dart
@@ -211,8 +211,17 @@
const String FLUTTER_NOTIFICATION_OUTLINE_INSTRUMENTED_CODE =
'instrumentedCode';
const String FLUTTER_NOTIFICATION_OUTLINE_OUTLINE = 'outline';
+const String FLUTTER_REQUEST_GET_CHANGE_ADD_FOR_DESIGN_TIME_CONSTRUCTOR =
+ 'flutter.getChangeAddForDesignTimeConstructor';
+const String FLUTTER_REQUEST_GET_CHANGE_ADD_FOR_DESIGN_TIME_CONSTRUCTOR_FILE =
+ 'file';
+const String FLUTTER_REQUEST_GET_CHANGE_ADD_FOR_DESIGN_TIME_CONSTRUCTOR_OFFSET =
+ 'offset';
const String FLUTTER_REQUEST_SET_SUBSCRIPTIONS = 'flutter.setSubscriptions';
const String FLUTTER_REQUEST_SET_SUBSCRIPTIONS_SUBSCRIPTIONS = 'subscriptions';
+const String
+ FLUTTER_RESPONSE_GET_CHANGE_ADD_FOR_DESIGN_TIME_CONSTRUCTOR_CHANGE =
+ 'change';
const String KYTHE_REQUEST_GET_KYTHE_ENTRIES = 'kythe.getKytheEntries';
const String KYTHE_REQUEST_GET_KYTHE_ENTRIES_FILE = 'file';
const String KYTHE_RESPONSE_GET_KYTHE_ENTRIES_ENTRIES = 'entries';
diff --git a/pkg/analysis_server/lib/protocol/protocol_generated.dart b/pkg/analysis_server/lib/protocol/protocol_generated.dart
index 4fffb99..cd60f28 100644
--- a/pkg/analysis_server/lib/protocol/protocol_generated.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_generated.dart
@@ -11072,6 +11072,210 @@
}
/**
+ * flutter.getChangeAddForDesignTimeConstructor params
+ *
+ * {
+ * "file": FilePath
+ * "offset": int
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class FlutterGetChangeAddForDesignTimeConstructorParams
+ implements RequestParams {
+ String _file;
+
+ int _offset;
+
+ /**
+ * The file containing the code of the class.
+ */
+ String get file => _file;
+
+ /**
+ * The file containing the code of the class.
+ */
+ void set file(String value) {
+ assert(value != null);
+ this._file = value;
+ }
+
+ /**
+ * The offset of the class in the code.
+ */
+ int get offset => _offset;
+
+ /**
+ * The offset of the class in the code.
+ */
+ void set offset(int value) {
+ assert(value != null);
+ this._offset = value;
+ }
+
+ FlutterGetChangeAddForDesignTimeConstructorParams(String file, int offset) {
+ this.file = file;
+ this.offset = offset;
+ }
+
+ factory FlutterGetChangeAddForDesignTimeConstructorParams.fromJson(
+ JsonDecoder jsonDecoder, String jsonPath, Object json) {
+ if (json == null) {
+ json = {};
+ }
+ if (json is Map) {
+ String file;
+ if (json.containsKey("file")) {
+ file = jsonDecoder.decodeString(jsonPath + ".file", json["file"]);
+ } else {
+ throw jsonDecoder.mismatch(jsonPath, "file");
+ }
+ int offset;
+ if (json.containsKey("offset")) {
+ offset = jsonDecoder.decodeInt(jsonPath + ".offset", json["offset"]);
+ } else {
+ throw jsonDecoder.mismatch(jsonPath, "offset");
+ }
+ return new FlutterGetChangeAddForDesignTimeConstructorParams(
+ file, offset);
+ } else {
+ throw jsonDecoder.mismatch(jsonPath,
+ "flutter.getChangeAddForDesignTimeConstructor params", json);
+ }
+ }
+
+ factory FlutterGetChangeAddForDesignTimeConstructorParams.fromRequest(
+ Request request) {
+ return new FlutterGetChangeAddForDesignTimeConstructorParams.fromJson(
+ new RequestDecoder(request), "params", request.params);
+ }
+
+ @override
+ Map<String, dynamic> toJson() {
+ Map<String, dynamic> result = {};
+ result["file"] = file;
+ result["offset"] = offset;
+ return result;
+ }
+
+ @override
+ Request toRequest(String id) {
+ return new Request(
+ id, "flutter.getChangeAddForDesignTimeConstructor", toJson());
+ }
+
+ @override
+ String toString() => json.encode(toJson());
+
+ @override
+ bool operator ==(other) {
+ if (other is FlutterGetChangeAddForDesignTimeConstructorParams) {
+ return file == other.file && offset == other.offset;
+ }
+ return false;
+ }
+
+ @override
+ int get hashCode {
+ int hash = 0;
+ hash = JenkinsSmiHash.combine(hash, file.hashCode);
+ hash = JenkinsSmiHash.combine(hash, offset.hashCode);
+ return JenkinsSmiHash.finish(hash);
+ }
+}
+
+/**
+ * flutter.getChangeAddForDesignTimeConstructor result
+ *
+ * {
+ * "change": SourceChange
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class FlutterGetChangeAddForDesignTimeConstructorResult
+ implements ResponseResult {
+ SourceChange _change;
+
+ /**
+ * The change that adds the forDesignTime() constructor. If the change cannot
+ * be produced, an error is returned.
+ */
+ SourceChange get change => _change;
+
+ /**
+ * The change that adds the forDesignTime() constructor. If the change cannot
+ * be produced, an error is returned.
+ */
+ void set change(SourceChange value) {
+ assert(value != null);
+ this._change = value;
+ }
+
+ FlutterGetChangeAddForDesignTimeConstructorResult(SourceChange change) {
+ this.change = change;
+ }
+
+ factory FlutterGetChangeAddForDesignTimeConstructorResult.fromJson(
+ JsonDecoder jsonDecoder, String jsonPath, Object json) {
+ if (json == null) {
+ json = {};
+ }
+ if (json is Map) {
+ SourceChange change;
+ if (json.containsKey("change")) {
+ change = new SourceChange.fromJson(
+ jsonDecoder, jsonPath + ".change", json["change"]);
+ } else {
+ throw jsonDecoder.mismatch(jsonPath, "change");
+ }
+ return new FlutterGetChangeAddForDesignTimeConstructorResult(change);
+ } else {
+ throw jsonDecoder.mismatch(jsonPath,
+ "flutter.getChangeAddForDesignTimeConstructor result", json);
+ }
+ }
+
+ factory FlutterGetChangeAddForDesignTimeConstructorResult.fromResponse(
+ Response response) {
+ return new FlutterGetChangeAddForDesignTimeConstructorResult.fromJson(
+ new ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
+ "result",
+ response.result);
+ }
+
+ @override
+ Map<String, dynamic> toJson() {
+ Map<String, dynamic> result = {};
+ result["change"] = change.toJson();
+ return result;
+ }
+
+ @override
+ Response toResponse(String id) {
+ return new Response(id, result: toJson());
+ }
+
+ @override
+ String toString() => json.encode(toJson());
+
+ @override
+ bool operator ==(other) {
+ if (other is FlutterGetChangeAddForDesignTimeConstructorResult) {
+ return change == other.change;
+ }
+ return false;
+ }
+
+ @override
+ int get hashCode {
+ int hash = 0;
+ hash = JenkinsSmiHash.combine(hash, change.hashCode);
+ return JenkinsSmiHash.finish(hash);
+ }
+}
+
+/**
* FlutterOutline
*
* {
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index c827e0f..84d9d18 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -408,11 +408,6 @@
static const String LIB_DIR_NAME = 'lib';
/**
- * The name of `packages` folders.
- */
- static const String PACKAGES_NAME = 'packages';
-
- /**
* File name of pubspec files.
*/
static const String PUBSPEC_NAME = 'pubspec.yaml';
@@ -836,9 +831,6 @@
changeSet.addedSource(source);
info.sources[path] = source;
} else if (child is Folder) {
- if (child.shortName == PACKAGES_NAME) {
- continue;
- }
_addPreviouslyExcludedSources(info, changeSet, child, oldExcludedPaths);
}
}
@@ -875,10 +867,6 @@
info.sources[path] = source;
}
} else if (child is Folder) {
- String shortName = child.shortName;
- if (shortName == PACKAGES_NAME) {
- continue;
- }
_addSourceFiles(changeSet, child, info);
}
}
@@ -1181,9 +1169,7 @@
*/
void _createContexts(ContextInfo parent, Folder folder,
List<String> excludedPaths, bool withPackageSpecOnly) {
- if (_isExcluded(folder.path) ||
- folder.shortName.startsWith('.') ||
- folder.shortName == 'packages') {
+ if (_isExcluded(folder.path) || folder.shortName.startsWith('.')) {
return;
}
// Decide whether a context needs to be created for [folder] here, and if
@@ -1383,7 +1369,6 @@
// maybe excluded globally
if (_isExcluded(path) ||
_isContainedInDotFolder(info.folder.path, path) ||
- _isInPackagesDir(info.folder.path, path) ||
_isInTopLevelDocDir(info.folder.path, path)) {
return;
}
@@ -1527,19 +1512,6 @@
}
/**
- * Determine whether the given [path], when interpreted relative to the
- * context root [root], contains a 'packages' folder.
- */
- bool _isInPackagesDir(String root, String path) {
- String suffixPath = absolutePathContext.suffix(root, path);
- if (suffixPath == null) {
- return false;
- }
- List<String> pathParts = absolutePathContext.split(suffixPath);
- return pathParts.contains(PACKAGES_NAME);
- }
-
- /**
* Determine whether the given [path] is in the direct 'doc' folder of the
* context root [root].
*/
diff --git a/pkg/analysis_server/lib/src/flutter/flutter_correction.dart b/pkg/analysis_server/lib/src/flutter/flutter_correction.dart
index 7e16232..3791140 100644
--- a/pkg/analysis_server/lib/src/flutter/flutter_correction.dart
+++ b/pkg/analysis_server/lib/src/flutter/flutter_correction.dart
@@ -71,7 +71,7 @@
builder.write(' ');
}
- builder.writeln('$className.forDesignTime() {');
+ builder.writeln('factory $className.forDesignTime() {');
builder.writeln(' // TODO: add arguments');
builder.writeln(' return new $className();');
builder.write(' }');
diff --git a/pkg/analysis_server/lib/src/flutter/flutter_domain.dart b/pkg/analysis_server/lib/src/flutter/flutter_domain.dart
index aa486b8..5c5470a3 100644
--- a/pkg/analysis_server/lib/src/flutter/flutter_domain.dart
+++ b/pkg/analysis_server/lib/src/flutter/flutter_domain.dart
@@ -2,13 +2,15 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'dart:core';
+import 'dart:async';
import 'package:analysis_server/protocol/protocol_constants.dart';
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/domain_abstract.dart';
+import 'package:analysis_server/src/flutter/flutter_correction.dart';
import 'package:analysis_server/src/protocol/protocol_internal.dart';
import 'package:analysis_server/src/protocol_server.dart';
+import 'package:analyzer/dart/analysis/results.dart';
/**
* A [RequestHandler] that handles requests in the `flutter` domain.
@@ -23,6 +25,11 @@
Response handleRequest(Request request) {
try {
String requestName = request.method;
+ if (requestName ==
+ FLUTTER_REQUEST_GET_CHANGE_ADD_FOR_DESIGN_TIME_CONSTRUCTOR) {
+ getChangeAddForDesignTimeConstructor(request);
+ return Response.DELAYED_RESPONSE;
+ }
if (requestName == FLUTTER_REQUEST_SET_SUBSCRIPTIONS) {
return setSubscriptions(request);
}
@@ -42,4 +49,35 @@
server.setFlutterSubscriptions(subMap);
return new FlutterSetSubscriptionsResult().toResponse(request.id);
}
+
+ /**
+ * Implement the 'flutter.getChangeAddForDesignTimeConstructor' request.
+ */
+ Future getChangeAddForDesignTimeConstructor(Request request) async {
+ var params =
+ new FlutterGetChangeAddForDesignTimeConstructorParams.fromRequest(
+ request);
+ String file = params.file;
+ int offset = params.offset;
+
+ ResolveResult result = await server.getAnalysisResult(file);
+ if (result != null) {
+ var corrections = new FlutterCorrections(
+ file: file,
+ fileContent: result.content,
+ selectionOffset: offset,
+ selectionLength: 0,
+ session: result.session,
+ unit: result.unit);
+ SourceChange change = await corrections.addForDesignTimeConstructor();
+ if (change != null) {
+ server.sendResponse(
+ new FlutterGetChangeAddForDesignTimeConstructorResult(change)
+ .toResponse(request.id));
+ return;
+ }
+ }
+ server.sendResponse(
+ new Response.invalidParameter(request, 'file', 'No change'));
+ }
}
diff --git a/pkg/analysis_server/test/analysis/get_hover_test.dart b/pkg/analysis_server/test/analysis/get_hover_test.dart
index 35cc310..e2e60a6 100644
--- a/pkg/analysis_server/test/analysis/get_hover_test.dart
+++ b/pkg/analysis_server/test/analysis/get_hover_test.dart
@@ -556,7 +556,7 @@
const A(int i);
}
main() {
- var a = A(0);
+ const a = A(0);
}
''');
HoverInformation hover = await prepareHover('A(0)');
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index f97f086..db983e5 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -180,24 +180,6 @@
expect(sourceFactory.forUri('dart:typed_data'), isNotNull);
}
- test_ignoreFilesInPackagesFolder() {
- // create a context with a pubspec.yaml file
- String pubspecPath = path.posix.join(projPath, 'pubspec.yaml');
- resourceProvider.newFile(pubspecPath, 'pubspec');
- // create a file in the "packages" folder
- String filePath1 = path.posix.join(projPath, 'packages', 'file1.dart');
- resourceProvider.newFile(filePath1, 'contents');
- // "packages" files are ignored initially
- manager.setRoots(<String>[projPath], <String>[], <String, String>{});
- expect(callbacks.currentFilePaths, isEmpty);
- // "packages" files are ignored during watch
- String filePath2 = path.posix.join(projPath, 'packages', 'file2.dart');
- resourceProvider.newFile(filePath2, 'contents');
- return pumpEventQueue().then((_) {
- expect(callbacks.currentFilePaths, isEmpty);
- });
- }
-
void test_isInAnalysisRoot_excluded() {
// prepare paths
String project = convertPath('/project');
@@ -238,6 +220,23 @@
expect(manager.isInAnalysisRoot('/test.dart'), isFalse);
}
+ test_packagesFolder_areAnalyzed() {
+ // create a context with a pubspec.yaml file
+ String pubspecPath = path.posix.join(projPath, 'pubspec.yaml');
+ resourceProvider.newFile(pubspecPath, 'pubspec');
+ // create a file in the "packages" folder
+ String filePath1 = path.posix.join(projPath, 'packages', 'file1.dart');
+ File file1 = resourceProvider.newFile(filePath1, 'contents');
+ manager.setRoots(<String>[projPath], <String>[], <String, String>{});
+ expect(callbacks.currentFilePaths, unorderedEquals([file1.path]));
+ String filePath2 = path.posix.join(projPath, 'packages', 'file2.dart');
+ File file2 = resourceProvider.newFile(filePath2, 'contents');
+ return pumpEventQueue().then((_) {
+ expect(callbacks.currentFilePaths,
+ unorderedEquals([file1.path, file2.path]));
+ });
+ }
+
test_path_filter() async {
// Setup context.
Folder root = resourceProvider.newFolder(projPath);
@@ -943,16 +942,6 @@
expect(callbacks.currentFilePaths, hasLength(0));
}
- void test_setRoots_noContext_inPackagesFolder() {
- String pubspecPath = path.posix.join(projPath, 'packages', 'pubspec.yaml');
- resourceProvider.newFile(pubspecPath, 'name: test');
- manager.setRoots(<String>[projPath], <String>[], <String, String>{});
- // verify
- expect(callbacks.currentContextRoots, hasLength(1));
- expect(callbacks.currentContextRoots, contains(projPath));
- expect(callbacks.currentFilePaths, hasLength(0));
- }
-
void test_setRoots_packageResolver() {
String filePath = join(projPath, 'lib', 'foo.dart');
newFile('$projPath/${ContextManagerImpl.PACKAGE_SPEC_NAME}',
@@ -968,6 +957,16 @@
expect(result.fullName, filePath);
}
+ void test_setRoots_packagesFolder_hasContext() {
+ String pubspecPath = path.posix.join(projPath, 'packages', 'pubspec.yaml');
+ resourceProvider.newFile(pubspecPath, 'name: test');
+ manager.setRoots(<String>[projPath], <String>[], <String, String>{});
+ // verify
+ expect(callbacks.currentContextRoots, hasLength(2));
+ expect(callbacks.currentContextRoots, contains(projPath));
+ expect(callbacks.currentFilePaths, hasLength(0));
+ }
+
void test_setRoots_pathContainsDotFile() {
// If the path to a file (relative to the context root) contains a folder
// whose name begins with '.', then the file is ignored.
diff --git a/pkg/analysis_server/test/integration/coverage.md b/pkg/analysis_server/test/integration/coverage.md
index 8ab1806..4dbeae6 100644
--- a/pkg/analysis_server/test/integration/coverage.md
+++ b/pkg/analysis_server/test/integration/coverage.md
@@ -84,5 +84,6 @@
- [x] kythe.getKytheEntries
## flutter domain
+- [ ] flutter.getChangeAddForDesignTimeConstructor
- [ ] flutter.setSubscriptions
- [ ] flutter.outline
diff --git a/pkg/analysis_server/test/integration/support/integration_test_methods.dart b/pkg/analysis_server/test/integration/support/integration_test_methods.dart
index cf284ec..9b77a47 100644
--- a/pkg/analysis_server/test/integration/support/integration_test_methods.dart
+++ b/pkg/analysis_server/test/integration/support/integration_test_methods.dart
@@ -2118,6 +2118,40 @@
}
/**
+ * Return the change that adds the forDesignTime() constructor for the widget
+ * class at the given offset.
+ *
+ * Parameters
+ *
+ * file: FilePath
+ *
+ * The file containing the code of the class.
+ *
+ * offset: int
+ *
+ * The offset of the class in the code.
+ *
+ * Returns
+ *
+ * change: SourceChange
+ *
+ * The change that adds the forDesignTime() constructor. If the change
+ * cannot be produced, an error is returned.
+ */
+ Future<FlutterGetChangeAddForDesignTimeConstructorResult>
+ sendFlutterGetChangeAddForDesignTimeConstructor(
+ String file, int offset) async {
+ var params =
+ new FlutterGetChangeAddForDesignTimeConstructorParams(file, offset)
+ .toJson();
+ var result = await server.send(
+ "flutter.getChangeAddForDesignTimeConstructor", params);
+ ResponseDecoder decoder = new ResponseDecoder(null);
+ return new FlutterGetChangeAddForDesignTimeConstructorResult.fromJson(
+ decoder, 'result', result);
+ }
+
+ /**
* Subscribe for services that are specific to individual files. All previous
* subscriptions are replaced by the current set of subscriptions. If a given
* service is not included as a key in the map then no files will be
diff --git a/pkg/analysis_server/test/integration/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
index 464d280..dd07221 100644
--- a/pkg/analysis_server/test/integration/support/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
@@ -2486,6 +2486,31 @@
() => new MatchesJsonObject("extractWidget options", {"name": isString}));
/**
+ * flutter.getChangeAddForDesignTimeConstructor params
+ *
+ * {
+ * "file": FilePath
+ * "offset": int
+ * }
+ */
+final Matcher isFlutterGetChangeAddForDesignTimeConstructorParams =
+ new LazyMatcher(() => new MatchesJsonObject(
+ "flutter.getChangeAddForDesignTimeConstructor params",
+ {"file": isFilePath, "offset": isInt}));
+
+/**
+ * flutter.getChangeAddForDesignTimeConstructor result
+ *
+ * {
+ * "change": SourceChange
+ * }
+ */
+final Matcher isFlutterGetChangeAddForDesignTimeConstructorResult =
+ new LazyMatcher(() => new MatchesJsonObject(
+ "flutter.getChangeAddForDesignTimeConstructor result",
+ {"change": isSourceChange}));
+
+/**
* flutter.outline params
*
* {
diff --git a/pkg/analysis_server/test/src/flutter/flutter_correction_test.dart b/pkg/analysis_server/test/src/flutter/flutter_correction_test.dart
index b285c2b..2e79d3f 100644
--- a/pkg/analysis_server/test/src/flutter/flutter_correction_test.dart
+++ b/pkg/analysis_server/test/src/flutter/flutter_correction_test.dart
@@ -65,7 +65,7 @@
class MyWidget extends StatelessWidget {
MyWidget(String text);
- MyWidget.forDesignTime() {
+ factory MyWidget.forDesignTime() {
// TODO: add arguments
return new MyWidget();
}
@@ -97,7 +97,7 @@
class MyWidget extends StatelessWidget {
MyWidget();
- MyWidget.forDesignTime() {
+ factory MyWidget.forDesignTime() {
// TODO: add arguments
return new MyWidget();
}
diff --git a/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java b/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
index e551044..6272649 100644
--- a/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
+++ b/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
@@ -619,6 +619,17 @@
public void execution_setSubscriptions(List<String> subscriptions);
/**
+ * {@code flutter.getChangeAddForDesignTimeConstructor}
+ *
+ * Return the change that adds the forDesignTime() constructor for the widget class at the given
+ * offset.
+ *
+ * @param file The file containing the code of the class.
+ * @param offset The offset of the class in the code.
+ */
+ public void flutter_getChangeAddForDesignTimeConstructor(String file, int offset, GetChangeAddForDesignTimeConstructorConsumer consumer);
+
+ /**
* {@code flutter.setSubscriptions}
*
* Subscribe for services that are specific to individual files. All previous subscriptions are
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index 49e3cb8..50954cd 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -2630,6 +2630,35 @@
<p>
The analysis domain contains API’s related to Flutter support.
</p>
+ <request method="getChangeAddForDesignTimeConstructor">
+ <p>
+ Return the change that adds the forDesignTime() constructor for the
+ widget class at the given offset.
+ </p>
+ <params>
+ <field name="file">
+ <ref>FilePath</ref>
+ <p>
+ The file containing the code of the class.
+ </p>
+ </field>
+ <field name="offset">
+ <ref>int</ref>
+ <p>
+ The offset of the class in the code.
+ </p>
+ </field>
+ </params>
+ <result>
+ <field name="change">
+ <ref>SourceChange</ref>
+ <p>
+ The change that adds the forDesignTime() constructor.
+ If the change cannot be produced, an error is returned.
+ </p>
+ </field>
+ </result>
+ </request>
<request method="setSubscriptions">
<p>
Subscribe for services that are specific to individual files.
diff --git a/pkg/analyzer/lib/src/dart/analysis/context_locator.dart b/pkg/analyzer/lib/src/dart/analysis/context_locator.dart
index 2f3fc05..83147d0 100644
--- a/pkg/analyzer/lib/src/dart/analysis/context_locator.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/context_locator.dart
@@ -41,11 +41,6 @@
static const String OLD_ANALYSIS_OPTIONS_NAME = '.analysis_options';
/**
- * The name of the packages folder.
- */
- static const String PACKAGES_DIR_NAME = 'packages';
-
- /**
* The name of the packages file.
*/
static const String PACKAGES_FILE_NAME = '.packages';
@@ -277,8 +272,7 @@
for (Resource child in folder.getChildren()) {
if (child is Folder) {
if (excludedFolders.contains(folder) ||
- folder.shortName.startsWith('.') ||
- folder.shortName == PACKAGES_DIR_NAME) {
+ folder.shortName.startsWith('.')) {
containingRoot.excluded.add(folder);
} else {
_createContextRoots(roots, child, excludedFolders, containingRoot,
diff --git a/pkg/analyzer/lib/src/dart/analysis/context_root.dart b/pkg/analyzer/lib/src/dart/analysis/context_root.dart
index 0d3a082..463b9f6 100644
--- a/pkg/analyzer/lib/src/dart/analysis/context_root.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/context_root.dart
@@ -98,8 +98,7 @@
bool _isExcluded(String path) {
Context context = resourceProvider.pathContext;
String name = context.basename(path);
- if (name.startsWith('.') ||
- (name == 'packages' && resourceProvider.getResource(path) is Folder)) {
+ if (name.startsWith('.')) {
return true;
}
for (String excludedPath in excludedPaths) {
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index b596dca..88f8525 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -95,7 +95,7 @@
/**
* The version of data format, should be incremented on every format change.
*/
- static const int DATA_VERSION = 55;
+ static const int DATA_VERSION = 56;
/**
* The number of exception contexts allowed to write. Once this field is
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 9774ad0..265a55c 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -2766,20 +2766,23 @@
@override
void onError(AnalysisError error) {
- switch (error.errorCode) {
- case CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL:
- case CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING:
- case CompileTimeErrorCode.CONST_EVAL_TYPE_INT:
- case CompileTimeErrorCode.CONST_EVAL_TYPE_NUM:
- case CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION:
- case CompileTimeErrorCode.CONST_EVAL_THROWS_IDBZE:
- case CompileTimeErrorCode.CONST_WITH_NON_CONSTANT_ARGUMENT:
- case CompileTimeErrorCode.NON_CONSTANT_VALUE_IN_INITIALIZER:
- case CompileTimeErrorCode
- .CONST_CONSTRUCTOR_WITH_FIELD_INITIALIZED_BY_NON_CONST:
- case CompileTimeErrorCode.INVALID_CONSTANT:
- case CompileTimeErrorCode.MISSING_CONST_IN_LIST_LITERAL:
- hasConstError = true;
+ ErrorCode errorCode = error.errorCode;
+ if (errorCode is CompileTimeErrorCode) {
+ switch (errorCode) {
+ case CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL:
+ case CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING:
+ case CompileTimeErrorCode.CONST_EVAL_TYPE_INT:
+ case CompileTimeErrorCode.CONST_EVAL_TYPE_NUM:
+ case CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION:
+ case CompileTimeErrorCode.CONST_EVAL_THROWS_IDBZE:
+ case CompileTimeErrorCode.CONST_WITH_NON_CONSTANT_ARGUMENT:
+ case CompileTimeErrorCode.NON_CONSTANT_VALUE_IN_INITIALIZER:
+ case CompileTimeErrorCode
+ .CONST_CONSTRUCTOR_WITH_FIELD_INITIALIZED_BY_NON_CONST:
+ case CompileTimeErrorCode.INVALID_CONSTANT:
+ case CompileTimeErrorCode.MISSING_CONST_IN_LIST_LITERAL:
+ hasConstError = true;
+ }
}
}
}
@@ -6555,7 +6558,7 @@
if (!isImplicit) {
return keyword.keyword == Keyword.CONST;
} else {
- return inConstantContext || canBeConst();
+ return inConstantContext;
}
}
@@ -6622,6 +6625,13 @@
}
}
}
+ } else if (argument is Identifier) {
+ Element element = argument.bestElement;
+ if (element is PropertyAccessorElement && !element.variable.isConst) {
+ return false;
+ } else if (element is VariableElement && !element.isConst) {
+ return false;
+ }
} else {
return false;
}
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index 2dc985f..2951395 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -1633,6 +1633,7 @@
element is PropertyAccessorElement ? element.variable : element;
if (variableElement is VariableElementImpl) {
evaluationEngine.validator.beforeGetEvaluationResult(variableElement);
+ variableElement.computeConstantValue();
EvaluationResultImpl value = variableElement.evaluationResult;
if (variableElement.isConst && value != null) {
return value.value;
diff --git a/pkg/analyzer/lib/src/dart/constant/utilities.dart b/pkg/analyzer/lib/src/dart/constant/utilities.dart
index b07ff69..7e47780 100644
--- a/pkg/analyzer/lib/src/dart/constant/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/constant/utilities.dart
@@ -69,8 +69,12 @@
InstanceCreationExpression node) {
InstanceCreationExpression expression =
super.visitInstanceCreationExpression(node);
- if (previewDart2 && node.keyword == null && node.isConst) {
- expression.keyword = new KeywordToken(Keyword.CONST, node.offset);
+ if (previewDart2 && node.keyword == null) {
+ if (node.isConst) {
+ expression.keyword = new KeywordToken(Keyword.CONST, node.offset);
+ } else {
+ expression.keyword = new KeywordToken(Keyword.NEW, node.offset);
+ }
}
expression.staticElement = node.staticElement;
return expression;
diff --git a/pkg/analyzer/lib/src/fasta/error_converter.dart b/pkg/analyzer/lib/src/fasta/error_converter.dart
index 836f94c..2b1db80 100644
--- a/pkg/analyzer/lib/src/fasta/error_converter.dart
+++ b/pkg/analyzer/lib/src/fasta/error_converter.dart
@@ -384,6 +384,10 @@
errorReporter?.reportErrorForOffset(
ScannerErrorCode.MISSING_DIGIT, offset, length);
return;
+ case "MISSING_EXPRESSION_IN_THROW":
+ errorReporter?.reportErrorForOffset(
+ ParserErrorCode.MISSING_EXPRESSION_IN_THROW, offset, length);
+ return;
case "MISSING_ENUM_BODY":
errorReporter?.reportErrorForOffset(
ParserErrorCode.MISSING_ENUM_BODY, offset, length);
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 529103f..69583e8 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -18,6 +18,7 @@
import 'package:analyzer/exception/exception.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/ast/ast_factory.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/member.dart' show ConstructorMember;
@@ -44,12 +45,14 @@
* feature.
*/
class AstRewriteVisitor extends ScopedVisitor {
+ final bool addConstKeyword;
+
/**
* Initialize a newly created visitor.
*/
AstRewriteVisitor(LibraryElement definingLibrary, Source source,
TypeProvider typeProvider, AnalysisErrorListener errorListener,
- {Scope nameScope})
+ {Scope nameScope, this.addConstKeyword: false})
: super(definingLibrary, source, typeProvider, errorListener,
nameScope: nameScope);
@@ -77,7 +80,7 @@
TypeName typeName = astFactory.typeName(methodName, node.typeArguments);
InstanceCreationExpression instanceCreationExpression =
astFactory.instanceCreationExpression(
- null,
+ _getKeyword(node),
astFactory.constructorName(typeName, null, null),
node.argumentList);
DartType type = _getType(element, node.typeArguments);
@@ -100,7 +103,7 @@
TypeName typeName = astFactory.typeName(target, node.typeArguments);
InstanceCreationExpression instanceCreationExpression =
astFactory.instanceCreationExpression(
- null,
+ _getKeyword(node),
astFactory.constructorName(
typeName, node.operator, methodName),
node.argumentList);
@@ -124,7 +127,7 @@
node.typeArguments);
InstanceCreationExpression instanceCreationExpression =
astFactory.instanceCreationExpression(
- null,
+ _getKeyword(node),
astFactory.constructorName(typeName, null, null),
node.argumentList);
DartType type = _getType(prefixedElement, node.typeArguments);
@@ -145,7 +148,7 @@
TypeName typeName = astFactory.typeName(target, node.typeArguments);
InstanceCreationExpression instanceCreationExpression =
astFactory.instanceCreationExpression(
- null,
+ _getKeyword(node),
astFactory.constructorName(
typeName, node.operator, methodName),
node.argumentList);
@@ -162,6 +165,16 @@
}
/**
+ * Return the token that should be used in the [InstanceCreationExpression]
+ * that corresponds to the given invocation [node].
+ */
+ Token _getKeyword(MethodInvocation node) {
+ return addConstKeyword
+ ? new KeywordToken(Keyword.CONST, node.offset)
+ : null;
+ }
+
+ /**
* Return the type of the given class [element] after substituting any type
* arguments from the list of [typeArguments] for the class' type parameters.
*/
diff --git a/pkg/analyzer/lib/src/pubspec/pubspec_validator.dart b/pkg/analyzer/lib/src/pubspec/pubspec_validator.dart
index ea14ea6..bb05401 100644
--- a/pkg/analyzer/lib/src/pubspec/pubspec_validator.dart
+++ b/pkg/analyzer/lib/src/pubspec/pubspec_validator.dart
@@ -182,17 +182,20 @@
} else if (assetsField != null) {
_reportErrorForNode(
reporter, assetsField, PubspecWarningCode.ASSET_FIELD_NOT_LIST);
- } else {
- // TODO(brianwilkerson) Should we report an error if `assets` is
- // missing?
}
+
if (flutterField.length > 1) {
// TODO(brianwilkerson) Should we report an error if `flutter` contains
// keys other than `assets`?
}
} else if (flutterField != null) {
- _reportErrorForNode(
- reporter, flutterField, PubspecWarningCode.FLUTTER_FIELD_NOT_MAP);
+ if (flutterField.value == null) {
+ // allow an empty `flutter:` section; explicitly fail on a non-empty,
+ // non-map one
+ } else {
+ _reportErrorForNode(
+ reporter, flutterField, PubspecWarningCode.FLUTTER_FIELD_NOT_MAP);
+ }
}
}
diff --git a/pkg/analyzer/lib/src/summary/resynthesize.dart b/pkg/analyzer/lib/src/summary/resynthesize.dart
index 5dec73d..e03b7aa 100644
--- a/pkg/analyzer/lib/src/summary/resynthesize.dart
+++ b/pkg/analyzer/lib/src/summary/resynthesize.dart
@@ -7,8 +7,10 @@
import 'dart:collection';
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/standard_ast_factory.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/handle.dart';
import 'package:analyzer/src/dart/element/member.dart';
@@ -1119,6 +1121,11 @@
CompilationUnitElementImpl unit;
/**
+ * The visitor to rewrite implicit `new` and `const`.
+ */
+ AstRewriteVisitor astRewriteVisitor;
+
+ /**
* Map from slot id to the corresponding [EntityRef] object for linked types
* (i.e. propagated and inferred types).
*/
@@ -1561,7 +1568,18 @@
}
Expression _buildConstExpression(ElementImpl context, UnlinkedExpr uc) {
- return new ExprBuilder(this, context, uc).build();
+ var expression = new ExprBuilder(this, context, uc).build();
+
+ if (expression != null && context.context.analysisOptions.previewDart2) {
+ astRewriteVisitor ??= new AstRewriteVisitor(libraryResynthesizer.library,
+ unit.source, typeProvider, AnalysisErrorListener.NULL_LISTENER,
+ addConstKeyword: true);
+ var container = astFactory.expressionStatement(expression, null);
+ expression.accept(astRewriteVisitor);
+ expression = container.expression;
+ }
+
+ return expression;
}
/**
diff --git a/pkg/analyzer/lib/src/summary/summarize_const_expr.dart b/pkg/analyzer/lib/src/summary/summarize_const_expr.dart
index 2cf21ed..8ac5f4f 100644
--- a/pkg/analyzer/lib/src/summary/summarize_const_expr.dart
+++ b/pkg/analyzer/lib/src/summary/summarize_const_expr.dart
@@ -595,10 +595,6 @@
}
void _serializeMethodInvocation(MethodInvocation invocation) {
- if (invocation.target != null ||
- invocation.methodName.name != 'identical') {
- isValidConst = false;
- }
Expression target = invocation.target;
SimpleIdentifier methodName = invocation.methodName;
ArgumentList argumentList = invocation.argumentList;
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index 17f11d3..1ab766a 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -472,18 +472,6 @@
@override
@failingTest
- void test_missingExpressionInThrow() {
- // TODO(brianwilkerson) Does not recover.
- // type 'RethrowExpressionImpl' is not a subtype of type 'ThrowExpression' of 'expression' where
- // RethrowExpressionImpl is from package:analyzer/src/dart/ast/ast.dart
- // ThrowExpression is from package:analyzer/dart/ast/ast.dart
- //
- // test/generated/parser_test.dart 3492:59 FastaParserTestCase&ErrorParserTestMixin.test_missingExpressionInThrow_withCascade
- super.test_missingExpressionInThrow();
- }
-
- @override
- @failingTest
void test_missingFunctionParameters_topLevel_void_block() {
// TODO(brianwilkerson) Wrong errors:
// Expected 1 errors of type ParserErrorCode.MISSING_FUNCTION_PARAMETERS, found 0
@@ -1202,7 +1190,9 @@
@override
void addCompileTimeError(Message message, int charOffset, int length, Uri uri,
- {bool silent: false, bool wasHandled: false, LocatedMessage context}) {
+ {bool silent: false,
+ bool wasHandled: false,
+ List<LocatedMessage> context}) {
fail('${message.message}');
}
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index a18492f..9a06e00 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -5589,7 +5589,7 @@
void test_varAndType_field() {
parseCompilationUnit("class C { var int x; }",
- errors: [expectedError(ParserErrorCode.VAR_AND_TYPE, 14, 3)]);
+ errors: [expectedError(ParserErrorCode.VAR_AND_TYPE, 10, 3)]);
}
void test_varAndType_local() {
@@ -5614,7 +5614,7 @@
void test_varAndType_topLevelVariable() {
parseCompilationUnit("var int x;",
- errors: [expectedError(ParserErrorCode.VAR_AND_TYPE, 4, 3)]);
+ errors: [expectedError(ParserErrorCode.VAR_AND_TYPE, 0, 3)]);
}
void test_varAsTypeName_as() {
@@ -9685,7 +9685,6 @@
parser.parseFunctionBodies = parseFunctionBodies;
parser.enableNnbd = enableNnbd;
parser.enableOptionalNewAndConst = enableOptionalNewAndConst;
- parser.enableUriInPartOf = enableUriInPartOf;
parser.currentToken = tokenStream;
}
@@ -15044,6 +15043,18 @@
expect(variableList.type, new isInstanceOf<GenericFunctionType>());
}
+ void test_invalid_typeParamAnnotation() {
+ parseCompilationUnit('main() { C<@Foo T> v; }',
+ errors: usingFastaParser
+ // TODO(danrubel): Improve this error to indicate that annotations
+ // are not valid in this context.
+ ? [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 11, 1)]
+ : [
+ expectedError(ParserErrorCode.MISSING_IDENTIFIER, 11, 1),
+ expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 1)
+ ]);
+ }
+
void test_parseStatement_emptyTypeArgumentList() {
var declaration = parseStatement('C<> c;') as VariableDeclarationStatement;
assertErrorsWithCodes([ParserErrorCode.EXPECTED_TYPE_NAME]);
diff --git a/pkg/analyzer/test/src/dart/analysis/context_locator_test.dart b/pkg/analyzer/test/src/dart/analysis/context_locator_test.dart
index b3f133b..ea4762e 100644
--- a/pkg/analyzer/test/src/dart/analysis/context_locator_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/context_locator_test.dart
@@ -211,24 +211,6 @@
expect(outerRoot.packagesFile, outerPackagesFile);
}
- void test_locateRoots_nested_excluded_packages() {
- Folder outerRootFolder = newFolder('/test/outer');
- File outerOptionsFile = newOptionsFile('/test/outer');
- File outerPackagesFile = newPackagesFile('/test/outer');
- Folder excludedFolder = newFolder('/test/outer/packages');
- newOptionsFile('/test/outer/packages/inner');
-
- List<ContextRoot> roots =
- contextLocator.locateRoots(includedPaths: [outerRootFolder.path]);
- expect(roots, hasLength(1));
-
- ContextRoot outerRoot = findRoot(roots, outerRootFolder);
- expect(outerRoot.includedPaths, unorderedEquals([outerRootFolder.path]));
- expect(outerRoot.excludedPaths, unorderedEquals([excludedFolder.path]));
- expect(outerRoot.optionsFile, outerOptionsFile);
- expect(outerRoot.packagesFile, outerPackagesFile);
- }
-
void test_locateRoots_nested_multiple() {
Folder outerRootFolder = newFolder('/test/outer');
File outerOptionsFile = newOptionsFile('/test/outer');
@@ -450,6 +432,24 @@
expect(outerRoot.packagesFile, overridePackagesFile);
}
+ void test_locateRoots_nested_packagesDirectory_included() {
+ Folder outerRootFolder = newFolder('/test/outer');
+ File outerOptionsFile = newOptionsFile('/test/outer');
+ File outerPackagesFile = newPackagesFile('/test/outer');
+ File innerOptionsFile = newOptionsFile('/test/outer/packages/inner');
+
+ List<ContextRoot> roots =
+ contextLocator.locateRoots(includedPaths: [outerRootFolder.path]);
+ expect(roots, hasLength(2));
+
+ ContextRoot outerRoot = findRoot(roots, outerRootFolder);
+ expect(outerRoot.includedPaths, unorderedEquals([outerRootFolder.path]));
+ expect(outerRoot.excludedPaths,
+ unorderedEquals([innerOptionsFile.parent.path]));
+ expect(outerRoot.optionsFile, outerOptionsFile);
+ expect(outerRoot.packagesFile, outerPackagesFile);
+ }
+
void test_locateRoots_single_dir_directOptions_directPackages() {
Folder rootFolder = newFolder('/test/root');
File optionsFile = newOptionsFile('/test/root');
diff --git a/pkg/analyzer/test/src/dart/analysis/context_root_test.dart b/pkg/analyzer/test/src/dart/analysis/context_root_test.dart
index 9f15523..573d210 100644
--- a/pkg/analyzer/test/src/dart/analysis/context_root_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/context_root_test.dart
@@ -65,14 +65,14 @@
expect(contextRoot.isAnalyzed(filePath), isFalse);
}
- test_isAnalyzed_implicitlyExcluded_packages() {
- String folderPath = provider.convertPath('/test/root/lib/packages');
- provider.newFolder(folderPath);
- expect(contextRoot.isAnalyzed(folderPath), isFalse);
- }
-
test_isAnalyzed_included() {
String filePath = provider.convertPath('/test/root/lib/root.dart');
expect(contextRoot.isAnalyzed(filePath), isTrue);
}
+
+ test_isAnalyzed_packagesDirectory_analyzed() {
+ String folderPath = provider.convertPath('/test/root/lib/packages');
+ provider.newFolder(folderPath);
+ expect(contextRoot.isAnalyzed(folderPath), isTrue);
+ }
}
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index 50be7e7..907139e 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -344,6 +344,12 @@
@reflectiveTest
class AnalysisDriverTest extends BaseAnalysisDriverTest {
+ void configurePreviewDart2() {
+ driver.configure(
+ analysisOptions: new AnalysisOptionsImpl.from(driver.analysisOptions)
+ ..previewDart2 = true);
+ }
+
test_addedFiles() async {
var a = _p('/test/lib/a.dart');
var b = _p('/test/lib/b.dart');
@@ -1002,6 +1008,63 @@
expect(x.constantValue, isNotNull);
}
+ test_const_implicitCreation() async {
+ configurePreviewDart2();
+
+ var a = _p('/test/bin/a.dart');
+ var b = _p('/test/bin/b.dart');
+ provider.newFile(a, r'''
+class C {
+ const C();
+ static const C WARNING = C();
+}
+''');
+ provider.newFile(b, r'''
+import 'a.dart';
+
+class D {
+ const D();
+ static const D WARNING = D();
+}
+
+const c = C.WARNING;
+const d = D.WARNING;
+''');
+ AnalysisResult result = await driver.getResult(b);
+ expect(result.errors, isEmpty);
+ }
+
+ test_const_implicitCreation_rewrite() async {
+ configurePreviewDart2();
+
+ var a = _p('/test/bin/a.dart');
+ var b = _p('/test/bin/b.dart');
+ provider.newFile(a, r'''
+class A {
+ const A();
+}
+
+class B {
+ final A a;
+ const B(this.a);
+}
+
+class C {
+ const b = B(A());
+ const C();
+}
+''');
+ provider.newFile(b, r'''
+import 'a.dart';
+
+main() {
+ const C();
+}
+''');
+ AnalysisResult result = await driver.getResult(b);
+ expect(result.errors, isEmpty);
+ }
+
test_const_implicitSuperConstructorInvocation() async {
addTestFile('''
class Base {}
diff --git a/pkg/analyzer/test/src/dart/ast/ast_test.dart b/pkg/analyzer/test/src/dart/ast/ast_test.dart
index c037947..c76c2a4 100644
--- a/pkg/analyzer/test/src/dart/ast/ast_test.dart
+++ b/pkg/analyzer/test/src/dart/ast/ast_test.dart
@@ -49,6 +49,32 @@
assertInContext("C(0", true);
}
+ test_inConstantContext_instanceCreation_fieldWithConstConstructor() {
+ parse('''
+class C {
+ final d = D();
+ const C();
+}
+class D {
+ const D();
+}
+''');
+ assertInContext("D()", false);
+ }
+
+ test_inConstantContext_instanceCreation_fieldWithoutConstConstructor() {
+ parse('''
+class C {
+ final d = D();
+ C();
+}
+class D {
+ const D();
+}
+''');
+ assertInContext("D()", false);
+ }
+
test_inConstantContext_instanceCreation_functionLiteral() {
parse('''
const V = () => C();
@@ -59,26 +85,6 @@
assertInContext("C()", false);
}
- test_inConstantContext_instanceCreation_initializer_false() {
- parse('''
-var c = C();
-class C {
- const C();
-}
-''');
- assertInContext("C()", false);
- }
-
- test_inConstantContext_instanceCreation_initializer_true() {
- parse('''
-const c = C();
-class C {
- const C();
-}
-''');
- assertInContext("C()", true);
- }
-
test_inConstantContext_instanceCreation_instanceCreation_false() {
parse('''
f() {
@@ -216,6 +222,26 @@
assertInContext("C()", true);
}
+ test_inConstantContext_instanceCreation_topLevelVariable_false() {
+ parse('''
+var c = C();
+class C {
+ const C();
+}
+''');
+ assertInContext("C()", false);
+ }
+
+ test_inConstantContext_instanceCreation_topLevelVariable_true() {
+ parse('''
+const c = C();
+class C {
+ const C();
+}
+''');
+ assertInContext("C()", true);
+ }
+
test_inConstantContext_listLiteral_annotation_true() {
parse('''
@C([])
@@ -442,6 +468,8 @@
String testSource;
CompilationUnitImpl testUnit;
+ bool get enableNewAnalysisDriver => true;
+
void assertIsConst(String snippet, bool isConst) {
int index = testSource.indexOf(snippet);
expect(index >= 0, isTrue);
@@ -462,6 +490,20 @@
testUnit = await resolveSource2('/test.dart', source);
}
+ void
+ test_isConst_notInContext_constructor_const_constParam_identifier() async {
+ enablePreviewDart2();
+ await resolve('''
+var v = C(C.a);
+class C {
+ static const C a = C.c();
+ const C(c);
+ const C.c();
+}
+''');
+ assertIsConst("C(C", false);
+ }
+
void test_isConst_notInContext_constructor_const_constParam_named() async {
enablePreviewDart2();
await resolve('''
@@ -470,7 +512,7 @@
const C({c});
}
''');
- assertIsConst("C(c", true);
+ assertIsConst("C(c", false);
}
void
@@ -482,7 +524,7 @@
const C({c});
}
''');
- assertIsConst("C(c", true);
+ assertIsConst("C(c", false);
}
void test_isConst_notInContext_constructor_const_constParam_parens() async {
@@ -494,7 +536,7 @@
const C.c();
}
''');
- assertIsConst("C( (", true);
+ assertIsConst("C( (", false);
}
void test_isConst_notInContext_constructor_const_generic_named() async {
@@ -505,7 +547,7 @@
const C.n();
}
''');
- assertIsConst("C<int>.n", true);
+ assertIsConst("C<int>.n", false);
}
void
@@ -520,7 +562,7 @@
import 'c.dart' as p;
f() => <Object>[p.C<int>.n()];
''');
- assertIsConst("C<int>", true);
+ assertIsConst("C<int>", false);
}
void test_isConst_notInContext_constructor_const_generic_unnamed() async {
@@ -531,7 +573,7 @@
const C();
}
''');
- assertIsConst("C<int>", true);
+ assertIsConst("C<int>", false);
}
void
@@ -546,7 +588,7 @@
import 'c.dart' as p;
f() => <Object>[p.C<int>()];
''');
- assertIsConst("C<int>", true);
+ assertIsConst("C<int>", false);
}
void
@@ -589,7 +631,7 @@
const C.n();
}
''');
- assertIsConst("C.n()", true);
+ assertIsConst("C.n()", false);
}
void
@@ -604,7 +646,7 @@
import 'c.dart' as p;
f() => <Object>[p.C.n()];
''');
- assertIsConst("C.n()", true);
+ assertIsConst("C.n()", false);
}
void test_isConst_notInContext_constructor_const_nonGeneric_unnamed() async {
@@ -615,7 +657,7 @@
const C();
}
''');
- assertIsConst("C()", true);
+ assertIsConst("C()", false);
}
void
@@ -630,7 +672,7 @@
import 'c.dart' as p;
f() => <Object>[p.C()];
''');
- assertIsConst("C()", true);
+ assertIsConst("C()", false);
}
void test_isConst_notInContext_constructor_nonConst() async {
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/class_declaration_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/class_declaration_test.dart
index 550eecb..9ba13da 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/class_declaration_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/class_declaration_test.dart
@@ -36,7 +36,6 @@
'class _s_ {}',
failing: <String>[
'typedef',
- 'functionVoid',
'functionNonVoid',
'getter',
'setter'
@@ -53,8 +52,7 @@
'class A extends _s_ {}',
failing: allExceptEof),
new TestDescriptor('extendsBody', 'class A extends {}',
- [ParserErrorCode.EXPECTED_TYPE_NAME], 'class A extends _s_ {}',
- allFailing: true),
+ [ParserErrorCode.EXPECTED_TYPE_NAME], 'class A extends _s_ {}'),
new TestDescriptor(
'extendsWithNameBody',
'class A extends with B {}',
@@ -80,8 +78,7 @@
'extendsNameWithBody',
'class A extends B with {}',
[ParserErrorCode.EXPECTED_TYPE_NAME],
- 'class A extends B with _s_ {}',
- allFailing: true),
+ 'class A extends B with _s_ {}'),
new TestDescriptor(
'extendsNameImplements',
'class A extends B implements',
@@ -95,8 +92,7 @@
'extendsNameImplementsBody',
'class A extends B implements {}',
[ParserErrorCode.EXPECTED_TYPE_NAME],
- 'class A extends B implements _s_ {}',
- allFailing: true),
+ 'class A extends B implements _s_ {}'),
new TestDescriptor(
'extendsNameWithNameImplements',
'class A extends B with C implements',
@@ -110,8 +106,7 @@
'extendsNameWithNameImplementsBody',
'class A extends B with C implements {}',
[ParserErrorCode.EXPECTED_TYPE_NAME],
- 'class A extends B with C implements _s_ {}',
- allFailing: true),
+ 'class A extends B with C implements _s_ {}'),
new TestDescriptor(
'implements',
'class A implements',
@@ -121,9 +116,11 @@
],
'class A implements _s_ {}',
failing: allExceptEof),
- new TestDescriptor('implementsBody', 'class A implements {}',
- [ParserErrorCode.EXPECTED_TYPE_NAME], 'class A implements _s_ {}',
- allFailing: true),
+ new TestDescriptor(
+ 'implementsBody',
+ 'class A implements {}',
+ [ParserErrorCode.EXPECTED_TYPE_NAME],
+ 'class A implements _s_ {}'),
new TestDescriptor(
'implementsNameComma',
'class A implements B,',
@@ -137,8 +134,7 @@
'implementsNameCommaBody',
'class A implements B, {}',
[ParserErrorCode.EXPECTED_TYPE_NAME],
- 'class A implements B, _s_ {}',
- allFailing: true),
+ 'class A implements B, _s_ {}'),
],
PartialCodeTest.declarationSuffixes);
}
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/local_variable_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/local_variable_test.dart
index 7a54709..23eac88 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/local_variable_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/local_variable_test.dart
@@ -66,7 +66,6 @@
'for',
'labeled',
'localFunctionNonVoid',
- 'localFunctionVoid',
'return',
]),
new TestDescriptor(
@@ -85,7 +84,6 @@
'for',
'labeled',
'localFunctionNonVoid',
- 'localFunctionVoid',
'return',
]),
new TestDescriptor('constNameCommaName', 'const a, b',
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/top_level_variable_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/top_level_variable_test.dart
index cc08a8b..1d27bed 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/top_level_variable_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/top_level_variable_test.dart
@@ -76,13 +76,7 @@
CompileTimeErrorCode.CONST_NOT_INITIALIZED
],
"const a, _s_;",
- failing: [
- 'typedef',
- 'functionVoid',
- 'functionNonVoid',
- 'getter',
- 'setter'
- ],
+ failing: ['typedef', 'functionNonVoid', 'getter', 'setter'],
expectedErrorsInValidCode: [
CompileTimeErrorCode.CONST_NOT_INITIALIZED,
CompileTimeErrorCode.CONST_NOT_INITIALIZED
@@ -98,13 +92,7 @@
CompileTimeErrorCode.CONST_NOT_INITIALIZED
],
"const int a, _s_;",
- failing: [
- 'typedef',
- 'functionVoid',
- 'functionNonVoid',
- 'getter',
- 'setter'
- ],
+ failing: ['typedef', 'functionNonVoid', 'getter', 'setter'],
expectedErrorsInValidCode: [
CompileTimeErrorCode.CONST_NOT_INITIALIZED,
CompileTimeErrorCode.CONST_NOT_INITIALIZED
diff --git a/pkg/analyzer/test/src/pubspec/pubspec_validator_test.dart b/pkg/analyzer/test/src/pubspec/pubspec_validator_test.dart
index 883fe5f..9386a8d 100644
--- a/pkg/analyzer/test/src/pubspec/pubspec_validator_test.dart
+++ b/pkg/analyzer/test/src/pubspec/pubspec_validator_test.dart
@@ -210,11 +210,17 @@
''', [PubspecWarningCode.FLUTTER_FIELD_NOT_MAP]);
}
- test_flutterFieldNotMap_error_empty() {
- assertErrors('''
+ test_flutterField_empty_noError() {
+ assertNoErrors('''
name: sample
flutter:
-''', [PubspecWarningCode.FLUTTER_FIELD_NOT_MAP]);
+''');
+
+ assertNoErrors('''
+name: sample
+flutter:
+
+''');
}
test_flutterFieldNotMap_noError() {
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 0b1369a..f707999 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -2526,7 +2526,7 @@
}
test_const_invalid_field_const() async {
- variablesWithNotConstInitializers.add('f');
+ shouldCompareLibraryElements = false;
var library = await checkLibrary(r'''
class C {
static const f = 1 + foo();
@@ -2545,14 +2545,16 @@
} else if (isStrongMode) {
checkElementText(library, r'''
class C {
- static const int f;
+ static const int f = 1 +
+ foo/*location: test.dart;foo*/();
}
int foo() {}
''');
} else {
checkElementText(library, r'''
class C {
- static const dynamic f;
+ static const dynamic f = 1 +
+ foo/*location: test.dart;foo*/();
}
int foo() {}
''');
@@ -2594,7 +2596,7 @@
}
test_const_invalid_topLevel() async {
- variablesWithNotConstInitializers.add('v');
+ shouldCompareLibraryElements = false;
var library = await checkLibrary(r'''
const v = 1 + foo();
int foo() => 42;
@@ -2608,12 +2610,14 @@
''');
} else if (isStrongMode) {
checkElementText(library, r'''
-const int v;
+const int v = 1 +
+ foo/*location: test.dart;foo*/();
int foo() {}
''');
} else {
checkElementText(library, r'''
-const dynamic v;
+const dynamic v = 1 +
+ foo/*location: test.dart;foo*/();
int foo() {}
''');
}
@@ -4566,7 +4570,7 @@
}
test_constructor_initializers_field_notConst() async {
- variablesWithNotConstInitializers.add('x');
+ shouldCompareLibraryElements = false;
var library = await checkLibrary('''
class C {
final x;
@@ -4574,9 +4578,8 @@
}
int foo() => 42;
''', allowErrors: true);
- if (isSharedFrontEnd) {
- // It is OK to keep non-constant initializers.
- checkElementText(library, r'''
+ // It is OK to keep non-constant initializers.
+ checkElementText(library, r'''
class C {
final dynamic x;
const C() :
@@ -4585,16 +4588,6 @@
}
int foo() {}
''');
- } else {
- checkElementText(library, r'''
-class C {
- final dynamic x;
- const C() :
- x/*location: test.dart;C;x*/ = <null>;
-}
-int foo() {}
-''');
- }
}
test_constructor_initializers_field_withParameter() async {
diff --git a/pkg/analyzer/test/src/summary/summary_common.dart b/pkg/analyzer/test/src/summary/summary_common.dart
index 0411275..37b5eca 100644
--- a/pkg/analyzer/test/src/summary/summary_common.dart
+++ b/pkg/analyzer/test/src/summary/summary_common.dart
@@ -6887,7 +6887,6 @@
}
UnlinkedVariable variable = serializeVariableText('var v = (x) => x.f();');
assertUnlinkedConst(variable.initializer.localFunctions[0].bodyExpr,
- isValidConst: false,
operators: [
UnlinkedExprOperation.pushParameter,
UnlinkedExprOperation.invokeMethod
@@ -6910,7 +6909,6 @@
UnlinkedVariable variable =
serializeVariableText('var v = (x) => x.y.f();');
assertUnlinkedConst(variable.initializer.localFunctions[0].bodyExpr,
- isValidConst: false,
operators: [
UnlinkedExprOperation.pushParameter,
UnlinkedExprOperation.extractProperty,
@@ -7135,31 +7133,26 @@
A a = new A();
final v = a.b.c.m(10, 20);
''');
- assertUnlinkedConst(variable.initializer.bodyExpr,
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.invokeMethodRef,
- ],
- ints: [
- 10,
- 20,
- 0,
- 2,
- 0
- ],
- strings: [],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'm',
- expectedKind: ReferenceKind.unresolved,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.unresolved, 'c'),
- new _PrefixExpectation(ReferenceKind.unresolved, 'b'),
- new _PrefixExpectation(
- ReferenceKind.topLevelPropertyAccessor, 'a')
- ])
- ]);
+ assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.invokeMethodRef,
+ ], ints: [
+ 10,
+ 20,
+ 0,
+ 2,
+ 0
+ ], strings: [], referenceValidators: [
+ (EntityRef r) => checkTypeRef(r, null, 'm',
+ expectedKind: ReferenceKind.unresolved,
+ prefixExpectations: [
+ new _PrefixExpectation(ReferenceKind.unresolved, 'c'),
+ new _PrefixExpectation(ReferenceKind.unresolved, 'b'),
+ new _PrefixExpectation(
+ ReferenceKind.topLevelPropertyAccessor, 'a')
+ ])
+ ]);
}
test_expr_invokeMethodRef_static_importedWithPrefix() {
@@ -7175,26 +7168,21 @@
import 'a.dart' as p;
final v = p.C.m();
''');
- assertUnlinkedConst(variable.initializer.bodyExpr,
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.invokeMethodRef,
- ],
- ints: [
- 0,
- 0,
- 0
- ],
- strings: [],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'm',
- expectedKind: ReferenceKind.method,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'C',
- absoluteUri: absUri('/a.dart')),
- new _PrefixExpectation(ReferenceKind.prefix, 'p')
- ])
- ]);
+ assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
+ UnlinkedExprOperation.invokeMethodRef,
+ ], ints: [
+ 0,
+ 0,
+ 0
+ ], strings: [], referenceValidators: [
+ (EntityRef r) => checkTypeRef(r, null, 'm',
+ expectedKind: ReferenceKind.method,
+ prefixExpectations: [
+ new _PrefixExpectation(ReferenceKind.classOrEnum, 'C',
+ absoluteUri: absUri('/a.dart')),
+ new _PrefixExpectation(ReferenceKind.prefix, 'p')
+ ])
+ ]);
}
test_expr_invokeMethodRef_with_reference_arg() {
@@ -7206,23 +7194,19 @@
final u = null;
final v = f(u);
''');
- assertUnlinkedConst(variable.initializer.bodyExpr,
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.pushReference,
- UnlinkedExprOperation.invokeMethodRef
- ],
- ints: [
- 0,
- 1,
- 0
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'u',
- expectedKind: ReferenceKind.topLevelPropertyAccessor),
- (EntityRef r) => checkTypeRef(r, null, 'f',
- expectedKind: ReferenceKind.topLevelFunction)
- ]);
+ assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
+ UnlinkedExprOperation.pushReference,
+ UnlinkedExprOperation.invokeMethodRef
+ ], ints: [
+ 0,
+ 1,
+ 0
+ ], referenceValidators: [
+ (EntityRef r) => checkTypeRef(r, null, 'u',
+ expectedKind: ReferenceKind.topLevelPropertyAccessor),
+ (EntityRef r) => checkTypeRef(r, null, 'f',
+ expectedKind: ReferenceKind.topLevelFunction)
+ ]);
}
test_expr_invokeMethodRef_withTypeParameters() {
@@ -7233,23 +7217,18 @@
f<T, U>() => null;
final v = f<int, String>();
''');
- assertUnlinkedConst(variable.initializer.bodyExpr,
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.invokeMethodRef
- ],
- ints: [
- 0,
- 0,
- 2
- ],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'f',
- expectedKind: ReferenceKind.topLevelFunction,
- numTypeParameters: 2),
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'int'),
- (EntityRef r) => checkTypeRef(r, 'dart:core', 'String')
- ]);
+ assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
+ UnlinkedExprOperation.invokeMethodRef
+ ], ints: [
+ 0,
+ 0,
+ 2
+ ], referenceValidators: [
+ (EntityRef r) => checkTypeRef(r, null, 'f',
+ expectedKind: ReferenceKind.topLevelFunction, numTypeParameters: 2),
+ (EntityRef r) => checkTypeRef(r, 'dart:core', 'int'),
+ (EntityRef r) => checkTypeRef(r, 'dart:core', 'String')
+ ]);
}
test_expr_makeTypedList() {
@@ -7462,27 +7441,22 @@
static int m() => 42;
}''').fields[0];
expect(variable.isFinal, isTrue);
- assertUnlinkedConst(variable.initializer.bodyExpr,
- isValidConst: false,
- operators: [
- UnlinkedExprOperation.pushInt,
- UnlinkedExprOperation.invokeMethodRef,
- UnlinkedExprOperation.add,
- ],
- ints: [
- 1,
- 0,
- 0,
- 0
- ],
- strings: [],
- referenceValidators: [
- (EntityRef r) => checkTypeRef(r, null, 'm',
- expectedKind: ReferenceKind.method,
- prefixExpectations: [
- new _PrefixExpectation(ReferenceKind.classOrEnum, 'C')
- ])
- ]);
+ assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.invokeMethodRef,
+ UnlinkedExprOperation.add,
+ ], ints: [
+ 1,
+ 0,
+ 0,
+ 0
+ ], strings: [], referenceValidators: [
+ (EntityRef r) => checkTypeRef(r, null, 'm',
+ expectedKind: ReferenceKind.method,
+ prefixExpectations: [
+ new _PrefixExpectation(ReferenceKind.classOrEnum, 'C')
+ ])
+ ]);
}
test_field_final_typeParameter() {
diff --git a/pkg/analyzer_cli/lib/src/options.dart b/pkg/analyzer_cli/lib/src/options.dart
index a901ed4..5136abf 100644
--- a/pkg/analyzer_cli/lib/src/options.dart
+++ b/pkg/analyzer_cli/lib/src/options.dart
@@ -153,9 +153,6 @@
/// Whether to treat lints as fatal
final bool lintsAreFatal;
- /// Whether to use memory byte store for analysis driver.
- final bool useAnalysisDriverMemoryByteStore;
-
/// Emit output in a verbose mode.
final bool verbose;
@@ -207,8 +204,6 @@
strongMode = args['strong'],
implicitCasts = args[implicitCastsFlag],
implicitDynamic = !args['no-implicit-dynamic'],
- useAnalysisDriverMemoryByteStore =
- args['use-analysis-driver-memory-byte-store'],
verbose = args['verbose'],
color = args['color'];
@@ -384,12 +379,12 @@
negatable: false,
hide: hide)
..addOption('build-analysis-output',
- help:
- 'Specifies the path to the file where analysis results should be written.',
+ help: 'Specifies the path to the file where analysis results should '
+ 'be written.',
hide: hide)
..addFlag('build-mode',
- // TODO(paulberry): add more documentation.
- help: 'Enable build mode.',
+ help: 'Run in build mode; '
+ 'this is used to generate analyzer summaries for build systems.',
defaultsTo: false,
negatable: false,
hide: hide)
diff --git a/pkg/compiler/lib/src/compile_time_constants.dart b/pkg/compiler/lib/src/compile_time_constants.dart
index 3b253de..693f8fd 100644
--- a/pkg/compiler/lib/src/compile_time_constants.dart
+++ b/pkg/compiler/lib/src/compile_time_constants.dart
@@ -16,6 +16,7 @@
import 'constants/values.dart';
import 'common_elements.dart' show CommonElements;
import 'elements/elements.dart';
+import 'elements/types.dart' show DartTypes;
import 'elements/modelx.dart' show ConstantVariableMixin;
import 'elements/operators.dart';
import 'elements/resolution_types.dart';
@@ -1460,13 +1461,16 @@
CommonElements get commonElements => _compiler.resolution.commonElements;
@override
+ DartTypes get types => _compiler.resolution.types;
+
+ @override
String readFromEnvironment(String name) {
return _compiler.fromEnvironment(name);
}
@override
ResolutionInterfaceType substByContext(
- ResolutionInterfaceType base, ResolutionInterfaceType target) {
+ ResolutionDartType base, ResolutionInterfaceType target) {
return base.substByContext(target);
}
diff --git a/pkg/compiler/lib/src/constants/evaluation.dart b/pkg/compiler/lib/src/constants/evaluation.dart
index cdb11cc..7a20827 100644
--- a/pkg/compiler/lib/src/constants/evaluation.dart
+++ b/pkg/compiler/lib/src/constants/evaluation.dart
@@ -18,6 +18,11 @@
abstract class EvaluationEnvironment {
CommonElements get commonElements;
+ DartTypes get types;
+
+ /// Type in the enclosing constructed
+ InterfaceType get enclosingConstructedType;
+
/// Read environments string passed in using the '-Dname=value' option.
String readFromEnvironment(String name);
@@ -35,7 +40,7 @@
/// Performs the substitution of the type arguments of [target] for their
/// corresponding type variables in [type].
InterfaceType substByContext(
- covariant InterfaceType base, covariant InterfaceType target);
+ covariant DartType base, covariant InterfaceType target);
void reportWarning(
ConstantExpression expression, MessageKind kind, Map arguments);
@@ -43,8 +48,8 @@
void reportError(
ConstantExpression expression, MessageKind kind, Map arguments);
- ConstantValue evaluateConstructor(
- ConstructorEntity constructor, ConstantValue evaluate());
+ ConstantValue evaluateConstructor(ConstructorEntity constructor,
+ InterfaceType type, ConstantValue evaluate());
ConstantValue evaluateField(FieldEntity field, ConstantValue evaluate());
@@ -54,6 +59,7 @@
abstract class EvaluationEnvironmentBase implements EvaluationEnvironment {
Link<Spannable> _spannableStack = const Link<Spannable>();
+ InterfaceType enclosingConstructedType;
final Set<FieldEntity> _currentlyEvaluatedFields = new Set<FieldEntity>();
final bool constantRequired;
@@ -94,10 +100,13 @@
}
@override
- ConstantValue evaluateConstructor(
- ConstructorEntity constructor, ConstantValue evaluate()) {
+ ConstantValue evaluateConstructor(ConstructorEntity constructor,
+ InterfaceType type, ConstantValue evaluate()) {
_spannableStack = _spannableStack.prepend(constructor);
+ var old = enclosingConstructedType;
+ enclosingConstructedType = type;
ConstantValue result = evaluate();
+ enclosingConstructedType = old;
_spannableStack = _spannableStack.tail;
return result;
}
diff --git a/pkg/compiler/lib/src/constants/expressions.dart b/pkg/compiler/lib/src/constants/expressions.dart
index a28c018..2a6813c 100644
--- a/pkg/compiler/lib/src/constants/expressions.dart
+++ b/pkg/compiler/lib/src/constants/expressions.dart
@@ -16,6 +16,7 @@
import 'values.dart';
enum ConstantExpressionKind {
+ AS,
BINARY,
BOOL,
BOOL_FROM_ENVIRONMENT,
@@ -580,7 +581,8 @@
@override
ConstantValue evaluate(
EvaluationEnvironment environment, ConstantSystem constantSystem) {
- return environment.evaluateConstructor(target, () {
+ InterfaceType instanceType = computeInstanceType(environment);
+ return environment.evaluateConstructor(target, instanceType, () {
InstanceData instanceData = computeInstanceData(environment);
if (instanceData == null) {
return new NonConstantValue();
@@ -607,8 +609,7 @@
}
}
if (isValidAsConstant) {
- return new ConstructedConstantValue(
- computeInstanceType(environment), fieldValues);
+ return new ConstructedConstantValue(instanceType, fieldValues);
} else {
return new NonConstantValue();
}
@@ -822,6 +823,67 @@
commonElements.typeType;
}
+/// Cast expressions: these may be from either explicit or implicit `as`
+/// checks.
+class AsConstantExpression extends ConstantExpression {
+ final ConstantExpression expression;
+ final DartType type;
+
+ AsConstantExpression(this.expression, this.type);
+
+ ConstantExpressionKind get kind => ConstantExpressionKind.AS;
+
+ accept(ConstantExpressionVisitor visitor, [context]) {
+ return visitor.visitAs(this, context);
+ }
+
+ @override
+ void _createStructuredText(StringBuffer sb) {
+ sb.write('As(value=');
+ expression._createStructuredText(sb);
+ sb.write(',type=$type)');
+ }
+
+ @override
+ ConstantValue evaluate(
+ EvaluationEnvironment environment, ConstantSystem constantSystem) {
+ ConstantValue expressionValue =
+ expression.evaluate(environment, constantSystem);
+ DartType expressionType =
+ expressionValue.getType(environment.commonElements);
+ DartType enclosingType = environment.enclosingConstructedType;
+ DartType superType = enclosingType != null
+ ? environment.substByContext(type, enclosingType)
+ : type;
+ if (!constantSystem.isSubtype(
+ environment.types, expressionType, superType)) {
+ // TODO(sigmund): consider reporting different messages and error
+ // locations for implicit vs explicit casts.
+ environment.reportError(expression, MessageKind.INVALID_CONSTANT_CAST,
+ {'constant': expression, 'type': expressionType, 'castType': type});
+ return new NonConstantValue();
+ }
+ return expressionValue;
+ }
+
+ @override
+ ConstantExpression apply(NormalizedArguments arguments) {
+ return new AsConstantExpression(expression.apply(arguments), type);
+ }
+
+ @override
+ int _computeHashCode() => 13 * type.hashCode + 17 * expression.hashCode;
+
+ @override
+ bool _equals(AsConstantExpression other) {
+ return expression == other.expression && type == other.type;
+ }
+
+ @override
+ InterfaceType getKnownType(CommonElements commonElements) =>
+ expression.getKnownType(commonElements);
+}
+
/// Reference to a constant top-level or static field.
class FieldConstantExpression extends ConstantExpression {
final FieldEntity element;
@@ -2060,6 +2122,7 @@
return constant.accept(this, context);
}
+ R visitAs(AsConstantExpression exp, A context);
R visitBool(BoolConstantExpression exp, A context);
R visitInt(IntConstantExpression exp, A context);
R visitDouble(DoubleConstantExpression exp, A context);
@@ -2127,6 +2190,13 @@
}
@override
+ void visitAs(AsConstantExpression exp, [_]) {
+ visit(exp.expression);
+ sb.write(' as ');
+ sb.write(exp.type);
+ }
+
+ @override
void visitBool(BoolConstantExpression exp, [_]) {
sb.write(exp.boolValue);
}
diff --git a/pkg/compiler/lib/src/diagnostics/generated/shared_messages.dart b/pkg/compiler/lib/src/diagnostics/generated/shared_messages.dart
index 7f640b3..467a5bf 100644
--- a/pkg/compiler/lib/src/diagnostics/generated/shared_messages.dart
+++ b/pkg/compiler/lib/src/diagnostics/generated/shared_messages.dart
@@ -77,11 +77,7 @@
MessageKind.MISSING_EXPRESSION_IN_THROW: const MessageTemplate(
MessageKind.MISSING_EXPRESSION_IN_THROW,
"Missing expression after 'throw'.",
- howToFix: "Did you mean 'rethrow'?",
- examples: const [
- "main() { throw; }",
- "main() { try { throw 0; } catch(e) { throw; } }",
- ]), // Generated. Don't edit.
+ howToFix: "Did you mean 'rethrow'?"), // Generated. Don't edit.
MessageKind.RETHROW_OUTSIDE_CATCH: const MessageTemplate(
MessageKind.RETHROW_OUTSIDE_CATCH,
"Rethrow must be inside of catch clause.",
diff --git a/pkg/compiler/lib/src/diagnostics/messages.dart b/pkg/compiler/lib/src/diagnostics/messages.dart
index 51ffa6b..0bd3e70 100644
--- a/pkg/compiler/lib/src/diagnostics/messages.dart
+++ b/pkg/compiler/lib/src/diagnostics/messages.dart
@@ -207,6 +207,7 @@
INVALID_BOOL_FROM_ENVIRONMENT_DEFAULT_VALUE_TYPE,
INVALID_BREAK,
INVALID_CASE_DEFAULT,
+ INVALID_CONSTANT_CAST,
INVALID_CONSTANT_ADD_TYPES,
INVALID_CONSTANT_BINARY_INT_TYPE,
INVALID_CONSTANT_BINARY_NUM_TYPE,
@@ -3506,6 +3507,10 @@
"constant binary + expression on 'num'. Must be a value of type "
"'int' or 'double'."),
+ MessageKind.INVALID_CONSTANT_CAST: const MessageTemplate(
+ MessageKind.INVALID_CONSTANT_CAST,
+ "`#{constant}` of type '#{type}' is not a subtype of #{castType}."),
+
MessageKind.INVALID_CONSTANT_ADD_TYPES: const MessageTemplate(
MessageKind.INVALID_CONSTANT_ADD_TYPES,
"`#{leftConstant}` of type '#{leftType}' and "
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index bc3d0c0..afceb3d 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -532,11 +532,7 @@
}
}
- int sizeOfNode(jsAst.Node node) {
- // TODO(sigmund): switch back to null aware operators (issue #24136)
- var size = _nodeToSize[node];
- return size == null ? 0 : size;
- }
+ int sizeOfNode(jsAst.Node node) => _nodeToSize[node] ?? 0;
String codeOf(Entity entity) {
List<jsAst.Node> code = _entityToNodes[entity];
@@ -629,6 +625,10 @@
new Duration(milliseconds: stopwatch.elapsedMilliseconds),
dumpInfoDuration: new Duration(milliseconds: this.timing),
noSuchMethodEnabled: closedWorld.backendUsage.isNoSuchMethodUsed,
+ isRuntimeTypeUsed: closedWorld.backendUsage.isRuntimeTypeUsed,
+ isIsolateInUse: closedWorld.backendUsage.isIsolateInUse,
+ isFunctionApplyUsed: closedWorld.backendUsage.isFunctionApplyUsed,
+ isMirrorsUsed: closedWorld.backendUsage.isMirrorsUsed,
minified: compiler.options.enableMinification);
ChunkedConversionSink<Object> sink = encoder.startChunkedConversion(
diff --git a/pkg/compiler/lib/src/io/source_file.dart b/pkg/compiler/lib/src/io/source_file.dart
index ff47c16..494111d 100644
--- a/pkg/compiler/lib/src/io/source_file.dart
+++ b/pkg/compiler/lib/src/io/source_file.dart
@@ -9,6 +9,7 @@
import 'dart:typed_data' show Uint8List;
import 'package:kernel/ast.dart' as kernel show Location, Source;
+
import 'location_provider.dart' show LocationProvider;
import '../../compiler_new.dart';
@@ -102,10 +103,6 @@
if (colorize == null) {
colorize = (text) => text;
}
- if (end > length) {
- start = length - 1;
- end = length;
- }
kernel.Location startLocation = kernelSource.getLocation(null, start);
kernel.Location endLocation = kernelSource.getLocation(null, end);
@@ -142,9 +139,15 @@
for (int line = lineStart; line <= lineEnd; line++) {
String textLine = kernelSource.getTextLine(line + 1);
if (line == lineStart) {
+ if (columnStart > textLine.length) {
+ columnStart = textLine.length;
+ }
buf.write(textLine.substring(0, columnStart));
buf.writeln(colorize(textLine.substring(columnStart)));
} else if (line == lineEnd) {
+ if (columnEnd > textLine.length) {
+ columnEnd = textLine.length;
+ }
buf.write(colorize(textLine.substring(0, columnEnd)));
buf.writeln(textLine.substring(columnEnd));
} else {
diff --git a/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
index 0ac5234..14177b0 100644
--- a/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart
@@ -392,6 +392,9 @@
for (int i = 0; i < selector.argumentCount; i++) {
parameterNames.add('a$i');
}
+ for (int i = 1; i <= selector.typeArgumentCount; i++) {
+ parameterNames.add('\$T$i');
+ }
}
jsAst.Name invocationName = _namer.invocationName(selector);
diff --git a/pkg/compiler/lib/src/js_model/closure_visitors.dart b/pkg/compiler/lib/src/js_model/closure_visitors.dart
index 4650e6b..28bd0f1 100644
--- a/pkg/compiler/lib/src/js_model/closure_visitors.dart
+++ b/pkg/compiler/lib/src/js_model/closure_visitors.dart
@@ -68,6 +68,11 @@
/// have unique names.
int _boxCounter = 0;
+ /// Set to `true` in the visitor if a type annotation is always needed.
+ ///
+ /// This is for instance the case for expressions like `o is T` and `o as T`.
+ bool _contextNeedsType = false;
+
CapturedScopeBuilder(this._model, this._options, {bool hasThisLocal})
: this._hasThisLocal = hasThisLocal;
@@ -414,6 +419,9 @@
_capturedVariables.add(freeVariable);
_markVariableAsUsed(freeVariable);
}
+ for (ir.Node freeVariableForRti in savedScopeInfo.freeVariablesForRti) {
+ _markVariableAsUsed(freeVariableForRti, onlyForRtiChecks: true);
+ }
if (_isInsideClosure && savedScopeInfo.thisUsedAsFreeVariable) {
_currentScopeInfo.thisUsedAsFreeVariable = true;
}
@@ -464,14 +472,32 @@
@override
visitTypeParameterType(ir.TypeParameterType type) {
- _analyzeTypeVariable(type);
+ _analyzeTypeVariable(type, onlyIfNeedsRti: !_contextNeedsType);
}
@override
visitTypeLiteral(ir.TypeLiteral node) {
- if (node.type is ir.TypeParameterType) {
- _analyzeTypeVariable(node.type, onlyIfNeedsRti: false);
- }
+ bool oldContextNeedsType = _contextNeedsType;
+ _contextNeedsType = true;
+ node.visitChildren(this);
+ _contextNeedsType = oldContextNeedsType;
+ }
+
+ @override
+ visitIsExpression(ir.IsExpression node) {
+ bool oldContextNeedsType = _contextNeedsType;
+ _contextNeedsType = true;
+ node.visitChildren(this);
+ _contextNeedsType = oldContextNeedsType;
+ }
+
+ @override
+ visitAsExpression(ir.AsExpression node) {
+ bool oldContextNeedsType = _contextNeedsType;
+ _contextNeedsType =
+ !node.isTypeError || _options.implicitDowncastCheckPolicy.isEmitted;
+ node.visitChildren(this);
+ _contextNeedsType = oldContextNeedsType;
}
/// Returns true if the node is a field, or a constructor (factory or
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index 63c2d8f..15e1ad0 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -1814,7 +1814,10 @@
CommonElements get commonElements => _elementMap.commonElements;
@override
- InterfaceType substByContext(InterfaceType base, InterfaceType target) {
+ DartTypes get types => _elementMap.types;
+
+ @override
+ InterfaceType substByContext(DartType base, InterfaceType target) {
return _elementMap._substByContext(base, target);
}
diff --git a/pkg/compiler/lib/src/kernel/element_map_mixins.dart b/pkg/compiler/lib/src/kernel/element_map_mixins.dart
index 8cdbb9c..8d08535 100644
--- a/pkg/compiler/lib/src/kernel/element_map_mixins.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_mixins.dart
@@ -690,6 +690,21 @@
}
@override
+ ConstantExpression visitAsExpression(ir.AsExpression node) {
+ ConstantExpression expression = visit(node.operand);
+ if (expression == null) return null;
+ DartType type = elementMap.getDartType(node.type);
+ return new AsConstantExpression(expression, type);
+ }
+
+ @override
+ ConstantExpression visitInstantiation(ir.Instantiation node) {
+ // TODO(sigmund, sra): add a constant representation for instantiations.
+ // See issue 32774.
+ return visit(node.expression);
+ }
+
+ @override
ConstantExpression visitNot(ir.Not node) {
ConstantExpression expression = visit(node.operand);
if (expression == null) return null;
diff --git a/pkg/compiler/lib/src/kernel/env.dart b/pkg/compiler/lib/src/kernel/env.dart
index 37d3e65..90077cb 100644
--- a/pkg/compiler/lib/src/kernel/env.dart
+++ b/pkg/compiler/lib/src/kernel/env.dart
@@ -317,6 +317,21 @@
void addProcedures(ir.Class c, {bool includeStatic}) {
for (ir.Procedure member in c.procedures) {
+ if (member.isForwardingStub && member.isAbstract) {
+ // Skip abstract forwarding stubs. These are never emitted but they
+ // might shadow the inclusion of a mixed in method in code like:
+ //
+ // class Super {}
+ // class Mixin<T> {
+ // void method(T t) {}
+ // }
+ // class Class extends Super with Mixin<int> {}
+ // main() => new Class().method();
+ //
+ // Here a stub is created for `Super&Mixin.method` hiding that
+ // `Mixin.method` is inherited by `Class`.
+ continue;
+ }
if (!includeStatic && member.isStatic) continue;
var name = member.name.name;
assert(!name.contains('#'));
diff --git a/pkg/compiler/lib/src/kernel/front_end_adapter.dart b/pkg/compiler/lib/src/kernel/front_end_adapter.dart
index 2dd227a..9a4097f 100644
--- a/pkg/compiler/lib/src/kernel/front_end_adapter.dart
+++ b/pkg/compiler/lib/src/kernel/front_end_adapter.dart
@@ -83,7 +83,7 @@
Spannable span;
if (message.span != null) {
span = new SourceSpan(message.span.start.sourceUrl,
- message.span.start.offset, message.span.start.offset + 1);
+ message.span.start.offset, message.span.end.offset);
} else {
span = NO_LOCATION_SPANNABLE;
}
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index 1f1d3c3..607e8e6 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -392,9 +392,9 @@
librariesSpecificationUri = _resolveLibrariesSpecification(libraryRoot);
if (strongMode) {
- // Strong mode represents implicit downcasts explicitly, so assignments
- // checks provide no additional value.
- assignmentCheckPolicy = CheckPolicy.ignored;
+ // Strong mode always trusts type annotations (inferred or explicit), so
+ // assignments checks should be trusted.
+ assignmentCheckPolicy = CheckPolicy.trusted;
if (omitImplicitChecks) {
parameterCheckPolicy = CheckPolicy.trusted;
implicitDowncastCheckPolicy = CheckPolicy.trusted;
diff --git a/pkg/compiler/lib/src/serialization/constant_serialization.dart b/pkg/compiler/lib/src/serialization/constant_serialization.dart
index bc0a163..46fade8 100644
--- a/pkg/compiler/lib/src/serialization/constant_serialization.dart
+++ b/pkg/compiler/lib/src/serialization/constant_serialization.dart
@@ -198,6 +198,11 @@
void visitAssert(AssertConstantExpression exp, ObjectEncoder context) {
throw new UnsupportedError("AssertConstantExpression is not supported.");
}
+
+ @override
+ void visitAs(AsConstantExpression exp, ObjectEncoder encoder) {
+ throw new UnsupportedError("AsConstantExpression is not supported.");
+ }
}
/// Utility class for deserializing [ConstantExpression]s.
@@ -305,6 +310,7 @@
decoder.getElement(Key.IMPORT) as ImportElement);
case ConstantExpressionKind.SYNTHETIC:
case ConstantExpressionKind.ASSERT:
+ case ConstantExpressionKind.AS:
}
throw new UnsupportedError("Unexpected constant kind: ${kind} in $decoder");
}
diff --git a/pkg/compiler/lib/src/serialization/equivalence.dart b/pkg/compiler/lib/src/serialization/equivalence.dart
index 65f12d5..486c774 100644
--- a/pkg/compiler/lib/src/serialization/equivalence.dart
+++ b/pkg/compiler/lib/src/serialization/equivalence.dart
@@ -746,6 +746,13 @@
}
@override
+ bool visitAs(AsConstantExpression exp1, covariant AsConstantExpression exp2) {
+ return strategy.test(
+ exp1, exp2, 'expression', exp1.expression, exp2.expression) &&
+ strategy.testTypes(exp1, exp2, 'type', exp1.type, exp2.type);
+ }
+
+ @override
bool visitBinary(
BinaryConstantExpression exp1, covariant BinaryConstantExpression exp2) {
return strategy.test(
diff --git a/pkg/compiler/lib/src/ssa/type_builder.dart b/pkg/compiler/lib/src/ssa/type_builder.dart
index eb334b9..0992bb1 100644
--- a/pkg/compiler/lib/src/ssa/type_builder.dart
+++ b/pkg/compiler/lib/src/ssa/type_builder.dart
@@ -98,7 +98,6 @@
HInstruction original, DartType type,
{int kind: HTypeConversion.CHECKED_MODE_CHECK}) {
if (type == null) return original;
- if (builder.options.strongMode) return original;
HInstruction checkedOrTrusted = original;
if (builder.options.assignmentCheckPolicy.isTrusted) {
checkedOrTrusted = _trustType(original, type);
diff --git a/pkg/compiler/lib/src/ssa/types_propagation.dart b/pkg/compiler/lib/src/ssa/types_propagation.dart
index 3fea8fd..0831c6e 100644
--- a/pkg/compiler/lib/src/ssa/types_propagation.dart
+++ b/pkg/compiler/lib/src/ssa/types_propagation.dart
@@ -55,7 +55,7 @@
// the phi thinks it has because new optimizations may imply
// changing it.
// In theory we would need to mark
- // the type of all other incoming edges as "unitialized" and take this
+ // the type of all other incoming edges as "uninitialized" and take this
// into account when doing the propagation inside the phis. Just
// setting the propagated type is however easier.
phi.instructionType = phi.inputs[0].instructionType;
diff --git a/pkg/compiler/lib/src/universe/function_set.dart b/pkg/compiler/lib/src/universe/function_set.dart
index b36729d..01f27b2 100644
--- a/pkg/compiler/lib/src/universe/function_set.dart
+++ b/pkg/compiler/lib/src/universe/function_set.dart
@@ -242,6 +242,19 @@
: const EmptyFunctionSetQuery();
return result;
}
+
+ String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.write('FunctionSetNode(');
+ String comma = '';
+ cache.forEach((mask, query) {
+ sb.write(comma);
+ sb.write('$mask=$query');
+ comma = ',';
+ });
+ sb.write(')');
+ return sb.toString();
+ }
}
/// A set of functions that are the potential targets of all call sites sharing
@@ -265,6 +278,8 @@
@override
Iterable<MemberEntity> get functions => const <MemberEntity>[];
+
+ String toString() => '<empty>';
}
class FullFunctionSetQuery implements FunctionSetQuery {
@@ -296,4 +311,6 @@
}),
closedWorld);
}
+
+ String toString() => '$_mask:$functions';
}
diff --git a/pkg/compiler/testing.json b/pkg/compiler/testing.json
index 9a4b50d..e2ef599 100644
--- a/pkg/compiler/testing.json
+++ b/pkg/compiler/testing.json
@@ -14,8 +14,8 @@
],
"exclude": [
- "^tests/compiler/dart2js/data/.*",
"^tests/compiler/dart2js/inference/data/super_invoke\\.dart",
+ "^tests/compiler/dart2js/old_frontend/data/.*",
"^tests/compiler/dart2js/path with spaces/.*"
]
}
diff --git a/pkg/compiler/testing_dart.json b/pkg/compiler/testing_dart.json
index 4ebf407..aa78e3e 100644
--- a/pkg/compiler/testing_dart.json
+++ b/pkg/compiler/testing_dart.json
@@ -16,7 +16,6 @@
"exclude": [
"^tests/compiler/dart2js/codegen_helper\\.dart",
"^tests/compiler/dart2js/codegen/type_inference8_test\\.dart",
- "^tests/compiler/dart2js/data/one_line_dart_program\\.dart",
"^tests/compiler/dart2js/deferred/inline_restrictions_test\\.dart",
"^tests/compiler/dart2js/deferred/load_graph_segmentation2_test\\.dart",
"^tests/compiler/dart2js/deferred/load_graph_segmentation_test\\.dart",
@@ -48,9 +47,10 @@
"^tests/compiler/dart2js/needs_no_such_method_test\\.dart",
"^tests/compiler/dart2js/no_such_method_enabled_test\\.dart",
"^tests/compiler/dart2js/output_collector\\.dart",
- "^tests/compiler/dart2js/old_frontend/patch_test\\.dart",
+ "^tests/compiler/dart2js/old_frontend/data/one_line_dart_program\\.dart",
"^tests/compiler/dart2js/old_frontend/message_kind_helper\\.dart",
"^tests/compiler/dart2js/old_frontend/metadata_test\\.dart",
+ "^tests/compiler/dart2js/old_frontend/patch_test\\.dart",
"^tests/compiler/dart2js/old_frontend/reexport_handled_test\\.dart",
"^tests/compiler/dart2js/old_frontend/resolution_test\\.dart",
"^tests/compiler/dart2js/quarantined/http_launch_data/http_launch_main_package\\.dart",
diff --git a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
index 122b9ce..508e4b1 100644
--- a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
@@ -39,6 +39,7 @@
import '../compiler/js_names.dart' as JS;
import '../compiler/js_utils.dart' as JS;
import '../compiler/module_builder.dart' show pathToJSIdentifier;
+import '../compiler/shared_compiler.dart';
import '../compiler/type_utilities.dart';
import '../js_ast/js_ast.dart' as JS;
import '../js_ast/js_ast.dart' show js;
@@ -71,7 +72,11 @@
// expressions (which result in JS.Expression) and statements
// (which result in (JS.Statement).
class CodeGenerator extends Object
- with ClosureAnnotator, JSTypeRefCodegen, NullableTypeInference
+ with
+ ClosureAnnotator,
+ JSTypeRefCodegen,
+ NullableTypeInference,
+ SharedCompiler
implements AstVisitor<JS.Node> {
final AnalysisContext context;
final SummaryDataStore summaryData;
@@ -254,6 +259,8 @@
LibraryElement get currentLibrary => _currentElement.library;
+ Uri get currentLibraryUri => _currentElement.librarySource.uri;
+
CompilationUnitElement get _currentCompilationUnit {
for (var e = _currentElement;; e = e.enclosingElement) {
if (e is CompilationUnitElement) return e;
@@ -2803,32 +2810,17 @@
var typeFormals = _emitTypeFormals(type.typeFormals);
if (_reifyGeneric(element)) formals.insertAll(0, typeFormals);
+ super.enterFunction(element.name, formals,
+ () => isPotentiallyMutated(body, parameters.parameters.last.element));
+
JS.Block code = isSync
? _emitFunctionBody(element, parameters, body)
: new JS.Block([
_emitGeneratorFunction(element, parameters, body).toReturn()
..sourceInformation = _nodeStart(body)
]);
- if (element.isOperator && formals.isNotEmpty) {
- if (element.name == '[]=') {
- // []= methods need to return the value. We could also address this at
- // call sites, but it's cleaner to instead transform the operator method.
- code = JS.alwaysReturnLastParameter(code, formals.last);
- } else if (element.name == '==' && !element.source.isInSystemLibrary) {
- // In Dart `operator ==` methods are not called with a null argument.
- // This is handled before calling them. For performance reasons, we push
- // this check inside the method, to simplify our `equals` helper.
- //
- // TODO(jmesserly): in most cases this check is not necessary, because
- // the Dart code already handles it (typically by an `is` check).
- // Eliminate it when possible.
- code = new JS.Block([
- js.statement('if (# == null) return false;', [formals.first]),
- code
- ]);
- }
- }
+ code = super.exitFunction(element.name, formals, code);
return new JS.Fun(formals, code,
typeParams: typeFormals, returnType: emitTypeRef(type.returnType));
}
@@ -4163,9 +4155,7 @@
@override
JS.Statement visitReturnStatement(ReturnStatement node) {
- var e = node.expression;
- if (e == null) return new JS.Return();
- return _visitExpression(e).toReturn();
+ return super.emitReturnStatement(_visitExpression(node.expression));
}
@override
diff --git a/pkg/dev_compiler/lib/src/compiler/js_utils.dart b/pkg/dev_compiler/lib/src/compiler/js_utils.dart
index 1710810..ff3296b 100644
--- a/pkg/dev_compiler/lib/src/compiler/js_utils.dart
+++ b/pkg/dev_compiler/lib/src/compiler/js_utils.dart
@@ -26,22 +26,6 @@
return fn;
}
-/// Transform the function so the last parameter is always returned.
-///
-/// This is useful for indexed set methods, which otherwise would not have
-/// the right return value in JS.
-Block alwaysReturnLastParameter(Block body, Parameter lastParam) {
- Statement blockBody = body;
- if (Return.foundIn(body)) {
- // If a return is inside body, transform `(params) { body }` to
- // `(params) { (() => { body })(); return value; }`.
- // TODO(jmesserly): we could instead generate the return differently,
- // and avoid the immediately invoked function.
- blockBody = new Call(new ArrowFun([], body), []).toStatement();
- }
- return new Block([blockBody, new Return(lastParam)]);
-}
-
Set<Identifier> findMutatedVariables(Node scope) {
var v = new MutationVisitor();
scope.accept(v);
diff --git a/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart b/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
new file mode 100644
index 0000000..165028a
--- /dev/null
+++ b/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
@@ -0,0 +1,90 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../compiler/js_metalet.dart' as JS;
+import '../compiler/js_names.dart' as JS;
+import '../compiler/js_utils.dart' as JS;
+import '../js_ast/js_ast.dart' as JS;
+import '../js_ast/js_ast.dart' show js;
+
+/// Shared code between Analyzer and Kernel backends.
+///
+/// This class should only implement functionality that depends purely on JS
+/// classes, rather than on Analyzer/Kernel types.
+abstract class SharedCompiler {
+ /// When inside a `[]=` operator, this will be a non-null value that should be
+ /// returned by any `return;` statement.
+ ///
+ /// This lets DDC use the setter method's return value directly.
+ final List<JS.Identifier> _operatorSetResultStack = [];
+
+ /// When compiling the body of a `operator []=` method, this will be non-null
+ /// and will indicate the the value that should be returned from any `return;`
+ /// statements.
+ JS.Identifier get _operatorSetResult {
+ var stack = _operatorSetResultStack;
+ return stack.isEmpty ? null : stack.last;
+ }
+
+ /// The import URI of current library.
+ Uri get currentLibraryUri;
+
+ void enterFunction(String name, List<JS.Parameter> formals,
+ bool Function() isLastParamMutated) {
+ if (name == '[]=') {
+ _operatorSetResultStack.add(isLastParamMutated()
+ ? new JS.TemporaryId((formals.last as JS.Identifier).name)
+ : formals.last);
+ } else {
+ _operatorSetResultStack.add(null);
+ }
+ }
+
+ JS.Block exitFunction(
+ String name, List<JS.Parameter> formals, JS.Block code) {
+ if (name == "==" &&
+ formals.isNotEmpty &&
+ currentLibraryUri.scheme != 'dart') {
+ // In Dart `operator ==` methods are not called with a null argument.
+ // This is handled before calling them. For performance reasons, we push
+ // this check inside the method, to simplify our `equals` helper.
+ //
+ // TODO(jmesserly): in most cases this check is not necessary, because
+ // the Dart code already handles it (typically by an `is` check).
+ // Eliminate it when possible.
+ code = js
+ .block('{ if (# == null) return false; #; }', [formals.first, code]);
+ }
+ var setOperatorResult = _operatorSetResultStack.removeLast();
+ if (setOperatorResult != null) {
+ // []= methods need to return the value. We could also address this at
+ // call sites, but it's less code size to handle inside the operator.
+ var valueParam = formals.last;
+ var statements = code.statements;
+ if (statements.isEmpty || !statements.last.alwaysReturns) {
+ statements.add(new JS.Return(setOperatorResult));
+ }
+ if (!identical(setOperatorResult, valueParam)) {
+ // If the value parameter was mutated, then we use a temporary
+ // variable to track the initial value
+ formals.last = setOperatorResult;
+ code = js
+ .block('{ let # = #; #; }', [valueParam, setOperatorResult, code]);
+ }
+ }
+ return code;
+ }
+
+ /// Emits a return statement `return <value>;`, handling special rules for
+ /// the `operator []=` method.
+ JS.Statement emitReturnStatement(JS.Expression value) {
+ if (_operatorSetResult != null) {
+ var result = new JS.Return(_operatorSetResult);
+ return value != null
+ ? new JS.Block([value.toStatement(), result])
+ : result;
+ }
+ return value != null ? value.toReturn() : new JS.Return();
+ }
+}
diff --git a/pkg/dev_compiler/lib/src/js_ast/nodes.dart b/pkg/dev_compiler/lib/src/js_ast/nodes.dart
index 5d37dac..2f7f188 100644
--- a/pkg/dev_compiler/lib/src/js_ast/nodes.dart
+++ b/pkg/dev_compiler/lib/src/js_ast/nodes.dart
@@ -331,6 +331,12 @@
/// JavaScript syntax error due to a redeclared identifier.
bool shadows(Set<String> names) => false;
+ /// Whether this statement would always `return` if used as a funtion body.
+ ///
+ /// This is only well defined on the outermost block; it cannot be used for a
+ /// block inside of a loop (because of `break` and `continue`).
+ bool get alwaysReturns => false;
+
/// If this statement [shadows] any name from [names], this will wrap it in a
/// new scoped [Block].
Statement toScopedBlock(Set<String> names) {
@@ -357,6 +363,10 @@
isScope = false;
@override
+ bool get alwaysReturns =>
+ statements.isNotEmpty && statements.last.alwaysReturns;
+
+ @override
Block toBlock() => this;
@override
@@ -413,6 +423,10 @@
If(this.condition, this.then, this.otherwise);
If.noElse(this.condition, this.then) : this.otherwise = null;
+ @override
+ bool get alwaysReturns =>
+ hasElse && then.alwaysReturns && otherwise.alwaysReturns;
+
bool get hasElse => otherwise != null;
T accept<T>(NodeVisitor<T> visitor) => visitor.visitIf(this);
@@ -545,6 +559,9 @@
Return([this.value = null]);
+ @override
+ bool get alwaysReturns => true;
+
Statement toReturn() => this;
T accept<T>(NodeVisitor<T> visitor) => visitor.visitReturn(this);
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index 87a5058..8e64b1d 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -16,6 +16,7 @@
import '../compiler/js_names.dart' as JS;
import '../compiler/js_utils.dart' as JS;
import '../compiler/module_builder.dart' show pathToJSIdentifier;
+import '../compiler/shared_compiler.dart';
import '../js_ast/js_ast.dart' as JS;
import '../js_ast/js_ast.dart' show js;
import '../js_ast/source_map_printer.dart' show NodeEnd, NodeSpan, HoverComment;
@@ -27,7 +28,8 @@
import 'property_model.dart';
import 'type_table.dart';
-class ProgramCompiler
+class ProgramCompiler extends Object
+ with SharedCompiler
implements
StatementVisitor<JS.Statement>,
ExpressionVisitor<JS.Expression>,
@@ -248,6 +250,8 @@
ClassHierarchy get hierarchy => types.hierarchy;
+ Uri get currentLibraryUri => _currentLibrary.importUri;
+
JS.Program emitProgram(
Component p, List<Component> summaries, List<Uri> summaryUris) {
if (_moduleItems.isNotEmpty) {
@@ -2752,6 +2756,10 @@
var typeFormals = _emitTypeFormals(f.typeParameters);
formals.insertAll(0, typeFormals);
+ // TODO(jmesserly): need a way of determining if parameters are
+ // potentially mutated in Kernel. For now we assume all parameters are.
+ super.enterFunction(name, formals, () => true);
+
JS.Block code = isSync
? _emitFunctionBody(f)
: new JS.Block([
@@ -2759,25 +2767,7 @@
..sourceInformation = _nodeStart(f)
]);
- if (name != null && formals.isNotEmpty) {
- if (name == '[]=') {
- // []= methods need to return the value. We could also address this at
- // call sites, but it's cleaner to instead transform the operator method.
- code = JS.alwaysReturnLastParameter(code, formals.last);
- } else if (name == '==' && _currentLibrary.importUri.scheme != 'dart') {
- // In Dart `operator ==` methods are not called with a null argument.
- // This is handled before calling them. For performance reasons, we push
- // this check inside the method, to simplify our `equals` helper.
- //
- // TODO(jmesserly): in most cases this check is not necessary, because
- // the Dart code already handles it (typically by an `is` check).
- // Eliminate it when possible.
- code = new JS.Block([
- js.statement('if (# == null) return false;', [formals.first]),
- code
- ]);
- }
- }
+ code = super.exitFunction(name, formals, code);
return new JS.Fun(formals, code);
}
@@ -3543,9 +3533,7 @@
@override
JS.Statement visitReturnStatement(ReturnStatement node) {
- var e = node.expression;
- if (e == null) return new JS.Return();
- return _visitExpression(e).toReturn();
+ return super.emitReturnStatement(_visitExpression(node.expression));
}
@override
diff --git a/pkg/front_end/lib/src/api_prototype/compiler_options.dart b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
index 4710a15..57e667a 100644
--- a/pkg/front_end/lib/src/api_prototype/compiler_options.dart
+++ b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
@@ -8,18 +8,20 @@
import 'package:front_end/src/base/performance_logger.dart';
import 'package:kernel/target/targets.dart' show Target;
-import '../fasta/fasta_codes.dart' show LocatedMessage;
+import '../fasta/fasta_codes.dart' show FormattedMessage;
import '../fasta/severity.dart' show Severity;
import 'compilation_message.dart';
import 'file_system.dart';
import 'standard_file_system.dart';
+export '../fasta/fasta_codes.dart' show FormattedMessage;
+
/// Callback used to report errors encountered during compilation.
typedef void ErrorHandler(CompilationMessage error);
-typedef void ProblemHandler(LocatedMessage problem, Severity severity,
- String formatted, int line, int column);
+typedef void ProblemHandler(FormattedMessage problem, Severity severity,
+ List<FormattedMessage> context);
/// Front-end options relevant to compiler back ends.
///
diff --git a/pkg/front_end/lib/src/api_unstable/summary_worker.dart b/pkg/front_end/lib/src/api_unstable/summary_worker.dart
index 2144265..2fdc8e5 100644
--- a/pkg/front_end/lib/src/api_unstable/summary_worker.dart
+++ b/pkg/front_end/lib/src/api_unstable/summary_worker.dart
@@ -18,7 +18,7 @@
export 'compiler_state.dart';
export '../api_prototype/standard_file_system.dart' show StandardFileSystem;
-export '../fasta/fasta_codes.dart' show LocatedMessage;
+export '../fasta/fasta_codes.dart' show FormattedMessage;
export '../fasta/severity.dart' show Severity;
Future<InitializedCompilerState> initializeCompiler(
diff --git a/pkg/front_end/lib/src/base/processed_options.dart b/pkg/front_end/lib/src/base/processed_options.dart
index f0a3761..02f7650 100644
--- a/pkg/front_end/lib/src/base/processed_options.dart
+++ b/pkg/front_end/lib/src/base/processed_options.dart
@@ -38,6 +38,7 @@
import '../fasta/fasta_codes.dart'
show
+ FormattedMessage,
LocatedMessage,
Message,
messageCantInferPackagesFromManyInputs,
@@ -204,32 +205,46 @@
(_raw.reportMessages ?? (_raw.onError == null));
}
- void report(LocatedMessage message, Severity severity) {
+ FormattedMessage format(LocatedMessage message, Severity severity) {
+ int offset = message.charOffset;
+ Uri uri = message.uri;
+ Location location = offset == -1 ? null : getLocation(uri, offset);
+ String formatted =
+ command_line_reporting.format(message, severity, location: location);
+ return message.withFormatting(
+ formatted, location?.line ?? -1, location?.column ?? -1);
+ }
+
+ void report(LocatedMessage message, Severity severity,
+ {List<LocatedMessage> context}) {
+ context ??= [];
if (_raw.onProblem != null) {
- int offset = message.charOffset;
- Uri uri = message.uri;
- Location location = offset == -1 ? null : getLocation(uri, offset);
- _raw.onProblem(
- message,
- severity,
- command_line_reporting.format(message, severity, location: location),
- location?.line ?? -1,
- location?.column ?? -1);
+ _raw.onProblem(format(message, severity), severity,
+ context.map((message) => format(message, Severity.context)).toList());
if (command_line_reporting.shouldThrowOn(severity)) {
if (verbose) print(StackTrace.current);
throw new deprecated_InputError(
- uri,
- offset,
+ message.uri,
+ message.charOffset,
"Compilation aborted due to fatal "
"${command_line_reporting.severityName(severity)}.");
}
return;
}
+
+ // Deprecated reporting mechanisms
if (_raw.onError != null) {
_raw.onError(new _CompilationMessage(message, severity));
+ for (LocatedMessage message in context) {
+ _raw.onError(new _CompilationMessage(message, Severity.context));
+ }
}
-
- if (_reportMessages) command_line_reporting.report(message, severity);
+ if (_reportMessages) {
+ command_line_reporting.report(message, severity);
+ for (LocatedMessage message in context) {
+ command_line_reporting.report(message, Severity.context);
+ }
+ }
}
// TODO(askesc): Remove this and direct callers directly to report.
@@ -377,7 +392,11 @@
///
/// This is an asynchronous method since file system operations may be
/// required to locate/read the packages file as well as SDK metadata.
- Future<UriTranslatorImpl> getUriTranslator() async {
+ Future<UriTranslatorImpl> getUriTranslator({bool bypassCache: false}) async {
+ if (bypassCache) {
+ _uriTranslator = null;
+ _packages = null;
+ }
if (_uriTranslator == null) {
ticker.logMs("Started building UriTranslator");
var libraries = await _computeLibrarySpecification();
diff --git a/pkg/front_end/lib/src/fasta/builder/class_builder.dart b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
index 80d8055..f6d512c 100644
--- a/pkg/front_end/lib/src/fasta/builder/class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
@@ -218,13 +218,13 @@
}
void addCompileTimeError(Message message, int charOffset, int length,
- {LocatedMessage context}) {
+ {List<LocatedMessage> context}) {
library.addCompileTimeError(message, charOffset, length, fileUri,
context: context);
}
void addProblem(Message message, int charOffset, int length,
- {LocatedMessage context}) {
+ {List<LocatedMessage> context}) {
library.addProblem(message, charOffset, length, fileUri, context: context);
}
}
diff --git a/pkg/front_end/lib/src/fasta/builder/library_builder.dart b/pkg/front_end/lib/src/fasta/builder/library_builder.dart
index a252d1e..2737d27 100644
--- a/pkg/front_end/lib/src/fasta/builder/library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/library_builder.dart
@@ -80,7 +80,7 @@
/// If [fileUri] is null, it defaults to `this.fileUri`.
void addCompileTimeError(
Message message, int charOffset, int length, Uri fileUri,
- {bool wasHandled: false, LocatedMessage context}) {
+ {bool wasHandled: false, List<LocatedMessage> context}) {
fileUri ??= this.fileUri;
loader.addCompileTimeError(message, charOffset, length, fileUri,
wasHandled: wasHandled, context: context);
@@ -88,7 +88,7 @@
/// Add a problem with a severity determined by the severity of the message.
void addProblem(Message message, int charOffset, int length, Uri fileUri,
- {LocatedMessage context}) {
+ {List<LocatedMessage> context}) {
fileUri ??= this.fileUri;
loader.addProblem(message, charOffset, length, fileUri, context: context);
}
diff --git a/pkg/front_end/lib/src/fasta/compiler_context.dart b/pkg/front_end/lib/src/fasta/compiler_context.dart
index 54d8af3..1795c7e 100644
--- a/pkg/front_end/lib/src/fasta/compiler_context.dart
+++ b/pkg/front_end/lib/src/fasta/compiler_context.dart
@@ -60,8 +60,9 @@
}
/// Report [message], for example, by printing it.
- void report(LocatedMessage message, Severity severity) {
- options.report(message, severity);
+ void report(LocatedMessage message, Severity severity,
+ {List<LocatedMessage> context}) {
+ options.report(message, severity, context: context);
}
/// Report [message], for example, by printing it.
diff --git a/pkg/front_end/lib/src/fasta/constant_context.dart b/pkg/front_end/lib/src/fasta/constant_context.dart
index a6dac50..a4d646a 100644
--- a/pkg/front_end/lib/src/fasta/constant_context.dart
+++ b/pkg/front_end/lib/src/fasta/constant_context.dart
@@ -23,19 +23,4 @@
/// This means that `Object()` and `[]` are equivalent to `const Object()` and
/// `const []` respectively. `new Object()` is a compile-time error.
inferred,
-
- /// In a context that allows only constant values, but requires them to be
- /// defined as `const` explicitly. For example, in default values of optional
- /// and named parameters.
- ///
- /// The following code should emit a compile-time error:
- ///
- /// class Bar { const Bar(); }
- /// class Foo { void foo({Bar bar: Bar()}) {} }
- ///
- /// The following code should compile without errors:
- ///
- /// class Bar { const Bar(); }
- /// class Foo { void foo({Bar bar: const Bar()}) {} }
- needsExplicitConst,
}
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes.dart b/pkg/front_end/lib/src/fasta/fasta_codes.dart
index d3b42b9..3d1368d 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes.dart
@@ -122,6 +122,31 @@
if (result != 0) return result;
return message.compareTo(message);
}
+
+ FormattedMessage withFormatting(String formatted, int line, int column) {
+ return new FormattedMessage(this, formatted, line, column);
+ }
+}
+
+class FormattedMessage {
+ final LocatedMessage locatedMessage;
+
+ final String formatted;
+
+ final int line;
+
+ final int column;
+
+ const FormattedMessage(
+ this.locatedMessage, this.formatted, this.line, this.column);
+
+ Code get code => locatedMessage.code;
+
+ String get message => locatedMessage.message;
+
+ String get tip => locatedMessage.tip;
+
+ Map<String, dynamic> get arguments => locatedMessage.arguments;
}
String relativizeUri(Uri uri) {
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
index f234c10..f1d773d 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
@@ -359,16 +359,6 @@
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeCantDetermineConstness = messageCantDetermineConstness;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageCantDetermineConstness = const MessageCode(
- "CantDetermineConstness",
- severity: Severity.error,
- message:
- r"""The keyword 'const' or 'new' is required here. Due to an implementation limit, the compiler isn't able to infer 'const' or 'new' here.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeCantInferPackagesFromManyInputs =
messageCantInferPackagesFromManyInputs;
@@ -2581,6 +2571,28 @@
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String string)>
+ templateInternalProblemContextSeverity =
+ const Template<Message Function(String string)>(
+ messageTemplate:
+ r"""Non-context message has context severity: #string""",
+ withArguments: _withArgumentsInternalProblemContextSeverity);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String string)> codeInternalProblemContextSeverity =
+ const Code<Message Function(String string)>(
+ "InternalProblemContextSeverity",
+ templateInternalProblemContextSeverity,
+ severity: Severity.internalProblem);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInternalProblemContextSeverity(String string) {
+ return new Message(codeInternalProblemContextSeverity,
+ message: """Non-context message has context severity: $string""",
+ arguments: {'string': string});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeInternalProblemExtendingUnmodifiableScope =
messageInternalProblemExtendingUnmodifiableScope;
@@ -3535,6 +3547,18 @@
r"""Make sure there is an exponent, and remove any whitespace before it.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeMissingExpressionInThrow = messageMissingExpressionInThrow;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageMissingExpressionInThrow = const MessageCode(
+ "MissingExpressionInThrow",
+ analyzerCode: "MISSING_EXPRESSION_IN_THROW",
+ dart2jsCode: "*fatal*",
+ message: r"""Missing expression after 'throw'.""",
+ tip:
+ r"""Add an expression after 'throw' or use 'rethrow' to throw a caught exception""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeMissingFunctionParameters =
messageMissingFunctionParameters;
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index fe2dddf9..9af08b2 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -45,6 +45,7 @@
List<Uri> invalidatedUris = <Uri>[];
DillTarget dillLoadedData;
+ Map<Uri, Source> dillLoadedDataUriToSource = <Uri, Source>{};
List<LibraryBuilder> platformBuilders;
Map<Uri, LibraryBuilder> userBuilders;
final Uri initializeFromDillUri;
@@ -62,22 +63,27 @@
entryPoint ??= context.options.inputs.single;
return context.runInContext<Future<Component>>((CompilerContext c) async {
IncrementalCompilerData data = new IncrementalCompilerData();
- if (dillLoadedData == null) {
- UriTranslator uriTranslator = await c.options.getUriTranslator();
- ticker.logMs("Read packages file");
+ // TODO(jensj): We should only bypass the cache if .packages has been
+ // invalidated, but Flutter does not currently invalidate .packages.
+ UriTranslator uriTranslator =
+ await c.options.getUriTranslator(bypassCache: true);
+ ticker.logMs("Read packages file");
+
+ if (dillLoadedData == null) {
List<int> summaryBytes = await c.options.loadSdkSummaryBytes();
int bytesLength = prepareSummary(summaryBytes, uriTranslator, c, data);
if (initializeFromDillUri != null) {
try {
- bytesLength += await initializeFromDill(summaryBytes, c, data);
+ bytesLength +=
+ await initializeFromDill(summaryBytes, uriTranslator, c, data);
} catch (e) {
// We might have loaded x out of y libraries into the component.
// To avoid any unforeseen problems start over.
bytesLength = prepareSummary(summaryBytes, uriTranslator, c, data);
}
}
- appendLibraries(data, bytesLength, uriTranslator);
+ appendLibraries(data, bytesLength);
try {
await dillLoadedData.buildOutlines();
@@ -88,7 +94,7 @@
initializedFromDill = false;
data.reset();
bytesLength = prepareSummary(summaryBytes, uriTranslator, c, data);
- appendLibraries(data, bytesLength, uriTranslator);
+ appendLibraries(data, bytesLength);
await dillLoadedData.buildOutlines();
}
summaryBytes = null;
@@ -111,7 +117,7 @@
}
List<LibraryBuilder> reusedLibraries =
- computeReusedLibraries(invalidatedUris);
+ computeReusedLibraries(invalidatedUris, uriTranslator);
Set<Uri> reusedLibraryUris =
new Set<Uri>.from(reusedLibraries.map((b) => b.uri));
for (Uri uri in new Set<Uri>.from(dillLoadedData.loader.builders.keys)
@@ -127,7 +133,7 @@
KernelIncrementalTarget userCodeOld = userCode;
userCode = new KernelIncrementalTarget(
- c.fileSystem, false, dillLoadedData, dillLoadedData.uriTranslator,
+ c.fileSystem, false, dillLoadedData, uriTranslator,
uriToSource: c.uriToSource);
for (LibraryBuilder library in reusedLibraries) {
@@ -157,38 +163,49 @@
userCode.loader.builders.clear();
userCode = userCodeOld;
return new Component(
- libraries: libraries, uriToSource: data.uriToSource);
+ libraries: libraries, uriToSource: <Uri, Source>{});
}
userCodeOld?.loader?.builders?.clear();
userCodeOld = null;
List<Library> libraries =
new List<Library>.from(userCode.loader.libraries);
- data.uriToSource.addAll(userCode.uriToSource);
+ Map<Uri, Source> uriToSource =
+ new Map<Uri, Source>.from(dillLoadedDataUriToSource);
+ uriToSource.addAll(userCode.uriToSource);
Procedure mainMethod = componentWithDill == null
? data.userLoadedUriMain
: componentWithDill.mainMethod;
+
if (data.includeUserLoadedLibraries || fullComponent) {
- addReusedLibraries(libraries, mainMethod, reusedLibraries, data);
+ addReusedLibraries(
+ libraries, mainMethod, entryPoint, reusedLibraries, data);
}
// Clean up.
userCode.loader.releaseAncillaryResources();
// This is the incremental component.
- return new Component(libraries: libraries, uriToSource: data.uriToSource)
+ return new Component(libraries: libraries, uriToSource: uriToSource)
..mainMethod = mainMethod;
});
}
- void addReusedLibraries(List<Library> libraries, Procedure mainMethod,
- List<LibraryBuilder> reusedLibraries, IncrementalCompilerData data) {
+ void addReusedLibraries(
+ List<Library> libraries,
+ Procedure mainMethod,
+ Uri entry,
+ List<LibraryBuilder> reusedLibraries,
+ IncrementalCompilerData data) {
Map<Uri, Library> libraryMap = <Uri, Library>{};
for (Library library in libraries) {
libraryMap[library.fileUri] = library;
}
List<Uri> worklist = new List<Uri>.from(libraryMap.keys);
worklist.add(mainMethod?.enclosingLibrary?.fileUri);
+ if (entry != null) {
+ worklist.add(entry);
+ }
Map<Uri, Library> potentiallyReferencedLibraries = <Uri, Library>{};
for (LibraryBuilder library in reusedLibraries) {
@@ -246,7 +263,10 @@
}
// This procedure will try to load the dill file and will crash if it cannot.
- Future<int> initializeFromDill(List<int> summaryBytes, CompilerContext c,
+ Future<int> initializeFromDill(
+ List<int> summaryBytes,
+ UriTranslator uriTranslator,
+ CompilerContext c,
IncrementalCompilerData data) async {
int bytesLength = 0;
FileSystemEntity entity =
@@ -265,6 +285,20 @@
new BinaryBuilder(initializationBytes, disableLazyReading: true)
.readComponent(data.component);
+ // Check the any package-urls still point to the same file
+ // (e.g. the package still exists and hasn't been updated).
+ for (Library lib in data.component.libraries) {
+ if (lib.importUri.scheme == "package" &&
+ uriTranslator.translate(lib.importUri, false) != lib.fileUri) {
+ // Package has been removed or updated.
+ // This library should be thrown away.
+ // Everything that depends on it should be thrown away.
+ // TODO(jensj): Anything that doesn't depend on it can be kept.
+ // For now just don't initialize from this dill.
+ throw "Changed package";
+ }
+ }
+
initializedFromDill = true;
bytesLength += initializationBytes.length;
for (Library lib in data.component.libraries) {
@@ -275,34 +309,23 @@
data.includeUserLoadedLibraries = true;
for (Uri uri in data.component.uriToSource.keys) {
if (sdkUris.contains(uri)) continue;
- data.uriToSource[uri] = data.component.uriToSource[uri];
+ dillLoadedDataUriToSource[uri] = data.component.uriToSource[uri];
}
}
}
return bytesLength;
}
- void appendLibraries(IncrementalCompilerData data, int bytesLength,
- UriTranslator uriTranslator) {
+ void appendLibraries(IncrementalCompilerData data, int bytesLength) {
if (data.component != null) {
- List<Library> keepLibraries = <Library>[];
- for (Library lib in data.component.libraries) {
- if (lib.importUri.scheme != "package" ||
- uriTranslator.translate(lib.importUri, false) != null) {
- keepLibraries.add(lib);
- }
- }
- data.component.libraries
- ..clear()
- ..addAll(keepLibraries);
-
dillLoadedData.loader
.appendLibraries(data.component, byteCount: bytesLength);
}
ticker.logMs("Appended libraries");
}
- List<LibraryBuilder> computeReusedLibraries(Iterable<Uri> invalidatedUris) {
+ List<LibraryBuilder> computeReusedLibraries(
+ Iterable<Uri> invalidatedUris, UriTranslator uriTranslator) {
if (userCode == null && userBuilders == null) {
return <LibraryBuilder>[];
}
@@ -326,7 +349,10 @@
invalidatedFileUris.contains(library.fileUri)) ||
(library is DillLibraryBuilder &&
uri != library.library.fileUri &&
- invalidatedFileUris.contains(library.library.fileUri))) {
+ invalidatedFileUris.contains(library.library.fileUri)) ||
+ (library.uri.scheme == "package" &&
+ uriTranslator.translate(library.uri, false) !=
+ library.target.fileUri)) {
invalidatedImportUris.add(uri);
}
if (!recursive) return;
@@ -407,7 +433,6 @@
class IncrementalCompilerData {
bool includeUserLoadedLibraries;
- Map<Uri, Source> uriToSource;
Map<Uri, int> importUriToOrder;
Procedure userLoadedUriMain;
Component component;
@@ -418,7 +443,6 @@
reset() {
includeUserLoadedLibraries = false;
- uriToSource = <Uri, Source>{};
importUriToOrder = <Uri, int>{};
userLoadedUriMain = null;
component = null;
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 822a724..b3df16c 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -76,8 +76,6 @@
import '../names.dart';
-import 'constness_evaluator.dart' show evaluateConstness, ConstnessEffect;
-
import 'fasta_accessors.dart';
import 'kernel_api.dart';
@@ -185,12 +183,6 @@
/// and where that was.
Map<String, int> initializedFields;
- /// Constructor invocations (either generative or factory) with not specified
- /// `new` or `const` keywords. The constness for these should be inferred
- /// based on the subexpressions.
- List<Expression> constructorInvocationsWithImplicitConstness =
- new List<Expression>();
-
BodyBuilder(
KernelLibraryBuilder library,
this.member,
@@ -398,7 +390,8 @@
pushQualifiedReference(beginToken.next, periodBeforeName);
if (arguments != null) {
push(arguments);
- endNewExpression(beginToken);
+ buildConstructorReferenceInvocation(
+ beginToken, beginToken.offset, Constness.explicitConst);
push(popForValue());
} else {
String name = pop();
@@ -693,50 +686,6 @@
unhandled("${builder.runtimeType}", "finishFunction", builder.charOffset,
builder.fileUri);
}
-
- inferConstness();
- }
-
- // Infers constness of the constructor invocations collected so far in
- // [constructorInvocationsWithImplicitConstness], then clears out the list.
- void inferConstness() {
- // The algorithm below takes advantage of the fact that for each expression
- // that needs constness inference comes after all its subexpressions that
- // also need constness inference in
- // [constructorInvocationsWithImplicitConstness].
- for (Expression invocation in constructorInvocationsWithImplicitConstness) {
- if (invocation is ConstructorInvocation) {
- ConstnessEffect constness =
- evaluateConstness(invocation, coreTypes, uri).effect;
- if (constness == ConstnessEffect.taintedConst) {
- // TODO(dmitryas): Find a better way to unwrap the error node.
- ShadowSyntheticExpression errorMessage = buildCompileTimeError(
- fasta.messageCantDetermineConstness,
- invocation.fileOffset,
- noLength);
- invocation.replaceWith(errorMessage.desugared);
- } else {
- invocation.isConst = constness == ConstnessEffect.allowedConst;
- }
- } else if (invocation is StaticInvocation) {
- ConstnessEffect constness =
- evaluateConstness(invocation, coreTypes, uri).effect;
- if (constness == ConstnessEffect.taintedConst) {
- // TODO(dmitryas): Find a better way to unwrap the error node.
- ShadowSyntheticExpression errorMessage = buildCompileTimeError(
- fasta.messageCantDetermineConstness,
- invocation.fileOffset,
- noLength);
- invocation.replaceWith(errorMessage.desugared);
- } else {
- invocation.isConst = constness == ConstnessEffect.allowedConst;
- }
- } else {
- unhandled("${invocation.runtimeType}", "inferConstness",
- invocation.fileOffset, invocation.location.file);
- }
- }
- constructorInvocationsWithImplicitConstness.clear();
}
@override
@@ -1071,7 +1020,7 @@
LocatedMessage argMessage}) {
Message message;
Name kernelName = new Name(name, library.library);
- LocatedMessage context;
+ List<LocatedMessage> context;
if (candidate != null) {
Uri uri = candidate.location.file;
int offset = candidate.fileOffset;
@@ -1085,7 +1034,7 @@
length = name.length;
message = fasta.messageCandidateFound;
}
- context = message.withLocation(uri, offset, length);
+ context = [message.withLocation(uri, offset, length)];
}
if (isGetter) {
@@ -1131,7 +1080,9 @@
@override
Message warnUnresolvedGet(Name name, int charOffset,
- {bool isSuper: false, bool reportWarning: true, LocatedMessage context}) {
+ {bool isSuper: false,
+ bool reportWarning: true,
+ List<LocatedMessage> context}) {
Message message = isSuper
? fasta.templateSuperclassHasNoGetter.withArguments(name.name)
: fasta.templateGetterNotFound.withArguments(name.name);
@@ -1144,7 +1095,9 @@
@override
Message warnUnresolvedSet(Name name, int charOffset,
- {bool isSuper: false, bool reportWarning: true, LocatedMessage context}) {
+ {bool isSuper: false,
+ bool reportWarning: true,
+ List<LocatedMessage> context}) {
Message message = isSuper
? fasta.templateSuperclassHasNoSetter.withArguments(name.name)
: fasta.templateSetterNotFound.withArguments(name.name);
@@ -1157,7 +1110,9 @@
@override
Message warnUnresolvedMethod(Name name, int charOffset,
- {bool isSuper: false, bool reportWarning: true, LocatedMessage context}) {
+ {bool isSuper: false,
+ bool reportWarning: true,
+ List<LocatedMessage> context}) {
String plainName = name.name;
int dotIndex = plainName.lastIndexOf(".");
if (dotIndex != -1) {
@@ -2187,7 +2142,7 @@
@override
void beginFormalParameterDefaultValueExpression() {
super.push(constantContext);
- constantContext = ConstantContext.needsExplicitConst;
+ constantContext = ConstantContext.none;
}
@override
@@ -2514,11 +2469,6 @@
argMessage: argMessage);
}
if (target is Constructor) {
- if (constantContext == ConstantContext.needsExplicitConst &&
- constness == Constness.implicit) {
- return buildCompileTimeError(
- fasta.messageCantDetermineConstness, charOffset, noLength);
- }
isConst =
isConst || constantContext != ConstantContext.none && target.isConst;
if ((isConst || constantContext == ConstantContext.inferred) &&
@@ -2526,19 +2476,10 @@
return deprecated_buildCompileTimeError(
"Not a const constructor.", charOffset);
}
- ShadowConstructorInvocation invocation = new ShadowConstructorInvocation(
- target,
- targetTypeArguments,
- initialTarget,
- forest.castArguments(arguments),
+ return new ShadowConstructorInvocation(target, targetTypeArguments,
+ initialTarget, forest.castArguments(arguments),
isConst: isConst)
..fileOffset = charOffset;
- if (constness == Constness.implicit &&
- target.isConst &&
- constantContext != ConstantContext.inferred) {
- constructorInvocationsWithImplicitConstness.add(invocation);
- }
- return invocation;
} else {
Procedure procedure = target;
if (procedure.isFactory) {
@@ -2549,22 +2490,10 @@
return deprecated_buildCompileTimeError(
"Not a const factory.", charOffset);
}
- if (constantContext == ConstantContext.needsExplicitConst &&
- constness == Constness.implicit) {
- return buildCompileTimeError(
- fasta.messageCantDetermineConstness, charOffset, noLength);
- }
- ShadowFactoryConstructorInvocation invocation =
- new ShadowFactoryConstructorInvocation(target, targetTypeArguments,
- initialTarget, forest.castArguments(arguments),
- isConst: isConst)
- ..fileOffset = charOffset;
- if (constness == Constness.implicit &&
- procedure.isConst &&
- constantContext != ConstantContext.inferred) {
- constructorInvocationsWithImplicitConstness.add(invocation);
- }
- return invocation;
+ return new ShadowFactoryConstructorInvocation(target,
+ targetTypeArguments, initialTarget, forest.castArguments(arguments),
+ isConst: isConst)
+ ..fileOffset = charOffset;
} else {
return new ShadowStaticInvocation(
target, forest.castArguments(arguments),
@@ -2679,6 +2608,12 @@
}
@override
+ void beginImplicitCreationExpression(Token token) {
+ debugEvent("beginImplicitCreationExpression");
+ super.push(constantContext);
+ }
+
+ @override
void endConstLiteral(Token token) {
debugEvent("endConstLiteral");
var literal = pop();
@@ -2689,7 +2624,12 @@
@override
void endNewExpression(Token token) {
debugEvent("NewExpression");
- Token nameToken = token.next;
+ buildConstructorReferenceInvocation(
+ token.next, token.offset, Constness.explicitNew);
+ }
+
+ void buildConstructorReferenceInvocation(
+ Token nameToken, int offset, Constness constness) {
Arguments arguments = pop();
String name = pop();
List<DartType> typeArguments = pop();
@@ -2715,28 +2655,27 @@
ConstantContext savedConstantContext = pop();
if (type is TypeDeclarationBuilder) {
Expression expression = buildConstructorInvocation(
- type,
- nameToken,
- arguments,
- name,
- typeArguments,
- token.charOffset,
- optional("const", token) || optional("@", token)
- ? Constness.explicitConst
- : Constness.explicitNew);
+ type, nameToken, arguments, name, typeArguments, offset, constness);
push(deferredPrefix != null
? wrapInDeferredCheck(expression, deferredPrefix, checkOffset)
: expression);
} else if (type is ErrorAccessor) {
push(type.buildError(arguments));
} else {
- push(throwNoSuchMethodError(forest.literalNull(token),
+ push(throwNoSuchMethodError(storeOffset(forest.literalNull(null), offset),
debugName(getNodeName(type), name), arguments, nameToken.charOffset));
}
constantContext = savedConstantContext;
}
@override
+ void endImplicitCreationExpression(Token token) {
+ debugEvent("ImplicitCreationExpression");
+ buildConstructorReferenceInvocation(
+ token, token.offset, Constness.implicit);
+ }
+
+ @override
Expression buildConstructorInvocation(
TypeDeclarationBuilder type,
Token nameToken,
@@ -2834,7 +2773,8 @@
@override
void endConstExpression(Token token) {
debugEvent("endConstExpression");
- endNewExpression(token);
+ buildConstructorReferenceInvocation(
+ token.next, token.offset, Constness.explicitConst);
}
@override
@@ -3624,7 +3564,7 @@
@override
Expression buildCompileTimeError(Message message, int charOffset, int length,
- {LocatedMessage context}) {
+ {List<LocatedMessage> context}) {
library.addCompileTimeError(message, charOffset, length, uri,
wasHandled: true, context: context);
return new ShadowSyntheticExpression(library.loader
@@ -3681,7 +3621,7 @@
}
Statement buildCompileTimeErrorStatement(Message message, int charOffset,
- {LocatedMessage context}) {
+ {List<LocatedMessage> context}) {
return new ShadowExpressionStatement(
buildCompileTimeError(message, charOffset, noLength, context: context));
}
@@ -3733,9 +3673,11 @@
.withArguments(name),
offset,
noLength,
- context: fasta.templateFinalInstanceVariableAlreadyInitializedCause
- .withArguments(name)
- .withLocation(uri, builder.charOffset, noLength));
+ context: [
+ fasta.templateFinalInstanceVariableAlreadyInitializedCause
+ .withArguments(name)
+ .withLocation(uri, builder.charOffset, noLength)
+ ]);
Builder constructor =
library.loader.getDuplicatedFieldInitializerError();
return buildInvalidInitializer(
@@ -3932,20 +3874,20 @@
@override
void addCompileTimeError(Message message, int charOffset, int length,
- {LocatedMessage context}) {
+ {List<LocatedMessage> context}) {
library.addCompileTimeError(message, charOffset, length, uri,
context: context);
}
@override
void addProblem(Message message, int charOffset, int length,
- {LocatedMessage context}) {
+ {List<LocatedMessage> context}) {
library.addProblem(message, charOffset, length, uri, context: context);
}
@override
void addProblemErrorIfConst(Message message, int charOffset, int length,
- {LocatedMessage context}) {
+ {List<LocatedMessage> context}) {
// TODO(askesc): Instead of deciding on the severity, this method should
// take two messages: one to use when a constant expression is
// required and one to use otherwise.
diff --git a/pkg/front_end/lib/src/fasta/kernel/constness_evaluator.dart b/pkg/front_end/lib/src/fasta/kernel/constness_evaluator.dart
index ab7f9ce..8322954 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constness_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constness_evaluator.dart
@@ -6,7 +6,7 @@
import 'package:kernel/core_types.dart' show CoreTypes;
-import 'package:kernel/visitor.dart' show ExpressionVisitor;
+import 'package:kernel/visitor.dart' show ExpressionVisitor, DartTypeVisitor;
import '../names.dart'
show
@@ -14,14 +14,12 @@
barName,
caretName,
divisionName,
- doubleAmpersandName,
- doubleBarName,
- doubleQuestionName,
equalsName,
greaterThanName,
greaterThanOrEqualsName,
identicalName,
leftShiftName,
+ lengthName,
lessThanName,
lessThanOrEqualsName,
minusName,
@@ -31,68 +29,19 @@
percentName,
plusName,
rightShiftName,
- tildaName,
+ tildeName,
unaryMinusName;
import '../fasta_codes.dart' show templateInternalVisitorUnsupportedDefault;
import '../problems.dart' show unsupported;
-enum ConstnessEffect {
- decidedNew,
- allowedConst,
- taintedConst,
-}
-
-enum ConstantKind {
- nullConstant,
- boolConstant,
- intConstant,
- doubleConstant,
- stringConstant,
- symbolConstant,
- typeConstant,
- listConstant,
- mapConstant,
- interfaceConstant,
-}
-
-class ConstnessInfo {
- final ConstnessEffect effect;
- final ConstantKind kind;
- final Map<Reference, ConstnessInfo> fields;
-
- // TODO(dmitryas): Find a way to impose the following restrictions:
- // * `kind == null || effect != ConstnessEffect.decidedNew`
- // * `fields == null || kind == ConstantKind.interfaceConstant`.
- const ConstnessInfo(this.effect, [this.kind, this.fields]);
-
- const ConstnessInfo.decidedNew()
- : this(ConstnessEffect.decidedNew, null, null);
-
- const ConstnessInfo.allowedConst(ConstantKind kind,
- [Map<Reference, ConstnessInfo> fields])
- : this(ConstnessEffect.allowedConst, kind, fields);
-
- const ConstnessInfo.taintedConst(ConstantKind kind,
- [Map<Reference, ConstnessInfo> fields])
- : this(ConstnessEffect.taintedConst, kind, fields);
-
- bool get isConst => effect != ConstnessEffect.decidedNew;
-
- bool get isPrimitiveConstant => kind != ConstantKind.interfaceConstant;
-
- bool get isInterfaceConstant => kind == ConstantKind.interfaceConstant;
-}
-
/// Evaluates constness of the given constructor invocation.
///
/// TODO(dmitryas): Share code with the constant evaluator from
/// pkg/kernel/lib/transformations/constants.dart.
-class ConstnessEvaluator implements ExpressionVisitor<ConstnessInfo> {
- final Map<Expression, ConstnessInfo> constnesses =
- <Expression, ConstnessInfo>{};
-
+class ConstnessEvaluator
+ implements ExpressionVisitor<bool>, DartTypeVisitor<bool> {
final CoreTypes coreTypes;
/// [Uri] of the file containing the expressions that are to be evaluated.
@@ -115,285 +64,227 @@
return defaultExpression(node);
}
- ConstnessInfo evaluate(Expression node) {
- return node.accept(this);
+ @override
+ defaultDartType(DartType node) {
+ return unsupported(
+ templateInternalVisitorUnsupportedDefault
+ .withArguments("${node.runtimeType}")
+ .message,
+ -1,
+ uri);
}
- List<ConstnessInfo> evaluateList(List<Expression> nodes) {
- List<ConstnessInfo> result = new List<ConstnessInfo>(nodes.length);
- for (int i = 0; i < nodes.length; ++i) {
- result[i] = nodes[i].accept(this);
+ @override
+ visitInvalidType(InvalidType node) => false;
+
+ @override
+ visitDynamicType(DynamicType node) => true;
+
+ @override
+ visitVoidType(VoidType node) => true;
+
+ @override
+ visitBottomType(BottomType node) => true;
+
+ @override
+ visitInterfaceType(InterfaceType node) {
+ for (var type in node.typeArguments) {
+ if (!type.accept(this)) return false;
}
- return result;
+ return true;
+ }
+
+ @override
+ visitVectorType(VectorType node) => true;
+
+ @override
+ visitFunctionType(FunctionType node) {
+ if (!node.returnType.accept(this)) return false;
+ for (var parameter in node.positionalParameters) {
+ if (!parameter.accept(this)) return false;
+ }
+ for (var parameter in node.namedParameters) {
+ if (!parameter.type.accept(this)) return false;
+ }
+ for (var typeParameter in node.typeParameters) {
+ if (!typeParameter.bound.accept(this)) return false;
+ }
+ return true;
+ }
+
+ @override
+ visitTypeParameterType(TypeParameterType node) => false;
+
+ @override
+ visitTypedefType(TypedefType node) {
+ for (var type in node.typeArguments) {
+ if (!type.accept(this)) return false;
+ }
+ return true;
+ }
+
+ bool evaluate(Expression node) {
+ return node.accept(this);
}
@override
visitNullLiteral(NullLiteral node) {
- return const ConstnessInfo.allowedConst(ConstantKind.nullConstant);
+ return true;
}
@override
visitBoolLiteral(BoolLiteral node) {
- return const ConstnessInfo.allowedConst(ConstantKind.boolConstant);
+ return true;
}
@override
visitIntLiteral(IntLiteral node) {
- return const ConstnessInfo.allowedConst(ConstantKind.intConstant);
+ return true;
}
@override
visitDoubleLiteral(DoubleLiteral node) {
- return const ConstnessInfo.allowedConst(ConstantKind.doubleConstant);
+ return true;
}
@override
visitStringLiteral(StringLiteral node) {
- return const ConstnessInfo.allowedConst(ConstantKind.stringConstant);
+ return true;
}
@override
visitSymbolLiteral(SymbolLiteral node) {
- return const ConstnessInfo.allowedConst(ConstantKind.symbolConstant);
+ return true;
}
@override
visitTypeLiteral(TypeLiteral node) {
- return const ConstnessInfo.allowedConst(ConstantKind.typeConstant);
+ // TODO(dmitryas): Figure out how to handle deferred types.
+ return node.type.accept(this);
}
@override
visitListLiteral(ListLiteral node) {
- if (node.isConst) {
- return const ConstnessInfo.allowedConst(ConstantKind.listConstant);
- }
- return const ConstnessInfo.decidedNew();
+ return node.isConst;
}
@override
visitMapLiteral(MapLiteral node) {
- if (node.isConst) {
- return const ConstnessInfo.allowedConst(ConstantKind.mapConstant);
- }
- return const ConstnessInfo.decidedNew();
+ return node.isConst;
}
@override
visitConstructorInvocation(ConstructorInvocation node) {
- if (constnesses[node] != null) return constnesses[node];
-
if (!node.target.isConst) {
- return const ConstnessInfo.decidedNew();
+ return false;
}
- List<ConstnessInfo> positionalArgumentsInfos =
- new List<ConstnessInfo>(node.arguments.positional.length);
- for (int i = 0; i < positionalArgumentsInfos.length; ++i) {
- positionalArgumentsInfos[i] = node.arguments.positional[i].accept(this);
+ for (var type in node.arguments.types) {
+ if (!type.accept(this)) return false;
+ }
+ for (var expression in node.arguments.positional) {
+ if (!expression.accept(this)) return false;
+ }
+ for (var namedExpression in node.arguments.named) {
+ if (!namedExpression.value.accept(this)) return false;
}
- Map<String, ConstnessInfo> namedArgumentsInfos = <String, ConstnessInfo>{};
- for (NamedExpression namedArgument in node.arguments.named) {
- namedArgumentsInfos[namedArgument.name] =
- namedArgument.value.accept(this);
- }
-
- ConstnessEffect resultEffect =
- minConstnessEffectOnInfos(positionalArgumentsInfos);
- if (resultEffect != null) {
- resultEffect = minConstnessEffectOnPair(
- resultEffect, minConstnessEffectOnInfos(namedArgumentsInfos.values));
- } else {
- resultEffect = minConstnessEffectOnInfos(namedArgumentsInfos.values);
- }
- resultEffect ??= ConstnessEffect.allowedConst;
-
- if (resultEffect == ConstnessEffect.decidedNew) {
- return const ConstnessInfo.decidedNew();
- }
-
- return constnesses[node] =
- new ConstnessInfo(resultEffect, ConstantKind.interfaceConstant);
+ return true;
}
@override
visitMethodInvocation(MethodInvocation node) {
- Expression receiver = node.receiver;
- ConstnessInfo receiverConstness = receiver.accept(this);
- List<ConstnessInfo> positionalArgumentConstness =
- new List<ConstnessInfo>(node.arguments.positional.length);
- for (int i = 0; i < positionalArgumentConstness.length; ++i) {
- positionalArgumentConstness[i] =
- node.arguments.positional[i].accept(this);
- }
- Map<String, ConstnessInfo> namedArgumentConstness =
- <String, ConstnessInfo>{};
- for (NamedExpression namedArgument in node.arguments.named) {
- namedArgumentConstness[namedArgument.name] =
- namedArgument.value.accept(this);
+ if (node.arguments.named.isNotEmpty ||
+ node.arguments.types.isNotEmpty ||
+ !isConstantMethodName(node.name, node.arguments.positional.length)) {
+ return false;
}
- ConstnessEffect minimumConstnessEffect = receiverConstness.effect;
- minimumConstnessEffect = minConstnessEffectOnPair(minimumConstnessEffect,
- minConstnessEffectOnInfos(positionalArgumentConstness));
- minimumConstnessEffect = minConstnessEffectOnPair(minimumConstnessEffect,
- minConstnessEffectOnInfos(namedArgumentConstness.values));
-
- if (minimumConstnessEffect == ConstnessEffect.decidedNew) {
- return const ConstnessInfo.decidedNew();
+ if (!node.receiver.accept(this)) return false;
+ for (var expression in node.arguments.positional) {
+ if (!expression.accept(this)) return false;
}
- // Special case: ==.
- if (node.name == equalsName) {
- assert(node.arguments.positional.length == 1);
- return new ConstnessInfo(
- minimumConstnessEffect, ConstantKind.boolConstant);
- }
-
- // Check for operations that are known to yield a constant value, like the
- // addition of two integer constants.
- if (node.arguments.named.length == 0) {
- List<ConstantKind> argumentsKinds =
- new List<ConstantKind>(positionalArgumentConstness.length);
- for (int i = 0; i < argumentsKinds.length; ++i) {
- argumentsKinds[i] = positionalArgumentConstness[i].kind;
- }
- ConstantKind resultKind = evaluateConstantMethodInvocationKind(
- receiverConstness.kind, node.name, argumentsKinds);
- if (resultKind != null) {
- return new ConstnessInfo(minimumConstnessEffect, resultKind);
- }
- }
-
- return const ConstnessInfo.decidedNew();
+ return true;
}
@override
visitLogicalExpression(LogicalExpression node) {
- ConstnessInfo left = node.left.accept(this);
- if (node.operator == doubleBarName) {
- ConstnessInfo right = node.right.accept(this);
- if (left.isConst && right.isConst) {
- return new ConstnessInfo(
- minConstnessEffectOnPair(left.effect, right.effect),
- ConstantKind.boolConstant);
- }
- // TODO(dmitryas): Handle the case where [left] is `true`.
- } else if (node.operator == doubleAmpersandName) {
- ConstnessInfo right = node.right.accept(this);
- if (left.isConst && right.isConst) {
- return new ConstnessInfo(
- minConstnessEffectOnPair(left.effect, right.effect),
- ConstantKind.boolConstant);
- }
- // TODO(dmitryas): Handle the case when [left] is `false`.
- } else if (node.operator == doubleQuestionName) {
- ConstnessInfo right = node.right.accept(this);
- if (left.isConst && left.kind == ConstantKind.nullConstant) {
- if (right.isConst) {
- return right;
- }
- } else {
- if (left.isConst) {
- return left;
- }
- }
- }
- return const ConstnessInfo.decidedNew();
+ return node.left.accept(this) && node.right.accept(this);
}
@override
visitConditionalExpression(ConditionalExpression node) {
- // TODO(dmitryas): Handle this case after boolean constants are handled.
- return const ConstnessInfo.taintedConst(null);
+ return node.condition.accept(this) &&
+ node.then.accept(this) &&
+ node.otherwise.accept(this);
}
@override
visitPropertyGet(PropertyGet node) {
- // TODO(dmitryas): Handle this case after fields are handled.
- ConstnessInfo receiverInfo = node.receiver.accept(this);
- if (receiverInfo.isConst &&
- receiverInfo.kind == ConstantKind.stringConstant) {
- return new ConstnessInfo(receiverInfo.effect, ConstantKind.intConstant);
- }
- return const ConstnessInfo.taintedConst(null);
+ if (!isConstantPropertyName(node.name)) return false;
+ return node.receiver.accept(this);
}
@override
visitLet(Let node) {
- return node.body.accept(this);
+ return node.variable.initializer.accept(this) && node.body.accept(this);
}
@override
visitVariableGet(VariableGet node) {
- if (!node.variable.isConst) return const ConstnessInfo.decidedNew();
- // TODO(dmitryas): Handle the case of recursive dependencies.
- // TODO(dmitryas): Find a way to get fileUri of the variable.
- return node.variable.initializer.accept(this);
+ return node.variable.isConst;
}
@override
visitStaticGet(StaticGet node) {
Member target = node.target;
if (target is Field) {
- if (target.isConst) {
- if (this.uri == target.fileUri) {
- return target.initializer.accept(this);
- }
- return target.initializer
- .accept(new ConstnessEvaluator(coreTypes, target.fileUri));
- } else {
- return const ConstnessInfo.decidedNew();
- }
+ return target.isConst;
} else {
- // TODO(dmitryas): Handle the case of a tear-off.
- return const ConstnessInfo.taintedConst(null);
+ // TODO(dmitryas): Figure out how to deal with deferred functions.
+ return true;
}
}
@override
visitStringConcatenation(StringConcatenation node) {
- List<ConstnessInfo> infos =
- new List<ConstnessInfo>(node.expressions.length);
- bool isPrimitiveConstant = true;
- for (int i = 0; i < infos.length; ++i) {
- infos[i] = node.expressions[i].accept(this);
- isPrimitiveConstant = isPrimitiveConstant && infos[i].isPrimitiveConstant;
+ for (var expression in node.expressions) {
+ if (!expression.accept(this)) return false;
}
- ConstnessEffect effect = minConstnessEffectOnInfos(infos);
-
- // Only primitive constants are allowed during const string interpolation.
- if (effect == ConstnessEffect.decidedNew || !isPrimitiveConstant) {
- return const ConstnessInfo.decidedNew();
- }
-
- return new ConstnessInfo(effect, ConstantKind.stringConstant);
+ return true;
}
@override
visitStaticInvocation(StaticInvocation node) {
- // TODO(dmitryas): Handle this case better.
Member target = node.target;
- if (target.name == identicalName) {
- final TreeNode parent = target.parent;
- if (parent is Library && parent == coreTypes.coreLibrary) {
- assert(node.arguments.positional.length == 2);
- ConstnessEffect effect = minConstnessEffectOnPair(
- node.arguments.positional[0].accept(this).effect,
- node.arguments.positional[1].accept(this).effect);
- if (effect == ConstnessEffect.decidedNew) {
- return const ConstnessInfo.decidedNew();
+ if (target is Procedure) {
+ if (target.isConst && target.isFactory) {
+ for (var type in node.arguments.types) {
+ if (!type.accept(this)) return false;
}
- return new ConstnessInfo(effect, ConstantKind.boolConstant);
+ for (var expression in node.arguments.positional) {
+ if (!expression.accept(this)) return false;
+ }
+ for (var namedExpression in node.arguments.named) {
+ if (!namedExpression.value.accept(this)) return false;
+ }
+ return true;
+ } else if (target.name == identicalName) {
+ final TreeNode parent = target.parent;
+ if (parent is Library && parent == coreTypes.coreLibrary) {
+ assert(node.arguments.positional.length == 2);
+ return node.arguments.positional[0].accept(this) &&
+ node.arguments.positional[1].accept(this);
+ }
}
}
- return const ConstnessInfo.taintedConst(null);
+ return false;
}
@override
visitAsExpression(AsExpression node) {
- // TODO(dmitryas): Handle this case.
- return const ConstnessInfo.taintedConst(null);
+ return node.operand.accept(this) && node.type.accept(this);
}
@override
@@ -402,265 +293,131 @@
}
@override
- visitInvalidExpression(InvalidExpression node) {
- // TODO(dmitryas): Handle this case.
- return const ConstnessInfo.taintedConst(null);
- }
+ visitInvalidExpression(InvalidExpression node) => false;
@override
- visitVariableSet(VariableSet node) {
- // TODO(dmitryas): Handle this case.
- return const ConstnessInfo.taintedConst(null);
- }
+ visitVariableSet(VariableSet node) => false;
@override
- visitPropertySet(PropertySet node) {
- // TODO(dmitryas): Handle this case.
- return const ConstnessInfo.taintedConst(null);
- }
+ visitPropertySet(PropertySet node) => false;
@override
visitDirectPropertyGet(DirectPropertyGet node) {
- // TODO(dmitryas): Handle this case.
- return const ConstnessInfo.taintedConst(null);
+ if (!isConstantPropertyName(node.target.name)) return false;
+ return node.receiver.accept(this);
}
@override
- visitDirectPropertySet(DirectPropertySet node) {
- // TODO(dmitryas): Handle this case.
- return const ConstnessInfo.taintedConst(null);
- }
+ visitDirectPropertySet(DirectPropertySet node) => false;
@override
- visitSuperPropertyGet(SuperPropertyGet node) {
- // TODO(dmitryas): Handle this case.
- return const ConstnessInfo.taintedConst(null);
- }
+ visitSuperPropertyGet(SuperPropertyGet node) => false;
@override
- visitSuperPropertySet(SuperPropertySet node) {
- // TODO(dmitryas): Handle this case.
- return const ConstnessInfo.taintedConst(null);
- }
+ visitSuperPropertySet(SuperPropertySet node) => false;
@override
- visitStaticSet(StaticSet node) {
- // TODO(dmitryas): Handle this case.
- return const ConstnessInfo.taintedConst(null);
- }
+ visitStaticSet(StaticSet node) => false;
@override
visitDirectMethodInvocation(DirectMethodInvocation node) {
- // TODO(dmitryas): Handle this case.
- return const ConstnessInfo.taintedConst(null);
+ if (node.arguments.named.isNotEmpty ||
+ node.arguments.types.isNotEmpty ||
+ !isConstantMethodName(node.name, node.arguments.positional.length)) {
+ return false;
+ }
+
+ if (!node.receiver.accept(this)) return false;
+ for (var expression in node.arguments.positional) {
+ if (!expression.accept(this)) return false;
+ }
+
+ return true;
}
@override
- visitSuperMethodInvocation(SuperMethodInvocation node) {
- // TODO(dmitryas): Handle this case.
- return const ConstnessInfo.taintedConst(null);
- }
+ visitSuperMethodInvocation(SuperMethodInvocation node) => false;
@override
visitIsExpression(IsExpression node) {
- // TODO(dmitryas): Handle this case.
- return const ConstnessInfo.taintedConst(null);
+ return node.operand.accept(this) && node.type.accept(this);
}
@override
- visitThisExpression(ThisExpression node) {
- // TODO(dmitryas): Handle this case.
- return const ConstnessInfo.taintedConst(null);
- }
+ visitThisExpression(ThisExpression node) => false;
@override
- visitRethrow(Rethrow node) {
- // TODO(dmitryas): Handle this case.
- return const ConstnessInfo.taintedConst(null);
- }
+ visitRethrow(Rethrow node) => false;
@override
- visitThrow(Throw node) {
- // TODO(dmitryas): Handle this case.
- return const ConstnessInfo.taintedConst(null);
- }
+ visitThrow(Throw node) => false;
@override
- visitAwaitExpression(AwaitExpression node) {
- // TODO(dmitryas): Handle this case.
- return const ConstnessInfo.taintedConst(null);
- }
+ visitAwaitExpression(AwaitExpression node) => false;
@override
- visitFunctionExpression(FunctionExpression node) {
- // TODO(dmitryas): Handle this case.
- return const ConstnessInfo.taintedConst(null);
- }
+ visitFunctionExpression(FunctionExpression node) => false;
@override
- visitConstantExpression(ConstantExpression node) {
- // TODO(dmitryas): Handle this case.
- return const ConstnessInfo.taintedConst(null);
- }
+ visitConstantExpression(ConstantExpression node) => true;
@override
- visitInstantiation(Instantiation node) {
- // TODO(dmitryas): Handle this case.
- return const ConstnessInfo.taintedConst(null);
- }
+ visitInstantiation(Instantiation node) => false;
@override
- visitLoadLibrary(LoadLibrary node) {
- // TODO(dmitryas): Handle this case.
- return const ConstnessInfo.taintedConst(null);
- }
+ visitLoadLibrary(LoadLibrary node) => false;
@override
- visitCheckLibraryIsLoaded(CheckLibraryIsLoaded node) {
- // TODO(dmitryas): Handle this case.
- return const ConstnessInfo.taintedConst(null);
- }
+ visitCheckLibraryIsLoaded(CheckLibraryIsLoaded node) => false;
@override
- visitVectorCreation(VectorCreation node) {
- // TODO(dmitryas): Handle this case.
- return const ConstnessInfo.taintedConst(null);
- }
+ visitVectorCreation(VectorCreation node) => false;
@override
- visitVectorGet(VectorGet node) {
- // TODO(dmitryas): Handle this case.
- return const ConstnessInfo.taintedConst(null);
- }
+ visitVectorGet(VectorGet node) => false;
@override
- visitVectorSet(VectorSet node) {
- // TODO(dmitryas): Handle this case.
- return const ConstnessInfo.taintedConst(null);
- }
+ visitVectorSet(VectorSet node) => false;
@override
- visitVectorCopy(VectorCopy node) {
- // TODO(dmitryas): Handle this case.
- return const ConstnessInfo.taintedConst(null);
- }
+ visitVectorCopy(VectorCopy node) => false;
@override
- visitClosureCreation(ClosureCreation node) {
- // TODO(dmitryas): Handle this case.
- return const ConstnessInfo.taintedConst(null);
- }
-
- /// Tells the minimum constness effect assuming the following:
- /// * [ConstnessEffect.allowedConst] > [ConstnessEffect.taintedConst]
- /// * [ConstnessEffect.taintedConst] > [ConstnessEffect.decidedNew]
- static ConstnessEffect minConstnessEffectOnPair(
- ConstnessEffect x, ConstnessEffect y) {
- if (x == ConstnessEffect.decidedNew) {
- return x;
- }
- if (x == ConstnessEffect.allowedConst) {
- return y;
- }
- // x == ConstnessEffect.taintedConst.
- if (y == ConstnessEffect.decidedNew) {
- return y;
- }
- return x;
- }
-
- /// Calculates minimum constness effect in [effects] using
- /// [minConstnessEffectOnPair]. Returns null if [effects] is null or empty.
- static ConstnessEffect minConstnessEffect(Iterable<ConstnessEffect> effects) {
- if (effects == null || effects.isEmpty) return null;
-
- ConstnessEffect result = ConstnessEffect.allowedConst;
- for (ConstnessEffect effect in effects) {
- result = minConstnessEffectOnPair(result, effect);
- }
- return result;
- }
-
- /// Calculates minimum constness effect in [infos] using
- /// [minConstnessEffectOnPair]. Returns null if [infos] is null or empty.
- static ConstnessEffect minConstnessEffectOnInfos(
- Iterable<ConstnessInfo> infos) {
- if (infos == null || infos.isEmpty) return null;
-
- ConstnessEffect result = ConstnessEffect.allowedConst;
- for (ConstnessInfo info in infos) {
- result = minConstnessEffectOnPair(result, info.effect);
- }
- return result;
- }
+ visitClosureCreation(ClosureCreation node) => false;
/// Returns null if `receiver.name(arguments)` is not a constant.
- static ConstantKind evaluateConstantMethodInvocationKind(
- ConstantKind receiver, Name name, List<ConstantKind> arguments) {
- if (receiver == ConstantKind.stringConstant) {
- if (arguments.length == 1) {
- if (arguments[0] == ConstantKind.stringConstant) {
- if (name == plusName) return ConstantKind.intConstant;
- }
- }
- } else if (receiver == ConstantKind.boolConstant) {
- if (arguments.length == 1) {
- if (name == negationName) return ConstantKind.boolConstant;
- } else if (arguments.length == 2) {
- // TODO(dmitryas): Figure out if `&&` and `||` can be methods.
- }
- } else if (receiver == ConstantKind.intConstant) {
- if (arguments.length == 0) {
- if (name == unaryMinusName) return ConstantKind.intConstant;
- if (name == tildaName) return ConstantKind.intConstant;
- } else if (arguments.length == 1) {
- if (arguments[0] == ConstantKind.intConstant) {
- if (name == barName) return ConstantKind.intConstant;
- if (name == ampersandName) return ConstantKind.intConstant;
- if (name == caretName) return ConstantKind.intConstant;
- if (name == leftShiftName) return ConstantKind.intConstant;
- if (name == rightShiftName) return ConstantKind.intConstant;
- }
- if (arguments[0] == ConstantKind.intConstant ||
- arguments[0] == ConstantKind.doubleConstant) {
- if (name == plusName) return arguments[0];
- if (name == minusName) return arguments[0];
- if (name == multiplyName) return arguments[0];
- if (name == divisionName) return arguments[0];
- if (name == mustacheName) return arguments[0];
- if (name == percentName) return arguments[0];
- if (name == lessThanName) return ConstantKind.boolConstant;
- if (name == lessThanOrEqualsName) return ConstantKind.boolConstant;
- if (name == greaterThanOrEqualsName) return ConstantKind.boolConstant;
- if (name == greaterThanName) return ConstantKind.boolConstant;
- }
- }
- } else if (receiver == ConstantKind.doubleConstant) {
- if (arguments.length == 0) {
- if (name == unaryMinusName) return ConstantKind.doubleConstant;
- } else if (arguments.length == 1) {
- if (arguments[0] == ConstantKind.intConstant ||
- arguments[0] == ConstantKind.doubleConstant) {
- if (name == plusName) return ConstantKind.doubleConstant;
- if (name == minusName) return ConstantKind.doubleConstant;
- if (name == multiplyName) return ConstantKind.doubleConstant;
- if (name == divisionName) return ConstantKind.doubleConstant;
- if (name == mustacheName) return ConstantKind.doubleConstant;
- if (name == percentName) return ConstantKind.doubleConstant;
- if (name == lessThanName) return ConstantKind.boolConstant;
- if (name == lessThanOrEqualsName) return ConstantKind.boolConstant;
- if (name == greaterThanOrEqualsName) return ConstantKind.boolConstant;
- if (name == greaterThanName) return ConstantKind.boolConstant;
- }
- }
+ static bool isConstantMethodName(Name name, int argumentCount) {
+ if (argumentCount == 0) {
+ if (name == tildeName) return true;
+ if (name == unaryMinusName) return true;
+ } else if (argumentCount == 1) {
+ if (name == ampersandName) return true;
+ if (name == barName) return true;
+ if (name == caretName) return true;
+ if (name == divisionName) return true;
+ if (name == equalsName) return true;
+ if (name == greaterThanName) return true;
+ if (name == greaterThanOrEqualsName) return true;
+ if (name == leftShiftName) return true;
+ if (name == lessThanName) return true;
+ if (name == lessThanOrEqualsName) return true;
+ if (name == minusName) return true;
+ if (name == multiplyName) return true;
+ if (name == mustacheName) return true;
+ if (name == negationName) return true;
+ if (name == percentName) return true;
+ if (name == plusName) return true;
+ if (name == rightShiftName) return true;
}
+ return false;
+ }
- return null;
+ static bool isConstantPropertyName(Name name) {
+ return name == lengthName;
}
}
// TODO(32717): Remove this helper function when the issue is resolved.
-ConstnessInfo evaluateConstness(
- Expression expression, CoreTypes coreTypes, Uri uri) {
+bool evaluateConstness(Expression expression, CoreTypes coreTypes, Uri uri) {
return new ConstnessEvaluator(coreTypes, uri).evaluate(expression);
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
index 2798fb5a..be422f2 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
@@ -419,10 +419,12 @@
"${interfaceMember.name.name}"),
declaredMember.fileOffset,
noLength,
- context: templateOverriddenMethodCause
- .withArguments(interfaceMember.name.name)
- .withLocation(_getMemberUri(interfaceMember),
- interfaceMember.fileOffset, noLength));
+ context: [
+ templateOverriddenMethodCause
+ .withArguments(interfaceMember.name.name)
+ .withLocation(_getMemberUri(interfaceMember),
+ interfaceMember.fileOffset, noLength)
+ ]);
} else if (library.loader.target.backendTarget.strongMode &&
declaredFunction?.typeParameters != null) {
var substitution = <TypeParameter, DartType>{};
@@ -482,10 +484,12 @@
fileOffset = declaredParameter.fileOffset;
}
library.addCompileTimeError(message, fileOffset, noLength, fileUri,
- context: templateOverriddenMethodCause
- .withArguments(interfaceMember.name.name)
- .withLocation(_getMemberUri(interfaceMember),
- interfaceMember.fileOffset, noLength));
+ context: [
+ templateOverriddenMethodCause
+ .withArguments(interfaceMember.name.name)
+ .withLocation(_getMemberUri(interfaceMember),
+ interfaceMember.fileOffset, noLength)
+ ]);
return true;
}
return false;
@@ -533,10 +537,12 @@
"${interfaceMember.name.name}"),
declaredMember.fileOffset,
noLength,
- context: templateOverriddenMethodCause
- .withArguments(interfaceMember.name.name)
- .withLocation(interfaceMember.fileUri, interfaceMember.fileOffset,
- noLength));
+ context: [
+ templateOverriddenMethodCause
+ .withArguments(interfaceMember.name.name)
+ .withLocation(interfaceMember.fileUri,
+ interfaceMember.fileOffset, noLength)
+ ]);
}
if (interfaceFunction.requiredParameterCount <
declaredFunction.requiredParameterCount) {
@@ -547,10 +553,12 @@
"${interfaceMember.name.name}"),
declaredMember.fileOffset,
noLength,
- context: templateOverriddenMethodCause
- .withArguments(interfaceMember.name.name)
- .withLocation(interfaceMember.fileUri, interfaceMember.fileOffset,
- noLength));
+ context: [
+ templateOverriddenMethodCause
+ .withArguments(interfaceMember.name.name)
+ .withLocation(interfaceMember.fileUri,
+ interfaceMember.fileOffset, noLength)
+ ]);
}
for (int i = 0;
i < declaredFunction.positionalParameters.length &&
@@ -580,10 +588,12 @@
"${interfaceMember.name.name}"),
declaredMember.fileOffset,
noLength,
- context: templateOverriddenMethodCause
- .withArguments(interfaceMember.name.name)
- .withLocation(interfaceMember.fileUri, interfaceMember.fileOffset,
- noLength));
+ context: [
+ templateOverriddenMethodCause
+ .withArguments(interfaceMember.name.name)
+ .withLocation(interfaceMember.fileUri,
+ interfaceMember.fileOffset, noLength)
+ ]);
}
int compareNamedParameters(VariableDeclaration p0, VariableDeclaration p1) {
return p0.name.compareTo(p1.name);
@@ -613,10 +623,12 @@
"${interfaceMember.name.name}"),
declaredMember.fileOffset,
noLength,
- context: templateOverriddenMethodCause
- .withArguments(interfaceMember.name.name)
- .withLocation(interfaceMember.fileUri,
- interfaceMember.fileOffset, noLength));
+ context: [
+ templateOverriddenMethodCause
+ .withArguments(interfaceMember.name.name)
+ .withLocation(interfaceMember.fileUri,
+ interfaceMember.fileOffset, noLength)
+ ]);
break outer;
}
}
@@ -711,10 +723,10 @@
int originLength = typeVariables?.length ?? 0;
int patchLength = patch.typeVariables?.length ?? 0;
if (originLength != patchLength) {
- patch.addCompileTimeError(
- messagePatchClassTypeVariablesMismatch, patch.charOffset, noLength,
- context: messagePatchClassOrigin.withLocation(
- fileUri, charOffset, noLength));
+ patch.addCompileTimeError(messagePatchClassTypeVariablesMismatch,
+ patch.charOffset, noLength, context: [
+ messagePatchClassOrigin.withLocation(fileUri, charOffset, noLength)
+ ]);
} else if (typeVariables != null) {
int count = 0;
for (KernelTypeVariableBuilder t in patch.typeVariables) {
@@ -723,9 +735,10 @@
}
} else {
library.addCompileTimeError(messagePatchDeclarationMismatch,
- patch.charOffset, noLength, patch.fileUri,
- context: messagePatchDeclarationOrigin.withLocation(
- fileUri, charOffset, noLength));
+ patch.charOffset, noLength, patch.fileUri, context: [
+ messagePatchDeclarationOrigin.withLocation(
+ fileUri, charOffset, noLength)
+ ]);
}
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
index 5bd9437..2d41321 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
@@ -201,8 +201,10 @@
templateConflictsWithTypeVariable.withArguments(name),
member.charOffset,
name.length,
- context: messageConflictsWithTypeVariableCause.withLocation(
- tv.fileUri, tv.charOffset, name.length));
+ context: [
+ messageConflictsWithTypeVariableCause.withLocation(
+ tv.fileUri, tv.charOffset, name.length)
+ ]);
}
}
setParent(name, member);
@@ -226,10 +228,12 @@
if (existing != null) {
addCompileTimeError(messageTypeVariableDuplicatedName, tv.charOffset,
tv.name.length, fileUri,
- context: templateTypeVariableDuplicatedNameCause
- .withArguments(tv.name)
- .withLocation(
- fileUri, existing.charOffset, existing.name.length));
+ context: [
+ templateTypeVariableDuplicatedNameCause
+ .withArguments(tv.name)
+ .withLocation(
+ fileUri, existing.charOffset, existing.name.length)
+ ]);
} else {
typeVariablesByName[tv.name] = tv;
if (owner is ClassBuilder) {
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart
index e239fa77..ed62a8a 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart
@@ -235,8 +235,10 @@
if (!isExternal) {
patch.library.addCompileTimeError(
messagePatchNonExternal, patch.charOffset, noLength, patch.fileUri,
- context: messagePatchDeclarationOrigin.withLocation(
- fileUri, charOffset, noLength));
+ context: [
+ messagePatchDeclarationOrigin.withLocation(
+ fileUri, charOffset, noLength)
+ ]);
return false;
}
return true;
@@ -244,9 +246,9 @@
void reportPatchMismatch(Builder patch) {
library.addCompileTimeError(messagePatchDeclarationMismatch,
- patch.charOffset, noLength, patch.fileUri,
- context: messagePatchDeclarationOrigin.withLocation(
- fileUri, charOffset, noLength));
+ patch.charOffset, noLength, patch.fileUri, context: [
+ messagePatchDeclarationOrigin.withLocation(fileUri, charOffset, noLength)
+ ]);
}
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
index 1eff9b7..cfeaeab 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -661,15 +661,11 @@
fieldInitializers[constructor] = myFieldInitializers;
if (constructor.isConst && nonFinalFields.isNotEmpty) {
builder.addCompileTimeError(messageConstConstructorNonFinalField,
- constructor.fileOffset, noLength);
- // TODO(askesc): Put as context argument when multiple contexts
- // are supported.
- for (Field field in nonFinalFields) {
- builder.addCompileTimeError(
- messageConstConstructorNonFinalFieldCause,
- field.fileOffset,
- noLength);
- }
+ constructor.fileOffset, noLength,
+ context: nonFinalFields
+ .map((field) => messageConstConstructorNonFinalFieldCause
+ .withLocation(field.fileUri, field.fileOffset, noLength))
+ .toList());
nonFinalFields.clear();
}
}
diff --git a/pkg/front_end/lib/src/fasta/loader.dart b/pkg/front_end/lib/src/fasta/loader.dart
index d14ac1e..ac10060 100644
--- a/pkg/front_end/lib/src/fasta/loader.dart
+++ b/pkg/front_end/lib/src/fasta/loader.dart
@@ -20,6 +20,7 @@
SummaryTemplate,
Template,
messagePlatformPrivateLibraryAccess,
+ templateInternalProblemContextSeverity,
templateInternalProblemMissingSeverity,
templateSourceBodySummary;
@@ -201,7 +202,7 @@
/// otherwise it is added to [unhandledErrors].
void addCompileTimeError(
Message message, int charOffset, int length, Uri fileUri,
- {bool wasHandled: false, LocatedMessage context}) {
+ {bool wasHandled: false, List<LocatedMessage> context}) {
addMessage(message, charOffset, length, fileUri, Severity.error,
wasHandled: wasHandled, context: context);
}
@@ -209,7 +210,7 @@
/// Register [message] as a problem with a severity determined by the
/// intrinsic severity of the message.
void addProblem(Message message, int charOffset, int length, Uri fileUri,
- {LocatedMessage context}) {
+ {List<LocatedMessage> context}) {
Severity severity = message.code.severity;
if (severity == null) {
addMessage(message, charOffset, length, fileUri, Severity.error,
@@ -236,7 +237,7 @@
/// three times by `OutlineBuilder`, `DietListener`, and `BodyBuilder`.
bool addMessage(Message message, int charOffset, int length, Uri fileUri,
Severity severity,
- {bool wasHandled: false, LocatedMessage context}) {
+ {bool wasHandled: false, List<LocatedMessage> context}) {
String trace = """
message: ${message.message}
charOffset: $charOffset
@@ -244,11 +245,16 @@
severity: $severity
""";
if (!seenMessages.add(trace)) return false;
- target.context
- .report(message.withLocation(fileUri, charOffset, length), severity);
- if (context != null) {
- target.context.report(context, Severity.context);
+ if (message.code.severity == Severity.context) {
+ internalProblem(
+ templateInternalProblemContextSeverity
+ .withArguments(message.code.name),
+ charOffset,
+ fileUri);
}
+ target.context.report(
+ message.withLocation(fileUri, charOffset, length), severity,
+ context: context);
recordMessage(severity, message, charOffset, length, fileUri,
context: context);
if (severity == Severity.error) {
@@ -272,7 +278,7 @@
void recordMessage(Severity severity, Message message, int charOffset,
int length, Uri fileUri,
- {LocatedMessage context}) {}
+ {List<LocatedMessage> context}) {}
}
String format(double d, int fractionDigits, int width) {
diff --git a/pkg/front_end/lib/src/fasta/names.dart b/pkg/front_end/lib/src/fasta/names.dart
index d58c171..ab5b774 100644
--- a/pkg/front_end/lib/src/fasta/names.dart
+++ b/pkg/front_end/lib/src/fasta/names.dart
@@ -60,6 +60,6 @@
final Name rightShiftName = new Name(">>");
-final Name tildaName = new Name("~");
+final Name tildeName = new Name("~");
final Name unaryMinusName = new Name("unary-");
diff --git a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
index 353a654..6e9fb76 100644
--- a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
@@ -952,6 +952,16 @@
}
@override
+ void beginImplicitCreationExpression(Token token) {
+ listener?.beginImplicitCreationExpression(token);
+ }
+
+ @override
+ void endImplicitCreationExpression(Token token) {
+ listener?.endImplicitCreationExpression(token);
+ }
+
+ @override
void handleEmptyStatement(Token token) {
listener?.handleEmptyStatement(token);
}
diff --git a/pkg/front_end/lib/src/fasta/parser/identifier_context.dart b/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
index d53576c..c22e78d 100644
--- a/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
+++ b/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
@@ -126,10 +126,7 @@
recoveryTemplate: templateExpectedType);
/// Identifier is the start of a reference to a type declared elsewhere.
- static const typeReference = const IdentifierContext('typeReference',
- isScopeReference: true,
- isBuiltInIdentifierAllowed: false,
- recoveryTemplate: templateExpectedType);
+ static const typeReference = const TypeReferenceIdentifierContext();
/// Identifier is part of a reference to a type declared elsewhere, but it's
/// not the first identifier of the reference.
diff --git a/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart b/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
index 3b096fb..92bb8c2 100644
--- a/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
+++ b/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
@@ -12,7 +12,8 @@
import 'parser.dart' show Parser;
-import 'type_info.dart' show insertSyntheticIdentifierAfter;
+import 'type_info.dart'
+ show insertSyntheticIdentifierAfter, isValidTypeReference;
import 'util.dart' show optional;
@@ -66,3 +67,72 @@
optional('var', token) ||
optional('void', token);
}
+
+class TypeReferenceIdentifierContext extends IdentifierContext {
+ const TypeReferenceIdentifierContext()
+ : super('typeReference',
+ isScopeReference: true,
+ isBuiltInIdentifierAllowed: false,
+ recoveryTemplate: fasta.templateExpectedType);
+
+ @override
+ Token ensureIdentifier(Token token, Parser parser) {
+ Token next = token.next;
+ assert(next.kind != IDENTIFIER_TOKEN);
+ if (isValidTypeReference(next)) {
+ return next;
+ }
+
+ // Recovery: skip over any annotations
+ while (optional('@', next)) {
+ // TODO(danrubel): Improve this error message to indicate that an
+ // annotation is not allowed before type arguments.
+ parser.reportRecoverableErrorWithToken(
+ next, fasta.templateUnexpectedToken);
+
+ Token annotation = next.next;
+ if (annotation.isIdentifier) {
+ if (optional('(', annotation.next)) {
+ if (annotation.next.endGroup.next.isIdentifier) {
+ token = annotation.next.endGroup;
+ next = token.next;
+ }
+ } else if (annotation.next.isIdentifier) {
+ token = annotation;
+ next = token.next;
+ }
+ }
+ }
+ if (isValidTypeReference(next)) {
+ return next;
+ } else if (next.isKeywordOrIdentifier) {
+ if (optional("void", next)) {
+ parser.reportRecoverableError(next, fasta.messageInvalidVoid);
+ } else if (next.type.isBuiltIn) {
+ parser.reportRecoverableErrorWithToken(
+ next, fasta.templateBuiltInIdentifierAsType);
+ } else {
+ parser.reportRecoverableErrorWithToken(
+ next, fasta.templateExpectedType);
+ }
+ return next;
+ }
+ parser.reportRecoverableErrorWithToken(next, fasta.templateExpectedType);
+ if (!isOneOfOrEof(next, ['>', ')', ']', '{', '}', ',', ';'])) {
+ // When in doubt, consume the token to ensure we make progress
+ token = next;
+ next = token.next;
+ }
+ // Insert a synthetic identifier to satisfy listeners.
+ return insertSyntheticIdentifierAfter(token, parser);
+ }
+}
+
+bool isOneOfOrEof(Token token, Iterable<String> followingValues) {
+ for (String tokenValue in followingValues) {
+ if (optional(tokenValue, token)) {
+ return true;
+ }
+ }
+ return token.isEof;
+}
diff --git a/pkg/front_end/lib/src/fasta/parser/listener.dart b/pkg/front_end/lib/src/fasta/parser/listener.dart
index e71259c..19ed1b1 100644
--- a/pkg/front_end/lib/src/fasta/parser/listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/listener.dart
@@ -516,6 +516,12 @@
logEvent("DottedName");
}
+ void beginImplicitCreationExpression(Token token) {}
+
+ void endImplicitCreationExpression(Token token) {
+ logEvent("ImplicitCreationExpression");
+ }
+
void beginInitializedIdentifier(Token token) {}
void endInitializedIdentifier(Token nameToken) {
diff --git a/pkg/front_end/lib/src/fasta/parser/modifier_context.dart b/pkg/front_end/lib/src/fasta/parser/modifier_context.dart
index 546501b..4b23332 100644
--- a/pkg/front_end/lib/src/fasta/parser/modifier_context.dart
+++ b/pkg/front_end/lib/src/fasta/parser/modifier_context.dart
@@ -46,12 +46,6 @@
}
}
-TypeContinuation typeContinuationFromMemberKind(
- bool isVarAllowed, MemberKind memberKind) =>
- (isVarAllowed || memberKind == MemberKind.GeneralizedFunctionType)
- ? TypeContinuation.Required
- : TypeContinuation.Optional;
-
/// This class is used to parse modifiers in most locations where modifiers
/// can occur. However, it isn't used when parsing a class or when parsing
/// the modifiers of a member function (non-local),
@@ -211,7 +205,6 @@
/// but does not call handleModifier or handleModifiers.
class ModifierRecoveryContext2 {
final Parser parser;
- TypeContinuation typeContinuation;
Token abstractToken;
Token constToken;
Token covariantToken;
@@ -230,13 +223,12 @@
ModifierRecoveryContext2(this.parser);
/// Parse modifiers for class methods and fields.
- Token parseClassMemberModifiers(
- Token token, TypeContinuation typeContinuation,
+ Token parseClassMemberModifiers(Token token,
{Token externalToken,
Token staticToken,
Token covariantToken,
Token varFinalOrConst}) {
- token = parseModifiers(token, typeContinuation,
+ token = parseModifiers(token,
externalToken: externalToken,
staticToken: staticToken,
covariantToken: covariantToken,
@@ -253,7 +245,7 @@
Token parseModifiersAfterFactory(Token token,
{Token externalToken, Token staticOrCovariant, Token varFinalOrConst}) {
afterFactory = true;
- token = parseModifiers(token, null,
+ token = parseModifiers(token,
externalToken: externalToken,
staticOrCovariant: staticOrCovariant,
varFinalOrConst: varFinalOrConst);
@@ -266,9 +258,9 @@
}
/// Parse modifiers for top level functions and fields.
- Token parseTopLevelModifiers(Token token, TypeContinuation typeContinuation,
+ Token parseTopLevelModifiers(Token token,
{Token externalToken, Token varFinalOrConst}) {
- token = parseModifiers(token, typeContinuation,
+ token = parseModifiers(token,
externalToken: externalToken, varFinalOrConst: varFinalOrConst);
reportExtraneousModifier(abstractToken);
@@ -280,7 +272,7 @@
/// Parse modifiers for variable declarations.
Token parseVariableDeclarationModifiers(Token token,
{Token varFinalOrConst}) {
- token = parseModifiers(token, null, varFinalOrConst: varFinalOrConst);
+ token = parseModifiers(token, varFinalOrConst: varFinalOrConst);
reportExtraneousModifier(abstractToken);
reportExtraneousModifier(covariantToken);
@@ -300,13 +292,12 @@
/// `static` or `covariant`. The first non-null parameter of
/// [staticOrCovariant], [staticToken], or [covariantToken] will be used,
/// in that order, and the others ignored.
- Token parseModifiers(Token token, TypeContinuation typeContinuation,
+ Token parseModifiers(Token token,
{Token externalToken,
Token staticToken,
Token staticOrCovariant,
Token covariantToken,
Token varFinalOrConst}) {
- this.typeContinuation = typeContinuation;
if (externalToken != null) {
this.externalToken = externalToken;
}
@@ -390,7 +381,6 @@
Token next = token.next;
assert(optional('const', next));
if (varFinalOrConst == null && covariantToken == null) {
- typeContinuation ??= TypeContinuation.Optional;
varFinalOrConst = constToken = next;
if (afterFactory) {
@@ -474,7 +464,6 @@
Token next = token.next;
assert(optional('final', next));
if (varFinalOrConst == null && !afterFactory) {
- typeContinuation ??= TypeContinuation.Optional;
varFinalOrConst = finalToken = next;
return next;
}
@@ -529,7 +518,6 @@
Token next = token.next;
assert(optional('var', next));
if (varFinalOrConst == null && !afterFactory) {
- typeContinuation = typeContinuationAfterVar(typeContinuation);
varFinalOrConst = varToken = next;
return next;
}
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index f53eba3..f282ad6 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -1843,10 +1843,7 @@
// ensureIdentifier methods in the various IdentifierContext subclasses.
if (!next.isIdentifier) {
- if (optional("void", next)) {
- reportRecoverableError(next, fasta.messageInvalidVoid);
- token = next;
- } else if (next is ErrorToken) {
+ if (next is ErrorToken) {
// TODO(brianwilkerson): This preserves the current semantics, but the
// listener should not be recovering from this case, so this needs to be
// reworked to recover in this method (probably inside the outermost
@@ -1898,13 +1895,8 @@
reportRecoverableErrorWithToken(
next, fasta.templateBuiltInIdentifierInDeclaration);
} else if (!optional("dynamic", next)) {
- if (context == IdentifierContext.typeReference &&
- optional('.', next.next)) {
- // Built in identifiers may be used as a prefix
- } else {
- reportRecoverableErrorWithToken(
- next, fasta.templateBuiltInIdentifierAsType);
- }
+ reportRecoverableErrorWithToken(
+ next, fasta.templateBuiltInIdentifierAsType);
}
token = next;
} else if (!inPlainSync && next.type.isPseudo) {
@@ -2016,8 +2008,7 @@
followingValues = [';', '=', ','];
} else if (context == IdentifierContext.typedefDeclaration) {
followingValues = ['(', '<', ';'];
- } else if (context == IdentifierContext.typeReference ||
- context == IdentifierContext.typeReferenceContinuation) {
+ } else if (context == IdentifierContext.typeReferenceContinuation) {
followingValues = ['>', ')', ']', '}', ',', ';'];
} else if (context == IdentifierContext.typeVariableDeclaration) {
followingValues = ['<', '>', ';', '}'];
@@ -2748,7 +2739,6 @@
Token externalToken;
Token varFinalOrConst;
- TypeContinuation typeContinuation;
if (isModifier(next)) {
if (optional('external', next)) {
@@ -2757,32 +2747,27 @@
}
if (isModifier(next)) {
if (optional('final', next)) {
- typeContinuation = TypeContinuation.Optional;
varFinalOrConst = token = next;
next = token.next;
} else if (optional('var', next)) {
- typeContinuation = TypeContinuation.OptionalAfterVar;
varFinalOrConst = token = next;
next = token.next;
} else if (optional('const', next)) {
- typeContinuation = TypeContinuation.Optional;
varFinalOrConst = token = next;
next = token.next;
}
if (isModifier(next)) {
ModifierRecoveryContext2 context = new ModifierRecoveryContext2(this);
- token = context.parseTopLevelModifiers(token, typeContinuation,
+ token = context.parseTopLevelModifiers(token,
externalToken: externalToken, varFinalOrConst: varFinalOrConst);
next = token.next;
- typeContinuation = context.typeContinuation;
externalToken = context.externalToken;
varFinalOrConst = context.varFinalOrConst;
context = null;
}
}
}
- typeContinuation ??= TypeContinuation.Required;
Token beforeType = token;
TypeInfo typeInfo = computeType(token, false);
@@ -2878,12 +2863,8 @@
reportRecoverableErrorWithToken(
getOrSet, fasta.templateExtraneousModifier);
}
- // TODO(danrubel): Use typeInfo when parsing fields.
- if (typeInfo == noTypeInfo) {
- beforeType = null;
- }
return parseFields(beforeStart, externalToken, null, null, varFinalOrConst,
- beforeType, token, MemberKind.TopLevelField, typeContinuation);
+ beforeType, typeInfo, token, true);
}
Token parseFields(
@@ -2893,9 +2874,9 @@
Token covariantToken,
Token varFinalOrConst,
Token beforeType,
+ TypeInfo typeInfo,
Token beforeName,
- MemberKind memberKind,
- TypeContinuation typeContinuation) {
+ bool isTopLevel) {
if (externalToken != null) {
reportRecoverableError(externalToken, fasta.messageExternalField);
}
@@ -2905,20 +2886,19 @@
covariantToken = null;
}
}
-
- bool isTopLevel = memberKind == MemberKind.TopLevelField;
-
- if (beforeType != null) {
- parseType(beforeType, typeContinuation, null, memberKind);
- } else if (varFinalOrConst != null) {
- listener.handleNoType(beforeName);
+ if (typeInfo == noTypeInfo) {
+ if (varFinalOrConst == null) {
+ reportRecoverableError(
+ beforeName.next, fasta.messageMissingConstFinalVarOrType);
+ }
} else {
- // Recovery
- reportRecoverableError(
- beforeName.next, fasta.messageMissingConstFinalVarOrType);
- listener.handleNoType(beforeName);
+ if (varFinalOrConst != null && optional('var', varFinalOrConst)) {
+ reportRecoverableError(varFinalOrConst, fasta.messageTypeAfterVar);
+ }
}
+ typeInfo.parseType(beforeType, this);
+
IdentifierContext context = isTopLevel
? IdentifierContext.topLevelVariableDeclaration
: IdentifierContext.fieldDeclaration;
@@ -3432,7 +3412,6 @@
Token parseClassMemberImpl(Token token) {
Token beforeStart = token = parseMetadataStar(token);
- TypeContinuation typeContinuation;
Token covariantToken;
Token externalToken;
Token staticToken;
@@ -3454,22 +3433,19 @@
}
if (isModifier(next)) {
if (optional('final', next)) {
- typeContinuation = TypeContinuation.Optional;
varFinalOrConst = token = next;
next = token.next;
} else if (optional('var', next)) {
- typeContinuation = TypeContinuation.OptionalAfterVar;
varFinalOrConst = token = next;
next = token.next;
} else if (optional('const', next) && covariantToken == null) {
- typeContinuation = TypeContinuation.Optional;
varFinalOrConst = token = next;
next = token.next;
}
if (isModifier(next)) {
ModifierRecoveryContext2 context =
new ModifierRecoveryContext2(this);
- token = context.parseClassMemberModifiers(token, typeContinuation,
+ token = context.parseClassMemberModifiers(token,
externalToken: externalToken,
staticToken: staticToken,
covariantToken: covariantToken,
@@ -3481,13 +3457,11 @@
staticToken = context.staticToken;
varFinalOrConst = context.varFinalOrConst;
- typeContinuation = context.typeContinuation;
context = null;
}
}
}
}
- typeContinuation ??= TypeContinuation.Required;
listener.beginMember();
@@ -3567,8 +3541,7 @@
varFinalOrConst,
beforeType,
typeInfo,
- getOrSet,
- typeContinuation);
+ getOrSet);
}
} else if (typeInfo == noTypeInfo && varFinalOrConst == null) {
Token next2 = next.next;
@@ -3608,22 +3581,8 @@
reportRecoverableErrorWithToken(
getOrSet, fasta.templateExtraneousModifier);
}
- // TODO(danrubel): Use typeInfo when parsing fields.
- if (typeInfo == noTypeInfo) {
- beforeType = null;
- }
- token = parseFields(
- beforeStart,
- externalToken,
- staticToken,
- covariantToken,
- varFinalOrConst,
- beforeType,
- token,
- staticToken != null
- ? MemberKind.StaticField
- : MemberKind.NonStaticField,
- typeContinuation);
+ token = parseFields(beforeStart, externalToken, staticToken,
+ covariantToken, varFinalOrConst, beforeType, typeInfo, token, false);
}
listener.endMember();
return token;
@@ -4173,9 +4132,6 @@
return parseForStatement(token, null);
} else if (identical(value, 'rethrow')) {
return parseRethrowStatement(token);
- } else if (identical(value, 'throw') && optional(';', token.next.next)) {
- // TODO(kasperl): Stop dealing with throw here.
- return parseRethrowStatement(token);
} else if (identical(value, 'while')) {
return parseWhileStatement(token);
} else if (identical(value, 'do')) {
@@ -4598,9 +4554,24 @@
token.next, POSTFIX_PRECEDENCE, allowCascades);
listener.handleUnaryPrefixAssignmentExpression(operator);
return token;
- } else {
- return parsePrimary(token, IdentifierContext.expression);
+ } else if (token.next.isIdentifier) {
+ Token identifier = token.next;
+ if (optional(".", identifier.next)) {
+ identifier = identifier.next.next;
+ }
+ if (identifier.isIdentifier) {
+ // Looking at `identifier ('.' identifier)?`.
+ if (optional("<", identifier.next)) {
+ BeginToken typeArguments = identifier.next;
+ Token endTypeArguments = typeArguments.endGroup;
+ if (endTypeArguments != null &&
+ optional(".", endTypeArguments.next)) {
+ return parseImplicitCreationExpression(token);
+ }
+ }
+ }
}
+ return parsePrimary(token, IdentifierContext.expression);
}
Token parseArgumentOrIndexStar(Token token, Token typeArguments) {
@@ -5013,6 +4984,15 @@
return token;
}
+ Token parseImplicitCreationExpression(Token token) {
+ Token begin = token;
+ listener.beginImplicitCreationExpression(token);
+ token = parseConstructorReference(token);
+ token = parseRequiredArguments(token);
+ listener.endImplicitCreationExpression(begin);
+ return token;
+ }
+
/// This method parses a list or map literal that is known to start with the
/// keyword 'const'.
///
@@ -5883,6 +5863,17 @@
Token parseThrowExpression(Token token, bool allowCascades) {
Token throwToken = token.next;
assert(optional('throw', throwToken));
+ if (optional(';', throwToken.next)) {
+ // TODO(danrubel): Find a better way to intercept the parseExpression
+ // recovery to generate this error message rather than explicitly
+ // checking the next token as we are doing here.
+ reportRecoverableError(
+ throwToken.next, fasta.messageMissingExpressionInThrow);
+ rewriter.insertTokenAfter(
+ throwToken,
+ new SyntheticStringToken(
+ TokenType.STRING, '""', throwToken.next.charOffset, 0));
+ }
token = allowCascades
? parseExpression(throwToken)
: parseExpressionWithoutCascade(throwToken);
@@ -5897,14 +5888,8 @@
/// ```
Token parseRethrowStatement(Token token) {
Token throwToken = token.next;
- assert(optional('rethrow', throwToken) || optional('throw', throwToken));
+ assert(optional('rethrow', throwToken));
listener.beginRethrowStatement(throwToken);
- // TODO(kasperl): Disallow throw here.
- if (optional('throw', throwToken)) {
- expect('throw', throwToken);
- } else {
- expect('rethrow', throwToken);
- }
token = ensureSemicolon(throwToken);
listener.endRethrowStatement(throwToken, token);
return token;
@@ -6351,8 +6336,7 @@
Token varFinalOrConst,
Token beforeType,
TypeInfo typeInfo,
- Token getOrSet,
- TypeContinuation typeContinuation) {
+ Token getOrSet) {
Token next = token.next;
String value = next.stringValue;
@@ -6404,10 +6388,6 @@
getOrSet,
token);
} else {
- // TODO(danrubel): Use typeInfo when parsing fields.
- if (typeInfo == noTypeInfo) {
- beforeType = null;
- }
token = parseFields(
beforeStart,
externalToken,
@@ -6415,9 +6395,9 @@
covariantToken,
varFinalOrConst,
beforeType,
+ typeInfo,
token,
- MemberKind.NonStaticField,
- typeContinuation);
+ false);
}
}
diff --git a/pkg/front_end/lib/src/fasta/scanner/string_scanner.dart b/pkg/front_end/lib/src/fasta/scanner/string_scanner.dart
index 5d86888..236b31e 100644
--- a/pkg/front_end/lib/src/fasta/scanner/string_scanner.dart
+++ b/pkg/front_end/lib/src/fasta/scanner/string_scanner.dart
@@ -81,20 +81,3 @@
bool atEndOfFile() => scanOffset >= string.length - 1;
}
-
-/**
- * Scanner that creates tokens for a part of a larger [String], where the part
- * starts at the [baseOffset].
- */
-class SubStringScanner extends StringScanner {
- final int baseOffset;
-
- SubStringScanner(this.baseOffset, String string,
- {bool includeComments: false})
- : super(string, includeComments: includeComments);
-
- @override
- void beginToken() {
- tokenStart = baseOffset + stringOffset;
- }
-}
diff --git a/pkg/front_end/lib/src/fasta/source/outline_builder.dart b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
index 36be86a..0bdf2dd 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -855,10 +855,12 @@
templateDuplicatedParameterName.withArguments(formals[1].name),
formals[1].charOffset,
formals[1].name.length,
- context: templateDuplicatedParameterNameCause
- .withArguments(formals[1].name)
- .withLocation(
- uri, formals[0].charOffset, formals[0].name.length));
+ context: [
+ templateDuplicatedParameterNameCause
+ .withArguments(formals[1].name)
+ .withLocation(
+ uri, formals[0].charOffset, formals[0].name.length)
+ ]);
}
} else if (formals.length > 2) {
Map<String, FormalParameterBuilder> seenNames =
@@ -869,11 +871,13 @@
addCompileTimeError(
templateDuplicatedParameterName.withArguments(formal.name),
formal.charOffset,
- formal.name.length);
- addCompileTimeError(
- templateDuplicatedParameterNameCause.withArguments(formal.name),
- seenNames[formal.name].charOffset,
- seenNames[formal.name].name.length);
+ formal.name.length,
+ context: [
+ templateDuplicatedParameterNameCause
+ .withArguments(formal.name)
+ .withLocation(uri, seenNames[formal.name].charOffset,
+ seenNames[formal.name].name.length)
+ ]);
} else {
seenNames[formal.name] = formal;
}
@@ -1179,13 +1183,13 @@
@override
void addCompileTimeError(Message message, int charOffset, int length,
- {LocatedMessage context}) {
+ {List<LocatedMessage> context}) {
library.addCompileTimeError(message, charOffset, length, uri,
context: context);
}
void addProblem(Message message, int charOffset, int length,
- {LocatedMessage context}) {
+ {List<LocatedMessage> context}) {
library.addProblem(message, charOffset, length, uri, context: context);
}
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index c82040d..149991e 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -486,9 +486,11 @@
deferred.charOffset,
noLength,
fileUri,
- context: templateDeferredPrefixDuplicatedCause
- .withArguments(name)
- .withLocation(fileUri, other.charOffset, noLength));
+ context: [
+ templateDeferredPrefixDuplicatedCause
+ .withArguments(name)
+ .withLocation(fileUri, other.charOffset, noLength)
+ ]);
}
return existing
..exportScope.merge(builder.exportScope,
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index e3e168e..79676d4 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -527,10 +527,12 @@
.withArguments(builder.fullNameForErrors),
cls.charOffset,
noLength,
- context: templateIllegalMixinDueToConstructorsCause
- .withArguments(builder.fullNameForErrors)
- .withLocation(constructory.fileUri,
- constructory.charOffset, noLength));
+ context: [
+ templateIllegalMixinDueToConstructorsCause
+ .withArguments(builder.fullNameForErrors)
+ .withLocation(constructory.fileUri,
+ constructory.charOffset, noLength)
+ ]);
}
}
}
@@ -761,7 +763,7 @@
void recordMessage(Severity severity, Message message, int charOffset,
int length, Uri fileUri,
- {LocatedMessage context}) {
+ {List<LocatedMessage> context}) {
if (instrumentation == null) return;
if (charOffset == -1 &&
@@ -811,8 +813,13 @@
// TODO(ahe): Should I add an InstrumentationValue for Message?
new InstrumentationValueLiteral(message.code.name));
if (context != null) {
- instrumentation.record(context.uri, context.charOffset, "context",
- new InstrumentationValueLiteral(context.code.name));
+ for (LocatedMessage contextMessage in context) {
+ instrumentation.record(
+ contextMessage.uri,
+ contextMessage.charOffset,
+ "context",
+ new InstrumentationValueLiteral(contextMessage.code.name));
+ }
}
}
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 795a7c7..dc8a017 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -277,6 +277,14 @@
analyzerCode: EXPECTED_TYPE_NAME
dart2jsCode: "*fatal*"
+MissingExpressionInThrow:
+ template: "Missing expression after 'throw'."
+ tip: "Add an expression after 'throw' or use 'rethrow' to throw a caught exception"
+ analyzerCode: MISSING_EXPRESSION_IN_THROW
+ dart2jsCode: "*fatal*"
+ statement:
+ - "throw;"
+
MissingConstFinalVarOrType:
template: "Variables must be declared using the keywords 'const', 'final', 'var' or a type name."
tip: "Try adding the name of the type of the variable or the keyword 'var'."
@@ -1249,6 +1257,10 @@
template: "Message code missing severity: #string"
severity: INTERNAL_PROBLEM
+InternalProblemContextSeverity:
+ template: "Non-context message has context severity: #string"
+ severity: INTERNAL_PROBLEM
+
InternalVerificationError:
template: |
Verification of the generated program failed:
@@ -2049,10 +2061,3 @@
template: "Can't invoke the type '#type' because its declaration of `.call` is not a method."
tip: "Change .call to a method or explicitly invoke .call."
severity: ERROR
-
-# TODO(ahe): Remove this message when the underlying issue is fixed.
-CantDetermineConstness:
- template: "The keyword 'const' or 'new' is required here. Due to an implementation limit, the compiler isn't able to infer 'const' or 'new' here."
- severity: ERROR
- expression:
- - "bool.fromEnvironment('fisk')"
diff --git a/pkg/front_end/test/fasta/assert_locations_test.dart b/pkg/front_end/test/fasta/assert_locations_test.dart
index a2e7355..e282b79 100644
--- a/pkg/front_end/test/fasta/assert_locations_test.dart
+++ b/pkg/front_end/test/fasta/assert_locations_test.dart
@@ -16,7 +16,7 @@
import 'package:front_end/src/testing/compiler_common.dart' show compileScript;
-import 'package:front_end/src/fasta/fasta_codes.dart' show LocatedMessage;
+import 'package:front_end/src/fasta/fasta_codes.dart' show FormattedMessage;
import 'package:front_end/src/fasta/severity.dart' show Severity;
@@ -137,9 +137,9 @@
asyncTest(() async {
Test test = generateTest();
CompilerOptions options = new CompilerOptions()
- ..onProblem = (LocatedMessage message, Severity severity,
- String formatted, int line, int column) {
- Expect.fail("Unexpected error: $formatted");
+ ..onProblem = (FormattedMessage message, Severity severity,
+ List<FormattedMessage> context) {
+ Expect.fail("Unexpected error: ${message.formatted}");
}
..strongMode = true;
Component p = await compileScript(test.source,
diff --git a/pkg/front_end/test/fasta/incremental_hello_test.dart b/pkg/front_end/test/fasta/incremental_hello_test.dart
index 7976f2d..f096675 100644
--- a/pkg/front_end/test/fasta/incremental_hello_test.dart
+++ b/pkg/front_end/test/fasta/incremental_hello_test.dart
@@ -21,16 +21,16 @@
import 'package:front_end/src/fasta/compiler_context.dart' show CompilerContext;
-import 'package:front_end/src/fasta/fasta_codes.dart' show LocatedMessage;
+import 'package:front_end/src/fasta/fasta_codes.dart' show FormattedMessage;
import 'package:front_end/src/fasta/incremental_compiler.dart'
show IncrementalCompiler;
import 'package:front_end/src/fasta/severity.dart' show Severity;
-void problemHandler(LocatedMessage message, Severity severity, String formatted,
- int line, int column) {
- throw "Unexpected message: $formatted";
+void problemHandler(FormattedMessage message, Severity severity,
+ List<FormattedMessage> context) {
+ throw "Unexpected message: ${message.formatted}";
}
test({bool sdkFromSource}) async {
diff --git a/pkg/front_end/test/fasta/messages_test.dart b/pkg/front_end/test/fasta/messages_test.dart
index 9386d6e..279bc8a 100644
--- a/pkg/front_end/test/fasta/messages_test.dart
+++ b/pkg/front_end/test/fasta/messages_test.dart
@@ -24,7 +24,7 @@
import 'package:front_end/src/compute_platform_binaries_location.dart'
show computePlatformBinariesLocation;
-import 'package:front_end/src/fasta/fasta_codes.dart' show LocatedMessage;
+import 'package:front_end/src/fasta/fasta_codes.dart' show FormattedMessage;
import 'package:front_end/src/fasta/severity.dart'
show Severity, severityEnumValues;
@@ -255,9 +255,9 @@
..write(message);
buffer.write("\n${span.text}");
for (List problem in problems) {
- LocatedMessage messsage = problem[0];
- String formatted = problem[2];
- buffer.write("\nCode: ${messsage.code.name}");
+ FormattedMessage message = problem[0];
+ String formatted = message.formatted;
+ buffer.write("\nCode: ${message.code.name}");
buffer.write("\n > ");
buffer.write(formatted.replaceAll("\n", "\n > "));
}
@@ -402,9 +402,9 @@
..sdkSummary = computePlatformBinariesLocation()
.resolve("vm_platform_strong.dill")
..fileSystem = new HybridFileSystem(suite.fileSystem)
- ..onProblem = (LocatedMessage problem, Severity severity,
- String formatted, int line, int column) {
- problems.add([problem, severity, formatted, line, column]);
+ ..onProblem = (FormattedMessage problem, Severity severity,
+ List<FormattedMessage> context) {
+ problems.add([problem, severity]);
}
..strongMode = true,
uri,
@@ -412,7 +412,7 @@
List<List> unexpectedProblems = <List>[];
for (List problem in problems) {
- LocatedMessage message = problem[0];
+ FormattedMessage message = problem[0];
if (message.code.name != example.expectedCode) {
unexpectedProblems.add(problem);
}
diff --git a/pkg/front_end/test/fasta/super_mixins_test.dart b/pkg/front_end/test/fasta/super_mixins_test.dart
index 450dac8..d0ad9eb 100644
--- a/pkg/front_end/test/fasta/super_mixins_test.dart
+++ b/pkg/front_end/test/fasta/super_mixins_test.dart
@@ -16,7 +16,7 @@
import 'package:front_end/src/testing/compiler_common.dart' show compileScript;
import 'package:front_end/src/fasta/fasta_codes.dart'
- show LocatedMessage, codeSuperclassHasNoMethod;
+ show FormattedMessage, codeSuperclassHasNoMethod;
import 'package:front_end/src/fasta/severity.dart' show Severity;
@@ -68,10 +68,11 @@
''';
ProblemHandler _makeProblemHandler(Set<String> names) {
- return (LocatedMessage message, Severity severity, String formatted, int line,
- int column) {
+ return (FormattedMessage message, Severity severity,
+ List<FormattedMessage> context) {
Expect.equals(Severity.error, severity);
Expect.equals(codeSuperclassHasNoMethod, message.code);
+ Expect.isTrue(context.isEmpty);
names.add(message.arguments['name']);
};
}
diff --git a/pkg/front_end/test/incremental_bulk_compiler_full.dart b/pkg/front_end/test/incremental_bulk_compiler_full.dart
index 6a78e85..ead6b7b 100644
--- a/pkg/front_end/test/incremental_bulk_compiler_full.dart
+++ b/pkg/front_end/test/incremental_bulk_compiler_full.dart
@@ -15,7 +15,7 @@
import 'package:front_end/src/compute_platform_binaries_location.dart'
show computePlatformBinariesLocation;
-import 'package:front_end/src/fasta/fasta_codes.dart' show LocatedMessage;
+import 'package:front_end/src/fasta/fasta_codes.dart' show FormattedMessage;
import 'package:front_end/src/fasta/incremental_compiler.dart'
show IncrementalCompiler;
@@ -60,8 +60,8 @@
var options = new CompilerOptions()
..sdkRoot = sdkRoot
..librariesSpecificationUri = Uri.base.resolve("sdk/lib/libraries.json")
- ..onProblem = (LocatedMessage message, Severity severity, String formatted,
- int line, int column) {
+ ..onProblem = (FormattedMessage problem, Severity severity,
+ List<FormattedMessage> context) {
// ignore
}
..strongMode = strong;
diff --git a/pkg/front_end/test/incremental_dart2js_load_from_dill_test.dart b/pkg/front_end/test/incremental_dart2js_load_from_dill_test.dart
index 50cedd6..0d52517 100644
--- a/pkg/front_end/test/incremental_dart2js_load_from_dill_test.dart
+++ b/pkg/front_end/test/incremental_dart2js_load_from_dill_test.dart
@@ -66,5 +66,18 @@
List<int> initializedDillData =
new File.fromUri(fullDillFromInitialized).readAsBytesSync();
checkIsEqual(normalDillData, initializedDillData);
+
+ // Also try without invalidating anything.
+ stopwatch.reset();
+ initializeResult = await initializedCompile(
+ dart2jsUrl, fullDillFromInitialized, initializeWith, []);
+ Expect.equals(initializeExpect, initializeResult);
+ print("Initialized compile(s) from ${initializeWith.pathSegments.last} "
+ "took ${stopwatch.elapsedMilliseconds} ms");
+
+ // Compare the two files.
+ initializedDillData =
+ new File.fromUri(fullDillFromInitialized).readAsBytesSync();
+ checkIsEqual(normalDillData, initializedDillData);
}
}
diff --git a/pkg/front_end/test/incremental_load_from_dill_test.dart b/pkg/front_end/test/incremental_load_from_dill_test.dart
index b324e31..610c148 100644
--- a/pkg/front_end/test/incremental_load_from_dill_test.dart
+++ b/pkg/front_end/test/incremental_load_from_dill_test.dart
@@ -22,7 +22,7 @@
import 'package:front_end/src/compute_platform_binaries_location.dart'
show computePlatformBinariesLocation;
-import 'package:front_end/src/fasta/fasta_codes.dart' show LocatedMessage;
+import 'package:front_end/src/fasta/fasta_codes.dart' show FormattedMessage;
import 'package:front_end/src/fasta/incremental_compiler.dart'
show IncrementalCompiler;
@@ -174,15 +174,33 @@
await new File.fromUri(platformUri).readAsBytes();
List<int> newestWholeComponent;
+ MemoryFileSystem fs;
+ Map<String, String> sourceFiles;
+ CompilerOptions options;
+ TestIncrementalCompiler compiler;
for (var world in worlds) {
- MemoryFileSystem fs = new MemoryFileSystem(base);
+ bool brandNewWorld = true;
+ if (world["worldType"] == "updated") {
+ brandNewWorld = false;
+ }
+
+ if (brandNewWorld) {
+ fs = new MemoryFileSystem(base);
+ }
fs.entityForUri(sdkSummary).writeAsBytesSync(sdkSummaryData);
bool expectInitializeFromDill = false;
if (newestWholeComponent != null && newestWholeComponent.isNotEmpty) {
fs.entityForUri(initializeFrom).writeAsBytesSync(newestWholeComponent);
expectInitializeFromDill = true;
}
- Map<String, String> sourceFiles = world["sources"];
+ if (world["expectInitializeFromDill"] != null) {
+ expectInitializeFromDill = world["expectInitializeFromDill"];
+ }
+ if (brandNewWorld) {
+ sourceFiles = new Map<String, String>.from(world["sources"]);
+ } else {
+ sourceFiles.addAll(world["sources"]);
+ }
Uri packagesUri;
for (String filename in sourceFiles.keys) {
String data = sourceFiles[filename] ?? "";
@@ -194,32 +212,35 @@
fs.entityForUri(uri).writeAsStringSync(data);
}
- CompilerOptions options = getOptions(strong);
- options.fileSystem = fs;
- options.sdkRoot = null;
- options.sdkSummary = sdkSummary;
- if (packagesUri != null) {
- options.packagesFileUri = packagesUri;
+ if (brandNewWorld) {
+ options = getOptions(strong);
+ options.fileSystem = fs;
+ options.sdkRoot = null;
+ options.sdkSummary = sdkSummary;
+ if (packagesUri != null) {
+ options.packagesFileUri = packagesUri;
+ }
}
bool gotError = false;
List<String> formattedErrors = <String>[];
bool gotWarning = false;
List<String> formattedWarnings = <String>[];
- options.onProblem = (LocatedMessage message, Severity severity,
- String formatted, int line, int column) {
+ options.onProblem = (FormattedMessage problem, Severity severity,
+ List<FormattedMessage> context) {
if (severity == Severity.error) {
gotError = true;
- formattedErrors.add(formatted);
+ formattedErrors.add(problem.formatted);
} else if (severity == Severity.warning) {
gotWarning = true;
- formattedWarnings.add(formatted);
+ formattedWarnings.add(problem.formatted);
}
};
Uri entry = base.resolve(world["entry"]);
- TestIncrementalCompiler compiler =
- new TestIncrementalCompiler(options, entry, initializeFrom);
+ if (brandNewWorld) {
+ compiler = new TestIncrementalCompiler(options, entry, initializeFrom);
+ }
if (world["invalidate"] != null) {
for (var filename in world["invalidate"]) {
@@ -228,7 +249,7 @@
}
Stopwatch stopwatch = new Stopwatch()..start();
- Component component = await compiler.computeDelta();
+ Component component = await compiler.computeDelta(fullComponent: true);
if (world["errors"] == true && !gotError) {
throw "Expected error, but didn't get any.";
} else if (world["errors"] != true && gotError) {
@@ -254,19 +275,27 @@
throw "Expected that initializedFromDill would be "
"$expectInitializeFromDill but was ${compiler.initializedFromDill}";
}
- if (world["invalidate"] != null) {
- Expect.equals(world["invalidate"].length,
- compiler.invalidatedImportUrisForTesting.length);
- List expectedInvalidatedUri = world["expectedInvalidatedUri"];
- if (expectedInvalidatedUri != null) {
- Expect.setEquals(
- expectedInvalidatedUri
- .map((s) => Uri.parse(substituteVariables(s, base))),
- compiler.invalidatedImportUrisForTesting);
+ if (world["checkInvalidatedFiles"] != false) {
+ if (world["invalidate"] != null) {
+ Expect.equals(world["invalidate"].length,
+ compiler.invalidatedImportUrisForTesting.length);
+ List expectedInvalidatedUri = world["expectedInvalidatedUri"];
+ if (expectedInvalidatedUri != null) {
+ Expect.setEquals(
+ expectedInvalidatedUri
+ .map((s) => Uri.parse(substituteVariables(s, base))),
+ compiler.invalidatedImportUrisForTesting);
+ }
+ } else {
+ Expect.isNull(compiler.invalidatedImportUrisForTesting);
+ Expect.isNull(world["expectedInvalidatedUri"]);
}
- } else {
- Expect.isNull(compiler.invalidatedImportUrisForTesting);
- Expect.isNull(world["expectedInvalidatedUri"]);
+ }
+
+ {
+ Component component2 = await compiler.computeDelta(fullComponent: true);
+ List<int> thisWholeComponent = serializeComponent(component2);
+ checkIsEqual(newestWholeComponent, thisWholeComponent);
}
}
}
@@ -289,10 +318,10 @@
var options = new CompilerOptions()
..sdkRoot = sdkRoot
..librariesSpecificationUri = Uri.base.resolve("sdk/lib/libraries.json")
- ..onProblem = (LocatedMessage message, Severity severity, String formatted,
- int line, int column) {
+ ..onProblem = (FormattedMessage problem, Severity severity,
+ List<FormattedMessage> context) {
if (severity == Severity.error || severity == Severity.warning) {
- Expect.fail("Unexpected error: $formatted");
+ Expect.fail("Unexpected error: ${problem.formatted}");
}
}
..strongMode = strong;
@@ -328,6 +357,14 @@
throwOnEmptyMixinBodies(initializedComponent);
bool result = compiler.initializedFromDill;
await writeComponentToFile(initializedComponent, output);
+
+ var initializedComponent2 = await compiler.computeDelta(fullComponent: true);
+ throwOnEmptyMixinBodies(initializedComponent2);
+ Expect.equals(initializedComponent.libraries.length,
+ initializedComponent2.libraries.length);
+ Expect.equals(initializedComponent.uriToSource.length,
+ initializedComponent2.uriToSource.length);
+
for (Uri invalidateUri in invalidateUris) {
compiler.invalidate(invalidateUri);
}
diff --git a/pkg/front_end/testcases/implicit_const_with_static_fields.dart.direct.expect b/pkg/front_end/testcases/implicit_const_with_static_fields.dart.direct.expect
index f928029..e086d53 100644
--- a/pkg/front_end/testcases/implicit_const_with_static_fields.dart.direct.expect
+++ b/pkg/front_end/testcases/implicit_const_with_static_fields.dart.direct.expect
@@ -10,6 +10,6 @@
}
static const field dynamic constTopLevelField = 42;
static method main() → dynamic {
- const self::C::•(self::C::constField);
- const self::C::•(self::constTopLevelField);
+ new self::C::•(self::C::constField);
+ new self::C::•(self::constTopLevelField);
}
diff --git a/pkg/front_end/testcases/implicit_const_with_static_fields.dart.direct.transformed.expect b/pkg/front_end/testcases/implicit_const_with_static_fields.dart.direct.transformed.expect
index f928029..e086d53 100644
--- a/pkg/front_end/testcases/implicit_const_with_static_fields.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/implicit_const_with_static_fields.dart.direct.transformed.expect
@@ -10,6 +10,6 @@
}
static const field dynamic constTopLevelField = 42;
static method main() → dynamic {
- const self::C::•(self::C::constField);
- const self::C::•(self::constTopLevelField);
+ new self::C::•(self::C::constField);
+ new self::C::•(self::constTopLevelField);
}
diff --git a/pkg/front_end/testcases/implicit_const_with_static_fields.dart.strong.expect b/pkg/front_end/testcases/implicit_const_with_static_fields.dart.strong.expect
index 90d9837..c4b4907 100644
--- a/pkg/front_end/testcases/implicit_const_with_static_fields.dart.strong.expect
+++ b/pkg/front_end/testcases/implicit_const_with_static_fields.dart.strong.expect
@@ -10,6 +10,6 @@
}
static const field core::int constTopLevelField = 42;
static method main() → dynamic {
- const self::C::•(self::C::constField);
- const self::C::•(self::constTopLevelField);
+ new self::C::•(self::C::constField);
+ new self::C::•(self::constTopLevelField);
}
diff --git a/pkg/front_end/testcases/implicit_const_with_static_fields.dart.strong.transformed.expect b/pkg/front_end/testcases/implicit_const_with_static_fields.dart.strong.transformed.expect
index 90d9837..c4b4907 100644
--- a/pkg/front_end/testcases/implicit_const_with_static_fields.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/implicit_const_with_static_fields.dart.strong.transformed.expect
@@ -10,6 +10,6 @@
}
static const field core::int constTopLevelField = 42;
static method main() → dynamic {
- const self::C::•(self::C::constField);
- const self::C::•(self::constTopLevelField);
+ new self::C::•(self::C::constField);
+ new self::C::•(self::constTopLevelField);
}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/disappearing_package.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/disappearing_package.yaml
index 78c978d..e441068 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/disappearing_package.yaml
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/disappearing_package.yaml
@@ -25,8 +25,11 @@
.packages: dummy:${outDirUri}
expectedLibraryCount: 2
- entry: main.dart
- invalidate:
- - main.dart
+ # TODO(jensj): For now we don't initialize from dill when a package was
+ # changed.
+ #invalidate:
+ # - main.dart
+ expectInitializeFromDill: false
sources:
main.dart: |
main() {
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_invalidate_on_export_of_main.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/no_invalidate_on_export_of_main.yaml
new file mode 100644
index 0000000..c9e0195
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_invalidate_on_export_of_main.yaml
@@ -0,0 +1,16 @@
+# Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE.md file.
+
+# Invalidate nothing when the entrypoint just exports another file
+# (which has main).
+
+type: basic
+entry: a.dart
+strong: true
+invalidate:
+sources:
+ a.dart: |
+ export 'b.dart';
+ b.dart: |
+ main() { print("hello"); }
\ No newline at end of file
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package.yaml
new file mode 100644
index 0000000..471546a
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package.yaml
@@ -0,0 +1,65 @@
+# Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE.md file.
+
+# Compile an application with a package and use it.
+# Then update the package from .packages.
+# The old package is still included in the dill file we initialize from,
+# but shouldn't cause trouble, nor be included in the output.
+
+type: newworld
+strong: false
+worlds:
+ - entry: main.dart
+ sources:
+ main.dart: |
+ import "package:dummy/b.dart";
+ main() {
+ print("hello");
+ b();
+ }
+ package_0.1.0/a.dart: |
+ a() {
+ la1();
+ }
+ la1() {
+ print("v0.1.0");
+ }
+ package_0.1.0/b.dart: |
+ import "a.dart";
+ b() {
+ a();
+ }
+ .packages: dummy:${outDirUri}package_0.1.0
+ expectedLibraryCount: 3
+ - entry: main.dart
+ # TODO(jensj): For now we don't initialize from dill when a package was
+ # changed.
+ #invalidate:
+ # - main.dart
+ expectInitializeFromDill: false
+ sources:
+ main.dart: |
+ import "package:dummy/b.dart";
+ main() {
+ print("hello");
+ b();
+ }
+ package_0.1.0/a.dart: |
+ a() {
+ la1();
+ }
+ la1() {
+ print("v0.1.0");
+ }
+ package_0.1.0/b.dart: |
+ import "a.dart";
+ b() {
+ a();
+ }
+ package_0.1.1/b.dart: |
+ b() {
+ print("hello from v0.1.1");
+ }
+ .packages: dummy:${outDirUri}package_0.1.1
+ expectedLibraryCount: 2
\ No newline at end of file
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package_2.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package_2.yaml
new file mode 100644
index 0000000..fcf5918
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package_2.yaml
@@ -0,0 +1,64 @@
+# Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE.md file.
+
+# Compile an application with a package and use it.
+# Then update the package from .packages.
+# The old package is still included in the dill file we initialize from,
+# but shouldn't cause trouble, nor be included in the output.
+
+type: newworld
+strong: false
+worlds:
+ - entry: main.dart
+ sources:
+ main.dart: |
+ import "package:dummy/b.dart";
+ main() {
+ print("hello");
+ b();
+ }
+ package_0.1.0/a.dart: |
+ a() {
+ la1();
+ }
+ la1() {
+ print("v0.1.0");
+ }
+ package_0.1.0/b.dart: |
+ import "a.dart";
+ b() {
+ a();
+ }
+ .packages: dummy:${outDirUri}package_0.1.0
+ expectedLibraryCount: 3
+ - entry: main.dart
+ invalidate:
+ # TODO(jensj): For now we don't initialize from dill when a package was
+ # changed.
+ expectInitializeFromDill: false
+ sources:
+ main.dart: |
+ import "package:dummy/b.dart";
+ main() {
+ print("hello");
+ b();
+ }
+ package_0.1.0/a.dart: |
+ a() {
+ la1();
+ }
+ la1() {
+ print("v0.1.0");
+ }
+ package_0.1.0/b.dart: |
+ import "a.dart";
+ b() {
+ a();
+ }
+ package_0.1.1/b.dart: |
+ b() {
+ print("hello from v0.1.1");
+ }
+ .packages: dummy:${outDirUri}package_0.1.1
+ expectedLibraryCount: 2
\ No newline at end of file
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package_3.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package_3.yaml
new file mode 100644
index 0000000..2516191
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/updated_package_3.yaml
@@ -0,0 +1,45 @@
+# Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE.md file.
+
+# Compile an application with a package and use it.
+# Then update the package from .packages but change nothing else and call
+# computeDelta on the same compiler.
+# The output should not include the old package.
+
+type: newworld
+strong: false
+worlds:
+ - entry: main.dart
+ sources:
+ main.dart: |
+ import "package:dummy/b.dart";
+ main() {
+ print("hello");
+ b();
+ }
+ package_0.1.0/a.dart: |
+ a() {
+ la1();
+ }
+ la1() {
+ print("v0.1.0");
+ }
+ package_0.1.0/b.dart: |
+ import "a.dart";
+ b() {
+ a();
+ }
+ .packages: dummy:${outDirUri}package_0.1.0
+ expectedLibraryCount: 3
+ - entry: main.dart
+ worldType: updated
+ expectInitializeFromDill: false
+ checkInvalidatedFiles: false
+ sources:
+ package_0.1.1/b.dart: |
+ b() {
+ print("hello from v0.1.1");
+ }
+ .packages: dummy:${outDirUri}package_0.1.1
+ expectedLibraryCount: 2
\ No newline at end of file
diff --git a/pkg/front_end/testcases/magic_const.dart.direct.expect b/pkg/front_end/testcases/magic_const.dart.direct.expect
index 8595e97..31bfe5f 100644
--- a/pkg/front_end/testcases/magic_const.dart.direct.expect
+++ b/pkg/front_end/testcases/magic_const.dart.direct.expect
@@ -12,20 +12,14 @@
: super core::Object::•()
;
}
-static method foo({dynamic a = invalid-expression "pkg/front_end/testcases/magic_const.dart:15:9: Error: The keyword 'const' or 'new' is required here. Due to an implementation limit, the compiler isn't able to infer 'const' or 'new' here.
-foo({a: Constant(), b: Constant(), c: []}) {}
- ^", dynamic b = invalid-expression "pkg/front_end/testcases/magic_const.dart:15:24: Error: The keyword 'const' or 'new' is required here. Due to an implementation limit, the compiler isn't able to infer 'const' or 'new' here.
-foo({a: Constant(), b: Constant(), c: []}) {}
- ^", dynamic c = <dynamic>[]}) → dynamic {}
+static method foo({dynamic a = new self::Constant::•(), dynamic b = new self::Constant::•(), dynamic c = <dynamic>[]}) → dynamic {}
static method test() → dynamic {
invalid-expression "pkg/front_end/testcases/magic_const.dart:18:9: Error: Not a const constructor.
const NotConstant();
^";
- const self::Constant::•();
+ new self::Constant::•();
const dynamic x = const self::Constant::•();
- invalid-expression "pkg/front_end/testcases/magic_const.dart:21:8: Error: The keyword 'const' or 'new' is required here. Due to an implementation limit, the compiler isn't able to infer 'const' or 'new' here.
- bool.fromEnvironment(\"fisk\");
- ^";
+ core::bool::fromEnvironment("fisk");
const dynamic b = const core::bool::fromEnvironment("fisk");
}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/magic_const.dart.direct.transformed.expect b/pkg/front_end/testcases/magic_const.dart.direct.transformed.expect
index 8595e97..31bfe5f 100644
--- a/pkg/front_end/testcases/magic_const.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/magic_const.dart.direct.transformed.expect
@@ -12,20 +12,14 @@
: super core::Object::•()
;
}
-static method foo({dynamic a = invalid-expression "pkg/front_end/testcases/magic_const.dart:15:9: Error: The keyword 'const' or 'new' is required here. Due to an implementation limit, the compiler isn't able to infer 'const' or 'new' here.
-foo({a: Constant(), b: Constant(), c: []}) {}
- ^", dynamic b = invalid-expression "pkg/front_end/testcases/magic_const.dart:15:24: Error: The keyword 'const' or 'new' is required here. Due to an implementation limit, the compiler isn't able to infer 'const' or 'new' here.
-foo({a: Constant(), b: Constant(), c: []}) {}
- ^", dynamic c = <dynamic>[]}) → dynamic {}
+static method foo({dynamic a = new self::Constant::•(), dynamic b = new self::Constant::•(), dynamic c = <dynamic>[]}) → dynamic {}
static method test() → dynamic {
invalid-expression "pkg/front_end/testcases/magic_const.dart:18:9: Error: Not a const constructor.
const NotConstant();
^";
- const self::Constant::•();
+ new self::Constant::•();
const dynamic x = const self::Constant::•();
- invalid-expression "pkg/front_end/testcases/magic_const.dart:21:8: Error: The keyword 'const' or 'new' is required here. Due to an implementation limit, the compiler isn't able to infer 'const' or 'new' here.
- bool.fromEnvironment(\"fisk\");
- ^";
+ core::bool::fromEnvironment("fisk");
const dynamic b = const core::bool::fromEnvironment("fisk");
}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/magic_const.dart.strong.expect b/pkg/front_end/testcases/magic_const.dart.strong.expect
index f3197ea..d60f57e 100644
--- a/pkg/front_end/testcases/magic_const.dart.strong.expect
+++ b/pkg/front_end/testcases/magic_const.dart.strong.expect
@@ -12,20 +12,14 @@
: super core::Object::•()
;
}
-static method foo({dynamic a = invalid-expression "pkg/front_end/testcases/magic_const.dart:15:9: Error: The keyword 'const' or 'new' is required here. Due to an implementation limit, the compiler isn't able to infer 'const' or 'new' here.
-foo({a: Constant(), b: Constant(), c: []}) {}
- ^", dynamic b = invalid-expression "pkg/front_end/testcases/magic_const.dart:15:24: Error: The keyword 'const' or 'new' is required here. Due to an implementation limit, the compiler isn't able to infer 'const' or 'new' here.
-foo({a: Constant(), b: Constant(), c: []}) {}
- ^", dynamic c = <dynamic>[]}) → dynamic {}
+static method foo({dynamic a = new self::Constant::•(), dynamic b = new self::Constant::•(), dynamic c = <dynamic>[]}) → dynamic {}
static method test() → dynamic {
invalid-expression "pkg/front_end/testcases/magic_const.dart:18:9: Error: Not a const constructor.
const NotConstant();
^";
- const self::Constant::•();
+ new self::Constant::•();
const self::Constant x = const self::Constant::•();
- invalid-expression "pkg/front_end/testcases/magic_const.dart:21:8: Error: The keyword 'const' or 'new' is required here. Due to an implementation limit, the compiler isn't able to infer 'const' or 'new' here.
- bool.fromEnvironment(\"fisk\");
- ^";
+ core::bool::fromEnvironment("fisk");
const core::bool b = const core::bool::fromEnvironment("fisk");
}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/magic_const.dart.strong.transformed.expect b/pkg/front_end/testcases/magic_const.dart.strong.transformed.expect
index f3197ea..d60f57e 100644
--- a/pkg/front_end/testcases/magic_const.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/magic_const.dart.strong.transformed.expect
@@ -12,20 +12,14 @@
: super core::Object::•()
;
}
-static method foo({dynamic a = invalid-expression "pkg/front_end/testcases/magic_const.dart:15:9: Error: The keyword 'const' or 'new' is required here. Due to an implementation limit, the compiler isn't able to infer 'const' or 'new' here.
-foo({a: Constant(), b: Constant(), c: []}) {}
- ^", dynamic b = invalid-expression "pkg/front_end/testcases/magic_const.dart:15:24: Error: The keyword 'const' or 'new' is required here. Due to an implementation limit, the compiler isn't able to infer 'const' or 'new' here.
-foo({a: Constant(), b: Constant(), c: []}) {}
- ^", dynamic c = <dynamic>[]}) → dynamic {}
+static method foo({dynamic a = new self::Constant::•(), dynamic b = new self::Constant::•(), dynamic c = <dynamic>[]}) → dynamic {}
static method test() → dynamic {
invalid-expression "pkg/front_end/testcases/magic_const.dart:18:9: Error: Not a const constructor.
const NotConstant();
^";
- const self::Constant::•();
+ new self::Constant::•();
const self::Constant x = const self::Constant::•();
- invalid-expression "pkg/front_end/testcases/magic_const.dart:21:8: Error: The keyword 'const' or 'new' is required here. Due to an implementation limit, the compiler isn't able to infer 'const' or 'new' here.
- bool.fromEnvironment(\"fisk\");
- ^";
+ core::bool::fromEnvironment("fisk");
const core::bool b = const core::bool::fromEnvironment("fisk");
}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nested_implicit_const_with_env_var.dart b/pkg/front_end/testcases/nested_implicit_const_with_env_var.dart
index 255ffe6..e797b0e 100644
--- a/pkg/front_end/testcases/nested_implicit_const_with_env_var.dart
+++ b/pkg/front_end/testcases/nested_implicit_const_with_env_var.dart
@@ -2,8 +2,6 @@
// 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.
-/*@testedFeatures=error*/
-
const int foo = const int.fromEnvironment("fisk");
class A {
@@ -18,8 +16,7 @@
class C {
fun() {
- /*@error=CantDetermineConstness*/ B(
- /*@error=CantDetermineConstness*/ A(foo));
+ B(A(foo));
}
}
diff --git a/pkg/front_end/testcases/nested_implicit_const_with_env_var.dart.direct.expect b/pkg/front_end/testcases/nested_implicit_const_with_env_var.dart.direct.expect
index c486c02..6c29079 100644
--- a/pkg/front_end/testcases/nested_implicit_const_with_env_var.dart.direct.expect
+++ b/pkg/front_end/testcases/nested_implicit_const_with_env_var.dart.direct.expect
@@ -19,9 +19,7 @@
: super core::Object::•()
;
method fun() → dynamic {
- invalid-expression "pkg/front_end/testcases/nested_implicit_const_with_env_var.dart:21:39: Error: The keyword 'const' or 'new' is required here. Due to an implementation limit, the compiler isn't able to infer 'const' or 'new' here.
- /*@error=CantDetermineConstness*/ B(
- ^";
+ new self::B::•(new self::A::•(self::foo));
}
}
static const field core::int foo = const core::int::fromEnvironment("fisk");
diff --git a/pkg/front_end/testcases/nested_implicit_const_with_env_var.dart.direct.transformed.expect b/pkg/front_end/testcases/nested_implicit_const_with_env_var.dart.direct.transformed.expect
index c486c02..6c29079 100644
--- a/pkg/front_end/testcases/nested_implicit_const_with_env_var.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/nested_implicit_const_with_env_var.dart.direct.transformed.expect
@@ -19,9 +19,7 @@
: super core::Object::•()
;
method fun() → dynamic {
- invalid-expression "pkg/front_end/testcases/nested_implicit_const_with_env_var.dart:21:39: Error: The keyword 'const' or 'new' is required here. Due to an implementation limit, the compiler isn't able to infer 'const' or 'new' here.
- /*@error=CantDetermineConstness*/ B(
- ^";
+ new self::B::•(new self::A::•(self::foo));
}
}
static const field core::int foo = const core::int::fromEnvironment("fisk");
diff --git a/pkg/front_end/testcases/nested_implicit_const_with_env_var.dart.strong.expect b/pkg/front_end/testcases/nested_implicit_const_with_env_var.dart.strong.expect
index c486c02..6c29079 100644
--- a/pkg/front_end/testcases/nested_implicit_const_with_env_var.dart.strong.expect
+++ b/pkg/front_end/testcases/nested_implicit_const_with_env_var.dart.strong.expect
@@ -19,9 +19,7 @@
: super core::Object::•()
;
method fun() → dynamic {
- invalid-expression "pkg/front_end/testcases/nested_implicit_const_with_env_var.dart:21:39: Error: The keyword 'const' or 'new' is required here. Due to an implementation limit, the compiler isn't able to infer 'const' or 'new' here.
- /*@error=CantDetermineConstness*/ B(
- ^";
+ new self::B::•(new self::A::•(self::foo));
}
}
static const field core::int foo = const core::int::fromEnvironment("fisk");
diff --git a/pkg/front_end/testcases/nested_implicit_const_with_env_var.dart.strong.transformed.expect b/pkg/front_end/testcases/nested_implicit_const_with_env_var.dart.strong.transformed.expect
index c486c02..6c29079 100644
--- a/pkg/front_end/testcases/nested_implicit_const_with_env_var.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nested_implicit_const_with_env_var.dart.strong.transformed.expect
@@ -19,9 +19,7 @@
: super core::Object::•()
;
method fun() → dynamic {
- invalid-expression "pkg/front_end/testcases/nested_implicit_const_with_env_var.dart:21:39: Error: The keyword 'const' or 'new' is required here. Due to an implementation limit, the compiler isn't able to infer 'const' or 'new' here.
- /*@error=CantDetermineConstness*/ B(
- ^";
+ new self::B::•(new self::A::•(self::foo));
}
}
static const field core::int foo = const core::int::fromEnvironment("fisk");
diff --git a/pkg/front_end/testcases/new_const_insertion/simple.dart.direct.expect b/pkg/front_end/testcases/new_const_insertion/simple.dart.direct.expect
index de2c44c..6053292 100644
--- a/pkg/front_end/testcases/new_const_insertion/simple.dart.direct.expect
+++ b/pkg/front_end/testcases/new_const_insertion/simple.dart.direct.expect
@@ -10,8 +10,8 @@
}
static method main() → dynamic {
core::int foo = 42;
- const self::A::•(5);
- const self::A::•(5.+(5));
+ new self::A::•(5);
+ new self::A::•(5.+(5));
new self::A::•(foo);
new self::A::•(5.+(foo));
}
diff --git a/pkg/front_end/testcases/new_const_insertion/simple.dart.direct.transformed.expect b/pkg/front_end/testcases/new_const_insertion/simple.dart.direct.transformed.expect
index de2c44c..6053292 100644
--- a/pkg/front_end/testcases/new_const_insertion/simple.dart.direct.transformed.expect
+++ b/pkg/front_end/testcases/new_const_insertion/simple.dart.direct.transformed.expect
@@ -10,8 +10,8 @@
}
static method main() → dynamic {
core::int foo = 42;
- const self::A::•(5);
- const self::A::•(5.+(5));
+ new self::A::•(5);
+ new self::A::•(5.+(5));
new self::A::•(foo);
new self::A::•(5.+(foo));
}
diff --git a/pkg/front_end/testcases/new_const_insertion/simple.dart.strong.expect b/pkg/front_end/testcases/new_const_insertion/simple.dart.strong.expect
index 4ee5522..d7f734b 100644
--- a/pkg/front_end/testcases/new_const_insertion/simple.dart.strong.expect
+++ b/pkg/front_end/testcases/new_const_insertion/simple.dart.strong.expect
@@ -10,8 +10,8 @@
}
static method main() → dynamic {
core::int foo = 42;
- const self::A::•(5);
- const self::A::•(5.{core::num::+}(5));
+ new self::A::•(5);
+ new self::A::•(5.{core::num::+}(5));
new self::A::•(foo);
new self::A::•(5.{core::num::+}(foo));
}
diff --git a/pkg/front_end/testcases/new_const_insertion/simple.dart.strong.transformed.expect b/pkg/front_end/testcases/new_const_insertion/simple.dart.strong.transformed.expect
index 4ee5522..d7f734b 100644
--- a/pkg/front_end/testcases/new_const_insertion/simple.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/new_const_insertion/simple.dart.strong.transformed.expect
@@ -10,8 +10,8 @@
}
static method main() → dynamic {
core::int foo = 42;
- const self::A::•(5);
- const self::A::•(5.{core::num::+}(5));
+ new self::A::•(5);
+ new self::A::•(5.{core::num::+}(5));
new self::A::•(foo);
new self::A::•(5.{core::num::+}(foo));
}
diff --git a/pkg/kernel/lib/binary/tag.dart b/pkg/kernel/lib/binary/tag.dart
index b58cda9..e55935e 100644
--- a/pkg/kernel/lib/binary/tag.dart
+++ b/pkg/kernel/lib/binary/tag.dart
@@ -135,7 +135,7 @@
/// Internal version of kernel binary format.
/// Bump it when making incompatible changes in kernel binaries.
/// Keep in sync with runtime/vm/kernel_binary.h.
- static const int BinaryFormatVersion = 3;
+ static const int BinaryFormatVersion = 4;
}
abstract class ConstantTag {
diff --git a/pkg/kernel/lib/clone.dart b/pkg/kernel/lib/clone.dart
index 22dbf96..9c1db32 100644
--- a/pkg/kernel/lib/clone.dart
+++ b/pkg/kernel/lib/clone.dart
@@ -392,7 +392,7 @@
}
visitYieldStatement(YieldStatement node) {
- return new YieldStatement(clone(node.expression));
+ return new YieldStatement(clone(node.expression))..flags = node.flags;
}
visitVariableDeclaration(VariableDeclaration node) {
diff --git a/pkg/vm/bin/kernel_service.dart b/pkg/vm/bin/kernel_service.dart
index a839ff4..de93109 100644
--- a/pkg/vm/bin/kernel_service.dart
+++ b/pkg/vm/bin/kernel_service.dart
@@ -86,25 +86,32 @@
..packagesFileUri = packagesUri
..sdkSummary = platformKernelPath
..verbose = verbose
- ..onProblem =
- (message, Severity severity, String formatted, int line, int column) {
+ ..onProblem = (FormattedMessage message, Severity severity,
+ List<FormattedMessage> context) {
+ bool printMessage;
switch (severity) {
case Severity.error:
- case Severity.errorLegacyWarning:
case Severity.internalProblem:
// TODO(sigmund): support emitting code with errors as long as they
// are handled in the generated code (issue #30194).
- errors.add(formatted);
- stderr.writeln(formatted);
+ printMessage = true;
+ errors.add(message.formatted);
break;
case Severity.nit:
+ printMessage = false;
break;
case Severity.warning:
- if (!suppressWarnings) stderr.writeln(formatted);
+ printMessage = !suppressWarnings;
break;
+ case Severity.errorLegacyWarning:
case Severity.context:
- stderr.writeln(formatted);
- break;
+ throw "Unexpected severity: $severity";
+ }
+ if (printMessage) {
+ stderr.writeln(message.formatted);
+ for (FormattedMessage message in context) {
+ stderr.writeln(message.formatted);
+ }
}
};
}
diff --git a/pkg/vm/lib/frontend_server.dart b/pkg/vm/lib/frontend_server.dart
index ebb7792..d8644fa 100644
--- a/pkg/vm/lib/frontend_server.dart
+++ b/pkg/vm/lib/frontend_server.dart
@@ -209,20 +209,29 @@
..strongMode = options['strong']
..sdkSummary = sdkRoot.resolve(platformKernelDill)
..onProblem =
- (message, Severity severity, String formatted, int line, int column) {
+ (message, Severity severity, List<FormattedMessage> context) {
+ bool printMessage;
switch (severity) {
case Severity.error:
- case Severity.errorLegacyWarning:
case Severity.internalProblem:
- _outputStream.writeln(formatted);
- errors.add(formatted);
+ printMessage = true;
+ errors.add(message.formatted);
break;
case Severity.nit:
+ printMessage = false;
break;
case Severity.warning:
- case Severity.context:
- _outputStream.writeln(formatted);
+ printMessage = true;
break;
+ case Severity.errorLegacyWarning:
+ case Severity.context:
+ throw "Unexpected severity: $severity";
+ }
+ if (printMessage) {
+ _outputStream.writeln(message.formatted);
+ for (FormattedMessage message in context) {
+ _outputStream.writeln(message.formatted);
+ }
}
};
if (options.wasParsed('filesystem-root')) {
diff --git a/pkg/vm/lib/transformations/type_flow/summary.dart b/pkg/vm/lib/transformations/type_flow/summary.dart
index f4e9f38..7c23deb 100644
--- a/pkg/vm/lib/transformations/type_flow/summary.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary.dart
@@ -53,6 +53,7 @@
void visitParameter(Parameter expr) => visitDefault(expr);
void visitNarrow(Narrow expr) => visitDefault(expr);
void visitJoin(Join expr) => visitDefault(expr);
+ void visitUse(Use expr) => visitDefault(expr);
void visitCall(Call expr) => visitDefault(expr);
}
@@ -135,6 +136,24 @@
}
}
+/// Artificial use of [arg]. Removed during summary normalization.
+class Use extends Statement {
+ TypeExpr arg;
+
+ Use(this.arg);
+
+ @override
+ void accept(StatementVisitor visitor) => visitor.visitUse(this);
+
+ @override
+ String dump() => "$label = _Use ($arg)";
+
+ @override
+ Type apply(List<Type> computedTypes, TypeHierarchy typeHierarchy,
+ CallHandler callHandler) =>
+ throw 'Use statements should be removed during summary normalization';
+}
+
/// Call site.
class Call extends Statement {
final Selector selector;
diff --git a/pkg/vm/lib/transformations/type_flow/summary_collector.dart b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
index f9bdcb1..8d48f99 100644
--- a/pkg/vm/lib/transformations/type_flow/summary_collector.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
@@ -61,6 +61,8 @@
for (Statement st in statements) {
if (st is Call) {
_normalizeExpr(st, false);
+ } else if (st is Use) {
+ _normalizeExpr(st.arg, true);
}
}
@@ -69,6 +71,7 @@
TypeExpr _normalizeExpr(TypeExpr st, bool isResultUsed) {
assertx(!_inLoop);
+ assertx(st is! Use);
if (st is Statement) {
if (isResultUsed && (st is Call)) {
st.setResultUsed();
@@ -137,6 +140,11 @@
}
@override
+ void visitUse(Use expr) {
+ throw '\'Use\' statement should not be referenced: $expr';
+ }
+
+ @override
void visitCall(Call expr) {
for (int i = 0; i < expr.args.values.length; i++) {
expr.args.values[i] = _normalizeExpr(expr.args.values[i], true);
@@ -485,6 +493,18 @@
return narrow;
}
+ // Add an artificial use of given expression in order to make it possible to
+ // infer its type even if it is not used in a summary.
+ void _addUse(TypeExpr arg) {
+ if (arg is Narrow) {
+ _addUse(arg.arg);
+ } else if (arg is Join || arg is Call) {
+ _summary.add(new Use(arg));
+ } else {
+ assertx(arg is Type || arg is Parameter);
+ }
+ }
+
Type _staticType(Expression node) =>
new Type.fromStatic(node.getStaticType(_environment));
@@ -553,7 +573,7 @@
@override
TypeExpr visitConditionalExpression(ConditionalExpression node) {
- _visit(node.condition);
+ _addUse(_visit(node.condition));
Join v = new Join(null, node.getStaticType(_environment));
_summary.add(v);
@@ -652,8 +672,8 @@
@override
TypeExpr visitLogicalExpression(LogicalExpression node) {
- _visit(node.left);
- _visit(node.right);
+ _addUse(_visit(node.left));
+ _addUse(_visit(node.right));
return _boolType;
}
@@ -812,7 +832,7 @@
@override
TypeExpr visitNot(Not node) {
- _visit(node.operand);
+ _addUse(_visit(node.operand));
return _boolType;
}
@@ -960,7 +980,7 @@
@override
TypeExpr visitAssertStatement(AssertStatement node) {
if (!kRemoveAsserts) {
- _visit(node.condition);
+ _addUse(_visit(node.condition));
if (node.message != null) {
_visit(node.message);
}
@@ -1017,7 +1037,7 @@
TypeExpr visitForStatement(ForStatement node) {
node.variables.forEach(visitVariableDeclaration);
if (node.condition != null) {
- _visit(node.condition);
+ _addUse(_visit(node.condition));
}
node.updates.forEach(_visit);
_visit(node.body);
@@ -1036,7 +1056,7 @@
@override
TypeExpr visitIfStatement(IfStatement node) {
- _visit(node.condition);
+ _addUse(_visit(node.condition));
_visit(node.then);
if (node.otherwise != null) {
_visit(node.otherwise);
@@ -1099,7 +1119,7 @@
@override
visitWhileStatement(WhileStatement node) {
- _visit(node.condition);
+ _addUse(_visit(node.condition));
_visit(node.body);
}
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart b/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart
new file mode 100644
index 0000000..a22bad2
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+dynamic foo() => null;
+bool bar() => null;
+
+void bool_expressions() {
+ if (foo()) {}
+ while (bar()) {}
+ for (int i = 0; i < 10; i++) {}
+ bool x = bar();
+ bool y = true;
+ if (x is bool) {
+ y = x ? true : foo();
+ y = bar() || bar();
+ }
+ x = foo() && foo();
+ y = !y;
+ assert(y);
+}
+
+main() {}
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart.expect
new file mode 100644
index 0000000..b36ef8c
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/bool_expressions.dart.expect
@@ -0,0 +1,27 @@
+------------ #lib::foo ------------
+
+RESULT: _T {}?
+------------ #lib::bar ------------
+
+RESULT: _T {}?
+------------ #lib::bool_expressions ------------
+t0* = _Call direct [#lib::foo] ()
+t1* = _Call direct [#lib::bar] ()
+t2* = _Call [dart.core::num::+] (_T (dart.core::int)+?, _T (dart.core::int)+)
+i = _Join [dart.core::int] (_T (dart.core::int)+, t2)
+t4* = _Call [dart.core::num::<] (i, _T (dart.core::int)+)
+t5* = _Call direct [#lib::bar] ()
+x = _Join [dart.core::bool] (t5, _T (dart.core::bool)+)
+t7* = _Call direct [#lib::foo] ()
+t8* = _Call direct [#lib::bar] ()
+t9* = _Call direct [#lib::bar] ()
+t10* = _Call direct [#lib::foo] ()
+t11* = _Call direct [#lib::foo] ()
+t12 = _Join [dynamic] (_T (dart.core::bool)+, t7)
+t13 = _Narrow (t12 to _T ANY?)
+t14 = _Narrow (t13 to _T (dart.core::bool)+?)
+y = _Join [dart.core::bool] (_T (dart.core::bool)+, t14, _T (dart.core::bool)+, _T (dart.core::bool)+)
+RESULT: _T {}?
+------------ #lib::main ------------
+
+RESULT: _T {}?
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart.expect
index 44d8318..2cad426 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/vars.dart.expect
@@ -9,12 +9,12 @@
------------ #lib::foo ------------
%a1 = _Parameter #0 [_T (dart.core::Object)+?]
%a2 = _Parameter #1 [_T (dart.core::Object)+?]
-t2 = _Call direct get [#lib::someStatic] ()
+t2* = _Call direct get [#lib::someStatic] ()
t3 = _Call direct [#lib::A::] (_T (#lib::A))
a1 = _Join [dart.core::Object] (%a1, _T (#lib::A), _T (#lib::B))
t5 = _Call direct [#lib::bar] (a1, _T (dart.core::int)+)
t6 = _Call direct [#lib::B::] (_T (#lib::B))
-t7 = _Call [dart.core::Object::==] (a1, %a2)
+t7* = _Call [dart.core::Object::==] (a1, %a2)
t8 = _Join [dart.core::Object] (a1, %a2)
t9 = _Narrow (t8 to _T (dart.core::Object)+?)
RESULT: t9
@@ -37,7 +37,7 @@
%x = _Parameter #0 [_T (dart.core::int)+?]
t1* = _Call [dart.core::num::+] (_T (dart.core::int)+?, _T (dart.core::int)+)
i = _Join [dart.core::int] (_T (dart.core::int)+, t1)
-t3 = _Call [dart.core::num::<] (i, _T (dart.core::int)+)
+t3* = _Call [dart.core::num::<] (i, _T (dart.core::int)+)
t4* = _Call [dart.core::num::+] (_T (dart.core::int)+?, _T (dart.core::int)+)
x = _Join [dart.core::int] (%x, t4)
RESULT: x
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect
index 2513602..e7c4fe3 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect
@@ -17,7 +17,7 @@
}
operator *([@vm.inferred-type.metadata=#lib::_Vector?] self::_Vector a) → core::double {
core::double result = 0.0;
- for (core::int i = 0; i.{core::num::<}([@vm.direct-call.metadata=#lib::_Vector::_length] [@vm.inferred-type.metadata=!] this.{self::_Vector::_length}); i = i.{core::num::+}(1))
+ for (core::int i = 0; [@vm.inferred-type.metadata=dart.core::bool?] i.{core::num::<}([@vm.direct-call.metadata=#lib::_Vector::_length] [@vm.inferred-type.metadata=!] this.{self::_Vector::_length}); i = i.{core::num::+}(1))
result = [@vm.direct-call.metadata=dart.core::_Double::+??] [@vm.inferred-type.metadata=dart.core::_Double] result.{core::double::+}([@vm.direct-call.metadata=dart.core::_Double::*] [@vm.inferred-type.metadata=dart.core::_Double] [@vm.direct-call.metadata=#lib::_Vector::[]] [@vm.inferred-type.metadata=dart.core::_Double] this.{self::_Vector::[]}(i).{core::double::*}([@vm.direct-call.metadata=#lib::_Vector::[]??] [@vm.inferred-type.metadata=dart.core::_Double] a.{self::_Vector::[]}(i)));
return result;
}
@@ -26,7 +26,7 @@
[@vm.inferred-type.metadata=dart.core::_Double?]static field core::double x = 0.0;
static method main(core::List<core::String> args) → dynamic {
core::Stopwatch timer = let final core::Stopwatch #t4 = new core::Stopwatch::•() in let final dynamic #t5 = [@vm.direct-call.metadata=dart.core::Stopwatch::start] #t4.{core::Stopwatch::start}() in #t4;
- for (core::int i = 0; i.{core::num::<}(100000000); i = i.{core::num::+}(1)) {
+ for (core::int i = 0; [@vm.inferred-type.metadata=dart.core::bool?] i.{core::num::<}(100000000); i = i.{core::num::+}(1)) {
self::x = [@vm.direct-call.metadata=dart.core::_Double::+??] [@vm.inferred-type.metadata=dart.core::_Double] [@vm.inferred-type.metadata=dart.core::_Double?] self::x.{core::double::+}([@vm.direct-call.metadata=#lib::_Vector::*??] [@vm.inferred-type.metadata=dart.core::_Double] [@vm.inferred-type.metadata=#lib::_Vector?] self::v.{self::_Vector::*}([@vm.inferred-type.metadata=#lib::_Vector?] self::v));
}
[@vm.direct-call.metadata=dart.core::Stopwatch::stop] timer.{core::Stopwatch::stop}();
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index b4d3d75..05ac9d1 100644
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -1059,17 +1059,6 @@
DART_EXPORT bool Dart_IsDart2Snapshot(const uint8_t* snapshot_buffer);
/**
- * Schedules an interrupt for the specified isolate.
- *
- * When the isolate is interrupted, the isolate interrupt callback
- * will be invoked with 'isolate' as the current isolate (see
- * Dart_SetIsolateEventHandler).
- *
- * \param isolate The isolate to be interrupted.
- */
-DART_EXPORT void Dart_InterruptIsolate(Dart_Isolate isolate);
-
-/**
* Make isolate runnable.
*
* When isolates are spawned this function is used to indicate that
@@ -1242,15 +1231,6 @@
DART_EXPORT Dart_Handle Dart_HandleMessage();
/**
- * Handles all pending messages for the current isolate.
- *
- * May generate an unhandled exception error.
- *
- * \return A valid handle if no error occurs during the operation.
- */
-DART_EXPORT Dart_Handle Dart_HandleMessages();
-
-/**
* Drains the microtask queue, then blocks the calling thread until the current
* isolate recieves a message, then handles all messages.
*
diff --git a/runtime/lib/compact_hash.dart b/runtime/lib/compact_hash.dart
index 82bc532..6f55f41 100644
--- a/runtime/lib/compact_hash.dart
+++ b/runtime/lib/compact_hash.dart
@@ -78,19 +78,14 @@
static const int _UNUSED_PAIR = 0;
static const int _DELETED_PAIR = 1;
- // On 32-bit, the top bits are wasted to avoid Mint allocation.
- // TODO(koda): Reclaim the bits by making the compiler treat hash patterns
- // as unsigned words.
+ // The top bits are wasted to avoid Mint allocation.
static int _indexSizeToHashMask(int indexSize) {
int indexBits = indexSize.bitLength - 2;
- return internal.is64Bit
- ? (1 << (32 - indexBits)) - 1
- : (1 << (30 - indexBits)) - 1;
+ return (1 << (30 - indexBits)) - 1;
}
static int _hashPattern(int fullHash, int hashMask, int size) {
final int maskedHash = fullHash & hashMask;
- // TODO(koda): Consider keeping bit length and use left shift.
return (maskedHash == 0) ? (size >> 1) : maskedHash * (size >> 1);
}
diff --git a/runtime/lib/integers_patch.dart b/runtime/lib/integers_patch.dart
index c7116c7..ef98727 100644
--- a/runtime/lib/integers_patch.dart
+++ b/runtime/lib/integers_patch.dart
@@ -32,7 +32,7 @@
return null; // Empty.
}
}
- var smiLimit = is64Bit ? 18 : 9;
+ var smiLimit = 9;
if ((last - ix) >= smiLimit) {
return null; // May not fit into a Smi.
}
@@ -117,7 +117,7 @@
static int _parseRadix(
String source, int radix, int start, int end, int sign) {
- int tableIndex = (radix - 2) * 4 + (is64Bit ? 2 : 0);
+ int tableIndex = (radix - 2) * 2;
int blockSize = _PARSE_LIMITS[tableIndex];
int length = end - start;
if (length <= blockSize) {
@@ -143,7 +143,7 @@
int positiveOverflowLimit = 0;
int negativeOverflowLimit = 0;
if (_limitIntsTo64Bits) {
- tableIndex = tableIndex << 1; // pre-multiply by 2 for simpler indexing
+ tableIndex = tableIndex << 1; // Pre-multiply by 2 for simpler indexing.
positiveOverflowLimit = _int64OverflowLimits[tableIndex];
if (positiveOverflowLimit == 0) {
positiveOverflowLimit =
@@ -159,14 +159,10 @@
if (result >= positiveOverflowLimit) {
if ((result > positiveOverflowLimit) ||
(smi > _int64OverflowLimits[tableIndex + 2])) {
- // Although the unsigned overflow limits do not depend on the
- // platform, the multiplier and block size, which are used to
- // compute it, do.
- int X = is64Bit ? 1 : 0;
if (radix == 16 &&
- !(result >= _int64UnsignedOverflowLimits[X] &&
- (result > _int64UnsignedOverflowLimits[X] ||
- smi > _int64UnsignedSmiOverflowLimits[X])) &&
+ !(result >= _int64UnsignedOverflowLimit &&
+ (result > _int64UnsignedOverflowLimit ||
+ smi > _int64UnsignedSmiOverflowLimit)) &&
blockEnd + blockSize > end) {
return (result * multiplier) + smi;
}
@@ -211,43 +207,42 @@
// For each radix, 2-36, how many digits are guaranteed to fit in a smi,
// and magnitude of such a block (radix ** digit-count).
- // 32-bit limit/multiplier at (radix - 2)*4, 64-bit limit at (radix-2)*4+2
static const _PARSE_LIMITS = const [
- 30, 1073741824, 62, 4611686018427387904, // radix: 2
- 18, 387420489, 39, 4052555153018976267,
- 15, 1073741824, 30, 1152921504606846976,
- 12, 244140625, 26, 1490116119384765625, // radix: 5
- 11, 362797056, 23, 789730223053602816,
- 10, 282475249, 22, 3909821048582988049,
- 10, 1073741824, 20, 1152921504606846976,
- 9, 387420489, 19, 1350851717672992089,
- 9, 1000000000, 18, 1000000000000000000, // radix: 10
- 8, 214358881, 17, 505447028499293771,
- 8, 429981696, 17, 2218611106740436992,
- 8, 815730721, 16, 665416609183179841,
- 7, 105413504, 16, 2177953337809371136,
- 7, 170859375, 15, 437893890380859375, // radix: 15
- 7, 268435456, 15, 1152921504606846976,
- 7, 410338673, 15, 2862423051509815793,
- 7, 612220032, 14, 374813367582081024,
- 7, 893871739, 14, 799006685782884121,
- 6, 64000000, 14, 1638400000000000000, // radix: 20
- 6, 85766121, 14, 3243919932521508681,
- 6, 113379904, 13, 282810057883082752,
- 6, 148035889, 13, 504036361936467383,
- 6, 191102976, 13, 876488338465357824,
- 6, 244140625, 13, 1490116119384765625, // radix: 25
- 6, 308915776, 13, 2481152873203736576,
- 6, 387420489, 13, 4052555153018976267,
- 6, 481890304, 12, 232218265089212416,
- 6, 594823321, 12, 353814783205469041,
- 6, 729000000, 12, 531441000000000000, // radix: 30
- 6, 887503681, 12, 787662783788549761,
- 6, 1073741824, 12, 1152921504606846976,
- 5, 39135393, 12, 1667889514952984961,
- 5, 45435424, 12, 2386420683693101056,
- 5, 52521875, 12, 3379220508056640625, // radix: 35
- 5, 60466176, 11, 131621703842267136,
+ 30, 1073741824, // radix: 2
+ 18, 387420489,
+ 15, 1073741824,
+ 12, 244140625, // radix: 5
+ 11, 362797056,
+ 10, 282475249,
+ 10, 1073741824,
+ 9, 387420489,
+ 9, 1000000000, // radix: 10
+ 8, 214358881,
+ 8, 429981696,
+ 8, 815730721,
+ 7, 105413504,
+ 7, 170859375, // radix: 15
+ 7, 268435456,
+ 7, 410338673,
+ 7, 612220032,
+ 7, 893871739,
+ 6, 64000000, // radix: 20
+ 6, 85766121,
+ 6, 113379904,
+ 6, 148035889,
+ 6, 191102976,
+ 6, 244140625, // radix: 25
+ 6, 308915776,
+ 6, 387420489,
+ 6, 481890304,
+ 6, 594823321,
+ 6, 729000000, // radix: 30
+ 6, 887503681,
+ 6, 1073741824,
+ 5, 39135393,
+ 5, 45435424,
+ 5, 52521875, // radix: 35
+ 5, 60466176,
];
/// Flag indicating if integers are limited by 64 bits
@@ -257,11 +252,8 @@
static const _maxInt64 = 0x7fffffffffffffff;
static const _minInt64 = -_maxInt64 - 1;
- static const _int64UnsignedOverflowLimits = const [0xfffffffff, 0xf];
- static const _int64UnsignedSmiOverflowLimits = const [
- 0xfffffff,
- 0xfffffffffffffff
- ];
+ static const _int64UnsignedOverflowLimit = 0xfffffffff;
+ static const _int64UnsignedSmiOverflowLimit = 0xfffffff;
/// In the `--limit-ints-to-64-bits` mode calculation of the expression
///
diff --git a/runtime/observatory/tests/service/bad_reload/v1/main.dart b/runtime/observatory/tests/service/bad_reload/v1/main.dart
index f9abf8b..5b930e8 100644
--- a/runtime/observatory/tests/service/bad_reload/v1/main.dart
+++ b/runtime/observatory/tests/service/bad_reload/v1/main.dart
@@ -9,5 +9,5 @@
main() {
RawReceivePort keepAlive = new RawReceivePort();
- print('slave isolate running');
+ print('spawned isolate running');
}
diff --git a/runtime/observatory/tests/service/bad_reload/v2/main.dart b/runtime/observatory/tests/service/bad_reload/v2/main.dart
index 2617291..5a9b293b 100644
--- a/runtime/observatory/tests/service/bad_reload/v2/main.dart
+++ b/runtime/observatory/tests/service/bad_reload/v2/main.dart
@@ -10,5 +10,5 @@
main() {
RawReceivePort keepAlive = new RawReceivePort();
- print('slave isolate running');
+ print('spawned isolate running');
}
diff --git a/runtime/observatory/tests/service/bad_reload_test.dart b/runtime/observatory/tests/service/bad_reload_test.dart
index b099a56..8e9aed7 100644
--- a/runtime/observatory/tests/service/bad_reload_test.dart
+++ b/runtime/observatory/tests/service/bad_reload_test.dart
@@ -51,17 +51,17 @@
await vm.reloadIsolates();
expect(vm.isolates.length, 2);
- // Find the slave isolate.
- Isolate slaveIsolate =
+ // Find the spawned isolate.
+ Isolate spawnedIsolate =
vm.isolates.firstWhere((Isolate i) => i != mainIsolate);
- expect(slaveIsolate, isNotNull);
+ expect(spawnedIsolate, isNotNull);
// Invoke test in v1.
- String v1 = await invokeTest(slaveIsolate);
+ String v1 = await invokeTest(spawnedIsolate);
expect(v1, 'apple');
// Reload to v2.
- var response = await slaveIsolate.reloadSources(
+ var response = await spawnedIsolate.reloadSources(
rootLibUri: v2Uri.toString(),
);
// Observe that it failed.
@@ -73,7 +73,7 @@
expect(reasonForCancelling['message'], contains('library_isnt_here_man'));
// Invoke test in v2.
- String v2 = await invokeTest(slaveIsolate);
+ String v2 = await invokeTest(spawnedIsolate);
expect(v2, 'apple');
}
];
diff --git a/runtime/observatory/tests/service/complex_reload/v1/main.dart b/runtime/observatory/tests/service/complex_reload/v1/main.dart
index ce7e29f..1e0596f 100644
--- a/runtime/observatory/tests/service/complex_reload/v1/main.dart
+++ b/runtime/observatory/tests/service/complex_reload/v1/main.dart
@@ -9,5 +9,5 @@
main() {
RawReceivePort keepAlive = new RawReceivePort();
- print('slave isolate running');
+ print('spawned isolate running');
}
diff --git a/runtime/observatory/tests/service/complex_reload_test.dart b/runtime/observatory/tests/service/complex_reload_test.dart
index 45d6f72..e1c6e36 100644
--- a/runtime/observatory/tests/service/complex_reload_test.dart
+++ b/runtime/observatory/tests/service/complex_reload_test.dart
@@ -53,17 +53,17 @@
await vm.reloadIsolates();
expect(vm.isolates.length, 2);
- // Find the slave isolate.
- Isolate slaveIsolate =
+ // Find the spawned isolate.
+ Isolate spawnedIsolate =
vm.isolates.firstWhere((Isolate i) => i != mainIsolate);
- expect(slaveIsolate, isNotNull);
+ expect(spawnedIsolate, isNotNull);
// Invoke test in v1.
- String v1 = await invokeTest(slaveIsolate);
+ String v1 = await invokeTest(spawnedIsolate);
expect(v1, 'apple');
// Reload to v2.
- var response = await slaveIsolate.reloadSources(
+ var response = await spawnedIsolate.reloadSources(
rootLibUri: v2Uri.toString(),
packagesUri: v2PackagesUri.toString(),
);
@@ -71,17 +71,17 @@
expect(response['success'], isTrue);
// Invoke test in v2.
- String v2 = await invokeTest(slaveIsolate);
+ String v2 = await invokeTest(spawnedIsolate);
expect(v2, 'fooLib');
// Reload to v3.
- response = await slaveIsolate.reloadSources(
+ response = await spawnedIsolate.reloadSources(
rootLibUri: v3Uri.toString(),
);
expect(response['success'], isTrue);
// Invoke test in v3.
- String v3 = await invokeTest(slaveIsolate);
+ String v3 = await invokeTest(spawnedIsolate);
expect(v3, 'cabbage');
}
];
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 423d363..f83553e 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -22,20 +22,6 @@
[ $builder_tag == asan ]
cc/CodeImmutability: Fail, OK # Address Sanitizer turns a crash into a failure.
-cc/IsolateReload_DanglingGetter_Class: Fail # Issue 28349
-cc/IsolateReload_DanglingGetter_Instance: Fail # Issue 28349
-cc/IsolateReload_LiveStack: Fail # Issue 28349
-cc/IsolateReload_PendingSuperCall: Fail # Issue 28349
-cc/IsolateReload_SmiFastPathStubs: Fail # Issue 28349
-cc/IsolateReload_TearOff_AddArguments: Fail # Issue 28349
-cc/IsolateReload_TearOff_AddArguments2: Fail # Issue 28349
-cc/IsolateReload_TearOff_Class_Identity: Fail # Issue 28349
-cc/IsolateReload_TearOff_Instance_Equality: Fail # Issue 28349
-cc/IsolateReload_TearOff_Library_Identity: Fail # Issue 28349
-cc/IsolateReload_TearOff_List_Set: Fail # Issue 28349
-cc/IsolateReload_TypeIdentity: Fail # Issue 28349
-cc/IsolateReload_TypeIdentityGeneric: Fail # Issue 28349
-cc/IsolateReload_TypeIdentityParameter: Fail # Issue 28349
[ $compiler == app_jit ]
dart/snapshot_version_test: Fail, OK # Expects to find script snapshot relative to Dart source.
@@ -60,7 +46,6 @@
[ $compiler == dartk ]
cc/DartAPI_New: Fail
cc/DartAPI_TypeGetParameterizedTypes: Crash
-cc/IsolateReload_TearOff_Parameter_Count_Mismatch: Pass, Fail # Issue 32781
dart/redirection_type_shuffling_test/00: RuntimeError
dart/redirection_type_shuffling_test/none: RuntimeError
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.h b/runtime/vm/compiler/assembler/assembler_arm64.h
index cfe69b9..2356a6e 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.h
+++ b/runtime/vm/compiler/assembler/assembler_arm64.h
@@ -1062,12 +1062,18 @@
const Register crn = ConcreteRegister(rn);
EmitFPIntCvtOp(SCVTFD, static_cast<Register>(vd), crn, kWord);
}
- void fcvtzds(Register rd, VRegister vn) {
+ void fcvtzdsx(Register rd, VRegister vn) {
ASSERT(rd != R31);
ASSERT(rd != CSP);
const Register crd = ConcreteRegister(rd);
EmitFPIntCvtOp(FCVTZDS, crd, static_cast<Register>(vn));
}
+ void fcvtzdsw(Register rd, VRegister vn) {
+ ASSERT(rd != R31);
+ ASSERT(rd != CSP);
+ const Register crd = ConcreteRegister(rd);
+ EmitFPIntCvtOp(FCVTZDS, crd, static_cast<Register>(vn), kWord);
+ }
void fmovdd(VRegister vd, VRegister vn) { EmitFPOneSourceOp(FMOVDD, vd, vn); }
void fabsd(VRegister vd, VRegister vn) { EmitFPOneSourceOp(FABSD, vd, vn); }
void fnegd(VRegister vd, VRegister vn) { EmitFPOneSourceOp(FNEGD, vd, vn); }
@@ -1358,9 +1364,17 @@
LslImmediate(dst, src, kSmiTagSize);
}
- void BranchIfNotSmi(Register reg, Label* label) { tbnz(label, reg, kSmiTag); }
+ void BranchIfNotSmi(Register reg, Label* label) {
+ ASSERT(kSmiTagMask == 1);
+ ASSERT(kSmiTag == 0);
+ tbnz(label, reg, 0);
+ }
- void BranchIfSmi(Register reg, Label* label) { tbz(label, reg, kSmiTag); }
+ void BranchIfSmi(Register reg, Label* label) {
+ ASSERT(kSmiTagMask == 1);
+ ASSERT(kSmiTag == 0);
+ tbz(label, reg, 0);
+ }
void Branch(const StubEntry& stub_entry,
Register pp,
@@ -1444,6 +1458,11 @@
kValueCanBeSmi,
};
+ enum CanBeHeapPointer {
+ kValueIsNotHeapPointer,
+ kValueCanBeHeapPointer,
+ };
+
// Storing into an object.
void StoreIntoObject(Register object,
const Address& dest,
@@ -1583,6 +1602,22 @@
Register tmp,
OperandSize sz);
+ void AssertSmiInRange(
+ Register object,
+ CanBeHeapPointer can_be_heap_pointer = kValueIsNotHeapPointer) {
+#if defined(DEBUG)
+ Label ok;
+ if (can_be_heap_pointer == kValueCanBeHeapPointer) {
+ BranchIfNotSmi(object, &ok);
+ }
+ cmp(object, Operand(object, SXTW, 0));
+ b(&ok, EQ);
+ Stop("Smi out of range");
+
+ Bind(&ok);
+#endif
+ }
+
private:
AssemblerBuffer buffer_; // Contains position independent code.
ObjectPoolWrapper object_pool_wrapper_;
diff --git a/runtime/vm/compiler/assembler/assembler_arm64_test.cc b/runtime/vm/compiler/assembler/assembler_arm64_test.cc
index a41fad24..523688b 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64_test.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64_test.cc
@@ -2576,17 +2576,73 @@
EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(DoubleReturn, test->entry()));
}
-ASSEMBLER_TEST_GENERATE(Fcvtzds, assembler) {
+ASSEMBLER_TEST_GENERATE(Fcvtzdsx, assembler) {
__ LoadDImmediate(V0, 42.0);
- __ fcvtzds(R0, V0);
+ __ fcvtzdsx(R0, V0);
__ ret();
}
-ASSEMBLER_TEST_RUN(Fcvtzds, test) {
+ASSEMBLER_TEST_RUN(Fcvtzdsx, test) {
typedef int64_t (*Int64Return)() DART_UNUSED;
EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
}
+ASSEMBLER_TEST_GENERATE(Fcvtzdsw, assembler) {
+ __ LoadDImmediate(V0, 42.0);
+ __ fcvtzdsw(R0, V0);
+ __ ret();
+}
+
+ASSEMBLER_TEST_RUN(Fcvtzdsw, test) {
+ typedef int64_t (*Int64Return)() DART_UNUSED;
+ EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
+}
+
+ASSEMBLER_TEST_GENERATE(Fcvtzdsx_overflow, assembler) {
+ __ LoadDImmediate(V0, 1e20);
+ __ fcvtzdsx(R0, V0);
+ __ ret();
+}
+
+ASSEMBLER_TEST_RUN(Fcvtzdsx_overflow, test) {
+ typedef int64_t (*Int64Return)() DART_UNUSED;
+ EXPECT_EQ(kMaxInt64, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
+}
+
+ASSEMBLER_TEST_GENERATE(Fcvtzdsx_overflow_negative, assembler) {
+ __ LoadDImmediate(V0, -1e20);
+ __ fcvtzdsx(R0, V0);
+ __ ret();
+}
+
+ASSEMBLER_TEST_RUN(Fcvtzdsx_overflow_negative, test) {
+ typedef int64_t (*Int64Return)() DART_UNUSED;
+ EXPECT_EQ(kMinInt64, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
+}
+
+ASSEMBLER_TEST_GENERATE(Fcvtzdsw_overflow, assembler) {
+ __ LoadDImmediate(V0, 1e10);
+ __ fcvtzdsw(R0, V0);
+ __ ret();
+}
+
+ASSEMBLER_TEST_RUN(Fcvtzdsw_overflow, test) {
+ typedef int64_t (*Int64Return)() DART_UNUSED;
+ EXPECT_EQ(kMaxInt32, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
+}
+
+ASSEMBLER_TEST_GENERATE(Fcvtzdsw_overflow_negative, assembler) {
+ __ LoadDImmediate(V0, -1e10);
+ __ fcvtzdsw(R0, V0);
+ __ sxtw(R0, R0);
+ __ ret();
+}
+
+ASSEMBLER_TEST_RUN(Fcvtzdsw_overflow_negative, test) {
+ typedef int64_t (*Int64Return)() DART_UNUSED;
+ EXPECT_EQ(kMinInt32, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
+}
+
ASSEMBLER_TEST_GENERATE(Scvtfdx, assembler) {
__ LoadImmediate(R0, 42);
__ scvtfdx(V0, R0);
diff --git a/runtime/vm/compiler/assembler/assembler_x64.h b/runtime/vm/compiler/assembler/assembler_x64.h
index 83a80ff..eb5b532 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.h
+++ b/runtime/vm/compiler/assembler/assembler_x64.h
@@ -521,7 +521,10 @@
return CompareImmediate(reg, Immediate(immediate));
}
- void testl(Register reg, const Immediate& imm) { testq(reg, imm); }
+ void testl(Register reg, const Immediate& imm) {
+ Immediate imm2(imm.value() & 0xffffffffll);
+ testq(reg, imm2);
+ }
void testb(const Address& address, const Immediate& imm);
void testq(Register reg, const Immediate& imm);
@@ -709,6 +712,11 @@
kValueCanBeSmi,
};
+ enum CanBeHeapPointer {
+ kValueIsNotHeapPointer,
+ kValueCanBeHeapPointer,
+ };
+
// Destroys value.
void StoreIntoObject(Register object, // Object we are storing into.
const Address& dest, // Where we are storing into.
@@ -932,6 +940,26 @@
Register array,
Register index);
+ void AssertSmiInRange(
+ Register object,
+ CanBeHeapPointer can_be_heap_pointer = kValueIsNotHeapPointer) {
+#if defined(DEBUG)
+ Register tmp = object == TMP ? TMP2 : TMP;
+ Label ok;
+ if (can_be_heap_pointer == kValueCanBeHeapPointer) {
+ testl(object, Immediate(kSmiTagMask));
+ ASSERT(kSmiTag == 0);
+ j(ZERO, &ok);
+ }
+ movsxd(tmp, object);
+ cmpq(tmp, object);
+ j(EQUAL, &ok);
+ Stop("Smi out of range");
+
+ Bind(&ok);
+#endif
+ }
+
static Address VMTagAddress() {
return Address(THR, Thread::vm_tag_offset());
}
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
index 25fb8a7..d710b8c 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
@@ -657,12 +657,12 @@
&runtime_call);
__ Bind(&runtime_call);
- __ PushObject(Object::null_object()); // Make room for the result.
- __ pushq(RAX); // Push the source object.
- __ PushObject(dst_type); // Push the type of the destination.
- __ pushq(RDX); // Instantiator type arguments.
- __ pushq(RCX); // Function type arguments.
- __ PushObject(dst_name); // Push the name of the destination.
+ __ PushObject(Object::null_object()); // Make room for the result.
+ __ pushq(RAX); // Push the source object.
+ __ PushObject(dst_type); // Push the type of the destination.
+ __ pushq(RDX); // Instantiator type arguments.
+ __ pushq(RCX); // Function type arguments.
+ __ PushObject(dst_name); // Push the name of the destination.
__ LoadUniqueObject(RAX, test_cache);
__ pushq(RAX);
GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 6, locs);
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index c4425ed..00e1ecf 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -1552,10 +1552,10 @@
return Utils::IsPowerOfTwo(Utils::Abs(int_value));
}
-static intptr_t RepresentationBits(Representation r) {
+static intptr_t SignificantRepresentationBits(Representation r) {
switch (r) {
case kTagged:
- return kBitsPerWord - 1;
+ return 31;
case kUnboxedInt32:
case kUnboxedUint32:
return 32;
@@ -1569,7 +1569,7 @@
static int64_t RepresentationMask(Representation r) {
return static_cast<int64_t>(static_cast<uint64_t>(-1) >>
- (64 - RepresentationBits(r)));
+ (64 - SignificantRepresentationBits(r)));
}
static bool ToIntegerConstant(Value* value, int64_t* result) {
@@ -2130,7 +2130,8 @@
break;
case Token::kSHL: {
- const intptr_t kMaxShift = RepresentationBits(representation()) - 1;
+ const intptr_t kMaxShift =
+ SignificantRepresentationBits(representation()) - 1;
if (rhs == 0) {
return left()->definition();
} else if ((rhs < 0) || (rhs >= kMaxShift)) {
@@ -2317,8 +2318,16 @@
}
Definition* AssertBooleanInstr::Canonicalize(FlowGraph* flow_graph) {
- if (FLAG_eliminate_type_checks && (value()->Type()->ToCid() == kBoolCid)) {
- return value()->definition();
+ if (FLAG_eliminate_type_checks) {
+ if (value()->Type()->ToCid() == kBoolCid) {
+ return value()->definition();
+ }
+
+ // In strong mode type is already verified either by static analysis
+ // or runtime checks, so AssertBoolean just ensures that value is not null.
+ if (Isolate::Current()->strong() && !value()->Type()->is_nullable()) {
+ return value()->definition();
+ }
}
return this;
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index 1b5ccc7..380601f 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -439,13 +439,13 @@
Label done;
Isolate* isolate = Isolate::Current();
- if (isolate->type_checks() || isolate->strong()) {
+ if (isolate->type_checks()) {
__ CompareObject(reg, Bool::True());
__ b(&done, EQ);
__ CompareObject(reg, Bool::False());
__ b(&done, EQ);
} else {
- ASSERT(isolate->asserts());
+ ASSERT(isolate->asserts() || isolate->strong());
__ CompareObject(reg, Object::null_instance());
__ b(&done, NE);
}
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 08cfa0b..3bd1061 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -437,13 +437,13 @@
Label done;
Isolate* isolate = Isolate::Current();
- if (isolate->type_checks() || isolate->strong()) {
+ if (isolate->type_checks()) {
__ CompareObject(reg, Bool::True());
__ b(&done, EQ);
__ CompareObject(reg, Bool::False());
__ b(&done, EQ);
} else {
- ASSERT(isolate->asserts());
+ ASSERT(isolate->asserts() || isolate->strong());
__ CompareObject(reg, Object::null_instance());
__ b(&done, NE);
}
@@ -955,9 +955,13 @@
case kTwoByteStringCid:
case kExternalOneByteStringCid:
case kExternalTwoByteStringCid:
+ return CompileType::FromCid(kSmiCid);
+
case kTypedDataInt32ArrayCid:
case kTypedDataUint32ArrayCid:
- return CompileType::FromCid(kSmiCid);
+ // TODO(erikcorry): Perhaps this can return a faster type. See
+ // https://github.com/dart-lang/sdk/issues/32582
+ return CompileType::Int();
default:
UNIMPLEMENTED();
@@ -1231,7 +1235,6 @@
default:
UNREACHABLE();
}
- __ SmiTag(result);
break;
case kTwoByteStringCid:
case kExternalTwoByteStringCid:
@@ -1245,12 +1248,15 @@
default:
UNREACHABLE();
}
- __ SmiTag(result);
break;
default:
UNREACHABLE();
break;
}
+ if (representation_ == kTagged) {
+ ASSERT(can_pack_into_smi());
+ __ SmiTag(result);
+ }
}
Representation StoreIndexedInstr::RequiredInputRepresentation(
@@ -2723,18 +2729,27 @@
if (locs.in(1).IsConstant()) {
const Object& constant = locs.in(1).constant();
ASSERT(constant.IsSmi());
- // Immediate shift operation takes 6 bits for the count.
- const intptr_t kCountLimit = 0x3F;
+ // Immediate shift operation takes 5 bits for the count.
+ const intptr_t kCountLimit = 0x1F;
+ // These should be around the same size.
+ COMPILE_ASSERT(kCountLimit + 1 == kSmiBits + 2);
const intptr_t value = Smi::Cast(constant).Value();
ASSERT((0 < value) && (value < kCountLimit));
if (shift_left->can_overflow()) {
// Check for overflow (preserve left).
- __ LslImmediate(TMP, left, value);
- __ cmp(left, Operand(TMP, ASR, value));
+ __ LslImmediate(TMP, left, value, kWord);
+ __ cmpw(left, Operand(TMP, ASR, value));
__ b(deopt, NE); // Overflow.
}
- // Shift for result now we know there is no overflow.
+ // Shift for result now we know there is no overflow. This writes the full
+ // 64 bits of the output register, but unless we are in truncating mode the
+ // top bits will just be sign extension bits.
__ LslImmediate(result, left, value);
+ if (shift_left->is_truncating()) {
+ // This preserves the invariant that Smis only use the low 32 bits of the
+ // register, the high bits being sign extension bits.
+ __ sxtw(result, result);
+ }
return;
}
@@ -2742,28 +2757,33 @@
const Register right = locs.in(1).reg();
Range* right_range = shift_left->right_range();
if (shift_left->left()->BindsToConstant() && shift_left->can_overflow()) {
- // TODO(srdjan): Implement code below for is_truncating().
// If left is constant, we know the maximal allowed size for right.
const Object& obj = shift_left->left()->BoundConstant();
- if (obj.IsSmi()) {
- const intptr_t left_int = Smi::Cast(obj).Value();
- if (left_int == 0) {
- __ CompareRegisters(right, ZR);
- __ b(deopt, MI);
- __ mov(result, ZR);
- return;
- }
- const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int);
- const bool right_needs_check =
- !RangeUtils::IsWithin(right_range, 0, max_right - 1);
- if (right_needs_check) {
- __ CompareImmediate(right,
- reinterpret_cast<int64_t>(Smi::New(max_right)));
- __ b(deopt, CS);
- }
- __ SmiUntag(TMP, right);
- __ lslv(result, left, TMP);
+ // Even though we have a non-Smi constant on the left, we might still emit
+ // a Smi op here. In that case the Smi check above will have deopted, so
+ // we can't reach this point. Emit a breakpoint to be sure.
+ if (!obj.IsSmi()) {
+ __ Breakpoint();
+ return;
}
+ const intptr_t left_int = Smi::Cast(obj).Value();
+ if (left_int == 0) {
+ __ CompareRegisters(right, ZR);
+ __ b(deopt, MI);
+ __ mov(result, ZR);
+ return;
+ }
+ const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int);
+ const bool right_needs_check =
+ !RangeUtils::IsWithin(right_range, 0, max_right - 1);
+ if (right_needs_check) {
+ __ CompareImmediate(right,
+ reinterpret_cast<int64_t>(Smi::New(max_right)));
+ __ b(deopt, CS);
+ }
+ __ SmiUntag(TMP, right);
+ __ lslv(result, left, TMP);
+ ASSERT(!shift_left->is_truncating());
return;
}
@@ -2787,7 +2807,11 @@
__ SmiUntag(TMP, right);
__ lslv(result, left, TMP);
}
+ if (shift_left->is_truncating()) {
+ __ sxtw(result, result);
+ }
} else {
+ // If we can overflow.
if (right_needs_check) {
ASSERT(shift_left->CanDeoptimize());
__ CompareImmediate(right,
@@ -2795,15 +2819,16 @@
__ b(deopt, CS);
}
// Left is not a constant.
- // Check if count too large for handling it inlined.
+ // Check if count is too large for handling it inlined.
__ SmiUntag(TMP, right);
// Overflow test (preserve left, right, and TMP);
const Register temp = locs.temp(0).reg();
- __ lslv(temp, left, TMP);
- __ asrv(TMP2, temp, TMP);
- __ CompareRegisters(left, TMP2);
+ __ lslvw(temp, left, TMP);
+ __ asrvw(TMP2, temp, TMP);
+ __ cmpw(left, Operand(TMP2));
__ b(deopt, NE); // Overflow.
- // Shift for result now we know there is no overflow.
+ // Shift for result now we know there is no overflow. This is a 64 bit
+ // operation, so no sign extension is needed.
__ lslv(result, left, TMP);
}
}
@@ -2885,18 +2910,20 @@
switch (op_kind()) {
case Token::kADD:
- __ adds(result, left, Operand(right));
+ __ addsw(result, left, Operand(right));
__ b(slow_path->entry_label(), VS);
+ __ sxtw(result, result);
break;
case Token::kSUB:
- __ subs(result, left, Operand(right));
+ __ subsw(result, left, Operand(right));
__ b(slow_path->entry_label(), VS);
+ __ sxtw(result, result);
break;
case Token::kMUL:
__ SmiUntag(TMP, left);
- __ mul(result, TMP, right);
- __ smulh(TMP, TMP, right);
- // TMP: result bits 64..127.
+ __ smull(result, TMP, right);
+ __ AsrImmediate(TMP, result, 31);
+ // TMP: result bits 31-63
__ cmp(TMP, Operand(result, ASR, 63));
__ b(slow_path->entry_label(), NE);
break;
@@ -2921,8 +2948,8 @@
__ SmiUntag(TMP, right);
__ lslv(result, left, TMP);
- __ asrv(TMP2, result, TMP);
- __ CompareRegisters(left, TMP2);
+ __ asrvw(TMP2, result, TMP);
+ __ cmp(left, Operand(TMP2, SXTW, 0));
__ b(slow_path->entry_label(), NE); // Overflow.
break;
case Token::kSHR:
@@ -2932,6 +2959,8 @@
reinterpret_cast<int64_t>(Smi::New(Smi::kBits)));
__ b(slow_path->entry_label(), CS);
+ __ AssertSmiInRange(left);
+ __ AssertSmiInRange(right);
__ SmiUntag(result, right);
__ SmiUntag(TMP, left);
__ asrv(result, TMP, result);
@@ -2941,6 +2970,7 @@
UNIMPLEMENTED();
}
__ Bind(slow_path->exit_label());
+ __ AssertSmiInRange(result, Assembler::kValueCanBeHeapPointer);
}
class CheckedSmiComparisonSlowPath : public SlowPathCode {
@@ -3131,20 +3161,28 @@
case Token::kADD: {
if (deopt == NULL) {
__ AddImmediate(result, left, imm);
+ if (is_truncating()) {
+ __ sxtw(result, result);
+ }
} else {
- __ AddImmediateSetFlags(result, left, imm);
+ __ AddImmediateSetFlags(result, left, imm, kWord);
__ b(deopt, VS);
+ __ sxtw(result, result);
}
break;
}
case Token::kSUB: {
if (deopt == NULL) {
__ AddImmediate(result, left, -imm);
+ if (is_truncating()) {
+ __ sxtw(result, result);
+ }
} else {
// Negating imm and using AddImmediateSetFlags would not detect the
- // overflow when imm == kMinInt64.
- __ SubImmediateSetFlags(result, left, imm);
+ // overflow when imm == kMinInt32.
+ __ SubImmediateSetFlags(result, left, imm, kWord);
__ b(deopt, VS);
+ __ sxtw(result, result);
}
break;
}
@@ -3152,12 +3190,14 @@
// Keep left value tagged and untag right value.
const intptr_t value = Smi::Cast(constant).Value();
__ LoadImmediate(TMP, value);
- __ mul(result, left, TMP);
+ __ smull(result, left, TMP);
if (deopt != NULL) {
- __ smulh(TMP, left, TMP);
- // TMP: result bits 64..127.
+ __ AsrImmediate(TMP, result, 31);
+ // TMP: result bits 31..63.
__ cmp(TMP, Operand(result, ASR, 63));
__ b(deopt, NE);
+ } else if (is_truncating()) {
+ __ sxtw(result, result);
}
break;
}
@@ -3168,9 +3208,10 @@
const intptr_t shift_count =
Utils::ShiftForPowerOfTwo(Utils::Abs(value)) + kSmiTagSize;
ASSERT(kSmiTagSize == 1);
- __ AsrImmediate(TMP, left, 63);
+ __ AsrImmediate(TMP, left, 31); // All 1s or all 0s.
ASSERT(shift_count > 1); // 1, -1 case handled above.
const Register temp = TMP2;
+ // Adjust so that we round to 0 instead of round down.
__ add(temp, left, Operand(TMP, LSR, 64 - shift_count));
ASSERT(shift_count > 0);
__ AsrImmediate(result, temp, shift_count);
@@ -3205,6 +3246,7 @@
UNREACHABLE();
break;
}
+ __ AssertSmiInRange(result);
return;
}
@@ -3213,18 +3255,26 @@
case Token::kADD: {
if (deopt == NULL) {
__ add(result, left, Operand(right));
+ if (is_truncating()) {
+ __ sxtw(result, result);
+ }
} else {
- __ adds(result, left, Operand(right));
+ __ addsw(result, left, Operand(right));
__ b(deopt, VS);
+ __ sxtw(result, result);
}
break;
}
case Token::kSUB: {
if (deopt == NULL) {
__ sub(result, left, Operand(right));
+ if (is_truncating()) {
+ __ sxtw(result, result);
+ }
} else {
- __ subs(result, left, Operand(right));
+ __ subsw(result, left, Operand(right));
__ b(deopt, VS);
+ __ sxtw(result, result);
}
break;
}
@@ -3232,10 +3282,13 @@
__ SmiUntag(TMP, left);
if (deopt == NULL) {
__ mul(result, TMP, right);
+ if (is_truncating()) {
+ __ sxtw(result, result);
+ }
} else {
- __ mul(result, TMP, right);
- __ smulh(TMP, TMP, right);
- // TMP: result bits 64..127.
+ __ smull(result, TMP, right);
+ __ AsrImmediate(TMP, result, 31);
+ // TMP: result bits 31..63.
__ cmp(TMP, Operand(result, ASR, 63));
__ b(deopt, NE);
}
@@ -3270,7 +3323,7 @@
// Check the corner case of dividing the 'MIN_SMI' with -1, in which
// case we cannot tag the result.
- __ CompareImmediate(result, 0x4000000000000000LL);
+ __ CompareImmediate(result, 0x40000000LL);
__ b(deopt, EQ);
__ SmiTag(result);
break;
@@ -3315,8 +3368,10 @@
__ b(deopt, LT);
}
__ SmiUntag(TMP, right);
- // sarl operation masks the count to 6 bits.
- const intptr_t kCountLimit = 0x3F;
+ // The asrv operation masks the count to 6 bits, but any shift between 31
+ // and 63 gives the same result because 32 bit Smis are stored sign
+ // extended in the registers.
+ const intptr_t kCountLimit = 0x1F;
if (!RangeUtils::OnlyLessThanOrEqualTo(right_range(), kCountLimit)) {
__ LoadImmediate(TMP2, kCountLimit);
__ CompareRegisters(TMP, TMP2);
@@ -3345,6 +3400,7 @@
UNREACHABLE();
break;
}
+ __ AssertSmiInRange(result);
}
LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Zone* zone,
@@ -3497,10 +3553,17 @@
ASSERT((from_representation() == kUnboxedInt32) ||
(from_representation() == kUnboxedUint32));
const intptr_t kNumInputs = 1;
- const intptr_t kNumTemps = 0;
+ const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1;
LocationSummary* summary = new (zone)
- LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ LocationSummary(zone, kNumInputs, kNumTemps,
+ ValueFitsSmi() ? LocationSummary::kNoCall
+ : LocationSummary::kCallOnSlowPath);
+ // Get two distinct registers for input and output, plus a temp
+ // register for testing for overflow and allocating a Mint.
summary->set_in(0, Location::RequiresRegister());
+ if (!ValueFitsSmi()) {
+ summary->set_temp(0, Location::RequiresRegister());
+ }
summary->set_out(0, Location::RequiresRegister());
return summary;
}
@@ -3509,16 +3572,51 @@
Register value = locs()->in(0).reg();
Register out = locs()->out(0).reg();
ASSERT(value != out);
+ Label done;
- ASSERT(kSmiTagSize == 1);
- // TODO(vegorov) implement and use UBFM/SBFM for this.
- __ LslImmediate(out, value, 32);
if (from_representation() == kUnboxedInt32) {
- __ AsrImmediate(out, out, 32 - kSmiTagSize);
+ ASSERT(kSmiTag == 0);
+ // Signed Bitfield Insert in Zero instruction extracts the 31 significant
+ // bits from a Smi.
+ __ sbfiz(out, value, kSmiTagSize, 32 - kSmiTagSize);
+ if (ValueFitsSmi()) {
+ return;
+ }
+ Register temp = locs()->temp(0).reg();
+ __ cmp(out, Operand(value, LSL, 1));
+ __ b(&done, EQ); // Jump if the sbfiz instruction didn't lose info.
+ BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), out,
+ temp);
+ __ sxtw(temp, value);
} else {
ASSERT(from_representation() == kUnboxedUint32);
- __ LsrImmediate(out, out, 32 - kSmiTagSize);
+ ASSERT(kSmiTag == 0);
+ // A 32 bit positive Smi has one tag bit and one unused sign bit,
+ // leaving only 30 bits for the payload.
+ __ ubfiz(out, value, kSmiTagSize, kSmiBits);
+ if (ValueFitsSmi()) {
+ return;
+ }
+ Register temp = locs()->temp(0).reg();
+ __ TestImmediate(value, 0xc0000000);
+ __ b(&done, EQ); // Jump if both bits are zero.
+ BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), out,
+ temp);
+ __ ubfiz(temp, value, 0, 32); // Zero extend word.
}
+
+ __ StoreToOffset(locs()->temp(0).reg(), out,
+ Mint::value_offset() - kHeapObjectTag);
+
+#if defined(DEBUG)
+ Label skip_smi_test;
+ __ b(&skip_smi_test);
+ __ Bind(&done);
+ __ AssertSmiInRange(out, Assembler::kValueCanBeHeapPointer);
+ __ Bind(&skip_smi_test);
+#else
+ __ Bind(&done);
+#endif
}
LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone,
@@ -3546,7 +3644,8 @@
}
ASSERT(kSmiTag == 0);
- __ LslImmediate(out, in, kSmiTagSize);
+ __ LslImmediate(out, in, kSmiTagSize, kWord);
+ __ sxtw(out, out);
Label done;
__ cmp(in, Operand(out, ASR, kSmiTagSize));
__ b(&done, EQ);
@@ -4287,8 +4386,9 @@
switch (op_kind()) {
case Token::kNEGATE: {
Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp);
- __ subs(result, ZR, Operand(value));
+ __ subsw(result, ZR, Operand(value));
__ b(deopt, VS);
+ __ sxtw(result, result);
break;
}
case Token::kBIT_NOT:
@@ -4299,6 +4399,7 @@
default:
UNREACHABLE();
}
+ __ AssertSmiInRange(result);
}
LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone,
@@ -4350,7 +4451,7 @@
const Register value = locs()->in(0).reg();
const VRegister result = locs()->out(0).fpu_reg();
__ SmiUntag(TMP, value);
- __ scvtfdx(result, TMP);
+ __ scvtfdw(result, TMP);
}
LocationSummary* Int64ToDoubleInstr::MakeLocationSummary(Zone* zone,
@@ -4394,12 +4495,13 @@
__ fcmpd(VTMP, VTMP);
__ b(&do_call, VS);
- __ fcvtzds(result, VTMP);
+ __ fcvtzdsx(result, VTMP);
// Overflow is signaled with minint.
// Check for overflow and that it fits into Smi.
- __ CompareImmediate(result, 0xC000000000000000);
- __ b(&do_call, MI);
+ __ AsrImmediate(TMP, result, 30);
+ __ cmp(TMP, Operand(result, ASR, 63));
+ __ b(&do_call, NE);
__ SmiTag(result);
__ b(&done);
__ Bind(&do_call);
@@ -4416,6 +4518,7 @@
args_info, locs(), ICData::Handle(),
ICData::kStatic);
__ Bind(&done);
+ __ AssertSmiInRange(result, Assembler::kValueCanBeHeapPointer);
}
LocationSummary* DoubleToSmiInstr::MakeLocationSummary(Zone* zone,
@@ -4439,11 +4542,13 @@
__ fcmpd(value, value);
__ b(deopt, VS);
- __ fcvtzds(result, value);
+ __ fcvtzdsx(result, value);
// Check for overflow and that it fits into Smi.
- __ CompareImmediate(result, 0xC000000000000000);
- __ b(deopt, MI);
+ __ AsrImmediate(TMP, result, 30);
+ __ cmp(TMP, Operand(result, ASR, 63));
+ __ b(deopt, NE);
__ SmiTag(result);
+ __ AssertSmiInRange(result);
}
LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone,
@@ -4712,7 +4817,7 @@
// Check the corner case of dividing the 'MIN_SMI' with -1, in which
// case we cannot tag the result.
- __ CompareImmediate(result_div, 0x4000000000000000);
+ __ CompareImmediate(result_div, 0x40000000);
__ b(deopt, EQ);
// result_mod <- left - right * result_div.
__ msub(result_mod, TMP, result_div, result_mod);
@@ -5241,6 +5346,10 @@
Register shifter = locs()->in(1).reg();
// TODO(johnmccutchan): Use range information to avoid these checks.
+ // Assert this is a legitimate Smi in debug mode, but does not assert
+ // anything about the range relative to the bit width.
+ __ AssertSmiInRange(shifter);
+
__ SmiUntag(TMP, shifter);
__ CompareImmediate(TMP, 0);
// If shift value is < 0, deoptimize.
@@ -5260,7 +5369,7 @@
__ CompareImmediate(TMP, kShifterLimit);
// If shift value is > 31, return zero.
- __ csel(out, out, ZR, GT);
+ __ csel(out, ZR, out, GT);
}
LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Zone* zone,
diff --git a/runtime/vm/compiler/backend/il_dbc.cc b/runtime/vm/compiler/backend/il_dbc.cc
index e9504a4..093c340 100644
--- a/runtime/vm/compiler/backend/il_dbc.cc
+++ b/runtime/vm/compiler/backend/il_dbc.cc
@@ -196,7 +196,7 @@
__ Push(locs()->in(0).reg());
}
Isolate* isolate = Isolate::Current();
- __ AssertBoolean((isolate->type_checks() || isolate->strong()) ? 1 : 0);
+ __ AssertBoolean(isolate->type_checks() ? 1 : 0);
compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(),
token_pos());
compiler->RecordAfterCall(this, FlowGraphCompiler::kHasResult);
diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc
index 83661ab..86a74e8 100644
--- a/runtime/vm/compiler/backend/il_ia32.cc
+++ b/runtime/vm/compiler/backend/il_ia32.cc
@@ -312,13 +312,13 @@
Label done;
Isolate* isolate = Isolate::Current();
- if (isolate->type_checks() || isolate->strong()) {
+ if (isolate->type_checks()) {
__ CompareObject(reg, Bool::True());
__ j(EQUAL, &done, Assembler::kNearJump);
__ CompareObject(reg, Bool::False());
__ j(EQUAL, &done, Assembler::kNearJump);
} else {
- ASSERT(isolate->asserts());
+ ASSERT(isolate->asserts() || isolate->strong());
__ CompareObject(reg, Object::null_instance());
__ j(NOT_EQUAL, &done, Assembler::kNearJump);
}
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index 9128f93..1e292ce 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -405,13 +405,13 @@
Label done;
Isolate* isolate = Isolate::Current();
- if (isolate->type_checks() || isolate->strong()) {
+ if (isolate->type_checks()) {
__ CompareObject(reg, Bool::True());
__ j(EQUAL, &done, Assembler::kNearJump);
__ CompareObject(reg, Bool::False());
__ j(EQUAL, &done, Assembler::kNearJump);
} else {
- ASSERT(isolate->asserts());
+ ASSERT(isolate->asserts() || isolate->strong());
__ CompareObject(reg, Object::null_instance());
__ j(NOT_EQUAL, &done, Assembler::kNearJump);
}
@@ -951,6 +951,61 @@
}
}
+class BoxAllocationSlowPath : public SlowPathCode {
+ public:
+ BoxAllocationSlowPath(Instruction* instruction,
+ const Class& cls,
+ Register result)
+ : instruction_(instruction), cls_(cls), result_(result) {}
+
+ virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
+ if (Assembler::EmittingComments()) {
+ __ Comment("%s slow path allocation of %s", instruction_->DebugName(),
+ String::Handle(cls_.ScrubbedName()).ToCString());
+ }
+ __ Bind(entry_label());
+ const Code& stub = Code::ZoneHandle(
+ compiler->zone(), StubCode::GetAllocationStubForClass(cls_));
+ const StubEntry stub_entry(stub);
+
+ LocationSummary* locs = instruction_->locs();
+
+ locs->live_registers()->Remove(Location::RegisterLocation(result_));
+
+ compiler->SaveLiveRegisters(locs);
+ compiler->GenerateCall(TokenPosition::kNoSource, // No token position.
+ stub_entry, RawPcDescriptors::kOther, locs);
+ compiler->AddStubCallTarget(stub);
+ __ MoveRegister(result_, RAX);
+ compiler->RestoreLiveRegisters(locs);
+ __ jmp(exit_label());
+ }
+
+ static void Allocate(FlowGraphCompiler* compiler,
+ Instruction* instruction,
+ const Class& cls,
+ Register result,
+ Register temp) {
+ if (compiler->intrinsic_mode()) {
+ __ TryAllocate(cls, compiler->intrinsic_slow_path_label(),
+ Assembler::kFarJump, result, temp);
+ } else {
+ BoxAllocationSlowPath* slow_path =
+ new BoxAllocationSlowPath(instruction, cls, result);
+ compiler->AddSlowPathCode(slow_path);
+
+ __ TryAllocate(cls, slow_path->entry_label(), Assembler::kFarJump, result,
+ temp);
+ __ Bind(slow_path->exit_label());
+ }
+ }
+
+ private:
+ Instruction* instruction_;
+ const Class& cls_;
+ const Register result_;
+};
+
CompileType LoadIndexedInstr::ComputeType() const {
switch (class_id_) {
case kArrayCid:
@@ -978,11 +1033,13 @@
case kTwoByteStringCid:
case kExternalOneByteStringCid:
case kExternalTwoByteStringCid:
- case kTypedDataInt32ArrayCid:
- case kTypedDataUint32ArrayCid:
return CompileType::FromCid(kSmiCid);
+ case kTypedDataInt32ArrayCid:
+ case kTypedDataUint32ArrayCid:
case kTypedDataInt64ArrayCid:
+ // TODO(erikcorry): Perhaps this can return a faster type. See
+ // https://github.com/dart-lang/sdk/issues/32582
return CompileType::Int();
default:
@@ -1165,16 +1222,24 @@
LocationSummary* LoadCodeUnitsInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
+ const bool might_box = (representation() == kTagged) && !can_pack_into_smi();
const intptr_t kNumInputs = 2;
- const intptr_t kNumTemps = 0;
- LocationSummary* summary = new (zone)
- LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ const intptr_t kNumTemps = might_box ? 2 : 0;
+ LocationSummary* summary = new (zone) LocationSummary(
+ zone, kNumInputs, kNumTemps,
+ might_box ? LocationSummary::kCallOnSlowPath : LocationSummary::kNoCall);
summary->set_in(0, Location::RequiresRegister());
// The smi index is either untagged (element size == 1), or it is left smi
// tagged (for all element sizes > 1).
summary->set_in(1, index_scale() == 1 ? Location::WritableRegister()
: Location::RequiresRegister());
summary->set_out(0, Location::RequiresRegister());
+
+ if (might_box) {
+ summary->set_temp(0, Location::RequiresRegister());
+ summary->set_temp(1, Location::RequiresRegister());
+ }
+
return summary;
}
@@ -1206,7 +1271,6 @@
default:
UNREACHABLE();
}
- __ SmiTag(result);
break;
case kTwoByteStringCid:
case kExternalTwoByteStringCid:
@@ -1220,12 +1284,34 @@
default:
UNREACHABLE();
}
- __ SmiTag(result);
break;
default:
UNREACHABLE();
break;
}
+ if (representation_ == kTagged) {
+ if (can_pack_into_smi()) {
+ __ SmiTag(result);
+ } else {
+ // If the value cannot fit in a smi then allocate a mint box for it.
+ Register temp = locs()->temp(0).reg();
+ Register temp2 = locs()->temp(1).reg();
+ // Temp register needs to be manually preserved on allocation slow-path.
+ locs()->live_registers()->Add(locs()->temp(0), kUnboxedInt32);
+
+ ASSERT(temp != result);
+ __ MoveRegister(temp, result);
+ __ SmiTag(result);
+
+ Label done;
+ __ TestImmediate(temp, Immediate(0xc0000000ll));
+ __ j(ZERO, &done);
+ BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(),
+ result, temp2);
+ __ movq(FieldAddress(result, Mint::value_offset()), temp);
+ __ Bind(&done);
+ }
+ }
}
Representation StoreIndexedInstr::RequiredInputRepresentation(
@@ -1688,61 +1774,6 @@
}
}
-class BoxAllocationSlowPath : public SlowPathCode {
- public:
- BoxAllocationSlowPath(Instruction* instruction,
- const Class& cls,
- Register result)
- : instruction_(instruction), cls_(cls), result_(result) {}
-
- virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
- if (Assembler::EmittingComments()) {
- __ Comment("%s slow path allocation of %s", instruction_->DebugName(),
- String::Handle(cls_.ScrubbedName()).ToCString());
- }
- __ Bind(entry_label());
- const Code& stub = Code::ZoneHandle(
- compiler->zone(), StubCode::GetAllocationStubForClass(cls_));
- const StubEntry stub_entry(stub);
-
- LocationSummary* locs = instruction_->locs();
-
- locs->live_registers()->Remove(Location::RegisterLocation(result_));
-
- compiler->SaveLiveRegisters(locs);
- compiler->GenerateCall(TokenPosition::kNoSource, // No token position.
- stub_entry, RawPcDescriptors::kOther, locs);
- compiler->AddStubCallTarget(stub);
- __ MoveRegister(result_, RAX);
- compiler->RestoreLiveRegisters(locs);
- __ jmp(exit_label());
- }
-
- static void Allocate(FlowGraphCompiler* compiler,
- Instruction* instruction,
- const Class& cls,
- Register result,
- Register temp) {
- if (compiler->intrinsic_mode()) {
- __ TryAllocate(cls, compiler->intrinsic_slow_path_label(),
- Assembler::kFarJump, result, temp);
- } else {
- BoxAllocationSlowPath* slow_path =
- new BoxAllocationSlowPath(instruction, cls, result);
- compiler->AddSlowPathCode(slow_path);
-
- __ TryAllocate(cls, slow_path->entry_label(), Assembler::kFarJump, result,
- temp);
- __ Bind(slow_path->exit_label());
- }
- }
-
- private:
- Instruction* instruction_;
- const Class& cls_;
- const Register result_;
-};
-
LocationSummary* StoreInstanceFieldInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 2;
@@ -2664,27 +2695,32 @@
if (locs.in(1).IsConstant()) {
const Object& constant = locs.in(1).constant();
ASSERT(constant.IsSmi());
- // shlq operation masks the count to 6 bits.
- const intptr_t kCountLimit = 0x3F;
+ // shll operation masks the count to 5 bits.
+ const intptr_t kCountLimit = 0x1F;
const intptr_t value = Smi::Cast(constant).Value();
ASSERT((0 < value) && (value < kCountLimit));
if (shift_left->can_overflow()) {
if (value == 1) {
// Use overflow flag.
- __ shlq(left, Immediate(1));
+ __ shll(left, Immediate(1));
__ j(OVERFLOW, deopt);
+ __ movsxd(left, left);
return;
}
// Check for overflow.
Register temp = locs.temp(0).reg();
__ movq(temp, left);
- __ shlq(left, Immediate(value));
- __ sarq(left, Immediate(value));
+ __ shll(left, Immediate(value));
+ __ sarl(left, Immediate(value));
+ __ movsxd(left, left);
__ cmpq(left, temp);
__ j(NOT_EQUAL, deopt); // Overflow.
}
// Shift for result now we know there is no overflow.
__ shlq(left, Immediate(value));
+ if (shift_left->is_truncating()) {
+ __ movsxd(left, left);
+ }
return;
}
@@ -2695,23 +2731,32 @@
// TODO(srdjan): Implement code below for is_truncating().
// If left is constant, we know the maximal allowed size for right.
const Object& obj = shift_left->left()->BoundConstant();
- if (obj.IsSmi()) {
- const intptr_t left_int = Smi::Cast(obj).Value();
- if (left_int == 0) {
- __ CompareImmediate(right, Immediate(0));
- __ j(NEGATIVE, deopt);
- return;
- }
- const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int);
- const bool right_needs_check =
- !RangeUtils::IsWithin(right_range, 0, max_right - 1);
- if (right_needs_check) {
- __ CompareImmediate(
- right, Immediate(reinterpret_cast<int64_t>(Smi::New(max_right))));
- __ j(ABOVE_EQUAL, deopt);
- }
- __ SmiUntag(right);
- __ shlq(left, right);
+ // Even though we have a non-Smi constant on the left, we might still emit
+ // a Smi op here. In that case the Smi check above will have deopted, so
+ // we can't reach this point. Emit a breakpoint to be sure.
+ if (!obj.IsSmi()) {
+ __ int3();
+ return;
+ }
+ const intptr_t left_int = Smi::Cast(obj).Value();
+ if (left_int == 0) {
+ __ CompareImmediate(right, Immediate(0));
+ __ j(NEGATIVE, deopt);
+ return;
+ }
+ const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int);
+ const bool right_needs_check =
+ !RangeUtils::IsWithin(right_range, 0, max_right - 1);
+ if (right_needs_check) {
+ __ CompareImmediate(
+ right, Immediate(reinterpret_cast<int64_t>(Smi::New(max_right))));
+ __ j(ABOVE_EQUAL, deopt);
+ }
+ __ AssertSmiInRange(right);
+ __ SmiUntag(right);
+ __ shlq(left, right);
+ if (shift_left->is_truncating()) {
+ __ movsxd(left, left);
}
return;
}
@@ -2735,13 +2780,18 @@
__ xorq(left, left);
__ jmp(&done, Assembler::kNearJump);
__ Bind(&is_not_zero);
+ __ AssertSmiInRange(right);
__ SmiUntag(right);
__ shlq(left, right);
__ Bind(&done);
} else {
+ __ AssertSmiInRange(right);
__ SmiUntag(right);
__ shlq(left, right);
}
+ if (shift_left->is_truncating()) {
+ __ movsxd(left, left);
+ }
} else {
if (right_needs_check) {
ASSERT(shift_left->CanDeoptimize());
@@ -2751,16 +2801,18 @@
}
// Left is not a constant.
Register temp = locs.temp(0).reg();
- // Check if count too large for handling it inlined.
- __ movq(temp, left);
+ // Check if count is too large for handling it inlined.
+ __ movl(temp, left);
+ __ AssertSmiInRange(right);
__ SmiUntag(right);
// Overflow test (preserve temp and right);
- __ shlq(left, right);
- __ sarq(left, right);
- __ cmpq(left, temp);
+ __ shll(temp, right);
+ __ sarl(temp, right);
+ __ cmpl(temp, left);
__ j(NOT_EQUAL, deopt); // Overflow.
// Shift for result now we know there is no overflow.
__ shlq(left, right);
+ ASSERT(!shift_left->is_truncating());
}
}
@@ -2861,19 +2913,23 @@
switch (op_kind()) {
case Token::kADD:
__ movq(result, left);
- __ addq(result, right);
+ __ addl(result, right);
__ j(OVERFLOW, slow_path->entry_label());
+ __ movsxd(result, result);
break;
case Token::kSUB:
__ movq(result, left);
- __ subq(result, right);
+ __ subl(result, right);
__ j(OVERFLOW, slow_path->entry_label());
+ __ movsxd(result, result);
break;
case Token::kMUL:
__ movq(result, left);
+ __ AssertSmiInRange(result);
__ SmiUntag(result);
- __ imulq(result, right);
+ __ imull(result, right);
__ j(OVERFLOW, slow_path->entry_label());
+ __ movsxd(result, result);
break;
case Token::kBIT_OR:
ASSERT(left == result);
@@ -2894,13 +2950,15 @@
__ j(ABOVE_EQUAL, slow_path->entry_label());
__ movq(RCX, right);
+ __ AssertSmiInRange(RCX);
__ SmiUntag(RCX);
__ movq(result, left);
- __ shlq(result, RCX);
+ __ shll(result, RCX);
__ movq(TMP, result);
- __ sarq(TMP, RCX);
- __ cmpq(TMP, left);
+ __ sarl(TMP, RCX);
+ __ cmpl(TMP, left);
__ j(NOT_EQUAL, slow_path->entry_label());
+ __ movsxd(result, result);
break;
case Token::kSHR: {
Label shift_count_ok;
@@ -2909,6 +2967,8 @@
__ cmpq(right, Immediate(Smi::RawValue(Smi::kBits)));
__ j(ABOVE_EQUAL, slow_path->entry_label());
+ __ AssertSmiInRange(left);
+ __ AssertSmiInRange(right);
__ movq(RCX, right);
__ SmiUntag(RCX);
__ movq(result, left);
@@ -3166,20 +3226,41 @@
const int64_t imm = reinterpret_cast<int64_t>(constant.raw());
switch (op_kind()) {
case Token::kADD: {
- __ AddImmediate(left, Immediate(imm));
- if (deopt != NULL) __ j(OVERFLOW, deopt);
+ if (deopt != NULL) {
+ __ AddImmediate(left, Immediate(imm), Assembler::k32Bit);
+ __ j(OVERFLOW, deopt);
+ } else {
+ __ AddImmediate(left, Immediate(imm), Assembler::k64Bit);
+ }
+ if (deopt != NULL || is_truncating()) {
+ __ movsxd(left, left);
+ }
break;
}
case Token::kSUB: {
- __ SubImmediate(left, Immediate(imm));
- if (deopt != NULL) __ j(OVERFLOW, deopt);
+ if (deopt != NULL) {
+ __ SubImmediate(left, Immediate(imm), Assembler::k32Bit);
+ __ j(OVERFLOW, deopt);
+ } else {
+ __ SubImmediate(left, Immediate(imm), Assembler::k64Bit);
+ }
+ if (deopt != NULL || is_truncating()) {
+ __ movsxd(left, left);
+ }
break;
}
case Token::kMUL: {
// Keep left value tagged and untag right value.
const intptr_t value = Smi::Cast(constant).Value();
- __ MulImmediate(left, Immediate(value));
- if (deopt != NULL) __ j(OVERFLOW, deopt);
+ if (deopt != NULL) {
+ __ MulImmediate(left, Immediate(value), Assembler::k32Bit);
+ __ j(OVERFLOW, deopt);
+ } else {
+ __ MulImmediate(left, Immediate(value), Assembler::k64Bit);
+ }
+ if (deopt != NULL || is_truncating()) {
+ __ movsxd(left, left);
+ }
break;
}
case Token::kTRUNCDIV: {
@@ -3191,7 +3272,9 @@
ASSERT(kSmiTagSize == 1);
Register temp = locs()->temp(0).reg();
__ movq(temp, left);
- __ sarq(temp, Immediate(63));
+ // Since Smis are sign extended this is enough shift to put all-1s or
+ // all-0s in the temp register.
+ __ sarq(temp, Immediate(31));
ASSERT(shift_count > 1); // 1, -1 case handled above.
__ shrq(temp, Immediate(64 - shift_count));
__ addq(left, temp);
@@ -3220,8 +3303,10 @@
}
case Token::kSHR: {
- // sarq operation masks the count to 6 bits.
- const intptr_t kCountLimit = 0x3F;
+ // The sarq operation masks the count to 6 bits, but any shift between
+ // 31 and 63 gives the same result because 32 bit Smis are stored sign
+ // extended in the registers.
+ const intptr_t kCountLimit = 0x1F;
const intptr_t value = Smi::Cast(constant).Value();
__ sarq(left,
Immediate(Utils::Minimum(value + kSmiTagSize, kCountLimit)));
@@ -3233,6 +3318,7 @@
UNREACHABLE();
break;
}
+ __ AssertSmiInRange(left);
return;
} // locs()->in(1).IsConstant().
@@ -3240,19 +3326,40 @@
const Address& right = locs()->in(1).ToStackSlotAddress();
switch (op_kind()) {
case Token::kADD: {
- __ addq(left, right);
- if (deopt != NULL) __ j(OVERFLOW, deopt);
+ if (deopt != NULL) {
+ __ addl(left, right);
+ __ j(OVERFLOW, deopt);
+ } else {
+ __ addq(left, right);
+ }
+ if (deopt != NULL || is_truncating()) {
+ __ movsxd(left, left);
+ }
break;
}
case Token::kSUB: {
- __ subq(left, right);
- if (deopt != NULL) __ j(OVERFLOW, deopt);
+ if (deopt != NULL) {
+ __ subl(left, right);
+ __ j(OVERFLOW, deopt);
+ } else {
+ __ subq(left, right);
+ }
+ if (deopt != NULL || is_truncating()) {
+ __ movsxd(left, left);
+ }
break;
}
case Token::kMUL: {
__ SmiUntag(left);
- __ imulq(left, right);
- if (deopt != NULL) __ j(OVERFLOW, deopt);
+ if (deopt != NULL) {
+ __ imull(left, right);
+ __ j(OVERFLOW, deopt);
+ } else {
+ __ imulq(left, right);
+ }
+ if (deopt != NULL || is_truncating()) {
+ __ movsxd(left, left);
+ }
break;
}
case Token::kBIT_AND: {
@@ -3281,19 +3388,40 @@
Register right = locs()->in(1).reg();
switch (op_kind()) {
case Token::kADD: {
- __ addq(left, right);
- if (deopt != NULL) __ j(OVERFLOW, deopt);
+ if (deopt != NULL) {
+ __ addl(left, right);
+ __ j(OVERFLOW, deopt);
+ } else {
+ __ addq(left, right);
+ }
+ if (deopt != NULL || is_truncating()) {
+ __ movsxd(left, left);
+ }
break;
}
case Token::kSUB: {
- __ subq(left, right);
- if (deopt != NULL) __ j(OVERFLOW, deopt);
+ if (deopt != NULL) {
+ __ subl(left, right);
+ __ j(OVERFLOW, deopt);
+ } else {
+ __ subq(left, right);
+ }
+ if (deopt != NULL || is_truncating()) {
+ __ movsxd(left, left);
+ }
break;
}
case Token::kMUL: {
__ SmiUntag(left);
- __ imulq(left, right);
- if (deopt != NULL) __ j(OVERFLOW, deopt);
+ if (deopt != NULL) {
+ __ imull(left, right);
+ __ j(OVERFLOW, deopt);
+ } else {
+ __ imulq(left, right);
+ }
+ if (deopt != NULL || is_truncating()) {
+ __ movsxd(left, left);
+ }
break;
}
case Token::kBIT_AND: {
@@ -3312,8 +3440,6 @@
break;
}
case Token::kTRUNCDIV: {
- Label not_32bit, done;
-
Register temp = locs()->temp(0).reg();
ASSERT(left == RAX);
ASSERT((right != RDX) && (right != RAX));
@@ -3324,43 +3450,20 @@
__ testq(right, right);
__ j(ZERO, deopt);
}
- // Check if both operands fit into 32bits as idiv with 64bit operands
- // requires twice as many cycles and has much higher latency.
- // We are checking this before untagging them to avoid corner case
- // dividing INT_MAX by -1 that raises exception because quotient is
- // too large for 32bit register.
- __ movsxd(temp, left);
- __ cmpq(temp, left);
- __ j(NOT_EQUAL, ¬_32bit);
- __ movsxd(temp, right);
- __ cmpq(temp, right);
- __ j(NOT_EQUAL, ¬_32bit);
-
// Both operands are 31bit smis. Divide using 32bit idiv.
__ SmiUntag(left);
__ SmiUntag(right);
__ cdq();
__ idivl(right);
- __ movsxd(result, result);
- __ jmp(&done);
-
- // Divide using 64bit idiv.
- __ Bind(¬_32bit);
- __ SmiUntag(left);
- __ SmiUntag(right);
- __ cqo(); // Sign extend RAX -> RDX:RAX.
- __ idivq(right); // RAX: quotient, RDX: remainder.
// Check the corner case of dividing the 'MIN_SMI' with -1, in which
// case we cannot tag the result.
- __ CompareImmediate(result, Immediate(0x4000000000000000));
+ __ cmpl(result, Immediate(0x40000000));
__ j(EQUAL, deopt);
- __ Bind(&done);
+ __ movsxd(result, result);
__ SmiTag(result);
break;
}
case Token::kMOD: {
- Label not_32bit, div_done;
-
Register temp = locs()->temp(0).reg();
ASSERT(left == RDX);
ASSERT((right != RDX) && (right != RAX));
@@ -3371,17 +3474,6 @@
__ testq(right, right);
__ j(ZERO, deopt);
}
- // Check if both operands fit into 32bits as idiv with 64bit operands
- // requires twice as many cycles and has much higher latency.
- // We are checking this before untagging them to avoid corner case
- // dividing INT_MAX by -1 that raises exception because quotient is
- // too large for 32bit register.
- __ movsxd(temp, left);
- __ cmpq(temp, left);
- __ j(NOT_EQUAL, ¬_32bit);
- __ movsxd(temp, right);
- __ cmpq(temp, right);
- __ j(NOT_EQUAL, ¬_32bit);
// Both operands are 31bit smis. Divide using 32bit idiv.
__ SmiUntag(left);
__ SmiUntag(right);
@@ -3389,16 +3481,7 @@
__ cdq();
__ idivl(right);
__ movsxd(result, result);
- __ jmp(&div_done);
- // Divide using 64bit idiv.
- __ Bind(¬_32bit);
- __ SmiUntag(left);
- __ SmiUntag(right);
- __ movq(RAX, RDX);
- __ cqo(); // Sign extend RAX -> RDX:RAX.
- __ idivq(right); // RAX: quotient, RDX: remainder.
- __ Bind(&div_done);
// res = left % right;
// if (res < 0) {
// if (right < 0) {
@@ -3436,7 +3519,10 @@
__ j(LESS, deopt);
}
__ SmiUntag(right);
- // sarq operation masks the count to 6 bits.
+ // The sarq operation masks the count to 6 bits, but any shift between 31
+ // and 63 gives the same result because 32 bit Smis are stored sign
+ // extended in the registers. We check for 63 in order to take the branch
+ // more predictably.
const intptr_t kCountLimit = 0x3F;
if (!RangeUtils::OnlyLessThanOrEqualTo(right_range(), kCountLimit)) {
__ CompareImmediate(right, Immediate(kCountLimit));
@@ -3649,41 +3735,52 @@
GetDeoptId(), ICData::kDeoptUnboxInteger)
: NULL;
ASSERT(value == locs()->out(0).reg());
+ Label done_and_no_need_to_check_range;
+
+ ASSERT(locs()->out(0).reg() == value);
if (value_cid == kSmiCid) {
+ __ AssertSmiInRange(value);
__ SmiUntag(value);
+ return;
} else if (value_cid == kMintCid) {
__ movq(value, FieldAddress(value, Mint::value_offset()));
} else if (!CanDeoptimize()) {
- // Type information is not conclusive, but range analysis found
- // the value to be in int64 range. Therefore it must be a smi
- // or mint value.
- ASSERT(is_truncating());
Label done;
__ SmiUntag(value);
__ j(NOT_CARRY, &done, Assembler::kNearJump);
- __ movq(value, Address(value, TIMES_2, Mint::value_offset()));
+ // Multiply by two in addressing mode because we erroneously
+ // untagged a pointer by dividing it by two.
+ Address value_field(value, TIMES_2, Mint::value_offset());
+ if (is_truncating()) {
+ __ movl(value, value_field);
+ __ movsxd(value, value);
+ } else {
+ __ movq(value, value_field);
+ }
__ Bind(&done);
return;
} else {
- Label done;
- // Optimistically untag value.
- __ SmiUntagOrCheckClass(value, kMintCid, &done);
+ __ SmiUntagOrCheckClass(value, kMintCid, &done_and_no_need_to_check_range);
__ j(NOT_EQUAL, deopt);
- // Undo untagging by multiplying value with 2.
+ // Multiply by two in addressing mode because we erroneously
+ // untagged a pointer by dividing it by two.
__ movq(value, Address(value, TIMES_2, Mint::value_offset()));
- __ Bind(&done);
}
- // TODO(vegorov): as it is implemented right now truncating unboxing would
- // leave "garbage" in the higher word.
+ // We get here for the Mint cases, which might be out of range for an
+ // unboxed int32 output.
+
+ // TODO(vegorov): Truncating unboxing leaves garbage in the higher word.
+ // Is this the best semantics?
if (!is_truncating() && (deopt != NULL)) {
ASSERT(representation() == kUnboxedInt32);
- Register temp = locs()->temp(0).reg();
+ const Register temp = locs()->temp(0).reg();
__ movsxd(temp, value);
__ cmpq(temp, value);
__ j(NOT_EQUAL, deopt);
}
+ __ Bind(&done_and_no_need_to_check_range);
}
LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone,
@@ -3691,27 +3788,61 @@
ASSERT((from_representation() == kUnboxedInt32) ||
(from_representation() == kUnboxedUint32));
const intptr_t kNumInputs = 1;
- const intptr_t kNumTemps = 0;
+ const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1;
LocationSummary* summary = new (zone)
- LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
- summary->set_in(0, Location::RequiresRegister());
- summary->set_out(0, Location::RequiresRegister());
+ LocationSummary(zone, kNumInputs, kNumTemps,
+ ValueFitsSmi() ? LocationSummary::kNoCall
+ : LocationSummary::kCallOnSlowPath);
+ const bool needs_writable_input =
+ ValueFitsSmi() || (from_representation() == kUnboxedUint32);
+ summary->set_in(0, needs_writable_input ? Location::RequiresRegister()
+ : Location::WritableRegister());
+ if (!ValueFitsSmi()) {
+ summary->set_temp(0, Location::RequiresRegister());
+ }
+ summary->set_out(0, ValueFitsSmi() ? Location::SameAsFirstInput()
+ : Location::RequiresRegister());
return summary;
}
void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
const Register value = locs()->in(0).reg();
const Register out = locs()->out(0).reg();
- ASSERT(value != out);
+ Label done;
- ASSERT(kSmiTagSize == 1);
if (from_representation() == kUnboxedInt32) {
- __ movsxd(out, value);
+ __ MoveRegister(out, value);
+ ASSERT(kSmiTagMask == 1 && kSmiTag == 0);
+ __ addl(out, out);
+ __ movsxd(out, out); // Does not affect flags.
} else {
- ASSERT(from_representation() == kUnboxedUint32);
+ // Unsigned.
__ movl(out, value);
+ __ SmiTag(out);
}
- __ SmiTag(out);
+
+ if (!ValueFitsSmi()) {
+ if (from_representation() == kUnboxedInt32) {
+ __ j(NO_OVERFLOW, &done);
+ } else {
+ ASSERT(value != out);
+ __ TestImmediate(value, Immediate(0xc0000000ll));
+ __ j(ZERO, &done);
+ }
+ // Allocate a mint.
+ // Value input is a writable register and we have to inform the compiler of
+ // the type so it can be preserved untagged on the slow path
+ locs()->live_registers()->Add(locs()->in(0), kUnboxedInt32);
+ BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), out,
+ locs()->temp(0).reg());
+ if (from_representation() == kUnboxedInt32) {
+ __ movsxd(value, value);
+ } else {
+ __ movl(value, value);
+ }
+ __ movq(FieldAddress(out, Mint::value_offset()), value);
+ __ Bind(&done);
+ }
}
LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone,
@@ -3733,15 +3864,20 @@
void BoxInt64Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
const Register out = locs()->out(0).reg();
const Register value = locs()->in(0).reg();
- __ MoveRegister(out, value);
- __ SmiTag(out);
+ __ leaq(out, Address(value, value, TIMES_1, 0));
if (!ValueFitsSmi()) {
const Register temp = locs()->temp(0).reg();
Label done;
- __ j(NO_OVERFLOW, &done);
+ __ movq(temp, value);
+ __ sarq(temp, Immediate(30));
+ __ addq(temp, Immediate(1));
+ __ cmpq(temp, Immediate(2));
+ __ j(BELOW, &done);
+
BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), out,
temp);
__ movq(FieldAddress(out, Mint::value_offset()), value);
+
__ Bind(&done);
}
}
@@ -4303,8 +4439,9 @@
switch (op_kind()) {
case Token::kNEGATE: {
Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp);
+ __ cmpq(value, Immediate(-0x80000000ll));
+ __ j(EQUAL, deopt);
__ negq(value);
- __ j(OVERFLOW, deopt);
break;
}
case Token::kBIT_NOT:
@@ -4453,6 +4590,7 @@
void SmiToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
Register value = locs()->in(0).reg();
FpuRegister result = locs()->out(0).fpu_reg();
+ __ AssertSmiInRange(value);
__ SmiUntag(value);
__ cvtsi2sdq(result, value);
}
@@ -4482,14 +4620,15 @@
ASSERT(result != value_obj);
ASSERT(result != temp);
__ movsd(value_double, FieldAddress(value_obj, Double::value_offset()));
- __ cvttsd2siq(result, value_double);
+ __ cvttsd2sil(result, value_double);
// Overflow is signalled with minint.
Label do_call, done;
// Check for overflow and that it fits into Smi.
- __ movq(temp, result);
- __ shlq(temp, Immediate(1));
+ __ movl(temp, result);
+ __ shll(temp, Immediate(1));
__ j(OVERFLOW, &do_call, Assembler::kNearJump);
- __ SmiTag(result);
+ ASSERT(kSmiTagShift == 1 && kSmiTag == 0);
+ __ movsxd(result, temp);
__ jmp(&done);
__ Bind(&do_call);
__ pushq(value_obj);
@@ -4525,14 +4664,15 @@
XmmRegister value = locs()->in(0).fpu_reg();
Register temp = locs()->temp(0).reg();
- __ cvttsd2siq(result, value);
+ __ cvttsd2sil(result, value);
// Overflow is signalled with minint.
Label do_call, done;
// Check for overflow and that it fits into Smi.
- __ movq(temp, result);
- __ shlq(temp, Immediate(1));
+ __ movl(temp, result);
+ __ shll(temp, Immediate(1));
__ j(OVERFLOW, deopt);
- __ SmiTag(result);
+ ASSERT(kSmiTagShift == 1 && kSmiTag == 0);
+ __ movsxd(result, temp);
}
LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(Zone* zone,
@@ -4831,6 +4971,7 @@
// Both inputs must be writable because they will be untagged.
summary->set_in(0, Location::RegisterLocation(RAX));
summary->set_in(1, Location::WritableRegister());
+ // Output is a pair of registers.
summary->set_out(0, Location::Pair(Location::RegisterLocation(RAX),
Location::RegisterLocation(RDX)));
return summary;
@@ -4845,50 +4986,26 @@
PairLocation* pair = locs()->out(0).AsPairLocation();
Register result1 = pair->At(0).reg();
Register result2 = pair->At(1).reg();
- Label not_32bit, done;
- Register temp = RDX;
- ASSERT(left == RAX);
- ASSERT((right != RDX) && (right != RAX));
- ASSERT(result1 == RAX);
- ASSERT(result2 == RDX);
if (RangeUtils::CanBeZero(divisor_range())) {
// Handle divide by zero in runtime.
__ testq(right, right);
__ j(ZERO, deopt);
}
- // Check if both operands fit into 32bits as idiv with 64bit operands
- // requires twice as many cycles and has much higher latency.
- // We are checking this before untagging them to avoid corner case
- // dividing INT_MAX by -1 that raises exception because quotient is
- // too large for 32bit register.
- __ movsxd(temp, left);
- __ cmpq(temp, left);
- __ j(NOT_EQUAL, ¬_32bit);
- __ movsxd(temp, right);
- __ cmpq(temp, right);
- __ j(NOT_EQUAL, ¬_32bit);
-
+ ASSERT(left == RAX);
+ ASSERT((right != RDX) && (right != RAX));
+ ASSERT(result1 == RAX);
+ ASSERT(result2 == RDX);
// Both operands are 31bit smis. Divide using 32bit idiv.
__ SmiUntag(left);
__ SmiUntag(right);
__ cdq();
__ idivl(right);
- __ movsxd(RAX, RAX);
- __ movsxd(RDX, RDX);
- __ jmp(&done);
-
- // Divide using 64bit idiv.
- __ Bind(¬_32bit);
- __ SmiUntag(left);
- __ SmiUntag(right);
- __ cqo(); // Sign extend RAX -> RDX:RAX.
- __ idivq(right); // RAX: quotient, RDX: remainder.
// Check the corner case of dividing the 'MIN_SMI' with -1, in which
// case we cannot tag the result.
- __ CompareImmediate(RAX, Immediate(0x4000000000000000));
+ __ cmpl(RAX, Immediate(0x40000000));
__ j(EQUAL, deopt);
- __ Bind(&done);
-
+ __ movsxd(RAX, RAX);
+ __ movsxd(RDX, RDX);
// Modulo correction (RDX).
// res = left % right;
// if (res < 0) {
@@ -4898,16 +5015,16 @@
// res = res + right;
// }
// }
- Label all_done;
+ Label done;
__ cmpq(RDX, Immediate(0));
- __ j(GREATER_EQUAL, &all_done, Assembler::kNearJump);
+ __ j(GREATER_EQUAL, &done, Assembler::kNearJump);
// Result is negative, adjust it.
if ((divisor_range() == NULL) || divisor_range()->Overlaps(-1, 1)) {
Label subtract;
__ cmpq(right, Immediate(0));
__ j(LESS, &subtract, Assembler::kNearJump);
__ addq(RDX, right);
- __ jmp(&all_done, Assembler::kNearJump);
+ __ jmp(&done, Assembler::kNearJump);
__ Bind(&subtract);
__ subq(RDX, right);
} else if (divisor_range()->IsPositive()) {
@@ -4917,7 +5034,7 @@
// Right is negative.
__ subq(RDX, right);
}
- __ Bind(&all_done);
+ __ Bind(&done);
__ SmiTag(RAX);
__ SmiTag(RDX);
@@ -5259,6 +5376,7 @@
// Code for a variable shift amount.
// Deoptimize if shift count is > 63 or negative.
// Sarq and shlq instructions mask the count to 6 bits.
+ __ AssertSmiInRange(RCX);
__ SmiUntag(RCX);
if (!IsShiftCountInRange()) {
__ cmpq(RCX, Immediate(kMintShiftCountLimit));
@@ -5291,15 +5409,15 @@
}
CompileType BinaryUint32OpInstr::ComputeType() const {
- return CompileType::FromCid(kSmiCid);
+ return CompileType::Int();
}
CompileType ShiftUint32OpInstr::ComputeType() const {
- return CompileType::FromCid(kSmiCid);
+ return CompileType::Int();
}
CompileType UnaryUint32OpInstr::ComputeType() const {
- return CompileType::FromCid(kSmiCid);
+ return CompileType::Int();
}
LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Zone* zone,
@@ -5414,6 +5532,7 @@
Label zero;
// TODO(johnmccutchan): Use range information to avoid these checks.
+ __ AssertSmiInRange(shifter);
__ SmiUntag(shifter);
__ cmpq(shifter, Immediate(0));
// If shift value is < 0, deoptimize.
@@ -5438,7 +5557,7 @@
__ Bind(&zero);
// Shift was greater than 31 bits, just return zero.
- __ xorq(left, left);
+ __ xorl(left, left);
// Exit path.
__ Bind(&done);
@@ -5479,8 +5598,8 @@
const Register out = locs()->out(0).reg();
// Representations are bitwise equivalent but we want to normalize
// upperbits for safety reasons.
- // TODO(vegorov) if we ensure that we never use upperbits we could
- // avoid this.
+ // TODO(vegorov) if we ensure that we never leave garbage in the upper bits
+ // we could avoid this.
__ movl(out, value);
} else if (from() == kUnboxedUint32 && to() == kUnboxedInt32) {
// Representations are bitwise equivalent.
diff --git a/runtime/vm/compiler/backend/range_analysis_test.cc b/runtime/vm/compiler/backend/range_analysis_test.cc
index 081c7e8..175b42b 100644
--- a/runtime/vm/compiler/backend/range_analysis_test.cc
+++ b/runtime/vm/compiler/backend/range_analysis_test.cc
@@ -66,17 +66,10 @@
RangeBoundary::PositiveInfinity());
TEST_RANGE_OP(Range::Shl, -1, 1, 63, 63, RangeBoundary(kMinInt64),
RangeBoundary::PositiveInfinity());
- if (kBitsPerWord == 64) {
- TEST_RANGE_OP_SMI(Range::Shl, -1, 1, 62, 62, RangeBoundary(kSmiMin),
- RangeBoundary(kSmiMax));
- TEST_RANGE_OP_SMI(Range::Shl, -1, 1, 30, 30, RangeBoundary(-(1 << 30)),
- RangeBoundary(1 << 30));
- } else {
- TEST_RANGE_OP_SMI(Range::Shl, -1, 1, 30, 30, RangeBoundary(kSmiMin),
- RangeBoundary(kSmiMax));
- TEST_RANGE_OP_SMI(Range::Shl, -1, 1, 62, 62, RangeBoundary(kSmiMin),
- RangeBoundary(kSmiMax));
- }
+ TEST_RANGE_OP_SMI(Range::Shl, -1, 1, 30, 30, RangeBoundary(kSmiMin),
+ RangeBoundary(kSmiMax));
+ TEST_RANGE_OP_SMI(Range::Shl, -1, 1, 62, 62, RangeBoundary(kSmiMin),
+ RangeBoundary(kSmiMax));
TEST_RANGE_OP(Range::Shl, 0, 100, 0, 64, RangeBoundary(0),
RangeBoundary::PositiveInfinity());
TEST_RANGE_OP(Range::Shl, -100, 0, 0, 64, RangeBoundary::NegativeInfinity(),
diff --git a/runtime/vm/compiler/call_specializer.cc b/runtime/vm/compiler/call_specializer.cc
index 30e0407..faae4bd 100644
--- a/runtime/vm/compiler/call_specializer.cc
+++ b/runtime/vm/compiler/call_specializer.cc
@@ -1558,10 +1558,10 @@
}
void CallSpecializer::VisitLoadCodeUnits(LoadCodeUnitsInstr* instr) {
-// TODO(zerny): Use kUnboxedUint32 once it is fully supported/optimized.
-#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM)
+ // Note that on ARM64 the result can always be packed into a Smi, so this
+ // is never triggered.
+ // TODO(zerny): Use kUnboxedUint32 once it is fully supported/optimized.
if (!instr->can_pack_into_smi()) instr->set_representation(kUnboxedInt64);
-#endif
}
static bool CidTestResultsContains(const ZoneGrowableArray<intptr_t>& results,
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 6e9ffcbd..2776ee8 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -195,7 +195,7 @@
if (builder_->ReadTag() == kSomething) {
if (detect_function_literal_initializer &&
builder_->PeekTag() == kFunctionExpression) {
- AlternativeReadingScope alt(builder_->reader_);
+ AlternativeReadingScope alt(&builder_->reader_);
Tag tag = builder_->ReadTag();
ASSERT(tag == kFunctionExpression);
builder_->ReadPosition(); // read position.
@@ -422,10 +422,10 @@
case kClassIndex:
// Read class index.
for (intptr_t i = 0; i < procedure_count_; ++i) {
- builder_->reader_->ReadUInt32();
+ builder_->reader_.ReadUInt32();
}
- builder_->reader_->ReadUInt32();
- builder_->reader_->ReadUInt32();
+ builder_->reader_.ReadUInt32();
+ builder_->reader_.ReadUInt32();
if (++next_read_ == field) return;
case kEnd:
return;
@@ -510,15 +510,15 @@
case kLibraryIndex:
// Read library index.
for (intptr_t i = 0; i < class_count_; ++i) {
- builder_->reader_->ReadUInt32();
+ builder_->reader_.ReadUInt32();
}
- builder_->reader_->ReadUInt32();
- builder_->reader_->ReadUInt32();
+ builder_->reader_.ReadUInt32();
+ builder_->reader_.ReadUInt32();
for (intptr_t i = 0; i < procedure_count_; ++i) {
- builder_->reader_->ReadUInt32();
+ builder_->reader_.ReadUInt32();
}
- builder_->reader_->ReadUInt32();
- builder_->reader_->ReadUInt32();
+ builder_->reader_.ReadUInt32();
+ builder_->reader_.ReadUInt32();
if (++next_read_ == field) return;
case kEnd:
return;
@@ -693,7 +693,7 @@
return false;
}
- AlternativeReadingScope alt(builder_->reader_, &H.metadata_payloads(),
+ AlternativeReadingScope alt(&builder_->reader_, &H.metadata_payloads(),
md_offset - MetadataPayloadOffset);
*target_name = builder_->ReadCanonicalNameReference();
@@ -771,7 +771,7 @@
return false;
}
- AlternativeReadingScope alt(builder_->reader_, &H.metadata_payloads(),
+ AlternativeReadingScope alt(&builder_->reader_, &H.metadata_payloads(),
md_offset - MetadataPayloadOffset);
const int kDynamicUsesBit = 1 << 0;
@@ -801,7 +801,7 @@
return InferredTypeMetadata(kDynamicCid, true);
}
- AlternativeReadingScope alt(builder_->reader_, &H.metadata_payloads(),
+ AlternativeReadingScope alt(&builder_->reader_, &H.metadata_payloads(),
md_offset - MetadataPayloadOffset);
const NameIndex kernel_name = builder_->ReadCanonicalNameReference();
@@ -967,7 +967,7 @@
TypedData::Handle(Z, class_field.KernelData());
ASSERT(!kernel_data.IsNull());
intptr_t field_offset = class_field.kernel_offset();
- AlternativeReadingScope alt(builder_->reader_, &kernel_data,
+ AlternativeReadingScope alt(&builder_->reader_, &kernel_data,
field_offset);
FieldHelper field_helper(builder_);
field_helper.ReadUntilExcluding(FieldHelper::kInitializer);
@@ -1169,7 +1169,7 @@
TypedData& kernel_data = TypedData::Handle(Z, class_field.KernelData());
ASSERT(!kernel_data.IsNull());
intptr_t field_offset = class_field.kernel_offset();
- AlternativeReadingScope alt(builder_->reader_, &kernel_data,
+ AlternativeReadingScope alt(&builder_->reader_, &kernel_data,
field_offset);
FieldHelper field_helper(builder_);
field_helper.ReadUntilExcluding(FieldHelper::kInitializer);
@@ -1251,9 +1251,9 @@
function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kBody);
if (builder_->ReadTag() == kSomething) {
- PositionScope scope(builder_->reader_);
+ PositionScope scope(&builder_->reader_);
VisitStatement(); // Read body
- first_body_token_position_ = builder_->reader_->min_position();
+ first_body_token_position_ = builder_->reader_.min_position();
}
// Ensure that :await_jump_var, :await_ctx_var, :async_op and
@@ -1529,7 +1529,7 @@
return;
}
case kLet: {
- PositionScope scope(builder_->reader_);
+ PositionScope scope(&builder_->reader_);
intptr_t offset =
builder_->ReaderOffset() - 1; // -1 to include tag byte.
@@ -1538,8 +1538,8 @@
VisitVariableDeclaration(); // read variable declaration.
VisitExpression(); // read expression.
- ExitScope(builder_->reader_->min_position(),
- builder_->reader_->max_position());
+ ExitScope(builder_->reader_.min_position(),
+ builder_->reader_.max_position());
return;
}
case kBigIntLiteral:
@@ -1616,7 +1616,7 @@
VisitExpression(); // read expression.
return;
case kBlock: {
- PositionScope scope(builder_->reader_);
+ PositionScope scope(&builder_->reader_);
intptr_t offset =
builder_->ReaderOffset() - 1; // -1 to include tag byte.
@@ -1628,15 +1628,15 @@
VisitStatement(); // read ith statement.
}
- ExitScope(builder_->reader_->min_position(),
- builder_->reader_->max_position());
+ ExitScope(builder_->reader_.min_position(),
+ builder_->reader_.max_position());
return;
}
case kEmptyStatement:
return;
case kAssertBlock:
if (I->asserts()) {
- PositionScope scope(builder_->reader_);
+ PositionScope scope(&builder_->reader_);
intptr_t offset =
builder_->ReaderOffset() - 1; // -1 to include tag byte.
@@ -1648,8 +1648,8 @@
VisitStatement(); // read ith statement.
}
- ExitScope(builder_->reader_->min_position(),
- builder_->reader_->max_position());
+ ExitScope(builder_->reader_.min_position(),
+ builder_->reader_.max_position());
} else {
builder_->SkipStatementList();
}
@@ -1695,7 +1695,7 @@
--depth_.loop_;
return;
case kForStatement: {
- PositionScope scope(builder_->reader_);
+ PositionScope scope(&builder_->reader_);
intptr_t offset =
builder_->ReaderOffset() - 1; // -1 to include tag byte.
@@ -1720,13 +1720,13 @@
}
VisitStatement(); // read body.
- ExitScope(position, builder_->reader_->max_position());
+ ExitScope(position, builder_->reader_.max_position());
--depth_.loop_;
return;
}
case kForInStatement:
case kAsyncForInStatement: {
- PositionScope scope(builder_->reader_);
+ PositionScope scope(&builder_->reader_);
intptr_t start_offset =
builder_->ReaderOffset() - 1; // -1 to include tag byte.
@@ -1747,17 +1747,17 @@
EnterScope(start_offset);
{
- AlternativeReadingScope alt(builder_->reader_, offset);
+ AlternativeReadingScope alt(&builder_->reader_, offset);
VisitVariableDeclaration(); // read variable.
}
VisitStatement(); // read body.
if (!body_position.IsReal()) {
- body_position = builder_->reader_->min_position();
+ body_position = builder_->reader_.min_position();
}
// TODO(jensj): From kernel_binary.cc
// forinstmt->variable_->set_end_position(forinstmt->position_);
- ExitScope(body_position, builder_->reader_->max_position());
+ ExitScope(body_position, builder_->reader_.max_position());
--depth_.loop_;
--depth_.for_in_;
return;
@@ -1820,7 +1820,7 @@
intptr_t catch_count =
builder_->ReadListLength(); // read number of catches.
for (intptr_t i = 0; i < catch_count; ++i) {
- PositionScope scope(builder_->reader_);
+ PositionScope scope(&builder_->reader_);
intptr_t offset = builder_->ReaderOffset(); // Catch has no tag.
EnterScope(offset);
@@ -1837,8 +1837,8 @@
}
VisitStatement(); // read body.
- ExitScope(builder_->reader_->min_position(),
- builder_->reader_->max_position());
+ ExitScope(builder_->reader_.min_position(),
+ builder_->reader_.max_position());
}
--depth_.catch_;
return;
@@ -1918,7 +1918,7 @@
}
void StreamingScopeBuilder::VisitVariableDeclaration() {
- PositionScope scope(builder_->reader_);
+ PositionScope scope(&builder_->reader_);
intptr_t kernel_offset_no_tag = builder_->ReaderOffset();
VariableDeclarationHelper helper(builder_);
@@ -1939,7 +1939,7 @@
// Go to next token position so it ends *after* the last potentially
// debuggable position in the initializer.
- TokenPosition end_position = builder_->reader_->max_position();
+ TokenPosition end_position = builder_->reader_.max_position();
if (end_position.IsReal()) {
end_position.Next();
}
@@ -2100,7 +2100,7 @@
int num_type_params = 0;
{
- AlternativeReadingScope _(builder_->reader_);
+ AlternativeReadingScope _(&builder_->reader_);
num_type_params = builder_->ReadListLength();
}
// Adding this scope here informs the type translator the type parameters of
@@ -3823,7 +3823,7 @@
ASSERT(!kernel_data.IsNull());
// Temporarily go to the variable declaration, read the name.
- AlternativeReadingScope alt(reader_, &kernel_data, kernel_offset);
+ AlternativeReadingScope alt(&reader_, &kernel_data, kernel_offset);
VariableDeclarationHelper helper(this);
helper.ReadUntilIncluding(VariableDeclarationHelper::kNameIndex);
return helper.name_index_;
@@ -3934,7 +3934,7 @@
ZoneGrowableArray<const Instance*>* default_values =
new ZoneGrowableArray<const Instance*>(Z, optional_parameter_count);
- AlternativeReadingScope alt(reader_);
+ AlternativeReadingScope alt(&reader_);
FunctionNodeHelper function_node_helper(this);
function_node_helper.ReadUntilExcluding(
FunctionNodeHelper::kPositionalParameters);
@@ -4031,7 +4031,7 @@
// Start by getting the position of the constructors initializer.
intptr_t initializers_offset = -1;
{
- AlternativeReadingScope alt(reader_);
+ AlternativeReadingScope alt(&reader_);
SkipFunctionNode(); // read constructors function node.
initializers_offset = ReaderOffset();
}
@@ -4044,7 +4044,7 @@
// (i.e. has a single initializer being of type kRedirectingInitializer).
bool is_redirecting_constructor = false;
{
- AlternativeReadingScope alt(reader_, initializers_offset);
+ AlternativeReadingScope alt(&reader_, initializers_offset);
intptr_t list_length = ReadListLength(); // read initializers list length.
bool no_field_initializers = true;
for (intptr_t i = 0; i < list_length; ++i) {
@@ -4067,7 +4067,7 @@
TypedData& kernel_data = TypedData::Handle(Z, class_field.KernelData());
ASSERT(!kernel_data.IsNull());
intptr_t field_offset = class_field.kernel_offset();
- AlternativeReadingScope alt(reader_, &kernel_data, field_offset);
+ AlternativeReadingScope alt(&reader_, &kernel_data, field_offset);
FieldHelper field_helper(this);
field_helper.ReadUntilExcluding(FieldHelper::kInitializer);
Tag initializer_tag = ReadTag(); // read first part of initializer.
@@ -4088,7 +4088,7 @@
// A(this.x) : super(expr), y = (expr);
// }
{
- AlternativeReadingScope alt(reader_, initializers_offset);
+ AlternativeReadingScope alt(&reader_, initializers_offset);
intptr_t list_length = ReadListLength(); // read initializers list length.
for (intptr_t i = 0; i < list_length; ++i) {
Tag tag = ReadTag();
@@ -4308,7 +4308,7 @@
if (!target.NeedsArgumentTypeChecks(I)) {
// Tearoffs of static methods needs to perform arguments checks since
// static methods they forward to don't do it themselves.
- AlternativeReadingScope _(reader_);
+ AlternativeReadingScope _(&reader_);
body += BuildArgumentTypeChecks();
} else {
// Check if parent function was annotated with no-dynamic-invocations.
@@ -4318,7 +4318,7 @@
if (!attrs.has_dynamic_invocations) {
// If it was then we might need to build some checks in the
// tear-off.
- AlternativeReadingScope _(reader_);
+ AlternativeReadingScope _(&reader_);
body +=
BuildArgumentTypeChecks(kTypeChecksForNoDynamicInvocationsTearOff);
}
@@ -4426,7 +4426,7 @@
function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kTypeParameters);
if (function.NeedsArgumentTypeChecks(I)) {
- AlternativeReadingScope _(reader_);
+ AlternativeReadingScope _(&reader_);
body += BuildArgumentTypeChecks();
}
@@ -4885,7 +4885,7 @@
FunctionNodeHelper::kPositionalParameters);
intptr_t first_parameter_offset = -1;
{
- AlternativeReadingScope alt(reader_);
+ AlternativeReadingScope alt(&reader_);
intptr_t list_length = ReadListLength(); // read number of positionals.
if (list_length > 0) {
first_parameter_offset = ReaderOffset() + data_program_offset_;
@@ -4928,7 +4928,7 @@
// If we run in checked mode or strong mode, we have to check the type of the
// passed arguments.
if (dart_function.NeedsArgumentTypeChecks(I)) {
- AlternativeReadingScope _(reader_);
+ AlternativeReadingScope _(&reader_);
SetOffset(type_parameters_offset);
body += BuildArgumentTypeChecks();
}
@@ -5119,7 +5119,7 @@
switch (function.kind()) {
case RawFunction::kImplicitClosureFunction:
case RawFunction::kRegularFunction: {
- AlternativeReadingScope alt(reader_);
+ AlternativeReadingScope alt(&reader_);
ReadUntilFunctionNode(parsed_function()); // read until function node.
}
default: {}
@@ -5356,45 +5356,45 @@
}
intptr_t StreamingFlowGraphBuilder::ReaderOffset() {
- return reader_->offset();
+ return reader_.offset();
}
void StreamingFlowGraphBuilder::SetOffset(intptr_t offset) {
- reader_->set_offset(offset);
+ reader_.set_offset(offset);
}
void StreamingFlowGraphBuilder::SkipBytes(intptr_t bytes) {
- reader_->set_offset(ReaderOffset() + bytes);
+ reader_.set_offset(ReaderOffset() + bytes);
}
bool StreamingFlowGraphBuilder::ReadBool() {
- return reader_->ReadBool();
+ return reader_.ReadBool();
}
uint8_t StreamingFlowGraphBuilder::ReadByte() {
- return reader_->ReadByte();
+ return reader_.ReadByte();
}
uint32_t StreamingFlowGraphBuilder::ReadUInt() {
- return reader_->ReadUInt();
+ return reader_.ReadUInt();
}
uint32_t StreamingFlowGraphBuilder::ReadUInt32() {
- return reader_->ReadUInt32();
+ return reader_.ReadUInt32();
}
uint32_t StreamingFlowGraphBuilder::PeekUInt() {
- AlternativeReadingScope alt(reader_);
- return reader_->ReadUInt();
+ AlternativeReadingScope alt(&reader_);
+ return reader_.ReadUInt();
}
uint32_t StreamingFlowGraphBuilder::PeekListLength() {
- AlternativeReadingScope alt(reader_);
- return reader_->ReadListLength();
+ AlternativeReadingScope alt(&reader_);
+ return reader_.ReadListLength();
}
intptr_t StreamingFlowGraphBuilder::ReadListLength() {
- return reader_->ReadListLength();
+ return reader_.ReadListLength();
}
StringIndex StreamingFlowGraphBuilder::ReadStringReference() {
@@ -5402,7 +5402,7 @@
}
NameIndex StreamingFlowGraphBuilder::ReadCanonicalNameReference() {
- return reader_->ReadCanonicalNameReference();
+ return reader_.ReadCanonicalNameReference();
}
StringIndex StreamingFlowGraphBuilder::ReadNameAsStringIndex() {
@@ -6077,7 +6077,7 @@
}
TokenPosition StreamingFlowGraphBuilder::ReadPosition(bool record) {
- TokenPosition position = reader_->ReadPosition();
+ TokenPosition position = reader_.ReadPosition();
if (record) {
record_token_position(position);
}
@@ -6099,11 +6099,11 @@
}
Tag StreamingFlowGraphBuilder::ReadTag(uint8_t* payload) {
- return reader_->ReadTag(payload);
+ return reader_.ReadTag(payload);
}
Tag StreamingFlowGraphBuilder::PeekTag(uint8_t* payload) {
- return reader_->PeekTag(payload);
+ return reader_.PeekTag(payload);
}
void StreamingFlowGraphBuilder::loop_depth_inc() {
@@ -6209,7 +6209,7 @@
Tag StreamingFlowGraphBuilder::PeekArgumentsFirstPositionalTag() {
// read parts of arguments, then go back to before doing so.
- AlternativeReadingScope alt(reader_);
+ AlternativeReadingScope alt(&reader_);
ReadUInt(); // read number of arguments.
SkipListOfDartTypes(); // Read list of types.
@@ -6227,7 +6227,7 @@
const TypeArguments& StreamingFlowGraphBuilder::PeekArgumentsInstantiatedType(
const Class& klass) {
// read parts of arguments, then go back to before doing so.
- AlternativeReadingScope alt(reader_);
+ AlternativeReadingScope alt(&reader_);
ReadUInt(); // read argument count.
intptr_t list_length = ReadListLength(); // read types list length.
return T.BuildInstantiatedTypeArguments(klass, list_length); // read types.
@@ -6498,7 +6498,7 @@
intptr_t target_context_depth) {
// TranslateFinallyFinalizers can move the readers offset.
// Save the current position and restore it afterwards.
- AlternativeReadingScope alt(reader_);
+ AlternativeReadingScope alt(&reader_);
return flow_graph_builder_->TranslateFinallyFinalizers(outer_finally,
target_context_depth);
}
@@ -6649,7 +6649,7 @@
SkipListOfDartTypes(); // read list of types.
{
- AlternativeReadingScope _(reader_);
+ AlternativeReadingScope _(&reader_);
if (positional_count == NULL) positional_count = &dummy;
*positional_count = ReadListLength(); // read length of expression list
}
@@ -7322,7 +7322,7 @@
intptr_t type_args_len = 0;
LocalVariable* type_arguments_temp = NULL;
if (I->reify_generic_functions()) {
- AlternativeReadingScope alt(reader_);
+ AlternativeReadingScope alt(&reader_);
SkipExpression(); // skip receiver
SkipName(); // skip method name
ReadUInt(); // read argument count.
@@ -7465,7 +7465,7 @@
Fragment instructions;
intptr_t type_args_len = 0;
if (I->reify_generic_functions()) {
- AlternativeReadingScope alt(reader_);
+ AlternativeReadingScope alt(&reader_);
SkipExpression(); // skip receiver
ReadCanonicalNameReference(); // skip target reference
ReadUInt(); // read argument count.
@@ -7531,7 +7531,7 @@
intptr_t type_args_len = 0;
if (I->reify_generic_functions()) {
- AlternativeReadingScope alt(reader_);
+ AlternativeReadingScope alt(&reader_);
SkipName(); // skip method name
ReadUInt(); // read argument count.
type_args_len = ReadListLength(); // read types list length.
@@ -7546,7 +7546,7 @@
intptr_t argument_count;
Array& argument_names = Array::Handle(Z);
{
- AlternativeReadingScope alt(reader_);
+ AlternativeReadingScope alt(&reader_);
argument_count = ReadUInt();
SkipListOfDartTypes();
@@ -7635,7 +7635,7 @@
Fragment instructions;
if (I->reify_generic_functions()) {
- AlternativeReadingScope alt(reader_);
+ AlternativeReadingScope alt(&reader_);
ReadUInt(); // read argument count.
intptr_t list_length = ReadListLength(); // read types list length.
if (list_length > 0) {
@@ -7727,7 +7727,7 @@
instructions += TranslateInstantiatedTypeArguments(type_arguments);
instructions += PushArgument();
} else if (!special_case_identical && I->reify_generic_functions()) {
- AlternativeReadingScope alt(reader_);
+ AlternativeReadingScope alt(&reader_);
ReadUInt(); // read argument count.
intptr_t list_length = ReadListLength(); // read types list length.
if (list_length > 0) {
@@ -9710,7 +9710,7 @@
// Step a) Create array of [TypeParameter] objects (without bound).
type_parameters = TypeArguments::New(type_parameter_count);
{
- AlternativeReadingScope alt(reader_);
+ AlternativeReadingScope alt(&reader_);
for (intptr_t i = 0; i < type_parameter_count; i++) {
TypeParameterHelper helper(this);
helper.Finish();
@@ -9987,55 +9987,55 @@
}
intptr_t StreamingFlowGraphBuilder::SourceTableSize() {
- AlternativeReadingScope alt(reader_);
- intptr_t library_count = reader_->ReadFromIndexNoReset(
- reader_->size(), LibraryCountFieldCountFromEnd, 1, 0);
- intptr_t source_table_offset = reader_->ReadFromIndexNoReset(
- reader_->size(),
+ AlternativeReadingScope alt(&reader_);
+ intptr_t library_count = reader_.ReadFromIndexNoReset(
+ reader_.size(), LibraryCountFieldCountFromEnd, 1, 0);
+ intptr_t source_table_offset = reader_.ReadFromIndexNoReset(
+ reader_.size(),
LibraryCountFieldCountFromEnd + 1 + library_count + 1 +
SourceTableFieldCountFromFirstLibraryOffset,
1, 0);
SetOffset(source_table_offset); // read source table offset.
- return reader_->ReadUInt32(); // read source table size.
+ return reader_.ReadUInt32(); // read source table size.
}
intptr_t StreamingFlowGraphBuilder::GetOffsetForSourceInfo(intptr_t index) {
- AlternativeReadingScope alt(reader_);
- intptr_t library_count = reader_->ReadFromIndexNoReset(
- reader_->size(), LibraryCountFieldCountFromEnd, 1, 0);
- intptr_t source_table_offset = reader_->ReadFromIndexNoReset(
- reader_->size(),
+ AlternativeReadingScope alt(&reader_);
+ intptr_t library_count = reader_.ReadFromIndexNoReset(
+ reader_.size(), LibraryCountFieldCountFromEnd, 1, 0);
+ intptr_t source_table_offset = reader_.ReadFromIndexNoReset(
+ reader_.size(),
LibraryCountFieldCountFromEnd + 1 + library_count + 1 +
SourceTableFieldCountFromFirstLibraryOffset,
1, 0);
- intptr_t next_field_offset = reader_->ReadUInt32();
+ intptr_t next_field_offset = reader_.ReadUInt32();
SetOffset(source_table_offset);
- intptr_t size = reader_->ReadUInt32(); // read source table size.
+ intptr_t size = reader_.ReadUInt32(); // read source table size.
- return reader_->ReadFromIndexNoReset(next_field_offset, 0, size, index);
+ return reader_.ReadFromIndexNoReset(next_field_offset, 0, size, index);
}
String& StreamingFlowGraphBuilder::SourceTableUriFor(intptr_t index) {
- AlternativeReadingScope alt(reader_);
+ AlternativeReadingScope alt(&reader_);
SetOffset(GetOffsetForSourceInfo(index));
intptr_t size = ReadUInt(); // read uri List<byte> size.
- return H.DartString(reader_->CopyDataIntoZone(Z, ReaderOffset(), size), size,
+ return H.DartString(reader_.CopyDataIntoZone(Z, ReaderOffset(), size), size,
Heap::kOld);
}
String& StreamingFlowGraphBuilder::GetSourceFor(intptr_t index) {
- AlternativeReadingScope alt(reader_);
+ AlternativeReadingScope alt(&reader_);
SetOffset(GetOffsetForSourceInfo(index));
SkipBytes(ReadUInt()); // skip uri.
intptr_t size = ReadUInt(); // read source List<byte> size.
- return H.DartString(reader_->CopyDataIntoZone(Z, ReaderOffset(), size), size,
+ return H.DartString(reader_.CopyDataIntoZone(Z, ReaderOffset(), size), size,
Heap::kOld);
}
RawTypedData* StreamingFlowGraphBuilder::GetLineStartsFor(intptr_t index) {
// Line starts are delta encoded. So get the max delta first so that we
// can store them as tighly as possible.
- AlternativeReadingScope alt(reader_);
+ AlternativeReadingScope alt(&reader_);
SetOffset(GetOffsetForSourceInfo(index));
SkipBytes(ReadUInt()); // skip uri.
SkipBytes(ReadUInt()); // skip source.
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index 36c1833..6881cc6 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -1010,7 +1010,7 @@
: flow_graph_builder_(flow_graph_builder),
translation_helper_(flow_graph_builder->translation_helper_),
zone_(flow_graph_builder->zone_),
- reader_(new Reader(data)),
+ reader_(data),
script_(Script::Handle(zone_, parsed_function()->function().script())),
constant_evaluator_(this),
type_translator_(this, /* finalize= */ true),
@@ -1032,7 +1032,7 @@
: flow_graph_builder_(NULL),
translation_helper_(*translation_helper),
zone_(zone),
- reader_(new Reader(data_buffer, buffer_length)),
+ reader_(data_buffer, buffer_length),
script_(Script::Handle(zone_)),
constant_evaluator_(this),
type_translator_(this, /* finalize= */ true),
@@ -1054,7 +1054,7 @@
: flow_graph_builder_(NULL),
translation_helper_(*translation_helper),
zone_(zone),
- reader_(new Reader(data)),
+ reader_(data),
script_(script),
constant_evaluator_(this),
type_translator_(this, /* finalize= */ true),
@@ -1068,7 +1068,7 @@
procedure_attributes_metadata_helper_(this),
metadata_scanned_(false) {}
- ~StreamingFlowGraphBuilder() { delete reader_; }
+ ~StreamingFlowGraphBuilder() {}
FlowGraph* BuildGraph(intptr_t kernel_offset);
@@ -1174,7 +1174,7 @@
void record_yield_position(TokenPosition position);
Tag ReadTag(uint8_t* payload = NULL);
Tag PeekTag(uint8_t* payload = NULL);
- uint8_t ReadFlags() { return reader_->ReadFlags(); }
+ uint8_t ReadFlags() { return reader_.ReadFlags(); }
void loop_depth_inc();
void loop_depth_dec();
@@ -1436,7 +1436,7 @@
FlowGraphBuilder* flow_graph_builder_;
TranslationHelper& translation_helper_;
Zone* zone_;
- Reader* reader_;
+ Reader reader_;
const Script& script_;
StreamingConstantEvaluator constant_evaluator_;
StreamingDartTypeTranslator type_translator_;
diff --git a/runtime/vm/compiler/intrinsifier_arm64.cc b/runtime/vm/compiler/intrinsifier_arm64.cc
index 4da90f0..3625729 100644
--- a/runtime/vm/compiler/intrinsifier_arm64.cc
+++ b/runtime/vm/compiler/intrinsifier_arm64.cc
@@ -265,8 +265,9 @@
void Intrinsifier::Integer_addFromInteger(Assembler* assembler) {
Label fall_through;
TestBothArgumentsSmis(assembler, &fall_through); // Checks two smis.
- __ adds(R0, R0, Operand(R1)); // Adds.
+ __ addsw(R0, R0, Operand(R1)); // Adds.
__ b(&fall_through, VS); // Fall-through on overflow.
+ __ sxtw(R0, R0); // Sign extend - flags not affected.
__ ret();
__ Bind(&fall_through);
}
@@ -278,8 +279,9 @@
void Intrinsifier::Integer_subFromInteger(Assembler* assembler) {
Label fall_through;
TestBothArgumentsSmis(assembler, &fall_through);
- __ subs(R0, R0, Operand(R1)); // Subtract.
- __ b(&fall_through, VS); // Fall-through on overflow.
+ __ subsw(R0, R0, Operand(R1)); // Subtract.
+ __ b(&fall_through, VS); // Fall-through on overflow.
+ __ sxtw(R0, R0); // Sign extend - flags not affected.
__ ret();
__ Bind(&fall_through);
}
@@ -287,8 +289,9 @@
void Intrinsifier::Integer_sub(Assembler* assembler) {
Label fall_through;
TestBothArgumentsSmis(assembler, &fall_through);
- __ subs(R0, R1, Operand(R0)); // Subtract.
- __ b(&fall_through, VS); // Fall-through on overflow.
+ __ subsw(R0, R1, Operand(R0)); // Subtract.
+ __ b(&fall_through, VS); // Fall-through on overflow.
+ __ sxtw(R0, R0); // Sign extend - flags not affected.
__ ret();
__ Bind(&fall_through);
}
@@ -299,9 +302,9 @@
TestBothArgumentsSmis(assembler, &fall_through); // checks two smis
__ SmiUntag(R0); // Untags R6. We only want result shifted by one.
- __ mul(TMP, R0, R1);
- __ smulh(TMP2, R0, R1);
- // TMP: result bits 64..127.
+ __ smull(TMP, R0, R1);
+ __ AsrImmediate(TMP2, TMP, 31);
+ // TMP: result bits 31..63.
__ cmp(TMP2, Operand(TMP, ASR, 63));
__ b(&fall_through, NE);
__ mov(R0, TMP);
@@ -417,7 +420,7 @@
// Check the corner case of dividing the 'MIN_SMI' with -1, in which case we
// cannot tag the result.
- __ CompareImmediate(R0, 0x4000000000000000);
+ __ CompareImmediate(R0, 0x40000000);
__ b(&fall_through, EQ);
__ SmiTag(R0); // Not equal. Okay to tag and return.
__ ret(); // Return.
@@ -428,8 +431,9 @@
Label fall_through;
__ ldr(R0, Address(SP, +0 * kWordSize)); // Grab first argument.
__ BranchIfNotSmi(R0, &fall_through);
- __ negs(R0, R0);
+ __ negsw(R0, R0);
__ b(&fall_through, VS);
+ __ sxtw(R0, R0); // Sign extend - flags not affected.
__ ret();
__ Bind(&fall_through);
}
@@ -488,9 +492,9 @@
// Check if count too large for handling it inlined.
__ SmiUntag(TMP, right); // SmiUntag right into TMP.
// Overflow test (preserve left, right, and TMP);
- __ lslv(temp, left, TMP);
- __ asrv(TMP2, temp, TMP);
- __ CompareRegisters(left, TMP2);
+ __ lslvw(temp, left, TMP);
+ __ asrvw(TMP2, temp, TMP);
+ __ cmpw(left, Operand(TMP2));
__ b(&fall_through, NE); // Overflow.
// Shift for result now we know there is no overflow.
__ lslv(result, left, TMP);
@@ -563,6 +567,7 @@
__ CompareClassId(R0, kDoubleCid);
__ b(&fall_through, EQ);
+ __ AssertSmiInRange(R1);
__ LoadObject(R0, Bool::False()); // Smi == Mint -> false.
__ ret();
@@ -573,6 +578,7 @@
__ b(&fall_through, NE);
// Receiver is Mint, return false if right is Smi.
__ BranchIfNotSmi(R0, &fall_through);
+ __ AssertSmiInRange(R0);
__ LoadObject(R0, Bool::False());
__ ret();
// TODO(srdjan): Implement Mint == Mint comparison.
@@ -1495,11 +1501,12 @@
__ fcmpd(V0, V0);
__ b(&fall_through, VS);
- __ fcvtzds(R0, V0);
+ __ fcvtzdsx(R0, V0);
// Overflow is signaled with minint.
// Check for overflow and that it fits into Smi.
- __ CompareImmediate(R0, 0xC000000000000000);
- __ b(&fall_through, MI);
+ __ AsrImmediate(TMP, R0, 30);
+ __ cmp(TMP, Operand(R0, ASR, 63));
+ __ b(&fall_through, NE);
__ SmiTag(R0);
__ ret();
__ Bind(&fall_through);
@@ -1516,10 +1523,10 @@
__ fcmpd(V0, V0);
__ b(&double_hash, VS);
- // Convert double value to signed 64-bit int in R0 and back to a
+ // Convert double value to signed 32-bit int in R0 and back to a
// double value in V1.
- __ fcvtzds(R0, V0);
- __ scvtfdx(V1, R0);
+ __ fcvtzdsw(R0, V0);
+ __ scvtfdw(V1, R0);
// Tag the int as a Smi, making sure that it fits; this checks for
// overflow in the conversion from double to int. Conversion
@@ -1527,8 +1534,9 @@
// INT64_MAX or INT64_MIN (saturation).
Label fall_through;
ASSERT(kSmiTag == 0 && kSmiTagShift == 1);
- __ adds(R0, R0, Operand(R0));
+ __ addsw(R0, R0, Operand(R0));
__ b(&fall_through, VS);
+ __ sxtw(R0, R0); // Sign extend - flags not affected.
// Compare the two double values. If they are equal, we return the
// Smi tagged result immediately as the hash code.
diff --git a/runtime/vm/compiler/intrinsifier_x64.cc b/runtime/vm/compiler/intrinsifier_x64.cc
index 1e2574c..c8ddf76 100644
--- a/runtime/vm/compiler/intrinsifier_x64.cc
+++ b/runtime/vm/compiler/intrinsifier_x64.cc
@@ -269,8 +269,10 @@
Label fall_through;
TestBothArgumentsSmis(assembler, &fall_through);
// RAX contains right argument.
- __ addq(RAX, Address(RSP, +2 * kWordSize));
+ __ AssertSmiInRange(RAX);
+ __ addl(RAX, Address(RSP, +2 * kWordSize));
__ j(OVERFLOW, &fall_through, Assembler::kNearJump);
+ __ movsxd(RAX, RAX);
// Result is in RAX.
__ ret();
__ Bind(&fall_through);
@@ -284,8 +286,10 @@
Label fall_through;
TestBothArgumentsSmis(assembler, &fall_through);
// RAX contains right argument, which is the actual minuend of subtraction.
- __ subq(RAX, Address(RSP, +2 * kWordSize));
+ __ AssertSmiInRange(RAX);
+ __ subl(RAX, Address(RSP, +2 * kWordSize));
__ j(OVERFLOW, &fall_through, Assembler::kNearJump);
+ __ movsxd(RAX, RAX);
// Result is in RAX.
__ ret();
__ Bind(&fall_through);
@@ -295,10 +299,13 @@
Label fall_through;
TestBothArgumentsSmis(assembler, &fall_through);
// RAX contains right argument, which is the actual subtrahend of subtraction.
+ __ AssertSmiInRange(RAX);
__ movq(RCX, RAX);
__ movq(RAX, Address(RSP, +2 * kWordSize));
- __ subq(RAX, RCX);
+ __ AssertSmiInRange(RAX);
+ __ subl(RAX, RCX);
__ j(OVERFLOW, &fall_through, Assembler::kNearJump);
+ __ movsxd(RAX, RAX);
// Result is in RAX.
__ ret();
__ Bind(&fall_through);
@@ -308,10 +315,12 @@
Label fall_through;
TestBothArgumentsSmis(assembler, &fall_through);
// RAX is the right argument.
+ __ AssertSmiInRange(RAX);
ASSERT(kSmiTag == 0); // Adjust code below if not the case.
__ SmiUntag(RAX);
- __ imulq(RAX, Address(RSP, +2 * kWordSize));
+ __ imull(RAX, Address(RSP, +2 * kWordSize));
__ j(OVERFLOW, &fall_through, Assembler::kNearJump);
+ __ movsxd(RAX, RAX);
// Result is in RAX.
__ ret();
__ Bind(&fall_through);
@@ -333,7 +342,9 @@
// RAX: Untagged fallthrough result (remainder to be adjusted), or
// RAX: Tagged return result (remainder).
static void EmitRemainderOperation(Assembler* assembler) {
- Label return_zero, try_modulo, not_32bit, done;
+ Label return_zero, try_modulo, not_32bit;
+ __ AssertSmiInRange(RAX);
+ __ AssertSmiInRange(RCX);
// Check for quick zero results.
__ cmpq(RAX, Immediate(0));
__ j(EQUAL, &return_zero, Assembler::kNearJump);
@@ -355,33 +366,12 @@
__ Bind(&try_modulo);
- // Check if both operands fit into 32bits as idiv with 64bit operands
- // requires twice as many cycles and has much higher latency. We are checking
- // this before untagging them to avoid corner case dividing INT_MAX by -1 that
- // raises exception because quotient is too large for 32bit register.
- __ movsxd(RBX, RAX);
- __ cmpq(RBX, RAX);
- __ j(NOT_EQUAL, ¬_32bit, Assembler::kNearJump);
- __ movsxd(RBX, RCX);
- __ cmpq(RBX, RCX);
- __ j(NOT_EQUAL, ¬_32bit, Assembler::kNearJump);
-
// Both operands are 31bit smis. Divide using 32bit idiv.
__ SmiUntag(RAX);
__ SmiUntag(RCX);
__ cdq();
__ idivl(RCX);
__ movsxd(RAX, RDX);
- __ jmp(&done, Assembler::kNearJump);
-
- // Divide using 64bit idiv.
- __ Bind(¬_32bit);
- __ SmiUntag(RAX);
- __ SmiUntag(RCX);
- __ cqo();
- __ idivq(RCX);
- __ movq(RAX, RDX);
- __ Bind(&done);
}
// Implementation:
@@ -396,7 +386,9 @@
void Intrinsifier::Integer_moduloFromInteger(Assembler* assembler) {
Label fall_through, negative_result;
TestBothArgumentsSmis(assembler, &fall_through);
+ __ AssertSmiInRange(RAX);
__ movq(RCX, Address(RSP, +2 * kWordSize));
+ __ AssertSmiInRange(RCX);
// RAX: Tagged left (dividend).
// RCX: Tagged right (divisor).
__ cmpq(RCX, Immediate(0));
@@ -430,21 +422,17 @@
Label fall_through, not_32bit;
TestBothArgumentsSmis(assembler, &fall_through);
// RAX: right argument (divisor)
+ __ AssertSmiInRange(RAX);
__ cmpq(RAX, Immediate(0));
__ j(EQUAL, &fall_through, Assembler::kNearJump);
__ movq(RCX, RAX);
__ movq(RAX, Address(RSP, +2 * kWordSize)); // Left argument (dividend).
+ __ AssertSmiInRange(RAX);
- // Check if both operands fit into 32bits as idiv with 64bit operands
- // requires twice as many cycles and has much higher latency. We are checking
- // this before untagging them to avoid corner case dividing INT_MAX by -1 that
- // raises exception because quotient is too large for 32bit register.
- __ movsxd(RBX, RAX);
- __ cmpq(RBX, RAX);
- __ j(NOT_EQUAL, ¬_32bit);
- __ movsxd(RBX, RCX);
- __ cmpq(RBX, RCX);
- __ j(NOT_EQUAL, ¬_32bit);
+ // Check the corner case of dividing the 'MIN_SMI' with -1, in which case we
+ // cannot tag the result.
+ __ cmpq(RAX, Immediate(-0x80000000ll));
+ __ j(EQUAL, &fall_through);
// Both operands are 31bit smis. Divide using 32bit idiv.
__ SmiUntag(RAX);
@@ -454,21 +442,6 @@
__ movsxd(RAX, RAX);
__ SmiTag(RAX); // Result is guaranteed to fit into a smi.
__ ret();
-
- // Divide using 64bit idiv.
- __ Bind(¬_32bit);
- __ SmiUntag(RAX);
- __ SmiUntag(RCX);
- __ pushq(RDX); // Preserve RDX in case of 'fall_through'.
- __ cqo();
- __ idivq(RCX);
- __ popq(RDX);
- // Check the corner case of dividing the 'MIN_SMI' with -1, in which case we
- // cannot tag the result.
- __ cmpq(RAX, Immediate(0x4000000000000000));
- __ j(EQUAL, &fall_through);
- __ SmiTag(RAX);
- __ ret();
__ Bind(&fall_through);
}
@@ -477,8 +450,10 @@
__ movq(RAX, Address(RSP, +1 * kWordSize));
__ testq(RAX, Immediate(kSmiTagMask));
__ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi value.
+ __ AssertSmiInRange(RAX);
+ __ cmpq(RAX, Immediate(-0x80000000ll));
+ __ j(EQUAL, &fall_through, Assembler::kNearJump);
__ negq(RAX);
- __ j(OVERFLOW, &fall_through, Assembler::kNearJump);
// Result is in RAX.
__ ret();
__ Bind(&fall_through);
@@ -487,6 +462,7 @@
void Intrinsifier::Integer_bitAndFromInteger(Assembler* assembler) {
Label fall_through;
TestBothArgumentsSmis(assembler, &fall_through);
+ __ AssertSmiInRange(RAX);
// RAX is the right argument.
__ andq(RAX, Address(RSP, +2 * kWordSize));
// Result is in RAX.
@@ -502,6 +478,7 @@
Label fall_through;
TestBothArgumentsSmis(assembler, &fall_through);
// RAX is the right argument.
+ __ AssertSmiInRange(RAX);
__ orq(RAX, Address(RSP, +2 * kWordSize));
// Result is in RAX.
__ ret();
@@ -517,6 +494,7 @@
TestBothArgumentsSmis(assembler, &fall_through);
// RAX is the right argument.
__ xorq(RAX, Address(RSP, +2 * kWordSize));
+ __ AssertSmiInRange(RAX);
// Result is in RAX.
__ ret();
__ Bind(&fall_through);
@@ -532,28 +510,32 @@
Label fall_through, overflow;
TestBothArgumentsSmis(assembler, &fall_through);
// Shift value is in RAX. Compare with tagged Smi.
+ __ AssertSmiInRange(RAX);
__ cmpq(RAX, Immediate(Smi::RawValue(Smi::kBits)));
__ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump);
__ SmiUntag(RAX);
__ movq(RCX, RAX); // Shift amount must be in RCX.
__ movq(RAX, Address(RSP, +2 * kWordSize)); // Value.
+ __ AssertSmiInRange(RAX);
// Overflow test - all the shifted-out bits must be same as the sign bit.
__ movq(RDI, RAX);
- __ shlq(RAX, RCX);
- __ sarq(RAX, RCX);
+ __ shll(RAX, RCX);
+ __ sarl(RAX, RCX);
+ __ movsxd(RAX, RAX);
__ cmpq(RAX, RDI);
__ j(NOT_EQUAL, &overflow, Assembler::kNearJump);
- __ shlq(RAX, RCX); // Shift for result now we know there is no overflow.
+ __ shlq(RDI, RCX); // Shift for result now we know there is no overflow.
+ __ movq(RAX, RDI);
// RAX is a correctly tagged Smi.
__ ret();
__ Bind(&overflow);
- // Mint is rarely used on x64 (only for integers requiring 64 bit instead of
- // 63 bits as represented by Smi).
+ // Mint is used on x64 for integers requiring 64 bit instead of 31 bits as
+ // represented by Smi.
__ Bind(&fall_through);
}
@@ -561,6 +543,7 @@
Label fall_through, true_label;
TestBothArgumentsSmis(assembler, &fall_through);
// RAX contains the right argument.
+ __ AssertSmiInRange(RAX);
__ cmpq(Address(RSP, +2 * kWordSize), RAX);
__ j(true_condition, &true_label, Assembler::kNearJump);
__ LoadObject(RAX, Bool::False());
@@ -606,6 +589,9 @@
__ orq(RAX, RCX);
__ testq(RAX, Immediate(kSmiTagMask));
__ j(NOT_ZERO, &check_for_mint, Assembler::kNearJump);
+ // Or-ing them together should still leave them both as compressible smis.
+ __ AssertSmiInRange(RAX);
+ __ AssertSmiInRange(RCX);
// Both arguments are smi, '===' is good enough.
__ LoadObject(RAX, Bool::False());
__ ret();
@@ -623,9 +609,21 @@
// Left (receiver) is Smi, return false if right is not Double.
// Note that an instance of Mint or Bigint never contains a value that can be
// represented by Smi.
+ __ AssertSmiInRange(RAX);
__ movq(RAX, Address(RSP, +kArgumentOffset * kWordSize));
__ CompareClassId(RAX, kDoubleCid);
__ j(EQUAL, &fall_through);
+#if defined(DEBUG)
+ Label ok;
+ __ CompareClassId(RAX, kMintCid);
+ __ j(NOT_EQUAL, &ok);
+ __ movq(RAX, FieldAddress(RAX, Mint::value_offset()));
+ __ sarq(RCX, Immediate(1));
+ __ cmpq(RAX, RCX);
+ __ j(NOT_EQUAL, &ok);
+ __ Stop("Smi wrapped in a Mint");
+ __ Bind(&ok);
+#endif
__ LoadObject(RAX, Bool::False());
__ ret();
@@ -637,6 +635,7 @@
__ movq(RAX, Address(RSP, +kArgumentOffset * kWordSize));
__ testq(RAX, Immediate(kSmiTagMask));
__ j(NOT_ZERO, &fall_through);
+ __ AssertSmiInRange(RAX);
// Smi == Mint -> false.
__ LoadObject(RAX, Bool::False());
__ ret();
@@ -666,6 +665,7 @@
__ Bind(&shift_count_ok);
__ movq(RCX, RAX); // Shift amount must be in RCX.
__ movq(RAX, Address(RSP, +2 * kWordSize)); // Value.
+ __ AssertSmiInRange(RAX);
__ SmiUntag(RAX); // Value.
__ sarq(RAX, RCX);
__ SmiTag(RAX);
@@ -676,6 +676,7 @@
// Argument is Smi (receiver).
void Intrinsifier::Smi_bitNegate(Assembler* assembler) {
__ movq(RAX, Address(RSP, +1 * kWordSize)); // Index.
+ __ AssertSmiInRange(RAX);
__ notq(RAX);
__ andq(RAX, Immediate(~kSmiTagMask)); // Remove inverted smi-tag.
__ ret();
@@ -684,6 +685,7 @@
void Intrinsifier::Smi_bitLength(Assembler* assembler) {
ASSERT(kSmiTagShift == 1);
__ movq(RAX, Address(RSP, +1 * kWordSize)); // Index.
+ __ AssertSmiInRange(RAX);
// XOR with sign bit to complement bits if value is negative.
__ movq(RCX, RAX);
__ sarq(RCX, Immediate(63)); // All 0 or all 1.
@@ -709,6 +711,7 @@
__ subq(R8, Immediate(2)); // x_used > 0, Smi. R8 = x_used - 1, round up.
__ sarq(R8, Immediate(2)); // R8 + 1 = number of digit pairs to read.
__ movq(RCX, Address(RSP, 2 * kWordSize)); // n is Smi
+ __ AssertSmiInRange(RCX);
__ SmiUntag(RCX);
__ movq(RBX, Address(RSP, 1 * kWordSize)); // r_digits
__ movq(RSI, RCX);
@@ -744,6 +747,7 @@
__ movq(RDI, Address(RSP, 4 * kWordSize)); // x_digits
__ movq(RCX, Address(RSP, 2 * kWordSize)); // n is Smi
+ __ AssertSmiInRange(RCX);
__ SmiUntag(RCX);
__ movq(RBX, Address(RSP, 1 * kWordSize)); // r_digits
__ movq(RDX, RCX);
@@ -1231,6 +1235,7 @@
__ LoadObject(RAX, Bool::True());
__ ret();
__ Bind(&is_smi);
+ __ AssertSmiInRange(RAX);
__ SmiUntag(RAX);
__ cvtsi2sdq(XMM1, RAX);
__ jmp(&double_op);
@@ -1291,6 +1296,7 @@
__ movsd(FieldAddress(RAX, Double::value_offset()), XMM0);
__ ret();
__ Bind(&is_smi);
+ __ AssertSmiInRange(RAX);
__ SmiUntag(RAX);
__ cvtsi2sdq(XMM1, RAX);
__ jmp(&double_op);
@@ -1320,6 +1326,7 @@
__ testq(RAX, Immediate(kSmiTagMask));
__ j(NOT_ZERO, &fall_through);
// Is Smi.
+ __ AssertSmiInRange(RAX);
__ SmiUntag(RAX);
__ cvtsi2sdq(XMM1, RAX);
__ movq(RAX, Address(RSP, +2 * kWordSize));
@@ -1342,6 +1349,7 @@
__ testq(RAX, Immediate(kSmiTagMask));
__ j(NOT_ZERO, &fall_through);
// Is Smi.
+ __ AssertSmiInRange(RAX);
__ SmiUntag(RAX);
__ cvtsi2sdq(XMM0, RAX);
const Class& double_class =
@@ -1412,14 +1420,15 @@
void Intrinsifier::DoubleToInteger(Assembler* assembler) {
__ movq(RAX, Address(RSP, +1 * kWordSize));
__ movsd(XMM0, FieldAddress(RAX, Double::value_offset()));
- __ cvttsd2siq(RAX, XMM0);
+ __ cvttsd2sil(RAX, XMM0);
// Overflow is signalled with minint.
Label fall_through;
// Check for overflow and that it fits into Smi.
__ movq(RCX, RAX);
- __ shlq(RCX, Immediate(1));
+ __ shll(RCX, Immediate(1));
__ j(OVERFLOW, &fall_through, Assembler::kNearJump);
- __ SmiTag(RAX);
+ ASSERT(kSmiTagShift == 1 && kSmiTag == 0);
+ __ movsxd(RAX, RCX);
__ ret();
__ Bind(&fall_through);
}
@@ -1431,16 +1440,17 @@
// back to a double in XMM1.
__ movq(RCX, Address(RSP, +1 * kWordSize));
__ movsd(XMM0, FieldAddress(RCX, Double::value_offset()));
- __ cvttsd2siq(RAX, XMM0);
- __ cvtsi2sdq(XMM1, RAX);
+ __ cvttsd2sil(RAX, XMM0);
+ __ cvtsi2sdl(XMM1, RAX);
// Tag the int as a Smi, making sure that it fits; this checks for
// overflow and NaN in the conversion from double to int. Conversion
- // overflow from cvttsd2si is signalled with an INT64_MIN value.
+ // overflow from cvttsd2sil is signalled with an INT32_MIN value.
Label fall_through;
ASSERT(kSmiTag == 0 && kSmiTagShift == 1);
- __ addq(RAX, RAX);
+ __ addl(RAX, RAX);
__ j(OVERFLOW, &fall_through, Assembler::kNearJump);
+ __ movsxd(RAX, RAX);
// Compare the two double values. If they are equal, we return the
// Smi tagged result immediately as the hash code.
@@ -1478,6 +1488,7 @@
__ movsd(FieldAddress(RAX, Double::value_offset()), XMM0);
__ ret();
__ Bind(&is_smi);
+ __ AssertSmiInRange(RAX);
__ SmiUntag(RAX);
__ cvtsi2sdq(XMM1, RAX);
__ jmp(&double_op);
diff --git a/runtime/vm/constants_arm64.h b/runtime/vm/constants_arm64.h
index 829e3d9..a34d996 100644
--- a/runtime/vm/constants_arm64.h
+++ b/runtime/vm/constants_arm64.h
@@ -707,14 +707,14 @@
enum Extend {
kNoExtend = -1,
- UXTB = 0,
- UXTH = 1,
- UXTW = 2,
- UXTX = 3,
- SXTB = 4,
- SXTH = 5,
- SXTW = 6,
- SXTX = 7,
+ UXTB = 0, // Zero extend byte.
+ UXTH = 1, // Zero extend halfword (16 bits).
+ UXTW = 2, // Zero extend word (32 bits).
+ UXTX = 3, // Zero extend doubleword (64 bits).
+ SXTB = 4, // Sign extend byte.
+ SXTH = 5, // Sign extend halfword (16 bits).
+ SXTW = 6, // Sign extend word (32 bits).
+ SXTX = 7, // Sign extend doubleword (64 bits).
kMaxExtend = 8,
};
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index b7a56b9..eff8af8 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -1586,16 +1586,6 @@
return false;
}
-DART_EXPORT void Dart_InterruptIsolate(Dart_Isolate isolate) {
- if (isolate == NULL) {
- FATAL1("%s expects argument 'isolate' to be non-null.", CURRENT_FUNC);
- }
- // TODO(16615): Validate isolate parameter.
- TransitionNativeToVM transition(Thread::Current());
- Isolate* iso = reinterpret_cast<Isolate*>(isolate);
- iso->SendInternalLibMessage(Isolate::kInterruptMsg, iso->pause_capability());
-}
-
DART_EXPORT bool Dart_IsolateMakeRunnable(Dart_Isolate isolate) {
CHECK_NO_ISOLATE(Isolate::Current());
API_TIMELINE_DURATION(Thread::Current());
@@ -1693,21 +1683,6 @@
return Api::Success();
}
-DART_EXPORT Dart_Handle Dart_HandleMessages() {
- Thread* T = Thread::Current();
- Isolate* I = T->isolate();
- CHECK_API_SCOPE(T);
- CHECK_CALLBACK_STATE(T);
- API_TIMELINE_BEGIN_END_BASIC(T);
- TransitionNativeToVM transition(T);
- if (I->message_handler()->HandleAllMessages() != MessageHandler::kOK) {
- Dart_Handle error = Api::NewHandle(T, T->sticky_error());
- T->clear_sticky_error();
- return error;
- }
- return Api::Success();
-}
-
DART_EXPORT Dart_Handle Dart_WaitForEvent(int64_t timeout_millis) {
Thread* T = Thread::Current();
Isolate* I = T->isolate();
diff --git a/runtime/vm/globals.h b/runtime/vm/globals.h
index 4fa43f2..c15516d 100644
--- a/runtime/vm/globals.h
+++ b/runtime/vm/globals.h
@@ -21,9 +21,8 @@
#undef OVERFLOW // From math.h conflicts in constants_ia32.h
namespace dart {
-// Smi value range is from -(2^N) to (2^N)-1.
-// N=30 (32-bit build) or N=62 (64-bit build).
-const intptr_t kSmiBits = kBitsPerWord - 2;
+// Smi value range is from -(2^N) to (2^N)-1. N=30
+const intptr_t kSmiBits = 30;
const intptr_t kSmiMax = (static_cast<intptr_t>(1) << kSmiBits) - 1;
const intptr_t kSmiMin = -(static_cast<intptr_t>(1) << kSmiBits);
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 1c45698..4fe67e6 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -956,6 +956,11 @@
#undef REUSABLE_HANDLE_INITIALIZERS
Isolate::~Isolate() {
+#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
+ // TODO(32796): Re-enable assertion.
+ // RELEASE_ASSERT(reload_context_ == NULL);
+#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
+
delete background_compiler_;
background_compiler_ = NULL;
diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc
index cd42d41..de94a29 100644
--- a/runtime/vm/isolate_reload.cc
+++ b/runtime/vm/isolate_reload.cc
@@ -463,6 +463,7 @@
}
IsolateReloadContext::~IsolateReloadContext() {
+ ASSERT(zone_ == Thread::Current()->zone());
ASSERT(saved_class_table_ == NULL);
}
@@ -605,6 +606,7 @@
if (retval.status != Dart_KernelCompilationStatus_Ok) {
TIR_Print("---- LOAD FAILED, ABORTING RELOAD\n");
const String& error_str = String::Handle(String::New(retval.error));
+ free(retval.error);
const ApiError& error = ApiError::Handle(ApiError::New(error_str));
AddReasonForCancelling(new Aborted(zone_, error));
ReportReasonsForCancelling();
@@ -1356,10 +1358,7 @@
// used for morphing. It is therefore important that morphing takes
// place prior to any heap walking.
// So please keep this code at the top of Commit().
- if (HasInstanceMorphers()) {
- // Perform shape shifting of instances if necessary.
- MorphInstances();
- } else {
+ if (!MorphInstances()) {
free(saved_class_table_);
saved_class_table_ = NULL;
}
@@ -1586,9 +1585,12 @@
intptr_t count_;
};
-void IsolateReloadContext::MorphInstances() {
+bool IsolateReloadContext::MorphInstances() {
TIMELINE_SCOPE(MorphInstances);
- ASSERT(HasInstanceMorphers());
+ if (!HasInstanceMorphers()) {
+ return false;
+ }
+
if (FLAG_trace_reload) {
LogBlock blocker;
TIR_Print("MorphInstance: \n");
@@ -1606,7 +1608,9 @@
// Return if no objects are located.
intptr_t count = locator.count();
- if (count == 0) return;
+ if (count == 0) {
+ return false;
+ }
TIR_Print("Found %" Pd " object%s subject to morphing.\n", count,
(count > 1) ? "s" : "");
@@ -1640,6 +1644,7 @@
free(saved_class_table_);
saved_class_table_ = NULL;
Become::ElementsForwardIdentity(before, after);
+ return true;
}
void IsolateReloadContext::RunNewFieldInitializers() {
diff --git a/runtime/vm/isolate_reload.h b/runtime/vm/isolate_reload.h
index 107e081..715802e 100644
--- a/runtime/vm/isolate_reload.h
+++ b/runtime/vm/isolate_reload.h
@@ -239,8 +239,9 @@
void CheckpointLibraries();
- // Transforms the heap based on instance_morphers_.
- void MorphInstances();
+ // Transforms the heap based on instance_morphers_. Return whether there was
+ // any morphing.
+ bool MorphInstances();
void RunNewFieldInitializers();
diff --git a/runtime/vm/isolate_reload_test.cc b/runtime/vm/isolate_reload_test.cc
index 08abecb5..f65c9e4 100644
--- a/runtime/vm/isolate_reload_test.cc
+++ b/runtime/vm/isolate_reload_test.cc
@@ -741,7 +741,7 @@
" return identical(oldType, newType).toString();\n"
"}\n";
- TestCase::SetReloadTestScript(kReloadScript);
+ EXPECT_VALID(TestCase::SetReloadTestScript(kReloadScript));
EXPECT_STREQ("true", SimpleInvokeStr(lib, "main"));
}
@@ -772,7 +772,7 @@
" return identical(oldType, newType).toString();\n"
"}\n";
- TestCase::SetReloadTestScript(kReloadScript);
+ EXPECT_VALID(TestCase::SetReloadTestScript(kReloadScript));
EXPECT_STREQ("true", SimpleInvokeStr(lib, "main"));
}
@@ -805,7 +805,7 @@
" return (oldType == newType).toString();\n"
"}\n";
- TestCase::SetReloadTestScript(kReloadScript);
+ EXPECT_VALID(TestCase::SetReloadTestScript(kReloadScript));
EXPECT_STREQ("true", SimpleInvokeStr(lib, "main"));
}
@@ -965,11 +965,11 @@
" return bar();\n"
"}\n";
- TestCase::SetReloadTestScript(kReloadScript);
+ EXPECT_VALID(TestCase::SetReloadTestScript(kReloadScript));
EXPECT_EQ(107, SimpleInvoke(lib, "main"));
- lib = TestCase::GetReloadLibrary();
+ lib = Dart_RootLibrary();
EXPECT_NON_NULL(lib);
EXPECT_EQ(105, SimpleInvoke(lib, "main"));
}
@@ -1110,7 +1110,7 @@
EXPECT_VALID(lib);
// Identity reload.
- TestCase::SetReloadTestScript(kScript);
+ EXPECT_VALID(TestCase::SetReloadTestScript(kScript));
EXPECT_EQ(8, SimpleInvoke(lib, "main"));
}
@@ -1208,11 +1208,11 @@
" return new C().test();\n"
"}\n";
- TestCase::SetReloadTestScript(kReloadScript);
+ EXPECT_VALID(TestCase::SetReloadTestScript(kReloadScript));
EXPECT_STREQ("instance", SimpleInvokeStr(lib, "main"));
- lib = TestCase::GetReloadLibrary();
+ lib = Dart_RootLibrary();
EXPECT_NON_NULL(lib);
EXPECT_STREQ("instance", SimpleInvokeStr(lib, "main"));
}
@@ -1247,11 +1247,11 @@
" return new C().test();\n"
"}\n";
- TestCase::SetReloadTestScript(kReloadScript);
+ EXPECT_VALID(TestCase::SetReloadTestScript(kReloadScript));
EXPECT_STREQ("static", SimpleInvokeStr(lib, "main"));
- lib = TestCase::GetReloadLibrary();
+ lib = Dart_RootLibrary();
EXPECT_NON_NULL(lib);
EXPECT_STREQ("static", SimpleInvokeStr(lib, "main"));
}
@@ -1296,11 +1296,11 @@
" }\n"
"}\n";
- TestCase::SetReloadTestScript(kReloadScript);
+ EXPECT_VALID(TestCase::SetReloadTestScript(kReloadScript));
EXPECT_STREQ("okay", SimpleInvokeStr(lib, "main"));
- lib = TestCase::GetReloadLibrary();
+ lib = Dart_RootLibrary();
EXPECT_NON_NULL(lib);
EXPECT_STREQ("okay", SimpleInvokeStr(lib, "main"));
}
@@ -1345,11 +1345,11 @@
" }\n"
"}\n";
- TestCase::SetReloadTestScript(kReloadScript);
+ EXPECT_VALID(TestCase::SetReloadTestScript(kReloadScript));
EXPECT_STREQ("exception", SimpleInvokeStr(lib, "main"));
- lib = TestCase::GetReloadLibrary();
+ lib = Dart_RootLibrary();
EXPECT_NON_NULL(lib);
EXPECT_STREQ("exception", SimpleInvokeStr(lib, "main"));
}
@@ -1391,11 +1391,11 @@
" }\n"
"}\n";
- TestCase::SetReloadTestScript(kReloadScript);
+ EXPECT_VALID(TestCase::SetReloadTestScript(kReloadScript));
EXPECT_STREQ("exception", SimpleInvokeStr(lib, "main"));
- lib = TestCase::GetReloadLibrary();
+ lib = Dart_RootLibrary();
EXPECT_NON_NULL(lib);
EXPECT_STREQ("exception", SimpleInvokeStr(lib, "main"));
}
@@ -1437,11 +1437,11 @@
" }\n"
"}\n";
- TestCase::SetReloadTestScript(kReloadScript);
+ EXPECT_VALID(TestCase::SetReloadTestScript(kReloadScript));
EXPECT_STREQ("static", SimpleInvokeStr(lib, "main"));
- lib = TestCase::GetReloadLibrary();
+ lib = Dart_RootLibrary();
EXPECT_NON_NULL(lib);
EXPECT_STREQ("static", SimpleInvokeStr(lib, "main"));
}
@@ -1484,7 +1484,7 @@
" return new C().test();\n"
"}\n";
- TestCase::SetReloadTestScript(kReloadScript);
+ EXPECT_VALID(TestCase::SetReloadTestScript(kReloadScript));
EXPECT_EQ(11, SimpleInvoke(lib, "main"));
}
@@ -1519,11 +1519,11 @@
" return '${f1()} ${f2()} ${f1 == f2} ${identical(f1, f2)}';\n"
"}\n";
- TestCase::SetReloadTestScript(kReloadScript);
+ EXPECT_VALID(TestCase::SetReloadTestScript(kReloadScript));
EXPECT_STREQ("new new true false", SimpleInvokeStr(lib, "main"));
- lib = TestCase::GetReloadLibrary();
+ lib = Dart_RootLibrary();
EXPECT_NON_NULL(lib);
}
@@ -1554,11 +1554,15 @@
"}\n";
TestCase::SetReloadTestScript(kReloadScript);
-
Dart_Handle error_handle = SimpleInvokeError(lib, "main");
const char* error;
- if (TestCase::UsingDartFrontend()) {
+ if (TestCase::UsingStrongMode()) {
+ error =
+ "file:///test-lib:8:12: Error: Too few positional"
+ " arguments to function: 1 required, 0 given.\n"
+ " return f1();";
+ } else if (TestCase::UsingDartFrontend()) {
error =
"NoSuchMethodError: Closure call with mismatched arguments: function "
"'C.foo'\n"
@@ -1617,9 +1621,10 @@
"NoSuchMethodError: No static method 'foo' declared in class 'C'.",
SimpleInvokeStr(lib, "main"));
- lib = TestCase::GetReloadLibrary();
+ lib = Dart_RootLibrary();
EXPECT_NON_NULL(lib);
}
+
TEST_CASE(IsolateReload_TearOff_Class_Identity) {
const char* kScript =
"import 'file:///test:isolate_reload_helper';\n"
@@ -1650,11 +1655,11 @@
" return '${f1()} ${f2()} ${f1 == f2} ${identical(f1, f2)}';\n"
"}\n";
- TestCase::SetReloadTestScript(kReloadScript);
+ EXPECT_VALID(TestCase::SetReloadTestScript(kReloadScript));
EXPECT_STREQ("new new true true", SimpleInvokeStr(lib, "main"));
- lib = TestCase::GetReloadLibrary();
+ lib = Dart_RootLibrary();
EXPECT_NON_NULL(lib);
}
@@ -1684,11 +1689,11 @@
" return '${f1()} ${f2()} ${f1 == f2} ${identical(f1, f2)}';\n"
"}\n";
- TestCase::SetReloadTestScript(kReloadScript);
+ EXPECT_VALID(TestCase::SetReloadTestScript(kReloadScript));
EXPECT_STREQ("new new true true", SimpleInvokeStr(lib, "main"));
- lib = TestCase::GetReloadLibrary();
+ lib = Dart_RootLibrary();
EXPECT_NON_NULL(lib);
}
@@ -1746,147 +1751,15 @@
" '${set.remove(c.foo)}';\n"
"}\n";
- TestCase::SetReloadTestScript(kReloadScript);
+ EXPECT_VALID(TestCase::SetReloadTestScript(kReloadScript));
EXPECT_STREQ("new new true true true new true true true",
SimpleInvokeStr(lib, "main"));
- lib = TestCase::GetReloadLibrary();
+ lib = Dart_RootLibrary();
EXPECT_NON_NULL(lib);
}
-// TODO(bkonyi): This test has been modified since it was written and no longer
-// tests functionality that it did originally. It needs to be either re-written
-// or removed.
-TEST_CASE(IsolateReload_DanglingGetter_Instance) {
- const char* kScript =
- "import 'file:///test:isolate_reload_helper';\n"
- "class C {\n"
- " var x = 3;\n"
- " var y = 4;\n"
- "}\n"
- "invoke(f) {\n"
- " try {\n"
- " return f();\n"
- " } catch (e) {\n"
- " return e.toString().split('\\n').first;\n"
- " }\n"
- "}\n"
- "main() {\n"
- " var c = new C();\n"
- " var f = c.y;\n"
- " var r1 = invoke(f);\n"
- " reloadTest();\n"
- " var r2 = invoke(f);\n"
- " return '$r1 $r2';\n"
- "}\n";
-
- Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
- EXPECT_VALID(lib);
-
- const char* kReloadScript =
- "import 'file:///test:isolate_reload_helper';\n"
- "class C {\n"
- " var x = 3;\n"
- "}\n"
- "invoke(f) {\n"
- " try {\n"
- " return f();\n"
- " } catch (e) {\n"
- " return e.toString().split('\\n').first;\n"
- " }\n"
- "}\n"
- "main() {\n"
- " var c = new C();\n"
- " var f = c.y;\n"
- " var r1 = invoke(f);\n"
- " reloadTest();\n"
- " var r2 = invoke(f);\n"
- " return '$r1 $r2';\n"
- "}\n";
-
- TestCase::SetReloadTestScript(kReloadScript);
-
- EXPECT_STREQ(
- "NoSuchMethodError: Class 'int' has no instance method 'call'. "
- "NoSuchMethodError: Class 'int' has no instance method 'call'.",
- SimpleInvokeStr(lib, "main"));
-
- lib = TestCase::GetReloadLibrary();
- if (TestCase::UsingDartFrontend() && TestCase::UsingStrongMode()) {
- EXPECT_NULL(lib);
- } else {
- EXPECT_NON_NULL(lib);
- }
-}
-
-// TODO(bkonyi): This test has been modified since it was written and no longer
-// tests functionality that it did originally. It needs to be either re-written
-// or removed.
-TEST_CASE(IsolateReload_DanglingGetter_Class) {
- const char* kScript =
- "import 'file:///test:isolate_reload_helper';\n"
- "class C {\n"
- " static var x;\n"
- " static var y;\n"
- "}\n"
- "invoke(f) {\n"
- " try {\n"
- " return f();\n"
- " } catch (e) {\n"
- " return e.toString().split('\\n').first;\n"
- " }\n"
- "}\n"
- "main() {\n"
- " C.x = 3;\n"
- " C.y = 4;\n"
- " var f = C.y;\n"
- " var r1 = invoke(f);\n"
- " reloadTest();\n"
- " var r2 = invoke(f);\n"
- " return '$r1 $r2';\n"
- "}\n";
-
- Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
- EXPECT_VALID(lib);
-
- const char* kReloadScript =
- "import 'file:///test:isolate_reload_helper';\n"
- "class C {\n"
- " static var x;\n"
- "}\n"
- "invoke(f) {\n"
- " try {\n"
- " return f();\n"
- " } catch (e) {\n"
- " return e.toString().split('\\n').first;\n"
- " }\n"
- "}\n"
- "main() {\n"
- " C.x = 3;\n"
- " C.y = 4;\n"
- " var f = C.y;\n"
- " var r1 = invoke(f);\n"
- " reloadTest();\n"
- " var r2 = invoke(f);\n"
- " return '$r1 $r2';\n"
- "}\n";
-
- TestCase::SetReloadTestScript(kReloadScript);
-
- EXPECT_STREQ(
- "NoSuchMethodError: Class 'int' has no instance method 'call'. "
- "NoSuchMethodError: Class 'int' has no instance method 'call'.",
- SimpleInvokeStr(lib, "main"));
-
- lib = TestCase::GetReloadLibrary();
- if (TestCase::UsingDartFrontend() && TestCase::UsingStrongMode()) {
- EXPECT_NULL(lib);
- } else {
- EXPECT_NON_NULL(lib);
- }
-}
-
TEST_CASE(IsolateReload_TearOff_AddArguments) {
const char* kScript =
"import 'file:///test:isolate_reload_helper';\n"
@@ -1933,14 +1806,14 @@
" return '$r1 $r2';\n"
"}\n";
- TestCase::SetReloadTestScript(kReloadScript);
+ EXPECT_VALID(TestCase::SetReloadTestScript(kReloadScript));
EXPECT_STREQ(
"1 NoSuchMethodError: Class 'C' has no instance method "
"'foo' with matching arguments.",
SimpleInvokeStr(lib, "main"));
- lib = TestCase::GetReloadLibrary();
+ lib = Dart_RootLibrary();
EXPECT_NON_NULL(lib);
}
@@ -1988,14 +1861,14 @@
" return '$r1 $r2';\n"
"}\n";
- TestCase::SetReloadTestScript(kReloadScript);
+ EXPECT_VALID(TestCase::SetReloadTestScript(kReloadScript));
EXPECT_STREQ(
"1 NoSuchMethodError: Closure call with mismatched arguments: "
"function 'C.foo'",
SimpleInvokeStr(lib, "main"));
- lib = TestCase::GetReloadLibrary();
+ lib = Dart_RootLibrary();
EXPECT_NON_NULL(lib);
}
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index 559d178..bf28e59 100644
--- a/runtime/vm/kernel_binary.h
+++ b/runtime/vm/kernel_binary.h
@@ -19,7 +19,7 @@
// Keep in sync with package:kernel/lib/binary/tag.dart.
static const uint32_t kMagicProgramFile = 0x90ABCDEFu;
-static const uint32_t kBinaryFormatVersion = 3;
+static const uint32_t kBinaryFormatVersion = 4;
// Keep in sync with package:kernel/lib/binary/tag.dart
#define KERNEL_TAG_LIST(V) \
@@ -160,7 +160,7 @@
static const int HeaderSize = 8; // 'magic', 'formatVersion'.
static const int MetadataPayloadOffset = HeaderSize; // Right after header.
-class Reader {
+class Reader : public ValueObject {
public:
Reader(const uint8_t* buffer, intptr_t size)
: thread_(NULL),
diff --git a/runtime/vm/kernel_isolate.cc b/runtime/vm/kernel_isolate.cc
index 5d2a12c..a8a9a1f 100644
--- a/runtime/vm/kernel_isolate.cc
+++ b/runtime/vm/kernel_isolate.cc
@@ -306,6 +306,13 @@
return files;
}
+static void ReleaseFilesPairs(const Dart_CObject& files) {
+ for (intptr_t i = 0; i < files.value.as_array.length; i++) {
+ delete files.value.as_array.values[i];
+ }
+ delete[] files.value.as_array.values;
+}
+
static void PassThroughFinalizer(void* isolate_callback_data,
Dart_WeakPersistentHandle handle,
void* peer) {}
@@ -405,13 +412,7 @@
Dart_CObject message;
message.type = Dart_CObject_kArray;
- Dart_CObject files;
- if (source_files_count != 0) {
- files = BuildFilesPairs(source_files_count, source_files);
- } else {
- files.type = Dart_CObject_kArray;
- files.value.as_array.length = 0;
- }
+ Dart_CObject files = BuildFilesPairs(source_files_count, source_files);
Dart_CObject suppress_warnings;
suppress_warnings.type = Dart_CObject_kBool;
@@ -436,6 +437,8 @@
// Send the message.
Dart_PostCObject(kernel_port, &message);
+ ReleaseFilesPairs(files);
+
// Wait for reply to arrive.
MonitorLocker ml(monitor_);
while (result_.status == Dart_KernelCompilationStatus_Unknown) {
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index b7fabf3..4b83212 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -40,7 +40,7 @@
builder_(builder) {}
bool IsSimple(intptr_t kernel_offset) {
- AlternativeReadingScope alt(builder_->reader_, kernel_offset);
+ AlternativeReadingScope alt(&builder_->reader_, kernel_offset);
uint8_t payload = 0;
Tag tag = builder_->ReadTag(&payload); // read tag.
switch (tag) {
@@ -726,8 +726,8 @@
library_kernel_data_ =
TypedData::New(kTypedDataUint8ArrayCid, library_size, Heap::kOld);
- builder_.reader_->CopyDataToVMHeap(library_kernel_data_,
- library_kernel_offset_, library_size);
+ builder_.reader_.CopyDataToVMHeap(library_kernel_data_,
+ library_kernel_offset_, library_size);
library.set_kernel_data(library_kernel_data_);
library.set_kernel_offset(library_kernel_offset_);
@@ -825,7 +825,7 @@
field_helper.ReadUntilExcluding(FieldHelper::kEnd);
{
// GenerateFieldAccessors reads (some of) the initializer.
- AlternativeReadingScope alt(builder_.reader_, field_initializer_offset);
+ AlternativeReadingScope alt(&builder_.reader_, field_initializer_offset);
GenerateFieldAccessors(toplevel_class, field, &field_helper);
}
if (FLAG_enable_mirrors && field_helper.annotation_count_ > 0) {
@@ -1159,7 +1159,8 @@
field_helper.ReadUntilExcluding(FieldHelper::kEnd);
{
// GenerateFieldAccessors reads (some of) the initializer.
- AlternativeReadingScope alt(builder_.reader_, field_initializer_offset);
+ AlternativeReadingScope alt(&builder_.reader_,
+ field_initializer_offset);
GenerateFieldAccessors(klass, field, &field_helper);
}
if (FLAG_enable_mirrors && field_helper.annotation_count_ > 0) {
diff --git a/runtime/vm/kernel_loader.h b/runtime/vm/kernel_loader.h
index d18fa6c..ed47893 100644
--- a/runtime/vm/kernel_loader.h
+++ b/runtime/vm/kernel_loader.h
@@ -120,7 +120,7 @@
DISALLOW_COPY_AND_ASSIGN(ClassIndex);
};
-class KernelLoader {
+class KernelLoader : public ValueObject {
public:
explicit KernelLoader(Program* program);
static Object& LoadEntireProgram(Program* program,
@@ -303,11 +303,6 @@
GrowableArray<const Field*> fields_;
};
-class ClassLoader {
- public:
- void LoadClassMembers();
-};
-
} // namespace kernel
} // namespace dart
diff --git a/runtime/vm/message_handler.cc b/runtime/vm/message_handler.cc
index eb14377..1a1ca67 100644
--- a/runtime/vm/message_handler.cc
+++ b/runtime/vm/message_handler.cc
@@ -290,18 +290,6 @@
return HandleMessages(&ml, true, false);
}
-MessageHandler::MessageStatus MessageHandler::HandleAllMessages() {
- // We can only call HandleAllMessages when this handler is not
- // assigned to a thread pool.
- MonitorLocker ml(&monitor_);
- ASSERT(pool_ == NULL);
- ASSERT(!delete_me_);
-#if defined(DEBUG)
- CheckAccess();
-#endif
- return HandleMessages(&ml, true, true);
-}
-
MessageHandler::MessageStatus MessageHandler::PauseAndHandleAllMessages(
int64_t timeout_millis) {
MonitorLocker ml(&monitor_);
diff --git a/runtime/vm/message_handler.h b/runtime/vm/message_handler.h
index a7d9f96..247bff0 100644
--- a/runtime/vm/message_handler.h
+++ b/runtime/vm/message_handler.h
@@ -61,13 +61,6 @@
// Returns true on success.
MessageStatus HandleNextMessage();
- // Handles all messages for this message handler. Should only
- // be used when not running the handler on the thread pool (via Run
- // or RunBlocking).
- //
- // Returns true on success.
- MessageStatus HandleAllMessages();
-
// Handles any OOB messages for this message handler. Can be used
// even if the message handler is running on the thread pool.
//
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 463013e..68574b2 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -7827,7 +7827,16 @@
virtual uword ComputeCanonicalTableHash() const;
static const intptr_t kBytesPerElement = kWordSize;
- static const intptr_t kMaxElements = kSmiMax / kBytesPerElement;
+ // The length field is a Smi so that sets one limit on the max Array length.
+ // But we also need to be able to represent the length in bytes in an
+ // intptr_t, which is a different limit. Either may be smaller. We can't
+ // use Utils::Minimum here because it is not a const expression.
+ static const intptr_t kElementLimitDueToIntptrMax = static_cast<intptr_t>(
+ (kIntptrMax - sizeof(RawArray) - kObjectAlignment + kBytesPerElement) /
+ kBytesPerElement);
+ static const intptr_t kMaxElements = kSmiMax < kElementLimitDueToIntptrMax
+ ? kSmiMax
+ : kElementLimitDueToIntptrMax;
static const intptr_t kMaxNewSpaceElements =
(Heap::kNewAllocatableSize - sizeof(RawArray)) / kBytesPerElement;
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index f7ffc17..17eadb0 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -308,16 +308,10 @@
EXPECT(Smi::IsValid(-15));
EXPECT(Smi::IsValid(0xFFu));
// Upper two bits must be either 00 or 11.
-#if defined(ARCH_IS_64_BIT)
- EXPECT(!Smi::IsValid(kMaxInt64));
- EXPECT(Smi::IsValid(0x3FFFFFFFFFFFFFFF));
- EXPECT(Smi::IsValid(-1));
-#else
EXPECT(!Smi::IsValid(kMaxInt32));
EXPECT(Smi::IsValid(0x3FFFFFFF));
EXPECT(Smi::IsValid(-1));
EXPECT(!Smi::IsValid(0xFFFFFFFFu));
-#endif
EXPECT_EQ(5, smi.AsInt64Value());
EXPECT_EQ(5.0, smi.AsDoubleValue());
@@ -445,9 +439,6 @@
}
ISOLATE_UNIT_TEST_CASE(Mint) {
-// On 64-bit architectures a Smi is stored in a 64 bit word. A Midint cannot
-// be allocated if it does fit into a Smi.
-#if !defined(ARCH_IS_64_BIT)
{
Mint& med = Mint::Handle();
EXPECT(med.IsNull());
@@ -517,7 +508,6 @@
EXPECT_EQ(mint1.value(), mint_value);
EXPECT_EQ(mint2.value(), mint_value);
EXPECT_EQ(mint1.raw(), mint2.raw());
-#endif
}
ISOLATE_UNIT_TEST_CASE(Double) {
@@ -2747,22 +2737,6 @@
EXPECT(Smi::Cast(result).Value() == kSmiTestValue);
}
-#if defined(ARCH_IS_64_BIT)
-// Test for Embedded Smi object in the instructions.
-ISOLATE_UNIT_TEST_CASE(EmbedSmiIn64BitCode) {
- extern void GenerateEmbedSmiInCode(Assembler * assembler, intptr_t value);
- const intptr_t kSmiTestValue = DART_INT64_C(5) << 32;
- Assembler _assembler_;
- GenerateEmbedSmiInCode(&_assembler_, kSmiTestValue);
- const Function& function =
- Function::Handle(CreateFunction("Test_EmbedSmiIn64BitCode"));
- const Code& code = Code::Handle(Code::FinalizeCode(function, &_assembler_));
- function.AttachCode(code);
- const Object& result =
- Object::Handle(DartEntry::InvokeFunction(function, Array::empty_array()));
- EXPECT(Smi::Cast(result).Value() == kSmiTestValue);
-}
-#endif // ARCH_IS_64_BIT
ISOLATE_UNIT_TEST_CASE(ExceptionHandlers) {
const int kNumEntries = 4;
diff --git a/runtime/vm/regexp.cc b/runtime/vm/regexp.cc
index 4d99e0f..3d23411 100644
--- a/runtime/vm/regexp.cc
+++ b/runtime/vm/regexp.cc
@@ -3023,10 +3023,19 @@
Trace* current_trace,
PreloadState* state) {
if (state->eats_at_least_ == PreloadState::kEatsAtLeastNotYetInitialized) {
- // Save some time by looking at most one machine word ahead.
- state->eats_at_least_ =
- EatsAtLeast(compiler->one_byte() ? 4 : 2, kRecursionBudget,
- current_trace->at_start() == Trace::FALSE_VALUE);
+ // On ARM64, only read 16 bits ahead for now. This ensures that boxing is
+ // trivial even with the new smaller Smis. See
+ // https://github.com/dart-lang/sdk/issues/29951 and
+ // LoadCodeUnitsInstr::EmitNativeCode.
+#if defined(TARGET_ARCH_ARM64)
+ const int kMaxBytesLoaded = 2;
+#else
+ const int kMaxBytesLoaded = 4;
+#endif
+ const int kMaxTwoByteCharactersLoaded = kMaxBytesLoaded / 2;
+ state->eats_at_least_ = EatsAtLeast(
+ compiler->one_byte() ? kMaxBytesLoaded : kMaxTwoByteCharactersLoaded,
+ kRecursionBudget, current_trace->at_start() == Trace::FALSE_VALUE);
}
state->preload_characters_ =
CalculatePreloadCharacters(compiler, state->eats_at_least_);
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index 616a253..9b99bed 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -1819,7 +1819,6 @@
// Handle interrupts:
// - store buffer overflow
// - OOB message (vm-service or dart:isolate)
- // - Dart_InterruptIsolate
const Error& error = Error::Handle(thread->HandleInterrupts());
if (!error.IsNull()) {
Exceptions::PropagateError(error);
diff --git a/runtime/vm/simulator_arm64.cc b/runtime/vm/simulator_arm64.cc
index c115b7c..9318cfd 100644
--- a/runtime/vm/simulator_arm64.cc
+++ b/runtime/vm/simulator_arm64.cc
@@ -3199,13 +3199,21 @@
set_vregisterd(vd, 1, 0);
} else if (instr->Bits(16, 5) == 24) {
// Format(instr, "fcvtzds'sf 'rd, 'vn");
+ const intptr_t max = instr->Bit(31) == 1 ? INT64_MAX : INT32_MAX;
+ const intptr_t min = instr->Bit(31) == 1 ? INT64_MIN : INT32_MIN;
const double vn_val = bit_cast<double, int64_t>(get_vregisterd(vn, 0));
- if (vn_val >= static_cast<double>(INT64_MAX)) {
- set_register(instr, rd, INT64_MAX, instr->RdMode());
- } else if (vn_val <= static_cast<double>(INT64_MIN)) {
- set_register(instr, rd, INT64_MIN, instr->RdMode());
+ int64_t result;
+ if (vn_val >= static_cast<double>(max)) {
+ result = max;
+ } else if (vn_val <= static_cast<double>(min)) {
+ result = min;
} else {
- set_register(instr, rd, static_cast<int64_t>(vn_val), instr->RdMode());
+ result = static_cast<int64_t>(vn_val);
+ }
+ if (instr->Bit(31) == 1) {
+ set_register(instr, rd, result, instr->RdMode());
+ } else {
+ set_register(instr, rd, result & 0xffffffffll, instr->RdMode());
}
} else {
UnimplementedInstruction(instr);
diff --git a/runtime/vm/simulator_dbc.cc b/runtime/vm/simulator_dbc.cc
index bd7be22..a4c6ea9 100644
--- a/runtime/vm/simulator_dbc.cc
+++ b/runtime/vm/simulator_dbc.cc
@@ -636,11 +636,11 @@
// __builtin_s{add,sub,mul}_overflow() intrinsics here and below.
// Note that they may clobber the output location even when there is overflow:
// https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html
-DART_FORCE_INLINE static bool SignedAddWithOverflow(intptr_t lhs,
- intptr_t rhs,
+DART_FORCE_INLINE static bool SignedAddWithOverflow(int32_t lhs,
+ int32_t rhs,
intptr_t* out) {
intptr_t res = 1;
-#if defined(HOST_ARCH_IA32) || defined(HOST_ARCH_X64)
+#if defined(HOST_ARCH_IA32)
asm volatile(
"add %2, %1\n"
"jo 1f;\n"
@@ -650,12 +650,25 @@
: "+r"(res), "+r"(lhs)
: "r"(rhs), "r"(out)
: "cc");
+#elif defined(HOST_ARCH_X64)
+ int64_t tmp;
+ asm volatile(
+ "addl %[rhs], %[lhs]\n"
+ "jo 1f;\n"
+ "xor %[res], %[res]\n"
+ "movslq %[lhs], %[tmp]\n"
+ "mov %[tmp], 0(%[out])\n"
+ "1: "
+ : [res] "+r"(res), [lhs] "+r"(lhs), [tmp] "=&r"(tmp)
+ : [rhs] "r"(rhs), [out] "r"(out)
+ : "cc");
#elif defined(HOST_ARCH_ARM) || defined(HOST_ARCH_ARM64)
asm volatile(
- "adds %1, %1, %2;\n"
+ "adds %w1, %w1, %w2;\n"
"bvs 1f;\n"
+ "sxtw %x1, %w1;\n"
"mov %0, #0;\n"
- "str %1, [%3, #0]\n"
+ "str %x1, [%3, #0]\n"
"1:"
: "+r"(res), "+r"(lhs)
: "r"(rhs), "r"(out)
@@ -666,11 +679,11 @@
return (res != 0);
}
-DART_FORCE_INLINE static bool SignedSubWithOverflow(intptr_t lhs,
- intptr_t rhs,
+DART_FORCE_INLINE static bool SignedSubWithOverflow(int32_t lhs,
+ int32_t rhs,
intptr_t* out) {
intptr_t res = 1;
-#if defined(HOST_ARCH_IA32) || defined(HOST_ARCH_X64)
+#if defined(HOST_ARCH_IA32)
asm volatile(
"sub %2, %1\n"
"jo 1f;\n"
@@ -680,12 +693,25 @@
: "+r"(res), "+r"(lhs)
: "r"(rhs), "r"(out)
: "cc");
+#elif defined(HOST_ARCH_X64)
+ int64_t tmp;
+ asm volatile(
+ "subl %[rhs], %[lhs]\n"
+ "jo 1f;\n"
+ "xor %[res], %[res]\n"
+ "movslq %[lhs], %[tmp]\n"
+ "mov %[tmp], 0(%[out])\n"
+ "1: "
+ : [res] "+r"(res), [lhs] "+r"(lhs), [tmp] "=&r"(tmp)
+ : [rhs] "r"(rhs), [out] "r"(out)
+ : "cc");
#elif defined(HOST_ARCH_ARM) || defined(HOST_ARCH_ARM64)
asm volatile(
- "subs %1, %1, %2;\n"
+ "subs %w1, %w1, %w2;\n"
"bvs 1f;\n"
+ "sxtw %x1, %w1;\n"
"mov %0, #0;\n"
- "str %1, [%3, #0]\n"
+ "str %x1, [%3, #0]\n"
"1:"
: "+r"(res), "+r"(lhs)
: "r"(rhs), "r"(out)
@@ -696,11 +722,11 @@
return (res != 0);
}
-DART_FORCE_INLINE static bool SignedMulWithOverflow(intptr_t lhs,
- intptr_t rhs,
+DART_FORCE_INLINE static bool SignedMulWithOverflow(int32_t lhs,
+ int32_t rhs,
intptr_t* out) {
intptr_t res = 1;
-#if defined(HOST_ARCH_IA32) || defined(HOST_ARCH_X64)
+#if defined(HOST_ARCH_IA32)
asm volatile(
"imul %2, %1\n"
"jo 1f;\n"
@@ -710,6 +736,18 @@
: "+r"(res), "+r"(lhs)
: "r"(rhs), "r"(out)
: "cc");
+#elif defined(HOST_ARCH_X64)
+ int64_t tmp;
+ asm volatile(
+ "imull %[rhs], %[lhs]\n"
+ "jo 1f;\n"
+ "xor %[res], %[res]\n"
+ "movslq %[lhs], %[tmp]\n"
+ "mov %[tmp], 0(%[out])\n"
+ "1: "
+ : [res] "+r"(res), [lhs] "+r"(lhs), [tmp] "=&r"(tmp)
+ : [rhs] "r"(rhs), [out] "r"(out)
+ : "cc");
#elif defined(HOST_ARCH_ARM)
asm volatile(
"smull %1, ip, %1, %2;\n"
@@ -724,12 +762,12 @@
#elif defined(HOST_ARCH_ARM64)
int64_t prod_lo = 0;
asm volatile(
- "mul %1, %2, %3\n"
- "smulh %2, %2, %3\n"
- "cmp %2, %1, ASR #63;\n"
+ "smull %x1, %w2, %w3\n"
+ "asr %x2, %x1, #63\n"
+ "cmp %x2, %x1, ASR #31;\n"
"bne 1f;\n"
"mov %0, #0;\n"
- "str %1, [%4, #0]\n"
+ "str %x1, [%4, #0]\n"
"1:"
: "=r"(res), "+r"(prod_lo), "+r"(lhs)
: "r"(rhs), "r"(out)
@@ -1971,11 +2009,7 @@
if (rhs != 0) {
const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]);
const intptr_t res = (lhs >> kSmiTagSize) / (rhs >> kSmiTagSize);
-#if defined(ARCH_IS_64_BIT)
- const intptr_t untaggable = 0x4000000000000000LL;
-#else
const intptr_t untaggable = 0x40000000L;
-#endif // defined(ARCH_IS_64_BIT)
if (res != untaggable) {
*reinterpret_cast<intptr_t*>(&FP[rA]) = res << kSmiTagSize;
pc++;
@@ -2001,11 +2035,12 @@
{
BYTECODE(Shl, A_B_C);
const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]) >> kSmiTagSize;
- if (static_cast<uintptr_t>(rhs) < kBitsPerWord) {
- const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]);
- const intptr_t res = lhs << rhs;
+ const int kBitsPerInt32 = 32;
+ if (static_cast<uintptr_t>(rhs) < kBitsPerInt32) {
+ const int32_t lhs = reinterpret_cast<intptr_t>(FP[rB]);
+ const int32_t res = lhs << rhs;
if (lhs == (res >> rhs)) {
- *reinterpret_cast<intptr_t*>(&FP[rA]) = res;
+ *reinterpret_cast<intptr_t*>(&FP[rA]) = static_cast<intptr_t>(res);
pc++;
}
}
@@ -2016,8 +2051,7 @@
BYTECODE(Shr, A_B_C);
const intptr_t rhs = reinterpret_cast<intptr_t>(FP[rC]) >> kSmiTagSize;
if (rhs >= 0) {
- const intptr_t shift_amount =
- (rhs >= kBitsPerWord) ? (kBitsPerWord - 1) : rhs;
+ const intptr_t shift_amount = (rhs >= 32) ? (32 - 1) : rhs;
const intptr_t lhs = reinterpret_cast<intptr_t>(FP[rB]) >> kSmiTagSize;
*reinterpret_cast<intptr_t*>(&FP[rA]) = (lhs >> shift_amount)
<< kSmiTagSize;
diff --git a/runtime/vm/snapshot_test.cc b/runtime/vm/snapshot_test.cc
index cff0584..c7241ba 100644
--- a/runtime/vm/snapshot_test.cc
+++ b/runtime/vm/snapshot_test.cc
@@ -253,10 +253,6 @@
// here covers most of the 64-bit range. On 32-bit platforms the smi
// range covers most of the 32-bit range and values outside that
// range are also represented as mints.
-#if defined(ARCH_IS_64_BIT)
- EXPECT_EQ(Dart_CObject_kInt64, mint_cobject->type);
- EXPECT_EQ(value, mint_cobject->value.as_int64);
-#else
if (kMinInt32 < value && value < kMaxInt32) {
EXPECT_EQ(Dart_CObject_kInt32, mint_cobject->type);
EXPECT_EQ(value, mint_cobject->value.as_int32);
@@ -264,7 +260,6 @@
EXPECT_EQ(Dart_CObject_kInt64, mint_cobject->type);
EXPECT_EQ(value, mint_cobject->value.as_int64);
}
-#endif
}
TEST_CASE(SerializeMints) {
diff --git a/runtime/vm/stub_code_arm64.cc b/runtime/vm/stub_code_arm64.cc
index e23bb90..f56ed03 100644
--- a/runtime/vm/stub_code_arm64.cc
+++ b/runtime/vm/stub_code_arm64.cc
@@ -1333,14 +1333,18 @@
__ ldr(R1, Address(SP, +1 * kWordSize)); // Left.
__ orr(TMP, R0, Operand(R1));
__ BranchIfNotSmi(TMP, not_smi_or_overflow);
+ __ AssertSmiInRange(R0);
+ __ AssertSmiInRange(R1);
switch (kind) {
case Token::kADD: {
- __ adds(R0, R1, Operand(R0)); // Adds.
+ __ addsw(R0, R1, Operand(R0)); // Adds.
+ __ sxtw(R0, R0);
__ b(not_smi_or_overflow, VS); // Branch if overflow.
break;
}
case Token::kSUB: {
- __ subs(R0, R1, Operand(R0)); // Subtract.
+ __ subsw(R0, R1, Operand(R0)); // Subtract.
+ __ sxtw(R0, R0);
__ b(not_smi_or_overflow, VS); // Branch if overflow.
break;
}
@@ -1382,6 +1386,8 @@
__ StoreToOffset(R1, R6, count_offset);
}
+ __ AssertSmiInRange(R0, Assembler::kValueCanBeHeapPointer);
+
__ ret();
}
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index 5183d28..a160513 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -1270,13 +1270,15 @@
__ j(NOT_ZERO, not_smi_or_overflow);
switch (kind) {
case Token::kADD: {
- __ addq(RAX, RCX);
+ __ addl(RAX, RCX);
__ j(OVERFLOW, not_smi_or_overflow);
+ __ movsxd(RAX, RAX);
break;
}
case Token::kSUB: {
- __ subq(RAX, RCX);
+ __ subl(RAX, RCX);
__ j(OVERFLOW, not_smi_or_overflow);
+ __ movsxd(RAX, RAX);
break;
}
case Token::kEQ: {
diff --git a/runtime/vm/token_position.h b/runtime/vm/token_position.h
index c28f9a4..eadb562 100644
--- a/runtime/vm/token_position.h
+++ b/runtime/vm/token_position.h
@@ -18,7 +18,7 @@
// ClassifyingTokenPositions N -> -1 - N
//
// Synthetically created AstNodes are given real source positions but encoded
-// as negative numbers from [kSmiMin32, -1 - N]. For example:
+// as negative numbers from [kSmiMin, -1 - N]. For example:
//
// A source position of 0 in a synthetic AstNode would be encoded as -2 - N.
// A source position of 1 in a synthetic AstNode would be encoded as -3 - N.
@@ -86,7 +86,7 @@
#undef DECLARE_VALUES
static const intptr_t kMinSourcePos = 0;
static const TokenPosition kMinSource;
- static const intptr_t kMaxSourcePos = kSmiMax32 - kMaxSentinelDescriptors - 2;
+ static const intptr_t kMaxSourcePos = kSmiMax - kMaxSentinelDescriptors - 2;
static const TokenPosition kMaxSource;
// Decode from a snapshot.
diff --git a/runtime/vm/unit_test.cc b/runtime/vm/unit_test.cc
index a8fcbc1..84b4dbb 100644
--- a/runtime/vm/unit_test.cc
+++ b/runtime/vm/unit_test.cc
@@ -196,7 +196,10 @@
}
static void ReloadTest(Dart_NativeArguments native_args) {
- DART_CHECK_VALID(TestCase::TriggerReload());
+ Dart_Handle result = TestCase::TriggerReload();
+ if (Dart_IsError(result)) {
+ Dart_PropagateError(result);
+ }
}
static Dart_NativeFunction IsolateReloadTestNativeResolver(
@@ -266,7 +269,10 @@
sourcefiles_count, sourcefiles, incrementally);
if (compilation_result.status != Dart_KernelCompilationStatus_Ok) {
- return OS::SCreate(zone, "Compilation failed %s", compilation_result.error);
+ char* result =
+ OS::SCreate(zone, "Compilation failed %s", compilation_result.error);
+ free(compilation_result.error);
+ return result;
}
const uint8_t* kernel_file = compilation_result.kernel;
intptr_t kernel_length = compilation_result.kernel_size;
@@ -500,11 +506,19 @@
#ifndef PRODUCT
-void TestCase::SetReloadTestScript(const char* script) {
+Dart_Handle TestCase::SetReloadTestScript(const char* script) {
if (FLAG_use_dart_frontend) {
Dart_SourceFile* sourcefiles = NULL;
intptr_t num_files = BuildSourceFilesArray(&sourcefiles, script);
- KernelIsolate::UpdateInMemorySources(num_files, sourcefiles);
+ Dart_KernelCompilationResult compilation_result =
+ KernelIsolate::UpdateInMemorySources(num_files, sourcefiles);
+ delete[] sourcefiles;
+ if (compilation_result.status != Dart_KernelCompilationStatus_Ok) {
+ Dart_Handle result = Dart_NewApiError(compilation_result.error);
+ free(compilation_result.error);
+ return result;
+ }
+ return Api::Success();
} else {
if (script_reload_key == kUnsetThreadLocalKey) {
script_reload_key = OSThread::CreateThreadLocal();
@@ -514,15 +528,17 @@
// Store the new script in TLS.
OSThread::SetThreadLocal(script_reload_key,
reinterpret_cast<uword>(script));
+ return Api::Success();
}
}
Dart_Handle TestCase::TriggerReload() {
- Isolate* isolate = Isolate::Current();
+ Thread* thread = Thread::Current();
+ Isolate* isolate = thread->isolate();
JSONStream js;
bool success = false;
{
- TransitionNativeToVM transition(Thread::Current());
+ TransitionNativeToVM transition(thread);
success = isolate->ReloadSources(&js,
false, // force_reload
NULL, NULL,
@@ -530,82 +546,48 @@
OS::PrintErr("RELOAD REPORT:\n%s\n", js.ToCString());
}
+ Dart_Handle result = Dart_Null();
if (success) {
- return Dart_FinalizeLoading(false);
+ result = Dart_FinalizeLoading(false);
+ }
+
+ if (Dart_IsError(result)) {
+ // Keep load error.
+ } else if (isolate->reload_context()->reload_aborted()) {
+ result = Api::NewHandle(thread, isolate->reload_context()->error());
} else {
- return Dart_Null();
+ result = Dart_RootLibrary();
}
-}
-Dart_Handle TestCase::GetReloadLibrary() {
- Isolate* isolate = Isolate::Current();
-
- if (isolate->reload_context() != NULL &&
- isolate->reload_context()->reload_aborted()) {
- return Dart_Null();
+ TransitionNativeToVM transition(thread);
+ if (isolate->reload_context() != NULL) {
+ isolate->DeleteReloadContext();
}
- return Dart_RootLibrary();
-}
-Dart_Handle TestCase::GetReloadErrorOrRootLibrary() {
- Isolate* isolate = Isolate::Current();
-
- if (isolate->reload_context() != NULL &&
- isolate->reload_context()->reload_aborted()) {
- // Return a handle to the error.
- return Api::NewHandle(Thread::Current(),
- isolate->reload_context()->error());
- }
- return Dart_RootLibrary();
+ return result;
}
Dart_Handle TestCase::ReloadTestScript(const char* script) {
if (FLAG_use_dart_frontend) {
Dart_SourceFile* sourcefiles = NULL;
intptr_t num_files = BuildSourceFilesArray(&sourcefiles, script);
- KernelIsolate::UpdateInMemorySources(num_files, sourcefiles);
+ Dart_KernelCompilationResult compilation_result =
+ KernelIsolate::UpdateInMemorySources(num_files, sourcefiles);
delete[] sourcefiles;
+ if (compilation_result.status != Dart_KernelCompilationStatus_Ok) {
+ Dart_Handle result = Dart_NewApiError(compilation_result.error);
+ free(compilation_result.error);
+ return result;
+ }
} else {
SetReloadTestScript(script);
}
- Dart_Handle result = TriggerReload();
- if (Dart_IsError(result)) {
- return result;
- }
-
- result = GetReloadErrorOrRootLibrary();
-
- {
- Thread* thread = Thread::Current();
- TransitionNativeToVM transition(thread);
- Isolate* isolate = thread->isolate();
- if (isolate->reload_context() != NULL) {
- isolate->DeleteReloadContext();
- }
- }
-
- return result;
+ return TriggerReload();
}
Dart_Handle TestCase::ReloadTestKernel(const void* kernel) {
- Dart_Handle result = TriggerReload();
- if (Dart_IsError(result)) {
- return result;
- }
-
- result = GetReloadErrorOrRootLibrary();
-
- {
- Thread* thread = Thread::Current();
- TransitionNativeToVM transition(thread);
- Isolate* isolate = thread->isolate();
- if (isolate->reload_context() != NULL) {
- isolate->DeleteReloadContext();
- }
- }
-
- return result;
+ return TriggerReload();
}
#endif // !PRODUCT
diff --git a/runtime/vm/unit_test.h b/runtime/vm/unit_test.h
index e8b1fc7..5aa1d6a 100644
--- a/runtime/vm/unit_test.h
+++ b/runtime/vm/unit_test.h
@@ -355,15 +355,11 @@
virtual void Run();
// Sets |script| to be the source used at next reload.
- static void SetReloadTestScript(const char* script);
+ static Dart_Handle SetReloadTestScript(const char* script);
// Initiates the reload.
static Dart_Handle TriggerReload();
- // Returns the root library if the last reload was successful, otherwise
- // returns Dart_Null().
- static Dart_Handle GetReloadLibrary();
-
// Helper function which reloads the current isolate using |script|.
static Dart_Handle ReloadTestScript(const char* script);
static Dart_Handle ReloadTestKernel(const void* kernel);
@@ -383,11 +379,6 @@
const char* name,
void* data = NULL);
- // Gets the result of a reload. This touches state in IsolateReloadContext
- // that is zone allocated and should not be used if a reload is triggered
- // using reloadTest() from package:isolate_reload_helper.
- static Dart_Handle GetReloadErrorOrRootLibrary();
-
RunEntry* const run_;
};
diff --git a/sdk/lib/_internal/js_runtime/lib/convert_patch.dart b/sdk/lib/_internal/js_runtime/lib/convert_patch.dart
index 771a73a..2d234a4 100644
--- a/sdk/lib/_internal/js_runtime/lib/convert_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/convert_patch.dart
@@ -6,7 +6,7 @@
import 'dart:_js_helper' show argumentErrorValue, patch;
import 'dart:_foreign_helper' show JS;
-import 'dart:_interceptors' show JSExtendableArray;
+import 'dart:_interceptors' show JSArray, JSExtendableArray;
import 'dart:_internal' show MappedIterable, ListIterable;
import 'dart:collection' show LinkedHashMap, MapBase;
import 'dart:_native_typed_data' show NativeUint8List;
@@ -274,7 +274,7 @@
assert(!_isUpgraded);
List keys = _data;
if (keys == null) {
- keys = _data = _getPropertyNames(_original);
+ keys = _data = new JSArray<String>.typed(_getPropertyNames(_original));
}
return JS('JSExtendableArray', '#', keys);
}
diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
index e3fe5422a..80a3910 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
@@ -986,9 +986,12 @@
return null;
}
- // This is to avoid stack overflows due to very large argument arrays in
- // apply(). It fixes http://dartbug.com/6919
- static String _fromCharCodeApply(List<int> array) {
+ /// Version of `String.fromCharCode.apply` that chunks the conversion to avoid
+ /// stack overflows due to very large argument arrays.
+ ///
+ /// [array] is pre-validated as a JSArray of int values but is not typed as
+ /// <int> so it can be called with any JSArray.
+ static String _fromCharCodeApply(List array) {
const kMaxApply = 500;
int end = array.length;
if (end <= kMaxApply) {
diff --git a/sdk/lib/_internal/js_runtime/lib/regexp_helper.dart b/sdk/lib/_internal/js_runtime/lib/regexp_helper.dart
index ddf159e..a588b08 100644
--- a/sdk/lib/_internal/js_runtime/lib/regexp_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/regexp_helper.dart
@@ -104,7 +104,7 @@
}
Match firstMatch(String string) {
- List<String> m = JS('JSExtendableArray|Null', r'#.exec(#)', _nativeRegExp,
+ List m = JS('JSExtendableArray|Null', r'#.exec(#)', _nativeRegExp,
checkString(string));
if (m == null) return null;
return new _MatchImplementation(this, m);
@@ -163,7 +163,9 @@
final Pattern pattern;
// Contains a JS RegExp match object.
// It is an Array of String values with extra 'index' and 'input' properties.
- final List<String> _match;
+ // We didn't force it to be JSArray<String>, so it is JSArray<dynamic>, but
+ // containing String or `undefined` values.
+ final JSArray _match;
_MatchImplementation(this.pattern, this._match) {
assert(JS('var', '#.input', _match) is String);
@@ -180,8 +182,12 @@
JS('returns:int;depends:none;effects:none;gvn:true', '#[0].length',
_match);
- String group(int index) => _match[index];
+ // The JS below changes the static type to avoid an implicit cast.
+ // TODO(sra): Find a nicer way to do this, e.g. unsafeCast.
+ String group(int index) => JS('String|Null', '#', _match[index]);
+
String operator [](int index) => group(index);
+
int get groupCount => _match.length - 1;
List<String> groups(List<int> groups) {
diff --git a/sdk/lib/async/future.dart b/sdk/lib/async/future.dart
index bcd1f22..8de4156 100644
--- a/sdk/lib/async/future.dart
+++ b/sdk/lib/async/future.dart
@@ -148,10 +148,12 @@
*/
abstract class Future<T> {
/// A `Future<Null>` completed with `null`.
- static final _Future<Null> _nullFuture = new _Future<Null>.value(null);
+ static final _Future<Null> _nullFuture =
+ new _Future<Null>.zoneValue(null, Zone.root);
/// A `Future<bool>` completed with `false`.
- static final _Future<bool> _falseFuture = new _Future<bool>.value(false);
+ static final _Future<bool> _falseFuture =
+ new _Future<bool>.zoneValue(false, Zone.root);
/**
* Creates a future containing the result of calling [computation]
diff --git a/sdk/lib/async/future_impl.dart b/sdk/lib/async/future_impl.dart
index 6eeaa08..2b56f9d 100644
--- a/sdk/lib/async/future_impl.dart
+++ b/sdk/lib/async/future_impl.dart
@@ -184,7 +184,7 @@
* Until the future is completed, the field may hold the zone that
* listener callbacks used to create this future should be run in.
*/
- final Zone _zone = Zone.current;
+ final Zone _zone;
/**
* Either the result, a list of listeners or another future.
@@ -204,20 +204,24 @@
var _resultOrListeners;
// This constructor is used by async/await.
- _Future();
+ _Future() : _zone = Zone.current;
- _Future.immediate(FutureOr<T> result) {
+ _Future.immediate(FutureOr<T> result) : _zone = Zone.current {
_asyncComplete(result);
}
- _Future.immediateError(var error, [StackTrace stackTrace]) {
+ /** Creates a future with the value and the specified zone. */
+ _Future.zoneValue(T value, this._zone) {
+ _setValue(value);
+ }
+
+ _Future.immediateError(var error, [StackTrace stackTrace])
+ : _zone = Zone.current {
_asyncCompleteError(error, stackTrace);
}
/** Creates a future that is already completed with the value. */
- _Future.value(T value) {
- _setValue(value);
- }
+ _Future.value(T value) : this.zoneValue(value, Zone.current);
bool get _mayComplete => _state == _stateIncomplete;
bool get _isPendingComplete => _state == _statePendingComplete;
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index 29afb71..4f9f8a9 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -1273,9 +1273,6 @@
* If an error occurs, or if this stream ends without finding a match and
* with no [orElse] function provided,
* the returned future is completed with an error.
- *
- * The [defaultValue] parameter is deprecated, and [orElse] should be used
- * instead.
*/
Future<T> firstWhere(bool test(T element), {T orElse()}) {
_Future<T> future = new _Future();
@@ -1314,9 +1311,6 @@
* instead of the first.
* That means that a non-error result cannot be provided before this stream
* is done.
- *
- * The [defaultValue] parameter is deprecated, and [orElse] should be used
- * instead.
*/
Future<T> lastWhere(bool test(T element), {T orElse()}) {
_Future<T> future = new _Future();
diff --git a/sdk/lib/async/zone.dart b/sdk/lib/async/zone.dart
index fa49808..951d027 100644
--- a/sdk/lib/async/zone.dart
+++ b/sdk/lib/async/zone.dart
@@ -388,7 +388,7 @@
* the current's zone behavior. All specification entries that are `null`
* inherit the behavior from the parent zone (`this`).
*
- * The new zone inherits the stored values (accessed through [[]])
+ * The new zone inherits the stored values (accessed through [operator []])
* of this zone and updates them with values from [zoneValues], which either
* adds new values or overrides existing ones.
*
diff --git a/sdk/lib/collection/hash_map.dart b/sdk/lib/collection/hash_map.dart
index 233f644..84655dc 100644
--- a/sdk/lib/collection/hash_map.dart
+++ b/sdk/lib/collection/hash_map.dart
@@ -48,7 +48,7 @@
* for keys in order to place them in the hash table. If it is omitted, the
* key's own [Object.hashCode] is used.
*
- * If using methods like [[]], [remove] and [containsKey] together
+ * If using methods like [operator []], [remove] and [containsKey] together
* with a custom equality and hashcode, an extra `isValidKey` function
* can be supplied. This function is called before calling [equals] or
* [hashCode] with an argument that may not be a [K] instance, and if the
diff --git a/sdk/lib/collection/linked_hash_map.dart b/sdk/lib/collection/linked_hash_map.dart
index 22fe5eb..b4c2bf4 100644
--- a/sdk/lib/collection/linked_hash_map.dart
+++ b/sdk/lib/collection/linked_hash_map.dart
@@ -35,7 +35,7 @@
* for keys in order to place them in the hash table. If it is omitted, the
* key's own [Object.hashCode] is used.
*
- * If using methods like [[]], [remove] and [containsKey] together
+ * If using methods like [operator []], [remove] and [containsKey] together
* with a custom equality and hashcode, an extra `isValidKey` function
* can be supplied. This function is called before calling [equals] or
* [hashCode] with an argument that may not be a [K] instance, and if the
diff --git a/sdk/lib/collection/splay_tree.dart b/sdk/lib/collection/splay_tree.dart
index b3eb7cb..fad3ce8 100644
--- a/sdk/lib/collection/splay_tree.dart
+++ b/sdk/lib/collection/splay_tree.dart
@@ -273,7 +273,7 @@
* Non-comparable objects (including `null`) will not work as keys
* in that case.
*
- * To allow calling [[]], [remove] or [containsKey] with objects
+ * To allow calling [operator []], [remove] or [containsKey] with objects
* that are not supported by the `compare` function, an extra `isValidKey`
* predicate function can be supplied. This function is tested before
* using the `compare` function on an argument value that may not be a [K]
diff --git a/sdk/lib/core/comparable.dart b/sdk/lib/core/comparable.dart
index 7a22948..bbb334f 100644
--- a/sdk/lib/core/comparable.dart
+++ b/sdk/lib/core/comparable.dart
@@ -33,10 +33,10 @@
* and to provide separate [Comparator]s instead.
*
* It is recommended that the order of a [Comparable] agrees
- * with its operator [==] equality (`a.compareTo(b) == 0` iff `a == b`),
+ * with its operator [operator ==] equality (`a.compareTo(b) == 0` iff `a == b`),
* but this is not a requirement.
* For example, [double] and [DateTime] have `compareTo` methods
- * that do not agree with operator [==].
+ * that do not agree with operator [operator ==].
* For doubles the [compareTo] method is more precise than the equality,
* and for [DateTime] it is less precise.
*
diff --git a/sdk/lib/core/object.dart b/sdk/lib/core/object.dart
index fda5662..0338f48 100644
--- a/sdk/lib/core/object.dart
+++ b/sdk/lib/core/object.dart
@@ -12,7 +12,7 @@
*
* When you define a class, you should override [toString]
* to return a string describing an instance of that class.
- * You might also need to define [hashCode] and [==], as described in the
+ * You might also need to define [hashCode] and [operator ==], as described in the
* [Implementing map
* keys](https://www.dartlang.org/docs/dart-up-and-running/ch03.html#implementing-map-keys)
* section of the [library
@@ -62,18 +62,18 @@
* The hash code for this object.
*
* A hash code is a single integer which represents the state of the object
- * that affects [==] comparisons.
+ * that affects [operator ==] comparisons.
*
* All objects have hash codes.
* The default hash code represents only the identity of the object,
- * the same way as the default [==] implementation only considers objects
+ * the same way as the default [operator ==] implementation only considers objects
* equal if they are identical (see [identityHashCode]).
*
- * If [==] is overridden to use the object state instead,
+ * If [operator ==] is overridden to use the object state instead,
* the hash code must also be changed to represent that state.
*
* Hash codes must be the same for objects that are equal to each other
- * according to [==].
+ * according to [operator ==].
* The hash code of an object should only change if the object changes
* in a way that affects equality.
* There are no further requirements for the hash codes.
@@ -86,7 +86,7 @@
* data structures like [HashSet] or [HashMap].
*
* If a subclass overrides [hashCode], it should override the
- * [==] operator as well to maintain consistency.
+ * [operator ==] operator as well to maintain consistency.
*/
external int get hashCode;
diff --git a/sdk/lib/core/set.dart b/sdk/lib/core/set.dart
index 8d95d2d..e7c36be 100644
--- a/sdk/lib/core/set.dart
+++ b/sdk/lib/core/set.dart
@@ -40,7 +40,7 @@
* Creates an empty [Set].
*
* The created [Set] is a plain [LinkedHashSet].
- * As such, it considers elements that are equal (using [==]) to be
+ * As such, it considers elements that are equal (using [operator ==]) to be
* indistinguishable, and requires them to have a compatible
* [Object.hashCode] implementation.
*
@@ -70,7 +70,7 @@
* new Set<SubType>.from(superSet.where((e) => e is SubType));
*
* The created [Set] is a [LinkedHashSet]. As such, it considers elements that
- * are equal (using [==]) to be indistinguishable, and requires them to
+ * are equal (using [operator ==]) to be indistinguishable, and requires them to
* have a compatible [Object.hashCode] implementation.
*
* The set is equivalent to one created by
@@ -82,7 +82,7 @@
* Creates a [Set] from [elements].
*
* The created [Set] is a [LinkedHashSet]. As such, it considers elements that
- * are equal (using [==]) to be indistinguishable, and requires them to
+ * are equal (using [operator ==]) to be indistinguishable, and requires them to
* have a compatible [Object.hashCode] implementation.
*
* The set is equivalent to one created by
diff --git a/sdk/lib/core/string.dart b/sdk/lib/core/string.dart
index ce66b2d..f81fdf6 100644
--- a/sdk/lib/core/string.dart
+++ b/sdk/lib/core/string.dart
@@ -193,7 +193,7 @@
/**
* Returns a hash code derived from the code units of the string.
*
- * This is compatible with [==]. Strings with the same sequence
+ * This is compatible with [operator ==]. Strings with the same sequence
* of code units have the same hash code.
*/
int get hashCode;
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index cba877e..19dc744 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -70,6 +70,7 @@
import 'dart:_interceptors'
show
Interceptor,
+ JavaScriptFunction,
JSExtendableArray,
JSUInt31,
findInterceptorConstructorForType,
@@ -26938,7 +26939,7 @@
// Messages posted to ports are initially paused, allowing listeners to be
// setup, start() needs to be explicitly invoked to begin handling messages.
if (type == 'message') {
- start();
+ _start();
}
super.addEventListener(type, listener, useCapture);
@@ -26986,9 +26987,10 @@
@DocsEditable()
void _postMessage_2(message) native;
+ @JSName('start')
@DomName('MessagePort.start')
@DocsEditable()
- void start() native;
+ void _start() native;
/// Stream of `message` events handled by this [MessagePort].
@DomName('MessagePort.onmessage')
@@ -28080,6 +28082,20 @@
NavigatorOnLine,
NavigatorAutomationInformation,
NavigatorID {
+ @DomName('Navigator.getGamepads')
+ List<Gamepad> getGamepads() {
+ var gamepadList = _getGamepads();
+
+ // If no prototype we need one for the world to hookup to the proper Dart class.
+ var jsProto = JS('', '#.prototype', gamepadList);
+ if (jsProto == null) {
+ JS('', '#.prototype = Object.create(null)', gamepadList);
+ }
+
+ applyExtension('GamepadList', gamepadList);
+ return gamepadList;
+ }
+
@DomName('Navigator.language')
String get language =>
JS('String', '#.language || #.userLanguage', this, this);
@@ -28293,12 +28309,13 @@
@Experimental() // untriaged
Future getBattery() native;
+ @JSName('getGamepads')
@DomName('Navigator.getGamepads')
@DocsEditable()
@Experimental() // untriaged
@Returns('_GamepadList|Null')
@Creates('_GamepadList')
- List<Gamepad> getGamepads() native;
+ List<Gamepad> _getGamepads() native;
@DomName('Navigator.getInstalledRelatedApps')
@DocsEditable()
@@ -50876,7 +50893,8 @@
JS('=Object', '#.extends = #', opts, extendsTagName);
}
- return JS('=Object', '#.registerElement(#, #)', document, tag, opts);
+ return JS(
+ 'JavaScriptFunction', '#.registerElement(#, #)', document, tag, opts);
}
//// Called by Element.created to do validation & initialization.
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index a8c5ade..08eb54c 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -931,7 +931,7 @@
LayoutTests/fast/text/sub-pixel/text-scaling-webfont_t01: Pass, RuntimeError # Please triage this failure
LayoutTests/fast/text/text-combine-shrink-to-fit_t01: RuntimeError # Please triage this failure
LayoutTests/fast/text/window-find_t01: Pass, RuntimeError # Please triage this failure
-LayoutTests/fast/text/zero-width-characters_t01: RuntimeError # Please triage this failure
+LayoutTests/fast/text/zero-width-characters_t01: RuntimeError, Pass # Please triage this failure
LayoutTests/fast/transforms/bounding-rect-zoom_t01: RuntimeError # Please triage this failure
LayoutTests/fast/transforms/hit-test-large-scale_t01: RuntimeError # Please triage this failure
LayoutTests/fast/url/anchor_t01: RuntimeError # Please triage this failure
@@ -1254,6 +1254,7 @@
LayoutTests/fast/canvas/webgl/index-validation-verifies-too-many-indices_t01: RuntimeError, Pass # Please triage this flake
LayoutTests/fast/canvas/webgl/premultiplyalpha-test_t01: RuntimeError, Pass # Please triage this flake
LayoutTests/fast/canvas/webgl/triangle_t01: RuntimeError, Pass # Please triage this flake
+LayoutTests/fast/css/font-face-unicode-range-load_t01: Pass, Slow
LayoutTests/fast/multicol/newmulticol/balance_t04: RuntimeError # Please triage this failure
LayoutTests/fast/shapes/shape-outside-floats/shape-outside-floats-inset-rounded-different-writing-modes-left_t01: RuntimeError # Please triage this failure
LayoutTests/fast/shapes/shape-outside-floats/shape-outside-rounded-boxes_t02: RuntimeError # Please triage this failure
@@ -7035,7 +7036,6 @@
Language/Classes/Getters/same_name_method_t07: MissingCompileTimeError
Language/Classes/Superinterfaces/more_than_once_t01: MissingCompileTimeError
Language/Classes/Superinterfaces/superclass_as_superinterface_t01: MissingCompileTimeError
-Language/Classes/definition_t16: Crash
Language/Classes/definition_t24: MissingCompileTimeError
Language/Classes/same_name_instance_and_static_members_t01: MissingCompileTimeError
Language/Classes/same_name_instance_and_static_members_t02: MissingCompileTimeError
@@ -7058,34 +7058,15 @@
Language/Expressions/Constants/logical_expression_t04: MissingCompileTimeError
Language/Expressions/Function_Invocation/Unqualified_Invocation/instance_context_invocation_t04: Crash
Language/Expressions/Instance_Creation/Const/exception_t01: MissingCompileTimeError
-Language/Expressions/Maps/syntax_t08: Crash
Language/Expressions/Method_Invocation/Ordinary_Invocation/evaluation_t08: RuntimeError
Language/Expressions/Method_Invocation/Super_Invocation/accessible_instance_member_t02: Crash
Language/Expressions/Method_Invocation/Super_Invocation/evaluation_t05: RuntimeError
Language/Expressions/Method_Invocation/Super_Invocation/invocation_t02: Crash
Language/Expressions/Null/instance_of_class_null_t01: RuntimeError
-Language/Expressions/Strings/String_Interpolation/syntax_t08: Crash
-Language/Expressions/Strings/multi_line_t11: Crash # Investiage: source-data from FE causes us to crash
-Language/Expressions/Strings/multi_line_t12: Crash
-Language/Expressions/Strings/multi_line_t13: Crash
-Language/Expressions/Strings/multi_line_t15: Crash
-Language/Expressions/Strings/multi_line_t16: Crash
-Language/Expressions/Strings/multi_line_t17: Crash
-Language/Expressions/Strings/multi_line_t18: Crash
-Language/Expressions/Strings/multi_line_t19: Crash
-Language/Expressions/Strings/multi_line_t20: Crash
-Language/Expressions/Strings/multi_line_t21: Crash
-Language/Expressions/Strings/multi_line_t22: Crash
-Language/Expressions/Strings/multi_line_t23: Crash
-Language/Expressions/Strings/multi_line_t24: Crash
-Language/Expressions/Strings/multi_line_t25: Crash
-Language/Expressions/Strings/multi_line_t28: Crash
-Language/Expressions/Strings/multi_line_t29: Crash
-Language/Expressions/Strings/multi_line_t32: Crash
-Language/Expressions/Strings/multi_line_t33: Crash
Language/Expressions/This/placement_t04: Crash
Language/Functions/External_Functions/not_connected_to_a_body_t01: RuntimeError
-Language/Functions/syntax_t09: Crash
+Language/Functions/Formal_Parameters/Optional_Formals/default_value_t01: MissingCompileTimeError
+Language/Functions/Formal_Parameters/Optional_Formals/default_value_t02: MissingCompileTimeError
Language/Libraries_and_Scripts/Imports/same_name_t10: RuntimeError
Language/Libraries_and_Scripts/Scripts/top_level_main_t01: CompileTimeError
Language/Metadata/before_class_t01: RuntimeError
@@ -7178,7 +7159,6 @@
Language/Classes/Instance_Methods/Operators/allowed_names_t20: Crash
Language/Classes/Instance_Methods/Operators/allowed_names_t21: Crash
Language/Classes/Instance_Methods/Operators/allowed_names_t22: Crash
-Language/Classes/definition_t16: Crash
Language/Classes/member_definition_t04: Crash
Language/Classes/member_definition_t06: Crash
Language/Classes/member_definition_t07: Crash
@@ -7189,31 +7169,11 @@
Language/Classes/member_definition_t12: Crash
Language/Expressions/Constants/depending_on_itself_t03: Crash
Language/Expressions/Function_Invocation/Unqualified_Invocation/instance_context_invocation_t04: Crash
-Language/Expressions/Maps/syntax_t08: Crash
Language/Expressions/Method_Invocation/Super_Invocation/accessible_instance_member_t02: Crash
Language/Expressions/Method_Invocation/Super_Invocation/evaluation_t05: Crash
Language/Expressions/Method_Invocation/Super_Invocation/getter_lookup_failed_t03: Crash
Language/Expressions/Method_Invocation/Super_Invocation/getter_lookup_failed_t04: Crash
Language/Expressions/Method_Invocation/Super_Invocation/invocation_t02: Crash
-Language/Expressions/Strings/String_Interpolation/syntax_t08: Crash
-Language/Expressions/Strings/multi_line_t11: Crash
-Language/Expressions/Strings/multi_line_t12: Crash
-Language/Expressions/Strings/multi_line_t13: Crash
-Language/Expressions/Strings/multi_line_t15: Crash
-Language/Expressions/Strings/multi_line_t16: Crash
-Language/Expressions/Strings/multi_line_t17: Crash
-Language/Expressions/Strings/multi_line_t18: Crash
-Language/Expressions/Strings/multi_line_t19: Crash
-Language/Expressions/Strings/multi_line_t20: Crash
-Language/Expressions/Strings/multi_line_t21: Crash
-Language/Expressions/Strings/multi_line_t22: Crash
-Language/Expressions/Strings/multi_line_t23: Crash
-Language/Expressions/Strings/multi_line_t24: Crash
-Language/Expressions/Strings/multi_line_t25: Crash
-Language/Expressions/Strings/multi_line_t28: Crash
-Language/Expressions/Strings/multi_line_t29: Crash
-Language/Expressions/Strings/multi_line_t32: Crash
-Language/Expressions/Strings/multi_line_t33: Crash
Language/Expressions/This/placement_t04: Crash
Language/Functions/setter_modifier_t01: Crash
Language/Functions/setter_modifier_t02: Crash
@@ -7221,7 +7181,6 @@
Language/Functions/setter_modifier_t04: Crash
Language/Functions/setter_modifier_t05: Crash
Language/Functions/setter_modifier_t06: Crash
-Language/Functions/syntax_t09: Crash
Language/Statements/For/syntax_t13: Crash
Language/Statements/For/syntax_t20: Crash
LibTest/core/Invocation/namedArguments_A01_t01: Crash
diff --git a/tests/co19/co19-kernel.status b/tests/co19/co19-kernel.status
index 3668431..9973899 100644
--- a/tests/co19/co19-kernel.status
+++ b/tests/co19/co19-kernel.status
@@ -4,6 +4,8 @@
[ $compiler == fasta ]
Language/Classes/definition_t24: MissingCompileTimeError
+Language/Functions/Formal_Parameters/Optional_Formals/default_value_t01: MissingCompileTimeError
+Language/Functions/Formal_Parameters/Optional_Formals/default_value_t02: MissingCompileTimeError
Language/Types/Type_Void/syntax_t08: MissingCompileTimeError
Language/Types/Type_Void/syntax_t09: MissingCompileTimeError
LayoutTests/*: Skip # TODO(ahe): Make dart:html available.
@@ -768,7 +770,6 @@
Language/Expressions/Strings/static_type_t09: CompileTimeError
Language/Expressions/This/placement_t04: MissingCompileTimeError
Language/Expressions/This/static_type_t01: CompileTimeError
-Language/Expressions/Throw/syntax_t02: MissingCompileTimeError
Language/Expressions/Throw/throw_various_types_t01: CompileTimeError
Language/Expressions/Type_Cast/evaluation_t04: CompileTimeError
Language/Expressions/Type_Cast/evaluation_t05: CompileTimeError
@@ -1697,7 +1698,6 @@
Language/Expressions/Property_Extraction/Getter_Access_and_Method_Extraction/class_object_member_t06: MissingCompileTimeError
Language/Expressions/Property_Extraction/Getter_Access_and_Method_Extraction/class_object_member_t07: MissingCompileTimeError
Language/Expressions/Property_Extraction/Getter_Access_and_Method_Extraction/class_object_member_t08: MissingCompileTimeError
-Language/Expressions/Throw/syntax_t02: MissingCompileTimeError
Language/Libraries_and_Scripts/Exports/reexport_t01: MissingCompileTimeError
Language/Libraries_and_Scripts/Exports/reexport_t02: MissingCompileTimeError
Language/Libraries_and_Scripts/Imports/invalid_uri_deferred_t02: CompileTimeError
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index 8a3884a..a4449ec 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -188,9 +188,6 @@
LibTest/collection/ListMixin/ListMixin_class_A01_t02: Skip # co19 issue 673, These tests take too much memory (300 MB) for our 1 GB test machine co19 issue 673. http://code.google.com/p/co19/issues/detail?id=673
LibTest/core/List/List_class_A01_t02: Skip # co19 issue 673, These tests take too much memory (300 MB) for our 1 GB test machine co19 issue 673. http://code.google.com/p/co19/issues/detail?id=673
-[ $arch != arm64 && $arch != simarm64 && $arch != simdbc && $arch != simdbc64 && $arch != x64 && ($runtime == dart_precompiled || $runtime == vm) ]
-LibTest/core/int/operator_left_shift_A01_t02: Fail # co19 issue 129
-
[ $arch == ia32 && $mode == release && $runtime == vm && $system == linux ]
service/dev_fs_spawn_test: Pass, Fail # Issue 28411
@@ -382,6 +379,9 @@
LibTest/typed_data/Uint64List/Uint64List.view_A01_t02: CompileTimeError # Large integer literal
WebPlatformTest/*: SkipByDesign # dart:html not supported on VM.
+[ $runtime == dart_precompiled || $runtime == vm ]
+LibTest/core/int/operator_left_shift_A01_t02: Fail # Can't represent 1 << 2147483647 without running out of memory.
+
[ $runtime == flutter || $hot_reload || $hot_reload_rollback ]
Language/Expressions/Assignment/prefix_object_t02: Skip # Requires deferred libraries
Language/Expressions/Constants/constant_constructor_t03: Skip # Requires deferred libraries
diff --git a/tests/co19_2/co19_2-kernel.status b/tests/co19_2/co19_2-kernel.status
index 7a80c04..6378421 100644
--- a/tests/co19_2/co19_2-kernel.status
+++ b/tests/co19_2/co19_2-kernel.status
@@ -199,7 +199,6 @@
Language/Expressions/Strings/String_Interpolation/double_quote_t02: CompileTimeError
Language/Expressions/Strings/String_Interpolation/single_quote_t02: CompileTimeError
Language/Expressions/This/placement_t04: MissingCompileTimeError
-Language/Expressions/Throw/syntax_t02: MissingCompileTimeError
Language/Expressions/Type_Cast/evaluation_t10: MissingCompileTimeError
Language/Expressions/Type_Test/evaluation_t10: MissingCompileTimeError
Language/Expressions/Unary_Expressions/syntax_t10: CompileTimeError
diff --git a/tests/compiler/dart2js/deferred_loading/libs/deferred_typed_map_lib1.dart b/tests/compiler/dart2js/deferred_loading/libs/deferred_typed_map_lib1.dart
index 0700011..4529ffb 100644
--- a/tests/compiler/dart2js/deferred_loading/libs/deferred_typed_map_lib1.dart
+++ b/tests/compiler/dart2js/deferred_loading/libs/deferred_typed_map_lib1.dart
@@ -10,6 +10,7 @@
const table =
/*ast.null*/
/*kernel.OutputUnit(1, {lib})*/
+/*strong.OutputUnit(1, {lib})*/
const <int, FF>{1: f1, 2: f2};
/*element: f1:OutputUnit(1, {lib})*/
diff --git a/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart b/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
index 35df582..fad8d47 100644
--- a/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
+++ b/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
@@ -442,7 +442,7 @@
/// file and any supporting libraries.
Future checkTests(Directory dataDir, ComputeMemberDataFunction computeFromAst,
ComputeMemberDataFunction computeFromKernel,
- {bool testStrongMode: false,
+ {bool testStrongMode: true,
List<String> skipForAst: const <String>[],
List<String> skipForKernel: const <String>[],
List<String> skipForStrong: const <String>[],
@@ -477,6 +477,7 @@
if (shouldContinue) continued = true;
List<String> testOptions = options.toList();
bool strongModeOnlyTest = false;
+ bool trustTypeAnnotations = false;
if (name.endsWith('_ea.dart')) {
testOptions.add(Flags.enableAsserts);
} else if (name.endsWith('_strong.dart')) {
@@ -486,6 +487,8 @@
}
} else if (name.endsWith('_checked.dart')) {
testOptions.add(Flags.enableCheckedMode);
+ } else if (name.endsWith('_trust.dart')) {
+ trustTypeAnnotations = true;
}
print('----------------------------------------------------------------');
@@ -537,11 +540,15 @@
print('--skipped for ast-----------------------------------------------');
} else {
print('--from ast------------------------------------------------------');
+ List<String> options = [Flags.useOldFrontend]..addAll(testOptions);
+ if (trustTypeAnnotations) {
+ options.add(Flags.trustTypeAnnotations);
+ }
MemberAnnotations<IdValue> annotations = expectedMaps[astMarker];
CompiledData compiledData1 = await computeData(
entryPoint, memorySourceFiles, computeFromAst,
computeClassData: computeClassDataFromAst,
- options: [Flags.useOldFrontend]..addAll(testOptions),
+ options: options,
verbose: verbose,
forUserLibrariesOnly: forUserLibrariesOnly,
globalIds: annotations.globalData.keys);
@@ -555,11 +562,15 @@
print('--skipped for kernel--------------------------------------------');
} else {
print('--from kernel---------------------------------------------------');
+ List<String> options = []..addAll(testOptions);
+ if (trustTypeAnnotations) {
+ options.add(Flags.trustTypeAnnotations);
+ }
MemberAnnotations<IdValue> annotations = expectedMaps[kernelMarker];
CompiledData compiledData2 = await computeData(
entryPoint, memorySourceFiles, computeFromKernel,
computeClassData: computeClassDataFromKernel,
- options: testOptions,
+ options: options,
verbose: verbose,
forUserLibrariesOnly: forUserLibrariesOnly,
globalIds: annotations.globalData.keys);
@@ -575,16 +586,17 @@
print('--skipped for kernel (strong mode)----------------------------');
} else {
print('--from kernel (strong mode)-----------------------------------');
+ List<String> options = [Flags.strongMode]..addAll(testOptions);
MemberAnnotations<IdValue> annotations = expectedMaps[strongMarker];
CompiledData compiledData2 = await computeData(
entryPoint, memorySourceFiles, computeFromKernel,
computeClassData: computeClassDataFromKernel,
- options: [Flags.strongMode]..addAll(testOptions),
+ options: options,
verbose: verbose,
forUserLibrariesOnly: forUserLibrariesOnly,
globalIds: annotations.globalData.keys);
if (await checkCode(
- kernelName, entity.uri, code, annotations, compiledData2,
+ strongName, entity.uri, code, annotations, compiledData2,
filterActualData: filterActualData,
fatalErrors: !testAfterFailures)) {
hasFailures = true;
@@ -708,7 +720,7 @@
} else if (id is ElementId) {
String memberName = id.memberName;
bool isSetter = false;
- if (memberName != '[]=' && memberName.endsWith('=')) {
+ if (memberName != '[]=' && memberName != '==' && memberName.endsWith('=')) {
isSetter = true;
memberName = memberName.substring(0, memberName.length - 1);
}
diff --git a/tests/compiler/dart2js/equivalence/show_helper.dart b/tests/compiler/dart2js/equivalence/show_helper.dart
index 9bdae9a..bbf0b1d 100644
--- a/tests/compiler/dart2js/equivalence/show_helper.dart
+++ b/tests/compiler/dart2js/equivalence/show_helper.dart
@@ -20,6 +20,10 @@
argParser.addFlag('all', negatable: false, defaultsTo: false);
argParser.addFlag('use-kernel', negatable: false, defaultsTo: false);
argParser.addFlag('strong', negatable: false, defaultsTo: false);
+ argParser.addFlag('omit-implicit-checks',
+ negatable: false, defaultsTo: false);
+ argParser.addFlag('trust-type-annotations',
+ negatable: false, defaultsTo: false);
return argParser;
}
@@ -34,6 +38,8 @@
bool verbose = argResults['verbose'];
bool strongMode = argResults['strong'];
bool useKernel = argResults['use-kernel'] || strongMode;
+ bool omitImplicitChecks = argResults['omit-implicit-checks'];
+ bool trustTypeAnnotations = argResults['trust-type-annotations'];
String file = argResults.rest.first;
Uri entryPoint = Uri.base.resolve(nativeToUriPath(file));
@@ -53,6 +59,12 @@
if (strongMode) {
options.add(Flags.strongMode);
}
+ if (trustTypeAnnotations) {
+ options.add(Flags.trustTypeAnnotations);
+ }
+ if (omitImplicitChecks) {
+ options.add(Flags.omitImplicitChecks);
+ }
CompiledData data = await computeData(
entryPoint, const {}, useKernel ? computeKernelData : computeAstData,
computeClassData:
diff --git a/tests/compiler/dart2js/inference/data/await.dart b/tests/compiler/dart2js/inference/data/await.dart
index 724648a..03099d8 100644
--- a/tests/compiler/dart2js/inference/data/await.dart
+++ b/tests/compiler/dart2js/inference/data/await.dart
@@ -16,7 +16,11 @@
////////////////////////////////////////////////////////////////////////////////
/*element: _method1:[null]*/
-_method1(/*[null|subclass=Object]*/ o) {}
+_method1(
+ /*ast.[null|subclass=Object]*/
+ /*kernel.[null|subclass=Object]*/
+ /*strong.[null|subclass=JSInt]*/
+ o) {}
/*element: awaitOfFuture:[exact=_Future]*/
awaitOfFuture() async {
@@ -30,7 +34,11 @@
////////////////////////////////////////////////////////////////////////////////
/*element: _method2:[null]*/
-_method2(/*[null|subclass=Object]*/ o) {}
+_method2(
+ /*ast.[null|subclass=Object]*/
+ /*kernel.[null|subclass=Object]*/
+ /*strong.[null|subclass=JSInt]*/
+ o) {}
/*element: awaitOfInt:[exact=_Future]*/
awaitOfInt() async {
@@ -47,7 +55,11 @@
/*Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)*/ o) {}
/*element: _method4:[null]*/
-_method4(/*[null|subclass=Object]*/ o) {}
+_method4(
+ /*ast.[null|subclass=Object]*/
+ /*kernel.[null|subclass=Object]*/
+ /*strong.[null|subclass=JSInt]*/
+ o) {}
/*element: awaitForOfStream:[exact=_Future]*/
awaitForOfStream() async {
diff --git a/tests/compiler/dart2js/inference/data/closure_tracer_28919.dart b/tests/compiler/dart2js/inference/data/closure_tracer_28919.dart
index 1fece67..96ea43a 100644
--- a/tests/compiler/dart2js/inference/data/closure_tracer_28919.dart
+++ b/tests/compiler/dart2js/inference/data/closure_tracer_28919.dart
@@ -56,7 +56,7 @@
methods. /*invoke: [exact=JSExtendableArray]*/ add(
/*[null]*/ (int /*[null|subclass=Object]*/ x) {
res = x;
- sum = x + i;
+ sum = x /*strong.invoke: [null|subclass=JSInt]*/ + i;
});
}
methods /*[exact=JSExtendableArray]*/ [0](499);
@@ -64,8 +64,15 @@
probe2methods(methods);
}
-/*element: probe2res:[null|subclass=Object]*/
-probe2res(/*[null|subclass=Object]*/ x) => x;
+/*ast.element: probe2res:[null|subclass=Object]*/
+/*kernel.element: probe2res:[null|subclass=Object]*/
+/*strong.element: probe2res:[null|subclass=JSInt]*/
+probe2res(
+ /*ast.[null|subclass=Object]*/
+ /*kernel.[null|subclass=Object]*/
+ /*strong.[null|subclass=JSInt]*/
+ x) =>
+ x;
/*element: probe2methods:[exact=JSExtendableArray]*/
probe2methods(/*[exact=JSExtendableArray]*/ x) => x;
diff --git a/tests/compiler/dart2js/inference/data/deferred_load_get.dart b/tests/compiler/dart2js/inference/data/deferred_load_get.dart
index 44b2121..a4b0fb6 100644
--- a/tests/compiler/dart2js/inference/data/deferred_load_get.dart
+++ b/tests/compiler/dart2js/inference/data/deferred_load_get.dart
@@ -6,7 +6,7 @@
// Synthetic getter added by kernel.
/*kernel.element: __loadLibrary_expect:[null|subclass=Object]*/
-/*strong.element: __loadLibrary_expect:[null|subclass=Object]*/
+/*strong.element: __loadLibrary_expect:[null|exact=_Future]*/
/*element: main:[null]*/
main() {
diff --git a/tests/compiler/dart2js/inference/data/expose_this_closure.dart b/tests/compiler/dart2js/inference/data/expose_this_closure.dart
index bffdc67..b60e4c9 100644
--- a/tests/compiler/dart2js/inference/data/expose_this_closure.dart
+++ b/tests/compiler/dart2js/inference/data/expose_this_closure.dart
@@ -58,7 +58,11 @@
abstract class SuperClass1 {
/*element: SuperClass1.:[exact=Class3]*/
- SuperClass1(/*[null|subclass=Object]*/ o);
+ SuperClass1(
+ /*ast.[null|subclass=Object]*/
+ /*kernel.[null|subclass=Object]*/
+ /*strong.[null|subclass=JSInt]*/
+ o);
}
class Class3 extends SuperClass1 {
diff --git a/tests/compiler/dart2js/inference/data/field_type.dart b/tests/compiler/dart2js/inference/data/field_type.dart
index aeec6f6..5fe9757 100644
--- a/tests/compiler/dart2js/inference/data/field_type.dart
+++ b/tests/compiler/dart2js/inference/data/field_type.dart
@@ -608,7 +608,12 @@
bar24();
/*element: A24.+:Value([exact=JSString], value: "foo")*/
- operator +(/*[exact=JSUInt31]*/ other) => 'foo';
+ operator +(
+ /*ast.[exact=JSUInt31]*/
+ /*kernel.[exact=JSUInt31]*/
+ /*strong.[empty]*/
+ other) =>
+ 'foo';
/*element: A24.bar24:[exact=JSDouble]*/
bar24() => 42.5;
diff --git a/tests/compiler/dart2js/inference/data/for_in.dart b/tests/compiler/dart2js/inference/data/for_in.dart
index d021fbc..d71083f 100644
--- a/tests/compiler/dart2js/inference/data/for_in.dart
+++ b/tests/compiler/dart2js/inference/data/for_in.dart
@@ -8,6 +8,7 @@
forInReturn();
forInReturnMulti();
forInReturnRefined();
+ forInReturnRefinedDynamic();
testInForIn();
operatorInForIn();
updateInForIn();
@@ -31,7 +32,9 @@
// Return element from a for-in loop on a list literal.
////////////////////////////////////////////////////////////////////////////////
-/*element: forInReturn:[null|subclass=Object]*/
+/*ast.element: forInReturn:[null|subclass=Object]*/
+/*kernel.element: forInReturn:[null|subclass=Object]*/
+/*strong.element: forInReturn:[null|subclass=JSInt]*/
forInReturn() {
/*iterator: Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 3)*/
/*current: [exact=ArrayIterator]*/
@@ -75,6 +78,25 @@
/*current: [exact=ArrayIterator]*/
/*moveNext: [exact=ArrayIterator]*/
for (var a in [1, 2, 3]) {
+ // TODO(johnniwinther): We should know the type of [a] here. Even if [a] has
+ // type `dynamic`.
+ a. /*strong.[null|subclass=JSInt]*/ isEven;
+ a. /*[subclass=JSInt]*/ isEven;
+ return a;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Sequentially refine element and return it from a for-in loop on known list
+// type with a dynamic variable.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: forInReturnRefinedDynamic:[null|subclass=JSInt]*/
+forInReturnRefinedDynamic() {
+ /*iterator: Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 3)*/
+ /*current: [exact=ArrayIterator]*/
+ /*moveNext: [exact=ArrayIterator]*/
+ for (dynamic a in [1, 2, 3]) {
// TODO(johnniwinther): We should know the type of [a] here.
a.isEven;
a. /*[subclass=JSInt]*/ isEven;
diff --git a/tests/compiler/dart2js/inference/data/general.dart b/tests/compiler/dart2js/inference/data/general.dart
index 867e759..1ca6af3 100644
--- a/tests/compiler/dart2js/inference/data/general.dart
+++ b/tests/compiler/dart2js/inference/data/general.dart
@@ -589,7 +589,10 @@
var a = topLevelGetter();
// Make [a] a captured variable. This should disable receiver
// specialization on [a].
- (/*[null|subclass=Object]*/ () => a.toString())();
+ (/*ast.[null|subclass=Object]*/
+ /*kernel.[null|subclass=Object]*/
+ /*strong.[null|exact=JSString]*/
+ () => a.toString())();
a - 42;
return a;
}
@@ -664,9 +667,13 @@
class A {
factory A() = A.generative;
+
/*element: A.generative:[exact=A]*/
A.generative();
- /*element: A.==:Union([exact=JSBool], [exact=JSUInt31])*/
+
+ /*ast.element: A.==:Union([exact=JSBool], [exact=JSUInt31])*/
+ /*kernel.element: A.==:Union([exact=JSBool], [exact=JSUInt31])*/
+ /*strong.element: A.==:[exact=JSBool]*/
operator ==(/*Union([exact=JSString], [exact=JSUInt31])*/ other) =>
42 as dynamic;
diff --git a/tests/compiler/dart2js/inference/data/js_interop.dart b/tests/compiler/dart2js/inference/data/js_interop.dart
index d8cdb06..168b52e 100644
--- a/tests/compiler/dart2js/inference/data/js_interop.dart
+++ b/tests/compiler/dart2js/inference/data/js_interop.dart
@@ -20,5 +20,7 @@
{/*[exact=JSUInt31]*/ a, /*Value([exact=JSString], value: "")*/ b});
}
-/*element: anonymousClass:[null|subclass=Object]*/
+/*ast.element: anonymousClass:[null|subclass=Object]*/
+/*kernel.element: anonymousClass:[null|subclass=Object]*/
+/*strong.element: anonymousClass:[null|subclass=JavaScriptObject]*/
anonymousClass() => new Class1(a: 1, b: '');
diff --git a/tests/compiler/dart2js/inference/data/locals_notrust.dart b/tests/compiler/dart2js/inference/data/locals_notrust.dart
new file mode 100644
index 0000000..bf14080
--- /dev/null
+++ b/tests/compiler/dart2js/inference/data/locals_notrust.dart
@@ -0,0 +1,61 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/*element: main:[null]*/
+main() {
+ dontTrustLocals();
+ dontTrustFunctions();
+ inferFromFunctions();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Test that we don't trust the explicit type of a local, unless we are in
+// strong mode.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: _dontTrustLocals:[exact=JSBool]*/ _dontTrustLocals(
+ int Function(int) /*[null|subclass=Closure]*/ f) {
+ int c = f(0);
+ return c /*strong.invoke: [null|subclass=JSInt]*/ == 0;
+}
+
+/*element: dontTrustLocals:[null]*/
+dontTrustLocals() {
+ _dontTrustLocals(/*[exact=JSUInt31]*/ (/*[exact=JSUInt31]*/ o) => o);
+ _dontTrustLocals(null);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Test that we don't infer the type of a dynamic local from the type of the
+// function.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: _dontTrustFunctions:[exact=JSBool]*/
+_dontTrustFunctions(int Function(int) /*[null|subclass=Closure]*/ f) {
+ dynamic c = f(0);
+ return c == 0;
+}
+
+/*element: dontTrustFunctions:[null]*/
+dontTrustFunctions() {
+ _dontTrustFunctions(/*[exact=JSUInt31]*/ (/*[exact=JSUInt31]*/ o) => o);
+ _dontTrustFunctions(null);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Test that we don't infer the type of a 'var' local from the type of the
+// function, unless we are in strong mode.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: _inferFromFunctions:[exact=JSBool]*/
+_inferFromFunctions(int Function(int) /*[null|subclass=Closure]*/ f) {
+ var c = f(0);
+ return c /*strong.invoke: [null|subclass=JSInt]*/ == 0;
+}
+
+/*element: inferFromFunctions:[null]*/
+inferFromFunctions() {
+ _inferFromFunctions(/*[exact=JSUInt31]*/ (/*[exact=JSUInt31]*/ o) => o);
+ _inferFromFunctions(null);
+}
diff --git a/tests/compiler/dart2js/inference/data/locals_trust.dart b/tests/compiler/dart2js/inference/data/locals_trust.dart
new file mode 100644
index 0000000..f3dc89b
--- /dev/null
+++ b/tests/compiler/dart2js/inference/data/locals_trust.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/*element: main:[null]*/
+main() {
+ trustLocals();
+ dontTrustFunctions();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Test that we trust the explicit type of a local with
+// --trust-type-annotations.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: _trustLocals:[exact=JSBool]*/ _trustLocals(
+ int Function(int) /*[null|subclass=Closure]*/ f) {
+ int c = f(0);
+ return c /*invoke: [null|subclass=JSInt]*/ == 0;
+}
+
+/*element: trustLocals:[null]*/
+trustLocals() {
+ _trustLocals(/*[exact=JSUInt31]*/ (/*[exact=JSUInt31]*/ o) => o);
+ _trustLocals(null);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Test that we don't trust the type of a function even with
+// --trust-type-annotations.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: _dontTrustFunctions:[exact=JSBool]*/
+_dontTrustFunctions(int Function(int) /*[null|subclass=Closure]*/ f) {
+ dynamic c = f(0);
+ return c == 0;
+}
+
+/*element: dontTrustFunctions:[null]*/
+dontTrustFunctions() {
+ _dontTrustFunctions(/*[exact=JSUInt31]*/ (/*[exact=JSUInt31]*/ o) => o);
+ _dontTrustFunctions(null);
+}
diff --git a/tests/compiler/dart2js/inference/data/map_tracer_const.dart b/tests/compiler/dart2js/inference/data/map_tracer_const.dart
index 4b2bd43..2bfe52f 100644
--- a/tests/compiler/dart2js/inference/data/map_tracer_const.dart
+++ b/tests/compiler/dart2js/inference/data/map_tracer_const.dart
@@ -2,7 +2,9 @@
// 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.
-/*element: closure:Union([exact=JSDouble], [exact=JSUInt31])*/
+/*ast.element: closure:Union([exact=JSDouble], [exact=JSUInt31])*/
+/*kernel.element: closure:Union([exact=JSDouble], [exact=JSUInt31])*/
+/*strong.element: closure:[exact=JSUInt31]*/
int closure(int /*Union([exact=JSDouble], [exact=JSUInt31])*/ x) {
return x;
}
diff --git a/tests/compiler/dart2js/inference/data/no_such_method.dart b/tests/compiler/dart2js/inference/data/no_such_method.dart
index c4225e3..09cce06 100644
--- a/tests/compiler/dart2js/inference/data/no_such_method.dart
+++ b/tests/compiler/dart2js/inference/data/no_such_method.dart
@@ -52,7 +52,13 @@
class Class3 {
/*element: Class3.noSuchMethod:[null|subclass=Object]*/
noSuchMethod(Invocation /*[null|subclass=Object]*/ invocation) {
- return invocation.positionalArguments.first;
+ return invocation
+ .
+ /*strong.[null|exact=JSInvocationMirror]*/
+ positionalArguments
+ .
+ /*strong.[exact=JSUnmodifiableArray]*/
+ first;
}
/*element: Class3.method:[null|subclass=Object]*/
@@ -78,8 +84,13 @@
/*element: Class4.noSuchMethod:[null]*/
noSuchMethod(Invocation /*[null|subclass=Object]*/ invocation) {
- this. /*update: [exact=Class4]*/ field =
- invocation.positionalArguments.first;
+ this. /*update: [exact=Class4]*/ field = invocation
+ .
+ /*strong.[null|exact=JSInvocationMirror]*/
+ positionalArguments
+ .
+ /*strong.[exact=JSUnmodifiableArray]*/
+ first;
return null;
}
diff --git a/tests/compiler/dart2js/inference/data/parameters_trust.dart b/tests/compiler/dart2js/inference/data/parameters_trust.dart
new file mode 100644
index 0000000..a36baa9
--- /dev/null
+++ b/tests/compiler/dart2js/inference/data/parameters_trust.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+
+/*element: main:[null]*/
+main() {
+ trustParameters();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Test that we trust the explicit type of a parameter with
+// --trust-type-annotations.
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: _trustParameters:[exact=JSUInt31]*/
+_trustParameters(
+ int
+ /*ast.[exact=JSUInt31]*/
+ /*kernel.[exact=JSUInt31]*/
+ /*strong.Union([exact=JSString], [exact=JSUInt31])*/
+ i) {
+ return i;
+}
+
+/*element: trustParameters:[null]*/
+trustParameters() {
+ dynamic f = _trustParameters;
+ Expect.equals(0, f(0));
+ Expect.throws(/*[null|subclass=Object]*/ () => f('foo'));
+}
diff --git a/tests/compiler/dart2js/inference/show.dart b/tests/compiler/dart2js/inference/show.dart
index 05389ea..94402a7 100644
--- a/tests/compiler/dart2js/inference/show.dart
+++ b/tests/compiler/dart2js/inference/show.dart
@@ -35,5 +35,5 @@
kernelFunction = computeMemberIrTypeMasks;
}
await show(results, astFunction, kernelFunction,
- options: [stopAfterTypeInference]);
+ options: [/*stopAfterTypeInference*/]);
}
diff --git a/tests/compiler/dart2js/inference/side_effects_test.dart b/tests/compiler/dart2js/inference/side_effects_test.dart
index e1966a4..f0189f7 100644
--- a/tests/compiler/dart2js/inference/side_effects_test.dart
+++ b/tests/compiler/dart2js/inference/side_effects_test.dart
@@ -24,7 +24,10 @@
new Directory.fromUri(Platform.script.resolve('side_effects'));
await checkTests(
dataDir, computeMemberAstSideEffects, computeMemberIrSideEffects,
- args: args, options: [stopAfterTypeInference]);
+ args: args,
+ options: [stopAfterTypeInference],
+ // TODO(johnniwinther): Run tests with strong mode.
+ testStrongMode: false);
});
}
diff --git a/tests/compiler/dart2js/inlining/inlining_test.dart b/tests/compiler/dart2js/inlining/inlining_test.dart
index d3a6f0b..c14e939 100644
--- a/tests/compiler/dart2js/inlining/inlining_test.dart
+++ b/tests/compiler/dart2js/inlining/inlining_test.dart
@@ -28,7 +28,10 @@
Directory dataDir = new Directory.fromUri(Platform.script.resolve('data'));
await checkTests(
dataDir, computeMemberAstInlinings, computeMemberIrInlinings,
- args: args, skipForAst: ['external.dart'], skipForKernel: []);
+ args: args,
+ skipForAst: ['external.dart'],
+ // TODO(johnniwinther): Run tests with strong mode.
+ testStrongMode: false);
});
}
diff --git a/tests/compiler/dart2js/jumps/jump_test.dart b/tests/compiler/dart2js/jumps/jump_test.dart
index b18da0e..2a911b4 100644
--- a/tests/compiler/dart2js/jumps/jump_test.dart
+++ b/tests/compiler/dart2js/jumps/jump_test.dart
@@ -24,7 +24,9 @@
Directory dataDir = new Directory.fromUri(Platform.script.resolve('data'));
await checkTests(dataDir, computeJumpsData, computeKernelJumpsData,
options: [Flags.disableTypeInference, stopAfterTypeInference],
- args: args);
+ args: args,
+ // TODO(johnniwinther): Run tests with strong mode.
+ testStrongMode: false);
});
}
diff --git a/tests/compiler/dart2js/model/constant_expression_evaluate_test.dart b/tests/compiler/dart2js/model/constant_expression_evaluate_test.dart
index 9bff47f..4cbd4b9 100644
--- a/tests/compiler/dart2js/model/constant_expression_evaluate_test.dart
+++ b/tests/compiler/dart2js/model/constant_expression_evaluate_test.dart
@@ -94,6 +94,13 @@
@override
CommonElements get commonElements => _environment.commonElements;
+ @override
+ DartTypes get types => _environment.types;
+
+ @override
+ InterfaceType get enclosingConstructedType =>
+ _environment.enclosingConstructedType;
+
void reportWarning(
ConstantExpression expression, MessageKind kind, Map arguments) {
errors.add(new EvaluationError(kind, arguments));
@@ -106,9 +113,10 @@
_environment.reportError(expression, kind, arguments);
}
- ConstantValue evaluateConstructor(
- ConstructorEntity constructor, ConstantValue evaluate()) {
- return _environment.evaluateConstructor(constructor, evaluate);
+ @override
+ ConstantValue evaluateConstructor(ConstructorEntity constructor,
+ InterfaceType type, ConstantValue evaluate()) {
+ return _environment.evaluateConstructor(constructor, type, evaluate);
}
ConstantValue evaluateField(FieldEntity field, ConstantValue evaluate()) {
diff --git a/tests/compiler/dart2js/model/forwarding_stub_test.dart b/tests/compiler/dart2js/model/forwarding_stub_test.dart
new file mode 100644
index 0000000..ed86ed3
--- /dev/null
+++ b/tests/compiler/dart2js/model/forwarding_stub_test.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:async_helper/async_helper.dart';
+import 'package:compiler/src/commandline_options.dart';
+import 'package:compiler/src/common_elements.dart';
+import 'package:compiler/src/compiler.dart';
+import 'package:compiler/src/elements/entities.dart';
+import 'package:compiler/src/world.dart';
+import 'package:expect/expect.dart';
+import '../memory_compiler.dart';
+
+const String source = '''
+
+class Mixin<T> {
+ void method(T t) {}
+}
+class Super {}
+class Class extends Super with Mixin<int> {}
+
+main() {
+ new Class().method(0);
+}
+''';
+
+main() {
+ asyncTest(() async {
+ CompilationResult result = await (runCompiler(
+ memorySourceFiles: {'main.dart': source}, options: [Flags.strongMode]));
+ Expect.isTrue(result.isSuccess);
+ Compiler compiler = result.compiler;
+ ClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
+ ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
+ ClassEntity cls =
+ elementEnvironment.lookupClass(elementEnvironment.mainLibrary, 'Class');
+ ClassEntity mixin =
+ elementEnvironment.lookupClass(elementEnvironment.mainLibrary, 'Mixin');
+ FunctionEntity method = elementEnvironment.lookupClassMember(cls, 'method');
+ Expect.isNotNull(method);
+ Expect.equals(mixin, method.enclosingClass);
+ Expect.isFalse(method.isAbstract);
+ });
+}
diff --git a/tests/compiler/dart2js/data/one_line_dart_program.dart b/tests/compiler/dart2js/old_frontend/data/one_line_dart_program.dart
similarity index 100%
rename from tests/compiler/dart2js/data/one_line_dart_program.dart
rename to tests/compiler/dart2js/old_frontend/data/one_line_dart_program.dart
diff --git a/tests/compiler/dart2js/zero_termination_test.dart b/tests/compiler/dart2js/old_frontend/zero_termination_test.dart
similarity index 70%
rename from tests/compiler/dart2js/zero_termination_test.dart
rename to tests/compiler/dart2js/old_frontend/zero_termination_test.dart
index 4a49e8c..0165af1 100644
--- a/tests/compiler/dart2js/zero_termination_test.dart
+++ b/tests/compiler/dart2js/old_frontend/zero_termination_test.dart
@@ -16,7 +16,7 @@
import 'package:expect/expect.dart';
import 'package:path/path.dart' as path;
-import 'end_to_end/launch_helper.dart' show launchDart2Js;
+import '../end_to_end/launch_helper.dart' show launchDart2Js;
Uri pathOfData = Platform.script;
Directory tempDir;
@@ -53,30 +53,35 @@
Expect.notEquals(0, result.exitCode);
List<int> stdout = result.stdout;
String stdoutString = utf8.decode(stdout);
- Expect.isTrue(stdoutString.contains("Error"));
+ Expect.isTrue(stdoutString.contains("Error"), "stdout:\n$stdoutString");
// Make sure the "499" from the last line is in the output.
- Expect.isTrue(stdoutString.contains("499"));
+ Expect.isTrue(stdoutString.contains("499"), "stdout:\n$stdoutString");
// Make sure that the output does not contain any 0 character.
Expect.isFalse(stdout.contains(0));
}
-Future testFile({bool useKernel}) async {
+Future testFile() async {
String inFilePath =
pathOfData.resolve('data/one_line_dart_program.dart').path;
- List<String> args = [inFilePath, "--out=" + outFilePath];
- if (!useKernel) args.add(Flags.useOldFrontend);
-
+ List<String> args = [
+ inFilePath,
+ "--out=" + outFilePath,
+ Flags.useOldFrontend
+ ];
await cleanup();
check(await launchDart2Js(args, noStdoutEncoding: true));
await cleanup();
}
-Future serverRunning(HttpServer server, {bool useKernel}) async {
+Future serverRunning(HttpServer server) async {
int port = server.port;
String inFilePath = "http://127.0.0.1:$port/data/one_line_dart_program.dart";
- List<String> args = [inFilePath, "--out=" + outFilePath];
- if (!useKernel) args.add(Flags.useOldFrontend);
+ List<String> args = [
+ inFilePath,
+ "--out=" + outFilePath,
+ Flags.useOldFrontend
+ ];
server.listen(handleRequest);
try {
@@ -88,22 +93,19 @@
}
}
-Future testHttp({bool useKernel}) {
+Future testHttp() {
return HttpServer
.bind(InternetAddress.LOOPBACK_IP_V4, 0)
- .then((HttpServer server) => serverRunning(server, useKernel: useKernel));
+ .then((HttpServer server) => serverRunning(server));
}
-runTests({bool useKernel}) async {
+runTests() async {
tempDir = Directory.systemTemp.createTempSync('directory_test');
outFilePath = path.join(tempDir.path, "out.js");
try {
- await testFile(useKernel: useKernel);
- if (!useKernel) {
- // TODO(johnniwinther): Handle this test for kernel.
- await testHttp(useKernel: useKernel);
- }
+ await testFile();
+ await testHttp();
} finally {
await tempDir.delete(recursive: true);
}
@@ -111,9 +113,6 @@
main() {
asyncTest(() async {
- print('--test from ast---------------------------------------------------');
- await runTests(useKernel: false);
- print('--test from kernel------------------------------------------------');
- await runTests(useKernel: true);
+ await runTests();
});
}
diff --git a/tests/compiler/dart2js/rti/data/closure.dart b/tests/compiler/dart2js/rti/data/closure.dart
index 6baf68e..7b45cde 100644
--- a/tests/compiler/dart2js/rti/data/closure.dart
+++ b/tests/compiler/dart2js/rti/data/closure.dart
@@ -10,7 +10,8 @@
/*element: A.f:*/
f() {
- return /**/ (int t) {};
+ // TODO(johnniwinther): Optimize local function type signature need.
+ return /*ast.*/ /*kernel.*/ /*strong.needsSignature*/ (int t) {};
}
}
diff --git a/tests/compiler/dart2js/rti/data/closure_unneeded.dart b/tests/compiler/dart2js/rti/data/closure_unneeded.dart
index 5e985bd..5ba4637 100644
--- a/tests/compiler/dart2js/rti/data/closure_unneeded.dart
+++ b/tests/compiler/dart2js/rti/data/closure_unneeded.dart
@@ -4,11 +4,14 @@
import 'package:expect/expect.dart';
-/*class: A:*/
+/*ast.class: A:*/
+/*kernel.class: A:*/
+/*strong.class: A:needsArgs*/
class A<T> {
@NoInline()
m() {
- return /**/ (T t, String s) {};
+ // TODO(johnniwinther): Optimize local function type signature need.
+ return /*ast.*/ /*kernel.*/ /*strong.needsSignature*/ (T t, String s) {};
}
}
diff --git a/tests/compiler/dart2js/rti/data/function_subtype_local5.dart b/tests/compiler/dart2js/rti/data/function_subtype_local5.dart
index 5acd91f..521daf0 100644
--- a/tests/compiler/dart2js/rti/data/function_subtype_local5.dart
+++ b/tests/compiler/dart2js/rti/data/function_subtype_local5.dart
@@ -17,7 +17,10 @@
/*class: C:explicit=[int Function(C.T),int Function(C.T,[String]),int Function(C.T,int),int Function(C.T,{,b:String})],needsArgs*/
class C<T> {
void test(String nameOfT, bool expectedResult) {
+ // TODO(johnniwinther): Optimize local function type signature need.
+ /*ast.*/ /*kernel.*/ /*strong.needsSignature*/
int foo(bool a, [String b]) => null;
+ /*ast.*/ /*kernel.*/ /*strong.needsSignature*/
int baz(bool a, {String b}) => null;
Expect.equals(expectedResult, foo is Foo<T>, 'foo is Foo<$nameOfT>');
diff --git a/tests/compiler/dart2js/rti/data/generic_method_instantiate.dart b/tests/compiler/dart2js/rti/data/generic_method_instantiate.dart
index 1f6c15e..a9fb97fe 100644
--- a/tests/compiler/dart2js/rti/data/generic_method_instantiate.dart
+++ b/tests/compiler/dart2js/rti/data/generic_method_instantiate.dart
@@ -8,7 +8,9 @@
/*class: B:deps=[method],explicit=[B<A>],needsArgs*/
class B<T> {}
-/*element: method:*/
+/*ast.element: method:*/
+/*kernel.element: method:*/
+/*strong.element: method:needsArgs*/
method<T>() => new B<T>();
main() {
diff --git a/tests/compiler/dart2js/rti/data/generic_method_instantiate_strong.dart b/tests/compiler/dart2js/rti/data/generic_method_instantiate_strong.dart
deleted file mode 100644
index 8364623..0000000
--- a/tests/compiler/dart2js/rti/data/generic_method_instantiate_strong.dart
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/*class: A:explicit=[B<A>]*/
-class A {}
-
-/*class: B:deps=[method],explicit=[B<A>],needsArgs*/
-class B<T> {}
-
-/*element: method:needsArgs*/
-method<T>() => new B<T>();
-
-main() {
- method<A>() is B<A>;
-}
diff --git a/tests/compiler/dart2js/rti/data/generic_method_is.dart b/tests/compiler/dart2js/rti/data/generic_method_is.dart
index 4adc872..5478c03 100644
--- a/tests/compiler/dart2js/rti/data/generic_method_is.dart
+++ b/tests/compiler/dart2js/rti/data/generic_method_is.dart
@@ -2,7 +2,9 @@
// 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.
-/*element: method:direct,explicit=[method.T]*/
+/*ast.element: method:direct,explicit=[method.T]*/
+/*kernel.element: method:direct,explicit=[method.T]*/
+/*strong.element: method:direct,explicit=[method.T],needsArgs*/
method<T>(T t) => t is T;
main() {
diff --git a/tests/compiler/dart2js/rti/data/list_to_set.dart b/tests/compiler/dart2js/rti/data/list_to_set.dart
index f858a43..1d86288 100644
--- a/tests/compiler/dart2js/rti/data/list_to_set.dart
+++ b/tests/compiler/dart2js/rti/data/list_to_set.dart
@@ -4,8 +4,11 @@
/*ast.class: global#List:deps=[Class,EmptyIterable,Iterable,JSArray,ListIterable,SetMixin,SubListIterable],explicit=[List],implicit=[List.E],indirect,needsArgs*/
/*kernel.class: global#List:deps=[Class,EmptyIterable,Iterable,JSArray,ListIterable,SetMixin],explicit=[List],implicit=[List.E],indirect,needsArgs*/
+/*strong.class: global#List:deps=[Class,EmptyIterable,Iterable,JSArray,ListIterable,SetMixin],explicit=[List],implicit=[List.E],indirect,needsArgs*/
+
/*ast.class: global#JSArray:deps=[List],explicit=[JSArray],implicit=[JSArray.E],indirect,needsArgs*/
/*kernel.class: global#JSArray:deps=[EmptyIterable,List,ListIterable,SetMixin,SubListIterable],explicit=[JSArray],implicit=[JSArray.E],indirect,needsArgs*/
+/*strong.class: global#JSArray:deps=[EmptyIterable,List,ListIterable,SetMixin,SubListIterable],explicit=[JSArray],implicit=[JSArray.E],indirect,needsArgs*/
main() {
var c = new Class<int>();
diff --git a/tests/compiler/dart2js/rti/emission/function_type_argument_strong.dart b/tests/compiler/dart2js/rti/emission/function_type_argument_strong.dart
new file mode 100644
index 0000000..7b56dde
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/function_type_argument_strong.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+import 'package:meta/dart2js.dart';
+
+/*class: C:checks=[],instance,typeArgument*/
+class C {
+ call(int i) {}
+}
+
+/*class: D:checks=[],instance,typeArgument*/
+class D {
+ call(double i) {}
+}
+
+@noInline
+test1(o) => o is Function(int);
+
+@noInline
+test2(o) => o is List<Function(int)>;
+
+main() {
+ Expect.isFalse(test1(new C()));
+ Expect.isFalse(test1(new D()));
+ Expect.isFalse(test2(<C>[]));
+ Expect.isFalse(test2(<D>[]));
+}
diff --git a/tests/compiler/dart2js/rti/emission/list.dart b/tests/compiler/dart2js/rti/emission/list.dart
index bfcd830..565ea00 100644
--- a/tests/compiler/dart2js/rti/emission/list.dart
+++ b/tests/compiler/dart2js/rti/emission/list.dart
@@ -4,7 +4,10 @@
import 'package:meta/dart2js.dart';
-/*class: global#JSArray:checkedInstance,checks=[$isIterable],instance*/
+/*ast.class: global#JSArray:checkedInstance,checks=[$isIterable],instance*/
+/*kernel.class: global#JSArray:checkedInstance,checks=[$isIterable],instance*/
+/*strong.class: global#JSArray:checkedInstance,checks=[$isIterable,$isList],instance*/
+
/*class: global#Iterable:checkedInstance*/
/*class: A:checkedTypeArgument,checks=[],typeArgument*/
diff --git a/tests/compiler/dart2js/rti/emission/map_literal.dart b/tests/compiler/dart2js/rti/emission/map_literal.dart
index d666180..4df5013 100644
--- a/tests/compiler/dart2js/rti/emission/map_literal.dart
+++ b/tests/compiler/dart2js/rti/emission/map_literal.dart
@@ -2,10 +2,17 @@
// 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.
-/*class: global#Map:instance*/
+/*ast.class: global#Map:instance*/
+/*kernel.class: global#Map:instance*/
+/*strong.class: global#Map:checkedInstance,checks=[],instance*/
+
/*class: global#LinkedHashMap:*/
/*class: global#JsLinkedHashMap:checks=[],instance*/
-/*class: global#double:checks=[],instance,typeArgument*/
+
+/*ast.class: global#double:checks=[],instance,typeArgument*/
+/*kernel.class: global#double:checks=[],instance,typeArgument*/
+/*strong.class: global#double:checkedInstance,checks=[],instance,typeArgument*/
+
/*class: global#JSDouble:checks=[],instance*/
main() {
diff --git a/tests/compiler/dart2js/rti/rti_emission_test.dart b/tests/compiler/dart2js/rti/rti_emission_test.dart
index f7b516b..5408325 100644
--- a/tests/compiler/dart2js/rti/rti_emission_test.dart
+++ b/tests/compiler/dart2js/rti/rti_emission_test.dart
@@ -27,15 +27,24 @@
Directory dataDir =
new Directory.fromUri(Platform.script.resolve('emission'));
await checkTests(
- dataDir, computeAstRtiMemberEmission, computeKernelRtiMemberEmission,
- computeClassDataFromAst: computeAstRtiClassEmission,
- computeClassDataFromKernel: computeKernelRtiClassEmission,
- args: args,
- skipForKernel: [
- // TODO(johnniwinther): Fix this. It triggers a crash in the ssa
- // builder.
- 'runtime_type.dart',
- ]);
+ dataDir,
+ computeAstRtiMemberEmission,
+ computeKernelRtiMemberEmission,
+ computeClassDataFromAst: computeAstRtiClassEmission,
+ computeClassDataFromKernel: computeKernelRtiClassEmission,
+ args: args,
+ skipForStrong: [
+ // Dart 1 semantics:
+ 'call.dart',
+ 'call_typed.dart',
+ 'call_typed_generic.dart',
+ 'function_subtype_call2.dart',
+ 'function_type_argument.dart',
+ 'map_literal_checked.dart',
+ // TODO(johnniwinther): Optimize local function type signature need.
+ 'subtype_named_args.dart',
+ ],
+ );
});
}
diff --git a/tests/compiler/dart2js/rti/rti_need_test.dart b/tests/compiler/dart2js/rti/rti_need_test.dart
index 644acd6..4768628 100644
--- a/tests/compiler/dart2js/rti/rti_need_test.dart
+++ b/tests/compiler/dart2js/rti/rti_need_test.dart
@@ -36,6 +36,12 @@
computeClassDataFromAst: computeAstRtiClassNeed,
computeClassDataFromKernel: computeKernelRtiClassNeed,
options: [Flags.omitImplicitChecks], // only used in strong-mode
+ skipForStrong: [
+ 'map_literal_checked.dart',
+ // TODO(johnniwinther): Optimize local function type signature need.
+ 'subtype_named_args.dart',
+ 'subtype_named_args1.dart',
+ ],
args: args);
});
}
diff --git a/tests/compiler/dart2js_extra/32770a_test.dart b/tests/compiler/dart2js_extra/32770a_test.dart
new file mode 100644
index 0000000..24aeb60
--- /dev/null
+++ b/tests/compiler/dart2js_extra/32770a_test.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// dart2jsOptions=--strong
+
+// Regression test for issue 32770.
+
+import 'package:expect/expect.dart';
+
+dynamic f;
+dynamic g;
+
+class A {}
+
+class B extends A {}
+
+class C extends A {}
+
+class Class<T> {
+ void Function(E) method<E, F extends E>(void Function(F) callback) {
+ return (E event) {
+ g = () => callback(event as F);
+ };
+ }
+}
+
+main() {
+ f = new Class<String>().method<A, B>((o) => print(o));
+ f(new B());
+ g();
+ f(new C());
+ Expect.throws(() => g(), (_) => true);
+}
diff --git a/tests/compiler/dart2js_extra/32770b_test.dart b/tests/compiler/dart2js_extra/32770b_test.dart
new file mode 100644
index 0000000..f58bcf5
--- /dev/null
+++ b/tests/compiler/dart2js_extra/32770b_test.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// dart2jsOptions=--strong
+
+// Regression test for issue 32770.
+
+import 'package:expect/expect.dart';
+
+dynamic f;
+dynamic g;
+
+class A {}
+
+class B extends A {}
+
+class C extends A {}
+
+class Class<T> {
+ void Function(E) method<E, F extends E>(bool Function(bool) callback) {
+ return (E event) {
+ g = () => callback(event is F);
+ };
+ }
+}
+
+main() {
+ f = new Class<String>().method<A, B>((o) => o);
+ f(new B());
+ Expect.isTrue(g());
+ f(new C());
+ Expect.isFalse(g());
+}
diff --git a/tests/compiler/dart2js_extra/32770c_test.dart b/tests/compiler/dart2js_extra/32770c_test.dart
new file mode 100644
index 0000000..15ac166
--- /dev/null
+++ b/tests/compiler/dart2js_extra/32770c_test.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// dart2jsOptions=--strong
+
+// Regression test for issue 32770.
+
+import 'dart:async' show Future;
+
+A<J> futureToA<T, J>(Future<T> future, [J wrapValue(T value)]) {
+ return new A<J>(
+ (void resolveFn(J value), void rejectFn(error)) {
+ future.then((value) {
+ dynamic wrapped;
+ if (wrapValue != null) {
+ wrapped = wrapValue(value);
+ } else if (value != null) {
+ wrapped = value;
+ }
+ resolveFn(wrapped);
+ }).catchError((error) {
+ rejectFn(error);
+ });
+ },
+ );
+}
+
+class A<X> {
+ var x;
+
+ A(this.x);
+}
+
+main() {
+ print(futureToA);
+}
diff --git a/tests/compiler/dart2js/rti/data/generic_method_is_strong.dart b/tests/compiler/dart2js_extra/eof_line_ending_test.dart
similarity index 61%
rename from tests/compiler/dart2js/rti/data/generic_method_is_strong.dart
rename to tests/compiler/dart2js_extra/eof_line_ending_test.dart
index dea3540..dafba6c 100644
--- a/tests/compiler/dart2js/rti/data/generic_method_is_strong.dart
+++ b/tests/compiler/dart2js_extra/eof_line_ending_test.dart
@@ -1,10 +1,10 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/*element: method:direct,explicit=[method.T],needsArgs*/
-method<T>(T t) => t is T;
-
-main() {
- method<int>(0);
-}
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression test derived from language/issue_1578_test.dart with Windows
+// line encoding.
+
+main() {}
+
+]~<)$ //# 01: compile-time error
diff --git a/tests/corelib_2/corelib_2.status b/tests/corelib_2/corelib_2.status
index 90bd0d6..b35abb8 100644
--- a/tests/corelib_2/corelib_2.status
+++ b/tests/corelib_2/corelib_2.status
@@ -213,15 +213,7 @@
[ $compiler == dart2js && $fasta && $host_checked && $strong ]
apply3_test: RuntimeError
-bigint_parse_radix_test: RuntimeError
-bigint_test: RuntimeError
cast_test: RuntimeError
-date_time2_test: RuntimeError
-date_time3_test: RuntimeError
-date_time4_test: RuntimeError
-date_time7_test: RuntimeError
-date_time_parse_test: RuntimeError
-date_time_test: RuntimeError
dynamic_nosuchmethod_test: RuntimeError
error_stack_trace1_test: RuntimeError # Issue 12399
growable_list_test: RuntimeError # Concurrent modifications test always runs
@@ -235,69 +227,14 @@
iterable_return_type_test/01: RuntimeError # Issue 20085
iterable_return_type_test/02: RuntimeError # Dart2js does not support Uint64*.
iterable_to_list_test/01: RuntimeError # Issue 26501
-json_map_test: RuntimeError
list_concurrent_modify_test: RuntimeError # dart2js does not fully implement these
list_test/01: RuntimeError
list_test/none: RuntimeError
list_unmodifiable_test: RuntimeError
main_test: RuntimeError
nan_infinity_test/01: RuntimeError
-reg_exp_all_matches_test: RuntimeError
-reg_exp_cache_test: RuntimeError
-reg_exp_first_match_test: RuntimeError
-reg_exp_group_test: RuntimeError
-reg_exp_groups_test: RuntimeError
-reg_exp_start_end_test: RuntimeError
-reg_exp_string_match_test: RuntimeError
-regexp/UC16_test: RuntimeError
-regexp/alternatives_test: RuntimeError
-regexp/assertion_test: RuntimeError
-regexp/bol-with-multiline_test: RuntimeError
-regexp/bol_test: RuntimeError
-regexp/capture-3_test: RuntimeError
-regexp/capture_test: RuntimeError
-regexp/character-match-out-of-order_test: RuntimeError
-regexp/default_arguments_test: RuntimeError
-regexp/dotstar_test: RuntimeError
-regexp/early-acid3-86_test: RuntimeError
-regexp/ecma-regex-examples_test: RuntimeError
-regexp/extended-characters-match_test: RuntimeError
-regexp/find-first-asserted_test: RuntimeError
-regexp/global_test: RuntimeError
-regexp/indexof_test: RuntimeError
-regexp/invalid-range-in-class_test: RuntimeError
-regexp/lastindex_test: RuntimeError
-regexp/look-ahead_test: RuntimeError
-regexp/lookahead_test: RuntimeError
-regexp/loop-capture_test: RuntimeError
-regexp/many-brackets_test: RuntimeError
-regexp/no-extensions_test: RuntimeError
-regexp/non-bmp_test: RuntimeError
-regexp/non-capturing-backtracking_test: RuntimeError
-regexp/non-capturing-groups_test: RuntimeError
-regexp/non-greedy-parentheses_test: RuntimeError
-regexp/parentheses_test: RuntimeError
-regexp/pcre-test-4_test: RuntimeError
regexp/pcre_test: RuntimeError
-regexp/range-bound-ffff_test: RuntimeError
-regexp/ranges-and-escaped-hyphens_test: RuntimeError
-regexp/regexp_escape_test: RuntimeError
-regexp/regexp_kde_test: RuntimeError
-regexp/regexp_test: RuntimeError
-regexp/regress-regexp-codeflush_test: RuntimeError
-regexp/regress-regexp-construct-result_test: RuntimeError
-regexp/repeat-match-waldemar_test: RuntimeError
-regexp/stack-overflow2_test: RuntimeError
-regexp/stack-overflow_test: RuntimeError
-regexp/standalones_test: RuntimeError
-regexp/unicode-handling_test: RuntimeError
-regexp/zero-length-alternatives_test: RuntimeError
-string_from_list_test: RuntimeError
-string_fromcharcodes_test: RuntimeError
-string_replace_test: RuntimeError
string_split_test/checkedstore: RuntimeError # Issue 30548: does not check stores into List<String>
-string_split_test/none: RuntimeError
-string_test: RuntimeError
symbol_reserved_word_test/03: RuntimeError # Issue 19972, new Symbol('void') should be allowed.
uri_base_test: RuntimeError
uri_parameters_all_test: RuntimeError
@@ -305,15 +242,7 @@
[ $compiler == dart2js && $fasta && $minified && $strong ]
apply3_test: RuntimeError
-bigint_parse_radix_test: RuntimeError
-bigint_test: RuntimeError
cast_test: RuntimeError
-date_time2_test: RuntimeError
-date_time3_test: RuntimeError
-date_time4_test: RuntimeError
-date_time7_test: RuntimeError
-date_time_parse_test: RuntimeError
-date_time_test: RuntimeError
dynamic_nosuchmethod_test: RuntimeError
error_stack_trace1_test: RuntimeError # Issue 12399
growable_list_test: RuntimeError # Concurrent modifications test always runs
@@ -328,7 +257,6 @@
iterable_return_type_test/01: RuntimeError # Issue 20085
iterable_return_type_test/02: RuntimeError # Dart2js does not support Uint64*.
iterable_to_list_test/01: RuntimeError # Issue 26501
-json_map_test: RuntimeError
list_concurrent_modify_test: RuntimeError # dart2js does not fully implement these
list_test/01: RuntimeError
list_test/none: RuntimeError
@@ -336,62 +264,8 @@
main_test: RuntimeError
nan_infinity_test/01: RuntimeError
nsm_invocation_test: RuntimeError # Symbols don't match due to minifiaction.
-reg_exp_all_matches_test: RuntimeError
-reg_exp_cache_test: RuntimeError
-reg_exp_first_match_test: RuntimeError
-reg_exp_group_test: RuntimeError
-reg_exp_groups_test: RuntimeError
-reg_exp_start_end_test: RuntimeError
-reg_exp_string_match_test: RuntimeError
-regexp/UC16_test: RuntimeError
-regexp/alternatives_test: RuntimeError
-regexp/assertion_test: RuntimeError
-regexp/bol-with-multiline_test: RuntimeError
-regexp/bol_test: RuntimeError
-regexp/capture-3_test: RuntimeError
-regexp/capture_test: RuntimeError
-regexp/character-match-out-of-order_test: RuntimeError
-regexp/default_arguments_test: RuntimeError
-regexp/dotstar_test: RuntimeError
-regexp/early-acid3-86_test: RuntimeError
-regexp/ecma-regex-examples_test: RuntimeError
-regexp/extended-characters-match_test: RuntimeError
-regexp/find-first-asserted_test: RuntimeError
-regexp/global_test: RuntimeError
-regexp/indexof_test: RuntimeError
-regexp/invalid-range-in-class_test: RuntimeError
-regexp/lastindex_test: RuntimeError
-regexp/look-ahead_test: RuntimeError
-regexp/lookahead_test: RuntimeError
-regexp/loop-capture_test: RuntimeError
-regexp/many-brackets_test: RuntimeError
-regexp/no-extensions_test: RuntimeError
-regexp/non-bmp_test: RuntimeError
-regexp/non-capturing-backtracking_test: RuntimeError
-regexp/non-capturing-groups_test: RuntimeError
-regexp/non-greedy-parentheses_test: RuntimeError
-regexp/parentheses_test: RuntimeError
-regexp/pcre-test-4_test: RuntimeError
regexp/pcre_test: RuntimeError
-regexp/range-bound-ffff_test: RuntimeError
-regexp/ranges-and-escaped-hyphens_test: RuntimeError
-regexp/regexp_escape_test: RuntimeError
-regexp/regexp_kde_test: RuntimeError
-regexp/regexp_test: RuntimeError
-regexp/regress-regexp-codeflush_test: RuntimeError
-regexp/regress-regexp-construct-result_test: RuntimeError
-regexp/repeat-match-waldemar_test: RuntimeError
-regexp/stack-overflow2_test: RuntimeError
-regexp/stack-overflow_test: RuntimeError
-regexp/standalones_test: RuntimeError
-regexp/unicode-handling_test: RuntimeError
-regexp/zero-length-alternatives_test: RuntimeError
-string_from_list_test: RuntimeError
-string_fromcharcodes_test: RuntimeError
-string_replace_test: RuntimeError
string_split_test/checkedstore: RuntimeError # Issue 30548: does not check stores into List<String>
-string_split_test/none: RuntimeError
-string_test: RuntimeError
symbol_operator_test/03: RuntimeError
symbol_operator_test/none: RuntimeError
symbol_reserved_word_test/03: RuntimeError # Issue 19972, new Symbol('void') should be allowed.
@@ -399,9 +273,6 @@
uri_parameters_all_test: RuntimeError
uri_test: RuntimeError
-[ $compiler == dart2js && $fasta && $strong ]
-shuffle_test: RuntimeError
-
[ $compiler == dart2js && $fasta && !$strong ]
*: SkipByDesign
@@ -755,6 +626,6 @@
[ $hot_reload || $hot_reload_rollback ]
bigint_parse_radix_test: Pass, Timeout # Issue 31659
-bigint_test: Pass, Crash # Issue 31660
+bigint_test: Pass, Slow, Crash # Issue 31660
integer_parsed_mul_div_vm_test: Pass, Slow # Slow
diff --git a/tests/language/language.status b/tests/language/language.status
index 78000d4..523475a 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -314,6 +314,13 @@
assertion_initializer_const_error_test/01: MissingCompileTimeError
assertion_initializer_const_function_error_test/01: MissingCompileTimeError
+# Detection of compile-time errors that are related to constants can't be fully
+# done at the front end, because constants are evaluated at back ends. So, some
+# errors aren't detected by fasta, but reported by back ends as compile-time
+# errors.
+[ $compiler != dart2js && $runtime != vm && $fasta ]
+deferred_constraints_constants_test/default_argument2: MissingCompileTimeError
+
[ $compiler != dartk && $compiler != dartkp && ($runtime == dart_precompiled || $runtime == flutter || $runtime == vm) ]
abstract_beats_arguments2_test/01: Crash # Issue 29171
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 25c60c3..31043ca 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -63,6 +63,12 @@
named_parameters3_test: RuntimeError
named_parameters4_test: RuntimeError
+[ $compiler == dart2js && $system == windows && $fasta ]
+deep_nesting2_negative_test: Pass, Crash
+illegal_declaration_test/01: Pass, Crash
+issue1578_negative_test: Pass, Crash
+regress_23051_test/01: Pass, Crash
+
[ $compiler == dart2js && $system == windows && !$fasta && ($runtime == chrome || $runtime == ff) ]
string_literals_test: RuntimeError # Issue 27533
diff --git a/tests/language/language_kernel.status b/tests/language/language_kernel.status
index 4eb9408..89fe0d9 100644
--- a/tests/language/language_kernel.status
+++ b/tests/language/language_kernel.status
@@ -3,6 +3,8 @@
# BSD-style license that can be found in the LICENSE file.
[ $compiler == fasta ]
+function_type_parameter2_negative_test: Fail
+function_type_parameter_negative_test: Fail
prefix5_negative_test: Fail
[ $fasta ]
diff --git a/tests/language_2/assertion_initializer_const_error2_test.dart b/tests/language_2/assertion_initializer_const_error2_test.dart
index e406b4a..dd152a3 100644
--- a/tests/language_2/assertion_initializer_const_error2_test.dart
+++ b/tests/language_2/assertion_initializer_const_error2_test.dart
@@ -2,6 +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.
// VMOptions=--assert_initializer
+// dart2jsOptions=--enable-asserts
//
// Test of asserts in initializer lists.
diff --git a/tests/language_2/const_cast1_test.dart b/tests/language_2/const_cast1_test.dart
new file mode 100644
index 0000000..2363f3f
--- /dev/null
+++ b/tests/language_2/const_cast1_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Implicit casts in constants are supported and treated as compile-time errors
+/// if they are not valid.
+
+class A {
+ final int n;
+ const A(dynamic input) : n = input;
+}
+
+main() {
+ print(const A(2)); //# 01: ok
+ print(const A('2')); //# 02: compile-time error
+}
diff --git a/tests/language_2/const_cast2_test.dart b/tests/language_2/const_cast2_test.dart
new file mode 100644
index 0000000..326a884
--- /dev/null
+++ b/tests/language_2/const_cast2_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Explicit casts in constants are supported and treated as compile-time errors
+/// if they are not valid.
+
+class A {
+ final int n;
+ const A(dynamic input) : n = input as int;
+}
+
+main() {
+ print(const A(2)); //# 01: ok
+ print(const A('2')); //# 02: compile-time error
+}
diff --git a/tests/language_2/const_cast3_test.dart b/tests/language_2/const_cast3_test.dart
new file mode 100644
index 0000000..f7d7354
--- /dev/null
+++ b/tests/language_2/const_cast3_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Casts in constants correctly substitute type variables.
+
+class A {
+ const A();
+}
+
+class B implements A {
+ const B();
+}
+
+class M<T extends A> {
+ final T a;
+ const M(dynamic t) : a = t; // adds implicit cast `as T`
+}
+
+main() {
+ print(const M<B>(const B()));
+}
diff --git a/tests/language_2/implicit_creation/implicit_new_or_const_composite_test.dart b/tests/language_2/implicit_creation/implicit_new_or_const_composite_test.dart
index 54092f7..1a7debe 100644
--- a/tests/language_2/implicit_creation/implicit_new_or_const_composite_test.dart
+++ b/tests/language_2/implicit_creation/implicit_new_or_const_composite_test.dart
@@ -29,12 +29,12 @@
const cd1 = const C(const D<int>(42));
const cd2 = C(D<int>(42)); // Const context.
- var cd3 = C(D<int>(42)); // All constant, even in non-const context.
- var cd4 = C(D<int>(x)); // x is a non-constant expression, so `new`.
- var cd5 = C(d42); // d42 is a non-constant expression, so `new`.
+ var cd3 = C(D<int>(42)); // Non-constant context, so `new`.
+ var cd4 = C(D<int>(x)); // Non-constant context, so `new`.
+ var cd5 = C(d42); // Non-constant context, so `new`.
Expect.identical(cd1, cd2);
- Expect.identical(cd1, cd3);
+ Expect.allDistinct([cd1, cd3]);
Expect.allDistinct([cd1, cd4, cd5]);
}
@@ -44,16 +44,16 @@
const cl2 = C(clist); // Constant context.
const cl3 = C(const <int>[37]); // Constant context.
const cl4 = C(<int>[37]);
- var cl5 = C(clist); // Constant argument, so const.
- var cl6 = C(const <int>[37]); // Constant arg, so const.
- var cl7 = C(list); // Non-constant arg.
- var cl8 = C(<int>[37]); // Same if literal.
+ var cl5 = C(clist); // Non-constant context, so `new`.
+ var cl6 = C(const <int>[37]); // Non-constant context, so `new`.
+ var cl7 = C(list); // Non-constant context, so `new`.
+ var cl8 = C(<int>[37]); // Non-constant context, so `new`.
Expect.identical(cl1, cl2);
Expect.identical(cl1, cl3);
Expect.identical(cl1, cl4);
- Expect.identical(cl1, cl5);
- Expect.identical(cl1, cl6);
+ Expect.allDistinct([cl1, cl5]);
+ Expect.allDistinct([cl1, cl6]);
Expect.allDistinct([cl1, cl7, cl8]);
}
@@ -62,15 +62,15 @@
const cm1 = C(cmap); // Constant context.
const cm2 = C(const <int, int>{19: 87}); // Constant context.
const cm3 = C(<int, int>{19: 87}); // Constant context.
- var cm4 = C(cmap); // Constant argument, so const.
- var cm5 = C(const <int, int>{19: 87}); // Constant arg, so const.
- var cm6 = C(map); // Non-constant arg, non-const context.
- var cm7 = C(<int, int>{19: 87}); // Same if literal.
+ var cm4 = C(cmap); // Non-constant context, so `new`.
+ var cm5 = C(const <int, int>{19: 87}); // Non-constant context, so `new`.
+ var cm6 = C(map); // Non-constant context, so `new`.
+ var cm7 = C(<int, int>{19: 87}); // Non-constant context, so `new`.
Expect.identical(cm1, cm2);
Expect.identical(cm1, cm3);
- Expect.identical(cm1, cm4);
- Expect.identical(cm1, cm5);
+ Expect.allDistinct([cm1, cm4]);
+ Expect.allDistinct([cm1, cm5]);
Expect.allDistinct([cm1, cm6, cm7]);
}
@@ -93,8 +93,8 @@
Expect.identical(n1, n2);
Expect.identical(n1, n3);
- Expect.identical(n1, n4);
- Expect.identical(n1, n8);
+ Expect.allDistinct([n1, n4]);
+ Expect.allDistinct([n1, n8]);
Expect.allDistinct([n1, n5, n6, n7, n9, n10, n11, n12, n13, n14]);
Expect.identical(clist, n6.left);
@@ -128,12 +128,12 @@
Expect.identical(n20, n22);
Expect.identical(n20, n23);
Expect.identical(n20, n24);
- Expect.identical(n20, n25);
- Expect.identical(n20, n26);
- Expect.identical(n20, n27);
+ Expect.allDistinct([n20, n25]);
+ Expect.allDistinct([n20, n26]);
+ Expect.allDistinct([n20, n27]);
Expect.allDistinct([n28, n29, n30, n31]);
- Expect.identical(cc42, n28.left);
- Expect.identical(cc42, n29.left);
+ Expect.allDistinct([cc42, n28.left]);
+ Expect.allDistinct([cc42, n29.left]);
Expect.identical(cc42, n30.left);
Expect.identical(cc42, n31.left);
Expect.identical(clist, n29.right);
@@ -185,10 +185,10 @@
// List literals are never const unless in const context.
Expect.allDistinct([l20, l25, l26, l27, l28, l29, l30, l31]);
Expect.identical(cc42, l25[0]);
- Expect.identical(cc42, l26[0]);
- Expect.identical(cc42, l27[0]);
- Expect.identical(cc42, l28[0]);
- Expect.identical(cc42, l29[0]);
+ Expect.allDistinct([cc42, l26[0]]);
+ Expect.allDistinct([cc42, l27[0]]);
+ Expect.allDistinct([cc42, l28[0]]);
+ Expect.allDistinct([cc42, l29[0]]);
Expect.identical(cc42, l30[0]);
Expect.identical(cc42, l31[0]);
Expect.identical(clist, l25[1]);
@@ -236,10 +236,10 @@
// Map literals are never const unless in const context.
Expect.allDistinct([m20, m25, m26, m27, m28, m29, m30, m31]);
Expect.identical(cc42, m25.keys.first);
- Expect.identical(cc42, m26.keys.first);
- Expect.identical(cc42, m27.keys.first);
- Expect.identical(cc42, m28.keys.first);
- Expect.identical(cc42, m29.keys.first);
+ Expect.allDistinct([cc42, m26.keys.first]);
+ Expect.allDistinct([cc42, m27.keys.first]);
+ Expect.allDistinct([cc42, m28.keys.first]);
+ Expect.allDistinct([cc42, m29.keys.first]);
Expect.identical(cc42, m30.keys.first);
Expect.identical(cc42, m31.keys.first);
Expect.identical(clist, m25.values.first);
diff --git a/tests/language_2/implicit_creation/implicit_new_or_const_generic_test.dart b/tests/language_2/implicit_creation/implicit_new_or_const_generic_test.dart
index 1f58aa5..ab9f148 100644
--- a/tests/language_2/implicit_creation/implicit_new_or_const_generic_test.dart
+++ b/tests/language_2/implicit_creation/implicit_new_or_const_generic_test.dart
@@ -72,7 +72,7 @@
for (var i = 0; i < instances.length; i++) {
var d = instances[i];
Expect.equals(d42, d);
- if (i % 5 == 2 || i % 5 == 4) {
+ if (i % 5 == 2) {
// The cases of D(42) without "new" are all constant.
Expect.identical(d42, d, "$i");
} else {
diff --git a/tests/language_2/implicit_creation/implicit_new_or_const_test.dart b/tests/language_2/implicit_creation/implicit_new_or_const_test.dart
index 3a0a7b0..00c8ae3 100644
--- a/tests/language_2/implicit_creation/implicit_new_or_const_test.dart
+++ b/tests/language_2/implicit_creation/implicit_new_or_const_test.dart
@@ -43,11 +43,9 @@
for (var i = 0; i < instances.length; i++) {
var c = instances[i];
Expect.equals(c42, c);
- if (i % 5 == 2 || i % 5 == 4) {
- // The cases of C(42) without "new" are all constant.
+ if (i % 5 == 2) {
Expect.identical(c42, c, "$i");
} else {
- // The rest are not.
Expect.notIdentical(c42, c, "$i");
}
}
diff --git a/tests/language_2/language_2.status b/tests/language_2/language_2.status
index 8cb9983..c746cd0 100644
--- a/tests/language_2/language_2.status
+++ b/tests/language_2/language_2.status
@@ -47,6 +47,25 @@
[ $compiler != dart2js && $compiler != dartdevc && !$fasta && $strong ]
type_promotion_functions_test: CompileTimeError # Issue 30895: This test requires a complete rewrite for 2.0.
+# Detection of compile-time errors that are related to constants can't be fully
+# done at the front end, because constants are evaluated at back ends. So, some
+# errors aren't detected by fasta, but reported by back ends as compile-time
+# errors.
+[ $compiler != dart2js && $runtime != dart_precompiled && $runtime != vm && $fasta ]
+deferred_constraints_constants_test/default_argument2: MissingCompileTimeError
+function_type_parameter2_negative_test: Fail
+function_type_parameter_negative_test: Fail
+implicit_creation/implicit_const_not_default_values_test/e12: MissingCompileTimeError
+implicit_creation/implicit_const_not_default_values_test/e15: MissingCompileTimeError
+implicit_creation/implicit_const_not_default_values_test/e18: MissingCompileTimeError
+implicit_creation/implicit_const_not_default_values_test/e21: MissingCompileTimeError
+implicit_creation/implicit_const_not_default_values_test/e24: MissingCompileTimeError
+implicit_creation/implicit_const_not_default_values_test/e27: MissingCompileTimeError
+implicit_creation/implicit_const_not_default_values_test/e3: MissingCompileTimeError
+implicit_creation/implicit_const_not_default_values_test/e30: MissingCompileTimeError
+implicit_creation/implicit_const_not_default_values_test/e6: MissingCompileTimeError
+implicit_creation/implicit_const_not_default_values_test/e9: MissingCompileTimeError
+
[ $compiler != dart2js && !$fasta && $strong ]
compile_time_constant_static5_test/11: CompileTimeError # Issue 30546
compile_time_constant_static5_test/16: CompileTimeError # Issue 30546
diff --git a/tests/language_2/language_2_analyzer.status b/tests/language_2/language_2_analyzer.status
index 7294e48..78aa5bd 100644
--- a/tests/language_2/language_2_analyzer.status
+++ b/tests/language_2/language_2_analyzer.status
@@ -13,6 +13,8 @@
cascade_test/none: Fail # Issue 11577
config_import_corelib_test: StaticWarning, OK
conflicting_type_variable_and_setter_test: CompileTimeError # Issue 25525
+const_cast2_test/01: CompileTimeError
+const_cast2_test/none: CompileTimeError
const_for_in_variable_test/01: MissingCompileTimeError # Issue 25161
constructor_call_wrong_argument_count_negative_test: Fail # Issue 11585
deep_nesting1_negative_test: CompileTimeError # Issue 25558
@@ -721,6 +723,7 @@
check_member_static_test/01: MissingCompileTimeError
check_method_override_test/01: MissingCompileTimeError
check_method_override_test/02: MissingCompileTimeError
+const_cast1_test/02: MissingCompileTimeError
const_constructor2_test/13: MissingCompileTimeError
const_constructor2_test/14: MissingCompileTimeError
const_constructor2_test/15: MissingCompileTimeError
diff --git a/tests/language_2/language_2_dart2js.status b/tests/language_2/language_2_dart2js.status
index 9099b15..716c75e 100644
--- a/tests/language_2/language_2_dart2js.status
+++ b/tests/language_2/language_2_dart2js.status
@@ -249,8 +249,6 @@
const_constructor2_test/20: MissingCompileTimeError
const_constructor2_test/22: MissingCompileTimeError
const_constructor2_test/24: MissingCompileTimeError
-const_constructor3_test/02: MissingCompileTimeError
-const_constructor3_test/04: MissingCompileTimeError
const_dynamic_type_literal_test/02: MissingCompileTimeError
const_error_multiply_initialized_test/02: MissingCompileTimeError
const_error_multiply_initialized_test/04: MissingCompileTimeError
@@ -548,7 +546,6 @@
covariance_field_test/03: RuntimeError
covariance_field_test/04: RuntimeError
covariance_field_test/05: RuntimeError
-recursive_mixin_test: RuntimeError # no check without --checked
[ $compiler == dart2js && !$checked && !$enable_asserts ]
assertion_test: RuntimeError, OK
@@ -595,7 +592,6 @@
vm/reflect_core_vm_test: Fail # mirrors not supported
[ $compiler == dart2js && $fast_startup && $fasta && $strong ]
-assertion_initializer_const_error2_test/none: CompileTimeError
assertion_initializer_const_function_test/01: MissingCompileTimeError
assertion_test: RuntimeError
async_star_cancel_while_paused_test: RuntimeError
@@ -666,8 +662,6 @@
const_constructor2_test/20: MissingCompileTimeError
const_constructor2_test/22: MissingCompileTimeError
const_constructor2_test/24: MissingCompileTimeError
-const_constructor3_test/02: MissingCompileTimeError
-const_constructor3_test/04: MissingCompileTimeError
const_dynamic_type_literal_test/02: MissingCompileTimeError
const_error_multiply_initialized_test/02: MissingCompileTimeError
const_error_multiply_initialized_test/04: MissingCompileTimeError
@@ -1034,17 +1028,14 @@
mixin_type_parameter_inference_test/13: CompileTimeError
mixin_type_parameter_inference_test/16: CompileTimeError
mixin_type_parameter_inference_test/none: CompileTimeError
-partial_tearoff_instantiation_test/02: CompileTimeError
-partial_tearoff_instantiation_test/04: CompileTimeError
partial_tearoff_instantiation_test/05: Pass # for the wrong reason.
partial_tearoff_instantiation_test/06: Pass # for the wrong reason.
partial_tearoff_instantiation_test/07: Pass # for the wrong reason.
partial_tearoff_instantiation_test/08: Pass # for the wrong reason.
-partial_tearoff_instantiation_test/none: CompileTimeError
-type_alias_equality_test/01: RuntimeError # Issue 31359
-type_alias_equality_test/02: RuntimeError # Issue 31359
-type_alias_equality_test/03: RuntimeError # Issue 31359
-type_alias_equality_test/04: RuntimeError # Issue 31359
+type_alias_equality_test/01: RuntimeError # Issue 32784
+type_alias_equality_test/02: RuntimeError # Issue 32784
+type_alias_equality_test/03: RuntimeError # Issue 32784
+type_alias_equality_test/04: RuntimeError # Issue 32784
[ $compiler == dart2js && $fasta && $host_checked && $strong ]
abstract_factory_constructor_test/00: MissingCompileTimeError
@@ -1054,8 +1045,6 @@
abstract_syntax_test/00: MissingCompileTimeError
additional_interface_adds_optional_args_concrete_subclass_test: MissingCompileTimeError
additional_interface_adds_optional_args_concrete_test: MissingCompileTimeError
-assertion_initializer_const_error2_test/none: CompileTimeError
-assertion_initializer_test: CompileTimeError
assertion_test: RuntimeError
async_await_test/02: RuntimeError
async_await_test/03: RuntimeError
@@ -1111,8 +1100,6 @@
closure_invoked_through_interface_target_field_test: MissingCompileTimeError
closure_invoked_through_interface_target_getter_test: MissingCompileTimeError
closure_self_reference_test: Crash # 'file:*/pkg/compiler/lib/src/ssa/nodes.dart': Failed assertion: line 641 pos 12: 'isClosed()': is not true.
-compile_time_constant_d_test: CompileTimeError
-compile_time_constant_e_test: CompileTimeError
compile_time_constant_k_test/01: MissingCompileTimeError
compile_time_constant_k_test/02: MissingCompileTimeError
compile_time_constant_k_test/03: MissingCompileTimeError
@@ -1127,9 +1114,6 @@
conditional_rewrite_test: RuntimeError
config_import_corelib_test: CompileTimeError
config_import_test: RuntimeError
-const_constructor2_test/11: CompileTimeError
-const_constructor2_test/12: CompileTimeError
-const_constructor3_test/03: CompileTimeError
const_dynamic_type_literal_test/02: MissingCompileTimeError
const_evaluation_test/01: RuntimeError
const_instance_field_test/01: MissingCompileTimeError
@@ -1137,8 +1121,6 @@
const_map2_test/00: MissingCompileTimeError
const_map3_test/00: MissingCompileTimeError
const_map4_test: RuntimeError
-const_map_test: RuntimeError
-const_redirecting_factory_test: CompileTimeError
const_switch2_test/01: MissingCompileTimeError
const_switch_test/02: RuntimeError, OK # constant identity based on JS constants
const_switch_test/04: RuntimeError, OK # constant identity based on JS constants
@@ -1150,13 +1132,11 @@
constructor_redirect1_negative_test/01: Crash # Stack Overflow
constructor_redirect2_negative_test: Crash # Issue 30856
constructor_redirect_test/01: Crash # Assertion failure: Cannot find value Instance of 'ThisLocal' in (local(A.named2#x), local(A.named2#y), local(A.named2#z)) for j:constructor(A.named2).
-constructor_redirect_test/none: CompileTimeError
covariance_type_parameter_test/01: RuntimeError
covariance_type_parameter_test/02: RuntimeError
covariance_type_parameter_test/03: RuntimeError
covariant_override/tear_off_type_test: RuntimeError
covariant_subtyping_test: CompileTimeError
-ct_const_test: CompileTimeError
cyclic_constructor_test/01: Crash # Issue 30856
cyclic_type_test/00: RuntimeError
cyclic_type_test/02: RuntimeError
@@ -1327,7 +1307,6 @@
library_env_test/has_mirror_support: RuntimeError
library_env_test/has_no_html_support: RuntimeError
library_env_test/has_no_io_support: RuntimeError
-library_prefixes_test: CompileTimeError
local_function2_test/none: RuntimeError
local_function3_test/none: RuntimeError
local_function_test/none: RuntimeError
@@ -1543,22 +1522,16 @@
override_inheritance_no_such_method_test/13: MissingCompileTimeError
override_method_with_field_test/01: MissingCompileTimeError
parser_quirks_test: CompileTimeError
-partial_tearoff_instantiation_test/02: Crash # Assertion failure: kind=special,memberName=instantiate,callStructure:CallStructure(arity=0, types=1)
-partial_tearoff_instantiation_test/04: Crash # Assertion failure: kind=special,memberName=instantiate,callStructure:CallStructure(arity=0, types=1)
partial_tearoff_instantiation_test/05: Crash # Assertion failure: kind=special,memberName=instantiate,callStructure:CallStructure(arity=0, types=1)
partial_tearoff_instantiation_test/06: Crash # Assertion failure: kind=special,memberName=instantiate,callStructure:CallStructure(arity=0, types=1)
partial_tearoff_instantiation_test/07: Crash # Assertion failure: kind=special,memberName=instantiate,callStructure:CallStructure(arity=0, types=1)
partial_tearoff_instantiation_test/08: Crash # Assertion failure: kind=special,memberName=instantiate,callStructure:CallStructure(arity=0, types=1)
-partial_tearoff_instantiation_test/none: Crash # Assertion failure: kind=special,memberName=instantiate,callStructure:CallStructure(arity=0, types=1)
prefix5_negative_test: Crash # 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart': Failed assertion: line 441 pos 16: 'identical(combiner.arguments.positional[0], rhs)': is not true.
redirecting_factory_default_values_test/01: MissingCompileTimeError
redirecting_factory_default_values_test/02: MissingCompileTimeError
redirecting_factory_infinite_steps_test/01: MissingCompileTimeError
redirecting_factory_malbounded_test/01: MissingCompileTimeError
redirecting_factory_reflection_test: RuntimeError
-reg_ex2_test: RuntimeError
-reg_exp2_test: RuntimeError
-reg_exp_test: RuntimeError
regress_13462_1_test: RuntimeError
regress_18535_test: RuntimeError
regress_22443_test: RuntimeError
@@ -1747,8 +1720,6 @@
abstract_syntax_test/00: MissingCompileTimeError
additional_interface_adds_optional_args_concrete_subclass_test: MissingCompileTimeError
additional_interface_adds_optional_args_concrete_test: MissingCompileTimeError
-assertion_initializer_const_error2_test/none: CompileTimeError
-assertion_initializer_test: CompileTimeError
assertion_test: RuntimeError
async_await_test/02: RuntimeError
async_await_test/03: RuntimeError
@@ -1802,8 +1773,6 @@
class_literal_static_test/07: MissingCompileTimeError
closure_invoked_through_interface_target_field_test: MissingCompileTimeError
closure_invoked_through_interface_target_getter_test: MissingCompileTimeError
-compile_time_constant_d_test: CompileTimeError
-compile_time_constant_e_test: CompileTimeError
compile_time_constant_k_test/01: MissingCompileTimeError
compile_time_constant_k_test/02: MissingCompileTimeError
compile_time_constant_k_test/03: MissingCompileTimeError
@@ -1818,9 +1787,6 @@
conditional_rewrite_test: RuntimeError
config_import_corelib_test: CompileTimeError
config_import_test: RuntimeError
-const_constructor2_test/11: CompileTimeError
-const_constructor2_test/12: CompileTimeError
-const_constructor3_test/03: CompileTimeError
const_dynamic_type_literal_test/02: MissingCompileTimeError
const_evaluation_test/01: RuntimeError
const_instance_field_test/01: MissingCompileTimeError
@@ -1828,8 +1794,6 @@
const_map2_test/00: MissingCompileTimeError
const_map3_test/00: MissingCompileTimeError
const_map4_test: RuntimeError
-const_map_test: RuntimeError
-const_redirecting_factory_test: CompileTimeError
const_switch2_test/01: MissingCompileTimeError
const_switch_test/02: RuntimeError, OK # constant identity based on JS constants
const_switch_test/04: RuntimeError, OK # constant identity based on JS constants
@@ -1841,13 +1805,11 @@
constructor_redirect1_negative_test/01: Crash # Stack Overflow
constructor_redirect2_negative_test: Crash # Issue 30856
constructor_redirect_test/01: Crash # Assertion failure: Cannot find value Instance of 'ThisLocal' in (local(A.named2#x), local(A.named2#y), local(A.named2#z)) for j:constructor(A.named2).
-constructor_redirect_test/none: CompileTimeError
covariance_type_parameter_test/01: RuntimeError
covariance_type_parameter_test/02: RuntimeError
covariance_type_parameter_test/03: RuntimeError
covariant_override/tear_off_type_test: RuntimeError
covariant_subtyping_test: CompileTimeError
-ct_const_test: CompileTimeError
cyclic_constructor_test/01: Crash # Issue 30856
cyclic_type_variable_test/01: MissingCompileTimeError
cyclic_type_variable_test/02: MissingCompileTimeError
@@ -2012,7 +1974,6 @@
library_env_test/has_mirror_support: RuntimeError
library_env_test/has_no_html_support: RuntimeError
library_env_test/has_no_io_support: RuntimeError
-library_prefixes_test: CompileTimeError
local_function2_test/none: RuntimeError
local_function3_test/none: RuntimeError
local_function_test/none: RuntimeError
@@ -2236,9 +2197,6 @@
redirecting_factory_infinite_steps_test/01: MissingCompileTimeError
redirecting_factory_malbounded_test/01: MissingCompileTimeError
redirecting_factory_reflection_test: RuntimeError
-reg_ex2_test: RuntimeError
-reg_exp2_test: RuntimeError
-reg_exp_test: RuntimeError
regress_13462_1_test: RuntimeError
regress_18535_test: RuntimeError
regress_21795_test: RuntimeError # Issue 12605
@@ -2363,8 +2321,8 @@
wrong_number_type_arguments_test/none: Pass
[ $compiler == dart2js && $fasta && $strong ]
-mixin_type_parameter5_test: RuntimeError
-mixin_type_parameter6_test: RuntimeError
+const_constructor3_test/04: MissingCompileTimeError # OK - Subtype check uses JS number semantics.
+ct_const_test: RuntimeError
[ $compiler == dart2js && $fasta && !$strong ]
*: SkipByDesign
diff --git a/tests/language_2/language_2_dartdevc.status b/tests/language_2/language_2_dartdevc.status
index 823ef0b..f1d8960 100644
--- a/tests/language_2/language_2_dartdevc.status
+++ b/tests/language_2/language_2_dartdevc.status
@@ -28,6 +28,8 @@
conflicting_generic_interfaces_hierarchy_loop_infinite_test: Skip # Crashes or times out
conflicting_generic_interfaces_simple_test: MissingCompileTimeError
conflicting_type_variable_and_setter_test: CompileTimeError
+const_cast2_test/01: CompileTimeError
+const_cast2_test/none: CompileTimeError
const_evaluation_test/01: RuntimeError # Issue 29920
const_for_in_variable_test/01: MissingCompileTimeError
const_types_test/07: MissingCompileTimeError
@@ -68,8 +70,6 @@
implicit_creation/implicit_const_context_constructor_generic_test: CompileTimeError
implicit_creation/implicit_const_context_prefix_constructor_generic_named_test: CompileTimeError
implicit_creation/implicit_const_context_prefix_constructor_generic_test: CompileTimeError
-implicit_creation/implicit_new_or_const_composite_test: RuntimeError
-implicit_creation/implicit_new_or_const_generic_test: RuntimeError
implicit_downcast_during_compound_assignment_test: RuntimeError
implicit_downcast_during_indexed_compound_assignment_test: RuntimeError
implicit_downcast_during_indexed_if_null_assignment_test: RuntimeError
@@ -181,10 +181,10 @@
truncdiv_test: RuntimeError # Issue 29920
try_catch_on_syntax_test/10: MissingCompileTimeError
try_catch_on_syntax_test/11: MissingCompileTimeError
-type_alias_equality_test/01: RuntimeError # Issue 31359
-type_alias_equality_test/02: RuntimeError # Issue 31359
-type_alias_equality_test/03: RuntimeError # Issue 31359
-type_alias_equality_test/04: RuntimeError # Issue 31359
+type_alias_equality_test/01: RuntimeError # Issue 32785
+type_alias_equality_test/02: RuntimeError # Issue 32785
+type_alias_equality_test/03: RuntimeError # Issue 32785
+type_alias_equality_test/04: RuntimeError # Issue 32785
type_inference_circularity_test: MissingCompileTimeError
type_inference_inconsistent_inheritance_test: MissingCompileTimeError
type_promotion_functions_test/02: CompileTimeError # Issue 30895
@@ -343,6 +343,7 @@
conditional_import_string_test: CompileTimeError # Test is broken
conditional_import_test: CompileTimeError # Test is broken
config_import_test: CompileTimeError
+const_cast1_test/02: MissingCompileTimeError
const_constructor3_test/04: MissingCompileTimeError
const_constructor_nonconst_field_test/01: MissingCompileTimeError
const_dynamic_type_literal_test/02: MissingCompileTimeError
@@ -401,6 +402,8 @@
function_call_generic_test: RuntimeError # Issue 32756. Crashes on dsend
function_propagation_test: RuntimeError
function_subtype_closure0_test: RuntimeError # Expect.throws(TypeError) fails: Did not throw
+function_type_parameter2_negative_test: Fail
+function_type_parameter_negative_test: Fail
generic_function_bounds_test: RuntimeError
generic_methods_generic_function_result_test/01: MissingCompileTimeError
generic_methods_recursive_bound_test/02: MissingCompileTimeError
@@ -655,7 +658,7 @@
syntax_test/33: MissingCompileTimeError
tearoff_dynamic_test: RuntimeError # Issue 32194
try_catch_test/01: MissingCompileTimeError
-type_alias_equality_test/02: RuntimeError # Issue 31359
+type_alias_equality_test/02: RuntimeError # Issue 32785
type_literal_test: RuntimeError # Expect.equals(expected: <Func>, actual: <(bool) => int>) fails.
type_promotion_functions_test/02: CompileTimeError # Issue 31537
type_promotion_functions_test/03: CompileTimeError # Issue 31537
diff --git a/tests/language_2/language_2_kernel.status b/tests/language_2/language_2_kernel.status
index e5a5738..73d5031 100644
--- a/tests/language_2/language_2_kernel.status
+++ b/tests/language_2/language_2_kernel.status
@@ -29,6 +29,7 @@
assertion_initializer_const_error2_test/cc08: MissingCompileTimeError
assertion_initializer_const_error2_test/cc09: MissingCompileTimeError
assertion_initializer_const_error2_test/cc10: MissingCompileTimeError
+const_cast1_test/02: MissingCompileTimeError
generic_test/01: MissingCompileTimeError
implicit_creation/implicit_const_not_default_values_test/e1: MissingCompileTimeError
implicit_creation/implicit_const_not_default_values_test/e10: MissingCompileTimeError
@@ -74,6 +75,8 @@
closure_invoked_through_interface_target_getter_test: MissingCompileTimeError
compile_time_constant_o_test/01: MissingCompileTimeError
compile_time_constant_o_test/02: MissingCompileTimeError
+const_cast2_test/01: CompileTimeError
+const_cast2_test/none: CompileTimeError
const_dynamic_type_literal_test/02: MissingCompileTimeError
const_instance_field_test/01: MissingCompileTimeError # Fasta bug: Const instance field. Issue 32326.
const_map2_test/00: MissingCompileTimeError # KernelVM bug: Constant evaluation.
@@ -112,11 +115,6 @@
identical_const_test/02: MissingCompileTimeError
identical_const_test/03: MissingCompileTimeError
identical_const_test/04: MissingCompileTimeError
-implicit_creation/implicit_const_context_constructor_generic_named_test: CompileTimeError
-implicit_creation/implicit_const_context_prefix_constructor_generic_named_test: CompileTimeError
-implicit_creation/implicit_new_constructor_generic_named_test: CompileTimeError
-implicit_creation/implicit_new_or_const_generic_test: CompileTimeError
-implicit_creation/implicit_new_prefix_constructor_generic_named_test: CompileTimeError
implicit_this_test/01: MissingCompileTimeError
implicit_this_test/04: MissingCompileTimeError
issue31596_override_test/07: MissingCompileTimeError
@@ -664,7 +662,6 @@
generic_tearoff_test: CompileTimeError
generic_tearoff_test: RuntimeError
if_null_evaluation_order_test: Pass
-implicit_creation/implicit_new_constructor_generic_test: Pass
initializing_formal_type_annotation_test/01: MissingCompileTimeError
initializing_formal_type_annotation_test/02: MissingCompileTimeError
instantiate_tearoff_of_call_test: CompileTimeError
@@ -777,7 +774,6 @@
assertion_initializer_const_error2_test/cc11: MissingCompileTimeError # Not reporting failed assert() at compile time.
redirecting_factory_reflection_test: RuntimeError
-
# Enabling of dartk for sim{arm,arm64,dbc64} revelaed these test failures, which
# are to be triaged. Isolate tests are skipped on purpose due to the usage of
# batch mode.
@@ -1008,7 +1004,6 @@
getter_override_test/02: MissingCompileTimeError # Issue 32613: override check is missing in CFE.
hello_dart_test: Skip # Incompatible flag: --compile_all
implicit_closure_test: Skip # Incompatible flag: --use_slow_path
-implicit_creation/implicit_new_constructor_generic_test: Pass
implicit_downcast_during_assignment_test: Pass # Correctly passes.
implicit_downcast_during_combiner_test: Pass # Correctly passes.
implicit_downcast_during_compound_assignment_test: Pass # Correctly passes.
diff --git a/tests/language_2/language_2_vm.status b/tests/language_2/language_2_vm.status
index a41c57f..cfbf354 100644
--- a/tests/language_2/language_2_vm.status
+++ b/tests/language_2/language_2_vm.status
@@ -1341,10 +1341,10 @@
nosuchmethod_forwarding/nosuchmethod_forwarding_arguments_test: RuntimeError
nsm5_test: MissingCompileTimeError
override_inheritance_no_such_method_test/05: MissingCompileTimeError
-type_alias_equality_test/01: RuntimeError # Issue 31359
-type_alias_equality_test/02: RuntimeError # Issue 31359
-type_alias_equality_test/03: RuntimeError # Issue 31359
-type_alias_equality_test/04: RuntimeError # Issue 31359
+type_alias_equality_test/01: RuntimeError # Issue 32783
+type_alias_equality_test/02: RuntimeError # Issue 32783
+type_alias_equality_test/03: RuntimeError # Issue 32783
+type_alias_equality_test/04: RuntimeError # Issue 32783
[ $compiler == none && $runtime == vm && !$checked ]
assertion_initializer_const_error_test/01: MissingCompileTimeError
@@ -1353,6 +1353,9 @@
generic_methods_dynamic_test/04: MissingRuntimeError
type_parameter_test/05: MissingCompileTimeError
+[ ($compiler == app_jit || $compiler == none || $compiler == precompiler) && ($runtime == dart_precompiled || $runtime == vm) ]
+const_cast2_test/01: CompileTimeError
+
[ $compiler != dartk && $runtime == vm || $compiler != dartkp && $runtime == dart_precompiled ]
built_in_identifier_type_annotation_test/22: MissingCompileTimeError # Error only in strong mode
int64_literal_test/*: Skip # This is testing Dart 2.0 int64 semantics.
diff --git a/tests/language_2/operator2_test.dart b/tests/language_2/operator2_test.dart
index 99c770b..17f1fd8f 100644
--- a/tests/language_2/operator2_test.dart
+++ b/tests/language_2/operator2_test.dart
@@ -17,15 +17,38 @@
}
}
-class OperatorTest {
- static testMain() {
- Helper obj = new Helper(10);
- Expect.equals(10, obj.i);
- obj[10] = 20;
- Expect.equals(30, obj[10]);
+main() {
+ Helper obj = new Helper(10);
+ Expect.equals(10, obj.i);
+ obj[10] = 20;
+ Expect.equals(30, obj[10]);
+
+ regress32754();
+}
+
+// Regression test for https://github.com/dart-lang/sdk/issues/32754
+class C {
+ operator []=(i, value) {
+ value = 'OOPS';
}
}
-main() {
- OperatorTest.testMain();
+class C2 {
+ int data;
+ operator []=(i, value) {
+ // The return expression must be evaluated, then ignored.
+ return () {
+ data = i + value;
+ return null;
+ }();
+ }
+}
+
+regress32754() {
+ var c = new C();
+ Expect.equals('ok', c[0] = 'ok');
+
+ var c2 = new C2();
+ Expect.equals(23, c2[100] = 23);
+ Expect.equals(123, c2.data);
}
diff --git a/tests/lib_2/async/null_future_zone_test.dart b/tests/lib_2/async/null_future_zone_test.dart
new file mode 100644
index 0000000..802c399
--- /dev/null
+++ b/tests/lib_2/async/null_future_zone_test.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+import 'dart:async';
+
+main() {
+ asyncStart(2);
+ () async {
+ var it = new StreamIterator(new Stream.fromIterable([]));
+ Expect.isFalse(await it.moveNext());
+
+ Future nullFuture;
+ Future falseFuture;
+
+ runZoned(() {
+ nullFuture = (new StreamController()..stream.listen(null).cancel()).done;
+ falseFuture = it.moveNext();
+ }, zoneSpecification: new ZoneSpecification(scheduleMicrotask:
+ (Zone self, ZoneDelegate parent, Zone zone, void f()) {
+ Expect.fail("Should not be called");
+ }));
+
+ nullFuture.then((value) {
+ Expect.isNull(value);
+ asyncEnd();
+ });
+
+ falseFuture.then((value) {
+ Expect.isFalse(value);
+ asyncEnd();
+ });
+ }();
+}
diff --git a/tests/lib_2/lib_2_dartdevc.status b/tests/lib_2/lib_2_dartdevc.status
index d3e9fe3..b8926562 100644
--- a/tests/lib_2/lib_2_dartdevc.status
+++ b/tests/lib_2/lib_2_dartdevc.status
@@ -89,7 +89,6 @@
html/element_classes_svg_test: RuntimeError # Issue 29922
html/element_classes_test: RuntimeError # Issue 29922
html/fontface_loaded_test: RuntimeError
-html/gamepad_test: RuntimeError # Issue 31029
html/interactive_media_test: Skip # requests interactive permissions (camera, geolocation)
html/isolates_test: RuntimeError # Issue 29922
html/js_typed_interop_default_arg_test/default_value: MissingCompileTimeError # Issue 29922
diff --git a/tests/standalone_2/standalone_2_kernel.status b/tests/standalone_2/standalone_2_kernel.status
index 50ce4be..3ee3c80 100644
--- a/tests/standalone_2/standalone_2_kernel.status
+++ b/tests/standalone_2/standalone_2_kernel.status
@@ -22,7 +22,7 @@
package/scenarios/invalid/non_existent_packages_file_test: CompileTimeError # Issue 32085
[ $builder_tag == optimization_counter_threshold && $compiler == dartk ]
-map_insert_remove_oom_test: Pass, Crash # Flaky on vm-kernel-optcounter-threshold-linux-release-x64, bug #31838
+map_insert_remove_oom_test: Pass, Crash, Timeout # Flaky on vm-kernel-optcounter-threshold-linux-release-x64, bug #31838. Sometimes times out, see issue 32786.
[ $compiler == dartk && $mode == debug && $runtime == vm && $strong ]
io/file_lock_test: Slow, Pass
diff --git a/tools/VERSION b/tools/VERSION
index 1d9868f..5eab473 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 0
PATCH 0
-PRERELEASE 46
+PRERELEASE 47
PRERELEASE_PATCH 0
diff --git a/tools/dom/scripts/htmlrenamer.py b/tools/dom/scripts/htmlrenamer.py
index 6e7b905..cde90fb 100644
--- a/tools/dom/scripts/htmlrenamer.py
+++ b/tools/dom/scripts/htmlrenamer.py
@@ -400,6 +400,7 @@
'MediaKeys.createSession',
'MediaKeySession.update',
'MessageEvent.initMessageEvent',
+ 'MessagePort.start',
'MouseEvent.initMouseEvent',
'MouseEvent.clientX',
'MouseEvent.clientY',
@@ -410,6 +411,7 @@
'MouseEvent.screenX',
'MouseEvent.screenY',
'MutationObserver.observe',
+ 'Navigator.getGamepads',
'Node.attributes',
'Node.localName',
'Node.namespaceURI',
diff --git a/tools/dom/src/dart2js_CustomElementSupport.dart b/tools/dom/src/dart2js_CustomElementSupport.dart
index 7869ea3..983ba1a 100644
--- a/tools/dom/src/dart2js_CustomElementSupport.dart
+++ b/tools/dom/src/dart2js_CustomElementSupport.dart
@@ -147,7 +147,8 @@
JS('=Object', '#.extends = #', opts, extendsTagName);
}
- return JS('=Object', '#.registerElement(#, #)', document, tag, opts);
+ return JS(
+ 'JavaScriptFunction', '#.registerElement(#, #)', document, tag, opts);
}
//// Called by Element.created to do validation & initialization.
diff --git a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
index b6959e6..2baac67 100644
--- a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
@@ -58,7 +58,7 @@
findDispatchTagForInterceptorClass, setNativeSubclassDispatchRecord,
makeLeafDispatchRecord, registerGlobalObject, applyExtension;
import 'dart:_interceptors' show
- Interceptor, JSExtendableArray, JSUInt31,
+ Interceptor, JavaScriptFunction, JSExtendableArray, JSUInt31,
findInterceptorConstructorForType,
findConstructorForNativeSubclassType,
getNativeInterceptor,
diff --git a/tools/dom/templates/html/impl/impl_MessagePort.darttemplate b/tools/dom/templates/html/impl/impl_MessagePort.darttemplate
index 824012e..0dbf89b 100644
--- a/tools/dom/templates/html/impl/impl_MessagePort.darttemplate
+++ b/tools/dom/templates/html/impl/impl_MessagePort.darttemplate
@@ -13,7 +13,7 @@
// Messages posted to ports are initially paused, allowing listeners to be
// setup, start() needs to be explicitly invoked to begin handling messages.
if (type == 'message') {
- start();
+ _start();
}
super.addEventListener(type, listener, useCapture);
diff --git a/tools/dom/templates/html/impl/impl_Navigator.darttemplate b/tools/dom/templates/html/impl/impl_Navigator.darttemplate
index 079fa93..022e9e3 100644
--- a/tools/dom/templates/html/impl/impl_Navigator.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Navigator.darttemplate
@@ -6,6 +6,20 @@
$(ANNOTATIONS)$(NATIVESPEC)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS {
+ @DomName('Navigator.getGamepads')
+ List<Gamepad> getGamepads() {
+ var gamepadList = _getGamepads();
+
+ // If no prototype we need one for the world to hookup to the proper Dart class.
+ var jsProto = JS('', '#.prototype', gamepadList);
+ if (jsProto == null) {
+ JS('', '#.prototype = Object.create(null)', gamepadList);
+ }
+
+ applyExtension('GamepadList', gamepadList);
+ return gamepadList;
+ }
+
@DomName('Navigator.language')
String get language => JS('String', '#.language || #.userLanguage', this,
this);
diff --git a/tools/sdks/linux/dart-sdk.tar.gz.sha1 b/tools/sdks/linux/dart-sdk.tar.gz.sha1
index fcfff24..b8078c6 100644
--- a/tools/sdks/linux/dart-sdk.tar.gz.sha1
+++ b/tools/sdks/linux/dart-sdk.tar.gz.sha1
@@ -1 +1 @@
-e1d5dbecbca504ffa66db767045aeb3714a2a696
\ No newline at end of file
+d603d2f9fe59281e37a250cb3105ab54d1c25e64
\ No newline at end of file
diff --git a/tools/sdks/mac/dart-sdk.tar.gz.sha1 b/tools/sdks/mac/dart-sdk.tar.gz.sha1
index 9921e91..e7dd518 100644
--- a/tools/sdks/mac/dart-sdk.tar.gz.sha1
+++ b/tools/sdks/mac/dart-sdk.tar.gz.sha1
@@ -1 +1 @@
-3e694dc99bb13d9b094401c6424764459109676e
\ No newline at end of file
+7b5adc71c75dc07815ccd8f233c4ccf50d11e11f
\ No newline at end of file
diff --git a/tools/sdks/win/dart-sdk.tar.gz.sha1 b/tools/sdks/win/dart-sdk.tar.gz.sha1
index 81e6c51..5ade4b8 100644
--- a/tools/sdks/win/dart-sdk.tar.gz.sha1
+++ b/tools/sdks/win/dart-sdk.tar.gz.sha1
@@ -1 +1 @@
-8ea5e44f520f93a65f05f36f1d7886d04650d29a
\ No newline at end of file
+520e55c06f22a50938c1682e6e0a56161fc43a65
\ No newline at end of file
diff --git a/utils/bazel/kernel_summary_worker.dart b/utils/bazel/kernel_summary_worker.dart
index 461e390..c572e88 100644
--- a/utils/bazel/kernel_summary_worker.dart
+++ b/utils/bazel/kernel_summary_worker.dart
@@ -131,11 +131,12 @@
new TargetFlags(strongMode: true)),
fileSystem);
- void onProblem(problem, severity, String formatted, line, column) {
- if (outputBuffer != null) {
- outputBuffer.writeln(formatted);
- } else {
- stderr.writeln(formatted);
+ void onProblem(fe.FormattedMessage message, severity,
+ List<fe.FormattedMessage> context) {
+ dynamic out = outputBuffer ?? stderr;
+ out.println(message.formatted);
+ for (fe.FormattedMessage message in context) {
+ out.println(message.formatted);
}
if (severity != fe.Severity.nit) {
succeeded = false;