Move serialize functions to variable-serializer.cpp
[hiphop-php.git] / hphp / util / compact-tagged-ptrs.h
blob3777c91b59ace657777f986165871bb3b2eacf9a
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2015 Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
16 #ifndef incl_HPHP_UTIL_COMPACT_TAGGED_PTRS_H_
17 #define incl_HPHP_UTIL_COMPACT_TAGGED_PTRS_H_
19 #include <cstdint>
22 * A combined pointer + tag intended to save space on x64. The tag must fit in
23 * a 16 bit integer anywhere you use this class (although the non-x64
24 * implementation uses larger space for the tag).
26 * For the x64 version, this class relies on the x64 property that a
27 * "canonical form" address must have all the upper bits set to the same
28 * value as bit 47. Further, it relies on the OS using only "lower
29 * half" canonical form addresses for userland pointers. For more,
30 * see:
32 * http://en.wikipedia.org/wiki/X86-64#Canonical_form_addresses
34 * The portable version just uses a pointer plus an actual TagType for the tag.
37 namespace HPHP {
39 //////////////////////////////////////////////////////////////////////
41 #if defined(__x86_64__) || defined(_M_X64)
43 template<class T, class TagType = uint32_t>
44 struct CompactTaggedPtr {
45 using Opaque = uintptr_t;
46 CompactTaggedPtr() { set(TagType{}, 0); }
48 // for save and restore
49 explicit CompactTaggedPtr(Opaque v) : m_data(v) {}
50 Opaque getOpaque() const { return m_data; }
52 void set(TagType ttag, T* ptr) {
53 auto const tag = static_cast<uint64_t>(ttag);
54 assert(tag <= 0xffffu);
55 assert(!(uintptr_t(ptr) >> 48));
56 m_data = uintptr_t(ptr) | (size_t(tag) << 48);
59 TagType tag() const { return static_cast<TagType>(m_data >> 48); }
61 const T* ptr() const {
62 return const_cast<CompactTaggedPtr*>(this)->ptr();
64 T* ptr() {
65 return reinterpret_cast<T*>(m_data & (-1ull >> 16));
68 private:
69 uintptr_t m_data;
72 #else
74 template<class T, class TagType = uint32_t>
75 struct CompactTaggedPtr {
76 using Opaque = std::pair<T*,uint32_t>;
78 CompactTaggedPtr() { set(TagType{}, 0); }
80 // for save and restore
81 explicit CompactTaggedPtr(Opaque v) : m_ptr(v.first), m_size(v.second) {}
82 Opaque getOpaque() const { return std::make_pair(m_ptr, m_size); }
84 void set(TagType ttag, T* ptr) {
85 auto const tag = static_cast<uint32_t>(ttag);
86 assert(tag <= 0xffffu);
87 m_tag = ttag;
88 m_ptr = ptr;
91 TagType tag() const { return m_tag; }
92 const T* ptr() const { return m_ptr; }
93 T* ptr() { return m_ptr; }
95 private:
96 T* m_ptr;
97 TagType m_tag;
100 #endif
102 //////////////////////////////////////////////////////////////////////
105 * Same thing, named differently for self-documentation when the tag is
106 * representing the size of something.
108 template<class T>
109 struct CompactSizedPtr {
110 void set(uint32_t size, T* ptr) { m_data.set(size, ptr); }
112 uint32_t size() const { return m_data.tag(); }
113 const T* ptr() const { return m_data.ptr(); }
114 T* ptr() { return m_data.ptr(); }
116 private:
117 CompactTaggedPtr<T> m_data;
120 //////////////////////////////////////////////////////////////////////
124 #endif