Skip to content

Commit 77d2f10

Browse files
committed
[MERGE #1829 @leirocks] reduce native code data memory usage for in-proc jit
Merge pull request #1829 from leirocks:inprocnatdata1 In OOP JIT when allocating native code data we record some information about the allocation. At the end of a JIT work item, the allocation information is used to make the pointer fixing up table which then used to fixup the internal pointers after passing native code data to runtime process. After a JIT work item is done, all the native code data including the allocation information are freed in JIT server, only the fixup table and aggregated data buffer is passed to runtime process. The fixup table is freed right after doing fixup in runntime process after the codegen call returned. When doing in-proc jit we don't need these fixup information, and we don't do pointer fixing up and data aggregating/copying, the the fixup information has same life time as the native code data themselves, thus wasting memory. This change bring back the same data structure which before the OOP JIT change and use it for in-proc JIT Note in OOP JIT it uses one pointer size less memory than in-proc JIT because even the next pointer on DataChunk is not kept after data aggregating.
2 parents 2b0bbf5 + 356300f commit 77d2f10

File tree

3 files changed

+141
-82
lines changed

3 files changed

+141
-82
lines changed

lib/Backend/NativeCodeData.cpp

Lines changed: 71 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
//-------------------------------------------------------------------------------------------------------
55
#include "Backend.h"
66

7-
NativeCodeData::NativeCodeData(DataChunk * chunkList) : chunkList(chunkList)
7+
NativeCodeData::NativeCodeData(DataChunk * chunkList)
8+
: chunkList(chunkList)
89
{
910
#ifdef PERF_COUNTERS
1011
this->size = 0;
@@ -13,7 +14,14 @@ NativeCodeData::NativeCodeData(DataChunk * chunkList) : chunkList(chunkList)
1314

1415
NativeCodeData::~NativeCodeData()
1516
{
16-
NativeCodeData::DeleteChunkList(this->chunkList);
17+
if (JITManager::GetJITManager()->IsJITServer())
18+
{
19+
NativeCodeData::DeleteChunkList(this->chunkList);
20+
}
21+
else
22+
{
23+
NativeCodeData::DeleteChunkList(this->noFixupChunkList);
24+
}
1725
PERF_COUNTER_SUB(Code, DynamicNativeCodeDataSize, this->size);
1826
PERF_COUNTER_SUB(Code, TotalNativeCodeDataSize, this->size);
1927
}
@@ -171,19 +179,23 @@ NativeCodeData::VerifyExistFixupEntry(void* targetAddr, void* addrToFixup, void*
171179
AssertMsg(false, "Data chunk not found");
172180
}
173181

182+
template<class DataChunkT>
174183
void
175-
NativeCodeData::DeleteChunkList(DataChunk * chunkList)
184+
NativeCodeData::DeleteChunkList(DataChunkT * chunkList)
176185
{
177-
DataChunk * next = chunkList;
186+
DataChunkT * next = chunkList;
178187
while (next != nullptr)
179188
{
180-
DataChunk * current = next;
189+
DataChunkT * current = next;
181190
next = next->next;
182191
delete current;
183192
}
184193
}
185194

186-
NativeCodeData::Allocator::Allocator() : chunkList(nullptr), lastChunkList(nullptr)
195+
NativeCodeData::Allocator::Allocator()
196+
: chunkList(nullptr),
197+
lastChunkList(nullptr),
198+
isOOPJIT(JITManager::GetJITManager()->IsJITServer())
187199
{
188200
this->totalSize = 0;
189201
this->allocCount = 0;
@@ -198,55 +210,73 @@ NativeCodeData::Allocator::Allocator() : chunkList(nullptr), lastChunkList(nullp
198210
NativeCodeData::Allocator::~Allocator()
199211
{
200212
Assert(!finalized || this->chunkList == nullptr);
201-
NativeCodeData::DeleteChunkList(this->chunkList);
213+
if (JITManager::GetJITManager()->IsJITServer())
214+
{
215+
NativeCodeData::DeleteChunkList(this->chunkList);
216+
}
217+
else
218+
{
219+
NativeCodeData::DeleteChunkList(this->noFixupChunkList);
220+
}
202221
PERF_COUNTER_SUB(Code, DynamicNativeCodeDataSize, this->size);
203222
PERF_COUNTER_SUB(Code, TotalNativeCodeDataSize, this->size);
204223
}
205224

206225
char *
207-
NativeCodeData::Allocator::Alloc(size_t requestSize)
226+
NativeCodeData::Allocator::Alloc(DECLSPEC_GUARD_OVERFLOW size_t requestSize)
208227
{
209-
char * data = nullptr;
210228
Assert(!finalized);
229+
char * data = nullptr;
211230
requestSize = Math::Align(requestSize, sizeof(void*));
212231

232+
if (isOOPJIT)
233+
{
234+
213235
#if DBG
214-
// Always zero out the data for chk build to reduce the chance of false
215-
// positive while verifying missing fixup entries
216-
// Allocation without zeroing out, and with bool field in the structure
217-
// will increase the chance of false positive because of reusing memory
218-
// without zeroing, and the bool field is set to false, makes the garbage
219-
// memory not changed, and the garbage memory might be just pointing to the
220-
// same range of NativeCodeData memory, the checking tool will report false
221-
// poisitive, see NativeCodeData::VerifyExistFixupEntry for more
222-
DataChunk * newChunk = HeapNewStructPlusZ(requestSize, DataChunk);
236+
// Always zero out the data for chk build to reduce the chance of false
237+
// positive while verifying missing fixup entries
238+
// Allocation without zeroing out, and with bool field in the structure
239+
// will increase the chance of false positive because of reusing memory
240+
// without zeroing, and the bool field is set to false, makes the garbage
241+
// memory not changed, and the garbage memory might be just pointing to the
242+
// same range of NativeCodeData memory, the checking tool will report false
243+
// poisitive, see NativeCodeData::VerifyExistFixupEntry for more
244+
DataChunk * newChunk = HeapNewStructPlusZ(requestSize, DataChunk);
223245
#else
224-
DataChunk * newChunk = HeapNewStructPlus(requestSize, DataChunk);
246+
DataChunk * newChunk = HeapNewStructPlus(requestSize, DataChunk);
225247
#endif
226248

227249
#if DBG
228-
newChunk->dataType = nullptr;
250+
newChunk->dataType = nullptr;
229251
#endif
230252

231-
newChunk->next = nullptr;
232-
newChunk->allocIndex = this->allocCount++;
233-
newChunk->len = (unsigned int)requestSize;
234-
newChunk->fixupList = nullptr;
235-
newChunk->fixupFunc = nullptr;
236-
newChunk->offset = this->totalSize;
237-
if (this->chunkList == nullptr)
238-
{
239-
this->chunkList = newChunk;
240-
this->lastChunkList = newChunk;
253+
newChunk->next = nullptr;
254+
newChunk->allocIndex = this->allocCount++;
255+
newChunk->len = (unsigned int)requestSize;
256+
newChunk->fixupList = nullptr;
257+
newChunk->fixupFunc = nullptr;
258+
newChunk->offset = this->totalSize;
259+
if (this->chunkList == nullptr)
260+
{
261+
this->chunkList = newChunk;
262+
this->lastChunkList = newChunk;
263+
}
264+
else
265+
{
266+
this->lastChunkList->next = newChunk;
267+
this->lastChunkList = newChunk;
268+
}
269+
this->totalSize += (unsigned int)requestSize;
270+
data = newChunk->data;
241271
}
242272
else
243273
{
244-
this->lastChunkList->next = newChunk;
245-
this->lastChunkList = newChunk;
274+
DataChunkNoFixup * newChunk = HeapNewStructPlus(requestSize, DataChunkNoFixup);
275+
newChunk->next = this->noFixupChunkList;
276+
this->noFixupChunkList = newChunk;
277+
data = newChunk->data;
246278
}
247279

248-
data = newChunk->data;
249-
this->totalSize += (unsigned int)requestSize;
250280

251281
#ifdef PERF_COUNTERS
252282
this->size += requestSize;
@@ -258,18 +288,23 @@ NativeCodeData::Allocator::Alloc(size_t requestSize)
258288
}
259289

260290
char *
261-
NativeCodeData::Allocator::AllocLeaf(size_t requestSize)
291+
NativeCodeData::Allocator::AllocLeaf(DECLSPEC_GUARD_OVERFLOW size_t requestSize)
262292
{
263293
return Alloc(requestSize);
264294
}
265295

266296
char *
267-
NativeCodeData::Allocator::AllocZero(size_t requestSize)
297+
NativeCodeData::Allocator::AllocZero(DECLSPEC_GUARD_OVERFLOW size_t requestSize)
268298
{
269299
char * data = Alloc(requestSize);
270300
#if !DBG
271301
// Allocated with HeapNewStructPlusZ for chk build
272302
memset(data, 0, requestSize);
303+
#else
304+
if (!isOOPJIT)
305+
{
306+
memset(data, 0, requestSize);
307+
}
273308
#endif
274309
return data;
275310
}

lib/Backend/NativeCodeData.h

Lines changed: 50 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -42,20 +42,32 @@ class NativeCodeData
4242
char data[0];
4343
};
4444

45+
struct DataChunkNoFixup
46+
{
47+
DataChunkNoFixup * next;
48+
char data[0];
49+
};
50+
4551
static DataChunk* GetDataChunk(void* data)
4652
{
53+
Assert(JITManager::GetJITManager()->IsJITServer());
4754
return (NativeCodeData::DataChunk*)((char*)data - offsetof(NativeCodeData::DataChunk, data));
4855
}
4956

5057
static char16* GetDataDescription(void* data, JitArenaAllocator * alloc);
5158

5259
static unsigned int GetDataTotalOffset(void* data)
5360
{
61+
Assert(JITManager::GetJITManager()->IsJITServer());
5462
return GetDataChunk(data)->offset;
5563
}
5664

5765
NativeCodeData(DataChunk * chunkList);
58-
DataChunk * chunkList;
66+
union
67+
{
68+
DataChunk * chunkList;
69+
DataChunkNoFixup * noFixupChunkList;
70+
};
5971

6072
#ifdef PERF_COUNTERS
6173
size_t size;
@@ -66,7 +78,8 @@ class NativeCodeData
6678
static void AddFixupEntry(void* targetAddr, void* addrToFixup, void* startAddress, DataChunk * chunkList);
6779
static void AddFixupEntry(void* targetAddr, void* targetStartAddr, void* addrToFixup, void* startAddress, DataChunk * chunkList);
6880
static void AddFixupEntryForPointerArray(void* startAddress, DataChunk * chunkList);
69-
static void DeleteChunkList(DataChunk * chunkList);
81+
template<class DataChunkT>
82+
static void DeleteChunkList(DataChunkT * chunkList);
7083
public:
7184
class Allocator
7285
{
@@ -83,8 +96,12 @@ class NativeCodeData
8396
NativeCodeData * Finalize();
8497
void Free(void * buffer, size_t byteSize);
8598

86-
DataChunk * chunkList;
87-
DataChunk * lastChunkList;
99+
union
100+
{
101+
DataChunk * chunkList;
102+
DataChunkNoFixup* noFixupChunkList;
103+
};
104+
DataChunk * lastChunkList; // used to maintain the allocation order in the list
88105
unsigned int totalSize;
89106
unsigned int allocCount;
90107

@@ -93,8 +110,9 @@ class NativeCodeData
93110
Allocator * TrackAllocInfo(TrackAllocData const& data) { return this; }
94111
void ClearTrackAllocInfo(TrackAllocData* data = NULL) {}
95112
#endif
113+
protected:
114+
bool isOOPJIT;
96115
private:
97-
98116
#if DBG
99117
bool finalized;
100118
#endif
@@ -125,12 +143,15 @@ class NativeCodeData
125143
{
126144
char* dataBlock = __super::Alloc(requestedBytes);
127145
#if DBG
128-
DataChunk* chunk = NativeCodeData::GetDataChunk(dataBlock);
129-
chunk->dataType = typeid(T).name();
130-
if (PHASE_TRACE1(Js::NativeCodeDataPhase))
146+
if (JITManager::GetJITManager()->IsJITServer())
131147
{
132-
Output::Print(_u("NativeCodeData AllocNoFix: chunk: %p, data: %p, index: %d, len: %x, totalOffset: %x, type: %S\n"),
133-
chunk, (void*)dataBlock, chunk->allocIndex, chunk->len, chunk->offset, chunk->dataType);
148+
DataChunk* chunk = NativeCodeData::GetDataChunk(dataBlock);
149+
chunk->dataType = typeid(T).name();
150+
if (PHASE_TRACE1(Js::NativeCodeDataPhase))
151+
{
152+
Output::Print(_u("NativeCodeData AllocNoFix: chunk: %p, data: %p, index: %d, len: %x, totalOffset: %x, type: %S\n"),
153+
chunk, (void*)dataBlock, chunk->allocIndex, chunk->len, chunk->offset, chunk->dataType);
154+
}
134155
}
135156
#endif
136157

@@ -141,12 +162,15 @@ class NativeCodeData
141162
char* dataBlock = __super::AllocZero(requestedBytes);
142163

143164
#if DBG
144-
DataChunk* chunk = NativeCodeData::GetDataChunk(dataBlock);
145-
chunk->dataType = typeid(T).name();
146-
if (PHASE_TRACE1(Js::NativeCodeDataPhase))
165+
if (JITManager::GetJITManager()->IsJITServer())
147166
{
148-
Output::Print(_u("NativeCodeData AllocNoFix: chunk: %p, data: %p, index: %d, len: %x, totalOffset: %x, type: %S\n"),
149-
chunk, (void*)dataBlock, chunk->allocIndex, chunk->len, chunk->offset, chunk->dataType);
167+
DataChunk* chunk = NativeCodeData::GetDataChunk(dataBlock);
168+
chunk->dataType = typeid(T).name();
169+
if (PHASE_TRACE1(Js::NativeCodeDataPhase))
170+
{
171+
Output::Print(_u("NativeCodeData AllocNoFix: chunk: %p, data: %p, index: %d, len: %x, totalOffset: %x, type: %S\n"),
172+
chunk, (void*)dataBlock, chunk->allocIndex, chunk->len, chunk->offset, chunk->dataType);
173+
}
150174
}
151175
#endif
152176

@@ -161,22 +185,21 @@ class NativeCodeData
161185
template<typename T>
162186
class AllocatorT : public Allocator
163187
{
164-
#if DBG
165-
__declspec(noinline) // compiler inline this function even in chk build... maybe because it's in .h file?
166-
#endif
167188
char* AddFixup(char* dataBlock)
168189
{
169-
DataChunk* chunk = NativeCodeData::GetDataChunk(dataBlock);
170-
chunk->fixupFunc = &Fixup;
171-
#if DBG
172-
chunk->dataType = typeid(T).name();
173-
if (PHASE_TRACE1(Js::NativeCodeDataPhase))
190+
if (isOOPJIT)
174191
{
175-
Output::Print(_u("NativeCodeData Alloc: chunk: %p, data: %p, index: %d, len: %x, totalOffset: %x, type: %S\n"),
176-
chunk, (void*)dataBlock, chunk->allocIndex, chunk->len, chunk->offset, chunk->dataType);
177-
}
192+
DataChunk* chunk = NativeCodeData::GetDataChunk(dataBlock);
193+
chunk->fixupFunc = &Fixup;
194+
#if DBG
195+
chunk->dataType = typeid(T).name();
196+
if (PHASE_TRACE1(Js::NativeCodeDataPhase))
197+
{
198+
Output::Print(_u("NativeCodeData Alloc: chunk: %p, data: %p, index: %d, len: %x, totalOffset: %x, type: %S\n"),
199+
chunk, (void*)dataBlock, chunk->allocIndex, chunk->len, chunk->offset, chunk->dataType);
200+
}
178201
#endif
179-
202+
}
180203
return dataBlock;
181204
}
182205

0 commit comments

Comments
 (0)