From 6052d41d5137c5d1e3421355c68168ab3d5a93fb Mon Sep 17 00:00:00 2001 From: Ben Clayton Date: Fri, 23 Apr 2021 18:21:34 +0000 Subject: [PATCH] sem::Alias::type_name(): Optimize complexity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precalculate the type_name to reduce complexity from O(N²) to O(N). Fixed: chromium:1199700 Fixed: chromium:1200936 Change-Id: Ifd16508ace42d4a686f06d58121cc106842df7d3 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/48691 Commit-Queue: Ben Clayton Reviewed-by: Antonio Maiorano --- src/ast/alias.cc | 7 +++++-- src/ast/alias.h | 1 + src/ast/alias_test.cc | 13 +++++++++++++ src/sem/alias_type.cc | 6 ++++-- src/sem/alias_type.h | 3 ++- src/sem/alias_type_test.cc | 13 +++++++++++++ 6 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/ast/alias.cc b/src/ast/alias.cc index 80e595780c..a3b6a2cd15 100644 --- a/src/ast/alias.cc +++ b/src/ast/alias.cc @@ -25,7 +25,10 @@ Alias::Alias(ProgramID program_id, const Source& source, const Symbol& sym, Type* subtype) - : Base(program_id, source), symbol_(sym), subtype_(subtype) { + : Base(program_id, source), + symbol_(sym), + subtype_(subtype), + type_name_("__alias_" + sym.to_str() + subtype->type_name()) { TINT_ASSERT(subtype_); } @@ -34,7 +37,7 @@ Alias::Alias(Alias&&) = default; Alias::~Alias() = default; std::string Alias::type_name() const { - return "__alias_" + symbol_.to_str() + subtype_->type_name(); + return type_name_; } std::string Alias::FriendlyName(const SymbolTable& symbols) const { diff --git a/src/ast/alias.h b/src/ast/alias.h index d95387d2f8..5f94ec693a 100644 --- a/src/ast/alias.h +++ b/src/ast/alias.h @@ -60,6 +60,7 @@ class Alias : public Castable { private: Symbol const symbol_; Type* const subtype_; + std::string const type_name_; }; } // namespace ast diff --git a/src/ast/alias_test.cc b/src/ast/alias_test.cc index ae36314bfd..3699aafb8d 100644 --- a/src/ast/alias_test.cc +++ b/src/ast/alias_test.cc @@ -57,6 +57,19 @@ TEST_F(AstAliasTest, Is) { EXPECT_FALSE(ty->Is()); } +// Check for linear-time evaluation of Alias::type_name(). +// If type_name() is non-linear, this test should noticeably stall. +// See: crbug.com/1200936 +TEST_F(AstAliasTest, TypeName_LinearTime) { + Type* type = ty.i32(); + for (int i = 0; i < 1024; i++) { + type = create(Symbols().New(), type); + } + for (int i = 0; i < 16384; i++) { + type->type_name(); + } +} + TEST_F(AstAliasTest, TypeName) { auto* at = create(Sym("Particle"), create()); EXPECT_EQ(at->type_name(), "__alias_$1__i32"); diff --git a/src/sem/alias_type.cc b/src/sem/alias_type.cc index d40001c878..8e5e750214 100644 --- a/src/sem/alias_type.cc +++ b/src/sem/alias_type.cc @@ -22,7 +22,9 @@ namespace tint { namespace sem { Alias::Alias(const Symbol& sym, const Type* subtype) - : symbol_(sym), subtype_(subtype) { + : symbol_(sym), + subtype_(subtype), + type_name_("__alias_" + sym.to_str() + subtype->type_name()) { TINT_ASSERT(subtype_); } @@ -31,7 +33,7 @@ Alias::Alias(Alias&&) = default; Alias::~Alias() = default; std::string Alias::type_name() const { - return "__alias_" + symbol_.to_str() + subtype_->type_name(); + return type_name_; } std::string Alias::FriendlyName(const SymbolTable& symbols) const { diff --git a/src/sem/alias_type.h b/src/sem/alias_type.h index e4544e0e0c..75ffe0a0e3 100644 --- a/src/sem/alias_type.h +++ b/src/sem/alias_type.h @@ -54,7 +54,8 @@ class Alias : public Castable { private: Symbol const symbol_; - const Type* const subtype_; + Type const* const subtype_; + std::string const type_name_; }; } // namespace sem diff --git a/src/sem/alias_type_test.cc b/src/sem/alias_type_test.cc index 05bb8520b1..62b96a10ea 100644 --- a/src/sem/alias_type_test.cc +++ b/src/sem/alias_type_test.cc @@ -46,6 +46,19 @@ TEST_F(AliasTest, Is) { EXPECT_FALSE(ty->Is()); } +// Check for linear-time evaluation of Alias::type_name(). +// If type_name() is non-linear, this test should noticeably stall. +// See: crbug.com/1200936 +TEST_F(AliasTest, TypeName_LinearTime) { + Type* type = ty.i32(); + for (int i = 0; i < 1024; i++) { + type = create(Symbols().New(), type); + } + for (int i = 0; i < 16384; i++) { + type->type_name(); + } +} + TEST_F(AliasTest, TypeName) { auto* at = create(Sym("Particle"), ty.i32()); EXPECT_EQ(at->type_name(), "__alias_$1__i32");