MCJITObjectCacheTest.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. //===- MCJITObjectCacheTest.cpp - Unit tests for MCJIT object caching -----===//
  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. #include "llvm/ADT/OwningPtr.h"
  10. #include "llvm/ADT/SmallVector.h"
  11. #include "llvm/ADT/StringMap.h"
  12. #include "llvm/ADT/StringSet.h"
  13. #include "llvm/ExecutionEngine/JIT.h"
  14. #include "llvm/ExecutionEngine/MCJIT.h"
  15. #include "llvm/ExecutionEngine/ObjectCache.h"
  16. #include "llvm/ExecutionEngine/SectionMemoryManager.h"
  17. #include "MCJITTestBase.h"
  18. #include "gtest/gtest.h"
  19. using namespace llvm;
  20. namespace {
  21. class TestObjectCache : public ObjectCache {
  22. public:
  23. TestObjectCache() : DuplicateInserted(false) { }
  24. virtual ~TestObjectCache() {
  25. // Free any buffers we've allocated.
  26. SmallVector<MemoryBuffer *, 2>::iterator it, end;
  27. end = AllocatedBuffers.end();
  28. for (it = AllocatedBuffers.begin(); it != end; ++it) {
  29. delete *it;
  30. }
  31. AllocatedBuffers.clear();
  32. }
  33. virtual void notifyObjectCompiled(const Module *M, const MemoryBuffer *Obj) {
  34. // If we've seen this module before, note that.
  35. const std::string ModuleID = M->getModuleIdentifier();
  36. if (ObjMap.find(ModuleID) != ObjMap.end())
  37. DuplicateInserted = true;
  38. // Store a copy of the buffer in our map.
  39. ObjMap[ModuleID] = copyBuffer(Obj);
  40. }
  41. // Test-harness-specific functions
  42. bool wereDuplicatesInserted() { return DuplicateInserted; }
  43. bool wasModuleLookedUp(const Module *M) {
  44. return ModulesLookedUp.find(M->getModuleIdentifier())
  45. != ModulesLookedUp.end();
  46. }
  47. const MemoryBuffer* getObjectInternal(const Module* M) {
  48. // Look for the module in our map.
  49. const std::string ModuleID = M->getModuleIdentifier();
  50. StringMap<const MemoryBuffer *>::iterator it = ObjMap.find(ModuleID);
  51. if (it == ObjMap.end())
  52. return 0;
  53. return it->second;
  54. }
  55. protected:
  56. virtual const MemoryBuffer* getObject(const Module* M) {
  57. const MemoryBuffer* BufferFound = getObjectInternal(M);
  58. ModulesLookedUp.insert(M->getModuleIdentifier());
  59. return BufferFound;
  60. }
  61. private:
  62. MemoryBuffer *copyBuffer(const MemoryBuffer *Buf) {
  63. // Create a local copy of the buffer.
  64. MemoryBuffer *NewBuffer = MemoryBuffer::getMemBufferCopy(Buf->getBuffer());
  65. AllocatedBuffers.push_back(NewBuffer);
  66. return NewBuffer;
  67. }
  68. StringMap<const MemoryBuffer *> ObjMap;
  69. StringSet<> ModulesLookedUp;
  70. SmallVector<MemoryBuffer *, 2> AllocatedBuffers;
  71. bool DuplicateInserted;
  72. };
  73. class MCJITObjectCacheTest : public testing::Test, public MCJITTestBase {
  74. protected:
  75. enum {
  76. OriginalRC = 6,
  77. ReplacementRC = 7
  78. };
  79. virtual void SetUp() {
  80. M.reset(createEmptyModule("<main>"));
  81. Main = insertMainFunction(M.get(), OriginalRC);
  82. }
  83. void compileAndRun(int ExpectedRC = OriginalRC) {
  84. // This function shouldn't be called until after SetUp.
  85. ASSERT_TRUE(0 != TheJIT);
  86. ASSERT_TRUE(0 != Main);
  87. TheJIT->finalizeObject();
  88. void *vPtr = TheJIT->getPointerToFunction(Main);
  89. static_cast<SectionMemoryManager*>(MM)->invalidateInstructionCache();
  90. EXPECT_TRUE(0 != vPtr)
  91. << "Unable to get pointer to main() from JIT";
  92. int (*FuncPtr)(void) = (int(*)(void))(intptr_t)vPtr;
  93. int returnCode = FuncPtr();
  94. EXPECT_EQ(returnCode, ExpectedRC);
  95. }
  96. Function *Main;
  97. };
  98. TEST_F(MCJITObjectCacheTest, SetNullObjectCache) {
  99. SKIP_UNSUPPORTED_PLATFORM;
  100. createJIT(M.take());
  101. TheJIT->setObjectCache(NULL);
  102. compileAndRun();
  103. }
  104. TEST_F(MCJITObjectCacheTest, VerifyBasicObjectCaching) {
  105. SKIP_UNSUPPORTED_PLATFORM;
  106. OwningPtr<TestObjectCache> Cache(new TestObjectCache);
  107. // Save a copy of the module pointer before handing it off to MCJIT.
  108. const Module * SavedModulePointer = M.get();
  109. createJIT(M.take());
  110. TheJIT->setObjectCache(Cache.get());
  111. // Verify that our object cache does not contain the module yet.
  112. const MemoryBuffer *ObjBuffer = Cache->getObjectInternal(SavedModulePointer);
  113. EXPECT_EQ(0, ObjBuffer);
  114. compileAndRun();
  115. // Verify that MCJIT tried to look-up this module in the cache.
  116. EXPECT_TRUE(Cache->wasModuleLookedUp(SavedModulePointer));
  117. // Verify that our object cache now contains the module.
  118. ObjBuffer = Cache->getObjectInternal(SavedModulePointer);
  119. EXPECT_TRUE(0 != ObjBuffer);
  120. // Verify that the cache was only notified once.
  121. EXPECT_FALSE(Cache->wereDuplicatesInserted());
  122. }
  123. TEST_F(MCJITObjectCacheTest, VerifyLoadFromCache) {
  124. SKIP_UNSUPPORTED_PLATFORM;
  125. OwningPtr<TestObjectCache> Cache(new TestObjectCache);
  126. // Compile this module with an MCJIT engine
  127. createJIT(M.take());
  128. TheJIT->setObjectCache(Cache.get());
  129. TheJIT->finalizeObject();
  130. // Destroy the MCJIT engine we just used
  131. TheJIT.reset();
  132. // Create a new memory manager.
  133. MM = new SectionMemoryManager;
  134. // Create a new module and save it. Use a different return code so we can
  135. // tell if MCJIT compiled this module or used the cache.
  136. M.reset(createEmptyModule("<main>"));
  137. Main = insertMainFunction(M.get(), ReplacementRC);
  138. const Module * SecondModulePointer = M.get();
  139. // Create a new MCJIT instance to load this module then execute it.
  140. createJIT(M.take());
  141. TheJIT->setObjectCache(Cache.get());
  142. compileAndRun();
  143. // Verify that MCJIT tried to look-up this module in the cache.
  144. EXPECT_TRUE(Cache->wasModuleLookedUp(SecondModulePointer));
  145. // Verify that MCJIT didn't try to cache this again.
  146. EXPECT_FALSE(Cache->wereDuplicatesInserted());
  147. }
  148. TEST_F(MCJITObjectCacheTest, VerifyNonLoadFromCache) {
  149. SKIP_UNSUPPORTED_PLATFORM;
  150. OwningPtr<TestObjectCache> Cache(new TestObjectCache);
  151. // Compile this module with an MCJIT engine
  152. createJIT(M.take());
  153. TheJIT->setObjectCache(Cache.get());
  154. TheJIT->finalizeObject();
  155. // Destroy the MCJIT engine we just used
  156. TheJIT.reset();
  157. // Create a new memory manager.
  158. MM = new SectionMemoryManager;
  159. // Create a new module and save it. Use a different return code so we can
  160. // tell if MCJIT compiled this module or used the cache. Note that we use
  161. // a new module name here so the module shouldn't be found in the cache.
  162. M.reset(createEmptyModule("<not-main>"));
  163. Main = insertMainFunction(M.get(), ReplacementRC);
  164. const Module * SecondModulePointer = M.get();
  165. // Create a new MCJIT instance to load this module then execute it.
  166. createJIT(M.take());
  167. TheJIT->setObjectCache(Cache.get());
  168. // Verify that our object cache does not contain the module yet.
  169. const MemoryBuffer *ObjBuffer = Cache->getObjectInternal(SecondModulePointer);
  170. EXPECT_EQ(0, ObjBuffer);
  171. // Run the function and look for the replacement return code.
  172. compileAndRun(ReplacementRC);
  173. // Verify that MCJIT tried to look-up this module in the cache.
  174. EXPECT_TRUE(Cache->wasModuleLookedUp(SecondModulePointer));
  175. // Verify that our object cache now contains the module.
  176. ObjBuffer = Cache->getObjectInternal(SecondModulePointer);
  177. EXPECT_TRUE(0 != ObjBuffer);
  178. // Verify that MCJIT didn't try to cache this again.
  179. EXPECT_FALSE(Cache->wereDuplicatesInserted());
  180. }
  181. } // Namespace