[WHLSL] Metal code generation takes a long time uniquing UnnamedTypes
authorweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 7 Aug 2019 23:47:49 +0000 (23:47 +0000)
committerweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 7 Aug 2019 23:47:49 +0000 (23:47 +0000)
https://bugs.webkit.org/show_bug.cgi?id=200512

Reviewed by Saam Barati.

Instead of using a trie for unnamed type uniquing, use the same technique used
in SynthesizeConstructors and use a HashMap of UnnamedTypeKeys. To make this
profitable, we also need to devirtualize the hash and equality functions on
UnnamedType, instead using an enum + switch. While this change only devirtualizes
the UnnamedType subtree, we should probably do it for the entire AST in a future
change.

* Modules/webgpu/WHLSL/AST/WHLSLArrayReferenceType.h:
* Modules/webgpu/WHLSL/AST/WHLSLArrayType.h:
* Modules/webgpu/WHLSL/AST/WHLSLPointerType.h:
* Modules/webgpu/WHLSL/AST/WHLSLReferenceType.h:
* Modules/webgpu/WHLSL/AST/WHLSLTypeReference.h:
* Modules/webgpu/WHLSL/AST/WHLSLUnnamedType.cpp: Added.
(WebCore::WHLSL::AST::UnnamedType::hash const):
(WebCore::WHLSL::AST::UnnamedType::operator== const):
 * Modules/webgpu/WHLSL/AST/WHLSLUnnamedType.h:
Devirtualize hash, operator== and type predicates.

* Modules/webgpu/WHLSL/AST/WHLSLUnnamedTypeHash.h: Added.
(WebCore::WHLSL::UnnamedTypeKey::UnnamedTypeKey):
* Modules/webgpu/WHLSL/WHLSLSynthesizeConstructors.cpp:
(WebCore::WHLSL::UnnamedTypeKey::UnnamedTypeKey): Deleted.
Moved UnnamedTypeKey into it's own header from WHLSLSynthesizeConstructors.cpp

* Modules/webgpu/WHLSL/Metal/WHLSLTypeNamer.cpp:
(WebCore::WHLSL::Metal::BaseTypeNameNode::BaseTypeNameNode):
(WebCore::WHLSL::Metal::BaseTypeNameNode::kind):
(WebCore::WHLSL::Metal::BaseTypeNameNode::isReferenceTypeNameNode const):
(WebCore::WHLSL::Metal::BaseTypeNameNode::isPointerTypeNameNode const):
(WebCore::WHLSL::Metal::BaseTypeNameNode::isArrayReferenceTypeNameNode const):
(WebCore::WHLSL::Metal::BaseTypeNameNode::isArrayTypeNameNode const):
Devirtualize BaseTypeNameNode as well. In a future change, we should consider removing
this class entirely and instead mapping directly to a parent/mangled name pair.

(WebCore::WHLSL::Metal::TypeNamer::visit):
(WebCore::WHLSL::Metal::TypeNamer::find):
(WebCore::WHLSL::Metal::TypeNamer::createNameNode):
(WebCore::WHLSL::Metal::parent):
(WebCore::WHLSL::Metal::TypeNamer::insert):
(WebCore::WHLSL::Metal::TypeNamer::emitUnnamedTypeDefinition):
(WebCore::WHLSL::Metal::TypeNamer::emitMetalTypeDefinitions):
(WebCore::WHLSL::Metal::TypeNamer::mangledNameForType):
(WebCore::WHLSL::Metal::findInVector): Deleted.
(WebCore::WHLSL::Metal::find): Deleted.
(WebCore::WHLSL::Metal::TypeNamer::emitAllUnnamedTypeDefinitions): Deleted.
* Modules/webgpu/WHLSL/Metal/WHLSLTypeNamer.h:
Switch from a Vector based trie to a HashMap for UnnamedType uniquing. Also
use UnnamedType::Kind where possible with switch statements to clarify code.

* WebCore.xcodeproj/project.pbxproj:
Add new files.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@248395 268f45cc-cd09-0410-ab3c-d52691b4dbfc

13 files changed:
Source/WebCore/ChangeLog
Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLArrayReferenceType.h
Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLArrayType.h
Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLPointerType.h
Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLReferenceType.h
Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLTypeReference.h
Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLUnnamedType.cpp [new file with mode: 0644]
Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLUnnamedType.h
Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLUnnamedTypeHash.h [new file with mode: 0644]
Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLTypeNamer.cpp
Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLTypeNamer.h
Source/WebCore/Modules/webgpu/WHLSL/WHLSLSynthesizeConstructors.cpp
Source/WebCore/WebCore.xcodeproj/project.pbxproj

index f007345..c4b14f0 100644 (file)
@@ -1,3 +1,62 @@
+2019-08-07  Sam Weinig  <weinig@apple.com>
+
+        [WHLSL] Metal code generation takes a long time uniquing UnnamedTypes
+        https://bugs.webkit.org/show_bug.cgi?id=200512
+
+        Reviewed by Saam Barati.
+
+        Instead of using a trie for unnamed type uniquing, use the same technique used
+        in SynthesizeConstructors and use a HashMap of UnnamedTypeKeys. To make this
+        profitable, we also need to devirtualize the hash and equality functions on
+        UnnamedType, instead using an enum + switch. While this change only devirtualizes
+        the UnnamedType subtree, we should probably do it for the entire AST in a future
+        change.
+
+        * Modules/webgpu/WHLSL/AST/WHLSLArrayReferenceType.h:
+        * Modules/webgpu/WHLSL/AST/WHLSLArrayType.h:
+        * Modules/webgpu/WHLSL/AST/WHLSLPointerType.h:
+        * Modules/webgpu/WHLSL/AST/WHLSLReferenceType.h:
+        * Modules/webgpu/WHLSL/AST/WHLSLTypeReference.h:
+        * Modules/webgpu/WHLSL/AST/WHLSLUnnamedType.cpp: Added.
+        (WebCore::WHLSL::AST::UnnamedType::hash const):
+        (WebCore::WHLSL::AST::UnnamedType::operator== const):
+         * Modules/webgpu/WHLSL/AST/WHLSLUnnamedType.h:
+        Devirtualize hash, operator== and type predicates.
+
+        * Modules/webgpu/WHLSL/AST/WHLSLUnnamedTypeHash.h: Added.
+        (WebCore::WHLSL::UnnamedTypeKey::UnnamedTypeKey):
+        * Modules/webgpu/WHLSL/WHLSLSynthesizeConstructors.cpp:
+        (WebCore::WHLSL::UnnamedTypeKey::UnnamedTypeKey): Deleted.
+        Moved UnnamedTypeKey into it's own header from WHLSLSynthesizeConstructors.cpp
+        
+        * Modules/webgpu/WHLSL/Metal/WHLSLTypeNamer.cpp:
+        (WebCore::WHLSL::Metal::BaseTypeNameNode::BaseTypeNameNode):
+        (WebCore::WHLSL::Metal::BaseTypeNameNode::kind):
+        (WebCore::WHLSL::Metal::BaseTypeNameNode::isReferenceTypeNameNode const):
+        (WebCore::WHLSL::Metal::BaseTypeNameNode::isPointerTypeNameNode const):
+        (WebCore::WHLSL::Metal::BaseTypeNameNode::isArrayReferenceTypeNameNode const):
+        (WebCore::WHLSL::Metal::BaseTypeNameNode::isArrayTypeNameNode const):
+        Devirtualize BaseTypeNameNode as well. In a future change, we should consider removing
+        this class entirely and instead mapping directly to a parent/mangled name pair.
+        (WebCore::WHLSL::Metal::TypeNamer::visit):
+        (WebCore::WHLSL::Metal::TypeNamer::find):
+        (WebCore::WHLSL::Metal::TypeNamer::createNameNode):
+        (WebCore::WHLSL::Metal::parent):
+        (WebCore::WHLSL::Metal::TypeNamer::insert):
+        (WebCore::WHLSL::Metal::TypeNamer::emitUnnamedTypeDefinition):
+        (WebCore::WHLSL::Metal::TypeNamer::emitMetalTypeDefinitions):
+        (WebCore::WHLSL::Metal::TypeNamer::mangledNameForType):
+        (WebCore::WHLSL::Metal::findInVector): Deleted.
+        (WebCore::WHLSL::Metal::find): Deleted.
+        (WebCore::WHLSL::Metal::TypeNamer::emitAllUnnamedTypeDefinitions): Deleted.
+        * Modules/webgpu/WHLSL/Metal/WHLSLTypeNamer.h:
+        Switch from a Vector based trie to a HashMap for UnnamedType uniquing. Also
+        use UnnamedType::Kind where possible with switch statements to clarify code.
+
+        * WebCore.xcodeproj/project.pbxproj:
+        Add new files.
+
 2019-08-07  Devin Rousso  <drousso@apple.com>
 
         Web Inspector: Uncaught Exception: TimelineAgent already enabled
index a32d7dc..bb0d886 100644 (file)
@@ -40,13 +40,13 @@ namespace WHLSL {
 
 namespace AST {
 
-class ArrayReferenceType : public ReferenceType {
+class ArrayReferenceType final : public ReferenceType {
     WTF_MAKE_FAST_ALLOCATED;
     WTF_MAKE_NONCOPYABLE(ArrayReferenceType);
     using Base = ReferenceType;
 
     ArrayReferenceType(CodeLocation location, AddressSpace addressSpace, Ref<UnnamedType> elementType)
-        : Base(location, addressSpace, WTFMove(elementType))
+        : Base(location, addressSpace, WTFMove(elementType), Kind::ArrayReferenceType)
     {
     }
 public:
@@ -57,28 +57,20 @@ public:
 
     virtual ~ArrayReferenceType() = default;
 
-    bool isArrayReferenceType() const override { return true; }
-
-    unsigned hash() const override
+    unsigned hash() const
     {
         return this->Base::hash() ^ StringHasher::computeLiteralHash("array");
     }
 
-    bool operator==(const UnnamedType& other) const override
+    bool operator==(const ArrayReferenceType& other) const
     {
-        if (!is<ArrayReferenceType>(other))
-            return false;
-
-        return addressSpace() == downcast<ArrayReferenceType>(other).addressSpace()
-            && elementType() == downcast<ArrayReferenceType>(other).elementType();
+        return addressSpace() == other.addressSpace() && elementType() == other.elementType();
     }
 
     String toString() const override
     {
         return makeString(elementType().toString(), "[]");
     }
-
-private:
 };
 
 } // namespace AST
index fc7acc3..9778037 100644 (file)
@@ -33,6 +33,7 @@
 #include <wtf/FastMalloc.h>
 #include <wtf/Noncopyable.h>
 #include <wtf/UniqueRef.h>
+#include <wtf/text/StringConcatenateNumbers.h>
 #include <wtf/text/WTFString.h>
 
 namespace WebCore {
@@ -45,7 +46,7 @@ class ArrayType final : public UnnamedType {
     WTF_MAKE_FAST_ALLOCATED;
     WTF_MAKE_NONCOPYABLE(ArrayType);
     ArrayType(CodeLocation location, Ref<UnnamedType> elementType, unsigned numElements)
-        : UnnamedType(location)
+        : UnnamedType(location, Kind::ArrayType)
         , m_elementType(WTFMove(elementType))
         , m_numElements(numElements)
     {
@@ -59,24 +60,18 @@ public:
 
     virtual ~ArrayType() = default;
 
-    bool isArrayType() const override { return true; }
-
     const UnnamedType& type() const { return m_elementType; }
     UnnamedType& type() { return m_elementType; }
     unsigned numElements() const { return m_numElements; }
 
-    unsigned hash() const override
+    unsigned hash() const
     {
         return WTF::IntHash<unsigned>::hash(m_numElements) ^ m_elementType->hash();
     }
 
-    bool operator==(const UnnamedType& other) const override
+    bool operator==(const ArrayType& other) const
     {
-        if (!is<ArrayType>(other))
-            return false;
-
-        return numElements() == downcast<ArrayType>(other).numElements()
-            && type() == downcast<ArrayType>(other).type();
+        return numElements() == other.numElements() && type() == other.type();
     }
 
     String toString() const override
index f30ca58..613a69d 100644 (file)
@@ -46,7 +46,7 @@ class PointerType final : public ReferenceType {
     using Base = ReferenceType;
 
     PointerType(CodeLocation location, AddressSpace addressSpace, Ref<UnnamedType> elementType)
-        : Base(location, addressSpace, WTFMove(elementType))
+        : Base(location, addressSpace, WTFMove(elementType), Kind::PointerType)
     {
     }
 
@@ -58,20 +58,14 @@ public:
 
     virtual ~PointerType() = default;
 
-    bool isPointerType() const override { return true; }
-
-    unsigned hash() const override
+    unsigned hash() const
     {
         return this->Base::hash() ^ StringHasher::computeLiteralHash("pointer");
     }
 
-    bool operator==(const UnnamedType& other) const override
+    bool operator==(const PointerType& other) const
     {
-        if (!is<PointerType>(other))
-            return false;
-
-        return addressSpace() == downcast<PointerType>(other).addressSpace()
-            && elementType() == downcast<PointerType>(other).elementType();
+        return addressSpace() == other.addressSpace() && elementType() == other.elementType();
     }
 
     String toString() const override
index 431e7ec..16a6db3 100644 (file)
@@ -44,23 +44,20 @@ class ReferenceType : public UnnamedType {
     WTF_MAKE_FAST_ALLOCATED;
     WTF_MAKE_NONCOPYABLE(ReferenceType);
 protected:
-    ReferenceType(CodeLocation location, AddressSpace addressSpace, Ref<UnnamedType> elementType)
-        : UnnamedType(location)
+    ReferenceType(CodeLocation location, AddressSpace addressSpace, Ref<UnnamedType> elementType, Kind kind)
+        : UnnamedType(location, kind)
         , m_addressSpace(addressSpace)
         , m_elementType(WTFMove(elementType))
     {
     }
 public:
-
     virtual ~ReferenceType() = default;
 
-    bool isReferenceType() const override { return true; }
-
     AddressSpace addressSpace() const { return m_addressSpace; }
     const UnnamedType& elementType() const { return m_elementType; }
     UnnamedType& elementType() { return m_elementType; }
 
-    unsigned hash() const override
+    unsigned hash() const
     {
         return ~m_elementType->hash();
     }
index fba3f91..edaff9e 100644 (file)
@@ -48,7 +48,7 @@ class TypeReference final : public UnnamedType {
     WTF_MAKE_FAST_ALLOCATED;
     WTF_MAKE_NONCOPYABLE(TypeReference);
     TypeReference(CodeLocation location, String&& name, TypeArguments&& typeArguments)
-        : UnnamedType(location)
+        : UnnamedType(location, Kind::TypeReference)
         , m_name(WTFMove(name))
         , m_typeArguments(WTFMove(typeArguments))
     {
@@ -63,8 +63,6 @@ public:
 
     static Ref<TypeReference> wrap(CodeLocation, NamedType& resolvedType);
 
-    bool isTypeReference() const override { return true; }
-
     String& name() { return m_name; }
     TypeArguments& typeArguments() { return m_typeArguments; }
     NamedType* maybeResolvedType() const { return m_resolvedType; }
@@ -91,7 +89,7 @@ public:
         m_resolvedType = &resolvedType;
     }
 
-    unsigned hash() const override
+    unsigned hash() const
     {
         // Currently, we only use this function after the name resolver runs.
         // Relying on having a resolved type simplifies this implementation.
@@ -99,13 +97,10 @@ public:
         return WTF::PtrHash<const Type*>::hash(&unifyNode());
     }
 
-    bool operator==(const UnnamedType& other) const override
+    bool operator==(const TypeReference& other) const
     {
         ASSERT(m_resolvedType);
-        if (!is<TypeReference>(other))
-            return false;
-
-        return &unifyNode() == &downcast<TypeReference>(other).unifyNode();
+        return &unifyNode() == &other.unifyNode();
     }
 
     String toString() const override
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLUnnamedType.cpp b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLUnnamedType.cpp
new file mode 100644 (file)
index 0000000..03a127a
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WHLSLUnnamedType.h"
+
+#if ENABLE(WEBGPU)
+
+#include "WHLSLArrayReferenceType.h"
+#include "WHLSLArrayType.h"
+#include "WHLSLPointerType.h"
+#include "WHLSLTypeReference.h"
+
+namespace WebCore {
+
+namespace WHLSL {
+
+namespace AST {
+
+unsigned UnnamedType::hash() const
+{
+    switch (m_kind) {
+    case Kind::TypeReference:
+        return downcast<TypeReference>(*this).hash();
+    case Kind::PointerType:
+        return downcast<PointerType>(*this).hash();
+    case Kind::ArrayReferenceType:
+        return downcast<ArrayReferenceType>(*this).hash();
+    case Kind::ArrayType:
+        return downcast<ArrayType>(*this).hash();
+    }
+}
+
+bool UnnamedType::operator==(const UnnamedType& other) const
+{
+    if (other.m_kind != m_kind)
+        return false;
+
+    switch (m_kind) {
+    case Kind::TypeReference:
+        return downcast<TypeReference>(*this) == downcast<TypeReference>(other);
+    case Kind::PointerType:
+        return downcast<PointerType>(*this) == downcast<PointerType>(other);
+    case Kind::ArrayReferenceType:
+        return downcast<ArrayReferenceType>(*this) == downcast<ArrayReferenceType>(other);
+    case Kind::ArrayType:
+        return downcast<ArrayType>(*this) == downcast<ArrayType>(other);
+    }
+}
+
+} // namespace AST
+
+} // namespace WHLSL
+
+} // namespace WebCore
+
+#endif
index 0f0e4e8..d472c1e 100644 (file)
@@ -45,25 +45,35 @@ class UnnamedType : public Type, public RefCounted<UnnamedType> {
     WTF_MAKE_FAST_ALLOCATED;
     WTF_MAKE_NONCOPYABLE(UnnamedType);
 public:
-    UnnamedType(CodeLocation location)
+    enum class Kind {
+        TypeReference,
+        PointerType,
+        ArrayReferenceType,
+        ArrayType
+    };
+
+    UnnamedType(CodeLocation location, Kind kind)
         : m_codeLocation(location)
+        , m_kind(kind)
     {
     }
 
     virtual ~UnnamedType() = default;
 
     bool isUnnamedType() const override { return true; }
-    virtual bool isTypeReference() const { return false; }
-    virtual bool isPointerType() const { return false; }
-    virtual bool isArrayReferenceType() const { return false; }
-    virtual bool isArrayType() const { return false; }
-    virtual bool isReferenceType() const { return false; }
+
+    Kind kind() const { return m_kind; }
+    bool isTypeReference() const { return m_kind == Kind::TypeReference; }
+    bool isPointerType() const { return m_kind == Kind::PointerType; }
+    bool isArrayReferenceType() const { return m_kind == Kind::ArrayReferenceType; }
+    bool isArrayType() const { return m_kind == Kind::ArrayType; }
+    bool isReferenceType() const { return isPointerType() || isArrayReferenceType(); }
 
     virtual const Type& unifyNode() const { return *this; }
     virtual Type& unifyNode() { return *this; }
 
-    virtual unsigned hash() const = 0;
-    virtual bool operator==(const UnnamedType&) const = 0;
+    unsigned hash() const;
+    bool operator==(const UnnamedType&) const;
 
     virtual String toString() const = 0;
 
@@ -71,6 +81,7 @@ public:
 
 private:
     CodeLocation m_codeLocation;
+    Kind m_kind;
 };
 
 } // namespace AST
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLUnnamedTypeHash.h b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLUnnamedTypeHash.h
new file mode 100644 (file)
index 0000000..3dbbb05
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(WEBGPU)
+
+#include "WHLSLUnnamedType.h"
+#include <wtf/HashTraits.h>
+
+namespace WebCore {
+
+namespace WHLSL {
+
+class UnnamedTypeKey {
+public:
+    UnnamedTypeKey() = default;
+    UnnamedTypeKey(WTF::HashTableDeletedValueType)
+        : m_type(bitwise_cast<AST::UnnamedType*>(static_cast<uintptr_t>(1)))
+    {
+    }
+
+    UnnamedTypeKey(AST::UnnamedType& type)
+        : m_type(&type)
+    {
+    }
+
+    bool isEmptyValue() const { return !m_type; }
+    bool isHashTableDeletedValue() const { return m_type == bitwise_cast<AST::UnnamedType*>(static_cast<uintptr_t>(1)); }
+
+    unsigned hash() const { return m_type->hash(); }
+    bool operator==(const UnnamedTypeKey& other) const { return *m_type == *other.m_type; }
+    AST::UnnamedType& unnamedType() const { return *m_type; }
+
+    struct Hash {
+        static unsigned hash(const UnnamedTypeKey& key) { return key.hash(); }
+        static bool equal(const UnnamedTypeKey& a, const UnnamedTypeKey& b) { return a == b; }
+        static const bool safeToCompareToEmptyOrDeleted = false;
+        static const bool emptyValueIsZero = true;
+    };
+
+    struct Traits : public WTF::SimpleClassHashTraits<UnnamedTypeKey> {
+        static const bool hasIsEmptyValueFunction = true;
+        static bool isEmptyValue(const UnnamedTypeKey& key) { return key.isEmptyValue(); }
+    };
+
+private:
+    AST::UnnamedType* m_type { nullptr };
+};
+
+}
+
+}
+
+#endif
index b4dc0e3..fa8c914 100644 (file)
@@ -58,91 +58,87 @@ namespace WHLSL {
 
 namespace Metal {
 
+// FIXME: Look into replacing BaseTypeNameNode with a simple struct { RefPtr<UnnamedType> parent; MangledTypeName; } that UnnamedTypeKeys map to.
 class BaseTypeNameNode {
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    BaseTypeNameNode(BaseTypeNameNode* parent, MangledTypeName&& mangledName)
+    BaseTypeNameNode(BaseTypeNameNode* parent, MangledTypeName&& mangledName, AST::UnnamedType::Kind kind)
         : m_parent(parent)
         , m_mangledName(mangledName)
+        , m_kind(kind)
     {
     }
     virtual ~BaseTypeNameNode() = default;
-    virtual bool isArrayTypeNameNode() const { return false; }
-    virtual bool isArrayReferenceTypeNameNode() const { return false; }
-    virtual bool isPointerTypeNameNode() const { return false; }
-    virtual bool isReferenceTypeNameNode() const { return false; }
-    Vector<UniqueRef<BaseTypeNameNode>>& children() { return m_children; }
-    void append(UniqueRef<BaseTypeNameNode>&& child)
-    {
-        m_children.append(WTFMove(child));
-    }
+    
+    AST::UnnamedType::Kind kind() { return m_kind; }
+    bool isReferenceTypeNameNode() const { return m_kind == AST::UnnamedType::Kind::TypeReference; }
+    bool isPointerTypeNameNode() const { return m_kind == AST::UnnamedType::Kind::PointerType; }
+    bool isArrayReferenceTypeNameNode() const { return m_kind == AST::UnnamedType::Kind::ArrayReferenceType; }
+    bool isArrayTypeNameNode() const { return m_kind == AST::UnnamedType::Kind::ArrayType; }
+
     BaseTypeNameNode* parent() { return m_parent; }
     MangledTypeName mangledName() const { return m_mangledName; }
 
 private:
-    Vector<UniqueRef<BaseTypeNameNode>> m_children;
     BaseTypeNameNode* m_parent;
     MangledTypeName m_mangledName;
+    AST::UnnamedType::Kind m_kind;
 };
 
-class ArrayTypeNameNode : public BaseTypeNameNode {
+class ArrayTypeNameNode final : public BaseTypeNameNode {
     WTF_MAKE_FAST_ALLOCATED;
 public:
     ArrayTypeNameNode(BaseTypeNameNode* parent, MangledTypeName&& mangledName, unsigned numElements)
-        : BaseTypeNameNode(parent, WTFMove(mangledName))
+        : BaseTypeNameNode(parent, WTFMove(mangledName), AST::UnnamedType::Kind::ArrayType)
         , m_numElements(numElements)
     {
     }
     virtual ~ArrayTypeNameNode() = default;
-    bool isArrayTypeNameNode() const override { return true; }
     unsigned numElements() const { return m_numElements; }
 
 private:
     unsigned m_numElements;
 };
 
-class ArrayReferenceTypeNameNode : public BaseTypeNameNode {
+class ArrayReferenceTypeNameNode final : public BaseTypeNameNode {
     WTF_MAKE_FAST_ALLOCATED;
 public:
     ArrayReferenceTypeNameNode(BaseTypeNameNode* parent, MangledTypeName&& mangledName, AST::AddressSpace addressSpace)
-        : BaseTypeNameNode(parent, WTFMove(mangledName))
+        : BaseTypeNameNode(parent, WTFMove(mangledName), AST::UnnamedType::Kind::ArrayReferenceType)
         , m_addressSpace(addressSpace)
     {
     }
     virtual ~ArrayReferenceTypeNameNode() = default;
-    bool isArrayReferenceTypeNameNode() const override { return true; }
     AST::AddressSpace addressSpace() const { return m_addressSpace; }
 
 private:
     AST::AddressSpace m_addressSpace;
 };
 
-class PointerTypeNameNode : public BaseTypeNameNode {
+class PointerTypeNameNode final : public BaseTypeNameNode {
     WTF_MAKE_FAST_ALLOCATED;
 public:
     PointerTypeNameNode(BaseTypeNameNode* parent, MangledTypeName&& mangledName, AST::AddressSpace addressSpace)
-        : BaseTypeNameNode(parent, WTFMove(mangledName))
+        : BaseTypeNameNode(parent, WTFMove(mangledName), AST::UnnamedType::Kind::PointerType)
         , m_addressSpace(addressSpace)
     {
     }
     virtual ~PointerTypeNameNode() = default;
-    bool isPointerTypeNameNode() const override { return true; }
     AST::AddressSpace addressSpace() const { return m_addressSpace; }
 
 private:
     AST::AddressSpace m_addressSpace;
 };
 
-class ReferenceTypeNameNode : public BaseTypeNameNode {
+class ReferenceTypeNameNode final : public BaseTypeNameNode {
     WTF_MAKE_FAST_ALLOCATED;
 public:
     ReferenceTypeNameNode(BaseTypeNameNode* parent, MangledTypeName&& mangledName, AST::NamedType& namedType)
-        : BaseTypeNameNode(parent, WTFMove(mangledName))
+        : BaseTypeNameNode(parent, WTFMove(mangledName), AST::UnnamedType::Kind::TypeReference)
         , m_namedType(namedType)
     {
     }
     virtual ~ReferenceTypeNameNode() = default;
-    bool isReferenceTypeNameNode() const override { return true; }
     AST::NamedType& namedType() { return m_namedType; }
 
 private:
@@ -181,42 +177,9 @@ TypeNamer::TypeNamer(Program& program)
 
 TypeNamer::~TypeNamer() = default;
 
-static Vector<UniqueRef<BaseTypeNameNode>>::iterator findInVector(AST::UnnamedType& unnamedType, Vector<UniqueRef<BaseTypeNameNode>>& types)
-{
-    return std::find_if(types.begin(), types.end(), [&](BaseTypeNameNode& baseTypeNameNode) -> bool {
-        if (is<AST::TypeReference>(unnamedType) && is<ReferenceTypeNameNode>(baseTypeNameNode)) {
-            auto& resolvedType = downcast<AST::TypeReference>(unnamedType).resolvedType();
-            return &resolvedType == &downcast<ReferenceTypeNameNode>(baseTypeNameNode).namedType();
-        }
-        if (is<AST::PointerType>(unnamedType) && is<PointerTypeNameNode>(baseTypeNameNode))
-            return downcast<AST::PointerType>(unnamedType).addressSpace() == downcast<PointerTypeNameNode>(baseTypeNameNode).addressSpace();
-        if (is<AST::ArrayReferenceType>(unnamedType) && is<ArrayReferenceTypeNameNode>(baseTypeNameNode))
-            return downcast<AST::ArrayReferenceType>(unnamedType).addressSpace() == downcast<ArrayReferenceTypeNameNode>(baseTypeNameNode).addressSpace();
-        if (is<AST::ArrayType>(unnamedType) && is<ArrayTypeNameNode>(baseTypeNameNode))
-            return downcast<AST::ArrayType>(unnamedType).numElements() == downcast<ArrayTypeNameNode>(baseTypeNameNode).numElements();
-        return false;
-    });
-}
-
-static BaseTypeNameNode& find(AST::UnnamedType& unnamedType, Vector<UniqueRef<BaseTypeNameNode>>& types)
-{
-    auto& vectorToSearch = ([&]() -> Vector<UniqueRef<BaseTypeNameNode>>& {
-        if (is<AST::TypeReference>(unnamedType))
-            return types;
-        if (is<AST::PointerType>(unnamedType))
-            return find(downcast<AST::PointerType>(unnamedType).elementType(), types).children();
-        if (is<AST::ArrayReferenceType>(unnamedType))
-            return find(downcast<AST::ArrayReferenceType>(unnamedType).elementType(), types).children();
-        return find(downcast<AST::ArrayType>(unnamedType).type(), types).children();
-    })();
-    auto iterator = findInVector(unnamedType, vectorToSearch);
-    ASSERT(iterator != types.end());
-    return *iterator;
-}
-
 void TypeNamer::visit(AST::UnnamedType& unnamedType)
 {
-    insert(unnamedType, m_trie);
+    insert(unnamedType);
 }
 
 void TypeNamer::visit(AST::EnumerationDefinition& enumerationDefinition)
@@ -234,7 +197,7 @@ void TypeNamer::visit(AST::EnumerationDefinition& enumerationDefinition)
     Visitor::visit(enumerationDefinition);
 
     {
-        Vector<std::reference_wrapper<BaseTypeNameNode>> neighbors = { find(enumerationDefinition.type(), m_trie) };
+        Vector<std::reference_wrapper<BaseTypeNameNode>> neighbors = { find(enumerationDefinition.type()) };
         auto addResult = m_dependencyGraph.add(&enumerationDefinition, WTFMove(neighbors));
         ASSERT_UNUSED(addResult, addResult.isNewEntry);
     }
@@ -259,7 +222,7 @@ void TypeNamer::visit(AST::StructureDefinition& structureDefinition)
         for (auto& structureElement : structureDefinition.structureElements()) {
             auto addResult = m_structureElementMapping.add(&structureElement, generateNextStructureElementName());
             ASSERT_UNUSED(addResult, addResult.isNewEntry);
-            neighbors.append(find(structureElement.type(), m_trie));
+            neighbors.append(find(structureElement.type()));
         }
         auto addResult = m_dependencyGraph.add(&structureDefinition, WTFMove(neighbors));
         ASSERT_UNUSED(addResult, addResult.isNewEntry);
@@ -274,7 +237,7 @@ void TypeNamer::visit(AST::TypeDefinition& typeDefinition)
     }
     Visitor::visit(typeDefinition);
     {
-        Vector<std::reference_wrapper<BaseTypeNameNode>> neighbors = { find(typeDefinition.type(), m_trie) };
+        Vector<std::reference_wrapper<BaseTypeNameNode>> neighbors = { find(typeDefinition.type()) };
         auto addResult = m_dependencyGraph.add(&typeDefinition, WTFMove(neighbors));
         ASSERT_UNUSED(addResult, addResult.isNewEntry);
     }
@@ -282,7 +245,7 @@ void TypeNamer::visit(AST::TypeDefinition& typeDefinition)
 
 void TypeNamer::visit(AST::Expression& expression)
 {
-    insert(expression.resolvedType(), m_trie);
+    insert(expression.resolvedType());
     Visitor::visit(expression);
 }
 
@@ -297,58 +260,63 @@ String TypeNamer::mangledNameForType(AST::NativeTypeDeclaration& nativeTypeDecla
     return writeNativeType(nativeTypeDeclaration);
 }
 
-UniqueRef<BaseTypeNameNode> TypeNamer::createNameNode(AST::UnnamedType& unnamedType, BaseTypeNameNode* parent)
+BaseTypeNameNode& TypeNamer::find(AST::UnnamedType& unnamedType)
 {
-    if (is<AST::TypeReference>(unnamedType)) {
+    auto iterator = m_unnamedTypesUniquingMap.find(unnamedType);
+    ASSERT(iterator != m_unnamedTypesUniquingMap.end());
+    return *iterator->value;
+}
+
+std::unique_ptr<BaseTypeNameNode> TypeNamer::createNameNode(AST::UnnamedType& unnamedType, BaseTypeNameNode* parent)
+{
+    switch (unnamedType.kind()) {
+    case AST::UnnamedType::Kind::TypeReference: {
         auto& typeReference = downcast<AST::TypeReference>(unnamedType);
-        return makeUniqueRef<ReferenceTypeNameNode>(parent, generateNextTypeName(), typeReference.resolvedType());
+        return std::make_unique<ReferenceTypeNameNode>(parent, generateNextTypeName(), typeReference.resolvedType());
     }
-    if (is<AST::PointerType>(unnamedType)) {
+    case AST::UnnamedType::Kind::PointerType: {
         auto& pointerType = downcast<AST::PointerType>(unnamedType);
-        return makeUniqueRef<PointerTypeNameNode>(parent, generateNextTypeName(), pointerType.addressSpace());
+        return std::make_unique<PointerTypeNameNode>(parent, generateNextTypeName(), pointerType.addressSpace());
     }
-    if (is<AST::ArrayReferenceType>(unnamedType)) {
+    case AST::UnnamedType::Kind::ArrayReferenceType: {
         auto& arrayReferenceType = downcast<AST::ArrayReferenceType>(unnamedType);
-        return makeUniqueRef<ArrayReferenceTypeNameNode>(parent, generateNextTypeName(), arrayReferenceType.addressSpace());
+        return std::make_unique<ArrayReferenceTypeNameNode>(parent, generateNextTypeName(), arrayReferenceType.addressSpace());
+    }
+    case AST::UnnamedType::Kind::ArrayType: {
+        auto& arrayType = downcast<AST::ArrayType>(unnamedType);
+        return std::make_unique<ArrayTypeNameNode>(parent, generateNextTypeName(), arrayType.numElements());
+    }
+    }
+}
+
+static AST::UnnamedType* parent(AST::UnnamedType& unnamedType)
+{
+    switch (unnamedType.kind()) {
+    case AST::UnnamedType::Kind::TypeReference:
+        return nullptr;
+    case AST::UnnamedType::Kind::PointerType:
+        return &downcast<AST::PointerType>(unnamedType).elementType();
+    case AST::UnnamedType::Kind::ArrayReferenceType:
+        return &downcast<AST::ArrayReferenceType>(unnamedType).elementType();
+    case AST::UnnamedType::Kind::ArrayType:
+        return &downcast<AST::ArrayType>(unnamedType).type();
     }
-    auto& arrayType = downcast<AST::ArrayType>(unnamedType);
-    return makeUniqueRef<ArrayTypeNameNode>(parent, generateNextTypeName(), arrayType.numElements());
 }
 
-BaseTypeNameNode* TypeNamer::insert(AST::UnnamedType& unnamedType, Vector<UniqueRef<BaseTypeNameNode>>& types)
+BaseTypeNameNode* TypeNamer::insert(AST::UnnamedType& unnamedType)
 {
     if (auto* result = m_unnamedTypeMapping.get(&unnamedType))
         return result;
 
-    Vector<UniqueRef<BaseTypeNameNode>>* vectorToInsertInto { nullptr };
-    BaseTypeNameNode* parent { nullptr };
-    if (is<AST::TypeReference>(unnamedType)) {
-        vectorToInsertInto = &types;
-        parent = nullptr;
-    } else if (is<AST::PointerType>(unnamedType)) {
-        parent = insert(downcast<AST::PointerType>(unnamedType).elementType(), types);
-        vectorToInsertInto = &parent->children();
-    } else if (is<AST::ArrayReferenceType>(unnamedType)) {
-        parent = insert(downcast<AST::ArrayReferenceType>(unnamedType).elementType(), types);
-        vectorToInsertInto = &parent->children();
-    } else {
-        parent = insert(downcast<AST::ArrayType>(unnamedType).type(), types);
-        vectorToInsertInto = &parent->children();
-    }
-    ASSERT(vectorToInsertInto);
+    auto* parentUnnamedType = parent(unnamedType);
+    BaseTypeNameNode* parentNode = parentUnnamedType ? insert(*parentUnnamedType) : nullptr;
 
-    auto iterator = findInVector(unnamedType, *vectorToInsertInto);
-    if (iterator == vectorToInsertInto->end()) {
-        auto result = createNameNode(unnamedType, parent);
-        {
-            auto addResult = m_unnamedTypeMapping.add(&unnamedType, &result);
-            ASSERT_UNUSED(addResult, addResult.isNewEntry);
-        }
-        vectorToInsertInto->append(WTFMove(result));
-        return &vectorToInsertInto->last().get();
-    }
-    m_unnamedTypeMapping.add(&unnamedType, &*iterator);
-    return &*iterator;
+    auto addResult = m_unnamedTypesUniquingMap.ensure(UnnamedTypeKey { unnamedType }, [&] {
+        return createNameNode(unnamedType, parentNode);
+    });
+
+    m_unnamedTypeMapping.add(&unnamedType, addResult.iterator->value.get());
+    return addResult.iterator->value.get();
 }
 
 class MetalTypeDeclarationWriter final : public Visitor {
@@ -382,17 +350,24 @@ void TypeNamer::emitUnnamedTypeDefinition(StringBuilder& stringBuilder, BaseType
 {
     if (emittedUnnamedTypes.contains(&baseTypeNameNode))
         return;
+
     if (baseTypeNameNode.parent())
         emitUnnamedTypeDefinition(stringBuilder, *baseTypeNameNode.parent(), emittedNamedTypes, emittedUnnamedTypes);
-    if (is<ReferenceTypeNameNode>(baseTypeNameNode)) {
+    
+    switch (baseTypeNameNode.kind()) {
+    case AST::UnnamedType::Kind::TypeReference: {
         auto& namedType = downcast<ReferenceTypeNameNode>(baseTypeNameNode).namedType();
         emitNamedTypeDefinition(stringBuilder, namedType, emittedNamedTypes, emittedUnnamedTypes);
         stringBuilder.flexibleAppend("typedef ", mangledNameForType(namedType), ' ', baseTypeNameNode.mangledName(), ";\n");
-    } else if (is<PointerTypeNameNode>(baseTypeNameNode)) {
+        break;
+    }
+    case AST::UnnamedType::Kind::PointerType: {
         auto& pointerType = downcast<PointerTypeNameNode>(baseTypeNameNode);
         ASSERT(baseTypeNameNode.parent());
         stringBuilder.flexibleAppend("typedef ", toString(pointerType.addressSpace()), ' ', pointerType.parent()->mangledName(), "* ", pointerType.mangledName(), ";\n");
-    } else if (is<ArrayReferenceTypeNameNode>(baseTypeNameNode)) {
+        break;
+    }
+    case AST::UnnamedType::Kind::ArrayReferenceType: {
         auto& arrayReferenceType = downcast<ArrayReferenceTypeNameNode>(baseTypeNameNode);
         ASSERT(baseTypeNameNode.parent());
         stringBuilder.flexibleAppend(
@@ -401,11 +376,16 @@ void TypeNamer::emitUnnamedTypeDefinition(StringBuilder& stringBuilder, BaseType
             "    uint32_t length;\n"
             "};\n"
         );
-    } else {
+        break;
+    }
+    case AST::UnnamedType::Kind::ArrayType: {
         auto& arrayType = downcast<ArrayTypeNameNode>(baseTypeNameNode);
         ASSERT(baseTypeNameNode.parent());
         stringBuilder.flexibleAppend("typedef array<", arrayType.parent()->mangledName(), ", ", arrayType.numElements(), "> ", arrayType.mangledName(), ";\n");
+        break;
     }
+    }
+
     emittedUnnamedTypes.add(&baseTypeNameNode);
 }
 
@@ -439,26 +419,19 @@ void TypeNamer::emitNamedTypeDefinition(StringBuilder& stringBuilder, AST::Named
     emittedNamedTypes.add(&namedType);
 }
 
-void TypeNamer::emitAllUnnamedTypeDefinitions(StringBuilder& stringBuilder, Vector<UniqueRef<BaseTypeNameNode>>& nodes, HashSet<AST::NamedType*>& emittedNamedTypes, HashSet<BaseTypeNameNode*>& emittedUnnamedTypes)
-{
-    for (auto& node : nodes) {
-        emitUnnamedTypeDefinition(stringBuilder, node, emittedNamedTypes, emittedUnnamedTypes);
-        emitAllUnnamedTypeDefinitions(stringBuilder, node->children(), emittedNamedTypes, emittedUnnamedTypes);
-    }
-}
-
 void TypeNamer::emitMetalTypeDefinitions(StringBuilder& stringBuilder)
 {
     HashSet<AST::NamedType*> emittedNamedTypes;
     HashSet<BaseTypeNameNode*> emittedUnnamedTypes;
-    for (auto& keyValuePair : m_dependencyGraph)
-        emitNamedTypeDefinition(stringBuilder, *keyValuePair.key, emittedNamedTypes, emittedUnnamedTypes);
-    emitAllUnnamedTypeDefinitions(stringBuilder, m_trie, emittedNamedTypes, emittedUnnamedTypes);
+    for (auto& namedType : m_dependencyGraph.keys())
+        emitNamedTypeDefinition(stringBuilder, *namedType, emittedNamedTypes, emittedUnnamedTypes);
+    for (auto& node : m_unnamedTypesUniquingMap.values())
+        emitUnnamedTypeDefinition(stringBuilder, *node, emittedNamedTypes, emittedUnnamedTypes);
 }
 
 MangledTypeName TypeNamer::mangledNameForType(AST::UnnamedType& unnamedType)
 {
-    return find(unnamedType, m_trie).mangledName();
+    return find(unnamedType).mangledName();
 }
 
 MangledOrNativeTypeName TypeNamer::mangledNameForType(AST::NamedType& namedType)
index defa7d4..b383cb5 100644 (file)
@@ -28,6 +28,7 @@
 #if ENABLE(WEBGPU)
 
 #include "WHLSLMangledNames.h"
+#include "WHLSLUnnamedTypeHash.h"
 #include "WHLSLVisitor.h"
 #include <wtf/HashMap.h>
 #include <wtf/text/WTFString.h>
@@ -84,15 +85,15 @@ private:
 
     void emitNamedTypeDefinition(StringBuilder&, AST::NamedType&, HashSet<AST::NamedType*>& emittedNamedTypes, HashSet<BaseTypeNameNode*>& emittedUnnamedTypes);
     void emitUnnamedTypeDefinition(StringBuilder&, BaseTypeNameNode&, HashSet<AST::NamedType*>& emittedNamedTypes, HashSet<BaseTypeNameNode*>& emittedUnnamedTypes);
-    void emitAllUnnamedTypeDefinitions(StringBuilder&, Vector<UniqueRef<BaseTypeNameNode>>&, HashSet<AST::NamedType*>& emittedNamedTypes, HashSet<BaseTypeNameNode*>& emittedUnnamedTypes);
     void emitMetalTypeDeclarations(StringBuilder&);
     void emitMetalTypeDefinitions(StringBuilder&);
 
-    UniqueRef<BaseTypeNameNode> createNameNode(AST::UnnamedType&, BaseTypeNameNode* parent);
-    BaseTypeNameNode* insert(AST::UnnamedType&, Vector<UniqueRef<BaseTypeNameNode>>&);
+    std::unique_ptr<BaseTypeNameNode> createNameNode(AST::UnnamedType&, BaseTypeNameNode* parent);
+    BaseTypeNameNode* insert(AST::UnnamedType&);
+    BaseTypeNameNode& find(AST::UnnamedType&);
 
     Program& m_program;
-    Vector<UniqueRef<BaseTypeNameNode>> m_trie;
+    HashMap<UnnamedTypeKey, std::unique_ptr<BaseTypeNameNode>, UnnamedTypeKey::Hash, UnnamedTypeKey::Traits> m_unnamedTypesUniquingMap;
     HashMap<AST::UnnamedType*, BaseTypeNameNode*> m_unnamedTypeMapping;
     HashMap<AST::NamedType*, MangledTypeName> m_namedTypeMapping;
     HashMap<AST::NamedType*, Vector<std::reference_wrapper<BaseTypeNameNode>>> m_dependencyGraph;
index 02ba7fc..00d98fb 100644 (file)
@@ -38,6 +38,7 @@
 #include "WHLSLProgram.h"
 #include "WHLSLStructureDefinition.h"
 #include "WHLSLTypeReference.h"
+#include "WHLSLUnnamedTypeHash.h"
 #include "WHLSLVariableDeclaration.h"
 #include "WHLSLVisitor.h"
 
@@ -45,41 +46,6 @@ namespace WebCore {
 
 namespace WHLSL {
 
-class UnnamedTypeKey {
-public:
-    UnnamedTypeKey() = default;
-    UnnamedTypeKey(WTF::HashTableDeletedValueType)
-    {
-        m_type = bitwise_cast<AST::UnnamedType*>(static_cast<uintptr_t>(1));
-    }
-
-    UnnamedTypeKey(AST::UnnamedType& type)
-        : m_type(&type)
-    { }
-
-    bool isEmptyValue() const { return !m_type; }
-    bool isHashTableDeletedValue() const { return m_type == bitwise_cast<AST::UnnamedType*>(static_cast<uintptr_t>(1)); }
-
-    unsigned hash() const { return m_type->hash(); }
-    bool operator==(const UnnamedTypeKey& other) const { return *m_type == *other.m_type; }
-    AST::UnnamedType& unnamedType() const { return *m_type; }
-
-    struct Hash {
-        static unsigned hash(const UnnamedTypeKey& key) { return key.hash(); }
-        static bool equal(const UnnamedTypeKey& a, const UnnamedTypeKey& b) { return a == b; }
-        static const bool safeToCompareToEmptyOrDeleted = false;
-        static const bool emptyValueIsZero = true;
-    };
-
-    struct Traits : public WTF::SimpleClassHashTraits<UnnamedTypeKey> {
-        static const bool hasIsEmptyValueFunction = true;
-        static bool isEmptyValue(const UnnamedTypeKey& key) { return key.isEmptyValue(); }
-    };
-
-private:
-    AST::UnnamedType* m_type { nullptr };
-};
-
 class FindAllTypes : public Visitor {
 public:
     virtual ~FindAllTypes() = default;
index b0ff4b0..c574e80 100644 (file)
                7C8139A81ED6287400CE26E8 /* JSDOMOperationReturningPromise.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C8139A51ED6281D00CE26E8 /* JSDOMOperationReturningPromise.h */; settings = {ATTRIBUTES = (Private, ); }; };
                7C8139AA1ED6604B00CE26E8 /* JSDOMCastedThisErrorBehavior.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C8139A91ED62DF200CE26E8 /* JSDOMCastedThisErrorBehavior.h */; settings = {ATTRIBUTES = (Private, ); }; };
                7C83DE861D04CC5D00FEBCF3 /* SpringSolver.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C83DE851D04CBD400FEBCF3 /* SpringSolver.h */; };
+               7C85B20222FB04850030684F /* WHLSLUnnamedType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C85B20122FB04850030684F /* WHLSLUnnamedType.cpp */; };
                7C8E34AD1E4A33AF0054CE23 /* JSDOMConvertAny.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C8E34921E4A338E0054CE23 /* JSDOMConvertAny.h */; settings = {ATTRIBUTES = (Private, ); }; };
                7C8E34AE1E4A33AF0054CE23 /* JSDOMConvertBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C8E34931E4A338E0054CE23 /* JSDOMConvertBase.h */; settings = {ATTRIBUTES = (Private, ); }; };
                7C8E34AF1E4A33AF0054CE23 /* JSDOMConvertBoolean.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C8E34941E4A338E0054CE23 /* JSDOMConvertBoolean.h */; settings = {ATTRIBUTES = (Private, ); }; };
                7C8139A51ED6281D00CE26E8 /* JSDOMOperationReturningPromise.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDOMOperationReturningPromise.h; sourceTree = "<group>"; };
                7C8139A91ED62DF200CE26E8 /* JSDOMCastedThisErrorBehavior.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDOMCastedThisErrorBehavior.h; sourceTree = "<group>"; };
                7C83DE851D04CBD400FEBCF3 /* SpringSolver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpringSolver.h; sourceTree = "<group>"; };
+               7C85B20122FB04850030684F /* WHLSLUnnamedType.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = WHLSLUnnamedType.cpp; sourceTree = "<group>"; };
+               7C85B20422FB06320030684F /* WHLSLUnnamedTypeHash.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLUnnamedTypeHash.h; sourceTree = "<group>"; };
                7C8E34921E4A338E0054CE23 /* JSDOMConvertAny.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDOMConvertAny.h; sourceTree = "<group>"; };
                7C8E34931E4A338E0054CE23 /* JSDOMConvertBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDOMConvertBase.h; sourceTree = "<group>"; };
                7C8E34941E4A338E0054CE23 /* JSDOMConvertBoolean.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDOMConvertBoolean.h; sourceTree = "<group>"; };
                1CA0C2F621EEDAD200A11860 /* AST */ = {
                        isa = PBXGroup;
                        children = (
-                               1C840B9021EC30F900D0500D /* WHLSLAddressSpace.h */,
                                52914C2C22F93E5D00578150 /* WHLSLAddressEscapeMode.h */,
+                               1C840B9021EC30F900D0500D /* WHLSLAddressSpace.h */,
                                C21BF72521CD89E200227979 /* WHLSLArrayReferenceType.h */,
                                C21BF70921CD89CA00227979 /* WHLSLArrayType.h */,
                                C21BF73021CD89ED00227979 /* WHLSLAssignmentExpression.h */,
                                C21BF72921CD89E600227979 /* WHLSLTypeDefinition.h */,
                                C20F4F6421DFBE5C0070C45A /* WHLSLTypeReference.cpp */,
                                C21BF71F21CD89DC00227979 /* WHLSLTypeReference.h */,
+                               7C85B20122FB04850030684F /* WHLSLUnnamedType.cpp */,
                                1C33277221CF0D2E000DC9F2 /* WHLSLUnnamedType.h */,
+                               7C85B20422FB06320030684F /* WHLSLUnnamedTypeHash.h */,
                                C20F4F6721DFF3A70070C45A /* WHLSLUnsignedIntegerLiteral.cpp */,
                                C21BF72B21CD89E800227979 /* WHLSLUnsignedIntegerLiteral.h */,
                                1CB69B3B21DF041E006E846A /* WHLSLUnsignedIntegerLiteralType.cpp */,
                                F12171F516A8CED2000053CA /* WebVTTElement.cpp in Sources */,
                                5D21A80213ECE5DF00BB7064 /* WebVTTParser.cpp in Sources */,
                                B10B6981140C174000BC1C26 /* WebVTTTokenizer.cpp in Sources */,
+                               7C85B20222FB04850030684F /* WHLSLUnnamedType.cpp in Sources */,
                                A14832C2187F65C700DA63A6 /* WKUtilities.c in Sources */,
                                A833C7CC0A2CF07400D57664 /* XLinkNames.cpp in Sources */,
                                A833C80C0A2CF25600D57664 /* XMLNames.cpp in Sources */,