blob: 175bec51d6b15c560482aae5970e5dd6714ccba8 [file] [log] [blame]
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001/*
Mathieu Chartier0795f232016-09-27 18:43:30 -07002 * Copyright (C) 2016 The Android Open Source Project
Ian Rogers00f7d0e2012-07-19 15:28:27 -07003 *
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
Brian Carlstromfc0e3212013-07-17 14:40:12 -070017#ifndef ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_H_
18#define ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_H_
Ian Rogers00f7d0e2012-07-19 15:28:27 -070019
Mathieu Chartierc7853442015-03-27 14:35:38 -070020#include "art_field.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070021#include "base/casts.h"
22#include "base/value_object.h"
23#include "java_vm_ext.h"
24#include "thread_state.h"
Mathieu Chartier4e305412014-02-19 10:54:44 -080025#include "verify_object.h"
Ian Rogers00f7d0e2012-07-19 15:28:27 -070026
27namespace art {
28
Mathieu Chartier0795f232016-09-27 18:43:30 -070029struct JNIEnvExt;
30template<class MirrorType, bool kPoison> class ObjPtr;
31
Ian Rogers00f7d0e2012-07-19 15:28:27 -070032// Scoped change into and out of a particular state. Handles Runnable transitions that require
33// more complicated suspension checking. The subclasses ScopedObjectAccessUnchecked and
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070034// ScopedObjectAccess are used to handle the change into Runnable to Get direct access to objects,
Ian Rogers00f7d0e2012-07-19 15:28:27 -070035// the unchecked variant doesn't aid annotalysis.
Mathieu Chartierf1d666e2015-09-03 16:13:34 -070036class ScopedThreadStateChange : public ValueObject {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070037 public:
Mathieu Chartier0795f232016-09-27 18:43:30 -070038 ALWAYS_INLINE ScopedThreadStateChange(Thread* self, ThreadState new_thread_state)
39 REQUIRES(!Locks::thread_suspend_count_lock_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -070040
Mathieu Chartier0795f232016-09-27 18:43:30 -070041 ALWAYS_INLINE ~ScopedThreadStateChange() REQUIRES(!Locks::thread_suspend_count_lock_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -070042
Mathieu Chartier0795f232016-09-27 18:43:30 -070043 ALWAYS_INLINE Thread* Self() const {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070044 return self_;
45 }
46
47 protected:
48 // Constructor used by ScopedJniThreadState for an unattached thread that has access to the VM*.
Mathieu Chartier0795f232016-09-27 18:43:30 -070049 ScopedThreadStateChange() {}
Ian Rogers00f7d0e2012-07-19 15:28:27 -070050
Mathieu Chartier0795f232016-09-27 18:43:30 -070051 Thread* const self_ = nullptr;
52 const ThreadState thread_state_ = kTerminated;
Ian Rogers00f7d0e2012-07-19 15:28:27 -070053
54 private:
Mathieu Chartier0795f232016-09-27 18:43:30 -070055 ThreadState old_thread_state_ = kTerminated;
56 const bool expected_has_no_thread_ = true;
Ian Rogers00f7d0e2012-07-19 15:28:27 -070057
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -070058 friend class ScopedObjectAccessUnchecked;
Ian Rogers00f7d0e2012-07-19 15:28:27 -070059 DISALLOW_COPY_AND_ASSIGN(ScopedThreadStateChange);
60};
61
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -070062// Assumes we are already runnable.
Mathieu Chartierf1d666e2015-09-03 16:13:34 -070063class ScopedObjectAccessAlreadyRunnable : public ValueObject {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070064 public:
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -070065 Thread* Self() const {
66 return self_;
Ian Rogersc0fa3ad2013-02-05 00:11:55 -080067 }
68
Ian Rogers00f7d0e2012-07-19 15:28:27 -070069 JNIEnvExt* Env() const {
70 return env_;
71 }
72
73 JavaVMExt* Vm() const {
74 return vm_;
75 }
76
Ian Rogers68d8b422014-07-17 11:09:10 -070077 bool ForceCopy() const {
78 return vm_->ForceCopy();
79 }
80
Ian Rogers00f7d0e2012-07-19 15:28:27 -070081 /*
82 * Add a local reference for an object to the indirect reference table associated with the
83 * current stack frame. When the native function returns, the reference will be discarded.
Ian Rogers00f7d0e2012-07-19 15:28:27 -070084 *
Mathieu Chartier2cebb242015-04-21 16:50:40 -070085 * We need to allow the same reference to be added multiple times, and cope with nullptr.
Ian Rogers00f7d0e2012-07-19 15:28:27 -070086 *
Elliott Hughes9dcd45c2013-07-29 14:40:52 -070087 * This will be called on otherwise unreferenced objects. We cannot do GC allocations here, and
Ian Rogers00f7d0e2012-07-19 15:28:27 -070088 * it's best if we don't grab a mutex.
Ian Rogers00f7d0e2012-07-19 15:28:27 -070089 */
Mathieu Chartier0795f232016-09-27 18:43:30 -070090 template<typename T, typename MirrorType, bool kPoison = kIsDebugBuild>
91 T AddLocalReference(ObjPtr<MirrorType, kPoison> obj) const
92 REQUIRES_SHARED(Locks::mutator_lock_);
93
94 // TODO: Delete
Ian Rogers00f7d0e2012-07-19 15:28:27 -070095 template<typename T>
Mathieu Chartier0795f232016-09-27 18:43:30 -070096 T AddLocalReference(mirror::Object* obj) const
97 REQUIRES_SHARED(Locks::mutator_lock_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -070098
Mathieu Chartier0795f232016-09-27 18:43:30 -070099 template<typename T, bool kPoison = kIsDebugBuild>
100 ObjPtr<T, kPoison> Decode(jobject obj) const REQUIRES_SHARED(Locks::mutator_lock_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700101
Mathieu Chartier0795f232016-09-27 18:43:30 -0700102 ArtField* DecodeField(jfieldID fid) const REQUIRES_SHARED(Locks::mutator_lock_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700103
Mathieu Chartier0795f232016-09-27 18:43:30 -0700104 jfieldID EncodeField(ArtField* field) const REQUIRES_SHARED(Locks::mutator_lock_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700105
Mathieu Chartier0795f232016-09-27 18:43:30 -0700106 ArtMethod* DecodeMethod(jmethodID mid) const REQUIRES_SHARED(Locks::mutator_lock_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700107
Mathieu Chartier0795f232016-09-27 18:43:30 -0700108 jmethodID EncodeMethod(ArtMethod* method) const REQUIRES_SHARED(Locks::mutator_lock_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700109
Mathieu Chartier0795f232016-09-27 18:43:30 -0700110 ALWAYS_INLINE bool IsRunnable() const;
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700111
112 protected:
Mathieu Chartier0795f232016-09-27 18:43:30 -0700113 ALWAYS_INLINE explicit ScopedObjectAccessAlreadyRunnable(JNIEnv* env)
114 REQUIRES(!Locks::thread_suspend_count_lock_);
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700115
Mathieu Chartier0795f232016-09-27 18:43:30 -0700116 ALWAYS_INLINE explicit ScopedObjectAccessAlreadyRunnable(Thread* self)
117 REQUIRES(!Locks::thread_suspend_count_lock_);
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700118
119 // Used when we want a scoped JNI thread state but have no thread/JNIEnv. Consequently doesn't
120 // change into Runnable or acquire a share on the mutator_lock_.
121 explicit ScopedObjectAccessAlreadyRunnable(JavaVM* vm)
122 : self_(nullptr), env_(nullptr), vm_(down_cast<JavaVMExt*>(vm)) {}
123
124 // Here purely to force inlining.
Mathieu Chartier0795f232016-09-27 18:43:30 -0700125 ALWAYS_INLINE ~ScopedObjectAccessAlreadyRunnable() {}
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700126
127 // Self thread, can be null.
128 Thread* const self_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700129 // The full JNIEnv.
130 JNIEnvExt* const env_;
131 // The full JavaVM.
132 JavaVMExt* const vm_;
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700133};
134
135// Entry/exit processing for transitions from Native to Runnable (ie within JNI functions).
136//
137// This class performs the necessary thread state switching to and from Runnable and lets us
138// amortize the cost of working out the current thread. Additionally it lets us check (and repair)
139// apps that are using a JNIEnv on the wrong thread. The class also decodes and encodes Objects
140// into jobjects via methods of this class. Performing this here enforces the Runnable thread state
141// for use of Object, thereby inhibiting the Object being modified by GC whilst native or VM code
142// is also manipulating the Object.
143//
144// The destructor transitions back to the previous thread state, typically Native. In this state
145// GC and thread suspension may occur.
146//
147// For annotalysis the subclass ScopedObjectAccess (below) makes it explicit that a shared of
148// the mutator_lock_ will be acquired on construction.
149class ScopedObjectAccessUnchecked : public ScopedObjectAccessAlreadyRunnable {
150 public:
Mathieu Chartier0795f232016-09-27 18:43:30 -0700151 ALWAYS_INLINE explicit ScopedObjectAccessUnchecked(JNIEnv* env)
152 REQUIRES(!Locks::thread_suspend_count_lock_);
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700153
Mathieu Chartier0795f232016-09-27 18:43:30 -0700154 ALWAYS_INLINE explicit ScopedObjectAccessUnchecked(Thread* self)
155 REQUIRES(!Locks::thread_suspend_count_lock_);
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700156
157 // Used when we want a scoped JNI thread state but have no thread/JNIEnv. Consequently doesn't
158 // change into Runnable or acquire a share on the mutator_lock_.
159 explicit ScopedObjectAccessUnchecked(JavaVM* vm) ALWAYS_INLINE
160 : ScopedObjectAccessAlreadyRunnable(vm), tsc_() {}
161
162 private:
163 // The scoped thread state change makes sure that we are runnable and restores the thread state
164 // in the destructor.
165 const ScopedThreadStateChange tsc_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700166
167 DISALLOW_COPY_AND_ASSIGN(ScopedObjectAccessUnchecked);
168};
169
170// Annotalysis helping variant of the above.
171class ScopedObjectAccess : public ScopedObjectAccessUnchecked {
172 public:
Mathieu Chartier0795f232016-09-27 18:43:30 -0700173 ALWAYS_INLINE explicit ScopedObjectAccess(JNIEnv* env)
Mathieu Chartier90443472015-07-16 20:32:27 -0700174 REQUIRES(!Locks::thread_suspend_count_lock_)
Mathieu Chartier0795f232016-09-27 18:43:30 -0700175 SHARED_LOCK_FUNCTION(Locks::mutator_lock_)
176 : ScopedObjectAccessUnchecked(env) {}
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700177
Mathieu Chartier0795f232016-09-27 18:43:30 -0700178 ALWAYS_INLINE explicit ScopedObjectAccess(Thread* self)
Mathieu Chartier90443472015-07-16 20:32:27 -0700179 REQUIRES(!Locks::thread_suspend_count_lock_)
Mathieu Chartier0795f232016-09-27 18:43:30 -0700180 SHARED_LOCK_FUNCTION(Locks::mutator_lock_)
181 : ScopedObjectAccessUnchecked(self) {}
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700182
Mathieu Chartier0795f232016-09-27 18:43:30 -0700183 // Base class will release share of lock. Invoked after this destructor.
184 ~ScopedObjectAccess() UNLOCK_FUNCTION(Locks::mutator_lock_) ALWAYS_INLINE {}
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700185
186 private:
187 // TODO: remove this constructor. It is used by check JNI's ScopedCheck to make it believe that
188 // routines operating with just a VM are sound, they are not, but when you have just a VM
189 // you cannot call the unsound routines.
Mathieu Chartier0795f232016-09-27 18:43:30 -0700190 explicit ScopedObjectAccess(JavaVM* vm) SHARED_LOCK_FUNCTION(Locks::mutator_lock_)
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700191 : ScopedObjectAccessUnchecked(vm) {}
192
193 friend class ScopedCheck;
194 DISALLOW_COPY_AND_ASSIGN(ScopedObjectAccess);
195};
196
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700197// Annotalysis helper for going to a suspended state from runnable.
198class ScopedThreadSuspension : public ValueObject {
199 public:
Mathieu Chartier0795f232016-09-27 18:43:30 -0700200 ALWAYS_INLINE explicit ScopedThreadSuspension(Thread* self, ThreadState suspended_state)
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700201 REQUIRES(!Locks::thread_suspend_count_lock_, !Roles::uninterruptible_)
Mathieu Chartier0795f232016-09-27 18:43:30 -0700202 UNLOCK_FUNCTION(Locks::mutator_lock_);
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700203
Mathieu Chartier0795f232016-09-27 18:43:30 -0700204 ALWAYS_INLINE ~ScopedThreadSuspension() SHARED_LOCK_FUNCTION(Locks::mutator_lock_);
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700205
206 private:
207 Thread* const self_;
208 const ThreadState suspended_state_;
209 DISALLOW_COPY_AND_ASSIGN(ScopedThreadSuspension);
210};
211
212
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700213} // namespace art
214
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700215#endif // ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_H_