blob: e284b5284662bddda56e0cc1007879a31bd61b2b [file] [log] [blame]
/*
* Copyright (C) 2017 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 "common_helper.h"
#include "jni.h"
#include "jvmti.h"
#include "jvmti_helper.h"
#include "scoped_local_ref.h"
#include "test_env.h"
namespace art {
namespace common_locals {
static void DeallocateContents(jvmtiLocalVariableEntry* vars, jint nvars) {
for (jint i = 0; i < nvars; i++) {
jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(vars[i].name));
jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(vars[i].signature));
jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(vars[i].generic_signature));
}
}
extern "C" JNIEXPORT void Java_art_Locals_EnableLocalVariableAccess(JNIEnv* env, jclass) {
jvmtiCapabilities caps;
if (JvmtiErrorToException(env, jvmti_env, jvmti_env->GetCapabilities(&caps))) {
return;
}
caps.can_access_local_variables = 1;
JvmtiErrorToException(env, jvmti_env, jvmti_env->AddCapabilities(&caps));
}
extern "C" JNIEXPORT void Java_art_Locals_SetLocalVariableObject(JNIEnv* env,
jclass,
jthread t,
jint depth,
jint slot,
jobject val) {
JvmtiErrorToException(env, jvmti_env, jvmti_env->SetLocalObject(t, depth, slot, val));
}
extern "C" JNIEXPORT void Java_art_Locals_SetLocalVariableDouble(JNIEnv* env,
jclass,
jthread t,
jint depth,
jint slot,
jdouble val) {
JvmtiErrorToException(env, jvmti_env, jvmti_env->SetLocalDouble(t, depth, slot, val));
}
extern "C" JNIEXPORT void Java_art_Locals_SetLocalVariableFloat(JNIEnv* env,
jclass,
jthread t,
jint depth,
jint slot,
jfloat val) {
JvmtiErrorToException(env, jvmti_env, jvmti_env->SetLocalFloat(t, depth, slot, val));
}
extern "C" JNIEXPORT void Java_art_Locals_SetLocalVariableLong(JNIEnv* env,
jclass,
jthread t,
jint depth,
jint slot,
jlong val) {
JvmtiErrorToException(env, jvmti_env, jvmti_env->SetLocalLong(t, depth, slot, val));
}
extern "C" JNIEXPORT void Java_art_Locals_SetLocalVariableInt(JNIEnv* env,
jclass,
jthread t,
jint depth,
jint slot,
jint val) {
JvmtiErrorToException(env, jvmti_env, jvmti_env->SetLocalInt(t, depth, slot, val));
}
extern "C" JNIEXPORT jdouble Java_art_Locals_GetLocalVariableDouble(JNIEnv* env,
jclass,
jthread t,
jint depth,
jint slot) {
jdouble ret = 0;
JvmtiErrorToException(env, jvmti_env, jvmti_env->GetLocalDouble(t, depth, slot, &ret));
return ret;
}
extern "C" JNIEXPORT jfloat Java_art_Locals_GetLocalVariableFloat(JNIEnv* env,
jclass,
jthread t,
jint depth,
jint slot) {
jfloat ret = 0;
JvmtiErrorToException(env, jvmti_env, jvmti_env->GetLocalFloat(t, depth, slot, &ret));
return ret;
}
extern "C" JNIEXPORT jlong Java_art_Locals_GetLocalVariableLong(JNIEnv* env,
jclass,
jthread t,
jint depth,
jint slot) {
jlong ret = 0;
JvmtiErrorToException(env, jvmti_env, jvmti_env->GetLocalLong(t, depth, slot, &ret));
return ret;
}
extern "C" JNIEXPORT jint Java_art_Locals_GetLocalVariableInt(JNIEnv* env,
jclass,
jthread t,
jint depth,
jint slot) {
jint ret = 0;
JvmtiErrorToException(env, jvmti_env, jvmti_env->GetLocalInt(t, depth, slot, &ret));
return ret;
}
extern "C" JNIEXPORT jobject Java_art_Locals_GetLocalInstance(JNIEnv* env,
jclass,
jthread t,
jint depth) {
jobject ret = nullptr;
JvmtiErrorToException(env, jvmti_env, jvmti_env->GetLocalInstance(t, depth, &ret));
return ret;
}
extern "C" JNIEXPORT jobject Java_art_Locals_GetLocalVariableObject(JNIEnv* env,
jclass,
jthread t,
jint depth,
jint slot) {
jobject ret = nullptr;
JvmtiErrorToException(env, jvmti_env, jvmti_env->GetLocalObject(t, depth, slot, &ret));
return ret;
}
extern "C" JNIEXPORT jobjectArray Java_art_Locals_GetLocalVariableTable(JNIEnv* env,
jclass,
jobject m) {
jmethodID method = env->FromReflectedMethod(m);
if (env->ExceptionCheck()) {
return nullptr;
}
ScopedLocalRef<jclass> klass(env, env->FindClass("art/Locals$VariableDescription"));
if (env->ExceptionCheck()) {
return nullptr;
}
jint nvars;
jvmtiLocalVariableEntry* vars = nullptr;
if (JvmtiErrorToException(env, jvmti_env,
jvmti_env->GetLocalVariableTable(method, &nvars, &vars))) {
return nullptr;
}
jobjectArray vars_array = env->NewObjectArray(nvars, klass.get(), nullptr);
if (env->ExceptionCheck()) {
DeallocateContents(vars, nvars);
jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(vars));
return nullptr;
}
jmethodID constructor = env->GetMethodID(
klass.get(), "<init>", "(JILjava/lang/String;Ljava/lang/String;Ljava/lang/String;I)V");
if (env->ExceptionCheck()) {
return nullptr;
}
for (jint i = 0; i < nvars; i++) {
ScopedLocalRef<jstring> name_string(env, env->NewStringUTF(vars[i].name));
ScopedLocalRef<jstring> sig_string(env, env->NewStringUTF(vars[i].signature));
ScopedLocalRef<jstring> generic_sig_string(env, env->NewStringUTF(vars[i].generic_signature));
jobject var_obj = env->NewObject(klass.get(),
constructor,
vars[i].start_location,
vars[i].length,
name_string.get(),
sig_string.get(),
generic_sig_string.get(),
vars[i].slot);
if (env->ExceptionCheck()) {
DeallocateContents(vars, nvars);
jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(vars));
return nullptr;
}
env->SetObjectArrayElement(vars_array, i, var_obj);
if (env->ExceptionCheck()) {
DeallocateContents(vars, nvars);
jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(vars));
return nullptr;
}
}
DeallocateContents(vars, nvars);
jvmti_env->Deallocate(reinterpret_cast<unsigned char*>(vars));
return vars_array;
}
} // namespace common_locals
} // namespace art