diff options
| author | 2014-06-04 18:02:34 +0000 | |
|---|---|---|
| committer | 2014-06-04 18:02:34 +0000 | |
| commit | 3476ed2732d9695e5d005d86e78f5cf53301a772 (patch) | |
| tree | c33ce9b871778335c0409b915a44fccfd5d65911 | |
| parent | eb757eeb244301b8a312cd2b975652341820f42e (diff) | |
| parent | 2a0d4ec9532a89abe722e5babdfbb846ffaad721 (diff) | |
Merge "ART: Fix forbidden thread state change in interpreter"
| -rw-r--r-- | runtime/interpreter/interpreter_common.cc | 14 | ||||
| -rw-r--r-- | runtime/oat.cc | 2 | ||||
| -rw-r--r-- | runtime/thread.cc | 19 | ||||
| -rw-r--r-- | runtime/thread.h | 14 |
4 files changed, 42 insertions, 7 deletions
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc index 63ae6fdf18..19b85e43a2 100644 --- a/runtime/interpreter/interpreter_common.cc +++ b/runtime/interpreter/interpreter_common.cc @@ -74,7 +74,13 @@ bool DoCall(ArtMethod* method, Thread* self, ShadowFrame& shadow_frame, // Initialize new shadow frame. const size_t first_dest_reg = num_regs - num_ins; if (do_assignability_check) { - // Slow path: we need to do runtime check on reference assignment. We need to load the shorty + // Slow path. + // We might need to do class loading, which incurs a thread state change to kNative. So + // register the shadow frame as under construction and allow suspension again. + self->SetShadowFrameUnderConstruction(new_shadow_frame); + self->EndAssertNoThreadSuspension(old_cause); + + // We need to do runtime check on reference assignment. We need to load the shorty // to get the exact type of each reference argument. const DexFile::TypeList* params = mh.GetParameterTypeList(); const char* shorty = mh.GetShorty(); @@ -107,11 +113,9 @@ bool DoCall(ArtMethod* method, Thread* self, ShadowFrame& shadow_frame, Class* arg_type = mh.GetClassFromTypeIdx(params->GetTypeItem(shorty_pos).type_idx_); if (arg_type == NULL) { CHECK(self->IsExceptionPending()); - self->EndAssertNoThreadSuspension(old_cause); return false; } if (!o->VerifierInstanceOf(arg_type)) { - self->EndAssertNoThreadSuspension(old_cause); // This should never happen. self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(), "Ljava/lang/VirtualMachineError;", @@ -138,6 +142,8 @@ bool DoCall(ArtMethod* method, Thread* self, ShadowFrame& shadow_frame, break; } } + // We're done with the construction. + self->ClearShadowFrameUnderConstruction(); } else { // Fast path: no extra checks. if (is_range) { @@ -158,8 +164,8 @@ bool DoCall(ArtMethod* method, Thread* self, ShadowFrame& shadow_frame, AssignRegister(new_shadow_frame, shadow_frame, first_dest_reg + arg_index, regList & 0x0f); } } + self->EndAssertNoThreadSuspension(old_cause); } - self->EndAssertNoThreadSuspension(old_cause); // Do the call now. if (LIKELY(Runtime::Current()->IsStarted())) { diff --git a/runtime/oat.cc b/runtime/oat.cc index 6ab0d1e4cb..96834b8527 100644 --- a/runtime/oat.cc +++ b/runtime/oat.cc @@ -22,7 +22,7 @@ namespace art { const uint8_t OatHeader::kOatMagic[] = { 'o', 'a', 't', '\n' }; -const uint8_t OatHeader::kOatVersion[] = { '0', '3', '2', '\0' }; +const uint8_t OatHeader::kOatVersion[] = { '0', '3', '3', '\0' }; OatHeader::OatHeader() { memset(this, 0, sizeof(*this)); diff --git a/runtime/thread.cc b/runtime/thread.cc index 758944cd57..f89fadaf54 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -122,6 +122,16 @@ ShadowFrame* Thread::GetAndClearDeoptimizationShadowFrame(JValue* ret_val) { return sf; } +void Thread::SetShadowFrameUnderConstruction(ShadowFrame* sf) { + sf->SetLink(tlsPtr_.shadow_frame_under_construction); + tlsPtr_.shadow_frame_under_construction = sf; +} + +void Thread::ClearShadowFrameUnderConstruction() { + CHECK_NE(static_cast<ShadowFrame*>(nullptr), tlsPtr_.shadow_frame_under_construction); + tlsPtr_.shadow_frame_under_construction = tlsPtr_.shadow_frame_under_construction->GetLink(); +} + void Thread::InitTid() { tls32_.tid = ::art::GetTid(); } @@ -2128,6 +2138,15 @@ void Thread::VisitRoots(RootCallback* visitor, void* arg) { mapper.VisitShadowFrame(shadow_frame); } } + if (tlsPtr_.shadow_frame_under_construction != nullptr) { + RootCallbackVisitor visitorToCallback(visitor, arg, thread_id); + ReferenceMapVisitor<RootCallbackVisitor> mapper(this, nullptr, visitorToCallback); + for (ShadowFrame* shadow_frame = tlsPtr_.shadow_frame_under_construction; + shadow_frame != nullptr; + shadow_frame = shadow_frame->GetLink()) { + mapper.VisitShadowFrame(shadow_frame); + } + } // Visit roots on this thread's stack Context* context = GetLongJumpContext(); RootCallbackVisitor visitorToCallback(visitor, arg, thread_id); diff --git a/runtime/thread.h b/runtime/thread.h index 6569a962a0..8ac106bcf9 100644 --- a/runtime/thread.h +++ b/runtime/thread.h @@ -711,6 +711,13 @@ class Thread { return tlsPtr_.deoptimization_shadow_frame != nullptr; } + void SetShadowFrameUnderConstruction(ShadowFrame* sf); + void ClearShadowFrameUnderConstruction(); + + bool HasShadowFrameUnderConstruction() const { + return tlsPtr_.shadow_frame_under_construction != nullptr; + } + std::deque<instrumentation::InstrumentationStackFrame>* GetInstrumentationStack() { return tlsPtr_.instrumentation_stack; } @@ -962,8 +969,8 @@ class Thread { stack_trace_sample(nullptr), wait_next(nullptr), monitor_enter_object(nullptr), top_handle_scope(nullptr), class_loader_override(nullptr), long_jump_context(nullptr), instrumentation_stack(nullptr), debug_invoke_req(nullptr), single_step_control(nullptr), - deoptimization_shadow_frame(nullptr), name(nullptr), pthread_self(0), - last_no_thread_suspension_cause(nullptr), thread_local_start(nullptr), + deoptimization_shadow_frame(nullptr), shadow_frame_under_construction(nullptr), name(nullptr), + pthread_self(0), last_no_thread_suspension_cause(nullptr), thread_local_start(nullptr), thread_local_pos(nullptr), thread_local_end(nullptr), thread_local_objects(0), thread_local_alloc_stack_top(nullptr), thread_local_alloc_stack_end(nullptr) { } @@ -1039,6 +1046,9 @@ class Thread { // Shadow frame stack that is used temporarily during the deoptimization of a method. ShadowFrame* deoptimization_shadow_frame; + // Shadow frame stack that is currently under construction but not yet on the stack + ShadowFrame* shadow_frame_under_construction; + // A cached copy of the java.lang.Thread's name. std::string* name; |