From 2f997310eecbb945e457ba28766b56869beb4e00 Mon Sep 17 00:00:00 2001 From: Shaunak Kishore Date: Wed, 24 Jun 2020 19:20:06 -0700 Subject: [PATCH] Shrink block bytecode vectors Summary: Shrink BytecodeVec at strategic points: a) when initially creating a Func and b) after each call to optimize. Note that we may lose out on a different memory optimization here: sharing bytecode between Funcs. I believe that because of the first shrink_to_fit, most of the time we'll only do the second when we have mutated (and COWed) the bytecode. We also pre-size a couple of other vectors - the initializer_list constructor gets it right. Reviewed By: ricklavoie Differential Revision: D22214700 fbshipit-source-id: cc73913fc33a1db77072d0934003094887e89326 --- hphp/hhbbc/optimize.cpp | 9 +++++++++ hphp/hhbbc/parse.cpp | 5 +++-- hphp/util/compact-vector.h | 4 ++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/hphp/hhbbc/optimize.cpp b/hphp/hhbbc/optimize.cpp index 8ae86ea3528..c42dce332c8 100644 --- a/hphp/hhbbc/optimize.cpp +++ b/hphp/hhbbc/optimize.cpp @@ -887,6 +887,15 @@ void do_optimize(const Index& index, FuncAnalysis&& ainfo, bool isFinal) { insert_assertions); } + // NOTE: We shouldn't duplicate blocks that are shared between two Funcs + // in this loop. We shrink BytecodeVec at the time we parse the function, + // so we only shrink when we've already mutated (and COWed) the bytecode. + for (auto& block : func->blocks) { + assertx(block->hhbcs.size()); + if (block->hhbcs.capacity() == block->hhbcs.size()) continue; + block.mutate()->hhbcs.shrink_to_fit(); + } + for (auto& p : func->params) fixTypeConstraint(index, p.typeConstraint); if (RuntimeOption::EvalCheckReturnTypeHints >= 3) { diff --git a/hphp/hhbbc/parse.cpp b/hphp/hhbbc/parse.cpp index 2dae92c9b2d..cd0a99744a4 100644 --- a/hphp/hhbbc/parse.cpp +++ b/hphp/hhbbc/parse.cpp @@ -282,6 +282,7 @@ void populate_block(ParseUnitState& puState, auto decode_stringvec = [&] { auto const vecLen = decode_iva(pc); CompactVector keys; + keys.reserve(vecLen); for (auto i = size_t{0}; i < vecLen; ++i) { keys.push_back(ue.lookupLitstr(decode(pc))); } @@ -653,6 +654,7 @@ void build_cfg(ParseUnitState& puState, auto const id = kv.second.first; blk->multiSucc = predSuccCounts[id].second > 1; blk->multiPred = predSuccCounts[id].first > 1; + blk->hhbcs.shrink_to_fit(); func.blocks[id] = std::move(kv.second.second); } } @@ -768,8 +770,7 @@ std::unique_ptr parse_func(ParseUnitState& puState, auto blk = php::Block{}; blk.exnNodeId = NoExnNodeId; - blk.hhbcs.push_back(gen_constant(it->second)); - blk.hhbcs.push_back(bc::RetC {}); + blk.hhbcs = {gen_constant(it->second), bc::RetC {}}; ret->blocks.emplace_back(std::move(blk)); ret->dvEntries.resize(fe.params.size(), NoBlockId); diff --git a/hphp/util/compact-vector.h b/hphp/util/compact-vector.h index 4fcdcd81d5d..65b10a070b6 100644 --- a/hphp/util/compact-vector.h +++ b/hphp/util/compact-vector.h @@ -79,7 +79,7 @@ struct CompactVector : private Alloc::template rebind::other { bool empty() const; size_type size() const; - size_type capacity(); + size_type capacity() const; void clear(); void push_back(const T& val); void push_back(T&& val); @@ -252,7 +252,7 @@ typename CompactVector::size_type CompactVector::size() const { } template -typename CompactVector::size_type CompactVector::capacity() { +typename CompactVector::size_type CompactVector::capacity() const { return m_data ? m_data->m_capacity : 0; } -- 2.11.4.GIT