X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=libjava%2Flink.cc;h=4ea548ec905881ff96594452e9ae0fb50512309a;hb=acaaf0c621688e090e0f8024ce19a90b1dcde7aa;hp=7f398889a29e5e767125a315d8c506f976374b76;hpb=ea517ca550bf8a1bed19dda72e731d717465850c;p=gcc.git diff --git a/libjava/link.cc b/libjava/link.cc index 7f398889a29..4ea548ec905 100644 --- a/libjava/link.cc +++ b/libjava/link.cc @@ -33,6 +33,8 @@ details. */ #include #include #include +#include +#include "jvmti-int.h" #include #include #include @@ -1020,15 +1022,17 @@ struct method_closure // be the same as the address of the overall structure. This is due // to disabling interior pointers in the GC. ffi_closure closure; + _Jv_ClosureList list; ffi_cif cif; ffi_type *arg_types[1]; }; void * -_Jv_Linker::create_error_method (_Jv_Utf8Const *class_name) +_Jv_Linker::create_error_method (_Jv_Utf8Const *class_name, jclass klass) { + void *code; method_closure *closure - = (method_closure *) _Jv_AllocBytes(sizeof (method_closure)); + = (method_closure *)ffi_closure_alloc (sizeof (method_closure), &code); closure->arg_types[0] = &ffi_type_void; @@ -1040,13 +1044,18 @@ _Jv_Linker::create_error_method (_Jv_Utf8Const *class_name) 1, &ffi_type_void, closure->arg_types) == FFI_OK - && ffi_prep_closure (&closure->closure, - &closure->cif, - _Jv_ThrowNoClassDefFoundErrorTrampoline, - class_name) == FFI_OK) - return &closure->closure; + && ffi_prep_closure_loc (&closure->closure, + &closure->cif, + _Jv_ThrowNoClassDefFoundErrorTrampoline, + class_name, + code) == FFI_OK) + { + closure->list.registerClosure (klass, closure); + return code; + } else { + ffi_closure_free (closure); java::lang::StringBuffer *buffer = new java::lang::StringBuffer(); buffer->append(JvNewStringLatin1("Error setting up FFI closure" " for static method of" @@ -1057,7 +1066,7 @@ _Jv_Linker::create_error_method (_Jv_Utf8Const *class_name) } #else void * -_Jv_Linker::create_error_method (_Jv_Utf8Const *) +_Jv_Linker::create_error_method (_Jv_Utf8Const *, jclass) { // Codepath for platforms which do not support (or want) libffi. // You have to accept that it is impossible to provide the name @@ -1088,8 +1097,6 @@ static bool debug_link = false; // at the corresponding position in the virtual method offset table // (klass->otable). -// The same otable and atable may be shared by many classes. - // This must be called while holding the class lock. void @@ -1240,13 +1247,15 @@ _Jv_Linker::link_symbol_table (jclass klass) // NullPointerException klass->atable->addresses[index] = NULL; + bool use_error_method = false; + // If the target class is missing we prepare a function call // that throws a NoClassDefFoundError and store the address of // that newly prepared method in the atable. The user can run // code in classes where the missing class is part of the // execution environment as long as it is never referenced. if (target_class == NULL) - klass->atable->addresses[index] = create_error_method(sym.class_name); + use_error_method = true; // We're looking for a static field or a static method, and we // can tell which is needed by looking at the signature. else if (signature->first() == '(' && signature->len() >= 2) @@ -1294,12 +1303,16 @@ _Jv_Linker::link_symbol_table (jclass klass) } } else + use_error_method = true; + + if (use_error_method) klass->atable->addresses[index] - = create_error_method(sym.class_name); + = create_error_method(sym.class_name, klass); continue; } + // Try fields only if the target class exists. if (target_class != NULL) { @@ -1941,33 +1954,35 @@ _Jv_Linker::wait_for_state (jclass klass, int state) if (klass->state >= state) return; - JvSynchronize sync (klass); - - // This is similar to the strategy for class initialization. If we - // already hold the lock, just leave. java::lang::Thread *self = java::lang::Thread::currentThread(); - while (klass->state <= state - && klass->thread - && klass->thread != self) - klass->wait (); - java::lang::Thread *save = klass->thread; - klass->thread = self; + { + JvSynchronize sync (klass); - // Allocate memory for static fields and constants. - if (GC_base (klass) && klass->fields && ! GC_base (klass->fields)) - { - jsize count = klass->field_count; - if (count) - { - _Jv_Field* fields - = (_Jv_Field*) _Jv_AllocRawObj (count * sizeof (_Jv_Field)); - memcpy ((void*)fields, - (void*)klass->fields, - count * sizeof (_Jv_Field)); - klass->fields = fields; - } - } + // This is similar to the strategy for class initialization. If we + // already hold the lock, just leave. + while (klass->state <= state + && klass->thread + && klass->thread != self) + klass->wait (); + + java::lang::Thread *save = klass->thread; + klass->thread = self; + + // Allocate memory for static fields and constants. + if (GC_base (klass) && klass->fields && ! GC_base (klass->fields)) + { + jsize count = klass->field_count; + if (count) + { + _Jv_Field* fields + = (_Jv_Field*) _Jv_AllocRawObj (count * sizeof (_Jv_Field)); + memcpy ((void*)fields, + (void*)klass->fields, + count * sizeof (_Jv_Field)); + klass->fields = fields; + } + } // Print some debugging info if requested. Interpreted classes are // handled in defineclass, so we only need to handle the two @@ -1981,49 +1996,59 @@ _Jv_Linker::wait_for_state (jclass klass, int state) ++gcj::loadedClasses; } - try - { - if (state >= JV_STATE_LOADING && klass->state < JV_STATE_LOADING) - { - ensure_supers_installed (klass); - klass->set_state(JV_STATE_LOADING); - } + try + { + if (state >= JV_STATE_LOADING && klass->state < JV_STATE_LOADING) + { + ensure_supers_installed (klass); + klass->set_state(JV_STATE_LOADING); + } - if (state >= JV_STATE_LOADED && klass->state < JV_STATE_LOADED) - { - ensure_method_table_complete (klass); - klass->set_state(JV_STATE_LOADED); - } + if (state >= JV_STATE_LOADED && klass->state < JV_STATE_LOADED) + { + ensure_method_table_complete (klass); + klass->set_state(JV_STATE_LOADED); + } - if (state >= JV_STATE_PREPARED && klass->state < JV_STATE_PREPARED) - { - ensure_fields_laid_out (klass); - make_vtable (klass); - layout_interface_methods (klass); - prepare_constant_time_tables (klass); - klass->set_state(JV_STATE_PREPARED); - } + if (state >= JV_STATE_PREPARED && klass->state < JV_STATE_PREPARED) + { + ensure_fields_laid_out (klass); + make_vtable (klass); + layout_interface_methods (klass); + prepare_constant_time_tables (klass); + klass->set_state(JV_STATE_PREPARED); + } - if (state >= JV_STATE_LINKED && klass->state < JV_STATE_LINKED) - { - if (gcj::verifyClasses) - verify_class (klass); + if (state >= JV_STATE_LINKED && klass->state < JV_STATE_LINKED) + { + if (gcj::verifyClasses) + verify_class (klass); - ensure_class_linked (klass); - link_exception_table (klass); - link_symbol_table (klass); - klass->set_state(JV_STATE_LINKED); - } - } - catch (java::lang::Throwable *exc) - { - klass->thread = save; - klass->set_state(JV_STATE_ERROR); - throw exc; - } + ensure_class_linked (klass); + link_exception_table (klass); + link_symbol_table (klass); + klass->set_state(JV_STATE_LINKED); + } + } + catch (java::lang::Throwable *exc) + { + klass->thread = save; + klass->set_state(JV_STATE_ERROR); + throw exc; + } + + klass->thread = save; - klass->thread = save; + if (klass->state == JV_STATE_ERROR) + throw new java::lang::LinkageError; + } - if (klass->state == JV_STATE_ERROR) - throw new java::lang::LinkageError; + if (__builtin_expect (klass->state == JV_STATE_LINKED, false) + && state >= JV_STATE_LINKED + && JVMTI_REQUESTED_EVENT (ClassPrepare)) + { + JNIEnv *jni_env = _Jv_GetCurrentJNIEnv (); + _Jv_JVMTI_PostEvent (JVMTI_EVENT_CLASS_PREPARE, self, jni_env, + klass); + } }