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
diff --git a/src/compiler_llvm/runtime_support_llvm.cc b/src/compiler_llvm/runtime_support_llvm.cc
index 371b32a..f01ca9a 100644
--- a/src/compiler_llvm/runtime_support_llvm.cc
+++ b/src/compiler_llvm/runtime_support_llvm.cc
@@ -156,11 +156,7 @@
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 e68896a..8c217c7 100644
--- a/src/interpreter/interpreter.cc
+++ b/src/interpreter/interpreter.cc
@@ -862,7 +862,7 @@
}
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 @@
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 @@
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 @@
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 9e33c43..ac188a8 100644
--- a/src/oat/runtime/support_stubs.cc
+++ b/src/oat/runtime/support_stubs.cc
@@ -347,7 +347,7 @@
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 21adc52..5bf48e4 100644
--- a/src/oat/runtime/support_throw.cc
+++ b/src/oat/runtime/support_throw.cc
@@ -35,7 +35,7 @@
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 @@
* 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 @@
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 @@
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 @@
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 @@
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 147b882..210c42d 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -1480,7 +1480,7 @@
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 8037886..ca57f8a 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -1770,7 +1770,7 @@
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 4e1f0e7..112db2d 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -319,8 +319,16 @@
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 ea587af..911c739 100644
--- a/test/051-thread/src/Main.java
+++ b/test/051-thread/src/Main.java
@@ -67,6 +67,10 @@
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 f551dc5..abad1f0 100644
--- a/test/084-class-init/src/Main.java
+++ b/test/084-class-init/src/Main.java
@@ -96,7 +96,7 @@
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 @@
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");