1*795d594fSAndroid Build Coastguard Worker /* Copyright (C) 2016 The Android Open Source Project
2*795d594fSAndroid Build Coastguard Worker * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3*795d594fSAndroid Build Coastguard Worker *
4*795d594fSAndroid Build Coastguard Worker * This file implements interfaces from the file jvmti.h. This implementation
5*795d594fSAndroid Build Coastguard Worker * is licensed under the same terms as the file jvmti.h. The
6*795d594fSAndroid Build Coastguard Worker * copyright and license information for the file jvmti.h follows.
7*795d594fSAndroid Build Coastguard Worker *
8*795d594fSAndroid Build Coastguard Worker * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
9*795d594fSAndroid Build Coastguard Worker * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
10*795d594fSAndroid Build Coastguard Worker *
11*795d594fSAndroid Build Coastguard Worker * This code is free software; you can redistribute it and/or modify it
12*795d594fSAndroid Build Coastguard Worker * under the terms of the GNU General Public License version 2 only, as
13*795d594fSAndroid Build Coastguard Worker * published by the Free Software Foundation. Oracle designates this
14*795d594fSAndroid Build Coastguard Worker * particular file as subject to the "Classpath" exception as provided
15*795d594fSAndroid Build Coastguard Worker * by Oracle in the LICENSE file that accompanied this code.
16*795d594fSAndroid Build Coastguard Worker *
17*795d594fSAndroid Build Coastguard Worker * This code is distributed in the hope that it will be useful, but WITHOUT
18*795d594fSAndroid Build Coastguard Worker * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19*795d594fSAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20*795d594fSAndroid Build Coastguard Worker * version 2 for more details (a copy is included in the LICENSE file that
21*795d594fSAndroid Build Coastguard Worker * accompanied this code).
22*795d594fSAndroid Build Coastguard Worker *
23*795d594fSAndroid Build Coastguard Worker * You should have received a copy of the GNU General Public License version
24*795d594fSAndroid Build Coastguard Worker * 2 along with this work; if not, write to the Free Software Foundation,
25*795d594fSAndroid Build Coastguard Worker * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
26*795d594fSAndroid Build Coastguard Worker *
27*795d594fSAndroid Build Coastguard Worker * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
28*795d594fSAndroid Build Coastguard Worker * or visit www.oracle.com if you need additional information or have any
29*795d594fSAndroid Build Coastguard Worker * questions.
30*795d594fSAndroid Build Coastguard Worker */
31*795d594fSAndroid Build Coastguard Worker
32*795d594fSAndroid Build Coastguard Worker #include "ti_field.h"
33*795d594fSAndroid Build Coastguard Worker #include <unordered_map>
34*795d594fSAndroid Build Coastguard Worker
35*795d594fSAndroid Build Coastguard Worker #include "android-base/thread_annotations.h"
36*795d594fSAndroid Build Coastguard Worker #include "art_field-inl.h"
37*795d594fSAndroid Build Coastguard Worker #include "art_field.h"
38*795d594fSAndroid Build Coastguard Worker #include "art_jvmti.h"
39*795d594fSAndroid Build Coastguard Worker #include "base/pointer_size.h"
40*795d594fSAndroid Build Coastguard Worker #include "base/locks.h"
41*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file_annotations.h"
42*795d594fSAndroid Build Coastguard Worker #include "dex/modifiers.h"
43*795d594fSAndroid Build Coastguard Worker #include "jni/jni_internal.h"
44*795d594fSAndroid Build Coastguard Worker #include "mirror/object_array-inl.h"
45*795d594fSAndroid Build Coastguard Worker #include "reflective_value_visitor.h"
46*795d594fSAndroid Build Coastguard Worker #include "runtime.h"
47*795d594fSAndroid Build Coastguard Worker #include "runtime_callbacks.h"
48*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change-inl.h"
49*795d594fSAndroid Build Coastguard Worker #include "thread-current-inl.h"
50*795d594fSAndroid Build Coastguard Worker
51*795d594fSAndroid Build Coastguard Worker namespace openjdkjvmti {
52*795d594fSAndroid Build Coastguard Worker
53*795d594fSAndroid Build Coastguard Worker class JvmtiFieldReflectionSource : public art::ReflectionSourceInfo {
54*795d594fSAndroid Build Coastguard Worker public:
JvmtiFieldReflectionSource(bool is_access,art::ArtField * f)55*795d594fSAndroid Build Coastguard Worker JvmtiFieldReflectionSource(bool is_access, art::ArtField* f)
56*795d594fSAndroid Build Coastguard Worker : art::ReflectionSourceInfo(art::ReflectionSourceType::kSourceMiscInternal),
57*795d594fSAndroid Build Coastguard Worker is_access_(is_access),
58*795d594fSAndroid Build Coastguard Worker f_(f) {}
Describe(std::ostream & os) const59*795d594fSAndroid Build Coastguard Worker void Describe(std::ostream& os) const override REQUIRES_SHARED(art::Locks::mutator_lock_) {
60*795d594fSAndroid Build Coastguard Worker art::ReflectionSourceInfo::Describe(os);
61*795d594fSAndroid Build Coastguard Worker os << " jvmti Field" << (is_access_ ? "Access" : "Modification")
62*795d594fSAndroid Build Coastguard Worker << "Watch Target=" << f_->PrettyField();
63*795d594fSAndroid Build Coastguard Worker }
64*795d594fSAndroid Build Coastguard Worker
65*795d594fSAndroid Build Coastguard Worker private:
66*795d594fSAndroid Build Coastguard Worker bool is_access_;
67*795d594fSAndroid Build Coastguard Worker art::ArtField* f_;
68*795d594fSAndroid Build Coastguard Worker };
69*795d594fSAndroid Build Coastguard Worker struct FieldReflectiveValueCallback : public art::ReflectiveValueVisitCallback {
70*795d594fSAndroid Build Coastguard Worker public:
VisitReflectiveTargetsopenjdkjvmti::FieldReflectiveValueCallback71*795d594fSAndroid Build Coastguard Worker void VisitReflectiveTargets(art::ReflectiveValueVisitor* visitor)
72*795d594fSAndroid Build Coastguard Worker REQUIRES(art::Locks::mutator_lock_) {
73*795d594fSAndroid Build Coastguard Worker art::Thread* self = art::Thread::Current();
74*795d594fSAndroid Build Coastguard Worker event_handler->ForEachEnv(self, [&](ArtJvmTiEnv* env) NO_THREAD_SAFETY_ANALYSIS {
75*795d594fSAndroid Build Coastguard Worker art::Locks::mutator_lock_->AssertExclusiveHeld(self);
76*795d594fSAndroid Build Coastguard Worker art::WriterMutexLock mu(self, env->event_info_mutex_);
77*795d594fSAndroid Build Coastguard Worker std::vector<std::pair<art::ArtField*, art::ArtField*>> updated_access_fields;
78*795d594fSAndroid Build Coastguard Worker for (auto it : env->access_watched_fields) {
79*795d594fSAndroid Build Coastguard Worker art::ArtField* af =
80*795d594fSAndroid Build Coastguard Worker visitor->VisitField(it, JvmtiFieldReflectionSource(/*is_access=*/true, it));
81*795d594fSAndroid Build Coastguard Worker if (af != it) {
82*795d594fSAndroid Build Coastguard Worker updated_access_fields.push_back({ af, it });
83*795d594fSAndroid Build Coastguard Worker }
84*795d594fSAndroid Build Coastguard Worker }
85*795d594fSAndroid Build Coastguard Worker for (auto it : updated_access_fields) {
86*795d594fSAndroid Build Coastguard Worker DCHECK(env->access_watched_fields.find(it.second) != env->access_watched_fields.end());
87*795d594fSAndroid Build Coastguard Worker env->access_watched_fields.erase(it.second);
88*795d594fSAndroid Build Coastguard Worker env->access_watched_fields.insert(it.first);
89*795d594fSAndroid Build Coastguard Worker }
90*795d594fSAndroid Build Coastguard Worker std::vector<std::pair<art::ArtField*, art::ArtField*>> updated_modify_fields;
91*795d594fSAndroid Build Coastguard Worker for (auto it : env->modify_watched_fields) {
92*795d594fSAndroid Build Coastguard Worker art::ArtField* af =
93*795d594fSAndroid Build Coastguard Worker visitor->VisitField(it, JvmtiFieldReflectionSource(/*is_access=*/false, it));
94*795d594fSAndroid Build Coastguard Worker if (af != it) {
95*795d594fSAndroid Build Coastguard Worker updated_modify_fields.push_back({ af, it });
96*795d594fSAndroid Build Coastguard Worker }
97*795d594fSAndroid Build Coastguard Worker }
98*795d594fSAndroid Build Coastguard Worker for (auto it : updated_modify_fields) {
99*795d594fSAndroid Build Coastguard Worker DCHECK(env->modify_watched_fields.find(it.second) != env->modify_watched_fields.end());
100*795d594fSAndroid Build Coastguard Worker env->modify_watched_fields.erase(it.second);
101*795d594fSAndroid Build Coastguard Worker env->modify_watched_fields.insert(it.first);
102*795d594fSAndroid Build Coastguard Worker }
103*795d594fSAndroid Build Coastguard Worker });
104*795d594fSAndroid Build Coastguard Worker }
105*795d594fSAndroid Build Coastguard Worker
106*795d594fSAndroid Build Coastguard Worker EventHandler* event_handler = nullptr;
107*795d594fSAndroid Build Coastguard Worker };
108*795d594fSAndroid Build Coastguard Worker
109*795d594fSAndroid Build Coastguard Worker static FieldReflectiveValueCallback gReflectiveValueCallback;
110*795d594fSAndroid Build Coastguard Worker
Register(EventHandler * eh)111*795d594fSAndroid Build Coastguard Worker void FieldUtil::Register(EventHandler* eh) {
112*795d594fSAndroid Build Coastguard Worker gReflectiveValueCallback.event_handler = eh;
113*795d594fSAndroid Build Coastguard Worker art::ScopedThreadStateChange stsc(art::Thread::Current(),
114*795d594fSAndroid Build Coastguard Worker art::ThreadState::kWaitingForDebuggerToAttach);
115*795d594fSAndroid Build Coastguard Worker art::ScopedSuspendAll ssa("Add reflective value visit callback");
116*795d594fSAndroid Build Coastguard Worker art::RuntimeCallbacks* callbacks = art::Runtime::Current()->GetRuntimeCallbacks();
117*795d594fSAndroid Build Coastguard Worker callbacks->AddReflectiveValueVisitCallback(&gReflectiveValueCallback);
118*795d594fSAndroid Build Coastguard Worker }
119*795d594fSAndroid Build Coastguard Worker
Unregister()120*795d594fSAndroid Build Coastguard Worker void FieldUtil::Unregister() {
121*795d594fSAndroid Build Coastguard Worker art::ScopedThreadStateChange stsc(art::Thread::Current(),
122*795d594fSAndroid Build Coastguard Worker art::ThreadState::kWaitingForDebuggerToAttach);
123*795d594fSAndroid Build Coastguard Worker art::ScopedSuspendAll ssa("Remove reflective value visit callback");
124*795d594fSAndroid Build Coastguard Worker art::RuntimeCallbacks* callbacks = art::Runtime::Current()->GetRuntimeCallbacks();
125*795d594fSAndroid Build Coastguard Worker callbacks->RemoveReflectiveValueVisitCallback(&gReflectiveValueCallback);
126*795d594fSAndroid Build Coastguard Worker }
127*795d594fSAndroid Build Coastguard Worker // Note: For all these functions, we could do a check that the field actually belongs to the given
128*795d594fSAndroid Build Coastguard Worker // class. But the spec seems to assume a certain encoding of the field ID, and so doesn't
129*795d594fSAndroid Build Coastguard Worker // specify any errors.
130*795d594fSAndroid Build Coastguard Worker
GetFieldName(jvmtiEnv * env,jclass klass,jfieldID field,char ** name_ptr,char ** signature_ptr,char ** generic_ptr)131*795d594fSAndroid Build Coastguard Worker jvmtiError FieldUtil::GetFieldName(jvmtiEnv* env,
132*795d594fSAndroid Build Coastguard Worker jclass klass,
133*795d594fSAndroid Build Coastguard Worker jfieldID field,
134*795d594fSAndroid Build Coastguard Worker char** name_ptr,
135*795d594fSAndroid Build Coastguard Worker char** signature_ptr,
136*795d594fSAndroid Build Coastguard Worker char** generic_ptr) {
137*795d594fSAndroid Build Coastguard Worker if (klass == nullptr) {
138*795d594fSAndroid Build Coastguard Worker return ERR(INVALID_CLASS);
139*795d594fSAndroid Build Coastguard Worker }
140*795d594fSAndroid Build Coastguard Worker if (field == nullptr) {
141*795d594fSAndroid Build Coastguard Worker return ERR(INVALID_FIELDID);
142*795d594fSAndroid Build Coastguard Worker }
143*795d594fSAndroid Build Coastguard Worker
144*795d594fSAndroid Build Coastguard Worker art::ScopedObjectAccess soa(art::Thread::Current());
145*795d594fSAndroid Build Coastguard Worker art::ArtField* art_field = art::jni::DecodeArtField(field);
146*795d594fSAndroid Build Coastguard Worker
147*795d594fSAndroid Build Coastguard Worker JvmtiUniquePtr<char[]> name_copy;
148*795d594fSAndroid Build Coastguard Worker if (name_ptr != nullptr) {
149*795d594fSAndroid Build Coastguard Worker const char* field_name = art_field->GetName();
150*795d594fSAndroid Build Coastguard Worker if (field_name == nullptr) {
151*795d594fSAndroid Build Coastguard Worker field_name = "<error>";
152*795d594fSAndroid Build Coastguard Worker }
153*795d594fSAndroid Build Coastguard Worker jvmtiError ret;
154*795d594fSAndroid Build Coastguard Worker name_copy = CopyString(env, field_name, &ret);
155*795d594fSAndroid Build Coastguard Worker if (name_copy == nullptr) {
156*795d594fSAndroid Build Coastguard Worker return ret;
157*795d594fSAndroid Build Coastguard Worker }
158*795d594fSAndroid Build Coastguard Worker *name_ptr = name_copy.get();
159*795d594fSAndroid Build Coastguard Worker }
160*795d594fSAndroid Build Coastguard Worker
161*795d594fSAndroid Build Coastguard Worker JvmtiUniquePtr<char[]> signature_copy;
162*795d594fSAndroid Build Coastguard Worker if (signature_ptr != nullptr) {
163*795d594fSAndroid Build Coastguard Worker const char* sig = art_field->GetTypeDescriptor();
164*795d594fSAndroid Build Coastguard Worker jvmtiError ret;
165*795d594fSAndroid Build Coastguard Worker signature_copy = CopyString(env, sig, &ret);
166*795d594fSAndroid Build Coastguard Worker if (signature_copy == nullptr) {
167*795d594fSAndroid Build Coastguard Worker return ret;
168*795d594fSAndroid Build Coastguard Worker }
169*795d594fSAndroid Build Coastguard Worker *signature_ptr = signature_copy.get();
170*795d594fSAndroid Build Coastguard Worker }
171*795d594fSAndroid Build Coastguard Worker
172*795d594fSAndroid Build Coastguard Worker if (generic_ptr != nullptr) {
173*795d594fSAndroid Build Coastguard Worker *generic_ptr = nullptr;
174*795d594fSAndroid Build Coastguard Worker if (!art_field->GetDeclaringClass()->IsProxyClass()) {
175*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::ObjectArray<art::mirror::String>> str_array =
176*795d594fSAndroid Build Coastguard Worker art::annotations::GetSignatureAnnotationForField(art_field);
177*795d594fSAndroid Build Coastguard Worker if (str_array != nullptr) {
178*795d594fSAndroid Build Coastguard Worker std::ostringstream oss;
179*795d594fSAndroid Build Coastguard Worker for (auto str : str_array->Iterate()) {
180*795d594fSAndroid Build Coastguard Worker oss << str->ToModifiedUtf8();
181*795d594fSAndroid Build Coastguard Worker }
182*795d594fSAndroid Build Coastguard Worker std::string output_string = oss.str();
183*795d594fSAndroid Build Coastguard Worker jvmtiError ret;
184*795d594fSAndroid Build Coastguard Worker JvmtiUniquePtr<char[]> copy = CopyString(env, output_string.c_str(), &ret);
185*795d594fSAndroid Build Coastguard Worker if (copy == nullptr) {
186*795d594fSAndroid Build Coastguard Worker return ret;
187*795d594fSAndroid Build Coastguard Worker }
188*795d594fSAndroid Build Coastguard Worker *generic_ptr = copy.release();
189*795d594fSAndroid Build Coastguard Worker } else if (soa.Self()->IsExceptionPending()) {
190*795d594fSAndroid Build Coastguard Worker // TODO: Should we report an error here?
191*795d594fSAndroid Build Coastguard Worker soa.Self()->ClearException();
192*795d594fSAndroid Build Coastguard Worker }
193*795d594fSAndroid Build Coastguard Worker }
194*795d594fSAndroid Build Coastguard Worker }
195*795d594fSAndroid Build Coastguard Worker
196*795d594fSAndroid Build Coastguard Worker // Everything is fine, release the buffers.
197*795d594fSAndroid Build Coastguard Worker name_copy.release();
198*795d594fSAndroid Build Coastguard Worker signature_copy.release();
199*795d594fSAndroid Build Coastguard Worker
200*795d594fSAndroid Build Coastguard Worker return ERR(NONE);
201*795d594fSAndroid Build Coastguard Worker }
202*795d594fSAndroid Build Coastguard Worker
GetFieldDeclaringClass(jvmtiEnv * env,jclass klass,jfieldID field,jclass * declaring_class_ptr)203*795d594fSAndroid Build Coastguard Worker jvmtiError FieldUtil::GetFieldDeclaringClass([[maybe_unused]] jvmtiEnv* env,
204*795d594fSAndroid Build Coastguard Worker jclass klass,
205*795d594fSAndroid Build Coastguard Worker jfieldID field,
206*795d594fSAndroid Build Coastguard Worker jclass* declaring_class_ptr) {
207*795d594fSAndroid Build Coastguard Worker if (klass == nullptr) {
208*795d594fSAndroid Build Coastguard Worker return ERR(INVALID_CLASS);
209*795d594fSAndroid Build Coastguard Worker }
210*795d594fSAndroid Build Coastguard Worker if (field == nullptr) {
211*795d594fSAndroid Build Coastguard Worker return ERR(INVALID_FIELDID);
212*795d594fSAndroid Build Coastguard Worker }
213*795d594fSAndroid Build Coastguard Worker if (declaring_class_ptr == nullptr) {
214*795d594fSAndroid Build Coastguard Worker return ERR(NULL_POINTER);
215*795d594fSAndroid Build Coastguard Worker }
216*795d594fSAndroid Build Coastguard Worker
217*795d594fSAndroid Build Coastguard Worker art::ScopedObjectAccess soa(art::Thread::Current());
218*795d594fSAndroid Build Coastguard Worker art::ArtField* art_field = art::jni::DecodeArtField(field);
219*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Class> field_klass = art_field->GetDeclaringClass();
220*795d594fSAndroid Build Coastguard Worker
221*795d594fSAndroid Build Coastguard Worker *declaring_class_ptr = soa.AddLocalReference<jclass>(field_klass);
222*795d594fSAndroid Build Coastguard Worker
223*795d594fSAndroid Build Coastguard Worker return ERR(NONE);
224*795d594fSAndroid Build Coastguard Worker }
225*795d594fSAndroid Build Coastguard Worker
GetFieldModifiers(jvmtiEnv * env,jclass klass,jfieldID field,jint * modifiers_ptr)226*795d594fSAndroid Build Coastguard Worker jvmtiError FieldUtil::GetFieldModifiers([[maybe_unused]] jvmtiEnv* env,
227*795d594fSAndroid Build Coastguard Worker jclass klass,
228*795d594fSAndroid Build Coastguard Worker jfieldID field,
229*795d594fSAndroid Build Coastguard Worker jint* modifiers_ptr) {
230*795d594fSAndroid Build Coastguard Worker if (klass == nullptr) {
231*795d594fSAndroid Build Coastguard Worker return ERR(INVALID_CLASS);
232*795d594fSAndroid Build Coastguard Worker }
233*795d594fSAndroid Build Coastguard Worker if (field == nullptr) {
234*795d594fSAndroid Build Coastguard Worker return ERR(INVALID_FIELDID);
235*795d594fSAndroid Build Coastguard Worker }
236*795d594fSAndroid Build Coastguard Worker if (modifiers_ptr == nullptr) {
237*795d594fSAndroid Build Coastguard Worker return ERR(NULL_POINTER);
238*795d594fSAndroid Build Coastguard Worker }
239*795d594fSAndroid Build Coastguard Worker
240*795d594fSAndroid Build Coastguard Worker art::ScopedObjectAccess soa(art::Thread::Current());
241*795d594fSAndroid Build Coastguard Worker art::ArtField* art_field = art::jni::DecodeArtField(field);
242*795d594fSAndroid Build Coastguard Worker // Note: Keep this code in sync with Field.getModifiers.
243*795d594fSAndroid Build Coastguard Worker uint32_t modifiers = art_field->GetAccessFlags() & 0xFFFF;
244*795d594fSAndroid Build Coastguard Worker
245*795d594fSAndroid Build Coastguard Worker *modifiers_ptr = modifiers;
246*795d594fSAndroid Build Coastguard Worker return ERR(NONE);
247*795d594fSAndroid Build Coastguard Worker }
248*795d594fSAndroid Build Coastguard Worker
IsFieldSynthetic(jvmtiEnv * env,jclass klass,jfieldID field,jboolean * is_synthetic_ptr)249*795d594fSAndroid Build Coastguard Worker jvmtiError FieldUtil::IsFieldSynthetic([[maybe_unused]] jvmtiEnv* env,
250*795d594fSAndroid Build Coastguard Worker jclass klass,
251*795d594fSAndroid Build Coastguard Worker jfieldID field,
252*795d594fSAndroid Build Coastguard Worker jboolean* is_synthetic_ptr) {
253*795d594fSAndroid Build Coastguard Worker if (klass == nullptr) {
254*795d594fSAndroid Build Coastguard Worker return ERR(INVALID_CLASS);
255*795d594fSAndroid Build Coastguard Worker }
256*795d594fSAndroid Build Coastguard Worker if (field == nullptr) {
257*795d594fSAndroid Build Coastguard Worker return ERR(INVALID_FIELDID);
258*795d594fSAndroid Build Coastguard Worker }
259*795d594fSAndroid Build Coastguard Worker if (is_synthetic_ptr == nullptr) {
260*795d594fSAndroid Build Coastguard Worker return ERR(NULL_POINTER);
261*795d594fSAndroid Build Coastguard Worker }
262*795d594fSAndroid Build Coastguard Worker
263*795d594fSAndroid Build Coastguard Worker art::ScopedObjectAccess soa(art::Thread::Current());
264*795d594fSAndroid Build Coastguard Worker art::ArtField* art_field = art::jni::DecodeArtField(field);
265*795d594fSAndroid Build Coastguard Worker uint32_t modifiers = art_field->GetAccessFlags();
266*795d594fSAndroid Build Coastguard Worker
267*795d594fSAndroid Build Coastguard Worker *is_synthetic_ptr = ((modifiers & art::kAccSynthetic) != 0) ? JNI_TRUE : JNI_FALSE;
268*795d594fSAndroid Build Coastguard Worker return ERR(NONE);
269*795d594fSAndroid Build Coastguard Worker }
270*795d594fSAndroid Build Coastguard Worker
SetFieldModificationWatch(jvmtiEnv * jenv,jclass klass,jfieldID field)271*795d594fSAndroid Build Coastguard Worker jvmtiError FieldUtil::SetFieldModificationWatch(jvmtiEnv* jenv, jclass klass, jfieldID field) {
272*795d594fSAndroid Build Coastguard Worker ArtJvmTiEnv* env = ArtJvmTiEnv::AsArtJvmTiEnv(jenv);
273*795d594fSAndroid Build Coastguard Worker art::WriterMutexLock lk(art::Thread::Current(), env->event_info_mutex_);
274*795d594fSAndroid Build Coastguard Worker if (klass == nullptr) {
275*795d594fSAndroid Build Coastguard Worker return ERR(INVALID_CLASS);
276*795d594fSAndroid Build Coastguard Worker }
277*795d594fSAndroid Build Coastguard Worker if (field == nullptr) {
278*795d594fSAndroid Build Coastguard Worker return ERR(INVALID_FIELDID);
279*795d594fSAndroid Build Coastguard Worker }
280*795d594fSAndroid Build Coastguard Worker auto res_pair = env->modify_watched_fields.insert(art::jni::DecodeArtField(field));
281*795d594fSAndroid Build Coastguard Worker if (!res_pair.second) {
282*795d594fSAndroid Build Coastguard Worker // Didn't get inserted because it's already present!
283*795d594fSAndroid Build Coastguard Worker return ERR(DUPLICATE);
284*795d594fSAndroid Build Coastguard Worker }
285*795d594fSAndroid Build Coastguard Worker return OK;
286*795d594fSAndroid Build Coastguard Worker }
287*795d594fSAndroid Build Coastguard Worker
ClearFieldModificationWatch(jvmtiEnv * jenv,jclass klass,jfieldID field)288*795d594fSAndroid Build Coastguard Worker jvmtiError FieldUtil::ClearFieldModificationWatch(jvmtiEnv* jenv, jclass klass, jfieldID field) {
289*795d594fSAndroid Build Coastguard Worker ArtJvmTiEnv* env = ArtJvmTiEnv::AsArtJvmTiEnv(jenv);
290*795d594fSAndroid Build Coastguard Worker art::WriterMutexLock lk(art::Thread::Current(), env->event_info_mutex_);
291*795d594fSAndroid Build Coastguard Worker if (klass == nullptr) {
292*795d594fSAndroid Build Coastguard Worker return ERR(INVALID_CLASS);
293*795d594fSAndroid Build Coastguard Worker }
294*795d594fSAndroid Build Coastguard Worker if (field == nullptr) {
295*795d594fSAndroid Build Coastguard Worker return ERR(INVALID_FIELDID);
296*795d594fSAndroid Build Coastguard Worker }
297*795d594fSAndroid Build Coastguard Worker auto pos = env->modify_watched_fields.find(art::jni::DecodeArtField(field));
298*795d594fSAndroid Build Coastguard Worker if (pos == env->modify_watched_fields.end()) {
299*795d594fSAndroid Build Coastguard Worker return ERR(NOT_FOUND);
300*795d594fSAndroid Build Coastguard Worker }
301*795d594fSAndroid Build Coastguard Worker env->modify_watched_fields.erase(pos);
302*795d594fSAndroid Build Coastguard Worker return OK;
303*795d594fSAndroid Build Coastguard Worker }
304*795d594fSAndroid Build Coastguard Worker
SetFieldAccessWatch(jvmtiEnv * jenv,jclass klass,jfieldID field)305*795d594fSAndroid Build Coastguard Worker jvmtiError FieldUtil::SetFieldAccessWatch(jvmtiEnv* jenv, jclass klass, jfieldID field) {
306*795d594fSAndroid Build Coastguard Worker ArtJvmTiEnv* env = ArtJvmTiEnv::AsArtJvmTiEnv(jenv);
307*795d594fSAndroid Build Coastguard Worker art::WriterMutexLock lk(art::Thread::Current(), env->event_info_mutex_);
308*795d594fSAndroid Build Coastguard Worker if (klass == nullptr) {
309*795d594fSAndroid Build Coastguard Worker return ERR(INVALID_CLASS);
310*795d594fSAndroid Build Coastguard Worker }
311*795d594fSAndroid Build Coastguard Worker if (field == nullptr) {
312*795d594fSAndroid Build Coastguard Worker return ERR(INVALID_FIELDID);
313*795d594fSAndroid Build Coastguard Worker }
314*795d594fSAndroid Build Coastguard Worker auto res_pair = env->access_watched_fields.insert(art::jni::DecodeArtField(field));
315*795d594fSAndroid Build Coastguard Worker if (!res_pair.second) {
316*795d594fSAndroid Build Coastguard Worker // Didn't get inserted because it's already present!
317*795d594fSAndroid Build Coastguard Worker return ERR(DUPLICATE);
318*795d594fSAndroid Build Coastguard Worker }
319*795d594fSAndroid Build Coastguard Worker return OK;
320*795d594fSAndroid Build Coastguard Worker }
321*795d594fSAndroid Build Coastguard Worker
ClearFieldAccessWatch(jvmtiEnv * jenv,jclass klass,jfieldID field)322*795d594fSAndroid Build Coastguard Worker jvmtiError FieldUtil::ClearFieldAccessWatch(jvmtiEnv* jenv, jclass klass, jfieldID field) {
323*795d594fSAndroid Build Coastguard Worker ArtJvmTiEnv* env = ArtJvmTiEnv::AsArtJvmTiEnv(jenv);
324*795d594fSAndroid Build Coastguard Worker art::WriterMutexLock lk(art::Thread::Current(), env->event_info_mutex_);
325*795d594fSAndroid Build Coastguard Worker if (klass == nullptr) {
326*795d594fSAndroid Build Coastguard Worker return ERR(INVALID_CLASS);
327*795d594fSAndroid Build Coastguard Worker }
328*795d594fSAndroid Build Coastguard Worker if (field == nullptr) {
329*795d594fSAndroid Build Coastguard Worker return ERR(INVALID_FIELDID);
330*795d594fSAndroid Build Coastguard Worker }
331*795d594fSAndroid Build Coastguard Worker auto pos = env->access_watched_fields.find(art::jni::DecodeArtField(field));
332*795d594fSAndroid Build Coastguard Worker if (pos == env->access_watched_fields.end()) {
333*795d594fSAndroid Build Coastguard Worker return ERR(NOT_FOUND);
334*795d594fSAndroid Build Coastguard Worker }
335*795d594fSAndroid Build Coastguard Worker env->access_watched_fields.erase(pos);
336*795d594fSAndroid Build Coastguard Worker return OK;
337*795d594fSAndroid Build Coastguard Worker }
338*795d594fSAndroid Build Coastguard Worker
339*795d594fSAndroid Build Coastguard Worker } // namespace openjdkjvmti
340