diff options
-rw-r--r-- | src/compiler_llvm/runtime_support_llvm.cc | 6 | ||||
-rw-r--r-- | src/interpreter/interpreter.cc | 71 | ||||
-rw-r--r-- | src/oat/runtime/support_stubs.cc | 2 | ||||
-rw-r--r-- | src/oat/runtime/support_throw.cc | 20 | ||||
-rw-r--r-- | src/object.cc | 2 | ||||
-rw-r--r-- | src/thread.cc | 2 | ||||
-rw-r--r-- | src/thread.h | 10 | ||||
-rw-r--r-- | test/051-thread/src/Main.java | 4 | ||||
-rw-r--r-- | test/084-class-init/src/Main.java | 4 |
9 files changed, 64 insertions, 57 deletions
diff --git a/src/compiler_llvm/runtime_support_llvm.cc b/src/compiler_llvm/runtime_support_llvm.cc index 371b32a4da..f01ca9a0a9 100644 --- a/src/compiler_llvm/runtime_support_llvm.cc +++ b/src/compiler_llvm/runtime_support_llvm.cc @@ -156,11 +156,7 @@ void art_throw_stack_overflow_from_code() void art_throw_exception_from_code(Object* exception) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { Thread* thread = art_get_current_thread_from_code(); - if (exception == NULL) { - thread->ThrowNewException("Ljava/lang/NullPointerException;", "throw with null exception"); - } else { - thread->SetException(static_cast<Throwable*>(exception)); - } + self->DeliverException(static_cast<Throwable*>(exception)); } void* art_get_and_clear_exception(Thread* self) diff --git a/src/interpreter/interpreter.cc b/src/interpreter/interpreter.cc index e68896a48d..8c217c71e3 100644 --- a/src/interpreter/interpreter.cc +++ b/src/interpreter/interpreter.cc @@ -862,7 +862,7 @@ static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* c } case Instruction::THROW: { Throwable* t = shadow_frame.GetReference(dec_insn.vA)->AsThrowable(); - self->SetException(t); + self->DeliverException(t); break; } case Instruction::GOTO: @@ -918,12 +918,13 @@ static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* c break; } case Instruction::FILL_ARRAY_DATA: { - Array* array = shadow_frame.GetReference(dec_insn.vA)->AsArray(); - if (UNLIKELY(array == NULL)) { + Object* obj = shadow_frame.GetReference(dec_insn.vA); + if (UNLIKELY(obj == NULL)) { Thread::Current()->ThrowNewExceptionF("Ljava/lang/NullPointerException;", "null array in FILL_ARRAY_DATA"); break; } + Array* array = obj->AsArray(); DCHECK(array->IsArrayInstance() && !array->IsObjectArray()); uint32_t dex_pc = inst->GetDexPc(insns); const Instruction::ArrayDataPayload* payload = @@ -1023,151 +1024,150 @@ static JValue Execute(Thread* self, MethodHelper& mh, const DexFile::CodeItem* c break; } case Instruction::AGET_BOOLEAN: { - BooleanArray* a = shadow_frame.GetReference(dec_insn.vB)->AsBooleanArray(); + Object* a = shadow_frame.GetReference(dec_insn.vB); if (UNLIKELY(a == NULL)) { ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns)); break; } int32_t index = shadow_frame.GetVReg(dec_insn.vC); - shadow_frame.SetVReg(dec_insn.vA, a->Get(index)); + shadow_frame.SetVReg(dec_insn.vA, a->AsBooleanArray()->Get(index)); break; } case Instruction::AGET_BYTE: { - ByteArray* a = shadow_frame.GetReference(dec_insn.vB)->AsByteArray(); + Object* a = shadow_frame.GetReference(dec_insn.vB); if (UNLIKELY(a == NULL)) { ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns)); break; } int32_t index = shadow_frame.GetVReg(dec_insn.vC); - shadow_frame.SetVReg(dec_insn.vA, a->Get(index)); + shadow_frame.SetVReg(dec_insn.vA, a->AsByteArray()->Get(index)); break; } case Instruction::AGET_CHAR: { - CharArray* a = shadow_frame.GetReference(dec_insn.vB)->AsCharArray(); + Object* a = shadow_frame.GetReference(dec_insn.vB); if (UNLIKELY(a == NULL)) { ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns)); break; } int32_t index = shadow_frame.GetVReg(dec_insn.vC); - shadow_frame.SetVReg(dec_insn.vA, a->Get(index)); + shadow_frame.SetVReg(dec_insn.vA, a->AsCharArray()->Get(index)); break; } case Instruction::AGET_SHORT: { - ShortArray* a = shadow_frame.GetReference(dec_insn.vB)->AsShortArray(); + Object* a = shadow_frame.GetReference(dec_insn.vB); if (UNLIKELY(a == NULL)) { ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns)); break; } int32_t index = shadow_frame.GetVReg(dec_insn.vC); - shadow_frame.SetVReg(dec_insn.vA, a->Get(index)); + shadow_frame.SetVReg(dec_insn.vA, a->AsShortArray()->Get(index)); break; } case Instruction::AGET: { - IntArray* a = shadow_frame.GetReference(dec_insn.vB)->AsIntArray(); + Object* a = shadow_frame.GetReference(dec_insn.vB); if (UNLIKELY(a == NULL)) { ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns)); break; } int32_t index = shadow_frame.GetVReg(dec_insn.vC); - shadow_frame.SetVReg(dec_insn.vA, a->Get(index)); + shadow_frame.SetVReg(dec_insn.vA, a->AsIntArray()->Get(index)); break; } case Instruction::AGET_WIDE: { - LongArray* a = shadow_frame.GetReference(dec_insn.vB)->AsLongArray(); + Object* a = shadow_frame.GetReference(dec_insn.vB); if (UNLIKELY(a == NULL)) { ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns)); break; } int32_t index = shadow_frame.GetVReg(dec_insn.vC); - shadow_frame.SetVRegLong(dec_insn.vA, a->Get(index)); + shadow_frame.SetVRegLong(dec_insn.vA, a->AsLongArray()->Get(index)); break; } case Instruction::AGET_OBJECT: { - ObjectArray<Object>* a = shadow_frame.GetReference(dec_insn.vB)->AsObjectArray<Object>(); + Object* a = shadow_frame.GetReference(dec_insn.vB); if (UNLIKELY(a == NULL)) { ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns)); break; } int32_t index = shadow_frame.GetVReg(dec_insn.vC); - Object* o = a->Get(index); - shadow_frame.SetReferenceAndVReg(dec_insn.vA, o); + shadow_frame.SetReferenceAndVReg(dec_insn.vA, a->AsObjectArray<Object>()->Get(index)); break; } case Instruction::APUT_BOOLEAN: { uint8_t val = shadow_frame.GetVReg(dec_insn.vA); - BooleanArray* a = shadow_frame.GetReference(dec_insn.vB)->AsBooleanArray(); + Object* a = shadow_frame.GetReference(dec_insn.vB); if (UNLIKELY(a == NULL)) { ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns)); break; } int32_t index = shadow_frame.GetVReg(dec_insn.vC); - a->Set(index, val); + a->AsBooleanArray()->Set(index, val); break; } case Instruction::APUT_BYTE: { int8_t val = shadow_frame.GetVReg(dec_insn.vA); - ByteArray* a = shadow_frame.GetReference(dec_insn.vB)->AsByteArray(); + Object* a = shadow_frame.GetReference(dec_insn.vB); if (UNLIKELY(a == NULL)) { ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns)); break; } int32_t index = shadow_frame.GetVReg(dec_insn.vC); - a->Set(index, val); + a->AsByteArray()->Set(index, val); break; } case Instruction::APUT_CHAR: { uint16_t val = shadow_frame.GetVReg(dec_insn.vA); - CharArray* a = shadow_frame.GetReference(dec_insn.vB)->AsCharArray(); + Object* a = shadow_frame.GetReference(dec_insn.vB); if (UNLIKELY(a == NULL)) { ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns)); break; } int32_t index = shadow_frame.GetVReg(dec_insn.vC); - a->Set(index, val); + a->AsCharArray()->Set(index, val); break; } case Instruction::APUT_SHORT: { int16_t val = shadow_frame.GetVReg(dec_insn.vA); - ShortArray* a = shadow_frame.GetReference(dec_insn.vB)->AsShortArray(); + Object* a = shadow_frame.GetReference(dec_insn.vB); if (UNLIKELY(a == NULL)) { ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns)); break; } int32_t index = shadow_frame.GetVReg(dec_insn.vC); - a->Set(index, val); + a->AsShortArray()->Set(index, val); break; } case Instruction::APUT: { int32_t val = shadow_frame.GetVReg(dec_insn.vA); - IntArray* a = shadow_frame.GetReference(dec_insn.vB)->AsIntArray(); + Object* a = shadow_frame.GetReference(dec_insn.vB); if (UNLIKELY(a == NULL)) { ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns)); break; } int32_t index = shadow_frame.GetVReg(dec_insn.vC); - a->Set(index, val); + a->AsIntArray()->Set(index, val); break; } case Instruction::APUT_WIDE: { int64_t val = shadow_frame.GetVRegLong(dec_insn.vA); - LongArray* a = shadow_frame.GetReference(dec_insn.vB)->AsLongArray(); + Object* a = shadow_frame.GetReference(dec_insn.vB); if (UNLIKELY(a == NULL)) { ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns)); break; } int32_t index = shadow_frame.GetVReg(dec_insn.vC); - a->Set(index, val); + a->AsLongArray()->Set(index, val); break; } case Instruction::APUT_OBJECT: { Object* val = shadow_frame.GetReference(dec_insn.vA); - ObjectArray<Object>* a = shadow_frame.GetReference(dec_insn.vB)->AsObjectArray<Object>(); + Object* a = shadow_frame.GetReference(dec_insn.vB); if (UNLIKELY(a == NULL)) { ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns)); break; } int32_t index = shadow_frame.GetVReg(dec_insn.vC); - a->Set(index, val); + a->AsObjectArray<Object>()->Set(index, val); break; } case Instruction::IGET_BOOLEAN: @@ -1787,8 +1787,11 @@ void EnterInterpreterFromInvoke(Thread* self, AbstractMethod* method, Object* re shadow_frame->SetReferenceAndVReg(cur_reg, receiver); ++cur_reg; } else if (!method->GetDeclaringClass()->IsInitializing()) { - Runtime::Current()->GetClassLinker()->EnsureInitialized(method->GetDeclaringClass(), - true, true); + if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(method->GetDeclaringClass(), + true, true)) { + DCHECK(Thread::Current()->IsExceptionPending()); + return; + } CHECK(method->GetDeclaringClass()->IsInitializing()); } const char* shorty = mh.GetShorty(); diff --git a/src/oat/runtime/support_stubs.cc b/src/oat/runtime/support_stubs.cc index 9e33c43026..ac188a82f8 100644 --- a/src/oat/runtime/support_stubs.cc +++ b/src/oat/runtime/support_stubs.cc @@ -347,7 +347,7 @@ extern void ThrowAbstractMethodErrorFromCode(AbstractMethod* method, Thread* thr FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll); thread->ThrowNewExceptionF("Ljava/lang/AbstractMethodError;", "abstract method \"%s\"", PrettyMethod(method).c_str()); - thread->DeliverException(); + thread->QuickDeliverException(); } #else // ART_USE_LLVM_COMPILER extern void ThrowAbstractMethodErrorFromCode(AbstractMethod* method, Thread* thread, AbstractMethod**) diff --git a/src/oat/runtime/support_throw.cc b/src/oat/runtime/support_throw.cc index 21adc52ef5..5bf48e4329 100644 --- a/src/oat/runtime/support_throw.cc +++ b/src/oat/runtime/support_throw.cc @@ -35,7 +35,7 @@ extern "C" void* GetAndClearException(Thread* self) SHARED_LOCKS_REQUIRED(Locks: extern "C" void artDeliverPendingExceptionFromCode(Thread* thread, AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll); - thread->DeliverException(); + thread->QuickDeliverException(); } // Called by generated call to throw an exception. @@ -50,12 +50,8 @@ extern "C" void artDeliverExceptionFromCode(Throwable* exception, Thread* thread * exception_ in thread and delivering the exception. */ FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll); - if (exception == NULL) { - thread->ThrowNewException("Ljava/lang/NullPointerException;", "throw with null exception"); - } else { - thread->SetException(exception); - } - thread->DeliverException(); + thread->DeliverException(exception); + thread->QuickDeliverException(); } // Called by generated call to throw a NPE exception. @@ -66,7 +62,7 @@ extern "C" void artThrowNullPointerExceptionFromCode(Thread* self, uint32_t dex_pc; AbstractMethod* throw_method = self->GetCurrentMethod(&dex_pc); ThrowNullPointerExceptionFromDexPC(throw_method, dex_pc); - self->DeliverException(); + self->QuickDeliverException(); } // Called by generated call to throw an arithmetic divide by zero exception. @@ -75,7 +71,7 @@ extern "C" void artThrowDivZeroFromCode(Thread* thread, SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll); thread->ThrowNewException("Ljava/lang/ArithmeticException;", "divide by zero"); - thread->DeliverException(); + thread->QuickDeliverException(); } // Called by generated call to throw an array index out of bounds exception. @@ -85,14 +81,14 @@ extern "C" void artThrowArrayBoundsFromCode(int index, int limit, Thread* thread FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll); thread->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;", "length=%d; index=%d", limit, index); - thread->DeliverException(); + thread->QuickDeliverException(); } extern "C" void artThrowStackOverflowFromCode(Thread* self, AbstractMethod** sp) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { FinishCalleeSaveFrameSetup(self, sp, Runtime::kSaveAll); ThrowStackOverflowError(self); - self->DeliverException(); + self->QuickDeliverException(); } extern "C" void artThrowNoSuchMethodFromCode(int32_t method_idx, Thread* self, @@ -101,7 +97,7 @@ extern "C" void artThrowNoSuchMethodFromCode(int32_t method_idx, Thread* self, FinishCalleeSaveFrameSetup(self, sp, Runtime::kSaveAll); AbstractMethod* method = self->GetCurrentMethod(); ThrowNoSuchMethodError(method_idx, method); - self->DeliverException(); + self->QuickDeliverException(); } } // namespace art diff --git a/src/object.cc b/src/object.cc index 147b882a50..210c42d54f 100644 --- a/src/object.cc +++ b/src/object.cc @@ -1480,7 +1480,7 @@ bool Array::ThrowArrayIndexOutOfBoundsException(int32_t index) const { bool Array::ThrowArrayStoreException(Object* object) const { Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;", - "Can't store an element of type %s into an array of type %s", + "%s cannot be stored in an array of type %s", PrettyTypeOf(object).c_str(), PrettyTypeOf(this).c_str()); return false; } diff --git a/src/thread.cc b/src/thread.cc index 8037886165..ca57f8a6bc 100644 --- a/src/thread.cc +++ b/src/thread.cc @@ -1770,7 +1770,7 @@ class CatchBlockStackVisitor : public StackVisitor { const char* last_no_assert_suspension_cause_; }; -void Thread::DeliverException() { +void Thread::QuickDeliverException() { Throwable* exception = GetException(); // Get exception from thread CHECK(exception != NULL); // Don't leave exception visible while we try to find the handler, which may cause class diff --git a/src/thread.h b/src/thread.h index 4e1f0e7a03..112db2d71f 100644 --- a/src/thread.h +++ b/src/thread.h @@ -319,8 +319,16 @@ class PACKED Thread { DCHECK(!IsExceptionPending()); } + void DeliverException(Throwable* exception) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + if (exception == NULL) { + ThrowNewException("Ljava/lang/NullPointerException;", "throw with null exception"); + } else { + SetException(exception); + } + } + // Find catch block and perform long jump to appropriate exception handle - void DeliverException() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void QuickDeliverException() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); Context* GetLongJumpContext(); void ReleaseLongJumpContext(Context* context) { diff --git a/test/051-thread/src/Main.java b/test/051-thread/src/Main.java index ea587af90e..911c739d92 100644 --- a/test/051-thread/src/Main.java +++ b/test/051-thread/src/Main.java @@ -67,6 +67,10 @@ public class Main { synchronized (MyThread.class) { ++mCount; } + try { + sleep(1000); + } catch (Exception ex) { + } } } } diff --git a/test/084-class-init/src/Main.java b/test/084-class-init/src/Main.java index f551dc5440..abad1f0cf1 100644 --- a/test/084-class-init/src/Main.java +++ b/test/084-class-init/src/Main.java @@ -96,7 +96,7 @@ public class Main { static class FieldThread extends Thread { public void run() { /* allow SlowInit's <clinit> to start */ - Main.sleep(1000); + Main.sleep(5000); /* collect fields; should delay until class init completes */ int field0, field1, field2, field3; @@ -115,7 +115,7 @@ public class Main { static class MethodThread extends Thread { public void run() { /* allow SlowInit's <clinit> to start */ - Main.sleep(1000); + Main.sleep(5000); /* use a method that shouldn't be accessible yet */ SlowInit.printMsg("MethodThread message"); |