eclipse-openj9 / openj9

Eclipse OpenJ9: A Java Virtual Machine for OpenJDK that's optimized for small footprint, fast start-up, and high throughput. Builds on Eclipse OMR (https://github.com/eclipse/omr) and combines with the Extensions for OpenJDK for OpenJ9 repo.
Other
3.24k stars 713 forks source link

Explore supporting OMR JitBuilder API from OpenJ9 JIT #5836

Open mstoodle opened 5 years ago

mstoodle commented 5 years ago

I have been working on a side project to enable the internal JVM as well as Java applications (under proper security permission) to be able to generate native code directly into the JIT code cache using the OMR JitBuilder API. That should include, at some point, the ability for the JIT to inject such code sequences (as IL) into Java method compiles (and vice versa).

There are a host of obstacles to making this work, not least that some fundamental structures aren’t really shared between the OpenJ9 JIT and the OMR compiler, but I’ve been trying to hack my way through just to see what all is needed.

Current status: From the jitHookAboutToRunMain() I created a TypeDictionary and a MethodBuilder object representing a function that returns the 64-bit constant '3'. I called compileMethodBuilder() on that object, cast the returned startPC to a function pointer, called the function and verified that I did get the 64-bit value 3 as its return value. Yay!

I am now working through the Java language client bindings which would enable using JitBuilder directly in a Java application. I'm building on top of the C generator originally started by @Leonardo2718 and now in an OMR pull request thanks to @daytonallen ( https://github.com/eclipse/omr/pull/3859 ). As of now, I have Java classes being correctly generated for the full JitBuilder API (they can be compiled with javac without errors though there are warnings due to use of Unsafe). The next step is to generate the native layer underneath the Java classes that connect Java calls into the JitBuilder library and support the callbacks coming out of the native JitBuilder library.

Issues encountered so far:

fjeremic commented 5 years ago

@Leonardo2718 FYI this will help with enabling Tril on OpenJ9.

mstoodle commented 5 years ago

MethodBuilder I'm currently trying to get to compile and then be used inside jitHookAboutToRunMain :

class TestTypeDictionary : public OMR::JitBuilder::TypeDictionary
   {
   public:
   TestTypeDictionary()
      : OMR::JitBuilder::TypeDictionary()
      {
      DEFINE_STRUCT(J9VMThread);
      DEFINE_FIELD(J9VMThread, javaVM, Word);
      CLOSE_STRUCT(J9VMThread);
      }
   };

class TestMethodBuilder : public OMR::JitBuilder::MethodBuilder
   {
   public:
   TestMethodBuilder(TestTypeDictionary * d)
      : OMR::JitBuilder::MethodBuilder(d)
      {
      DefineLine(LINETOSTR(__LINE__));
      DefineFile(__FILE__);
      DefineName("getJavaVMFromThread");

      OMR::JitBuilder::IlType *pJ9JavaVM = d->PointerTo(Word);
      DefineReturnType(pJ9JavaVM);

      OMR::JitBuilder::IlType *j9VMThreadType = d->LookupStruct("J9VMThread");
      OMR::JitBuilder::IlType *pJ9VMThreadType = d->PointerTo(j9VMThreadType);
      DefineParameter("vmThread", pJ9VMThreadType);
      }

   bool buildIL()
      {
      Return(
         LoadIndirect("J9VMThread", "javaVM",
            Load("vmThread")));
      return true;
      }
   };
mstoodle commented 5 years ago

Update: today I hacked my way to compiling a simpler test (the infamous Return(ConstInt64(3))) while inside the OpenJ9 JIT. Still need to verify things are doing what I think they're doing, but it looks sort of reasonable.

Next step: get the Java API to work.

mstoodle commented 5 years ago

The MethodBuilder I have tested so far:

class TestMethodBuilder : public OMR::JitBuilder::MethodBuilder
   {
   public:
   TestMethodBuilder(TestTypeDictionary * d)
      : OMR::JitBuilder::MethodBuilder(d)
      {
      DefineLine(LINETOSTR(__LINE__));
      DefineFile(__FILE__);
      DefineName("ReturnThree");
      DefineReturnType(Int64);

      }

   bool buildIL()
      {
      Return(
         ConstInt64(3));
      return true;
      }
   };
mstoodle commented 5 years ago

Verbose output:

[ .. lots of other JIT compiled methods ... ]
+ (warm) /Users/mstoodle/git/openj9-openjdk-jdk11/build/macosx-x86_64-normal-server-release/vm/compiler/../compiler/control/HookedByTheJit.cpp:284:ReturnThree @ 0000000019002238-0000000019002258 MethodBuilder JitBuilder Q_SZ=5 Q_SZI=4 QW=26 sync compThread=0 CpuLoad=0%(0%avg) JvmCpu=283%

And the output that verified it worked, just for completeness :) :

Return3 MethodBuilder Passed! returned 3
mstoodle commented 5 years ago

I'll clean up my branch a bit and will then push, just for reference. It's got some ugly stuff in it we'll have to think harder about how to solve more properly.

fjeremic commented 5 years ago

Thanks for all the efforts here. I'm closely following the progress and appreciate the work. Getting JitBuilder working in OpenJ9 opens up a world of possibilities, including a Java API to generate JIT bodies on the fly, as well as a plethora of things we can do around testing the JIT.

mstoodle commented 5 years ago

I just pushed https://github.com/mstoodle/openj9/tree/explore_jitbuilder which contains the commits I used to get JitBuilder to compile inside the OpenJ9 JIT as well as to be able to invoke it from within the OpenJ9 JIT. I'm not filing it as a pull request because there are too many hacks, but if anyone wants to look through it, feedback welcome.

Note that it's very preliminary at the moment (not only due to hacks): only a subset of the JitBuilder API will work properly given the current state of things. More work will be needed to align the use of Symbols/SymbolReferences so things like Struct and Union can work, not to mention augmenting the J9 API with first class Java concepts like objects, classes, fields, and ability to construct try/catch blocks, etc.

mstoodle commented 5 years ago

Made some more progress on the way to being able to use JitBuilder from Java applications.

I managed to get the Java API client classes generated now, and successfully compiling with javac . I still need to generate the native layer that connects the Java classes to the JitBuilder implementation classes, but that shouldn't be too bad since it's mostly a pass-through layer (a lot of the implementation versus client object stuff landed in the Java layer).