Version 2.0.0-dev.32.0
Merge commit '0e48dce272ba37f25bf6d715861f99d770550d31' into dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ba4829f..29e2bfd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -274,15 +274,22 @@
* Pub will now automatically retry HTTP requests that fail with a 502, 503, of
504 error code ([issue 1556][pub#1556]).
+* Pub now caches compiled packages and snapshots in the `.dart_tool/pub`
+ directory, rather than the `.pub` directory ([issue 1795][pub#1795]).
+
* Emit exit code 66 when a path dependency doesn't exist ([issue 1747][pub#1747]).
* `pub publish` throws a more explicit error if the `publish_to` field isn't an
absolute URL ([issue 1769][pub#1769]).
+* `pub publish` provides more detailed information if the package is too large
+ to upload.
+
[pub#1556]: https://github.com/dart-lang/pub/issues/1556
[pub#1747]: https://github.com/dart-lang/pub/issues/1747
[pub#1769]: https://github.com/dart-lang/pub/issues/1769
[pub#1775]: https://github.com/dart-lang/pub/issues/1775
+[pub#1795]: https://github.com/dart-lang/pub/issues/1795
##### Bug Fixes
diff --git a/DEPS b/DEPS
index f7bafe3..07dc0fc 100644
--- a/DEPS
+++ b/DEPS
@@ -58,8 +58,8 @@
"barback_tag" : "@0.15.2+14",
"bazel_worker_tag": "@v0.1.9",
"boolean_selector_tag" : "@1.0.2",
- "boringssl_gen_rev": "@d2b56d1b7657e52eb5a1f075968c773aa3e53614",
- "boringssl_rev" : "@d519bf6be0b447fb80fbc539d4bff4479b5482a2",
+ "boringssl_gen_rev": "@39762c7f9ee4d828ff212838fae79528b94d5443",
+ "boringssl_rev" : "@a62dbf88d8a3c04446db833a1eb80a620cb1514d",
"charcode_tag": "@v1.1.1",
"chrome_rev" : "@19997",
"cli_util_tag" : "@0.1.2+1",
@@ -83,7 +83,7 @@
# For more details, see https://github.com/dart-lang/sdk/issues/30164
"dart_style_tag": "@1.0.10", # Please see the note above before updating.
- "dartdoc_tag" : "@v0.16.0",
+ "dartdoc_tag" : "@v0.17.0",
"fixnum_tag": "@0.10.5",
"func_rev": "@25eec48146a58967d75330075ab376b3838b18a8",
"glob_tag": "@1.1.5",
@@ -115,7 +115,7 @@
"ply_rev": "@604b32590ffad5cbb82e4afef1d305512d06ae93",
"pool_tag": "@1.3.4",
"protobuf_tag": "@0.7.0",
- "pub_rev": "@64c5f40adf6828da1b63320dd39bcedbef1354c6",
+ "pub_rev": "@73ff0d3d9f80f60d41e3135ac44597d011abb4f3",
"pub_semver_tag": "@1.3.2",
"quiver_tag": "@0.28.0",
"resource_rev":"@af5a5bf65511943398146cf146e466e5f0b95cb9",
diff --git a/pkg/analysis_server/benchmark/perf/memory_tests.dart b/pkg/analysis_server/benchmark/perf/memory_tests.dart
index ed9a3d1..6803a4e 100644
--- a/pkg/analysis_server/benchmark/perf/memory_tests.dart
+++ b/pkg/analysis_server/benchmark/perf/memory_tests.dart
@@ -34,9 +34,15 @@
static const int vmServicePort = 12345;
int getMemoryUsage() {
- ProcessResult result = _run('curl', <String>[
- 'localhost:$vmServicePort/_getAllocationProfile\?isolateId=isolates/root\&gc=full'
- ]);
+ String vmService =
+ 'http://localhost:$vmServicePort/_getAllocationProfile\?isolateId=isolates/root\&gc=full';
+ ProcessResult result;
+ if (Platform.isWindows) {
+ result = _run(
+ 'powershell', <String>['-Command', '(curl "$vmService").Content']);
+ } else {
+ result = _run('curl', <String>[vmService]);
+ }
Map json = JSON.decode(result.stdout);
Map heaps = json['result']['heaps'];
int newSpace = heaps['new']['used'];
@@ -53,7 +59,7 @@
/**
* The server is automatically started before every test.
- */
+ */
@override
Future setUp({bool useCFE: false}) {
onAnalysisErrors.listen((AnalysisErrorsParams params) {
diff --git a/pkg/analysis_server/lib/protocol/protocol_constants.dart b/pkg/analysis_server/lib/protocol/protocol_constants.dart
index d9cad4b..cf044e0 100644
--- a/pkg/analysis_server/lib/protocol/protocol_constants.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_constants.dart
@@ -208,6 +208,8 @@
const String EXECUTION_RESPONSE_MAP_URI_URI = 'uri';
const String FLUTTER_NOTIFICATION_OUTLINE = 'flutter.outline';
const String FLUTTER_NOTIFICATION_OUTLINE_FILE = 'file';
+const String FLUTTER_NOTIFICATION_OUTLINE_INSTRUMENTATION_EDITS =
+ 'instrumentationEdits';
const String FLUTTER_NOTIFICATION_OUTLINE_OUTLINE = 'outline';
const String FLUTTER_REQUEST_SET_SUBSCRIPTIONS = 'flutter.setSubscriptions';
const String FLUTTER_REQUEST_SET_SUBSCRIPTIONS_SUBSCRIPTIONS = 'subscriptions';
diff --git a/pkg/analysis_server/lib/protocol/protocol_generated.dart b/pkg/analysis_server/lib/protocol/protocol_generated.dart
index 3616da5..78949dd 100644
--- a/pkg/analysis_server/lib/protocol/protocol_generated.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_generated.dart
@@ -10959,6 +10959,10 @@
* "parentAssociationLabel": optional String
* "variableName": optional String
* "children": optional List<FlutterOutline>
+ * "id": optional int
+ * "renderConstructor": optional String
+ * "stateOffset": optional int
+ * "stateLength": optional int
* }
*
* Clients may not extend, implement or mix-in this class.
@@ -10984,6 +10988,14 @@
List<FlutterOutline> _children;
+ int _id;
+
+ String _renderConstructor;
+
+ int _stateOffset;
+
+ int _stateLength;
+
/**
* The kind of the node.
*/
@@ -11127,6 +11139,72 @@
this._children = value;
}
+ /**
+ * If the node is a widget, and it is instrumented, the unique identifier of
+ * this widget, that can be used to associate rendering information with this
+ * node.
+ */
+ int get id => _id;
+
+ /**
+ * If the node is a widget, and it is instrumented, the unique identifier of
+ * this widget, that can be used to associate rendering information with this
+ * node.
+ */
+ void set id(int value) {
+ this._id = value;
+ }
+
+ /**
+ * If the node is a widget class that can be rendered for IDE, the name of
+ * the constructor that should be used to instantiate the widget. Empty
+ * string for default constructor. Absent if the node is not a widget class
+ * that can be rendered.
+ */
+ String get renderConstructor => _renderConstructor;
+
+ /**
+ * If the node is a widget class that can be rendered for IDE, the name of
+ * the constructor that should be used to instantiate the widget. Empty
+ * string for default constructor. Absent if the node is not a widget class
+ * that can be rendered.
+ */
+ void set renderConstructor(String value) {
+ this._renderConstructor = value;
+ }
+
+ /**
+ * If the node is a StatefulWidget that can be rendered, and its State class
+ * is defined in the same file, the offset of the State class code in the
+ * file.
+ */
+ int get stateOffset => _stateOffset;
+
+ /**
+ * If the node is a StatefulWidget that can be rendered, and its State class
+ * is defined in the same file, the offset of the State class code in the
+ * file.
+ */
+ void set stateOffset(int value) {
+ this._stateOffset = value;
+ }
+
+ /**
+ * If the node is a StatefulWidget that can be rendered, and its State class
+ * is defined in the same file, the length of the State class code in the
+ * file.
+ */
+ int get stateLength => _stateLength;
+
+ /**
+ * If the node is a StatefulWidget that can be rendered, and its State class
+ * is defined in the same file, the length of the State class code in the
+ * file.
+ */
+ void set stateLength(int value) {
+ this._stateLength = value;
+ }
+
FlutterOutline(FlutterOutlineKind kind, int offset, int length,
{String label,
Element dartElement,
@@ -11134,7 +11212,11 @@
String className,
String parentAssociationLabel,
String variableName,
- List<FlutterOutline> children}) {
+ List<FlutterOutline> children,
+ int id,
+ String renderConstructor,
+ int stateOffset,
+ int stateLength}) {
this.kind = kind;
this.offset = offset;
this.length = length;
@@ -11145,6 +11227,10 @@
this.parentAssociationLabel = parentAssociationLabel;
this.variableName = variableName;
this.children = children;
+ this.id = id;
+ this.renderConstructor = renderConstructor;
+ this.stateOffset = stateOffset;
+ this.stateLength = stateLength;
}
factory FlutterOutline.fromJson(
@@ -11214,6 +11300,25 @@
(String jsonPath, Object json) =>
new FlutterOutline.fromJson(jsonDecoder, jsonPath, json));
}
+ int id;
+ if (json.containsKey("id")) {
+ id = jsonDecoder.decodeInt(jsonPath + ".id", json["id"]);
+ }
+ String renderConstructor;
+ if (json.containsKey("renderConstructor")) {
+ renderConstructor = jsonDecoder.decodeString(
+ jsonPath + ".renderConstructor", json["renderConstructor"]);
+ }
+ int stateOffset;
+ if (json.containsKey("stateOffset")) {
+ stateOffset = jsonDecoder.decodeInt(
+ jsonPath + ".stateOffset", json["stateOffset"]);
+ }
+ int stateLength;
+ if (json.containsKey("stateLength")) {
+ stateLength = jsonDecoder.decodeInt(
+ jsonPath + ".stateLength", json["stateLength"]);
+ }
return new FlutterOutline(kind, offset, length,
label: label,
dartElement: dartElement,
@@ -11221,7 +11326,11 @@
className: className,
parentAssociationLabel: parentAssociationLabel,
variableName: variableName,
- children: children);
+ children: children,
+ id: id,
+ renderConstructor: renderConstructor,
+ stateOffset: stateOffset,
+ stateLength: stateLength);
} else {
throw jsonDecoder.mismatch(jsonPath, "FlutterOutline", json);
}
@@ -11257,6 +11366,18 @@
result["children"] =
children.map((FlutterOutline value) => value.toJson()).toList();
}
+ if (id != null) {
+ result["id"] = id;
+ }
+ if (renderConstructor != null) {
+ result["renderConstructor"] = renderConstructor;
+ }
+ if (stateOffset != null) {
+ result["stateOffset"] = stateOffset;
+ }
+ if (stateLength != null) {
+ result["stateLength"] = stateLength;
+ }
return result;
}
@@ -11280,7 +11401,11 @@
parentAssociationLabel == other.parentAssociationLabel &&
variableName == other.variableName &&
listEqual(children, other.children,
- (FlutterOutline a, FlutterOutline b) => a == b);
+ (FlutterOutline a, FlutterOutline b) => a == b) &&
+ id == other.id &&
+ renderConstructor == other.renderConstructor &&
+ stateOffset == other.stateOffset &&
+ stateLength == other.stateLength;
}
return false;
}
@@ -11298,6 +11423,10 @@
hash = JenkinsSmiHash.combine(hash, parentAssociationLabel.hashCode);
hash = JenkinsSmiHash.combine(hash, variableName.hashCode);
hash = JenkinsSmiHash.combine(hash, children.hashCode);
+ hash = JenkinsSmiHash.combine(hash, id.hashCode);
+ hash = JenkinsSmiHash.combine(hash, renderConstructor.hashCode);
+ hash = JenkinsSmiHash.combine(hash, stateOffset.hashCode);
+ hash = JenkinsSmiHash.combine(hash, stateLength.hashCode);
return JenkinsSmiHash.finish(hash);
}
}
@@ -11605,6 +11734,7 @@
* {
* "file": FilePath
* "outline": FlutterOutline
+ * "instrumentationEdits": List<SourceEdit>
* }
*
* Clients may not extend, implement or mix-in this class.
@@ -11614,6 +11744,8 @@
FlutterOutline _outline;
+ List<SourceEdit> _instrumentationEdits;
+
/**
* The file with which the outline is associated.
*/
@@ -11640,9 +11772,28 @@
this._outline = value;
}
- FlutterOutlineParams(String file, FlutterOutline outline) {
+ /**
+ * If the file has Flutter widgets that can be rendered, the list of edits
+ * that should be applied to the file to instrument widgets and associate
+ * them with outline nodes.
+ */
+ List<SourceEdit> get instrumentationEdits => _instrumentationEdits;
+
+ /**
+ * If the file has Flutter widgets that can be rendered, the list of edits
+ * that should be applied to the file to instrument widgets and associate
+ * them with outline nodes.
+ */
+ void set instrumentationEdits(List<SourceEdit> value) {
+ assert(value != null);
+ this._instrumentationEdits = value;
+ }
+
+ FlutterOutlineParams(String file, FlutterOutline outline,
+ List<SourceEdit> instrumentationEdits) {
this.file = file;
this.outline = outline;
+ this.instrumentationEdits = instrumentationEdits;
}
factory FlutterOutlineParams.fromJson(
@@ -11664,7 +11815,17 @@
} else {
throw jsonDecoder.mismatch(jsonPath, "outline");
}
- return new FlutterOutlineParams(file, outline);
+ List<SourceEdit> instrumentationEdits;
+ if (json.containsKey("instrumentationEdits")) {
+ instrumentationEdits = jsonDecoder.decodeList(
+ jsonPath + ".instrumentationEdits",
+ json["instrumentationEdits"],
+ (String jsonPath, Object json) =>
+ new SourceEdit.fromJson(jsonDecoder, jsonPath, json));
+ } else {
+ throw jsonDecoder.mismatch(jsonPath, "instrumentationEdits");
+ }
+ return new FlutterOutlineParams(file, outline, instrumentationEdits);
} else {
throw jsonDecoder.mismatch(jsonPath, "flutter.outline params", json);
}
@@ -11680,6 +11841,8 @@
Map<String, dynamic> result = {};
result["file"] = file;
result["outline"] = outline.toJson();
+ result["instrumentationEdits"] =
+ instrumentationEdits.map((SourceEdit value) => value.toJson()).toList();
return result;
}
@@ -11693,7 +11856,10 @@
@override
bool operator ==(other) {
if (other is FlutterOutlineParams) {
- return file == other.file && outline == other.outline;
+ return file == other.file &&
+ outline == other.outline &&
+ listEqual(instrumentationEdits, other.instrumentationEdits,
+ (SourceEdit a, SourceEdit b) => a == b);
}
return false;
}
@@ -11703,6 +11869,7 @@
int hash = 0;
hash = JenkinsSmiHash.combine(hash, file.hashCode);
hash = JenkinsSmiHash.combine(hash, outline.hashCode);
+ hash = JenkinsSmiHash.combine(hash, instrumentationEdits.hashCode);
return JenkinsSmiHash.finish(hash);
}
}
diff --git a/pkg/analysis_server/lib/src/flutter/flutter_notifications.dart b/pkg/analysis_server/lib/src/flutter/flutter_notifications.dart
index f526036..bf407e1 100644
--- a/pkg/analysis_server/lib/src/flutter/flutter_notifications.dart
+++ b/pkg/analysis_server/lib/src/flutter/flutter_notifications.dart
@@ -15,7 +15,7 @@
new FlutterOutlineComputer(file, content, lineInfo, dartUnit);
protocol.FlutterOutline outline = computer.compute();
// send notification
- var params = new protocol.FlutterOutlineParams(file, outline);
+ var params = new protocol.FlutterOutlineParams(file, outline, []);
server.sendNotification(params.toNotification());
});
}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/uri_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/uri_contributor.dart
index b8b7f58c..de77d4c 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/uri_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/uri_contributor.dart
@@ -149,7 +149,15 @@
}
String uriPrefix = parentUri == '.' ? '' : parentUri;
- String dirPath = resContext.normalize(parentUri);
+ // Only handle file uris in the format file:///xxx or /xxx
+ String parentUriScheme = Uri.parse(parentUri).scheme;
+ if (!parentUri.startsWith('file://') && parentUriScheme != '') {
+ return;
+ }
+
+ String dirPath = resProvider.pathContext.fromUri(parentUri);
+ dirPath = resContext.normalize(dirPath);
+
if (resContext.isRelative(dirPath)) {
String sourceDirPath = resContext.dirname(source.fullName);
if (resContext.isAbsolute(sourceDirPath)) {
diff --git a/pkg/analysis_server/test/domain_completion_test.dart b/pkg/analysis_server/test/domain_completion_test.dart
index 94c8884..57cd8ee 100644
--- a/pkg/analysis_server/test/domain_completion_test.dart
+++ b/pkg/analysis_server/test/domain_completion_test.dart
@@ -250,15 +250,18 @@
}
test_import_uri_with_trailing() {
- newFile('/project/bin/testA.dart', content: 'library libA;');
+ final filePath = '/project/bin/testA.dart';
+ final incompleteImportText = convertPathForImport('/project/bin/t');
+ newFile(filePath, content: 'library libA;');
addTestFile('''
- import '/project/bin/t^.dart';
- main() {}''');
+ import "$incompleteImportText^.dart";
+ main() {}''');
return getSuggestions().then((_) {
- expect(replacementOffset, equals(completionOffset - 14));
- expect(replacementLength, equals(5 + 14));
+ expect(replacementOffset,
+ equals(completionOffset - incompleteImportText.length));
+ expect(replacementLength, equals(5 + incompleteImportText.length));
assertHasResult(
- CompletionSuggestionKind.IMPORT, '/project/bin/testA.dart');
+ CompletionSuggestionKind.IMPORT, convertPathForImport(filePath));
assertNoResult('test');
});
}
@@ -664,7 +667,7 @@
test_partFile() {
newFile('/project/bin/testA.dart', content: '''
library libA;
- part "$testFile";
+ part "${convertPathForImport(testFile)}";
import 'dart:html';
class A { }
''');
@@ -687,7 +690,7 @@
class A { }''');
addTestFile('''
library libA;
- part "/testA.dart";
+ part "${convertPathForImport("/testA.dart")}";
import 'dart:html';
main() {^}
''');
diff --git a/pkg/analysis_server/test/integration/analysis/set_general_subscriptions_test.dart b/pkg/analysis_server/test/integration/analysis/set_general_subscriptions_test.dart
index ff147fc..c75655b 100644
--- a/pkg/analysis_server/test/integration/analysis/set_general_subscriptions_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/set_general_subscriptions_test.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/protocol/protocol_generated.dart';
+import 'package:path/path.dart' show join;
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -35,7 +36,8 @@
expect(lastAnalyzedFiles, isNotEmpty);
expect(lastAnalyzedFiles, contains(pathname));
expect(
- lastAnalyzedFiles.any((String file) => file.endsWith('core/core.dart')),
+ lastAnalyzedFiles
+ .any((String file) => file.endsWith(join('core', 'core.dart'))),
true);
}
}
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 ab48dde..33968b2 100644
--- a/pkg/analysis_server/test/integration/support/integration_test_methods.dart
+++ b/pkg/analysis_server/test/integration/support/integration_test_methods.dart
@@ -2168,6 +2168,12 @@
* outline: FlutterOutline
*
* The outline associated with the file.
+ *
+ * instrumentationEdits: List<SourceEdit>
+ *
+ * If the file has Flutter widgets that can be rendered, the list of edits
+ * that should be applied to the file to instrument widgets and associate
+ * them with outline nodes.
*/
Stream<FlutterOutlineParams> onFlutterOutline;
diff --git a/pkg/analysis_server/test/integration/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
index 93cc065..aaaa3d9 100644
--- a/pkg/analysis_server/test/integration/support/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
@@ -484,6 +484,10 @@
* "parentAssociationLabel": optional String
* "variableName": optional String
* "children": optional List<FlutterOutline>
+ * "id": optional int
+ * "renderConstructor": optional String
+ * "stateOffset": optional int
+ * "stateLength": optional int
* }
*/
final Matcher isFlutterOutline =
@@ -498,7 +502,11 @@
"className": isString,
"parentAssociationLabel": isString,
"variableName": isString,
- "children": isListOf(isFlutterOutline)
+ "children": isListOf(isFlutterOutline),
+ "id": isInt,
+ "renderConstructor": isString,
+ "stateOffset": isInt,
+ "stateLength": isInt
}));
/**
@@ -2447,11 +2455,15 @@
* {
* "file": FilePath
* "outline": FlutterOutline
+ * "instrumentationEdits": List<SourceEdit>
* }
*/
-final Matcher isFlutterOutlineParams = new LazyMatcher(() =>
- new MatchesJsonObject("flutter.outline params",
- {"file": isFilePath, "outline": isFlutterOutline}));
+final Matcher isFlutterOutlineParams =
+ new LazyMatcher(() => new MatchesJsonObject("flutter.outline params", {
+ "file": isFilePath,
+ "outline": isFlutterOutline,
+ "instrumentationEdits": isListOf(isSourceEdit)
+ }));
/**
* flutter.setSubscriptions params
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
index f0c3285..40da511 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
@@ -227,7 +227,12 @@
}
CompletionSuggestion assertSuggestEnumConst(String completion,
- {int relevance: DART_RELEVANCE_DEFAULT, bool isDeprecated: false}) {
+ {int relevance: DART_RELEVANCE_DEFAULT,
+ bool isDeprecated: false,
+ bool hasTypeBoost: false}) {
+ if (hasTypeBoost) {
+ relevance += DART_RELEVANCE_BOOST_TYPE;
+ }
CompletionSuggestion suggestion = assertSuggest(completion,
relevance: relevance, isDeprecated: isDeprecated);
expect(suggestion.completion, completion);
diff --git a/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart
index 9c62da3..6ae7e6b 100644
--- a/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart
@@ -1866,10 +1866,8 @@
await computeSuggestions();
assertSuggestEnum('E');
- assertSuggestEnumConst('E.one',
- relevance: DART_RELEVANCE_DEFAULT + DART_RELEVANCE_BOOST_TYPE);
- assertSuggestEnumConst('E.two',
- relevance: DART_RELEVANCE_DEFAULT + DART_RELEVANCE_BOOST_TYPE);
+ assertSuggestEnumConst('E.one', hasTypeBoost: true);
+ assertSuggestEnumConst('E.two', hasTypeBoost: true);
assertSuggestEnum('F');
assertSuggestEnumConst('F.three');
diff --git a/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
index 8650537..fb5a912 100644
--- a/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
@@ -20,7 +20,14 @@
class LocalReferenceContributorTest extends DartCompletionContributorTest {
CompletionSuggestion assertSuggestLocalVariable(
String name, String returnType,
- {int relevance: DART_RELEVANCE_LOCAL_VARIABLE}) {
+ {int relevance: DART_RELEVANCE_LOCAL_VARIABLE,
+ bool hasTypeBoost: false,
+ bool hasSubtypeBoost: false}) {
+ if (hasTypeBoost) {
+ relevance += DART_RELEVANCE_BOOST_TYPE;
+ } else if (hasSubtypeBoost) {
+ relevance += DART_RELEVANCE_BOOST_SUBTYPE;
+ }
// Local variables should only be suggested by LocalReferenceContributor
CompletionSuggestion cs = assertSuggest(name,
csKind: CompletionSuggestionKind.INVOCATION, relevance: relevance);
@@ -645,7 +652,7 @@
expect(replacementOffset, completionOffset);
expect(replacementLength, 0);
- assertSuggestLocalVariable('a', 'int');
+ assertSuggestLocalVariable('a', 'int', hasTypeBoost: true);
assertSuggestFunction('main', null,
relevance: DART_RELEVANCE_LOCAL_FUNCTION);
assertSuggestClass('A');
@@ -790,7 +797,11 @@
expect(replacementOffset, completionOffset);
expect(replacementLength, 0);
- assertSuggestLocalVariable('a', 'int');
+ // We should not have the type boost, but we do.
+ // The reason is that coveringNode is VariableDeclaration, and the
+ // entity is BinaryExpression, so the expected type is int.
+ // It would be more correct to use BinaryExpression as coveringNode.
+ assertSuggestLocalVariable('a', 'int', hasTypeBoost: true);
assertNotSuggested('Object');
assertNotSuggested('b');
}
@@ -803,8 +814,7 @@
expect(replacementOffset, completionOffset);
expect(replacementLength, 0);
- assertSuggestLocalVariable('a', 'int',
- relevance: DART_RELEVANCE_LOCAL_VARIABLE + DART_RELEVANCE_BOOST_TYPE);
+ assertSuggestLocalVariable('a', 'int', hasSubtypeBoost: true);
assertNotSuggested('Object');
assertNotSuggested('b');
assertNotSuggested('==');
@@ -2168,10 +2178,91 @@
await computeSuggestions();
assertSuggestEnum('E');
- assertSuggestEnumConst('E.one',
- relevance: DART_RELEVANCE_DEFAULT + DART_RELEVANCE_BOOST_TYPE);
- assertSuggestEnumConst('E.two',
- relevance: DART_RELEVANCE_DEFAULT + DART_RELEVANCE_BOOST_TYPE);
+ assertSuggestEnumConst('E.one', hasTypeBoost: true);
+ assertSuggestEnumConst('E.two', hasTypeBoost: true);
+
+ assertSuggestEnum('F');
+ assertSuggestEnumConst('F.three');
+ assertSuggestEnumConst('F.four');
+ }
+
+ test_enum_filter_assignment() async {
+ addTestSource('''
+enum E { one, two }
+enum F { three, four }
+
+main() {
+ E e;
+ e = ^;
+}
+''');
+ await computeSuggestions();
+
+ assertSuggestEnum('E');
+ assertSuggestEnumConst('E.one', hasTypeBoost: true);
+ assertSuggestEnumConst('E.two', hasTypeBoost: true);
+
+ assertSuggestEnum('F');
+ assertSuggestEnumConst('F.three');
+ assertSuggestEnumConst('F.four');
+ }
+
+ test_enum_filter_binaryEquals() async {
+ addTestSource('''
+enum E { one, two }
+enum F { three, four }
+
+main(E e) {
+ e == ^;
+}
+''');
+ await computeSuggestions();
+
+ assertSuggestEnum('E');
+ assertSuggestEnumConst('E.one', hasTypeBoost: true);
+ assertSuggestEnumConst('E.two', hasTypeBoost: true);
+
+ assertSuggestEnum('F');
+ assertSuggestEnumConst('F.three');
+ assertSuggestEnumConst('F.four');
+ }
+
+ test_enum_filter_switchCase() async {
+ addTestSource('''
+enum E { one, two }
+enum F { three, four }
+
+main(E e) {
+ switch (e) {
+ case ^
+ }
+}
+''');
+ await computeSuggestions();
+
+ assertSuggestEnum('E');
+ assertSuggestEnumConst('E.one', hasTypeBoost: true);
+ assertSuggestEnumConst('E.two', hasTypeBoost: true);
+
+ assertSuggestEnum('F');
+ assertSuggestEnumConst('F.three');
+ assertSuggestEnumConst('F.four');
+ }
+
+ test_enum_filter_variableDeclaration() async {
+ addTestSource('''
+enum E { one, two }
+enum F { three, four }
+
+main() {
+ E e = ^;
+}
+''');
+ await computeSuggestions();
+
+ assertSuggestEnum('E');
+ assertSuggestEnumConst('E.one', hasTypeBoost: true);
+ assertSuggestEnumConst('E.two', hasTypeBoost: true);
assertSuggestEnum('F');
assertSuggestEnumConst('F.three');
@@ -4197,11 +4288,9 @@
assertSuggestFunction('g', 'dynamic',
relevance: DART_RELEVANCE_LOCAL_FUNCTION);
- assertSuggestLocalVariable('t', 'dynamic',
- relevance: DART_RELEVANCE_LOCAL_VARIABLE);
+ assertSuggestLocalVariable('t', 'dynamic');
assertSuggestParameter('x', 'int', relevance: DART_RELEVANCE_PARAMETER);
- assertSuggestLocalVariable('bar', 'dynamic',
- relevance: DART_RELEVANCE_LOCAL_VARIABLE);
+ assertSuggestLocalVariable('bar', 'dynamic');
assertNotSuggested('String');
}
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/FlutterOutline.java b/pkg/analysis_server/tool/spec/generated/java/types/FlutterOutline.java
index 9a18b64..8be67a3 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/FlutterOutline.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/FlutterOutline.java
@@ -93,9 +93,34 @@
private final List<FlutterOutline> children;
/**
+ * If the node is a widget, and it is instrumented, the unique identifier of this widget, that can
+ * be used to associate rendering information with this node.
+ */
+ private final Integer id;
+
+ /**
+ * If the node is a widget class that can be rendered for IDE, the name of the constructor that
+ * should be used to instantiate the widget. Empty string for default constructor. Absent if the
+ * node is not a widget class that can be rendered.
+ */
+ private final String renderConstructor;
+
+ /**
+ * If the node is a StatefulWidget that can be rendered, and its State class is defined in the same
+ * file, the offset of the State class code in the file.
+ */
+ private final Integer stateOffset;
+
+ /**
+ * If the node is a StatefulWidget that can be rendered, and its State class is defined in the same
+ * file, the length of the State class code in the file.
+ */
+ private final Integer stateLength;
+
+ /**
* Constructor for {@link FlutterOutline}.
*/
- public FlutterOutline(String kind, int offset, int length, String label, Element dartElement, List<FlutterOutlineAttribute> attributes, String className, String parentAssociationLabel, String variableName, List<FlutterOutline> children) {
+ public FlutterOutline(String kind, int offset, int length, String label, Element dartElement, List<FlutterOutlineAttribute> attributes, String className, String parentAssociationLabel, String variableName, List<FlutterOutline> children, Integer id, String renderConstructor, Integer stateOffset, Integer stateLength) {
this.kind = kind;
this.offset = offset;
this.length = length;
@@ -106,6 +131,10 @@
this.parentAssociationLabel = parentAssociationLabel;
this.variableName = variableName;
this.children = children;
+ this.id = id;
+ this.renderConstructor = renderConstructor;
+ this.stateOffset = stateOffset;
+ this.stateLength = stateLength;
}
@Override
@@ -122,7 +151,11 @@
ObjectUtilities.equals(other.className, className) &&
ObjectUtilities.equals(other.parentAssociationLabel, parentAssociationLabel) &&
ObjectUtilities.equals(other.variableName, variableName) &&
- ObjectUtilities.equals(other.children, children);
+ ObjectUtilities.equals(other.children, children) &&
+ ObjectUtilities.equals(other.id, id) &&
+ ObjectUtilities.equals(other.renderConstructor, renderConstructor) &&
+ ObjectUtilities.equals(other.stateOffset, stateOffset) &&
+ ObjectUtilities.equals(other.stateLength, stateLength);
}
return false;
}
@@ -138,7 +171,11 @@
String parentAssociationLabel = jsonObject.get("parentAssociationLabel") == null ? null : jsonObject.get("parentAssociationLabel").getAsString();
String variableName = jsonObject.get("variableName") == null ? null : jsonObject.get("variableName").getAsString();
List<FlutterOutline> children = jsonObject.get("children") == null ? null : FlutterOutline.fromJsonArray(jsonObject.get("children").getAsJsonArray());
- return new FlutterOutline(kind, offset, length, label, dartElement, attributes, className, parentAssociationLabel, variableName, children);
+ Integer id = jsonObject.get("id") == null ? null : jsonObject.get("id").getAsInt();
+ String renderConstructor = jsonObject.get("renderConstructor") == null ? null : jsonObject.get("renderConstructor").getAsString();
+ Integer stateOffset = jsonObject.get("stateOffset") == null ? null : jsonObject.get("stateOffset").getAsInt();
+ Integer stateLength = jsonObject.get("stateLength") == null ? null : jsonObject.get("stateLength").getAsInt();
+ return new FlutterOutline(kind, offset, length, label, dartElement, attributes, className, parentAssociationLabel, variableName, children, id, renderConstructor, stateOffset, stateLength);
}
public static List<FlutterOutline> fromJsonArray(JsonArray jsonArray) {
@@ -185,6 +222,14 @@
}
/**
+ * If the node is a widget, and it is instrumented, the unique identifier of this widget, that can
+ * be used to associate rendering information with this node.
+ */
+ public Integer getId() {
+ return id;
+ }
+
+ /**
* The kind of the node.
*/
public String getKind() {
@@ -224,6 +269,31 @@
}
/**
+ * If the node is a widget class that can be rendered for IDE, the name of the constructor that
+ * should be used to instantiate the widget. Empty string for default constructor. Absent if the
+ * node is not a widget class that can be rendered.
+ */
+ public String getRenderConstructor() {
+ return renderConstructor;
+ }
+
+ /**
+ * If the node is a StatefulWidget that can be rendered, and its State class is defined in the same
+ * file, the length of the State class code in the file.
+ */
+ public Integer getStateLength() {
+ return stateLength;
+ }
+
+ /**
+ * If the node is a StatefulWidget that can be rendered, and its State class is defined in the same
+ * file, the offset of the State class code in the file.
+ */
+ public Integer getStateOffset() {
+ return stateOffset;
+ }
+
+ /**
* If FlutterOutlineKind.VARIABLE, the name of the variable.
*/
public String getVariableName() {
@@ -243,6 +313,10 @@
builder.append(parentAssociationLabel);
builder.append(variableName);
builder.append(children);
+ builder.append(id);
+ builder.append(renderConstructor);
+ builder.append(stateOffset);
+ builder.append(stateLength);
return builder.toHashCode();
}
@@ -280,6 +354,18 @@
}
jsonObject.add("children", jsonArrayChildren);
}
+ if (id != null) {
+ jsonObject.addProperty("id", id);
+ }
+ if (renderConstructor != null) {
+ jsonObject.addProperty("renderConstructor", renderConstructor);
+ }
+ if (stateOffset != null) {
+ jsonObject.addProperty("stateOffset", stateOffset);
+ }
+ if (stateLength != null) {
+ jsonObject.addProperty("stateLength", stateLength);
+ }
return jsonObject;
}
@@ -306,7 +392,15 @@
builder.append("variableName=");
builder.append(variableName + ", ");
builder.append("children=");
- builder.append(StringUtils.join(children, ", "));
+ builder.append(StringUtils.join(children, ", ") + ", ");
+ builder.append("id=");
+ builder.append(id + ", ");
+ builder.append("renderConstructor=");
+ builder.append(renderConstructor + ", ");
+ builder.append("stateOffset=");
+ builder.append(stateOffset + ", ");
+ builder.append("stateLength=");
+ builder.append(stateLength);
builder.append("]");
return builder.toString();
}
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index cab50c6..0de9134 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -2699,6 +2699,16 @@
The outline associated with the file.
</p>
</field>
+ <field name="instrumentationEdits">
+ <list>
+ <ref>SourceEdit</ref>
+ </list>
+ <p>
+ If the file has Flutter widgets that can be rendered, the list
+ of edits that should be applied to the file to instrument widgets and
+ associate them with outline nodes.
+ </p>
+ </field>
</params>
</notification>
</domain>
@@ -3135,6 +3145,39 @@
children.
</p>
</field>
+ <field name="id" optional="true">
+ <ref>int</ref>
+ <p>
+ If the node is a widget, and it is instrumented, the unique identifier
+ of this widget, that can be used to associate rendering information
+ with this node.
+ </p>
+ </field>
+ <field name="renderConstructor" optional="true">
+ <ref>String</ref>
+ <p>
+ If the node is a widget class that can be rendered for IDE, the name
+ of the constructor that should be used to instantiate the widget.
+ Empty string for default constructor. Absent if the node is not a
+ widget class that can be rendered.
+ </p>
+ </field>
+ <field name="stateOffset" optional="true">
+ <ref>int</ref>
+ <p>
+ If the node is a StatefulWidget that can be rendered, and its State
+ class is defined in the same file, the offset of the State class code
+ in the file.
+ </p>
+ </field>
+ <field name="stateLength" optional="true">
+ <ref>int</ref>
+ <p>
+ If the node is a StatefulWidget that can be rendered, and its State
+ class is defined in the same file, the length of the State class code
+ in the file.
+ </p>
+ </field>
</object>
</type>
<type name="FlutterOutlineAttribute" experimental="true">
diff --git a/pkg/analyzer/lib/dart/element/type.dart b/pkg/analyzer/lib/dart/element/type.dart
index 4f0729c..69d76ad 100644
--- a/pkg/analyzer/lib/dart/element/type.dart
+++ b/pkg/analyzer/lib/dart/element/type.dart
@@ -172,6 +172,16 @@
*/
DartType substitute2(
List<DartType> argumentTypes, List<DartType> parameterTypes);
+
+ /// Indicates whether `this` represents a type that is equivalent to `dest`.
+ ///
+ /// This is different from `operator==`. Consider for example:
+ ///
+ /// typedef void F<T>(); // T not used!
+ ///
+ /// `operator==` would consider F<int> and F<bool> to be different types;
+ /// `isEquivalentTo` considers them to be equivalent.
+ bool isEquivalentTo(DartType dest);
}
/**
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 95df0b9..724bc66 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -172,6 +172,7 @@
CompileTimeErrorCode.MIXIN_HAS_NO_CONSTRUCTORS,
CompileTimeErrorCode.MIXIN_INFERENCE_INCONSISTENT_MATCHING_CLASSES,
CompileTimeErrorCode.MIXIN_INFERENCE_NO_MATCHING_CLASS,
+ CompileTimeErrorCode.MIXIN_INFERENCE_NO_POSSIBLE_SUBSTITUTION,
CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT,
CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS,
CompileTimeErrorCode.MIXIN_OF_ENUM,
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index 67fe7c13..62345fc 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -774,6 +774,35 @@
}
@override
+ bool isEquivalentTo(DartType other) {
+ if (other is FunctionTypeImpl) {
+ if (typeFormals.length != other.typeFormals.length) {
+ return false;
+ }
+ // `<T>T -> T` should be equal to `<U>U -> U`
+ // To test this, we instantiate both types with the same (unique) type
+ // variables, and see if the result is equal.
+ if (typeFormals.isNotEmpty) {
+ List<DartType> freshVariables =
+ relateTypeFormals(this, other, (t, s, _, __) => t == s);
+ if (freshVariables == null) {
+ return false;
+ }
+ return instantiate(freshVariables)
+ .isEquivalentTo(other.instantiate(freshVariables));
+ }
+
+ return returnType.isEquivalentTo(other.returnType) &&
+ TypeImpl.equivalentArrays(
+ normalParameterTypes, other.normalParameterTypes) &&
+ TypeImpl.equivalentArrays(
+ optionalParameterTypes, other.optionalParameterTypes) &&
+ _equivalent(namedParameterTypes, other.namedParameterTypes);
+ }
+ return false;
+ }
+
+ @override
bool operator ==(Object object) {
if (object is FunctionTypeImpl) {
if (typeFormals.length != object.typeFormals.length) {
@@ -1384,6 +1413,31 @@
}
return true;
}
+
+ /**
+ * Return `true` if all of the name/type pairs in the first map ([firstTypes])
+ * are equivalent to the corresponding name/type pairs in the second map
+ * ([secondTypes]). The maps are expected to iterate over their entries in the
+ * same order in which those entries were added to the map.
+ */
+ static bool _equivalent(
+ Map<String, DartType> firstTypes, Map<String, DartType> secondTypes) {
+ if (secondTypes.length != firstTypes.length) {
+ return false;
+ }
+ Iterator<String> firstKeys = firstTypes.keys.iterator;
+ Iterator<String> secondKeys = secondTypes.keys.iterator;
+ while (firstKeys.moveNext() && secondKeys.moveNext()) {
+ String firstKey = firstKeys.current;
+ String secondKey = secondKeys.current;
+ TypeImpl firstType = firstTypes[firstKey];
+ TypeImpl secondType = secondTypes[secondKey];
+ if (firstKey != secondKey || !firstType.isEquivalentTo(secondType)) {
+ return false;
+ }
+ }
+ return true;
+ }
}
/**
@@ -1669,6 +1723,18 @@
}
@override
+ bool isEquivalentTo(DartType other) {
+ if (identical(other, this)) {
+ return true;
+ }
+ if (other is InterfaceTypeImpl) {
+ return (element == other.element) &&
+ TypeImpl.equivalentArrays(typeArguments, other.typeArguments);
+ }
+ return false;
+ }
+
+ @override
void appendTo(StringBuffer buffer, Set<TypeImpl> visitedTypes) {
if (visitedTypes.add(this)) {
buffer.write(name);
@@ -2521,6 +2587,9 @@
*/
final Element _element;
+ @override
+ bool isEquivalentTo(DartType other) => this == other;
+
/**
* The name of this type, or `null` if the type does not have a name.
*/
@@ -2704,6 +2773,31 @@
}
/**
+ * Return `true` if corresponding elements of the [first] and [second] lists
+ * of type arguments are all equivalent.
+ */
+ static bool equivalentArrays(List<DartType> first, List<DartType> second) {
+ if (first.length != second.length) {
+ return false;
+ }
+ for (int i = 0; i < first.length; i++) {
+ if (first[i] == null) {
+ AnalysisEngine.instance.logger
+ .logInformation('Found null type argument in TypeImpl.equalArrays');
+ return second[i] == null;
+ } else if (second[i] == null) {
+ AnalysisEngine.instance.logger
+ .logInformation('Found null type argument in TypeImpl.equalArrays');
+ return false;
+ }
+ if (!first[i].isEquivalentTo(second[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
* Return a list containing the results of using the given [argumentTypes] and
* [parameterTypes] to perform a substitution on all of the given [types].
*
@@ -2772,6 +2866,24 @@
return false;
}
+ @override
+ bool isEquivalentTo(DartType other) {
+ if (other is TypeParameterTypeImpl && element == other.element) {
+ if (_comparingBounds) {
+ // If we're comparing bounds already, then we only need type variable
+ // equality.
+ return true;
+ }
+ _comparingBounds = true;
+ try {
+ return bound.isEquivalentTo(other.bound);
+ } finally {
+ _comparingBounds = false;
+ }
+ }
+ return false;
+ }
+
/**
* Append a textual representation of this type to the given [buffer]. The set
* of [visitedTypes] is used to prevent infinite recursion.
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index 29e93e1..c3cdad5 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -1701,6 +1701,13 @@
"the base class does not implement the mixin's supertype "
"constraint '{1}'");
+ static const CompileTimeErrorCode MIXIN_INFERENCE_NO_POSSIBLE_SUBSTITUTION =
+ const CompileTimeErrorCode(
+ 'MIXIN_INFERENCE_NO_POSSIBLE_SUBSTITUTION',
+ "Type parameters could not be inferred for the mixin '{0}' because "
+ "no type parameter substitution could be found matching the mixin's "
+ "supertype constraints");
+
/**
* 9 Mixins: It is a compile-time error if a mixin is derived from a class
* whose superclass is not Object.
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index a5e5ca7..e9fed4b 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -20,6 +20,7 @@
optional,
Parser;
import 'package:front_end/src/fasta/scanner.dart' hide StringToken;
+import 'package:front_end/src/scanner/errors.dart' show translateErrorToken;
import 'package:front_end/src/scanner/token.dart'
show
StringToken,
@@ -39,6 +40,7 @@
messageDirectiveAfterDeclaration,
messageFieldInitializerOutsideConstructor,
messageIllegalAssignmentToNonAssignable,
+ messageInterpolationInUri,
messageMissingAssignableSelector,
messageNativeClauseShouldBeAnnotation,
messageStaticConstructor;
@@ -1583,6 +1585,16 @@
StringLiteral libraryUri = pop();
StringLiteral value = popIfNotNull(equalSign);
+ if (value is StringInterpolation) {
+ for (var child in value.childEntities) {
+ if (child is InterpolationExpression) {
+ // This error is reported in OutlineBuilder.endLiteralString
+ handleRecoverableError(
+ messageInterpolationInUri, child.beginToken, child.endToken);
+ break;
+ }
+ }
+ }
DottedName name = pop();
push(ast.configuration(ifKeyword, leftParen, name, equalSign, value,
leftParen?.endGroup, libraryUri));
@@ -1831,9 +1843,13 @@
return;
}
debugEvent("Error: ${message.message}");
- int offset = startToken.offset;
- int length = endToken.end - offset;
- addCompileTimeError(message, offset, length);
+ if (message.code.analyzerCode == null && startToken is ErrorToken) {
+ translateErrorToken(startToken, errorReporter.reportScannerError);
+ } else {
+ int offset = startToken.offset;
+ int length = endToken.end - offset;
+ addCompileTimeError(message, offset, length);
+ }
}
@override
@@ -2186,8 +2202,7 @@
if (parameters?.parameters != null) {
parameters.parameters.forEach((FormalParameter param) {
if (param is FieldFormalParameter) {
- // Added comment in OutlineBuilder.endMethod at the location
- // where this error could be reported.
+ // This error is reported in the BodyBuilder.endFormalParameter.
handleRecoverableError(messageFieldInitializerOutsideConstructor,
param.thisKeyword, param.thisKeyword);
}
diff --git a/pkg/analyzer/lib/src/fasta/error_converter.dart b/pkg/analyzer/lib/src/fasta/error_converter.dart
index 81e09c5..df8586b 100644
--- a/pkg/analyzer/lib/src/fasta/error_converter.dart
+++ b/pkg/analyzer/lib/src/fasta/error_converter.dart
@@ -286,6 +286,10 @@
errorReporter?.reportErrorForOffset(
ScannerErrorCode.ILLEGAL_CHARACTER, offset, length);
return;
+ case "INITIALIZED_VARIABLE_IN_FOR_EACH":
+ errorReporter?.reportErrorForOffset(
+ ParserErrorCode.INITIALIZED_VARIABLE_IN_FOR_EACH, offset, length);
+ return;
case "INVALID_ASSIGNMENT":
var type1 = arguments['type'];
var type2 = arguments['type2'];
@@ -295,6 +299,10 @@
length,
[type1, type2]);
return;
+ case "INVALID_LITERAL_IN_CONFIGURATION":
+ errorReporter?.reportErrorForOffset(
+ ParserErrorCode.INVALID_LITERAL_IN_CONFIGURATION, offset, length);
+ return;
case "INVALID_AWAIT_IN_FOR":
errorReporter?.reportErrorForOffset(
ParserErrorCode.INVALID_AWAIT_IN_FOR, offset, length);
@@ -610,6 +618,13 @@
reportByCode(code.analyzerCode, offset, length, message);
}
+ void reportScannerError(
+ ScannerErrorCode errorCode, int offset, List<Object> arguments) {
+ // TODO(danrubel): update client to pass length in addition to offset.
+ int length = 1;
+ errorReporter?.reportErrorForOffset(errorCode, offset, length, arguments);
+ }
+
void _reportByCode(
ErrorCode errorCode, Message message, int offset, int length) {
if (errorReporter != null) {
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 41b1d43..abd1238 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -6206,6 +6206,7 @@
NamedCompilationUnitMember node, WithClause withClause) {
if (withClause == null) return;
if (!_options.enableSuperMixins) return;
+ if (!_options.strongMode) return;
ClassElement classElement = node.element;
var type = classElement.type;
var supertype = classElement.supertype;
@@ -6216,10 +6217,26 @@
if (typeName.typeArguments != null) continue;
var mixinElement = typeName.name.staticElement;
if (mixinElement is ClassElement) {
- var mixinSupertypeConstraint = mixinElement.supertype;
- if (mixinSupertypeConstraint.element.typeParameters.isNotEmpty) {
- _findInterfaceTypeForMixin(
- typeName, mixinSupertypeConstraint, supertypesForMixinInference);
+ var mixinSupertypeConstraints =
+ _typeSystem.gatherMixinSupertypeConstraints(mixinElement);
+ if (mixinSupertypeConstraints.isNotEmpty) {
+ var matchingInterfaceTypes = _findInterfaceTypesForConstraints(
+ typeName, mixinSupertypeConstraints, supertypesForMixinInference);
+ if (matchingInterfaceTypes != null) {
+ // Try to pattern match matchingInterfaceType against
+ // mixinSupertypeConstraint to find the correct set of type
+ // parameters to apply to the mixin.
+ var matchedType = _typeSystem.matchSupertypeConstraints(
+ mixinElement,
+ mixinSupertypeConstraints,
+ matchingInterfaceTypes);
+ if (matchedType == null) {
+ _errorReporter.reportErrorForToken(
+ CompileTimeErrorCode.MIXIN_INFERENCE_NO_POSSIBLE_SUBSTITUTION,
+ typeName.name.beginToken,
+ [typeName]);
+ }
+ }
}
ClassElementImpl.collectAllSupertypes(
supertypesForMixinInference, mixinElement.type, type);
@@ -6343,7 +6360,25 @@
isDeclarationCast: isDeclarationCast);
}
- void _findInterfaceTypeForMixin(TypeName mixin,
+ List<InterfaceType> _findInterfaceTypesForConstraints(
+ TypeName mixin,
+ List<InterfaceType> supertypeConstraints,
+ List<InterfaceType> interfaceTypes) {
+ var result = <InterfaceType>[];
+ for (var constraint in supertypeConstraints) {
+ var interfaceType =
+ _findInterfaceTypeForMixin(mixin, constraint, interfaceTypes);
+ if (interfaceType == null) {
+ // No matching interface type found, so inference fails. The error has
+ // already been reported.
+ return null;
+ }
+ result.add(interfaceType);
+ }
+ return result;
+ }
+
+ InterfaceType _findInterfaceTypeForMixin(TypeName mixin,
InterfaceType supertypeConstraint, List<InterfaceType> interfaceTypes) {
var element = supertypeConstraint.element;
InterfaceType foundInterfaceType;
@@ -6367,6 +6402,7 @@
mixin.name.beginToken,
[mixin, supertypeConstraint]);
}
+ return foundInterfaceType;
}
MethodElement _findOverriddenMemberThatMustCallSuper(MethodDeclaration node) {
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index fb56381..d580ab9 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -9787,6 +9787,7 @@
element.declaredReturnType = _computeReturnType(node.returnType);
element.type = new FunctionTypeImpl(element);
_inferSetterReturnType(element);
+ _inferOperatorReturnType(element);
if (element is PropertyAccessorElement) {
PropertyAccessorElement accessor = element as PropertyAccessorElement;
PropertyInducingElementImpl variable =
@@ -10043,6 +10044,20 @@
}
/**
+ * In strong mode we infer "void" as the return type of operator []= (as void
+ * is the only legal return type for []=). This allows us to give better
+ * errors later if an invalid type is returned.
+ */
+ void _inferOperatorReturnType(ExecutableElementImpl element) {
+ if (_strongMode &&
+ element.isOperator &&
+ element.name == '[]=' &&
+ element.hasImplicitReturnType) {
+ element.declaredReturnType = VoidTypeImpl.instance;
+ }
+ }
+
+ /**
* Record that the static type of the given node is the given type.
*
* @param expression the node whose type is to be recorded
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index 41f0e15..a206cdf 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -1112,6 +1112,44 @@
*/
bool get isStrong;
+ List<InterfaceType> gatherMixinSupertypeConstraints(
+ ClassElement mixinElement) {
+ var mixinSupertypeConstraints = <InterfaceType>[];
+ void addIfGeneric(InterfaceType type) {
+ if (type.element.typeParameters.isNotEmpty) {
+ mixinSupertypeConstraints.add(type);
+ }
+ }
+
+ addIfGeneric(mixinElement.supertype);
+ mixinElement.mixins.forEach(addIfGeneric);
+ return mixinSupertypeConstraints;
+ }
+
+ /// Attempts to find the appropriate substitution for [typeParameters] that can
+ /// be applied to [src] to make it equal to [dest]. If no such substitution can
+ /// be found, `null` is returned.
+ InterfaceType matchSupertypeConstraints(
+ ClassElement mixinElement, List<DartType> srcs, List<DartType> dests) {
+ var typeParameters = mixinElement.typeParameters;
+ var inferrer = new _GenericInferrer(typeProvider, this, typeParameters);
+ for (int i = 0; i < srcs.length; i++) {
+ inferrer.constrainReturnType(srcs[i], dests[i]);
+ inferrer.constrainReturnType(dests[i], srcs[i]);
+ }
+ var result = inferrer.infer(mixinElement.type, typeParameters,
+ considerExtendsClause: false);
+ for (int i = 0; i < srcs.length; i++) {
+ if (!srcs[i]
+ .substitute2(result.typeArguments, mixinElement.type.typeArguments)
+ .isEquivalentTo(dests[i])) {
+ // Failed to find an appropriate substitution
+ return null;
+ }
+ }
+ return result;
+ }
+
/**
* The provider of types for the system
*/
@@ -1711,7 +1749,8 @@
/// including argument types, and must not conclude `?` for any type formal.
T infer<T extends ParameterizedType>(
T genericType, List<TypeParameterElement> typeFormals,
- {ErrorReporter errorReporter,
+ {bool considerExtendsClause: true,
+ ErrorReporter errorReporter,
AstNode errorNode,
bool downwardsInferPhase: false}) {
var fnTypeParams = TypeParameterTypeImpl.getTypes(typeFormals);
@@ -1731,7 +1770,7 @@
var typeParamBound = typeParam.bound;
_TypeConstraint extendsClause;
- if (!typeParamBound.isDynamic) {
+ if (considerExtendsClause && !typeParamBound.isDynamic) {
extendsClause = new _TypeConstraint.fromExtends(typeParam,
typeParam.bound.substitute2(inferredTypes, fnTypeParams));
}
diff --git a/pkg/analyzer/lib/src/summary/link.dart b/pkg/analyzer/lib/src/summary/link.dart
index 6a75797..759c3b4 100644
--- a/pkg/analyzer/lib/src/summary/link.dart
+++ b/pkg/analyzer/lib/src/summary/link.dart
@@ -671,12 +671,15 @@
var mixin = _computeInterfaceType(entity);
var mixinElement = mixin.element;
var slot = entity.refinedSlot;
- if (slot != 0 && mixinElement.typeParameters.isNotEmpty) {
+ if (slot != 0 &&
+ mixinElement.typeParameters.isNotEmpty &&
+ library._linker.strongMode) {
CompilationUnitElementForLink enclosingElement =
this.enclosingElement;
if (enclosingElement is CompilationUnitElementInBuildUnit) {
- var mixinSupertypeConstraint = mixinElement.supertype;
- if (mixinSupertypeConstraint.element.typeParameters.isNotEmpty) {
+ var mixinSupertypeConstraints = context.typeSystem
+ .gatherMixinSupertypeConstraints(mixinElement);
+ if (mixinSupertypeConstraints.isNotEmpty) {
if (supertypesForMixinInference == null) {
supertypesForMixinInference = <InterfaceType>[];
ClassElementImpl.collectAllSupertypes(
@@ -686,33 +689,23 @@
supertypesForMixinInference, previousMixin, type);
}
}
- var matchingInterfaceType = _findInterfaceTypeForElement(
- mixinSupertypeConstraint.element,
- supertypesForMixinInference);
- // TODO(paulberry): If matchingInterfaceType is null, that's an
- // error. Also, if there are multiple matching interface types
- // that use different type parameters, that's also an error. But
- // we can't report errors from the linker, so we just use the
- // first matching interface type (if there is one) and hope for
- // the best. The error detection logic will have to be
- // implemented in the ErrorVerifier.
- if (matchingInterfaceType != null) {
- // TODO(paulberry): now we should pattern match
- // matchingInterfaceType against mixinSupertypeConstraint to
- // find the correct set of type parameters to apply to the
- // mixin. But as a quick hack, we assume that the mixin just
- // passes its type parameters through to the supertype
- // constraint (that is, each type in
- // mixinSupertypeConstraint.typeParameters should be a
- // TypeParameterType pointing to the corresponding element of
- // mixinElement.typeParameters). To avoid a complete disaster
- // if this assumption is wrong, we only do the inference if the
- // number of type arguments applied to mixinSupertypeConstraint
- // matches the number of type parameters accepted by the mixin.
- if (mixinSupertypeConstraint.typeArguments.length ==
- mixinElement.typeParameters.length) {
- mixin = mixinElement.type
- .instantiate(matchingInterfaceType.typeArguments);
+ var matchingInterfaceTypes = _findInterfaceTypesForConstraints(
+ mixinSupertypeConstraints, supertypesForMixinInference);
+ // Note: if matchingInterfaceType is null, that's an error. Also,
+ // if there are multiple matching interface types that use
+ // different type parameters, that's also an error. But we can't
+ // report errors from the linker, so we just use the
+ // first matching interface type (if there is one). The error
+ // detection logic is implemented in the ErrorVerifier.
+ if (matchingInterfaceTypes != null) {
+ // Try to pattern match matchingInterfaceTypes against
+ // mixinSupertypeConstraints to find the correct set of type
+ // parameters to apply to the mixin.
+ var inferredMixin = context.typeSystem
+ .matchSupertypeConstraints(mixinElement,
+ mixinSupertypeConstraints, matchingInterfaceTypes);
+ if (inferredMixin != null) {
+ mixin = inferredMixin;
enclosingElement._storeLinkedType(slot, mixin, this);
}
}
@@ -831,6 +824,21 @@
return enclosingElement.enclosingElement._linker.typeProvider.objectType;
}
+ List<InterfaceType> _findInterfaceTypesForConstraints(
+ List<InterfaceType> constraints, List<InterfaceType> interfaceTypes) {
+ var result = <InterfaceType>[];
+ for (var constraint in constraints) {
+ var interfaceType =
+ _findInterfaceTypeForElement(constraint.element, interfaceTypes);
+ if (interfaceType == null) {
+ // No matching interface type found, so inference fails.
+ return null;
+ }
+ result.add(interfaceType);
+ }
+ return result;
+ }
+
InterfaceType _findInterfaceTypeForElement(
ClassElement element, List<InterfaceType> interfaceTypes) {
for (var interfaceType in interfaceTypes) {
diff --git a/pkg/analyzer/test/generated/compile_time_error_code_driver_test.dart b/pkg/analyzer/test/generated/compile_time_error_code_driver_test.dart
index c901d70..4e73768 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code_driver_test.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code_driver_test.dart
@@ -16,4 +16,8 @@
class CompileTimeErrorCodeTest_Driver extends CompileTimeErrorCodeTest {
@override
bool get enableNewAnalysisDriver => true;
+
+ @override // Passes with driver
+ test_mixinInference_recursiveSubtypeCheck() =>
+ super.test_mixinInference_recursiveSubtypeCheck();
}
diff --git a/pkg/analyzer/test/generated/compile_time_error_code_kernel_test.dart b/pkg/analyzer/test/generated/compile_time_error_code_kernel_test.dart
index f766e7c..00619ba 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code_kernel_test.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code_kernel_test.dart
@@ -1725,6 +1725,16 @@
@override
@failingTest
+ test_mixinInference_conflictingSubstitution() =>
+ super.test_mixinInference_conflictingSubstitution();
+
+ @override
+ @failingTest
+ test_mixinInference_impossibleSubstitution() =>
+ super.test_mixinInference_impossibleSubstitution();
+
+ @override
+ @failingTest
test_mixinInference_noMatchingClass() =>
super.test_mixinInference_noMatchingClass();
diff --git a/pkg/analyzer/test/generated/compile_time_error_code_test.dart b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
index 706e1c6..184d0e3 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code_test.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
@@ -3955,9 +3955,40 @@
verify([source]);
}
+ test_mixinInference_conflictingSubstitution() async {
+ AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+ options.enableSuperMixins = true;
+ options.strongMode = true;
+ resetWith(options: options);
+ Source source = addSource('''
+abstract class A<T> {}
+class M<T> extends A<Map<T, T>> {}
+class C extends A<Map<int, String>> with M {}
+''');
+ await computeAnalysisResult(source);
+ assertErrors(source,
+ [CompileTimeErrorCode.MIXIN_INFERENCE_NO_POSSIBLE_SUBSTITUTION]);
+ }
+
+ test_mixinInference_impossibleSubstitution() async {
+ AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+ options.enableSuperMixins = true;
+ options.strongMode = true;
+ resetWith(options: options);
+ Source source = addSource('''
+abstract class A<T> {}
+class M<T> extends A<Map<T, T>> {}
+class C extends A<List<int>> with M {}
+''');
+ await computeAnalysisResult(source);
+ assertErrors(source,
+ [CompileTimeErrorCode.MIXIN_INFERENCE_NO_POSSIBLE_SUBSTITUTION]);
+ }
+
test_mixinInference_matchingClass() async {
AnalysisOptionsImpl options = new AnalysisOptionsImpl();
options.enableSuperMixins = true;
+ options.strongMode = true;
resetWith(options: options);
Source source = addSource('''
abstract class A<T> {}
@@ -3972,6 +4003,7 @@
test_mixinInference_matchingClass_inPreviousMixin() async {
AnalysisOptionsImpl options = new AnalysisOptionsImpl();
options.enableSuperMixins = true;
+ options.strongMode = true;
resetWith(options: options);
Source source = addSource('''
abstract class A<T> {}
@@ -3987,6 +4019,7 @@
test_mixinInference_noMatchingClass() async {
AnalysisOptionsImpl options = new AnalysisOptionsImpl();
options.enableSuperMixins = true;
+ options.strongMode = true;
resetWith(options: options);
Source source = addSource('''
abstract class A<T> {}
@@ -4002,6 +4035,7 @@
test_mixinInference_noMatchingClass_constraintSatisfiedByImplementsClause() async {
AnalysisOptionsImpl options = new AnalysisOptionsImpl();
options.enableSuperMixins = true;
+ options.strongMode = true;
resetWith(options: options);
Source source = addSource('''
abstract class A<T> {}
@@ -4017,6 +4051,7 @@
test_mixinInference_noMatchingClass_namedMixinApplication() async {
AnalysisOptionsImpl options = new AnalysisOptionsImpl();
options.enableSuperMixins = true;
+ options.strongMode = true;
resetWith(options: options);
Source source = addSource('''
abstract class A<T> {}
@@ -4032,6 +4067,7 @@
test_mixinInference_noMatchingClass_noSuperclassConstraint() async {
AnalysisOptionsImpl options = new AnalysisOptionsImpl();
options.enableSuperMixins = true;
+ options.strongMode = true;
resetWith(options: options);
Source source = addSource('''
abstract class A<T> {}
@@ -4046,6 +4082,7 @@
test_mixinInference_noMatchingClass_typeParametersSupplied() async {
AnalysisOptionsImpl options = new AnalysisOptionsImpl();
options.enableSuperMixins = true;
+ options.strongMode = true;
resetWith(options: options);
Source source = addSource('''
abstract class A<T> {}
@@ -4057,6 +4094,45 @@
assertNoErrors(source);
}
+ @failingTest // Does not work with old task model
+ test_mixinInference_recursiveSubtypeCheck() async {
+ // See dartbug.com/32353 for a detailed explanation.
+ AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+ options.enableSuperMixins = true;
+ options.strongMode = true;
+ resetWith(options: options);
+ Source source = addSource('''
+class ioDirectory implements ioFileSystemEntity {}
+
+class ioFileSystemEntity {}
+
+abstract class _LocalDirectory
+ extends _LocalFileSystemEntity<_LocalDirectory, ioDirectory>
+ with ForwardingDirectory, DirectoryAddOnsMixin {}
+
+abstract class _LocalFileSystemEntity<T extends FileSystemEntity,
+ D extends ioFileSystemEntity> extends ForwardingFileSystemEntity<T, D> {}
+
+abstract class FileSystemEntity implements ioFileSystemEntity {}
+
+abstract class ForwardingFileSystemEntity<T extends FileSystemEntity,
+ D extends ioFileSystemEntity> implements FileSystemEntity {}
+
+
+abstract class ForwardingDirectory<T extends Directory>
+ extends ForwardingFileSystemEntity<T, ioDirectory>
+ implements Directory {}
+
+abstract class Directory implements FileSystemEntity, ioDirectory {}
+
+abstract class DirectoryAddOnsMixin implements Directory {}
+''');
+ var analysisResult = await computeAnalysisResult(source);
+ assertNoErrors(source);
+ var mixins = analysisResult.unit.element.getType('_LocalDirectory').mixins;
+ expect(mixins[0].toString(), 'ForwardingDirectory<_LocalDirectory>');
+ }
+
test_mixinInheritsFromNotObject_classDeclaration_extends() async {
Source source = addSource(r'''
class A {}
diff --git a/pkg/analyzer/test/generated/non_error_resolver_driver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_driver_test.dart
index 7cfa206..d02bde0 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_driver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_driver_test.dart
@@ -19,4 +19,16 @@
@override // Passes with driver
test_infer_mixin() => super.test_infer_mixin();
+
+ @override // Passes with driver
+ test_infer_mixin_multiplyConstrained() =>
+ super.test_infer_mixin_multiplyConstrained();
+
+ @override // Passes with driver
+ test_infer_mixin_with_substitution() =>
+ super.test_infer_mixin_with_substitution();
+
+ @override // Passes with driver
+ test_infer_mixin_with_substitution_functionType() =>
+ super.test_infer_mixin_with_substitution_functionType();
}
diff --git a/pkg/analyzer/test/generated/non_error_resolver_kernel_test.dart b/pkg/analyzer/test/generated/non_error_resolver_kernel_test.dart
index aab1574..c52404a 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_kernel_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_kernel_test.dart
@@ -191,6 +191,23 @@
return super.test_genericTypeAlias_invalidGenericFunctionType();
}
+ @override // passes with kernel
+ test_infer_mixin() => super.test_infer_mixin();
+
+ @override // Passes with kernel
+ test_infer_mixin_multiplyConstrained() =>
+ super.test_infer_mixin_multiplyConstrained();
+
+ @override
+ @failingTest
+ test_infer_mixin_with_substitution() =>
+ super.test_infer_mixin_with_substitution();
+
+ @override
+ @failingTest
+ test_infer_mixin_with_substitution_functionType() =>
+ super.test_infer_mixin_with_substitution_functionType();
+
@override
@failingTest
@potentialAnalyzerProblem
diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
index 23fd626..29f7980 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -2707,6 +2707,7 @@
test_infer_mixin() async {
AnalysisOptionsImpl options = new AnalysisOptionsImpl();
options.enableSuperMixins = true;
+ options.strongMode = true;
resetWith(options: options);
Source source = addSource('''
abstract class A<T> {}
@@ -2727,6 +2728,86 @@
expect(classC.mixins[0].toString(), 'M<B>');
}
+ @failingTest // Does not work with old task model
+ test_infer_mixin_multiplyConstrained() async {
+ AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+ options.enableSuperMixins = true;
+ options.strongMode = true;
+ resetWith(options: options);
+ Source source = addSource('''
+abstract class A<T> {}
+
+abstract class B<U> {}
+
+class C {}
+
+class D {}
+
+class M<T, U> extends A<T> with B<U> {}
+
+class E extends A<C> implements B<D> {}
+
+class F extends E with M {}
+''');
+ TestAnalysisResult analysisResult = await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ CompilationUnit unit = analysisResult.unit;
+ ClassElement classF =
+ resolutionMap.elementDeclaredByCompilationUnit(unit).getType('F');
+ expect(classF.mixins, hasLength(1));
+ expect(classF.mixins[0].toString(), 'M<C, D>');
+ }
+
+ @failingTest // Does not work with old task model
+ test_infer_mixin_with_substitution() async {
+ AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+ options.enableSuperMixins = true;
+ options.strongMode = true;
+ resetWith(options: options);
+ Source source = addSource('''
+abstract class A<T> {}
+
+class B {}
+
+class M<T> extends A<List<T>> {}
+
+class C extends A<List<B>> with M {}
+''');
+ TestAnalysisResult analysisResult = await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ CompilationUnit unit = analysisResult.unit;
+ ClassElement classC =
+ resolutionMap.elementDeclaredByCompilationUnit(unit).getType('C');
+ expect(classC.mixins, hasLength(1));
+ expect(classC.mixins[0].toString(), 'M<B>');
+ }
+
+ @failingTest // Does not work with old task model
+ test_infer_mixin_with_substitution_functionType() async {
+ AnalysisOptionsImpl options = new AnalysisOptionsImpl();
+ options.enableSuperMixins = true;
+ options.strongMode = true;
+ resetWith(options: options);
+ Source source = addSource('''
+abstract class A<T> {}
+
+class B {}
+
+class M<T, U> extends A<T Function(U)> {}
+
+class C extends A<int Function(String)> with M {}
+''');
+ TestAnalysisResult analysisResult = await computeAnalysisResult(source);
+ assertNoErrors(source);
+ CompilationUnit unit = analysisResult.unit;
+ ClassElement classC =
+ resolutionMap.elementDeclaredByCompilationUnit(unit).getType('C');
+ expect(classC.mixins, hasLength(1));
+ expect(classC.mixins[0].toString(), 'M<int, String>');
+ }
+
test_initializingFormalForNonExistentField() async {
Source source = addSource(r'''
class A {
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index b28d44d..5fe1d70 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -382,14 +382,6 @@
@override
@failingTest
- void test_initializedVariableInForEach() {
- // TODO(brianwilkerson) Wrong errors:
- // Expected 1 errors of type ParserErrorCode.INITIALIZED_VARIABLE_IN_FOR_EACH, found 0
- super.test_initializedVariableInForEach();
- }
-
- @override
- @failingTest
void test_invalidCodePoint() {
// TODO(brianwilkerson) Does not recover.
// Internal problem: Compiler cannot run without a compiler context.
@@ -512,14 +504,6 @@
@override
@failingTest
- void test_invalidLiteralInConfiguration() {
- // TODO(brianwilkerson) Wrong errors:
- // Expected 1 errors of type ParserErrorCode.INVALID_LITERAL_IN_CONFIGURATION, found 0
- super.test_invalidLiteralInConfiguration();
- }
-
- @override
- @failingTest
void test_invalidOperatorAfterSuper_primaryExpression() {
// TODO(brianwilkerson) Does not recover.
// Expected: true
@@ -789,13 +773,9 @@
}
@override
- @failingTest
void test_method_invalidTypeParameterExtendsComment() {
- // TODO(brianwilkerson) Wrong errors:
- // Expected 2 errors of type ParserErrorCode.EXPECTED_TOKEN, found 0;
- // 2 errors of type ParserErrorCode.MISSING_IDENTIFIER, found 0;
- // 1 errors of type ParserErrorCode.MISSING_FUNCTION_BODY, found 0
- super.test_method_invalidTypeParameterExtendsComment();
+ // Fasta no longer supports type comment based syntax
+ // super.test_method_invalidTypeParameterExtendsComment();
}
@override
@@ -950,22 +930,6 @@
@override
@failingTest
- void test_missingTerminatorForParameterGroup_named() {
- // TODO(brianwilkerson) Wrong errors:
- // Expected 1 errors of type ScannerErrorCode.EXPECTED_TOKEN, found 0
- super.test_missingTerminatorForParameterGroup_named();
- }
-
- @override
- @failingTest
- void test_missingTerminatorForParameterGroup_optional() {
- // TODO(brianwilkerson) Wrong errors:
- // Expected 1 errors of type ScannerErrorCode.EXPECTED_TOKEN, found 0
- super.test_missingTerminatorForParameterGroup_optional();
- }
-
- @override
- @failingTest
void test_missingVariableInForEach() {
// TODO(brianwilkerson) Does not recover.
// type 'BinaryExpressionImpl' is not a subtype of type 'VariableDeclarationStatement' in type cast where
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index 9a03215..92e1c59 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -3570,8 +3570,8 @@
parseCompilationUnit("void f(int Function(",
errors: usingFastaParser
? [
- expectedError(ScannerErrorCode.EXPECTED_TOKEN, 6, 1),
- expectedError(ScannerErrorCode.EXPECTED_TOKEN, 19, 1),
+ expectedError(ScannerErrorCode.EXPECTED_TOKEN, 20, 1),
+ expectedError(ScannerErrorCode.EXPECTED_TOKEN, 20, 1),
expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 8),
expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 20, 0),
]
@@ -3829,7 +3829,7 @@
Configuration configuration = parser.parseConfiguration();
expectNotNullIfNoErrors(configuration);
listener.assertErrors([
- expectedError(ParserErrorCode.INVALID_LITERAL_IN_CONFIGURATION, 9, 9)
+ expectedError(ParserErrorCode.INVALID_LITERAL_IN_CONFIGURATION, 12, 2)
]);
}
@@ -4563,8 +4563,8 @@
FormalParameterList list = parser.parseFormalParameterList();
expectNotNullIfNoErrors(list);
if (fe.Scanner.useFasta) {
- listener
- .assertErrors([expectedError(ScannerErrorCode.EXPECTED_TOKEN, 9, 1)]);
+ listener.assertErrors(
+ [expectedError(ScannerErrorCode.EXPECTED_TOKEN, 10, 1)]);
} else {
listener.assertErrorsWithCodes(
[ParserErrorCode.MISSING_TERMINATOR_FOR_PARAMETER_GROUP]);
@@ -5296,7 +5296,7 @@
var x = "''', errors: [
expectedError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 24, 1),
fe.Scanner.useFasta
- ? expectedError(ScannerErrorCode.EXPECTED_TOKEN, 12, 1)
+ ? expectedError(ScannerErrorCode.EXPECTED_TOKEN, 25, 1)
: expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 1),
expectedError(ParserErrorCode.EXPECTED_TOKEN, 25, 0)
]);
@@ -5548,8 +5548,10 @@
expectNotNullIfNoErrors(list);
// fasta scanner generates '(a, {b, c]})' where '}' is synthetic
if (usingFastaParser) {
- listener
- .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 1)]);
+ listener.assertErrors([
+ expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 1),
+ expectedError(ScannerErrorCode.EXPECTED_TOKEN, 10, 1)
+ ]);
} else {
listener.assertErrors([
expectedError(ScannerErrorCode.EXPECTED_TOKEN, 9, 1),
@@ -5565,8 +5567,10 @@
expectNotNullIfNoErrors(list);
// fasta scanner generates '(a, [b, c}])' where ']' is synthetic
if (usingFastaParser) {
- listener
- .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 1)]);
+ listener.assertErrors([
+ expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 1),
+ expectedError(ScannerErrorCode.EXPECTED_TOKEN, 10, 1)
+ ]);
} else {
listener.assertErrors([
expectedError(ScannerErrorCode.EXPECTED_TOKEN, 4, 1),
@@ -15669,22 +15673,10 @@
for (Keyword keyword in Keyword.values) {
if (keyword.isBuiltIn || keyword.isPseudo) {
String lexeme = keyword.lexeme;
- List<ExpectedError> expectedErrors = [];
- if (lexeme == 'dynamic') {
- expectedErrors = [
- expectedError(
- ParserErrorCode.TYPE_ARGUMENTS_ON_TYPE_VARIABLE, 7, 1)
- ];
- }
- parseCompilationUnit('$lexeme<T>(x) => 0;', errors: expectedErrors);
- if (lexeme == 'dynamic') {
- expectedErrors = [
- expectedError(
- ParserErrorCode.TYPE_ARGUMENTS_ON_TYPE_VARIABLE, 16, 1)
- ];
- }
- parseCompilationUnit('class C {$lexeme<T>(x) => 0;}',
- errors: expectedErrors);
+ // The fasta type resolution phase will report an error
+ // on type arguments on `dynamic` (e.g. `dynamic<int>`).
+ parseCompilationUnit('$lexeme<T>(x) => 0;');
+ parseCompilationUnit('class C {$lexeme<T>(x) => 0;}');
}
}
}
diff --git a/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart b/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart
index 3969217..33108c9 100644
--- a/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart
+++ b/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart
@@ -17,6 +17,7 @@
void main() {
defineReflectiveSuite(() {
defineReflectiveTests(Dart2InferenceTest);
+ defineReflectiveTests(Dart2InferenceTest_Task);
});
}
@@ -902,3 +903,9 @@
}
}
}
+
+@reflectiveTest
+class Dart2InferenceTest_Task extends Dart2InferenceTest {
+ @override
+ bool get enableNewAnalysisDriver => false;
+}
diff --git a/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart b/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
index b9740ce..a0b7e60 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
@@ -182,20 +182,37 @@
* Try to determine the required context type, and configure filters.
*/
void _computeRequiredTypeAndFilters(CompletionTarget target) {
- var node = target.containingNode;
- if (node is Expression) {
- AstNode parent = node.parent;
- if (parent is VariableDeclaration) {
- _requiredType = parent.element?.type;
- } else if (parent is AssignmentExpression) {
- _requiredType = parent.leftHandSide.staticType;
- } else if (node.staticParameterElement != null) {
- _requiredType = node.staticParameterElement.type;
- } else if (parent is NamedExpression &&
- parent.staticParameterElement != null) {
- _requiredType = parent.staticParameterElement.type;
- }
+ Object entity = target.entity;
+ AstNode node = target.containingNode;
+
+ if (node is InstanceCreationExpression &&
+ node.keyword != null &&
+ node.constructorName == entity) {
+ entity = node;
+ node = node.parent;
}
+
+ if (node is AssignmentExpression &&
+ node.operator.type == TokenType.EQ &&
+ node.rightHandSide == entity) {
+ _requiredType = node.leftHandSide?.staticType;
+ } else if (node is BinaryExpression &&
+ node.operator.type == TokenType.EQ_EQ &&
+ node.rightOperand == entity) {
+ _requiredType = node.leftOperand?.staticType;
+ } else if (node is NamedExpression && node.expression == entity) {
+ _requiredType = node.staticParameterElement?.type;
+ } else if (node is SwitchCase && node.expression == entity) {
+ AstNode parent = node.parent;
+ if (parent is SwitchStatement) {
+ _requiredType = parent.expression?.staticType;
+ }
+ } else if (node is VariableDeclaration && node.initializer == entity) {
+ _requiredType = node.element?.type;
+ } else if (entity is Expression && entity.staticParameterElement != null) {
+ _requiredType = entity.staticParameterElement.type;
+ }
+
if (_requiredType == null) {
return;
}
diff --git a/pkg/compiler/lib/src/common/names.dart b/pkg/compiler/lib/src/common/names.dart
index 749c072..2b63cc3 100644
--- a/pkg/compiler/lib/src/common/names.dart
+++ b/pkg/compiler/lib/src/common/names.dart
@@ -40,6 +40,9 @@
/// The name of the getter returning the size of containers and strings.
static const String length = 'length';
+
+ /// The name of the signature function in closure classes.
+ static const String signature = 'signature';
}
/// [Name]s commonly used.
@@ -75,6 +78,9 @@
static const Name runtimeType_ = const PublicName(Identifiers.runtimeType_);
static const Name genericInstantiation = const PublicName('instantiate');
+
+ /// The name of the signature function in closure classes.
+ static const Name signature = const PublicName(Identifiers.signature);
}
/// [Selector]s commonly used.
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
index 0b7ac2b..831ff2c 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
@@ -33,6 +33,7 @@
import '../../js_backend/js_interop_analysis.dart';
import '../../js_backend/runtime_types.dart'
show RuntimeTypesChecks, RuntimeTypesNeed, RuntimeTypesEncoder;
+import '../../js_model/elements.dart' show JSignatureMethod;
import '../../native/enqueue.dart' show NativeCodegenEnqueuer;
import '../../options.dart';
import '../../universe/selector.dart' show Selector;
@@ -93,8 +94,8 @@
/// Contains the collected information the program builder used to build
/// the model.
// The collector will be filled on the first call to `buildProgram`.
- // It is stored and publicly exposed for backwards compatibility. New code
- // (and in particular new emitters) should not use it.
+ // It is publicly exposed for backwards compatibility. New code
+ // (and in particular new emitters) should not access it outside this class.
final Collector collector;
final Registry _registry;
@@ -684,13 +685,15 @@
_namer,
_rtiChecks,
_rtiEncoder,
- _jsInteropAnalysis);
+ _jsInteropAnalysis,
+ _options.useKernel,
+ _options.strongMode,
+ _options.disableRtiOptimization);
void visitMember(MemberEntity member) {
if (member.isInstanceMember && !member.isAbstract && !member.isField) {
- // TODO(herhut): Remove once _buildMethod can no longer return null.
Method method = _buildMethod(member);
- if (method != null) methods.add(method);
+ if (method != null && member is! JSignatureMethod) methods.add(method);
}
if (member.isGetter || member.isField) {
Map<Selector, SelectorConstraints> selectors =
@@ -752,7 +755,8 @@
visitStatics: true,
isHolderInterceptedClass: isInterceptedClass);
- TypeTestProperties typeTests = runtimeTypeGenerator.generateIsTests(cls,
+ TypeTestProperties typeTests = runtimeTypeGenerator.generateIsTests(
+ cls, _generatedCode,
storeFunctionTypeInMetadata: _storeFunctionTypesInMetadata);
List<StubMethod> checkedSetters = <StubMethod>[];
diff --git a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
index bb68ca8..7a88ac1 100644
--- a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
@@ -109,6 +109,9 @@
final RuntimeTypesChecks _rtiChecks;
final RuntimeTypesEncoder _rtiEncoder;
final JsInteropAnalysis _jsInteropAnalysis;
+ final bool _useKernel;
+ final bool _strongMode;
+ final bool _disableRtiOptimization;
RuntimeTypeGenerator(
this._elementEnvironment,
@@ -119,7 +122,10 @@
this._namer,
this._rtiChecks,
this._rtiEncoder,
- this._jsInteropAnalysis);
+ this._jsInteropAnalysis,
+ this._useKernel,
+ this._strongMode,
+ this._disableRtiOptimization);
TypeTestRegistry get _typeTestRegistry => emitterTask.typeTestRegistry;
@@ -143,6 +149,7 @@
/// the result. This is only possible for function types that do not contain
/// type variables.
TypeTestProperties generateIsTests(ClassEntity classElement,
+ Map<MemberEntity, jsAst.Expression> generatedCode,
{bool storeFunctionTypeInMetadata: true}) {
TypeTestProperties result = new TypeTestProperties();
@@ -173,8 +180,36 @@
result.functionTypeIndex =
emitterTask.metadataCollector.reifyType(type, outputUnit);
} else {
- jsAst.Expression encoding = _rtiEncoder.getSignatureEncoding(
- emitterTask.emitter, type, thisAccess);
+ jsAst.Expression encoding;
+ MemberEntity signature = _elementEnvironment.lookupLocalClassMember(
+ method.enclosingClass, Identifiers.signature);
+ if (_useKernel &&
+ signature != null &&
+ generatedCode[signature] != null) {
+ encoding = generatedCode[signature];
+ } else {
+ // With Dart 2, if disableRtiOptimization is true, then we might
+ // generate some code for classes that are not actually called,
+ // so following this path is "okay." Also, classes that have call
+ // methods are no longer a subtype of Function (and therefore we don't
+ // create a closure class), so this path is also acceptable.
+
+ // TODO(efortuna, johnniwinther): Verify that closures that use this
+ // path are in fact dead code. If this *not* actually dead code, we
+ // get to this point because TrivialRuntimeTypesChecksBuilder
+ // specifies that every subtype of Object and its types is "used"
+ // (ClassUse = true). However, on the codegen side, we only codegen
+ // entities that are actually reachable via treeshaking. To solve this
+ // issue, if disableRtiOptimization is turned on, we could literally
+ // in world_impact.dart loop through every subclass of Object and say
+ // that all types related to JClosureClasses are "used" so the go
+ // through the codegen queue and therefore we generate code for it.
+ // This seems not ideal though.
+ assert(!(_useKernel && _strongMode && !_disableRtiOptimization) ||
+ (_useKernel && _strongMode && !method.enclosingClass.isClosure));
+ encoding = _rtiEncoder.getSignatureEncoding(
+ emitterTask.emitter, type, thisAccess);
+ }
jsAst.Name operatorSignature = _namer.asName(_namer.operatorSignature);
result.addSignature(classElement, operatorSignature, encoding);
}
diff --git a/pkg/compiler/lib/src/js_model/elements.dart b/pkg/compiler/lib/src/js_model/elements.dart
index d1792a6..c6e9710 100644
--- a/pkg/compiler/lib/src/js_model/elements.dart
+++ b/pkg/compiler/lib/src/js_model/elements.dart
@@ -540,7 +540,7 @@
class JSignatureMethod extends JMethod {
JSignatureMethod(LibraryEntity enclosingLibrary, ClassEntity enclosingClass,
ParameterStructure parameterStructure, AsyncMarker asyncMarker)
- : super(enclosingLibrary, enclosingClass, const PublicName('\$signature'),
+ : super(enclosingLibrary, enclosingClass, Names.signature,
parameterStructure, asyncMarker,
isStatic: false, isExternal: false, isAbstract: false);
diff --git a/pkg/dart_internal/README.md b/pkg/dart_internal/README.md
new file mode 100644
index 0000000..3ce15a1
--- /dev/null
+++ b/pkg/dart_internal/README.md
@@ -0,0 +1,15 @@
+**Scary warning: This package is experimental and may deprecated in a future
+version of Dart.**
+
+This package is not intended for wide use. It provides a temporary API to
+solve the problem: "Given an object some generic type A, how do I construct an
+instance of generic type B with the same type argument(s)?"
+
+This is necessary in a few rare places in order to migrate existing code to
+Dart 2's stronger type system. Eventually, the hope is to have direct
+language support for solving this problem but we don't have time to get that
+into 2.0, so this package is provided as a temporary workaround.
+
+We will very likely remove support for this in a later version of Dart. Please
+avoid using this if you can. If you feel you *do* need to use it, please reach
+out to @munificent or @leafpetersen and let us know.
diff --git a/pkg/dart_internal/pubspec.yaml b/pkg/dart_internal/pubspec.yaml
index 49cb8dac..945aaa1 100644
--- a/pkg/dart_internal/pubspec.yaml
+++ b/pkg/dart_internal/pubspec.yaml
@@ -1,18 +1,19 @@
name: dart_internal
-version: 0.1.0-dev
+version: 0.1.1
author: "Dart Team <misc@dartlang.org>"
homepage: http://www.dartlang.org
description: >
- This package is not intended for any external use. Basically, if you don't
- personally know exactly what it's for, you're probably not the intended user.
+ This package is not intended for wide use. It provides a temporary API to
+ solve the problem: "Given an object some generic type A, how do I construct an
+ instance of generic type B with the same type argument(s)?"
- It contains functionality to enable some internal Google code to transition
- to strong mode before some anticipated language features are in place. In
- particular, it provides an API to solve the problem: "Given an object some
- generic type A, how do I construct an instance of generic type B with the
- same type argument(s)?"
-publish_to:
- # This package is not intended to be used externally (or, at least, not yet).
- none
+ This is necessary in a few rare places in order to migrate existing code to
+ Dart 2's stronger type system. Eventually, the hope is to have direct
+ language support for solving this problem but we don't have time to get that
+ into 2.0, so this package is provided as a temporary workaround.
+
+ We will very likely remove support for this in a later version of Dart.
environment:
- sdk: ">=2.0.0 <2.0.0"
+ # Restrict the upper bound so that we can remove support for this in a later
+ # version of the SDK without it being a breaking change.
+ sdk: ">=2.0.0-dev.12.0 <2.1.0"
diff --git a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
index 383507a..489c467 100644
--- a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
@@ -6039,6 +6039,7 @@
if (type == null || type.isDynamic || type.isObject) {
return isObjectMember(name);
} else if (type is InterfaceType) {
+ type = getImplementationType(type) ?? type;
var element = type.element;
if (_extensionTypes.isNativeClass(element)) {
var member = _lookupForwardedMember(element, name);
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index 99b102e..c8047fa 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -183,6 +183,9 @@
final _labelNames = new HashMap<Statement, String>.identity();
final Class _jsArrayClass;
+ final Class _jsBoolClass;
+ final Class _jsNumberClass;
+ final Class _jsStringClass;
final Class privateSymbolClass;
final Class linkedHashMapImplClass;
final Class identityHashMapImplClass;
@@ -219,6 +222,11 @@
_constants = new ConstantVisitor(nativeTypes.coreTypes),
_jsArrayClass =
nativeTypes.sdk.getClass('dart:_interceptors', 'JSArray'),
+ _jsBoolClass = nativeTypes.sdk.getClass('dart:_interceptors', 'JSBool'),
+ _jsNumberClass =
+ nativeTypes.sdk.getClass('dart:_interceptors', 'JSNumber'),
+ _jsStringClass =
+ nativeTypes.sdk.getClass('dart:_interceptors', 'JSString'),
_asyncStreamIteratorClass =
nativeTypes.sdk.getClass('dart:async', 'StreamIterator'),
privateSymbolClass =
@@ -2316,7 +2324,7 @@
type == coreTypes.objectClass) {
return isObjectMember(name);
} else if (type is InterfaceType) {
- var c = type.classNode;
+ var c = getImplementationClass(type) ?? type.classNode;
if (_extensionTypes.isNativeClass(c)) {
var member = _lookupForwardedMember(c, name);
@@ -4696,6 +4704,14 @@
return null;
}
+ Class getImplementationClass(DartType type) {
+ var t = _typeRep.typeFor(type);
+ if (t is JSNumber) return _jsNumberClass;
+ if (t is JSString) return _jsStringClass;
+ if (t is JSBoolean) return _jsBoolClass;
+ return null;
+ }
+
@override
visitAsExpression(AsExpression node) {
Expression fromExpr = node.operand;
diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart
index 1d7790c..b78c49f 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart
@@ -26,12 +26,14 @@
namedArguments = _namedArgsToSymbols(namedArguments),
typeArguments = typeArguments == null
? const []
- : typeArguments.map(wrapType).toList();
+ : new List.unmodifiable(typeArguments.map(wrapType));
static Map<Symbol, dynamic> _namedArgsToSymbols(namedArgs) {
- if (namedArgs == null) return {};
- return new Map.fromIterable(getOwnPropertyNames(namedArgs),
- key: _dartSymbol, value: (k) => JS('', '#[#]', namedArgs, k));
+ if (namedArgs == null) return const {};
+ return new Map.unmodifiable(new Map.fromIterable(
+ getOwnPropertyNames(namedArgs),
+ key: _dartSymbol,
+ value: (k) => JS('', '#[#]', namedArgs, k)));
}
}
@@ -206,7 +208,7 @@
// Names starting with _ are escaped names used to disambiguate Dart and
// JS names.
if ($name[0] === '_') {
- // Inverse of
+ // Inverse of
switch($name) {
case '_get':
return '[]';
@@ -293,7 +295,7 @@
// Apply type arguments
if ($ftype instanceof $GenericFunctionType) {
let formalCount = $ftype.formalCount;
-
+
if ($typeArgs == null) {
$typeArgs = $ftype.instantiateDefaultBounds();
} else if ($typeArgs.length != formalCount) {
diff --git a/pkg/dev_compiler/tool/input_sdk/private/js_array.dart b/pkg/dev_compiler/tool/input_sdk/private/js_array.dart
index 714ad2a..69c90ff 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/js_array.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/js_array.dart
@@ -598,17 +598,10 @@
Type get runtimeType =>
dart.wrapType(JS('', '#(#)', dart.getGenericClass(List), E));
- Iterable<E> followedBy(Iterable<E> other) sync* {
- yield* this;
- yield* other;
- }
+ Iterable<E> followedBy(Iterable<E> other) =>
+ new FollowedByIterable<E>.firstEfficient(this, other);
- Iterable<T> whereType<T>() sync* {
- for (var i = 0; i < this.length; i++) {
- var element = this[i];
- if (element is T) yield element;
- }
- }
+ Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
List<E> operator +(List<E> other) {
int totalLength = this.length + other.length;
diff --git a/pkg/dev_compiler/web/source_map_stack_trace.dart b/pkg/dev_compiler/web/source_map_stack_trace.dart
index d5c019a..8cdb4f1 100644
--- a/pkg/dev_compiler/web/source_map_stack_trace.dart
+++ b/pkg/dev_compiler/web/source_map_stack_trace.dart
@@ -56,6 +56,15 @@
}
}
+ if (!sourceUrl.startsWith('dart:') &&
+ !sourceUrl.startsWith('package:') &&
+ sourceUrl.contains('dart_sdk.js')) {
+ // This compresses the long dart_sdk URLs if SDK source maps are missing.
+ // It's no longer linkable, but neither are the properly mapped ones
+ // above.
+ sourceUrl = 'dart_sdk.js';
+ }
+
return new Frame(Uri.parse(sourceUrl), span.start.line + 1,
span.start.column + 1, _prettifyMember(frame.member));
}).where((frame) => frame != null));
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 caab6a4..18161b7 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
@@ -2033,8 +2033,7 @@
analyzerCode: "FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR",
dart2jsCode: "*fatal*",
message: r"""Field formal parameters can only be used in a constructor.""",
- tip:
- r"""Try replacing the field formal parameter with a normal parameter.""");
+ tip: r"""Try removing 'this.'.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeFinalAndCovariant = messageFinalAndCovariant;
@@ -2401,6 +2400,19 @@
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeInitializedVariableInForEach =
+ messageInitializedVariableInForEach;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageInitializedVariableInForEach = const MessageCode(
+ "InitializedVariableInForEach",
+ analyzerCode: "INITIALIZED_VARIABLE_IN_FOR_EACH",
+ dart2jsCode: "*fatal*",
+ message: r"""The loop variable in a for-each loop can't be initialized.""",
+ tip:
+ r"""Try removing the initializer, or using a different kind of loop.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<Message Function(Uri uri_)> templateInputFileNotFound =
const Template<Message Function(Uri uri_)>(
messageTemplate: r"""Input file not found: #uri.""",
@@ -2788,6 +2800,8 @@
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const MessageCode messageInterpolationInUri = const MessageCode(
"InterpolationInUri",
+ analyzerCode: "INVALID_LITERAL_IN_CONFIGURATION",
+ dart2jsCode: "*fatal*",
message: r"""Can't use string interpolation in a URI.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
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 2f12afa..db948bc 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
@@ -45,7 +45,6 @@
import '../messages.dart'
show
- messageInternalProblemBodyOnAbstractMethod,
messageNonInstanceTypeVariableUse,
messagePatchDeclarationMismatch,
messagePatchDeclarationOrigin,
@@ -53,7 +52,7 @@
import '../parser.dart' show noLength;
-import '../problems.dart' show internalProblem, unexpected;
+import '../problems.dart' show unexpected;
import '../deprecated_problems.dart' show deprecated_inputError;
@@ -103,12 +102,13 @@
KernelFunctionBuilder get actualOrigin;
void set body(Statement newBody) {
- if (newBody != null) {
- if (isAbstract) {
- return internalProblem(messageInternalProblemBodyOnAbstractMethod,
- newBody.fileOffset, fileUri);
- }
- }
+// if (newBody != null) {
+// if (isAbstract) {
+// // TODO(danrubel): Is this check needed?
+// return internalProblem(messageInternalProblemBodyOnAbstractMethod,
+// newBody.fileOffset, fileUri);
+// }
+// }
actualBody = newBody;
if (function != null) {
// A forwarding semi-stub is a method that is abstract in the source code,
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
index 568f3f9..0f9acb9 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
@@ -112,7 +112,7 @@
@override
DartType _inferExpression(ShadowTypeInferrer inferrer, DartType typeContext) {
- inferrer.inferExpression(operand, null, false);
+ inferrer.inferExpression(operand, const UnknownType(), false);
return type;
}
}
@@ -145,7 +145,7 @@
inferrer.ensureAssignable(
expectedType, actualType, condition, condition.fileOffset);
if (message != null) {
- inferrer.inferExpression(message, null, false);
+ inferrer.inferExpression(message, const UnknownType(), false);
}
}
}
@@ -260,7 +260,8 @@
}
Let section = body;
while (true) {
- inferrer.inferExpression(section.variable.initializer, null, false);
+ inferrer.inferExpression(
+ section.variable.initializer, const UnknownType(), false);
if (section.body is! Let) break;
section = section.body;
}
@@ -409,7 +410,7 @@
} else {
// Analyzer uses a null context for the RHS here.
// TODO(paulberry): improve on this.
- rhsType = inferrer.inferExpression(rhs, null, true);
+ rhsType = inferrer.inferExpression(rhs, const UnknownType(), true);
// It's not necessary to call _storeLetType for [rhs] because the RHS
// is always passed directly to the combiner; it's never stored in a
// temporary variable first.
@@ -441,7 +442,8 @@
}
_storeLetType(inferrer, replacedCombiner, combinedType);
} else {
- var rhsType = inferrer.inferExpression(rhs, writeContext, true);
+ var rhsType = inferrer.inferExpression(
+ rhs, writeContext ?? const UnknownType(), true);
var replacedRhs =
inferrer.ensureAssignable(writeContext, rhsType, rhs, writeOffset);
_storeLetType(inferrer, replacedRhs ?? rhs, rhsType);
@@ -495,7 +497,8 @@
DartType _inferReceiver(ShadowTypeInferrer inferrer) {
if (receiver != null) {
- var receiverType = inferrer.inferExpression(receiver, null, true);
+ var receiverType =
+ inferrer.inferExpression(receiver, const UnknownType(), true);
_storeLetType(inferrer, receiver, receiverType);
return receiverType;
} else if (isSuper) {
@@ -685,7 +688,7 @@
@override
void _inferStatement(ShadowTypeInferrer inferrer) {
- inferrer.inferExpression(expression, null, false);
+ inferrer.inferExpression(expression, const UnknownType(), false);
}
}
@@ -910,7 +913,7 @@
expectedType, conditionType, condition, condition.fileOffset);
}
for (var update in updates) {
- inferrer.inferExpression(update, null, false);
+ inferrer.inferExpression(update, const UnknownType(), false);
}
inferrer.inferStatement(body);
}
@@ -981,11 +984,12 @@
if (inferrer.strongMode) {
variable.type = lhsType;
}
- // - Let J = T0 if K is `_` else K.
- var rhsContext = typeContext ?? lhsType;
+ // - Let J = T0 if K is `?` else K.
// - Infer e1 in context J to get T1
- bool useLub = _forceLub || typeContext == null;
- var rhsType = inferrer.inferExpression(_rhs, rhsContext, useLub);
+ bool useLub = _forceLub || typeContext is UnknownType;
+ var rhsType = typeContext is UnknownType
+ ? inferrer.inferExpression(_rhs, lhsType, true)
+ : inferrer.inferExpression(_rhs, typeContext, _forceLub);
// - Let T = greatest closure of K with respect to `?` if K is not `_`, else
// UP(t0, t1)
// - Then the inferred type is T.
@@ -1029,7 +1033,7 @@
@override
DartType _inferExpression(ShadowTypeInferrer inferrer, DartType typeContext) {
if (write != null) {
- inferrer.inferExpression(write, null, false);
+ inferrer.inferExpression(write, const UnknownType(), false);
}
_replaceWithDesugared();
return const DynamicType();
@@ -1075,13 +1079,12 @@
var calleeType =
inferrer.getCalleeFunctionType(writeMember, receiverType, false);
DartType expectedIndexTypeForWrite;
- DartType indexContext;
+ DartType indexContext = const UnknownType();
DartType writeContext;
if (calleeType.positionalParameters.length >= 2) {
// TODO(paulberry): we ought to get a context for the index expression
// from the index formal parameter, but analyzer doesn't so for now we
// replicate its behavior.
- indexContext = null;
expectedIndexTypeForWrite = calleeType.positionalParameters[0];
writeContext = calleeType.positionalParameters[1];
}
@@ -1151,7 +1154,7 @@
@override
void _inferInitializer(ShadowTypeInferrer inferrer) {
- inferrer.inferExpression(variable.initializer, null, false);
+ inferrer.inferExpression(variable.initializer, const UnknownType(), false);
}
}
@@ -1161,7 +1164,7 @@
@override
DartType _inferExpression(ShadowTypeInferrer inferrer, DartType typeContext) {
- inferrer.inferExpression(operand, null, false);
+ inferrer.inferExpression(operand, const UnknownType(), false);
return inferrer.coreTypes.boolClass.rawType;
}
}
@@ -1174,7 +1177,7 @@
@override
DartType _inferExpression(ShadowTypeInferrer inferrer, DartType typeContext) {
IsExpression isExpression = this.operand;
- inferrer.inferExpression(isExpression.operand, null, false);
+ inferrer.inferExpression(isExpression.operand, const UnknownType(), false);
return inferrer.coreTypes.boolClass.rawType;
}
}
@@ -1660,7 +1663,8 @@
? closureContext.returnOrYieldContext
: null;
var inferredType = expression != null
- ? inferrer.inferExpression(expression, typeContext, true)
+ ? inferrer.inferExpression(
+ expression, typeContext ?? const UnknownType(), true)
: const VoidType();
// Analyzer treats bare `return` statements as having no effect on the
// inferred type of the closure. TODO(paulberry): is this what we want
@@ -1759,7 +1763,7 @@
DartType _inferExpression(ShadowTypeInferrer inferrer, DartType typeContext) {
if (!inferrer.isTopLevel) {
for (Expression expression in expressions) {
- inferrer.inferExpression(expression, null, false);
+ inferrer.inferExpression(expression, const UnknownType(), false);
}
}
return inferrer.coreTypes.stringClass.rawType;
@@ -1843,7 +1847,8 @@
@override
void _inferStatement(ShadowTypeInferrer inferrer) {
- var expressionType = inferrer.inferExpression(expression, null, true);
+ var expressionType =
+ inferrer.inferExpression(expression, const UnknownType(), true);
for (var switchCase in cases) {
for (var caseExpression in switchCase.expressions) {
inferrer.inferExpression(caseExpression, expressionType, false);
@@ -1939,7 +1944,7 @@
@override
DartType _inferExpression(ShadowTypeInferrer inferrer, DartType typeContext) {
- inferrer.inferExpression(expression, null, false);
+ inferrer.inferExpression(expression, const UnknownType(), false);
return const BottomType();
}
}
@@ -2017,6 +2022,10 @@
@override
DartType inferExpression(
Expression expression, DartType typeContext, bool typeNeeded) {
+ // `null` should never be used as the type context. An instance of
+ // `UnknownType` should be used instead.
+ assert(typeContext != null);
+
// It isn't safe to do type inference on an expression without a parent,
// because type inference might cause us to have to replace one expression
// with another, and we can only replace a node if it has a parent pointer.
@@ -2048,10 +2057,9 @@
}
@override
- DartType inferFieldTopLevel(
- ShadowField field, DartType type, bool typeNeeded) {
+ DartType inferFieldTopLevel(ShadowField field, bool typeNeeded) {
if (field.initializer == null) return const DynamicType();
- return inferExpression(field.initializer, type, typeNeeded);
+ return inferExpression(field.initializer, const UnknownType(), typeNeeded);
}
@override
@@ -2245,7 +2253,7 @@
@override
void _inferStatement(ShadowTypeInferrer inferrer) {
- var declaredType = _implicitlyTyped ? null : type;
+ var declaredType = _implicitlyTyped ? const UnknownType() : type;
DartType inferredType;
DartType initializerType;
if (initializer != null) {
@@ -2349,7 +2357,8 @@
? inferrer.coreTypes.streamClass
: inferrer.coreTypes.iterableClass);
}
- var inferredType = inferrer.inferExpression(expression, typeContext, true);
+ var inferredType = inferrer.inferExpression(
+ expression, typeContext ?? const UnknownType(), true);
closureContext.handleYield(
inferrer, isYieldStar, inferredType, expression, fileOffset);
}
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index cb8a1f9..dc3c99e 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -1367,7 +1367,7 @@
/// as in `abstract<t> foo`. In situations such as this, return the last
/// token in that type reference and assume the caller will report the error
/// and recover.
- Token skipTypeReferenceOpt(Token token) {
+ Token skipTypeReferenceOpt(Token token, bool inDeclaration) {
final Token beforeStart = token;
Token next = token.next;
@@ -1460,7 +1460,7 @@
}
return next.isIdentifier ||
- (next.isOperator && !optional('=', next)) ||
+ (inDeclaration && next.isOperator && !optional('=', next)) ||
looksLikeTypeRef
? token
: beforeStart;
@@ -2658,14 +2658,6 @@
throw new StateError("beforeName.next != name");
return parseNamedFunctionRest(beforeName, begin, formals, true);
- case TypeContinuation.VariablesDeclarationOrExpression:
- if (looksLikeType && token.isIdentifier) {
- // TODO(ahe): Generate type events and call
- // parseVariablesDeclarationNoSemicolonRest instead.
- return parseVariablesDeclarationNoSemicolon(beforeBegin);
- }
- return parseExpression(beforeBegin);
-
case TypeContinuation.NormalFormalParameter:
case TypeContinuation.NormalFormalParameterAfterVar:
parameterKind = FormalParameterKind.mandatory;
@@ -2909,10 +2901,6 @@
Function endStuff, Function handleNoStuff) {
Token next = token.next;
if (optional('<', next)) {
- if (optional('dynamic', token)) {
- reportRecoverableError(next,
- fasta.templateTypeArgumentsOnTypeVariable.withArguments('dynamic'));
- }
BeginToken begin = next;
rewriteLtEndGroupOpt(begin);
beginStuff(begin);
@@ -2987,7 +2975,7 @@
// TODO(danrubel): Consider changing the listener contract
// so that the type reference can be parsed immediately
// rather than skipped now and parsed later.
- token = skipTypeReferenceOpt(token);
+ token = skipTypeReferenceOpt(token, true);
if (token == beforeType) {
// There is no type reference.
beforeType = null;
@@ -3703,7 +3691,7 @@
// TODO(danrubel): Consider changing the listener contract
// so that the type reference can be parsed immediately
// rather than skipped now and parsed later.
- token = skipTypeReferenceOpt(token);
+ token = skipTypeReferenceOpt(token, true);
if (token == beforeType) {
// There is no type reference.
beforeType = null;
@@ -4342,7 +4330,7 @@
} else if (identical(value, 'await') && optional('for', token.next.next)) {
return parseForStatement(token.next, token.next);
} else if (identical(value, 'for')) {
- return parseForStatement(null, token);
+ return parseForStatement(token, null);
} else if (identical(value, 'rethrow')) {
return parseRethrowStatement(token);
} else if (identical(value, 'throw') && optional(';', token.next.next)) {
@@ -5538,6 +5526,7 @@
}
Token parseVariablesDeclaration(Token token) {
+ token = parseMetadataStar(token);
return parseVariablesDeclarationMaybeSemicolon(token, true);
}
@@ -5545,11 +5534,6 @@
return parseVariablesDeclarationMaybeSemicolonRest(token, true);
}
- Token parseVariablesDeclarationNoSemicolon(Token token) {
- // Only called when parsing a for loop, so this is for parsing locals.
- return parseVariablesDeclarationMaybeSemicolon(token, false);
- }
-
Token parseVariablesDeclarationNoSemicolonRest(Token token) {
// Only called when parsing a for loop, so this is for parsing locals.
return parseVariablesDeclarationMaybeSemicolonRest(token, false);
@@ -5557,7 +5541,6 @@
Token parseVariablesDeclarationMaybeSemicolon(
Token token, bool endWithSemicolon) {
- token = parseMetadataStar(token);
Token next = token.next;
MemberKind memberKind = MemberKind.Local;
@@ -5661,21 +5644,78 @@
/// declaredIdentifier 'in' expression |
/// identifier 'in' expression
/// ;
+ ///
+ /// forInitializerStatement:
+ /// localVariableDeclaration |
+ /// expression? ';'
+ /// ;
/// ```
- Token parseForStatement(Token awaitToken, Token token) {
- // TODO(brianwilkerson): Consider moving `token` to be the first parameter.
- Token forKeyword = token.next;
+ Token parseForStatement(Token token, Token awaitToken) {
+ Token forKeyword = token = token.next;
assert(awaitToken == null || optional('await', awaitToken));
+ assert(optional('for', token));
listener.beginForStatement(forKeyword);
- token = expect('for', forKeyword);
- Token leftParenthesis = token;
- expect('(', token);
- token = parseVariablesDeclarationOrExpressionOpt(token);
+
+ Token leftParenthesis = forKeyword.next;
+ if (!optional('(', leftParenthesis)) {
+ // Recovery
+ reportRecoverableError(
+ leftParenthesis, fasta.templateExpectedButGot.withArguments('('));
+ int offset = leftParenthesis.offset;
+
+ BeginToken openParen =
+ token.setNext(new SyntheticBeginToken(TokenType.OPEN_PAREN, offset));
+ Token semicolon =
+ openParen.setNext(new SyntheticToken(TokenType.SEMICOLON, offset));
+ semicolon =
+ semicolon.setNext(new SyntheticToken(TokenType.SEMICOLON, offset));
+ Token closeParen =
+ semicolon.setNext(new SyntheticToken(TokenType.CLOSE_PAREN, offset));
+ openParen.endGroup = closeParen;
+
+ closeParen.setNext(leftParenthesis);
+ leftParenthesis = openParen;
+ }
+ token = leftParenthesis;
+
+ Token beforeIdentifier;
+ final String stringValue = token.next.stringValue;
+ if (identical(stringValue, ';')) {
+ listener.handleNoExpression(token.next);
+ } else {
+ if (identical('@', stringValue) ||
+ identical('var', stringValue) ||
+ identical('final', stringValue) ||
+ identical('const', stringValue)) {
+ token = parseMetadataStar(token);
+ beforeIdentifier = skipTypeReferenceOpt(token, false);
+ // TODO(ahe, danrubel): Generate type events and call
+ // parseVariablesDeclarationNoSemicolonRest instead.
+ token = parseVariablesDeclarationMaybeSemicolon(token, false);
+ } else {
+ beforeIdentifier = skipTypeReferenceOpt(token, false);
+ if (token == beforeIdentifier) {
+ // No type found, just parse expression
+ token = parseExpression(token);
+ } else {
+ // TODO(ahe, danrubel): Generate type events and call
+ // parseVariablesDeclarationNoSemicolonRest instead.
+ token = parseMetadataStar(token);
+ token = parseVariablesDeclarationMaybeSemicolon(token, false);
+ }
+ }
+ }
+
Token next = token.next;
if (optional('in', next)) {
if (awaitToken != null && !inAsync) {
reportRecoverableError(next, fasta.messageAwaitForNotAsync);
}
+ if (beforeIdentifier != null &&
+ optional('=', beforeIdentifier.next.next)) {
+ reportRecoverableError(beforeIdentifier.next.next,
+ fasta.messageInitializedVariableInForEach);
+ }
return parseForInRest(awaitToken, forKeyword, leftParenthesis, token);
} else if (optional(':', next)) {
reportRecoverableError(next, fasta.messageColonInPlaceOfIn);
@@ -5691,24 +5731,6 @@
}
}
- /// ```
- /// forInitializerStatement:
- /// localVariableDeclaration |
- /// expression? ';'
- /// ;
- /// ```
- Token parseVariablesDeclarationOrExpressionOpt(Token token) {
- Token next = token.next;
- final String value = next.stringValue;
- if (identical(value, ';')) {
- listener.handleNoExpression(next);
- return token;
- } else if (isOneOf4(next, '@', 'var', 'final', 'const')) {
- return parseVariablesDeclarationNoSemicolon(token);
- }
- return parseType(token, TypeContinuation.VariablesDeclarationOrExpression);
- }
-
/// This method parses the portion of the forLoopParts that starts with the
/// first semicolon (the one that terminates the forInitializerStatement).
///
diff --git a/pkg/front_end/lib/src/fasta/parser/type_continuation.dart b/pkg/front_end/lib/src/fasta/parser/type_continuation.dart
index 300d819..165353e 100644
--- a/pkg/front_end/lib/src/fasta/parser/type_continuation.dart
+++ b/pkg/front_end/lib/src/fasta/parser/type_continuation.dart
@@ -43,10 +43,6 @@
/// identifier.
SendOrFunctionLiteral,
- /// Indicates that the parser has just parsed `for '('` and is looking to
- /// parse a variable declaration or expression.
- VariablesDeclarationOrExpression,
-
/// Indicates that an optional type followed by a normal formal parameter is
/// expected.
NormalFormalParameter,
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 ff5906f..a8f84fd 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -553,7 +553,7 @@
modifiers.add(Const);
}
}
- push(varFinalOrConst ?? NullValue.VarFinalOrConstToken);
+ push(varFinalOrConst?.charOffset ?? -1);
push(modifiers);
library.beginNestedDeclaration("#method", hasMembers: false);
}
@@ -634,7 +634,8 @@
if ((modifiers & externalMask) != 0) {
modifiers &= ~abstractMask;
}
- Token varFinalOrConst = pop(NullValue.VarFinalOrConstToken);
+ bool isConst = (modifiers & constMask) != 0;
+ int varFinalOrConstOffset = pop();
List<MetadataBuilder> metadata = pop();
String documentationComment = getDocumentationComment(beginToken);
library
@@ -645,14 +646,10 @@
? null
: library.computeAndValidateConstructorName(name, charOffset);
if (constructorName != null) {
- if (varFinalOrConst != null) {
- if (optional('const', varFinalOrConst) &&
- (endToken != null && !optional(';', endToken))) {
- handleRecoverableError(messageConstConstructorWithBody,
- varFinalOrConst, varFinalOrConst);
- varFinalOrConst = null;
- modifiers &= ~constMask;
- }
+ if (isConst && bodyKind != MethodBody.Abstract) {
+ addCompileTimeError(
+ messageConstConstructorWithBody, varFinalOrConstOffset, 5);
+ modifiers &= ~constMask;
}
if (returnType != null) {
// TODO(danrubel): Report this error on the return type
@@ -674,16 +671,10 @@
endToken.charOffset,
nativeMethodName);
} else {
- if (varFinalOrConst != null) {
- if (optional('const', varFinalOrConst)) {
- handleRecoverableError(
- messageConstMethod, varFinalOrConst, varFinalOrConst);
- varFinalOrConst = null;
- modifiers &= ~constMask;
- }
+ if (isConst) {
+ addCompileTimeError(messageConstMethod, varFinalOrConstOffset, 5);
+ modifiers &= ~constMask;
}
- // TODO(danrubel): report messageFieldInitializerOutsideConstructor
- // for any parameter of the form `this.fieldName`.
library.addProcedure(
documentationComment,
metadata,
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
index 5c2b314..9e4d468 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
@@ -51,8 +51,8 @@
// typeInferrer to be null. If this happens, just skip type inference for
// this field.
if (typeInferrer != null) {
- var inferredType = typeInferrer.inferDeclarationType(
- typeInferrer.inferFieldTopLevel(field, null, true));
+ var inferredType = typeInferrer
+ .inferDeclarationType(typeInferrer.inferFieldTopLevel(field, true));
if (isCircular) {
// Report the appropriate error.
_library.addCompileTimeError(
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index ae22062..9cbbcb7 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -83,7 +83,7 @@
import '../parser.dart' show noLength;
-import '../problems.dart' show unhandled;
+import '../problems.dart' show unexpected, unhandled;
import '../source/source_library_builder.dart' show SourceLibraryBuilder;
@@ -967,8 +967,8 @@
BuilderHelper helper, DartType declaredType, Expression initializer) {
assert(closureContext == null);
this.helper = helper;
- var actualType =
- inferExpression(initializer, declaredType, declaredType != null);
+ var actualType = inferExpression(
+ initializer, declaredType ?? const UnknownType(), declaredType != null);
if (declaredType != null) {
ensureAssignable(
declaredType, actualType, initializer, initializer.fileOffset);
@@ -980,8 +980,7 @@
///
/// Derived classes should provide an implementation that calls
/// [inferExpression] for the given [field]'s initializer expression.
- DartType inferFieldTopLevel(
- ShadowField field, DartType type, bool typeNeeded);
+ DartType inferFieldTopLevel(ShadowField field, bool typeNeeded);
@override
void inferFunctionBody(BuilderHelper helper, DartType returnType,
@@ -1287,7 +1286,7 @@
// replaced during type inference.
new ListLiteral(annotations);
for (var annotation in annotations) {
- inferExpression(annotation, null, false);
+ inferExpression(annotation, const UnknownType(), false);
}
this.helper = null;
}
@@ -1303,8 +1302,9 @@
Name methodName,
Arguments arguments}) {
// First infer the receiver so we can look up the method that was invoked.
- var receiverType =
- receiver == null ? thisType : inferExpression(receiver, null, true);
+ var receiverType = receiver == null
+ ? thisType
+ : inferExpression(receiver, const UnknownType(), true);
if (strongMode) {
receiverVariable?.type = receiverType;
}
@@ -1369,8 +1369,9 @@
Object interfaceMember,
Name propertyName}) {
// First infer the receiver so we can look up the getter that was invoked.
- var receiverType =
- receiver == null ? thisType : inferExpression(receiver, null, true);
+ var receiverType = receiver == null
+ ? thisType
+ : inferExpression(receiver, const UnknownType(), true);
if (strongMode) {
receiverVariable?.type = receiverType;
}
@@ -1691,11 +1692,28 @@
// where the type parameters of S0&M0 are the X0, ..., Xn that occured
// free in S0 and M0. Treat S0 and M0 as separate supertype constraints
// by recursively calling this algorithm.
+ //
+ // In some back ends (e.g., the Dart VM) the mixin application classes
+ // themselves are all eliminated by translating them to normal classes.
+ // In that case, the mixin appears as the only interface in the
+ // introduced class:
+ //
+ // class S0&M0<...> extends S0 implements M0 {}
+ var mixinSuperclass = mixinSupertype.classNode;
+ if (mixinSuperclass.mixedInType == null &&
+ mixinSuperclass.implementedTypes.length != 1) {
+ unexpected(
+ 'Compiler-generated mixin applications have a mixin or else '
+ 'implement exactly one type',
+ '$mixinSuperclass implements '
+ '${mixinSuperclass.implementedTypes.length} types',
+ mixinSuperclass.fileOffset,
+ mixinSuperclass.fileUri);
+ }
var substitution = Substitution.fromSupertype(mixinSupertype);
- var s0 =
- substitution.substituteSupertype(mixinSupertype.classNode.supertype);
- var m0 = substitution
- .substituteSupertype(mixinSupertype.classNode.mixedInType);
+ var s0 = substitution.substituteSupertype(mixinSuperclass.supertype);
+ var m0 = substitution.substituteSupertype(mixinSuperclass.mixedInType ??
+ mixinSuperclass.implementedTypes.first);
generateConstraints(hierarchy, mixinClass, baseType, s0);
generateConstraints(hierarchy, mixinClass, baseType, m0);
} else {
diff --git a/pkg/front_end/lib/src/scanner/errors.dart b/pkg/front_end/lib/src/scanner/errors.dart
index 62756b7..0e77ee52 100644
--- a/pkg/front_end/lib/src/scanner/errors.dart
+++ b/pkg/front_end/lib/src/scanner/errors.dart
@@ -130,6 +130,7 @@
default:
if (errorCode == codeUnmatchedToken) {
+ charOffset = token.begin.endToken.charOffset;
TokenType type = token.begin?.type;
if (type == TokenType.OPEN_CURLY_BRACKET ||
type == TokenType.STRING_INTERPOLATION_EXPRESSION) {
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
new file mode 100644
index 0000000..b03c6fa
--- /dev/null
+++ b/pkg/front_end/messages.status
@@ -0,0 +1,392 @@
+# 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.
+
+# Please don't add more failures to this status file of the "analyzerCode" or
+# "example" varity.
+
+AbstractClassInstantiation/analyzerCode: Fail
+AbstractClassInstantiation/example: Fail
+AbstractNotSync/analyzerCode: Fail
+AbstractNotSync/example: Fail
+AbstractRedirectedClassInstantiation/analyzerCode: Fail
+AbstractRedirectedClassInstantiation/example: Fail
+AccessError/analyzerCode: Fail
+AccessError/example: Fail
+AmbiguousSupertypes/analyzerCode: Fail
+AmbiguousSupertypes/example: Fail
+AnnotationOnEnumConstant/example: Fail
+AssertAsExpression/analyzerCode: Fail
+AssertAsExpression/example: Fail
+AssertExtraneousArgument/analyzerCode: Fail
+AssertExtraneousArgument/example: Fail
+AsyncAsIdentifier/example: Fail
+AwaitAsIdentifier/example: Fail
+AwaitNotAsync/analyzerCode: Fail
+AwaitNotAsync/example: Fail
+BuiltInIdentifierAsType/example: Fail
+BuiltInIdentifierInDeclaration/example: Fail
+CandidateFound/analyzerCode: Fail
+CandidateFound/example: Fail
+CandidateFoundIsDefaultConstructor/analyzerCode: Fail
+CandidateFoundIsDefaultConstructor/example: Fail
+CannotReadPackagesFile/analyzerCode: Fail
+CannotReadPackagesFile/example: Fail
+CannotReadSdkSpecification/analyzerCode: Fail
+CannotReadSdkSpecification/example: Fail
+CantInferPackagesFromManyInputs/analyzerCode: Fail
+CantInferPackagesFromManyInputs/example: Fail
+CantInferPackagesFromPackageUri/analyzerCode: Fail
+CantInferPackagesFromPackageUri/example: Fail
+CantInferTypeDueToCircularity/analyzerCode: Fail
+CantInferTypeDueToCircularity/example: Fail
+CantInferTypeDueToInconsistentOverrides/analyzerCode: Fail
+CantInferTypeDueToInconsistentOverrides/example: Fail
+CantUseSuperBoundedTypeForInstanceCreation/analyzerCode: Fail
+CantUseSuperBoundedTypeForInstanceCreation/example: Fail
+CatchSyntax/analyzerCode: Fail
+CatchSyntax/example: Fail
+ColonInPlaceOfIn/example: Fail
+ConflictsWithConstructor/analyzerCode: Fail
+ConflictsWithConstructor/example: Fail
+ConflictsWithFactory/analyzerCode: Fail
+ConflictsWithFactory/example: Fail
+ConflictsWithMember/analyzerCode: Fail
+ConflictsWithMember/example: Fail
+ConflictsWithMemberWarning/analyzerCode: Fail
+ConflictsWithMemberWarning/example: Fail
+ConflictsWithSetter/analyzerCode: Fail
+ConflictsWithSetter/example: Fail
+ConflictsWithSetterWarning/analyzerCode: Fail
+ConflictsWithSetterWarning/example: Fail
+ConflictsWithTypeVariable/analyzerCode: Fail
+ConflictsWithTypeVariable/example: Fail
+ConflictsWithTypeVariableCause/analyzerCode: Fail
+ConflictsWithTypeVariableCause/example: Fail
+ConstConstructorNonFinalField/analyzerCode: Fail
+ConstConstructorNonFinalField/example: Fail
+ConstConstructorNonFinalFieldCause/analyzerCode: Fail
+ConstConstructorNonFinalFieldCause/example: Fail
+ConstFieldWithoutInitializer/example: Fail
+ConstructorHasNoSuchNamedParameter/analyzerCode: Fail
+ConstructorHasNoSuchNamedParameter/example: Fail
+ConstructorNotFound/analyzerCode: Fail
+ConstructorNotFound/example: Fail
+CouldNotParseUri/analyzerCode: Fail
+CouldNotParseUri/example: Fail
+CyclicClassHierarchy/analyzerCode: Fail
+CyclicClassHierarchy/example: Fail
+CyclicTypedef/analyzerCode: Fail
+CyclicTypedef/example: Fail
+DeferredAfterPrefix/example: Fail
+DeferredPrefixDuplicated/analyzerCode: Fail
+DeferredPrefixDuplicated/example: Fail
+DeferredPrefixDuplicatedCause/analyzerCode: Fail
+DeferredPrefixDuplicatedCause/example: Fail
+DeferredTypeAnnotation/example: Fail
+DillOutlineSummary/analyzerCode: Fail
+DillOutlineSummary/example: Fail
+DuplicateDeferred/example: Fail
+DuplicatePrefix/example: Fail
+DuplicatedDefinition/analyzerCode: Fail
+DuplicatedDefinition/example: Fail
+DuplicatedExport/example: Fail
+DuplicatedExportInType/analyzerCode: Fail
+DuplicatedExportInType/example: Fail
+DuplicatedImport/analyzerCode: Fail
+DuplicatedImport/example: Fail
+DuplicatedImportInType/analyzerCode: Fail
+DuplicatedImportInType/example: Fail
+DuplicatedName/analyzerCode: Fail
+DuplicatedName/example: Fail
+DuplicatedParameterName/analyzerCode: Fail
+DuplicatedParameterName/example: Fail
+DuplicatedParameterNameCause/analyzerCode: Fail
+DuplicatedParameterNameCause/example: Fail
+Encoding/analyzerCode: Fail
+EnumConstantSameNameAsEnclosing/analyzerCode: Fail
+EnumConstantSameNameAsEnclosing/example: Fail
+ExpectedClassBody/example: Fail
+ExpectedClassMember/example: Fail
+ExpectedDeclaration/example: Fail
+ExpectedFunctionBody/example: Fail
+ExpectedOpenParens/analyzerCode: Fail
+ExpectedOpenParens/example: Fail
+ExpectedString/example: Fail
+ExpectedToken/example: Fail
+ExpectedType/example: Fail
+ExpectedUri/analyzerCode: Fail
+ExpectedUri/example: Fail
+ExportHidesExport/analyzerCode: Fail
+ExportHidesExport/example: Fail
+ExpressionNotMetadata/analyzerCode: Fail
+ExpressionNotMetadata/example: Fail
+ExtendingEnum/analyzerCode: Fail
+ExtendingEnum/example: Fail
+ExtendingRestricted/example: Fail
+ExternalFactoryRedirection/example: Fail
+FactoryNotSync/analyzerCode: Fail
+FactoryNotSync/example: Fail
+FastaCLIArgumentRequired/analyzerCode: Fail
+FastaCLIArgumentRequired/example: Fail
+FastaUsageLong/analyzerCode: Fail
+FastaUsageLong/example: Fail
+FastaUsageShort/analyzerCode: Fail
+FastaUsageShort/example: Fail
+FinalFieldWithoutInitializer/example: Fail
+FinalInstanceVariableAlreadyInitialized/analyzerCode: Fail
+FinalInstanceVariableAlreadyInitialized/example: Fail
+FinalInstanceVariableAlreadyInitializedCause/analyzerCode: Fail
+FinalInstanceVariableAlreadyInitializedCause/example: Fail
+FunctionHasNoSuchNamedParameter/analyzerCode: Fail
+FunctionHasNoSuchNamedParameter/example: Fail
+FunctionTypeDefaultValue/example: Fail
+GeneratorReturnsValue/example: Fail
+GetterNotFound/analyzerCode: Fail
+GetterNotFound/example: Fail
+GetterWithFormals/example: Fail
+IllegalMethodName/analyzerCode: Fail
+IllegalMethodName/example: Fail
+IllegalMixin/analyzerCode: Fail
+IllegalMixin/example: Fail
+IllegalMixinDueToConstructors/analyzerCode: Fail
+IllegalMixinDueToConstructors/example: Fail
+IllegalMixinDueToConstructorsCause/analyzerCode: Fail
+IllegalMixinDueToConstructorsCause/example: Fail
+ImplicitCallOfNonMethod/analyzerCode: Fail
+ImplicitCallOfNonMethod/example: Fail
+ImportHidesImport/analyzerCode: Fail
+ImportHidesImport/example: Fail
+InputFileNotFound/analyzerCode: Fail
+InputFileNotFound/example: Fail
+IntegerLiteralIsOutOfRange/example: Fail
+InternalProblemAlreadyInitialized/analyzerCode: Fail
+InternalProblemAlreadyInitialized/example: Fail
+InternalProblemBodyOnAbstractMethod/analyzerCode: Fail
+InternalProblemBodyOnAbstractMethod/example: Fail
+InternalProblemConstructorNotFound/analyzerCode: Fail
+InternalProblemConstructorNotFound/example: Fail
+InternalProblemExtendingUnmodifiableScope/analyzerCode: Fail
+InternalProblemExtendingUnmodifiableScope/example: Fail
+InternalProblemMissingContext/analyzerCode: Fail
+InternalProblemMissingContext/example: Fail
+InternalProblemMissingSeverity/analyzerCode: Fail
+InternalProblemMissingSeverity/example: Fail
+InternalProblemNotFound/analyzerCode: Fail
+InternalProblemNotFound/example: Fail
+InternalProblemNotFoundIn/analyzerCode: Fail
+InternalProblemNotFoundIn/example: Fail
+InternalProblemPreviousTokenNotFound/analyzerCode: Fail
+InternalProblemPreviousTokenNotFound/example: Fail
+InternalProblemPrivateConstructorAccess/analyzerCode: Fail
+InternalProblemPrivateConstructorAccess/example: Fail
+InternalProblemProvidedBothCompileSdkAndSdkSummary/analyzerCode: Fail
+InternalProblemProvidedBothCompileSdkAndSdkSummary/example: Fail
+InternalProblemStackNotEmpty/analyzerCode: Fail
+InternalProblemStackNotEmpty/example: Fail
+InternalProblemSuperclassNotFound/analyzerCode: Fail
+InternalProblemSuperclassNotFound/example: Fail
+InternalProblemUnexpected/analyzerCode: Fail
+InternalProblemUnexpected/example: Fail
+InternalProblemUnhandled/analyzerCode: Fail
+InternalProblemUnhandled/example: Fail
+InternalProblemUnimplemented/analyzerCode: Fail
+InternalProblemUnimplemented/example: Fail
+InternalProblemUnsupported/analyzerCode: Fail
+InternalProblemUnsupported/example: Fail
+InternalProblemUriMissingScheme/analyzerCode: Fail
+InternalProblemUriMissingScheme/example: Fail
+InternalVerificationError/analyzerCode: Fail
+InternalVerificationError/example: Fail
+InterpolationInUri/example: Fail
+InvalidCastFunctionExpr/example: Fail
+InvalidCastLiteralList/example: Fail
+InvalidCastLiteralMap/example: Fail
+InvalidCastLocalFunction/example: Fail
+InvalidCastNewExpr/example: Fail
+InvalidCastStaticMethod/example: Fail
+InvalidCastTopLevelFunction/example: Fail
+InvalidInitializer/analyzerCode: Fail
+InvalidInitializer/example: Fail
+InvalidInlineFunctionType/analyzerCode: Fail
+InvalidPackageUri/analyzerCode: Fail
+InvalidPackageUri/example: Fail
+InvalidVoid/analyzerCode: Fail
+ListLiteralTooManyTypeArguments/analyzerCode: Fail
+ListLiteralTooManyTypeArguments/example: Fail
+ListLiteralTypeArgumentMismatch/analyzerCode: Fail
+ListLiteralTypeArgumentMismatch/example: Fail
+LoadLibraryHidesMember/analyzerCode: Fail
+LoadLibraryHidesMember/example: Fail
+LoadLibraryTakesNoArguments/analyzerCode: Fail
+LoadLibraryTakesNoArguments/example: Fail
+LocalDefinitionHidesExport/analyzerCode: Fail
+LocalDefinitionHidesExport/example: Fail
+LocalDefinitionHidesImport/analyzerCode: Fail
+LocalDefinitionHidesImport/example: Fail
+MemberWithSameNameAsClass/analyzerCode: Fail
+MemberWithSameNameAsClass/example: Fail
+MetadataTypeArguments/analyzerCode: Fail
+MetadataTypeArguments/example: Fail
+MethodHasNoSuchNamedParameter/analyzerCode: Fail
+MethodHasNoSuchNamedParameter/example: Fail
+MethodNotFound/analyzerCode: Fail
+MethodNotFound/example: Fail
+MissingInput/analyzerCode: Fail
+MissingInput/example: Fail
+MissingMain/analyzerCode: Fail
+MissingMain/example: Fail
+MissingPartOf/analyzerCode: Fail
+MissingPartOf/example: Fail
+MissingPrefixInDeferredImport/example: Fail
+MixinInferenceNoMatchingClass/analyzerCode: Fail
+MixinInferenceNoMatchingClass/example: Fail
+MultipleLibraryDirectives/example: Fail
+NamedFunctionExpression/example: Fail
+NativeClauseShouldBeAnnotation/example: Fail
+NoFormals/example: Fail
+NoUnnamedConstructorInObject/analyzerCode: Fail
+NoUnnamedConstructorInObject/example: Fail
+NonInstanceTypeVariableUse/analyzerCode: Fail
+NonInstanceTypeVariableUse/example: Fail
+NotAPrefixInTypeAnnotation/example: Fail
+NotAType/example: Fail
+NotAnLvalue/analyzerCode: Fail
+NotAnLvalue/example: Fail
+OperatorMinusParameterMismatch/analyzerCode: Fail
+OperatorMinusParameterMismatch/example: Fail
+OperatorParameterMismatch0/analyzerCode: Fail
+OperatorParameterMismatch0/example: Fail
+OperatorParameterMismatch1/analyzerCode: Fail
+OperatorParameterMismatch1/example: Fail
+OperatorParameterMismatch2/analyzerCode: Fail
+OperatorParameterMismatch2/example: Fail
+OperatorWithOptionalFormals/analyzerCode: Fail
+OperatorWithOptionalFormals/example: Fail
+OverriddenMethodCause/analyzerCode: Fail
+OverriddenMethodCause/example: Fail
+OverrideFewerNamedArguments/analyzerCode: Fail
+OverrideFewerNamedArguments/example: Fail
+OverrideFewerPositionalArguments/analyzerCode: Fail
+OverrideFewerPositionalArguments/example: Fail
+OverrideMismatchNamedParameter/analyzerCode: Fail
+OverrideMismatchNamedParameter/example: Fail
+OverrideMoreRequiredArguments/analyzerCode: Fail
+OverrideMoreRequiredArguments/example: Fail
+OverrideTypeMismatchParameter/example: Fail
+OverrideTypeMismatchReturnType/example: Fail
+OverrideTypeVariablesMismatch/analyzerCode: Fail
+OverrideTypeVariablesMismatch/example: Fail
+PackageNotFound/analyzerCode: Fail
+PackageNotFound/example: Fail
+PartOfLibraryNameMismatch/analyzerCode: Fail
+PartOfLibraryNameMismatch/example: Fail
+PartOfSelf/analyzerCode: Fail
+PartOfSelf/example: Fail
+PartOfUriMismatch/analyzerCode: Fail
+PartOfUriMismatch/example: Fail
+PartOfUseUri/analyzerCode: Fail
+PartOfUseUri/example: Fail
+PartTwice/analyzerCode: Fail
+PartTwice/example: Fail
+PatchClassOrigin/analyzerCode: Fail
+PatchClassOrigin/example: Fail
+PatchClassTypeVariablesMismatch/analyzerCode: Fail
+PatchClassTypeVariablesMismatch/example: Fail
+PatchDeclarationMismatch/analyzerCode: Fail
+PatchDeclarationMismatch/example: Fail
+PatchDeclarationOrigin/analyzerCode: Fail
+PatchDeclarationOrigin/example: Fail
+PatchInjectionFailed/analyzerCode: Fail
+PatchInjectionFailed/example: Fail
+PatchNonExternal/analyzerCode: Fail
+PatchNonExternal/example: Fail
+PlatformPrivateLibraryAccess/analyzerCode: Fail
+PlatformPrivateLibraryAccess/example: Fail
+PositionalAfterNamedArgument/example: Fail
+PrefixAfterCombinator/example: Fail
+PreviousUseOfName/analyzerCode: Fail
+PreviousUseOfName/example: Fail
+PrivateNamedParameter/analyzerCode: Fail
+PrivateNamedParameter/example: Fail
+RedirectionTargetNotFound/analyzerCode: Fail
+RedirectionTargetNotFound/example: Fail
+ReturnTypeFunctionExpression/analyzerCode: Fail
+ReturnTypeFunctionExpression/example: Fail
+SdkRootNotFound/analyzerCode: Fail
+SdkRootNotFound/example: Fail
+SdkSpecificationNotFound/analyzerCode: Fail
+SdkSpecificationNotFound/example: Fail
+SdkSummaryNotFound/analyzerCode: Fail
+SdkSummaryNotFound/example: Fail
+SetterNotFound/analyzerCode: Fail
+SetterNotFound/example: Fail
+SetterNotSync/example: Fail
+SetterWithWrongNumberOfFormals/example: Fail
+SourceBodySummary/analyzerCode: Fail
+SourceBodySummary/example: Fail
+SourceOutlineSummary/analyzerCode: Fail
+SourceOutlineSummary/example: Fail
+StackOverflow/analyzerCode: Fail
+StackOverflow/example: Fail
+SuperAsExpression/analyzerCode: Fail
+SuperAsExpression/example: Fail
+SuperAsIdentifier/analyzerCode: Fail
+SuperAsIdentifier/example: Fail
+SuperNullAware/example: Fail
+SuperclassHasNoDefaultConstructor/example: Fail
+SuperclassHasNoGetter/analyzerCode: Fail
+SuperclassHasNoGetter/example: Fail
+SuperclassHasNoMethod/example: Fail
+SuperclassHasNoSetter/analyzerCode: Fail
+SuperclassHasNoSetter/example: Fail
+SuperclassMethodArgumentMismatch/analyzerCode: Fail
+SuperclassMethodArgumentMismatch/example: Fail
+SupertypeIsFunction/analyzerCode: Fail
+SupertypeIsFunction/example: Fail
+SupertypeIsIllegal/analyzerCode: Fail
+SupertypeIsIllegal/example: Fail
+SupertypeIsTypeVariable/analyzerCode: Fail
+SupertypeIsTypeVariable/example: Fail
+SwitchCaseFallThrough/analyzerCode: Fail
+SwitchCaseFallThrough/example: Fail
+ThisAccessInFieldInitializer/analyzerCode: Fail
+ThisAccessInFieldInitializer/example: Fail
+ThisAsIdentifier/analyzerCode: Fail
+ThisAsIdentifier/example: Fail
+TooFewArgumentsToConstructor/analyzerCode: Fail
+TooFewArgumentsToConstructor/example: Fail
+TooFewArgumentsToFunction/analyzerCode: Fail
+TooFewArgumentsToFunction/example: Fail
+TooFewArgumentsToMethod/analyzerCode: Fail
+TooFewArgumentsToMethod/example: Fail
+TooManyArgumentsToConstructor/analyzerCode: Fail
+TooManyArgumentsToConstructor/example: Fail
+TooManyArgumentsToFunction/analyzerCode: Fail
+TooManyArgumentsToFunction/example: Fail
+TooManyArgumentsToMethod/analyzerCode: Fail
+TooManyArgumentsToMethod/example: Fail
+TypeAfterVar/example: Fail
+TypeArgumentMismatch/analyzerCode: Fail
+TypeArgumentMismatch/example: Fail
+TypeNotFound/analyzerCode: Fail
+TypeNotFound/example: Fail
+TypeVariableDuplicatedName/analyzerCode: Fail
+TypeVariableDuplicatedName/example: Fail
+TypeVariableDuplicatedNameCause/analyzerCode: Fail
+TypeVariableDuplicatedNameCause/example: Fail
+TypeVariableInStaticContext/analyzerCode: Fail
+TypeVariableInStaticContext/example: Fail
+TypeVariableSameNameAsEnclosing/analyzerCode: Fail
+TypeVariableSameNameAsEnclosing/example: Fail
+TypedefNotFunction/analyzerCode: Fail
+TypedefNotFunction/example: Fail
+UnexpectedDollarInString/analyzerCode: Fail
+UnmatchedToken/analyzerCode: Fail
+UnresolvedPrefixInTypeAnnotation/example: Fail
+Unspecified/analyzerCode: Fail
+Unspecified/example: Fail
+UnterminatedToken/analyzerCode: Fail
+UnterminatedToken/example: Fail
+YieldAsIdentifier/example: Fail
+YieldNotGenerator/example: Fail
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 0cb16f1c..edbcd7b 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -408,7 +408,7 @@
analyzerCode: CONST_METHOD
dart2jsCode: "*fatal*"
script:
- - "class C { const C() {} }"
+ - "class C { const m() {} }"
CovariantAfterFinal:
template: "The modifier 'covariant' should be before the modifier 'final'."
@@ -615,6 +615,14 @@
script:
- "main() { switch (x) {case 1: continue;} }"
+InitializedVariableInForEach:
+ template: "The loop variable in a for-each loop can't be initialized."
+ tip: "Try removing the initializer, or using a different kind of loop."
+ analyzerCode: INITIALIZED_VARIABLE_IN_FOR_EACH
+ dart2jsCode: "*fatal*"
+ statement:
+ - "for (int a = 0 in <int>[10]) {}"
+
InvalidAwaitFor:
template: "The keyword 'await' isn't allowed for a normal 'for' statement."
tip: "Try removing the keyword, or use a for-each statement."
@@ -939,11 +947,11 @@
analyzerCode: CONSTRUCTOR_WITH_RETURN_TYPE
dart2jsCode: "*fatal*"
script:
- - "class C { T C() {} }"
+ - "class C { int C() {} }"
FieldInitializerOutsideConstructor:
template: "Field formal parameters can only be used in a constructor."
- tip: "Try replacing the field formal parameter with a normal parameter."
+ tip: "Try removing 'this.'."
analyzerCode: FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR
dart2jsCode: "*fatal*"
script:
@@ -1831,6 +1839,8 @@
InterpolationInUri:
template: "Can't use string interpolation in a URI."
+ analyzerCode: INVALID_LITERAL_IN_CONFIGURATION
+ dart2jsCode: "*fatal*"
IntegerLiteralIsOutOfRange:
template: "The integer literal #lexeme can't be represented in 64 bits."
diff --git a/pkg/front_end/test/fasta/messages_test.dart b/pkg/front_end/test/fasta/messages_test.dart
index 7217879..9e46ca3 100644
--- a/pkg/front_end/test/fasta/messages_test.dart
+++ b/pkg/front_end/test/fasta/messages_test.dart
@@ -2,76 +2,299 @@
// 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:io';
+import "dart:async" show Future, Stream;
-import 'package:front_end/src/testing/package_root.dart' as package_root;
-import 'package:path/path.dart' as path;
-import 'package:yaml/yaml.dart' show loadYaml;
+import "dart:convert" show utf8;
-main([List<String> arguments = const []]) async {
- File file = new File(
- path.join(package_root.packageRoot, 'front_end', 'messages.yaml'));
- if (!await file.exists()) {
- file = new File.fromUri(Uri.base.resolve('messages.yaml'));
- }
- Map yaml = loadYaml(await file.readAsString());
+import "dart:io" show File;
- int untestedExampleCount = 0;
- int missingExamplesCount = 0;
- int missingAnalyzerCode = 0;
- List<String> keysWithAnalyzerCodeButNoDart2JsCode = <String>[];
- List<String> keys = yaml.keys.toList()..sort();
- for (String name in keys) {
- var description = yaml[name];
- while (description is String) {
- description = yaml[description];
- }
- Map map = description;
+import "dart:typed_data" show Uint8List;
- int localUntestedExampleCount = countExamples(map, name, 'bytes');
- localUntestedExampleCount += countExamples(map, name, 'declaration');
- localUntestedExampleCount += countExamples(map, name, 'expression');
- localUntestedExampleCount += countExamples(map, name, 'script');
- localUntestedExampleCount += countExamples(map, name, 'statement');
- if (localUntestedExampleCount == 0) ++missingExamplesCount;
- untestedExampleCount += localUntestedExampleCount;
+import "package:testing/testing.dart"
+ show Chain, ChainContext, Result, Step, TestDescription, runMe;
- if (map['analyzerCode'] == null) {
- ++missingAnalyzerCode;
- } else {
- if (map['dart2jsCode'] == null) {
- keysWithAnalyzerCodeButNoDart2JsCode.add(name);
+import "package:yaml/yaml.dart" show loadYaml;
+
+class MessageTestDescription extends TestDescription {
+ @override
+ final Uri uri;
+
+ @override
+ final String shortName;
+
+ final String name;
+
+ final Map data;
+
+ final Example example;
+
+ final String problem;
+
+ MessageTestDescription(this.uri, this.shortName, this.name, this.data,
+ this.example, this.problem);
+}
+
+class MessageTestSuite extends ChainContext {
+ final List<Step> steps = const <Step>[
+ const Validate(),
+ const Compile(),
+ ];
+
+ /// Convert all the examples found in `messages.yaml` to a test
+ /// description. In addition, for each problem found, create a test
+ /// description that has a problem. This problem will then be reported as a
+ /// failure by the [Validate] step that can be suppressed via the status
+ /// file.
+ Stream<MessageTestDescription> list(Chain suite) async* {
+ Uri uri = suite.uri.resolve("messages.yaml");
+ File file = new File.fromUri(uri);
+ Map yaml = loadYaml(await file.readAsString());
+ for (String name in yaml.keys) {
+ var data = yaml[name];
+ if (data is String) continue;
+
+ List<String> unknownKeys = <String>[];
+ List<Example> examples = <Example>[];
+ String analyzerCode;
+ String dart2jsCode;
+
+ for (String key in data.keys) {
+ var value = data[key];
+ switch (key) {
+ case "template":
+ case "tip":
+ case "severity":
+ break;
+
+ case "analyzerCode":
+ analyzerCode = value;
+ break;
+
+ case "dart2jsCode":
+ dart2jsCode = value;
+ break;
+
+ case "bytes":
+ if (value.first is List) {
+ for (List bytes in value) {
+ int i = 0;
+ examples.add(new BytesExample("bytes${++i}", name, bytes));
+ }
+ } else {
+ examples.add(new BytesExample("bytes", name, value));
+ }
+ break;
+
+ case "declaration":
+ if (value is List) {
+ int i = 0;
+ for (String declaration in value) {
+ examples.add(new DeclarationExample(
+ "declaration${++i}", name, declaration));
+ }
+ } else {
+ examples.add(new DeclarationExample("declaration", name, value));
+ }
+ break;
+
+ case "expression":
+ if (value is List) {
+ int i = 0;
+ for (String expression in value) {
+ examples.add(new ExpressionExample(
+ "expression${++i}", name, expression));
+ }
+ } else {
+ examples.add(new ExpressionExample("expression", name, value));
+ }
+ break;
+
+ case "script":
+ if (value is List) {
+ int i = 0;
+ for (String script in value) {
+ examples.add(new ScriptExample("script${++i}", name, script));
+ }
+ } else {
+ examples.add(new ScriptExample("script", name, value));
+ }
+ break;
+
+ case "statement":
+ if (value is List) {
+ int i = 0;
+ for (String statement in value) {
+ examples.add(
+ new StatementExample("statement${++i}", name, statement));
+ }
+ } else {
+ examples.add(new StatementExample("statement", name, value));
+ }
+ break;
+
+ default:
+ unknownKeys.add(key);
+ }
+ }
+
+ MessageTestDescription createDescription(
+ String subName, Example example, String problem) {
+ String shortName = "$name/$subName";
+ if (problem != null) {
+ String base = "${Uri.base}";
+ String filename = "$uri";
+ if (filename.startsWith(base)) {
+ filename = filename.substring(base.length);
+ }
+ var location = data.span.start;
+ int line = location.line;
+ int column = location.column;
+ problem = "$filename:$line:$column: error:\n$problem";
+ }
+ return new MessageTestDescription(uri.resolve("#$shortName"), shortName,
+ name, data, example, problem);
+ }
+
+ for (Example example in examples) {
+ yield createDescription(example.name, example, null);
+ }
+
+ if (unknownKeys.isNotEmpty) {
+ yield createDescription(
+ "knownKeys", null, "Unknown keys: ${unknownKeys.join(' ')}");
+ }
+
+ if (examples.isEmpty) {
+ yield createDescription("example", null, "No example for $name");
+ }
+
+ if (analyzerCode == null) {
+ yield createDescription(
+ "analyzerCode", null, "No analyzer code for $name");
+ } else {
+ if (dart2jsCode == null) {
+ yield createDescription(
+ "dart2jsCode", null, "No dart2js code for $name");
+ }
}
}
}
+}
- if (keysWithAnalyzerCodeButNoDart2JsCode.isNotEmpty) {
- print('${keysWithAnalyzerCodeButNoDart2JsCode.length}'
- ' error codes have an analyzerCode but no dart2jsCode:');
- for (String name in keysWithAnalyzerCodeButNoDart2JsCode) {
- print(' $name');
- }
- print('');
+abstract class Example {
+ final String name;
+
+ final String expectedCode;
+
+ Example(this.name, this.expectedCode);
+
+ Uint8List get bytes;
+}
+
+class BytesExample extends Example {
+ @override
+ final Uint8List bytes;
+
+ BytesExample(String name, String code, List bytes)
+ : bytes = new Uint8List.fromList(bytes),
+ super(name, code);
+}
+
+class DeclarationExample extends Example {
+ final String declaration;
+
+ DeclarationExample(String name, String code, this.declaration)
+ : super(name, code);
+
+ @override
+ Uint8List get bytes {
+ return new Uint8List.fromList(utf8.encode("""
+$declaration
+
+main() {
+}
+"""));
}
- print('$untestedExampleCount examples not tested');
- print('$missingExamplesCount error codes missing examples');
- print('$missingAnalyzerCode error codes missing analyzer code');
-
- // TODO(danrubel): Update this to assert each count == 0 and stays zero.
- exit(keysWithAnalyzerCodeButNoDart2JsCode.isEmpty &&
- untestedExampleCount > 0 &&
- missingExamplesCount > 0 &&
- missingAnalyzerCode > 0
- ? 0
- : 1);
}
-int countExamples(Map map, String name, String key) {
- var example = map[key];
- if (example == null) return 0;
- if (example is String) return 1;
- if (example is List) return example.length;
- if (example is Map) return example.length;
+class StatementExample extends Example {
+ final String statement;
- throw 'Unknown value for $name $key --> ${example.runtimeType}\n $example';
+ StatementExample(String name, String code, this.statement)
+ : super(name, code);
+
+ @override
+ Uint8List get bytes {
+ return new Uint8List.fromList(utf8.encode("""
+main() {
+ $statement
}
+"""));
+ }
+}
+
+class ExpressionExample extends Example {
+ final String expression;
+
+ ExpressionExample(String name, String code, this.expression)
+ : super(name, code);
+
+ @override
+ Uint8List get bytes {
+ return new Uint8List.fromList(utf8.encode("""
+main() {
+ $expression;
+}
+"""));
+ }
+}
+
+class ScriptExample extends Example {
+ final String script;
+
+ ScriptExample(String name, String code, this.script) : super(name, code);
+
+ @override
+ Uint8List get bytes {
+ return new Uint8List.fromList(utf8.encode(script));
+ }
+}
+
+class Validate extends Step<MessageTestDescription, Example, MessageTestSuite> {
+ const Validate();
+
+ String get name => "validate";
+
+ Future<Result<Example>> run(
+ MessageTestDescription description, MessageTestSuite suite) async {
+ if (description.problem != null) {
+ return fail(null, description.problem);
+ } else {
+ return pass(description.example);
+ }
+ }
+}
+
+class Compile extends Step<Example, Null, MessageTestSuite> {
+ const Compile();
+
+ String get name => "compile";
+
+ Future<Result<Null>> run(Example example, MessageTestSuite suite) async {
+ // TODO(ahe): This is where I should actually compile the example and
+ // verify that only one message is reported, and it is the expected
+ // message.
+ if (example is! BytesExample) {
+ print(utf8.decode(example.bytes));
+ }
+ return pass(null);
+ }
+}
+
+Future<MessageTestSuite> createContext(
+ Chain suite, Map<String, String> environment) async {
+ return new MessageTestSuite();
+}
+
+main([List<String> arguments = const []]) =>
+ runMe(arguments, createContext, "../../testing.json");
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 99fe3f2..5236bed 100644
--- a/pkg/front_end/test/incremental_load_from_dill_test.dart
+++ b/pkg/front_end/test/incremental_load_from_dill_test.dart
@@ -22,17 +22,75 @@
Directory outDir;
main() async {
+ await runPassingTest(testDart2jsCompile);
+ await runPassingTest(testDisappearingLibrary);
+ await runPassingTest(testDeferredLibrary);
+ await runPassingTest(testStrongModeMixins);
+}
+
+void runFailingTest(dynamic test, String expectContains) async {
+ try {
+ await runPassingTest(test);
+ throw "Expected this to fail.";
+ } catch (e) {
+ if (e.toString().contains(expectContains)) {
+ print("got expected error as this test is currently failing");
+ } else {
+ rethrow;
+ }
+ }
+}
+
+void runPassingTest(dynamic test) async {
outDir =
Directory.systemTemp.createTempSync("incremental_load_from_dill_test");
try {
- await testDart2jsCompile();
- await testDisappearingLibrary();
- await testDeferredLibrary();
+ await test();
+ print("----");
} finally {
outDir.deleteSync(recursive: true);
}
}
+/// Compile in strong mode. Invalidate a file so type inferrer starts
+/// on something compiled from source and (potentially) goes into
+/// something loaded from dill.
+void testStrongModeMixins() async {
+ final Uri a = outDir.uri.resolve("testStrongModeMixins_a.dart");
+ final Uri b = outDir.uri.resolve("testStrongModeMixins_b.dart");
+
+ Uri output = outDir.uri.resolve("testStrongModeMixins_full.dill");
+ Uri bootstrappedOutput =
+ outDir.uri.resolve("testStrongModeMixins_full_from_bootstrap.dill");
+
+ new File.fromUri(a).writeAsStringSync("""
+ import 'testStrongModeMixins_b.dart';
+ class A extends Object with B<Object>, C {}
+ """);
+ new File.fromUri(b).writeAsStringSync("""
+ abstract class C<T extends Object> extends Object with B<T> {}
+ abstract class B<ChildType extends Object> extends Object {}
+ """);
+
+ Stopwatch stopwatch = new Stopwatch()..start();
+ await normalCompile(a, output, options: getOptions()..strongMode = true);
+ print("Normal compile took ${stopwatch.elapsedMilliseconds} ms");
+
+ stopwatch.reset();
+ bool bootstrapResult = await bootstrapCompile(
+ a, bootstrappedOutput, output, [a],
+ performSizeTests: false, options: getOptions()..strongMode = true);
+ print("Bootstrapped compile(s) from ${output.pathSegments.last} "
+ "took ${stopwatch.elapsedMilliseconds} ms");
+ Expect.isTrue(bootstrapResult);
+
+ // Compare the two files.
+ List<int> normalDillData = new File.fromUri(output).readAsBytesSync();
+ List<int> bootstrappedDillData =
+ new File.fromUri(bootstrappedOutput).readAsBytesSync();
+ checkBootstrappedIsEqual(normalDillData, bootstrappedDillData);
+}
+
/// Test loading from a dill file with a deferred library.
/// This is done by bootstrapping with no changes.
void testDeferredLibrary() async {
@@ -169,7 +227,9 @@
options.sdkSummary = sdkSummary;
IncrementalCompiler compiler =
new IncrementalKernelGenerator(options, main);
+ Stopwatch stopwatch = new Stopwatch()..start();
var program = await compiler.computeDelta();
+ print("Normal compile took ${stopwatch.elapsedMilliseconds} ms");
libCount2 = serializeProgram(program);
if (program.libraries.length != 2) {
throw "Expected 2 libraries, got ${program.libraries.length}";
@@ -199,7 +259,9 @@
new IncrementalKernelGenerator(options, b, bootstrap);
compiler.invalidate(main);
compiler.invalidate(b);
+ Stopwatch stopwatch = new Stopwatch()..start();
var program = await compiler.computeDelta();
+ print("Bootstrapped compile took ${stopwatch.elapsedMilliseconds} ms");
if (program.libraries.length != 1) {
throw "Expected 1 library, got ${program.libraries.length}";
}
@@ -215,8 +277,9 @@
return options;
}
-Future<bool> normalCompile(Uri input, Uri output) async {
- CompilerOptions options = getOptions();
+Future<bool> normalCompile(Uri input, Uri output,
+ {CompilerOptions options}) async {
+ options ??= getOptions();
IncrementalCompiler compiler = new IncrementalKernelGenerator(options, input);
var y = await compiler.computeDelta();
await writeProgramToFile(y, output);
@@ -225,8 +288,8 @@
Future<bool> bootstrapCompile(
Uri input, Uri output, Uri bootstrapWith, List<Uri> invalidateUris,
- {bool performSizeTests: true}) async {
- CompilerOptions options = getOptions();
+ {bool performSizeTests: true, CompilerOptions options}) async {
+ options ??= getOptions();
IncrementalCompiler compiler =
new IncrementalKernelGenerator(options, input, bootstrapWith);
for (Uri invalidateUri in invalidateUris) {
diff --git a/pkg/front_end/test/scanner_fasta_test.dart b/pkg/front_end/test/scanner_fasta_test.dart
index 683f559..c21bdc9 100644
--- a/pkg/front_end/test/scanner_fasta_test.dart
+++ b/pkg/front_end/test/scanner_fasta_test.dart
@@ -299,8 +299,8 @@
expect(openBrace.endToken, same(closeBrace));
expect(openParen2.endToken, same(closeParen2));
listener.assertErrors([
- new TestError(3, ScannerErrorCode.EXPECTED_TOKEN, [')']),
- new TestError(5, ScannerErrorCode.EXPECTED_TOKEN, [')']),
+ new TestError(6, ScannerErrorCode.EXPECTED_TOKEN, [')']),
+ new TestError(7, ScannerErrorCode.EXPECTED_TOKEN, [')']),
]);
}
@@ -335,9 +335,9 @@
expect(openBracket.endToken, same(closeBracket));
expect(openParen.endToken, same(closeParen));
listener.assertErrors([
- new TestError(0, ScannerErrorCode.EXPECTED_TOKEN, ['}']),
- new TestError(1, ScannerErrorCode.EXPECTED_TOKEN, [']']),
- new TestError(2, ScannerErrorCode.EXPECTED_TOKEN, [')']),
+ new TestError(2, ScannerErrorCode.EXPECTED_TOKEN, ['}']),
+ new TestError(3, ScannerErrorCode.EXPECTED_TOKEN, [']']),
+ new TestError(3, ScannerErrorCode.EXPECTED_TOKEN, [')']),
]);
}
}
diff --git a/pkg/front_end/test/scanner_replacement_test.dart b/pkg/front_end/test/scanner_replacement_test.dart
index 824a1d3..9cfcb94 100644
--- a/pkg/front_end/test/scanner_replacement_test.dart
+++ b/pkg/front_end/test/scanner_replacement_test.dart
@@ -86,7 +86,7 @@
expect(open.isSynthetic, isFalse);
expect(close.isSynthetic, isTrue);
listener.assertErrors([
- new TestError(0, ScannerErrorCode.EXPECTED_TOKEN, [expectedCloser]),
+ new TestError(1, ScannerErrorCode.EXPECTED_TOKEN, [expectedCloser]),
]);
}
@@ -176,8 +176,8 @@
expect(closeParen2.isSynthetic, isTrue);
expect(eof.isEof, isTrue);
listener.assertErrors([
- new TestError(3, ScannerErrorCode.EXPECTED_TOKEN, [')']),
- new TestError(5, ScannerErrorCode.EXPECTED_TOKEN, [')']),
+ new TestError(6, ScannerErrorCode.EXPECTED_TOKEN, [')']),
+ new TestError(7, ScannerErrorCode.EXPECTED_TOKEN, [')']),
]);
}
@@ -200,9 +200,9 @@
expect(eof.isEof, true);
listener.assertErrors([
- new TestError(2, ScannerErrorCode.EXPECTED_TOKEN, [')']),
- new TestError(1, ScannerErrorCode.EXPECTED_TOKEN, [']']),
- new TestError(0, ScannerErrorCode.EXPECTED_TOKEN, ['}']),
+ new TestError(4, ScannerErrorCode.EXPECTED_TOKEN, [')']),
+ new TestError(4, ScannerErrorCode.EXPECTED_TOKEN, [']']),
+ new TestError(4, ScannerErrorCode.EXPECTED_TOKEN, ['}']),
]);
}
diff --git a/pkg/front_end/test/scanner_test.dart b/pkg/front_end/test/scanner_test.dart
index d1ec614..861b2fd 100644
--- a/pkg/front_end/test/scanner_test.dart
+++ b/pkg/front_end/test/scanner_test.dart
@@ -451,7 +451,7 @@
new SyntheticStringToken(TokenType.STRING, "\"", 10, 0),
]);
expectedErrors.addAll([
- new TestError(5, ScannerErrorCode.EXPECTED_TOKEN, ['}']),
+ new TestError(10, ScannerErrorCode.EXPECTED_TOKEN, ['}']),
]);
} else {
expectedTokens.addAll([
@@ -823,7 +823,7 @@
expect(openBracket.endToken, same(closeBracket));
expect(openParen.endToken, same(closeParen));
listener.assertErrors([
- new TestError(1, ScannerErrorCode.EXPECTED_TOKEN, [')']),
+ new TestError(2, ScannerErrorCode.EXPECTED_TOKEN, [')']),
]);
} else {
var closeBracket = openParen.next;
@@ -855,7 +855,7 @@
expect(openBracket.endToken, closeBracket);
expect(openParen.endToken, closeParen);
listener.assertErrors([
- new TestError(1, ScannerErrorCode.EXPECTED_TOKEN, [']']),
+ new TestError(2, ScannerErrorCode.EXPECTED_TOKEN, [']']),
]);
} else {
var closeParen = openBracket.next;
@@ -1095,7 +1095,7 @@
new SyntheticStringToken(TokenType.STRING, "'''", 9, 0),
]);
expectedErrors.addAll([
- new TestError(3, ScannerErrorCode.EXPECTED_TOKEN, ['}']),
+ new TestError(9, ScannerErrorCode.EXPECTED_TOKEN, ['}']),
]);
} else {
expectedTokens.addAll([
@@ -1369,7 +1369,7 @@
new SyntheticStringToken(TokenType.STRING, "'", 7, 0),
]);
expectedErrors.addAll([
- new TestError(1, ScannerErrorCode.EXPECTED_TOKEN, ['}']),
+ new TestError(7, ScannerErrorCode.EXPECTED_TOKEN, ['}']),
]);
} else {
expectedTokens.addAll([
diff --git a/pkg/front_end/testcases/inference/bug32291.dart b/pkg/front_end/testcases/inference/bug32291.dart
new file mode 100644
index 0000000..d3a62f5
--- /dev/null
+++ b/pkg/front_end/testcases/inference/bug32291.dart
@@ -0,0 +1,21 @@
+// 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.
+
+/*@testedFeatures=inference*/
+library test;
+
+void main() {
+ var /*@type=List<List<String>>*/ l = /*@typeArgs=List<String>*/ [
+ /*@typeArgs=String*/ ["hi", "world"]
+ ];
+ var /*@type=Iterable<List<String>>*/ i1 =
+ l. /*@target=Iterable::map*/ /*@typeArgs=List<String>*/ map(
+ /*@returnType=List<String>*/ (/*@type=List<String>*/ ll) =>
+ ll ?? /*@typeArgs=String*/ []);
+ var /*@type=Iterable<int>*/ i2 =
+ i1. /*@target=Iterable::map*/ /*@typeArgs=int*/ map(
+ /*@returnType=int*/ (List<String> l) =>
+ l. /*@target=List::length*/ length);
+ print(i2);
+}
diff --git a/pkg/front_end/testcases/inference/bug32291.dart.direct.expect b/pkg/front_end/testcases/inference/bug32291.dart.direct.expect
new file mode 100644
index 0000000..f2dc0b2
--- /dev/null
+++ b/pkg/front_end/testcases/inference/bug32291.dart.direct.expect
@@ -0,0 +1,10 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+static method main() → void {
+ dynamic l = <dynamic>[<dynamic>["hi", "world"]];
+ dynamic i1 = l.map((dynamic ll) → dynamic => let final dynamic #t1 = ll in #t1.==(null) ? <dynamic>[] : #t1);
+ dynamic i2 = i1.map((core::List<core::String> l) → dynamic => l.length);
+ core::print(i2);
+}
diff --git a/pkg/front_end/testcases/inference/bug32291.dart.outline.expect b/pkg/front_end/testcases/inference/bug32291.dart.outline.expect
new file mode 100644
index 0000000..27b374a
--- /dev/null
+++ b/pkg/front_end/testcases/inference/bug32291.dart.outline.expect
@@ -0,0 +1,5 @@
+library test;
+import self as self;
+
+static method main() → void
+ ;
diff --git a/pkg/front_end/testcases/inference/bug32291.dart.strong.expect b/pkg/front_end/testcases/inference/bug32291.dart.strong.expect
new file mode 100644
index 0000000..6193515
--- /dev/null
+++ b/pkg/front_end/testcases/inference/bug32291.dart.strong.expect
@@ -0,0 +1,10 @@
+library test;
+import self as self;
+import "dart:core" as core;
+
+static method main() → void {
+ core::List<core::List<core::String>> l = <core::List<core::String>>[<core::String>["hi", "world"]];
+ core::Iterable<core::List<core::String>> i1 = l.{core::Iterable::map}<core::List<core::String>>((core::List<core::String> ll) → core::List<core::String> => let final core::List<core::String> #t1 = ll in #t1.==(null) ?{core::List<core::String>} <core::String>[] : #t1);
+ core::Iterable<core::int> i2 = i1.{core::Iterable::map}<core::int>((core::List<core::String> l) → core::int => l.{core::List::length});
+ core::print(i2);
+}
diff --git a/pkg/front_end/testing.json b/pkg/front_end/testing.json
index 8168094..b1fadda 100644
--- a/pkg/front_end/testing.json
+++ b/pkg/front_end/testing.json
@@ -6,6 +6,17 @@
"packages": "../../.packages",
"suites": [
+ {
+ "name": "messages",
+ "kind": "Chain",
+ "source": "test/fasta/messages_test.dart",
+ "path": "./",
+ "status": "messages.status",
+ "pattern": [
+ ],
+ "exclude": [
+ ]
+ },
{
"name": "scanner",
@@ -254,14 +265,16 @@
"lib/",
"tool/",
"test/",
- "../kernel/lib/"
+ "../kernel/lib/",
+ "../testing/"
],
"git grep": {
"pathspecs": [ "*.dart" ],
"patterns": [
"package:front_end/",
- "package:kernel/"
+ "package:kernel/",
+ "package:testing/"
]
},
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 95c0b5f..ab5b52f 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -188,7 +188,7 @@
}
abstract class FileUriNode extends TreeNode {
- /// The uri of the source file this node was loaded from.
+ /// The URI of the source file this node was loaded from.
Uri get fileUri;
}
@@ -275,7 +275,7 @@
/// If the URI has the `app` scheme, it is relative to the application root.
Uri importUri;
- /// The uri of the source file this library was loaded from.
+ /// The URI of the source file this library was loaded from.
Uri fileUri;
/// If true, the library is part of another build unit and its contents
@@ -575,7 +575,7 @@
/// Declaration of a type alias.
class Typedef extends NamedNode implements FileUriNode {
- /// The uri of the source file that contains the declaration of this typedef.
+ /// The URI of the source file that contains the declaration of this typedef.
Uri fileUri;
List<Expression> annotations = const <Expression>[];
String name;
@@ -717,7 +717,7 @@
/// All X&Y classes are marked as synthetic.
bool isSyntheticMixinImplementation;
- /// The uri of the source file this class was loaded from.
+ /// The URI of the source file this class was loaded from.
Uri fileUri;
final List<TypeParameter> typeParameters;
@@ -938,7 +938,7 @@
// ------------------------------------------------------------------------
@coq
-abstract class Member extends NamedNode {
+abstract class Member extends NamedNode implements FileUriNode {
/// End offset in the source file it comes from. Valid values are from 0 and
/// up, or -1 ([TreeNode.noOffset]) if the file end offset is not available
/// (this is the default if none is specifically set).
@@ -953,6 +953,9 @@
Name name;
+ /// The URI of the source file this member was loaded from.
+ Uri fileUri;
+
/// Flags summarizing the kinds of AST nodes contained in this member, for
/// speeding up transformations that only affect certain types of nodes.
///
@@ -970,7 +973,7 @@
// TODO(asgerf): It might be worthwhile to put this on classes as well.
int transformerFlags = 0;
- Member(this.name, Reference reference) : super(reference);
+ Member(this.name, this.fileUri, Reference reference) : super(reference);
Class get enclosingClass => parent is Class ? parent : null;
Library get enclosingLibrary => parent is Class ? parent.parent : parent;
@@ -1034,15 +1037,12 @@
///
/// The implied getter and setter for the field are not represented explicitly,
/// but can be made explicit if needed.
-class Field extends Member implements FileUriNode {
+class Field extends Member {
DartType type; // Not null. Defaults to DynamicType.
int flags = 0;
int flags2 = 0;
Expression initializer; // May be null.
- /// The uri of the source file this field was loaded from.
- Uri fileUri;
-
Field(Name name,
{this.type: const DynamicType(),
this.initializer,
@@ -1053,9 +1053,9 @@
bool hasImplicitGetter,
bool hasImplicitSetter,
int transformerFlags: 0,
- this.fileUri,
+ Uri fileUri,
Reference reference})
- : super(name, reference) {
+ : super(name, fileUri, reference) {
assert(type != null);
initializer?.parent = this;
this.isCovariant = isCovariant;
@@ -1222,14 +1222,11 @@
/// invocation should be matched with the type parameters declared in the class.
///
/// For unnamed constructors, the name is an empty string (in a [Name]).
-class Constructor extends Member implements FileUriNode {
+class Constructor extends Member {
int flags = 0;
FunctionNode function;
List<Initializer> initializers;
- /// The uri of the source file this field was loaded from.
- Uri fileUri;
-
Constructor(this.function,
{Name name,
bool isConst: false,
@@ -1237,10 +1234,10 @@
bool isSynthetic: false,
List<Initializer> initializers,
int transformerFlags: 0,
- this.fileUri,
+ Uri fileUri,
Reference reference})
: this.initializers = initializers ?? <Initializer>[],
- super(name, reference) {
+ super(name, fileUri, reference) {
function?.parent = this;
setParents(this.initializers, this);
this.isConst = isConst;
@@ -1326,12 +1323,9 @@
///
/// Redirecting factory constructors can be unnamed. In this case, the name is
/// an empty string (in a [Name]).
-class RedirectingFactoryConstructor extends Member implements FileUriNode {
+class RedirectingFactoryConstructor extends Member {
int flags = 0;
- /// The uri of the source file this field was loaded from.
- Uri fileUri;
-
/// [RedirectingFactoryConstructor]s may redirect to constructors or factories
/// of instantiated generic types, that is, generic types with supplied type
/// arguments. The supplied type arguments are stored in this field.
@@ -1367,7 +1361,7 @@
List<VariableDeclaration> positionalParameters,
List<VariableDeclaration> namedParameters,
int requiredParameterCount,
- this.fileUri,
+ Uri fileUri,
Reference reference})
: this.typeArguments = typeArguments ?? <DartType>[],
this.typeParameters = typeParameters ?? <TypeParameter>[],
@@ -1376,7 +1370,7 @@
this.namedParameters = namedParameters ?? <VariableDeclaration>[],
this.requiredParameterCount =
requiredParameterCount ?? positionalParameters?.length ?? 0,
- super(name, reference) {
+ super(name, fileUri, reference) {
setParents(this.typeParameters, this);
setParents(this.positionalParameters, this);
setParents(this.namedParameters, this);
@@ -1454,7 +1448,7 @@
/// For operators, this is the token for the operator, e.g. `+` or `==`,
/// except for the unary minus operator, whose name is `unary-`.
@coq
-class Procedure extends Member implements FileUriNode {
+class Procedure extends Member {
ProcedureKind kind;
int flags = 0;
// function is null if and only if abstract, external.
@@ -1483,9 +1477,6 @@
super.transformerFlags = newValue;
}
- /// The uri of the source file this procedure was loaded from.
- Uri fileUri;
-
Reference forwardingStubSuperTargetReference;
Reference forwardingStubInterfaceTargetReference;
@@ -1524,11 +1515,11 @@
bool isForwardingStub: false,
bool isForwardingSemiStub: false,
int transformerFlags: 0,
- this.fileUri,
+ Uri fileUri,
Reference reference,
this.forwardingStubSuperTargetReference,
this.forwardingStubInterfaceTargetReference})
- : super(name, reference) {
+ : super(name, fileUri, reference) {
function?.parent = this;
this.isAbstract = isAbstract;
this.isStatic = isStatic;
@@ -5564,8 +5555,8 @@
final List<Library> libraries;
- /// Map from a source file uri to a line-starts table and source code.
- /// Given a source file uri and a offset in that file one can translate
+ /// Map from a source file URI to a line-starts table and source code.
+ /// Given a source file URI and a offset in that file one can translate
/// it to a line:column position in that file.
final Map<Uri, Source> uriToSource;
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 2fa7f84..1fbd076 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -195,9 +195,9 @@
unittest/*: Skip # Issue 21949
[ $runtime == vm && $system == windows ]
-analysis_server/*: Skip # Issue 27557
analysis_server/test/analysis/get_errors_test: Skip # runtime error, Issue 22180
-analysis_server/test/integration/analysis/analysis_options_test: RuntimeError # Issue 24796
+analysis_server/test/benchmarks_test: RuntimeError # Issue 32355
+analysis_server/test/integration/*: Skip # Issue 32356
analyzer/test/generated/non_error_resolver_kernel_test: RuntimeError # Issue 30785
analyzer/test/src/task/strong/checker_test: Pass, Slow
analyzer/tool/task_dependency_graph/check_test: Slow, Pass
diff --git a/pkg/testing/lib/dart_vm_suite.dart b/pkg/testing/lib/dart_vm_suite.dart
index 37a1d24..09ed485 100644
--- a/pkg/testing/lib/dart_vm_suite.dart
+++ b/pkg/testing/lib/dart_vm_suite.dart
@@ -15,12 +15,13 @@
final List<Step> steps = const <Step>[const DartVmStep()];
}
-class DartVmStep extends Step<TestDescription, int, VmContext> {
+class DartVmStep extends Step<FileBasedTestDescription, int, VmContext> {
const DartVmStep();
String get name => "Dart VM";
- Future<Result<int>> run(TestDescription input, VmContext context) async {
+ Future<Result<int>> run(
+ FileBasedTestDescription input, VmContext context) async {
StdioProcess process = await StdioProcess.run("dart", [input.file.path]);
return process.toResult();
}
diff --git a/pkg/testing/lib/src/chain.dart b/pkg/testing/lib/src/chain.dart
index 15d74ac..f93a31b 100644
--- a/pkg/testing/lib/src/chain.dart
+++ b/pkg/testing/lib/src/chain.dart
@@ -12,7 +12,7 @@
import 'suite.dart' show Suite;
-import '../testing.dart' show TestDescription;
+import '../testing.dart' show FileBasedTestDescription, TestDescription;
import 'test_dart/status_file_parser.dart'
show ReadTestExpectations, TestExpectations;
@@ -247,7 +247,7 @@
String path = entity.uri.path;
if (suite.exclude.any((RegExp r) => path.contains(r))) continue;
if (suite.pattern.any((RegExp r) => path.contains(r))) {
- yield new TestDescription(suite.uri, entity);
+ yield new FileBasedTestDescription(suite.uri, entity);
}
}
} else {
@@ -257,7 +257,8 @@
Result processTestResult(
TestDescription description, Result result, bool last) {
- if (description.multitestExpectations != null) {
+ if (description is FileBasedTestDescription &&
+ description.multitestExpectations != null) {
if (isError(description.multitestExpectations)) {
result =
toNegativeTestResult(result, description.multitestExpectations);
diff --git a/pkg/testing/lib/src/discover.dart b/pkg/testing/lib/src/discover.dart
index edcbf03..9b82e8a 100644
--- a/pkg/testing/lib/src/discover.dart
+++ b/pkg/testing/lib/src/discover.dart
@@ -8,7 +8,7 @@
import 'dart:async' show Future, Stream, StreamController, StreamSubscription;
-import '../testing.dart' show TestDescription;
+import '../testing.dart' show FileBasedTestDescription;
final Uri packageConfig = computePackageConfig();
@@ -19,9 +19,10 @@
List<String> get dartArguments =>
<String>["-c", "--packages=${packageConfig.toFilePath()}"];
-Stream<TestDescription> listTests(List<Uri> testRoots, {Pattern pattern}) {
- StreamController<TestDescription> controller =
- new StreamController<TestDescription>();
+Stream<FileBasedTestDescription> listTests(List<Uri> testRoots,
+ {Pattern pattern}) {
+ StreamController<FileBasedTestDescription> controller =
+ new StreamController<FileBasedTestDescription>();
Map<Uri, StreamSubscription> subscriptions = <Uri, StreamSubscription>{};
for (Uri testRootUri in testRoots) {
subscriptions[testRootUri] = null;
@@ -31,8 +32,8 @@
Stream<FileSystemEntity> stream =
testRoot.list(recursive: true, followLinks: false);
var subscription = stream.listen((FileSystemEntity entity) {
- TestDescription description =
- TestDescription.from(testRootUri, entity, pattern: pattern);
+ FileBasedTestDescription description = FileBasedTestDescription
+ .from(testRootUri, entity, pattern: pattern);
if (description != null) {
controller.add(description);
}
diff --git a/pkg/testing/lib/src/multitest.dart b/pkg/testing/lib/src/multitest.dart
index c87a654..b049210 100644
--- a/pkg/testing/lib/src/multitest.dart
+++ b/pkg/testing/lib/src/multitest.dart
@@ -10,7 +10,7 @@
import 'log.dart' show splitLines;
-import 'test_description.dart' show TestDescription;
+import 'test_description.dart' show FileBasedTestDescription;
bool isError(Set<String> expectations) {
if (expectations.contains("compile-time error")) return true;
@@ -24,8 +24,8 @@
return isError(expectations);
}
-class MultitestTransformer
- extends StreamTransformerBase<TestDescription, TestDescription> {
+class MultitestTransformer extends StreamTransformerBase<
+ FileBasedTestDescription, FileBasedTestDescription> {
static RegExp multitestMarker = new RegExp(r"//[#/]");
static int _multitestMarkerLength = 3;
@@ -42,7 +42,8 @@
static final Set<String> validOutcomes =
new Set<String>.from(validOutcomesList);
- Stream<TestDescription> bind(Stream<TestDescription> stream) async* {
+ Stream<FileBasedTestDescription> bind(
+ Stream<FileBasedTestDescription> stream) async* {
List<String> errors = <String>[];
reportError(String error) {
errors.add(error);
@@ -50,7 +51,7 @@
}
nextTest:
- await for (TestDescription test in stream) {
+ await for (FileBasedTestDescription test in stream) {
String contents = await test.file.readAsString();
if (!contents.contains(multitestMarker)) {
yield test;
@@ -124,8 +125,8 @@
for (String name in testsAsLines.keys) {
List<String> lines = testsAsLines[name];
Uri uri = generated.uri.resolve("${name}_generated.dart");
- TestDescription subtest =
- new TestDescription(root, new File.fromUri(uri));
+ FileBasedTestDescription subtest =
+ new FileBasedTestDescription(root, new File.fromUri(uri));
subtest.multitestExpectations = outcomes[name];
await subtest.file.writeAsString(lines.join(""));
yield subtest;
diff --git a/pkg/testing/lib/src/run.dart b/pkg/testing/lib/src/run.dart
index c5dc77c..c628a7a 100644
--- a/pkg/testing/lib/src/run.dart
+++ b/pkg/testing/lib/src/run.dart
@@ -14,13 +14,12 @@
import 'test_root.dart' show TestRoot;
-import 'test_description.dart' show TestDescription;
-
import 'error_handling.dart' show withErrorHandling;
import 'chain.dart' show CreateContext;
-import '../testing.dart' show Chain, ChainContext, TestDescription, listTests;
+import '../testing.dart'
+ show Chain, ChainContext, FileBasedTestDescription, listTests;
import 'analyze.dart' show Analyze;
@@ -164,7 +163,7 @@
StringBuffer chain = new StringBuffer();
bool hasRunnableTests = false;
- await for (TestDescription description in listDescriptions()) {
+ await for (FileBasedTestDescription description in listDescriptions()) {
hasRunnableTests = true;
description.writeImportOn(imports);
description.writeClosureOn(dart);
@@ -228,9 +227,9 @@
return hasAnalyzerSuites;
}
- Stream<TestDescription> listDescriptions() async* {
+ Stream<FileBasedTestDescription> listDescriptions() async* {
for (Dart suite in suites.where((Suite suite) => suite is Dart)) {
- await for (TestDescription description
+ await for (FileBasedTestDescription description
in listTests(<Uri>[suite.uri], pattern: "")) {
testUris.add(await Isolate.resolvePackageUri(description.uri));
if (shouldRunSuite(suite)) {
diff --git a/pkg/testing/lib/src/test_description.dart b/pkg/testing/lib/src/test_description.dart
index 12e0b03..7480ee0 100644
--- a/pkg/testing/lib/src/test_description.dart
+++ b/pkg/testing/lib/src/test_description.dart
@@ -6,7 +6,15 @@
import 'dart:io' show File, FileSystemEntity;
-class TestDescription implements Comparable<TestDescription> {
+abstract class TestDescription implements Comparable<TestDescription> {
+ Uri get uri;
+
+ String get shortName;
+
+ int compareTo(TestDescription other) => "$uri".compareTo("${other.uri}");
+}
+
+class FileBasedTestDescription extends TestDescription {
final Uri root;
final File file;
final Uri output;
@@ -15,10 +23,12 @@
/// expected outcomes.
Set<String> multitestExpectations;
- TestDescription(this.root, this.file, {this.output});
+ FileBasedTestDescription(this.root, this.file, {this.output});
+ @override
Uri get uri => file.uri;
+ @override
String get shortName {
String baseName = "$uri".substring("$root".length);
return baseName.substring(0, baseName.length - ".dart".length);
@@ -42,7 +52,7 @@
sink.writeln('.main,');
}
- static TestDescription from(Uri root, FileSystemEntity entity,
+ static FileBasedTestDescription from(Uri root, FileSystemEntity entity,
{Pattern pattern}) {
if (entity is! File) return null;
pattern ??= "_test.dart";
@@ -53,11 +63,9 @@
} else if (path.contains(pattern)) {
hasMatch = true;
}
- return hasMatch ? new TestDescription(root, entity) : null;
+ return hasMatch ? new FileBasedTestDescription(root, entity) : null;
}
- int compareTo(TestDescription other) => "$uri".compareTo("${other.uri}");
-
String formatError(String message) {
String base = Uri.base.toFilePath();
String path = uri.toFilePath();
diff --git a/pkg/testing/lib/testing.dart b/pkg/testing/lib/testing.dart
index 3934ef1..8c963a4 100644
--- a/pkg/testing/lib/testing.dart
+++ b/pkg/testing/lib/testing.dart
@@ -8,7 +8,8 @@
export 'src/discover.dart';
-export 'src/test_description.dart';
+export 'src/test_description.dart'
+ show FileBasedTestDescription, TestDescription;
export 'src/chain.dart' show Chain, ChainContext, Result, Step;
diff --git a/pkg/vm/bin/gen_kernel.dart b/pkg/vm/bin/gen_kernel.dart
index c7e6fad..c28e2fc 100644
--- a/pkg/vm/bin/gen_kernel.dart
+++ b/pkg/vm/bin/gen_kernel.dart
@@ -31,6 +31,10 @@
..addFlag('embed-sources',
help: 'Embed source files in the generated kernel program',
defaultsTo: true)
+ ..addFlag('tfa',
+ help:
+ 'Enable global type flow analysis and related transformations in AOT mode.',
+ defaultsTo: false)
..addOption('entry-points',
help: 'Path to JSON file with the list of entry points',
allowMultiple: true);
@@ -69,12 +73,14 @@
final bool strongMode = options['strong-mode'];
final bool aot = options['aot'];
final bool syncAsync = options['sync-async'];
+ final bool tfa = options['tfa'];
final List<String> entryPoints = options['entry-points'] ?? <String>[];
if (entryPoints.isEmpty) {
entryPoints.addAll([
'pkg/vm/lib/transformations/type_flow/entry_points.json',
'pkg/vm/lib/transformations/type_flow/entry_points_extra.json',
+ 'pkg/vm/lib/transformations/type_flow/entry_points_extra_standalone.json',
]);
}
@@ -95,7 +101,7 @@
Program program = await compileToKernel(
Uri.base.resolveUri(new Uri.file(filename)), compilerOptions,
- aot: aot, entryPoints: entryPoints);
+ aot: aot, useGlobalTypeFlowAnalysis: tfa, entryPoints: entryPoints);
if (errorDetector.hasCompilationErrors || (program == null)) {
return _compileTimeErrorExitCode;
diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart
index 73e0ecd..e7c9030 100644
--- a/pkg/vm/lib/kernel_front_end.dart
+++ b/pkg/vm/lib/kernel_front_end.dart
@@ -24,16 +24,15 @@
import 'transformations/type_flow/transformer.dart' as globalTypeFlow
show transformProgram;
-// Flag to enable global type flow analysis and related transformations.
-const kUseGlobalTypeFlow = const bool.fromEnvironment('use.global.type.flow');
-
/// Generates a kernel representation of the program whose main library is in
/// the given [source]. Intended for whole program (non-modular) compilation.
///
/// VM-specific replacement of [kernelForProgram].
///
Future<Program> compileToKernel(Uri source, CompilerOptions options,
- {bool aot: false, List<String> entryPoints}) async {
+ {bool aot: false,
+ bool useGlobalTypeFlowAnalysis: false,
+ List<String> entryPoints}) async {
// Replace error handler to detect if there are compilation errors.
final errorDetector =
new ErrorDetector(previousErrorHandler: options.onError);
@@ -46,18 +45,19 @@
// Run global transformations only if program is correct.
if (aot && (program != null) && !errorDetector.hasCompilationErrors) {
- _runGlobalTransformations(program, options.strongMode, entryPoints);
+ _runGlobalTransformations(
+ program, options.strongMode, useGlobalTypeFlowAnalysis, entryPoints);
}
return program;
}
-_runGlobalTransformations(
- Program program, bool strongMode, List<String> entryPoints) {
+_runGlobalTransformations(Program program, bool strongMode,
+ bool useGlobalTypeFlowAnalysis, List<String> entryPoints) {
if (strongMode) {
final coreTypes = new CoreTypes(program);
- if (kUseGlobalTypeFlow) {
+ if (useGlobalTypeFlowAnalysis) {
globalTypeFlow.transformProgram(coreTypes, program, entryPoints);
} else {
devirtualization.transformProgram(coreTypes, program);
diff --git a/pkg/vm/lib/metadata/procedure_attributes.dart b/pkg/vm/lib/metadata/procedure_attributes.dart
index 1e6acb8..5581074 100644
--- a/pkg/vm/lib/metadata/procedure_attributes.dart
+++ b/pkg/vm/lib/metadata/procedure_attributes.dart
@@ -8,20 +8,29 @@
/// Metadata for annotating procedures with various attributes.
class ProcedureAttributesMetadata {
- final bool hasDynamicInvocations;
+ final bool hasDynamicUses;
+ final bool hasNonThisUses;
+ final bool hasTearOffUses;
- const ProcedureAttributesMetadata({this.hasDynamicInvocations});
+ const ProcedureAttributesMetadata(
+ {this.hasDynamicUses, this.hasNonThisUses, this.hasTearOffUses});
- const ProcedureAttributesMetadata.noDynamicInvocations()
- : hasDynamicInvocations = false;
+ const ProcedureAttributesMetadata.noDynamicUses()
+ : this(hasDynamicUses: false, hasNonThisUses: true, hasTearOffUses: true);
@override
- String toString() => "hasDynamicInvocations:${hasDynamicInvocations}";
+ String toString() => "hasDynamicUses:$hasDynamicUses,"
+ "hasNonThisUses:$hasNonThisUses,"
+ "hasTearOffUses:$hasTearOffUses";
}
/// Repository for [ProcedureAttributesMetadata].
class ProcedureAttributesMetadataRepository
extends MetadataRepository<ProcedureAttributesMetadata> {
+ static const int kDynamicUsesBit = 1 << 0;
+ static const int kNonThisUsesBit = 1 << 1;
+ static const int kTearOffUsesBit = 1 << 2;
+
@override
final String tag = 'vm.procedure-attributes.metadata';
@@ -31,11 +40,30 @@
@override
void writeToBinary(ProcedureAttributesMetadata metadata, BinarySink sink) {
- assert(!metadata.hasDynamicInvocations);
+ int flags = 0;
+ if (metadata.hasDynamicUses) {
+ flags |= kDynamicUsesBit;
+ }
+ if (metadata.hasNonThisUses) {
+ flags |= kNonThisUsesBit;
+ }
+ if (metadata.hasTearOffUses) {
+ flags |= kTearOffUsesBit;
+ }
+ sink.writeByte(flags);
}
@override
ProcedureAttributesMetadata readFromBinary(BinarySource source) {
- return const ProcedureAttributesMetadata.noDynamicInvocations();
+ final int flags = source.readByte();
+
+ final bool hasDynamicUses = (flags & kDynamicUsesBit) == kDynamicUsesBit;
+ final bool hasNonThisUses = (flags & kNonThisUsesBit) == kNonThisUsesBit;
+ final bool hasTearOffUses = (flags & kTearOffUsesBit) == kTearOffUsesBit;
+
+ return new ProcedureAttributesMetadata(
+ hasDynamicUses: hasDynamicUses,
+ hasNonThisUses: hasNonThisUses,
+ hasTearOffUses: hasTearOffUses);
}
}
diff --git a/pkg/vm/lib/transformations/no_dynamic_invocations_annotator.dart b/pkg/vm/lib/transformations/no_dynamic_invocations_annotator.dart
index 95b11ce..a176469 100644
--- a/pkg/vm/lib/transformations/no_dynamic_invocations_annotator.dart
+++ b/pkg/vm/lib/transformations/no_dynamic_invocations_annotator.dart
@@ -12,7 +12,7 @@
/// via dynamic invocation from anywhere then annotates it with appropriate
/// [ProcedureAttributeMetadata] annotation.
Program transformProgram(Program program) {
- new NoDynamicInvocationsAnnotator(program).visitProgram(program);
+ new NoDynamicUsesAnnotator(program).visitProgram(program);
return program;
}
@@ -50,12 +50,14 @@
}
}
-class NoDynamicInvocationsAnnotator {
- final Set<Selector> _dynamicSelectors;
+// TODO(kustermann): Try to extend the idea of tracking uses based on the 'this'
+// hierarchy.
+class NoDynamicUsesAnnotator {
+ final DynamicSelectorsCollector _selectors;
final ProcedureAttributesMetadataRepository _metadata;
- NoDynamicInvocationsAnnotator(Program program)
- : _dynamicSelectors = DynamicSelectorsCollector.collect(program),
+ NoDynamicUsesAnnotator(Program program)
+ : _selectors = DynamicSelectorsCollector.collect(program),
_metadata = new ProcedureAttributesMetadataRepository() {
program.addMetadataRepository(_metadata);
}
@@ -83,10 +85,19 @@
return;
}
- if (!_dynamicSelectors.contains(new Selector.doSet(node.name))) {
- _metadata.mapping[node] =
- const ProcedureAttributesMetadata.noDynamicInvocations();
+ final selector = new Selector.doSet(node.name);
+ if (_selectors.dynamicSelectors.contains(selector)) {
+ return;
}
+
+ ProcedureAttributesMetadata metadata;
+ if (!_selectors.nonThisSelectors.contains(selector)) {
+ metadata = const ProcedureAttributesMetadata(
+ hasDynamicUses: false, hasNonThisUses: true, hasTearOffUses: false);
+ } else {
+ metadata = const ProcedureAttributesMetadata.noDynamicUses();
+ }
+ _metadata.mapping[node] = metadata;
}
visitProcedure(Procedure node) {
@@ -103,28 +114,81 @@
return;
}
- if (!_dynamicSelectors.contains(selector)) {
- _metadata.mapping[node] =
- const ProcedureAttributesMetadata.noDynamicInvocations();
+ if (_selectors.dynamicSelectors.contains(selector)) {
+ return;
}
+
+ final bool hasNonThisUses = _selectors.nonThisSelectors.contains(selector);
+ final bool hasTearOffUses = _selectors.tearOffSelectors.contains(selector);
+ ProcedureAttributesMetadata metadata;
+ if (!hasNonThisUses && !hasTearOffUses) {
+ metadata = const ProcedureAttributesMetadata(
+ hasDynamicUses: false, hasNonThisUses: false, hasTearOffUses: false);
+ } else if (!hasNonThisUses && hasTearOffUses) {
+ metadata = const ProcedureAttributesMetadata(
+ hasDynamicUses: false, hasNonThisUses: false, hasTearOffUses: true);
+ } else if (hasNonThisUses && !hasTearOffUses) {
+ metadata = const ProcedureAttributesMetadata(
+ hasDynamicUses: false, hasNonThisUses: true, hasTearOffUses: false);
+ } else {
+ metadata = const ProcedureAttributesMetadata.noDynamicUses();
+ }
+ _metadata.mapping[node] = metadata;
}
}
class DynamicSelectorsCollector extends RecursiveVisitor<Null> {
final Set<Selector> dynamicSelectors = new Set<Selector>();
+ final Set<Selector> nonThisSelectors = new Set<Selector>();
+ final Set<Selector> tearOffSelectors = new Set<Selector>();
- static Set<Selector> collect(Program program) {
+ static DynamicSelectorsCollector collect(Program program) {
final v = new DynamicSelectorsCollector();
v.visitProgram(program);
- return v.dynamicSelectors;
+
+ // We only populate [nonThisSelectors] and [tearOffSelectors] inside the
+ // non-dynamic case (for efficiency reasons) while visiting the [Program].
+ //
+ // After the recursive visit of [Program] we complete the sets here.
+ for (final Selector selector in v.dynamicSelectors) {
+ // All dynamic getters can be tearoffs.
+ if (selector.action == Action.get) {
+ v.tearOffSelectors.add(new Selector.doInvoke(selector.target));
+ }
+
+ // All dynamic selectors are non-this selectors.
+ v.nonThisSelectors.add(selector);
+ }
+
+ return v;
}
@override
visitMethodInvocation(MethodInvocation node) {
super.visitMethodInvocation(node);
+ Selector selector;
if (node.dispatchCategory == DispatchCategory.dynamicDispatch) {
dynamicSelectors.add(new Selector.doInvoke(node.name));
+ } else {
+ if (node.receiver is! ThisExpression) {
+ nonThisSelectors.add(selector ??= new Selector.doInvoke(node.name));
+ }
+ }
+ }
+
+ @override
+ visitDirectMethodInvocation(DirectMethodInvocation node) {
+ super.visitDirectMethodInvocation(node);
+
+ Selector selector;
+ if (node.dispatchCategory == DispatchCategory.dynamicDispatch) {
+ dynamicSelectors.add(selector = new Selector.doInvoke(node.target.name));
+ } else {
+ if (node.receiver is! ThisExpression) {
+ nonThisSelectors
+ .add(selector ??= new Selector.doInvoke(node.target.name));
+ }
}
}
@@ -132,8 +196,36 @@
visitPropertyGet(PropertyGet node) {
super.visitPropertyGet(node);
+ Selector selector;
if (node.dispatchCategory == DispatchCategory.dynamicDispatch) {
- dynamicSelectors.add(new Selector.doGet(node.name));
+ dynamicSelectors.add(selector = new Selector.doGet(node.name));
+ } else {
+ if (node.receiver is! ThisExpression) {
+ nonThisSelectors.add(selector ??= new Selector.doGet(node.name));
+ }
+
+ final target = node.interfaceTarget;
+ if (target is Procedure && target.kind == ProcedureKind.Method) {
+ tearOffSelectors.add(new Selector.doInvoke(node.name));
+ }
+ }
+ }
+
+ @override
+ visitDirectPropertyGet(DirectPropertyGet node) {
+ super.visitDirectPropertyGet(node);
+
+ if (node.dispatchCategory == DispatchCategory.dynamicDispatch) {
+ dynamicSelectors.add(new Selector.doGet(node.target.name));
+ } else {
+ if (node.receiver is! ThisExpression) {
+ nonThisSelectors.add(new Selector.doGet(node.target.name));
+ }
+
+ final target = node.target;
+ if (target is Procedure && target.kind == ProcedureKind.Method) {
+ tearOffSelectors.add(new Selector.doInvoke(target.name));
+ }
}
}
@@ -141,8 +233,27 @@
visitPropertySet(PropertySet node) {
super.visitPropertySet(node);
+ Selector selector;
if (node.dispatchCategory == DispatchCategory.dynamicDispatch) {
- dynamicSelectors.add(new Selector.doSet(node.name));
+ dynamicSelectors.add(selector = new Selector.doSet(node.name));
+ } else {
+ if (node.receiver is! ThisExpression) {
+ nonThisSelectors.add(selector ??= new Selector.doSet(node.name));
+ }
+ }
+ }
+
+ @override
+ visitDirectPropertySet(DirectPropertySet node) {
+ super.visitDirectPropertySet(node);
+
+ Selector selector;
+ if (node.dispatchCategory == DispatchCategory.dynamicDispatch) {
+ dynamicSelectors.add(selector = new Selector.doSet(node.target.name));
+ } else {
+ if (node.receiver is! ThisExpression) {
+ nonThisSelectors.add(selector ??= new Selector.doSet(node.target.name));
+ }
}
}
}
diff --git a/pkg/vm/lib/transformations/type_flow/entry_points_extra.json b/pkg/vm/lib/transformations/type_flow/entry_points_extra.json
index d45ef2a..892b058 100644
--- a/pkg/vm/lib/transformations/type_flow/entry_points_extra.json
+++ b/pkg/vm/lib/transformations/type_flow/entry_points_extra.json
@@ -68,11 +68,6 @@
"action": "call"
},
{
- "library": "dart:_builtin",
- "name": "_resolveScriptUri",
- "action": "call"
- },
- {
"library": "dart:math",
"class": "_Random",
"name": "_A",
diff --git a/pkg/vm/lib/transformations/type_flow/entry_points_extra_standalone.json b/pkg/vm/lib/transformations/type_flow/entry_points_extra_standalone.json
new file mode 100644
index 0000000..8979143
--- /dev/null
+++ b/pkg/vm/lib/transformations/type_flow/entry_points_extra_standalone.json
@@ -0,0 +1,9 @@
+{
+ "roots": [
+ {
+ "library": "dart:_builtin",
+ "name": "_resolveScriptUri",
+ "action": "call"
+ }
+ ]
+}
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 aa44be5..b23ebd2 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
@@ -20,7 +20,7 @@
}
operator *([@vm.inferred-type.metadata=#lib::_Vector] self::_Vector a) → core::double {
core::double result = 0.0;
- for (core::int i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation::<??] 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; 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;
}
@@ -29,7 +29,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 #t1 = new core::Stopwatch::•() in let final dynamic #t2 = [@vm.direct-call.metadata=dart.core::Stopwatch::start] #t1.{core::Stopwatch::start}() in #t1;
- for (core::int i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation::<??] i.{core::num::<}(100000000); i = i.{core::num::+}(1)) {
+ for (core::int i = 0; 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/pkg/vm/tool/precompiler2 b/pkg/vm/tool/precompiler2
index d0776cb..cd965fe 100755
--- a/pkg/vm/tool/precompiler2
+++ b/pkg/vm/tool/precompiler2
@@ -15,8 +15,8 @@
set -e
OPTIONS=()
+GEN_KERNEL_OPTIONS=()
PACKAGES=
-SYNC_ASYNC=
ARGV=()
for arg in "$@"; do
@@ -24,8 +24,11 @@
--packages=*)
PACKAGES="$arg"
;;
- --sync-async)
- SYNC_ASYNC="--sync-async"
+ --sync-async | \
+ --no-sync-async | \
+ --tfa | \
+ --no-tfa )
+ GEN_KERNEL_OPTIONS+=("$arg")
;;
--*)
OPTIONS+=("$arg")
@@ -71,7 +74,8 @@
BIN_DIR="$OUT_DIR/$DART_CONFIGURATION"
ENTRY_POINTS="--entry-points ${BIN_DIR}/gen/runtime/bin/precompiler_entry_points.json \
- --entry-points ${SDK_DIR}/pkg/vm/lib/transformations/type_flow/entry_points_extra.json"
+ --entry-points ${SDK_DIR}/pkg/vm/lib/transformations/type_flow/entry_points_extra.json \
+ --entry-points ${SDK_DIR}/pkg/vm/lib/transformations/type_flow/entry_points_extra_standalone.json"
# Step 1: Generate Kernel binary from the input Dart source.
"$BIN_DIR"/dart \
@@ -79,7 +83,7 @@
"${SDK_DIR}/pkg/vm/bin/gen_kernel.dart" \
--platform "${BIN_DIR}/vm_platform_strong.dill" \
--aot \
- $SYNC_ASYNC \
+ "${GEN_KERNEL_OPTIONS[@]}" \
$PACKAGES \
$ENTRY_POINTS \
-o "$SNAPSHOT_FILE.dill" \
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index 410bde7..4442c92 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -6,6 +6,7 @@
import("../../sdk/lib/_http/http_sources.gni")
import("../../sdk/lib/io/io_sources.gni")
import("../../sdk/lib/cli/cli_sources.gni")
+import("../../utils/generate_entry_points_json.gni")
import("../runtime_args.gni")
import("../vm/compiler/compiler_sources.gni")
import("../vm/vm_sources.gni")
@@ -751,23 +752,30 @@
deps = [
":isolate_snapshot_data_assembly",
":isolate_snapshot_instructions_assembly",
- ":kernel_service_dill_cc",
- ":platform_dill_cc",
- ":platform_strong_dill_cc",
":vm_snapshot_data_assembly",
":vm_snapshot_instructions_assembly",
]
sources = [
- "$root_gen_dir/kernel_service.dill.cc",
"$target_gen_dir/isolate_snapshot_data.S",
"$target_gen_dir/isolate_snapshot_instructions.S",
- "$target_gen_dir/vm_platform.dill.cc",
- "$target_gen_dir/vm_platform_strong.dill.cc",
"$target_gen_dir/vm_snapshot_data.S",
"$target_gen_dir/vm_snapshot_instructions.S",
]
}
+source_set("dart_kernel_platform_cc") {
+ deps = [
+ ":kernel_service_dill_cc",
+ ":platform_dill_cc",
+ ":platform_strong_dill_cc",
+ ]
+ sources = [
+ "$root_gen_dir/kernel_service.dill.cc",
+ "$target_gen_dir/vm_platform.dill.cc",
+ "$target_gen_dir/vm_platform_strong.dill.cc",
+ ]
+}
+
template("dart_executable") {
extra_configs = []
if (defined(invoker.extra_configs)) {
@@ -872,6 +880,9 @@
if (dart_runtime_mode != "release") {
extra_deps += [ "../observatory:standalone_observatory_archive" ]
}
+ if (dart_runtime_mode != "release") {
+ extra_deps += [ ":dart_kernel_platform_cc" ]
+ }
extra_sources = [
"builtin_nolib.cc",
"dfe.cc",
@@ -931,6 +942,9 @@
":generate_web_sql_cc_file",
"..:libdart_nosnapshot_with_precompiler",
]
+ if (dart_runtime_mode != "release") {
+ extra_deps += [ ":dart_kernel_platform_cc" ]
+ }
extra_defines = [ "NO_OBSERVATORY" ]
extra_sources = [
"builtin.cc",
@@ -1108,6 +1122,7 @@
}
deps = [
+ ":dart_kernel_platform_cc",
":dart_snapshot_cc",
":generate_snapshot_test_dat_file",
":libdart_builtin",
@@ -1206,29 +1221,10 @@
}
}
-compiled_action("precompiler_entry_points_json") {
- # Printing precompiler entry points is folded into precompilation, so dart_bootstrap is invoked
- # with correct arguments to generate app-aot snapshot.
-
+generate_entry_points_json_with_dart_bootstrap(
+ "precompiler_entry_points_json") {
# Dart script to precompile (any valid script would suffice).
- input = "../vm/snapshot_test.dart"
-
- # Output snapshot for precompilation.
- snapshot = "$target_gen_dir/dummy.snapshot"
+ input = "../tests/vm/dart/hello_world_test.dart"
output = "$target_gen_dir/precompiler_entry_points.json"
- tool = ":dart_bootstrap"
- inputs = [
- input,
- ]
- outputs = [
- output,
- ]
- args = [
- "--print-precompiler-entry-points=" + rebase_path(output),
- "--snapshot=" + rebase_path(snapshot),
- "--snapshot-kind=app-aot",
- "--use-blobs",
- rebase_path(input),
- ]
}
diff --git a/runtime/bin/dartutils.cc b/runtime/bin/dartutils.cc
index d9fde37..c4c7d3d 100644
--- a/runtime/bin/dartutils.cc
+++ b/runtime/bin/dartutils.cc
@@ -197,7 +197,7 @@
if (slash == NULL) {
return strdup(url);
} else {
- return StringUtils::StrNDup(url, slash - url + 1);
+ return Utils::StrNDup(url, slash - url + 1);
}
}
diff --git a/runtime/bin/dfe.cc b/runtime/bin/dfe.cc
index df9750e..d80f237 100644
--- a/runtime/bin/dfe.cc
+++ b/runtime/bin/dfe.cc
@@ -13,12 +13,21 @@
#include "vm/kernel.h"
extern "C" {
+#if !defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM)
extern const uint8_t kKernelServiceDill[];
extern intptr_t kKernelServiceDillSize;
extern const uint8_t kPlatformDill[];
extern intptr_t kPlatformDillSize;
extern const uint8_t kPlatformStrongDill[];
extern intptr_t kPlatformStrongDillSize;
+#else
+const uint8_t* kKernelServiceDill = NULL;
+intptr_t kKernelServiceDillSize = 0;
+const uint8_t* kPlatformDill = NULL;
+intptr_t kPlatformDillSize = 0;
+const uint8_t* kPlatformStrongDill = NULL;
+intptr_t kPlatformStrongDillSize = 0;
+#endif // !defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM)
}
namespace dart {
@@ -59,7 +68,7 @@
return strdup("");
}
- return StringUtils::StrNDup(name, i + 1);
+ return Utils::StrNDup(name, i + 1);
}
static void NoopRelease(uint8_t* buffer) {}
diff --git a/runtime/bin/extensions.cc b/runtime/bin/extensions.cc
index 9f8edfe..b4ba1e7 100644
--- a/runtime/bin/extensions.cc
+++ b/runtime/bin/extensions.cc
@@ -13,6 +13,7 @@
#include "include/dart_api.h"
#include "platform/assert.h"
#include "platform/globals.h"
+#include "platform/utils.h"
namespace dart {
namespace bin {
@@ -65,7 +66,7 @@
void* Extensions::ResolveAbsPathExtension(const char* extension_path) {
const char* last_slash = strrchr(extension_path, PathSeparator()) + 1;
char* name = strdup(last_slash);
- char* dir = StringUtils::StrNDup(extension_path, last_slash - extension_path);
+ char* dir = Utils::StrNDup(extension_path, last_slash - extension_path);
void* library_handle = MakePathAndResolve(dir, name);
free(dir);
free(name);
diff --git a/runtime/bin/loader.cc b/runtime/bin/loader.cc
index 9774833..9c05e0d 100644
--- a/runtime/bin/loader.cc
+++ b/runtime/bin/loader.cc
@@ -296,7 +296,7 @@
}
// Convert buffer buffer to NUL-terminated string.
- (*dependencies)[i] = StringUtils::StrNDup(
+ (*dependencies)[i] = Utils::StrNDup(
reinterpret_cast<const char*>(file_path), file_path_length);
free(file_path);
free(resolved_uri);
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 32aa820..a9e51c3 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -323,7 +323,7 @@
return isolate;
}
-#if !defined(DART_PRECOMPILED_RUNTIME)
+#if !defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM)
// Returns newly created Kernel Isolate on success, NULL on failure.
// For now we only support the kernel isolate coming up from an
// application snapshot or from a .dill file.
@@ -382,7 +382,7 @@
return IsolateSetupHelper(isolate, false, uri, package_root, packages_config,
true, isolate_run_app_snapshot, error, exit_code);
}
-#endif // !defined(DART_PRECOMPILED_RUNTIME)
+#endif // !defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM)
// Returns newly created Service Isolate on success, NULL on failure.
// For now we only support the service isolate coming up from sources
@@ -609,13 +609,13 @@
}
int exit_code = 0;
-#if !defined(DART_PRECOMPILED_RUNTIME)
+#if !defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM)
if (strcmp(script_uri, DART_KERNEL_ISOLATE_NAME) == 0) {
return CreateAndSetupKernelIsolate(script_uri, main, package_root,
package_config, flags, error,
&exit_code);
}
-#endif // !defined(DART_PRECOMPILED_RUNTIME)
+#endif // !defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM)
if (strcmp(script_uri, DART_VM_SERVICE_ISOLATE_NAME) == 0) {
return CreateAndSetupServiceIsolate(script_uri, main, package_root,
package_config, flags, error,
diff --git a/runtime/bin/main_options.cc b/runtime/bin/main_options.cc
index 30f656b..bf1737a 100644
--- a/runtime/bin/main_options.cc
+++ b/runtime/bin/main_options.cc
@@ -63,15 +63,23 @@
CB_OPTIONS_LIST(CB_OPTION_DEFINITION)
#undef CB_OPTION_DEFINITION
+static void SetPreviewDart2Options(CommandLineOptions* vm_options) {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+ Options::dfe()->set_use_dfe();
+#endif // !defined(DART_PRECOMPILED_RUNTIME)
+ vm_options->AddArgument("--strong");
+ vm_options->AddArgument("--reify-generic-functions");
+ vm_options->AddArgument("--limit-ints-to-64-bits");
+}
+
+DEFINE_BOOL_OPTION_CB(preview_dart_2, { SetPreviewDart2Options(vm_options); });
+
#if !defined(DART_PRECOMPILED_RUNTIME)
DFE* Options::dfe_ = NULL;
-DEFINE_BOOL_OPTION_CB(preview_dart_2, { Options::dfe()->set_use_dfe(); });
-
// TODO(sivachandra): Make it an error to specify --dfe without
// specifying --preview_dart_2.
DEFINE_STRING_OPTION_CB(dfe, { Options::dfe()->set_frontend_filename(value); });
-
#endif // !defined(DART_PRECOMPILED_RUNTIME)
DEFINE_BOOL_OPTION_CB(hot_reload_test_mode, {
diff --git a/runtime/bin/utils.h b/runtime/bin/utils.h
index b313ff1..234a969 100644
--- a/runtime/bin/utils.h
+++ b/runtime/bin/utils.h
@@ -78,9 +78,6 @@
intptr_t len = -1,
intptr_t* result_len = NULL);
- // Not all platforms support strndup.
- static char* StrNDup(const char* s, intptr_t n);
-
private:
DISALLOW_ALLOCATION();
DISALLOW_IMPLICIT_CONSTRUCTORS(StringUtils);
diff --git a/runtime/bin/utils_android.cc b/runtime/bin/utils_android.cc
index 83bfcc7..a705997 100644
--- a/runtime/bin/utils_android.cc
+++ b/runtime/bin/utils_android.cc
@@ -69,10 +69,6 @@
return NULL;
}
-char* StringUtils::StrNDup(const char* s, intptr_t n) {
- return strndup(s, n);
-}
-
bool ShellUtils::GetUtf8Argv(int argc, char** argv) {
return false;
}
diff --git a/runtime/bin/utils_fuchsia.cc b/runtime/bin/utils_fuchsia.cc
index b763016..e1f3dca 100644
--- a/runtime/bin/utils_fuchsia.cc
+++ b/runtime/bin/utils_fuchsia.cc
@@ -66,10 +66,6 @@
return NULL;
}
-char* StringUtils::StrNDup(const char* s, intptr_t n) {
- return strndup(s, n);
-}
-
bool ShellUtils::GetUtf8Argv(int argc, char** argv) {
return false;
}
diff --git a/runtime/bin/utils_linux.cc b/runtime/bin/utils_linux.cc
index 766ccdb..3e27c0c 100644
--- a/runtime/bin/utils_linux.cc
+++ b/runtime/bin/utils_linux.cc
@@ -67,10 +67,6 @@
return NULL;
}
-char* StringUtils::StrNDup(const char* s, intptr_t n) {
- return strndup(s, n);
-}
-
bool ShellUtils::GetUtf8Argv(int argc, char** argv) {
return false;
}
diff --git a/runtime/bin/utils_macos.cc b/runtime/bin/utils_macos.cc
index d4be9a8..bec7153 100644
--- a/runtime/bin/utils_macos.cc
+++ b/runtime/bin/utils_macos.cc
@@ -72,29 +72,6 @@
return NULL;
}
-char* StringUtils::StrNDup(const char* s, intptr_t n) {
-// strndup has only been added to Mac OS X in 10.7. We are supplying
-// our own copy here if needed.
-#if !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || \
- __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ <= 1060
- intptr_t len = strlen(s);
- if ((n < 0) || (len < 0)) {
- return NULL;
- }
- if (n < len) {
- len = n;
- }
- char* result = reinterpret_cast<char*>(malloc(len + 1));
- if (result == NULL) {
- return NULL;
- }
- result[len] = '\0';
- return reinterpret_cast<char*>(memmove(result, s, len));
-#else // !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || ...
- return strndup(s, n);
-#endif // !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || ...
-}
-
bool ShellUtils::GetUtf8Argv(int argc, char** argv) {
return false;
}
diff --git a/runtime/bin/utils_win.cc b/runtime/bin/utils_win.cc
index e06cb9b..99e9fb8 100644
--- a/runtime/bin/utils_win.cc
+++ b/runtime/bin/utils_win.cc
@@ -144,22 +144,6 @@
StringUtilsWin::Utf8ToWide(const_cast<char*>(utf8), len, result_len));
}
-char* StringUtils::StrNDup(const char* s, intptr_t n) {
- intptr_t len = strlen(s);
- if ((n < 0) || (len < 0)) {
- return NULL;
- }
- if (n < len) {
- len = n;
- }
- char* result = reinterpret_cast<char*>(malloc(len + 1));
- if (result == NULL) {
- return NULL;
- }
- result[len] = '\0';
- return reinterpret_cast<char*>(memmove(result, s, len));
-}
-
bool ShellUtils::GetUtf8Argv(int argc, char** argv) {
wchar_t* command_line = GetCommandLineW();
int unicode_argc;
diff --git a/runtime/lib/array_patch.dart b/runtime/lib/array_patch.dart
index 820594a..27fc745 100644
--- a/runtime/lib/array_patch.dart
+++ b/runtime/lib/array_patch.dart
@@ -8,6 +8,9 @@
// whether a parameter was passed.
class _GrowableArrayMarker implements int {
const _GrowableArrayMarker();
+ noSuchMethod(_) {
+ throw new UnimplementedError();
+ }
}
const _GROWABLE_ARRAY_MARKER = const _GrowableArrayMarker();
diff --git a/runtime/lib/bigint.dart b/runtime/lib/bigint.dart
index 03a4b70..b6a9db3 100644
--- a/runtime/lib/bigint.dart
+++ b/runtime/lib/bigint.dart
@@ -1863,7 +1863,7 @@
}
// Interface for modular reduction.
-class _Reduction {
+abstract class _Reduction {
// Return the number of digits used by r_digits.
int _convert(_Bigint x, Uint32List r_digits);
int _mul(Uint32List x_digits, int x_used, Uint32List y_digits, int y_used,
diff --git a/runtime/lib/bigint_patch.dart b/runtime/lib/bigint_patch.dart
index 05b37a1..7094f29 100644
--- a/runtime/lib/bigint_patch.dart
+++ b/runtime/lib/bigint_patch.dart
@@ -60,10 +60,13 @@
int _max(int a, int b) => a > b ? a : b;
int _min(int a, int b) => a < b ? a : b;
+/// Allocate a new digits list of even length.
+Uint32List _newDigits(int length) => new Uint32List(length + (length & 1));
+
/**
* An implementation for the arbitrarily large integer.
*
- * The integer number is represented by a sign, an array of 16-bit unsigned
+ * The integer number is represented by a sign, an array of 32-bit unsigned
* integers in little endian format, and a number of used digits in that array.
*/
class _BigIntImpl implements BigInt {
@@ -81,6 +84,8 @@
static final _BigIntImpl two = new _BigIntImpl._fromInt(2);
static final _BigIntImpl _minusOne = -one;
+ static final _BigIntImpl _oneDigitMask = new _BigIntImpl._fromInt(_digitMask);
+ static final _BigIntImpl _twoDigitMask = (one << (2 * _digitBits)) - one;
static final _BigIntImpl _oneBillion = new _BigIntImpl._fromInt(1000000000);
static const int _minInt = -0x8000000000000000;
static const int _maxInt = 0x7fffffffffffffff;
@@ -104,12 +109,22 @@
/// The least significant digit is in slot 0.
/// The list may have more digits than needed. That is, `_digits.length` may
/// be strictly greater than `_used`.
+ /// Also, `_digits.length` must always be even, because intrinsics on 64-bit
+ /// platforms may process a digit pair as a 64-bit value.
final Uint32List _digits;
/// The number of used entries in [_digits].
///
/// To avoid reallocating [Uint32List]s, lists that are too big are not
- /// replaced.
+ /// replaced, but `_used` reflects the smaller number of digits actually used.
+ ///
+ /// Note that functions shortening an existing list of digits to a smaller
+ /// `_used` number of digits must ensure that the highermost pair of digits
+ /// is correct when read as a 64-bit value by intrinsics. Therefore, if the
+ /// smaller '_used' number is odd, the high digit of that pair must be
+ /// explicitly cleared, i.e. _digits[_used] = 0, which cannot result in an
+ /// out of bounds access, since the length of the list is guaranteed to be
+ /// even.
final int _used;
/**
@@ -197,34 +212,33 @@
///
/// The [source] (substring) must be a valid hex literal.
static _BigIntImpl _parseHex(String source, int startPos, bool isNegative) {
- int hexDigitsPerChunk = _digitBits ~/ 4;
+ int hexCharsPerDigit = _digitBits ~/ 4;
int sourceLength = source.length - startPos;
- int chunkCount =
- (sourceLength + hexDigitsPerChunk - 1) ~/ hexDigitsPerChunk;
- var digits = new Uint32List(chunkCount);
+ int used = (sourceLength + hexCharsPerDigit - 1) ~/ hexCharsPerDigit;
+ var digits = _newDigits(used);
- int lastDigitLength = sourceLength - (chunkCount - 1) * hexDigitsPerChunk;
- int digitIndex = digits.length - 1;
+ int lastDigitLength = sourceLength - (used - 1) * hexCharsPerDigit;
+ int digitIndex = used - 1;
int i = startPos;
- int chunk = 0;
+ int digit = 0;
for (int j = 0; j < lastDigitLength; j++) {
- var digitValue = _codeUnitToRadixValue(source.codeUnitAt(i++));
- if (digitValue >= 16) return null;
- chunk = chunk * 16 + digitValue;
+ var value = _codeUnitToRadixValue(source.codeUnitAt(i++));
+ if (value >= 16) return null;
+ digit = digit * 16 + value;
}
- digits[digitIndex--] = chunk;
+ digits[digitIndex--] = digit;
while (i < source.length) {
- chunk = 0;
- for (int j = 0; j < hexDigitsPerChunk; j++) {
- var digitValue = _codeUnitToRadixValue(source.codeUnitAt(i++));
- if (digitValue >= 16) return null;
- chunk = chunk * 16 + digitValue;
+ digit = 0;
+ for (int j = 0; j < hexCharsPerDigit; j++) {
+ var value = _codeUnitToRadixValue(source.codeUnitAt(i++));
+ if (value >= 16) return null;
+ digit = digit * 16 + value;
}
- digits[digitIndex--] = chunk;
+ digits[digitIndex--] = digit;
}
- if (digits.length == 1 && digits[0] == 0) return zero;
- return new _BigIntImpl._(isNegative, digits.length, digits);
+ if (used == 1 && digits[0] == 0) return zero;
+ return new _BigIntImpl._(isNegative, used, digits);
}
/// Parses the given [source] as a [radix] literal.
@@ -235,9 +249,9 @@
var result = zero;
var base = new _BigIntImpl._fromInt(radix);
for (int i = 0; i < source.length; i++) {
- var digitValue = _codeUnitToRadixValue(source.codeUnitAt(i));
- if (digitValue >= radix) return null;
- result = result * base + new _BigIntImpl._fromInt(digitValue);
+ var value = _codeUnitToRadixValue(source.codeUnitAt(i));
+ if (value >= radix) return null;
+ result = result * base + new _BigIntImpl._fromInt(value);
}
if (isNegative) return -result;
return result;
@@ -308,7 +322,10 @@
: this._normalized(isNegative, _normalize(used, digits), digits);
_BigIntImpl._normalized(bool isNegative, this._used, this._digits)
- : _isNegative = _used == 0 ? false : isNegative;
+ : _isNegative = _used == 0 ? false : isNegative {
+ assert(_digits.length.isEven);
+ assert(_used.isEven || _digits[_used] == 0); // Leading zero for 64-bit.
+ }
/// Whether this big integer is zero.
bool get _isZero => _used == 0;
@@ -318,7 +335,7 @@
/// digits.
static Uint32List _cloneDigits(
Uint32List digits, int from, int to, int length) {
- var resultDigits = new Uint32List(length);
+ var resultDigits = _newDigits(length);
var n = to - from;
for (var i = 0; i < n; i++) {
resultDigits[i] = digits[from + i];
@@ -341,22 +358,20 @@
factory _BigIntImpl._fromInt(int value) {
bool isNegative = value < 0;
assert(_digitBits == 32);
+ var digits = _newDigits(2);
if (isNegative) {
// Handle the min 64-bit value differently, since its negation is not
// positive.
if (value == _minInt) {
- var digits = new Uint32List(2);
digits[1] = 0x80000000;
return new _BigIntImpl._(true, 2, digits);
}
value = -value;
}
if (value < _digitBase) {
- var digits = new Uint32List(1);
digits[0] = value;
return new _BigIntImpl._(isNegative, 1, digits);
}
- var digits = new Uint32List(2);
digits[0] = value & _digitMask;
digits[1] = value >> _digitBits;
return new _BigIntImpl._(isNegative, 2, digits);
@@ -389,7 +404,7 @@
assert(_digitBits == 32);
// The significant bits are in 0 .. 52.
- var unshiftedDigits = new Uint32List(2);
+ var unshiftedDigits = _newDigits(2);
unshiftedDigits[0] =
(bits[3] << 24) + (bits[2] << 16) + (bits[1] << 8) + bits[0];
// Don't forget to add the hidden bit.
@@ -425,7 +440,7 @@
*/
_BigIntImpl abs() => _isNegative ? -this : this;
- /// Returns this << n *_DIGIT_BITS.
+ /// Returns this << n*_digitBits.
_BigIntImpl _dlShift(int n) {
final used = _used;
if (used == 0) {
@@ -433,7 +448,7 @@
}
final resultUsed = used + n;
final digits = _digits;
- final resultDigits = new Uint32List(resultUsed);
+ final resultDigits = _newDigits(resultUsed);
for (int i = used - 1; i >= 0; i--) {
resultDigits[i + n] = digits[i];
}
@@ -444,7 +459,7 @@
///
/// Returns `resultUsed`.
///
- /// `resultDigits[0..resultUsed-1] = xDigits[0..xUsed-1] << n*_DIGIT_BITS`.
+ /// `resultDigits[0..resultUsed-1] = xDigits[0..xUsed-1] << n*_digitBits`.
static int _dlShiftDigits(
Uint32List xDigits, int xUsed, int n, Uint32List resultDigits) {
if (xUsed == 0) {
@@ -454,16 +469,20 @@
return xUsed;
}
final resultUsed = xUsed + n;
+ assert(resultDigits.length >= resultUsed + (resultUsed & 1));
for (int i = xUsed - 1; i >= 0; i--) {
resultDigits[i + n] = xDigits[i];
}
for (int i = n - 1; i >= 0; i--) {
resultDigits[i] = 0;
}
+ if (resultUsed.isOdd) {
+ resultDigits[resultUsed] = 0;
+ }
return resultUsed;
}
- /// Returns `this >> n*_DIGIT_BITS`.
+ /// Returns `this >> n*_digitBits`.
_BigIntImpl _drShift(int n) {
final used = _used;
if (used == 0) {
@@ -474,7 +493,7 @@
return _isNegative ? _minusOne : zero;
}
final digits = _digits;
- final resultDigits = new Uint32List(resultUsed);
+ final resultDigits = _newDigits(resultUsed);
for (var i = n; i < used; i++) {
resultDigits[i - n] = digits[i];
}
@@ -490,12 +509,35 @@
return result;
}
+ /// Same as [_drShift] but works on the decomposed big integers.
+ ///
+ /// Returns `resultUsed`.
+ ///
+ /// `resultDigits[0..resultUsed-1] = xDigits[0..xUsed-1] >> n*_digitBits`.
+ static int _drShiftDigits(
+ Uint32List xDigits, int xUsed, int n, Uint32List resultDigits) {
+ final resultUsed = xUsed - n;
+ if (resultUsed <= 0) {
+ return 0;
+ }
+ assert(resultDigits.length >= resultUsed + (resultUsed & 1));
+ for (var i = n; i < xUsed; i++) {
+ resultDigits[i - n] = xDigits[i];
+ }
+ if (resultUsed.isOdd) {
+ resultDigits[resultUsed] = 0;
+ }
+ return resultUsed;
+ }
+
/// Shifts the digits of [xDigits] into the right place in [resultDigits].
///
- /// `resultDigits[ds..xUsed+ds] = xDigits[0..xUsed-1] << (n % _DIGIT_BITS)`
- /// where `ds = ceil(n / _DIGIT_BITS)`
+ /// `resultDigits[ds..xUsed+ds] = xDigits[0..xUsed-1] << (n % _digitBits)`
+ /// where `ds = ceil(n / _digitBits)`
///
/// Does *not* clear digits below ds.
+ ///
+ /// Note: This function may be intrinsified.
static void _lsh(
Uint32List xDigits, int xUsed, int n, Uint32List resultDigits) {
final digitShift = n ~/ _digitBits;
@@ -525,21 +567,22 @@
*/
_BigIntImpl operator <<(int shiftAmount) {
if (shiftAmount < 0) {
- throw new ArgumentError("shift-amount must be posititve $shiftAmount");
+ throw new ArgumentError("shift-amount must be positive $shiftAmount");
}
final digitShift = shiftAmount ~/ _digitBits;
final bitShift = shiftAmount % _digitBits;
if (bitShift == 0) {
return _dlShift(digitShift);
}
+ // Need one extra digit to hold bits shifted by bitShift.
var resultUsed = _used + digitShift + 1;
- var resultDigits = new Uint32List(resultUsed);
+ var resultDigits = _newDigits(resultUsed);
_lsh(_digits, _used, shiftAmount, resultDigits);
return new _BigIntImpl._(_isNegative, resultUsed, resultDigits);
}
- // resultDigits[0..resultUsed-1] = xDigits[0..xUsed-1] << n.
- // Returns resultUsed.
+ /// resultDigits[0..resultUsed-1] = xDigits[0..xUsed-1] << n.
+ /// Returns resultUsed.
static int _lShiftDigits(
Uint32List xDigits, int xUsed, int n, Uint32List resultDigits) {
final digitsShift = n ~/ _digitBits;
@@ -547,7 +590,9 @@
if (bitShift == 0) {
return _dlShiftDigits(xDigits, xUsed, digitsShift, resultDigits);
}
+ // Need one extra digit to hold bits shifted by bitShift.
var resultUsed = xUsed + digitsShift + 1;
+ assert(resultDigits.length >= resultUsed + (resultUsed & 1));
_lsh(xDigits, xUsed, n, resultDigits);
var i = digitsShift;
while (--i >= 0) {
@@ -555,11 +600,15 @@
}
if (resultDigits[resultUsed - 1] == 0) {
resultUsed--; // Clamp result.
+ } else if (resultUsed.isOdd) {
+ resultDigits[resultUsed] = 0;
}
return resultUsed;
}
- // resultDigits[0..resultUsed-1] = xDigits[0..xUsed-1] >> n.
+ /// resultDigits[0..resultUsed-1] = xDigits[0..xUsed-1] >> n.
+ ///
+ /// Note: This function may be intrinsified.
static void _rsh(
Uint32List xDigits, int xUsed, int n, Uint32List resultDigits) {
final digitsShift = n ~/ _digitBits;
@@ -587,7 +636,7 @@
*/
_BigIntImpl operator >>(int shiftAmount) {
if (shiftAmount < 0) {
- throw new ArgumentError("shift-amount must be posititve $shiftAmount");
+ throw new ArgumentError("shift-amount must be positive $shiftAmount");
}
final digitShift = shiftAmount ~/ _digitBits;
final bitShift = shiftAmount % _digitBits;
@@ -600,7 +649,7 @@
return _isNegative ? _minusOne : zero;
}
final digits = _digits;
- final resultDigits = new Uint32List(resultUsed);
+ final resultDigits = _newDigits(resultUsed);
_rsh(digits, used, shiftAmount, resultDigits);
final result = new _BigIntImpl._(_isNegative, resultUsed, resultDigits);
if (_isNegative) {
@@ -617,6 +666,29 @@
return result;
}
+ /// resultDigits[0..resultUsed-1] = xDigits[0..xUsed-1] >> n.
+ /// Returns resultUsed.
+ static int _rShiftDigits(
+ Uint32List xDigits, int xUsed, int n, Uint32List resultDigits) {
+ final digitShift = n ~/ _digitBits;
+ final bitShift = n % _digitBits;
+ if (bitShift == 0) {
+ return _drShiftDigits(xDigits, xUsed, digitShift, resultDigits);
+ }
+ var resultUsed = xUsed - digitShift;
+ if (resultUsed <= 0) {
+ return 0;
+ }
+ assert(resultDigits.length >= resultUsed + (resultUsed & 1));
+ _rsh(xDigits, xUsed, n, resultDigits);
+ if (resultDigits[resultUsed - 1] == 0) {
+ resultUsed--; // Clamp result.
+ } else if (resultUsed.isOdd) {
+ resultDigits[resultUsed] = 0;
+ }
+ return resultUsed;
+ }
+
/// Compares this to [other] taking the absolute value of both operands.
///
/// Returns 0 if abs(this) == abs(other); a positive number if
@@ -658,8 +730,10 @@
return result;
}
- // resultDigits[0..used] = digits[0..used-1] + otherDigits[0..otherUsed-1].
- // used >= otherUsed > 0.
+ /// resultDigits[0..used] = digits[0..used-1] + otherDigits[0..otherUsed-1].
+ /// used >= otherUsed > 0.
+ ///
+ /// Note: This function may be intrinsified.
static void _absAdd(Uint32List digits, int used, Uint32List otherDigits,
int otherUsed, Uint32List resultDigits) {
assert(used >= otherUsed && otherUsed > 0);
@@ -677,12 +751,13 @@
resultDigits[used] = carry;
}
- // resultDigits[0..used-1] = digits[0..used-1] - otherDigits[0..otherUsed-1].
- // used >= otherUsed > 0.
+ /// resultDigits[0..used-1] = digits[0..used-1] - otherDigits[0..otherUsed-1].
+ /// used >= otherUsed > 0.
+ ///
+ /// Note: This function may be intrinsified.
static void _absSub(Uint32List digits, int used, Uint32List otherDigits,
int otherUsed, Uint32List resultDigits) {
assert(used >= otherUsed && otherUsed > 0);
-
var carry = 0;
for (var i = 0; i < otherUsed; i++) {
carry += digits[i] - otherDigits[i];
@@ -711,7 +786,7 @@
return _isNegative == isNegative ? this : -this;
}
var resultUsed = used + 1;
- var resultDigits = new Uint32List(resultUsed);
+ var resultDigits = _newDigits(resultUsed);
_absAdd(_digits, used, other._digits, otherUsed, resultDigits);
return new _BigIntImpl._(isNegative, resultUsed, resultDigits);
}
@@ -730,7 +805,7 @@
if (otherUsed == 0) {
return _isNegative == isNegative ? this : -this;
}
- var resultDigits = new Uint32List(used);
+ var resultDigits = _newDigits(used);
_absSub(_digits, used, other._digits, otherUsed, resultDigits);
return new _BigIntImpl._(isNegative, used, resultDigits);
}
@@ -740,7 +815,7 @@
var resultUsed = _min(_used, other._used);
var digits = _digits;
var otherDigits = other._digits;
- var resultDigits = new Uint32List(resultUsed);
+ var resultDigits = _newDigits(resultUsed);
for (var i = 0; i < resultUsed; i++) {
resultDigits[i] = digits[i] & otherDigits[i];
}
@@ -752,7 +827,7 @@
var resultUsed = _used;
var digits = _digits;
var otherDigits = other._digits;
- var resultDigits = new Uint32List(resultUsed);
+ var resultDigits = _newDigits(resultUsed);
var m = _min(resultUsed, other._used);
for (var i = 0; i < m; i++) {
resultDigits[i] = digits[i] & ~otherDigits[i];
@@ -770,7 +845,7 @@
var resultUsed = _max(used, otherUsed);
var digits = _digits;
var otherDigits = other._digits;
- var resultDigits = new Uint32List(resultUsed);
+ var resultDigits = _newDigits(resultUsed);
var l, m;
if (used < otherUsed) {
l = other;
@@ -796,7 +871,7 @@
var resultUsed = _max(used, otherUsed);
var digits = _digits;
var otherDigits = other._digits;
- var resultDigits = new Uint32List(resultUsed);
+ var resultDigits = _newDigits(resultUsed);
var l, m;
if (used < otherUsed) {
l = other;
@@ -983,23 +1058,33 @@
return other._absSubSetSign(this, !isNegative);
}
- /// Multiplies [x] with [multiplicandDigits] and adds the result to
- /// [accumulatorDigits].
+ /// Multiplies `xDigits[xIndex]` with `multiplicandDigits` and adds the result
+ /// to `accumulatorDigits`.
///
- /// The [multiplicandDigits] in the range [i] to [i]+[n]-1 are the
+ /// The `multiplicandDigits` in the range `i` to `i`+`n`-1 are the
/// multiplicand digits.
///
- /// The [acculumatorDigits] in the range [j] to [j]+[n]-1 are the accumulator
+ /// The `acculumatorDigits` in the range `j` to `j`+`n`-1 are the accumulator
/// digits.
///
- /// Adds the result of the multiplicand-digits * [x] to the accumulator.
+ /// Concretely:
+ /// `accumulatorDigits[j..j+n] += xDigits[xIndex] * m_digits[i..i+n-1]`.
+ /// Returns 1.
///
- /// Concretely: `accumulatorDigits[j..j+n] += x * m_digits[i..i+n-1]`.
- static void _mulAdd(int x, Uint32List multiplicandDigits, int i,
- Uint32List accumulatorDigits, int j, int n) {
+ /// Note: This function may be intrinsified. Intrinsics on 64-bit platforms
+ /// process digit pairs at even indices and returns 2.
+ static int _mulAdd(
+ Uint32List xDigits,
+ int xIndex,
+ Uint32List multiplicandDigits,
+ int i,
+ Uint32List accumulatorDigits,
+ int j,
+ int n) {
+ int x = xDigits[xIndex];
if (x == 0) {
// No-op if x is 0.
- return;
+ return 1;
}
int carry = 0;
int xl = x & _halfDigitMask;
@@ -1020,6 +1105,63 @@
carry = l >> _digitBits;
accumulatorDigits[j++] = l & _digitMask;
}
+ return 1;
+ }
+
+ /// Multiplies `xDigits[i]` with `xDigits` and adds the result to
+ /// `accumulatorDigits`.
+ ///
+ /// The `xDigits` in the range `i` to `used`-1 are the multiplicand digits.
+ ///
+ /// The `acculumatorDigits` in the range 2*`i` to `i`+`used`-1 are the
+ /// accumulator digits.
+ ///
+ /// Concretely:
+ /// `accumulatorDigits[2*i..i+used-1] += xDigits[i]*xDigits[i] +
+ /// 2*xDigits[i]*xDigits[i+1..used-1]`.
+ /// Returns 1.
+ ///
+ /// Note: This function may be intrinsified. Intrinsics on 64-bit platforms
+ /// process digit pairs at even indices and returns 2.
+ static int _sqrAdd(
+ Uint32List xDigits, int i, Uint32List acculumatorDigits, int used) {
+ int x = xDigits[i];
+ if (x == 0) return 1;
+ int j = 2 * i;
+ int carry = 0;
+ int xl = x & _halfDigitMask;
+ int xh = x >> _halfDigitBits;
+ int ph = 2 * xh * xl;
+ int pl = xl * xl +
+ ((ph & _halfDigitMask) << _halfDigitBits) +
+ acculumatorDigits[j];
+ carry = (pl >> _digitBits) + (ph >> _halfDigitBits) + xh * xh;
+ acculumatorDigits[j] = pl & _digitMask;
+ x <<= 1;
+ xl = x & _halfDigitMask;
+ xh = x >> _halfDigitBits;
+ int n = used - i - 1;
+ int k = i + 1;
+ j++;
+ while (--n >= 0) {
+ int l = xDigits[k] & _halfDigitMask;
+ int h = xDigits[k++] >> _halfDigitBits;
+ int ph = xh * l + h * xl;
+ int pl = xl * l +
+ ((ph & _halfDigitMask) << _halfDigitBits) +
+ acculumatorDigits[j] +
+ carry;
+ carry = (pl >> _digitBits) + (ph >> _halfDigitBits) + xh * h;
+ acculumatorDigits[j++] = pl & _digitMask;
+ }
+ carry += acculumatorDigits[i + used];
+ if (carry >= _digitBase) {
+ acculumatorDigits[i + used] = carry - _digitBase;
+ acculumatorDigits[i + used + 1] = 1;
+ } else {
+ acculumatorDigits[i + used] = carry;
+ }
+ return 1;
}
/// Multiplication operator.
@@ -1033,44 +1175,91 @@
var resultUsed = used + otherUsed;
var digits = _digits;
var otherDigits = other._digits;
- var resultDigits = new Uint32List(resultUsed);
+ var resultDigits = _newDigits(resultUsed);
var i = 0;
while (i < otherUsed) {
- _mulAdd(otherDigits[i], digits, 0, resultDigits, i, used);
- i++;
+ i += _mulAdd(otherDigits, i, digits, 0, resultDigits, i, used);
}
return new _BigIntImpl._(
_isNegative != other._isNegative, resultUsed, resultDigits);
}
- // r_digits[0..rUsed-1] = xDigits[0..xUsed-1]*otherDigits[0..otherUsed-1].
- // Return resultUsed = xUsed + otherUsed.
+ // resultDigits[0..resultUsed-1] =
+ // xDigits[0..xUsed-1]*otherDigits[0..otherUsed-1].
+ // Returns resultUsed = xUsed + otherUsed.
static int _mulDigits(Uint32List xDigits, int xUsed, Uint32List otherDigits,
int otherUsed, Uint32List resultDigits) {
var resultUsed = xUsed + otherUsed;
- var i = resultUsed;
+ var i = resultUsed + (resultUsed & 1);
assert(resultDigits.length >= i);
while (--i >= 0) {
resultDigits[i] = 0;
}
i = 0;
while (i < otherUsed) {
- _mulAdd(otherDigits[i], xDigits, 0, resultDigits, i, xUsed);
- i++;
+ i += _mulAdd(otherDigits, i, xDigits, 0, resultDigits, i, xUsed);
}
return resultUsed;
}
- /// Returns an estimate of `digits[i-1..i] ~/ topDigitDivisor`.
- static int _estimateQuotientDigit(
- int topDigitDivisor, Uint32List digits, int i) {
- if (digits[i] == topDigitDivisor) return _digitMask;
- // Chop off one bit, since a Mint cannot hold 2 digits.
- var quotientDigit =
- ((digits[i] << (_digitBits - 1)) | (digits[i - 1] >> 1)) ~/
- (topDigitDivisor >> 1);
- if (quotientDigit > _digitMask) return _digitMask;
- return quotientDigit;
+ // resultDigits[0..resultUsed-1] = xDigits[0..xUsed-1]^2.
+ // Returns resultUsed = 2*xUsed.
+ static int _sqrDigits(
+ Uint32List xDigits, int xUsed, Uint32List resultDigits) {
+ var resultUsed = 2 * xUsed;
+ assert(resultDigits.length >= resultUsed);
+ // Since resultUsed is even, no need for a leading zero for
+ // 64-bit processing.
+ var i = resultUsed;
+ while (--i >= 0) {
+ resultDigits[i] = 0;
+ }
+ i = 0;
+ while (i < xUsed - 1) {
+ i += _sqrAdd(xDigits, i, resultDigits, xUsed);
+ }
+ // The last step is already done if digit pairs were processed above.
+ if (i < xUsed) {
+ _mulAdd(xDigits, i, xDigits, i, resultDigits, 2 * i, 1);
+ }
+ return resultUsed;
+ }
+
+ // Indices of the arguments of _estimateQuotientDigit.
+ // For 64-bit processing by intrinsics on 64-bit platforms, the top digit pair
+ // of the divisor is provided in the args array, and a 64-bit estimated
+ // quotient is returned. However, on 32-bit platforms, the low 32-bit digit is
+ // ignored and only one 32-bit digit is returned as the estimated quotient.
+ static const int _divisorLowTopDigit = 0; // Low digit of top pair of divisor.
+ static const int _divisorTopDigit = 1; // Top digit of divisor.
+ static const int _quotientDigit = 2; // Estimated quotient.
+ static const int _quotientHighDigit = 3; // High digit of estimated quotient.
+
+ /// Estimate `args[_quotientDigit] = digits[i-1..i] ~/ args[_divisorTopDigit]`
+ /// Returns 1.
+ ///
+ /// Note: This function may be intrinsified. Intrinsics on 64-bit platforms
+ /// process a digit pair (i always odd):
+ /// Estimate `args[_quotientDigit.._quotientHighDigit] = digits[i-3..i] ~/
+ /// args[_divisorLowTopDigit.._divisorTopDigit]`.
+ /// Returns 2.
+ static int _estimateQuotientDigit(Uint32List args, Uint32List digits, int i) {
+ // Verify that digit pairs are accessible for 64-bit processing.
+ assert(digits.length >= 4);
+ if (digits[i] == args[_divisorTopDigit]) {
+ args[_quotientDigit] = _digitMask;
+ } else {
+ // Chop off one bit, since a Mint cannot hold 2 digits.
+ var quotientDigit =
+ ((digits[i] << (_digitBits - 1)) | (digits[i - 1] >> 1)) ~/
+ (args[_divisorTopDigit] >> 1);
+ if (quotientDigit > _digitMask) {
+ args[_quotientDigit] = _digitMask;
+ } else {
+ args[_quotientDigit] = quotientDigit;
+ }
+ }
+ return 1;
}
/// Returns `trunc(this / other)`, with `other != 0`.
@@ -1134,32 +1323,43 @@
assert(_used >= other._used);
var nsh = _digitBits - other._digits[other._used - 1].bitLength;
+ // For 64-bit processing, make sure other has an even number of digits.
+ if (other._used.isOdd) {
+ nsh += _digitBits;
+ }
// Concatenated positive quotient and normalized positive remainder.
// The resultDigits can have at most one more digit than the dividend.
Uint32List resultDigits;
int resultUsed;
- // Normalized positive divisor.
+ // Normalized positive divisor (referred to as 'y').
// The normalized divisor has the most-significant bit of its most
// significant digit set.
// This makes estimating the quotient easier.
Uint32List yDigits;
int yUsed;
if (nsh > 0) {
- yDigits = new Uint32List(other._used + 5);
+ // Extra digits for normalization.
+ yDigits = _newDigits(other._used + (nsh % _digitBits) + 1);
yUsed = _lShiftDigits(other._digits, other._used, nsh, yDigits);
- resultDigits = new Uint32List(_used + 5);
+ // Extra digits for normalization, also used for possible _mulAdd carry.
+ resultDigits = _newDigits(_used + (nsh % _digitBits) + 1);
resultUsed = _lShiftDigits(_digits, _used, nsh, resultDigits);
} else {
yDigits = other._digits;
yUsed = other._used;
- resultDigits = _cloneDigits(_digits, 0, _used, _used + 2);
+ // Extra digit to hold possible _mulAdd carry.
+ resultDigits = _cloneDigits(_digits, 0, _used, _used + 1);
resultUsed = _used;
}
- var topDigitDivisor = yDigits[yUsed - 1];
- var i = resultUsed;
+ Uint32List args = _newDigits(4);
+ args[_divisorLowTopDigit] = yDigits[yUsed - 2];
+ args[_divisorTopDigit] = yDigits[yUsed - 1];
+ // For 64-bit processing, make sure yUsed, i, and j are even.
+ assert(yUsed.isEven);
+ var i = resultUsed + (resultUsed & 1);
var j = i - yUsed;
- // tmpDigits is a temporary array of i (resultUsed) digits.
- var tmpDigits = new Uint32List(i);
+ // tmpDigits is a temporary array of i (even resultUsed) digits.
+ var tmpDigits = _newDigits(i);
var tmpUsed = _dlShiftDigits(yDigits, yUsed, j, tmpDigits);
// Explicit first division step in case normalized dividend is larger or
// equal to shifted normalized divisor.
@@ -1172,32 +1372,61 @@
// Account for possible carry in _mulAdd step.
resultDigits[resultUsed++] = 0;
}
-
+ if (resultUsed.isOdd) {
+ resultDigits[resultUsed] = 0; // Leading zero for 64-bit processing.
+ }
// Negate y so we can later use _mulAdd instead of non-existent _mulSub.
- var nyDigits = new Uint32List(yUsed + 2);
+ var nyDigits = _newDigits(yUsed + 2);
nyDigits[yUsed] = 1;
_absSub(nyDigits, yUsed + 1, yDigits, yUsed, nyDigits);
// nyDigits is read-only and has yUsed digits (possibly including several
- // leading zeros).
+ // leading zeros) plus a leading zero for 64-bit processing.
// resultDigits is modified during iteration.
// resultDigits[0..yUsed-1] is the current remainder.
// resultDigits[yUsed..resultUsed-1] is the current quotient.
--i;
-
while (j > 0) {
- var estimatedQuotientDigit =
- _estimateQuotientDigit(topDigitDivisor, resultDigits, i);
- j--;
- _mulAdd(estimatedQuotientDigit, nyDigits, 0, resultDigits, j, yUsed);
- if (resultDigits[i] < estimatedQuotientDigit) {
- // Reusing the already existing tmpDigits array.
- var tmpUsed = _dlShiftDigits(nyDigits, yUsed, j, tmpDigits);
- _absSub(resultDigits, resultUsed, tmpDigits, tmpUsed, resultDigits);
- while (resultDigits[i] < --estimatedQuotientDigit) {
+ var d0 = _estimateQuotientDigit(args, resultDigits, i);
+ j -= d0;
+ var d1 =
+ _mulAdd(args, _quotientDigit, nyDigits, 0, resultDigits, j, yUsed);
+ // _estimateQuotientDigit and _mulAdd must agree on the number of digits
+ // to process.
+ assert(d0 == d1);
+ if (d0 == 1) {
+ if (resultDigits[i] < args[_quotientDigit]) {
+ // Reusing the already existing tmpDigits array.
+ var tmpUsed = _dlShiftDigits(nyDigits, yUsed, j, tmpDigits);
_absSub(resultDigits, resultUsed, tmpDigits, tmpUsed, resultDigits);
+ while (resultDigits[i] < --args[_quotientDigit]) {
+ _absSub(resultDigits, resultUsed, tmpDigits, tmpUsed, resultDigits);
+ }
+ }
+ } else {
+ assert(d0 == 2);
+ assert(resultDigits[i] <= args[_quotientHighDigit]);
+ if (resultDigits[i] < args[_quotientHighDigit] ||
+ resultDigits[i - 1] < args[_quotientDigit]) {
+ // Reusing the already existing tmpDigits array.
+ var tmpUsed = _dlShiftDigits(nyDigits, yUsed, j, tmpDigits);
+ _absSub(resultDigits, resultUsed, tmpDigits, tmpUsed, resultDigits);
+ if (args[_quotientDigit] == 0) {
+ --args[_quotientHighDigit];
+ }
+ --args[_quotientDigit];
+ assert(resultDigits[i] <= args[_quotientHighDigit]);
+ while (resultDigits[i] < args[_quotientHighDigit] ||
+ resultDigits[i - 1] < args[_quotientDigit]) {
+ _absSub(resultDigits, resultUsed, tmpDigits, tmpUsed, resultDigits);
+ if (args[_quotientDigit] == 0) {
+ --args[_quotientHighDigit];
+ }
+ --args[_quotientDigit];
+ assert(resultDigits[i] <= args[_quotientHighDigit]);
+ }
}
}
- i--;
+ i -= d0;
}
// Cache result.
_lastDividendDigits = _digits;
@@ -1210,6 +1439,108 @@
_lastRem_nsh = nsh;
}
+ // Customized version of _rem() minimizing allocations for use in reduction.
+ // Input:
+ // xDigits[0..xUsed-1]: positive dividend.
+ // yDigits[0..yUsed-1]: normalized positive divisor.
+ // nyDigits[0..yUsed-1]: negated yDigits.
+ // nsh: normalization shift amount.
+ // args: top y digit(s) and place holder for estimated quotient digit(s).
+ // tmpDigits: temp array of 2*yUsed digits.
+ // resultDigits: result digits array large enough to temporarily hold
+ // concatenated quotient and normalized remainder.
+ // Output:
+ // resultDigits[0..resultUsed-1]: positive remainder.
+ // Returns resultUsed.
+ static int _remDigits(
+ Uint32List xDigits,
+ int xUsed,
+ Uint32List yDigits,
+ int yUsed,
+ Uint32List nyDigits,
+ int nsh,
+ Uint32List args,
+ Uint32List tmpDigits,
+ Uint32List resultDigits) {
+ // Initialize resultDigits to normalized positive dividend.
+ var resultUsed = _lShiftDigits(xDigits, xUsed, nsh, resultDigits);
+ // For 64-bit processing, make sure yUsed, i, and j are even.
+ assert(yUsed.isEven);
+ var i = resultUsed + (resultUsed & 1);
+ var j = i - yUsed;
+ var tmpUsed = _dlShiftDigits(yDigits, yUsed, j, tmpDigits);
+ // Explicit first division step in case normalized dividend is larger or
+ // equal to shifted normalized divisor.
+ if (_compareDigits(resultDigits, resultUsed, tmpDigits, tmpUsed) >= 0) {
+ assert(i == resultUsed);
+ resultDigits[resultUsed++] = 1; // Quotient = 1.
+ // Subtract divisor from remainder.
+ _absSub(resultDigits, resultUsed, tmpDigits, tmpUsed, resultDigits);
+ } else {
+ // Account for possible carry in _mulAdd step.
+ resultDigits[resultUsed++] = 0;
+ }
+ if (resultUsed.isOdd) {
+ resultDigits[resultUsed] = 0; // Leading zero for 64-bit processing.
+ }
+ // Negated yDigits passed in nyDigits allow the use of _mulAdd instead of
+ // unimplemented _mulSub.
+ // nyDigits is read-only and has yUsed digits (possibly including several
+ // leading zeros) plus a leading zero for 64-bit processing.
+ // resultDigits is modified during iteration.
+ // resultDigits[0..yUsed-1] is the current remainder.
+ // resultDigits[yUsed..resultUsed-1] is the current quotient.
+ --i;
+ while (j > 0) {
+ var d0 = _estimateQuotientDigit(args, resultDigits, i);
+ j -= d0;
+ var d1 =
+ _mulAdd(args, _quotientDigit, nyDigits, 0, resultDigits, j, yUsed);
+ // _estimateQuotientDigit and _mulAdd must agree on the number of digits
+ // to process.
+ assert(d0 == d1);
+ if (d0 == 1) {
+ if (resultDigits[i] < args[_quotientDigit]) {
+ var tmpUsed = _dlShiftDigits(nyDigits, yUsed, j, tmpDigits);
+ _absSub(resultDigits, resultUsed, tmpDigits, tmpUsed, resultDigits);
+ while (resultDigits[i] < --args[_quotientDigit]) {
+ _absSub(resultDigits, resultUsed, tmpDigits, tmpUsed, resultDigits);
+ }
+ }
+ } else {
+ assert(d0 == 2);
+ assert(resultDigits[i] <= args[_quotientHighDigit]);
+ if ((resultDigits[i] < args[_quotientHighDigit]) ||
+ (resultDigits[i - 1] < args[_quotientDigit])) {
+ var tmpUsed = _dlShiftDigits(nyDigits, yUsed, j, tmpDigits);
+ _absSub(resultDigits, resultUsed, tmpDigits, tmpUsed, resultDigits);
+ if (args[_quotientDigit] == 0) {
+ --args[_quotientHighDigit];
+ }
+ --args[_quotientDigit];
+ assert(resultDigits[i] <= args[_quotientHighDigit]);
+ while ((resultDigits[i] < args[_quotientHighDigit]) ||
+ (resultDigits[i - 1] < args[_quotientDigit])) {
+ _absSub(resultDigits, resultUsed, tmpDigits, tmpUsed, resultDigits);
+ if (args[_quotientDigit] == 0) {
+ --args[_quotientHighDigit];
+ }
+ --args[_quotientDigit];
+ assert(resultDigits[i] <= args[_quotientHighDigit]);
+ }
+ }
+ }
+ i -= d0;
+ }
+ // Return remainder, i.e. denormalized resultDigits[0..yUsed-1].
+ resultUsed = yUsed;
+ if (nsh > 0) {
+ // Denormalize remainder.
+ resultUsed = _rShiftDigits(resultDigits, resultUsed, nsh, resultDigits);
+ }
+ return resultUsed;
+ }
+
int get hashCode {
// This is the [Jenkins hash function][1] but using masking to keep
// values in SMI range.
@@ -1239,8 +1570,8 @@
/**
* Test whether this value is numerically equal to `other`.
*
- * If [other] is a [_BigIntImpl] returns whether the two operands have the same
- * value.
+ * If [other] is a [_BigIntImpl] returns whether the two operands have the
+ * same value.
*
* Returns false if `other` is not a [_BigIntImpl].
*/
@@ -1419,38 +1750,142 @@
}
if (exponent._isZero) return one;
- final modulusUsed = modulus._used;
- final modulusUsed2p4 = 2 * modulusUsed + 4;
final exponentBitlen = exponent.bitLength;
if (exponentBitlen <= 0) return one;
- _BigIntReduction z = new _BigIntClassic(modulus);
- var resultDigits = new Uint32List(modulusUsed2p4);
- var result2Digits = new Uint32List(modulusUsed2p4);
- var gDigits = new Uint32List(modulusUsed);
- var gUsed = z.convert(this, gDigits);
- // Initialize result with g.
- // Copy leading zero if any.
- for (int j = gUsed - 1; j >= 0; j--) {
- resultDigits[j] = gDigits[j];
+ final bool cannotUseMontgomery = modulus.isEven || abs() >= modulus;
+ if (cannotUseMontgomery || exponentBitlen < 64) {
+ _BigIntReduction z = (cannotUseMontgomery || exponentBitlen < 8)
+ ? new _BigIntClassicReduction(modulus)
+ : new _BigIntMontgomeryReduction(modulus);
+ var resultDigits = _newDigits(2 * z._normModulusUsed + 2);
+ var result2Digits = _newDigits(2 * z._normModulusUsed + 2);
+ var gDigits = _newDigits(z._normModulusUsed);
+ var gUsed = z._convert(this, gDigits);
+ // Initialize result with g.
+ // Copy leading zero if any.
+ for (int j = gUsed + (gUsed & 1) - 1; j >= 0; j--) {
+ resultDigits[j] = gDigits[j];
+ }
+ var resultUsed = gUsed;
+ var result2Used;
+ for (int i = exponentBitlen - 2; i >= 0; i--) {
+ result2Used = z._sqr(resultDigits, resultUsed, result2Digits);
+ if (exponent._digits[i ~/ _digitBits] & (1 << (i % _digitBits)) != 0) {
+ resultUsed =
+ z._mul(result2Digits, result2Used, gDigits, gUsed, resultDigits);
+ } else {
+ // Swap result and result2.
+ var tmpDigits = resultDigits;
+ var tmpUsed = resultUsed;
+ resultDigits = result2Digits;
+ resultUsed = result2Used;
+ result2Digits = tmpDigits;
+ result2Used = tmpUsed;
+ }
+ }
+ return z._revert(resultDigits, resultUsed);
}
- var resultUsed = gUsed;
- var result2Used;
- for (int i = exponentBitlen - 2; i >= 0; i--) {
- result2Used = z.sqr(resultDigits, resultUsed, result2Digits);
- if (!(exponent & (one << i))._isZero) {
- resultUsed =
- z.mul(result2Digits, result2Used, gDigits, gUsed, resultDigits);
- } else {
- // Swap result and result2.
- var tmpDigits = resultDigits;
- var tmpUsed = resultUsed;
- resultDigits = result2Digits;
- resultUsed = result2Used;
- result2Digits = tmpDigits;
- result2Used = tmpUsed;
+ var k;
+ if (exponentBitlen < 18)
+ k = 1;
+ else if (exponentBitlen < 48)
+ k = 3;
+ else if (exponentBitlen < 144)
+ k = 4;
+ else if (exponentBitlen < 768)
+ k = 5;
+ else
+ k = 6;
+ _BigIntReduction z = new _BigIntMontgomeryReduction(modulus);
+ var n = 3;
+ final k1 = k - 1;
+ final km = (1 << k) - 1;
+ List gDigits = new List(km + 1);
+ List gUsed = new List(km + 1);
+ gDigits[1] = _newDigits(z._normModulusUsed);
+ gUsed[1] = z._convert(this, gDigits[1]);
+ if (k > 1) {
+ var g2Digits = _newDigits(2 * z._normModulusUsed + 2);
+ var g2Used = z._sqr(gDigits[1], gUsed[1], g2Digits);
+ while (n <= km) {
+ gDigits[n] = _newDigits(2 * z._normModulusUsed + 2);
+ gUsed[n] =
+ z._mul(g2Digits, g2Used, gDigits[n - 2], gUsed[n - 2], gDigits[n]);
+ n += 2;
}
}
- return z.revert(resultDigits, resultUsed);
+ var w;
+ var isOne = true;
+ var resultDigits = one._digits;
+ var resultUsed = one._used;
+ var result2Digits = _newDigits(2 * z._normModulusUsed + 2);
+ var result2Used;
+ var exponentDigits = exponent._digits;
+ var j = exponent._used - 1;
+ var i = exponentDigits[j].bitLength - 1;
+ while (j >= 0) {
+ if (i >= k1) {
+ w = (exponentDigits[j] >> (i - k1)) & km;
+ } else {
+ w = (exponentDigits[j] & ((1 << (i + 1)) - 1)) << (k1 - i);
+ if (j > 0) {
+ w |= exponentDigits[j - 1] >> (_digitBits + i - k1);
+ }
+ }
+ n = k;
+ while ((w & 1) == 0) {
+ w >>= 1;
+ --n;
+ }
+ if ((i -= n) < 0) {
+ i += _digitBits;
+ --j;
+ }
+ if (isOne) {
+ // r == 1, don't bother squaring or multiplying it.
+ resultDigits = _newDigits(2 * z._normModulusUsed + 2);
+ resultUsed = gUsed[w];
+ var gwDigits = gDigits[w];
+ var ri = resultUsed + (resultUsed & 1); // Copy leading zero if any.
+ while (--ri >= 0) {
+ resultDigits[ri] = gwDigits[ri];
+ }
+ isOne = false;
+ } else {
+ while (n > 1) {
+ result2Used = z._sqr(resultDigits, resultUsed, result2Digits);
+ resultUsed = z._sqr(result2Digits, result2Used, resultDigits);
+ n -= 2;
+ }
+ if (n > 0) {
+ result2Used = z._sqr(resultDigits, resultUsed, result2Digits);
+ } else {
+ var swapDigits = resultDigits;
+ var swapUsed = resultUsed;
+ resultDigits = result2Digits;
+ resultUsed = result2Used;
+ result2Digits = swapDigits;
+ result2Used = swapUsed;
+ }
+ resultUsed = z._mul(
+ result2Digits, result2Used, gDigits[w], gUsed[w], resultDigits);
+ }
+ while (j >= 0 && (exponentDigits[j] & (1 << i)) == 0) {
+ result2Used = z._sqr(resultDigits, resultUsed, result2Digits);
+ var swapDigits = resultDigits;
+ var swapUsed = resultUsed;
+ resultDigits = result2Digits;
+ resultUsed = result2Used;
+ result2Digits = swapDigits;
+ result2Used = swapUsed;
+ if (--i < 0) {
+ i = _digitBits - 1;
+ --j;
+ }
+ }
+ }
+ assert(!isOne);
+ return z._revert(resultDigits, resultUsed);
}
// If inv is false, returns gcd(x, y).
@@ -1461,10 +1896,10 @@
var yDigits = y._digits;
var xUsed = x._used;
var yUsed = y._used;
- var maxUsed = xUsed > yUsed ? xUsed : yUsed;
- var unshiftedMaxUsed = maxUsed; // Keep
- xDigits = _cloneDigits(xDigits, 0, xUsed, maxUsed);
- yDigits = _cloneDigits(yDigits, 0, yUsed, maxUsed);
+ var maxUsed = _max(xUsed, yUsed);
+ final maxLen = maxUsed + (maxUsed & 1);
+ xDigits = _cloneDigits(xDigits, 0, xUsed, maxLen);
+ yDigits = _cloneDigits(yDigits, 0, yUsed, maxLen);
int shiftAmount = 0;
if (inv) {
if ((yUsed == 1) && (yDigits[0] == 1)) return one;
@@ -1501,26 +1936,25 @@
yUsed = tmpUsed;
}
}
- var uDigits = _cloneDigits(xDigits, 0, xUsed, unshiftedMaxUsed);
- var vDigits =
- _cloneDigits(yDigits, 0, yUsed, unshiftedMaxUsed + 2); // +2 for lsh.
+ var uDigits = _cloneDigits(xDigits, 0, xUsed, maxLen);
+ var vDigits = _cloneDigits(yDigits, 0, yUsed, maxLen + 2); // +2 for lsh.
final bool ac = (xDigits[0] & 1) == 0;
// Variables a, b, c, and d require one more digit.
final abcdUsed = maxUsed + 1;
- final abcdLen = abcdUsed + 2; // +2 to satisfy _absAdd.
+ final abcdLen = abcdUsed + (abcdUsed & 1) + 2; // +2 to satisfy _absAdd.
var aDigits, bDigits, cDigits, dDigits;
bool aIsNegative, bIsNegative, cIsNegative, dIsNegative;
if (ac) {
- aDigits = new Uint32List(abcdLen);
+ aDigits = _newDigits(abcdLen);
aIsNegative = false;
aDigits[0] = 1;
- cDigits = new Uint32List(abcdLen);
+ cDigits = _newDigits(abcdLen);
cIsNegative = false;
}
- bDigits = new Uint32List(abcdLen);
+ bDigits = _newDigits(abcdLen);
bIsNegative = false;
- dDigits = new Uint32List(abcdLen);
+ dDigits = _newDigits(abcdLen);
dIsNegative = false;
dDigits[0] = 1;
@@ -2046,27 +2480,240 @@
// Interface for modular reduction.
abstract class _BigIntReduction {
- // Return the number of digits used by r_digits.
- int convert(_BigIntImpl x, Uint32List r_digits);
- int mul(Uint32List xDigits, int xUsed, Uint32List yDigits, int yUsed,
+ int get _normModulusUsed;
+ // Return the number of digits used by resultDigits.
+ int _convert(_BigIntImpl x, Uint32List resultDigits);
+ int _mul(Uint32List xDigits, int xUsed, Uint32List yDigits, int yUsed,
Uint32List resultDigits);
- int sqr(Uint32List xDigits, int xUsed, Uint32List resultDigits);
+ int _sqr(Uint32List xDigits, int xUsed, Uint32List resultDigits);
// Return x reverted to _BigIntImpl.
- _BigIntImpl revert(Uint32List xDigits, int xUsed);
+ _BigIntImpl _revert(Uint32List xDigits, int xUsed);
+}
+
+// Montgomery reduction on _BigIntImpl.
+class _BigIntMontgomeryReduction implements _BigIntReduction {
+ final _BigIntImpl _modulus;
+ int _normModulusUsed; // Even if processing 64-bit (digit pairs).
+ Uint32List _modulusDigits;
+ Uint32List _args;
+ int _digitsPerStep; // Number of digits processed in one step. 1 or 2.
+ static const int _xDigit = 0; // Index of digit of x.
+ static const int _xHighDigit = 1; // Index of high digit of x (64-bit only).
+ static const int _rhoDigit = 2; // Index of digit of rho.
+ static const int _rhoHighDigit = 3; // Index of high digit of rho (64-bit).
+ static const int _muDigit = 4; // Index of mu.
+ static const int _muHighDigit = 5; // Index of high 32-bits of mu (64-bit).
+
+ _BigIntMontgomeryReduction(this._modulus) {
+ _modulusDigits = _modulus._digits;
+ _args = _newDigits(6);
+ // Determine if we can process digit pairs by calling an intrinsic.
+ _digitsPerStep = _mulMod(_args, _args, 0);
+ _args[_xDigit] = _modulusDigits[0];
+ if (_digitsPerStep == 1) {
+ _normModulusUsed = _modulus._used;
+ _invDigit(_args);
+ } else {
+ assert(_digitsPerStep == 2);
+ _normModulusUsed = _modulus._used + (_modulus._used & 1);
+ _args[_xHighDigit] = _modulusDigits[1];
+ _invDigitPair(_args);
+ }
+ }
+
+ // Calculates -1/x % _digitBase, x is 32-bit digit.
+ // xy == 1 (mod m)
+ // xy = 1+km
+ // xy(2-xy) = (1+km)(1-km)
+ // x(y(2-xy)) = 1-k^2 m^2
+ // x(y(2-xy)) == 1 (mod m^2)
+ // if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
+ // Should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
+ //
+ // Operation:
+ // args[_rhoDigit] = 1/args[_xDigit] mod _digitBase.
+ static void _invDigit(Uint32List args) {
+ var x = args[_xDigit];
+ var y = x & 3; // y == 1/x mod 2^2
+ y = (y * (2 - (x & 0xf) * y)) & 0xf; // y == 1/x mod 2^4
+ y = (y * (2 - (x & 0xff) * y)) & 0xff; // y == 1/x mod 2^8
+ y = (y * (2 - (((x & 0xffff) * y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16
+ y = (y * (2 - x * y % _BigIntImpl._digitBase)) % _BigIntImpl._digitBase;
+ // y == 1/x mod _digitBase
+ y = -y; // We really want the negative inverse.
+ args[_rhoDigit] = y & _BigIntImpl._digitMask;
+ assert(((x * y) & _BigIntImpl._digitMask) == _BigIntImpl._digitMask);
+ }
+
+ // Calculates -1/x % _digitBase^2, x is a pair of 32-bit digits.
+ // Operation:
+ // args[_rhoDigit.._rhoHighDigit] =
+ // 1/args[_xDigit.._xHighDigit] mod _digitBase^2.
+ static void _invDigitPair(Uint32List args) {
+ var two = _BigIntImpl.two;
+ var mask32 = _BigIntImpl._oneDigitMask;
+ var mask64 = _BigIntImpl._twoDigitMask;
+ var xl = args[_xDigit]; // Lower 32-bit digit of x.
+ var y = xl & 3; // y == 1/x mod 2^2
+ y = (y * (2 - (xl & 0xf) * y)) & 0xf; // y == 1/x mod 2^4
+ y = (y * (2 - (xl & 0xff) * y)) & 0xff; // y == 1/x mod 2^8
+ y = (y * (2 - (((xl & 0xffff) * y) & 0xffff))) & 0xffff;
+ // y == 1/x mod 2^16
+ y = (y * (2 - ((xl * y) & 0xffffffff))) & 0xffffffff; // y == 1/x mod 2^32
+ var x = (args[_xHighDigit] << _BigIntImpl._digitBits) | xl;
+ y *= 2 - x * y; // Masking with 2^64-1 is implied by 64-bit arithmetic.
+ // y == 1/x mod _digitBase^2
+ y = -y; // We really want the negative inverse.
+ args[_rhoDigit] = y & _BigIntImpl._digitMask;
+ args[_rhoHighDigit] =
+ (y >> _BigIntImpl._digitBits) & _BigIntImpl._digitMask;
+ assert(x * y == -1);
+ }
+
+ // Operation:
+ // args[_muDigit] = args[_rhoDigit]*digits[i] mod _digitBase.
+ // Returns 1.
+ // Note: Intrinsics on 64-bit platforms process digit pairs at even indices:
+ // args[_muDigit.._muHighDigit] =
+ // args[_rhoDigit.._rhoHighDigit] * digits[i..i+1] mod _digitBase^2.
+ // Returns 2.
+ static int _mulMod(Uint32List args, Uint32List digits, int i) {
+ var rhol = args[_rhoDigit] & _BigIntImpl._halfDigitMask;
+ var rhoh = args[_rhoDigit] >> _BigIntImpl._halfDigitBits;
+ var dh = digits[i] >> _BigIntImpl._halfDigitBits;
+ var dl = digits[i] & _BigIntImpl._halfDigitMask;
+ args[_muDigit] = (dl * rhol +
+ (((dl * rhoh + dh * rhol) & _BigIntImpl._halfDigitMask) <<
+ _BigIntImpl._halfDigitBits)) &
+ _BigIntImpl._digitMask;
+ return 1;
+ }
+
+ // result = x*R mod _modulus.
+ // Returns resultUsed.
+ int _convert(_BigIntImpl x, Uint32List resultDigits) {
+ // Montgomery reduction only works if abs(x) < _modulus.
+ assert(x.abs() < _modulus);
+ assert(_digitsPerStep == 1 || _normModulusUsed.isEven);
+ var result = x.abs()._dlShift(_normModulusUsed)._rem(_modulus);
+ if (x._isNegative && !result._isNegative && result._used > 0) {
+ result = _modulus - result;
+ }
+ var used = result._used;
+ var digits = result._digits;
+ var i = used + (used & 1);
+ while (--i >= 0) {
+ resultDigits[i] = digits[i];
+ }
+ return used;
+ }
+
+ _BigIntImpl _revert(Uint32List xDigits, int xUsed) {
+ var resultDigits = _newDigits(2 * _normModulusUsed);
+ var i = xUsed + (xUsed & 1);
+ while (--i >= 0) {
+ resultDigits[i] = xDigits[i];
+ }
+ var resultUsed = _reduce(resultDigits, xUsed);
+ return new _BigIntImpl._(false, resultUsed, resultDigits);
+ }
+
+ // x = x/R mod _modulus.
+ // Returns xUsed.
+ int _reduce(Uint32List xDigits, int xUsed) {
+ while (xUsed < 2 * _normModulusUsed) {
+ // Pad x so _mulAdd has enough room later.
+ xDigits[xUsed++] = 0;
+ }
+ var i = 0;
+ while (i < _normModulusUsed) {
+ var d = _mulMod(_args, xDigits, i);
+ assert(d == _digitsPerStep);
+ d = _BigIntImpl._mulAdd(
+ _args, _muDigit, _modulusDigits, 0, xDigits, i, _normModulusUsed);
+ assert(d == _digitsPerStep);
+ i += d;
+ }
+ // Clamp x.
+ while (xUsed > 0 && xDigits[xUsed - 1] == 0) {
+ --xUsed;
+ }
+ xUsed = _BigIntImpl._drShiftDigits(xDigits, xUsed, i, xDigits);
+ if (_BigIntImpl._compareDigits(
+ xDigits, xUsed, _modulusDigits, _normModulusUsed) >=
+ 0) {
+ _BigIntImpl._absSub(
+ xDigits, xUsed, _modulusDigits, _normModulusUsed, xDigits);
+ }
+ // Clamp x.
+ while (xUsed > 0 && xDigits[xUsed - 1] == 0) {
+ --xUsed;
+ }
+ return xUsed;
+ }
+
+ int _sqr(Uint32List xDigits, int xUsed, Uint32List resultDigits) {
+ var resultUsed = _BigIntImpl._sqrDigits(xDigits, xUsed, resultDigits);
+ return _reduce(resultDigits, resultUsed);
+ }
+
+ int _mul(Uint32List xDigits, int xUsed, Uint32List yDigits, int yUsed,
+ Uint32List resultDigits) {
+ var resultUsed =
+ _BigIntImpl._mulDigits(xDigits, xUsed, yDigits, yUsed, resultDigits);
+ return _reduce(resultDigits, resultUsed);
+ }
}
// Modular reduction using "classic" algorithm.
-class _BigIntClassic implements _BigIntReduction {
+class _BigIntClassicReduction implements _BigIntReduction {
final _BigIntImpl _modulus; // Modulus.
- final _BigIntImpl _normalizedModulus; // Normalized _modulus.
+ int _normModulusUsed;
+ _BigIntImpl _normModulus; // Normalized _modulus.
+ Uint32List _normModulusDigits;
+ Uint32List _negNormModulusDigits; // Negated _normModulus digits.
+ int _modulusNsh; // Normalization shift amount.
+ Uint32List _args; // Top _normModulus digit(s) and place holder for estimated
+ // quotient digit(s).
+ Uint32List _tmpDigits; // Temporary digits used during reduction.
- _BigIntClassic(this._modulus)
- : _normalizedModulus = _modulus <<
- (_BigIntImpl._digitBits -
- _modulus._digits[_modulus._used - 1].bitLength);
+ _BigIntClassicReduction(this._modulus) {
+ // Preprocess arguments to _remDigits.
+ var nsh =
+ _BigIntImpl._digitBits - _modulus._digits[_modulus._used - 1].bitLength;
+ // For 64-bit processing, make sure _negNormModulusDigits has an even number
+ // of digits.
+ if (_modulus._used.isOdd) {
+ nsh += _BigIntImpl._digitBits;
+ }
+ _modulusNsh = nsh;
+ _normModulus = _modulus << nsh;
+ _normModulusUsed = _normModulus._used;
+ _normModulusDigits = _normModulus._digits;
+ assert(_normModulusUsed.isEven);
+ _args = _newDigits(4);
+ _args[_BigIntImpl._divisorLowTopDigit] =
+ _normModulusDigits[_normModulusUsed - 2];
+ _args[_BigIntImpl._divisorTopDigit] =
+ _normModulusDigits[_normModulusUsed - 1];
+ // Negate _normModulus so we can use _mulAdd instead of
+ // unimplemented _mulSub.
+ var negNormModulus =
+ _BigIntImpl.one._dlShift(_normModulusUsed) - _normModulus;
+ if (negNormModulus._used < _normModulusUsed) {
+ _negNormModulusDigits = _BigIntImpl._cloneDigits(
+ negNormModulus._digits, 0, _normModulusUsed, _normModulusUsed);
+ } else {
+ _negNormModulusDigits = negNormModulus._digits;
+ }
+ // _negNormModulusDigits is read-only and has _normModulusUsed digits (possibly
+ // including several leading zeros) plus a leading zero for 64-bit
+ // processing.
+ _tmpDigits = _newDigits(2 * _normModulusUsed);
+ }
- int convert(_BigIntImpl x, Uint32List resultDigits) {
+ int _convert(_BigIntImpl x, Uint32List resultDigits) {
var digits;
var used;
if (x._isNegative || x.compareTo(_modulus) >= 0) {
@@ -2081,14 +2728,14 @@
used = x._used;
digits = x._digits;
}
- var i = used; // Copy leading zero if any.
+ var i = used + (used & 1); // Copy leading zero if any.
while (--i >= 0) {
resultDigits[i] = digits[i];
}
return used;
}
- _BigIntImpl revert(Uint32List xDigits, int xUsed) {
+ _BigIntImpl _revert(Uint32List xDigits, int xUsed) {
return new _BigIntImpl._(false, xUsed, xDigits);
}
@@ -2096,24 +2743,27 @@
if (xUsed < _modulus._used) {
return xUsed;
}
- var reverted = revert(xDigits, xUsed);
- var rem = reverted._rem(_normalizedModulus);
- return convert(rem, xDigits);
+ // The function _BigIntImpl._remDigits(...) is optimized for reduction and
+ // equivalent to calling
+ // 'convert(revert(xDigits, xUsed)._rem(_normModulus), xDigits);'
+ return _BigIntImpl._remDigits(
+ xDigits,
+ xUsed,
+ _normModulusDigits,
+ _normModulusUsed,
+ _negNormModulusDigits,
+ _modulusNsh,
+ _args,
+ _tmpDigits,
+ xDigits);
}
- int sqr(Uint32List xDigits, int xUsed, Uint32List resultDigits) {
- var b = new _BigIntImpl._(false, xUsed, xDigits);
- var b2 = b * b;
- for (int i = 0; i < b2._used; i++) {
- resultDigits[i] = b2._digits[i];
- }
- for (int i = b2._used; i < 2 * xUsed; i++) {
- resultDigits[i] = 0;
- }
- return _reduce(resultDigits, 2 * xUsed);
+ int _sqr(Uint32List xDigits, int xUsed, Uint32List resultDigits) {
+ var resultUsed = _BigIntImpl._sqrDigits(xDigits, xUsed, resultDigits);
+ return _reduce(resultDigits, resultUsed);
}
- int mul(Uint32List xDigits, int xUsed, Uint32List yDigits, int yUsed,
+ int _mul(Uint32List xDigits, int xUsed, Uint32List yDigits, int yUsed,
Uint32List resultDigits) {
var resultUsed =
_BigIntImpl._mulDigits(xDigits, xUsed, yDigits, yUsed, resultDigits);
diff --git a/runtime/lib/compact_hash.dart b/runtime/lib/compact_hash.dart
index 742457a..7961370 100644
--- a/runtime/lib/compact_hash.dart
+++ b/runtime/lib/compact_hash.dart
@@ -115,6 +115,8 @@
int get _checkSum => _usedData + _deletedKeys;
bool _isModifiedSince(List oldData, int oldCheckSum) =>
!identical(_data, oldData) || (_checkSum != oldCheckSum);
+
+ int get length;
}
class _OperatorEqualsAndHashCode {
@@ -144,7 +146,7 @@
}
}
-abstract class _LinkedHashMapMixin<K, V> implements _HashVMBase {
+abstract class _LinkedHashMapMixin<K, V> implements _HashBase {
int _hashCode(e);
bool _equals(e1, e2);
int get _checkSum;
@@ -401,7 +403,7 @@
// Iterates through _data[_offset + _step], _data[_offset + 2*_step], ...
// and checks for concurrent modification.
class _CompactIterable<E> extends Iterable<E> {
- final _table;
+ final _HashBase _table;
final List _data;
final int _len;
final int _offset;
@@ -419,7 +421,7 @@
}
class _CompactIterator<E> implements Iterator<E> {
- final _table;
+ final _HashBase _table;
final List _data;
final int _len;
int _offset;
diff --git a/runtime/lib/immutable_map.dart b/runtime/lib/immutable_map.dart
index 726a376..0417d71 100644
--- a/runtime/lib/immutable_map.dart
+++ b/runtime/lib/immutable_map.dart
@@ -5,12 +5,21 @@
// part of "core_patch.dart";
/// Immutable map class for compiler generated map literals.
+// TODO(lrn): Extend MapBase with UnmodifiableMapMixin when mixins
+// support forwarding const constructors.
class _ImmutableMap<K, V> implements Map<K, V> {
final _ImmutableList _kvPairs;
const _ImmutableMap._create(_ImmutableList keyValuePairs)
: _kvPairs = keyValuePairs;
+ Map<K2, V2> cast<K2, V2>() {
+ Map<Object, Object> self = this;
+ return (self is Map<K2, V2>) ? self : this.retype<K2, V2>();
+ }
+
+ Map<K2, V2> retype<K2, V2>() => Map.castFrom<K, V, K2, V2>(this);
+
V operator [](Object key) {
// To preserve the key-value order of the map literal, the keys are
// not sorted. Need to do linear search or implement an additional
@@ -69,6 +78,10 @@
throw new UnsupportedError("Cannot set value in unmodifiable Map");
}
+ void addAll(Map<K, V> other) {
+ throw new UnsupportedError("Cannot set value in unmodifiable Map");
+ }
+
V putIfAbsent(K key, V ifAbsent()) {
throw new UnsupportedError("Cannot set value in unmodifiable Map");
}
diff --git a/runtime/lib/typed_data_patch.dart b/runtime/lib/typed_data_patch.dart
index 5e2312c..4d6161c 100644
--- a/runtime/lib/typed_data_patch.dart
+++ b/runtime/lib/typed_data_patch.dart
@@ -12,6 +12,7 @@
ClassID,
CodeUnits,
ExpandIterable,
+ FollowedByIterable,
IterableElementError,
ListMapView,
Lists,
@@ -23,6 +24,7 @@
SubListIterable,
TakeWhileIterable,
WhereIterable,
+ WhereTypeIterable,
patch;
import "dart:collection" show ListBase;
@@ -112,6 +114,11 @@
List<int> _createList(int length);
+ Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
+
+ Iterable<int> followedBy(Iterable<int> other) =>
+ new FollowedByIterable<int>.firstEfficient(this, other);
+
List<R> cast<R>() {
List<Object> self = this;
return self is List<R> ? self : List.castFrom<int, R>(this);
@@ -466,6 +473,11 @@
List<double> _createList(int length);
+ Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
+
+ Iterable<double> followedBy(Iterable<double> other) =>
+ new FollowedByIterable<double>.firstEfficient(this, other);
+
List<R> cast<R>() {
List<Object> self = this;
return self is List<R> ? self : List.castFrom<double, R>(this);
@@ -823,6 +835,11 @@
List<Float32x4> _createList(int length);
+ Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
+
+ Iterable<Float32x4> followedBy(Iterable<Float32x4> other) =>
+ new FollowedByIterable<Float32x4>.firstEfficient(this, other);
+
List<R> cast<R>() {
List<Object> self = this;
return self is List<R> ? self : List.castFrom<Float32x4, R>(this);
@@ -1184,6 +1201,11 @@
List<Int32x4> _createList(int length);
+ Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
+
+ Iterable<Int32x4> followedBy(Iterable<Int32x4> other) =>
+ new FollowedByIterable<Int32x4>.firstEfficient(this, other);
+
List<R> cast<R>() {
List<Object> self = this;
return self is List<R> ? self : List.castFrom<Int32x4, R>(this);
@@ -1544,6 +1566,11 @@
List<Float64x2> _createList(int length);
+ Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
+
+ Iterable<Float64x2> followedBy(Iterable<Float64x2> other) =>
+ new FollowedByIterable<Float64x2>.firstEfficient(this, other);
+
List<R> cast<R>() {
List<Object> self = this;
return self is List<R> ? self : List.castFrom<Float64x2, R>(this);
diff --git a/runtime/observatory/tests/service/external_service_asynchronous_invocation_test.dart b/runtime/observatory/tests/service/external_service_asynchronous_invocation_test.dart
index 3bb764c..a6860b9 100644
--- a/runtime/observatory/tests/service/external_service_asynchronous_invocation_test.dart
+++ b/runtime/observatory/tests/service/external_service_asynchronous_invocation_test.dart
@@ -8,7 +8,7 @@
import 'test_helper.dart';
import 'dart:io' show WebSocket;
import 'dart:convert' show JSON;
-import 'dart:async' show Future, StreamController;
+import 'dart:async' show Future, Stream, StreamController;
var tests = <IsolateTest>[
(Isolate isolate) async {
@@ -23,8 +23,13 @@
final socket = new StreamController();
// Avoid to manually encode and decode messages from the stream
- socket.stream.map(JSON.encode).pipe(_socket);
- final client = _socket.map(JSON.decode).asBroadcastStream();
+ Stream<String> stream = socket.stream.map(JSON.encode);
+ stream.retype<Object>().pipe(_socket);
+ dynamic _decoder(dynamic obj) {
+ return JSON.decode(obj);
+ }
+
+ final client = _socket.map(_decoder).asBroadcastStream();
const successServiceName = 'successService';
const errorServiceName = 'errorService';
@@ -145,7 +150,7 @@
expect(false, isTrue, reason: 'shouldn\'t get here');
}).catchError((e) => e);
}));
- errors.forEach((final ServerRpcException error) {
+ errors.forEach((dynamic error) {
final iteration = errors.indexOf(error);
final end = iteration.toString();
diff --git a/runtime/observatory/tests/service/external_service_disappear_test.dart b/runtime/observatory/tests/service/external_service_disappear_test.dart
index c30ea64..8199de2 100644
--- a/runtime/observatory/tests/service/external_service_disappear_test.dart
+++ b/runtime/observatory/tests/service/external_service_disappear_test.dart
@@ -8,7 +8,7 @@
import 'test_helper.dart';
import 'dart:io' show WebSocket;
import 'dart:convert' show JSON;
-import 'dart:async' show Future, StreamController;
+import 'dart:async' show Future, Stream, StreamController;
var tests = <IsolateTest>[
(Isolate isolate) async {
@@ -23,8 +23,13 @@
final socket = new StreamController();
// Avoid to manually encode and decode messages from the stream
- socket.stream.map(JSON.encode).pipe(_socket);
- final client = _socket.map(JSON.decode).asBroadcastStream();
+ Stream<String> stream = socket.stream.map(JSON.encode);
+ stream.retype<Object>().pipe(_socket);
+ dynamic _decoder(dynamic obj) {
+ return JSON.decode(obj);
+ }
+
+ final client = _socket.map(_decoder).asBroadcastStream();
// Note: keep this in sync with sdk/lib/vmservice.dart
const kServiceDisappeared = 111;
@@ -74,7 +79,8 @@
await Future.wait(results.map((future) {
return future.then((_) {
expect(false, isTrue, reason: 'shouldn\'t get here');
- }).catchError((ServerRpcException error) {
+ }).catchError((Object error_object) {
+ ServerRpcException error = error_object as ServerRpcException;
expect(error, isNotNull);
expect(error.code, equals(kServiceDisappeared));
expect(error.message, equals(kServiceDisappeared_Msg));
diff --git a/runtime/observatory/tests/service/external_service_notification_invocation_test.dart b/runtime/observatory/tests/service/external_service_notification_invocation_test.dart
index 3eec32a..bba191a 100644
--- a/runtime/observatory/tests/service/external_service_notification_invocation_test.dart
+++ b/runtime/observatory/tests/service/external_service_notification_invocation_test.dart
@@ -8,7 +8,7 @@
import 'test_helper.dart';
import 'dart:io' show WebSocket;
import 'dart:convert' show JSON;
-import 'dart:async' show Future, StreamController;
+import 'dart:async' show Future, Stream, StreamController;
var tests = <IsolateTest>[
(Isolate isolate) async {
@@ -26,10 +26,17 @@
final socket_invoker = new StreamController<Map>();
// Avoid to manually encode and decode messages from the stream
- socket.stream.map(JSON.encode).pipe(_socket);
- socket_invoker.stream.map(JSON.encode).pipe(_socket_invoker);
- final client = _socket.map(JSON.decode).asBroadcastStream();
- final client_invoker = _socket_invoker.map(JSON.decode).asBroadcastStream();
+ Stream<String> socket_stream = socket.stream.map(JSON.encode);
+ socket_stream.retype<Object>().pipe(_socket);
+ Stream<String> socket_invoker_stream =
+ socket_invoker.stream.map(JSON.encode);
+ socket_invoker_stream.retype<Object>().pipe(_socket_invoker);
+ dynamic _decoder(dynamic obj) {
+ return JSON.decode(obj);
+ }
+
+ final client = _socket.map(_decoder).asBroadcastStream();
+ final client_invoker = _socket_invoker.map(_decoder).asBroadcastStream();
const serviceName = 'successService';
const serviceAlias = 'serviceAlias';
diff --git a/runtime/observatory/tests/service/external_service_registration_test.dart b/runtime/observatory/tests/service/external_service_registration_test.dart
index b66563b..c0dab2f 100644
--- a/runtime/observatory/tests/service/external_service_registration_test.dart
+++ b/runtime/observatory/tests/service/external_service_registration_test.dart
@@ -8,7 +8,7 @@
import 'test_helper.dart';
import 'dart:io' show WebSocket;
import 'dart:convert' show JSON;
-import 'dart:async' show Future, StreamController;
+import 'dart:async' show Future, Stream, StreamController;
var tests = <IsolateTest>[
(Isolate isolate) async {
@@ -26,8 +26,13 @@
final socket = new StreamController();
// Avoid to manually encode and decode messages from the stream
- socket.stream.map(JSON.encode).pipe(_socket);
- final client = _socket.map(JSON.decode).asBroadcastStream();
+ Stream<String> socket_stream = socket.stream.map(JSON.encode);
+ socket_stream.retype<Object>().pipe(_socket);
+ dynamic _decoder(dynamic obj) {
+ return JSON.decode(obj);
+ }
+
+ final client = _socket.map(_decoder).asBroadcastStream();
// Note: keep this in sync with sdk/lib/vmservice.dart
const kServiceAlreadyRegistered = 110;
diff --git a/runtime/observatory/tests/service/external_service_registration_via_notification_test.dart b/runtime/observatory/tests/service/external_service_registration_via_notification_test.dart
index 37027f8..74e258c 100644
--- a/runtime/observatory/tests/service/external_service_registration_via_notification_test.dart
+++ b/runtime/observatory/tests/service/external_service_registration_via_notification_test.dart
@@ -8,7 +8,7 @@
import 'test_helper.dart';
import 'dart:io' show WebSocket;
import 'dart:convert' show JSON;
-import 'dart:async' show Future, StreamController;
+import 'dart:async' show Future, Stream, StreamController;
var tests = <IsolateTest>[
(Isolate isolate) async {
@@ -26,8 +26,13 @@
final socket = new StreamController();
// Avoid to manually encode and decode messages from the stream
- socket.stream.map(JSON.encode).pipe(_socket);
- final client = _socket.map(JSON.decode).asBroadcastStream();
+ Stream<String> stream = socket.stream.map(JSON.encode);
+ stream.retype<Object>().pipe(_socket);
+ dynamic _decoder(dynamic obj) {
+ return JSON.decode(obj);
+ }
+
+ final client = _socket.map(_decoder).asBroadcastStream();
// Note: keep this in sync with sdk/lib/vmservice.dart
const kServiceAlreadyRegistered = 110;
diff --git a/runtime/observatory/tests/service/external_service_synchronous_invocation_test.dart b/runtime/observatory/tests/service/external_service_synchronous_invocation_test.dart
index 372ce1a..78091e1 100644
--- a/runtime/observatory/tests/service/external_service_synchronous_invocation_test.dart
+++ b/runtime/observatory/tests/service/external_service_synchronous_invocation_test.dart
@@ -8,7 +8,7 @@
import 'test_helper.dart';
import 'dart:io' show WebSocket;
import 'dart:convert' show JSON;
-import 'dart:async' show Future, StreamController;
+import 'dart:async' show Future, Stream, StreamController;
var tests = <IsolateTest>[
(Isolate isolate) async {
@@ -23,8 +23,13 @@
final socket = new StreamController();
// Avoid to manually encode and decode messages from the stream
- socket.stream.map(JSON.encode).pipe(_socket);
- final client = _socket.map(JSON.decode).asBroadcastStream();
+ Stream<String> stream = socket.stream.map(JSON.encode);
+ stream.retype<Object>().pipe(_socket);
+ dynamic _decoder(dynamic obj) {
+ return JSON.decode(obj);
+ }
+
+ final client = _socket.map(_decoder).asBroadcastStream();
const successServiceName = 'successService';
const errorServiceName = 'errorService';
diff --git a/runtime/observatory/tests/service/service_kernel.status b/runtime/observatory/tests/service/service_kernel.status
index a3d1244..baff3ed 100644
--- a/runtime/observatory/tests/service/service_kernel.status
+++ b/runtime/observatory/tests/service/service_kernel.status
@@ -44,9 +44,6 @@
isolate_lifecycle_test: Skip # Flaky.
pause_idle_isolate_test: Skip # Flaky
-[ $compiler == dartk && $mode == debug && $strong ]
-external_service_disappear_test: Crash # Issue 31587
-
[ $compiler == dartk && $system == windows ]
break_on_default_constructor_test: Skip # Issues 32137 and 32138.
coverage_leaf_function_test: RuntimeError
@@ -108,12 +105,6 @@
[ $compiler == dartk && $strong ]
awaiter_async_stack_contents_test: RuntimeError
-external_service_asynchronous_invocation_test: CompileTimeError # Issue 31696
-external_service_disappear_test: CompileTimeError # Issue 31696
-external_service_notification_invocation_test: CompileTimeError # Issue 31696
-external_service_registration_test: CompileTimeError # Issue 31696
-external_service_registration_via_notification_test: CompileTimeError # Issue 31696
-external_service_synchronous_invocation_test: CompileTimeError # Issue 31696
step_through_arithmetic_test: RuntimeError
[ $compiler == dartk && $strong && ($arch == simarm || $arch == simarm64) ]
diff --git a/runtime/platform/globals.h b/runtime/platform/globals.h
index b87e9e3..09c0a81 100644
--- a/runtime/platform/globals.h
+++ b/runtime/platform/globals.h
@@ -146,6 +146,10 @@
#define NOT_IN_PRECOMPILED(code) code
#endif // defined(DART_PRECOMPILED_RUNTIME)
+#if defined(DART_PRECOMPILED_RUNTIME) || defined(PRODUCT)
+#define EXCLUDE_CFE_AND_KERNEL_PLATFORM 1
+#endif // defined(DART_PRECOMPILED_RUNTIME)
+
namespace dart {
struct simd128_value_t {
diff --git a/runtime/platform/platform_sources.gni b/runtime/platform/platform_sources.gni
index e007ac3..f61930c 100644
--- a/runtime/platform/platform_sources.gni
+++ b/runtime/platform/platform_sources.gni
@@ -25,4 +25,9 @@
"text_buffer.h",
"utils.cc",
"utils.h",
+ "utils_android.cc",
+ "utils_fuchsia.cc",
+ "utils_linux.cc",
+ "utils_macos.cc",
+ "utils_win.cc",
]
diff --git a/runtime/platform/text_buffer.cc b/runtime/platform/text_buffer.cc
index b4700ac..5717604 100644
--- a/runtime/platform/text_buffer.cc
+++ b/runtime/platform/text_buffer.cc
@@ -7,7 +7,6 @@
#include "platform/assert.h"
#include "platform/globals.h"
#include "platform/utils.h"
-#include "vm/os.h"
#include "vm/unicode.h"
namespace dart {
@@ -59,7 +58,7 @@
va_start(args, format);
intptr_t remaining = buf_size_ - msg_len_;
ASSERT(remaining >= 0);
- intptr_t len = OS::VSNPrint(buf_ + msg_len_, remaining, format, args);
+ intptr_t len = Utils::VSNPrint(buf_ + msg_len_, remaining, format, args);
va_end(args);
if (len >= remaining) {
EnsureCapacity(len);
@@ -67,7 +66,7 @@
ASSERT(remaining > len);
va_list args2;
va_start(args2, format);
- intptr_t len2 = OS::VSNPrint(buf_ + msg_len_, remaining, format, args2);
+ intptr_t len2 = Utils::VSNPrint(buf_ + msg_len_, remaining, format, args2);
va_end(args2);
ASSERT(len == len2);
}
@@ -163,7 +162,8 @@
void BufferFormatter::VPrint(const char* format, va_list args) {
intptr_t available = size_ - position_;
if (available <= 0) return;
- intptr_t written = OS::VSNPrint(buffer_ + position_, available, format, args);
+ intptr_t written =
+ Utils::VSNPrint(buffer_ + position_, available, format, args);
if (written >= 0) {
position_ += (available <= written) ? available : written;
}
diff --git a/runtime/platform/text_buffer.h b/runtime/platform/text_buffer.h
index 37376e8..23deeed 100644
--- a/runtime/platform/text_buffer.h
+++ b/runtime/platform/text_buffer.h
@@ -5,8 +5,8 @@
#ifndef RUNTIME_PLATFORM_TEXT_BUFFER_H_
#define RUNTIME_PLATFORM_TEXT_BUFFER_H_
-#include "vm/allocation.h"
-#include "vm/globals.h"
+#include "platform/allocation.h"
+#include "platform/globals.h"
namespace dart {
diff --git a/runtime/platform/utils.h b/runtime/platform/utils.h
index 69a615c..3b05c02 100644
--- a/runtime/platform/utils.h
+++ b/runtime/platform/utils.h
@@ -105,28 +105,29 @@
static uintptr_t RoundUpToPowerOfTwo(uintptr_t x);
static int CountOneBits32(uint32_t x) {
-#ifdef _MSC_VER
- return __popcnt(x);
-#elif __GNUC__
+ // Apparently there are x64 chips without popcount.
+#if __GNUC__ && !defined(HOST_ARCH_IA32) && !defined(HOST_ARCH_X64)
return __builtin_popcount(x);
#else
-#error CountOneBits32 not implemented for this compiler
+ // Implementation is from "Hacker's Delight" by Henry S. Warren, Jr.,
+ // figure 5-2, page 66, where the function is called pop.
+ x = x - ((x >> 1) & 0x55555555);
+ x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
+ x = (x + (x >> 4)) & 0x0F0F0F0F;
+ x = x + (x >> 8);
+ x = x + (x >> 16);
+ return static_cast<int>(x & 0x0000003F);
#endif
}
static int CountOneBits64(uint64_t x) {
-#ifdef _MSC_VER
-#ifdef ARCH_IS_64_BIT
- return __popcnt64(x);
+ // Apparently there are x64 chips without popcount.
+#if __GNUC__ && !defined(HOST_ARCH_IA32) && !defined(HOST_ARCH_X64)
+ return __builtin_popcountll(x);
#else
return CountOneBits32(static_cast<uint32_t>(x)) +
CountOneBits32(static_cast<uint32_t>(x >> 32));
#endif
-#elif __GNUC__
- return __builtin_popcountll(x);
-#else
-#error CountOneBits64 not implemented for this compiler
-#endif
}
static int CountOneBitsWord(uword x) {
@@ -320,6 +321,30 @@
}
static char* StrError(int err, char* buffer, size_t bufsize);
+
+ // Not all platforms support strndup.
+ static char* StrNDup(const char* s, intptr_t n);
+ static intptr_t StrNLen(const char* s, intptr_t n);
+
+ // Print formatted output info a buffer.
+ //
+ // Does not write more than size characters (including the trailing '\0').
+ //
+ // Returns the number of characters (excluding the trailing '\0')
+ // that would been written if the buffer had been big enough. If
+ // the return value is greater or equal than the given size then the
+ // output has been truncated. The return value is never negative.
+ //
+ // The buffer will always be terminated by a '\0', unless the buffer
+ // is of size 0. The buffer might be NULL if the size is 0.
+ //
+ // This specification conforms to C99 standard which is implemented
+ // by glibc 2.1+ with one exception: the C99 standard allows a
+ // negative return value. We will terminate the vm rather than let
+ // that occur.
+ static int SNPrint(char* str, size_t size, const char* format, ...)
+ PRINTF_ATTRIBUTE(3, 4);
+ static int VSNPrint(char* str, size_t size, const char* format, va_list args);
};
} // namespace dart
diff --git a/runtime/platform/utils_android.cc b/runtime/platform/utils_android.cc
new file mode 100644
index 0000000..21c2e02
--- /dev/null
+++ b/runtime/platform/utils_android.cc
@@ -0,0 +1,38 @@
+// Copyright (c) 2012, 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.
+
+#include "platform/globals.h"
+#if defined(HOST_OS_ANDROID)
+
+#include "platform/utils.h"
+
+namespace dart {
+
+char* Utils::StrNDup(const char* s, intptr_t n) {
+ return strndup(s, n);
+}
+
+intptr_t Utils::StrNLen(const char* s, intptr_t n) {
+ return strnlen(s, n);
+}
+
+int Utils::SNPrint(char* str, size_t size, const char* format, ...) {
+ va_list args;
+ va_start(args, format);
+ int retval = VSNPrint(str, size, format, args);
+ va_end(args);
+ return retval;
+}
+
+int Utils::VSNPrint(char* str, size_t size, const char* format, va_list args) {
+ int retval = vsnprintf(str, size, format, args);
+ if (retval < 0) {
+ FATAL1("Fatal error in Utils::VSNPrint with format '%s'", format);
+ }
+ return retval;
+}
+
+} // namespace dart
+
+#endif // defined(HOST_OS_ANDROID)
diff --git a/runtime/platform/utils_fuchsia.cc b/runtime/platform/utils_fuchsia.cc
new file mode 100644
index 0000000..04e813a
--- /dev/null
+++ b/runtime/platform/utils_fuchsia.cc
@@ -0,0 +1,38 @@
+// Copyright (c) 2016, 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.
+
+#include "platform/globals.h"
+#if defined(HOST_OS_FUCHSIA)
+
+#include "platform/utils.h"
+
+namespace dart {
+
+char* Utils::StrNDup(const char* s, intptr_t n) {
+ return strndup(s, n);
+}
+
+intptr_t Utils::StrNLen(const char* s, intptr_t n) {
+ return strnlen(s, n);
+}
+
+int Utils::SNPrint(char* str, size_t size, const char* format, ...) {
+ va_list args;
+ va_start(args, format);
+ int retval = VSNPrint(str, size, format, args);
+ va_end(args);
+ return retval;
+}
+
+int Utils::VSNPrint(char* str, size_t size, const char* format, va_list args) {
+ int retval = vsnprintf(str, size, format, args);
+ if (retval < 0) {
+ FATAL1("Fatal error in Utils::VSNPrint with format '%s'", format);
+ }
+ return retval;
+}
+
+} // namespace dart
+
+#endif // defined(HOST_OS_FUCHSIA)
diff --git a/runtime/platform/utils_linux.cc b/runtime/platform/utils_linux.cc
new file mode 100644
index 0000000..4c3d617
--- /dev/null
+++ b/runtime/platform/utils_linux.cc
@@ -0,0 +1,39 @@
+// Copyright (c) 2012, 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.
+
+#include "platform/globals.h"
+#if defined(HOST_OS_LINUX)
+
+#include "platform/utils.h"
+
+namespace dart {
+
+char* Utils::StrNDup(const char* s, intptr_t n) {
+ return strndup(s, n);
+}
+
+intptr_t Utils::StrNLen(const char* s, intptr_t n) {
+ return strnlen(s, n);
+}
+
+int Utils::SNPrint(char* str, size_t size, const char* format, ...) {
+ va_list args;
+ va_start(args, format);
+ int retval = VSNPrint(str, size, format, args);
+ va_end(args);
+ return retval;
+}
+
+int Utils::VSNPrint(char* str, size_t size, const char* format, va_list args) {
+ MSAN_UNPOISON(str, size);
+ int retval = vsnprintf(str, size, format, args);
+ if (retval < 0) {
+ FATAL1("Fatal error in Utils::VSNPrint with format '%s'", format);
+ }
+ return retval;
+}
+
+} // namespace dart
+
+#endif // defined(HOST_OS_LINUX)
diff --git a/runtime/platform/utils_macos.cc b/runtime/platform/utils_macos.cc
new file mode 100644
index 0000000..eaab319
--- /dev/null
+++ b/runtime/platform/utils_macos.cc
@@ -0,0 +1,69 @@
+// Copyright (c) 2012, 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.
+
+#include "platform/globals.h"
+#if defined(HOST_OS_MACOS)
+
+#include "platform/utils.h"
+
+namespace dart {
+
+char* Utils::StrNDup(const char* s, intptr_t n) {
+// strndup has only been added to Mac OS X in 10.7. We are supplying
+// our own copy here if needed.
+#if !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || \
+ __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ <= 1060
+ intptr_t len = strlen(s);
+ if ((n < 0) || (len < 0)) {
+ return NULL;
+ }
+ if (n < len) {
+ len = n;
+ }
+ char* result = reinterpret_cast<char*>(malloc(len + 1));
+ if (result == NULL) {
+ return NULL;
+ }
+ result[len] = '\0';
+ return reinterpret_cast<char*>(memmove(result, s, len));
+#else // !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || ...
+ return strndup(s, n);
+#endif // !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || ...
+}
+
+intptr_t Utils::StrNLen(const char* s, intptr_t n) {
+// strnlen has only been added to Mac OS X in 10.7. We are supplying
+// our own copy here if needed.
+#if !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || \
+ __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ <= 1060
+ intptr_t len = 0;
+ while ((len <= n) && (*s != '\0')) {
+ s++;
+ len++;
+ }
+ return len;
+#else // !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || ...
+ return strnlen(s, n);
+#endif // !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || ...
+}
+
+int Utils::SNPrint(char* str, size_t size, const char* format, ...) {
+ va_list args;
+ va_start(args, format);
+ int retval = VSNPrint(str, size, format, args);
+ va_end(args);
+ return retval;
+}
+
+int Utils::VSNPrint(char* str, size_t size, const char* format, va_list args) {
+ int retval = vsnprintf(str, size, format, args);
+ if (retval < 0) {
+ FATAL1("Fatal error in Utils::VSNPrint with format '%s'", format);
+ }
+ return retval;
+}
+
+} // namespace dart
+
+#endif // defined(HOST_OS_MACOS)
diff --git a/runtime/platform/utils_win.cc b/runtime/platform/utils_win.cc
new file mode 100644
index 0000000..84f277c
--- /dev/null
+++ b/runtime/platform/utils_win.cc
@@ -0,0 +1,76 @@
+// Copyright (c) 2012, 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.
+
+#include "platform/globals.h"
+#if defined(HOST_OS_WINDOWS)
+
+#include "platform/utils.h"
+
+namespace dart {
+
+char* Utils::StrNDup(const char* s, intptr_t n) {
+ intptr_t len = strlen(s);
+ if ((n < 0) || (len < 0)) {
+ return NULL;
+ }
+ if (n < len) {
+ len = n;
+ }
+ char* result = reinterpret_cast<char*>(malloc(len + 1));
+ if (result == NULL) {
+ return NULL;
+ }
+ result[len] = '\0';
+ return reinterpret_cast<char*>(memmove(result, s, len));
+}
+
+intptr_t Utils::StrNLen(const char* s, intptr_t n) {
+ return strnlen(s, n);
+}
+
+int Utils::SNPrint(char* str, size_t size, const char* format, ...) {
+ va_list args;
+ va_start(args, format);
+ int retval = VSNPrint(str, size, format, args);
+ va_end(args);
+ return retval;
+}
+
+int Utils::VSNPrint(char* str, size_t size, const char* format, va_list args) {
+ if (str == NULL || size == 0) {
+ int retval = _vscprintf(format, args);
+ if (retval < 0) {
+ FATAL1("Fatal error in Utils::VSNPrint with format '%s'", format);
+ }
+ return retval;
+ }
+ va_list args_copy;
+ va_copy(args_copy, args);
+ int written = _vsnprintf(str, size, format, args_copy);
+ va_end(args_copy);
+ if (written < 0) {
+ // _vsnprintf returns -1 if the number of characters to be written is
+ // larger than 'size', so we call _vscprintf which returns the number
+ // of characters that would have been written.
+ va_list args_retry;
+ va_copy(args_retry, args);
+ written = _vscprintf(format, args_retry);
+ if (written < 0) {
+ FATAL1("Fatal error in Utils::VSNPrint with format '%s'", format);
+ }
+ va_end(args_retry);
+ }
+ // Make sure to zero-terminate the string if the output was
+ // truncated or if there was an error.
+ // The static cast is safe here as we have already determined that 'written'
+ // is >= 0.
+ if (static_cast<size_t>(written) >= size) {
+ str[size - 1] = '\0';
+ }
+ return written;
+}
+
+} // namespace dart
+
+#endif // defined(HOST_OS_WINDOWS)
diff --git a/runtime/tests/vm/dart/hello_world_test.dart b/runtime/tests/vm/dart/hello_world_test.dart
new file mode 100644
index 0000000..8c9c377
--- /dev/null
+++ b/runtime/tests/vm/dart/hello_world_test.dart
@@ -0,0 +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.
+
+// Classic "Hello, world!". Used in the VM build (runtime/bin/BUILD.gn) as
+// a tiny script for precompilation.
+
+main() {
+ print("Hello, world!");
+}
diff --git a/runtime/tests/vm/dart/optimized_stacktrace_line_and_column_test.dart b/runtime/tests/vm/dart/optimized_stacktrace_line_and_column_test.dart
index 4bcb31e..83dd0f7 100644
--- a/runtime/tests/vm/dart/optimized_stacktrace_line_and_column_test.dart
+++ b/runtime/tests/vm/dart/optimized_stacktrace_line_and_column_test.dart
@@ -21,9 +21,9 @@
String s = stacktrace.toString();
print(s);
Expect.isFalse(s.contains("-1:-1"), "A");
- Expect.isTrue(
- s.contains("optimized_stacktrace_line_and_column_test.dart:11:18"),
- "B");
+ RegExp regex = new RegExp(
+ "optimized_stacktrace_line_and_column_test(_none|_01)*\.dart:11(:18)*");
+ Expect.isTrue(regex.hasMatch(s), s);
}
// Optimized.
@@ -35,9 +35,9 @@
String s = stacktrace.toString();
print(s);
Expect.isFalse(s.contains("-1:-1"), "C");
- Expect.isTrue(
- s.contains("optimized_stacktrace_line_and_column_test.dart:11:18"),
- "D");
+ RegExp regex = new RegExp(
+ "optimized_stacktrace_line_and_column_test(_none|_01)*\.dart:11(:18)*");
+ Expect.isTrue(regex.hasMatch(s), "D");
}
}
@@ -45,9 +45,9 @@
maximus(x) => moritz(x);
moritz(x) {
- if (x == 333) return 42 ? 0 : 1; // Throws in checked mode.
+ if (x == 333) return true ? 0 : 1;
if (x == 777) {
- bool b = x; // Throws in checked mode.
+ bool b = x;
return b;
}
diff --git a/runtime/tests/vm/dart/optimized_stacktrace_line_test.dart b/runtime/tests/vm/dart/optimized_stacktrace_line_test.dart
index abdbefa..43e5fde 100644
--- a/runtime/tests/vm/dart/optimized_stacktrace_line_test.dart
+++ b/runtime/tests/vm/dart/optimized_stacktrace_line_test.dart
@@ -21,7 +21,9 @@
String s = stacktrace.toString();
print(s);
Expect.isFalse(s.contains("-1:-1"), "A");
- Expect.isTrue(s.contains("optimized_stacktrace_line_test.dart:11"), "B");
+ RegExp regex =
+ new RegExp("optimized_stacktrace_line_test(_none|_01)*\.dart:11");
+ Expect.isTrue(regex.hasMatch(s), "B");
}
// Optimized.
@@ -33,7 +35,9 @@
String s = stacktrace.toString();
print(s);
Expect.isFalse(s.contains("-1:-1"), "C");
- Expect.isTrue(s.contains("optimized_stacktrace_line_test.dart:11"), "D");
+ RegExp regex =
+ new RegExp("optimized_stacktrace_line_test(_none|_01)*\.dart:11");
+ Expect.isTrue(regex.hasMatch(s), "D");
}
}
@@ -41,9 +45,9 @@
maximus(x) => moritz(x);
moritz(x) {
- if (x == 333) return 42 ? 0 : 1; // Throws in checked mode.
+ if (x == 333) return (42 as bool) ? 0 : 1;
if (x == 777) {
- bool b = x; // Throws in checked mode.
+ bool b = x;
return b;
}
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 6d78dea..8553eca 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -39,14 +39,11 @@
cc/IsolateReload_TypeIdentityParameter: Fail # Issue 28349
[ $compiler == app_jit ]
-dart/optimized_stacktrace_line_and_column_test: RuntimeError, OK # app-jit lacks column information
dart/snapshot_version_test: Fail, OK # Expects to find script snapshot relative to Dart source.
[ $compiler == dart2analyzer ]
dart/byte_array_optimized_test: CompileTimeError # int64
dart/byte_array_test: CompileTimeError # int64
-dart/optimized_stacktrace_line_and_column_test: StaticWarning
-dart/optimized_stacktrace_line_test: StaticWarning
dart/truncating_ints_test: CompileTimeError # int64
[ $compiler == dart2js ]
@@ -296,8 +293,6 @@
cc/IsolateReload_LibraryLookup: Crash # Issue 32190
cc/Mixin_PrivateSuperResolutionCrossLibraryShouldFail: Fail, Crash # Issue 32190
cc/StackMapGC: Crash # Issue 32190
-dart/optimized_stacktrace_line_and_column_test: CompileTimeError # Issue 31586
-dart/optimized_stacktrace_line_test: CompileTimeError # Issue 31586
# 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
@@ -306,12 +301,7 @@
dart/data_uri_spawn_test: Skip # Please triage.
dart/snapshot_version_test: RuntimeError # Please triage.
-[ $compiler == dartkp && $strong ]
-dart/optimized_stacktrace_line_and_column_test: CompileTimeError
-dart/optimized_stacktrace_line_test: CompileTimeError
-
[ $compiler == dartkp && !$strong ]
-dart/optimized_stacktrace_line_and_column_test: RuntimeError, OK # AOT lacks column information
dart/truncating_ints_test: Skip # This test cannot be run in dartkp/legacy mode (gen_kernel does not pass --limit-ints-to-64-bits in legacy mode).
[ $compiler == dartkp && ($runtime == dart_precompiled || $runtime == vm) ]
@@ -322,9 +312,6 @@
[ $compiler == none && $runtime == drt ]
dart/truncating_ints_test: Skip # Issue 14651
-[ $compiler == precompiler && $runtime == dart_precompiled ]
-dart/optimized_stacktrace_line_and_column_test: RuntimeError, OK # AOT lacks column information
-
[ $mode == debug && $system == windows ]
dart/spawn_shutdown_test: Skip # Flaky crashes unable to start thread; likely low memory on the bot.
diff --git a/runtime/vm/ast.cc b/runtime/vm/ast.cc
index 2d3c01b..e7e74bc 100644
--- a/runtime/vm/ast.cc
+++ b/runtime/vm/ast.cc
@@ -92,8 +92,8 @@
Zone* zone = thread->zone();
initializers_.Add(node);
char name[64];
- OS::SNPrint(name, sizeof(name), ":lt%s_%" Pd "", token_pos().ToCString(),
- vars_.length());
+ Utils::SNPrint(name, sizeof(name), ":lt%s_%" Pd "", token_pos().ToCString(),
+ vars_.length());
LocalVariable* temp_var =
new LocalVariable(TokenPosition::kNoSource, token_pos(),
String::ZoneHandle(zone, Symbols::New(thread, name)),
diff --git a/runtime/vm/benchmark_test.cc b/runtime/vm/benchmark_test.cc
index 84b433b..4fc6436 100644
--- a/runtime/vm/benchmark_test.cc
+++ b/runtime/vm/benchmark_test.cc
@@ -40,8 +40,9 @@
char* ptr = strrchr(dart2js_path, *path_separator);
while (ptr != NULL) {
*ptr = '\0';
- OS::SNPrint(buffer, 2048, compiler_path, dart2js_path, path_separator,
- path_separator, path_separator, path_separator, path_separator);
+ Utils::SNPrint(buffer, 2048, compiler_path, dart2js_path, path_separator,
+ path_separator, path_separator, path_separator,
+ path_separator);
if (File::Exists(NULL, buffer)) {
break;
}
@@ -77,8 +78,8 @@
strdup(File::GetCanonicalPath(NULL, Benchmark::Executable()));
const char* packages_path = "%s%s..%spackages";
const char* path_separator = File::PathSeparator();
- OS::SNPrint(buffer, 2048, packages_path, executable_path, path_separator,
- path_separator);
+ Utils::SNPrint(buffer, 2048, packages_path, executable_path, path_separator,
+ path_separator);
result = bin::DartUtils::SetupPackageRoot(buffer, NULL);
DART_CHECK_VALID(result);
}
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index fecad3a..ef85c3f 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -5278,9 +5278,9 @@
if (PendingBytes() < version_len) {
const intptr_t kMessageBufferSize = 128;
char message_buffer[kMessageBufferSize];
- OS::SNPrint(message_buffer, kMessageBufferSize,
- "No full snapshot version found, expected '%s'",
- expected_version);
+ Utils::SNPrint(message_buffer, kMessageBufferSize,
+ "No full snapshot version found, expected '%s'",
+ expected_version);
// This can also fail while bringing up the VM isolate, so make sure to
// allocate the error message in old space.
const String& msg = String::Handle(String::New(message_buffer, Heap::kOld));
@@ -5292,11 +5292,11 @@
if (strncmp(version, expected_version, version_len)) {
const intptr_t kMessageBufferSize = 256;
char message_buffer[kMessageBufferSize];
- char* actual_version = OS::StrNDup(version, version_len);
- OS::SNPrint(message_buffer, kMessageBufferSize,
- "Wrong %s snapshot version, expected '%s' found '%s'",
- (Snapshot::IsFull(kind_)) ? "full" : "script", expected_version,
- actual_version);
+ char* actual_version = Utils::StrNDup(version, version_len);
+ Utils::SNPrint(message_buffer, kMessageBufferSize,
+ "Wrong %s snapshot version, expected '%s' found '%s'",
+ (Snapshot::IsFull(kind_)) ? "full" : "script",
+ expected_version, actual_version);
free(actual_version);
// This can also fail while bringing up the VM isolate, so make sure to
// allocate the error message in old space.
@@ -5312,17 +5312,17 @@
const char* features = reinterpret_cast<const char*>(CurrentBufferAddress());
ASSERT(features != NULL);
- intptr_t buffer_len = OS::StrNLen(features, PendingBytes());
+ intptr_t buffer_len = Utils::StrNLen(features, PendingBytes());
if ((buffer_len != expected_len) ||
strncmp(features, expected_features, expected_len)) {
const intptr_t kMessageBufferSize = 1024;
char message_buffer[kMessageBufferSize];
char* actual_features =
- OS::StrNDup(features, buffer_len < 128 ? buffer_len : 128);
- OS::SNPrint(message_buffer, kMessageBufferSize,
- "Snapshot not compatible with the current VM configuration: "
- "the snapshot requires '%s' but the VM has '%s'",
- actual_features, expected_features);
+ Utils::StrNDup(features, buffer_len < 128 ? buffer_len : 128);
+ Utils::SNPrint(message_buffer, kMessageBufferSize,
+ "Snapshot not compatible with the current VM configuration: "
+ "the snapshot requires '%s' but the VM has '%s'",
+ actual_features, expected_features);
free(const_cast<char*>(expected_features));
free(actual_features);
// This can also fail while bringing up the VM isolate, so make sure to
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index bf90c32..6e912c6 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -1046,13 +1046,7 @@
} else if (entry.IsInstance()) {
// Const object, literal or args descriptor.
instance ^= entry.raw();
- if (entry.IsAbstractType()) {
- AddType(AbstractType::Cast(entry));
- } else if (entry.IsTypeArguments()) {
- AddTypeArguments(TypeArguments::Cast(entry));
- } else {
- AddConstObject(instance);
- }
+ AddConstObject(instance);
} else if (entry.IsFunction()) {
// Local closure function.
target ^= entry.raw();
@@ -1199,6 +1193,15 @@
}
void Precompiler::AddConstObject(const Instance& instance) {
+ // Types and type arguments require special handling.
+ if (instance.IsAbstractType()) {
+ AddType(AbstractType::Cast(instance));
+ return;
+ } else if (instance.IsTypeArguments()) {
+ AddTypeArguments(TypeArguments::Cast(instance));
+ return;
+ }
+
const Class& cls = Class::Handle(Z, instance.clazz());
AddInstantiatedClass(cls);
@@ -1241,9 +1244,7 @@
virtual void VisitPointers(RawObject** first, RawObject** last) {
for (RawObject** current = first; current <= last; current++) {
subinstance_ = *current;
- if (subinstance_.IsTypeArguments()) {
- precompiler_->AddTypeArguments(TypeArguments::Cast(subinstance_));
- } else if (subinstance_.IsInstance()) {
+ if (subinstance_.IsInstance()) {
precompiler_->AddConstObject(Instance::Cast(subinstance_));
}
}
diff --git a/runtime/vm/compiler/assembler/assembler.cc b/runtime/vm/compiler/assembler/assembler.cc
index c19a0d2..c2dc4e7 100644
--- a/runtime/vm/compiler/assembler/assembler.cc
+++ b/runtime/vm/compiler/assembler/assembler.cc
@@ -175,25 +175,25 @@
// Shared macros are implemented here.
void Assembler::Unimplemented(const char* message) {
const char* format = "Unimplemented: %s";
- const intptr_t len = OS::SNPrint(NULL, 0, format, message);
+ const intptr_t len = Utils::SNPrint(NULL, 0, format, message);
char* buffer = reinterpret_cast<char*>(malloc(len + 1));
- OS::SNPrint(buffer, len + 1, format, message);
+ Utils::SNPrint(buffer, len + 1, format, message);
Stop(buffer);
}
void Assembler::Untested(const char* message) {
const char* format = "Untested: %s";
- const intptr_t len = OS::SNPrint(NULL, 0, format, message);
+ const intptr_t len = Utils::SNPrint(NULL, 0, format, message);
char* buffer = reinterpret_cast<char*>(malloc(len + 1));
- OS::SNPrint(buffer, len + 1, format, message);
+ Utils::SNPrint(buffer, len + 1, format, message);
Stop(buffer);
}
void Assembler::Unreachable(const char* message) {
const char* format = "Unreachable: %s";
- const intptr_t len = OS::SNPrint(NULL, 0, format, message);
+ const intptr_t len = Utils::SNPrint(NULL, 0, format, message);
char* buffer = reinterpret_cast<char*>(malloc(len + 1));
- OS::SNPrint(buffer, len + 1, format, message);
+ Utils::SNPrint(buffer, len + 1, format, message);
Stop(buffer);
}
@@ -203,7 +203,7 @@
va_list args;
va_start(args, format);
- OS::VSNPrint(buffer, sizeof(buffer), format, args);
+ Utils::VSNPrint(buffer, sizeof(buffer), format, args);
va_end(args);
comments_.Add(
diff --git a/runtime/vm/compiler/assembler/disassembler.cc b/runtime/vm/compiler/assembler/disassembler.cc
index fb53b11..c1b4c4d 100644
--- a/runtime/vm/compiler/assembler/disassembler.cc
+++ b/runtime/vm/compiler/assembler/disassembler.cc
@@ -76,11 +76,11 @@
void DisassembleToJSONStream::Print(const char* format, ...) {
va_list args;
va_start(args, format);
- intptr_t len = OS::VSNPrint(NULL, 0, format, args);
+ intptr_t len = Utils::VSNPrint(NULL, 0, format, args);
va_end(args);
char* p = reinterpret_cast<char*>(malloc(len + 1));
va_start(args, format);
- intptr_t len2 = OS::VSNPrint(p, len, format, args);
+ intptr_t len2 = Utils::VSNPrint(p, len, format, args);
va_end(args);
ASSERT(len == len2);
for (intptr_t i = 0; i < len; i++) {
@@ -132,7 +132,7 @@
}
va_list args;
va_start(args, format);
- intptr_t len = OS::VSNPrint(NULL, 0, format, args);
+ intptr_t len = Utils::VSNPrint(NULL, 0, format, args);
va_end(args);
if (remaining_ < len + 100) {
*buffer_++ = '.';
@@ -144,7 +144,7 @@
return;
}
va_start(args, format);
- intptr_t len2 = OS::VSNPrint(buffer_, len, format, args);
+ intptr_t len2 = Utils::VSNPrint(buffer_, len, format, args);
va_end(args);
ASSERT(len == len2);
buffer_ += len;
diff --git a/runtime/vm/compiler/assembler/disassembler_arm.cc b/runtime/vm/compiler/assembler/disassembler_arm.cc
index 9c80fe9..5c718de 100644
--- a/runtime/vm/compiler/assembler/disassembler_arm.cc
+++ b/runtime/vm/compiler/assembler/disassembler_arm.cc
@@ -127,22 +127,22 @@
void ARMDecoder::PrintSRegister(int reg) {
ASSERT(0 <= reg);
ASSERT(reg < kNumberOfSRegisters);
- buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), "s%d", reg);
+ buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), "s%d", reg);
}
void ARMDecoder::PrintDRegister(int reg) {
ASSERT(0 <= reg);
ASSERT(reg < kNumberOfDRegisters);
- buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), "d%d", reg);
+ buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), "d%d", reg);
}
void ARMDecoder::PrintQRegister(int reg) {
ASSERT(0 <= reg);
ASSERT(reg < kNumberOfQRegisters);
- buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), "q%d", reg);
+ buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), "q%d", reg);
}
// These shift names are defined in a way to match the native disassembler
@@ -171,14 +171,14 @@
shift_amount = 32;
}
buffer_pos_ +=
- OS::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(),
- ", %s #%d", shift_names[shift], shift_amount);
+ Utils::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(),
+ ", %s #%d", shift_names[shift], shift_amount);
} else {
// by register
int rs = instr->RsField();
buffer_pos_ +=
- OS::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(),
- ", %s ", shift_names[shift]);
+ Utils::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(),
+ ", %s ", shift_names[shift]);
PrintRegister(rs);
}
}
@@ -189,8 +189,8 @@
int rotate = instr->RotateField() * 2;
int immed8 = instr->Immed8Field();
int imm = (immed8 >> rotate) | (immed8 << (32 - rotate));
- buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), "#%d", imm);
+ buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), "#%d", imm);
}
// Print PU formatting to reduce complexity of FormatOption.
@@ -406,8 +406,8 @@
int off = (instr->SImmed24Field() << 2) + 8;
uword destination = reinterpret_cast<uword>(instr) + off;
buffer_pos_ +=
- OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), "%#" Px "", destination);
+ Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), "%#" Px "", destination);
return 4;
} else {
return FormatDRegister(instr, format);
@@ -420,15 +420,15 @@
uint16_t immed16;
if (format[3] == 'f') {
ASSERT(STRING_STARTS_WITH(format, "immf"));
- buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), "%f",
- instr->ImmFloatField());
+ buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), "%f",
+ instr->ImmFloatField());
return 4;
} else if (format[3] == 'd') {
ASSERT(STRING_STARTS_WITH(format, "immd"));
- buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), "%g",
- instr->ImmDoubleField());
+ buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), "%g",
+ instr->ImmDoubleField());
return 4;
} else if (format[3] == '1') {
ASSERT(STRING_STARTS_WITH(format, "imm12_4"));
@@ -445,16 +445,17 @@
idx = imm4 >> 2;
else if ((imm4 & 4) != 0)
idx = imm4 >> 3;
- buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), "%d", idx);
+ buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), "%d", idx);
return 9;
} else {
ASSERT(STRING_STARTS_WITH(format, "imm4_12"));
immed16 = instr->MovwField();
}
}
- buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), "0x%x", immed16);
+ buffer_pos_ +=
+ Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), "0x%x", immed16);
return 7;
}
case 'l': { // 'l: branch and link
@@ -478,23 +479,23 @@
if (format[3] == '1') {
if (format[4] == '0') {
// 'off10: 10-bit offset for VFP load and store instructions
- buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), "%d",
- instr->Bits(0, 8) << 2);
+ buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), "%d",
+ instr->Bits(0, 8) << 2);
} else {
// 'off12: 12-bit offset for load and store instructions.
ASSERT(STRING_STARTS_WITH(format, "off12"));
- buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), "%d",
- instr->Offset12Field());
+ buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), "%d",
+ instr->Offset12Field());
}
return 5;
}
// 'off8: 8-bit offset for extra load and store instructions.
ASSERT(STRING_STARTS_WITH(format, "off8"));
int offs8 = (instr->ImmedHField() << 4) | instr->ImmedLField();
- buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), "%d", offs8);
+ buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), "%d", offs8);
return 4;
}
case 'p': { // 'pu: P and U bits for load and store instructions.
@@ -523,9 +524,9 @@
}
} else if (format[1] == 'v') { // 'svc
ASSERT(STRING_STARTS_WITH(format, "svc"));
- buffer_pos_ +=
- OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), "0x%x", instr->SvcField());
+ buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), "0x%x",
+ instr->SvcField());
return 3;
} else if (format[1] == 'z') {
// 'sz: Size field of SIMD instructions.
@@ -548,8 +549,8 @@
sz_str = "?";
break;
}
- buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), "%s", sz_str);
+ buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), "%s", sz_str);
return 2;
} else if (format[1] == ' ') {
// 's: S field of data processing instructions.
@@ -564,8 +565,8 @@
case 't': { // 'target: target of branch instructions.
ASSERT(STRING_STARTS_WITH(format, "target"));
int off = (instr->SImmed24Field() << 2) + 8;
- buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), "%+d", off);
+ buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), "%+d", off);
return 6;
}
case 'u': { // 'u: signed or unsigned multiplies.
@@ -657,9 +658,9 @@
if (instr->BkptField() == Instr::kStopMessageCode) {
const char* message = *reinterpret_cast<const char**>(
reinterpret_cast<intptr_t>(instr) - Instr::kInstrSize);
- buffer_pos_ +=
- OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), " ; \"%s\"", message);
+ buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(),
+ " ; \"%s\"", message);
}
} else {
// Format(instr, "smc'cond");
@@ -1494,7 +1495,7 @@
ARMDecoder decoder(human_buffer, human_size);
decoder.InstructionDecode(pc);
int32_t instruction_bits = Instr::At(pc)->InstructionBits();
- OS::SNPrint(hex_buffer, hex_size, "%08x", instruction_bits);
+ Utils::SNPrint(hex_buffer, hex_size, "%08x", instruction_bits);
if (out_instr_size) {
*out_instr_size = Instr::kInstrSize;
}
diff --git a/runtime/vm/compiler/assembler/disassembler_arm64.cc b/runtime/vm/compiler/assembler/disassembler_arm64.cc
index 64f2f15..06b9ad7 100644
--- a/runtime/vm/compiler/assembler/disassembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/disassembler_arm64.cc
@@ -104,8 +104,8 @@
void ARM64Decoder::PrintVRegister(int reg) {
ASSERT(0 <= reg);
ASSERT(reg < kNumberOfVRegisters);
- buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), "v%d", reg);
+ buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), "v%d", reg);
}
// These shift names are defined in a way to match the native disassembler
@@ -165,20 +165,20 @@
shift_amount = 32;
}
buffer_pos_ +=
- OS::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(),
- " %s #%d", shift_names[shift], shift_amount);
+ Utils::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(),
+ " %s #%d", shift_names[shift], shift_amount);
} else {
ASSERT(instr->IsExtend());
// by register
buffer_pos_ +=
- OS::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(),
- " %s", extend_names[extend]);
+ Utils::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(),
+ " %s", extend_names[extend]);
if (((instr->SFField() == 1) && (extend == UXTX)) ||
((instr->SFField() == 0) && (extend == UXTW))) {
// Shift amount.
- buffer_pos_ +=
- OS::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(),
- " %d", extend_shift_amount);
+ buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), " %d",
+ extend_shift_amount);
}
}
}
@@ -193,8 +193,8 @@
Print("[");
PrintRegister(rn, R31IsSP);
if (off != 0) {
- buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), ", #%d", off);
+ buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), ", #%d", off);
}
Print("]");
} else {
@@ -204,8 +204,9 @@
const int32_t imm9 = instr->SImm9Field();
Print("[");
PrintRegister(rn, R31IsSP);
- buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), ", #%d", imm9);
+ buffer_pos_ +=
+ Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), ", #%d", imm9);
Print("]");
break;
}
@@ -215,8 +216,9 @@
Print("[");
PrintRegister(rn, R31IsSP);
Print("]");
- buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), ", #%d !", imm9);
+ buffer_pos_ +=
+ Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), ", #%d !", imm9);
break;
}
case 2: {
@@ -227,9 +229,9 @@
PrintRegister(rn, R31IsSP);
Print(", ");
PrintRegister(rm, R31IsZR);
- buffer_pos_ +=
- OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), " %s", extend_names[ext]);
+ buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), " %s",
+ extend_names[ext]);
if (s == 1) {
Print(" scaled");
}
@@ -241,8 +243,9 @@
// rn + signed 9-bit immediate, pre-index, writeback.
Print("[");
PrintRegister(rn, R31IsSP);
- buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), ", #%d", imm9);
+ buffer_pos_ +=
+ Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), ", #%d", imm9);
Print("] !");
break;
}
@@ -261,19 +264,20 @@
case 1:
// rn + (imm7 << (2 + B31)), post-index, writeback.
buffer_pos_ +=
- OS::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(),
- "], #%d !", offset);
+ Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), "], #%d !", offset);
break;
case 2:
// rn + (imm7 << (2 + B31)), pre-index, no writeback.
- buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), ", #%d ]", offset);
+ buffer_pos_ +=
+ Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), ", #%d ]", offset);
break;
case 3:
// rn + (imm7 << (2 + B31)), pre-index, writeback.
buffer_pos_ +=
- OS::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(),
- ", #%d ]!", offset);
+ Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), ", #%d ]!", offset);
break;
default:
Print(", ???]");
@@ -348,14 +352,16 @@
if (format[3] == 'i') {
ASSERT(STRING_STARTS_WITH(format, "bitimm"));
const uint64_t imm = instr->ImmLogical();
- buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), "0x%" Px64, imm);
+ buffer_pos_ +=
+ Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), "0x%" Px64, imm);
return 6;
} else {
ASSERT(STRING_STARTS_WITH(format, "bitpos"));
int bitpos = instr->Bits(19, 4) | (instr->Bit(31) << 5);
- buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), "#%d", bitpos);
+ buffer_pos_ +=
+ Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), "#%d", bitpos);
return 6;
}
}
@@ -373,8 +379,8 @@
} else if (imm5 & 0x8) {
typ = "d";
}
- buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), "%s", typ);
+ buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), "%s", typ);
return 3;
} else {
ASSERT(STRING_STARTS_WITH(format, "cond"));
@@ -394,23 +400,23 @@
int64_t off = instr->SImm26Field() << 2;
uword destination = reinterpret_cast<uword>(instr) + off;
buffer_pos_ +=
- OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), "%#" Px "", destination);
+ Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), "%#" Px "", destination);
} else {
if (format[5] == '4') {
ASSERT(STRING_STARTS_WITH(format, "dest14"));
int64_t off = instr->SImm14Field() << 2;
uword destination = reinterpret_cast<uword>(instr) + off;
- buffer_pos_ +=
- OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), "%#" Px "", destination);
+ buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), "%#" Px "",
+ destination);
} else {
ASSERT(STRING_STARTS_WITH(format, "dest19"));
int64_t off = instr->SImm19Field() << 2;
uword destination = reinterpret_cast<uword>(instr) + off;
- buffer_pos_ +=
- OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), "%#" Px "", destination);
+ buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), "%#" Px "",
+ destination);
}
}
return 6;
@@ -440,16 +446,17 @@
sz_str = "?";
break;
}
- buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), "%s", sz_str);
+ buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), "%s", sz_str);
return 3;
}
case 'h': {
ASSERT(STRING_STARTS_WITH(format, "hw"));
const int shift = instr->HWField() << 4;
if (shift != 0) {
- buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), "lsl %d", shift);
+ buffer_pos_ +=
+ Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), "lsl %d", shift);
}
return 2;
}
@@ -477,8 +484,8 @@
} else if (imm5 & 0x8) {
idx = imm >> (shift + 3);
}
- buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), "[%d]", idx);
+ buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), "[%d]", idx);
return 4;
} else if (format[3] == '1') {
uint64_t imm;
@@ -499,27 +506,30 @@
ASSERT(STRING_STARTS_WITH(format, "imm16"));
imm = instr->Imm16Field();
}
- buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), "0x%" Px64, imm);
+ buffer_pos_ +=
+ Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), "0x%" Px64, imm);
return ret;
} else {
ASSERT(STRING_STARTS_WITH(format, "imm"));
if (format[3] == 'd') {
double dimm = bit_cast<double, int64_t>(
Instr::VFPExpandImm(instr->Imm8Field()));
- buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), "%f", dimm);
+ buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), "%f", dimm);
return 4;
} else if (format[3] == 'r') {
int immr = instr->ImmRField();
- buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), "#%d", immr);
+ buffer_pos_ +=
+ Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), "#%d", immr);
return 4;
} else {
ASSERT(format[3] == 's');
int imms = instr->ImmSField();
- buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), "#%d", imms);
+ buffer_pos_ +=
+ Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), "#%d", imms);
return 4;
}
}
@@ -539,16 +549,16 @@
const int64_t pc = reinterpret_cast<int64_t>(instr);
const int64_t dest = pc + off;
buffer_pos_ +=
- OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), "0x%" Px64, dest);
+ Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), "0x%" Px64, dest);
} else {
ASSERT(STRING_STARTS_WITH(format, "pcldr"));
const int64_t off = instr->SImm19Field() << 2;
const int64_t pc = reinterpret_cast<int64_t>(instr);
const int64_t dest = pc + off;
buffer_pos_ +=
- OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), "0x%" Px64, dest);
+ Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), "0x%" Px64, dest);
}
return 5;
} else {
@@ -589,8 +599,8 @@
break;
}
}
- buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), "%s", sz_str);
+ buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), "%s", sz_str);
return 3;
} else {
return FormatVRegister(instr, format);
@@ -632,8 +642,8 @@
sz_str = "?";
break;
}
- buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
- remaining_size_in_buffer(), "%s", sz_str);
+ buffer_pos_ += Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), "%s", sz_str);
return 2;
} else if (format[1] == ' ') {
if (instr->HasS()) {
@@ -881,8 +891,8 @@
const char* message = *reinterpret_cast<const char**>(
reinterpret_cast<intptr_t>(instr) - 2 * Instr::kInstrSize);
buffer_pos_ +=
- OS::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(),
- " ; \"%s\"", message);
+ Utils::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(), " ; \"%s\"", message);
}
} else if ((instr->Bits(0, 2) == 0) && (instr->Bits(2, 3) == 0) &&
(instr->Bits(21, 3) == 2)) {
@@ -1520,7 +1530,7 @@
ARM64Decoder decoder(human_buffer, human_size);
decoder.InstructionDecode(pc);
int32_t instruction_bits = Instr::At(pc)->InstructionBits();
- OS::SNPrint(hex_buffer, hex_size, "%08x", instruction_bits);
+ Utils::SNPrint(hex_buffer, hex_size, "%08x", instruction_bits);
if (out_instr_size) {
*out_instr_size = Instr::kInstrSize;
}
diff --git a/runtime/vm/compiler/assembler/disassembler_dbc.cc b/runtime/vm/compiler/assembler/disassembler_dbc.cc
index 7947d9f..7a15129 100644
--- a/runtime/vm/compiler/assembler/disassembler_dbc.cc
+++ b/runtime/vm/compiler/assembler/disassembler_dbc.cc
@@ -34,7 +34,7 @@
intptr_t* size,
const char* fmt,
ValueType value) {
- intptr_t written = OS::SNPrint(*buf, *size, fmt, value);
+ intptr_t written = Utils::SNPrint(*buf, *size, fmt, value);
if (written < *size) {
*buf += written;
*size += written;
@@ -218,13 +218,13 @@
const uint8_t opcode = instr & 0xFF;
ASSERT(opcode < kOpcodeCount);
size_t name_size =
- OS::SNPrint(human_buffer, human_size, "%-10s\t", kOpcodeNames[opcode]);
+ Utils::SNPrint(human_buffer, human_size, "%-10s\t", kOpcodeNames[opcode]);
human_buffer += name_size;
human_size -= name_size;
kFormatters[opcode](human_buffer, human_size, pc, instr);
- OS::SNPrint(hex_buffer, hex_size, "%08x", instr);
+ Utils::SNPrint(hex_buffer, hex_size, "%08x", instr);
if (out_instr_size) {
*out_instr_size = sizeof(uint32_t);
}
diff --git a/runtime/vm/compiler/assembler/disassembler_x86.cc b/runtime/vm/compiler/assembler/disassembler_x86.cc
index 459eb4c..bd9b2de 100644
--- a/runtime/vm/compiler/assembler/disassembler_x86.cc
+++ b/runtime/vm/compiler/assembler/disassembler_x86.cc
@@ -385,7 +385,7 @@
char* buf = buffer_ + buffer_pos_;
va_list args;
va_start(args, format);
- int length = OS::VSNPrint(buf, available, format, args);
+ int length = Utils::VSNPrint(buf, available, format, args);
va_end(args);
buffer_pos_ =
(length >= available) ? (buffer_size_ - 1) : (buffer_pos_ + length);
@@ -1957,7 +1957,7 @@
int hex_index = 0;
int remaining_size = hex_size - hex_index;
for (int i = 0; (i < instruction_length) && (remaining_size > 2); ++i) {
- OS::SNPrint(&hex_buffer[hex_index], remaining_size, "%02x", pc_ptr[i]);
+ Utils::SNPrint(&hex_buffer[hex_index], remaining_size, "%02x", pc_ptr[i]);
hex_index += 2;
remaining_size -= 2;
}
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.h b/runtime/vm/compiler/backend/flow_graph_compiler.h
index 7c10118..54cdc63 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.h
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.h
@@ -189,12 +189,12 @@
const char* Name() const {
const char* kFormat = "Deopt stub for id %d, reason: %s";
- const intptr_t len = OS::SNPrint(NULL, 0, kFormat, deopt_id(),
- DeoptReasonToCString(reason())) +
+ const intptr_t len = Utils::SNPrint(NULL, 0, kFormat, deopt_id(),
+ DeoptReasonToCString(reason())) +
1;
char* chars = Thread::Current()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, kFormat, deopt_id(),
- DeoptReasonToCString(reason()));
+ Utils::SNPrint(chars, len, kFormat, deopt_id(),
+ DeoptReasonToCString(reason()));
return chars;
}
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 2362012..ef164ec 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -2055,7 +2055,12 @@
}
Definition* RedefinitionInstr::Canonicalize(FlowGraph* flow_graph) {
- if (!HasUses()) {
+ // Must not remove Redifinitions without uses until LICM, even though
+ // Redefinition might not have any uses itself it can still be dominating
+ // uses of the value it redefines and must serve as a barrier for those
+ // uses. RenameUsesDominatedByRedefinitions would normalize the graph and
+ // route those uses through this redefinition.
+ if (!HasUses() && !flow_graph->is_licm_allowed()) {
return NULL;
}
if ((constrained_type() != NULL) &&
diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index dfbd141..cb60f6a3 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -714,15 +714,17 @@
return type_;
}
- const Class& type_class =
- Class::Handle(Isolate::Current()->class_table()->At(cid_));
-
+ Isolate* I = Isolate::Current();
+ const Class& type_class = Class::Handle(I->class_table()->At(cid_));
if (type_class.NumTypeArguments() > 0) {
- type_ = &Object::dynamic_type();
- return type_;
+ if (I->strong()) {
+ type_ = &AbstractType::ZoneHandle(type_class.RareType());
+ } else {
+ type_ = &Object::dynamic_type();
+ }
+ } else {
+ type_ = &Type::ZoneHandle(Type::NewNonParameterizedType(type_class));
}
-
- type_ = &Type::ZoneHandle(Type::NewNonParameterizedType(type_class));
}
return type_;
@@ -1254,21 +1256,27 @@
}
const Isolate* isolate = Isolate::Current();
- const AbstractType* abstract_type = NULL;
+ CompileType compile_type_annotation = CompileType::None();
if ((isolate->strong() && FLAG_use_strong_mode_types) ||
(isolate->type_checks() &&
(type().IsFunctionType() || type().HasResolvedTypeClass()))) {
- abstract_type = &type();
+ const AbstractType* abstract_type = abstract_type = &type();
TraceStrongModeType(this, *abstract_type);
+ compile_type_annotation = CompileType::FromAbstractType(*abstract_type);
}
+ CompileType compile_type_cid = CompileType::None();
if ((field_ != NULL) && (field_->guarded_cid() != kIllegalCid)) {
bool is_nullable = field_->is_nullable();
intptr_t field_cid = field_->guarded_cid();
- return CompileType(is_nullable, field_cid, abstract_type);
+
+ compile_type_cid = CompileType(is_nullable, field_cid, NULL);
+ } else {
+ compile_type_cid = CompileType::FromCid(result_cid_);
}
- return CompileType::Create(result_cid_, *abstract_type);
+ return *CompileType::ComputeRefinedType(&compile_type_cid,
+ &compile_type_annotation);
}
CompileType LoadCodeUnitsInstr::ComputeType() const {
diff --git a/runtime/vm/compiler/frontend/flow_graph_builder.cc b/runtime/vm/compiler/frontend/flow_graph_builder.cc
index 0de502c..f22532f 100644
--- a/runtime/vm/compiler/frontend/flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/flow_graph_builder.cc
@@ -2112,7 +2112,7 @@
ASSERT(value->definition()->temp_index() == (owner()->temp_count() - 1));
intptr_t index = GetCurrentTempLocalIndex();
char name[64];
- OS::SNPrint(name, 64, ":tmp_local%" Pd, index);
+ Utils::SNPrint(name, 64, ":tmp_local%" Pd, index);
LocalVariable* var =
new (Z) LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
String::ZoneHandle(Z, Symbols::New(T, name)),
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index aa504d3..f1ec175 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -732,23 +732,35 @@
return DirectCallMetadata(target, check_receiver_for_null);
}
-bool ProcedureAttributesMetadataHelper::ReadMetadata(intptr_t node_offset,
- bool* has_dynamic_calls) {
+bool ProcedureAttributesMetadataHelper::ReadMetadata(
+ intptr_t node_offset,
+ ProcedureAttributesMetadata* metadata) {
intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset);
if (md_offset < 0) {
- *has_dynamic_calls = true;
return false;
}
- *has_dynamic_calls = false;
+
+ AlternativeReadingScope alt(builder_->reader_, &H.metadata_payloads(),
+ md_offset - MetadataPayloadOffset);
+
+ const int kDynamicUsesBit = 1 << 0;
+ const int kNonThisUsesBit = 1 << 1;
+ const int kTearOffUsesBit = 1 << 2;
+
+ const uint8_t flags = builder_->ReadByte();
+ metadata->has_dynamic_invocations =
+ (flags & kDynamicUsesBit) == kDynamicUsesBit;
+ metadata->has_non_this_uses = (flags & kNonThisUsesBit) == kNonThisUsesBit;
+ metadata->has_tearoff_uses = (flags & kTearOffUsesBit) == kTearOffUsesBit;
return true;
}
ProcedureAttributesMetadata
ProcedureAttributesMetadataHelper::GetProcedureAttributes(
intptr_t node_offset) {
- bool has_dynamic_calls = true;
- ReadMetadata(node_offset, &has_dynamic_calls);
- return ProcedureAttributesMetadata(has_dynamic_calls);
+ ProcedureAttributesMetadata metadata;
+ ReadMetadata(node_offset, &metadata);
+ return metadata;
}
InferredTypeMetadata InferredTypeMetadataHelper::GetInferredType(
@@ -973,7 +985,7 @@
// Continue reading FunctionNode:
// read positional_parameters and named_parameters.
- AddPositionalAndNamedParameters(pos, type_check_mode);
+ AddPositionalAndNamedParameters(pos, type_check_mode, attrs);
// We generate a synthetic body for implicit closure functions - which
// will forward the call to the real function.
@@ -1032,7 +1044,8 @@
field_helper.ReadUntilIncluding(FieldHelper::kFlags);
if (!field_helper.IsCovariant() &&
- !field_helper.IsGenericCovariantImpl()) {
+ (!field_helper.IsGenericCovariantImpl() ||
+ (!attrs.has_non_this_uses && !attrs.has_tearoff_uses))) {
result_->setter_value->set_type_check_mode(
LocalVariable::kTypeCheckedByCaller);
}
@@ -2032,7 +2045,9 @@
// read positional_parameters and named_parameters.
function_node_helper.ReadUntilExcluding(
FunctionNodeHelper::kPositionalParameters);
- AddPositionalAndNamedParameters(0, kTypeCheckAllParameters);
+
+ ProcedureAttributesMetadata default_attrs;
+ AddPositionalAndNamedParameters(0, kTypeCheckAllParameters, default_attrs);
// "Peek" is now done.
builder_->SetOffset(offset);
@@ -2060,23 +2075,25 @@
void StreamingScopeBuilder::AddPositionalAndNamedParameters(
intptr_t pos,
- ParameterTypeCheckMode type_check_mode /* = kTypeCheckAllParameters*/) {
+ ParameterTypeCheckMode type_check_mode /* = kTypeCheckAllParameters*/,
+ const ProcedureAttributesMetadata& attrs) {
// List of positional.
intptr_t list_length = builder_->ReadListLength(); // read list length.
for (intptr_t i = 0; i < list_length; ++i) {
- AddVariableDeclarationParameter(pos++, type_check_mode);
+ AddVariableDeclarationParameter(pos++, type_check_mode, attrs);
}
// List of named.
list_length = builder_->ReadListLength(); // read list length.
for (intptr_t i = 0; i < list_length; ++i) {
- AddVariableDeclarationParameter(pos++, type_check_mode);
+ AddVariableDeclarationParameter(pos++, type_check_mode, attrs);
}
}
void StreamingScopeBuilder::AddVariableDeclarationParameter(
intptr_t pos,
- ParameterTypeCheckMode type_check_mode) {
+ ParameterTypeCheckMode type_check_mode,
+ const ProcedureAttributesMetadata& attrs) {
intptr_t kernel_offset = builder_->ReaderOffset(); // no tag.
const InferredTypeMetadata parameter_type =
builder_->inferred_type_metadata_helper_.GetInferredType(kernel_offset);
@@ -2096,14 +2113,16 @@
variable->set_is_forced_stack();
}
- const bool is_covariant =
- helper.IsGenericCovariantImpl() || helper.IsCovariant();
+ const bool needs_covariant_checke_in_method =
+ helper.IsCovariant() ||
+ (helper.IsGenericCovariantImpl() && attrs.has_non_this_uses);
+
switch (type_check_mode) {
case kTypeCheckAllParameters:
variable->set_type_check_mode(LocalVariable::kDoTypeCheck);
break;
case kTypeCheckForTearOffOfNonDynamicallyInvokedMethod:
- if (is_covariant) {
+ if (needs_covariant_checke_in_method) {
// Don't type check covariant parameters - they will be checked by
// a function we forward to. Their types however are not known.
variable->set_type_check_mode(LocalVariable::kSkipTypeCheck);
@@ -2112,7 +2131,7 @@
}
break;
case kTypeCheckForNonDynamicallyInvokedMethod:
- if (is_covariant) {
+ if (needs_covariant_checke_in_method) {
variable->set_type_check_mode(LocalVariable::kDoTypeCheck);
} else {
// Types of non-covariant parameters are guaranteed to match by
@@ -2271,7 +2290,7 @@
const String& StreamingScopeBuilder::GenerateName(const char* prefix,
intptr_t suffix) {
char name[64];
- OS::SNPrint(name, 64, "%s%" Pd "", prefix, suffix);
+ Utils::SNPrint(name, 64, "%s%" Pd "", prefix, suffix);
return H.DartSymbolObfuscate(name);
}
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index 80da18a..aac0ad34 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -605,9 +605,15 @@
};
struct ProcedureAttributesMetadata {
- explicit ProcedureAttributesMetadata(bool has_dynamic_invocations)
- : has_dynamic_invocations(has_dynamic_invocations) {}
- const bool has_dynamic_invocations;
+ ProcedureAttributesMetadata(bool has_dynamic_invocations = true,
+ bool has_non_this_uses = true,
+ bool has_tearoff_uses = true)
+ : has_dynamic_invocations(has_dynamic_invocations),
+ has_non_this_uses(has_non_this_uses),
+ has_tearoff_uses(has_tearoff_uses) {}
+ bool has_dynamic_invocations;
+ bool has_non_this_uses;
+ bool has_tearoff_uses;
};
// Helper class which provides access to direct call metadata.
@@ -621,7 +627,8 @@
ProcedureAttributesMetadata GetProcedureAttributes(intptr_t node_offset);
private:
- bool ReadMetadata(intptr_t node_offset, bool* has_dynamic_invocations);
+ bool ReadMetadata(intptr_t node_offset,
+ ProcedureAttributesMetadata* metadata);
};
class StreamingDartTypeTranslator {
@@ -749,13 +756,17 @@
// This assumes that the reader is at a FunctionNode,
// about to read the positional parameters.
- void AddPositionalAndNamedParameters(intptr_t pos,
- ParameterTypeCheckMode type_check_mode);
+ void AddPositionalAndNamedParameters(
+ intptr_t pos,
+ ParameterTypeCheckMode type_check_mode,
+ const ProcedureAttributesMetadata& attrs);
// This assumes that the reader is at a FunctionNode,
// about to read a parameter (i.e. VariableDeclaration).
- void AddVariableDeclarationParameter(intptr_t pos,
- ParameterTypeCheckMode type_check_mode);
+ void AddVariableDeclarationParameter(
+ intptr_t pos,
+ ParameterTypeCheckMode type_check_mode,
+ const ProcedureAttributesMetadata& attrs);
LocalVariable* MakeVariable(TokenPosition declaration_pos,
TokenPosition token_pos,
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index e8b7c6b..2e5356c 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -1843,7 +1843,7 @@
LocalVariable* BaseFlowGraphBuilder::MakeTemporary() {
char name[64];
intptr_t index = stack_->definition()->temp_index();
- OS::SNPrint(name, 64, ":temp%" Pd, index);
+ Utils::SNPrint(name, 64, ":temp%" Pd, index);
const String& symbol_name =
String::ZoneHandle(Z, Symbols::New(thread_, name));
LocalVariable* variable =
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index faa46ac..8d58ab9 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -470,13 +470,13 @@
va_list args;
va_start(args, format);
- intptr_t len = OS::VSNPrint(NULL, 0, format, args);
+ intptr_t len = Utils::VSNPrint(NULL, 0, format, args);
va_end(args);
char* buffer = Z->Alloc<char>(len + 1);
va_list args2;
va_start(args2, format);
- OS::VSNPrint(buffer, (len + 1), format, args2);
+ Utils::VSNPrint(buffer, (len + 1), format, args2);
va_end(args2);
const String& message = String::Handle(Z, String::New(buffer));
@@ -1080,9 +1080,9 @@
}
char* chars = NULL;
- intptr_t len = OS::SNPrint(NULL, 0, "%s:%s()", script_uri, main) + 1;
+ intptr_t len = Utils::SNPrint(NULL, 0, "%s:%s()", script_uri, main) + 1;
chars = reinterpret_cast<char*>(malloc(len));
- OS::SNPrint(chars, len, "%s:%s()", script_uri, main);
+ Utils::SNPrint(chars, len, "%s:%s()", script_uri, main);
return chars;
}
@@ -1546,7 +1546,7 @@
const char* features = version + version_len;
ASSERT(features != NULL);
intptr_t pending_len = snapshot_size - version_len;
- intptr_t buffer_len = OS::StrNLen(features, pending_len);
+ intptr_t buffer_len = Utils::StrNLen(features, pending_len);
// if buffer_len is less than pending_len it means we have a null terminated
// string and we can safely execute 'strstr' on it.
if ((buffer_len < pending_len)) {
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index d2507e8..2c6f781 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -3610,7 +3610,7 @@
// Use a unique expected value.
static int counter = 0;
char buffer[256];
- OS::SNPrint(buffer, 256, "Expected%d", ++counter);
+ Utils::SNPrint(buffer, 256, "Expected%d", ++counter);
// Try to change the field value.
result = Dart_SetField(container, name, NewString(buffer));
diff --git a/runtime/vm/datastream.h b/runtime/vm/datastream.h
index a4948a1..bab0dff 100644
--- a/runtime/vm/datastream.h
+++ b/runtime/vm/datastream.h
@@ -395,7 +395,7 @@
// Measure.
va_list measure_args;
va_copy(measure_args, args);
- intptr_t len = OS::VSNPrint(NULL, 0, format, measure_args);
+ intptr_t len = Utils::VSNPrint(NULL, 0, format, measure_args);
va_end(measure_args);
// Alloc.
@@ -407,8 +407,8 @@
// Print.
va_list print_args;
va_copy(print_args, args);
- OS::VSNPrint(reinterpret_cast<char*>(current_), len + 1, format,
- print_args);
+ Utils::VSNPrint(reinterpret_cast<char*>(current_), len + 1, format,
+ print_args);
va_end(print_args);
current_ += len; // Not len + 1 to swallow the terminating NUL.
}
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index 80e7a1b..ee069b2 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -417,8 +417,8 @@
String& line_string = String::Handle(script.GetLine(line));
THR_Print(" Function: %s\n", top_function.ToFullyQualifiedCString());
char line_buffer[80];
- OS::SNPrint(line_buffer, sizeof(line_buffer), " Line %" Pd ": '%s'", line,
- line_string.ToCString());
+ Utils::SNPrint(line_buffer, sizeof(line_buffer), " Line %" Pd ": '%s'",
+ line, line_string.ToCString());
THR_Print("%s\n", line_buffer);
THR_Print(" Deopt args: %" Pd "\n", deopt_arg_count);
}
@@ -1401,7 +1401,7 @@
// Compute the buffer size required.
intptr_t len = 1; // Trailing '\0'.
for (intptr_t i = 0; i < deopt_instrs.length(); i++) {
- len += OS::SNPrint(NULL, 0, FORMAT, deopt_instrs[i]->ToCString());
+ len += Utils::SNPrint(NULL, 0, FORMAT, deopt_instrs[i]->ToCString());
}
// Allocate the buffer.
@@ -1410,8 +1410,8 @@
// Layout the fields in the buffer.
intptr_t index = 0;
for (intptr_t i = 0; i < deopt_instrs.length(); i++) {
- index += OS::SNPrint((buffer + index), (len - index), FORMAT,
- deopt_instrs[i]->ToCString());
+ index += Utils::SNPrint((buffer + index), (len - index), FORMAT,
+ deopt_instrs[i]->ToCString());
}
return buffer;
diff --git a/runtime/vm/find_code_object_test.cc b/runtime/vm/find_code_object_test.cc
index 2d0e82f..0be5a94 100644
--- a/runtime/vm/find_code_object_test.cc
+++ b/runtime/vm/find_code_object_test.cc
@@ -46,14 +46,14 @@
lib = Library::CoreLibrary();
// Load up class A with 1024 functions.
- int written = OS::SNPrint(scriptChars, kScriptSize, "class A {");
+ int written = Utils::SNPrint(scriptChars, kScriptSize, "class A {");
for (int i = 0; i < kNumFunctions; i++) {
- OS::SNPrint(buffer, 256,
- "static foo%d([int i=1,int j=2,int k=3]){return i+j+k;}", i);
- written += OS::SNPrint((scriptChars + written), (kScriptSize - written),
- "%s", buffer);
+ Utils::SNPrint(buffer, 256,
+ "static foo%d([int i=1,int j=2,int k=3]){return i+j+k;}", i);
+ written += Utils::SNPrint((scriptChars + written), (kScriptSize - written),
+ "%s", buffer);
}
- OS::SNPrint((scriptChars + written), (kScriptSize - written), "}");
+ Utils::SNPrint((scriptChars + written), (kScriptSize - written), "}");
source = String::New(scriptChars);
script = Script::New(url, source, RawScript::kScriptTag);
EXPECT(CompilerTest::TestCompileScript(lib, script));
@@ -61,7 +61,7 @@
EXPECT(!clsA.IsNull());
ClassFinalizer::ProcessPendingClasses();
for (int i = 0; i < kNumFunctions; i++) {
- OS::SNPrint(buffer, 256, "foo%d", i);
+ Utils::SNPrint(buffer, 256, "foo%d", i);
function_name = String::New(buffer);
function = clsA.LookupStaticFunction(function_name);
EXPECT(!function.IsNull());
@@ -72,28 +72,28 @@
}
// Now load up class B with 1024 functions.
- written = OS::SNPrint(scriptChars, kScriptSize, "class B {");
+ written = Utils::SNPrint(scriptChars, kScriptSize, "class B {");
// Create one large function.
- OS::SNPrint(buffer, sizeof(buffer), "static moo0([var i=1]) { ");
- written += OS::SNPrint((scriptChars + written), (kScriptSize - written), "%s",
- buffer);
+ Utils::SNPrint(buffer, sizeof(buffer), "static moo0([var i=1]) { ");
+ written += Utils::SNPrint((scriptChars + written), (kScriptSize - written),
+ "%s", buffer);
// Generate a large function so that the code for this function when
// compiled will reside in a large page.
for (int i = 0; i < kLoopCount; i++) {
- OS::SNPrint(buffer, sizeof(buffer), "i = i+i;");
- written += OS::SNPrint((scriptChars + written), (kScriptSize - written),
- "%s", buffer);
+ Utils::SNPrint(buffer, sizeof(buffer), "i = i+i;");
+ written += Utils::SNPrint((scriptChars + written), (kScriptSize - written),
+ "%s", buffer);
}
- OS::SNPrint(buffer, sizeof(buffer), "return i; }");
- written += OS::SNPrint((scriptChars + written), (kScriptSize - written), "%s",
- buffer);
+ Utils::SNPrint(buffer, sizeof(buffer), "return i; }");
+ written += Utils::SNPrint((scriptChars + written), (kScriptSize - written),
+ "%s", buffer);
for (int i = 1; i < kNumFunctions; i++) {
- OS::SNPrint(buffer, 256,
- "static moo%d([int i=1,int j=2,int k=3]){return i+j+k;}", i);
- written += OS::SNPrint((scriptChars + written), (kScriptSize - written),
- "%s", buffer);
+ Utils::SNPrint(buffer, 256,
+ "static moo%d([int i=1,int j=2,int k=3]){return i+j+k;}", i);
+ written += Utils::SNPrint((scriptChars + written), (kScriptSize - written),
+ "%s", buffer);
}
- OS::SNPrint((scriptChars + written), (kScriptSize - written), "}");
+ Utils::SNPrint((scriptChars + written), (kScriptSize - written), "}");
url = String::New("dart-test:FindCodeObject");
source = String::New(scriptChars);
script = Script::New(url, source, RawScript::kScriptTag);
@@ -102,7 +102,7 @@
EXPECT(!clsB.IsNull());
ClassFinalizer::ProcessPendingClasses();
for (int i = 0; i < kNumFunctions; i++) {
- OS::SNPrint(buffer, 256, "moo%d", i);
+ Utils::SNPrint(buffer, 256, "moo%d", i);
function_name = String::New(buffer);
function = clsB.LookupStaticFunction(function_name);
EXPECT(!function.IsNull());
@@ -115,7 +115,7 @@
// Now try and access these functions using the code index table.
Code& code = Code::Handle();
uword pc;
- OS::SNPrint(buffer, 256, "foo%d", 123);
+ Utils::SNPrint(buffer, 256, "foo%d", 123);
function_name = String::New(buffer);
function = clsA.LookupStaticFunction(function_name);
EXPECT(!function.IsNull());
@@ -124,7 +124,7 @@
pc = code.PayloadStart() + 16;
EXPECT(Code::LookupCode(pc) == code.raw());
- OS::SNPrint(buffer, 256, "moo%d", 54);
+ Utils::SNPrint(buffer, 256, "moo%d", 54);
function_name = String::New(buffer);
function = clsB.LookupStaticFunction(function_name);
EXPECT(!function.IsNull());
@@ -134,7 +134,7 @@
EXPECT(Code::LookupCode(pc) == code.raw());
// Lookup the large function
- OS::SNPrint(buffer, 256, "moo%d", 0);
+ Utils::SNPrint(buffer, 256, "moo%d", 0);
function_name = String::New(buffer);
function = clsB.LookupStaticFunction(function_name);
EXPECT(!function.IsNull());
diff --git a/runtime/vm/heap.cc b/runtime/vm/heap.cc
index da02f72..7468e02 100644
--- a/runtime/vm/heap.cc
+++ b/runtime/vm/heap.cc
@@ -528,7 +528,7 @@
default:
UNREACHABLE();
}
- OS::SNPrint(name, name_size, "dart-%s %s", space_name, isolate_name);
+ Utils::SNPrint(name, name_size, "dart-%s %s", space_name, isolate_name);
}
void Heap::AddRegionsToObjectSet(ObjectSet* set) const {
diff --git a/runtime/vm/json_stream.cc b/runtime/vm/json_stream.cc
index 14f7506..da65506 100644
--- a/runtime/vm/json_stream.cc
+++ b/runtime/vm/json_stream.cc
@@ -163,13 +163,13 @@
if (details_format != NULL) {
va_list args;
va_start(args, details_format);
- intptr_t len = OS::VSNPrint(NULL, 0, details_format, args);
+ intptr_t len = Utils::VSNPrint(NULL, 0, details_format, args);
va_end(args);
char* buffer = Thread::Current()->zone()->Alloc<char>(len + 1);
va_list args2;
va_start(args2, details_format);
- OS::VSNPrint(buffer, (len + 1), details_format, args2);
+ Utils::VSNPrint(buffer, (len + 1), details_format, args2);
va_end(args2);
data.AddProperty("details", buffer);
diff --git a/runtime/vm/json_writer.cc b/runtime/vm/json_writer.cc
index c4e980c..4e7c98a 100644
--- a/runtime/vm/json_writer.cc
+++ b/runtime/vm/json_writer.cc
@@ -189,7 +189,7 @@
va_list measure_args;
va_copy(measure_args, args);
- intptr_t len = OS::VSNPrint(NULL, 0, format, measure_args);
+ intptr_t len = Utils::VSNPrint(NULL, 0, format, measure_args);
va_end(measure_args);
MaybeOnStackBuffer mosb(len + 1);
@@ -197,7 +197,7 @@
va_list print_args;
va_copy(print_args, args);
- intptr_t len2 = OS::VSNPrint(p, len + 1, format, print_args);
+ intptr_t len2 = Utils::VSNPrint(p, len + 1, format, print_args);
va_end(print_args);
ASSERT(len == len2);
@@ -265,7 +265,7 @@
va_list measure_args;
va_copy(measure_args, args);
- intptr_t len = OS::VSNPrint(NULL, 0, format, measure_args);
+ intptr_t len = Utils::VSNPrint(NULL, 0, format, measure_args);
va_end(measure_args);
MaybeOnStackBuffer mosb(len + 1);
@@ -273,7 +273,7 @@
va_list print_args;
va_copy(print_args, args);
- intptr_t len2 = OS::VSNPrint(p, len + 1, format, print_args);
+ intptr_t len2 = Utils::VSNPrint(p, len + 1, format, print_args);
va_end(print_args);
ASSERT(len == len2);
diff --git a/runtime/vm/log.cc b/runtime/vm/log.cc
index 23005a7..06a4263 100644
--- a/runtime/vm/log.cc
+++ b/runtime/vm/log.cc
@@ -63,14 +63,14 @@
// Measure.
va_list measure_args;
va_copy(measure_args, args);
- intptr_t len = OS::VSNPrint(NULL, 0, format, measure_args);
+ intptr_t len = Utils::VSNPrint(NULL, 0, format, measure_args);
va_end(measure_args);
// Print.
char* buffer = reinterpret_cast<char*>(malloc(len + 1));
va_list print_args;
va_copy(print_args, args);
- OS::VSNPrint(buffer, (len + 1), format, print_args);
+ Utils::VSNPrint(buffer, (len + 1), format, print_args);
va_end(print_args);
// Append.
diff --git a/runtime/vm/log_test.cc b/runtime/vm/log_test.cc
index c64fd21..f17c4d9 100644
--- a/runtime/vm/log_test.cc
+++ b/runtime/vm/log_test.cc
@@ -21,14 +21,14 @@
// Measure.
va_list args;
va_start(args, format);
- intptr_t len = OS::VSNPrint(NULL, 0, format, args);
+ intptr_t len = Utils::VSNPrint(NULL, 0, format, args);
va_end(args);
// Print string to buffer.
char* buffer = reinterpret_cast<char*>(malloc(len + 1));
va_list args2;
va_start(args2, format);
- OS::VSNPrint(buffer, (len + 1), format, args2);
+ Utils::VSNPrint(buffer, (len + 1), format, args2);
va_end(args2);
if (test_output_ != NULL) {
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 3a928b4..707af78 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -2712,7 +2712,7 @@
for (; i < desc.PositionalCount(); i++) {
invocation.SetParameterTypeAt(i, Object::dynamic_type());
char name[64];
- OS::SNPrint(name, 64, ":p%" Pd, i);
+ Utils::SNPrint(name, 64, ":p%" Pd, i);
invocation.SetParameterNameAt(
i, String::Handle(zone, Symbols::New(thread, name)));
}
@@ -6307,9 +6307,9 @@
if (error_message != NULL) {
const intptr_t kMessageBufferSize = 64;
char message_buffer[kMessageBufferSize];
- OS::SNPrint(message_buffer, kMessageBufferSize,
- "%" Pd " type arguments passed, but %" Pd " expected",
- num_type_arguments, NumTypeParameters());
+ Utils::SNPrint(message_buffer, kMessageBufferSize,
+ "%" Pd " type arguments passed, but %" Pd " expected",
+ num_type_arguments, NumTypeParameters());
// Allocate in old space because it can be invoked in background
// optimizing compilation.
*error_message = String::New(message_buffer, Heap::kOld);
@@ -6320,9 +6320,9 @@
if (error_message != NULL) {
const intptr_t kMessageBufferSize = 64;
char message_buffer[kMessageBufferSize];
- OS::SNPrint(message_buffer, kMessageBufferSize,
- "%" Pd " named passed, at most %" Pd " expected",
- num_named_arguments, NumOptionalNamedParameters());
+ Utils::SNPrint(message_buffer, kMessageBufferSize,
+ "%" Pd " named passed, at most %" Pd " expected",
+ num_named_arguments, NumOptionalNamedParameters());
// Allocate in old space because it can be invoked in background
// optimizing compilation.
*error_message = String::New(message_buffer, Heap::kOld);
@@ -6338,12 +6338,12 @@
char message_buffer[kMessageBufferSize];
// Hide implicit parameters to the user.
const intptr_t num_hidden_params = NumImplicitParameters();
- OS::SNPrint(message_buffer, kMessageBufferSize,
- "%" Pd "%s passed, %s%" Pd " expected",
- num_pos_args - num_hidden_params,
- num_opt_pos_params > 0 ? " positional" : "",
- num_opt_pos_params > 0 ? "at most " : "",
- num_pos_params - num_hidden_params);
+ Utils::SNPrint(message_buffer, kMessageBufferSize,
+ "%" Pd "%s passed, %s%" Pd " expected",
+ num_pos_args - num_hidden_params,
+ num_opt_pos_params > 0 ? " positional" : "",
+ num_opt_pos_params > 0 ? "at most " : "",
+ num_pos_params - num_hidden_params);
// Allocate in old space because it can be invoked in background
// optimizing compilation.
*error_message = String::New(message_buffer, Heap::kOld);
@@ -6356,12 +6356,12 @@
char message_buffer[kMessageBufferSize];
// Hide implicit parameters to the user.
const intptr_t num_hidden_params = NumImplicitParameters();
- OS::SNPrint(message_buffer, kMessageBufferSize,
- "%" Pd "%s passed, %s%" Pd " expected",
- num_pos_args - num_hidden_params,
- num_opt_pos_params > 0 ? " positional" : "",
- num_opt_pos_params > 0 ? "at least " : "",
- num_fixed_parameters() - num_hidden_params);
+ Utils::SNPrint(message_buffer, kMessageBufferSize,
+ "%" Pd "%s passed, %s%" Pd " expected",
+ num_pos_args - num_hidden_params,
+ num_opt_pos_params > 0 ? " positional" : "",
+ num_opt_pos_params > 0 ? "at least " : "",
+ num_fixed_parameters() - num_hidden_params);
// Allocate in old space because it can be invoked in background
// optimizing compilation.
*error_message = String::New(message_buffer, Heap::kOld);
@@ -6403,9 +6403,9 @@
if (error_message != NULL) {
const intptr_t kMessageBufferSize = 64;
char message_buffer[kMessageBufferSize];
- OS::SNPrint(message_buffer, kMessageBufferSize,
- "no optional formal parameter named '%s'",
- argument_name.ToCString());
+ Utils::SNPrint(message_buffer, kMessageBufferSize,
+ "no optional formal parameter named '%s'",
+ argument_name.ToCString());
// Allocate in old space because it can be invoked in background
// optimizing compilation.
*error_message = String::New(message_buffer, Heap::kOld);
@@ -6448,9 +6448,9 @@
if (error_message != NULL) {
const intptr_t kMessageBufferSize = 64;
char message_buffer[kMessageBufferSize];
- OS::SNPrint(message_buffer, kMessageBufferSize,
- "no optional formal parameter named '%s'",
- argument_name.ToCString());
+ Utils::SNPrint(message_buffer, kMessageBufferSize,
+ "no optional formal parameter named '%s'",
+ argument_name.ToCString());
// Allocate in old space because it can be invoked in background
// optimizing compilation.
*error_message = String::New(message_buffer, Heap::kOld);
@@ -6479,7 +6479,7 @@
QualifiedFunctionLibKind lib_kind) {
const char* name = String::Handle(function.name()).ToCString();
const char* function_format = (reserve_len == 0) ? "%s" : "%s_";
- reserve_len += OS::SNPrint(NULL, 0, function_format, name);
+ reserve_len += Utils::SNPrint(NULL, 0, function_format, name);
const Function& parent = Function::Handle(function.parent_function());
intptr_t written = 0;
if (parent.IsNull()) {
@@ -6509,18 +6509,18 @@
lib_class_format = "%s%s.";
}
reserve_len +=
- OS::SNPrint(NULL, 0, lib_class_format, library_name, class_name);
+ Utils::SNPrint(NULL, 0, lib_class_format, library_name, class_name);
ASSERT(chars != NULL);
*chars = Thread::Current()->zone()->Alloc<char>(reserve_len + 1);
- written = OS::SNPrint(*chars, reserve_len + 1, lib_class_format,
- library_name, class_name);
+ written = Utils::SNPrint(*chars, reserve_len + 1, lib_class_format,
+ library_name, class_name);
} else {
written = ConstructFunctionFullyQualifiedCString(parent, chars, reserve_len,
with_lib, lib_kind);
}
ASSERT(*chars != NULL);
char* next = *chars + written;
- written += OS::SNPrint(next, reserve_len + 1, function_format, name);
+ written += Utils::SNPrint(next, reserve_len + 1, function_format, name);
// Replace ":" with "_".
while (true) {
next = strchr(next, ':');
@@ -11443,8 +11443,8 @@
char name_buffer[kNameLength];
String& cls_name = String::Handle(zone);
for (int fld_cnt = 1; fld_cnt <= kNumNativeWrappersClasses; fld_cnt++) {
- OS::SNPrint(name_buffer, kNameLength, "%s%d", kNativeWrappersClass,
- fld_cnt);
+ Utils::SNPrint(name_buffer, kNameLength, "%s%d", kNativeWrappersClass,
+ fld_cnt);
cls_name = Symbols::New(thread, name_buffer);
Class::NewNativeWrapper(native_flds_lib, cls_name, fld_cnt);
}
@@ -11549,8 +11549,8 @@
intptr_t sequence_value = libs.Length();
char private_key[32];
- OS::SNPrint(private_key, sizeof(private_key), "%c%" Pd "%06" Pd "",
- kPrivateKeySeparator, sequence_value, hash_value);
+ Utils::SNPrint(private_key, sizeof(private_key), "%c%" Pd "%06" Pd "",
+ kPrivateKeySeparator, sequence_value, hash_value);
const String& key =
String::Handle(zone, String::New(private_key, Heap::kOld));
key.Hash(); // This string may end up in the VM isolate.
@@ -12653,9 +12653,9 @@
{
Iterator iter(*this, RawPcDescriptors::kAnyKind);
while (iter.MoveNext()) {
- len += OS::SNPrint(NULL, 0, FORMAT, addr_width, iter.PcOffset(),
- KindAsStr(iter.Kind()), iter.DeoptId(),
- iter.TokenPos().ToCString(), iter.TryIndex());
+ len += Utils::SNPrint(NULL, 0, FORMAT, addr_width, iter.PcOffset(),
+ KindAsStr(iter.Kind()), iter.DeoptId(),
+ iter.TokenPos().ToCString(), iter.TryIndex());
}
}
// Allocate the buffer.
@@ -12665,9 +12665,9 @@
Iterator iter(*this, RawPcDescriptors::kAnyKind);
while (iter.MoveNext()) {
index +=
- OS::SNPrint((buffer + index), (len - index), FORMAT, addr_width,
- iter.PcOffset(), KindAsStr(iter.Kind()), iter.DeoptId(),
- iter.TokenPos().ToCString(), iter.TryIndex());
+ Utils::SNPrint((buffer + index), (len - index), FORMAT, addr_width,
+ iter.PcOffset(), KindAsStr(iter.Kind()), iter.DeoptId(),
+ iter.TokenPos().ToCString(), iter.TryIndex());
}
return buffer;
#undef FORMAT
@@ -12839,7 +12839,7 @@
if (IsNull()) {
return "{null}";
} else {
- intptr_t fixed_length = OS::SNPrint(NULL, 0, FORMAT, PcOffset()) + 1;
+ intptr_t fixed_length = Utils::SNPrint(NULL, 0, FORMAT, PcOffset()) + 1;
Thread* thread = Thread::Current();
// Guard against integer overflow in the computation of alloc_size.
//
@@ -12850,7 +12850,7 @@
}
intptr_t alloc_size = fixed_length + Length();
char* chars = thread->zone()->Alloc<char>(alloc_size);
- intptr_t index = OS::SNPrint(chars, alloc_size, FORMAT, PcOffset());
+ intptr_t index = Utils::SNPrint(chars, alloc_size, FORMAT, PcOffset());
for (intptr_t i = 0; i < Length(); i++) {
chars[index++] = IsObject(i) ? '1' : '0';
}
@@ -12889,15 +12889,15 @@
const RawLocalVarDescriptors::VarInfoKind kind = info.kind();
const int32_t index = info.index();
if (kind == RawLocalVarDescriptors::kContextLevel) {
- return OS::SNPrint(buffer, len,
- "%2" Pd
- " %-13s level=%-3d"
- " begin=%-3d end=%d\n",
- i, LocalVarDescriptors::KindToCString(kind), index,
- static_cast<int>(info.begin_pos.value()),
- static_cast<int>(info.end_pos.value()));
+ return Utils::SNPrint(buffer, len,
+ "%2" Pd
+ " %-13s level=%-3d"
+ " begin=%-3d end=%d\n",
+ i, LocalVarDescriptors::KindToCString(kind), index,
+ static_cast<int>(info.begin_pos.value()),
+ static_cast<int>(info.end_pos.value()));
} else if (kind == RawLocalVarDescriptors::kContextVar) {
- return OS::SNPrint(
+ return Utils::SNPrint(
buffer, len,
"%2" Pd
" %-13s level=%-3d index=%-3d"
@@ -12906,7 +12906,7 @@
static_cast<int>(info.begin_pos.Pos()),
static_cast<int>(info.end_pos.Pos()), var_name.ToCString());
} else {
- return OS::SNPrint(
+ return Utils::SNPrint(
buffer, len,
"%2" Pd
" %-13s scope=%-3d index=%-3d"
@@ -13129,13 +13129,13 @@
handled_types = GetHandledTypes(i);
const intptr_t num_types =
handled_types.IsNull() ? 0 : handled_types.Length();
- len += OS::SNPrint(NULL, 0, FORMAT1, i, info.handler_pc_offset, num_types,
- info.outer_try_index,
- info.is_generated ? "(generated)" : "");
+ len += Utils::SNPrint(NULL, 0, FORMAT1, i, info.handler_pc_offset,
+ num_types, info.outer_try_index,
+ info.is_generated ? "(generated)" : "");
for (int k = 0; k < num_types; k++) {
type ^= handled_types.At(k);
ASSERT(!type.IsNull());
- len += OS::SNPrint(NULL, 0, FORMAT2, k, type.ToCString());
+ len += Utils::SNPrint(NULL, 0, FORMAT2, k, type.ToCString());
}
}
// Allocate the buffer.
@@ -13148,13 +13148,13 @@
const intptr_t num_types =
handled_types.IsNull() ? 0 : handled_types.Length();
num_chars +=
- OS::SNPrint((buffer + num_chars), (len - num_chars), FORMAT1, i,
- info.handler_pc_offset, num_types, info.outer_try_index,
- info.is_generated ? "(generated)" : "");
+ Utils::SNPrint((buffer + num_chars), (len - num_chars), FORMAT1, i,
+ info.handler_pc_offset, num_types, info.outer_try_index,
+ info.is_generated ? "(generated)" : "");
for (int k = 0; k < num_types; k++) {
type ^= handled_types.At(k);
- num_chars += OS::SNPrint((buffer + num_chars), (len - num_chars), FORMAT2,
- k, type.ToCString());
+ num_chars += Utils::SNPrint((buffer + num_chars), (len - num_chars),
+ FORMAT2, k, type.ToCString());
}
}
return buffer;
@@ -18315,11 +18315,12 @@
"TypeParameter: name %s; index: %d; function: %s; bound: %s";
const Function& function = Function::Handle(parameterized_function());
const char* fun_cstr = String::Handle(function.name()).ToCString();
- intptr_t len =
- OS::SNPrint(NULL, 0, format, name_cstr, index(), fun_cstr, bound_cstr) +
- 1;
+ intptr_t len = Utils::SNPrint(NULL, 0, format, name_cstr, index(), fun_cstr,
+ bound_cstr) +
+ 1;
char* chars = Thread::Current()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, format, name_cstr, index(), fun_cstr, bound_cstr);
+ Utils::SNPrint(chars, len, format, name_cstr, index(), fun_cstr,
+ bound_cstr);
return chars;
} else {
const char* format =
@@ -18327,11 +18328,12 @@
const Class& cls = Class::Handle(parameterized_class());
const char* cls_cstr =
cls.IsNull() ? " null" : String::Handle(cls.Name()).ToCString();
- intptr_t len =
- OS::SNPrint(NULL, 0, format, name_cstr, index(), cls_cstr, bound_cstr) +
- 1;
+ intptr_t len = Utils::SNPrint(NULL, 0, format, name_cstr, index(), cls_cstr,
+ bound_cstr) +
+ 1;
char* chars = Thread::Current()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, format, name_cstr, index(), cls_cstr, bound_cstr);
+ Utils::SNPrint(chars, len, format, name_cstr, index(), cls_cstr,
+ bound_cstr);
return chars;
}
}
@@ -18564,12 +18566,12 @@
const char* type_param_cstr = String::Handle(type_param.name()).ToCString();
const Class& cls = Class::Handle(type_param.parameterized_class());
const char* cls_cstr = String::Handle(cls.Name()).ToCString();
- intptr_t len = OS::SNPrint(NULL, 0, format, type_cstr, bound_cstr,
- type_param_cstr, cls_cstr) +
+ intptr_t len = Utils::SNPrint(NULL, 0, format, type_cstr, bound_cstr,
+ type_param_cstr, cls_cstr) +
1;
char* chars = Thread::Current()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, format, type_cstr, bound_cstr, type_param_cstr,
- cls_cstr);
+ Utils::SNPrint(chars, len, format, type_cstr, bound_cstr, type_param_cstr,
+ cls_cstr);
return chars;
}
@@ -18592,9 +18594,10 @@
const char* first_mixin_type_cstr =
String::Handle(AbstractType::Handle(MixinTypeAt(0)).Name()).ToCString();
intptr_t len =
- OS::SNPrint(NULL, 0, format, super_type_cstr, first_mixin_type_cstr) + 1;
+ Utils::SNPrint(NULL, 0, format, super_type_cstr, first_mixin_type_cstr) +
+ 1;
char* chars = Thread::Current()->zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, format, super_type_cstr, first_mixin_type_cstr);
+ Utils::SNPrint(chars, len, format, super_type_cstr, first_mixin_type_cstr);
return chars;
}
@@ -20785,12 +20788,12 @@
Heap::Space space) {
va_list args_copy;
va_copy(args_copy, args);
- intptr_t len = OS::VSNPrint(NULL, 0, format, args_copy);
+ intptr_t len = Utils::VSNPrint(NULL, 0, format, args_copy);
va_end(args_copy);
Zone* zone = Thread::Current()->zone();
char* buffer = zone->Alloc<char>(len + 1);
- OS::VSNPrint(buffer, (len + 1), format, args);
+ Utils::VSNPrint(buffer, (len + 1), format, args);
return String::New(buffer, space);
}
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index 056a349..0dd75a3 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -1807,7 +1807,7 @@
// Make sure to cause symbol table overflow.
for (int i = 0; i < 1024; i++) {
char buf[256];
- OS::SNPrint(buf, sizeof(buf), "%d", i);
+ Utils::SNPrint(buf, sizeof(buf), "%d", i);
Symbols::New(thread, buf);
}
eins = Symbols::New(thread, "Eins");
@@ -1911,20 +1911,20 @@
static void TestIllegalArrayLength(intptr_t length) {
char buffer[1024];
- OS::SNPrint(buffer, sizeof(buffer),
- "main() {\n"
- " new List(%" Pd
- ");\n"
- "}\n",
- length);
+ Utils::SNPrint(buffer, sizeof(buffer),
+ "main() {\n"
+ " new List(%" Pd
+ ");\n"
+ "}\n",
+ length);
Dart_Handle lib = TestCase::LoadTestScript(buffer, NULL);
EXPECT_VALID(lib);
Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
- OS::SNPrint(buffer, sizeof(buffer),
- "Unhandled exception:\n"
- "RangeError (length): Invalid value: "
- "Not in range 0..%" Pd ", inclusive: %" Pd,
- Array::kMaxElements, length);
+ Utils::SNPrint(buffer, sizeof(buffer),
+ "Unhandled exception:\n"
+ "RangeError (length): Invalid value: "
+ "Not in range 0..%" Pd ", inclusive: %" Pd,
+ Array::kMaxElements, length);
EXPECT_ERROR(result, buffer);
}
@@ -1942,12 +1942,12 @@
TEST_CASE(ArrayLengthMaxElements) {
char buffer[1024];
- OS::SNPrint(buffer, sizeof(buffer),
- "main() {\n"
- " return new List(%" Pd
- ");\n"
- "}\n",
- Array::kMaxElements);
+ Utils::SNPrint(buffer, sizeof(buffer),
+ "main() {\n"
+ " return new List(%" Pd
+ ");\n"
+ "}\n",
+ Array::kMaxElements);
Dart_Handle lib = TestCase::LoadTestScript(buffer, NULL);
EXPECT_VALID(lib);
Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
@@ -1964,17 +1964,17 @@
static void TestIllegalTypedDataLength(const char* class_name,
intptr_t length) {
char buffer[1024];
- OS::SNPrint(buffer, sizeof(buffer),
- "import 'dart:typed_data';\n"
- "main() {\n"
- " new %s(%" Pd
- ");\n"
- "}\n",
- class_name, length);
+ Utils::SNPrint(buffer, sizeof(buffer),
+ "import 'dart:typed_data';\n"
+ "main() {\n"
+ " new %s(%" Pd
+ ");\n"
+ "}\n",
+ class_name, length);
Dart_Handle lib = TestCase::LoadTestScript(buffer, NULL);
EXPECT_VALID(lib);
Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
- OS::SNPrint(buffer, sizeof(buffer), "%" Pd, length);
+ Utils::SNPrint(buffer, sizeof(buffer), "%" Pd, length);
EXPECT_ERROR(result, "Invalid argument(s)");
EXPECT_ERROR(result, buffer);
}
@@ -1995,13 +1995,13 @@
TEST_CASE(Int8ListLengthMaxElements) {
const intptr_t max_elements = TypedData::MaxElements(kTypedDataInt8ArrayCid);
char buffer[1024];
- OS::SNPrint(buffer, sizeof(buffer),
- "import 'dart:typed_data';\n"
- "main() {\n"
- " return new Int8List(%" Pd
- ");\n"
- "}\n",
- max_elements);
+ Utils::SNPrint(buffer, sizeof(buffer),
+ "import 'dart:typed_data';\n"
+ "main() {\n"
+ " return new Int8List(%" Pd
+ ");\n"
+ "}\n",
+ max_elements);
Dart_Handle lib = TestCase::LoadTestScript(buffer, NULL);
EXPECT_VALID(lib);
Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
diff --git a/runtime/vm/os.h b/runtime/vm/os.h
index ee37e15..1fde4da 100644
--- a/runtime/vm/os.h
+++ b/runtime/vm/os.h
@@ -91,33 +91,10 @@
// Returns the current program counter.
static uintptr_t GetProgramCounter();
- // Not all platform support strndup.
- static char* StrNDup(const char* s, intptr_t n);
- static intptr_t StrNLen(const char* s, intptr_t n);
-
// Print formatted output to stdout/stderr for debugging.
static void Print(const char* format, ...) PRINTF_ATTRIBUTE(1, 2);
static void PrintErr(const char* format, ...) PRINTF_ATTRIBUTE(1, 2);
static void VFPrint(FILE* stream, const char* format, va_list args);
- // Print formatted output info a buffer.
- //
- // Does not write more than size characters (including the trailing '\0').
- //
- // Returns the number of characters (excluding the trailing '\0')
- // that would been written if the buffer had been big enough. If
- // the return value is greater or equal than the given size then the
- // output has been truncated. The return value is never negative.
- //
- // The buffer will always be terminated by a '\0', unless the buffer
- // is of size 0. The buffer might be NULL if the size is 0.
- //
- // This specification conforms to C99 standard which is implemented
- // by glibc 2.1+ with one exception: the C99 standard allows a
- // negative return value. We will terminate the vm rather than let
- // that occur.
- static int SNPrint(char* str, size_t size, const char* format, ...)
- PRINTF_ATTRIBUTE(3, 4);
- static int VSNPrint(char* str, size_t size, const char* format, va_list args);
// Allocate a string and print formatted output into the buffer.
// Uses the zone for allocation if one if provided, and otherwise uses
diff --git a/runtime/vm/os_android.cc b/runtime/vm/os_android.cc
index 01e4000..0b796ff 100644
--- a/runtime/vm/os_android.cc
+++ b/runtime/vm/os_android.cc
@@ -248,14 +248,6 @@
__builtin_extract_return_addr(__builtin_return_address(0)));
}
-char* OS::StrNDup(const char* s, intptr_t n) {
- return strndup(s, n);
-}
-
-intptr_t OS::StrNLen(const char* s, intptr_t n) {
- return strnlen(s, n);
-}
-
uint16_t HostToBigEndian16(uint16_t value) {
return htobe16(value);
}
@@ -293,22 +285,6 @@
fflush(stream);
}
-int OS::SNPrint(char* str, size_t size, const char* format, ...) {
- va_list args;
- va_start(args, format);
- int retval = VSNPrint(str, size, format, args);
- va_end(args);
- return retval;
-}
-
-int OS::VSNPrint(char* str, size_t size, const char* format, va_list args) {
- int retval = vsnprintf(str, size, format, args);
- if (retval < 0) {
- FATAL1("Fatal error in OS::VSNPrint with format '%s'", format);
- }
- return retval;
-}
-
char* OS::SCreate(Zone* zone, const char* format, ...) {
va_list args;
va_start(args, format);
@@ -321,7 +297,7 @@
// Measure.
va_list measure_args;
va_copy(measure_args, args);
- intptr_t len = VSNPrint(NULL, 0, format, measure_args);
+ intptr_t len = Utils::VSNPrint(NULL, 0, format, measure_args);
va_end(measure_args);
char* buffer;
@@ -335,7 +311,7 @@
// Print.
va_list print_args;
va_copy(print_args, args);
- VSNPrint(buffer, len + 1, format, print_args);
+ Utils::VSNPrint(buffer, len + 1, format, print_args);
va_end(print_args);
return buffer;
}
diff --git a/runtime/vm/os_fuchsia.cc b/runtime/vm/os_fuchsia.cc
index abdae63..24a5608 100644
--- a/runtime/vm/os_fuchsia.cc
+++ b/runtime/vm/os_fuchsia.cc
@@ -176,14 +176,6 @@
__builtin_extract_return_addr(__builtin_return_address(0)));
}
-char* OS::StrNDup(const char* s, intptr_t n) {
- return strndup(s, n);
-}
-
-intptr_t OS::StrNLen(const char* s, intptr_t n) {
- return strnlen(s, n);
-}
-
void OS::Print(const char* format, ...) {
va_list args;
va_start(args, format);
@@ -196,22 +188,6 @@
fflush(stream);
}
-int OS::SNPrint(char* str, size_t size, const char* format, ...) {
- va_list args;
- va_start(args, format);
- int retval = VSNPrint(str, size, format, args);
- va_end(args);
- return retval;
-}
-
-int OS::VSNPrint(char* str, size_t size, const char* format, va_list args) {
- int retval = vsnprintf(str, size, format, args);
- if (retval < 0) {
- FATAL1("Fatal error in OS::VSNPrint with format '%s'", format);
- }
- return retval;
-}
-
char* OS::SCreate(Zone* zone, const char* format, ...) {
va_list args;
va_start(args, format);
@@ -224,7 +200,7 @@
// Measure.
va_list measure_args;
va_copy(measure_args, args);
- intptr_t len = VSNPrint(NULL, 0, format, measure_args);
+ intptr_t len = Utils::VSNPrint(NULL, 0, format, measure_args);
va_end(measure_args);
char* buffer;
@@ -238,7 +214,7 @@
// Print.
va_list print_args;
va_copy(print_args, args);
- VSNPrint(buffer, len + 1, format, print_args);
+ Utils::VSNPrint(buffer, len + 1, format, print_args);
va_end(print_args);
return buffer;
}
diff --git a/runtime/vm/os_linux.cc b/runtime/vm/os_linux.cc
index e1b1621..4a4bf3d 100644
--- a/runtime/vm/os_linux.cc
+++ b/runtime/vm/os_linux.cc
@@ -258,14 +258,6 @@
__builtin_extract_return_addr(__builtin_return_address(0)));
}
-char* OS::StrNDup(const char* s, intptr_t n) {
- return strndup(s, n);
-}
-
-intptr_t OS::StrNLen(const char* s, intptr_t n) {
- return strnlen(s, n);
-}
-
void OS::Print(const char* format, ...) {
va_list args;
va_start(args, format);
@@ -278,23 +270,6 @@
fflush(stream);
}
-int OS::SNPrint(char* str, size_t size, const char* format, ...) {
- va_list args;
- va_start(args, format);
- int retval = VSNPrint(str, size, format, args);
- va_end(args);
- return retval;
-}
-
-int OS::VSNPrint(char* str, size_t size, const char* format, va_list args) {
- MSAN_UNPOISON(str, size);
- int retval = vsnprintf(str, size, format, args);
- if (retval < 0) {
- FATAL1("Fatal error in OS::VSNPrint with format '%s'", format);
- }
- return retval;
-}
-
char* OS::SCreate(Zone* zone, const char* format, ...) {
va_list args;
va_start(args, format);
@@ -307,7 +282,7 @@
// Measure.
va_list measure_args;
va_copy(measure_args, args);
- intptr_t len = VSNPrint(NULL, 0, format, measure_args);
+ intptr_t len = Utils::VSNPrint(NULL, 0, format, measure_args);
va_end(measure_args);
char* buffer;
@@ -321,7 +296,7 @@
// Print.
va_list print_args;
va_copy(print_args, args);
- VSNPrint(buffer, len + 1, format, print_args);
+ Utils::VSNPrint(buffer, len + 1, format, print_args);
va_end(print_args);
return buffer;
}
diff --git a/runtime/vm/os_macos.cc b/runtime/vm/os_macos.cc
index 36660e3..0d52e03 100644
--- a/runtime/vm/os_macos.cc
+++ b/runtime/vm/os_macos.cc
@@ -212,44 +212,6 @@
__builtin_extract_return_addr(__builtin_return_address(0)));
}
-char* OS::StrNDup(const char* s, intptr_t n) {
-// strndup has only been added to Mac OS X in 10.7. We are supplying
-// our own copy here if needed.
-#if !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || \
- __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ <= 1060
- intptr_t len = strlen(s);
- if ((n < 0) || (len < 0)) {
- return NULL;
- }
- if (n < len) {
- len = n;
- }
- char* result = reinterpret_cast<char*>(malloc(len + 1));
- if (result == NULL) {
- return NULL;
- }
- result[len] = '\0';
- return reinterpret_cast<char*>(memmove(result, s, len));
-#else // !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || ...
- return strndup(s, n);
-#endif // !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || ...
-}
-
-intptr_t OS::StrNLen(const char* s, intptr_t n) {
-// strnlen has only been added to Mac OS X in 10.7. We are supplying
-// our own copy here if needed.
-#if !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || \
- __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ <= 1060
- intptr_t len = 0;
- while ((len <= n) && (*s != '\0')) {
- s++;
- len++;
- }
- return len;
-#else // !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || ...
- return strnlen(s, n);
-#endif // !defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || ...
-}
void OS::Print(const char* format, ...) {
#if HOST_OS_IOS
@@ -270,22 +232,6 @@
fflush(stream);
}
-int OS::SNPrint(char* str, size_t size, const char* format, ...) {
- va_list args;
- va_start(args, format);
- int retval = VSNPrint(str, size, format, args);
- va_end(args);
- return retval;
-}
-
-int OS::VSNPrint(char* str, size_t size, const char* format, va_list args) {
- int retval = vsnprintf(str, size, format, args);
- if (retval < 0) {
- FATAL1("Fatal error in OS::VSNPrint with format '%s'", format);
- }
- return retval;
-}
-
char* OS::SCreate(Zone* zone, const char* format, ...) {
va_list args;
va_start(args, format);
@@ -298,7 +244,7 @@
// Measure.
va_list measure_args;
va_copy(measure_args, args);
- intptr_t len = VSNPrint(NULL, 0, format, measure_args);
+ intptr_t len = Utils::VSNPrint(NULL, 0, format, measure_args);
va_end(measure_args);
char* buffer;
@@ -312,7 +258,7 @@
// Print.
va_list print_args;
va_copy(print_args, args);
- VSNPrint(buffer, len + 1, format, print_args);
+ Utils::VSNPrint(buffer, len + 1, format, print_args);
va_end(print_args);
return buffer;
}
diff --git a/runtime/vm/os_test.cc b/runtime/vm/os_test.cc
index 3967bf0..d8be0f7 100644
--- a/runtime/vm/os_test.cc
+++ b/runtime/vm/os_test.cc
@@ -24,16 +24,16 @@
VM_UNIT_TEST_CASE(SNPrint) {
char buffer[256];
int length;
- length = OS::SNPrint(buffer, 10, "%s", "foo");
+ length = Utils::SNPrint(buffer, 10, "%s", "foo");
EXPECT_EQ(3, length);
EXPECT_STREQ("foo", buffer);
- length = OS::SNPrint(buffer, 3, "%s", "foo");
+ length = Utils::SNPrint(buffer, 3, "%s", "foo");
EXPECT_EQ(3, length);
EXPECT_STREQ("fo", buffer);
- length = OS::SNPrint(buffer, 256, "%s%c%d", "foo", 'Z', 42);
+ length = Utils::SNPrint(buffer, 256, "%s%c%d", "foo", 'Z', 42);
EXPECT_EQ(6, length);
EXPECT_STREQ("fooZ42", buffer);
- length = OS::SNPrint(NULL, 0, "foo");
+ length = Utils::SNPrint(NULL, 0, "foo");
EXPECT_EQ(3, length);
}
@@ -41,7 +41,7 @@
VM_UNIT_TEST_CASE(SNPrint_BadArgs) {
int width = kMaxInt32;
int num = 7;
- OS::SNPrint(NULL, 0, "%*d%*d", width, num, width, num);
+ Utils::SNPrint(NULL, 0, "%*d%*d", width, num, width, num);
}
VM_UNIT_TEST_CASE(OsFuncs) {
diff --git a/runtime/vm/os_win.cc b/runtime/vm/os_win.cc
index 75c2245..d8a0a9a 100644
--- a/runtime/vm/os_win.cc
+++ b/runtime/vm/os_win.cc
@@ -237,26 +237,6 @@
return reinterpret_cast<uintptr_t>(_ReturnAddress());
}
-char* OS::StrNDup(const char* s, intptr_t n) {
- intptr_t len = strlen(s);
- if ((n < 0) || (len < 0)) {
- return NULL;
- }
- if (n < len) {
- len = n;
- }
- char* result = reinterpret_cast<char*>(malloc(len + 1));
- if (result == NULL) {
- return NULL;
- }
- result[len] = '\0';
- return reinterpret_cast<char*>(memmove(result, s, len));
-}
-
-intptr_t OS::StrNLen(const char* s, intptr_t n) {
- return strnlen(s, n);
-}
-
void OS::Print(const char* format, ...) {
va_list args;
va_start(args, format);
@@ -269,48 +249,6 @@
fflush(stream);
}
-int OS::SNPrint(char* str, size_t size, const char* format, ...) {
- va_list args;
- va_start(args, format);
- int retval = VSNPrint(str, size, format, args);
- va_end(args);
- return retval;
-}
-
-int OS::VSNPrint(char* str, size_t size, const char* format, va_list args) {
- if (str == NULL || size == 0) {
- int retval = _vscprintf(format, args);
- if (retval < 0) {
- FATAL1("Fatal error in OS::VSNPrint with format '%s'", format);
- }
- return retval;
- }
- va_list args_copy;
- va_copy(args_copy, args);
- int written = _vsnprintf(str, size, format, args_copy);
- va_end(args_copy);
- if (written < 0) {
- // _vsnprintf returns -1 if the number of characters to be written is
- // larger than 'size', so we call _vscprintf which returns the number
- // of characters that would have been written.
- va_list args_retry;
- va_copy(args_retry, args);
- written = _vscprintf(format, args_retry);
- if (written < 0) {
- FATAL1("Fatal error in OS::VSNPrint with format '%s'", format);
- }
- va_end(args_retry);
- }
- // Make sure to zero-terminate the string if the output was
- // truncated or if there was an error.
- // The static cast is safe here as we have already determined that 'written'
- // is >= 0.
- if (static_cast<size_t>(written) >= size) {
- str[size - 1] = '\0';
- }
- return written;
-}
-
char* OS::SCreate(Zone* zone, const char* format, ...) {
va_list args;
va_start(args, format);
@@ -323,7 +261,7 @@
// Measure.
va_list measure_args;
va_copy(measure_args, args);
- intptr_t len = VSNPrint(NULL, 0, format, measure_args);
+ intptr_t len = Utils::VSNPrint(NULL, 0, format, measure_args);
va_end(measure_args);
char* buffer;
@@ -337,7 +275,7 @@
// Print.
va_list print_args;
va_copy(print_args, args);
- VSNPrint(buffer, len + 1, format, print_args);
+ Utils::VSNPrint(buffer, len + 1, format, print_args);
va_end(print_args);
return buffer;
}
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index a144a86..7568b96 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -1752,7 +1752,7 @@
for (; i < desc.PositionalCount(); ++i) {
ParamDesc p;
char name[64];
- OS::SNPrint(name, 64, ":p%" Pd, i);
+ Utils::SNPrint(name, 64, ":p%" Pd, i);
p.name = &String::ZoneHandle(Z, Symbols::New(T, name));
p.type = &Object::dynamic_type();
params.parameters->Add(p);
@@ -11120,7 +11120,7 @@
LocalVariable* Parser::CreateTempConstVariable(TokenPosition token_pos,
const char* s) {
char name[64];
- OS::SNPrint(name, 64, ":%s%" Pd "", s, token_pos.value());
+ Utils::SNPrint(name, 64, ":%s%" Pd "", s, token_pos.value());
LocalVariable* temp = new (Z) LocalVariable(
token_pos, token_pos, String::ZoneHandle(Z, Symbols::New(T, name)),
Object::dynamic_type());
diff --git a/runtime/vm/parser_test.cc b/runtime/vm/parser_test.cc
index 02c0854..bd06546 100644
--- a/runtime/vm/parser_test.cc
+++ b/runtime/vm/parser_test.cc
@@ -219,8 +219,8 @@
const char* function_str =
String::Handle(frame->function().QualifiedUserVisibleName())
.ToCString();
- pos += OS::SNPrint(pos, (kBufferLen - (pos - buffer)), "%s\n%s",
- function_str, var_str);
+ pos += Utils::SNPrint(pos, (kBufferLen - (pos - buffer)), "%s\n%s",
+ function_str, var_str);
delete[] var_str;
}
pos[0] = '\0';
diff --git a/runtime/vm/profiler_service.cc b/runtime/vm/profiler_service.cc
index 7e2e787..9cdfa47 100644
--- a/runtime/vm/profiler_service.cc
+++ b/runtime/vm/profiler_service.cc
@@ -339,8 +339,8 @@
void ProfileCode::GenerateAndSetSymbolName(const char* prefix) {
const intptr_t kBuffSize = 512;
char buff[kBuffSize];
- OS::SNPrint(&buff[0], kBuffSize - 1, "%s [%" Px ", %" Px ")", prefix, start(),
- end());
+ Utils::SNPrint(&buff[0], kBuffSize - 1, "%s [%" Px ", %" Px ")", prefix,
+ start(), end());
SetName(buff);
}
diff --git a/runtime/vm/resolver_test.cc b/runtime/vm/resolver_test.cc
index a6f5597..7df722a 100644
--- a/runtime/vm/resolver_test.cc
+++ b/runtime/vm/resolver_test.cc
@@ -24,17 +24,17 @@
// Setup a dart class and function.
char script_chars[1024];
- OS::SNPrint(script_chars, sizeof(script_chars),
- "class Base {\n"
- " dynCall() { return 3; }\n"
- " static statCall() { return 4; }\n"
- "\n"
- "}\n"
- "class %s extends Base {\n"
- " %s %s(String s, int i) { return i; }\n"
- "}\n",
- test_class_name, is_static ? "static" : "",
- test_static_function_name);
+ Utils::SNPrint(script_chars, sizeof(script_chars),
+ "class Base {\n"
+ " dynCall() { return 3; }\n"
+ " static statCall() { return 4; }\n"
+ "\n"
+ "}\n"
+ "class %s extends Base {\n"
+ " %s %s(String s, int i) { return i; }\n"
+ "}\n",
+ test_class_name, is_static ? "static" : "",
+ test_static_function_name);
String& url = String::Handle(
zone, is_static ? String::New("dart-test:DartStaticResolve")
diff --git a/runtime/vm/scanner.cc b/runtime/vm/scanner.cc
index 1b146cb..80d6add 100644
--- a/runtime/vm/scanner.cc
+++ b/runtime/vm/scanner.cc
@@ -838,8 +838,9 @@
char utf8_char[5];
int len = Utf8::Encode(c0_, utf8_char);
utf8_char[len] = '\0';
- OS::SNPrint(msg, sizeof(msg), "unexpected character: '%s' (U+%04X)\n",
- utf8_char, c0_);
+ Utils::SNPrint(msg, sizeof(msg),
+ "unexpected character: '%s' (U+%04X)\n", utf8_char,
+ c0_);
ErrorMsg(msg);
ReadChar();
}
diff --git a/runtime/vm/service_test.cc b/runtime/vm/service_test.cc
index 46424c7..3a53ad4 100644
--- a/runtime/vm/service_test.cc
+++ b/runtime/vm/service_test.cc
@@ -99,13 +99,13 @@
static RawArray* EvalF(Dart_Handle lib, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
- intptr_t len = OS::VSNPrint(NULL, 0, fmt, args);
+ intptr_t len = Utils::VSNPrint(NULL, 0, fmt, args);
va_end(args);
char* buffer = Thread::Current()->zone()->Alloc<char>(len + 1);
va_list args2;
va_start(args2, fmt);
- OS::VSNPrint(buffer, (len + 1), fmt, args2);
+ Utils::VSNPrint(buffer, (len + 1), fmt, args2);
va_end(args2);
return Eval(lib, buffer);
@@ -280,9 +280,9 @@
// Only perform a partial match.
const intptr_t kBufferSize = 512;
char buffer[kBufferSize];
- OS::SNPrint(buffer, kBufferSize - 1,
- "\"fixedId\":true,\"id\":\"code\\/%" Px64 "-%" Px "\",",
- compile_timestamp, entry);
+ Utils::SNPrint(buffer, kBufferSize - 1,
+ "\"fixedId\":true,\"id\":\"code\\/%" Px64 "-%" Px "\",",
+ compile_timestamp, entry);
EXPECT_SUBSTRING(buffer, handler.msg());
}
@@ -601,12 +601,12 @@
uword addr = start_addr + offset;
char buf[1024];
bool ref = offset % 2 == 0;
- OS::SNPrint(buf, sizeof(buf),
- (ref ? "[0, port, '0', '_getObjectByAddress', "
- "['address', 'ref'], ['%" Px "', 'true']]"
- : "[0, port, '0', '_getObjectByAddress', "
- "['address'], ['%" Px "']]"),
- addr);
+ Utils::SNPrint(buf, sizeof(buf),
+ (ref ? "[0, port, '0', '_getObjectByAddress', "
+ "['address', 'ref'], ['%" Px "', 'true']]"
+ : "[0, port, '0', '_getObjectByAddress', "
+ "['address'], ['%" Px "']]"),
+ addr);
service_msg = Eval(lib, buf);
HandleIsolateMessage(isolate, service_msg);
EXPECT_EQ(MessageHandler::kOK, handler.HandleNextMessage());
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index a03d79f..a906dd7 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -616,9 +616,9 @@
if (!obj_.IsError()) {
const intptr_t kMessageBufferSize = 128;
char message_buffer[kMessageBufferSize];
- OS::SNPrint(message_buffer, kMessageBufferSize,
- "Invalid object %s found in script snapshot",
- obj_.ToCString());
+ Utils::SNPrint(message_buffer, kMessageBufferSize,
+ "Invalid object %s found in script snapshot",
+ obj_.ToCString());
const String& msg = String::Handle(String::New(message_buffer));
obj_ = ApiError::New(msg);
}
@@ -636,9 +636,9 @@
if (PendingBytes() < version_len) {
const intptr_t kMessageBufferSize = 128;
char message_buffer[kMessageBufferSize];
- OS::SNPrint(message_buffer, kMessageBufferSize,
- "No full snapshot version found, expected '%s'",
- expected_version);
+ Utils::SNPrint(message_buffer, kMessageBufferSize,
+ "No full snapshot version found, expected '%s'",
+ expected_version);
// This can also fail while bringing up the VM isolate, so make sure to
// allocate the error message in old space.
const String& msg = String::Handle(String::New(message_buffer, Heap::kOld));
@@ -650,11 +650,11 @@
if (strncmp(version, expected_version, version_len)) {
const intptr_t kMessageBufferSize = 256;
char message_buffer[kMessageBufferSize];
- char* actual_version = OS::StrNDup(version, version_len);
- OS::SNPrint(message_buffer, kMessageBufferSize,
- "Wrong %s snapshot version, expected '%s' found '%s'",
- (Snapshot::IsFull(kind_)) ? "full" : "script", expected_version,
- actual_version);
+ char* actual_version = Utils::StrNDup(version, version_len);
+ Utils::SNPrint(message_buffer, kMessageBufferSize,
+ "Wrong %s snapshot version, expected '%s' found '%s'",
+ (Snapshot::IsFull(kind_)) ? "full" : "script",
+ expected_version, actual_version);
free(actual_version);
// This can also fail while bringing up the VM isolate, so make sure to
// allocate the error message in old space.
@@ -669,17 +669,17 @@
const char* features = reinterpret_cast<const char*>(CurrentBufferAddress());
ASSERT(features != NULL);
- intptr_t buffer_len = OS::StrNLen(features, PendingBytes());
+ intptr_t buffer_len = Utils::StrNLen(features, PendingBytes());
if ((buffer_len != expected_len) ||
strncmp(features, expected_features, expected_len)) {
const intptr_t kMessageBufferSize = 256;
char message_buffer[kMessageBufferSize];
char* actual_features =
- OS::StrNDup(features, buffer_len < 128 ? buffer_len : 128);
- OS::SNPrint(message_buffer, kMessageBufferSize,
- "Snapshot not compatible with the current VM configuration: "
- "the snapshot requires '%s' but the VM has '%s'",
- actual_features, expected_features);
+ Utils::StrNDup(features, buffer_len < 128 ? buffer_len : 128);
+ Utils::SNPrint(message_buffer, kMessageBufferSize,
+ "Snapshot not compatible with the current VM configuration: "
+ "the snapshot requires '%s' but the VM has '%s'",
+ actual_features, expected_features);
free(const_cast<char*>(expected_features));
free(actual_features);
// This can also fail while bringing up the VM isolate, so make sure to
diff --git a/runtime/vm/symbols.cc b/runtime/vm/symbols.cc
index f14c39b..2e8c7db 100644
--- a/runtime/vm/symbols.cc
+++ b/runtime/vm/symbols.cc
@@ -654,12 +654,12 @@
va_list args) {
va_list args_copy;
va_copy(args_copy, args);
- intptr_t len = OS::VSNPrint(NULL, 0, format, args_copy);
+ intptr_t len = Utils::VSNPrint(NULL, 0, format, args_copy);
va_end(args_copy);
Zone* zone = Thread::Current()->zone();
char* buffer = zone->Alloc<char>(len + 1);
- OS::VSNPrint(buffer, (len + 1), format, args);
+ Utils::VSNPrint(buffer, (len + 1), format, args);
return Symbols::New(thread, buffer);
}
diff --git a/runtime/vm/thread_test.cc b/runtime/vm/thread_test.cc
index 492e26d..b00cd0a 100644
--- a/runtime/vm/thread_test.cc
+++ b/runtime/vm/thread_test.cc
@@ -502,17 +502,17 @@
const intptr_t kLoopCount = 1234567890;
#endif // USING_SIMULATOR
char buffer[1024];
- OS::SNPrint(buffer, sizeof(buffer),
- "import 'dart:developer';\n"
- "int dummy = 0;\n"
- "main() {\n"
- " new UserTag('foo').makeCurrent();\n"
- " for (dummy = 0; dummy < %" Pd
- "; ++dummy) {\n"
- " dummy += (dummy & 1);\n"
- " }\n"
- "}\n",
- kLoopCount);
+ Utils::SNPrint(buffer, sizeof(buffer),
+ "import 'dart:developer';\n"
+ "int dummy = 0;\n"
+ "main() {\n"
+ " new UserTag('foo').makeCurrent();\n"
+ " for (dummy = 0; dummy < %" Pd
+ "; ++dummy) {\n"
+ " dummy += (dummy & 1);\n"
+ " }\n"
+ "}\n",
+ kLoopCount);
Dart_Handle lib = TestCase::LoadTestScript(buffer, NULL);
EXPECT_VALID(lib);
Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
diff --git a/runtime/vm/timeline.cc b/runtime/vm/timeline.cc
index ce1530a..be11b0e 100644
--- a/runtime/vm/timeline.cc
+++ b/runtime/vm/timeline.cc
@@ -355,11 +355,11 @@
ASSERT(i < length_);
va_list args2;
va_copy(args2, args);
- intptr_t len = OS::VSNPrint(NULL, 0, fmt, args);
+ intptr_t len = Utils::VSNPrint(NULL, 0, fmt, args);
va_end(args);
char* buffer = reinterpret_cast<char*>(malloc(len + 1));
- OS::VSNPrint(buffer, (len + 1), fmt, args2);
+ Utils::VSNPrint(buffer, (len + 1), fmt, args2);
va_end(args2);
SetArgument(i, name, buffer);
diff --git a/runtime/vm/timeline_android.cc b/runtime/vm/timeline_android.cc
index 44e1cb0..b43c508 100644
--- a/runtime/vm/timeline_android.cc
+++ b/runtime/vm/timeline_android.cc
@@ -49,17 +49,17 @@
int64_t pid = OS::ProcessId();
switch (event->event_type()) {
case TimelineEvent::kBegin: {
- length = OS::SNPrint(buffer, buffer_size, "B|%" Pd64 "|%s", pid,
- event->label());
+ length = Utils::SNPrint(buffer, buffer_size, "B|%" Pd64 "|%s", pid,
+ event->label());
} break;
case TimelineEvent::kEnd: {
- length = OS::SNPrint(buffer, buffer_size, "E");
+ length = Utils::SNPrint(buffer, buffer_size, "E");
} break;
case TimelineEvent::kCounter: {
if (event->arguments_length() > 0) {
// We only report the first counter value.
- length = OS::SNPrint(buffer, buffer_size, "C|%" Pd64 "|%s|%s", pid,
- event->label(), event->arguments()[0].value);
+ length = Utils::SNPrint(buffer, buffer_size, "C|%" Pd64 "|%s|%s", pid,
+ event->label(), event->arguments()[0].value);
}
}
default:
diff --git a/runtime/vm/timeline_linux.cc b/runtime/vm/timeline_linux.cc
index 0ced816..b244ecd 100644
--- a/runtime/vm/timeline_linux.cc
+++ b/runtime/vm/timeline_linux.cc
@@ -49,17 +49,17 @@
int64_t pid = OS::ProcessId();
switch (event->event_type()) {
case TimelineEvent::kBegin: {
- length = OS::SNPrint(buffer, buffer_size, "B|%" Pd64 "|%s", pid,
- event->label());
+ length = Utils::SNPrint(buffer, buffer_size, "B|%" Pd64 "|%s", pid,
+ event->label());
} break;
case TimelineEvent::kEnd: {
- length = OS::SNPrint(buffer, buffer_size, "E");
+ length = Utils::SNPrint(buffer, buffer_size, "E");
} break;
case TimelineEvent::kCounter: {
if (event->arguments_length() > 0) {
// We only report the first counter value.
- length = OS::SNPrint(buffer, buffer_size, "C|%" Pd64 "|%s|%s", pid,
- event->label(), event->arguments()[0].value);
+ length = Utils::SNPrint(buffer, buffer_size, "C|%" Pd64 "|%s|%s", pid,
+ event->label(), event->arguments()[0].value);
}
}
default:
diff --git a/runtime/vm/uri.cc b/runtime/vm/uri.cc
index 0e93b57..67fbcbf 100644
--- a/runtime/vm/uri.cc
+++ b/runtime/vm/uri.cc
@@ -100,7 +100,7 @@
buffer[buffer_pos] = escaped_value;
buffer_pos++;
} else {
- OS::SNPrint(buffer + buffer_pos, 4, "%%%02X", escaped_value);
+ Utils::SNPrint(buffer + buffer_pos, 4, "%%%02X", escaped_value);
buffer_pos += 3;
}
pos += 3;
@@ -114,7 +114,7 @@
buffer_pos++;
} else {
// Escape funky characters.
- OS::SNPrint(buffer + buffer_pos, 4, "%%%02X", c);
+ Utils::SNPrint(buffer + buffer_pos, 4, "%%%02X", c);
buffer_pos += 3;
}
pos++;
diff --git a/runtime/vm/zone_text_buffer.cc b/runtime/vm/zone_text_buffer.cc
index 43a90e7..5754b11 100644
--- a/runtime/vm/zone_text_buffer.cc
+++ b/runtime/vm/zone_text_buffer.cc
@@ -25,7 +25,7 @@
va_start(args, format);
intptr_t remaining = capacity_ - length_;
ASSERT(remaining >= 0);
- intptr_t len = OS::VSNPrint(buffer_ + length_, remaining, format, args);
+ intptr_t len = Utils::VSNPrint(buffer_ + length_, remaining, format, args);
va_end(args);
if (len >= remaining) {
EnsureCapacity(len);
@@ -33,7 +33,8 @@
ASSERT(remaining > len);
va_list args2;
va_start(args2, format);
- intptr_t len2 = OS::VSNPrint(buffer_ + length_, remaining, format, args2);
+ intptr_t len2 =
+ Utils::VSNPrint(buffer_ + length_, remaining, format, args2);
va_end(args2);
ASSERT(len == len2);
}
diff --git a/samples/sample_extension/test/sample_extension_test_helper.dart b/samples/sample_extension/test/sample_extension_test_helper.dart
index 08d5191..6141a88 100644
--- a/samples/sample_extension/test/sample_extension_test_helper.dart
+++ b/samples/sample_extension/test/sample_extension_test_helper.dart
@@ -33,7 +33,7 @@
}
}
-Future run(String program, List arguments) async {
+Future run(String program, List<String> arguments) async {
print("+ $program ${arguments.join(' ')}");
ProcessResult result = await Process.run(program, arguments);
if (result.exitCode != 0) {
diff --git a/samples/samples.status b/samples/samples.status
index f72813e..3e8b4db 100644
--- a/samples/samples.status
+++ b/samples/samples.status
@@ -28,11 +28,6 @@
[ $compiler == dart2js && $runtime == none ]
*: Fail, Pass # TODO(ahe): Triage these tests.
-[ $compiler == dartk && $strong ]
-sample_extension/test/sample_extension_app_snapshot_test: RuntimeError
-sample_extension/test/sample_extension_script_snapshot_test: RuntimeError
-sample_extension/test/sample_extension_test: RuntimeError
-
[ $compiler == none && $mode == debug && $runtime == vm && $system == windows ]
sample_extension/test/sample_extension_app_snapshot_test: Pass, RuntimeError # Issue 28842
diff --git a/sdk/api_readme.md b/sdk/api_readme.md
index c723990..3e5990dd 100644
--- a/sdk/api_readme.md
+++ b/sdk/api_readme.md
@@ -1,31 +1,32 @@
-Welcome to the Dart API reference documentation, covering the official Dart API
+Welcome to the Dart API reference documentation, covering the core Dart API
libraries. Some of the most fundamental Dart libraries include:
- * [dart:core](dart-core/dart-core-library.html): Core functionality such as strings, numbers, collections, errors, dates, and URIs.
- * [dart:html](dart-html/dart-html-library.html): DOM manipulation for web apps.
- * [dart:io](dart-io/dart-io-library.html): I/O for command-line apps.
+ * [dart:core](dart-core/dart-core-library.html): Core functionality such as
+ strings, numbers, collections, errors, dates, and URIs.
+ * [dart:html](dart-html/dart-html-library.html): DOM manipulation for web apps
+ (available only to web apps).
+ * [dart:io](dart-io/dart-io-library.html): I/O for non-web apps.
Except for `dart:core`, you must import a library before you can use it. Here's
-an example of importing `dart:html` and `dart:math`:
+an example of importing `dart:async` and `dart:math`:
```dart
-import 'dart:html';
+import 'dart:async';
import 'dart:math';
```
-You can install more libraries using the pub package manager. For information
-on finding, using, and publishing libraries with pub, see
-[pub.dartlang.org](https://pub.dartlang.org).
+You can install more libraries using the
+[pub package manager](https://www.dartlang.org/tools/pub).
The main site for learning and using Dart is
-[www.dartlang.org](https://www.dartlang.org). Check out these additional pages:
+[www.dartlang.org](https://www.dartlang.org). Check out these pages:
- * [Tutorials](https://www.dartlang.org/docs/tutorials/)
- * [Programmer's Guide](https://www.dartlang.org/docs/)
- * [Samples](https://www.dartlang.org/samples/)
- * [A Tour of the Dart Libraries](https://www.dartlang.org/docs/dart-up-and-running/contents/ch03.html)
+ * [Get started](https://www.dartlang.org/guides/get-started)
+ * [Language tour](https://www.dartlang.org/guides/language/language-tour)
+ * [Library tour](https://www.dartlang.org/guides/libraries/library-tour)
+ * [Sample code](https://www.dartlang.org/samples)
-This API reference is automatically generated from the source code in the
-[Dart project](https://github.com/dart-lang/sdk). If you'd like to contribute to
-this documentation, see
+This API reference is automatically generated from source code in the [Dart
+SDK project](https://github.com/dart-lang/sdk).
+If you'd like to give feedback or edit this documentation, see
[Contributing](https://github.com/dart-lang/sdk/wiki/Contributing).
diff --git a/sdk/lib/_internal/js_runtime/lib/js_array.dart b/sdk/lib/_internal/js_runtime/lib/js_array.dart
index e8dbab7..563297a 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_array.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_array.dart
@@ -635,17 +635,10 @@
return new ListMapView<E>(this);
}
- Iterable<E> followedBy(Iterable<E> other) sync* {
- yield* this;
- yield* other;
- }
+ Iterable<E> followedBy(Iterable<E> other) =>
+ new FollowedByIterable<E>.firstEfficient(this, other);
- Iterable<T> whereType<T>() sync* {
- for (var i = 0; i < this.length; i++) {
- var element = this[i];
- if (element is T) yield element;
- }
- }
+ Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
List<E> operator +(List<E> other) {
int totalLength = this.length + other.length;
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index 9d06d03..e564c8c 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -1273,9 +1273,12 @@
* 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),
- {dynamic defaultValue(), T orElse()}) {
+ {@deprecated dynamic defaultValue(), T orElse()}) {
_Future<T> future = new _Future();
StreamSubscription subscription;
subscription = this.listen(
@@ -1315,9 +1318,12 @@
* 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),
- {dynamic defaultValue(), T orElse()}) {
+ {@deprecated dynamic defaultValue(), T orElse()}) {
_Future<T> future = new _Future();
T result = null;
bool foundResult = false;
diff --git a/sdk/lib/collection/iterable.dart b/sdk/lib/collection/iterable.dart
index 7d028a4..67bfdd8 100644
--- a/sdk/lib/collection/iterable.dart
+++ b/sdk/lib/collection/iterable.dart
@@ -26,18 +26,19 @@
Iterable<E> where(bool f(E element)) => new WhereIterable<E>(this, f);
- Iterable<T> whereType<T>() sync* {
- for (Object element in this) if (element is T) yield element;
- }
+ Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
Iterable<T> expand<T>(Iterable<T> f(E element)) =>
new ExpandIterable<E, T>(this, f);
- Iterable<E> followedBy(Iterable<E> other) sync* {
- // TODO(lrn): Optimize this (some operations can be more efficient,
- // and the concatenation has efficient length if the source iterables do).
- yield* this;
- yield* other;
+ Iterable<E> followedBy(Iterable<E> other) {
+ // Type workaround because IterableMixin<E> doesn't promote
+ // to EfficientLengthIterable<E>.
+ Iterable<E> self = this;
+ if (self is EfficientLengthIterable<E>) {
+ return new FollowedByIterable<E>.firstEfficient(self, other);
+ }
+ return new FollowedByIterable<E>(this, other);
}
bool contains(Object element) {
diff --git a/sdk/lib/collection/list.dart b/sdk/lib/collection/list.dart
index 57e5ef4..2a5792d 100644
--- a/sdk/lib/collection/list.dart
+++ b/sdk/lib/collection/list.dart
@@ -59,12 +59,8 @@
E elementAt(int index) => this[index];
- Iterable<E> followedBy(Iterable<E> other) sync* {
- for (var i = 0; i < length; i++) {
- yield this[i];
- }
- yield* other;
- }
+ Iterable<E> followedBy(Iterable<E> other) =>
+ new FollowedByIterable<E>.firstEfficient(this, other);
void forEach(void action(E element)) {
int length = this.length;
@@ -195,9 +191,7 @@
Iterable<E> where(bool test(E element)) => new WhereIterable<E>(this, test);
- Iterable<T> whereType<T>() sync* {
- for (var element in this) if (element is T) yield (element as T);
- }
+ Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
Iterable<T> map<T>(T f(E element)) => new MappedListIterable<E, T>(this, f);
diff --git a/sdk/lib/collection/set.dart b/sdk/lib/collection/set.dart
index 5d51dff..71bf718 100644
--- a/sdk/lib/collection/set.dart
+++ b/sdk/lib/collection/set.dart
@@ -58,16 +58,10 @@
Set<R> retype<R>() => Set.castFrom<E, R>(this);
- Iterable<E> followedBy(Iterable<E> other) sync* {
- // TODO(lrn): Optimize this (some operations can be more efficient,
- // and the concatenation has efficient length if the source iterables do).
- yield* this;
- yield* other;
- }
+ Iterable<E> followedBy(Iterable<E> other) =>
+ new FollowedByIterable<E>.firstEfficient(this, other);
- Iterable<T> whereType<T>() sync* {
- for (Object element in this) if (element is T) yield element;
- }
+ Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
void clear() {
removeAll(toList());
diff --git a/sdk/lib/core/iterable.dart b/sdk/lib/core/iterable.dart
index d3cc85b..410b57d 100644
--- a/sdk/lib/core/iterable.dart
+++ b/sdk/lib/core/iterable.dart
@@ -186,11 +186,11 @@
* and, after that, the elements of [other], in the same order as in the
* original iterables.
*/
- Iterable<E> followedBy(Iterable<E> other) sync* {
- // TODO(lrn): Optimize this (some operations can be more efficient,
- // and the concatenation has efficient length if the source iterables do).
- yield* this;
- yield* other;
+ Iterable<E> followedBy(Iterable<E> other) {
+ if (this is EfficientLengthIterable<E>) {
+ return new FollowedByIterable<E>.firstEfficient(this, other);
+ }
+ return new FollowedByIterable<E>(this, other);
}
/**
@@ -236,9 +236,7 @@
* the returned [Iterable] may yield different results,
* if the underlying elements change between iterations.
*/
- Iterable<T> whereType<T>() sync* {
- for (var element in this) if (element is T) yield (element as T);
- }
+ Iterable<T> whereType<T>() => new WhereTypeIterable<T>(this);
/**
* Expands each element of this [Iterable] into zero or more elements.
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index b3d29f9..82e2175 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -29,7 +29,6 @@
import 'dart:_internal' hide Symbol;
import 'dart:html_common';
import 'dart:indexed_db';
-import 'dart:isolate';
import "dart:convert";
import 'dart:math';
import 'dart:_native_typed_data';
@@ -115,18 +114,6 @@
HtmlElement.created() : super.created();
}
-/**
- * Spawn a DOM isolate using the given URI in the same window.
- * This isolate is not concurrent. It runs on the browser thread
- * with full access to the DOM.
- * Note: this API is still evolving and may move to dart:isolate.
- */
-@Experimental()
-Future<Isolate> spawnDomUri(Uri uri, List<String> args, message) {
- // TODO(17738): Implement this.
- throw new UnimplementedError();
-}
-
createCustomUpgrader(Type customElementClass, $this) => $this;
/**
diff --git a/sdk/lib/internal/iterable.dart b/sdk/lib/internal/iterable.dart
index d8941c9..1c11e53 100644
--- a/sdk/lib/internal/iterable.dart
+++ b/sdk/lib/internal/iterable.dart
@@ -767,6 +767,125 @@
E get current => null;
}
+class FollowedByIterable<E> extends Iterable<E> {
+ final Iterable<E> _first;
+ final Iterable<E> _second;
+ FollowedByIterable(this._first, this._second);
+
+ factory FollowedByIterable.firstEfficient(
+ EfficientLengthIterable<E> first, Iterable<E> second) {
+ if (second is EfficientLengthIterable<E>) {
+ return new EfficientLengthFollowedByIterable<E>(first, second);
+ }
+ return new FollowedByIterable<E>(first, second);
+ }
+
+ Iterator<E> get iterator => new FollowedByIterator(_first, _second);
+
+ int get length => _first.length + _second.length;
+ bool get isEmpty => _first.isEmpty && _second.isEmpty;
+ bool get isNotEmpty => _first.isNotEmpty || _second.isNotEmpty;
+
+ // May be more efficient if either iterable is a Set.
+ bool contains(Object value) =>
+ _first.contains(value) || _second.contains(value);
+
+ E get first {
+ var iterator = _first.iterator;
+ if (iterator.moveNext()) return iterator.current;
+ return _second.first;
+ }
+
+ E get last {
+ var iterator = _second.iterator;
+ if (iterator.moveNext()) {
+ E last = iterator.current;
+ while (iterator.moveNext()) last = iterator.current;
+ return last;
+ }
+ return _first.last;
+ }
+
+ // If linear sequences of `followedBy` becomes an issue, we can flatten
+ // into a list of iterables instead of a tree or spine.
+}
+
+class EfficientLengthFollowedByIterable<E> extends FollowedByIterable<E>
+ implements EfficientLengthIterable<E> {
+ EfficientLengthFollowedByIterable(
+ EfficientLengthIterable<E> first, EfficientLengthIterable<E> second)
+ : super(first, second);
+
+ Iterable<E> skip(int count) {
+ int firstLength = _first.length;
+ if (count >= firstLength) return _second.skip(count - firstLength);
+ return new EfficientLengthFollowedByIterable<E>(
+ _first.skip(count), _second);
+ }
+
+ Iterable<E> take(int count) {
+ int firstLength = _first.length;
+ if (count <= firstLength) return _first.take(count);
+ return new EfficientLengthFollowedByIterable<E>(
+ _first, _second.take(count - firstLength));
+ }
+
+ E elementAt(int index) {
+ int firstLength = _first.length;
+ if (index < firstLength) return _first.elementAt(index);
+ return _second.elementAt(index - firstLength);
+ }
+
+ E get first {
+ if (_first.isNotEmpty) return _first.first;
+ return _second.first;
+ }
+
+ E get last {
+ if (_second.isNotEmpty) return _second.last;
+ return _first.last;
+ }
+}
+
+class FollowedByIterator<E> implements Iterator<E> {
+ Iterator<E> _currentIterator;
+ Iterable<E> _nextIterable;
+
+ FollowedByIterator(Iterable<E> first, this._nextIterable)
+ : _currentIterator = first.iterator;
+
+ bool moveNext() {
+ if (_currentIterator.moveNext()) return true;
+ if (_nextIterable != null) {
+ _currentIterator = _nextIterable.iterator;
+ _nextIterable = null;
+ return _currentIterator.moveNext();
+ }
+ return false;
+ }
+
+ E get current => _currentIterator.current;
+}
+
+class WhereTypeIterable<T> extends Iterable<T> {
+ final Iterable<Object> _source;
+ WhereTypeIterable(this._source);
+ Iterator<T> get iterator => new WhereTypeIterator<T>(_source.iterator);
+}
+
+class WhereTypeIterator<T> implements Iterator<T> {
+ final Iterator<Object> _source;
+ WhereTypeIterator(this._source);
+ bool moveNext() {
+ while (_source.moveNext()) {
+ if (_source.current is T) return true;
+ }
+ return false;
+ }
+
+ T get current => _source.current;
+}
+
/**
* Creates errors throw by [Iterable] when the element count is wrong.
*/
diff --git a/sdk/lib/io/io.dart b/sdk/lib/io/io.dart
index ad7e28d..0feb4ba 100644
--- a/sdk/lib/io/io.dart
+++ b/sdk/lib/io/io.dart
@@ -3,22 +3,25 @@
// BSD-style license that can be found in the LICENSE file.
/**
- * File, socket, HTTP, and other I/O support for server applications.
+ * File, socket, HTTP, and other I/O support for non-web applications.
*
- * The I/O library is used for Dart server applications,
- * which run on a stand-alone Dart VM from the command line.
- * *This library does not work in browser-based applications.*
+ * **Important:** Browser-based applications can't use this library.
+ * Only servers, command-line scripts, and Flutter mobile apps can import
+ * and use dart:io.
*
* This library allows you to work with files, directories,
* sockets, processes, HTTP servers and clients, and more.
+ * Many operations related to input and output are asynchronous
+ * and are handled using [Future]s or [Stream]s, both of which
+ * are defined in the [dart:async
+ * library](../dart-async/dart-async-library.html).
*
- * To use this library in your code:
+ * To use the dart:io library in your code:
*
* import 'dart:io';
*
- * *Note:* Many operations related to input and output are asynchronous
- * and are handled using [Future]s or [Stream]s, both of which
- * are defined in the `dart:async` library.
+ * For an introduction to I/O in Dart, see the [dart:io library
+ * tour](https://www.dartlang.org/dart-vm/io-library-tour).
*
* ## File, Directory, and Link
*
@@ -182,14 +185,6 @@
* (the program blocks waiting for user to type information):
*
* String inputText = stdin.readLineSync();
- *
- * ## Other resources
- *
- * For an introduction to I/O in Dart, see the [dart:io section of the library
- * tour](https://www.dartlang.org/docs/dart-up-and-running/ch03.html#dartio---io-for-command-line-apps).
- *
- * To learn more about I/O in Dart, refer to the [tutorial about writing
- * command-line apps](https://www.dartlang.org/docs/tutorials/cmdline/).
*/
library dart.io;
diff --git a/sdk/lib/vmservice/message.dart b/sdk/lib/vmservice/message.dart
index e6083aa..83432dd 100644
--- a/sdk/lib/vmservice/message.dart
+++ b/sdk/lib/vmservice/message.dart
@@ -127,7 +127,7 @@
}
dynamic forwardToJson([Map overloads]) {
- var json = {'jsonrpc': '2.0', 'id': serial};
+ Map<dynamic, dynamic> json = {'jsonrpc': '2.0', 'id': serial};
switch (type) {
case MessageType.Request:
case MessageType.Notification:
diff --git a/tests/co19/co19-kernel.status b/tests/co19/co19-kernel.status
index e4570b3..5b34f75 100644
--- a/tests/co19/co19-kernel.status
+++ b/tests/co19/co19-kernel.status
@@ -2,19 +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.
-[ $compiler == dartk ]
-Language/Expressions/Instance_Creation/Const/canonicalized_t05: RuntimeError
-Language/Expressions/Object_Identity/string_t01: RuntimeError
-Language/Expressions/Strings/adjacent_strings_t02: RuntimeError
-Language/Metadata/before_type_param_t01: RuntimeError
-LibTest/isolate/Isolate/spawnUri_A01_t03: Pass, Timeout
-
-[ $compiler == dartkp ]
-Language/Classes/definition_t23: RuntimeError # New entries after going from kernel-service to batch-mode compilation. Please investigate.
-Language/Mixins/Mixin_Application/syntax_t16: RuntimeError # New entries after going from kernel-service to batch-mode compilation. Please investigate.
-Language/Overview/Scoping/hiding_declaration_t11: Crash, Pass
-Language/Overview/Scoping/hiding_declaration_t12: Crash, Pass
-
[ $compiler == fasta ]
Language/Classes/Constructors/Constant_Constructors/initializer_not_a_constant_t01: MissingCompileTimeError
Language/Classes/Constructors/Constant_Constructors/initializer_not_a_constant_t02: MissingCompileTimeError
@@ -202,101 +189,6 @@
LibTest/typed_data/Uint64List/Uint64List.view_A01_t01: CompileTimeError
LibTest/typed_data/Uint64List/Uint64List.view_A01_t02: CompileTimeError
-[ $arch == simarm && $compiler == dartkp ]
-LibTest/typed_data/Float32x4/operator_division_A01_t02: 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.
-[ $arch == simarm64 && $compiler == dartk && $mode == debug ]
-LibTest/core/DateTime/parse_A01_t02: Crash # Please triage.
-LibTest/core/DateTime/parse_A01_t03: Crash # Please triage.
-LibTest/core/DateTime/parse_A03_t01: Crash # Please triage.
-
-[ $compiler == dartk && $mode == debug ]
-LibTest/isolate/Isolate/spawnUri_A01_t04: Pass, Slow, Timeout
-
-[ $compiler == dartk && $system == windows ]
-Language/Libraries_and_Scripts/top_level_syntax_t06: Pass, Timeout
-Language/Reference/Operator_Precedence/precedence_t03: Pass, Timeout
-
-[ $compiler == dartk && $strong ]
-*: SkipByDesign
-
-# 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.
-[ $compiler == dartk && ($arch == simarm || $arch == simarm64 || $arch == simdbc64) ]
-Language/Classes/definition_t23: RuntimeError # Please triaage.
-Language/Expressions/Spawning_an_Isolate/*: Skip
-Language/Mixins/Mixin_Application/syntax_t16: RuntimeError # Please triaage.
-LibTest/isolate/*/*: Skip
-
-[ $compiler == dartkp && $mode == debug ]
-Language/Functions/External_Functions/not_connected_to_a_body_t01: Crash
-
-[ $compiler == dartkp && $minified ]
-Language/Expressions/Property_Extraction/Getter_Access_and_Method_Extraction/no_such_method_t01: RuntimeError # Compares new Symbol with noSuchMethod actual name.
-
-[ $compiler == dartkp && $strong ]
-*: SkipByDesign
-
-[ $mode == debug && ($compiler == dartk || $compiler == dartkp) ]
-Language/Classes/Constructors/Generative_Constructors/execution_t04: Crash
-Language/Classes/Instance_Variables/constant_t01: Crash
-
-[ $checked && ($compiler == dartk || $compiler == dartkp) ]
-Language/Classes/Constructors/Factories/arguments_type_t01: RuntimeError
-Language/Classes/Constructors/Factories/function_type_t02: Fail # dartbug.com/30527
-Language/Expressions/Constants/exception_t04: Pass
-Language/Expressions/Function_Expressions/static_type_dynamic_async_t03: RuntimeError # dartbgug.com/30667
-Language/Expressions/Function_Expressions/static_type_dynamic_asyncs_t03: RuntimeError # dartbgug.com/30667
-Language/Expressions/Function_Expressions/static_type_dynamic_syncs_t03: RuntimeError # dartbug.com/30667
-Language/Expressions/Function_Expressions/static_type_form_3_async_t03: RuntimeError # dartbgug.com/30667
-Language/Expressions/Function_Expressions/static_type_form_3_asyncs_t03: RuntimeError # dartbgug.com/30667
-Language/Expressions/Function_Expressions/static_type_form_3_syncs_t03: RuntimeError # dartbgug.com/30667
-Language/Generics/malformed_t02: RuntimeError
-Language/Statements/Return/runtime_type_t04: RuntimeError
-Language/Statements/Switch/execution_t01: RuntimeError
-Language/Statements/Switch/type_t01: RuntimeError
-Language/Types/Dynamic_Type_System/malbounded_type_error_t01: RuntimeError
-Language/Types/Parameterized_Types/malbounded_t06: RuntimeError
-Language/Types/Static_Types/malformed_type_t04: RuntimeError
-
[ $compiler == dartk || $compiler == dartkp ]
-Language/Classes/definition_t23: CompileTimeError
-Language/Expressions/Constants/bitwise_operators_t02: Crash
-Language/Expressions/Constants/bitwise_operators_t03: Crash
-Language/Expressions/Constants/bitwise_operators_t04: Crash
-Language/Expressions/Constants/bitwise_operators_t06: Crash
-Language/Expressions/Constants/depending_on_itself_t03: Crash
-Language/Expressions/Constants/math_operators_t04: Crash
-Language/Expressions/Constants/math_operators_t05: Crash
-Language/Expressions/Instance_Creation/New/evaluation_t19: RuntimeError # Issue 31938
-Language/Expressions/Instance_Creation/New/evaluation_t20: RuntimeError # Issue 31938
-Language/Functions/External_Functions/not_connected_to_a_body_t01: RuntimeError # Dartk Issue 28565
-Language/Libraries_and_Scripts/Imports/deferred_import_t01: RuntimeError # Deferred loading kernel issue 28335.
-Language/Libraries_and_Scripts/Imports/same_name_t10: RuntimeError
-Language/Libraries_and_Scripts/Imports/static_type_t01: Skip # No support for deferred libraries.
-Language/Metadata/before_export_t01: RuntimeError # Issue 28434: Kernel IR misses these annotations.
-Language/Metadata/before_import_t01: RuntimeError # Issue 28434: Kernel IR misses these annotations.
-Language/Metadata/before_library_t01: RuntimeError # Issue 28434: Kernel IR misses these annotations.
-Language/Metadata/before_param_t01: RuntimeError # Issue 28434: Kernel IR misses these annotations.
-Language/Metadata/before_param_t02: RuntimeError # Issue 28434: Kernel IR misses these annotations.
-Language/Metadata/before_param_t03: RuntimeError # Issue 28434: Kernel IR misses these annotations.
-Language/Metadata/before_param_t04: RuntimeError # Issue 28434: Kernel IR misses these annotations.
-Language/Metadata/before_param_t05: RuntimeError # Issue 28434: Kernel IR misses these annotations.
-Language/Metadata/before_param_t06: RuntimeError # Issue 28434: Kernel IR misses these annotations.
-Language/Metadata/before_param_t07: RuntimeError # Issue 28434: Kernel IR misses these annotations.
-Language/Metadata/before_param_t08: RuntimeError # Issue 28434: Kernel IR misses these annotations.
-Language/Metadata/before_param_t09: RuntimeError # Issue 28434: Kernel IR misses these annotations.
-Language/Metadata/before_typedef_t01: RuntimeError # Issue 28434: Kernel IR misses these annotations.
-Language/Mixins/Mixin_Application/syntax_t16: CompileTimeError # Issue 25765
-Language/Types/Type_Void/syntax_t01: Pass # Issue 30470
-LibTest/async/DeferredLibrary/DeferredLibrary_A01_t01: Skip # No support for deferred libraries.
-LibTest/isolate/Isolate/spawnUri_A01_t06: Skip
-
-[ $compiler == dartkp || $compiler == fasta ]
-Language/Classes/Superinterfaces/more_than_once_t01: MissingCompileTimeError
-Language/Classes/Superinterfaces/superclass_as_superinterface_t01: MissingCompileTimeError
+*: SkipByDesign
diff --git a/tests/compiler/dart2js/generic_methods/generic_method_test.dart b/tests/compiler/dart2js/generic_methods/generic_method_test.dart
index 668e99c..4138e44 100644
--- a/tests/compiler/dart2js/generic_methods/generic_method_test.dart
+++ b/tests/compiler/dart2js/generic_methods/generic_method_test.dart
@@ -92,6 +92,13 @@
}
}
+class Class4<T> {
+ Function method7<Q>() {
+ foo(T t, Q q) => '';
+ return foo;
+ }
+}
+
// Nested generic local function.
outside<T>() {
nested<T>(T t) => '';
@@ -115,6 +122,8 @@
print('noSuchMethod: Class2.method6<int>');
print('');
}
+ var c = new Class4<bool>();
+ print((c.method7<int>()).runtimeType);
outside();
}
''';
@@ -160,6 +169,7 @@
noSuchMethod: Class2.method6<int>
+(bool, int) => String
''';
main(List<String> args) {
diff --git a/tests/compiler/dart2js/old_frontend/analyze_api_test.dart b/tests/compiler/dart2js/old_frontend/analyze_api_test.dart
index c74aee2..458824e 100644
--- a/tests/compiler/dart2js/old_frontend/analyze_api_test.dart
+++ b/tests/compiler/dart2js/old_frontend/analyze_api_test.dart
@@ -18,25 +18,7 @@
* the error/warning message in the list of white-listings for each file.
*/
// TODO(johnniwinther): Support canonical URIs as keys.
-const Map<String, List<String>> WHITE_LIST = const {
- "sdk/lib/_internal/js_runtime/lib/js_array.dart": const [
- "Method type variables do not have a runtime value.",
- ],
- "sdk/lib/collection/iterable.dart": const [
- "Method type variables do not have a runtime value.",
- ],
- "sdk/lib/collection/list.dart": const [
- "Method type variables do not have a runtime value.",
- "Method type variables are treated as `dynamic` in `as` expressions.",
- ],
- "sdk/lib/collection/set.dart": const [
- "Method type variables do not have a runtime value.",
- ],
- "sdk/lib/core/iterable.dart": const [
- "Method type variables do not have a runtime value.",
- "Method type variables are treated as `dynamic` in `as` expressions.",
- ],
-};
+const Map<String, List<String>> WHITE_LIST = const {};
void main() {
var uriList = new List<Uri>();
diff --git a/tests/compiler/dart2js/old_frontend/diagnose_ambiguous_test.dart b/tests/compiler/dart2js/old_frontend/diagnose_ambiguous_test.dart
index 8af9a96..53538ed 100644
--- a/tests/compiler/dart2js/old_frontend/diagnose_ambiguous_test.dart
+++ b/tests/compiler/dart2js/old_frontend/diagnose_ambiguous_test.dart
@@ -28,12 +28,6 @@
"memory:library.dart:41:47:'hest' is defined here.:info",
"MessageKind.DUPLICATE_IMPORT:"
"memory:main.dart:86:92:Duplicate import of 'hest'.:warning",
- "MessageKind.HIDDEN_WARNINGS:"
- "null:null:null:1 warning(s) suppressed in dart:_interceptors.:hint",
- "MessageKind.HIDDEN_WARNINGS_HINTS:"
- "null:null:null:1 warning(s) and 1 hint(s) suppressed in dart:core.:hint",
- "MessageKind.HIDDEN_WARNINGS_HINTS:"
- "null:null:null:3 warning(s) and 1 hint(s) suppressed in dart:collection.:hint",
"MessageKind.IMPORTED_HERE:"
"memory:main.dart:0:22:'hest' is imported here.:info",
"MessageKind.IMPORTED_HERE:"
diff --git a/tests/compiler/dart2js/old_frontend/duplicate_library_test.dart b/tests/compiler/dart2js/old_frontend/duplicate_library_test.dart
index 44c81c8..0f10f25 100644
--- a/tests/compiler/dart2js/old_frontend/duplicate_library_test.dart
+++ b/tests/compiler/dart2js/old_frontend/duplicate_library_test.dart
@@ -14,7 +14,7 @@
void check(String kind, Iterable<CollectedMessage> messages,
List<MessageKind> expectedMessageKinds) {
- Expect.equals(messages.length, expectedMessageKinds.length,
+ Expect.equals(expectedMessageKinds.length, messages.length,
"Unexpected $kind count: $messages");
int i = 0;
messages.forEach((CollectedMessage message) {
@@ -56,11 +56,7 @@
"""
}, warnings: [
MessageKind.DUPLICATED_LIBRARY_RESOURCE
- ], hints: [
- MessageKind.HIDDEN_WARNINGS,
- MessageKind.HIDDEN_WARNINGS_HINTS,
- MessageKind.HIDDEN_WARNINGS_HINTS,
- ]);
+ ], hints: []);
await test({
'main.dart': """
@@ -79,11 +75,7 @@
"""
}, warnings: [
MessageKind.DUPLICATED_LIBRARY_RESOURCE
- ], hints: [
- MessageKind.HIDDEN_WARNINGS,
- MessageKind.HIDDEN_WARNINGS_HINTS,
- MessageKind.HIDDEN_WARNINGS_HINTS,
- ]);
+ ], hints: []);
await test({
'main.dart': """
@@ -102,11 +94,7 @@
"""
}, warnings: [
MessageKind.DUPLICATED_LIBRARY_RESOURCE
- ], hints: [
- MessageKind.HIDDEN_WARNINGS,
- MessageKind.HIDDEN_WARNINGS_HINTS,
- MessageKind.HIDDEN_WARNINGS_HINTS,
- ]);
+ ], hints: []);
await test({
'main.dart': """
@@ -130,11 +118,7 @@
"""
}, warnings: [
MessageKind.DUPLICATED_LIBRARY_RESOURCE
- ], hints: [
- MessageKind.HIDDEN_WARNINGS,
- MessageKind.HIDDEN_WARNINGS_HINTS,
- MessageKind.HIDDEN_WARNINGS_HINTS,
- ]);
+ ], hints: []);
await test({
'main.dart': """
@@ -148,9 +132,6 @@
"""
}, hints: [
MessageKind.DUPLICATED_RESOURCE,
- MessageKind.HIDDEN_WARNINGS,
- MessageKind.HIDDEN_WARNINGS_HINTS,
- MessageKind.HIDDEN_WARNINGS_HINTS,
]);
await test({
@@ -169,9 +150,5 @@
}, warnings: [
MessageKind.DUPLICATED_LIBRARY_NAME,
MessageKind.DUPLICATED_LIBRARY_NAME
- ], hints: [
- MessageKind.HIDDEN_WARNINGS,
- MessageKind.HIDDEN_WARNINGS_HINTS,
- MessageKind.HIDDEN_WARNINGS_HINTS,
- ]);
+ ], hints: []);
}
diff --git a/tests/corelib_2/corelib_2.status b/tests/corelib_2/corelib_2.status
index e0bcaf1..5384ab4 100644
--- a/tests/corelib_2/corelib_2.status
+++ b/tests/corelib_2/corelib_2.status
@@ -8,6 +8,9 @@
iterable_element_at_test/static: Pass
num_sign_test: Crash, Pass # Issue 31768
+[ $compiler == dart2js ]
+iterable_where_type_test: RuntimeError # issue 31718
+
[ $compiler != dartdevc ]
error_stack_trace_test/static: MissingCompileTimeError
@@ -364,7 +367,15 @@
symbol_test/none: RuntimeError # Issues 11669 and 31936 - throwing const constructors.
unicode_test: RuntimeError # Issue 18061: German double S.
+# ===== dartkp + dart_precompiled + debug status lines =====
+[ $compiler == dartkp && $mode == debug && $runtime == dart_precompiled && $strong ]
+null_nosuchmethod_test/01: Crash # dartbug.com/32377
+null_nosuchmethod_test/none: Crash # dartbug.com/32377
+
# ===== dartkp + dart_precompiled status lines =====
+[ $compiler == dartkp && $mode == debug && $runtime == dart_precompiled && $strong ]
+null_nosuchmethod_test: Crash
+
[ $compiler == dartkp && $runtime == dart_precompiled && $strong ]
apply_test: RuntimeError, OK
iterable_fold_test/02: RuntimeError
diff --git a/tests/corelib_2/iterable_followed_by_test.dart b/tests/corelib_2/iterable_followed_by_test.dart
new file mode 100644
index 0000000..5edf0e3
--- /dev/null
+++ b/tests/corelib_2/iterable_followed_by_test.dart
@@ -0,0 +1,102 @@
+// 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 "dart:collection" show Queue;
+import "dart:typed_data" show Int32List;
+
+import "package:expect/expect.dart";
+
+// Tests behavior of result of an operation on a followedBy iterable.
+test(List expects, Iterable iterable, [String name]) {
+ try {
+ Expect.isFalse(iterable is List, "$name is! List");
+ Expect.isFalse(iterable is Set, "$name is! Set");
+ Expect.isFalse(iterable is Queue, "$name is! Queue");
+ if (expects.isNotEmpty) {
+ Expect.equals(expects.first, iterable.first, "$name: first");
+ Expect.equals(expects.last, iterable.last, "$name: last");
+ } else {
+ Expect.throwsStateError(() => iterable.first, "$name: first");
+ Expect.throwsStateError(() => iterable.last, "$name: last");
+ }
+ var it = iterable.iterator;
+ for (int index = 0; index < expects.length; index++) {
+ Expect.isTrue(it.moveNext(), "$name: has element $index");
+ var expect = expects[index];
+ Expect.equals(expect, it.current, "$name at $index");
+ Expect.equals(
+ expect, iterable.elementAt(index), "$name: elementAt($index)");
+ Expect.isTrue(iterable.contains(expect), "$name:contains $index");
+ }
+ Expect.isFalse(it.moveNext(),
+ "$name: extra element at ${expects.length}: ${it.current}");
+ } on Error {
+ print("Failed during: $name");
+ rethrow;
+ }
+}
+
+// Tests various operations on the a followedBy iterable.
+tests(List<int> expects, Iterable<int> follow, [String name]) {
+ int length = expects.length;
+ test(expects, follow, name);
+ for (int i = 0; i <= length; i++) {
+ test(expects.sublist(i), follow.skip(i), "$name.skip($i)");
+ }
+ for (int i = 0; i <= length; i++) {
+ test(expects.sublist(0, i), follow.take(i), "$name.take($i)");
+ }
+ for (int i = 0; i <= length; i++) {
+ for (int j = 0; j <= length - i; j++) {
+ test(expects.sublist(i, i + j), follow.skip(i).take(j),
+ "$name.skiptake($i,${i+j})");
+ test(expects.sublist(i, i + j), follow.take(i + j).skip(i),
+ "$name.takeskip($i,${i+j})");
+ }
+ }
+}
+
+// Tests various different types of iterables as first and second operand.
+types(List expects, List<int> first, List<int> second, [String name]) {
+ var conversions = <String, Iterable<int> Function(List<int>)>{
+ "const": toConst,
+ "list": toList,
+ "unmod": toUnmodifiable,
+ "set": toSet,
+ "queue": toQueue,
+ "eff-len-iter": toELIter,
+ "non-eff-iter": toNEIter,
+ "typed": toTyped,
+ "keys": toKeys,
+ "values": toValues,
+ };
+ conversions.forEach((n1, c1) {
+ conversions.forEach((n2, c2) {
+ tests(expects, c1(first).followedBy(c2(second)), "$name:$n1/$n2");
+ });
+ });
+}
+
+List<int> toConst(List<int> elements) => elements;
+List<int> toList(List<int> elements) => elements.toList();
+List<int> toUnmodifiable(List<int> elements) =>
+ new List<int>.unmodifiable(elements);
+Set<int> toSet(List<int> elements) => elements.toSet();
+Queue<int> toQueue(List<int> elements) => new Queue<int>.from(elements);
+// Creates an efficient-length iterable.
+Iterable<int> toELIter(List<int> elements) => elements.map<int>((x) => x);
+// Creates a non-efficient-length iterable.
+Iterable<int> toNEIter(List<int> elements) => elements.where((x) => true);
+List<int> toTyped(List<int> elements) => new Int32List.fromList(elements);
+Iterable<int> toKeys(List<int> elements) =>
+ new Map<int, int>.fromIterables(elements, elements).keys;
+Iterable<int> toValues(List<int> elements) =>
+ new Map<int, int>.fromIterables(elements, elements).values;
+
+main() {
+ types(<int>[], const <int>[], const <int>[], "0+0");
+ types(<int>[1, 2, 3, 4], const <int>[], const <int>[1, 2, 3, 4], "0+4");
+ types(<int>[1, 2, 3, 4], const <int>[1, 2], const <int>[3, 4], "2+2");
+ types(<int>[1, 2, 3, 4], const <int>[1, 2, 3, 4], const <int>[], "4+0");
+}
diff --git a/tests/corelib_2/iterable_where_type_test.dart b/tests/corelib_2/iterable_where_type_test.dart
new file mode 100644
index 0000000..8715149
--- /dev/null
+++ b/tests/corelib_2/iterable_where_type_test.dart
@@ -0,0 +1,105 @@
+// 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 "dart:collection" show Queue;
+import "dart:typed_data" show Int32List;
+
+import "package:expect/expect.dart";
+
+// Tests behavior of result of an operation on a followedBy iterable.
+test(List expects, Iterable iterable, [String name]) {
+ try {
+ Expect.isFalse(iterable is List, "$name is! List");
+ Expect.isFalse(iterable is Set, "$name is! Set");
+ Expect.isFalse(iterable is Queue, "$name is! Queue");
+ if (expects.isNotEmpty) {
+ Expect.equals(expects.first, iterable.first, "$name: first");
+ Expect.equals(expects.last, iterable.last, "$name: last");
+ } else {
+ Expect.throwsStateError(() => iterable.first, "$name: first");
+ Expect.throwsStateError(() => iterable.last, "$name: last");
+ }
+ var it = iterable.iterator;
+ for (int index = 0; index < expects.length; index++) {
+ Expect.isTrue(it.moveNext(), "$name: has element $index");
+ var expect = expects[index];
+ Expect.equals(expect, it.current, "$name at $index");
+ Expect.equals(
+ expect, iterable.elementAt(index), "$name: elementAt($index)");
+ Expect.isTrue(iterable.contains(expect), "$name:contains $index");
+ }
+ Expect.isFalse(it.moveNext(),
+ "$name: extra element at ${expects.length}: ${it.current}");
+ } on Error {
+ print("Failed during: $name");
+ rethrow;
+ }
+}
+
+main() {
+ var conversions = <String, Iterable<int> Function(List<int>)>{
+ "const": toConst,
+ "list": toList,
+ "unmod": toUnmodifiable,
+ "set": toSet,
+ "queue": toQueue,
+ "eff-len-iter": toELIter,
+ "non-eff-iter": toNEIter,
+ "typed": toTyped,
+ "keys": toKeys,
+ "values": toValues,
+ };
+ for (var data in [
+ const <int>[],
+ const <int>[1],
+ const <int>[1, 2, 3]
+ ]) {
+ conversions.forEach((name, c) {
+ test(data, c(data).whereType<int>(), "$name#${data.length}.wt<int>");
+ test(data, c(data).whereType<num>(), "$name#${data.length}.wt<num>");
+ test([], c(data).whereType<Null>(), "$name#${data.length}.wt<Null>");
+ });
+ }
+
+ test([1, 0.1], ["a", 1, new Object(), 0.1, null].whereType<num>(), "mixed");
+
+ var o = new Object();
+ var a = new A();
+ var b = new B();
+ var c = new C();
+ var d = new D();
+ var n = null;
+ test([o, a, b, c, d, n], [o, a, b, c, d, n].whereType<Object>(), "Object");
+ test([a, b, c, d], [o, a, b, c, d, n].whereType<A>(), "A");
+ test([b, d], [o, a, b, c, d, n].whereType<B>(), "B");
+ test([c, d], [o, a, b, c, d, n].whereType<C>(), "C");
+ test([d], [o, a, b, c, d, n].whereType<D>(), "D");
+ test([n], [o, a, b, c, d, n].whereType<Null>(), "Null");
+
+ test([d], <B>[d].whereType<C>(), "Unrelated");
+}
+
+class A {}
+
+class B implements A {}
+
+class C implements A {}
+
+class D implements B, C {}
+
+List<int> toConst(List<int> elements) => elements; // Argument is const.
+List<int> toList(List<int> elements) => elements.toList();
+List<int> toUnmodifiable(List<int> elements) =>
+ new List<int>.unmodifiable(elements);
+Set<int> toSet(List<int> elements) => elements.toSet();
+Queue<int> toQueue(List<int> elements) => new Queue<int>.from(elements);
+// Creates an efficient-length iterable.
+Iterable<int> toELIter(List<int> elements) => elements.map<int>((x) => x);
+// Creates a non-efficient-length iterable.
+Iterable<int> toNEIter(List<int> elements) => elements.where((x) => true);
+List<int> toTyped(List<int> elements) => new Int32List.fromList(elements);
+Iterable<int> toKeys(List<int> elements) =>
+ new Map<int, int>.fromIterables(elements, elements).keys;
+Iterable<int> toValues(List<int> elements) =>
+ new Map<int, int>.fromIterables(elements, elements).values;
diff --git a/tests/corelib_2/map_unmodifiable_cast_test.dart b/tests/corelib_2/map_unmodifiable_cast_test.dart
index 9c1e19b..3091337 100644
--- a/tests/corelib_2/map_unmodifiable_cast_test.dart
+++ b/tests/corelib_2/map_unmodifiable_cast_test.dart
@@ -8,45 +8,76 @@
import 'dart:collection';
void main() {
- test(const {1: 37});
- test(new UnmodifiableMapView({1: 37}));
+ testNum(const {1: 37}, "const");
+ testNum(const <num, num>{1: 37}.cast<int, int>(), "const.cast");
+ testNum(const <num, num>{1: 37}.retype<int, int>(), "const.retype");
- test(new UnmodifiableMapView<num, num>(<num, num>{1: 37}));
- test(new UnmodifiableMapView<num, num>(<int, int>{1: 37}));
+ testNum(new UnmodifiableMapView({1: 37}), "unmod");
+ testNum(new UnmodifiableMapView<num, num>(<num, num>{1: 37}), "unmod.cast");
+ testNum(new UnmodifiableMapView<num, num>(<int, int>{1: 37}), "unmod.retype");
- test(new UnmodifiableMapView<num, num>(<num, num>{1: 37}).cast<int, int>());
- test(new UnmodifiableMapView<num, num>(<int, int>{1: 37}).cast<int, int>());
- test(new UnmodifiableMapView<Object, Object>(<num, num>{1: 37})
- .cast<int, int>());
- test(new UnmodifiableMapView<Object, Object>(<int, int>{1: 37})
- .cast<num, num>());
+ testNum(new UnmodifiableMapView<num, num>(<num, num>{1: 37}).cast<int, int>(),
+ "unmodView<num>.cast<int>");
+ testNum(new UnmodifiableMapView<num, num>(<int, int>{1: 37}).cast<int, int>(),
+ "unmodView<int>.cast<int>");
+ testNum(
+ new UnmodifiableMapView<Object, Object>(<num, num>{1: 37})
+ .cast<int, int>(),
+ "unmodView<Object>(num).cast<int>");
+ testNum(
+ new UnmodifiableMapView<Object, Object>(<int, int>{1: 37})
+ .cast<num, num>(),
+ "unmodView<Object>(int).cast<num>");
- test(new UnmodifiableMapView<num, num>(<num, num>{1: 37}).retype<int, int>());
- test(new UnmodifiableMapView<num, num>(<int, int>{1: 37}).retype<int, int>());
- test(new UnmodifiableMapView<Object, Object>(<num, num>{1: 37})
- .retype<int, int>());
- test(new UnmodifiableMapView<Object, Object>(<int, int>{1: 37})
- .retype<num, num>());
+ testNum(
+ new UnmodifiableMapView<num, num>(<num, num>{1: 37}).retype<int, int>(),
+ "unmodView<num>(num).retype<int>");
+ testNum(
+ new UnmodifiableMapView<num, num>(<int, int>{1: 37}).retype<int, int>(),
+ "unmodView<num>(int).retype<int>");
+ testNum(
+ new UnmodifiableMapView<Object, Object>(<num, num>{1: 37})
+ .retype<int, int>(),
+ "unmodView<Object>(num).retype<int>");
+ testNum(
+ new UnmodifiableMapView<Object, Object>(<int, int>{1: 37})
+ .retype<num, num>(),
+ "unmodView<Object>(int).retype<num>");
var m2 = new Map<num, num>.unmodifiable({1: 37});
- test(m2);
- test(m2.cast<int, int>());
+ testNum(m2, "Map<num>.unmod");
+ testNum(m2.cast<int, int>(), "Map<num>.unmod.cast<int>");
+
+ Map<Symbol, dynamic> nsm = new NsmMap().foo(a: 0);
+ test(nsm, #a, 0, "nsm");
+ test(nsm.cast<Object, int>(), #a, 0, "nsm.cast");
+ test(nsm.retype<Object, int>(), #a, 0, "nsm.retype");
}
-void test(Map map) {
- Expect.isTrue(map.containsKey(1));
- Expect.equals(1, map.length);
- Expect.equals(1, map.keys.first);
- Expect.equals(37, map.values.first);
+void testNum(Map<Object, Object> map, String name) {
+ test(map, 1, 37, name);
+}
- Expect.throws(map.clear);
- Expect.throws(() {
- map.remove(1);
- });
- Expect.throws(() {
- map[2] = 42;
- });
- Expect.throws(() {
- map.addAll(<int, int>{2: 42});
- });
+void test(
+ Map<Object, Object> map, Object firstKey, Object firstValue, String name) {
+ Expect.isTrue(map.containsKey(firstKey), "$name.containsKey");
+ Expect.equals(1, map.length, "$name.length");
+ Expect.equals(firstKey, map.keys.first, "$name.keys.first");
+ Expect.equals(firstValue, map.values.first, "$name.values.first");
+
+ Expect.throwsUnsupportedError(map.clear, "$name.clear");
+ Expect.throwsUnsupportedError(() {
+ map.remove(firstKey);
+ }, "$name.remove");
+ Expect.throwsUnsupportedError(() {
+ map[null] = null;
+ }, "$name[]=");
+ Expect.throwsUnsupportedError(() {
+ map.addAll(<Null, Null>{null: null});
+ }, "$name.addAll");
+}
+
+class NsmMap {
+ noSuchMethod(i) => i.namedArguments;
+ foo({a, b, c, d});
}
diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status
index c97a6b0..2d33902 100644
--- a/tests/isolate/isolate.status
+++ b/tests/isolate/isolate.status
@@ -116,52 +116,12 @@
[ $compiler == dart2js && ($runtime == chrome || $runtime == chromeOnAndroid || $runtime == drt || $runtime == ff || $runtime == safari) ]
isolate_stress_test: Pass, Slow # Issue 10697
-# 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.
-[ $compiler == dartk && ($arch == simarm || $arch == simarm64 || $arch == simdbc64) ]
-checked_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-count_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-cross_isolate_message_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-error_at_spawnuri_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-error_exit_at_spawnuri_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-exit_at_spawnuri_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-illegal_msg_function_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-illegal_msg_mirror_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-isolate_complex_messages_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-issue_21398_parent_isolate1_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-issue_21398_parent_isolate_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-issue_24243_parent_isolate_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-mandel_isolate_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-message2_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-message_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-mint_maker_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-nested_spawn2_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-nested_spawn_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-raw_port_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-request_reply_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-spawn_function_custom_class_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-spawn_function_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-spawn_uri_exported_main_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-spawn_uri_missing_from_isolate_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-spawn_uri_missing_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-spawn_uri_multi_test/01: Skip # No support for Isolate.spawnUri in batch-mode atm.
-spawn_uri_multi_test/none: Skip # No support for Isolate.spawnUri in batch-mode atm.
-spawn_uri_nested_vm_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-spawn_uri_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-spawn_uri_vm_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-static_function_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-unresolved_ports_test: Skip # No support for Isolate.spawnUri in batch-mode atm.
-
[ $compiler == none && $runtime == vm && $system == fuchsia ]
*: Skip # Not yet triaged.
[ $compiler == none && ($runtime == flutter || $runtime == vm) ]
scenarios/short_package/short_package_test: Fail, OK # We do not plan to support the tested behavior anyway.
-[ $mode == debug && ($compiler == dartk || $compiler == dartkp) ]
-static_function_test: Skip # Times out. Issue 31855
-
[ $compiler == app_jit || $compiler == none || $compiler == precompiler ]
compile_time_error_test/01: Skip # Issue 12587
kill3_test: Pass, Fail # Bad test: expects total message order
@@ -172,12 +132,7 @@
checked_test: Skip # Unsupported.
[ $compiler == dartk || $compiler == dartkp ]
-deferred_in_isolate2_test: Skip # Timeout. Deferred loading kernel issue 28335.
-deferred_in_isolate_test: Skip # Timeout. Deferred loading kernel issue 28335.
-issue_21398_parent_isolate2_test/01: Skip # Timeout. Deferred loading kernel issue 28335.
-ping_pause_test: Pass, Timeout
-spawn_function_custom_class_test: Pass, Timeout
-spawn_uri_nested_vm_test: Pass, Timeout
+*: Skip # This directory has only Dart1 tests (Dart2 tests are in lib_2/isolate).
[ $compiler != none || $runtime != vm ]
package_config_test: SkipByDesign # Uses Isolate.packageConfig
diff --git a/tests/kernel/kernel.status b/tests/kernel/kernel.status
index d79e280..6d9eea4 100644
--- a/tests/kernel/kernel.status
+++ b/tests/kernel/kernel.status
@@ -12,32 +12,14 @@
[ !$fasta ]
unsorted/loop_test: Skip # This test uses optional new/const.
-[ !$strong ]
-unsorted/invocation_errors_test: RuntimeError
-
-[ $arch == simarm && $compiler == dartkp && $strong ]
-unsorted/invocation_errors_test: CompileTimeError
-unsorted/nsm_dispatcher_test: CompileTimeError
-unsorted/super_mixin_test: CompileTimeError
-unsorted/types_test: RuntimeError
-
-[ $arch == simarm64 && $compiler == dartkp && $strong ]
-unsorted/invocation_errors_test: CompileTimeError
-unsorted/nsm_dispatcher_test: CompileTimeError
-unsorted/super_mixin_test: CompileTimeError
-unsorted/types_test: RuntimeError
-
[ $compiler == dart2analyzer && $runtime == none ]
-unsorted/invocation_errors_test: StaticWarning
unsorted/super_mixin_test: CompileTimeError
[ $compiler == dart2analyzer && $strong ]
*: Skip # Issue 28649
-[ $compiler == dartk && $strong ]
-unsorted/invocation_errors_test: CompileTimeError
-unsorted/nsm_dispatcher_test: CompileTimeError
-unsorted/super_mixin_test: CompileTimeError
+[ $compiler != dartk && $compiler != dartkp ]
+unsorted/invocation_errors_test/00: MissingCompileTimeError # This test has been tuned for dart 2.
unsorted/types_test: RuntimeError
[ $runtime == dart_precompiled && $minified ]
diff --git a/tests/kernel/unsorted/invocation_errors_test.dart b/tests/kernel/unsorted/invocation_errors_test.dart
index 9c9c516..95e3106 100644
--- a/tests/kernel/unsorted/invocation_errors_test.dart
+++ b/tests/kernel/unsorted/invocation_errors_test.dart
@@ -11,6 +11,5 @@
}
main() {
- // Incorrect number of arguments, should be NoSuchMethodError but crashes.
- test0(0, 1);
+ test0(0, 1); //# 00: compile-time error
}
diff --git a/tests/kernel/unsorted/nsm_dispatcher_test.dart b/tests/kernel/unsorted/nsm_dispatcher_test.dart
index add1ece..8a0722a 100644
--- a/tests/kernel/unsorted/nsm_dispatcher_test.dart
+++ b/tests/kernel/unsorted/nsm_dispatcher_test.dart
@@ -19,7 +19,7 @@
}
main() {
- var o = new A();
+ dynamic o = new A();
Expect.isTrue(o.fun() == '|${#fun}|');
Expect.isTrue(o.fun(1) == '|${#fun}|1|');
Expect.isTrue(o.fun(1, 2) == '|${#fun}|1|2|');
diff --git a/tests/kernel/unsorted/super_mixin_test.dart b/tests/kernel/unsorted/super_mixin_test.dart
index 8c04aab..f70b888 100644
--- a/tests/kernel/unsorted/super_mixin_test.dart
+++ b/tests/kernel/unsorted/super_mixin_test.dart
@@ -4,6 +4,17 @@
import 'package:expect/expect.dart';
+class BaseMixin {
+ method(x) {
+ print(x);
+ return x + 'error';
+ }
+
+ set setter(x) {
+ print(x);
+ }
+}
+
class Base {
var field;
@@ -18,7 +29,7 @@
}
}
-class Mixin {
+class Mixin extends BaseMixin {
method(x) {
return super.method(x + 'Mixin');
}
diff --git a/tests/kernel/unsorted/types_test.dart b/tests/kernel/unsorted/types_test.dart
index 0a41f1d..0b989a1 100644
--- a/tests/kernel/unsorted/types_test.dart
+++ b/tests/kernel/unsorted/types_test.dart
@@ -45,13 +45,14 @@
testConstantLiteralTypes() {
Expect.isTrue(const [1] is List);
Expect.isTrue(const [1] is List<int>);
- Expect.isTrue(const [1] is List<String>);
+ Expect.isTrue(const ["1"] is List<String>);
+ Expect.isTrue(!(const [1] is List<String>));
Expect.isTrue(const <int>[1] is List);
Expect.isTrue(const <int>[1] is List<int>);
Expect.isTrue(!(const <int>[1] is List<String>));
Expect.isTrue(const {"a": 1} is Map);
Expect.isTrue(const {"a": 1} is Map<String, int>);
- Expect.isTrue(const {"a": 1} is Map<int, String>);
+ Expect.isTrue(const {1: "a"} is Map<int, String>);
Expect.isTrue(const <String, int>{"a": 1} is Map);
Expect.isTrue(const <String, int>{"a": 1} is Map<String, int>);
Expect.isTrue(!(const <String, int>{"a": 1} is Map<int, String>));
@@ -60,7 +61,8 @@
testNonConstantLiteralTypes() {
Expect.isTrue([1] is List);
Expect.isTrue([1] is List<int>);
- Expect.isTrue([1] is List<String>);
+ Expect.isTrue(["1"] is List<String>);
+ Expect.isTrue(!([1] is List<String>));
Expect.isTrue(<int>[1] is List);
Expect.isTrue(<int>[1] is List<int>);
Expect.isTrue(!(<int>[1] is List<String>));
@@ -163,8 +165,15 @@
testFunctionTypes() {
fun(int x, String y) => "${x}${y}";
- Expect.isTrue(fun is FunctionType);
- Expect.isTrue(nan is FunctionType);
+ Expect.isTrue(!(fun is FunctionType));
+
+ fun1(num x, Pattern y) => 123;
+ Expect.isTrue(fun1 is FunctionType);
+
+ fun2(num x, String y) => 123;
+ Expect.isTrue(!(fun2 is FunctionType));
+
+ Expect.isTrue(!(nan is FunctionType));
Expect.isTrue(nan is Function);
}
diff --git a/tests/language_2/bug32353_test.dart b/tests/language_2/bug32353_test.dart
new file mode 100644
index 0000000..3284e51
--- /dev/null
+++ b/tests/language_2/bug32353_test.dart
@@ -0,0 +1,36 @@
+// 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.
+// SharedOptions=--supermixin
+
+import 'dart:io' as io;
+
+import "package:expect/expect.dart";
+
+class _LocalDirectory
+ extends _LocalFileSystemEntity<_LocalDirectory, io.Directory>
+ with ForwardingDirectory, DirectoryAddOnsMixin {
+ noSuchMethod(invocation) => null;
+}
+
+abstract class _LocalFileSystemEntity<T extends FileSystemEntity,
+ D extends io.FileSystemEntity> extends ForwardingFileSystemEntity<T, D> {}
+
+abstract class FileSystemEntity implements io.FileSystemEntity {}
+
+abstract class ForwardingFileSystemEntity<T extends FileSystemEntity,
+ D extends io.FileSystemEntity> implements FileSystemEntity {}
+
+abstract class ForwardingDirectory<T extends Directory>
+ extends ForwardingFileSystemEntity<T, io.Directory> implements Directory {
+ get t => T;
+}
+
+abstract class Directory implements FileSystemEntity, io.Directory {}
+
+abstract class DirectoryAddOnsMixin implements Directory {}
+
+main() {
+ var x = new _LocalDirectory();
+ Expect.equals(x.t, _LocalDirectory);
+}
diff --git a/tests/language_2/call_method_implicit_invoke_instance_test.dart b/tests/language_2/call_method_implicit_invoke_instance_test.dart
index aa176fa..fdcb12b 100644
--- a/tests/language_2/call_method_implicit_invoke_instance_test.dart
+++ b/tests/language_2/call_method_implicit_invoke_instance_test.dart
@@ -34,13 +34,13 @@
main() {
new D().test();
// Implicitly invokes D.c1.call(1)
- Expect.equals(new D().c1(1), 2); //# 09: ok
+ Expect.equals(new D().c1(1), 2); //# 05: ok
// Implicitly invokes D.d1.call(1)
- Expect.equals(new D().d1(1), 2); //# 10: ok
+ Expect.equals(new D().d1(1), 2); //# 06: ok
// Implicitly invokes D.c2.call(1)
- Expect.equals(new D().c2(1), 2); //# 11: ok
+ Expect.equals(new D().c2(1), 2); //# 07: ok
// Implicitly invokes D.d2.call(1)
- Expect.equals(new D().d2(1), 2); //# 12: ok
+ Expect.equals(new D().d2(1), 2); //# 08: ok
D d = new D();
// Implicitly invokes d.c1.call(1)
Expect.equals(d.c1(1), 2); //# 09: ok
diff --git a/tests/language_2/language_2_analyzer.status b/tests/language_2/language_2_analyzer.status
index bf6f7d9..c8f9a3e 100644
--- a/tests/language_2/language_2_analyzer.status
+++ b/tests/language_2/language_2_analyzer.status
@@ -1559,6 +1559,10 @@
malformed_test/23: MissingCompileTimeError
malformed_test/24: MissingCompileTimeError
malformed_type_test: MissingCompileTimeError
+mixin_type_parameter_inference_error_test/01: MissingCompileTimeError
+mixin_type_parameter_inference_error_test/02: MissingCompileTimeError
+mixin_type_parameter_inference_error_test/03: MissingCompileTimeError
+mixin_type_parameter_inference_error_test/04: MissingCompileTimeError
mixin_type_parameter_inference_previous_mixin_test/03: MissingCompileTimeError
mixin_type_parameter_inference_previous_mixin_test/04: MissingCompileTimeError
mixin_type_parameter_inference_test/04: MissingCompileTimeError
diff --git a/tests/language_2/language_2_dart2js.status b/tests/language_2/language_2_dart2js.status
index 18de4de..9841b1f 100644
--- a/tests/language_2/language_2_dart2js.status
+++ b/tests/language_2/language_2_dart2js.status
@@ -35,6 +35,7 @@
[ $compiler == dart2js && $runtime == d8 && $dart2js_with_kernel ]
assertion_test: RuntimeError
+bug32353_test: CompileTimeError
implicit_creation/implicit_new_constructor_generic_test: Pass
[ $compiler == dart2js && $runtime == d8 && !$dart2js_with_kernel ]
@@ -2857,7 +2858,9 @@
bad_override_test/06: MissingCompileTimeError
bad_typedef_test/00: Crash # Issue 28214
bug31436_test: RuntimeError
+bug32353_test: CompileTimeError
built_in_identifier_prefix_test: CompileTimeError
+built_in_identifier_type_annotation_test/22: MissingCompileTimeError # Error only in strong mode
call_constructor_on_unresolvable_class_test/01: MissingCompileTimeError
call_constructor_on_unresolvable_class_test/02: MissingCompileTimeError
call_constructor_on_unresolvable_class_test/03: MissingCompileTimeError
@@ -3207,6 +3210,10 @@
integer_division_by_zero_test: RuntimeError # Issue 8301
interface_test/00: MissingCompileTimeError
invalid_override_in_mixin_test/01: MissingCompileTimeError
+invalid_type_argument_count_test/01: MissingCompileTimeError
+invalid_type_argument_count_test/02: MissingCompileTimeError
+invalid_type_argument_count_test/03: MissingCompileTimeError
+invalid_type_argument_count_test/04: MissingCompileTimeError
invocation_mirror2_test: RuntimeError # Issue 6490 (wrong retval).
issue31596_override_test/05: MissingCompileTimeError
issue31596_override_test/06: MissingCompileTimeError
diff --git a/tests/language_2/language_2_dartdevc.status b/tests/language_2/language_2_dartdevc.status
index e41601c..35e3b0a 100644
--- a/tests/language_2/language_2_dartdevc.status
+++ b/tests/language_2/language_2_dartdevc.status
@@ -21,6 +21,7 @@
await_future_test: Pass, Timeout # Issue 29920
bit_operations_test: RuntimeError # No bigints on web.
black_listed_test/none: Fail # Issue 14228
+bug32353_test: RuntimeError
built_in_identifier_prefix_test: CompileTimeError
built_in_identifier_type_annotation_test/22: MissingCompileTimeError # Issue 28816
call_method_as_cast_test/01: RuntimeError
@@ -334,6 +335,7 @@
bad_override_test/03: MissingCompileTimeError
bad_override_test/04: MissingCompileTimeError
bad_override_test/05: MissingCompileTimeError
+bug32353_test: Crash # Issue 32353
built_in_identifier_type_annotation_test/05: RuntimeError # Issue 32194
built_in_identifier_type_annotation_test/none: RuntimeError # Issue 32194
call_method_as_cast_test/01: RuntimeError
diff --git a/tests/language_2/language_2_kernel.status b/tests/language_2/language_2_kernel.status
index d5d228a..9b0ad47 100644
--- a/tests/language_2/language_2_kernel.status
+++ b/tests/language_2/language_2_kernel.status
@@ -11,6 +11,7 @@
# to add them.
[ $compiler == dartkp ]
+bug32353_test: DartkCrash # Issue 32353
class_cycle_test/02: MissingCompileTimeError
class_cycle_test/03: MissingCompileTimeError
duplicate_implements_test/01: MissingCompileTimeError
@@ -20,6 +21,7 @@
mock_writable_final_field_test: RuntimeError # Issue 31424
no_such_method_subtype_test: RuntimeError # Issue 31424
+
[ $fasta ]
abstract_factory_constructor_test/00: MissingCompileTimeError # Issue 32013.
abstract_getter_test/01: MissingCompileTimeError # Issue 32013.
@@ -578,6 +580,7 @@
async_star_cancel_while_paused_test: RuntimeError
async_star_pause_test: Fail, OK
async_star_test/02: RuntimeError # Issue 31402 (Invocation arguments)
+bug32353_test: DartkCrash # Issue 32353
built_in_identifier_prefix_test: CompileTimeError
call_method_must_not_be_field_test/03: RuntimeError # Issue 32265
call_method_must_not_be_getter_test/03: RuntimeError # Issue 32265
@@ -1105,6 +1108,7 @@
super_operator_index8_test: CompileTimeError
super_test: Fail, OK
syntax_test/00: MissingCompileTimeError
+tearoff_dynamic_test: Crash
type_literal_test: RuntimeError
type_promotion_functions_test/02: CompileTimeError # Issue 31537
type_promotion_functions_test/03: CompileTimeError # Issue 31537
diff --git a/tests/language_2/language_2_precompiled.status b/tests/language_2/language_2_precompiled.status
index b9ea3dc..57a932d 100644
--- a/tests/language_2/language_2_precompiled.status
+++ b/tests/language_2/language_2_precompiled.status
@@ -87,6 +87,7 @@
bool_check_test: RuntimeError
bool_condition_check_test: RuntimeError
bug31436_test: RuntimeError
+bug32353_test: RuntimeError
built_in_identifier_prefix_test: CompileTimeError
call_constructor_on_unresolvable_class_test/01: MissingCompileTimeError
call_constructor_on_unresolvable_class_test/02: MissingCompileTimeError
diff --git a/tests/language_2/language_2_vm.status b/tests/language_2/language_2_vm.status
index 726711c..13af2f9 100644
--- a/tests/language_2/language_2_vm.status
+++ b/tests/language_2/language_2_vm.status
@@ -177,6 +177,7 @@
bad_override_test/02: MissingCompileTimeError
bad_override_test/06: MissingCompileTimeError
bug31436_test: RuntimeError
+bug32353_test: RuntimeError
built_in_identifier_prefix_test: CompileTimeError
call_constructor_on_unresolvable_class_test/01: MissingCompileTimeError
call_constructor_on_unresolvable_class_test/02: MissingCompileTimeError
diff --git a/tests/language_2/vm/regress_32322_test.dart b/tests/language_2/vm/regress_32322_test.dart
new file mode 100644
index 0000000..61415d7
--- /dev/null
+++ b/tests/language_2/vm/regress_32322_test.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.
+
+// Verify that optimizing compiler does not perform an illegal code motion
+// past CheckNull instruction.
+
+import "package:expect/expect.dart";
+
+class C {
+ final String padding = "";
+ final String field = "1"; // Note: need padding to hit an object header
+ // of the next object after [null] object when
+ // doing illegal null.field read. Need to hit
+ // object header to cause crash.
+}
+
+int foofoo(C p) {
+ int sum = 0;
+ for (var i = 0; i < 10; i++) {
+ // Note: need redundant instructions in the loop to trigger Canonicalize
+ // after CSE. Canonicalize then would illegally remove the Redefinition.
+ sum += p.field.length;
+ sum += p.field.length;
+ }
+ return sum;
+}
+
+void main() {
+ Expect.equals(20, foofoo(new C()));
+ Expect.throwsNoSuchMethodError(() => foofoo(null));
+}
diff --git a/tests/language_2/vm/regress_flutter_14891_test.dart b/tests/language_2/vm/regress_flutter_14891_test.dart
new file mode 100644
index 0000000..1f410df
--- /dev/null
+++ b/tests/language_2/vm/regress_flutter_14891_test.dart
@@ -0,0 +1,15 @@
+// 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.
+
+// Test verifying that type literals hidden within other constant objects
+// are correctly handled by the AOT compiler.
+
+import "package:expect/expect.dart";
+
+class _ClassOnlyUsedAsTypeLiteral {}
+
+void main() {
+ Expect
+ .isTrue((const [_ClassOnlyUsedAsTypeLiteral]).toString().startsWith('['));
+}
diff --git a/tests/standalone_2/standalone_2_kernel.status b/tests/standalone_2/standalone_2_kernel.status
index 8249747..927f9a0 100644
--- a/tests/standalone_2/standalone_2_kernel.status
+++ b/tests/standalone_2/standalone_2_kernel.status
@@ -66,7 +66,7 @@
[ $compiler == dartk && $strong && ($arch == simarm || $arch == simarm64 || $arch == simdbc64) ]
io/directory_list_sync_test: Timeout, Pass # Please triage.
io/file_blocking_lock_test: Pass, Crash # Please triage.
-io/file_lock_test: RuntimeError # Please triage.
+io/file_lock_test: Slow, Pass
io/platform_resolved_executable_test/05: Pass, RuntimeError # Issue 32134
io/platform_test: RuntimeError # Please triage.
io/test_extension_fail_test: RuntimeError # Please traige.
@@ -81,6 +81,7 @@
*: SkipByDesign
[ $compiler == dartkp && $mode == debug && $runtime == dart_precompiled && $strong ]
+io/compile_all_test: Crash # Issue 32373
io/raw_socket_test: Crash
io/skipping_dart2js_compilations_test: Crash
io/socket_exception_test: Pass, Crash
diff --git a/tools/VERSION b/tools/VERSION
index 9bcd14c..862960b 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 0
PATCH 0
-PRERELEASE 31
+PRERELEASE 32
PRERELEASE_PATCH 0
diff --git a/tools/apps/update_homebrew/lib/update_homebrew.dart b/tools/apps/update_homebrew/lib/update_homebrew.dart
index 49e8da7..350c779 100644
--- a/tools/apps/update_homebrew/lib/update_homebrew.dart
+++ b/tools/apps/update_homebrew/lib/update_homebrew.dart
@@ -170,13 +170,13 @@
end
def shim_script(target)
- <<-EOS.undent
+ <<~EOS
#!/usr/bin/env bash
exec "#{prefix}/#{target}" "\$@"
EOS
end
- def caveats; <<-EOS.undent
+ def caveats; <<~EOS
Please note the path to the Dart SDK:
#{opt_libexec}
@@ -187,7 +187,7 @@
end
test do
- (testpath/"sample.dart").write <<-EOS.undent
+ (testpath/"sample.dart").write <<~EOS
void main() {
print(r"test message");
}
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index fda892d..473c023 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -823,7 +823,6 @@
"dart2js-linux-x64-chrome",
"dart2js-linux-x64-drt",
"dart2js-linux-x64-ff",
- "dart2js-linux-x64-jsshell",
"dart2js-mac-x64-chrome",
"dart2js-mac-x64-safari",
"dart2js-win-x64-chrome",
@@ -1303,28 +1302,27 @@
"arguments": ["--compiler=dart2analyzer", "--use-sdk"]
},
{
- "name": "analyze tests checked",
- "arguments": ["--compiler=dart2analyzer", "--use-sdk", "--checked"]
- },
- {
"name": "analyze pkg tests",
"arguments": ["--compiler=dart2analyzer", "--use-sdk", "pkg"]
},
{
+ "name": "analyze tests checked",
+ "arguments": ["--checked", "--compiler=dart2analyzer", "--use-sdk"]
+ },
+ {
"name": "analyze pkg tests checked",
"arguments": [
+ "--checked",
"--compiler=dart2analyzer",
"--use-sdk",
- "--checked",
"pkg"
]
},
{
- "name": "analyze unit tests",
+ "name": "analyzer unit tests",
"arguments": [
- "--compiler=none",
- "--runtime=vm",
"--checked",
+ "--compiler=none",
"--use-sdk",
"pkg/analyzer"
]
@@ -1332,29 +1330,132 @@
{
"name": "analysis_server unit tests",
"arguments": [
- "--compiler=none",
- "--runtime=vm",
"--checked",
+ "--compiler=none",
"--use-sdk",
"pkg/analysis_server"
]
},
{
- "name": "analysis_cli unit tests",
+ "name": "analyzer_cli unit tests",
"arguments": [
- "--compiler=none",
- "--runtime=vm",
"--checked",
+ "--compiler=none",
"--use-sdk",
"pkg/analyzer_cli"
]
},
{
+ "name": "analyzer_plugin unit tests",
+ "arguments": [
+ "--checked",
+ "--compiler=none",
+ "--use-sdk",
+ "pkg/analyzer_plugin"
+ ]
+ },
+ {
"name": "front end unit tests",
"arguments": [
- "--compiler=none",
- "--runtime=vm",
"--checked",
+ "--compiler=none",
+ "--timeout=120",
+ "--use-sdk",
+ "pkg/front_end"
+ ]
+ }
+ ]
+ },
+ {
+ "builders": [
+ "analyzer-linux-release-strong-hostchecked"
+ ],
+ "meta": {
+ "description": "This configuration is used by the analyzer CQ builder running in strong and hostchecked mode."
+ },
+ "steps": [
+ {
+ "name": "build dart",
+ "script": "tools/build.py",
+ "arguments": ["create_sdk"]
+ },
+ {
+ "name": "analyze tests",
+ "arguments": [
+ "--compiler=dart2analyzer",
+ "--host-checked",
+ "--strong"
+ ]
+ },
+ {
+ "name": "analyze pkg tests",
+ "arguments": [
+ "--compiler=dart2analyzer",
+ "--host-checked",
+ "--strong",
+ "pkg"
+ ]
+ },
+ {
+ "name": "analyze tests checked",
+ "arguments": [
+ "--checked",
+ "--compiler=dart2analyzer",
+ "--host-checked",
+ "--strong"
+ ]
+ },
+ {
+ "name": "analyze pkg tests checked",
+ "arguments": [
+ "--checked",
+ "--compiler=dart2analyzer",
+ "--host-checked",
+ "--strong",
+ "pkg"
+ ]
+ },
+ {
+ "name": "analyzer unit tests",
+ "arguments": [
+ "--checked",
+ "--compiler=none",
+ "--use-sdk",
+ "pkg/analyzer"
+ ]
+ },
+ {
+ "name": "analysis_server unit tests",
+ "arguments": [
+ "--checked",
+ "--compiler=none",
+ "--use-sdk",
+ "pkg/analysis_server"
+ ]
+ },
+ {
+ "name": "analyzer_cli unit tests",
+ "arguments": [
+ "--checked",
+ "--compiler=none",
+ "--use-sdk",
+ "pkg/analyzer_cli"
+ ]
+ },
+ {
+ "name": "analyzer_plugin unit tests",
+ "arguments": [
+ "--checked",
+ "--compiler=none",
+ "--use-sdk",
+ "pkg/analyzer_plugin"
+ ]
+ },
+ {
+ "name": "front end unit tests",
+ "arguments": [
+ "--checked",
+ "--compiler=none",
"--timeout=120",
"--use-sdk",
"pkg/front_end"
@@ -1378,13 +1479,32 @@
"arguments": ["create_sdk"]
},
{
- "name": "analyze tests strong",
- "arguments": ["--compiler=dart2analyzer", "--use-sdk", "--strong"]
+ "name": "analyze tests",
+ "arguments": ["--compiler=dart2analyzer", "--strong", "--use-sdk"]
},
{
"name": "analyze pkg tests",
"arguments": [
"--compiler=dart2analyzer",
+ "--strong",
+ "--use-sdk",
+ "pkg"
+ ]
+ },
+ {
+ "name": "analyze tests checked",
+ "arguments": [
+ "--checked",
+ "--compiler=dart2analyzer",
+ "--strong",
+ "--use-sdk"
+ ]
+ },
+ {
+ "name": "analyze pkg tests checked",
+ "arguments": [
+ "--checked",
+ "--compiler=dart2analyzer",
"--use-sdk",
"--strong",
"pkg"
diff --git a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
index 380bece..dfb08cb 100644
--- a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
@@ -37,7 +37,6 @@
import 'dart:_internal' hide Symbol;
import 'dart:html_common';
import 'dart:indexed_db';
-import 'dart:isolate';
import "dart:convert";
import 'dart:math';
import 'dart:_native_typed_data';
@@ -133,18 +132,6 @@
HtmlElement.created() : super.created();
}
-/**
- * Spawn a DOM isolate using the given URI in the same window.
- * This isolate is not concurrent. It runs on the browser thread
- * with full access to the DOM.
- * Note: this API is still evolving and may move to dart:isolate.
- */
-@Experimental()
-Future<Isolate> spawnDomUri(Uri uri, List<String> args, message) {
- // TODO(17738): Implement this.
- throw new UnimplementedError();
-}
-
createCustomUpgrader(Type customElementClass, $this) => $this;
/**
diff --git a/tools/gardening/bin/results_list.dart b/tools/gardening/bin/results_list.dart
index 688d2b3..b90bb6f 100644
--- a/tools/gardening/bin/results_list.dart
+++ b/tools/gardening/bin/results_list.dart
@@ -18,6 +18,7 @@
argParser.addFlag("csp", negatable: false);
argParser.addFlag("fasta", negatable: false);
argParser.addFlag("dart2js-with-kernel", negatable: false);
+ argParser.addFlag("dart2js-old-frontend", negatable: false);
argParser.addFlag("dart2js-with-kernel-in-ssa", negatable: false);
argParser.addFlag("enable-asserts", negatable: false);
argParser.addFlag("fast-startup", negatable: false);
@@ -53,6 +54,7 @@
argResults["fast-startup"],
0,
argResults["dart2js-with-kernel"],
+ argResults["dart2js-old-frontend"],
argResults["enable-asserts"],
argResults["hot-reload"],
argResults["hot-reload-rollback"],
diff --git a/tools/gardening/lib/src/results/configuration_environment.dart b/tools/gardening/lib/src/results/configuration_environment.dart
index 2640ae3..e2da3fb 100644
--- a/tools/gardening/lib/src/results/configuration_environment.dart
+++ b/tools/gardening/lib/src/results/configuration_environment.dart
@@ -28,6 +28,7 @@
"compiler": new _Variable((c) => c.compiler, Compiler.names),
"csp": new _Variable.bool((c) => c.csp),
"dart2js_with_kernel": new _Variable.bool((c) => c.dart2JsWithKernel),
+ "dart2js_old_frontend": new _Variable.bool((c) => c.dart2JsOldFrontend),
"fasta": new _Variable.bool((c) => c.fasta),
"fast_startup": new _Variable.bool((c) => c.fastStartup),
"enable_asserts": new _Variable.bool((c) => c.enableAsserts),
diff --git a/tools/gardening/lib/src/results/result_json_models.dart b/tools/gardening/lib/src/results/result_json_models.dart
index 5d82d62..9f96d48 100644
--- a/tools/gardening/lib/src/results/result_json_models.dart
+++ b/tools/gardening/lib/src/results/result_json_models.dart
@@ -24,6 +24,7 @@
final bool fastStartup;
final int timeout;
final bool dart2JsWithKernel;
+ final bool dart2JsOldFrontend;
final bool enableAsserts;
final bool hotReload;
final bool hotReloadRollback;
@@ -48,6 +49,7 @@
this.fastStartup,
this.timeout,
this.dart2JsWithKernel,
+ this.dart2JsOldFrontend,
this.enableAsserts,
this.hotReload,
this.hotReloadRollback,
@@ -73,6 +75,7 @@
json["fast_startup"],
json["timeout"],
json["dart2js_with_kernel"] ?? false,
+ json["dart2js_old_frontend"] ?? false,
json["enable_asserts"] ?? false,
json["hot_reload"] ?? false,
json["hot_reload_rollback"] ?? false,
@@ -100,6 +103,7 @@
_stringToArg("builder-tag", builderTag),
_boolToArg("fast-startup", fastStartup),
_boolToArg("dart2js-with-kernel", dart2JsWithKernel),
+ _boolToArg("dart2js-old-frontend", dart2JsOldFrontend),
_boolToArg("enable-asserts", enableAsserts),
_boolToArg("hot-reload", hotReload),
_boolToArg("hot-reload-rollback", hotReloadRollback),
@@ -114,7 +118,7 @@
String toCsvString() {
return "$mode;$arch;$compiler;$runtime;$checked;$strong;$hostChecked;"
"$minified;$csp;$fasta;$system;$vmOptions;$useSdk;$builderTag;$fastStartup;"
- "$dart2JsWithKernel;$enableAsserts;$hotReload;"
+ "$dart2JsWithKernel;$dart2JsOldFrontend;$enableAsserts;$hotReload;"
"$hotReloadRollback;$previewDart2;$selectors";
}
diff --git a/tools/testing/dart/compiler_configuration.dart b/tools/testing/dart/compiler_configuration.dart
index a6d9f5f..d362670 100644
--- a/tools/testing/dart/compiler_configuration.dart
+++ b/tools/testing/dart/compiler_configuration.dart
@@ -245,11 +245,7 @@
List<String> originalArguments,
CommandArtifact artifact) {
var args = <String>[];
- if (_isStrong) {
- args.add('--strong');
- args.add('--reify-generic-functions');
- args.add('--limit-ints-to-64-bits');
- }
+ args.add('--preview-dart-2');
if (_isChecked) {
args.add('--enable_asserts');
args.add('--enable_type_checks');
@@ -760,6 +756,7 @@
args.add('--strong');
}
if (useDfe) {
+ args.add('--preview-dart-2');
args.addAll(_replaceDartFiles(arguments, tempKernelFile(tempDir)));
} else {
args.addAll(arguments);
@@ -883,8 +880,8 @@
args.add('--enable_asserts');
args.add('--enable_type_checks');
}
- if (_isStrong) {
- args.add('--strong');
+ if (useDfe) {
+ args.add('--preview-dart-2');
}
var dir = artifact.filename;
if (runtimeConfiguration is DartPrecompiledAdbRuntimeConfiguration) {
@@ -1070,15 +1067,16 @@
? '${_configuration.buildDirectory}/dart-sdk/lib/_internal'
: '${_configuration.buildDirectory}';
- final vmPlatform = _isStrong
- ? '$kernelBinariesFolder/vm_platform_strong.dill'
- : '$kernelBinariesFolder/vm_platform.dill';
+ // Always use strong platform as preview_dart_2 implies strong.
+ final vmPlatform = '$kernelBinariesFolder/vm_platform_strong.dill';
final dillFile = tempKernelFile(tempDir);
final args = [
_isAot ? '--aot' : '--no-aot',
- _isStrong ? '--strong-mode' : '--no-strong-mode',
+ // Specify strong mode irrespective of the value of _isStrong
+ // as preview_dart_2 implies strong mode anyway.
+ '--strong-mode',
_isStrong ? '--sync-async' : '--no-sync-async',
'--platform=$vmPlatform',
'-o',
@@ -1086,12 +1084,10 @@
];
args.add(arguments.where((name) => name.endsWith('.dart')).single);
- if (_isStrong) {
- // Pass environment variable to the gen_kernel script as
- // arguments are not passed if gen_kernel runs in batch mode.
- environmentOverrides = new Map.from(environmentOverrides);
- environmentOverrides['DART_VM_FLAGS'] = '--limit-ints-to-64-bits';
- }
+ // Pass environment variable to the gen_kernel script as
+ // arguments are not passed if gen_kernel runs in batch mode.
+ environmentOverrides = new Map.from(environmentOverrides);
+ environmentOverrides['DART_VM_FLAGS'] = '--limit-ints-to-64-bits';
return Command.vmKernelCompilation(dillFile, true, bootstrapDependencies(),
genKernel, args, environmentOverrides);
diff --git a/tools/testing/dart/configuration.dart b/tools/testing/dart/configuration.dart
index 0791d9d..ed47086 100644
--- a/tools/testing/dart/configuration.dart
+++ b/tools/testing/dart/configuration.dart
@@ -51,6 +51,7 @@
this.useFastStartup,
this.useEnableAsserts,
this.useDart2JSWithKernel,
+ this.useDart2JSOldFrontend,
this.writeDebugLog,
this.writeTestOutcomeLog,
this.writeResultLog,
@@ -124,6 +125,7 @@
final bool useFastStartup;
final bool useEnableAsserts;
final bool useDart2JSWithKernel;
+ final bool useDart2JSOldFrontend;
final bool writeDebugLog;
final bool writeTestOutcomeLog;
final bool writeResultLog;
@@ -253,6 +255,7 @@
if (useFastStartup) args.add("--fast-startup");
if (useEnableAsserts) args.add("--enable-asserts");
if (useDart2JSWithKernel) args.add("--use-kernel");
+ if (useDart2JSOldFrontend) args.add("--use-old-frontend");
if (isStrong) args.add("--strong");
return args;
}
@@ -473,6 +476,7 @@
'timeout': timeout,
'preview_dart_2': previewDart2,
'dart2js_with_kernel': useDart2JSWithKernel,
+ 'dart2js_old_frontend': useDart2JSOldFrontend,
'enable_asserts': useEnableAsserts,
'hot_reload': hotReload,
'hot_reload_rollback': hotReloadRollback,
diff --git a/tools/testing/dart/environment.dart b/tools/testing/dart/environment.dart
index 1b9dc2d..47abfea 100644
--- a/tools/testing/dart/environment.dart
+++ b/tools/testing/dart/environment.dart
@@ -20,6 +20,7 @@
"compiler": new _Variable((c) => c.compiler.name, Compiler.names),
"csp": new _Variable.bool((c) => c.isCsp),
"dart2js_with_kernel": new _Variable.bool((c) => c.useDart2JSWithKernel),
+ "dart2js_old_frontend": new _Variable.bool((c) => c.useDart2JSOldFrontend),
"enable_asserts": new _Variable.bool((c) => c.useEnableAsserts),
"fast_startup": new _Variable.bool((c) => c.useFastStartup),
"fasta": new _Variable.bool((c) => c.usesFasta),
diff --git a/tools/testing/dart/options.dart b/tools/testing/dart/options.dart
index 03fe413..4b3eac5 100644
--- a/tools/testing/dart/options.dart
+++ b/tools/testing/dart/options.dart
@@ -173,6 +173,9 @@
new _Option.bool(
'dart2js_with_kernel', 'Pass the --use-kernel flag to dart2js.',
hide: true),
+ new _Option.bool(
+ 'dart2js_old_frontend', 'Pass the --use-old-frontend flag to dart2js.',
+ hide: true),
new _Option.bool('hot_reload', 'Run hot reload stress tests.', hide: true),
new _Option.bool(
'hot_reload_rollback', 'Run hot reload rollback stress tests.',
@@ -649,6 +652,7 @@
useFastStartup: data["fast_startup"] as bool,
useEnableAsserts: data["enable_asserts"] as bool,
useDart2JSWithKernel: data["dart2js_with_kernel"] as bool,
+ useDart2JSOldFrontend: data["dart2js_old_frontend"] as bool,
writeDebugLog: data["write_debug_log"] as bool,
writeTestOutcomeLog: data["write_test_outcome_log"] as bool,
writeResultLog: data["write_result_log"] as bool,
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index 8d9b5df..71d70d4 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -727,6 +727,24 @@
}
void enqueueFile(String filename, FutureGroup group) {
+ bool match = false;
+ for (var regex in configuration.selectors.values) {
+ String pattern = regex.pattern;
+ if (pattern.contains("/")) {
+ String lastPart = pattern.substring(pattern.lastIndexOf("/") + 1);
+ if (int.parse(lastPart, onError: (_) => -1) >= 0 ||
+ lastPart.toLowerCase() == "none") {
+ pattern = pattern.substring(0, pattern.lastIndexOf("/"));
+ }
+ }
+ if (pattern != regex.pattern) {
+ regex = new RegExp(pattern);
+ }
+ if (regex.hasMatch(filename)) match = true;
+ if (match) break;
+ }
+ if (!match) return;
+
if (isHtmlTestFile(filename)) {
var info = html_test.getInformation(filename);
if (info == null) {
diff --git a/utils/dartdevc/BUILD.gn b/utils/dartdevc/BUILD.gn
index 23c945c..8838af5 100644
--- a/utils/dartdevc/BUILD.gn
+++ b/utils/dartdevc/BUILD.gn
@@ -214,7 +214,6 @@
rebase_path(sdk_summary),
"--source-map",
"--source-map-comment",
- "--inline-source-map",
"--modules=amd",
"-o",
rebase_path("$target_gen_dir/js/amd/dart_sdk.js"),
diff --git a/utils/generate_entry_points_json.gni b/utils/generate_entry_points_json.gni
new file mode 100644
index 0000000..63684c9
--- /dev/null
+++ b/utils/generate_entry_points_json.gni
@@ -0,0 +1,109 @@
+# 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("../build/compiled_action.gni")
+import("../build/dart_host_sdk_toolchain.gni")
+
+_dart_root = get_path_info("..", "abspath")
+
+# Template to generate entry points JSON file using dart_bootstrap tool.
+# List of entry points is generated as a by-product while doing precompilation.
+#
+# This template expects the following arguments:
+# - input: Name of the input dart script for precompilation.
+# - output: Name of the output entry points JSON file.
+# - extra_args: Extra arguments to pass to dart_bootstrap (optional).
+#
+template("generate_entry_points_json_with_dart_bootstrap") {
+ assert(defined(invoker.input), "Must define input dart script")
+ assert(defined(invoker.output), "Must define output json file")
+ extra_args = []
+ if (defined(invoker.extra_args)) {
+ extra_args += invoker.extra_args
+ }
+ compiled_action(target_name) {
+ # Printing precompiler entry points is folded into precompilation, so dart_bootstrap is invoked
+ # with correct arguments to generate app-aot snapshot.
+
+ input = invoker.input
+ output = invoker.output
+
+ tool = "$_dart_root/runtime/bin:dart_bootstrap"
+ inputs = [
+ input,
+ ]
+ outputs = [
+ output,
+ ]
+ args = [
+ "--print-precompiler-entry-points=" + rebase_path(output),
+ "--snapshot=" + rebase_path("$target_gen_dir/dummy.snapshot"),
+ "--snapshot-kind=app-aot",
+ "--use-blobs",
+ "--snapshot-kind=app-aot",
+ ] + extra_args + [
+ rebase_path(input),
+ ]
+ }
+}
+
+# Template to generate entry points JSON file using gen_snapshot tool.
+# List of entry points is generated as a by-product while doing precompilation.
+#
+# This template expects the following arguments:
+# - input: Name of the input dart script for precompilation.
+# - output: Name of the output entry points JSON file.
+# - extra_args: Extra arguments to pass to dart_bootstrap (optional).
+# - extra_inputs: Extra input dependencies (optional).
+#
+template("generate_entry_points_json_with_gen_snapshot") {
+ assert(defined(invoker.input), "Must define input dart script")
+ assert(defined(invoker.output), "Must define output json file")
+ extra_args = []
+ if (defined(invoker.extra_args)) {
+ extra_args += invoker.extra_args
+ }
+ extra_inputs = []
+ if (defined(invoker.extra_inputs)) {
+ extra_inputs += invoker.extra_inputs
+ }
+ compiled_action(target_name) {
+ # Printing precompiler entry points is folded into precompilation, so gen_snapshot is invoked
+ # with correct arguments to generate app-aot snapshot.
+
+ input = invoker.input
+ output = invoker.output
+
+ tool = "$_dart_root/runtime/bin:gen_snapshot"
+ inputs = [
+ input,
+ ] + extra_inputs
+ outputs = [
+ output,
+ ]
+ args = [
+ "--print-precompiler-entry-points=" + rebase_path(output),
+ "--snapshot-kind=app-aot-blobs",
+ "--vm_snapshot_data=" + rebase_path("$target_gen_dir/dummy.vm_data.snapshot"),
+ "--vm_snapshot_instructions=" + rebase_path("$target_gen_dir/dummy.vm_instr.snapshot"),
+ "--isolate_snapshot_data=" + rebase_path("$target_gen_dir/dummy.isolate_data.snapshot"),
+ "--isolate_snapshot_instructions=" + rebase_path("$target_gen_dir/dummy.isolate_instr.snapshot"),
+ ] + extra_args + [
+ rebase_path(input),
+ ]
+ }
+}
+
+# Template to copy checked-in extra entry points JSON file.
+#
+# This template expects the following argument:
+# - output: Target destination for the extra entry points JSON file.
+#
+template("copy_entry_points_extra_json") {
+ assert(defined(invoker.output), "Must define output json file")
+ copy(target_name) {
+ sources = [ "$_dart_root/pkg/vm/lib/transformations/type_flow/entry_points_extra.json" ]
+ outputs = [ invoker.output ]
+ }
+}