diff options
Diffstat (limited to 'runtime/entrypoints/quick/quick_throw_entrypoints.cc')
| -rw-r--r-- | runtime/entrypoints/quick/quick_throw_entrypoints.cc | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/runtime/entrypoints/quick/quick_throw_entrypoints.cc b/runtime/entrypoints/quick/quick_throw_entrypoints.cc index 9b0756b529b..ba7fb6b9db5 100644 --- a/runtime/entrypoints/quick/quick_throw_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_throw_entrypoints.cc @@ -16,8 +16,11 @@ #include "art_method-inl.h" #include "callee_save_frame.h" +#include "dex/code_item_accessors-inl.h" +#include "dex/dex_instruction-inl.h" #include "common_throws.h" #include "mirror/object-inl.h" +#include "nth_caller_visitor.h" #include "thread.h" #include "well_known_classes.h" @@ -112,6 +115,26 @@ extern "C" NO_RETURN void artThrowClassCastException(mirror::Class* dest_type, Thread* self) REQUIRES_SHARED(Locks::mutator_lock_) { ScopedQuickEntrypointChecks sqec(self); + if (dest_type == nullptr) { + // Find the target class for check cast using the bitstring check (dest_type == null). + NthCallerVisitor visitor(self, 0u); + visitor.WalkStack(); + DCHECK(visitor.caller != nullptr); + uint32_t dex_pc = visitor.GetDexPc(); + CodeItemDataAccessor accessor(*visitor.caller->GetDexFile(), visitor.caller->GetCodeItem()); + const Instruction& check_cast = accessor.InstructionAt(dex_pc); + DCHECK_EQ(check_cast.Opcode(), Instruction::CHECK_CAST); + dex::TypeIndex type_index(check_cast.VRegB_21c()); + ClassLinker* linker = Runtime::Current()->GetClassLinker(); + dest_type = linker->LookupResolvedType(type_index, visitor.caller).Ptr(); + CHECK(dest_type != nullptr) << "Target class should have been previously resolved: " + << visitor.caller->GetDexFile()->PrettyType(type_index); + CHECK(!dest_type->IsAssignableFrom(src_type)) + << " " << std::hex << dest_type->PrettyDescriptor() << ";" << dest_type->Depth() + << "/" << dest_type->GetField32(mirror::Class::StatusOffset()) + << " <: " << src_type->PrettyDescriptor() << ";" << src_type->Depth() + << "/" << src_type->GetField32(mirror::Class::StatusOffset()); + } DCHECK(!dest_type->IsAssignableFrom(src_type)); ThrowClassCastException(dest_type, src_type); self->QuickDeliverException(); |
