Mercurial > hg > CbC > CbC_llvm
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 |