summaryrefslogtreecommitdiffstats
path: root/runtime/interpreter/interpreter.cc
diff options
context:
space:
mode:
authorMathieu Chartier <mathieuc@google.com>2014-02-25 18:22:39 -0800
committerMathieu Chartier <mathieuc@google.com>2014-02-25 18:27:30 -0800
commit92246bb5d6caae4fdb09cd3c8c10d78e41932d45 (patch)
tree632ddc6aa34d4c5941d3f65f2e4a8f49a5a05272 /runtime/interpreter/interpreter.cc
parentef2cc5a9c6e508a3e8b24d04ca35f7422f27e112 (diff)
downloadart-92246bb5d6caae4fdb09cd3c8c10d78e41932d45.zip
art-92246bb5d6caae4fdb09cd3c8c10d78e41932d45.tar.gz
art-92246bb5d6caae4fdb09cd3c8c10d78e41932d45.tar.bz2
Fix moving GC bugs in EnterInterpreterFromInvoke.
Calling EnterInterpreterFromInvoke on a static method could cause class initialization and trash the args before calling the method. Change-Id: If053d46dd6db403c8ebd1a816c20635194dd0e99
Diffstat (limited to 'runtime/interpreter/interpreter.cc')
-rw-r--r--runtime/interpreter/interpreter.cc24
1 files changed, 14 insertions, 10 deletions
diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc
index cb9e2e8..40d4ea3 100644
--- a/runtime/interpreter/interpreter.cc
+++ b/runtime/interpreter/interpreter.cc
@@ -372,22 +372,12 @@ void EnterInterpreterFromInvoke(Thread* self, ArtMethod* method, Object* receive
void* memory = alloca(ShadowFrame::ComputeSize(num_regs));
ShadowFrame* shadow_frame(ShadowFrame::Create(num_regs, last_shadow_frame, method, 0, memory));
self->PushShadowFrame(shadow_frame);
- self->EndAssertNoThreadSuspension(old_cause);
size_t cur_reg = num_regs - num_ins;
if (!method->IsStatic()) {
CHECK(receiver != NULL);
shadow_frame->SetVRegReference(cur_reg, receiver);
++cur_reg;
- } else if (UNLIKELY(!method->GetDeclaringClass()->IsInitializing())) {
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- SirtRef<mirror::Class> sirt_c(self, method->GetDeclaringClass());
- if (UNLIKELY(!class_linker->EnsureInitialized(sirt_c, true, true))) {
- CHECK(self->IsExceptionPending());
- self->PopShadowFrame();
- return;
- }
- CHECK(sirt_c->IsInitializing());
}
const char* shorty = mh.GetShorty();
for (size_t shorty_pos = 0, arg_pos = 0; cur_reg < num_regs; ++shorty_pos, ++arg_pos, cur_reg++) {
@@ -410,6 +400,17 @@ void EnterInterpreterFromInvoke(Thread* self, ArtMethod* method, Object* receive
break;
}
}
+ self->EndAssertNoThreadSuspension(old_cause);
+ // Do this after populating the shadow frame in case EnsureInitialized causes a GC.
+ if (method->IsStatic() && UNLIKELY(!method->GetDeclaringClass()->IsInitializing())) {
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ SirtRef<mirror::Class> sirt_c(self, method->GetDeclaringClass());
+ if (UNLIKELY(!class_linker->EnsureInitialized(sirt_c, true, true))) {
+ CHECK(self->IsExceptionPending());
+ self->PopShadowFrame();
+ return;
+ }
+ }
if (LIKELY(!method->IsNative())) {
JValue r = Execute(self, mh, code_item, *shadow_frame, JValue());
if (result != NULL) {
@@ -418,6 +419,9 @@ void EnterInterpreterFromInvoke(Thread* self, ArtMethod* method, Object* receive
} else {
// We don't expect to be asked to interpret native code (which is entered via a JNI compiler
// generated stub) except during testing and image writing.
+ // Update args to be the args in the shadow frame since the input ones could hold stale
+ // references pointers due to moving GC.
+ args = shadow_frame->GetVRegArgs(method->IsStatic() ? 0 : 1);
if (!Runtime::Current()->IsStarted()) {
UnstartedRuntimeJni(self, method, receiver, args, result);
} else {