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 22 namespace art { 23 24 extern "C" void art_portable_throw_div_zero_from_code() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 25 ThrowArithmeticExceptionDivideByZero(); 26 } 27 28 extern "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 33 extern "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 38 extern "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 47 extern "C" void art_portable_throw_stack_overflow_from_code() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 48 ThrowStackOverflowError(Thread::Current()); 49 } 50 51 extern "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 62 extern "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 71 extern "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 const DexFile::CodeItem* code_item = current_method->GetCodeItem(); 84 DCHECK_LT(ti_offset, code_item->tries_size_); 85 const DexFile::TryItem* try_item = DexFile::GetTryItems(*code_item, ti_offset); 86 87 int iter_index = 0; 88 int result = -1; 89 uint32_t catch_dex_pc = -1; 90 // Iterate over the catch handlers associated with dex_pc 91 for (CatchHandlerIterator it(*code_item, *try_item); it.HasNext(); it.Next()) { 92 uint16_t iter_type_idx = it.GetHandlerTypeIndex(); 93 // Catch all case 94 if (iter_type_idx == DexFile::kDexNoIndex16) { 95 catch_dex_pc = it.GetHandlerAddress(); 96 result = iter_index; 97 break; 98 } 99 // Does this catch exception type apply? 100 mirror::Class* iter_exception_type = 101 current_method->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