diff --git a/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp b/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp index 4cb0270d576..31cee16039f 100644 --- a/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp +++ b/lib/ExecutionEngine/IntelJITEvents/IntelJITEventListener.cpp @@ -22,6 +22,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/ExecutionEngine/ObjectImage.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Errno.h" @@ -41,6 +42,11 @@ class IntelJITEventListener : public JITEventListener { MethodIDMap MethodIDs; FilenameCache Filenames; + typedef SmallVector MethodAddressVector; + typedef DenseMap ObjectMap; + + ObjectMap LoadedObjectMap; + public: IntelJITEventListener(IntelJITEventsWrapper* libraryWrapper) { Wrapper.reset(libraryWrapper); @@ -169,9 +175,78 @@ void IntelJITEventListener::NotifyFreeingMachineCode(void *FnStart) { } void IntelJITEventListener::NotifyObjectEmitted(const ObjectImage &Obj) { + // Get the address of the object image for use as a unique identifier + const void* ObjData = Obj.getData().data(); + MethodAddressVector Functions; + + // Use symbol info to iterate functions in the object. + error_code ec; + for (object::symbol_iterator I = Obj.begin_symbols(), + E = Obj.end_symbols(); + I != E && !ec; + I.increment(ec)) { + object::SymbolRef::Type SymType; + if (I->getType(SymType)) continue; + if (SymType == object::SymbolRef::ST_Function) { + StringRef Name; + uint64_t Addr; + uint64_t Size; + if (I->getName(Name)) continue; + if (I->getAddress(Addr)) continue; + if (I->getSize(Size)) continue; + + // Record this address in a local vector + Functions.push_back((void*)Addr); + + // Build the function loaded notification message + iJIT_Method_Load FunctionMessage = FunctionDescToIntelJITFormat(*Wrapper, + Name.data(), + Addr, + Size); + + // FIXME: Try to find line info for this function in the DWARF sections. + FunctionMessage.source_file_name = 0; + FunctionMessage.line_number_size = 0; + FunctionMessage.line_number_table = 0; + + Wrapper->iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, + &FunctionMessage); + MethodIDs[(void*)Addr] = FunctionMessage.method_id; + } + } + + // To support object unload notification, we need to keep a list of + // registered function addresses for each loaded object. We will + // use the MethodIDs map to get the registered ID for each function. + LoadedObjectMap[ObjData] = Functions; } void IntelJITEventListener::NotifyFreeingObject(const ObjectImage &Obj) { + // Get the address of the object image for use as a unique identifier + const void* ObjData = Obj.getData().data(); + + // Get the object's function list from LoadedObjectMap + ObjectMap::iterator OI = LoadedObjectMap.find(ObjData); + if (OI == LoadedObjectMap.end()) + return; + MethodAddressVector& Functions = OI->second; + + // Walk the function list, unregistering each function + for (MethodAddressVector::iterator FI = Functions.begin(), + FE = Functions.end(); + FI != FE; + ++FI) { + void* FnStart = const_cast(*FI); + MethodIDMap::iterator MI = MethodIDs.find(FnStart); + if (MI != MethodIDs.end()) { + Wrapper->iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_UNLOAD_START, + &MI->second); + MethodIDs.erase(MI); + } + } + + // Erase the object from LoadedObjectMap + LoadedObjectMap.erase(OI); } } // anonymous namespace.