Skip to content

Commit

Permalink
Stackmaps are used for OSR exits, which is a custom kind of unwinding…
Browse files Browse the repository at this point in the history
…. 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.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@201826 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
Filip Pizlo committed Feb 20, 2014
1 parent 0aabe66 commit 23ffb3e
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 2 deletions.
3 changes: 2 additions & 1 deletion include/llvm/IR/Intrinsics.td
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions unittests/ExecutionEngine/MCJIT/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ set(LLVM_LINK_COMPONENTS
Analysis
Core
ExecutionEngine
IPO
JIT
MCJIT
ScalarOpts
Expand Down
90 changes: 90 additions & 0 deletions unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -26,6 +27,7 @@
using namespace llvm;

static bool didCallAllocateCodeSection;
static bool didAllocateCompactUnwindSection;

static uint8_t *roundTripAllocateCodeSection(void *object, uintptr_t size,
unsigned alignment,
Expand All @@ -41,6 +43,8 @@ static uint8_t *roundTripAllocateDataSection(void *object, uintptr_t size,
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);
}
Expand Down Expand Up @@ -135,6 +139,7 @@ class MCJITCAPITest : public testing::Test, public MCJITTestAPICommon {

virtual void SetUp() {
didCallAllocateCodeSection = false;
didAllocateCompactUnwindSection = false;
Module = 0;
Function = 0;
Engine = 0;
Expand Down Expand Up @@ -168,6 +173,36 @@ class MCJITCAPITest : public testing::Test, public MCJITTestAPICommon {
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");

Expand Down Expand Up @@ -248,6 +283,38 @@ class MCJITCAPITest : public testing::Test, public MCJITTestAPICommon {
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;
Expand Down Expand Up @@ -293,6 +360,29 @@ TEST_F(MCJITCAPITest, custom_memory_manager) {
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;

Expand Down
2 changes: 1 addition & 1 deletion unittests/ExecutionEngine/MCJIT/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions utils/TableGen/IntrinsicEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,7 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) {
OS << " }\n";
} else {
OS << " return AttributeSet();\n";
OS << " }\n";
}
}

Expand Down

0 comments on commit 23ffb3e

Please sign in to comment.