Change MethodHelper to use a Handle.

Added ConstHandle to help prevent errors where you modify the value
stored in the handle of the caller. Also fixed compaction bugs
related to not knowing MethodHelper::GetReturnType can resolve types.
This bug was present in interpreter RETURN_OBJECT.

Bug: 13077697

Change-Id: I71f964d4d810ab4debda1a09bc968af8f3c874a3
diff --git a/runtime/handle.h b/runtime/handle.h
index b70f651..7e13601 100644
--- a/runtime/handle.h
+++ b/runtime/handle.h
@@ -26,18 +26,20 @@
 
 class Thread;
 
+template<class T> class Handle;
+
 template<class T>
-class Handle {
+class ConstHandle {
  public:
-  Handle() : reference_(nullptr) {
+  ConstHandle() : reference_(nullptr) {
   }
-  Handle(const Handle<T>& handle) ALWAYS_INLINE : reference_(handle.reference_) {
+  ConstHandle(const ConstHandle<T>& handle) ALWAYS_INLINE : reference_(handle.reference_) {
   }
-  Handle<T>& operator=(const Handle<T>& handle) ALWAYS_INLINE {
+  ConstHandle<T>& operator=(const ConstHandle<T>& handle) ALWAYS_INLINE {
     reference_ = handle.reference_;
     return *this;
   }
-  explicit Handle(StackReference<T>* reference) ALWAYS_INLINE : reference_(reference) {
+  explicit ConstHandle(StackReference<T>* reference) ALWAYS_INLINE : reference_(reference) {
   }
   T& operator*() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE {
     return *Get();
@@ -48,11 +50,6 @@
   T* Get() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE {
     return reference_->AsMirrorPtr();
   }
-  T* Assign(T* reference) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE {
-    T* old = reference_->AsMirrorPtr();
-    reference_->Assign(reference);
-    return old;
-  }
   jobject ToJObject() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE {
     if (UNLIKELY(reference_->AsMirrorPtr() == nullptr)) {
       // Special case so that we work with NullHandles.
@@ -65,17 +62,62 @@
   StackReference<T>* reference_;
 
   template<typename S>
-  explicit Handle(StackReference<S>* reference)
+  explicit ConstHandle(StackReference<S>* reference)
       : reference_(reinterpret_cast<StackReference<T>*>(reference)) {
   }
   template<typename S>
-  explicit Handle(const Handle<S>& handle)
+  explicit ConstHandle(const ConstHandle<S>& handle)
       : reference_(reinterpret_cast<StackReference<T>*>(handle.reference_)) {
   }
 
   StackReference<T>* GetReference() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE {
     return reference_;
   }
+  const StackReference<T>* GetReference() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+      ALWAYS_INLINE {
+    return reference_;
+  }
+
+ private:
+  friend class BuildGenericJniFrameVisitor;
+  template<class S> friend class ConstHandle;
+  friend class HandleScope;
+  template<class S> friend class HandleWrapper;
+  template<size_t kNumReferences> friend class StackHandleScope;
+};
+
+template<class T>
+class Handle : public ConstHandle<T> {
+ public:
+  Handle() {
+  }
+  Handle(const Handle<T>& handle) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE
+      : ConstHandle<T>(handle.reference_) {
+  }
+  Handle<T>& operator=(const Handle<T>& handle) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+      ALWAYS_INLINE {
+    ConstHandle<T>::operator=(handle);
+    return *this;
+  }
+  explicit Handle(StackReference<T>* reference) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+      ALWAYS_INLINE : ConstHandle<T>(reference) {
+  }
+  T* Assign(T* reference) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE {
+    StackReference<T>* ref = ConstHandle<T>::GetReference();
+    T* const old = ref->AsMirrorPtr();
+    ref->Assign(reference);
+    return old;
+  }
+
+ protected:
+  template<typename S>
+  explicit Handle(StackReference<S>* reference) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+      : ConstHandle<T>(reference) {
+  }
+  template<typename S>
+  explicit Handle(const Handle<S>& handle) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
+      : ConstHandle<T>(handle) {
+  }
 
  private:
   friend class BuildGenericJniFrameVisitor;