From bec9475f6fd24ea43596c0ccb6605ab8cc7f58b2 Mon Sep 17 00:00:00 2001 From: Oguz Bastemur Date: Wed, 2 Aug 2017 14:52:40 +0200 Subject: [PATCH 1/2] JSONStack: Improve performance 1% Acme Air LTO gain. Majority of the time, there is at max 1 item on the stacks and SList is too expensive to maintain 1 item in/out during the whole JSON.stringify --- lib/Runtime/Library/JSONStack.cpp | 82 ++++++++++++++++++++++++++++--- lib/Runtime/Library/JSONStack.h | 7 +++ 2 files changed, 83 insertions(+), 6 deletions(-) diff --git a/lib/Runtime/Library/JSONStack.cpp b/lib/Runtime/Library/JSONStack.cpp index 949c9fbd5a0..95fcdfe34fd 100644 --- a/lib/Runtime/Library/JSONStack.cpp +++ b/lib/Runtime/Library/JSONStack.cpp @@ -6,13 +6,26 @@ #include "JSONStack.h" namespace JSON { +#if defined(_JS_VALUE) || (_DOM_VALUE) +#error "Something went wrong!" +#endif + +#define _JS_VALUE tempValues[0] +#define _DOM_VALUE tempValues[1] + bool StrictEqualsObjectComparer::Equals(Js::Var x, Js::Var y) { return JSONStack::Equals(x,y); } - JSONStack::JSONStack(ArenaAllocator *allocator, Js::ScriptContext *context) : jsObjectStack(allocator), domObjectStack(nullptr), alloc(allocator), scriptContext(context) + JSONStack::JSONStack(ArenaAllocator *allocator, Js::ScriptContext *context) + : jsObjectStack(allocator), domObjectStack(nullptr), + alloc(allocator), scriptContext(context) { + // most of the time, the size of the stack is 1 object. + // use direct member instead of expensive Push / Pop / Has + _JS_VALUE = nullptr; + _DOM_VALUE = nullptr; } bool JSONStack::Equals(Js::Var x, Js::Var y) @@ -24,10 +37,18 @@ namespace JSON { if (bJsObject) { + if (_JS_VALUE) + { + return (data == _JS_VALUE); + } return jsObjectStack.Has(data); } else if (domObjectStack) { + if (_DOM_VALUE) + { + return (data == _DOM_VALUE); + } return domObjectStack->Contains(data); } return false; @@ -37,10 +58,41 @@ namespace JSON { if (bJsObject) { - return jsObjectStack.Push(data); + bool result = true; + if (_JS_VALUE) + { + jsObjectStack.Push(_JS_VALUE); + _JS_VALUE = nullptr; + } + + if (jsObjectStack.Count()) + { + result = jsObjectStack.Push(data); + } + else + { + _JS_VALUE = data; + } + + return result; } + EnsuresDomObjectStack(); - domObjectStack->Add(data); + + if (_DOM_VALUE) + { + domObjectStack->Add(_DOM_VALUE); + _DOM_VALUE = nullptr; + } + + if (domObjectStack->Count()) + { + domObjectStack->Add(data); + } + else + { + _DOM_VALUE = data; + } return true; } @@ -48,11 +100,26 @@ namespace JSON { if (bJsObject) { - jsObjectStack.Pop(); + if (_JS_VALUE) + { + _JS_VALUE = nullptr; + } + else + { + jsObjectStack.Pop(); + } return; } AssertMsg(domObjectStack != NULL, "Misaligned pop"); - domObjectStack->RemoveAtEnd(); + + if (_DOM_VALUE) + { + _DOM_VALUE = nullptr; + } + else + { + domObjectStack->RemoveAtEnd(); + } } void JSONStack::EnsuresDomObjectStack(void) @@ -62,4 +129,7 @@ namespace JSON domObjectStack = DOMObjectStack::New(alloc); } } -}// namespace JSON +} // namespace JSON + +#undef _JS_VALUE +#undef _DOM_VALUE diff --git a/lib/Runtime/Library/JSONStack.h b/lib/Runtime/Library/JSONStack.h index 55aacface5d..ec713b35eb4 100644 --- a/lib/Runtime/Library/JSONStack.h +++ b/lib/Runtime/Library/JSONStack.h @@ -15,6 +15,7 @@ namespace JSON class JSONStack { private: + Js::Var tempValues[2]; SList jsObjectStack; // Consider: key-only dictionary here typedef JsUtil::List::TComparerType> DOMObjectStack; @@ -31,6 +32,12 @@ namespace JSON bool Push(Js::Var data, bool bJsObject = true); void Pop(bool bJsObject = true); + ~JSONStack() + { + tempValues[0] = nullptr; // _JS_VALUE + tempValues[1] = nullptr; // _DOM_VALUE + } + private: void EnsuresDomObjectStack(void); }; From 2e19ab70886eb08b645df3ec3603206da112753b Mon Sep 17 00:00:00 2001 From: Oguz Bastemur Date: Wed, 2 Aug 2017 14:54:07 +0200 Subject: [PATCH 2/2] SList: Add missing function Count to FakeCount --- lib/Common/DataStructures/SList.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/Common/DataStructures/SList.h b/lib/Common/DataStructures/SList.h index 81d3fc270f3..f1f1ce28b89 100644 --- a/lib/Common/DataStructures/SList.h +++ b/lib/Common/DataStructures/SList.h @@ -17,6 +17,8 @@ class FakeCount void DecrementCount() {} void SetCount(uint count) {} void AddCount(FakeCount& c) {} +public: + uint Count() const { return 0; } }; class RealCount