Class Load and Prepare event.
* src/native/jni.c (RegisterNatives): Add comment for calling jvmti
Native Method Bind event.
* src/native/vm/VMClassLoader.c (defineClass): Add call to jvmti
Class File Load Hook event.
* src/native/vm/VMObject.c (wait): Add call to jvmti Monitor Wait
and Waited event.
* src/native/native.c (native_resolve_function): Add call to jvmti
Native Method Bind event.
* src/native/jvmti/cacaodbg.c (jvmti_ClassFileLoadHook): new function
to supprt event.
(jvmti_ClassLoadPrepare): idem
(jvmti_MonitorContendedEntering): idem
(jvmti_MonitorWaiting): idem
(jvmti_ThreadStartEnd): idem
(jvmti_NativeMethodBind): idem
* src/native/jvmti/cacaodbg.h: Add function headers for
jvmti_ClassFileLoadHook, jvmti_ClassLoadPrepare,
jvmti_MonitorContendedEntering, jvmti_MonitorWaiting,
jvmti_ThreadStartEnd, jvmti_NativeMethodBind.
* src/native/jvmti/jvmti.c (execute_callback): Add support for Class
File Load Hook event.
(GetOwnedMonitorInfo): Adapt lock record iteration to new
data structure.
(GetCurrentContendedMonitor): idem
* src/threads/native/lock.c (lock_monitor_enter): Add call to jvmti
Monitor Contended Enter and Entered event
* src/threads/native/threads.c (threads_startup_thread): replace
breakpoint by direct call to jvmti Thread Start/End event
* src/cacaoh/headers.c add dummy functions jvmti_ThreadStartEnd,
jvmti_ClassLoadPrepare and jvmti_MonitorContendedEntering
Christian Thalinger
Edwin Steiner
- $Id: headers.c 5019 2006-06-06 21:13:41Z motse $
+ $Id: headers.c 5031 2006-06-14 18:36:22Z motse $
*/
/* jvmti releated functions ************************************************/
#if defined(ENABLE_JVMTI)
-void jvmti_fireEvent(void* d) {;}
+void jvmti_ThreadStartEnd(int ev) {;}
+void jvmti_ClassLoadPrepare(bool prepared, classinfo *c) {;}
+void jvmti_MonitorContendedEntering(bool entered, jobject obj) {;}
#endif
Christian Thalinger
Edwin Steiner
- $Id: jni.c 4969 2006-05-29 09:41:02Z motse $
+ $Id: jni.c 5031 2006-06-14 18:36:22Z motse $
*/
STATISTICS(jniinvokation());
log_text("JNI-Call: RegisterNatives: IMPLEMENT ME!!!");
+ /* XXX: if implemented this needs a call to jvmti_NativeMethodBind
+ if (jvmti) jvmti_NativeMethodBind(method, address, new_address_ptr);
+ */
return 0;
}
}
+/* jvmti_ClassFileLoadHook ****************************************************
+
+ prepares firing a new Class File Load Hook event
+
+*******************************************************************************/
+
+void jvmti_ClassFileLoadHook(utf* name, int class_data_len,
+ unsigned char* class_data,
+ java_objectheader* loader,
+ java_objectheader* protection_domain,
+ jint* new_class_data_len,
+ unsigned char** new_class_data) {
+ genericEventData d;
+
+ d.ev = JVMTI_EVENT_CLASS_FILE_LOAD_HOOK;
+ d.klass = NULL; /* class is not redefined */
+ d.object = loader;
+ d.name = (char*)MNEW(char,(utf_bytes(name)+1));
+ utf_sprint_convert_to_latin1(d.name, name);
+ d.protection_domain = protection_domain;
+ d.class_data = class_data;
+ d.jint1 = class_data_len;
+ d.new_class_data_len = new_class_data_len;
+ d.new_class_data = new_class_data;
+
+ jvmti_fireEvent(&d);
+ MFREE(d.name,char,utf_bytes(name)+1);
+}
+
+
+/* jvmti_ClassFileLoadHook ****************************************************
+
+ prepares firing a new Class Prepare or Load event
+
+*******************************************************************************/
+
+void jvmti_ClassLoadPrepare(bool prepared, classinfo *c) {
+ genericEventData d;
+
+ if (prepared)
+ d.ev = JVMTI_EVENT_CLASS_PREPARE;
+ else
+ d.ev = JVMTI_EVENT_CLASS_LOAD;
+
+ d.klass = c;
+ jvmti_fireEvent(&d);
+}
+
+
+/* jvmti_MonitorContendedEntering *********************************************
+
+ prepares firing a new Monitor Contended Enter or Entered event
+
+*******************************************************************************/
+
+void jvmti_MonitorContendedEntering(bool entered, jobject obj) {
+ genericEventData d;
+
+ if (entered)
+ d.ev = JVMTI_EVENT_MONITOR_CONTENDED_ENTERED;
+ else
+ d.ev = JVMTI_EVENT_MONITOR_CONTENDED_ENTER;
+
+ d.object = obj;
+
+ jvmti_fireEvent(&d);
+}
+
+/* jvmti_MonitorWaiting ******************************************************
+
+ prepares firing a new Monitor Wait or Waited event
+
+*******************************************************************************/
+
+void jvmti_MonitorWaiting(bool wait, jobject obj, jlong timeout) {
+ genericEventData d;
+
+ if (wait) {
+ d.ev = JVMTI_EVENT_MONITOR_WAIT;
+ d.jlong = timeout;
+ } else {
+ d.ev = JVMTI_EVENT_MONITOR_WAITED;
+ d.b = timeout != 0;
+ }
+
+ d.object = obj;
+
+ jvmti_fireEvent(&d);
+}
+
+/* jvmti_ThreadStartEnd ********************************************************
+
+ prepares firing a new Thread Start or End event
+
+*******************************************************************************/
+
+void jvmti_ThreadStartEnd(jvmtiEvent ev) {
+ genericEventData d;
+
+ d.ev = ev;
+ jvmti_fireEvent(&d);
+}
+
+/* jvmti_NativeMethodBind *****************************************************
+
+ prepares firing a new Native Method Bind event
+
+*******************************************************************************/
+
+void jvmti_NativeMethodBind(jmethodID method, void* address,
+ void** new_address_ptr) {
+ genericEventData d;
+
+ d.ev = JVMTI_EVENT_NATIVE_METHOD_BIND;
+ d.method = method;
+ d.address = address;
+ d.new_address_ptr = new_address_ptr;
+
+ jvmti_fireEvent(&d);
+}
+
+
+
/*
* These are local overrides for various environment variables in Emacs.
* Please do not remove this and leave it at the end of the file, where
jthread jvmti_get_current_thread();
void jvmti_cacao_debug_init();
void jvmti_cacaodbgserver_quit();
+
+void jvmti_ClassLoadPrepare(bool prepared, classinfo *c);
+void jvmti_ClassFileLoadHook(utf* name, int class_data_len,
+ unsigned char* class_data,
+ java_objectheader* loader,
+ java_objectheader* protection_domain,
+ jint* new_class_data_len,
+ unsigned char** new_class_data);
+void jvmti_MonitorContendedEntering(bool entered, jobject obj);
+void jvmti_MonitorWaiting(bool wait, jobject obj, jlong timeout);
+void jvmti_ThreadStartEnd(jvmtiEvent ev);
+void jvmti_NativeMethodBind(jmethodID method, void* address,
+ void** new_address_ptr);
#endif
/*
+
/* src/native/jvmti/cacaodbgserver.c - contains the cacaodbgserver process. This
process controls the cacao vm through gdb
Changes: Edwin Steiner
Samuel Vinson
- $Id$
+ $Id: cacaodbgserver.c $
*/
Samuel Vinson
- $Id: jvmti.c 5019 2006-06-06 21:13:41Z motse $
+ $Id: jvmti.c 5031 2006-06-14 18:36:22Z motse $
*/
return JVMTI_ERROR_NONE;
}
-/* execcallback ***************************************************************
+/* execute_callback ************************************************************
executes the registerd callbacks for the given jvmti event with parameter
in the data structure.
data->class_data,
data->new_class_data_len,
data->new_class_data);
+
+ /* if class data has been modified use it as class data for other agents
+ waiting for the same event */
+ if (data->new_class_data != NULL) {
+ data->jint1 = *(data->new_class_data_len);
+ data->class_data = *(data->new_class_data);
+ }
break;
/* GetOwnedMonitorInfo *********************************************************
- Get information about the monitors owned by the specified thread
+ Gets all monitors owned by the specified thread
*******************************************************************************/
lock_record_pool_t* lrp;
threadobject* t;
- log_text("GetOwnedMonitorInfo called");
-
CHECK_PHASE_START
CHECK_PHASE(JVMTI_PHASE_LIVE)
CHECK_PHASE_END;
pthread_mutex_lock(&lock_global_pool_lock);
lrp=lock_global_pool;
+ /* iterate over all lock record pools */
while (lrp != NULL) {
+ /* iterate over every lock record in a pool */
for (j=0; j<lrp->header.size; j++) {
-/* if((lrp->lr[j].owner==t)&&
- (!lrp->lr[j].waiting)) {
- if (i>=size) {
- MREALLOC(om,java_objectheader*,size,size*2);
- size=size*2;
+ /* if the lock record is owned by the given thread add it to
+ the result array */
+ if(lrp->lr[j].owner == t) {
+ if (i >= size) {
+ MREALLOC(om, java_objectheader*, size, size * 2);
+ size = size * 2;
}
- om[i]=lrp->lr[j].o;
+ om[i] = lrp->lr[j].obj;
i++;
- }*/
+ }
}
lrp=lrp->header.next;
}
pthread_mutex_unlock(&lock_global_pool_lock);
- *owned_monitors_ptr = heap_allocate(sizeof(java_objectheader*)*i,true,NULL);
- memcpy(*owned_monitors_ptr,om,i*sizeof(java_objectheader*));
- MFREE(om,java_objectheader*,size);
+ *owned_monitors_ptr =
+ heap_allocate(sizeof(java_objectheader*) * i, true, NULL);
+ memcpy(*owned_monitors_ptr, om, i * sizeof(java_objectheader*));
+ MFREE(om, java_objectheader*, size);
*owned_monitor_count_ptr = i;
{
int j;
lock_record_pool_t* lrp;
- java_objectheader* monitor;
+ threadobject* t;
+ lock_waiter_t* waiter;
CHECK_PHASE_START
CHECK_PHASE(JVMTI_PHASE_LIVE)
if (monitor_ptr == NULL) return JVMTI_ERROR_NULL_POINTER;
*monitor_ptr=NULL;
- if(!builtin_instanceof(thread,class_java_lang_Thread))
- return JVMTI_ERROR_INVALID_THREAD;
-
- CHECK_THREAD_IS_ALIVE(thread);
-
+ if (thread == NULL) {
+ t = jvmti_get_current_thread();
+ } else {
+ if(!builtin_instanceof(thread,class_java_lang_Thread))
+ return JVMTI_ERROR_INVALID_THREAD;
+
+ CHECK_THREAD_IS_ALIVE(thread);
+ t = (threadobject*) thread;
+ }
#if defined(ENABLE_THREADS)
lrp=lock_global_pool;
- while ((lrp != NULL)&&(monitor == NULL)) {
+ /* iterate over all lock record pools */
+ while ((lrp != NULL) && (*monitor_ptr == NULL)) {
+ /* iterate over every lock record in a pool */
for (j=0; j<lrp->header.size; j++) {
-/* if((lrp->lr[j].owner==(threadobject*)thread)&&(lrp->lr[j].waiting)) {
- monitor=lrp->lr[j].o;
- break;
- }*/
+ /* iterate over every thread that is wait on this lock record */
+ waiter = lrp->lr[j].waiters;
+ while (waiter != NULL)
+ /* if the waiting thread equals to the given thread we are
+ done. Stop iterateting. */
+ if(waiter->waiter == t) {
+ *monitor_ptr=lrp->lr[j].obj;
+ break;
+ }
}
lrp=lrp->header.next;
}
pthread_mutex_unlock(&lock_global_pool_lock);
- if (monitor!=NULL) {
- *monitor_ptr = heap_allocate(sizeof(java_objectheader*),true,NULL);
- *monitor_ptr = (jobject)monitor;
- }
#endif
return JVMTI_ERROR_NONE;
0, /* can_generate_single_step_events */
1, /* can_generate_exception_events */
0, /* can_generate_frame_pop_events */
- 0, /* can_generate_breakpoint_events */
+ 1, /* can_generate_breakpoint_events */
1, /* can_suspend */
0, /* can_redefine_any_class */
0, /* can_get_current_thread_cpu_time */
0, /* can_generate_method_exit_events */
0, /* can_generate_all_class_hook_events */
0, /* can_generate_compiled_method_load_events */
- 0, /* can_generate_monitor_events */
+ 1, /* can_generate_monitor_events */
0, /* can_generate_vm_object_alloc_events */
0, /* can_generate_native_method_bind_events */
0, /* can_generate_garbage_collection_events */
&GetObjectSize
};
+/* jvmti_set_phase ************************************************************
+
+ sets a new jvmti phase a fires an apropriate event.
+
+*******************************************************************************/
void jvmti_set_phase(jvmtiPhase p) {
genericEventData d;
jvmti_fireEvent(&d);
}
+
+/* jvmti_new_environment ******************************************************
+
+ creates a new JVMTI environment
+
+*******************************************************************************/
+
jvmtiEnv* jvmti_new_environment() {
environment* env;
return (jvmtiEnv*)env;
}
+/* jvmti_agentload ************************************************************
+
+ loads the indicated shared library containing the jvmti agent and calls the
+ Agent_OnLoad function.
+
+*******************************************************************************/
+
void jvmti_agentload(char* opt_arg, bool agentbypath, lt_dlhandle *handle, char **libname) {
lt_ptr onload;
char *arg;
if (retval != 0) exit (retval);
}
+/* jvmti_agentunload **********************************************************
+
+ calls the Agent_UnLoad function in the jvmti agent if present.
+
+*******************************************************************************/
+
void jvmti_agentunload() {
if (unload != NULL) {
((JNIEXPORT void JNICALL (*) (JavaVM *vm)) unload)
}
}
+
/*
* These are local overrides for various environment variables in Emacs.
* Please do not remove this and leave it at the end of the file, where
Changes: Christian Thalinger
- $Id: native.c 4921 2006-05-15 14:24:36Z twisti $
+ $Id: native.c 5031 2006-06-14 18:36:22Z motse $
*/
}
+#if defined(ENABLE_JVMTI)
+ /* fire Native Method Bind event */
+ jvmti_NativeMethodBind(m, sym, &sym);
+#endif
+
/* no symbol found? throw exception */
if (sym == NULL) {
Christian Thalinger
Edwin Steiner
- $Id: VMClassLoader.c 4906 2006-05-11 14:02:37Z twisti $
+ $Id: VMClassLoader.c 5031 2006-06-14 18:36:22Z motse $
*/
#include "vm/zip.h"
#include "vm/jit/asmpart.h"
+#if defined(ENABLE_JVMTI)
+#include "native/jvmti/cacaodbg.h"
+#endif
+
/*
* Class: java/lang/VMClassLoader
classinfo *r;
classbuffer *cb;
utf *utfname;
+#if defined(ENABLE_JVMTI)
+ jint new_class_data_len = 0;
+ unsigned char* new_class_data = NULL;
+#endif
/* check if data was passed */
utfname = NULL;
}
+
+#if defined(ENABLE_JVMTI)
+ /* fire Class File Load Hook JVMTI event */
+ if (jvmti) jvmti_ClassFileLoadHook(utfname, len, (unsigned char*)data->data,
+ (java_objectheader *)cl, (java_objectheader *)pd,
+ &new_class_data_len, &new_class_data);
+#endif
+
+
/* create a new classinfo struct */
c = class_create_classinfo(utfname);
cb = NEW(classbuffer);
cb->class = c;
+#if defined(ENABLE_JVMTI)
+ /* check if the JVMTI wants to modify the class */
+ if (new_class_data == NULL) {
+#endif
cb->size = len;
cb->data = (u1 *) &data->data[offset];
+#if defined(ENABLE_JVMTI)
+ } else {
+ cb->size = new_class_data_len;
+ cb->data = (u1 *) new_class_data;
+ }
+#endif
cb->pos = cb->data;
/* preset the defining classloader */
Changes: Joseph Wenninger
Christian Thalinger
- $Id: VMObject.c 4957 2006-05-26 11:48:10Z edwin $
+ $Id: VMObject.c 5031 2006-06-14 18:36:22Z motse $
*/
#include "vm/options.h"
#include "vm/stringlocal.h"
+#if defined(ENABLE_JVMTI)
+#include "native/jvmti/cacaodbg.h"
+#endif
+
/*
* Class: java/lang/VMObject
*/
JNIEXPORT void JNICALL Java_java_lang_VMObject_wait(JNIEnv *env, jclass clazz, java_lang_Object *o, s8 ms, s4 ns)
{
+#if defined(ENABLE_JVMTI)
+ /* Monitor Wait */
+ if (jvmti) jvmti_MonitorWaiting(true, o, ms);
+#endif
+
#if defined(ENABLE_THREADS)
lock_wait_for_object(&o->header, ms, ns);
#endif
+
+#if defined(ENABLE_JVMTI)
+ /* Monitor Waited */
+ /* XXX: How do you know if wait timed out ?*/
+ if (jvmti) jvmti_MonitorWaiting(false, o, 0);
+#endif
}
#include "machine-instr.h"
#endif
+#if defined(ENABLE_JVMTI)
+#include "native/jvmti/cacaodbg.h"
+#endif
+
/******************************************************************************/
/* DEBUGGING MACROS */
lr = lock_hashtable_get_lock_record(t, o);
+#if defined(ENABLE_JVMTI)
+ /* Monitor Contended Enter */
+ jvmti_MonitorContendedEntering(false, o);
+#endif
/* enter the monitor */
lock_record_enter(t, lr);
+
+#if defined(ENABLE_JVMTI)
+ /* Monitor Contended Entered */
+ jvmti_MonitorContendedEntering(true, o);
+#endif
+
/* inflation loop */
while (IS_THIN_LOCK(lockword = (ptrint) o->monitorPtr)) {
Changes: Christian Thalinger
Edwin Steiner
- $Id: threads.c 5019 2006-06-06 21:13:41Z motse $
+ $Id: threads.c 5031 2006-06-14 18:36:22Z motse $
*/
methodinfo *method;
functionptr function;
-#if defined(ENABLE_JVMTI)
- genericEventData d;
-#endif
-
#if defined(ENABLE_INTRP)
u1 *intrp_thread_stack;
#if defined(ENABLE_JVMTI)
- /* breakpoint for thread start event */
- if (jvmti) {
- d.ev = JVMTI_EVENT_THREAD_START;
- jvmti_fireEvent(&d);
- }
+ /* fire thread start event */
+ if (jvmti) jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
#endif
}
#if defined(ENABLE_JVMTI)
- /* breakpoint for thread end event */
- if (jvmti) {
- d.ev = JVMTI_EVENT_THREAD_END;
- jvmti_fireEvent(&d);
- }
+ /* fire thread end event */
+ if (jvmti) jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
#endif
Edwin Steiner
Christian Thalinger
- $Id: loader.c 4921 2006-05-15 14:24:36Z twisti $
+ $Id: loader.c 5031 2006-06-14 18:36:22Z motse $
*/
#include "vm/jit/codegen-common.h"
#include "vm/rt-timing.h"
+#if defined(ENABLE_JVMTI)
+#include "native/jvmti/cacaodbg.h"
+#endif
/******************************************************************************/
/* DEBUG HELPERS */
printf("]\n");
}
+#if defined(ENABLE_JVMTI)
+ /* fire Class Load JVMTI event */
+ if (jvmti) jvmti_ClassLoadPrepare(false, c);
+#endif
+
+
return c;
}
/* revert loading state and class is loaded */
c->state = (c->state & ~CLASS_LOADING) | CLASS_LOADED;
+#if defined(ENABLE_JVMTI)
+ /* fire Class Prepare JVMTI event */
+ if (jvmti) jvmti_ClassLoadPrepare(true, c);
+#endif
+
#if !defined(NDEBUG)
if (loadverbose)