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 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_VM_PRECLASS_H_
18 #define incl_HPHP_VM_PRECLASS_H_
20 #include "hphp/runtime/base/atomic-shared-ptr.h"
21 #include "hphp/runtime/base/attr.h"
22 #include "hphp/runtime/base/repo-auth-type.h"
23 #include "hphp/runtime/base/type-string.h"
24 #include "hphp/runtime/base/typed-value.h"
25 #include "hphp/runtime/base/user-attributes.h"
26 #include "hphp/runtime/base/atomic-countable.h"
27 #include "hphp/runtime/vm/containers.h"
28 #include "hphp/runtime/vm/indexed-string-map.h"
29 #include "hphp/runtime/vm/type-constraint.h"
31 #include "hphp/util/fixed-vector.h"
33 #include <type_traits>
34 #include <unordered_set>
37 ///////////////////////////////////////////////////////////////////////////////
46 struct PreClassEmitter
;
48 namespace Native
{ struct NativeDataInfo
; }
50 ///////////////////////////////////////////////////////////////////////////////
52 using TraitNameSet
= std::set
<LowStringPtr
,
55 using BuiltinCtorFunction
= LowPtr
<ObjectData
*(Class
*)>;
56 using BuiltinDtorFunction
= LowPtr
<void(ObjectData
*, const Class
*)>;
59 * A PreClass represents the source-level definition of a PHP class, interface,
60 * or trait. Includes things like the names of the parent class (if any), and
61 * the names of any interfaces implemented or traits used. Also contains
62 * metadata about properties and methods of the class.
64 * This is separate from an actual Class because in different requests
65 * (depending on include order), the actual instantiation of a PreClass may
66 * differ since names may have different meanings. For example, if the
67 * PreClass "extends Foo", and Foo is defined differently in different
68 * requests, we will make a different Class.
72 * When a Unit is loaded at run time, each PreClass in the Unit which is
73 * determined to be `hoistable' will be loaded by the runtime (in the order
74 * they appear in the source) before the Unit's pseudo-main is executed.
75 * The hoistability rules ensure that loading a PreClass which is determined
76 * to be hoistable will never cause the autoload facility to be invoked.
78 * A class is considered `hoistable' iff the following conditions apply:
80 * - It's defined at the top level.
82 * - There is no other definition for a class of the same name in
85 * - It uses no traits. (It may however *be* a trait.)
87 * - It implements no interfaces. (It may however *be* an interface.)
89 * - It is not an enum.
91 * - It has no parent OR
92 * The parent is hoistable and defined earlier in the unit OR
93 * The parent is already defined when the unit is required
95 * The very last condition here (parent already defined when the unit is
96 * required) is not known at parse time. This leads to the Maybe/Always
100 struct PreClass
: AtomicCountable
{
101 friend struct PreClassEmitter
;
102 using UpperBoundVec
= VMCompactVector
<TypeConstraint
>;
103 using UpperBoundMap
= vm_flat_map
<const StringData
*, UpperBoundVec
>;
105 /////////////////////////////////////////////////////////////////////////////
116 * Instance property information.
119 Prop(PreClass
* preClass
,
120 const StringData
* name
,
122 const StringData
* userType
,
123 const TypeConstraint
& typeConstraint
,
124 const CompactVector
<TypeConstraint
>& ubs
,
125 const StringData
* docComment
,
126 const TypedValue
& val
,
127 RepoAuthType repoAuthType
,
128 UserAttributeMap userAttributes
);
130 void prettyPrint(std::ostream
&, const PreClass
*) const;
132 const StringData
* name() const { return m_name
; }
133 const StringData
* mangledName() const { return m_mangledName
; }
134 Attr
attrs() const { return m_attrs
; }
135 const StringData
* userType() const { return m_userType
; }
136 const TypeConstraint
& typeConstraint() const { return m_typeConstraint
; }
137 const UpperBoundVec
& upperBounds() const { return m_ubs
; }
138 const StringData
* docComment() const { return m_docComment
; }
139 const TypedValue
& val() const { return m_val
; }
140 RepoAuthType
repoAuthType() const { return m_repoAuthType
; }
141 const UserAttributeMap
&
142 userAttributes() const { return m_userAttributes
; }
146 LowStringPtr m_mangledName
;
148 LowStringPtr m_userType
;
149 LowStringPtr m_docComment
;
151 RepoAuthType m_repoAuthType
;
152 TypeConstraint m_typeConstraint
;
154 UserAttributeMap m_userAttributes
;
158 * Class constant information.
161 Const(const StringData
* name
,
162 const TypedValueAux
& val
,
163 const StringData
* phpCode
);
165 void prettyPrint(std::ostream
&, const PreClass
*) const;
167 const StringData
* name() const { return m_name
; }
168 const TypedValueAux
& val() const { return m_val
; }
169 const StringData
* phpCode() const { return m_phpCode
; }
170 bool isAbstract() const { return m_val
.constModifiers().isAbstract(); }
171 bool isType() const { return m_val
.constModifiers().isType(); }
173 template<class SerDe
> void serde(SerDe
& sd
);
177 /* m_aux.u_isAbstractConst indicates an abstract constant. A TypedValue
178 * with KindOfUninit represents a constant whose value is not
179 * statically available (e.g. "const X = self::Y + 5;") */
181 LowStringPtr m_phpCode
;
185 * Trait precedence rule. Describes a usage of the `insteadof' operator.
187 * @see: http://php.net/manual/en/language.oop5.traits.php#language.oop5.traits.conflict
189 struct TraitPrecRule
{
191 TraitPrecRule(const StringData
* selectedTraitName
,
192 const StringData
* methodName
);
194 const StringData
* methodName() const { return m_methodName
; }
195 const StringData
* selectedTraitName() const { return m_selectedTraitName
; }
196 const TraitNameSet
& otherTraitNames() const { return m_otherTraitNames
; }
198 void addOtherTraitName(const StringData
* traitName
);
200 template<class SerDe
> void serde(SerDe
& sd
) {
201 sd(m_methodName
)(m_selectedTraitName
)(m_otherTraitNames
);
205 LowStringPtr m_methodName
;
206 LowStringPtr m_selectedTraitName
;
207 TraitNameSet m_otherTraitNames
;
211 * Trait alias rule. Describes a usage of the `as' operator.
213 * @see: http://php.net/manual/en/language.oop5.traits.php#language.oop5.traits.conflict
215 struct TraitAliasRule
{
217 TraitAliasRule(const StringData
* traitName
,
218 const StringData
* origMethodName
,
219 const StringData
* newMethodName
,
222 const StringData
* traitName() const { return m_traitName
; }
223 const StringData
* origMethodName() const { return m_origMethodName
; }
224 const StringData
* newMethodName() const { return m_newMethodName
; }
225 Attr
modifiers() const { return m_modifiers
; }
227 template<class SerDe
> void serde(SerDe
& sd
) {
228 sd(m_traitName
)(m_origMethodName
)(m_newMethodName
)(m_modifiers
);
232 * Pair of (new name, original name) representing the rule.
234 * This is the format for alias rules expected by reflection.
236 using NamePair
= std::pair
<LowStringPtr
,LowStringPtr
>;
239 * Get the rule as a NamePair.
241 NamePair
asNamePair() const;
244 LowStringPtr m_traitName
;
245 LowStringPtr m_origMethodName
;
246 LowStringPtr m_newMethodName
;
251 * Trait and interface requirements.
253 * Represents a `require implements' or `require extends' declaration.
255 struct ClassRequirement
{
257 ClassRequirement(const StringData
* req
, bool isExtends
);
259 const StringData
* name() const;
260 bool is_extends() const;
261 bool is_implements() const;
262 bool is_same(const ClassRequirement
* other
) const;
265 template<class SerDe
>
266 typename
std::enable_if
<SerDe::deserializing
>::type
serde(SerDe
& sd
);
268 template<class SerDe
>
269 typename
std::enable_if
<!SerDe::deserializing
>::type
serde(SerDe
& sd
);
272 static uintptr_t pack(const StringData
* req
, bool isExtends
);
278 typedef IndexedStringMap
<Func
*,false,Slot
> MethodMap
;
279 typedef IndexedStringMap
<Prop
,true,Slot
> PropMap
;
280 typedef IndexedStringMap
<Const
,true,Slot
> ConstMap
;
283 typedef VMFixedVector
<LowStringPtr
> InterfaceVec
;
284 typedef VMFixedVector
<LowStringPtr
> UsedTraitVec
;
285 typedef VMFixedVector
<ClassRequirement
> ClassRequirementsVec
;
286 typedef VMFixedVector
<TraitPrecRule
> TraitPrecRuleVec
;
287 typedef VMFixedVector
<TraitAliasRule
> TraitAliasRuleVec
;
290 /////////////////////////////////////////////////////////////////////////////
291 // Construction and destruction.
293 PreClass(Unit
* unit
, int line1
, int line2
, const StringData
* n
,
294 Attr attrs
, const StringData
* parent
, const StringData
* docComment
,
295 Id id
, Hoistable hoistable
);
298 void atomicRelease();
301 /////////////////////////////////////////////////////////////////////////////
302 // Direct data accessors.
307 Unit
* unit() const { return m_unit
; }
308 NamedEntity
* namedEntity() const { return m_namedEntity
; }
309 int line1() const { return m_line1
; }
310 int line2() const { return m_line2
; }
311 Id
id() const { return m_id
; }
312 Attr
attrs() const { return m_attrs
; }
313 const StringData
* name() const { return m_name
; }
314 const StringData
* parent() const { return m_parent
; }
315 const StringData
* docComment() const { return m_docComment
; }
316 Hoistable
hoistability() const { return m_hoistable
; }
318 int64_t dynConstructSampleRate() const {
319 return m_dynConstructSampleRate
;
323 * Number of methods declared on this class (as opposed to included via
326 * This value is only valid when trait methods are flattened; otherwise, it
329 int32_t numDeclMethods() const { return m_numDeclMethods
; }
332 * The interface vtable slot for this PreClass, or kInvalidSlot if it wasn't
333 * assigned one or isn't an interface.
335 Slot
ifaceVtableSlot() const { return m_ifaceVtableSlot
; }
338 * If this is an enum class, return the type of its enum values.
340 const TypeConstraint
& enumBaseTy() const { return m_enumBaseTy
; }
343 * Accessors for vectory data.
345 const InterfaceVec
& interfaces() const { return m_interfaces
; }
346 const UsedTraitVec
& usedTraits() const { return m_usedTraits
; }
347 const ClassRequirementsVec
& requirements() const { return m_requirements
; }
348 const TraitPrecRuleVec
& traitPrecRules() const { return m_traitPrecRules
; }
349 const TraitAliasRuleVec
& traitAliasRules() const { return m_traitAliasRules
; }
350 const UserAttributeMap
& userAttributes() const { return m_userAttributes
; }
353 * If the parent is sealed, enforce that we are in the whitelist.
354 * Note that parent may be derived through a using, extending, or
355 * implementing relationship.
358 enforceInMaybeSealedParentWhitelist(const PreClass
* parentPreClass
) const;
361 * Funcs, Consts, and Props all behave similarly. Define raw accessors
362 * foo() and numFoos() for people munging by hand, and ranges.
364 * methods(); constants(); properties();
365 * mutableMethods(); mutableConstants(); mutableProperties();
366 * numMethods(); numConstants(); numProperties();
367 * FuncRange ConstRange PropRange
368 * allMethods(); allConstants(); allProperties();
370 #define DEF_ACCESSORS(Type, TypeName, fields, Fields) \
371 Type const* fields() const { return m_##fields.accessList(); } \
372 Type* mutable##Fields() { return m_##fields.mutableAccessList(); } \
373 size_t num##Fields() const { return m_##fields.size(); } \
374 using TypeName##Range = folly::Range<Type const*>; \
375 TypeName##Range all##Fields() const { \
376 return TypeName##Range(fields(), m_##fields.size()); \
379 DEF_ACCESSORS(Func
*, Func
, methods
, Methods
)
380 DEF_ACCESSORS(Const
, Const
, constants
, Constants
)
381 DEF_ACCESSORS(Prop
, Prop
, properties
, Properties
)
385 const ConstMap
& constantsMap() const { return m_constants
; }
388 * NativeData type declared in <<__NativeData("Type")>>.
390 const Native::NativeDataInfo
* nativeDataInfo() const {
391 return m_nativeDataInfo
;
395 /////////////////////////////////////////////////////////////////////////////
399 * StrNR wrappers for name() and parent().
401 StrNR
nameStr() const { return StrNR(m_name
); }
402 StrNR
parentStr() const { return StrNR(m_parent
); }
405 * Attribute shortcut accessors.
407 bool isPersistent() const;
408 bool isBuiltin() const;
411 * Check whether a constant, method, or property exists on the PreClass.
413 bool hasConstant(const StringData
* cnsName
) const;
414 bool hasMethod(const StringData
* methName
) const;
415 bool hasProp(const StringData
* propName
) const;
418 * Look up a constant, method, or property on the PreClass.
420 * @requires: hasConstant(), hasMethod(), hasProp(), respectively.
422 const Const
* lookupConstant(const StringData
* cnsName
) const;
423 Func
* lookupMethod(const StringData
* methName
) const;
426 * Static offset accessors, used by the JIT.
428 static constexpr Offset
nameOffset() { return offsetof(PreClass
, m_name
); }
429 static constexpr Offset
attrsOffset() { return offsetof(PreClass
, m_attrs
); }
432 /////////////////////////////////////////////////////////////////////////////
435 void prettyPrint(std::ostream
& out
) const;
438 * Munge a property's accessibility into its name.
440 static const StringData
* manglePropName(const StringData
* className
,
441 const StringData
* propName
,
445 /////////////////////////////////////////////////////////////////////////////
450 LowPtr
<NamedEntity
> m_namedEntity
;
455 Hoistable m_hoistable
;
457 LowStringPtr m_parent
;
458 LowStringPtr m_docComment
;
459 int32_t m_numDeclMethods
;
460 Slot m_ifaceVtableSlot
{kInvalidSlot
};
461 TypeConstraint m_enumBaseTy
;
462 InterfaceVec m_interfaces
;
463 UsedTraitVec m_usedTraits
;
464 ClassRequirementsVec m_requirements
;
465 TraitPrecRuleVec m_traitPrecRules
;
466 TraitAliasRuleVec m_traitAliasRules
;
467 UserAttributeMap m_userAttributes
;
468 const Native::NativeDataInfo
*m_nativeDataInfo
{nullptr};
470 PropMap m_properties
;
471 ConstMap m_constants
;
472 int64_t m_dynConstructSampleRate
;
475 typedef AtomicSharedPtr
<PreClass
> PreClassPtr
;
477 ///////////////////////////////////////////////////////////////////////////////
480 #define incl_HPHP_VM_PRECLASS_INL_H_
481 #include "hphp/runtime/vm/preclass-inl.h"
482 #undef incl_HPHP_VM_PRECLASS_INL_H_
484 #endif // incl_HPHP_VM_PRECLASS_H_