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 <android-base/logging.h>
     21 
     22 #include "base/casts.h"
     23 #include "base/macros.h"
     24 #include "base/mutex.h"
     25 #include "base/value_object.h"
     26 #include "jni.h"
     27 #include "obj_ptr.h"
     28 #include "stack_reference.h"
     29 
     30 namespace art {
     31 
     32 class Thread;
     33 
     34 template<class T> class Handle;
     35 
     36 // Handles are memory locations that contain GC roots. As the mirror::Object*s within a handle are
     37 // GC visible then the GC may move the references within them, something that couldn't be done with
     38 // a wrap pointer. Handles are generally allocated within HandleScopes. Handle is a super-class
     39 // of MutableHandle and doesn't support assignment operations.
     40 template<class T>
     41 class Handle : public ValueObject {
     42  public:
     43   Handle() : reference_(nullptr) {
     44   }
     45 
     46   ALWAYS_INLINE Handle(const Handle<T>& handle) = default;
     47 
     48   ALWAYS_INLINE Handle<T>& operator=(const Handle<T>& handle) = default;
     49 
     50   ALWAYS_INLINE explicit Handle(StackReference<T>* reference) : reference_(reference) {
     51   }
     52 
     53   ALWAYS_INLINE T& operator*() const REQUIRES_SHARED(Locks::mutator_lock_) {
     54     return *Get();
     55   }
     56 
     57   ALWAYS_INLINE T* operator->() const REQUIRES_SHARED(Locks::mutator_lock_) {
     58     return Get();
     59   }
     60 
     61   ALWAYS_INLINE T* Get() const REQUIRES_SHARED(Locks::mutator_lock_) {
     62     return down_cast<T*>(reference_->AsMirrorPtr());
     63   }
     64 
     65   ALWAYS_INLINE bool IsNull() const REQUIRES_SHARED(Locks::mutator_lock_) {
     66     return Get() == nullptr;
     67   }
     68 
     69   ALWAYS_INLINE jobject ToJObject() const REQUIRES_SHARED(Locks::mutator_lock_) {
     70     if (UNLIKELY(reference_->AsMirrorPtr() == nullptr)) {
     71       // Special case so that we work with null handles.
     72       return nullptr;
     73     }
     74     return reinterpret_cast<jobject>(reference_);
     75   }
     76 
     77   ALWAYS_INLINE StackReference<mirror::Object>* GetReference() {
     78     return reference_;
     79   }
     80 
     81   ALWAYS_INLINE const StackReference<mirror::Object>* GetReference() const {
     82     return reference_;
     83   }
     84 
     85   ALWAYS_INLINE bool operator!=(std::nullptr_t) const REQUIRES_SHARED(Locks::mutator_lock_) {
     86     return !IsNull();
     87   }
     88 
     89   ALWAYS_INLINE bool operator==(std::nullptr_t) const REQUIRES_SHARED(Locks::mutator_lock_) {
     90     return IsNull();
     91   }
     92 
     93  protected:
     94   template<typename S>
     95   explicit Handle(StackReference<S>* reference)
     96       : reference_(reference) {
     97   }
     98   template<typename S>
     99   explicit Handle(const Handle<S>& handle)
    100       : reference_(handle.reference_) {
    101   }
    102 
    103   StackReference<mirror::Object>* reference_;
    104 
    105  private:
    106   friend class BuildGenericJniFrameVisitor;
    107   template<class S> friend class Handle;
    108   friend class HandleScope;
    109   template<class S> friend class HandleWrapper;
    110   template<size_t kNumReferences> friend class StackHandleScope;
    111 };
    112 
    113 // Handles that support assignment.
    114 template<class T>
    115 class MutableHandle : public Handle<T> {
    116  public:
    117   MutableHandle() {
    118   }
    119 
    120   ALWAYS_INLINE MutableHandle(const MutableHandle<T>& handle)
    121       REQUIRES_SHARED(Locks::mutator_lock_) = default;
    122 
    123   ALWAYS_INLINE MutableHandle<T>& operator=(const MutableHandle<T>& handle)
    124       REQUIRES_SHARED(Locks::mutator_lock_) = default;
    125 
    126   ALWAYS_INLINE explicit MutableHandle(StackReference<T>* reference)
    127       REQUIRES_SHARED(Locks::mutator_lock_)
    128       : Handle<T>(reference) {
    129   }
    130 
    131   ALWAYS_INLINE T* Assign(T* reference) REQUIRES_SHARED(Locks::mutator_lock_) {
    132     StackReference<mirror::Object>* ref = Handle<T>::GetReference();
    133     T* old = down_cast<T*>(ref->AsMirrorPtr());
    134     ref->Assign(reference);
    135     return old;
    136   }
    137 
    138   ALWAYS_INLINE T* Assign(ObjPtr<T> reference) REQUIRES_SHARED(Locks::mutator_lock_) {
    139     StackReference<mirror::Object>* ref = Handle<T>::GetReference();
    140     T* old = down_cast<T*>(ref->AsMirrorPtr());
    141     ref->Assign(reference.Ptr());
    142     return old;
    143   }
    144 
    145 
    146   template<typename S>
    147   explicit MutableHandle(const MutableHandle<S>& handle) REQUIRES_SHARED(Locks::mutator_lock_)
    148       : Handle<T>(handle) {
    149   }
    150 
    151   template<typename S>
    152   explicit MutableHandle(StackReference<S>* reference) REQUIRES_SHARED(Locks::mutator_lock_)
    153       : Handle<T>(reference) {
    154   }
    155 
    156  private:
    157   friend class BuildGenericJniFrameVisitor;
    158   friend class HandleScope;
    159   template<class S> friend class HandleWrapper;
    160   template<size_t kNumReferences> friend class StackHandleScope;
    161 };
    162 
    163 // A special case of Handle that only holds references to null. Invalid when if it goes out of
    164 // scope. Example: Handle<T> h = ScopedNullHandle<T> will leave h being undefined.
    165 template<class T>
    166 class ScopedNullHandle : public Handle<T> {
    167  public:
    168   ScopedNullHandle() : Handle<T>(&null_ref_) {}
    169 
    170  private:
    171   StackReference<mirror::Object> null_ref_;
    172 };
    173 
    174 }  // namespace art
    175 
    176 #endif  // ART_RUNTIME_HANDLE_H_
    177