Index: gcv4/src/gc_for_vm.cpp =================================================================== --- gcv4/src/gc_for_vm.cpp (revision 454089) +++ gcv4/src/gc_for_vm.cpp (working copy) @@ -439,7 +439,7 @@ p_global_gc->gc_v4_init(); // create a nursery for the main thread - gc_thread_init(vm_get_gc_thread_local()); + // gc_thread_init(vm_get_gc_thread_local()); assert (sizeof(block_info) <= 4096); // If we hit this we should take a close look at our defines. While it is possible Index: gcv4/src/gc_utils.cpp =================================================================== --- gcv4/src/gc_utils.cpp (revision 454089) +++ gcv4/src/gc_utils.cpp (working copy) @@ -166,8 +166,7 @@ get_num_consecutive_similar_bits(uint8 *p_byte_start, unsigned int bit_index_to_search_from, unsigned int *num_consec_bits, uint8 *p_ceil) { if (p_ceil <= p_byte_start) { - ASSERT(0, "Unexpected values of input prameters"); - vm_exit(-7520); + DIE("Unexpected values of input prameters"); } bool is_zero_str = ((*p_byte_start) & (1 << bit_index_to_search_from)) ? false : true; Index: include/interpreter_imports.h =================================================================== --- include/interpreter_imports.h (revision 454089) +++ include/interpreter_imports.h (working copy) @@ -31,7 +31,7 @@ VMEXPORT void class_throw_linking_error_for_interpreter(Class_Handle ch, unsigned cp_index, unsigned opcode); -VMEXPORT struct JNIEnv_Internal* get_jni_native_intf(); +VMEXPORT JNIEnv * get_jni_native_intf(); VMEXPORT jbyte jvmti_process_interpreter_breakpoint_event(jmethodID method, jlocation loc); VMEXPORT void jvmti_process_single_step_event(jmethodID method, jlocation location); Index: include/jni.h =================================================================== --- include/jni.h (revision 454089) +++ include/jni.h (working copy) @@ -1,4 +1,4 @@ -/* +/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. @@ -38,7 +38,6 @@ #define JNI_VERSION_1_2 0x00010002 #define JNI_VERSION_1_4 0x00010004 - /* * JNI Native Method Interface - C */ @@ -1688,12 +1687,18 @@ jboolean ignoreUnrecognized; } JavaVMInitArgs; +typedef struct JavaVMAttachArgs { + jint version; + char *name; + jobject group; +} JavaVMAttachArgs; + struct JNIInvokeInterface_ { void* reserved0; void* reserved1; void* reserved2; - jint (JNICALL *DestroyVM)(JavaVM*); + jint (JNICALL *DestroyJavaVM)(JavaVM*); jint (JNICALL *AttachCurrentThread)(JavaVM*, void** penv, void* args); jint (JNICALL *DetachCurrentThread)(JavaVM*); @@ -1707,13 +1712,14 @@ const struct JNIInvokeInterface_* functions; #ifdef __cplusplus - jint DestroyVM() { - return functions->DestroyVM(this); + jint DestroyJavaVM() { + return functions->DestroyJavaVM(this); } jint AttachCurrentThread(void** penv, void* args) { return functions->AttachCurrentThread(this, penv, args); } + jint DetachCurrentThread() { return functions->DetachCurrentThread(this); } @@ -1725,20 +1731,32 @@ jint AttachCurrentThreadAsDaemon(void** penv, void* args) { return functions->AttachCurrentThreadAsDaemon(this, penv, args); } + #endif }; - #ifdef __cplusplus extern "C" { #endif -JNIEXPORT jint JNICALL JNI_CreateJavaVM(JavaVM **p_vm, JNIEnv **p_env, void *vm_args); +#ifdef BUILDING_VM +#define _JNI_EXPORT_ JNIEXPORT +#else +#define _JNI_EXPORT_ JNIIMPORT +#endif +_JNI_EXPORT_ jint JNICALL JNI_GetDefaultJavaVMInitArgs(void * vm_args); + +_JNI_EXPORT_ jint JNICALL JNI_GetCreatedJavaVMs(JavaVM ** vmBuf, + jsize bufLen, + jsize * nVMs); + +_JNI_EXPORT_ jint JNICALL JNI_CreateJavaVM(JavaVM ** p_vm, JNIEnv ** p_env, + void * vm_args); + #ifdef __cplusplus } #endif - #endif /* _JNI_H_ */ Index: include/open/hythread_ext.h =================================================================== --- include/open/hythread_ext.h (revision 454089) +++ include/open/hythread_ext.h (working copy) @@ -148,15 +148,19 @@ IDATA VMCALL hythread_global_lock(); IDATA VMCALL hythread_global_unlock(); -void VMCALL hythread_init (hythread_library_t lib); +void VMCALL hythread_init(hythread_library_t lib); +void VMCALL hythread_shutdown(); +IDATA VMCALL hythread_lib_create(hythread_library_t * lib); +void VMCALL hythread_lib_destroy(hythread_library_t lib); //@} /** @name Basic manipulation */ //@{ -IDATA VMCALL hythread_attach_to_group(hythread_t *handle, hythread_group_t group); - IDATA hythread_create_with_group(hythread_t *ret_thread, hythread_group_t group, UDATA stacksize, UDATA priority, UDATA suspend, hythread_entrypoint_t func, void *data); +IDATA VMCALL hythread_attach_ex(hythread_t *handle, hythread_library_t lib); +IDATA VMCALL hythread_attach_to_group(hythread_t *handle, hythread_library_t lib, hythread_group_t group); +IDATA hythread_create_with_group(hythread_t *ret_thread, hythread_group_t group, UDATA stacksize, UDATA priority, UDATA suspend, hythread_entrypoint_t func, void *data); UDATA VMCALL hythread_clear_interrupted_other(hythread_t thread); IDATA VMCALL hythread_join(hythread_t t); IDATA VMCALL hythread_join_timed(hythread_t t, I_64 millis, IDATA nanos); @@ -164,9 +168,8 @@ IDATA VMCALL hythread_get_self_id(); IDATA VMCALL hythread_get_id(hythread_t t); hythread_t VMCALL hythread_get_thread(IDATA id); -IDATA VMCALL hythread_struct_init(hythread_t *ret_thread, hythread_group_t group); +IDATA VMCALL hythread_struct_init(hythread_t *ret_thread); IDATA VMCALL hythread_cancel_all(hythread_group_t group); -IDATA VMCALL hythread_wait_for_all_nondaemon_threads(); IDATA hythread_group_create(hythread_group_t *group); IDATA VMCALL hythread_group_release(hythread_group_t group); IDATA VMCALL hythread_group_get_list(hythread_group_t **list, int* size); @@ -191,11 +194,11 @@ */ //@{ - IDATA hythread_is_suspend_enabled(); - void hythread_suspend_enable(); - void hythread_suspend_disable(); - void hythread_safe_point(); - IDATA VMCALL hythread_suspend_other(hythread_t thread); +IDATA hythread_is_suspend_enabled(); +void hythread_suspend_enable(); +void hythread_suspend_disable(); +void hythread_safe_point(); +IDATA VMCALL hythread_suspend_other(hythread_t thread); IDATA VMCALL hythread_set_safepoint_callback(hythread_t thread, hythread_event_callback_proc callback); hythread_event_callback_proc VMCALL hythread_get_safepoint_callback(hythread_t t); @@ -233,22 +236,22 @@ */ //@{ - IDATA hysem_create(hysem_t *sem, UDATA initial_count, UDATA max_count); +IDATA hysem_create(hysem_t *sem, UDATA initial_count, UDATA max_count); IDATA VMCALL hysem_wait_timed(hysem_t sem, I_64 ms, IDATA nano); IDATA VMCALL hysem_wait_interruptable(hysem_t sem, I_64 ms, IDATA nano); IDATA VMCALL hysem_getvalue(IDATA *count, hysem_t sem); - IDATA hysem_set(hysem_t sem, IDATA count); +IDATA hysem_set(hysem_t sem, IDATA count); //@} /** @name Mutex */ //@{ - IDATA hymutex_create (hymutex_t *mutex, UDATA flags); - IDATA hymutex_lock(hymutex_t mutex); - IDATA hymutex_trylock (hymutex_t mutex); - IDATA hymutex_unlock (hymutex_t mutex); - IDATA hymutex_destroy (hymutex_t mutex); +IDATA hymutex_create (hymutex_t *mutex, UDATA flags); +IDATA hymutex_lock(hymutex_t mutex); +IDATA hymutex_trylock (hymutex_t mutex); +IDATA hymutex_unlock (hymutex_t mutex); +IDATA hymutex_destroy (hymutex_t mutex); //@} /** @name Thin monitors support @@ -284,14 +287,9 @@ int VMCALL hythread_is_in_monitor_wait(hythread_t thread) ; int VMCALL hythread_is_parked(hythread_t thread) ; int VMCALL hythread_is_suspended(hythread_t thread) ; - -/** - * Returns non-zero if thread is interrupted. - * - * @param[in] thread those attribute is read - */ int VMCALL hythread_is_interrupted(hythread_t thread) ; int VMCALL hythread_is_in_native(hythread_t thread) ; +int VMCALL hythread_is_daemon(hythread_t thread) ; /** @@ -317,7 +315,6 @@ #define TM_THREAD_STATE_RESERVED1 JVMTI_THREAD_STATE_VENDOR_2 // 0x20000000 Defined by VM vendor. #define TM_THREAD_STATE_RESERVED2 JVMTI_THREAD_STATE_VENDOR_3 // 0x40000000 Defined by VM vendor - #define TM_MUTEX_DEFAULT 0 #define TM_MUTEX_NESTED 1 #define TM_MUTEX_UNNESTED 2 Index: include/open/jthread.h =================================================================== --- include/open/jthread.h (revision 454089) +++ include/open/jthread.h (working copy) @@ -81,9 +81,9 @@ } jthread_threadattr_t; jlong jthread_thread_init(jvmti_thread_t *ret_thread, JNIEnv* env, jthread java_thread, jobject weak_ref, jlong old_thread); - IDATA jthread_create(JNIEnv *env, jthread thread, jthread_threadattr_t *attrs); - IDATA jthread_create_with_function(JNIEnv *env, jthread thread, jthread_threadattr_t *attrs, jvmtiStartFunction proc, const void* arg); - IDATA jthread_attach(JNIEnv* env, jthread thread); +IDATA jthread_create(JNIEnv * jni_env, jthread thread, jthread_threadattr_t *attrs); +IDATA jthread_create_with_function(JNIEnv * jni_env, jthread thread, jthread_threadattr_t *attrs, jvmtiStartFunction proc, const void* arg); +IDATA jthread_attach(JNIEnv * jni_env, jthread thread, jboolean daemon); IDATA jthread_detach(jthread thread); IDATA jthread_join(jthread thread); IDATA jthread_timed_join(jthread thread, jlong millis, jint nanos); @@ -92,6 +92,7 @@ IDATA jthread_exception_stop(jthread thread, jobject throwable); IDATA jthread_sleep(jlong millis, jint nanos); JNIEnv *jthread_get_JNI_env(jthread thread); +IDATA jthread_wait_for_all_nondaemon_threads(); @@ -122,27 +123,9 @@ //@{ -/** - * Sets the daemon attribute for the thread. - * - * JVM exits when the only threads running are all daemon threads. - * - * @param[in] thread those attribute is set - * @param[in] on daemon off or on - * @sa java.lang.Thread.setDaemon() - */ -IDATA jthread_set_daemon(jthread thread, jboolean on); - -/** - * Returns true if the threadis daemon. - * - * @param[in] thread those attribute is read - * @sa java.lang.Thread.isDaemon() - */ -jboolean jthread_is_daemon(jthread thread); - IDATA jthread_set_priority(jthread thread, int priority); int jthread_get_priority(jthread thread); +jboolean jthread_is_daemon(jthread thread); /** * Sets the name for the thread. Index: include/open/thread_externals.h =================================================================== --- include/open/thread_externals.h (revision 454089) +++ include/open/thread_externals.h (working copy) @@ -1,9 +1,9 @@ - /* Licensed to the Apache Software Foundation (ASF) under one or more - /* contributor license agreements. See the NOTICE file distributed with - /* this work for additional information regarding copyright ownership. - /* The ASF licenses this file to You 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 +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 * @@ -72,13 +72,17 @@ VMEXPORT void *vm_jthread_get_tm_data(jthread thread); /** - * registtrate thread in VM, so it could execute Java - */ -VMEXPORT IDATA vm_attach(); + * Registrates current thread in VM, so it could execute Java + * + * @param[in] java_vm current thread will be attached to the specified VM + * @param[out] p_jni_env will point to JNI environment assocciated with the thread + */ +VMEXPORT jint vm_attach(JavaVM * java_vm, JNIEnv ** p_jni_env); + /** - * free java related resources before thread exit - */ -VMEXPORT IDATA vm_detach(); + * Frees java related resources before thread exit. + */ +VMEXPORT jint vm_detach(jthread java_thread); /** * creates exception object using given class name and message and throws it @@ -115,19 +119,12 @@ */ VMEXPORT int ti_is_enabled(); -/** - * get JNIEnv * - * @return JNIEnv * - */ -VMEXPORT JNIEnv * get_jnienv(void); - - #ifdef __cplusplus } /** - * all folowing entries is requiried for VM helpers only - */ + * all folowing entries is requiried for VM helpers only + */ #include "encoder.h" Index: include/open/vm.h =================================================================== --- include/open/vm.h (revision 454089) +++ include/open/vm.h (working copy) @@ -716,9 +716,6 @@ VMEXPORT Boolean vm_get_boolean_property_value_with_default(const char *property_name); -// Exit and perform the necessary cleanup. -VMEXPORT void vm_exit(int exit_code); - // end miscellaneous functions. ///////////////////////////////////////////////////////////////// Index: include/open/vm_util.h =================================================================== --- include/open/vm_util.h (revision 454089) +++ include/open/vm_util.h (working copy) @@ -46,8 +46,6 @@ // #include "object_layout.h" #include "vm_threads.h" -VMEXPORT void vm_exit(int exit_code); - unsigned sizeof_java_lang_class(); @@ -59,7 +57,7 @@ }; //VM_Global_State -extern struct JNIEnv_Internal *jni_native_intf; +extern JNIEnv * jni_native_intf; extern VTable *cached_object_array_vtable_ptr; @@ -162,17 +160,6 @@ long m_nInc; }; -class StaticInitializer { -public: - StaticInitializer() { - apr_initialize(); - } - ~StaticInitializer() { - apr_terminate2(); - } -}; - - /** * @brief Generates an VM's helper to invoke the provided function. * Index: interpreter/src/interpreter_ti.cpp =================================================================== --- interpreter/src/interpreter_ti.cpp (revision 454089) +++ interpreter/src/interpreter_ti.cpp (working copy) @@ -270,7 +270,7 @@ /* * Looks like no way to get JNIEnv from jvmtiEnv, strange. */ -static JNIEnv_Internal * UNUSED jvmti_test_jenv = get_jni_native_intf(); +static JNIEnv * UNUSED jvmti_test_jenv = get_jni_native_intf(); jvmtiError interpreter_ti_getStackTrace( Index: jitrino/src/vm/drl/DrlVMInterface.cpp =================================================================== --- jitrino/src/vm/drl/DrlVMInterface.cpp (revision 454089) +++ jitrino/src/vm/drl/DrlVMInterface.cpp (working copy) @@ -480,7 +480,7 @@ DrlVMCompilationInterface::hardAssert(const char *message, int line, const char *file) { ::std::cerr << message << " at line " << line << " of file " << file << ::std::endl; - vm_exit(1); + exit(1); } Type* Index: port/src/encoder/ia32_em64t/encoder.inl =================================================================== --- port/src/encoder/ia32_em64t/encoder.inl (revision 454089) +++ port/src/encoder/ia32_em64t/encoder.inl (working copy) @@ -597,14 +597,14 @@ ENCODER_DECLARE_EXPORT char * jump(char * stream, char * target) { #ifdef _EM64T_ int64 offset = target - stream; + // sub 2 bytes for the short version + offset -= 2; if (fit8(offset)) { - // sub 2 bytes for the short version - offset -= 2; // use 8-bit signed relative form return jump8(stream, Imm_Opnd(size_8, offset)); } else if (fit32(offset)) { - // sub 5 bytes for the long version - offset -= 5; + // sub 5 (3 + 2)bytes for the long version + offset -= 3; // use 32-bit signed relative form return jump32(stream, Imm_Opnd(size_32, offset)); } @@ -613,14 +613,14 @@ return jump(stream, rax_opnd, size_64); #else int32 offset = target - stream; + // sub 2 bytes for the short version + offset -= 2; if (fit8(offset)) { - // sub 2 bytes for the short version - offset -= 2; // use 8-bit signed relative form return jump8(stream, Imm_Opnd(size_8, offset)); } - // sub 5 bytes for the long version - offset -= 5; + // sub 5 (3 + 2) bytes for the long version + offset -= 3; // use 32-bit signed relative form return jump32(stream, Imm_Opnd(size_32, offset)); #endif Index: port/src/lil/em64t/pim/stack_iterator_em64t.cpp =================================================================== --- port/src/lil/em64t/pim/stack_iterator_em64t.cpp (revision 454089) +++ port/src/lil/em64t/pim/stack_iterator_em64t.cpp (working copy) @@ -216,8 +216,9 @@ StackIterator * si = (StackIterator *)STD_MALLOC(sizeof(StackIterator)); memset(si, 0, sizeof(StackIterator)); + Global_Env *env = VM_Global_State::loader_env; // Setup current frame - si->cci = vm_methods->find((NativeCodePtr)regs->rip, is_ip_past); + si->cci = env->vm_methods->find((NativeCodePtr)regs->rip, is_ip_past); assert(si->cci); init_context_from_registers(si->jit_frame_context, *regs, is_ip_past); @@ -257,7 +258,9 @@ si->cci->get_jit()->unwind_stack_frame(si->cci->get_method(), si_get_jit_context(si)); si->jit_frame_context.is_ip_past = TRUE; } - si->cci = vm_methods->find(si_get_ip(si), si_get_jit_context(si)->is_ip_past); + + Global_Env *vm_env = VM_Global_State::loader_env; + si->cci = vm_env->vm_methods->find(si_get_ip(si), si_get_jit_context(si)->is_ip_past); #ifndef NDEBUG if (si_is_native(si)) { TRACE2("si", "si_goto_previous to ip = " << (void*)si_get_ip(si) Index: port/src/lil/ia32/pim/stack_iterator_ia32.cpp =================================================================== --- port/src/lil/ia32/pim/stack_iterator_ia32.cpp (revision 454089) +++ port/src/lil/ia32/pim/stack_iterator_ia32.cpp (working copy) @@ -20,7 +20,7 @@ * @version $Revision$ */ - +#include "environment.h" #include "jit_intf_cpp.h" #include "m2n.h" #include "m2n_ia32_internal.h" @@ -268,9 +268,9 @@ memset(res, 0, sizeof(StackIterator)); // Setup current frame + Global_Env *env = VM_Global_State::loader_env; // It's possible that registers represent native code and res->cci==NULL - res->cci = vm_methods->find((NativeCodePtr)regs->eip, is_ip_past); - + res->cci = env->vm_methods->find((NativeCodePtr)regs->eip, is_ip_past); res->c.esp = regs->esp; res->c.p_eip = ®s->eip; res->c.p_ebp = ®s->ebp; @@ -316,7 +316,8 @@ if (!si->m2nfl) return; si_unwind_from_m2n(si, over_popped); } - si->cci = vm_methods->find(si_get_ip(si), si_get_jit_context(si)->is_ip_past); + Global_Env *vm_env = VM_Global_State::loader_env; + si->cci = vm_env->vm_methods->find(si_get_ip(si), si_get_jit_context(si)->is_ip_past); if (si->cci) { TRACE2("si", ("si_goto_previous to ip = %p (%s%s)", (void*)si_get_ip(si), @@ -519,7 +520,6 @@ inline static uint32 unref_reg(uint32* p_reg) { return p_reg ? *p_reg : 0; } - void si_copy_to_registers(StackIterator* si, Registers* regs) { ASSERT_NO_INTERPRETER Index: port/src/lil/ipf/pim/lil_code_generator_ipf.cpp =================================================================== --- port/src/lil/ipf/pim/lil_code_generator_ipf.cpp (revision 454089) +++ port/src/lil/ipf/pim/lil_code_generator_ipf.cpp (working copy) @@ -2089,7 +2089,7 @@ // initialization of static members -static StaticInitializer lil_initializer; +// TODO: we have to get rid of memory pool in static area due to initialization problems static tl::MemoryPool loc_mem; const LcgIpfLoc* LcgIpfCodeGen::gp = new(loc_mem) LcgIpfLoc(LLK_Gr, 1); const LcgIpfLoc* LcgIpfCodeGen::sp = new(loc_mem) LcgIpfLoc(LLK_Gr, 12); Index: port/src/lil/ipf/pim/stack_iterator_ipf.cpp =================================================================== --- port/src/lil/ipf/pim/stack_iterator_ipf.cpp (revision 454089) +++ port/src/lil/ipf/pim/stack_iterator_ipf.cpp (working copy) @@ -511,8 +511,9 @@ if (!si->m2nfl) return; si_unwind_from_m2n(si); } + Global_Env *env = VM_Global_State::loader_env; si->c.is_ip_past = TRUE; - si->cci = vm_methods->find(si_get_ip(si)); + si->cci = env->vm_methods->find(si_get_ip(si)); si_unwind_bsp(si); si_setup_stacked_registers(si); } Index: port/src/lil/lil.cpp =================================================================== --- port/src/lil/lil.cpp (revision 454089) +++ port/src/lil/lil.cpp (working copy) @@ -1309,7 +1309,7 @@ break; case LIT_StdPlaces: c->num_std_places = i->u.std_places; - for(j=0; jnum_locals; j++) c->std_place_types[j] = LT_Void; + for(j=0; jnum_std_places; j++) c->std_place_types[j] = LT_Void; break; case LIT_Alloc: c->amt_alloced += i->u.alloc.num_bytes; Index: thread/src/hythr.def =================================================================== --- thread/src/hythr.def (revision 454089) +++ thread/src/hythr.def (working copy) @@ -9,6 +9,7 @@ hythread_monitor_enter hythread_monitor_notify_all hythread_attach +hythread_attach_ex hythread_monitor_destroy hythread_monitor_num_waiting hythread_interrupted @@ -110,12 +111,14 @@ hymutex_destroy -hythread_wait_for_all_nondaemon_threads hythread_is_alive hythread_is_terminated hythread_init -countdown_nondaemon_threads -increase_nondaemon_threads_count +hythread_shutdown +hythread_lib_create +hythread_lib_destroy +hythread_lib_lock +hythread_lib_unlock release_start_lock acquire_start_lock Index: thread/src/hythr.exp =================================================================== --- thread/src/hythr.exp (revision 454089) +++ thread/src/hythr.exp (working copy) @@ -8,6 +8,7 @@ hythread_monitor_enter; hythread_monitor_notify_all; hythread_attach; +hythread_attach_ex; hythread_monitor_destroy; hythread_monitor_num_waiting; hythread_interrupted; @@ -121,11 +122,13 @@ hymutex_destroy; hythread_exit; -hythread_wait_for_all_nondaemon_threads; hythread_is_alive; hythread_init; -countdown_nondaemon_threads; -increase_nondaemon_threads_count; +hythread_shutdown; +hythread_lib_create; +hythread_lib_destroy; +hythread_lib_lock; +hythread_lib_unlock; set_safepoint_callback; release_start_lock; Index: thread/src/thread_init.c =================================================================== --- thread/src/thread_init.c (revision 454089) +++ thread/src/thread_init.c (working copy) @@ -33,11 +33,10 @@ //global constants: -//library instance -hythread_library_t hythread_lib; +// Global pointer to the threading library +hythread_library_t TM_LIBRARY = NULL; - //Thread manager memory pool apr_pool_t *TM_POOL = NULL; @@ -45,7 +44,6 @@ apr_threadkey_t *TM_THREAD_KEY; //Thread manager global lock -hymutex_t TM_LOCK = NULL; hymutex_t TM_START_LOCK = NULL; hymutex_t FAT_MONITOR_TABLE_LOCK = NULL; #define GLOBAL_MONITOR_NAME "global_monitor" @@ -60,9 +58,6 @@ IDATA groups_count; -IDATA nondaemon_thread_count; -hycond_t nondaemon_thread_cond; - static IDATA init_group_list(); static IDATA destroy_group_list(); @@ -70,18 +65,60 @@ #include BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpres) { if (dwReason == DLL_PROCESS_ATTACH) { - hythread_init (NULL); + hythread_lib_create(&TM_LIBRARY); } return TRUE; } #else void hythread_library_init(void) { - hythread_init(NULL); - + hythread_lib_create(&TM_LIBRARY); } #endif /** + * Creates and initializes a threading library. + * + * @param[out] lib pointer to the created thread library + * @return The thead library's initStatus will be set to 0 on success or + * a negative value on failure. + * + * @see hythread_attach, hythread_shutdown + */ +IDATA VMCALL hythread_lib_create(hythread_library_t * lib) { + apr_status_t apr_status; + + // Current implementation doesn't support more than one library instance. + if (TM_LIBRARY) { + *lib = TM_LIBRARY; + return TM_ERROR_NONE; + } + + apr_status = apr_initialize(); + assert(apr_status == APR_SUCCESS); + + apr_status = apr_pool_create(&TM_POOL, NULL); + if (apr_status != APR_SUCCESS) return CONVERT_ERROR(apr_status); + + *lib = (hythread_library_t) apr_palloc(TM_POOL, sizeof(HyThreadLibrary)); + if (*lib == NULL) return TM_ERROR_OUT_OF_MEMORY; + + hythread_init(*lib); + return TM_ERROR_NONE; +} + +/** + * Shut down the threading library. + * + * @param lib the library + * @return none + * + * @see hythread_lib_create + */ +void VMCALL hythread_lib_destroy(hythread_library_t lib) { + apr_pool_destroy(TM_POOL); +} + +/** * Initialize a threading library. * * @note This must only be called once. @@ -96,23 +133,33 @@ * @see hythread_attach, hythread_shutdown */ void VMCALL hythread_init(hythread_library_t lib){ - apr_status_t apr_status; + apr_status_t apr_status; IDATA status; hythread_monitor_t *mon; - // check the someone already init the library - if(TM_LOCK) { - return; - } + + // Current implementation doesn't support more than one library instance. + if (TM_LIBRARY == NULL) { + TM_LIBRARY = lib; + } + assert(TM_LIBRARY == lib); + + // Check if someone already initialized the library. + if (TM_START_LOCK != NULL) { + return; + } apr_status = apr_initialize(); assert(apr_status == APR_SUCCESS); - apr_status = apr_pool_create(&TM_POOL, NULL); - assert(apr_status == APR_SUCCESS); + // TM_POOL will be NULL if hythread_lib_create was not used to create the library + if (TM_POOL == NULL) { + apr_status = apr_pool_create(&TM_POOL, NULL); + assert(apr_status == APR_SUCCESS); + } apr_status = apr_threadkey_private_create(&TM_THREAD_KEY, NULL, TM_POOL); assert(apr_status == APR_SUCCESS); - status = hymutex_create(&TM_LOCK, TM_MUTEX_NESTED); + status = hymutex_create(&lib->TM_LOCK, TM_MUTEX_NESTED); assert (status == TM_ERROR_NONE); status = hymutex_create(&TM_START_LOCK, TM_MUTEX_NESTED); assert (status == TM_ERROR_NONE); @@ -128,8 +175,8 @@ //nondaemon thread barrier //// - nondaemon_thread_count = 0; - status = hycond_create(&nondaemon_thread_cond); + lib->nondaemon_thread_count = 0; + status = hycond_create(&lib->nondaemon_thread_cond); assert (status == TM_ERROR_NONE); lock_table = (hythread_monitor_t *)malloc(sizeof(hythread_monitor_t)*table_size); @@ -152,96 +199,51 @@ * * @see hythread_init */ -IDATA VMCALL hythread_shutdown(){ - IDATA status; - apr_status_t apr_status; - if (destroy_group_list() == TM_ERROR_NONE) { - status=hymutex_destroy(TM_LOCK); - if (status != TM_ERROR_NONE) return status; - status=hymutex_destroy(TM_START_LOCK); - if (status != TM_ERROR_NONE) return status; - apr_status=apr_threadkey_private_delete(TM_THREAD_KEY); - if (apr_status != APR_SUCCESS) return CONVERT_ERROR(apr_status); - apr_pool_destroy(TM_POOL); - return TM_ERROR_NONE; - } - return TM_ERROR_RUNNING_THREADS; +void VMCALL hythread_shutdown() { + hythread_lib_destroy(hythread_self()->library); } + /** - * Acquires the lock over threading subsystem. - * - * The lock blocks new thread creation and thread exit operations. + * Acquires global lock of the library assocciated with the current thread. + * + * @param[in] self current thread */ -IDATA VMCALL hythread_global_lock() { - return hymutex_lock(TM_LOCK); +void VMCALL hythread_lib_lock(hythread_t self) { + IDATA status; + + assert(self == hythread_self()); + status = hymutex_lock(self->library->TM_LOCK); + assert(status == TM_ERROR_NONE); } /** - * Releases the lock over threading subsystem. - * + * Releases global lock of the library assocciated with the current thread. + * + * @param[in] self current thread */ -IDATA VMCALL hythread_global_unlock() { - return hymutex_unlock(TM_LOCK); -} - - -IDATA increase_nondaemon_threads_count() { +void VMCALL hythread_lib_unlock(hythread_t self) { IDATA status; - - status = hymutex_lock(TM_LOCK); - if (status != TM_ERROR_NONE) return status; - nondaemon_thread_count++; - status = hymutex_unlock(TM_LOCK); - return status; + assert(self == hythread_self()); + status = hymutex_unlock(self->library->TM_LOCK); + assert(status == TM_ERROR_NONE); } -IDATA countdown_nondaemon_threads() { - IDATA status; - - status = hymutex_lock(TM_LOCK); - if (status != TM_ERROR_NONE) return status; - - if(nondaemon_thread_count <= 0) { - status = hymutex_unlock(TM_LOCK); - if (status != TM_ERROR_NONE) return status; - return TM_ERROR_ILLEGAL_STATE; - } - TRACE(("TM: nondaemons decreased, thread: %p count: %d", tm_self_tls, nondaemon_thread_count)); - nondaemon_thread_count--; - if(nondaemon_thread_count == 0) { - status = hycond_notify_all(nondaemon_thread_cond); - TRACE(("TM: nondaemons all dead, thread: %p count: %d", tm_self_tls, nondaemon_thread_count)); - if (status != TM_ERROR_NONE){ - hymutex_unlock(TM_LOCK); - return status; - } - } - - status = hymutex_unlock(TM_LOCK); - return status; +/** + * Acquires the lock over threading subsystem. + * + * The lock blocks new thread creation and thread exit operations. + */ +IDATA VMCALL hythread_global_lock() { + return hymutex_lock(TM_LIBRARY->TM_LOCK); } + /** - * waiting all nondaemon thread's + * Releases the lock over threading subsystem. * */ -IDATA VMCALL hythread_wait_for_all_nondaemon_threads() { - IDATA status; - - status = hymutex_lock(TM_LOCK); - if (status != TM_ERROR_NONE) return status; - - while (nondaemon_thread_count) { - status = hycond_wait(nondaemon_thread_cond, TM_LOCK); - //check interruption and other problems - TRACE(("TM wait for nondaemons notified, count: %d", nondaemon_thread_count)); - if(status != TM_ERROR_NONE) { - hymutex_unlock(TM_LOCK); - return status; - } - } - status = hymutex_unlock(TM_LOCK); - return status; +IDATA VMCALL hythread_global_unlock() { + return hymutex_unlock(TM_LIBRARY->TM_LOCK);; } hythread_group_t get_java_thread_group(void){ @@ -297,7 +299,6 @@ return hymutex_unlock(TM_START_LOCK); } - /* // very simple Map implementation // current scenario use only one global so it works well @@ -350,8 +351,7 @@ * 0 on failure. * */ -UDATA* -VMCALL hythread_global (char* name) { +UDATA* VMCALL hythread_global (char* name) { //hythread_monitor_enter(*p_global_monitor); int index = find_entry(name); if(index == -1) { Index: thread/src/thread_java_attrs.c =================================================================== --- thread/src/thread_java_attrs.c (revision 454089) +++ thread/src/thread_java_attrs.c (working copy) @@ -51,3 +51,15 @@ hythread_t tm_native_thread = jthread_get_native_thread(java_thread); return hythread_set_priority(tm_native_thread, priority); } + +/** + * Returns daemon status for the specified thread. + * + * @param[in] java_thread thread those attribute is read + */ +jboolean jthread_is_daemon(jthread thread) { + jvmti_thread_t jvmti_thread; + + jvmti_thread = hythread_get_private_data(hythread_self()); + return jvmti_thread->daemon; +} Index: thread/src/thread_java_basic.c =================================================================== --- thread/src/thread_java_basic.c (revision 454089) +++ thread/src/thread_java_basic.c (working copy) @@ -27,6 +27,7 @@ #include #include +#include "open/thread_externals.h" #include "thread_private.h" #include "jni.h" @@ -35,18 +36,19 @@ void stop_callback(void); jmethodID getRunMethod(JNIEnv *env); +IDATA increase_nondaemon_threads_count(hythread_t self); +IDATA countdown_nondaemon_threads(hythread_t self); typedef struct { - JNIEnv *jenv; - jthread thread; + JavaVM * java_vm; jboolean daemon; - jvmtiEnv *tiEnv; - jvmtiStartFunction tiProc; - void *tiProcArgs; + jvmtiEnv *tiEnv; + jvmtiStartFunction tiProc; + void *tiProcArgs; } wrapper_proc_data; -IDATA associate_native_and_java_thread(JNIEnv* env, jthread java_thread, hythread_t tm_native_thread, jobject thread_ref); +IDATA associate_native_and_java_thread(JNIEnv* env, jthread java_thread, hythread_t tm_native_thread, jobject thread_ref); /** * Creates new Java thread. @@ -54,70 +56,60 @@ * The newly created thread will immediately start to execute the run() * method of the appropriate thread object. * - * @param[in] env JNI environment that will be associated with the created Java thread + * @param[in] jni_env jni environment for the current thread. * @param[in] java_thread Java thread object with which new thread must be associated. * @param[in] attrs thread attributes. * @sa java.lang.Thread.run() */ -IDATA jthread_create(JNIEnv* env, jthread java_thread, jthread_threadattr_t *attrs) { +IDATA jthread_create(JNIEnv * jni_env, jthread java_thread, jthread_threadattr_t *attrs) { - IDATA status; - status = jthread_create_with_function(env,java_thread,attrs,NULL,NULL); - return status; + return jthread_create_with_function(jni_env, java_thread, attrs, NULL, NULL); } int wrapper_proc(void *arg) { - - IDATA status,status1; + IDATA status; + JNIEnv * jni_env; + hythread_t native_thread; + jvmti_thread_t jvmti_thread; + jthread java_thread; wrapper_proc_data *data = (wrapper_proc_data *)arg; - JNIEnv *env = data->jenv; - jvmtiEnv *tiEnv = data->tiEnv; - jvmtiStartFunction tiProc = data->tiProc; - void *tiProcArgs = data->tiProcArgs; + + // Assocciation should be already done. + native_thread = hythread_self(); + jvmti_thread = hythread_get_private_data(native_thread); + assert(jvmti_thread); + java_thread = jvmti_thread->thread_object; - TRACE(("TM: Java thread started: id=%d OS_handle=%p", hythread_self()->thread_id, apr_os_thread_current())); - //status = hythread_global_lock(); - //assert (status == TM_ERROR_NONE); - status=vm_attach(); - if(status!=TM_ERROR_NONE) - { - if (!data->daemon){ - status1 = countdown_nondaemon_threads(); - assert (status1 == TM_ERROR_NONE); - } - return status; + status = vm_attach(data->java_vm, &jni_env); + if (status != JNI_OK) return TM_ERROR_INTERNAL; + + jvmti_thread->jenv = jni_env; + jvmti_thread->daemon = data->daemon; + + if (!jvmti_thread->daemon) { + increase_nondaemon_threads_count(native_thread); } + + TRACE(("TM: Java thread started: id=%d OS_handle=%p", native_thread->thread_id, apr_os_thread_current())); + + // Send Thread Start event. jvmti_send_thread_start_end_event(1); - //status = hythread_global_unlock(); - // assert (status == TM_ERROR_NONE); - if(tiProc!=NULL) - { - tiProc(tiEnv, env, tiProcArgs); - } - else - { - (*env) -> CallVoidMethodA(env, data->thread, getRunMethod(env), NULL);//for jthread_create(); - } - jvmti_send_thread_start_end_event(0); - (*env) -> DeleteGlobalRef(env, data->thread); - TRACE(("TM: Java thread finished: id=%d OS_handle=%p", hythread_self()->thread_id, apr_os_thread_current())); - assert(hythread_is_suspend_enabled()); - status=vm_detach(); - if(status!=TM_ERROR_NONE) + if(data->tiProc != NULL) { - if (!data->daemon){ - status1 = countdown_nondaemon_threads(); - assert (status1 == TM_ERROR_NONE); - } - return status; + data->tiProc(data->tiEnv, jni_env, data->tiProcArgs); } - assert(hythread_is_suspend_enabled()); - if (!data->daemon){ - status = countdown_nondaemon_threads(); - assert (status == TM_ERROR_NONE); - } - return TM_ERROR_NONE; + else + { + // for jthread_create(); + (*jni_env) -> CallVoidMethodA(jni_env, java_thread, getRunMethod(jni_env), NULL); + } + + status = jthread_detach(java_thread); + + TRACE(("TM: Java thread finished: id=%d OS_handle=%p", native_thread->thread_id, apr_os_thread_current())); + + return status; } /** @@ -129,72 +121,57 @@ * This method of thread creation would be useful for creating TI agent threads (i.e. Java threads * which always execute only native code). * - * @param[in] env JNI environment that will be associated with the created Java thread + * @param[in] jni_env jni environment for the current thread. * @param[in] java_thread Java thread object with which new thread must be associated. * @param[in] attrs thread attributes. * @param[in] proc the start function to be executed in this thread. * @param[in] arg The argument to the start function. Is passed as an array. * @sa JVMTI::RunAgentThread() */ -IDATA jthread_create_with_function(JNIEnv *env, jthread java_thread, jthread_threadattr_t *attrs,jvmtiStartFunction proc, const void* arg) +IDATA jthread_create_with_function(JNIEnv * jni_env, jthread java_thread, jthread_threadattr_t *attrs, jvmtiStartFunction proc, const void* arg) { - hythread_t tm_native_thread = NULL; - jvmti_thread_t tm_java_thread = NULL; - wrapper_proc_data *data; - IDATA status; - apr_status_t apr_status; - apr_pool_t * pool; - - if (env == NULL || java_thread == NULL || attrs == NULL){ - return TM_ERROR_NULL_POINTER; + hythread_t tm_native_thread = NULL; + jvmti_thread_t tm_java_thread; + wrapper_proc_data * data; + IDATA status; + + if (jni_env == NULL || java_thread == NULL || attrs == NULL) { + return TM_ERROR_NULL_POINTER; + } + tm_native_thread = vm_jthread_get_tm_data(java_thread); + + // This is for irregular use. In ordinary live valid jthread instance + // contains weak reference associated with it and native thread to reuse. + if (tm_native_thread == NULL) { + if( !jthread_thread_init(NULL, jni_env, java_thread, NULL, 0)) { + return TM_ERROR_OUT_OF_MEMORY; } - tm_native_thread = vm_jthread_get_tm_data(java_thread); - - //This is for irregular use. In ordinary live valid jthread instance - //contains weak reference associated with it and native thread to reuse - //if any - //// + tm_native_thread = vm_jthread_get_tm_data(java_thread); + } - if (tm_native_thread==NULL) - { - if(!jthread_thread_init(NULL,env,java_thread, NULL, 0)) - { - return TM_ERROR_OUT_OF_MEMORY; - } - tm_native_thread = vm_jthread_get_tm_data(java_thread); - } tm_java_thread = hythread_get_private_data(tm_native_thread); - assert(tm_java_thread); - apr_status = apr_pool_create(&pool, 0); - if (apr_status != APR_SUCCESS) { - return CONVERT_ERROR(apr_status); - } - data = apr_palloc(pool, sizeof(wrapper_proc_data)); - if(data == NULL) { - return TM_ERROR_OUT_OF_MEMORY; - } + assert(tm_java_thread); + data = apr_palloc(tm_java_thread->pool, sizeof(wrapper_proc_data)); + if (data == NULL) { + return TM_ERROR_OUT_OF_MEMORY; + } + // Prepare argumets for wrapper proc - data->jenv = env; - data->thread = tm_java_thread->thread_object; + status = (*jni_env) -> GetJavaVM(jni_env, &data->java_vm); + if (status != JNI_OK) return TM_ERROR_INTERNAL; + data->daemon = attrs->daemon; - data->tiEnv = attrs->jvmti_env; + data->tiEnv = attrs->jvmti_env; data->tiProc = proc; data->tiProcArgs = (void *)arg; - // create native thread with wrapper_proc - if (!attrs->daemon){ - status = increase_nondaemon_threads_count(); - if (status != TM_ERROR_NONE) return status; - } - status = hythread_create(&tm_native_thread, (attrs->stacksize)?attrs->stacksize:1024000, - attrs->priority, 0, wrapper_proc, data); - if ((!attrs->daemon)&&(status != TM_ERROR_NONE)){ - countdown_nondaemon_threads(); - } + status = hythread_create(&tm_native_thread, (attrs->stacksize)?attrs->stacksize:1024000, + attrs->priority, 0, wrapper_proc, data); + TRACE(("TM: Created thread: id=%d", tm_native_thread->thread_id)); - return status; + return status; } /** @@ -204,30 +181,39 @@ * and associate it with the current native thread. Nothing happens * if this thread is already attached. * - * @param[in] env JNI environment that will be associated with the attached Java thread - * @param[in] java_thread Java thread object with which the current native thread must be associated. + * @param[in] jni_env JNI environment for cuurent thread + * @param[in] java_thread j.l.Thread instance to associate with current thread + * @param[in] daemon JNI_TRUE if attaching thread is a daemon thread, JNI_FALSE overwise * @sa JNI::AttachCurrentThread () */ -IDATA jthread_attach(JNIEnv* env, jthread java_thread) { - +IDATA jthread_attach(JNIEnv * jni_env, jthread java_thread, jboolean daemon) { hythread_t tm_native_thread; + jvmti_thread_t jvmti_thread; IDATA status; - status = hythread_attach(NULL); - if (status != TM_ERROR_NONE){ - return status; + + // Do nothing if thread already attached. + if (jthread_self() != NULL) return TM_ERROR_NONE; + + tm_native_thread = hythread_self(); + assert(tm_native_thread); + + status = associate_native_and_java_thread(jni_env, java_thread, tm_native_thread, NULL); + if (status != TM_ERROR_NONE) return status; + + jvmti_thread = hythread_get_private_data(tm_native_thread); + assert(jvmti_thread); + jvmti_thread->jenv = jni_env; + jvmti_thread->daemon = daemon; + + if (!jvmti_thread->daemon) { + increase_nondaemon_threads_count(tm_native_thread); } - tm_native_thread = hythread_self(); - //I wonder if we need it. - //since jthread already created, thus association is already done, - //see jthread_init - //VVVVVVVVVVVVVVVVVVVVVV - status=associate_native_and_java_thread(env, java_thread, tm_native_thread, NULL); - if (status != TM_ERROR_NONE){ - return status; - } + + // Send Thread Start event. + jvmti_send_thread_start_end_event(1); + TRACE(("TM: Current thread attached to jthread=%p", java_thread)); - status=vm_attach(); - return status; + return TM_ERROR_NONE; } /** @@ -243,25 +229,24 @@ jlong jthread_thread_init(jvmti_thread_t *ret_thread, JNIEnv* env, jthread java_thread, jobject weak_ref, jlong old_thread) { hythread_t tm_native_thread = NULL; jvmti_thread_t tmj_thread; - IDATA status; + IDATA status; if (old_thread) { tm_native_thread = (hythread_t)((IDATA)old_thread); tmj_thread = (jvmti_thread_t)hythread_get_private_data(tm_native_thread); //delete used weak reference - if (tmj_thread->thread_ref) (*env)->DeleteGlobalRef(env, tmj_thread->thread_ref); - + if (tmj_thread->thread_ref) (*env)->DeleteGlobalRef(env, tmj_thread->thread_ref); } - status = hythread_struct_init(&tm_native_thread, NULL); - if(status != TM_ERROR_NONE) - { - return 0; - } - status=associate_native_and_java_thread(env, java_thread, tm_native_thread, weak_ref); - if(status != TM_ERROR_NONE) - { - return 0; - } + + status = hythread_struct_init(&tm_native_thread); + if (status != TM_ERROR_NONE) { + return 0; + } + + status = associate_native_and_java_thread(env, java_thread, tm_native_thread, weak_ref); + if (status != TM_ERROR_NONE) { + return 0; + } return (jlong)((IDATA)tm_native_thread); } @@ -273,66 +258,73 @@ * @param[in] java_thread Java thread to be detached */ IDATA jthread_detach(jthread java_thread) { - jvmti_thread_t tm_java_thread; + IDATA status; hythread_t tm_native_thread; + jvmti_thread_t tm_jvmti_thread; + JNIEnv * jni_env; + + assert(hythread_is_suspend_enabled()); - // Check input arg + // Check input arg assert(java_thread); - TRACE(("TM: jthread_detach %x", hythread_self())); + TRACE(("TM: jthread_detach %x", hythread_self())); - tm_native_thread = vm_jthread_get_tm_data(java_thread); - tm_java_thread = hythread_get_private_data(tm_native_thread); + tm_native_thread = jthread_get_native_thread(java_thread); + tm_jvmti_thread = hythread_get_private_data(tm_native_thread); + jni_env = tm_jvmti_thread->jenv; - // Remove tm_thread_t pointer from java.lang.Thread object - vm_jthread_set_tm_data(java_thread, NULL); - - vm_detach(); + if (!tm_jvmti_thread->daemon){ + countdown_nondaemon_threads(tm_native_thread); + } - // Deallocate tm_java_thread - apr_pool_destroy(tm_java_thread->pool); + // Send Thread End event + jvmti_send_thread_start_end_event(0); - // Remove tm_jthread_t pointer from *tm_native_thread - /* - status = hythread_set_private_data(tm_native_thread, NULL); - if (status != TM_ERROR_NONE){ - return status; - }*/ - assert(hythread_is_suspend_enabled()); + // Detach from VM. + status = vm_detach(java_thread); + if (status != JNI_OK) return TM_ERROR_INTERNAL; + + // Delete global reference to current thread object. + (*jni_env)->DeleteGlobalRef(jni_env, tm_jvmti_thread->thread_object); + // jthread_self() will return NULL now. + tm_jvmti_thread->thread_object = NULL; + + + // Deallocate tm_jvmti_thread + //apr_pool_destroy(tm_jvmti_thread->pool); + + assert(hythread_is_suspend_enabled()); return TM_ERROR_NONE; } -IDATA associate_native_and_java_thread(JNIEnv* env, jthread java_thread, hythread_t tm_native_thread, jobject thread_ref) +IDATA associate_native_and_java_thread(JNIEnv * jni_env, jthread java_thread, hythread_t tm_native_thread, jobject thread_ref) { - IDATA status; + IDATA status; apr_status_t apr_status; apr_pool_t *pool; - jvmti_thread_t tm_java_thread; - if ((env == NULL) || (java_thread == NULL)||(tm_native_thread==NULL)){ + jvmti_thread_t tm_java_thread; + + if ((jni_env == NULL) || (java_thread == NULL) || (tm_native_thread == NULL)) { return TM_ERROR_NULL_POINTER; } - tm_java_thread = hythread_get_private_data(tm_native_thread); if (!tm_java_thread) { apr_status = apr_pool_create(&pool, 0); - if (apr_status != APR_SUCCESS) return CONVERT_ERROR(apr_status); - if (pool==NULL) return TM_ERROR_OUT_OF_MEMORY; + if (apr_status != APR_SUCCESS) return CONVERT_ERROR(apr_status); + if (pool == NULL) return TM_ERROR_OUT_OF_MEMORY; tm_java_thread = apr_palloc(pool, sizeof(JVMTIThread)); - if(tm_java_thread == NULL) { - return TM_ERROR_OUT_OF_MEMORY; - } + if (tm_java_thread == NULL) return TM_ERROR_OUT_OF_MEMORY; tm_java_thread->pool = pool; status = hythread_set_private_data(tm_native_thread, tm_java_thread); - if (status != TM_ERROR_NONE){ - return status; - } + if (status != TM_ERROR_NONE) return status; } - - tm_java_thread->jenv = env; - tm_java_thread->thread_object = (*env)->NewGlobalRef(env,java_thread); - tm_java_thread->thread_ref = (thread_ref)?(*env)->NewGlobalRef(env, thread_ref):NULL; + // JNI environment is created when this thread attaches to VM. + tm_java_thread->jenv = NULL; + tm_java_thread->thread_object = (*jni_env)->NewGlobalRef(jni_env, java_thread); + tm_java_thread->thread_ref = (thread_ref) ? (*jni_env)->NewGlobalRef(jni_env, thread_ref) : NULL; tm_java_thread->contended_monitor = 0; tm_java_thread->wait_monitor = 0; tm_java_thread->owned_monitors = 0; @@ -343,7 +335,7 @@ // Associate java_thread with tm_thread vm_jthread_set_tm_data(java_thread, tm_native_thread); - return TM_ERROR_NONE; + return TM_ERROR_NONE; } /** @@ -355,18 +347,17 @@ * @sa java.lang.Thread.join() */ IDATA jthread_join(jthread java_thread) { - + IDATA status; hythread_t tm_native_thread; - IDATA status; - - if (java_thread == NULL){ - return TM_ERROR_NULL_POINTER; - } + + if (java_thread == NULL) { + return TM_ERROR_NULL_POINTER; + } tm_native_thread = jthread_get_native_thread(java_thread); status = hythread_join_interruptable(tm_native_thread, 0, 0); TRACE(("TM: jthread %d joined %d", hythread_self()->thread_id, tm_native_thread->thread_id)); - - return status; + + return status; } /** @@ -488,17 +479,20 @@ IDATA status; tm_native_thread->state &= ~TM_THREAD_STATE_RUNNABLE; - tm_native_thread->state |= TM_THREAD_STATE_WAITING | TM_THREAD_STATE_SLEEPING | - TM_THREAD_STATE_WAITING_WITH_TIMEOUT; + tm_native_thread->state |= TM_THREAD_STATE_WAITING | TM_THREAD_STATE_SLEEPING | + TM_THREAD_STATE_WAITING_WITH_TIMEOUT; status = hythread_sleep_interruptable(millis, nanos); +#ifndef NDEBUG + if (status == TM_ERROR_INTERRUPT) { + TRACE(("TM: sleep interrupted status received, thread: %p", hythread_self())); + } +#endif + + tm_native_thread->state &= ~(TM_THREAD_STATE_WAITING | TM_THREAD_STATE_SLEEPING | + TM_THREAD_STATE_WAITING_WITH_TIMEOUT); - tm_native_thread->state &= ~(TM_THREAD_STATE_WAITING | TM_THREAD_STATE_SLEEPING | - TM_THREAD_STATE_WAITING_WITH_TIMEOUT); tm_native_thread->state |= TM_THREAD_STATE_RUNNABLE; - if (status == TM_ERROR_INTERRUPT) { - TRACE(("TM: sleep interrupted status received, thread: %p", hythread_self())); - } return status; } @@ -511,21 +505,20 @@ * @param[in] java_thread java.lang.Thread object */ JNIEnv *jthread_get_JNI_env(jthread java_thread) { + hythread_t tm_native_thread; + jvmti_thread_t tm_java_thread; - hythread_t tm_native_thread; - jvmti_thread_t tm_java_thread; - - if (java_thread == NULL){ + if (java_thread == NULL) { return NULL; - } - tm_native_thread = jthread_get_native_thread(java_thread); - if (tm_native_thread == NULL){ + } + tm_native_thread = jthread_get_native_thread(java_thread); + if (tm_native_thread == NULL) { return NULL; - } - tm_java_thread = hythread_get_private_data(tm_native_thread); - if (tm_java_thread == NULL){ + } + tm_java_thread = hythread_get_private_data(tm_native_thread); + if (tm_java_thread == NULL) { return NULL; - } + } return tm_java_thread->jenv; } /** @@ -540,11 +533,11 @@ jlong jthread_get_id(jthread java_thread) { hythread_t tm_native_thread; - - tm_native_thread = jthread_get_native_thread(java_thread); + + tm_native_thread = jthread_get_native_thread(java_thread); assert(tm_native_thread); - - return hythread_get_id(tm_native_thread); + + return hythread_get_id(tm_native_thread); } /** @@ -554,19 +547,19 @@ * @return jthread for the given ID, or NULL if there are no such. */ jthread jthread_get_thread(jlong thread_id) { - - hythread_t tm_native_thread; - jvmti_thread_t tm_java_thread; - jthread java_thread; + hythread_t tm_native_thread; + jvmti_thread_t tm_java_thread; + jthread java_thread; + tm_native_thread = hythread_get_thread((jint)thread_id); - if (tm_native_thread == NULL){ + if (tm_native_thread == NULL) { return NULL; - } - tm_java_thread = hythread_get_private_data(tm_native_thread); - java_thread = tm_java_thread->thread_object; + } + tm_java_thread = hythread_get_private_data(tm_native_thread); + java_thread = tm_java_thread->thread_object; assert(java_thread); - return java_thread; + return java_thread; } /** @@ -575,9 +568,8 @@ * @return native thread */ hythread_t jthread_get_native_thread(jthread thread) { - - assert(thread); - + + assert(thread); return vm_jthread_get_tm_data(thread); } @@ -587,19 +579,19 @@ * @return Java thread */ jthread jthread_get_java_thread(hythread_t tm_native_thread) { + + jvmti_thread_t tm_java_thread; - jvmti_thread_t tm_java_thread; - - if (tm_native_thread == NULL){ + if (tm_native_thread == NULL) { TRACE(("TM: native thread is NULL")); return NULL; - } - tm_java_thread = hythread_get_private_data(tm_native_thread); + } + tm_java_thread = hythread_get_private_data(tm_native_thread); - if (tm_java_thread == NULL){ + if (tm_java_thread == NULL) { TRACE(("TM: tmj thread is NULL")); return NULL; - } + } return tm_java_thread->thread_object; } @@ -610,7 +602,6 @@ * or NULL if the current native thread is not attached to JVM. */ jthread jthread_self(void) { - return jthread_get_java_thread(hythread_self()); } @@ -622,6 +613,42 @@ return hythread_cancel_all(NULL); } +/** + * waiting all nondaemon thread's + * + */ +IDATA VMCALL jthread_wait_for_all_nondaemon_threads() { + hythread_t native_thread; + jvmti_thread_t jvmti_thread; + hythread_library_t lib; + IDATA status; + + native_thread = hythread_self(); + jvmti_thread = hythread_get_private_data(native_thread); + lib = native_thread->library; + + status = hymutex_lock(lib->TM_LOCK); + if (status != TM_ERROR_NONE) return status; + + if (lib->nondaemon_thread_count == 1 && !jvmti_thread->daemon) { + status = hymutex_unlock(lib->TM_LOCK); + return status; + } + + while (lib->nondaemon_thread_count) { + status = hycond_wait(lib->nondaemon_thread_cond, lib->TM_LOCK); + //check interruption and other problems + TRACE(("TM wait for nondaemons notified, count: %d", nondaemon_thread_count)); + if(status != TM_ERROR_NONE) { + hymutex_unlock(lib->TM_LOCK); + return status; + } + } + + status = hymutex_unlock(lib->TM_LOCK); + return status; +} + /* * Auxiliary function to throw java.lang.InterruptedException */ @@ -631,29 +658,74 @@ jvmti_thread_t tm_java_thread; hythread_t tm_native_thread; jclass clazz; - JNIEnv *env; - TRACE(("interrupted_exception thrown")); + JNIEnv *env; + + TRACE(("interrupted_exception thrown")); tm_native_thread = hythread_self(); tm_java_thread = hythread_get_private_data(tm_native_thread); - env = tm_java_thread->jenv; - clazz = (*env) -> FindClass(env, "java/lang/InterruptedException"); - (*env) -> ThrowNew(env, clazz, "Park() is interrupted"); + env = tm_java_thread->jenv; + clazz = (*env) -> FindClass(env, "java/lang/InterruptedException"); + (*env) -> ThrowNew(env, clazz, "Park() is interrupted"); } jmethodID getRunMethod(JNIEnv *env) { jclass clazz; static jmethodID run_method = NULL; - IDATA status; + IDATA status; status=acquire_start_lock(); - assert (status == TM_ERROR_NONE); + assert (status == TM_ERROR_NONE); //printf("run method find enter\n"); if (!run_method) { clazz = (*env) -> FindClass(env, "java/lang/Thread"); - run_method = (*env) -> GetMethodID(env, clazz, "runImpl", "()V"); + run_method = (*env) -> GetMethodID(env, clazz, "run", "()V"); } status=release_start_lock(); //printf("run method find exit\n"); assert (status == TM_ERROR_NONE); return run_method; } + +IDATA increase_nondaemon_threads_count(hythread_t self) { + hythread_library_t lib; + IDATA status; + + lib = self->library; + + status = hymutex_lock(lib->TM_LOCK); + if (status != TM_ERROR_NONE) return status; + + lib->nondaemon_thread_count++; + status = hymutex_unlock(lib->TM_LOCK); + return status; +} + +IDATA countdown_nondaemon_threads(hythread_t self) { + hythread_library_t lib; + IDATA status; + + lib = self->library; + + status = hymutex_lock(lib->TM_LOCK); + if (status != TM_ERROR_NONE) return status; + + if(lib->nondaemon_thread_count <= 0) { + status = hymutex_unlock(lib->TM_LOCK); + if (status != TM_ERROR_NONE) return status; + return TM_ERROR_ILLEGAL_STATE; + } + + TRACE(("TM: nondaemons decreased, thread: %p count: %d", self, lib->nondaemon_thread_count)); + lib->nondaemon_thread_count--; + if(lib->nondaemon_thread_count == 0) { + status = hycond_notify_all(lib->nondaemon_thread_cond); + TRACE(("TM: nondaemons all dead, thread: %p count: %d", self, lib->nondaemon_thread_count)); + if (status != TM_ERROR_NONE){ + hymutex_unlock(lib->TM_LOCK); + return status; + } + } + + status = hymutex_unlock(lib->TM_LOCK); + return status; +} Index: thread/src/thread_native_attrs.c =================================================================== --- thread/src/thread_native_attrs.c (revision 454089) +++ thread/src/thread_native_attrs.c (working copy) @@ -46,7 +46,7 @@ */ IDATA VMCALL hythread_set_priority(hythread_t thread, UDATA priority){ apr_status_t apr_status = apr_thread_set_priority(thread->os_handle, priority); - if (apr_status != APR_SUCCESS) return CONVERT_ERROR(apr_status); + if (apr_status != APR_SUCCESS) return CONVERT_ERROR(apr_status); thread->priority = priority; return TM_ERROR_NONE; } Index: thread/src/thread_native_basic.c =================================================================== --- thread/src/thread_native_basic.c (revision 454089) +++ thread/src/thread_native_basic.c (working copy) @@ -31,10 +31,19 @@ #include #include "thread_private.h" +typedef struct { + hythread_t thread; + hythread_group_t group; + hythread_entrypoint_t start_proc; + void * start_proc_args; +} thread_start_proc_data; + extern hythread_group_t TM_DEFAULT_GROUP; +extern hythread_library_t TM_LIBRARY; static void* APR_THREAD_FUNC thread_start_proc(apr_thread_t* thd, void *p_args); -static hythread_t init_thread(hythread_group_t group); +static hythread_t allocate_thread(); static void reset_thread(hythread_t thread); +static IDATA register_to_group(hythread_t thread, hythread_group_t group); //#define APR_TLS_USE 1 #define NAKED __declspec( naked ) @@ -51,6 +60,7 @@ #define MAX_ID 1000000 hythread_t fast_thread_array[MAX_ID]; int next_id = 1; + /* IDATA add_to_fast_thread_array(hythread_t thread,int id) { @@ -87,18 +97,21 @@ IDATA VMCALL hythread_create_with_group(hythread_t *ret_thread, hythread_group_t group, UDATA stacksize, UDATA priority, UDATA suspend, hythread_entrypoint_t func, void *data) { apr_threadattr_t *apr_attrs; hythread_t new_thread; + thread_start_proc_data * start_proc_data; apr_status_t apr_status; - if (!ret_thread || !(*ret_thread)) { - // Allocate & init thread structure - new_thread = init_thread(group); - if(new_thread==NULL){ - return TM_ERROR_OUT_OF_MEMORY; - } + if (ret_thread) { + hythread_struct_init(ret_thread); + new_thread = *ret_thread; } else { - new_thread = (*ret_thread); + new_thread = allocate_thread(); } + + if (new_thread == NULL) { + return TM_ERROR_OUT_OF_MEMORY; + } + new_thread->library = hythread_self()->library; if (stacksize) { apr_threadattr_create(&apr_attrs, new_thread->pool); apr_threadattr_stacksize_set(apr_attrs, stacksize); @@ -108,23 +121,27 @@ } new_thread->priority = priority ? priority : HYTHREAD_PRIORITY_NORMAL; + new_thread->state = TM_THREAD_STATE_ALIVE; //new_thread->suspend_request = suspend ? 1 : 0; + start_proc_data = (thread_start_proc_data *) apr_palloc(new_thread->pool, sizeof(thread_start_proc_data)); + if (start_proc_data == NULL) { + return TM_ERROR_OUT_OF_MEMORY; + } + // Set up thread body procedure - new_thread->start_proc = func; - new_thread->start_proc_args = data; - new_thread->state = TM_THREAD_STATE_ALIVE; + start_proc_data->thread = new_thread; + start_proc_data->group = group == NULL ? TM_DEFAULT_GROUP : group; + start_proc_data->start_proc = func; + start_proc_data->start_proc_args = data; + // Create APR thread using the given attributes; - apr_status = apr_thread_create(&(new_thread->os_handle), // new thread OS handle - new_thread->apr_attrs, // thread attr created here - thread_start_proc, // - (void *)new_thread, //thread_proc attrs + apr_status = apr_thread_create(&(new_thread->os_handle), // new thread OS handle + new_thread->apr_attrs, // thread attr created here + thread_start_proc, // + (void *)start_proc_data, //thread_proc attrs new_thread->pool); - // Store the pointer to the resulting thread - if(ret_thread) { - *ret_thread = new_thread; - } return CONVERT_ERROR(apr_status); } @@ -157,14 +174,19 @@ * Registers the current OS thread with the threading subsystem. * * @param[in] handle thread to register + * @param[in] lib thread library to attach to * @param[in] group thread group, or NULL; in case of NULL this thread will go to the default group */ -IDATA VMCALL hythread_attach_to_group(hythread_t *handle, hythread_group_t group) { +IDATA hythread_attach_to_group(hythread_t * handle, hythread_library_t lib, hythread_group_t group) { hythread_t thread; apr_thread_t *os_handle = NULL; apr_os_thread_t *os_thread; - apr_status_t apr_status; + apr_status_t apr_status; + if (lib == NULL) { + lib = TM_LIBRARY; + } + // Do nothing and return if the thread is already attached thread = tm_self_tls; if (thread) { @@ -173,30 +195,29 @@ } return TM_ERROR_NONE; } - thread = init_thread(group); // allocate & init thread structure - if (thread==NULL){ - return TM_ERROR_OUT_OF_MEMORY; - } + if (handle) { + hythread_struct_init(handle); + thread = *handle; + } else { + thread = allocate_thread(); + } + if (thread == NULL) { + return TM_ERROR_OUT_OF_MEMORY; + } + thread->library = lib; os_thread = apr_palloc(thread->pool, sizeof(apr_os_thread_t)); - if(os_thread == NULL) { + if (os_thread == NULL) { return TM_ERROR_OUT_OF_MEMORY; - } + } *os_thread = apr_os_thread_current(); apr_status = apr_os_thread_put(&os_handle, os_thread, thread->pool); - if (apr_status != APR_SUCCESS) return CONVERT_ERROR(apr_status); + if (apr_status != APR_SUCCESS) return CONVERT_ERROR(apr_status); thread->os_handle = os_handle; - thread_set_self(thread); - - thread->state = TM_THREAD_STATE_ALIVE | TM_THREAD_STATE_RUNNABLE; - assert(thread == tm_self_tls); + TRACE(("TM: native attached: native: %p ", tm_self_tls)); - - if (handle) { - *handle = thread; - } - return TM_ERROR_NONE; + return register_to_group(thread, group == NULL ? TM_DEFAULT_GROUP : group); } /** @@ -213,13 +234,28 @@ * @param[out] handle pointer to a hythread_t to be set (will be ignored if null) * @return 0 on success or negative value on failure * + * @note (*handle) should be NULL or point to hythread_t structure * @see hythread_detach */ IDATA VMCALL hythread_attach(hythread_t *handle) { - return hythread_attach_to_group(handle, NULL); + return hythread_attach_to_group(handle, TM_LIBRARY, NULL); } /** + * Attach an OS thread to the threading library. + * + * @param[out] handle pointer to a hythread_t to be set (will be ignored if null) + * @param[in] lib thread library to attach thread to + * @return 0 on success or negative value on failure + * + * @note (*handle) should be NULL or point to hythread_t structure + * @see hythread_detach + */ +IDATA VMCALL hythread_attach_ex(hythread_t *handle, hythread_library_t lib) { + return hythread_attach_to_group(handle, lib, NULL); +} + +/** * Detaches a thread from the threading library. * * @note Assumes that the thread being detached is already attached.
@@ -237,22 +273,23 @@ */ void VMCALL hythread_detach(hythread_t thread) { // Acquire global TM lock to prevent concurrent acccess to thread list - IDATA status; + IDATA status; + + assert(thread == tm_self_tls); status = hythread_global_lock(NULL); - assert (status == TM_ERROR_NONE); - - if (!(thread = tm_self_tls)) { - status = hythread_global_unlock(NULL); - assert (status == TM_ERROR_NONE); - return; - } - - status = thread_destroy(thread); // Remove thread from the list of thread assert (status == TM_ERROR_NONE); - thread_set_self(NULL); - status = hythread_global_unlock(NULL); - assert (status == TM_ERROR_NONE); + + thread_set_self(NULL); + fast_thread_array[thread->thread_id] = NULL; + + thread->prev->next = thread->next; + thread->next->prev = thread->prev; + thread->group->threads_count--; + + hythread_global_unlock(NULL); + assert(status == TM_ERROR_NONE); } + /** * Waits until the selected thread finishes execution. * @@ -481,66 +518,6 @@ return TM_ERROR_NONE; } -//============================================================================== -// Private functions -/* - */ -IDATA thread_destroy(hythread_t thread) { - - // Acquire global TM lock to prevent concurrent acccess to thread list - IDATA status; - status =hythread_global_lock(NULL); - if (status != TM_ERROR_NONE) return status; - thread->prev->next = thread->next; - thread->next->prev = thread->prev; - thread->group->threads_count--; - - //fast_thread_array[thread->thread_id] = NULL; - - status =hythread_global_unlock(NULL); - if (status != TM_ERROR_NONE) return status; - return TM_ERROR_NONE; -} -/* - */ -IDATA allocate_thread(hythread_t thread, hythread_group_t group) { - int id = 0; - hythread_t cur, prev; - IDATA status; - //thread_list points to the dummy thread, which is not actual thread, just - //a auxiliary thread structure to maintain the thread list - ///// - - // Acquire global TM lock to prevent concurrent acccess to thread list - status =hythread_global_lock(NULL); - if (status != TM_ERROR_NONE) return status; - - // Append the thread to the list of threads - cur = group->thread_list->next; - if (thread->thread_id) { - id = thread->thread_id; - } else { - id = ++next_id; - } - if (id>=MAX_ID){ - hythread_global_unlock(NULL); - return TM_ERROR_OUT_OF_MEMORY; - } - prev = cur->prev; - - thread->next = cur; - thread->prev = prev; - prev->next = cur->prev = thread; - thread->thread_id = id; - fast_thread_array[id] = thread; - /*status=add_to_fast_thread_array(thread,id); - if (status != TM_ERROR_NONE) return status;*/ - status=hythread_global_unlock(NULL); - if (status != TM_ERROR_NONE) return status; - return TM_ERROR_NONE; - -} - /** * Terminates a running thread. * @@ -570,14 +547,14 @@ group = TM_DEFAULT_GROUP; } - iter = hythread_iterator_create (group); + iter = hythread_iterator_create(group); while((next = hythread_iterator_next (&iter)) != NULL) { - if(next != self) { - hythread_cancel(next); + if(next != self) { + hythread_cancel(next); //since this method being used at shutdown it does not //males any sence to exit on error, but continue terminating threads - } - } + } + } return TM_ERROR_NONE; } @@ -586,44 +563,75 @@ * Allocates and initializes a new thread_t structure. * */ -IDATA VMCALL hythread_struct_init(hythread_t *ret_thread, hythread_group_t group) { +IDATA VMCALL hythread_struct_init(hythread_t *ret_thread) { if (*ret_thread) { reset_thread(*ret_thread); - } else { - (*ret_thread) = init_thread(group); + return TM_ERROR_NONE; } - if ((*ret_thread)==NULL) - { - return TM_ERROR_OUT_OF_MEMORY; - } - return TM_ERROR_NONE; + (*ret_thread) = allocate_thread(); + return (*ret_thread) == NULL ? TM_ERROR_OUT_OF_MEMORY : TM_ERROR_NONE; } +//============================================================================== +// Private functions /* + */ +static IDATA register_to_group(hythread_t thread, hythread_group_t group) { + IDATA status; + hythread_t cur, prev; + + assert(thread); + assert(group); + + // Acquire global TM lock to prevent concurrent acccess to thread list + status = hythread_global_lock(NULL); + if (status != TM_ERROR_NONE) return status; + + thread_set_self(thread); + assert(thread == tm_self_tls); + + thread->state = TM_THREAD_STATE_ALIVE | TM_THREAD_STATE_RUNNABLE; + + if (!thread->thread_id) { + ++next_id; + thread->thread_id = next_id; + if (next_id >= MAX_ID) { + hythread_global_unlock(NULL); + return TM_ERROR_OUT_OF_MEMORY; + } + } + + fast_thread_array[thread->thread_id] = thread; + + thread->group = group; + group->threads_count++; + cur = group->thread_list->next; + prev = cur->prev; + thread->next = cur; + thread->prev = prev; + prev->next = cur->prev = thread; + return hythread_global_unlock(NULL); +} + +/* * Allocates and initializes a new thread_t structure * * @return created and initialized thread_t structure */ -static hythread_t init_thread(hythread_group_t group) { +static hythread_t allocate_thread() { apr_pool_t *pool; - apr_status_t apr_status; + apr_status_t apr_status; hythread_t ptr; - IDATA status; + IDATA status; - if (!group) { - group = TM_DEFAULT_GROUP; - } + apr_status = apr_pool_create(&pool, TM_POOL); + if((apr_status != APR_SUCCESS) || (pool == NULL)) return NULL; - apr_status = apr_pool_create(&pool, group->pool); - if((apr_status!=APR_SUCCESS)||(pool==NULL)) - return NULL; ptr = (hythread_t )apr_pcalloc(pool, sizeof(HyThread)); - if (ptr==NULL) - return NULL; + if (ptr == NULL) return NULL; + ptr->pool = pool; - ptr->group = group; ptr->os_handle = NULL; - ptr->next = ptr->prev = ptr; ptr->priority = HYTHREAD_PRIORITY_NORMAL; // not implemented //ptr->big_thread_local_storage = (void **)apr_pcalloc(pool, sizeof(void*)*tm_tls_capacity); @@ -632,91 +640,94 @@ ptr->suspend_request = 0; ptr->suspend_disable_count = 0; status = hylatch_create(&ptr->join_event, 1); - assert (status == TM_ERROR_NONE); - status = hylatch_create(&ptr->safe_region_event, 1); - assert (status == TM_ERROR_NONE); + assert (status == TM_ERROR_NONE); + status = hylatch_create(&ptr->safe_region_event, 1); + assert (status == TM_ERROR_NONE); status = hysem_create(&ptr->resume_event, 0, 1); - assert (status == TM_ERROR_NONE); + assert (status == TM_ERROR_NONE); status = hysem_create(&ptr->park_event, 0, 1); - assert (status == TM_ERROR_NONE); + assert (status == TM_ERROR_NONE); status = hysem_create(&ptr->sleep_event, 0, 1); - assert (status == TM_ERROR_NONE); + assert (status == TM_ERROR_NONE); ptr->state = TM_THREAD_STATE_ALLOCATED; - status = allocate_thread(ptr, group); - if (status !=TM_ERROR_NONE) - { - return NULL; - } - group->threads_count++; - return ptr; } static void reset_thread(hythread_t thread) { apr_status_t apr_status; - IDATA status; - apr_thread_join(&apr_status, thread->os_handle); + IDATA status; + if (thread->os_handle) { + apr_thread_join(&apr_status, thread->os_handle); assert(!apr_status); + } + thread->os_handle = NULL; thread->priority = HYTHREAD_PRIORITY_NORMAL; // not implemented //ptr->big_thread_local_storage = (void **)apr_pcalloc(pool, sizeof(void*)*tm_tls_capacity); - thread->next = thread->prev = thread; + // Suspension thread->suspend_request = 0; thread->suspend_disable_count = 0; status = hylatch_set(thread->join_event, 1); - assert (status == TM_ERROR_NONE); - status = hylatch_set(thread->safe_region_event, 1); - assert (status == TM_ERROR_NONE); + assert (status == TM_ERROR_NONE); + status = hylatch_set(thread->safe_region_event, 1); + assert (status == TM_ERROR_NONE); status = hysem_set(thread->resume_event, 0); - assert (status == TM_ERROR_NONE); + assert (status == TM_ERROR_NONE); status = hysem_set(thread->park_event, 0); - assert (status == TM_ERROR_NONE); + assert (status == TM_ERROR_NONE); status = hysem_set(thread->sleep_event, 0); - assert (status == TM_ERROR_NONE); + assert (status == TM_ERROR_NONE); thread->state = TM_THREAD_STATE_ALLOCATED; - status =allocate_thread(thread, thread->group); - if (status!=TM_ERROR_NONE) - { - thread=NULL; - } - thread->group->threads_count++; } // Wrapper around user thread start proc. Used to perform some duty jobs // right after thread is started. ////// static void* APR_THREAD_FUNC thread_start_proc(apr_thread_t* thd, void *p_args) { - IDATA status; - hythread_t thread = (hythread_t )p_args; + IDATA status; + hythread_t thread; + thread_start_proc_data * start_proc_data; + + start_proc_data = (thread_start_proc_data *) p_args; + thread = start_proc_data->thread; TRACE(("TM: native thread started: native: %p tm: %p", apr_os_thread_current(), thread)); + + status = register_to_group(thread, start_proc_data->group); + if (status != TM_ERROR_NONE) { + thread->exit_value = status; + return &thread->exit_value; + } + // Also, should it be executed under TM global lock? thread->os_handle = thd; // DELETE? - thread_set_self(thread); status = hythread_set_priority(thread, thread->priority); - //assert (status == TM_ERROR_NONE);//now we down - fixme + //assert (status == TM_ERROR_NONE);//now we down - fixme thread->state |= TM_THREAD_STATE_RUNNABLE; - // Do actual call of the thread body supplied by the user - thread->start_proc(thread->start_proc_args); + // Do actual call of the thread body supplied by the user. + start_proc_data->start_proc(start_proc_data->start_proc_args); - // shutdown sequence + // Shutdown sequence. status = hythread_global_lock(NULL); assert (status == TM_ERROR_NONE); assert(hythread_is_suspend_enabled()); thread->state = TM_THREAD_STATE_TERMINATED | (TM_THREAD_STATE_INTERRUPTED & thread->state); - // Send join event to those threads who called join on this thread + thread->exit_value = 0; + + hythread_detach(thread); + // Send join event to those threads who called join on this thread. hylatch_count_down(thread->join_event); - status = thread_destroy(thread); // Remove thread from the list of thread - assert (status == TM_ERROR_NONE); - // Cleanup TLS after thread completes - thread_set_self(NULL); + status = hythread_global_unlock(NULL); - assert (status == TM_ERROR_NONE); + assert (status == TM_ERROR_NONE); + + // TODO: It seems it is there is no need to call apr_thread_exit. + // Current thread should automatically exit upon returning from this function. return (void *)(IDATA)apr_thread_exit(thd, APR_SUCCESS); } @@ -733,12 +744,8 @@ } apr_pool_t* get_local_pool() { - hythread_t self = tm_self_tls; - if(self == NULL) { - return TM_POOL; - } else { - return self->pool; - } + hythread_t self = tm_self_tls; + return self == NULL ? TM_POOL : self->pool; } /** Index: thread/src/thread_native_state.c =================================================================== --- thread/src/thread_native_state.c (revision 454089) +++ thread/src/thread_native_state.c (working copy) @@ -33,9 +33,7 @@ * * @param[in] thread those attribute is read */ -int VMCALL hythread_is_alive(hythread_t thread) { - return thread->state & TM_THREAD_STATE_ALIVE; -}; +int VMCALL hythread_is_alive(hythread_t thread) { return thread->state & TM_THREAD_STATE_ALIVE ; }; /** * Returns non-zero if thread is blocked on monitor enter. Index: thread/src/thread_native_suspend.c =================================================================== --- thread/src/thread_native_suspend.c (revision 454089) +++ thread/src/thread_native_suspend.c (working copy) @@ -104,6 +104,11 @@ void VMCALL hythread_suspend_disable() { register hythread_t thread; +#ifndef NDEBUG + // Check that current thread is in default thread group. + // Justification: GC suspends and enumerates threads from default group only. + assert(tm_self_tls->group == TM_DEFAULT_GROUP); +#endif #ifdef FS14_TLS_USE __asm { Index: thread/src/thread_private.h =================================================================== --- thread/src/thread_private.h (revision 454089) +++ thread/src/thread_private.h (working copy) @@ -107,7 +107,7 @@ #endif /** - * get_local_pool() function return apr pool asociated with the current thread. + * get_local_pool() function return apr pool associated with the current thread. * the memory could be allocated without lock using this pool * dealocation should be done in the same thread, otherwise * local_pool_cleanup_register() should be called @@ -153,6 +153,9 @@ typedef struct HyThreadLibrary { IDATA a; + hymutex_t TM_LOCK; + IDATA nondaemon_thread_count; + hycond_t nondaemon_thread_cond; } HyThreadLibrary; @@ -161,6 +164,12 @@ * Native thread control structure. */ typedef struct HyThread { + + /** + * Each thread keeps a pointer to the libary it belongs to. + */ + HyThreadLibrary * library; + // Suspension /** @@ -279,14 +288,8 @@ /** * Hint for scheduler about thread priority */ - IDATA priority; + IDATA priority; - /** - * Is this thread daemon? - */ - IDATA daemon; - - // Monitors /** @@ -306,18 +309,7 @@ */ apr_threadattr_t *apr_attrs; - /** - * Procedure that describes thread body to be executed. - */ - hythread_entrypoint_t start_proc; - - /** - * Arguments to be passed to the thread body. - */ - void *start_proc_args; - - /** * Array representing thread local storage */ void *thread_local_storage[10]; @@ -400,6 +392,11 @@ */ jobject thread_ref; + /** + * Is this thread daemon? + */ + IDATA daemon; + } JVMTIThread; @@ -603,19 +600,12 @@ * threads at shutdown. */ -IDATA countdown_nondaemon_threads(); -IDATA increase_nondaemon_threads_count(); - -IDATA VMCALL hythread_create_with_group(hythread_t *ret_thread, hythread_group_t group, UDATA stacksize, UDATA priority, UDATA suspend, hythread_entrypoint_t func, void *data); - typedef void (*tm_thread_event_callback_proc)(void); IDATA VMCALL set_safepoint_callback(hythread_t thread, tm_thread_event_callback_proc callback); IDATA acquire_start_lock(void); IDATA release_start_lock(void); -IDATA thread_destroy(hythread_t thread); - IDATA thread_sleep_impl(I_64 millis, IDATA nanos, IDATA interruptable); IDATA condvar_wait_impl(hycond_t cond, hymutex_t mutex, I_64 ms, IDATA nano, IDATA interruptable); IDATA monitor_wait_impl(hythread_monitor_t mon_ptr, I_64 ms, IDATA nano, IDATA interruptable); Index: vmcore/include/environment.h =================================================================== --- vmcore/include/environment.h (revision 454089) +++ vmcore/include/environment.h (working copy) @@ -22,31 +22,40 @@ #ifndef _ENVIRONMENT_H #define _ENVIRONMENT_H -#include "tl/memory_pool.h" +#include +#include + +#include "open/hythread.h" +#include "open/compmgr.h" +#include "open/em_vm.h" + #include "String_Pool.h" #include "vm_core_types.h" #include "object_handles.h" #include "jvmti_internal.h" -#include "open/compmgr.h" -#include "open/em_vm.h" +#include "method_lookup.h" typedef struct NSOTableItem NSOTableItem; typedef struct DynamicCode DynamicCode; typedef struct Assertion_Registry Assertion_Registry; struct Global_Env { - public: - tl::MemoryPool& mem_pool; // memory pool - String_Pool string_pool; // string table + public: + apr_pool_t* mem_pool; // memory pool BootstrapClassLoader* bootstrap_class_loader; - JavaVMInitArgs vm_arguments; UserDefinedClassLoader* system_class_loader; - Properties& properties; + Properties* properties; DebugUtilsTI* TI; NSOTableItem* nsoTable; void* portLib; // Classlib's port library DynamicCode* dcList; Assertion_Registry* assert_reg; + Method_Lookup_Table* vm_methods; + hythread_library_t hythread_lib; + String_Pool string_pool; // string table + JavaVMInitArgs vm_arguments; + + // // globals // @@ -127,6 +136,7 @@ Class* java_lang_ExceptionInInitializerError_Class; Class* java_lang_NullPointerException_Class; Class* java_lang_StackOverflowError_Class; + Class* java_lang_ThreadDeathError_Class; Class* java_lang_ClassNotFoundException_Class; Class* java_lang_NoClassDefFoundError_Class; @@ -137,7 +147,7 @@ Class* java_lang_ClassCastException_Class; Class* java_lang_OutOfMemoryError_Class; ObjectHandle java_lang_OutOfMemoryError; - + ObjectHandle java_lang_ThreadDeathError; // object of java.lang.Error class used for JVMTI JIT PopFrame support ObjectHandle popFrameException; @@ -163,8 +173,12 @@ VTable* JavaLangString_VTable; Allocation_Handle JavaLangString_allocation_handle; + // Keeps uncaught exception for the thread which is destroying VM. + jthrowable uncaught_exception; + // Offset to the vm_class field in java.lang.Class; unsigned vm_class_offset; + /** * Shutting down state. * 0 - working @@ -172,7 +186,7 @@ * 2 - deadly errors in shutdown */ int shutting_down; - + // FIXME // The whole environemt will be refactored to VM instance // The following contains a cached copy of EM interface table @@ -180,13 +194,17 @@ OpenInstanceHandle em_instance; OpenEmVmHandle em_interface; - // - // constructor - // - Global_Env(tl::MemoryPool& mm, Properties& prop); - // function is used instead of destructor to uninitialize manually - void EnvClearInternals(); + Global_Env(apr_pool_t * pool); + ~Global_Env(); + void * operator new(size_t size, apr_pool_t * pool) { + return apr_palloc(pool, sizeof(Global_Env)); + } + + void operator delete(void *) {} + + void operator delete(void * mem, apr_pool_t * pool) {}; + // // determine bootstrapping of root classes // Index: vmcore/include/init.h =================================================================== --- vmcore/include/init.h (revision 454089) +++ vmcore/include/init.h (working copy) @@ -25,24 +25,18 @@ #include "environment.h" -bool vm_init(Global_Env *env); -int run_java_main(char *classname, char **j_argv, int j_argc, Global_Env *p_env); -int run_main_platform_specific(char *classname, char **j_argv, int j_argc, Global_Env *p_env); +jint vm_attach_internal(JNIEnv ** p_jni_env, jthread * java_thread, + JavaVM * java_vm, jobject group, + char * name, jboolean daemon); +jint vm_init1(JavaVM_Internal * java_vm, JavaVMInitArgs * vm_arguments); +jint vm_init2(JNIEnv * jni_env); +jint vm_destroy(JavaVM_Internal * java_vm, jthread java_thread); +void vm_exit(int exit_code); -JavaVMInitArgs* parse_cmd_arguments(int argc, char *argv[], char **class_name, char **jar_file, int *p_java_arg_num); -void clear_vm_arguments(JavaVMInitArgs* vm_args); void initialize_vm_cmd_state(Global_Env *p_env, JavaVMInitArgs* arguments); void set_log_levels_from_cmd(JavaVMInitArgs* vm_arguments); void parse_vm_arguments(Global_Env *p_env); void parse_jit_arguments(JavaVMInitArgs* vm_arguments); void print_generic_help(); -void create_vm(Global_Env *p_env, JavaVMInitArgs* vm_arguments); -void destroy_vm(Global_Env *p_env); - -/* - * declared in vm_main.cpp - */ -extern Global_Env env; - #endif //_INIT_H Index: vmcore/include/jni_direct.h =================================================================== --- vmcore/include/jni_direct.h (revision 454089) +++ vmcore/include/jni_direct.h (working copy) @@ -20,44 +20,34 @@ */ - - - #ifndef _JNI_DIRECT_H_ #define _JNI_DIRECT_H_ -#include "jni.h" +#include +#include + #include "open/types.h" + +#include "jni.h" #include "Class.h" -struct _jfieldID : public Field { -}; +typedef struct JavaVM_Internal JavaVM_Internal; +typedef struct JNIEnv_Internal JNIEnv_Internal; -VMEXPORT jint JNICALL GetVersion(JNIEnv *env); - struct JavaVM_Internal : public JavaVM_External { - JavaVM_Internal(const JNIInvokeInterface_ *_functions, - Global_Env *_vm_env, - void *_reserved) : vm_env(_vm_env), reserved(_reserved) - { - functions = _functions; - } - Global_Env* vm_env; + apr_pool_t * pool; + Global_Env * vm_env; + APR_RING_ENTRY(JavaVM_Internal) link; void* reserved; }; struct JNIEnv_Internal : public JNIEnv_External { - JNIEnv_Internal(const JNINativeInterface_ *_functions, - JavaVM_Internal *_vm, - void *_reserved0) : vm(_vm), reserved0(_reserved0) - { - functions = _functions; - } JavaVM_Internal* vm; void *reserved0; }; -void jni_init(); +struct _jfieldID : public Field { +}; jmethodID reflection_unreflect_method(JNIEnv *jenv, jobject ref_method); jmethodID reflection_unreflect_constructor(JNIEnv *jenv, jobject ref_constructor); @@ -606,7 +596,7 @@ VMEXPORT jlong JNICALL GetDirectBufferCapacity(JNIEnv* env, jobject buf); -VMEXPORT jint JNICALL DestroyVM(JavaVM*); +VMEXPORT jint JNICALL DestroyJavaVM(JavaVM*); VMEXPORT jint JNICALL AttachCurrentThread(JavaVM*, void** penv, void* args); VMEXPORT jint JNICALL DetachCurrentThread(JavaVM*); Index: vmcore/include/jni_utils.h =================================================================== --- vmcore/include/jni_utils.h (revision 454089) +++ vmcore/include/jni_utils.h (working copy) @@ -23,6 +23,7 @@ #ifndef _JNI_UTILS_H_ #define _JNI_UTILS_H_ +#include "environment.h" #include "object_handles.h" #include "platform.h" #include "jni_direct.h" @@ -39,7 +40,6 @@ VMEXPORT ClassLoaderHandle class_loader_lookup(jobject loader); VMEXPORT void class_loader_load_native_lib(const char* lib, ClassLoaderHandle loader); VMEXPORT ClassLoaderHandle class_loader_find_if_exists(jobject loader); -VMEXPORT void class_loader_set_system_class_loader(ClassLoaderHandle); VMEXPORT jvalue *get_jvalue_arg_array(Method *method, va_list args); @@ -95,6 +95,9 @@ // String* parameter (instead of const char* in JNI FindClass) jclass FindClass(JNIEnv* env_ext, String* name); +JavaVM * jni_get_java_vm(JNIEnv * jni_env); +Global_Env * jni_get_vm_env(JNIEnv * jni_env); + /* global handles */ extern ObjectHandle gh_jlc; //java.lang.Class extern ObjectHandle gh_jls; //java.lang.String Index: vmcore/include/method_lookup.h =================================================================== --- vmcore/include/method_lookup.h (revision 454089) +++ vmcore/include/method_lookup.h (working copy) @@ -86,7 +86,4 @@ }; //class Method_Lookup_Table -VMEXPORT extern Method_Lookup_Table *vm_methods; - - #endif //_METHOD_LOOKUP_H_ Index: vmcore/include/natives_support.h =================================================================== --- vmcore/include/natives_support.h (revision 454089) +++ vmcore/include/natives_support.h (working copy) @@ -60,9 +60,9 @@ /** * Initializes natives_support module. Caller must provide thread safety. * - * @return Returns true if initialized successfully. + * @return Returns JNI_OK if initialized successfully. */ -bool +jint natives_init(); /** Index: vmcore/include/properties.h =================================================================== --- vmcore/include/properties.h (revision 454089) +++ vmcore/include/properties.h (working copy) @@ -279,21 +279,6 @@ bucket = (Prop_entry**)STD_CALLOC(sizeof(Prop_entry*), size_); iterator = new Iterator(this); } -#ifdef USE_MEM_MANAGER_FOR_ALLOCATION -public: - void *operator new(size_t sz, tl::MemoryPool& m) { - return m.alloc(sz); - } - void operator delete(void *obj, tl::MemoryPool& m){ - //do nothing - }; - void *operator new(size_t sz) { - return m_malloc(sz); - } - void operator delete(void *obj){ - m_free(obj); - }; -#endif }; typedef struct _properties* PropertiesHandle; Index: vmcore/include/thread_manager.h =================================================================== --- vmcore/include/thread_manager.h (revision 454089) +++ vmcore/include/thread_manager.h (working copy) @@ -28,15 +28,8 @@ extern "C" { #endif - -void vm_thread_shutdown(); -void vm_thread_init(Global_Env *p_env); - -void vm_thread_attach(); -void vm_thread_detach(); - void free_this_thread_block(VM_thread *); -VM_thread * get_a_thread_block(); +VM_thread * get_a_thread_block(JavaVM_Internal * java_vm); extern volatile VM_thread *p_the_safepoint_control_thread; // only set when a gc is happening Index: vmcore/include/version_svn_tag.h =================================================================== --- vmcore/include/version_svn_tag.h (revision 454089) +++ vmcore/include/version_svn_tag.h (working copy) @@ -18,6 +18,6 @@ #ifndef _VERSION_SVN_TAG_ #define _VERSION_SVN_TAG_ -#define VERSION_SVN_TAG "453599" +#define VERSION_SVN_TAG "454089" #endif // _VERSION_SVN_TAG_ Index: vmcore/include/vm_threads.h =================================================================== --- vmcore/include/vm_threads.h (revision 454089) +++ vmcore/include/vm_threads.h (working copy) @@ -31,14 +31,18 @@ #include "vm_process.h" #endif +#include + #include "open/types.h" #include "open/hythread.h" #include "open/ti_thread.h" + #include "vm_core_types.h" #include "object_layout.h" #include "open/vm_gc.h" #include "exceptions_type.h" #include "jvmti.h" +#include "jni_direct.h" // @@ -66,10 +70,17 @@ class VM_thread { public: - // FIXME: workaround for strange bug. If this line is removed Visual Stidio - // has corrupted list of modules and no debug info at all. - void* system_private_data; + /** + * Memory pool where this structure is allocated. + * This pool should be used by current thread for memory allocations. + */ + apr_pool_t * pool; + /** + * JNI environment associated with this thread. + */ + JNIEnv_Internal * jni_env; + // In case exception is thrown, Exception object is put here // TODO: Needs to be replaced with jobject! //volatile ManagedObject* p_exception_object; Index: vmcore/src/class_support/Assertion_Registry.cpp =================================================================== --- vmcore/src/class_support/Assertion_Registry.cpp (revision 454089) +++ vmcore/src/class_support/Assertion_Registry.cpp (working copy) @@ -22,11 +22,13 @@ #define LOG_DOMAIN "vm.core" #include "cxxlog.h" +#include + #include "assertion_registry.h" void Assertion_Registry::add_class(const Global_Env* genv, const char* name, unsigned len, bool value) { - Assertion_Record* rec = (Assertion_Record*)genv->mem_pool.alloc( - sizeof(Assertion_Record) + len * sizeof(char)); + Assertion_Record* rec = (Assertion_Record*) + apr_palloc(genv->mem_pool, sizeof(Assertion_Record) + len * sizeof(char)); rec->status = value; rec->len = len; strncpy(rec->name, name, len); @@ -36,8 +38,8 @@ } void Assertion_Registry::add_package(const Global_Env* genv, const char* name, unsigned len, bool value) { - Assertion_Record* rec = (Assertion_Record*)genv->mem_pool.alloc( - sizeof(Assertion_Record) + len * sizeof(char)); + Assertion_Record* rec = (Assertion_Record*) + apr_palloc(genv->mem_pool, sizeof(Assertion_Record) + len * sizeof(char)); rec->status = value; rec->len = len; strncpy(rec->name, name, len); Index: vmcore/src/class_support/C_Interface.cpp =================================================================== --- vmcore/src/class_support/C_Interface.cpp (revision 454089) +++ vmcore/src/class_support/C_Interface.cpp (working copy) @@ -313,7 +313,8 @@ void method_set_relocatable(Method_Handle m, JIT_Handle j, NativeCodePtr code_address, Boolean is_relocatable) { - CodeChunkInfo *cci = vm_methods->find(code_address); + Global_Env *env = VM_Global_State::loader_env; + CodeChunkInfo *cci = env->vm_methods->find(code_address); assert(cci); assert(cci->get_jit() == j); assert(cci->get_method() == m); @@ -499,14 +500,16 @@ Method_Iterator method_get_first_method_jit(JIT_Handle j) { - return vm_methods->get_first_method_jit((JIT *)j); + Global_Env *env = VM_Global_State::loader_env; + return env->vm_methods->get_first_method_jit((JIT *)j); } //method_get_first_method_jit Method_Iterator method_get_next_method_jit(Method_Iterator i) { - return vm_methods->get_next_method_jit((CodeChunkInfo *)i); + Global_Env *env = VM_Global_State::loader_env; + return env->vm_methods->get_next_method_jit((CodeChunkInfo *)i); } //method_get_next_method_jit @@ -2421,7 +2424,7 @@ const char *vm_get_property_value(const char *property_name) { assert(property_name); - PropertiesHandle props = (PropertiesHandle)&VM_Global_State::loader_env->properties; + PropertiesHandle props = (PropertiesHandle)VM_Global_State::loader_env->properties; const char *result = properties_get_string_property(props, property_name); if (result == NULL) result = ""; @@ -2431,7 +2434,7 @@ Boolean vm_get_property_value_boolean(const char *property_name, Boolean default_value) { assert(property_name); - PropertiesHandle props = (PropertiesHandle)&VM_Global_State::loader_env->properties; + PropertiesHandle props = (PropertiesHandle)VM_Global_State::loader_env->properties; const char *value = properties_get_string_property(props, property_name); // fall back to provided default if the property is not set @@ -2510,10 +2513,10 @@ // a branch long. Note that this function does not synchronize the I- or D-caches. // Run through list of active threads and suspend the other ones. - hythread_suspend_all(NULL, NULL); + hythread_suspend_all(NULL, NULL); patch_code_with_threads_suspended(code_block, new_code, size); - hythread_resume_all(NULL); + hythread_resume_all(NULL); } //vm_patch_code_block @@ -2678,7 +2681,7 @@ void vm_properties_set_value(const char* name, const char* value) { - PropertiesHandle ph = (PropertiesHandle)&VM_Global_State::loader_env->properties; + PropertiesHandle ph = (PropertiesHandle)VM_Global_State::loader_env->properties; properties_set_string_property(ph, name, value); } @@ -2686,13 +2689,13 @@ // All iterators created with this method call // must be destroyed with vm_properties_iterator_destroy PropertiesIteratorHandle vm_properties_iterator_create() { - PropertiesHandle ph = (PropertiesHandle)&VM_Global_State::loader_env->properties; + PropertiesHandle ph = (PropertiesHandle)VM_Global_State::loader_env->properties; return properties_iterator_create(ph); } // Destroy iterator created by vm_properties_iterator_create void vm_properties_iterator_destroy(PropertiesIteratorHandle props_iter) { - PropertiesHandle ph = (PropertiesHandle)&VM_Global_State::loader_env->properties; + PropertiesHandle ph = (PropertiesHandle)VM_Global_State::loader_env->properties; properties_iterator_destroy(ph, props_iter); } Index: vmcore/src/class_support/classloader.cpp =================================================================== --- vmcore/src/class_support/classloader.cpp (revision 454089) +++ vmcore/src/class_support/classloader.cpp (working copy) @@ -1354,7 +1354,7 @@ { // get property value const char *bcp_value = properties_get_string_property( - reinterpret_cast(&m_env->properties), prop_string); + reinterpret_cast(m_env->properties), prop_string); assert(bcp_value); size_t len = strlen(bcp_value) + 1; @@ -1534,7 +1534,7 @@ // get list of natives libraries const char *lib_list = properties_get_string_property( - reinterpret_cast(&m_env->properties), + reinterpret_cast(m_env->properties), "vm.other_natives_dlls" ); size_t len = strlen( lib_list ) + 1; char *libraries = (char*)STD_ALLOCA( len ); @@ -1567,7 +1567,7 @@ * the kernel */ - PropertiesHandle hProps = reinterpret_cast(&m_env->properties); + PropertiesHandle hProps = reinterpret_cast(m_env->properties); /* strdup so that it's freeable w/o extra logic */ @@ -1636,8 +1636,8 @@ * that needs it */ - add_pair_to_properties(m_env->properties, VM_BOOT_CLASS_PATH, bcp_value); - add_pair_to_properties(m_env->properties, SUN_BOOT_CLASS_PATH, bcp_value); + add_pair_to_properties(*m_env->properties, VM_BOOT_CLASS_PATH, bcp_value); + add_pair_to_properties(*m_env->properties, SUN_BOOT_CLASS_PATH, bcp_value); free(bcp_value); Index: vmcore/src/class_support/Environment.cpp =================================================================== --- vmcore/src/class_support/Environment.cpp (revision 454089) +++ vmcore/src/class_support/Environment.cpp (working copy) @@ -33,14 +33,27 @@ #include "native_overrides.h" #include "compile.h" -Global_Env::Global_Env(tl::MemoryPool & mp, Properties & prop): -mem_pool(mp), + +Global_Env::Global_Env(apr_pool_t * pool): +mem_pool(pool), bootstrap_class_loader(NULL), system_class_loader(NULL), -properties(prop), +properties(NULL), +TI(NULL), +nsoTable(NULL), +portLib(NULL), +dcList(NULL), +assert_reg(NULL), +vm_methods(NULL), bootstrapping(false), ready_for_exceptions(false) { + // TODO: Use proper MM. + properties = new Properties(); + bootstrap_class_loader = new BootstrapClassLoader(this); + + hythread_lib_create(&hythread_lib); + JavaLangString_String = string_pool.lookup("java/lang/String"); JavaLangStringBuffer_String = string_pool.lookup("java/lang/StringBuffer"); JavaLangObject_String = string_pool.lookup("java/lang/Object"); @@ -117,6 +130,7 @@ JavaLangClass_Class = NULL; java_lang_Throwable_Class = NULL; java_lang_Error_Class = NULL; + java_lang_ThreadDeathError_Class = NULL; java_lang_ExceptionInInitializerError_Class = NULL; java_lang_NullPointerException_Class = NULL; java_lang_StackOverflowError_Class = NULL; @@ -141,22 +155,20 @@ JavaLangString_VTable = NULL; JavaLangString_allocation_handle = 0; + uncaught_exception = NULL; + vm_class_offset = 0; shutting_down = 0; - TI = NULL; - portLib = NULL; + TI = new DebugUtilsTI; + vm_methods = new Method_Lookup_Table; + nsoTable = nso_init_lookup_table(&string_pool); - nsoTable = nso_init_lookup_table(&this->string_pool); +} //Global_Env::Global_Env - dcList = NULL; -} //Global_Env::Global_Env - -void Global_Env::EnvClearInternals() +Global_Env::~Global_Env() { - // No GC should work during iteration - tmn_suspend_disable(); GlobalClassLoaderIterator ClIterator; ClassLoader *cl = ClIterator.first(); @@ -166,18 +178,28 @@ delete cltmp; } ClassLoader::DeleteClassLoaderTable(); - tmn_suspend_enable(); - if (TI) - delete TI; + delete TI; + TI = NULL; + delete vm_methods; + vm_methods = NULL; + + delete properties; + properties = NULL; + + delete bootstrap_class_loader; + bootstrap_class_loader = NULL; + nso_clear_lookup_table(nsoTable); nsoTable = NULL; compile_clear_dynamic_code_list(dcList); dcList = NULL; -} + hythread_lib_destroy(hythread_lib); + } + Class* Global_Env::LoadCoreClass(const String* s) { Class* clss = Index: vmcore/src/class_support/method.cpp =================================================================== --- vmcore/src/class_support/method.cpp (revision 454089) +++ vmcore/src/class_support/method.cpp (working copy) @@ -354,7 +354,8 @@ jit_info->_code_block_alignment = alignment; unlock(); - vm_methods->add(jit_info); // Method table is thread safe + Global_Env *env = VM_Global_State::loader_env; + env->vm_methods->add(jit_info); // Method table is thread safe return addr; } // Method::allocate_code_block Index: vmcore/src/class_support/method_lookup.cpp =================================================================== --- vmcore/src/class_support/method_lookup.cpp (revision 454089) +++ vmcore/src/class_support/method_lookup.cpp (working copy) @@ -24,6 +24,7 @@ #define LOG_DOMAIN "vm.methods" #include "cxxlog.h" +#include "environment.h" #include "platform.h" #include #include "lock_manager.h" @@ -36,10 +37,6 @@ #define EIP_CACHE_SIZE 1024 #define EIP_ALIGNMENT 4 - -Method_Lookup_Table *vm_methods = NULL; - - Method_Lookup_Table::Method_Lookup_Table() { _next_free_entry = 0; @@ -402,7 +399,8 @@ VM_Code_Type vm_identify_eip(void *addr) { - CodeChunkInfo *m = vm_methods->find(addr); + Global_Env *env = VM_Global_State::loader_env; + CodeChunkInfo *m = env->vm_methods->find(addr); if (m == NULL) { return VM_TYPE_UNKNOWN; } @@ -418,7 +416,8 @@ VM_Code_Type vm_identify_eip_deadlock_free(void *addr) { - CodeChunkInfo *m = vm_methods->find_deadlock_free(addr); + Global_Env *env = VM_Global_State::loader_env; + CodeChunkInfo *m = env->vm_methods->find_deadlock_free(addr); if (m == NULL) { return VM_TYPE_UNKNOWN; } Index: vmcore/src/class_support/Resolve.cpp =================================================================== --- vmcore/src/class_support/Resolve.cpp (revision 454089) +++ vmcore/src/class_support/Resolve.cpp (working copy) @@ -1059,7 +1059,7 @@ /** * Resolve whole constant pool */ -unsigned resolve_const_pool(Global_Env& env, Class *clss) { +int resolve_const_pool(Global_Env& env, Class *clss) { Const_Pool *cp = clss->const_pool; // It's possible that cp is null when defining class on the fly @@ -1071,5 +1071,5 @@ return i; } } - return 0xFFFFFFFF; + return 0; } //resolve_const_pool Index: vmcore/src/class_support/String_Pool.cpp =================================================================== --- vmcore/src/class_support/String_Pool.cpp (revision 454089) +++ vmcore/src/class_support/String_Pool.cpp (working copy) @@ -80,6 +80,7 @@ index_interned = (Interned_Strings_Index *)memory_pool.alloc(sizeof(Interned_Strings_Index)); + string_pool_lock = 0; #ifdef VM_STATS string_stat = apr_hash_make(VM_Statistics::get_vm_stats().vm_stats_pool); num_ambiguity = 0; Index: vmcore/src/exception/exceptions.cpp =================================================================== --- vmcore/src/exception/exceptions.cpp (revision 454089) +++ vmcore/src/exception/exceptions.cpp (working copy) @@ -373,7 +373,7 @@ inline void exn_java_print_stack_trace(FILE * UNREF f, jthrowable exc) { // finds java environment - JNIEnv_Internal *jenv = jni_native_intf; + JNIEnv *jenv = jni_native_intf; // finds class of Throwable jclass throwableClazz = FindClass(jenv, VM_Global_State::loader_env->JavaLangThrowable_String); @@ -389,7 +389,7 @@ { assert(hythread_is_suspend_enabled()); // finds java environment - JNIEnv_Internal *jenv = jni_native_intf; + JNIEnv *jenv = jni_native_intf; // finds class of Throwable jclass throwableClazz = FindClass(jenv, VM_Global_State::loader_env->JavaLangThrowable_String); Index: vmcore/src/gc/dll_gc.cpp =================================================================== --- vmcore/src/gc/dll_gc.cpp (revision 454089) +++ vmcore/src/gc/dll_gc.cpp (working copy) @@ -397,8 +397,7 @@ static void default_gc_add_compressed_root_set_entry(uint32 * UNREF ref) { - printf("Fatal GC error: compressed references are not supported\n"); - vm_exit(1); + DIE("Fatal GC error: compressed references are not supported\n"); } //default_gc_add_compressed_root_set_entry @@ -406,8 +405,7 @@ static void default_gc_add_root_set_entry_managed_pointer(void ** UNREF slot, Boolean UNREF is_pinned) { - printf("Fatal GC error: managed pointers are not supported\n"); - vm_exit(1); + DIE("Fatal GC error: managed pointers are not supported\n"); } //default_gc_add_root_set_entry_managed_pointer Index: vmcore/src/gc/stop_the_world_root_set_enum.cpp =================================================================== --- vmcore/src/gc/stop_the_world_root_set_enum.cpp (revision 454089) +++ vmcore/src/gc/stop_the_world_root_set_enum.cpp (working copy) @@ -53,12 +53,13 @@ static void -vm_enumerate_the_current_thread() +vm_enumerate_the_current_thread(VM_thread * vm_thread) { + assert(p_TLS_vmthread == vm_thread); // Process roots for the current thread //assert(p_TLS_vmthread->gc_status == zero); //p_TLS_vmthread->gc_status = gc_at_safepoint; - vm_enumerate_thread(p_TLS_vmthread); + vm_enumerate_thread(vm_thread); // Enumeration for this thread is complete. //p_TLS_vmthread->gc_status = gc_enumeration_done; @@ -79,14 +80,16 @@ static void stop_the_world_root_set_enumeration() { + VM_thread * current_vm_thread; + TRACE2("vm.gc", "stop_the_world_root_set_enumeration()"); // Run through list of active threads and suspend each one of them. INFO2("threads","Start thread suspension "); vm_time_start_hook(&_start_time); //thread suspension time measurement - - hythread_iterator_t iterator; + + hythread_iterator_t iterator; hythread_suspend_all(&iterator, NULL); thread_suspend_time = vm_time_end_hook(&_start_time, &_end_time); @@ -94,13 +97,13 @@ class_unloading_clear_mark_bits(); + current_vm_thread = p_TLS_vmthread; // Run through list of active threads and enumerate each one of them. - hythread_t tm_thread = hythread_iterator_next(&iterator); - - //VM_thread *thread = get_vm_thread (hythread_iterator_next(&iterator)); - while(tm_thread) { + hythread_t tm_thread = hythread_iterator_next(&iterator); + while (tm_thread) { VM_thread *thread = get_vm_thread(tm_thread); - if (thread && thread != p_TLS_vmthread) { + //assert(thread); + if (thread && thread != current_vm_thread) { vm_enumerate_thread(thread); // Enumeration for this thread is complete. //thread->gc_status = gc_enumeration_done; @@ -110,7 +113,7 @@ tm_thread = hythread_iterator_next(&iterator); } - vm_enumerate_the_current_thread(); + vm_enumerate_the_current_thread(current_vm_thread); // finally, process all the global refs vm_enumerate_root_set_global_refs(); Index: vmcore/src/init/parse_arguments.cpp =================================================================== --- vmcore/src/init/parse_arguments.cpp (revision 454091) +++ vmcore/src/init/parse_arguments.cpp (working copy) @@ -19,27 +19,20 @@ * @version $Revision: 1.1.2.4.4.7 $ */ - -#define LOG_DOMAIN "vm.core" -#include "cxxlog.h" - -#include -#include -#include "port_filepath.h" - #include #include #include +#include +#include +#include "open/gc.h" +#include "open/vm_util.h" #include "Class.h" #include "properties.h" #include "environment.h" #include "assertion_registry.h" - -#include "open/gc.h" - -#include "open/vm_util.h" +#include "port_filepath.h" #include "compile.h" #include "vm_stats.h" #include "nogc.h" @@ -52,6 +45,9 @@ #include "dll_jit_intf.h" #include "dll_gc.h" +#define LOG_DOMAIN "vm.core" +#include "cxxlog.h" + //------ Begin DYNOPT support -------------------------------------- // #ifndef PLATFORM_POSIX // for DYNOPT in Win64 @@ -134,7 +130,7 @@ static inline Assertion_Registry* get_assert_reg(Global_Env *p_env) { if (!p_env->assert_reg) { - void * mem = p_env->mem_pool.alloc(sizeof(Assertion_Registry)); + void * mem = apr_palloc(p_env->mem_pool, sizeof(Assertion_Registry)); p_env->assert_reg = new (mem) Assertion_Registry(); } return p_env->assert_reg; @@ -177,7 +173,7 @@ * This is the directory where the virtual machine artifacts are located * (vm.dll, etc) including the kernel.jar GEIR */ - add_pair_to_properties(p_env->properties, "org.apache.harmony.vm.vmdir", + add_pair_to_properties(*p_env->properties, "org.apache.harmony.vm.vmdir", option + strlen("-Dorg.apache.harmony.vm.vmdir=")); } else if (begins_with(option, XBOOTCLASSPATH)) { @@ -187,7 +183,7 @@ * processing and setting up "vm.boot.class.path" and "sun.boot.class.path" * Note that in the case of multiple arguments, the last one will be used */ - add_pair_to_properties(p_env->properties, XBOOTCLASSPATH, option + strlen(XBOOTCLASSPATH)); + add_pair_to_properties(*p_env->properties, XBOOTCLASSPATH, option + strlen(XBOOTCLASSPATH)); } else if (begins_with(option, XBOOTCLASSPATH_A)) { /* @@ -196,7 +192,7 @@ * Note that we accumulate if multiple, appending each time */ - const char *bcp_old = properties_get_string_property((PropertiesHandle)&p_env->properties, + const char *bcp_old = properties_get_string_property((PropertiesHandle)p_env->properties, XBOOTCLASSPATH_A); const char *value = option + strlen(XBOOTCLASSPATH_A); @@ -213,7 +209,7 @@ bcp_new = tmp; } - add_pair_to_properties(p_env->properties, XBOOTCLASSPATH_A, bcp_old ? bcp_new : value); + add_pair_to_properties(*p_env->properties, XBOOTCLASSPATH_A, bcp_old ? bcp_new : value); if (bcp_new) { free(bcp_new); @@ -226,7 +222,7 @@ * Note that we accumulate if multiple, prepending each time */ - const char *bcp_old = properties_get_string_property((PropertiesHandle)&p_env->properties, + const char *bcp_old = properties_get_string_property((PropertiesHandle)p_env->properties, XBOOTCLASSPATH_P); const char *value = option + strlen(XBOOTCLASSPATH_P); @@ -243,7 +239,7 @@ bcp_new = tmp; } - add_pair_to_properties(p_env->properties, XBOOTCLASSPATH_P, bcp_old ? bcp_new : value); + add_pair_to_properties(*p_env->properties, XBOOTCLASSPATH_P, bcp_old ? bcp_new : value); if (bcp_new) { free(bcp_new); @@ -262,7 +258,7 @@ } else if (begins_with(option, "-Xjit:")) { // Do nothing here, just skip this option for later parsing } else if (strcmp(option, "-Xint") == 0) { - add_pair_to_properties(p_env->properties, "vm.use_interpreter", "true"); + add_pair_to_properties(*p_env->properties, "vm.use_interpreter", "true"); #ifdef VM_STATS } else if (begins_with(option, "-Xstats:")) { vm_print_total_stats = true; @@ -286,12 +282,12 @@ char* prop_key = strdup(option + strlen("-X")); prop_key[2] = '.'; TRACE2("init", prop_key << " = 1"); - add_pair_to_properties(p_env->properties, prop_key, "1"); + add_pair_to_properties(*p_env->properties, prop_key, "1"); free(prop_key); } else if (begins_with(option, "-Xem:")) { const char* arg = option + strlen("-Xem:"); - add_pair_to_properties(p_env->properties, "em.properties", arg); + add_pair_to_properties(*p_env->properties, "em.properties", arg); } else if (begins_with(option, "-Xms")) { // cut -Xms @@ -300,7 +296,7 @@ if (atoi(arg) == 0) { ECHO("Negative or invalid heap size. Default value will be used!"); } - add_pair_to_properties(p_env->properties, "gc.ms", arg); + add_pair_to_properties(*p_env->properties, "gc.ms", arg); } else if (begins_with(option, "-Xmx")) { // cut -Xmx @@ -309,7 +305,7 @@ if (atoi(arg) == 0) { ECHO("Negative or invalid heap size. Default value will be used!"); } - add_pair_to_properties(p_env->properties, "gc.mx", arg); + add_pair_to_properties(*p_env->properties, "gc.mx", arg); } else if (begins_with(option, "-agentlib:")) { p_env->TI->addAgent(option); @@ -372,7 +368,7 @@ dump_file_name = arg; } else if (strcmp(option, "-XcleanupOnExit") == 0) { - add_pair_to_properties(p_env->properties, "vm.cleanupOnExit", "true"); + add_pair_to_properties(*p_env->properties, "vm.cleanupOnExit", "true"); } else if (strcmp(option, "_org.apache.harmony.vmi.portlib") == 0) { // Store a pointer to the portlib @@ -554,73 +550,6 @@ } // for (arg_num) } //set_log_levels_from_cmd -struct cmd_arg -{ - bool substring; - char *param; - int length; - int args; -}; - -static const cmd_arg supported_parameters[] = -{ - {false, "-classpath", strlen("-classpath"), 1}, - {false, "-cp", strlen("-cp"), 1}, - {true, "-Xbootclasspath:", strlen("-Xbootclasspath:"), 0}, - {true, "-Xbootclasspath/a:", strlen("-Xbootclasspath/a:"), 0}, - {true, "-Xbootclasspath/p:", strlen("-Xbootclasspath/p:"), 0}, - {false, "-?", strlen("-?"), 0}, - {false, "-help", strlen("-help"), 1}, - {true, "-Xjit", strlen("-Xjit"), 1}, - {false, "-Xint", strlen("-Xint"), 0}, -#ifdef VM_STATS - {false, "-Xstats", strlen("-Xstats"), 1}, -#endif - {false, "-version", strlen("-version"), 0}, - {false, "-showversion", strlen("-showversion"), 0}, - {false, "-fullversion", strlen("-fullversion"), 0}, - {true, "-ea", strlen("-ea"), 0}, - {true, "-enableassertions", strlen("-enableassertions"), 0}, - {true, "-da", strlen("-da"), 0}, - {true, "-disableassertions", strlen("-disableassertions"), 0}, - {false, "-dsa", strlen("-esa"), 0}, - {false, "-esa", strlen("-dsa"), 0}, - {false, "-enablesystemassertions", strlen("-enablesystemassertions"), 0}, - {false, "-disablesystemassertions", strlen("-disablesystemassertions"), 0}, - {false, "-Xgc", strlen("-Xgc"), 1}, - {true, "-Xem", strlen("-Xem"), 1}, - {true, "-Xms", strlen("-Xms"), 0}, - {true, "-Xmx", strlen("-Xmx"), 0}, - {true, "-agentlib:", strlen("-agentlib:"), 0}, - {true, "-agentpath:", strlen("-agentpath:"), 0}, - {false, "-Xdebug", strlen("-Xdebug"), 0}, - {false, "-Xverify", strlen("-Xverify"), 0}, - {false, "-verify", strlen("-verify"), 0}, - {false, "-Xnoagent", strlen("-Xnoagent"), 0}, - {true, "-Xrun", strlen("-Xrun"), 0}, - {true, "-verbose", strlen("-verbose"), 0}, - {true, "-Xverbose", strlen("-Xverbose"), 0}, - {true, "-Xverboseconf:", strlen("-Xverboseconf:"), 0}, - {true, "-Xverboselog:", strlen("-Xverboselog:"), 0}, - {true, "-Xfileline", strlen("-Xfileline"), 0}, - {true, "-Xthread", strlen("-Xthread"), 0}, - {true, "-Xcategory", strlen("-Xcategory"), 0}, - {true, "-Xtimestamp", strlen("-Xtimestamp"), 0}, - {true, "-Xwarn", strlen("-Xwarn"), 0}, - {true, "-Xfunction", strlen("-Xfunction"), 0}, -#ifdef _DEBUG - {true, "-Xtrace", strlen("-Xtrace"), 0}, - {true, "-Xlog", strlen("-Xlog"), 0}, -#endif //_DEBUG - {true, "-D", strlen("-D"), 0}, - {false, "-Xdumpstubs", strlen("-Xdumpstubs"), 0}, - {false, "-Xparallel_jit", strlen("-Xparallel_jit"), 0}, - {false, "-Xno_parallel_jit", strlen("-Xno_parallel_jit"), 0}, - {false, "-Xdumpfile", strlen("-Xdumpfile"), 1}, - {false, "-XcleanupOnExit", strlen("-XcleanupOnExit"), 0}, - {false, "-jar", strlen("-jar"), 0} -}; //supported_parameters - static void print_help_on_nonstandard_options() { #ifdef _DEBUG @@ -702,217 +631,6 @@ " Excplicitly free VM resources before exit\n"); } //print_help_on_nonstandard_options -static JavaVMInitArgs* create_vm_arguments(int options_capacity) -{ - JavaVMInitArgs* vm_arguments = (JavaVMInitArgs*) STD_MALLOC(sizeof(JavaVMInitArgs)); - assert(vm_arguments); - vm_arguments->version = JNI_VERSION_1_4; - vm_arguments->nOptions = 0; - vm_arguments->ignoreUnrecognized = JNI_FALSE; - vm_arguments->options = - (JavaVMOption*)STD_MALLOC(sizeof(JavaVMOption) * (options_capacity)); - assert(vm_arguments->options); - - return vm_arguments; -} //create_vm_arguments - -void clear_vm_arguments(JavaVMInitArgs* vm_args) -{ - STD_FREE(vm_args->options); - STD_FREE(vm_args); -} - -static void vm_arguments_append_classpath(JavaVMInitArgs* vm_arguments, const char* jar_file) -{ - static const char prefix[] = "-Djava.class.path="; - - // search for the last java.class.path property declaration - for (int i = vm_arguments->nOptions - 1; i >= 0 ; i--) - { - const char* option = vm_arguments->options[i].optionString; - if (strncmp(option, prefix, strlen(prefix)) == 0) - { - // if found, append jar file name - char* new_option = (char*) STD_MALLOC(strlen(option) + - strlen(PORT_PATH_SEPARATOR_STR) + strlen(jar_file) + 1); - assert(new_option); - - strcpy(new_option, option); - strcat(new_option, PORT_PATH_SEPARATOR_STR); - strcat(new_option, jar_file); - - vm_arguments->options[i].optionString = new_option; - return; - } - } - - // if not found, define java.class.path with jar file name - char* option = (char*) STD_MALLOC(strlen(prefix) + strlen(jar_file) + 1); - assert(option); - - strcpy(option, prefix); - strcat(option, jar_file); - - vm_arguments->options[vm_arguments->nOptions].optionString = option; - vm_arguments->nOptions ++; - return; -} //vm_arguments_append_classpath - -static int parse_vm_option(JavaVMInitArgs* vm_arguments, int argc, char *argv[], int i) -{ - // return 0, if arguments are over - if (i >= argc) - return 0; - - // if '-jar' met, thean vm options are over - if (strcmp(argv[i], "-jar") == 0) - return 0; - - const cmd_arg* supported_parameter; - bool found = false; - for (unsigned j = 0; j < sizeof(supported_parameters) / sizeof(cmd_arg); j++) - { - supported_parameter = &(supported_parameters[j]); - if ((supported_parameters[j].substring && - strncmp(argv[i], supported_parameters[j].param, - supported_parameters[j].length) == 0) || - (!supported_parameters[j].substring && - strcmp(argv[i], supported_parameters[j].param) == 0)) - { - found = true; - break; - } - } - - if (found) - { - char* option; - - if (strcmp(argv[i], "-classpath") == 0 || strcmp(argv[i], "-cp") == 0) - { - if (i + 1 >= argc) { - ECHO("Classpath option " - << argv[i] - << " should be followed by classpath value" - USE_JAVA_HELP); - LOGGER_EXIT(1); - } - - char* class_path = argv[i + 1]; - static const char prefix[] = "-Djava.class.path="; - - option = (char*) STD_MALLOC(strlen(prefix) + strlen(class_path) + 1); - assert(option); - - strcpy(option, prefix); - strcat(option, class_path); - } - else if (strcmp(argv[i], "-help") == 0 || strcmp(argv[i], "-?") == 0) - { - if (i + 1 >= argc) - { - // out a generic help message - print_generic_help(); - LOGGER_EXIT(0); - } - - const char* arg = argv[i + 1]; - if (strcmp(arg, "jit") != 0 && !begins_with(arg, "prop")) - { - // out a generic help message - print_generic_help(); - LOGGER_EXIT(0); - } - - static const char prefix[] = "-Xhelp:"; - - option = (char*) STD_MALLOC(strlen(prefix) + strlen(arg) + 1); - assert(option); - - strcpy(option, prefix); - strcat(option, arg); - - } - else if (supported_parameter->args == 1) - { - if (i + 1 >= argc) - { - ECHO("Option " << argv[i] << " should be followed by a additional parameter"); - LOGGER_EXIT(1); - } - - option = (char*) STD_MALLOC(strlen(argv[i]) + 1 + strlen(argv[i + 1]) + 1); - assert(option); - - strcpy(option, argv[i]); - strcat(option, ":"); - strcat(option, argv[i + 1]); - } - else - { - option = argv[i]; - } - - vm_arguments->options[vm_arguments->nOptions].optionString = option; - vm_arguments->nOptions ++; - - return 1 + supported_parameter->args; - } - - if (argv[i][0] != '-') - return 0; - - if (strcmp(argv[i], "-X") == 0) - { - print_help_on_nonstandard_options(); - LOGGER_EXIT(0); - } else { - ECHO("Unknown option " << argv[i] << USE_JAVA_HELP); - LOGGER_EXIT(1); - } - -} //parse_vm_option - -JavaVMInitArgs* parse_cmd_arguments(int argc, char *argv[], - char **p_class_name, char **p_jar_file, int *p_java_arg_num) -{ - *p_class_name = NULL; - *p_jar_file = NULL; - - JavaVMInitArgs* vm_arguments = create_vm_arguments(argc); - - int i = 1; // skip argv[0], since it is a program name - int inc = 0; - do - { - inc = parse_vm_option(vm_arguments, argc, argv, i); - i += inc; - } while (inc > 0); - - if (i < argc) - { - if (strcmp(argv[i], "-jar") == 0) - { - i++; - if (i >= argc) { - ECHO("Option -jar must be followed by a jar file name"); - LOGGER_EXIT(1); - } - - *p_jar_file = argv[i]; - vm_arguments_append_classpath(vm_arguments, *p_jar_file); - } - else - { - *p_class_name = argv[i]; - } - } - - *p_java_arg_num = argc - i - 1; - - return vm_arguments; -} //parse_cmd_arguments - void initialize_vm_cmd_state(Global_Env *p_env, JavaVMInitArgs* arguments) { p_env->vm_arguments.version = arguments->version; Index: vmcore/src/init/properties.cpp =================================================================== --- vmcore/src/init/properties.cpp (revision 454089) +++ vmcore/src/init/properties.cpp (working copy) @@ -390,12 +390,12 @@ */ - define_undefined_predefined_properties(p_env->properties); + define_undefined_predefined_properties(*p_env->properties); char **pp = predefined_propeties; while (NULL != *pp) { - p_env->properties.add(*pp); + p_env->properties->add(*pp); pp++; } @@ -443,7 +443,7 @@ if (strncmp(option, "-D", 2) == 0) { TRACE("setting property " << option + 2); - add_to_properties(p_env->properties, option + 2); + add_to_properties(*p_env->properties, option + 2); } } apr_pool_clear(prop_pool); Index: vmcore/src/init/vm.cpp =================================================================== --- vmcore/src/init/vm.cpp (revision 454089) +++ vmcore/src/init/vm.cpp (working copy) @@ -158,75 +158,7 @@ ///////////////////////////////////////////////////////////////// -//============================================================================================================== -// VM_EXIT -//============================================================================================================== - -// this is a prototype of Invocation API DestroyJavaVM function -// It should be updated to wait for all user threads to complite. -// Current VM calls it if -XcleanOpOnExit flag specified - -void DestroyVM() { - TRACE("cleanup started"); - if (vm_methods != NULL) { - vm_methods->unload_all(); - } - vm_thread_shutdown(); //move up here - - VM_Global_State::loader_env->shutting_down += 1; - - vm_delete_all_jits(); - CmFreeComponent("em"); - CmRelease(); - - ClassLoader::PrintUnloadingStats(); - -#ifdef VM_STATS - VM_Statistics::get_vm_stats().print(); -#endif //VM_STATS - - // Unloads all system native libraries - natives_cleanup(); - - VM_Global_State::loader_env->EnvClearInternals(); - gc_thread_kill(&p_TLS_vmthread->_gc_private_information); - gc_wrapup(); - vm_mem_dealloc(); - vm_uninitialize_critical_sections(); - - // FIXME: vm_methods should be moved to Global_Env - then - // call ~Method_Lookup_Table() in EnvClearInternals() - vm_methods->~Method_Lookup_Table(); - -#ifdef DUMP_IPF_STUBS - extern FILE *ipf_stubs_out_file; - if (ipf_stubs_out_file) { - fclose(ipf_stubs_out_file); - } -#endif //DUMP_IPF_STUBS -} -void vm_exit(int exit_code) -{ - // Send VM_Death event and switch phase to VM_Death - jvmti_send_vm_death_event(); - if (vm_get_boolean_property_value_with_default("vm.cleanupOnExit")) - jthread_cancel_all(); - /* FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME * - * gregory - JVMTI shutdown should be part of DestroyVM after current VM shutdown * - * problems are fixed * - * FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME */ - // call Agent_OnUnload() for agents and unload agents - VM_Global_State::loader_env->TI->Shutdown(); - - if (vm_get_boolean_property_value_with_default("vm.cleanupOnExit")) - { - DestroyVM(); - LOGGER_EXIT(exit_code); - } - _exit(exit_code); -} //vm_exit - static struct VmStandardProperty { const char *name; // Full name of the property const char *docString; // Documentation of the property Index: vmcore/src/init/vm_init.cpp =================================================================== --- vmcore/src/init/vm_init.cpp (revision 454089) +++ vmcore/src/init/vm_init.cpp (working copy) @@ -19,455 +19,818 @@ * @version $Revision: 1.1.2.4.4.3 $ */ +#include +#include -#define LOG_DOMAIN "vm.core" -#include "cxxlog.h" +#include "open/gc.h" +#include "open/thread_externals.h" +#include "init.h" #include "classloader.h" #include "jni_utils.h" #include "mon_enter_exit.h" #include "heap.h" +#include "port_filepath.h" +#include "component_manager.h" +#include "dll_gc.h" +#include "compile.h" +#include "interpreter.h" +#include "em_intf.h" +#include "dll_jit_intf.h" +#include "jni_utils.h" +#include "platform_lowlevel.h" +#include "verify_stack_enumeration.h" +#include "nogc.h" +#include "vm_strings.h" #ifdef PLATFORM_NT // 20040427 Used to turn on heap checking on every allocation #include -#endif //PLATFORM_NT +#endif -bool vm_is_initialized = false; +#define LOG_DOMAIN "vm.core.init" +#include "cxxlog.h" -void vm_initialize_critical_sections() -{ +VTable * cached_object_array_vtable_ptr; +bool parallel_jit = true; +VMEXPORT bool dump_stubs = false; +JNIEnv * jni_native_intf; + +void vm_initialize_critical_sections() { p_jit_a_method_lock = new Lock_Manager(); p_vtable_patch_lock = new Lock_Manager(); p_meth_addr_table_lock = new Lock_Manager(); p_handle_lock = new Lock_Manager(); - - // 20040224 Support for recording which methods (actually, CodeChunkInfo's) call which other methods. p_method_call_lock = new Lock_Manager(); -} //vm_initialize_critical_sections +} -void vm_uninitialize_critical_sections() -{ +void vm_uninitialize_critical_sections() { delete p_jit_a_method_lock; delete p_vtable_patch_lock; delete p_meth_addr_table_lock; delete p_handle_lock; - delete p_method_call_lock; -} //vm_uninitialize_critical_sections +} -Class* preload_class(Global_Env* env, const char* classname) -{ - String* s = env->string_pool.lookup(classname); - return env->LoadCoreClass(s); +Class * preload_class(Global_Env * vm_env, const char * classname) { + String * s = vm_env->string_pool.lookup(classname); + return vm_env->LoadCoreClass(s); } -Class* preload_class(Global_Env* env, String* s) -{ - return env->LoadCoreClass(s); +Class * preload_class(Global_Env * vm_env, String* s) { + return vm_env->LoadCoreClass(s); } - -static Class* preload_primitive_class(Global_Env* env, const char* classname) -{ - String *s = env->string_pool.lookup(classname); - ClassLoader* cl = env->bootstrap_class_loader; - Class *clss = cl->NewClass(env, s); +static Class * preload_primitive_class(Global_Env * vm_env, const char * classname) { + String * s = vm_env->string_pool.lookup(classname); + ClassLoader * cl = vm_env->bootstrap_class_loader; + Class *clss = cl->NewClass(vm_env, s); clss->is_primitive = 1; clss->class_loader = cl; clss->access_flags = ACC_ABSTRACT | ACC_FINAL | ACC_PUBLIC; clss->is_verified = 2; cl->InsertClass(clss); - class_prepare(env, clss); + class_prepare(vm_env, clss); return clss; -} //preload_primitive_class +} - - #ifdef LIB_DEPENDENT_OPTS -static Class *class_initialize_by_name(const char *classname) -{ +static Class * class_initialize_by_name(Global_Env * vm_env, const char * classname) { ASSERT_RAISE_AREA; - Global_Env* env = VM_Global_State::loader_env; - String *s = env->string_pool.lookup(classname); - Class *clss = env->bootstrap_class_loader->LoadVerifyAndPrepareClass(env, s); - if(clss == NULL) { - DIE("Couldn't load class " << classname); - } else { + String *s = vm_env->string_pool.lookup(classname); + Class *clss = vm_env->bootstrap_class_loader->LoadVerifyAndPrepareClass(vm_env, s); + if (clss != NULL) { class_initialize(clss); } return clss; -} //class_initialize_by_name +} - - -void lib_dependent_opts() -{ +static jint lib_dependent_opts() { ASSERT_RAISE_AREA; - class_initialize_by_name("java/lang/Math"); -} //lib_dependent_opts + return class_initialize_by_name("java/lang/Math") != null ? JNI_OK : JNI_ERR; +} +#endif -#endif // LIB_DEPENDENT_OPTS - // Create the java_lang_Class instance for a struct Class // and set its "vm_class" field to point back to that structure. -void create_instance_for_class(Global_Env *env, Class *clss) +void create_instance_for_class(Global_Env * vm_env, Class *clss) { - clss->class_loader->AllocateAndReportInstance(env, clss); -} //create_instance_for_class + clss->class_loader->AllocateAndReportInstance(vm_env, clss); +} +/** + * Loads DLLs. + */ +static jint process_properties_dlls(Global_Env * vm_env) { + jint status; + char * tok; + const char * dlls; + const char delimiters[] = {PORT_PATH_SEPARATOR, 0}; -VTable *cached_object_array_vtable_ptr; + post_initialize_ee_dlls((PropertiesHandle)vm_env->properties); + const char* dll = properties_get_string_property((PropertiesHandle)vm_env->properties, "vm.em_dll"); + TRACE("analyzing em dll " << dll); -static void bootstrap_initial_java_classes(Global_Env *env) + status = CmLoadComponent(dll, "EmInitialize"); + if (status != JNI_OK) { + WARN("Cannot load EM component from " << dll); + return status; + } + + status = vm_env->cm->CreateInstance(&(vm_env->em_instance), "em"); + if (status != JNI_OK) { + WARN("Cannot instantiate EM"); + return status; + } + + status = vm_env->em_instance->intf->GetInterface( + (OpenInterfaceHandle*) &(vm_env->em_interface), OPEN_INTF_EM_VM); + if (status != JNI_OK) { + WARN("Cannot get EM_VM interface"); + return status; + } + + dlls = properties_get_string_property((PropertiesHandle)vm_env->properties, "vm.dlls"); + if (!dlls) return JNI_OK; + + dlls = strdup(dlls); + assert(dlls); + + tok = strtok((char *)dlls, delimiters); + while (tok) { + TRACE("analyzing dll " << tok); +#ifndef USE_GC_STATIC + if (vm_is_a_gc_dll(tok)) { + vm_add_gc(tok); + goto next_dll; + } +#endif + +#ifdef USE_DISEM + if (vm_is_a_disem_dll(tok)) { + vm_add_disem(tok); + goto next_dll; + } +#endif + WARN("Mandatory library cannot be loaded: " << tok); + return JNI_ERR; +next_dll: + tok = strtok(NULL, delimiters); + } + STD_FREE((void*)dlls); + + return JNI_OK; +} + +/** + * Checks whether current platform is supported or not. + */ +static jint check_platform() { +#if defined(PLATFORM_NT) + OSVERSIONINFO osvi; + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + BOOL ok = GetVersionEx(&osvi); + if(!ok) { + DWORD e = GetLastError(); + printf("Windows error: %d\n", e); + return JNI_ERR; + } + if((osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0) || // NT 4.0 + (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) || // Windows 2000 + (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) || // Windows XP + (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)) { // Windows.NET + return JNI_OK; + } + printf("Windows %d.%d is not supported\n", osvi.dwMajorVersion, osvi.dwMinorVersion); + return JNI_ERR; +#else + return JNI_OK; +#endif +} + +/** + * Ensures that different VM components have consistent compression modes. + */ +static jint check_compression() { + // Check for a mismatch between whether the various VM components all compress references or not. + Boolean vm_compression = vm_references_are_compressed(); + Boolean gc_compression = gc_supports_compressed_references(); + if (vm_compression) { + if (!gc_compression) { + WARN("VM component mismatch: the VM compresses references but the GC doesn't."); + return JNI_ERR; + } + + // We actually check the first element in the jit_compilers array, as current JIT + // always returns FALSE to the supports_compressed_references() call. + JIT **jit = &jit_compilers[0]; + if (!interpreter_enabled()) { + Boolean jit_compression = (*jit)->supports_compressed_references(); + if (!jit_compression) { + WARN("VM component mismatch: the VM compresses references but a JIT doesn't"); + return JNI_ERR; + } + } + } else { + if (gc_compression) { + WARN("VM component mismatch: the VM doesn't compress references but the GC does."); + return JNI_ERR; + } + JIT **jit = &jit_compilers[0]; + if (!interpreter_enabled()) { + Boolean jit_compression = (*jit)->supports_compressed_references(); + if (jit_compression) { + WARN("VM component mismatch: the VM doesn't compress references but a JIT does"); + return JNI_ERR; + } + } + } + return JNI_OK; +} + +/** + * Loads initial classes. For example j.l.Object, j.l.Class, etc. + */ +static void bootstrap_initial_java_classes(Global_Env * vm_env) { assert(hythread_is_suspend_enabled()); - TRACE2("init", "bootstrapping initial java classes"); - + TRACE("bootstrapping initial java classes"); + + vm_env->bootstrap_class_loader->Initialize(); + /* * Bootstrap java.lang.Class class. This requires also loading the other classes * it inherits/implements: java.io.Serializable and java.lang.Object, and * j.l.reflect.AnnotatedElement, GenericDeclaration and Type as per Java 5 */ - env->StartVMBootstrap(); - env->JavaLangObject_Class = preload_class(env, env->JavaLangObject_String); - env->java_io_Serializable_Class = preload_class(env, env->Serializable_String); - env->JavaLangClass_Class = preload_class(env, env->JavaLangClass_String); - env->FinishVMBootstrap(); + vm_env->StartVMBootstrap(); + vm_env->JavaLangObject_Class = preload_class(vm_env, vm_env->JavaLangObject_String); + vm_env->java_io_Serializable_Class = preload_class(vm_env, vm_env->Serializable_String); + vm_env->JavaLangClass_Class = preload_class(vm_env, vm_env->JavaLangClass_String); + vm_env->FinishVMBootstrap(); // Now create the java_lang_Class instance. - create_instance_for_class(env, env->JavaLangClass_Class); + create_instance_for_class(vm_env, vm_env->JavaLangClass_Class); - ClassTable* table = env->bootstrap_class_loader->GetLoadedClasses(); + ClassTable* table = vm_env->bootstrap_class_loader->GetLoadedClasses(); unsigned num = 0; for (ClassTable::const_iterator it = table->begin(), end = table->end(); it != end; ++it, ++num) { Class* booted = (*it).second; - if (booted != env->JavaLangClass_Class) { - create_instance_for_class(env, booted); + if (booted != vm_env->JavaLangClass_Class) { + create_instance_for_class(vm_env, booted); } - jvmti_send_class_load_event(env, booted); + jvmti_send_class_load_event(vm_env, booted); jvmti_send_class_prepare_event(booted); } - #ifdef VM_STATS - // Account for the classes loaded before env->JavaLangObject_Class is set. - env->JavaLangObject_Class->num_allocations += num; - env->JavaLangObject_Class->num_bytes_allocated += (num * env->JavaLangClass_Class->instance_data_size); +#ifdef VM_STATS + // Account for the classes loaded before vm_env->JavaLangObject_Class is set. + vm_env->JavaLangObject_Class->num_allocations += num; + vm_env->JavaLangObject_Class->num_bytes_allocated += (num * vm_env->JavaLangClass_Class->instance_data_size); #endif //VM_STATS - TRACE2("init", "bootstrapping initial java classes complete"); -} // bootstrap_initial_java_classes + TRACE("bootstrapping initial java classes complete"); +} -/** Calls java.lang.ClassLoader.getSystemClassLoader() to obtein system class loader object - * and pass it to class_loader_set_system_class_loader(..) function - * @return success status +/** + * Loads hot classes. */ -static bool initialize_system_class_loader(JNIEnv* jenv) -{ - jclass cl = jenv->FindClass("java/lang/ClassLoader"); +static jint preload_classes(Global_Env * vm_env) { + // Bootstrap initial classes + bootstrap_initial_java_classes(vm_env); + + TRACE2("init", "preloading primitive type classes"); + vm_env->Boolean_Class = preload_primitive_class(vm_env, "boolean"); + vm_env->Char_Class = preload_primitive_class(vm_env, "char"); + vm_env->Float_Class = preload_primitive_class(vm_env, "float"); + vm_env->Double_Class = preload_primitive_class(vm_env, "double"); + vm_env->Byte_Class = preload_primitive_class(vm_env, "byte"); + vm_env->Short_Class = preload_primitive_class(vm_env, "short"); + vm_env->Int_Class = preload_primitive_class(vm_env, "int"); + vm_env->Long_Class = preload_primitive_class(vm_env, "long"); + + vm_env->Void_Class = preload_primitive_class(vm_env, "void"); + + vm_env->ArrayOfBoolean_Class = preload_class(vm_env, "[Z"); + vm_env->ArrayOfByte_Class = preload_class(vm_env, "[B"); + vm_env->ArrayOfChar_Class = preload_class(vm_env, "[C"); + vm_env->ArrayOfShort_Class = preload_class(vm_env, "[S"); + vm_env->ArrayOfInt_Class = preload_class(vm_env, "[I"); + vm_env->ArrayOfLong_Class = preload_class(vm_env, "[J"); + vm_env->ArrayOfFloat_Class = preload_class(vm_env, "[F"); + vm_env->ArrayOfDouble_Class = preload_class(vm_env, "[D"); + +#ifndef POINTER64 + // In IA32, Arrays of Doubles need to be eight byte aligned to improve + // performance. In IPF all objects (arrays, class data structures, heap objects) + // get aligned on eight byte boundaries. So, this special code is not needed. + vm_env->ArrayOfDouble_Class->alignment = ((GC_OBJECT_ALIGNMENT < 8) ? 8: GC_OBJECT_ALIGNMENT); + // The alignment is either 4 or it is a multiple of 8. Things like 12 aren't allowed. + assert ((GC_OBJECT_ALIGNMENT == 4) || ((GC_OBJECT_ALIGNMENT % 8) == 0)); + // align doubles on 8, clear alignment field and put in 8. + set_prop_alignment_mask(vm_env->ArrayOfDouble_Class, 8); + // Set high bit in size so that gc knows there are constraints +#endif + + TRACE2("init", "preloading string class"); + vm_env->JavaLangString_Class = preload_class(vm_env, vm_env->JavaLangString_String); + vm_env->strings_are_compressed = + (class_lookup_field_recursive(vm_env->JavaLangString_Class, "bvalue", "[B") != NULL); + vm_env->JavaLangString_VTable = vm_env->JavaLangString_Class->vtable; + vm_env->JavaLangString_allocation_handle = vm_env->JavaLangString_Class->allocation_handle; + + TRACE2("init", "preloading exceptions"); + vm_env->java_lang_Throwable_Class = + preload_class(vm_env, vm_env->JavaLangThrowable_String); + vm_env->java_lang_StackTraceElement_Class = + preload_class(vm_env, "java/lang/StackTraceElement"); + vm_env->java_lang_Error_Class = + preload_class(vm_env, "java/lang/Error"); + vm_env->java_lang_ThreadDeathError_Class = + preload_class(vm_env, "java/lang/ThreadDeath"); + vm_env->java_lang_ExceptionInInitializerError_Class = + preload_class(vm_env, "java/lang/ExceptionInInitializerError"); + vm_env->java_lang_NoClassDefFoundError_Class = + preload_class(vm_env, "java/lang/NoClassDefFoundError"); + vm_env->java_lang_ClassNotFoundException_Class = + preload_class(vm_env, "java/lang/ClassNotFoundException"); + vm_env->java_lang_NullPointerException_Class = + preload_class(vm_env, vm_env->JavaLangNullPointerException_String); + vm_env->java_lang_StackOverflowError_Class = + preload_class(vm_env, "java/lang/StackOverflowError"); + vm_env->java_lang_ArrayIndexOutOfBoundsException_Class = + preload_class(vm_env, vm_env->JavaLangArrayIndexOutOfBoundsException_String); + vm_env->java_lang_ArrayStoreException_Class = + preload_class(vm_env, "java/lang/ArrayStoreException"); + vm_env->java_lang_ArithmeticException_Class = + preload_class(vm_env, "java/lang/ArithmeticException"); + vm_env->java_lang_ClassCastException_Class = + preload_class(vm_env, "java/lang/ClassCastException"); + vm_env->java_lang_OutOfMemoryError_Class = + preload_class(vm_env, "java/lang/OutOfMemoryError"); + + vm_env->java_lang_Cloneable_Class = + preload_class(vm_env, vm_env->Clonable_String); + vm_env->java_lang_Thread_Class = + preload_class(vm_env, "java/lang/Thread"); + vm_env->java_lang_ThreadGroup_Class = + preload_class(vm_env, "java/lang/ThreadGroup"); + vm_env->java_util_Date_Class = + preload_class(vm_env, "java/util/Date"); + vm_env->java_util_Properties_Class = + preload_class(vm_env, "java/util/Properties"); + vm_env->java_lang_Runtime_Class = + preload_class(vm_env, "java/lang/Runtime"); + + vm_env->java_lang_reflect_Constructor_Class = + preload_class(vm_env, vm_env->JavaLangReflectConstructor_String); + vm_env->java_lang_reflect_Field_Class = + preload_class(vm_env, vm_env->JavaLangReflectField_String); + vm_env->java_lang_reflect_Method_Class = + preload_class(vm_env, vm_env->JavaLangReflectMethod_String); + + return JNI_OK; +} + +/** + * Calls java.lang.ClassLoader.getSystemClassLoader() to obtain system + * class loader object. + * @return JNI_OK on success. + */ +static jint initialize_system_class_loader(JNIEnv * jni_env) { + Global_Env * vm_env = jni_get_vm_env(jni_env); + jclass cl = jni_env->FindClass("java/lang/ClassLoader"); if (! cl) - return false; + return JNI_ERR; - jmethodID gcl = jenv->GetStaticMethodID(cl, "getSystemClassLoader", "()Ljava/lang/ClassLoader;"); + jmethodID gcl = jni_env->GetStaticMethodID(cl, "getSystemClassLoader", "()Ljava/lang/ClassLoader;"); if (! gcl) - return false; + return JNI_ERR; - jobject scl = jenv->CallStaticObjectMethod(cl, gcl); - if (exn_raised()) - return false; + jobject scl = jni_env->CallStaticObjectMethod(cl, gcl); + if (! scl) + return JNI_ERR; - if(scl) { - tmn_suspend_disable(); - class_loader_set_system_class_loader(ClassLoader::LookupLoader(((ObjectHandle)scl)->object)); - tmn_suspend_enable(); + hythread_suspend_disable(); + vm_env->system_class_loader = (UserDefinedClassLoader *) + ClassLoader::LookupLoader(((ObjectHandle)scl)->object); + hythread_suspend_enable(); + + return JNI_OK; +} + +#define PROCESS_EXCEPTION(message) \ +{ \ + ECHO("Internal error: " << message); \ +\ + if (jni_env->ExceptionCheck()== JNI_TRUE) \ + { \ + jni_env->ExceptionDescribe(); \ + jni_env->ExceptionClear(); \ + } \ +\ + return JNI_ERR; \ +} \ + +/** + * Executes j.l.VMStart.initialize() method. + */ +static jint run_java_init(JNIEnv * jni_env) { + assert(hythread_is_suspend_enabled()); + + jclass start_class = jni_env->FindClass("java/lang/VMStart"); + if (jni_env->ExceptionCheck()== JNI_TRUE || start_class == NULL) { + PROCESS_EXCEPTION("can't find starter class: java.lang.VMStart."); } - return true; -} //initialize_system_class_loader + jmethodID init_method = jni_env->GetStaticMethodID(start_class, "initialize", "()V"); + if (jni_env->ExceptionCheck()== JNI_TRUE || init_method == NULL) { + PROCESS_EXCEPTION("can't find java.lang.VMStart.initialize() method."); + } -static bool init_thread_object(JNIEnv *); + jni_env->CallStaticVoidMethod(start_class, init_method); + if (jni_env->ExceptionCheck()== JNI_TRUE) { + PROCESS_EXCEPTION("java.lang.VMStart.initialize() method completed with an exception."); + } + return JNI_OK; +} -bool vm_init(Global_Env *env) -{ - ASSERT_RAISE_AREA; +/** + * Creates new j.l.Thread object + * + * @param[out] thread_object pointer to created thread object + * @param[in] jni_env JNI environment assocciated with the current thread + * @param[in] group thread group where new thread should be placed in + * @param[in] name thread's name + * @param[in] daemon JNI_TRUE if new thread is a daemon, JNI_FALSE overwise + */ +static jint vm_create_jthread(jthread * thread_object, JNIEnv * jni_env, jobject group, char * name, jboolean daemon) { + static Method * constructor = NULL; + const char * descriptor = "(Ljava/lang/ThreadGroup;Ljava/lang/String;JJIZ)V"; + jvalue args[7]; + Global_Env * vm_env; + Class * thread_class; + ObjectHandle thread_handle; + hythread_t native_thread; - if(vm_is_initialized) - return false; + + assert(!hythread_is_suspend_enabled()); + + vm_env = jni_get_vm_env(jni_env); + + thread_class = vm_env->java_lang_Thread_Class; + class_initialize(thread_class); + if (exn_raised()) return TM_ERROR_INTERNAL; + + // Allocate new j.l.Thread object. + thread_handle = oh_allocate_global_handle(); + thread_handle->object = class_alloc_new_object(thread_class); + if (thread_handle->object == NULL) { + assert(exn_get() == vm_env->java_lang_OutOfMemoryError); + return JNI_ENOMEM; + } + *thread_object = thread_handle; + + if (constructor == NULL) { + // Initialize created thread object. + constructor = class_lookup_method_init(thread_class, descriptor); + if (constructor == NULL) { + TRACE("Failed to find thread's constructor " << descriptor << " , exception = " << exn_get()); + return JNI_ERR; + } + } + + args[0].l = thread_handle; + args[1].l = group; + + if (name) { + args[2].l = oh_allocate_local_handle(); + args[2].l->object = string_create_from_utf8(name, strlen(name)); + } else { + args[2].l = NULL; + } + native_thread = hythread_self(); + args[3].j = (POINTER_SIZE_INT) native_thread; + args[4].j = 0; + args[5].i = hythread_get_priority(native_thread); + args[6].z = daemon; + + vm_execute_java_method_array((jmethodID) constructor, 0, args); + if (exn_raised()) { + TRACE("Failed to initialize new thread object, exception = " << exn_get_name()); + return JNI_ERR; + } + return JNI_OK; +} + +/** + * Attaches current thread to VM and creates j.l.Thread instance. + * + * @param[out] p_jni_env points to created JNI environment + * @param[out] java_thread global reference holding j.l.Thread object + * @param[in] java_vm VM to attach thread to + * @param[in] group thread group for attaching thread + * @param[in] name thread name + * @param[in] daemon JNI_TRUE if thread is daemon, JNI_FALSE overwise + * @return JNI_OK on success. + */ +jint vm_attach_internal(JNIEnv ** p_jni_env, jthread * java_thread, JavaVM * java_vm, jobject group, char * name, jboolean daemon) { + JNIEnv * jni_env; + hythread_t native_thread; + jint status; + + native_thread = hythread_self(); + if (!native_thread) { + status = hythread_attach_to_group(&native_thread, + ((JavaVM_Internal *)java_vm)->vm_env->hythread_lib, NULL); + if (status != TM_ERROR_NONE) return JNI_ERR; + } + assert(native_thread); + + status = vm_attach(java_vm, &jni_env); + if (status != JNI_OK) return status; + + *p_jni_env = jni_env; + + hythread_suspend_disable(); + // Global reference will be created for new thread object. + status = vm_create_jthread(java_thread, jni_env, group, name, daemon); + hythread_suspend_enable(); + + return status; +} + +/** + * First VM initialization step. At that moment neither JNI is available + * nor main thread is attached to VM. + */ +int vm_init1(JavaVM_Internal * java_vm, JavaVMInitArgs * vm_arguments) { + jint status; + Global_Env * vm_env; + JNIEnv * jni_env; + + TRACE("Initializing VM"); + + vm_env = java_vm->vm_env; + + if (hythread_attach_ex(NULL, vm_env->hythread_lib) != TM_ERROR_NONE) { + return JNI_ERR; + } + assert(hythread_is_suspend_enabled()); - vm_is_initialized = true; - TRACE2("init","Initializing VM"); + status = check_platform(); + if (status != JNI_OK) return status; + // TODO: global variables should be removed for multi-VM support + VM_Global_State::loader_env = vm_env; + + // Initialize arguments + initialize_vm_cmd_state(vm_env, vm_arguments); + + // Initialize logging system as soon as possible. + init_log_system(); + set_log_levels_from_cmd(&vm_env->vm_arguments); + + vm_initialize_critical_sections(); vm_monitor_init(); - env->bootstrap_class_loader = new BootstrapClassLoader(env); // !!! use proper MM - env->bootstrap_class_loader->Initialize(); + status = CmAcquire(&vm_env->cm); + if (status != JNI_OK) { + WARN("Faild to initialize a \"Component Manager\"."); + return status; + } -/////////////// Start bootstrap of initial classes //////////////// + /* BEGIN: Property processing. */ - bootstrap_initial_java_classes(env); + // 20030407 Note: property initialization must follow initialization of the default JITs to allow + // the command line to override those default JITs. -/////////////// End bootstrap of initial classes //////////////// + initialize_properties(vm_env, *vm_env->properties); - TRACE2("init", "preloading primitive type classes"); - env->Boolean_Class = preload_primitive_class(env, "boolean"); - env->Char_Class = preload_primitive_class(env, "char"); - env->Float_Class = preload_primitive_class(env, "float"); - env->Double_Class = preload_primitive_class(env, "double"); - env->Byte_Class = preload_primitive_class(env, "byte"); - env->Short_Class = preload_primitive_class(env, "short"); - env->Int_Class = preload_primitive_class(env, "int"); - env->Long_Class = preload_primitive_class(env, "long"); + parse_vm_arguments(vm_env); - env->Void_Class = preload_primitive_class(env, "void"); + status = process_properties_dlls(vm_env); + if (status != JNI_OK) return status; + + parse_jit_arguments(&vm_env->vm_arguments); - env->ArrayOfBoolean_Class = preload_class(env, "[Z"); - env->ArrayOfByte_Class = preload_class(env, "[B"); - env->ArrayOfChar_Class = preload_class(env, "[C"); - env->ArrayOfShort_Class = preload_class(env, "[S"); - env->ArrayOfInt_Class = preload_class(env, "[I"); - env->ArrayOfLong_Class = preload_class(env, "[J"); - env->ArrayOfFloat_Class = preload_class(env, "[F"); - env->ArrayOfDouble_Class = preload_class(env, "[D"); + vm_env->pin_interned_strings = + (bool)vm_get_property_value_boolean("vm.pin_interned_strings", FALSE); -#ifndef POINTER64 - // In IA32, Arrays of Doubles need to be eight byte aligned to improve - // performance. In IPF all objects (arrays, class data structures, heap objects) - // get aligned on eight byte boundaries. So, this special code is not needed. - env->ArrayOfDouble_Class->alignment = ((GC_OBJECT_ALIGNMENT<8)?8:GC_OBJECT_ALIGNMENT); - // The alignment is either 4 or it is a multiple of 8. Things like 12 aren't allowed. - assert ((GC_OBJECT_ALIGNMENT==4) || ((GC_OBJECT_ALIGNMENT % 8) == 0)); - // align doubles on 8, clear alignment field and put in 8. - set_prop_alignment_mask (env->ArrayOfDouble_Class, 8); - // Set high bit in size so that gc knows there are constraints -#endif // POINTER64 + if (!vm_get_boolean_property_value_with_default("vm.assert_dialog")) { + TRACE("disabling assertion dialogs"); + disable_assert_dialogs(); + } - TRACE2("init", "preloading string class"); - env->JavaLangString_Class = preload_class(env, env->JavaLangString_String); - env->strings_are_compressed = - (class_lookup_field_recursive(env->JavaLangString_Class, "bvalue", "[B") != NULL); - env->JavaLangString_VTable = env->JavaLangString_Class->vtable; - env->JavaLangString_allocation_handle = env->JavaLangString_Class->allocation_handle; + initialize_verify_stack_enumeration(); - TRACE2("init", "preloading exceptions"); - env->java_lang_Throwable_Class = - preload_class(env, env->JavaLangThrowable_String); - env->java_lang_StackTraceElement_Class = - preload_class(env, "java/lang/StackTraceElement"); - env->java_lang_Error_Class = - preload_class(env, "java/lang/Error"); - env->java_lang_ExceptionInInitializerError_Class = - preload_class(env, "java/lang/ExceptionInInitializerError"); - env->java_lang_NoClassDefFoundError_Class = - preload_class(env, "java/lang/NoClassDefFoundError"); - env->java_lang_ClassNotFoundException_Class = - preload_class(env, "java/lang/ClassNotFoundException"); - env->java_lang_NullPointerException_Class = - preload_class(env, env->JavaLangNullPointerException_String); - env->java_lang_StackOverflowError_Class = - preload_class(env, "java/lang/StackOverflowError"); - env->java_lang_ArrayIndexOutOfBoundsException_Class = - preload_class(env, env->JavaLangArrayIndexOutOfBoundsException_String); - env->java_lang_ArrayStoreException_Class = - preload_class(env, "java/lang/ArrayStoreException"); - env->java_lang_ArithmeticException_Class = - preload_class(env, "java/lang/ArithmeticException"); - env->java_lang_ClassCastException_Class = - preload_class(env, "java/lang/ClassCastException"); - env->java_lang_OutOfMemoryError_Class = - preload_class(env, "java/lang/OutOfMemoryError"); + /* END: Property processing. */ - env->java_lang_OutOfMemoryError = oh_allocate_global_handle(); - env->popFrameException = oh_allocate_global_handle(); + // Initialize memory allocation. + vm_init_mem_alloc(); + gc_init(); - tmn_suspend_disable(); - // precompile StackOverflowError - class_alloc_new_object_and_run_default_constructor(env->java_lang_StackOverflowError_Class); - env->java_lang_OutOfMemoryError->object = - class_alloc_new_object(env->java_lang_OutOfMemoryError_Class); - env->popFrameException->object = - class_alloc_new_object(env->java_lang_Error_Class); - tmn_suspend_enable(); + // TODO: find another way to initialize the following. + Class::heap_base = (Byte *)gc_heap_base_address(); + Class::heap_end = (Byte *)gc_heap_ceiling_address(); + Class::managed_null = (vm_references_are_compressed() ? Class::heap_base : NULL); - env->java_lang_Cloneable_Class = - preload_class(env, env->Clonable_String); - env->java_lang_Thread_Class = - preload_class(env, "java/lang/Thread"); - env->java_lang_ThreadGroup_Class = - preload_class(env, "java/lang/ThreadGroup"); - env->java_util_Date_Class = - preload_class(env, "java/util/Date"); - env->java_util_Properties_Class = - preload_class(env, "java/util/Properties"); - env->java_lang_Runtime_Class = - preload_class(env, "java/lang/Runtime"); + // 20030404 This handshaking protocol isn't quite correct. It doesn't + // work at the moment because JIT has not yet been modified to support + // compressed references, so it never answers "true" to supports_compressed_references(). + status = check_compression(); + if (status != JNI_OK) return status; - env->java_lang_reflect_Constructor_Class = - preload_class(env, env->JavaLangReflectConstructor_String); - env->java_lang_reflect_Field_Class = - preload_class(env, env->JavaLangReflectField_String); - env->java_lang_reflect_Method_Class = - preload_class(env, env->JavaLangReflectMethod_String); + // Prepares to load natives + status = natives_init(); + if (status != JNI_OK) return status; - Method *m = class_lookup_method(env->java_lang_Throwable_Class, - env->Init_String, env->VoidVoidDescriptor_String); + // "Tool Interface" initialization + status = vm_env->TI->Init(); + if (status != JNI_OK) { + WARN("Failed to initialize JVMTI."); + return status; + } + + // Enable interpreter by default if TI should be enabled. + vm_env->TI->setExecutionMode(vm_env); + + extern void initialize_signals(); + initialize_signals(); + + status = vm_attach(java_vm, &jni_env); + if (status != JNI_OK) return status; + + // TODO: jni_native_intf should be removed from global namespace + jni_native_intf = jni_env; + + status = preload_classes(vm_env); + if (status != JNI_OK) return status; + + // Now the thread is attached to VM and it is valid to disable it. + hythread_suspend_disable(); + + // Create OutOfMemoryError. + vm_env->java_lang_OutOfMemoryError = oh_allocate_global_handle(); + vm_env->java_lang_OutOfMemoryError->object = + class_alloc_new_object(vm_env->java_lang_OutOfMemoryError_Class); + + // Create pop frame exception. + vm_env->popFrameException = oh_allocate_global_handle(); + vm_env->popFrameException->object = + class_alloc_new_object(vm_env->java_lang_Error_Class); + + + // Precompile StackOverflowError. + class_alloc_new_object_and_run_default_constructor(vm_env->java_lang_StackOverflowError_Class); + // Precompile ThreadDeathError. + class_alloc_new_object_and_run_default_constructor(vm_env->java_lang_ThreadDeathError_Class); + + hythread_suspend_enable(); + + // Mark j.l.Throwable() constructor as a side effects free. + Method * m = class_lookup_method(vm_env->java_lang_Throwable_Class, + vm_env->Init_String, vm_env->VoidVoidDescriptor_String); assert(m); - assert(hythread_is_suspend_enabled()); m->set_side_effects(MSE_False); - m = class_lookup_method(env->java_lang_Throwable_Class, - env->Init_String, env->FromStringConstructorDescriptor_String); + // Mark j.l.Throwable(j.l.String) constructor as a side effects free. + m = class_lookup_method(vm_env->java_lang_Throwable_Class, + vm_env->Init_String, vm_env->FromStringConstructorDescriptor_String); assert(m); m->set_side_effects(MSE_False); + void global_object_handles_init(JNIEnv *); + global_object_handles_init(jni_env); - void global_object_handles_init(); - global_object_handles_init(); - Class *aoObjectArray = preload_class(env, "[Ljava/lang/Object;"); + Class * aoObjectArray = preload_class(vm_env, "[Ljava/lang/Object;"); cached_object_array_vtable_ptr = aoObjectArray->vtable; // the following is required for creating exceptions - preload_class(env, "[Ljava/lang/VMClassRegistry;"); - extern unsigned resolve_const_pool(Global_Env& env, Class *clss); - unsigned fail_idx = resolve_const_pool(*env, env->java_lang_Throwable_Class); - if(fail_idx != 0xFFFFFFFF) - { + preload_class(vm_env, "[Ljava/lang/VMClassRegistry;"); + extern int resolve_const_pool(Global_Env& env, Class *clss); + status = resolve_const_pool(*vm_env, vm_env->java_lang_Throwable_Class); + if(status != 0) { WARN("Failed to resolve class java/lang/Throwable"); - return false; + return JNI_ERR; } // We assume, that at this point VM supports exception objects creation. - env->ReadyForExceptions(); + vm_env->ReadyForExceptions(); - TRACE2("init", "initializing thread group"); + return JNI_OK; +} + +/** + * Second VM initialization stage. At that moment JNI services are available + * and main thread has been already attached to VM. + */ +jint vm_init2(JNIEnv * jni_env) { + jint status; + Global_Env * vm_env; + assert(hythread_is_suspend_enabled()); - JNIEnv *jni_env = (JNIEnv *)jni_native_intf; - if (! init_thread_object(jni_env)) - return false; + vm_env = jni_get_vm_env(jni_env); - TRACE2("init", "Invoking the java.lang.Class constructor"); - Class *jlc = env->JavaLangClass_Class; + TRACE("Invoking the java.lang.Class constructor"); + Class * jlc = vm_env->JavaLangClass_Class; jobject jlo = struct_Class_to_java_lang_Class_Handle(jlc); jmethodID java_lang_class_init = GetMethodID(jni_env, jlo, "", "()V"); jvalue args[1]; args[0].l = jlo; - tmn_suspend_disable(); + + hythread_suspend_disable(); + vm_execute_java_method_array(java_lang_class_init, 0, args); - assert(!exn_raised()); - void unsafe_global_object_handles_init(); - unsafe_global_object_handles_init(); + void unsafe_global_object_handles_init(JNIEnv *); + unsafe_global_object_handles_init(jni_env); - tmn_suspend_enable(); + hythread_suspend_enable(); if (vm_get_boolean_property_value_with_default("vm.finalize")) { - // load and initialize finalizer thread - env->finalizer_thread = preload_class(env, "java/lang/FinalizerThread"); - assert(env->finalizer_thread); + // Load and initialize finalizer thread. + vm_env->finalizer_thread = preload_class(vm_env, "java/lang/FinalizerThread"); + assert(vm_env->finalizer_thread); - Field* finalizer_shutdown_field = class_lookup_field_recursive(env->finalizer_thread, - "shutdown", "Z"); - Field* finalizer_on_exit_field = class_lookup_field_recursive(env->finalizer_thread, - "onExit", "Z"); + Field * finalizer_shutdown_field = + class_lookup_field_recursive(vm_env->finalizer_thread, "shutdown", "Z"); + Field* finalizer_on_exit_field = + class_lookup_field_recursive(vm_env->finalizer_thread, "onExit", "Z"); assert(finalizer_shutdown_field); assert(finalizer_on_exit_field); - env->finalizer_shutdown = (jboolean*) finalizer_shutdown_field->get_address(); - env->finalizer_on_exit = (jboolean*) finalizer_on_exit_field->get_address(); - assert(env->finalizer_shutdown); - assert(env->finalizer_on_exit); - class_initialize_from_jni(env->finalizer_thread); + vm_env->finalizer_shutdown = (jboolean*) finalizer_shutdown_field->get_address(); + vm_env->finalizer_on_exit = (jboolean*) finalizer_on_exit_field->get_address(); + assert(vm_env->finalizer_shutdown); + assert(vm_env->finalizer_on_exit); + class_initialize_from_jni(vm_env->finalizer_thread); } else { - env->finalizer_thread = NULL; + vm_env->finalizer_thread = NULL; } - TRACE2("init", "initialization of system classes completed"); + TRACE("initialization of system classes completed"); #ifdef WIN32 // Code to start up Networking on Win32 WORD wVersionRequested; WSADATA wsaData; - int err; - wVersionRequested = MAKEWORD( 2, 2 ); - err = WSAStartup( wVersionRequested, &wsaData ); - - if ( err != 0 ) { + int err; + wVersionRequested = MAKEWORD(2, 2); + err = WSAStartup(wVersionRequested, &wsaData); + if (err != 0) { // Tell the user that we could not find a usable WinSock DLL. WARN("Couldn't startup Winsock 2.0 dll "); } -#endif // WIN32 +#endif #ifdef LIB_DEPENDENT_OPTS lib_dependent_opts(); #endif TRACE2("init", "initializing system class loader"); - //XXX NativeObjectHandles lhs; - bool res = initialize_system_class_loader(jni_env); - if(!res) { - WARN("Fail to initialize system class loader."); - } - if(exn_raised()) { - print_uncaught_exception_message(stderr, + status = initialize_system_class_loader(jni_env); + if (status != JNI_OK) { + WARN("Failed to initialize system class loader."); + if(exn_raised()) { + print_uncaught_exception_message(stderr, "system class loader initialisation", exn_get()); + } + return status; } - exn_clear(); // Ignore any exception that might have occured - TRACE2("init", "system class loader initialized"); - jvmti_send_vm_start_event(env, jni_env); + TRACE("system class loader initialized"); + status = run_java_init(jni_env); + if (status != JNI_OK) return status; + + TRACE("VM initialization completed"); assert(!exn_raised()); - TRACE2("init", "VM initialization completed"); - return true; -} //vm_init + return JNI_OK; +} -static bool init_thread_object(JNIEnv *jenv) -{ - Global_Env *env = VM_Global_State::loader_env; - - assert(hythread_is_suspend_enabled()); - - // Load, prepare and initialize the "Thread class" - String *ss = env->string_pool.lookup("java/lang/VMStart"); - Class *thread_clss = env->bootstrap_class_loader->LoadVerifyAndPrepareClass(env, ss); - assert(thread_clss); - assert(hythread_is_suspend_enabled()); - tmn_suspend_disable(); - class_initialize(thread_clss); - assert(!hythread_is_suspend_enabled()); - - ObjectHandle jThreadClass = oh_allocate_local_handle(); - jThreadClass->object = struct_Class_to_java_lang_Class(thread_clss); - tmn_suspend_enable(); - - jmethodID main_method = jenv->GetStaticMethodID(jThreadClass, "mainThreadInit", "()V"); - if (ExceptionOccurred(jenv) || !main_method) { - WARN("*** Error: exception occured in main Thread constructor."); - ExceptionDescribe(jenv); - ExceptionClear(jenv); - return false; - } - - jenv->CallStaticVoidMethod(jThreadClass, main_method); - - if (ExceptionOccurred(jenv)) { - WARN("*** Error: exception occured in main Thread constructor."); - ExceptionDescribe(jenv); - ExceptionClear(jenv); - return false; - } - - return true; -} //init_thread_object +JIT_Handle vm_load_jit(const char* file_name, apr_dso_handle_t** handle) { + //if (vm_is_a_jit_dll(file_name)) { + Dll_JIT* jit = new Dll_JIT(file_name); + handle[0]=jit->get_lib_handle(); + vm_add_jit(jit); + return (JIT_Handle)jit; + + //} + //printf("not a jit\n"); + //handle[0]=NULL; + //return 0; +} Index: vmcore/src/init/vm_main.cpp =================================================================== --- vmcore/src/init/vm_main.cpp (revision 454089) +++ vmcore/src/init/vm_main.cpp (working copy) @@ -1,643 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 Intel, Alexei Fedotov - * @version $Revision: 1.1.2.5.4.3 $ - */ - -#define LOG_DOMAIN "vm.core" -#include "cxxlog.h" - -#include "thread_generic.h" -#include "open/vm_util.h" -#include "open/hythread_ext.h" -#include "properties.h" -#include -#include "vm_synch.h" -#include "init.h" -#include "compile.h" -#include "method_lookup.h" -#include "nogc.h" -#include "classloader.h" -#include "thread_dump.h" -#include "interpreter.h" -#include "verify_stack_enumeration.h" - -// Multiple-JIT support. -#include "component_manager.h" -#include "jit_intf.h" -#include "dll_jit_intf.h" -#include "dll_gc.h" -#include "em_intf.h" -#include "port_filepath.h" - -union Scalar_Arg { - int i; - unsigned u; - void *p; -}; - -#include "m2n.h" -// FIXME Alexei -// There should be no need to expose internal m2n strucutre here -#ifdef _IPF_ -#include "../m2n_ipf_internal.h" -#elif defined _EM64T_ -#include "../m2n_em64t_internal.h" -#else -#include "../m2n_ia32_internal.h" -#endif - -static StaticInitializer vm_initializer; - -/* - * The VM's global environment. Extern declared in init.h - * @TODO - make this per-VM - */ -tl::MemoryPool m; -Properties properties; -Global_Env env(m, properties); - -#include "jarfile_util.h" -bool runjarfile = false; - -VMEXPORT bool instrumenting = false; - -VMEXPORT bool vtune_support = false; - -VMEXPORT bool dump_stubs = false; - -bool parallel_jit = true; - -static bool begin_shutdown_hooks = false; - -static M2nFrame* p_m2n = NULL; - -typedef union { - ObjectHandlesOld old; - ObjectHandlesNew nw; -} HandlesUnion; - -static HandlesUnion* p_handles = NULL; - -hythread_library_t hythread_lib; - -static void initialize_javahome(Global_Env* p_env) -{ - PropertiesHandle ph = (PropertiesHandle)&p_env->properties; - // Determine java home - const char* jh = properties_get_string_property(ph, "java.home"); - if (!jh) { - if (apr_env_get((char**)&jh, "JAVA_HOME", 0) != APR_SUCCESS) { - DIE("Failed to determine Java home directory"); - } - p_env->properties.add(strdup("java.home"), new Prop_String(strdup(jh))); - } -} //initialize_javahome - -/** - * Must be called after vm_arguments parsing. - */ -static void initialize_classpath(Global_Env* p_env) -{ - Properties* props = &p_env->properties; - apr_pool_t *pool; - apr_pool_create(&pool, 0); - - const char* class_path = properties_get_string_property((PropertiesHandle)props, "java.class.path"); - - // if classpath was not defined by cmd line arguments, check environment - if (!class_path) - { - apr_env_get((char**) &class_path, "CLASSPATH", pool); - if (class_path) - TRACE("No classpath specified, using \"CLASSPATH\" environment setting"); - } - - // if classpath not defined or empty string, use dafault "." value - if (!class_path || !class_path[0]) { - class_path = "."; - } - - add_pair_to_properties(*props, "java.class.path", class_path); - apr_pool_destroy(pool); -} //initialize_classpath - -static void process_properties_dlls(Global_Env* p_env) -{ - post_initialize_ee_dlls((PropertiesHandle)&p_env->properties); - - const char* dll = properties_get_string_property((PropertiesHandle)&p_env->properties, "vm.em_dll"); - TRACE2("init", "analyzing em dll " << dll); - - int ret = CmLoadComponent(dll, "EmInitialize"); - if (JNI_OK != ret) { - WARN("Cannot load EM component from " << dll << ", error " << ret); - LOGGER_EXIT(1); - } - - ret = p_env->cm->CreateInstance(&(p_env->em_instance), "em"); - if (JNI_OK != ret) { - WARN("Cannot instantiate EM, error " << ret); - LOGGER_EXIT(1); - } - - ret = p_env->em_instance->intf->GetInterface((OpenInterfaceHandle*) &(p_env->em_interface), - OPEN_INTF_EM_VM); - if (JNI_OK != ret) { - WARN("Cannot get EM_VM interface, error " << ret); - LOGGER_EXIT(1); - } - - const char* dlls = properties_get_string_property((PropertiesHandle)&p_env->properties, "vm.dlls"); - if (!dlls) { - return; - } - dlls = strdup(dlls); - assert(dlls); - static const char delimiters[] = { PORT_PATH_SEPARATOR, 0 }; - char* tok = strtok((char*)dlls, delimiters); - while (tok) { - TRACE2("init", "analyzing dll " << tok); -#ifndef USE_GC_STATIC - if (vm_is_a_gc_dll(tok)) - { - vm_add_gc(tok); - } -#endif // !USE_GC_STATIC -#ifdef USE_DISEM - else if (vm_is_a_disem_dll(tok)) { - vm_add_disem(tok); - } -#endif - else - { - WARN("Mandatory library cannot be loaded: " << tok); - LOGGER_EXIT(1); - } - tok = strtok(NULL, delimiters); - } - STD_FREE((void*)dlls); - -} //process_properties_dlls - -#define PROCESS_EXCEPTION(message) \ -{ \ - ECHO("Error occured while running starter class: " << message); \ -\ - if (jenv->ExceptionOccurred()) \ - { \ - jenv->ExceptionDescribe(); \ - jenv->ExceptionClear(); \ - } \ -\ - return 1; \ -} \ - -static int run_java_main(char *class_name, char **java_args, int java_args_num) -{ - assert(hythread_is_suspend_enabled()); - - JNIEnv* jenv = (JNIEnv*) jni_native_intf; - - jclass start_class = jenv->FindClass("java/lang/VMStart"); - if (jenv->ExceptionOccurred() || !start_class) - PROCESS_EXCEPTION("can't find starter class: java/lang/VMStart"); - - jmethodID main_method = jenv->GetStaticMethodID(start_class, "start", "(Ljava/lang/String;[Ljava/lang/String;)V"); - if (jenv->ExceptionOccurred() || !main_method) - PROCESS_EXCEPTION("can't find start method in class java/lang/VMStart"); - - jclass string_class = jenv->FindClass("java/lang/String"); - if (jenv->ExceptionOccurred() || !string_class) - PROCESS_EXCEPTION("can't find java.lang.String class"); - - jarray args = jenv->NewObjectArray(java_args_num, string_class, NULL); - if (jenv->ExceptionOccurred() || !args) - PROCESS_EXCEPTION("can't create arguments array: java.lang.String[" << java_args_num <<"]"); - - for (int i = 0; i < java_args_num; i++) - { - jstring arg = jenv->NewStringUTF(java_args[i]); - if (jenv->ExceptionOccurred() || !arg) - PROCESS_EXCEPTION("can't create java.lang.String object for \"" << java_args[i] << "\""); - - jenv->SetObjectArrayElement(args, i, arg); - if (jenv->ExceptionOccurred()) - PROCESS_EXCEPTION("can't set array element for index " << i); - } - - //create Main class name string - jstring jclassname = jenv->NewStringUTF(class_name); - - jenv->CallStaticVoidMethod(start_class, main_method, jclassname, args); - if (jenv->ExceptionOccurred()) - PROCESS_EXCEPTION("error during start(...) method execution"); - - return 0; -} //run_java_main - -static int run_java_init() -{ - assert(hythread_is_suspend_enabled()); - - JNIEnv* jenv = (JNIEnv*) jni_native_intf; - - jclass start_class = jenv->FindClass("java/lang/VMStart"); - if (jenv->ExceptionOccurred() || !start_class) - PROCESS_EXCEPTION("can't find starter class: java/lang/VMStart"); - - jmethodID init_method = jenv->GetStaticMethodID(start_class, "initialize", "()V"); - if (jenv->ExceptionOccurred() || !init_method) - PROCESS_EXCEPTION("can't find initialize method in class java/lang/VMStart"); - - jenv->CallStaticVoidMethod(start_class, init_method); - if (jenv->ExceptionOccurred()) - PROCESS_EXCEPTION("error during initialize() method execution"); - - return 0; -} //run_java_init - -static int run_java_shutdown() -{ - assert(hythread_is_suspend_enabled()); - - JNIEnv* jenv = (JNIEnv*) jni_native_intf; - - /* - * Make shutdown resistant to possible exceptions left in JNI code - */ - if (jenv->ExceptionOccurred()) { - PROCESS_EXCEPTION("Exception left unhandled before destroying VM"); - } - - jclass start_class = jenv->FindClass("java/lang/VMStart"); - if (jenv->ExceptionOccurred() || !start_class) { - PROCESS_EXCEPTION("can't find starter class: java/lang/VMStart"); - } - - jmethodID shutdown_method = jenv->GetStaticMethodID(start_class, "shutdown", "()V"); - if (jenv->ExceptionOccurred() || !shutdown_method) { - PROCESS_EXCEPTION("can't find initialize method in class java/lang/VMStart"); - } - - jenv->CallStaticVoidMethod(start_class, shutdown_method); - if (jenv->ExceptionOccurred()) { - PROCESS_EXCEPTION("error during shutdown() method execution"); - } - - return 0; -} //run_java_shutdown - -void create_vm(Global_Env *p_env, JavaVMInitArgs* vm_arguments) -{ - -#if defined(PLATFORM_NT) - OSVERSIONINFO osvi; - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - BOOL ok = GetVersionEx(&osvi); - if(!ok) { - DWORD e = GetLastError(); - printf("Windows error: %d\n", e); - exit(1); - } - if((osvi.dwMajorVersion != 4 || osvi.dwMinorVersion != 0) && // NT 4.0 - (osvi.dwMajorVersion != 5 || osvi.dwMinorVersion != 0) && // Windows 2000 - (osvi.dwMajorVersion != 5 || osvi.dwMinorVersion != 1) && // Windows XP - (osvi.dwMajorVersion != 5 || osvi.dwMinorVersion != 2)) { // Windows.NET - printf("Windows %d.%d is not supported\n", osvi.dwMajorVersion, osvi.dwMinorVersion); - exit(1); - } -#endif - hythread_init(hythread_lib); - vm_thread_init(&env); - - VM_Global_State::loader_env = &env; - hythread_attach(NULL); - // should be removed - vm_thread_attach(); - MARK_STACK_END - - p_env->TI = new DebugUtilsTI; - - assert(hythread_is_suspend_enabled()); - - vm_initialize_critical_sections(); - initialize_vm_cmd_state(p_env, vm_arguments); //PASS vm_arguments to p_env->vm_arguments and free vm_arguments - set_log_levels_from_cmd(&p_env->vm_arguments); - - if (JNI_OK != CmAcquire(&p_env->cm)) { - WARN("Cannot initialize a component manager"); - LOGGER_EXIT(1); - } - - /////////////////////////////////////////////////////////////////////////////////////////////////////// - // Begin property processing - // - // 20030407 Note: property initialization must follow initialization of the default JITs to allow - // the command line to override those default JITs. - - initialize_properties(p_env, env.properties); - - // Enable interpreter by default if TI should be enabled - p_env->TI->setExecutionMode(p_env); - - parse_vm_arguments(p_env); - - process_properties_dlls(p_env); - VERIFY(p_env->em_instance != NULL, "EM init failed"); - - parse_jit_arguments(&p_env->vm_arguments); - - // The following must go after getting propertes and parsing arguments - initialize_classpath(p_env); - initialize_javahome(p_env); - - VM_Global_State::loader_env->pin_interned_strings = - (bool)vm_get_property_value_boolean("vm.pin_interned_strings", FALSE); - - initialize_verify_stack_enumeration(); - - // - // End property processing - /////////////////////////////////////////////////////////////////////////////////////////////////////// - -#ifdef _WINDOWS - if (!vm_get_boolean_property_value_with_default("vm.assert_dialog")) - { - TRACE2("init", "disabling assertion dialogs"); - _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); - _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT); - _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); - _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDOUT); - _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); - _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT); - _set_error_mode(_OUT_TO_STDERR); - } -#endif // _WINDOWS - - // Initialize the VM's sorted list of code chunks (sorted by starting code address) - void *p = p_env->mem_pool.alloc(sizeof(Method_Lookup_Table)); - vm_methods = new (p) Method_Lookup_Table(); - - // Initialize memory allocation - vm_init_mem_alloc(); - gc_init(); - // gc_thread_init(&p_TLS_vmthread->_gc_private_information); - - // Prepares to load natives - bool UNREF status = natives_init(); - assert( status ); - // Preloading system native libraries - // initialize_natives((PropertiesHandle)&env.properties); - - jni_init(); - /* - * Valentin Al. Sitnick - * Initialisation of TI. - */ - if (0 != p_env->TI->Init()) { - WARN("JVMTI initialization failed. Exiting."); - p_env->TI->setDisabled(); - vm_exit(1); - } - - // Moved after Method_Lookup_Table initialization - extern void initialize_signals(); - initialize_signals(); - - Class::heap_base = (Byte *)gc_heap_base_address(); - Class::heap_end = (Byte *)gc_heap_ceiling_address(); - Class::managed_null = (vm_references_are_compressed() ? Class::heap_base : NULL); - - // 20030404 This handshaking protocol isn't quite correct. It doesn't work at the moment because JIT has not yet been - // modified to support compressed references, so it never answers "true" to supports_compressed_references(). - - // Check for a mismatch between whether the various VM components all compress references or not. - Boolean vm_compression = vm_references_are_compressed(); - Boolean gc_compression = gc_supports_compressed_references(); - if (vm_compression) { - if (!gc_compression) { - WARN("VM component mismatch: the VM compresses references but the GC doesn't."); - vm_exit(1); - } - - // We actually check the first element in the jit_compilers array, as current JIT - // always returns FALSE to the supports_compressed_references() call. - JIT **jit = &jit_compilers[0]; - if (!interpreter_enabled()) { - Boolean jit_compression = (*jit)->supports_compressed_references(); - if (!jit_compression) { - WARN("VM component mismatch: the VM compresses references but a JIT doesn't"); - vm_exit(1); - } - } - } else { - if (gc_compression) { - WARN("VM component mismatch: the VM doesn't compress references but the GC does."); - vm_exit(1); - } - JIT **jit = &jit_compilers[0]; - if (!interpreter_enabled()) { - Boolean jit_compression = (*jit)->supports_compressed_references(); - if (jit_compression) { - WARN("VM component mismatch: the VM doesn't compress references but a JIT does"); - vm_exit(1); - } - } - } - - // create first m2n frame - assert(hythread_is_suspend_enabled()); - tmn_suspend_disable(); - p_m2n = (M2nFrame*) p_env->mem_pool.alloc(sizeof(M2nFrame)); - p_handles = (HandlesUnion*) p_env->mem_pool.alloc(sizeof(HandlesUnion)); - - m2n_null_init(p_m2n); - m2n_set_last_frame(p_m2n); - - oh_null_init_handles((ObjectHandles*)p_handles); - m2n_set_local_handles(p_m2n, (ObjectHandles*)p_handles); - m2n_set_frame_type(p_m2n, FRAME_NON_UNWINDABLE); - tmn_suspend_enable(); - - if (! vm_init(p_env)) - { - WARN("Failed to initialize VM."); - vm_exit(1); - } - - // Send VM init event - jvmti_send_vm_init_event(p_env); - - - int result = run_java_init(); - - if (result != 0) - { - WARN("Failed execute starter class initialize() method."); - vm_exit(1); - } -} //create_vm - -static int run_main(Global_Env *p_env, char* class_name, char* jar_file, - int java_args_num, char* java_args[]) -{ - if (jar_file) - { - // check if file is archive - if(!file_is_archive(jar_file)) { - ECHO("You must specify a jar file to run."); - LOGGER_EXIT(1); - } - - // create archive file structure - void *mem_jar = STD_ALLOCA(sizeof(JarFile)); - JarFile* jarfl = new (mem_jar) JarFile(); - if(!jarfl || !(jarfl->Parse(jar_file)) ) { - ECHO("VM can't find the jar file you want to run."); - LOGGER_EXIT(1); - } - - // extract main class name from jar's manifest - class_name = strdup(archive_get_main_class_name(jarfl)); - if(!class_name) { - ECHO("Your jar file hasn't specified Main-Class manifest attribute."); - LOGGER_EXIT(1); - } - - // close archive file - jarfl->~JarFile(); - - } else if (class_name) { - // convert class name: change '.' to '/' - for (char* pointer = class_name; *pointer; pointer++) { - if (*pointer == '/') { - *pointer = '.'; - } - } - } - - // if class_name unknown print help and exit - if (!class_name) { - p_env->TI->setDisabled(); - print_generic_help(); - vm_exit(1); - } - - // run a given class - int result = run_java_main(class_name, java_args, java_args_num); - - return result; -} //run_main - -void destroy_vm(Global_Env *p_env) -{ - - run_java_shutdown(); - - // usually shutdown hooks do vm_exit(). - // so we do not reach this point - // but in case ... - - WARN("Error occured in starter class shutdown() method."); - vm_exit(-1); -} //destroy_vm - - -VMEXPORT int vm_main(int argc, char *argv[]) -{ - init_log_system(); - - char** java_args; - int java_args_num; - char* class_name; - char* jar_file; - - JavaVMInitArgs* vm_arguments = - parse_cmd_arguments(argc, argv, &class_name, &jar_file, &java_args_num); - - java_args = argv + argc - java_args_num; - - create_vm(&env, vm_arguments); - - clear_vm_arguments(vm_arguments); - - run_main(&env, class_name, jar_file, java_args_num, java_args); - - destroy_vm(&env); - - return 33; -} //vm_main - -static inline -void dump_all_java_stacks() { - hythread_iterator_t iterator; - hythread_suspend_all(&iterator, NULL); - VM_thread *thread = get_vm_thread (hythread_iterator_next(&iterator)); - while(thread) { - interpreter.stack_dump(thread); - thread = get_vm_thread (hythread_iterator_next(&iterator)); - } - hythread_resume_all( NULL); - INFO("****** END OF JAVA STACKS *****\n"); -} - -void quit_handler(int UNREF x) { - if (VM_Global_State::loader_env->shutting_down != 0) { - // too late for quit handler - // required infrastructure can be missing. - fprintf(stderr, "quit_handler(): called in shut down stage\n"); - return; - } - - if (interpreter_enabled()) { - dump_all_java_stacks(); - } else { - td_dump_all_threads(stderr); - } -} - -void interrupt_handler(int UNREF x) -{ - if (VM_Global_State::loader_env->shutting_down != 0) { - // too late for quit handler - // required infrastructure can be missing. - fprintf(stderr, "interrupt_handler(): called in shutdown stage\n"); - return; - } - - if(!begin_shutdown_hooks){ - begin_shutdown_hooks = true; - //FIXME: integration should do int another way. - //vm_set_event(non_daemon_threads_dead_handle); - }else - exit(1); //vm_exit(1); -} - -JIT_Handle vm_load_jit(const char* file_name, apr_dso_handle_t** handle) { - //if (vm_is_a_jit_dll(file_name)) { - Dll_JIT* jit = new Dll_JIT(file_name); - handle[0]=jit->get_lib_handle(); - vm_add_jit(jit); - return (JIT_Handle)jit; - - /*} - printf("not a jit\n"); - handle[0]=NULL; - return 0;*/ -} Index: vmcore/src/init/vm_shutdown.cpp =================================================================== --- vmcore/src/init/vm_shutdown.cpp (revision 0) +++ vmcore/src/init/vm_shutdown.cpp (revision 0) @@ -0,0 +1,242 @@ +/* + * 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 Intel, Evgueni Brevnov + * @version $Revision: 1.1 $ + */ + +#include +#include + +#include "open/hythread.h" +#include "open/jthread.h" + +#include "jni.h" +#include "jni_direct.h" +#include "environment.h" +#include "classloader.h" +#include "compile.h" +#include "component_manager.h" +#include "nogc.h" +#include "jni_utils.h" +#include "vm_synch.h" +#include "vm_stats.h" +#include "thread_dump.h" +#include "interpreter.h" + +#define LOG_DOMAIN "vm.core.shutdown" +#include "cxxlog.h" + + +/** + * TODO: + */ +void vm_cleanup_internal_data() { + // Print out gathered data. +#ifdef VM_STATS + ClassLoader::PrintUnloadingStats(); + VM_Statistics::get_vm_stats().print(); +#endif + + // Unload jit instances. + vm_delete_all_jits(); + + // Unload component manager and all registered components. + // TODO: why do we need to unload "em" explicitly? + CmFreeComponent("em"); + CmRelease(); + + // Unload all system native libraries. + natives_cleanup(); + + // TODO: it seems we don't need to do it!!! At least here!!! + gc_wrapup(); + + // Release global data. + // TODO: move these data to VM space. + vm_uninitialize_critical_sections(); + vm_mem_dealloc(); +} + +/** + * TODO: + */ +void vm_exit(int exit_code) +{ + jthread java_thread; + JNIEnv * jni_env; + Global_Env * vm_env; + + assert(hythread_is_suspend_enabled()); + + java_thread = jthread_self(); + jni_env = jthread_get_JNI_env(java_thread); + vm_env = jni_get_vm_env(jni_env); + + // Send VM_Death event and switch phase to VM_Death + jvmti_send_vm_death_event(); + + /* FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME * + * gregory - JVMTI shutdown should be part of DestroyVM after current VM shutdown * + * problems are fixed * + * FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME */ + // call Agent_OnUnload() for agents and unload agents + vm_env->TI->Shutdown(); + + // Raise uncaught exception to current thread. + // It will be properly processed in jthread_detach(). + if (vm_env->uncaught_exception) { + exn_raise_object(vm_env->uncaught_exception); + } + + // Detach current thread. + IDATA UNREF status = jthread_detach(java_thread); + assert(status == TM_ERROR_NONE); + + // Cleanup internal data. Disabled by default due to violation access exception. + if (vm_get_boolean_property_value_with_default("vm.cleanupOnExit")) { + jthread_cancel_all(); + vm_cleanup_internal_data(); + LOGGER_EXIT(exit_code); + } + + _exit(exit_code); +} + +#define PROCESS_EXCEPTION(message) \ +{ \ + ECHO("Internal error: " << message); \ +\ + if (jni_env->ExceptionCheck()== JNI_TRUE) \ + { \ + jni_env->ExceptionDescribe(); \ + jni_env->ExceptionClear(); \ + } \ +\ + return JNI_ERR; \ +} \ + +/** + * Calls java.lang.System.exit() method. + * Current thread should be attached to VM. + * + * @param exit_status VM exit code + */ +static jint run_system_exit(JNIEnv * jni_env, jint exit_status) { + jvalue args[1]; + + assert(hythread_is_suspend_enabled()); + + args[0].i = exit_status; + + jclass system_class = jni_env->FindClass("java/lang/System"); + if (jni_env->ExceptionCheck() == JNI_TRUE || system_class == NULL) { + // This is debug message only. May appear when VM is already in shutdown stage. + PROCESS_EXCEPTION("can't find java.lang.System class."); + } + + jmethodID exit_method = jni_env->GetStaticMethodID(system_class, "exit", "(I)V"); + if (jni_env->ExceptionCheck() == JNI_TRUE || exit_method == NULL) { + PROCESS_EXCEPTION("can't find java.lang.System.exit(int) method."); + } + + jni_env->CallStaticVoidMethodA(system_class, exit_method, args); + + if (jni_env->ExceptionCheck() == JNI_TRUE) { + PROCESS_EXCEPTION("java.lang.System.exit(int) method completed with an exception."); + } + return JNI_OK; +} + +/** + * TODO: + */ +jint vm_destroy(JavaVM_Internal * java_vm, jthread java_thread) +{ + jint status; + JNIEnv * jni_env; + + assert(hythread_is_suspend_enabled()); + + jni_env = jthread_get_JNI_env(java_thread); + + status = jthread_wait_for_all_nondaemon_threads(); + if (status != TM_ERROR_NONE) { + TRACE("Failed to wait for all non-daemon threads completion."); + return JNI_ERR; + } + + // Remember thread's uncaught exception if any. + java_vm->vm_env->uncaught_exception = jni_env->ExceptionOccurred(); + jni_env->ExceptionClear(); + + status = java_vm->vm_env->uncaught_exception == NULL ? 0 : 1; + + return run_system_exit(jni_env, status); +} + +static inline void dump_all_java_stacks() +{ + hythread_t native_thread; + hythread_iterator_t iterator; + VM_thread * vm_thread; + + INFO("****** BEGIN OF JAVA STACKS *****\n"); + + hythread_suspend_all(&iterator, NULL); + native_thread ; + while(native_thread = hythread_iterator_next(&iterator)) { + vm_thread = get_vm_thread(native_thread); + assert(vm_thread); + interpreter.stack_dump(vm_thread); + } + hythread_resume_all(NULL); + + INFO("****** END OF JAVA STACKS *****\n"); +} + +void quit_handler(int UNREF x) { + if (VM_Global_State::loader_env->shutting_down != 0) { + // too late for quit handler + // required infrastructure can be missing. + fprintf(stderr, "quit_handler(): called in shut down stage\n"); + return; + } + + if (interpreter_enabled()) { + dump_all_java_stacks(); + } else { + td_dump_all_threads(stderr); + } +} + +void interrupt_handler(int UNREF x) +{ + static bool begin_shutdown_hooks = false; + if (VM_Global_State::loader_env->shutting_down != 0) { + // too late for quit handler + // required infrastructure can be missing. + fprintf(stderr, "interrupt_handler(): called in shutdown stage\n"); + return; + } + + if(!begin_shutdown_hooks){ + begin_shutdown_hooks = true; + //FIXME: integration should do int another way. + //vm_set_event(non_daemon_threads_dead_handle); + }else + exit(1); //vm_exit(1); +} Index: vmcore/src/interpreter/interp_imports.cpp =================================================================== --- vmcore/src/interpreter/interp_imports.cpp (revision 454089) +++ vmcore/src/interpreter/interp_imports.cpp (working copy) @@ -37,9 +37,9 @@ class_throw_linking_error(ch, index, opcode); } -extern struct JNIEnv_Internal *jni_native_intf; +extern JNIEnv *jni_native_intf; -VMEXPORT struct JNIEnv_Internal* get_jni_native_intf() { +VMEXPORT JNIEnv * get_jni_native_intf() { return jni_native_intf; } Index: vmcore/src/jit/compile.cpp =================================================================== --- vmcore/src/jit/compile.cpp (revision 454089) +++ vmcore/src/jit/compile.cpp (working copy) @@ -903,7 +903,8 @@ assert(ret_ip); // Record call from caller to the callee. - CodeChunkInfo *caller = vm_methods->find(ret_ip); + Global_Env *env = VM_Global_State::loader_env; + CodeChunkInfo *caller = env->vm_methods->find(ret_ip); if (caller != NULL) { caller->record_call_to_callee(callee, ret_ip); } Index: vmcore/src/jni/jni.cpp =================================================================== --- vmcore/src/jni/jni.cpp (revision 454089) +++ vmcore/src/jni/jni.cpp (working copy) @@ -19,21 +19,25 @@ * @version $Revision: 1.1.2.2.4.5 $ */ - #define LOG_DOMAIN "jni" #include "cxxlog.h" +#include +#include +#include + +#include "open/types.h" +#include "open/hythread.h" +#include "open/jthread.h" +#include "open/vm_util.h" + #include "platform.h" #include "lock_manager.h" #include "Class.h" #include "classloader.h" #include "environment.h" #include "object_handles.h" -#include "open/types.h" -#include "open/vm_util.h" #include "vm_threads.h" -#include "open/jthread.h" - #include "vm_synch.h" #include "exceptions.h" #include "reflection.h" @@ -44,13 +48,9 @@ #include "m2n.h" #include "nogc.h" #include "init.h" - #include "Verifier_stub.h" - #include "jni_utils.h" - #include "jit_runtime_support.h" - #include "jvmti_direct.h" #ifdef _IPF_ @@ -58,6 +58,7 @@ #endif // _IPF_ static void JNICALL UnimpStub(JNIEnv*); +jint JNICALL GetVersion(JNIEnv *); struct JNINativeInterface_ jni_vtable = { @@ -65,6 +66,7 @@ (void*)UnimpStub, (void*)UnimpStub, (void*)UnimpStub, + GetVersion, DefineClass, @@ -333,29 +335,208 @@ (void*)UnimpStub, (void*)UnimpStub, - DestroyVM, + DestroyJavaVM, AttachCurrentThread, DetachCurrentThread, GetEnv, - AttachCurrentThreadAsDaemon, - + AttachCurrentThreadAsDaemon }; -static JavaVM_Internal java_vm = JavaVM_Internal(&java_vm_vtable, NULL, (void *)0x1234abcd); +/** + * List of all running in the current process. + */ +APR_RING_HEAD(JavaVM_Internal_T, JavaVM_Internal) GLOBAL_VMS; -static JNIEnv_Internal jni_env = JNIEnv_Internal(&jni_vtable, &java_vm, (void *)0x1234abcd); +/** + * Memory pool to keep global data. + */ +apr_pool_t * GLOBAL_POOL = NULL; -struct JNIEnv_Internal *jni_native_intf = &jni_env; +/** + * Used to synchronize VM creation and destruction. + */ +apr_thread_mutex_t * GLOBAL_LOCK = NULL; -void jni_init() +static jboolean & get_init_status() { + static jboolean init_status = JNI_FALSE; + return init_status; +} +/** + * Initializes JNI module. + * Should be called before creating first VM. + */ +static jint jni_init() { - java_vm.vm_env = VM_Global_State::loader_env; -} //jni_init + jint status; + if (get_init_status() == JNI_FALSE) { + status = apr_initialize(); + if (status != APR_SUCCESS) return JNI_ERR; + if (apr_atomic_cas32((volatile apr_uint32_t *)&get_init_status(), JNI_TRUE, JNI_FALSE) == JNI_FALSE) { + APR_RING_INIT(&GLOBAL_VMS, JavaVM_Internal, link); + status = apr_pool_create(&GLOBAL_POOL, 0); + if (status != APR_SUCCESS) return JNI_ERR; + + status = apr_thread_mutex_create(&GLOBAL_LOCK, APR_THREAD_MUTEX_DEFAULT, GLOBAL_POOL); + if (status != APR_SUCCESS) { + apr_pool_destroy(GLOBAL_POOL); + return JNI_ERR; + } + } + } + return JNI_OK; +} + +/* BEGIN: List of directly exported functions. */ + +JNIEXPORT jint JNICALL JNI_GetDefaultJavaVMInitArgs(void * args) +{ + // TODO: current implementation doesn't support JDK1_1InitArgs. + if (((JavaVMInitArgs *)args)->version == JNI_VERSION_1_1) { + return JNI_EVERSION; + } + ((JavaVMInitArgs *)args)->version = JNI_VERSION_1_4; + return JNI_OK; +} + +JNIEXPORT jint JNICALL JNI_GetCreatedJavaVMs(JavaVM ** vmBuf, + jsize bufLen, + jsize * nVMs) +{ + + jint status = jni_init(); + if (status != JNI_OK) { + return status; + } + + apr_thread_mutex_lock(GLOBAL_LOCK); + + *nVMs = 0; + if (!APR_RING_EMPTY(&GLOBAL_VMS, JavaVM_Internal, link)) { + JavaVM_Internal * current_vm = APR_RING_FIRST(&GLOBAL_VMS); + while (current_vm) { + if (*nVMs < bufLen) { + vmBuf[*nVMs] = (JavaVM *)current_vm; + } + ++(*nVMs); + current_vm = APR_RING_NEXT(current_vm, link); + } + + } + apr_thread_mutex_unlock(GLOBAL_LOCK); + return JNI_OK; +} + +JNIEXPORT jint JNICALL JNI_CreateJavaVM(JavaVM ** p_vm, JNIEnv ** p_jni_env, + void * args) { + jboolean daemon = JNI_FALSE; + char * name = "main"; + JNIEnv * jni_env; + JavaVMInitArgs * vm_args; + JavaVM_Internal * java_vm; + Global_Env * vm_env; + apr_pool_t * vm_global_pool; + jthread java_thread; + jint status; + + + status = jni_init(); + if (status != JNI_OK) return status; + + apr_thread_mutex_lock(GLOBAL_LOCK); + + // TODO: only one VM instance can be created in the process address space. + if (!APR_RING_EMPTY(&GLOBAL_VMS, JavaVM_Internal, link)) { + status = JNI_ERR; + goto done; + } + + // Create global memory pool. + status = apr_pool_create(&vm_global_pool, NULL); + if (status != APR_SUCCESS) { + TRACE2("jni", "Unable to create memory pool for VM"); + status = JNI_ENOMEM; + goto done; + } + + // TODO: current implementation doesn't support JDK1_1InitArgs. + if (((JavaVMInitArgs *)args)->version == JNI_VERSION_1_1) { + status = JNI_EVERSION; + goto done; + } + + vm_args = (JavaVMInitArgs *)args; + // Create JavaVM_Internal. + java_vm = (JavaVM_Internal *) apr_palloc(vm_global_pool, sizeof(JavaVM_Internal)); + if (java_vm == NULL) { + status = JNI_ENOMEM; + goto done; + } + + // Create Global_Env. + vm_env = new(vm_global_pool) Global_Env(vm_global_pool); + if (vm_env == NULL) { + status = JNI_ENOMEM; + goto done; + } + + java_vm->functions = &java_vm_vtable; + java_vm->pool = vm_global_pool; + java_vm->vm_env = vm_env; + java_vm->reserved = (void *)0x1234abcd; + *p_vm = java_vm; + + status = vm_init1(java_vm, vm_args); + if (status != JNI_OK) { + goto done; + } + + // Attaches main thread to VM. + status = vm_attach_internal(&jni_env, &java_thread, java_vm, NULL, name, daemon); + if (status != JNI_OK) goto done; + + // Attaches main thread to TM. + status = jthread_attach(jni_env, java_thread, daemon); + if (status != TM_ERROR_NONE) { + status = JNI_ERR; + goto done; + } + assert(jthread_self() != NULL); + *p_jni_env = jni_env; + + // Now JVMTIThread keeps global reference. Discared temporary global reference. + jni_env->DeleteGlobalRef(java_thread); + + // Send VM start event. JNI services are available now. + // JVMTI services permited in the start phase are available as well. + jvmti_send_vm_start_event(vm_env, jni_env); + + status = vm_init2(jni_env); + if (status != JNI_OK) { + goto done; + } + + // Send VM init event. + jvmti_send_vm_init_event(vm_env); + + // Thread start event for the main thread should be sent after VMInit callback has finished. + jvmti_send_thread_start_end_event(1); + + // Register created VM. + APR_RING_INSERT_TAIL(&GLOBAL_VMS, java_vm, JavaVM_Internal, link); + + status = JNI_OK; +done: + apr_thread_mutex_unlock(GLOBAL_LOCK); + return status; +} + +/* END: List of directly exported functions. */ + static void JNICALL UnimpStub(JNIEnv* UNREF env) { // If we ever get here, we are in an implemented JNI function @@ -614,10 +795,7 @@ TRACE2("jni", "ExceptionDescribe called"); assert(hythread_is_suspend_enabled()); if (exn_raised()) { -// tmn_suspend_disable(); //---------------------------------v - fprintf(stderr, "JNI.ExceptionDescribe: %s:\n", exn_get_name()); exn_print_stack_trace(stderr, exn_get()); -// tmn_suspend_enable(); //---------------------------------^ } } //ExceptionDescribe @@ -644,8 +822,7 @@ { TRACE2("jni", "FatalError called"); assert(hythread_is_suspend_enabled()); - fprintf(stderr, "\nFATAL error occurred in a JNI native method:\n\t%s\n", msg); - vm_exit(109); + DIE("\nFATAL error occurred in a JNI native method:\n\t" << msg); } //FatalError jobject JNICALL NewGlobalRef(JNIEnv * UNREF env, jobject obj) @@ -1256,77 +1433,156 @@ return (jlong)CallStaticIntMethod(env, bbcl, id, buf); } +/* BEGIN: Invocation API functions. */ -VMEXPORT jint JNICALL JNI_CreateJavaVM(JavaVM **p_vm, JNIEnv **p_env, void *vm_args) { - static int called = 0; // this function can only be called once for now; +VMEXPORT jint JNICALL DestroyJavaVM(JavaVM * vm) +{ + char * name = "destroy"; + jboolean daemon = JNI_FALSE; + jthread java_thread; + JavaVM_Internal * java_vm; + JNIEnv * jni_env; + jint status; - init_log_system(); - TRACE2("jni", "CreateJavaVM called"); - if (called) { - WARN("Java Invoke :: multiple VM instances are not implemented"); - ASSERT(0, "Not implemented"); - return JNI_ERR; - } else { - create_vm(&env, (JavaVMInitArgs *)vm_args); - *p_env = &jni_env; - *p_vm = jni_env.vm; + TRACE2("jni", "DestroyJavaVM called"); + + java_vm = (JavaVM_Internal *) vm; + + java_thread = jthread_self(); + if (java_thread == NULL) { + // Attaches main thread to VM. + status = vm_attach_internal(&jni_env, &java_thread, java_vm, NULL, name, daemon); + if (status != JNI_OK) return status; + + status = jthread_attach(jni_env, java_thread, daemon); + if (status != TM_ERROR_NONE) return JNI_ERR; + // Now JVMTIThread keeps global reference. Discared temporary global reference. + jni_env->DeleteGlobalRef(java_thread); + + java_thread = jthread_self(); + } + assert(java_thread != NULL); + + apr_thread_mutex_lock(GLOBAL_LOCK); + + status = vm_destroy(java_vm, java_thread); + if (status != JNI_OK) return status; + + APR_RING_REMOVE(java_vm, link); + + // Destroy VM environment. + delete java_vm->vm_env; + + // Destroy VM pool. + apr_pool_destroy(java_vm->pool); + + // TODO: Destroy globals if it is last VM. + + apr_thread_mutex_unlock(GLOBAL_LOCK); + + // TODO: error code should be returned until + // VM cleanups its internals properly. + return JNI_ERR; +} + +static jint attach_current_thread(JavaVM * java_vm, void ** p_jni_env, void * args, jboolean daemon) +{ + char * name; + jobject group; + JNIEnv * jni_env; + JavaVMAttachArgs * jni_1_2_args; + jthread java_thread; + IDATA status; + + TRACE2("jni", "AttachCurrentThread called"); + + if (jthread_self()) { + *p_jni_env = jthread_get_JNI_env(jthread_self()); return JNI_OK; } + + name = NULL; + group = NULL; + + if (args != NULL) { + jni_1_2_args = (JavaVMAttachArgs *) args; + if (jni_1_2_args->version != JNI_VERSION_1_2) { + return JNI_EVERSION; + } + name = jni_1_2_args->name; + group = jni_1_2_args->group; + } + + // Attaches current thread to VM. + status = vm_attach_internal(&jni_env, &java_thread, java_vm, group, name, daemon); + if (status != JNI_OK) return status; + + *p_jni_env = jni_env; + + // Attaches current thread to TM. + status = jthread_attach(jni_env, java_thread, daemon); + assert(jthread_self() != NULL); + + // Now JVMTIThread keeps global reference. Discared temporary global reference. + jni_env->DeleteGlobalRef(java_thread); + + // Send thread start event. + // TODO: Thread start event should be sent before its initial method executes. + jvmti_send_thread_start_end_event(1); + + return status == TM_ERROR_NONE ? JNI_OK : JNI_ERR; } - -VMEXPORT jint JNICALL DestroyVM(JavaVM*) +VMEXPORT jint JNICALL AttachCurrentThread(JavaVM * vm, void ** p_jni_env, void * args) { - TRACE2("jni", "DestroyVM called"); - destroy_vm(&env); - return JNI_OK; + return attach_current_thread(vm, p_jni_env, args, JNI_FALSE); } -VMEXPORT jint JNICALL AttachCurrentThread(JavaVM* vm, void** penv, void* UNREF args) +VMEXPORT jint JNICALL AttachCurrentThreadAsDaemon(JavaVM * vm, void ** p_jni_env, void * args) { - TRACE2("jni", "AttachCurrentThread called"); - if (NULL == p_TLS_vmthread) - WARN("WARNING!! Attaching deattached thread is not implemented!!\n"); - GetEnv(vm, penv, JNI_VERSION_1_4); - return JNI_ERR; + return attach_current_thread(vm, p_jni_env, args, JNI_TRUE); } -VMEXPORT jint JNICALL DetachCurrentThread(JavaVM*) +VMEXPORT jint JNICALL DetachCurrentThread(JavaVM * vm) { - WARN("Java Invoke :: DetachCurrentThread not implemented"); - ASSERT(0, "Not implemented"); - return JNI_ERR; + jthread java_thread; + IDATA status; + + java_thread = jthread_self(); + if (java_thread == NULL) return JNI_EDETACHED; + + status = jthread_detach(java_thread); + + // Send thread end event. + jvmti_send_thread_start_end_event(0); + return status == TM_ERROR_NONE ? JNI_OK : JNI_ERR; } -VMEXPORT jint JNICALL GetEnv(JavaVM* vm, void** penv, jint ver) +VMEXPORT jint JNICALL GetEnv(JavaVM * vm, void ** penv, jint ver) { + VM_thread * vm_thread; + TRACE2("jni", "GetEnv called, ver = " << ver); assert(hythread_is_suspend_enabled()); - if (p_TLS_vmthread == NULL) - return JNI_EDETACHED; + vm_thread = p_TLS_vmthread; + if (vm_thread == NULL) return JNI_EDETACHED; - if ((ver & JVMTI_VERSION_MASK_INTERFACE_TYPE) == JVMTI_VERSION_INTERFACE_JNI) - switch (ver) - { + if ((ver & JVMTI_VERSION_MASK_INTERFACE_TYPE) == JVMTI_VERSION_INTERFACE_JNI) { + switch (ver) { case JNI_VERSION_1_1: case JNI_VERSION_1_2: case JNI_VERSION_1_4: - *penv = (void*)jni_native_intf; + *penv = (void*)vm_thread->jni_env; return JNI_OK; } - else if((ver & JVMTI_VERSION_MASK_INTERFACE_TYPE) == JVMTI_VERSION_INTERFACE_JVMTI) + } else if((ver & JVMTI_VERSION_MASK_INTERFACE_TYPE) == JVMTI_VERSION_INTERFACE_JVMTI) { return create_jvmti_environment(vm, penv, ver); - else if((ver & JVMTI_VERSION_MASK_INTERFACE_TYPE) == 0x10000000) - { + } else if((ver & JVMTI_VERSION_MASK_INTERFACE_TYPE) == 0x10000000) { WARN("GetEnv requested unsupported JVMPI environment!! Only JVMTI is supported by VM."); - } - else if((ver & JVMTI_VERSION_MASK_INTERFACE_TYPE) == 0x20000000) - { + } else if((ver & JVMTI_VERSION_MASK_INTERFACE_TYPE) == 0x20000000) { WARN("GetEnv requested unsupported JVMDI environment!! Only JVMTI is supported by VM."); - } - else - { + } else { WARN("GetEnv called with unsupported interface version 0x" << ((void *)((POINTER_SIZE_INT)ver))); } @@ -1334,12 +1590,7 @@ return JNI_EVERSION; } -VMEXPORT jint JNICALL AttachCurrentThreadAsDaemon(JavaVM*, void** UNREF penv, void* UNREF args) -{ - WARN("Java Invoke :: AttachCurrentThreadAsDaemon not implemented"); - ASSERT(0, "Not implemented"); - return JNI_ERR; -} +/* END: Invocation API functions. */ /* Global Handles: see jni_utils.h for more information about them */ ObjectHandle gh_jlc; @@ -1384,21 +1635,19 @@ jdouble gc_double_POSITIVE_INFINITY = 0; jdouble gc_double_NEGATIVE_INFINITY = 0; - +// TODO: should return error code instead of exiting. static void check_for_unexpected_exception(){ assert(hythread_is_suspend_enabled()); if (exn_raised()) { - fprintf(stderr, "Error initializing java machine\n"); - fprintf(stderr, "Uncaught and unexpected exception\n"); print_uncaught_exception_message(stderr, "static initializing", exn_get()); - vm_exit(1); + DIE("Error initializing java machine\n"); } } -void global_object_handles_init(){ - Global_Env *env = VM_Global_State::loader_env; - JNIEnv_Internal *jenv = jni_native_intf; +void global_object_handles_init(JNIEnv * jni_env) { + Global_Env * vm_env = jni_get_vm_env(jni_env); + gh_jlc = oh_allocate_global_handle(); gh_jls = oh_allocate_global_handle(); gh_jlcloneable = oh_allocate_global_handle(); @@ -1422,27 +1671,27 @@ ObjectHandle h_jlt = oh_allocate_global_handle(); tmn_suspend_disable(); - gh_jlc->object = struct_Class_to_java_lang_Class(env->JavaLangClass_Class); - gh_jls->object = struct_Class_to_java_lang_Class(env->JavaLangString_Class); - gh_jlcloneable->object = struct_Class_to_java_lang_Class(env->java_lang_Cloneable_Class); - gh_aoboolean->object = struct_Class_to_java_lang_Class(env->ArrayOfBoolean_Class); - gh_aobyte->object = struct_Class_to_java_lang_Class(env->ArrayOfByte_Class); - gh_aochar->object = struct_Class_to_java_lang_Class(env->ArrayOfChar_Class); - gh_aoshort->object = struct_Class_to_java_lang_Class(env->ArrayOfShort_Class); - gh_aoint->object = struct_Class_to_java_lang_Class(env->ArrayOfInt_Class); - gh_aolong->object = struct_Class_to_java_lang_Class(env->ArrayOfLong_Class); - gh_aofloat->object = struct_Class_to_java_lang_Class(env->ArrayOfFloat_Class); - gh_aodouble->object = struct_Class_to_java_lang_Class(env->ArrayOfDouble_Class); + gh_jlc->object = struct_Class_to_java_lang_Class(vm_env->JavaLangClass_Class); + gh_jls->object = struct_Class_to_java_lang_Class(vm_env->JavaLangString_Class); + gh_jlcloneable->object = struct_Class_to_java_lang_Class(vm_env->java_lang_Cloneable_Class); + gh_aoboolean->object = struct_Class_to_java_lang_Class(vm_env->ArrayOfBoolean_Class); + gh_aobyte->object = struct_Class_to_java_lang_Class(vm_env->ArrayOfByte_Class); + gh_aochar->object = struct_Class_to_java_lang_Class(vm_env->ArrayOfChar_Class); + gh_aoshort->object = struct_Class_to_java_lang_Class(vm_env->ArrayOfShort_Class); + gh_aoint->object = struct_Class_to_java_lang_Class(vm_env->ArrayOfInt_Class); + gh_aolong->object = struct_Class_to_java_lang_Class(vm_env->ArrayOfLong_Class); + gh_aofloat->object = struct_Class_to_java_lang_Class(vm_env->ArrayOfFloat_Class); + gh_aodouble->object = struct_Class_to_java_lang_Class(vm_env->ArrayOfDouble_Class); tmn_suspend_enable(); //-------------------------------------------------------^ - Class *preload_class(Global_Env* env, const char *classname); - Class* jlboolean = preload_class(env, "java/lang/Boolean"); - Class* jlbyte = preload_class(env, "java/lang/Byte"); - Class* jlchar = preload_class(env, "java/lang/Character"); - Class* jlshort = preload_class(env, "java/lang/Short"); - Class* jlint = preload_class(env, "java/lang/Integer"); - Class* jllong = preload_class(env, "java/lang/Long"); - Class* jlfloat = preload_class(env, "java/lang/Float"); - Class* jldouble = preload_class(env, "java/lang/Double"); + Class *preload_class(Global_Env* vm_env, const char *classname); + Class* jlboolean = preload_class(vm_env, "java/lang/Boolean"); + Class* jlbyte = preload_class(vm_env, "java/lang/Byte"); + Class* jlchar = preload_class(vm_env, "java/lang/Character"); + Class* jlshort = preload_class(vm_env, "java/lang/Short"); + Class* jlint = preload_class(vm_env, "java/lang/Integer"); + Class* jllong = preload_class(vm_env, "java/lang/Long"); + Class* jlfloat = preload_class(vm_env, "java/lang/Float"); + Class* jldouble = preload_class(vm_env, "java/lang/Double"); tmn_suspend_disable(); gh_jlboolean->object = struct_Class_to_java_lang_Class(jlboolean); @@ -1453,33 +1702,34 @@ gh_jllong->object = struct_Class_to_java_lang_Class(jllong); gh_jlfloat->object = struct_Class_to_java_lang_Class(jlfloat); gh_jldouble->object = struct_Class_to_java_lang_Class(jldouble); - h_jlt->object= struct_Class_to_java_lang_Class(env->java_lang_Throwable_Class); + h_jlt->object= struct_Class_to_java_lang_Class(vm_env->java_lang_Throwable_Class); tmn_suspend_enable(); //-------------------------------------------------------^ assert(hythread_is_suspend_enabled()); - gid_throwable_traceinfo = jenv->GetFieldID((jclass)h_jlt, "vm_stacktrace", "[J"); + gid_throwable_traceinfo = jni_env->GetFieldID((jclass)h_jlt, "vm_stacktrace", "[J"); assert(hythread_is_suspend_enabled()); - gid_boolean_value = jenv->GetFieldID((jclass)gh_jlboolean, "value", "Z"); - gid_byte_value = jenv->GetFieldID((jclass)gh_jlbyte, "value", "B"); - gid_char_value = jenv->GetFieldID((jclass)gh_jlchar, "value", "C"); - gid_short_value = jenv->GetFieldID((jclass)gh_jlshort, "value", "S"); - gid_int_value = jenv->GetFieldID((jclass)gh_jlint, "value", "I"); - gid_long_value = jenv->GetFieldID((jclass)gh_jllong, "value", "J"); - gid_float_value = jenv->GetFieldID((jclass)gh_jlfloat, "value", "F"); - gid_double_value = jenv->GetFieldID((jclass)gh_jldouble, "value", "D"); + gid_boolean_value = jni_env->GetFieldID((jclass)gh_jlboolean, "value", "Z"); + gid_byte_value = jni_env->GetFieldID((jclass)gh_jlbyte, "value", "B"); + gid_char_value = jni_env->GetFieldID((jclass)gh_jlchar, "value", "C"); + gid_short_value = jni_env->GetFieldID((jclass)gh_jlshort, "value", "S"); + gid_int_value = jni_env->GetFieldID((jclass)gh_jlint, "value", "I"); + gid_long_value = jni_env->GetFieldID((jclass)gh_jllong, "value", "J"); + gid_float_value = jni_env->GetFieldID((jclass)gh_jlfloat, "value", "F"); + gid_double_value = jni_env->GetFieldID((jclass)gh_jldouble, "value", "D"); assert(hythread_is_suspend_enabled()); - gid_doubleisNaN = jenv->GetStaticMethodID((jclass)gh_jldouble, "isNaN", "(D)Z"); + gid_doubleisNaN = jni_env->GetStaticMethodID((jclass)gh_jldouble, "isNaN", "(D)Z"); - gid_stringinit = jenv->GetMethodID((jclass)gh_jls, "", "([C)V"); - gid_string_field_value = jenv->GetFieldID((jclass)gh_jls, "value", "[C"); - if(env->strings_are_compressed) - gid_string_field_bvalue = jenv->GetFieldID((jclass)gh_jls, "bvalue", "[B"); - assert(hythread_is_suspend_enabled()); + gid_stringinit = jni_env->GetMethodID((jclass)gh_jls, "", "([C)V"); + gid_string_field_value = jni_env->GetFieldID((jclass)gh_jls, "value", "[C"); + + if (vm_env->strings_are_compressed) { + gid_string_field_bvalue = jni_env->GetFieldID((jclass)gh_jls, "bvalue", "[B"); + } - gid_string_field_offset = jenv->GetFieldID((jclass)gh_jls, "offset", "I"); - gid_string_field_count = jenv->GetFieldID((jclass)gh_jls, "count", "I"); + gid_string_field_offset = jni_env->GetFieldID((jclass)gh_jls, "offset", "I"); + gid_string_field_count = jni_env->GetFieldID((jclass)gh_jls, "count", "I"); assert(hythread_is_suspend_enabled()); oh_deallocate_global_handle(h_jlt); @@ -1493,18 +1743,17 @@ assert(hythread_is_suspend_enabled()); } -void unsafe_global_object_handles_init(){ +void unsafe_global_object_handles_init(JNIEnv * jni_env) { assert(!hythread_is_suspend_enabled()); tmn_suspend_enable(); - JNIEnv_Internal *jenv = jni_native_intf; - jfieldID POSITIVE_INFINITY_id = jenv->GetStaticFieldID((jclass)gh_jldouble, "POSITIVE_INFINITY", "D"); - gc_double_POSITIVE_INFINITY = jenv->GetStaticDoubleField((jclass)gh_jldouble, POSITIVE_INFINITY_id); + jfieldID POSITIVE_INFINITY_id = jni_env->GetStaticFieldID((jclass)gh_jldouble, "POSITIVE_INFINITY", "D"); + gc_double_POSITIVE_INFINITY = jni_env->GetStaticDoubleField((jclass)gh_jldouble, POSITIVE_INFINITY_id); check_for_unexpected_exception(); assert(hythread_is_suspend_enabled()); - jfieldID NEGATIVE_INFINITY_id = jenv->GetStaticFieldID((jclass)gh_jldouble, "NEGATIVE_INFINITY", "D"); - gc_double_NEGATIVE_INFINITY = jenv->GetStaticDoubleField((jclass)gh_jldouble, NEGATIVE_INFINITY_id); + jfieldID NEGATIVE_INFINITY_id = jni_env->GetStaticFieldID((jclass)gh_jldouble, "NEGATIVE_INFINITY", "D"); + gc_double_NEGATIVE_INFINITY = jni_env->GetStaticDoubleField((jclass)gh_jldouble, NEGATIVE_INFINITY_id); assert(hythread_is_suspend_enabled()); check_for_unexpected_exception(); assert(hythread_is_suspend_enabled()); Index: vmcore/src/jni/jni_utils.cpp =================================================================== --- vmcore/src/jni/jni_utils.cpp (revision 454089) +++ vmcore/src/jni/jni_utils.cpp (working copy) @@ -84,10 +84,10 @@ return cl; } //class_loader_lookup -void class_loader_load_native_lib( const char* lib, +void class_loader_load_native_lib(const char* lib, ClassLoaderHandle cl) { - cl->LoadNativeLibrary( lib ); + cl->LoadNativeLibrary(lib); } @@ -102,12 +102,6 @@ return cl; } //class_loader_find_if_exists - -void class_loader_set_system_class_loader(ClassLoaderHandle cl) -{ - VM_Global_State::loader_env->system_class_loader = (UserDefinedClassLoader*) cl; -} - VMEXPORT jvalue *get_jvalue_arg_array(Method *method, va_list args) { @@ -453,7 +447,6 @@ jclass SignatureToClass (JNIEnv* env_ext, const char* sig, ClassLoader *class_loader) { assert(hythread_is_suspend_enabled()); - JNIEnv_Internal *env = (JNIEnv_Internal *)env_ext; assert (sig); if (sig[0] == 'L' || sig[0] == '[') { @@ -463,7 +456,7 @@ return clazz; } - Global_Env *ge = env->vm->vm_env; + Global_Env *ge = jni_get_vm_env(env_ext); Class* clss = NULL; switch (sig[0]) { @@ -499,7 +492,7 @@ break; } - return jni_class_from_handle(env, clss); + return jni_class_from_handle(env_ext, clss); } // SignatureToClass @@ -722,8 +715,7 @@ jthrowable exn = class_get_error(loader, name->bytes); assert(exn); exn_clear(); - jint UNUSED ok = Throw(env, exn); - assert(ok == 0); + Throw(env, exn); return 0; } } @@ -817,3 +809,11 @@ } return true; } + +JavaVM * jni_get_java_vm(JNIEnv * jni_env) { + return ((JNIEnv_Internal *)jni_env)->vm; +} + +Global_Env * jni_get_vm_env(JNIEnv * jni_env) { + return ((JNIEnv_Internal *)jni_env)->vm->vm_env; +} Index: vmcore/src/jvmti/jvmti.cpp =================================================================== --- vmcore/src/jvmti/jvmti.cpp (revision 454089) +++ vmcore/src/jvmti/jvmti.cpp (working copy) @@ -290,7 +290,7 @@ !strncmp(option, "-Xrun", 5)) { TRACE2("jvmti", "Enabling EM JVMTI mode"); - add_pair_to_properties(p_env->properties, "vm.jvmti.enabled", "true"); + add_pair_to_properties(*p_env->properties, "vm.jvmti.enabled", "true"); break; } } @@ -472,7 +472,7 @@ const char *lib_name, char **p_path1, char **p_path2) { - const char *vm_libs = vm->vm_env->properties.get("vm.boot.library.path")->as_string(); + const char *vm_libs = vm->vm_env->properties->get("vm.boot.library.path")->as_string(); assert(vm_libs); char *path1 = apr_pstrdup(pool, vm_libs); char *path2 = port_dso_name_decorate(lib_name, pool); Index: vmcore/src/jvmti/jvmti_break.cpp =================================================================== --- vmcore/src/jvmti/jvmti_break.cpp (revision 454089) +++ vmcore/src/jvmti/jvmti_break.cpp (working copy) @@ -64,7 +64,7 @@ hThread->object = (Java_java_lang_Thread *)j_thread->object; tmn_suspend_enable(); - JNIEnv *jni_env = (JNIEnv *)jni_native_intf; + JNIEnv *jni_env = jni_native_intf; jvmtiEventBreakpoint func = (jvmtiEventBreakpoint)env->get_event_callback(JVMTI_EVENT_BREAKPOINT); Index: vmcore/src/jvmti/jvmti_event.cpp =================================================================== --- vmcore/src/jvmti/jvmti_event.cpp (revision 454089) +++ vmcore/src/jvmti/jvmti_event.cpp (working copy) @@ -80,7 +80,6 @@ jvmtiError add_event_to_thread(jvmtiEnv *env, jvmtiEvent event_type, jthread event_thread) { TIEnv *p_env = (TIEnv *)env; - //JNIEnv *jni_env = jni_native_intf; hythread_t p_thread = jthread_get_native_thread(event_thread); TIEventThread *et = p_env->event_threads[event_type - JVMTI_MIN_EVENT_TYPE_VAL]; @@ -107,7 +106,6 @@ void remove_event_from_thread(jvmtiEnv *env, jvmtiEvent event_type, jthread event_thread) { TIEnv *p_env = (TIEnv *)env; - // JNIEnv *jni_env = jni_native_intf; hythread_t p_thread = jthread_get_native_thread(event_thread); TIEventThread *et = p_env->event_threads[event_type - JVMTI_MIN_EVENT_TYPE_VAL]; @@ -419,7 +417,7 @@ tmn_suspend_enable(); // Send VM_INIT TI events TIEnv *ti_env = ti->getEnvironments(); - JNIEnv *jni_env = (JNIEnv *)jni_native_intf; + JNIEnv *jni_env = jni_native_intf; TIEnv *next_env; while (NULL != ti_env) { @@ -652,7 +650,7 @@ // event is enabled in this environment jthread thread = getCurrentThread(); - JNIEnv *jni_env = (JNIEnv *)jni_native_intf; + JNIEnv *jni_env = jni_native_intf; jvmtiEnv *jvmti_env = (jvmtiEnv*) ti_env; if (NULL != ti_env->event_table.MethodEntry) @@ -696,7 +694,7 @@ // event is enabled in this environment jthread thread = getCurrentThread(); - JNIEnv *jni_env = (JNIEnv *)jni_native_intf; + JNIEnv *jni_env = jni_native_intf; jvmtiEnv *jvmti_env = (jvmtiEnv*) ti_env; if (NULL != ti_env->event_table.MethodExit) { TRACE2("jvmti.stack", "Calling MethodExit callback for method: " @@ -843,7 +841,7 @@ TIEnv *ti_env = (TIEnv*) jvmti_env; jthread thread = getCurrentThread(); - JNIEnv *jni_env = (JNIEnv *)jni_native_intf; + JNIEnv *jni_env = jni_native_intf; assert(method); TRACE2("jvmti.event.popframe", "PopFrame event is called for method:" @@ -895,7 +893,7 @@ // event is enabled in this environment jthread thread = getCurrentThread(); - JNIEnv *jni_env = (JNIEnv *)jni_native_intf; + JNIEnv *jni_env = jni_native_intf; jvmtiEnv *jvmti_env = (jvmtiEnv*) ti_env; TRACE2("jvmti.break.ss", "Calling SingleStep callback for env " << jvmti_env << ": " << @@ -974,7 +972,7 @@ // event is enabled in this environment jthread thread = getCurrentThread(); - JNIEnv *jni_env = (JNIEnv *)jni_native_intf; + JNIEnv *jni_env = jni_native_intf; jvmtiEnv *jvmti_env = (jvmtiEnv*) ti_env; if (NULL != ti_env->event_table.FieldAccess) @@ -1049,7 +1047,7 @@ // event is enabled in this environment jthread thread = getCurrentThread(); - JNIEnv *jni_env = (JNIEnv *)jni_native_intf; + JNIEnv *jni_env = jni_native_intf; jvmtiEnv *jvmti_env = (jvmtiEnv*) ti_env; if (NULL != ti_env->event_table.FieldModification) @@ -1080,7 +1078,7 @@ assert(ti->isEnabled()); // Create local handles frame - JNIEnv *jni_env = (JNIEnv *)jni_native_intf; + JNIEnv *jni_env = jni_native_intf; ObjectHandle hThread = oh_allocate_local_handle(); hThread->object = (Java_java_lang_Thread *)jthread_get_java_thread(curr_native_thread)->object; @@ -1234,7 +1232,7 @@ hythread_t curr_thread = hythread_self(); // Create local handles frame - JNIEnv *jni_env = (JNIEnv *)jni_native_intf; + JNIEnv *jni_env = jni_native_intf; ObjectHandle exn_object = oh_allocate_local_handle(); exn_object->object = exn; @@ -1351,7 +1349,7 @@ return; } - JNIEnv *jni_env = (JNIEnv *)jni_native_intf; + JNIEnv *jni_env = jni_native_intf; tmn_suspend_disable(); // Create local handles frame @@ -1408,7 +1406,7 @@ return; } - JNIEnv *jni_env = (JNIEnv *)jni_native_intf; + JNIEnv *jni_env = jni_native_intf; tmn_suspend_disable(); ObjectHandle hThread = oh_allocate_local_handle(); ObjectHandle hClass = oh_allocate_local_handle(); @@ -1467,7 +1465,7 @@ if (!ti->isEnabled()) return; - JNIEnv *jni_env = (JNIEnv *)jni_native_intf; + JNIEnv *jni_env = jni_native_intf; tmn_suspend_disable(); ObjectHandle hLoader = oh_convert_to_local_handle((ManagedObject*)loader->GetLoader()); if( !(hLoader->object) ) hLoader = NULL; @@ -1552,7 +1550,7 @@ return; } - JNIEnv *jni_env = (JNIEnv *)jni_native_intf; + JNIEnv *jni_env = jni_native_intf; tmn_suspend_disable(); // -----------vv ObjectHandle hThread = oh_allocate_local_handle(); ObjectHandle hClass = oh_allocate_local_handle(); @@ -1650,7 +1648,7 @@ static void process_jvmti_event(jvmtiEvent event_type, int per_thread, ...) { va_list args; - JNIEnv *jni_env = (JNIEnv *)jni_native_intf; + JNIEnv *jni_env = jni_native_intf; TIEnv *ti_env, *next_env; DebugUtilsTI *ti = VM_Global_State::loader_env->TI; void *callback_func; @@ -1759,7 +1757,7 @@ if (ti_env->global_events[JVMTI_EVENT_VM_DEATH - JVMTI_MIN_EVENT_TYPE_VAL]) { jvmtiEventVMDeath func = (jvmtiEventVMDeath)ti_env->get_event_callback(JVMTI_EVENT_VM_DEATH); - JNIEnv *jni_env = (JNIEnv *)jni_native_intf; + JNIEnv *jni_env = jni_native_intf; if (NULL != func) { TRACE2("jvmti.event.vd", "Callback JVMTI_PHASE_DEATH called"); Index: vmcore/src/jvmti/jvmti_property.cpp =================================================================== --- vmcore/src/jvmti/jvmti_property.cpp (revision 454089) +++ vmcore/src/jvmti/jvmti_property.cpp (working copy) @@ -75,7 +75,7 @@ // get bootclasspath property Global_Env *g_env = ((TIEnv*)env)->vm->vm_env; - Properties *properties = &g_env->properties; + Properties *properties = g_env->properties; const char *bcp_prop = properties_get_string_property( reinterpret_cast(properties), "vm.boot.class.path"); @@ -131,7 +131,7 @@ jint properties_count = 0; - Properties::Iterator *iterator = ((TIEnv*)env)->vm->vm_env->properties.getIterator(); + Properties::Iterator *iterator = ((TIEnv*)env)->vm->vm_env->properties->getIterator(); const Prop_entry *next = NULL; while((next = iterator->next())) properties_count++; @@ -142,7 +142,7 @@ return errorCode; // Copy properties defined in properties list - iterator = ((TIEnv*)env)->vm->vm_env->properties.getIterator(); + iterator = ((TIEnv*)env)->vm->vm_env->properties->getIterator(); for (int iii = 0; iii < properties_count; iii++) { next = iterator->next(); @@ -188,7 +188,7 @@ if (NULL == property || NULL == value_ptr) return JVMTI_ERROR_NULL_POINTER; - Prop_Value *prop_value = ((TIEnv*)env)->vm->vm_env->properties.get(property); + Prop_Value *prop_value = ((TIEnv*)env)->vm->vm_env->properties->get(property); if (NULL == prop_value) return JVMTI_ERROR_NOT_AVAILABLE; @@ -240,9 +240,9 @@ e->key = strdup(property); e->value = ps; - Prop_entry *pe = vm_env->properties.get_entry(property); + Prop_entry *pe = vm_env->properties->get_entry(property); if (NULL == pe) - vm_env->properties.add(e); + vm_env->properties->add(e); else pe->replace(e); Index: vmcore/src/jvmti/jvmti_step.cpp =================================================================== --- vmcore/src/jvmti/jvmti_step.cpp (revision 454089) +++ vmcore/src/jvmti/jvmti_step.cpp (working copy) @@ -31,6 +31,7 @@ #include "open/bytecodes.h" #include "open/jthread.h" #include "jvmti_break_intf.h" +#include "jni_utils.h" static inline short jvmti_GetHalfWordValue( const unsigned char *bytecode, @@ -483,7 +484,8 @@ // call so we need to search through all methods for this // one to find it, no way to get vtable and offset in it NativeCodePtr ip = disasm->get_target_address_from_context(regs); - CodeChunkInfo *cci = vm_methods->find(ip); + Global_Env * vm_env = jni_get_vm_env(vm_thread->jni_env); + CodeChunkInfo *cci = vm_env->vm_methods->find(ip); if (cci) method = cci->get_method(); else Index: vmcore/src/jvmti/jvmti_thread.cpp =================================================================== --- vmcore/src/jvmti/jvmti_thread.cpp (revision 454089) +++ vmcore/src/jvmti/jvmti_thread.cpp (working copy) @@ -26,6 +26,7 @@ #include "cxxlog.h" #include "jvmti_utils.h" +#include "jni_utils.h" #include "vm_threads.h" #include "thread_generic.h" @@ -648,6 +649,8 @@ const void* arg, jint priority) { + JNIEnv * jni_env; + TRACE2("jvmti.thread", "RunAgentThread called"); SuspendEnabledChecker sec; /* @@ -673,6 +676,8 @@ jmethodID set_daemon = GetMethodID(jvmti_test_jenv, thread_class, "setDaemon", "(Z)V"); assert(set_daemon); CallVoidMethod(jvmti_test_jenv, thread, set_daemon, JNI_TRUE); + + jni_env = jthread_get_JNI_env(jthread_self()); // Run new thread // FIXME TM integration, pass arguments correctly //Java_java_lang_Thread_start_generic(jvmti_test_jenv, thread, env, proc, arg, priority); @@ -681,7 +686,7 @@ attrs.stacksize = 0; attrs.daemon = JNI_TRUE; attrs.jvmti_env = env; - jthread_create_with_function(jvmti_test_jenv, thread, &attrs, proc, arg); + jthread_create_with_function(jni_env, thread, &attrs, proc, arg); return JVMTI_ERROR_NONE; } Index: vmcore/src/jvmti/jvmti_thread_group.cpp =================================================================== --- vmcore/src/jvmti/jvmti_thread_group.cpp (revision 454089) +++ vmcore/src/jvmti/jvmti_thread_group.cpp (working copy) @@ -30,7 +30,7 @@ #include "suspend_checker.h" #include "environment.h" -static JNIEnv_Internal * jvmti_test_jenv = jni_native_intf; +static JNIEnv * jvmti_test_jenv = jni_native_intf; /* * Get Top Thread Groups Index: vmcore/src/kernel_classes/javasrc/java/lang/ClassLoader.java =================================================================== --- vmcore/src/kernel_classes/javasrc/java/lang/ClassLoader.java (revision 454089) +++ vmcore/src/kernel_classes/javasrc/java/lang/ClassLoader.java (working copy) @@ -163,7 +163,7 @@ // current thread isn't allowed to set systemClassLoader as a // context class loader. Actually, it is abnormal situation if // thread can not change his own context class loader. - Thread.currentThread().setContextClassLoader(systemClassLoader); + // Thread.currentThread().setContextClassLoader(systemClassLoader); } //assert initialized; SecurityManager sc = System.getSecurityManager(); Index: vmcore/src/kernel_classes/javasrc/java/lang/EMThreadSupport.java =================================================================== --- vmcore/src/kernel_classes/javasrc/java/lang/EMThreadSupport.java (revision 454089) +++ vmcore/src/kernel_classes/javasrc/java/lang/EMThreadSupport.java (working copy) @@ -44,7 +44,7 @@ EMThreadSupport.run(); } }; - profilerThread = new Thread(emWorker, "profiler thread"); + profilerThread = new Thread(Thread.systemThreadGroup, emWorker, "profiler thread"); profilerThread.setDaemon(true); profilerThread.start(); } Index: vmcore/src/kernel_classes/javasrc/java/lang/FinalizerThread.java =================================================================== --- vmcore/src/kernel_classes/javasrc/java/lang/FinalizerThread.java (revision 454089) +++ vmcore/src/kernel_classes/javasrc/java/lang/FinalizerThread.java (working copy) @@ -111,10 +111,7 @@ /* * Staic private part */ - - // Finalizer Threads Group - private static final ThreadGroup threadGroup = new ThreadGroup("Finalizer Threads Group"); - + // Maximum quantity of finalizers threads private static final int MAX_THREADS = 256; @@ -313,7 +310,7 @@ private FinalizerStartLock startLock = new FinalizerStartLock(); protected FinalizerThread (boolean permanent) { - super(threadGroup, "FinalizerThread"); + super(Thread.systemThreadGroup, "FinalizerThread"); this.permanent = permanent; this.setDaemon(true); } Index: vmcore/src/kernel_classes/javasrc/java/lang/Thread.java =================================================================== --- vmcore/src/kernel_classes/javasrc/java/lang/Thread.java (revision 454089) +++ vmcore/src/kernel_classes/javasrc/java/lang/Thread.java (working copy) @@ -56,11 +56,6 @@ private static final String STACK_TRACE_INDENT = " "; /** - * Counter used to generate default thread names - */ - private static int threadCounter = 0; - - /** * This thread's thread group */ ThreadGroup group; @@ -140,18 +135,32 @@ Object lock = new Object(); /** - * generates a unique thread ID - */ - private static synchronized long getNextThreadId() { - return ++threadOrdinalNum; - } - - /* * used to generate a default thread name */ private static final String THREAD = "Thread-"; /** + * System thread group for keeping helper threads. + */ + static ThreadGroup systemThreadGroup = null; + + /** + * Main thread group. + */ + static ThreadGroup mainThreadGroup = null; + + /* + * Number of threads that was created w/o garbage collection. + */ + private static int currentGCWatermarkCount = 0; + + /* + * Max number of threads to be created w/o GC, required collect dead Thread + * references. + */ + private static final int GC_WATERMARK_MAX_COUNT = 700; + + /** * @com.intel.drl.spec_ref */ public Thread() { @@ -194,6 +203,58 @@ } /** + * Creates a new thread object for the thread attached to VM. + * The first attached thread is the main thread. + * + * @param group determines the thread group to place the thread in + * @param name thread's name + * @param nativeAddr address of the attached native thread + * @param stackeSize size of the thread's stack + * @param priority thread's priority + * @param daemon true if the thread is daemon, false otherwise + */ + Thread(ThreadGroup group, String name, long nativeAddr, + long stackSize, int priority, boolean daemon) { + + ClassLoader contextLoader = null; + + if (group == null) { + if (systemThreadGroup == null) { + // This is main thread. + systemThreadGroup = new ThreadGroup(); + mainThreadGroup = new ThreadGroup(systemThreadGroup, "main"); + group = mainThreadGroup; + // Initialize system class loader. + contextLoader = ClassLoader.getSystemClassLoader(); + } else { + group = mainThreadGroup; + } + } + + this.group = group; + this.stackSize = stackSize; + this.priority = priority; + this.daemon = daemon; + this.threadId = getNextThreadId(); + this.name = (name != null) ? name : THREAD + threadId; + // Each thread created from JNI has bootstrap class loader as + // its context class loader. The only exception is the main thread + // which has system class loader as its context class loader. + this.contextClassLoader = contextLoader; + this.target = null; + // The thread is actually running. + this.isAlive = true; + this.started = true; + + ThreadWeakRef newRef = new ThreadWeakRef(this); + newRef.setNativeAddr(nativeAddr); + + SecurityUtils.putContext(this, AccessController.getContext()); + // adding the thread to the thread group should be the last action + group.add(this); + } + + /** * @com.intel.drl.spec_ref */ public Thread(ThreadGroup group, Runnable target, String name, @@ -201,70 +262,53 @@ Thread currentThread = VMThreadManager.currentThread(); SecurityManager securityManager = System.getSecurityManager(); + + ThreadGroup threadGroup = null; + if (group != null) { + if (securityManager != null) { + securityManager.checkAccess(group); + } + threadGroup = group; + } else if (securityManager != null) { + threadGroup = securityManager.getThreadGroup(); + } + if (threadGroup == null) { + threadGroup = currentThread.group; + } + this.group = threadGroup; + this.daemon = currentThread.daemon; + this.contextClassLoader = currentThread.contextClassLoader; + this.target = target; + this.stackSize = stackSize; + this.priority = currentThread.priority; + this.threadId = getNextThreadId(); + // throws NullPointerException if the given name is null + this.name = (name != THREAD) ? this.name = name.toString() : + THREAD + threadId; - ThreadGroup threadGroup = null; - if (group != null) { - if (securityManager != null) { - securityManager.checkAccess(group); - } - threadGroup = group; - } else if (securityManager != null) { - threadGroup = securityManager.getThreadGroup(); - } - if (threadGroup == null) { - threadGroup = currentThread.group; - } - this.group = threadGroup; - // throws NullPointerException if the given name is null - this.name = (name != THREAD) ? this.name = name.toString() : THREAD - + threadCounter++; - this.daemon = currentThread.daemon; - this.contextClassLoader = currentThread.contextClassLoader; - this.target = target; - this.stackSize = stackSize; - this.priority = currentThread.priority; - initializeInheritableLocalValues(currentThread); + initializeInheritableLocalValues(currentThread); checkGCWatermark(); ThreadWeakRef oldRef = ThreadWeakRef.poll(); ThreadWeakRef newRef = new ThreadWeakRef(this); - long oldPointer = (oldRef == null)? 0 : oldRef.getNativeAddr(); + long oldPointer = (oldRef == null) ? 0 : oldRef.getNativeAddr(); long newPointer = VMThreadManager.init(this, newRef, oldPointer); if (newPointer == 0) { - throw new OutOfMemoryError("Failed to create new thread"); + throw new OutOfMemoryError("Failed to create new thread"); } newRef.setNativeAddr(newPointer); - - this.threadId = getNextThreadId(); + SecurityUtils.putContext(this, AccessController.getContext()); - checkAccess(); + checkAccess(); + // adding the thread to the thread group should be the last action threadGroup.add(this); } /** * @com.intel.drl.spec_ref */ - Thread(boolean nativeThread) { - VMThreadManager.attach(this); - this.name = "System thread"; - this.group = new ThreadGroup(); - this.group.add(this); - this.daemon = false; - this.started = true; - this.priority = NORM_PRIORITY; - // initialize the system class loader and set it as context - // classloader - ClassLoader.getSystemClassLoader(); - - this.threadId = getNextThreadId(); - SecurityUtils.putContext(this, AccessController.getContext()); - } - - /** - * @com.intel.drl.spec_ref - */ public Thread(ThreadGroup group, String name) { this(group, null, name, 0); } @@ -482,11 +526,7 @@ } } StackTraceElement ste[] = VMStack.getThreadStackTrace(this); - if (ste != null) { - return ste; - } else { - return new StackTraceElement[0]; - } + return ste != null ? ste : new StackTraceElement[0]; } /** @@ -668,8 +708,7 @@ ? threadGroup.maxPriority : priority; int status = VMThreadManager.setPriority(this, this.priority); if (status != VMThreadManager.TM_ERROR_NONE) { - // throw new InternalError( - // "Thread Manager internal error " + status); + //throw new InternalError("Thread Manager internal error " + status); } } @@ -687,22 +726,25 @@ this.isAlive = true; if (VMThreadManager.start(this, stackSize, daemon, priority) != 0) { - throw new OutOfMemoryError("Failed to start new thread"); + throw new OutOfMemoryError("Failed to create new thread"); } started = true; } } - /* - * This method serves as a wrapper around Thread.run() method to meet - * specification requirements in regard to ucaught exception catching. + /** + * Performs premortal actions. First it processes uncaught exception if any. + * Second removes current thread from its thread group. + * VM calls this method when current thread is detaching from VM. + * + * @param uncaughtException uncaught exception or null */ - void runImpl() { + void detach(Throwable uncaughtException) { try { - run(); - } catch (Throwable e) { - getUncaughtExceptionHandler().uncaughtException(this, e); + if (uncaughtException != null) { + getUncaughtExceptionHandler().uncaughtException(this, uncaughtException); + } } finally { group.remove(this); synchronized(lock) { @@ -712,8 +754,6 @@ } } - - public enum State { NEW, RUNNABLE, @@ -810,12 +850,10 @@ /** * @com.intel.drl.spec_ref */ - public static void setDefaultUncaughtExceptionHandler( - UncaughtExceptionHandler eh) { + public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { - sm - .checkPermission(RuntimePermissionCollection.SET_DEFAULT_UNCAUGHT_EXCEPTION_HANDLER_PERMISSION); + sm.checkPermission(RuntimePermissionCollection.SET_DEFAULT_UNCAUGHT_EXCEPTION_HANDLER_PERMISSION); } defaultExceptionHandler = eh; } @@ -836,8 +874,7 @@ public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { - sm - .checkPermission(RuntimePermissionCollection.MODIFY_THREAD_PERMISSION); + sm.checkPermission(RuntimePermissionCollection.MODIFY_THREAD_PERMISSION); } exceptionHandler = eh; } @@ -890,6 +927,14 @@ localValues.remove(local); } } + + /** + * Associate current thread object with native thread structure. + */ + private void initNativeThread() { + + } + /** * Initializes local values represented by @@ -899,7 +944,8 @@ * InheritableThreadLocal class
* This method should be called from Thread's constructor. */ - private void initializeInheritableLocalValues(Thread parent) { + private void initializeInheritableLocalValues(Thread parent) + { Map, Object> parentLocalValues = parent.localValues; if (parentLocalValues == null) { return; @@ -916,34 +962,34 @@ } /** - * @com.intel.drl.spec_ref + * generates a unique thread ID */ - public static interface UncaughtExceptionHandler { - - /** - * @com.intel.drl.spec_ref - */ - void uncaughtException(Thread t, Throwable e); + private static synchronized long getNextThreadId() + { + return ++threadOrdinalNum; } /* - * Number of threads that was created w/o garbage collection. - */ - private static int currentGCWatermarkCount = 0; - - /* - * Max number of threads to be created w/o GC, required collect dead Thread - * references. - */ - private static final int GC_WATERMARK_MAX_COUNT = 700; - - /* * Checks if more then GC_WATERMARK_MAX_COUNT threads was created and calls - * System.gc() to ensure that dead thread references was callected. + * System.gc() to ensure that dead thread references was collected. */ - private void checkGCWatermark() { - if (++currentGCWatermarkCount % GC_WATERMARK_MAX_COUNT == 0) { + private void checkGCWatermark() + { + if (++currentGCWatermarkCount % GC_WATERMARK_MAX_COUNT == 0) + { System.gc(); } } + + /** + * @com.intel.drl.spec_ref + */ + public static interface UncaughtExceptionHandler + { + + /** + * @com.intel.drl.spec_ref + */ + void uncaughtException(Thread t, Throwable e); + } } Index: vmcore/src/kernel_classes/javasrc/java/lang/ThreadGroup.java =================================================================== --- vmcore/src/kernel_classes/javasrc/java/lang/ThreadGroup.java (revision 454089) +++ vmcore/src/kernel_classes/javasrc/java/lang/ThreadGroup.java (working copy) @@ -363,7 +363,7 @@ if(throwable instanceof ThreadDeath){ return; } - System.err.println("Uncaught exception in "+thread.getName()+":"); + System.err.println("Uncaught exception in " + thread.getName() + ":"); throwable.printStackTrace(); } Index: vmcore/src/kernel_classes/javasrc/java/lang/VMClassRegistry.java =================================================================== --- vmcore/src/kernel_classes/javasrc/java/lang/VMClassRegistry.java (revision 454089) +++ vmcore/src/kernel_classes/javasrc/java/lang/VMClassRegistry.java (working copy) @@ -41,7 +41,8 @@ * * @api2vm */ -final class VMClassRegistry { +final class VMClassRegistry +{ /** * This method satisfies the requirements of the specification for the * {@link Class#getSimpleName() Class.getSimpleName()} @@ -86,7 +87,8 @@ /** * This class is not supposed to be instantiated. */ - private VMClassRegistry() { + private VMClassRegistry() + { } /** @@ -108,7 +110,7 @@ * @api2vm */ static native Class defineClass(String name, ClassLoader classLoader, - byte[] data, int off, int len) throws ClassFormatError; + byte[] data, int off, int len) throws ClassFormatError; /** * This method satisfies the requirements of the specification for the @@ -138,10 +140,24 @@ /** * This method satisfies the requirements of the specification for the + * {@link Class#getClassLoader() Class.getClassLoader()} method except + * the clazz parameter may be null. In this case context class loader + * of the current thread is returned. + * + * @api2vm + */ + static ClassLoader getClassLoader(Class clazz) { + return clazz != null ? getClassLoader0(clazz) + : Thread.currentThread().getContextClassLoader(); + } + + /** + * This method satisfies the requirements of the specification for the * {@link Class#getClassLoader() Class.getClassLoader()} method. + * * @api2vm */ - static native ClassLoader getClassLoader(Class clazz); + static native ClassLoader getClassLoader0(Class clazz); /** * This method satisfies the requirements of the specification for the Index: vmcore/src/kernel_classes/javasrc/java/lang/VMStart.java =================================================================== --- vmcore/src/kernel_classes/javasrc/java/lang/VMStart.java (revision 454089) +++ vmcore/src/kernel_classes/javasrc/java/lang/VMStart.java (working copy) @@ -37,7 +37,7 @@ * */ class VMStart { - static int exitCode = 0; + public static void initialize() { //start helper threads such as Finalizer startHelperThreads(); @@ -47,30 +47,6 @@ parseSystemProperties(); } - public static void start (String mainClassName, String args[]) { - try { - // create main thread in new thread group - MainThread mainThread = new MainThread(mainClassName, args); - mainThread.start(); - //startHelperThreads(); - //System.out.println("Join Group " + Thread.currentThread().getThreadGroup()); - } catch (Throwable e) { - e.printStackTrace(System.err); - System.exit(-1); - } - } - - public static void shutdown() { - try { - joinAllNonDaemonThreads(); - //System.out.println("Joined all "); - System.exit(exitCode); - } catch (Throwable e) { - e.printStackTrace(System.err); - System.exit(-1); - } - } - public static void parseSystemProperties() { } @@ -87,75 +63,14 @@ } // should shutdown helper threads static class DefaultShutDownHook extends Thread { + + public DefaultShutDownHook() { + super("Thread-shutdown"); + } + public void run() { FinalizerThread.shutdown(); EMThreadSupport.shutdown(); } } - - // main thread - static class MainThread extends Thread { - String mainClass; - String args[]; - public boolean started = false; - - MainThread (String mainClass, String args[]) { - super(new ThreadGroup("main"), "main"); - this.mainClass = mainClass; - this.args = args; - - } - public void run() { - } - - void runImpl() { - // prevent access from user classes to run() method - if(started) { - return; - } - started = true; - - try { - // load and start main class - ClassLoader loader = ClassLoader.getSystemClassLoader(); - Class cl = Class.forName(mainClass, true, loader); - final Method mainMethod = cl.getMethod("main", - new Class[]{String[].class}); - int expectedModifiers = (Modifier.PUBLIC | Modifier.STATIC); - if ((mainMethod.getModifiers() & expectedModifiers) != expectedModifiers - || mainMethod.getReturnType() != Void.TYPE) { - throw new NoSuchMethodError( - "The method main must be declared public, static, and void."); - } - // the class itself may be non-public - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { - mainMethod.setAccessible(true); - return null; - } - }); - - mainMethod.invoke(null, new Object[] {args}); - } catch (InvocationTargetException userException) { - exitCode = 1; - userException.getCause().printStackTrace(); - } catch (Throwable e) { - exitCode = 1; - e.printStackTrace(System.err); - } finally { - group.remove(this); - synchronized(lock) { - this.isAlive = false; - lock.notifyAll(); - } - } - } - } - - static void mainThreadInit() { - Thread theFirstThread = new Thread(true); - } - - - native static void joinAllNonDaemonThreads(); } Index: vmcore/src/kernel_classes/javasrc/java/lang/VMThreadManager.java =================================================================== --- vmcore/src/kernel_classes/javasrc/java/lang/VMThreadManager.java (revision 454089) +++ vmcore/src/kernel_classes/javasrc/java/lang/VMThreadManager.java (working copy) @@ -234,19 +234,13 @@ */ static native int yield(); - /** - * This method initialize native thread structure as well as inter dependencies - * between java thread and native thread. - * @api2vm - */ - static native long init(Thread thread, ThreadWeakRef ref, long oldAddr); + /** + * This method initialize native thread structure as well as inter dependencies + * between java thread and native thread. + * @api2vm + */ + static native long init(Thread thread, ThreadWeakRef ref, long oldAddr); - /** - * This method attches current thread to vm. Required for main thread construction. - * @api2vm - */ - static native int attach(java.lang.Thread thread); - /** * Returns the state of the given thread as described by JVMTI spec * @api2vm Index: vmcore/src/kernel_classes/javasrc/org/apache/harmony/kernel/vm/VM.java =================================================================== --- vmcore/src/kernel_classes/javasrc/org/apache/harmony/kernel/vm/VM.java (revision 454089) +++ vmcore/src/kernel_classes/javasrc/org/apache/harmony/kernel/vm/VM.java (working copy) @@ -70,7 +70,7 @@ * @deprecated */ public static ClassLoader callerClassLoader() { - return getClassLoader(VMStack.getCallerClass(1)); + return getStackClassLoader(2); } private static native ClassLoader getClassLoader(Class clazz); Index: vmcore/src/kernel_classes/javasrc/org/apache/harmony/vm/VMStack.java =================================================================== --- vmcore/src/kernel_classes/javasrc/org/apache/harmony/vm/VMStack.java (revision 454089) +++ vmcore/src/kernel_classes/javasrc/org/apache/harmony/vm/VMStack.java (working copy) @@ -114,12 +114,24 @@ * VMClassRegistry.getClassLoader(Class clazz)} method. It has package * visibility only. So it can be used by other classes in this package to * to get class loader with out security checks. - * @param clazz class to get class loader for. The clazz argument should - * never be null. - * @return class loader of the specified class. + * + * @param clazz class to get class loader for. + * @return class loader for the specified class. * @api2vm */ - static native ClassLoader getClassLoader(Class clazz); + static ClassLoader getClassLoader(Class clazz) { + return clazz != null ? getClassLoader0(clazz) + : Thread.currentThread().getContextClassLoader(); + } + + /** + * This method satisfies the requirements of the specification for the + * {@link Class#getClassLoader() Class.getClassLoader()} method. + * + * @api2vm + */ + static native ClassLoader getClassLoader0(Class clazz); + public static native StackTraceElement[] getThreadStackTrace(Thread t); } Index: vmcore/src/kernel_classes/native/java_lang_VMClassRegistry.cpp =================================================================== --- vmcore/src/kernel_classes/native/java_lang_VMClassRegistry.cpp (revision 454089) +++ vmcore/src/kernel_classes/native/java_lang_VMClassRegistry.cpp (working copy) @@ -91,18 +91,17 @@ * Signature: (Ljava/lang/String;Ljava/lang/ClassLoader;)Ljava/lang/Class; */ JNIEXPORT jclass JNICALL Java_java_lang_VMClassRegistry_findLoadedClass - (JNIEnv *jenv_ext, jclass, jstring name, jobject cl) + (JNIEnv *jenv, jclass, jstring name, jobject cl) { ASSERT_RAISE_AREA; // check the name is provided if (name == NULL) { - ThrowNew_Quick(jenv_ext, "java/lang/NullPointerException", "null class name value."); + ThrowNew_Quick(jenv, "java/lang/NullPointerException", "null class name value."); return NULL; } // obtain char* for the name - JNIEnv_Internal *jenv = (JNIEnv_Internal *)jenv_ext; unsigned length = GetStringUTFLength(jenv, name); char* buf = (char*)STD_MALLOC(length+1); assert(buf); @@ -116,7 +115,7 @@ // filter out primitive types - Global_Env *ge = jenv->vm->vm_env; + Global_Env *ge = jni_get_vm_env(jenv); Class* primitives[] = { ge->Boolean_Class, ge->Char_Class, @@ -185,7 +184,7 @@ * Method: getClassLoader * Signature: (Ljava/lang/Class;)Ljava/lang/ClassLoader; */ -JNIEXPORT jobject JNICALL Java_java_lang_VMClassRegistry_getClassLoader +JNIEXPORT jobject JNICALL Java_java_lang_VMClassRegistry_getClassLoader0 (JNIEnv *jenv, jclass, jclass clazz) { Class_Handle clss = jni_get_class_handle(jenv, clazz); @@ -556,13 +555,13 @@ // load native library ClassLoaderHandle loader; if( classLoader ) { - loader = class_loader_lookup( classLoader ); + loader = class_loader_lookup(classLoader); } else { // bootstrap class loader loader = (ClassLoaderHandle) - ((JNIEnv_Internal*)jenv)->vm->vm_env->bootstrap_class_loader; + jni_get_vm_env(jenv)->bootstrap_class_loader; } - class_loader_load_native_lib( str_filename, loader ); + class_loader_load_native_lib(str_filename, loader); // release char string ReleaseStringUTFChars(jenv, filename, str_filename); Index: vmcore/src/kernel_classes/native/java_lang_VMClassRegistry.h =================================================================== --- vmcore/src/kernel_classes/native/java_lang_VMClassRegistry.h (revision 454089) +++ vmcore/src/kernel_classes/native/java_lang_VMClassRegistry.h (working copy) @@ -67,7 +67,7 @@ * Method: java.lang.VMClassRegistry.getClassLoader(Ljava/lang/Class;)Ljava/lang/ClassLoader; */ JNIEXPORT jobject JNICALL -Java_java_lang_VMClassRegistry_getClassLoader(JNIEnv *, jclass, +Java_java_lang_VMClassRegistry_getClassLoader0(JNIEnv *, jclass, jclass); /* Index: vmcore/src/kernel_classes/native/java_lang_VMExecutionEngine.cpp =================================================================== --- vmcore/src/kernel_classes/native/java_lang_VMExecutionEngine.cpp (revision 454089) +++ vmcore/src/kernel_classes/native/java_lang_VMExecutionEngine.cpp (working copy) @@ -45,6 +45,7 @@ #include "exceptions.h" #include "java_lang_VMExecutionEngine.h" #include "assertion_registry.h" +#include "init.h" /* * Class: java_lang_VMExecutionEngine @@ -84,7 +85,7 @@ (JNIEnv * jenv, jclass, jclass jclss, jboolean recursive, jint defaultStatus) { Assertion_Status status = ASRT_UNSPECIFIED; - Global_Env* genv = ((JNIEnv_Internal*)jenv)->vm->vm_env; + Global_Env* genv = jni_get_vm_env(jenv); Assertion_Registry* reg = genv->assert_reg; if (!reg) { return status; @@ -173,7 +174,7 @@ PropPut(jenv, pProperties, "java.tmpdir", tmp); PropPut(jenv, pProperties, "java.class.path", properties_get_string_property( - reinterpret_cast(&((JNIEnv_Internal*)jenv)->vm->vm_env->properties), + reinterpret_cast(jni_get_vm_env(jenv)->properties), "java.class.path") ); // TODO : fix this - it should come from Class.h @@ -199,7 +200,7 @@ } // Next, add runtime specified properties. - Properties::Iterator *iterator = VM_Global_State::loader_env->properties.getIterator(); + Properties::Iterator *iterator = VM_Global_State::loader_env->properties->getIterator(); const Prop_entry *next = NULL; while((next = iterator->next())){ if (!PropPut(jenv, pProperties, next->key, ((Prop_String*)next->value)->value)){ Index: vmcore/src/kernel_classes/native/java_lang_VMStart.cpp =================================================================== --- vmcore/src/kernel_classes/native/java_lang_VMStart.cpp (revision 454089) +++ vmcore/src/kernel_classes/native/java_lang_VMStart.cpp (working copy) @@ -1,36 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 Artem Aliev - * @version $Revision: 1.1.2.1.4.4 $ - */ -#include "thread_generic.h" -#include "open/hythread_ext.h" - - -#ifdef __cplusplus -extern "C" { -#endif - -JNIEXPORT void JNICALL Java_java_lang_VMStart_joinAllNonDaemonThreads (JNIEnv * UNREF jenv, jclass UNREF starter) -{ - hythread_wait_for_all_nondaemon_threads(); -} - -#ifdef __cplusplus -} -#endif Index: vmcore/src/kernel_classes/native/java_lang_VMThreadManager.cpp =================================================================== --- vmcore/src/kernel_classes/native/java_lang_VMThreadManager.cpp (revision 454089) +++ vmcore/src/kernel_classes/native/java_lang_VMThreadManager.cpp (working copy) @@ -28,6 +28,7 @@ #include "open/jthread.h" #include "open/ti_thread.h" #include "open/thread_externals.h" +#include "jni_utils.h" /* * Class: java_lang_VMThreadManager @@ -159,7 +160,7 @@ (JNIEnv *jenv, jclass clazz, jobject thread, jlong stackSize, jboolean daemon, jint priority) { jthread_threadattr_t attrs; - + attrs.daemon = daemon; attrs.priority = priority; attrs.stacksize = stackSize > 40000000? 0:(jint)stackSize; @@ -197,6 +198,7 @@ JNIEXPORT jint JNICALL Java_java_lang_VMThreadManager_wait (JNIEnv *env, jclass clazz, jobject monitor, jlong millis, jint UNREF nanos) { + // TODO: need to evaluate return code properly return jthread_monitor_timed_wait(monitor, millis, nanos); } @@ -213,17 +215,6 @@ /* * Class: java_lang_VMThreadManager - * Method: attach - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_java_lang_VMThreadManager_attach - (JNIEnv * UNREF jenv, jclass clazz, jobject java_thread) -{ - jthread_attach(jenv, java_thread); -} - -/* - * Class: java_lang_VMThreadManager * Method: isAlive * Signature: (Ljava/lang/Thread;)Z */ Index: vmcore/src/kernel_classes/native/org_apache_harmony_kernel_vm_VM.cpp =================================================================== --- vmcore/src/kernel_classes/native/org_apache_harmony_kernel_vm_VM.cpp (revision 454089) +++ vmcore/src/kernel_classes/native/org_apache_harmony_kernel_vm_VM.cpp (working copy) @@ -39,7 +39,7 @@ (JNIEnv *jenv, jclass, jclass clazz) { // reuse similar method in VMClassRegistry - return Java_java_lang_VMClassRegistry_getClassLoader(jenv, NULL, clazz); + return Java_java_lang_VMClassRegistry_getClassLoader0(jenv, NULL, clazz); } /** Index: vmcore/src/kernel_classes/native/org_apache_harmony_vm_VMGenericsAndAnnotations.cpp =================================================================== --- vmcore/src/kernel_classes/native/org_apache_harmony_vm_VMGenericsAndAnnotations.cpp (revision 454089) +++ vmcore/src/kernel_classes/native/org_apache_harmony_vm_VMGenericsAndAnnotations.cpp (working copy) @@ -76,7 +76,7 @@ JNIEXPORT jobjectArray JNICALL Java_org_apache_harmony_vm_VMGenericsAndAnnotations_getParameterAnnotations (JNIEnv *jenv, jclass, jlong jmethod) { - static Global_Env* genv = ((JNIEnv_Internal*)jenv)->vm->vm_env; + static Global_Env* genv = jni_get_vm_env(jenv); Method* method = (Method*) ((POINTER_SIZE_INT) jmethod); Class* declaring_class = method->get_class(); @@ -91,7 +91,7 @@ if (num == 0) { unsigned nparams = (method->get_num_args() - (method->is_static() ? 0 : 1)); if (nparams > 0) { - static Class* antn_class = ((JNIEnv_Internal*)jenv)->vm->vm_env->LoadCoreClass( + static Class* antn_class = jni_get_vm_env(jenv)->LoadCoreClass( "java/lang/annotation/Annotation"); array = NewObjectArray(jenv, nparams, struct_Class_to_java_lang_Class_Handle(array_class), NewObjectArray(jenv, 0, Index: vmcore/src/kernel_classes/native/org_apache_harmony_vm_VMStack.cpp =================================================================== --- vmcore/src/kernel_classes/native/org_apache_harmony_vm_VMStack.cpp (revision 454089) +++ vmcore/src/kernel_classes/native/org_apache_harmony_vm_VMStack.cpp (working copy) @@ -106,9 +106,8 @@ * Signature: (IZ)[Ljava/lang/Class; */ JNIEXPORT jobjectArray JNICALL Java_org_apache_harmony_vm_VMStack_getClasses - (JNIEnv *jenv_ext, jclass, jint signedMaxSize, jboolean considerPrivileged) + (JNIEnv *jenv, jclass, jint signedMaxSize, jboolean considerPrivileged) { - JNIEnv_Internal *jenv = (JNIEnv_Internal *)jenv_ext; // if signedMaxSize is negative, maxSize will be > MAX_INT_VALUE unsigned maxSize = signedMaxSize; @@ -123,7 +122,7 @@ // For details look at the org/apache/harmony/vm/VMStack.java file. Thus skipping 2 frames. unsigned skip = 2; - Global_Env* genv = ((JNIEnv_Internal*)jenv)->vm->vm_env; + Global_Env* genv = jni_get_vm_env(jenv); // count target array length ignoring reflection frames unsigned length = 0, s; @@ -214,15 +213,14 @@ * Signature: (Ljava/lang/Object;)[Ljava/lang/StackTraceElement; */ JNIEXPORT jobjectArray JNICALL Java_org_apache_harmony_vm_VMStack_getStackTrace - (JNIEnv * jenv_ext, jclass, jobject state) + (JNIEnv * jenv, jclass, jobject state) { ASSERT_RAISE_AREA; if (NULL == state) return NULL; - Global_Env* genv = VM_Global_State::loader_env; + Global_Env* genv = jni_get_vm_env(jenv); - JNIEnv_Internal *jenv = (JNIEnv_Internal *)jenv_ext; // state object contains raw data as long array jlongArray array = (jlongArray)state; assert(array); @@ -255,7 +253,7 @@ Method *method = frames[skip].method; // skip Throwable constructor if (method->is_init() && method->get_class() == - VM_Global_State::loader_env->java_lang_Throwable_Class) { + genv->java_lang_Throwable_Class) { void *old_this = frames[skip].outdated_this; skip++; @@ -272,25 +270,6 @@ } } - - // skip the VMStart$MainThread.runImpl() if it exists from the bottom - // of the stack along with 2 reflection frames used to invoke method main - static String* starter_String = genv->string_pool.lookup("java/lang/VMStart$MainThread"); - Method_Handle method = frames[size - 1].method; - assert(method); - - if (!strcmp(method_get_name(method), "runImpl") - && method->get_class()->name == starter_String) { - for (; --size;) { - method = frames[size - 1].method; - assert(method); - if ((strstr(method->get_class()->name->bytes, "java/lang/reflect")) - == NULL) { - break; - } - } - } - ASSERT(size >= skip, "Trying to skip " << skip << " frames but there are only " << size << " frames in stack"); @@ -335,8 +314,7 @@ tmn_suspend_disable(); // class name - String* className = class_get_java_name(method->get_class(), - VM_Global_State::loader_env); + String* className = class_get_java_name(method->get_class(), genv); strClassName->object = vm_instantiate_cp_string_resolved(className); if (!strClassName->object) { tmn_suspend_enable(); @@ -376,7 +354,7 @@ (JNIEnv *jenv, jclass, jclass clazz) { // reuse similar method in VMClassRegistry - return Java_java_lang_VMClassRegistry_getClassLoader(jenv, NULL, clazz); + return Java_java_lang_VMClassRegistry_getClassLoader0(jenv, NULL, clazz); } /* Index: vmcore/src/kernel_classes/native/org_apache_harmony_vm_VMStack.h =================================================================== --- vmcore/src/kernel_classes/native/org_apache_harmony_vm_VMStack.h (revision 454089) +++ vmcore/src/kernel_classes/native/org_apache_harmony_vm_VMStack.h (working copy) @@ -72,7 +72,7 @@ * Method: org.apache.harmony.vm.VMStack.getClassLoader(Ljava/lang/Class;)Ljava/lang/ClassLoader; */ JNIEXPORT jobject JNICALL -Java_org_apache_harmony_vm_VMStack_getClassLoader(JNIEnv *, jclass, +Java_org_apache_harmony_vm_VMStack_getClassLoader0(JNIEnv *, jclass, jclass); /* Index: vmcore/src/object/object_handles.cpp =================================================================== --- vmcore/src/object/object_handles.cpp (revision 454089) +++ vmcore/src/object/object_handles.cpp (working copy) @@ -206,7 +206,7 @@ h->handle.object = NULL; h->allocated_on_the_stack = false; - tmn_suspend_disable(); // ----------------vvv + hythread_suspend_disable(); // ----------------vvv p_handle_lock->_lock(); // Insert at beginning of globals list h->prev = NULL; @@ -215,7 +215,7 @@ if(h->next) h->next->prev = h; p_handle_lock->_unlock(); - tmn_suspend_enable(); //--------------------------------------------^^^ + hythread_suspend_enable(); //--------------------------------------------^^^ return &h->handle; } //vm_create_global_object_handle Index: vmcore/src/reflection/annotations.cpp =================================================================== --- vmcore/src/reflection/annotations.cpp (revision 454089) +++ vmcore/src/reflection/annotations.cpp (working copy) @@ -40,7 +40,7 @@ unsigned num = table ? table->length : 0; TRACE("annotations table size = " << num); - static Class* antn_class = ((JNIEnv_Internal*)jenv)->vm->vm_env->LoadCoreClass( + static Class* antn_class = jni_get_vm_env(jenv)->LoadCoreClass( "java/lang/annotation/Annotation"); jobjectArray array = NewObjectArray(jenv, num, @@ -122,7 +122,7 @@ } TRACE("Annotation type " << antn_type); - static Global_Env* genv = ((JNIEnv_Internal*)jenv)->vm->vm_env; + static Global_Env* genv = jni_get_vm_env(jenv); static Class* factory_class = genv->LoadCoreClass( "org/apache/harmony/lang/annotation/AnnotationFactory"); static jmethodID factory_method = (jmethodID)class_lookup_method(factory_class, "createAnnotation", @@ -184,7 +184,7 @@ if (enum_value) { return enum_value; } else { - static Global_Env* genv = ((JNIEnv_Internal*)jenv)->vm->vm_env; + static Global_Env* genv = jni_get_vm_env(jenv); static Class* ECNPE_class = genv->LoadCoreClass( "java/lang/EnumConstantNotPresentException"); static jmethodID ECNPE_ctor = (jmethodID)class_lookup_method(ECNPE_class, "", @@ -210,7 +210,7 @@ String* name, jthrowable* cause, jarray array, unsigned idx, Class* type) { - Global_Env* genv = ((JNIEnv_Internal*)jenv)->vm->vm_env; + Global_Env* genv = jni_get_vm_env(jenv); switch (value.tag) { case AVT_INT: { Index: vmcore/src/stack/stack_trace.cpp =================================================================== --- vmcore/src/stack/stack_trace.cpp (revision 454089) +++ vmcore/src/stack/stack_trace.cpp (working copy) @@ -25,7 +25,7 @@ #include "stack_trace.h" #include "interpreter.h" #include "jit_intf_cpp.h" - +#include "environment.h" #include "method_lookup.h" void get_file_and_line(Method_Handle mh, void *ip, bool is_ip_past, const char **file, int *line) { @@ -55,7 +55,8 @@ uint16 bcOffset; POINTER_SIZE_INT callLength = 5; - CodeChunkInfo* jit_info = vm_methods->find((unsigned char*)ip - callLength); + Global_Env * vm_env = VM_Global_State::loader_env; + CodeChunkInfo* jit_info = vm_env->vm_methods->find((unsigned char*)ip - callLength); if (jit_info->get_jit()->get_bc_location_for_native( method, (NativeCodePtr) ((POINTER_SIZE_INT) ip - callLength), Index: vmcore/src/thread/lock_manager.cpp =================================================================== --- vmcore/src/thread/lock_manager.cpp (revision 454089) +++ vmcore/src/thread/lock_manager.cpp (working copy) @@ -46,8 +46,7 @@ } Lock_Manager::Lock_Manager() -{ // init thread menager if needed - hythread_init(hythread_lib); +{ UNREF IDATA stat = hymutex_create (&lock, TM_MUTEX_NESTED); assert(stat==TM_ERROR_NONE); } Index: vmcore/src/thread/thread_generic.cpp =================================================================== --- vmcore/src/thread/thread_generic.cpp (revision 454089) +++ vmcore/src/thread/thread_generic.cpp (working copy) @@ -42,15 +42,20 @@ #include #endif +#include + +#include "open/hythread.h" +#include "open/jthread.h" #include "open/thread_externals.h" +#include "open/types.h" +#include "open/vm_util.h" +#include "open/gc.h" + #include "environment.h" #include "vm_strings.h" -#include "open/types.h" -#include "open/vm_util.h" #include "object_layout.h" #include "Class.h" #include "classloader.h" -#include "open/gc.h" #include "vm_threads.h" #include "nogc.h" #include "ini.h" @@ -62,15 +67,20 @@ #include "vm_threads.h" #include "jni_utils.h" #include "object.h" - #include "platform_core_natives.h" #include "heap.h" #include "verify_stack_enumeration.h" - #include "sync_bits.h" #include "vm_stats.h" #include "native_utils.h" +#include "thread_manager.h" +#include "object_generic.h" +#include "thread_generic.h" +#include "mon_enter_exit.h" +#include "jni_direct.h" +#include "port_malloc.h" + #ifdef PLATFORM_NT // wjw -- following lines needs to be generic for all OSs #include "java_lang_thread_nt.h" @@ -78,66 +88,105 @@ #ifdef _IPF_ #include "java_lang_thread_ipf.h" +#include "../m2n_ipf_internal.h" #elif defined _EM64T_ #include "java_lang_thread_em64t.h" +#include "../m2n_em64t_internal.h" #else #include "java_lang_thread_ia32.h" +#include "../m2n_ia32_internal.h" #endif -#include "thread_manager.h" -#include "object_generic.h" -#include "thread_generic.h" +extern struct JNINativeInterface_ jni_vtable; -#include "mon_enter_exit.h" +/** + * Runs java.lang.Thread.detach() method. + */ +static IDATA run_java_detach(jthread java_thread) { + static Method * detach = NULL; + const char * method_name = "detach"; + const char * descriptor = "(Ljava/lang/Throwable;)V"; + jvalue args[2]; + JNIEnv * jni_env; + Global_Env * vm_env; + Class * thread_class; -#include "jni_direct.h" + assert(hythread_is_suspend_enabled()); -#ifdef _IPF_ -#include "../m2n_ipf_internal.h" -#elif defined _EM64T_ -#include "../m2n_em64t_internal.h" -#else -#include "../m2n_ia32_internal.h" -#endif + jni_env = jthread_get_JNI_env(java_thread); + vm_env = jni_get_vm_env(jni_env); + thread_class = vm_env->java_lang_Thread_Class; -#include "port_malloc.h" + if (detach == NULL) { + detach = class_lookup_method(thread_class, method_name, descriptor); + if (detach == NULL) { + TRACE("Failed to find thread's detach method " << descriptor << " , exception = " << exn_get()); + return TM_ERROR_INTERNAL; + } + } -#include "open/jthread.h" + // Initialize arguments. + args[0].l = java_thread; + args[1].l = exn_get(); + exn_clear(); -///////////////////////////////////////////////////////////////////// -// Native lib stuff + hythread_suspend_disable(); + vm_execute_java_method_array((jmethodID) detach, 0, args); + hythread_suspend_enable(); + if (exn_raised()) { + TRACE("java.lang.Thread.detach(Throwable) method completed with an exception: " << exn_get_name()); + return TM_ERROR_INTERNAL; + } + return TM_ERROR_NONE; +} -IDATA vm_attach() { - //hythread_suspend_disable(); - IDATA status; - status = hythread_global_lock(); - if(status != TM_ERROR_NONE) - return status; - VM_thread * p_vm_thread = get_a_thread_block(); - if (NULL == p_vm_thread) { - TRACE2("thread", "can't get a thread block for a new thread"); - status =hythread_global_unlock(); - assert (status == TM_ERROR_NONE); - return TM_ERROR_OUT_OF_MEMORY; +/** + * Attaches thread current thread to VM. + */ +jint vm_attach(JavaVM * java_vm, JNIEnv ** p_jni_env) { + M2nFrame * p_m2n; + VM_thread * p_vm_thread; + ObjectHandles * p_handles; + + // It seems to be reasonable to have suspend enabled state here. + // It is unsafe to perform operations which require suspend disabled + // mode until current thread is not attaced to VM. + assert(hythread_is_suspend_enabled()); + + p_vm_thread = p_TLS_vmthread; + if (p_vm_thread != NULL) { + if (java_vm != p_vm_thread->jni_env->vm) { + return TM_ERROR_INTERNAL; + } + *p_jni_env = p_vm_thread->jni_env; + return JNI_OK; } - set_TLS_data(p_vm_thread); - M2nFrame* p_m2n = (M2nFrame*) STD_MALLOC(sizeof(M2nFrame)); - ObjectHandles* p_handles = (ObjectHandles*) STD_MALLOC (sizeof(ObjectHandlesNew)); - if ((p_m2n==NULL)||(p_handles==NULL)) - { + p_vm_thread = get_a_thread_block((JavaVM_Internal *)java_vm); + if (p_vm_thread == NULL) { TRACE2("thread", "can't get a thread block for a new thread"); - status =hythread_global_unlock(); - assert (status == TM_ERROR_NONE); - return TM_ERROR_OUT_OF_MEMORY; + return JNI_ENOMEM; } - status =hythread_global_unlock(); - if(status != TM_ERROR_NONE) - return status; - - hythread_suspend_disable(); - + + // Create JNI environment for current thread. + p_vm_thread->jni_env = (JNIEnv_Internal *) apr_palloc(p_vm_thread->pool, sizeof(JNIEnv_Internal)); + + // Initialize JNI environment. + p_vm_thread->jni_env->functions = &jni_vtable; + p_vm_thread->jni_env->vm = (JavaVM_Internal *)java_vm; + p_vm_thread->jni_env->reserved0 = (void *)0x1234abcd; + *p_jni_env = p_vm_thread->jni_env; + + // Create top level M2N frame. + p_m2n = (M2nFrame*) apr_palloc(p_vm_thread->pool, sizeof(M2nFrame)); + // Create local handles. + p_handles = (ObjectHandles*) apr_palloc(p_vm_thread->pool, sizeof(ObjectHandlesNew)); + if (p_vm_thread->jni_env == NULL || p_m2n == NULL ||p_handles == NULL) { + TRACE2("thread", "can't get a thread block for a new thread"); + return JNI_ENOMEM; + } + init_stack_info(); m2n_null_init(p_m2n); @@ -149,31 +198,57 @@ m2n_set_frame_type(p_m2n, FRAME_NON_UNWINDABLE); gc_thread_init(&p_vm_thread->_gc_private_information); - assert(!hythread_is_suspend_enabled()); - hythread_suspend_enable(); - return TM_ERROR_NONE; - } + assert(hythread_is_suspend_enabled()); + return JNI_OK; +} -IDATA vm_detach() { - IDATA status; - VM_thread *p_vm_thread=get_thread_ptr(); +/** + * Detaches current thread from VM. + */ +jint vm_detach(jthread java_thread) { + VM_thread * p_vm_thread; + jint status; + + assert(hythread_is_suspend_enabled()); + status = run_java_detach(java_thread); + if (status != JNI_OK) return status; + hythread_suspend_disable(); -// assert(p_vm_thread->app_status == thread_is_running); + + p_vm_thread = get_thread_ptr(); + + // Notify GC about thread detaching. gc_thread_kill(&p_vm_thread->_gc_private_information); + assert(p_vm_thread->gc_frames == 0); + // Remove current VM_thread from TLS. + set_TLS_data(NULL); + // Destroy current VM_thread structure. + apr_pool_destroy(p_vm_thread->pool); + hythread_suspend_enable(); - - status = hythread_global_lock(); - if(status != TM_ERROR_NONE) - return status; - assert(p_vm_thread->gc_frames == 0); - free_this_thread_block( p_vm_thread ); - set_TLS_data(NULL); - status =hythread_global_unlock(); - return status; - } + return JNI_OK; + +/** TODO: Check if we need these actions!!! + jint monitor_count; + jobject * monitor_objects; +#ifndef NDEBUG + hythread_t tm_native_thread = jthread_get_native_thread(); + assert(tm_native_thread); + assert(tm_native_thread == hythread_self()); +#endif -//////////////////////////////////////////////////////////////////////////////////////////// -//////// CALLED by vm_init() to initialialize thread groups and create the main thread //// + // 2) release all owned monitors if any. + status = jthread_get_owned_monitors(java_thread, &monitor_count, &monitor_objects); + // TODO: how to deal with OutOfMemoryError? + assert(status != TM_ERROR_NONE); + for (int i = 0; i < monitor_count; i++) { + jthread_monitor_notify_all(monitor_objects[i]); + jthread_monitor_exit(monitor_objects[i]); + } + // 3) Remove tm_thread_t pointer from java.lang.Thread object. + vm_jthread_set_tm_data(jthread java_thread, NULL); +*/ +} Index: vmcore/src/thread/thread_manager.cpp =================================================================== --- vmcore/src/thread/thread_manager.cpp (revision 454089) +++ vmcore/src/thread/thread_manager.cpp (working copy) @@ -54,11 +54,14 @@ #include "open/jthread.h" #include "vm_threads.h" -#define LOG_DOMAIN "thread" -#include "cxxlog.h" #include "tl/memory_pool.h" #include "open/vm_util.h" #include "suspend_checker.h" +#include "jni_utils.h" +#include "heap.h" +#include "vm_strings.h" +#include "interpreter.h" +#include "exceptions_int.h" #ifdef PLATFORM_NT // wjw -- following lines needs to be generic for all OSs @@ -71,13 +74,9 @@ #include "java_lang_thread_ia32.h" #endif -#include "interpreter.h" -#include "exceptions_int.h" +#define LOG_DOMAIN "vmcore.thread" +#include "cxxlog.h" -static StaticInitializer thread_runtime_initializer; - -static tl::MemoryPool thr_pool; - hythread_tls_key_t TLS_key_pvmthread; #ifdef __cplusplus @@ -91,52 +90,33 @@ } #endif + void init_TLS_data(); -void vm_thread_init(Global_Env * UNREF p_env___not_used) -{ - init_TLS_data(); -} +VM_thread * get_a_thread_block(JavaVM_Internal * java_vm) { + VM_thread * p_vmthread; + apr_pool_t * thread_pool; - -void vm_thread_shutdown() -{ -} //vm_thread_shutdown - - - -VM_thread * get_a_thread_block() -{ - VM_thread *p_vmthread; - - p_vmthread = p_TLS_vmthread; + p_vmthread = p_TLS_vmthread; if (!p_vmthread) { - p_vmthread = (VM_thread *)thr_pool.alloc(sizeof(VM_thread)); - memset(p_vmthread, 0, sizeof(VM_thread) ); - } - return p_vmthread; - } - -void free_this_thread_block(VM_thread *p_vmthread) -{ - } - -void vm_thread_attach() -{ - VM_thread *p_vmthread; - - p_vmthread = p_TLS_vmthread; - if (!p_vmthread) { - p_vmthread = (VM_thread *)thr_pool.alloc(sizeof(VM_thread)); - memset(p_vmthread, 0, sizeof(VM_thread) ); + if (apr_pool_create(&thread_pool, java_vm->vm_env->mem_pool) != APR_SUCCESS) { + return NULL; + } + p_vmthread = (VM_thread *) apr_pcalloc(thread_pool, sizeof(VM_thread)); + if (!p_vmthread) return NULL; + + p_vmthread->pool = thread_pool; set_TLS_data(p_vmthread); + } else { + memset(p_vmthread, 0, sizeof(VM_thread)); } -} //init_thread_block - + return p_vmthread; +} + VM_thread *get_vm_thread(hythread_t thr) { if (thr == NULL) { return NULL; -} + } return (VM_thread *)hythread_tls_get(thr, TLS_key_pvmthread); } @@ -166,7 +146,7 @@ void set_TLS_data(VM_thread *thread) { hythread_tls_set(hythread_self(), TLS_key_pvmthread, thread); - //printf ("sett ls call %p %p\n", get_thread_ptr(), get_vm_thread(hythread_self())); + //printf ("sett ls call %p %p\n", get_thread_ptr(), get_vm_thread(hythread_self())); } IDATA jthread_throw_exception(char* name, char* message) { @@ -204,7 +184,7 @@ void* vm_jthread_get_tm_data(jthread thread) { - JNIEnv *jenv = (JNIEnv*)jni_native_intf; + JNIEnv *jenv = jni_native_intf; jclass jThreadClass = jenv->GetObjectClass(thread); jfieldID field_id = jenv->GetFieldID(jThreadClass, "vm_thread", "J"); POINTER_SIZE_INT data = (POINTER_SIZE_INT)jenv->GetLongField(thread, field_id); @@ -213,17 +193,12 @@ } void vm_jthread_set_tm_data(jthread jt, void* nt) { - JNIEnv *jenv = (JNIEnv*)jni_native_intf; + JNIEnv *jenv = jni_native_intf; jclass jthreadclass = jenv->GetObjectClass(jt); jfieldID field_id = jenv->GetFieldID(jthreadclass, "vm_thread", "J"); jenv->SetLongField(jt, field_id, (jlong)(POINTER_SIZE_INT)nt); } -JNIEnv * get_jnienv(void) -{ - return (JNIEnv*)jni_native_intf; -} - int vm_objects_are_equal(jobject obj1, jobject obj2){ //ObjectHandle h1 = (ObjectHandle)obj1; //ObjectHandle h2 = (ObjectHandle)obj2; @@ -239,4 +214,3 @@ int ti_is_enabled(){ return VM_Global_State::loader_env->TI->isEnabled(); } - Index: vmcore/src/util/ia32/base/ini_iA32.cpp =================================================================== --- vmcore/src/util/ia32/base/ini_iA32.cpp (revision 454089) +++ vmcore/src/util/ia32/base/ini_iA32.cpp (working copy) @@ -240,6 +240,7 @@ } if (exn_raised()) { + TRACE("Exception occured: " << exn_get_name()); if ((resultPtr != NULL) && (ret_type != JAVA_TYPE_VOID)) { resultPtr->l = 0; //clear result } Index: vmcore/src/util/ia32/base/jit_runtime_support_ia32.cpp =================================================================== --- vmcore/src/util/ia32/base/jit_runtime_support_ia32.cpp (revision 454089) +++ vmcore/src/util/ia32/base/jit_runtime_support_ia32.cpp (working copy) @@ -1261,61 +1261,7 @@ */ -// a structure used in memoizing already created stubs -struct TypecheckStubMemoizer { - Class *clss; // the class for which this stub is for - void *fast_checkcast_stub, *fast_instanceof_stub; - TypecheckStubMemoizer *next; - static TypecheckStubMemoizer* head; // head of the list - static tl::MemoryPool mem; // we'll alocate structures from here - - static void* find_stub(Class *c, bool is_checkcast) { - // search for an existing struct for this class - for (TypecheckStubMemoizer *t = head; t != NULL; t = t->next) { - if (t->clss == c) { - return (is_checkcast) ? - t->fast_checkcast_stub : t->fast_instanceof_stub; - } - } - - return NULL; - } - - static void add_stub(Class *c, void *stub, bool is_checkcast) { - // search for an existing struct for this class - - TypecheckStubMemoizer *t; - for (t = head; t != NULL; t = t->next) { - if (t->clss == c) - break; - } - - if (t == NULL) { - // create new structure - t = (TypecheckStubMemoizer*) mem.alloc(sizeof(TypecheckStubMemoizer)); - t->clss = c; - t->fast_checkcast_stub = NULL; - t->fast_instanceof_stub = NULL; - t->next = head; - head = t; - } - - if (is_checkcast) { - assert(t->fast_checkcast_stub == NULL); - t->fast_checkcast_stub = stub; - } - else { - assert(t->fast_instanceof_stub == NULL); - t->fast_instanceof_stub = stub; - } - } -}; - -static StaticInitializer jit_runtime_initializer; -TypecheckStubMemoizer* TypecheckStubMemoizer::head = NULL; -tl::MemoryPool TypecheckStubMemoizer::mem; // we'll alocate structures from here - /* ? 03/07/30: temporary interface change!!! */ void *vm_get_rt_support_addr_optimized(VM_RT_SUPPORT f, Class_Handle c) { Class *clss = (Class*) c; Index: vmcore/src/util/ipf/base/ini_ipf.cpp =================================================================== --- vmcore/src/util/ipf/base/ini_ipf.cpp (revision 454089) +++ vmcore/src/util/ipf/base/ini_ipf.cpp (working copy) @@ -306,12 +306,11 @@ break; default: #ifdef _DEBUG - printf("Return type %c is not implemented\n", ret_type); printf("Returned to C from %s.%s%s\n", meth->get_class()->name->bytes, meth->get_name()->bytes, meth->get_descriptor()->bytes); #endif - vm_exit(1); + DIE("Return type " << ret_type << " is not implemented\n"); } } //vm_execute_java_method_array Index: vmcore/src/util/ipf/base/jit_runtime_support_ipf.cpp =================================================================== --- vmcore/src/util/ipf/base/jit_runtime_support_ipf.cpp (revision 454089) +++ vmcore/src/util/ipf/base/jit_runtime_support_ipf.cpp (working copy) @@ -126,8 +126,7 @@ static void unimplemented_rt_support_func1(int f, const char *name) { - printf("This runtime support function is not implemented: f=%d, '%s'\n", f, name); - vm_exit(1); + DIE("This runtime support function is not implemented: f=" << f << ", " << name); } //unimplemented_rt_support_func1 Index: vmcore/src/util/mem_alloc.cpp =================================================================== --- vmcore/src/util/mem_alloc.cpp (revision 454089) +++ vmcore/src/util/mem_alloc.cpp (working copy) @@ -51,7 +51,7 @@ static apr_thread_mutex_t* jit_code_mutex; -// this vector is used to store ptrs of allocated memory to free it in vm_exit +// this vector is used to store ptrs of allocated memory to free it on exit static std::vector m_allocated_memory_ptrs; Index: vmcore/src/util/natives_support.cpp =================================================================== --- vmcore/src/util/natives_support.cpp (revision 454089) +++ vmcore/src/util/natives_support.cpp (working copy) @@ -36,6 +36,7 @@ #include "open/vm_util.h" #include "jni_types.h" +#include "jni_utils.h" #define LOG_DOMAIN "natives" #include "cxxlog.h" @@ -57,17 +58,17 @@ // Initializes natives_support module. Caller must provide thread safety. -bool natives_init() +jint natives_init() { apr_status_t apr_status = apr_pool_create(&jni_libs.ppool, NULL); if (APR_SUCCESS != apr_status) { assert(jni_libs.ppool == NULL); - return false; + return JNI_ENOMEM; } - return true; + return JNI_OK; } // Searches for given name trough the list of loaded libraries @@ -112,7 +113,7 @@ assert(onload_func); - JavaVM* vm = jni_native_intf->vm; // FIXME ???? Can we use it here ???? + JavaVM* vm = jni_get_java_vm(jni_native_intf); // FIXME ???? Can we use it here ???? assert(hythread_is_suspend_enabled()); jint res = onload_func(vm, NULL); @@ -149,7 +150,7 @@ assert(onunload_func); - JavaVM* vm = jni_native_intf->vm; // FIXME ???? Can we use it here ???? + JavaVM* vm = jni_get_java_vm(jni_native_intf); // FIXME ???? Can we use it here ???? assert(hythread_is_suspend_enabled()); onunload_func(vm, NULL); Index: vmcore/src/util/vm_stats.cpp =================================================================== --- vmcore/src/util/vm_stats.cpp (revision 454089) +++ vmcore/src/util/vm_stats.cpp (working copy) @@ -320,7 +320,6 @@ } VM_Statistics & VM_Statistics::get_vm_stats() { - static StaticInitializer initializer = StaticInitializer(); static VM_Statistics vm_stats = VM_Statistics(); return vm_stats; } @@ -657,6 +656,7 @@ void VM_Statistics::print() { + Global_Env *env = VM_Global_State::loader_env; if(!vm_print_total_stats) return; @@ -668,9 +668,7 @@ print_methods(); } - if (vm_methods != NULL) { - vm_methods->print_stats(); - } + env->vm_methods->print_stats(); printf("%11" FMT64 "u ::::Number of native methods\n", num_native_methods); printf("%11" FMT64 "u ::::Number of Java methods\n", num_java_methods); Index: vmcore/src/util/win/em64t/nt_exception_filter.cpp =================================================================== --- vmcore/src/util/win/em64t/nt_exception_filter.cpp (revision 454089) +++ vmcore/src/util/win/em64t/nt_exception_filter.cpp (working copy) @@ -114,8 +114,7 @@ case STATUS_PRIVILEGED_INSTRUCTION: { - ABORT("Unexpected exception code"); - vm_exit(99553); + DIE("Unexpected exception code"); } break; Index: vmi/src/vmi.cpp =================================================================== --- vmi/src/vmi.cpp (revision 454089) +++ vmi/src/vmi.cpp (working copy) @@ -20,6 +20,7 @@ */ #include + #include "platform_lowlevel.h" #include "vm_trace.h" @@ -147,7 +148,7 @@ { *valuePtr = const_cast( properties_get_string_property( - (PropertiesHandle)&VM_Global_State::loader_env->properties, key)); + (PropertiesHandle)VM_Global_State::loader_env->properties, key)); return VMI_ERROR_NONE; } @@ -158,14 +159,14 @@ /* * The possible implemenation might be: */ - add_pair_to_properties(VM_Global_State::loader_env->properties, key, value); + add_pair_to_properties(*VM_Global_State::loader_env->properties, key, value); return VMI_ERROR_NONE; } vmiError JNICALL CountSystemProperties(VMInterface *vmi, int *countPtr) { - Properties &p = VM_Global_State::loader_env->properties; - Properties::Iterator *iter = p.getIterator(); + Properties *p = VM_Global_State::loader_env->properties; + Properties::Iterator *iter = p->getIterator(); int count = 0; const Prop_entry *next = NULL; @@ -179,8 +180,8 @@ vmiError JNICALL IterateSystemProperties(VMInterface *vmi, vmiSystemPropertyIterator iterator, void *userData) { - Properties &p = VM_Global_State::loader_env->properties; - Properties::Iterator *iter = p.getIterator(); + Properties *p = VM_Global_State::loader_env->properties; + Properties::Iterator *iter = p->getIterator(); const Prop_entry *next = NULL; while((next = iter->next())) Index: vmstart/src/main.cpp =================================================================== --- vmstart/src/main.cpp (revision 454089) +++ vmstart/src/main.cpp (working copy) @@ -1,32 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 Intel, Alexei Fedotov - * @version $Revision: 1.1.2.1.4.3 $ - */ - -int vm_main(int argc, char *argv[]); - -int main(int argc, char *argv[]) -{ - /* - * delegate control to vm-provided initialization function - * currently found in vmcore/src/init/vm_main.cpp - */ - - return vm_main(argc, argv); -}