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-09 16:13:24.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,54 @@ /* 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; + + return (obj_belongs_to_space(p_obj, space)) + && fspace_object_to_be_forwarded(p_obj, (Fspace*)space) + && !obj_is_forwarded_in_vt(p_obj); +} + +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-11 06:30:12.000000000 +0800 @@ -0,0 +1,182 @@ +/* + * 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); +} + + +#define MAX_INT ((((unsigned int)(~(int)(-1)))) >> 1) +#define DEFAULT_QUANTITY MAX_INT +static int do_finalization_func(void) +{ + return vm_do_finalization(DEFAULT_QUANTITY); +} + +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 }