1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2013 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 <inttypes.h>
18*795d594fSAndroid Build Coastguard Worker
19*795d594fSAndroid Build Coastguard Worker #include <cstdio>
20*795d594fSAndroid Build Coastguard Worker #include <cstring>
21*795d594fSAndroid Build Coastguard Worker #include <iostream>
22*795d594fSAndroid Build Coastguard Worker #include <map>
23*795d594fSAndroid Build Coastguard Worker #include <sstream>
24*795d594fSAndroid Build Coastguard Worker #include <vector>
25*795d594fSAndroid Build Coastguard Worker
26*795d594fSAndroid Build Coastguard Worker #include "android-base/logging.h"
27*795d594fSAndroid Build Coastguard Worker #include "android-base/macros.h"
28*795d594fSAndroid Build Coastguard Worker #include "android-base/stringprintf.h"
29*795d594fSAndroid Build Coastguard Worker
30*795d594fSAndroid Build Coastguard Worker #include "jni.h"
31*795d594fSAndroid Build Coastguard Worker #include "jvmti.h"
32*795d594fSAndroid Build Coastguard Worker
33*795d594fSAndroid Build Coastguard Worker // Test infrastructure
34*795d594fSAndroid Build Coastguard Worker #include "jni_helper.h"
35*795d594fSAndroid Build Coastguard Worker #include "jvmti_helper.h"
36*795d594fSAndroid Build Coastguard Worker #include "test_env.h"
37*795d594fSAndroid Build Coastguard Worker #include "ti_utf.h"
38*795d594fSAndroid Build Coastguard Worker
39*795d594fSAndroid Build Coastguard Worker namespace art {
40*795d594fSAndroid Build Coastguard Worker namespace Test913Heaps {
41*795d594fSAndroid Build Coastguard Worker
42*795d594fSAndroid Build Coastguard Worker using android::base::StringPrintf;
43*795d594fSAndroid Build Coastguard Worker
44*795d594fSAndroid Build Coastguard Worker #define UNREACHABLE __builtin_unreachable
45*795d594fSAndroid Build Coastguard Worker
46*795d594fSAndroid Build Coastguard Worker // The tag value used on the Java side to tag the current thread.
47*795d594fSAndroid Build Coastguard Worker static constexpr jlong kThreadTag = 3000;
48*795d594fSAndroid Build Coastguard Worker static constexpr const char* kThreadReferree = "3000@0";
49*795d594fSAndroid Build Coastguard Worker
Java_art_Test913_forceGarbageCollection(JNIEnv * env,jclass klass)50*795d594fSAndroid Build Coastguard Worker extern "C" JNIEXPORT void JNICALL Java_art_Test913_forceGarbageCollection(
51*795d594fSAndroid Build Coastguard Worker JNIEnv* env, [[maybe_unused]] jclass klass) {
52*795d594fSAndroid Build Coastguard Worker jvmtiError ret = jvmti_env->ForceGarbageCollection();
53*795d594fSAndroid Build Coastguard Worker JvmtiErrorToException(env, jvmti_env, ret);
54*795d594fSAndroid Build Coastguard Worker }
55*795d594fSAndroid Build Coastguard Worker
56*795d594fSAndroid Build Coastguard Worker // Collect sizes of objects (classes) ahead of time, to be able to normalize.
57*795d594fSAndroid Build Coastguard Worker struct ClassData {
58*795d594fSAndroid Build Coastguard Worker jlong size; // Size as reported by GetObjectSize.
59*795d594fSAndroid Build Coastguard Worker jlong serial; // Computed serial that should be printed instead of the size.
60*795d594fSAndroid Build Coastguard Worker };
61*795d594fSAndroid Build Coastguard Worker
62*795d594fSAndroid Build Coastguard Worker // Stores a map from tags to ClassData.
63*795d594fSAndroid Build Coastguard Worker static std::map<jlong, ClassData> sClassData;
64*795d594fSAndroid Build Coastguard Worker static size_t sClassDataSerial = 0;
65*795d594fSAndroid Build Coastguard Worker // Large enough number that a collision with a test object is unlikely.
66*795d594fSAndroid Build Coastguard Worker static constexpr jlong kClassDataSerialBase = 123456780000;
67*795d594fSAndroid Build Coastguard Worker
68*795d594fSAndroid Build Coastguard Worker // Register a class (or general object) in the class-data map. The serial number is determined by
69*795d594fSAndroid Build Coastguard Worker // the order of calls to this function (so stable Java code leads to stable numbering).
Java_art_Test913_registerClass(JNIEnv * env,jclass klass,jlong tag,jobject obj)70*795d594fSAndroid Build Coastguard Worker extern "C" JNIEXPORT void JNICALL Java_art_Test913_registerClass(
71*795d594fSAndroid Build Coastguard Worker JNIEnv* env, [[maybe_unused]] jclass klass, jlong tag, jobject obj) {
72*795d594fSAndroid Build Coastguard Worker ClassData data;
73*795d594fSAndroid Build Coastguard Worker if (JvmtiErrorToException(env, jvmti_env, jvmti_env->GetObjectSize(obj, &data.size))) {
74*795d594fSAndroid Build Coastguard Worker return;
75*795d594fSAndroid Build Coastguard Worker }
76*795d594fSAndroid Build Coastguard Worker data.serial = kClassDataSerialBase + sClassDataSerial++;
77*795d594fSAndroid Build Coastguard Worker // Remove old element, if it exists.
78*795d594fSAndroid Build Coastguard Worker auto old = sClassData.find(tag);
79*795d594fSAndroid Build Coastguard Worker if (old != sClassData.end()) {
80*795d594fSAndroid Build Coastguard Worker sClassData.erase(old);
81*795d594fSAndroid Build Coastguard Worker }
82*795d594fSAndroid Build Coastguard Worker // Now insert the new mapping.
83*795d594fSAndroid Build Coastguard Worker sClassData.insert(std::pair<jlong, ClassData>(tag, data));
84*795d594fSAndroid Build Coastguard Worker }
85*795d594fSAndroid Build Coastguard Worker
86*795d594fSAndroid Build Coastguard Worker class IterationConfig {
87*795d594fSAndroid Build Coastguard Worker public:
IterationConfig()88*795d594fSAndroid Build Coastguard Worker IterationConfig() {}
~IterationConfig()89*795d594fSAndroid Build Coastguard Worker virtual ~IterationConfig() {}
90*795d594fSAndroid Build Coastguard Worker
91*795d594fSAndroid Build Coastguard Worker virtual jint Handle(jvmtiHeapReferenceKind reference_kind,
92*795d594fSAndroid Build Coastguard Worker const jvmtiHeapReferenceInfo* reference_info,
93*795d594fSAndroid Build Coastguard Worker jlong class_tag,
94*795d594fSAndroid Build Coastguard Worker jlong referrer_class_tag,
95*795d594fSAndroid Build Coastguard Worker jlong size,
96*795d594fSAndroid Build Coastguard Worker jlong* tag_ptr,
97*795d594fSAndroid Build Coastguard Worker jlong* referrer_tag_ptr,
98*795d594fSAndroid Build Coastguard Worker jint length,
99*795d594fSAndroid Build Coastguard Worker void* user_data) = 0;
100*795d594fSAndroid Build Coastguard Worker };
101*795d594fSAndroid Build Coastguard Worker
HeapReferenceCallback(jvmtiHeapReferenceKind reference_kind,const jvmtiHeapReferenceInfo * reference_info,jlong class_tag,jlong referrer_class_tag,jlong size,jlong * tag_ptr,jlong * referrer_tag_ptr,jint length,void * user_data)102*795d594fSAndroid Build Coastguard Worker static jint JNICALL HeapReferenceCallback(jvmtiHeapReferenceKind reference_kind,
103*795d594fSAndroid Build Coastguard Worker const jvmtiHeapReferenceInfo* reference_info,
104*795d594fSAndroid Build Coastguard Worker jlong class_tag,
105*795d594fSAndroid Build Coastguard Worker jlong referrer_class_tag,
106*795d594fSAndroid Build Coastguard Worker jlong size,
107*795d594fSAndroid Build Coastguard Worker jlong* tag_ptr,
108*795d594fSAndroid Build Coastguard Worker jlong* referrer_tag_ptr,
109*795d594fSAndroid Build Coastguard Worker jint length,
110*795d594fSAndroid Build Coastguard Worker void* user_data) {
111*795d594fSAndroid Build Coastguard Worker IterationConfig* config = reinterpret_cast<IterationConfig*>(user_data);
112*795d594fSAndroid Build Coastguard Worker return config->Handle(reference_kind,
113*795d594fSAndroid Build Coastguard Worker reference_info,
114*795d594fSAndroid Build Coastguard Worker class_tag,
115*795d594fSAndroid Build Coastguard Worker referrer_class_tag,
116*795d594fSAndroid Build Coastguard Worker size,
117*795d594fSAndroid Build Coastguard Worker tag_ptr,
118*795d594fSAndroid Build Coastguard Worker referrer_tag_ptr,
119*795d594fSAndroid Build Coastguard Worker length,
120*795d594fSAndroid Build Coastguard Worker user_data);
121*795d594fSAndroid Build Coastguard Worker }
122*795d594fSAndroid Build Coastguard Worker
Run(JNIEnv * env,jint heap_filter,jclass klass_filter,jobject initial_object,IterationConfig * config)123*795d594fSAndroid Build Coastguard Worker static bool Run(JNIEnv* env,
124*795d594fSAndroid Build Coastguard Worker jint heap_filter,
125*795d594fSAndroid Build Coastguard Worker jclass klass_filter,
126*795d594fSAndroid Build Coastguard Worker jobject initial_object,
127*795d594fSAndroid Build Coastguard Worker IterationConfig* config) {
128*795d594fSAndroid Build Coastguard Worker jvmtiHeapCallbacks callbacks;
129*795d594fSAndroid Build Coastguard Worker memset(&callbacks, 0, sizeof(jvmtiHeapCallbacks));
130*795d594fSAndroid Build Coastguard Worker callbacks.heap_reference_callback = HeapReferenceCallback;
131*795d594fSAndroid Build Coastguard Worker
132*795d594fSAndroid Build Coastguard Worker jvmtiError ret = jvmti_env->FollowReferences(heap_filter,
133*795d594fSAndroid Build Coastguard Worker klass_filter,
134*795d594fSAndroid Build Coastguard Worker initial_object,
135*795d594fSAndroid Build Coastguard Worker &callbacks,
136*795d594fSAndroid Build Coastguard Worker config);
137*795d594fSAndroid Build Coastguard Worker return !JvmtiErrorToException(env, jvmti_env, ret);
138*795d594fSAndroid Build Coastguard Worker }
139*795d594fSAndroid Build Coastguard Worker
Java_art_Test913_followReferences(JNIEnv * env,jclass klass,jint heap_filter,jclass klass_filter,jobject initial_object,jint stop_after,jint follow_set,jobject jniRef)140*795d594fSAndroid Build Coastguard Worker extern "C" JNIEXPORT jobjectArray JNICALL Java_art_Test913_followReferences(
141*795d594fSAndroid Build Coastguard Worker JNIEnv* env,
142*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] jclass klass,
143*795d594fSAndroid Build Coastguard Worker jint heap_filter,
144*795d594fSAndroid Build Coastguard Worker jclass klass_filter,
145*795d594fSAndroid Build Coastguard Worker jobject initial_object,
146*795d594fSAndroid Build Coastguard Worker jint stop_after,
147*795d594fSAndroid Build Coastguard Worker jint follow_set,
148*795d594fSAndroid Build Coastguard Worker jobject jniRef) {
149*795d594fSAndroid Build Coastguard Worker class PrintIterationConfig final : public IterationConfig {
150*795d594fSAndroid Build Coastguard Worker public:
151*795d594fSAndroid Build Coastguard Worker PrintIterationConfig(jint _stop_after, jint _follow_set)
152*795d594fSAndroid Build Coastguard Worker : counter_(0),
153*795d594fSAndroid Build Coastguard Worker stop_after_(_stop_after),
154*795d594fSAndroid Build Coastguard Worker follow_set_(_follow_set) {
155*795d594fSAndroid Build Coastguard Worker }
156*795d594fSAndroid Build Coastguard Worker
157*795d594fSAndroid Build Coastguard Worker jint Handle(jvmtiHeapReferenceKind reference_kind,
158*795d594fSAndroid Build Coastguard Worker const jvmtiHeapReferenceInfo* reference_info,
159*795d594fSAndroid Build Coastguard Worker jlong class_tag,
160*795d594fSAndroid Build Coastguard Worker jlong referrer_class_tag,
161*795d594fSAndroid Build Coastguard Worker jlong size,
162*795d594fSAndroid Build Coastguard Worker jlong* tag_ptr,
163*795d594fSAndroid Build Coastguard Worker jlong* referrer_tag_ptr,
164*795d594fSAndroid Build Coastguard Worker jint length,
165*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] void* user_data) override {
166*795d594fSAndroid Build Coastguard Worker jlong tag = *tag_ptr;
167*795d594fSAndroid Build Coastguard Worker
168*795d594fSAndroid Build Coastguard Worker // Ignore any jni-global roots with untagged classes. These can be from the environment,
169*795d594fSAndroid Build Coastguard Worker // or the JIT.
170*795d594fSAndroid Build Coastguard Worker if (reference_kind == JVMTI_HEAP_REFERENCE_JNI_GLOBAL && class_tag == 0) {
171*795d594fSAndroid Build Coastguard Worker return 0;
172*795d594fSAndroid Build Coastguard Worker }
173*795d594fSAndroid Build Coastguard Worker // Ignore HEAP_REFERENCE_OTHER roots because these are vm-internal roots and can vary
174*795d594fSAndroid Build Coastguard Worker // depending on the configuration of the runtime (notably having trampoline tracing will add a
175*795d594fSAndroid Build Coastguard Worker // lot of these).
176*795d594fSAndroid Build Coastguard Worker if (reference_kind == JVMTI_HEAP_REFERENCE_OTHER) {
177*795d594fSAndroid Build Coastguard Worker return 0;
178*795d594fSAndroid Build Coastguard Worker }
179*795d594fSAndroid Build Coastguard Worker // Ignore classes (1000 <= tag < 3000) for thread objects. These can be held by the JIT.
180*795d594fSAndroid Build Coastguard Worker if (reference_kind == JVMTI_HEAP_REFERENCE_THREAD && class_tag == 0 &&
181*795d594fSAndroid Build Coastguard Worker (1000 <= *tag_ptr && *tag_ptr < kThreadTag)) {
182*795d594fSAndroid Build Coastguard Worker return 0;
183*795d594fSAndroid Build Coastguard Worker }
184*795d594fSAndroid Build Coastguard Worker // Ignore stack-locals of untagged threads. That is the environment.
185*795d594fSAndroid Build Coastguard Worker if (reference_kind == JVMTI_HEAP_REFERENCE_STACK_LOCAL &&
186*795d594fSAndroid Build Coastguard Worker reference_info->stack_local.thread_tag != kThreadTag) {
187*795d594fSAndroid Build Coastguard Worker return 0;
188*795d594fSAndroid Build Coastguard Worker }
189*795d594fSAndroid Build Coastguard Worker // Ignore array elements with an untagged source. These are from the environment.
190*795d594fSAndroid Build Coastguard Worker if (reference_kind == JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT && *referrer_tag_ptr == 0) {
191*795d594fSAndroid Build Coastguard Worker return 0;
192*795d594fSAndroid Build Coastguard Worker }
193*795d594fSAndroid Build Coastguard Worker
194*795d594fSAndroid Build Coastguard Worker // Ignore system classes, which may come from the JIT compiling a method
195*795d594fSAndroid Build Coastguard Worker // in these classes.
196*795d594fSAndroid Build Coastguard Worker if (reference_kind == JVMTI_HEAP_REFERENCE_SYSTEM_CLASS) {
197*795d594fSAndroid Build Coastguard Worker return 0;
198*795d594fSAndroid Build Coastguard Worker }
199*795d594fSAndroid Build Coastguard Worker
200*795d594fSAndroid Build Coastguard Worker // Only check tagged objects.
201*795d594fSAndroid Build Coastguard Worker if (tag == 0) {
202*795d594fSAndroid Build Coastguard Worker return JVMTI_VISIT_OBJECTS;
203*795d594fSAndroid Build Coastguard Worker }
204*795d594fSAndroid Build Coastguard Worker
205*795d594fSAndroid Build Coastguard Worker Print(reference_kind,
206*795d594fSAndroid Build Coastguard Worker reference_info,
207*795d594fSAndroid Build Coastguard Worker class_tag,
208*795d594fSAndroid Build Coastguard Worker referrer_class_tag,
209*795d594fSAndroid Build Coastguard Worker size,
210*795d594fSAndroid Build Coastguard Worker tag_ptr,
211*795d594fSAndroid Build Coastguard Worker referrer_tag_ptr,
212*795d594fSAndroid Build Coastguard Worker length);
213*795d594fSAndroid Build Coastguard Worker
214*795d594fSAndroid Build Coastguard Worker counter_++;
215*795d594fSAndroid Build Coastguard Worker if (counter_ == stop_after_) {
216*795d594fSAndroid Build Coastguard Worker return JVMTI_VISIT_ABORT;
217*795d594fSAndroid Build Coastguard Worker }
218*795d594fSAndroid Build Coastguard Worker
219*795d594fSAndroid Build Coastguard Worker if (tag > 0 && tag < 32) {
220*795d594fSAndroid Build Coastguard Worker bool should_visit_references = (follow_set_ & (1 << static_cast<int32_t>(tag))) != 0;
221*795d594fSAndroid Build Coastguard Worker return should_visit_references ? JVMTI_VISIT_OBJECTS : 0;
222*795d594fSAndroid Build Coastguard Worker }
223*795d594fSAndroid Build Coastguard Worker
224*795d594fSAndroid Build Coastguard Worker return JVMTI_VISIT_OBJECTS;
225*795d594fSAndroid Build Coastguard Worker }
226*795d594fSAndroid Build Coastguard Worker
227*795d594fSAndroid Build Coastguard Worker void Print(jvmtiHeapReferenceKind reference_kind,
228*795d594fSAndroid Build Coastguard Worker const jvmtiHeapReferenceInfo* reference_info,
229*795d594fSAndroid Build Coastguard Worker jlong class_tag,
230*795d594fSAndroid Build Coastguard Worker jlong referrer_class_tag,
231*795d594fSAndroid Build Coastguard Worker jlong size,
232*795d594fSAndroid Build Coastguard Worker jlong* tag_ptr,
233*795d594fSAndroid Build Coastguard Worker jlong* referrer_tag_ptr,
234*795d594fSAndroid Build Coastguard Worker jint length) {
235*795d594fSAndroid Build Coastguard Worker std::string referrer_str;
236*795d594fSAndroid Build Coastguard Worker if (referrer_tag_ptr == nullptr) {
237*795d594fSAndroid Build Coastguard Worker referrer_str = "root@root";
238*795d594fSAndroid Build Coastguard Worker } else {
239*795d594fSAndroid Build Coastguard Worker referrer_str = StringPrintf("%" PRId64 "@%" PRId64, *referrer_tag_ptr, referrer_class_tag);
240*795d594fSAndroid Build Coastguard Worker }
241*795d594fSAndroid Build Coastguard Worker
242*795d594fSAndroid Build Coastguard Worker jlong adapted_size = size;
243*795d594fSAndroid Build Coastguard Worker if (*tag_ptr != 0) {
244*795d594fSAndroid Build Coastguard Worker // This is a class or interface, the size of which will be dependent on the architecture.
245*795d594fSAndroid Build Coastguard Worker // Do not print the size, but detect known values and "normalize" for the golden file.
246*795d594fSAndroid Build Coastguard Worker auto it = sClassData.find(*tag_ptr);
247*795d594fSAndroid Build Coastguard Worker if (it != sClassData.end()) {
248*795d594fSAndroid Build Coastguard Worker const ClassData& class_data = it->second;
249*795d594fSAndroid Build Coastguard Worker if (class_data.size == size) {
250*795d594fSAndroid Build Coastguard Worker adapted_size = class_data.serial;
251*795d594fSAndroid Build Coastguard Worker } else {
252*795d594fSAndroid Build Coastguard Worker adapted_size = 0xDEADDEAD;
253*795d594fSAndroid Build Coastguard Worker }
254*795d594fSAndroid Build Coastguard Worker }
255*795d594fSAndroid Build Coastguard Worker }
256*795d594fSAndroid Build Coastguard Worker
257*795d594fSAndroid Build Coastguard Worker std::string referree_str = StringPrintf("%" PRId64 "@%" PRId64, *tag_ptr, class_tag);
258*795d594fSAndroid Build Coastguard Worker
259*795d594fSAndroid Build Coastguard Worker lines_.push_back(CreateElem(referrer_str,
260*795d594fSAndroid Build Coastguard Worker referree_str,
261*795d594fSAndroid Build Coastguard Worker reference_kind,
262*795d594fSAndroid Build Coastguard Worker reference_info,
263*795d594fSAndroid Build Coastguard Worker adapted_size,
264*795d594fSAndroid Build Coastguard Worker length));
265*795d594fSAndroid Build Coastguard Worker }
266*795d594fSAndroid Build Coastguard Worker
267*795d594fSAndroid Build Coastguard Worker std::vector<std::string> GetLines() const {
268*795d594fSAndroid Build Coastguard Worker std::vector<std::string> ret;
269*795d594fSAndroid Build Coastguard Worker ret.reserve(lines_.size());
270*795d594fSAndroid Build Coastguard Worker for (const std::unique_ptr<Elem>& e : lines_) {
271*795d594fSAndroid Build Coastguard Worker ret.push_back(e->Print());
272*795d594fSAndroid Build Coastguard Worker }
273*795d594fSAndroid Build Coastguard Worker return ret;
274*795d594fSAndroid Build Coastguard Worker }
275*795d594fSAndroid Build Coastguard Worker
276*795d594fSAndroid Build Coastguard Worker private:
277*795d594fSAndroid Build Coastguard Worker // We need to postpone some printing, as required functions are not callback-safe.
278*795d594fSAndroid Build Coastguard Worker class Elem {
279*795d594fSAndroid Build Coastguard Worker public:
280*795d594fSAndroid Build Coastguard Worker Elem(const std::string& referrer, const std::string& referree, jlong size, jint length)
281*795d594fSAndroid Build Coastguard Worker : referrer_(referrer), referree_(referree), size_(size), length_(length) {}
282*795d594fSAndroid Build Coastguard Worker virtual ~Elem() {}
283*795d594fSAndroid Build Coastguard Worker
284*795d594fSAndroid Build Coastguard Worker std::string Print() const {
285*795d594fSAndroid Build Coastguard Worker return StringPrintf("%s --(%s)--> %s [size=%" PRId64 ", length=%d]",
286*795d594fSAndroid Build Coastguard Worker referrer_.c_str(),
287*795d594fSAndroid Build Coastguard Worker PrintArrowType().c_str(),
288*795d594fSAndroid Build Coastguard Worker referree_.c_str(),
289*795d594fSAndroid Build Coastguard Worker size_,
290*795d594fSAndroid Build Coastguard Worker length_);
291*795d594fSAndroid Build Coastguard Worker }
292*795d594fSAndroid Build Coastguard Worker
293*795d594fSAndroid Build Coastguard Worker protected:
294*795d594fSAndroid Build Coastguard Worker virtual std::string PrintArrowType() const = 0;
295*795d594fSAndroid Build Coastguard Worker
296*795d594fSAndroid Build Coastguard Worker private:
297*795d594fSAndroid Build Coastguard Worker std::string referrer_;
298*795d594fSAndroid Build Coastguard Worker std::string referree_;
299*795d594fSAndroid Build Coastguard Worker jlong size_;
300*795d594fSAndroid Build Coastguard Worker jint length_;
301*795d594fSAndroid Build Coastguard Worker };
302*795d594fSAndroid Build Coastguard Worker
303*795d594fSAndroid Build Coastguard Worker class JNILocalElement : public Elem {
304*795d594fSAndroid Build Coastguard Worker public:
305*795d594fSAndroid Build Coastguard Worker JNILocalElement(const std::string& referrer,
306*795d594fSAndroid Build Coastguard Worker const std::string& referree,
307*795d594fSAndroid Build Coastguard Worker jlong size,
308*795d594fSAndroid Build Coastguard Worker jint length,
309*795d594fSAndroid Build Coastguard Worker const jvmtiHeapReferenceInfo* reference_info)
310*795d594fSAndroid Build Coastguard Worker : Elem(referrer, referree, size, length) {
311*795d594fSAndroid Build Coastguard Worker memcpy(&info_, reference_info, sizeof(jvmtiHeapReferenceInfo));
312*795d594fSAndroid Build Coastguard Worker }
313*795d594fSAndroid Build Coastguard Worker
314*795d594fSAndroid Build Coastguard Worker protected:
315*795d594fSAndroid Build Coastguard Worker std::string PrintArrowType() const override {
316*795d594fSAndroid Build Coastguard Worker char* name = nullptr;
317*795d594fSAndroid Build Coastguard Worker if (info_.jni_local.method != nullptr) {
318*795d594fSAndroid Build Coastguard Worker jvmti_env->GetMethodName(info_.jni_local.method, &name, nullptr, nullptr);
319*795d594fSAndroid Build Coastguard Worker }
320*795d594fSAndroid Build Coastguard Worker // Normalize the thread id, as this depends on the number of other threads
321*795d594fSAndroid Build Coastguard Worker // and which thread is running the test. Should be:
322*795d594fSAndroid Build Coastguard Worker // jlong thread_id = info_.jni_local.thread_id;
323*795d594fSAndroid Build Coastguard Worker // TODO: A pre-pass before the test should be able fetch this number, so it can
324*795d594fSAndroid Build Coastguard Worker // be compared explicitly.
325*795d594fSAndroid Build Coastguard Worker jlong thread_id = 1;
326*795d594fSAndroid Build Coastguard Worker std::string ret = StringPrintf("jni-local[id=%" PRId64 ",tag=%" PRId64 ",depth=%d,"
327*795d594fSAndroid Build Coastguard Worker "method=%s]",
328*795d594fSAndroid Build Coastguard Worker thread_id,
329*795d594fSAndroid Build Coastguard Worker info_.jni_local.thread_tag,
330*795d594fSAndroid Build Coastguard Worker info_.jni_local.depth,
331*795d594fSAndroid Build Coastguard Worker name == nullptr ? "<null>" : name);
332*795d594fSAndroid Build Coastguard Worker if (name != nullptr) {
333*795d594fSAndroid Build Coastguard Worker jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(name));
334*795d594fSAndroid Build Coastguard Worker }
335*795d594fSAndroid Build Coastguard Worker
336*795d594fSAndroid Build Coastguard Worker return ret;
337*795d594fSAndroid Build Coastguard Worker }
338*795d594fSAndroid Build Coastguard Worker
339*795d594fSAndroid Build Coastguard Worker private:
340*795d594fSAndroid Build Coastguard Worker const std::string string_;
341*795d594fSAndroid Build Coastguard Worker jvmtiHeapReferenceInfo info_;
342*795d594fSAndroid Build Coastguard Worker };
343*795d594fSAndroid Build Coastguard Worker
344*795d594fSAndroid Build Coastguard Worker class StackLocalElement : public Elem {
345*795d594fSAndroid Build Coastguard Worker public:
346*795d594fSAndroid Build Coastguard Worker StackLocalElement(const std::string& referrer,
347*795d594fSAndroid Build Coastguard Worker const std::string& referree,
348*795d594fSAndroid Build Coastguard Worker jlong size,
349*795d594fSAndroid Build Coastguard Worker jint length,
350*795d594fSAndroid Build Coastguard Worker const jvmtiHeapReferenceInfo* reference_info)
351*795d594fSAndroid Build Coastguard Worker : Elem(referrer, referree, size, length) {
352*795d594fSAndroid Build Coastguard Worker memcpy(&info_, reference_info, sizeof(jvmtiHeapReferenceInfo));
353*795d594fSAndroid Build Coastguard Worker
354*795d594fSAndroid Build Coastguard Worker // Debug code. Try to figure out where bad depth is coming from.
355*795d594fSAndroid Build Coastguard Worker if (reference_info->stack_local.depth == 6) {
356*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected depth of 6";
357*795d594fSAndroid Build Coastguard Worker }
358*795d594fSAndroid Build Coastguard Worker }
359*795d594fSAndroid Build Coastguard Worker
360*795d594fSAndroid Build Coastguard Worker protected:
361*795d594fSAndroid Build Coastguard Worker std::string PrintArrowType() const override {
362*795d594fSAndroid Build Coastguard Worker char* name = nullptr;
363*795d594fSAndroid Build Coastguard Worker if (info_.stack_local.method != nullptr) {
364*795d594fSAndroid Build Coastguard Worker jvmti_env->GetMethodName(info_.stack_local.method, &name, nullptr, nullptr);
365*795d594fSAndroid Build Coastguard Worker }
366*795d594fSAndroid Build Coastguard Worker // Normalize the thread id, as this depends on the number of other threads
367*795d594fSAndroid Build Coastguard Worker // and which thread is running the test. Should be:
368*795d594fSAndroid Build Coastguard Worker // jlong thread_id = info_.stack_local.thread_id;
369*795d594fSAndroid Build Coastguard Worker // TODO: A pre-pass before the test should be able fetch this number, so it can
370*795d594fSAndroid Build Coastguard Worker // be compared explicitly.
371*795d594fSAndroid Build Coastguard Worker jlong thread_id = 1;
372*795d594fSAndroid Build Coastguard Worker std::string ret = StringPrintf("stack-local[id=%" PRId64 ",tag=%" PRId64 ",depth=%d,"
373*795d594fSAndroid Build Coastguard Worker "method=%s,vreg=%d,location=% " PRId64 "]",
374*795d594fSAndroid Build Coastguard Worker thread_id,
375*795d594fSAndroid Build Coastguard Worker info_.stack_local.thread_tag,
376*795d594fSAndroid Build Coastguard Worker info_.stack_local.depth,
377*795d594fSAndroid Build Coastguard Worker name == nullptr ? "<null>" : name,
378*795d594fSAndroid Build Coastguard Worker info_.stack_local.slot,
379*795d594fSAndroid Build Coastguard Worker info_.stack_local.location);
380*795d594fSAndroid Build Coastguard Worker if (name != nullptr) {
381*795d594fSAndroid Build Coastguard Worker jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(name));
382*795d594fSAndroid Build Coastguard Worker }
383*795d594fSAndroid Build Coastguard Worker
384*795d594fSAndroid Build Coastguard Worker return ret;
385*795d594fSAndroid Build Coastguard Worker }
386*795d594fSAndroid Build Coastguard Worker
387*795d594fSAndroid Build Coastguard Worker private:
388*795d594fSAndroid Build Coastguard Worker const std::string string_;
389*795d594fSAndroid Build Coastguard Worker jvmtiHeapReferenceInfo info_;
390*795d594fSAndroid Build Coastguard Worker };
391*795d594fSAndroid Build Coastguard Worker
392*795d594fSAndroid Build Coastguard Worker // For simple or unimplemented cases.
393*795d594fSAndroid Build Coastguard Worker class StringElement : public Elem {
394*795d594fSAndroid Build Coastguard Worker public:
395*795d594fSAndroid Build Coastguard Worker StringElement(const std::string& referrer,
396*795d594fSAndroid Build Coastguard Worker const std::string& referree,
397*795d594fSAndroid Build Coastguard Worker jlong size,
398*795d594fSAndroid Build Coastguard Worker jint length,
399*795d594fSAndroid Build Coastguard Worker const std::string& string)
400*795d594fSAndroid Build Coastguard Worker : Elem(referrer, referree, size, length), string_(string) {}
401*795d594fSAndroid Build Coastguard Worker
402*795d594fSAndroid Build Coastguard Worker protected:
403*795d594fSAndroid Build Coastguard Worker std::string PrintArrowType() const override {
404*795d594fSAndroid Build Coastguard Worker return string_;
405*795d594fSAndroid Build Coastguard Worker }
406*795d594fSAndroid Build Coastguard Worker
407*795d594fSAndroid Build Coastguard Worker private:
408*795d594fSAndroid Build Coastguard Worker const std::string string_;
409*795d594fSAndroid Build Coastguard Worker };
410*795d594fSAndroid Build Coastguard Worker
411*795d594fSAndroid Build Coastguard Worker static std::unique_ptr<Elem> CreateElem(const std::string& referrer,
412*795d594fSAndroid Build Coastguard Worker const std::string& referree,
413*795d594fSAndroid Build Coastguard Worker jvmtiHeapReferenceKind reference_kind,
414*795d594fSAndroid Build Coastguard Worker const jvmtiHeapReferenceInfo* reference_info,
415*795d594fSAndroid Build Coastguard Worker jlong size,
416*795d594fSAndroid Build Coastguard Worker jint length) {
417*795d594fSAndroid Build Coastguard Worker switch (reference_kind) {
418*795d594fSAndroid Build Coastguard Worker case JVMTI_HEAP_REFERENCE_CLASS:
419*795d594fSAndroid Build Coastguard Worker return std::unique_ptr<Elem>(new StringElement(referrer,
420*795d594fSAndroid Build Coastguard Worker referree,
421*795d594fSAndroid Build Coastguard Worker size,
422*795d594fSAndroid Build Coastguard Worker length,
423*795d594fSAndroid Build Coastguard Worker "class"));
424*795d594fSAndroid Build Coastguard Worker case JVMTI_HEAP_REFERENCE_FIELD: {
425*795d594fSAndroid Build Coastguard Worker std::string tmp = StringPrintf("field@%d", reference_info->field.index);
426*795d594fSAndroid Build Coastguard Worker return std::unique_ptr<Elem>(new StringElement(referrer,
427*795d594fSAndroid Build Coastguard Worker referree,
428*795d594fSAndroid Build Coastguard Worker size,
429*795d594fSAndroid Build Coastguard Worker length,
430*795d594fSAndroid Build Coastguard Worker tmp));
431*795d594fSAndroid Build Coastguard Worker }
432*795d594fSAndroid Build Coastguard Worker case JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT: {
433*795d594fSAndroid Build Coastguard Worker jint index = reference_info->array.index;
434*795d594fSAndroid Build Coastguard Worker // Normalize if it's "0@0" -> "3000@1".
435*795d594fSAndroid Build Coastguard Worker // TODO: A pre-pass could probably give us this index to check explicitly.
436*795d594fSAndroid Build Coastguard Worker if (referrer == "0@0" && referree == kThreadReferree) {
437*795d594fSAndroid Build Coastguard Worker index = 0;
438*795d594fSAndroid Build Coastguard Worker }
439*795d594fSAndroid Build Coastguard Worker std::string tmp = StringPrintf("array-element@%d", index);
440*795d594fSAndroid Build Coastguard Worker return std::unique_ptr<Elem>(new StringElement(referrer,
441*795d594fSAndroid Build Coastguard Worker referree,
442*795d594fSAndroid Build Coastguard Worker size,
443*795d594fSAndroid Build Coastguard Worker length,
444*795d594fSAndroid Build Coastguard Worker tmp));
445*795d594fSAndroid Build Coastguard Worker }
446*795d594fSAndroid Build Coastguard Worker case JVMTI_HEAP_REFERENCE_CLASS_LOADER:
447*795d594fSAndroid Build Coastguard Worker return std::unique_ptr<Elem>(new StringElement(referrer,
448*795d594fSAndroid Build Coastguard Worker referree,
449*795d594fSAndroid Build Coastguard Worker size,
450*795d594fSAndroid Build Coastguard Worker length,
451*795d594fSAndroid Build Coastguard Worker "classloader"));
452*795d594fSAndroid Build Coastguard Worker case JVMTI_HEAP_REFERENCE_SIGNERS:
453*795d594fSAndroid Build Coastguard Worker return std::unique_ptr<Elem>(new StringElement(referrer,
454*795d594fSAndroid Build Coastguard Worker referree,
455*795d594fSAndroid Build Coastguard Worker size,
456*795d594fSAndroid Build Coastguard Worker length,
457*795d594fSAndroid Build Coastguard Worker "signers"));
458*795d594fSAndroid Build Coastguard Worker case JVMTI_HEAP_REFERENCE_PROTECTION_DOMAIN:
459*795d594fSAndroid Build Coastguard Worker return std::unique_ptr<Elem>(new StringElement(referrer,
460*795d594fSAndroid Build Coastguard Worker referree,
461*795d594fSAndroid Build Coastguard Worker size,
462*795d594fSAndroid Build Coastguard Worker length,
463*795d594fSAndroid Build Coastguard Worker "protection-domain"));
464*795d594fSAndroid Build Coastguard Worker case JVMTI_HEAP_REFERENCE_INTERFACE:
465*795d594fSAndroid Build Coastguard Worker return std::unique_ptr<Elem>(new StringElement(referrer,
466*795d594fSAndroid Build Coastguard Worker referree,
467*795d594fSAndroid Build Coastguard Worker size,
468*795d594fSAndroid Build Coastguard Worker length,
469*795d594fSAndroid Build Coastguard Worker "interface"));
470*795d594fSAndroid Build Coastguard Worker case JVMTI_HEAP_REFERENCE_STATIC_FIELD: {
471*795d594fSAndroid Build Coastguard Worker std::string tmp = StringPrintf("array-element@%d", reference_info->array.index);
472*795d594fSAndroid Build Coastguard Worker return std::unique_ptr<Elem>(new StringElement(referrer,
473*795d594fSAndroid Build Coastguard Worker referree,
474*795d594fSAndroid Build Coastguard Worker size,
475*795d594fSAndroid Build Coastguard Worker length,
476*795d594fSAndroid Build Coastguard Worker tmp));;
477*795d594fSAndroid Build Coastguard Worker }
478*795d594fSAndroid Build Coastguard Worker case JVMTI_HEAP_REFERENCE_CONSTANT_POOL:
479*795d594fSAndroid Build Coastguard Worker return std::unique_ptr<Elem>(new StringElement(referrer,
480*795d594fSAndroid Build Coastguard Worker referree,
481*795d594fSAndroid Build Coastguard Worker size,
482*795d594fSAndroid Build Coastguard Worker length,
483*795d594fSAndroid Build Coastguard Worker "constant-pool"));
484*795d594fSAndroid Build Coastguard Worker case JVMTI_HEAP_REFERENCE_SUPERCLASS:
485*795d594fSAndroid Build Coastguard Worker return std::unique_ptr<Elem>(new StringElement(referrer,
486*795d594fSAndroid Build Coastguard Worker referree,
487*795d594fSAndroid Build Coastguard Worker size,
488*795d594fSAndroid Build Coastguard Worker length,
489*795d594fSAndroid Build Coastguard Worker "superclass"));
490*795d594fSAndroid Build Coastguard Worker case JVMTI_HEAP_REFERENCE_JNI_GLOBAL:
491*795d594fSAndroid Build Coastguard Worker return std::unique_ptr<Elem>(new StringElement(referrer,
492*795d594fSAndroid Build Coastguard Worker referree,
493*795d594fSAndroid Build Coastguard Worker size,
494*795d594fSAndroid Build Coastguard Worker length,
495*795d594fSAndroid Build Coastguard Worker "jni-global"));
496*795d594fSAndroid Build Coastguard Worker case JVMTI_HEAP_REFERENCE_SYSTEM_CLASS:
497*795d594fSAndroid Build Coastguard Worker return std::unique_ptr<Elem>(new StringElement(referrer,
498*795d594fSAndroid Build Coastguard Worker referree,
499*795d594fSAndroid Build Coastguard Worker size,
500*795d594fSAndroid Build Coastguard Worker length,
501*795d594fSAndroid Build Coastguard Worker "system-class"));
502*795d594fSAndroid Build Coastguard Worker case JVMTI_HEAP_REFERENCE_MONITOR:
503*795d594fSAndroid Build Coastguard Worker return std::unique_ptr<Elem>(new StringElement(referrer,
504*795d594fSAndroid Build Coastguard Worker referree,
505*795d594fSAndroid Build Coastguard Worker size,
506*795d594fSAndroid Build Coastguard Worker length,
507*795d594fSAndroid Build Coastguard Worker "monitor"));
508*795d594fSAndroid Build Coastguard Worker case JVMTI_HEAP_REFERENCE_STACK_LOCAL:
509*795d594fSAndroid Build Coastguard Worker return std::unique_ptr<Elem>(new StackLocalElement(referrer,
510*795d594fSAndroid Build Coastguard Worker referree,
511*795d594fSAndroid Build Coastguard Worker size,
512*795d594fSAndroid Build Coastguard Worker length,
513*795d594fSAndroid Build Coastguard Worker reference_info));
514*795d594fSAndroid Build Coastguard Worker case JVMTI_HEAP_REFERENCE_JNI_LOCAL:
515*795d594fSAndroid Build Coastguard Worker return std::unique_ptr<Elem>(new JNILocalElement(referrer,
516*795d594fSAndroid Build Coastguard Worker referree,
517*795d594fSAndroid Build Coastguard Worker size,
518*795d594fSAndroid Build Coastguard Worker length,
519*795d594fSAndroid Build Coastguard Worker reference_info));
520*795d594fSAndroid Build Coastguard Worker case JVMTI_HEAP_REFERENCE_THREAD:
521*795d594fSAndroid Build Coastguard Worker return std::unique_ptr<Elem>(new StringElement(referrer,
522*795d594fSAndroid Build Coastguard Worker referree,
523*795d594fSAndroid Build Coastguard Worker size,
524*795d594fSAndroid Build Coastguard Worker length,
525*795d594fSAndroid Build Coastguard Worker "thread"));
526*795d594fSAndroid Build Coastguard Worker case JVMTI_HEAP_REFERENCE_OTHER:
527*795d594fSAndroid Build Coastguard Worker return std::unique_ptr<Elem>(new StringElement(referrer,
528*795d594fSAndroid Build Coastguard Worker referree,
529*795d594fSAndroid Build Coastguard Worker size,
530*795d594fSAndroid Build Coastguard Worker length,
531*795d594fSAndroid Build Coastguard Worker "other"));
532*795d594fSAndroid Build Coastguard Worker }
533*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unknown kind";
534*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
535*795d594fSAndroid Build Coastguard Worker }
536*795d594fSAndroid Build Coastguard Worker
537*795d594fSAndroid Build Coastguard Worker jint counter_;
538*795d594fSAndroid Build Coastguard Worker const jint stop_after_;
539*795d594fSAndroid Build Coastguard Worker const jint follow_set_;
540*795d594fSAndroid Build Coastguard Worker
541*795d594fSAndroid Build Coastguard Worker std::vector<std::unique_ptr<Elem>> lines_;
542*795d594fSAndroid Build Coastguard Worker };
543*795d594fSAndroid Build Coastguard Worker
544*795d594fSAndroid Build Coastguard Worker // If jniRef isn't null, add a local and a global ref.
545*795d594fSAndroid Build Coastguard Worker ScopedLocalRef<jobject> jni_local_ref(env, nullptr);
546*795d594fSAndroid Build Coastguard Worker jobject jni_global_ref = nullptr;
547*795d594fSAndroid Build Coastguard Worker if (jniRef != nullptr) {
548*795d594fSAndroid Build Coastguard Worker jni_local_ref.reset(env->NewLocalRef(jniRef));
549*795d594fSAndroid Build Coastguard Worker jni_global_ref = env->NewGlobalRef(jniRef);
550*795d594fSAndroid Build Coastguard Worker }
551*795d594fSAndroid Build Coastguard Worker
552*795d594fSAndroid Build Coastguard Worker PrintIterationConfig config(stop_after, follow_set);
553*795d594fSAndroid Build Coastguard Worker if (!Run(env, heap_filter, klass_filter, initial_object, &config)) {
554*795d594fSAndroid Build Coastguard Worker return nullptr;
555*795d594fSAndroid Build Coastguard Worker }
556*795d594fSAndroid Build Coastguard Worker
557*795d594fSAndroid Build Coastguard Worker std::vector<std::string> lines = config.GetLines();
558*795d594fSAndroid Build Coastguard Worker jobjectArray ret = CreateObjectArray(env,
559*795d594fSAndroid Build Coastguard Worker static_cast<jint>(lines.size()),
560*795d594fSAndroid Build Coastguard Worker "java/lang/String",
561*795d594fSAndroid Build Coastguard Worker [&](jint i) {
562*795d594fSAndroid Build Coastguard Worker return env->NewStringUTF(lines[i].c_str());
563*795d594fSAndroid Build Coastguard Worker });
564*795d594fSAndroid Build Coastguard Worker
565*795d594fSAndroid Build Coastguard Worker if (jni_global_ref != nullptr) {
566*795d594fSAndroid Build Coastguard Worker env->DeleteGlobalRef(jni_global_ref);
567*795d594fSAndroid Build Coastguard Worker }
568*795d594fSAndroid Build Coastguard Worker
569*795d594fSAndroid Build Coastguard Worker return ret;
570*795d594fSAndroid Build Coastguard Worker }
571*795d594fSAndroid Build Coastguard Worker
Java_art_Test913_followReferencesString(JNIEnv * env,jclass klass,jobject initial_object)572*795d594fSAndroid Build Coastguard Worker extern "C" JNIEXPORT jobjectArray JNICALL Java_art_Test913_followReferencesString(
573*795d594fSAndroid Build Coastguard Worker JNIEnv* env, [[maybe_unused]] jclass klass , jobject initial_object) {
574*795d594fSAndroid Build Coastguard Worker struct FindStringCallbacks {
575*795d594fSAndroid Build Coastguard Worker static jint JNICALL FollowReferencesCallback(
576*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] jvmtiHeapReferenceKind reference_kind,
577*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] const jvmtiHeapReferenceInfo* reference_info,
578*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] jlong class_tag,
579*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] jlong referrer_class_tag,
580*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] jlong size,
581*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] jlong* tag_ptr,
582*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] jlong* referrer_tag_ptr,
583*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] jint length,
584*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] void* user_data) {
585*795d594fSAndroid Build Coastguard Worker return JVMTI_VISIT_OBJECTS; // Continue visiting.
586*795d594fSAndroid Build Coastguard Worker }
587*795d594fSAndroid Build Coastguard Worker
588*795d594fSAndroid Build Coastguard Worker static jint JNICALL StringValueCallback(jlong class_tag,
589*795d594fSAndroid Build Coastguard Worker jlong size,
590*795d594fSAndroid Build Coastguard Worker jlong* tag_ptr,
591*795d594fSAndroid Build Coastguard Worker const jchar* value,
592*795d594fSAndroid Build Coastguard Worker jint value_length,
593*795d594fSAndroid Build Coastguard Worker void* user_data) {
594*795d594fSAndroid Build Coastguard Worker FindStringCallbacks* p = reinterpret_cast<FindStringCallbacks*>(user_data);
595*795d594fSAndroid Build Coastguard Worker if (*tag_ptr != 0) {
596*795d594fSAndroid Build Coastguard Worker size_t utf_byte_count = ti::CountModifiedUtf8BytesInUtf16(value, value_length);
597*795d594fSAndroid Build Coastguard Worker std::unique_ptr<char[]> mod_utf(new char[utf_byte_count + 1]);
598*795d594fSAndroid Build Coastguard Worker memset(mod_utf.get(), 0, utf_byte_count + 1);
599*795d594fSAndroid Build Coastguard Worker ti::ConvertUtf16ToModifiedUtf8(mod_utf.get(), utf_byte_count, value, value_length);
600*795d594fSAndroid Build Coastguard Worker p->data.push_back(android::base::StringPrintf("%" PRId64 "@%" PRId64 " (%" PRId64 ", '%s')",
601*795d594fSAndroid Build Coastguard Worker *tag_ptr,
602*795d594fSAndroid Build Coastguard Worker class_tag,
603*795d594fSAndroid Build Coastguard Worker size,
604*795d594fSAndroid Build Coastguard Worker mod_utf.get()));
605*795d594fSAndroid Build Coastguard Worker // Update the tag to test whether that works.
606*795d594fSAndroid Build Coastguard Worker *tag_ptr = *tag_ptr + 1;
607*795d594fSAndroid Build Coastguard Worker }
608*795d594fSAndroid Build Coastguard Worker return 0;
609*795d594fSAndroid Build Coastguard Worker }
610*795d594fSAndroid Build Coastguard Worker
611*795d594fSAndroid Build Coastguard Worker std::vector<std::string> data;
612*795d594fSAndroid Build Coastguard Worker };
613*795d594fSAndroid Build Coastguard Worker
614*795d594fSAndroid Build Coastguard Worker jvmtiHeapCallbacks callbacks;
615*795d594fSAndroid Build Coastguard Worker memset(&callbacks, 0, sizeof(jvmtiHeapCallbacks));
616*795d594fSAndroid Build Coastguard Worker callbacks.heap_reference_callback = FindStringCallbacks::FollowReferencesCallback;
617*795d594fSAndroid Build Coastguard Worker callbacks.string_primitive_value_callback = FindStringCallbacks::StringValueCallback;
618*795d594fSAndroid Build Coastguard Worker
619*795d594fSAndroid Build Coastguard Worker FindStringCallbacks fsc;
620*795d594fSAndroid Build Coastguard Worker jvmtiError ret = jvmti_env->FollowReferences(0, nullptr, initial_object, &callbacks, &fsc);
621*795d594fSAndroid Build Coastguard Worker if (JvmtiErrorToException(env, jvmti_env, ret)) {
622*795d594fSAndroid Build Coastguard Worker return nullptr;
623*795d594fSAndroid Build Coastguard Worker }
624*795d594fSAndroid Build Coastguard Worker
625*795d594fSAndroid Build Coastguard Worker jobjectArray retArray = CreateObjectArray(env,
626*795d594fSAndroid Build Coastguard Worker static_cast<jint>(fsc.data.size()),
627*795d594fSAndroid Build Coastguard Worker "java/lang/String",
628*795d594fSAndroid Build Coastguard Worker [&](jint i) {
629*795d594fSAndroid Build Coastguard Worker return env->NewStringUTF(fsc.data[i].c_str());
630*795d594fSAndroid Build Coastguard Worker });
631*795d594fSAndroid Build Coastguard Worker return retArray;
632*795d594fSAndroid Build Coastguard Worker }
633*795d594fSAndroid Build Coastguard Worker
634*795d594fSAndroid Build Coastguard Worker
Java_art_Test913_followReferencesPrimitiveArray(JNIEnv * env,jclass klass,jobject initial_object)635*795d594fSAndroid Build Coastguard Worker extern "C" JNIEXPORT jstring JNICALL Java_art_Test913_followReferencesPrimitiveArray(
636*795d594fSAndroid Build Coastguard Worker JNIEnv* env, [[maybe_unused]] jclass klass , jobject initial_object) {
637*795d594fSAndroid Build Coastguard Worker struct FindArrayCallbacks {
638*795d594fSAndroid Build Coastguard Worker static jint JNICALL FollowReferencesCallback(
639*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] jvmtiHeapReferenceKind reference_kind,
640*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] const jvmtiHeapReferenceInfo* reference_info,
641*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] jlong class_tag,
642*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] jlong referrer_class_tag,
643*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] jlong size,
644*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] jlong* tag_ptr,
645*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] jlong* referrer_tag_ptr,
646*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] jint length,
647*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] void* user_data) {
648*795d594fSAndroid Build Coastguard Worker return JVMTI_VISIT_OBJECTS; // Continue visiting.
649*795d594fSAndroid Build Coastguard Worker }
650*795d594fSAndroid Build Coastguard Worker
651*795d594fSAndroid Build Coastguard Worker static jint JNICALL ArrayValueCallback(jlong class_tag,
652*795d594fSAndroid Build Coastguard Worker jlong size,
653*795d594fSAndroid Build Coastguard Worker jlong* tag_ptr,
654*795d594fSAndroid Build Coastguard Worker jint element_count,
655*795d594fSAndroid Build Coastguard Worker jvmtiPrimitiveType element_type,
656*795d594fSAndroid Build Coastguard Worker const void* elements,
657*795d594fSAndroid Build Coastguard Worker void* user_data) {
658*795d594fSAndroid Build Coastguard Worker FindArrayCallbacks* p = reinterpret_cast<FindArrayCallbacks*>(user_data);
659*795d594fSAndroid Build Coastguard Worker // The thread object may be reachable from the starting value because of setup in the
660*795d594fSAndroid Build Coastguard Worker // framework (when this test runs as part of CTS). Ignore, we're not testing the thread
661*795d594fSAndroid Build Coastguard Worker // here.)
662*795d594fSAndroid Build Coastguard Worker if (*tag_ptr != 0 && *tag_ptr != kThreadTag) {
663*795d594fSAndroid Build Coastguard Worker std::ostringstream oss;
664*795d594fSAndroid Build Coastguard Worker oss << *tag_ptr
665*795d594fSAndroid Build Coastguard Worker << '@'
666*795d594fSAndroid Build Coastguard Worker << class_tag
667*795d594fSAndroid Build Coastguard Worker << " ("
668*795d594fSAndroid Build Coastguard Worker << size
669*795d594fSAndroid Build Coastguard Worker << ", "
670*795d594fSAndroid Build Coastguard Worker << element_count
671*795d594fSAndroid Build Coastguard Worker << "x"
672*795d594fSAndroid Build Coastguard Worker << static_cast<char>(element_type)
673*795d594fSAndroid Build Coastguard Worker << " '";
674*795d594fSAndroid Build Coastguard Worker size_t element_size;
675*795d594fSAndroid Build Coastguard Worker switch (element_type) {
676*795d594fSAndroid Build Coastguard Worker case JVMTI_PRIMITIVE_TYPE_BOOLEAN:
677*795d594fSAndroid Build Coastguard Worker case JVMTI_PRIMITIVE_TYPE_BYTE:
678*795d594fSAndroid Build Coastguard Worker element_size = 1;
679*795d594fSAndroid Build Coastguard Worker break;
680*795d594fSAndroid Build Coastguard Worker case JVMTI_PRIMITIVE_TYPE_CHAR:
681*795d594fSAndroid Build Coastguard Worker case JVMTI_PRIMITIVE_TYPE_SHORT:
682*795d594fSAndroid Build Coastguard Worker element_size = 2;
683*795d594fSAndroid Build Coastguard Worker break;
684*795d594fSAndroid Build Coastguard Worker case JVMTI_PRIMITIVE_TYPE_INT:
685*795d594fSAndroid Build Coastguard Worker case JVMTI_PRIMITIVE_TYPE_FLOAT:
686*795d594fSAndroid Build Coastguard Worker element_size = 4;
687*795d594fSAndroid Build Coastguard Worker break;
688*795d594fSAndroid Build Coastguard Worker case JVMTI_PRIMITIVE_TYPE_LONG:
689*795d594fSAndroid Build Coastguard Worker case JVMTI_PRIMITIVE_TYPE_DOUBLE:
690*795d594fSAndroid Build Coastguard Worker element_size = 8;
691*795d594fSAndroid Build Coastguard Worker break;
692*795d594fSAndroid Build Coastguard Worker }
693*795d594fSAndroid Build Coastguard Worker const uint8_t* data = reinterpret_cast<const uint8_t*>(elements);
694*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i != element_size * element_count; ++i) {
695*795d594fSAndroid Build Coastguard Worker oss << android::base::StringPrintf("%02x", data[i]);
696*795d594fSAndroid Build Coastguard Worker }
697*795d594fSAndroid Build Coastguard Worker oss << "')";
698*795d594fSAndroid Build Coastguard Worker
699*795d594fSAndroid Build Coastguard Worker if (!p->data.empty()) {
700*795d594fSAndroid Build Coastguard Worker p->data += "\n";
701*795d594fSAndroid Build Coastguard Worker }
702*795d594fSAndroid Build Coastguard Worker p->data += oss.str();
703*795d594fSAndroid Build Coastguard Worker // Update the tag to test whether that works.
704*795d594fSAndroid Build Coastguard Worker *tag_ptr = *tag_ptr + 1;
705*795d594fSAndroid Build Coastguard Worker }
706*795d594fSAndroid Build Coastguard Worker return 0;
707*795d594fSAndroid Build Coastguard Worker }
708*795d594fSAndroid Build Coastguard Worker
709*795d594fSAndroid Build Coastguard Worker std::string data;
710*795d594fSAndroid Build Coastguard Worker };
711*795d594fSAndroid Build Coastguard Worker
712*795d594fSAndroid Build Coastguard Worker jvmtiHeapCallbacks callbacks;
713*795d594fSAndroid Build Coastguard Worker memset(&callbacks, 0, sizeof(jvmtiHeapCallbacks));
714*795d594fSAndroid Build Coastguard Worker callbacks.heap_reference_callback = FindArrayCallbacks::FollowReferencesCallback;
715*795d594fSAndroid Build Coastguard Worker callbacks.array_primitive_value_callback = FindArrayCallbacks::ArrayValueCallback;
716*795d594fSAndroid Build Coastguard Worker
717*795d594fSAndroid Build Coastguard Worker FindArrayCallbacks fac;
718*795d594fSAndroid Build Coastguard Worker jvmtiError ret = jvmti_env->FollowReferences(0, nullptr, initial_object, &callbacks, &fac);
719*795d594fSAndroid Build Coastguard Worker if (JvmtiErrorToException(env, jvmti_env, ret)) {
720*795d594fSAndroid Build Coastguard Worker return nullptr;
721*795d594fSAndroid Build Coastguard Worker }
722*795d594fSAndroid Build Coastguard Worker return env->NewStringUTF(fac.data.c_str());
723*795d594fSAndroid Build Coastguard Worker }
724*795d594fSAndroid Build Coastguard Worker
GetPrimitiveTypeName(jvmtiPrimitiveType type)725*795d594fSAndroid Build Coastguard Worker static constexpr const char* GetPrimitiveTypeName(jvmtiPrimitiveType type) {
726*795d594fSAndroid Build Coastguard Worker switch (type) {
727*795d594fSAndroid Build Coastguard Worker case JVMTI_PRIMITIVE_TYPE_BOOLEAN:
728*795d594fSAndroid Build Coastguard Worker return "boolean";
729*795d594fSAndroid Build Coastguard Worker case JVMTI_PRIMITIVE_TYPE_BYTE:
730*795d594fSAndroid Build Coastguard Worker return "byte";
731*795d594fSAndroid Build Coastguard Worker case JVMTI_PRIMITIVE_TYPE_CHAR:
732*795d594fSAndroid Build Coastguard Worker return "char";
733*795d594fSAndroid Build Coastguard Worker case JVMTI_PRIMITIVE_TYPE_SHORT:
734*795d594fSAndroid Build Coastguard Worker return "short";
735*795d594fSAndroid Build Coastguard Worker case JVMTI_PRIMITIVE_TYPE_INT:
736*795d594fSAndroid Build Coastguard Worker return "int";
737*795d594fSAndroid Build Coastguard Worker case JVMTI_PRIMITIVE_TYPE_FLOAT:
738*795d594fSAndroid Build Coastguard Worker return "float";
739*795d594fSAndroid Build Coastguard Worker case JVMTI_PRIMITIVE_TYPE_LONG:
740*795d594fSAndroid Build Coastguard Worker return "long";
741*795d594fSAndroid Build Coastguard Worker case JVMTI_PRIMITIVE_TYPE_DOUBLE:
742*795d594fSAndroid Build Coastguard Worker return "double";
743*795d594fSAndroid Build Coastguard Worker }
744*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unknown type " << static_cast<size_t>(type);
745*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
746*795d594fSAndroid Build Coastguard Worker }
747*795d594fSAndroid Build Coastguard Worker
Java_art_Test913_followReferencesPrimitiveFields(JNIEnv * env,jclass klass,jobject initial_object)748*795d594fSAndroid Build Coastguard Worker extern "C" JNIEXPORT jstring JNICALL Java_art_Test913_followReferencesPrimitiveFields(
749*795d594fSAndroid Build Coastguard Worker JNIEnv* env, [[maybe_unused]] jclass klass , jobject initial_object) {
750*795d594fSAndroid Build Coastguard Worker struct FindFieldCallbacks {
751*795d594fSAndroid Build Coastguard Worker static jint JNICALL FollowReferencesCallback(
752*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] jvmtiHeapReferenceKind reference_kind,
753*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] const jvmtiHeapReferenceInfo* reference_info,
754*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] jlong class_tag,
755*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] jlong referrer_class_tag,
756*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] jlong size,
757*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] jlong* tag_ptr,
758*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] jlong* referrer_tag_ptr,
759*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] jint length,
760*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] void* user_data) {
761*795d594fSAndroid Build Coastguard Worker return JVMTI_VISIT_OBJECTS; // Continue visiting.
762*795d594fSAndroid Build Coastguard Worker }
763*795d594fSAndroid Build Coastguard Worker
764*795d594fSAndroid Build Coastguard Worker static jint JNICALL PrimitiveFieldValueCallback(jvmtiHeapReferenceKind kind,
765*795d594fSAndroid Build Coastguard Worker const jvmtiHeapReferenceInfo* info,
766*795d594fSAndroid Build Coastguard Worker jlong class_tag,
767*795d594fSAndroid Build Coastguard Worker jlong* tag_ptr,
768*795d594fSAndroid Build Coastguard Worker jvalue value,
769*795d594fSAndroid Build Coastguard Worker jvmtiPrimitiveType value_type,
770*795d594fSAndroid Build Coastguard Worker void* user_data) {
771*795d594fSAndroid Build Coastguard Worker FindFieldCallbacks* p = reinterpret_cast<FindFieldCallbacks*>(user_data);
772*795d594fSAndroid Build Coastguard Worker // The thread object may be reachable from the starting value because of setup in the
773*795d594fSAndroid Build Coastguard Worker // framework (when this test runs as part of CTS). Ignore, we're not testing the thread
774*795d594fSAndroid Build Coastguard Worker // here.)
775*795d594fSAndroid Build Coastguard Worker if (*tag_ptr != 0 && *tag_ptr != kThreadTag) {
776*795d594fSAndroid Build Coastguard Worker std::ostringstream oss;
777*795d594fSAndroid Build Coastguard Worker oss << *tag_ptr
778*795d594fSAndroid Build Coastguard Worker << '@'
779*795d594fSAndroid Build Coastguard Worker << class_tag
780*795d594fSAndroid Build Coastguard Worker << " ("
781*795d594fSAndroid Build Coastguard Worker << (kind == JVMTI_HEAP_REFERENCE_FIELD ? "instance, " : "static, ")
782*795d594fSAndroid Build Coastguard Worker << GetPrimitiveTypeName(value_type)
783*795d594fSAndroid Build Coastguard Worker << ", index="
784*795d594fSAndroid Build Coastguard Worker << info->field.index
785*795d594fSAndroid Build Coastguard Worker << ") ";
786*795d594fSAndroid Build Coastguard Worker // Be lazy, always print eight bytes.
787*795d594fSAndroid Build Coastguard Worker static_assert(sizeof(jvalue) == sizeof(uint64_t), "Unexpected jvalue size");
788*795d594fSAndroid Build Coastguard Worker uint64_t val;
789*795d594fSAndroid Build Coastguard Worker memcpy(&val, &value, sizeof(uint64_t)); // To avoid undefined behavior.
790*795d594fSAndroid Build Coastguard Worker oss << android::base::StringPrintf("%016" PRIx64, val);
791*795d594fSAndroid Build Coastguard Worker
792*795d594fSAndroid Build Coastguard Worker if (!p->data.empty()) {
793*795d594fSAndroid Build Coastguard Worker p->data += "\n";
794*795d594fSAndroid Build Coastguard Worker }
795*795d594fSAndroid Build Coastguard Worker p->data += oss.str();
796*795d594fSAndroid Build Coastguard Worker // Update the tag to test whether that works.
797*795d594fSAndroid Build Coastguard Worker *tag_ptr = *tag_ptr + 1;
798*795d594fSAndroid Build Coastguard Worker }
799*795d594fSAndroid Build Coastguard Worker return 0;
800*795d594fSAndroid Build Coastguard Worker }
801*795d594fSAndroid Build Coastguard Worker
802*795d594fSAndroid Build Coastguard Worker std::string data;
803*795d594fSAndroid Build Coastguard Worker };
804*795d594fSAndroid Build Coastguard Worker
805*795d594fSAndroid Build Coastguard Worker jvmtiHeapCallbacks callbacks;
806*795d594fSAndroid Build Coastguard Worker memset(&callbacks, 0, sizeof(jvmtiHeapCallbacks));
807*795d594fSAndroid Build Coastguard Worker callbacks.heap_reference_callback = FindFieldCallbacks::FollowReferencesCallback;
808*795d594fSAndroid Build Coastguard Worker callbacks.primitive_field_callback = FindFieldCallbacks::PrimitiveFieldValueCallback;
809*795d594fSAndroid Build Coastguard Worker
810*795d594fSAndroid Build Coastguard Worker FindFieldCallbacks ffc;
811*795d594fSAndroid Build Coastguard Worker jvmtiError ret = jvmti_env->FollowReferences(0, nullptr, initial_object, &callbacks, &ffc);
812*795d594fSAndroid Build Coastguard Worker if (JvmtiErrorToException(env, jvmti_env, ret)) {
813*795d594fSAndroid Build Coastguard Worker return nullptr;
814*795d594fSAndroid Build Coastguard Worker }
815*795d594fSAndroid Build Coastguard Worker return env->NewStringUTF(ffc.data.c_str());
816*795d594fSAndroid Build Coastguard Worker }
817*795d594fSAndroid Build Coastguard Worker
818*795d594fSAndroid Build Coastguard Worker // This is copied from test 908. Consider moving this to the main shim.
819*795d594fSAndroid Build Coastguard Worker
820*795d594fSAndroid Build Coastguard Worker static size_t starts = 0;
821*795d594fSAndroid Build Coastguard Worker static size_t finishes = 0;
822*795d594fSAndroid Build Coastguard Worker
GarbageCollectionFinish(jvmtiEnv * ti_env)823*795d594fSAndroid Build Coastguard Worker static void JNICALL GarbageCollectionFinish([[maybe_unused]] jvmtiEnv* ti_env) {
824*795d594fSAndroid Build Coastguard Worker finishes++;
825*795d594fSAndroid Build Coastguard Worker }
826*795d594fSAndroid Build Coastguard Worker
GarbageCollectionStart(jvmtiEnv * ti_env)827*795d594fSAndroid Build Coastguard Worker static void JNICALL GarbageCollectionStart([[maybe_unused]] jvmtiEnv* ti_env) {
828*795d594fSAndroid Build Coastguard Worker starts++;
829*795d594fSAndroid Build Coastguard Worker }
830*795d594fSAndroid Build Coastguard Worker
Java_art_Test913_setupGcCallback(JNIEnv * env,jclass klass)831*795d594fSAndroid Build Coastguard Worker extern "C" JNIEXPORT void JNICALL Java_art_Test913_setupGcCallback(
832*795d594fSAndroid Build Coastguard Worker JNIEnv* env, [[maybe_unused]] jclass klass) {
833*795d594fSAndroid Build Coastguard Worker jvmtiEventCallbacks callbacks;
834*795d594fSAndroid Build Coastguard Worker memset(&callbacks, 0, sizeof(jvmtiEventCallbacks));
835*795d594fSAndroid Build Coastguard Worker callbacks.GarbageCollectionFinish = GarbageCollectionFinish;
836*795d594fSAndroid Build Coastguard Worker callbacks.GarbageCollectionStart = GarbageCollectionStart;
837*795d594fSAndroid Build Coastguard Worker
838*795d594fSAndroid Build Coastguard Worker jvmtiError ret = jvmti_env->SetEventCallbacks(&callbacks, sizeof(callbacks));
839*795d594fSAndroid Build Coastguard Worker JvmtiErrorToException(env, jvmti_env, ret);
840*795d594fSAndroid Build Coastguard Worker }
841*795d594fSAndroid Build Coastguard Worker
Java_art_Test913_enableGcTracking(JNIEnv * env,jclass klass,jboolean enable)842*795d594fSAndroid Build Coastguard Worker extern "C" JNIEXPORT void JNICALL Java_art_Test913_enableGcTracking(JNIEnv* env,
843*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] jclass klass,
844*795d594fSAndroid Build Coastguard Worker jboolean enable) {
845*795d594fSAndroid Build Coastguard Worker jvmtiError ret = jvmti_env->SetEventNotificationMode(
846*795d594fSAndroid Build Coastguard Worker enable ? JVMTI_ENABLE : JVMTI_DISABLE,
847*795d594fSAndroid Build Coastguard Worker JVMTI_EVENT_GARBAGE_COLLECTION_START,
848*795d594fSAndroid Build Coastguard Worker nullptr);
849*795d594fSAndroid Build Coastguard Worker if (JvmtiErrorToException(env, jvmti_env, ret)) {
850*795d594fSAndroid Build Coastguard Worker return;
851*795d594fSAndroid Build Coastguard Worker }
852*795d594fSAndroid Build Coastguard Worker ret = jvmti_env->SetEventNotificationMode(
853*795d594fSAndroid Build Coastguard Worker enable ? JVMTI_ENABLE : JVMTI_DISABLE,
854*795d594fSAndroid Build Coastguard Worker JVMTI_EVENT_GARBAGE_COLLECTION_FINISH,
855*795d594fSAndroid Build Coastguard Worker nullptr);
856*795d594fSAndroid Build Coastguard Worker if (JvmtiErrorToException(env, jvmti_env, ret)) {
857*795d594fSAndroid Build Coastguard Worker return;
858*795d594fSAndroid Build Coastguard Worker }
859*795d594fSAndroid Build Coastguard Worker }
860*795d594fSAndroid Build Coastguard Worker
Java_art_Test913_getGcStarts(JNIEnv * env,jclass klass)861*795d594fSAndroid Build Coastguard Worker extern "C" JNIEXPORT jint JNICALL Java_art_Test913_getGcStarts([[maybe_unused]] JNIEnv* env,
862*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] jclass klass) {
863*795d594fSAndroid Build Coastguard Worker jint result = static_cast<jint>(starts);
864*795d594fSAndroid Build Coastguard Worker starts = 0;
865*795d594fSAndroid Build Coastguard Worker return result;
866*795d594fSAndroid Build Coastguard Worker }
867*795d594fSAndroid Build Coastguard Worker
Java_art_Test913_getGcFinishes(JNIEnv * env,jclass klass)868*795d594fSAndroid Build Coastguard Worker extern "C" JNIEXPORT jint JNICALL Java_art_Test913_getGcFinishes([[maybe_unused]] JNIEnv* env,
869*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] jclass klass) {
870*795d594fSAndroid Build Coastguard Worker jint result = static_cast<jint>(finishes);
871*795d594fSAndroid Build Coastguard Worker finishes = 0;
872*795d594fSAndroid Build Coastguard Worker return result;
873*795d594fSAndroid Build Coastguard Worker }
874*795d594fSAndroid Build Coastguard Worker
875*795d594fSAndroid Build Coastguard Worker using GetObjectHeapId = jvmtiError(*)(jvmtiEnv*, jlong, jint*, ...);
876*795d594fSAndroid Build Coastguard Worker static GetObjectHeapId gGetObjectHeapIdFn = nullptr;
877*795d594fSAndroid Build Coastguard Worker
878*795d594fSAndroid Build Coastguard Worker using GetHeapName = jvmtiError(*)(jvmtiEnv*, jint, char**, ...);
879*795d594fSAndroid Build Coastguard Worker static GetHeapName gGetHeapNameFn = nullptr;
880*795d594fSAndroid Build Coastguard Worker
881*795d594fSAndroid Build Coastguard Worker using IterateThroughHeapExt = jvmtiError(*)(jvmtiEnv*,
882*795d594fSAndroid Build Coastguard Worker jint,
883*795d594fSAndroid Build Coastguard Worker jclass,
884*795d594fSAndroid Build Coastguard Worker const jvmtiHeapCallbacks*,
885*795d594fSAndroid Build Coastguard Worker const void*);
886*795d594fSAndroid Build Coastguard Worker static IterateThroughHeapExt gIterateThroughHeapExt = nullptr;
887*795d594fSAndroid Build Coastguard Worker
888*795d594fSAndroid Build Coastguard Worker
FreeExtensionFunctionInfo(jvmtiExtensionFunctionInfo * extensions,jint count)889*795d594fSAndroid Build Coastguard Worker static void FreeExtensionFunctionInfo(jvmtiExtensionFunctionInfo* extensions, jint count) {
890*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i != static_cast<size_t>(count); ++i) {
891*795d594fSAndroid Build Coastguard Worker jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(extensions[i].id));
892*795d594fSAndroid Build Coastguard Worker jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(extensions[i].short_description));
893*795d594fSAndroid Build Coastguard Worker for (size_t j = 0; j != static_cast<size_t>(extensions[i].param_count); ++j) {
894*795d594fSAndroid Build Coastguard Worker jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(extensions[i].params[j].name));
895*795d594fSAndroid Build Coastguard Worker }
896*795d594fSAndroid Build Coastguard Worker jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(extensions[i].params));
897*795d594fSAndroid Build Coastguard Worker jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(extensions[i].errors));
898*795d594fSAndroid Build Coastguard Worker }
899*795d594fSAndroid Build Coastguard Worker }
900*795d594fSAndroid Build Coastguard Worker
Java_art_Test913_checkForExtensionApis(JNIEnv * env,jclass klass)901*795d594fSAndroid Build Coastguard Worker extern "C" JNIEXPORT void JNICALL Java_art_Test913_checkForExtensionApis(
902*795d594fSAndroid Build Coastguard Worker JNIEnv* env, [[maybe_unused]] jclass klass) {
903*795d594fSAndroid Build Coastguard Worker jint extension_count;
904*795d594fSAndroid Build Coastguard Worker jvmtiExtensionFunctionInfo* extensions;
905*795d594fSAndroid Build Coastguard Worker jvmtiError result = jvmti_env->GetExtensionFunctions(&extension_count, &extensions);
906*795d594fSAndroid Build Coastguard Worker if (JvmtiErrorToException(env, jvmti_env, result)) {
907*795d594fSAndroid Build Coastguard Worker return;
908*795d594fSAndroid Build Coastguard Worker }
909*795d594fSAndroid Build Coastguard Worker
910*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i != static_cast<size_t>(extension_count); ++i) {
911*795d594fSAndroid Build Coastguard Worker if (strcmp("com.android.art.heap.get_object_heap_id", extensions[i].id) == 0) {
912*795d594fSAndroid Build Coastguard Worker CHECK(gGetObjectHeapIdFn == nullptr);
913*795d594fSAndroid Build Coastguard Worker gGetObjectHeapIdFn = reinterpret_cast<GetObjectHeapId>(extensions[i].func);
914*795d594fSAndroid Build Coastguard Worker
915*795d594fSAndroid Build Coastguard Worker CHECK_EQ(extensions[i].param_count, 2);
916*795d594fSAndroid Build Coastguard Worker
917*795d594fSAndroid Build Coastguard Worker CHECK_EQ(strcmp("tag", extensions[i].params[0].name), 0);
918*795d594fSAndroid Build Coastguard Worker CHECK_EQ(extensions[i].params[0].base_type, JVMTI_TYPE_JLONG);
919*795d594fSAndroid Build Coastguard Worker CHECK_EQ(extensions[i].params[0].kind, JVMTI_KIND_IN);
920*795d594fSAndroid Build Coastguard Worker
921*795d594fSAndroid Build Coastguard Worker CHECK_EQ(strcmp("heap_id", extensions[i].params[1].name), 0);
922*795d594fSAndroid Build Coastguard Worker CHECK_EQ(extensions[i].params[1].base_type, JVMTI_TYPE_JINT);
923*795d594fSAndroid Build Coastguard Worker CHECK_EQ(extensions[i].params[1].kind, JVMTI_KIND_OUT);
924*795d594fSAndroid Build Coastguard Worker CHECK_EQ(extensions[i].params[1].null_ok, false);
925*795d594fSAndroid Build Coastguard Worker
926*795d594fSAndroid Build Coastguard Worker CHECK_EQ(extensions[i].error_count, 1);
927*795d594fSAndroid Build Coastguard Worker CHECK(extensions[i].errors != nullptr);
928*795d594fSAndroid Build Coastguard Worker CHECK(extensions[i].errors[0] == JVMTI_ERROR_NOT_FOUND);
929*795d594fSAndroid Build Coastguard Worker
930*795d594fSAndroid Build Coastguard Worker continue;
931*795d594fSAndroid Build Coastguard Worker }
932*795d594fSAndroid Build Coastguard Worker
933*795d594fSAndroid Build Coastguard Worker if (strcmp("com.android.art.heap.get_heap_name", extensions[i].id) == 0) {
934*795d594fSAndroid Build Coastguard Worker CHECK(gGetHeapNameFn == nullptr);
935*795d594fSAndroid Build Coastguard Worker gGetHeapNameFn = reinterpret_cast<GetHeapName>(extensions[i].func);
936*795d594fSAndroid Build Coastguard Worker
937*795d594fSAndroid Build Coastguard Worker CHECK_EQ(extensions[i].param_count, 2);
938*795d594fSAndroid Build Coastguard Worker
939*795d594fSAndroid Build Coastguard Worker CHECK_EQ(strcmp("heap_id", extensions[i].params[0].name), 0);
940*795d594fSAndroid Build Coastguard Worker CHECK_EQ(extensions[i].params[0].base_type, JVMTI_TYPE_JINT);
941*795d594fSAndroid Build Coastguard Worker CHECK_EQ(extensions[i].params[0].kind, JVMTI_KIND_IN);
942*795d594fSAndroid Build Coastguard Worker
943*795d594fSAndroid Build Coastguard Worker CHECK_EQ(strcmp("heap_name", extensions[i].params[1].name), 0);
944*795d594fSAndroid Build Coastguard Worker CHECK_EQ(extensions[i].params[1].base_type, JVMTI_TYPE_CCHAR);
945*795d594fSAndroid Build Coastguard Worker CHECK_EQ(extensions[i].params[1].kind, JVMTI_KIND_ALLOC_BUF);
946*795d594fSAndroid Build Coastguard Worker CHECK_EQ(extensions[i].params[1].null_ok, false);
947*795d594fSAndroid Build Coastguard Worker
948*795d594fSAndroid Build Coastguard Worker CHECK_EQ(extensions[i].error_count, 1);
949*795d594fSAndroid Build Coastguard Worker CHECK(extensions[i].errors != nullptr);
950*795d594fSAndroid Build Coastguard Worker CHECK(extensions[i].errors[0] == JVMTI_ERROR_ILLEGAL_ARGUMENT);
951*795d594fSAndroid Build Coastguard Worker }
952*795d594fSAndroid Build Coastguard Worker
953*795d594fSAndroid Build Coastguard Worker if (strcmp("com.android.art.heap.iterate_through_heap_ext", extensions[i].id) == 0) {
954*795d594fSAndroid Build Coastguard Worker CHECK(gIterateThroughHeapExt == nullptr);
955*795d594fSAndroid Build Coastguard Worker gIterateThroughHeapExt = reinterpret_cast<IterateThroughHeapExt>(extensions[i].func);
956*795d594fSAndroid Build Coastguard Worker
957*795d594fSAndroid Build Coastguard Worker CHECK_EQ(extensions[i].param_count, 4);
958*795d594fSAndroid Build Coastguard Worker
959*795d594fSAndroid Build Coastguard Worker CHECK_EQ(strcmp("heap_filter", extensions[i].params[0].name), 0);
960*795d594fSAndroid Build Coastguard Worker CHECK_EQ(extensions[i].params[0].base_type, JVMTI_TYPE_JINT);
961*795d594fSAndroid Build Coastguard Worker CHECK_EQ(extensions[i].params[0].kind, JVMTI_KIND_IN);
962*795d594fSAndroid Build Coastguard Worker
963*795d594fSAndroid Build Coastguard Worker CHECK_EQ(strcmp("klass", extensions[i].params[1].name), 0);
964*795d594fSAndroid Build Coastguard Worker CHECK_EQ(extensions[i].params[1].base_type, JVMTI_TYPE_JCLASS);
965*795d594fSAndroid Build Coastguard Worker CHECK_EQ(extensions[i].params[1].kind, JVMTI_KIND_IN);
966*795d594fSAndroid Build Coastguard Worker CHECK_EQ(extensions[i].params[1].null_ok, true);
967*795d594fSAndroid Build Coastguard Worker
968*795d594fSAndroid Build Coastguard Worker CHECK_EQ(strcmp("callbacks", extensions[i].params[2].name), 0);
969*795d594fSAndroid Build Coastguard Worker CHECK_EQ(extensions[i].params[2].base_type, JVMTI_TYPE_CVOID);
970*795d594fSAndroid Build Coastguard Worker CHECK_EQ(extensions[i].params[2].kind, JVMTI_KIND_IN_PTR);
971*795d594fSAndroid Build Coastguard Worker CHECK_EQ(extensions[i].params[2].null_ok, false);
972*795d594fSAndroid Build Coastguard Worker
973*795d594fSAndroid Build Coastguard Worker CHECK_EQ(strcmp("user_data", extensions[i].params[3].name), 0);
974*795d594fSAndroid Build Coastguard Worker CHECK_EQ(extensions[i].params[3].base_type, JVMTI_TYPE_CVOID);
975*795d594fSAndroid Build Coastguard Worker CHECK_EQ(extensions[i].params[3].kind, JVMTI_KIND_IN_PTR);
976*795d594fSAndroid Build Coastguard Worker CHECK_EQ(extensions[i].params[3].null_ok, true);
977*795d594fSAndroid Build Coastguard Worker
978*795d594fSAndroid Build Coastguard Worker CHECK_EQ(extensions[i].error_count, 3);
979*795d594fSAndroid Build Coastguard Worker CHECK(extensions[i].errors != nullptr);
980*795d594fSAndroid Build Coastguard Worker CHECK(extensions[i].errors[0] == JVMTI_ERROR_MUST_POSSESS_CAPABILITY);
981*795d594fSAndroid Build Coastguard Worker CHECK(extensions[i].errors[1] == JVMTI_ERROR_INVALID_CLASS);
982*795d594fSAndroid Build Coastguard Worker CHECK(extensions[i].errors[2] == JVMTI_ERROR_NULL_POINTER);
983*795d594fSAndroid Build Coastguard Worker }
984*795d594fSAndroid Build Coastguard Worker }
985*795d594fSAndroid Build Coastguard Worker
986*795d594fSAndroid Build Coastguard Worker CHECK(gGetObjectHeapIdFn != nullptr);
987*795d594fSAndroid Build Coastguard Worker CHECK(gGetHeapNameFn != nullptr);
988*795d594fSAndroid Build Coastguard Worker
989*795d594fSAndroid Build Coastguard Worker FreeExtensionFunctionInfo(extensions, extension_count);
990*795d594fSAndroid Build Coastguard Worker }
991*795d594fSAndroid Build Coastguard Worker
Java_art_Test913_getObjectHeapId(JNIEnv * env,jclass klass,jlong tag)992*795d594fSAndroid Build Coastguard Worker extern "C" JNIEXPORT jint JNICALL Java_art_Test913_getObjectHeapId(
993*795d594fSAndroid Build Coastguard Worker JNIEnv* env, [[maybe_unused]] jclass klass , jlong tag) {
994*795d594fSAndroid Build Coastguard Worker CHECK(gGetObjectHeapIdFn != nullptr);
995*795d594fSAndroid Build Coastguard Worker jint heap_id;
996*795d594fSAndroid Build Coastguard Worker jvmtiError result = gGetObjectHeapIdFn(jvmti_env, tag, &heap_id);
997*795d594fSAndroid Build Coastguard Worker JvmtiErrorToException(env, jvmti_env, result);
998*795d594fSAndroid Build Coastguard Worker return heap_id;
999*795d594fSAndroid Build Coastguard Worker }
1000*795d594fSAndroid Build Coastguard Worker
Java_art_Test913_getHeapName(JNIEnv * env,jclass klass,jint heap_id)1001*795d594fSAndroid Build Coastguard Worker extern "C" JNIEXPORT jstring JNICALL Java_art_Test913_getHeapName(
1002*795d594fSAndroid Build Coastguard Worker JNIEnv* env, [[maybe_unused]] jclass klass , jint heap_id) {
1003*795d594fSAndroid Build Coastguard Worker CHECK(gGetHeapNameFn != nullptr);
1004*795d594fSAndroid Build Coastguard Worker char* heap_name;
1005*795d594fSAndroid Build Coastguard Worker jvmtiError result = gGetHeapNameFn(jvmti_env, heap_id, &heap_name);
1006*795d594fSAndroid Build Coastguard Worker if (JvmtiErrorToException(env, jvmti_env, result)) {
1007*795d594fSAndroid Build Coastguard Worker return nullptr;
1008*795d594fSAndroid Build Coastguard Worker }
1009*795d594fSAndroid Build Coastguard Worker jstring ret = env->NewStringUTF(heap_name);
1010*795d594fSAndroid Build Coastguard Worker jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(heap_name));
1011*795d594fSAndroid Build Coastguard Worker return ret;
1012*795d594fSAndroid Build Coastguard Worker }
1013*795d594fSAndroid Build Coastguard Worker
Java_art_Test913_checkGetObjectHeapIdInCallback(JNIEnv * env,jclass klass,jlong tag,jint heap_id)1014*795d594fSAndroid Build Coastguard Worker extern "C" JNIEXPORT void JNICALL Java_art_Test913_checkGetObjectHeapIdInCallback(
1015*795d594fSAndroid Build Coastguard Worker JNIEnv* env, [[maybe_unused]] jclass klass , jlong tag, jint heap_id) {
1016*795d594fSAndroid Build Coastguard Worker CHECK(gGetObjectHeapIdFn != nullptr);
1017*795d594fSAndroid Build Coastguard Worker
1018*795d594fSAndroid Build Coastguard Worker {
1019*795d594fSAndroid Build Coastguard Worker struct GetObjectHeapIdCallbacks {
1020*795d594fSAndroid Build Coastguard Worker static jint JNICALL FollowReferencesCallback(
1021*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] jvmtiHeapReferenceKind reference_kind,
1022*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] const jvmtiHeapReferenceInfo* reference_info,
1023*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] jlong class_tag,
1024*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] jlong referrer_class_tag,
1025*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] jlong size,
1026*795d594fSAndroid Build Coastguard Worker jlong* tag_ptr,
1027*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] jlong* referrer_tag_ptr,
1028*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] jint length,
1029*795d594fSAndroid Build Coastguard Worker void* user_data) {
1030*795d594fSAndroid Build Coastguard Worker if (*tag_ptr != 0) {
1031*795d594fSAndroid Build Coastguard Worker GetObjectHeapIdCallbacks* p = reinterpret_cast<GetObjectHeapIdCallbacks*>(user_data);
1032*795d594fSAndroid Build Coastguard Worker if (*tag_ptr == p->check_callback_tag) {
1033*795d594fSAndroid Build Coastguard Worker jint tag_heap_id;
1034*795d594fSAndroid Build Coastguard Worker jvmtiError result = gGetObjectHeapIdFn(jvmti_env, *tag_ptr, &tag_heap_id);
1035*795d594fSAndroid Build Coastguard Worker CHECK_EQ(result, JVMTI_ERROR_NONE);
1036*795d594fSAndroid Build Coastguard Worker CHECK_EQ(tag_heap_id, p->check_callback_id);
1037*795d594fSAndroid Build Coastguard Worker return JVMTI_VISIT_ABORT;
1038*795d594fSAndroid Build Coastguard Worker }
1039*795d594fSAndroid Build Coastguard Worker }
1040*795d594fSAndroid Build Coastguard Worker
1041*795d594fSAndroid Build Coastguard Worker return JVMTI_VISIT_OBJECTS; // Continue visiting.
1042*795d594fSAndroid Build Coastguard Worker }
1043*795d594fSAndroid Build Coastguard Worker
1044*795d594fSAndroid Build Coastguard Worker jlong check_callback_tag;
1045*795d594fSAndroid Build Coastguard Worker jint check_callback_id;
1046*795d594fSAndroid Build Coastguard Worker };
1047*795d594fSAndroid Build Coastguard Worker
1048*795d594fSAndroid Build Coastguard Worker jvmtiHeapCallbacks callbacks;
1049*795d594fSAndroid Build Coastguard Worker memset(&callbacks, 0, sizeof(jvmtiHeapCallbacks));
1050*795d594fSAndroid Build Coastguard Worker callbacks.heap_reference_callback = GetObjectHeapIdCallbacks::FollowReferencesCallback;
1051*795d594fSAndroid Build Coastguard Worker
1052*795d594fSAndroid Build Coastguard Worker GetObjectHeapIdCallbacks ffc;
1053*795d594fSAndroid Build Coastguard Worker ffc.check_callback_tag = tag;
1054*795d594fSAndroid Build Coastguard Worker ffc.check_callback_id = heap_id;
1055*795d594fSAndroid Build Coastguard Worker
1056*795d594fSAndroid Build Coastguard Worker jvmtiError ret = jvmti_env->FollowReferences(0, nullptr, nullptr, &callbacks, &ffc);
1057*795d594fSAndroid Build Coastguard Worker if (JvmtiErrorToException(env, jvmti_env, ret)) {
1058*795d594fSAndroid Build Coastguard Worker return;
1059*795d594fSAndroid Build Coastguard Worker }
1060*795d594fSAndroid Build Coastguard Worker }
1061*795d594fSAndroid Build Coastguard Worker
1062*795d594fSAndroid Build Coastguard Worker {
1063*795d594fSAndroid Build Coastguard Worker struct GetObjectHeapIdCallbacks {
1064*795d594fSAndroid Build Coastguard Worker static jint JNICALL HeapIterationCallback([[maybe_unused]] jlong class_tag,
1065*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] jlong size,
1066*795d594fSAndroid Build Coastguard Worker jlong* tag_ptr,
1067*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] jint length,
1068*795d594fSAndroid Build Coastguard Worker void* user_data) {
1069*795d594fSAndroid Build Coastguard Worker if (*tag_ptr != 0) {
1070*795d594fSAndroid Build Coastguard Worker GetObjectHeapIdCallbacks* p = reinterpret_cast<GetObjectHeapIdCallbacks*>(user_data);
1071*795d594fSAndroid Build Coastguard Worker if (*tag_ptr == p->check_callback_tag) {
1072*795d594fSAndroid Build Coastguard Worker jint tag_heap_id;
1073*795d594fSAndroid Build Coastguard Worker jvmtiError result = gGetObjectHeapIdFn(jvmti_env, *tag_ptr, &tag_heap_id);
1074*795d594fSAndroid Build Coastguard Worker CHECK_EQ(result, JVMTI_ERROR_NONE);
1075*795d594fSAndroid Build Coastguard Worker CHECK_EQ(tag_heap_id, p->check_callback_id);
1076*795d594fSAndroid Build Coastguard Worker return JVMTI_VISIT_ABORT;
1077*795d594fSAndroid Build Coastguard Worker }
1078*795d594fSAndroid Build Coastguard Worker }
1079*795d594fSAndroid Build Coastguard Worker
1080*795d594fSAndroid Build Coastguard Worker return 0; // Continue visiting.
1081*795d594fSAndroid Build Coastguard Worker }
1082*795d594fSAndroid Build Coastguard Worker
1083*795d594fSAndroid Build Coastguard Worker jlong check_callback_tag;
1084*795d594fSAndroid Build Coastguard Worker jint check_callback_id;
1085*795d594fSAndroid Build Coastguard Worker };
1086*795d594fSAndroid Build Coastguard Worker
1087*795d594fSAndroid Build Coastguard Worker jvmtiHeapCallbacks callbacks;
1088*795d594fSAndroid Build Coastguard Worker memset(&callbacks, 0, sizeof(jvmtiHeapCallbacks));
1089*795d594fSAndroid Build Coastguard Worker callbacks.heap_iteration_callback = GetObjectHeapIdCallbacks::HeapIterationCallback;
1090*795d594fSAndroid Build Coastguard Worker
1091*795d594fSAndroid Build Coastguard Worker GetObjectHeapIdCallbacks ffc;
1092*795d594fSAndroid Build Coastguard Worker ffc.check_callback_tag = tag;
1093*795d594fSAndroid Build Coastguard Worker ffc.check_callback_id = heap_id;
1094*795d594fSAndroid Build Coastguard Worker
1095*795d594fSAndroid Build Coastguard Worker jvmtiError ret = jvmti_env->IterateThroughHeap(0, nullptr, &callbacks, &ffc);
1096*795d594fSAndroid Build Coastguard Worker if (JvmtiErrorToException(env, jvmti_env, ret)) {
1097*795d594fSAndroid Build Coastguard Worker return;
1098*795d594fSAndroid Build Coastguard Worker }
1099*795d594fSAndroid Build Coastguard Worker }
1100*795d594fSAndroid Build Coastguard Worker }
1101*795d594fSAndroid Build Coastguard Worker
1102*795d594fSAndroid Build Coastguard Worker static bool gFoundExt = false;
1103*795d594fSAndroid Build Coastguard Worker
HeapIterationExtCallback(jlong class_tag,jlong size,jlong * tag_ptr,jint length,void * user_data,jint heap_id)1104*795d594fSAndroid Build Coastguard Worker static jint JNICALL HeapIterationExtCallback([[maybe_unused]] jlong class_tag,
1105*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] jlong size,
1106*795d594fSAndroid Build Coastguard Worker jlong* tag_ptr,
1107*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] jint length,
1108*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] void* user_data,
1109*795d594fSAndroid Build Coastguard Worker jint heap_id) {
1110*795d594fSAndroid Build Coastguard Worker // We expect some tagged objects at or above the threshold, where the expected heap id is
1111*795d594fSAndroid Build Coastguard Worker // encoded into lowest byte.
1112*795d594fSAndroid Build Coastguard Worker constexpr jlong kThreshold = 30000000;
1113*795d594fSAndroid Build Coastguard Worker jlong tag = *tag_ptr;
1114*795d594fSAndroid Build Coastguard Worker if (tag >= kThreshold) {
1115*795d594fSAndroid Build Coastguard Worker jint expected_heap_id = static_cast<jint>(tag - kThreshold);
1116*795d594fSAndroid Build Coastguard Worker CHECK_EQ(expected_heap_id, heap_id);
1117*795d594fSAndroid Build Coastguard Worker gFoundExt = true;
1118*795d594fSAndroid Build Coastguard Worker }
1119*795d594fSAndroid Build Coastguard Worker return 0;
1120*795d594fSAndroid Build Coastguard Worker }
1121*795d594fSAndroid Build Coastguard Worker
Java_art_Test913_iterateThroughHeapExt(JNIEnv * env,jclass klass)1122*795d594fSAndroid Build Coastguard Worker extern "C" JNIEXPORT void JNICALL Java_art_Test913_iterateThroughHeapExt(
1123*795d594fSAndroid Build Coastguard Worker JNIEnv* env, [[maybe_unused]] jclass klass) {
1124*795d594fSAndroid Build Coastguard Worker CHECK(gIterateThroughHeapExt != nullptr);
1125*795d594fSAndroid Build Coastguard Worker
1126*795d594fSAndroid Build Coastguard Worker jvmtiHeapCallbacks callbacks;
1127*795d594fSAndroid Build Coastguard Worker memset(&callbacks, 0, sizeof(jvmtiHeapCallbacks));
1128*795d594fSAndroid Build Coastguard Worker callbacks.heap_iteration_callback =
1129*795d594fSAndroid Build Coastguard Worker reinterpret_cast<decltype(callbacks.heap_iteration_callback)>(HeapIterationExtCallback);
1130*795d594fSAndroid Build Coastguard Worker
1131*795d594fSAndroid Build Coastguard Worker jvmtiError ret = gIterateThroughHeapExt(jvmti_env, 0, nullptr, &callbacks, nullptr);
1132*795d594fSAndroid Build Coastguard Worker JvmtiErrorToException(env, jvmti_env, ret);
1133*795d594fSAndroid Build Coastguard Worker CHECK(gFoundExt);
1134*795d594fSAndroid Build Coastguard Worker }
1135*795d594fSAndroid Build Coastguard Worker
Java_art_Test913_checkInitialized(JNIEnv * env,jclass,jclass c)1136*795d594fSAndroid Build Coastguard Worker extern "C" JNIEXPORT jboolean JNICALL Java_art_Test913_checkInitialized(JNIEnv* env, jclass, jclass c) {
1137*795d594fSAndroid Build Coastguard Worker jint status;
1138*795d594fSAndroid Build Coastguard Worker jvmtiError error = jvmti_env->GetClassStatus(c, &status);
1139*795d594fSAndroid Build Coastguard Worker if (JvmtiErrorToException(env, jvmti_env, error)) {
1140*795d594fSAndroid Build Coastguard Worker return false;
1141*795d594fSAndroid Build Coastguard Worker }
1142*795d594fSAndroid Build Coastguard Worker return (status & JVMTI_CLASS_STATUS_INITIALIZED) != 0;
1143*795d594fSAndroid Build Coastguard Worker }
1144*795d594fSAndroid Build Coastguard Worker
1145*795d594fSAndroid Build Coastguard Worker } // namespace Test913Heaps
1146*795d594fSAndroid Build Coastguard Worker } // namespace art
1147