Skip to content

Commit b59d5a2

Browse files
alexmarkovcommit-bot@chromium.org
authored andcommitted
[vm] Relax assertion about duplicated direct implementors
When mixin application is transformed, mixin is added to the end of interfaces list. This may cause assertion failure if the same class is used as mixin and mentioned among implemented interfaces. This CL relaxes that assertion for mixins as this duplication is very rare and seems harmless. Note that it would not be valid to remove duplicated interface/mixin from the list of interfaces, as it would break dart:mirrors in this case: dart:mirrors needs to reflect duplicated interface/mixin both in ClassMirror.superinterfaces (which is populated from the list of interfaces without last element) and ClassMirror.mixin (the last element in the list of interfaces). Fixes #35854 Change-Id: I9b986f7759a76cb6f963ebd837e9ea26f6242f8e Reviewed-on: https://dart-review.googlesource.com/c/91961 Reviewed-by: Régis Crelier <[email protected]> Commit-Queue: Alexander Markov <[email protected]>
1 parent 1f63860 commit b59d5a2

File tree

5 files changed

+21
-9
lines changed

5 files changed

+21
-9
lines changed

runtime/vm/class_finalizer.cc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1078,11 +1078,15 @@ void ClassFinalizer::FinalizeTypesInClass(const Class& cls) {
10781078
// classes.
10791079
Zone* zone = thread->zone();
10801080
auto& interface_class = Class::Handle(zone);
1081+
const intptr_t mixin_index = cls.is_transformed_mixin_application()
1082+
? interface_types.Length() - 1
1083+
: -1;
10811084
for (intptr_t i = 0; i < interface_types.Length(); ++i) {
10821085
interface_type ^= interface_types.At(i);
10831086
interface_class = interface_type.type_class();
10841087
MarkImplemented(thread->zone(), interface_class);
1085-
interface_class.AddDirectImplementor(cls);
1088+
interface_class.AddDirectImplementor(cls,
1089+
/* is_mixin = */ i == mixin_index);
10861090
}
10871091

10881092
if (FLAG_use_cha_deopt) {

runtime/vm/isolate_reload.cc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2269,10 +2269,14 @@ void IsolateReloadContext::RebuildDirectSubclasses() {
22692269

22702270
interface_types = cls.interfaces();
22712271
if (!interface_types.IsNull()) {
2272+
const intptr_t mixin_index = cls.is_transformed_mixin_application()
2273+
? interface_types.Length() - 1
2274+
: -1;
22722275
for (intptr_t j = 0; j < interface_types.Length(); ++j) {
22732276
interface_type ^= interface_types.At(j);
22742277
interface_class = interface_type.type_class();
2275-
interface_class.AddDirectImplementor(cls);
2278+
interface_class.AddDirectImplementor(
2279+
cls, /* is_mixin = */ i == mixin_index);
22762280
}
22772281
}
22782282
}

runtime/vm/object.cc

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3979,7 +3979,8 @@ RawClass* Class::GetPatchClass() const {
39793979
return lib.GetPatchClass(String::Handle(Name()));
39803980
}
39813981

3982-
void Class::AddDirectImplementor(const Class& implementor) const {
3982+
void Class::AddDirectImplementor(const Class& implementor,
3983+
bool is_mixin) const {
39833984
ASSERT(is_implemented());
39843985
ASSERT(!implementor.IsNull());
39853986
GrowableObjectArray& direct_implementors =
@@ -3990,8 +3991,14 @@ void Class::AddDirectImplementor(const Class& implementor) const {
39903991
}
39913992
#if defined(DEBUG)
39923993
// Verify that the same class is not added twice.
3993-
for (intptr_t i = 0; i < direct_implementors.Length(); i++) {
3994-
ASSERT(direct_implementors.At(i) != implementor.raw());
3994+
// The only exception is mixins: when mixin application is transformed,
3995+
// mixin is added to the end of interfaces list and may be duplicated:
3996+
// class X = A with B implements B;
3997+
// This is rare and harmless.
3998+
if (!is_mixin) {
3999+
for (intptr_t i = 0; i < direct_implementors.Length(); i++) {
4000+
ASSERT(direct_implementors.At(i) != implementor.raw());
4001+
}
39954002
}
39964003
#endif
39974004
direct_implementors.Add(implementor, Heap::kOld);

runtime/vm/object.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -962,7 +962,7 @@ class Class : public Object {
962962
RawGrowableObjectArray* direct_implementors() const {
963963
return raw_ptr()->direct_implementors_;
964964
}
965-
void AddDirectImplementor(const Class& subclass) const;
965+
void AddDirectImplementor(const Class& subclass, bool is_mixin) const;
966966
void ClearDirectImplementors() const;
967967

968968
// Returns the list of classes having this class as direct superclass.

tests/co19_2/co19_2-kernel.status

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -751,9 +751,6 @@ Language/Statements/Switch/equal_operator_t02: MissingCompileTimeError # Issue 3
751751
LibTest/io/Stdin/readByteSync_A02_t01: RuntimeError, Pass
752752
LibTest/io/WebSocket/pingInterval_A01_t01: RuntimeError, Pass
753753

754-
[ $mode == debug && $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
755-
Language/Classes/definition_t23: Crash # Issue 35854
756-
757754
[ $runtime == vm && $system == linux && ($compiler == dartk || $compiler == dartkb) ]
758755
LibTest/io/Link/stat_A01_t01: RuntimeError
759756
LibTest/isolate/Isolate/spawn_A06_t03: Crash, Pass

0 commit comments

Comments
 (0)