summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/interpreter/mterp/arm/floating_point.S5
-rw-r--r--runtime/interpreter/mterp/mterp.cc8
-rw-r--r--runtime/obj_ptr.h57
3 files changed, 41 insertions, 29 deletions
diff --git a/runtime/interpreter/mterp/arm/floating_point.S b/runtime/interpreter/mterp/arm/floating_point.S
index 9e4d00cb9a..035fc134dd 100644
--- a/runtime/interpreter/mterp/arm/floating_point.S
+++ b/runtime/interpreter/mterp/arm/floating_point.S
@@ -413,9 +413,10 @@ f2l_maybeNaN:
*/
mov r3, rINST, lsr #12 @ r3<- B
ubfx r9, rINST, #8, #4 @ r9<- A
+ CLEAR_SHADOW_PAIR r9, ip, lr @ Zero shadow regs
VREG_INDEX_TO_ADDR r3, r3 @ r3<- &fp[B]
VREG_INDEX_TO_ADDR r9, r9 @ r9<- &fp[A]
- vldr d0, [r3] @ d0<- vAA
+ GET_VREG_DOUBLE_BY_ADDR d0, r3 @ d0<- vBB
FETCH_ADVANCE_INST 1 @ advance rPC, load rINST
vcvt.f64.s32 d1, s1 @ d1<- (double)(vAAh)
@@ -424,7 +425,7 @@ f2l_maybeNaN:
vmla.f64 d2, d1, d3 @ d2<- vAAh*2^32 + vAAl
GET_INST_OPCODE ip @ extract opcode from rINST
- vstr.64 d2, [r9] @ vAA<- d2
+ SET_VREG_DOUBLE_BY_ADDR d2, r9 @ vAA<- d2
GOTO_OPCODE ip @ jump to next instruction
/* literal pool helper */
diff --git a/runtime/interpreter/mterp/mterp.cc b/runtime/interpreter/mterp/mterp.cc
index 878d9215dd..912c44463f 100644
--- a/runtime/interpreter/mterp/mterp.cc
+++ b/runtime/interpreter/mterp/mterp.cc
@@ -539,6 +539,11 @@ extern "C" size_t MterpHandleException(Thread* self, ShadowFrame* shadow_frame)
return MoveToExceptionHandler(self, *shadow_frame, instrumentation);
}
+struct MterpCheckHelper {
+ DECLARE_RUNTIME_DEBUG_FLAG(kSlowMode);
+};
+DEFINE_RUNTIME_DEBUG_FLAG(MterpCheckHelper, kSlowMode);
+
extern "C" void MterpCheckBefore(Thread* self, ShadowFrame* shadow_frame, uint16_t* dex_pc_ptr)
REQUIRES_SHARED(Locks::mutator_lock_) {
// Check that we are using the right interpreter.
@@ -563,6 +568,9 @@ extern "C" void MterpCheckBefore(Thread* self, ShadowFrame* shadow_frame, uint16
// Save invalid dex pc to force segfault if improperly used.
shadow_frame->SetDexPCPtr(reinterpret_cast<uint16_t*>(kExportPCPoison));
}
+ if (MterpCheckHelper::kSlowMode) {
+ shadow_frame->CheckConsistentVRegs();
+ }
}
extern "C" void MterpLogDivideByZeroException(Thread* self, ShadowFrame* shadow_frame)
diff --git a/runtime/obj_ptr.h b/runtime/obj_ptr.h
index 60e21ab3b5..efbb66fdde 100644
--- a/runtime/obj_ptr.h
+++ b/runtime/obj_ptr.h
@@ -24,6 +24,9 @@
#include "base/macros.h"
#include "base/mutex.h" // For Locks::mutator_lock_.
+// Always inline ObjPtr methods even in debug builds.
+#define OBJPTR_INLINE __attribute__ ((always_inline))
+
namespace art {
constexpr bool kObjPtrPoisoning = kIsDebugBuild;
@@ -45,26 +48,26 @@ class ObjPtr {
"must have a least kObjectAlignmentShift bits");
public:
- ALWAYS_INLINE ObjPtr() REQUIRES_SHARED(Locks::mutator_lock_) : reference_(0u) {}
+ OBJPTR_INLINE ObjPtr() REQUIRES_SHARED(Locks::mutator_lock_) : reference_(0u) {}
// Note: The following constructors allow implicit conversion. This simplifies code that uses
// them, e.g., for parameter passing. However, in general, implicit-conversion constructors
// are discouraged and detected by clang-tidy.
- ALWAYS_INLINE ObjPtr(std::nullptr_t)
+ OBJPTR_INLINE ObjPtr(std::nullptr_t)
REQUIRES_SHARED(Locks::mutator_lock_)
: reference_(0u) {}
template <typename Type,
typename = typename std::enable_if<std::is_base_of<MirrorType, Type>::value>::type>
- ALWAYS_INLINE ObjPtr(Type* ptr)
+ OBJPTR_INLINE ObjPtr(Type* ptr)
REQUIRES_SHARED(Locks::mutator_lock_)
: reference_(Encode(static_cast<MirrorType*>(ptr))) {
}
template <typename Type,
typename = typename std::enable_if<std::is_base_of<MirrorType, Type>::value>::type>
- ALWAYS_INLINE ObjPtr(const ObjPtr<Type>& other)
+ OBJPTR_INLINE ObjPtr(const ObjPtr<Type>& other)
REQUIRES_SHARED(Locks::mutator_lock_)
: reference_(kObjPtrPoisoningValidateOnCopy
? Encode(static_cast<MirrorType*>(other.Ptr()))
@@ -73,7 +76,7 @@ class ObjPtr {
template <typename Type,
typename = typename std::enable_if<std::is_base_of<MirrorType, Type>::value>::type>
- ALWAYS_INLINE ObjPtr& operator=(const ObjPtr<Type>& other)
+ OBJPTR_INLINE ObjPtr& operator=(const ObjPtr<Type>& other)
REQUIRES_SHARED(Locks::mutator_lock_) {
reference_ = kObjPtrPoisoningValidateOnCopy
? Encode(static_cast<MirrorType*>(other.Ptr()))
@@ -81,63 +84,63 @@ class ObjPtr {
return *this;
}
- ALWAYS_INLINE ObjPtr& operator=(MirrorType* ptr) REQUIRES_SHARED(Locks::mutator_lock_) {
+ OBJPTR_INLINE ObjPtr& operator=(MirrorType* ptr) REQUIRES_SHARED(Locks::mutator_lock_) {
Assign(ptr);
return *this;
}
- ALWAYS_INLINE void Assign(MirrorType* ptr) REQUIRES_SHARED(Locks::mutator_lock_) {
+ OBJPTR_INLINE void Assign(MirrorType* ptr) REQUIRES_SHARED(Locks::mutator_lock_) {
reference_ = Encode(ptr);
}
- ALWAYS_INLINE MirrorType* operator->() const REQUIRES_SHARED(Locks::mutator_lock_) {
+ OBJPTR_INLINE MirrorType* operator->() const REQUIRES_SHARED(Locks::mutator_lock_) {
return Ptr();
}
- ALWAYS_INLINE bool IsNull() const {
+ OBJPTR_INLINE bool IsNull() const {
return reference_ == 0;
}
// Ptr makes sure that the object pointer is valid.
- ALWAYS_INLINE MirrorType* Ptr() const REQUIRES_SHARED(Locks::mutator_lock_) {
+ OBJPTR_INLINE MirrorType* Ptr() const REQUIRES_SHARED(Locks::mutator_lock_) {
AssertValid();
return PtrUnchecked();
}
- ALWAYS_INLINE bool IsValid() const REQUIRES_SHARED(Locks::mutator_lock_);
+ OBJPTR_INLINE bool IsValid() const REQUIRES_SHARED(Locks::mutator_lock_);
- ALWAYS_INLINE void AssertValid() const REQUIRES_SHARED(Locks::mutator_lock_);
+ OBJPTR_INLINE void AssertValid() const REQUIRES_SHARED(Locks::mutator_lock_);
- ALWAYS_INLINE bool operator==(const ObjPtr& ptr) const REQUIRES_SHARED(Locks::mutator_lock_) {
+ OBJPTR_INLINE bool operator==(const ObjPtr& ptr) const REQUIRES_SHARED(Locks::mutator_lock_) {
return Ptr() == ptr.Ptr();
}
template <typename PointerType>
- ALWAYS_INLINE bool operator==(const PointerType* ptr) const
+ OBJPTR_INLINE bool operator==(const PointerType* ptr) const
REQUIRES_SHARED(Locks::mutator_lock_) {
return Ptr() == ptr;
}
- ALWAYS_INLINE bool operator==(std::nullptr_t) const {
+ OBJPTR_INLINE bool operator==(std::nullptr_t) const {
return IsNull();
}
- ALWAYS_INLINE bool operator!=(const ObjPtr& ptr) const REQUIRES_SHARED(Locks::mutator_lock_) {
+ OBJPTR_INLINE bool operator!=(const ObjPtr& ptr) const REQUIRES_SHARED(Locks::mutator_lock_) {
return Ptr() != ptr.Ptr();
}
template <typename PointerType>
- ALWAYS_INLINE bool operator!=(const PointerType* ptr) const
+ OBJPTR_INLINE bool operator!=(const PointerType* ptr) const
REQUIRES_SHARED(Locks::mutator_lock_) {
return Ptr() != ptr;
}
- ALWAYS_INLINE bool operator!=(std::nullptr_t) const {
+ OBJPTR_INLINE bool operator!=(std::nullptr_t) const {
return !IsNull();
}
// Ptr unchecked does not check that object pointer is valid. Do not use if you can avoid it.
- ALWAYS_INLINE MirrorType* PtrUnchecked() const {
+ OBJPTR_INLINE MirrorType* PtrUnchecked() const {
if (kObjPtrPoisoning) {
return reinterpret_cast<MirrorType*>(
static_cast<uintptr_t>(static_cast<uint32_t>(reference_ << kObjectAlignmentShift)));
@@ -156,13 +159,13 @@ class ObjPtr {
private:
// Trim off high bits of thread local cookie.
- ALWAYS_INLINE static uintptr_t GetCurrentTrimedCookie();
+ OBJPTR_INLINE static uintptr_t GetCurrentTrimedCookie();
- ALWAYS_INLINE uintptr_t GetCookie() const {
+ OBJPTR_INLINE uintptr_t GetCookie() const {
return reference_ >> kCookieShift;
}
- ALWAYS_INLINE static uintptr_t Encode(MirrorType* ptr) REQUIRES_SHARED(Locks::mutator_lock_);
+ OBJPTR_INLINE static uintptr_t Encode(MirrorType* ptr) REQUIRES_SHARED(Locks::mutator_lock_);
// The encoded reference and cookie.
uintptr_t reference_;
@@ -182,24 +185,24 @@ class HashObjPtr {
};
template<class MirrorType, typename PointerType>
-ALWAYS_INLINE bool operator==(const PointerType* a, const ObjPtr<MirrorType>& b)
+OBJPTR_INLINE bool operator==(const PointerType* a, const ObjPtr<MirrorType>& b)
REQUIRES_SHARED(Locks::mutator_lock_) {
return b == a;
}
template<class MirrorType>
-ALWAYS_INLINE bool operator==(std::nullptr_t, const ObjPtr<MirrorType>& b) {
+OBJPTR_INLINE bool operator==(std::nullptr_t, const ObjPtr<MirrorType>& b) {
return b == nullptr;
}
template<typename MirrorType, typename PointerType>
-ALWAYS_INLINE bool operator!=(const PointerType* a, const ObjPtr<MirrorType>& b)
+OBJPTR_INLINE bool operator!=(const PointerType* a, const ObjPtr<MirrorType>& b)
REQUIRES_SHARED(Locks::mutator_lock_) {
return b != a;
}
template<class MirrorType>
-ALWAYS_INLINE bool operator!=(std::nullptr_t, const ObjPtr<MirrorType>& b) {
+OBJPTR_INLINE bool operator!=(std::nullptr_t, const ObjPtr<MirrorType>& b) {
return b != nullptr;
}
@@ -214,7 +217,7 @@ static inline ObjPtr<MirrorType> MakeObjPtr(ObjPtr<MirrorType> ptr) {
}
template<class MirrorType>
-ALWAYS_INLINE std::ostream& operator<<(std::ostream& os, ObjPtr<MirrorType> ptr);
+OBJPTR_INLINE std::ostream& operator<<(std::ostream& os, ObjPtr<MirrorType> ptr);
} // namespace art