diff --git a/lib/Backend/NativeCodeData.cpp b/lib/Backend/NativeCodeData.cpp index 9042c585e08..79f8bc19276 100644 --- a/lib/Backend/NativeCodeData.cpp +++ b/lib/Backend/NativeCodeData.cpp @@ -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; @@ -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); } @@ -171,19 +179,23 @@ NativeCodeData::VerifyExistFixupEntry(void* targetAddr, void* addrToFixup, void* AssertMsg(false, "Data chunk not found"); } +template 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; @@ -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; @@ -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; } diff --git a/lib/Backend/NativeCodeData.h b/lib/Backend/NativeCodeData.h index 5591ef6ad0f..eb418ac9601 100644 --- a/lib/Backend/NativeCodeData.h +++ b/lib/Backend/NativeCodeData.h @@ -42,8 +42,15 @@ 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)); } @@ -51,11 +58,16 @@ class NativeCodeData 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; @@ -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 + static void DeleteChunkList(DataChunkT * chunkList); public: class Allocator { @@ -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; @@ -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 @@ -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 @@ -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 @@ -161,22 +185,21 @@ class NativeCodeData template 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; } diff --git a/lib/Runtime/Language/JavascriptNativeOperators.h b/lib/Runtime/Language/JavascriptNativeOperators.h index 4f0c60161eb..2d68615013f 100644 --- a/lib/Runtime/Language/JavascriptNativeOperators.h +++ b/lib/Runtime/Language/JavascriptNativeOperators.h @@ -16,12 +16,15 @@ namespace Js { char* dataBlock = __super::Alloc(requestedBytes); #if DBG - NativeCodeData::DataChunk* chunk = NativeCodeData::GetDataChunk(dataBlock); - chunk->dataType = "BranchDictionary::Bucket"; - if (PHASE_TRACE1(Js::NativeCodeDataPhase)) + if (JITManager::GetJITManager()->IsJITServer()) { - Output::Print(_u("NativeCodeData BranchDictionary::Bucket: chunk: %p, data: %p, index: %d, len: %x, totalOffset: %x, type: %S\n"), - chunk, (void*)dataBlock, chunk->allocIndex, chunk->len, chunk->offset, chunk->dataType); + NativeCodeData::DataChunk* chunk = NativeCodeData::GetDataChunk(dataBlock); + chunk->dataType = "BranchDictionary::Bucket"; + if (PHASE_TRACE1(Js::NativeCodeDataPhase)) + { + Output::Print(_u("NativeCodeData BranchDictionary::Bucket: 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; @@ -31,12 +34,15 @@ namespace Js { char* dataBlock = __super::AllocZero(requestedBytes); #if DBG - NativeCodeData::DataChunk* chunk = NativeCodeData::GetDataChunk(dataBlock); - chunk->dataType = "BranchDictionary::Entries"; - if (PHASE_TRACE1(Js::NativeCodeDataPhase)) + if (JITManager::GetJITManager()->IsJITServer()) { - Output::Print(_u("NativeCodeData BranchDictionary::Entries: chunk: %p, data: %p, index: %d, len: %x, totalOffset: %x, type: %S\n"), - chunk, (void*)dataBlock, chunk->allocIndex, chunk->len, chunk->offset, chunk->dataType); + NativeCodeData::DataChunk* chunk = NativeCodeData::GetDataChunk(dataBlock); + chunk->dataType = "BranchDictionary::Entries"; + if (PHASE_TRACE1(Js::NativeCodeDataPhase)) + { + Output::Print(_u("NativeCodeData BranchDictionary::Entries: 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; @@ -47,7 +53,6 @@ namespace Js class SimpleDictionaryEntryWithFixUp : public JsUtil::SimpleDictionaryEntry { public: - __declspec(noinline) void FixupWithRemoteKey(void* remoteKey) { this->key = (TKey)remoteKey; @@ -63,7 +68,6 @@ namespace Js : BranchBaseDictionary(allocator, dictionarySize) { } - __declspec(noinline) void Fixup(NativeCodeData::DataChunk* chunkList, void** remoteKeys) { for (int i = 0; i < this->Count(); i++) @@ -84,6 +88,7 @@ namespace Js } else { + Assert(!JITManager::GetJITManager()->IsJITServer()); remoteKeys = nullptr; } } @@ -92,11 +97,6 @@ namespace Js void* defaultTarget; void** remoteKeys; - bool IsOOPJit() - { - return remoteKeys != nullptr; - } - static BranchDictionaryWrapper* New(NativeCodeData::Allocator * allocator, uint dictionarySize, ArenaAllocator* remoteKeyAlloc) { return NativeCodeDataNew(allocator, BranchDictionaryWrapper, allocator, dictionarySize, remoteKeyAlloc); @@ -105,15 +105,16 @@ namespace Js void AddEntry(uint32 offset, T key, void* remoteVar) { int index = dictionary.AddNew(key, (void**)offset); - if (IsOOPJit()) + if (JITManager::GetJITManager()->IsJITServer()) { + Assert(remoteKeys); remoteKeys[index] = remoteVar; } } void Fixup(NativeCodeData::DataChunk* chunkList) { - if (IsOOPJit()) + if (JITManager::GetJITManager()->IsJITServer()) { dictionary.Fixup(chunkList, remoteKeys); }