You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by ge...@apache.org on 2006/11/03 18:00:29 UTC
svn commit: r470903 - in /incubator/harmony/enhanced/drlvm/trunk/vm:
gc_cc/src/ include/ include/open/ interpreter/src/ vmcore/include/
vmcore/src/class_support/ vmcore/src/gc/ vmcore/src/init/ vmcore/src/jvmti/
Author: geirm
Date: Fri Nov 3 09:00:27 2006
New Revision: 470903
URL: http://svn.apache.org/viewvc?view=rev&rev=470903
Log:
HARMONY-1635
jvmti heap iteration
Ubunutu 6 - smoke, c-unit, ~kernel)
Modified:
incubator/harmony/enhanced/drlvm/trunk/vm/gc_cc/src/gc_types.h
incubator/harmony/enhanced/drlvm/trunk/vm/gc_cc/src/prepare.cpp
incubator/harmony/enhanced/drlvm/trunk/vm/include/interpreter_exports.h
incubator/harmony/enhanced/drlvm/trunk/vm/include/open/gc.h
incubator/harmony/enhanced/drlvm/trunk/vm/include/open/vm_gc.h
incubator/harmony/enhanced/drlvm/trunk/vm/interpreter/src/interp_defs.h
incubator/harmony/enhanced/drlvm/trunk/vm/interpreter/src/interp_exports.cpp
incubator/harmony/enhanced/drlvm/trunk/vm/interpreter/src/interp_stack_trace.cpp
incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/jvmti_direct.h
incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/jvmti_internal.h
incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/object_layout.h
incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/root_set_enum_internal.h
incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/thread_manager.h
incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/version_svn_tag.h
incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Prepare.cpp
incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/gc/dll_gc.cpp
incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/gc/root_set_enum_common.cpp
incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/gc/stop_the_world_root_set_enum.cpp
incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm.cpp
incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_init.cpp
incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti.cpp
incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_capability.cpp
incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_event.cpp
incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_heap.cpp
Modified: incubator/harmony/enhanced/drlvm/trunk/vm/gc_cc/src/gc_types.h
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/gc_cc/src/gc_types.h?view=diff&rev=470903&r1=470902&r2=470903
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/gc_cc/src/gc_types.h (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/gc_cc/src/gc_types.h Fri Nov 3 09:00:27 2006
@@ -34,6 +34,7 @@
#include <apr_atomic.h>
#include <cxxlog.h>
#include "slot.h"
+#include "object_layout.h"
static char* gc_version_string() {
#if (defined _DEBUG) || ! (defined NDEBUG)
@@ -179,7 +180,7 @@
#endif
}
- int array_length() { return array_len; }
+ int array_length() { return ((VM_Vector*)this)->get_length(); }
Partial_Reveal_Object **get_array_elements(GC_VTable_Info *gcvt) {
assert(gcvt->is_array());
Modified: incubator/harmony/enhanced/drlvm/trunk/vm/gc_cc/src/prepare.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/gc_cc/src/prepare.cpp?view=diff&rev=470903&r1=470902&r2=470903
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/gc_cc/src/prepare.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/gc_cc/src/prepare.cpp Fri Nov 3 09:00:27 2006
@@ -113,7 +113,7 @@
void gc_class_prepared(Class_Handle ch, VTable_Handle vth) {
- TRACE2("gc.init", "gc_class_prepared");
+ TRACE2("gc.init", "gc_class_prepared " << class_get_name(ch));
assert(ch);
assert(vth);
Partial_Reveal_VTable *vt = (Partial_Reveal_VTable *)vth;
@@ -124,12 +124,10 @@
int el_offset;
for(el_offset = -1; el_size; el_size >>= 1, el_offset++);
- // FIXME: use data from VM
-#ifdef _EM64T_
- int first_element = 16;
-#else
- int first_element = (el_offset == 3) ? 16 : 12;
-#endif
+ int first_element = vector_first_element_offset_unboxed(
+ class_get_array_element_class(ch));
+
+ TRACE2("gc.init.size", "first array element offset " << first_element);
POINTER_SIZE_INT flags = GC_VT_ARRAY
| (el_offset << GC_VT_ARRAY_ELEMENT_SHIFT)
Modified: incubator/harmony/enhanced/drlvm/trunk/vm/include/interpreter_exports.h
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/include/interpreter_exports.h?view=diff&rev=470903&r1=470902&r2=470903
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/include/interpreter_exports.h (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/include/interpreter_exports.h Fri Nov 3 09:00:27 2006
@@ -36,6 +36,8 @@
// 'end' is not inclusive
bool (*is_frame_in_native_frame) (struct FrameHandle* frame, void* begin, void* end);
+ void (*interpreter_ti_enumerate_thread) (jvmtiEnv*, class VM_thread *thread);
+
#ifdef _IPF_
uint64* (*interpreter_get_stacked_register_address) (uint64* bsp, unsigned reg);
#endif
Modified: incubator/harmony/enhanced/drlvm/trunk/vm/include/open/gc.h
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/include/open/gc.h?view=diff&rev=470903&r1=470902&r2=470903
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/include/open/gc.h (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/include/open/gc.h Fri Nov 3 09:00:27 2006
@@ -587,7 +587,7 @@
extern int32 (*gc_get_hashcode)(Managed_Object_Handle);
extern int32 (*gc_get_hashcode0) (Managed_Object_Handle p_object);
extern Managed_Object_Handle (*gc_get_next_live_object)(void *iterator);
-
+extern void (*gc_iterate_heap)();
extern void (*gc_finalize_on_exit)();
@@ -756,6 +756,17 @@
* Should be use only in classloader for class unloading purposes.
*/
GCExport Managed_Object_Handle gc_get_next_live_object(void *iterator);
+
+/**
+ * Iterates all objects in the heap.
+ * This function calls vm_iterate_object() for each
+ * iterated object.
+ * Used for JVMTI Heap Iteration.
+ * Should be called only in stop-the-world setting
+ *
+ * @see vm_gc.h#vm_iterate_object()
+ */
+GCExport void gc_iterate_heap();
/**
* Moves all finalizable objects to vm finalization queue
Modified: incubator/harmony/enhanced/drlvm/trunk/vm/include/open/vm_gc.h
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/include/open/vm_gc.h?view=diff&rev=470903&r1=470902&r2=470903
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/include/open/vm_gc.h (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/include/open/vm_gc.h Fri Nov 3 09:00:27 2006
@@ -97,6 +97,16 @@
VMEXPORT void vm_classloader_iterate_objects(void *iterator);
/**
+ * GC calls this function during heap iteration to iterate
+ * one object. The GC aborts heap iteration if this function
+ * returns false.
+ *
+ * @return true to continue heap iteration, false to abort
+ * @see gc.h#gc_iterate_heap()
+ */
+VMEXPORT bool vm_iterate_object(Managed_Object_Handle object);
+
+/**
* GC calls this function to hint VM that finalizers may need to be run
* and references enqueued. This method is guaranteed not to hold global
* GC lock.
Modified: incubator/harmony/enhanced/drlvm/trunk/vm/interpreter/src/interp_defs.h
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/interpreter/src/interp_defs.h?view=diff&rev=470903&r1=470902&r2=470903
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/interpreter/src/interp_defs.h (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/interpreter/src/interp_defs.h Fri Nov 3 09:00:27 2006
@@ -28,6 +28,7 @@
#include "open/bytecodes.h"
#include "open/vm_util.h"
#include "ini.h"
+#include "jvmti_types.h"
//#define INTERPRETER_DEEP_DEBUG
#define DEBUG_PRINT(a) TRACE2("interpreter", a)
@@ -181,6 +182,7 @@
static inline int getStorageSize(int size);
inline int getIndex() { return index + 1; }
friend void interp_enumerate_root_set_single_thread_on_stack(VM_thread*);
+ friend void interp_ti_enumerate_root_set_single_thread_on_stack(jvmtiEnv* ti_env, VM_thread *thread);
};
class Locals {
@@ -203,6 +205,7 @@
inline uint32 getLocalsNumber() { return varNum; }
friend void interp_enumerate_root_set_single_thread_on_stack(VM_thread*);
+ friend void interp_ti_enumerate_root_set_single_thread_on_stack(jvmtiEnv* ti_env, VM_thread *thread);
};
struct FramePopListener {
Modified: incubator/harmony/enhanced/drlvm/trunk/vm/interpreter/src/interp_exports.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/interpreter/src/interp_exports.cpp?view=diff&rev=470903&r1=470902&r2=470903
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/interpreter/src/interp_exports.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/interpreter/src/interp_exports.cpp Fri Nov 3 09:00:27 2006
@@ -80,6 +80,9 @@
extern unsigned int interpreter_st_get_interrupted_method_native_bit(class VM_thread *);
extern void interpreter_enumerate_thread(class VM_thread *);
+extern void interpreter_ti_enumerate_thread(jvmtiEnv*, class VM_thread*);
+extern void interpreter_st_get_interrupted_method(struct Method * *,int64 *);
+extern void interpreter_st_get_catch_method(struct Method * *,int64 *,struct _jobject *);
extern void interpreter_st_get_trace(VM_thread *thread, unsigned int *,struct StackTraceFrame * *);
uint64* interpreter_get_stacked_register_address(uint64* bsp, unsigned reg);
extern void interpreter_execute_method(Method *method, jvalue *return_value, jvalue *args);
@@ -104,6 +107,7 @@
interpreter->interpreter_get_last_frame = &interpreter_get_last_frame;
interpreter->interpreter_get_prev_frame = &interpreter_get_prev_frame;
interpreter->is_frame_in_native_frame = &is_frame_in_native_frame;
+ interpreter->interpreter_ti_enumerate_thread = &interpreter_ti_enumerate_thread;
#ifdef _IPF_
interpreter->interpreter_get_stacked_register_address = &interpreter_get_stacked_register_address;
#endif
Modified: incubator/harmony/enhanced/drlvm/trunk/vm/interpreter/src/interp_stack_trace.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/interpreter/src/interp_stack_trace.cpp?view=diff&rev=470903&r1=470902&r2=470903
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/interpreter/src/interp_stack_trace.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/interpreter/src/interp_stack_trace.cpp Fri Nov 3 09:00:27 2006
@@ -24,6 +24,7 @@
#include "interp_defs.h"
#include "stack_trace.h"
#include "exceptions.h"
+#include "jvmti_support.h"
// ppervov: HACK: allows using STL modifiers (dec/hex) and special constants (endl)
using namespace std;
@@ -249,3 +250,110 @@
// Enumerate references associated with a thread that are not stored on the thread's stack.
vm_enumerate_root_set_single_thread_not_on_stack(thread);
} //vm_enumerate_thread
+
+void
+interp_ti_enumerate_root_set_single_thread_on_stack(jvmtiEnv* ti_env, VM_thread *thread) {
+ TRACE2("enumeration", "interp_enumerate_root_set_single_thread_on_stack()");
+ StackIterator_interp* si;
+ si = interp_si_create_from_native(thread);
+
+ int i;
+ int depth;
+ DEBUG_GC("\n\nGC enumeration in interpreter stack:\n");
+ for (depth = 0; !interp_si_is_past_end(si); depth++) {
+ Method* method = (Method*)interp_si_get_method(si);
+ jmethodID method_id = (jmethodID)method;
+ int slot = 0;
+
+ if (si->This) {
+ vm_ti_enumerate_stack_root(ti_env,
+ (void**)&si->This, si->This,
+ JVMTI_HEAP_ROOT_STACK_LOCAL,
+ depth, method_id, slot++);
+ DEBUG_GC(" [THIS]: " << si->This->vt()->clss->name->bytes << endl);
+ }
+
+ if (si->exc) {
+ vm_ti_enumerate_stack_root(ti_env,
+ (void**)&si->exc, si->exc,
+ JVMTI_HEAP_ROOT_STACK_LOCAL,
+ depth, method_id, slot++);
+ DEBUG_GC(" [EXCEPTION]: " << si->exc->vt()->clss->name->bytes << endl);
+ }
+
+ if (method->is_native()) {
+ DEBUG_GC("[METHOD <native>]: "
+ << method->get_class()->name->bytes << "."
+ << method->get_name()->bytes
+ << method->get_descriptor()->bytes << endl);
+ interp_si_goto_previous(si);
+ continue;
+ }
+
+ DEBUG_GC("[METHOD "<< si->stack.size << " " << (int)si->locals.varNum << "]: "
+ << method->get_class()->name->bytes << "."
+ << method->get_name()->bytes
+ << method->get_descriptor()->bytes << endl);
+
+ if (si->stack.size)
+ for(i = 0; i <= si->stack.index; i++) {
+ if (si->stack.refs[i] == FLAG_OBJECT) {
+ DEBUG_GC(" Stack[" << i << "] ");
+ CREF* cref = &si->stack.data[i].cr;
+ ManagedObject *obj = UNCOMPRESS_REF(*cref);
+ if (obj == 0) {
+ DEBUG_GC("NULL");
+ } else {
+ DEBUG_GC(obj->vt()->clss->name->bytes << endl);
+ vm_ti_enumerate_stack_root(ti_env,
+ cref, (Managed_Object_Handle)obj,
+ JVMTI_HEAP_ROOT_STACK_LOCAL,
+ depth, method_id, slot++);
+ }
+ }
+ }
+
+ unsigned j;
+ if (si->locals.varNum)
+ for(j = 0; j < si->locals.varNum; j++) {
+ if (si->locals.refs[j] == FLAG_OBJECT) {
+ DEBUG_GC(" Locals[" << j << "] ");
+ CREF* cref = &si->locals.var[j].cr;
+ ManagedObject *obj = UNCOMPRESS_REF(*cref);
+ if (obj == 0) {
+ DEBUG_GC("NULL\n");
+ } else {
+ DEBUG_GC(obj->vt()->clss->name->bytes << endl);
+ vm_ti_enumerate_stack_root(ti_env,
+ cref, (Managed_Object_Handle)obj,
+ JVMTI_HEAP_ROOT_STACK_LOCAL,
+ depth, method_id, slot++);
+ }
+ }
+ }
+ MonitorList *ml = si->locked_monitors;
+ while(ml) {
+ vm_ti_enumerate_stack_root(ti_env,
+ &ml->monitor, ml->monitor,
+ JVMTI_HEAP_ROOT_MONITOR,
+ depth, method_id, slot++);
+ ml = ml->next;
+ }
+ interp_si_goto_previous(si);
+ }
+
+ // enumerate m2n frames
+ M2nFrame *m2n = m2n_get_last_frame(thread);
+ while(m2n) {
+ oh_enumerate_handles(m2n_get_local_handles(m2n));
+ m2n = m2n_get_previous_frame(m2n);
+ }
+}
+
+void interpreter_ti_enumerate_thread(jvmtiEnv *ti_env, VM_thread *thread)
+{
+ interp_ti_enumerate_root_set_single_thread_on_stack(ti_env, thread);
+
+ // Enumerate references associated with a thread that are not stored on the thread's stack.
+ vm_enumerate_root_set_single_thread_not_on_stack(thread);
+}
Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/jvmti_direct.h
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/jvmti_direct.h?view=diff&rev=470903&r1=470902&r2=470903
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/jvmti_direct.h (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/jvmti_direct.h Fri Nov 3 09:00:27 2006
@@ -24,6 +24,7 @@
#include "jni_direct.h"
#include "jvmti.h"
+#include "open/hythread_ext.h"
struct TIEventThread
{
@@ -35,12 +36,22 @@
extern Agent *current_loading_agent;
class VMBreakInterface;
+// declared privately in jvmti_tags.h
+struct TITags;
+
+// declared privately in jvmti_heap.h
+struct TIIterationState;
+
/*
* Type that describes TI environment created by GetEnv function
*/
struct TIEnv
{
const ti_interface *functions;
+
+ /// Lock used to protect TIEnv instance
+ hymutex_t lock;
+
JavaVM_Internal *vm;
Agent *agent;
void *user_storage;
@@ -48,6 +59,8 @@
jvmtiExtensionEvent *extension_event_table;
jvmtiCapabilities posessed_capabilities;
VMBreakInterface *brpt_intf;
+ TITags* tags;
+ TIIterationState* iteration_state;
TIEnv* next;
bool global_events[TOTAL_EVENT_TYPE_NUM];
@@ -112,9 +125,12 @@
void jvmti_send_class_prepare_event(Class* clss);
VMEXPORT void jvmti_send_thread_start_end_event(int is_start);
void jvmti_send_vm_death_event();
+void jvmti_send_gc_finish_event();
+void jvmti_send_gc_start_event();
bool jvmti_jit_breakpoint_handler(Registers *regs);
VMEXPORT void jvmti_process_native_method_bind_event(jmethodID method,
NativeCodePtr address, NativeCodePtr* new_address_ptr);
+void jvmti_clean_reclaimed_object_tags();
#ifdef __cplusplus
}
Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/jvmti_internal.h
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/jvmti_internal.h?view=diff&rev=470903&r1=470902&r2=470903
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/jvmti_internal.h (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/jvmti_internal.h Fri Nov 3 09:00:27 2006
@@ -222,6 +222,8 @@
return p_TIenvs;
}
+ void enumerate();
+
// Watched fields' support
Watch** get_access_watch_list()
@@ -289,7 +291,8 @@
TI_GC_ENABLE_EXCEPTION_EVENT = 0x10,
TI_GC_ENABLE_FIELD_ACCESS_EVENT = 0x20,
TI_GC_ENABLE_FIELD_MODIFICATION_EVENT = 0x40,
- TI_GC_ENABLE_POP_FRAME = 0x80
+ TI_GC_ENABLE_POP_FRAME = 0x80,
+ TI_GC_ENABLE_TAG_OBJECTS = 0x100,
};
void set_global_capability(GlobalCapabilities ti_gc)
Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/object_layout.h
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/object_layout.h?view=diff&rev=470903&r1=470902&r2=470903
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/object_layout.h (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/object_layout.h Fri Nov 3 09:00:27 2006
@@ -14,10 +14,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-/**
- * @author Intel, Alexei Fedotov
- * @version $Revision: 1.1.2.1.4.4 $
- */
#ifndef _OBJECT_LAYOUT_H_
#define _OBJECT_LAYOUT_H_
@@ -25,7 +21,6 @@
// Define USE_COMPRESSED_VTABLE_POINTERS here to explicitly enable compressed vtable
// pointers within objects.
// Define USE_UNCOMPRESSED_VTABLE_POINTERS to explicitly disable them.
-// Leave both undefined to make it command-line switchable.
#if defined _IPF_ || defined _EM64T_
#define USE_COMPRESSED_VTABLE_POINTERS
#else // !_IPF_
@@ -37,6 +32,7 @@
#include "open/hythread_ext.h"
#include "jni.h"
#include "open/vm.h"
+
typedef struct VTable VTable;
#ifdef __cplusplus
@@ -44,118 +40,86 @@
#endif
+// The object layout is currently as follows
//
-// Built-in types
+// * VTable* / uint32 vt_offset +
+// .-* uint32 lockword +- get_constant_header_size()
+// | [int32 array lenth]
+// | * [void* tag pointer]
+// | [padding]
+// | fields / array elements
+// |
+// `- get_size()
//
+// tag pointer field is present iff ManagedObject::_tag_pointer is true
+// length field is present in array objects
-// Note: if the header layout of the object changes, VM_VECTOR_RT_OVERHEAD must changed
-// below as well.
-typedef struct ManagedObjectCompressedVtablePtr {
+typedef struct ManagedObject {
+#if defined USE_COMPRESSED_VTABLE_POINTERS
uint32 vt_offset;
uint32 obj_info;
- VTable *vt_unsafe() { return (VTable *) (vt_offset + vm_get_vtable_base()); }
+ VTable *vt_unsafe() { return (VTable*)(vt_offset + vm_get_vtable_base()); }
VTable *vt() { assert(vt_offset); return vt_unsafe(); }
- uint32 get_obj_info() { return obj_info; }
- void set_obj_info(uint32 value) { obj_info = value; }
static VTable *allocation_handle_to_vtable(Allocation_Handle ah) {
return (VTable *) ((POINTER_SIZE_INT)ah + vm_get_vtable_base());
}
static unsigned header_offset() { return sizeof(uint32); }
- static size_t get_size() { return sizeof(ManagedObjectCompressedVtablePtr); }
- static bool are_vtable_pointers_compressed() { return TRUE; }
-} ManagedObjectCompressedVtablePtr;
-
-typedef struct ManagedObjectUncompressedVtablePtr {
+ static bool are_vtable_pointers_compressed() { return true; }
+#elif defined USE_UNCOMPRESSED_VTABLE_POINTERS
VTable *vt_raw;
POINTER_SIZE_INT obj_info;
VTable *vt_unsafe() { return vt_raw; }
VTable *vt() { assert(vt_raw); return vt_unsafe(); }
- uint32 get_obj_info() { return (uint32) obj_info; }
- void set_obj_info(uint32 value) { obj_info = (uint32) value; }
static VTable *allocation_handle_to_vtable(Allocation_Handle ah) {
return (VTable *) ah;
}
static unsigned header_offset() { return sizeof(VTable *); }
- static size_t get_size() { return sizeof(ManagedObjectUncompressedVtablePtr); }
- static bool are_vtable_pointers_compressed() { return FALSE; }
-} ManagedObjectUncompressedVtablePtr;
-
-typedef struct ManagedObject {
- VTable *vt_unsafe() {
- if (are_vtable_pointers_compressed())
- return ((ManagedObjectCompressedVtablePtr *)this)->vt_unsafe();
- else
- return ((ManagedObjectUncompressedVtablePtr *)this)->vt_unsafe();
- }
- VTable *vt() {
- assert(!hythread_is_suspend_enabled());
- if (are_vtable_pointers_compressed())
- return ((ManagedObjectCompressedVtablePtr *)this)->vt();
- else
- return ((ManagedObjectUncompressedVtablePtr *)this)->vt();
- }
- uint32 get_obj_info() {
- assert(!hythread_is_suspend_enabled());
- if (are_vtable_pointers_compressed())
- return ((ManagedObjectCompressedVtablePtr *)this)->get_obj_info();
- else
- return ((ManagedObjectUncompressedVtablePtr *)this)->get_obj_info();
+ static bool are_vtable_pointers_compressed() { return false; }
+#endif
+ /// returns the size of constant object header part (vt pointer and obj_info)
+ static size_t get_constant_header_size() { return sizeof(ManagedObject); }
+ /// returns the size of object header including dynamically enabled fields.
+ static size_t get_size() {
+ return get_constant_header_size() + (_tag_pointer ? sizeof(void*) : 0);
}
+
+ uint32 get_obj_info() { return (uint32)obj_info; }
+ void set_obj_info(uint32 value) { obj_info = value; }
uint32 *get_obj_info_addr() { return (uint32 *)((char *)this + header_offset()); }
- void set_obj_info(uint32 value) {
- assert(!hythread_is_suspend_enabled());
- if (are_vtable_pointers_compressed())
- ((ManagedObjectCompressedVtablePtr *)this)->set_obj_info(value);
- else
- ((ManagedObjectUncompressedVtablePtr *)this)->set_obj_info(value);
+ /**
+ * returns address of a tag pointer field in a _non-array_ object.
+ * For array objects use VM_Vector::get_tag_pointer_address().
+ */
+ void** get_tag_pointer_address() {
+ assert(_tag_pointer);
+ return (void**)((char*)this + get_constant_header_size());
}
- static VTable *allocation_handle_to_vtable(Allocation_Handle ah) {
- return are_vtable_pointers_compressed() ?
- ManagedObjectCompressedVtablePtr::allocation_handle_to_vtable(ah) : ManagedObjectUncompressedVtablePtr::allocation_handle_to_vtable(ah);
- }
- static unsigned header_offset() {
- return are_vtable_pointers_compressed() ?
- ManagedObjectCompressedVtablePtr::header_offset() : ManagedObjectUncompressedVtablePtr::header_offset();
- }
- static size_t get_size() {
- return are_vtable_pointers_compressed() ?
- ManagedObjectCompressedVtablePtr::get_size() : ManagedObjectUncompressedVtablePtr::get_size();
- }
- static bool are_vtable_pointers_compressed() {
-#ifdef USE_COMPRESSED_VTABLE_POINTERS
- return true;
-#else // !USE_COMPRESSED_VTABLE_POINTERS
-#ifdef USE_UNCOMPRESSED_VTABLE_POINTERS
- return false;
-#else // !USE_UNCOMPRESSED_VTABLE_POINTERS
- return _compressed;
-#endif // !USE_UNCOMPRESSED_VTABLE_POINTERS
-#endif // !USE_COMPRESSED_VTABLE_POINTERS
- }
- static bool _compressed;
-} ManagedObject;
+ VMEXPORT static bool _tag_pointer;
+} ManagedObject;
// See gc_for_vm, any change here needs to be reflected in Partial_Reveal_JavaArray.
typedef struct VM_Vector
{
- // The length field comes immediately after the ManagedObject fields.
- static size_t length_offset() { return ManagedObject::get_size(); }
- int32 get_length() { return *(int32 *)((char *)this + length_offset()); }
- void set_length(int32 len) { *(int32 *)((char *)this + length_offset()) = len; }
-} VM_Vector;
-
+ ManagedObject object;
+ int32 length;
+ static size_t length_offset() { return (size_t)(&((VM_Vector*)NULL)->length); }
+ int32 get_length() { return length; }
+ void set_length(int32 len) { length = len; }
+
+ void** get_tag_pointer_address() {
+ assert(ManagedObject::_tag_pointer);
+ int offset = sizeof(VM_Vector);
+ return (void**)((char*)this + offset);
+ }
+} VM_Vector;
-//////////////////////////////////////////////////////////
-// Field access functions follow
-ManagedObject *get_java_lang_throwable_field_trace(Java_java_lang_Throwable *thr);
-void set_java_lang_throwable_field_trace(Java_java_lang_Throwable *thr, ManagedObject *trace);
// Every vector has two pointers that can be found in any VM object
Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/root_set_enum_internal.h
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/root_set_enum_internal.h?view=diff&rev=470903&r1=470902&r2=470903
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/root_set_enum_internal.h (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/root_set_enum_internal.h Fri Nov 3 09:00:27 2006
@@ -35,4 +35,11 @@
void vm_enumerate_root_set_global_refs();
void vm_enumerate_thread(VM_thread *thread);
+void vm_enumerate_static_fields();
+void vm_enumerate_references_to_enqueue();
+void oh_enumerate_global_handles();
+void vm_enumerate_interned_strings();
+void vm_enumerate_root_set_mon_arrays();
+
+
#endif // _ROOT_SET_ENUM_INTERNAL_H_
Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/thread_manager.h
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/thread_manager.h?view=diff&rev=470903&r1=470902&r2=470903
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/thread_manager.h (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/thread_manager.h Fri Nov 3 09:00:27 2006
@@ -23,6 +23,9 @@
#ifndef THREAD_MANAGER_HEADER
#define THREAD_MANAGER_HEADER
+#include "platform.h"
+#include "vm_threads.h"
+
#ifdef __cplusplus
extern "C" {
Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/version_svn_tag.h
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/version_svn_tag.h?view=diff&rev=470903&r1=470902&r2=470903
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/version_svn_tag.h (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/include/version_svn_tag.h Fri Nov 3 09:00:27 2006
@@ -18,6 +18,6 @@
#ifndef _VERSION_SVN_TAG_
#define _VERSION_SVN_TAG_
-#define VERSION_SVN_TAG "470723"
+#define VERSION_SVN_TAG "470869"
#endif // _VERSION_SVN_TAG_
Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Prepare.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Prepare.cpp?view=diff&rev=470903&r1=470902&r2=470903
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Prepare.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Prepare.cpp Fri Nov 3 09:00:27 2006
@@ -39,6 +39,7 @@
#include "interpreter.h"
#include "lil.h"
#include "lil_code_generator.h"
+#include "vm_log.h"
#ifdef _DEBUG
#include "jni.h"
@@ -1516,6 +1517,8 @@
// Move the size to the vtable.
clss->vtable->allocated_size = clss->allocated_size;
clss->instance_data_size = clss->allocated_size;
+ TRACE2("class.size", "class " << clss << " allocated size "
+ << clss->allocated_size);
//
//
Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/gc/dll_gc.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/gc/dll_gc.cpp?view=diff&rev=470903&r1=470902&r2=470903
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/gc/dll_gc.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/gc/dll_gc.cpp Fri Nov 3 09:00:27 2006
@@ -41,6 +41,7 @@
static void default_gc_unpin_object(Managed_Object_Handle*);
static int32 default_gc_get_hashcode(Managed_Object_Handle);
static Managed_Object_Handle default_gc_get_next_live_object(void*);
+static void default_gc_iterate_heap();
static void default_gc_finalize_on_exit();
static int64 default_gc_max_memory();
static void default_gc_wrapup();
@@ -66,6 +67,8 @@
/* $$$ GMJ static int32 default_gc_get_hashcode(Managed_Object_Handle); */
static Boolean default_gc_supports_frontier_allocation(unsigned *offset_of_current, unsigned *offset_of_limit);
+static void default_gc_add_weak_root_set_entry(
+ Managed_Object_Handle*, Boolean, Boolean);
@@ -122,6 +125,7 @@
int32 (*gc_get_hashcode)(Managed_Object_Handle obj) = 0;
Managed_Object_Handle (*gc_get_next_live_object)(void *iterator) = 0;
int32 (*gc_get_hashcode0) (Managed_Object_Handle p_object) = 0;
+void (*gc_iterate_heap)() = 0;
void (*gc_finalize_on_exit)() = 0;
@@ -172,7 +176,13 @@
dllName,
(apr_dso_handle_sym_t)default_gc_supports_compressed_references);
- gc_add_root_set_entry = (void (*)(Managed_Object_Handle *ref, Boolean is_pinned)) getFunction(handle, "gc_add_root_set_entry", dllName);
+ gc_add_root_set_entry = (void (*)(Managed_Object_Handle *ref, Boolean is_pinned))
+ getFunction(handle, "gc_add_root_set_entry", dllName);
+
+ gc_add_weak_root_set_entry = (void (*)(Managed_Object_Handle *, Boolean, Boolean))
+ getFunctionOptional(handle, "gc_add_weak_root_set_entry", dllName,
+ (apr_dso_handle_sym_t) default_gc_add_weak_root_set_entry);
+
gc_add_compressed_root_set_entry = (void (*)(uint32 *ref, Boolean is_pinned))
getFunctionOptional(handle,
"gc_add_compressed_root_set_entry",
@@ -247,6 +257,10 @@
gc_get_next_live_object = (Managed_Object_Handle (*)(void*))
getFunctionOptional(handle, "gc_get_next_live_object", dllName,
(apr_dso_handle_sym_t)default_gc_get_next_live_object);
+
+ gc_iterate_heap = (void (*)())
+ getFunctionOptional(handle, "gc_iterate_heap", dllName,
+ (apr_dso_handle_sym_t)default_gc_iterate_heap);
gc_finalize_on_exit = (void (*)())
getFunctionOptional(handle, "gc_finalize_on_exit", dllName,
@@ -473,6 +487,11 @@
return NULL;
}
+static void default_gc_iterate_heap()
+{
+ WARN_ONCE("The GC did not provide heap iteration");
+}
+
static void default_gc_finalize_on_exit()
{
WARN_ONCE("The GC did not provide finalization on exit");
@@ -486,5 +505,13 @@
static void default_gc_write_barrier(Managed_Object_Handle)
{
+}
+
+static void default_gc_add_weak_root_set_entry(
+ Managed_Object_Handle* root, Boolean pinned, Boolean is_short)
+{
+ WARN_ONCE("The GC did not provide gc_add_weak_root_set_entry()");
+ // default to strong reference semantics
+ gc_add_root_set_entry(root, pinned);
}
#endif // !USE_GC_STATIC
Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/gc/root_set_enum_common.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/gc/root_set_enum_common.cpp?view=diff&rev=470903&r1=470902&r2=470903
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/gc/root_set_enum_common.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/gc/root_set_enum_common.cpp Fri Nov 3 09:00:27 2006
@@ -31,8 +31,7 @@
#include "open/vm_util.h"
#include "finalize.h"
-static void
-vm_enumerate_interned_strings()
+void vm_enumerate_interned_strings()
{
TRACE2("enumeration", "vm_enumerate_interned_strings()");
// string enumeration should be done in stop_the_world phase.
@@ -65,8 +64,7 @@
// Enumerate all globally visible classes and their static fields.
-static void
-vm_enumerate_static_fields()
+void vm_enumerate_static_fields()
{
TRACE2("enumeration", "vm_enumerate_static_fields()");
Global_Env *global_env = VM_Global_State::loader_env;
@@ -128,8 +126,8 @@
void
vm_enumerate_root_reference(void **ref, Boolean is_pinned)
{
- if (get_global_safepoint_status() == enumerate_the_universe) {
-
+ TRACE2("vm.enum", "vm_enumerate_root_reference("
+ << ref << " -> " << *ref << ")");
#if _DEBUG
if (VM_Global_State::loader_env->compress_references) {
// 20030324 DEBUG: verify the slot whose reference is being passed.
@@ -143,8 +141,7 @@
}
#endif // _DEBUG
- gc_add_root_set_entry((Managed_Object_Handle *)ref, is_pinned);
- }
+ gc_add_root_set_entry((Managed_Object_Handle *)ref, is_pinned);
} //vm_enumerate_root_reference
@@ -154,8 +151,6 @@
{
assert(VM_Global_State::loader_env->compress_references);
- if (get_global_safepoint_status() == enumerate_the_universe) {
-
#if _DEBUG
// 20030324 Temporary: verify the slot whose reference is being passed.
COMPRESSED_REFERENCE compressed_ref = *ref;
@@ -172,8 +167,7 @@
}
#endif // _DEBUG
- gc_add_compressed_root_set_entry(ref, is_pinned);
- }
+ gc_add_compressed_root_set_entry(ref, is_pinned);
} //vm_enumerate_compressed_root_reference
@@ -195,6 +189,10 @@
void
vm_enumerate_root_set_global_refs()
{
+ // ! The enumeration code is duplicated in !
+ // ! ti_enumerate_globals(), plase apply !
+ // ! all changes there too. !
+
////////////////////////////////////////
///// First enumerate strong pointers
@@ -212,6 +210,12 @@
vm_enumerate_root_set_mon_arrays();
ClassLoader::gc_enumerate();
+
+ // this enumeration part is needed only for real garbage collection,
+ // and not needed for JVMTI IterateOverReachableObjects
+ if (VM_Global_State::loader_env->TI->isEnabled()) {
+ VM_Global_State::loader_env->TI->enumerate();
+ }
} //vm_enumerate_root_set_global_refs
Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/gc/stop_the_world_root_set_enum.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/gc/stop_the_world_root_set_enum.cpp?view=diff&rev=470903&r1=470902&r2=470903
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/gc/stop_the_world_root_set_enum.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/gc/stop_the_world_root_set_enum.cpp Fri Nov 3 09:00:27 2006
@@ -28,6 +28,7 @@
#include "thread_manager.h"
#include "interpreter.h"
#include "finalize.h"
+#include "jvmti_direct.h"
////////// M E A S U R E M E N T of thread suspension time///////////
@@ -95,6 +96,8 @@
thread_suspend_time = vm_time_end_hook(&_start_time, &_end_time);
INFO2("tm.suspend","Thread suspension time: "<< thread_suspend_time <<" mksec");
+ jvmti_send_gc_start_event();
+
class_unloading_clear_mark_bits();
current_vm_thread = p_TLS_vmthread;
@@ -161,6 +164,9 @@
p_the_safepoint_control_thread = 0;
class_unloading_start();
+
+ jvmti_send_gc_finish_event();
+ jvmti_clean_reclaimed_object_tags();
// Run through list of active threads and resume each one of them.
hythread_resume_all( NULL);
Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm.cpp?view=diff&rev=470903&r1=470902&r2=470903
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm.cpp Fri Nov 3 09:00:27 2006
@@ -61,12 +61,8 @@
Global_Env *VM_Global_State::loader_env = 0;
-// Set the default for compressed vtable pointers depending on the architecture.
-#ifdef _IPF_
-bool ManagedObject::_compressed = true;
-#else // !_IPF_
-bool ManagedObject::_compressed = false;
-#endif // !_IPF_
+// tag pointer is not allocated by default, enabled by TI
+bool ManagedObject::_tag_pointer = false;
Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_init.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_init.cpp?view=diff&rev=470903&r1=470902&r2=470903
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_init.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_init.cpp Fri Nov 3 09:00:27 2006
@@ -42,6 +42,7 @@
#include "verify_stack_enumeration.h"
#include "nogc.h"
#include "vm_strings.h"
+#include "slot.h"
#ifdef PLATFORM_NT
// 20040427 Used to turn on heap checking on every allocation
@@ -55,6 +56,9 @@
bool parallel_jit = true;
VMEXPORT bool dump_stubs = false;
+void* Slot::heap_base = NULL;
+void* Slot::heap_ceiling = NULL;
+
void vm_initialize_critical_sections() {
p_jit_a_method_lock = new Lock_Manager();
p_vtable_patch_lock = new Lock_Manager();
@@ -640,6 +644,9 @@
// Initialize memory allocation.
vm_init_mem_alloc();
gc_init();
+
+ // TODO: change all uses of Class::heap_base to Slot::heap_base
+ Slot::init(gc_heap_base_address(), gc_heap_ceiling_address());
// TODO: find another way to initialize the following.
Class::heap_base = (Byte *)gc_heap_base_address();
Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti.cpp?view=diff&rev=470903&r1=470902&r2=470903
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti.cpp Fri Nov 3 09:00:27 2006
@@ -248,9 +248,20 @@
return error_code;
}
+ memset(newenv, 0, sizeof(TIEnv));
+
+ IDATA error_code1 = hymutex_create(&newenv->lock, 0/*HYTHREAD_MUTEX_DEFAULT*/);
+ if (error_code1 != APR_SUCCESS)
+ {
+ _deallocate((unsigned char *)newenv);
+ *env = NULL;
+ return JVMTI_ERROR_OUT_OF_MEMORY;
+ }
+
error_code = newenv->allocate_extension_event_callbacks_table();
if (error_code != JVMTI_ERROR_NONE)
{
+ hymutex_destroy(newenv->lock);
_deallocate((unsigned char *)newenv);
*env = NULL;
return error_code;
Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_capability.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_capability.cpp?view=diff&rev=470903&r1=470902&r2=470903
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_capability.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_capability.cpp Fri Nov 3 09:00:27 2006
@@ -31,7 +31,7 @@
static const jvmtiCapabilities jvmti_supported_interpreter_capabilities =
{
- 0, // can_tag_objects
+ 1, // can_tag_objects
1, // can_generate_field_modification_events
1, // can_generate_field_access_events
1, // can_get_bytecodes
@@ -62,13 +62,13 @@
1, // can_generate_monitor_events
1, // can_generate_vm_object_alloc_events
1, // can_generate_native_method_bind_events
- 0, // can_generate_garbage_collection_events
- 0 // can_generate_object_free_events
+ 1, // can_generate_garbage_collection_events
+ 1 // can_generate_object_free_events
};
static const jvmtiCapabilities jvmti_supported_jit_capabilities =
{
- 0, // can_tag_objects
+ 1, // can_tag_objects
1, // can_generate_field_modification_events
1, // can_generate_field_access_events
1, // can_get_bytecodes
@@ -99,8 +99,8 @@
1, // can_generate_monitor_events
1, // can_generate_vm_object_alloc_events
1, // can_generate_native_method_bind_events
- 0, // can_generate_garbage_collection_events
- 0 // can_generate_object_free_events
+ 1, // can_generate_garbage_collection_events
+ 1 // can_generate_object_free_events
};
// 1 means that corresponding capability can be enabled
@@ -138,8 +138,8 @@
0, // can_generate_monitor_events
1, // can_generate_vm_object_alloc_events
1, // can_generate_native_method_bind_events
- 0, // can_generate_garbage_collection_events
- 0 // can_generate_object_free_events
+ 1, // can_generate_garbage_collection_events
+ 1 // can_generate_object_free_events
};
/*
@@ -275,6 +275,11 @@
if (capabilities_ptr->can_pop_frame)
ti->set_global_capability(DebugUtilsTI::TI_GC_ENABLE_POP_FRAME);
+
+ if (capabilities_ptr->can_tag_objects) {
+ ti->set_global_capability(DebugUtilsTI::TI_GC_ENABLE_TAG_OBJECTS);
+ ManagedObject::_tag_pointer = true;
+ }
return JVMTI_ERROR_NONE;
}
Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_event.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_event.cpp?view=diff&rev=470903&r1=470902&r2=470903
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_event.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_event.cpp Fri Nov 3 09:00:27 2006
@@ -1905,3 +1905,66 @@
ti->nextPhase(JVMTI_PHASE_DEAD);
}
+void jvmti_send_gc_start_event()
+{
+ Global_Env *env = VM_Global_State::loader_env;
+ // this event is sent from stop-the-world setting
+ assert(!hythread_is_suspend_enabled());
+
+ DebugUtilsTI *ti = env->TI;
+ if (!ti->isEnabled())
+ return;
+
+ TIEnv *ti_env = ti->getEnvironments();
+ TIEnv *next_env;
+ while (NULL != ti_env)
+ {
+ next_env = ti_env->next;
+ if (ti_env->global_events[JVMTI_EVENT_GARBAGE_COLLECTION_START - JVMTI_MIN_EVENT_TYPE_VAL])
+ {
+ jvmtiEventGarbageCollectionStart func =
+ (jvmtiEventGarbageCollectionStart)
+ ti_env->get_event_callback(JVMTI_EVENT_GARBAGE_COLLECTION_START);
+
+ if (NULL != func)
+ {
+ TRACE2("jvmti.event.gc", "Callback JVMTI_EVENT_GARBAGE_COLLECTION_START called");
+ func((jvmtiEnv*)ti_env);
+ TRACE2("jvmti.event.gc", "Callback JVMTI_EVENT_GARBAGE_COLLECTION_START finished");
+ }
+ }
+ ti_env = next_env;
+ }
+}
+
+void jvmti_send_gc_finish_event()
+{
+ Global_Env *env = VM_Global_State::loader_env;
+ // this event is sent from stop-the-world setting
+ assert(!hythread_is_suspend_enabled());
+
+ DebugUtilsTI *ti = env->TI;
+ if (!ti->isEnabled())
+ return;
+
+ TIEnv *ti_env = ti->getEnvironments();
+ TIEnv *next_env;
+ while (NULL != ti_env)
+ {
+ next_env = ti_env->next;
+ if (ti_env->global_events[JVMTI_EVENT_GARBAGE_COLLECTION_FINISH - JVMTI_MIN_EVENT_TYPE_VAL])
+ {
+ jvmtiEventGarbageCollectionFinish func =
+ (jvmtiEventGarbageCollectionFinish)
+ ti_env->get_event_callback(JVMTI_EVENT_GARBAGE_COLLECTION_FINISH);
+
+ if (NULL != func)
+ {
+ TRACE2("jvmti.event.gc", "Callback JVMTI_EVENT_GARBAGE_COLLECTION_FINISH called");
+ func((jvmtiEnv*)ti_env);
+ TRACE2("jvmti.event.gc", "Callback JVMTI_EVENT_GARBAGE_COLLECTION_FINISH finished");
+ }
+ }
+ ti_env = next_env;
+ }
+}
Modified: incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_heap.cpp
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_heap.cpp?view=diff&rev=470903&r1=470902&r2=470903
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_heap.cpp (original)
+++ incubator/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jvmti/jvmti_heap.cpp Fri Nov 3 09:00:27 2006
@@ -15,20 +15,38 @@
* limitations under the License.
*/
/**
- * @author Gregory Shimansky
+ * @author Salikh Zakirov
* @version $Revision: 1.1.2.1.4.4 $
*/
/*
* JVMTI heap API
*/
+#include "cxxlog.h"
+
#include "jvmti_direct.h"
#include "jvmti_utils.h"
-#include "cxxlog.h"
#include "open/gc.h"
+#include "open/vm_gc.h"
+#include "open/thread.h"
+#include "open/hythread_ext.h"
+#include "object_layout.h"
+#include "thread_manager.h"
#include "suspend_checker.h"
+#include "vm_arrays.h"
+#include "object_handles.h"
+#include "vm_log.h"
+
+// private module headers
+#include "jvmti_heap.h"
+#include "jvmti_roots.h"
+#include "jvmti_tags.h"
+#include "jvmti_trace.h"
+
+// FIXME: use TLS to store ti_env
+TIEnv* ti_env;
/*
* Get Tag
@@ -42,8 +60,8 @@
*/
jvmtiError JNICALL
jvmtiGetTag(jvmtiEnv* env,
- jobject UNREF object,
- jlong* UNREF tag_ptr)
+ jobject object,
+ jlong* tag_ptr)
{
TRACE2("jvmti.heap", "GetTag called");
SuspendEnabledChecker sec;
@@ -54,9 +72,26 @@
CHECK_EVERYTHING();
- //TBD
+ if (NULL == tag_ptr || !is_jobject_valid(object))
+ return JVMTI_ERROR_ILLEGAL_ARGUMENT;
- return JVMTI_NYI;
+ TIEnv* ti_env = reinterpret_cast<TIEnv *>(env);
+
+ if (!ti_env->posessed_capabilities.can_tag_objects) {
+ return JVMTI_ERROR_MUST_POSSESS_CAPABILITY;
+ }
+
+ if (ti_env->tags == NULL) {
+ *tag_ptr = 0;
+ return JVMTI_ERROR_NONE;
+ }
+
+ tmn_suspend_disable(); // ----vv
+ Managed_Object_Handle obj = object->object;
+ *tag_ptr = ti_env->tags->get(obj);
+ tmn_suspend_enable(); // ----^^
+
+ return JVMTI_ERROR_NONE;
}
/*
@@ -70,8 +105,8 @@
*/
jvmtiError JNICALL
jvmtiSetTag(jvmtiEnv* env,
- jobject UNREF object,
- jlong UNREF tag)
+ jobject object,
+ jlong tag)
{
TRACE2("jvmti.heap", "SetTag called");
SuspendEnabledChecker sec;
@@ -81,10 +116,34 @@
jvmtiPhase phases[] = {JVMTI_PHASE_START, JVMTI_PHASE_LIVE};
CHECK_EVERYTHING();
+ if (!is_jobject_valid(object))
+ return JVMTI_ERROR_ILLEGAL_ARGUMENT;
+
+ TIEnv* ti_env = reinterpret_cast<TIEnv *>(env);
- //TBD
+ if (!ti_env->posessed_capabilities.can_tag_objects) {
+ return JVMTI_ERROR_MUST_POSSESS_CAPABILITY;
+ }
+
+ if (ti_env->tags == NULL) {
+ assert(ti_env->lock);
+ hymutex_lock(ti_env->lock);
+ if (ti_env->tags == NULL) {
+ ti_env->tags = new TITags;
+ }
+ hymutex_unlock(ti_env->lock);
+ }
+
+ if (ti_env->tags == NULL) {
+ return JVMTI_ERROR_OUT_OF_MEMORY;
+ }
+
+ tmn_suspend_disable(); // ----vv
+ Managed_Object_Handle obj = object->object;
+ ti_env->tags->set(obj, tag);
+ tmn_suspend_enable(); // ----^^
- return JVMTI_NYI;
+ return JVMTI_ERROR_NONE;
}
/*
@@ -109,19 +168,66 @@
CHECK_EVERYTHING();
- assert(hythread_is_suspend_enabled());
// no matter how counter-intuitive,
- // gc_force_gc() expects gc_enabled_status == disabled,
+ // gc_force_gc() expects suspend_enabled_status == disabled,
// but, obviously, at a GC safepoint.
- // See gc-safety (aka suspend-safety) rules explained elsewhere
- // -salikh 2005-05-12
- tmn_suspend_disable();
+ // for more details, see
+ // * "SAFE SUSPENSION" section of Developers' Guide
+ // * "THREAD SUSPENSION" section of Thread Manager documentation
+ hythread_suspend_disable();
gc_force_gc();
- tmn_suspend_enable();
+ hythread_suspend_enable();
- return JVMTI_NYI;
+ return JVMTI_ERROR_NONE;
+}
+
+static jvmtiError allocate_iteration_state(TIEnv* ti_env)
+{
+ assert(NULL == ti_env->iteration_state);
+ ti_env->iteration_state = new TIIterationState;
+ TIIterationState* state = ti_env->iteration_state;
+ if (NULL == state) {
+ return JVMTI_ERROR_OUT_OF_MEMORY;
+ }
+
+ memset(state, 0, sizeof(TIIterationState));
+
+ // we trust in correct values of global values
+ // Class::heap_base and Class::heap_ceiling
+ assert((UDATA)Class::heap_base == (UDATA)gc_heap_base_address());
+ assert((UDATA)Class::heap_end == (UDATA)gc_heap_ceiling_address());
+
+ state->markbits_size = ((UDATA)Class::heap_end - (UDATA)Class::heap_base)
+ / GC_OBJECT_ALIGNMENT / 8;
+ state->markbits = new unsigned char[state->markbits_size];
+ if (state->markbits == NULL) {
+ delete state;
+ ti_env->iteration_state = NULL;
+ return JVMTI_ERROR_OUT_OF_MEMORY;
+ }
+ state->markstack = new std::stack<ManagedObject*>;
+ if (state->markstack == NULL) {
+ delete[] state->markbits;
+ delete state;
+ ti_env->iteration_state = NULL;
+ return JVMTI_ERROR_OUT_OF_MEMORY;
+ }
+ memset(state->markbits, 0, state->markbits_size);
+ return JVMTI_ERROR_NONE;
+}
+
+static void free_iteration_state(TIEnv* ti_env)
+{
+ assert(ti_env->iteration_state);
+ assert(ti_env->iteration_state->markstack);
+ assert(ti_env->iteration_state->markbits);
+ delete ti_env->iteration_state->markstack;
+ delete[] ti_env->iteration_state->markbits;
+ delete ti_env->iteration_state;
+ ti_env->iteration_state = NULL;
}
+
/*
* Iterate Over Objects Reachable From Object
*
@@ -132,9 +238,9 @@
*/
jvmtiError JNICALL
jvmtiIterateOverObjectsReachableFromObject(jvmtiEnv* env,
- jobject UNREF object,
- jvmtiObjectReferenceCallback UNREF object_reference_callback,
- void* UNREF user_data)
+ jobject object,
+ jvmtiObjectReferenceCallback object_ref_callback,
+ void* user_data)
{
TRACE2("jvmti.heap", "IterateOverObjectsReachableFromObject called");
SuspendEnabledChecker sec;
@@ -145,9 +251,52 @@
CHECK_EVERYTHING();
- //TBD
+ if (!is_jobject_valid(object)) {
+ return JVMTI_ERROR_ILLEGAL_ARGUMENT;
+ }
+
+ TIEnv* ti_env = reinterpret_cast<TIEnv *>(env);
+ hythread_global_lock();
+
+ jvmtiError r;
+ r = allocate_iteration_state(ti_env);
+ if (r != JVMTI_ERROR_NONE) {
+ hythread_global_unlock();
+ return r;
+ }
+
+ hythread_suspend_disable(); // to keep assertions happy
+ hythread_iterator_t iterator;
+ hythread_suspend_all(&iterator, NULL);
+
+ ::ti_env = ti_env; // FIXME: use TLS to store TIEnv pointer
+
+ ti_env->iteration_state->user_data = user_data;
+ ti_env->iteration_state->object_ref_callback = object_ref_callback;
- return JVMTI_NYI;
+ ti_env->iteration_state->markstack->push((ManagedObject*)object->object);
+ ti_trace_heap(ti_env);
+
+ free_iteration_state(ti_env);
+
+ TRACE2("ti.iterate", "iteration complete");
+ hythread_resume_all(NULL);
+ hythread_suspend_enable();
+ hythread_global_unlock();
+
+ return JVMTI_ERROR_NONE;
+}
+
+static void ti_iterate_reachable(TIEnv* ti_env,
+ hythread_iterator_t iterator)
+{
+ // enumerate roots and the trace the heap
+ ti_enumerate_roots(ti_env, iterator);
+
+ // check if we don't need to trace heap
+ if (ti_env->iteration_state->abort) return;
+
+ ti_trace_heap(ti_env);
}
/*
@@ -163,10 +312,10 @@
*/
jvmtiError JNICALL
jvmtiIterateOverReachableObjects(jvmtiEnv* env,
- jvmtiHeapRootCallback UNREF heap_root_callback,
- jvmtiStackReferenceCallback UNREF stack_ref_callback,
- jvmtiObjectReferenceCallback UNREF object_ref_callback,
- void* UNREF user_data)
+ jvmtiHeapRootCallback heap_root_callback,
+ jvmtiStackReferenceCallback stack_ref_callback,
+ jvmtiObjectReferenceCallback object_ref_callback,
+ void* user_data)
{
TRACE2("jvmti.heap", "IterateOverReachableObjects called");
SuspendEnabledChecker sec;
@@ -177,9 +326,81 @@
CHECK_EVERYTHING();
- //TBD
+ TIEnv* ti_env = reinterpret_cast<TIEnv *>(env);
+ hythread_global_lock();
+
+ jvmtiError r;
+ r = allocate_iteration_state(ti_env);
+ if (r != JVMTI_ERROR_NONE) {
+ hythread_global_unlock();
+ return r;
+ }
+
+ hythread_suspend_disable(); // to keep assertions happy
+ hythread_iterator_t iterator;
+ hythread_suspend_all(&iterator, NULL);
+
+ ::ti_env = ti_env; // FIXME: use TLS to store TIEnv pointer
+
+ ti_env->iteration_state->user_data = user_data;
+ ti_env->iteration_state->heap_root_callback = heap_root_callback;
+ ti_env->iteration_state->stack_ref_callback = stack_ref_callback;
+ ti_env->iteration_state->object_ref_callback = object_ref_callback;
+
+ ti_iterate_reachable(ti_env, iterator);
+
+ free_iteration_state(ti_env);
+
+ TRACE2("ti.iterate", "iteration complete");
+ hythread_resume_all(NULL);
+ hythread_suspend_enable();
+ hythread_global_unlock();
+
+ return JVMTI_ERROR_NONE;
+}
+
+bool vm_iterate_object(Managed_Object_Handle obj)
+{
+ TIEnv* ti_env = ::ti_env; // FIXME: use TLS to store ti_env
+
+ TRACE2("vm.iterate", "vm_iterate_object " << (ManagedObject*)obj);
+ assert(ti_env->tags);
+
+ jlong class_tag = ti_get_object_class_tag(ti_env, obj);
+ tag_pair** tp = ti_get_object_tptr(obj);
+ jlong tag = (*tp != NULL ? (*tp)->tag : 0);
+ jlong size = ti_get_object_size(ti_env, obj);
+
+ TIIterationState *state = ti_env->iteration_state;
+ assert(state);
+ void* user_data = state->user_data;
+ jvmtiHeapObjectCallback heap_object_callback
+ = state->heap_object_callback;
+
+ if (state->class_filter != NULL &&
+ ((ManagedObject*)obj)->vt()->clss != state->class_filter) {
+ // do not run user callback if we were
+ // asked to iterate instances of specified class
+ return true;
+ }
+
+ if (state->object_filter == JVMTI_HEAP_OBJECT_UNTAGGED && tag != 0) {
+ // do not run user callback for tagged objects
+ // if we were asked for untagged objects only
+ return true;
+ }
+
+ // in JVMTI_HEAP_OBJECT_TAGGED case, we should only get tagged objects
+ assert(!(state->object_filter == JVMTI_HEAP_OBJECT_TAGGED && tag == 0));
- return JVMTI_NYI;
+ jvmtiIterationControl r =
+ heap_object_callback(class_tag, size, &tag, user_data);
+
+ // update tag value or remove tag
+ ti_env->tags->update(obj, tag, tp);
+
+ // return true to continue iteration, false to terminate it
+ return (JVMTI_ITERATION_CONTINUE == r);
}
/*
@@ -192,9 +413,9 @@
*/
jvmtiError JNICALL
jvmtiIterateOverHeap(jvmtiEnv* env,
- jvmtiHeapObjectFilter UNREF object_filter,
- jvmtiHeapObjectCallback UNREF heap_object_callback,
- void* UNREF user_data)
+ jvmtiHeapObjectFilter object_filter,
+ jvmtiHeapObjectCallback heap_object_callback,
+ void* user_data)
{
TRACE2("jvmti.heap", "IterateOverHeap called");
SuspendEnabledChecker sec;
@@ -205,9 +426,50 @@
CHECK_EVERYTHING();
- //TBD
+ TIEnv* ti_env = reinterpret_cast<TIEnv *>(env);
+
- return JVMTI_NYI;
+ // heap iteration requires stop-the-world
+ hythread_global_lock();
+
+ assert(NULL == ti_env->iteration_state);
+ ti_env->iteration_state = new TIIterationState;
+ TIIterationState* state = ti_env->iteration_state;
+ if (NULL == state) {
+ hythread_global_unlock();
+ return JVMTI_ERROR_OUT_OF_MEMORY;
+ }
+
+ memset(state, 0, sizeof(TIIterationState));
+
+ hythread_suspend_disable(); // to keep assertions happy
+ hythread_iterator_t iterator;
+ hythread_suspend_all(&iterator, NULL);
+ TRACE2("ti.iterate", "suspended all threads");
+
+ ::ti_env = ti_env; // FIXME: use TLS to store TIEnv pointer
+ state->user_data = user_data;
+ state->heap_object_callback = heap_object_callback;
+ state->object_filter = object_filter;
+
+ if (JVMTI_HEAP_OBJECT_TAGGED == object_filter) {
+ // we iterate tagged objects directly from tags structure
+ if (ti_env->tags)
+ ti_env->tags->iterate();
+ } else {
+ // iterating untagged objects requires full heap iteration
+ gc_iterate_heap();
+ }
+
+ delete ti_env->iteration_state;
+ ti_env->iteration_state = NULL;
+
+ TRACE2("ti.iterate", "iteration complete");
+ hythread_resume_all(NULL);
+ hythread_suspend_enable();
+ hythread_global_unlock();
+
+ return JVMTI_ERROR_NONE;
}
/*
@@ -221,10 +483,10 @@
*/
jvmtiError JNICALL
jvmtiIterateOverInstancesOfClass(jvmtiEnv* env,
- jclass UNREF klass,
- jvmtiHeapObjectFilter UNREF object_filter,
- jvmtiHeapObjectCallback UNREF heap_object_callback,
- void* UNREF user_data)
+ jclass klass,
+ jvmtiHeapObjectFilter object_filter,
+ jvmtiHeapObjectCallback heap_object_callback,
+ void* user_data)
{
TRACE2("jvmti.heap", "IterateOverInstancesOfClass called");
SuspendEnabledChecker sec;
@@ -235,9 +497,52 @@
CHECK_EVERYTHING();
- //TBD
+ TIEnv* ti_env = reinterpret_cast<TIEnv *>(env);
+
- return JVMTI_NYI;
+ // heap iteration requires stop-the-world
+ TRACE2("ti.iterate", "acquire tm lock");
+ hythread_global_lock();
+ TRACE2("ti.iterate", "got tm lock");
+
+ assert(NULL == ti_env->iteration_state);
+ ti_env->iteration_state = new TIIterationState;
+ TIIterationState* state = ti_env->iteration_state;
+ if (NULL == state) {
+ hythread_global_unlock();
+ return JVMTI_ERROR_OUT_OF_MEMORY;
+ }
+
+ memset(state, 0, sizeof(TIIterationState));
+
+ hythread_suspend_disable(); // to keep assertions happy
+ hythread_iterator_t iterator;
+ hythread_suspend_all(&iterator, NULL);
+ TRACE2("ti.iterate", "suspended all threads");
+
+ ::ti_env = ti_env; // FIXME: use TLS to store TIEnv pointer
+ state->user_data = user_data;
+ state->heap_object_callback = heap_object_callback;
+ state->object_filter = object_filter;
+ state->class_filter = jclass_to_struct_Class(klass);
+
+ if (JVMTI_HEAP_OBJECT_TAGGED == object_filter) {
+ // we iterate tagged objects directly from tags structure
+ ti_env->tags->iterate();
+ } else {
+ // iterating untagged objects requires full heap iteration
+ gc_iterate_heap();
+ }
+
+ delete ti_env->iteration_state;
+ ti_env->iteration_state = NULL;
+
+ TRACE2("ti.iterate", "iteration complete");
+ hythread_resume_all(NULL);
+ hythread_suspend_enable();
+ hythread_global_unlock();
+
+ return JVMTI_ERROR_NONE;
}
/*
@@ -250,11 +555,11 @@
*/
jvmtiError JNICALL
jvmtiGetObjectsWithTags(jvmtiEnv* env,
- jint UNREF tag_count,
- const jlong* UNREF tags,
- jint* UNREF count_ptr,
- jobject** UNREF object_result_ptr,
- jlong** UNREF tag_result_ptr)
+ jint tag_count,
+ const jlong* tags,
+ jint* count_ptr,
+ jobject** object_result_ptr,
+ jlong** tag_result_ptr)
{
TRACE2("jvmti.heap", "GetObjectsWithTags called");
SuspendEnabledChecker sec;
@@ -264,8 +569,63 @@
jvmtiPhase phases[] = {JVMTI_PHASE_LIVE};
CHECK_EVERYTHING();
-
- //TBD
-
- return JVMTI_NYI;
+ if (count_ptr == NULL || tags == NULL || tag_count <= 0 ||
+ (object_result_ptr == NULL && tag_result_ptr == NULL)) {
+ return JVMTI_ERROR_ILLEGAL_ARGUMENT;
+ }
+
+ hythread_suspend_disable(); // ---------------vv
+
+ std::set<jlong> tag_set;
+ std::list<tag_pair> objects;
+ jvmtiError error = JVMTI_ERROR_NONE;
+
+ int i;
+ for (i = 0; i < tag_count; i++) {
+ tag_set.insert(tags[i]);
+ }
+
+ ti_env->tags->get_objects_with_tags(tag_set, objects);
+ int count = objects.size();
+ *count_ptr = count;
+ if (count > 0) {
+ if (object_result_ptr != NULL) {
+ jvmtiError r = _allocate(count * sizeof(jobject),
+ (unsigned char **)object_result_ptr);
+ if (r == JVMTI_ERROR_NONE) {
+ memset(*object_result_ptr, 0, count * sizeof(jobject));
+ std::list<tag_pair>::iterator o;
+ for (i = 0, o = objects.begin(); o != objects.end(); o++, i++) {
+ jobject jobj = oh_allocate_local_handle();
+ if (jobj) jobj->object = (ManagedObject*)o->obj;
+ else error = JVMTI_ERROR_OUT_OF_MEMORY;
+ (*object_result_ptr)[i] = jobj;
+ }
+ } else {
+ error = r;
+ }
+ if (r != JVMTI_ERROR_NONE && (*object_result_ptr)) {
+ _deallocate((unsigned char *)*object_result_ptr);
+ *object_result_ptr = NULL;
+ }
+ }
+
+ if (tag_result_ptr != NULL && error == JVMTI_ERROR_NONE) {
+ jvmtiError r = _allocate(count * sizeof(jlong),
+ (unsigned char **)tag_result_ptr);
+ if (JVMTI_ERROR_NONE == r) {
+ memset(*tag_result_ptr, 0, count * sizeof(jlong));
+ std::list<tag_pair>::iterator o;
+ for (i = 0, o = objects.begin(); o != objects.end(); o++, i++) {
+ (*tag_result_ptr)[i] = o->tag;
+ }
+ } else {
+ error = r;
+ }
+ }
+ }
+
+ hythread_suspend_enable(); // ---------------^^
+
+ return error;
}