From 037e5e9224648fdc9f3956d612fb476966847f5c Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 11 Aug 2021 11:07:09 +0200 Subject: Optimize process_libraries() some more --- libbuild2/cc/common.cxx | 56 ++++++++++++++++++++++++++++++++++++------------- libbuild2/cc/common.hxx | 2 +- libbuild2/cc/init.cxx | 3 +++ libbuild2/target.cxx | 14 ++++++++----- libbuild2/target.hxx | 7 +++++-- 5 files changed, 59 insertions(+), 23 deletions(-) diff --git a/libbuild2/cc/common.cxx b/libbuild2/cc/common.cxx index 4b4aef8..d9afd21 100644 --- a/libbuild2/cc/common.cxx +++ b/libbuild2/cc/common.cxx @@ -99,13 +99,13 @@ namespace build2 bool exp)>& proc_opt, // *.export. bool self /*= false*/, // Call proc_lib on l? library_cache* cache, - small_vector* chain) const + small_vector* chain) const { library_cache cache_storage; if (cache == nullptr) cache = &cache_storage; - small_vector chain_storage; + small_vector chain_storage; if (chain == nullptr) { chain = &chain_storage; @@ -126,21 +126,30 @@ namespace build2 // See what type of library this is (C, C++, etc). Use it do decide // which x.libs variable name to use. If it's unknown, then we only // look into prerequisites. Note: lookup starting from rule-specific - // variables (target should already be matched). + // variables (target should already be matched). Note also that for + // performance we use lookup_original() directly and only look in the + // target (so no target type/pattern-specific). // - const string* t (cast_null (l.state[a][c_type])); + const string* t ( + cast_null ( + l.state[a].lookup_original (c_type, true /* target_only */).first)); bool impl (proc_impl && proc_impl (l, la)); bool cc (false), same (false); - lookup c_e_libs; - lookup x_e_libs; - if (t != nullptr) { cc = (*t == "cc"); same = (!cc && *t == x); + } + + const scope& bs (t == nullptr || cc ? top_bs : l.base_scope ()); + lookup c_e_libs; + lookup x_e_libs; + + if (t != nullptr) + { // Note that we used to treat *.export.libs set on the liba/libs{} // members as *.libs overrides rather than as member-specific // interface dependencies. This difference in semantics proved to be @@ -152,12 +161,25 @@ namespace build2 // be set to NULL or empty (this is why we check for the result // being defined). // - c_e_libs = l[impl ? c_export_impl_libs : c_export_libs]; + // Note: for performance we call lookup_original() directly (we know + // these variables are not overridable) and pass the base scope we + // have already resolved. + // + // @@ PERF: do target_only (helps a bit in non-installed case)? + // + { + const variable& v (impl ? c_export_impl_libs : c_export_libs); + c_e_libs = l.lookup_original (v, false, &bs).first; + } if (!cc) - x_e_libs = l[same - ? (impl ? x_export_impl_libs : x_export_libs) - : vp[*t + (impl ? ".export.impl_libs" : ".export.libs")]]; + { + const variable& v ( + same + ? (impl ? x_export_impl_libs : x_export_libs) + : vp[*t + (impl ? ".export.impl_libs" : ".export.libs")]); + x_e_libs = l.lookup_original (v, false, &bs).first; + } // Process options first. // @@ -252,7 +274,6 @@ namespace build2 break; } - const scope& bs (t == nullptr || cc ? top_bs : l.base_scope ()); optional> li; // Calculate lazily. const dir_paths* sysd (nullptr); // Resolve lazily. @@ -275,7 +296,7 @@ namespace build2 { li = (t == nullptr || cc) ? top_li - : optional (link_info (bs, link_type (l).type)); + : optional (link_info (bs, link_type (l).type)); // @@ PERF }; // Only go into prerequisites (implementation) if instructed and we @@ -558,10 +579,15 @@ namespace build2 // used to build the library. Since libraries in (non-export) // *.libs are not targets, we don't need to recurse. // + // Note: for performance we call lookup_original() directly + // (we know these variables are not overridable) and pass the + // base scope we have already resolved. + // if (proc_lib) { - proc_imp (l[c_libs]); - proc_imp (l[same ? x_libs : vp[*t + ".libs"]]); + const variable& v (same ? x_libs : vp[*t + ".libs"]); + proc_imp (l.lookup_original (c_libs, false, &bs).first); + proc_imp (l.lookup_original (v, false, &bs).first); } } } diff --git a/libbuild2/cc/common.hxx b/libbuild2/cc/common.hxx index f15bf23..64de228 100644 --- a/libbuild2/cc/common.hxx +++ b/libbuild2/cc/common.hxx @@ -298,7 +298,7 @@ namespace build2 const function&, bool = false, library_cache* = nullptr, - small_vector* = nullptr) const; + small_vector* = nullptr) const; const target* search_library (action a, diff --git a/libbuild2/cc/init.cxx b/libbuild2/cc/init.cxx index f201d79..07f082f 100644 --- a/libbuild2/cc/init.cxx +++ b/libbuild2/cc/init.cxx @@ -133,6 +133,9 @@ namespace build2 // but specific language is not known. Used in the import installed // logic. // + // Note that this variable cannot be set via the target type/pattern- + // specific mechanism (see process_libraries()). + // vp.insert ("cc.type", v_t); // If set and is true, then this (imported) library has been found in a diff --git a/libbuild2/target.cxx b/libbuild2/target.cxx index a686fc2..24ad01e 100644 --- a/libbuild2/target.cxx +++ b/libbuild2/target.cxx @@ -146,7 +146,9 @@ namespace build2 } pair target:: - lookup_original (const variable& var, bool target_only) const + lookup_original (const variable& var, + bool target_only, + const scope* bs) const { pair r (lookup_type (), 0); @@ -185,10 +187,12 @@ namespace build2 target_key tk (key ()); target_key gk (g != nullptr ? g->key () : target_key {}); - auto p (base_scope ().lookup_original ( - var, - &tk, - g != nullptr ? &gk : nullptr)); + if (bs == nullptr) + bs = &base_scope (); + + auto p (bs->lookup_original (var, + &tk, + g != nullptr ? &gk : nullptr)); r.first = move (p.first); r.second = r.first ? r.second + p.second : p.second; diff --git a/libbuild2/target.hxx b/libbuild2/target.hxx index 01f01e1..de17fa8 100644 --- a/libbuild2/target.hxx +++ b/libbuild2/target.hxx @@ -446,10 +446,13 @@ namespace build2 } // If target_only is true, then only look in target and its target group - // without continuing in scopes. + // without continuing in scopes. As an optimization, the caller can also + // pass the base scope of the target, if already known. // pair - lookup_original (const variable&, bool target_only = false) const; + lookup_original (const variable&, + bool target_only = false, + const scope* bs = nullptr) const; // Return a value suitable for assignment. See scope for details. // -- cgit v1.1