IntelJITEventListener.cpp revision 61b1851a205cb8dd29c1d3d4231efb8f8f7da283
161b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky//===-- IntelJITEventListener.cpp - Tell Intel profiler about JITed code --===//
261b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky//
361b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky//                     The LLVM Compiler Infrastructure
461b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky//
561b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky// This file is distributed under the University of Illinois Open Source
661b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky// License. See LICENSE.TXT for details.
761b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky//
861b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky//===----------------------------------------------------------------------===//
961b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky//
1061b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky// This file defines a JITEventListener object to tell Intel(R) VTune(TM)
1161b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky// Amplifier XE 2011 about JITted functions.
1261b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky//
1361b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky//===----------------------------------------------------------------------===//
1461b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky
1561b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky#include "llvm/Config/config.h"
1661b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky#include "llvm/ExecutionEngine/JITEventListener.h"
1761b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky
1861b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky#define DEBUG_TYPE "amplifier-jit-event-listener"
1961b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky#include "llvm/Function.h"
2061b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky#include "llvm/Metadata.h"
2161b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky#include "llvm/ADT/DenseMap.h"
2261b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky#include "llvm/ADT/OwningPtr.h"
2361b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky#include "llvm/Analysis/DebugInfo.h"
2461b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky#include "llvm/CodeGen/MachineFunction.h"
2561b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky#include "llvm/ExecutionEngine/IntelJITEventsWrapper.h"
2661b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky#include "llvm/Support/Debug.h"
2761b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky#include "llvm/Support/raw_ostream.h"
2861b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky#include "llvm/Support/Errno.h"
2961b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky#include "llvm/Support/ValueHandle.h"
3061b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky#include "EventListenerCommon.h"
3161b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky
3261b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Benderskyusing namespace llvm;
3361b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Benderskyusing namespace llvm::jitprofiling;
3461b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky
3561b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Benderskynamespace {
3661b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky
3761b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Benderskyclass IntelJITEventListener : public JITEventListener {
3861b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  typedef DenseMap<void*, unsigned int> MethodIDMap;
3961b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky
4061b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  IntelJITEventsWrapper& Wrapper;
4161b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  MethodIDMap MethodIDs;
4261b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  FilenameCache Filenames;
4361b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky
4461b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Benderskypublic:
4561b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  IntelJITEventListener(IntelJITEventsWrapper& libraryWrapper)
4661b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  : Wrapper(libraryWrapper) {
4761b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  }
4861b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky
4961b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  ~IntelJITEventListener() {
5061b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  }
5161b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky
5261b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  virtual void NotifyFunctionEmitted(const Function &F,
5361b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky                                     void *FnStart, size_t FnSize,
5461b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky                                     const EmittedFunctionDetails &Details);
5561b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky
5661b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  virtual void NotifyFreeingMachineCode(void *OldPtr);
5761b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky};
5861b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky
5961b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Benderskystatic LineNumberInfo LineStartToIntelJITFormat(
6061b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky    uintptr_t StartAddress,
6161b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky    uintptr_t Address,
6261b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky    DebugLoc Loc) {
6361b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  LineNumberInfo Result;
6461b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky
6561b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  Result.Offset = Address - StartAddress;
6661b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  Result.LineNumber = Loc.getLine();
6761b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky
6861b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  return Result;
6961b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky}
7061b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky
7161b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Benderskystatic iJIT_Method_Load FunctionDescToIntelJITFormat(
7261b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky    IntelJITEventsWrapper& Wrapper,
7361b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky    const char* FnName,
7461b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky    uintptr_t FnStart,
7561b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky    size_t FnSize) {
7661b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  iJIT_Method_Load Result;
7761b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  memset(&Result, 0, sizeof(iJIT_Method_Load));
7861b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky
7961b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  Result.method_id = Wrapper.iJIT_GetNewMethodID();
8061b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  Result.method_name = const_cast<char*>(FnName);
8161b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  Result.method_load_address = reinterpret_cast<void*>(FnStart);
8261b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  Result.method_size = FnSize;
8361b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky
8461b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  Result.class_id = 0;
8561b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  Result.class_file_name = NULL;
8661b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  Result.user_data = NULL;
8761b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  Result.user_data_size = 0;
8861b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  Result.env = iJDE_JittingAPI;
8961b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky
9061b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  return Result;
9161b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky}
9261b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky
9361b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky// Adds the just-emitted function to the symbol table.
9461b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Benderskyvoid IntelJITEventListener::NotifyFunctionEmitted(
9561b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky    const Function &F, void *FnStart, size_t FnSize,
9661b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky    const EmittedFunctionDetails &Details) {
9761b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  iJIT_Method_Load FunctionMessage = FunctionDescToIntelJITFormat(Wrapper,
9861b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky                                      F.getName().data(),
9961b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky                                      reinterpret_cast<uint64_t>(FnStart),
10061b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky                                      FnSize);
10161b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky
10261b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  std::vector<LineNumberInfo> LineInfo;
10361b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky
10461b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  if (!Details.LineStarts.empty()) {
10561b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky    // Now convert the line number information from the address/DebugLoc
10661b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky    // format in Details to the offset/lineno in Intel JIT API format.
10761b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky
10861b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky    LineInfo.reserve(Details.LineStarts.size() + 1);
10961b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky
11061b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky    DebugLoc FirstLoc = Details.LineStarts[0].Loc;
11161b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky    assert(!FirstLoc.isUnknown()
11261b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky           && "LineStarts should not contain unknown DebugLocs");
11361b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky
11461b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky    MDNode *FirstLocScope = FirstLoc.getScope(F.getContext());
11561b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky    DISubprogram FunctionDI = getDISubprogram(FirstLocScope);
11661b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky    if (FunctionDI.Verify()) {
11761b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky      FunctionMessage.source_file_name = const_cast<char*>(
11861b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky                                          Filenames.getFullPath(FirstLocScope));
11961b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky
12061b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky      LineNumberInfo FirstLine;
12161b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky      FirstLine.Offset = 0;
12261b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky      FirstLine.LineNumber = FunctionDI.getLineNumber();
12361b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky      LineInfo.push_back(FirstLine);
12461b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky    }
12561b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky
12661b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky    for (std::vector<EmittedFunctionDetails::LineStart>::const_iterator I =
12761b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky          Details.LineStarts.begin(), E = Details.LineStarts.end();
12861b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky          I != E; ++I) {
12961b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky      // This implementation ignores the DebugLoc filename because the Intel
13061b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky      // JIT API does not support multiple source files associated with a single
13161b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky      // JIT function
13261b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky      LineInfo.push_back(LineStartToIntelJITFormat(
13361b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky                          reinterpret_cast<uintptr_t>(FnStart),
13461b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky                          I->Address,
13561b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky                          I->Loc));
13661b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky
13761b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky      // If we have no file name yet for the function, use the filename from
13861b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky      // the first instruction that has one
13961b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky      if (FunctionMessage.source_file_name == 0) {
14061b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky        MDNode *scope = I->Loc.getScope(
14161b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky					Details.MF->getFunction()->getContext());
14261b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky        FunctionMessage.source_file_name = const_cast<char*>(
14361b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky                                                  Filenames.getFullPath(scope));
14461b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky      }
14561b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky    }
14661b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky
14761b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky    FunctionMessage.line_number_size = LineInfo.size();
14861b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky    FunctionMessage.line_number_table = &*LineInfo.begin();
14961b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  } else {
15061b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky    FunctionMessage.line_number_size = 0;
15161b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky    FunctionMessage.line_number_table = 0;
15261b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  }
15361b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky
15461b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  Wrapper.iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED,
15561b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky													 &FunctionMessage);
15661b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  MethodIDs[FnStart] = FunctionMessage.method_id;
15761b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky}
15861b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky
15961b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Benderskyvoid IntelJITEventListener::NotifyFreeingMachineCode(void *FnStart) {
16061b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  MethodIDMap::iterator I = MethodIDs.find(FnStart);
16161b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  if (I != MethodIDs.end()) {
16261b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky    Wrapper.iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_UNLOAD_START, &I->second);
16361b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky    MethodIDs.erase(I);
16461b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  }
16561b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky}
16661b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky
16761b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky}  // anonymous namespace.
16861b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky
16961b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Benderskynamespace llvm {
17061b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli BenderskyJITEventListener *JITEventListener::createIntelJITEventListener() {
17161b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  static OwningPtr<IntelJITEventsWrapper> JITProfilingWrapper(
17261b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky                                            new IntelJITEventsWrapper);
17361b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  return new IntelJITEventListener(*JITProfilingWrapper);
17461b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky}
17561b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky
17661b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky// for testing
17761b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli BenderskyJITEventListener *JITEventListener::createIntelJITEventListener(
17861b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky                                      IntelJITEventsWrapper* TestImpl) {
17961b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky  return new IntelJITEventListener(*TestImpl);
18061b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky}
18161b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky
18261b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky} // namespace llvm
18361b1851a205cb8dd29c1d3d4231efb8f8f7da283Eli Bendersky
184