Enable HHIRInliningUseReachableCost by default, tweak inlining constants
[hiphop-php.git] / hphp / runtime / base / repo-auth-type.h
blob790380c1af77e263ce2a8e96ee6289502d520d80
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present 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_REPO_AUTH_TYPE_H_
17 #define incl_HPHP_REPO_AUTH_TYPE_H_
19 #include <limits>
20 #include <string>
22 #include <folly/Optional.h>
24 #include "hphp/util/assertions.h"
25 #include "hphp/util/compact-tagged-ptrs.h"
27 #include "hphp/runtime/base/datatype.h"
28 #include "hphp/runtime/base/runtime-option.h"
30 namespace HPHP {
32 //////////////////////////////////////////////////////////////////////
34 struct StringData;
35 struct TypedValue;
36 struct Unit;
37 struct UnitEmitter;
38 struct RepoAuthType;
40 //////////////////////////////////////////////////////////////////////
43 * Representation of types inferred statically for RepoAuthoritative
44 * mode, for use in runtime data structures, or the bytecode stream
45 * (see the AssertRAT{L,Stk} opcodes).
47 * This is encoded to be space efficient, so there's a small
48 * abstraction layer.
51 //////////////////////////////////////////////////////////////////////
53 constexpr uint16_t kRATPtrBit = 0x4000;
55 struct RepoAuthType {
56 struct Array;
58 #define REPO_AUTH_TYPE_TAGS \
59 TAG(Uninit) \
60 TAG(InitNull) \
61 TAG(Null) \
62 TAG(Int) \
63 TAG(OptInt) \
64 TAG(Dbl) \
65 TAG(OptDbl) \
66 TAG(Res) \
67 TAG(OptRes) \
68 TAG(Bool) \
69 TAG(OptBool) \
70 TAG(SStr) \
71 TAG(OptSStr) \
72 TAG(Str) \
73 TAG(OptStr) \
74 TAG(Obj) \
75 TAG(OptObj) \
76 TAG(Func) \
77 TAG(OptFunc) \
78 TAG(Cls) \
79 TAG(OptCls) \
80 TAG(ClsMeth) \
81 TAG(OptClsMeth) \
82 TAG(Record) \
83 TAG(OptRecord) \
84 TAG(InitUnc) \
85 TAG(Unc) \
86 TAG(UncArrKey) \
87 TAG(ArrKey) \
88 TAG(OptUncArrKey) \
89 TAG(OptArrKey) \
90 TAG(UncStrLike) \
91 TAG(StrLike) \
92 TAG(OptUncStrLike) \
93 TAG(OptStrLike) \
94 TAG(InitCell) \
95 TAG(Cell) \
96 TAG(Ref) \
97 TAG(InitGen) \
98 TAG(Gen) \
99 /* Types where array() may be non-null. */ \
100 TAG(SArr) \
101 TAG(OptSArr) \
102 TAG(Arr) \
103 TAG(OptArr) \
104 TAG(SVArr) \
105 TAG(OptSVArr) \
106 TAG(VArr) \
107 TAG(OptVArr) \
108 TAG(SDArr) \
109 TAG(OptSDArr) \
110 TAG(DArr) \
111 TAG(OptDArr) \
112 TAG(SVec) \
113 TAG(OptSVec) \
114 TAG(Vec) \
115 TAG(OptVec) \
116 TAG(SDict) \
117 TAG(OptSDict) \
118 TAG(Dict) \
119 TAG(OptDict) \
120 TAG(SKeyset) \
121 TAG(OptSKeyset) \
122 TAG(Keyset) \
123 TAG(OptKeyset) \
124 /* Types where clsName() will be non-null. */ \
125 TAG(ExactObj) \
126 TAG(SubObj) \
127 TAG(OptExactObj) \
128 TAG(OptSubObj) \
129 TAG(ExactCls) \
130 TAG(SubCls) \
131 TAG(OptExactCls) \
132 TAG(OptSubCls) \
134 enum class Tag : uint16_t {
135 #define TAG(x) x,
136 REPO_AUTH_TYPE_TAGS
137 #undef TAG
140 explicit RepoAuthType(Tag tag = Tag::Gen, const StringData* sd = nullptr) {
141 m_data.set(static_cast<uint16_t>(tag), sd);
142 switch (tag) {
143 case Tag::OptSubObj: case Tag::OptExactObj:
144 case Tag::SubObj: case Tag::ExactObj:
145 case Tag::OptSubCls: case Tag::OptExactCls:
146 case Tag::SubCls: case Tag::ExactCls:
147 assertx(sd != nullptr);
148 break;
149 default:
150 break;
154 explicit RepoAuthType(Tag tag, const Array* ar) {
155 m_data.set(static_cast<uint16_t>(tag), ar);
156 assertx(mayHaveArrData());
159 Tag tag() const { return toResolvedTag(m_data.tag()); }
161 bool operator==(RepoAuthType) const;
162 bool operator!=(RepoAuthType o) const { return !(*this == o); }
163 size_t hash() const;
166 * Class Names.
169 const StringData* clsName() const {
170 assertx(hasClassName());
171 return static_cast<const StringData*>(m_data.ptr());
174 bool hasClassName() const {
175 switch (tag()) {
176 case Tag::SubObj: case Tag::ExactObj:
177 case Tag::OptSubObj: case Tag::OptExactObj:
178 case Tag::SubCls: case Tag::ExactCls:
179 case Tag::OptSubCls: case Tag::OptExactCls:
180 return true;
181 default:
182 return false;
184 not_reached();
188 * Arrays.
191 const Array* array() const {
192 assertx(resolved());
193 return static_cast<const Array*>(m_data.ptr());
196 // Returns a valid id if there is a corresponding Array* somewhere,
197 // or return kInvalidArrayId if Array* is null or if it is unresolved.
198 const uint32_t arrayId() const;
199 static constexpr auto kInvalidArrayId = std::numeric_limits<uint32_t>::max();
201 // Turn an array RAT represented by ID into equivalent array RAT represented
202 // by its actual Array*. Should only be called when it is indeed not resolved
203 // yet, which should be the place where an RAT is initally loaded from Repo.
204 void resolveArray(const UnitEmitter& ue);
206 bool mayHaveArrData() const {
207 switch (tag()) {
208 case Tag::OptArr: case Tag::OptSArr: case Tag::Arr: case Tag::SArr:
209 case Tag::OptVArr: case Tag::OptSVArr: case Tag::VArr: case Tag::SVArr:
210 case Tag::OptDArr: case Tag::OptSDArr: case Tag::DArr: case Tag::SDArr:
211 case Tag::OptVec: case Tag::OptSVec: case Tag::Vec: case Tag::SVec:
212 case Tag::OptDict: case Tag::OptSDict: case Tag::Dict: case Tag::SDict:
213 case Tag::OptKeyset: case Tag::OptSKeyset:
214 case Tag::Keyset: case Tag::SKeyset:
215 return true;
216 default:
217 return false;
219 not_reached();
222 // Return true if m_data contains non-null Array*.
223 bool hasArrData() const {
224 return mayHaveArrData() && resolved() && m_data.ptr();
228 * Serialization/Deserialization
231 template <class SerDe>
232 void serde(SerDe& sd) {
233 auto t = tag();
234 sd(t);
236 if (SerDe::deserializing) {
237 // mayHaveArrData and hasClassName need to read tag().
238 m_data.set(static_cast<uint16_t>(t), nullptr);
241 // the kRATPtrBit bit for resolved/unresolved Array* should not be visible
242 // to the outside world.
243 assertx(resolved());
245 if (mayHaveArrData()) {
246 // serialization
247 if (!SerDe::deserializing) {
248 // either a valid id for non-null array, or a kInvalidArrayId for null
249 uint32_t id = arrayId();
250 sd(id);
251 return;
254 // deserialization
255 uint32_t id;
256 sd(id);
258 // nullptr case, already done
259 if (id == kInvalidArrayId) return;
261 // id case
262 // this is the only case where we set the kRATPtrBit bit
263 auto ptr = reinterpret_cast<const void*>(id);
264 m_data.set(toIdTag(t), ptr);
265 return;
268 if (hasClassName()) {
269 auto c = clsName();
270 sd(c);
271 m_data.set(static_cast<uint16_t>(t), reinterpret_cast<const void*>(c));
275 private:
276 #define TAG(x) \
277 static_assert((static_cast<uint16_t>(Tag::x) & kRATPtrBit) == 0, "");
278 REPO_AUTH_TYPE_TAGS
279 #undef TAG
281 friend struct ArrayTypeTable;
282 friend struct Array;
284 template <class LookupFn>
285 void doResolve(LookupFn fn) {
286 if (!mayHaveArrData() || resolved()) return;
288 auto const id = arrayId();
289 assertx(id != kInvalidArrayId); // this case is handled in deser time.
290 auto const array = fn(id);
291 m_data.set(static_cast<uint16_t>(tag()), array);
294 // false if m_data contains an uint32_t id for array type.
295 // true otherwise (it may not even be an array type).
296 // Note that the kRATArrayDataBit bit is used by encodeRAT and decodeRAT,
297 // and the 0x20 bit is used in the Tag enum.
298 const bool resolved() const {
299 return (m_data.tag() & kRATPtrBit) == 0;
301 static uint16_t toIdTag(Tag tag) {
302 return static_cast<uint16_t>(tag) | kRATPtrBit;
304 static Tag toResolvedTag(uint16_t tag) {
305 return static_cast<Tag>(tag & ~kRATPtrBit);
308 private:
309 // This is the type tag (for the lower 6 bits) plus two flag bits (
310 // kRATArrayDataBit used by encodeRAT/decodeRAT and
311 // kRATPtrBit used by ourselves), plus an optional pointer to a class name
312 // (for the obj_* types), or an optional pointer to
313 // array information for array types, or alternatively, an optional id to the
314 // array information with kRATPtrBit flag set to 1 to differentiate from the
315 // pointer case.
316 CompactTaggedPtr<const void,uint16_t> m_data;
319 //////////////////////////////////////////////////////////////////////
322 * Return whether a TypedValue is a legal match for a RepoAuthType.
323 * This can be used for validating that assumptions from static
324 * analysis are not violated (for example, by unserializing objects
325 * with changed private property types).
327 * Note: this function returns true on array types without checking
328 * every element. This is ok for private properties for now because
329 * we don't ever infer inner-array types on properties, but if that
330 * changes new mechanisms may be needed. Relevant to both:
331 * TODO(#3696042,#2516227).
333 bool tvMatchesRepoAuthType(TypedValue, RepoAuthType);
336 * Produce a human-readable string from a RepoAuthType. (Intended for
337 * debugging purposes.)
339 std::string show(RepoAuthType);
341 //////////////////////////////////////////////////////////////////////
345 #endif