changeset 3555:22d11b3bc561

Various hacks to be able to install machine code from a Java thread.
author Thomas Wuerthinger <thomas@wuerthinger.net>
date Wed, 24 Aug 2011 01:05:02 +0200
parents b20889b42d12
children b2cd623a93ad
files src/share/vm/ci/ciEnv.cpp src/share/vm/ci/ciEnv.hpp src/share/vm/ci/ciUtilities.hpp src/share/vm/classfile/classLoader.cpp src/share/vm/compiler/compileBroker.cpp src/share/vm/graal/graalCodeInstaller.cpp src/share/vm/graal/graalCompiler.cpp src/share/vm/graal/graalCompiler.hpp src/share/vm/graal/graalVMEntries.cpp src/share/vm/runtime/thread.cpp src/share/vm/runtime/thread.hpp
diffstat 11 files changed, 96 insertions(+), 52 deletions(-) [+]
line wrap: on
line diff
--- 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);
 }
--- 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; }
--- 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;
 
 
--- 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) {
 
--- 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());
--- 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);
--- 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<Handle>(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<Handle>(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");
--- 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
--- 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<Handle>(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<Handle>(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<Handle>(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)},
--- 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
--- 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) {