Version 2.12.0-114.0.dev
Merge commit '3e7b5b2e7b2a19bd01042647a4be0e1dd81236d5' into 'dev'
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index d466c551..54435dc 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -2057,9 +2057,37 @@
// If the variable isn't initialized, call the initializer and set it.
Fragment initialize(is_uninitialized);
initialize += BuildExpression();
- initialize += StoreLocal(position, variable);
- initialize += Drop();
- initialize += Goto(join);
+ if (variable->is_final()) {
+ // Late final variable, so check whether it has been assigned
+ // during initialization.
+ initialize += LoadLocal(variable);
+ TargetEntryInstr *is_uninitialized_after_init,
+ *is_initialized_after_init;
+ initialize += Constant(Object::sentinel());
+ initialize += flow_graph_builder_->BranchIfStrictEqual(
+ &is_uninitialized_after_init, &is_initialized_after_init);
+ {
+ // The variable is uninitialized, so store the initializer result.
+ Fragment store_result(is_uninitialized_after_init);
+ store_result += StoreLocal(position, variable);
+ store_result += Drop();
+ store_result += Goto(join);
+ }
+
+ {
+ // Already initialized, so throw a LateInitializationError.
+ Fragment already_assigned(is_initialized_after_init);
+ already_assigned += flow_graph_builder_->ThrowLateInitializationError(
+ position, "_throwLocalAssignedDuringInitialization",
+ variable->name());
+ already_assigned += Goto(join);
+ }
+ } else {
+ // Late non-final variable. Store the initializer result.
+ initialize += StoreLocal(position, variable);
+ initialize += Drop();
+ initialize += Goto(join);
+ }
} else {
// The variable has no initializer, so throw a LateInitializationError.
Fragment initialize(is_uninitialized);
diff --git a/sdk/lib/_internal/vm/lib/array.dart b/sdk/lib/_internal/vm/lib/array.dart
index 643faf4..99e04aa 100644
--- a/sdk/lib/_internal/vm/lib/array.dart
+++ b/sdk/lib/_internal/vm/lib/array.dart
@@ -35,6 +35,72 @@
return result;
}
+ // Specialization of List.of constructor for growable == false.
+ factory _List.of(Iterable<E> elements) {
+ if (elements is _GrowableList) {
+ return _List._ofGrowableList(unsafeCast(elements));
+ }
+ if (elements is _List) {
+ return _List._ofList(unsafeCast(elements));
+ }
+ if (elements is _ImmutableList) {
+ return _List._ofImmutableList(unsafeCast(elements));
+ }
+ if (elements is EfficientLengthIterable) {
+ return _List._ofEfficientLengthIterable(unsafeCast(elements));
+ }
+ return _List._ofOther(elements);
+ }
+
+ factory _List._ofGrowableList(_GrowableList<E> elements) {
+ final int length = elements.length;
+ final list = _List<E>(length);
+ for (int i = 0; i < length; i++) {
+ list[i] = elements[i];
+ }
+ return list;
+ }
+
+ factory _List._ofList(_List<E> elements) {
+ final int length = elements.length;
+ final list = _List<E>(length);
+ for (int i = 0; i < length; i++) {
+ list[i] = elements[i];
+ }
+ return list;
+ }
+
+ factory _List._ofImmutableList(_ImmutableList<E> elements) {
+ final int length = elements.length;
+ final list = _List<E>(length);
+ for (int i = 0; i < length; i++) {
+ list[i] = elements[i];
+ }
+ return list;
+ }
+
+ factory _List._ofEfficientLengthIterable(
+ EfficientLengthIterable<E> elements) {
+ final int length = elements.length;
+ final list = _List<E>(length);
+ if (length > 0) {
+ int i = 0;
+ for (var element in elements) {
+ list[i++] = element;
+ }
+ if (i != length) throw ConcurrentModificationError(elements);
+ }
+ return list;
+ }
+
+ factory _List._ofOther(Iterable<E> elements) {
+ // The static type of `makeListFixedLength` is `List<E>`, not `_List<E>`,
+ // but we know that is what it does. `makeListFixedLength` is too generally
+ // typed since it is available on the web platform which has different
+ // system List types.
+ return unsafeCast(makeListFixedLength(_GrowableList<E>._ofOther(elements)));
+ }
+
@pragma("vm:recognized", "graph-intrinsic")
E operator [](int index) native "List_getIndexed";
diff --git a/sdk/lib/_internal/vm/lib/array_patch.dart b/sdk/lib/_internal/vm/lib/array_patch.dart
index df03cf6..e935025 100644
--- a/sdk/lib/_internal/vm/lib/array_patch.dart
+++ b/sdk/lib/_internal/vm/lib/array_patch.dart
@@ -46,44 +46,11 @@
@patch
factory List.of(Iterable<E> elements, {bool growable: true}) {
- final cid = ClassID.getID(elements);
- final isVMList = (cid == ClassID.cidArray) ||
- (cid == ClassID.cidGrowableObjectArray) ||
- (cid == ClassID.cidImmutableArray);
-
- if (isVMList) {
- final ListBase<E> elementsAsList = elements as ListBase<E>;
- final int length = elementsAsList.length;
- final list =
- growable ? new _GrowableList<E>(length) : new _List<E>(length);
- if (length > 0) {
- for (int i = 0; i < length; i++) {
- list[i] = elementsAsList[i];
- }
- }
- return list;
+ if (growable) {
+ return _GrowableList.of(elements);
+ } else {
+ return _List.of(elements);
}
-
- if (elements is EfficientLengthIterable) {
- final int length = elements.length;
- final list =
- growable ? new _GrowableList<E>(length) : new _List<E>(length);
- if (length > 0) {
- int i = 0;
- for (var element in elements) {
- list[i++] = element;
- }
- if (i != length) throw ConcurrentModificationError(elements);
- }
- return list;
- }
-
- final list = <E>[];
- for (var elements in elements) {
- list.add(elements);
- }
- if (growable) return list;
- return makeListFixedLength(list);
}
@patch
diff --git a/sdk/lib/_internal/vm/lib/growable_array.dart b/sdk/lib/_internal/vm/lib/growable_array.dart
index 416e7bd..537fb34 100644
--- a/sdk/lib/_internal/vm/lib/growable_array.dart
+++ b/sdk/lib/_internal/vm/lib/growable_array.dart
@@ -130,6 +130,72 @@
return result;
}
+ // Specialization of List.of constructor for growable == true.
+ factory _GrowableList.of(Iterable<T> elements) {
+ if (elements is _GrowableList) {
+ return _GrowableList._ofGrowableList(unsafeCast(elements));
+ }
+ if (elements is _List) {
+ return _GrowableList._ofList(unsafeCast(elements));
+ }
+ if (elements is _ImmutableList) {
+ return _GrowableList._ofImmutableList(unsafeCast(elements));
+ }
+ if (elements is EfficientLengthIterable) {
+ return _GrowableList._ofEfficientLengthIterable(unsafeCast(elements));
+ }
+ return _GrowableList._ofOther(elements);
+ }
+
+ factory _GrowableList._ofList(_List<T> elements) {
+ final int length = elements.length;
+ final list = _GrowableList<T>(length);
+ for (int i = 0; i < length; i++) {
+ list[i] = elements[i];
+ }
+ return list;
+ }
+
+ factory _GrowableList._ofGrowableList(_GrowableList<T> elements) {
+ final int length = elements.length;
+ final list = _GrowableList<T>(length);
+ for (int i = 0; i < length; i++) {
+ list[i] = elements[i];
+ }
+ return list;
+ }
+
+ factory _GrowableList._ofImmutableList(_ImmutableList<T> elements) {
+ final int length = elements.length;
+ final list = _GrowableList<T>(length);
+ for (int i = 0; i < length; i++) {
+ list[i] = elements[i];
+ }
+ return list;
+ }
+
+ factory _GrowableList._ofEfficientLengthIterable(
+ EfficientLengthIterable<T> elements) {
+ final int length = elements.length;
+ final list = _GrowableList<T>(length);
+ if (length > 0) {
+ int i = 0;
+ for (var element in elements) {
+ list[i++] = element;
+ }
+ if (i != length) throw ConcurrentModificationError(elements);
+ }
+ return list;
+ }
+
+ factory _GrowableList._ofOther(Iterable<T> elements) {
+ final list = _GrowableList<T>(0);
+ for (var elements in elements) {
+ list.add(elements);
+ }
+ return list;
+ }
+
@pragma("vm:recognized", "asm-intrinsic")
@pragma("vm:exact-result-type",
<dynamic>[_GrowableList, "result-type-uses-passed-type-arguments"])
diff --git a/sdk/lib/_internal/vm/lib/internal_patch.dart b/sdk/lib/_internal/vm/lib/internal_patch.dart
index 24f9461..f1d22c9 100644
--- a/sdk/lib/_internal/vm/lib/internal_patch.dart
+++ b/sdk/lib/_internal/vm/lib/internal_patch.dart
@@ -212,4 +212,9 @@
static _throwLocalAlreadyInitialized(String localName) {
throw new LateError.localAI(localName);
}
+
+ @pragma("vm:entry-point")
+ static _throwLocalAssignedDuringInitialization(String localName) {
+ throw new LateError.localADI(localName);
+ }
}
diff --git a/tests/dart2js/native/fake_thing_test.dart b/tests/dart2js/native/fake_thing_test.dart
index 0131821..542a5ca 100644
--- a/tests/dart2js/native/fake_thing_test.dart
+++ b/tests/dart2js/native/fake_thing_test.dart
@@ -26,13 +26,9 @@
})()""");
}
-inscrutable(x) {
- if (new DateTime.now().millisecondsSinceEpoch == 0) {
- return x;
- } else {
- return 42;
- }
-}
+@pragma('dart2js:noInline')
+@pragma('dart2js:assumeDynamic')
+inscrutable(x) => x;
main() {
setup();
diff --git a/tests/dart2js_2/native/fake_thing_test.dart b/tests/dart2js_2/native/fake_thing_test.dart
index 8e1ca18..63fda12 100644
--- a/tests/dart2js_2/native/fake_thing_test.dart
+++ b/tests/dart2js_2/native/fake_thing_test.dart
@@ -28,13 +28,9 @@
})()""");
}
-inscrutable(x) {
- if (new DateTime.now().millisecondsSinceEpoch == 0) {
- return x;
- } else {
- return 42;
- }
-}
+@pragma('dart2js:noInline')
+@pragma('dart2js:assumeDynamic')
+inscrutable(x) => x;
main() {
setup();
diff --git a/tests/language/nnbd/syntax/late_modifier_runtime_error_test.dart b/tests/language/nnbd/syntax/late_modifier_runtime_error_test.dart
index 851d225..c410775 100644
--- a/tests/language/nnbd/syntax/late_modifier_runtime_error_test.dart
+++ b/tests/language/nnbd/syntax/late_modifier_runtime_error_test.dart
@@ -106,7 +106,8 @@
Expect.throws(() {
local2 = 2;
}, (e) => isValidError(e, "Local 'local2' has already been initialized."));
- // Uncomment after https://github.com/dart-lang/sdk/issues/44372 is fixed.
- // Expect.throws(() => local3,
- // (e) => isValidError(e, "Local 'local3' has already been initialized."));
+ Expect.throws(
+ () => local3,
+ (e) => isValidError(
+ e, "Local 'local3' has been assigned during initialization."));
}
diff --git a/tools/VERSION b/tools/VERSION
index 5397bdc..41ab758 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 12
PATCH 0
-PRERELEASE 113
+PRERELEASE 114
PRERELEASE_PATCH 0
\ No newline at end of file