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