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;
 };