blob: b4992586ce355b6c6c396768231c16915a02813c [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 ALWAYS_INLINE bool IsRunnable() const;
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -070098
99 protected:
Mathieu Chartier0795f232016-09-27 18:43:30 -0700100 ALWAYS_INLINE explicit ScopedObjectAccessAlreadyRunnable(JNIEnv* env)
101 REQUIRES(!Locks::thread_suspend_count_lock_);
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700102
Mathieu Chartier0795f232016-09-27 18:43:30 -0700103 ALWAYS_INLINE explicit ScopedObjectAccessAlreadyRunnable(Thread* self)
104 REQUIRES(!Locks::thread_suspend_count_lock_);
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700105
106 // Used when we want a scoped JNI thread state but have no thread/JNIEnv. Consequently doesn't
107 // change into Runnable or acquire a share on the mutator_lock_.
108 explicit ScopedObjectAccessAlreadyRunnable(JavaVM* vm)
109 : self_(nullptr), env_(nullptr), vm_(down_cast<JavaVMExt*>(vm)) {}
110
111 // Here purely to force inlining.
Mathieu Chartier0795f232016-09-27 18:43:30 -0700112 ALWAYS_INLINE ~ScopedObjectAccessAlreadyRunnable() {}
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700113
114 // Self thread, can be null.
115 Thread* const self_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700116 // The full JNIEnv.
117 JNIEnvExt* const env_;
118 // The full JavaVM.
119 JavaVMExt* const vm_;
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700120};
121
122// Entry/exit processing for transitions from Native to Runnable (ie within JNI functions).
123//
124// This class performs the necessary thread state switching to and from Runnable and lets us
125// amortize the cost of working out the current thread. Additionally it lets us check (and repair)
126// apps that are using a JNIEnv on the wrong thread. The class also decodes and encodes Objects
127// into jobjects via methods of this class. Performing this here enforces the Runnable thread state
128// for use of Object, thereby inhibiting the Object being modified by GC whilst native or VM code
129// is also manipulating the Object.
130//
131// The destructor transitions back to the previous thread state, typically Native. In this state
132// GC and thread suspension may occur.
133//
134// For annotalysis the subclass ScopedObjectAccess (below) makes it explicit that a shared of
135// the mutator_lock_ will be acquired on construction.
136class ScopedObjectAccessUnchecked : public ScopedObjectAccessAlreadyRunnable {
137 public:
Mathieu Chartier0795f232016-09-27 18:43:30 -0700138 ALWAYS_INLINE explicit ScopedObjectAccessUnchecked(JNIEnv* env)
139 REQUIRES(!Locks::thread_suspend_count_lock_);
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700140
Mathieu Chartier0795f232016-09-27 18:43:30 -0700141 ALWAYS_INLINE explicit ScopedObjectAccessUnchecked(Thread* self)
142 REQUIRES(!Locks::thread_suspend_count_lock_);
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700143
144 // Used when we want a scoped JNI thread state but have no thread/JNIEnv. Consequently doesn't
145 // change into Runnable or acquire a share on the mutator_lock_.
146 explicit ScopedObjectAccessUnchecked(JavaVM* vm) ALWAYS_INLINE
147 : ScopedObjectAccessAlreadyRunnable(vm), tsc_() {}
148
149 private:
150 // The scoped thread state change makes sure that we are runnable and restores the thread state
151 // in the destructor.
152 const ScopedThreadStateChange tsc_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700153
154 DISALLOW_COPY_AND_ASSIGN(ScopedObjectAccessUnchecked);
155};
156
157// Annotalysis helping variant of the above.
158class ScopedObjectAccess : public ScopedObjectAccessUnchecked {
159 public:
Mathieu Chartier0795f232016-09-27 18:43:30 -0700160 ALWAYS_INLINE explicit ScopedObjectAccess(JNIEnv* env)
Mathieu Chartier90443472015-07-16 20:32:27 -0700161 REQUIRES(!Locks::thread_suspend_count_lock_)
Mathieu Chartier0795f232016-09-27 18:43:30 -0700162 SHARED_LOCK_FUNCTION(Locks::mutator_lock_)
163 : ScopedObjectAccessUnchecked(env) {}
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700164
Mathieu Chartier0795f232016-09-27 18:43:30 -0700165 ALWAYS_INLINE explicit ScopedObjectAccess(Thread* self)
Mathieu Chartier90443472015-07-16 20:32:27 -0700166 REQUIRES(!Locks::thread_suspend_count_lock_)
Mathieu Chartier0795f232016-09-27 18:43:30 -0700167 SHARED_LOCK_FUNCTION(Locks::mutator_lock_)
168 : ScopedObjectAccessUnchecked(self) {}
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700169
Mathieu Chartier0795f232016-09-27 18:43:30 -0700170 // Base class will release share of lock. Invoked after this destructor.
171 ~ScopedObjectAccess() UNLOCK_FUNCTION(Locks::mutator_lock_) ALWAYS_INLINE {}
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700172
173 private:
174 // TODO: remove this constructor. It is used by check JNI's ScopedCheck to make it believe that
175 // routines operating with just a VM are sound, they are not, but when you have just a VM
176 // you cannot call the unsound routines.
Mathieu Chartier0795f232016-09-27 18:43:30 -0700177 explicit ScopedObjectAccess(JavaVM* vm) SHARED_LOCK_FUNCTION(Locks::mutator_lock_)
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700178 : ScopedObjectAccessUnchecked(vm) {}
179
180 friend class ScopedCheck;
181 DISALLOW_COPY_AND_ASSIGN(ScopedObjectAccess);
182};
183
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700184// Annotalysis helper for going to a suspended state from runnable.
185class ScopedThreadSuspension : public ValueObject {
186 public:
Mathieu Chartier0795f232016-09-27 18:43:30 -0700187 ALWAYS_INLINE explicit ScopedThreadSuspension(Thread* self, ThreadState suspended_state)
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700188 REQUIRES(!Locks::thread_suspend_count_lock_, !Roles::uninterruptible_)
Mathieu Chartier0795f232016-09-27 18:43:30 -0700189 UNLOCK_FUNCTION(Locks::mutator_lock_);
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700190
Mathieu Chartier0795f232016-09-27 18:43:30 -0700191 ALWAYS_INLINE ~ScopedThreadSuspension() SHARED_LOCK_FUNCTION(Locks::mutator_lock_);
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700192
193 private:
194 Thread* const self_;
195 const ThreadState suspended_state_;
196 DISALLOW_COPY_AND_ASSIGN(ScopedThreadSuspension);
197};
198
199
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700200} // namespace art
201
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700202#endif // ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_H_