summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Lively <7121787+tlively@users.noreply.github.com>2022-01-27 10:26:31 -0800
committerGitHub <noreply@github.com>2022-01-27 10:26:31 -0800
commit8265388adc8341d52aa075b937ea3f0b10c05a9f (patch)
tree8b7a87da842e1d23156ad913eba58952f58a0172
parentdd6f63524c35b8b9fa0cb8745f305d5dac56d545 (diff)
downloadbinaryen-8265388adc8341d52aa075b937ea3f0b10c05a9f.tar.gz
binaryen-8265388adc8341d52aa075b937ea3f0b10c05a9f.tar.bz2
binaryen-8265388adc8341d52aa075b937ea3f0b10c05a9f.zip
Add a HeapType method for getting the rec group index (#4480)
Storing the rec group index on the HeapTypeInfo avoids having to do a linear scan through the rec group to find the index for a particular type. This will be important for isorecursive canonicalization, which uses rec group indices.
-rw-r--r--src/wasm-type.h5
-rw-r--r--src/wasm/wasm-type.cpp7
-rw-r--r--test/gtest/type-builder.cpp27
3 files changed, 37 insertions, 2 deletions
diff --git a/src/wasm-type.h b/src/wasm-type.h
index 7b63adf9d..99194b81d 100644
--- a/src/wasm-type.h
+++ b/src/wasm-type.h
@@ -356,6 +356,7 @@ public:
// Get the recursion group for this non-basic type.
RecGroup getRecGroup() const;
+ size_t getRecGroupIndex() const;
constexpr TypeID getID() const { return id; }
constexpr BasicHeapType getBasic() const {
@@ -392,8 +393,8 @@ class RecGroup {
public:
explicit RecGroup(uintptr_t id) : id(id) {}
- bool operator==(const RecGroup& other) { return id == other.id; }
- bool operator!=(const RecGroup& other) { return id != other.id; }
+ bool operator==(const RecGroup& other) const { return id == other.id; }
+ bool operator!=(const RecGroup& other) const { return id != other.id; }
size_t size() const;
struct Iterator : ParentIndexIterator<const RecGroup*, Iterator> {
diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp
index 53de89aa5..f63505b20 100644
--- a/src/wasm/wasm-type.cpp
+++ b/src/wasm/wasm-type.cpp
@@ -113,6 +113,7 @@ struct HeapTypeInfo {
// In isorecursive mode, the recursion group of this type or null if the
// recursion group is trivial (i.e. contains only this type).
RecGroupInfo* recGroup = nullptr;
+ size_t recGroupIndex = 0;
enum Kind {
BasicKind,
SignatureKind,
@@ -1263,6 +1264,11 @@ RecGroup HeapType::getRecGroup() const {
}
}
+size_t HeapType::getRecGroupIndex() const {
+ assert(!isBasic());
+ return getHeapTypeInfo(*this)->recGroupIndex;
+}
+
HeapType RecGroup::Iterator::operator*() const {
if (parent->id & 1) {
// This is a trivial recursion group. Mask off the low bit to recover the
@@ -3242,6 +3248,7 @@ std::optional<TypeBuilder::Error> canonicalizeIsorecursive(
// Fill out the recursion groups.
for (auto& info : state.newInfos) {
if (info->recGroup != nullptr) {
+ info->recGroupIndex = info->recGroup->size();
info->recGroup->push_back(asHeapType(info));
}
}
diff --git a/test/gtest/type-builder.cpp b/test/gtest/type-builder.cpp
index 78c8037a4..9cbd04298 100644
--- a/test/gtest/type-builder.cpp
+++ b/test/gtest/type-builder.cpp
@@ -242,3 +242,30 @@ TEST_F(IsorecursiveTest, ForwardReferencedChild) {
EXPECT_EQ(error->reason, TypeBuilder::ErrorReason::ForwardChildReference);
EXPECT_EQ(error->index, 1u);
}
+
+TEST_F(IsorecursiveTest, RecGroupIndices) {
+ TypeBuilder builder(5);
+
+ builder.createRecGroup(0, 2);
+ builder[0] = Struct{};
+ builder[1] = Struct{};
+
+ builder.createRecGroup(2, 3);
+ builder[2] = Struct{};
+ builder[3] = Struct{};
+ builder[4] = Struct{};
+
+ auto result = builder.build();
+ ASSERT_TRUE(result);
+ auto built = *result;
+
+ EXPECT_EQ(built[0].getRecGroup(), built[1].getRecGroup());
+ EXPECT_EQ(built[0].getRecGroupIndex(), 0u);
+ EXPECT_EQ(built[1].getRecGroupIndex(), 1u);
+
+ EXPECT_EQ(built[2].getRecGroup(), built[3].getRecGroup());
+ EXPECT_EQ(built[3].getRecGroup(), built[4].getRecGroup());
+ EXPECT_EQ(built[2].getRecGroupIndex(), 0u);
+ EXPECT_EQ(built[3].getRecGroupIndex(), 1u);
+ EXPECT_EQ(built[4].getRecGroupIndex(), 2u);
+}