# HG changeset patch # User Thomas Wuerthinger # Date 1314140702 -7200 # Node ID 22d11b3bc561d16f3c2089e6bea1c0db6b049b2e # Parent b20889b42d125337891ad445c52adf040b5c2921 Various hacks to be able to install machine code from a Java thread. diff -r b20889b42d12 -r 22d11b3bc561 src/share/vm/ci/ciEnv.cpp --- a/src/share/vm/ci/ciEnv.cpp Mon Aug 22 19:55:06 2011 +0200 +++ b/src/share/vm/ci/ciEnv.cpp Wed Aug 24 01:05:02 2011 +0200 @@ -94,7 +94,7 @@ // ciEnv::ciEnv ciEnv::ciEnv(CompileTask* task, int system_dictionary_modification_counter) { VM_ENTRY_MARK; - + CompilerThread* compiler_thread = CompilerThread::current(); // Set up ciEnv::current immediately, for the sake of ciObjectFactory, etc. thread->set_env(this); assert(ciEnv::current() == this, "sanity"); @@ -106,13 +106,13 @@ _compilable = MethodCompilable; _break_at_compile = false; _compiler_data = NULL; -#ifndef PRODUCT - assert(!firstEnv, "not initialized properly"); -#endif /* !PRODUCT */ +//#ifndef PRODUCT +// assert(!firstEnv, "not initialized properly"); +//#endif /* !PRODUCT */ _system_dictionary_modification_counter = system_dictionary_modification_counter; _num_inlined_bytecodes = 0; - assert(task == NULL || thread->task() == task, "sanity"); + assert(task == NULL || compiler_thread->task() == task, "sanity"); _task = task; _log = NULL; @@ -149,7 +149,7 @@ ASSERT_IN_VM; // Set up ciEnv::current immediately, for the sake of ciObjectFactory, etc. - CompilerThread* current_thread = CompilerThread::current(); + JavaThread* current_thread = JavaThread::current(); assert(current_thread->env() == NULL, "must be"); current_thread->set_env(this); assert(ciEnv::current() == this, "sanity"); @@ -161,10 +161,10 @@ _compilable = MethodCompilable_never; _break_at_compile = false; _compiler_data = NULL; -#ifndef PRODUCT - assert(firstEnv, "must be first"); - firstEnv = false; -#endif /* !PRODUCT */ +//#ifndef PRODUCT +// assert(firstEnv, "must be first"); +// firstEnv = false; +//#endif /* !PRODUCT */ _system_dictionary_modification_counter = 0; _num_inlined_bytecodes = 0; @@ -202,7 +202,7 @@ ciEnv::~ciEnv() { _factory->cleanup(); - CompilerThread* current_thread = CompilerThread::current(); + JavaThread* current_thread = JavaThread::current(); _factory->remove_symbols(); current_thread->set_env(NULL); } diff -r b20889b42d12 -r 22d11b3bc561 src/share/vm/ci/ciEnv.hpp --- a/src/share/vm/ci/ciEnv.hpp Mon Aug 22 19:55:06 2011 +0200 +++ b/src/share/vm/ci/ciEnv.hpp Wed Aug 24 01:05:02 2011 +0200 @@ -384,10 +384,10 @@ Arena* arena() { return _arena; } // What is the current compilation environment? - static ciEnv* current() { return CompilerThread::current()->env(); } + static ciEnv* current() { return JavaThread::current()->env(); } // Overload with current thread argument - static ciEnv* current(CompilerThread *thread) { return thread->env(); } + static ciEnv* current(JavaThread *thread) { return thread->env(); } // Per-compiler data. (Used by C2 to publish the Compile* pointer.) void* compiler_data() { return _compiler_data; } diff -r b20889b42d12 -r 22d11b3bc561 src/share/vm/ci/ciUtilities.hpp --- a/src/share/vm/ci/ciUtilities.hpp Mon Aug 22 19:55:06 2011 +0200 +++ b/src/share/vm/ci/ciUtilities.hpp Wed Aug 24 01:05:02 2011 +0200 @@ -36,7 +36,7 @@ // Bring the compilation thread into the VM state. #define VM_ENTRY_MARK \ - CompilerThread* thread=CompilerThread::current(); \ + JavaThread* thread=JavaThread::current(); \ ThreadInVMfromNative __tiv(thread); \ ResetNoHandleMark rnhm; \ HandleMarkCleaner __hm(thread); \ @@ -47,7 +47,7 @@ // Bring the compilation thread into the VM state. No handle mark. #define VM_QUICK_ENTRY_MARK \ - CompilerThread* thread=CompilerThread::current(); \ + JavaThread* thread=JavaThread::current(); \ ThreadInVMfromNative __tiv(thread); \ /* \ * [TODO] The NoHandleMark line does nothing but declare a function prototype \ @@ -60,7 +60,7 @@ #define EXCEPTION_CONTEXT \ - CompilerThread* thread=CompilerThread::current(); \ + JavaThread* thread=JavaThread::current(); \ Thread* THREAD = thread; diff -r b20889b42d12 -r 22d11b3bc561 src/share/vm/classfile/classLoader.cpp --- a/src/share/vm/classfile/classLoader.cpp Mon Aug 22 19:55:06 2011 +0200 +++ b/src/share/vm/classfile/classLoader.cpp Wed Aug 24 01:05:02 2011 +0200 @@ -585,7 +585,7 @@ // File or directory found ClassPathEntry* new_entry = NULL; create_class_path_entry((char *)path, st, &new_entry, LazyBootClassLoader); - new_entry->set_compiler_thread_only(compiler_cp); + //new_entry->set_compiler_thread_only(compiler_cp); // The kernel VM adds dynamically to the end of the classloader path and // doesn't reorder the bootclasspath which would break java.lang.Package // (see PackageInfo). @@ -913,6 +913,22 @@ } } + if (stream == NULL && !(THREAD->is_Compiler_thread())) { + classpath_index = 0; + PerfClassTraceTime vmtimer(perf_sys_class_lookup_time(), + ((JavaThread*) THREAD)->get_thread_stat()->perf_timers_addr(), + PerfClassTraceTime::CLASS_LOAD); + ClassPathEntry* e = _first_entry; + while (e != NULL) { + stream = e->open_stream(name); + if (stream != NULL) { + break; + } + e = e->next(); + ++classpath_index; + } + } + instanceKlassHandle h(THREAD, klassOop(NULL)); if (stream != NULL) { diff -r b20889b42d12 -r 22d11b3bc561 src/share/vm/compiler/compileBroker.cpp --- a/src/share/vm/compiler/compileBroker.cpp Mon Aug 22 19:55:06 2011 +0200 +++ b/src/share/vm/compiler/compileBroker.cpp Wed Aug 24 01:05:02 2011 +0200 @@ -660,7 +660,7 @@ tty->print_cr("Bootstrapping graal...."); GraalCompiler* compiler = GraalCompiler::instance(); - if (compiler == NULL) fatal("must use flag -XX:+UseGraal"); + assert(compiler != NULL, "just checking"); jlong start = os::javaTimeMillis(); add_method_to_queue(SystemDictionary::Object_klass(), vmSymbols::object_initializer_name(), vmSymbols::void_method_signature()); diff -r b20889b42d12 -r 22d11b3bc561 src/share/vm/graal/graalCodeInstaller.cpp --- a/src/share/vm/graal/graalCodeInstaller.cpp Mon Aug 22 19:55:06 2011 +0200 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Wed Aug 24 01:05:02 2011 +0200 @@ -231,23 +231,25 @@ // constructor used to create a method CodeInstaller::CodeInstaller(Handle target_method) { + _env = CURRENT_ENV; ciMethod *ciMethodObject = NULL; { + methodOop method = getMethodFromHotSpotMethod(HotSpotTargetMethod::method(target_method)); + ciMethodObject = (ciMethod *) _env->get_object(method); + _parameter_count = method->size_of_parameters(); + No_Safepoint_Verifier no_safepoint; - _env = CURRENT_ENV; initialize_fields(target_method); assert(_hotspot_method != NULL && _name == NULL, "installMethod needs NON-NULL method and NULL name"); assert(_hotspot_method->is_a(HotSpotMethodResolved::klass()), "installMethod needs a HotSpotMethodResolved"); - methodOop method = getMethodFromHotSpotMethod(_hotspot_method); - ciMethodObject = (ciMethod *) _env->get_object(method); - _parameter_count = method->size_of_parameters(); } // (very) conservative estimate: each site needs a relocation //CodeBuffer buffer("temp graal method", _total_size, _sites->length() * relocInfo::length_limit); - CodeBuffer buffer(CompilerThread::current()->get_buffer_blob()); + GraalCompiler::initialize_buffer_blob(); + CodeBuffer buffer(JavaThread::current()->get_buffer_blob()); initialize_buffer(buffer); process_exception_handlers(); @@ -267,7 +269,8 @@ assert(_hotspot_method == NULL && _name != NULL, "installMethod needs NON-NULL name and NULL method"); // (very) conservative estimate: each site needs a relocation - CodeBuffer buffer(CompilerThread::current()->get_buffer_blob()); + GraalCompiler::initialize_buffer_blob(); + CodeBuffer buffer(JavaThread::current()->get_buffer_blob()); initialize_buffer(buffer); const char* cname = java_lang_String::as_utf8_string(_name); diff -r b20889b42d12 -r 22d11b3bc561 src/share/vm/graal/graalCompiler.cpp --- a/src/share/vm/graal/graalCompiler.cpp Mon Aug 22 19:55:06 2011 +0200 +++ b/src/share/vm/graal/graalCompiler.cpp Wed Aug 24 01:05:02 2011 +0200 @@ -84,7 +84,7 @@ void GraalCompiler::initialize_buffer_blob() { - CompilerThread* THREAD = CompilerThread::current(); + JavaThread* THREAD = JavaThread::current(); if (THREAD->get_buffer_blob() == NULL) { // setup CodeBuffer. Preallocate a BufferBlob of size // NMethodSizeLimit plus some extra space for constants. @@ -104,15 +104,13 @@ ResourceMark rm; HandleMark hm; - initialize_buffer_blob(); VmIds::initializeObjects(); TRACE_graal_2("GraalCompiler::compile_method"); CompilerThread::current()->set_compiling(true); methodOop method = (methodOop) target->get_oop(); - Handle name = VmIds::toString(method->name(), CHECK); - Handle hotspot_method = GraalCompiler::createHotSpotMethodResolved(method, name, CHECK); + Handle hotspot_method = GraalCompiler::createHotSpotMethodResolved(method, CHECK); VMExits::compileMethod(hotspot_method, entry_bci); CompilerThread::current()->set_compiling(false); @@ -202,12 +200,14 @@ return obj(); } -oop GraalCompiler::createHotSpotMethodResolved(methodHandle method, Handle name, TRAPS) { +oop GraalCompiler::createHotSpotMethodResolved(methodHandle method, TRAPS) { if (method->graal_mirror() != NULL) { assert(method->graal_mirror()->is_a(HotSpotMethodResolved::klass()), "unexpected class..."); return method->graal_mirror(); } + Handle name = VmIds::toString(method->name(), CHECK_NULL); + instanceKlass::cast(HotSpotMethodResolved::klass())->initialize(CHECK_NULL); Handle obj = instanceKlass::cast(HotSpotMethodResolved::klass())->allocate_instance(CHECK_NULL); assert(obj() != NULL, "must succeed in allocating instance"); diff -r b20889b42d12 -r 22d11b3bc561 src/share/vm/graal/graalCompiler.hpp --- a/src/share/vm/graal/graalCompiler.hpp Mon Aug 22 19:55:06 2011 +0200 +++ b/src/share/vm/graal/graalCompiler.hpp Wed Aug 24 01:05:02 2011 +0200 @@ -61,7 +61,7 @@ static oop get_RiField(ciField *ciField, ciInstanceKlass* accessor_klass, KlassHandle accessor, Bytecodes::Code byteCode, TRAPS); static oop createHotSpotTypeResolved(KlassHandle klass, Handle name, TRAPS); - static oop createHotSpotMethodResolved(methodHandle method, Handle name, TRAPS); + static oop createHotSpotMethodResolved(methodHandle method, TRAPS); void exit(); @@ -75,9 +75,7 @@ return index; } -private: - - void initialize_buffer_blob(); + static void initialize_buffer_blob(); }; // Tracing macros diff -r b20889b42d12 -r 22d11b3bc561 src/share/vm/graal/graalVMEntries.cpp --- a/src/share/vm/graal/graalVMEntries.cpp Mon Aug 22 19:55:06 2011 +0200 +++ b/src/share/vm/graal/graalVMEntries.cpp Wed Aug 24 01:05:02 2011 +0200 @@ -143,6 +143,19 @@ return cimethod->has_balanced_monitors(); } +// public RiMethod getRiMethod(java.lang.reflect.Method reflectionMethod); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_getRiMethod(JNIEnv *, jobject, jobject reflection_method_handle) { + TRACE_graal_3("VMEntries::getRiMethod"); + VM_ENTRY_MARK; + oop reflection_method = JNIHandles::resolve(reflection_method_handle); + oop reflection_holder = java_lang_reflect_Method::clazz(reflection_method); + int slot = java_lang_reflect_Method::slot(reflection_method); + klassOop holder = java_lang_Class::as_klassOop(reflection_holder); + methodOop method = instanceKlass::cast(holder)->method_with_idnum(slot); + oop ret = GraalCompiler::createHotSpotMethodResolved(method, CHECK_NULL); + return JNIHandles::make_local(THREAD, ret); +} + // public boolean RiMethod_uniqueConcreteMethod(long vmId); JNIEXPORT jobject JNICALL Java_com_oracle_graal_runtime_VMEntries_RiMethod_1uniqueConcreteMethod(JNIEnv *, jobject, jobject hotspot_method) { TRACE_graal_3("VMEntries::RiMethod_uniqueConcreteMethod"); @@ -171,8 +184,7 @@ return NULL; } - Handle name = VmIds::toString(unique_concrete->name(), CHECK_NULL); - oop method_resolved = GraalCompiler::createHotSpotMethodResolved(unique_concrete(), name, CHECK_NULL); + oop method_resolved = GraalCompiler::createHotSpotMethodResolved(unique_concrete(), CHECK_NULL); return JNIHandles::make_local(THREAD, method_resolved); } @@ -462,8 +474,7 @@ ciMethod *cimethod = CURRENT_ENV->get_method_by_index(cp, index, bc, loading_klass); if (cimethod->is_loaded()) { methodOop method = (methodOop) cimethod->get_oop(); - Handle name = VmIds::toString(method->name(), CHECK_NULL); - oop ret = GraalCompiler::createHotSpotMethodResolved(method, name, CHECK_NULL); + oop ret = GraalCompiler::createHotSpotMethodResolved(method, CHECK_NULL); return JNIHandles::make_local(THREAD, ret); } else { Handle name = VmIds::toString(cimethod->name()->get_symbol(), CHECK_NULL); @@ -584,7 +595,7 @@ } return NULL; } - oop ret = GraalCompiler::createHotSpotMethodResolved(method, Handle(JNIHandles::resolve(name)), CHECK_NULL); + oop ret = GraalCompiler::createHotSpotMethodResolved(method, CHECK_NULL); return JNIHandles::make_local(THREAD, ret); } @@ -858,14 +869,26 @@ // public void installMethod(HotSpotTargetMethod targetMethod); JNIEXPORT void JNICALL Java_com_oracle_graal_runtime_VMEntries_installMethod(JNIEnv *jniEnv, jobject, jobject targetMethod) { VM_ENTRY_MARK; - CodeInstaller installer(JNIHandles::resolve(targetMethod)); + if (CURRENT_ENV == NULL) { + Arena arena; + ciEnv env(&arena); + CodeInstaller installer(JNIHandles::resolve(targetMethod)); + } else { + CodeInstaller installer(JNIHandles::resolve(targetMethod)); + } } // public HotSpotProxy installStub(HotSpotTargetMethod targetMethod, String name); JNIEXPORT jlong JNICALL Java_com_oracle_graal_runtime_VMEntries_installStub(JNIEnv *jniEnv, jobject, jobject targetMethod) { VM_ENTRY_MARK; jlong id; - CodeInstaller installer(JNIHandles::resolve(targetMethod), id); + if (CURRENT_ENV == NULL) { + Arena arena; + ciEnv env(&arena); + CodeInstaller installer(JNIHandles::resolve(targetMethod), id); + } else { + CodeInstaller installer(JNIHandles::resolve(targetMethod), id); + } return id; } @@ -891,6 +914,7 @@ #define RESOLVED_TYPE "Lcom/oracle/max/graal/runtime/HotSpotTypeResolved;" #define METHOD "Lcom/sun/cri/ri/RiMethod;" #define RESOLVED_METHOD "Lcom/oracle/max/graal/runtime/HotSpotMethodResolved;" +#define REFLECT_METHOD "Ljava/lang/reflect/Method;" #define TYPE_PROFILE "Lcom/sun/cri/ri/RiTypeProfile;" #define SIGNATURE "Lcom/sun/cri/ri/RiSignature;" #define FIELD "Lcom/sun/cri/ri/RiField;" @@ -911,6 +935,7 @@ {CC"RiMethod_exceptionHandlers", CC"("RESOLVED_METHOD")"EXCEPTION_HANDLERS, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1exceptionHandlers)}, {CC"RiMethod_hasBalancedMonitors", CC"("RESOLVED_METHOD")Z", FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1hasBalancedMonitors)}, {CC"RiMethod_uniqueConcreteMethod", CC"("RESOLVED_METHOD")"METHOD, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_1uniqueConcreteMethod)}, + {CC"getRiMethod", CC"("REFLECT_METHOD")"METHOD, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_getRiMethod)}, {CC"RiMethod_typeProfile", CC"("RESOLVED_METHOD"I)"TYPE_PROFILE, FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_2typeProfile)}, {CC"RiMethod_branchProbability", CC"("RESOLVED_METHOD"I)D", FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_2branchProbability)}, {CC"RiMethod_switchProbability", CC"("RESOLVED_METHOD"I)[D", FN_PTR(Java_com_oracle_graal_runtime_VMEntries_RiMethod_2switchProbability)}, diff -r b20889b42d12 -r 22d11b3bc561 src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Mon Aug 22 19:55:06 2011 +0200 +++ b/src/share/vm/runtime/thread.cpp Wed Aug 24 01:05:02 2011 +0200 @@ -1245,7 +1245,9 @@ // Set the claimed par_id to -1 (ie not claiming any par_ids) set_claimed_par_id(-1); - + + _env = NULL; + _buffer_blob = NULL; set_saved_exception_pc(NULL); set_threadObj(NULL); _anchor.clear(); @@ -2940,13 +2942,11 @@ // Create a CompilerThread CompilerThread::CompilerThread(CompileQueue* queue, CompilerCounters* counters) : JavaThread(&compiler_thread_entry) { - _env = NULL; _log = NULL; _task = NULL; _queue = queue; _counters = counters; _is_compiling = false; - _buffer_blob = NULL; _scanned_nmethod = NULL; #ifndef PRODUCT diff -r b20889b42d12 -r 22d11b3bc561 src/share/vm/runtime/thread.hpp --- a/src/share/vm/runtime/thread.hpp Mon Aug 22 19:55:06 2011 +0200 +++ b/src/share/vm/runtime/thread.hpp Wed Aug 24 01:05:02 2011 +0200 @@ -713,6 +713,10 @@ JavaThread* _next; // The next thread in the Threads list oop _threadObj; // The Java level thread object + // (tw) Necessary for holding a compilation buffer and ci environment. Moved from CompilerThread to JavaThread in order to enable code installation from Java application code. + BufferBlob* _buffer_blob; + ciEnv* _env; + #ifdef ASSERT private: int _java_call_counter; @@ -909,6 +913,13 @@ struct JNINativeInterface_* get_jni_functions() { return (struct JNINativeInterface_ *)_jni_environment.functions; } + + // Get/set the thread's compilation environment. + ciEnv* env() { return _env; } + void set_env(ciEnv* env) { _env = env; } + + BufferBlob* get_buffer_blob() { return _buffer_blob; } + void set_buffer_blob(BufferBlob* b) { _buffer_blob = b; }; // This function is called at thread creation to allow // platform specific thread variables to be initialized. @@ -1696,12 +1707,10 @@ private: CompilerCounters* _counters; - ciEnv* _env; CompileLog* _log; CompileTask* _task; CompileQueue* _queue; bool _is_compiling; - BufferBlob* _buffer_blob; nmethod* _scanned_nmethod; // nmethod being scanned by the sweeper @@ -1721,13 +1730,6 @@ CompileQueue* queue() { return _queue; } CompilerCounters* counters() { return _counters; } - // Get/set the thread's compilation environment. - ciEnv* env() { return _env; } - void set_env(ciEnv* env) { _env = env; } - - BufferBlob* get_buffer_blob() { return _buffer_blob; } - void set_buffer_blob(BufferBlob* b) { _buffer_blob = b; }; - // Get/set the thread's logging information CompileLog* log() { return _log; } void init_log(CompileLog* log) {