[llvm-branch-commits] [llvm-branch] r96835 - in /llvm/branches/Apple/Hermes: include/llvm/ExecutionEngine/ExecutionEngine.h include/llvm/ExecutionEngine/JITMemoryManager.h lib/ExecutionEngine/ExecutionEngine.cpp lib/ExecutionEngine/JIT/JIT.cpp lib/ExecutionEngine/JIT/JIT.h lib/ExecutionEngine/JIT/JITEmitter.cpp lib/ExecutionEngine/JIT/JITMemoryManager.cpp unittests/ExecutionEngine/JIT/JITTest.cpp
Evan Cheng
evan.cheng at apple.com
Mon Feb 22 16:09:35 PST 2010
Author: evancheng
Date: Mon Feb 22 18:09:35 2010
New Revision: 96835
URL: http://llvm.org/viewvc/llvm-project?rev=96835&view=rev
Log:
Revert 86606 from Hermes to bring dlsym capability back.
Modified:
llvm/branches/Apple/Hermes/include/llvm/ExecutionEngine/ExecutionEngine.h
llvm/branches/Apple/Hermes/include/llvm/ExecutionEngine/JITMemoryManager.h
llvm/branches/Apple/Hermes/lib/ExecutionEngine/ExecutionEngine.cpp
llvm/branches/Apple/Hermes/lib/ExecutionEngine/JIT/JIT.cpp
llvm/branches/Apple/Hermes/lib/ExecutionEngine/JIT/JIT.h
llvm/branches/Apple/Hermes/lib/ExecutionEngine/JIT/JITEmitter.cpp
llvm/branches/Apple/Hermes/lib/ExecutionEngine/JIT/JITMemoryManager.cpp
llvm/branches/Apple/Hermes/unittests/ExecutionEngine/JIT/JITTest.cpp
Modified: llvm/branches/Apple/Hermes/include/llvm/ExecutionEngine/ExecutionEngine.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Hermes/include/llvm/ExecutionEngine/ExecutionEngine.h?rev=96835&r1=96834&r2=96835&view=diff
==============================================================================
--- llvm/branches/Apple/Hermes/include/llvm/ExecutionEngine/ExecutionEngine.h (original)
+++ llvm/branches/Apple/Hermes/include/llvm/ExecutionEngine/ExecutionEngine.h Mon Feb 22 18:09:35 2010
@@ -92,6 +92,7 @@
bool CompilingLazily;
bool GVCompilationDisabled;
bool SymbolSearchingDisabled;
+ bool DlsymStubsEnabled;
friend class EngineBuilder; // To allow access to JITCtor and InterpCtor.
@@ -373,7 +374,15 @@
bool isSymbolSearchingDisabled() const {
return SymbolSearchingDisabled;
}
-
+
+ /// EnableDlsymStubs -
+ void EnableDlsymStubs(bool Enabled = true) {
+ DlsymStubsEnabled = Enabled;
+ }
+ bool areDlsymStubsEnabled() const {
+ return DlsymStubsEnabled;
+ }
+
/// InstallLazyFunctionCreator - If an unknown function is needed, the
/// specified function pointer is invoked to create it. If it returns null,
/// the JIT will abort.
Modified: llvm/branches/Apple/Hermes/include/llvm/ExecutionEngine/JITMemoryManager.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Hermes/include/llvm/ExecutionEngine/JITMemoryManager.h?rev=96835&r1=96834&r2=96835&view=diff
==============================================================================
--- llvm/branches/Apple/Hermes/include/llvm/ExecutionEngine/JITMemoryManager.h (original)
+++ llvm/branches/Apple/Hermes/include/llvm/ExecutionEngine/JITMemoryManager.h Mon Feb 22 18:09:35 2010
@@ -71,6 +71,17 @@
/// return a pointer to its base.
virtual uint8_t *getGOTBase() const = 0;
+ /// SetDlsymTable - If the JIT must be able to relocate stubs after they have
+ /// been emitted, potentially because they are being copied to a process
+ /// where external symbols live at different addresses than in the JITing
+ /// process, allocate a table with sufficient information to do so.
+ virtual void SetDlsymTable(void *ptr) = 0;
+
+ /// getDlsymTable - If this is managing a table of entries so that stubs to
+ /// external symbols can be later relocated, this method should return a
+ /// pointer to it.
+ virtual void *getDlsymTable() const = 0;
+
/// NeedsExactSize - If the memory manager requires to know the size of the
/// objects to be emitted
bool NeedsExactSize() const {
Modified: llvm/branches/Apple/Hermes/lib/ExecutionEngine/ExecutionEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Hermes/lib/ExecutionEngine/ExecutionEngine.cpp?rev=96835&r1=96834&r2=96835&view=diff
==============================================================================
--- llvm/branches/Apple/Hermes/lib/ExecutionEngine/ExecutionEngine.cpp (original)
+++ llvm/branches/Apple/Hermes/lib/ExecutionEngine/ExecutionEngine.cpp Mon Feb 22 18:09:35 2010
@@ -56,6 +56,7 @@
CompilingLazily = false;
GVCompilationDisabled = false;
SymbolSearchingDisabled = false;
+ DlsymStubsEnabled = false;
Modules.push_back(M);
assert(M && "Module is null?");
}
Modified: llvm/branches/Apple/Hermes/lib/ExecutionEngine/JIT/JIT.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Hermes/lib/ExecutionEngine/JIT/JIT.cpp?rev=96835&r1=96834&r2=96835&view=diff
==============================================================================
--- llvm/branches/Apple/Hermes/lib/ExecutionEngine/JIT/JIT.cpp (original)
+++ llvm/branches/Apple/Hermes/lib/ExecutionEngine/JIT/JIT.cpp Mon Feb 22 18:09:35 2010
@@ -606,6 +606,11 @@
// the stub with real address of the function.
updateFunctionStub(PF);
}
+
+ // 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() && !isCompilingLazily())
+ updateDlsymStubTable();
}
/// getPointerToFunction - This method is used to get the address of the
@@ -631,7 +636,8 @@
return Addr;
if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
- bool AbortOnFailure = !F->hasExternalWeakLinkage();
+ bool AbortOnFailure =
+ !areDlsymStubsEnabled() && !F->hasExternalWeakLinkage();
void *Addr = getPointerToNamedFunction(F->getName(), AbortOnFailure);
addGlobalMapping(F, Addr);
return Addr;
@@ -660,7 +666,7 @@
return (void*)&__dso_handle;
#endif
Ptr = sys::DynamicLibrary::SearchForAddressOfSymbol(GV->getName());
- if (Ptr == 0) {
+ if (Ptr == 0 && !areDlsymStubsEnabled()) {
llvm_report_error("Could not resolve external global address: "
+GV->getName());
}
Modified: llvm/branches/Apple/Hermes/lib/ExecutionEngine/JIT/JIT.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Hermes/lib/ExecutionEngine/JIT/JIT.h?rev=96835&r1=96834&r2=96835&view=diff
==============================================================================
--- llvm/branches/Apple/Hermes/lib/ExecutionEngine/JIT/JIT.h (original)
+++ llvm/branches/Apple/Hermes/lib/ExecutionEngine/JIT/JIT.h Mon Feb 22 18:09:35 2010
@@ -198,6 +198,7 @@
TargetMachine &tm);
void runJITOnFunctionUnlocked(Function *F, const MutexGuard &locked);
void updateFunctionStub(Function *F);
+ void updateDlsymStubTable();
protected:
Modified: llvm/branches/Apple/Hermes/lib/ExecutionEngine/JIT/JITEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Hermes/lib/ExecutionEngine/JIT/JITEmitter.cpp?rev=96835&r1=96834&r2=96835&view=diff
==============================================================================
--- llvm/branches/Apple/Hermes/lib/ExecutionEngine/JIT/JITEmitter.cpp (original)
+++ llvm/branches/Apple/Hermes/lib/ExecutionEngine/JIT/JITEmitter.cpp Mon Feb 22 18:09:35 2010
@@ -369,6 +369,10 @@
// the stub is unused.
DenseMap<void *, SmallPtrSet<const Function*, 1> > StubFnRefs;
+ // ExtFnStubs - A map of external function names to stubs which have entries
+ // in the JITResolver's ExternalFnToStubMap.
+ StringMap<void *> ExtFnStubs;
+
DILocation PrevDLT;
public:
@@ -410,7 +414,7 @@
void startGVStub(const GlobalValue* GV,
unsigned StubSize, unsigned Alignment = 1);
void startGVStub(void *Buffer, unsigned StubSize);
- void finishGVStub();
+ void *finishGVStub();
virtual void *allocIndirectGV(const GlobalValue *GV,
const uint8_t *Buffer, size_t Size,
unsigned Alignment);
@@ -459,6 +463,10 @@
/// deallocateMemForFunction to also remove stubs no longer referenced.
void AddStubToCurrentFunction(void *Stub);
+ /// getExternalFnStubs - Accessor for the JIT to find stubs emitted for
+ /// MachineRelocations that reference external functions by name.
+ const StringMap<void*> &getExternalFnStubs() const { return ExtFnStubs; }
+
virtual void processDebugLoc(DebugLoc DL, bool BeforePrintingInsn);
virtual void emitLabel(uint64_t LabelID) {
@@ -530,8 +538,10 @@
Actual = TheJIT->getPointerToFunction(F);
// If we resolved the symbol to a null address (eg. a weak external)
- // don't emit a stub. Return a null pointer to the application.
- if (!Actual) return 0;
+ // don't emit a stub. Return a null pointer to the application. If dlsym
+ // stubs are enabled, not being able to resolve the address is not
+ // meaningful.
+ if (!Actual && !TheJIT->areDlsymStubsEnabled()) return 0;
}
TargetJITInfo::StubLayout SL = TheJIT->getJITInfo().getStubLayout();
@@ -763,8 +773,10 @@
if (ResultPtr) return ResultPtr;
// If this is an external function pointer, we can force the JIT to
- // 'compile' it, which really just adds it to the map.
- if (isNonGhostDeclaration(F) || F->hasAvailableExternallyLinkage())
+ // 'compile' it, which really just adds it to the map. In dlsym mode,
+ // external functions are forced through a stub, regardless of reloc type.
+ if (isNonGhostDeclaration(F) || F->hasAvailableExternallyLinkage() &&
+ !TheJIT->areDlsymStubsEnabled())
return TheJIT->getPointerToFunction(F);
}
@@ -1113,7 +1125,16 @@
// If the target REALLY wants a stub for this function, emit it now.
if (MR.mayNeedFarStub()) {
- ResultPtr = Resolver.getExternalFunctionStub(ResultPtr);
+ if (!TheJIT->areDlsymStubsEnabled()) {
+ ResultPtr = Resolver.getExternalFunctionStub(ResultPtr);
+ } else {
+ void *&Stub = ExtFnStubs[MR.getExternalSymbol()];
+ if (!Stub) {
+ Stub = Resolver.getExternalFunctionStub((void *)&Stub);
+ AddStubToCurrentFunction(Stub);
+ }
+ ResultPtr = Stub;
+ }
}
} else if (MR.isGlobalValue()) {
ResultPtr = getPointerToGlobal(MR.getGlobalValue(),
@@ -1327,10 +1348,19 @@
StubFnRefs.erase(Stub);
// Invalidate the stub. If it is a GV stub, update the JIT's global
- // mapping for that GV to zero.
+ // mapping for that GV to zero, otherwise, search the string map of
+ // external function names to stubs and remove the entry for this stub.
GlobalValue *GV = Resolver.invalidateStub(Stub);
if (GV) {
TheJIT->updateGlobalMapping(GV, 0);
+ } else {
+ for (StringMapIterator<void*> i = ExtFnStubs.begin(),
+ e = ExtFnStubs.end(); i != e; ++i) {
+ if (i->second == Stub) {
+ ExtFnStubs.erase(i);
+ break;
+ }
+ }
}
}
}
@@ -1488,12 +1518,13 @@
BufferEnd = BufferBegin+StubSize+1;
}
-void JITEmitter::finishGVStub() {
+void *JITEmitter::finishGVStub() {
assert(CurBufferPtr != BufferEnd && "Stub overflowed allocated space.");
NumBytes += getCurrentPCOffset();
- BufferBegin = SavedBufferBegin;
+ std::swap(SavedBufferBegin, BufferBegin);
BufferEnd = SavedBufferEnd;
CurBufferPtr = SavedCurBufferPtr;
+ return SavedBufferBegin;
}
void *JITEmitter::allocIndirectGV(const GlobalValue *GV,
@@ -1596,6 +1627,92 @@
JE->finishGVStub();
}
+/// updateDlsymStubTable - Emit the data necessary to relocate the stubs
+/// that were emitted during code generation.
+///
+void JIT::updateDlsymStubTable() {
+ assert(isa<JITEmitter>(JCE) && "Unexpected MCE?");
+ JITEmitter *JE = cast<JITEmitter>(getCodeEmitter());
+
+ SmallVector<GlobalValue*, 8> GVs;
+ SmallVector<void*, 8> Ptrs;
+ const StringMap<void *> &ExtFns = JE->getExternalFnStubs();
+
+ JE->getJITResolver().getRelocatableGVs(GVs, Ptrs);
+
+ unsigned nStubs = GVs.size() + ExtFns.size();
+
+ // If there are no relocatable stubs, return.
+ if (nStubs == 0)
+ return;
+
+ // If there are no new relocatable stubs, return.
+ void *CurTable = JE->getMemMgr()->getDlsymTable();
+ if (CurTable && (*(unsigned *)CurTable == nStubs))
+ return;
+
+ // Calculate the size of the stub info
+ unsigned offset = 4 + 4 * nStubs + sizeof(intptr_t) * nStubs;
+
+ SmallVector<unsigned, 8> Offsets;
+ for (unsigned i = 0; i != GVs.size(); ++i) {
+ Offsets.push_back(offset);
+ offset += GVs[i]->getName().size() + 1;
+ }
+ for (StringMapConstIterator<void*> i = ExtFns.begin(), e = ExtFns.end();
+ i != e; ++i) {
+ Offsets.push_back(offset);
+ offset += strlen(i->first()) + 1;
+ }
+
+ // Allocate space for the new "stub", which contains the dlsym table.
+ JE->startGVStub(0, offset, 4);
+
+ // Emit the number of records
+ JE->emitInt32(nStubs);
+
+ // Emit the string offsets
+ for (unsigned i = 0; i != nStubs; ++i)
+ JE->emitInt32(Offsets[i]);
+
+ // Emit the pointers. Verify that they are at least 2-byte aligned, and set
+ // the low bit to 0 == GV, 1 == Function, so that the client code doing the
+ // relocation can write the relocated pointer at the appropriate place in
+ // the stub.
+ for (unsigned i = 0; i != GVs.size(); ++i) {
+ intptr_t Ptr = (intptr_t)Ptrs[i];
+ assert((Ptr & 1) == 0 && "Stub pointers must be at least 2-byte aligned!");
+
+ if (isa<Function>(GVs[i]))
+ Ptr |= (intptr_t)1;
+
+ if (sizeof(Ptr) == 8)
+ JE->emitInt64(Ptr);
+ else
+ JE->emitInt32(Ptr);
+ }
+ for (StringMapConstIterator<void*> i = ExtFns.begin(), e = ExtFns.end();
+ i != e; ++i) {
+ intptr_t Ptr = (intptr_t)i->second | 1;
+
+ if (sizeof(Ptr) == 8)
+ JE->emitInt64(Ptr);
+ else
+ JE->emitInt32(Ptr);
+ }
+
+ // Emit the strings.
+ for (unsigned i = 0; i != GVs.size(); ++i)
+ JE->emitString(GVs[i]->getName());
+ for (StringMapConstIterator<void*> i = ExtFns.begin(), e = ExtFns.end();
+ i != e; ++i)
+ JE->emitString(i->first());
+
+ // Tell the JIT memory manager where it is. The JIT Memory Manager will
+ // deallocate space for the old one, if one existed.
+ JE->getMemMgr()->SetDlsymTable(JE->finishGVStub());
+}
+
/// freeMachineCodeForFunction - release machine code memory for given Function.
///
void JIT::freeMachineCodeForFunction(Function *F) {
Modified: llvm/branches/Apple/Hermes/lib/ExecutionEngine/JIT/JITMemoryManager.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Hermes/lib/ExecutionEngine/JIT/JITMemoryManager.cpp?rev=96835&r1=96834&r2=96835&view=diff
==============================================================================
--- llvm/branches/Apple/Hermes/lib/ExecutionEngine/JIT/JITMemoryManager.cpp (original)
+++ llvm/branches/Apple/Hermes/lib/ExecutionEngine/JIT/JITMemoryManager.cpp Mon Feb 22 18:09:35 2010
@@ -296,6 +296,7 @@
MemoryRangeHeader *CurBlock;
uint8_t *GOTBase; // Target Specific reserved memory
+ void *DlsymTable; // Stub external symbol information
public:
DefaultJITMemoryManager();
~DefaultJITMemoryManager();
@@ -317,6 +318,7 @@
static const size_t DefaultSizeThreshold;
void AllocateGOT();
+ void SetDlsymTable(void *);
// Testing methods.
virtual bool CheckInvariants(std::string &ErrorStr);
@@ -467,6 +469,10 @@
return GOTBase;
}
+ void *getDlsymTable() const {
+ return DlsymTable;
+ }
+
void deallocateBlock(void *Block) {
// Find the block that is allocated for this function.
MemoryRangeHeader *MemRange = static_cast<MemoryRangeHeader*>(Block) - 1;
@@ -593,6 +599,7 @@
FreeMemoryList = Mem0;
GOTBase = NULL;
+ DlsymTable = NULL;
}
void DefaultJITMemoryManager::AllocateGOT() {
@@ -601,6 +608,10 @@
HasGOT = true;
}
+void DefaultJITMemoryManager::SetDlsymTable(void *ptr) {
+ DlsymTable = ptr;
+}
+
DefaultJITMemoryManager::~DefaultJITMemoryManager() {
for (unsigned i = 0, e = CodeSlabs.size(); i != e; ++i)
sys::Memory::ReleaseRWX(CodeSlabs[i]);
Modified: llvm/branches/Apple/Hermes/unittests/ExecutionEngine/JIT/JITTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Hermes/unittests/ExecutionEngine/JIT/JITTest.cpp?rev=96835&r1=96834&r2=96835&view=diff
==============================================================================
--- llvm/branches/Apple/Hermes/unittests/ExecutionEngine/JIT/JITTest.cpp (original)
+++ llvm/branches/Apple/Hermes/unittests/ExecutionEngine/JIT/JITTest.cpp Mon Feb 22 18:09:35 2010
@@ -70,6 +70,8 @@
virtual void setPoisonMemory(bool poison) { Base->setPoisonMemory(poison); }
virtual void AllocateGOT() { Base->AllocateGOT(); }
virtual uint8_t *getGOTBase() const { return Base->getGOTBase(); }
+ virtual void SetDlsymTable(void *ptr) { Base->SetDlsymTable(ptr); }
+ virtual void *getDlsymTable() const { return Base->getDlsymTable(); }
struct StartFunctionBodyCall {
StartFunctionBodyCall(uint8_t *Result, const Function *F,
uintptr_t ActualSize, uintptr_t ActualSizeResult)
@@ -309,6 +311,7 @@
ConstantInt::get(TypeBuilder<int, false>::get(Context), 7));
Builder.CreateRet(result);
+ TheJIT->EnableDlsymStubs(false);
TheJIT->DisableLazyCompilation(true);
int (*TestFunctionPtr)() = reinterpret_cast<int(*)()>(
(intptr_t)TheJIT->getPointerToFunction(TestFunction));
More information about the llvm-branch-commits
mailing list