mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 23:49:47 +00:00
[test] Run late field tests in optimised mode
Fix the tests by disabling the optimisation that turns getter calls into raw gets if the field is late, and by calling recording the null init store in bytecode mode. Change-Id: I8f12e3237cd32c890b5cef8d00c32940e937330d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/134180 Commit-Queue: Liam Appelbe <liama@google.com> Reviewed-by: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
parent
30e80f0a64
commit
a793c36c77
|
@ -738,6 +738,10 @@ bool CallSpecializer::TryInlineImplicitInstanceGetter(InstanceCallInstr* call) {
|
|||
if (field.needs_load_guard()) {
|
||||
return false;
|
||||
}
|
||||
if (field.is_late()) {
|
||||
// TODO(http://dartbug.com/40447): Inline implicit getters for late fields.
|
||||
return false;
|
||||
}
|
||||
if (should_clone_fields_) {
|
||||
field = field.CloneFromOriginal();
|
||||
}
|
||||
|
|
|
@ -2017,7 +2017,14 @@ void BytecodeReaderHelper::ReadFieldDeclarations(const Class& cls,
|
|||
field.set_is_extension_member(is_extension_member);
|
||||
field.set_has_initializer(has_initializer);
|
||||
|
||||
if (!has_nontrivial_initializer) {
|
||||
if (has_nontrivial_initializer) {
|
||||
if (field.is_late()) {
|
||||
// Late fields are initialized to Object::sentinel, which is a flavor of
|
||||
// null. So we need to record that store so that the field guard doesn't
|
||||
// prematurely optimise out the late field's sentinel checking logic.
|
||||
field.RecordStore(Object::null_object());
|
||||
}
|
||||
} else {
|
||||
value ^= ReadObject();
|
||||
if (is_static) {
|
||||
if (field.is_late() && !has_initializer) {
|
||||
|
|
|
@ -200,10 +200,6 @@ Fragment StreamingFlowGraphBuilder::BuildLateFieldInitializer(
|
|||
}
|
||||
return Fragment();
|
||||
}
|
||||
// Late fields are initialized to Object::sentinel, which is a flavor of null.
|
||||
// So we need to record that store so that the field guard doesn't prematurely
|
||||
// optimise out the late field's sentinel checking logic.
|
||||
field.RecordStore(Object::null_object());
|
||||
|
||||
Fragment instructions;
|
||||
instructions += LoadLocal(parsed_function()->receiver_var());
|
||||
|
|
|
@ -2121,6 +2121,13 @@ void KernelLoader::GenerateFieldAccessors(const Class& klass,
|
|||
}
|
||||
ASSERT(field.NeedsGetter());
|
||||
|
||||
if (field.is_late() && field.has_nontrivial_initializer()) {
|
||||
// Late fields are initialized to Object::sentinel, which is a flavor of
|
||||
// null. So we need to record that store so that the field guard doesn't
|
||||
// prematurely optimise out the late field's sentinel checking logic.
|
||||
field.RecordStore(Object::null_object());
|
||||
}
|
||||
|
||||
const String& getter_name = H.DartGetterName(field_helper->canonical_name_);
|
||||
const Object& script_class =
|
||||
ClassForScriptAt(klass, field_helper->source_uri_index_);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
// SharedOptions=--enable-experiment=non-nullable
|
||||
// VMOptions=--optimization_counter_threshold=10
|
||||
import 'package:expect/expect.dart';
|
||||
|
||||
int initCalls = 0;
|
||||
|
@ -25,45 +26,48 @@ class B {
|
|||
}
|
||||
|
||||
main() {
|
||||
Base a = A();
|
||||
Expect.equals(0, initCalls);
|
||||
Expect.equals(123, a.fieldWithInit);
|
||||
Expect.equals(1, initCalls);
|
||||
Expect.equals(123, a.fieldWithInit);
|
||||
Expect.equals(1, initCalls);
|
||||
// Setting Base.fieldWithInit once is ok but causes no calls to init().
|
||||
a.fieldWithInit = 456;
|
||||
Expect.equals(456, (a as A).superFieldWithInit);
|
||||
Expect.equals(123, a.fieldWithInit);
|
||||
Expect.equals(1, initCalls);
|
||||
// Setting Base.fieldWithInit twice throws an error.
|
||||
Expect.throws(() => {a.fieldWithInit = 789},
|
||||
(error) => error is LateInitializationError);
|
||||
Expect.equals(1, initCalls);
|
||||
Expect.equals(123, a.fieldWithInit);
|
||||
Expect.equals(1, initCalls);
|
||||
initCalls = 0;
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
Base a = A();
|
||||
Expect.equals(0, initCalls);
|
||||
Expect.equals(123, a.fieldWithInit);
|
||||
Expect.equals(1, initCalls);
|
||||
Expect.equals(123, a.fieldWithInit);
|
||||
Expect.equals(1, initCalls);
|
||||
// Setting Base.fieldWithInit once is ok but causes no calls to init().
|
||||
a.fieldWithInit = 456;
|
||||
Expect.equals(456, (a as A).superFieldWithInit);
|
||||
Expect.equals(123, a.fieldWithInit);
|
||||
Expect.equals(1, initCalls);
|
||||
// Setting Base.fieldWithInit twice throws an error.
|
||||
Expect.throws(() => {a.fieldWithInit = 789},
|
||||
(error) => error is LateInitializationError);
|
||||
Expect.equals(1, initCalls);
|
||||
Expect.equals(123, a.fieldWithInit);
|
||||
Expect.equals(1, initCalls);
|
||||
initCalls = 0;
|
||||
|
||||
Base a2 = A();
|
||||
Expect.equals(0, initCalls);
|
||||
// Setting Base.fieldWithInit once is ok but causes no calls to init().
|
||||
a2.fieldWithInit = 456;
|
||||
Expect.equals(456, (a as A).superFieldWithInit);
|
||||
Expect.equals(0, initCalls);
|
||||
// Setting Base.fieldWithInit twice throws an error.
|
||||
Expect.throws(() => {a2.fieldWithInit = 789},
|
||||
(error) => error is LateInitializationError);
|
||||
Expect.equals(0, initCalls);
|
||||
Expect.equals(123, a2.fieldWithInit);
|
||||
Expect.equals(456, (a as A).superFieldWithInit);
|
||||
Expect.equals(1, initCalls);
|
||||
Base a2 = A();
|
||||
Expect.equals(0, initCalls);
|
||||
// Setting Base.fieldWithInit once is ok but causes no calls to init().
|
||||
a2.fieldWithInit = 456;
|
||||
Expect.equals(456, (a as A).superFieldWithInit);
|
||||
Expect.equals(0, initCalls);
|
||||
// Setting Base.fieldWithInit twice throws an error.
|
||||
Expect.throws(() => {a2.fieldWithInit = 789},
|
||||
(error) => error is LateInitializationError);
|
||||
Expect.equals(0, initCalls);
|
||||
Expect.equals(123, a2.fieldWithInit);
|
||||
Expect.equals(456, (a as A).superFieldWithInit);
|
||||
Expect.equals(1, initCalls);
|
||||
|
||||
B b = B();
|
||||
Expect.throws(
|
||||
() => b.fieldWithNoInit, (error) => error is LateInitializationError);
|
||||
b.fieldWithNoInit = 123;
|
||||
Expect.equals(123, b.fieldWithNoInit);
|
||||
Expect.throws(() => {b.fieldWithNoInit = 456},
|
||||
(error) => error is LateInitializationError);
|
||||
Expect.equals(123, b.fieldWithNoInit);
|
||||
B b = B();
|
||||
Expect.throws(
|
||||
() => b.fieldWithNoInit, (error) => error is LateInitializationError);
|
||||
b.fieldWithNoInit = 123;
|
||||
Expect.equals(123, b.fieldWithNoInit);
|
||||
Expect.throws(() => {b.fieldWithNoInit = 456},
|
||||
(error) => error is LateInitializationError);
|
||||
Expect.equals(123, b.fieldWithNoInit);
|
||||
initCalls = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
// SharedOptions=--enable-experiment=non-nullable
|
||||
// VMOptions=--optimization_counter_threshold=10
|
||||
import 'package:expect/expect.dart';
|
||||
|
||||
int initCalls = 0;
|
||||
|
@ -12,28 +13,31 @@ int init() {
|
|||
}
|
||||
|
||||
main() {
|
||||
late final int fieldWithInit = init();
|
||||
Expect.equals(0, initCalls);
|
||||
Expect.equals(123, fieldWithInit);
|
||||
Expect.equals(1, initCalls);
|
||||
Expect.equals(123, fieldWithInit);
|
||||
Expect.equals(1, initCalls);
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
late final int fieldWithInit = init();
|
||||
Expect.equals(0, initCalls);
|
||||
Expect.equals(123, fieldWithInit);
|
||||
Expect.equals(1, initCalls);
|
||||
Expect.equals(123, fieldWithInit);
|
||||
Expect.equals(1, initCalls);
|
||||
|
||||
late final int fieldWithNoInit;
|
||||
Expect.throws(
|
||||
() => fieldWithNoInit,
|
||||
(error) => error is LateInitializationError,
|
||||
);
|
||||
// Confuse the definite assignment analysis.
|
||||
if (1 > 0) {
|
||||
fieldWithNoInit = 123;
|
||||
late final int fieldWithNoInit;
|
||||
Expect.throws(
|
||||
() => fieldWithNoInit,
|
||||
(error) => error is LateInitializationError,
|
||||
);
|
||||
// Confuse the definite assignment analysis.
|
||||
if (1 > 0) {
|
||||
fieldWithNoInit = 123;
|
||||
}
|
||||
Expect.equals(123, fieldWithNoInit);
|
||||
Expect.throws(
|
||||
() {
|
||||
fieldWithNoInit = 456;
|
||||
},
|
||||
(error) => error is LateInitializationError,
|
||||
);
|
||||
Expect.equals(123, fieldWithNoInit);
|
||||
initCalls = 0;
|
||||
}
|
||||
Expect.equals(123, fieldWithNoInit);
|
||||
Expect.throws(
|
||||
() {
|
||||
fieldWithNoInit = 456;
|
||||
},
|
||||
(error) => error is LateInitializationError,
|
||||
);
|
||||
Expect.equals(123, fieldWithNoInit);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
// SharedOptions=--enable-experiment=non-nullable
|
||||
// VMOptions=--optimization_counter_threshold=10
|
||||
import 'package:expect/expect.dart';
|
||||
|
||||
int initCalls = 0;
|
||||
|
@ -12,59 +13,62 @@ int init() {
|
|||
}
|
||||
|
||||
main() {
|
||||
late int varWithInit = init();
|
||||
late int varWithTrivialInit = 123;
|
||||
late int? varWithNullInit = null;
|
||||
late int varWithNoInit;
|
||||
Expect.equals(0, initCalls);
|
||||
Expect.equals(123, varWithInit);
|
||||
Expect.equals(123, varWithTrivialInit);
|
||||
Expect.equals(null, varWithNullInit);
|
||||
Expect.throws(
|
||||
() => varWithNoInit, (error) => error is LateInitializationError);
|
||||
Expect.equals(1, initCalls);
|
||||
Expect.equals(123, varWithInit);
|
||||
Expect.equals(123, varWithTrivialInit);
|
||||
Expect.equals(null, varWithNullInit);
|
||||
Expect.throws(
|
||||
() => varWithNoInit, (error) => error is LateInitializationError);
|
||||
Expect.equals(1, initCalls);
|
||||
varWithInit = 456;
|
||||
varWithTrivialInit = 456;
|
||||
varWithNullInit = 456;
|
||||
varWithNoInit = 456;
|
||||
Expect.equals(1, initCalls);
|
||||
Expect.equals(456, varWithInit);
|
||||
Expect.equals(456, varWithTrivialInit);
|
||||
Expect.equals(456, varWithNullInit);
|
||||
Expect.equals(456, varWithNoInit);
|
||||
Expect.equals(1, initCalls);
|
||||
initCalls = 0;
|
||||
|
||||
late int varWithInit2 = init();
|
||||
Expect.equals(0, initCalls);
|
||||
varWithInit2 = 456;
|
||||
Expect.equals(0, initCalls);
|
||||
Expect.equals(456, varWithInit2);
|
||||
Expect.equals(0, initCalls);
|
||||
|
||||
late int? varWithInit3 = init();
|
||||
Expect.equals(0, initCalls);
|
||||
varWithInit3 = null;
|
||||
Expect.equals(0, initCalls);
|
||||
Expect.equals(null, varWithInit3);
|
||||
Expect.equals(0, initCalls);
|
||||
|
||||
late int varWithCondInit = null ?? init();
|
||||
var lambda = () {
|
||||
Expect.equals(123, varWithCondInit);
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
late int varWithInit = init();
|
||||
late int varWithTrivialInit = 123;
|
||||
late int? varWithNullInit = null;
|
||||
late int varWithNoInit;
|
||||
Expect.equals(0, initCalls);
|
||||
Expect.equals(123, varWithInit);
|
||||
Expect.equals(123, varWithTrivialInit);
|
||||
Expect.equals(null, varWithNullInit);
|
||||
Expect.throws(
|
||||
() => varWithNoInit, (error) => error is LateInitializationError);
|
||||
Expect.equals(1, initCalls);
|
||||
};
|
||||
lambda();
|
||||
lambda();
|
||||
lambda();
|
||||
initCalls = 0;
|
||||
Expect.equals(123, varWithInit);
|
||||
Expect.equals(123, varWithTrivialInit);
|
||||
Expect.equals(null, varWithNullInit);
|
||||
Expect.throws(
|
||||
() => varWithNoInit, (error) => error is LateInitializationError);
|
||||
Expect.equals(1, initCalls);
|
||||
varWithInit = 456;
|
||||
varWithTrivialInit = 456;
|
||||
varWithNullInit = 456;
|
||||
varWithNoInit = 456;
|
||||
Expect.equals(1, initCalls);
|
||||
Expect.equals(456, varWithInit);
|
||||
Expect.equals(456, varWithTrivialInit);
|
||||
Expect.equals(456, varWithNullInit);
|
||||
Expect.equals(456, varWithNoInit);
|
||||
Expect.equals(1, initCalls);
|
||||
initCalls = 0;
|
||||
|
||||
if (true) late int varNotInBlock = init();
|
||||
Expect.equals(0, initCalls);
|
||||
late int varWithInit2 = init();
|
||||
Expect.equals(0, initCalls);
|
||||
varWithInit2 = 456;
|
||||
Expect.equals(0, initCalls);
|
||||
Expect.equals(456, varWithInit2);
|
||||
Expect.equals(0, initCalls);
|
||||
|
||||
late int? varWithInit3 = init();
|
||||
Expect.equals(0, initCalls);
|
||||
varWithInit3 = null;
|
||||
Expect.equals(0, initCalls);
|
||||
Expect.equals(null, varWithInit3);
|
||||
Expect.equals(0, initCalls);
|
||||
|
||||
late int varWithCondInit = null ?? init();
|
||||
var lambda = () {
|
||||
Expect.equals(123, varWithCondInit);
|
||||
Expect.equals(1, initCalls);
|
||||
};
|
||||
lambda();
|
||||
lambda();
|
||||
lambda();
|
||||
initCalls = 0;
|
||||
|
||||
if (true) late int varNotInBlock = init();
|
||||
Expect.equals(0, initCalls);
|
||||
initCalls = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
// SharedOptions=--enable-experiment=non-nullable
|
||||
// VMOptions=--optimization_counter_threshold=10
|
||||
import 'package:expect/expect.dart';
|
||||
|
||||
int initCalls = 0;
|
||||
|
@ -19,46 +20,49 @@ class A {
|
|||
}
|
||||
|
||||
main() {
|
||||
// Late, non-final, with init.
|
||||
var a = A();
|
||||
Expect.equals(0, initCalls);
|
||||
Expect.equals(123, a.fieldWithInit);
|
||||
Expect.equals(123, a.fieldWithTrivialInit);
|
||||
Expect.equals(null, a.fieldWithNullInit);
|
||||
Expect.throws(
|
||||
() => a.fieldWithNoInit, (error) => error is LateInitializationError);
|
||||
Expect.equals(1, initCalls);
|
||||
Expect.equals(123, a.fieldWithInit);
|
||||
Expect.equals(123, a.fieldWithTrivialInit);
|
||||
Expect.equals(null, a.fieldWithNullInit);
|
||||
Expect.throws(
|
||||
() => a.fieldWithNoInit, (error) => error is LateInitializationError);
|
||||
Expect.equals(1, initCalls);
|
||||
a.fieldWithInit = 456;
|
||||
a.fieldWithTrivialInit = 456;
|
||||
a.fieldWithNullInit = 456;
|
||||
a.fieldWithNoInit = 456;
|
||||
Expect.equals(1, initCalls);
|
||||
Expect.equals(456, a.fieldWithInit);
|
||||
Expect.equals(456, a.fieldWithTrivialInit);
|
||||
Expect.equals(456, a.fieldWithNullInit);
|
||||
Expect.equals(456, a.fieldWithNoInit);
|
||||
Expect.equals(1, initCalls);
|
||||
initCalls = 0;
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
// Late, non-final, with init.
|
||||
var a = A();
|
||||
Expect.equals(0, initCalls);
|
||||
Expect.equals(123, a.fieldWithInit);
|
||||
Expect.equals(123, a.fieldWithTrivialInit);
|
||||
Expect.equals(null, a.fieldWithNullInit);
|
||||
Expect.throws(
|
||||
() => a.fieldWithNoInit, (error) => error is LateInitializationError);
|
||||
Expect.equals(1, initCalls);
|
||||
Expect.equals(123, a.fieldWithInit);
|
||||
Expect.equals(123, a.fieldWithTrivialInit);
|
||||
Expect.equals(null, a.fieldWithNullInit);
|
||||
Expect.throws(
|
||||
() => a.fieldWithNoInit, (error) => error is LateInitializationError);
|
||||
Expect.equals(1, initCalls);
|
||||
a.fieldWithInit = 456;
|
||||
a.fieldWithTrivialInit = 456;
|
||||
a.fieldWithNullInit = 456;
|
||||
a.fieldWithNoInit = 456;
|
||||
Expect.equals(1, initCalls);
|
||||
Expect.equals(456, a.fieldWithInit);
|
||||
Expect.equals(456, a.fieldWithTrivialInit);
|
||||
Expect.equals(456, a.fieldWithNullInit);
|
||||
Expect.equals(456, a.fieldWithNoInit);
|
||||
Expect.equals(1, initCalls);
|
||||
initCalls = 0;
|
||||
|
||||
// Late, non-final, with init that's pre-empted by setter.
|
||||
var b = A();
|
||||
Expect.equals(0, initCalls);
|
||||
b.fieldWithInit = 456;
|
||||
Expect.equals(0, initCalls);
|
||||
Expect.equals(456, b.fieldWithInit);
|
||||
Expect.equals(0, initCalls);
|
||||
// Late, non-final, with init that's pre-empted by setter.
|
||||
var b = A();
|
||||
Expect.equals(0, initCalls);
|
||||
b.fieldWithInit = 456;
|
||||
Expect.equals(0, initCalls);
|
||||
Expect.equals(456, b.fieldWithInit);
|
||||
Expect.equals(0, initCalls);
|
||||
|
||||
// Late, non-final, with init that's pre-empted by null setter.
|
||||
var c = A();
|
||||
Expect.equals(0, initCalls);
|
||||
c.fieldWithInit = null;
|
||||
Expect.equals(0, initCalls);
|
||||
Expect.equals(null, c.fieldWithInit);
|
||||
Expect.equals(0, initCalls);
|
||||
// Late, non-final, with init that's pre-empted by null setter.
|
||||
var c = A();
|
||||
Expect.equals(0, initCalls);
|
||||
c.fieldWithInit = null;
|
||||
Expect.equals(0, initCalls);
|
||||
Expect.equals(null, c.fieldWithInit);
|
||||
Expect.equals(0, initCalls);
|
||||
initCalls = 0;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue