mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 22:02:23 +01:00
Just a small packing optimization. We currently have 222 `NodeKinds`, so this reduces us to just 30ish more we can add without needing to pack more. However, if we did, there would be a couple options for bringing the count down by reusing `NodeKinds` and disambiguating based on the token kind (the 29 infix operators as an example). Or we could just undo this. I'm expecting this to yield a small improvement. I'll see if I can get better numbers since my machine's not really reliable, but here are some basic values. Also suggesting to draw the use of `::RawEnumType` for `TokenKind`, since bit packing appears to work without it. Hoping the `static_assert` is easier for people to understand the size of the field. With the change: ``` ---------------------------------------------------------------------------------------------------------------------------- Benchmark Time CPU Iterations Bytes Lines Tokens ---------------------------------------------------------------------------------------------------------------------------- BM_CompileAPIFileDenseDecls<Phase::Parse>/256 50399 ns 50359 ns 14336 104.588M/s 3.87217M/s 21.8629M/s BM_CompileAPIFileDenseDecls<Phase::Parse>/1024 237823 ns 237629 ns 3072 136.721M/s 4.11986M/s 24.2058M/s BM_CompileAPIFileDenseDecls<Phase::Parse>/4096 997645 ns 996771 ns 768 142.343M/s 4.04105M/s 23.9363M/s BM_CompileAPIFileDenseDecls<Phase::Parse>/16384 4020308 ns 4018319 ns 192 152.041M/s 4.05966M/s 24.0874M/s BM_CompileAPIFileDenseDecls<Phase::Parse>/65536 16691390 ns 16683058 ns 48 151.317M/s 3.92374M/s 23.2936M/s BM_CompileAPIFileDenseDecls<Phase::Parse>/262144 75265735 ns 75233476 ns 8 135.842M/s 3.48421M/s 20.6862M/s ``` Without the change: ``` ---------------------------------------------------------------------------------------------------------------------------- Benchmark Time CPU Iterations Bytes Lines Tokens ---------------------------------------------------------------------------------------------------------------------------- BM_CompileAPIFileDenseDecls<Phase::Parse>/256 51515 ns 51480 ns 13312 102.312M/s 3.78789M/s 21.387M/s BM_CompileAPIFileDenseDecls<Phase::Parse>/1024 241040 ns 240900 ns 3072 134.865M/s 4.06392M/s 23.8771M/s BM_CompileAPIFileDenseDecls<Phase::Parse>/4096 985593 ns 984657 ns 768 144.094M/s 4.09077M/s 24.2308M/s BM_CompileAPIFileDenseDecls<Phase::Parse>/16384 4109327 ns 4105496 ns 192 148.813M/s 3.97345M/s 23.576M/s BM_CompileAPIFileDenseDecls<Phase::Parse>/65536 17459655 ns 17446006 ns 48 144.7M/s 3.75215M/s 22.275M/s BM_CompileAPIFileDenseDecls<Phase::Parse>/262144 80802815 ns 80737489 ns 8 126.581M/s 3.24668M/s 19.276M/s ``` --------- Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
90 lines
3.0 KiB
C++
90 lines
3.0 KiB
C++
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
|
// Exceptions. See /LICENSE for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
#include "toolchain/parse/tree.h"
|
|
|
|
#include "common/check.h"
|
|
#include "common/error.h"
|
|
#include "llvm/ADT/Sequence.h"
|
|
#include "llvm/ADT/SmallVector.h"
|
|
#include "toolchain/lex/tokenized_buffer.h"
|
|
#include "toolchain/parse/node_kind.h"
|
|
#include "toolchain/parse/tree_and_subtrees.h"
|
|
#include "toolchain/parse/typed_nodes.h"
|
|
|
|
namespace Carbon::Parse {
|
|
|
|
auto Tree::postorder() const -> llvm::iterator_range<PostorderIterator> {
|
|
return llvm::iterator_range<PostorderIterator>(
|
|
PostorderIterator(NodeId(0)),
|
|
PostorderIterator(NodeId(node_impls_.size())));
|
|
}
|
|
|
|
auto Tree::node_token(NodeId n) const -> Lex::TokenIndex {
|
|
CARBON_CHECK(n.is_valid());
|
|
return node_impls_[n.index].token();
|
|
}
|
|
|
|
auto Tree::Print(llvm::raw_ostream& output) const -> void {
|
|
TreeAndSubtrees(*tokens_, *this).Print(output);
|
|
}
|
|
|
|
auto Tree::Verify() const -> ErrorOr<Success> {
|
|
llvm::SmallVector<NodeId> nodes;
|
|
// Traverse the tree in postorder.
|
|
for (NodeId n : postorder()) {
|
|
if (node_has_error(n) && !has_errors()) {
|
|
return Error(llvm::formatv(
|
|
"Node {0} has errors, but the tree is not marked as having any.", n));
|
|
}
|
|
|
|
if (node_kind(n) == NodeKind::Placeholder) {
|
|
return Error(llvm::formatv(
|
|
"Node {0} is a placeholder node that wasn't replaced.", n));
|
|
}
|
|
}
|
|
|
|
// Not every token that can produce a virtual node will, so we only check that
|
|
// the number of nodes is in a range.
|
|
int32_t num_nodes = size();
|
|
if (!has_errors() && num_nodes > tokens_->expected_max_parse_tree_size()) {
|
|
return Error(llvm::formatv(
|
|
"Tree has {0} nodes and no errors, but "
|
|
"Lex::TokenizedBuffer expected up to {1} nodes for {2} tokens.",
|
|
num_nodes, tokens_->expected_max_parse_tree_size(), tokens_->size()));
|
|
}
|
|
if (!has_errors() && num_nodes < tokens_->size()) {
|
|
return Error(
|
|
llvm::formatv("Tree has {0} nodes and no errors, but expected at least "
|
|
"{1} nodes to match the number of tokens.",
|
|
num_nodes, tokens_->size()));
|
|
}
|
|
|
|
#ifndef NDEBUG
|
|
TreeAndSubtrees subtrees(*tokens_, *this);
|
|
CARBON_RETURN_IF_ERROR(subtrees.Verify());
|
|
#endif // NDEBUG
|
|
|
|
return Success();
|
|
}
|
|
|
|
auto Tree::CollectMemUsage(MemUsage& mem_usage, llvm::StringRef label) const
|
|
-> void {
|
|
mem_usage.Collect(MemUsage::ConcatLabel(label, "node_impls_"), node_impls_);
|
|
mem_usage.Collect(MemUsage::ConcatLabel(label, "imports_"), imports_);
|
|
}
|
|
|
|
auto Tree::PostorderIterator::MakeRange(NodeId begin, NodeId end)
|
|
-> llvm::iterator_range<PostorderIterator> {
|
|
CARBON_CHECK(begin.is_valid() && end.is_valid());
|
|
return llvm::iterator_range<PostorderIterator>(
|
|
PostorderIterator(begin), PostorderIterator(NodeId(end.index + 1)));
|
|
}
|
|
|
|
auto Tree::PostorderIterator::Print(llvm::raw_ostream& output) const -> void {
|
|
output << node_;
|
|
}
|
|
|
|
} // namespace Carbon::Parse
|