summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authorMathieu Chartier <mathieuc@google.com>2014-04-30 22:22:55 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2014-04-30 22:22:55 +0000
commitadcfc69aa94cc1d406ef78e194b1ac36e389ad95 (patch)
tree6558bc3aa273cbb31fa601a1e3034de32c1a30a6 /runtime
parent3c541e3438c2ec4f0acc9c9023a1f8644e2458ee (diff)
parentb2c7ead6bb5c98282cdfbc89db8984a004bea030 (diff)
downloadart-adcfc69aa94cc1d406ef78e194b1ac36e389ad95.zip
art-adcfc69aa94cc1d406ef78e194b1ac36e389ad95.tar.gz
art-adcfc69aa94cc1d406ef78e194b1ac36e389ad95.tar.bz2
Merge "Don't allow allocating finalizable objects during transactions."
Diffstat (limited to 'runtime')
-rw-r--r--runtime/interpreter/interpreter.cc7
-rw-r--r--runtime/interpreter/interpreter_common.cc10
-rw-r--r--runtime/interpreter/interpreter_common.h3
-rw-r--r--runtime/interpreter/interpreter_goto_table_impl.cc12
-rw-r--r--runtime/interpreter/interpreter_switch_impl.cc11
5 files changed, 35 insertions, 8 deletions
diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc
index 3c6c225..1e1a8c1 100644
--- a/runtime/interpreter/interpreter.cc
+++ b/runtime/interpreter/interpreter.cc
@@ -98,11 +98,8 @@ static void UnstartedRuntimeJni(Thread* self, ArtMethod* method,
Primitive::Type primitive_type = component->GetPrimitiveType();
result->SetI(Primitive::ComponentSize(primitive_type));
} else {
- // Throw an exception so we can abort the transaction and undo every change.
- ThrowLocation throw_location = self->GetCurrentLocationForThrow();
- self->ThrowNewExceptionF(throw_location, "Ljava/lang/InternalError;",
- "Attempt to invoke native method in non-started runtime: %s",
- name.c_str());
+ AbortTransaction(self, "Attempt to invoke native method in non-started runtime: %s",
+ name.c_str());
}
}
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index 297f1a8..5660508 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -40,6 +40,16 @@ static inline void AssignRegister(ShadowFrame* new_shadow_frame, const ShadowFra
}
}
+void AbortTransaction(Thread* self, const char* fmt, ...) {
+ CHECK(Runtime::Current()->IsActiveTransaction());
+ // Throw an exception so we can abort the transaction and undo every change.
+ va_list args;
+ va_start(args, fmt);
+ self->ThrowNewExceptionV(self->GetCurrentLocationForThrow(), "Ljava/lang/InternalError;", fmt,
+ args);
+ va_end(args);
+}
+
template<bool is_range, bool do_assignability_check>
bool DoCall(ArtMethod* method, Thread* self, ShadowFrame& shadow_frame,
const Instruction* inst, uint16_t inst_data, JValue* result) {
diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h
index ce3346e..819b79d 100644
--- a/runtime/interpreter/interpreter_common.h
+++ b/runtime/interpreter/interpreter_common.h
@@ -82,6 +82,9 @@ static inline void DoMonitorExit(Thread* self, Object* ref) NO_THREAD_SAFETY_ANA
ref->MonitorExit(self);
}
+void AbortTransaction(Thread* self, const char* fmt, ...)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
void RecordArrayElementsInTransaction(mirror::Array* array, int32_t count)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/interpreter/interpreter_goto_table_impl.cc b/runtime/interpreter/interpreter_goto_table_impl.cc
index d0bb001..74b7c42 100644
--- a/runtime/interpreter/interpreter_goto_table_impl.cc
+++ b/runtime/interpreter/interpreter_goto_table_impl.cc
@@ -496,7 +496,7 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
}
HANDLE_INSTRUCTION_END();
- HANDLE_INSTRUCTION_START(ARRAY_LENGTH) {
+ HANDLE_INSTRUCTION_START(ARRAY_LENGTH) {
Object* array = shadow_frame.GetVRegReference(inst->VRegB_12x(inst_data));
if (UNLIKELY(array == NULL)) {
ThrowNullPointerExceptionFromDexPC(shadow_frame.GetCurrentLocationForThrow());
@@ -509,12 +509,20 @@ JValue ExecuteGotoImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem*
HANDLE_INSTRUCTION_END();
HANDLE_INSTRUCTION_START(NEW_INSTANCE) {
+ Runtime* runtime = Runtime::Current();
Object* obj = AllocObjectFromCode<do_access_check, true>(
inst->VRegB_21c(), shadow_frame.GetMethod(), self,
- Runtime::Current()->GetHeap()->GetCurrentAllocator());
+ runtime->GetHeap()->GetCurrentAllocator());
if (UNLIKELY(obj == NULL)) {
HANDLE_PENDING_EXCEPTION();
} else {
+ // Don't allow finalizable objects to be allocated during a transaction since these can't be
+ // finalized without a started runtime.
+ if (transaction_active && obj->GetClass()->IsFinalizable()) {
+ AbortTransaction(self, "Allocating finalizable object in transcation: %s",
+ PrettyTypeOf(obj).c_str());
+ HANDLE_PENDING_EXCEPTION();
+ }
shadow_frame.SetVRegReference(inst->VRegA_21c(inst_data), obj);
ADVANCE(2);
}
diff --git a/runtime/interpreter/interpreter_switch_impl.cc b/runtime/interpreter/interpreter_switch_impl.cc
index 77e2a82..0da1445 100644
--- a/runtime/interpreter/interpreter_switch_impl.cc
+++ b/runtime/interpreter/interpreter_switch_impl.cc
@@ -422,12 +422,21 @@ JValue ExecuteSwitchImpl(Thread* self, MethodHelper& mh, const DexFile::CodeItem
}
case Instruction::NEW_INSTANCE: {
PREAMBLE();
+ Runtime* runtime = Runtime::Current();
Object* obj = AllocObjectFromCode<do_access_check, true>(
inst->VRegB_21c(), shadow_frame.GetMethod(), self,
- Runtime::Current()->GetHeap()->GetCurrentAllocator());
+ runtime->GetHeap()->GetCurrentAllocator());
if (UNLIKELY(obj == NULL)) {
HANDLE_PENDING_EXCEPTION();
} else {
+ // Don't allow finalizable objects to be allocated during a transaction since these can't
+ // be finalized without a started runtime.
+ if (transaction_active && obj->GetClass()->IsFinalizable()) {
+ AbortTransaction(self, "Allocating finalizable object in transcation: %s",
+ PrettyTypeOf(obj).c_str());
+ HANDLE_PENDING_EXCEPTION();
+ break;
+ }
shadow_frame.SetVRegReference(inst->VRegA_21c(inst_data), obj);
inst = inst->Next_2xx();
}