-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[llvm][mustache] Use BumpPtrAllocator to save ASTNodes #159194
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-llvm-support @llvm/pr-subscribers-clang-tools-extra Author: Paul Kirth (ilovepi) ChangesWe make the Mustache ASTNodes usable in the arena by first removing all Additionally, update clang-doc APIs to use the new interfaces. Future work can make better use of Twine interfaces to help avoid any Patch is 85.76 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/159194.diff 5 Files Affected:
diff --git a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp
index 1ab40aacbfe09..1ff691e46fa02 100644
--- a/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp
+++ b/clang-tools-extra/clang-doc/HTMLMustacheGenerator.cpp
@@ -46,7 +46,13 @@ class MustacheHTMLGenerator : public Generator {
const ClangDocContext &CDCtx) override;
};
-class MustacheTemplateFile : public Template {
+class MustacheTemplateFile {
+ BumpPtrAllocator Allocator;
+ StringSaver Saver;
+ MustacheContext Ctx;
+ Template T;
+ std::unique_ptr<MemoryBuffer> Buffer;
+
public:
static Expected<std::unique_ptr<MustacheTemplateFile>>
createMustacheFile(StringRef FileName) {
@@ -54,10 +60,7 @@ class MustacheTemplateFile : public Template {
MemoryBuffer::getFile(FileName);
if (auto EC = BufferOrError.getError())
return createFileOpenError(FileName, EC);
-
- std::unique_ptr<MemoryBuffer> Buffer = std::move(BufferOrError.get());
- StringRef FileContent = Buffer->getBuffer();
- return std::make_unique<MustacheTemplateFile>(FileContent);
+ return std::make_unique<MustacheTemplateFile>(std::move(BufferOrError.get()));
}
Error registerPartialFile(StringRef Name, StringRef FileName) {
@@ -68,11 +71,15 @@ class MustacheTemplateFile : public Template {
std::unique_ptr<MemoryBuffer> Buffer = std::move(BufferOrError.get());
StringRef FileContent = Buffer->getBuffer();
- registerPartial(Name.str(), FileContent.str());
+ T.registerPartial(Name.str(), FileContent.str());
return Error::success();
}
- MustacheTemplateFile(StringRef TemplateStr) : Template(TemplateStr) {}
+ void render(json::Value &V, raw_ostream &OS) { T.render(V, OS); }
+
+ MustacheTemplateFile(std::unique_ptr<MemoryBuffer> &&B)
+ : Saver(Allocator), Ctx(Allocator, Saver),
+ T(B->getBuffer(), Ctx), Buffer(std::move(B)) {}
};
static std::unique_ptr<MustacheTemplateFile> NamespaceTemplate = nullptr;
diff --git a/llvm/include/llvm/Support/Mustache.h b/llvm/include/llvm/Support/Mustache.h
index ee9f40638fd12..83047f2aafff6 100644
--- a/llvm/include/llvm/Support/Mustache.h
+++ b/llvm/include/llvm/Support/Mustache.h
@@ -71,6 +71,8 @@
#include "Error.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/ilist.h"
+#include "llvm/ADT/ilist_node.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/JSON.h"
@@ -84,10 +86,15 @@ using Lambda = std::function<llvm::json::Value()>;
using SectionLambda = std::function<llvm::json::Value(std::string)>;
class ASTNode;
-using AstPtr = std::unique_ptr<ASTNode>;
+using AstPtr = ASTNode *;
using EscapeMap = DenseMap<char, std::string>;
+using ASTNodeList = iplist<ASTNode>;
struct MustacheContext {
+ MustacheContext(BumpPtrAllocator &Allocator, StringSaver &Saver)
+ : Allocator(Allocator), Saver(Saver) {}
+ BumpPtrAllocator &Allocator;
+ StringSaver &Saver;
StringMap<AstPtr> Partials;
StringMap<Lambda> Lambdas;
StringMap<SectionLambda> SectionLambdas;
@@ -98,7 +105,7 @@ struct MustacheContext {
// and Lambdas that are registered with it.
class Template {
public:
- LLVM_ABI Template(StringRef TemplateStr);
+ LLVM_ABI Template(StringRef TemplateStr, MustacheContext &Ctx);
Template(const Template &) = delete;
@@ -110,7 +117,7 @@ class Template {
// type.
LLVM_ABI ~Template();
- LLVM_ABI Template &operator=(Template &&Other) noexcept;
+ Template &operator=(Template &&) = delete;
LLVM_ABI void render(const llvm::json::Value &Data, llvm::raw_ostream &OS);
@@ -126,7 +133,7 @@ class Template {
LLVM_ABI void overrideEscapeCharacters(DenseMap<char, std::string> Escapes);
private:
- MustacheContext Ctx;
+ MustacheContext &Ctx;
AstPtr Tree;
};
} // namespace llvm::mustache
diff --git a/llvm/lib/Support/Mustache.cpp b/llvm/lib/Support/Mustache.cpp
index 6dab658ea535d..c17c2fba323d4 100644
--- a/llvm/lib/Support/Mustache.cpp
+++ b/llvm/lib/Support/Mustache.cpp
@@ -21,7 +21,7 @@ using namespace llvm::mustache;
namespace {
-using Accessor = SmallVector<std::string>;
+using Accessor = ArrayRef<StringRef>;
static bool isFalsey(const json::Value &V) {
return V.getAsNull() || (V.getAsBoolean() && !V.getAsBoolean().value()) ||
@@ -35,23 +35,32 @@ static bool isContextFalsey(const json::Value *V) {
return isFalsey(*V);
}
-static Accessor splitMustacheString(StringRef Str) {
+static Accessor splitMustacheString(StringRef Str, MustacheContext &Ctx) {
// We split the mustache string into an accessor.
// For example:
// "a.b.c" would be split into {"a", "b", "c"}
// We make an exception for a single dot which
// refers to the current context.
- Accessor Tokens;
+ SmallVector<StringRef> Tokens;
if (Str == ".") {
- Tokens.emplace_back(Str);
- return Tokens;
- }
- while (!Str.empty()) {
- StringRef Part;
- std::tie(Part, Str) = Str.split(".");
- Tokens.emplace_back(Part.trim());
+ // "." is a special accessor that refers to the current context.
+ // It's a literal, so it doesn't need to be saved.
+ Tokens.push_back(".");
+ } else {
+ while (!Str.empty()) {
+ StringRef Part;
+ std::tie(Part, Str) = Str.split('.');
+ // Each part of the accessor needs to be saved to the arena
+ // to ensure it has a stable address.
+ Tokens.push_back(Ctx.Saver.save(Part.trim()));
+ }
}
- return Tokens;
+ // Now, allocate memory for the array of StringRefs in the arena.
+ StringRef *ArenaTokens = Ctx.Allocator.Allocate<StringRef>(Tokens.size());
+ // Copy the StringRefs from the stack vector to the arena.
+ std::copy(Tokens.begin(), Tokens.end(), ArenaTokens);
+ // Return an ArrayRef pointing to the stable arena memory.
+ return ArrayRef<StringRef>(ArenaTokens, Tokens.size());
}
} // namespace
@@ -98,23 +107,23 @@ class Token {
SetDelimiter,
};
- Token(std::string Str)
- : TokenType(Type::Text), RawBody(std::move(Str)), TokenBody(RawBody),
+ Token(StringRef Str)
+ : TokenType(Type::Text), RawBody(Str), TokenBody(RawBody),
AccessorValue({}), Indentation(0) {};
- Token(std::string RawBody, std::string TokenBody, char Identifier)
- : RawBody(std::move(RawBody)), TokenBody(std::move(TokenBody)),
- Indentation(0) {
+ Token(StringRef RawBody, StringRef TokenBody, char Identifier,
+ MustacheContext &Ctx)
+ : RawBody(RawBody), TokenBody(TokenBody), Indentation(0) {
TokenType = getTokenType(Identifier);
if (TokenType == Type::Comment)
return;
StringRef AccessorStr(this->TokenBody);
if (TokenType != Type::Variable)
AccessorStr = AccessorStr.substr(1);
- AccessorValue = splitMustacheString(StringRef(AccessorStr).trim());
+ AccessorValue = splitMustacheString(StringRef(AccessorStr).trim(), Ctx);
}
- Accessor getAccessor() const { return AccessorValue; }
+ ArrayRef<StringRef> getAccessor() const { return AccessorValue; }
Type getType() const { return TokenType; }
@@ -145,16 +154,16 @@ class Token {
Type TokenType;
// RawBody is the original string that was tokenized.
- std::string RawBody;
+ StringRef RawBody;
// TokenBody is the original string with the identifier removed.
- std::string TokenBody;
- Accessor AccessorValue;
+ StringRef TokenBody;
+ ArrayRef<StringRef> AccessorValue;
size_t Indentation;
};
using EscapeMap = DenseMap<char, std::string>;
-class ASTNode {
+class ASTNode : public ilist_node<ASTNode> {
public:
enum Type {
Root,
@@ -169,18 +178,19 @@ class ASTNode {
ASTNode(MustacheContext &Ctx)
: Ctx(Ctx), Ty(Type::Root), Parent(nullptr), ParentContext(nullptr) {}
- ASTNode(MustacheContext &Ctx, std::string Body, ASTNode *Parent)
- : Ctx(Ctx), Ty(Type::Text), Body(std::move(Body)), Parent(Parent),
+ ASTNode(MustacheContext &Ctx, StringRef Body, ASTNode *Parent)
+ : Ctx(Ctx), Ty(Type::Text), Body(Body), Parent(Parent),
ParentContext(nullptr) {}
// Constructor for Section/InvertSection/Variable/UnescapeVariable Nodes
- ASTNode(MustacheContext &Ctx, Type Ty, Accessor Accessor, ASTNode *Parent)
- : Ctx(Ctx), Ty(Ty), Parent(Parent), AccessorValue(std::move(Accessor)),
+ ASTNode(MustacheContext &Ctx, Type Ty, ArrayRef<StringRef> Accessor,
+ ASTNode *Parent)
+ : Ctx(Ctx), Ty(Ty), Parent(Parent), AccessorValue(Accessor),
ParentContext(nullptr) {}
- void addChild(AstPtr Child) { Children.emplace_back(std::move(Child)); };
+ void addChild(AstPtr Child) { Children.push_back(Child); };
- void setRawBody(std::string NewBody) { RawBody = std::move(NewBody); };
+ void setRawBody(StringRef NewBody) { RawBody = NewBody; };
void setIndentation(size_t NewIndentation) { Indentation = NewIndentation; };
@@ -213,28 +223,27 @@ class ASTNode {
MustacheContext &Ctx;
Type Ty;
size_t Indentation = 0;
- std::string RawBody;
- std::string Body;
+ StringRef RawBody;
+ StringRef Body;
ASTNode *Parent;
- // TODO: switch implementation to SmallVector<T>
- std::vector<AstPtr> Children;
- const Accessor AccessorValue;
+ ASTNodeList Children;
+ const ArrayRef<StringRef> AccessorValue;
const llvm::json::Value *ParentContext;
};
// A wrapper for arena allocator for ASTNodes
static AstPtr createRootNode(MustacheContext &Ctx) {
- return std::make_unique<ASTNode>(Ctx);
+ return new (Ctx.Allocator.Allocate<ASTNode>()) ASTNode(Ctx);
}
-static AstPtr createNode(MustacheContext &Ctx, ASTNode::Type T, Accessor A,
- ASTNode *Parent) {
- return std::make_unique<ASTNode>(Ctx, T, std::move(A), Parent);
+static AstPtr createNode(MustacheContext &Ctx, ASTNode::Type T,
+ ArrayRef<StringRef> A, ASTNode *Parent) {
+ return new (Ctx.Allocator.Allocate<ASTNode>()) ASTNode(Ctx, T, A, Parent);
}
-static AstPtr createTextNode(MustacheContext &Ctx, std::string Body,
+static AstPtr createTextNode(MustacheContext &Ctx, StringRef Body,
ASTNode *Parent) {
- return std::make_unique<ASTNode>(Ctx, std::move(Body), Parent);
+ return new (Ctx.Allocator.Allocate<ASTNode>()) ASTNode(Ctx, Body, Parent);
}
// Function to check if there is meaningful text behind.
@@ -296,9 +305,9 @@ static void stripTokenAhead(SmallVectorImpl<Token> &Tokens, size_t Idx) {
StringRef NextTokenBody = NextToken.TokenBody;
// Cut off the leading newline which could be \n or \r\n.
if (NextTokenBody.starts_with("\r\n"))
- NextToken.TokenBody = NextTokenBody.substr(2).str();
+ NextToken.TokenBody = NextTokenBody.substr(2);
else if (NextTokenBody.starts_with("\n"))
- NextToken.TokenBody = NextTokenBody.substr(1).str();
+ NextToken.TokenBody = NextTokenBody.substr(1);
}
// Adjust previous token body if there no text behind.
@@ -315,7 +324,7 @@ static void stripTokenBefore(SmallVectorImpl<Token> &Tokens, size_t Idx,
StringRef PrevTokenBody = PrevToken.TokenBody;
StringRef Unindented = PrevTokenBody.rtrim(" \r\t\v");
size_t Indentation = PrevTokenBody.size() - Unindented.size();
- PrevToken.TokenBody = Unindented.str();
+ PrevToken.TokenBody = Unindented;
CurrentToken.setIndentation(Indentation);
}
@@ -405,21 +414,20 @@ static Tag findNextTag(StringRef Template, size_t StartPos, StringRef Open,
}
static std::optional<std::pair<StringRef, StringRef>>
-processTag(const Tag &T, SmallVectorImpl<Token> &Tokens) {
+processTag(const Tag &T, SmallVectorImpl<Token> &Tokens, MustacheContext &Ctx) {
LLVM_DEBUG(dbgs() << "[Tag] " << T.FullMatch << ", Content: " << T.Content
<< ", Kind: " << tagKindToString(T.TagKind) << "\n");
if (T.TagKind == Tag::Kind::Triple) {
- Tokens.emplace_back(T.FullMatch.str(), "&" + T.Content.str(), '&');
+ Tokens.emplace_back(T.FullMatch, Ctx.Saver.save("&" + T.Content), '&', Ctx);
return std::nullopt;
}
StringRef Interpolated = T.Content;
- std::string RawBody = T.FullMatch.str();
if (!Interpolated.trim().starts_with("=")) {
char Front = Interpolated.empty() ? ' ' : Interpolated.trim().front();
- Tokens.emplace_back(RawBody, Interpolated.str(), Front);
+ Tokens.emplace_back(T.FullMatch, Interpolated, Front, Ctx);
return std::nullopt;
}
- Tokens.emplace_back(RawBody, Interpolated.str(), '=');
+ Tokens.emplace_back(T.FullMatch, Interpolated, '=', Ctx);
StringRef DelimSpec = Interpolated.trim();
DelimSpec = DelimSpec.drop_front(1);
DelimSpec = DelimSpec.take_until([](char C) { return C == '='; });
@@ -435,7 +443,7 @@ processTag(const Tag &T, SmallVectorImpl<Token> &Tokens) {
// The mustache spec allows {{{ }}} to unescape variables,
// but we don't support that here. An unescape variable
// is represented only by {{& variable}}.
-static SmallVector<Token> tokenize(StringRef Template) {
+static SmallVector<Token> tokenize(StringRef Template, MustacheContext &Ctx) {
LLVM_DEBUG(dbgs() << "[Tokenize Template] \"" << Template << "\"\n");
SmallVector<Token> Tokens;
SmallString<8> Open("{{");
@@ -449,17 +457,17 @@ static SmallVector<Token> tokenize(StringRef Template) {
if (T.TagKind == Tag::Kind::None) {
// No more tags, the rest is text.
- Tokens.emplace_back(Template.substr(Start).str());
+ Tokens.emplace_back(Template.substr(Start));
break;
}
// Add the text before the tag.
if (T.StartPosition > Start) {
StringRef Text = Template.substr(Start, T.StartPosition - Start);
- Tokens.emplace_back(Text.str());
+ Tokens.emplace_back(Text);
}
- if (auto NewDelims = processTag(T, Tokens)) {
+ if (auto NewDelims = processTag(T, Tokens, Ctx)) {
std::tie(Open, Close) = *NewDelims;
}
@@ -600,20 +608,20 @@ void Parser::parseSection(ASTNode *Parent, ASTNode::Type Ty,
const Accessor &A) {
AstPtr CurrentNode = createNode(Ctx, Ty, A, Parent);
size_t Start = CurrentPtr;
- parseMustache(CurrentNode.get());
+ parseMustache(CurrentNode);
const size_t End = CurrentPtr - 1;
- std::string RawBody;
+ SmallString<128> RawBody;
for (std::size_t I = Start; I < End; I++)
RawBody += Tokens[I].RawBody;
- CurrentNode->setRawBody(std::move(RawBody));
- Parent->addChild(std::move(CurrentNode));
+ CurrentNode->setRawBody(Ctx.Saver.save(StringRef(RawBody)));
+ Parent->addChild(CurrentNode);
}
AstPtr Parser::parse() {
- Tokens = tokenize(TemplateStr);
+ Tokens = tokenize(TemplateStr, Ctx);
CurrentPtr = 0;
AstPtr RootNode = createRootNode(Ctx);
- parseMustache(RootNode.get());
+ parseMustache(RootNode);
return RootNode;
}
@@ -622,31 +630,29 @@ void Parser::parseMustache(ASTNode *Parent) {
while (CurrentPtr < Tokens.size()) {
Token CurrentToken = Tokens[CurrentPtr];
CurrentPtr++;
- Accessor A = CurrentToken.getAccessor();
+ ArrayRef<StringRef> A = CurrentToken.getAccessor();
AstPtr CurrentNode;
switch (CurrentToken.getType()) {
case Token::Type::Text: {
- CurrentNode =
- createTextNode(Ctx, std::move(CurrentToken.TokenBody), Parent);
- Parent->addChild(std::move(CurrentNode));
+ CurrentNode = createTextNode(Ctx, CurrentToken.TokenBody, Parent);
+ Parent->addChild(CurrentNode);
break;
}
case Token::Type::Variable: {
- CurrentNode = createNode(Ctx, ASTNode::Variable, std::move(A), Parent);
- Parent->addChild(std::move(CurrentNode));
+ CurrentNode = createNode(Ctx, ASTNode::Variable, A, Parent);
+ Parent->addChild(CurrentNode);
break;
}
case Token::Type::UnescapeVariable: {
- CurrentNode =
- createNode(Ctx, ASTNode::UnescapeVariable, std::move(A), Parent);
- Parent->addChild(std::move(CurrentNode));
+ CurrentNode = createNode(Ctx, ASTNode::UnescapeVariable, A, Parent);
+ Parent->addChild(CurrentNode);
break;
}
case Token::Type::Partial: {
- CurrentNode = createNode(Ctx, ASTNode::Partial, std::move(A), Parent);
+ CurrentNode = createNode(Ctx, ASTNode::Partial, A, Parent);
CurrentNode->setIndentation(CurrentToken.getIndentation());
- Parent->addChild(std::move(CurrentNode));
+ Parent->addChild(CurrentNode);
break;
}
case Token::Type::SectionOpen: {
@@ -712,7 +718,7 @@ void ASTNode::renderPartial(const json::Value &CurrentCtx,
<< ", Indentation=" << Indentation << "\n");
auto Partial = Ctx.Partials.find(AccessorValue[0]);
if (Partial != Ctx.Partials.end())
- renderPartial(CurrentCtx, OS, Partial->getValue().get());
+ renderPartial(CurrentCtx, OS, Partial->getValue());
}
void ASTNode::renderVariable(const json::Value &CurrentCtx,
@@ -843,8 +849,8 @@ const json::Value *ASTNode::findContext() {
void ASTNode::renderChild(const json::Value &Contexts,
MustacheOutputStream &OS) {
- for (AstPtr &Child : Children)
- Child->render(Contexts, OS);
+ for (ASTNode &Child : Children)
+ Child.render(Contexts, OS);
}
void ASTNode::renderPartial(const json::Value &Contexts,
@@ -854,7 +860,7 @@ void ASTNode::renderPartial(const json::Value &Contexts,
Partial->render(Contexts, IS);
}
-void ASTNode::renderLambdas(const json::Value &Contexts,
+void ASTNode::renderLambdas(const llvm::json::Value &Contexts,
MustacheOutputStream &OS, Lambda &L) {
json::Value LambdaResult = L();
std::string LambdaStr;
@@ -871,9 +877,9 @@ void ASTNode::renderLambdas(const json::Value &Contexts,
LambdaNode->render(Contexts, OS);
}
-void ASTNode::renderSectionLambdas(const json::Value &Contexts,
+void ASTNode::renderSectionLambdas(const llvm::json::Value &Contexts,
MustacheOutputStream &OS, SectionLambda &L) {
- json::Value Return = L(RawBody);
+ json::Value Return = L(RawBody.str());
if (isFalsey(Return))
return;
std::string LambdaStr;
@@ -884,15 +890,16 @@ void ASTNode::renderSectionLambdas(const json::Value &Contexts,
LambdaNode->render(Contexts, OS);
}
-void Template::render(const json::Value &Data, llvm::raw_ostream &OS) {
+void Template::render(const llvm::json::Value &Data, llvm::raw_ostream &OS) {
RawMustacheOutputStream MOS(OS);
Tree->render(Data, MOS);
}
void Template::registerPartial(std::string Name, std::string Partial) {
- Parser P(Partial, Ctx);
+ StringRef SavedPartial = Ctx.Saver.save(Partial);
+ Parser P(SavedPartial, Ctx);
AstPtr PartialTree = P.parse();
- Ctx.Partials.insert(std::make_pair(Name, std::move(PartialTree)));
+ Ctx.Partials.insert(std::make_pair(Name, PartialTree));
}
void Template::registerLambda(std::string Name, Lambda L) {
@@ -907,7 +914,7 @@ void Template::overrideEscapeCharacters(EscapeMap E) {
Ctx.Escapes = std::move(E);
}
-Template::Template(StringRef TemplateStr) {
+Template::Template(StringRef TemplateStr, MustacheContext &Ctx) : Ctx(Ctx) {
Parser P(TemplateStr, Ctx);
Tree = P.parse();
// The default behavior is to escape html entities.
@@ -920,18 +927,12 @@ Template::Template(StringRef TemplateStr) {
}
Template::Template(Template &&Other) noexcept
- : Ctx(std::move(Other.Ctx)), Tree(std::move(Other.Tree)) {}
+ : Ctx(Other.Ctx), Tree(Other.Tree) {
+ Other.Tree = nullptr;
+}
Template::~Template() = default;
-Template &Template::operator=(Template &&Other) noexcept {
- if (this != &Other) {
- Ctx = std::move(Other.Ctx);
- Tree = std::move(Other.Tree);
- Other.Tree = nullptr;
- }
- return *this;
-}
} // namespace llvm::mustache
#undef DEBUG_TYPE
diff --git a/llvm/unittests/Support/MustacheTest.cpp b/llvm/unittests/Support/MustacheTest.cpp
index b98c218796b0b..3cad4a4562c2b 100644
--- a/llvm/unittests/Support/MustacheTest.cpp
+++ b/llvm/unittests/Support/MustacheTest.cpp
@@ -22,7 +22,10 @@ using namespace llvm::json;
TEST(MustacheInterpolation, NoInterpolation) {
// Mustache-free templates should render as-is.
Value D = {};
- Template T("Hello from {Mustache}!\n");
+ BumpPtrAllocator Allocator;
+ StringSaver Saver(Allocator);
+ MustacheContext Ctx(Allocator, Saver);
+ Template T("Hello from {Mustache}!\n", Ctx);
std::string Out;
raw_string_ostream OS(Out);
T.render(D, OS);
@@ -32,7 +35,10 @@ TEST(MustacheInterpolation, NoInterpolation) {
TEST(MustacheInterpolation, BasicInterpolation) {
// Unadorned tags ...
[truncated]
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
94875b6
to
ddcaf16
Compare
1fa886b
to
b95282a
Compare
e89315c
to
68c27a3
Compare
b95282a
to
7100270
Compare
68c27a3
to
c2719fb
Compare
7100270
to
2a32dcd
Compare
c2719fb
to
f153c6a
Compare
2a32dcd
to
165e659
Compare
f153c6a
to
f4b4bc8
Compare
165e659
to
b233591
Compare
f4b4bc8
to
df32a14
Compare
b233591
to
385ae4b
Compare
df32a14
to
b22fb3e
Compare
385ae4b
to
28e0058
Compare
b22fb3e
to
79eaa0a
Compare
a6c453d
to
f9e86b8
Compare
79eaa0a
to
eb3ba40
Compare
f9e86b8
to
8395d94
Compare
8395d94
to
c0cfd17
Compare
We make the Mustache ASTNodes usable in the arena by first removing all of the memory owning data structures, like std::vector, std::unique_ptr, and SmallVector. We use standard LLVM list types to hold this data instead, and make use of a UniqueStringSaver to hold the various templates strings. Additionally, update clang-doc APIs to use the new interfaces. Future work can make better use of Twine interfaces to help avoid any intermediate copies or allocations. | Benchmark | Baseline (ns) | Arena (ns) | Change | | :--- | :--- | :--- | :--- | | `StringRendering/Escaped` | 12,883,958 | 12,938,218 | +0.42% | | `StringRendering/Unescaped_Triple` | 68,050 | 66,989 | -1.56% | | `StringRendering/Unescaped_Ampersand` | 67,132 | 67,955 | +1.23% | | `DeepTraversal` | 4,249,942 | 4,185,837 | -1.51% | | `DeeplyNestedRendering` | 2,720 | 2,408 | -11.47% | | `HugeArrayIteration` | 56,290,788 | 54,710,396 | -2.81% | | `ComplexTemplateParsing` | 764,660,111 | 754,830,429 | -1.29% | | `SmallTemplateParsing` | 4,853 | 4,828 | -0.52% | | `PartialsRendering` | 223,235,384 | 225,555,792 | +1.04% | | `LargeOutputString` | 598,101 | 566,055 | -5.36% |
c0cfd17
to
6bf75e7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
We make the Mustache ASTNodes usable in the arena by first removing all of the memory owning data structures, like std::vector, std::unique_ptr, and SmallVector. We use standard LLVM list types to hold this data instead, and make use of a UniqueStringSaver to hold the various templates strings. Additionally, update clang-doc APIs to use the new interfaces. Future work can make better use of Twine interfaces to help avoid any intermediate copies or allocations.
We make the Mustache ASTNodes usable in the arena by first removing all of the memory owning data structures, like std::vector, std::unique_ptr, and SmallVector. We use standard LLVM list types to hold this data instead, and make use of a UniqueStringSaver to hold the various templates strings. Additionally, update clang-doc APIs to use the new interfaces. Future work can make better use of Twine interfaces to help avoid any intermediate copies or allocations.
We make the Mustache ASTNodes usable in the arena by first removing all of the memory owning data structures, like std::vector, std::unique_ptr, and SmallVector. We use standard LLVM list types to hold this data instead, and make use of a UniqueStringSaver to hold the various templates strings. Additionally, update clang-doc APIs to use the new interfaces. Future work can make better use of Twine interfaces to help avoid any intermediate copies or allocations.
We make the Mustache ASTNodes usable in the arena by first removing all
of the memory owning data structures, like std::vector, std::unique_ptr,
and SmallVector. We use standard LLVM list types to hold this data
instead, and make use of a UniqueStringSaver to hold the various
templates strings.
Additionally, update clang-doc APIs to use the new interfaces.
Future work can make better use of Twine interfaces to help avoid any
intermediate copies or allocations.