[llvm-commits] [llvm] r85295 - in /llvm/trunk: docs/tutorial/LangImpl4.html docs/tutorial/OCamlLangImpl4.html include/llvm/ExecutionEngine/ExecutionEngine.h lib/ExecutionEngine/ExecutionEngine.cpp lib/ExecutionEngine/JIT/JIT.cpp lib/ExecutionEngine/JIT/JITEmitter.cpp tools/lli/lli.cpp unittests/ExecutionEngine/JIT/JITTest.cpp

Jeffrey Yasskin jyasskin at google.com
Tue Oct 27 13:30:29 PDT 2009


Author: jyasskin
Date: Tue Oct 27 15:30:28 2009
New Revision: 85295

URL: http://llvm.org/viewvc/llvm-project?rev=85295&view=rev
Log:
Change the JIT to compile eagerly by default as agreed in
http://llvm.org/PR5184, and beef up the comments to describe what both options
do and the risks of lazy compilation in the presence of threads.

Modified:
    llvm/trunk/docs/tutorial/LangImpl4.html
    llvm/trunk/docs/tutorial/OCamlLangImpl4.html
    llvm/trunk/include/llvm/ExecutionEngine/ExecutionEngine.h
    llvm/trunk/lib/ExecutionEngine/ExecutionEngine.cpp
    llvm/trunk/lib/ExecutionEngine/JIT/JIT.cpp
    llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp
    llvm/trunk/tools/lli/lli.cpp
    llvm/trunk/unittests/ExecutionEngine/JIT/JITTest.cpp

Modified: llvm/trunk/docs/tutorial/LangImpl4.html
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/tutorial/LangImpl4.html?rev=85295&r1=85294&r2=85295&view=diff

==============================================================================
--- llvm/trunk/docs/tutorial/LangImpl4.html (original)
+++ llvm/trunk/docs/tutorial/LangImpl4.html Tue Oct 27 15:30:28 2009
@@ -388,24 +388,19 @@
 </pre>
 </div>
 
-<p>This illustrates that we can now call user code, but there is something a bit subtle
-going on here.  Note that we only invoke the JIT on the anonymous functions
-that <em>call testfunc</em>, but we never invoked it on <em>testfunc
-</em>itself.</p>
-
-<p>What actually happened here is that the anonymous function was
-JIT'd when requested.  When the Kaleidoscope app calls through the function
-pointer that is returned, the anonymous function starts executing.  It ends up
-making the call to the "testfunc" function, and ends up in a stub that invokes
-the JIT, lazily, on testfunc.  Once the JIT finishes lazily compiling testfunc,
-it returns and the code re-executes the call.</p>
-
-<p>In summary, the JIT will lazily JIT code, on the fly, as it is needed.  The
-JIT provides a number of other more advanced interfaces for things like freeing
-allocated machine code, rejit'ing functions to update them, etc.  However, even
-with this simple code, we get some surprisingly powerful capabilities - check
-this out (I removed the dump of the anonymous functions, you should get the idea
-by now :) :</p>
+<p>This illustrates that we can now call user code, but there is something a bit
+subtle going on here.  Note that we only invoke the JIT on the anonymous
+functions that <em>call testfunc</em>, but we never invoked it
+on <em>testfunc</em> itself.  What actually happened here is that the JIT
+scanned for all non-JIT'd functions transitively called from the anonymous
+function and compiled all of them before returning
+from <tt>getPointerToFunction()</tt>.</p>
+
+<p>The JIT provides a number of other more advanced interfaces for things like
+freeing allocated machine code, rejit'ing functions to update them, etc.
+However, even with this simple code, we get some surprisingly powerful
+capabilities - check this out (I removed the dump of the anonymous functions,
+you should get the idea by now :) :</p>
 
 <div class="doc_code">
 <pre>
@@ -453,8 +448,8 @@
 resolved.  It allows you to establish explicit mappings between IR objects and
 addresses (useful for LLVM global variables that you want to map to static
 tables, for example), allows you to dynamically decide on the fly based on the
-function name, and even allows you to have the JIT abort itself if any lazy
-compilation is attempted.</p>
+function name, and even allows you to have the JIT compile functions lazily the
+first time they're called.</p>
 
 <p>One interesting application of this is that we can now extend the language
 by writing arbitrary C++ code to implement operations.  For example, if we add:

Modified: llvm/trunk/docs/tutorial/OCamlLangImpl4.html
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/tutorial/OCamlLangImpl4.html?rev=85295&r1=85294&r2=85295&view=diff

==============================================================================
--- llvm/trunk/docs/tutorial/OCamlLangImpl4.html (original)
+++ llvm/trunk/docs/tutorial/OCamlLangImpl4.html Tue Oct 27 15:30:28 2009
@@ -406,22 +406,17 @@
 
 <p>This illustrates that we can now call user code, but there is something a bit
 subtle going on here.  Note that we only invoke the JIT on the anonymous
-functions that <em>call testfunc</em>, but we never invoked it on <em>testfunc
-</em>itself.</p>
-
-<p>What actually happened here is that the anonymous function was JIT'd when
-requested.  When the Kaleidoscope app calls through the function pointer that is
-returned, the anonymous function starts executing.  It ends up making the call
-to the "testfunc" function, and ends up in a stub that invokes the JIT, lazily,
-on testfunc.  Once the JIT finishes lazily compiling testfunc,
-it returns and the code re-executes the call.</p>
-
-<p>In summary, the JIT will lazily JIT code, on the fly, as it is needed.  The
-JIT provides a number of other more advanced interfaces for things like freeing
-allocated machine code, rejit'ing functions to update them, etc.  However, even
-with this simple code, we get some surprisingly powerful capabilities - check
-this out (I removed the dump of the anonymous functions, you should get the idea
-by now :) :</p>
+functions that <em>call testfunc</em>, but we never invoked it
+on <em>testfunc</em> itself.  What actually happened here is that the JIT
+scanned for all non-JIT'd functions transitively called from the anonymous
+function and compiled all of them before returning
+from <tt>run_function</tt>.</p>
+
+<p>The JIT provides a number of other more advanced interfaces for things like
+freeing allocated machine code, rejit'ing functions to update them, etc.
+However, even with this simple code, we get some surprisingly powerful
+capabilities - check this out (I removed the dump of the anonymous functions,
+you should get the idea by now :) :</p>
 
 <div class="doc_code">
 <pre>
@@ -467,8 +462,8 @@
 get resolved.  It allows you to establish explicit mappings between IR objects
 and addresses (useful for LLVM global variables that you want to map to static
 tables, for example), allows you to dynamically decide on the fly based on the
-function name, and even allows you to have the JIT abort itself if any lazy
-compilation is attempted.</p>
+function name, and even allows you to have the JIT compile functions lazily the
+first time they're called.</p>
 
 <p>One interesting application of this is that we can now extend the language
 by writing arbitrary C code to implement operations.  For example, if we add:

Modified: llvm/trunk/include/llvm/ExecutionEngine/ExecutionEngine.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/ExecutionEngine.h?rev=85295&r1=85294&r2=85295&view=diff

==============================================================================
--- llvm/trunk/include/llvm/ExecutionEngine/ExecutionEngine.h (original)
+++ llvm/trunk/include/llvm/ExecutionEngine/ExecutionEngine.h Tue Oct 27 15:30:28 2009
@@ -88,7 +88,7 @@
 class ExecutionEngine {
   const TargetData *TD;
   ExecutionEngineState EEState;
-  bool LazyCompilationDisabled;
+  bool CompilingLazily;
   bool GVCompilationDisabled;
   bool SymbolSearchingDisabled;
   bool DlsymStubsEnabled;
@@ -319,13 +319,24 @@
   virtual void RegisterJITEventListener(JITEventListener *) {}
   virtual void UnregisterJITEventListener(JITEventListener *) {}
 
-  /// DisableLazyCompilation - If called, the JIT will abort if lazy compilation
-  /// is ever attempted.
-  void DisableLazyCompilation(bool Disabled = true) {
-    LazyCompilationDisabled = Disabled;
+  /// EnableLazyCompilation - When lazy compilation is off (the default), the
+  /// JIT will eagerly compile every function reachable from the argument to
+  /// getPointerToFunction.  If lazy compilation is turned on, the JIT will only
+  /// compile the one function and emit stubs to compile the rest when they're
+  /// first called.  If lazy compilation is turned off again while some lazy
+  /// stubs are still around, and one of those stubs is called, the program will
+  /// abort.
+  ///
+  /// In order to safely compile lazily in a threaded program, the user must
+  /// ensure that 1) only one thread at a time can call any particular lazy
+  /// stub, and 2) any thread modifying LLVM IR must hold the JIT's lock
+  /// (ExecutionEngine::lock) or otherwise ensure that no other thread calls a
+  /// lazy stub.  See http://llvm.org/PR5184 for details.
+  void EnableLazyCompilation(bool Enabled = true) {
+    CompilingLazily = Enabled;
   }
-  bool isLazyCompilationDisabled() const {
-    return LazyCompilationDisabled;
+  bool isCompilingLazily() const {
+    return CompilingLazily;
   }
 
   /// DisableGVCompilation - If called, the JIT will abort if it's asked to

Modified: llvm/trunk/lib/ExecutionEngine/ExecutionEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/ExecutionEngine.cpp?rev=85295&r1=85294&r2=85295&view=diff

==============================================================================
--- llvm/trunk/lib/ExecutionEngine/ExecutionEngine.cpp (original)
+++ llvm/trunk/lib/ExecutionEngine/ExecutionEngine.cpp Tue Oct 27 15:30:28 2009
@@ -49,7 +49,7 @@
 ExecutionEngine::ExecutionEngine(ModuleProvider *P)
   : EEState(*this),
     LazyFunctionCreator(0) {
-  LazyCompilationDisabled = false;
+  CompilingLazily         = false;
   GVCompilationDisabled   = false;
   SymbolSearchingDisabled = false;
   DlsymStubsEnabled       = false;

Modified: llvm/trunk/lib/ExecutionEngine/JIT/JIT.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/JIT/JIT.cpp?rev=85295&r1=85294&r2=85295&view=diff

==============================================================================
--- llvm/trunk/lib/ExecutionEngine/JIT/JIT.cpp (original)
+++ llvm/trunk/lib/ExecutionEngine/JIT/JIT.cpp Tue Oct 27 15:30:28 2009
@@ -599,7 +599,7 @@
   isAlreadyCodeGenerating = false;
 
   // If the function referred to another function that had not yet been
-  // read from bitcode, but we are jitting non-lazily, emit it now.
+  // read from bitcode, and we are jitting non-lazily, emit it now.
   while (!jitstate->getPendingFunctions(locked).empty()) {
     Function *PF = jitstate->getPendingFunctions(locked).back();
     jitstate->getPendingFunctions(locked).pop_back();
@@ -616,7 +616,7 @@
   
   // If the JIT is configured to emit info so that dlsym can be used to
   // rewrite stubs to external globals, do so now.
-  if (areDlsymStubsEnabled() && isLazyCompilationDisabled())
+  if (areDlsymStubsEnabled() && !isCompilingLazily())
     updateDlsymStubTable();
 }
 

Modified: llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp?rev=85295&r1=85294&r2=85295&view=diff

==============================================================================
--- llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp (original)
+++ llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp Tue Oct 27 15:30:28 2009
@@ -295,11 +295,11 @@
   void *&Stub = state.getFunctionToStubMap(locked)[F];
   if (Stub) return Stub;
 
-  // Call the lazy resolver function unless we are JIT'ing non-lazily, in which
-  // case we must resolve the symbol now.
-  void *Actual = TheJIT->isLazyCompilationDisabled()
-    ? (void *)0 : (void *)(intptr_t)LazyResolverFn;
-  
+  // Call the lazy resolver function if we are JIT'ing lazily.  Otherwise we
+  // must resolve the symbol now.
+  void *Actual = TheJIT->isCompilingLazily()
+    ? (void *)(intptr_t)LazyResolverFn : (void *)0;
+
   // If this is an external declaration, attempt to resolve the address now
   // to place in the stub.
   if (F->isDeclaration() && !F->hasNotBeenReadFromBitcode()) {
@@ -334,7 +334,7 @@
   // If we are JIT'ing non-lazily but need to call a function that does not
   // exist yet, add it to the JIT's work list so that we can fill in the stub
   // address later.
-  if (!Actual && TheJIT->isLazyCompilationDisabled())
+  if (!Actual && !TheJIT->isCompilingLazily())
     if (!F->isDeclaration() || F->hasNotBeenReadFromBitcode())
       TheJIT->addPendingFunction(F);
 
@@ -471,7 +471,7 @@
     // Otherwise we don't have it, do lazy compilation now.
     
     // If lazy compilation is disabled, emit a useful error message and abort.
-    if (TheJIT->isLazyCompilationDisabled()) {
+    if (!TheJIT->isCompilingLazily()) {
       llvm_report_error("LLVM JIT requested to do lazy compilation of function '"
                         + F->getName() + "' when lazy compiles are disabled!");
     }
@@ -769,7 +769,7 @@
   // mechanism is capable of rewriting the instruction directly, prefer to do
   // that instead of emitting a stub.  This uses the lazy resolver, so is not
   // legal if lazy compilation is disabled.
-  if (DoesntNeedStub && !TheJIT->isLazyCompilationDisabled())
+  if (DoesntNeedStub && TheJIT->isCompilingLazily())
     return Resolver.AddCallbackAtLocation(F, Reference);
 
   // Otherwise, we have to emit a stub.

Modified: llvm/trunk/tools/lli/lli.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lli/lli.cpp?rev=85295&r1=85294&r2=85295&view=diff

==============================================================================
--- llvm/trunk/tools/lli/lli.cpp (original)
+++ llvm/trunk/tools/lli/lli.cpp Tue Oct 27 15:30:28 2009
@@ -165,8 +165,7 @@
 
   EE->RegisterJITEventListener(createOProfileJITEventListener());
 
-  if (NoLazyCompilation)
-    EE->DisableLazyCompilation();
+  EE->EnableLazyCompilation(!NoLazyCompilation);
 
   // If the user specifically requested an argv[0] to pass into the program,
   // do it now.

Modified: llvm/trunk/unittests/ExecutionEngine/JIT/JITTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ExecutionEngine/JIT/JITTest.cpp?rev=85295&r1=85294&r2=85295&view=diff

==============================================================================
--- llvm/trunk/unittests/ExecutionEngine/JIT/JITTest.cpp (original)
+++ llvm/trunk/unittests/ExecutionEngine/JIT/JITTest.cpp Tue Oct 27 15:30:28 2009
@@ -304,7 +304,7 @@
   Builder.CreateRet(result);
 
   TheJIT->EnableDlsymStubs(false);
-  TheJIT->DisableLazyCompilation();
+  TheJIT->EnableLazyCompilation(false);
   int (*TestFunctionPtr)() = reinterpret_cast<int(*)()>(
       (intptr_t)TheJIT->getPointerToFunction(TestFunction));
   // This used to crash in trying to call PlusOne().
@@ -314,7 +314,7 @@
 #if !defined(__arm__) && !defined(__powerpc__) && !defined(__ppc__)
 // Test a function C which calls A and B which call each other.
 TEST_F(JITTest, NonLazyCompilationStillNeedsStubs) {
-  TheJIT->DisableLazyCompilation();
+  TheJIT->EnableLazyCompilation(false);
 
   const FunctionType *Func1Ty =
       cast<FunctionType>(TypeBuilder<void(void), false>::get(Context));
@@ -370,7 +370,7 @@
 // Regression test for PR5162.  This used to trigger an AssertingVH inside the
 // JIT's Function to stub mapping.
 TEST_F(JITTest, NonLazyLeaksNoStubs) {
-  TheJIT->DisableLazyCompilation();
+  TheJIT->EnableLazyCompilation(false);
 
   // Create two functions with a single basic block each.
   const FunctionType *FuncTy =





More information about the llvm-commits mailing list