comparison unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp @ 77:54457678186b LLVM3.6

LLVM 3.6
author Kaito Tokumori <e105711@ie.u-ryukyu.ac.jp>
date Mon, 08 Sep 2014 22:06:00 +0900
parents 95c75e76d11b
children 60c9769439b8
comparison
equal deleted inserted replaced
34:e874dbf0ad9d 77:54457678186b
5 // This file is distributed under the University of Illinois Open Source 5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details. 6 // License. See LICENSE.TXT for details.
7 // 7 //
8 //===----------------------------------------------------------------------===// 8 //===----------------------------------------------------------------------===//
9 9
10 #include "llvm/ADT/OwningPtr.h" 10 #include "MCJITTestBase.h"
11 #include "llvm/ADT/SmallVector.h" 11 #include "llvm/ADT/SmallVector.h"
12 #include "llvm/ADT/StringMap.h" 12 #include "llvm/ADT/StringMap.h"
13 #include "llvm/ADT/StringSet.h" 13 #include "llvm/ADT/StringSet.h"
14 #include "llvm/ExecutionEngine/JIT.h"
15 #include "llvm/ExecutionEngine/MCJIT.h" 14 #include "llvm/ExecutionEngine/MCJIT.h"
16 #include "llvm/ExecutionEngine/ObjectCache.h" 15 #include "llvm/ExecutionEngine/ObjectCache.h"
17 #include "llvm/ExecutionEngine/SectionMemoryManager.h" 16 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
18 #include "MCJITTestBase.h"
19 #include "gtest/gtest.h" 17 #include "gtest/gtest.h"
20 18
21 using namespace llvm; 19 using namespace llvm;
22 20
23 namespace { 21 namespace {
24 22
25 class TestObjectCache : public ObjectCache { 23 class TestObjectCache : public ObjectCache {
26 public: 24 public:
27 TestObjectCache() : DuplicateInserted(false) { } 25 TestObjectCache() : DuplicateInserted(false) { }
28 26
29 virtual ~TestObjectCache() { 27 void notifyObjectCompiled(const Module *M, MemoryBufferRef Obj) override {
30 // Free any buffers we've allocated.
31 SmallVectorImpl<MemoryBuffer *>::iterator it, end;
32 end = AllocatedBuffers.end();
33 for (it = AllocatedBuffers.begin(); it != end; ++it) {
34 delete *it;
35 }
36 AllocatedBuffers.clear();
37 }
38
39 virtual void notifyObjectCompiled(const Module *M, const MemoryBuffer *Obj) {
40 // If we've seen this module before, note that. 28 // If we've seen this module before, note that.
41 const std::string ModuleID = M->getModuleIdentifier(); 29 const std::string ModuleID = M->getModuleIdentifier();
42 if (ObjMap.find(ModuleID) != ObjMap.end()) 30 if (ObjMap.find(ModuleID) != ObjMap.end())
43 DuplicateInserted = true; 31 DuplicateInserted = true;
44 // Store a copy of the buffer in our map. 32 // Store a copy of the buffer in our map.
45 ObjMap[ModuleID] = copyBuffer(Obj); 33 ObjMap[ModuleID] = copyBuffer(Obj);
46 } 34 }
47 35
48 virtual MemoryBuffer* getObject(const Module* M) { 36 virtual std::unique_ptr<MemoryBuffer> getObject(const Module* M) {
49 const MemoryBuffer* BufferFound = getObjectInternal(M); 37 const MemoryBuffer* BufferFound = getObjectInternal(M);
50 ModulesLookedUp.insert(M->getModuleIdentifier()); 38 ModulesLookedUp.insert(M->getModuleIdentifier());
51 if (!BufferFound) 39 if (!BufferFound)
52 return NULL; 40 return nullptr;
53 // Our test cache wants to maintain ownership of its object buffers 41 // Our test cache wants to maintain ownership of its object buffers
54 // so we make a copy here for the execution engine. 42 // so we make a copy here for the execution engine.
55 return MemoryBuffer::getMemBufferCopy(BufferFound->getBuffer()); 43 return MemoryBuffer::getMemBufferCopy(BufferFound->getBuffer());
56 } 44 }
57 45
66 const MemoryBuffer* getObjectInternal(const Module* M) { 54 const MemoryBuffer* getObjectInternal(const Module* M) {
67 // Look for the module in our map. 55 // Look for the module in our map.
68 const std::string ModuleID = M->getModuleIdentifier(); 56 const std::string ModuleID = M->getModuleIdentifier();
69 StringMap<const MemoryBuffer *>::iterator it = ObjMap.find(ModuleID); 57 StringMap<const MemoryBuffer *>::iterator it = ObjMap.find(ModuleID);
70 if (it == ObjMap.end()) 58 if (it == ObjMap.end())
71 return 0; 59 return nullptr;
72 return it->second; 60 return it->second;
73 } 61 }
74 62
75 private: 63 private:
76 MemoryBuffer *copyBuffer(const MemoryBuffer *Buf) { 64 MemoryBuffer *copyBuffer(MemoryBufferRef Buf) {
77 // Create a local copy of the buffer. 65 // Create a local copy of the buffer.
78 MemoryBuffer *NewBuffer = MemoryBuffer::getMemBufferCopy(Buf->getBuffer()); 66 std::unique_ptr<MemoryBuffer> NewBuffer =
79 AllocatedBuffers.push_back(NewBuffer); 67 MemoryBuffer::getMemBufferCopy(Buf.getBuffer());
80 return NewBuffer; 68 MemoryBuffer *Ret = NewBuffer.get();
69 AllocatedBuffers.push_back(std::move(NewBuffer));
70 return Ret;
81 } 71 }
82 72
83 StringMap<const MemoryBuffer *> ObjMap; 73 StringMap<const MemoryBuffer *> ObjMap;
84 StringSet<> ModulesLookedUp; 74 StringSet<> ModulesLookedUp;
85 SmallVector<MemoryBuffer *, 2> AllocatedBuffers; 75 SmallVector<std::unique_ptr<MemoryBuffer>, 2> AllocatedBuffers;
86 bool DuplicateInserted; 76 bool DuplicateInserted;
87 }; 77 };
88 78
89 class MCJITObjectCacheTest : public testing::Test, public MCJITTestBase { 79 class MCJITObjectCacheTest : public testing::Test, public MCJITTestBase {
90 protected: 80 protected:
99 Main = insertMainFunction(M.get(), OriginalRC); 89 Main = insertMainFunction(M.get(), OriginalRC);
100 } 90 }
101 91
102 void compileAndRun(int ExpectedRC = OriginalRC) { 92 void compileAndRun(int ExpectedRC = OriginalRC) {
103 // This function shouldn't be called until after SetUp. 93 // This function shouldn't be called until after SetUp.
104 ASSERT_TRUE(TheJIT.isValid()); 94 ASSERT_TRUE(bool(TheJIT));
105 ASSERT_TRUE(0 != Main); 95 ASSERT_TRUE(nullptr != Main);
106 96
107 // We may be using a null cache, so ensure compilation is valid. 97 // We may be using a null cache, so ensure compilation is valid.
108 TheJIT->finalizeObject(); 98 TheJIT->finalizeObject();
109 void *vPtr = TheJIT->getPointerToFunction(Main); 99 void *vPtr = TheJIT->getPointerToFunction(Main);
110 100
111 EXPECT_TRUE(0 != vPtr) 101 EXPECT_TRUE(nullptr != vPtr)
112 << "Unable to get pointer to main() from JIT"; 102 << "Unable to get pointer to main() from JIT";
113 103
114 int (*FuncPtr)(void) = (int(*)(void))(intptr_t)vPtr; 104 int (*FuncPtr)(void) = (int(*)(void))(intptr_t)vPtr;
115 int returnCode = FuncPtr(); 105 int returnCode = FuncPtr();
116 EXPECT_EQ(returnCode, ExpectedRC); 106 EXPECT_EQ(returnCode, ExpectedRC);
120 }; 110 };
121 111
122 TEST_F(MCJITObjectCacheTest, SetNullObjectCache) { 112 TEST_F(MCJITObjectCacheTest, SetNullObjectCache) {
123 SKIP_UNSUPPORTED_PLATFORM; 113 SKIP_UNSUPPORTED_PLATFORM;
124 114
125 createJIT(M.take()); 115 createJIT(std::move(M));
126 116
127 TheJIT->setObjectCache(NULL); 117 TheJIT->setObjectCache(nullptr);
128 118
129 compileAndRun(); 119 compileAndRun();
130 } 120 }
131 121
132 122
133 TEST_F(MCJITObjectCacheTest, VerifyBasicObjectCaching) { 123 TEST_F(MCJITObjectCacheTest, VerifyBasicObjectCaching) {
134 SKIP_UNSUPPORTED_PLATFORM; 124 SKIP_UNSUPPORTED_PLATFORM;
135 125
136 OwningPtr<TestObjectCache> Cache(new TestObjectCache); 126 std::unique_ptr<TestObjectCache> Cache(new TestObjectCache);
137 127
138 // Save a copy of the module pointer before handing it off to MCJIT. 128 // Save a copy of the module pointer before handing it off to MCJIT.
139 const Module * SavedModulePointer = M.get(); 129 const Module * SavedModulePointer = M.get();
140 130
141 createJIT(M.take()); 131 createJIT(std::move(M));
142 132
143 TheJIT->setObjectCache(Cache.get()); 133 TheJIT->setObjectCache(Cache.get());
144 134
145 // Verify that our object cache does not contain the module yet. 135 // Verify that our object cache does not contain the module yet.
146 const MemoryBuffer *ObjBuffer = Cache->getObjectInternal(SavedModulePointer); 136 const MemoryBuffer *ObjBuffer = Cache->getObjectInternal(SavedModulePointer);
147 EXPECT_EQ(0, ObjBuffer); 137 EXPECT_EQ(nullptr, ObjBuffer);
148 138
149 compileAndRun(); 139 compileAndRun();
150 140
151 // Verify that MCJIT tried to look-up this module in the cache. 141 // Verify that MCJIT tried to look-up this module in the cache.
152 EXPECT_TRUE(Cache->wasModuleLookedUp(SavedModulePointer)); 142 EXPECT_TRUE(Cache->wasModuleLookedUp(SavedModulePointer));
153 143
154 // Verify that our object cache now contains the module. 144 // Verify that our object cache now contains the module.
155 ObjBuffer = Cache->getObjectInternal(SavedModulePointer); 145 ObjBuffer = Cache->getObjectInternal(SavedModulePointer);
156 EXPECT_TRUE(0 != ObjBuffer); 146 EXPECT_TRUE(nullptr != ObjBuffer);
157 147
158 // Verify that the cache was only notified once. 148 // Verify that the cache was only notified once.
159 EXPECT_FALSE(Cache->wereDuplicatesInserted()); 149 EXPECT_FALSE(Cache->wereDuplicatesInserted());
160 } 150 }
161 151
162 TEST_F(MCJITObjectCacheTest, VerifyLoadFromCache) { 152 TEST_F(MCJITObjectCacheTest, VerifyLoadFromCache) {
163 SKIP_UNSUPPORTED_PLATFORM; 153 SKIP_UNSUPPORTED_PLATFORM;
164 154
165 OwningPtr<TestObjectCache> Cache(new TestObjectCache); 155 std::unique_ptr<TestObjectCache> Cache(new TestObjectCache);
166 156
167 // Compile this module with an MCJIT engine 157 // Compile this module with an MCJIT engine
168 createJIT(M.take()); 158 createJIT(std::move(M));
169 TheJIT->setObjectCache(Cache.get()); 159 TheJIT->setObjectCache(Cache.get());
170 TheJIT->finalizeObject(); 160 TheJIT->finalizeObject();
171 161
172 // Destroy the MCJIT engine we just used 162 // Destroy the MCJIT engine we just used
173 TheJIT.reset(); 163 TheJIT.reset();
180 M.reset(createEmptyModule("<main>")); 170 M.reset(createEmptyModule("<main>"));
181 Main = insertMainFunction(M.get(), ReplacementRC); 171 Main = insertMainFunction(M.get(), ReplacementRC);
182 const Module * SecondModulePointer = M.get(); 172 const Module * SecondModulePointer = M.get();
183 173
184 // Create a new MCJIT instance to load this module then execute it. 174 // Create a new MCJIT instance to load this module then execute it.
185 createJIT(M.take()); 175 createJIT(std::move(M));
186 TheJIT->setObjectCache(Cache.get()); 176 TheJIT->setObjectCache(Cache.get());
187 compileAndRun(); 177 compileAndRun();
188 178
189 // Verify that MCJIT tried to look-up this module in the cache. 179 // Verify that MCJIT tried to look-up this module in the cache.
190 EXPECT_TRUE(Cache->wasModuleLookedUp(SecondModulePointer)); 180 EXPECT_TRUE(Cache->wasModuleLookedUp(SecondModulePointer));
194 } 184 }
195 185
196 TEST_F(MCJITObjectCacheTest, VerifyNonLoadFromCache) { 186 TEST_F(MCJITObjectCacheTest, VerifyNonLoadFromCache) {
197 SKIP_UNSUPPORTED_PLATFORM; 187 SKIP_UNSUPPORTED_PLATFORM;
198 188
199 OwningPtr<TestObjectCache> Cache(new TestObjectCache); 189 std::unique_ptr<TestObjectCache> Cache(new TestObjectCache);
200 190
201 // Compile this module with an MCJIT engine 191 // Compile this module with an MCJIT engine
202 createJIT(M.take()); 192 createJIT(std::move(M));
203 TheJIT->setObjectCache(Cache.get()); 193 TheJIT->setObjectCache(Cache.get());
204 TheJIT->finalizeObject(); 194 TheJIT->finalizeObject();
205 195
206 // Destroy the MCJIT engine we just used 196 // Destroy the MCJIT engine we just used
207 TheJIT.reset(); 197 TheJIT.reset();
215 M.reset(createEmptyModule("<not-main>")); 205 M.reset(createEmptyModule("<not-main>"));
216 Main = insertMainFunction(M.get(), ReplacementRC); 206 Main = insertMainFunction(M.get(), ReplacementRC);
217 const Module * SecondModulePointer = M.get(); 207 const Module * SecondModulePointer = M.get();
218 208
219 // Create a new MCJIT instance to load this module then execute it. 209 // Create a new MCJIT instance to load this module then execute it.
220 createJIT(M.take()); 210 createJIT(std::move(M));
221 TheJIT->setObjectCache(Cache.get()); 211 TheJIT->setObjectCache(Cache.get());
222 212
223 // Verify that our object cache does not contain the module yet. 213 // Verify that our object cache does not contain the module yet.
224 const MemoryBuffer *ObjBuffer = Cache->getObjectInternal(SecondModulePointer); 214 const MemoryBuffer *ObjBuffer = Cache->getObjectInternal(SecondModulePointer);
225 EXPECT_EQ(0, ObjBuffer); 215 EXPECT_EQ(nullptr, ObjBuffer);
226 216
227 // Run the function and look for the replacement return code. 217 // Run the function and look for the replacement return code.
228 compileAndRun(ReplacementRC); 218 compileAndRun(ReplacementRC);
229 219
230 // Verify that MCJIT tried to look-up this module in the cache. 220 // Verify that MCJIT tried to look-up this module in the cache.
231 EXPECT_TRUE(Cache->wasModuleLookedUp(SecondModulePointer)); 221 EXPECT_TRUE(Cache->wasModuleLookedUp(SecondModulePointer));
232 222
233 // Verify that our object cache now contains the module. 223 // Verify that our object cache now contains the module.
234 ObjBuffer = Cache->getObjectInternal(SecondModulePointer); 224 ObjBuffer = Cache->getObjectInternal(SecondModulePointer);
235 EXPECT_TRUE(0 != ObjBuffer); 225 EXPECT_TRUE(nullptr != ObjBuffer);
236 226
237 // Verify that MCJIT didn't try to cache this again. 227 // Verify that MCJIT didn't try to cache this again.
238 EXPECT_FALSE(Cache->wereDuplicatesInserted()); 228 EXPECT_FALSE(Cache->wereDuplicatesInserted());
239 } 229 }
240 230