aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2003-05-08 21:34:11 +0000
committerChris Lattner <sabre@nondot.org>2003-05-08 21:34:11 +0000
commitc309a7627ce8849b63f6f297ca319d582f4ae066 (patch)
tree01fc11fdf36bc55d685ea4f10a71004397263626
parent66a8494e98a36e2639fa60ab31364290652fe396 (diff)
Improve efficiency of JIT by having it use direct function calls instead of
signals to regain control from the executing code git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@6051 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/ExecutionEngine/JIT/Callback.cpp55
-rw-r--r--lib/ExecutionEngine/JIT/JIT.h5
-rw-r--r--lib/ExecutionEngine/JIT/JITEmitter.cpp5
-rw-r--r--lib/ExecutionEngine/JIT/VM.h5
4 files changed, 34 insertions, 36 deletions
diff --git a/lib/ExecutionEngine/JIT/Callback.cpp b/lib/ExecutionEngine/JIT/Callback.cpp
index 3b40e2ebe1..75abf435e6 100644
--- a/lib/ExecutionEngine/JIT/Callback.cpp
+++ b/lib/ExecutionEngine/JIT/Callback.cpp
@@ -7,63 +7,48 @@
#include "VM.h"
#include "Support/Statistic.h"
-#include <signal.h>
-#include <ucontext.h>
#include <iostream>
static VM *TheVM = 0;
-static void TrapHandler(int TN, siginfo_t *SI, ucontext_t *ucp) {
- assert(TN == SIGSEGV && "Should be SIGSEGV!");
+// CompilationCallback - Invoked the first time that a call site is found,
+// which causes lazy compilation of the target function.
+//
+void VM::CompilationCallback() {
+#if defined(i386) || defined(__i386__) || defined(__x86__)
+ unsigned *StackPtr = (unsigned*)__builtin_frame_address(0);
+ unsigned RetAddr = (unsigned)__builtin_return_address(0);
-#ifdef REG_EIP /* this code does not compile on Sparc! */
- if (SI->si_code != SEGV_MAPERR || SI->si_addr != 0 ||
- ucp->uc_mcontext.gregs[REG_EIP] != 0) {
- std::cerr << "Bad SEGV encountered EIP = 0x" << std::hex
- << ucp->uc_mcontext.gregs[REG_EIP] << " addr = "
- << SI->si_addr << "!\n";
-
- struct sigaction SA; // Restore old SEGV handler...
- SA.sa_handler = SIG_DFL;
- SA.sa_flags = SA_NOMASK;
- sigaction(SIGSEGV, &SA, 0);
- return; // Should core dump now...
- }
+ assert(StackPtr[1] == RetAddr &&
+ "Could not find return address on the stack!");
// The call instruction should have pushed the return value onto the stack...
- unsigned RefAddr = *(unsigned*)ucp->uc_mcontext.gregs[REG_ESP];
- RefAddr -= 4; // Backtrack to the reference itself...
+ RetAddr -= 4; // Backtrack to the reference itself...
- DEBUG(std::cerr << "In SEGV handler! Addr=0x" << std::hex << RefAddr
- << " ESP=0x" << ucp->uc_mcontext.gregs[REG_ESP] << std::dec
+ DEBUG(std::cerr << "In callback! Addr=0x" << std::hex << RetAddr
+ << " ESP=0x" << (unsigned)StackPtr << std::dec
<< ": Resolving call to function: "
- << TheVM->getFunctionReferencedName((void*)RefAddr) << "\n");
+ << TheVM->getFunctionReferencedName((void*)RetAddr) << "\n");
// Sanity check to make sure this really is a call instruction...
- assert(((unsigned char*)RefAddr)[-1] == 0xE8 && "Not a call instr!");
+ assert(((unsigned char*)RetAddr)[-1] == 0xE8 && "Not a call instr!");
- unsigned NewVal = (unsigned)TheVM->resolveFunctionReference((void*)RefAddr);
+ unsigned NewVal = (unsigned)TheVM->resolveFunctionReference((void*)RetAddr);
// Rewrite the call target... so that we don't fault every time we execute
// the call.
- *(unsigned*)RefAddr = NewVal-RefAddr-4;
-
- // Change the instruction pointer to be the real target of the call...
- ucp->uc_mcontext.gregs[REG_EIP] = NewVal;
+ *(unsigned*)RetAddr = NewVal-RetAddr-4;
+ // Change the return address to reexecute the call instruction...
+ StackPtr[1] -= 5;
+#else
+ abort();
#endif
}
void VM::registerCallback() {
TheVM = this;
-
- // Register the signal handler...
- struct sigaction SA;
- SA.sa_sigaction = (void (*)(int, siginfo_t*, void*))TrapHandler;
- sigfillset(&SA.sa_mask); // Block all signals while codegen'ing
- SA.sa_flags = SA_NOCLDSTOP|SA_SIGINFO; // Get siginfo
- sigaction(SIGSEGV, &SA, 0); // Install the handler
}
diff --git a/lib/ExecutionEngine/JIT/JIT.h b/lib/ExecutionEngine/JIT/JIT.h
index 3b267ed877..9080b3be04 100644
--- a/lib/ExecutionEngine/JIT/JIT.h
+++ b/lib/ExecutionEngine/JIT/JIT.h
@@ -50,10 +50,15 @@ public:
///
void *getPointerToNamedFunction(const std::string &Name);
+ // CompilationCallback - Invoked the first time that a call site is found,
+ // which causes lazy compilation of the target function.
+ //
+ static void CompilationCallback();
private:
static MachineCodeEmitter *createEmitter(VM &V);
void setupPassManager();
void *getPointerToFunction(const Function *F);
+
void registerCallback();
};
diff --git a/lib/ExecutionEngine/JIT/JITEmitter.cpp b/lib/ExecutionEngine/JIT/JITEmitter.cpp
index 1c89bdba26..d6f75c08f7 100644
--- a/lib/ExecutionEngine/JIT/JITEmitter.cpp
+++ b/lib/ExecutionEngine/JIT/JITEmitter.cpp
@@ -131,8 +131,11 @@ void Emitter::emitAddress(void *Addr, bool isPCRelative) {
void Emitter::emitGlobalAddress(GlobalValue *V, bool isPCRelative) {
if (isPCRelative) { // must be a call, this is a major hack!
+ // FIXME: Try looking up the function to see if it is already compiled!
TheVM.addFunctionRef(CurByte, cast<Function>(V));
- emitAddress(0, isPCRelative); // Delayed resolution...
+
+ // Delayed resolution...
+ emitAddress((void*)VM::CompilationCallback, isPCRelative);
} else {
emitAddress(TheVM.getPointerToGlobal(V), isPCRelative);
}
diff --git a/lib/ExecutionEngine/JIT/VM.h b/lib/ExecutionEngine/JIT/VM.h
index 3b267ed877..9080b3be04 100644
--- a/lib/ExecutionEngine/JIT/VM.h
+++ b/lib/ExecutionEngine/JIT/VM.h
@@ -50,10 +50,15 @@ public:
///
void *getPointerToNamedFunction(const std::string &Name);
+ // CompilationCallback - Invoked the first time that a call site is found,
+ // which causes lazy compilation of the target function.
+ //
+ static void CompilationCallback();
private:
static MachineCodeEmitter *createEmitter(VM &V);
void setupPassManager();
void *getPointerToFunction(const Function *F);
+
void registerCallback();
};