| /* | 
 |  * Copyright (C) 2014-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. ``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 | 
 |  * 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(DFG_JIT) | 
 |  | 
 | #include "DFGEdge.h" | 
 | #include "DFGNodeOrigin.h" | 
 | #include <wtf/HashTable.h> | 
 | #include <wtf/PrintStream.h> | 
 |  | 
 | namespace JSC { namespace DFG { | 
 |  | 
 | struct Node; | 
 |  | 
 | // Promoted locations are like heap locations but are meant to be more precise. A heap location is | 
 | // applicable to CSE scenarios, where it makes sense to speak of a location very abstractly. A | 
 | // promoted heap location is for cases where we speak of a specific object and the compiler knows | 
 | // this object's identity - for example, the object allocation has been eliminated and we turned the | 
 | // fields into local variables. Because these two cases have subtly different needs, we use subtly | 
 | // different structures. One of the really significant differences is that promoted locations can be | 
 | // spoken of using either a descriptor which does not refer to any Node*'s or with a heap location, | 
 | // which is a descriptor with a Node* base. | 
 |  | 
 | enum PromotedLocationKind { | 
 |     InvalidPromotedLocationKind, | 
 |      | 
 |     ActivationScopePLoc, | 
 |     ActivationSymbolTablePLoc, | 
 |     ArgumentCountPLoc, | 
 |     ArgumentPLoc, | 
 |     ArgumentsCalleePLoc, | 
 |     ClosureVarPLoc, | 
 |     PromiseInternalFieldPLoc, | 
 |     FunctionActivationPLoc, | 
 |     FunctionExecutablePLoc, | 
 |     IndexedPropertyPLoc, | 
 |     NamedPropertyPLoc, | 
 |     PublicLengthPLoc, | 
 |     StructurePLoc, | 
 |     VectorLengthPLoc, | 
 |     SpreadPLoc, | 
 |     NewArrayWithSpreadArgumentPLoc, | 
 |     NewArrayBufferPLoc, | 
 |     RegExpObjectRegExpPLoc, | 
 |     RegExpObjectLastIndexPLoc, | 
 | }; | 
 |  | 
 | class PromotedLocationDescriptor { | 
 | public: | 
 |     PromotedLocationDescriptor( | 
 |         PromotedLocationKind kind = InvalidPromotedLocationKind, unsigned info = 0) | 
 |         : m_kind(kind) | 
 |         , m_info(info) | 
 |     { | 
 |     } | 
 |  | 
 |     PromotedLocationDescriptor(WTF::HashTableDeletedValueType) | 
 |         : m_kind(InvalidPromotedLocationKind) | 
 |         , m_info(1) | 
 |     { | 
 |     } | 
 |  | 
 |     bool operator!() const { return m_kind == InvalidPromotedLocationKind; } | 
 |  | 
 |     explicit operator bool() const { return !!*this; } | 
 |      | 
 |     PromotedLocationKind kind() const { return m_kind; } | 
 |     unsigned info() const { return m_info; } | 
 |      | 
 |     unsigned imm1() const { return static_cast<uint32_t>(m_kind); } | 
 |     unsigned imm2() const { return static_cast<uint32_t>(m_info); } | 
 |      | 
 |     unsigned hash() const | 
 |     { | 
 |         return m_kind + m_info; | 
 |     } | 
 |      | 
 |     bool operator==(const PromotedLocationDescriptor& other) const | 
 |     { | 
 |         return m_kind == other.m_kind | 
 |             && m_info == other.m_info; | 
 |     } | 
 |      | 
 |     bool operator!=(const PromotedLocationDescriptor& other) const | 
 |     { | 
 |         return !(*this == other); | 
 |     } | 
 |  | 
 |     bool isHashTableDeletedValue() const | 
 |     { | 
 |         return m_kind == InvalidPromotedLocationKind && m_info; | 
 |     } | 
 |  | 
 |     bool neededForMaterialization() const | 
 |     { | 
 |         switch (kind()) { | 
 |         case NamedPropertyPLoc: | 
 |         case ClosureVarPLoc: | 
 |         case RegExpObjectLastIndexPLoc: | 
 |             return false; | 
 |  | 
 |         default: | 
 |             return true; | 
 |         } | 
 |     } | 
 |      | 
 |     void dump(PrintStream& out) const; | 
 |  | 
 | private: | 
 |     PromotedLocationKind m_kind; | 
 |     unsigned m_info; | 
 | }; | 
 |  | 
 | struct PromotedLocationDescriptorHash { | 
 |     static unsigned hash(const PromotedLocationDescriptor& key) { return key.hash(); } | 
 |     static bool equal(const PromotedLocationDescriptor& a, const PromotedLocationDescriptor& b) { return a == b; } | 
 |     static constexpr bool safeToCompareToEmptyOrDeleted = true; | 
 | }; | 
 |  | 
 | class PromotedHeapLocation { | 
 | public: | 
 |     PromotedHeapLocation( | 
 |         PromotedLocationKind kind = InvalidPromotedLocationKind, | 
 |         Node* base = nullptr, unsigned info = 0) | 
 |         : m_base(base) | 
 |         , m_meta(kind, info) | 
 |     { | 
 |     } | 
 |      | 
 |     PromotedHeapLocation( | 
 |         PromotedLocationKind kind, Edge base, unsigned info = 0) | 
 |         : PromotedHeapLocation(kind, base.node(), info) | 
 |     { | 
 |     } | 
 |      | 
 |     PromotedHeapLocation(Node* base, PromotedLocationDescriptor meta) | 
 |         : m_base(base) | 
 |         , m_meta(meta) | 
 |     { | 
 |     } | 
 |      | 
 |     PromotedHeapLocation(WTF::HashTableDeletedValueType) | 
 |         : m_base(nullptr) | 
 |         , m_meta(InvalidPromotedLocationKind, 1) | 
 |     { | 
 |     } | 
 |      | 
 |     Node* createHint(Graph&, NodeOrigin, Node* value); | 
 |      | 
 |     bool operator!() const { return kind() == InvalidPromotedLocationKind; } | 
 |      | 
 |     PromotedLocationKind kind() const { return m_meta.kind(); } | 
 |     Node* base() const { return m_base; } | 
 |     unsigned info() const { return m_meta.info(); } | 
 |     PromotedLocationDescriptor descriptor() const { return m_meta; } | 
 |      | 
 |     unsigned hash() const | 
 |     { | 
 |         return m_meta.hash() + WTF::PtrHash<Node*>::hash(m_base); | 
 |     } | 
 |      | 
 |     bool operator==(const PromotedHeapLocation& other) const | 
 |     { | 
 |         return m_base == other.m_base | 
 |             && m_meta == other.m_meta; | 
 |     } | 
 |      | 
 |     bool isHashTableDeletedValue() const | 
 |     { | 
 |         return m_meta.isHashTableDeletedValue(); | 
 |     } | 
 |      | 
 |     void dump(PrintStream& out) const; | 
 |      | 
 | private: | 
 |     Node* m_base; | 
 |     PromotedLocationDescriptor m_meta; | 
 | }; | 
 |  | 
 | struct PromotedHeapLocationHash { | 
 |     static unsigned hash(const PromotedHeapLocation& key) { return key.hash(); } | 
 |     static bool equal(const PromotedHeapLocation& a, const PromotedHeapLocation& b) { return a == b; } | 
 |     static constexpr bool safeToCompareToEmptyOrDeleted = true; | 
 | }; | 
 |  | 
 | } } // namespace JSC::DFG | 
 |  | 
 | namespace WTF { | 
 |  | 
 | void printInternal(PrintStream&, JSC::DFG::PromotedLocationKind); | 
 |  | 
 | template<typename T> struct DefaultHash; | 
 | template<> struct DefaultHash<JSC::DFG::PromotedHeapLocation> { | 
 |     typedef JSC::DFG::PromotedHeapLocationHash Hash; | 
 | }; | 
 |  | 
 | template<typename T> struct HashTraits; | 
 | template<> struct HashTraits<JSC::DFG::PromotedHeapLocation> : SimpleClassHashTraits<JSC::DFG::PromotedHeapLocation> { | 
 |     static constexpr bool emptyValueIsZero = false; | 
 | }; | 
 |  | 
 | template<typename T> struct DefaultHash; | 
 | template<> struct DefaultHash<JSC::DFG::PromotedLocationDescriptor> { | 
 |     typedef JSC::DFG::PromotedLocationDescriptorHash Hash; | 
 | }; | 
 |  | 
 | template<typename T> struct HashTraits; | 
 | template<> struct HashTraits<JSC::DFG::PromotedLocationDescriptor> : SimpleClassHashTraits<JSC::DFG::PromotedLocationDescriptor> { | 
 |     static constexpr bool emptyValueIsZero = false; | 
 | }; | 
 |  | 
 | } // namespace WTF | 
 |  | 
 | #endif // ENABLE(DFG_JIT) |