mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 10:51:06 +01:00
Port the toolchain to use the new Carbon hashtable (#4097)
This works to leverage the capabilities of the hashtable as much as possible, for example using the key context in the value stores. However, there may still be opportunities to refactor more deeply and use the functionality even better. Hopefully this is at least a reasonable start and gets us a clean baseline. On an Arm M1, this is a 15% improvement on my large lexing stress test, but ends up a wash on my x86-64 server. This is a smaller benefit than I expected, and it's because we're using a set-of-IDs and looking up values with a key context for things like identifiers. This pattern has a surprising tradeoff. The new hashtable uses significantly less memory, a 10% peak RSS reduction just from the hashtable change. But indirecting through the vector of values makes growing the hashtable dramatically less cache-friendly: it causes growth to randomly access every key when rehashing. On x86, everything gained by the faster hashtable is lost in even slower growth. And even on Arm, this eats into the benefits. But I have a plan to tweak how identifiers specifically work to avoid most of the growth, and so I suspect this is the right tradeoff on the whole. It gives us significant working set size reduction and we can likely avoid the regressed operation (growth with rehash) in most cases by clever reserving and if necessary by adding a hash caching layer to the table infrastructure. --------- Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
This commit is contained in:
co-authored by
Jon Ross-Perkins
parent
f5f8342542
commit
8992d22ab3
@@ -39,12 +39,12 @@ auto ScopeStack::Push(SemIR::InstId scope_inst_id, SemIR::NameScopeId scope_id,
|
||||
auto ScopeStack::Pop() -> void {
|
||||
auto scope = scope_stack_.pop_back_val();
|
||||
|
||||
for (const auto& str_id : scope.names) {
|
||||
scope.names.ForEach([&](SemIR::NameId str_id) {
|
||||
auto& lexical_results = lexical_lookup_.Get(str_id);
|
||||
CARBON_CHECK(lexical_results.back().scope_index == scope.index)
|
||||
<< "Inconsistent scope index for name " << str_id;
|
||||
lexical_results.pop_back();
|
||||
}
|
||||
});
|
||||
|
||||
if (scope.scope_id.is_valid()) {
|
||||
CARBON_CHECK(non_lexical_scope_stack_.back().scope_index == scope.index);
|
||||
@@ -120,12 +120,13 @@ auto ScopeStack::LookupInLexicalScopes(SemIR::NameId name_id)
|
||||
|
||||
auto ScopeStack::LookupOrAddName(SemIR::NameId name_id, SemIR::InstId target_id)
|
||||
-> SemIR::InstId {
|
||||
if (!scope_stack_.back().names.insert(name_id).second) {
|
||||
if (!scope_stack_.back().names.Insert(name_id).is_inserted()) {
|
||||
auto existing = lexical_lookup_.Get(name_id).back().inst_id;
|
||||
CARBON_CHECK(existing.is_valid())
|
||||
<< "Name in scope but not in lexical lookups";
|
||||
return existing;
|
||||
}
|
||||
++scope_stack_.back().num_names;
|
||||
|
||||
// TODO: Reject if we previously performed a failed lookup for this name
|
||||
// in this scope or a scope nested within it.
|
||||
@@ -166,16 +167,18 @@ auto ScopeStack::Suspend() -> SuspendedScope {
|
||||
scope_stack_.empty()
|
||||
? 0
|
||||
: scope_stack_.back().next_compile_time_bind_index.index;
|
||||
|
||||
result.suspended_items.reserve(result.entry.names.size() +
|
||||
result.suspended_items.reserve(result.entry.num_names +
|
||||
compile_time_binding_stack_.size() -
|
||||
remaining_compile_time_bindings);
|
||||
for (auto name_id : result.entry.names) {
|
||||
|
||||
result.entry.names.ForEach([&](SemIR::NameId name_id) {
|
||||
auto [index, inst_id] = lexical_lookup_.Suspend(name_id);
|
||||
CARBON_CHECK(index !=
|
||||
SuspendedScope::ScopeItem::IndexForCompileTimeBinding);
|
||||
result.suspended_items.push_back({.index = index, .inst_id = inst_id});
|
||||
}
|
||||
});
|
||||
CARBON_CHECK(static_cast<int>(result.suspended_items.size()) ==
|
||||
result.entry.num_names);
|
||||
|
||||
// Move any compile-time bindings into the suspended scope.
|
||||
for (auto inst_id : llvm::ArrayRef(compile_time_binding_stack_)
|
||||
|
||||
Reference in New Issue
Block a user