Skip to content

Commit b7fa63b

Browse files
committed
[MERGE chakra-core#301] Use smaller data type to represent the counter fields of FunctionBody.
Merge pull request chakra-core#301 from leirocks:fb_counters_pr 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.
2 parents 0a55868 + 0cdf521 commit b7fa63b

18 files changed

Lines changed: 939 additions & 376 deletions

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: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,10 +182,9 @@ namespace Js
182182
template<class T, typename FieldsEnum>
183183
void AuxPtrs<T, FieldsEnum>::AllocAuxPtr(T* host, uint8 count)
184184
{
185-
Assert(count >= AuxPtrs32::MaxCount);
186-
187185
Recycler* recycler = host->GetRecycler();
188186
Assert(recycler != nullptr);
187+
Assert(count >= AuxPtrs32::MaxCount);
189188

190189
auto requestSize = sizeof(AuxPtrs<T, FieldsEnum>) + (count - 1)*sizeof(void*);
191190
auto allocSize = ::Math::Align<uint8>((uint8)requestSize, 16);
@@ -218,6 +217,7 @@ namespace Js
218217
template<class T, typename FieldsEnum>
219218
void AuxPtrs<T, FieldsEnum>::SetAuxPtr(T* host, FieldsEnum e, void* ptr)
220219
{
220+
221221
if (host->auxPtrs == nullptr)
222222
{
223223
AuxPtrs<FunctionProxy, FieldsEnum>::AllocAuxPtrFix(host, 16);

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: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
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+
#pragma warning(push)
8+
#pragma warning(disable:6200) // C6200: Index is out of valid index range, compiler complains here we use variable length array
9+
10+
namespace Js
11+
{
12+
template<class T, typename CountT = T::CounterFields>
13+
struct CompactCounters
14+
{
15+
uint8 fieldSize;
16+
#if DBG
17+
mutable bool bgThreadCallStarted;
18+
bool isCleaningUp;
19+
#endif
20+
union {
21+
uint8 u8Fields[CountT::Max];
22+
int8 i8Fields[CountT::Max];
23+
WriteBarrierPtr<uint16> u16Fields;
24+
WriteBarrierPtr<uint32> u32Fields;
25+
WriteBarrierPtr<int16> i16Fields;
26+
WriteBarrierPtr<int32> i32Fields;
27+
};
28+
29+
CompactCounters()
30+
:fieldSize(1)
31+
#if DBG
32+
, bgThreadCallStarted(false), isCleaningUp(false)
33+
#endif
34+
{
35+
memset(u8Fields, 0, (uint8)CountT::Max);
36+
}
37+
38+
void AllocCounters(T* host, uint8 newSize);
39+
40+
uint32 Get(CountT typeEnum) const
41+
{
42+
#if DBG
43+
if (ThreadContext::GetContextForCurrentThread() == nullptr)
44+
{
45+
bgThreadCallStarted = true;
46+
}
47+
#endif
48+
uint8 type = static_cast<uint8>(typeEnum);
49+
uint8 localFieldSize = fieldSize;
50+
uint32 value = 0;
51+
if (localFieldSize == 1)
52+
{
53+
value = this->u8Fields[type];
54+
}
55+
else if (localFieldSize == 2)
56+
{
57+
value = this->u16Fields[type];
58+
}
59+
else
60+
{
61+
Assert(localFieldSize == 4);
62+
value = this->u32Fields[type];
63+
}
64+
65+
return value;
66+
}
67+
68+
int32 GetSigned(CountT typeEnum) const
69+
{
70+
#if DBG
71+
if (ThreadContext::GetContextForCurrentThread() == nullptr)
72+
{
73+
bgThreadCallStarted = true;
74+
}
75+
#endif
76+
77+
uint8 type = static_cast<uint8>(typeEnum);
78+
uint8 localFieldSize = fieldSize;
79+
int32 value = 0;
80+
if (localFieldSize == 1)
81+
{
82+
value = this->i8Fields[type];
83+
}
84+
else if (localFieldSize == 2)
85+
{
86+
value = this->i16Fields[type];
87+
}
88+
else
89+
{
90+
Assert(localFieldSize == 4);
91+
value = this->i32Fields[type];
92+
}
93+
return value;
94+
}
95+
96+
uint32 Set(CountT typeEnum, uint32 val, T* host)
97+
{
98+
Assert(bgThreadCallStarted == false || isCleaningUp == true);
99+
100+
uint8 type = static_cast<uint8>(typeEnum);
101+
if (fieldSize == 1)
102+
{
103+
if (val <= UINT8_MAX)
104+
{
105+
return this->u8Fields[type] = static_cast<uint8>(val);
106+
}
107+
else
108+
{
109+
AllocCounters(host, val <= UINT16_MAX ? 2 : 4);
110+
}
111+
return this->Set(typeEnum, val, host);
112+
}
113+
114+
if (fieldSize == 2)
115+
{
116+
if (val <= UINT16_MAX)
117+
{
118+
return this->u16Fields[type] = static_cast<uint16>(val);
119+
}
120+
else
121+
{
122+
AllocCounters(host, 4);
123+
}
124+
return this->Set(typeEnum, val, host);
125+
}
126+
127+
Assert(fieldSize == 4);
128+
return this->u32Fields[type] = val;
129+
}
130+
131+
int32 SetSigned(CountT typeEnum, int32 val, T* host)
132+
{
133+
Assert(bgThreadCallStarted == false || isCleaningUp == true);
134+
135+
uint8 type = static_cast<uint8>(typeEnum);
136+
if (fieldSize == 1)
137+
{
138+
if (val <= INT8_MAX && val >= INT8_MIN)
139+
{
140+
return this->i8Fields[type] = static_cast<uint8>(val);
141+
}
142+
else
143+
{
144+
AllocCounters(host, (val <= INT16_MAX && val >= INT16_MIN) ? 2 : 4);
145+
}
146+
return this->SetSigned(typeEnum, val, host);
147+
}
148+
149+
if (fieldSize == 2)
150+
{
151+
if (val <= INT16_MAX && val >= INT16_MIN)
152+
{
153+
return this->i16Fields[type] = static_cast<uint16>(val);
154+
}
155+
else
156+
{
157+
AllocCounters(host, 4);
158+
}
159+
return this->SetSigned(typeEnum, val, host);
160+
}
161+
162+
Assert(fieldSize == 4);
163+
return this->i32Fields[type] = val;
164+
}
165+
166+
uint32 Increase(CountT typeEnum, T* host)
167+
{
168+
Assert(bgThreadCallStarted == false);
169+
170+
uint8 type = static_cast<uint8>(typeEnum);
171+
if (fieldSize == 1)
172+
{
173+
if (this->u8Fields[type] < UINT8_MAX)
174+
{
175+
return this->u8Fields[type]++;
176+
}
177+
else
178+
{
179+
AllocCounters(host, 2);
180+
}
181+
return this->Increase(typeEnum, host);
182+
}
183+
184+
if (fieldSize == 2)
185+
{
186+
if (this->u16Fields[type] < UINT16_MAX)
187+
{
188+
return this->u16Fields[type]++;
189+
}
190+
else
191+
{
192+
AllocCounters(host, 4);
193+
}
194+
return this->Increase(typeEnum, host);
195+
}
196+
197+
Assert(fieldSize == 4);
198+
return this->u32Fields[type]++;
199+
}
200+
};
201+
202+
203+
template<class T, typename CountT>
204+
void CompactCounters<T, CountT>::AllocCounters(T* host, uint8 newSize)
205+
{
206+
Assert(ThreadContext::GetContextForCurrentThread() || ThreadContext::GetCriticalSection()->IsLocked());
207+
208+
typedef CompactCounters<T, CountT> CounterT;
209+
Assert(host->GetRecycler() != nullptr);
210+
211+
const uint8 signedStart = static_cast<uint8>(CountT::SignedFieldsStart);
212+
const uint8 max = static_cast<uint8>(CountT::Max);
213+
214+
void* newFieldsArray = nullptr;
215+
if (newSize == 2)
216+
{
217+
newFieldsArray = RecyclerNewArrayLeafZ(host->GetRecycler(), uint16, max);
218+
}
219+
else
220+
{
221+
Assert(newSize == 4);
222+
newFieldsArray = RecyclerNewArrayLeafZ(host->GetRecycler(), uint32, max);
223+
}
224+
225+
uint8 i = 0;
226+
if (this->fieldSize == 1)
227+
{
228+
if (newSize == 2)
229+
{
230+
for (; i < signedStart; i++)
231+
{
232+
((uint16*)newFieldsArray)[i] = this->u8Fields[i];
233+
}
234+
for (; i < max; i++)
235+
{
236+
((int16*)newFieldsArray)[i] = this->i8Fields[i];
237+
}
238+
}
239+
else
240+
{
241+
for (; i < signedStart; i++)
242+
{
243+
((uint32*)newFieldsArray)[i] = this->u8Fields[i];
244+
}
245+
for (; i < max; i++)
246+
{
247+
((int32*)newFieldsArray)[i] = this->i8Fields[i];
248+
}
249+
}
250+
}
251+
else if (this->fieldSize == 2)
252+
{
253+
for (; i < signedStart; i++)
254+
{
255+
((uint32*)newFieldsArray)[i] = this->u16Fields[i];
256+
}
257+
for (; i < max; i++)
258+
{
259+
((int32*)newFieldsArray)[i] = this->i16Fields[i];
260+
}
261+
}
262+
else
263+
{
264+
Assert(false);
265+
}
266+
267+
this->fieldSize = newSize;
268+
this->u16Fields = (uint16*)newFieldsArray;
269+
270+
}
271+
}
272+
273+
#pragma warning(pop)

0 commit comments

Comments
 (0)