Home | History | Annotate | Download | only in runtime
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef ART_RUNTIME_HANDLE_H_
     18 #define ART_RUNTIME_HANDLE_H_
     19 
     20 #include "base/casts.h"
     21 #include "base/logging.h"
     22 #include "base/macros.h"
     23 #include "base/mutex.h"
     24 #include "base/value_object.h"
     25 #include "jni.h"
     26 #include "obj_ptr.h"
     27 #include "stack_reference.h"
     28 
     29 namespace art {
     30 
     31 class Thread;
     32 
     33 template<class T> class Handle;
     34 
     35 // Handles are memory locations that contain GC roots. As the mirror::Object*s within a handle are
     36 // GC visible then the GC may move the references within them, something that couldn't be done with
     37 // a wrap pointer. Handles are generally allocated within HandleScopes. Handle is a super-class
     38 // of MutableHandle and doesn't support assignment operations.
     39 template<class T>
     40 class Handle : public ValueObject {
     41  public:
     42   Handle() : reference_(nullptr) {
     43   }
     44 
     45   ALWAYS_INLINE Handle(const Handle<T>& handle) = default;
     46 
     47   ALWAYS_INLINE Handle<T>& operator=(const Handle<T>& handle) = default;
     48 
     49   ALWAYS_INLINE explicit Handle(StackReference<T>* reference) : reference_(reference) {
     50   }
     51 
     52   ALWAYS_INLINE T& operator*() const REQUIRES_SHARED(Locks::mutator_lock_) {
     53     return *Get();
     54   }
     55 
     56   ALWAYS_INLINE T* operator->() const REQUIRES_SHARED(Locks::mutator_lock_) {
     57     return Get();
     58   }
     59 
     60   ALWAYS_INLINE T* Get() const REQUIRES_SHARED(Locks::mutator_lock_) {
     61     return down_cast<T*>(reference_->AsMirrorPtr());
     62   }
     63 
     64   ALWAYS_INLINE bool IsNull() const REQUIRES_SHARED(Locks::mutator_lock_) {
     65     return Get() == nullptr;
     66   }
     67 
     68   ALWAYS_INLINE jobject ToJObject() const REQUIRES_SHARED(Locks::mutator_lock_) {
     69     if (UNLIKELY(reference_->AsMirrorPtr() == nullptr)) {
     70       // Special case so that we work with null handles.
     71       return nullptr;
     72     }
     73     return reinterpret_cast<jobject>(reference_);
     74   }
     75 
     76   ALWAYS_INLINE StackReference<mirror::Object>* GetReference() {
     77     return reference_;
     78   }
     79 
     80   ALWAYS_INLINE const StackReference<mirror::Object>* GetReference() const {
     81     return reference_;
     82   }
     83 
     84   ALWAYS_INLINE bool operator!=(std::nullptr_t) const REQUIRES_SHARED(Locks::mutator_lock_) {
     85     return !IsNull();
     86   }
     87 
     88   ALWAYS_INLINE bool operator==(std::nullptr_t) const REQUIRES_SHARED(Locks::mutator_lock_) {
     89     return IsNull();
     90   }
     91 
     92  protected:
     93   template<typename S>
     94   explicit Handle(StackReference<S>* reference)
     95       : reference_(reference) {
     96   }
     97   template<typename S>
     98   explicit Handle(const Handle<S>& handle)
     99       : reference_(handle.reference_) {
    100   }
    101 
    102   StackReference<mirror::Object>* reference_;
    103 
    104  private:
    105   friend class BuildGenericJniFrameVisitor;
    106   template<class S> friend class Handle;
    107   friend class HandleScope;
    108   template<class S> friend class HandleWrapper;
    109   template<size_t kNumReferences> friend class StackHandleScope;
    110 };
    111 
    112 // Handles that support assignment.
    113 template<class T>
    114 class MutableHandle : public Handle<T> {
    115  public:
    116   MutableHandle() {
    117   }
    118 
    119   ALWAYS_INLINE MutableHandle(const MutableHandle<T>& handle)
    120       REQUIRES_SHARED(Locks::mutator_lock_) = default;
    121 
    122   ALWAYS_INLINE MutableHandle<T>& operator=(const MutableHandle<T>& handle)
    123       REQUIRES_SHARED(Locks::mutator_lock_) = default;
    124 
    125   ALWAYS_INLINE explicit MutableHandle(StackReference<T>* reference)
    126       REQUIRES_SHARED(Locks::mutator_lock_)
    127       : Handle<T>(reference) {
    128   }
    129 
    130   ALWAYS_INLINE T* Assign(T* reference) REQUIRES_SHARED(Locks::mutator_lock_) {
    131     StackReference<mirror::Object>* ref = Handle<T>::GetReference();
    132     T* old = down_cast<T*>(ref->AsMirrorPtr());
    133     ref->Assign(reference);
    134     return old;
    135   }
    136 
    137   ALWAYS_INLINE T* Assign(ObjPtr<T> reference) REQUIRES_SHARED(Locks::mutator_lock_) {
    138     StackReference<mirror::Object>* ref = Handle<T>::GetReference();
    139     T* old = down_cast<T*>(ref->AsMirrorPtr());
    140     ref->Assign(reference.Ptr());
    141     return old;
    142   }
    143 
    144 
    145   template<typename S>
    146   explicit MutableHandle(const MutableHandle<S>& handle) REQUIRES_SHARED(Locks::mutator_lock_)
    147       : Handle<T>(handle) {
    148   }
    149 
    150   template<typename S>
    151   explicit MutableHandle(StackReference<S>* reference) REQUIRES_SHARED(Locks::mutator_lock_)
    152       : Handle<T>(reference) {
    153   }
    154 
    155  private:
    156   friend class BuildGenericJniFrameVisitor;
    157   friend class HandleScope;
    158   template<class S> friend class HandleWrapper;
    159   template<size_t kNumReferences> friend class StackHandleScope;
    160 };
    161 
    162 // A special case of Handle that only holds references to null. Invalid when if it goes out of
    163 // scope. Example: Handle<T> h = ScopedNullHandle<T> will leave h being undefined.
    164 template<class T>
    165 class ScopedNullHandle : public Handle<T> {
    166  public:
    167   ScopedNullHandle() : Handle<T>(&null_ref_) {}
    168 
    169  private:
    170   StackReference<mirror::Object> null_ref_;
    171 };
    172 
    173 }  // namespace art
    174 
    175 #endif  // ART_RUNTIME_HANDLE_H_
    176