From: <jen...@de...> - 2007-09-27 15:32:16
|
This patch add the JVMTI agent implementation. Together with libopagent this is used to instrument the Java VMs. --- ChangeLog | 10 ++ Makefile.am | 3 agents/Makefile.am | 7 + agents/jvmti/Makefile.am | 14 +++ agents/jvmti/libjvmti_oprofile.c | 182 +++++++++++++++++++++++++++++++++++++++ configure.in | 18 +++ 6 files changed, 232 insertions(+), 2 deletions(-) Index: oprofile-CVS-jit/configure.in =================================================================== --- oprofile-CVS-jit.orig/configure.in +++ oprofile-CVS-jit/configure.in @@ -68,6 +68,20 @@ [ --with-module-dir=dir Path to module installation directory], MODINSTALLDIR=$withval) AC_SUBST(MODINSTALLDIR) +AC_ARG_WITH(java, +[ --with-java=java-home Path to Java home directory], JAVA_HOMEDIR=$withval) +AC_SUBST(JAVA_HOMEDIR) + +if test -n "$JAVA_HOMEDIR"; then + AC_CHECK_FILE("$JAVA_HOMEDIR/include/jvmti.h",JVMTI_H_EXISTS="yes",) + if test -z "$JVMTI_H_EXISTS"; then + AC_CHECK_FILE("$JAVA_HOMEDIR/include/jvmpi.h",JVMPI_H_EXISTS="yes",) + fi +fi + +AM_CONDITIONAL(BUILD_JVMTI_AGENT, test -n "$JVMTI_H_EXISTS") +AM_CONDITIONAL(BUILD_JVMPI_AGENT, test -n "$JVMPI_H_EXISTS") + AX_MALLOC_ATTRIBUTE AX_BUILTIN_EXPECT @@ -242,7 +256,9 @@ gui/ui/Makefile \ module/Makefile \ module/x86/Makefile \ - module/ia64/Makefile) + module/ia64/Makefile \ + agents/Makefile \ + agents/jvmti/Makefile) AX_COPY_IF_CHANGE(doc/xsl/catalog-1.xml, doc/xsl/catalog.xml) Index: oprofile-CVS-jit/agents/Makefile.am =================================================================== --- /dev/null +++ oprofile-CVS-jit/agents/Makefile.am @@ -0,0 +1,7 @@ + +SUBDIRS = + +if BUILD_JVMTI_AGENT +SUBDIRS += jvmti +endif + Index: oprofile-CVS-jit/agents/jvmti/Makefile.am =================================================================== --- /dev/null +++ oprofile-CVS-jit/agents/jvmti/Makefile.am @@ -0,0 +1,14 @@ +targetlib = libjvmti_oprofile.so + +pkglib_PROGRAMS = $(targetlib) + +libjvmti_oprofile_so_CFLAGS = -fPIC + +libjvmti_oprofile_so_LDFLAGS = -shared -L../../libopagent -l opagent -o $(targetlib) -Wl,-soname=$(targetlib) + +libjvmti_oprofile_so_SOURCES = libjvmti_oprofile.c + +AM_CPPFLAGS = \ + -I ${top_srcdir}/libopagent \ + -I @JAVA_HOMEDIR@/include \ + -I @JAVA_HOMEDIR@/include/linux Index: oprofile-CVS-jit/Makefile.am =================================================================== --- oprofile-CVS-jit.orig/Makefile.am +++ oprofile-CVS-jit/Makefile.am @@ -16,7 +16,8 @@ pp \ events \ doc \ - gui + gui \ + agents ACLOCAL_AMFLAGS = -I m4 Index: oprofile-CVS-jit/agents/jvmti/libjvmti_oprofile.c =================================================================== --- /dev/null +++ oprofile-CVS-jit/agents/jvmti/libjvmti_oprofile.c @@ -0,0 +1,182 @@ +/** + * @file jvmti_oprofile.c + * JVMTI agent implementation to report jitted JVM code to Oprofile + * + * @remark Copyright 2007 OProfile authors + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * @author Jens Wilke + * + * Copyright IBM Corporation 2007 + * + */ + +#include <stdio.h> +#include <jvmti.h> +#include <string.h> +#include <libopagent.h> +#include <stdint.h> + +static int debug = 0; + +void JNICALL cb_compiled_method_load( + jvmtiEnv * jvmti, + jmethodID method, + jint code_size, + const void * code_addr, + jint map_length, + const jvmtiAddrLocationMap * map, + const void * compile_info) +{ + /* Get the declaring class of the method */ + jclass declaring_class; + char * class_signature = NULL; + char * method_name = NULL; + char * method_signature = NULL; + jvmtiError err; + + err = (*jvmti)->GetMethodDeclaringClass(jvmti, method, &declaring_class); + if (err != JVMTI_ERROR_NONE) { + fprintf(stderr, "Error, GetMethodDeclaringClass, rc=%i\n", err); + goto cleanup; + } + err = (*jvmti)->GetClassSignature(jvmti, declaring_class, &class_signature, NULL); + if (err != JVMTI_ERROR_NONE) { + fprintf(stderr, "Error, GetClassSignature, rc=%i\n", err); + goto cleanup; + } + err = (*jvmti)->GetMethodName(jvmti, method, &method_name, &method_signature, NULL); + if (err != JVMTI_ERROR_NONE) { + fprintf(stderr, "Error, GeMethodName, rc=%i\n", err); + goto cleanup; + } + + if (debug) { + fprintf(stderr, "load: class=%s, method=%s, signature=%s, addr=%x, size=%i \n", + class_signature, method_name, method_signature, code_addr, code_size); + } + // produce a symbol name out of class name and method name + { + int cnt = strlen(method_name) + strlen(class_signature) + 2; + char buf[cnt]; + int len = 0; + buf[0] = 0; + if (*class_signature) { + strncat(buf, class_signature + 1, cnt - 1); + len = strlen(buf); + /* cut away the ; */ + if (len>0) + buf[len-1] = '/'; + } + strncat(buf, method_name, cnt-len - 1); + op_write_native_code(buf, code_addr, code_size); + } + + cleanup: + if (class_signature!=NULL) { (*jvmti)->Deallocate(jvmti, class_signature); } + if (method_name!=NULL) { (*jvmti)->Deallocate(jvmti, method_name); } + if (method_signature!=NULL) { (*jvmti)->Deallocate(jvmti, method_signature); } +} + +void JNICALL cb_compiled_method_unload( + jvmtiEnv * jvmti_env, + jmethodID method, + const void * code_addr) +{ + if (debug) { + fprintf(stderr, "unload: addr=%llx \n", + (unsigned long long) (uintptr_t) code_addr); + } + op_unload_native_code(code_addr); +} + +void JNICALL cb_dynamic_code_generated( + jvmtiEnv * jvmti_env, + const char * name, + const void * code_addr, + jint code_size) +{ + if (debug) { + fprintf(stderr, "dyncode: name=%s, addr=%llx, size=%i \n", + name, + (unsigned long long) (uintptr_t) code_addr, + code_size); + } + op_write_native_code(name, code_addr, code_size); +} + +JNIEXPORT jint JNICALL Agent_OnLoad( + JavaVM * jvm, + char * options, + void * reserved) +{ + jint rc; + jvmtiEnv *jvmti = NULL; + jvmtiEventCallbacks callbacks; + jvmtiCapabilities caps; + jvmtiError error; + int err; + + fprintf(stderr, "jvmti_oprofile: agent activated\n"); + if (options && strcmp("debug", options)==0) { + debug = 1; + } + err = op_open_agent(); + if (err) { + fprintf(stderr, "ERROR: op_open_agent, rc=%i\n", err); + return -1; + } + + /* Get the jvmti environment */ + rc = (*jvm)->GetEnv(jvm, (void **) &jvmti, JVMTI_VERSION_1); + if (rc != JNI_OK) { + fprintf(stderr, "ERROR: Unable to access JVMTI Version 1, rc=%i\n", rc); + return -1; + } + rc = (*jvmti)->GetCapabilities(jvmti, &caps); + if (rc != JNI_OK) { + fprintf(stderr, "ERROR: GetCapabilities, rc=%i\n", rc); + return -1; + } + caps.can_generate_compiled_method_load_events = 1; + rc = (*jvmti)->AddCapabilities(jvmti, &caps); + if (rc != JNI_OK) { + fprintf(stderr, "ERROR: AddCapabilities, rc=%i\n", rc); + return -1; + } + memset(&callbacks, 0, sizeof(callbacks)); + callbacks.CompiledMethodLoad = cb_compiled_method_load; + callbacks.CompiledMethodUnload = cb_compiled_method_unload; + callbacks.DynamicCodeGenerated = cb_dynamic_code_generated; + rc = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, sizeof(callbacks)); + if (rc != JNI_OK) { + fprintf(stderr, "ERROR: SetEventCallbacks, rc=%i\n", rc); + return -1; + } + + rc = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, + JVMTI_EVENT_COMPILED_METHOD_LOAD, (jthread)NULL); + rc = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, + JVMTI_EVENT_COMPILED_METHOD_UNLOAD, (jthread)NULL); + rc = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, + JVMTI_EVENT_DYNAMIC_CODE_GENERATED, (jthread)NULL); + return 0; +} + +JNIEXPORT void JNICALL Agent_OnUnload(JavaVM * jvm) +{ + op_close_agent(); +} Index: oprofile-CVS-jit/ChangeLog =================================================================== --- oprofile-CVS-jit.orig/ChangeLog +++ oprofile-CVS-jit/ChangeLog @@ -1,5 +1,15 @@ 2007-09-27 Jens Wilke <jen...@de...> + * configure.in: + * agents/Makefile.am: + * agents/jvmti/Makefile.am: + * Makefile.am: + * agents/jvmti/libjvmti_oprofile.c: Patch 4 of 6 for JIT code + support. This patch add the JVMTI agent implementation. Together + with libopagent this is used to instrument the Java VMs. + +2007-09-27 Jens Wilke <jen...@de...> + * utils/opcontrol: Patch 3 of 6 for JIT code support. This patch adds the "glue" code to opcontrol that generates the ELF files and cleans up the jitdump directory. -- Jens Wilke Linux on System z - Application Development Tools phone +49-(0)7031-16-3936 - tl *120-3936 - email jen...@de... IBM Germany Lab, Schoenaicher Str. 220, 71032 Boeblingen |