Compacting collector.
The compacting collector is currently similar to semispace. It works by
copying objects back and forth between two bump pointer spaces. There
are types of objects which are "non-movable" due to current runtime
limitations. These are Classes, Methods, and Fields.
Bump pointer spaces are a new type of continuous alloc space which have
no lock in the allocation code path. When you allocate from these it uses
atomic operations to increase an index. Traversing the objects in the bump
pointer space relies on Object::SizeOf matching the allocated size exactly.
Runtime changes:
JNI::GetArrayElements returns copies objects if you attempt to get the
backing data of a movable array. For GetArrayElementsCritical, we return
direct backing storage for any types of arrays, but temporarily disable
the GC until the critical region is completed.
Added a new runtime call called VisitObjects, this is used in place of
the old pattern which was flushing the allocation stack and walking
the bitmaps.
Changed image writer to be compaction safe and use object monitor word
for forwarding addresses.
Added a bunch of added SIRTs to ClassLinker, MethodLinker, etc..
TODO: Enable switching allocators, compacting on background, etc..
Bug: 8981901
Change-Id: I3c886fd322a6eef2b99388d19a765042ec26ab99
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 9f98061..9cd8f73 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -39,6 +39,7 @@
#include "object_utils.h"
#include "register_line-inl.h"
#include "runtime.h"
+#include "scoped_thread_state_change.h"
#include "verifier/dex_gc_map.h"
namespace art {
@@ -113,17 +114,15 @@
*error += dex_file.GetLocation();
return kHardFailure;
}
- return VerifyClass(&dex_file,
- kh.GetDexCache(),
- klass->GetClassLoader(),
- class_def,
- allow_soft_failures,
- error);
+ Thread* self = Thread::Current();
+ SirtRef<mirror::DexCache> dex_cache(self, kh.GetDexCache());
+ SirtRef<mirror::ClassLoader> class_loader(self, klass->GetClassLoader());
+ return VerifyClass(&dex_file, dex_cache, class_loader, class_def, allow_soft_failures, error);
}
MethodVerifier::FailureKind MethodVerifier::VerifyClass(const DexFile* dex_file,
- mirror::DexCache* dex_cache,
- mirror::ClassLoader* class_loader,
+ SirtRef<mirror::DexCache>& dex_cache,
+ SirtRef<mirror::ClassLoader>& class_loader,
const DexFile::ClassDef* class_def,
bool allow_soft_failures,
std::string* error) {
@@ -233,8 +232,8 @@
MethodVerifier::FailureKind MethodVerifier::VerifyMethod(uint32_t method_idx,
const DexFile* dex_file,
- mirror::DexCache* dex_cache,
- mirror::ClassLoader* class_loader,
+ SirtRef<mirror::DexCache>& dex_cache,
+ SirtRef<mirror::ClassLoader>& class_loader,
const DexFile::ClassDef* class_def,
const DexFile::CodeItem* code_item,
mirror::ArtMethod* method,
@@ -243,8 +242,8 @@
MethodVerifier::FailureKind result = kNoFailure;
uint64_t start_ns = NanoTime();
- MethodVerifier verifier_(dex_file, dex_cache, class_loader, class_def, code_item, method_idx,
- method, method_access_flags, true, allow_soft_failures);
+ MethodVerifier verifier_(dex_file, &dex_cache, &class_loader, class_def, code_item,
+ method_idx, method, method_access_flags, true, allow_soft_failures);
if (verifier_.Verify()) {
// Verification completed, however failures may be pending that didn't cause the verification
// to hard fail.
@@ -277,13 +276,14 @@
}
void MethodVerifier::VerifyMethodAndDump(std::ostream& os, uint32_t dex_method_idx,
- const DexFile* dex_file, mirror::DexCache* dex_cache,
- mirror::ClassLoader* class_loader,
+ const DexFile* dex_file,
+ SirtRef<mirror::DexCache>& dex_cache,
+ SirtRef<mirror::ClassLoader>& class_loader,
const DexFile::ClassDef* class_def,
const DexFile::CodeItem* code_item,
mirror::ArtMethod* method,
uint32_t method_access_flags) {
- MethodVerifier verifier(dex_file, dex_cache, class_loader, class_def, code_item,
+ MethodVerifier verifier(dex_file, &dex_cache, &class_loader, class_def, code_item,
dex_method_idx, method, method_access_flags, true, true);
verifier.Verify();
verifier.DumpFailures(os);
@@ -291,13 +291,12 @@
verifier.Dump(os);
}
-MethodVerifier::MethodVerifier(const DexFile* dex_file, mirror::DexCache* dex_cache,
- mirror::ClassLoader* class_loader,
+MethodVerifier::MethodVerifier(const DexFile* dex_file, SirtRef<mirror::DexCache>* dex_cache,
+ SirtRef<mirror::ClassLoader>* class_loader,
const DexFile::ClassDef* class_def,
- const DexFile::CodeItem* code_item,
- uint32_t dex_method_idx, mirror::ArtMethod* method,
- uint32_t method_access_flags, bool can_load_classes,
- bool allow_soft_failures)
+ const DexFile::CodeItem* code_item, uint32_t dex_method_idx,
+ mirror::ArtMethod* method, uint32_t method_access_flags,
+ bool can_load_classes, bool allow_soft_failures)
: reg_types_(can_load_classes),
work_insn_idx_(-1),
dex_method_idx_(dex_method_idx),
@@ -323,12 +322,19 @@
DCHECK(class_def != nullptr);
}
+MethodVerifier::~MethodVerifier() {
+ STLDeleteElements(&failure_messages_);
+}
+
void MethodVerifier::FindLocksAtDexPc(mirror::ArtMethod* m, uint32_t dex_pc,
std::vector<uint32_t>& monitor_enter_dex_pcs) {
MethodHelper mh(m);
- MethodVerifier verifier(&mh.GetDexFile(), mh.GetDexCache(), mh.GetClassLoader(),
- &mh.GetClassDef(), mh.GetCodeItem(), m->GetDexMethodIndex(),
- m, m->GetAccessFlags(), false, true);
+ Thread* self = Thread::Current();
+ SirtRef<mirror::DexCache> dex_cache(self, mh.GetDexCache());
+ SirtRef<mirror::ClassLoader> class_loader(self, mh.GetClassLoader());
+ MethodVerifier verifier(&mh.GetDexFile(), &dex_cache, &class_loader, &mh.GetClassDef(),
+ mh.GetCodeItem(), m->GetDexMethodIndex(), m, m->GetAccessFlags(), false,
+ true);
verifier.interesting_dex_pc_ = dex_pc;
verifier.monitor_enter_dex_pcs_ = &monitor_enter_dex_pcs;
verifier.FindLocksAtDexPc();
@@ -348,9 +354,12 @@
mirror::ArtField* MethodVerifier::FindAccessedFieldAtDexPc(mirror::ArtMethod* m,
uint32_t dex_pc) {
MethodHelper mh(m);
- MethodVerifier verifier(&mh.GetDexFile(), mh.GetDexCache(), mh.GetClassLoader(),
- &mh.GetClassDef(), mh.GetCodeItem(), m->GetDexMethodIndex(),
- m, m->GetAccessFlags(), false, true);
+ Thread* self = Thread::Current();
+ SirtRef<mirror::DexCache> dex_cache(self, mh.GetDexCache());
+ SirtRef<mirror::ClassLoader> class_loader(self, mh.GetClassLoader());
+ MethodVerifier verifier(&mh.GetDexFile(), &dex_cache, &class_loader, &mh.GetClassDef(),
+ mh.GetCodeItem(), m->GetDexMethodIndex(), m, m->GetAccessFlags(), false,
+ true);
return verifier.FindAccessedFieldAtDexPc(dex_pc);
}
@@ -374,11 +383,14 @@
}
mirror::ArtMethod* MethodVerifier::FindInvokedMethodAtDexPc(mirror::ArtMethod* m,
- uint32_t dex_pc) {
+ uint32_t dex_pc) {
MethodHelper mh(m);
- MethodVerifier verifier(&mh.GetDexFile(), mh.GetDexCache(), mh.GetClassLoader(),
- &mh.GetClassDef(), mh.GetCodeItem(), m->GetDexMethodIndex(),
- m, m->GetAccessFlags(), false, true);
+ Thread* self = Thread::Current();
+ SirtRef<mirror::DexCache> dex_cache(self, mh.GetDexCache());
+ SirtRef<mirror::ClassLoader> class_loader(self, mh.GetClassLoader());
+ MethodVerifier verifier(&mh.GetDexFile(), &dex_cache, &class_loader, &mh.GetClassDef(),
+ mh.GetCodeItem(), m->GetDexMethodIndex(), m, m->GetAccessFlags(), false,
+ true);
return verifier.FindInvokedMethodAtDexPc(dex_pc);
}
@@ -589,7 +601,7 @@
if (iterator.GetHandlerTypeIndex() != DexFile::kDexNoIndex16) {
mirror::Class* exception_type = linker->ResolveType(*dex_file_,
iterator.GetHandlerTypeIndex(),
- dex_cache_, class_loader_);
+ *dex_cache_, *class_loader_);
if (exception_type == NULL) {
DCHECK(Thread::Current()->IsExceptionPending());
Thread::Current()->ClearException();
@@ -1211,7 +1223,8 @@
// it's effectively considered initialized the instant we reach here (in the sense that we
// can return without doing anything or call virtual methods).
{
- const RegType& reg_type = reg_types_.FromDescriptor(class_loader_, descriptor, false);
+ const RegType& reg_type = reg_types_.FromDescriptor(class_loader_->get(), descriptor,
+ false);
reg_line->SetRegisterType(arg_start + cur_arg, reg_type);
}
break;
@@ -1853,7 +1866,8 @@
Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "invalid fill-array-data with array type "
<< array_type;
} else {
- const RegType& component_type = reg_types_.GetComponentType(array_type, class_loader_);
+ const RegType& component_type = reg_types_.GetComponentType(array_type,
+ class_loader_->get());
DCHECK(!component_type.IsConflict());
if (component_type.IsNonZeroReferenceTypes()) {
Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "invalid fill-array-data with component type "
@@ -2168,7 +2182,7 @@
const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
uint32_t return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_;
const char* descriptor = dex_file_->StringByTypeIdx(return_type_idx);
- return_type = ®_types_.FromDescriptor(class_loader_, descriptor, false);
+ return_type = ®_types_.FromDescriptor(class_loader_->get(), descriptor, false);
}
if (!return_type->IsLowHalf()) {
work_line_->SetResultRegisterType(*return_type);
@@ -2235,8 +2249,8 @@
*/
work_line_->MarkRefsAsInitialized(this_type);
}
- const RegType& return_type = reg_types_.FromDescriptor(class_loader_, return_type_descriptor,
- false);
+ const RegType& return_type = reg_types_.FromDescriptor(class_loader_->get(),
+ return_type_descriptor, false);
if (!return_type.IsLowHalf()) {
work_line_->SetResultRegisterType(return_type);
} else {
@@ -2257,11 +2271,12 @@
uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
const DexFile::MethodId& method_id = dex_file_->GetMethodId(method_idx);
uint32_t return_type_idx = dex_file_->GetProtoId(method_id.proto_idx_).return_type_idx_;
- descriptor = dex_file_->StringByTypeIdx(return_type_idx);
+ descriptor = dex_file_->StringByTypeIdx(return_type_idx);
} else {
descriptor = MethodHelper(called_method).GetReturnTypeDescriptor();
}
- const RegType& return_type = reg_types_.FromDescriptor(class_loader_, descriptor, false);
+ const RegType& return_type = reg_types_.FromDescriptor(class_loader_->get(), descriptor,
+ false);
if (!return_type.IsLowHalf()) {
work_line_->SetResultRegisterType(return_type);
} else {
@@ -2318,7 +2333,8 @@
} else {
descriptor = MethodHelper(abs_method).GetReturnTypeDescriptor();
}
- const RegType& return_type = reg_types_.FromDescriptor(class_loader_, descriptor, false);
+ const RegType& return_type = reg_types_.FromDescriptor(class_loader_->get(), descriptor,
+ false);
if (!return_type.IsLowHalf()) {
work_line_->SetResultRegisterType(return_type);
} else {
@@ -2584,7 +2600,8 @@
mirror::ArtMethod* called_method = VerifyInvokeVirtualQuickArgs(inst, is_range);
if (called_method != NULL) {
const char* descriptor = MethodHelper(called_method).GetReturnTypeDescriptor();
- const RegType& return_type = reg_types_.FromDescriptor(class_loader_, descriptor, false);
+ const RegType& return_type = reg_types_.FromDescriptor(class_loader_->get(), descriptor,
+ false);
if (!return_type.IsLowHalf()) {
work_line_->SetResultRegisterType(return_type);
} else {
@@ -2850,18 +2867,18 @@
const RegType& MethodVerifier::ResolveClassAndCheckAccess(uint32_t class_idx) {
const char* descriptor = dex_file_->StringByTypeIdx(class_idx);
const RegType& referrer = GetDeclaringClass();
- mirror::Class* klass = dex_cache_->GetResolvedType(class_idx);
+ mirror::Class* klass = (*dex_cache_)->GetResolvedType(class_idx);
const RegType& result =
klass != NULL ? reg_types_.FromClass(descriptor, klass,
klass->CannotBeAssignedFromOtherTypes())
- : reg_types_.FromDescriptor(class_loader_, descriptor, false);
+ : reg_types_.FromDescriptor(class_loader_->get(), descriptor, false);
if (result.IsConflict()) {
Fail(VERIFY_ERROR_BAD_CLASS_SOFT) << "accessing broken descriptor '" << descriptor
<< "' in " << referrer;
return result;
}
if (klass == NULL && !result.IsUnresolvedTypes()) {
- dex_cache_->SetResolvedType(class_idx, result.GetClass());
+ (*dex_cache_)->SetResolvedType(class_idx, result.GetClass());
}
// Check if access is allowed. Unresolved types use xxxWithAccessCheck to
// check at runtime if access is allowed and so pass here. If result is
@@ -2935,7 +2952,7 @@
}
mirror::Class* klass = klass_type.GetClass();
const RegType& referrer = GetDeclaringClass();
- mirror::ArtMethod* res_method = dex_cache_->GetResolvedMethod(dex_method_idx);
+ mirror::ArtMethod* res_method = (*dex_cache_)->GetResolvedMethod(dex_method_idx);
if (res_method == NULL) {
const char* name = dex_file_->GetMethodName(method_id);
const Signature signature = dex_file_->GetMethodSignature(method_id);
@@ -2948,7 +2965,7 @@
res_method = klass->FindVirtualMethod(name, signature);
}
if (res_method != NULL) {
- dex_cache_->SetResolvedMethod(dex_method_idx, res_method);
+ (*dex_cache_)->SetResolvedMethod(dex_method_idx, res_method);
} else {
// If a virtual or interface method wasn't found with the expected type, look in
// the direct methods. This can happen when the wrong invoke type is used or when
@@ -3112,7 +3129,7 @@
<< " missing signature component";
return NULL;
}
- const RegType& reg_type = reg_types_.FromDescriptor(class_loader_, descriptor, false);
+ const RegType& reg_type = reg_types_.FromDescriptor(class_loader_->get(), descriptor, false);
uint32_t get_reg = is_range ? inst->VRegC_3rc() + actual_args : arg[actual_args];
if (reg_type.IsIntegralTypes()) {
const RegType& src_type = work_line_->GetRegisterType(get_reg);
@@ -3136,8 +3153,7 @@
}
mirror::ArtMethod* MethodVerifier::GetQuickInvokedMethod(const Instruction* inst,
- RegisterLine* reg_line,
- bool is_range) {
+ RegisterLine* reg_line, bool is_range) {
DCHECK(inst->Opcode() == Instruction::INVOKE_VIRTUAL_QUICK ||
inst->Opcode() == Instruction::INVOKE_VIRTUAL_RANGE_QUICK);
const RegType& actual_arg_type = reg_line->GetInvocationThis(inst, is_range);
@@ -3152,11 +3168,13 @@
} else {
const std::string& descriptor(actual_arg_type.GetDescriptor());
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- this_class = class_linker->FindClass(descriptor.c_str(), class_loader_);
+ this_class = class_linker->FindClass(descriptor.c_str(), *class_loader_);
if (this_class == NULL) {
- Thread::Current()->ClearException();
+ Thread* self = Thread::Current();
+ self->ClearException();
// Look for a system class
- this_class = class_linker->FindClass(descriptor.c_str(), NULL);
+ SirtRef<mirror::ClassLoader> null_class_loader(self, nullptr);
+ this_class = class_linker->FindClass(descriptor.c_str(), null_class_loader);
}
}
if (this_class == NULL) {
@@ -3246,7 +3264,7 @@
<< " missing signature component";
return NULL;
}
- const RegType& reg_type = reg_types_.FromDescriptor(class_loader_, descriptor, false);
+ const RegType& reg_type = reg_types_.FromDescriptor(class_loader_->get(), descriptor, false);
uint32_t get_reg = is_range ? inst->VRegC_3rc() + actual_args : arg[actual_args];
if (!work_line_->VerifyRegisterType(get_reg, reg_type)) {
return res_method;
@@ -3290,7 +3308,7 @@
} else {
// Verify each register. If "arg_count" is bad, VerifyRegisterType() will run off the end of
// the list and fail. It's legal, if silly, for arg_count to be zero.
- const RegType& expected_type = reg_types_.GetComponentType(res_type, class_loader_);
+ const RegType& expected_type = reg_types_.GetComponentType(res_type, class_loader_->get());
uint32_t arg_count = (is_range) ? inst->VRegA_3rc() : inst->VRegA_35c();
uint32_t arg[5];
if (!is_range) {
@@ -3332,7 +3350,7 @@
Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "not array type " << array_type << " with aget";
} else {
/* verify the class */
- const RegType& component_type = reg_types_.GetComponentType(array_type, class_loader_);
+ const RegType& component_type = reg_types_.GetComponentType(array_type, class_loader_->get());
if (!component_type.IsReferenceTypes() && !is_primitive) {
Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "primitive array type " << array_type
<< " source for aget-object";
@@ -3409,7 +3427,7 @@
} else if (!array_type.IsArrayTypes()) {
Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "not array type " << array_type << " with aput";
} else {
- const RegType& component_type = reg_types_.GetComponentType(array_type, class_loader_);
+ const RegType& component_type = reg_types_.GetComponentType(array_type, class_loader_->get());
const uint32_t vregA = inst->VRegA_23x();
if (is_primitive) {
VerifyPrimitivePut(component_type, insn_type, vregA);
@@ -3441,10 +3459,9 @@
if (klass_type.IsUnresolvedTypes()) {
return NULL; // Can't resolve Class so no more to do here, will do checking at runtime.
}
- mirror::ArtField* field = Runtime::Current()->GetClassLinker()->ResolveFieldJLS(*dex_file_,
- field_idx,
- dex_cache_,
- class_loader_);
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ mirror::ArtField* field = class_linker->ResolveFieldJLS(*dex_file_, field_idx, *dex_cache_,
+ *class_loader_);
if (field == NULL) {
VLOG(verifier) << "Unable to resolve static field " << field_idx << " ("
<< dex_file_->GetFieldName(field_id) << ") in "
@@ -3460,9 +3477,8 @@
} else if (!field->IsStatic()) {
Fail(VERIFY_ERROR_CLASS_CHANGE) << "expected field " << PrettyField(field) << " to be static";
return NULL;
- } else {
- return field;
}
+ return field;
}
mirror::ArtField* MethodVerifier::GetInstanceField(const RegType& obj_type, int field_idx) {
@@ -3478,10 +3494,9 @@
if (klass_type.IsUnresolvedTypes()) {
return NULL; // Can't resolve Class so no more to do here
}
- mirror::ArtField* field = Runtime::Current()->GetClassLinker()->ResolveFieldJLS(*dex_file_,
- field_idx,
- dex_cache_,
- class_loader_);
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ mirror::ArtField* field = class_linker->ResolveFieldJLS(*dex_file_, field_idx, *dex_cache_,
+ *class_loader_);
if (field == NULL) {
VLOG(verifier) << "Unable to resolve instance field " << field_idx << " ("
<< dex_file_->GetFieldName(field_id) << ") in "
@@ -3550,8 +3565,7 @@
if (field_type == nullptr) {
const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx);
const char* descriptor = dex_file_->GetFieldTypeDescriptor(field_id);
- mirror::ClassLoader* loader = class_loader_;
- field_type = ®_types_.FromDescriptor(loader, descriptor, false);
+ field_type = ®_types_.FromDescriptor(class_loader_->get(), descriptor, false);
}
const uint32_t vregA = (is_static) ? inst->VRegA_21c() : inst->VRegA_22c();
if (is_primitive) {
@@ -3613,8 +3627,7 @@
if (field_type == nullptr) {
const DexFile::FieldId& field_id = dex_file_->GetFieldId(field_idx);
const char* descriptor = dex_file_->GetFieldTypeDescriptor(field_id);
- mirror::ClassLoader* loader = class_loader_;
- field_type = ®_types_.FromDescriptor(loader, descriptor, false);
+ field_type = ®_types_.FromDescriptor(class_loader_->get(), descriptor, false);
}
const uint32_t vregA = (is_static) ? inst->VRegA_21c() : inst->VRegA_22c();
if (is_primitive) {
@@ -3671,11 +3684,13 @@
// We need to resolve the class from its descriptor.
const std::string& descriptor(object_type.GetDescriptor());
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- object_class = class_linker->FindClass(descriptor.c_str(), class_loader_);
+ Thread* self = Thread::Current();
+ object_class = class_linker->FindClass(descriptor.c_str(), *class_loader_);
if (object_class == NULL) {
- Thread::Current()->ClearException();
+ self->ClearException();
// Look for a system class
- object_class = class_linker->FindClass(descriptor.c_str(), NULL);
+ SirtRef<mirror::ClassLoader> null_class_loader(self, nullptr);
+ object_class = class_linker->FindClass(descriptor.c_str(), null_class_loader);
}
}
if (object_class == NULL) {
@@ -3881,8 +3896,8 @@
MethodHelper mh(mirror_method_);
mirror::Class* return_type_class = mh.GetReturnType();
if (return_type_class != nullptr) {
- return_type_ =®_types_.FromClass(mh.GetReturnTypeDescriptor(), return_type_class,
- return_type_class->CannotBeAssignedFromOtherTypes());
+ return_type_ = ®_types_.FromClass(mh.GetReturnTypeDescriptor(), return_type_class,
+ return_type_class->CannotBeAssignedFromOtherTypes());
} else {
Thread* self = Thread::Current();
DCHECK(self->IsExceptionPending());
@@ -3894,7 +3909,7 @@
const DexFile::ProtoId& proto_id = dex_file_->GetMethodPrototype(method_id);
uint16_t return_type_idx = proto_id.return_type_idx_;
const char* descriptor = dex_file_->GetTypeDescriptor(dex_file_->GetTypeId(return_type_idx));
- return_type_ = ®_types_.FromDescriptor(class_loader_, descriptor, false);
+ return_type_ = ®_types_.FromDescriptor(class_loader_->get(), descriptor, false);
}
}
return *return_type_;
@@ -3910,7 +3925,7 @@
declaring_class_ = ®_types_.FromClass(descriptor, klass,
klass->CannotBeAssignedFromOtherTypes());
} else {
- declaring_class_ = ®_types_.FromDescriptor(class_loader_, descriptor, false);
+ declaring_class_ = ®_types_.FromDescriptor(class_loader_->get(), descriptor, false);
}
}
return *declaring_class_;
@@ -3969,7 +3984,8 @@
// String[] in which case the stores need to be of Strings.
if (array_type.IsPreciseReference()) {
const RegType& value_type(line->GetRegisterType(inst->VRegA_23x()));
- const RegType& component_type(reg_types_.GetComponentType(array_type, class_loader_));
+ const RegType& component_type(reg_types_.GetComponentType(array_type,
+ class_loader_->get()));
is_safe_cast = component_type.IsStrictlyAssignableFrom(value_type);
}
}
@@ -4026,8 +4042,8 @@
// We can't devirtualize abstract classes except on arrays of abstract classes.
continue;
}
- mirror::ArtMethod* abstract_method =
- dex_cache_->GetResolvedMethod(is_range ? inst->VRegB_3rc() : inst->VRegB_35c());
+ mirror::ArtMethod* abstract_method = (*dex_cache_)->GetResolvedMethod(
+ is_range ? inst->VRegB_3rc() : inst->VRegB_35c());
if (abstract_method == NULL) {
// If the method is not found in the cache this means that it was never found
// by ResolveMethodAndCheckAccess() called when verifying invoke_*.