portable_throw_entrypoints.cc revision 98d1cc8033251c93786e2fa8c59a2e555a9493be
1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "dex_instruction.h" 18#include "entrypoints/entrypoint_utils-inl.h" 19#include "mirror/art_method-inl.h" 20#include "mirror/object-inl.h" 21 22namespace art { 23 24extern "C" void art_portable_throw_div_zero_from_code() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 25 ThrowArithmeticExceptionDivideByZero(); 26} 27 28extern "C" void art_portable_throw_array_bounds_from_code(int32_t index, int32_t length) 29 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 30 ThrowArrayIndexOutOfBoundsException(index, length); 31} 32 33extern "C" void art_portable_throw_no_such_method_from_code(int32_t method_idx) 34 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 35 ThrowNoSuchMethodError(method_idx); 36} 37 38extern "C" void art_portable_throw_null_pointer_exception_from_code(uint32_t dex_pc) 39 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 40 // TODO: remove dex_pc argument from caller. 41 UNUSED(dex_pc); 42 Thread* self = Thread::Current(); 43 ThrowLocation throw_location = self->GetCurrentLocationForThrow(); 44 ThrowNullPointerExceptionFromDexPC(throw_location); 45} 46 47extern "C" void art_portable_throw_stack_overflow_from_code() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 48 ThrowStackOverflowError(Thread::Current()); 49} 50 51extern "C" void art_portable_throw_exception_from_code(mirror::Throwable* exception) 52 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 53 Thread* self = Thread::Current(); 54 ThrowLocation throw_location = self->GetCurrentLocationForThrow(); 55 if (exception == NULL) { 56 ThrowNullPointerException(NULL, "throw with null exception"); 57 } else { 58 self->SetException(throw_location, exception); 59 } 60} 61 62extern "C" void* art_portable_get_and_clear_exception(Thread* self) 63 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 64 DCHECK(self->IsExceptionPending()); 65 // TODO: make this inline. 66 mirror::Throwable* exception = self->GetException(NULL); 67 self->ClearException(); 68 return exception; 69} 70 71extern "C" int32_t art_portable_find_catch_block_from_code(mirror::ArtMethod* current_method, 72 uint32_t ti_offset) 73 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 74 Thread* self = Thread::Current(); // TODO: make an argument. 75 ThrowLocation throw_location; 76 mirror::Throwable* exception = self->GetException(&throw_location); 77 // Check for special deoptimization exception. 78 if (UNLIKELY(reinterpret_cast<intptr_t>(exception) == -1)) { 79 return -1; 80 } 81 mirror::Class* exception_type = exception->GetClass(); 82 StackHandleScope<1> hs(self); 83 MethodHelper mh(hs.NewHandle(current_method)); 84 const DexFile::CodeItem* code_item = current_method->GetCodeItem(); 85 DCHECK_LT(ti_offset, code_item->tries_size_); 86 const DexFile::TryItem* try_item = DexFile::GetTryItems(*code_item, ti_offset); 87 88 int iter_index = 0; 89 int result = -1; 90 uint32_t catch_dex_pc = -1; 91 // Iterate over the catch handlers associated with dex_pc 92 for (CatchHandlerIterator it(*code_item, *try_item); it.HasNext(); it.Next()) { 93 uint16_t iter_type_idx = it.GetHandlerTypeIndex(); 94 // Catch all case 95 if (iter_type_idx == DexFile::kDexNoIndex16) { 96 catch_dex_pc = it.GetHandlerAddress(); 97 result = iter_index; 98 break; 99 } 100 // Does this catch exception type apply? 101 mirror::Class* iter_exception_type = mh.GetDexCacheResolvedType(iter_type_idx); 102 if (UNLIKELY(iter_exception_type == NULL)) { 103 // TODO: check, the verifier (class linker?) should take care of resolving all exception 104 // classes early. 105 LOG(WARNING) << "Unresolved exception class when finding catch block: " 106 << current_method->GetTypeDescriptorFromTypeIdx(iter_type_idx); 107 } else if (iter_exception_type->IsAssignableFrom(exception_type)) { 108 catch_dex_pc = it.GetHandlerAddress(); 109 result = iter_index; 110 break; 111 } 112 ++iter_index; 113 } 114 if (result != -1) { 115 // Handler found. 116 Runtime::Current()->GetInstrumentation()->ExceptionCaughtEvent( 117 self, throw_location, current_method, catch_dex_pc, exception); 118 // If the catch block has no move-exception then clear the exception for it. 119 const Instruction* first_catch_instr = Instruction::At( 120 ¤t_method->GetCodeItem()->insns_[catch_dex_pc]); 121 if (first_catch_instr->Opcode() != Instruction::MOVE_EXCEPTION) { 122 self->ClearException(); 123 } 124 } 125 return result; 126} 127 128} // namespace art 129