Remove kAccMiranda and kAccDefaultConflicting.
Use a combination of other existing flags to mark miranda
and default conflicting methods.
Also change the value of identical flags kAccCriticalNative
and kAccPreCompiled to 0x00100000 to have the values of
kAccFastNative and kAccCriticalNative in consecutive bits.
The method access flag 0x00200000 is now free for future
use. The method access flag 0x00100000 is also potentially
usable for some methods the same way that the old
kAccMiranda flag was used despite sharing the same value
with both kAccCriticalNative and kAccPreCompiled.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Bug: 112676029
Change-Id: Ibfd20598f9b4af78e1e72f8331dc647d01dd8eb5
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index b98708e..11b5480 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -5121,9 +5121,9 @@
// Set class to be the concrete proxy class.
out->SetDeclaringClass(klass.Get());
- // Clear the abstract, default and conflict flags to ensure that defaults aren't picked in
+ // Clear the abstract and default flags to ensure that defaults aren't picked in
// preference to the invocation handler.
- const uint32_t kRemoveFlags = kAccAbstract | kAccDefault | kAccDefaultConflict;
+ const uint32_t kRemoveFlags = kAccAbstract | kAccDefault;
// Make the method final.
// Mark kAccCompileDontBother so that we don't take JIT samples for the method. b/62349349
const uint32_t kAddFlags = kAccFinal | kAccCompileDontBother;
@@ -7881,9 +7881,11 @@
ArtMethod* mir_method = miranda_methods_[i];
ArtMethod& new_method = *out;
new_method.CopyFrom(mir_method, pointer_size);
- new_method.SetAccessFlags(new_method.GetAccessFlags() | kAccMiranda | kAccCopied);
- DCHECK_NE(new_method.GetAccessFlags() & kAccAbstract, 0u)
- << "Miranda method should be abstract!";
+ uint32_t access_flags = new_method.GetAccessFlags();
+ DCHECK_EQ(access_flags & kAccIntrinsic, 0u) << "Miranda method should not be an intrinsic!";
+ DCHECK_EQ(access_flags & kAccDefault, 0u) << "Miranda method should not be a default method!";
+ DCHECK_NE(access_flags & kAccAbstract, 0u) << "Miranda method should be abstract!";
+ new_method.SetAccessFlags(access_flags | kAccCopied);
move_table_.emplace(mir_method, &new_method);
// Update the entry in the method array, as the array will be used for future lookups,
// where thread suspension is allowed.
@@ -7928,17 +7930,20 @@
ArtMethod& new_method = *out;
new_method.CopyFrom(conf_method, pointer_size);
// This is a type of default method (there are default method impls, just a conflict) so
- // mark this as a default, non-abstract method, since thats what it is. Also clear the
- // kAccSkipAccessChecks bit since this class hasn't been verified yet it shouldn't have
- // methods that are skipping access checks.
- // Also clear potential kAccSingleImplementation to avoid CHA trying to inline
- // the default method.
- DCHECK_EQ(new_method.GetAccessFlags() & kAccNative, 0u);
- constexpr uint32_t kSetFlags = kAccDefault | kAccDefaultConflict | kAccCopied;
- constexpr uint32_t kMaskFlags =
- ~(kAccAbstract | kAccSkipAccessChecks | kAccSingleImplementation);
- new_method.SetAccessFlags((new_method.GetAccessFlags() | kSetFlags) & kMaskFlags);
+ // mark this as a default. We use the `kAccAbstract` flag to distinguish it from invokable
+ // copied default method without using a separate access flag but the default conflicting
+ // method is technically not abstract and ArtMethod::IsAbstract() shall return false.
+ // Also clear the kAccSkipAccessChecks bit since this class hasn't been verified yet it
+ // shouldn't have methods that are skipping access checks. Also clear potential
+ // kAccSingleImplementation to avoid CHA trying to inline the default method.
+ uint32_t access_flags = new_method.GetAccessFlags();
+ DCHECK_EQ(access_flags & kAccNative, 0u);
+ DCHECK_EQ(access_flags & kAccIntrinsic, 0u);
+ constexpr uint32_t kSetFlags = kAccDefault | kAccAbstract | kAccCopied;
+ constexpr uint32_t kMaskFlags = ~(kAccSkipAccessChecks | kAccSingleImplementation);
+ new_method.SetAccessFlags((access_flags | kSetFlags) & kMaskFlags);
DCHECK(new_method.IsDefaultConflicting());
+ DCHECK(!new_method.IsAbstract());
// The actual method might or might not be marked abstract since we just copied it from a
// (possibly default) interface method. We need to set it entry point to be the bridge so
// that the compiler will not invoke the implementation of whatever method we copied from.