blob: c8ebfc331a83f839136251eaca3554e648fcb529 [file] [log] [blame]
Alex Light79d6c802019-06-27 15:50:11 +00001/*
2 * Copyright (C) 2019 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_JNI_JNI_ID_MANAGER_H_
18#define ART_RUNTIME_JNI_JNI_ID_MANAGER_H_
19
Nicolas Geoffrayc34eab42019-10-07 07:15:53 +000020#include <jni.h>
Alex Light55eccdf2019-10-07 13:51:13 +000021
22#include <atomic>
Alex Light79d6c802019-06-27 15:50:11 +000023#include <vector>
24
25#include "art_field.h"
26#include "art_method.h"
27#include "base/mutex.h"
Alex Lightbc19b752019-12-02 18:54:13 +000028#include "gc_root.h"
Alex Lightf3677472019-06-26 16:31:53 -070029#include "jni_id_type.h"
Alex Lightc18eba32019-09-24 14:36:27 -070030#include "reflective_value_visitor.h"
Alex Light79d6c802019-06-27 15:50:11 +000031
32namespace art {
Alex Lightbc19b752019-12-02 18:54:13 +000033namespace mirror {
34class Object;
35class ClassExt;
36} // namespace mirror
Alex Light55eccdf2019-10-07 13:51:13 +000037template<typename RT> class ReflectiveHandle;
38
Alex Light79d6c802019-06-27 15:50:11 +000039namespace jni {
40
41class ScopedEnableSuspendAllJniIdQueries;
42class JniIdManager {
43 public:
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +000044 template <typename T,
45 typename = typename std::enable_if<std::is_same_v<T, jmethodID> ||
46 std::is_same_v<T, jfieldID>>>
47 static constexpr bool IsIndexId(T val) {
48 return val == nullptr || reinterpret_cast<uintptr_t>(val) % 2 == 1;
49 }
50
Alex Lightbc19b752019-12-02 18:54:13 +000051 void Init(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_);
52
Alex Light79d6c802019-06-27 15:50:11 +000053 ArtMethod* DecodeMethodId(jmethodID method) REQUIRES(!Locks::jni_id_lock_);
54 ArtField* DecodeFieldId(jfieldID field) REQUIRES(!Locks::jni_id_lock_);
Alex Light55eccdf2019-10-07 13:51:13 +000055 jmethodID EncodeMethodId(ReflectiveHandle<ArtMethod> method) REQUIRES(!Locks::jni_id_lock_)
56 REQUIRES_SHARED(Locks::mutator_lock_);
Alex Light79d6c802019-06-27 15:50:11 +000057 jmethodID EncodeMethodId(ArtMethod* method) REQUIRES(!Locks::jni_id_lock_)
58 REQUIRES_SHARED(Locks::mutator_lock_);
Alex Light55eccdf2019-10-07 13:51:13 +000059 jfieldID EncodeFieldId(ReflectiveHandle<ArtField> field) REQUIRES(!Locks::jni_id_lock_)
60 REQUIRES_SHARED(Locks::mutator_lock_);
Alex Light79d6c802019-06-27 15:50:11 +000061 jfieldID EncodeFieldId(ArtField* field) REQUIRES(!Locks::jni_id_lock_)
62 REQUIRES_SHARED(Locks::mutator_lock_);
63
Alex Lightc18eba32019-09-24 14:36:27 -070064 void VisitReflectiveTargets(ReflectiveValueVisitor* rvv)
65 REQUIRES(Locks::mutator_lock_, !Locks::jni_id_lock_);
Nicolas Geoffray4ac0e152019-09-18 06:14:50 +000066
Alex Lightbc19b752019-12-02 18:54:13 +000067 void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_);
68
69 ObjPtr<mirror::Object> GetPointerMarker() REQUIRES_SHARED(Locks::mutator_lock_);
70
Alex Light79d6c802019-06-27 15:50:11 +000071 private:
72 template <typename ArtType>
Alex Light55eccdf2019-10-07 13:51:13 +000073 uintptr_t EncodeGenericId(ReflectiveHandle<ArtType> t) REQUIRES(!Locks::jni_id_lock_)
Alex Light79d6c802019-06-27 15:50:11 +000074 REQUIRES_SHARED(Locks::mutator_lock_);
75 template <typename ArtType>
76 ArtType* DecodeGenericId(uintptr_t input) REQUIRES(!Locks::jni_id_lock_);
Alex Light55eccdf2019-10-07 13:51:13 +000077 template <typename ArtType> std::vector<ArtType*>& GetGenericMap()
78 REQUIRES(Locks::jni_id_lock_);
Alex Lightbc19b752019-12-02 18:54:13 +000079 template <typename ArtType> uintptr_t GetNextId(JniIdType id)
Alex Light55eccdf2019-10-07 13:51:13 +000080 REQUIRES_SHARED(Locks::mutator_lock_)
81 REQUIRES(Locks::jni_id_lock_);
Alex Light79d6c802019-06-27 15:50:11 +000082 template <typename ArtType>
Alex Light55eccdf2019-10-07 13:51:13 +000083 size_t GetLinearSearchStartId(ReflectiveHandle<ArtType> t)
84 REQUIRES(Locks::jni_id_lock_)
85 REQUIRES_SHARED(Locks::mutator_lock_);
Alex Light79d6c802019-06-27 15:50:11 +000086
87 void StartDefer() REQUIRES(!Locks::jni_id_lock_) REQUIRES_SHARED(Locks::mutator_lock_);
88 void EndDefer() REQUIRES(!Locks::jni_id_lock_) REQUIRES_SHARED(Locks::mutator_lock_);
89
90 uintptr_t next_method_id_ GUARDED_BY(Locks::jni_id_lock_) = 1u;
91 std::vector<ArtMethod*> method_id_map_ GUARDED_BY(Locks::jni_id_lock_);
92 uintptr_t next_field_id_ GUARDED_BY(Locks::jni_id_lock_) = 1u;
93 std::vector<ArtField*> field_id_map_ GUARDED_BY(Locks::jni_id_lock_);
94
95 // If non-zero indicates that some thread is trying to allocate ids without being able to update
96 // the method->id mapping (due to not being able to allocate or something). In this case decode
97 // and encode need to do a linear scan of the lists. The ScopedEnableSuspendAllJniIdQueries struct
98 // will deal with fixing everything up.
99 size_t deferred_allocation_refcount_ GUARDED_BY(Locks::jni_id_lock_) = 0;
100 // min jmethodID that might not have it's method->id mapping filled in.
101 uintptr_t deferred_allocation_method_id_start_ GUARDED_BY(Locks::jni_id_lock_) = 0u;
102 // min jfieldID that might not have it's field->id mapping filled in.
103 uintptr_t deferred_allocation_field_id_start_ GUARDED_BY(Locks::jni_id_lock_) = 0u;
104
Alex Lightbc19b752019-12-02 18:54:13 +0000105 GcRoot<mirror::Object> pointer_marker_;
106
Alex Light79d6c802019-06-27 15:50:11 +0000107 friend class ScopedEnableSuspendAllJniIdQueries;
Alex Lightbc19b752019-12-02 18:54:13 +0000108 // For GetPointerMarker
109 friend class mirror::ClassExt;
Alex Light79d6c802019-06-27 15:50:11 +0000110};
111
112// A scope that will enable using the Encode/Decode JNI id functions with all threads suspended.
113// This is required since normally we need to be able to allocate to encode new ids. This should
114// only be used when absolutely required, for example to invoke user-callbacks during heap walking
115// or similar.
116class ScopedEnableSuspendAllJniIdQueries {
117 public:
118 ScopedEnableSuspendAllJniIdQueries() REQUIRES_SHARED(Locks::mutator_lock_);
119 ~ScopedEnableSuspendAllJniIdQueries() REQUIRES_SHARED(Locks::mutator_lock_);
120
121 private:
122 JniIdManager* manager_;
123};
124
125} // namespace jni
126} // namespace art
127
128#endif // ART_RUNTIME_JNI_JNI_ID_MANAGER_H_