92 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			92 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			C++
		
	
	
	
| /*
 | |
|  * Copyright (C) 2019 The Android Open Source Project
 | |
|  *
 | |
|  * Licensed under the Apache License, Version 2.0 (the "License");
 | |
|  * you may not use this file except in compliance with the License.
 | |
|  * You may obtain a copy of the License at
 | |
|  *
 | |
|  *      http://www.apache.org/licenses/LICENSE-2.0
 | |
|  *
 | |
|  * Unless required by applicable law or agreed to in writing, software
 | |
|  * distributed under the License is distributed on an "AS IS" BASIS,
 | |
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
|  * See the License for the specific language governing permissions and
 | |
|  * limitations under the License.
 | |
|  */
 | |
| 
 | |
| #include <stdio.h>
 | |
| 
 | |
| #include "android-base/macros.h"
 | |
| 
 | |
| #include "jni.h"
 | |
| #include "jvmti.h"
 | |
| #include "scoped_local_ref.h"
 | |
| 
 | |
| // Test infrastructure
 | |
| #include "jni_helper.h"
 | |
| #include "jvmti_helper.h"
 | |
| #include "test_env.h"
 | |
| 
 | |
| namespace art {
 | |
| namespace Test1962MultiThreadEvents {
 | |
| 
 | |
| struct BreakpointData {
 | |
|   jobject events;
 | |
|   jmethodID target;
 | |
| };
 | |
| void cbMethodEntry(jvmtiEnv* jvmti,
 | |
|                    JNIEnv* env,
 | |
|                    jthread thread,
 | |
|                    jmethodID method,
 | |
|                    jboolean was_exception ATTRIBUTE_UNUSED,
 | |
|                    jvalue val ATTRIBUTE_UNUSED) {
 | |
|   BreakpointData* data = nullptr;
 | |
|   if (JvmtiErrorToException(
 | |
|           env, jvmti, jvmti->GetThreadLocalStorage(thread, reinterpret_cast<void**>(&data)))) {
 | |
|     return;
 | |
|   }
 | |
|   if (data->target != method) {
 | |
|     return;
 | |
|   }
 | |
|   jclass klass = env->FindClass("art/Test1962");
 | |
|   jmethodID handler =
 | |
|       env->GetStaticMethodID(klass, "HandleEvent", "(Ljava/lang/Thread;Ljava/util/List;)V");
 | |
|   CHECK(data != nullptr);
 | |
|   env->CallStaticVoidMethod(klass, handler, thread, data->events);
 | |
| }
 | |
| 
 | |
| extern "C" JNIEXPORT void JNICALL Java_art_Test1962_setupTest(JNIEnv* env,
 | |
|                                                               jclass klass ATTRIBUTE_UNUSED) {
 | |
|   jvmtiCapabilities caps{
 | |
|     .can_generate_method_exit_events = 1,
 | |
|   };
 | |
|   if (JvmtiErrorToException(env, jvmti_env, jvmti_env->AddCapabilities(&caps))) {
 | |
|     return;
 | |
|   }
 | |
|   jvmtiEventCallbacks cb{
 | |
|     .MethodExit = cbMethodEntry,
 | |
|   };
 | |
|   JvmtiErrorToException(env, jvmti_env, jvmti_env->SetEventCallbacks(&cb, sizeof(cb)));
 | |
| }
 | |
| 
 | |
| extern "C" JNIEXPORT void JNICALL Java_art_Test1962_setupThread(
 | |
|     JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jthread thr, jobject events, jobject target) {
 | |
|   BreakpointData* data = nullptr;
 | |
|   if (JvmtiErrorToException(
 | |
|           env, jvmti_env, jvmti_env->Allocate(sizeof(*data), reinterpret_cast<uint8_t**>(&data)))) {
 | |
|     return;
 | |
|   }
 | |
|   data->events = env->NewGlobalRef(events);
 | |
|   data->target = env->FromReflectedMethod(target);
 | |
|   if (JvmtiErrorToException(env, jvmti_env, jvmti_env->SetThreadLocalStorage(thr, data))) {
 | |
|     return;
 | |
|   }
 | |
|   JvmtiErrorToException(
 | |
|       env,
 | |
|       jvmti_env,
 | |
|       jvmti_env->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_METHOD_EXIT, thr));
 | |
| }
 | |
| 
 | |
| }  // namespace Test1962MultiThreadEvents
 | |
| }  // namespace art
 |