Merge "Use explicit cast to avoid compilers error"
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index 00cd2f6..a834216 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -673,6 +673,16 @@
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(
soa.Decode<mirror::ClassLoader*>(dex_compilation_unit_->GetClassLoader())));
Handle<mirror::Class> compiling_class(hs.NewHandle(GetCompilingClass()));
+ // We fetch the referenced class eagerly (that is, the class pointed by in the MethodId
+ // at method_idx), as `CanAccessResolvedMethod` expects it be be in the dex cache.
+ Handle<mirror::Class> methods_class(hs.NewHandle(class_linker->ResolveReferencedClassOfMethod(
+ method_idx, dex_compilation_unit_->GetDexCache(), class_loader)));
+
+ if (UNLIKELY(methods_class.Get() == nullptr)) {
+ // Clean up any exception left by type resolution.
+ soa.Self()->ClearException();
+ return nullptr;
+ }
ArtMethod* resolved_method = class_linker->ResolveMethod<ClassLinker::kForceICCECheck>(
*dex_compilation_unit_->GetDexFile(),
@@ -711,47 +721,33 @@
DCHECK(Runtime::Current()->IsAotCompiler());
return nullptr;
}
- ArtMethod* current_method = graph_->GetArtMethod();
- DCHECK(current_method != nullptr);
- Handle<mirror::Class> methods_class(hs.NewHandle(
- dex_compilation_unit_->GetClassLinker()->ResolveReferencedClassOfMethod(Thread::Current(),
- method_idx,
- current_method)));
- if (methods_class.Get() == nullptr) {
- // Invoking a super method requires knowing the actual super class. If we did not resolve
- // the compiling method's declaring class (which only happens for ahead of time
- // compilation), bail out.
- DCHECK(Runtime::Current()->IsAotCompiler());
- return nullptr;
+ ArtMethod* actual_method;
+ if (methods_class->IsInterface()) {
+ actual_method = methods_class->FindVirtualMethodForInterfaceSuper(
+ resolved_method, class_linker->GetImagePointerSize());
} else {
- ArtMethod* actual_method;
- if (methods_class->IsInterface()) {
- actual_method = methods_class->FindVirtualMethodForInterfaceSuper(
- resolved_method, class_linker->GetImagePointerSize());
- } else {
- uint16_t vtable_index = resolved_method->GetMethodIndex();
- actual_method = compiling_class->GetSuperClass()->GetVTableEntry(
- vtable_index, class_linker->GetImagePointerSize());
- }
- if (actual_method != resolved_method &&
- !IsSameDexFile(*actual_method->GetDexFile(), *dex_compilation_unit_->GetDexFile())) {
- // The back-end code generator relies on this check in order to ensure that it will not
- // attempt to read the dex_cache with a dex_method_index that is not from the correct
- // dex_file. If we didn't do this check then the dex_method_index will not be updated in the
- // builder, which means that the code-generator (and compiler driver during sharpening and
- // inliner, maybe) might invoke an incorrect method.
- // TODO: The actual method could still be referenced in the current dex file, so we
- // could try locating it.
- // TODO: Remove the dex_file restriction.
- return nullptr;
- }
- if (!actual_method->IsInvokable()) {
- // Fail if the actual method cannot be invoked. Otherwise, the runtime resolution stub
- // could resolve the callee to the wrong method.
- return nullptr;
- }
- resolved_method = actual_method;
+ uint16_t vtable_index = resolved_method->GetMethodIndex();
+ actual_method = compiling_class->GetSuperClass()->GetVTableEntry(
+ vtable_index, class_linker->GetImagePointerSize());
}
+ if (actual_method != resolved_method &&
+ !IsSameDexFile(*actual_method->GetDexFile(), *dex_compilation_unit_->GetDexFile())) {
+ // The back-end code generator relies on this check in order to ensure that it will not
+ // attempt to read the dex_cache with a dex_method_index that is not from the correct
+ // dex_file. If we didn't do this check then the dex_method_index will not be updated in the
+ // builder, which means that the code-generator (and compiler driver during sharpening and
+ // inliner, maybe) might invoke an incorrect method.
+ // TODO: The actual method could still be referenced in the current dex file, so we
+ // could try locating it.
+ // TODO: Remove the dex_file restriction.
+ return nullptr;
+ }
+ if (!actual_method->IsInvokable()) {
+ // Fail if the actual method cannot be invoked. Otherwise, the runtime resolution stub
+ // could resolve the callee to the wrong method.
+ return nullptr;
+ }
+ resolved_method = actual_method;
}
// Check for incompatible class changes. The class linker has a fast path for
diff --git a/runtime/base/arena_allocator.cc b/runtime/base/arena_allocator.cc
index 5b6801f..b84e29f 100644
--- a/runtime/base/arena_allocator.cc
+++ b/runtime/base/arena_allocator.cc
@@ -321,24 +321,26 @@
// and padding between allocations marked as inaccessible.
size_t rounded_bytes = RoundUp(bytes + kMemoryToolRedZoneBytes, 8);
ArenaAllocatorStats::RecordAlloc(rounded_bytes, kind);
+ uint8_t* ret;
if (UNLIKELY(rounded_bytes > static_cast<size_t>(end_ - ptr_))) {
- void* ret = AllocFromNewArena(rounded_bytes);
+ ret = AllocFromNewArena(rounded_bytes);
+ uint8_t* noaccess_begin = ret + bytes;
+ uint8_t* noaccess_end;
if (ret == arena_head_->Begin()) {
DCHECK(ptr_ - rounded_bytes == ret);
- uint8_t* noaccess_begin = ptr_ - rounded_bytes + bytes;
- MEMORY_TOOL_MAKE_NOACCESS(noaccess_begin, end_ - noaccess_begin);
+ noaccess_end = end_;
} else {
// We're still using the old arena but `ret` comes from a new one just after it.
DCHECK(arena_head_->next_ != nullptr);
DCHECK(ret == arena_head_->next_->Begin());
DCHECK_EQ(rounded_bytes, arena_head_->next_->GetBytesAllocated());
- uint8_t* noaccess_begin = arena_head_->next_->Begin() + bytes;
- MEMORY_TOOL_MAKE_NOACCESS(noaccess_begin, arena_head_->next_->End() - noaccess_begin);
+ noaccess_end = arena_head_->next_->End();
}
- return ret;
+ MEMORY_TOOL_MAKE_NOACCESS(noaccess_begin, noaccess_end - noaccess_begin);
+ } else {
+ ret = ptr_;
+ ptr_ += rounded_bytes;
}
- uint8_t* ret = ptr_;
- ptr_ += rounded_bytes;
MEMORY_TOOL_MAKE_DEFINED(ret, bytes);
// Check that the memory is already zeroed out.
DCHECK(std::all_of(ret, ret + bytes, [](uint8_t val) { return val == 0u; }));
@@ -351,7 +353,7 @@
pool_->FreeArenaChain(arena_head_);
}
-void* ArenaAllocator::AllocFromNewArena(size_t bytes) {
+uint8_t* ArenaAllocator::AllocFromNewArena(size_t bytes) {
Arena* new_arena = pool_->AllocArena(std::max(Arena::kDefaultSize, bytes));
DCHECK(new_arena != nullptr);
DCHECK_LE(bytes, new_arena->Size());
diff --git a/runtime/base/arena_allocator.h b/runtime/base/arena_allocator.h
index 4b745f0..6c1a898 100644
--- a/runtime/base/arena_allocator.h
+++ b/runtime/base/arena_allocator.h
@@ -364,7 +364,7 @@
private:
void* AllocWithMemoryTool(size_t bytes, ArenaAllocKind kind);
- void* AllocFromNewArena(size_t bytes);
+ uint8_t* AllocFromNewArena(size_t bytes);
static constexpr size_t kAlignment = 8;
diff --git a/runtime/base/arena_allocator_test.cc b/runtime/base/arena_allocator_test.cc
index c07c0ed..9de3cc4 100644
--- a/runtime/base/arena_allocator_test.cc
+++ b/runtime/base/arena_allocator_test.cc
@@ -41,6 +41,28 @@
EXPECT_EQ(2U, bv.GetStorageSize());
}
+TEST_F(ArenaAllocatorTest, MakeDefined) {
+ // Regression test to make sure we mark the allocated area defined.
+ ArenaPool pool;
+ static constexpr size_t kSmallArraySize = 10;
+ static constexpr size_t kLargeArraySize = 50;
+ uint32_t* small_array;
+ {
+ // Allocate a small array from an arena and release it.
+ ArenaAllocator arena(&pool);
+ small_array = arena.AllocArray<uint32_t>(kSmallArraySize);
+ ASSERT_EQ(0u, small_array[kSmallArraySize - 1u]);
+ }
+ {
+ // Reuse the previous arena and allocate more than previous allocation including red zone.
+ ArenaAllocator arena(&pool);
+ uint32_t* large_array = arena.AllocArray<uint32_t>(kLargeArraySize);
+ ASSERT_EQ(0u, large_array[kLargeArraySize - 1u]);
+ // Verify that the allocation was made on the same arena.
+ ASSERT_EQ(small_array, large_array);
+ }
+}
+
TEST_F(ArenaAllocatorTest, LargeAllocations) {
{
ArenaPool pool;
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h
index 7e8a4a4..f3e260b 100644
--- a/runtime/class_linker-inl.h
+++ b/runtime/class_linker-inl.h
@@ -116,9 +116,10 @@
return resolved_method;
}
-inline mirror::Class* ClassLinker::ResolveReferencedClassOfMethod(Thread* self,
- uint32_t method_idx,
- ArtMethod* referrer) {
+inline mirror::Class* ClassLinker::ResolveReferencedClassOfMethod(
+ uint32_t method_idx,
+ Handle<mirror::DexCache> dex_cache,
+ Handle<mirror::ClassLoader> class_loader) {
// NB: We cannot simply use `GetResolvedMethod(method_idx, ...)->GetDeclaringClass()`. This is
// because if we did so than an invoke-super could be incorrectly dispatched in cases where
// GetMethodId(method_idx).class_idx_ refers to a non-interface, non-direct-superclass
@@ -127,15 +128,11 @@
// interface (either miranda, default or conflict) we would incorrectly assume that is what we
// want to invoke on, instead of the 'concrete' implementation that the direct superclass
// contains.
- mirror::Class* declaring_class = referrer->GetDeclaringClass();
- StackHandleScope<2> hs(self);
- Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(declaring_class->GetDexCache()));
- const DexFile* dex_file = h_dex_cache->GetDexFile();
+ const DexFile* dex_file = dex_cache->GetDexFile();
const DexFile::MethodId& method = dex_file->GetMethodId(method_idx);
- mirror::Class* resolved_type = h_dex_cache->GetResolvedType(method.class_idx_);
+ mirror::Class* resolved_type = dex_cache->GetResolvedType(method.class_idx_);
if (UNLIKELY(resolved_type == nullptr)) {
- Handle<mirror::ClassLoader> class_loader(hs.NewHandle(declaring_class->GetClassLoader()));
- resolved_type = ResolveType(*dex_file, method.class_idx_, h_dex_cache, class_loader);
+ resolved_type = ResolveType(*dex_file, method.class_idx_, dex_cache, class_loader);
}
return resolved_type;
}
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 5de502b..97a1036 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -310,9 +310,9 @@
// This returns the class referred to by GetMethodId(method_idx).class_idx_. This might be
// different then the declaring class of the resolved method due to copied
// miranda/default/conflict methods.
- mirror::Class* ResolveReferencedClassOfMethod(Thread* self,
- uint32_t method_idx,
- ArtMethod* referrer)
+ mirror::Class* ResolveReferencedClassOfMethod(uint32_t method_idx,
+ Handle<mirror::DexCache> dex_cache,
+ Handle<mirror::ClassLoader> class_loader)
SHARED_REQUIRES(Locks::mutator_lock_)
REQUIRES(!dex_lock_, !Roles::uninterruptible_);
template <ResolveMode kResolveMode>
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index f3e8dba..da6af72 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -1038,9 +1038,14 @@
} else {
DCHECK_EQ(invoke_type, kSuper);
CHECK(caller != nullptr) << invoke_type;
+ StackHandleScope<2> hs(self);
+ Handle<mirror::DexCache> dex_cache(
+ hs.NewHandle(caller->GetDeclaringClass()->GetDexCache()));
+ Handle<mirror::ClassLoader> class_loader(
+ hs.NewHandle(caller->GetDeclaringClass()->GetClassLoader()));
// TODO Maybe put this into a mirror::Class function.
mirror::Class* ref_class = linker->ResolveReferencedClassOfMethod(
- self, called_method.dex_method_index, caller);
+ called_method.dex_method_index, dex_cache, class_loader);
if (ref_class->IsInterface()) {
called = ref_class->FindVirtualMethodForInterfaceSuper(called, sizeof(void*));
} else {