[llvm] r201826 - Stackmaps are used for OSR exits, which is a custom kind of unwinding. Hence, they

Filip Pizlo fpizlo at apple.com
Thu Feb 20 15:57:32 PST 2014


Author: fpizlo
Date: Thu Feb 20 17:57:31 2014
New Revision: 201826

URL: http://llvm.org/viewvc/llvm-project?rev=201826&view=rev
Log:
Stackmaps are used for OSR exits, which is a custom kind of unwinding. Hence, they 
should not be marked nounwind.

Marking them nounwind caused crashes in the WebKit FTL JIT, because if we enable 
sufficient optimizations, LLVM starts eliding compact_unwind sections (or any unwind 
data for that matter), making deoptimization via stackmaps impossible.

This changes the stackmap intrinsic to be may-throw, adds a test for exactly the 
sympton that WebKit saw, and fixes TableGen to handle un-attributed intrinsics.

Thanks to atrick and philipreames for reviewing this.


Modified:
    llvm/trunk/include/llvm/IR/Intrinsics.td
    llvm/trunk/unittests/ExecutionEngine/MCJIT/CMakeLists.txt
    llvm/trunk/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp
    llvm/trunk/unittests/ExecutionEngine/MCJIT/Makefile
    llvm/trunk/utils/TableGen/IntrinsicEmitter.cpp

Modified: llvm/trunk/include/llvm/IR/Intrinsics.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Intrinsics.td?rev=201826&r1=201825&r2=201826&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Intrinsics.td (original)
+++ llvm/trunk/include/llvm/IR/Intrinsics.td Thu Feb 20 17:57:31 2014
@@ -458,7 +458,8 @@ def int_invariant_end   : Intrinsic<[],
 //===------------------------ Stackmap Intrinsics -------------------------===//
 //
 def int_experimental_stackmap : Intrinsic<[],
-                                  [llvm_i64_ty, llvm_i32_ty, llvm_vararg_ty]>;
+                                  [llvm_i64_ty, llvm_i32_ty, llvm_vararg_ty],
+                                  [Throws]>;
 def int_experimental_patchpoint_void : Intrinsic<[],
                                                  [llvm_i64_ty, llvm_i32_ty,
                                                   llvm_ptr_ty, llvm_i32_ty,

Modified: llvm/trunk/unittests/ExecutionEngine/MCJIT/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ExecutionEngine/MCJIT/CMakeLists.txt?rev=201826&r1=201825&r2=201826&view=diff
==============================================================================
--- llvm/trunk/unittests/ExecutionEngine/MCJIT/CMakeLists.txt (original)
+++ llvm/trunk/unittests/ExecutionEngine/MCJIT/CMakeLists.txt Thu Feb 20 17:57:31 2014
@@ -2,6 +2,7 @@ set(LLVM_LINK_COMPONENTS
   Analysis
   Core
   ExecutionEngine
+  IPO
   JIT
   MCJIT
   ScalarOpts

Modified: llvm/trunk/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp?rev=201826&r1=201825&r2=201826&view=diff
==============================================================================
--- llvm/trunk/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp (original)
+++ llvm/trunk/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp Thu Feb 20 17:57:31 2014
@@ -18,6 +18,7 @@
 #include "llvm-c/ExecutionEngine.h"
 #include "llvm-c/Target.h"
 #include "llvm-c/Transforms/Scalar.h"
+#include "llvm-c/Transforms/PassManagerBuilder.h"
 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
 #include "llvm/Support/Host.h"
 #include "gtest/gtest.h"
@@ -26,6 +27,7 @@
 using namespace llvm;
 
 static bool didCallAllocateCodeSection;
+static bool didAllocateCompactUnwindSection;
 
 static uint8_t *roundTripAllocateCodeSection(void *object, uintptr_t size,
                                              unsigned alignment,
@@ -41,6 +43,8 @@ static uint8_t *roundTripAllocateDataSec
                                              unsigned sectionID,
                                              const char *sectionName,
                                              LLVMBool isReadOnly) {
+  if (!strcmp(sectionName, "__compact_unwind"))
+    didAllocateCompactUnwindSection = true;
   return static_cast<SectionMemoryManager*>(object)->allocateDataSection(
     size, alignment, sectionID, sectionName, isReadOnly);
 }
@@ -135,6 +139,7 @@ protected:
   
   virtual void SetUp() {
     didCallAllocateCodeSection = false;
+    didAllocateCompactUnwindSection = false;
     Module = 0;
     Function = 0;
     Engine = 0;
@@ -168,6 +173,36 @@ protected:
     LLVMDisposeBuilder(builder);
   }
   
+  void buildFunctionThatUsesStackmap() {
+    Module = LLVMModuleCreateWithName("simple_module");
+    
+    LLVMSetTarget(Module, HostTriple.c_str());
+    
+    LLVMTypeRef stackmapParamTypes[] = { LLVMInt64Type(), LLVMInt32Type() };
+    LLVMValueRef stackmap = LLVMAddFunction(
+      Module, "llvm.experimental.stackmap",
+      LLVMFunctionType(LLVMVoidType(), stackmapParamTypes, 2, 1));
+    LLVMSetLinkage(stackmap, LLVMExternalLinkage);
+    
+    Function = LLVMAddFunction(
+      Module, "simple_function", LLVMFunctionType(LLVMInt32Type(), 0, 0, 0));
+    
+    LLVMBasicBlockRef entry = LLVMAppendBasicBlock(Function, "entry");
+    LLVMBuilderRef builder = LLVMCreateBuilder();
+    LLVMPositionBuilderAtEnd(builder, entry);
+    LLVMValueRef stackmapArgs[] = {
+      LLVMConstInt(LLVMInt64Type(), 0, 0), LLVMConstInt(LLVMInt32Type(), 5, 0),
+      LLVMConstInt(LLVMInt32Type(), 42, 0)
+    };
+    LLVMBuildCall(builder, stackmap, stackmapArgs, 3, "");
+    LLVMBuildRet(builder, LLVMConstInt(LLVMInt32Type(), 42, 0));
+    
+    LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error);
+    LLVMDisposeMessage(Error);
+    
+    LLVMDisposeBuilder(builder);
+  }
+  
   void buildModuleWithCodeAndData() {
     Module = LLVMModuleCreateWithName("simple_module");
     
@@ -248,6 +283,38 @@ protected:
     LLVMDisposePassManager(pass);
   }
   
+  void buildAndRunOptPasses() {
+    LLVMPassManagerBuilderRef passBuilder;
+    
+    passBuilder = LLVMPassManagerBuilderCreate();
+    LLVMPassManagerBuilderSetOptLevel(passBuilder, 2);
+    LLVMPassManagerBuilderSetSizeLevel(passBuilder, 0);
+    
+    LLVMPassManagerRef functionPasses =
+      LLVMCreateFunctionPassManagerForModule(Module);
+    LLVMPassManagerRef modulePasses =
+      LLVMCreatePassManager();
+    
+    LLVMAddTargetData(LLVMGetExecutionEngineTargetData(Engine), modulePasses);
+    
+    LLVMPassManagerBuilderPopulateFunctionPassManager(passBuilder,
+                                                      functionPasses);
+    LLVMPassManagerBuilderPopulateModulePassManager(passBuilder, modulePasses);
+    
+    LLVMPassManagerBuilderDispose(passBuilder);
+    
+    LLVMInitializeFunctionPassManager(functionPasses);
+    for (LLVMValueRef value = LLVMGetFirstFunction(Module);
+         value; value = LLVMGetNextFunction(value))
+      LLVMRunFunctionPassManager(functionPasses, value);
+    LLVMFinalizeFunctionPassManager(functionPasses);
+    
+    LLVMRunPassManager(modulePasses, Module);
+    
+    LLVMDisposePassManager(functionPasses);
+    LLVMDisposePassManager(modulePasses);
+  }
+  
   LLVMModuleRef Module;
   LLVMValueRef Function;
   LLVMValueRef Function2;
@@ -293,6 +360,29 @@ TEST_F(MCJITCAPITest, custom_memory_mana
   EXPECT_TRUE(didCallAllocateCodeSection);
 }
 
+TEST_F(MCJITCAPITest, stackmap_creates_compact_unwind_on_darwin) {
+  SKIP_UNSUPPORTED_PLATFORM;
+  
+  buildFunctionThatUsesStackmap();
+  buildMCJITOptions();
+  useRoundTripSectionMemoryManager();
+  buildMCJITEngine();
+  buildAndRunOptPasses();
+  
+  union {
+    void *raw;
+    int (*usable)();
+  } functionPointer;
+  functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function);
+  
+  EXPECT_EQ(42, functionPointer.usable());
+  EXPECT_TRUE(didCallAllocateCodeSection);
+  
+  EXPECT_TRUE(
+    Triple(HostTriple).getOS() != Triple::Darwin ||
+    didAllocateCompactUnwindSection);
+}
+
 TEST_F(MCJITCAPITest, reserve_allocation_space) {
   SKIP_UNSUPPORTED_PLATFORM;
   

Modified: llvm/trunk/unittests/ExecutionEngine/MCJIT/Makefile
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ExecutionEngine/MCJIT/Makefile?rev=201826&r1=201825&r2=201826&view=diff
==============================================================================
--- llvm/trunk/unittests/ExecutionEngine/MCJIT/Makefile (original)
+++ llvm/trunk/unittests/ExecutionEngine/MCJIT/Makefile Thu Feb 20 17:57:31 2014
@@ -9,7 +9,7 @@
 
 LEVEL = ../../..
 TESTNAME = MCJIT
-LINK_COMPONENTS := core jit mcjit native support
+LINK_COMPONENTS := core ipo jit mcjit native support
 
 include $(LEVEL)/Makefile.config
 include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest

Modified: llvm/trunk/utils/TableGen/IntrinsicEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/IntrinsicEmitter.cpp?rev=201826&r1=201825&r2=201826&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/IntrinsicEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/IntrinsicEmitter.cpp Thu Feb 20 17:57:31 2014
@@ -666,6 +666,7 @@ EmitAttributes(const std::vector<CodeGen
       OS << "      }\n";
     } else {
       OS << "      return AttributeSet();\n";
+      OS << "      }\n";
     }
   }
 





More information about the llvm-commits mailing list