Skip to content

Commit 3a15ec4

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 dd8c63b commit 3a15ec4

17 files changed

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

0 commit comments

Comments
 (0)