Home | History | Annotate | Download | only in JIT
      1 //===- JITEventListenerTest.cpp - Unit tests for JITEventListeners --------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "llvm/ExecutionEngine/JITEventListener.h"
     11 
     12 #include "llvm/LLVMContext.h"
     13 #include "llvm/Instructions.h"
     14 #include "llvm/Module.h"
     15 #include "llvm/ADT/OwningPtr.h"
     16 #include "llvm/CodeGen/MachineCodeInfo.h"
     17 #include "llvm/ExecutionEngine/JIT.h"
     18 #include "llvm/Support/TypeBuilder.h"
     19 #include "llvm/Support/TargetSelect.h"
     20 #include "gtest/gtest.h"
     21 #include <vector>
     22 
     23 using namespace llvm;
     24 
     25 int dummy;
     26 
     27 namespace {
     28 
     29 struct FunctionEmittedEvent {
     30   // Indices are local to the RecordingJITEventListener, since the
     31   // JITEventListener interface makes no guarantees about the order of
     32   // calls between Listeners.
     33   unsigned Index;
     34   const Function *F;
     35   void *Code;
     36   size_t Size;
     37   JITEvent_EmittedFunctionDetails Details;
     38 };
     39 struct FunctionFreedEvent {
     40   unsigned Index;
     41   void *Code;
     42 };
     43 
     44 struct RecordingJITEventListener : public JITEventListener {
     45   std::vector<FunctionEmittedEvent> EmittedEvents;
     46   std::vector<FunctionFreedEvent> FreedEvents;
     47 
     48   unsigned NextIndex;
     49 
     50   RecordingJITEventListener() : NextIndex(0) {}
     51 
     52   virtual void NotifyFunctionEmitted(const Function &F,
     53                                      void *Code, size_t Size,
     54                                      const EmittedFunctionDetails &Details) {
     55     FunctionEmittedEvent Event = {NextIndex++, &F, Code, Size, Details};
     56     EmittedEvents.push_back(Event);
     57   }
     58 
     59   virtual void NotifyFreeingMachineCode(void *OldPtr) {
     60     FunctionFreedEvent Event = {NextIndex++, OldPtr};
     61     FreedEvents.push_back(Event);
     62   }
     63 };
     64 
     65 class JITEventListenerTest : public testing::Test {
     66  protected:
     67   JITEventListenerTest()
     68       : M(new Module("module", getGlobalContext())),
     69         EE(EngineBuilder(M)
     70            .setEngineKind(EngineKind::JIT)
     71            .create()) {
     72   }
     73 
     74   Module *M;
     75   const OwningPtr<ExecutionEngine> EE;
     76 };
     77 
     78 Function *buildFunction(Module *M) {
     79   Function *Result = Function::Create(
     80       TypeBuilder<int32_t(int32_t), false>::get(getGlobalContext()),
     81       GlobalValue::ExternalLinkage, "id", M);
     82   Value *Arg = Result->arg_begin();
     83   BasicBlock *BB = BasicBlock::Create(M->getContext(), "entry", Result);
     84   ReturnInst::Create(M->getContext(), Arg, BB);
     85   return Result;
     86 }
     87 
     88 // Tests that a single JITEventListener follows JIT events accurately.
     89 TEST_F(JITEventListenerTest, Simple) {
     90   RecordingJITEventListener Listener;
     91   EE->RegisterJITEventListener(&Listener);
     92   Function *F1 = buildFunction(M);
     93   Function *F2 = buildFunction(M);
     94 
     95   void *F1_addr = EE->getPointerToFunction(F1);
     96   void *F2_addr = EE->getPointerToFunction(F2);
     97   EE->getPointerToFunction(F1);  // Should do nothing.
     98   EE->freeMachineCodeForFunction(F1);
     99   EE->freeMachineCodeForFunction(F2);
    100 
    101   ASSERT_EQ(2U, Listener.EmittedEvents.size());
    102   ASSERT_EQ(2U, Listener.FreedEvents.size());
    103 
    104   EXPECT_EQ(0U, Listener.EmittedEvents[0].Index);
    105   EXPECT_EQ(F1, Listener.EmittedEvents[0].F);
    106   EXPECT_EQ(F1_addr, Listener.EmittedEvents[0].Code);
    107   EXPECT_LT(0U, Listener.EmittedEvents[0].Size)
    108       << "We don't know how big the function will be, but it had better"
    109       << " contain some bytes.";
    110 
    111   EXPECT_EQ(1U, Listener.EmittedEvents[1].Index);
    112   EXPECT_EQ(F2, Listener.EmittedEvents[1].F);
    113   EXPECT_EQ(F2_addr, Listener.EmittedEvents[1].Code);
    114   EXPECT_LT(0U, Listener.EmittedEvents[1].Size)
    115       << "We don't know how big the function will be, but it had better"
    116       << " contain some bytes.";
    117 
    118   EXPECT_EQ(2U, Listener.FreedEvents[0].Index);
    119   EXPECT_EQ(F1_addr, Listener.FreedEvents[0].Code);
    120 
    121   EXPECT_EQ(3U, Listener.FreedEvents[1].Index);
    122   EXPECT_EQ(F2_addr, Listener.FreedEvents[1].Code);
    123 
    124   F1->eraseFromParent();
    125   F2->eraseFromParent();
    126 }
    127 
    128 // Tests that a single JITEventListener follows JIT events accurately.
    129 TEST_F(JITEventListenerTest, MultipleListenersDontInterfere) {
    130   RecordingJITEventListener Listener1;
    131   RecordingJITEventListener Listener2;
    132   RecordingJITEventListener Listener3;
    133   Function *F1 = buildFunction(M);
    134   Function *F2 = buildFunction(M);
    135 
    136   EE->RegisterJITEventListener(&Listener1);
    137   EE->RegisterJITEventListener(&Listener2);
    138   void *F1_addr = EE->getPointerToFunction(F1);
    139   EE->RegisterJITEventListener(&Listener3);
    140   EE->UnregisterJITEventListener(&Listener1);
    141   void *F2_addr = EE->getPointerToFunction(F2);
    142   EE->UnregisterJITEventListener(&Listener2);
    143   EE->UnregisterJITEventListener(&Listener3);
    144   EE->freeMachineCodeForFunction(F1);
    145   EE->RegisterJITEventListener(&Listener2);
    146   EE->RegisterJITEventListener(&Listener3);
    147   EE->RegisterJITEventListener(&Listener1);
    148   EE->freeMachineCodeForFunction(F2);
    149   EE->UnregisterJITEventListener(&Listener1);
    150   EE->UnregisterJITEventListener(&Listener2);
    151   EE->UnregisterJITEventListener(&Listener3);
    152 
    153   // Listener 1.
    154   ASSERT_EQ(1U, Listener1.EmittedEvents.size());
    155   ASSERT_EQ(1U, Listener1.FreedEvents.size());
    156 
    157   EXPECT_EQ(0U, Listener1.EmittedEvents[0].Index);
    158   EXPECT_EQ(F1, Listener1.EmittedEvents[0].F);
    159   EXPECT_EQ(F1_addr, Listener1.EmittedEvents[0].Code);
    160   EXPECT_LT(0U, Listener1.EmittedEvents[0].Size)
    161       << "We don't know how big the function will be, but it had better"
    162       << " contain some bytes.";
    163 
    164   EXPECT_EQ(1U, Listener1.FreedEvents[0].Index);
    165   EXPECT_EQ(F2_addr, Listener1.FreedEvents[0].Code);
    166 
    167   // Listener 2.
    168   ASSERT_EQ(2U, Listener2.EmittedEvents.size());
    169   ASSERT_EQ(1U, Listener2.FreedEvents.size());
    170 
    171   EXPECT_EQ(0U, Listener2.EmittedEvents[0].Index);
    172   EXPECT_EQ(F1, Listener2.EmittedEvents[0].F);
    173   EXPECT_EQ(F1_addr, Listener2.EmittedEvents[0].Code);
    174   EXPECT_LT(0U, Listener2.EmittedEvents[0].Size)
    175       << "We don't know how big the function will be, but it had better"
    176       << " contain some bytes.";
    177 
    178   EXPECT_EQ(1U, Listener2.EmittedEvents[1].Index);
    179   EXPECT_EQ(F2, Listener2.EmittedEvents[1].F);
    180   EXPECT_EQ(F2_addr, Listener2.EmittedEvents[1].Code);
    181   EXPECT_LT(0U, Listener2.EmittedEvents[1].Size)
    182       << "We don't know how big the function will be, but it had better"
    183       << " contain some bytes.";
    184 
    185   EXPECT_EQ(2U, Listener2.FreedEvents[0].Index);
    186   EXPECT_EQ(F2_addr, Listener2.FreedEvents[0].Code);
    187 
    188   // Listener 3.
    189   ASSERT_EQ(1U, Listener3.EmittedEvents.size());
    190   ASSERT_EQ(1U, Listener3.FreedEvents.size());
    191 
    192   EXPECT_EQ(0U, Listener3.EmittedEvents[0].Index);
    193   EXPECT_EQ(F2, Listener3.EmittedEvents[0].F);
    194   EXPECT_EQ(F2_addr, Listener3.EmittedEvents[0].Code);
    195   EXPECT_LT(0U, Listener3.EmittedEvents[0].Size)
    196       << "We don't know how big the function will be, but it had better"
    197       << " contain some bytes.";
    198 
    199   EXPECT_EQ(1U, Listener3.FreedEvents[0].Index);
    200   EXPECT_EQ(F2_addr, Listener3.FreedEvents[0].Code);
    201 
    202   F1->eraseFromParent();
    203   F2->eraseFromParent();
    204 }
    205 
    206 TEST_F(JITEventListenerTest, MatchesMachineCodeInfo) {
    207   RecordingJITEventListener Listener;
    208   MachineCodeInfo MCI;
    209   Function *F = buildFunction(M);
    210 
    211   EE->RegisterJITEventListener(&Listener);
    212   EE->runJITOnFunction(F, &MCI);
    213   void *F_addr = EE->getPointerToFunction(F);
    214   EE->freeMachineCodeForFunction(F);
    215 
    216   ASSERT_EQ(1U, Listener.EmittedEvents.size());
    217   ASSERT_EQ(1U, Listener.FreedEvents.size());
    218 
    219   EXPECT_EQ(0U, Listener.EmittedEvents[0].Index);
    220   EXPECT_EQ(F, Listener.EmittedEvents[0].F);
    221   EXPECT_EQ(F_addr, Listener.EmittedEvents[0].Code);
    222   EXPECT_EQ(MCI.address(), Listener.EmittedEvents[0].Code);
    223   EXPECT_EQ(MCI.size(), Listener.EmittedEvents[0].Size);
    224 
    225   EXPECT_EQ(1U, Listener.FreedEvents[0].Index);
    226   EXPECT_EQ(F_addr, Listener.FreedEvents[0].Code);
    227 }
    228 
    229 class JITEnvironment : public testing::Environment {
    230   virtual void SetUp() {
    231     // Required to create a JIT.
    232     InitializeNativeTarget();
    233   }
    234 };
    235 testing::Environment* const jit_env =
    236   testing::AddGlobalTestEnvironment(new JITEnvironment);
    237 
    238 }  // anonymous namespace
    239