aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2021-08-11 11:07:09 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2021-08-11 11:07:09 +0200
commit037e5e9224648fdc9f3956d612fb476966847f5c (patch)
tree7c829f581fbd0caafd4a121c7f3a1ab60e3c5557
parent67db22fcae32c8a8014866ef2ee55b6c7733c3f9 (diff)
Optimize process_libraries() some more
-rw-r--r--libbuild2/cc/common.cxx56
-rw-r--r--libbuild2/cc/common.hxx2
-rw-r--r--libbuild2/cc/init.cxx3
-rw-r--r--libbuild2/target.cxx14
-rw-r--r--libbuild2/target.hxx7
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<const target*, 16>* chain) const
+ small_vector<const target*, 24>* chain) const
{
library_cache cache_storage;
if (cache == nullptr)
cache = &cache_storage;
- small_vector<const target*, 16> chain_storage;
+ small_vector<const target*, 24> 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<string> (l.state[a][c_type]));
+ const string* t (
+ cast_null<string> (
+ 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<optional<linfo>> li; // Calculate lazily.
const dir_paths* sysd (nullptr); // Resolve lazily.
@@ -275,7 +296,7 @@ namespace build2
{
li = (t == nullptr || cc)
? top_li
- : optional<linfo> (link_info (bs, link_type (l).type));
+ : optional<linfo> (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 (const target&, const string&, bool, bool)>&,
bool = false,
library_cache* = nullptr,
- small_vector<const target*, 16>* = nullptr) const;
+ small_vector<const target*, 24>* = 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<string> ("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<lookup, size_t> target::
- lookup_original (const variable& var, bool target_only) const
+ lookup_original (const variable& var,
+ bool target_only,
+ const scope* bs) const
{
pair<lookup_type, size_t> 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_type, size_t>
- 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.
//