Mercurial > hg > CbC > CbC_llvm
comparison lib/ExecutionEngine/SectionMemoryManager.cpp @ 83:60c9769439b8 LLVM3.7
LLVM 3.7
author | Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp> |
---|---|
date | Wed, 18 Feb 2015 14:55:36 +0900 |
parents | |
children | afa8332a0e37 |
comparison
equal
deleted
inserted
replaced
78:af83660cff7b | 83:60c9769439b8 |
---|---|
1 //===- SectionMemoryManager.cpp - Memory manager for MCJIT/RtDyld *- C++ -*-==// | |
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 // This file implements the section-based memory manager used by the MCJIT | |
11 // execution engine and RuntimeDyld | |
12 // | |
13 //===----------------------------------------------------------------------===// | |
14 | |
15 #include "llvm/Config/config.h" | |
16 #include "llvm/ExecutionEngine/SectionMemoryManager.h" | |
17 #include "llvm/Support/MathExtras.h" | |
18 | |
19 namespace llvm { | |
20 | |
21 uint8_t *SectionMemoryManager::allocateDataSection(uintptr_t Size, | |
22 unsigned Alignment, | |
23 unsigned SectionID, | |
24 StringRef SectionName, | |
25 bool IsReadOnly) { | |
26 if (IsReadOnly) | |
27 return allocateSection(RODataMem, Size, Alignment); | |
28 return allocateSection(RWDataMem, Size, Alignment); | |
29 } | |
30 | |
31 uint8_t *SectionMemoryManager::allocateCodeSection(uintptr_t Size, | |
32 unsigned Alignment, | |
33 unsigned SectionID, | |
34 StringRef SectionName) { | |
35 return allocateSection(CodeMem, Size, Alignment); | |
36 } | |
37 | |
38 uint8_t *SectionMemoryManager::allocateSection(MemoryGroup &MemGroup, | |
39 uintptr_t Size, | |
40 unsigned Alignment) { | |
41 if (!Alignment) | |
42 Alignment = 16; | |
43 | |
44 assert(!(Alignment & (Alignment - 1)) && "Alignment must be a power of two."); | |
45 | |
46 uintptr_t RequiredSize = Alignment * ((Size + Alignment - 1)/Alignment + 1); | |
47 uintptr_t Addr = 0; | |
48 | |
49 // Look in the list of free memory regions and use a block there if one | |
50 // is available. | |
51 for (int i = 0, e = MemGroup.FreeMem.size(); i != e; ++i) { | |
52 sys::MemoryBlock &MB = MemGroup.FreeMem[i]; | |
53 if (MB.size() >= RequiredSize) { | |
54 Addr = (uintptr_t)MB.base(); | |
55 uintptr_t EndOfBlock = Addr + MB.size(); | |
56 // Align the address. | |
57 Addr = (Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1); | |
58 // Store cutted free memory block. | |
59 MemGroup.FreeMem[i] = sys::MemoryBlock((void*)(Addr + Size), | |
60 EndOfBlock - Addr - Size); | |
61 return (uint8_t*)Addr; | |
62 } | |
63 } | |
64 | |
65 // No pre-allocated free block was large enough. Allocate a new memory region. | |
66 // Note that all sections get allocated as read-write. The permissions will | |
67 // be updated later based on memory group. | |
68 // | |
69 // FIXME: It would be useful to define a default allocation size (or add | |
70 // it as a constructor parameter) to minimize the number of allocations. | |
71 // | |
72 // FIXME: Initialize the Near member for each memory group to avoid | |
73 // interleaving. | |
74 std::error_code ec; | |
75 sys::MemoryBlock MB = sys::Memory::allocateMappedMemory(RequiredSize, | |
76 &MemGroup.Near, | |
77 sys::Memory::MF_READ | | |
78 sys::Memory::MF_WRITE, | |
79 ec); | |
80 if (ec) { | |
81 // FIXME: Add error propagation to the interface. | |
82 return nullptr; | |
83 } | |
84 | |
85 // Save this address as the basis for our next request | |
86 MemGroup.Near = MB; | |
87 | |
88 MemGroup.AllocatedMem.push_back(MB); | |
89 Addr = (uintptr_t)MB.base(); | |
90 uintptr_t EndOfBlock = Addr + MB.size(); | |
91 | |
92 // Align the address. | |
93 Addr = (Addr + Alignment - 1) & ~(uintptr_t)(Alignment - 1); | |
94 | |
95 // The allocateMappedMemory may allocate much more memory than we need. In | |
96 // this case, we store the unused memory as a free memory block. | |
97 unsigned FreeSize = EndOfBlock-Addr-Size; | |
98 if (FreeSize > 16) | |
99 MemGroup.FreeMem.push_back(sys::MemoryBlock((void*)(Addr + Size), FreeSize)); | |
100 | |
101 // Return aligned address | |
102 return (uint8_t*)Addr; | |
103 } | |
104 | |
105 bool SectionMemoryManager::finalizeMemory(std::string *ErrMsg) | |
106 { | |
107 // FIXME: Should in-progress permissions be reverted if an error occurs? | |
108 std::error_code ec; | |
109 | |
110 // Don't allow free memory blocks to be used after setting protection flags. | |
111 CodeMem.FreeMem.clear(); | |
112 | |
113 // Make code memory executable. | |
114 ec = applyMemoryGroupPermissions(CodeMem, | |
115 sys::Memory::MF_READ | sys::Memory::MF_EXEC); | |
116 if (ec) { | |
117 if (ErrMsg) { | |
118 *ErrMsg = ec.message(); | |
119 } | |
120 return true; | |
121 } | |
122 | |
123 // Don't allow free memory blocks to be used after setting protection flags. | |
124 RODataMem.FreeMem.clear(); | |
125 | |
126 // Make read-only data memory read-only. | |
127 ec = applyMemoryGroupPermissions(RODataMem, | |
128 sys::Memory::MF_READ | sys::Memory::MF_EXEC); | |
129 if (ec) { | |
130 if (ErrMsg) { | |
131 *ErrMsg = ec.message(); | |
132 } | |
133 return true; | |
134 } | |
135 | |
136 // Read-write data memory already has the correct permissions | |
137 | |
138 // Some platforms with separate data cache and instruction cache require | |
139 // explicit cache flush, otherwise JIT code manipulations (like resolved | |
140 // relocations) will get to the data cache but not to the instruction cache. | |
141 invalidateInstructionCache(); | |
142 | |
143 return false; | |
144 } | |
145 | |
146 std::error_code | |
147 SectionMemoryManager::applyMemoryGroupPermissions(MemoryGroup &MemGroup, | |
148 unsigned Permissions) { | |
149 | |
150 for (int i = 0, e = MemGroup.AllocatedMem.size(); i != e; ++i) { | |
151 std::error_code ec; | |
152 ec = | |
153 sys::Memory::protectMappedMemory(MemGroup.AllocatedMem[i], Permissions); | |
154 if (ec) { | |
155 return ec; | |
156 } | |
157 } | |
158 | |
159 return std::error_code(); | |
160 } | |
161 | |
162 void SectionMemoryManager::invalidateInstructionCache() { | |
163 for (int i = 0, e = CodeMem.AllocatedMem.size(); i != e; ++i) | |
164 sys::Memory::InvalidateInstructionCache(CodeMem.AllocatedMem[i].base(), | |
165 CodeMem.AllocatedMem[i].size()); | |
166 } | |
167 | |
168 SectionMemoryManager::~SectionMemoryManager() { | |
169 for (unsigned i = 0, e = CodeMem.AllocatedMem.size(); i != e; ++i) | |
170 sys::Memory::releaseMappedMemory(CodeMem.AllocatedMem[i]); | |
171 for (unsigned i = 0, e = RWDataMem.AllocatedMem.size(); i != e; ++i) | |
172 sys::Memory::releaseMappedMemory(RWDataMem.AllocatedMem[i]); | |
173 for (unsigned i = 0, e = RODataMem.AllocatedMem.size(); i != e; ++i) | |
174 sys::Memory::releaseMappedMemory(RODataMem.AllocatedMem[i]); | |
175 } | |
176 | |
177 } // namespace llvm | |
178 |