Skip to content

Commit 92ce4fc

Browse files
committed
Use smaller data type to represent the counter fields of FunctionBody.
Most of the counters has value less than 256, use single byte to hold them. And can promote to short or full 32 bit integer when necessary.
1 parent 09eea22 commit 92ce4fc

18 files changed

+865
-357
lines changed

lib/Backend/BailOut.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1433,8 +1433,8 @@ BailOutRecord::BailOutHelper(Js::JavascriptCallStackLayout * layout, Js::ScriptF
14331433
memset(newInstance->m_localSlots + constantCount, 0, varCount * sizeof(Js::Var));
14341434
}
14351435

1436-
Js::RegSlot localFrameDisplayReg = executeFunction->GetLocalFrameDisplayReg();
1437-
Js::RegSlot localClosureReg = executeFunction->GetLocalClosureReg();
1436+
Js::RegSlot localFrameDisplayReg = executeFunction->GetLocalFrameDisplayRegister();
1437+
Js::RegSlot localClosureReg = executeFunction->GetLocalClosureRegister();
14381438

14391439
if (!isInlinee)
14401440
{
@@ -1503,7 +1503,7 @@ BailOutRecord::BailOutHelper(Js::JavascriptCallStackLayout * layout, Js::ScriptF
15031503
uint32 innerScopeCount = executeFunction->GetInnerScopeCount();
15041504
for (uint32 i = 0; i < innerScopeCount; i++)
15051505
{
1506-
Js::RegSlot reg = executeFunction->FirstInnerScopeReg() + i;
1506+
Js::RegSlot reg = executeFunction->GetFirstInnerScopeRegister() + i;
15071507
newInstance->SetInnerScopeFromIndex(i, newInstance->GetNonVarReg(reg));
15081508
newInstance->SetNonVarReg(reg, nullptr);
15091509
}

lib/Backend/CodeGenWorkItem.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ struct JsFunctionCodeGen sealed : public CodeGenWorkItem
279279

280280
uint GetInterpretedCount() const override
281281
{
282-
return this->functionBody->interpretedCount;
282+
return this->functionBody->GetInterpretedCount();
283283
}
284284

285285
void Delete() override

lib/Backend/Func.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -956,15 +956,15 @@ void Func::InitLocalClosureSyms()
956956
// Allocate stack space for closure pointers. Do this only if we're jitting for stack closures, and
957957
// tell bailout that these are not byte code symbols so that we don't try to encode them in the bailout record,
958958
// as they don't have normal lifetimes.
959-
Js::RegSlot regSlot = this->GetJnFunction()->GetLocalClosureReg();
959+
Js::RegSlot regSlot = this->GetJnFunction()->GetLocalClosureRegister();
960960
if (regSlot != Js::Constants::NoRegister)
961961
{
962962
this->m_localClosureSym =
963963
StackSym::FindOrCreate(static_cast<SymID>(regSlot),
964964
this->DoStackFrameDisplay() ? (Js::RegSlot)-1 : regSlot,
965965
this);
966966
}
967-
regSlot = this->GetJnFunction()->GetLocalFrameDisplayReg();
967+
regSlot = this->GetJnFunction()->GetLocalFrameDisplayRegister();
968968
if (regSlot != Js::Constants::NoRegister)
969969
{
970970
this->m_localFrameDisplaySym =

lib/Backend/IRBuilder.cpp

Lines changed: 43 additions & 43 deletions
Large diffs are not rendered by default.

lib/Runtime/Base/AuxPtrs.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ namespace Js
5656
static void AllocAuxPtrFix(T* host, uint8 size, Recycler* recycler);
5757
static void AllocAuxPtr(T* host, uint8 count, Recycler* recycler);
5858
static void* GetAuxPtr(const T* host, FieldsEnum e);
59-
static void SetAuxPtr(T* host, FieldsEnum e, void* ptr, Recycler* recycler);
59+
static void SetAuxPtr(T* host, FieldsEnum e, void* ptr);
6060
};
6161

6262

@@ -218,12 +218,14 @@ namespace Js
218218
return host->auxPtrs->Get(e);
219219
}
220220
template<class T, typename FieldsEnum>
221-
void AuxPtrs<T, FieldsEnum>::SetAuxPtr(T* host, FieldsEnum e, void* ptr, Recycler* recycler)
221+
void AuxPtrs<T, FieldsEnum>::SetAuxPtr(T* host, FieldsEnum e, void* ptr)
222222
{
223223
if (ptr == nullptr && GetAuxPtr(host, e) == nullptr)
224224
{
225225
return;
226226
}
227+
Recycler* recycler = host->GetRecycler();
228+
227229
if (host->auxPtrs == nullptr)
228230
{
229231
AuxPtrs<FunctionProxy, FieldsEnum>::AllocAuxPtrFix(host, 16, recycler);

lib/Runtime/Base/Chakra.Runtime.Base.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
</ClCompile>
7070
</ItemGroup>
7171
<ItemGroup>
72+
<ClInclude Include="CompactCounters.h" />
7273
<ClInclude Include="RuntimeBasePch.h" />
7374
<ClInclude Include="AuxPtrs.h" />
7475
<ClInclude Include="CallInfo.h" />

lib/Runtime/Base/CompactCounters.h

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
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+
#pragma once
6+
namespace Js
7+
{
8+
template<class T, typename CountT = T::CounterFields>
9+
struct Counter
10+
{
11+
uint8 fieldSize;
12+
union {
13+
uint8 fields1[1];
14+
uint16 fields2[1];
15+
uint32 fields4[1];
16+
int8 signedFields1[1];
17+
int16 signedFields2[1];
18+
int32 signedFields4[1];
19+
};
20+
21+
22+
Counter(uint8 size)
23+
{
24+
fieldSize = size;
25+
}
26+
27+
static void AllocCounters(T* _this, uint8 newSize);
28+
29+
uint32 Get(CountT typeEnum) const
30+
{
31+
uint8 type = static_cast<uint8>(typeEnum);
32+
if (fieldSize == 1)
33+
{
34+
return this->fields1[type];
35+
}
36+
else if (fieldSize == 2)
37+
{
38+
return this->fields2[type];
39+
}
40+
else
41+
{
42+
Assert(fieldSize == 4);
43+
return this->fields4[type];
44+
}
45+
}
46+
47+
int32 GetSigned(CountT typeEnum) const
48+
{
49+
uint8 type = static_cast<uint8>(typeEnum);
50+
if (fieldSize == 1)
51+
{
52+
return this->signedFields1[type];
53+
}
54+
else if (fieldSize == 2)
55+
{
56+
return this->signedFields2[type];
57+
}
58+
else
59+
{
60+
Assert(fieldSize == 4);
61+
return this->signedFields4[type];
62+
}
63+
}
64+
65+
uint32 Set(CountT typeEnum, uint32 val, T* _this)
66+
{
67+
uint8 type = static_cast<uint8>(typeEnum);
68+
if (fieldSize == 1)
69+
{
70+
if (val <= UINT8_MAX)
71+
{
72+
return fields1[type] = static_cast<uint8>(val);
73+
}
74+
else
75+
{
76+
AllocCounters(_this, val <= UINT16_MAX ? 2 : 4);
77+
}
78+
return _this->counters->Set(typeEnum, val, _this);
79+
}
80+
81+
if (fieldSize == 2)
82+
{
83+
if (val <= UINT16_MAX)
84+
{
85+
return fields2[type] = static_cast<uint16>(val);
86+
}
87+
else
88+
{
89+
AllocCounters(_this, 4);
90+
}
91+
return _this->counters->Set(typeEnum, val, _this);
92+
}
93+
94+
Assert(fieldSize == 4);
95+
return fields4[type] = val;
96+
}
97+
98+
int32 SetSigned(CountT typeEnum, int32 val, T* _this)
99+
{
100+
uint8 type = static_cast<uint8>(typeEnum);
101+
if (fieldSize == 1)
102+
{
103+
if (val <= INT8_MAX && val >= INT8_MIN)
104+
{
105+
return signedFields1[type] = static_cast<uint8>(val);
106+
}
107+
else
108+
{
109+
AllocCounters(_this, (val <= INT16_MAX && val >= INT16_MIN) ? 2 : 4);
110+
}
111+
return _this->counters->SetSigned(typeEnum, val, _this);
112+
}
113+
114+
if (fieldSize == 2)
115+
{
116+
if (val <= INT16_MAX && val >= INT16_MIN)
117+
{
118+
return signedFields2[type] = static_cast<uint16>(val);
119+
}
120+
else
121+
{
122+
AllocCounters(_this, 4);
123+
}
124+
return _this->counters->SetSigned(typeEnum, val, _this);
125+
}
126+
127+
Assert(fieldSize == 4);
128+
return signedFields4[type] = val;
129+
}
130+
131+
uint32 Increase(CountT typeEnum, T* _this)
132+
{
133+
uint8 type = static_cast<uint8>(typeEnum);
134+
if (fieldSize == 1)
135+
{
136+
if (fields1[type] < UINT8_MAX)
137+
{
138+
return fields1[type]++;
139+
}
140+
else
141+
{
142+
AllocCounters(_this, fields1[type] < UINT16_MAX ? 2 : 4);
143+
}
144+
return _this->counters->Increase(typeEnum, _this);
145+
}
146+
147+
if (fieldSize == 2)
148+
{
149+
if (fields1[type] < UINT16_MAX)
150+
{
151+
return fields2[type]++;
152+
}
153+
else
154+
{
155+
AllocCounters(_this, 4);
156+
}
157+
return _this->counters->Increase(typeEnum, _this);
158+
}
159+
160+
Assert(fieldSize == 4);
161+
return fields4[type]++;
162+
}
163+
};
164+
165+
166+
template<class T, typename CountT>
167+
void Counter<T, CountT>::AllocCounters(T* _this, uint8 newSize)
168+
{
169+
typedef Counter<T, CountT> CounterT;
170+
Assert(_this->GetRecycler() != nullptr);
171+
172+
const uint8 signedStart = static_cast<uint8>(CountT::SignedFieldsStart);
173+
const uint8 max = static_cast<uint8>(CountT::Max);
174+
auto plusSize = (max - 1)*newSize;
175+
CounterT* newCounters = RecyclerNewPlusLeafZ(_this->GetRecycler(), plusSize, CounterT, newSize);
176+
177+
if (_this->counters != nullptr)
178+
{
179+
uint8 i = 0;
180+
if (_this->counters->fieldSize == 1)
181+
{
182+
if (newSize == 2)
183+
{
184+
for (; i < signedStart; i++)
185+
{
186+
newCounters->fields2[i] = _this->counters->fields1[i];
187+
}
188+
for (; i < max; i++)
189+
{
190+
newCounters->signedFields2[i] = _this->counters->signedFields1[i];
191+
}
192+
}
193+
else
194+
{
195+
for (; i < signedStart; i++)
196+
{
197+
newCounters->fields4[i] = _this->counters->fields1[i];
198+
}
199+
for (; i < max; i++)
200+
{
201+
newCounters->signedFields4[i] = _this->counters->signedFields1[i];
202+
}
203+
}
204+
}
205+
else if (_this->counters->fieldSize == 2)
206+
{
207+
for (; i < signedStart; i++)
208+
{
209+
newCounters->fields4[i] = _this->counters->fields2[i];
210+
}
211+
for (; i < max; i++)
212+
{
213+
newCounters->signedFields4[i] = _this->counters->signedFields2[i];
214+
}
215+
}
216+
else
217+
{
218+
Assert(false);
219+
}
220+
221+
}
222+
_this->counters = newCounters;
223+
}
224+
}

0 commit comments

Comments
 (0)