2 +----------------------------------------------------------------------+
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_
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"
32 //////////////////////////////////////////////////////////////////////
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
51 //////////////////////////////////////////////////////////////////////
53 constexpr uint16_t kRATPtrBit
= 0x4000;
58 #define REPO_AUTH_TYPE_TAGS \
99 /* Types where array() may be non-null. */ \
124 /* Types where clsName() will be non-null. */ \
134 enum class Tag : uint16_t {
140 explicit RepoAuthType(Tag tag
= Tag::Gen
, const StringData
* sd
= nullptr) {
141 m_data
.set(static_cast<uint16_t>(tag
), sd
);
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);
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
); }
169 const StringData
* clsName() const {
170 assertx(hasClassName());
171 return static_cast<const StringData
*>(m_data
.ptr());
174 bool hasClassName() const {
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
:
191 const Array
* array() const {
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 {
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
:
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
) {
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.
245 if (mayHaveArrData()) {
247 if (!SerDe::deserializing
) {
248 // either a valid id for non-null array, or a kInvalidArrayId for null
249 uint32_t id
= arrayId();
258 // nullptr case, already done
259 if (id
== kInvalidArrayId
) return;
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
);
268 if (hasClassName()) {
271 m_data
.set(static_cast<uint16_t>(t
), reinterpret_cast<const void*>(c
));
277 static_assert((static_cast<uint16_t>(Tag::x) & kRATPtrBit) == 0, "");
281 friend struct ArrayTypeTable
;
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
);
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
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 //////////////////////////////////////////////////////////////////////