Avoid strict-aliasing problems with Handles.
Replace use of reinterpret_cast with down_cast.
Bug: 18074773
Change-Id: Id42d462f2798f69a2210e5912f441c868b8b5812
diff --git a/runtime/handle.h b/runtime/handle.h
index addb663..6af3220 100644
--- a/runtime/handle.h
+++ b/runtime/handle.h
@@ -20,6 +20,7 @@
#include "base/casts.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/value_object.h"
#include "stack.h"
namespace art {
@@ -33,7 +34,7 @@
// a wrap pointer. Handles are generally allocated within HandleScopes. Handle is a super-class
// of MutableHandle and doesn't support assignment operations.
template<class T>
-class Handle {
+class Handle : public ValueObject {
public:
Handle() : reference_(nullptr) {
}
@@ -58,7 +59,7 @@
}
ALWAYS_INLINE T* Get() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return reference_->AsMirrorPtr();
+ return down_cast<T*>(reference_->AsMirrorPtr());
}
ALWAYS_INLINE jobject ToJObject() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -70,25 +71,25 @@
}
protected:
- StackReference<T>* reference_;
-
template<typename S>
explicit Handle(StackReference<S>* reference)
- : reference_(reinterpret_cast<StackReference<T>*>(reference)) {
+ : reference_(reference) {
}
template<typename S>
explicit Handle(const Handle<S>& handle)
- : reference_(reinterpret_cast<StackReference<T>*>(handle.reference_)) {
+ : reference_(handle.reference_) {
}
- StackReference<T>* GetReference() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE {
+ StackReference<mirror::Object>* GetReference() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE {
return reference_;
}
- ALWAYS_INLINE const StackReference<T>* GetReference() const
+ ALWAYS_INLINE const StackReference<mirror::Object>* GetReference() const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return reference_;
}
+ StackReference<mirror::Object>* reference_;
+
private:
friend class BuildGenericJniFrameVisitor;
template<class S> friend class Handle;
@@ -121,8 +122,8 @@
}
ALWAYS_INLINE T* Assign(T* reference) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- StackReference<T>* ref = Handle<T>::GetReference();
- T* const old = ref->AsMirrorPtr();
+ StackReference<mirror::Object>* ref = Handle<T>::GetReference();
+ T* old = down_cast<T*>(ref->AsMirrorPtr());
ref->Assign(reference);
return old;
}
@@ -132,7 +133,6 @@
: Handle<T>(handle) {
}
- protected:
template<typename S>
explicit MutableHandle(StackReference<S>* reference) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
: Handle<T>(reference) {
@@ -153,7 +153,7 @@
}
private:
- StackReference<T> null_ref_;
+ StackReference<mirror::Object> null_ref_;
};
} // namespace art
diff --git a/runtime/handle_scope.h b/runtime/handle_scope.h
index f795e38..13c939f 100644
--- a/runtime/handle_scope.h
+++ b/runtime/handle_scope.h
@@ -159,7 +159,7 @@
}
private:
- T** obj_;
+ T** const obj_;
};
// Scoped handle storage of a fixed size that is usually stack allocated.
@@ -169,19 +169,28 @@
explicit StackHandleScope(Thread* self);
~StackHandleScope();
- // Currently unused, using this GetReference instead of the one in HandleScope is preferred to
- // avoid compiler optimizations incorrectly optimizing out of bound array accesses.
- // TODO: Remove this when it is un-necessary.
- ALWAYS_INLINE mirror::Object* GetReference(size_t i) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK_LT(i, kNumReferences);
- return GetReferences()[i].AsMirrorPtr();
+ template<class T>
+ MutableHandle<T> NewHandle(T* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ SetReference(pos_, object);
+ MutableHandle<T> h(GetHandle<T>(pos_));
+ pos_++;
+ return h;
}
- ALWAYS_INLINE MutableHandle<mirror::Object> GetHandle(size_t i)
+ template<class T>
+ HandleWrapper<T> NewHandleWrapper(T** object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ SetReference(pos_, *object);
+ MutableHandle<T> h(GetHandle<T>(pos_));
+ pos_++;
+ return HandleWrapper<T>(object, h);
+ }
+
+ private:
+ template<class T>
+ ALWAYS_INLINE MutableHandle<T> GetHandle(size_t i)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
DCHECK_LT(i, kNumReferences);
- return MutableHandle<mirror::Object>(&GetReferences()[i]);
+ return MutableHandle<T>(&GetReferences()[i]);
}
ALWAYS_INLINE void SetReference(size_t i, mirror::Object* object)
@@ -190,23 +199,6 @@
GetReferences()[i].Assign(object);
}
- template<class T>
- MutableHandle<T> NewHandle(T* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- SetReference(pos_, object);
- MutableHandle<T> h(GetHandle(pos_));
- pos_++;
- return h;
- }
-
- template<class T>
- HandleWrapper<T> NewHandleWrapper(T** object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- SetReference(pos_, *object);
- MutableHandle<T> h(GetHandle(pos_));
- pos_++;
- return HandleWrapper<T>(object, h);
- }
-
- private:
// Reference storage needs to be first as expected by the HandleScope layout.
StackReference<mirror::Object> storage_[kNumReferences];