blob: 1c2d2a145a92663f0aa11d22c0db2719d744a4a2 [file] [log] [blame]
Alex Light0aa7a5a2018-10-10 15:58:14 +00001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <inttypes.h>
18
19#include <cstdio>
20#include <memory>
21#include <string>
22#include <vector>
23
24#include "android-base/logging.h"
25#include "android-base/stringprintf.h"
26
27#include "jni.h"
28#include "jvmti.h"
29#include "scoped_local_ref.h"
30#include "scoped_utf_chars.h"
31
32// Test infrastructure
33#include "jni_binder.h"
34#include "jni_helper.h"
35#include "jvmti_helper.h"
36#include "test_env.h"
37#include "ti_macros.h"
38
39namespace art {
40namespace Test1953PopFrame {
41
42struct TestData {
43 jlocation target_loc;
44 jmethodID target_method;
45 jclass target_klass;
46 jfieldID target_field;
47 jrawMonitorID notify_monitor;
48 jint frame_pop_offset;
49 jmethodID frame_pop_setup_method;
50 std::vector<std::string> interesting_classes;
51 bool hit_location;
52
53 TestData(jvmtiEnv* jvmti,
54 JNIEnv* env,
55 jlocation loc,
56 jobject meth,
57 jclass klass,
58 jobject field,
59 jobject setup_meth,
60 jint pop_offset,
61 const std::vector<std::string>&& interesting)
62 : target_loc(loc),
63 target_method(meth != nullptr ? env->FromReflectedMethod(meth) : nullptr),
64 target_klass(reinterpret_cast<jclass>(env->NewGlobalRef(klass))),
65 target_field(field != nullptr ? env->FromReflectedField(field) : nullptr),
66 frame_pop_offset(pop_offset),
67 frame_pop_setup_method(setup_meth != nullptr ? env->FromReflectedMethod(setup_meth)
68 : nullptr),
69 interesting_classes(interesting),
70 hit_location(false) {
71 JvmtiErrorToException(env, jvmti, jvmti->CreateRawMonitor("SuspendStopMonitor",
72 &notify_monitor));
73 }
74
75 void PerformSuspend(jvmtiEnv* jvmti, JNIEnv* env) {
76 // Wake up the waiting thread.
77 JvmtiErrorToException(env, jvmti, jvmti->RawMonitorEnter(notify_monitor));
78 hit_location = true;
79 JvmtiErrorToException(env, jvmti, jvmti->RawMonitorNotifyAll(notify_monitor));
80 JvmtiErrorToException(env, jvmti, jvmti->RawMonitorExit(notify_monitor));
81 // Suspend ourself
82 jvmti->SuspendThread(nullptr);
83 }
84};
85
86void JNICALL cbSingleStep(jvmtiEnv* jvmti,
87 JNIEnv* env,
88 jthread thr,
89 jmethodID meth,
90 jlocation loc) {
91 TestData *data;
92 if (JvmtiErrorToException(env,
93 jvmti,
94 jvmti->GetThreadLocalStorage(thr, reinterpret_cast<void**>(&data)))) {
95 return;
96 }
97 CHECK(data != nullptr);
98 if (meth != data->target_method || loc != data->target_loc) {
99 return;
100 }
101 data->PerformSuspend(jvmti, env);
102}
103
104void JNICALL cbExceptionCatch(jvmtiEnv *jvmti,
105 JNIEnv* env,
106 jthread thr,
107 jmethodID method,
108 jlocation location ATTRIBUTE_UNUSED,
109 jobject exception ATTRIBUTE_UNUSED) {
110 TestData *data;
111 if (JvmtiErrorToException(env,
112 jvmti,
113 jvmti->GetThreadLocalStorage(thr, reinterpret_cast<void**>(&data)))) {
114 return;
115 }
116 CHECK(data != nullptr);
117 if (method != data->target_method) {
118 return;
119 }
120 data->PerformSuspend(jvmti, env);
121}
122
123void JNICALL cbException(jvmtiEnv *jvmti,
124 JNIEnv* env,
125 jthread thr,
126 jmethodID method,
127 jlocation location ATTRIBUTE_UNUSED,
128 jobject exception ATTRIBUTE_UNUSED,
129 jmethodID catch_method ATTRIBUTE_UNUSED,
130 jlocation catch_location ATTRIBUTE_UNUSED) {
131 TestData *data;
132 if (JvmtiErrorToException(env,
133 jvmti,
134 jvmti->GetThreadLocalStorage(thr, reinterpret_cast<void**>(&data)))) {
135 return;
136 }
137 CHECK(data != nullptr);
138 if (method != data->target_method) {
139 return;
140 }
141 data->PerformSuspend(jvmti, env);
142}
143
144void JNICALL cbMethodEntry(jvmtiEnv *jvmti,
145 JNIEnv* env,
146 jthread thr,
147 jmethodID method) {
148 TestData *data;
149 if (JvmtiErrorToException(env,
150 jvmti,
151 jvmti->GetThreadLocalStorage(thr, reinterpret_cast<void**>(&data)))) {
152 return;
153 }
154 CHECK(data != nullptr);
155 if (method != data->target_method) {
156 return;
157 }
158 data->PerformSuspend(jvmti, env);
159}
160
161void JNICALL cbMethodExit(jvmtiEnv *jvmti,
162 JNIEnv* env,
163 jthread thr,
164 jmethodID method,
165 jboolean was_popped_by_exception ATTRIBUTE_UNUSED,
166 jvalue return_value ATTRIBUTE_UNUSED) {
167 TestData *data;
168 if (JvmtiErrorToException(env,
169 jvmti,
170 jvmti->GetThreadLocalStorage(thr, reinterpret_cast<void**>(&data)))) {
171 return;
172 }
173 CHECK(data != nullptr);
174 if (method != data->target_method) {
175 return;
176 }
177 data->PerformSuspend(jvmti, env);
178}
179
180void JNICALL cbFieldModification(jvmtiEnv* jvmti,
181 JNIEnv* env,
182 jthread thr,
183 jmethodID method ATTRIBUTE_UNUSED,
184 jlocation location ATTRIBUTE_UNUSED,
185 jclass field_klass ATTRIBUTE_UNUSED,
186 jobject object ATTRIBUTE_UNUSED,
187 jfieldID field,
188 char signature_type ATTRIBUTE_UNUSED,
189 jvalue new_value ATTRIBUTE_UNUSED) {
190 TestData *data;
191 if (JvmtiErrorToException(env,
192 jvmti,
193 jvmti->GetThreadLocalStorage(thr, reinterpret_cast<void**>(&data)))) {
194 return;
195 }
196 CHECK(data != nullptr);
197 if (field != data->target_field) {
198 // TODO What to do here.
199 LOG(FATAL) << "Strange, shouldn't get here!";
200 }
201 data->PerformSuspend(jvmti, env);
202}
203
204void JNICALL cbFieldAccess(jvmtiEnv* jvmti,
205 JNIEnv* env,
206 jthread thr,
207 jmethodID method ATTRIBUTE_UNUSED,
208 jlocation location ATTRIBUTE_UNUSED,
209 jclass field_klass,
210 jobject object ATTRIBUTE_UNUSED,
211 jfieldID field) {
212 TestData *data;
213 if (JvmtiErrorToException(env,
214 jvmti,
215 jvmti->GetThreadLocalStorage(thr, reinterpret_cast<void**>(&data)))) {
216 return;
217 }
218 CHECK(data != nullptr);
219 if (field != data->target_field || !env->IsSameObject(field_klass, data->target_klass)) {
220 // TODO What to do here.
221 LOG(FATAL) << "Strange, shouldn't get here!";
222 }
223 data->PerformSuspend(jvmti, env);
224}
225
226void JNICALL cbBreakpointHit(jvmtiEnv* jvmti,
227 JNIEnv* env,
228 jthread thr,
229 jmethodID method,
230 jlocation loc) {
231 TestData *data;
232 if (JvmtiErrorToException(env,
233 jvmti,
234 jvmti->GetThreadLocalStorage(thr, reinterpret_cast<void**>(&data)))) {
235 return;
236 }
237 CHECK(data != nullptr);
238 if (data->frame_pop_setup_method == method) {
239 CHECK(loc == 0) << "We should have stopped at location 0";
240 if (JvmtiErrorToException(env,
241 jvmti,
242 jvmti->NotifyFramePop(thr, data->frame_pop_offset))) {
243 return;
244 }
245 return;
246 }
247 if (method != data->target_method || loc != data->target_loc) {
248 // TODO What to do here.
249 LOG(FATAL) << "Strange, shouldn't get here!";
250 }
251 data->PerformSuspend(jvmti, env);
252}
253
254void JNICALL cbFramePop(jvmtiEnv* jvmti,
255 JNIEnv* env,
256 jthread thr,
257 jmethodID method ATTRIBUTE_UNUSED,
258 jboolean was_popped_by_exception ATTRIBUTE_UNUSED) {
259 TestData *data;
260 if (JvmtiErrorToException(env,
261 jvmti,
262 jvmti->GetThreadLocalStorage(thr, reinterpret_cast<void**>(&data)))) {
263 return;
264 }
265 CHECK(data != nullptr);
266 data->PerformSuspend(jvmti, env);
267}
268
269void JNICALL cbClassLoadOrPrepare(jvmtiEnv* jvmti,
270 JNIEnv* env,
271 jthread thr,
272 jclass klass) {
273 TestData *data;
274 if (JvmtiErrorToException(env,
275 jvmti,
276 jvmti->GetThreadLocalStorage(thr, reinterpret_cast<void**>(&data)))) {
277 return;
278 }
279 CHECK(data != nullptr);
280 char* name;
281 if (JvmtiErrorToException(env, jvmti, jvmti->GetClassSignature(klass, &name, nullptr))) {
282 return;
283 }
284 std::string name_str(name);
285 if (JvmtiErrorToException(env,
286 jvmti,
287 jvmti->Deallocate(reinterpret_cast<unsigned char*>(name)))) {
288 return;
289 }
290 if (std::find(data->interesting_classes.cbegin(),
291 data->interesting_classes.cend(),
292 name_str) != data->interesting_classes.cend()) {
293 data->PerformSuspend(jvmti, env);
294 }
295}
296
297extern "C" JNIEXPORT
298void JNICALL Java_art_Test1953_setupTest(JNIEnv* env, jclass klass ATTRIBUTE_UNUSED) {
299 jvmtiCapabilities caps;
300 memset(&caps, 0, sizeof(caps));
301 // Most of these will already be there but might as well be complete.
302 caps.can_pop_frame = 1;
303 caps.can_generate_single_step_events = 1;
304 caps.can_generate_breakpoint_events = 1;
305 caps.can_suspend = 1;
306 caps.can_generate_method_entry_events = 1;
307 caps.can_generate_method_exit_events = 1;
308 caps.can_generate_monitor_events = 1;
309 caps.can_generate_exception_events = 1;
310 caps.can_generate_frame_pop_events = 1;
311 caps.can_generate_field_access_events = 1;
312 caps.can_generate_field_modification_events = 1;
313 caps.can_redefine_classes = 1;
314 if (JvmtiErrorToException(env, jvmti_env, jvmti_env->AddCapabilities(&caps))) {
315 return;
316 }
317 jvmtiEventCallbacks cb;
318 memset(&cb, 0, sizeof(cb));
319 // TODO Add the rest of these.
320 cb.Breakpoint = cbBreakpointHit;
321 cb.SingleStep = cbSingleStep;
322 cb.FieldAccess = cbFieldAccess;
323 cb.FieldModification = cbFieldModification;
324 cb.MethodEntry = cbMethodEntry;
325 cb.MethodExit = cbMethodExit;
326 cb.Exception = cbException;
327 cb.ExceptionCatch = cbExceptionCatch;
328 cb.FramePop = cbFramePop;
329 cb.ClassLoad = cbClassLoadOrPrepare;
330 cb.ClassPrepare = cbClassLoadOrPrepare;
331 JvmtiErrorToException(env, jvmti_env, jvmti_env->SetEventCallbacks(&cb, sizeof(cb)));
332}
333
334static bool DeleteTestData(JNIEnv* env, jthread thr, TestData* data) {
335 env->DeleteGlobalRef(data->target_klass);
336 if (JvmtiErrorToException(env,
337 jvmti_env,
338 jvmti_env->SetThreadLocalStorage(thr, nullptr))) {
339 return false;
340 }
341 return JvmtiErrorToException(env,
342 jvmti_env,
343 jvmti_env->Deallocate(reinterpret_cast<uint8_t*>(data)));
344}
345
346static TestData* SetupTestData(JNIEnv* env,
347 jobject meth,
348 jlocation loc,
349 jclass target_klass,
350 jobject field,
351 jobject setup_meth,
352 jint pop_offset,
353 const std::vector<std::string>&& interesting_names) {
354 void* data_ptr;
355 TestData *data;
356 if (JvmtiErrorToException(env,
357 jvmti_env,
358 jvmti_env->Allocate(sizeof(TestData),
359 reinterpret_cast<uint8_t**>(&data_ptr)))) {
360 return nullptr;
361 }
362 data = new (data_ptr) TestData(jvmti_env,
363 env,
364 loc,
365 meth,
366 target_klass,
367 field,
368 setup_meth,
369 pop_offset,
370 std::move(interesting_names));
371 if (env->ExceptionCheck()) {
372 env->DeleteGlobalRef(data->target_klass);
373 jvmti_env->Deallocate(reinterpret_cast<uint8_t*>(data));
374 return nullptr;
375 }
376 return data;
377}
378
379static TestData* SetupTestData(JNIEnv* env,
380 jobject meth,
381 jlocation loc,
382 jclass target_klass,
383 jobject field,
384 jobject setup_meth,
385 jint pop_offset) {
386 std::vector<std::string> empty;
387 return SetupTestData(
388 env, meth, loc, target_klass, field, setup_meth, pop_offset, std::move(empty));
389}
390
391extern "C" JNIEXPORT
392void JNICALL Java_art_Test1953_setupSuspendClassEvent(JNIEnv* env,
393 jclass klass ATTRIBUTE_UNUSED,
394 jint event_num,
395 jobjectArray interesting_names,
396 jthread thr) {
397 CHECK(event_num == JVMTI_EVENT_CLASS_LOAD || event_num == JVMTI_EVENT_CLASS_PREPARE);
398 std::vector<std::string> names;
399 jint cnt = env->GetArrayLength(interesting_names);
400 for (jint i = 0; i < cnt; i++) {
401 env->PushLocalFrame(1);
402 jstring name_obj = reinterpret_cast<jstring>(env->GetObjectArrayElement(interesting_names, i));
403 const char* name_chr = env->GetStringUTFChars(name_obj, nullptr);
404 names.push_back(std::string(name_chr));
405 env->ReleaseStringUTFChars(name_obj, name_chr);
406 env->PopLocalFrame(nullptr);
407 }
408 TestData* data;
409 if (JvmtiErrorToException(env,
410 jvmti_env,
411 jvmti_env->GetThreadLocalStorage(thr,
412 reinterpret_cast<void**>(&data)))) {
413 return;
414 }
415 CHECK(data == nullptr) << "Data was not cleared!";
416 data = SetupTestData(env, nullptr, 0, nullptr, nullptr, nullptr, 0, std::move(names));
417 if (data == nullptr) {
418 return;
419 }
420 if (JvmtiErrorToException(env,
421 jvmti_env,
422 jvmti_env->SetThreadLocalStorage(thr, data))) {
423 return;
424 }
425 JvmtiErrorToException(env,
426 jvmti_env,
427 jvmti_env->SetEventNotificationMode(JVMTI_ENABLE,
428 static_cast<jvmtiEvent>(event_num),
429 thr));
430}
431
432extern "C" JNIEXPORT
433void JNICALL Java_art_Test1953_clearSuspendClassEvent(JNIEnv* env,
434 jclass klass ATTRIBUTE_UNUSED,
435 jthread thr) {
436 TestData *data;
437 if (JvmtiErrorToException(env,
438 jvmti_env,
439 jvmti_env->GetThreadLocalStorage(thr,
440 reinterpret_cast<void**>(&data)))) {
441 return;
442 }
443 CHECK(data != nullptr);
444 if (JvmtiErrorToException(env,
445 jvmti_env,
446 jvmti_env->SetEventNotificationMode(JVMTI_DISABLE,
447 JVMTI_EVENT_CLASS_LOAD,
448 thr))) {
449 return;
450 }
451 if (JvmtiErrorToException(env,
452 jvmti_env,
453 jvmti_env->SetEventNotificationMode(JVMTI_DISABLE,
454 JVMTI_EVENT_CLASS_PREPARE,
455 thr))) {
456 return;
457 }
458 DeleteTestData(env, thr, data);
459}
460
461extern "C" JNIEXPORT
462void JNICALL Java_art_Test1953_setupSuspendSingleStepAt(JNIEnv* env,
463 jclass klass ATTRIBUTE_UNUSED,
464 jobject meth,
465 jlocation loc,
466 jthread thr) {
467 TestData *data;
468 if (JvmtiErrorToException(env,
469 jvmti_env,
470 jvmti_env->GetThreadLocalStorage(thr,
471 reinterpret_cast<void**>(&data)))) {
472 return;
473 }
474 CHECK(data == nullptr) << "Data was not cleared!";
475 data = SetupTestData(env, meth, loc, nullptr, nullptr, nullptr, 0);
476 if (data == nullptr) {
477 return;
478 }
479 if (JvmtiErrorToException(env,
480 jvmti_env,
481 jvmti_env->SetThreadLocalStorage(thr, data))) {
482 return;
483 }
484 JvmtiErrorToException(env, jvmti_env, jvmti_env->SetEventNotificationMode(JVMTI_ENABLE,
485 JVMTI_EVENT_SINGLE_STEP,
486 thr));
487}
488
489extern "C" JNIEXPORT
490void JNICALL Java_art_Test1953_clearSuspendSingleStepFor(JNIEnv* env,
491 jclass klass ATTRIBUTE_UNUSED,
492 jthread thr) {
493 TestData *data;
494 if (JvmtiErrorToException(env,
495 jvmti_env,
496 jvmti_env->GetThreadLocalStorage(thr,
497 reinterpret_cast<void**>(&data)))) {
498 return;
499 }
500 CHECK(data != nullptr);
501 if (JvmtiErrorToException(env,
502 jvmti_env,
503 jvmti_env->SetEventNotificationMode(JVMTI_DISABLE,
504 JVMTI_EVENT_SINGLE_STEP,
505 thr))) {
506 return;
507 }
508 DeleteTestData(env, thr, data);
509}
510
511extern "C" JNIEXPORT
512void JNICALL Java_art_Test1953_setupSuspendPopFrameEvent(JNIEnv* env,
513 jclass klass ATTRIBUTE_UNUSED,
514 jint offset,
515 jobject breakpoint_func,
516 jthread thr) {
517 TestData *data;
518 if (JvmtiErrorToException(env,
519 jvmti_env,
520 jvmti_env->GetThreadLocalStorage(thr,
521 reinterpret_cast<void**>(&data)))) {
522 return;
523 }
524 CHECK(data == nullptr) << "Data was not cleared!";
525 data = SetupTestData(env, nullptr, 0, nullptr, nullptr, breakpoint_func, offset);
526 CHECK(data != nullptr);
527 if (JvmtiErrorToException(env,
528 jvmti_env,
529 jvmti_env->SetThreadLocalStorage(thr, data))) {
530 return;
531 }
532 if (JvmtiErrorToException(env,
533 jvmti_env,
534 jvmti_env->SetEventNotificationMode(JVMTI_ENABLE,
535 JVMTI_EVENT_FRAME_POP,
536 thr))) {
537 return;
538 }
539 if (JvmtiErrorToException(env,
540 jvmti_env,
541 jvmti_env->SetEventNotificationMode(JVMTI_ENABLE,
542 JVMTI_EVENT_BREAKPOINT,
543 thr))) {
544 return;
545 }
546 if (JvmtiErrorToException(env,
547 jvmti_env,
548 jvmti_env->SetBreakpoint(data->frame_pop_setup_method, 0))) {
549 return;
550 }
551}
552
553extern "C" JNIEXPORT
554void JNICALL Java_art_Test1953_clearSuspendPopFrameEvent(JNIEnv* env,
555 jclass klass ATTRIBUTE_UNUSED,
556 jthread thr) {
557 TestData *data;
558 if (JvmtiErrorToException(env,
559 jvmti_env,
560 jvmti_env->GetThreadLocalStorage(thr,
561 reinterpret_cast<void**>(&data)))) {
562 return;
563 }
564 CHECK(data != nullptr);
565 if (JvmtiErrorToException(env,
566 jvmti_env,
567 jvmti_env->SetEventNotificationMode(JVMTI_DISABLE,
568 JVMTI_EVENT_FRAME_POP,
569 thr))) {
570 return;
571 }
572 if (JvmtiErrorToException(env,
573 jvmti_env,
574 jvmti_env->SetEventNotificationMode(JVMTI_DISABLE,
575 JVMTI_EVENT_BREAKPOINT,
576 thr))) {
577 return;
578 }
579 if (JvmtiErrorToException(env,
580 jvmti_env,
581 jvmti_env->ClearBreakpoint(data->frame_pop_setup_method, 0))) {
582 return;
583 }
584 DeleteTestData(env, thr, data);
585}
586
587extern "C" JNIEXPORT
588void JNICALL Java_art_Test1953_setupSuspendBreakpointFor(JNIEnv* env,
589 jclass klass ATTRIBUTE_UNUSED,
590 jobject meth,
591 jlocation loc,
592 jthread thr) {
593 TestData *data;
594 if (JvmtiErrorToException(env,
595 jvmti_env,
596 jvmti_env->GetThreadLocalStorage(thr,
597 reinterpret_cast<void**>(&data)))) {
598 return;
599 }
600 CHECK(data == nullptr) << "Data was not cleared!";
601 data = SetupTestData(env, meth, loc, nullptr, nullptr, nullptr, 0);
602 if (data == nullptr) {
603 return;
604 }
605 if (JvmtiErrorToException(env,
606 jvmti_env,
607 jvmti_env->SetThreadLocalStorage(thr, data))) {
608 return;
609 }
610 if (JvmtiErrorToException(env,
611 jvmti_env,
612 jvmti_env->SetEventNotificationMode(JVMTI_ENABLE,
613 JVMTI_EVENT_BREAKPOINT,
614 thr))) {
615 return;
616 }
617 JvmtiErrorToException(env, jvmti_env, jvmti_env->SetBreakpoint(data->target_method,
618 data->target_loc));
619}
620
621extern "C" JNIEXPORT
622void JNICALL Java_art_Test1953_clearSuspendBreakpointFor(JNIEnv* env,
623 jclass klass ATTRIBUTE_UNUSED,
624 jthread thr) {
625 TestData *data;
626 if (JvmtiErrorToException(env,
627 jvmti_env,
628 jvmti_env->GetThreadLocalStorage(thr,
629 reinterpret_cast<void**>(&data)))) {
630 return;
631 }
632 CHECK(data != nullptr);
633 if (JvmtiErrorToException(env,
634 jvmti_env,
635 jvmti_env->SetEventNotificationMode(JVMTI_DISABLE,
636 JVMTI_EVENT_BREAKPOINT,
637 thr))) {
638 return;
639 }
640 if (JvmtiErrorToException(env,
641 jvmti_env,
642 jvmti_env->ClearBreakpoint(data->target_method,
643 data->target_loc))) {
644 return;
645 }
646 if (JvmtiErrorToException(env,
647 jvmti_env,
648 jvmti_env->SetThreadLocalStorage(thr, nullptr))) {
649 return;
650 }
651 DeleteTestData(env, thr, data);
652}
653
654extern "C" JNIEXPORT
655void JNICALL Java_art_Test1953_setupSuspendExceptionEvent(JNIEnv* env,
656 jclass klass ATTRIBUTE_UNUSED,
657 jobject method,
658 jboolean is_catch,
659 jthread thr) {
660 TestData *data;
661 if (JvmtiErrorToException(env,
662 jvmti_env,
663 jvmti_env->GetThreadLocalStorage(
664 thr, reinterpret_cast<void**>(&data)))) {
665 return;
666 }
667 CHECK(data == nullptr) << "Data was not cleared!";
668 data = SetupTestData(env, method, 0, nullptr, nullptr, nullptr, 0);
669 if (data == nullptr) {
670 return;
671 }
672 if (JvmtiErrorToException(env,
673 jvmti_env,
674 jvmti_env->SetThreadLocalStorage(thr, data))) {
675 return;
676 }
677 JvmtiErrorToException(env,
678 jvmti_env,
679 jvmti_env->SetEventNotificationMode(
680 JVMTI_ENABLE,
681 is_catch ? JVMTI_EVENT_EXCEPTION_CATCH : JVMTI_EVENT_EXCEPTION,
682 thr));
683}
684
685extern "C" JNIEXPORT
686void JNICALL Java_art_Test1953_clearSuspendExceptionEvent(JNIEnv* env,
687 jclass klass ATTRIBUTE_UNUSED,
688 jthread thr) {
689 TestData *data;
690 if (JvmtiErrorToException(env,
691 jvmti_env,
692 jvmti_env->GetThreadLocalStorage(thr,
693 reinterpret_cast<void**>(&data)))) {
694 return;
695 }
696 CHECK(data != nullptr);
697 if (JvmtiErrorToException(env,
698 jvmti_env,
699 jvmti_env->SetEventNotificationMode(JVMTI_DISABLE,
700 JVMTI_EVENT_EXCEPTION_CATCH,
701 thr))) {
702 return;
703 }
704 if (JvmtiErrorToException(env,
705 jvmti_env,
706 jvmti_env->SetEventNotificationMode(JVMTI_DISABLE,
707 JVMTI_EVENT_EXCEPTION,
708 thr))) {
709 return;
710 }
711 DeleteTestData(env, thr, data);
712}
713
714extern "C" JNIEXPORT
715void JNICALL Java_art_Test1953_setupSuspendMethodEvent(JNIEnv* env,
716 jclass klass ATTRIBUTE_UNUSED,
717 jobject method,
718 jboolean enter,
719 jthread thr) {
720 TestData *data;
721 if (JvmtiErrorToException(env,
722 jvmti_env,
723 jvmti_env->GetThreadLocalStorage(
724 thr, reinterpret_cast<void**>(&data)))) {
725 return;
726 }
727 CHECK(data == nullptr) << "Data was not cleared!";
728 data = SetupTestData(env, method, 0, nullptr, nullptr, nullptr, 0);
729 if (data == nullptr) {
730 return;
731 }
732 if (JvmtiErrorToException(env,
733 jvmti_env,
734 jvmti_env->SetThreadLocalStorage(thr, data))) {
735 return;
736 }
737 JvmtiErrorToException(env,
738 jvmti_env,
739 jvmti_env->SetEventNotificationMode(
740 JVMTI_ENABLE,
741 enter ? JVMTI_EVENT_METHOD_ENTRY : JVMTI_EVENT_METHOD_EXIT,
742 thr));
743}
744
745extern "C" JNIEXPORT
746void JNICALL Java_art_Test1953_clearSuspendMethodEvent(JNIEnv* env,
747 jclass klass ATTRIBUTE_UNUSED,
748 jthread thr) {
749 TestData *data;
750 if (JvmtiErrorToException(env,
751 jvmti_env,
752 jvmti_env->GetThreadLocalStorage(thr,
753 reinterpret_cast<void**>(&data)))) {
754 return;
755 }
756 CHECK(data != nullptr);
757 if (JvmtiErrorToException(env,
758 jvmti_env,
759 jvmti_env->SetEventNotificationMode(JVMTI_DISABLE,
760 JVMTI_EVENT_METHOD_EXIT,
761 thr))) {
762 return;
763 }
764 if (JvmtiErrorToException(env,
765 jvmti_env,
766 jvmti_env->SetEventNotificationMode(JVMTI_DISABLE,
767 JVMTI_EVENT_METHOD_ENTRY,
768 thr))) {
769 return;
770 }
771 DeleteTestData(env, thr, data);
772}
773
774extern "C" JNIEXPORT
775void JNICALL Java_art_Test1953_setupFieldSuspendFor(JNIEnv* env,
776 jclass klass ATTRIBUTE_UNUSED,
777 jclass target_klass,
778 jobject field,
779 jboolean access,
780 jthread thr) {
781 TestData *data;
782 if (JvmtiErrorToException(env,
783 jvmti_env,
784 jvmti_env->GetThreadLocalStorage(
785 thr, reinterpret_cast<void**>(&data)))) {
786 return;
787 }
788 CHECK(data == nullptr) << "Data was not cleared!";
789 data = SetupTestData(env, nullptr, 0, target_klass, field, nullptr, 0);
790 if (data == nullptr) {
791 return;
792 }
793 if (JvmtiErrorToException(env,
794 jvmti_env,
795 jvmti_env->SetThreadLocalStorage(thr, data))) {
796 return;
797 }
798 if (JvmtiErrorToException(env,
799 jvmti_env,
800 jvmti_env->SetEventNotificationMode(
801 JVMTI_ENABLE,
802 access ? JVMTI_EVENT_FIELD_ACCESS : JVMTI_EVENT_FIELD_MODIFICATION,
803 thr))) {
804 return;
805 }
806 if (access) {
807 JvmtiErrorToException(env, jvmti_env, jvmti_env->SetFieldAccessWatch(data->target_klass,
808 data->target_field));
809 } else {
810 JvmtiErrorToException(env, jvmti_env, jvmti_env->SetFieldModificationWatch(data->target_klass,
811 data->target_field));
812 }
813}
814
815extern "C" JNIEXPORT
816void JNICALL Java_art_Test1953_clearFieldSuspendFor(JNIEnv* env,
817 jclass klass ATTRIBUTE_UNUSED,
818 jthread thr) {
819 TestData *data;
820 if (JvmtiErrorToException(env,
821 jvmti_env,
822 jvmti_env->GetThreadLocalStorage(thr,
823 reinterpret_cast<void**>(&data)))) {
824 return;
825 }
826 CHECK(data != nullptr);
827 if (JvmtiErrorToException(env,
828 jvmti_env,
829 jvmti_env->SetEventNotificationMode(JVMTI_DISABLE,
830 JVMTI_EVENT_FIELD_ACCESS,
831 thr))) {
832 return;
833 }
834 if (JvmtiErrorToException(env,
835 jvmti_env,
836 jvmti_env->SetEventNotificationMode(JVMTI_DISABLE,
837 JVMTI_EVENT_FIELD_MODIFICATION,
838 thr))) {
839 return;
840 }
841 if (JvmtiErrorToException(env,
842 jvmti_env,
843 jvmti_env->ClearFieldModificationWatch(
844 data->target_klass, data->target_field)) &&
845 JvmtiErrorToException(env,
846 jvmti_env,
847 jvmti_env->ClearFieldAccessWatch(
848 data->target_klass, data->target_field))) {
849 return;
850 } else {
851 env->ExceptionClear();
852 }
853 if (JvmtiErrorToException(env,
854 jvmti_env,
855 jvmti_env->SetThreadLocalStorage(thr, nullptr))) {
856 return;
857 }
858 DeleteTestData(env, thr, data);
859}
860
861extern "C" JNIEXPORT
862void JNICALL Java_art_Test1953_setupWaitForNativeCall(JNIEnv* env,
863 jclass klass ATTRIBUTE_UNUSED,
864 jthread thr) {
865 TestData *data;
866 if (JvmtiErrorToException(env,
867 jvmti_env,
868 jvmti_env->GetThreadLocalStorage(
869 thr, reinterpret_cast<void**>(&data)))) {
870 return;
871 }
872 CHECK(data == nullptr) << "Data was not cleared!";
873 data = SetupTestData(env, nullptr, 0, nullptr, nullptr, nullptr, 0);
874 if (data == nullptr) {
875 return;
876 }
877 if (JvmtiErrorToException(env,
878 jvmti_env,
879 jvmti_env->SetThreadLocalStorage(thr, data))) {
880 return;
881 }
882}
883
884extern "C" JNIEXPORT
885void JNICALL Java_art_Test1953_clearWaitForNativeCall(JNIEnv* env,
886 jclass klass ATTRIBUTE_UNUSED,
887 jthread thr) {
888 TestData *data;
889 if (JvmtiErrorToException(env,
890 jvmti_env,
891 jvmti_env->GetThreadLocalStorage(thr,
892 reinterpret_cast<void**>(&data)))) {
893 return;
894 }
895 CHECK(data != nullptr);
896 if (JvmtiErrorToException(env,
897 jvmti_env,
898 jvmti_env->SetThreadLocalStorage(thr, nullptr))) {
899 return;
900 }
901 DeleteTestData(env, thr, data);
902}
903
904extern "C" JNIEXPORT
905void JNICALL Java_art_Test1953_waitForSuspendHit(JNIEnv* env,
906 jclass klass ATTRIBUTE_UNUSED,
907 jthread thr) {
908 TestData *data;
909 if (JvmtiErrorToException(env,
910 jvmti_env,
911 jvmti_env->GetThreadLocalStorage(thr,
912 reinterpret_cast<void**>(&data)))) {
913 return;
914 }
915 CHECK(data != nullptr);
916 if (JvmtiErrorToException(env, jvmti_env, jvmti_env->RawMonitorEnter(data->notify_monitor))) {
917 return;
918 }
919 while (!data->hit_location) {
920 if (JvmtiErrorToException(env, jvmti_env, jvmti_env->RawMonitorWait(data->notify_monitor, -1))) {
921 return;
922 }
923 }
924 if (JvmtiErrorToException(env, jvmti_env, jvmti_env->RawMonitorExit(data->notify_monitor))) {
925 return;
926 }
927 jint state = 0;
928 while (!JvmtiErrorToException(env, jvmti_env, jvmti_env->GetThreadState(thr, &state)) &&
929 (state & JVMTI_THREAD_STATE_SUSPENDED) == 0) { }
930}
931
932extern "C" JNIEXPORT
933void JNICALL Java_art_Test1953_popFrame(JNIEnv* env,
934 jclass klass ATTRIBUTE_UNUSED,
935 jthread thr) {
936 JvmtiErrorToException(env, jvmti_env, jvmti_env->PopFrame(thr));
937}
938
939extern "C" JNIEXPORT
940void JNICALL Java_art_Test1953_00024NativeCalledObject_calledFunction(
941 JNIEnv* env, jobject thiz) {
942 env->PushLocalFrame(1);
943 jclass klass = env->GetObjectClass(thiz);
944 jfieldID cnt = env->GetFieldID(klass, "cnt", "I");
945 env->SetIntField(thiz, cnt, env->GetIntField(thiz, cnt) + 1);
946 env->PopLocalFrame(nullptr);
947 TestData *data;
948 if (JvmtiErrorToException(env,
949 jvmti_env,
950 jvmti_env->GetThreadLocalStorage(/* thread */ nullptr,
951 reinterpret_cast<void**>(&data)))) {
952 return;
953 }
954 CHECK(data != nullptr);
955 data->PerformSuspend(jvmti_env, env);
956}
957
958extern "C" JNIEXPORT
959void JNICALL Java_art_Test1953_00024NativeCallerObject_run(
960 JNIEnv* env, jobject thiz) {
961 env->PushLocalFrame(1);
962 jclass klass = env->GetObjectClass(thiz);
963 jfieldID baseCnt = env->GetFieldID(klass, "baseCnt", "I");
964 env->SetIntField(thiz, baseCnt, env->GetIntField(thiz, baseCnt) + 1);
965 jmethodID called = env->GetMethodID(klass, "calledFunction", "()V");
966 env->CallVoidMethod(thiz, called);
967 env->PopLocalFrame(nullptr);
968}
969
970extern "C" JNIEXPORT
971jboolean JNICALL Java_art_Test1953_isClassLoaded(JNIEnv* env, jclass, jstring name) {
972 ScopedUtfChars chr(env, name);
973 if (env->ExceptionCheck()) {
974 return false;
975 }
976 jint cnt = 0;
977 jclass* klasses = nullptr;
978 if (JvmtiErrorToException(env, jvmti_env, jvmti_env->GetLoadedClasses(&cnt, &klasses))) {
979 return false;
980 }
981 bool res = false;
982 for (jint i = 0; !res && i < cnt; i++) {
983 char* sig;
984 if (JvmtiErrorToException(env,
985 jvmti_env,
986 jvmti_env->GetClassSignature(klasses[i], &sig, nullptr))) {
987 return false;
988 }
989 res = (strcmp(sig, chr.c_str()) == 0);
990 jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(sig));
991 }
992 jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(klasses));
993 return res;
994}
995
996} // namespace Test1953PopFrame
997} // namespace art
998