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;
 }