Implementing basic function-level profiling support in IntelJITEventListener.

Tests to follow in another patch.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@168444 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Andrew Kaylor 2012-11-21 18:50:33 +00:00
parent 0ae6124034
commit 34519fc11d

View File

@ -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<const void *, 64> MethodAddressVector;
typedef DenseMap<const void *, MethodAddressVector> 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<void*>(*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.