diff options
-rw-r--r-- | runtime/quick_exception_handler.cc | 5 | ||||
-rw-r--r-- | runtime/scoped_thread_state_change.h | 1 | ||||
-rw-r--r-- | runtime/stack.cc | 28 | ||||
-rw-r--r-- | runtime/stack.h | 3 | ||||
-rw-r--r-- | runtime/thread.cc | 4 | ||||
-rw-r--r-- | runtime/utils.h | 5 |
6 files changed, 41 insertions, 5 deletions
diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc index a80eed6073..9e79bd20cb 100644 --- a/runtime/quick_exception_handler.cc +++ b/runtime/quick_exception_handler.cc @@ -223,7 +223,10 @@ class DeoptimizeStackVisitor FINAL : public StackVisitor { break; case kReferenceVReg: { uint32_t value = 0; - if (GetVReg(h_method.Get(), reg, kind, &value)) { + // Check IsReferenceVReg in case the compiled GC map doesn't agree with the verifier. + // We don't want to copy a stale reference into the shadow frame as a reference. + // b/20736048 + if (GetVReg(h_method.Get(), reg, kind, &value) && IsReferenceVReg(h_method.Get(), reg)) { new_frame->SetVRegReference(reg, reinterpret_cast<mirror::Object*>(value)); } else { new_frame->SetVReg(reg, kDeadValue); diff --git a/runtime/scoped_thread_state_change.h b/runtime/scoped_thread_state_change.h index 99750a16d0..60ed55a914 100644 --- a/runtime/scoped_thread_state_change.h +++ b/runtime/scoped_thread_state_change.h @@ -133,6 +133,7 @@ class ScopedObjectAccessAlreadyRunnable { T AddLocalReference(mirror::Object* obj) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { Locks::mutator_lock_->AssertSharedHeld(Self()); DCHECK(IsRunnable()); // Don't work with raw objects in non-runnable states. + DCHECK_NE(obj, Runtime::Current()->GetClearedJniWeakGlobal()); return obj == nullptr ? nullptr : Env()->AddLocalReference<T>(obj); } diff --git a/runtime/stack.cc b/runtime/stack.cc index e49bc1d78f..a566886d73 100644 --- a/runtime/stack.cc +++ b/runtime/stack.cc @@ -19,6 +19,7 @@ #include "arch/context.h" #include "base/hex_dump.h" #include "entrypoints/runtime_asm_entrypoints.h" +#include "gc_map.h" #include "mirror/art_method-inl.h" #include "mirror/class-inl.h" #include "mirror/object.h" @@ -151,6 +152,33 @@ size_t StackVisitor::GetNativePcOffset() const { return GetMethod()->NativeQuickPcOffset(cur_quick_frame_pc_); } +bool StackVisitor::IsReferenceVReg(mirror::ArtMethod* m, uint16_t vreg) { + // Process register map (which native and runtime methods don't have) + if (m->IsNative() || m->IsRuntimeMethod() || m->IsProxyMethod()) { + return false; + } + if (m->IsOptimized(sizeof(void*))) { + return true; // TODO: Implement. + } + const uint8_t* native_gc_map = m->GetNativeGcMap(sizeof(void*)); + CHECK(native_gc_map != nullptr) << PrettyMethod(m); + const DexFile::CodeItem* code_item = m->GetCodeItem(); + // Can't be null or how would we compile its instructions? + DCHECK(code_item != nullptr) << PrettyMethod(m); + NativePcOffsetToReferenceMap map(native_gc_map); + size_t num_regs = std::min(map.RegWidth() * 8, static_cast<size_t>(code_item->registers_size_)); + const uint8_t* reg_bitmap = nullptr; + if (num_regs > 0) { + Runtime* runtime = Runtime::Current(); + const void* entry_point = runtime->GetInstrumentation()->GetQuickCodeFor(m, sizeof(void*)); + uintptr_t native_pc_offset = m->NativeQuickPcOffset(GetCurrentQuickFramePc(), entry_point); + reg_bitmap = map.FindBitMap(native_pc_offset); + DCHECK(reg_bitmap != nullptr); + } + // Does this register hold a reference? + return vreg < num_regs && TestBitmap(vreg, reg_bitmap); +} + bool StackVisitor::GetVReg(mirror::ArtMethod* m, uint16_t vreg, VRegKind kind, uint32_t* val) const { if (cur_quick_frame_ != nullptr) { diff --git a/runtime/stack.h b/runtime/stack.h index 3f1bff8b9c..ab8641b4d5 100644 --- a/runtime/stack.h +++ b/runtime/stack.h @@ -478,6 +478,9 @@ class StackVisitor { bool GetNextMethodAndDexPc(mirror::ArtMethod** next_method, uint32_t* next_dex_pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + bool IsReferenceVReg(mirror::ArtMethod* m, uint16_t vreg) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + bool GetVReg(mirror::ArtMethod* m, uint16_t vreg, VRegKind kind, uint32_t* val) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); diff --git a/runtime/thread.cc b/runtime/thread.cc index c8aad1b787..605a1b5419 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -2311,10 +2311,6 @@ class ReferenceMapVisitor : public StackVisitor { } } - static bool TestBitmap(size_t reg, const uint8_t* reg_vector) { - return ((reg_vector[reg / kBitsPerByte] >> (reg % kBitsPerByte)) & 0x01) != 0; - } - // Visitor for when we visit a root. RootVisitor& visitor_; }; diff --git a/runtime/utils.h b/runtime/utils.h index eaafcf0a64..71ccf85277 100644 --- a/runtime/utils.h +++ b/runtime/utils.h @@ -604,6 +604,11 @@ std::unique_ptr<T> MakeUnique(Args&& ... args) { return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); } +inline bool TestBitmap(size_t idx, const uint8_t* bitmap) { + return ((bitmap[idx / kBitsPerByte] >> (idx % kBitsPerByte)) & 0x01) != 0; +} + + } // namespace art #endif // ART_RUNTIME_UTILS_H_ |