Convert statement arrays from std::vector to SkSTArray.
This will help us avoid allocations for arrays of statements.
Currently, this is a wash in Nanobench (~0% change). In the near
future, we expect to collapse the expression array and statement array
into a single hybrid array, and this helps bring us closer to that end
goal.
Change-Id: Id146907352799c41b568090ab65e454247b294c8
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/325625
Commit-Queue: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp
index 5fcff8a..0ff4112 100644
--- a/src/sksl/SkSLCompiler.cpp
+++ b/src/sksl/SkSLCompiler.cpp
@@ -1172,14 +1172,13 @@
return ContainsUnconditionalBreak{}.visitStatement(stmt);
}
-static void move_all_but_break(std::unique_ptr<Statement>& stmt,
- std::vector<std::unique_ptr<Statement>>* target) {
+static void move_all_but_break(std::unique_ptr<Statement>& stmt, StatementArray* target) {
switch (stmt->kind()) {
case Statement::Kind::kBlock: {
// Recurse into the block.
Block& block = static_cast<Block&>(*stmt);
- std::vector<std::unique_ptr<Statement>> blockStmts;
+ StatementArray blockStmts;
blockStmts.reserve(block.children().size());
for (std::unique_ptr<Statement>& stmt : block.children()) {
move_all_but_break(stmt, &blockStmts);
@@ -1245,7 +1244,7 @@
// We fell off the bottom of the switch or encountered a break. We know the range of statements
// that we need to move over, and we know it's safe to do so.
- std::vector<std::unique_ptr<Statement>> caseStmts;
+ StatementArray caseStmts;
// We can move over most of the statements as-is.
while (startIter != iter) {
diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp
index c94fd7b..9313af1 100644
--- a/src/sksl/SkSLIRGenerator.cpp
+++ b/src/sksl/SkSLIRGenerator.cpp
@@ -208,7 +208,8 @@
if (expr.kind() == Expression::Kind::kFunctionCall) {
FunctionCall& fc = expr.as<FunctionCall>();
if (fc.function().isBuiltin() && fc.function().name() == "EmitVertex") {
- std::vector<std::unique_ptr<Statement>> statements;
+ StatementArray statements;
+ statements.reserve(2);
statements.push_back(getNormalizeSkPositionCode());
statements.push_back(std::move(result));
return std::make_unique<Block>(statement.fOffset, std::move(statements),
@@ -221,7 +222,7 @@
}
std::unique_ptr<Statement> IRGenerator::convertStatement(const ASTNode& statement) {
- std::vector<std::unique_ptr<Statement>> oldExtraStatements = std::move(fExtraStatements);
+ StatementArray oldExtraStatements = std::move(fExtraStatements);
std::unique_ptr<Statement> result = this->convertSingleStatement(statement);
if (!result) {
fExtraStatements = std::move(oldExtraStatements);
@@ -229,10 +230,10 @@
}
if (fExtraStatements.size()) {
fExtraStatements.push_back(std::move(result));
- std::unique_ptr<Statement> block(new Block(-1, std::move(fExtraStatements), nullptr,
- false));
+ auto block = std::make_unique<Block>(/*offset=*/-1, std::move(fExtraStatements),
+ /*symbols=*/nullptr, /*isScope=*/false);
fExtraStatements = std::move(oldExtraStatements);
- return block;
+ return std::move(block);
}
fExtraStatements = std::move(oldExtraStatements);
return result;
@@ -241,7 +242,7 @@
std::unique_ptr<Block> IRGenerator::convertBlock(const ASTNode& block) {
SkASSERT(block.fKind == ASTNode::Kind::kBlock);
AutoSymbolTable table(this);
- std::vector<std::unique_ptr<Statement>> statements;
+ StatementArray statements;
for (const auto& child : block) {
std::unique_ptr<Statement> statement = this->convertStatement(child);
if (!statement) {
@@ -266,13 +267,12 @@
}
}
-std::vector<std::unique_ptr<Statement>> IRGenerator::convertVarDeclarations(
- const ASTNode& decls, Variable::Storage storage) {
+StatementArray IRGenerator::convertVarDeclarations(const ASTNode& decls,
+ Variable::Storage storage) {
SkASSERT(decls.fKind == ASTNode::Kind::kVarDeclarations);
auto declarationsIter = decls.begin();
const Modifiers& modifiers = declarationsIter++->getModifiers();
const ASTNode& rawType = *(declarationsIter++);
- std::vector<std::unique_ptr<Statement>> varDecls;
const Type* baseType = this->convertType(rawType);
if (!baseType) {
return {};
@@ -365,6 +365,8 @@
Modifiers::kCoherent_Flag | Modifiers::kBuffer_Flag;
}
this->checkModifiers(decls.fOffset, modifiers, permitted);
+
+ StatementArray varDecls;
for (; declarationsIter != decls.end(); ++declarationsIter) {
const ASTNode& varDecl = *declarationsIter;
if (modifiers.fLayout.fLocation == 0 && modifiers.fLayout.fIndex == 0 &&
@@ -633,7 +635,7 @@
caseValues.insert(v);
}
++childIter;
- std::vector<std::unique_ptr<Statement>> statements;
+ StatementArray statements;
for (; childIter != c.end(); ++childIter) {
std::unique_ptr<Statement> converted = this->convertStatement(*childIter);
if (!converted) {
@@ -641,12 +643,11 @@
}
statements.push_back(std::move(converted));
}
- cases.emplace_back(new SwitchCase(c.fOffset, std::move(caseValue),
- std::move(statements)));
+ cases.push_back(std::make_unique<SwitchCase>(c.fOffset, std::move(caseValue),
+ std::move(statements)));
}
- return std::unique_ptr<Statement>(new SwitchStatement(s.fOffset, s.getBool(),
- std::move(value), std::move(cases),
- fSymbolTable));
+ return std::make_unique<SwitchStatement>(s.fOffset, s.getBool(), std::move(value),
+ std::move(cases), fSymbolTable);
}
std::unique_ptr<Statement> IRGenerator::convertExpressionStatement(const ASTNode& s) {
@@ -743,8 +744,8 @@
std::unique_ptr<Expression> endPrimitive = this->convertExpression(endPrimitiveID);
SkASSERT(endPrimitive);
- std::vector<std::unique_ptr<Statement>> loopBody;
- std::vector<std::unique_ptr<Expression>> invokeArgs;
+ StatementArray loopBody;
+ loopBody.reserve(2);
loopBody.push_back(std::make_unique<ExpressionStatement>(this->call(
/*offset=*/-1, *invokeDecl,
ExpressionArray{})));
@@ -763,7 +764,7 @@
std::move(test), std::move(next),
std::make_unique<Block>(-1, std::move(loopBody)),
fSymbolTable);
- std::vector<std::unique_ptr<Statement>> children;
+ StatementArray children;
children.push_back(std::move(loop));
return std::make_unique<Block>(-1, std::move(children));
}
@@ -1085,8 +1086,8 @@
bool foundRTAdjust = false;
auto iter = intf.begin();
for (size_t i = 0; i < id.fDeclarationCount; ++i) {
- std::vector<std::unique_ptr<Statement>> decls =
- this->convertVarDeclarations(*(iter++), Variable::Storage::kInterfaceBlock);
+ StatementArray decls = this->convertVarDeclarations(*(iter++),
+ Variable::Storage::kInterfaceBlock);
if (decls.empty()) {
return nullptr;
}
@@ -2974,8 +2975,8 @@
for (const auto& decl : fFile->root()) {
switch (decl.fKind) {
case ASTNode::Kind::kVarDeclarations: {
- std::vector<std::unique_ptr<Statement>> decls =
- this->convertVarDeclarations(decl, Variable::Storage::kGlobal);
+ StatementArray decls = this->convertVarDeclarations(decl,
+ Variable::Storage::kGlobal);
for (auto& varDecl : decls) {
fProgramElements->push_back(std::make_unique<GlobalVarDeclaration>(
decl.fOffset, std::move(varDecl)));
diff --git a/src/sksl/SkSLIRGenerator.h b/src/sksl/SkSLIRGenerator.h
index 3b9917d..3964773 100644
--- a/src/sksl/SkSLIRGenerator.h
+++ b/src/sksl/SkSLIRGenerator.h
@@ -143,8 +143,7 @@
void popSymbolTable();
void checkModifiers(int offset, const Modifiers& modifiers, int permitted);
- std::vector<std::unique_ptr<Statement>> convertVarDeclarations(const ASTNode& decl,
- Variable::Storage storage);
+ StatementArray convertVarDeclarations(const ASTNode& decl, Variable::Storage storage);
void convertFunction(const ASTNode& f);
std::unique_ptr<Statement> convertSingleStatement(const ASTNode& statement);
std::unique_ptr<Statement> convertStatement(const ASTNode& statement);
@@ -226,7 +225,7 @@
std::shared_ptr<SymbolTable> fSymbolTable = nullptr;
// additional statements that need to be inserted before the one that convertStatement is
// currently working on
- std::vector<std::unique_ptr<Statement>> fExtraStatements;
+ StatementArray fExtraStatements;
// Symbols which have definitions in the include files.
IRIntrinsicMap* fIntrinsics = nullptr;
std::unordered_set<const FunctionDeclaration*> fReferencedIntrinsics;
diff --git a/src/sksl/SkSLInliner.cpp b/src/sksl/SkSLInliner.cpp
index da97b1c..36762f9 100644
--- a/src/sksl/SkSLInliner.cpp
+++ b/src/sksl/SkSLInliner.cpp
@@ -443,14 +443,16 @@
return nullptr;
};
auto blockStmts = [&](const Block& block) {
- std::vector<std::unique_ptr<Statement>> result;
+ StatementArray result;
+ result.reserve(block.children().size());
for (const std::unique_ptr<Statement>& child : block.children()) {
result.push_back(stmt(child));
}
return result;
};
- auto stmts = [&](const std::vector<std::unique_ptr<Statement>>& ss) {
- std::vector<std::unique_ptr<Statement>> result;
+ auto stmts = [&](const StatementArray& ss) {
+ StatementArray result;
+ result.reserve(ss.size());
for (const auto& s : ss) {
result.push_back(stmt(s));
}
@@ -510,9 +512,10 @@
expr(r.expression()),
&resultExpr->type()));
if (haveEarlyReturns) {
- std::vector<std::unique_ptr<Statement>> block;
+ StatementArray block;
+ block.reserve(2);
block.push_back(std::move(assignment));
- block.emplace_back(new BreakStatement(offset));
+ block.push_back(std::make_unique<BreakStatement>(offset));
return std::make_unique<Block>(offset, std::move(block), /*symbols=*/nullptr,
/*isScope=*/true);
} else {
@@ -529,9 +532,10 @@
case Statement::Kind::kSwitch: {
const SwitchStatement& ss = statement.as<SwitchStatement>();
std::vector<std::unique_ptr<SwitchCase>> cases;
+ cases.reserve(ss.fCases.size());
for (const auto& sc : ss.fCases) {
- cases.emplace_back(new SwitchCase(offset, expr(sc->fValue),
- stmts(sc->fStatements)));
+ cases.push_back(std::make_unique<SwitchCase>(offset, expr(sc->fValue),
+ stmts(sc->fStatements)));
}
return std::make_unique<SwitchStatement>(offset, ss.fIsStatic, expr(ss.fValue),
std::move(cases), ss.fSymbols);
@@ -539,6 +543,7 @@
case Statement::Kind::kVarDeclaration: {
const VarDeclaration& decl = statement.as<VarDeclaration>();
std::vector<std::unique_ptr<Expression>> sizes;
+ sizes.reserve(decl.fSizes.size());
for (const auto& size : decl.fSizes) {
sizes.push_back(expr(size));
}
@@ -597,8 +602,7 @@
const bool hasEarlyReturn = has_early_return(function);
InlinedCall inlinedCall;
- inlinedCall.fInlinedBody = std::make_unique<Block>(offset,
- std::vector<std::unique_ptr<Statement>>{},
+ inlinedCall.fInlinedBody = std::make_unique<Block>(offset, StatementArray{},
/*symbols=*/nullptr,
/*isScope=*/false);
@@ -692,7 +696,7 @@
}
const Block& body = function.fBody->as<Block>();
- auto inlineBlock = std::make_unique<Block>(offset, std::vector<std::unique_ptr<Statement>>{});
+ auto inlineBlock = std::make_unique<Block>(offset, StatementArray{});
inlineBlock->children().reserve(body.children().size());
for (const std::unique_ptr<Statement>& stmt : body.children()) {
inlineBlock->children().push_back(this->inlineStatement(offset, &varMap, symbolTableForCall,
diff --git a/src/sksl/SkSLMetalCodeGenerator.h b/src/sksl/SkSLMetalCodeGenerator.h
index 15c4618..0a14a57 100644
--- a/src/sksl/SkSLMetalCodeGenerator.h
+++ b/src/sksl/SkSLMetalCodeGenerator.h
@@ -231,7 +231,7 @@
void writeStatement(const Statement& s);
- void writeStatements(const std::vector<std::unique_ptr<Statement>>& statements);
+ void writeStatements(const StatementArray& statements);
void writeBlock(const Block& b);
diff --git a/src/sksl/SkSLRehydrator.cpp b/src/sksl/SkSLRehydrator.cpp
index 88e49f8..25b6127 100644
--- a/src/sksl/SkSLRehydrator.cpp
+++ b/src/sksl/SkSLRehydrator.cpp
@@ -338,14 +338,14 @@
case Rehydrator::kBlock_Command: {
AutoRehydratorSymbolTable symbols(this);
int count = this->readU8();
- std::vector<std::unique_ptr<Statement>> statements;
+ StatementArray statements;
statements.reserve(count);
for (int i = 0; i < count; ++i) {
statements.push_back(this->statement());
}
bool isScope = this->readU8();
- return std::unique_ptr<Statement>(new Block(-1, std::move(statements), fSymbolTable,
- isScope));
+ return std::make_unique<Block>(/*offset=*/-1, std::move(statements), fSymbolTable,
+ isScope);
}
case Rehydrator::kBreak_Command:
return std::unique_ptr<Statement>(new BreakStatement(-1));
@@ -406,16 +406,16 @@
for (int i = 0; i < caseCount; ++i) {
std::unique_ptr<Expression> value = this->expression();
int statementCount = this->readU8();
- std::vector<std::unique_ptr<Statement>> statements;
+ StatementArray statements;
statements.reserve(statementCount);
for (int j = 0; j < statementCount; ++j) {
statements.push_back(this->statement());
}
- cases.emplace_back(new SwitchCase(-1, std::move(value), std::move(statements)));
+ cases.push_back(std::make_unique<SwitchCase>(/*offset=*/-1, std::move(value),
+ std::move(statements)));
}
- return std::unique_ptr<Statement>(new SwitchStatement(-1, isStatic, std::move(expr),
- std::move(cases),
- fSymbolTable));
+ return std::make_unique<SwitchStatement>(-1, isStatic, std::move(expr),
+ std::move(cases), fSymbolTable);
}
case Rehydrator::kVarDeclaration_Command: {
Variable* var = this->symbolRef<Variable>(Symbol::Kind::kVariable);
diff --git a/src/sksl/ir/SkSLBlock.h b/src/sksl/ir/SkSLBlock.h
index b224b78..a8b745a 100644
--- a/src/sksl/ir/SkSLBlock.h
+++ b/src/sksl/ir/SkSLBlock.h
@@ -20,16 +20,16 @@
public:
static constexpr Kind kStatementKind = Kind::kBlock;
- Block(int offset, std::vector<std::unique_ptr<Statement>> statements,
+ Block(int offset, StatementArray statements,
const std::shared_ptr<SymbolTable> symbols = nullptr, bool isScope = true)
: INHERITED(offset, kStatementKind, BlockData{std::move(symbols), isScope},
std::move(statements)) {}
- const std::vector<std::unique_ptr<Statement>>& children() const {
+ const StatementArray& children() const {
return fStatementChildren;
}
- std::vector<std::unique_ptr<Statement>>& children() {
+ StatementArray& children() {
return fStatementChildren;
}
@@ -55,13 +55,14 @@
}
std::unique_ptr<Statement> clone() const override {
- std::vector<std::unique_ptr<Statement>> cloned;
+ StatementArray cloned;
+ cloned.reserve(this->children().size());
for (const std::unique_ptr<Statement>& stmt : this->children()) {
cloned.push_back(stmt->clone());
}
const BlockData& data = this->blockData();
- return std::unique_ptr<Statement>(new Block(fOffset, std::move(cloned), data.fSymbolTable,
- data.fIsScope));
+ return std::make_unique<Block>(fOffset, std::move(cloned), data.fSymbolTable,
+ data.fIsScope);
}
String description() const override {
diff --git a/src/sksl/ir/SkSLIRNode.cpp b/src/sksl/ir/SkSLIRNode.cpp
index a2113eb..44a500c 100644
--- a/src/sksl/ir/SkSLIRNode.cpp
+++ b/src/sksl/ir/SkSLIRNode.cpp
@@ -11,8 +11,7 @@
namespace SkSL {
-IRNode::IRNode(int offset, int kind, const BlockData& data,
- std::vector<std::unique_ptr<Statement>> stmts)
+IRNode::IRNode(int offset, int kind, const BlockData& data, StatementArray stmts)
: fOffset(offset)
, fKind(kind)
, fData(data)
diff --git a/src/sksl/ir/SkSLIRNode.h b/src/sksl/ir/SkSLIRNode.h
index 742813b..118e6bb 100644
--- a/src/sksl/ir/SkSLIRNode.h
+++ b/src/sksl/ir/SkSLIRNode.h
@@ -35,6 +35,7 @@
enum class VariableStorage : int8_t;
using ExpressionArray = SkSTArray<2, std::unique_ptr<Expression>>;
+using StatementArray = SkSTArray<2, std::unique_ptr<Statement>>;
/**
* Represents a node in the intermediate representation (IR) tree. The IR is a fully-resolved
@@ -608,8 +609,7 @@
}
};
- IRNode(int offset, int kind, const BlockData& data,
- std::vector<std::unique_ptr<Statement>> stmts);
+ IRNode(int offset, int kind, const BlockData& data, StatementArray stmts);
IRNode(int offset, int kind, const BoolLiteralData& data);
@@ -879,9 +879,9 @@
// When the transition is finished, we'll be able to drop the unique_ptrs and just handle
// <IRNode> directly.
ExpressionArray fExpressionChildren;
- // it's important to keep fStatements defined after (and thus destroyed before) fData,
+ // it's important to keep the statement array defined after (and thus destroyed before) fData,
// because destroying statements can modify reference counts in a SymbolTable contained in fData
- std::vector<std::unique_ptr<Statement>> fStatementChildren;
+ StatementArray fStatementChildren;
};
} // namespace SkSL
diff --git a/src/sksl/ir/SkSLStatement.h b/src/sksl/ir/SkSLStatement.h
index 7cc10a6..a37ec0c 100644
--- a/src/sksl/ir/SkSLStatement.h
+++ b/src/sksl/ir/SkSLStatement.h
@@ -44,7 +44,7 @@
SkASSERT(kind >= Kind::kFirst && kind <= Kind::kLast);
}
- Statement(int offset, Kind kind, BlockData data, std::vector<std::unique_ptr<Statement>> stmts)
+ Statement(int offset, Kind kind, BlockData data, StatementArray stmts)
: INHERITED(offset, (int) kind, data, std::move(stmts)) {
SkASSERT(kind >= Kind::kFirst && kind <= Kind::kLast);
}
diff --git a/src/sksl/ir/SkSLSwitchCase.h b/src/sksl/ir/SkSLSwitchCase.h
index bd78dee..8b63b17 100644
--- a/src/sksl/ir/SkSLSwitchCase.h
+++ b/src/sksl/ir/SkSLSwitchCase.h
@@ -19,20 +19,20 @@
struct SwitchCase : public Statement {
static constexpr Kind kStatementKind = Kind::kSwitchCase;
- SwitchCase(int offset, std::unique_ptr<Expression> value,
- std::vector<std::unique_ptr<Statement>> statements)
- : INHERITED(offset, kStatementKind)
- , fValue(std::move(value))
- , fStatements(std::move(statements)) {}
+ SwitchCase(int offset, std::unique_ptr<Expression> value, StatementArray statements)
+ : INHERITED(offset, kStatementKind)
+ , fValue(std::move(value))
+ , fStatements(std::move(statements)) {}
std::unique_ptr<Statement> clone() const override {
- std::vector<std::unique_ptr<Statement>> cloned;
+ StatementArray cloned;
+ cloned.reserve(fStatements.size());
for (const auto& s : fStatements) {
cloned.push_back(s->clone());
}
- return std::unique_ptr<Statement>(new SwitchCase(fOffset,
- fValue ? fValue->clone() : nullptr,
- std::move(cloned)));
+ return std::make_unique<SwitchCase>(fOffset,
+ fValue ? fValue->clone() : nullptr,
+ std::move(cloned));
}
String description() const override {
@@ -50,7 +50,7 @@
// null value implies "default" case
std::unique_ptr<Expression> fValue;
- std::vector<std::unique_ptr<Statement>> fStatements;
+ StatementArray fStatements;
using INHERITED = Statement;
};