Skip to content

Commit 8629563

Browse files
mralephcommit-bot@chromium.org
authored andcommitted
[vm] Fix few issues with field exactness tracking.
- Don't add dependency on fields that are either unitialized or already marked as non guarded (guarded cid is kIllegalCid in the first case and kDynamicCid in the second case). - Exit early from FieldStore if guarded_cid is kDynamicCid (or we are storing null into a nullable field). - Don't track exactness of fields which have function type type. Also move logic for starting to track fields into class_finalizer because we need resolved field types to make our decisions. Change-Id: I164b42abe3108a70b0769f4c78d92459b4e78883 Reviewed-on: https://dart-review.googlesource.com/70620 Commit-Queue: Vyacheslav Egorov <[email protected]> Reviewed-by: Martin Kustermann <[email protected]>
1 parent 9085009 commit 8629563

File tree

5 files changed

+49
-65
lines changed

5 files changed

+49
-65
lines changed

runtime/vm/class_finalizer.cc

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1582,6 +1582,25 @@ void ClassFinalizer::FinalizeUpperBounds(const Class& cls,
15821582
}
15831583
}
15841584

1585+
#if defined(TARGET_ARCH_X64)
1586+
static bool IsPotentialExactGeneric(const AbstractType& type) {
1587+
// TODO(dartbug.com/34170) Investigate supporting this for fields with types
1588+
// that depend on type parameters of the enclosing class.
1589+
if (type.IsType() && !type.IsFunctionType() && !type.IsDartFunctionType() &&
1590+
type.IsInstantiated()) {
1591+
const Class& cls = Class::Handle(type.type_class());
1592+
return cls.IsGeneric();
1593+
}
1594+
1595+
return false;
1596+
}
1597+
#else
1598+
// TODO(dartbug.com/34170) Support other architectures.
1599+
static bool IsPotentialExactGeneric(const AbstractType& type) {
1600+
return false;
1601+
}
1602+
#endif
1603+
15851604
void ClassFinalizer::ResolveAndFinalizeMemberTypes(const Class& cls) {
15861605
// Note that getters and setters are explicitly listed as such in the list of
15871606
// functions of a class, so we do not need to consider fields as implicitly
@@ -1605,6 +1624,7 @@ void ClassFinalizer::ResolveAndFinalizeMemberTypes(const Class& cls) {
16051624
// instance method.
16061625

16071626
// Resolve type of fields and check for conflicts in super classes.
1627+
Isolate* isolate = Isolate::Current();
16081628
Zone* zone = Thread::Current()->zone();
16091629
Array& array = Array::Handle(zone, cls.fields());
16101630
Field& field = Field::Handle(zone);
@@ -1614,11 +1634,16 @@ void ClassFinalizer::ResolveAndFinalizeMemberTypes(const Class& cls) {
16141634
String& other_name = String::Handle(zone);
16151635
Class& super_class = Class::Handle(zone);
16161636
const intptr_t num_fields = array.Length();
1637+
const bool track_exactness = isolate->strong() && isolate->use_field_guards();
16171638
for (intptr_t i = 0; i < num_fields; i++) {
16181639
field ^= array.At(i);
16191640
type = field.type();
16201641
type = FinalizeType(cls, type);
16211642
field.SetFieldType(type);
1643+
if (track_exactness && IsPotentialExactGeneric(type)) {
1644+
field.set_static_type_exactness_state(
1645+
StaticTypeExactnessState::Unitialized());
1646+
}
16221647
name = field.name();
16231648
if (field.is_static()) {
16241649
getter_name = Field::GetterSymbol(name);
@@ -1676,7 +1701,7 @@ void ClassFinalizer::ResolveAndFinalizeMemberTypes(const Class& cls) {
16761701
(!type.IsDynamicType() &&
16771702
!const_value.IsInstanceOf(type, Object::null_type_arguments(),
16781703
Object::null_type_arguments(), &error))) {
1679-
if (Isolate::Current()->error_on_bad_type()) {
1704+
if (isolate->error_on_bad_type()) {
16801705
const AbstractType& const_value_type =
16811706
AbstractType::Handle(zone, const_value.GetType(Heap::kNew));
16821707
const String& const_value_type_name =
@@ -1718,7 +1743,6 @@ void ClassFinalizer::ResolveAndFinalizeMemberTypes(const Class& cls) {
17181743
// If we check for bad overrides, collect interfaces, super interfaces, and
17191744
// super classes of this class.
17201745
GrowableArray<const Class*> interfaces(zone, 4);
1721-
Isolate* isolate = Isolate::Current();
17221746
if (isolate->error_on_bad_override() && !isolate->strong()) {
17231747
CollectInterfaces(cls, &interfaces);
17241748
// Include superclasses in list of interfaces and super interfaces.

runtime/vm/compiler/backend/il.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5164,6 +5164,7 @@ class LoadFieldInstr : public TemplateDefinition<1, NoThrow> {
51645164
native_field_(nullptr),
51655165
field_(field),
51665166
token_pos_(token_pos) {
5167+
ASSERT(Class::Handle(field->Owner()).is_finalized());
51675168
ASSERT(field->IsZoneHandle());
51685169
// May be null if field is not an instance.
51695170
ASSERT(type.IsZoneHandle() || type.IsReadOnlyHandle());

runtime/vm/kernel_loader.cc

Lines changed: 0 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1239,50 +1239,6 @@ Class& KernelLoader::LoadClass(const Library& library,
12391239
return klass;
12401240
}
12411241

1242-
#if defined(TARGET_ARCH_X64)
1243-
static bool ReferencesAnyTypeArguments(const AbstractType& type) {
1244-
if (type.IsTypeRef()) {
1245-
return false;
1246-
}
1247-
1248-
if (type.IsType()) {
1249-
const TypeArguments& args =
1250-
TypeArguments::Handle(Type::Cast(type).arguments());
1251-
AbstractType& arg = AbstractType::Handle();
1252-
for (intptr_t i = 0; i < args.Length(); i++) {
1253-
arg = args.TypeAt(i);
1254-
if (ReferencesAnyTypeArguments(arg)) {
1255-
return true;
1256-
}
1257-
}
1258-
}
1259-
1260-
return type.IsTypeParameter();
1261-
}
1262-
1263-
static bool IsPotentialExactGeneric(const AbstractType& type) {
1264-
if (type.IsType()) {
1265-
const TypeArguments& args =
1266-
TypeArguments::Handle(Type::Cast(type).arguments());
1267-
if (args.Length() == 0) {
1268-
return false;
1269-
}
1270-
1271-
// TODO(dartbug.com/34170) Investigate supporting this for
1272-
// fields with types that depend on type parameters
1273-
// of the enclosoing class.
1274-
return !ReferencesAnyTypeArguments(type);
1275-
}
1276-
1277-
return false;
1278-
}
1279-
#else
1280-
// TODO(dartbug.com/34170) Support other architectures.
1281-
static bool IsPotentialExactGeneric(const AbstractType& type) {
1282-
return false;
1283-
}
1284-
#endif
1285-
12861242
void KernelLoader::FinishClassLoading(const Class& klass,
12871243
const Library& library,
12881244
const Class& toplevel_class,
@@ -1344,11 +1300,6 @@ void KernelLoader::FinishClassLoading(const Class& klass,
13441300
Field::New(name, field_helper.IsStatic(), is_final,
13451301
field_helper.IsConst(), is_reflectable, script_class, type,
13461302
field_helper.position_, field_helper.end_position_));
1347-
if (I->strong() && I->use_field_guards() &&
1348-
IsPotentialExactGeneric(type)) {
1349-
field.set_static_type_exactness_state(
1350-
StaticTypeExactnessState::Unitialized());
1351-
}
13521303
field.set_kernel_offset(field_offset);
13531304
CheckForInitializer(field);
13541305
field_helper.ReadUntilExcluding(FieldHelper::kInitializer);

runtime/vm/object.cc

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9067,17 +9067,19 @@ const char* Field::GuardedPropertiesAsCString() const {
90679067
}
90689068

90699069
const char* exactness = "";
9070-
if (!static_type_exactness_state().IsExactOrUninitialized()) {
9071-
exactness = " {!exact}";
9072-
} else if (static_type_exactness_state().IsTriviallyExact()) {
9073-
exactness = " {trivially-exact}";
9074-
} else if (static_type_exactness_state().IsHasExactSuperType()) {
9075-
exactness = " {has-exact-super-type}";
9076-
} else if (static_type_exactness_state().IsHasExactSuperClass()) {
9077-
exactness = " {has-exact-super-class}";
9078-
} else {
9079-
ASSERT(static_type_exactness_state().IsUninitialized());
9080-
exactness = " {unknown exactness}";
9070+
if (static_type_exactness_state().IsTracking()) {
9071+
if (!static_type_exactness_state().IsExactOrUninitialized()) {
9072+
exactness = " {!exact}";
9073+
} else if (static_type_exactness_state().IsTriviallyExact()) {
9074+
exactness = " {trivially-exact}";
9075+
} else if (static_type_exactness_state().IsHasExactSuperType()) {
9076+
exactness = " {has-exact-super-type}";
9077+
} else if (static_type_exactness_state().IsHasExactSuperClass()) {
9078+
exactness = " {has-exact-super-class}";
9079+
} else {
9080+
ASSERT(static_type_exactness_state().IsUninitialized());
9081+
exactness = " {unknown exactness}";
9082+
}
90819083
}
90829084

90839085
const Class& cls =
@@ -9413,6 +9415,13 @@ void Field::RecordStore(const Object& value) const {
94139415
return;
94149416
}
94159417

9418+
if ((guarded_cid() == kDynamicCid) ||
9419+
(is_nullable() && value.raw() == Object::null())) {
9420+
// Nothing to do: the field is not guarded or we are storing null into
9421+
// a nullable field.
9422+
return;
9423+
}
9424+
94169425
if (FLAG_trace_field_guards) {
94179426
THR_Print("Store %s %s <- %s\n", ToCString(), GuardedPropertiesAsCString(),
94189427
value.ToCString());

runtime/vm/parser.cc

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -214,9 +214,8 @@ ParsedFunction::ParsedFunction(Thread* thread, const Function& function)
214214
}
215215

216216
void ParsedFunction::AddToGuardedFields(const Field* field) const {
217-
if (((field->guarded_cid() == kDynamicCid) ||
218-
(field->guarded_cid() == kIllegalCid)) &&
219-
field->static_type_exactness_state().IsExactOrUninitialized()) {
217+
if ((field->guarded_cid() == kDynamicCid) ||
218+
(field->guarded_cid() == kIllegalCid)) {
220219
return;
221220
}
222221

0 commit comments

Comments
 (0)