Skip to content

Commit 9432774

Browse files
committed
[MERGE #3465 @obastemur] JSONStack: Improve performance
Merge pull request #3465 from obastemur:imp_jsonstack 1% Acme Air LTO gain. Majority of the time, there is at max 1 item on the stacks and SList too expensive to maintain 1item in/out during the whole JSON.stringify
2 parents ff22ab8 + 2e19ab7 commit 9432774

File tree

3 files changed

+85
-6
lines changed

3 files changed

+85
-6
lines changed

lib/Common/DataStructures/SList.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ class FakeCount
1717
void DecrementCount() {}
1818
void SetCount(uint count) {}
1919
void AddCount(FakeCount& c) {}
20+
public:
21+
uint Count() const { return 0; }
2022
};
2123

2224
class RealCount

lib/Runtime/Library/JSONStack.cpp

Lines changed: 76 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,26 @@
66
#include "JSONStack.h"
77
namespace JSON
88
{
9+
#if defined(_JS_VALUE) || (_DOM_VALUE)
10+
#error "Something went wrong!"
11+
#endif
12+
13+
#define _JS_VALUE tempValues[0]
14+
#define _DOM_VALUE tempValues[1]
15+
916
bool StrictEqualsObjectComparer::Equals(Js::Var x, Js::Var y)
1017
{
1118
return JSONStack::Equals(x,y);
1219
}
1320

14-
JSONStack::JSONStack(ArenaAllocator *allocator, Js::ScriptContext *context) : jsObjectStack(allocator), domObjectStack(nullptr), alloc(allocator), scriptContext(context)
21+
JSONStack::JSONStack(ArenaAllocator *allocator, Js::ScriptContext *context)
22+
: jsObjectStack(allocator), domObjectStack(nullptr),
23+
alloc(allocator), scriptContext(context)
1524
{
25+
// most of the time, the size of the stack is 1 object.
26+
// use direct member instead of expensive Push / Pop / Has
27+
_JS_VALUE = nullptr;
28+
_DOM_VALUE = nullptr;
1629
}
1730

1831
bool JSONStack::Equals(Js::Var x, Js::Var y)
@@ -24,10 +37,18 @@ namespace JSON
2437
{
2538
if (bJsObject)
2639
{
40+
if (_JS_VALUE)
41+
{
42+
return (data == _JS_VALUE);
43+
}
2744
return jsObjectStack.Has(data);
2845
}
2946
else if (domObjectStack)
3047
{
48+
if (_DOM_VALUE)
49+
{
50+
return (data == _DOM_VALUE);
51+
}
3152
return domObjectStack->Contains(data);
3253
}
3354
return false;
@@ -37,22 +58,68 @@ namespace JSON
3758
{
3859
if (bJsObject)
3960
{
40-
return jsObjectStack.Push(data);
61+
bool result = true;
62+
if (_JS_VALUE)
63+
{
64+
jsObjectStack.Push(_JS_VALUE);
65+
_JS_VALUE = nullptr;
66+
}
67+
68+
if (jsObjectStack.Count())
69+
{
70+
result = jsObjectStack.Push(data);
71+
}
72+
else
73+
{
74+
_JS_VALUE = data;
75+
}
76+
77+
return result;
4178
}
79+
4280
EnsuresDomObjectStack();
43-
domObjectStack->Add(data);
81+
82+
if (_DOM_VALUE)
83+
{
84+
domObjectStack->Add(_DOM_VALUE);
85+
_DOM_VALUE = nullptr;
86+
}
87+
88+
if (domObjectStack->Count())
89+
{
90+
domObjectStack->Add(data);
91+
}
92+
else
93+
{
94+
_DOM_VALUE = data;
95+
}
4496
return true;
4597
}
4698

4799
void JSONStack::Pop(bool bJsObject)
48100
{
49101
if (bJsObject)
50102
{
51-
jsObjectStack.Pop();
103+
if (_JS_VALUE)
104+
{
105+
_JS_VALUE = nullptr;
106+
}
107+
else
108+
{
109+
jsObjectStack.Pop();
110+
}
52111
return;
53112
}
54113
AssertMsg(domObjectStack != NULL, "Misaligned pop");
55-
domObjectStack->RemoveAtEnd();
114+
115+
if (_DOM_VALUE)
116+
{
117+
_DOM_VALUE = nullptr;
118+
}
119+
else
120+
{
121+
domObjectStack->RemoveAtEnd();
122+
}
56123
}
57124

58125
void JSONStack::EnsuresDomObjectStack(void)
@@ -62,4 +129,7 @@ namespace JSON
62129
domObjectStack = DOMObjectStack::New(alloc);
63130
}
64131
}
65-
}// namespace JSON
132+
} // namespace JSON
133+
134+
#undef _JS_VALUE
135+
#undef _DOM_VALUE

lib/Runtime/Library/JSONStack.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ namespace JSON
1515
class JSONStack
1616
{
1717
private:
18+
Js::Var tempValues[2];
1819
SList<Js::Var> jsObjectStack; // Consider: key-only dictionary here
1920
typedef JsUtil::List<Js::Var, ArenaAllocator, false, Js::CopyRemovePolicy,
2021
SpecializedComparer<Js::Var, JSON::StrictEqualsObjectComparer>::TComparerType> DOMObjectStack;
@@ -31,6 +32,12 @@ namespace JSON
3132
bool Push(Js::Var data, bool bJsObject = true);
3233
void Pop(bool bJsObject = true);
3334

35+
~JSONStack()
36+
{
37+
tempValues[0] = nullptr; // _JS_VALUE
38+
tempValues[1] = nullptr; // _DOM_VALUE
39+
}
40+
3441
private:
3542
void EnsuresDomObjectStack(void);
3643
};

0 commit comments

Comments
 (0)