1/*
2 * Copyright (C) 2018-2019 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#pragma once
27
28#include <wtf/HashTraits.h>
29#include <wtf/PtrTag.h>
30#include <wtf/StdLibExtras.h>
31
32namespace WTF {
33
34template<PtrTag tag>
35class MetaAllocatorPtr {
36public:
37 MetaAllocatorPtr() = default;
38 MetaAllocatorPtr(std::nullptr_t) { }
39
40 explicit MetaAllocatorPtr(void* ptr)
41 : m_ptr(tagCodePtr<tag>(ptr))
42 {
43 assertIsNotTagged(ptr);
44 }
45
46 explicit MetaAllocatorPtr(uintptr_t ptrAsInt)
47 : MetaAllocatorPtr(reinterpret_cast<void*>(ptrAsInt))
48 { }
49
50 template<typename T = void*>
51 T untaggedPtr() const { return bitwise_cast<T>(untagCodePtr<tag>(m_ptr)); }
52
53 template<PtrTag newTag, typename T = void*>
54 T retaggedPtr() const { return bitwise_cast<T>(retagCodePtr<tag, newTag>(m_ptr)); }
55
56 // Disallow any casting operations (except for booleans).
57 template<typename T, typename = std::enable_if_t<!std::is_same<T, bool>::value>>
58 operator T() = delete;
59
60 explicit operator bool() const { return !!m_ptr; }
61 bool operator!() const { return !m_ptr; }
62
63 bool operator==(MetaAllocatorPtr other) const { return m_ptr == other.m_ptr; }
64 bool operator!=(MetaAllocatorPtr other) const { return m_ptr != other.m_ptr; }
65
66 MetaAllocatorPtr operator+(size_t sizeInBytes) const { return MetaAllocatorPtr(untaggedPtr<uint8_t*>() + sizeInBytes); }
67 MetaAllocatorPtr operator-(size_t sizeInBytes) const { return MetaAllocatorPtr(untaggedPtr<uint8_t*>() - sizeInBytes); }
68
69 MetaAllocatorPtr& operator+=(size_t sizeInBytes)
70 {
71 return *this = *this + sizeInBytes;
72 }
73
74 MetaAllocatorPtr& operator-=(size_t sizeInBytes)
75 {
76 return *this = *this - sizeInBytes;
77 }
78
79 enum EmptyValueTag { EmptyValue };
80 enum DeletedValueTag { DeletedValue };
81
82 MetaAllocatorPtr(EmptyValueTag)
83 : m_ptr(emptyValue())
84 { }
85
86 MetaAllocatorPtr(DeletedValueTag)
87 : m_ptr(deletedValue())
88 { }
89
90 bool isEmptyValue() const { return m_ptr == emptyValue(); }
91 bool isDeletedValue() const { return m_ptr == deletedValue(); }
92
93 unsigned hash() const { return PtrHash<void*>::hash(m_ptr); }
94
95private:
96 static void* emptyValue() { return reinterpret_cast<void*>(1); }
97 static void* deletedValue() { return reinterpret_cast<void*>(2); }
98
99 void* m_ptr { nullptr };
100};
101
102template<PtrTag tag>
103struct MetaAllocatorPtrHash {
104 static unsigned hash(const MetaAllocatorPtr<tag>& ptr) { return ptr.hash(); }
105 static bool equal(const MetaAllocatorPtr<tag>& a, const MetaAllocatorPtr<tag>& b)
106 {
107 return a == b;
108 }
109 static constexpr bool safeToCompareToEmptyOrDeleted = true;
110};
111
112template<typename T> struct DefaultHash;
113template<PtrTag tag> struct DefaultHash<MetaAllocatorPtr<tag>> {
114 typedef MetaAllocatorPtrHash<tag> Hash;
115};
116
117template<PtrTag tag> struct HashTraits<MetaAllocatorPtr<tag>> : public CustomHashTraits<MetaAllocatorPtr<tag>> { };
118
119} // namespace WTF
120
121using WTF::MetaAllocatorPtr;
122