Version 2.0.0-dev.36.0
Merge commit '1df3150d0543b4df5fe2ab03a1f155416da0e44e' into dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0d71cdf..33c562a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,10 +1,17 @@
+## 2.0.0-dev.36.0
### Core library changes
-* Temporarily disabled the `whereType` method until generic methods are enabled
- on all platforms ([issue 32463]).
-
-[issue 32463]: https://github.com/dart-lang/sdk/issues/32463
+* `dart:core`
+ * Temporarily disabled the `whereType` method until generic methods are
+ enabled on all platforms
+ ([issue 32463](https://github.com/dart-lang/sdk/issues/32463)).
+ * Changed return type of `UriData.dataAsBytes` to `Uint8List`.
+* `dart:convert`
+ * Added `jsonEncode`, `jsonDecode`, `base64Encode`, `base64UrlEncode` and
+ `base64Decode` top-level functions.
+ * Changed return type of `encode` on `AsciiCodec` and `Latin1Codec`,
+ and `convert` on `AsciiEncoder`, `Latin1Encoder`, to `Uint8List`.
## 2.0.0
diff --git a/DEPS b/DEPS
index 0be6cc5..e360ee3 100644
--- a/DEPS
+++ b/DEPS
@@ -87,7 +87,7 @@
"fixnum_tag": "@0.10.5",
"func_rev": "@25eec48146a58967d75330075ab376b3838b18a8",
"glob_tag": "@1.1.5",
- "html_tag" : "@0.13.2+2",
+ "html_tag" : "@0.13.3",
"http_io_tag": "@35dc43c9144cf7ed4236843dacd62ebaf89df21a",
"http_multi_server_tag" : "@2.0.4",
"http_parser_tag" : "@3.1.1",
@@ -114,7 +114,7 @@
"plugin_tag": "@0.2.0+2",
"ply_rev": "@604b32590ffad5cbb82e4afef1d305512d06ae93",
"pool_tag": "@1.3.4",
- "protobuf_tag": "@0.7.0",
+ "protobuf_tag": "@0.7.1",
"pub_rev": "@73ff0d3d9f80f60d41e3135ac44597d011abb4f3",
"pub_semver_tag": "@1.3.2",
"quiver_tag": "@5aaa3f58c48608af5b027444d561270b53f15dbf",
diff --git a/build/.gitignore b/build/.gitignore
index 512a659..0c6f306 100644
--- a/build/.gitignore
+++ b/build/.gitignore
@@ -5,5 +5,6 @@
linux/debian_jessie_arm-sysroot
linux/debian_jessie_arm64-sysroot
linux/debian_wheezy_amd64-sysroot
+linux/debian_jessie_amd64-sysroot
linux/debian_wheezy_arm-sysroot
linux/debian_wheezy_i386-sysroot
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index 7418019..bdddd97 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -261,6 +261,16 @@
cflags += [ "-fcolor-diagnostics" ]
}
+ # C++14 compiler flags setup.
+ # ---------------------------
+ if (is_win) {
+ cc_std = [ "/std:c++14" ]
+ } else {
+ cc_std = [ "-std=c++14" ]
+ }
+ cflags_cc += cc_std
+ cflags_objcc += cc_std
+
# Android-specific flags setup.
# -----------------------------
if (is_android) {
diff --git a/build/config/sysroot.gni b/build/config/sysroot.gni
index 478f369..ddee618 100644
--- a/build/config/sysroot.gni
+++ b/build/config/sysroot.gni
@@ -18,7 +18,11 @@
if (current_cpu == "x86") {
target_sysroot = rebase_path("//build/linux/debian_wheezy_i386-sysroot")
} else if (current_cpu == "x64") {
- target_sysroot = rebase_path("//build/linux/debian_wheezy_amd64-sysroot")
+ if (is_asan || is_lsan || is_msan || is_tsan) {
+ target_sysroot = rebase_path("//build/linux/debian_jessie_amd64-sysroot")
+ } else {
+ target_sysroot = rebase_path("//build/linux/debian_wheezy_amd64-sysroot")
+ }
} else if (current_cpu == "arm") {
target_sysroot = rebase_path("//build/linux/debian_wheezy_arm-sysroot")
} else if (current_cpu == "arm64") {
diff --git a/build/linux/sysroot_scripts/install-sysroot.py b/build/linux/sysroot_scripts/install-sysroot.py
index 2fc9d53..88bdd62 100755
--- a/build/linux/sysroot_scripts/install-sysroot.py
+++ b/build/linux/sysroot_scripts/install-sysroot.py
@@ -96,6 +96,7 @@
def InstallDefaultSysrootForArch(target_arch):
if target_arch == 'amd64':
InstallSysroot('Wheezy', 'amd64')
+ InstallSysroot('Jessie', 'amd64')
elif target_arch == 'arm':
InstallSysroot('Wheezy', 'arm')
elif target_arch == 'arm64':
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart
index 594ca15..3f35824 100644
--- a/pkg/analysis_server/lib/src/server/driver.dart
+++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -316,7 +316,9 @@
analysisServerOptions.clientId = results[CLIENT_ID];
analysisServerOptions.clientVersion = results[CLIENT_VERSION];
analysisServerOptions.cacheFolder = results[CACHE_FOLDER];
- analysisServerOptions.previewDart2 = results[PREVIEW_DART2];
+ if (results.wasParsed(PREVIEW_DART2)) {
+ analysisServerOptions.previewDart2 = results[PREVIEW_DART2];
+ }
analysisServerOptions.useCFE = results[USE_CFE];
ContextBuilderOptions.flutterRepo = results[FLUTTER_REPO];
@@ -624,7 +626,7 @@
for (int i = numOld - 1; i >= 0; i--) {
try {
String oldPath = i == 0 ? path : '$path.$i';
- new File(oldPath).renameSync('$path.${i+1}');
+ new File(oldPath).renameSync('$path.${i + 1}');
} catch (e) {}
}
}
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index b33abd7..dd3dc19 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -177,6 +177,7 @@
const FixKind('REMOVE_DEAD_CODE', 50, "Remove dead code");
static const MAKE_FIELD_NOT_FINAL =
const FixKind('MAKE_FIELD_NOT_FINAL', 50, "Make field '{0}' not final");
+ static const MAKE_FINAL = const FixKind('MAKE_FINAL', 50, "Make final");
static const REMOVE_AWAIT = const FixKind('REMOVE_AWAIT', 50, "Remove await");
static const REMOVE_EMPTY_CATCH =
const FixKind('REMOVE_EMPTY_CATCH', 50, "Remove empty catch clause");
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index 634df8d..c5340dc 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -456,6 +456,12 @@
if (errorCode.name == LintNames.prefer_const_declarations) {
await _addFix_replaceFinalWithConst();
}
+ if (name == LintNames.prefer_final_fields) {
+ await _addFix_makeVariableFinal();
+ }
+ if (name == LintNames.prefer_final_locals) {
+ await _addFix_makeVariableFinal();
+ }
if (name == LintNames.prefer_is_not_empty) {
await _addFix_isNotEmpty();
}
@@ -2060,6 +2066,25 @@
}
}
+ Future<Null> _addFix_makeVariableFinal() async {
+ AstNode node = this.node;
+ if (node is SimpleIdentifier && node.parent is VariableDeclaration) {
+ VariableDeclaration declaration = node.parent;
+ VariableDeclarationList list = declaration.parent;
+ if (list.variables.length == 1) {
+ DartChangeBuilder changeBuilder = new DartChangeBuilder(session);
+ await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
+ if (list.type == null && list.keyword.keyword == Keyword.VAR) {
+ builder.addSimpleReplacement(range.token(list.keyword), 'final');
+ } else if (list.type != null && list.keyword == null) {
+ builder.addSimpleInsertion(list.type.offset, 'final ');
+ }
+ });
+ _addFixFromBuilder(changeBuilder, DartFixKind.MAKE_FINAL);
+ }
+ }
+ }
+
Future<Null> _addFix_nonBoolCondition_addNotNull() async {
DartChangeBuilder changeBuilder = new DartChangeBuilder(session);
await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
@@ -3414,6 +3439,8 @@
static const String prefer_conditional_assignment =
'prefer_conditional_assignment';
static const String prefer_const_declarations = 'prefer_const_declarations';
+ static const String prefer_final_fields = 'prefer_final_fields';
+ static const String prefer_final_locals = 'prefer_final_locals';
static const String prefer_is_not_empty = 'prefer_is_not_empty';
static const String type_init_formals = 'type_init_formals';
static const String unnecessary_brace_in_string_interp =
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_local.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_local.dart
index 8a02a2b..4b1c9eb4 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/rename_local.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/rename_local.dart
@@ -77,7 +77,14 @@
Future fillChange() async {
for (Element element in elements) {
addDeclarationEdit(element);
- await searchEngine.searchReferences(element).then(addReferenceEdits);
+ var references = await searchEngine.searchReferences(element);
+
+ // Exclude "implicit" references to optional positional parameters.
+ if (element is ParameterElement && element.isOptionalPositional) {
+ references.removeWhere((match) => match.sourceRange.length == 0);
+ }
+
+ addReferenceEdits(references);
}
}
diff --git a/pkg/analysis_server/test/services/correction/fix_test.dart b/pkg/analysis_server/test/services/correction/fix_test.dart
index 847da32..334b46a 100644
--- a/pkg/analysis_server/test/services/correction/fix_test.dart
+++ b/pkg/analysis_server/test/services/correction/fix_test.dart
@@ -6177,6 +6177,74 @@
''');
}
+ test_makeFieldFinal_type() async {
+ String src = '''
+class C {
+ int /*LINT*/f = 2;
+}
+''';
+ await findLint(src, LintNames.prefer_final_fields);
+
+ await applyFix(DartFixKind.MAKE_FINAL);
+
+ verifyResult('''
+class C {
+ final int f = 2;
+}
+''');
+ }
+
+ test_makeFieldFinal_var() async {
+ String src = '''
+class C {
+ var /*LINT*/f = 2;
+}
+''';
+ await findLint(src, LintNames.prefer_final_fields);
+
+ await applyFix(DartFixKind.MAKE_FINAL);
+
+ verifyResult('''
+class C {
+ final f = 2;
+}
+''');
+ }
+
+ test_makeLocalFinal_type() async {
+ String src = '''
+bad() {
+ int /*LINT*/x = 2;
+}
+''';
+ await findLint(src, LintNames.prefer_final_locals);
+
+ await applyFix(DartFixKind.MAKE_FINAL);
+
+ verifyResult('''
+bad() {
+ final int x = 2;
+}
+''');
+ }
+
+ test_makeLocalFinal_var() async {
+ String src = '''
+bad() {
+ var /*LINT*/x = 2;
+}
+''';
+ await findLint(src, LintNames.prefer_final_locals);
+
+ await applyFix(DartFixKind.MAKE_FINAL);
+
+ verifyResult('''
+bad() {
+ final x = 2;
+}
+''');
+ }
+
test_removeAwait_intLiteral() async {
String src = '''
bad() async {
diff --git a/pkg/analysis_server/test/services/refactoring/rename_local_test.dart b/pkg/analysis_server/test/services/refactoring/rename_local_test.dart
index 8533be0..505843c 100644
--- a/pkg/analysis_server/test/services/refactoring/rename_local_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/rename_local_test.dart
@@ -412,7 +412,7 @@
''');
}
- test_createChange_parameter() async {
+ test_createChange_parameter_named() async {
await indexTestUnit('''
myFunction({int test}) {
test = 1;
@@ -531,6 +531,35 @@
''');
}
+ test_createChange_parameter_optionalPositional() async {
+ await indexTestUnit('''
+myFunction([int test]) {
+ test = 1;
+ test += 2;
+ print(test);
+}
+main() {
+ myFunction(2);
+}
+''');
+ // configure refactoring
+ createRenameRefactoringAtString('test]) {');
+ expect(refactoring.refactoringName, 'Rename Parameter');
+ expect(refactoring.elementKindName, 'parameter');
+ refactoring.newName = 'newName';
+ // validate change
+ return assertSuccessfulRefactoring('''
+myFunction([int newName]) {
+ newName = 1;
+ newName += 2;
+ print(newName);
+}
+main() {
+ myFunction(2);
+}
+''');
+ }
+
test_oldName() async {
await indexTestUnit('''
main() {
diff --git a/pkg/analyzer/.gitignore b/pkg/analyzer/.gitignore
index 1410a61..186d37d 100644
--- a/pkg/analyzer/.gitignore
+++ b/pkg/analyzer/.gitignore
@@ -1,6 +1,6 @@
# Files and directories created by pub
.packages
-.pub/
+.dart_tool/
build/
# Remove the following pattern if you wish to check in your lock file
pubspec.lock
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 89ba18c..c8f3023 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -94,7 +94,7 @@
/**
* The version of data format, should be incremented on every format change.
*/
- static const int DATA_VERSION = 49;
+ static const int DATA_VERSION = 50;
/**
* The number of exception contexts allowed to write. Once this field is
diff --git a/pkg/analyzer/lib/src/dart/analysis/index.dart b/pkg/analyzer/lib/src/dart/analysis/index.dart
index 448de64..9fd2e75 100644
--- a/pkg/analyzer/lib/src/dart/analysis/index.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/index.dart
@@ -441,7 +441,7 @@
element.enclosingElement is ExecutableElement ||
elementKind == ElementKind.PARAMETER &&
element is ParameterElement &&
- !element.isNamed ||
+ !element.isOptional ||
false) {
return;
}
@@ -558,6 +558,16 @@
}
@override
+ visitExpression(Expression node) {
+ ParameterElement parameterElement = node.staticParameterElement;
+ if (parameterElement != null && parameterElement.isOptionalPositional) {
+ recordRelationOffset(parameterElement, IndexRelationKind.IS_REFERENCED_BY,
+ node.offset, 0, true);
+ }
+ super.visitExpression(node);
+ }
+
+ @override
visitExportDirective(ExportDirective node) {
ExportElement element = node.element;
recordUriReference(element?.exportedLibrary, node);
diff --git a/pkg/analyzer/lib/src/dart/analysis/search.dart b/pkg/analyzer/lib/src/dart/analysis/search.dart
index 00b550c..3933454 100644
--- a/pkg/analyzer/lib/src/dart/analysis/search.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/search.dart
@@ -121,7 +121,6 @@
RegExp regExp, int maxResults, List<String> files,
{String onlyForFile}) async {
List<Declaration> declarations = <Declaration>[];
- UnlinkedUnit unlinkedUnit;
DeclarationKind getExecutableKind(
UnlinkedExecutable executable, bool topLevel) {
@@ -141,43 +140,6 @@
}
}
- void appendParameter(StringBuffer buffer, UnlinkedParam parameter) {
- EntityRef type = parameter.type;
- if (type?.entityKind == EntityRefKind.named) {
- if (type.reference != null) {
- UnlinkedReference typeRef = unlinkedUnit.references[type.reference];
- buffer.write(typeRef.name);
- buffer.write(' ');
- }
- }
- buffer.write(parameter.name);
- }
-
- String getParametersString(List<UnlinkedParam> parameters) {
- var buffer = new StringBuffer();
- buffer.write('(');
-
- bool isFirstParameter = true;
- for (var parameter in parameters) {
- if (isFirstParameter) {
- isFirstParameter = false;
- } else {
- buffer.write(', ');
- }
- appendParameter(buffer, parameter);
- }
-
- buffer.write(')');
- return buffer.toString();
- }
-
- String getExecutableParameters(UnlinkedExecutable executable) {
- if (executable.kind == UnlinkedExecutableKind.getter) {
- return null;
- }
- return getParametersString(executable.parameters);
- }
-
try {
for (String path in _driver.addedFiles) {
if (onlyForFile != null && path != onlyForFile) {
@@ -219,7 +181,22 @@
parameters));
}
- unlinkedUnit = file.unlinked;
+ UnlinkedUnit unlinkedUnit = file.unlinked;
+ var parameterComposer = new _UnlinkedParameterComposer(unlinkedUnit);
+
+ String getParametersString(List<UnlinkedParam> parameters) {
+ parameterComposer.clear();
+ parameterComposer.appendParameters(parameters);
+ return parameterComposer.buffer.toString();
+ }
+
+ String getExecutableParameters(UnlinkedExecutable executable) {
+ if (executable.kind == UnlinkedExecutableKind.getter) {
+ return null;
+ }
+ return getParametersString(executable.parameters);
+ }
+
for (var class_ in unlinkedUnit.classes) {
String className = class_.name;
addDeclaration(
@@ -230,6 +207,7 @@
class_.nameOffset,
class_.codeRange.offset,
class_.codeRange.length);
+ parameterComposer.outerTypeParameters = class_.typeParameters;
for (var field in class_.fields) {
addDeclaration(field.name, DeclarationKind.FIELD, field.nameOffset,
@@ -238,17 +216,19 @@
}
for (var executable in class_.executables) {
- if (executable.name.isNotEmpty) {
- addDeclaration(
- executable.name,
- getExecutableKind(executable, false),
- executable.nameOffset,
- executable.codeRange.offset,
- executable.codeRange.length,
- className: className,
- parameters: getExecutableParameters(executable));
- }
+ parameterComposer.innerTypeParameters = executable.typeParameters;
+ addDeclaration(
+ executable.name,
+ getExecutableKind(executable, false),
+ executable.nameOffset,
+ executable.codeRange.offset,
+ executable.codeRange.length,
+ className: className,
+ parameters: getExecutableParameters(executable));
+ parameterComposer.innerTypeParameters = const [];
}
+
+ parameterComposer.outerTypeParameters = const [];
}
for (var enum_ in unlinkedUnit.enums) {
@@ -261,6 +241,7 @@
}
for (var executable in unlinkedUnit.executables) {
+ parameterComposer.outerTypeParameters = executable.typeParameters;
addDeclaration(
executable.name,
getExecutableKind(executable, true),
@@ -271,6 +252,7 @@
}
for (var typedef_ in unlinkedUnit.typedefs) {
+ parameterComposer.outerTypeParameters = typedef_.typeParameters;
addDeclaration(
typedef_.name,
DeclarationKind.FUNCTION_TYPE_ALIAS,
@@ -278,6 +260,7 @@
typedef_.codeRange.offset,
typedef_.codeRange.length,
parameters: getParametersString(typedef_.parameters));
+ parameterComposer.outerTypeParameters = const [];
}
for (var variable in unlinkedUnit.variables) {
@@ -685,7 +668,7 @@
AstNode parent = node.parent;
return parent is ClassDeclaration || parent is CompilationUnit;
}));
- if (parameter.isNamed) {
+ if (parameter.isOptional) {
results.addAll(await _searchReferences(parameter));
}
return results;
@@ -1183,3 +1166,99 @@
class _MaxNumberOfDeclarationsError {
const _MaxNumberOfDeclarationsError();
}
+
+/**
+ * Helper for composing parameter strings.
+ */
+class _UnlinkedParameterComposer {
+ final UnlinkedUnit unlinkedUnit;
+ final StringBuffer buffer = new StringBuffer();
+
+ List<UnlinkedTypeParam> outerTypeParameters = const [];
+ List<UnlinkedTypeParam> innerTypeParameters = const [];
+
+ _UnlinkedParameterComposer(this.unlinkedUnit);
+
+ void appendParameter(UnlinkedParam parameter) {
+ bool hasType = appendType(parameter.type);
+ if (hasType && parameter.name.isNotEmpty) {
+ buffer.write(' ');
+ }
+ buffer.write(parameter.name);
+ if (parameter.isFunctionTyped) {
+ appendParameters(parameter.parameters);
+ }
+ }
+
+ void appendParameters(List<UnlinkedParam> parameters) {
+ buffer.write('(');
+
+ bool isFirstParameter = true;
+ for (var parameter in parameters) {
+ if (isFirstParameter) {
+ isFirstParameter = false;
+ } else {
+ buffer.write(', ');
+ }
+ appendParameter(parameter);
+ }
+
+ buffer.write(')');
+ }
+
+ bool appendType(EntityRef type) {
+ EntityRefKind kind = type?.entityKind;
+ if (kind == EntityRefKind.named) {
+ if (type.reference != 0) {
+ UnlinkedReference typeRef = unlinkedUnit.references[type.reference];
+ buffer.write(typeRef.name);
+ appendTypeArguments(type);
+ return true;
+ }
+ if (type.paramReference != 0) {
+ int ref = type.paramReference;
+ if (ref <= innerTypeParameters.length) {
+ var param = innerTypeParameters[innerTypeParameters.length - ref];
+ buffer.write(param.name);
+ return true;
+ }
+ ref -= innerTypeParameters.length;
+ if (ref <= outerTypeParameters.length) {
+ var param = outerTypeParameters[outerTypeParameters.length - ref];
+ buffer.write(param.name);
+ return true;
+ }
+ return false;
+ }
+ }
+ if (kind == EntityRefKind.genericFunctionType) {
+ if (appendType(type.syntheticReturnType)) {
+ buffer.write(' ');
+ }
+ buffer.write('Function');
+ appendParameters(type.syntheticParams);
+ return true;
+ }
+ return false;
+ }
+
+ void appendTypeArguments(EntityRef type) {
+ if (type.typeArguments.isNotEmpty) {
+ buffer.write('<');
+ bool first = true;
+ for (var arguments in type.typeArguments) {
+ if (first) {
+ first = false;
+ } else {
+ buffer.write(', ');
+ }
+ appendType(arguments);
+ }
+ buffer.write('>');
+ }
+ }
+
+ void clear() {
+ buffer.clear();
+ }
+}
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 81cc956..59e05e7 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -701,9 +701,7 @@
*/
void _checkForDeprecatedMemberUse(Element element, AstNode node) {
bool isDeprecated(Element element) {
- if (element == null) {
- return false;
- } else if (element is PropertyAccessorElement && element.isSynthetic) {
+ if (element is PropertyAccessorElement && element.isSynthetic) {
// TODO(brianwilkerson) Why isn't this the implementation for PropertyAccessorElement?
Element variable = element.variable;
if (variable == null) {
@@ -714,7 +712,34 @@
return element.hasDeprecated;
}
- if (!inDeprecatedMember && isDeprecated(element)) {
+ bool isLocalParameter(Element element, AstNode node) {
+ if (element is ParameterElement) {
+ ExecutableElement definingFunction = element.enclosingElement;
+ FunctionBody body =
+ node.getAncestor((ancestor) => ancestor is FunctionBody);
+ while (body != null) {
+ ExecutableElement enclosingFunction;
+ AstNode parent = body.parent;
+ if (parent is ConstructorDeclaration) {
+ enclosingFunction = parent.element;
+ } else if (parent is FunctionExpression) {
+ enclosingFunction = parent.element;
+ } else if (parent is MethodDeclaration) {
+ enclosingFunction = parent.element;
+ }
+ if (enclosingFunction == definingFunction) {
+ return true;
+ }
+ body = parent?.getAncestor((ancestor) => ancestor is FunctionBody);
+ }
+ }
+ return false;
+ }
+
+ if (!inDeprecatedMember &&
+ element != null &&
+ isDeprecated(element) &&
+ !isLocalParameter(element, node)) {
String displayName = element.displayName;
if (element is ConstructorElement) {
// TODO(jwren) We should modify ConstructorElement.getDisplayName(),
diff --git a/pkg/analyzer/lib/src/pubspec/pubspec_validator.dart b/pkg/analyzer/lib/src/pubspec/pubspec_validator.dart
index 414933d..e0a25cb 100644
--- a/pkg/analyzer/lib/src/pubspec/pubspec_validator.dart
+++ b/pkg/analyzer/lib/src/pubspec/pubspec_validator.dart
@@ -70,6 +70,31 @@
}
/**
+ * Return `true` if an asset (file) exists at the given absolute, normalized
+ * [assetPath] or in a subdirectory of the parent of the file.
+ */
+ bool _assetExistsAtPath(String assetPath) {
+ File assetFile = provider.getFile(assetPath);
+ if (assetFile.exists) {
+ return true;
+ }
+ String fileName = assetFile.shortName;
+ Folder assetFolder = assetFile.parent;
+ if (!assetFolder.exists) {
+ return false;
+ }
+ for (Resource child in assetFolder.getChildren()) {
+ if (child is Folder) {
+ File innerFile = child.getChildAssumingFile(fileName);
+ if (innerFile.exists) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
* Return a map whose keys are the names of declared dependencies and whose
* values are the specifications of those dependencies. The map is extracted
* from the given [contents] using the given [key].
@@ -131,12 +156,13 @@
if (entryValue is YamlScalar) {
Object entry = entryValue.value;
if (entry is String) {
- if (!entry.startsWith('packages/')) {
+ if (entry.startsWith('packages/')) {
// TODO(brianwilkerson) Add validation of package references.
+ } else {
String normalizedEntry =
context.joinAll(path.posix.split(entry));
String assetPath = context.join(packageRoot, normalizedEntry);
- if (!provider.getFile(assetPath).exists) {
+ if (!_assetExistsAtPath(assetPath)) {
_reportErrorForNode(
reporter,
entryValue,
diff --git a/pkg/analyzer/lib/src/summary/link.dart b/pkg/analyzer/lib/src/summary/link.dart
index f8e38c3..c8e60f3 100644
--- a/pkg/analyzer/lib/src/summary/link.dart
+++ b/pkg/analyzer/lib/src/summary/link.dart
@@ -2510,15 +2510,39 @@
List<DartType> positionalArgTypes = _popList(numPositional);
EntityRef ref = _getNextRef();
+
+ var typeArguments = new List<DartType>(ref.typeArguments.length);
+ for (int i = 0; i < ref.typeArguments.length; i++) {
+ typeArguments[i] = unit.resolveTypeRef(function, ref.typeArguments[i]);
+ }
+
+ _doInvokeConstructorImpl(ref, typeArguments, numNamed, numPositional,
+ namedArgNames, namedArgTypeList, positionalArgTypes);
+ }
+
+ /**
+ * Implements constructor invocation inference, and accepts the reference,
+ * type arguments, and types of arguments. It is used for explicit instance
+ * creation, and also for implicit creation, that looks like
+ * [UnlinkedExprOperation.invokeMethodRef].
+ */
+ void _doInvokeConstructorImpl(
+ EntityRef ref,
+ List<DartType> typeArguments,
+ int numNamed,
+ int numPositional,
+ List<String> namedArgNames,
+ List<DartType> namedArgTypeList,
+ List<DartType> positionalArgTypes) {
ReferenceableElementForLink refElement = unit.resolveRef(ref.reference);
ConstructorElementForLink constructorElement = refElement.asConstructor;
if (constructorElement != null) {
stack.add(() {
- if (ref.typeArguments.isNotEmpty) {
+ if (typeArguments.isNotEmpty) {
return constructorElement.enclosingClass.buildType((int i) {
- if (i < ref.typeArguments.length) {
- return unit.resolveTypeRef(function, ref.typeArguments[i]);
+ if (i < typeArguments.length) {
+ return typeArguments[i];
} else {
return null;
}
@@ -2594,9 +2618,19 @@
List<String> namedArgNames = _getNextStrings(numNamed);
List<DartType> namedArgTypeList = _popList(numNamed);
List<DartType> positionalArgTypes = _popList(numPositional);
+
EntityRef ref = _getNextRef();
ReferenceableElementForLink element = unit.resolveRef(ref.reference);
+
List<DartType> typeArguments = _getTypeArguments();
+
+ // Check for implicit instance creation.
+ if (element.asClass != null || element.asConstructor != null) {
+ _doInvokeConstructorImpl(ref, typeArguments, numNamed, numPositional,
+ namedArgNames, namedArgTypeList, positionalArgTypes);
+ return;
+ }
+
stack.add(() {
DartType rawType = element.asStaticType;
if (rawType is FunctionType) {
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index edbda6c..4d2f038 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
name: analyzer
-version: 0.31.2-alpha.0
+version: 0.31.2-alpha.1
author: Dart Team <misc@dartlang.org>
description: Static analyzer for Dart.
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer
@@ -11,11 +11,11 @@
collection: ^1.10.1
convert: ^2.0.0
crypto: '>=1.1.1 <3.0.0'
- front_end: 0.1.0-alpha.10
+ front_end: 0.1.0-alpha.11
glob: ^1.0.3
html: '>=0.12.0 <1.14.0'
isolate: '>=0.2.2 <2.0.0'
- kernel: 0.3.0-alpha.10
+ kernel: 0.3.0-alpha.11
meta: ^1.0.2
package_config: '>=0.1.5 <2.0.0'
path: '>=0.9.0 <2.0.0'
diff --git a/pkg/analyzer/test/generated/non_hint_code_test.dart b/pkg/analyzer/test/generated/non_hint_code_test.dart
index 5d0f10b..089c32b 100644
--- a/pkg/analyzer/test/generated/non_hint_code_test.dart
+++ b/pkg/analyzer/test/generated/non_hint_code_test.dart
@@ -236,6 +236,60 @@
verify([source]);
}
+ test_deprecatedAnnotationUse_namedParameter_inDefiningFunction() async {
+ Source source = addSource(r'''
+f({@deprecated int x}) => x;
+''');
+ await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ test_deprecatedAnnotationUse_namedParameter_inDefiningLocalFunction() async {
+ Source source = addSource(r'''
+class C {
+ m() {
+ f({@deprecated int x}) {
+ return x;
+ }
+ return f();
+ }
+}
+''');
+ await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ test_deprecatedAnnotationUse_namedParameter_inDefiningMethod() async {
+ Source source = addSource(r'''
+class C {
+ m({@deprecated int x}) {
+ return x;
+ }
+}
+''');
+ await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ test_deprecatedAnnotationUse_namedParameter_inNestedLocalFunction() async {
+ Source source = addSource(r'''
+class C {
+ m({@deprecated int x}) {
+ f() {
+ return x;
+ }
+ return f();
+ }
+}
+''');
+ await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
test_deprecatedMemberUse_inDeprecatedClass() async {
Source source = addSource(r'''
@deprecated
diff --git a/pkg/analyzer/test/src/dart/analysis/index_test.dart b/pkg/analyzer/test/src/dart/analysis/index_test.dart
index 33f75d7..a05eef9 100644
--- a/pkg/analyzer/test/src/dart/analysis/index_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/index_test.dart
@@ -820,6 +820,21 @@
assertThat(element)..isReferencedAt('p: 1', true);
}
+ test_isReferencedBy_ParameterElement_optionalPositional() async {
+ await _indexTestUnit('''
+foo([p]) {
+ p; // 1
+}
+main() {
+ foo(1); // 2
+}
+''');
+ Element element = findElement('p');
+ assertThat(element)
+ ..hasRelationCount(1)
+ ..isReferencedAt('1); // 2', true, length: 0);
+ }
+
test_isReferencedBy_synthetic_leastUpperBound() async {
await _indexTestUnit('''
int f1({int p}) => 1;
diff --git a/pkg/analyzer/test/src/dart/analysis/search_test.dart b/pkg/analyzer/test/src/dart/analysis/search_test.dart
index 933ade7..52cadae 100644
--- a/pkg/analyzer/test/src/dart/analysis/search_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/search_test.dart
@@ -116,6 +116,8 @@
offset: 6, codeOffset: 0, codeLength: 91);
_assertHasDeclaration(declarations, 'f', DeclarationKind.FIELD,
offset: 16, codeOffset: 12, codeLength: 6, className: 'C');
+ _assertHasDeclaration(declarations, '', DeclarationKind.CONSTRUCTOR,
+ offset: 21, codeOffset: 21, codeLength: 4, className: 'C');
_assertHasDeclaration(declarations, 'named', DeclarationKind.CONSTRUCTOR,
offset: 30, codeOffset: 28, codeLength: 10, className: 'C');
_assertHasDeclaration(declarations, 'g', DeclarationKind.GETTER,
@@ -184,6 +186,7 @@
}
void f(bool a, String b) {}
typedef F(int a);
+typedef T F2<T, U>(U a);
''');
var files = <String>[];
List<Declaration> declarations =
@@ -212,6 +215,70 @@
declaration = _assertHasDeclaration(
declarations, 'F', DeclarationKind.FUNCTION_TYPE_ALIAS);
expect(declaration.parameters, '(int a)');
+
+ declaration = _assertHasDeclaration(
+ declarations, 'F2', DeclarationKind.FUNCTION_TYPE_ALIAS);
+ expect(declaration.parameters, '(U a)');
+ }
+
+ test_declarations_parameters_functionTyped() async {
+ await _resolveTestUnit('''
+void f1(bool a(int b, String c)) {}
+void f2(a(b, c)) {}
+void f3(bool Function(int a, String b) c) {}
+void f4(bool Function(int, String) a) {}
+''');
+ var files = <String>[];
+ List<Declaration> declarations =
+ await driver.search.declarations(null, null, files);
+
+ Declaration declaration;
+
+ declaration =
+ _assertHasDeclaration(declarations, 'f1', DeclarationKind.FUNCTION);
+ expect(declaration.parameters, '(bool a(int b, String c))');
+
+ declaration =
+ _assertHasDeclaration(declarations, 'f2', DeclarationKind.FUNCTION);
+ expect(declaration.parameters, '(a(b, c))');
+
+ declaration =
+ _assertHasDeclaration(declarations, 'f3', DeclarationKind.FUNCTION);
+ expect(declaration.parameters, '(bool Function(int a, String b) c)');
+
+ declaration =
+ _assertHasDeclaration(declarations, 'f4', DeclarationKind.FUNCTION);
+ expect(declaration.parameters, '(bool Function(int, String) a)');
+ }
+
+ test_declarations_parameters_typeArguments() async {
+ await _resolveTestUnit('''
+class A<T, T2> {
+ void m1(Map<int, String> a) {}
+ void m2<U>(Map<T, U> a) {}
+ void m3<U1, U2>(Map<Map<T2, U2>, Map<U1, T>> a) {}
+}
+''');
+ var files = <String>[];
+ List<Declaration> declarations =
+ await driver.search.declarations(null, null, files);
+
+ Declaration declaration;
+
+ declaration = _assertHasDeclaration(
+ declarations, 'm1', DeclarationKind.METHOD,
+ className: 'A');
+ expect(declaration.parameters, '(Map<int, String> a)');
+
+ declaration = _assertHasDeclaration(
+ declarations, 'm2', DeclarationKind.METHOD,
+ className: 'A');
+ expect(declaration.parameters, '(Map<T, U> a)');
+
+ declaration = _assertHasDeclaration(
+ declarations, 'm3', DeclarationKind.METHOD,
+ className: 'A');
+ expect(declaration.parameters, '(Map<Map<T2, U2>, Map<U1, T>> a)');
}
test_declarations_regExp() async {
@@ -984,6 +1051,31 @@
await _verifyReferences(element, expected);
}
+ test_searchReferences_ParameterElement_optionalPositional() async {
+ await _resolveTestUnit('''
+foo([p]) {
+ p = 1;
+ p += 2;
+ print(p);
+ p();
+}
+main() {
+ foo(42);
+}
+''');
+ ParameterElement element = _findElement('p');
+ Element fooElement = _findElement('foo');
+ Element mainElement = _findElement('main');
+ var expected = [
+ _expectId(fooElement, SearchResultKind.WRITE, 'p = 1;'),
+ _expectId(fooElement, SearchResultKind.READ_WRITE, 'p += 2;'),
+ _expectId(fooElement, SearchResultKind.READ, 'p);'),
+ _expectId(fooElement, SearchResultKind.INVOCATION, 'p();'),
+ _expectIdQ(mainElement, SearchResultKind.REFERENCE, '42', length: 0)
+ ];
+ await _verifyReferences(element, expected);
+ }
+
test_searchReferences_PrefixElement() async {
String partCode = r'''
part of my_lib;
diff --git a/pkg/analyzer/test/src/pubspec/pubspec_validator_test.dart b/pkg/analyzer/test/src/pubspec/pubspec_validator_test.dart
index 84c9688..883fe5f 100644
--- a/pkg/analyzer/test/src/pubspec/pubspec_validator_test.dart
+++ b/pkg/analyzer/test/src/pubspec/pubspec_validator_test.dart
@@ -62,7 +62,7 @@
''', [PubspecWarningCode.ASSET_DOES_NOT_EXIST]);
}
- test_assetDoesNotExist_path_noError() {
+ test_assetDoesNotExist_path_inRoot_noError() {
newFile('/sample/assets/my_icon.png');
assertNoErrors('''
name: sample
@@ -72,6 +72,16 @@
''');
}
+ test_assetDoesNotExist_path_inSubdir_noError() {
+ newFile('/sample/assets/images/2.0x/my_icon.png');
+ assertNoErrors('''
+name: sample
+flutter:
+ assets:
+ - assets/images/my_icon.png
+''');
+ }
+
@failingTest
test_assetDoesNotExist_uri_error() {
assertErrors('''
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index f47ce77..ea66e05 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -7008,6 +7008,65 @@
}
}
+ test_inferredType_implicitCreation() async {
+ shouldCompareLibraryElements = false;
+ var library = await checkLibrary(r'''
+class A {
+ A();
+ A.named();
+}
+var a1 = A();
+var a2 = A.named();
+''');
+ if (isStrongMode) {
+ checkElementText(library, r'''
+class A {
+ A();
+ A.named();
+}
+A a1;
+A a2;
+''');
+ } else {
+ checkElementText(library, r'''
+class A {
+ A();
+ A.named();
+}
+dynamic a1;
+dynamic a2;
+''');
+ }
+ }
+
+ test_inferredType_implicitCreation_prefixed() async {
+ shouldCompareLibraryElements = false;
+ addLibrarySource('/foo.dart', '''
+class A {
+ A();
+ A.named();
+}
+''');
+ var library = await checkLibrary('''
+import 'foo.dart' as foo;
+var a1 = foo.A();
+var a2 = foo.A.named();
+''');
+ if (isStrongMode) {
+ checkElementText(library, r'''
+import 'foo.dart' as foo;
+A a1;
+A a2;
+''');
+ } else {
+ checkElementText(library, r'''
+import 'foo.dart' as foo;
+dynamic a1;
+dynamic a2;
+''');
+ }
+ }
+
test_inferredType_usesSyntheticFunctionType_functionTypedParam() async {
// AnalysisContext does not set the enclosing element for the synthetic
// FunctionElement created for the [f, g] type argument.
diff --git a/pkg/analyzer_cli/lib/src/context_cache.dart b/pkg/analyzer_cli/lib/src/context_cache.dart
index 578293c..7c82294 100644
--- a/pkg/analyzer_cli/lib/src/context_cache.dart
+++ b/pkg/analyzer_cli/lib/src/context_cache.dart
@@ -95,7 +95,9 @@
contextOptions.hint = !clOptions.disableHints;
contextOptions.generateImplicitErrors = clOptions.showPackageWarnings;
contextOptions.generateSdkErrors = clOptions.showSdkWarnings;
- contextOptions.previewDart2 = clOptions.previewDart2;
+ if (clOptions.previewDart2 != null) {
+ contextOptions.previewDart2 = clOptions.previewDart2;
+ }
if (clOptions.useCFE) {
contextOptions.useFastaParser = true;
}
diff --git a/pkg/analyzer_cli/lib/src/options.dart b/pkg/analyzer_cli/lib/src/options.dart
index 831841b..52bcbb3 100644
--- a/pkg/analyzer_cli/lib/src/options.dart
+++ b/pkg/analyzer_cli/lib/src/options.dart
@@ -191,7 +191,8 @@
machineFormat = args['format'] == 'machine',
perfReport = args['x-perf-report'],
useCFE = args['use-cfe'],
- previewDart2 = args['preview-dart-2'],
+ previewDart2 =
+ args.wasParsed('preview-dart-2') ? args['preview-dart-2'] : null,
batchMode = args['batch'],
showPackageWarnings = args['show-package-warnings'] ||
args['package-warnings'] ||
@@ -519,10 +520,7 @@
negatable: false,
hide: hide)
..addFlag('preview-dart-2',
- help: 'Enable the Dart 2.0 preview.',
- defaultsTo: false,
- negatable: false,
- hide: hide);
+ help: 'Enable the Dart 2.0 preview.', hide: hide);
try {
if (args.contains('--$ignoreUnrecognizedFlagsFlag')) {
diff --git a/pkg/analyzer_cli/test/options_test.dart b/pkg/analyzer_cli/test/options_test.dart
index a9e07f4..bdde061 100644
--- a/pkg/analyzer_cli/test/options_test.dart
+++ b/pkg/analyzer_cli/test/options_test.dart
@@ -75,7 +75,7 @@
expect(options.strongMode, isFalse);
expect(options.lintsAreFatal, isFalse);
expect(options.useCFE, isFalse);
- expect(options.previewDart2, isFalse);
+ expect(options.previewDart2, null);
});
test('batch', () {
@@ -256,6 +256,12 @@
CommandLineOptions.parse(['--preview-dart-2', 'foo.dart']);
expect(options.previewDart2, isTrue);
});
+
+ test('--no-preview-dart-2', () {
+ CommandLineOptions options =
+ CommandLineOptions.parse(['--no-preview-dart-2', 'foo.dart']);
+ expect(options.previewDart2, isFalse);
+ });
});
});
defineReflectiveTests(CommandLineOptionsTest);
diff --git a/pkg/analyzer_plugin/pubspec.yaml b/pkg/analyzer_plugin/pubspec.yaml
index 02b20bb..9fdfd1a 100644
--- a/pkg/analyzer_plugin/pubspec.yaml
+++ b/pkg/analyzer_plugin/pubspec.yaml
@@ -1,6 +1,6 @@
name: analyzer_plugin
description: A framework for building plugins for the analysis server.
-version: 0.0.1-alpha.0
+version: 0.0.1-alpha.2
author: Dart Team <misc@dartlang.org>
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer_plugin
@@ -8,9 +8,10 @@
sdk: '>=1.8.0 <2.0.0'
dependencies:
- analyzer: '^0.31.0-alpha.1'
+ analyzer: '^0.31.2-alpha.1'
charcode: '^1.1.0'
html: '^0.13.1'
+ meta: ^1.0.2
path: '^1.4.1'
pub_semver: '^1.3.2'
diff --git a/pkg/compiler/lib/src/common_elements.dart b/pkg/compiler/lib/src/common_elements.dart
index e1f2ad8..e01a9cc 100644
--- a/pkg/compiler/lib/src/common_elements.dart
+++ b/pkg/compiler/lib/src/common_elements.dart
@@ -1074,6 +1074,8 @@
FunctionEntity get instantiate1 => _findHelperFunction('instantiate1');
FunctionEntity get instantiate2 => _findHelperFunction('instantiate2');
FunctionEntity get instantiate3 => _findHelperFunction('instantiate3');
+ FunctionEntity get instantiatedGenericFunctionType =>
+ _findHelperFunction('instantiatedGenericFunctionType');
// From dart:_internal
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
index 3b2ccaa..ab0a2ae 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
@@ -1964,7 +1964,7 @@
} else if (annotation.isTypedef || annotation.isFunctionType) {
otherType = closedWorld.commonMasks.functionType;
} else {
- assert(annotation.isTypeVariable);
+ assert(annotation.isTypeVariable || annotation.isFunctionTypeVariable);
// TODO(ngeoffray): Narrow to bound.
return type;
}
diff --git a/pkg/compiler/lib/src/js_backend/backend_impact.dart b/pkg/compiler/lib/src/js_backend/backend_impact.dart
index e712bee..363d50f 100644
--- a/pkg/compiler/lib/src/js_backend/backend_impact.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_impact.dart
@@ -794,6 +794,7 @@
_commonElements.instantiate1,
_commonElements.instantiate2,
_commonElements.instantiate3,
+ _commonElements.instantiatedGenericFunctionType,
], instantiatedClasses: [
_commonElements.instantiation1Class,
_commonElements.instantiation2Class,
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index 66f8e79..ec4fc0f 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -4,6 +4,7 @@
library js_backend.runtime_types;
+import '../common/names.dart' show Identifiers;
import '../common_elements.dart' show CommonElements, ElementEnvironment;
import '../elements/elements.dart' show ClassElement;
import '../elements/entities.dart';
@@ -170,20 +171,6 @@
/// Return all classes needed for runtime type information.
Iterable<ClassEntity> get requiredClasses;
-
- /// Return all classes immediately used in explicit or implicit is-tests.
- ///
- /// An is-test of `o is List<String>` will add `List`, but _not_ `String` to
- /// the [checkedClasses] set.
- Iterable<ClassEntity> get checkedClasses;
-
- // Returns all function types immediately used in explicit or implicit
- // is-tests.
- //
- // An is-test of `of is Function(Function())` will add `Function(Function())`
- // but _not_ `Function()` to the [checkedFunctionTypes] set. An is-test
- // against a typedef will add its alias to the [checkedFunctionTypes] set.
- Iterable<FunctionType> get checkedFunctionTypes;
}
class TrivialTypesChecks implements RuntimeTypesChecks {
@@ -201,12 +188,6 @@
@override
Iterable<ClassEntity> getReferencedClasses(FunctionType type) => _allClasses;
-
- @override
- Iterable<ClassEntity> get checkedClasses => _allClasses;
-
- @override
- Iterable<FunctionType> get checkedFunctionTypes => const <FunctionType>[];
}
/// Interface for computing the needed runtime type checks.
@@ -238,15 +219,17 @@
RuntimeTypesChecks computeRequiredChecks(
CodegenWorldBuilder codegenWorldBuilder) {
rtiChecksBuilderClosed = true;
- ClassUse classUse = new ClassUse()
- ..instance = true
- ..checkedInstance = true
- ..typeArgument = true
- ..checkedTypeArgument = true;
+
Map<ClassEntity, ClassUse> classUseMap = <ClassEntity, ClassUse>{};
for (ClassEntity cls in _closedWorld
.getClassSet(_closedWorld.commonElements.objectClass)
.subtypes()) {
+ ClassUse classUse = new ClassUse()
+ ..instance = true
+ ..checkedInstance = true
+ ..typeArgument = true
+ ..checkedTypeArgument = true
+ ..functionType = _computeFunctionType(_elementEnvironment, cls);
classUseMap[cls] = classUse;
}
TypeChecks typeChecks = _substitutions._requiredChecks =
@@ -307,9 +290,9 @@
ClassChecks computeChecks(ClassEntity cls) {
if (!handled.add(cls)) return result[cls];
- ClassChecks checks = new ClassChecks();
- result[cls] = checks;
ClassUse classUse = classUseMap[cls] ?? emptyUse;
+ ClassChecks checks = new ClassChecks(classUse.functionType);
+ result[cls] = checks;
// Find the superclass from which [cls] inherits checks.
ClassEntity superClass = _elementEnvironment.getSuperClass(cls,
@@ -1494,11 +1477,8 @@
class _RuntimeTypesChecks implements RuntimeTypesChecks {
final RuntimeTypesSubstitutions _substitutions;
final TypeChecks requiredChecks;
- final Iterable<ClassEntity> checkedClasses;
- final Iterable<FunctionType> checkedFunctionTypes;
- _RuntimeTypesChecks(this._substitutions, this.requiredChecks,
- this.checkedClasses, this.checkedFunctionTypes);
+ _RuntimeTypesChecks(this._substitutions, this.requiredChecks);
@override
Iterable<ClassEntity> get requiredClasses {
@@ -1586,11 +1566,25 @@
classUseMap.putIfAbsent(t.element, () => new ClassUse());
classUse.instance = true;
});
- Set<FunctionType> instantiatedClosureTypes =
- computeInstantiatedClosureTypes(codegenWorldBuilder);
- instantiatedClosureTypes.forEach((t) {
- testedTypeVisitor.visitType(t, false);
- });
+
+ for (InterfaceType instantiatedType
+ in codegenWorldBuilder.instantiatedTypes) {
+ FunctionType callType = _types.getCallType(instantiatedType);
+ if (callType != null) {
+ testedTypeVisitor.visitType(callType, false);
+ }
+ }
+
+ for (FunctionEntity element
+ in codegenWorldBuilder.staticFunctionsNeedingGetter) {
+ FunctionType functionType = _elementEnvironment.getFunctionType(element);
+ testedTypeVisitor.visitType(functionType, false);
+ }
+
+ for (FunctionEntity element in codegenWorldBuilder.closurizedMembers) {
+ FunctionType functionType = _elementEnvironment.getFunctionType(element);
+ testedTypeVisitor.visitType(functionType, false);
+ }
void processMethodTypeArguments(_, Set<DartType> typeArguments) {
for (DartType typeArgument in typeArguments) {
@@ -1613,56 +1607,63 @@
explicitIsChecks.forEach(processCheckedType);
implicitIsChecks.forEach(processCheckedType);
+ // In Dart 1, a class that defines a `call` method implicitly has function
+ // type of its `call` method and needs a signature function for testing its
+ // function type against typedefs and function types that are used in
+ // is-checks.
+ //
+ // In Dart 2, a closure class implements the function type of its `call`
+ // method and needs a signature function for testing its function type
+ // against typedefs and function types that are used in is-checks.
+ if (checkedClasses.contains(_commonElements.functionClass) ||
+ checkedFunctionTypes.isNotEmpty) {
+ Set<ClassEntity> processedClasses = new Set<ClassEntity>();
+
+ void processClass(ClassEntity cls) {
+ ClassFunctionType functionType =
+ _computeFunctionType(_elementEnvironment, cls);
+ if (functionType != null) {
+ ClassUse classUse =
+ classUseMap.putIfAbsent(cls, () => new ClassUse());
+ classUse.functionType = functionType;
+ }
+ }
+
+ void processSuperClasses(ClassEntity cls, [ClassUse classUse]) {
+ while (cls != null && processedClasses.add(cls)) {
+ processClass(cls);
+ cls = _elementEnvironment.getSuperClass(cls);
+ }
+ }
+
+ // Collect classes that are 'live' either through instantiation or use in
+ // type arguments.
+ List<ClassEntity> liveClasses = <ClassEntity>[];
+ classUseMap.forEach((ClassEntity cls, ClassUse classUse) {
+ if (classUse.isLive) {
+ liveClasses.add(cls);
+ }
+ });
+ liveClasses.forEach(processSuperClasses);
+ }
+
cachedRequiredChecks = _computeChecks(classUseMap);
rtiChecksBuilderClosed = true;
- return new _RuntimeTypesChecks(
- this, cachedRequiredChecks, checkedClasses, checkedFunctionTypes);
+ return new _RuntimeTypesChecks(this, cachedRequiredChecks);
}
+}
- Set<FunctionType> computeInstantiatedClosureTypes(
- CodegenWorldBuilder codegenWorldBuilder) {
- Set<FunctionType> instantiatedClosureTypes = new Set<FunctionType>();
- for (InterfaceType instantiatedType
- in codegenWorldBuilder.instantiatedTypes) {
- FunctionType callType = _types.getCallType(instantiatedType);
- if (callType != null) {
- instantiatedClosureTypes.add(callType);
- }
- }
- for (FunctionEntity element
- in codegenWorldBuilder.staticFunctionsNeedingGetter) {
- instantiatedClosureTypes
- .add(_elementEnvironment.getFunctionType(element));
- }
-
- for (FunctionEntity element in codegenWorldBuilder.closurizedMembers) {
- instantiatedClosureTypes
- .add(_elementEnvironment.getFunctionType(element));
- }
- return instantiatedClosureTypes;
+// TODO(johnniwinther): Handle Dart 2 semantics.
+ClassFunctionType _computeFunctionType(
+ ElementEnvironment _elementEnvironment, ClassEntity cls) {
+ MemberEntity call =
+ _elementEnvironment.lookupLocalClassMember(cls, Identifiers.call);
+ if (call != null && call.isFunction) {
+ FunctionEntity callFunction = call;
+ FunctionType callType = _elementEnvironment.getFunctionType(callFunction);
+ return new ClassFunctionType(callFunction, callType);
}
-
- Set<DartType> computeInstantiatedTypesAndClosures(
- CodegenWorldBuilder codegenWorldBuilder) {
- Set<DartType> instantiatedTypes =
- new Set<DartType>.from(codegenWorldBuilder.instantiatedTypes);
- for (InterfaceType instantiatedType
- in codegenWorldBuilder.instantiatedTypes) {
- FunctionType callType = _types.getCallType(instantiatedType);
- if (callType != null) {
- instantiatedTypes.add(callType);
- }
- }
- for (FunctionEntity element
- in codegenWorldBuilder.staticFunctionsNeedingGetter) {
- instantiatedTypes.add(_elementEnvironment.getFunctionType(element));
- }
-
- for (FunctionEntity element in codegenWorldBuilder.closurizedMembers) {
- instantiatedTypes.add(_elementEnvironment.getFunctionType(element));
- }
- return instantiatedTypes;
- }
+ return null;
}
class RuntimeTypesEncoderImpl implements RuntimeTypesEncoder {
@@ -2277,9 +2278,13 @@
class ClassChecks {
final Map<ClassEntity, TypeCheck> _map;
- ClassChecks() : _map = <ClassEntity, TypeCheck>{};
+ final ClassFunctionType functionType;
- const ClassChecks.empty() : _map = const <ClassEntity, TypeCheck>{};
+ ClassChecks(this.functionType) : _map = <ClassEntity, TypeCheck>{};
+
+ const ClassChecks.empty()
+ : _map = const <ClassEntity, TypeCheck>{},
+ functionType = null;
void add(TypeCheck check) {
_map[check.cls] = check;
@@ -2296,6 +2301,18 @@
}
}
+/// Data needed for generating a signature function for the function type of
+/// a class.
+class ClassFunctionType {
+ /// The `call` function that defines the function type.
+ final MemberEntity callFunction;
+
+ /// The type of the `call` function.
+ final FunctionType callType;
+
+ ClassFunctionType(this.callFunction, this.callType);
+}
+
/// Runtime type usage for a class.
class ClassUse {
/// Whether the class is instantiated.
@@ -2321,7 +2338,7 @@
/// For instance `A` in:
///
/// class A {}
- /// main() => new List<A>() is List<String>();
+ /// main() => new List<A>() is List<String>;
///
bool typeArgument = false;
@@ -2330,10 +2347,24 @@
/// For instance `A` in:
///
/// class A {}
- /// main() => new List<String>() is List<A>();
+ /// main() => new List<String>() is List<A>;
///
bool checkedTypeArgument = false;
+ /// The function type of the class, if any.
+ ///
+ /// This is only set if the function type is needed at runtime. For instance,
+ /// if no function types are checked at runtime then the function type isn't
+ /// needed.
+ ///
+ /// Furthermore optimization might also omit function type that are known not
+ /// to be valid in any subtype test.
+ ClassFunctionType functionType;
+
+ /// `true` if the class is 'live' either through instantiation or use in
+ /// type arguments.
+ bool get isLive => instance || typeArgument;
+
String toString() {
List<String> properties = <String>[];
if (instance) {
@@ -2348,6 +2379,9 @@
if (checkedTypeArgument) {
properties.add('checkedTypeArgument');
}
+ if (functionType != null) {
+ properties.add('functionType');
+ }
return 'ClassUse(${properties.join(',')})';
}
}
diff --git a/pkg/compiler/lib/src/js_emitter/instantiation_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/instantiation_stub_generator.dart
index 08725fca..35ff906 100644
--- a/pkg/compiler/lib/src/js_emitter/instantiation_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/instantiation_stub_generator.dart
@@ -4,6 +4,7 @@
library dart2js.js_emitter.instantiation_stub_generator;
+import '../common_elements.dart' show CommonElements;
import '../elements/entities.dart';
import '../io/source_information.dart';
import '../js/js.dart' as jsAst;
@@ -17,12 +18,12 @@
import 'model.dart';
-import 'code_emitter_task.dart' show CodeEmitterTask;
+import 'code_emitter_task.dart' show CodeEmitterTask, Emitter;
// Generator of stubs required for Instantiation classes.
class InstantiationStubGenerator {
- // ignore: UNUSED_FIELD
final CodeEmitterTask _emitterTask;
+ final CommonElements _commonElements;
final Namer _namer;
final CodegenWorldBuilder _codegenWorldBuilder;
final ClosedWorld _closedWorld;
@@ -31,11 +32,14 @@
InstantiationStubGenerator(
this._emitterTask,
+ this._commonElements,
this._namer,
this._codegenWorldBuilder,
this._closedWorld,
this._sourceInformationStrategy);
+ Emitter get _emitter => _emitterTask.emitter;
+
/// Generates a stub to forward a call selector with no type arguments to a
/// call selector with stored types.
///
@@ -92,6 +96,33 @@
return new ParameterStubMethod(name, null, function);
}
+ /// Generates a stub for a 'signature' selector. The stub calls the underlying
+ /// function's 'signature' method and calls a helper to subsitute the type
+ /// parameters in the type term. The stub looks like this:
+ ///
+ /// ```
+ /// $signature:: function() {
+ /// return H.instantiatedGenericFunctionType(
+ /// this._genericClosure.$signature(),
+ /// this.$ti);
+ /// }
+ /// ```
+ ParameterStubMethod _generateSignatureStub(FieldEntity functionField) {
+ jsAst.Name operatorSignature = _namer.asName(_namer.operatorSignature);
+
+ jsAst.Fun function = js('function() { return #(this.#.#(), this.#); }', [
+ _emitter.staticFunctionAccess(
+ _commonElements.instantiatedGenericFunctionType),
+ _namer.fieldPropertyName(functionField),
+ operatorSignature,
+ _namer.rtiFieldJsName,
+ ]);
+ // TODO(sra): Generate source information for stub that has no member.
+ // TODO(sra): .withSourceInformation(sourceInformation);
+
+ return new ParameterStubMethod(operatorSignature, null, function);
+ }
+
// Returns all stubs for an instantiation class.
//
List<StubMethod> generateStubs(
@@ -124,6 +155,8 @@
for (Selector selector in callSelectors.keys) {
CallStructure callStructure = selector.callStructure;
if (callStructure.typeArgumentCount != 0) continue;
+ // TODO(sra): Eliminate selectors that are not supported by any generic
+ // function with [typeArgumentCount] type arguments.
CallStructure genericCallStructrure =
callStructure.withTypeArgumentCount(typeArgumentCount);
Selector genericSelector =
@@ -132,8 +165,7 @@
instantiationClass, functionField, selector, genericSelector));
}
- // TODO(sra): Generate $signature() stub that forwards to
- // $instantiatedSignature() method of _f.
+ stubs.add(_generateSignatureStub(functionField));
return stubs;
}
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 db83938..7bc40d2 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
@@ -988,7 +988,12 @@
List<StubMethod> _generateInstantiationStubs(ClassEntity instantiationClass) {
InstantiationStubGenerator generator = new InstantiationStubGenerator(
- _task, _namer, _worldBuilder, _closedWorld, _sourceInformationStrategy);
+ _task,
+ _commonElements,
+ _namer,
+ _worldBuilder,
+ _closedWorld,
+ _sourceInformationStrategy);
return generator.generateStubs(instantiationClass, null);
}
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 532499d..e856ec6 100644
--- a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
@@ -23,17 +23,16 @@
import '../js_backend/namer.dart' show Namer;
import '../js_backend/runtime_types.dart'
show
+ ClassChecks,
RuntimeTypesChecks,
RuntimeTypesEncoder,
Substitution,
- TypeCheck,
- TypeChecks;
+ TypeCheck;
import '../js_emitter/sorter.dart';
import '../js_model/closure.dart' show JClosureField;
import '../util/util.dart' show Setlet;
import 'code_emitter_task.dart' show CodeEmitterTask;
-import 'type_test_registry.dart' show TypeTestRegistry;
// Function signatures used in the generation of runtime type information.
typedef void FunctionTypeSignatureEmitter(
@@ -131,14 +130,6 @@
this._strongMode,
this._disableRtiOptimization);
- TypeTestRegistry get _typeTestRegistry => emitterTask.typeTestRegistry;
-
- Iterable<ClassEntity> get checkedClasses =>
- _typeTestRegistry.rtiChecks.checkedClasses;
-
- Iterable<FunctionType> get checkedFunctionTypes =>
- _typeTestRegistry.rtiChecks.checkedFunctionTypes;
-
/// Generates all properties necessary for is-checks on the [classElement].
///
/// Returns an instance of [TypeTestProperties] that contains the properties
@@ -249,29 +240,20 @@
Setlet<ClassEntity> generated = new Setlet<ClassEntity>();
// Precomputed is checks.
- TypeChecks typeChecks = _rtiChecks.requiredChecks;
- Iterable<TypeCheck> classChecks = typeChecks[cls].checks;
- if (classChecks != null) {
- for (TypeCheck check in classChecks) {
- if (!generated.contains(check.cls)) {
- emitTypeCheck(check);
- generated.add(check.cls);
+ ClassChecks classChecks = _rtiChecks.requiredChecks[cls];
+ Iterable<TypeCheck> typeChecks = classChecks.checks;
+ if (typeChecks != null) {
+ for (TypeCheck typeCheck in typeChecks) {
+ if (!generated.contains(typeCheck.cls)) {
+ emitTypeCheck(typeCheck);
+ generated.add(typeCheck.cls);
}
}
}
- // A class that defines a `call` method implicitly implements
- // [Function] and needs checks for all typedefs that are used in is-checks.
- if (checkedClasses.contains(_commonElements.functionClass) ||
- checkedFunctionTypes.isNotEmpty) {
- MemberEntity call =
- _elementEnvironment.lookupLocalClassMember(cls, Identifiers.call);
- if (call != null && call.isFunction) {
- FunctionEntity callFunction = call;
- FunctionType callType =
- _elementEnvironment.getFunctionType(callFunction);
- generateFunctionTypeSignature(callFunction, callType);
- }
+ if (classChecks.functionType != null) {
+ generateFunctionTypeSignature(classChecks.functionType.callFunction,
+ classChecks.functionType.callType);
}
}
}
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index 06bdf3a..f582b52 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -453,6 +453,7 @@
return type.subst(typeVariables, typeParameters);
}
+ returnType = subst(returnType);
parameterTypes = parameterTypes.map(subst).toList();
optionalParameterTypes = optionalParameterTypes.map(subst).toList();
namedParameterTypes = namedParameterTypes.map(subst).toList();
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index d19b61e..a475ae1 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -1268,7 +1268,9 @@
return;
}
} else {
- value = typeBuilder.potentiallyCheckOrTrustType(value, _returnType);
+ if (!options.strongMode) {
+ value = typeBuilder.potentiallyCheckOrTrustType(value, _returnType);
+ }
}
}
handleInTryStatement();
diff --git a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
index 58d2169..239e873 100644
--- a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
@@ -2124,16 +2124,19 @@
]));
}
+ var mockMembers = _classProperties.mockMembers;
+
{
var extMembers = _classProperties.extensionMethods;
var staticMethods = <JS.Property>[];
var instanceMethods = <JS.Property>[];
- for (var method in classElem.methods) {
- // TODO(vsm): Clean up all the nasty duplication.
- if (method.isAbstract) {
- continue;
- }
+ var classMethods = classElem.methods.where((m) => !m.isAbstract).toList();
+ for (var m in mockMembers.values) {
+ if (m is MethodElement) classMethods.add(m);
+ }
+
+ for (var method in classMethods) {
var name = method.name;
var reifiedType = _getMemberRuntimeType(method);
var memberOverride =
@@ -2177,10 +2180,15 @@
var instanceGetters = <JS.Property>[];
var staticSetters = <JS.Property>[];
var instanceSetters = <JS.Property>[];
- for (var accessor in classElem.accessors) {
- if (accessor.isAbstract || accessor.isSynthetic) {
- continue;
- }
+
+ var classAccessors = classElem.accessors
+ .where((m) => !m.isAbstract && !m.isSynthetic)
+ .toList();
+ for (var m in mockMembers.values) {
+ if (m is PropertyAccessorElement) classAccessors.add(m);
+ }
+
+ for (var accessor in classAccessors) {
// Static getters/setters cannot be called with dynamic dispatch, nor
// can they be torn off.
// TODO(jmesserly): can we attach static method type info at the tearoff
@@ -2239,6 +2247,7 @@
{
var instanceFields = <JS.Property>[];
var staticFields = <JS.Property>[];
+
for (var field in classElem.fields) {
if (field.isSynthetic && !classElem.isEnum) continue;
// Only instance fields need to be saved for dynamic dispatch.
diff --git a/pkg/dev_compiler/lib/src/analyzer/property_model.dart b/pkg/dev_compiler/lib/src/analyzer/property_model.dart
index 636ca24..617c9d8 100644
--- a/pkg/dev_compiler/lib/src/analyzer/property_model.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/property_model.dart
@@ -283,9 +283,10 @@
for (var i in type.interfaces) visit(i, true);
for (var m in [type.methods, type.accessors].expand((m) => m)) {
+ if (m.isStatic) continue;
if (isAbstract || m.isAbstract) {
mockMembers[m.name] = m;
- } else if (!m.isStatic) {
+ } else {
concreteMembers.add(m.name);
}
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 00f7201..44f684f 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -823,8 +823,8 @@
List<DartType> typeArguments = pop();
Object receiver = pop();
if (arguments != null && typeArguments != null) {
- assert(forest.argumentsTypes(arguments).isEmpty);
- forest.argumentsSetExplicitArgumentTypes(arguments, typeArguments);
+ assert(forest.argumentsTypeArguments(arguments).isEmpty);
+ forest.argumentsSetTypeArguments(arguments, typeArguments);
} else {
assert(typeArguments == null);
}
@@ -2534,7 +2534,7 @@
}
}
- List types = forest.argumentsTypes(arguments);
+ List types = forest.argumentsTypeArguments(arguments);
if (typeParameters != null && typeParameters.length != types.length) {
// TODO(paulberry): Report error in this case as well,
// after https://github.com/dart-lang/sdk/issues/32130 is fixed.
@@ -2643,8 +2643,8 @@
}
if (typeArguments != null) {
- assert(forest.argumentsTypes(arguments).isEmpty);
- forest.argumentsSetExplicitArgumentTypes(arguments, typeArguments);
+ assert(forest.argumentsTypeArguments(arguments).isEmpty);
+ forest.argumentsSetTypeArguments(arguments, typeArguments);
}
String errorName;
diff --git a/pkg/front_end/lib/src/fasta/kernel/fangorn.dart b/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
index 6771997..6aff6ed 100644
--- a/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
@@ -60,14 +60,13 @@
}
@override
- List<DartType> argumentsTypes(Arguments arguments) {
+ List<DartType> argumentsTypeArguments(Arguments arguments) {
return arguments.types;
}
@override
- void argumentsSetExplicitArgumentTypes(
- Arguments arguments, List<DartType> types) {
- ShadowArguments.setExplicitArgumentTypes(arguments, types);
+ void argumentsSetTypeArguments(Arguments arguments, List<DartType> types) {
+ ShadowArguments.setNonInferrableArgumentTypes(arguments, types);
}
@override
diff --git a/pkg/front_end/lib/src/fasta/kernel/forest.dart b/pkg/front_end/lib/src/fasta/kernel/forest.dart
index 3ff5778..0656e8c 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forest.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forest.dart
@@ -18,10 +18,9 @@
List<Expression> argumentsPositional(Arguments arguments);
- List argumentsTypes(Arguments arguments);
+ List argumentsTypeArguments(Arguments arguments);
- void argumentsSetExplicitArgumentTypes(
- Arguments arguments, covariant List types);
+ void argumentsSetTypeArguments(Arguments arguments, covariant List types);
Expression asLiteralString(Expression value);
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 4e9fc11..11440d4 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
@@ -97,12 +97,17 @@
: _hasExplicitTypeArguments = types != null && types.isNotEmpty,
super(positional, types: types, named: named);
- static void setExplicitArgumentTypes(
+ static void setNonInferrableArgumentTypes(
ShadowArguments arguments, List<DartType> types) {
arguments.types.clear();
arguments.types.addAll(types);
arguments._hasExplicitTypeArguments = true;
}
+
+ static void removeNonInferrableArgumentTypes(ShadowArguments arguments) {
+ arguments.types.clear();
+ arguments._hasExplicitTypeArguments = false;
+ }
}
/// Shadow object for [AsExpression].
@@ -1642,9 +1647,18 @@
@override
_inferInitializer(ShadowTypeInferrer inferrer) {
+ List<TypeParameter> classTypeParameters =
+ target.enclosingClass.typeParameters;
+ List<DartType> typeArguments =
+ new List<DartType>(classTypeParameters.length);
+ for (int i = 0; i < typeArguments.length; i++) {
+ typeArguments[i] = new TypeParameterType(classTypeParameters[i]);
+ }
+ ShadowArguments.setNonInferrableArgumentTypes(arguments, typeArguments);
inferrer.inferInvocation(null, fileOffset, target.function.functionType,
target.enclosingClass.thisType, arguments,
skipTypeArgumentInference: true);
+ ShadowArguments.removeNonInferrableArgumentTypes(arguments);
}
}
diff --git a/pkg/front_end/pubspec.yaml b/pkg/front_end/pubspec.yaml
index 0644769..c5970959 100644
--- a/pkg/front_end/pubspec.yaml
+++ b/pkg/front_end/pubspec.yaml
@@ -1,5 +1,5 @@
name: front_end
-version: 0.1.0-alpha.10
+version: 0.1.0-alpha.11
author: Dart Team <misc@dartlang.org>
description: Front end for compilation of Dart code.
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/front_end
diff --git a/pkg/front_end/test/fasta/messages_test.dart b/pkg/front_end/test/fasta/messages_test.dart
index e254b8d..9386d6e 100644
--- a/pkg/front_end/test/fasta/messages_test.dart
+++ b/pkg/front_end/test/fasta/messages_test.dart
@@ -16,10 +16,13 @@
import "package:yaml/yaml.dart" show YamlList, YamlMap, YamlNode, loadYamlNode;
import 'package:front_end/src/api_prototype/compiler_options.dart'
- show ProblemHandler;
+ show CompilerOptions;
import 'package:front_end/src/api_prototype/memory_file_system.dart'
- show MemoryFileSystem, MemoryFileSystemEntity;
+ show MemoryFileSystem;
+
+import 'package:front_end/src/compute_platform_binaries_location.dart'
+ show computePlatformBinariesLocation;
import 'package:front_end/src/fasta/fasta_codes.dart' show LocatedMessage;
@@ -31,13 +34,6 @@
import "../../tool/_fasta/entry_points.dart" show BatchCompiler;
-ProblemHandler problemHandler(List<List> problems) {
- return (LocatedMessage problem, Severity severity, String formatted, int line,
- int column) {
- problems.add([problem, severity, formatted, line, column]);
- };
-}
-
class MessageTestDescription extends TestDescription {
@override
final Uri uri;
@@ -67,15 +63,9 @@
final BatchCompiler compiler;
- final List<List> problems;
-
MessageTestSuite()
- : this.internal(new MemoryFileSystem(Uri.parse("org-dartlang-fasta:///")),
- <List>[]);
-
- MessageTestSuite.internal(this.fileSystem, this.problems)
- : compiler = new BatchCompiler.forTesting(
- new HybridFileSystem(fileSystem), problemHandler(problems));
+ : fileSystem = new MemoryFileSystem(Uri.parse("org-dartlang-fasta:///")),
+ compiler = new BatchCompiler(null);
/// Convert all the examples found in `messages.yaml` to a test
/// description. In addition, create a test description for each kind of
@@ -252,19 +242,6 @@
}
}
- Uri addSource(String name, List<int> bytes) {
- Uri uri = fileSystem.currentDirectory.resolve(name);
- MemoryFileSystemEntity entity = fileSystem.entityForUri(uri);
- entity.writeAsBytesSync(bytes);
- return uri;
- }
-
- List<List> takeProblems() {
- List<List> result = problems.toList();
- problems.clear();
- return result;
- }
-
String formatProblems(String message, Example example, List<List> problems) {
var span = example.node.span;
StringBuffer buffer = new StringBuffer();
@@ -413,14 +390,26 @@
Future<Result<Null>> run(Example example, MessageTestSuite suite) async {
if (example == null) return pass(null);
String name = "${example.expectedCode}/${example.name}";
- Uri uri = suite.addSource("${name}.dart", example.bytes);
+ Uri uri = suite.fileSystem.currentDirectory.resolve("${name}.dart");
+ suite.fileSystem.entityForUri(uri).writeAsBytesSync(example.bytes);
+ Uri output = uri.resolve("${uri.path}.dill");
+
print("Compiling $uri");
- List<List> problems;
- try {
- await suite.compiler.batchCompile(<String>["--strong", "$uri"]);
- } finally {
- problems = suite.takeProblems();
- }
+ List<List> problems = <List>[];
+
+ await suite.compiler.batchCompile(
+ new CompilerOptions()
+ ..sdkSummary = computePlatformBinariesLocation()
+ .resolve("vm_platform_strong.dill")
+ ..fileSystem = new HybridFileSystem(suite.fileSystem)
+ ..onProblem = (LocatedMessage problem, Severity severity,
+ String formatted, int line, int column) {
+ problems.add([problem, severity, formatted, line, column]);
+ }
+ ..strongMode = true,
+ uri,
+ output);
+
List<List> unexpectedProblems = <List>[];
for (List problem in problems) {
LocatedMessage message = problem[0];
diff --git a/pkg/front_end/test/src/incremental/hot_reload_e2e_test.dart b/pkg/front_end/test/src/incremental/hot_reload_e2e_test.dart
index 932fa35..23e91a3 100644
--- a/pkg/front_end/test/src/incremental/hot_reload_e2e_test.dart
+++ b/pkg/front_end/test/src/incremental/hot_reload_e2e_test.dart
@@ -71,6 +71,7 @@
fs.entityForUri(root).createDirectory();
writeFile(fs, 'a.dart', sourceA);
writeFile(fs, 'b.dart', sourceB);
+ writeFile(fs, 'c.dart', sourceC);
writeFile(fs, '.packages', '');
compiler = createIncrementalCompiler(
'org-dartlang-test:///a.dart', new HybridFileSystem(fs));
@@ -230,6 +231,55 @@
}
}
+class ReloadToplevelField extends TestCase {
+ @override
+ String get name => "reload top level field";
+
+ @override
+ Future run() async {
+ await startProgram(2);
+ Expect.stringEquals("part1 part2", await lines[1]);
+
+ writeFile(fs, 'b.dart', sourceB.replaceAll("part1", "part3"));
+ writeFile(fs, 'c.dart', r"""
+ void g() {
+ bField.a("a");
+ }
+
+ class B {
+ dynamic a;
+ B({this.a});
+ }
+
+ var bField = new B(a: (String s) => "$s");
+ """);
+
+ await rebuild(compiler, outputUri);
+ await hotReload();
+ Expect.stringEquals("part3 part2", await lines[2]);
+
+ writeFile(fs, 'b.dart', sourceB.replaceAll("part1", "part4"));
+ writeFile(fs, 'c.dart', r"""
+ void g() {
+ bField.a("a");
+ }
+
+ class B {
+ dynamic a;
+ dynamic b;
+ B({this.a});
+ }
+
+ var bField = new B(a: (String s) => "$s");
+ """);
+
+ await rebuild(compiler, outputUri);
+ await hotReload();
+ Expect.stringEquals("part4 part2", await lines[3]);
+ await programIsDone;
+ }
+}
+
main() {
asyncTest(() async {
await new InitialProgramIsValid().test();
@@ -237,6 +287,7 @@
await new ReloadAfterNonLeafLibraryModification().test();
await new ReloadAfterWholeProgramModification().test();
await new ReloadTwice().test();
+ await new ReloadToplevelField().test();
});
}
@@ -256,6 +307,7 @@
Future<bool> rebuild(IncrementalKernelGenerator compiler, Uri outputUri) async {
compiler.invalidate(Uri.parse("org-dartlang-test:///a.dart"));
compiler.invalidate(Uri.parse("org-dartlang-test:///b.dart"));
+ compiler.invalidate(Uri.parse("org-dartlang-test:///c.dart"));
var program = await compiler.computeDelta();
if (program != null && !program.libraries.isEmpty) {
await writeProgram(program, outputUri);
@@ -287,10 +339,12 @@
const sourceA = r'''
import 'dart:async';
import 'b.dart';
+import 'c.dart';
void main(List<String> args) {
var last = f();
print(last);
+ g();
// The argument indicates how many "visible" hot-reloads to run
int reloadCount = 0;
@@ -303,6 +357,7 @@
var result = f();
if (last != result) {
print(result);
+ g();
last = result;
if (--reloadCount == 0) timer.cancel();
}
@@ -316,5 +371,9 @@
get line => "part1";
''';
+const sourceC = r'''
+void g() {}
+''';
+
RegExp observatoryPortRegExp =
new RegExp("Observatory listening on http://127.0.0.1:\([0-9]*\)/");
diff --git a/pkg/front_end/testcases/mixin_inherited_setter_for_mixed_in_field.dart b/pkg/front_end/testcases/mixin_inherited_setter_for_mixed_in_field.dart
new file mode 100644
index 0000000..8f33bdf
--- /dev/null
+++ b/pkg/front_end/testcases/mixin_inherited_setter_for_mixed_in_field.dart
@@ -0,0 +1,24 @@
+// 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.
+
+class A {}
+
+class C<T extends A> {
+ T _field;
+
+ foo(T x) {
+ _field = x;
+ }
+}
+
+class D extends C<B> {}
+
+class Foo extends Object with C<B> {}
+
+class B extends A {}
+
+main() {
+ var foo = new Foo();
+ foo.foo(new B());
+}
diff --git a/pkg/front_end/testcases/mixin_inherited_setter_for_mixed_in_field.dart.direct.expect b/pkg/front_end/testcases/mixin_inherited_setter_for_mixed_in_field.dart.direct.expect
new file mode 100644
index 0000000..4affa80
--- /dev/null
+++ b/pkg/front_end/testcases/mixin_inherited_setter_for_mixed_in_field.dart.direct.expect
@@ -0,0 +1,39 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+}
+class C<T extends self::A> extends core::Object {
+ field self::C::T _field = null;
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method foo(self::C::T x) → dynamic {
+ this.{self::C::_field} = x;
+ }
+}
+class D extends self::C<self::B> {
+ synthetic constructor •() → void
+ : super self::C::•()
+ ;
+}
+abstract class _Foo&Object&C = core::Object with self::C<self::B> {
+}
+class Foo extends self::_Foo&Object&C {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+}
+class B extends self::A {
+ synthetic constructor •() → void
+ : super self::A::•()
+ ;
+}
+static method main() → dynamic {
+ dynamic foo = new self::Foo::•();
+ foo.foo(new self::B::•());
+}
diff --git a/pkg/front_end/testcases/mixin_inherited_setter_for_mixed_in_field.dart.direct.transformed.expect b/pkg/front_end/testcases/mixin_inherited_setter_for_mixed_in_field.dart.direct.transformed.expect
new file mode 100644
index 0000000..064c86e
--- /dev/null
+++ b/pkg/front_end/testcases/mixin_inherited_setter_for_mixed_in_field.dart.direct.transformed.expect
@@ -0,0 +1,42 @@
+class A extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+}
+class C<T extends mix::A> extends core::Object {
+ field mix::C::T _field = null;
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method foo(mix::C::T x) → dynamic {
+ this.{mix::C::_field} = x;
+ }
+}
+class D extends mix::C<mix::B> {
+ synthetic constructor •() → void
+ : super mix::C::•()
+ ;
+}
+abstract class _Foo&Object&C extends core::Object implements mix::C<mix::B> {
+ field mix::B _field = null;
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method foo(mix::B x) → dynamic {
+ this.{mix::C::_field} = x;
+ }
+}
+class Foo extends mix::_Foo&Object&C {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+}
+class B extends mix::A {
+ synthetic constructor •() → void
+ : super mix::A::•()
+ ;
+}
+static method main() → dynamic {
+ dynamic foo = new mix::Foo::•();
+ foo.foo(new mix::B::•());
+}
diff --git a/pkg/front_end/testcases/mixin_inherited_setter_for_mixed_in_field.dart.outline.expect b/pkg/front_end/testcases/mixin_inherited_setter_for_mixed_in_field.dart.outline.expect
new file mode 100644
index 0000000..dbe9a87
--- /dev/null
+++ b/pkg/front_end/testcases/mixin_inherited_setter_for_mixed_in_field.dart.outline.expect
@@ -0,0 +1,31 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → void
+ ;
+}
+class C<T extends self::A> extends core::Object {
+ field self::C::T _field;
+ synthetic constructor •() → void
+ ;
+ method foo(self::C::T x) → dynamic
+ ;
+}
+class D extends self::C<self::B> {
+ synthetic constructor •() → void
+ ;
+}
+abstract class _Foo&Object&C = core::Object with self::C<self::B> {
+}
+class Foo extends self::_Foo&Object&C {
+ synthetic constructor •() → void
+ ;
+}
+class B extends self::A {
+ synthetic constructor •() → void
+ ;
+}
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/mixin_inherited_setter_for_mixed_in_field.dart.strong.expect b/pkg/front_end/testcases/mixin_inherited_setter_for_mixed_in_field.dart.strong.expect
new file mode 100644
index 0000000..453c4fe
--- /dev/null
+++ b/pkg/front_end/testcases/mixin_inherited_setter_for_mixed_in_field.dart.strong.expect
@@ -0,0 +1,44 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+}
+class C<T extends self::A> extends core::Object {
+ generic-covariant-impl generic-covariant-interface field self::C::T _field = null;
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method foo(generic-covariant-impl generic-covariant-interface self::C::T x) → dynamic {
+ this.{self::C::_field} = x;
+ }
+}
+class D extends self::C<self::B> {
+ synthetic constructor •() → void
+ : super self::C::•()
+ ;
+ abstract forwarding-stub method foo(generic-covariant-impl self::B x) → dynamic;
+ abstract forwarding-stub set _field(generic-covariant-impl self::B _) → void;
+}
+abstract class _Foo&Object&C = core::Object with self::C<self::B> {
+ abstract forwarding-stub method foo(generic-covariant-impl self::B x) → dynamic;
+ abstract forwarding-stub set _field(generic-covariant-impl self::B _) → void;
+}
+class Foo extends self::_Foo&Object&C {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ abstract forwarding-stub set _field(generic-covariant-impl self::B _) → void;
+}
+class B extends self::A {
+ synthetic constructor •() → void
+ : super self::A::•()
+ ;
+}
+static method main() → dynamic {
+ self::Foo foo = new self::Foo::•();
+ foo.{self::C::foo}(new self::B::•());
+}
diff --git a/pkg/front_end/testcases/mixin_inherited_setter_for_mixed_in_field.dart.strong.transformed.expect b/pkg/front_end/testcases/mixin_inherited_setter_for_mixed_in_field.dart.strong.transformed.expect
new file mode 100644
index 0000000..8935444
--- /dev/null
+++ b/pkg/front_end/testcases/mixin_inherited_setter_for_mixed_in_field.dart.strong.transformed.expect
@@ -0,0 +1,45 @@
+class A extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+}
+class C<T extends mix::A> extends core::Object {
+ generic-covariant-impl generic-covariant-interface field mix::C::T _field = null;
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method foo(generic-covariant-impl generic-covariant-interface mix::C::T x) → dynamic {
+ this.{mix::C::_field} = x;
+ }
+}
+class D extends mix::C<mix::B> {
+ synthetic constructor •() → void
+ : super mix::C::•()
+ ;
+ abstract forwarding-stub method foo(generic-covariant-impl mix::B x) → dynamic;
+ abstract forwarding-stub set _field(generic-covariant-impl mix::B _) → void;
+}
+abstract class _Foo&Object&C extends core::Object implements mix::C<mix::B> {
+ generic-covariant-impl field mix::B _field = null;
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method foo(generic-covariant-impl mix::B x) → dynamic {
+ this.{mix::C::_field} = x;
+ }
+}
+class Foo extends mix::_Foo&Object&C {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ abstract forwarding-stub set _field(generic-covariant-impl mix::B _) → void;
+}
+class B extends mix::A {
+ synthetic constructor •() → void
+ : super mix::A::•()
+ ;
+}
+static method main() → dynamic {
+ mix::Foo foo = new mix::Foo::•();
+ foo.{mix::C::foo}(new mix::B::•());
+}
diff --git a/pkg/front_end/testcases/redirecting_initializer_arguments_assignable_test.dart b/pkg/front_end/testcases/redirecting_initializer_arguments_assignable_test.dart
new file mode 100644
index 0000000..e05cd8a
--- /dev/null
+++ b/pkg/front_end/testcases/redirecting_initializer_arguments_assignable_test.dart
@@ -0,0 +1,18 @@
+// 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.
+
+// The test checks that types of arguments of redirecting initializers are
+// checked against the corresponding formal parameter types of the redirection
+// targets, and the downcasts are inserted where appropriate.
+
+class X {}
+
+class Foo<T extends X> {
+ T x;
+ Foo.fromX(X _init) : this._internal(x: _init);
+ Foo.fromT(T _init) : this._internal(x: _init);
+ Foo._internal({this.x});
+}
+
+void main() {}
diff --git a/pkg/front_end/testcases/redirecting_initializer_arguments_assignable_test.dart.direct.expect b/pkg/front_end/testcases/redirecting_initializer_arguments_assignable_test.dart.direct.expect
new file mode 100644
index 0000000..ff74d26
--- /dev/null
+++ b/pkg/front_end/testcases/redirecting_initializer_arguments_assignable_test.dart.direct.expect
@@ -0,0 +1,22 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class X extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+}
+class Foo<T extends self::X> extends core::Object {
+ field self::Foo::T x;
+ constructor fromX(self::X _init) → void
+ : this self::Foo::_internal(x: _init)
+ ;
+ constructor fromT(self::Foo::T _init) → void
+ : this self::Foo::_internal(x: _init)
+ ;
+ constructor _internal({self::Foo::T x = null}) → void
+ : self::Foo::x = x, super core::Object::•()
+ ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/redirecting_initializer_arguments_assignable_test.dart.outline.expect b/pkg/front_end/testcases/redirecting_initializer_arguments_assignable_test.dart.outline.expect
new file mode 100644
index 0000000..5cbe7eb
--- /dev/null
+++ b/pkg/front_end/testcases/redirecting_initializer_arguments_assignable_test.dart.outline.expect
@@ -0,0 +1,19 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class X extends core::Object {
+ synthetic constructor •() → void
+ ;
+}
+class Foo<T extends self::X> extends core::Object {
+ field self::Foo::T x;
+ constructor fromX(self::X _init) → void
+ ;
+ constructor fromT(self::Foo::T _init) → void
+ ;
+ constructor _internal({self::Foo::T x}) → void
+ ;
+}
+static method main() → void
+ ;
diff --git a/pkg/front_end/testcases/redirecting_initializer_arguments_assignable_test.dart.strong.expect b/pkg/front_end/testcases/redirecting_initializer_arguments_assignable_test.dart.strong.expect
new file mode 100644
index 0000000..81b63fc
--- /dev/null
+++ b/pkg/front_end/testcases/redirecting_initializer_arguments_assignable_test.dart.strong.expect
@@ -0,0 +1,22 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class X extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+}
+class Foo<T extends self::X> extends core::Object {
+ generic-covariant-impl generic-covariant-interface field self::Foo::T x;
+ constructor fromX(self::X _init) → void
+ : this self::Foo::_internal(x: _init as{TypeError} self::Foo::T)
+ ;
+ constructor fromT(self::Foo::T _init) → void
+ : this self::Foo::_internal(x: _init)
+ ;
+ constructor _internal({self::Foo::T x = null}) → void
+ : self::Foo::x = x, super core::Object::•()
+ ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/redirecting_initializer_arguments_test.dart b/pkg/front_end/testcases/redirecting_initializer_arguments_test.dart
new file mode 100644
index 0000000..9dbb286
--- /dev/null
+++ b/pkg/front_end/testcases/redirecting_initializer_arguments_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// The test checks that types of arguments of redirecting initializers are
+// checked against the corresponding formal parameter types of the redirection
+// targets, and the compile-time error is emitted in the case they are not
+// assignable.
+
+class Foo<T> {
+ T x;
+ Foo.from(String _init) : this._internal(x: _init);
+ Foo._internal({this.x});
+}
+
+void main() {}
diff --git a/pkg/front_end/testcases/redirecting_initializer_arguments_test.dart.direct.expect b/pkg/front_end/testcases/redirecting_initializer_arguments_test.dart.direct.expect
new file mode 100644
index 0000000..d42aaa0
--- /dev/null
+++ b/pkg/front_end/testcases/redirecting_initializer_arguments_test.dart.direct.expect
@@ -0,0 +1,14 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Foo<T extends core::Object> extends core::Object {
+ field self::Foo::T x;
+ constructor from(core::String _init) → void
+ : this self::Foo::_internal(x: _init)
+ ;
+ constructor _internal({self::Foo::T x = null}) → void
+ : self::Foo::x = x, super core::Object::•()
+ ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/redirecting_initializer_arguments_test.dart.outline.expect b/pkg/front_end/testcases/redirecting_initializer_arguments_test.dart.outline.expect
new file mode 100644
index 0000000..10bf447
--- /dev/null
+++ b/pkg/front_end/testcases/redirecting_initializer_arguments_test.dart.outline.expect
@@ -0,0 +1,13 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Foo<T extends core::Object> extends core::Object {
+ field self::Foo::T x;
+ constructor from(core::String _init) → void
+ ;
+ constructor _internal({self::Foo::T x}) → void
+ ;
+}
+static method main() → void
+ ;
diff --git a/pkg/front_end/testcases/redirecting_initializer_arguments_test.dart.strong.expect b/pkg/front_end/testcases/redirecting_initializer_arguments_test.dart.strong.expect
new file mode 100644
index 0000000..910fa36
--- /dev/null
+++ b/pkg/front_end/testcases/redirecting_initializer_arguments_test.dart.strong.expect
@@ -0,0 +1,17 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Foo<T extends core::Object> extends core::Object {
+ generic-covariant-impl generic-covariant-interface field self::Foo::T x;
+ constructor from(core::String _init) → void
+ : this self::Foo::_internal(x: let final dynamic #t1 = _init in let dynamic _ = null in invalid-expression "pkg/front_end/testcases/redirecting_initializer_arguments_test.dart:12:46: Error: A value of type 'dart.core::String' can't be assigned to a variable of type '#lib1::Foo::T'.
+Try changing the type of the left hand side, or casting the right hand side to '#lib1::Foo::T'.
+ Foo.from(String _init) : this._internal(x: _init);
+ ^")
+ ;
+ constructor _internal({self::Foo::T x = null}) → void
+ : self::Foo::x = x, super core::Object::•()
+ ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/tool/_fasta/command_line.dart b/pkg/front_end/tool/_fasta/command_line.dart
index 82caa0e..c504e29 100644
--- a/pkg/front_end/tool/_fasta/command_line.dart
+++ b/pkg/front_end/tool/_fasta/command_line.dart
@@ -7,9 +7,7 @@
import 'dart:io' show exit;
import 'package:front_end/src/api_prototype/compiler_options.dart'
- show CompilerOptions, ProblemHandler;
-
-import 'package:front_end/src/api_prototype/file_system.dart' show FileSystem;
+ show CompilerOptions;
import 'package:front_end/src/base/processed_options.dart'
show ProcessedOptions;
@@ -34,6 +32,8 @@
import 'package:kernel/target/targets.dart'
show Target, getTarget, TargetFlags, targets;
+Uri resolveFile(String path) => Uri.base.resolveUri(new Uri.file(path));
+
class CommandLineProblem {
final Message message;
@@ -159,7 +159,7 @@
"but expected one of: 'true', 'false', 'yes', or 'no'.");
}
} else if (valueSpecification == Uri) {
- parsedValue = Uri.base.resolveUri(new Uri.file(value));
+ parsedValue = resolveFile(value);
} else if (valueSpecification == String) {
parsedValue = value;
} else if (valueSpecification is String) {
@@ -228,9 +228,7 @@
String programName,
ParsedArguments parsedArguments,
bool areRestArgumentsInputs,
- bool verbose,
- FileSystem fileSystem,
- ProblemHandler problemHandler) {
+ bool verbose) {
final Map<String, dynamic> options = parsedArguments.options;
final List<String> arguments = parsedArguments.arguments;
@@ -299,11 +297,8 @@
return new ProcessedOptions(
new CompilerOptions()
- ..fileSystem = fileSystem
- ..onProblem = problemHandler
..sdkSummary = options["--platform"]
- ..librariesSpecificationUri =
- Uri.base.resolveUri(new Uri.file(arguments[1]))
+ ..librariesSpecificationUri = resolveFile(arguments[1])
..setExitCodeOnProblem = true
..chaseDependencies = true
..packagesFileUri = packages
@@ -318,12 +313,12 @@
..verify = verify,
false,
<Uri>[Uri.parse(arguments[0])],
- Uri.base.resolveUri(new Uri.file(arguments[2])));
+ resolveFile(arguments[2]));
} else if (arguments.isEmpty) {
return throw new CommandLineProblem.deprecated("No Dart file specified.");
}
- final Uri defaultOutput = Uri.base.resolve("${arguments.first}.dill");
+ final Uri defaultOutput = resolveFile("${arguments.first}.dill");
final Uri output = options["-o"] ?? options["--output"] ?? defaultOutput;
@@ -335,8 +330,6 @@
computePlatformBinariesLocation().resolve("vm_platform.dill"));
CompilerOptions compilerOptions = new CompilerOptions()
- ..fileSystem = fileSystem
- ..onProblem = problemHandler
..compileSdk = compileSdk
..sdkRoot = sdk
..sdkSummary = platform
@@ -353,9 +346,11 @@
// TODO(ahe): What about chase dependencies?
- var inputs = <Uri>[];
+ List<Uri> inputs = <Uri>[];
if (areRestArgumentsInputs) {
- inputs = arguments.map(Uri.base.resolve).toList();
+ for (String argument in arguments) {
+ inputs.add(resolveFile(argument));
+ }
}
return new ProcessedOptions(compilerOptions, false, inputs, output);
}
@@ -364,10 +359,7 @@
String programName,
List<String> arguments,
bool areRestArgumentsInputs,
- dynamic f(CompilerContext context, List<String> restArguments),
- {FileSystem fileSystem,
- ProblemHandler problemHandler}) {
- fileSystem ??= new CompilerOptions().fileSystem;
+ dynamic f(CompilerContext context, List<String> restArguments)) {
bool verbose = false;
for (String argument in arguments) {
if (argument == "--") break;
@@ -381,8 +373,8 @@
CommandLineProblem problem;
try {
parsedArguments = ParsedArguments.parse(arguments, optionSpecification);
- options = analyzeCommandLine(programName, parsedArguments,
- areRestArgumentsInputs, verbose, fileSystem, problemHandler);
+ options = analyzeCommandLine(
+ programName, parsedArguments, areRestArgumentsInputs, verbose);
} on CommandLineProblem catch (e) {
options = new ProcessedOptions(new CompilerOptions());
problem = e;
diff --git a/pkg/front_end/tool/_fasta/entry_points.dart b/pkg/front_end/tool/_fasta/entry_points.dart
index a68f9fd..8411f0e 100644
--- a/pkg/front_end/tool/_fasta/entry_points.dart
+++ b/pkg/front_end/tool/_fasta/entry_points.dart
@@ -18,9 +18,7 @@
import 'package:kernel/target/targets.dart' show TargetFlags, targets;
import 'package:front_end/src/api_prototype/compiler_options.dart'
- show ProblemHandler;
-
-import 'package:front_end/src/api_prototype/file_system.dart' show FileSystem;
+ show CompilerOptions;
import 'package:front_end/src/base/processed_options.dart'
show ProcessedOptions;
@@ -91,24 +89,16 @@
class BatchCompiler {
final Stream lines;
- final FileSystem fileSystem;
-
- final ProblemHandler problemHandler;
-
Uri platformUri;
Program platformComponent;
- BatchCompiler(this.lines)
- : fileSystem = null,
- problemHandler = null;
-
- BatchCompiler.forTesting(this.fileSystem, this.problemHandler) : lines = null;
+ BatchCompiler(this.lines);
run() async {
await for (String line in lines) {
try {
- if (await batchCompile(JSON.decode(line))) {
+ if (await batchCompileArguments(JSON.decode(line))) {
stdout.writeln(">>> TEST OK");
} else {
stdout.writeln(">>> TEST FAIL");
@@ -124,41 +114,49 @@
}
}
- Future<bool> batchCompile(List<String> arguments) async {
+ Future<bool> batchCompileArguments(List<String> arguments) async {
try {
return await withGlobalOptions("compile", arguments, true,
- (CompilerContext c, _) async {
- ProcessedOptions options = c.options;
- bool verbose = options.verbose;
- Ticker ticker = new Ticker(isVerbose: verbose);
- if (verbose) {
- print("Compiling directly to Kernel: ${arguments.join(' ')}");
- }
- if (platformComponent == null || platformUri != options.sdkSummary) {
- platformUri = options.sdkSummary;
- platformComponent = await options.loadSdkSummary(null);
- } else {
- options.sdkSummaryComponent = platformComponent;
- }
- CompileTask task = new CompileTask(c, ticker);
- await task.compile(sansPlatform: true);
- CanonicalName root = platformComponent.root;
- for (Library library in platformComponent.libraries) {
- library.parent = platformComponent;
- CanonicalName name = library.reference.canonicalName;
- if (name != null && name.parent != root) {
- root.adoptChild(name);
- }
- }
- root.unbindAll();
- return c.errors.isEmpty;
- }, fileSystem: fileSystem, problemHandler: problemHandler);
+ (CompilerContext c, _) => batchCompileImpl(c));
} on deprecated_InputError catch (e) {
CompilerContext.runWithDefaultOptions(
(c) => c.report(deprecated_InputError.toMessage(e), Severity.error));
return false;
}
}
+
+ Future<bool> batchCompile(CompilerOptions options, Uri input, Uri output) {
+ return CompilerContext.runWithOptions(
+ new ProcessedOptions(options, false, <Uri>[input], output),
+ batchCompileImpl);
+ }
+
+ Future<bool> batchCompileImpl(CompilerContext c) async {
+ ProcessedOptions options = c.options;
+ bool verbose = options.verbose;
+ Ticker ticker = new Ticker(isVerbose: verbose);
+ if (platformComponent == null || platformUri != options.sdkSummary) {
+ platformUri = options.sdkSummary;
+ platformComponent = await options.loadSdkSummary(null);
+ if (platformComponent == null) {
+ throw "platformComponent is null";
+ }
+ } else {
+ options.sdkSummaryComponent = platformComponent;
+ }
+ CompileTask task = new CompileTask(c, ticker);
+ await task.compile(sansPlatform: true);
+ CanonicalName root = platformComponent.root;
+ for (Library library in platformComponent.libraries) {
+ library.parent = platformComponent;
+ CanonicalName name = library.reference.canonicalName;
+ if (name != null && name.parent != root) {
+ root.adoptChild(name);
+ }
+ }
+ root.unbindAll();
+ return c.errors.isEmpty;
+ }
}
Future<KernelTarget> outline(List<String> arguments) async {
diff --git a/pkg/kernel/lib/class_hierarchy.dart b/pkg/kernel/lib/class_hierarchy.dart
index 55cd916..05ba206 100644
--- a/pkg/kernel/lib/class_hierarchy.dart
+++ b/pkg/kernel/lib/class_hierarchy.dart
@@ -702,7 +702,7 @@
// Build the class ordering based on a topological sort.
for (var library in _program.libraries) {
for (var classNode in library.classes) {
- _topologicalSortVisit(classNode, mixinInferrer);
+ _topologicalSortVisit(classNode);
}
}
@@ -726,6 +726,23 @@
// each class, and build their subtype sets as interval lists.
_topDownSortVisit(_infoFor[classes[0]]);
+ // Now that the intervals for subclass, mixer, and implementer queries are
+ // built, we may infer and record supertypes for the classes.
+ for (int i = 0; i < classes.length; ++i) {
+ Class classNode = classes[i];
+ _ClassInfo info = _infoFor[classNode];
+ if (classNode.supertype != null) {
+ _recordSuperTypes(info, classNode.supertype);
+ }
+ if (classNode.mixedInType != null) {
+ mixinInferrer?.infer(this, classNode);
+ _recordSuperTypes(info, classNode.mixedInType);
+ }
+ for (Supertype supertype in classNode.implementedTypes) {
+ _recordSuperTypes(info, supertype);
+ }
+ }
+
for (int i = 0; i < classes.length; ++i) {
var class_ = classes[i];
_buildInterfaceMembers(class_, _infoFor[class_], setters: true);
@@ -757,7 +774,7 @@
/// Returns the depth of the visited class (the number of steps in the longest
/// inheritance path to the root class).
int _topSortIndex = 0;
- int _topologicalSortVisit(Class classNode, MixinInferrer mixinInferrer) {
+ int _topologicalSortVisit(Class classNode) {
var info = _infoFor[classNode];
if (info != null) {
if (info.isBeingVisited) {
@@ -769,22 +786,15 @@
_infoFor[classNode] = info = new _ClassInfo(classNode);
info.isBeingVisited = true;
if (classNode.supertype != null) {
- superDepth = max(superDepth,
- _topologicalSortVisit(classNode.supertype.classNode, mixinInferrer));
- _recordSuperTypes(info, classNode.supertype);
+ superDepth =
+ max(superDepth, _topologicalSortVisit(classNode.supertype.classNode));
}
if (classNode.mixedInType != null) {
superDepth = max(
- superDepth,
- _topologicalSortVisit(
- classNode.mixedInType.classNode, mixinInferrer));
- if (mixinInferrer != null) mixinInferrer.infer(this, classNode);
- _recordSuperTypes(info, classNode.mixedInType);
+ superDepth, _topologicalSortVisit(classNode.mixedInType.classNode));
}
for (var supertype in classNode.implementedTypes) {
- superDepth = max(superDepth,
- _topologicalSortVisit(supertype.classNode, mixinInferrer));
- _recordSuperTypes(info, supertype);
+ superDepth = max(superDepth, _topologicalSortVisit(supertype.classNode));
}
_buildDeclaredMembers(classNode, info);
_buildImplementedMembers(classNode, info);
diff --git a/pkg/kernel/lib/transformations/mixin_full_resolution.dart b/pkg/kernel/lib/transformations/mixin_full_resolution.dart
index 59ec97b..24a5e33 100644
--- a/pkg/kernel/lib/transformations/mixin_full_resolution.dart
+++ b/pkg/kernel/lib/transformations/mixin_full_resolution.dart
@@ -137,9 +137,35 @@
// Clone fields and methods from the mixin class.
var substitution = getSubstitutionMap(class_.mixedInType);
var cloner = new CloneVisitor(typeSubstitution: substitution);
- for (var field in class_.mixin.fields) {
- class_.addMember(cloner.clone(field));
+
+ // When we copy a field from the mixed in class, we remove any
+ // forwarding-stub getters/setters from the superclass, but copy their
+ // covariance-bits onto the new field.
+ var nonSetters = <Name, Procedure>{};
+ var setters = <Name, Procedure>{};
+ for (var procedure in class_.procedures) {
+ if (procedure.isSetter) {
+ setters[procedure.name] = procedure;
+ } else {
+ nonSetters[procedure.name] = procedure;
+ }
}
+ for (var field in class_.mixin.fields) {
+ Field clone = cloner.clone(field);
+ Procedure setter = setters[field.name];
+ if (setter != null) {
+ setters.remove(field.name);
+ VariableDeclaration parameter =
+ setter.function.positionalParameters.first;
+ clone.isGenericCovariantImpl = parameter.isGenericCovariantImpl;
+ clone.isGenericCovariantInterface =
+ parameter.isGenericCovariantInterface;
+ }
+ nonSetters.remove(field.name);
+ class_.addMember(clone);
+ }
+ class_.procedures.clear();
+ class_.procedures..addAll(nonSetters.values)..addAll(setters.values);
// Existing procedures in the class should only be forwarding stubs.
// Replace them with methods from the mixin class if they have the same
diff --git a/pkg/kernel/pubspec.yaml b/pkg/kernel/pubspec.yaml
index f4f5728..6e17f7d 100644
--- a/pkg/kernel/pubspec.yaml
+++ b/pkg/kernel/pubspec.yaml
@@ -1,5 +1,5 @@
name: kernel
-version: 0.3.0-alpha.10
+version: 0.3.0-alpha.11
author: Dart Team <misc@dartlang.org>
description: Dart IR (Intermediate Representation)
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/kernel
diff --git a/pkg/vm/bin/gen_kernel.dart b/pkg/vm/bin/gen_kernel.dart
index c28e2fc..c2571f2 100644
--- a/pkg/vm/bin/gen_kernel.dart
+++ b/pkg/vm/bin/gen_kernel.dart
@@ -34,7 +34,7 @@
..addFlag('tfa',
help:
'Enable global type flow analysis and related transformations in AOT mode.',
- defaultsTo: false)
+ defaultsTo: true)
..addOption('entry-points',
help: 'Path to JSON file with the list of entry points',
allowMultiple: true);
diff --git a/runtime/bin/console.h b/runtime/bin/console.h
new file mode 100644
index 0000000..519d21c
--- /dev/null
+++ b/runtime/bin/console.h
@@ -0,0 +1,26 @@
+// 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.
+
+#ifndef RUNTIME_BIN_CONSOLE_H_
+#define RUNTIME_BIN_CONSOLE_H_
+
+#include "platform/globals.h"
+
+namespace dart {
+namespace bin {
+
+class Console {
+ public:
+ static void SaveConfig();
+ static void RestoreConfig();
+
+ private:
+ DISALLOW_ALLOCATION();
+ DISALLOW_IMPLICIT_CONSTRUCTORS(Console);
+};
+
+} // namespace bin
+} // namespace dart
+
+#endif // RUNTIME_BIN_CONSOLE_H_
diff --git a/runtime/bin/console_posix.cc b/runtime/bin/console_posix.cc
new file mode 100644
index 0000000..1abbe05
--- /dev/null
+++ b/runtime/bin/console_posix.cc
@@ -0,0 +1,92 @@
+// 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.
+
+#include "platform/globals.h"
+#if defined(HOST_OS_LINUX) || defined(HOST_OS_MACOS) || \
+ defined(HOST_OS_ANDROID) || defined(HOST_OS_FUCHSIA)
+
+#include "bin/console.h"
+
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <termios.h>
+
+#include "bin/fdutils.h"
+#include "platform/signal_blocker.h"
+
+namespace dart {
+namespace bin {
+
+class PosixConsole {
+ public:
+ static const tcflag_t kInvalidFlag = -1;
+
+ static void Initialize() {
+ SaveMode(STDOUT_FILENO, &stdout_initial_c_lflag_);
+ SaveMode(STDERR_FILENO, &stderr_initial_c_lflag_);
+ SaveMode(STDIN_FILENO, &stdin_initial_c_lflag_);
+ }
+
+ static void Cleanup() {
+ RestoreMode(STDOUT_FILENO, stdout_initial_c_lflag_);
+ RestoreMode(STDERR_FILENO, stderr_initial_c_lflag_);
+ RestoreMode(STDIN_FILENO, stdin_initial_c_lflag_);
+ ClearLFlags();
+ }
+
+ private:
+ static tcflag_t stdout_initial_c_lflag_;
+ static tcflag_t stderr_initial_c_lflag_;
+ static tcflag_t stdin_initial_c_lflag_;
+
+ static void ClearLFlags() {
+ stdout_initial_c_lflag_ = kInvalidFlag;
+ stderr_initial_c_lflag_ = kInvalidFlag;
+ stdin_initial_c_lflag_ = kInvalidFlag;
+ }
+
+ static void SaveMode(intptr_t fd, tcflag_t* flag) {
+ ASSERT(flag != NULL);
+ struct termios term;
+ int status = NO_RETRY_EXPECTED(tcgetattr(fd, &term));
+ if (status != 0) {
+ return;
+ }
+ *flag = term.c_lflag;
+ }
+
+ static void RestoreMode(intptr_t fd, tcflag_t flag) {
+ if (flag == kInvalidFlag) {
+ return;
+ }
+ struct termios term;
+ int status = NO_RETRY_EXPECTED(tcgetattr(fd, &term));
+ if (status != 0) {
+ return;
+ }
+ term.c_lflag = flag;
+ NO_RETRY_EXPECTED(tcsetattr(fd, TCSANOW, &term));
+ }
+
+ DISALLOW_ALLOCATION();
+ DISALLOW_IMPLICIT_CONSTRUCTORS(PosixConsole);
+};
+
+tcflag_t PosixConsole::stdout_initial_c_lflag_ = PosixConsole::kInvalidFlag;
+tcflag_t PosixConsole::stderr_initial_c_lflag_ = PosixConsole::kInvalidFlag;
+tcflag_t PosixConsole::stdin_initial_c_lflag_ = PosixConsole::kInvalidFlag;
+
+void Console::SaveConfig() {
+ PosixConsole::Initialize();
+}
+
+void Console::RestoreConfig() {
+ PosixConsole::Cleanup();
+}
+
+} // namespace bin
+} // namespace dart
+
+#endif // defined(HOST_OS_LINUX) || defined(HOST_OS_MACOS) || \
+ // defined(HOST_OS_ANDROID) || defined(HOST_OS_FUCHSIA)
diff --git a/runtime/bin/console_win.cc b/runtime/bin/console_win.cc
new file mode 100644
index 0000000..6442dc2
--- /dev/null
+++ b/runtime/bin/console_win.cc
@@ -0,0 +1,143 @@
+// 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.
+
+#include "platform/globals.h"
+#if defined(HOST_OS_WINDOWS)
+#include "bin/console.h"
+
+#include "bin/file.h"
+#include "bin/lockers.h"
+#include "bin/platform.h"
+#include "bin/utils.h"
+#include "bin/utils_win.h"
+
+// These are not always defined in the header files. See:
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx
+#ifndef ENABLE_VIRTUAL_TERMINAL_INPUT
+#define ENABLE_VIRTUAL_TERMINAL_INPUT 0x0200
+#endif
+
+#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
+#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
+#endif
+
+namespace dart {
+namespace bin {
+
+class ConsoleWin {
+ public:
+ static const int kInvalidFlag = -1;
+
+ static void Initialize() {
+ saved_output_cp_ = kInvalidFlag;
+ saved_input_cp_ = kInvalidFlag;
+ // Set up a signal handler that restores the console state on a
+ // CTRL_C_EVENT signal. This will only run when there is no signal handler
+ // registered for the CTRL_C_EVENT from Dart code.
+ SetConsoleCtrlHandler(SignalHandler, TRUE);
+
+ // Set both the input and output code pages to UTF8.
+ const int output_cp = GetConsoleOutputCP();
+ const int input_cp = GetConsoleCP();
+ if (output_cp != CP_UTF8) {
+ SetConsoleOutputCP(CP_UTF8);
+ saved_output_cp_ = output_cp;
+ }
+ if (input_cp != CP_UTF8) {
+ SetConsoleCP(CP_UTF8);
+ saved_input_cp_ = input_cp;
+ }
+
+ // Try to set the bits for ANSI support, but swallow any failures.
+ saved_stdout_mode_ =
+ ModifyMode(STD_OUTPUT_HANDLE, ENABLE_VIRTUAL_TERMINAL_PROCESSING);
+
+ // TODO(28984): Due to issue #29104, we cannot set
+ // ENABLE_VIRTUAL_TERMINAL_INPUT here, as it causes ENABLE_PROCESSED_INPUT
+ // to be ignored.
+ }
+
+ static void Cleanup() {
+ // STD_OUTPUT_HANDLE, may have been closed or redirected. Therefore, we
+ // explicitly open the CONOUT$, CONERR$ and CONIN$ devices, so that we can
+ // be sure that we are really restoring the console to its original state.
+ if (saved_stdout_mode_ != kInvalidFlag) {
+ CleanupDevices("CONOUT$", STD_OUTPUT_HANDLE, saved_stdout_mode_);
+ saved_stdout_mode_ = kInvalidFlag;
+ }
+ if (saved_output_cp_ != kInvalidFlag) {
+ SetConsoleOutputCP(saved_output_cp_);
+ saved_output_cp_ = kInvalidFlag;
+ }
+ if (saved_input_cp_ != kInvalidFlag) {
+ SetConsoleCP(saved_input_cp_);
+ saved_input_cp_ = kInvalidFlag;
+ }
+ }
+
+ private:
+ static int saved_output_cp_;
+ static int saved_input_cp_;
+ static DWORD saved_stdout_mode_;
+
+ static BOOL WINAPI SignalHandler(DWORD signal) {
+ if (signal == CTRL_C_EVENT) {
+ Cleanup();
+ }
+ return FALSE;
+ }
+
+ static DWORD ModifyMode(DWORD handle, DWORD flags) {
+ HANDLE h = GetStdHandle(handle);
+ DWORD mode;
+ DWORD old_mode = 0;
+
+ if ((h != INVALID_HANDLE_VALUE) && GetConsoleMode(h, &mode)) {
+ old_mode = mode;
+ if (flags != 0) {
+ const DWORD request = mode | flags;
+ SetConsoleMode(h, request);
+ }
+ }
+ return old_mode;
+ }
+
+ static void CleanupDevices(const char* device,
+ DWORD handle,
+ DWORD orig_flags) {
+ const intptr_t kWideBufLen = 64;
+ wchar_t widebuf[kWideBufLen];
+ int result =
+ MultiByteToWideChar(CP_UTF8, 0, device, -1, widebuf, kWideBufLen);
+ ASSERT(result != 0);
+ HANDLE h = CreateFileW(widebuf, GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
+ if (h != INVALID_HANDLE_VALUE) {
+ SetStdHandle(STD_OUTPUT_HANDLE, h);
+ if (orig_flags != kInvalidFlag) {
+ SetConsoleMode(h, orig_flags);
+ }
+ }
+ }
+
+ DISALLOW_ALLOCATION();
+ DISALLOW_IMPLICIT_CONSTRUCTORS(ConsoleWin);
+};
+
+int ConsoleWin::saved_output_cp_ = ConsoleWin::kInvalidFlag;
+int ConsoleWin::saved_input_cp_ = ConsoleWin::kInvalidFlag;
+DWORD ConsoleWin::saved_stdout_mode_ = ConsoleWin::kInvalidFlag;
+
+void Console::SaveConfig() {
+ ConsoleWin::Initialize();
+}
+
+void Console::RestoreConfig() {
+ ConsoleWin::Cleanup();
+}
+
+} // namespace bin
+} // namespace dart
+
+#endif // defined(HOST_OS_WINDOWS)
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index 7179a53..145e48b 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -12,6 +12,7 @@
#include <cstdarg>
#include "bin/builtin.h"
+#include "bin/console.h"
#include "bin/dartutils.h"
#include "bin/dfe.h"
#include "bin/eventhandler.h"
@@ -1489,6 +1490,7 @@
Log::PrintErr("Initialization failed\n");
return kErrorExitCode;
}
+ Console::SaveConfig();
Thread::InitOnce();
Loader::InitOnce();
DartUtils::SetOriginalWorkingDirectory();
diff --git a/runtime/bin/io_impl_sources.gni b/runtime/bin/io_impl_sources.gni
index 408652f..1e46f4d 100644
--- a/runtime/bin/io_impl_sources.gni
+++ b/runtime/bin/io_impl_sources.gni
@@ -5,6 +5,9 @@
# This file contains some C++ sources for the dart:io library. The other
# implementation files are in builtin_impl_sources.gypi.
io_impl_sources = [
+ "console.h",
+ "console_posix.cc",
+ "console_win.cc",
"eventhandler.cc",
"eventhandler.h",
"eventhandler_android.cc",
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index a9e51c3..f7868e1 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -10,6 +10,7 @@
#include "include/dart_tools_api.h"
#include "bin/builtin.h"
+#include "bin/console.h"
#include "bin/dartutils.h"
#include "bin/dfe.h"
#include "bin/directory.h"
@@ -1008,6 +1009,9 @@
Platform::Exit(kErrorExitCode);
}
+ // Save the console state so we can restore it at shutdown.
+ Console::SaveConfig();
+
// On Windows, the argv strings are code page encoded and not
// utf8. We need to convert them to utf8.
bool argv_converted = ShellUtils::GetUtf8Argv(argc, argv);
diff --git a/runtime/bin/platform_android.cc b/runtime/bin/platform_android.cc
index 8031f9e..6471168 100644
--- a/runtime/bin/platform_android.cc
+++ b/runtime/bin/platform_android.cc
@@ -7,14 +7,14 @@
#include "bin/platform.h"
+#include <errno.h> // NOLINT
#include <signal.h> // NOLINT
#include <string.h> // NOLINT
#include <sys/utsname.h> // NOLINT
#include <unistd.h> // NOLINT
-#include "bin/fdutils.h"
+#include "bin/console.h"
#include "bin/file.h"
-#include "bin/log.h"
namespace dart {
namespace bin {
@@ -152,6 +152,7 @@
}
void Platform::Exit(int exit_code) {
+ Console::RestoreConfig();
exit(exit_code);
}
diff --git a/runtime/bin/platform_fuchsia.cc b/runtime/bin/platform_fuchsia.cc
index cda405e..58aecb1 100644
--- a/runtime/bin/platform_fuchsia.cc
+++ b/runtime/bin/platform_fuchsia.cc
@@ -14,6 +14,7 @@
#include <zircon/status.h>
#include <zircon/syscalls.h>
+#include "bin/console.h"
#include "bin/dartutils.h"
#include "bin/fdutils.h"
#include "bin/file.h"
@@ -147,6 +148,7 @@
}
void Platform::Exit(int exit_code) {
+ Console::RestoreConfig();
exit(exit_code);
}
diff --git a/runtime/bin/platform_linux.cc b/runtime/bin/platform_linux.cc
index 0d5d885..afd8cac 100644
--- a/runtime/bin/platform_linux.cc
+++ b/runtime/bin/platform_linux.cc
@@ -7,14 +7,14 @@
#include "bin/platform.h"
+#include <errno.h> // NOLINT
#include <signal.h> // NOLINT
#include <string.h> // NOLINT
#include <sys/utsname.h> // NOLINT
#include <unistd.h> // NOLINT
-#include "bin/fdutils.h"
+#include "bin/console.h"
#include "bin/file.h"
-#include "bin/log.h"
namespace dart {
namespace bin {
@@ -152,6 +152,7 @@
}
void Platform::Exit(int exit_code) {
+ Console::RestoreConfig();
exit(exit_code);
}
diff --git a/runtime/bin/platform_macos.cc b/runtime/bin/platform_macos.cc
index d6544be..5c148b1 100644
--- a/runtime/bin/platform_macos.cc
+++ b/runtime/bin/platform_macos.cc
@@ -12,6 +12,7 @@
#if !HOST_OS_IOS
#include <crt_externs.h> // NOLINT
#endif // !HOST_OS_IOS
+#include <errno.h> // NOLINT
#include <mach-o/dyld.h>
#include <signal.h> // NOLINT
#include <string.h> // NOLINT
@@ -20,9 +21,8 @@
#include <sys/utsname.h> // NOLINT
#include <unistd.h> // NOLINT
-#include "bin/fdutils.h"
+#include "bin/console.h"
#include "bin/file.h"
-#include "bin/log.h"
namespace dart {
namespace bin {
@@ -240,6 +240,7 @@
}
void Platform::Exit(int exit_code) {
+ Console::RestoreConfig();
exit(exit_code);
}
diff --git a/runtime/bin/platform_win.cc b/runtime/bin/platform_win.cc
index b7a2115..796f250 100644
--- a/runtime/bin/platform_win.cc
+++ b/runtime/bin/platform_win.cc
@@ -9,6 +9,7 @@
#include <crtdbg.h>
+#include "bin/console.h"
#include "bin/file.h"
#include "bin/lockers.h"
#include "bin/log.h"
@@ -19,15 +20,6 @@
#include "bin/utils.h"
#include "bin/utils_win.h"
-// These are not always defined in the header files. See:
-// https://msdn.microsoft.com/en-us/library/windows/desktop/ms686033(v=vs.85).aspx
-#ifndef ENABLE_VIRTUAL_TERMINAL_INPUT
-#define ENABLE_VIRTUAL_TERMINAL_INPUT 0x0200
-#endif
-
-#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
-#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
-#endif
namespace dart {
@@ -44,9 +36,6 @@
class PlatformWin {
public:
static void InitOnce() {
- platform_win_mutex_ = new Mutex();
- saved_output_cp_ = -1;
- saved_input_cp_ = -1;
// Set up a no-op handler so that CRT functions return an error instead of
// hitting an assertion failure.
// See: https://msdn.microsoft.com/en-us/library/a9yf33zb.aspx
@@ -59,58 +48,12 @@
// See: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680621(v=vs.85).aspx
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX |
SEM_NOGPFAULTERRORBOX);
- // Set up a signal handler that restores the console state on a
- // CTRL_C_EVENT signal. This will only run when there is no signal handler
- // registered for the CTRL_C_EVENT from Dart code.
- SetConsoleCtrlHandler(SignalHandler, TRUE);
#ifndef PRODUCT
// Set up global exception handler to be able to dump stack trace on crash.
SetExceptionHandler();
#endif
}
- static BOOL WINAPI SignalHandler(DWORD signal) {
- if (signal == CTRL_C_EVENT) {
- // We call this without taking the lock because this is a signal
- // handler, and because the process is about to go down.
- RestoreConsoleLocked();
- }
- return FALSE;
- }
-
- static void SaveAndConfigureConsole() {
- MutexLocker ml(platform_win_mutex_);
- // Set both the input and output code pages to UTF8.
- ASSERT(saved_output_cp_ == -1);
- ASSERT(saved_input_cp_ == -1);
- const int output_cp = GetConsoleOutputCP();
- const int input_cp = GetConsoleCP();
- if (output_cp != CP_UTF8) {
- SetConsoleOutputCP(CP_UTF8);
- saved_output_cp_ = output_cp;
- }
- if (input_cp != CP_UTF8) {
- SetConsoleCP(CP_UTF8);
- saved_input_cp_ = input_cp;
- }
-
- // Try to set the bits for ANSI support, but swallow any failures.
- HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
- DWORD out_mode;
- if ((out != INVALID_HANDLE_VALUE) && GetConsoleMode(out, &out_mode)) {
- const DWORD request = out_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING;
- SetConsoleMode(out, request);
- }
- // TODO(28984): Due to issue #29104, we cannot set
- // ENABLE_VIRTUAL_TERMINAL_INPUT here, as it causes ENABLE_PROCESSED_INPUT
- // to be ignored.
- }
-
- static void RestoreConsole() {
- MutexLocker ml(platform_win_mutex_);
- RestoreConsoleLocked();
- }
-
// Windows top-level unhandled exception handler function.
// See MSDN documentation for UnhandledExceptionFilter.
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms681401(v=vs.85).aspx
@@ -139,57 +82,6 @@
}
private:
- static Mutex* platform_win_mutex_;
- static int saved_output_cp_;
- static int saved_input_cp_;
-
- static void RestoreConsoleLocked() {
- // STD_OUTPUT_HANDLE and STD_INPUT_HANDLE may have been closed or
- // redirected. Therefore, we explicitly open the CONOUT$ and CONIN$
- // devices, so that we can be sure that we are really unsetting
- // ENABLE_VIRTUAL_TERMINAL_PROCESSING and ENABLE_VIRTUAL_TERMINAL_INPUT
- // respectively.
- const intptr_t kWideBufLen = 64;
- const char* conout = "CONOUT$";
- wchar_t widebuf[kWideBufLen];
- int result =
- MultiByteToWideChar(CP_UTF8, 0, conout, -1, widebuf, kWideBufLen);
- ASSERT(result != 0);
- HANDLE out = CreateFileW(widebuf, GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
- if (out != INVALID_HANDLE_VALUE) {
- SetStdHandle(STD_OUTPUT_HANDLE, out);
- }
- DWORD out_mode;
- if ((out != INVALID_HANDLE_VALUE) && GetConsoleMode(out, &out_mode)) {
- DWORD request = out_mode & ~ENABLE_VIRTUAL_TERMINAL_INPUT;
- SetConsoleMode(out, request);
- }
-
- const char* conin = "CONIN$";
- result = MultiByteToWideChar(CP_UTF8, 0, conin, -1, widebuf, kWideBufLen);
- ASSERT(result != 0);
- HANDLE in = CreateFileW(widebuf, GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
- if (in != INVALID_HANDLE_VALUE) {
- SetStdHandle(STD_INPUT_HANDLE, in);
- }
- DWORD in_mode;
- if ((in != INVALID_HANDLE_VALUE) && GetConsoleMode(in, &in_mode)) {
- DWORD request = in_mode & ~ENABLE_VIRTUAL_TERMINAL_INPUT;
- SetConsoleMode(in, request);
- }
-
- if (saved_output_cp_ != -1) {
- SetConsoleOutputCP(saved_output_cp_);
- saved_output_cp_ = -1;
- }
- if (saved_input_cp_ != -1) {
- SetConsoleCP(saved_input_cp_);
- saved_input_cp_ = -1;
- }
- }
-
static void InvalidParameterHandler(const wchar_t* expression,
const wchar_t* function,
const wchar_t* file,
@@ -203,13 +95,8 @@
DISALLOW_IMPLICIT_CONSTRUCTORS(PlatformWin);
};
-int PlatformWin::saved_output_cp_ = -1;
-int PlatformWin::saved_input_cp_ = -1;
-Mutex* PlatformWin::platform_win_mutex_ = NULL;
-
bool Platform::Initialize() {
PlatformWin::InitOnce();
- PlatformWin::SaveAndConfigureConsole();
return true;
}
@@ -394,7 +281,7 @@
// TODO(zra): Remove once VM shuts down cleanly.
::dart::private_flag_windows_run_tls_destructors = false;
// Restore the console's output code page
- PlatformWin::RestoreConsole();
+ Console::RestoreConfig();
// On Windows we use ExitProcess so that threads can't clobber the exit_code.
// See: https://code.google.com/p/nativeclient/issues/detail?id=2870
::ExitProcess(exit_code);
diff --git a/runtime/bin/run_vm_tests.cc b/runtime/bin/run_vm_tests.cc
index 6246c4a..42e4f63 100644
--- a/runtime/bin/run_vm_tests.cc
+++ b/runtime/bin/run_vm_tests.cc
@@ -4,6 +4,7 @@
#include <stdio.h>
+#include "bin/console.h"
#include "bin/dartutils.h"
#include "bin/dfe.h"
#include "bin/eventhandler.h"
@@ -212,6 +213,9 @@
return 1;
}
+ // Save the console state so we can restore it later.
+ dart::bin::Console::SaveConfig();
+
if (argc < 2) {
// Bad parameter count.
PrintUsage();
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index bf9dfa1..69d0ef0 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -18,7 +18,6 @@
cc/IsolateReload_RunNewFieldInitializersWithGenerics: Fail # Issue 32299
cc/Profiler_InliningIntervalBoundry: Skip # Differences in ia32, debug, release
cc/SNPrint_BadArgs: Crash, Fail # These tests are expected to crash on all platforms.
-cc/Sleep: Skip # Flaky # Flaky on buildbot. Issue 5133 and 10409.
dart/data_uri_import_test/none: SkipByDesign
[ $builder_tag == asan ]
@@ -193,7 +192,7 @@
cc/Debugger_Rewind_Optimized: SkipSlow
cc/Debugger_SetBreakpointInPartOfLibrary: Crash
cc/FunctionSourceFingerprint: Fail
-cc/GenerateSource: Skip # Cannot generate source from a kernel binary.
+cc/GenerateSource: Skip # Cannot generate source from a kernel binary.
cc/IsolateReload_NotTypedefToTypedef: Fail
cc/IsolateReload_TypedefToNotTypedef: Fail
cc/Parser_AllocateVariables_CaptureLoopVar: Fail
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index ef85c3f..38a1b58 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -4970,7 +4970,9 @@
AddBaseObject(Object::void_type().raw());
AddBaseObject(Bool::True().raw());
AddBaseObject(Bool::False().raw());
+ ASSERT(Object::extractor_parameter_types().raw() != Object::null());
AddBaseObject(Object::extractor_parameter_types().raw());
+ ASSERT(Object::extractor_parameter_names().raw() != Object::null());
AddBaseObject(Object::extractor_parameter_names().raw());
AddBaseObject(Object::empty_context().raw());
AddBaseObject(Object::empty_context_scope().raw());
@@ -5413,7 +5415,9 @@
AddBaseObject(Object::void_type().raw());
AddBaseObject(Bool::True().raw());
AddBaseObject(Bool::False().raw());
+ ASSERT(Object::extractor_parameter_types().raw() != Object::null());
AddBaseObject(Object::extractor_parameter_types().raw());
+ ASSERT(Object::extractor_parameter_names().raw() != Object::null());
AddBaseObject(Object::extractor_parameter_names().raw());
AddBaseObject(Object::empty_context().raw());
AddBaseObject(Object::empty_context_scope().raw());
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.h b/runtime/vm/compiler/assembler/assembler_arm64.h
index 3b7e289..b26fd9b 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.h
+++ b/runtime/vm/compiler/assembler/assembler_arm64.h
@@ -1331,8 +1331,15 @@
}
}
// We use an alias of add, where ARM recommends an alias of ubfm.
- void LsrImmediate(Register rd, Register rn, int shift) {
- add(rd, ZR, Operand(rn, LSR, shift));
+ void LsrImmediate(Register rd,
+ Register rn,
+ int shift,
+ OperandSize sz = kDoubleWord) {
+ if (sz == kDoubleWord) {
+ add(rd, ZR, Operand(rn, LSR, shift));
+ } else {
+ addw(rd, ZR, Operand(rn, LSR, shift));
+ }
}
// We use an alias of add, where ARM recommends an alias of sbfm.
void AsrImmediate(Register rd, Register rn, int shift) {
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
index 2609224..dd22a37 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
@@ -25,6 +25,7 @@
DEFINE_FLAG(bool, trap_on_deoptimization, false, "Trap on deoptimization.");
DECLARE_FLAG(bool, enable_simd_inline);
+DEFINE_FLAG(bool, unbox_mints, true, "Optimize 64-bit integer arithmetic.");
FlowGraphCompiler::~FlowGraphCompiler() {
// BlockInfos are zone-allocated, so their destructors are not called.
@@ -39,7 +40,7 @@
}
bool FlowGraphCompiler::SupportsUnboxedInt64() {
- return false;
+ return FLAG_unbox_mints;
}
bool FlowGraphCompiler::SupportsUnboxedSimd128() {
@@ -47,8 +48,7 @@
}
bool FlowGraphCompiler::CanConvertInt64ToDouble() {
- // Unboxed int64 are not supported on ARM64.
- return false;
+ return true;
}
bool FlowGraphCompiler::SupportsHardwareDivision() {
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index 556d1f4..94b1d80 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -1781,7 +1781,7 @@
bool HasSSATemp() const { return ssa_temp_index_ >= 0; }
void ClearSSATempIndex() { ssa_temp_index_ = -1; }
bool HasPairRepresentation() const {
-#if defined(TARGET_ARCH_X64)
+#if defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64)
return representation() == kPairOfTagged;
#else
return (representation() == kPairOfTagged) ||
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 182d697..bb7b194a 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -984,6 +984,8 @@
return kUnboxedInt32;
case kTypedDataUint32ArrayCid:
return kUnboxedUint32;
+ case kTypedDataInt64ArrayCid:
+ return kUnboxedInt64;
case kTypedDataFloat32ArrayCid:
case kTypedDataFloat64ArrayCid:
return kUnboxedDouble;
@@ -1135,6 +1137,17 @@
return;
}
+ if (representation() == kUnboxedInt64) {
+ ASSERT(class_id() == kTypedDataInt64ArrayCid);
+ Register result = locs()->out(0).reg();
+ if (aligned()) {
+ __ ldr(result, element_address, kDoubleWord);
+ } else {
+ __ LoadUnaligned(result, address, TMP, kDoubleWord);
+ }
+ return;
+ }
+
ASSERT(representation() == kTagged);
const Register result = locs()->out(0).reg();
switch (class_id()) {
@@ -1260,6 +1273,8 @@
return kUnboxedInt32;
case kTypedDataUint32ArrayCid:
return kUnboxedUint32;
+ case kTypedDataInt64ArrayCid:
+ return kUnboxedInt64;
case kTypedDataFloat32ArrayCid:
case kTypedDataFloat64ArrayCid:
return kUnboxedDouble;
@@ -3403,10 +3418,12 @@
LocationSummary* UnboxInstr::MakeLocationSummary(Zone* zone, bool opt) const {
const intptr_t kNumInputs = 1;
const intptr_t kNumTemps = 0;
+ const bool is_floating_point = representation() != kUnboxedInt64;
LocationSummary* summary = new (zone)
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
summary->set_in(0, Location::RequiresRegister());
- summary->set_out(0, Location::RequiresFpuRegister());
+ summary->set_out(0, is_floating_point ? Location::RequiresFpuRegister()
+ : Location::RequiresRegister());
return summary;
}
@@ -3415,7 +3432,8 @@
switch (representation()) {
case kUnboxedInt64: {
- UNIMPLEMENTED();
+ const Register result = locs()->out(0).reg();
+ __ ldr(result, FieldAddress(box, ValueOffset()));
break;
}
@@ -3444,7 +3462,8 @@
switch (representation()) {
case kUnboxedInt64: {
- UNIMPLEMENTED();
+ const Register result = locs()->out(0).reg();
+ __ SmiUntag(result, box);
break;
}
@@ -3462,7 +3481,14 @@
}
void UnboxInstr::EmitLoadInt64FromBoxOrSmi(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ const Register value = locs()->in(0).reg();
+ const Register result = locs()->out(0).reg();
+ ASSERT(value != result);
+ Label done;
+ __ SmiUntag(result, value);
+ __ BranchIfSmi(value, &done);
+ __ LoadFieldFromOffset(result, value, Mint::value_offset());
+ __ Bind(&done);
}
LocationSummary* BoxInteger32Instr::MakeLocationSummary(Zone* zone,
@@ -3494,7 +3520,43 @@
}
}
-DEFINE_UNIMPLEMENTED_INSTRUCTION(BoxInt64Instr)
+LocationSummary* BoxInt64Instr::MakeLocationSummary(Zone* zone,
+ bool opt) const {
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1;
+ LocationSummary* summary = new (zone)
+ LocationSummary(zone, kNumInputs, kNumTemps,
+ ValueFitsSmi() ? LocationSummary::kNoCall
+ : LocationSummary::kCallOnSlowPath);
+ summary->set_in(0, Location::RequiresRegister());
+ summary->set_out(0, Location::RequiresRegister());
+ if (!ValueFitsSmi()) {
+ summary->set_temp(0, Location::RequiresRegister());
+ }
+ return summary;
+}
+
+void BoxInt64Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ Register in = locs()->in(0).reg();
+ Register out = locs()->out(0).reg();
+ if (ValueFitsSmi()) {
+ __ SmiTag(out, in);
+ return;
+ }
+
+ ASSERT(kSmiTag == 0);
+ __ LslImmediate(out, in, kSmiTagSize);
+ Label done;
+ __ cmp(in, Operand(out, ASR, kSmiTagSize));
+ __ b(&done, EQ);
+
+ Register temp = locs()->temp(0).reg();
+ BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), out,
+ temp);
+
+ __ StoreToOffset(in, out, Mint::value_offset() - kHeapObjectTag);
+ __ Bind(&done);
+}
LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Zone* zone,
bool opt) const {
@@ -4292,12 +4354,19 @@
LocationSummary* Int64ToDoubleInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* result = new (zone)
+ LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ result->set_in(0, Location::RequiresRegister());
+ result->set_out(0, Location::RequiresFpuRegister());
+ return result;
}
void Int64ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ const Register value = locs()->in(0).reg();
+ const VRegister result = locs()->out(0).fpu_reg();
+ __ scvtfdx(result, value);
}
LocationSummary* DoubleToIntegerInstr::MakeLocationSummary(Zone* zone,
@@ -4867,32 +4936,208 @@
LocationSummary* BinaryInt64OpInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 2;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary = new (zone)
+ LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresRegister());
+ summary->set_in(1, Location::RegisterOrConstant(right()));
+ summary->set_out(0, Location::RequiresRegister());
+ return summary;
}
void BinaryInt64OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ Label* deopt = NULL;
+ if (CanDeoptimize()) {
+ deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryInt64Op);
+ }
+
+ const Register left = locs()->in(0).reg();
+ const Location right = locs()->in(1);
+ const Register out = locs()->out(0).reg();
+
+ if (op_kind() == Token::kMUL) {
+ Register r = TMP;
+ if (right.IsConstant()) {
+ ConstantInstr* constant_instr = right.constant_instruction();
+ const int64_t value =
+ constant_instr->GetUnboxedSignedIntegerConstantValue();
+ __ LoadImmediate(r, value);
+ } else {
+ r = right.reg();
+ }
+ __ mul(out, left, r);
+ if (CanDeoptimize()) {
+ __ smulh(TMP, left, r);
+ // TMP: result bits 64..127.
+ __ cmp(TMP, Operand(out, ASR, 63));
+ __ b(deopt, NE);
+ }
+ return;
+ }
+
+ if (right.IsConstant()) {
+ ConstantInstr* constant_instr = right.constant_instruction();
+ const int64_t value =
+ constant_instr->GetUnboxedSignedIntegerConstantValue();
+ switch (op_kind()) {
+ case Token::kADD:
+ if (CanDeoptimize()) {
+ __ AddImmediateSetFlags(out, left, value);
+ __ b(deopt, VS);
+ } else {
+ __ AddImmediate(out, left, value);
+ }
+ break;
+ case Token::kSUB:
+ if (CanDeoptimize()) {
+ __ SubImmediateSetFlags(out, left, value);
+ __ b(deopt, VS);
+ } else {
+ __ AddImmediate(out, left, -value);
+ }
+ break;
+ case Token::kBIT_AND:
+ __ AndImmediate(out, left, value);
+ break;
+ case Token::kBIT_OR:
+ __ OrImmediate(out, left, value);
+ break;
+ case Token::kBIT_XOR:
+ __ XorImmediate(out, left, value);
+ break;
+ default:
+ UNREACHABLE();
+ }
+ } else {
+ Operand r = Operand(right.reg());
+ switch (op_kind()) {
+ case Token::kADD:
+ if (CanDeoptimize()) {
+ __ adds(out, left, r);
+ __ b(deopt, VS);
+ } else {
+ __ add(out, left, r);
+ }
+ break;
+ case Token::kSUB:
+ if (CanDeoptimize()) {
+ __ subs(out, left, r);
+ __ b(deopt, VS);
+ } else {
+ __ sub(out, left, r);
+ }
+ break;
+ case Token::kBIT_AND:
+ __ and_(out, left, r);
+ break;
+ case Token::kBIT_OR:
+ __ orr(out, left, r);
+ break;
+ case Token::kBIT_XOR:
+ __ eor(out, left, r);
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
}
LocationSummary* ShiftInt64OpInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 2;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary = new (zone)
+ LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresRegister());
+ summary->set_in(1, Location::WritableRegisterOrSmiConstant(right()));
+ summary->set_out(0, Location::RequiresRegister());
+ return summary;
}
void ShiftInt64OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ const Register left = locs()->in(0).reg();
+ const Register out = locs()->out(0).reg();
+
+ Label* deopt = NULL;
+ if (CanDeoptimize()) {
+ deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryInt64Op);
+ }
+ if (locs()->in(1).IsConstant()) {
+ // Code for a constant shift amount.
+ ASSERT(locs()->in(1).constant().IsSmi());
+ const int32_t shift = Smi::Cast(locs()->in(1).constant()).Value();
+ ASSERT(shift >= 0);
+ switch (op_kind()) {
+ case Token::kSHR: {
+ __ AsrImmediate(out, left, Utils::Minimum(shift, kBitsPerWord - 1));
+ break;
+ }
+ case Token::kSHL: {
+ ASSERT(shift < 64);
+ __ LslImmediate(out, left, shift);
+ // Check for overflow.
+ if (can_overflow()) {
+ __ cmp(left, Operand(out, ASR, shift));
+ __ b(deopt, NE);
+ }
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+ } else {
+ // Code for a variable shift amount.
+ Register shift = locs()->in(1).reg();
+
+ // Untag shift count.
+ __ SmiUntag(TMP, shift);
+
+ // Deopt if shift is larger than 63 or less than 0.
+ if (!IsShiftCountInRange()) {
+ __ CompareImmediate(TMP, kMintShiftCountLimit);
+ __ b(deopt, HI);
+ }
+
+ switch (op_kind()) {
+ case Token::kSHR: {
+ __ lsrv(out, left, TMP);
+ break;
+ }
+ case Token::kSHL: {
+ __ lslv(out, left, TMP);
+
+ // Check for overflow.
+ if (can_overflow()) {
+ __ asrv(TMP2, out, TMP);
+ __ cmp(left, Operand(TMP2));
+ __ b(deopt, NE);
+ }
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+ }
}
LocationSummary* UnaryInt64OpInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary = new (zone)
+ LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresRegister());
+ summary->set_out(0, Location::RequiresRegister());
+ return summary;
}
void UnaryInt64OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ ASSERT(op_kind() == Token::kBIT_NOT);
+ const Register left = locs()->in(0).reg();
+ const Register out = locs()->out(0).reg();
+ ASSERT(out == left);
+ __ mvn(out, left);
}
CompileType BinaryUint32OpInstr::ComputeType() const {
@@ -4907,9 +5152,135 @@
return CompileType::FromCid(kSmiCid);
}
-DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryUint32OpInstr)
-DEFINE_UNIMPLEMENTED_INSTRUCTION(ShiftUint32OpInstr)
-DEFINE_UNIMPLEMENTED_INSTRUCTION(UnaryUint32OpInstr)
+LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Zone* zone,
+ bool opt) const {
+ const intptr_t kNumInputs = 2;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary = new (zone)
+ LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresRegister());
+ summary->set_in(1, Location::RequiresRegister());
+ summary->set_out(0, Location::RequiresRegister());
+ return summary;
+}
+
+void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ Register left = locs()->in(0).reg();
+ Register right = locs()->in(1).reg();
+ Operand r = Operand(right);
+ Register out = locs()->out(0).reg();
+ switch (op_kind()) {
+ case Token::kBIT_AND:
+ __ and_(out, left, r);
+ break;
+ case Token::kBIT_OR:
+ __ orr(out, left, r);
+ break;
+ case Token::kBIT_XOR:
+ __ eor(out, left, r);
+ break;
+ case Token::kADD:
+ __ addw(out, left, r);
+ break;
+ case Token::kSUB:
+ __ subw(out, left, r);
+ break;
+ case Token::kMUL:
+ __ mulw(out, left, right);
+ break;
+ default:
+ UNREACHABLE();
+ }
+}
+
+LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Zone* zone,
+ bool opt) const {
+ const intptr_t kNumInputs = 2;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary = new (zone)
+ LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresRegister());
+ summary->set_in(1, Location::RegisterOrSmiConstant(right()));
+ summary->set_out(0, Location::RequiresRegister());
+ return summary;
+}
+
+void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ const intptr_t kShifterLimit = 31;
+
+ Register left = locs()->in(0).reg();
+ Register out = locs()->out(0).reg();
+
+ Label* deopt =
+ compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryInt64Op);
+
+ if (locs()->in(1).IsConstant()) {
+ // Shifter is constant.
+
+ const Object& constant = locs()->in(1).constant();
+ ASSERT(constant.IsSmi());
+ const intptr_t shift_value = Smi::Cast(constant).Value();
+
+ // Do the shift: (shift_value > 0) && (shift_value <= kShifterLimit).
+ switch (op_kind()) {
+ case Token::kSHR:
+ __ LsrImmediate(out, left, shift_value, kWord);
+ break;
+ case Token::kSHL:
+ __ LslImmediate(out, left, shift_value, kWord);
+ break;
+ default:
+ UNREACHABLE();
+ }
+ return;
+ }
+
+ // Non constant shift value.
+
+ Register shifter = locs()->in(1).reg();
+
+ // TODO(johnmccutchan): Use range information to avoid these checks.
+ __ SmiUntag(TMP, shifter);
+ __ CompareImmediate(TMP, 0);
+ // If shift value is < 0, deoptimize.
+ __ b(deopt, LT);
+
+ // Do the shift.
+ switch (op_kind()) {
+ case Token::kSHR:
+ __ lsrv(out, left, TMP);
+ break;
+ case Token::kSHL:
+ __ lslvw(out, left, TMP);
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ __ CompareImmediate(TMP, kShifterLimit);
+ // If shift value is > 31, return zero.
+ __ csel(out, out, ZR, GT);
+}
+
+LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Zone* zone,
+ bool opt) const {
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary = new (zone)
+ LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresRegister());
+ summary->set_out(0, Location::RequiresRegister());
+ return summary;
+}
+
+void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ Register left = locs()->in(0).reg();
+ Register out = locs()->out(0).reg();
+
+ ASSERT(op_kind() == Token::kBIT_NOT);
+ __ mvnw(out, left);
+}
+
DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr)
LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Zone* zone,
@@ -4919,49 +5290,70 @@
LocationSummary* summary = new (zone)
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
if (from() == kUnboxedInt64) {
- UNREACHABLE();
+ ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32));
} else if (to() == kUnboxedInt64) {
- UNREACHABLE();
+ ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32));
} else {
ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32));
ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32));
- summary->set_in(0, Location::RequiresRegister());
+ }
+ summary->set_in(0, Location::RequiresRegister());
+ if (CanDeoptimize()) {
summary->set_out(0, Location::RequiresRegister());
+ } else {
+ summary->set_out(0, Location::SameAsFirstInput());
}
return summary;
}
void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ ASSERT(from() != to()); // We don't convert from a representation to itself.
+ const Register value = locs()->in(0).reg();
+ const Register out = locs()->out(0).reg();
+ Label* deopt = !CanDeoptimize() ? NULL
+ : compiler->AddDeoptStub(
+ deopt_id(), ICData::kDeoptUnboxInteger);
if (from() == kUnboxedInt32 && to() == kUnboxedUint32) {
- const Register value = locs()->in(0).reg();
- const Register out = locs()->out(0).reg();
- // Representations are bitwise equivalent but we want to normalize
- // upperbits for safety reasons.
- // TODO(vegorov) if we ensure that we never use kDoubleWord size
- // with it then we could avoid this.
- // TODO(vegorov) implement and use UBFM for zero extension.
- __ LslImmediate(out, value, 32);
- __ LsrImmediate(out, out, 32);
- } else if (from() == kUnboxedUint32 && to() == kUnboxedInt32) {
- // Representations are bitwise equivalent.
- // TODO(vegorov) if we ensure that we never use kDoubleWord size
- // with it then we could avoid this.
- // TODO(vegorov) implement and use SBFM for sign extension.
- const Register value = locs()->in(0).reg();
- const Register out = locs()->out(0).reg();
- __ LslImmediate(out, value, 32);
- __ AsrImmediate(out, out, 32);
if (CanDeoptimize()) {
- Label* deopt =
- compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger);
- __ cmp(out, Operand(value, UXTW, 0));
- __ b(deopt, NE);
+ __ tbnz(deopt, value,
+ 31); // If sign bit is set it won't fit in a uint32.
+ }
+ if (out != value) {
+ __ mov(out, value); // For positive values the bits are the same.
+ }
+ } else if (from() == kUnboxedUint32 && to() == kUnboxedInt32) {
+ if (CanDeoptimize()) {
+ __ tbnz(deopt, value,
+ 31); // If high bit is set it won't fit in an int32.
+ }
+ if (out != value) {
+ __ mov(out, value); // For 31 bit values the bits are the same.
}
} else if (from() == kUnboxedInt64) {
- UNREACHABLE();
+ if (to() == kUnboxedInt32) {
+ if (is_truncating() || out != value) {
+ __ sxtw(out, value); // Signed extension 64->32.
+ }
+ } else {
+ ASSERT(to() == kUnboxedUint32);
+ if (is_truncating() || out != value) {
+ __ uxtw(out, value); // Unsigned extension 64->32.
+ }
+ }
+ if (CanDeoptimize()) {
+ ASSERT(to() == kUnboxedInt32);
+ __ cmp(out, Operand(value));
+ __ b(deopt, NE); // Value cannot be held in Int32, deopt.
+ }
} else if (to() == kUnboxedInt64) {
- ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32));
- UNREACHABLE();
+ if (from() == kUnboxedUint32) {
+ if (out != value) {
+ __ mov(out, value);
+ }
+ } else {
+ ASSERT(from() == kUnboxedInt32);
+ __ sxtw(out, value); // Signed extension 32->64.
+ }
} else {
UNREACHABLE();
}
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index 532fec3..9e86173 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -5317,8 +5317,7 @@
static void EmitIntegerArithmetic(FlowGraphCompiler* compiler,
Token::Kind op_kind,
Register left,
- const OperandType& right,
- Label* deopt) {
+ const OperandType& right) {
switch (op_kind) {
case Token::kADD:
__ addl(left, right);
@@ -5341,7 +5340,6 @@
default:
UNREACHABLE();
}
- if (deopt != NULL) __ j(OVERFLOW, deopt);
}
void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
@@ -5356,7 +5354,7 @@
case Token::kADD:
case Token::kSUB:
case Token::kMUL:
- EmitIntegerArithmetic(compiler, op_kind(), left, right, NULL);
+ EmitIntegerArithmetic(compiler, op_kind(), left, right);
return;
default:
UNREACHABLE();
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 2b8015a..0cbd93e 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -959,7 +959,18 @@
}
ParameterTypeCheckMode type_check_mode = kTypeCheckAllParameters;
- if (!function.IsImplicitClosureFunction()) {
+ if (function.IsNonImplicitClosureFunction()) {
+ type_check_mode = kTypeCheckAllParameters;
+ } else if (function.IsImplicitClosureFunction()) {
+ if (!attrs.has_dynamic_invocations) {
+ // This is a tear-off of an instance method that can not be reached
+ // from any dynamic invocation. The method would not check any
+ // parameters except covariant ones and those annotated with
+ // generic-covariant-impl. Which means that we have to check
+ // the rest in the tear-off itself..
+ type_check_mode = kTypeCheckForTearOffOfNonDynamicallyInvokedMethod;
+ }
+ } else {
if (function.is_static()) {
// In static functions we don't check anything.
type_check_mode = kTypeCheckForStaticFunction;
@@ -972,15 +983,6 @@
// guarantees that it was checked at the caller side.
type_check_mode = kTypeCheckForNonDynamicallyInvokedMethod;
}
- } else {
- if (!attrs.has_dynamic_invocations) {
- // This is a tear-off of an instance method that can not be reached
- // from any dynamic invocation. The method would not check any
- // parameters except covariant ones and those annotated with
- // generic-covariant-impl. Which means that we have to check
- // the rest in the tear-off itself..
- type_check_mode = kTypeCheckForTearOffOfNonDynamicallyInvokedMethod;
- }
}
// Continue reading FunctionNode:
@@ -1089,6 +1091,13 @@
return result_;
}
+void StreamingScopeBuilder::ReportUnexpectedTag(const char* variant, Tag tag) {
+ H.ReportError(builder_->script(), TokenPosition::kNoSource,
+ "Unexpected tag %d (%s) in %s, expected %s", tag,
+ Reader::TagName(tag),
+ parsed_function_->function().ToQualifiedCString(), variant);
+}
+
void StreamingScopeBuilder::VisitNode() {
Tag tag = builder_->PeekTag();
switch (tag) {
@@ -1269,7 +1278,7 @@
VisitStatement();
return;
default:
- H.ReportError("Unsupported tag at this point: %d.", tag);
+ ReportUnexpectedTag("initializer", tag);
UNREACHABLE();
}
}
@@ -1504,7 +1513,7 @@
case kStringLiteral:
builder_->SkipStringReference(); // read string reference.
return;
- case kSpecialIntLiteral:
+ case kSpecializedIntLiteral:
return;
case kNegativeIntLiteral:
builder_->ReadUInt(); // read value.
@@ -1560,7 +1569,7 @@
builder_->ReadUInt(); // library index
break;
default:
- H.ReportError("Unsupported tag at this point: %d.", tag);
+ ReportUnexpectedTag("expression", tag);
UNREACHABLE();
}
}
@@ -1826,7 +1835,7 @@
return;
}
default:
- H.ReportError("Unsupported tag at this point: %d.", tag);
+ ReportUnexpectedTag("declaration", tag);
UNREACHABLE();
}
}
@@ -1924,7 +1933,7 @@
VisitTypeParameterType();
return;
default:
- H.ReportError("Unsupported tag at this point: %d.", tag);
+ ReportUnexpectedTag("type", tag);
UNREACHABLE();
}
}
@@ -2413,7 +2422,7 @@
BuildTypeParameterType();
break;
default:
- H.ReportError("Unsupported tag at this point: %d.", tag);
+ builder_->ReportUnexpectedTag("type", tag);
UNREACHABLE();
}
}
@@ -2806,7 +2815,7 @@
case kStringLiteral:
EvaluateStringLiteral();
break;
- case kSpecialIntLiteral:
+ case kSpecializedIntLiteral:
EvaluateIntLiteral(payload);
break;
case kNegativeIntLiteral:
@@ -2831,8 +2840,10 @@
EvaluateConstantExpression();
break;
default:
- H.ReportError(script_, TokenPosition::kNoSource,
- "Not a constant expression.");
+ H.ReportError(
+ script_, TokenPosition::kNoSource,
+ "Not a constant expression: unexpected kernel tag %s (%" Pd ")",
+ Reader::TagName(tag), tag);
}
CacheConstantValue(offset, result_);
@@ -3745,7 +3756,7 @@
} else if (tag == kFunctionNode) {
// Already at start of FunctionNode.
} else {
- H.ReportError("Unsupported tag at this point: %d.", tag);
+ ReportUnexpectedTag("a procedure, a constructor or a function node", tag);
UNREACHABLE();
}
}
@@ -4129,7 +4140,7 @@
break;
}
default:
- H.ReportError("Unsupported tag at this point: %d.", tag);
+ ReportUnexpectedTag("initializer", tag);
UNREACHABLE();
}
}
@@ -4889,7 +4900,7 @@
return BuildBigIntLiteral(position);
case kStringLiteral:
return BuildStringLiteral(position);
- case kSpecialIntLiteral:
+ case kSpecializedIntLiteral:
return BuildIntLiteral(payload, position);
case kNegativeIntLiteral:
return BuildIntLiteral(true, position);
@@ -4922,7 +4933,7 @@
ReadUInt(); // skip library index
return BuildFutureNullValue(position);
default:
- H.ReportError("Unsupported tag at this point: %d.", tag);
+ ReportUnexpectedTag("expression", tag);
UNREACHABLE();
}
@@ -4973,7 +4984,7 @@
case kFunctionDeclaration:
return BuildFunctionDeclaration();
default:
- H.ReportError("Unsupported tag at this point: %d.", tag);
+ ReportUnexpectedTag("statement", tag);
UNREACHABLE();
}
return Fragment();
@@ -5097,6 +5108,17 @@
ReadUInt();
}
+void StreamingFlowGraphBuilder::ReportUnexpectedTag(const char* variant,
+ Tag tag) {
+ H.ReportError(script_, TokenPosition::kNoSource,
+ "Unexpected tag %d (%s) in %s, expected %s", tag,
+ Reader::TagName(tag),
+ flow_graph_builder_ != NULL && parsed_function() != NULL
+ ? parsed_function()->function().ToQualifiedCString()
+ : "?",
+ variant);
+}
+
void StreamingFlowGraphBuilder::SkipDartType() {
Tag tag = ReadTag();
switch (tag) {
@@ -5124,7 +5146,7 @@
SkipOptionalDartType(); // read bound bound.
return;
default:
- H.ReportError("Unsupported tag at this point: %d.", tag);
+ ReportUnexpectedTag("type", tag);
UNREACHABLE();
}
}
@@ -5237,7 +5259,7 @@
SkipStatement();
return;
default:
- H.ReportError("Unsupported tag at this point: %d.", tag);
+ ReportUnexpectedTag("initializer", tag);
UNREACHABLE();
}
}
@@ -5453,7 +5475,7 @@
case kStringLiteral:
SkipStringReference(); // read string reference.
return;
- case kSpecialIntLiteral:
+ case kSpecializedIntLiteral:
return;
case kNegativeIntLiteral:
ReadUInt(); // read value.
@@ -5478,7 +5500,7 @@
ReadUInt(); // skip library index
return;
default:
- H.ReportError("Unsupported tag at this point: %d.", tag);
+ ReportUnexpectedTag("expression", tag);
UNREACHABLE();
}
}
@@ -5616,7 +5638,7 @@
SkipFunctionNode(); // read function node.
return;
default:
- H.ReportError("Unsupported tag at this point: %d.", tag);
+ ReportUnexpectedTag("statement", tag);
UNREACHABLE();
}
}
@@ -6880,7 +6902,7 @@
static bool IsNumberLiteral(Tag tag) {
return tag == kNegativeIntLiteral || tag == kPositiveIntLiteral ||
- tag == kSpecialIntLiteral || tag == kDoubleLiteral;
+ tag == kSpecializedIntLiteral || tag == kDoubleLiteral;
}
Fragment StreamingFlowGraphBuilder::BuildMethodInvocation(TokenPosition* p) {
@@ -7720,7 +7742,9 @@
if (position != NULL) *position = TokenPosition::kNoSource;
const AbstractType& type = T.BuildType(); // read type.
- if (type.IsMalformed()) H.ReportError("Malformed type literal");
+ if (type.IsMalformed()) {
+ H.ReportError(script_, TokenPosition::kNoSource, "Malformed type literal");
+ }
Fragment instructions;
if (type.IsInstantiated()) {
@@ -7928,7 +7952,8 @@
const Integer& integer =
Integer::ZoneHandle(Z, Integer::New(value, Heap::kOld));
if (integer.IsNull()) {
- H.ReportError("Integer literal %s is out of range", value.ToCString());
+ H.ReportError(script_, TokenPosition::kNoSource,
+ "Integer literal %s is out of range", value.ToCString());
UNREACHABLE();
}
return Constant(integer);
@@ -9561,7 +9586,7 @@
ClassHelper class_helper(this);
class_helper.ReadUntilExcluding(ClassHelper::kEnd);
} else {
- H.ReportError("Unsupported tag at this point: %d.", tag);
+ ReportUnexpectedTag("a class or a member", tag);
UNREACHABLE();
}
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index dda7bbd..1b7c927 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -744,6 +744,8 @@
void EnterScope(intptr_t kernel_offset);
void ExitScope(TokenPosition start_position, TokenPosition end_position);
+ void ReportUnexpectedTag(const char* variant, Tag tag);
+
// This enum controls which parameters would be marked as requring type
// check on the callee side.
enum ParameterTypeCheckMode {
@@ -1045,6 +1047,8 @@
enum DispatchCategory { Interface, ViaThis, Closure, DynamicDispatch };
+ void ReportUnexpectedTag(const char* variant, Tag tag);
+
private:
void LoadAndSetupTypeParameters(ActiveClass* active_class,
const Object& set_on,
diff --git a/runtime/vm/isolate_reload_test.cc b/runtime/vm/isolate_reload_test.cc
index f2a44d1..a8b8928 100644
--- a/runtime/vm/isolate_reload_test.cc
+++ b/runtime/vm/isolate_reload_test.cc
@@ -17,9 +17,6 @@
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
-// TODO(johnmccutchan):
-// - Tests involving generics.
-
int64_t SimpleInvoke(Dart_Handle lib, const char* method) {
Dart_Handle result = Dart_Invoke(lib, NewString(method), 0, NULL);
EXPECT_VALID(result);
@@ -3500,6 +3497,31 @@
EXPECT_STREQ("false", SimpleInvokeStr(lib, "main"));
}
+TEST_CASE(IsolateReload_PatchStaticInitializerWithClosure) {
+ const char* kScript =
+ "dynamic field = (a) => 'a$a';\n"
+ "main() {\n"
+ " dynamic f = field;\n"
+ " return f('b');\n"
+ "}\n";
+
+ Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+ EXPECT_VALID(lib);
+ EXPECT_STREQ("ab", SimpleInvokeStr(lib, "main"));
+
+ const char* kReloadScript =
+ "extraFunction() => 'Just here to change kernel offsets';\n"
+ "dynamic field = (_, __) => 'Not executed';\n"
+ "main() {\n"
+ " dynamic f = field;\n"
+ " return f('c');\n"
+ "}\n";
+
+ lib = TestCase::ReloadTestScript(kReloadScript);
+ EXPECT_VALID(lib);
+ EXPECT_STREQ("ac", SimpleInvokeStr(lib, "main"));
+}
+
#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
} // namespace dart
diff --git a/runtime/vm/kernel_binary.cc b/runtime/vm/kernel_binary.cc
index eaa2ce6..21e833f 100644
--- a/runtime/vm/kernel_binary.cc
+++ b/runtime/vm/kernel_binary.cc
@@ -16,6 +16,19 @@
namespace kernel {
+const char* Reader::TagName(Tag tag) {
+ switch (tag) {
+#define CASE(Name, value) \
+ case k##Name: \
+ return #Name;
+ KERNEL_TAG_LIST(CASE)
+#undef CASE
+ default:
+ break;
+ }
+ return "Unknown";
+}
+
Program* Program::ReadFrom(Reader* reader, bool take_buffer_ownership) {
uint32_t magic = reader->ReadUInt32();
if (magic != kMagicProgramFile) FATAL("Invalid magic identifier");
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index d514487..3c56a69 100644
--- a/runtime/vm/kernel_binary.h
+++ b/runtime/vm/kernel_binary.h
@@ -22,122 +22,120 @@
static const uint32_t kBinaryFormatVersion = 3;
// Keep in sync with package:kernel/lib/binary/tag.dart
+#define KERNEL_TAG_LIST(V) \
+ V(Nothing, 0) \
+ V(Something, 1) \
+ V(Class, 2) \
+ V(FunctionNode, 3) \
+ V(Field, 4) \
+ V(Constructor, 5) \
+ V(Procedure, 6) \
+ V(RedirectingFactoryConstructor, 108) \
+ V(InvalidInitializer, 7) \
+ V(FieldInitializer, 8) \
+ V(SuperInitializer, 9) \
+ V(RedirectingInitializer, 10) \
+ V(LocalInitializer, 11) \
+ V(AssertInitializer, 12) \
+ V(CheckLibraryIsLoaded, 13) \
+ V(LoadLibrary, 14) \
+ V(DirectPropertyGet, 15) \
+ V(DirectPropertySet, 16) \
+ V(DirectMethodInvocation, 17) \
+ V(ConstStaticInvocation, 18) \
+ V(InvalidExpression, 19) \
+ V(VariableGet, 20) \
+ V(VariableSet, 21) \
+ V(PropertyGet, 22) \
+ V(PropertySet, 23) \
+ V(SuperPropertyGet, 24) \
+ V(SuperPropertySet, 25) \
+ V(StaticGet, 26) \
+ V(StaticSet, 27) \
+ V(MethodInvocation, 28) \
+ V(SuperMethodInvocation, 29) \
+ V(StaticInvocation, 30) \
+ V(ConstructorInvocation, 31) \
+ V(ConstConstructorInvocation, 32) \
+ V(Not, 33) \
+ V(LogicalExpression, 34) \
+ V(ConditionalExpression, 35) \
+ V(StringConcatenation, 36) \
+ V(IsExpression, 37) \
+ V(AsExpression, 38) \
+ V(StringLiteral, 39) \
+ V(DoubleLiteral, 40) \
+ V(TrueLiteral, 41) \
+ V(FalseLiteral, 42) \
+ V(NullLiteral, 43) \
+ V(SymbolLiteral, 44) \
+ V(TypeLiteral, 45) \
+ V(ThisExpression, 46) \
+ V(Rethrow, 47) \
+ V(Throw, 48) \
+ V(ListLiteral, 49) \
+ V(MapLiteral, 50) \
+ V(AwaitExpression, 51) \
+ V(FunctionExpression, 52) \
+ V(Let, 53) \
+ V(Instantiation, 54) \
+ V(PositiveIntLiteral, 55) \
+ V(NegativeIntLiteral, 56) \
+ V(BigIntLiteral, 57) \
+ V(ConstListLiteral, 58) \
+ V(ConstMapLiteral, 59) \
+ V(ExpressionStatement, 61) \
+ V(Block, 62) \
+ V(EmptyStatement, 63) \
+ V(AssertStatement, 64) \
+ V(LabeledStatement, 65) \
+ V(BreakStatement, 66) \
+ V(WhileStatement, 67) \
+ V(DoStatement, 68) \
+ V(ForStatement, 69) \
+ V(ForInStatement, 70) \
+ V(SwitchStatement, 71) \
+ V(ContinueSwitchStatement, 72) \
+ V(IfStatement, 73) \
+ V(ReturnStatement, 74) \
+ V(TryCatch, 75) \
+ V(TryFinally, 76) \
+ V(YieldStatement, 77) \
+ V(VariableDeclaration, 78) \
+ V(FunctionDeclaration, 79) \
+ V(AsyncForInStatement, 80) \
+ V(TypedefType, 87) \
+ V(VectorType, 88) \
+ V(BottomType, 89) \
+ V(InvalidType, 90) \
+ V(DynamicType, 91) \
+ V(VoidType, 92) \
+ V(InterfaceType, 93) \
+ V(FunctionType, 94) \
+ V(TypeParameterType, 95) \
+ V(SimpleInterfaceType, 96) \
+ V(SimpleFunctionType, 97) \
+ V(NullReference, 99) \
+ V(ClassReference, 100) \
+ V(MemberReference, 101) \
+ V(VectorCreation, 102) \
+ V(VectorGet, 103) \
+ V(VectorSet, 104) \
+ V(VectorCopy, 105) \
+ V(ClosureCreation, 106) \
+ V(ConstantExpression, 107) \
+ V(SpecializedVariableGet, 128) \
+ V(SpecializedVariableSet, 136) \
+ V(SpecializedIntLiteral, 144)
+
+static const intptr_t kSpecializedTagHighBit = 0x80;
+static const intptr_t kSpecializedTagMask = 0xf8;
+static const intptr_t kSpecializedPayloadMask = 0x7;
+
enum Tag {
- kNothing = 0,
- kSomething = 1,
-
- kClass = 2,
-
- kFunctionNode = 3,
- kField = 4,
- kConstructor = 5,
- kProcedure = 6,
-
- kInvalidInitializer = 7,
- kFieldInitializer = 8,
- kSuperInitializer = 9,
- kRedirectingInitializer = 10,
- kLocalInitializer = 11,
- kAssertInitializer = 12,
-
- kCheckLibraryIsLoaded = 13,
- kLoadLibrary = 14,
- kDirectPropertyGet = 15,
- kDirectPropertySet = 16,
- kDirectMethodInvocation = 17,
- kConstStaticInvocation = 18,
- kInvalidExpression = 19,
- kVariableGet = 20,
- kVariableSet = 21,
- kPropertyGet = 22,
- kPropertySet = 23,
- kSuperPropertyGet = 24,
- kSuperPropertySet = 25,
- kStaticGet = 26,
- kStaticSet = 27,
- kMethodInvocation = 28,
- kSuperMethodInvocation = 29,
- kStaticInvocation = 30,
- kConstructorInvocation = 31,
- kConstConstructorInvocation = 32,
- kNot = 33,
- kLogicalExpression = 34,
- kConditionalExpression = 35,
- kStringConcatenation = 36,
- kIsExpression = 37,
- kAsExpression = 38,
- kStringLiteral = 39,
- kDoubleLiteral = 40,
- kTrueLiteral = 41,
- kFalseLiteral = 42,
- kNullLiteral = 43,
- kSymbolLiteral = 44,
- kTypeLiteral = 45,
- kThisExpression = 46,
- kRethrow = 47,
- kThrow = 48,
- kListLiteral = 49,
- kMapLiteral = 50,
- kAwaitExpression = 51,
- kFunctionExpression = 52,
- kLet = 53,
- kInstantiation = 54,
-
- kPositiveIntLiteral = 55,
- kNegativeIntLiteral = 56,
- kBigIntLiteral = 57,
- kConstListLiteral = 58,
- kConstMapLiteral = 59,
-
- kExpressionStatement = 61,
- kBlock = 62,
- kEmptyStatement = 63,
- kAssertStatement = 64,
- kLabeledStatement = 65,
- kBreakStatement = 66,
- kWhileStatement = 67,
- kDoStatement = 68,
- kForStatement = 69,
- kForInStatement = 70,
- kSwitchStatement = 71,
- kContinueSwitchStatement = 72,
- kIfStatement = 73,
- kReturnStatement = 74,
- kTryCatch = 75,
- kTryFinally = 76,
- kYieldStatement = 77,
- kVariableDeclaration = 78,
- kFunctionDeclaration = 79,
- kAsyncForInStatement = 80,
-
- kTypedefType = 87,
- kVectorType = 88,
- kBottomType = 89,
- kInvalidType = 90,
- kDynamicType = 91,
- kVoidType = 92,
- kInterfaceType = 93,
- kFunctionType = 94,
- kTypeParameterType = 95,
- kSimpleInterfaceType = 96,
- kSimpleFunctionType = 97,
-
- kVectorCreation = 102,
- kVectorGet = 103,
- kVectorSet = 104,
- kVectorCopy = 105,
-
- kClosureCreation = 106,
-
- kConstantExpression = 107,
-
- kSpecializedTagHighBit = 0x80, // 10000000
- kSpecializedTagMask = 0xF8, // 11111000
- kSpecializedPayloadMask = 0x7, // 00000111
-
- kSpecializedVariableGet = 128,
- kSpecializedVariableSet = 136,
- kSpecialIntLiteral = 144,
+#define DECLARE(Name, value) k##Name = value,
+ KERNEL_TAG_LIST(DECLARE)
+#undef DECLARE
};
// Keep in sync with package:kernel/lib/binary/tag.dart
@@ -259,6 +257,8 @@
uint8_t ReadFlags() { return ReadByte(); }
+ static const char* TagName(Tag tag);
+
Tag ReadTag(uint8_t* payload = NULL) {
uint8_t byte = ReadByte();
bool has_payload = (byte & kSpecializedTagHighBit) != 0;
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index 831115a..c95abf0 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -61,7 +61,7 @@
simple_value_ = &H.DartSymbolPlain(
builder_->ReadStringReference()); // read index into string table.
return true;
- case kSpecialIntLiteral:
+ case kSpecializedIntLiteral:
simple_value_ =
&Integer::ZoneHandle(Z, Integer::New(static_cast<int32_t>(payload) -
SpecializedIntLiteralBias,
@@ -1607,8 +1607,22 @@
String& init_name = String::Handle(zone, field.name());
init_name = Symbols::FromConcat(thread, Symbols::InitPrefix(), init_name);
+ // Static field initializers are not added as members of their owning class,
+ // so they must be pre-emptively given a patch class to avoid the meaning of
+ // their kernel/token position changing during a reload. Compare
+ // Class::PatchFieldsAndFunctions().
+ // This might also be necessary for lazy computation of local var descriptors.
+ // Compare https://codereview.chromium.org//1317753004
+ const Script& script = Script::Handle(zone, field.Script());
+ const Class& field_owner = Class::Handle(zone, field.Owner());
+ const PatchClass& initializer_owner =
+ PatchClass::Handle(zone, PatchClass::New(field_owner, script));
+ const Library& lib = Library::Handle(zone, field_owner.library());
+ initializer_owner.set_library_kernel_data(
+ TypedData::Handle(zone, lib.kernel_data()));
+ initializer_owner.set_library_kernel_offset(lib.kernel_offset());
+
// Create a static initializer.
- const Object& owner = Object::Handle(field.RawOwner());
const Function& initializer_fun = Function::Handle(
zone, Function::New(init_name,
// TODO(alexmarkov): Consider creating a separate
@@ -1619,7 +1633,7 @@
false, // is_abstract
false, // is_external
false, // is_native
- owner, TokenPosition::kNoSource));
+ initializer_owner, TokenPosition::kNoSource));
initializer_fun.set_kernel_offset(field.kernel_offset());
initializer_fun.set_result_type(AbstractType::Handle(zone, field.type()));
initializer_fun.set_is_debuggable(false);
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 8c6d854..7702bac 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -929,6 +929,15 @@
*background_compilation_error_ =
LanguageError::New(error_str, Report::kBailout, Heap::kOld);
+ // Allocate the parameter arrays for method extractor types and names.
+ *extractor_parameter_types_ = Array::New(1, Heap::kOld);
+ extractor_parameter_types_->SetAt(0, Object::dynamic_type());
+ *extractor_parameter_names_ = Array::New(1, Heap::kOld);
+ // Fill in extractor_parameter_names_ later, after symbols are initialized
+ // (in Object::FinalizeVMIsolate). extractor_parameter_names_ object
+ // needs to be created earlier as VM isolate snapshot reader references it
+ // before Object::FinalizeVMIsolate.
+
// Some thread fields need to be reinitialized as null constants have not been
// initialized until now.
Thread* thr = Thread::Current();
@@ -984,6 +993,10 @@
ASSERT(background_compilation_error_->IsLanguageError());
ASSERT(!vm_isolate_snapshot_object_table_->IsSmi());
ASSERT(vm_isolate_snapshot_object_table_->IsArray());
+ ASSERT(!extractor_parameter_types_->IsSmi());
+ ASSERT(extractor_parameter_types_->IsArray());
+ ASSERT(!extractor_parameter_names_->IsSmi());
+ ASSERT(extractor_parameter_names_->IsArray());
}
// An object visitor which will mark all visited objects. This is used to
@@ -1046,17 +1059,10 @@
// Should only be run by the vm isolate.
ASSERT(isolate == Dart::vm_isolate());
- // Allocate the parameter arrays for method extractor types and names.
- *extractor_parameter_types_ = Array::New(1, Heap::kOld);
- extractor_parameter_types_->SetAt(0, Object::dynamic_type());
- *extractor_parameter_names_ = Array::New(1, Heap::kOld);
+ // Finish initialization of extractor_parameter_names_ which was
+ // Started in Object::InitOnce()
extractor_parameter_names_->SetAt(0, Symbols::This());
- ASSERT(!extractor_parameter_types_->IsSmi());
- ASSERT(extractor_parameter_types_->IsArray());
- ASSERT(!extractor_parameter_names_->IsSmi());
- ASSERT(extractor_parameter_names_->IsArray());
-
// Set up names for all VM singleton classes.
Class& cls = Class::Handle();
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 4f1f085..8946317 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -2389,7 +2389,8 @@
bool NeedsArgumentTypeChecks(Isolate* I) const {
if (I->strong()) {
- return !(is_static() || (kind() == RawFunction::kConstructor));
+ return IsNonImplicitClosureFunction() ||
+ !(is_static() || (kind() == RawFunction::kConstructor));
}
return I->type_checks();
}
diff --git a/runtime/vm/os_fuchsia.cc b/runtime/vm/os_fuchsia.cc
index 24a5608..0e4e6c4 100644
--- a/runtime/vm/os_fuchsia.cc
+++ b/runtime/vm/os_fuchsia.cc
@@ -68,9 +68,9 @@
if (GetTimeServicePtr(&time_svc) == ZX_OK) {
f1dl::String res;
time_svc->GetTimezoneId(&res);
- char* tz_name = Thread::Current()->zone()->Alloc<char>(res.size() + 1);
- memmove(tz_name, res.get().c_str(), res.size());
- tz_name[res.size()] = '\0';
+ char* tz_name = Thread::Current()->zone()->Alloc<char>(res->size() + 1);
+ memmove(tz_name, res->data(), res->size());
+ tz_name[res->size()] = '\0';
return tz_name;
}
return "";
diff --git a/runtime/vm/os_test.cc b/runtime/vm/os_test.cc
index d8be0f7..07b3cd9 100644
--- a/runtime/vm/os_test.cc
+++ b/runtime/vm/os_test.cc
@@ -10,17 +10,6 @@
namespace dart {
-VM_UNIT_TEST_CASE(Sleep) {
- // All times measured in microseconds.
- int64_t start_time = OS::GetCurrentMonotonicMicros();
- int64_t sleep_time = 702000;
- OS::SleepMicros(sleep_time);
- int64_t delta = OS::GetCurrentMonotonicMicros() - start_time;
- const int kAcceptableSleepWakeupJitter = 200000;
- EXPECT_GE(delta, sleep_time - kAcceptableSleepWakeupJitter);
- EXPECT_LE(delta, sleep_time + kAcceptableSleepWakeupJitter);
-}
-
VM_UNIT_TEST_CASE(SNPrint) {
char buffer[256];
int length;
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index 2b2537c..9ff89ee 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -419,7 +419,7 @@
// Only attempt to symbolize Dart frames if we can safely iterate the
// current isolate's heap.
Code& code = Code::Handle(Code::LookupCodeInVmIsolate(pc));
- if (!code.IsNull()) {
+ if (code.IsNull()) {
code = Code::LookupCode(pc); // In current isolate.
}
if (!code.IsNull()) {
@@ -934,23 +934,19 @@
// Get |thread|'s stack boundary and verify that |sp| and |fp| are within
// it. Return |false| if anything looks suspicious.
-static bool GetAndValidateThreadStackBounds(Thread* thread,
+static bool GetAndValidateThreadStackBounds(OSThread* os_thread,
+ Thread* thread,
uintptr_t fp,
uintptr_t sp,
uword* stack_lower,
uword* stack_upper) {
- OSThread* os_thread = NULL;
- if (thread != NULL) {
- os_thread = thread->os_thread();
- } else {
- os_thread = OSThread::Current();
- }
ASSERT(os_thread != NULL);
ASSERT(stack_lower != NULL);
ASSERT(stack_upper != NULL);
#if defined(USING_SIMULATOR)
- const bool use_simulator_stack_bounds = thread->IsExecutingDartCode();
+ const bool use_simulator_stack_bounds =
+ thread != NULL && thread->IsExecutingDartCode();
if (use_simulator_stack_bounds) {
Isolate* isolate = thread->isolate();
ASSERT(isolate != NULL);
@@ -1098,31 +1094,20 @@
}
}
- Thread* thread = Thread::Current();
- if (thread == NULL) {
- OS::PrintErr("Stack dump aborted because no current Dart thread.\n");
- return;
- }
- OSThread* os_thread = thread->os_thread();
+ OSThread* os_thread = OSThread::Current();
ASSERT(os_thread != NULL);
- Isolate* isolate = thread->isolate();
- if (!CheckIsolate(isolate)) {
- OS::PrintErr("Stack dump aborted because CheckIsolate failed.\n");
- return;
- }
-
OS::PrintErr("Dumping native stack trace for thread %" Px "\n",
OSThread::ThreadIdToIntPtr(os_thread->trace_id()));
- uword stack_lower = 0;
- uword stack_upper = 0;
-
if (!InitialRegisterCheck(pc, fp, sp)) {
OS::PrintErr("Stack dump aborted because InitialRegisterCheck failed.\n");
return;
}
- if (!GetAndValidateThreadStackBounds(thread, fp, sp, &stack_lower,
+ Thread* thread = Thread::Current(); // NULL if no current isolate.
+ uword stack_lower = 0;
+ uword stack_upper = 0;
+ if (!GetAndValidateThreadStackBounds(os_thread, thread, fp, sp, &stack_lower,
&stack_upper)) {
OS::PrintErr(
"Stack dump aborted because GetAndValidateThreadStackBounds failed.\n");
@@ -1130,8 +1115,7 @@
}
ProfilerNativeStackWalker native_stack_walker(
- (isolate != NULL) ? isolate->main_port() : ILLEGAL_PORT, NULL, NULL,
- stack_lower, stack_upper, pc, fp, sp);
+ ILLEGAL_PORT, NULL, NULL, stack_lower, stack_upper, pc, fp, sp);
native_stack_walker.walk();
OS::PrintErr("-- End of DumpStackTrace\n");
}
@@ -1166,7 +1150,7 @@
return;
}
- if (!GetAndValidateThreadStackBounds(thread, fp, sp, &stack_lower,
+ if (!GetAndValidateThreadStackBounds(os_thread, thread, fp, sp, &stack_lower,
&stack_upper)) {
// Could not get stack boundary.
return;
@@ -1352,7 +1336,7 @@
uword stack_lower = 0;
uword stack_upper = 0;
- if (!GetAndValidateThreadStackBounds(thread, fp, sp, &stack_lower,
+ if (!GetAndValidateThreadStackBounds(os_thread, thread, fp, sp, &stack_lower,
&stack_upper)) {
AtomicOperations::IncrementInt64By(
&counters_.single_frame_sample_get_and_validate_stack_bounds, 1);
diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
index ed7134c..a947a5f 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
@@ -3080,6 +3080,16 @@
final Closure _genericClosure;
Instantiation(this._genericClosure) {
// TODO(sra): Copy some metadata used by Function.apply.
+
+ // Mark support code as used. The JS condition is inscrutable to dart2js,
+ // so the 'if (false)' is in the final program.
+ // TODO(sra): Find a better way to do this. Generating the signature methods
+ // earlier as SSA on the instantiation closures should achieve this.
+ if (JS('bool', 'false')) {
+ // [instantiatedGenericFunctionType] is called from injected $signature
+ // methods with runtime type representations.
+ instantiatedGenericFunctionType(JS('', '0'), JS('', '0'));
+ }
}
/// Returns a list of the bound types.
diff --git a/sdk/lib/_internal/js_runtime/lib/js_rti.dart b/sdk/lib/_internal/js_runtime/lib/js_rti.dart
index 46c77da..9c20637 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_rti.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_rti.dart
@@ -1181,6 +1181,144 @@
return type is num; // Actually int, but 'is num' is faster.
}
+/// Returns [genericFunctionRti] with type parameters bound to [parameters].
+///
+/// [genericFunctionRti] must be an rti representation with a number of generic
+/// type parameters matching the number of types in [parameters].
+///
+/// Called from generated code.
+@NoInline()
+instantiatedGenericFunctionType(genericFunctionRti, parameters) {
+ assert(isDartFunctionType(genericFunctionRti));
+
+ var genericBoundsTag =
+ JS_GET_NAME(JsGetName.FUNCTION_TYPE_GENERIC_BOUNDS_TAG);
+
+ assert(hasField(genericFunctionRti, genericBoundsTag));
+ var bounds = getField(genericFunctionRti, genericBoundsTag);
+
+ // Generic function types must agree on number of type parameters and bounds.
+ int boundLength = getLength(bounds);
+ int parametersLength = getLength(parameters);
+ assert(boundLength == parametersLength);
+
+ var result = JS('', '{#:1}', JS_GET_NAME(JsGetName.FUNCTION_TYPE_TAG));
+ return finishBindInstantiatedFunctionType(
+ genericFunctionRti, result, parameters, 0);
+}
+
+bindInstantiatedFunctionType(rti, parameters, int depth) {
+ var result = JS('', '{#:1}', JS_GET_NAME(JsGetName.FUNCTION_TYPE_TAG));
+
+ var genericBoundsTag =
+ JS_GET_NAME(JsGetName.FUNCTION_TYPE_GENERIC_BOUNDS_TAG);
+ if (hasField(rti, genericBoundsTag)) {
+ var bounds = getField(rti, genericBoundsTag);
+ depth += getLength(bounds);
+ setField(result, genericBoundsTag,
+ bindInstantiatedTypes(bounds, parameters, depth));
+ }
+
+ return finishBindInstantiatedFunctionType(rti, result, parameters, depth);
+}
+
+/// Common code for function types that copies all non-bounds parts of the
+/// function [rti] into [result].
+finishBindInstantiatedFunctionType(rti, result, parameters, int depth) {
+ var voidReturnTag = JS_GET_NAME(JsGetName.FUNCTION_TYPE_VOID_RETURN_TAG);
+ var returnTypeTag = JS_GET_NAME(JsGetName.FUNCTION_TYPE_RETURN_TYPE_TAG);
+
+ if (hasField(rti, voidReturnTag)) {
+ setField(result, voidReturnTag, getField(rti, voidReturnTag));
+ } else if (hasField(rti, returnTypeTag)) {
+ setField(result, returnTypeTag,
+ bindInstantiatedType(getField(rti, returnTypeTag), parameters, depth));
+ }
+
+ var requiredParametersTag =
+ JS_GET_NAME(JsGetName.FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG);
+ if (hasField(rti, requiredParametersTag)) {
+ setField(
+ result,
+ requiredParametersTag,
+ bindInstantiatedTypes(
+ getField(rti, requiredParametersTag), parameters, depth));
+ }
+
+ String optionalParametersTag =
+ JS_GET_NAME(JsGetName.FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG);
+ if (hasField(rti, optionalParametersTag)) {
+ setField(
+ result,
+ optionalParametersTag,
+ bindInstantiatedTypes(
+ getField(rti, optionalParametersTag), parameters, depth));
+ }
+
+ String namedParametersTag =
+ JS_GET_NAME(JsGetName.FUNCTION_TYPE_NAMED_PARAMETERS_TAG);
+ if (hasField(rti, namedParametersTag)) {
+ var namedParameters = getField(rti, namedParametersTag);
+ var boundNamed = JS('', '{}');
+ var names = JS('JSFixedArray', 'Object.keys(#)', namedParameters);
+ for (var name in names) {
+ setField(
+ boundNamed,
+ name,
+ bindInstantiatedType(
+ getField(namedParameters, name), parameters, depth));
+ }
+ setField(result, namedParametersTag, boundNamed);
+ }
+
+ return result;
+}
+
+/// Copies [rti], substituting generic type parameters from [parameters].
+///
+/// Generic type parameters are de Bruijn indexes counting up through the
+/// generic function type parameters scopes to index into [parameters].
+///
+/// [depth] is the number of subsequent generic function parameters that are in
+/// scope. This is subtracted off the de Bruijn index for the type parameter to
+/// arrive at an potential index into [parameters].
+bindInstantiatedType(rti, parameters, int depth) {
+ if (rti == null) return rti; // dynamic.
+ // Functions are constructors denoting the class of the constructor.
+ if (isJsFunction(rti)) return rti;
+
+ // de Bruijn type indexes.
+ if (isGenericFunctionTypeParameter(rti)) {
+ if (rti < depth) return rti;
+ return JS('', '#[#]', parameters, rti - depth);
+ }
+ // Other things encoded as numbers.
+ if (rti is num) return rti;
+
+ if (isJsArray(rti)) {
+ // An array is a parameterized class type, e.g. the list of three
+ // constructor functions [Map, String, int] represents `Map<String, int>`.
+ // Since the 'head' of the term and the arguments are encoded in the same
+ // scheme, it is sufficient to walk all the types.
+ return bindInstantiatedTypes(rti, parameters, depth);
+ }
+ if (isDartFunctionType(rti)) {
+ return bindInstantiatedFunctionType(rti, parameters, depth);
+ }
+
+ // Can't include the bad [rti] since it is not a Dart value.
+ throw new ArgumentError('Unknown RTI format in bindInstantiatedType.');
+}
+
+/// Returns a copy of array [rti] with each type bound.
+bindInstantiatedTypes(rti, parameters, int depth) {
+ List array = JS('JSFixedArray', '#.slice()', rti);
+ for (int i = 0; i < array.length; i++) {
+ array[i] = bindInstantiatedType(array[i], parameters, depth);
+ }
+ return array;
+}
+
/**
* Calls the JavaScript [function] with the [arguments] with the global scope
* as the `this` context.
@@ -1209,6 +1347,14 @@
return JS('var', r'#[#]', array, index);
}
+setField(var object, String name, var value) {
+ JS('', '#[#] = #', object, name, value);
+}
+
+setIndex(var array, int index, var value) {
+ JS('', '#[#] = #', array, index, value);
+}
+
/// Returns the length of the JavaScript array [array].
int getLength(var array) {
assert(isJsArray(array));
diff --git a/sdk/lib/convert/ascii.dart b/sdk/lib/convert/ascii.dart
index cd54517..40cf405 100644
--- a/sdk/lib/convert/ascii.dart
+++ b/sdk/lib/convert/ascii.dart
@@ -11,10 +11,11 @@
* use cases.
*
* Examples:
- *
- * var encoded = ascii.encode("This is ASCII!");
- * var decoded = ascii.decode([0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73,
- * 0x20, 0x41, 0x53, 0x43, 0x49, 0x49, 0x21]);
+ * ```dart
+ * var encoded = ascii.encode("This is ASCII!");
+ * var decoded = ascii.decode([0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73,
+ * 0x20, 0x41, 0x53, 0x43, 0x49, 0x49, 0x21]);
+ * ```
*/
const AsciiCodec ascii = const AsciiCodec();
@Deprecated("Use ascii instead")
@@ -43,6 +44,8 @@
String get name => "us-ascii";
+ Uint8List encode(String source) => encoder.convert(source);
+
/**
* Decodes the ASCII [bytes] (a list of unsigned 7-bit integers) to the
* corresponding string.
@@ -82,12 +85,12 @@
* If [start] and [end] are provided, only the substring
* `string.substring(start, end)` is used as input to the conversion.
*/
- List<int> convert(String string, [int start = 0, int end]) {
+ Uint8List convert(String string, [int start = 0, int end]) {
int stringLength = string.length;
RangeError.checkValidRange(start, end, stringLength);
if (end == null) end = stringLength;
int length = end - start;
- List<int> result = new Uint8List(length);
+ var result = new Uint8List(length);
for (int i = 0; i < length; i++) {
var codeUnit = string.codeUnitAt(start + i);
if ((codeUnit & ~_subsetMask) != 0) {
diff --git a/sdk/lib/convert/base64.dart b/sdk/lib/convert/base64.dart
index bbccf95..a2a29f4 100644
--- a/sdk/lib/convert/base64.dart
+++ b/sdk/lib/convert/base64.dart
@@ -38,6 +38,27 @@
@Deprecated("Use base64Url instead")
const Base64Codec BASE64URL = base64Url;
+/**
+ * Encodes [bytes] using [base64](https://tools.ietf.org/html/rfc4648) encoding.
+ *
+ * Shorthand for [base64.encode].
+ */
+String base64Encode(List<int> bytes) => base64.encode(bytes);
+
+/**
+ * Encodes [bytes] using [base64url](https://tools.ietf.org/html/rfc4648) encoding.
+ *
+ * Shorthand for [base64url.encode].
+ */
+String base64UrlEncode(List<int> bytes) => base64Url.encode(bytes);
+
+/**
+ * Decodes [base64](https://tools.ietf.org/html/rfc4648) or [base64url](https://tools.ietf.org/html/rfc4648) encoded bytes.
+ *
+ * Shorthand for [base64.decode].
+ */
+Uint8List base64Decode(String source) => base64.decode(source);
+
// Constants used in more than one class.
const int _paddingChar = 0x3d; // '='.
diff --git a/sdk/lib/convert/json.dart b/sdk/lib/convert/json.dart
index b9095d1..a5e8d86 100644
--- a/sdk/lib/convert/json.dart
+++ b/sdk/lib/convert/json.dart
@@ -69,6 +69,37 @@
@Deprecated("Use json instead")
const JsonCodec JSON = json;
+/**
+ * Converts [value] to a JSON string.
+ *
+ * If value contains objects that are not directly encodable to a JSON
+ * string (a value that is not a number, boolean, string, null, list or a map
+ * with string keys), the [toEncodable] function is used to convert it to an
+ * object that must be directly encodable.
+ *
+ * If [toEncodable] is omitted, it defaults to a function that returns the
+ * result of calling `.toJson()` on the unencodable object.
+ *
+ * Shorthand for [json.encode].
+ */
+String jsonEncode(Object object, {Object toEncodable(Object nonEncodable)}) =>
+ json.encode(object, toEncodable: toEncodable);
+
+/**
+ * Parses the string and returns the resulting Json object.
+ *
+ * The optional [reviver] function is called once for each object or list
+ * property that has been parsed during decoding. The `key` argument is either
+ * the integer list index for a list property, the string map key for object
+ * properties, or `null` for the final result.
+ *
+ * The default [reviver] (when not provided) is the identity function.
+ *
+ * Shorthand for [json.decode].
+ */
+dynamic jsonDecode(String source, {Object reviver(Object key, Object value)}) =>
+ json.decode(source, reviver: reviver);
+
typedef _Reviver(Object key, Object value);
typedef _ToEncodable(var o);
diff --git a/sdk/lib/convert/latin1.dart b/sdk/lib/convert/latin1.dart
index a2f8e8a..1de1bb3 100644
--- a/sdk/lib/convert/latin1.dart
+++ b/sdk/lib/convert/latin1.dart
@@ -11,10 +11,11 @@
* use cases.
*
* Examples:
- *
- * var encoded = latin1.encode("blåbærgrød");
- * var decoded = latin1.decode([0x62, 0x6c, 0xe5, 0x62, 0xe6,
- * 0x72, 0x67, 0x72, 0xf8, 0x64]);
+ * ```dart
+ * var encoded = latin1.encode("blåbærgrød");
+ * var decoded = latin1.decode([0x62, 0x6c, 0xe5, 0x62, 0xe6,
+ * 0x72, 0x67, 0x72, 0xf8, 0x64]);
+ * ```
*/
const Latin1Codec latin1 = const Latin1Codec();
@Deprecated("Use latin1 instead")
@@ -42,6 +43,8 @@
String get name => "iso-8859-1";
+ Uint8List encode(String source) => encoder.convert(source);
+
/**
* Decodes the Latin-1 [bytes] (a list of unsigned 8-bit integers) to the
* corresponding string.
diff --git a/sdk/lib/core/uri.dart b/sdk/lib/core/uri.dart
index b301d80..dce9ac3 100644
--- a/sdk/lib/core/uri.dart
+++ b/sdk/lib/core/uri.dart
@@ -3472,7 +3472,7 @@
* percent-escaped characters and returning byte values of each unescaped
* character. The bytes will not be, e.g., UTF-8 decoded.
*/
- List<int> contentAsBytes() {
+ Uint8List contentAsBytes() {
String text = _text;
int start = _separatorIndices.last + 1;
if (isBase64) {
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index 8cb3115..1d1faa0 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -1451,6 +1451,7 @@
[ $compiler == dart2js && $runtime == d8 && $fasta ]
LayoutTests/*: SkipByDesign
LibTest/html/*: SkipByDesign
+LibTest/html/Element/mouseEnterEvent_A01_t01: RuntimeError
WebPlatformTest/*: SkipByDesign
[ $compiler == dart2js && $runtime != d8 && $runtime != drt && $checked ]
@@ -7079,7 +7080,6 @@
LibTest/html/Document/dispatchEvent_A01_t01: Crash
LibTest/html/Document/on_A01_t01: Crash
LibTest/html/Document/on_A01_t02: Crash
-LibTest/html/Element/mouseEnterEvent_A01_t01: RuntimeError
LibTest/html/HttpRequest/abort_A01_t01: Crash
LibTest/html/HttpRequest/dispatchEvent_A01_t01: Crash
LibTest/html/HttpRequest/getAllResponseHeaders_A01_t01: Crash
diff --git a/tests/compiler/dart2js/equivalence/check_functions.dart b/tests/compiler/dart2js/equivalence/check_functions.dart
index a0fd52d..01e83cc 100644
--- a/tests/compiler/dart2js/equivalence/check_functions.dart
+++ b/tests/compiler/dart2js/equivalence/check_functions.dart
@@ -1037,20 +1037,6 @@
"TypeTestRegistry rti needed classes mismatch",
strategy.elementEquivalence,
verbose: verbose);
-
- checkSets(
- emitter1.typeTestRegistry.rtiChecks.checkedFunctionTypes,
- emitter2.typeTestRegistry.rtiChecks.checkedFunctionTypes,
- "TypeTestRegistry checked function types mismatch",
- strategy.typeEquivalence,
- verbose: verbose);
-
- checkSets(
- emitter1.typeTestRegistry.rtiChecks.checkedClasses,
- emitter2.typeTestRegistry.rtiChecks.checkedClasses,
- "TypeTestRegistry checked classes mismatch",
- strategy.elementEquivalence,
- verbose: verbose);
}
void checkEmitterPrograms(
diff --git a/tests/compiler/dart2js/rti/emission/function_subtype_call2.dart b/tests/compiler/dart2js/rti/emission/function_subtype_call2.dart
new file mode 100644
index 0000000..d26680e
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/function_subtype_call2.dart
@@ -0,0 +1,64 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test program for constructors and initializers.
+
+// Based on tests/language/function_subtype_call2_test.dart
+
+import 'package:expect/expect.dart';
+
+typedef void Foo(bool a, [String b]);
+typedef void Bar(bool a, [String b]);
+typedef void Baz(bool a, {String b});
+typedef void Boz(bool a);
+
+/*class: C1:checks=[$signature]*/
+class C1<T> {
+ void call(T a, [String b]) {}
+}
+
+/*class: D1:checks=[$asC1],instance*/
+class D1<S, T> extends C1<T> {}
+
+/*class: C2:checks=[$signature]*/
+class C2<T> {
+ void call(T a, {String b}) {}
+}
+
+/*class: D2:checks=[$asC2],instance*/
+class D2<S, T> extends C2<T> {}
+
+main() {
+ Expect.isTrue(new D1<String, bool>() is Foo, 'new D1<String, bool>() is Foo');
+ Expect.isTrue(new D1<String, bool>() is Bar, 'new D1<String, bool>() is Bar');
+ Expect.isFalse(
+ new D1<String, bool>() is Baz, 'new D1<String, bool>() is Baz');
+ Expect.isTrue(new D1<String, bool>() is Boz, 'new D1<String, bool>() is Boz');
+
+ Expect.isFalse(new D1<bool, int>() is Foo, 'new D1<bool, int>() is Foo');
+ Expect.isFalse(new D1<bool, int>() is Bar, 'new D1<bool, int>() is Bar');
+ Expect.isFalse(new D1<bool, int>() is Baz, 'new D1<bool, int>() is Baz');
+ Expect.isFalse(new D1<bool, int>() is Boz, 'new D1<bool, int>() is Boz');
+
+ Expect.isTrue(new D1() is Foo, 'new D1() is Foo');
+ Expect.isTrue(new D1() is Bar, 'new D1() is Bar');
+ Expect.isFalse(new D1() is Baz, 'new D1() is Baz');
+ Expect.isTrue(new D1() is Boz, 'new D1() is Boz');
+
+ Expect.isFalse(
+ new D2<String, bool>() is Foo, 'new D2<String, bool>() is Foo');
+ Expect.isFalse(
+ new D2<String, bool>() is Bar, 'new D2<String, bool>() is Bar');
+ Expect.isTrue(new D2<String, bool>() is Baz, 'new D2<String, bool>() is Baz');
+ Expect.isTrue(new D2<String, bool>() is Boz, 'new D2<String, bool>() is Boz');
+
+ Expect.isFalse(new D2<bool, int>() is Foo, 'new D2<bool, int>() is Foo');
+ Expect.isFalse(new D2<bool, int>() is Bar, 'new D2<bool, int>() is Bar');
+ Expect.isFalse(new D2<bool, int>() is Baz, 'new D2<bool, int>() is Baz');
+ Expect.isFalse(new D2<bool, int>() is Boz, 'new D2<bool, int>() is Boz');
+
+ Expect.isFalse(new D2() is Foo, 'new D2() is Foo');
+ Expect.isFalse(new D2() is Bar, 'new D2() is Bar');
+ Expect.isTrue(new D2() is Baz, 'new D2() is Baz');
+ Expect.isTrue(new D2() is Boz, 'new D2() is Boz');
+}
diff --git a/tests/compiler/dart2js/rti/emission/type_variable_function_type.dart b/tests/compiler/dart2js/rti/emission/type_variable_function_type.dart
index 6f7f82e..44d0e88 100644
--- a/tests/compiler/dart2js/rti/emission/type_variable_function_type.dart
+++ b/tests/compiler/dart2js/rti/emission/type_variable_function_type.dart
@@ -2,7 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// Based on tests\language_2\type_variable_function_type_test.dart
+// Based on tests/language_2/type_variable_function_type_test.dart
import 'package:expect/expect.dart';
diff --git a/tests/compiler/dart2js_extra/dart2js_extra.status b/tests/compiler/dart2js_extra/dart2js_extra.status
index 265e9ab..0eded1d 100644
--- a/tests/compiler/dart2js_extra/dart2js_extra.status
+++ b/tests/compiler/dart2js_extra/dart2js_extra.status
@@ -12,6 +12,8 @@
no_such_method_test: Fail # Wrong Invocation.memberName.
statements_test: Fail
typed_locals_test: Pass, Fail
+
+[ $compiler == dart2js && !$checked ]
closure_signature_unneeded_test: RuntimeError # Too eager signature generation.
[ $compiler != dart2js ]
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index a1906b5..3099dae 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -443,8 +443,6 @@
class_literal_test/01: RuntimeError
class_literal_test/03: RuntimeError
class_literal_test/07: RuntimeError
-closure_in_field_test/01: RuntimeError
-closure_in_field_test/02: RuntimeError
config_import_test: RuntimeError
const_error_multiply_initialized_test/02: MissingCompileTimeError
const_error_multiply_initialized_test/04: MissingCompileTimeError
diff --git a/tests/language_2/issue32353_2_test.dart b/tests/language_2/issue32353_2_test.dart
new file mode 100644
index 0000000..6f0723b
--- /dev/null
+++ b/tests/language_2/issue32353_2_test.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.
+// SharedOptions=--supermixin
+
+// The following compile-time error is expected:
+//
+// Error: 'D' can't implement both '#lib1::B<#lib1::D::X, #lib1::D::Y>' and
+// '#lib1::B<#lib1::D::X, #lib1::A>'
+// class D<X, Y> extends B<X, Y> with C<X> {}
+// ^
+
+class A {}
+
+class B<X, Y> {}
+
+class C<X> extends B<X, A> {}
+
+class /*@compile-error=unspecified*/ D<X, Y> extends B<X, Y> with C {}
+
+main() {}
diff --git a/tests/language_2/bug32353_test.dart b/tests/language_2/issue32353_test.dart
similarity index 63%
rename from tests/language_2/bug32353_test.dart
rename to tests/language_2/issue32353_test.dart
index 3284e51..fbcc5d4 100644
--- a/tests/language_2/bug32353_test.dart
+++ b/tests/language_2/issue32353_test.dart
@@ -3,30 +3,32 @@
// BSD-style license that can be found in the LICENSE file.
// SharedOptions=--supermixin
-import 'dart:io' as io;
-
import "package:expect/expect.dart";
+class io_FileSystemEntity {}
+
+class io_Directory extends io_FileSystemEntity {}
+
class _LocalDirectory
- extends _LocalFileSystemEntity<_LocalDirectory, io.Directory>
+ 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> {}
+ D extends io_FileSystemEntity> extends ForwardingFileSystemEntity<T, D> {}
-abstract class FileSystemEntity implements io.FileSystemEntity {}
+abstract class FileSystemEntity implements io_FileSystemEntity {}
abstract class ForwardingFileSystemEntity<T extends FileSystemEntity,
- D extends io.FileSystemEntity> implements FileSystemEntity {}
+ D extends io_FileSystemEntity> implements FileSystemEntity {}
abstract class ForwardingDirectory<T extends Directory>
- extends ForwardingFileSystemEntity<T, io.Directory> implements Directory {
+ extends ForwardingFileSystemEntity<T, io_Directory> implements Directory {
get t => T;
}
-abstract class Directory implements FileSystemEntity, io.Directory {}
+abstract class Directory implements FileSystemEntity, io_Directory {}
abstract class DirectoryAddOnsMixin implements Directory {}
diff --git a/tests/language_2/language_2_analyzer.status b/tests/language_2/language_2_analyzer.status
index 621ca8b..c0b565c 100644
--- a/tests/language_2/language_2_analyzer.status
+++ b/tests/language_2/language_2_analyzer.status
@@ -1479,6 +1479,7 @@
issue31596_override_test/08: MissingCompileTimeError
issue31596_super_test/02: MissingCompileTimeError
issue31596_super_test/04: MissingCompileTimeError
+issue32353_2_test: MissingCompileTimeError
known_identifier_prefix_error_test/*: MissingCompileTimeError # Error only in strong mode.
known_identifier_prefix_error_test/none: Pass
least_upper_bound_expansive_test/01: MissingCompileTimeError
diff --git a/tests/language_2/language_2_dart2js.status b/tests/language_2/language_2_dart2js.status
index f9b08c8..90f26a7 100644
--- a/tests/language_2/language_2_dart2js.status
+++ b/tests/language_2/language_2_dart2js.status
@@ -34,9 +34,9 @@
[ $compiler == dart2js && $runtime == d8 && $fasta ]
assertion_test: RuntimeError
-bug32353_test: CompileTimeError
bug32372_test: CompileTimeError
implicit_creation/implicit_new_constructor_generic_test: Pass
+issue32353_test: CompileTimeError
[ $compiler == dart2js && $runtime == ff ]
field_override_optimization_test: RuntimeError
@@ -1467,14 +1467,12 @@
generic_function_dcall_test: RuntimeError
generic_function_type_as_type_argument_test/01: MissingCompileTimeError
generic_function_type_as_type_argument_test/02: MissingCompileTimeError
-generic_function_type_as_type_argument_test/03: RuntimeError
generic_function_type_within_type_argument_test: RuntimeError
generic_function_typedef_test/01: RuntimeError
generic_instanceof2_test: RuntimeError
generic_instanceof_test: RuntimeError
generic_is_check_test: RuntimeError
generic_method_types_test/02: RuntimeError
-generic_method_types_test/03: RuntimeError
generic_methods_bounds_test/01: MissingCompileTimeError
generic_methods_bounds_test/02: MissingRuntimeError
generic_methods_dynamic_test/02: MissingRuntimeError
@@ -1485,14 +1483,12 @@
generic_methods_recursive_bound_test/02: MissingCompileTimeError
generic_methods_recursive_bound_test/03: Crash # 'file:*/pkg/compiler/lib/src/js_emitter/metadata_collector.dart': Failed assertion: line 100 pos 12: 'isBound': is not true.
generic_methods_simple_as_expression_test/02: MissingRuntimeError
-generic_methods_tearoff_specialization_test: RuntimeError
generic_methods_type_expression_test: RuntimeError
generic_methods_unused_parameter_test: Crash # Assertion failure: kind=special,memberName=instantiate,callStructure:CallStructure(arity=0, types=1)
generic_no_such_method_dispatcher_simple_test: CompileTimeError
generic_no_such_method_dispatcher_test: CompileTimeError
generic_tearoff_test: CompileTimeError
generic_test: RuntimeError
-generic_typedef_test: RuntimeError
getter_override2_test/02: MissingCompileTimeError
getter_override_test/00: MissingCompileTimeError
getter_override_test/01: MissingCompileTimeError
@@ -2325,14 +2321,12 @@
generic_function_dcall_test: RuntimeError
generic_function_type_as_type_argument_test/01: MissingCompileTimeError
generic_function_type_as_type_argument_test/02: MissingCompileTimeError
-generic_function_type_as_type_argument_test/03: RuntimeError
generic_function_type_within_type_argument_test: RuntimeError
generic_function_typedef_test/01: RuntimeError
generic_instanceof2_test: RuntimeError
generic_instanceof_test: RuntimeError
generic_is_check_test: RuntimeError
generic_method_types_test/02: RuntimeError
-generic_method_types_test/03: RuntimeError
generic_methods_bounds_test/01: MissingCompileTimeError
generic_methods_bounds_test/02: MissingRuntimeError
generic_methods_dynamic_test/02: MissingRuntimeError
@@ -2343,13 +2337,11 @@
generic_methods_recursive_bound_test/02: MissingCompileTimeError
generic_methods_recursive_bound_test/03: Crash # NoSuchMethodError: The method 'markSeen' was called on null.
generic_methods_simple_as_expression_test/02: MissingRuntimeError
-generic_methods_tearoff_specialization_test: RuntimeError
generic_methods_type_expression_test: RuntimeError
generic_methods_unused_parameter_test: RuntimeError
generic_no_such_method_dispatcher_simple_test: CompileTimeError
generic_no_such_method_dispatcher_test: CompileTimeError
generic_tearoff_test: CompileTimeError
-generic_typedef_test: RuntimeError
getter_override2_test/02: MissingCompileTimeError
getter_override_test/00: MissingCompileTimeError
getter_override_test/01: MissingCompileTimeError
diff --git a/tests/language_2/language_2_dartdevc.status b/tests/language_2/language_2_dartdevc.status
index 71846f3..5fdbc77 100644
--- a/tests/language_2/language_2_dartdevc.status
+++ b/tests/language_2/language_2_dartdevc.status
@@ -21,7 +21,6 @@
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
bug32372_test: RuntimeError
built_in_identifier_prefix_test: CompileTimeError
built_in_identifier_type_annotation_test/22: MissingCompileTimeError # Issue 28816
@@ -128,6 +127,7 @@
issue31596_super_test/none: CompileTimeError
issue31596_tearoff_test: CompileTimeError
issue31596_test: CompileTimeError
+issue32353_test: RuntimeError
label_test: RuntimeError
lazy_static3_test: RuntimeError # Issue 30852
lazy_static8_test: RuntimeError # Issue 30852
@@ -335,7 +335,6 @@
bad_override_test/03: MissingCompileTimeError
bad_override_test/04: MissingCompileTimeError
bad_override_test/05: MissingCompileTimeError
-bug32353_test: RuntimeError # Issue 32428
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
@@ -472,6 +471,7 @@
issue31596_super_test/03: CompileTimeError
issue31596_super_test/04: MissingCompileTimeError
issue31596_super_test/05: RuntimeError
+issue32353_test: RuntimeError # Issue 32428
library_env_test/has_io_support: RuntimeError # Unsupported operation: bool.fromEnvironment can only be used as a const constructor
library_env_test/has_mirror_support: RuntimeError # Unsupported operation: bool.fromEnvironment can only be used as a const constructor
library_env_test/has_no_html_support: RuntimeError # Unsupported operation: bool.fromEnvironment can only be used as a const constructor
@@ -590,6 +590,8 @@
multiline_newline_test/06r: MissingCompileTimeError
named_constructor_test/01: MissingCompileTimeError
named_parameters_default_eq_test/02: MissingCompileTimeError
+no_such_method_mock_test: RuntimeError # Issue 31425
+nosuchmethod_forwarding/nosuchmethod_forwarding_test/06: RuntimeError # Issue 31425
nsm5_test: MissingCompileTimeError
null2_test: RuntimeError # Issue 32194
null_method_test: RuntimeError # Issue 32194
@@ -821,7 +823,6 @@
nan_identical_test: RuntimeError # Issue 29920; Unsupported operation: Uint64 accessor not supported by dart2js.
nested_switch_label_test: RuntimeError # Issue 29920; UnimplementedError: node <ShadowContinueSwitchStatement> see https://github.com/dart-lang/sdk/issues/29352 `continue #L1;
no_such_method_test: RuntimeError # UnimplementedError: JsInstanceMirror.delegate unimplemented
-nosuchmethod_forwarding/nosuchmethod_forwarding_test/06: RuntimeError # Issue #31425
null_test/mirrors: RuntimeError # Uses mirrors.; ReferenceError: GenericOfT is not defined
number_identity2_test: RuntimeError # Issue 29920; Expect.isTrue(false) fails.
numbers_test: RuntimeError # Issue 29920; Expect.equals(expected: <false>, actual: <true>) fails.
diff --git a/tests/language_2/language_2_kernel.status b/tests/language_2/language_2_kernel.status
index 57094de..055e78b 100644
--- a/tests/language_2/language_2_kernel.status
+++ b/tests/language_2/language_2_kernel.status
@@ -17,8 +17,6 @@
duplicate_implements_test/02: MissingCompileTimeError
generic_methods_generic_function_result_test/01: MissingCompileTimeError
generic_no_such_method_dispatcher_test: RuntimeError # Issue 31424
-mock_writable_final_field_test: RuntimeError # Issue 31424
-no_such_method_subtype_test: RuntimeError # Issue 31424
[ $compiler == fasta ]
assertion_initializer_const_error2_test/cc01: MissingCompileTimeError
@@ -716,8 +714,9 @@
nested_generic_closure_test: RuntimeError
no_main_test/01: DartkCrash
no_main_test/01: Skip
-nosuchmethod_forwarding/nosuchmethod_forwarding_test/05: RuntimeError # Issue #31426
-nosuchmethod_forwarding/nosuchmethod_forwarding_test/06: RuntimeError # Issue #31426
+no_such_method_mock_test: RuntimeError # Issue 31426
+nosuchmethod_forwarding/nosuchmethod_forwarding_test/05: RuntimeError # Issue 31426
+nosuchmethod_forwarding/nosuchmethod_forwarding_test/06: RuntimeError # Issue 31426
null_no_such_method_test: CompileTimeError # Issue 31533
override_inheritance_field_test/04: CompileTimeError # Issue 31616
override_inheritance_field_test/06: CompileTimeError # Issue 31616
@@ -1075,9 +1074,8 @@
no_main_test/01: Skip
no_such_method_mock_test: RuntimeError
no_such_method_test: SkipByDesign
-nosuchmethod_forwarding/nosuchmethod_forwarding_test/04: RuntimeError # Issue #31911
-nosuchmethod_forwarding/nosuchmethod_forwarding_test/05: RuntimeError # Issue #31426
-nosuchmethod_forwarding/nosuchmethod_forwarding_test/06: RuntimeError # Issue #31426
+nosuchmethod_forwarding/nosuchmethod_forwarding_test/05: RuntimeError # Issue 31426
+nosuchmethod_forwarding/nosuchmethod_forwarding_test/06: RuntimeError # Issue 31426
null_no_such_method_test: CompileTimeError # Issue 31533
null_test/mirrors: Skip # Uses mirrors.
null_test/none: SkipByDesign
diff --git a/tests/language_2/language_2_precompiled.status b/tests/language_2/language_2_precompiled.status
index b5d8b63..c69bb03 100644
--- a/tests/language_2/language_2_precompiled.status
+++ b/tests/language_2/language_2_precompiled.status
@@ -87,7 +87,6 @@
bool_check_test: RuntimeError
bool_condition_check_test: RuntimeError
bug31436_test: RuntimeError
-bug32353_test: RuntimeError
bug32372_test: RuntimeError
built_in_identifier_prefix_test: CompileTimeError
call_constructor_on_unresolvable_class_test/01: MissingCompileTimeError
@@ -517,6 +516,7 @@
issue31596_super_test/04: MissingCompileTimeError
issue31596_super_test/05: RuntimeError
issue31596_tearoff_test: RuntimeError
+issue32353_test: RuntimeError
language_2/least_upper_bound_expansive_test/none: CompileTimeError
least_upper_bound_expansive_test/none: CompileTimeError
least_upper_bound_test/03: MissingCompileTimeError
diff --git a/tests/language_2/language_2_vm.status b/tests/language_2/language_2_vm.status
index dcd6d4d..a6dedf1 100644
--- a/tests/language_2/language_2_vm.status
+++ b/tests/language_2/language_2_vm.status
@@ -174,7 +174,6 @@
bad_override_test/02: MissingCompileTimeError
bad_override_test/06: MissingCompileTimeError
bug31436_test: RuntimeError
-bug32353_test: RuntimeError
bug32372_test: RuntimeError
built_in_identifier_prefix_test: CompileTimeError
call_constructor_on_unresolvable_class_test/01: MissingCompileTimeError
@@ -548,6 +547,8 @@
issue31596_super_test/04: MissingCompileTimeError
issue31596_super_test/05: RuntimeError
issue31596_tearoff_test: RuntimeError
+issue32353_2_test: MissingCompileTimeError # Issue 32353
+issue32353_test: RuntimeError
least_upper_bound_expansive_test/none: CompileTimeError
least_upper_bound_test/03: MissingCompileTimeError
least_upper_bound_test/04: MissingCompileTimeError
diff --git a/tests/language_2/no_such_method_mock_test.dart b/tests/language_2/no_such_method_mock_test.dart
index 50c5760..8f146b7 100644
--- a/tests/language_2/no_such_method_mock_test.dart
+++ b/tests/language_2/no_such_method_mock_test.dart
@@ -97,9 +97,64 @@
Expect.isTrue(s.invocation.isSetter);
Expect.isFalse(s.invocation.isMethod);
+ testMockTearoffs();
+ testMockCallable();
+
+ // TODO(jmesserly): enable these tests once we have implicit call tearoff.
+ // testMockCallableTearoff();
+}
+
+testMockCallable() {
Callable call = new MockCallable();
Expect.equals(42, call());
Expect.equals(42, (call as dynamic)());
Expect.equals(0, call.m());
Expect.equals(0, (call as dynamic).m());
}
+
+testMockCallableTearoff() {
+ var mock = new MockCallable();
+ Function f = mock;
+ Expect.equals(42, f());
+ Expect.equals(42, (f as dynamic)());
+ Expect.equals(f, mock.call);
+ Expect.equals(f.call, mock.call);
+ Expect.equals((f as dynamic).call, mock.call);
+ Expect.equals(f.call, (mock as dynamic).call);
+}
+
+typedef bool EatFoodType(String food);
+
+testMockTearoffs() {
+ var mock2 = new MockCat2();
+ var eat = mock2.eatFood;
+ var eat2 = (mock2 as dynamic).eatFood;
+
+ Expect.isTrue(eat is EatFoodType, 'eat is EatFoodType');
+ Expect.isTrue(eat2 is EatFoodType, 'eat2 is EatFoodType');
+ Expect.equals(eat, eat2, 'eat == eat2');
+ Expect.isTrue(eat.runtimeType == eat2.runtimeType,
+ 'eat.runtimeType == eat2.runtimeType');
+
+ Expect.isTrue(eat("cat food"), 'eat("cat food")');
+ Expect.isFalse(eat(""), 'eat("")');
+ Expect.isTrue(eat2("cat food"), 'eat2("cat food")');
+ Expect.isFalse(eat2(""), 'eat2("")');
+
+ var g = new MockWithGenerics();
+ var doStuff = g.doStuff;
+ var doStuff2 = (g as dynamic).doStuff;
+
+ Expect.equals(doStuff, doStuff2, 'doStuff == doStuff2');
+ Expect.equals(doStuff.runtimeType, doStuff2.runtimeType,
+ 'doStuff.runtimeType == doStuff2.runtimeType');
+
+ Expect.listEquals([int], doStuff(42));
+ Expect.listEquals([num], doStuff<num>(42));
+ Expect.listEquals([String], doStuff('hi'));
+
+ // no inference happens because `doStuff2` is dynamic.
+ Expect.listEquals([dynamic], doStuff2(42));
+ Expect.listEquals([num], doStuff2<num>(42));
+ Expect.listEquals([dynamic], doStuff2('hi'));
+}
diff --git a/tests/language_2/vm/regress_32502_test.dart b/tests/language_2/vm/regress_32502_test.dart
new file mode 100644
index 0000000..6bdf285
--- /dev/null
+++ b/tests/language_2/vm/regress_32502_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify that VM does not omit type checks from closure prologues.
+
+import "package:expect/expect.dart";
+
+void invoke(dynamic f, dynamic arg) {
+ f(arg);
+}
+
+void main() {
+ dynamic x = 42;
+
+ foo(int v) {
+ x = v;
+ }
+
+ bar<T>() {
+ return (T v) {
+ x = v;
+ };
+ }
+
+ Expect.throwsTypeError(() => invoke(foo, "hello"));
+ Expect.throwsTypeError(() => invoke(bar<int>(), "hello"));
+ Expect.equals(42, x);
+}
diff --git a/tests/lib_2/convert/base64_test.dart b/tests/lib_2/convert/base64_test.dart
index d00bd89..40f7c7c 100644
--- a/tests/lib_2/convert/base64_test.dart
+++ b/tests/lib_2/convert/base64_test.dart
@@ -107,6 +107,10 @@
}
}
}
+ // Using .encode
+ Expect.equals(uriEncoded, base64Url.encode(list), ".encode($list)");
+ // Using base64UrlEncode
+ Expect.equals(uriEncoded, base64UrlEncode(list), ".encode($list)");
for (var encoded in [encodedNormal, encodedPercent, uriEncoded]) {
increment = encoded.length ~/ 7 + 1;
@@ -141,6 +145,9 @@
}
}
}
+ Expect.listEquals(list, base64.decode(encoded), ".decode($encoded)");
+ Expect.listEquals(list, base64Url.decode(encoded), "url.decode($encoded)");
+ Expect.listEquals(list, base64Decode(encoded), "base64Decode($encoded)");
}
}
diff --git a/tests/lib_2/convert/json_test.dart b/tests/lib_2/convert/json_test.dart
index cc5988f..edd89e9 100644
--- a/tests/lib_2/convert/json_test.dart
+++ b/tests/lib_2/convert/json_test.dart
@@ -35,7 +35,7 @@
}
for (var reviver in [null, (k, v) => v]) {
- for (var split in [0, 1, 2, 3]) {
+ for (var split in [0, 1, 2, 3, 4, 5]) {
var name = (reviver == null) ? "" : "reviver:";
var sink = new ChunkedConversionSink.withCallback((values) {
var value = values[0];
@@ -72,6 +72,14 @@
decoderSink.add(jsonText.substring(2 * third));
decoderSink.close();
break;
+ case 4:
+ // Use .decode
+ sink.add([json.decode(jsonText)]);
+ break;
+ case 5:
+ // Use jsonDecode
+ sink.add([jsonDecode(jsonText)]);
+ break;
}
}
}
@@ -98,6 +106,8 @@
void testThrows(jsonText) {
Expect.throwsFormatException(() => json.decode(jsonText),
"json = '${escape(jsonText)}'");
+ Expect.throwsFormatException(() => jsonDecode(jsonText),
+ "json = '${escape(jsonText)}'");
}
testNumbers() {
@@ -187,6 +197,9 @@
Expect.throws(() => json.encode(double.nan));
Expect.throws(() => json.encode(double.infinity));
Expect.throws(() => json.encode(double.negativeInfinity));
+ Expect.throws(() => jsonEncode(double.nan));
+ Expect.throws(() => jsonEncode(double.infinity));
+ Expect.throws(() => jsonEncode(double.negativeInfinity));
}
testStrings() {
diff --git a/tools/VERSION b/tools/VERSION
index fd31ce7..f28bcf5 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 0
PATCH 0
-PRERELEASE 35
+PRERELEASE 36
PRERELEASE_PATCH 0
diff --git a/tools/bots/try_benchmarks.sh b/tools/bots/try_benchmarks.sh
index 8816f73..a2be3ca 100755
--- a/tools/bots/try_benchmarks.sh
+++ b/tools/bots/try_benchmarks.sh
@@ -246,6 +246,7 @@
out/ReleaseX64/dart-sdk \
out/ReleaseSIMDBC64/dart \
out/ReleaseX64/gen/kernel-service.dart.snapshot \
+ out/ReleaseX64/gen/runtime/bin/precompiler_entry_points.json \
out/ReleaseX64/dart \
out/ReleaseX64/dart_bootstrap \
out/ReleaseX64/run_vm_tests \
@@ -366,6 +367,7 @@
out/ReleaseX64/dart-sdk \
out/ReleaseSIMDBC64/dart \
out/ReleaseX64/gen/kernel-service.dart.snapshot \
+ out/ReleaseX64/gen/runtime/bin/precompiler_entry_points.json \
out/ReleaseX64/dart \
out/ReleaseX64/dart_bootstrap \
out/ReleaseX64/run_vm_tests \
@@ -393,7 +395,6 @@
EOF
out/ReleaseX64/dart --profile-period=10000 --packages=.packages hello.dart
out/ReleaseX64/dart --profile-period=10000 --packages=.packages --checked hello.dart
- out/ReleaseX64/dart --profile-period=10000 --packages=.packages --dfe=out/ReleaseX64/gen/kernel-service.dart.snapshot hello.dart
out/ReleaseX64/dart_bootstrap --packages=.packages --use-blobs --snapshot-kind=app-aot --snapshot=blob.bin hello.dart
out/ReleaseX64/dart_precompiled_runtime --profile-period=10000 blob.bin
DART_CONFIGURATION=ReleaseX64 pkg/vm/tool/dart2 --profile-period=10000 --packages=.packages hello.dart
diff --git a/tools/testing/dart/compiler_configuration.dart b/tools/testing/dart/compiler_configuration.dart
index d362670..79ea762 100644
--- a/tools/testing/dart/compiler_configuration.dart
+++ b/tools/testing/dart/compiler_configuration.dart
@@ -1059,9 +1059,8 @@
Command computeCompileToKernelCommand(String tempDir, List<String> arguments,
Map<String, String> environmentOverrides) {
- final genKernel = Platform.script
- .resolve('../../../pkg/vm/tool/gen_kernel${executableScriptSuffix}')
- .toFilePath();
+ final pkgVmDir = Platform.script.resolve('../../../pkg/vm').toFilePath();
+ final genKernel = '${pkgVmDir}/tool/gen_kernel${executableScriptSuffix}';
final kernelBinariesFolder = _useSdk
? '${_configuration.buildDirectory}/dart-sdk/lib/_internal'
@@ -1082,6 +1081,18 @@
'-o',
dillFile,
];
+
+ if (_isAot) {
+ args.addAll([
+ '--entry-points',
+ '${_configuration.buildDirectory}/gen/runtime/bin/precompiler_entry_points.json',
+ '--entry-points',
+ '${pkgVmDir}/lib/transformations/type_flow/entry_points_extra.json',
+ '--entry-points',
+ '${pkgVmDir}/lib/transformations/type_flow/entry_points_extra_standalone.json',
+ ]);
+ }
+
args.add(arguments.where((name) => name.endsWith('.dart')).single);
// Pass environment variable to the gen_kernel script as