diff options
author | Mathieu Chartier <mathieuc@google.com> | 2014-02-25 18:22:39 -0800 |
---|---|---|
committer | Mathieu Chartier <mathieuc@google.com> | 2014-02-25 18:27:30 -0800 |
commit | 92246bb5d6caae4fdb09cd3c8c10d78e41932d45 (patch) | |
tree | 632ddc6aa34d4c5941d3f65f2e4a8f49a5a05272 /runtime/interpreter/interpreter.cc | |
parent | ef2cc5a9c6e508a3e8b24d04ca35f7422f27e112 (diff) | |
download | art-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.cc | 24 |
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 { |