xref: /aosp_15_r20/art/openjdkjvmti/ti_heap.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2016 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #include "ti_heap.h"
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker #include <ios>
20*795d594fSAndroid Build Coastguard Worker #include <unordered_map>
21*795d594fSAndroid Build Coastguard Worker 
22*795d594fSAndroid Build Coastguard Worker #include "android-base/logging.h"
23*795d594fSAndroid Build Coastguard Worker #include "android-base/thread_annotations.h"
24*795d594fSAndroid Build Coastguard Worker #include "arch/context.h"
25*795d594fSAndroid Build Coastguard Worker #include "art_field-inl.h"
26*795d594fSAndroid Build Coastguard Worker #include "art_jvmti.h"
27*795d594fSAndroid Build Coastguard Worker #include "base/logging.h"
28*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
29*795d594fSAndroid Build Coastguard Worker #include "base/mutex.h"
30*795d594fSAndroid Build Coastguard Worker #include "base/utils.h"
31*795d594fSAndroid Build Coastguard Worker #include "class_linker.h"
32*795d594fSAndroid Build Coastguard Worker #include "deopt_manager.h"
33*795d594fSAndroid Build Coastguard Worker #include "dex/primitive.h"
34*795d594fSAndroid Build Coastguard Worker #include "events-inl.h"
35*795d594fSAndroid Build Coastguard Worker #include "gc/collector_type.h"
36*795d594fSAndroid Build Coastguard Worker #include "gc/gc_cause.h"
37*795d594fSAndroid Build Coastguard Worker #include "gc/heap-visit-objects-inl.h"
38*795d594fSAndroid Build Coastguard Worker #include "gc/heap-inl.h"
39*795d594fSAndroid Build Coastguard Worker #include "gc/scoped_gc_critical_section.h"
40*795d594fSAndroid Build Coastguard Worker #include "gc_root-inl.h"
41*795d594fSAndroid Build Coastguard Worker #include "handle.h"
42*795d594fSAndroid Build Coastguard Worker #include "handle_scope.h"
43*795d594fSAndroid Build Coastguard Worker #include "java_frame_root_info.h"
44*795d594fSAndroid Build Coastguard Worker #include "jni/jni_env_ext.h"
45*795d594fSAndroid Build Coastguard Worker #include "jni/jni_id_manager.h"
46*795d594fSAndroid Build Coastguard Worker #include "jni/jni_internal.h"
47*795d594fSAndroid Build Coastguard Worker #include "jvmti_weak_table-inl.h"
48*795d594fSAndroid Build Coastguard Worker #include "mirror/array-inl.h"
49*795d594fSAndroid Build Coastguard Worker #include "mirror/array.h"
50*795d594fSAndroid Build Coastguard Worker #include "mirror/class.h"
51*795d594fSAndroid Build Coastguard Worker #include "mirror/object-inl.h"
52*795d594fSAndroid Build Coastguard Worker #include "mirror/object-refvisitor-inl.h"
53*795d594fSAndroid Build Coastguard Worker #include "mirror/object_array-inl.h"
54*795d594fSAndroid Build Coastguard Worker #include "mirror/object_array-alloc-inl.h"
55*795d594fSAndroid Build Coastguard Worker #include "mirror/object_reference.h"
56*795d594fSAndroid Build Coastguard Worker #include "obj_ptr-inl.h"
57*795d594fSAndroid Build Coastguard Worker #include "object_callbacks.h"
58*795d594fSAndroid Build Coastguard Worker #include "object_tagging.h"
59*795d594fSAndroid Build Coastguard Worker #include "offsets.h"
60*795d594fSAndroid Build Coastguard Worker #include "read_barrier.h"
61*795d594fSAndroid Build Coastguard Worker #include "runtime.h"
62*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change-inl.h"
63*795d594fSAndroid Build Coastguard Worker #include "stack.h"
64*795d594fSAndroid Build Coastguard Worker #include "thread-inl.h"
65*795d594fSAndroid Build Coastguard Worker #include "thread_list.h"
66*795d594fSAndroid Build Coastguard Worker #include "ti_logging.h"
67*795d594fSAndroid Build Coastguard Worker #include "ti_stack.h"
68*795d594fSAndroid Build Coastguard Worker #include "ti_thread.h"
69*795d594fSAndroid Build Coastguard Worker #include "well_known_classes.h"
70*795d594fSAndroid Build Coastguard Worker 
71*795d594fSAndroid Build Coastguard Worker namespace openjdkjvmti {
72*795d594fSAndroid Build Coastguard Worker 
73*795d594fSAndroid Build Coastguard Worker EventHandler* HeapExtensions::gEventHandler = nullptr;
74*795d594fSAndroid Build Coastguard Worker 
75*795d594fSAndroid Build Coastguard Worker namespace {
76*795d594fSAndroid Build Coastguard Worker 
77*795d594fSAndroid Build Coastguard Worker struct IndexCache {
78*795d594fSAndroid Build Coastguard Worker   // The number of interface fields implemented by the class. This is a prefix to all assigned
79*795d594fSAndroid Build Coastguard Worker   // field indices.
80*795d594fSAndroid Build Coastguard Worker   size_t interface_fields;
81*795d594fSAndroid Build Coastguard Worker 
82*795d594fSAndroid Build Coastguard Worker   // It would be nice to also cache the following, but it is complicated to wire up into the
83*795d594fSAndroid Build Coastguard Worker   // generic visit:
84*795d594fSAndroid Build Coastguard Worker   // The number of fields in interfaces and superclasses. This is the first index assigned to
85*795d594fSAndroid Build Coastguard Worker   // fields of the class.
86*795d594fSAndroid Build Coastguard Worker   // size_t superclass_fields;
87*795d594fSAndroid Build Coastguard Worker };
88*795d594fSAndroid Build Coastguard Worker using IndexCachingTable = JvmtiWeakTable<IndexCache>;
89*795d594fSAndroid Build Coastguard Worker 
90*795d594fSAndroid Build Coastguard Worker static IndexCachingTable gIndexCachingTable;
91*795d594fSAndroid Build Coastguard Worker 
92*795d594fSAndroid Build Coastguard Worker // Report the contents of a string, if a callback is set.
ReportString(art::ObjPtr<art::mirror::Object> obj,jvmtiEnv * env,ObjectTagTable * tag_table,const jvmtiHeapCallbacks * cb,const void * user_data)93*795d594fSAndroid Build Coastguard Worker jint ReportString(art::ObjPtr<art::mirror::Object> obj,
94*795d594fSAndroid Build Coastguard Worker                   jvmtiEnv* env,
95*795d594fSAndroid Build Coastguard Worker                   ObjectTagTable* tag_table,
96*795d594fSAndroid Build Coastguard Worker                   const jvmtiHeapCallbacks* cb,
97*795d594fSAndroid Build Coastguard Worker                   const void* user_data) REQUIRES_SHARED(art::Locks::mutator_lock_) {
98*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(cb->string_primitive_value_callback != nullptr) && obj->IsString()) {
99*795d594fSAndroid Build Coastguard Worker     art::ObjPtr<art::mirror::String> str = obj->AsString();
100*795d594fSAndroid Build Coastguard Worker     int32_t string_length = str->GetLength();
101*795d594fSAndroid Build Coastguard Worker     JvmtiUniquePtr<uint16_t[]> data;
102*795d594fSAndroid Build Coastguard Worker 
103*795d594fSAndroid Build Coastguard Worker     if (string_length > 0) {
104*795d594fSAndroid Build Coastguard Worker       jvmtiError alloc_error;
105*795d594fSAndroid Build Coastguard Worker       data = AllocJvmtiUniquePtr<uint16_t[]>(env, string_length, &alloc_error);
106*795d594fSAndroid Build Coastguard Worker       if (data == nullptr) {
107*795d594fSAndroid Build Coastguard Worker         // TODO: Not really sure what to do here. Should we abort the iteration and go all the way
108*795d594fSAndroid Build Coastguard Worker         //       back? For now just warn.
109*795d594fSAndroid Build Coastguard Worker         LOG(WARNING) << "Unable to allocate buffer for string reporting! Silently dropping value."
110*795d594fSAndroid Build Coastguard Worker                      << " >" << str->ToModifiedUtf8() << "<";
111*795d594fSAndroid Build Coastguard Worker         return 0;
112*795d594fSAndroid Build Coastguard Worker       }
113*795d594fSAndroid Build Coastguard Worker 
114*795d594fSAndroid Build Coastguard Worker       if (str->IsCompressed()) {
115*795d594fSAndroid Build Coastguard Worker         uint8_t* compressed_data = str->GetValueCompressed();
116*795d594fSAndroid Build Coastguard Worker         for (int32_t i = 0; i != string_length; ++i) {
117*795d594fSAndroid Build Coastguard Worker           data[i] = compressed_data[i];
118*795d594fSAndroid Build Coastguard Worker         }
119*795d594fSAndroid Build Coastguard Worker       } else {
120*795d594fSAndroid Build Coastguard Worker         // Can copy directly.
121*795d594fSAndroid Build Coastguard Worker         memcpy(data.get(), str->GetValue(), string_length * sizeof(uint16_t));
122*795d594fSAndroid Build Coastguard Worker       }
123*795d594fSAndroid Build Coastguard Worker     }
124*795d594fSAndroid Build Coastguard Worker 
125*795d594fSAndroid Build Coastguard Worker     const jlong class_tag = tag_table->GetTagOrZero(obj->GetClass());
126*795d594fSAndroid Build Coastguard Worker     jlong string_tag = tag_table->GetTagOrZero(obj.Ptr());
127*795d594fSAndroid Build Coastguard Worker     const jlong saved_string_tag = string_tag;
128*795d594fSAndroid Build Coastguard Worker 
129*795d594fSAndroid Build Coastguard Worker     jint result = cb->string_primitive_value_callback(class_tag,
130*795d594fSAndroid Build Coastguard Worker                                                       obj->SizeOf(),
131*795d594fSAndroid Build Coastguard Worker                                                       &string_tag,
132*795d594fSAndroid Build Coastguard Worker                                                       data.get(),
133*795d594fSAndroid Build Coastguard Worker                                                       string_length,
134*795d594fSAndroid Build Coastguard Worker                                                       const_cast<void*>(user_data));
135*795d594fSAndroid Build Coastguard Worker     if (string_tag != saved_string_tag) {
136*795d594fSAndroid Build Coastguard Worker       tag_table->Set(obj.Ptr(), string_tag);
137*795d594fSAndroid Build Coastguard Worker     }
138*795d594fSAndroid Build Coastguard Worker 
139*795d594fSAndroid Build Coastguard Worker     return result;
140*795d594fSAndroid Build Coastguard Worker   }
141*795d594fSAndroid Build Coastguard Worker   return 0;
142*795d594fSAndroid Build Coastguard Worker }
143*795d594fSAndroid Build Coastguard Worker 
144*795d594fSAndroid Build Coastguard Worker // Report the contents of a primitive array, if a callback is set.
ReportPrimitiveArray(art::ObjPtr<art::mirror::Object> obj,jvmtiEnv * env,ObjectTagTable * tag_table,const jvmtiHeapCallbacks * cb,const void * user_data)145*795d594fSAndroid Build Coastguard Worker jint ReportPrimitiveArray(art::ObjPtr<art::mirror::Object> obj,
146*795d594fSAndroid Build Coastguard Worker                           jvmtiEnv* env,
147*795d594fSAndroid Build Coastguard Worker                           ObjectTagTable* tag_table,
148*795d594fSAndroid Build Coastguard Worker                           const jvmtiHeapCallbacks* cb,
149*795d594fSAndroid Build Coastguard Worker                           const void* user_data) REQUIRES_SHARED(art::Locks::mutator_lock_) {
150*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(cb->array_primitive_value_callback != nullptr) &&
151*795d594fSAndroid Build Coastguard Worker       obj->IsArrayInstance() &&
152*795d594fSAndroid Build Coastguard Worker       !obj->IsObjectArray()) {
153*795d594fSAndroid Build Coastguard Worker     art::ObjPtr<art::mirror::Array> array = obj->AsArray();
154*795d594fSAndroid Build Coastguard Worker     int32_t array_length = array->GetLength();
155*795d594fSAndroid Build Coastguard Worker     size_t component_size = array->GetClass()->GetComponentSize();
156*795d594fSAndroid Build Coastguard Worker     art::Primitive::Type art_prim_type = array->GetClass()->GetComponentType()->GetPrimitiveType();
157*795d594fSAndroid Build Coastguard Worker     jvmtiPrimitiveType prim_type =
158*795d594fSAndroid Build Coastguard Worker         static_cast<jvmtiPrimitiveType>(art::Primitive::Descriptor(art_prim_type)[0]);
159*795d594fSAndroid Build Coastguard Worker     DCHECK(prim_type == JVMTI_PRIMITIVE_TYPE_BOOLEAN ||
160*795d594fSAndroid Build Coastguard Worker            prim_type == JVMTI_PRIMITIVE_TYPE_BYTE ||
161*795d594fSAndroid Build Coastguard Worker            prim_type == JVMTI_PRIMITIVE_TYPE_CHAR ||
162*795d594fSAndroid Build Coastguard Worker            prim_type == JVMTI_PRIMITIVE_TYPE_SHORT ||
163*795d594fSAndroid Build Coastguard Worker            prim_type == JVMTI_PRIMITIVE_TYPE_INT ||
164*795d594fSAndroid Build Coastguard Worker            prim_type == JVMTI_PRIMITIVE_TYPE_LONG ||
165*795d594fSAndroid Build Coastguard Worker            prim_type == JVMTI_PRIMITIVE_TYPE_FLOAT ||
166*795d594fSAndroid Build Coastguard Worker            prim_type == JVMTI_PRIMITIVE_TYPE_DOUBLE);
167*795d594fSAndroid Build Coastguard Worker 
168*795d594fSAndroid Build Coastguard Worker     const jlong class_tag = tag_table->GetTagOrZero(obj->GetClass());
169*795d594fSAndroid Build Coastguard Worker     jlong array_tag = tag_table->GetTagOrZero(obj.Ptr());
170*795d594fSAndroid Build Coastguard Worker     const jlong saved_array_tag = array_tag;
171*795d594fSAndroid Build Coastguard Worker 
172*795d594fSAndroid Build Coastguard Worker     jint result;
173*795d594fSAndroid Build Coastguard Worker     if (array_length == 0) {
174*795d594fSAndroid Build Coastguard Worker       result = cb->array_primitive_value_callback(class_tag,
175*795d594fSAndroid Build Coastguard Worker                                                   obj->SizeOf(),
176*795d594fSAndroid Build Coastguard Worker                                                   &array_tag,
177*795d594fSAndroid Build Coastguard Worker                                                   0,
178*795d594fSAndroid Build Coastguard Worker                                                   prim_type,
179*795d594fSAndroid Build Coastguard Worker                                                   nullptr,
180*795d594fSAndroid Build Coastguard Worker                                                   const_cast<void*>(user_data));
181*795d594fSAndroid Build Coastguard Worker     } else {
182*795d594fSAndroid Build Coastguard Worker       jvmtiError alloc_error;
183*795d594fSAndroid Build Coastguard Worker       JvmtiUniquePtr<char[]> data = AllocJvmtiUniquePtr<char[]>(env,
184*795d594fSAndroid Build Coastguard Worker                                                                 array_length * component_size,
185*795d594fSAndroid Build Coastguard Worker                                                                 &alloc_error);
186*795d594fSAndroid Build Coastguard Worker       if (data == nullptr) {
187*795d594fSAndroid Build Coastguard Worker         // TODO: Not really sure what to do here. Should we abort the iteration and go all the way
188*795d594fSAndroid Build Coastguard Worker         //       back? For now just warn.
189*795d594fSAndroid Build Coastguard Worker         LOG(WARNING) << "Unable to allocate buffer for array reporting! Silently dropping value.";
190*795d594fSAndroid Build Coastguard Worker         return 0;
191*795d594fSAndroid Build Coastguard Worker       }
192*795d594fSAndroid Build Coastguard Worker 
193*795d594fSAndroid Build Coastguard Worker       memcpy(data.get(), array->GetRawData(component_size, 0), array_length * component_size);
194*795d594fSAndroid Build Coastguard Worker 
195*795d594fSAndroid Build Coastguard Worker       result = cb->array_primitive_value_callback(class_tag,
196*795d594fSAndroid Build Coastguard Worker                                                   obj->SizeOf(),
197*795d594fSAndroid Build Coastguard Worker                                                   &array_tag,
198*795d594fSAndroid Build Coastguard Worker                                                   array_length,
199*795d594fSAndroid Build Coastguard Worker                                                   prim_type,
200*795d594fSAndroid Build Coastguard Worker                                                   data.get(),
201*795d594fSAndroid Build Coastguard Worker                                                   const_cast<void*>(user_data));
202*795d594fSAndroid Build Coastguard Worker     }
203*795d594fSAndroid Build Coastguard Worker 
204*795d594fSAndroid Build Coastguard Worker     if (array_tag != saved_array_tag) {
205*795d594fSAndroid Build Coastguard Worker       tag_table->Set(obj.Ptr(), array_tag);
206*795d594fSAndroid Build Coastguard Worker     }
207*795d594fSAndroid Build Coastguard Worker 
208*795d594fSAndroid Build Coastguard Worker     return result;
209*795d594fSAndroid Build Coastguard Worker   }
210*795d594fSAndroid Build Coastguard Worker   return 0;
211*795d594fSAndroid Build Coastguard Worker }
212*795d594fSAndroid Build Coastguard Worker 
213*795d594fSAndroid Build Coastguard Worker template <typename UserData>
VisitorFalse(art::ObjPtr<art::mirror::Object> obj,art::ObjPtr<art::mirror::Class> klass,art::ArtField & field,size_t field_index,UserData * user_data)214*795d594fSAndroid Build Coastguard Worker bool VisitorFalse([[maybe_unused]] art::ObjPtr<art::mirror::Object> obj,
215*795d594fSAndroid Build Coastguard Worker                   [[maybe_unused]] art::ObjPtr<art::mirror::Class> klass,
216*795d594fSAndroid Build Coastguard Worker                   [[maybe_unused]] art::ArtField& field,
217*795d594fSAndroid Build Coastguard Worker                   [[maybe_unused]] size_t field_index,
218*795d594fSAndroid Build Coastguard Worker                   [[maybe_unused]] UserData* user_data) {
219*795d594fSAndroid Build Coastguard Worker   return false;
220*795d594fSAndroid Build Coastguard Worker }
221*795d594fSAndroid Build Coastguard Worker 
222*795d594fSAndroid Build Coastguard Worker template <typename UserData, bool kCallVisitorOnRecursion>
223*795d594fSAndroid Build Coastguard Worker class FieldVisitor {
224*795d594fSAndroid Build Coastguard Worker  public:
225*795d594fSAndroid Build Coastguard Worker   // Report the contents of a primitive fields of the given object, if a callback is set.
226*795d594fSAndroid Build Coastguard Worker   template <typename StaticPrimitiveVisitor,
227*795d594fSAndroid Build Coastguard Worker             typename StaticReferenceVisitor,
228*795d594fSAndroid Build Coastguard Worker             typename InstancePrimitiveVisitor,
229*795d594fSAndroid Build Coastguard Worker             typename InstanceReferenceVisitor>
ReportFields(art::ObjPtr<art::mirror::Object> obj,UserData * user_data,StaticPrimitiveVisitor & static_prim_visitor,StaticReferenceVisitor & static_ref_visitor,InstancePrimitiveVisitor & instance_prim_visitor,InstanceReferenceVisitor & instance_ref_visitor)230*795d594fSAndroid Build Coastguard Worker   static bool ReportFields(art::ObjPtr<art::mirror::Object> obj,
231*795d594fSAndroid Build Coastguard Worker                            UserData* user_data,
232*795d594fSAndroid Build Coastguard Worker                            StaticPrimitiveVisitor& static_prim_visitor,
233*795d594fSAndroid Build Coastguard Worker                            StaticReferenceVisitor& static_ref_visitor,
234*795d594fSAndroid Build Coastguard Worker                            InstancePrimitiveVisitor& instance_prim_visitor,
235*795d594fSAndroid Build Coastguard Worker                            InstanceReferenceVisitor& instance_ref_visitor)
236*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_) {
237*795d594fSAndroid Build Coastguard Worker     FieldVisitor fv(user_data);
238*795d594fSAndroid Build Coastguard Worker 
239*795d594fSAndroid Build Coastguard Worker     if (obj->IsClass()) {
240*795d594fSAndroid Build Coastguard Worker       // When visiting a class, we only visit the static fields of the given class. No field of
241*795d594fSAndroid Build Coastguard Worker       // superclasses is visited.
242*795d594fSAndroid Build Coastguard Worker       art::ObjPtr<art::mirror::Class> klass = obj->AsClass();
243*795d594fSAndroid Build Coastguard Worker       // Only report fields on resolved classes. We need valid field data.
244*795d594fSAndroid Build Coastguard Worker       if (!klass->IsResolved()) {
245*795d594fSAndroid Build Coastguard Worker         return false;
246*795d594fSAndroid Build Coastguard Worker       }
247*795d594fSAndroid Build Coastguard Worker       return fv.ReportFieldsImpl(nullptr,
248*795d594fSAndroid Build Coastguard Worker                                  obj->AsClass(),
249*795d594fSAndroid Build Coastguard Worker                                  obj->AsClass()->IsInterface(),
250*795d594fSAndroid Build Coastguard Worker                                  static_prim_visitor,
251*795d594fSAndroid Build Coastguard Worker                                  static_ref_visitor,
252*795d594fSAndroid Build Coastguard Worker                                  instance_prim_visitor,
253*795d594fSAndroid Build Coastguard Worker                                  instance_ref_visitor);
254*795d594fSAndroid Build Coastguard Worker     } else {
255*795d594fSAndroid Build Coastguard Worker       // See comment above. Just double-checking here, but an instance *should* mean the class was
256*795d594fSAndroid Build Coastguard Worker       // resolved.
257*795d594fSAndroid Build Coastguard Worker       DCHECK(obj->GetClass()->IsResolved() || obj->GetClass()->IsErroneousResolved());
258*795d594fSAndroid Build Coastguard Worker       return fv.ReportFieldsImpl(obj,
259*795d594fSAndroid Build Coastguard Worker                                  obj->GetClass(),
260*795d594fSAndroid Build Coastguard Worker                                  false,
261*795d594fSAndroid Build Coastguard Worker                                  static_prim_visitor,
262*795d594fSAndroid Build Coastguard Worker                                  static_ref_visitor,
263*795d594fSAndroid Build Coastguard Worker                                  instance_prim_visitor,
264*795d594fSAndroid Build Coastguard Worker                                  instance_ref_visitor);
265*795d594fSAndroid Build Coastguard Worker     }
266*795d594fSAndroid Build Coastguard Worker   }
267*795d594fSAndroid Build Coastguard Worker 
268*795d594fSAndroid Build Coastguard Worker  private:
FieldVisitor(UserData * user_data)269*795d594fSAndroid Build Coastguard Worker   explicit FieldVisitor(UserData* user_data) : user_data_(user_data) {}
270*795d594fSAndroid Build Coastguard Worker 
271*795d594fSAndroid Build Coastguard Worker   // Report the contents of fields of the given object. If obj is null, report the static fields,
272*795d594fSAndroid Build Coastguard Worker   // otherwise the instance fields.
273*795d594fSAndroid Build Coastguard Worker   template <typename StaticPrimitiveVisitor,
274*795d594fSAndroid Build Coastguard Worker             typename StaticReferenceVisitor,
275*795d594fSAndroid Build Coastguard Worker             typename InstancePrimitiveVisitor,
276*795d594fSAndroid Build Coastguard Worker             typename InstanceReferenceVisitor>
ReportFieldsImpl(art::ObjPtr<art::mirror::Object> obj,art::ObjPtr<art::mirror::Class> klass,bool skip_java_lang_object,StaticPrimitiveVisitor & static_prim_visitor,StaticReferenceVisitor & static_ref_visitor,InstancePrimitiveVisitor & instance_prim_visitor,InstanceReferenceVisitor & instance_ref_visitor)277*795d594fSAndroid Build Coastguard Worker   bool ReportFieldsImpl(art::ObjPtr<art::mirror::Object> obj,
278*795d594fSAndroid Build Coastguard Worker                         art::ObjPtr<art::mirror::Class> klass,
279*795d594fSAndroid Build Coastguard Worker                         bool skip_java_lang_object,
280*795d594fSAndroid Build Coastguard Worker                         StaticPrimitiveVisitor& static_prim_visitor,
281*795d594fSAndroid Build Coastguard Worker                         StaticReferenceVisitor& static_ref_visitor,
282*795d594fSAndroid Build Coastguard Worker                         InstancePrimitiveVisitor& instance_prim_visitor,
283*795d594fSAndroid Build Coastguard Worker                         InstanceReferenceVisitor& instance_ref_visitor)
284*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_) {
285*795d594fSAndroid Build Coastguard Worker     // Compute the offset of field indices.
286*795d594fSAndroid Build Coastguard Worker     size_t interface_field_count = CountInterfaceFields(klass);
287*795d594fSAndroid Build Coastguard Worker 
288*795d594fSAndroid Build Coastguard Worker     size_t tmp;
289*795d594fSAndroid Build Coastguard Worker     bool aborted = ReportFieldsRecursive(obj,
290*795d594fSAndroid Build Coastguard Worker                                          klass,
291*795d594fSAndroid Build Coastguard Worker                                          interface_field_count,
292*795d594fSAndroid Build Coastguard Worker                                          skip_java_lang_object,
293*795d594fSAndroid Build Coastguard Worker                                          static_prim_visitor,
294*795d594fSAndroid Build Coastguard Worker                                          static_ref_visitor,
295*795d594fSAndroid Build Coastguard Worker                                          instance_prim_visitor,
296*795d594fSAndroid Build Coastguard Worker                                          instance_ref_visitor,
297*795d594fSAndroid Build Coastguard Worker                                          &tmp);
298*795d594fSAndroid Build Coastguard Worker     return aborted;
299*795d594fSAndroid Build Coastguard Worker   }
300*795d594fSAndroid Build Coastguard Worker 
301*795d594fSAndroid Build Coastguard Worker   // Visit primitive fields in an object (instance). Return true if the visit was aborted.
302*795d594fSAndroid Build Coastguard Worker   template <typename StaticPrimitiveVisitor,
303*795d594fSAndroid Build Coastguard Worker             typename StaticReferenceVisitor,
304*795d594fSAndroid Build Coastguard Worker             typename InstancePrimitiveVisitor,
305*795d594fSAndroid Build Coastguard Worker             typename InstanceReferenceVisitor>
ReportFieldsRecursive(art::ObjPtr<art::mirror::Object> obj,art::ObjPtr<art::mirror::Class> klass,size_t interface_fields,bool skip_java_lang_object,StaticPrimitiveVisitor & static_prim_visitor,StaticReferenceVisitor & static_ref_visitor,InstancePrimitiveVisitor & instance_prim_visitor,InstanceReferenceVisitor & instance_ref_visitor,size_t * field_index_out)306*795d594fSAndroid Build Coastguard Worker   bool ReportFieldsRecursive(art::ObjPtr<art::mirror::Object> obj,
307*795d594fSAndroid Build Coastguard Worker                              art::ObjPtr<art::mirror::Class> klass,
308*795d594fSAndroid Build Coastguard Worker                              size_t interface_fields,
309*795d594fSAndroid Build Coastguard Worker                              bool skip_java_lang_object,
310*795d594fSAndroid Build Coastguard Worker                              StaticPrimitiveVisitor& static_prim_visitor,
311*795d594fSAndroid Build Coastguard Worker                              StaticReferenceVisitor& static_ref_visitor,
312*795d594fSAndroid Build Coastguard Worker                              InstancePrimitiveVisitor& instance_prim_visitor,
313*795d594fSAndroid Build Coastguard Worker                              InstanceReferenceVisitor& instance_ref_visitor,
314*795d594fSAndroid Build Coastguard Worker                              size_t* field_index_out)
315*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_) {
316*795d594fSAndroid Build Coastguard Worker     DCHECK(klass != nullptr);
317*795d594fSAndroid Build Coastguard Worker     size_t field_index;
318*795d594fSAndroid Build Coastguard Worker     if (klass->GetSuperClass() == nullptr) {
319*795d594fSAndroid Build Coastguard Worker       // j.l.Object. Start with the fields from interfaces.
320*795d594fSAndroid Build Coastguard Worker       field_index = interface_fields;
321*795d594fSAndroid Build Coastguard Worker       if (skip_java_lang_object) {
322*795d594fSAndroid Build Coastguard Worker         *field_index_out = field_index;
323*795d594fSAndroid Build Coastguard Worker         return false;
324*795d594fSAndroid Build Coastguard Worker       }
325*795d594fSAndroid Build Coastguard Worker     } else {
326*795d594fSAndroid Build Coastguard Worker       // Report superclass fields.
327*795d594fSAndroid Build Coastguard Worker       if (kCallVisitorOnRecursion) {
328*795d594fSAndroid Build Coastguard Worker         if (ReportFieldsRecursive(obj,
329*795d594fSAndroid Build Coastguard Worker                                   klass->GetSuperClass(),
330*795d594fSAndroid Build Coastguard Worker                                   interface_fields,
331*795d594fSAndroid Build Coastguard Worker                                   skip_java_lang_object,
332*795d594fSAndroid Build Coastguard Worker                                   static_prim_visitor,
333*795d594fSAndroid Build Coastguard Worker                                   static_ref_visitor,
334*795d594fSAndroid Build Coastguard Worker                                   instance_prim_visitor,
335*795d594fSAndroid Build Coastguard Worker                                   instance_ref_visitor,
336*795d594fSAndroid Build Coastguard Worker                                   &field_index)) {
337*795d594fSAndroid Build Coastguard Worker           return true;
338*795d594fSAndroid Build Coastguard Worker         }
339*795d594fSAndroid Build Coastguard Worker       } else {
340*795d594fSAndroid Build Coastguard Worker         // Still call, but with empty visitor. This is required for correct counting.
341*795d594fSAndroid Build Coastguard Worker         ReportFieldsRecursive(obj,
342*795d594fSAndroid Build Coastguard Worker                               klass->GetSuperClass(),
343*795d594fSAndroid Build Coastguard Worker                               interface_fields,
344*795d594fSAndroid Build Coastguard Worker                               skip_java_lang_object,
345*795d594fSAndroid Build Coastguard Worker                               VisitorFalse<UserData>,
346*795d594fSAndroid Build Coastguard Worker                               VisitorFalse<UserData>,
347*795d594fSAndroid Build Coastguard Worker                               VisitorFalse<UserData>,
348*795d594fSAndroid Build Coastguard Worker                               VisitorFalse<UserData>,
349*795d594fSAndroid Build Coastguard Worker                               &field_index);
350*795d594fSAndroid Build Coastguard Worker       }
351*795d594fSAndroid Build Coastguard Worker     }
352*795d594fSAndroid Build Coastguard Worker 
353*795d594fSAndroid Build Coastguard Worker     // Now visit fields for the current klass.
354*795d594fSAndroid Build Coastguard Worker 
355*795d594fSAndroid Build Coastguard Worker     for (auto& static_field : klass->GetSFields()) {
356*795d594fSAndroid Build Coastguard Worker       if (static_field.IsPrimitiveType()) {
357*795d594fSAndroid Build Coastguard Worker         if (static_prim_visitor(obj,
358*795d594fSAndroid Build Coastguard Worker                                 klass,
359*795d594fSAndroid Build Coastguard Worker                                 static_field,
360*795d594fSAndroid Build Coastguard Worker                                 field_index,
361*795d594fSAndroid Build Coastguard Worker                                 user_data_)) {
362*795d594fSAndroid Build Coastguard Worker           return true;
363*795d594fSAndroid Build Coastguard Worker         }
364*795d594fSAndroid Build Coastguard Worker       } else {
365*795d594fSAndroid Build Coastguard Worker         if (static_ref_visitor(obj,
366*795d594fSAndroid Build Coastguard Worker                                klass,
367*795d594fSAndroid Build Coastguard Worker                                static_field,
368*795d594fSAndroid Build Coastguard Worker                                field_index,
369*795d594fSAndroid Build Coastguard Worker                                user_data_)) {
370*795d594fSAndroid Build Coastguard Worker           return true;
371*795d594fSAndroid Build Coastguard Worker         }
372*795d594fSAndroid Build Coastguard Worker       }
373*795d594fSAndroid Build Coastguard Worker       field_index++;
374*795d594fSAndroid Build Coastguard Worker     }
375*795d594fSAndroid Build Coastguard Worker 
376*795d594fSAndroid Build Coastguard Worker     for (auto& instance_field : klass->GetIFields()) {
377*795d594fSAndroid Build Coastguard Worker       if (instance_field.IsPrimitiveType()) {
378*795d594fSAndroid Build Coastguard Worker         if (instance_prim_visitor(obj,
379*795d594fSAndroid Build Coastguard Worker                                   klass,
380*795d594fSAndroid Build Coastguard Worker                                   instance_field,
381*795d594fSAndroid Build Coastguard Worker                                   field_index,
382*795d594fSAndroid Build Coastguard Worker                                   user_data_)) {
383*795d594fSAndroid Build Coastguard Worker           return true;
384*795d594fSAndroid Build Coastguard Worker         }
385*795d594fSAndroid Build Coastguard Worker       } else {
386*795d594fSAndroid Build Coastguard Worker         if (instance_ref_visitor(obj,
387*795d594fSAndroid Build Coastguard Worker                                  klass,
388*795d594fSAndroid Build Coastguard Worker                                  instance_field,
389*795d594fSAndroid Build Coastguard Worker                                  field_index,
390*795d594fSAndroid Build Coastguard Worker                                  user_data_)) {
391*795d594fSAndroid Build Coastguard Worker           return true;
392*795d594fSAndroid Build Coastguard Worker         }
393*795d594fSAndroid Build Coastguard Worker       }
394*795d594fSAndroid Build Coastguard Worker       field_index++;
395*795d594fSAndroid Build Coastguard Worker     }
396*795d594fSAndroid Build Coastguard Worker 
397*795d594fSAndroid Build Coastguard Worker     *field_index_out = field_index;
398*795d594fSAndroid Build Coastguard Worker     return false;
399*795d594fSAndroid Build Coastguard Worker   }
400*795d594fSAndroid Build Coastguard Worker 
401*795d594fSAndroid Build Coastguard Worker   // Implements a visit of the implemented interfaces of a given class.
402*795d594fSAndroid Build Coastguard Worker   template <typename T>
403*795d594fSAndroid Build Coastguard Worker   struct RecursiveInterfaceVisit {
VisitStaticopenjdkjvmti::__anon9790dd1d0111::FieldVisitor::RecursiveInterfaceVisit404*795d594fSAndroid Build Coastguard Worker     static void VisitStatic(art::Thread* self, art::ObjPtr<art::mirror::Class> klass, T& visitor)
405*795d594fSAndroid Build Coastguard Worker         REQUIRES_SHARED(art::Locks::mutator_lock_) {
406*795d594fSAndroid Build Coastguard Worker       RecursiveInterfaceVisit rv;
407*795d594fSAndroid Build Coastguard Worker       rv.Visit(self, klass, visitor);
408*795d594fSAndroid Build Coastguard Worker     }
409*795d594fSAndroid Build Coastguard Worker 
Visitopenjdkjvmti::__anon9790dd1d0111::FieldVisitor::RecursiveInterfaceVisit410*795d594fSAndroid Build Coastguard Worker     void Visit(art::Thread* self, art::ObjPtr<art::mirror::Class> klass, T& visitor)
411*795d594fSAndroid Build Coastguard Worker         REQUIRES_SHARED(art::Locks::mutator_lock_) {
412*795d594fSAndroid Build Coastguard Worker       // First visit the parent, to get the order right.
413*795d594fSAndroid Build Coastguard Worker       // (We do this in preparation for actual visiting of interface fields.)
414*795d594fSAndroid Build Coastguard Worker       if (klass->GetSuperClass() != nullptr) {
415*795d594fSAndroid Build Coastguard Worker         Visit(self, klass->GetSuperClass(), visitor);
416*795d594fSAndroid Build Coastguard Worker       }
417*795d594fSAndroid Build Coastguard Worker       for (uint32_t i = 0; i != klass->NumDirectInterfaces(); ++i) {
418*795d594fSAndroid Build Coastguard Worker         art::ObjPtr<art::mirror::Class> inf_klass = klass->GetDirectInterface(i);
419*795d594fSAndroid Build Coastguard Worker         DCHECK(inf_klass != nullptr);
420*795d594fSAndroid Build Coastguard Worker         VisitInterface(self, inf_klass, visitor);
421*795d594fSAndroid Build Coastguard Worker       }
422*795d594fSAndroid Build Coastguard Worker     }
423*795d594fSAndroid Build Coastguard Worker 
VisitInterfaceopenjdkjvmti::__anon9790dd1d0111::FieldVisitor::RecursiveInterfaceVisit424*795d594fSAndroid Build Coastguard Worker     void VisitInterface(art::Thread* self, art::ObjPtr<art::mirror::Class> inf_klass, T& visitor)
425*795d594fSAndroid Build Coastguard Worker         REQUIRES_SHARED(art::Locks::mutator_lock_) {
426*795d594fSAndroid Build Coastguard Worker       auto it = visited_interfaces.find(inf_klass.Ptr());
427*795d594fSAndroid Build Coastguard Worker       if (it != visited_interfaces.end()) {
428*795d594fSAndroid Build Coastguard Worker         return;
429*795d594fSAndroid Build Coastguard Worker       }
430*795d594fSAndroid Build Coastguard Worker       visited_interfaces.insert(inf_klass.Ptr());
431*795d594fSAndroid Build Coastguard Worker 
432*795d594fSAndroid Build Coastguard Worker       // Let the visitor know about this one. Note that this order is acceptable, as the ordering
433*795d594fSAndroid Build Coastguard Worker       // of these fields never matters for known visitors.
434*795d594fSAndroid Build Coastguard Worker       visitor(inf_klass);
435*795d594fSAndroid Build Coastguard Worker 
436*795d594fSAndroid Build Coastguard Worker       // Now visit the superinterfaces.
437*795d594fSAndroid Build Coastguard Worker       for (uint32_t i = 0; i != inf_klass->NumDirectInterfaces(); ++i) {
438*795d594fSAndroid Build Coastguard Worker         art::ObjPtr<art::mirror::Class> super_inf_klass = inf_klass->GetDirectInterface(i);
439*795d594fSAndroid Build Coastguard Worker         DCHECK(super_inf_klass != nullptr);
440*795d594fSAndroid Build Coastguard Worker         VisitInterface(self, super_inf_klass, visitor);
441*795d594fSAndroid Build Coastguard Worker       }
442*795d594fSAndroid Build Coastguard Worker     }
443*795d594fSAndroid Build Coastguard Worker 
444*795d594fSAndroid Build Coastguard Worker     std::unordered_set<art::mirror::Class*> visited_interfaces;
445*795d594fSAndroid Build Coastguard Worker   };
446*795d594fSAndroid Build Coastguard Worker 
447*795d594fSAndroid Build Coastguard Worker   // Counting interface fields. Note that we cannot use the interface table, as that only contains
448*795d594fSAndroid Build Coastguard Worker   // "non-marker" interfaces (= interfaces with methods).
CountInterfaceFields(art::ObjPtr<art::mirror::Class> klass)449*795d594fSAndroid Build Coastguard Worker   static size_t CountInterfaceFields(art::ObjPtr<art::mirror::Class> klass)
450*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_) {
451*795d594fSAndroid Build Coastguard Worker     // Do we have a cached value?
452*795d594fSAndroid Build Coastguard Worker     IndexCache tmp;
453*795d594fSAndroid Build Coastguard Worker     if (gIndexCachingTable.GetTag(klass.Ptr(), &tmp)) {
454*795d594fSAndroid Build Coastguard Worker       return tmp.interface_fields;
455*795d594fSAndroid Build Coastguard Worker     }
456*795d594fSAndroid Build Coastguard Worker 
457*795d594fSAndroid Build Coastguard Worker     size_t count = 0;
458*795d594fSAndroid Build Coastguard Worker     auto visitor = [&count](art::ObjPtr<art::mirror::Class> inf_klass)
459*795d594fSAndroid Build Coastguard Worker         REQUIRES_SHARED(art::Locks::mutator_lock_) {
460*795d594fSAndroid Build Coastguard Worker       DCHECK(inf_klass->IsInterface());
461*795d594fSAndroid Build Coastguard Worker       DCHECK_EQ(0u, inf_klass->NumInstanceFields());
462*795d594fSAndroid Build Coastguard Worker       count += inf_klass->NumStaticFields();
463*795d594fSAndroid Build Coastguard Worker     };
464*795d594fSAndroid Build Coastguard Worker     RecursiveInterfaceVisit<decltype(visitor)>::VisitStatic(art::Thread::Current(), klass, visitor);
465*795d594fSAndroid Build Coastguard Worker 
466*795d594fSAndroid Build Coastguard Worker     // Store this into the cache.
467*795d594fSAndroid Build Coastguard Worker     tmp.interface_fields = count;
468*795d594fSAndroid Build Coastguard Worker     gIndexCachingTable.Set(klass.Ptr(), tmp);
469*795d594fSAndroid Build Coastguard Worker 
470*795d594fSAndroid Build Coastguard Worker     return count;
471*795d594fSAndroid Build Coastguard Worker   }
472*795d594fSAndroid Build Coastguard Worker 
473*795d594fSAndroid Build Coastguard Worker   UserData* user_data_;
474*795d594fSAndroid Build Coastguard Worker };
475*795d594fSAndroid Build Coastguard Worker 
476*795d594fSAndroid Build Coastguard Worker // Debug helper. Prints the structure of an object.
477*795d594fSAndroid Build Coastguard Worker template <bool kStatic, bool kRef>
478*795d594fSAndroid Build Coastguard Worker struct DumpVisitor {
Callbackopenjdkjvmti::__anon9790dd1d0111::DumpVisitor479*795d594fSAndroid Build Coastguard Worker   static bool Callback([[maybe_unused]] art::ObjPtr<art::mirror::Object> obj,
480*795d594fSAndroid Build Coastguard Worker                        [[maybe_unused]] art::ObjPtr<art::mirror::Class> klass,
481*795d594fSAndroid Build Coastguard Worker                        art::ArtField& field,
482*795d594fSAndroid Build Coastguard Worker                        size_t field_index,
483*795d594fSAndroid Build Coastguard Worker                        [[maybe_unused]] void* user_data)
484*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_) {
485*795d594fSAndroid Build Coastguard Worker     LOG(ERROR) << (kStatic ? "static " : "instance ")
486*795d594fSAndroid Build Coastguard Worker                << (kRef ? "ref " : "primitive ")
487*795d594fSAndroid Build Coastguard Worker                << field.PrettyField()
488*795d594fSAndroid Build Coastguard Worker                << " @ "
489*795d594fSAndroid Build Coastguard Worker                << field_index;
490*795d594fSAndroid Build Coastguard Worker     return false;
491*795d594fSAndroid Build Coastguard Worker   }
492*795d594fSAndroid Build Coastguard Worker };
DumpObjectFields(art::ObjPtr<art::mirror::Object> obj)493*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] void DumpObjectFields(art::ObjPtr<art::mirror::Object> obj)
494*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(art::Locks::mutator_lock_) {
495*795d594fSAndroid Build Coastguard Worker   if (obj->IsClass()) {
496*795d594fSAndroid Build Coastguard Worker     FieldVisitor<void, false>:: ReportFields(obj,
497*795d594fSAndroid Build Coastguard Worker                                              nullptr,
498*795d594fSAndroid Build Coastguard Worker                                              DumpVisitor<true, false>::Callback,
499*795d594fSAndroid Build Coastguard Worker                                              DumpVisitor<true, true>::Callback,
500*795d594fSAndroid Build Coastguard Worker                                              DumpVisitor<false, false>::Callback,
501*795d594fSAndroid Build Coastguard Worker                                              DumpVisitor<false, true>::Callback);
502*795d594fSAndroid Build Coastguard Worker   } else {
503*795d594fSAndroid Build Coastguard Worker     FieldVisitor<void, true>::ReportFields(obj,
504*795d594fSAndroid Build Coastguard Worker                                            nullptr,
505*795d594fSAndroid Build Coastguard Worker                                            DumpVisitor<true, false>::Callback,
506*795d594fSAndroid Build Coastguard Worker                                            DumpVisitor<true, true>::Callback,
507*795d594fSAndroid Build Coastguard Worker                                            DumpVisitor<false, false>::Callback,
508*795d594fSAndroid Build Coastguard Worker                                            DumpVisitor<false, true>::Callback);
509*795d594fSAndroid Build Coastguard Worker   }
510*795d594fSAndroid Build Coastguard Worker }
511*795d594fSAndroid Build Coastguard Worker 
512*795d594fSAndroid Build Coastguard Worker class ReportPrimitiveField {
513*795d594fSAndroid Build Coastguard Worker  public:
Report(art::ObjPtr<art::mirror::Object> obj,ObjectTagTable * tag_table,const jvmtiHeapCallbacks * cb,const void * user_data)514*795d594fSAndroid Build Coastguard Worker   static bool Report(art::ObjPtr<art::mirror::Object> obj,
515*795d594fSAndroid Build Coastguard Worker                      ObjectTagTable* tag_table,
516*795d594fSAndroid Build Coastguard Worker                      const jvmtiHeapCallbacks* cb,
517*795d594fSAndroid Build Coastguard Worker                      const void* user_data)
518*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_) {
519*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(cb->primitive_field_callback != nullptr)) {
520*795d594fSAndroid Build Coastguard Worker       jlong class_tag = tag_table->GetTagOrZero(obj->GetClass());
521*795d594fSAndroid Build Coastguard Worker       ReportPrimitiveField rpf(tag_table, class_tag, cb, user_data);
522*795d594fSAndroid Build Coastguard Worker       if (obj->IsClass()) {
523*795d594fSAndroid Build Coastguard Worker         return FieldVisitor<ReportPrimitiveField, false>::ReportFields(
524*795d594fSAndroid Build Coastguard Worker             obj,
525*795d594fSAndroid Build Coastguard Worker             &rpf,
526*795d594fSAndroid Build Coastguard Worker             ReportPrimitiveFieldCallback<true>,
527*795d594fSAndroid Build Coastguard Worker             VisitorFalse<ReportPrimitiveField>,
528*795d594fSAndroid Build Coastguard Worker             VisitorFalse<ReportPrimitiveField>,
529*795d594fSAndroid Build Coastguard Worker             VisitorFalse<ReportPrimitiveField>);
530*795d594fSAndroid Build Coastguard Worker       } else {
531*795d594fSAndroid Build Coastguard Worker         return FieldVisitor<ReportPrimitiveField, true>::ReportFields(
532*795d594fSAndroid Build Coastguard Worker             obj,
533*795d594fSAndroid Build Coastguard Worker             &rpf,
534*795d594fSAndroid Build Coastguard Worker             VisitorFalse<ReportPrimitiveField>,
535*795d594fSAndroid Build Coastguard Worker             VisitorFalse<ReportPrimitiveField>,
536*795d594fSAndroid Build Coastguard Worker             ReportPrimitiveFieldCallback<false>,
537*795d594fSAndroid Build Coastguard Worker             VisitorFalse<ReportPrimitiveField>);
538*795d594fSAndroid Build Coastguard Worker       }
539*795d594fSAndroid Build Coastguard Worker     }
540*795d594fSAndroid Build Coastguard Worker     return false;
541*795d594fSAndroid Build Coastguard Worker   }
542*795d594fSAndroid Build Coastguard Worker 
543*795d594fSAndroid Build Coastguard Worker 
544*795d594fSAndroid Build Coastguard Worker  private:
ReportPrimitiveField(ObjectTagTable * tag_table,jlong class_tag,const jvmtiHeapCallbacks * cb,const void * user_data)545*795d594fSAndroid Build Coastguard Worker   ReportPrimitiveField(ObjectTagTable* tag_table,
546*795d594fSAndroid Build Coastguard Worker                        jlong class_tag,
547*795d594fSAndroid Build Coastguard Worker                        const jvmtiHeapCallbacks* cb,
548*795d594fSAndroid Build Coastguard Worker                        const void* user_data)
549*795d594fSAndroid Build Coastguard Worker       : tag_table_(tag_table), class_tag_(class_tag), cb_(cb), user_data_(user_data) {}
550*795d594fSAndroid Build Coastguard Worker 
551*795d594fSAndroid Build Coastguard Worker   template <bool kReportStatic>
ReportPrimitiveFieldCallback(art::ObjPtr<art::mirror::Object> obj,art::ObjPtr<art::mirror::Class> klass,art::ArtField & field,size_t field_index,ReportPrimitiveField * user_data)552*795d594fSAndroid Build Coastguard Worker   static bool ReportPrimitiveFieldCallback(art::ObjPtr<art::mirror::Object> obj,
553*795d594fSAndroid Build Coastguard Worker                                            art::ObjPtr<art::mirror::Class> klass,
554*795d594fSAndroid Build Coastguard Worker                                            art::ArtField& field,
555*795d594fSAndroid Build Coastguard Worker                                            size_t field_index,
556*795d594fSAndroid Build Coastguard Worker                                            ReportPrimitiveField* user_data)
557*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_) {
558*795d594fSAndroid Build Coastguard Worker     art::Primitive::Type art_prim_type = field.GetTypeAsPrimitiveType();
559*795d594fSAndroid Build Coastguard Worker     jvmtiPrimitiveType prim_type =
560*795d594fSAndroid Build Coastguard Worker         static_cast<jvmtiPrimitiveType>(art::Primitive::Descriptor(art_prim_type)[0]);
561*795d594fSAndroid Build Coastguard Worker     DCHECK(prim_type == JVMTI_PRIMITIVE_TYPE_BOOLEAN ||
562*795d594fSAndroid Build Coastguard Worker            prim_type == JVMTI_PRIMITIVE_TYPE_BYTE ||
563*795d594fSAndroid Build Coastguard Worker            prim_type == JVMTI_PRIMITIVE_TYPE_CHAR ||
564*795d594fSAndroid Build Coastguard Worker            prim_type == JVMTI_PRIMITIVE_TYPE_SHORT ||
565*795d594fSAndroid Build Coastguard Worker            prim_type == JVMTI_PRIMITIVE_TYPE_INT ||
566*795d594fSAndroid Build Coastguard Worker            prim_type == JVMTI_PRIMITIVE_TYPE_LONG ||
567*795d594fSAndroid Build Coastguard Worker            prim_type == JVMTI_PRIMITIVE_TYPE_FLOAT ||
568*795d594fSAndroid Build Coastguard Worker            prim_type == JVMTI_PRIMITIVE_TYPE_DOUBLE);
569*795d594fSAndroid Build Coastguard Worker     jvmtiHeapReferenceInfo info;
570*795d594fSAndroid Build Coastguard Worker     info.field.index = field_index;
571*795d594fSAndroid Build Coastguard Worker 
572*795d594fSAndroid Build Coastguard Worker     jvalue value;
573*795d594fSAndroid Build Coastguard Worker     memset(&value, 0, sizeof(jvalue));
574*795d594fSAndroid Build Coastguard Worker     art::ObjPtr<art::mirror::Object> src = kReportStatic ? klass : obj;
575*795d594fSAndroid Build Coastguard Worker     switch (art_prim_type) {
576*795d594fSAndroid Build Coastguard Worker       case art::Primitive::Type::kPrimBoolean:
577*795d594fSAndroid Build Coastguard Worker         value.z = field.GetBoolean(src) == 0 ? JNI_FALSE : JNI_TRUE;
578*795d594fSAndroid Build Coastguard Worker         break;
579*795d594fSAndroid Build Coastguard Worker       case art::Primitive::Type::kPrimByte:
580*795d594fSAndroid Build Coastguard Worker         value.b = field.GetByte(src);
581*795d594fSAndroid Build Coastguard Worker         break;
582*795d594fSAndroid Build Coastguard Worker       case art::Primitive::Type::kPrimChar:
583*795d594fSAndroid Build Coastguard Worker         value.c = field.GetChar(src);
584*795d594fSAndroid Build Coastguard Worker         break;
585*795d594fSAndroid Build Coastguard Worker       case art::Primitive::Type::kPrimShort:
586*795d594fSAndroid Build Coastguard Worker         value.s = field.GetShort(src);
587*795d594fSAndroid Build Coastguard Worker         break;
588*795d594fSAndroid Build Coastguard Worker       case art::Primitive::Type::kPrimInt:
589*795d594fSAndroid Build Coastguard Worker         value.i = field.GetInt(src);
590*795d594fSAndroid Build Coastguard Worker         break;
591*795d594fSAndroid Build Coastguard Worker       case art::Primitive::Type::kPrimLong:
592*795d594fSAndroid Build Coastguard Worker         value.j = field.GetLong(src);
593*795d594fSAndroid Build Coastguard Worker         break;
594*795d594fSAndroid Build Coastguard Worker       case art::Primitive::Type::kPrimFloat:
595*795d594fSAndroid Build Coastguard Worker         value.f = field.GetFloat(src);
596*795d594fSAndroid Build Coastguard Worker         break;
597*795d594fSAndroid Build Coastguard Worker       case art::Primitive::Type::kPrimDouble:
598*795d594fSAndroid Build Coastguard Worker         value.d = field.GetDouble(src);
599*795d594fSAndroid Build Coastguard Worker         break;
600*795d594fSAndroid Build Coastguard Worker       case art::Primitive::Type::kPrimVoid:
601*795d594fSAndroid Build Coastguard Worker       case art::Primitive::Type::kPrimNot: {
602*795d594fSAndroid Build Coastguard Worker         LOG(FATAL) << "Should not reach here";
603*795d594fSAndroid Build Coastguard Worker         UNREACHABLE();
604*795d594fSAndroid Build Coastguard Worker       }
605*795d594fSAndroid Build Coastguard Worker     }
606*795d594fSAndroid Build Coastguard Worker 
607*795d594fSAndroid Build Coastguard Worker     jlong obj_tag = user_data->tag_table_->GetTagOrZero(src.Ptr());
608*795d594fSAndroid Build Coastguard Worker     const jlong saved_obj_tag = obj_tag;
609*795d594fSAndroid Build Coastguard Worker 
610*795d594fSAndroid Build Coastguard Worker     jint ret = user_data->cb_->primitive_field_callback(kReportStatic
611*795d594fSAndroid Build Coastguard Worker                                                             ? JVMTI_HEAP_REFERENCE_STATIC_FIELD
612*795d594fSAndroid Build Coastguard Worker                                                             : JVMTI_HEAP_REFERENCE_FIELD,
613*795d594fSAndroid Build Coastguard Worker                                                         &info,
614*795d594fSAndroid Build Coastguard Worker                                                         user_data->class_tag_,
615*795d594fSAndroid Build Coastguard Worker                                                         &obj_tag,
616*795d594fSAndroid Build Coastguard Worker                                                         value,
617*795d594fSAndroid Build Coastguard Worker                                                         prim_type,
618*795d594fSAndroid Build Coastguard Worker                                                         const_cast<void*>(user_data->user_data_));
619*795d594fSAndroid Build Coastguard Worker 
620*795d594fSAndroid Build Coastguard Worker     if (saved_obj_tag != obj_tag) {
621*795d594fSAndroid Build Coastguard Worker       user_data->tag_table_->Set(src.Ptr(), obj_tag);
622*795d594fSAndroid Build Coastguard Worker     }
623*795d594fSAndroid Build Coastguard Worker 
624*795d594fSAndroid Build Coastguard Worker     if ((ret & JVMTI_VISIT_ABORT) != 0) {
625*795d594fSAndroid Build Coastguard Worker       return true;
626*795d594fSAndroid Build Coastguard Worker     }
627*795d594fSAndroid Build Coastguard Worker 
628*795d594fSAndroid Build Coastguard Worker     return false;
629*795d594fSAndroid Build Coastguard Worker   }
630*795d594fSAndroid Build Coastguard Worker 
631*795d594fSAndroid Build Coastguard Worker   ObjectTagTable* tag_table_;
632*795d594fSAndroid Build Coastguard Worker   jlong class_tag_;
633*795d594fSAndroid Build Coastguard Worker   const jvmtiHeapCallbacks* cb_;
634*795d594fSAndroid Build Coastguard Worker   const void* user_data_;
635*795d594fSAndroid Build Coastguard Worker };
636*795d594fSAndroid Build Coastguard Worker 
637*795d594fSAndroid Build Coastguard Worker struct HeapFilter {
HeapFilteropenjdkjvmti::__anon9790dd1d0111::HeapFilter638*795d594fSAndroid Build Coastguard Worker   explicit HeapFilter(jint heap_filter)
639*795d594fSAndroid Build Coastguard Worker       : filter_out_tagged((heap_filter & JVMTI_HEAP_FILTER_TAGGED) != 0),
640*795d594fSAndroid Build Coastguard Worker         filter_out_untagged((heap_filter & JVMTI_HEAP_FILTER_UNTAGGED) != 0),
641*795d594fSAndroid Build Coastguard Worker         filter_out_class_tagged((heap_filter & JVMTI_HEAP_FILTER_CLASS_TAGGED) != 0),
642*795d594fSAndroid Build Coastguard Worker         filter_out_class_untagged((heap_filter & JVMTI_HEAP_FILTER_CLASS_UNTAGGED) != 0),
643*795d594fSAndroid Build Coastguard Worker         any_filter(filter_out_tagged ||
644*795d594fSAndroid Build Coastguard Worker                    filter_out_untagged ||
645*795d594fSAndroid Build Coastguard Worker                    filter_out_class_tagged ||
646*795d594fSAndroid Build Coastguard Worker                    filter_out_class_untagged) {
647*795d594fSAndroid Build Coastguard Worker   }
648*795d594fSAndroid Build Coastguard Worker 
ShouldReportByHeapFilteropenjdkjvmti::__anon9790dd1d0111::HeapFilter649*795d594fSAndroid Build Coastguard Worker   bool ShouldReportByHeapFilter(jlong tag, jlong class_tag) const {
650*795d594fSAndroid Build Coastguard Worker     if (!any_filter) {
651*795d594fSAndroid Build Coastguard Worker       return true;
652*795d594fSAndroid Build Coastguard Worker     }
653*795d594fSAndroid Build Coastguard Worker 
654*795d594fSAndroid Build Coastguard Worker     if ((tag == 0 && filter_out_untagged) || (tag != 0 && filter_out_tagged)) {
655*795d594fSAndroid Build Coastguard Worker       return false;
656*795d594fSAndroid Build Coastguard Worker     }
657*795d594fSAndroid Build Coastguard Worker 
658*795d594fSAndroid Build Coastguard Worker     if ((class_tag == 0 && filter_out_class_untagged) ||
659*795d594fSAndroid Build Coastguard Worker         (class_tag != 0 && filter_out_class_tagged)) {
660*795d594fSAndroid Build Coastguard Worker       return false;
661*795d594fSAndroid Build Coastguard Worker     }
662*795d594fSAndroid Build Coastguard Worker 
663*795d594fSAndroid Build Coastguard Worker     return true;
664*795d594fSAndroid Build Coastguard Worker   }
665*795d594fSAndroid Build Coastguard Worker 
666*795d594fSAndroid Build Coastguard Worker   const bool filter_out_tagged;
667*795d594fSAndroid Build Coastguard Worker   const bool filter_out_untagged;
668*795d594fSAndroid Build Coastguard Worker   const bool filter_out_class_tagged;
669*795d594fSAndroid Build Coastguard Worker   const bool filter_out_class_untagged;
670*795d594fSAndroid Build Coastguard Worker   const bool any_filter;
671*795d594fSAndroid Build Coastguard Worker };
672*795d594fSAndroid Build Coastguard Worker 
673*795d594fSAndroid Build Coastguard Worker }  // namespace
674*795d594fSAndroid Build Coastguard Worker 
Register()675*795d594fSAndroid Build Coastguard Worker void HeapUtil::Register() {
676*795d594fSAndroid Build Coastguard Worker   art::Runtime::Current()->AddSystemWeakHolder(&gIndexCachingTable);
677*795d594fSAndroid Build Coastguard Worker }
678*795d594fSAndroid Build Coastguard Worker 
Unregister()679*795d594fSAndroid Build Coastguard Worker void HeapUtil::Unregister() {
680*795d594fSAndroid Build Coastguard Worker   art::Runtime::Current()->RemoveSystemWeakHolder(&gIndexCachingTable);
681*795d594fSAndroid Build Coastguard Worker }
682*795d594fSAndroid Build Coastguard Worker 
IterateOverInstancesOfClass(jvmtiEnv * env,jclass klass,jvmtiHeapObjectFilter filter,jvmtiHeapObjectCallback cb,const void * user_data)683*795d594fSAndroid Build Coastguard Worker jvmtiError HeapUtil::IterateOverInstancesOfClass(jvmtiEnv* env,
684*795d594fSAndroid Build Coastguard Worker                                                  jclass klass,
685*795d594fSAndroid Build Coastguard Worker                                                  jvmtiHeapObjectFilter filter,
686*795d594fSAndroid Build Coastguard Worker                                                  jvmtiHeapObjectCallback cb,
687*795d594fSAndroid Build Coastguard Worker                                                  const void* user_data) {
688*795d594fSAndroid Build Coastguard Worker   if (cb == nullptr || klass == nullptr) {
689*795d594fSAndroid Build Coastguard Worker     return ERR(NULL_POINTER);
690*795d594fSAndroid Build Coastguard Worker   }
691*795d594fSAndroid Build Coastguard Worker 
692*795d594fSAndroid Build Coastguard Worker   art::Thread* self = art::Thread::Current();
693*795d594fSAndroid Build Coastguard Worker   art::ScopedObjectAccess soa(self);      // Now we know we have the shared lock.
694*795d594fSAndroid Build Coastguard Worker   art::StackHandleScope<1> hs(self);
695*795d594fSAndroid Build Coastguard Worker 
696*795d594fSAndroid Build Coastguard Worker   art::ObjPtr<art::mirror::Object> klass_ptr(soa.Decode<art::mirror::Class>(klass));
697*795d594fSAndroid Build Coastguard Worker   if (!klass_ptr->IsClass()) {
698*795d594fSAndroid Build Coastguard Worker     return ERR(INVALID_CLASS);
699*795d594fSAndroid Build Coastguard Worker   }
700*795d594fSAndroid Build Coastguard Worker   art::Handle<art::mirror::Class> filter_klass(hs.NewHandle(klass_ptr->AsClass()));
701*795d594fSAndroid Build Coastguard Worker   ObjectTagTable* tag_table = ArtJvmTiEnv::AsArtJvmTiEnv(env)->object_tag_table.get();
702*795d594fSAndroid Build Coastguard Worker   bool stop_reports = false;
703*795d594fSAndroid Build Coastguard Worker   auto visitor = [&](art::mirror::Object* obj) REQUIRES_SHARED(art::Locks::mutator_lock_) {
704*795d594fSAndroid Build Coastguard Worker     // Early return, as we can't really stop visiting.
705*795d594fSAndroid Build Coastguard Worker     if (stop_reports) {
706*795d594fSAndroid Build Coastguard Worker       return;
707*795d594fSAndroid Build Coastguard Worker     }
708*795d594fSAndroid Build Coastguard Worker 
709*795d594fSAndroid Build Coastguard Worker     art::ScopedAssertNoThreadSuspension no_suspension("IterateOverInstancesOfClass");
710*795d594fSAndroid Build Coastguard Worker 
711*795d594fSAndroid Build Coastguard Worker     art::ObjPtr<art::mirror::Class> klass = obj->GetClass();
712*795d594fSAndroid Build Coastguard Worker 
713*795d594fSAndroid Build Coastguard Worker     if (filter_klass != nullptr && !filter_klass->IsAssignableFrom(klass)) {
714*795d594fSAndroid Build Coastguard Worker       return;
715*795d594fSAndroid Build Coastguard Worker     }
716*795d594fSAndroid Build Coastguard Worker 
717*795d594fSAndroid Build Coastguard Worker     jlong tag = 0;
718*795d594fSAndroid Build Coastguard Worker     tag_table->GetTag(obj, &tag);
719*795d594fSAndroid Build Coastguard Worker     if ((filter != JVMTI_HEAP_OBJECT_EITHER) &&
720*795d594fSAndroid Build Coastguard Worker         ((tag == 0 && filter == JVMTI_HEAP_OBJECT_TAGGED) ||
721*795d594fSAndroid Build Coastguard Worker          (tag != 0 && filter == JVMTI_HEAP_OBJECT_UNTAGGED))) {
722*795d594fSAndroid Build Coastguard Worker       return;
723*795d594fSAndroid Build Coastguard Worker     }
724*795d594fSAndroid Build Coastguard Worker 
725*795d594fSAndroid Build Coastguard Worker     jlong class_tag = 0;
726*795d594fSAndroid Build Coastguard Worker     tag_table->GetTag(klass.Ptr(), &class_tag);
727*795d594fSAndroid Build Coastguard Worker 
728*795d594fSAndroid Build Coastguard Worker     jlong saved_tag = tag;
729*795d594fSAndroid Build Coastguard Worker     jint ret = cb(class_tag, obj->SizeOf(), &tag, const_cast<void*>(user_data));
730*795d594fSAndroid Build Coastguard Worker 
731*795d594fSAndroid Build Coastguard Worker     stop_reports = (ret == JVMTI_ITERATION_ABORT);
732*795d594fSAndroid Build Coastguard Worker 
733*795d594fSAndroid Build Coastguard Worker     if (tag != saved_tag) {
734*795d594fSAndroid Build Coastguard Worker       tag_table->Set(obj, tag);
735*795d594fSAndroid Build Coastguard Worker     }
736*795d594fSAndroid Build Coastguard Worker   };
737*795d594fSAndroid Build Coastguard Worker   art::Runtime::Current()->GetHeap()->VisitObjects(visitor);
738*795d594fSAndroid Build Coastguard Worker 
739*795d594fSAndroid Build Coastguard Worker   return OK;
740*795d594fSAndroid Build Coastguard Worker }
741*795d594fSAndroid Build Coastguard Worker 
742*795d594fSAndroid Build Coastguard Worker template <typename T>
DoIterateThroughHeap(T fn,jvmtiEnv * env,ObjectTagTable * tag_table,jint heap_filter_int,jclass klass,const jvmtiHeapCallbacks * callbacks,const void * user_data)743*795d594fSAndroid Build Coastguard Worker static jvmtiError DoIterateThroughHeap(T fn,
744*795d594fSAndroid Build Coastguard Worker                                        jvmtiEnv* env,
745*795d594fSAndroid Build Coastguard Worker                                        ObjectTagTable* tag_table,
746*795d594fSAndroid Build Coastguard Worker                                        jint heap_filter_int,
747*795d594fSAndroid Build Coastguard Worker                                        jclass klass,
748*795d594fSAndroid Build Coastguard Worker                                        const jvmtiHeapCallbacks* callbacks,
749*795d594fSAndroid Build Coastguard Worker                                        const void* user_data) {
750*795d594fSAndroid Build Coastguard Worker   if (callbacks == nullptr) {
751*795d594fSAndroid Build Coastguard Worker     return ERR(NULL_POINTER);
752*795d594fSAndroid Build Coastguard Worker   }
753*795d594fSAndroid Build Coastguard Worker 
754*795d594fSAndroid Build Coastguard Worker   art::Thread* self = art::Thread::Current();
755*795d594fSAndroid Build Coastguard Worker   art::ScopedObjectAccess soa(self);      // Now we know we have the shared lock.
756*795d594fSAndroid Build Coastguard Worker 
757*795d594fSAndroid Build Coastguard Worker   bool stop_reports = false;
758*795d594fSAndroid Build Coastguard Worker   const HeapFilter heap_filter(heap_filter_int);
759*795d594fSAndroid Build Coastguard Worker   art::StackHandleScope<1> hs(self);
760*795d594fSAndroid Build Coastguard Worker   art::Handle<art::mirror::Class> filter_klass(hs.NewHandle(soa.Decode<art::mirror::Class>(klass)));
761*795d594fSAndroid Build Coastguard Worker   auto visitor = [&](art::mirror::Object* obj) REQUIRES_SHARED(art::Locks::mutator_lock_) {
762*795d594fSAndroid Build Coastguard Worker     // Early return, as we can't really stop visiting.
763*795d594fSAndroid Build Coastguard Worker     if (stop_reports) {
764*795d594fSAndroid Build Coastguard Worker       return;
765*795d594fSAndroid Build Coastguard Worker     }
766*795d594fSAndroid Build Coastguard Worker 
767*795d594fSAndroid Build Coastguard Worker     art::ScopedAssertNoThreadSuspension no_suspension("IterateThroughHeapCallback");
768*795d594fSAndroid Build Coastguard Worker 
769*795d594fSAndroid Build Coastguard Worker     jlong tag = 0;
770*795d594fSAndroid Build Coastguard Worker     tag_table->GetTag(obj, &tag);
771*795d594fSAndroid Build Coastguard Worker 
772*795d594fSAndroid Build Coastguard Worker     jlong class_tag = 0;
773*795d594fSAndroid Build Coastguard Worker     art::ObjPtr<art::mirror::Class> klass = obj->GetClass();
774*795d594fSAndroid Build Coastguard Worker     tag_table->GetTag(klass.Ptr(), &class_tag);
775*795d594fSAndroid Build Coastguard Worker     // For simplicity, even if we find a tag = 0, assume 0 = not tagged.
776*795d594fSAndroid Build Coastguard Worker 
777*795d594fSAndroid Build Coastguard Worker     if (!heap_filter.ShouldReportByHeapFilter(tag, class_tag)) {
778*795d594fSAndroid Build Coastguard Worker       return;
779*795d594fSAndroid Build Coastguard Worker     }
780*795d594fSAndroid Build Coastguard Worker 
781*795d594fSAndroid Build Coastguard Worker     if (filter_klass != nullptr) {
782*795d594fSAndroid Build Coastguard Worker       if (filter_klass.Get() != klass) {
783*795d594fSAndroid Build Coastguard Worker         return;
784*795d594fSAndroid Build Coastguard Worker       }
785*795d594fSAndroid Build Coastguard Worker     }
786*795d594fSAndroid Build Coastguard Worker 
787*795d594fSAndroid Build Coastguard Worker     jlong size = obj->SizeOf();
788*795d594fSAndroid Build Coastguard Worker 
789*795d594fSAndroid Build Coastguard Worker     jint length = -1;
790*795d594fSAndroid Build Coastguard Worker     if (obj->IsArrayInstance()) {
791*795d594fSAndroid Build Coastguard Worker       length = obj->AsArray()->GetLength();
792*795d594fSAndroid Build Coastguard Worker     }
793*795d594fSAndroid Build Coastguard Worker 
794*795d594fSAndroid Build Coastguard Worker     jlong saved_tag = tag;
795*795d594fSAndroid Build Coastguard Worker     jint ret = fn(obj, callbacks, class_tag, size, &tag, length, const_cast<void*>(user_data));
796*795d594fSAndroid Build Coastguard Worker 
797*795d594fSAndroid Build Coastguard Worker     if (tag != saved_tag) {
798*795d594fSAndroid Build Coastguard Worker       tag_table->Set(obj, tag);
799*795d594fSAndroid Build Coastguard Worker     }
800*795d594fSAndroid Build Coastguard Worker 
801*795d594fSAndroid Build Coastguard Worker     stop_reports = (ret & JVMTI_VISIT_ABORT) != 0;
802*795d594fSAndroid Build Coastguard Worker 
803*795d594fSAndroid Build Coastguard Worker     if (!stop_reports) {
804*795d594fSAndroid Build Coastguard Worker       jint string_ret = ReportString(obj, env, tag_table, callbacks, user_data);
805*795d594fSAndroid Build Coastguard Worker       stop_reports = (string_ret & JVMTI_VISIT_ABORT) != 0;
806*795d594fSAndroid Build Coastguard Worker     }
807*795d594fSAndroid Build Coastguard Worker 
808*795d594fSAndroid Build Coastguard Worker     if (!stop_reports) {
809*795d594fSAndroid Build Coastguard Worker       jint array_ret = ReportPrimitiveArray(obj, env, tag_table, callbacks, user_data);
810*795d594fSAndroid Build Coastguard Worker       stop_reports = (array_ret & JVMTI_VISIT_ABORT) != 0;
811*795d594fSAndroid Build Coastguard Worker     }
812*795d594fSAndroid Build Coastguard Worker 
813*795d594fSAndroid Build Coastguard Worker     if (!stop_reports) {
814*795d594fSAndroid Build Coastguard Worker       stop_reports = ReportPrimitiveField::Report(obj, tag_table, callbacks, user_data);
815*795d594fSAndroid Build Coastguard Worker     }
816*795d594fSAndroid Build Coastguard Worker   };
817*795d594fSAndroid Build Coastguard Worker   art::Runtime::Current()->GetHeap()->VisitObjects(visitor);
818*795d594fSAndroid Build Coastguard Worker 
819*795d594fSAndroid Build Coastguard Worker   return ERR(NONE);
820*795d594fSAndroid Build Coastguard Worker }
821*795d594fSAndroid Build Coastguard Worker 
IterateThroughHeap(jvmtiEnv * env,jint heap_filter,jclass klass,const jvmtiHeapCallbacks * callbacks,const void * user_data)822*795d594fSAndroid Build Coastguard Worker jvmtiError HeapUtil::IterateThroughHeap(jvmtiEnv* env,
823*795d594fSAndroid Build Coastguard Worker                                         jint heap_filter,
824*795d594fSAndroid Build Coastguard Worker                                         jclass klass,
825*795d594fSAndroid Build Coastguard Worker                                         const jvmtiHeapCallbacks* callbacks,
826*795d594fSAndroid Build Coastguard Worker                                         const void* user_data) {
827*795d594fSAndroid Build Coastguard Worker   auto JvmtiIterateHeap = []([[maybe_unused]] art::mirror::Object* obj,
828*795d594fSAndroid Build Coastguard Worker                              const jvmtiHeapCallbacks* cb_callbacks,
829*795d594fSAndroid Build Coastguard Worker                              jlong class_tag,
830*795d594fSAndroid Build Coastguard Worker                              jlong size,
831*795d594fSAndroid Build Coastguard Worker                              jlong* tag,
832*795d594fSAndroid Build Coastguard Worker                              jint length,
833*795d594fSAndroid Build Coastguard Worker                              void* cb_user_data) REQUIRES_SHARED(art::Locks::mutator_lock_) {
834*795d594fSAndroid Build Coastguard Worker     return cb_callbacks->heap_iteration_callback(class_tag,
835*795d594fSAndroid Build Coastguard Worker                                                  size,
836*795d594fSAndroid Build Coastguard Worker                                                  tag,
837*795d594fSAndroid Build Coastguard Worker                                                  length,
838*795d594fSAndroid Build Coastguard Worker                                                  cb_user_data);
839*795d594fSAndroid Build Coastguard Worker   };
840*795d594fSAndroid Build Coastguard Worker   return DoIterateThroughHeap(JvmtiIterateHeap,
841*795d594fSAndroid Build Coastguard Worker                               env,
842*795d594fSAndroid Build Coastguard Worker                               ArtJvmTiEnv::AsArtJvmTiEnv(env)->object_tag_table.get(),
843*795d594fSAndroid Build Coastguard Worker                               heap_filter,
844*795d594fSAndroid Build Coastguard Worker                               klass,
845*795d594fSAndroid Build Coastguard Worker                               callbacks,
846*795d594fSAndroid Build Coastguard Worker                               user_data);
847*795d594fSAndroid Build Coastguard Worker }
848*795d594fSAndroid Build Coastguard Worker 
849*795d594fSAndroid Build Coastguard Worker class FollowReferencesHelper final {
850*795d594fSAndroid Build Coastguard Worker  public:
FollowReferencesHelper(HeapUtil * h,jvmtiEnv * jvmti_env,art::ObjPtr<art::mirror::Object> initial_object,const jvmtiHeapCallbacks * callbacks,art::ObjPtr<art::mirror::Class> class_filter,jint heap_filter,const void * user_data)851*795d594fSAndroid Build Coastguard Worker   FollowReferencesHelper(HeapUtil* h,
852*795d594fSAndroid Build Coastguard Worker                          jvmtiEnv* jvmti_env,
853*795d594fSAndroid Build Coastguard Worker                          art::ObjPtr<art::mirror::Object> initial_object,
854*795d594fSAndroid Build Coastguard Worker                          const jvmtiHeapCallbacks* callbacks,
855*795d594fSAndroid Build Coastguard Worker                          art::ObjPtr<art::mirror::Class> class_filter,
856*795d594fSAndroid Build Coastguard Worker                          jint heap_filter,
857*795d594fSAndroid Build Coastguard Worker                          const void* user_data)
858*795d594fSAndroid Build Coastguard Worker       : env(jvmti_env),
859*795d594fSAndroid Build Coastguard Worker         tag_table_(h->GetTags()),
860*795d594fSAndroid Build Coastguard Worker         initial_object_(initial_object),
861*795d594fSAndroid Build Coastguard Worker         callbacks_(callbacks),
862*795d594fSAndroid Build Coastguard Worker         class_filter_(class_filter),
863*795d594fSAndroid Build Coastguard Worker         heap_filter_(heap_filter),
864*795d594fSAndroid Build Coastguard Worker         user_data_(user_data),
865*795d594fSAndroid Build Coastguard Worker         start_(0),
866*795d594fSAndroid Build Coastguard Worker         stop_reports_(false) {
867*795d594fSAndroid Build Coastguard Worker   }
868*795d594fSAndroid Build Coastguard Worker 
Init()869*795d594fSAndroid Build Coastguard Worker   void Init()
870*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_)
871*795d594fSAndroid Build Coastguard Worker       REQUIRES(!*tag_table_->GetAllowDisallowLock()) {
872*795d594fSAndroid Build Coastguard Worker     if (initial_object_.IsNull()) {
873*795d594fSAndroid Build Coastguard Worker       CollectAndReportRootsVisitor carrv(this, tag_table_, &worklist_, &visited_);
874*795d594fSAndroid Build Coastguard Worker 
875*795d594fSAndroid Build Coastguard Worker       // We need precise info (e.g., vregs).
876*795d594fSAndroid Build Coastguard Worker       constexpr art::VisitRootFlags kRootFlags = static_cast<art::VisitRootFlags>(
877*795d594fSAndroid Build Coastguard Worker           art::VisitRootFlags::kVisitRootFlagAllRoots | art::VisitRootFlags::kVisitRootFlagPrecise);
878*795d594fSAndroid Build Coastguard Worker       art::Runtime::Current()->VisitRoots(&carrv, kRootFlags);
879*795d594fSAndroid Build Coastguard Worker 
880*795d594fSAndroid Build Coastguard Worker       art::Runtime::Current()->VisitImageRoots(&carrv);
881*795d594fSAndroid Build Coastguard Worker       stop_reports_ = carrv.IsStopReports();
882*795d594fSAndroid Build Coastguard Worker 
883*795d594fSAndroid Build Coastguard Worker       if (stop_reports_) {
884*795d594fSAndroid Build Coastguard Worker         worklist_.clear();
885*795d594fSAndroid Build Coastguard Worker       }
886*795d594fSAndroid Build Coastguard Worker     } else {
887*795d594fSAndroid Build Coastguard Worker       visited_.insert(initial_object_.Ptr());
888*795d594fSAndroid Build Coastguard Worker       worklist_.push_back(initial_object_.Ptr());
889*795d594fSAndroid Build Coastguard Worker     }
890*795d594fSAndroid Build Coastguard Worker   }
891*795d594fSAndroid Build Coastguard Worker 
Work()892*795d594fSAndroid Build Coastguard Worker   void Work()
893*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_)
894*795d594fSAndroid Build Coastguard Worker       REQUIRES(!*tag_table_->GetAllowDisallowLock()) {
895*795d594fSAndroid Build Coastguard Worker     // Currently implemented as a BFS. To lower overhead, we don't erase elements immediately
896*795d594fSAndroid Build Coastguard Worker     // from the head of the work list, instead postponing until there's a gap that's "large."
897*795d594fSAndroid Build Coastguard Worker     //
898*795d594fSAndroid Build Coastguard Worker     // Alternatively, we can implement a DFS and use the work list as a stack.
899*795d594fSAndroid Build Coastguard Worker     while (start_ < worklist_.size()) {
900*795d594fSAndroid Build Coastguard Worker       art::mirror::Object* cur_obj = worklist_[start_];
901*795d594fSAndroid Build Coastguard Worker       start_++;
902*795d594fSAndroid Build Coastguard Worker 
903*795d594fSAndroid Build Coastguard Worker       if (start_ >= kMaxStart) {
904*795d594fSAndroid Build Coastguard Worker         worklist_.erase(worklist_.begin(), worklist_.begin() + start_);
905*795d594fSAndroid Build Coastguard Worker         start_ = 0;
906*795d594fSAndroid Build Coastguard Worker       }
907*795d594fSAndroid Build Coastguard Worker 
908*795d594fSAndroid Build Coastguard Worker       VisitObject(cur_obj);
909*795d594fSAndroid Build Coastguard Worker 
910*795d594fSAndroid Build Coastguard Worker       if (stop_reports_) {
911*795d594fSAndroid Build Coastguard Worker         break;
912*795d594fSAndroid Build Coastguard Worker       }
913*795d594fSAndroid Build Coastguard Worker     }
914*795d594fSAndroid Build Coastguard Worker   }
915*795d594fSAndroid Build Coastguard Worker 
916*795d594fSAndroid Build Coastguard Worker  private:
917*795d594fSAndroid Build Coastguard Worker   class CollectAndReportRootsVisitor final : public art::RootVisitor {
918*795d594fSAndroid Build Coastguard Worker    public:
CollectAndReportRootsVisitor(FollowReferencesHelper * helper,ObjectTagTable * tag_table,std::vector<art::mirror::Object * > * worklist,std::unordered_set<art::mirror::Object * > * visited)919*795d594fSAndroid Build Coastguard Worker     CollectAndReportRootsVisitor(FollowReferencesHelper* helper,
920*795d594fSAndroid Build Coastguard Worker                                  ObjectTagTable* tag_table,
921*795d594fSAndroid Build Coastguard Worker                                  std::vector<art::mirror::Object*>* worklist,
922*795d594fSAndroid Build Coastguard Worker                                  std::unordered_set<art::mirror::Object*>* visited)
923*795d594fSAndroid Build Coastguard Worker         : helper_(helper),
924*795d594fSAndroid Build Coastguard Worker           tag_table_(tag_table),
925*795d594fSAndroid Build Coastguard Worker           worklist_(worklist),
926*795d594fSAndroid Build Coastguard Worker           visited_(visited),
927*795d594fSAndroid Build Coastguard Worker           stop_reports_(false) {}
928*795d594fSAndroid Build Coastguard Worker 
VisitRoots(art::mirror::Object *** roots,size_t count,const art::RootInfo & info)929*795d594fSAndroid Build Coastguard Worker     void VisitRoots(art::mirror::Object*** roots, size_t count, const art::RootInfo& info)
930*795d594fSAndroid Build Coastguard Worker         override
931*795d594fSAndroid Build Coastguard Worker         REQUIRES_SHARED(art::Locks::mutator_lock_)
932*795d594fSAndroid Build Coastguard Worker         REQUIRES(!*helper_->tag_table_->GetAllowDisallowLock()) {
933*795d594fSAndroid Build Coastguard Worker       for (size_t i = 0; i != count; ++i) {
934*795d594fSAndroid Build Coastguard Worker         AddRoot(*roots[i], info);
935*795d594fSAndroid Build Coastguard Worker       }
936*795d594fSAndroid Build Coastguard Worker     }
937*795d594fSAndroid Build Coastguard Worker 
VisitRoots(art::mirror::CompressedReference<art::mirror::Object> ** roots,size_t count,const art::RootInfo & info)938*795d594fSAndroid Build Coastguard Worker     void VisitRoots(art::mirror::CompressedReference<art::mirror::Object>** roots,
939*795d594fSAndroid Build Coastguard Worker                     size_t count,
940*795d594fSAndroid Build Coastguard Worker                     const art::RootInfo& info)
941*795d594fSAndroid Build Coastguard Worker         override REQUIRES_SHARED(art::Locks::mutator_lock_)
942*795d594fSAndroid Build Coastguard Worker         REQUIRES(!*helper_->tag_table_->GetAllowDisallowLock()) {
943*795d594fSAndroid Build Coastguard Worker       for (size_t i = 0; i != count; ++i) {
944*795d594fSAndroid Build Coastguard Worker         AddRoot(roots[i]->AsMirrorPtr(), info);
945*795d594fSAndroid Build Coastguard Worker       }
946*795d594fSAndroid Build Coastguard Worker     }
947*795d594fSAndroid Build Coastguard Worker 
IsStopReports()948*795d594fSAndroid Build Coastguard Worker     bool IsStopReports() {
949*795d594fSAndroid Build Coastguard Worker       return stop_reports_;
950*795d594fSAndroid Build Coastguard Worker     }
951*795d594fSAndroid Build Coastguard Worker 
952*795d594fSAndroid Build Coastguard Worker    private:
AddRoot(art::mirror::Object * root_obj,const art::RootInfo & info)953*795d594fSAndroid Build Coastguard Worker     void AddRoot(art::mirror::Object* root_obj, const art::RootInfo& info)
954*795d594fSAndroid Build Coastguard Worker         REQUIRES_SHARED(art::Locks::mutator_lock_)
955*795d594fSAndroid Build Coastguard Worker         REQUIRES(!*tag_table_->GetAllowDisallowLock()) {
956*795d594fSAndroid Build Coastguard Worker       if (stop_reports_) {
957*795d594fSAndroid Build Coastguard Worker         return;
958*795d594fSAndroid Build Coastguard Worker       }
959*795d594fSAndroid Build Coastguard Worker       bool add_to_worklist = ReportRoot(root_obj, info);
960*795d594fSAndroid Build Coastguard Worker       // We use visited_ to mark roots already so we do not need another set.
961*795d594fSAndroid Build Coastguard Worker       if (visited_->find(root_obj) == visited_->end()) {
962*795d594fSAndroid Build Coastguard Worker         if (add_to_worklist) {
963*795d594fSAndroid Build Coastguard Worker           visited_->insert(root_obj);
964*795d594fSAndroid Build Coastguard Worker           worklist_->push_back(root_obj);
965*795d594fSAndroid Build Coastguard Worker         }
966*795d594fSAndroid Build Coastguard Worker       }
967*795d594fSAndroid Build Coastguard Worker     }
968*795d594fSAndroid Build Coastguard Worker 
969*795d594fSAndroid Build Coastguard Worker     // Remove NO_THREAD_SAFETY_ANALYSIS once ASSERT_CAPABILITY works correctly.
FindThread(const art::RootInfo & info)970*795d594fSAndroid Build Coastguard Worker     art::Thread* FindThread(const art::RootInfo& info) NO_THREAD_SAFETY_ANALYSIS {
971*795d594fSAndroid Build Coastguard Worker       art::Locks::thread_list_lock_->AssertExclusiveHeld(art::Thread::Current());
972*795d594fSAndroid Build Coastguard Worker       return art::Runtime::Current()->GetThreadList()->FindThreadByThreadId(info.GetThreadId());
973*795d594fSAndroid Build Coastguard Worker     }
974*795d594fSAndroid Build Coastguard Worker 
GetReferenceKind(const art::RootInfo & info,jvmtiHeapReferenceInfo * ref_info)975*795d594fSAndroid Build Coastguard Worker     jvmtiHeapReferenceKind GetReferenceKind(const art::RootInfo& info,
976*795d594fSAndroid Build Coastguard Worker                                             jvmtiHeapReferenceInfo* ref_info)
977*795d594fSAndroid Build Coastguard Worker         REQUIRES_SHARED(art::Locks::mutator_lock_) {
978*795d594fSAndroid Build Coastguard Worker       // We do not necessarily hold thread_list_lock_ here, but we may if we are called from
979*795d594fSAndroid Build Coastguard Worker       // VisitThreadRoots, which can happen from JVMTI FollowReferences. If it was acquired in
980*795d594fSAndroid Build Coastguard Worker       // ThreadList::VisitRoots, it's unsafe to temporarily release it. Thus we act as if we did
981*795d594fSAndroid Build Coastguard Worker       // not hold the thread_list_lock_ here, and relax CHECKs appropriately. If it does happen,
982*795d594fSAndroid Build Coastguard Worker       // we are in a SuspendAll situation with concurrent GC disabled, and should not need to run
983*795d594fSAndroid Build Coastguard Worker       // flip functions. TODO: Find a way to clean this up.
984*795d594fSAndroid Build Coastguard Worker 
985*795d594fSAndroid Build Coastguard Worker       // TODO: Fill in ref_info.
986*795d594fSAndroid Build Coastguard Worker       memset(ref_info, 0, sizeof(jvmtiHeapReferenceInfo));
987*795d594fSAndroid Build Coastguard Worker 
988*795d594fSAndroid Build Coastguard Worker       switch (info.GetType()) {
989*795d594fSAndroid Build Coastguard Worker         case art::RootType::kRootJNIGlobal:
990*795d594fSAndroid Build Coastguard Worker           return JVMTI_HEAP_REFERENCE_JNI_GLOBAL;
991*795d594fSAndroid Build Coastguard Worker 
992*795d594fSAndroid Build Coastguard Worker         case art::RootType::kRootJNILocal:
993*795d594fSAndroid Build Coastguard Worker         {
994*795d594fSAndroid Build Coastguard Worker           uint32_t thread_id = info.GetThreadId();
995*795d594fSAndroid Build Coastguard Worker           ref_info->jni_local.thread_id = thread_id;
996*795d594fSAndroid Build Coastguard Worker 
997*795d594fSAndroid Build Coastguard Worker           art::Thread* thread = FindThread(info);
998*795d594fSAndroid Build Coastguard Worker           if (thread != nullptr) {
999*795d594fSAndroid Build Coastguard Worker             art::mirror::Object* thread_obj;
1000*795d594fSAndroid Build Coastguard Worker             if (thread->IsStillStarting()) {
1001*795d594fSAndroid Build Coastguard Worker               thread_obj = nullptr;
1002*795d594fSAndroid Build Coastguard Worker             } else {
1003*795d594fSAndroid Build Coastguard Worker               thread_obj = thread->GetPeerFromOtherThread();
1004*795d594fSAndroid Build Coastguard Worker             }
1005*795d594fSAndroid Build Coastguard Worker             if (thread_obj != nullptr) {
1006*795d594fSAndroid Build Coastguard Worker               ref_info->jni_local.thread_tag = tag_table_->GetTagOrZero(thread_obj);
1007*795d594fSAndroid Build Coastguard Worker             }
1008*795d594fSAndroid Build Coastguard Worker           }
1009*795d594fSAndroid Build Coastguard Worker 
1010*795d594fSAndroid Build Coastguard Worker           // TODO: We don't have this info.
1011*795d594fSAndroid Build Coastguard Worker           if (thread != nullptr) {
1012*795d594fSAndroid Build Coastguard Worker             ref_info->jni_local.depth = 0;
1013*795d594fSAndroid Build Coastguard Worker             art::ArtMethod* method = thread->GetCurrentMethod(nullptr,
1014*795d594fSAndroid Build Coastguard Worker                                                               /* check_suspended= */ true,
1015*795d594fSAndroid Build Coastguard Worker                                                               /* abort_on_error= */ false);
1016*795d594fSAndroid Build Coastguard Worker             if (method != nullptr) {
1017*795d594fSAndroid Build Coastguard Worker               ref_info->jni_local.method = art::jni::EncodeArtMethod(method);
1018*795d594fSAndroid Build Coastguard Worker             }
1019*795d594fSAndroid Build Coastguard Worker           }
1020*795d594fSAndroid Build Coastguard Worker 
1021*795d594fSAndroid Build Coastguard Worker           return JVMTI_HEAP_REFERENCE_JNI_LOCAL;
1022*795d594fSAndroid Build Coastguard Worker         }
1023*795d594fSAndroid Build Coastguard Worker 
1024*795d594fSAndroid Build Coastguard Worker         case art::RootType::kRootJavaFrame:
1025*795d594fSAndroid Build Coastguard Worker         {
1026*795d594fSAndroid Build Coastguard Worker           uint32_t thread_id = info.GetThreadId();
1027*795d594fSAndroid Build Coastguard Worker           ref_info->stack_local.thread_id = thread_id;
1028*795d594fSAndroid Build Coastguard Worker 
1029*795d594fSAndroid Build Coastguard Worker           art::Thread* thread = FindThread(info);
1030*795d594fSAndroid Build Coastguard Worker           if (thread != nullptr) {
1031*795d594fSAndroid Build Coastguard Worker             art::mirror::Object* thread_obj;
1032*795d594fSAndroid Build Coastguard Worker             if (thread->IsStillStarting()) {
1033*795d594fSAndroid Build Coastguard Worker               thread_obj = nullptr;
1034*795d594fSAndroid Build Coastguard Worker             } else {
1035*795d594fSAndroid Build Coastguard Worker               thread_obj = thread->GetPeerFromOtherThread();
1036*795d594fSAndroid Build Coastguard Worker             }
1037*795d594fSAndroid Build Coastguard Worker             if (thread_obj != nullptr) {
1038*795d594fSAndroid Build Coastguard Worker               ref_info->stack_local.thread_tag = tag_table_->GetTagOrZero(thread_obj);
1039*795d594fSAndroid Build Coastguard Worker             }
1040*795d594fSAndroid Build Coastguard Worker           }
1041*795d594fSAndroid Build Coastguard Worker 
1042*795d594fSAndroid Build Coastguard Worker           auto& java_info = static_cast<const art::JavaFrameRootInfo&>(info);
1043*795d594fSAndroid Build Coastguard Worker           size_t vreg = java_info.GetVReg();
1044*795d594fSAndroid Build Coastguard Worker           ref_info->stack_local.slot = static_cast<jint>(
1045*795d594fSAndroid Build Coastguard Worker               vreg <= art::JavaFrameRootInfo::kMaxVReg ? vreg : -1);
1046*795d594fSAndroid Build Coastguard Worker           const art::StackVisitor* visitor = java_info.GetVisitor();
1047*795d594fSAndroid Build Coastguard Worker           ref_info->stack_local.location =
1048*795d594fSAndroid Build Coastguard Worker               static_cast<jlocation>(visitor->GetDexPc(/* abort_on_failure= */ false));
1049*795d594fSAndroid Build Coastguard Worker           ref_info->stack_local.depth = static_cast<jint>(visitor->GetFrameDepth());
1050*795d594fSAndroid Build Coastguard Worker           art::ArtMethod* method = visitor->GetMethod();
1051*795d594fSAndroid Build Coastguard Worker           if (method != nullptr) {
1052*795d594fSAndroid Build Coastguard Worker             ref_info->stack_local.method = art::jni::EncodeArtMethod(method);
1053*795d594fSAndroid Build Coastguard Worker           }
1054*795d594fSAndroid Build Coastguard Worker 
1055*795d594fSAndroid Build Coastguard Worker           return JVMTI_HEAP_REFERENCE_STACK_LOCAL;
1056*795d594fSAndroid Build Coastguard Worker         }
1057*795d594fSAndroid Build Coastguard Worker 
1058*795d594fSAndroid Build Coastguard Worker         case art::RootType::kRootNativeStack:
1059*795d594fSAndroid Build Coastguard Worker         case art::RootType::kRootThreadBlock:
1060*795d594fSAndroid Build Coastguard Worker         case art::RootType::kRootThreadObject:
1061*795d594fSAndroid Build Coastguard Worker           return JVMTI_HEAP_REFERENCE_THREAD;
1062*795d594fSAndroid Build Coastguard Worker 
1063*795d594fSAndroid Build Coastguard Worker         case art::RootType::kRootStickyClass:
1064*795d594fSAndroid Build Coastguard Worker         case art::RootType::kRootInternedString:
1065*795d594fSAndroid Build Coastguard Worker           // Note: this isn't a root in the RI.
1066*795d594fSAndroid Build Coastguard Worker           return JVMTI_HEAP_REFERENCE_SYSTEM_CLASS;
1067*795d594fSAndroid Build Coastguard Worker 
1068*795d594fSAndroid Build Coastguard Worker         case art::RootType::kRootMonitorUsed:
1069*795d594fSAndroid Build Coastguard Worker         case art::RootType::kRootJNIMonitor:
1070*795d594fSAndroid Build Coastguard Worker           return JVMTI_HEAP_REFERENCE_MONITOR;
1071*795d594fSAndroid Build Coastguard Worker 
1072*795d594fSAndroid Build Coastguard Worker         case art::RootType::kRootFinalizing:
1073*795d594fSAndroid Build Coastguard Worker         case art::RootType::kRootDebugger:
1074*795d594fSAndroid Build Coastguard Worker         case art::RootType::kRootReferenceCleanup:
1075*795d594fSAndroid Build Coastguard Worker         case art::RootType::kRootVMInternal:
1076*795d594fSAndroid Build Coastguard Worker         case art::RootType::kRootUnknown:
1077*795d594fSAndroid Build Coastguard Worker           return JVMTI_HEAP_REFERENCE_OTHER;
1078*795d594fSAndroid Build Coastguard Worker       }
1079*795d594fSAndroid Build Coastguard Worker       LOG(FATAL) << "Unreachable";
1080*795d594fSAndroid Build Coastguard Worker       UNREACHABLE();
1081*795d594fSAndroid Build Coastguard Worker     }
1082*795d594fSAndroid Build Coastguard Worker 
ReportRoot(art::mirror::Object * root_obj,const art::RootInfo & info)1083*795d594fSAndroid Build Coastguard Worker     bool ReportRoot(art::mirror::Object* root_obj, const art::RootInfo& info)
1084*795d594fSAndroid Build Coastguard Worker         REQUIRES_SHARED(art::Locks::mutator_lock_)
1085*795d594fSAndroid Build Coastguard Worker         REQUIRES(!*tag_table_->GetAllowDisallowLock()) {
1086*795d594fSAndroid Build Coastguard Worker       jvmtiHeapReferenceInfo ref_info;
1087*795d594fSAndroid Build Coastguard Worker       jvmtiHeapReferenceKind kind = GetReferenceKind(info, &ref_info);
1088*795d594fSAndroid Build Coastguard Worker       jint result = helper_->ReportReference(kind, &ref_info, nullptr, root_obj);
1089*795d594fSAndroid Build Coastguard Worker       if ((result & JVMTI_VISIT_ABORT) != 0) {
1090*795d594fSAndroid Build Coastguard Worker         stop_reports_ = true;
1091*795d594fSAndroid Build Coastguard Worker       }
1092*795d594fSAndroid Build Coastguard Worker       return (result & JVMTI_VISIT_OBJECTS) != 0;
1093*795d594fSAndroid Build Coastguard Worker     }
1094*795d594fSAndroid Build Coastguard Worker 
1095*795d594fSAndroid Build Coastguard Worker    private:
1096*795d594fSAndroid Build Coastguard Worker     FollowReferencesHelper* helper_;
1097*795d594fSAndroid Build Coastguard Worker     ObjectTagTable* tag_table_;
1098*795d594fSAndroid Build Coastguard Worker     std::vector<art::mirror::Object*>* worklist_;
1099*795d594fSAndroid Build Coastguard Worker     std::unordered_set<art::mirror::Object*>* visited_;
1100*795d594fSAndroid Build Coastguard Worker     bool stop_reports_;
1101*795d594fSAndroid Build Coastguard Worker   };
1102*795d594fSAndroid Build Coastguard Worker 
VisitObject(art::mirror::Object * obj)1103*795d594fSAndroid Build Coastguard Worker   void VisitObject(art::mirror::Object* obj)
1104*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_)
1105*795d594fSAndroid Build Coastguard Worker       REQUIRES(!*tag_table_->GetAllowDisallowLock()) {
1106*795d594fSAndroid Build Coastguard Worker     if (obj->IsClass()) {
1107*795d594fSAndroid Build Coastguard Worker       VisitClass(obj->AsClass().Ptr());
1108*795d594fSAndroid Build Coastguard Worker       return;
1109*795d594fSAndroid Build Coastguard Worker     }
1110*795d594fSAndroid Build Coastguard Worker     if (obj->IsArrayInstance()) {
1111*795d594fSAndroid Build Coastguard Worker       VisitArray(obj);
1112*795d594fSAndroid Build Coastguard Worker       return;
1113*795d594fSAndroid Build Coastguard Worker     }
1114*795d594fSAndroid Build Coastguard Worker 
1115*795d594fSAndroid Build Coastguard Worker     // All instance fields.
1116*795d594fSAndroid Build Coastguard Worker     auto report_instance_field =
1117*795d594fSAndroid Build Coastguard Worker         [&](art::ObjPtr<art::mirror::Object> src,
1118*795d594fSAndroid Build Coastguard Worker             [[maybe_unused]] art::ObjPtr<art::mirror::Class> obj_klass,
1119*795d594fSAndroid Build Coastguard Worker             art::ArtField& field,
1120*795d594fSAndroid Build Coastguard Worker             size_t field_index,
1121*795d594fSAndroid Build Coastguard Worker             [[maybe_unused]] void* user_data) REQUIRES_SHARED(art::Locks::mutator_lock_)
1122*795d594fSAndroid Build Coastguard Worker             REQUIRES(!*tag_table_->GetAllowDisallowLock()) {
1123*795d594fSAndroid Build Coastguard Worker               art::ObjPtr<art::mirror::Object> field_value = field.GetObject(src);
1124*795d594fSAndroid Build Coastguard Worker               if (field_value != nullptr) {
1125*795d594fSAndroid Build Coastguard Worker                 jvmtiHeapReferenceInfo reference_info;
1126*795d594fSAndroid Build Coastguard Worker                 memset(&reference_info, 0, sizeof(reference_info));
1127*795d594fSAndroid Build Coastguard Worker 
1128*795d594fSAndroid Build Coastguard Worker                 reference_info.field.index = field_index;
1129*795d594fSAndroid Build Coastguard Worker 
1130*795d594fSAndroid Build Coastguard Worker                 jvmtiHeapReferenceKind kind =
1131*795d594fSAndroid Build Coastguard Worker                     field.GetOffset().Int32Value() ==
1132*795d594fSAndroid Build Coastguard Worker                             art::mirror::Object::ClassOffset().Int32Value() ?
1133*795d594fSAndroid Build Coastguard Worker                         JVMTI_HEAP_REFERENCE_CLASS :
1134*795d594fSAndroid Build Coastguard Worker                         JVMTI_HEAP_REFERENCE_FIELD;
1135*795d594fSAndroid Build Coastguard Worker                 const jvmtiHeapReferenceInfo* reference_info_ptr =
1136*795d594fSAndroid Build Coastguard Worker                     kind == JVMTI_HEAP_REFERENCE_CLASS ? nullptr : &reference_info;
1137*795d594fSAndroid Build Coastguard Worker 
1138*795d594fSAndroid Build Coastguard Worker                 return !ReportReferenceMaybeEnqueue(
1139*795d594fSAndroid Build Coastguard Worker                     kind, reference_info_ptr, src.Ptr(), field_value.Ptr());
1140*795d594fSAndroid Build Coastguard Worker               }
1141*795d594fSAndroid Build Coastguard Worker               return false;
1142*795d594fSAndroid Build Coastguard Worker             };
1143*795d594fSAndroid Build Coastguard Worker     stop_reports_ = FieldVisitor<void, true>::ReportFields(obj,
1144*795d594fSAndroid Build Coastguard Worker                                                            nullptr,
1145*795d594fSAndroid Build Coastguard Worker                                                            VisitorFalse<void>,
1146*795d594fSAndroid Build Coastguard Worker                                                            VisitorFalse<void>,
1147*795d594fSAndroid Build Coastguard Worker                                                            VisitorFalse<void>,
1148*795d594fSAndroid Build Coastguard Worker                                                            report_instance_field);
1149*795d594fSAndroid Build Coastguard Worker     if (stop_reports_) {
1150*795d594fSAndroid Build Coastguard Worker       return;
1151*795d594fSAndroid Build Coastguard Worker     }
1152*795d594fSAndroid Build Coastguard Worker 
1153*795d594fSAndroid Build Coastguard Worker     jint string_ret = ReportString(obj, env, tag_table_, callbacks_, user_data_);
1154*795d594fSAndroid Build Coastguard Worker     stop_reports_ = (string_ret & JVMTI_VISIT_ABORT) != 0;
1155*795d594fSAndroid Build Coastguard Worker     if (stop_reports_) {
1156*795d594fSAndroid Build Coastguard Worker       return;
1157*795d594fSAndroid Build Coastguard Worker     }
1158*795d594fSAndroid Build Coastguard Worker 
1159*795d594fSAndroid Build Coastguard Worker     stop_reports_ = ReportPrimitiveField::Report(obj, tag_table_, callbacks_, user_data_);
1160*795d594fSAndroid Build Coastguard Worker   }
1161*795d594fSAndroid Build Coastguard Worker 
VisitArray(art::mirror::Object * array)1162*795d594fSAndroid Build Coastguard Worker   void VisitArray(art::mirror::Object* array)
1163*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_)
1164*795d594fSAndroid Build Coastguard Worker       REQUIRES(!*tag_table_->GetAllowDisallowLock()) {
1165*795d594fSAndroid Build Coastguard Worker     stop_reports_ = !ReportReferenceMaybeEnqueue(JVMTI_HEAP_REFERENCE_CLASS,
1166*795d594fSAndroid Build Coastguard Worker                                                  nullptr,
1167*795d594fSAndroid Build Coastguard Worker                                                  array,
1168*795d594fSAndroid Build Coastguard Worker                                                  array->GetClass());
1169*795d594fSAndroid Build Coastguard Worker     if (stop_reports_) {
1170*795d594fSAndroid Build Coastguard Worker       return;
1171*795d594fSAndroid Build Coastguard Worker     }
1172*795d594fSAndroid Build Coastguard Worker 
1173*795d594fSAndroid Build Coastguard Worker     if (array->IsObjectArray()) {
1174*795d594fSAndroid Build Coastguard Worker       art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> obj_array =
1175*795d594fSAndroid Build Coastguard Worker           array->AsObjectArray<art::mirror::Object>();
1176*795d594fSAndroid Build Coastguard Worker       for (auto elem_pair : art::ZipCount(obj_array->Iterate())) {
1177*795d594fSAndroid Build Coastguard Worker         if (elem_pair.first != nullptr) {
1178*795d594fSAndroid Build Coastguard Worker           jvmtiHeapReferenceInfo reference_info;
1179*795d594fSAndroid Build Coastguard Worker           reference_info.array.index = elem_pair.second;
1180*795d594fSAndroid Build Coastguard Worker           stop_reports_ = !ReportReferenceMaybeEnqueue(JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT,
1181*795d594fSAndroid Build Coastguard Worker                                                        &reference_info,
1182*795d594fSAndroid Build Coastguard Worker                                                        array,
1183*795d594fSAndroid Build Coastguard Worker                                                        elem_pair.first.Ptr());
1184*795d594fSAndroid Build Coastguard Worker           if (stop_reports_) {
1185*795d594fSAndroid Build Coastguard Worker             break;
1186*795d594fSAndroid Build Coastguard Worker           }
1187*795d594fSAndroid Build Coastguard Worker         }
1188*795d594fSAndroid Build Coastguard Worker       }
1189*795d594fSAndroid Build Coastguard Worker     } else {
1190*795d594fSAndroid Build Coastguard Worker       if (!stop_reports_) {
1191*795d594fSAndroid Build Coastguard Worker         jint array_ret = ReportPrimitiveArray(array, env, tag_table_, callbacks_, user_data_);
1192*795d594fSAndroid Build Coastguard Worker         stop_reports_ = (array_ret & JVMTI_VISIT_ABORT) != 0;
1193*795d594fSAndroid Build Coastguard Worker       }
1194*795d594fSAndroid Build Coastguard Worker     }
1195*795d594fSAndroid Build Coastguard Worker   }
1196*795d594fSAndroid Build Coastguard Worker 
VisitClass(art::mirror::Class * klass)1197*795d594fSAndroid Build Coastguard Worker   void VisitClass(art::mirror::Class* klass)
1198*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_)
1199*795d594fSAndroid Build Coastguard Worker       REQUIRES(!*tag_table_->GetAllowDisallowLock()) {
1200*795d594fSAndroid Build Coastguard Worker     // TODO: Are erroneous classes reported? Are non-prepared ones? For now, just use resolved ones.
1201*795d594fSAndroid Build Coastguard Worker     if (!klass->IsResolved()) {
1202*795d594fSAndroid Build Coastguard Worker       return;
1203*795d594fSAndroid Build Coastguard Worker     }
1204*795d594fSAndroid Build Coastguard Worker 
1205*795d594fSAndroid Build Coastguard Worker     // Superclass.
1206*795d594fSAndroid Build Coastguard Worker     stop_reports_ = !ReportReferenceMaybeEnqueue(JVMTI_HEAP_REFERENCE_SUPERCLASS,
1207*795d594fSAndroid Build Coastguard Worker                                                  nullptr,
1208*795d594fSAndroid Build Coastguard Worker                                                  klass,
1209*795d594fSAndroid Build Coastguard Worker                                                  klass->GetSuperClass().Ptr());
1210*795d594fSAndroid Build Coastguard Worker     if (stop_reports_) {
1211*795d594fSAndroid Build Coastguard Worker       return;
1212*795d594fSAndroid Build Coastguard Worker     }
1213*795d594fSAndroid Build Coastguard Worker 
1214*795d594fSAndroid Build Coastguard Worker     // Directly implemented or extended interfaces.
1215*795d594fSAndroid Build Coastguard Worker     art::Thread* self = art::Thread::Current();
1216*795d594fSAndroid Build Coastguard Worker     art::StackHandleScope<1> hs(self);
1217*795d594fSAndroid Build Coastguard Worker     art::Handle<art::mirror::Class> h_klass(hs.NewHandle<art::mirror::Class>(klass));
1218*795d594fSAndroid Build Coastguard Worker     for (size_t i = 0; i < h_klass->NumDirectInterfaces(); ++i) {
1219*795d594fSAndroid Build Coastguard Worker       art::ObjPtr<art::mirror::Class> inf_klass =
1220*795d594fSAndroid Build Coastguard Worker           art::mirror::Class::ResolveDirectInterface(self, h_klass, i);
1221*795d594fSAndroid Build Coastguard Worker       if (inf_klass == nullptr) {
1222*795d594fSAndroid Build Coastguard Worker         // TODO: With a resolved class this should not happen...
1223*795d594fSAndroid Build Coastguard Worker         self->ClearException();
1224*795d594fSAndroid Build Coastguard Worker         break;
1225*795d594fSAndroid Build Coastguard Worker       }
1226*795d594fSAndroid Build Coastguard Worker 
1227*795d594fSAndroid Build Coastguard Worker       stop_reports_ = !ReportReferenceMaybeEnqueue(JVMTI_HEAP_REFERENCE_INTERFACE,
1228*795d594fSAndroid Build Coastguard Worker                                                    nullptr,
1229*795d594fSAndroid Build Coastguard Worker                                                    klass,
1230*795d594fSAndroid Build Coastguard Worker                                                    inf_klass.Ptr());
1231*795d594fSAndroid Build Coastguard Worker       if (stop_reports_) {
1232*795d594fSAndroid Build Coastguard Worker         return;
1233*795d594fSAndroid Build Coastguard Worker       }
1234*795d594fSAndroid Build Coastguard Worker     }
1235*795d594fSAndroid Build Coastguard Worker 
1236*795d594fSAndroid Build Coastguard Worker     // Classloader.
1237*795d594fSAndroid Build Coastguard Worker     // TODO: What about the boot classpath loader? We'll skip for now, but do we have to find the
1238*795d594fSAndroid Build Coastguard Worker     //       fake BootClassLoader?
1239*795d594fSAndroid Build Coastguard Worker     if (klass->GetClassLoader() != nullptr) {
1240*795d594fSAndroid Build Coastguard Worker       stop_reports_ = !ReportReferenceMaybeEnqueue(JVMTI_HEAP_REFERENCE_CLASS_LOADER,
1241*795d594fSAndroid Build Coastguard Worker                                                    nullptr,
1242*795d594fSAndroid Build Coastguard Worker                                                    klass,
1243*795d594fSAndroid Build Coastguard Worker                                                    klass->GetClassLoader().Ptr());
1244*795d594fSAndroid Build Coastguard Worker       if (stop_reports_) {
1245*795d594fSAndroid Build Coastguard Worker         return;
1246*795d594fSAndroid Build Coastguard Worker       }
1247*795d594fSAndroid Build Coastguard Worker     }
1248*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(h_klass.Get(), klass);
1249*795d594fSAndroid Build Coastguard Worker 
1250*795d594fSAndroid Build Coastguard Worker     // Declared static fields.
1251*795d594fSAndroid Build Coastguard Worker     auto report_static_field =
1252*795d594fSAndroid Build Coastguard Worker         [&]([[maybe_unused]] art::ObjPtr<art::mirror::Object> obj,
1253*795d594fSAndroid Build Coastguard Worker             art::ObjPtr<art::mirror::Class> obj_klass,
1254*795d594fSAndroid Build Coastguard Worker             art::ArtField& field,
1255*795d594fSAndroid Build Coastguard Worker             size_t field_index,
1256*795d594fSAndroid Build Coastguard Worker             [[maybe_unused]] void* user_data) REQUIRES_SHARED(art::Locks::mutator_lock_)
1257*795d594fSAndroid Build Coastguard Worker             REQUIRES(!*tag_table_->GetAllowDisallowLock()) {
1258*795d594fSAndroid Build Coastguard Worker               art::ObjPtr<art::mirror::Object> field_value = field.GetObject(obj_klass);
1259*795d594fSAndroid Build Coastguard Worker               if (field_value != nullptr) {
1260*795d594fSAndroid Build Coastguard Worker                 jvmtiHeapReferenceInfo reference_info;
1261*795d594fSAndroid Build Coastguard Worker                 memset(&reference_info, 0, sizeof(reference_info));
1262*795d594fSAndroid Build Coastguard Worker 
1263*795d594fSAndroid Build Coastguard Worker                 reference_info.field.index = static_cast<jint>(field_index);
1264*795d594fSAndroid Build Coastguard Worker 
1265*795d594fSAndroid Build Coastguard Worker                 return !ReportReferenceMaybeEnqueue(JVMTI_HEAP_REFERENCE_STATIC_FIELD,
1266*795d594fSAndroid Build Coastguard Worker                                                     &reference_info,
1267*795d594fSAndroid Build Coastguard Worker                                                     obj_klass.Ptr(),
1268*795d594fSAndroid Build Coastguard Worker                                                     field_value.Ptr());
1269*795d594fSAndroid Build Coastguard Worker               }
1270*795d594fSAndroid Build Coastguard Worker               return false;
1271*795d594fSAndroid Build Coastguard Worker             };
1272*795d594fSAndroid Build Coastguard Worker     stop_reports_ = FieldVisitor<void, false>::ReportFields(klass,
1273*795d594fSAndroid Build Coastguard Worker                                                             nullptr,
1274*795d594fSAndroid Build Coastguard Worker                                                             VisitorFalse<void>,
1275*795d594fSAndroid Build Coastguard Worker                                                             report_static_field,
1276*795d594fSAndroid Build Coastguard Worker                                                             VisitorFalse<void>,
1277*795d594fSAndroid Build Coastguard Worker                                                             VisitorFalse<void>);
1278*795d594fSAndroid Build Coastguard Worker     if (stop_reports_) {
1279*795d594fSAndroid Build Coastguard Worker       return;
1280*795d594fSAndroid Build Coastguard Worker     }
1281*795d594fSAndroid Build Coastguard Worker 
1282*795d594fSAndroid Build Coastguard Worker     stop_reports_ = ReportPrimitiveField::Report(klass, tag_table_, callbacks_, user_data_);
1283*795d594fSAndroid Build Coastguard Worker   }
1284*795d594fSAndroid Build Coastguard Worker 
MaybeEnqueue(art::mirror::Object * obj)1285*795d594fSAndroid Build Coastguard Worker   void MaybeEnqueue(art::mirror::Object* obj) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1286*795d594fSAndroid Build Coastguard Worker     if (visited_.find(obj) == visited_.end()) {
1287*795d594fSAndroid Build Coastguard Worker       worklist_.push_back(obj);
1288*795d594fSAndroid Build Coastguard Worker       visited_.insert(obj);
1289*795d594fSAndroid Build Coastguard Worker     }
1290*795d594fSAndroid Build Coastguard Worker   }
1291*795d594fSAndroid Build Coastguard Worker 
ReportReferenceMaybeEnqueue(jvmtiHeapReferenceKind kind,const jvmtiHeapReferenceInfo * reference_info,art::mirror::Object * referree,art::mirror::Object * referrer)1292*795d594fSAndroid Build Coastguard Worker   bool ReportReferenceMaybeEnqueue(jvmtiHeapReferenceKind kind,
1293*795d594fSAndroid Build Coastguard Worker                                    const jvmtiHeapReferenceInfo* reference_info,
1294*795d594fSAndroid Build Coastguard Worker                                    art::mirror::Object* referree,
1295*795d594fSAndroid Build Coastguard Worker                                    art::mirror::Object* referrer)
1296*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_)
1297*795d594fSAndroid Build Coastguard Worker       REQUIRES(!*tag_table_->GetAllowDisallowLock()) {
1298*795d594fSAndroid Build Coastguard Worker     jint result = ReportReference(kind, reference_info, referree, referrer);
1299*795d594fSAndroid Build Coastguard Worker     if ((result & JVMTI_VISIT_ABORT) == 0) {
1300*795d594fSAndroid Build Coastguard Worker       if ((result & JVMTI_VISIT_OBJECTS) != 0) {
1301*795d594fSAndroid Build Coastguard Worker         MaybeEnqueue(referrer);
1302*795d594fSAndroid Build Coastguard Worker       }
1303*795d594fSAndroid Build Coastguard Worker       return true;
1304*795d594fSAndroid Build Coastguard Worker     } else {
1305*795d594fSAndroid Build Coastguard Worker       return false;
1306*795d594fSAndroid Build Coastguard Worker     }
1307*795d594fSAndroid Build Coastguard Worker   }
1308*795d594fSAndroid Build Coastguard Worker 
ReportReference(jvmtiHeapReferenceKind kind,const jvmtiHeapReferenceInfo * reference_info,art::mirror::Object * referrer,art::mirror::Object * referree)1309*795d594fSAndroid Build Coastguard Worker   jint ReportReference(jvmtiHeapReferenceKind kind,
1310*795d594fSAndroid Build Coastguard Worker                        const jvmtiHeapReferenceInfo* reference_info,
1311*795d594fSAndroid Build Coastguard Worker                        art::mirror::Object* referrer,
1312*795d594fSAndroid Build Coastguard Worker                        art::mirror::Object* referree)
1313*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_)
1314*795d594fSAndroid Build Coastguard Worker       REQUIRES(!*tag_table_->GetAllowDisallowLock()) {
1315*795d594fSAndroid Build Coastguard Worker     if (referree == nullptr || stop_reports_) {
1316*795d594fSAndroid Build Coastguard Worker       return 0;
1317*795d594fSAndroid Build Coastguard Worker     }
1318*795d594fSAndroid Build Coastguard Worker 
1319*795d594fSAndroid Build Coastguard Worker     if (UNLIKELY(class_filter_ != nullptr) && class_filter_ != referree->GetClass()) {
1320*795d594fSAndroid Build Coastguard Worker       return JVMTI_VISIT_OBJECTS;
1321*795d594fSAndroid Build Coastguard Worker     }
1322*795d594fSAndroid Build Coastguard Worker 
1323*795d594fSAndroid Build Coastguard Worker     const jlong class_tag = tag_table_->GetTagOrZero(referree->GetClass());
1324*795d594fSAndroid Build Coastguard Worker     jlong tag = tag_table_->GetTagOrZero(referree);
1325*795d594fSAndroid Build Coastguard Worker 
1326*795d594fSAndroid Build Coastguard Worker     if (!heap_filter_.ShouldReportByHeapFilter(tag, class_tag)) {
1327*795d594fSAndroid Build Coastguard Worker       return JVMTI_VISIT_OBJECTS;
1328*795d594fSAndroid Build Coastguard Worker     }
1329*795d594fSAndroid Build Coastguard Worker 
1330*795d594fSAndroid Build Coastguard Worker     const jlong referrer_class_tag =
1331*795d594fSAndroid Build Coastguard Worker         referrer == nullptr ? 0 : tag_table_->GetTagOrZero(referrer->GetClass());
1332*795d594fSAndroid Build Coastguard Worker     const jlong size = static_cast<jlong>(referree->SizeOf());
1333*795d594fSAndroid Build Coastguard Worker     jlong saved_tag = tag;
1334*795d594fSAndroid Build Coastguard Worker     jlong referrer_tag = 0;
1335*795d594fSAndroid Build Coastguard Worker     jlong saved_referrer_tag = 0;
1336*795d594fSAndroid Build Coastguard Worker     jlong* referrer_tag_ptr;
1337*795d594fSAndroid Build Coastguard Worker     if (referrer == nullptr) {
1338*795d594fSAndroid Build Coastguard Worker       referrer_tag_ptr = nullptr;
1339*795d594fSAndroid Build Coastguard Worker     } else {
1340*795d594fSAndroid Build Coastguard Worker       if (referrer == referree) {
1341*795d594fSAndroid Build Coastguard Worker         referrer_tag_ptr = &tag;
1342*795d594fSAndroid Build Coastguard Worker       } else {
1343*795d594fSAndroid Build Coastguard Worker         referrer_tag = saved_referrer_tag = tag_table_->GetTagOrZero(referrer);
1344*795d594fSAndroid Build Coastguard Worker         referrer_tag_ptr = &referrer_tag;
1345*795d594fSAndroid Build Coastguard Worker       }
1346*795d594fSAndroid Build Coastguard Worker     }
1347*795d594fSAndroid Build Coastguard Worker 
1348*795d594fSAndroid Build Coastguard Worker     jint length = -1;
1349*795d594fSAndroid Build Coastguard Worker     if (referree->IsArrayInstance()) {
1350*795d594fSAndroid Build Coastguard Worker       length = referree->AsArray()->GetLength();
1351*795d594fSAndroid Build Coastguard Worker     }
1352*795d594fSAndroid Build Coastguard Worker 
1353*795d594fSAndroid Build Coastguard Worker     jint result = callbacks_->heap_reference_callback(kind,
1354*795d594fSAndroid Build Coastguard Worker                                                       reference_info,
1355*795d594fSAndroid Build Coastguard Worker                                                       class_tag,
1356*795d594fSAndroid Build Coastguard Worker                                                       referrer_class_tag,
1357*795d594fSAndroid Build Coastguard Worker                                                       size,
1358*795d594fSAndroid Build Coastguard Worker                                                       &tag,
1359*795d594fSAndroid Build Coastguard Worker                                                       referrer_tag_ptr,
1360*795d594fSAndroid Build Coastguard Worker                                                       length,
1361*795d594fSAndroid Build Coastguard Worker                                                       const_cast<void*>(user_data_));
1362*795d594fSAndroid Build Coastguard Worker 
1363*795d594fSAndroid Build Coastguard Worker     if (tag != saved_tag) {
1364*795d594fSAndroid Build Coastguard Worker       tag_table_->Set(referree, tag);
1365*795d594fSAndroid Build Coastguard Worker     }
1366*795d594fSAndroid Build Coastguard Worker     if (referrer_tag != saved_referrer_tag) {
1367*795d594fSAndroid Build Coastguard Worker       tag_table_->Set(referrer, referrer_tag);
1368*795d594fSAndroid Build Coastguard Worker     }
1369*795d594fSAndroid Build Coastguard Worker 
1370*795d594fSAndroid Build Coastguard Worker     return result;
1371*795d594fSAndroid Build Coastguard Worker   }
1372*795d594fSAndroid Build Coastguard Worker 
1373*795d594fSAndroid Build Coastguard Worker   jvmtiEnv* env;
1374*795d594fSAndroid Build Coastguard Worker   ObjectTagTable* tag_table_;
1375*795d594fSAndroid Build Coastguard Worker   art::ObjPtr<art::mirror::Object> initial_object_;
1376*795d594fSAndroid Build Coastguard Worker   const jvmtiHeapCallbacks* callbacks_;
1377*795d594fSAndroid Build Coastguard Worker   art::ObjPtr<art::mirror::Class> class_filter_;
1378*795d594fSAndroid Build Coastguard Worker   const HeapFilter heap_filter_;
1379*795d594fSAndroid Build Coastguard Worker   const void* user_data_;
1380*795d594fSAndroid Build Coastguard Worker 
1381*795d594fSAndroid Build Coastguard Worker   std::vector<art::mirror::Object*> worklist_;
1382*795d594fSAndroid Build Coastguard Worker   size_t start_;
1383*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kMaxStart = 1000000U;
1384*795d594fSAndroid Build Coastguard Worker 
1385*795d594fSAndroid Build Coastguard Worker   std::unordered_set<art::mirror::Object*> visited_;
1386*795d594fSAndroid Build Coastguard Worker 
1387*795d594fSAndroid Build Coastguard Worker   bool stop_reports_;
1388*795d594fSAndroid Build Coastguard Worker 
1389*795d594fSAndroid Build Coastguard Worker   friend class CollectAndReportRootsVisitor;
1390*795d594fSAndroid Build Coastguard Worker };
1391*795d594fSAndroid Build Coastguard Worker 
FollowReferences(jvmtiEnv * env,jint heap_filter,jclass klass,jobject initial_object,const jvmtiHeapCallbacks * callbacks,const void * user_data)1392*795d594fSAndroid Build Coastguard Worker jvmtiError HeapUtil::FollowReferences(jvmtiEnv* env,
1393*795d594fSAndroid Build Coastguard Worker                                       jint heap_filter,
1394*795d594fSAndroid Build Coastguard Worker                                       jclass klass,
1395*795d594fSAndroid Build Coastguard Worker                                       jobject initial_object,
1396*795d594fSAndroid Build Coastguard Worker                                       const jvmtiHeapCallbacks* callbacks,
1397*795d594fSAndroid Build Coastguard Worker                                       const void* user_data) {
1398*795d594fSAndroid Build Coastguard Worker   if (callbacks == nullptr) {
1399*795d594fSAndroid Build Coastguard Worker     return ERR(NULL_POINTER);
1400*795d594fSAndroid Build Coastguard Worker   }
1401*795d594fSAndroid Build Coastguard Worker 
1402*795d594fSAndroid Build Coastguard Worker   art::Thread* self = art::Thread::Current();
1403*795d594fSAndroid Build Coastguard Worker 
1404*795d594fSAndroid Build Coastguard Worker   art::gc::Heap* heap = art::Runtime::Current()->GetHeap();
1405*795d594fSAndroid Build Coastguard Worker   if (heap->IsGcConcurrentAndMoving()) {
1406*795d594fSAndroid Build Coastguard Worker     // Need to take a heap dump while GC isn't running. See the
1407*795d594fSAndroid Build Coastguard Worker     // comment in Heap::VisitObjects().
1408*795d594fSAndroid Build Coastguard Worker     heap->IncrementDisableMovingGC(self);
1409*795d594fSAndroid Build Coastguard Worker   }
1410*795d594fSAndroid Build Coastguard Worker   {
1411*795d594fSAndroid Build Coastguard Worker     art::ScopedObjectAccess soa(self);      // Now we know we have the shared lock.
1412*795d594fSAndroid Build Coastguard Worker     art::jni::ScopedEnableSuspendAllJniIdQueries sjni;  // make sure we can get JNI ids.
1413*795d594fSAndroid Build Coastguard Worker     art::ScopedThreadSuspension sts(self, art::ThreadState::kWaitingForVisitObjects);
1414*795d594fSAndroid Build Coastguard Worker     art::ScopedSuspendAll ssa("FollowReferences");
1415*795d594fSAndroid Build Coastguard Worker 
1416*795d594fSAndroid Build Coastguard Worker     art::ObjPtr<art::mirror::Class> class_filter = klass == nullptr
1417*795d594fSAndroid Build Coastguard Worker         ? nullptr
1418*795d594fSAndroid Build Coastguard Worker         : art::ObjPtr<art::mirror::Class>::DownCast(self->DecodeJObject(klass));
1419*795d594fSAndroid Build Coastguard Worker     FollowReferencesHelper frh(this,
1420*795d594fSAndroid Build Coastguard Worker                                env,
1421*795d594fSAndroid Build Coastguard Worker                                self->DecodeJObject(initial_object),
1422*795d594fSAndroid Build Coastguard Worker                                callbacks,
1423*795d594fSAndroid Build Coastguard Worker                                class_filter,
1424*795d594fSAndroid Build Coastguard Worker                                heap_filter,
1425*795d594fSAndroid Build Coastguard Worker                                user_data);
1426*795d594fSAndroid Build Coastguard Worker     frh.Init();
1427*795d594fSAndroid Build Coastguard Worker     frh.Work();
1428*795d594fSAndroid Build Coastguard Worker   }
1429*795d594fSAndroid Build Coastguard Worker   if (heap->IsGcConcurrentAndMoving()) {
1430*795d594fSAndroid Build Coastguard Worker     heap->DecrementDisableMovingGC(self);
1431*795d594fSAndroid Build Coastguard Worker   }
1432*795d594fSAndroid Build Coastguard Worker 
1433*795d594fSAndroid Build Coastguard Worker   return ERR(NONE);
1434*795d594fSAndroid Build Coastguard Worker }
1435*795d594fSAndroid Build Coastguard Worker 
GetLoadedClasses(jvmtiEnv * env,jint * class_count_ptr,jclass ** classes_ptr)1436*795d594fSAndroid Build Coastguard Worker jvmtiError HeapUtil::GetLoadedClasses(jvmtiEnv* env,
1437*795d594fSAndroid Build Coastguard Worker                                       jint* class_count_ptr,
1438*795d594fSAndroid Build Coastguard Worker                                       jclass** classes_ptr) {
1439*795d594fSAndroid Build Coastguard Worker   if (class_count_ptr == nullptr || classes_ptr == nullptr) {
1440*795d594fSAndroid Build Coastguard Worker     return ERR(NULL_POINTER);
1441*795d594fSAndroid Build Coastguard Worker   }
1442*795d594fSAndroid Build Coastguard Worker 
1443*795d594fSAndroid Build Coastguard Worker   class ReportClassVisitor : public art::ClassVisitor {
1444*795d594fSAndroid Build Coastguard Worker    public:
1445*795d594fSAndroid Build Coastguard Worker     explicit ReportClassVisitor(art::Thread* self) : self_(self) {}
1446*795d594fSAndroid Build Coastguard Worker 
1447*795d594fSAndroid Build Coastguard Worker     bool operator()(art::ObjPtr<art::mirror::Class> klass)
1448*795d594fSAndroid Build Coastguard Worker         override REQUIRES_SHARED(art::Locks::mutator_lock_) {
1449*795d594fSAndroid Build Coastguard Worker       if (klass->IsLoaded() || klass->IsErroneous()) {
1450*795d594fSAndroid Build Coastguard Worker         classes_.push_back(self_->GetJniEnv()->AddLocalReference<jclass>(klass));
1451*795d594fSAndroid Build Coastguard Worker       }
1452*795d594fSAndroid Build Coastguard Worker       return true;
1453*795d594fSAndroid Build Coastguard Worker     }
1454*795d594fSAndroid Build Coastguard Worker 
1455*795d594fSAndroid Build Coastguard Worker     art::Thread* self_;
1456*795d594fSAndroid Build Coastguard Worker     std::vector<jclass> classes_;
1457*795d594fSAndroid Build Coastguard Worker   };
1458*795d594fSAndroid Build Coastguard Worker 
1459*795d594fSAndroid Build Coastguard Worker   art::Thread* self = art::Thread::Current();
1460*795d594fSAndroid Build Coastguard Worker   ReportClassVisitor rcv(self);
1461*795d594fSAndroid Build Coastguard Worker   {
1462*795d594fSAndroid Build Coastguard Worker     art::ScopedObjectAccess soa(self);
1463*795d594fSAndroid Build Coastguard Worker     art::Runtime::Current()->GetClassLinker()->VisitClasses(&rcv);
1464*795d594fSAndroid Build Coastguard Worker   }
1465*795d594fSAndroid Build Coastguard Worker 
1466*795d594fSAndroid Build Coastguard Worker   size_t size = rcv.classes_.size();
1467*795d594fSAndroid Build Coastguard Worker   jclass* classes = nullptr;
1468*795d594fSAndroid Build Coastguard Worker   jvmtiError alloc_ret = env->Allocate(static_cast<jlong>(size * sizeof(jclass)),
1469*795d594fSAndroid Build Coastguard Worker                                        reinterpret_cast<unsigned char**>(&classes));
1470*795d594fSAndroid Build Coastguard Worker   if (alloc_ret != ERR(NONE)) {
1471*795d594fSAndroid Build Coastguard Worker     return alloc_ret;
1472*795d594fSAndroid Build Coastguard Worker   }
1473*795d594fSAndroid Build Coastguard Worker 
1474*795d594fSAndroid Build Coastguard Worker   for (size_t i = 0; i < size; ++i) {
1475*795d594fSAndroid Build Coastguard Worker     classes[i] = rcv.classes_[i];
1476*795d594fSAndroid Build Coastguard Worker   }
1477*795d594fSAndroid Build Coastguard Worker   *classes_ptr = classes;
1478*795d594fSAndroid Build Coastguard Worker   *class_count_ptr = static_cast<jint>(size);
1479*795d594fSAndroid Build Coastguard Worker 
1480*795d594fSAndroid Build Coastguard Worker   return ERR(NONE);
1481*795d594fSAndroid Build Coastguard Worker }
1482*795d594fSAndroid Build Coastguard Worker 
ForceGarbageCollection(jvmtiEnv * env)1483*795d594fSAndroid Build Coastguard Worker jvmtiError HeapUtil::ForceGarbageCollection([[maybe_unused]] jvmtiEnv* env) {
1484*795d594fSAndroid Build Coastguard Worker   art::Runtime::Current()->GetHeap()->CollectGarbage(/* clear_soft_references= */ false);
1485*795d594fSAndroid Build Coastguard Worker 
1486*795d594fSAndroid Build Coastguard Worker   return ERR(NONE);
1487*795d594fSAndroid Build Coastguard Worker }
1488*795d594fSAndroid Build Coastguard Worker 
1489*795d594fSAndroid Build Coastguard Worker static constexpr jint kHeapIdDefault = 0;
1490*795d594fSAndroid Build Coastguard Worker static constexpr jint kHeapIdImage = 1;
1491*795d594fSAndroid Build Coastguard Worker static constexpr jint kHeapIdZygote = 2;
1492*795d594fSAndroid Build Coastguard Worker static constexpr jint kHeapIdApp = 3;
1493*795d594fSAndroid Build Coastguard Worker 
GetHeapId(art::ObjPtr<art::mirror::Object> obj)1494*795d594fSAndroid Build Coastguard Worker static jint GetHeapId(art::ObjPtr<art::mirror::Object> obj)
1495*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(art::Locks::mutator_lock_) {
1496*795d594fSAndroid Build Coastguard Worker   if (obj == nullptr) {
1497*795d594fSAndroid Build Coastguard Worker     return -1;
1498*795d594fSAndroid Build Coastguard Worker   }
1499*795d594fSAndroid Build Coastguard Worker 
1500*795d594fSAndroid Build Coastguard Worker   art::gc::Heap* const heap = art::Runtime::Current()->GetHeap();
1501*795d594fSAndroid Build Coastguard Worker   const art::gc::space::ContinuousSpace* const space =
1502*795d594fSAndroid Build Coastguard Worker       heap->FindContinuousSpaceFromObject(obj, true);
1503*795d594fSAndroid Build Coastguard Worker   jint heap_type = kHeapIdApp;
1504*795d594fSAndroid Build Coastguard Worker   if (space != nullptr) {
1505*795d594fSAndroid Build Coastguard Worker     if (space->IsZygoteSpace()) {
1506*795d594fSAndroid Build Coastguard Worker       heap_type = kHeapIdZygote;
1507*795d594fSAndroid Build Coastguard Worker     } else if (space->IsImageSpace() && heap->ObjectIsInBootImageSpace(obj)) {
1508*795d594fSAndroid Build Coastguard Worker       // Only count objects in the boot image as HPROF_HEAP_IMAGE, this leaves app image objects
1509*795d594fSAndroid Build Coastguard Worker       // as HPROF_HEAP_APP. b/35762934
1510*795d594fSAndroid Build Coastguard Worker       heap_type = kHeapIdImage;
1511*795d594fSAndroid Build Coastguard Worker     }
1512*795d594fSAndroid Build Coastguard Worker   } else {
1513*795d594fSAndroid Build Coastguard Worker     const auto* los = heap->GetLargeObjectsSpace();
1514*795d594fSAndroid Build Coastguard Worker     if (los->Contains(obj.Ptr()) && los->IsZygoteLargeObject(art::Thread::Current(), obj.Ptr())) {
1515*795d594fSAndroid Build Coastguard Worker       heap_type = kHeapIdZygote;
1516*795d594fSAndroid Build Coastguard Worker     }
1517*795d594fSAndroid Build Coastguard Worker   }
1518*795d594fSAndroid Build Coastguard Worker   return heap_type;
1519*795d594fSAndroid Build Coastguard Worker };
1520*795d594fSAndroid Build Coastguard Worker 
GetObjectHeapId(jvmtiEnv * env,jlong tag,jint * heap_id,...)1521*795d594fSAndroid Build Coastguard Worker jvmtiError HeapExtensions::GetObjectHeapId(jvmtiEnv* env, jlong tag, jint* heap_id, ...) {
1522*795d594fSAndroid Build Coastguard Worker   if (heap_id == nullptr) {
1523*795d594fSAndroid Build Coastguard Worker     return ERR(NULL_POINTER);
1524*795d594fSAndroid Build Coastguard Worker   }
1525*795d594fSAndroid Build Coastguard Worker 
1526*795d594fSAndroid Build Coastguard Worker   art::Thread* self = art::Thread::Current();
1527*795d594fSAndroid Build Coastguard Worker 
1528*795d594fSAndroid Build Coastguard Worker   auto work = [&]() REQUIRES_SHARED(art::Locks::mutator_lock_) {
1529*795d594fSAndroid Build Coastguard Worker     ObjectTagTable* tag_table = ArtJvmTiEnv::AsArtJvmTiEnv(env)->object_tag_table.get();
1530*795d594fSAndroid Build Coastguard Worker     art::ObjPtr<art::mirror::Object> obj = tag_table->Find(tag);
1531*795d594fSAndroid Build Coastguard Worker     jint heap_type = GetHeapId(obj);
1532*795d594fSAndroid Build Coastguard Worker     if (heap_type == -1) {
1533*795d594fSAndroid Build Coastguard Worker       return ERR(NOT_FOUND);
1534*795d594fSAndroid Build Coastguard Worker     }
1535*795d594fSAndroid Build Coastguard Worker     *heap_id = heap_type;
1536*795d594fSAndroid Build Coastguard Worker     return ERR(NONE);
1537*795d594fSAndroid Build Coastguard Worker   };
1538*795d594fSAndroid Build Coastguard Worker 
1539*795d594fSAndroid Build Coastguard Worker   if (!art::Locks::mutator_lock_->IsSharedHeld(self)) {
1540*795d594fSAndroid Build Coastguard Worker     if (!self->IsThreadSuspensionAllowable()) {
1541*795d594fSAndroid Build Coastguard Worker       return ERR(INTERNAL);
1542*795d594fSAndroid Build Coastguard Worker     }
1543*795d594fSAndroid Build Coastguard Worker     art::ScopedObjectAccess soa(self);
1544*795d594fSAndroid Build Coastguard Worker     return work();
1545*795d594fSAndroid Build Coastguard Worker   } else {
1546*795d594fSAndroid Build Coastguard Worker     // We cannot use SOA in this case. We might be holding the lock, but may not be in the
1547*795d594fSAndroid Build Coastguard Worker     // runnable state (e.g., during GC).
1548*795d594fSAndroid Build Coastguard Worker     art::Locks::mutator_lock_->AssertSharedHeld(self);
1549*795d594fSAndroid Build Coastguard Worker     // TODO: Investigate why ASSERT_SHARED_CAPABILITY doesn't work.
1550*795d594fSAndroid Build Coastguard Worker     auto annotalysis_workaround = [&]() NO_THREAD_SAFETY_ANALYSIS {
1551*795d594fSAndroid Build Coastguard Worker       return work();
1552*795d594fSAndroid Build Coastguard Worker     };
1553*795d594fSAndroid Build Coastguard Worker     return annotalysis_workaround();
1554*795d594fSAndroid Build Coastguard Worker   }
1555*795d594fSAndroid Build Coastguard Worker }
1556*795d594fSAndroid Build Coastguard Worker 
CopyStringAndReturn(jvmtiEnv * env,const char * in,char ** out)1557*795d594fSAndroid Build Coastguard Worker static jvmtiError CopyStringAndReturn(jvmtiEnv* env, const char* in, char** out) {
1558*795d594fSAndroid Build Coastguard Worker   jvmtiError error;
1559*795d594fSAndroid Build Coastguard Worker   JvmtiUniquePtr<char[]> param_name = CopyString(env, in, &error);
1560*795d594fSAndroid Build Coastguard Worker   if (param_name == nullptr) {
1561*795d594fSAndroid Build Coastguard Worker     return error;
1562*795d594fSAndroid Build Coastguard Worker   }
1563*795d594fSAndroid Build Coastguard Worker   *out = param_name.release();
1564*795d594fSAndroid Build Coastguard Worker   return ERR(NONE);
1565*795d594fSAndroid Build Coastguard Worker }
1566*795d594fSAndroid Build Coastguard Worker 
1567*795d594fSAndroid Build Coastguard Worker static constexpr const char* kHeapIdDefaultName = "default";
1568*795d594fSAndroid Build Coastguard Worker static constexpr const char* kHeapIdImageName = "image";
1569*795d594fSAndroid Build Coastguard Worker static constexpr const char* kHeapIdZygoteName = "zygote";
1570*795d594fSAndroid Build Coastguard Worker static constexpr const char* kHeapIdAppName = "app";
1571*795d594fSAndroid Build Coastguard Worker 
GetHeapName(jvmtiEnv * env,jint heap_id,char ** heap_name,...)1572*795d594fSAndroid Build Coastguard Worker jvmtiError HeapExtensions::GetHeapName(jvmtiEnv* env, jint heap_id, char** heap_name, ...) {
1573*795d594fSAndroid Build Coastguard Worker   switch (heap_id) {
1574*795d594fSAndroid Build Coastguard Worker     case kHeapIdDefault:
1575*795d594fSAndroid Build Coastguard Worker       return CopyStringAndReturn(env, kHeapIdDefaultName, heap_name);
1576*795d594fSAndroid Build Coastguard Worker     case kHeapIdImage:
1577*795d594fSAndroid Build Coastguard Worker       return CopyStringAndReturn(env, kHeapIdImageName, heap_name);
1578*795d594fSAndroid Build Coastguard Worker     case kHeapIdZygote:
1579*795d594fSAndroid Build Coastguard Worker       return CopyStringAndReturn(env, kHeapIdZygoteName, heap_name);
1580*795d594fSAndroid Build Coastguard Worker     case kHeapIdApp:
1581*795d594fSAndroid Build Coastguard Worker       return CopyStringAndReturn(env, kHeapIdAppName, heap_name);
1582*795d594fSAndroid Build Coastguard Worker 
1583*795d594fSAndroid Build Coastguard Worker     default:
1584*795d594fSAndroid Build Coastguard Worker       return ERR(ILLEGAL_ARGUMENT);
1585*795d594fSAndroid Build Coastguard Worker   }
1586*795d594fSAndroid Build Coastguard Worker }
1587*795d594fSAndroid Build Coastguard Worker 
IterateThroughHeapExt(jvmtiEnv * env,jint heap_filter,jclass klass,const jvmtiHeapCallbacks * callbacks,const void * user_data)1588*795d594fSAndroid Build Coastguard Worker jvmtiError HeapExtensions::IterateThroughHeapExt(jvmtiEnv* env,
1589*795d594fSAndroid Build Coastguard Worker                                                  jint heap_filter,
1590*795d594fSAndroid Build Coastguard Worker                                                  jclass klass,
1591*795d594fSAndroid Build Coastguard Worker                                                  const jvmtiHeapCallbacks* callbacks,
1592*795d594fSAndroid Build Coastguard Worker                                                  const void* user_data) {
1593*795d594fSAndroid Build Coastguard Worker   if (ArtJvmTiEnv::AsArtJvmTiEnv(env)->capabilities.can_tag_objects != 1) { \
1594*795d594fSAndroid Build Coastguard Worker     return ERR(MUST_POSSESS_CAPABILITY); \
1595*795d594fSAndroid Build Coastguard Worker   }
1596*795d594fSAndroid Build Coastguard Worker 
1597*795d594fSAndroid Build Coastguard Worker   // ART extension API: Also pass the heap id.
1598*795d594fSAndroid Build Coastguard Worker   auto ArtIterateHeap = [](art::mirror::Object* obj,
1599*795d594fSAndroid Build Coastguard Worker                            const jvmtiHeapCallbacks* cb_callbacks,
1600*795d594fSAndroid Build Coastguard Worker                            jlong class_tag,
1601*795d594fSAndroid Build Coastguard Worker                            jlong size,
1602*795d594fSAndroid Build Coastguard Worker                            jlong* tag,
1603*795d594fSAndroid Build Coastguard Worker                            jint length,
1604*795d594fSAndroid Build Coastguard Worker                            void* cb_user_data)
1605*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(art::Locks::mutator_lock_) {
1606*795d594fSAndroid Build Coastguard Worker     jint heap_id = GetHeapId(obj);
1607*795d594fSAndroid Build Coastguard Worker     using ArtExtensionAPI = jint (*)(jlong, jlong, jlong*, jint length, void*, jint);
1608*795d594fSAndroid Build Coastguard Worker     return reinterpret_cast<ArtExtensionAPI>(cb_callbacks->heap_iteration_callback)(
1609*795d594fSAndroid Build Coastguard Worker         class_tag, size, tag, length, cb_user_data, heap_id);
1610*795d594fSAndroid Build Coastguard Worker   };
1611*795d594fSAndroid Build Coastguard Worker   return DoIterateThroughHeap(ArtIterateHeap,
1612*795d594fSAndroid Build Coastguard Worker                               env,
1613*795d594fSAndroid Build Coastguard Worker                               ArtJvmTiEnv::AsArtJvmTiEnv(env)->object_tag_table.get(),
1614*795d594fSAndroid Build Coastguard Worker                               heap_filter,
1615*795d594fSAndroid Build Coastguard Worker                               klass,
1616*795d594fSAndroid Build Coastguard Worker                               callbacks,
1617*795d594fSAndroid Build Coastguard Worker                               user_data);
1618*795d594fSAndroid Build Coastguard Worker }
1619*795d594fSAndroid Build Coastguard Worker 
1620*795d594fSAndroid Build Coastguard Worker namespace {
1621*795d594fSAndroid Build Coastguard Worker 
1622*795d594fSAndroid Build Coastguard Worker using ObjectPtr = art::ObjPtr<art::mirror::Object>;
1623*795d594fSAndroid Build Coastguard Worker using ObjectMap = std::unordered_map<ObjectPtr, ObjectPtr, art::HashObjPtr>;
1624*795d594fSAndroid Build Coastguard Worker 
ReplaceObjectReferences(const ObjectMap & map)1625*795d594fSAndroid Build Coastguard Worker static void ReplaceObjectReferences(const ObjectMap& map)
1626*795d594fSAndroid Build Coastguard Worker     REQUIRES(art::Locks::mutator_lock_,
1627*795d594fSAndroid Build Coastguard Worker              art::Roles::uninterruptible_) {
1628*795d594fSAndroid Build Coastguard Worker   art::Runtime::Current()->GetHeap()->VisitObjectsPaused(
1629*795d594fSAndroid Build Coastguard Worker       [&](art::mirror::Object* ref) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1630*795d594fSAndroid Build Coastguard Worker         // Rewrite all references in the object if needed.
1631*795d594fSAndroid Build Coastguard Worker         class ResizeReferenceVisitor {
1632*795d594fSAndroid Build Coastguard Worker          public:
1633*795d594fSAndroid Build Coastguard Worker           using CompressedObj = art::mirror::CompressedReference<art::mirror::Object>;
1634*795d594fSAndroid Build Coastguard Worker           explicit ResizeReferenceVisitor(const ObjectMap& map, ObjectPtr ref)
1635*795d594fSAndroid Build Coastguard Worker               : map_(map), ref_(ref) {}
1636*795d594fSAndroid Build Coastguard Worker 
1637*795d594fSAndroid Build Coastguard Worker           // Ignore class roots.
1638*795d594fSAndroid Build Coastguard Worker           void VisitRootIfNonNull(CompressedObj* root) const
1639*795d594fSAndroid Build Coastguard Worker               REQUIRES_SHARED(art::Locks::mutator_lock_) {
1640*795d594fSAndroid Build Coastguard Worker             if (root != nullptr) {
1641*795d594fSAndroid Build Coastguard Worker               VisitRoot(root);
1642*795d594fSAndroid Build Coastguard Worker             }
1643*795d594fSAndroid Build Coastguard Worker           }
1644*795d594fSAndroid Build Coastguard Worker           void VisitRoot(CompressedObj* root) const REQUIRES_SHARED(art::Locks::mutator_lock_) {
1645*795d594fSAndroid Build Coastguard Worker             auto it = map_.find(root->AsMirrorPtr());
1646*795d594fSAndroid Build Coastguard Worker             if (it != map_.end()) {
1647*795d594fSAndroid Build Coastguard Worker               root->Assign(it->second);
1648*795d594fSAndroid Build Coastguard Worker               art::WriteBarrier::ForEveryFieldWrite(ref_);
1649*795d594fSAndroid Build Coastguard Worker             }
1650*795d594fSAndroid Build Coastguard Worker           }
1651*795d594fSAndroid Build Coastguard Worker 
1652*795d594fSAndroid Build Coastguard Worker           void operator()(art::ObjPtr<art::mirror::Object> obj,
1653*795d594fSAndroid Build Coastguard Worker                           art::MemberOffset off,
1654*795d594fSAndroid Build Coastguard Worker                           bool is_static) const
1655*795d594fSAndroid Build Coastguard Worker               REQUIRES_SHARED(art::Locks::mutator_lock_) {
1656*795d594fSAndroid Build Coastguard Worker             auto it = map_.find(obj->GetFieldObject<art::mirror::Object>(off));
1657*795d594fSAndroid Build Coastguard Worker             if (it != map_.end()) {
1658*795d594fSAndroid Build Coastguard Worker               UNUSED(is_static);
1659*795d594fSAndroid Build Coastguard Worker               if (UNLIKELY(!is_static && off == art::mirror::Object::ClassOffset())) {
1660*795d594fSAndroid Build Coastguard Worker                 // We don't want to update the declaring class of any objects. They will be replaced
1661*795d594fSAndroid Build Coastguard Worker                 // in the heap and we need the declaring class to know its size.
1662*795d594fSAndroid Build Coastguard Worker                 return;
1663*795d594fSAndroid Build Coastguard Worker               } else if (UNLIKELY(!is_static && off == art::mirror::Class::SuperClassOffset() &&
1664*795d594fSAndroid Build Coastguard Worker                                   obj->IsClass())) {
1665*795d594fSAndroid Build Coastguard Worker                 // We don't want to be messing with the class hierarcy either.
1666*795d594fSAndroid Build Coastguard Worker                 return;
1667*795d594fSAndroid Build Coastguard Worker               }
1668*795d594fSAndroid Build Coastguard Worker               VLOG(plugin) << "Updating field at offset " << off.Uint32Value() << " of type "
1669*795d594fSAndroid Build Coastguard Worker                            << obj->GetClass()->PrettyClass();
1670*795d594fSAndroid Build Coastguard Worker               obj->SetFieldObject</*transaction*/ false>(off, it->second);
1671*795d594fSAndroid Build Coastguard Worker               art::WriteBarrier::ForEveryFieldWrite(obj);
1672*795d594fSAndroid Build Coastguard Worker             }
1673*795d594fSAndroid Build Coastguard Worker           }
1674*795d594fSAndroid Build Coastguard Worker 
1675*795d594fSAndroid Build Coastguard Worker           // java.lang.ref.Reference visitor.
1676*795d594fSAndroid Build Coastguard Worker           void operator()([[maybe_unused]] art::ObjPtr<art::mirror::Class> klass,
1677*795d594fSAndroid Build Coastguard Worker                           art::ObjPtr<art::mirror::Reference> ref) const
1678*795d594fSAndroid Build Coastguard Worker               REQUIRES_SHARED(art::Locks::mutator_lock_) {
1679*795d594fSAndroid Build Coastguard Worker             operator()(ref, art::mirror::Reference::ReferentOffset(), /* is_static */ false);
1680*795d594fSAndroid Build Coastguard Worker           }
1681*795d594fSAndroid Build Coastguard Worker 
1682*795d594fSAndroid Build Coastguard Worker          private:
1683*795d594fSAndroid Build Coastguard Worker           const ObjectMap& map_;
1684*795d594fSAndroid Build Coastguard Worker           ObjectPtr ref_;
1685*795d594fSAndroid Build Coastguard Worker         };
1686*795d594fSAndroid Build Coastguard Worker 
1687*795d594fSAndroid Build Coastguard Worker         ResizeReferenceVisitor rrv(map, ref);
1688*795d594fSAndroid Build Coastguard Worker         if (ref->IsClass()) {
1689*795d594fSAndroid Build Coastguard Worker           // Class object native roots are the ArtField and ArtMethod 'declaring_class_' fields
1690*795d594fSAndroid Build Coastguard Worker           // which we don't want to be messing with as it would break ref-visitor assumptions about
1691*795d594fSAndroid Build Coastguard Worker           // what a class looks like. We want to keep the default behavior in other cases (such as
1692*795d594fSAndroid Build Coastguard Worker           // dex-cache) though. Unfortunately there is no way to tell from the visitor where exactly
1693*795d594fSAndroid Build Coastguard Worker           // the root came from.
1694*795d594fSAndroid Build Coastguard Worker           // TODO It might be nice to have the visitors told where the reference came from.
1695*795d594fSAndroid Build Coastguard Worker           ref->VisitReferences</*kVisitNativeRoots*/false>(rrv, rrv);
1696*795d594fSAndroid Build Coastguard Worker         } else {
1697*795d594fSAndroid Build Coastguard Worker           ref->VisitReferences</*kVisitNativeRoots*/true>(rrv, rrv);
1698*795d594fSAndroid Build Coastguard Worker         }
1699*795d594fSAndroid Build Coastguard Worker       });
1700*795d594fSAndroid Build Coastguard Worker }
1701*795d594fSAndroid Build Coastguard Worker 
ReplaceStrongRoots(art::Thread * self,const ObjectMap & map)1702*795d594fSAndroid Build Coastguard Worker static void ReplaceStrongRoots(art::Thread* self, const ObjectMap& map)
1703*795d594fSAndroid Build Coastguard Worker     REQUIRES(art::Locks::mutator_lock_, art::Roles::uninterruptible_) {
1704*795d594fSAndroid Build Coastguard Worker   // replace root references expcept java frames.
1705*795d594fSAndroid Build Coastguard Worker   struct ResizeRootVisitor : public art::RootVisitor {
1706*795d594fSAndroid Build Coastguard Worker    public:
1707*795d594fSAndroid Build Coastguard Worker     explicit ResizeRootVisitor(const ObjectMap& map) : map_(map) {}
1708*795d594fSAndroid Build Coastguard Worker 
1709*795d594fSAndroid Build Coastguard Worker     // TODO It's somewhat annoying to have to have this function implemented twice. It might be
1710*795d594fSAndroid Build Coastguard Worker     // good/useful to implement operator= for CompressedReference to allow us to use a template to
1711*795d594fSAndroid Build Coastguard Worker     // implement both of these.
1712*795d594fSAndroid Build Coastguard Worker     void VisitRoots(art::mirror::Object*** roots, size_t count, const art::RootInfo& info) override
1713*795d594fSAndroid Build Coastguard Worker         REQUIRES_SHARED(art::Locks::mutator_lock_) {
1714*795d594fSAndroid Build Coastguard Worker       art::mirror::Object*** end = roots + count;
1715*795d594fSAndroid Build Coastguard Worker       for (art::mirror::Object** obj = *roots; roots != end; obj = *(++roots)) {
1716*795d594fSAndroid Build Coastguard Worker         auto it = map_.find(*obj);
1717*795d594fSAndroid Build Coastguard Worker         if (it != map_.end()) {
1718*795d594fSAndroid Build Coastguard Worker           // Java frames might have the JIT doing optimizations (for example loop-unrolling or
1719*795d594fSAndroid Build Coastguard Worker           // eliding bounds checks) so we need deopt them once we're done here.
1720*795d594fSAndroid Build Coastguard Worker           if (info.GetType() == art::RootType::kRootJavaFrame) {
1721*795d594fSAndroid Build Coastguard Worker             const art::JavaFrameRootInfo& jfri =
1722*795d594fSAndroid Build Coastguard Worker                 art::down_cast<const art::JavaFrameRootInfo&>(info);
1723*795d594fSAndroid Build Coastguard Worker             if (jfri.GetVReg() == art::JavaFrameRootInfo::kMethodDeclaringClass) {
1724*795d594fSAndroid Build Coastguard Worker               info.Describe(VLOG_STREAM(plugin) << "Not changing declaring-class during stack"
1725*795d594fSAndroid Build Coastguard Worker                                                 << " walk. Found obsolete java frame id ");
1726*795d594fSAndroid Build Coastguard Worker               continue;
1727*795d594fSAndroid Build Coastguard Worker             } else {
1728*795d594fSAndroid Build Coastguard Worker               info.Describe(VLOG_STREAM(plugin) << "Found java frame id ");
1729*795d594fSAndroid Build Coastguard Worker               threads_with_roots_.insert(info.GetThreadId());
1730*795d594fSAndroid Build Coastguard Worker             }
1731*795d594fSAndroid Build Coastguard Worker           }
1732*795d594fSAndroid Build Coastguard Worker           *obj = it->second.Ptr();
1733*795d594fSAndroid Build Coastguard Worker         }
1734*795d594fSAndroid Build Coastguard Worker       }
1735*795d594fSAndroid Build Coastguard Worker     }
1736*795d594fSAndroid Build Coastguard Worker 
1737*795d594fSAndroid Build Coastguard Worker     void VisitRoots(art::mirror::CompressedReference<art::mirror::Object>** roots,
1738*795d594fSAndroid Build Coastguard Worker                     size_t count,
1739*795d594fSAndroid Build Coastguard Worker                     const art::RootInfo& info) override REQUIRES_SHARED(art::Locks::mutator_lock_) {
1740*795d594fSAndroid Build Coastguard Worker       art::mirror::CompressedReference<art::mirror::Object>** end = roots + count;
1741*795d594fSAndroid Build Coastguard Worker       for (art::mirror::CompressedReference<art::mirror::Object>* obj = *roots; roots != end;
1742*795d594fSAndroid Build Coastguard Worker            obj = *(++roots)) {
1743*795d594fSAndroid Build Coastguard Worker         auto it = map_.find(obj->AsMirrorPtr());
1744*795d594fSAndroid Build Coastguard Worker         if (it != map_.end()) {
1745*795d594fSAndroid Build Coastguard Worker           // Java frames might have the JIT doing optimizations (for example loop-unrolling or
1746*795d594fSAndroid Build Coastguard Worker           // eliding bounds checks) so we need deopt them once we're done here.
1747*795d594fSAndroid Build Coastguard Worker           if (info.GetType() == art::RootType::kRootJavaFrame) {
1748*795d594fSAndroid Build Coastguard Worker             const art::JavaFrameRootInfo& jfri =
1749*795d594fSAndroid Build Coastguard Worker                 art::down_cast<const art::JavaFrameRootInfo&>(info);
1750*795d594fSAndroid Build Coastguard Worker             if (jfri.GetVReg() == art::JavaFrameRootInfo::kMethodDeclaringClass) {
1751*795d594fSAndroid Build Coastguard Worker               info.Describe(VLOG_STREAM(plugin) << "Not changing declaring-class during stack"
1752*795d594fSAndroid Build Coastguard Worker                                                 << " walk. Found obsolete java frame id ");
1753*795d594fSAndroid Build Coastguard Worker               continue;
1754*795d594fSAndroid Build Coastguard Worker             } else {
1755*795d594fSAndroid Build Coastguard Worker               info.Describe(VLOG_STREAM(plugin) << "Found java frame id ");
1756*795d594fSAndroid Build Coastguard Worker               threads_with_roots_.insert(info.GetThreadId());
1757*795d594fSAndroid Build Coastguard Worker             }
1758*795d594fSAndroid Build Coastguard Worker           }
1759*795d594fSAndroid Build Coastguard Worker           obj->Assign(it->second);
1760*795d594fSAndroid Build Coastguard Worker         }
1761*795d594fSAndroid Build Coastguard Worker       }
1762*795d594fSAndroid Build Coastguard Worker     }
1763*795d594fSAndroid Build Coastguard Worker 
1764*795d594fSAndroid Build Coastguard Worker     const std::unordered_set<uint32_t>& GetThreadsWithJavaFrameRoots() const {
1765*795d594fSAndroid Build Coastguard Worker       return threads_with_roots_;
1766*795d594fSAndroid Build Coastguard Worker     }
1767*795d594fSAndroid Build Coastguard Worker 
1768*795d594fSAndroid Build Coastguard Worker    private:
1769*795d594fSAndroid Build Coastguard Worker     const ObjectMap& map_;
1770*795d594fSAndroid Build Coastguard Worker     std::unordered_set<uint32_t> threads_with_roots_;
1771*795d594fSAndroid Build Coastguard Worker   };
1772*795d594fSAndroid Build Coastguard Worker   ResizeRootVisitor rrv(map);
1773*795d594fSAndroid Build Coastguard Worker   art::Runtime::Current()->VisitRoots(&rrv, art::VisitRootFlags::kVisitRootFlagAllRoots);
1774*795d594fSAndroid Build Coastguard Worker   // Handle java Frames. Annoyingly the JIT can embed information about the length of the array into
1775*795d594fSAndroid Build Coastguard Worker   // the compiled code. By changing the length of the array we potentially invalidate these
1776*795d594fSAndroid Build Coastguard Worker   // assumptions and so could cause (eg) OOB array access or other issues.
1777*795d594fSAndroid Build Coastguard Worker   if (!rrv.GetThreadsWithJavaFrameRoots().empty()) {
1778*795d594fSAndroid Build Coastguard Worker     art::MutexLock mu(self, *art::Locks::thread_list_lock_);
1779*795d594fSAndroid Build Coastguard Worker     art::ThreadList* thread_list = art::Runtime::Current()->GetThreadList();
1780*795d594fSAndroid Build Coastguard Worker     art::instrumentation::Instrumentation* instr = art::Runtime::Current()->GetInstrumentation();
1781*795d594fSAndroid Build Coastguard Worker     for (uint32_t id : rrv.GetThreadsWithJavaFrameRoots()) {
1782*795d594fSAndroid Build Coastguard Worker       art::Thread* t = thread_list->FindThreadByThreadId(id);
1783*795d594fSAndroid Build Coastguard Worker       CHECK(t != nullptr) << "id " << id << " does not refer to a valid thread."
1784*795d594fSAndroid Build Coastguard Worker                           << " Where did the roots come from?";
1785*795d594fSAndroid Build Coastguard Worker       VLOG(plugin) << "Instrumenting thread stack of thread " << *t;
1786*795d594fSAndroid Build Coastguard Worker       // TODO Use deopt manager. We need a version that doesn't acquire all the locks we
1787*795d594fSAndroid Build Coastguard Worker       // already have.
1788*795d594fSAndroid Build Coastguard Worker       // TODO We technically only need to do this if the frames are not already being interpreted.
1789*795d594fSAndroid Build Coastguard Worker       // The cost for doing an extra stack walk is unlikely to be worth it though.
1790*795d594fSAndroid Build Coastguard Worker       instr->InstrumentThreadStack(t, /* force_deopt= */ true);
1791*795d594fSAndroid Build Coastguard Worker     }
1792*795d594fSAndroid Build Coastguard Worker   }
1793*795d594fSAndroid Build Coastguard Worker }
1794*795d594fSAndroid Build Coastguard Worker 
ReplaceWeakRoots(art::Thread * self,EventHandler * event_handler,const ObjectMap & map)1795*795d594fSAndroid Build Coastguard Worker static void ReplaceWeakRoots(art::Thread* self,
1796*795d594fSAndroid Build Coastguard Worker                              EventHandler* event_handler,
1797*795d594fSAndroid Build Coastguard Worker                              const ObjectMap& map)
1798*795d594fSAndroid Build Coastguard Worker     REQUIRES(art::Locks::mutator_lock_, art::Roles::uninterruptible_) {
1799*795d594fSAndroid Build Coastguard Worker   // Handle tags. We want to do this seprately from other weak-refs (handled below) because we need
1800*795d594fSAndroid Build Coastguard Worker   // to send additional events and handle cases where the agent might have tagged the new
1801*795d594fSAndroid Build Coastguard Worker   // replacement object during the VMObjectAlloc. We do this by removing all tags associated with
1802*795d594fSAndroid Build Coastguard Worker   // both the obsolete and the new arrays. Then we send the ObsoleteObjectCreated event and cache
1803*795d594fSAndroid Build Coastguard Worker   // the new tag values. We next update all the other weak-references (the tags have been removed)
1804*795d594fSAndroid Build Coastguard Worker   // and finally update the tag table with the new values. Doing things in this way (1) keeps all
1805*795d594fSAndroid Build Coastguard Worker   // code relating to updating weak-references together and (2) ensures we don't end up in strange
1806*795d594fSAndroid Build Coastguard Worker   // situations where the order of weak-ref visiting affects the final tagging state. Since we have
1807*795d594fSAndroid Build Coastguard Worker   // the mutator_lock_ and gc-paused throughout this whole process no threads should be able to see
1808*795d594fSAndroid Build Coastguard Worker   // the interval where the objects are not tagged.
1809*795d594fSAndroid Build Coastguard Worker   struct NewTagValue {
1810*795d594fSAndroid Build Coastguard Worker    public:
1811*795d594fSAndroid Build Coastguard Worker     ObjectPtr obsolete_obj_;
1812*795d594fSAndroid Build Coastguard Worker     jlong obsolete_tag_;
1813*795d594fSAndroid Build Coastguard Worker     ObjectPtr new_obj_;
1814*795d594fSAndroid Build Coastguard Worker     jlong new_tag_;
1815*795d594fSAndroid Build Coastguard Worker   };
1816*795d594fSAndroid Build Coastguard Worker 
1817*795d594fSAndroid Build Coastguard Worker   // Map from the environment to the list of <obsolete_tag, new_tag> pairs that were changed.
1818*795d594fSAndroid Build Coastguard Worker   std::unordered_map<ArtJvmTiEnv*, std::vector<NewTagValue>> changed_tags;
1819*795d594fSAndroid Build Coastguard Worker   event_handler->ForEachEnv(self, [&](ArtJvmTiEnv* env) {
1820*795d594fSAndroid Build Coastguard Worker     // Cannot have REQUIRES(art::Locks::mutator_lock_) since ForEachEnv doesn't require it.
1821*795d594fSAndroid Build Coastguard Worker     art::Locks::mutator_lock_->AssertExclusiveHeld(self);
1822*795d594fSAndroid Build Coastguard Worker     env->object_tag_table->Lock();
1823*795d594fSAndroid Build Coastguard Worker     // Get the tags and clear them (so we don't need to special-case the normal weak-ref visitor)
1824*795d594fSAndroid Build Coastguard Worker     for (auto it : map) {
1825*795d594fSAndroid Build Coastguard Worker       jlong new_tag = 0;
1826*795d594fSAndroid Build Coastguard Worker       jlong obsolete_tag = 0;
1827*795d594fSAndroid Build Coastguard Worker       bool had_obsolete_tag = env->object_tag_table->RemoveLocked(it.first, &obsolete_tag);
1828*795d594fSAndroid Build Coastguard Worker       bool had_new_tag = env->object_tag_table->RemoveLocked(it.second, &new_tag);
1829*795d594fSAndroid Build Coastguard Worker       // Dispatch event.
1830*795d594fSAndroid Build Coastguard Worker       if (had_obsolete_tag || had_new_tag) {
1831*795d594fSAndroid Build Coastguard Worker         event_handler->DispatchEventOnEnv<ArtJvmtiEvent::kObsoleteObjectCreated>(
1832*795d594fSAndroid Build Coastguard Worker             env, self, &obsolete_tag, &new_tag);
1833*795d594fSAndroid Build Coastguard Worker         changed_tags.try_emplace(env).first->second.push_back(
1834*795d594fSAndroid Build Coastguard Worker             { it.first, obsolete_tag, it.second, new_tag });
1835*795d594fSAndroid Build Coastguard Worker       }
1836*795d594fSAndroid Build Coastguard Worker     }
1837*795d594fSAndroid Build Coastguard Worker     // After weak-ref update we need to go back and re-add obsoletes. We wait to avoid having to
1838*795d594fSAndroid Build Coastguard Worker     // deal with the visit-weaks overwriting the initial new_obj_ptr tag and generally making things
1839*795d594fSAndroid Build Coastguard Worker     // difficult.
1840*795d594fSAndroid Build Coastguard Worker     env->object_tag_table->Unlock();
1841*795d594fSAndroid Build Coastguard Worker   });
1842*795d594fSAndroid Build Coastguard Worker   // Handle weak-refs.
1843*795d594fSAndroid Build Coastguard Worker   struct ReplaceWeaksVisitor : public art::IsMarkedVisitor {
1844*795d594fSAndroid Build Coastguard Worker    public:
1845*795d594fSAndroid Build Coastguard Worker     ReplaceWeaksVisitor(const ObjectMap& map) : map_(map) {}
1846*795d594fSAndroid Build Coastguard Worker 
1847*795d594fSAndroid Build Coastguard Worker     art::mirror::Object* IsMarked(art::mirror::Object* obj)
1848*795d594fSAndroid Build Coastguard Worker         REQUIRES_SHARED(art::Locks::mutator_lock_) {
1849*795d594fSAndroid Build Coastguard Worker       auto it = map_.find(obj);
1850*795d594fSAndroid Build Coastguard Worker       if (it != map_.end()) {
1851*795d594fSAndroid Build Coastguard Worker         return it->second.Ptr();
1852*795d594fSAndroid Build Coastguard Worker       } else {
1853*795d594fSAndroid Build Coastguard Worker         return obj;
1854*795d594fSAndroid Build Coastguard Worker       }
1855*795d594fSAndroid Build Coastguard Worker     }
1856*795d594fSAndroid Build Coastguard Worker 
1857*795d594fSAndroid Build Coastguard Worker    private:
1858*795d594fSAndroid Build Coastguard Worker     const ObjectMap& map_;
1859*795d594fSAndroid Build Coastguard Worker   };
1860*795d594fSAndroid Build Coastguard Worker   ReplaceWeaksVisitor rwv(map);
1861*795d594fSAndroid Build Coastguard Worker   art::Runtime* runtime = art::Runtime::Current();
1862*795d594fSAndroid Build Coastguard Worker   runtime->SweepSystemWeaks(&rwv);
1863*795d594fSAndroid Build Coastguard Worker   runtime->GetThreadList()->SweepInterpreterCaches(&rwv);
1864*795d594fSAndroid Build Coastguard Worker   // Re-add the object tags. At this point all weak-references to the old_obj_ptr are gone.
1865*795d594fSAndroid Build Coastguard Worker   event_handler->ForEachEnv(self, [&](ArtJvmTiEnv* env) {
1866*795d594fSAndroid Build Coastguard Worker     // Cannot have REQUIRES(art::Locks::mutator_lock_) since ForEachEnv doesn't require it.
1867*795d594fSAndroid Build Coastguard Worker     art::Locks::mutator_lock_->AssertExclusiveHeld(self);
1868*795d594fSAndroid Build Coastguard Worker     env->object_tag_table->Lock();
1869*795d594fSAndroid Build Coastguard Worker     auto it = changed_tags.find(env);
1870*795d594fSAndroid Build Coastguard Worker     if (it != changed_tags.end()) {
1871*795d594fSAndroid Build Coastguard Worker       for (const NewTagValue& v : it->second) {
1872*795d594fSAndroid Build Coastguard Worker         env->object_tag_table->SetLocked(v.obsolete_obj_, v.obsolete_tag_);
1873*795d594fSAndroid Build Coastguard Worker         env->object_tag_table->SetLocked(v.new_obj_, v.new_tag_);
1874*795d594fSAndroid Build Coastguard Worker       }
1875*795d594fSAndroid Build Coastguard Worker     }
1876*795d594fSAndroid Build Coastguard Worker     env->object_tag_table->Unlock();
1877*795d594fSAndroid Build Coastguard Worker   });
1878*795d594fSAndroid Build Coastguard Worker }
1879*795d594fSAndroid Build Coastguard Worker 
1880*795d594fSAndroid Build Coastguard Worker }  // namespace
1881*795d594fSAndroid Build Coastguard Worker 
ReplaceReference(art::Thread * self,art::ObjPtr<art::mirror::Object> old_obj_ptr,art::ObjPtr<art::mirror::Object> new_obj_ptr)1882*795d594fSAndroid Build Coastguard Worker void HeapExtensions::ReplaceReference(art::Thread* self,
1883*795d594fSAndroid Build Coastguard Worker                                       art::ObjPtr<art::mirror::Object> old_obj_ptr,
1884*795d594fSAndroid Build Coastguard Worker                                       art::ObjPtr<art::mirror::Object> new_obj_ptr) {
1885*795d594fSAndroid Build Coastguard Worker   ObjectMap map { { old_obj_ptr, new_obj_ptr } };
1886*795d594fSAndroid Build Coastguard Worker   ReplaceReferences(self, map);
1887*795d594fSAndroid Build Coastguard Worker }
1888*795d594fSAndroid Build Coastguard Worker 
ReplaceReferences(art::Thread * self,const ObjectMap & map)1889*795d594fSAndroid Build Coastguard Worker void HeapExtensions::ReplaceReferences(art::Thread* self, const ObjectMap& map) {
1890*795d594fSAndroid Build Coastguard Worker   ReplaceObjectReferences(map);
1891*795d594fSAndroid Build Coastguard Worker   ReplaceStrongRoots(self, map);
1892*795d594fSAndroid Build Coastguard Worker   ReplaceWeakRoots(self, HeapExtensions::gEventHandler, map);
1893*795d594fSAndroid Build Coastguard Worker }
1894*795d594fSAndroid Build Coastguard Worker 
ChangeArraySize(jvmtiEnv * env,jobject arr,jsize new_size)1895*795d594fSAndroid Build Coastguard Worker jvmtiError HeapExtensions::ChangeArraySize(jvmtiEnv* env, jobject arr, jsize new_size) {
1896*795d594fSAndroid Build Coastguard Worker   if (ArtJvmTiEnv::AsArtJvmTiEnv(env)->capabilities.can_tag_objects != 1) {
1897*795d594fSAndroid Build Coastguard Worker     return ERR(MUST_POSSESS_CAPABILITY);
1898*795d594fSAndroid Build Coastguard Worker   }
1899*795d594fSAndroid Build Coastguard Worker   art::Thread* self = art::Thread::Current();
1900*795d594fSAndroid Build Coastguard Worker   ScopedNoUserCodeSuspension snucs(self);
1901*795d594fSAndroid Build Coastguard Worker   art::ScopedObjectAccess soa(self);
1902*795d594fSAndroid Build Coastguard Worker   if (arr == nullptr) {
1903*795d594fSAndroid Build Coastguard Worker     JVMTI_LOG(INFO, env) << "Cannot resize a null object";
1904*795d594fSAndroid Build Coastguard Worker     return ERR(NULL_POINTER);
1905*795d594fSAndroid Build Coastguard Worker   }
1906*795d594fSAndroid Build Coastguard Worker   art::ObjPtr<art::mirror::Class> klass(soa.Decode<art::mirror::Object>(arr)->GetClass());
1907*795d594fSAndroid Build Coastguard Worker   if (!klass->IsArrayClass()) {
1908*795d594fSAndroid Build Coastguard Worker     JVMTI_LOG(INFO, env) << klass->PrettyClass() << " is not an array class!";
1909*795d594fSAndroid Build Coastguard Worker     return ERR(ILLEGAL_ARGUMENT);
1910*795d594fSAndroid Build Coastguard Worker   }
1911*795d594fSAndroid Build Coastguard Worker   if (new_size < 0) {
1912*795d594fSAndroid Build Coastguard Worker     JVMTI_LOG(INFO, env) << "Cannot resize an array to a negative size";
1913*795d594fSAndroid Build Coastguard Worker     return ERR(ILLEGAL_ARGUMENT);
1914*795d594fSAndroid Build Coastguard Worker   }
1915*795d594fSAndroid Build Coastguard Worker   // Allocate the new copy.
1916*795d594fSAndroid Build Coastguard Worker   art::StackHandleScope<2> hs(self);
1917*795d594fSAndroid Build Coastguard Worker   art::Handle<art::mirror::Array> old_arr(hs.NewHandle(soa.Decode<art::mirror::Array>(arr)));
1918*795d594fSAndroid Build Coastguard Worker   art::MutableHandle<art::mirror::Array> new_arr(hs.NewHandle<art::mirror::Array>(nullptr));
1919*795d594fSAndroid Build Coastguard Worker   if (klass->IsObjectArrayClass()) {
1920*795d594fSAndroid Build Coastguard Worker     new_arr.Assign(
1921*795d594fSAndroid Build Coastguard Worker         art::mirror::ObjectArray<art::mirror::Object>::Alloc(self, old_arr->GetClass(), new_size));
1922*795d594fSAndroid Build Coastguard Worker   } else {
1923*795d594fSAndroid Build Coastguard Worker     // NB This also copies the old array but since we aren't suspended we need to do this again to
1924*795d594fSAndroid Build Coastguard Worker     // catch any concurrent modifications.
1925*795d594fSAndroid Build Coastguard Worker     new_arr.Assign(art::mirror::Array::CopyOf(old_arr, self, new_size));
1926*795d594fSAndroid Build Coastguard Worker   }
1927*795d594fSAndroid Build Coastguard Worker   if (new_arr.IsNull()) {
1928*795d594fSAndroid Build Coastguard Worker     self->AssertPendingOOMException();
1929*795d594fSAndroid Build Coastguard Worker     JVMTI_LOG(INFO, env) << "Unable to allocate " << old_arr->GetClass()->PrettyClass()
1930*795d594fSAndroid Build Coastguard Worker                          << " (length: " << new_size << ") due to OOME. Error was: "
1931*795d594fSAndroid Build Coastguard Worker                          << self->GetException()->Dump();
1932*795d594fSAndroid Build Coastguard Worker     self->ClearException();
1933*795d594fSAndroid Build Coastguard Worker     return ERR(OUT_OF_MEMORY);
1934*795d594fSAndroid Build Coastguard Worker   } else {
1935*795d594fSAndroid Build Coastguard Worker     self->AssertNoPendingException();
1936*795d594fSAndroid Build Coastguard Worker   }
1937*795d594fSAndroid Build Coastguard Worker   // Suspend everything.
1938*795d594fSAndroid Build Coastguard Worker   art::ScopedThreadSuspension sts(self, art::ThreadState::kSuspended);
1939*795d594fSAndroid Build Coastguard Worker   art::gc::ScopedGCCriticalSection sgccs(
1940*795d594fSAndroid Build Coastguard Worker       self, art::gc::GcCause::kGcCauseDebugger, art::gc::CollectorType::kCollectorTypeDebugger);
1941*795d594fSAndroid Build Coastguard Worker   art::ScopedSuspendAll ssa("Resize array!");
1942*795d594fSAndroid Build Coastguard Worker   // Replace internals.
1943*795d594fSAndroid Build Coastguard Worker   new_arr->SetLockWord(old_arr->GetLockWord(false), false);
1944*795d594fSAndroid Build Coastguard Worker   old_arr->SetLockWord(art::LockWord::Default(), false);
1945*795d594fSAndroid Build Coastguard Worker   // Copy the contents now when everything is suspended.
1946*795d594fSAndroid Build Coastguard Worker   int32_t size = std::min(old_arr->GetLength(), new_size);
1947*795d594fSAndroid Build Coastguard Worker   switch (old_arr->GetClass()->GetComponentType()->GetPrimitiveType()) {
1948*795d594fSAndroid Build Coastguard Worker     case art::Primitive::kPrimBoolean:
1949*795d594fSAndroid Build Coastguard Worker       new_arr->AsBooleanArray()->Memcpy(0, old_arr->AsBooleanArray(), 0, size);
1950*795d594fSAndroid Build Coastguard Worker       break;
1951*795d594fSAndroid Build Coastguard Worker     case art::Primitive::kPrimByte:
1952*795d594fSAndroid Build Coastguard Worker       new_arr->AsByteArray()->Memcpy(0, old_arr->AsByteArray(), 0, size);
1953*795d594fSAndroid Build Coastguard Worker       break;
1954*795d594fSAndroid Build Coastguard Worker     case art::Primitive::kPrimChar:
1955*795d594fSAndroid Build Coastguard Worker       new_arr->AsCharArray()->Memcpy(0, old_arr->AsCharArray(), 0, size);
1956*795d594fSAndroid Build Coastguard Worker       break;
1957*795d594fSAndroid Build Coastguard Worker     case art::Primitive::kPrimShort:
1958*795d594fSAndroid Build Coastguard Worker       new_arr->AsShortArray()->Memcpy(0, old_arr->AsShortArray(), 0, size);
1959*795d594fSAndroid Build Coastguard Worker       break;
1960*795d594fSAndroid Build Coastguard Worker     case art::Primitive::kPrimInt:
1961*795d594fSAndroid Build Coastguard Worker       new_arr->AsIntArray()->Memcpy(0, old_arr->AsIntArray(), 0, size);
1962*795d594fSAndroid Build Coastguard Worker       break;
1963*795d594fSAndroid Build Coastguard Worker     case art::Primitive::kPrimLong:
1964*795d594fSAndroid Build Coastguard Worker       new_arr->AsLongArray()->Memcpy(0, old_arr->AsLongArray(), 0, size);
1965*795d594fSAndroid Build Coastguard Worker       break;
1966*795d594fSAndroid Build Coastguard Worker     case art::Primitive::kPrimFloat:
1967*795d594fSAndroid Build Coastguard Worker       new_arr->AsFloatArray()->Memcpy(0, old_arr->AsFloatArray(), 0, size);
1968*795d594fSAndroid Build Coastguard Worker       break;
1969*795d594fSAndroid Build Coastguard Worker     case art::Primitive::kPrimDouble:
1970*795d594fSAndroid Build Coastguard Worker       new_arr->AsDoubleArray()->Memcpy(0, old_arr->AsDoubleArray(), 0, size);
1971*795d594fSAndroid Build Coastguard Worker       break;
1972*795d594fSAndroid Build Coastguard Worker     case art::Primitive::kPrimNot:
1973*795d594fSAndroid Build Coastguard Worker       for (int32_t i = 0; i < size; i++) {
1974*795d594fSAndroid Build Coastguard Worker         new_arr->AsObjectArray<art::mirror::Object>()->Set(
1975*795d594fSAndroid Build Coastguard Worker             i, old_arr->AsObjectArray<art::mirror::Object>()->Get(i));
1976*795d594fSAndroid Build Coastguard Worker       }
1977*795d594fSAndroid Build Coastguard Worker       break;
1978*795d594fSAndroid Build Coastguard Worker     case art::Primitive::kPrimVoid:
1979*795d594fSAndroid Build Coastguard Worker       LOG(FATAL) << "void-array is not a legal type!";
1980*795d594fSAndroid Build Coastguard Worker       UNREACHABLE();
1981*795d594fSAndroid Build Coastguard Worker   }
1982*795d594fSAndroid Build Coastguard Worker   // Actually replace all the pointers.
1983*795d594fSAndroid Build Coastguard Worker   ReplaceReference(self, old_arr.Get(), new_arr.Get());
1984*795d594fSAndroid Build Coastguard Worker   return OK;
1985*795d594fSAndroid Build Coastguard Worker }
1986*795d594fSAndroid Build Coastguard Worker 
Register(EventHandler * eh)1987*795d594fSAndroid Build Coastguard Worker void HeapExtensions::Register(EventHandler* eh) {
1988*795d594fSAndroid Build Coastguard Worker   gEventHandler = eh;
1989*795d594fSAndroid Build Coastguard Worker }
1990*795d594fSAndroid Build Coastguard Worker 
1991*795d594fSAndroid Build Coastguard Worker }  // namespace openjdkjvmti
1992