Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 71 additions & 36 deletions lib/Backend/NativeCodeData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
//-------------------------------------------------------------------------------------------------------
#include "Backend.h"

NativeCodeData::NativeCodeData(DataChunk * chunkList) : chunkList(chunkList)
NativeCodeData::NativeCodeData(DataChunk * chunkList)
: chunkList(chunkList)
{
#ifdef PERF_COUNTERS
this->size = 0;
Expand All @@ -13,7 +14,14 @@ NativeCodeData::NativeCodeData(DataChunk * chunkList) : chunkList(chunkList)

NativeCodeData::~NativeCodeData()
{
NativeCodeData::DeleteChunkList(this->chunkList);
if (JITManager::GetJITManager()->IsJITServer())
{
NativeCodeData::DeleteChunkList(this->chunkList);
}
else
{
NativeCodeData::DeleteChunkList(this->noFixupChunkList);
}
PERF_COUNTER_SUB(Code, DynamicNativeCodeDataSize, this->size);
PERF_COUNTER_SUB(Code, TotalNativeCodeDataSize, this->size);
}
Expand Down Expand Up @@ -171,19 +179,23 @@ NativeCodeData::VerifyExistFixupEntry(void* targetAddr, void* addrToFixup, void*
AssertMsg(false, "Data chunk not found");
}

template<class DataChunkT>
void
NativeCodeData::DeleteChunkList(DataChunk * chunkList)
NativeCodeData::DeleteChunkList(DataChunkT * chunkList)
{
DataChunk * next = chunkList;
DataChunkT * next = chunkList;
while (next != nullptr)
{
DataChunk * current = next;
DataChunkT * current = next;
next = next->next;
delete current;
}
}

NativeCodeData::Allocator::Allocator() : chunkList(nullptr), lastChunkList(nullptr)
NativeCodeData::Allocator::Allocator()
: chunkList(nullptr),
lastChunkList(nullptr),
isOOPJIT(JITManager::GetJITManager()->IsJITServer())
{
this->totalSize = 0;
this->allocCount = 0;
Expand All @@ -198,55 +210,73 @@ NativeCodeData::Allocator::Allocator() : chunkList(nullptr), lastChunkList(nullp
NativeCodeData::Allocator::~Allocator()
{
Assert(!finalized || this->chunkList == nullptr);
NativeCodeData::DeleteChunkList(this->chunkList);
if (JITManager::GetJITManager()->IsJITServer())
{
NativeCodeData::DeleteChunkList(this->chunkList);
}
else
{
NativeCodeData::DeleteChunkList(this->noFixupChunkList);
}
PERF_COUNTER_SUB(Code, DynamicNativeCodeDataSize, this->size);
PERF_COUNTER_SUB(Code, TotalNativeCodeDataSize, this->size);
}

char *
NativeCodeData::Allocator::Alloc(size_t requestSize)
NativeCodeData::Allocator::Alloc(DECLSPEC_GUARD_OVERFLOW size_t requestSize)
{
char * data = nullptr;
Assert(!finalized);
char * data = nullptr;
requestSize = Math::Align(requestSize, sizeof(void*));

if (isOOPJIT)
{

#if DBG
// Always zero out the data for chk build to reduce the chance of false
// positive while verifying missing fixup entries
// Allocation without zeroing out, and with bool field in the structure
// will increase the chance of false positive because of reusing memory
// without zeroing, and the bool field is set to false, makes the garbage
// memory not changed, and the garbage memory might be just pointing to the
// same range of NativeCodeData memory, the checking tool will report false
// poisitive, see NativeCodeData::VerifyExistFixupEntry for more
DataChunk * newChunk = HeapNewStructPlusZ(requestSize, DataChunk);
// Always zero out the data for chk build to reduce the chance of false
// positive while verifying missing fixup entries
// Allocation without zeroing out, and with bool field in the structure
// will increase the chance of false positive because of reusing memory
// without zeroing, and the bool field is set to false, makes the garbage
// memory not changed, and the garbage memory might be just pointing to the
// same range of NativeCodeData memory, the checking tool will report false
// poisitive, see NativeCodeData::VerifyExistFixupEntry for more
DataChunk * newChunk = HeapNewStructPlusZ(requestSize, DataChunk);
#else
DataChunk * newChunk = HeapNewStructPlus(requestSize, DataChunk);
DataChunk * newChunk = HeapNewStructPlus(requestSize, DataChunk);
#endif

#if DBG
newChunk->dataType = nullptr;
newChunk->dataType = nullptr;
#endif

newChunk->next = nullptr;
newChunk->allocIndex = this->allocCount++;
newChunk->len = (unsigned int)requestSize;
newChunk->fixupList = nullptr;
newChunk->fixupFunc = nullptr;
newChunk->offset = this->totalSize;
if (this->chunkList == nullptr)
{
this->chunkList = newChunk;
this->lastChunkList = newChunk;
newChunk->next = nullptr;
newChunk->allocIndex = this->allocCount++;
newChunk->len = (unsigned int)requestSize;
newChunk->fixupList = nullptr;
newChunk->fixupFunc = nullptr;
newChunk->offset = this->totalSize;
if (this->chunkList == nullptr)
{
this->chunkList = newChunk;
this->lastChunkList = newChunk;
}
else
{
this->lastChunkList->next = newChunk;
this->lastChunkList = newChunk;
}
this->totalSize += (unsigned int)requestSize;
data = newChunk->data;
}
else
{
this->lastChunkList->next = newChunk;
this->lastChunkList = newChunk;
DataChunkNoFixup * newChunk = HeapNewStructPlus(requestSize, DataChunkNoFixup);
newChunk->next = this->noFixupChunkList;
this->noFixupChunkList = newChunk;
data = newChunk->data;
}

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

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

char *
NativeCodeData::Allocator::AllocLeaf(size_t requestSize)
NativeCodeData::Allocator::AllocLeaf(DECLSPEC_GUARD_OVERFLOW size_t requestSize)
{
return Alloc(requestSize);
}

char *
NativeCodeData::Allocator::AllocZero(size_t requestSize)
NativeCodeData::Allocator::AllocZero(DECLSPEC_GUARD_OVERFLOW size_t requestSize)
{
char * data = Alloc(requestSize);
#if !DBG
// Allocated with HeapNewStructPlusZ for chk build
memset(data, 0, requestSize);
#else
if (!isOOPJIT)
{
memset(data, 0, requestSize);
}
#endif
return data;
}
Expand Down
77 changes: 50 additions & 27 deletions lib/Backend/NativeCodeData.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,32 @@ class NativeCodeData
char data[0];
};

struct DataChunkNoFixup
{
DataChunkNoFixup * next;
char data[0];
};

static DataChunk* GetDataChunk(void* data)
{
Assert(JITManager::GetJITManager()->IsJITServer());
return (NativeCodeData::DataChunk*)((char*)data - offsetof(NativeCodeData::DataChunk, data));
}

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

static unsigned int GetDataTotalOffset(void* data)
{
Assert(JITManager::GetJITManager()->IsJITServer());
return GetDataChunk(data)->offset;
}

NativeCodeData(DataChunk * chunkList);
DataChunk * chunkList;
union
{
DataChunk * chunkList;
DataChunkNoFixup * noFixupChunkList;
};

#ifdef PERF_COUNTERS
size_t size;
Expand All @@ -66,7 +78,8 @@ class NativeCodeData
static void AddFixupEntry(void* targetAddr, void* addrToFixup, void* startAddress, DataChunk * chunkList);
static void AddFixupEntry(void* targetAddr, void* targetStartAddr, void* addrToFixup, void* startAddress, DataChunk * chunkList);
static void AddFixupEntryForPointerArray(void* startAddress, DataChunk * chunkList);
static void DeleteChunkList(DataChunk * chunkList);
template<class DataChunkT>
static void DeleteChunkList(DataChunkT * chunkList);
public:
class Allocator
{
Expand All @@ -83,8 +96,12 @@ class NativeCodeData
NativeCodeData * Finalize();
void Free(void * buffer, size_t byteSize);

DataChunk * chunkList;
DataChunk * lastChunkList;
union
{
DataChunk * chunkList;
DataChunkNoFixup* noFixupChunkList;
};
DataChunk * lastChunkList; // used to maintain the allocation order in the list
unsigned int totalSize;
unsigned int allocCount;

Expand All @@ -93,8 +110,9 @@ class NativeCodeData
Allocator * TrackAllocInfo(TrackAllocData const& data) { return this; }
void ClearTrackAllocInfo(TrackAllocData* data = NULL) {}
#endif
protected:
bool isOOPJIT;
private:

#if DBG
bool finalized;
#endif
Expand Down Expand Up @@ -125,12 +143,15 @@ class NativeCodeData
{
char* dataBlock = __super::Alloc(requestedBytes);
#if DBG
DataChunk* chunk = NativeCodeData::GetDataChunk(dataBlock);
chunk->dataType = typeid(T).name();
if (PHASE_TRACE1(Js::NativeCodeDataPhase))
if (JITManager::GetJITManager()->IsJITServer())
{
Output::Print(_u("NativeCodeData AllocNoFix: chunk: %p, data: %p, index: %d, len: %x, totalOffset: %x, type: %S\n"),
chunk, (void*)dataBlock, chunk->allocIndex, chunk->len, chunk->offset, chunk->dataType);
DataChunk* chunk = NativeCodeData::GetDataChunk(dataBlock);
chunk->dataType = typeid(T).name();
if (PHASE_TRACE1(Js::NativeCodeDataPhase))
{
Output::Print(_u("NativeCodeData AllocNoFix: chunk: %p, data: %p, index: %d, len: %x, totalOffset: %x, type: %S\n"),
chunk, (void*)dataBlock, chunk->allocIndex, chunk->len, chunk->offset, chunk->dataType);
}
}
#endif

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

#if DBG
DataChunk* chunk = NativeCodeData::GetDataChunk(dataBlock);
chunk->dataType = typeid(T).name();
if (PHASE_TRACE1(Js::NativeCodeDataPhase))
if (JITManager::GetJITManager()->IsJITServer())
{
Output::Print(_u("NativeCodeData AllocNoFix: chunk: %p, data: %p, index: %d, len: %x, totalOffset: %x, type: %S\n"),
chunk, (void*)dataBlock, chunk->allocIndex, chunk->len, chunk->offset, chunk->dataType);
DataChunk* chunk = NativeCodeData::GetDataChunk(dataBlock);
chunk->dataType = typeid(T).name();
if (PHASE_TRACE1(Js::NativeCodeDataPhase))
{
Output::Print(_u("NativeCodeData AllocNoFix: chunk: %p, data: %p, index: %d, len: %x, totalOffset: %x, type: %S\n"),
chunk, (void*)dataBlock, chunk->allocIndex, chunk->len, chunk->offset, chunk->dataType);
}
}
#endif

Expand All @@ -161,22 +185,21 @@ class NativeCodeData
template<typename T>
class AllocatorT : public Allocator
{
#if DBG
__declspec(noinline) // compiler inline this function even in chk build... maybe because it's in .h file?
#endif
char* AddFixup(char* dataBlock)
{
DataChunk* chunk = NativeCodeData::GetDataChunk(dataBlock);
chunk->fixupFunc = &Fixup;
#if DBG
chunk->dataType = typeid(T).name();
if (PHASE_TRACE1(Js::NativeCodeDataPhase))
if (isOOPJIT)
{
Output::Print(_u("NativeCodeData Alloc: chunk: %p, data: %p, index: %d, len: %x, totalOffset: %x, type: %S\n"),
chunk, (void*)dataBlock, chunk->allocIndex, chunk->len, chunk->offset, chunk->dataType);
}
DataChunk* chunk = NativeCodeData::GetDataChunk(dataBlock);
chunk->fixupFunc = &Fixup;
#if DBG
chunk->dataType = typeid(T).name();
if (PHASE_TRACE1(Js::NativeCodeDataPhase))
{
Output::Print(_u("NativeCodeData Alloc: chunk: %p, data: %p, index: %d, len: %x, totalOffset: %x, type: %S\n"),
chunk, (void*)dataBlock, chunk->allocIndex, chunk->len, chunk->offset, chunk->dataType);
}
#endif

}
return dataBlock;
}

Expand Down
Loading