From 94d6df471a406a03bb1afba8ca3ae9c0fbf366b5 Mon Sep 17 00:00:00 2001 From: jeffhao Date: Mon, 26 Nov 2012 16:02:12 -0800 Subject: Fixes to make all run-tests except 051-thread work. - Moved exception delivery into common method DeliverException - Renamed old DeliverException to QuickDeliverException since it is only used by quick - Fixed null checks for arrays returned by GetReference - Standardized ArrayStoreException error message - Added additional sleeps to ensure threads stay alive long enough in 051-thread, and that is complete for 084-class-init Change-Id: I9ca306896a4bd10f453150fcf3965d9750fa0cbd --- src/compiler_llvm/runtime_support_llvm.cc | 6 +-- src/interpreter/interpreter.cc | 71 ++++++++++++++++--------------- src/oat/runtime/support_stubs.cc | 2 +- src/oat/runtime/support_throw.cc | 20 ++++----- src/object.cc | 2 +- src/thread.cc | 2 +- src/thread.h | 10 ++++- 7 files changed, 58 insertions(+), 55 deletions(-) (limited to 'src') 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(exception)); - } + self->DeliverException(static_cast(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* a = shadow_frame.GetReference(dec_insn.vB)->AsObjectArray(); + 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()->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* a = shadow_frame.GetReference(dec_insn.vB)->AsObjectArray(); + 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()->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) { -- cgit v1.2.3-59-g8ed1b