summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author jeffhao <jeffhao@google.com> 2012-11-26 16:02:12 -0800
committer jeffhao <jeffhao@google.com> 2012-11-26 16:02:12 -0800
commit94d6df471a406a03bb1afba8ca3ae9c0fbf366b5 (patch)
treef89af30dbe4a23dc6f62bb17c3b0a36b778ade33
parent5bc252873e6e50f8257e33ca158d0e350413fcbf (diff)
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 <clinit> is complete for 084-class-init Change-Id: I9ca306896a4bd10f453150fcf3965d9750fa0cbd
-rw-r--r--src/compiler_llvm/runtime_support_llvm.cc6
-rw-r--r--src/interpreter/interpreter.cc71
-rw-r--r--src/oat/runtime/support_stubs.cc2
-rw-r--r--src/oat/runtime/support_throw.cc20
-rw-r--r--src/object.cc2
-rw-r--r--src/thread.cc2
-rw-r--r--src/thread.h10
-rw-r--r--test/051-thread/src/Main.java4
-rw-r--r--test/084-class-init/src/Main.java4
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");