blob: 04fd9141ea70a77ff98478308c6b8d1fbc88674b [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 */
90 template<typename T>
Mathieu Chartier8778c522016-10-04 19:06:30 -070091 T AddLocalReference(ObjPtr<mirror::Object> obj) const
Mathieu Chartier0795f232016-09-27 18:43:30 -070092 REQUIRES_SHARED(Locks::mutator_lock_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -070093
Mathieu Chartier0795f232016-09-27 18:43:30 -070094 template<typename T, bool kPoison = kIsDebugBuild>
95 ObjPtr<T, kPoison> Decode(jobject obj) const REQUIRES_SHARED(Locks::mutator_lock_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -070096
Mathieu Chartier0795f232016-09-27 18:43:30 -070097 ArtField* DecodeField(jfieldID fid) const REQUIRES_SHARED(Locks::mutator_lock_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -070098
Mathieu Chartier0795f232016-09-27 18:43:30 -070099 jfieldID EncodeField(ArtField* field) const REQUIRES_SHARED(Locks::mutator_lock_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700100
Mathieu Chartier0795f232016-09-27 18:43:30 -0700101 ArtMethod* DecodeMethod(jmethodID mid) const REQUIRES_SHARED(Locks::mutator_lock_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700102
Mathieu Chartier0795f232016-09-27 18:43:30 -0700103 jmethodID EncodeMethod(ArtMethod* method) const REQUIRES_SHARED(Locks::mutator_lock_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700104
Mathieu Chartier0795f232016-09-27 18:43:30 -0700105 ALWAYS_INLINE bool IsRunnable() const;
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700106
107 protected:
Mathieu Chartier0795f232016-09-27 18:43:30 -0700108 ALWAYS_INLINE explicit ScopedObjectAccessAlreadyRunnable(JNIEnv* env)
109 REQUIRES(!Locks::thread_suspend_count_lock_);
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700110
Mathieu Chartier0795f232016-09-27 18:43:30 -0700111 ALWAYS_INLINE explicit ScopedObjectAccessAlreadyRunnable(Thread* self)
112 REQUIRES(!Locks::thread_suspend_count_lock_);
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700113
114 // Used when we want a scoped JNI thread state but have no thread/JNIEnv. Consequently doesn't
115 // change into Runnable or acquire a share on the mutator_lock_.
116 explicit ScopedObjectAccessAlreadyRunnable(JavaVM* vm)
117 : self_(nullptr), env_(nullptr), vm_(down_cast<JavaVMExt*>(vm)) {}
118
119 // Here purely to force inlining.
Mathieu Chartier0795f232016-09-27 18:43:30 -0700120 ALWAYS_INLINE ~ScopedObjectAccessAlreadyRunnable() {}
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700121
122 // Self thread, can be null.
123 Thread* const self_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700124 // The full JNIEnv.
125 JNIEnvExt* const env_;
126 // The full JavaVM.
127 JavaVMExt* const vm_;
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700128};
129
130// Entry/exit processing for transitions from Native to Runnable (ie within JNI functions).
131//
132// This class performs the necessary thread state switching to and from Runnable and lets us
133// amortize the cost of working out the current thread. Additionally it lets us check (and repair)
134// apps that are using a JNIEnv on the wrong thread. The class also decodes and encodes Objects
135// into jobjects via methods of this class. Performing this here enforces the Runnable thread state
136// for use of Object, thereby inhibiting the Object being modified by GC whilst native or VM code
137// is also manipulating the Object.
138//
139// The destructor transitions back to the previous thread state, typically Native. In this state
140// GC and thread suspension may occur.
141//
142// For annotalysis the subclass ScopedObjectAccess (below) makes it explicit that a shared of
143// the mutator_lock_ will be acquired on construction.
144class ScopedObjectAccessUnchecked : public ScopedObjectAccessAlreadyRunnable {
145 public:
Mathieu Chartier0795f232016-09-27 18:43:30 -0700146 ALWAYS_INLINE explicit ScopedObjectAccessUnchecked(JNIEnv* env)
147 REQUIRES(!Locks::thread_suspend_count_lock_);
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700148
Mathieu Chartier0795f232016-09-27 18:43:30 -0700149 ALWAYS_INLINE explicit ScopedObjectAccessUnchecked(Thread* self)
150 REQUIRES(!Locks::thread_suspend_count_lock_);
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700151
152 // Used when we want a scoped JNI thread state but have no thread/JNIEnv. Consequently doesn't
153 // change into Runnable or acquire a share on the mutator_lock_.
154 explicit ScopedObjectAccessUnchecked(JavaVM* vm) ALWAYS_INLINE
155 : ScopedObjectAccessAlreadyRunnable(vm), tsc_() {}
156
157 private:
158 // The scoped thread state change makes sure that we are runnable and restores the thread state
159 // in the destructor.
160 const ScopedThreadStateChange tsc_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700161
162 DISALLOW_COPY_AND_ASSIGN(ScopedObjectAccessUnchecked);
163};
164
165// Annotalysis helping variant of the above.
166class ScopedObjectAccess : public ScopedObjectAccessUnchecked {
167 public:
Mathieu Chartier0795f232016-09-27 18:43:30 -0700168 ALWAYS_INLINE explicit ScopedObjectAccess(JNIEnv* env)
Mathieu Chartier90443472015-07-16 20:32:27 -0700169 REQUIRES(!Locks::thread_suspend_count_lock_)
Mathieu Chartier0795f232016-09-27 18:43:30 -0700170 SHARED_LOCK_FUNCTION(Locks::mutator_lock_)
171 : ScopedObjectAccessUnchecked(env) {}
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700172
Mathieu Chartier0795f232016-09-27 18:43:30 -0700173 ALWAYS_INLINE explicit ScopedObjectAccess(Thread* self)
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(self) {}
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700177
Mathieu Chartier0795f232016-09-27 18:43:30 -0700178 // Base class will release share of lock. Invoked after this destructor.
179 ~ScopedObjectAccess() UNLOCK_FUNCTION(Locks::mutator_lock_) ALWAYS_INLINE {}
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700180
181 private:
182 // TODO: remove this constructor. It is used by check JNI's ScopedCheck to make it believe that
183 // routines operating with just a VM are sound, they are not, but when you have just a VM
184 // you cannot call the unsound routines.
Mathieu Chartier0795f232016-09-27 18:43:30 -0700185 explicit ScopedObjectAccess(JavaVM* vm) SHARED_LOCK_FUNCTION(Locks::mutator_lock_)
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700186 : ScopedObjectAccessUnchecked(vm) {}
187
188 friend class ScopedCheck;
189 DISALLOW_COPY_AND_ASSIGN(ScopedObjectAccess);
190};
191
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700192// Annotalysis helper for going to a suspended state from runnable.
193class ScopedThreadSuspension : public ValueObject {
194 public:
Mathieu Chartier0795f232016-09-27 18:43:30 -0700195 ALWAYS_INLINE explicit ScopedThreadSuspension(Thread* self, ThreadState suspended_state)
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700196 REQUIRES(!Locks::thread_suspend_count_lock_, !Roles::uninterruptible_)
Mathieu Chartier0795f232016-09-27 18:43:30 -0700197 UNLOCK_FUNCTION(Locks::mutator_lock_);
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700198
Mathieu Chartier0795f232016-09-27 18:43:30 -0700199 ALWAYS_INLINE ~ScopedThreadSuspension() SHARED_LOCK_FUNCTION(Locks::mutator_lock_);
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700200
201 private:
202 Thread* const self_;
203 const ThreadState suspended_state_;
204 DISALLOW_COPY_AND_ASSIGN(ScopedThreadSuspension);
205};
206
207
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700208} // namespace art
209
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700210#endif // ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_H_