diff -ruN oldtrunk/build/make/components/vm/gc_gen.xml newtrunk/build/make/components/vm/gc_gen.xml
--- oldtrunk/build/make/components/vm/gc_gen.xml 2006-12-09 19:17:31.000000000 +0800
+++ newtrunk/build/make/components/vm/gc_gen.xml 2006-12-07 09:57:58.000000000 +0800
@@ -61,7 +61,8 @@
-
+
+
diff -ruN oldtrunk/vm/gc_gen/gc_gen.xml newtrunk/vm/gc_gen/gc_gen.xml
--- oldtrunk/vm/gc_gen/gc_gen.xml 2006-12-03 23:49:30.000000000 +0800
+++ newtrunk/vm/gc_gen/gc_gen.xml 2006-12-10 01:05:36.000000000 +0800
@@ -16,7 +16,7 @@
-->
*/
Vector_Block* rem_set;
+ Vector_Block* objects_with_finalizer;
Mutator* next; /* The gc info area associated with the next active thread. */
} Mutator;
diff -ruN oldtrunk/vm/gc_gen/src/trace_forward/fspace_collect_copy.cpp newtrunk/vm/gc_gen/src/trace_forward/fspace_collect_copy.cpp
--- oldtrunk/vm/gc_gen/src/trace_forward/fspace_collect_copy.cpp 2006-12-03 23:49:30.000000000 +0800
+++ newtrunk/vm/gc_gen/src/trace_forward/fspace_collect_copy.cpp 2006-12-09 16:13:18.000000000 +0800
@@ -22,6 +22,7 @@
#include "../mark_compact/mspace.h"
#include "../mark_sweep/lspace.h"
#include "../thread/collector.h"
+#include "../finalizer_weakref/finalizer_weakref.h"
static volatile Block_Header* current_copy_block;
static volatile Block_Header* current_target_block;
@@ -179,6 +180,9 @@
/* world for single thread, e.g., verification of last phase, and preparation of next phase */
current_copy_block = fspace_get_first_copy_block(fspace);
current_target_block = mspace_get_first_target_block_for_nos(mspace);
+
+ collector_process_finalizer_weakref(collector);
+
/* let other collectors go */
num_marking_collectors++;
}
@@ -203,6 +207,8 @@
if( collector->thread_handle != 0 ) return;
gc_update_repointed_refs(collector);
+
+ gc_post_process_finalizer_weakref(gc);
/* FIXME:: Pass 2 and 3 can be merged into one pass */
/* Pass 3: copy live fspace object to new location */
diff -ruN oldtrunk/vm/gc_gen/src/trace_forward/fspace_collect_forward.cpp newtrunk/vm/gc_gen/src/trace_forward/fspace_collect_forward.cpp
--- oldtrunk/vm/gc_gen/src/trace_forward/fspace_collect_forward.cpp 2006-12-06 17:04:50.000000000 +0800
+++ newtrunk/vm/gc_gen/src/trace_forward/fspace_collect_forward.cpp 2006-12-12 19:08:01.000000000 +0800
@@ -22,6 +22,7 @@
#include "fspace.h"
#include "../thread/collector.h"
#include "../common/gc_metadata.h"
+#include "../finalizer_weakref/finalizer_weakref.h"
static Boolean fspace_object_to_be_forwarded(Partial_Reveal_Object *p_obj, Fspace *fspace)
{
@@ -71,6 +72,8 @@
offset_scanner = offset_next_ref(offset_scanner);
}
+ scan_weak_reference(collector, p_obj, scan_slot);
+
return;
}
@@ -95,7 +98,7 @@
/* Fastpath: object has already been forwarded, update the ref slot */
if(obj_is_forwarded_in_vt(p_obj)) {
- *p_ref = obj_get_forwarding_pointer_in_vt(p_obj);
+ *p_ref = obj_get_forwarding_pointer_in_vt(p_obj);
return;
}
@@ -122,11 +125,11 @@
is set in the atomic instruction, which requires to roll back the mos_alloced
space. That is easy for thread local block allocation cancellation. */
if( p_target_obj == NULL ){
- *p_ref = obj_get_forwarding_pointer_in_vt(p_obj);
- return;
+ *p_ref = obj_get_forwarding_pointer_in_vt(p_obj);
+ return;
}
/* otherwise, we successfully forwarded */
- *p_ref = p_target_obj;
+ *p_ref = p_target_obj;
/* we forwarded it, we need remember it for verification. */
if(verify_live_heap) {
@@ -240,9 +243,60 @@
/* the rest work is not enough for parallelization, so let only one thread go */
if( collector->thread_handle != 0 ) return;
+ collector_process_finalizer_weakref(collector);
+
gc_update_repointed_refs(collector);
+
+ gc_post_process_finalizer_weakref(gc);
+
reset_fspace_for_allocation(space);
return;
}
+
+Boolean obj_is_dead_in_minor_forward_collection(Collector *collector, Partial_Reveal_Object *p_obj)
+{
+ Space *space = collector->collect_space;
+ Boolean belong_to_nos = obj_belongs_to_space(p_obj, space);
+
+ if(!belong_to_nos)
+ return FALSE;
+
+ Boolean space_to_be_forwarded = fspace_object_to_be_forwarded(p_obj, (Fspace*)space);
+ Boolean forwarded = obj_is_forwarded_in_vt(p_obj);
+ Boolean marked = obj_is_marked_in_vt(p_obj);
+
+ return (space_to_be_forwarded && !forwarded) || (!space_to_be_forwarded && !marked);
+}
+
+void resurrect_obj_tree_after_trace(Collector *collector, Partial_Reveal_Object **p_ref)
+{
+ GC *gc = collector->gc;
+ GC_Metadata* metadata = gc->metadata;
+
+ collector->trace_stack = pool_get_entry(metadata->free_task_pool);
+ collector_tracestack_push(collector, p_ref);
+ pool_put_entry(metadata->mark_task_pool, collector->trace_stack);
+
+//collector->rep_set = pool_get_entry(metadata->free_set_pool); /* has got collector->rep_set in caller */
+ collector->trace_stack = pool_get_entry(metadata->free_task_pool);
+ Vector_Block* trace_task = pool_get_entry(metadata->mark_task_pool);
+ while(trace_task){
+ unsigned int* iter = vector_block_iterator_init(trace_task);
+ while(!vector_block_iterator_end(trace_task,iter)){
+ Partial_Reveal_Object** p_ref = (Partial_Reveal_Object** )*iter;
+ iter = vector_block_iterator_advance(trace_task,iter);
+ assert(*p_ref);
+ trace_object(collector, p_ref);
+ }
+ vector_stack_clear(trace_task);
+ pool_put_entry(metadata->free_task_pool, trace_task);
+ trace_task = pool_get_entry(metadata->mark_task_pool);
+ }
+
+ trace_task = (Vector_Block*)collector->trace_stack;
+ vector_stack_clear(trace_task);
+ pool_put_entry(metadata->free_task_pool, trace_task);
+ collector->trace_stack = NULL;
+}
diff -ruN oldtrunk/vm/include/open/vm_gc.h newtrunk/vm/include/open/vm_gc.h
--- oldtrunk/vm/include/open/vm_gc.h 2006-12-09 19:17:40.000000000 +0800
+++ newtrunk/vm/include/open/vm_gc.h 2006-12-09 15:49:12.000000000 +0800
@@ -176,12 +176,16 @@
*/
VMEXPORT void vm_finalize_object(Managed_Object_Handle p_obj);
+VMEXPORT void set_native_finalizer_thread_flag(Boolean flag);
+
/**
* GC should call this function when an phantom reference object
* is to be enqueued, i.e. when the reference is not reachable anymore.
*/
VMEXPORT void vm_enqueue_reference(Managed_Object_Handle p_obj);
+VMEXPORT void set_native_ref_enqueue_thread_flag(Boolean flag);
+
enum WeakReferenceType {
NOT_REFERENCE = 0,
WEAK_REFERENCE,
diff -ruN oldtrunk/vm/vmcore/include/finalize.h newtrunk/vm/vmcore/include/finalize.h
--- oldtrunk/vm/vmcore/include/finalize.h 2006-12-09 19:18:09.000000000 +0800
+++ newtrunk/vm/vmcore/include/finalize.h 2006-12-09 15:50:16.000000000 +0800
@@ -50,5 +50,8 @@
void vm_enqueue_references();
+void vm_ref_enqueue_func(void); // added for NATIVE REFERENCE ENQUEUE THREAD
+
+Boolean get_native_finalizer_thread_flag(); // added for NATIVE FINALIZER THREAD
#endif
diff -ruN oldtrunk/vm/vmcore/include/finalizer_thread.h newtrunk/vm/vmcore/include/finalizer_thread.h
--- oldtrunk/vm/vmcore/include/finalizer_thread.h 1970-01-01 08:00:00.000000000 +0800
+++ newtrunk/vm/vmcore/include/finalizer_thread.h 2006-12-09 14:23:16.000000000 +0800
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2005-2006 The Apache Software Foundation or its licensors, as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @author Li-Gang Wang, 2006/11/15
+ */
+
+#ifndef _FINALIZER_THREAD_H_
+#define _FINALIZER_THREAD_H_
+
+#include "jni_types.h"
+#include "open/hythread_ext.h"
+#include
+#include "open/types.h"
+#include
+
+#ifndef _FINALIZER_WEAKREF_PLATFORM_
+#define _FINALIZER_WEAKREF_PLATFORM_
+
+#define VmEventHandle hysem_t
+
+inline int vm_wait_event(VmEventHandle event)
+{
+ IDATA stat = hysem_wait(event);
+ assert(stat == TM_ERROR_NONE); return stat;
+}
+inline int vm_set_event(VmEventHandle event, IDATA count)
+{
+ IDATA stat = hysem_set(event, count);
+ assert(stat == TM_ERROR_NONE); return stat;
+}
+inline int vm_post_event(VmEventHandle event)
+{
+ IDATA stat = hysem_set(event, 1);
+ assert(stat == TM_ERROR_NONE); return stat;
+}
+inline int vm_create_event(VmEventHandle* event, unsigned int initial_count, unsigned int max_count)
+{
+ return hysem_create(event, initial_count, max_count);
+}
+
+
+typedef volatile unsigned int SpinLock;
+enum Lock_State{
+ FREE_LOCK,
+ LOCKED
+};
+
+#define gc_try_lock(x) (!apr_atomic_cas32(&(x), LOCKED, FREE_LOCK))
+#define gc_lock(x) while( !gc_try_lock(x)){ while( x==LOCKED );}
+#define gc_unlock(x) do{ x = FREE_LOCK;}while(0)
+
+#endif
+
+#define FINALIZER_THREAD_PRIORITY (HYTHREAD_PRIORITY_USER_MAX - 3)
+
+struct finalizer_thread_info {
+ SpinLock lock;
+ int thread_num;
+ int working_thread_num;
+ Boolean shutdown;
+ Boolean on_exit;
+ VmEventHandle finalizer_pending_event;
+ VmEventHandle finalization_end_event;
+};
+
+
+extern Boolean get_finalizer_shutdown_flag();
+extern Boolean get_finalizer_on_exit_flag();
+extern void finalizer_threads_init(JavaVM *java_vm, JNIEnv *jni_env);
+extern void finalizer_shutdown(Boolean start_finalization_on_exit);
+extern void activate_finalizer_threads(Boolean wait);
+extern void vmmemory_manager_runfinalization(void);
+
+#endif // _FINALIZER_THREAD_H_
diff -ruN oldtrunk/vm/vmcore/include/ref_enqueue_thread.h newtrunk/vm/vmcore/include/ref_enqueue_thread.h
--- oldtrunk/vm/vmcore/include/ref_enqueue_thread.h 1970-01-01 08:00:00.000000000 +0800
+++ newtrunk/vm/vmcore/include/ref_enqueue_thread.h 2006-12-09 14:23:40.000000000 +0800
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2005-2006 The Apache Software Foundation or its licensors, as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @author Li-Gang Wang, 2006/11/15
+ */
+
+#ifndef _REF_ENQUEUE_THREAD_H_
+#define _REF_ENQUEUE_THREAD_H_
+
+#include "jni_types.h"
+#include "open/hythread_ext.h"
+#include
+#include "open/types.h"
+#include
+
+#ifndef _FINALIZER_WEAKREF_PLATFORM_
+#define _FINALIZER_WEAKREF_PLATFORM_
+
+#define VmEventHandle hysem_t
+
+inline int vm_wait_event(VmEventHandle event)
+{
+ IDATA stat = hysem_wait(event);
+ assert(stat == TM_ERROR_NONE); return stat;
+}
+inline int vm_set_event(VmEventHandle event, IDATA count)
+{
+ IDATA stat = hysem_set(event, count);
+ assert(stat == TM_ERROR_NONE); return stat;
+}
+inline int vm_post_event(VmEventHandle event)
+{
+ IDATA stat = hysem_set(event, 1);
+ assert(stat == TM_ERROR_NONE); return stat;
+}
+inline int vm_create_event(VmEventHandle* event, unsigned int initial_count, unsigned int max_count)
+{
+ return hysem_create(event, initial_count, max_count);
+}
+
+
+typedef volatile unsigned int SpinLock;
+enum Lock_State{
+ FREE_LOCK,
+ LOCKED
+};
+
+#define gc_try_lock(x) (!apr_atomic_cas32(&(x), LOCKED, FREE_LOCK))
+#define gc_lock(x) while( !gc_try_lock(x)){ while( x==LOCKED );}
+#define gc_unlock(x) do{ x = FREE_LOCK;}while(0)
+
+#endif
+
+#define REF_ENQUEUE_THREAD_PRIORITY (HYTHREAD_PRIORITY_USER_MAX - 1)
+
+struct ref_enqueue_thread_info {
+ SpinLock lock;
+ VmEventHandle reference_pending_event;
+ Boolean shutdown;
+};
+
+extern Boolean get_native_ref_enqueue_thread_flag();
+extern void ref_enqueue_thread_init(JavaVM *java_vm, JNIEnv *jni_env);
+extern void ref_enqueue_shutdown(void);
+extern void activate_ref_enqueue_thread(void);
+
+#endif // _REF_ENQUEUE_THREAD_H_
diff -ruN oldtrunk/vm/vmcore/src/init/finalize.cpp newtrunk/vm/vmcore/src/init/finalize.cpp
--- oldtrunk/vm/vmcore/src/init/finalize.cpp 2006-12-09 19:18:22.000000000 +0800
+++ newtrunk/vm/vmcore/src/init/finalize.cpp 2006-12-09 15:53:44.000000000 +0800
@@ -37,6 +37,9 @@
#include "jit_runtime_support.h"
#include "finalize.h"
+#include "finalizer_thread.h" /* added for NATIVE FINALIZER THREAD */
+#include "ref_enqueue_thread.h" /* added for NATIVE REFERENCE ENQUEUE THREAD */
+
#define LOG_DOMAIN "vm.object_queue"
#include "classloader.h"
@@ -343,8 +346,14 @@
} //Objects_To_Finalize::run_finalizers
int Objects_To_Finalize::do_finalization(int quantity) {
+ /* BEGIN: added for NATIVE FINALIZER THREAD */
+ Boolean native_finalizer_thread_flag = get_native_finalizer_thread_flag();
+ Boolean native_finalizer_shutdown, native_finalizer_on_exit;
+ /* END: added for NATIVE FINALIZER THREAD */
+
//SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_HIGHEST);
- p_TLS_vmthread->finalize_thread_flags = FINALIZER_THREAD;
+ if(!native_finalizer_thread_flag) // added for NATIVE FINALIZER THREAD
+ p_TLS_vmthread->finalize_thread_flags = FINALIZER_THREAD;
int i;
tmn_suspend_disable();
@@ -353,18 +362,28 @@
jvalue args[1];
args[0].l = (jobject) handle;
- assert(VM_Global_State::loader_env->finalizer_thread);
- jboolean* finalizer_shutdown = VM_Global_State::loader_env->finalizer_shutdown;
- assert(finalizer_shutdown);
- jboolean* finalizer_on_exit = VM_Global_State::loader_env->finalizer_on_exit;
- assert(finalizer_on_exit);
+ /* BEGIN: modified for NATIVE FINALIZER THREAD */
+ jboolean *finalizer_shutdown, *finalizer_on_exit;
+ if(!native_finalizer_thread_flag){
+ assert(VM_Global_State::loader_env->finalizer_thread);
+ finalizer_shutdown = VM_Global_State::loader_env->finalizer_shutdown;
+ assert(finalizer_shutdown);
+ finalizer_on_exit = VM_Global_State::loader_env->finalizer_on_exit;
+ assert(finalizer_on_exit);
+ native_finalizer_shutdown = (Boolean)*finalizer_shutdown;
+ native_finalizer_on_exit = (Boolean)*finalizer_on_exit;
+ }
+ /* END: modified for NATIVE FINALIZER THREAD */
for (i=0; ((iobject->vt()->clss;
assert(clss);
- if ((*finalizer_on_exit) && is_class_ignored(clss)) {
+ /* BEGIN: modified for NATIVE FINALIZER THREAD */
+ if(native_finalizer_thread_flag)
+ native_finalizer_on_exit = get_finalizer_on_exit_flag();
+ if (native_finalizer_on_exit && is_class_ignored(clss)) {
tmn_suspend_enable();
continue;
}
+ /* END: modified for NATIVE FINALIZER THREAD */
Method *finalize = class_lookup_method_recursive(clss,
VM_Global_State::loader_env->FinalizeName_String,
@@ -467,7 +490,12 @@
{
NativeObjectHandles nhs;
assert(hythread_is_suspend_enabled());
- objects_to_finalize.run_finalizers();
+ /* BEGIN: modified for NATIVE FINALIZER THREAD */
+ if(get_native_finalizer_thread_flag())
+ activate_finalizer_threads(FALSE);
+ else
+ objects_to_finalize.run_finalizers();
+ /* END: modified for NATIVE FINALIZER THREAD */
} //vm_run_pending_finalizers
int vm_do_finalization(int quantity)
@@ -510,5 +538,16 @@
void vm_enqueue_references()
{
- references_to_enqueue.enqueue_references();
+ /* BEGIN: modified for NATIVE REFERENCE ENQUEUE THREAD */
+ if(get_native_ref_enqueue_thread_flag())
+ activate_ref_enqueue_thread();
+ else
+ references_to_enqueue.enqueue_references();
+ /* END: modified for NATIVE REFERENCE ENQUEUE THREAD */
} //vm_enqueue_references
+
+/* added for NATIVE REFERENCE ENQUEUE THREAD */
+void vm_ref_enqueue_func(void)
+{
+ references_to_enqueue.enqueue_references();
+}
diff -ruN oldtrunk/vm/vmcore/src/init/finalizer_thread.cpp newtrunk/vm/vmcore/src/init/finalizer_thread.cpp
--- oldtrunk/vm/vmcore/src/init/finalizer_thread.cpp 1970-01-01 08:00:00.000000000 +0800
+++ newtrunk/vm/vmcore/src/init/finalizer_thread.cpp 2006-12-12 19:05:56.000000000 +0800
@@ -0,0 +1,180 @@
+/*
+ * Copyright 2005-2006 The Apache Software Foundation or its licensors, as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @author Li-Gang Wang, 2006/11/15
+ */
+
+#include "finalizer_thread.h"
+#include "ref_enqueue_thread.h"
+#include "open/gc.h"
+#include "port_sysinfo.h"
+#include "finalize.h"
+#include "vm_threads.h"
+#include "../../../thread/src/thread_private.h"
+
+static Boolean native_finalizer_thread_flag = FALSE;
+static struct finalizer_thread_info *finalizer_thread_info = NULL;
+
+
+Boolean get_native_finalizer_thread_flag()
+{
+ return native_finalizer_thread_flag;
+}
+
+void set_native_finalizer_thread_flag(Boolean flag)
+{
+ native_finalizer_thread_flag = flag;
+}
+
+Boolean get_finalizer_shutdown_flag()
+{
+ return finalizer_thread_info->shutdown;
+}
+
+Boolean get_finalizer_on_exit_flag()
+{
+ return finalizer_thread_info->on_exit;
+}
+
+static int finalizer_thread_func(void **args);
+
+void finalizer_threads_init(JavaVM *java_vm, JNIEnv *jni_env)
+{
+ if(!native_finalizer_thread_flag)
+ return;
+
+ finalizer_thread_info = (struct finalizer_thread_info *)STD_MALLOC(sizeof(struct finalizer_thread_info));
+ finalizer_thread_info->lock = FREE_LOCK;
+ finalizer_thread_info->thread_num = port_CPUs_number();
+ finalizer_thread_info->working_thread_num = 0;
+ finalizer_thread_info->shutdown = FALSE;
+ finalizer_thread_info->on_exit = FALSE;
+
+ int status = vm_create_event(&finalizer_thread_info->finalizer_pending_event, 0, finalizer_thread_info->thread_num);
+ assert(status == TM_ERROR_NONE);
+ status = vm_create_event(&finalizer_thread_info->finalization_end_event, 0, 1);
+ assert(status == TM_ERROR_NONE);
+
+ void **args = (void **)STD_MALLOC(sizeof(void *)*2);
+ args[0] = (void *)java_vm;
+ args[1] = (void *)jni_env;
+ for(int i = 0; i < finalizer_thread_info->thread_num; i++){
+ status = (unsigned int)hythread_create(NULL, 0, 0, 0, (hythread_entrypoint_t)finalizer_thread_func, args);
+ assert(status == TM_ERROR_NONE);
+ }
+}
+
+void finalizer_shutdown(Boolean start_finalization_on_exit)
+{
+ if(start_finalization_on_exit){
+ tmn_suspend_disable();
+ gc_force_gc();
+ tmn_suspend_enable();
+ activate_finalizer_threads(TRUE);
+ tmn_suspend_disable();
+ gc_finalize_on_exit();
+ tmn_suspend_enable();
+ gc_lock(finalizer_thread_info->lock);
+ finalizer_thread_info->on_exit = TRUE;
+ gc_unlock(finalizer_thread_info->lock);
+ activate_finalizer_threads(TRUE);
+ }
+ gc_lock(finalizer_thread_info->lock);
+ finalizer_thread_info->shutdown = TRUE;
+ gc_unlock(finalizer_thread_info->lock);
+ ref_enqueue_shutdown();
+ activate_finalizer_threads(FALSE);
+}
+
+static void wait_finalization_end(void)
+{
+ vm_wait_event(finalizer_thread_info->finalization_end_event);
+}
+
+void activate_finalizer_threads(Boolean wait)
+{
+ gc_lock(finalizer_thread_info->lock);
+ vm_set_event(finalizer_thread_info->finalizer_pending_event,
+ finalizer_thread_info->thread_num - finalizer_thread_info->working_thread_num);
+ gc_unlock(finalizer_thread_info->lock);
+
+ if(wait)
+ wait_finalization_end();
+}
+
+void vmmemory_manager_runfinalization(void)
+{
+ activate_finalizer_threads(TRUE);
+}
+
+
+static int do_finalization_func(void)
+{
+ return vm_do_finalization(0);
+}
+
+static void wait_pending_finalizer(void)
+{
+ vm_wait_event(finalizer_thread_info->finalizer_pending_event);
+}
+
+static void notify_finalization_end(void)
+{
+ vm_post_event(finalizer_thread_info->finalization_end_event);
+}
+
+static void finalizer_notify_work_done(void)
+{
+ gc_lock(finalizer_thread_info->lock);
+ --finalizer_thread_info->working_thread_num;
+ if(finalizer_thread_info->working_thread_num == 0)
+ notify_finalization_end();
+ gc_unlock(finalizer_thread_info->lock);
+}
+
+static int finalizer_thread_func(void **args)
+{
+ JavaVM *java_vm = (JavaVM *)args[0];
+ JNIEnv *jni_env = (JNIEnv *)args[1];
+
+ IDATA status = vm_attach(java_vm, &jni_env);
+ if(status != TM_ERROR_NONE)
+ return status;
+
+ while(true){
+ /* Waiting for pending finalizers */
+ wait_pending_finalizer();
+
+ gc_lock(finalizer_thread_info->lock);
+ ++finalizer_thread_info->working_thread_num;
+ gc_unlock(finalizer_thread_info->lock);
+
+ /* do the real finalization work */
+ do_finalization_func();
+
+ finalizer_notify_work_done();
+
+ gc_lock(finalizer_thread_info->lock);
+ if(finalizer_thread_info->shutdown){
+ gc_unlock(finalizer_thread_info->lock);
+ break;
+ }
+ gc_unlock(finalizer_thread_info->lock);
+ }
+
+ return TM_ERROR_NONE;
+}
diff -ruN oldtrunk/vm/vmcore/src/init/ref_enqueue_thread.cpp newtrunk/vm/vmcore/src/init/ref_enqueue_thread.cpp
--- oldtrunk/vm/vmcore/src/init/ref_enqueue_thread.cpp 1970-01-01 08:00:00.000000000 +0800
+++ newtrunk/vm/vmcore/src/init/ref_enqueue_thread.cpp 2006-12-11 06:30:12.000000000 +0800
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2005-2006 The Apache Software Foundation or its licensors, as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @author Li-Gang Wang, 2006/11/15
+ */
+
+#include "ref_enqueue_thread.h"
+#include "finalize.h"
+#include "vm_threads.h"
+#include "../../../thread/src/thread_private.h"
+
+static Boolean native_ref_enqueue_thread_flag = FALSE;
+static struct ref_enqueue_thread_info *ref_enqueue_thread_info = NULL;
+
+
+Boolean get_native_ref_enqueue_thread_flag()
+{
+ return native_ref_enqueue_thread_flag;
+}
+
+void set_native_ref_enqueue_thread_flag(Boolean flag)
+{
+ native_ref_enqueue_thread_flag = flag;
+}
+
+static int ref_enqueue_thread_func(void **args);
+
+void ref_enqueue_thread_init(JavaVM *java_vm, JNIEnv *jni_env)
+{
+ if(!get_native_ref_enqueue_thread_flag())
+ return;
+
+ ref_enqueue_thread_info = (struct ref_enqueue_thread_info *)STD_MALLOC(sizeof(struct ref_enqueue_thread_info));
+ ref_enqueue_thread_info->lock = FREE_LOCK;
+ ref_enqueue_thread_info->shutdown = FALSE;
+
+ int status = vm_create_event(&ref_enqueue_thread_info->reference_pending_event, 0, 1);
+ assert(status == TM_ERROR_NONE);
+
+ void **args = (void **)STD_MALLOC(sizeof(void *)*2);
+ args[0] = (void *)java_vm;
+ args[1] = (void *)jni_env;
+ status = (unsigned int)hythread_create(NULL, 0, REF_ENQUEUE_THREAD_PRIORITY, 0, (hythread_entrypoint_t)ref_enqueue_thread_func, args);
+ assert(status == TM_ERROR_NONE);
+}
+
+void ref_enqueue_shutdown(void)
+{
+ gc_lock(ref_enqueue_thread_info->lock);
+ ref_enqueue_thread_info->shutdown = TRUE;
+ gc_unlock(ref_enqueue_thread_info->lock);
+ activate_ref_enqueue_thread();
+}
+
+void activate_ref_enqueue_thread(void)
+{
+ vm_post_event(ref_enqueue_thread_info->reference_pending_event);
+}
+
+
+static int ref_enqueue_func(void)
+{
+ vm_ref_enqueue_func();
+ return 0;
+}
+
+static void wait_pending_reference(void)
+{
+ vm_wait_event(ref_enqueue_thread_info->reference_pending_event);
+}
+
+
+static int ref_enqueue_thread_func(void **args)
+{
+ JavaVM *java_vm = (JavaVM *)args[0];
+ JNIEnv *jni_env = (JNIEnv *)args[1];
+
+ IDATA status = vm_attach(java_vm, &jni_env);
+ if(status != TM_ERROR_NONE)
+ return status;
+
+ while(true){
+ /* Waiting for pending weak references */
+ wait_pending_reference();
+
+ /* do the real reference enqueue work */
+ ref_enqueue_func();
+
+ gc_lock(ref_enqueue_thread_info->lock);
+ if(ref_enqueue_thread_info->shutdown){
+ gc_unlock(ref_enqueue_thread_info->lock);
+ break;
+ }
+ gc_unlock(ref_enqueue_thread_info->lock);
+ }
+
+ return TM_ERROR_NONE;
+}
diff -ruN oldtrunk/vm/vmcore/src/init/vm_init.cpp newtrunk/vm/vmcore/src/init/vm_init.cpp
--- oldtrunk/vm/vmcore/src/init/vm_init.cpp 2006-12-09 19:18:22.000000000 +0800
+++ newtrunk/vm/vmcore/src/init/vm_init.cpp 2006-12-09 15:53:56.000000000 +0800
@@ -46,6 +46,8 @@
#include "vm_strings.h"
#include "slot.h"
#include "classpath_const.h"
+#include "finalizer_thread.h" /* added for NATIVE FINALIZER THREAD */
+#include "ref_enqueue_thread.h" /* added for NATIVE REFERENCE ENQUEUE THREAD */
#ifdef PLATFORM_NT
// 20040427 Used to turn on heap checking on every allocation
@@ -676,6 +678,9 @@
status = vm_attach(java_vm, &jni_env);
if (status != JNI_OK) return status;
+ finalizer_threads_init(java_vm, jni_env); /* added for NATIVE FINALIZER THREAD */
+ ref_enqueue_thread_init(java_vm, jni_env); /* added for NATIVE REFERENCE ENQUEUE THREAD */
+
// "Tool Interface" initialization
status = vm_env->TI->Init(java_vm);
if (status != JNI_OK) {
diff -ruN oldtrunk/vm/vmcore/src/kernel_classes/javasrc/java/lang/FinalizerThread.java newtrunk/vm/vmcore/src/kernel_classes/javasrc/java/lang/FinalizerThread.java
--- oldtrunk/vm/vmcore/src/kernel_classes/javasrc/java/lang/FinalizerThread.java 2006-12-09 19:18:44.000000000 +0800
+++ newtrunk/vm/vmcore/src/kernel_classes/javasrc/java/lang/FinalizerThread.java 2006-12-09 15:52:00.000000000 +0800
@@ -51,7 +51,12 @@
* VM calls this thread from Runtime.runFinalization().
*/
public static void runFinalization() {
- startFinalization(true);
+ /* BEGIN: added for NATIVE FINALIZER THREAD */
+ if(NATIVE_FINALIZER_THREAD)
+ runFinalizationInNativeFinalizerThreads();
+ else
+ /* END: added for NATIVE FINALIZER THREAD */
+ startFinalization(true);
}
/*
@@ -62,6 +67,11 @@
* Initializes finalization system. Starts permanent thread.
*/
static void initialize() {
+ /* BEGIN: added for NATIVE FINALIZER THREAD */
+ if (NATIVE_FINALIZER_THREAD)
+ return;
+ /* END: added for NATIVE FINALIZER THREAD */
+
if (TRACE) {
trace("FinalizerThread: static initialization started");
}
@@ -87,6 +97,12 @@
* VM calls this method to request finalizer thread shutdown.
*/
static void shutdown(boolean startFinalizationOnExit) {
+ /* BEGIN: added for NATIVE FINALIZER THREAD */
+ if(NATIVE_FINALIZER_THREAD) {
+ finalizerShutDown(startFinalizationOnExit);
+ return;
+ }
+ /* END: added for NATIVE FINALIZER THREAD */
if (TRACE) {
trace("shutting down finalizer thread");
}
@@ -101,6 +117,29 @@
}
}
+ /* added for NATIVE FINALIZER THREAD
+ * A flag to indicate whether the finalizer threads are native threads or Java threads.
+ */
+ private static final boolean NATIVE_FINALIZER_THREAD = getNativeFinalizerThreadFlagFromVM();
+
+ /* BEGIN: These three methods are added for NATIVE FINALIZER THREAD */
+ /**
+ * This method gets the flag that indicates
+ * whether VM uses native finalizer threads or Java finalizer threads.
+ */
+ private static native boolean getNativeFinalizerThreadFlagFromVM();
+
+ /**
+ * This method implements runFinalization() method in native finalizer threads.
+ */
+ private static native void runFinalizationInNativeFinalizerThreads();
+
+ /**
+ * This method does finalization work related to VM shutdown in native finalizer threads.
+ */
+ private static native void finalizerShutDown(boolean finalizeOnExit);
+ /* END: These three methods are added for NATIVE FINALIZER THREAD */
+
/*
* Staic private part
*/
diff -ruN oldtrunk/vm/vmcore/src/kernel_classes/native/java_lang_FinalizerThread.cpp newtrunk/vm/vmcore/src/kernel_classes/native/java_lang_FinalizerThread.cpp
--- oldtrunk/vm/vmcore/src/kernel_classes/native/java_lang_FinalizerThread.cpp 2006-12-09 19:18:39.000000000 +0800
+++ newtrunk/vm/vmcore/src/kernel_classes/native/java_lang_FinalizerThread.cpp 2006-12-09 15:54:18.000000000 +0800
@@ -34,6 +34,9 @@
#include "port_sysinfo.h"
#include "vm_threads.h"
+/* added for NATIVE FINALIZER THREAD */
+#include "finalizer_thread.h"
+
/**
* Implements getObject(..) method.
* For details see kernel classes component documentation.
@@ -90,3 +93,41 @@
gc_finalize_on_exit();
tmn_suspend_enable();
}
+
+/* BEGIN: These three methods are added for NATIVE FINALIZER THREAD */
+/*
+ * Class: java_lang_FinalizerThread
+ * Method: getNativeFinalizerThreadFlagFromVM
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_lang_FinalizerThread_getNativeFinalizerThreadFlagFromVM
+ (JNIEnv *, jclass)
+{
+ return (jboolean)get_native_finalizer_thread_flag();
+}
+
+/*
+ * Class: java_lang_FinalizerThread
+ * Method: runFinalizationInNativeFinalizerThreads
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_lang_FinalizerThread_runFinalizationInNativeFinalizerThreads
+ (JNIEnv *, jclass)
+{
+ vm_enqueue_references();
+
+ // Do finalization in dedicated native finalizer threads.
+ vmmemory_manager_runfinalization();
+}
+
+/*
+ * Class: java_lang_FinalizerThread
+ * Method: finalizerShutDown
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_lang_FinalizerThread_finalizerShutDown
+ (JNIEnv *, jclass, jboolean value)
+{
+ finalizer_shutdown(value);
+}
+/* END: These three methods are added for NATIVE FINALIZER THREAD */
diff -ruN oldtrunk/vm/vmcore/src/kernel_classes/native/java_lang_FinalizerThread.h newtrunk/vm/vmcore/src/kernel_classes/native/java_lang_FinalizerThread.h
--- oldtrunk/vm/vmcore/src/kernel_classes/native/java_lang_FinalizerThread.h 2006-12-09 19:18:39.000000000 +0800
+++ newtrunk/vm/vmcore/src/kernel_classes/native/java_lang_FinalizerThread.h 2006-12-09 15:54:36.000000000 +0800
@@ -81,6 +81,26 @@
JNIEXPORT void JNICALL
Java_java_lang_FinalizerThread_fillFinalizationQueueOnExit(JNIEnv *, jclass);
+/* BEGIN: These three methods are added for NATIVE FINALIZER THREAD */
+/*
+ * Method: java.lang.FinalizerThread.getNativeFinalizerThreadFlagFromVM()Z
+ */
+JNIEXPORT jboolean JNICALL
+Java_java_lang_FinalizerThread_getNativeFinalizerThreadFlagFromVM(JNIEnv *, jclass);
+
+/*
+ * Method: java_lang_FinalizerThread.runFinalizationInNativeFinalizerThreads()V
+ */
+JNIEXPORT void JNICALL
+Java_java_lang_FinalizerThread_runFinalizationInNativeFinalizerThreads(JNIEnv *, jclass);
+
+/*
+ * Method: java_lang_FinalizerThread.finalizerShutDown()V
+ */
+JNIEXPORT void JNICALL
+Java_java_lang_FinalizerThread_finalizerShutDown(JNIEnv *, jclass, jboolean);
+/* END: These three methods are added for NATIVE FINALIZER THREAD */
+
#ifdef __cplusplus
}