Skip to content

Commit 3741b1a

Browse files
committed
Refactor field related to JIT'ed code in EntryPointInfo into a separate structure
Reduced FunctionEntryPointInfo from 336 bytes to 96 bytes in 64 bits Also fix an issue that JitTransferData wasn't deleted when SimpleJit work completes. Reduce memory usage of MS Teams page load by 6MB
1 parent a47597a commit 3741b1a

29 files changed

+1584
-1171
lines changed

lib/Backend/BailOut.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1130,7 +1130,7 @@ BailOutRecord::BailOutInlinedHelper(Js::JavascriptCallStackLayout * layout, Bail
11301130
// While bailing out, RestoreFrames should box all Vars on the stack. If there are multiple Vars pointing to the same
11311131
// object, the cached version (that was previously boxed) will be reused to maintain pointer identity and correctness
11321132
// after the transition to the interpreter.
1133-
InlinedFrameLayout* outerMostFrame = (InlinedFrameLayout *)(((uint8 *)Js::JavascriptCallStackLayout::ToFramePointer(layout)) - entryPointInfo->frameHeight);
1133+
InlinedFrameLayout* outerMostFrame = (InlinedFrameLayout *)(((uint8 *)Js::JavascriptCallStackLayout::ToFramePointer(layout)) - entryPointInfo->GetFrameHeight());
11341134
inlineeFrameRecord->RestoreFrames(functionBody, outerMostFrame, layout, true /* boxArgs */);
11351135
}
11361136
}

lib/Backend/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ add_library (Chakra.Backend OBJECT
5151
JITTimePolymorphicInlineCacheInfo.cpp
5252
JITTimeProfileInfo.cpp
5353
JITTimeWorkItem.cpp
54+
JitTransferData.cpp
5455
JITType.cpp
5556
JITTypeHandler.cpp
5657
JnHelperMethod.cpp
@@ -60,6 +61,7 @@ add_library (Chakra.Backend OBJECT
6061
LowerMDSharedSimd128.cpp
6162
NativeCodeData.cpp
6263
NativeCodeGenerator.cpp
64+
NativeEntryPointData.cpp
6365
ObjTypeSpecFldInfo.cpp
6466
Opnd.cpp
6567
PDataManager.cpp

lib/Backend/Chakra.Backend.vcxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,8 +253,12 @@
253253
<ClCompile Include="$(MSBuildThisFileDirectory)ValueInfo.cpp" />
254254
<ClCompile Include="$(MSBuildThisFileDirectory)JITThunkEmitter.cpp" />
255255
<ClCompile Include="$(MSBuildThisFileDirectory)IntConstMath.cpp" />
256+
<ClCompile Include="$(MSBuildThisFileDirectory)NativeEntryPointData.cpp" />
257+
<ClCompile Include="$(MSBuildThisFileDirectory)JitTransferData.cpp" />
256258
</ItemGroup>
257259
<ItemGroup>
260+
<ClInclude Include="JitTransferData.h" />
261+
<ClInclude Include="NativeEntryPointData.h" />
258262
<ClInclude Include="AgenPeeps.h" />
259263
<ClInclude Include="arm64\ARM64Encoder.h">
260264
<ExcludedFromBuild Condition="'$(Platform)'!='ARM64'">true</ExcludedFromBuild>

lib/Backend/CodeGenWorkItem.cpp

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
//-------------------------------------------------------------------------------------------------------
55
#include "Backend.h"
66
#include "Language/SourceDynamicProfileManager.h"
7+
#include "NativeEntryPointData.h"
78

89
CodeGenWorkItem::CodeGenWorkItem(
910
JsUtil::JobManager *const manager,
@@ -184,7 +185,7 @@ void CodeGenWorkItem::OnRemoveFromJitQueue(NativeCodeGenerator* generator)
184185
// Go ahead and delete it and let it re-queue if more interpreting of the loop happens
185186
auto loopBodyWorkItem = static_cast<JsLoopBodyCodeGen*>(this);
186187
loopBodyWorkItem->loopHeader->ResetInterpreterCount();
187-
loopBodyWorkItem->GetEntryPoint()->Reset();
188+
loopBodyWorkItem->GetEntryPoint()->Reset(true);
188189
HeapDelete(loopBodyWorkItem);
189190
}
190191
else
@@ -207,15 +208,19 @@ void CodeGenWorkItem::OnWorkItemProcessFail(NativeCodeGenerator* codeGen)
207208
#endif
208209

209210
#if PDATA_ENABLED & defined(_WIN32)
210-
if (this->entryPointInfo && this->entryPointInfo->GetXDataInfo())
211+
if (this->entryPointInfo)
211212
{
212-
void* functionTable = this->entryPointInfo->GetXDataInfo()->functionTable;
213-
if (functionTable)
213+
XDataAllocation * xdataAllocation = this->entryPointInfo->GetNativeEntryPointData()->GetXDataInfo();
214+
if (xdataAllocation)
214215
{
215-
if (!DelayDeletingFunctionTable::AddEntry(functionTable))
216+
void* functionTable = xdataAllocation->functionTable;
217+
if (functionTable)
216218
{
217-
PHASE_PRINT_TESTTRACE1(Js::XDataPhase, _u("OnWorkItemProcessFail: Failed to add to slist, table: %llx\n"), functionTable);
218-
DelayDeletingFunctionTable::DeleteFunctionTable(functionTable);
219+
if (!DelayDeletingFunctionTable::AddEntry(functionTable))
220+
{
221+
PHASE_PRINT_TESTTRACE1(Js::XDataPhase, _u("OnWorkItemProcessFail: Failed to add to slist, table: %llx\n"), functionTable);
222+
DelayDeletingFunctionTable::DeleteFunctionTable(functionTable);
223+
}
219224
}
220225
}
221226
}

lib/Backend/Encoder.cpp

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
//-------------------------------------------------------------------------------------------------------
55
#include "Backend.h"
66
#include "Core/CRC.h"
7+
#include "NativeEntryPointData.h"
8+
#include "JitTransferData.h"
79

810
///----------------------------------------------------------------------------
911
///
@@ -74,8 +76,8 @@ Encoder::Encode()
7476
#endif
7577

7678
m_pc = m_encodeBuffer;
77-
m_inlineeFrameMap = Anew(m_tempAlloc, InlineeFrameMap, m_tempAlloc);
78-
m_bailoutRecordMap = Anew(m_tempAlloc, BailoutRecordMap, m_tempAlloc);
79+
m_inlineeFrameMap = Anew(m_tempAlloc, ArenaInlineeFrameMap, m_tempAlloc);
80+
m_bailoutRecordMap = Anew(m_tempAlloc, ArenaBailoutRecordMap, m_tempAlloc);
7981

8082
IR::PragmaInstr* pragmaInstr = nullptr;
8183
uint32 pragmaOffsetInBuffer = 0;
@@ -435,7 +437,7 @@ Encoder::Encode()
435437
else
436438
{
437439
XDataAllocator::Register(&allocation->xdata, m_func->GetJITOutput()->GetCodeAddress(), (DWORD)m_func->GetJITOutput()->GetCodeSize());
438-
m_func->GetInProcJITEntryPointInfo()->SetXDataInfo(&allocation->xdata);
440+
m_func->GetInProcJITEntryPointInfo()->GetNativeEntryPointData()->SetXDataInfo(&allocation->xdata);
439441
}
440442
m_func->GetJITOutput()->SetCodeAddress(m_func->GetJITOutput()->GetCodeAddress() | 0x1); // Set thumb mode
441443
#endif
@@ -447,7 +449,7 @@ Encoder::Encode()
447449
{
448450
if (!m_func->IsOOPJIT()) // in-proc JIT
449451
{
450-
m_func->GetInProcJITEntryPointInfo()->RecordInlineeFrameMap(m_inlineeFrameMap);
452+
m_func->GetInProcJITEntryPointInfo()->GetInProcNativeEntryPointData()->RecordInlineeFrameMap(m_inlineeFrameMap);
451453
}
452454
else // OOP JIT
453455
{
@@ -472,7 +474,7 @@ Encoder::Encode()
472474

473475
if (this->m_bailoutRecordMap->Count() > 0)
474476
{
475-
m_func->GetInProcJITEntryPointInfo()->RecordBailOutMap(m_bailoutRecordMap);
477+
m_func->GetInProcJITEntryPointInfo()->GetInProcNativeEntryPointData()->RecordBailOutMap(m_bailoutRecordMap);
476478
}
477479

478480
if (this->m_func->pinnedTypeRefs != nullptr)
@@ -492,7 +494,6 @@ Encoder::Encode()
492494

493495
pinnedTypeRefs->count = pinnedTypeRefCount;
494496
pinnedTypeRefs->isOOPJIT = true;
495-
this->m_func->GetJITOutput()->GetOutputData()->pinnedTypeRefs = pinnedTypeRefs;
496497
}
497498
else
498499
{
@@ -515,10 +516,7 @@ Encoder::Encode()
515516
Output::Flush();
516517
}
517518

518-
if (!this->m_func->IsOOPJIT())
519-
{
520-
m_func->GetInProcJITEntryPointInfo()->GetJitTransferData()->SetRuntimeTypeRefs(pinnedTypeRefs);
521-
}
519+
this->m_func->GetJITOutput()->GetOutputData()->pinnedTypeRefs = pinnedTypeRefs;
522520
}
523521

524522
// Save all equivalent type guards in a fixed size array on the JIT transfer data
@@ -642,7 +640,7 @@ Encoder::Encode()
642640

643641
Assert(reinterpret_cast<char*>(dstEntry) <= reinterpret_cast<char*>(typeGuardTransferRecord) + typeGuardTransferSize + sizeof(Js::TypeGuardTransferEntry));
644642

645-
m_func->GetInProcJITEntryPointInfo()->RecordTypeGuards(this->m_func->indexedPropertyGuardCount, typeGuardTransferRecord, typeGuardTransferSize);
643+
m_func->GetInProcJITEntryPointInfo()->GetJitTransferData()->RecordTypeGuards(this->m_func->indexedPropertyGuardCount, typeGuardTransferRecord, typeGuardTransferSize);
646644
}
647645
else
648646
{
@@ -730,7 +728,7 @@ Encoder::Encode()
730728
}
731729
else
732730
{
733-
Assert(m_func->GetInProcJITEntryPointInfo()->GetConstructorCacheCount() > 0);
731+
Assert(m_func->GetInProcJITEntryPointInfo()->GetNativeEntryPointData()->GetConstructorCacheCount() > 0);
734732

735733
size_t ctorCachesTransferSize = // Reserve enough room for:
736734
propertyCount * sizeof(Js::CtorCacheGuardTransferEntry) + // each propertyId,
@@ -763,7 +761,7 @@ Encoder::Encode()
763761

764762
Assert(reinterpret_cast<char*>(dstEntry) <= reinterpret_cast<char*>(ctorCachesTransferRecord) + ctorCachesTransferSize + sizeof(Js::CtorCacheGuardTransferEntry));
765763

766-
m_func->GetInProcJITEntryPointInfo()->RecordCtorCacheGuards(ctorCachesTransferRecord, ctorCachesTransferSize);
764+
m_func->GetInProcJITEntryPointInfo()->GetJitTransferData()->RecordCtorCacheGuards(ctorCachesTransferRecord, ctorCachesTransferSize);
767765
}
768766
}
769767
m_func->GetJITOutput()->FinalizeNativeCode();
@@ -1413,7 +1411,7 @@ void Encoder::CopyMaps(OffsetList **m_origInlineeFrameRecords
14131411
)
14141412
{
14151413
InlineeFrameRecords *recList = m_inlineeFrameRecords;
1416-
InlineeFrameMap *mapList = m_inlineeFrameMap;
1414+
ArenaInlineeFrameMap *mapList = m_inlineeFrameMap;
14171415
PragmaInstrList *pInstrList = m_pragmaInstrToRecordOffset;
14181416

14191417
OffsetList *origRecList, *origMapList, *origPInstrList;

lib/Backend/Encoder.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
///
1212
///---------------------------------------------------------------------------
1313

14-
typedef JsUtil::List<NativeOffsetInlineeFramePair, ArenaAllocator> InlineeFrameMap;
14+
typedef JsUtil::List<NativeOffsetInlineeFramePair, ArenaAllocator> ArenaInlineeFrameMap;
1515
typedef JsUtil::List<IR::PragmaInstr*, ArenaAllocator> PragmaInstrList;
1616
typedef JsUtil::List<uint32, ArenaAllocator> OffsetList;
1717
typedef JsUtil::List<BranchJumpTableWrapper*, ArenaAllocator> JmpTableList;
@@ -35,11 +35,11 @@ class Encoder
3535
uint32 m_encodeBufferSize;
3636
ArenaAllocator *m_tempAlloc;
3737

38-
InlineeFrameMap* m_inlineeFrameMap;
38+
ArenaInlineeFrameMap* m_inlineeFrameMap;
3939
uint32 m_inlineeFrameMapDataOffset;
4040
uint32 m_inlineeFrameMapRecordCount;
41-
typedef JsUtil::List<LazyBailOutRecord, ArenaAllocator> BailoutRecordMap;
42-
BailoutRecordMap* m_bailoutRecordMap;
41+
typedef JsUtil::List<LazyBailOutRecord, ArenaAllocator> ArenaBailoutRecordMap;
42+
ArenaBailoutRecordMap* m_bailoutRecordMap;
4343
#if DBG_DUMP
4444
void DumpInlineeFrameMap(size_t baseAddress);
4545
uint32 * m_offsetBuffer;

lib/Backend/JITOutput.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
//-------------------------------------------------------------------------------------------------------
55

66
#include "Backend.h"
7+
#include "NativeEntryPointData.h"
8+
#include "JitTransferData.h"
79

810
JITOutput::JITOutput(JITOutputIDL * outputData) :
911
m_outputData(outputData),
@@ -267,11 +269,11 @@ JITOutput::FinalizeNativeCode()
267269
#endif
268270
{
269271
m_func->GetInProcCodeGenAllocators()->emitBufferManager.CompletePreviousAllocation(m_inProcAlloc);
270-
m_func->GetInProcJITEntryPointInfo()->SetInProcJITNativeCodeData(m_func->GetNativeCodeDataAllocator()->Finalize());
272+
m_func->GetInProcJITEntryPointInfo()->GetInProcNativeEntryPointData()->SetNativeCodeData(m_func->GetNativeCodeDataAllocator()->Finalize());
271273
m_func->GetInProcJITEntryPointInfo()->GetJitTransferData()->SetRawData(m_func->GetTransferDataAllocator()->Finalize());
272274
#if !FLOATVAR
273275
CodeGenNumberChunk * numberChunks = m_func->GetNumberAllocator()->Finalize();
274-
m_func->GetInProcJITEntryPointInfo()->SetNumberChunks(numberChunks);
276+
m_func->GetInProcJITEntryPointInfo()->GetInProcNativeEntryPointData()->SetNumberChunks(numberChunks);
275277
#endif
276278

277279
#if defined(_CONTROL_FLOW_GUARD) && !defined(_M_ARM)

lib/Backend/JitTransferData.cpp

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
//-------------------------------------------------------------------------------------------------------
2+
// Copyright (C) Microsoft. All rights reserved.
3+
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
4+
//-------------------------------------------------------------------------------------------------------
5+
#include "Backend.h"
6+
#include "JitTransferData.h"
7+
8+
using namespace Js;
9+
10+
void JitTransferData::AddJitTimeTypeRef(void* typeRef, Recycler* recycler)
11+
{
12+
Assert(typeRef != nullptr);
13+
EnsureJitTimeTypeRefs(recycler);
14+
this->jitTimeTypeRefs->AddNew(typeRef);
15+
}
16+
17+
void JitTransferData::EnsureJitTimeTypeRefs(Recycler* recycler)
18+
{
19+
if (this->jitTimeTypeRefs == nullptr)
20+
{
21+
this->jitTimeTypeRefs = RecyclerNew(recycler, TypeRefSet, recycler);
22+
}
23+
}
24+
25+
void JitTransferData::RecordTypeGuards(int typeGuardCount, TypeGuardTransferEntry* typeGuardTransferRecord, size_t typeGuardTransferPlusSize)
26+
{
27+
this->propertyGuardCount = typeGuardCount;
28+
this->propertyGuardsByPropertyId = typeGuardTransferRecord;
29+
this->propertyGuardsByPropertyIdPlusSize = typeGuardTransferPlusSize;
30+
}
31+
32+
void JitTransferData::RecordCtorCacheGuards(CtorCacheGuardTransferEntry* ctorCacheTransferRecord, size_t ctorCacheTransferPlusSize)
33+
{
34+
this->ctorCacheGuardsByPropertyId = ctorCacheTransferRecord;
35+
this->ctorCacheGuardsByPropertyIdPlusSize = ctorCacheTransferPlusSize;
36+
}
37+
38+
39+
void JitTransferData::Cleanup()
40+
{
41+
// This dictionary is recycler allocated so it doesn't need to be explicitly freed.
42+
this->jitTimeTypeRefs = nullptr;
43+
44+
if (this->lazyBailoutProperties != nullptr)
45+
{
46+
HeapDeleteArray(this->lazyBailoutPropertyCount, this->lazyBailoutProperties);
47+
this->lazyBailoutProperties = nullptr;
48+
}
49+
50+
// All structures below are heap allocated and need to be freed explicitly.
51+
if (this->runtimeTypeRefs != nullptr)
52+
{
53+
if (this->runtimeTypeRefs->isOOPJIT)
54+
{
55+
midl_user_free(this->runtimeTypeRefs);
56+
}
57+
else
58+
{
59+
HeapDeletePlus(offsetof(PinnedTypeRefsIDL, typeRefs) + sizeof(void*)*this->runtimeTypeRefs->count - sizeof(PinnedTypeRefsIDL),
60+
PointerValue(this->runtimeTypeRefs));
61+
}
62+
this->runtimeTypeRefs = nullptr;
63+
}
64+
65+
if (this->propertyGuardsByPropertyId != nullptr)
66+
{
67+
HeapDeletePlus(this->propertyGuardsByPropertyIdPlusSize, this->propertyGuardsByPropertyId);
68+
this->propertyGuardsByPropertyId = nullptr;
69+
}
70+
this->propertyGuardCount = 0;
71+
this->propertyGuardsByPropertyIdPlusSize = 0;
72+
73+
if (this->ctorCacheGuardsByPropertyId != nullptr)
74+
{
75+
HeapDeletePlus(this->ctorCacheGuardsByPropertyIdPlusSize, this->ctorCacheGuardsByPropertyId);
76+
this->ctorCacheGuardsByPropertyId = nullptr;
77+
}
78+
this->ctorCacheGuardsByPropertyIdPlusSize = 0;
79+
80+
if (this->equivalentTypeGuards != nullptr)
81+
{
82+
HeapDeleteArray(this->equivalentTypeGuardCount, this->equivalentTypeGuards);
83+
this->equivalentTypeGuards = nullptr;
84+
}
85+
this->equivalentTypeGuardCount = 0;
86+
87+
if (this->jitTransferRawData != nullptr)
88+
{
89+
HeapDelete(this->jitTransferRawData);
90+
this->jitTransferRawData = nullptr;
91+
}
92+
93+
if (this->equivalentTypeGuardOffsets)
94+
{
95+
midl_user_free(this->equivalentTypeGuardOffsets);
96+
}
97+
98+
if (this->typeGuardTransferData.entries != nullptr)
99+
{
100+
auto next = &this->typeGuardTransferData.entries;
101+
while (*next)
102+
{
103+
auto current = (*next);
104+
*next = (*next)->next;
105+
midl_user_free(current);
106+
}
107+
}
108+
109+
if (this->ctorCacheTransferData.entries != nullptr)
110+
{
111+
CtorCacheTransferEntryIDL ** entries = this->ctorCacheTransferData.entries;
112+
for (uint i = 0; i < this->ctorCacheTransferData.ctorCachesCount; ++i)
113+
{
114+
midl_user_free(entries[i]);
115+
}
116+
midl_user_free(entries);
117+
}
118+
}

0 commit comments

Comments
 (0)