summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Santiago Aboy Solanes <solanes@google.com> 2024-10-11 17:24:46 +0100
committer Santiago Aboy Solanes <solanes@google.com> 2024-11-12 09:08:01 +0000
commit8666596312768c91d5d031468dfc61ed5cfe5483 (patch)
treef10fee8e2b47c9e3946f206f23ce8ef7498c9a44
parent918a1812f609c3d380f088ea95b4d8ce967d9b50 (diff)
Add an extra bit for intrinsics in ArtMethod
This increases the number of intrinsics from 255 to 511. Bug: 370367478 Test: art/test/testrunner/testrunner.py --host --64 -b --optimizing Change-Id: I9104dab59b06f4fb72c44ec9e004566cc28e668f
-rw-r--r--libdexfile/dex/modifiers.h2
-rw-r--r--runtime/art_method.h10
-rw-r--r--runtime/class_linker.cc13
-rw-r--r--runtime/oat/image.cc4
4 files changed, 23 insertions, 6 deletions
diff --git a/libdexfile/dex/modifiers.h b/libdexfile/dex/modifiers.h
index 5e5e859dc9..94e25e8e6e 100644
--- a/libdexfile/dex/modifiers.h
+++ b/libdexfile/dex/modifiers.h
@@ -129,7 +129,7 @@ static constexpr uint32_t kAccHiddenapiBits = kAccPublicApi | kAccCorePlatformAp
// which overlap are not valid when kAccIntrinsic is set.
static constexpr uint32_t kAccIntrinsicBits = kAccHiddenapiBits |
kAccSingleImplementation | kAccMustCountLocks | kAccCompileDontBother | kAccCopied |
- kAccPreviouslyWarm | kAccMemorySharedMethod;
+ kAccPreviouslyWarm | kAccMemorySharedMethod | kAccDefault;
// Valid (meaningful) bits for a field.
static constexpr uint32_t kAccValidFieldFlags = kAccPublic | kAccPrivate | kAccProtected |
diff --git a/runtime/art_method.h b/runtime/art_method.h
index 51520ddd4c..ee11328385 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -421,9 +421,13 @@ class EXPORT ArtMethod final {
}
static bool IsDefault(uint32_t access_flags) {
- static_assert((kAccDefault & (kAccIntrinsic | kAccIntrinsicBits)) == 0,
- "kAccDefault conflicts with intrinsic modifier");
- return (access_flags & kAccDefault) != 0;
+ // The intrinsic bits use `kAccDefault`. However, we don't generate intrinsics for default
+ // methods. Therefore, we check that both `kAccDefault` is set and `kAccIntrinsic` unset.
+ static_assert((kAccDefault & kAccIntrinsicBits) != 0,
+ "kAccDefault deliberately overlaps intrinsic bits");
+ static constexpr uint32_t kMask = kAccIntrinsic | kAccDefault;
+ static constexpr uint32_t kValue = kAccDefault;
+ return (access_flags & kMask) == kValue;
}
// Returns true if the method is obsolete.
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index b4c2e4a54d..6d247a6d7a 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -77,6 +77,7 @@
#include "dex/dex_file_annotations.h"
#include "dex/dex_file_exception_helpers.h"
#include "dex/dex_file_loader.h"
+#include "dex/modifiers.h"
#include "dex/signature-inl.h"
#include "dex/utf.h"
#include "entrypoints/entrypoint_utils-inl.h"
@@ -5530,6 +5531,9 @@ void ClassLinker::CreateProxyMethod(Handle<mirror::Class> klass, ArtMethod* prot
// 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;
+ static_assert((kAccDefault & kAccIntrinsicBits) != 0);
+ DCHECK(!out->IsIntrinsic()) << "Removing kAccDefault from an intrinsic would be a mistake as it "
+ << "overlaps with kAccIntrinsicBits.";
// 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;
@@ -8200,6 +8204,9 @@ void ClassLinker::LinkMethodsHelper<kPointerSize>::ReallocMethods(ObjPtr<mirror:
// TODO This is rather arbitrary. We should maybe support classes where only some of its
// methods are skip_access_checks.
DCHECK_EQ(new_method.GetAccessFlags() & kAccNative, 0u);
+ static_assert((kAccDefault & kAccIntrinsicBits) != 0);
+ DCHECK(!new_method.IsIntrinsic()) << "Adding kAccDefault to an intrinsic would be a "
+ << "mistake as it overlaps with kAccIntrinsicBits.";
constexpr uint32_t kSetFlags = kAccDefault | kAccCopied;
constexpr uint32_t kMaskFlags = ~kAccSkipAccessChecks;
new_method.SetAccessFlags((new_method.GetAccessFlags() | kSetFlags) & kMaskFlags);
@@ -8216,6 +8223,9 @@ void ClassLinker::LinkMethodsHelper<kPointerSize>::ReallocMethods(ObjPtr<mirror:
uint32_t access_flags = new_method.GetAccessFlags();
DCHECK_EQ(access_flags & (kAccNative | kAccIntrinsic), 0u);
constexpr uint32_t kSetFlags = kAccDefault | kAccAbstract | kAccCopied;
+ static_assert((kAccDefault & kAccIntrinsicBits) != 0);
+ DCHECK(!new_method.IsIntrinsic()) << "Adding kAccDefault to an intrinsic would be a "
+ << "mistake as it overlaps with kAccIntrinsicBits.";
constexpr uint32_t kMaskFlags = ~(kAccSkipAccessChecks | kAccSingleImplementation);
new_method.SetAccessFlags((access_flags | kSetFlags) & kMaskFlags);
new_method.SetDataPtrSize(nullptr, kPointerSize);
@@ -8843,6 +8853,9 @@ bool ClassLinker::LinkMethodsHelper<kPointerSize>::LinkMethods(
<< "This will be a fatal error in subsequent versions of android. "
<< "Continuing anyway.";
}
+ static_assert((kAccDefault & kAccIntrinsicBits) != 0);
+ DCHECK(!m->IsIntrinsic()) << "Adding kAccDefault to an intrinsic would be a mistake as it "
+ << "overlaps with kAccIntrinsicBits.";
m->SetAccessFlags(access_flags | kAccDefault);
has_defaults = true;
}
diff --git a/runtime/oat/image.cc b/runtime/oat/image.cc
index 1c8517bc77..77eb7df6e6 100644
--- a/runtime/oat/image.cc
+++ b/runtime/oat/image.cc
@@ -34,8 +34,8 @@
namespace art HIDDEN {
const uint8_t ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' };
-// Use arrays for resolved methods and resolved fields in DexCache.
-const uint8_t ImageHeader::kImageVersion[] = { '1', '1', '6', '\0' };
+// Last change: Add kAccDefault as an intrinsic bit.
+const uint8_t ImageHeader::kImageVersion[] = { '1', '1', '7', '\0' };
ImageHeader::ImageHeader(uint32_t image_reservation_size,
uint32_t component_count,