Version 2.14.0-182.0.dev
Merge commit 'e1f37f602954681b64ffcd37900f44ef857afd0b' into 'dev'
diff --git a/benchmarks/SDKArtifactSizes/dart/SDKArtifactSizes.dart b/benchmarks/SDKArtifactSizes/dart/SDKArtifactSizes.dart
index d914254..1130ac6 100644
--- a/benchmarks/SDKArtifactSizes/dart/SDKArtifactSizes.dart
+++ b/benchmarks/SDKArtifactSizes/dart/SDKArtifactSizes.dart
@@ -35,7 +35,7 @@
Future<void> reportArtifactSize(String path, String name) async {
final size = await File(path).length();
- print('SDKArtifactSize.$name(CodeSize): $size');
+ print('SDKArtifactSizes.$name(CodeSize): $size');
}
Future<void> main() async {
diff --git a/benchmarks/SDKArtifactSizes/dart2/SDKArtifactSizes.dart b/benchmarks/SDKArtifactSizes/dart2/SDKArtifactSizes.dart
index d914254..1130ac6 100644
--- a/benchmarks/SDKArtifactSizes/dart2/SDKArtifactSizes.dart
+++ b/benchmarks/SDKArtifactSizes/dart2/SDKArtifactSizes.dart
@@ -35,7 +35,7 @@
Future<void> reportArtifactSize(String path, String name) async {
final size = await File(path).length();
- print('SDKArtifactSize.$name(CodeSize): $size');
+ print('SDKArtifactSizes.$name(CodeSize): $size');
}
Future<void> main() async {
diff --git a/pkg/analysis_server/lib/src/cider/rename.dart b/pkg/analysis_server/lib/src/cider/rename.dart
index 72e884b..6ea1b32 100644
--- a/pkg/analysis_server/lib/src/cider/rename.dart
+++ b/pkg/analysis_server/lib/src/cider/rename.dart
@@ -4,10 +4,19 @@
import 'package:analysis_server/src/services/refactoring/refactoring.dart';
import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dart/micro/resolve_file.dart';
import 'package:analyzer/src/dart/micro/utils.dart';
+class CanRenameResponse {
+ final LineInfo lineInfo;
+ final RenameRefactoringElement refactoringElement;
+ final String oldName;
+
+ CanRenameResponse(this.lineInfo, this.refactoringElement, this.oldName);
+}
+
class CiderRenameComputer {
final FileResolver _fileResolver;
@@ -15,7 +24,7 @@
/// Check if the identifier at the [line], [column] for the file at the
/// [filePath] can be renamed.
- RenameRefactoringElement? canRename(String filePath, int line, int column) {
+ CanRenameResponse? canRename(String filePath, int line, int column) {
var resolvedUnit = _fileResolver.resolve(path: filePath);
var lineInfo = resolvedUnit.lineInfo;
var offset = lineInfo.getOffsetOfLine(line) + column;
@@ -35,7 +44,11 @@
if (!_canRenameElement(element)) {
return null;
}
- return RenameRefactoring.getElementToRename(node, element);
+ var refactoring = RenameRefactoring.getElementToRename(node, element);
+ if (refactoring != null) {
+ return CanRenameResponse(lineInfo, refactoring, element.displayName);
+ }
+ return null;
}
bool _canRenameElement(Element element) {
diff --git a/pkg/analysis_server/test/src/cider/rename_test.dart b/pkg/analysis_server/test/src/cider/rename_test.dart
index 290379f..31c96d5 100644
--- a/pkg/analysis_server/test/src/cider/rename_test.dart
+++ b/pkg/analysis_server/test/src/cider/rename_test.dart
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/src/cider/rename.dart';
-import 'package:analysis_server/src/services/refactoring/refactoring.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -31,8 +30,8 @@
''');
expect(refactor, isNotNull);
- expect(refactor!.element.name, 'bar');
- expect(refactor.offset, _correctionContext.offset);
+ expect(refactor!.refactoringElement.element.name, 'bar');
+ expect(refactor.refactoringElement.offset, _correctionContext.offset);
}
void test_canRename_function() {
@@ -42,8 +41,8 @@
''');
expect(refactor, isNotNull);
- expect(refactor!.element.name, 'foo');
- expect(refactor.offset, _correctionContext.offset);
+ expect(refactor!.refactoringElement.element.name, 'foo');
+ expect(refactor.refactoringElement.offset, _correctionContext.offset);
}
void test_canRename_label() {
@@ -58,8 +57,8 @@
''');
expect(refactor, isNotNull);
- expect(refactor!.element.name, 'myLabel');
- expect(refactor.offset, _correctionContext.offset);
+ expect(refactor!.refactoringElement.element.name, 'myLabel');
+ expect(refactor.refactoringElement.offset, _correctionContext.offset);
}
void test_canRename_local() {
@@ -70,8 +69,8 @@
''');
expect(refactor, isNotNull);
- expect(refactor!.element.name, 'a');
- expect(refactor.offset, _correctionContext.offset);
+ expect(refactor!.refactoringElement.element.name, 'a');
+ expect(refactor.refactoringElement.offset, _correctionContext.offset);
}
void test_canRename_method() {
@@ -82,8 +81,8 @@
''');
expect(refactor, isNotNull);
- expect(refactor!.element.name, 'foo');
- expect(refactor.offset, _correctionContext.offset);
+ expect(refactor!.refactoringElement.element.name, 'foo');
+ expect(refactor.refactoringElement.offset, _correctionContext.offset);
}
void test_canRename_operator() {
@@ -104,11 +103,11 @@
''');
expect(refactor, isNotNull);
- expect(refactor!.element.name, 'bar');
- expect(refactor.offset, _correctionContext.offset);
+ expect(refactor!.refactoringElement.element.name, 'bar');
+ expect(refactor.refactoringElement.offset, _correctionContext.offset);
}
- RenameRefactoringElement? _compute(String content) {
+ CanRenameResponse? _compute(String content) {
_updateFile(content);
return CiderRenameComputer(
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index d8536a9..68ce3c5 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -822,11 +822,12 @@
DartObjectImpl obj,
DartType type,
) {
- if (obj.isNull) {
- return true;
+ var typeSystem = library.typeSystem;
+ if (!typeSystem.isNonNullableByDefault) {
+ type = typeSystem.toLegacyType(type);
}
var objType = obj.type;
- return library.typeSystem.isSubtypeOf(objType, type);
+ return typeSystem.isSubtypeOf(objType, type);
}
DartObjectImpl _nullObject(LibraryElementImpl library) {
diff --git a/pkg/analyzer/test/generated/constant_test.dart b/pkg/analyzer/test/generated/constant_test.dart
index 5b8847d..f4a4079 100644
--- a/pkg/analyzer/test/generated/constant_test.dart
+++ b/pkg/analyzer/test/generated/constant_test.dart
@@ -50,7 +50,7 @@
"const Center(name: 'v')",
context: '''
class Align {
- final double widthFactor;
+ final double? widthFactor;
const Align({String name, this.widthFactor})
assert(widthFactor == null || widthFactor >= 0.0);
}
diff --git a/pkg/analyzer/test/src/diagnostics/const_constructor_field_type_mismatch_test.dart b/pkg/analyzer/test/src/diagnostics/const_constructor_field_type_mismatch_test.dart
index 1a3846a..6f8fad0 100644
--- a/pkg/analyzer/test/src/diagnostics/const_constructor_field_type_mismatch_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/const_constructor_field_type_mismatch_test.dart
@@ -15,7 +15,7 @@
@reflectiveTest
class ConstConstructorFieldTypeMismatchTest extends PubPackageResolutionTest {
- test_assignable_generic() async {
+ test_generic_int_int() async {
await assertErrorsInCode(
r'''
class C<T> {
@@ -31,41 +31,7 @@
);
}
- test_assignable_nullValue() async {
- await assertNoErrorsInCode(r'''
-class A {
- const A(x) : y = x;
- final int y;
-}
-var v = const A(null);
-''');
- }
-
- test_assignable_unresolvedFieldAndNullValue() async {
- await assertErrorsInCode(r'''
-class A {
- const A(x) : y = x;
- final Unresolved y;
-}
-var v = const A(null);
-''', [
- error(CompileTimeErrorCode.UNDEFINED_CLASS, 40, 10),
- ]);
- }
-
- test_notAssignable() async {
- await assertErrorsInCode(r'''
-class A {
- const A(x) : y = x;
- final int y;
-}
-var v = const A('foo');
-''', [
- error(CompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH, 57, 14),
- ]);
- }
-
- test_notAssignable_generic() async {
+ test_generic_string_int() async {
await assertErrorsInCode(
r'''
class C<T> {
@@ -83,13 +49,77 @@
);
}
- test_notAssignable_unresolved() async {
+ test_notGeneric_int_int() async {
+ await assertErrorsInCode(r'''
+class A {
+ const A(x) : y = x;
+ final int y;
+}
+var v = const A('foo');
+''', [
+ error(CompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH, 57, 14),
+ ]);
+ }
+
+ test_notGeneric_int_null() async {
+ var errors = expectedErrorsByNullability(nullable: [
+ error(CompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH, 57, 13),
+ ], legacy: []);
+ await assertErrorsInCode(r'''
+class A {
+ const A(x) : y = x;
+ final int y;
+}
+var v = const A(null);
+''', errors);
+ }
+
+ test_notGeneric_null_forNonNullable_fromLegacy() async {
+ newFile('$testPackageLibPath/a.dart', content: r'''
+class C {
+ final int f;
+ const C(a) : f = a;
+}
+''');
+ await assertNoErrorsInCode('''
+// @dart = 2.9
+import 'a.dart';
+const a = const C(null);
+''');
+ }
+
+ test_notGeneric_null_forNonNullable_fromNullSafe() async {
+ await assertErrorsInCode('''
+class C {
+ final int f;
+ const C(a) : f = a;
+}
+
+const a = const C(null);
+''', [
+ error(CompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH, 60, 13),
+ ]);
+ }
+
+ test_notGeneric_unresolved_int() async {
await assertErrorsInCode(r'''
class A {
const A(x) : y = x;
final Unresolved y;
}
-var v = const A('foo');
+var v = const A(0);
+''', [
+ error(CompileTimeErrorCode.UNDEFINED_CLASS, 40, 10),
+ ]);
+ }
+
+ test_notGeneric_unresolved_null() async {
+ await assertErrorsInCode(r'''
+class A {
+ const A(x) : y = x;
+ final Unresolved y;
+}
+var v = const A(null);
''', [
error(CompileTimeErrorCode.UNDEFINED_CLASS, 40, 10),
]);
diff --git a/pkg/analyzer/test/src/diagnostics/list_element_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/list_element_type_not_assignable_test.dart
index f15fcae..76204ef 100644
--- a/pkg/analyzer/test/src/diagnostics/list_element_type_not_assignable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/list_element_type_not_assignable_test.dart
@@ -11,12 +11,19 @@
defineReflectiveSuite(() {
defineReflectiveTests(ListElementTypeNotAssignableTest);
defineReflectiveTests(ListElementTypeNotAssignableWithNoImplicitCastsTest);
+ defineReflectiveTests(ListElementTypeNotAssignableWithoutNullSafetyTest);
});
}
@reflectiveTest
class ListElementTypeNotAssignableTest extends PubPackageResolutionTest
- with ListElementTypeNotAssignableTestCases {}
+ with ListElementTypeNotAssignableTestCases {
+ test_const_stringQuestion_null_value() async {
+ await assertNoErrorsInCode('''
+var v = const <String?>[null];
+''');
+ }
+}
mixin ListElementTypeNotAssignableTestCases on PubPackageResolutionTest {
test_const_ifElement_thenElseFalse_intInt() async {
@@ -68,6 +75,32 @@
]);
}
+ test_const_intInt() async {
+ await assertNoErrorsInCode(r'''
+var v1 = <int> [42];
+var v2 = const <int> [42];
+''');
+ }
+
+ test_const_intNull_dynamic() async {
+ var errors = expectedErrorsByNullability(nullable: [
+ error(CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, 36, 1),
+ ], legacy: []);
+ await assertErrorsInCode('''
+const a = null;
+var v = const <int>[a];
+''', errors);
+ }
+
+ test_const_intNull_value() async {
+ var errors = expectedErrorsByNullability(nullable: [
+ error(CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, 20, 4),
+ ], legacy: []);
+ await assertErrorsInCode('''
+var v = const <int>[null];
+''', errors);
+ }
+
test_const_spread_intInt() async {
await assertNoErrorsInCode('''
var v = const <int>[...[0, 1]];
@@ -91,32 +124,12 @@
]);
}
- test_const_stringNull() async {
- await assertNoErrorsInCode('''
-var v = const <String?>[null];
-''');
- }
-
- test_const_stringNull_dynamic() async {
- await assertNoErrorsInCode('''
-const dynamic x = null;
-var v = const <String>[x];
-''');
- }
-
test_const_voidInt() async {
await assertNoErrorsInCode('''
var v = const <void>[42];
''');
}
- test_element_type_is_assignable() async {
- await assertNoErrorsInCode(r'''
-var v1 = <int> [42];
-var v2 = const <int> [42];
-''');
- }
-
test_nonConst_ifElement_thenElseFalse_intDynamic() async {
await assertNoErrorsInCode('''
const dynamic a = 'a';
@@ -237,3 +250,8 @@
]);
}
}
+
+@reflectiveTest
+class ListElementTypeNotAssignableWithoutNullSafetyTest
+ extends PubPackageResolutionTest
+ with WithoutNullSafetyMixin, ListElementTypeNotAssignableTestCases {}
diff --git a/pkg/analyzer/test/src/diagnostics/map_key_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/map_key_type_not_assignable_test.dart
index c1b9c6d..1216de7 100644
--- a/pkg/analyzer/test/src/diagnostics/map_key_type_not_assignable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/map_key_type_not_assignable_test.dart
@@ -17,7 +17,20 @@
@reflectiveTest
class MapKeyTypeNotAssignableTest extends PubPackageResolutionTest
- with MapKeyTypeNotAssignableTestCases {}
+ with MapKeyTypeNotAssignableTestCases {
+ test_const_intQuestion_null_dynamic() async {
+ await assertNoErrorsInCode('''
+const dynamic a = null;
+var v = const <int?, bool>{a : true};
+''');
+ }
+
+ test_const_intQuestion_null_value() async {
+ await assertNoErrorsInCode('''
+var v = const <int?, bool>{null : true};
+''');
+ }
+}
mixin MapKeyTypeNotAssignableTestCases on PubPackageResolutionTest {
test_const_ifElement_thenElseFalse_intInt_dynamic() async {
@@ -85,6 +98,25 @@
''');
}
+ test_const_intNull_dynamic() async {
+ var errors = expectedErrorsByNullability(nullable: [
+ error(CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 50, 1),
+ ], legacy: []);
+ await assertErrorsInCode('''
+const dynamic a = null;
+var v = const <int, bool>{a : true};
+''', errors);
+ }
+
+ test_const_intNull_value() async {
+ var errors = expectedErrorsByNullability(nullable: [
+ error(CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 26, 4),
+ ], legacy: []);
+ await assertErrorsInCode('''
+var v = const <int, bool>{null : true};
+''', errors);
+ }
+
test_const_intString_dynamic() async {
await assertErrorsInCode('''
const dynamic a = 'a';
diff --git a/pkg/analyzer/test/src/diagnostics/map_value_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/map_value_type_not_assignable_test.dart
index cbcfd6c..212b70b 100644
--- a/pkg/analyzer/test/src/diagnostics/map_value_type_not_assignable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/map_value_type_not_assignable_test.dart
@@ -17,7 +17,20 @@
@reflectiveTest
class MapValueTypeNotAssignableTest extends PubPackageResolutionTest
- with MapValueTypeNotAssignableTestCases {}
+ with MapValueTypeNotAssignableTestCases {
+ test_const_intQuestion_null_dynamic() async {
+ await assertNoErrorsInCode('''
+const dynamic a = null;
+var v = const <bool, int?>{true: a};
+''');
+ }
+
+ test_const_intQuestion_null_value() async {
+ await assertNoErrorsInCode('''
+var v = const <bool, int?>{true: null};
+''');
+ }
+}
mixin MapValueTypeNotAssignableTestCases on PubPackageResolutionTest {
test_const_ifElement_thenElseFalse_intInt_dynamic() async {
@@ -85,6 +98,25 @@
''');
}
+ test_const_intNull_dynamic() async {
+ var errors = expectedErrorsByNullability(nullable: [
+ error(CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 56, 1),
+ ], legacy: []);
+ await assertErrorsInCode('''
+const dynamic a = null;
+var v = const <bool, int>{true: a};
+''', errors);
+ }
+
+ test_const_intNull_value() async {
+ var errors = expectedErrorsByNullability(nullable: [
+ error(CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 32, 4),
+ ], legacy: []);
+ await assertErrorsInCode('''
+var v = const <bool, int>{true: null};
+''', errors);
+ }
+
test_const_intString_dynamic() async {
await assertErrorsInCode('''
const dynamic a = 'a';
diff --git a/pkg/analyzer/test/src/diagnostics/not_enough_positional_arguments_test.dart b/pkg/analyzer/test/src/diagnostics/not_enough_positional_arguments_test.dart
index b08bd58..c3ca2c0 100644
--- a/pkg/analyzer/test/src/diagnostics/not_enough_positional_arguments_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/not_enough_positional_arguments_test.dart
@@ -24,6 +24,7 @@
const A();
}
''', [
+ error(CompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH, 41, 9),
error(CompileTimeErrorCode.NOT_ENOUGH_POSITIONAL_ARGUMENTS, 48, 2),
]);
}
diff --git a/pkg/analyzer/test/src/diagnostics/set_element_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/set_element_type_not_assignable_test.dart
index 88efa36..a74f2cc 100644
--- a/pkg/analyzer/test/src/diagnostics/set_element_type_not_assignable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/set_element_type_not_assignable_test.dart
@@ -11,12 +11,26 @@
defineReflectiveSuite(() {
defineReflectiveTests(SetElementTypeNotAssignableTest);
defineReflectiveTests(SetElementTypeNotAssignableWithNoImplicitCastsTest);
+ defineReflectiveTests(SetElementTypeNotAssignableWithoutNullSafetyTest);
});
}
@reflectiveTest
class SetElementTypeNotAssignableTest extends PubPackageResolutionTest
- with SetElementTypeNotAssignableTestCases {}
+ with SetElementTypeNotAssignableTestCases {
+ test_const_stringQuestion_null_dynamic() async {
+ await assertNoErrorsInCode('''
+const a = null;
+var v = const <String?>{a};
+''');
+ }
+
+ test_const_stringQuestion_null_value() async {
+ await assertNoErrorsInCode('''
+var v = const <String?>{null};
+''');
+ }
+}
mixin SetElementTypeNotAssignableTestCases on PubPackageResolutionTest {
test_const_ifElement_thenElseFalse_intInt() async {
@@ -68,44 +82,61 @@
]);
}
- test_const_spread_intInt() async {
+ test_const_intInt_dynamic() async {
await assertNoErrorsInCode('''
-var v = const <int>{...[0, 1]};
+const dynamic a = 42;
+var v = const <int>{a};
''');
}
- test_explicitTypeArgs_const() async {
- await assertErrorsInCode('''
-var v = const <String>{42};
-''', [
- error(CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, 23, 2),
- ]);
- }
-
- test_explicitTypeArgs_const_actualTypeMatch() async {
+ test_const_intInt_value() async {
await assertNoErrorsInCode('''
-const dynamic x = null;
-var v = const <String>{x};
+var v = const <int>{42};
''');
}
- test_explicitTypeArgs_const_actualTypeMismatch() async {
+ test_const_intNull_dynamic() async {
+ var errors = expectedErrorsByNullability(nullable: [
+ error(CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, 36, 1),
+ ], legacy: []);
await assertErrorsInCode('''
-const dynamic x = 42;
-var v = const <String>{x};
+const a = null;
+var v = const <int>{a};
+''', errors);
+ }
+
+ test_const_intNull_value() async {
+ var errors = expectedErrorsByNullability(nullable: [
+ error(CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, 20, 4),
+ ], legacy: []);
+ await assertErrorsInCode('''
+var v = const <int>{null};
+''', errors);
+ }
+
+ test_const_intString_dynamic() async {
+ await assertErrorsInCode('''
+const dynamic x = 'abc';
+var v = const <int>{x};
''', [
error(CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, 45, 1),
]);
}
- test_explicitTypeArgs_notConst() async {
+ test_const_intString_value() async {
await assertErrorsInCode('''
-var v = <String>{42};
+var v = const <int>{'abc'};
''', [
- error(CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, 17, 2),
+ error(CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, 20, 5),
]);
}
+ test_const_spread_intInt() async {
+ await assertNoErrorsInCode('''
+var v = const <int>{...[0, 1]};
+''');
+ }
+
test_nonConst_ifElement_thenElseFalse_intDynamic() async {
await assertNoErrorsInCode('''
const dynamic a = 'a';
@@ -149,6 +180,21 @@
var v = <int>{...[0, 1]};
''');
}
+
+ test_notConst_intString_dynamic() async {
+ await assertNoErrorsInCode('''
+const dynamic x = 'abc';
+var v = <int>{x};
+''');
+ }
+
+ test_notConst_intString_value() async {
+ await assertErrorsInCode('''
+var v = <int>{'abc'};
+''', [
+ error(CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, 14, 5),
+ ]);
+ }
}
@reflectiveTest
@@ -205,3 +251,8 @@
]);
}
}
+
+@reflectiveTest
+class SetElementTypeNotAssignableWithoutNullSafetyTest
+ extends PubPackageResolutionTest
+ with WithoutNullSafetyMixin, SetElementTypeNotAssignableTestCases {}
diff --git a/pkg/compiler/lib/src/js_backend/deferred_holder_expression.dart b/pkg/compiler/lib/src/js_backend/deferred_holder_expression.dart
index 572d468..5398071 100644
--- a/pkg/compiler/lib/src/js_backend/deferred_holder_expression.dart
+++ b/pkg/compiler/lib/src/js_backend/deferred_holder_expression.dart
@@ -9,7 +9,6 @@
import '../js/js.dart' as js;
import '../serialization/serialization.dart';
import '../util/util.dart';
-import '../js_emitter/model.dart' show Fragment;
import 'namer.dart';
@@ -18,7 +17,7 @@
// for the entity referenced in the DeferredHolderExpression.
enum DeferredHolderExpressionKind {
globalObjectForStaticState,
- globalObjectForConstant,
+ globalObjectForConstants,
globalObjectForLibrary,
globalObjectForClass,
globalObjectForMember,
@@ -35,15 +34,19 @@
static const String tag = 'deferred-holder-expression';
final DeferredHolderExpressionKind kind;
- final Object data;
+ final Entity entity;
js.Expression _value;
@override
final js.JavaScriptNodeSourceInformation sourceInformation;
- DeferredHolderExpression(this.kind, this.data) : sourceInformation = null;
+ DeferredHolderExpression(this.kind, this.entity) : sourceInformation = null;
DeferredHolderExpression._(
- this.kind, this.data, this._value, this.sourceInformation);
+ this.kind, this.entity, this._value, this.sourceInformation);
+ factory DeferredHolderExpression.forConstants() {
+ return DeferredHolderExpression(
+ DeferredHolderExpressionKind.globalObjectForConstants, null);
+ }
factory DeferredHolderExpression.forStaticState() {
return DeferredHolderExpression(
@@ -53,26 +56,24 @@
factory DeferredHolderExpression.readFromDataSource(DataSource source) {
source.begin(tag);
var kind = source.readEnum(DeferredHolderExpressionKind.values);
- Object data;
+ Entity entity;
switch (kind) {
case DeferredHolderExpressionKind.globalObjectForLibrary:
- data = source.readLibrary();
+ entity = source.readLibrary();
break;
case DeferredHolderExpressionKind.globalObjectForClass:
- data = source.readClass();
+ entity = source.readClass();
break;
case DeferredHolderExpressionKind.globalObjectForMember:
- data = source.readMember();
- break;
- case DeferredHolderExpressionKind.globalObjectForConstant:
- data = source.readConstant();
+ entity = source.readMember();
break;
case DeferredHolderExpressionKind.globalObjectForStaticState:
+ case DeferredHolderExpressionKind.globalObjectForConstants:
// no entity.
break;
}
source.end(tag);
- return DeferredHolderExpression(kind, data);
+ return DeferredHolderExpression(kind, entity);
}
void writeToDataSink(DataSink sink) {
@@ -80,18 +81,16 @@
sink.writeEnum(kind);
switch (kind) {
case DeferredHolderExpressionKind.globalObjectForLibrary:
- sink.writeLibrary(data);
+ sink.writeLibrary(entity);
break;
case DeferredHolderExpressionKind.globalObjectForClass:
- sink.writeClass(data);
+ sink.writeClass(entity);
break;
case DeferredHolderExpressionKind.globalObjectForMember:
- sink.writeMember(data);
- break;
- case DeferredHolderExpressionKind.globalObjectForConstant:
- sink.writeConstant(data);
+ sink.writeMember(entity);
break;
case DeferredHolderExpressionKind.globalObjectForStaticState:
+ case DeferredHolderExpressionKind.globalObjectForConstants:
// no entity.
break;
}
@@ -117,7 +116,8 @@
js.JavaScriptNodeSourceInformation newSourceInformation) {
if (newSourceInformation == sourceInformation) return this;
if (newSourceInformation == null) return this;
- return DeferredHolderExpression._(kind, data, _value, newSourceInformation);
+ return DeferredHolderExpression._(
+ kind, entity, _value, newSourceInformation);
}
@override
@@ -125,7 +125,7 @@
@override
int get hashCode {
- return Hashing.objectsHash(kind, data);
+ return Hashing.objectsHash(kind, entity);
}
@override
@@ -133,13 +133,13 @@
if (identical(this, other)) return true;
return other is DeferredHolderExpression &&
kind == other.kind &&
- data == other.data;
+ entity == other.entity;
}
@override
String toString() {
- StringBuffer sb = StringBuffer();
- sb.write('DeferredHolderExpression(kind=$kind,data=$data,');
+ StringBuffer sb = new StringBuffer();
+ sb.write('DeferredHolderExpression(kind=$kind,entity=$entity,');
sb.write('value=$_value)');
return sb.toString();
}
@@ -205,43 +205,40 @@
@override
String toString() {
- StringBuffer sb = StringBuffer();
+ StringBuffer sb = new StringBuffer();
sb.write('DeferredHolderParameter(name=$_name)');
return sb.toString();
}
}
enum DeferredHolderResourceKind {
- mainFragment,
- deferredFragment,
+ declaration,
+ update,
}
/// A [DeferredHolderResource] is a deferred JavaScript statement determined by
-/// the finalization of holders. Each fragment contains one
-/// [DeferredHolderResource]. The actual [Statement] contained with the
+/// the finalization of holders. It is the injection point for data or
+/// code to holders. The actual [Statement] contained with the
/// [DeferredHolderResource] will be determined by the
/// [DeferredHolderResourceKind]. These [Statement]s differ considerably
-/// depending on where they are used in the AST. This class is created by the
-/// fragment emitter so does not need to support serialization.
+/// depending on where they are used in the AST. This class does not support
+/// serialization.
class DeferredHolderResource extends js.DeferredStatement
implements js.AstContainer {
DeferredHolderResourceKind kind;
- // Each resource has a distinct name.
- String name;
- List<Fragment> fragments;
Map<Entity, List<js.Property>> holderCode;
+ bool initializeEmptyHolders;
js.Statement _statement;
@override
final js.JavaScriptNodeSourceInformation sourceInformation;
- DeferredHolderResource(this.kind, this.name, this.fragments, this.holderCode)
+ DeferredHolderResource(this.kind,
+ {this.holderCode: const {}, this.initializeEmptyHolders: false})
: sourceInformation = null;
- DeferredHolderResource._(this.kind, this.name, this.fragments,
- this.holderCode, this._statement, this.sourceInformation);
-
- bool get isMainFragment => kind == DeferredHolderResourceKind.mainFragment;
+ DeferredHolderResource._(this.kind, this.holderCode,
+ this.initializeEmptyHolders, this._statement, this.sourceInformation);
set statement(js.Statement statement) {
assert(!isFinalized && statement != null);
@@ -262,7 +259,7 @@
js.JavaScriptNodeSourceInformation newSourceInformation) {
if (newSourceInformation == sourceInformation) return this;
if (newSourceInformation == null) return this;
- return DeferredHolderResource._(kind, this.name, this.fragments, holderCode,
+ return DeferredHolderResource._(kind, holderCode, initializeEmptyHolders,
_statement, newSourceInformation);
}
@@ -280,87 +277,41 @@
}
}
-const String mainResourceName = 'MAIN';
-
abstract class DeferredHolderExpressionFinalizer {
/// Collects DeferredHolderExpressions from the JavaScript
- /// AST [code] and associates it with [resourceName].
- void addCode(String resourceName, js.Node code);
+ /// AST [code];
+ void addCode(js.Node code);
/// Performs analysis on all collected DeferredHolderExpression nodes
/// finalizes the values to expressions to access the holders.
void finalize();
}
-/// An abstraction representing a [Holder] object, which will contain some
-/// portion of the programs code.
-class Holder {
- final String name;
- final Map<String, int> refCountPerResource = {};
- final Map<String, List<js.Property>> propertiesPerResource = {};
- int _index;
- int _hashCode;
-
- Holder(this.name);
-
- int refCount(String resource) => refCountPerResource[resource];
-
- void registerUse(String resource) {
- refCountPerResource.update(resource, (count) => count + 1,
- ifAbsent: () => 0);
- }
-
- void registerUpdate(String resource, List<js.Property> properties) {
- (propertiesPerResource[resource] ??= []).addAll(properties);
- registerUse(resource);
- }
-
- int get index {
- assert(_index != null);
- return _index;
- }
-
- set index(int newIndex) {
- assert(_index == null);
- _index = newIndex;
- }
-
- @override
- bool operator ==(that) {
- return that is Holder && name == that.name;
- }
-
- @override
- int get hashCode {
- return _hashCode ??= Hashing.objectsHash(name);
- }
-}
-
/// [DeferredHolderExpressionFinalizerImpl] finalizes
/// [DeferredHolderExpression]s, [DeferredHolderParameter]s,
/// [DeferredHolderResource]s, [DeferredHolderResourceExpression]s.
class DeferredHolderExpressionFinalizerImpl
implements DeferredHolderExpressionFinalizer {
_DeferredHolderExpressionCollectorVisitor _visitor;
- final Map<String, List<DeferredHolderExpression>> holderReferences = {};
+ final List<DeferredHolderExpression> holderReferences = [];
final List<DeferredHolderParameter> holderParameters = [];
final List<DeferredHolderResource> holderResources = [];
- final Map<String, Set<Holder>> holdersPerResource = {};
- final Map<String, Holder> holderMap = {};
+ final Set<String> _uniqueHolders = {};
+ final List<String> _holders = [];
+ final Map<Entity, String> _entityMap = {};
final JCommonElements _commonElements;
- DeferredHolderResource mainHolderResource;
DeferredHolderExpressionFinalizerImpl(this._commonElements) {
_visitor = _DeferredHolderExpressionCollectorVisitor(this);
}
@override
- void addCode(String resourceName, js.Node code) {
- _visitor.setResourceNameAndVisit(resourceName, code);
+ void addCode(js.Node code) {
+ code.accept(_visitor);
}
final List<String> userGlobalObjects =
- List.from(Namer.reservedGlobalObjectNames)
+ new List.from(Namer.reservedGlobalObjectNames)
..remove('C')
..remove('H')
..remove('J')
@@ -368,7 +319,7 @@
..remove('W');
/// Returns the [reservedGlobalObjectNames] for [library].
- String globalObjectNameForLibrary(LibraryEntity library) {
+ String globalObjectForLibrary(LibraryEntity library) {
if (library == _commonElements.interceptorsLibrary) return 'J';
Uri uri = library.canonicalUri;
if (uri.scheme == 'dart') {
@@ -390,285 +341,236 @@
return element.isField;
}
- String globalObjectNameForMember(MemberEntity entity) {
+ String globalObjectForMember(MemberEntity entity) {
if (_isPropertyOfStaticStateHolder(entity)) {
- return globalObjectNameForStaticState();
+ return globalObjectForStaticState();
} else {
- return globalObjectNameForLibrary(entity.library);
+ return globalObjectForLibrary(entity.library);
}
}
- String globalObjectNameForClass(ClassEntity entity) {
- return globalObjectNameForLibrary(entity.library);
+ String globalObjectForClass(ClassEntity entity) {
+ return globalObjectForLibrary(entity.library);
}
- final Holder globalObjectForStaticState =
- Holder(globalObjectNameForStaticState());
+ String globalObjectForStaticState() => r'$';
- static String globalObjectNameForStaticState() => r'$';
+ String globalObjectForConstants() => 'C';
- String globalObjectNameForConstants() => 'C';
-
- String globalObjectNameForEntity(Entity entity) {
+ String globalObjectForEntity(Entity entity) {
if (entity is MemberEntity) {
- return globalObjectNameForMember(entity);
+ return globalObjectForMember(entity);
} else if (entity is ClassEntity) {
- return globalObjectNameForLibrary(entity.library);
+ return globalObjectForLibrary(entity.library);
} else {
assert(entity is LibraryEntity);
- return globalObjectNameForLibrary(entity);
+ return globalObjectForLibrary(entity);
}
}
- Holder holderNameToHolder(String holderKey) {
- if (holderKey == globalObjectNameForStaticState()) {
- return globalObjectForStaticState;
- } else {
- return holderMap[holderKey];
+ /// Registers an [Entity] with a specific [holder].
+ void registerHolderUse(String holder, Entity entity) {
+ if (_uniqueHolders.add(holder)) _holders.add(holder);
+ if (entity != null) {
+ assert(!_entityMap.containsKey(entity) || _entityMap[entity] == holder);
+ _entityMap[entity] = holder;
}
}
- Holder globalObjectForEntity(Entity entity) {
- return holderNameToHolder(globalObjectNameForEntity(entity));
- }
-
- /// Registers a [holder] use within a given [resource], if [properties] are
- /// provided then it is assumed this is an update to a holder.
- void registerHolderUseOrUpdate(String resourceName, String holderName,
- {List<js.Property> properties}) {
- // For simplicity, we don't currently track the static state holder per
- // resource.
- if (holderName == globalObjectNameForStaticState()) return;
- Holder holder = holderMap[holderName] ??= Holder(holderName);
- if (properties == null) {
- holder.registerUse(resourceName);
- } else {
- holder.registerUpdate(resourceName, properties);
- }
- (holdersPerResource[resourceName] ??= {}).add(holder);
- }
-
- /// Returns a key to a global object for a given [Object] based on the
+ /// Returns a global object for a given [Entity] based on the
/// [DeferredHolderExpressionKind].
- String kindToHolderName(DeferredHolderExpressionKind kind, Object data) {
+ String kindToHolder(DeferredHolderExpressionKind kind, Entity entity) {
switch (kind) {
case DeferredHolderExpressionKind.globalObjectForLibrary:
- return globalObjectNameForLibrary(data);
+ return globalObjectForLibrary(entity);
case DeferredHolderExpressionKind.globalObjectForClass:
- return globalObjectNameForClass(data);
+ return globalObjectForClass(entity);
case DeferredHolderExpressionKind.globalObjectForMember:
- return globalObjectNameForMember(data);
- case DeferredHolderExpressionKind.globalObjectForConstant:
- return globalObjectNameForConstants();
+ return globalObjectForMember(entity);
+ case DeferredHolderExpressionKind.globalObjectForConstants:
+ return globalObjectForConstants();
case DeferredHolderExpressionKind.globalObjectForStaticState:
- return globalObjectNameForStaticState();
+ return globalObjectForStaticState();
}
throw UnsupportedError("Unreachable");
}
- /// Returns a global object for a given [Object] based on the
- /// [DeferredHolderExpressionKind].
- Holder kindToHolder(DeferredHolderExpressionKind kind, Object data) {
- return holderNameToHolder(kindToHolderName(kind, data));
- }
-
- /// Finalizes [DeferredHolderParameter]s.
- void finalizeParameters() {
- for (var parameter in holderParameters) {
- if (parameter.isFinalized) continue;
- parameter.name = globalObjectNameForStaticState();
- }
- }
-
- /// Finalizes all of the [DeferredHolderExpression]s associated with a
- /// [DeferredHolderResource].
- void finalizeReferences(DeferredHolderResource resource) {
- if (!holderReferences.containsKey(resource.name)) return;
- for (var reference in holderReferences[resource.name]) {
+ /// Finalizes [DeferredHolderExpression]s [DeferredHolderParameter]s.
+ void finalizeReferences() {
+ // Finalize [DeferredHolderExpression]s and registers holder usage.
+ for (var reference in holderReferences) {
if (reference.isFinalized) continue;
- String holder = kindToHolder(reference.kind, reference.data).name;
+ Entity entity = reference.entity;
+ String holder = kindToHolder(reference.kind, entity);
js.Expression value = js.VariableUse(holder);
+ registerHolderUse(holder, entity);
reference.value =
value.withSourceInformation(reference.sourceInformation);
}
+
+ // Finalize [DeferredHolderParameter]s.
+ for (var parameter in holderParameters) {
+ if (parameter.isFinalized) continue;
+ parameter.name = globalObjectForStaticState();
+ }
}
- /// Registers all of the holders used in the entire program.
- void registerHolders() {
- // Register all holders used in all [DeferredHolderResource]s.
- for (var resource in holderResources) {
- resource.holderCode.forEach((entity, properties) {
- String holderName = globalObjectNameForEntity(entity);
- registerHolderUseOrUpdate(resource.name, holderName,
- properties: properties);
- });
+ /// Registers all of the holders used by a given [DeferredHolderResource].
+ void registerHolders(DeferredHolderResource resource) {
+ for (var entity in resource.holderCode.keys) {
+ var holder = globalObjectForEntity(entity);
+ registerHolderUse(holder, entity);
+ }
+ }
+
+ /// Returns a [List<String>] containing all of the holders except the static
+ /// state holder.
+ List<String> get nonStaticStateHolders {
+ return _holders
+ .where((holder) => holder != globalObjectForStaticState())
+ .toList(growable: false);
+ }
+
+ /// Generates code to declare holders.
+ HolderCode declareHolders(DeferredHolderResource resource) {
+ // Collect all holders except the static state holder. Then, create a map of
+ // holder to list of properties which are associated with that holder, but
+ // only with respect to a given [DeferredHolderResource]. Each fragment will
+ // have its own [DeferredHolderResource] and associated code.
+ Map<String, List<js.Property>> codePerHolder = {};
+ final holders = nonStaticStateHolders;
+ for (var holder in holders) {
+ codePerHolder[holder] = [];
}
- // Register all holders used in [DeferredHolderReference]s.
- holderReferences.forEach((resource, references) {
- for (var reference in references) {
- String holderName = kindToHolderName(reference.kind, reference.data);
- registerHolderUseOrUpdate(resource, holderName);
- }
+ final holderCode = resource.holderCode;
+ holderCode.forEach((entity, properties) {
+ assert(_entityMap.containsKey(entity));
+ var holder = _entityMap[entity];
+ assert(codePerHolder.containsKey(holder));
+ codePerHolder[holder].addAll(properties);
});
- }
- /// Returns an [Iterable<Holder>] containing all of the holders used within a
- /// given [DeferredHolderResource]except the static state holder (if any).
- Iterable<Holder> nonStaticStateHolders(DeferredHolderResource resource) {
- return holdersPerResource[resource.name] ?? [];
- }
-
- /// Returns an [Iterable<Holder>] containing all of the holders used within a
- /// given [DeferredHolderResource] except the static state holder.
- Iterable<Holder> get allNonStaticStateHolders {
- return holderMap.values;
- }
-
- /// Generates code to declare holders for a given [resourceName].
- HolderInitCode declareHolders(String resourceName, Iterable<Holder> holders,
- {bool initializeEmptyHolders = false}) {
- // Create holder initialization code. If there are no properties
- // associated with a given holder in this specific [DeferredHolderResource]
- // then it will be omitted. However, in some cases, i.e. the main output
- // unit, we still want to declare the holder with an empty object literal
- // which will be filled in later by another [DeferredHolderResource], i.e.
- // in a specific deferred fragment. The generated code looks like this:
+ // Create holder initialization code based on the [codePerHolder]. If there
+ // are no properties associated with a given holder in this specific
+ // [DeferredHolderResource] then it will be omitted. However, in some cases,
+ // i.e. the main output unit, we still want to declare the holder with an
+ // empty object literal which will be filled in later by another
+ // [DeferredHolderResource], i.e. in a specific deferred fragment.
+ // The generated code looks like this:
//
// {
// var H = {...}, ..., G = {...};
+ // var holders = [ H, ..., G ]; // Main unit only.
// }
- List<Holder> activeHolders = [];
+ List<String> activeHolders = [];
List<js.VariableInitialization> holderInitializations = [];
for (var holder in holders) {
- var holderName = holder.name;
- List<js.Property> properties =
- holder.propertiesPerResource[resourceName] ?? [];
+ List<js.Property> properties = codePerHolder[holder];
if (properties.isEmpty) {
holderInitializations.add(js.VariableInitialization(
- js.VariableDeclaration(holderName, allowRename: false),
- initializeEmptyHolders ? js.ObjectInitializer(properties) : null));
+ js.VariableDeclaration(holder, allowRename: false),
+ resource.initializeEmptyHolders
+ ? js.ObjectInitializer(properties)
+ : null));
} else {
activeHolders.add(holder);
holderInitializations.add(js.VariableInitialization(
- js.VariableDeclaration(holderName, allowRename: false),
+ js.VariableDeclaration(holder, allowRename: false),
js.ObjectInitializer(properties)));
}
}
- // Create statement to initialize holders.
- var initStatement = js.ExpressionStatement(
- js.VariableDeclarationList(holderInitializations, indentSplits: false));
- return HolderInitCode(holders, activeHolders, initStatement);
+ List<js.Statement> statements = [];
+ statements.add(js.ExpressionStatement(js.VariableDeclarationList(
+ holderInitializations,
+ indentSplits: false)));
+ if (resource.initializeEmptyHolders) {
+ statements.add(js.js.statement(
+ 'var holders = #',
+ js.ArrayInitializer(holders
+ .map((holder) => js.VariableUse(holder))
+ .toList(growable: false))));
+ }
+ return HolderCode(activeHolders, statements);
}
/// Finalizes [resource] to code that updates holders. [resource] must be in
/// the AST of a deferred fragment.
void updateHolders(DeferredHolderResource resource) {
- final holderCode =
- declareHolders(resource.name, nonStaticStateHolders(resource));
+ // Declare holders.
+ final holderCode = declareHolders(resource);
// Set names if necessary on deferred holders list.
js.Expression deferredHoldersList = js.ArrayInitializer(holderCode
.activeHolders
- .map((holder) => js.js("#", holder.name))
+ .map((holder) => js.js("#", holder))
.toList(growable: false));
js.Statement setNames = js.js.statement(
'hunkHelpers.setFunctionNamesIfNecessary(#deferredHoldersList)',
{'deferredHoldersList': deferredHoldersList});
// Update holder assignments.
- List<js.Statement> updateHolderAssignments = [
- holderCode.statement,
- setNames
- ];
- for (var holder in holderCode.allHolders) {
- var holderName = holder.name;
- var holderIndex = js.number(holder.index);
+ final holders = nonStaticStateHolders;
+ List<js.Statement> updateHolderAssignments = [setNames];
+ for (int i = 0; i < holders.length; i++) {
+ var holder = holders[i];
if (holderCode.activeHolders.contains(holder)) {
updateHolderAssignments.add(js.js.statement(
'#holder = hunkHelpers.updateHolder(holdersList[#index], #holder)',
- {'index': holderIndex, 'holder': js.VariableUse(holderName)}));
+ {'index': js.number(i), 'holder': js.VariableUse(holder)}));
} else {
// TODO(sra): Change declaration followed by assignments to declarations
// with initialization.
updateHolderAssignments.add(js.js.statement(
'#holder = holdersList[#index]',
- {'index': holderIndex, 'holder': js.VariableUse(holderName)}));
+ {'index': js.number(i), 'holder': js.VariableUse(holder)}));
}
}
// Create a single block of all statements.
- resource.statement = js.Block(updateHolderAssignments);
+ List<js.Statement> statements = holderCode.statements
+ .followedBy(updateHolderAssignments)
+ .toList(growable: false);
+ resource.statement = js.Block(statements);
}
- /// Declares all holders in the [DeferredHolderResource] representing the main
- /// fragment.
- void declareHoldersInMainResource() {
- // Declare holders in main output unit.
- var holders = allNonStaticStateHolders;
- var holderCode = declareHolders(mainHolderResource.name, holders,
- initializeEmptyHolders: true);
-
- // Create holder uses and init holder indices.
- List<js.VariableUse> holderUses = [];
- int i = 0;
- for (var holder in holders) {
- holder.index = i++;
- holderUses.add(js.VariableUse(holder.name));
+ /// Allocates all [DeferredHolderResource]s and
+ /// [DeferredHolderResourceExpression]s.
+ void allocateResources() {
+ // First ensure all holders used in all [DeferredHolderResource]s have been
+ // allocated.
+ for (var resource in holderResources) {
+ registerHolders(resource);
}
-
- // Create holders array statement.
- // {
- // var holders = [ H, ..., G ];
- // }
- var holderArray =
- js.js.statement('var holders = #', js.ArrayInitializer(holderUses));
-
- mainHolderResource.statement =
- js.Block([holderCode.statement, holderArray]);
- }
-
- /// Allocates all [DeferredHolderResource]s and finalizes the associated
- /// [DeferredHolderExpression]s.
- void allocateResourcesAndFinalizeReferences() {
- // First finalize all holders in the main output unit.
- declareHoldersInMainResource();
+ _holders.sort();
// Next finalize all [DeferredHolderResource]s.
for (var resource in holderResources) {
switch (resource.kind) {
- case DeferredHolderResourceKind.mainFragment:
- // There should only be one main resource and at this point it
- // should have already been finalized.
- assert(mainHolderResource == resource && resource.isFinalized);
+ case DeferredHolderResourceKind.declaration:
+ var holderCode = declareHolders(resource);
+ resource.statement = js.Block(holderCode.statements);
break;
- case DeferredHolderResourceKind.deferredFragment:
+ case DeferredHolderResourceKind.update:
updateHolders(resource);
break;
}
- finalizeReferences(resource);
}
}
@override
void finalize() {
- registerHolders();
- finalizeParameters();
- allocateResourcesAndFinalizeReferences();
+ finalizeReferences();
+ allocateResources();
}
- void _registerDeferredHolderExpression(
- String resourceName, DeferredHolderExpression node) {
- (holderReferences[resourceName] ??= []).add(node);
+ void _registerDeferredHolderExpression(DeferredHolderExpression node) {
+ holderReferences.add(node);
}
void _registerDeferredHolderResource(DeferredHolderResource node) {
- if (node.isMainFragment) {
- assert(mainHolderResource == null);
- mainHolderResource = node;
- }
holderResources.add(node);
}
@@ -684,17 +586,10 @@
/// The state is kept in the finalizer so that this scan could be extended to
/// look for other deferred expressions in one pass.
class _DeferredHolderExpressionCollectorVisitor extends js.BaseVisitor<void> {
- String resourceName;
final DeferredHolderExpressionFinalizerImpl _finalizer;
_DeferredHolderExpressionCollectorVisitor(this._finalizer);
- void setResourceNameAndVisit(String resourceName, js.Node code) {
- this.resourceName = resourceName;
- code.accept(this);
- this.resourceName = null;
- }
-
@override
void visitNode(js.Node node) {
assert(node is! DeferredHolderExpression);
@@ -710,8 +605,7 @@
@override
void visitDeferredExpression(js.DeferredExpression node) {
if (node is DeferredHolderExpression) {
- assert(resourceName != null);
- _finalizer._registerDeferredHolderExpression(resourceName, node);
+ _finalizer._registerDeferredHolderExpression(node);
} else {
visitNode(node);
}
@@ -736,9 +630,8 @@
}
}
-class HolderInitCode {
- final Iterable<Holder> allHolders;
- final List<Holder> activeHolders;
- final js.Statement statement;
- HolderInitCode(this.allHolders, this.activeHolders, this.statement);
+class HolderCode {
+ final List<String> activeHolders;
+ final List<js.Statement> statements;
+ HolderCode(this.activeHolders, this.statements);
}
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index 5e4afbd..8503a49 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -2071,9 +2071,8 @@
FixedNames get fixedNames;
/// Returns a variable use for accessing constants.
- jsAst.Expression globalObjectForConstant(ConstantValue constant) {
- return DeferredHolderExpression(
- DeferredHolderExpressionKind.globalObjectForConstant, constant);
+ jsAst.Expression globalObjectForConstants() {
+ return DeferredHolderExpression.forConstants();
}
/// Returns a variable use for accessing static state.
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
index a4249ee..bea472a 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
@@ -679,7 +679,6 @@
size = estimator.charCount;
}
var emittedOutputUnit = EmittedOutputUnit(
- fragment,
fragment.outputUnit,
fragment.libraries,
classPrototypes,
@@ -705,10 +704,9 @@
// Emit holder code.
var holderCode = emitHolderCode(fragment.libraries);
var holderDeclaration = DeferredHolderResource(
- DeferredHolderResourceKind.mainFragment,
- mainResourceName,
- [fragment],
- holderCode);
+ DeferredHolderResourceKind.declaration,
+ holderCode: holderCode,
+ initializeEmptyHolders: true);
js.Statement mainCode = js.js.statement(_mainBoilerplate, {
// TODO(29455): 'hunkHelpers' displaces other names, so don't minify it.
'hunkHelpers': js.VariableDeclaration('hunkHelpers', allowRename: false),
@@ -760,7 +758,7 @@
'call2selector': js.quoteName(call2Name)
});
// We assume emitMainFragment will be the last piece of code we emit.
- finalizeCode(mainResourceName, mainCode, holderCode, finalizeHolders: true);
+ finalizeCode(mainCode, holderCode, finalizeHolders: true);
return mainCode;
}
@@ -780,12 +778,9 @@
return null;
}
- var resourceName = fragment.canonicalOutputUnit.name;
var updateHolders = DeferredHolderResource(
- DeferredHolderResourceKind.deferredFragment,
- resourceName,
- fragment.fragments,
- holderCode);
+ DeferredHolderResourceKind.update,
+ holderCode: holderCode);
js.Expression code = js.js(_deferredBoilerplate, {
// TODO(floitsch): don't just reference 'init'.
'embeddedGlobalsObject': new js.Parameter('init'),
@@ -811,7 +806,7 @@
if (_options.experimentStartupFunctions) {
code = js.Parentheses(code);
}
- finalizeCode(resourceName, code, holderCode);
+ finalizeCode(code, holderCode);
return code;
}
@@ -828,8 +823,7 @@
/// Finalizes the code for a fragment, and optionally finalizes holders.
/// Finalizing holders must be the last step of the emitter.
- void finalizeCode(String resourceName, js.Node code,
- Map<Entity, List<js.Property>> holderCode,
+ void finalizeCode(js.Node code, Map<Entity, List<js.Property>> holderCode,
{bool finalizeHolders: false}) {
StringReferenceFinalizer stringFinalizer =
StringReferenceFinalizerImpl(_options.enableMinification);
@@ -847,11 +841,7 @@
// per output unit, the holderFinalizer is a whole-program finalizer,
// which collects deferred [Node]s from each call to `finalizeCode`
// before begin finalized once for the last (main) unit.
- void _addCode(js.Node code) {
- _holderFinalizer.addCode(resourceName, code);
- }
-
- addCodeToFinalizer(_addCode, code, holderCode);
+ addCodeToFinalizer(_holderFinalizer.addCode, code, holderCode);
if (finalizeHolders) {
_holderFinalizer.finalize();
}
@@ -1579,7 +1569,7 @@
// TODO(25230): We only need to name constants that are used from function
// bodies or from other constants in a different part.
var assignment = js.js.statement('#.# = #', [
- _namer.globalObjectForConstant(constant.value),
+ _namer.globalObjectForConstants(),
constant.name,
_constantEmitter.generate(constant.value)
]);
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_merger.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_merger.dart
index 9fae89c..89cc19c 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_merger.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_merger.dart
@@ -109,7 +109,6 @@
/// sent to the client.
class EmittedOutputUnit {
- final Fragment fragment;
final OutputUnit outputUnit;
final List<Library> libraries;
final js.Statement classPrototypes;
@@ -125,7 +124,6 @@
final js.Statement nativeSupport;
EmittedOutputUnit(
- this.fragment,
this.outputUnit,
this.libraries,
this.classPrototypes,
@@ -142,7 +140,6 @@
CodeFragment toCodeFragment(Program program) {
return CodeFragment(
- [fragment],
[outputUnit],
libraries,
classPrototypes,
@@ -204,7 +201,6 @@
return seedEmittedOutputUnit.toCodeFragment(program);
} else {
var seedOutputUnit = seedEmittedOutputUnit.outputUnit;
- List<Fragment> fragments = [];
List<Library> libraries = [];
List<OutputUnit> outputUnits = [seedOutputUnit];
List<js.Statement> classPrototypes = [];
@@ -223,7 +219,6 @@
if (seedOutputUnit != thatOutputUnit) {
program.mergeOutputUnitMetadata(seedOutputUnit, thatOutputUnit);
outputUnits.add(thatOutputUnit);
- fragments.add(emittedOutputUnit.fragment);
}
libraries.addAll(emittedOutputUnit.libraries);
classPrototypes.add(emittedOutputUnit.classPrototypes);
@@ -239,7 +234,6 @@
nativeSupport.add(emittedOutputUnit.nativeSupport);
}
return CodeFragment(
- fragments,
outputUnits,
libraries,
js.Block(classPrototypes),
@@ -322,7 +316,6 @@
}
class CodeFragment {
- final List<Fragment> fragments;
final List<OutputUnit> outputUnits;
final List<Library> libraries;
final js.Statement classPrototypes;
@@ -339,7 +332,6 @@
final js.Expression deferredTypes;
CodeFragment(
- this.fragments,
this.outputUnits,
this.libraries,
this.classPrototypes,
@@ -396,8 +388,6 @@
}
return outputUnitStrings.join('+');
}
-
- OutputUnit get canonicalOutputUnit => outputUnits.first;
}
class FinalizedFragment {
@@ -410,7 +400,7 @@
// TODO(joshualitt): Refactor this to more clearly disambiguate between
// [OutputUnits](units of deferred merging), fragments(units of emitted code),
// and files.
- OutputUnit get canonicalOutputUnit => codeFragments.first.canonicalOutputUnit;
+ OutputUnit get canonicalOutputUnit => codeFragments.first.outputUnits.first;
@override
String toString() {
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
index 8a272c6..21fe02f 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
@@ -65,8 +65,7 @@
DeferredHolderExpressionFinalizerImpl,
DeferredHolderParameter,
DeferredHolderResource,
- DeferredHolderResourceKind,
- mainResourceName;
+ DeferredHolderResourceKind;
import '../../js_backend/type_reference.dart'
show
TypeReferenceFinalizer,
@@ -219,8 +218,8 @@
if (isConstantInlinedOrAlreadyEmitted(value)) {
return constantEmitter.generate(value);
}
- return js.js('#.#',
- [_namer.globalObjectForConstant(value), _namer.constantName(value)]);
+ return js.js(
+ '#.#', [_namer.globalObjectForConstants(), _namer.constantName(value)]);
}
bool get shouldMergeFragments => _options.mergeFragmentsThreshold != null;
diff --git a/pkg/dds/CHANGELOG.md b/pkg/dds/CHANGELOG.md
index c899383..84e2e6a 100644
--- a/pkg/dds/CHANGELOG.md
+++ b/pkg/dds/CHANGELOG.md
@@ -1,3 +1,6 @@
+# 2.0.1
+- Update `package:vm_service` to ^7.0.0.
+
# 2.0.0
- **Breaking change:** add null safety support.
- **Breaking change:** minimum Dart SDK revision bumped to 2.12.0.
diff --git a/pkg/dds/pubspec.yaml b/pkg/dds/pubspec.yaml
index cf7e081..2bf3136 100644
--- a/pkg/dds/pubspec.yaml
+++ b/pkg/dds/pubspec.yaml
@@ -3,7 +3,7 @@
A library used to spawn the Dart Developer Service, used to communicate with
a Dart VM Service instance.
-version: 2.0.0
+version: 2.0.1
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/dds
@@ -25,7 +25,7 @@
sse: ^4.0.0
stream_channel: ^2.0.0
usage: ^4.0.0
- vm_service: ^6.0.1
+ vm_service: ^7.0.0
web_socket_channel: ^2.0.0
dev_dependencies:
diff --git a/pkg/nnbd_migration/lib/src/edge_builder.dart b/pkg/nnbd_migration/lib/src/edge_builder.dart
index 316b4b2..3ae06c1 100644
--- a/pkg/nnbd_migration/lib/src/edge_builder.dart
+++ b/pkg/nnbd_migration/lib/src/edge_builder.dart
@@ -1912,6 +1912,13 @@
}
}
typeName.visitChildren(this);
+ // If the type name is followed by a `/*!*/` comment, it is considered to
+ // apply to the type and not to the "as" expression. In order to prevent
+ // a future call to _handleNullCheck from interpreting it as applying to
+ // the "as" expression, we need to store the `/*!*/` comment in
+ // _nullCheckHints.
+ var token = typeName.endToken;
+ _nullCheckHints[token] = getPostfixHint(token);
typeNameVisited(
typeName); // Note this has been visited to TypeNameTracker.
return null;
@@ -2264,11 +2271,7 @@
DecoratedType _dispatch(AstNode node, {bool skipNullCheckHint = false}) {
try {
var type = node?.accept(this);
- if (!skipNullCheckHint &&
- node is Expression &&
- // A /*!*/ hint following an AsExpression should be interpreted as a
- // nullability hint for the type, not a null-check hint.
- node is! AsExpression) {
+ if (!skipNullCheckHint && node is Expression) {
type = _handleNullCheckHint(node, type);
}
return type;
diff --git a/pkg/nnbd_migration/test/api_test.dart b/pkg/nnbd_migration/test/api_test.dart
index 70abd3d5..19248f9 100644
--- a/pkg/nnbd_migration/test/api_test.dart
+++ b/pkg/nnbd_migration/test/api_test.dart
@@ -251,6 +251,54 @@
await _checkSingleFileChanges(content, expected);
}
+ Future<void> test_ambiguous_bang_hint_after_as() async {
+ var content = '''
+T f<T>(Object/*?*/ x) => x as T/*!*/;
+''';
+ // The `/*!*/` is considered to apply to the type `T`, not to the expression
+ // `x as T`, so we shouldn't produce `(x as T)!`.
+ var expected = '''
+T f<T>(Object? x) => x as T;
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
+ Future<void> test_ambiguous_bang_hint_after_as_assigned() async {
+ var content = '''
+T f<T>(Object/*?*/ x, T/*!*/ y) => y = x as T/*!*/;
+''';
+ // The `/*!*/` is considered to apply to the type `T`, not to the expression
+ // `y = x as T`, so we shouldn't produce `(y = x as T)!`.
+ var expected = '''
+T f<T>(Object? x, T y) => y = x as T;
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
+ Future<void> test_ambiguous_bang_hint_after_is() async {
+ var content = '''
+bool f<T>(Object/*?*/ x) => x is T/*!*/;
+''';
+ // The `/*!*/` is considered to apply to the type `T`, not to the expression
+ // `x is T`, so we shouldn't produce `(x is T)!`.
+ var expected = '''
+bool f<T>(Object? x) => x is T;
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
+ Future<void> test_ambiguous_bang_hint_after_is_conditional() async {
+ var content = '''
+dynamic f<T>(Object/*?*/ x, dynamic y) => y ? y : x is T/*!*/;
+''';
+ // The `/*!*/` is considered to apply to the type `T`, not to the expression
+ // `y ? y : x is T`, so we shouldn't produce `(y ? y : x is T)!`.
+ var expected = '''
+dynamic f<T>(Object? x, dynamic y) => y ? y : x is T;
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
Future<void> test_ambiguous_closure_parameter_in_local_variable() async {
var content = '''
Object f<T>(Object Function(T) callback, Object obj) => 0;
@@ -2308,34 +2356,6 @@
await _checkSingleFileChanges(content, expected);
}
- Future<void> test_extension_null_check_non_nullable_method() async {
- var content = '''
-class C {}
-extension E on C/*!*/ {
- void m() {}
-}
-void f(C c, bool b) {
- if (b) {
- c.m();
- }
-}
-void g() => f(null, false);
-''';
- var expected = '''
-class C {}
-extension E on C {
- void m() {}
-}
-void f(C? c, bool b) {
- if (b) {
- c!.m();
- }
-}
-void g() => f(null, false);
-''';
- await _checkSingleFileChanges(content, expected);
- }
-
Future<void> test_extension_null_check_non_nullable_binary() async {
var content = '''
class C {}
@@ -2364,27 +2384,27 @@
await _checkSingleFileChanges(content, expected);
}
- Future<void> test_extension_null_check_non_nullable_prefix() async {
+ Future<void> test_extension_null_check_non_nullable_generic() async {
var content = '''
class C {}
-extension E on C/*!*/ {
- void operator-() {}
+extension E<T extends Object/*!*/> on T/*!*/ {
+ void m() {}
}
void f(C c, bool b) {
if (b) {
- -c;
+ c.m();
}
}
void g() => f(null, false);
''';
var expected = '''
class C {}
-extension E on C {
- void operator-() {}
+extension E<T extends Object> on T {
+ void m() {}
}
void f(C? c, bool b) {
if (b) {
- -c!;
+ c!.m();
}
}
void g() => f(null, false);
@@ -2420,10 +2440,10 @@
await _checkSingleFileChanges(content, expected);
}
- Future<void> test_extension_null_check_non_nullable_generic() async {
+ Future<void> test_extension_null_check_non_nullable_method() async {
var content = '''
class C {}
-extension E<T extends Object/*!*/> on T/*!*/ {
+extension E on C/*!*/ {
void m() {}
}
void f(C c, bool b) {
@@ -2435,7 +2455,7 @@
''';
var expected = '''
class C {}
-extension E<T extends Object> on T {
+extension E on C {
void m() {}
}
void f(C? c, bool b) {
@@ -2448,6 +2468,34 @@
await _checkSingleFileChanges(content, expected);
}
+ Future<void> test_extension_null_check_non_nullable_prefix() async {
+ var content = '''
+class C {}
+extension E on C/*!*/ {
+ void operator-() {}
+}
+void f(C c, bool b) {
+ if (b) {
+ -c;
+ }
+}
+void g() => f(null, false);
+''';
+ var expected = '''
+class C {}
+extension E on C {
+ void operator-() {}
+}
+void f(C? c, bool b) {
+ if (b) {
+ -c!;
+ }
+}
+void g() => f(null, false);
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
Future<void> test_extension_null_check_nullable() async {
var content = '''
class C {}
diff --git a/pkg/wasm/README.md b/pkg/wasm/README.md
index ecf418d..4558a3c 100644
--- a/pkg/wasm/README.md
+++ b/pkg/wasm/README.md
@@ -4,7 +4,7 @@
## Setup
-Run `dart bin/setup.dart` to build the Wasmer runtime.
+Run `dart run wasm:setup` to build the Wasmer runtime.
## Basic Usage
@@ -25,15 +25,15 @@
Then we can load and run it like this:
```dart
-import "dart:io";
-import "package:wasm/wasm.dart";
+import 'dart:io';
+import 'package:wasm/wasm.dart';
void main() {
- final data = File("square.wasm").readAsBytesSync();
+ final data = File('square.wasm').readAsBytesSync();
final mod = WasmModule(data);
print(mod.describe());
final inst = mod.instantiate().build();
- final square = inst.lookupFunction("square");
+ final square = inst.lookupFunction('square');
print(square(12));
}
```
diff --git a/pkg/wasm/analysis_options.yaml b/pkg/wasm/analysis_options.yaml
index 2bb8d1d..74fd4c8 100644
--- a/pkg/wasm/analysis_options.yaml
+++ b/pkg/wasm/analysis_options.yaml
@@ -1,4 +1,4 @@
-include: package:pedantic/analysis_options.1.9.0.yaml
+include: package:lints/recommended.yaml
analyzer:
strong-mode:
@@ -15,6 +15,7 @@
- avoid_returning_null_for_void
- avoid_unused_constructor_parameters
- await_only_futures
+ - cancel_subscriptions
- camel_case_types
- cascade_invocations
- constant_identifier_names
@@ -44,6 +45,7 @@
- prefer_interpolation_to_compose_strings
- prefer_is_not_operator
- prefer_null_aware_operators
+ - prefer_single_quotes
- prefer_relative_imports
- prefer_typing_uninitialized_variables
- prefer_void_to_null
@@ -53,6 +55,7 @@
- test_types_in_equals
- throw_in_finally
- type_annotate_public_apis
+ - unawaited_futures
- unnecessary_brace_in_string_interps
- unnecessary_lambdas
- unnecessary_null_aware_assignments
diff --git a/pkg/wasm/bin/setup.dart b/pkg/wasm/bin/setup.dart
index 04fc145..2497ecd 100644
--- a/pkg/wasm/bin/setup.dart
+++ b/pkg/wasm/bin/setup.dart
@@ -5,17 +5,38 @@
// Builds the wasmer runtime library, to by used by package:wasm. Requires
// rustc, cargo, clang, and clang++. If a target triple is not specified, it
// will default to the host target.
-// Usage: dart setup.dart [target-triple]
+// Usage: dart run wasm:setup [target-triple]
import 'dart:convert';
-import 'dart:io';
+import 'dart:io' hide exit;
-Uri getSdkDir() {
+import 'package:wasm/src/shared.dart';
+
+Future<void> main(List<String> args) async {
+ if (args.length > 1) {
+ print('Usage: $invocationString [target-triple]');
+ exitCode = 64; // bad usage
+ return;
+ }
+
+ final target = args.isNotEmpty ? args[0] : await _getTargetTriple();
+
+ try {
+ await _main(target);
+ } on ProcessException catch (e) {
+ final invocation = [e.executable, ...e.arguments].join(' ');
+ print('FAILED with exit code ${e.errorCode} `$invocation`');
+ exitCode = 70; // software error
+ return;
+ }
+}
+
+Uri _getSdkDir() {
// The common case, and how cli_util.dart computes the Dart SDK directory,
// path.dirname called twice on Platform.resolvedExecutable.
final exe = Uri.file(Platform.resolvedExecutable);
final commonSdkDir = exe.resolve('../../dart-sdk/');
- if (Directory(commonSdkDir.path).existsSync()) {
+ if (FileSystemEntity.isDirectorySync(commonSdkDir.path)) {
return commonSdkDir;
}
@@ -23,13 +44,13 @@
// SDK, and is executing dart via:
// ./out/ReleaseX64/dart ...
final checkedOutSdkDir = exe.resolve('../dart-sdk/');
- if (Directory(checkedOutSdkDir.path).existsSync()) {
+ if (FileSystemEntity.isDirectorySync(checkedOutSdkDir.path)) {
return checkedOutSdkDir;
}
final homebrewOutSdkDir = exe.resolve('..');
final homebrewIncludeDir = homebrewOutSdkDir.resolve('include');
- if (Directory(homebrewIncludeDir.path).existsSync()) {
+ if (FileSystemEntity.isDirectorySync(homebrewIncludeDir.path)) {
return homebrewOutSdkDir;
}
@@ -37,30 +58,28 @@
return commonSdkDir;
}
-Uri getOutDir(Uri root) {
- // Traverse up until we see a `.dart_tool/package_config.json` file.
- do {
- if (File.fromUri(root.resolve('.dart_tool/package_config.json'))
- .existsSync()) {
- return root.resolve('.dart_tool/wasm/');
- }
- } while (root != (root = root.resolve('..')));
- throw Exception('.dart_tool/package_config.json not found');
+Uri _getOutDir(Uri root) {
+ final pkgRoot = packageRootUri(root);
+ if (pkgRoot == null) {
+ throw Exception('$pkgConfigFile not found');
+ }
+ return pkgRoot.resolve(wasmToolDir);
}
-String getOutLib(String target) {
+String _getOutLib(String target) {
final os = RegExp(r'^.*-.*-(.*)').firstMatch(target)?.group(1) ?? '';
if (os == 'darwin' || os == 'ios') {
- return 'libwasmer.dylib';
+ return appleLib;
} else if (os == 'windows') {
return 'wasmer.dll';
}
- return 'libwasmer.so';
+ return linuxLib;
}
-Future<String> getTargetTriple() async {
+Future<String> _getTargetTriple() async {
+ final _regexp = RegExp(r'^([^=]+)="(.*)"$');
final process = await Process.start('rustc', ['--print', 'cfg']);
- process.stderr
+ final sub = process.stderr
.transform(utf8.decoder)
.transform(const LineSplitter())
.listen((line) => stderr.writeln(line));
@@ -68,10 +87,11 @@
await process.stdout
.transform(utf8.decoder)
.transform(const LineSplitter())
- .listen((line) {
- final match = RegExp(r'^([^=]+)="(.*)"$').firstMatch(line);
+ .forEach((line) {
+ final match = _regexp.firstMatch(line);
if (match != null) cfg[match.group(1)!] = match.group(2);
- }).asFuture();
+ });
+ await sub.cancel();
var arch = cfg['target_arch'] ?? 'unknown';
var vendor = cfg['target_vendor'] ?? 'unknown';
var os = cfg['target_os'] ?? 'unknown';
@@ -82,35 +102,21 @@
.join('-');
}
-Future<void> run(String exe, List<String> args) async {
+Future<void> _run(String exe, List<String> args) async {
print('\n$exe ${args.join(' ')}\n');
- final process = await Process.start(exe, args);
- process.stdout
- .transform(utf8.decoder)
- .transform(const LineSplitter())
- .listen(print);
- process.stderr
- .transform(utf8.decoder)
- .transform(const LineSplitter())
- .listen((line) => stderr.writeln(line));
- final exitCode = await process.exitCode;
- if (exitCode != 0) {
- print('Command failed with exit code $exitCode');
- exit(exitCode);
+ final process =
+ await Process.start(exe, args, mode: ProcessStartMode.inheritStdio);
+ final result = await process.exitCode;
+ if (result != 0) {
+ throw ProcessException(exe, args, '', result);
}
}
-Future<void> main(List<String> args) async {
- if (args.length > 1) {
- print('Usage: dart setup.dart [target-triple]');
- exit(1);
- }
-
- final target = args.isNotEmpty ? args[0] : await getTargetTriple();
- final sdkDir = getSdkDir();
+Future<void> _main(String target) async {
+ final sdkDir = _getSdkDir();
final binDir = Platform.script;
- final outDir = getOutDir(binDir);
- final outLib = outDir.resolve(getOutLib(target)).path;
+ final outDir = _getOutDir(Directory.current.uri);
+ final outLib = outDir.resolve(_getOutLib(target)).path;
print('Dart SDK directory: ${sdkDir.path}');
print('Script directory: ${binDir.path}');
@@ -119,7 +125,7 @@
print('Output library: $outLib');
// Build wasmer crate.
- await run('cargo', [
+ await _run('cargo', [
'build',
'--target',
target,
@@ -130,18 +136,18 @@
'--release'
]);
- final dartApiDlImplFile =
- File.fromUri(sdkDir.resolve('include/internal/dart_api_dl_impl.h'));
+ const dartApiDlImplPath = 'include/internal/dart_api_dl_impl.h';
+
+ final dartApiDlImplFile = File.fromUri(sdkDir.resolve(dartApiDlImplPath));
// Hack around a bug with dart_api_dl_impl.h include path in dart_api_dl.c.
if (!dartApiDlImplFile.existsSync()) {
Directory(outDir.resolve('include/internal/').path)
.createSync(recursive: true);
- await dartApiDlImplFile
- .copy(outDir.resolve('include/internal/dart_api_dl_impl.h').path);
+ await dartApiDlImplFile.copy(outDir.resolve(dartApiDlImplPath).path);
}
// Build dart_api_dl.o.
- await run('clang', [
+ await _run('clang', [
'-DDART_SHARED_LIB',
'-DNDEBUG',
'-fno-exceptions',
@@ -160,7 +166,7 @@
]);
// Build finalizers.o.
- await run('clang++', [
+ await _run('clang++', [
'-DDART_SHARED_LIB',
'-DNDEBUG',
'-fno-exceptions',
@@ -181,7 +187,7 @@
]);
// Link wasmer, dart_api_dl, and finalizers to create the output library.
- await run('clang++', [
+ await _run('clang++', [
'-shared',
'-fPIC',
'-target',
diff --git a/pkg/wasm/lib/src/runtime.dart b/pkg/wasm/lib/src/runtime.dart
index 40e892b..3f9bcf0 100644
--- a/pkg/wasm/lib/src/runtime.dart
+++ b/pkg/wasm/lib/src/runtime.dart
@@ -10,6 +10,7 @@
import 'package:ffi/ffi.dart';
+import 'shared.dart';
import 'wasmer_api.dart';
part 'runtime.g.dart';
@@ -99,23 +100,16 @@
}
String _getLibName() {
- if (Platform.isMacOS) return 'libwasmer.dylib';
- if (Platform.isLinux) return 'libwasmer.so';
+ if (Platform.isMacOS) return appleLib;
+ if (Platform.isLinux) return linuxLib;
// TODO(dartbug.com/37882): Support more platforms.
throw Exception('Wasm not currently supported on this platform');
}
String? _getLibPathFrom(Uri root) {
- // The dynamic library created by pub run wasm:setup is located relative to
- // the package_config.json file, so walk up from the script directory until
- // we find it.
- do {
- if (File.fromUri(root.resolve('.dart_tool/package_config.json'))
- .existsSync()) {
- return root.resolve('.dart_tool/wasm/${_getLibName()}').path;
- }
- } while (root != (root = root.resolve('..')));
- return null;
+ final pkgRoot = packageRootUri(root);
+
+ return pkgRoot?.resolve('$wasmToolDir${_getLibName()}').path;
}
String _getLibPath() {
@@ -123,5 +117,5 @@
if (path != null) return path;
path = _getLibPathFrom(Directory.current.uri);
if (path != null) return path;
- throw Exception('Wasm library not found. Did you `pub run wasm:setup`?');
+ throw Exception('Wasm library not found. Did you `$invocationString`?');
}
diff --git a/pkg/wasm/lib/src/shared.dart b/pkg/wasm/lib/src/shared.dart
new file mode 100644
index 0000000..0f666b7
--- /dev/null
+++ b/pkg/wasm/lib/src/shared.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+const invocationString = 'dart run wasm:setup';
+
+const pkgConfigFile = '.dart_tool/package_config.json';
+const wasmToolDir = '.dart_tool/wasm/';
+
+const appleLib = 'libwasmer.dylib';
+const linuxLib = 'libwasmer.so';
+
+Uri? packageRootUri(Uri root) {
+ do {
+ if (FileSystemEntity.isFileSync(root.resolve(pkgConfigFile).path)) {
+ return root;
+ }
+ } while (root != (root = root.resolve('..')));
+ return null;
+}
diff --git a/pkg/wasm/pubspec.yaml b/pkg/wasm/pubspec.yaml
index 9cd60c7..a91c321 100644
--- a/pkg/wasm/pubspec.yaml
+++ b/pkg/wasm/pubspec.yaml
@@ -10,5 +10,5 @@
ffi: ^1.0.0
dev_dependencies:
- pedantic: ^1.10.0
+ lints: ^1.0.0
test: ^1.16.0
diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h
index 56e8f0e..a880734 100644
--- a/runtime/vm/compiler/runtime_offsets_extracted.h
+++ b/runtime/vm/compiler/runtime_offsets_extracted.h
@@ -527,7 +527,7 @@
static constexpr dart::compiler::target::word Pointer_InstanceSize = 12;
static constexpr dart::compiler::target::word ReceivePort_InstanceSize = 20;
static constexpr dart::compiler::target::word RegExp_InstanceSize = 60;
-static constexpr dart::compiler::target::word Script_InstanceSize = 48;
+static constexpr dart::compiler::target::word Script_InstanceSize = 56;
static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
16;
@@ -1072,7 +1072,7 @@
static constexpr dart::compiler::target::word Pointer_InstanceSize = 24;
static constexpr dart::compiler::target::word ReceivePort_InstanceSize = 40;
static constexpr dart::compiler::target::word RegExp_InstanceSize = 120;
-static constexpr dart::compiler::target::word Script_InstanceSize = 80;
+static constexpr dart::compiler::target::word Script_InstanceSize = 96;
static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
32;
@@ -1607,7 +1607,7 @@
static constexpr dart::compiler::target::word Pointer_InstanceSize = 12;
static constexpr dart::compiler::target::word ReceivePort_InstanceSize = 20;
static constexpr dart::compiler::target::word RegExp_InstanceSize = 60;
-static constexpr dart::compiler::target::word Script_InstanceSize = 48;
+static constexpr dart::compiler::target::word Script_InstanceSize = 56;
static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
16;
@@ -2153,7 +2153,7 @@
static constexpr dart::compiler::target::word Pointer_InstanceSize = 24;
static constexpr dart::compiler::target::word ReceivePort_InstanceSize = 40;
static constexpr dart::compiler::target::word RegExp_InstanceSize = 120;
-static constexpr dart::compiler::target::word Script_InstanceSize = 80;
+static constexpr dart::compiler::target::word Script_InstanceSize = 96;
static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
32;
@@ -2697,7 +2697,7 @@
static constexpr dart::compiler::target::word Pointer_InstanceSize = 24;
static constexpr dart::compiler::target::word ReceivePort_InstanceSize = 24;
static constexpr dart::compiler::target::word RegExp_InstanceSize = 80;
-static constexpr dart::compiler::target::word Script_InstanceSize = 56;
+static constexpr dart::compiler::target::word Script_InstanceSize = 64;
static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
32;
@@ -3242,7 +3242,7 @@
static constexpr dart::compiler::target::word Pointer_InstanceSize = 24;
static constexpr dart::compiler::target::word ReceivePort_InstanceSize = 24;
static constexpr dart::compiler::target::word RegExp_InstanceSize = 80;
-static constexpr dart::compiler::target::word Script_InstanceSize = 56;
+static constexpr dart::compiler::target::word Script_InstanceSize = 64;
static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
32;
@@ -7062,7 +7062,7 @@
static constexpr dart::compiler::target::word AOT_Pointer_InstanceSize = 12;
static constexpr dart::compiler::target::word AOT_ReceivePort_InstanceSize = 20;
static constexpr dart::compiler::target::word AOT_RegExp_InstanceSize = 60;
-static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 40;
+static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 48;
static constexpr dart::compiler::target::word AOT_SendPort_InstanceSize = 24;
static constexpr dart::compiler::target::word
AOT_SingleTargetCache_InstanceSize = 16;
@@ -7669,7 +7669,7 @@
static constexpr dart::compiler::target::word AOT_Pointer_InstanceSize = 24;
static constexpr dart::compiler::target::word AOT_ReceivePort_InstanceSize = 40;
static constexpr dart::compiler::target::word AOT_RegExp_InstanceSize = 120;
-static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 72;
+static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 80;
static constexpr dart::compiler::target::word AOT_SendPort_InstanceSize = 24;
static constexpr dart::compiler::target::word
AOT_SingleTargetCache_InstanceSize = 32;
@@ -8280,7 +8280,7 @@
static constexpr dart::compiler::target::word AOT_Pointer_InstanceSize = 24;
static constexpr dart::compiler::target::word AOT_ReceivePort_InstanceSize = 40;
static constexpr dart::compiler::target::word AOT_RegExp_InstanceSize = 120;
-static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 72;
+static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 80;
static constexpr dart::compiler::target::word AOT_SendPort_InstanceSize = 24;
static constexpr dart::compiler::target::word
AOT_SingleTargetCache_InstanceSize = 32;
@@ -10093,7 +10093,7 @@
static constexpr dart::compiler::target::word AOT_Pointer_InstanceSize = 12;
static constexpr dart::compiler::target::word AOT_ReceivePort_InstanceSize = 12;
static constexpr dart::compiler::target::word AOT_RegExp_InstanceSize = 60;
-static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 40;
+static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 48;
static constexpr dart::compiler::target::word AOT_SendPort_InstanceSize = 24;
static constexpr dart::compiler::target::word
AOT_SingleTargetCache_InstanceSize = 16;
@@ -10693,7 +10693,7 @@
static constexpr dart::compiler::target::word AOT_Pointer_InstanceSize = 24;
static constexpr dart::compiler::target::word AOT_ReceivePort_InstanceSize = 24;
static constexpr dart::compiler::target::word AOT_RegExp_InstanceSize = 120;
-static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 72;
+static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 80;
static constexpr dart::compiler::target::word AOT_SendPort_InstanceSize = 24;
static constexpr dart::compiler::target::word
AOT_SingleTargetCache_InstanceSize = 32;
@@ -11297,7 +11297,7 @@
static constexpr dart::compiler::target::word AOT_Pointer_InstanceSize = 24;
static constexpr dart::compiler::target::word AOT_ReceivePort_InstanceSize = 24;
static constexpr dart::compiler::target::word AOT_RegExp_InstanceSize = 120;
-static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 72;
+static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 80;
static constexpr dart::compiler::target::word AOT_SendPort_InstanceSize = 24;
static constexpr dart::compiler::target::word
AOT_SingleTargetCache_InstanceSize = 32;
diff --git a/runtime/vm/malloc_hooks_tcmalloc.cc b/runtime/vm/malloc_hooks_tcmalloc.cc
index 443285e..438e477 100644
--- a/runtime/vm/malloc_hooks_tcmalloc.cc
+++ b/runtime/vm/malloc_hooks_tcmalloc.cc
@@ -4,7 +4,7 @@
#include "platform/globals.h"
-#if defined(DART_USE_TCMALLOC) && !defined(PRODUCT)
+#if defined(DART_USE_TCMALLOC) && defined(DEBUG)
#include "vm/malloc_hooks.h"
@@ -421,4 +421,4 @@
} // namespace dart
-#endif // defined(DART_USE_TCMALLOC) && !defined(PRODUCT)
+#endif // defined(DART_USE_TCMALLOC) && !defined(DEBUG)
diff --git a/runtime/vm/malloc_hooks_test.cc b/runtime/vm/malloc_hooks_test.cc
index 76b789b..8edd992 100644
--- a/runtime/vm/malloc_hooks_test.cc
+++ b/runtime/vm/malloc_hooks_test.cc
@@ -4,7 +4,7 @@
#include "platform/globals.h"
-#if defined(DART_USE_TCMALLOC) && !defined(PRODUCT)
+#if defined(DART_USE_TCMALLOC) && defined(DEBUG)
#include "platform/assert.h"
#include "vm/globals.h"
@@ -200,4 +200,4 @@
}; // namespace dart
-#endif // defined(DART_USE_TCMALLOC) && !defined(PRODUCT)
+#endif // defined(DART_USE_TCMALLOC) && !defined(DEBUG)
diff --git a/runtime/vm/malloc_hooks_unsupported.cc b/runtime/vm/malloc_hooks_unsupported.cc
index bf986dc..d28100f 100644
--- a/runtime/vm/malloc_hooks_unsupported.cc
+++ b/runtime/vm/malloc_hooks_unsupported.cc
@@ -4,7 +4,7 @@
#include "platform/globals.h"
-#if defined(PRODUCT) || !defined(DART_USE_TCMALLOC)
+#if !defined(DEBUG) || !defined(DART_USE_TCMALLOC)
#include "vm/malloc_hooks.h"
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index cf4a20d..571b390 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -11603,6 +11603,10 @@
}
#endif // !defined(DART_PRECOMPILED_RUNTIME)
+void Script::set_compile_time_constants(const Array& value) const {
+ untag()->set_compile_time_constants(value.ptr());
+}
+
void Script::set_kernel_program_info(const KernelProgramInfo& info) const {
untag()->set_kernel_program_info(info.ptr());
}
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index fe21539..065e42d 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -4464,6 +4464,11 @@
// The load time in milliseconds since epoch.
int64_t load_timestamp() const { return untag()->load_timestamp_; }
+ ArrayPtr compile_time_constants() const {
+ return untag()->compile_time_constants();
+ }
+ void set_compile_time_constants(const Array& value) const;
+
KernelProgramInfoPtr kernel_program_info() const {
return untag()->kernel_program_info();
}
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index 684d7f3..51a7f20 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -27,7 +27,6 @@
namespace dart {
-static const intptr_t kSampleSize = 8;
static const intptr_t kMaxSamplesPerTick = 16;
DEFINE_FLAG(bool, trace_profiled_isolates, false, "Trace profiled isolates.");
@@ -38,7 +37,7 @@
"Time between profiler samples in microseconds. Minimum 50.");
DEFINE_FLAG(int,
max_profile_depth,
- kSampleSize* kMaxSamplesPerTick,
+ Sample::kPCArraySizeInWords* kMaxSamplesPerTick,
"Maximum number stack frames walked. Minimum 1. Maximum 255.");
#if defined(USING_SIMULATOR)
DEFINE_FLAG(bool, profile_vm, true, "Always collect native stack traces.");
@@ -69,7 +68,6 @@
void Profiler::Init() {
// Place some sane restrictions on user controlled flags.
SetSampleDepth(FLAG_max_profile_depth);
- Sample::Init();
if (!FLAG_profiler) {
return;
}
@@ -158,24 +156,9 @@
SetSamplePeriod(FLAG_profile_period);
}
-intptr_t Sample::pcs_length_ = 0;
-intptr_t Sample::instance_size_ = 0;
-
-void Sample::Init() {
- pcs_length_ = kSampleSize;
- instance_size_ = sizeof(Sample) + (sizeof(uword) * pcs_length_); // NOLINT.
-}
-
-uword* Sample::GetPCArray() const {
- return reinterpret_cast<uword*>(reinterpret_cast<uintptr_t>(this) +
- sizeof(*this));
-}
-
SampleBuffer::SampleBuffer(intptr_t capacity) {
- ASSERT(Sample::instance_size() > 0);
-
- const intptr_t size = Utils::RoundUp(capacity * Sample::instance_size(),
- VirtualMemory::PageSize());
+ const intptr_t size =
+ Utils::RoundUp(capacity * sizeof(Sample), VirtualMemory::PageSize());
const bool kNotExecutable = false;
memory_ = VirtualMemory::Allocate(size, kNotExecutable, "dart-profiler");
if (memory_ == NULL) {
@@ -188,7 +171,7 @@
if (FLAG_trace_profiler) {
OS::PrintErr("Profiler holds %" Pd " samples\n", capacity);
- OS::PrintErr("Profiler sample is %" Pd " bytes\n", Sample::instance_size());
+ OS::PrintErr("Profiler sample is %" Pd " bytes\n", sizeof(Sample));
OS::PrintErr("Profiler memory usage = %" Pd " bytes\n", size);
}
if (FLAG_sample_buffer_duration != 0) {
@@ -218,9 +201,7 @@
Sample* SampleBuffer::At(intptr_t idx) const {
ASSERT(idx >= 0);
ASSERT(idx < capacity_);
- intptr_t offset = idx * Sample::instance_size();
- uint8_t* samples = reinterpret_cast<uint8_t*>(samples_);
- return reinterpret_cast<Sample*>(samples + offset);
+ return &samples_[idx];
}
intptr_t SampleBuffer::ReserveSampleSlot() {
@@ -273,7 +254,7 @@
uint8_t* samples_array_ptr = reinterpret_cast<uint8_t*>(samples_);
uint8_t* free_sample_ptr = reinterpret_cast<uint8_t*>(free_sample);
return static_cast<intptr_t>((free_sample_ptr - samples_array_ptr) /
- Sample::instance_size());
+ sizeof(Sample));
} else if (cursor_ < static_cast<uintptr_t>(capacity_ - 1)) {
return cursor_ += 1;
} else {
@@ -510,7 +491,7 @@
return false;
}
ASSERT(sample_ != NULL);
- if (frame_index_ == kSampleSize) {
+ if (frame_index_ == Sample::kPCArraySizeInWords) {
Sample* new_sample = sample_buffer_->ReserveSampleAndLink(sample_);
if (new_sample == NULL) {
// Could not reserve new sample- mark this as truncated.
@@ -520,7 +501,7 @@
frame_index_ = 0;
sample_ = new_sample;
}
- ASSERT(frame_index_ < kSampleSize);
+ ASSERT(frame_index_ < Sample::kPCArraySizeInWords);
sample_->SetAt(frame_index_, pc);
frame_index_++;
total_frames_++;
@@ -1573,7 +1554,7 @@
bool truncated = false;
Sample* current = sample;
while (current != NULL) {
- for (intptr_t i = 0; i < kSampleSize; i++) {
+ for (intptr_t i = 0; i < Sample::kPCArraySizeInWords; i++) {
if (current->At(i) == 0) {
break;
}
@@ -1585,7 +1566,7 @@
}
if (!sample->exit_frame_sample()) {
- processed_sample->FixupCaller(clt, sample->pc_marker(),
+ processed_sample->FixupCaller(clt, /* pc_marker */ 0,
sample->GetStackBuffer());
}
@@ -1612,7 +1593,7 @@
}
ProcessedSample::ProcessedSample()
- : pcs_(kSampleSize),
+ : pcs_(Sample::kPCArraySizeInWords),
timestamp_(0),
vm_tag_(0),
user_tag_(0),
diff --git a/runtime/vm/profiler.h b/runtime/vm/profiler.h
index 215d357..6dad274 100644
--- a/runtime/vm/profiler.h
+++ b/runtime/vm/profiler.h
@@ -202,25 +202,25 @@
ThreadId tid() const { return tid_; }
void Clear() {
+ timestamp_ = 0;
port_ = ILLEGAL_PORT;
- pc_marker_ = 0;
+ tid_ = OSThread::kInvalidThreadId;
for (intptr_t i = 0; i < kStackBufferSizeInWords; i++) {
stack_buffer_[i] = 0;
}
+ for (intptr_t i = 0; i < kPCArraySizeInWords; i++) {
+ pc_array_[i] = 0;
+ }
vm_tag_ = VMTag::kInvalidTagId;
user_tag_ = UserTags::kDefaultUserTag;
- lr_ = 0;
- metadata_ = 0;
state_ = 0;
+ continuation_index_ = -1;
allocation_identity_hash_ = 0;
+#if defined(DART_USE_TCMALLOC) && defined(DEBUG)
native_allocation_address_ = 0;
native_allocation_size_bytes_ = 0;
- continuation_index_ = -1;
next_free_ = NULL;
- uword* pcs = GetPCArray();
- for (intptr_t i = 0; i < pcs_length_; i++) {
- pcs[i] = 0;
- }
+#endif
set_head_sample(true);
}
@@ -233,21 +233,19 @@
// Get stack trace entry.
uword At(intptr_t i) const {
ASSERT(i >= 0);
- ASSERT(i < pcs_length_);
- uword* pcs = GetPCArray();
- return pcs[i];
+ ASSERT(i < kPCArraySizeInWords);
+ return pc_array_[i];
}
// Set stack trace entry.
void SetAt(intptr_t i, uword pc) {
ASSERT(i >= 0);
- ASSERT(i < pcs_length_);
- uword* pcs = GetPCArray();
- pcs[i] = pc;
+ ASSERT(i < kPCArraySizeInWords);
+ pc_array_[i] = pc;
}
void DumpStackTrace() {
- for (intptr_t i = 0; i < pcs_length_; ++i) {
+ for (intptr_t i = 0; i < kPCArraySizeInWords; ++i) {
uintptr_t start = 0;
uword pc = At(i);
char* native_symbol_name =
@@ -270,14 +268,6 @@
uword user_tag() const { return user_tag_; }
void set_user_tag(uword tag) { user_tag_ = tag; }
- uword pc_marker() const { return pc_marker_; }
-
- void set_pc_marker(uword pc_marker) { pc_marker_ = pc_marker; }
-
- uword lr() const { return lr_; }
-
- void set_lr(uword link_register) { lr_ = link_register; }
-
bool leaf_frame_is_dart() const { return LeafFrameIsDart::decode(state_); }
void set_leaf_frame_is_dart(bool leaf_frame_is_dart) {
@@ -326,8 +316,8 @@
allocation_identity_hash_ = hash;
}
+#if defined(DART_USE_TCMALLOC) && defined(DEBUG)
uword native_allocation_address() const { return native_allocation_address_; }
-
void set_native_allocation_address(uword address) {
native_allocation_address_ = address;
}
@@ -335,13 +325,22 @@
uintptr_t native_allocation_size_bytes() const {
return native_allocation_size_bytes_;
}
-
void set_native_allocation_size_bytes(uintptr_t size) {
native_allocation_size_bytes_ = size;
}
Sample* next_free() const { return next_free_; }
void set_next_free(Sample* next_free) { next_free_ = next_free; }
+#else
+ uword native_allocation_address() const { return 0; }
+ void set_native_allocation_address(uword address) { UNREACHABLE(); }
+
+ uintptr_t native_allocation_size_bytes() const { return 0; }
+ void set_native_allocation_size_bytes(uintptr_t size) { UNREACHABLE(); }
+
+ Sample* next_free() const { return nullptr; }
+ void set_next_free(Sample* next_free) { UNREACHABLE(); }
+#endif // defined(DART_USE_TCMALLOC) && defined(DEBUG)
Thread::TaskKind thread_task() const { return ThreadTaskBit::decode(state_); }
@@ -368,7 +367,7 @@
intptr_t allocation_cid() const {
ASSERT(is_allocation_sample());
- return metadata_;
+ return metadata();
}
void set_head_sample(bool head_sample) {
@@ -377,25 +376,23 @@
bool head_sample() const { return HeadSampleBit::decode(state_); }
- void set_metadata(intptr_t metadata) { metadata_ = metadata; }
+ intptr_t metadata() const { return MetadataBits::decode(state_); }
+ void set_metadata(intptr_t metadata) {
+ state_ = MetadataBits::update(metadata, state_);
+ }
void SetAllocationCid(intptr_t cid) {
set_is_allocation_sample(true);
set_metadata(cid);
}
- static void Init();
+ static constexpr int kPCArraySizeInWords = 8;
+ uword* GetPCArray() { return &pc_array_[0]; }
- static intptr_t instance_size() { return instance_size_; }
-
- uword* GetPCArray() const;
-
- static const int kStackBufferSizeInWords = 2;
+ static constexpr int kStackBufferSizeInWords = 2;
uword* GetStackBuffer() { return &stack_buffer_[0]; }
private:
- static intptr_t instance_size_;
- static intptr_t pcs_length_;
enum StateBits {
kHeadSampleBit = 0,
kLeafFrameIsDartBit = 1,
@@ -406,42 +403,43 @@
kClassAllocationSampleBit = 6,
kContinuationSampleBit = 7,
kThreadTaskBit = 8, // 6 bits.
- kNextFreeBit = 14,
+ kMetadataBit = 14, // 16 bits.
+ kNextFreeBit = 30,
};
- class HeadSampleBit : public BitField<uword, bool, kHeadSampleBit, 1> {};
- class LeafFrameIsDart : public BitField<uword, bool, kLeafFrameIsDartBit, 1> {
- };
- class IgnoreBit : public BitField<uword, bool, kIgnoreBit, 1> {};
- class ExitFrameBit : public BitField<uword, bool, kExitFrameBit, 1> {};
+ class HeadSampleBit : public BitField<uint32_t, bool, kHeadSampleBit, 1> {};
+ class LeafFrameIsDart
+ : public BitField<uint32_t, bool, kLeafFrameIsDartBit, 1> {};
+ class IgnoreBit : public BitField<uint32_t, bool, kIgnoreBit, 1> {};
+ class ExitFrameBit : public BitField<uint32_t, bool, kExitFrameBit, 1> {};
class MissingFrameInsertedBit
- : public BitField<uword, bool, kMissingFrameInsertedBit, 1> {};
+ : public BitField<uint32_t, bool, kMissingFrameInsertedBit, 1> {};
class TruncatedTraceBit
- : public BitField<uword, bool, kTruncatedTraceBit, 1> {};
+ : public BitField<uint32_t, bool, kTruncatedTraceBit, 1> {};
class ClassAllocationSampleBit
- : public BitField<uword, bool, kClassAllocationSampleBit, 1> {};
+ : public BitField<uint32_t, bool, kClassAllocationSampleBit, 1> {};
class ContinuationSampleBit
- : public BitField<uword, bool, kContinuationSampleBit, 1> {};
+ : public BitField<uint32_t, bool, kContinuationSampleBit, 1> {};
class ThreadTaskBit
- : public BitField<uword, Thread::TaskKind, kThreadTaskBit, 6> {};
+ : public BitField<uint32_t, Thread::TaskKind, kThreadTaskBit, 6> {};
+ class MetadataBits : public BitField<uint32_t, intptr_t, kMetadataBit, 16> {};
int64_t timestamp_;
- ThreadId tid_;
Dart_Port port_;
- uword pc_marker_;
+ ThreadId tid_;
uword stack_buffer_[kStackBufferSizeInWords];
+ uword pc_array_[kPCArraySizeInWords];
uword vm_tag_;
uword user_tag_;
- uword metadata_;
- uword lr_;
- uword state_;
+ uint32_t state_;
+ int32_t continuation_index_;
uint32_t allocation_identity_hash_;
+
+#if defined(DART_USE_TCMALLOC) && defined(DEBUG)
uword native_allocation_address_;
uintptr_t native_allocation_size_bytes_;
- intptr_t continuation_index_;
Sample* next_free_;
+#endif
- /* There are a variable number of words that follow, the words hold the
- * sampled pc values. Access via GetPCArray() */
DISALLOW_COPY_AND_ASSIGN(Sample);
};
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 8d3185d..da4c33a 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -1567,6 +1567,7 @@
COMPRESSED_POINTER_FIELD(StringPtr, url)
VISIT_FROM(url)
COMPRESSED_POINTER_FIELD(StringPtr, resolved_url)
+ COMPRESSED_POINTER_FIELD(ArrayPtr, compile_time_constants)
COMPRESSED_POINTER_FIELD(TypedDataPtr, line_starts)
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
COMPRESSED_POINTER_FIELD(ExternalTypedDataPtr, constant_coverage)
@@ -1615,11 +1616,11 @@
#endif
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
- int32_t kernel_script_index_;
int64_t load_timestamp_;
+ int32_t kernel_script_index_;
#else
- int64_t load_timestamp_;
int32_t kernel_script_index_;
+ int64_t load_timestamp_;
#endif
};
diff --git a/runtime/vm/raw_object_fields.cc b/runtime/vm/raw_object_fields.cc
index 1b09c40..629d62b 100644
--- a/runtime/vm/raw_object_fields.cc
+++ b/runtime/vm/raw_object_fields.cc
@@ -43,6 +43,7 @@
F(Field, host_offset_or_field_id_) \
F(Script, url_) \
F(Script, resolved_url_) \
+ F(Script, compile_time_constants_) \
F(Script, line_starts_) \
F(Script, debug_positions_) \
F(Script, kernel_program_info_) \
diff --git a/tests/language/constructor/bodyless_wrong_arg_test.dart b/tests/language/constructor/bodyless_wrong_arg_test.dart
index 4e669d0..51f16f5 100644
--- a/tests/language/constructor/bodyless_wrong_arg_test.dart
+++ b/tests/language/constructor/bodyless_wrong_arg_test.dart
@@ -18,4 +18,6 @@
main() {
const C("str");
+//^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_EVAL_THROWS_EXCEPTION
}
diff --git a/tests/language/string/interpolation1_test.dart b/tests/language/string/interpolation1_test.dart
index 7f43236..d5eaea9 100644
--- a/tests/language/string/interpolation1_test.dart
+++ b/tests/language/string/interpolation1_test.dart
@@ -12,6 +12,8 @@
class StringInterpolation1NegativeTest {
// Dollar not followed by "{" or identifier.
static const DOLLAR = const A("$");
+ // [error line 14, column 33, length 3]
+ // [analyzer] COMPILE_TIME_ERROR.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH
// [error line 14, column 35, length 0]
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
// [cfe] A '$' has special meaning inside a string, and must be followed by an identifier or an expression in curly braces ({}).
diff --git a/tools/VERSION b/tools/VERSION
index 93fc29b..addd689 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 14
PATCH 0
-PRERELEASE 181
+PRERELEASE 182
PRERELEASE_PATCH 0
\ No newline at end of file