Revert "Combine direct_methods_ and virtual_methods_ fields of mirror::Class"
This reverts commit 6286a97bea0f584342803a215550038852b24776.
Change-Id: I5b00f6d1350e9c587acd4b185367dc815ea707de
diff --git a/compiler/common_compiler_test.cc b/compiler/common_compiler_test.cc
index c7c1907..638b897 100644
--- a/compiler/common_compiler_test.cc
+++ b/compiler/common_compiler_test.cc
@@ -142,7 +142,10 @@
mirror::Class* klass = class_linker_->FindClass(self, class_descriptor.c_str(), loader);
CHECK(klass != nullptr) << "Class not found " << class_name;
size_t pointer_size = class_linker_->GetImagePointerSize();
- for (auto& m : klass->GetMethods(pointer_size)) {
+ for (auto& m : klass->GetDirectMethods(pointer_size)) {
+ MakeExecutable(&m);
+ }
+ for (auto& m : klass->GetVirtualMethods(pointer_size)) {
MakeExecutable(&m);
}
}
@@ -256,7 +259,10 @@
mirror::Class* klass = class_linker_->FindClass(self, class_descriptor.c_str(), loader);
CHECK(klass != nullptr) << "Class not found " << class_name;
auto pointer_size = class_linker_->GetImagePointerSize();
- for (auto& m : klass->GetMethods(pointer_size)) {
+ for (auto& m : klass->GetDirectMethods(pointer_size)) {
+ CompileMethod(&m);
+ }
+ for (auto& m : klass->GetVirtualMethods(pointer_size)) {
CompileMethod(&m);
}
}
diff --git a/compiler/compiled_method.h b/compiler/compiled_method.h
index 7a93613..15a4ba0 100644
--- a/compiler/compiled_method.h
+++ b/compiler/compiled_method.h
@@ -23,7 +23,7 @@
#include "arch/instruction_set.h"
#include "base/bit_utils.h"
-#include "base/length_prefixed_array.h"
+#include "length_prefixed_array.h"
#include "method_reference.h"
#include "utils/array_ref.h"
diff --git a/compiler/driver/compiled_method_storage.h b/compiler/driver/compiled_method_storage.h
index d6961a0..ef10b67 100644
--- a/compiler/driver/compiled_method_storage.h
+++ b/compiler/driver/compiled_method_storage.h
@@ -20,8 +20,8 @@
#include <iosfwd>
#include <memory>
-#include "base/length_prefixed_array.h"
#include "base/macros.h"
+#include "length_prefixed_array.h"
#include "utils/array_ref.h"
#include "utils/dedupe_set.h"
#include "utils/swap_space.h"
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 56839f8..ba8f1d0 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -790,7 +790,10 @@
virtual bool Visit(mirror::Class* c) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
const auto pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
- for (auto& m : c->GetMethods(pointer_size)) {
+ for (auto& m : c->GetVirtualMethods(pointer_size)) {
+ ResolveExceptionsForMethod(&m, pointer_size);
+ }
+ for (auto& m : c->GetDirectMethods(pointer_size)) {
ResolveExceptionsForMethod(&m, pointer_size);
}
return true;
diff --git a/compiler/driver/compiler_driver_test.cc b/compiler/driver/compiler_driver_test.cc
index 86f8b82..f8de9fa 100644
--- a/compiler/driver/compiler_driver_test.cc
+++ b/compiler/driver/compiler_driver_test.cc
@@ -86,7 +86,10 @@
mirror::Class* c = class_linker->FindClass(soa.Self(), descriptor, loader);
CHECK(c != nullptr);
const auto pointer_size = class_linker->GetImagePointerSize();
- for (auto& m : c->GetMethods(pointer_size)) {
+ for (auto& m : c->GetDirectMethods(pointer_size)) {
+ MakeExecutable(&m);
+ }
+ for (auto& m : c->GetVirtualMethods(pointer_size)) {
MakeExecutable(&m);
}
}
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index b9ec47d..fce08ea 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -1030,42 +1030,44 @@
}
}
// Visit and assign offsets for methods.
- size_t num_methods = as_klass->NumMethods();
- if (num_methods != 0) {
+ LengthPrefixedArray<ArtMethod>* method_arrays[] = {
+ as_klass->GetDirectMethodsPtr(), as_klass->GetVirtualMethodsPtr(),
+ };
+ for (LengthPrefixedArray<ArtMethod>* array : method_arrays) {
+ if (array == nullptr) {
+ continue;
+ }
bool any_dirty = false;
- for (auto& m : as_klass->GetMethods(target_ptr_size_)) {
- if (WillMethodBeDirty(&m)) {
- any_dirty = true;
- break;
- }
+ size_t count = 0;
+ const size_t method_alignment = ArtMethod::Alignment(target_ptr_size_);
+ const size_t method_size = ArtMethod::Size(target_ptr_size_);
+ auto iteration_range =
+ MakeIterationRangeFromLengthPrefixedArray(array, method_size, method_alignment);
+ for (auto& m : iteration_range) {
+ any_dirty = any_dirty || WillMethodBeDirty(&m);
+ ++count;
}
NativeObjectRelocationType type = any_dirty
? kNativeObjectRelocationTypeArtMethodDirty
: kNativeObjectRelocationTypeArtMethodClean;
Bin bin_type = BinTypeForNativeRelocationType(type);
// Forward the entire array at once, but header first.
- const size_t method_alignment = ArtMethod::Alignment(target_ptr_size_);
- const size_t method_size = ArtMethod::Size(target_ptr_size_);
const size_t header_size = LengthPrefixedArray<ArtMethod>::ComputeSize(0,
method_size,
method_alignment);
- LengthPrefixedArray<ArtMethod>* array = as_klass->GetMethodsPtr();
auto it = native_object_relocations_.find(array);
- CHECK(it == native_object_relocations_.end())
- << "Method array " << array << " already forwarded";
+ CHECK(it == native_object_relocations_.end()) << "Method array " << array
+ << " already forwarded";
size_t& offset = bin_slot_sizes_[bin_type];
DCHECK(!IsInBootImage(array));
- native_object_relocations_.emplace(
- array, NativeObjectRelocation {
- offset,
- any_dirty ? kNativeObjectRelocationTypeArtMethodArrayDirty
- : kNativeObjectRelocationTypeArtMethodArrayClean
- });
+ native_object_relocations_.emplace(array, NativeObjectRelocation { offset,
+ any_dirty ? kNativeObjectRelocationTypeArtMethodArrayDirty :
+ kNativeObjectRelocationTypeArtMethodArrayClean });
offset += header_size;
- for (auto& m : as_klass->GetMethods(target_ptr_size_)) {
+ for (auto& m : iteration_range) {
AssignMethodOffset(&m, type);
}
- (any_dirty ? dirty_methods_ : clean_methods_) += num_methods;
+ (any_dirty ? dirty_methods_ : clean_methods_) += count;
}
} else if (h_obj->IsObjectArray()) {
// Walk elements of an object array.
diff --git a/compiler/image_writer.h b/compiler/image_writer.h
index f1b2965..8e930f0 100644
--- a/compiler/image_writer.h
+++ b/compiler/image_writer.h
@@ -27,11 +27,11 @@
#include <ostream>
#include "base/bit_utils.h"
-#include "base/length_prefixed_array.h"
#include "base/macros.h"
#include "driver/compiler_driver.h"
#include "gc/space/space.h"
#include "image.h"
+#include "length_prefixed_array.h"
#include "lock_word.h"
#include "mem_map.h"
#include "oat_file.h"
diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc
index b849b12..a2b29a3 100644
--- a/compiler/oat_test.cc
+++ b/compiler/oat_test.cc
@@ -238,12 +238,12 @@
++method_index;
}
size_t visited_virtuals = 0;
- // TODO We should also check copied methods in this test.
- for (auto& m : klass->GetDeclaredVirtualMethods(pointer_size)) {
- EXPECT_FALSE(m.IsMiranda());
- CheckMethod(&m, oat_class.GetOatMethod(method_index), dex_file);
- ++method_index;
- ++visited_virtuals;
+ for (auto& m : klass->GetVirtualMethods(pointer_size)) {
+ if (!m.IsMiranda()) {
+ CheckMethod(&m, oat_class.GetOatMethod(method_index), dex_file);
+ ++method_index;
+ ++visited_virtuals;
+ }
}
EXPECT_EQ(visited_virtuals, num_virtual_methods);
}
diff --git a/runtime/asm_support.h b/runtime/asm_support.h
index 73d9b0c..29c8232 100644
--- a/runtime/asm_support.h
+++ b/runtime/asm_support.h
@@ -163,13 +163,13 @@
#define MIRROR_CLASS_COMPONENT_TYPE_OFFSET (4 + MIRROR_OBJECT_HEADER_SIZE)
ADD_TEST_EQ(MIRROR_CLASS_COMPONENT_TYPE_OFFSET,
art::mirror::Class::ComponentTypeOffset().Int32Value())
-#define MIRROR_CLASS_ACCESS_FLAGS_OFFSET (64 + MIRROR_OBJECT_HEADER_SIZE)
+#define MIRROR_CLASS_ACCESS_FLAGS_OFFSET (72 + MIRROR_OBJECT_HEADER_SIZE)
ADD_TEST_EQ(MIRROR_CLASS_ACCESS_FLAGS_OFFSET,
art::mirror::Class::AccessFlagsOffset().Int32Value())
-#define MIRROR_CLASS_OBJECT_SIZE_OFFSET (96 + MIRROR_OBJECT_HEADER_SIZE)
+#define MIRROR_CLASS_OBJECT_SIZE_OFFSET (104 + MIRROR_OBJECT_HEADER_SIZE)
ADD_TEST_EQ(MIRROR_CLASS_OBJECT_SIZE_OFFSET,
art::mirror::Class::ObjectSizeOffset().Int32Value())
-#define MIRROR_CLASS_STATUS_OFFSET (108 + MIRROR_OBJECT_HEADER_SIZE)
+#define MIRROR_CLASS_STATUS_OFFSET (116 + MIRROR_OBJECT_HEADER_SIZE)
ADD_TEST_EQ(MIRROR_CLASS_STATUS_OFFSET,
art::mirror::Class::StatusOffset().Int32Value())
diff --git a/runtime/base/array_slice.h b/runtime/base/array_slice.h
deleted file mode 100644
index 19ad302..0000000
--- a/runtime/base/array_slice.h
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ART_RUNTIME_BASE_ARRAY_SLICE_H_
-#define ART_RUNTIME_BASE_ARRAY_SLICE_H_
-
-#include "length_prefixed_array.h"
-#include "stride_iterator.h"
-#include "base/bit_utils.h"
-#include "base/casts.h"
-#include "base/iteration_range.h"
-
-namespace art {
-
-// An ArraySlice is an abstraction over an array or a part of an array of a particular type. It does
-// bounds checking and can be made from several common array-like structures in Art.
-template<typename T>
-class ArraySlice {
- public:
- // Create an empty array slice.
- ArraySlice() : array_(nullptr), size_(0), element_size_(0) {}
-
- // Create an array slice of the first 'length' elements of the array, with each element being
- // element_size bytes long.
- ArraySlice(T* array,
- size_t length,
- size_t element_size = sizeof(T))
- : array_(array),
- size_(dchecked_integral_cast<uint32_t>(length)),
- element_size_(element_size) {
- DCHECK(array_ != nullptr || length == 0);
- }
-
- // Create an array slice of the elements between start_offset and end_offset of the array with
- // each element being element_size bytes long. Both start_offset and end_offset are in
- // element_size units.
- ArraySlice(T* array,
- uint32_t start_offset,
- uint32_t end_offset,
- size_t element_size = sizeof(T))
- : array_(nullptr),
- size_(end_offset - start_offset),
- element_size_(element_size) {
- DCHECK(array_ != nullptr || size_ == 0);
- DCHECK_LE(start_offset, end_offset);
- if (size_ != 0) {
- uintptr_t offset = start_offset * element_size_;
- array_ = *reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(array) + offset);
- }
- }
-
- // Create an array slice of the elements between start_offset and end_offset of the array with
- // each element being element_size bytes long and having the given alignment. Both start_offset
- // and end_offset are in element_size units.
- ArraySlice(LengthPrefixedArray<T>* array,
- uint32_t start_offset,
- uint32_t end_offset,
- size_t element_size = sizeof(T),
- size_t alignment = alignof(T))
- : array_(nullptr),
- size_(end_offset - start_offset),
- element_size_(element_size) {
- DCHECK(array != nullptr || size_ == 0);
- if (size_ != 0) {
- DCHECK_LE(start_offset, end_offset);
- DCHECK_LE(start_offset, array->size());
- DCHECK_LE(end_offset, array->size());
- array_ = &array->At(start_offset, element_size_, alignment);
- }
- }
-
- T& At(size_t index) {
- DCHECK_LT(index, size_);
- return AtUnchecked(index);
- }
-
- const T& At(size_t index) const {
- DCHECK_LT(index, size_);
- return AtUnchecked(index);
- }
-
- T& operator[](size_t index) {
- return At(index);
- }
-
- const T& operator[](size_t index) const {
- return At(index);
- }
-
- StrideIterator<T> begin() {
- return StrideIterator<T>(&AtUnchecked(0), element_size_);
- }
-
- StrideIterator<const T> begin() const {
- return StrideIterator<const T>(&AtUnchecked(0), element_size_);
- }
-
- StrideIterator<T> end() {
- return StrideIterator<T>(&AtUnchecked(size_), element_size_);
- }
-
- StrideIterator<const T> end() const {
- return StrideIterator<const T>(&AtUnchecked(size_), element_size_);
- }
-
- IterationRange<StrideIterator<T>> AsRange() {
- return size() != 0 ? MakeIterationRange(begin(), end())
- : MakeEmptyIterationRange(StrideIterator<T>(nullptr, 0));
- }
-
- size_t size() const {
- return size_;
- }
-
- size_t ElementSize() const {
- return element_size_;
- }
-
- private:
- T& AtUnchecked(size_t index) {
- return *reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(array_) + index * element_size_);
- }
-
- const T& AtUnchecked(size_t index) const {
- return *reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(array_) + index * element_size_);
- }
-
- T* array_;
- size_t size_;
- size_t element_size_;
-};
-
-} // namespace art
-
-#endif // ART_RUNTIME_BASE_ARRAY_SLICE_H_
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index a82c1dc..f5085ed 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -807,7 +807,10 @@
auto* runtime = Runtime::Current();
auto* image_space = runtime->GetHeap()->GetBootImageSpace();
auto pointer_size = runtime->GetClassLinker()->GetImagePointerSize();
- for (auto& m : klass->GetMethods(pointer_size)) {
+ for (auto& m : klass->GetDirectMethods(pointer_size)) {
+ SanityCheckArtMethod(&m, klass, image_space);
+ }
+ for (auto& m : klass->GetVirtualMethods(pointer_size)) {
SanityCheckArtMethod(&m, klass, image_space);
}
auto* vtable = klass->GetVTable();
@@ -2242,14 +2245,11 @@
klass->SetIFieldsPtr(ifields);
DCHECK_EQ(klass->NumInstanceFields(), num_ifields);
// Load methods.
- klass->SetMethodsPtr(
- AllocArtMethodArray(self, allocator, it.NumDirectMethods() + it.NumVirtualMethods()),
- it.NumDirectMethods(),
- it.NumVirtualMethods());
+ klass->SetDirectMethodsPtr(AllocArtMethodArray(self, allocator, it.NumDirectMethods()));
+ klass->SetVirtualMethodsPtr(AllocArtMethodArray(self, allocator, it.NumVirtualMethods()));
size_t class_def_method_index = 0;
uint32_t last_dex_method_index = DexFile::kDexNoIndex;
size_t last_class_def_method_index = 0;
- // TODO These should really use the iterators.
for (size_t i = 0; it.HasNextDirectMethod(); i++, it.Next()) {
ArtMethod* method = klass->GetDirectMethodUnchecked(i, image_pointer_size_);
LoadMethod(self, dex_file, it, klass, method);
@@ -2728,12 +2728,9 @@
return nullptr;
}
-// TODO This should really be in mirror::Class.
-void ClassLinker::UpdateClassMethods(mirror::Class* klass,
- LengthPrefixedArray<ArtMethod>* new_methods) {
- klass->SetMethodsPtrUnchecked(new_methods,
- klass->NumDirectMethods(),
- klass->NumDeclaredVirtualMethods());
+void ClassLinker::UpdateClassVirtualMethods(mirror::Class* klass,
+ LengthPrefixedArray<ArtMethod>* new_methods) {
+ klass->SetVirtualMethodsPtr(new_methods);
// Need to mark the card so that the remembered sets and mod union tables get updated.
Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(klass);
}
@@ -3305,30 +3302,29 @@
throws_sfield.SetAccessFlags(kAccStatic | kAccPublic | kAccFinal);
// Proxies have 1 direct method, the constructor
- const size_t num_direct_methods = 1;
+ LengthPrefixedArray<ArtMethod>* directs = AllocArtMethodArray(self, allocator, 1);
+ // Currently AllocArtMethodArray cannot return null, but the OOM logic is left there in case we
+ // want to throw OOM in the future.
+ if (UNLIKELY(directs == nullptr)) {
+ self->AssertPendingOOMException();
+ return nullptr;
+ }
+ klass->SetDirectMethodsPtr(directs);
+ CreateProxyConstructor(klass, klass->GetDirectMethodUnchecked(0, image_pointer_size_));
- // They have as many virtual methods as the array
+ // Create virtual method using specified prototypes.
auto h_methods = hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::Method>*>(methods));
DCHECK_EQ(h_methods->GetClass(), mirror::Method::ArrayClass())
<< PrettyClass(h_methods->GetClass());
const size_t num_virtual_methods = h_methods->GetLength();
-
- // Create the methods array.
- LengthPrefixedArray<ArtMethod>* proxy_class_methods = AllocArtMethodArray(
- self, allocator, num_direct_methods + num_virtual_methods);
+ auto* virtuals = AllocArtMethodArray(self, allocator, num_virtual_methods);
// Currently AllocArtMethodArray cannot return null, but the OOM logic is left there in case we
// want to throw OOM in the future.
- if (UNLIKELY(proxy_class_methods == nullptr)) {
+ if (UNLIKELY(virtuals == nullptr)) {
self->AssertPendingOOMException();
return nullptr;
}
- klass->SetMethodsPtr(proxy_class_methods, num_direct_methods, num_virtual_methods);
-
- // Create the single direct method.
- CreateProxyConstructor(klass, klass->GetDirectMethodUnchecked(0, image_pointer_size_));
-
- // Create virtual method using specified prototypes.
- // TODO These should really use the iterators.
+ klass->SetVirtualMethodsPtr(virtuals);
for (size_t i = 0; i < num_virtual_methods; ++i) {
auto* virtual_method = klass->GetVirtualMethodUnchecked(i, image_pointer_size_);
auto* prototype = h_methods->Get(i)->GetArtMethod();
@@ -4106,8 +4102,14 @@
}
DCHECK_EQ(temp_class->NumDirectMethods(), 0u);
+ for (auto& method : new_class->GetDirectMethods(image_pointer_size_)) {
+ if (method.GetDeclaringClass() == temp_class) {
+ method.SetDeclaringClass(new_class);
+ }
+ }
+
DCHECK_EQ(temp_class->NumVirtualMethods(), 0u);
- for (auto& method : new_class->GetMethods(image_pointer_size_)) {
+ for (auto& method : new_class->GetVirtualMethods(image_pointer_size_)) {
if (method.GetDeclaringClass() == temp_class) {
method.SetDeclaringClass(new_class);
}
@@ -4191,7 +4193,8 @@
// ArtMethod array pointers. If this occurs, it causes bugs in remembered sets since the GC
// may not see any references to the target space and clean the card for a class if another
// class had the same array pointer.
- klass->SetMethodsPtrUnchecked(nullptr, 0, 0);
+ klass->SetDirectMethodsPtrUnchecked(nullptr);
+ klass->SetVirtualMethodsPtr(nullptr);
klass->SetSFieldsPtrUnchecked(nullptr);
klass->SetIFieldsPtrUnchecked(nullptr);
if (UNLIKELY(h_new_class.Get() == nullptr)) {
@@ -4956,10 +4959,12 @@
for (size_t k = ifstart + 1; k < iftable_count; k++) {
// Skip ifstart since our current interface obviously cannot override itself.
current_iface.Assign(iftable->GetInterface(k));
- // Iterate through every method on this interface. The order does not matter.
- for (ArtMethod& current_method : current_iface->GetDeclaredVirtualMethods(image_pointer_size)) {
+ size_t num_instance_methods = current_iface->NumVirtualMethods();
+ // Iterate through every method on this interface. The order does not matter so we go forwards.
+ for (size_t m = 0; m < num_instance_methods; m++) {
+ ArtMethod* current_method = current_iface->GetVirtualMethodUnchecked(m, image_pointer_size);
if (UNLIKELY(target.HasSameNameAndSignature(
- current_method.GetInterfaceMethodIfProxy(image_pointer_size)))) {
+ current_method->GetInterfaceMethodIfProxy(image_pointer_size)))) {
// Check if the i'th interface is a subtype of this one.
if (iface->IsAssignableFrom(current_iface.Get())) {
return true;
@@ -5012,9 +5017,10 @@
DCHECK_LT(k, iftable->Count());
iface.Assign(iftable->GetInterface(k));
- // Iterate through every declared method on this interface. The order does not matter.
- for (auto& method_iter : iface->GetDeclaredVirtualMethods(image_pointer_size_)) {
- ArtMethod* current_method = &method_iter;
+ size_t num_instance_methods = iface->NumVirtualMethods();
+ // Iterate through every method on this interface. The order does not matter so we go forwards.
+ for (size_t m = 0; m < num_instance_methods; m++) {
+ ArtMethod* current_method = iface->GetVirtualMethodUnchecked(m, image_pointer_size_);
// Skip abstract methods and methods with different names.
if (current_method->IsAbstract() ||
!target_name_comparator.HasSameNameAndSignature(
@@ -5321,27 +5327,6 @@
return nullptr;
}
-static void SanityCheckVTable(Handle<mirror::Class> klass, uint32_t pointer_size)
- SHARED_REQUIRES(Locks::mutator_lock_) {
- mirror::PointerArray* check_vtable = klass->GetVTableDuringLinking();
- mirror::Class* superclass = (klass->HasSuperClass()) ? klass->GetSuperClass() : nullptr;
- int32_t super_vtable_length = (superclass != nullptr) ? superclass->GetVTableLength() : 0;
- for (int32_t i = 0; i < check_vtable->GetLength(); ++i) {
- ArtMethod* m = check_vtable->GetElementPtrSize<ArtMethod*>(i, pointer_size);
- CHECK(m != nullptr);
-
- ArraySlice<ArtMethod> virtuals = klass->GetVirtualMethodsSliceUnchecked(pointer_size);
- auto is_same_method = [m] (const ArtMethod& meth) {
- return &meth == m;
- };
- CHECK((super_vtable_length > i && superclass->GetVTableEntry(i, pointer_size) == m) ||
- std::find_if(virtuals.begin(), virtuals.end(), is_same_method) != virtuals.end())
- << "While linking class '" << PrettyClass(klass.Get()) << "' unable to find owning class "
- << "of '" << PrettyMethod(m) << "' (vtable index: " << i << ").";
- }
-}
-
-// TODO Combine virtuals and directs.
bool ClassLinker::LinkInterfaceMethods(
Thread* self,
Handle<mirror::Class> klass,
@@ -5464,27 +5449,25 @@
const bool super_interface = is_super && extend_super_iftable;
auto method_array(hs2.NewHandle(iftable->GetMethodArray(i)));
- ArraySlice<ArtMethod> input_virtual_methods;
+ LengthPrefixedArray<ArtMethod>* input_virtual_methods = nullptr;
Handle<mirror::PointerArray> input_vtable_array = NullHandle<mirror::PointerArray>();
int32_t input_array_length = 0;
-
// TODO Cleanup Needed: In the presence of default methods this optimization is rather dirty
// and confusing. Default methods should always look through all the superclasses
// because they are the last choice of an implementation. We get around this by looking
// at the super-classes iftable methods (copied into method_array previously) when we are
// looking for the implementation of a super-interface method but that is rather dirty.
if (super_interface) {
- // If we are overwriting a super class interface, try to only virtual methods instead of the
+ // We are overwriting a super class interface, try to only virtual methods instead of the
// whole vtable.
- input_virtual_methods = klass->GetDeclaredMethodsSlice(image_pointer_size_);
- input_array_length = input_virtual_methods.size();
+ input_virtual_methods = klass->GetVirtualMethodsPtr();
+ input_array_length = klass->NumVirtualMethods();
} else {
- // For a new interface, however, we need the whole vtable in case a new
- // interface method is implemented in the whole superclass.
+ // A new interface, we need the whole vtable in case a new interface method is implemented
+ // in the whole superclass.
input_vtable_array = vtable;
input_array_length = input_vtable_array->GetLength();
}
-
// For each method in interface
for (size_t j = 0; j < num_methods; ++j) {
auto* interface_method = iftable->GetInterface(i)->GetVirtualMethod(j, image_pointer_size_);
@@ -5505,8 +5488,8 @@
bool found_impl = false;
ArtMethod* vtable_impl = nullptr;
for (int32_t k = input_array_length - 1; k >= 0; --k) {
- ArtMethod* vtable_method = input_vtable_array.Get() == nullptr ?
- &input_virtual_methods[k] :
+ ArtMethod* vtable_method = input_virtual_methods != nullptr ?
+ &input_virtual_methods->At(k, method_size, method_alignment) :
input_vtable_array->GetElementPtrSize<ArtMethod*>(k, image_pointer_size_);
ArtMethod* vtable_method_for_name_comparison =
vtable_method->GetInterfaceMethodIfProxy(image_pointer_size_);
@@ -5667,39 +5650,38 @@
VLOG(class_linker) << PrettyClass(klass.Get()) << ": miranda_methods=" << miranda_methods.size()
<< " default_methods=" << default_methods.size()
<< " default_conflict_methods=" << default_conflict_methods.size();
- const size_t old_method_count = klass->NumMethods();
+ const size_t old_method_count = klass->NumVirtualMethods();
const size_t new_method_count = old_method_count +
miranda_methods.size() +
default_methods.size() +
default_conflict_methods.size();
// Attempt to realloc to save RAM if possible.
- LengthPrefixedArray<ArtMethod>* old_methods = klass->GetMethodsPtr();
- // The Realloced virtual methods aren't visible from the class roots, so there is no issue
+ LengthPrefixedArray<ArtMethod>* old_virtuals = klass->GetVirtualMethodsPtr();
+ // The Realloced virtual methods aren't visiblef from the class roots, so there is no issue
// where GCs could attempt to mark stale pointers due to memcpy. And since we overwrite the
// realloced memory with out->CopyFrom, we are guaranteed to have objects in the to space since
// CopyFrom has internal read barriers.
- //
- // TODO We should maybe move some of this into mirror::Class or at least into another method.
- const size_t old_size = LengthPrefixedArray<ArtMethod>::ComputeSize(old_method_count,
- method_size,
- method_alignment);
+ const size_t old_size = old_virtuals != nullptr
+ ? LengthPrefixedArray<ArtMethod>::ComputeSize(old_method_count,
+ method_size,
+ method_alignment)
+ : 0u;
const size_t new_size = LengthPrefixedArray<ArtMethod>::ComputeSize(new_method_count,
method_size,
method_alignment);
- const size_t old_methods_ptr_size = (old_methods != nullptr) ? old_size : 0;
- auto* methods = reinterpret_cast<LengthPrefixedArray<ArtMethod>*>(
- runtime->GetLinearAlloc()->Realloc(self, old_methods, old_methods_ptr_size, new_size));
- if (UNLIKELY(methods == nullptr)) {
+ auto* virtuals = reinterpret_cast<LengthPrefixedArray<ArtMethod>*>(
+ runtime->GetLinearAlloc()->Realloc(self, old_virtuals, old_size, new_size));
+ if (UNLIKELY(virtuals == nullptr)) {
self->AssertPendingOOMException();
self->EndAssertNoThreadSuspension(old_cause);
return false;
}
ScopedArenaUnorderedMap<ArtMethod*, ArtMethod*> move_table(allocator.Adapter());
- if (methods != old_methods) {
+ if (virtuals != old_virtuals) {
// Maps from heap allocated miranda method to linear alloc miranda method.
- StrideIterator<ArtMethod> out = methods->begin(method_size, method_alignment);
- // Copy over the old methods.
- for (auto& m : klass->GetMethods(image_pointer_size_)) {
+ StrideIterator<ArtMethod> out = virtuals->begin(method_size, method_alignment);
+ // Copy over the old methods + miranda methods.
+ for (auto& m : klass->GetVirtualMethods(image_pointer_size_)) {
move_table.emplace(&m, &*out);
// The CopyFrom is only necessary to not miss read barriers since Realloc won't do read
// barriers when it copies.
@@ -5707,7 +5689,8 @@
++out;
}
}
- StrideIterator<ArtMethod> out(methods->begin(method_size, method_alignment) + old_method_count);
+ StrideIterator<ArtMethod> out(virtuals->begin(method_size, method_alignment)
+ + old_method_count);
// Copy over miranda methods before copying vtable since CopyOf may cause thread suspension and
// we want the roots of the miranda methods to get visited.
for (ArtMethod* mir_method : miranda_methods) {
@@ -5719,8 +5702,9 @@
move_table.emplace(mir_method, &new_method);
++out;
}
- // We need to copy the default methods into our own method table since the runtime requires that
- // every method on a class's vtable be in that respective class's virtual method table.
+ // We need to copy the default methods into our own virtual method table since the runtime
+ // requires that every method on a class's vtable be in that respective class's virtual method
+ // table.
// NOTE This means that two classes might have the same implementation of a method from the same
// interface but will have different ArtMethod*s for them. This also means we cannot compare a
// default method found on a class with one found on the declaring interface directly and must
@@ -5754,8 +5738,8 @@
move_table.emplace(conf_method, &new_method);
++out;
}
- methods->SetSize(new_method_count);
- UpdateClassMethods(klass.Get(), methods);
+ virtuals->SetSize(new_method_count);
+ UpdateClassVirtualMethods(klass.Get(), virtuals);
// Done copying methods, they are all roots in the class now, so we can end the no thread
// suspension assert.
self->EndAssertNoThreadSuspension(old_cause);
@@ -5771,7 +5755,7 @@
self->AssertPendingOOMException();
return false;
}
- out = methods->begin(method_size, method_alignment) + old_method_count;
+ out = virtuals->begin(method_size, method_alignment) + old_method_count;
size_t vtable_pos = old_vtable_count;
for (size_t i = old_method_count; i < new_method_count; ++i) {
// Leave the declaring class alone as type indices are relative to it
@@ -5825,16 +5809,8 @@
}
}
- if (kIsDebugBuild) {
- for (size_t i = 0; i < new_vtable_count; ++i) {
- CHECK(move_table.find(vtable->GetElementPtrSize<ArtMethod*>(i, image_pointer_size_)) ==
- move_table.end());
- }
- }
-
klass->SetVTable(vtable.Get());
- // Go fix up all the stale (old miranda or default method) pointers.
- // First do it on the iftable.
+ // Go fix up all the stale miranda pointers.
for (size_t i = 0; i < ifcount; ++i) {
for (size_t j = 0, count = iftable->GetMethodArrayCount(i); j < count; ++j) {
auto* method_array = iftable->GetMethodArray(i);
@@ -5848,7 +5824,7 @@
}
}
}
- // Fix up IMT next
+ // Fix up IMT in case it has any miranda methods in it.
for (size_t i = 0; i < mirror::Class::kImtSize; ++i) {
auto it = move_table.find(out_imt[i]);
if (it != move_table.end()) {
@@ -5860,26 +5836,25 @@
auto* resolved_methods = klass->GetDexCache()->GetResolvedMethods();
for (size_t i = 0, count = klass->GetDexCache()->NumResolvedMethods(); i < count; ++i) {
auto* m = mirror::DexCache::GetElementPtrSize(resolved_methods, i, image_pointer_size_);
- CHECK(move_table.find(m) == move_table.end() ||
- // The original versions of copied methods will still be present so allow those too.
- // Note that if the first check passes this might fail to GetDeclaringClass().
- std::find_if(m->GetDeclaringClass()->GetMethods(image_pointer_size_).begin(),
- m->GetDeclaringClass()->GetMethods(image_pointer_size_).end(),
- [m] (ArtMethod& meth) {
- return &meth == m;
- }) != m->GetDeclaringClass()->GetMethods(image_pointer_size_).end())
- << "Obsolete methods " << PrettyMethod(m) << " is in dex cache!";
+ // We don't remove default methods from the move table since we need them to update the
+ // vtable. Therefore just skip them for this check.
+ if (!m->IsDefault()) {
+ CHECK(move_table.find(m) == move_table.end()) << PrettyMethod(m);
+ }
}
}
- // Put some random garbage in old methods to help find stale pointers.
- if (methods != old_methods && old_methods != nullptr) {
- memset(old_methods, 0xFEu, old_size);
+ // Put some random garbage in old virtuals to help find stale pointers.
+ if (virtuals != old_virtuals) {
+ memset(old_virtuals, 0xFEu, old_size);
}
} else {
self->EndAssertNoThreadSuspension(old_cause);
}
if (kIsDebugBuild) {
- SanityCheckVTable(klass, image_pointer_size_);
+ auto* check_vtable = klass->GetVTableDuringLinking();
+ for (int i = 0; i < check_vtable->GetLength(); ++i) {
+ CHECK(check_vtable->GetElementPtrSize<ArtMethod*>(i, image_pointer_size_) != nullptr);
+ }
}
return true;
}
@@ -5954,20 +5929,6 @@
// we want a relatively stable order so that adding new fields
// minimizes disruption of C++ version such as Class and Method.
- //
- // The overall sort order order is:
- // 1) All object reference fields, sorted alphabetically.
- // 2) All java long (64-bit) integer fields, sorted alphabetically.
- // 3) All java double (64-bit) floating point fields, sorted alphabetically.
- // 4) All java int (32-bit) integer fields, sorted alphabetically.
- // 5) All java float (32-bit) floating point fields, sorted alphabetically.
- // 6) All java char (16-bit) integer fields, sorted alphabetically.
- // 7) All java short (16-bit) integer fields, sorted alphabetically.
- // 8) All java boolean (8-bit) integer fields, sorted alphabetically.
- // 9) All java byte (8-bit) integer fields, sorted alphabetically.
- //
- // Once the fields are sorted in this order we will attempt to fill any gaps that might be present
- // in the memory layout of the structure. See ShuffleForward for how this is done.
std::deque<ArtField*> grouped_and_sorted_fields;
const char* old_no_suspend_cause = self->StartAssertNoThreadSuspension(
"Naked ArtField references in deque");
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index f16fe92..0d3bc1e 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -983,8 +983,8 @@
bool CanWeInitializeClass(mirror::Class* klass, bool can_init_statics, bool can_init_parents)
SHARED_REQUIRES(Locks::mutator_lock_);
- void UpdateClassMethods(mirror::Class* klass,
- LengthPrefixedArray<ArtMethod>* new_methods)
+ void UpdateClassVirtualMethods(mirror::Class* klass,
+ LengthPrefixedArray<ArtMethod>* new_methods)
SHARED_REQUIRES(Locks::mutator_lock_)
REQUIRES(!Locks::classlinker_classes_lock_);
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index 387ac0a..2c086c5 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -254,20 +254,10 @@
EXPECT_EQ(klass.Get(), method.GetDeclaringClass());
}
- for (ArtMethod& method : klass->GetDeclaredVirtualMethods(sizeof(void*))) {
+ for (ArtMethod& method : klass->GetVirtualMethods(sizeof(void*))) {
AssertMethod(&method);
EXPECT_FALSE(method.IsDirect());
- EXPECT_EQ(klass.Get(), method.GetDeclaringClass());
- }
-
- for (ArtMethod& method : klass->GetCopiedMethods(sizeof(void*))) {
- AssertMethod(&method);
- EXPECT_FALSE(method.IsDirect());
- EXPECT_TRUE(method.IsMiranda() || method.IsDefault() || method.IsDefaultConflicting());
- EXPECT_TRUE(method.GetDeclaringClass()->IsInterface())
- << "declaring class: " << PrettyClass(method.GetDeclaringClass());
- EXPECT_TRUE(method.GetDeclaringClass()->IsAssignableFrom(klass.Get()))
- << "declaring class: " << PrettyClass(method.GetDeclaringClass());
+ EXPECT_TRUE(method.GetDeclaringClass()->IsAssignableFrom(klass.Get()));
}
for (size_t i = 0; i < klass->NumInstanceFields(); i++) {
@@ -506,14 +496,13 @@
addOffset(OFFSETOF_MEMBER(mirror::Class, class_size_), "classSize");
addOffset(OFFSETOF_MEMBER(mirror::Class, clinit_thread_id_), "clinitThreadId");
addOffset(OFFSETOF_MEMBER(mirror::Class, component_type_), "componentType");
- addOffset(OFFSETOF_MEMBER(mirror::Class, copied_methods_offset_), "copiedMethodsOffset");
addOffset(OFFSETOF_MEMBER(mirror::Class, dex_cache_), "dexCache");
addOffset(OFFSETOF_MEMBER(mirror::Class, dex_cache_strings_), "dexCacheStrings");
addOffset(OFFSETOF_MEMBER(mirror::Class, dex_class_def_idx_), "dexClassDefIndex");
addOffset(OFFSETOF_MEMBER(mirror::Class, dex_type_idx_), "dexTypeIndex");
+ addOffset(OFFSETOF_MEMBER(mirror::Class, direct_methods_), "directMethods");
addOffset(OFFSETOF_MEMBER(mirror::Class, ifields_), "iFields");
addOffset(OFFSETOF_MEMBER(mirror::Class, iftable_), "ifTable");
- addOffset(OFFSETOF_MEMBER(mirror::Class, methods_), "methods");
addOffset(OFFSETOF_MEMBER(mirror::Class, name_), "name");
addOffset(OFFSETOF_MEMBER(mirror::Class, num_reference_instance_fields_),
"numReferenceInstanceFields");
@@ -527,7 +516,7 @@
addOffset(OFFSETOF_MEMBER(mirror::Class, status_), "status");
addOffset(OFFSETOF_MEMBER(mirror::Class, super_class_), "superClass");
addOffset(OFFSETOF_MEMBER(mirror::Class, verify_error_), "verifyError");
- addOffset(OFFSETOF_MEMBER(mirror::Class, virtual_methods_offset_), "virtualMethodsOffset");
+ addOffset(OFFSETOF_MEMBER(mirror::Class, virtual_methods_), "virtualMethods");
addOffset(OFFSETOF_MEMBER(mirror::Class, vtable_), "vtable");
};
};
@@ -1133,7 +1122,10 @@
SHARED_REQUIRES(Locks::mutator_lock_) {
EXPECT_EQ((c->GetAccessFlags() & kAccPreverified) != 0U, preverified)
<< "Class " << PrettyClass(c) << " not as expected";
- for (auto& m : c->GetMethods(sizeof(void*))) {
+ for (auto& m : c->GetDirectMethods(sizeof(void*))) {
+ CheckMethod(&m, preverified);
+ }
+ for (auto& m : c->GetVirtualMethods(sizeof(void*))) {
CheckMethod(&m, preverified);
}
}
diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc
index 915d9ab..87e29ae 100644
--- a/runtime/entrypoints/entrypoint_utils.cc
+++ b/runtime/entrypoints/entrypoint_utils.cc
@@ -306,13 +306,11 @@
mirror::Method* interface_method = soa.Decode<mirror::Method*>(interface_method_jobj);
ArtMethod* proxy_method = rcvr->GetClass()->FindVirtualMethodForInterface(
interface_method->GetArtMethod(), sizeof(void*));
- auto virtual_methods = proxy_class->GetVirtualMethodsSlice(sizeof(void*));
+ auto* virtual_methods = proxy_class->GetVirtualMethodsPtr();
size_t num_virtuals = proxy_class->NumVirtualMethods();
size_t method_size = ArtMethod::Size(sizeof(void*));
- // Rely on the fact that the methods are contiguous to determine the index of the method in
- // the slice.
int throws_index = (reinterpret_cast<uintptr_t>(proxy_method) -
- reinterpret_cast<uintptr_t>(&virtual_methods.At(0))) / method_size;
+ reinterpret_cast<uintptr_t>(virtual_methods)) / method_size;
CHECK_LT(throws_index, static_cast<int>(num_virtuals));
mirror::ObjectArray<mirror::Class>* declared_exceptions =
proxy_class->GetThrows()->Get(throws_index);
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index cb67ee3..5e3fa19 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -316,7 +316,12 @@
static ArtMethod* FindMethod(mirror::Class* c, const StringPiece& name, const StringPiece& sig)
SHARED_REQUIRES(Locks::mutator_lock_) {
auto pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
- for (auto& method : c->GetMethods(pointer_size)) {
+ for (auto& method : c->GetDirectMethods(pointer_size)) {
+ if (kNative == method.IsNative() && name == method.GetName() && method.GetSignature() == sig) {
+ return &method;
+ }
+ }
+ for (auto& method : c->GetVirtualMethods(pointer_size)) {
if (kNative == method.IsNative() && name == method.GetName() && method.GetSignature() == sig) {
return &method;
}
@@ -2215,7 +2220,13 @@
size_t unregistered_count = 0;
auto pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
- for (auto& m : c->GetMethods(pointer_size)) {
+ for (auto& m : c->GetDirectMethods(pointer_size)) {
+ if (m.IsNative()) {
+ m.UnregisterNative();
+ unregistered_count++;
+ }
+ }
+ for (auto& m : c->GetVirtualMethods(pointer_size)) {
if (m.IsNative()) {
m.UnregisterNative();
unregistered_count++;
diff --git a/runtime/base/length_prefixed_array.h b/runtime/length_prefixed_array.h
similarity index 95%
rename from runtime/base/length_prefixed_array.h
rename to runtime/length_prefixed_array.h
index d632871..e01b6cc 100644
--- a/runtime/base/length_prefixed_array.h
+++ b/runtime/length_prefixed_array.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_BASE_LENGTH_PREFIXED_ARRAY_H_
-#define ART_RUNTIME_BASE_LENGTH_PREFIXED_ARRAY_H_
+#ifndef ART_RUNTIME_LENGTH_PREFIXED_ARRAY_H_
+#define ART_RUNTIME_LENGTH_PREFIXED_ARRAY_H_
#include <stddef.h> // for offsetof()
@@ -110,4 +110,4 @@
} // namespace art
-#endif // ART_RUNTIME_BASE_LENGTH_PREFIXED_ARRAY_H_
+#endif // ART_RUNTIME_LENGTH_PREFIXED_ARRAY_H_
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index ef4fe15..9e416dc 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -22,14 +22,13 @@
#include "art_field-inl.h"
#include "art_method.h"
#include "art_method-inl.h"
-#include "base/array_slice.h"
-#include "base/length_prefixed_array.h"
#include "class_loader.h"
#include "common_throws.h"
#include "dex_cache.h"
#include "dex_file.h"
#include "gc/heap-inl.h"
#include "iftable.h"
+#include "length_prefixed_array.h"
#include "object_array-inl.h"
#include "read_barrier-inl.h"
#include "reference-inl.h"
@@ -63,148 +62,61 @@
return GetFieldObject<DexCache, kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_));
}
-inline uint32_t Class::GetCopiedMethodsStartOffset() {
- return GetFieldShort(OFFSET_OF_OBJECT_MEMBER(Class, copied_methods_offset_));
-}
-
-inline uint32_t Class::GetDirectMethodsStartOffset() {
- return 0;
-}
-
-inline uint32_t Class::GetVirtualMethodsStartOffset() {
- return GetFieldShort(OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_offset_));
-}
-
-template<VerifyObjectFlags kVerifyFlags>
-inline ArraySlice<ArtMethod> Class::GetDirectMethodsSlice(size_t pointer_size) {
+inline LengthPrefixedArray<ArtMethod>* Class::GetDirectMethodsPtr() {
DCHECK(IsLoaded() || IsErroneous());
- DCHECK(ValidPointerSize(pointer_size)) << pointer_size;
- return GetDirectMethodsSliceUnchecked(pointer_size);
+ return GetDirectMethodsPtrUnchecked();
}
-inline ArraySlice<ArtMethod> Class::GetDirectMethodsSliceUnchecked(size_t pointer_size) {
- return ArraySlice<ArtMethod>(GetMethodsPtr(),
- GetDirectMethodsStartOffset(),
- GetVirtualMethodsStartOffset(),
- ArtMethod::Size(pointer_size),
- ArtMethod::Alignment(pointer_size));
-}
-
-template<VerifyObjectFlags kVerifyFlags>
-inline ArraySlice<ArtMethod> Class::GetDeclaredMethodsSlice(size_t pointer_size) {
- DCHECK(IsLoaded() || IsErroneous());
- DCHECK(ValidPointerSize(pointer_size)) << pointer_size;
- return GetDeclaredMethodsSliceUnchecked(pointer_size);
-}
-
-inline ArraySlice<ArtMethod> Class::GetDeclaredMethodsSliceUnchecked(size_t pointer_size) {
- return ArraySlice<ArtMethod>(GetMethodsPtr(),
- GetDirectMethodsStartOffset(),
- GetCopiedMethodsStartOffset(),
- ArtMethod::Size(pointer_size),
- ArtMethod::Alignment(pointer_size));
-}
-template<VerifyObjectFlags kVerifyFlags>
-inline ArraySlice<ArtMethod> Class::GetDeclaredVirtualMethodsSlice(size_t pointer_size) {
- DCHECK(IsLoaded() || IsErroneous());
- DCHECK(ValidPointerSize(pointer_size)) << pointer_size;
- return GetDeclaredVirtualMethodsSliceUnchecked(pointer_size);
-}
-
-inline ArraySlice<ArtMethod> Class::GetDeclaredVirtualMethodsSliceUnchecked(size_t pointer_size) {
- return ArraySlice<ArtMethod>(GetMethodsPtr(),
- GetVirtualMethodsStartOffset(),
- GetCopiedMethodsStartOffset(),
- ArtMethod::Size(pointer_size),
- ArtMethod::Alignment(pointer_size));
-}
-
-template<VerifyObjectFlags kVerifyFlags>
-inline ArraySlice<ArtMethod> Class::GetVirtualMethodsSlice(size_t pointer_size) {
- DCHECK(IsLoaded() || IsErroneous());
- DCHECK(ValidPointerSize(pointer_size)) << pointer_size;
- return GetVirtualMethodsSliceUnchecked(pointer_size);
-}
-
-inline ArraySlice<ArtMethod> Class::GetVirtualMethodsSliceUnchecked(size_t pointer_size) {
- LengthPrefixedArray<ArtMethod>* methods = GetMethodsPtr();
- return ArraySlice<ArtMethod>(methods,
- GetVirtualMethodsStartOffset(),
- NumMethods(),
- ArtMethod::Size(pointer_size),
- ArtMethod::Alignment(pointer_size));
-}
-
-template<VerifyObjectFlags kVerifyFlags>
-inline ArraySlice<ArtMethod> Class::GetCopiedMethodsSlice(size_t pointer_size) {
- DCHECK(IsLoaded() || IsErroneous());
- DCHECK(ValidPointerSize(pointer_size)) << pointer_size;
- return GetCopiedMethodsSliceUnchecked(pointer_size);
-}
-
-inline ArraySlice<ArtMethod> Class::GetCopiedMethodsSliceUnchecked(size_t pointer_size) {
- LengthPrefixedArray<ArtMethod>* methods = GetMethodsPtr();
- return ArraySlice<ArtMethod>(methods,
- GetCopiedMethodsStartOffset(),
- NumMethods(),
- ArtMethod::Size(pointer_size),
- ArtMethod::Alignment(pointer_size));
-}
-
-inline LengthPrefixedArray<ArtMethod>* Class::GetMethodsPtr() {
+inline LengthPrefixedArray<ArtMethod>* Class::GetDirectMethodsPtrUnchecked() {
return reinterpret_cast<LengthPrefixedArray<ArtMethod>*>(
- GetField64(OFFSET_OF_OBJECT_MEMBER(Class, methods_)));
+ GetField64(OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_)));
}
-template<VerifyObjectFlags kVerifyFlags>
-inline ArraySlice<ArtMethod> Class::GetMethodsSlice(size_t pointer_size) {
- DCHECK(IsLoaded() || IsErroneous());
- LengthPrefixedArray<ArtMethod>* methods = GetMethodsPtr();
- return ArraySlice<ArtMethod>(methods,
- 0,
- NumMethods(),
- ArtMethod::Size(pointer_size),
- ArtMethod::Alignment(pointer_size));
+inline LengthPrefixedArray<ArtMethod>* Class::GetVirtualMethodsPtrUnchecked() {
+ return reinterpret_cast<LengthPrefixedArray<ArtMethod>*>(
+ GetField64(OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_)));
}
+inline void Class::SetDirectMethodsPtr(LengthPrefixedArray<ArtMethod>* new_direct_methods) {
+ DCHECK(GetDirectMethodsPtrUnchecked() == nullptr);
+ SetDirectMethodsPtrUnchecked(new_direct_methods);
+}
-inline uint32_t Class::NumMethods() {
- LengthPrefixedArray<ArtMethod>* methods = GetMethodsPtr();
- return (methods == nullptr) ? 0 : methods->size();
+inline void Class::SetDirectMethodsPtrUnchecked(
+ LengthPrefixedArray<ArtMethod>* new_direct_methods) {
+ SetField64<false>(OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_),
+ reinterpret_cast<uint64_t>(new_direct_methods));
}
inline ArtMethod* Class::GetDirectMethodUnchecked(size_t i, size_t pointer_size) {
CheckPointerSize(pointer_size);
- return &GetDirectMethodsSliceUnchecked(pointer_size).At(i);
+ auto* methods = GetDirectMethodsPtrUnchecked();
+ DCHECK(methods != nullptr);
+ return &methods->At(i,
+ ArtMethod::Size(pointer_size),
+ ArtMethod::Alignment(pointer_size));
}
inline ArtMethod* Class::GetDirectMethod(size_t i, size_t pointer_size) {
CheckPointerSize(pointer_size);
- return &GetDirectMethodsSlice(pointer_size).At(i);
+ auto* methods = GetDirectMethodsPtr();
+ DCHECK(methods != nullptr);
+ return &methods->At(i,
+ ArtMethod::Size(pointer_size),
+ ArtMethod::Alignment(pointer_size));
}
-inline void Class::SetMethodsPtr(LengthPrefixedArray<ArtMethod>* new_methods,
- uint32_t num_direct,
- uint32_t num_virtual) {
- DCHECK(GetMethodsPtr() == nullptr);
- SetMethodsPtrUnchecked(new_methods, num_direct, num_virtual);
+template<VerifyObjectFlags kVerifyFlags>
+inline LengthPrefixedArray<ArtMethod>* Class::GetVirtualMethodsPtr() {
+ DCHECK(IsLoaded<kVerifyFlags>() || IsErroneous<kVerifyFlags>());
+ return GetVirtualMethodsPtrUnchecked();
}
-
-inline void Class::SetMethodsPtrUnchecked(LengthPrefixedArray<ArtMethod>* new_methods,
- uint32_t num_direct,
- uint32_t num_virtual) {
- DCHECK_LE(num_direct + num_virtual, (new_methods == nullptr) ? 0 : new_methods->size());
- SetMethodsPtrInternal(new_methods);
- SetFieldShort<false>(OFFSET_OF_OBJECT_MEMBER(Class, copied_methods_offset_),
- dchecked_integral_cast<uint16_t>(num_direct + num_virtual));
- SetFieldShort<false>(OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_offset_),
- dchecked_integral_cast<uint16_t>(num_direct));
-}
-
-inline void Class::SetMethodsPtrInternal(LengthPrefixedArray<ArtMethod>* new_methods) {
- SetField64<false>(OFFSET_OF_OBJECT_MEMBER(Class, methods_),
- reinterpret_cast<uint64_t>(new_methods));
+inline void Class::SetVirtualMethodsPtr(LengthPrefixedArray<ArtMethod>* new_virtual_methods) {
+ // TODO: we reassign virtual methods to grow the table for miranda
+ // methods.. they should really just be assigned once.
+ SetField64<false>(OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_),
+ reinterpret_cast<uint64_t>(new_virtual_methods));
}
template<VerifyObjectFlags kVerifyFlags>
@@ -223,7 +135,11 @@
inline ArtMethod* Class::GetVirtualMethodUnchecked(size_t i, size_t pointer_size) {
CheckPointerSize(pointer_size);
- return &GetVirtualMethodsSliceUnchecked(pointer_size).At(i);
+ LengthPrefixedArray<ArtMethod>* methods = GetVirtualMethodsPtrUnchecked();
+ DCHECK(methods != nullptr);
+ return &methods->At(i,
+ ArtMethod::Size(pointer_size),
+ ArtMethod::Alignment(pointer_size));
}
inline PointerArray* Class::GetVTable() {
@@ -917,42 +833,24 @@
CHECK_EQ(field.GetDeclaringClass(), this) << GetStatus();
}
}
- for (ArtMethod& method : GetMethods(pointer_size)) {
+ for (ArtMethod& method : GetDirectMethods(pointer_size)) {
+ method.VisitRoots(visitor, pointer_size);
+ }
+ for (ArtMethod& method : GetVirtualMethods(pointer_size)) {
method.VisitRoots(visitor, pointer_size);
}
}
inline IterationRange<StrideIterator<ArtMethod>> Class::GetDirectMethods(size_t pointer_size) {
CheckPointerSize(pointer_size);
- return GetDirectMethodsSliceUnchecked(pointer_size).AsRange();
-}
-
-inline IterationRange<StrideIterator<ArtMethod>> Class::GetDeclaredMethods(
- size_t pointer_size) {
- CheckPointerSize(pointer_size);
- return GetDeclaredMethodsSliceUnchecked(pointer_size).AsRange();
-}
-
-inline IterationRange<StrideIterator<ArtMethod>> Class::GetDeclaredVirtualMethods(
- size_t pointer_size) {
- CheckPointerSize(pointer_size);
- return GetDeclaredVirtualMethodsSliceUnchecked(pointer_size).AsRange();
+ return MakeIterationRangeFromLengthPrefixedArray(GetDirectMethodsPtrUnchecked(),
+ ArtMethod::Size(pointer_size),
+ ArtMethod::Alignment(pointer_size));
}
inline IterationRange<StrideIterator<ArtMethod>> Class::GetVirtualMethods(size_t pointer_size) {
CheckPointerSize(pointer_size);
- return GetVirtualMethodsSliceUnchecked(pointer_size).AsRange();
-}
-
-inline IterationRange<StrideIterator<ArtMethod>> Class::GetCopiedMethods(size_t pointer_size) {
- CheckPointerSize(pointer_size);
- return GetCopiedMethodsSliceUnchecked(pointer_size).AsRange();
-}
-
-
-inline IterationRange<StrideIterator<ArtMethod>> Class::GetMethods(size_t pointer_size) {
- CheckPointerSize(pointer_size);
- return MakeIterationRangeFromLengthPrefixedArray(GetMethodsPtr(),
+ return MakeIterationRangeFromLengthPrefixedArray(GetVirtualMethodsPtrUnchecked(),
ArtMethod::Size(pointer_size),
ArtMethod::Alignment(pointer_size));
}
@@ -1020,15 +918,13 @@
}
inline uint32_t Class::NumDirectMethods() {
- return GetVirtualMethodsStartOffset();
-}
-
-inline uint32_t Class::NumDeclaredVirtualMethods() {
- return GetCopiedMethodsStartOffset() - GetVirtualMethodsStartOffset();
+ LengthPrefixedArray<ArtMethod>* arr = GetDirectMethodsPtrUnchecked();
+ return arr != nullptr ? arr->size() : 0u;
}
inline uint32_t Class::NumVirtualMethods() {
- return NumMethods() - GetVirtualMethodsStartOffset();
+ LengthPrefixedArray<ArtMethod>* arr = GetVirtualMethodsPtrUnchecked();
+ return arr != nullptr ? arr->size() : 0u;
}
inline uint32_t Class::NumInstanceFields() {
@@ -1056,11 +952,16 @@
if (ifields != new_ifields) {
dest->SetIFieldsPtrUnchecked(new_ifields);
}
- // Update method array.
- LengthPrefixedArray<ArtMethod>* methods = GetMethodsPtr();
- LengthPrefixedArray<ArtMethod>* new_methods = visitor(methods);
- if (methods != new_methods) {
- dest->SetMethodsPtrInternal(new_methods);
+ // Update direct and virtual method arrays.
+ LengthPrefixedArray<ArtMethod>* direct_methods = GetDirectMethodsPtr();
+ LengthPrefixedArray<ArtMethod>* new_direct_methods = visitor(direct_methods);
+ if (direct_methods != new_direct_methods) {
+ dest->SetDirectMethodsPtrUnchecked(new_direct_methods);
+ }
+ LengthPrefixedArray<ArtMethod>* virtual_methods = GetVirtualMethodsPtr();
+ LengthPrefixedArray<ArtMethod>* new_virtual_methods = visitor(virtual_methods);
+ if (virtual_methods != new_virtual_methods) {
+ dest->SetVirtualMethodsPtr(new_virtual_methods);
}
// Update dex cache strings.
GcRoot<mirror::String>* strings = GetDexCacheStrings();
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 66060f2..05a9039 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -457,10 +457,6 @@
return nullptr;
}
-// TODO These should maybe be changed to be named FindOwnedVirtualMethod or something similar
-// because they do not only find 'declared' methods and will return copied methods. This behavior is
-// desired and correct but the naming can lead to confusion because in the java language declared
-// excludes interface methods which might be found by this.
ArtMethod* Class::FindDeclaredVirtualMethod(const StringPiece& name, const StringPiece& signature,
size_t pointer_size) {
for (auto& method : GetVirtualMethods(pointer_size)) {
@@ -486,8 +482,10 @@
ArtMethod* Class::FindDeclaredVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx,
size_t pointer_size) {
if (GetDexCache() == dex_cache) {
- for (auto& method : GetDeclaredVirtualMethods(pointer_size)) {
- if (method.GetDexMethodIndex() == dex_method_idx) {
+ for (auto& method : GetVirtualMethods(pointer_size)) {
+ // A miranda method may have a different DexCache and is always created by linking,
+ // never *declared* in the class.
+ if (method.GetDexMethodIndex() == dex_method_idx && !method.IsMiranda()) {
return &method;
}
}
@@ -727,7 +725,12 @@
void Class::SetPreverifiedFlagOnAllMethods(size_t pointer_size) {
DCHECK(IsVerified());
- for (auto& m : GetMethods(pointer_size)) {
+ for (auto& m : GetDirectMethods(pointer_size)) {
+ if (!m.IsNative() && m.IsInvokable()) {
+ m.SetPreverified();
+ }
+ }
+ for (auto& m : GetVirtualMethods(pointer_size)) {
if (!m.IsNative() && m.IsInvokable()) {
m.SetPreverified();
}
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index ce879ba..0ab5b97 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -44,7 +44,6 @@
struct ClassOffsets;
template<class T> class Handle;
template<typename T> class LengthPrefixedArray;
-template<typename T> class ArraySlice;
class Signature;
class StringPiece;
template<size_t kNumReferences> class PACKED(4) StackHandleScope;
@@ -703,24 +702,12 @@
ALWAYS_INLINE IterationRange<StrideIterator<ArtMethod>> GetDirectMethods(size_t pointer_size)
SHARED_REQUIRES(Locks::mutator_lock_);
- ALWAYS_INLINE LengthPrefixedArray<ArtMethod>* GetMethodsPtr()
- SHARED_REQUIRES(Locks::mutator_lock_);
+ LengthPrefixedArray<ArtMethod>* GetDirectMethodsPtr() SHARED_REQUIRES(Locks::mutator_lock_);
- ALWAYS_INLINE IterationRange<StrideIterator<ArtMethod>> GetMethods(size_t pointer_size)
- SHARED_REQUIRES(Locks::mutator_lock_);
-
- void SetMethodsPtr(LengthPrefixedArray<ArtMethod>* new_methods,
- uint32_t num_direct,
- uint32_t num_virtual)
+ void SetDirectMethodsPtr(LengthPrefixedArray<ArtMethod>* new_direct_methods)
SHARED_REQUIRES(Locks::mutator_lock_);
// Used by image writer.
- void SetMethodsPtrUnchecked(LengthPrefixedArray<ArtMethod>* new_methods,
- uint32_t num_direct,
- uint32_t num_virtual)
- SHARED_REQUIRES(Locks::mutator_lock_);
-
- template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
- ALWAYS_INLINE ArraySlice<ArtMethod> GetDirectMethodsSlice(size_t pointer_size)
+ void SetDirectMethodsPtrUnchecked(LengthPrefixedArray<ArtMethod>* new_direct_methods)
SHARED_REQUIRES(Locks::mutator_lock_);
ALWAYS_INLINE ArtMethod* GetDirectMethod(size_t i, size_t pointer_size)
@@ -736,50 +723,18 @@
ALWAYS_INLINE uint32_t NumDirectMethods() SHARED_REQUIRES(Locks::mutator_lock_);
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
- ALWAYS_INLINE ArraySlice<ArtMethod> GetMethodsSlice(size_t pointer_size)
- SHARED_REQUIRES(Locks::mutator_lock_);
-
- template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
- ALWAYS_INLINE ArraySlice<ArtMethod> GetDeclaredMethodsSlice(size_t pointer_size)
- SHARED_REQUIRES(Locks::mutator_lock_);
-
- ALWAYS_INLINE IterationRange<StrideIterator<ArtMethod>> GetDeclaredMethods(
- size_t pointer_size)
- SHARED_REQUIRES(Locks::mutator_lock_);
-
- template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
- ALWAYS_INLINE ArraySlice<ArtMethod> GetDeclaredVirtualMethodsSlice(size_t pointer_size)
- SHARED_REQUIRES(Locks::mutator_lock_);
-
- ALWAYS_INLINE IterationRange<StrideIterator<ArtMethod>> GetDeclaredVirtualMethods(
- size_t pointer_size)
- SHARED_REQUIRES(Locks::mutator_lock_);
-
- template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
- ALWAYS_INLINE ArraySlice<ArtMethod> GetCopiedMethodsSlice(size_t pointer_size)
- SHARED_REQUIRES(Locks::mutator_lock_);
-
- ALWAYS_INLINE IterationRange<StrideIterator<ArtMethod>> GetCopiedMethods(size_t pointer_size)
- SHARED_REQUIRES(Locks::mutator_lock_);
-
- template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
- ALWAYS_INLINE ArraySlice<ArtMethod> GetVirtualMethodsSlice(size_t pointer_size)
+ ALWAYS_INLINE LengthPrefixedArray<ArtMethod>* GetVirtualMethodsPtr()
SHARED_REQUIRES(Locks::mutator_lock_);
ALWAYS_INLINE IterationRange<StrideIterator<ArtMethod>> GetVirtualMethods(size_t pointer_size)
SHARED_REQUIRES(Locks::mutator_lock_);
- // Returns the number of non-inherited virtual methods (sum of declared and copied methods).
+ void SetVirtualMethodsPtr(LengthPrefixedArray<ArtMethod>* new_virtual_methods)
+ SHARED_REQUIRES(Locks::mutator_lock_);
+
+ // Returns the number of non-inherited virtual methods.
ALWAYS_INLINE uint32_t NumVirtualMethods() SHARED_REQUIRES(Locks::mutator_lock_);
- // Returns the number of copied virtual methods.
- ALWAYS_INLINE uint32_t NumCopiedVirtualMethods() SHARED_REQUIRES(Locks::mutator_lock_);
-
- // Returns the number of declared virtual methods.
- ALWAYS_INLINE uint32_t NumDeclaredVirtualMethods() SHARED_REQUIRES(Locks::mutator_lock_);
-
- ALWAYS_INLINE uint32_t NumMethods() SHARED_REQUIRES(Locks::mutator_lock_);
-
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
ArtMethod* GetVirtualMethod(size_t i, size_t pointer_size)
SHARED_REQUIRES(Locks::mutator_lock_);
@@ -1200,19 +1155,10 @@
return pointer_size;
}
- ALWAYS_INLINE ArraySlice<ArtMethod> GetDirectMethodsSliceUnchecked(size_t pointer_size)
+ ALWAYS_INLINE LengthPrefixedArray<ArtMethod>* GetDirectMethodsPtrUnchecked()
SHARED_REQUIRES(Locks::mutator_lock_);
- ALWAYS_INLINE ArraySlice<ArtMethod> GetVirtualMethodsSliceUnchecked(size_t pointer_size)
- SHARED_REQUIRES(Locks::mutator_lock_);
-
- ALWAYS_INLINE ArraySlice<ArtMethod> GetDeclaredMethodsSliceUnchecked(size_t pointer_size)
- SHARED_REQUIRES(Locks::mutator_lock_);
-
- ALWAYS_INLINE ArraySlice<ArtMethod> GetDeclaredVirtualMethodsSliceUnchecked(size_t pointer_size)
- SHARED_REQUIRES(Locks::mutator_lock_);
-
- ALWAYS_INLINE ArraySlice<ArtMethod> GetCopiedMethodsSliceUnchecked(size_t pointer_size)
+ ALWAYS_INLINE LengthPrefixedArray<ArtMethod>* GetVirtualMethodsPtrUnchecked()
SHARED_REQUIRES(Locks::mutator_lock_);
// Fix up all of the native pointers in the class by running them through the visitor. Only sets
@@ -1223,9 +1169,6 @@
SHARED_REQUIRES(Locks::mutator_lock_);
private:
- ALWAYS_INLINE void SetMethodsPtrInternal(LengthPrefixedArray<ArtMethod>* new_methods)
- SHARED_REQUIRES(Locks::mutator_lock_);
-
void SetVerifyError(Object* klass) SHARED_REQUIRES(Locks::mutator_lock_);
template <bool throw_on_failure, bool use_referrers_cache>
@@ -1251,15 +1194,6 @@
IterationRange<StrideIterator<ArtField>> GetIFieldsUnchecked()
SHARED_REQUIRES(Locks::mutator_lock_);
- // The index in the methods_ array where the first declared virtual method is.
- ALWAYS_INLINE uint32_t GetVirtualMethodsStartOffset() SHARED_REQUIRES(Locks::mutator_lock_);
-
- // The index in the methods_ array where the first direct method is.
- ALWAYS_INLINE uint32_t GetDirectMethodsStartOffset() SHARED_REQUIRES(Locks::mutator_lock_);
-
- // The index in the methods_ array where the first copied method is.
- ALWAYS_INLINE uint32_t GetCopiedMethodsStartOffset() SHARED_REQUIRES(Locks::mutator_lock_);
-
bool ProxyDescriptorEquals(const char* match) SHARED_REQUIRES(Locks::mutator_lock_);
// Check that the pointer size matches the one in the class linker.
@@ -1272,9 +1206,6 @@
void VisitReferences(mirror::Class* klass, const Visitor& visitor)
SHARED_REQUIRES(Locks::mutator_lock_);
- // 'Class' Object Fields
- // Order governed by java field ordering. See art::ClassLinker::LinkFields.
-
// Defining class loader, or null for the "bootstrap" system loader.
HeapReference<ClassLoader> class_loader_;
@@ -1323,6 +1254,9 @@
// Short cuts to dex_cache_ member for fast compiled code access.
uint64_t dex_cache_strings_;
+ // static, private, and <init> methods. Pointer to an ArtMethod length-prefixed array.
+ uint64_t direct_methods_;
+
// instance fields
//
// These describe the layout of the contents of an Object.
@@ -1334,24 +1268,13 @@
// ArtFields.
uint64_t ifields_;
- // Pointer to an ArtMethod length-prefixed array. All the methods where this class is the place
- // where they are logically defined. This includes all private, static, final and virtual methods
- // as well as inherited default methods and miranda methods.
- //
- // The slice methods_ [0, virtual_methods_offset_) are the direct (static, private, init) methods
- // declared by this class.
- //
- // The slice methods_ [virtual_methods_offset_, copied_methods_offset_) are the virtual methods
- // declared by this class.
- //
- // The slice methods_ [copied_methods_offset_, |methods_|) are the methods that are copied from
- // interfaces such as miranda or default methods. These are copied for resolution purposes as this
- // class is where they are (logically) declared as far as the virtual dispatch is concerned.
- uint64_t methods_;
-
// Static fields length-prefixed array.
uint64_t sfields_;
+ // Virtual methods defined in this class; invoked through vtable. Pointer to an ArtMethod
+ // length-prefixed array.
+ uint64_t virtual_methods_;
+
// Access flags; low 16 bits are defined by VM spec.
uint32_t access_flags_;
@@ -1394,14 +1317,6 @@
// State of class initialization.
Status status_;
- // The offset of the first virtual method that is copied from an interface. This includes miranda,
- // default, and default-conflict methods. Having a hard limit of ((2 << 16) - 1) for methods
- // defined on a single class is well established in Java so we will use only uint16_t's here.
- uint16_t copied_methods_offset_;
-
- // The offset of the first declared virtual methods in the methods_ array.
- uint16_t virtual_methods_offset_;
-
// TODO: ?
// initiating class loader list
// NOTE: for classes with low serialNumber, these are unused, and the
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index 14d284e..5e42392 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -439,9 +439,16 @@
StackHandleScope<2> hs(soa.Self());
Handle<mirror::Class> klass = hs.NewHandle(DecodeClass(soa, javaThis));
size_t num_methods = 0;
- for (auto& m : klass->GetDeclaredMethods(sizeof(void*))) {
+ for (auto& m : klass->GetVirtualMethods(sizeof(void*))) {
auto modifiers = m.GetAccessFlags();
- // Add non-constructor declared methods.
+ if ((publicOnly == JNI_FALSE || (modifiers & kAccPublic) != 0) &&
+ (modifiers & kAccMiranda) == 0) {
+ ++num_methods;
+ }
+ }
+ for (auto& m : klass->GetDirectMethods(sizeof(void*))) {
+ auto modifiers = m.GetAccessFlags();
+ // Add non-constructor direct/static methods.
if ((publicOnly == JNI_FALSE || (modifiers & kAccPublic) != 0) &&
(modifiers & kAccConstructor) == 0) {
++num_methods;
@@ -450,9 +457,22 @@
auto ret = hs.NewHandle(mirror::ObjectArray<mirror::Method>::Alloc(
soa.Self(), mirror::Method::ArrayClass(), num_methods));
num_methods = 0;
- for (auto& m : klass->GetDeclaredMethods(sizeof(void*))) {
+ for (auto& m : klass->GetVirtualMethods(sizeof(void*))) {
auto modifiers = m.GetAccessFlags();
if ((publicOnly == JNI_FALSE || (modifiers & kAccPublic) != 0) &&
+ (modifiers & kAccMiranda) == 0) {
+ auto* method = mirror::Method::CreateFromArtMethod(soa.Self(), &m);
+ if (method == nullptr) {
+ soa.Self()->AssertPendingException();
+ return nullptr;
+ }
+ ret->SetWithoutChecks<false>(num_methods++, method);
+ }
+ }
+ for (auto& m : klass->GetDirectMethods(sizeof(void*))) {
+ auto modifiers = m.GetAccessFlags();
+ // Add non-constructor direct/static methods.
+ if ((publicOnly == JNI_FALSE || (modifiers & kAccPublic) != 0) &&
(modifiers & kAccConstructor) == 0) {
auto* method = mirror::Method::CreateFromArtMethod(soa.Self(), &m);
if (method == nullptr) {
diff --git a/runtime/native/java_lang_reflect_Method.cc b/runtime/native/java_lang_reflect_Method.cc
index d7cf62e..caacba6 100644
--- a/runtime/native/java_lang_reflect_Method.cc
+++ b/runtime/native/java_lang_reflect_Method.cc
@@ -71,7 +71,7 @@
mirror::Class* klass = method->GetDeclaringClass();
int throws_index = -1;
size_t i = 0;
- for (const auto& m : klass->GetDeclaredVirtualMethods(sizeof(void*))) {
+ for (const auto& m : klass->GetVirtualMethods(sizeof(void*))) {
if (&m == method) {
throws_index = i;
break;
diff --git a/runtime/native_bridge_art_interface.cc b/runtime/native_bridge_art_interface.cc
index 61a1085..46cc5aa 100644
--- a/runtime/native_bridge_art_interface.cc
+++ b/runtime/native_bridge_art_interface.cc
@@ -45,7 +45,10 @@
mirror::Class* c = soa.Decode<mirror::Class*>(clazz);
uint32_t native_method_count = 0;
- for (auto& m : c->GetMethods(sizeof(void*))) {
+ for (auto& m : c->GetDirectMethods(sizeof(void*))) {
+ native_method_count += m.IsNative() ? 1u : 0u;
+ }
+ for (auto& m : c->GetVirtualMethods(sizeof(void*))) {
native_method_count += m.IsNative() ? 1u : 0u;
}
return native_method_count;
@@ -60,7 +63,19 @@
mirror::Class* c = soa.Decode<mirror::Class*>(clazz);
uint32_t count = 0;
- for (auto& m : c->GetMethods(sizeof(void*))) {
+ for (auto& m : c->GetDirectMethods(sizeof(void*))) {
+ if (m.IsNative()) {
+ if (count < method_count) {
+ methods[count].name = m.GetName();
+ methods[count].signature = m.GetShorty();
+ methods[count].fnPtr = m.GetEntryPointFromJni();
+ count++;
+ } else {
+ LOG(WARNING) << "Output native method array too small. Skipping " << PrettyMethod(&m);
+ }
+ }
+ }
+ for (auto& m : c->GetVirtualMethods(sizeof(void*))) {
if (m.IsNative()) {
if (count < method_count) {
methods[count].name = m.GetName();
diff --git a/runtime/proxy_test.cc b/runtime/proxy_test.cc
index 4d9ca6d..57472ad 100644
--- a/runtime/proxy_test.cc
+++ b/runtime/proxy_test.cc
@@ -79,7 +79,7 @@
mirror::Method::CreateFromArtMethod(soa.Self(), method)));
// Now adds all interfaces virtual methods.
for (mirror::Class* interface : interfaces) {
- for (auto& m : interface->GetDeclaredVirtualMethods(sizeof(void*))) {
+ for (auto& m : interface->GetVirtualMethods(sizeof(void*))) {
soa.Env()->SetObjectArrayElement(
proxyClassMethods, array_index++, soa.AddLocalReference<jobject>(
mirror::Method::CreateFromArtMethod(soa.Self(), &m)));