ART: Add unchecked conversions of arrays
Add array conversion functions that do not check the type,
and use them in an unchecked version for PointerArray.
Decreases dex2oatd preopting of a big app from 151s to 150s.
Bug: 123888325
Test: m test-art-host
Change-Id: Id58c65ac603a20c2cfb9e3289af4f3bc323554b6
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index cb1fbfe..ef0d72f 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -7090,7 +7090,9 @@
MethodNameAndSignatureComparator name_comparator(
vtable_entry->GetInterfaceMethodIfProxy(kPointerSize));
for (int32_t j = i + 1; j < num_entries; j++) {
- ArtMethod* other_entry = vtable->GetElementPtrSize<ArtMethod*, kPointerSize>(j);
+ // Can use Unchecked here as the outer loop already ensured that the arrays are correct
+ // wrt/ kPointerSize.
+ ArtMethod* other_entry = vtable->GetElementPtrSizeUnchecked<ArtMethod*, kPointerSize>(j);
if (!klass->CanAccessMember(other_entry->GetDeclaringClass(),
other_entry->GetAccessFlags())) {
continue;
diff --git a/runtime/mirror/array-inl.h b/runtime/mirror/array-inl.h
index 40507e7..c4a892b 100644
--- a/runtime/mirror/array-inl.h
+++ b/runtime/mirror/array-inl.h
@@ -233,6 +233,15 @@
}
return (T)static_cast<uintptr_t>(AsIntArray<kVerifyFlags>()->GetWithoutChecks(idx));
}
+template<typename T, PointerSize kPointerSize, VerifyObjectFlags kVerifyFlags>
+inline T PointerArray::GetElementPtrSizeUnchecked(uint32_t idx) {
+ // C style casts here since we sometimes have T be a pointer, or sometimes an integer
+ // (for stack traces).
+ if (kPointerSize == PointerSize::k64) {
+ return (T)static_cast<uintptr_t>(AsLongArrayUnchecked<kVerifyFlags>()->GetWithoutChecks(idx));
+ }
+ return (T)static_cast<uintptr_t>(AsIntArrayUnchecked<kVerifyFlags>()->GetWithoutChecks(idx));
+}
template<typename T, VerifyObjectFlags kVerifyFlags>
inline T PointerArray::GetElementPtrSize(uint32_t idx, PointerSize ptr_size) {
// C style casts here since we sometimes have T be a pointer, or sometimes an integer
diff --git a/runtime/mirror/array.h b/runtime/mirror/array.h
index ce64272..2e894d5 100644
--- a/runtime/mirror/array.h
+++ b/runtime/mirror/array.h
@@ -224,6 +224,12 @@
template<typename T, PointerSize kPtrSize, VerifyObjectFlags kVerifyFlags = kVerifyNone>
T GetElementPtrSize(uint32_t idx)
REQUIRES_SHARED(Locks::mutator_lock_);
+ // Same as GetElementPtrSize, but uses unchecked version of array conversion. It is thus not
+ // checked whether kPtrSize matches the underlying array. Only use after at least one invocation
+ // of GetElementPtrSize!
+ template<typename T, PointerSize kPtrSize, VerifyObjectFlags kVerifyFlags = kVerifyNone>
+ T GetElementPtrSizeUnchecked(uint32_t idx)
+ REQUIRES_SHARED(Locks::mutator_lock_);
template<VerifyObjectFlags kVerifyFlags = kVerifyNone>
void** ElementAddress(size_t index, PointerSize ptr_size) REQUIRES_SHARED(Locks::mutator_lock_) {
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index 2c2ad9b..005e272 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -253,9 +253,13 @@
}
template<VerifyObjectFlags kVerifyFlags>
+inline IntArray* Object::AsIntArrayUnchecked() {
+ return down_cast<IntArray*>(this);
+}
+template<VerifyObjectFlags kVerifyFlags>
inline IntArray* Object::AsIntArray() {
DCHECK((IsIntArray<kVerifyFlags>()));
- return down_cast<IntArray*>(this);
+ return AsIntArrayUnchecked<kVerifyFlags>();
}
template<VerifyObjectFlags kVerifyFlags>
@@ -264,9 +268,13 @@
}
template<VerifyObjectFlags kVerifyFlags>
+inline LongArray* Object::AsLongArrayUnchecked() {
+ return down_cast<LongArray*>(this);
+}
+template<VerifyObjectFlags kVerifyFlags>
inline LongArray* Object::AsLongArray() {
DCHECK((IsLongArray<kVerifyFlags>()));
- return down_cast<LongArray*>(this);
+ return AsLongArrayUnchecked<kVerifyFlags>();
}
template<VerifyObjectFlags kVerifyFlags>
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index ba222f6..ca8867d8 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -223,11 +223,15 @@
bool IsIntArray() REQUIRES_SHARED(Locks::mutator_lock_);
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
IntArray* AsIntArray() REQUIRES_SHARED(Locks::mutator_lock_);
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ IntArray* AsIntArrayUnchecked() REQUIRES_SHARED(Locks::mutator_lock_);
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsLongArray() REQUIRES_SHARED(Locks::mutator_lock_);
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
LongArray* AsLongArray() REQUIRES_SHARED(Locks::mutator_lock_);
+ template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
+ LongArray* AsLongArrayUnchecked() REQUIRES_SHARED(Locks::mutator_lock_);
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
bool IsFloatArray() REQUIRES_SHARED(Locks::mutator_lock_);