Simplify our intrinsic recognizer.
- Use the modifiers for storing the intrinsic kind.
- Delete dex_file_method_inliner and its associated map.
This work was also motivated by the fact that the inline
method analyzer leaks intrinsic tables, and even worse, might re-use
a table from one dex file to another unrelated dex file in the presence
of class unloading and the unlikely event of the dex files getting
the same address.
test: m test-art-host m test-art-target
Change-Id: Ia653d2c72df13889dc85dd8c84997582c034ea4b
diff --git a/runtime/art_method.h b/runtime/art_method.h
index 3d2db69..7a8f479 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -137,7 +137,52 @@
return (GetAccessFlags() & kAccFinal) != 0;
}
+ bool IsIntrinsic() {
+ return (GetAccessFlags() & kAccIntrinsic) != 0;
+ }
+
+ void SetIntrinsic(uint32_t intrinsic) {
+ DCHECK(IsUint<8>(intrinsic));
+ uint32_t new_value = (GetAccessFlags() & kAccFlagsNotUsedByIntrinsic) |
+ kAccIntrinsic |
+ (intrinsic << POPCOUNT(kAccFlagsNotUsedByIntrinsic));
+ if (kIsDebugBuild) {
+ uint32_t java_flags = (GetAccessFlags() & kAccJavaFlagsMask);
+ bool is_constructor = IsConstructor();
+ bool is_synchronized = IsSynchronized();
+ bool skip_access_checks = SkipAccessChecks();
+ bool is_fast_native = IsFastNative();
+ bool is_copied = IsCopied();
+ bool is_miranda = IsMiranda();
+ bool is_default = IsDefault();
+ bool is_default_conflict = IsDefaultConflicting();
+ bool is_compilable = IsCompilable();
+ bool must_count_locks = MustCountLocks();
+ SetAccessFlags(new_value);
+ DCHECK_EQ(java_flags, (GetAccessFlags() & kAccJavaFlagsMask));
+ DCHECK_EQ(is_constructor, IsConstructor());
+ DCHECK_EQ(is_synchronized, IsSynchronized());
+ DCHECK_EQ(skip_access_checks, SkipAccessChecks());
+ DCHECK_EQ(is_fast_native, IsFastNative());
+ DCHECK_EQ(is_copied, IsCopied());
+ DCHECK_EQ(is_miranda, IsMiranda());
+ DCHECK_EQ(is_default, IsDefault());
+ DCHECK_EQ(is_default_conflict, IsDefaultConflicting());
+ DCHECK_EQ(is_compilable, IsCompilable());
+ DCHECK_EQ(must_count_locks, MustCountLocks());
+ } else {
+ SetAccessFlags(new_value);
+ }
+ }
+
+ uint32_t GetIntrinsic() {
+ DCHECK(IsIntrinsic());
+ return (GetAccessFlags() >> POPCOUNT(kAccFlagsNotUsedByIntrinsic)) & kAccMaxIntrinsic;
+ }
+
bool IsCopied() {
+ static_assert((kAccCopied & kAccFlagsNotUsedByIntrinsic) == kAccCopied,
+ "kAccCopied conflicts with intrinsic modifier");
const bool copied = (GetAccessFlags() & kAccCopied) != 0;
// (IsMiranda() || IsDefaultConflicting()) implies copied
DCHECK(!(IsMiranda() || IsDefaultConflicting()) || copied)
@@ -146,6 +191,8 @@
}
bool IsMiranda() {
+ static_assert((kAccMiranda & kAccFlagsNotUsedByIntrinsic) == kAccMiranda,
+ "kAccMiranda conflicts with intrinsic modifier");
return (GetAccessFlags() & kAccMiranda) != 0;
}
@@ -156,6 +203,9 @@
}
bool IsCompilable() {
+ if (IsIntrinsic()) {
+ return true;
+ }
return (GetAccessFlags() & kAccCompileDontBother) == 0;
}
@@ -163,11 +213,16 @@
// multiple default methods. It cannot be invoked, throwing an IncompatibleClassChangeError if one
// attempts to do so.
bool IsDefaultConflicting() {
+ if (IsIntrinsic()) {
+ return false;
+ }
return (GetAccessFlags() & kAccDefaultConflict) != 0u;
}
// This is set by the class linker.
bool IsDefault() {
+ static_assert((kAccDefault & kAccFlagsNotUsedByIntrinsic) == kAccDefault,
+ "kAccDefault conflicts with intrinsic modifier");
return (GetAccessFlags() & kAccDefault) != 0;
}
@@ -204,6 +259,9 @@
// Should this method be run in the interpreter and count locks (e.g., failed structured-
// locking verification)?
bool MustCountLocks() {
+ if (IsIntrinsic()) {
+ return false;
+ }
return (GetAccessFlags() & kAccMustCountLocks) != 0;
}
diff --git a/runtime/base/mutex.h b/runtime/base/mutex.h
index 8af9fa5..91e31d8 100644
--- a/runtime/base/mutex.h
+++ b/runtime/base/mutex.h
@@ -78,7 +78,6 @@
kAllocSpaceLock,
kBumpPointerSpaceBlockLock,
kArenaPoolLock,
- kDexFileMethodInlinerLock,
kDexFileToMethodInlinerMapLock,
kInternTableLock,
kOatFileSecondaryLookupLock,
diff --git a/runtime/image.cc b/runtime/image.cc
index 7e6790a..299d5fd 100644
--- a/runtime/image.cc
+++ b/runtime/image.cc
@@ -25,7 +25,7 @@
namespace art {
const uint8_t ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' };
-const uint8_t ImageHeader::kImageVersion[] = { '0', '3', '0', '\0' };
+const uint8_t ImageHeader::kImageVersion[] = { '0', '3', '1', '\0' };
ImageHeader::ImageHeader(uint32_t image_begin,
uint32_t image_size,
diff --git a/runtime/modifiers.h b/runtime/modifiers.h
index fd7a125..dd32df6 100644
--- a/runtime/modifiers.h
+++ b/runtime/modifiers.h
@@ -67,6 +67,7 @@
// Set by the verifier for a method that could not be verified to follow structured locking.
static constexpr uint32_t kAccMustCountLocks = 0x02000000; // method (runtime)
+static constexpr uint32_t kAccIntrinsic = 0x80000000; // method (runtime)
// Special runtime-only flags.
// Interface and all its super-interfaces with default methods have been recursively initialized.
@@ -76,6 +77,9 @@
// class/ancestor overrides finalize()
static constexpr uint32_t kAccClassIsFinalizable = 0x80000000;
+static constexpr uint32_t kAccFlagsNotUsedByIntrinsic = 0x007FFFFF;
+static constexpr uint32_t kAccMaxIntrinsic = 0xFF;
+
// Valid (meaningful) bits for a field.
static constexpr uint32_t kAccValidFieldFlags = kAccPublic | kAccPrivate | kAccProtected |
kAccStatic | kAccFinal | kAccVolatile | kAccTransient | kAccSynthetic | kAccEnum;