Reland D23318594 and D23318592 add recordbasenativesp instr
[hiphop-php.git] / hphp / runtime / vm / preclass.h
blob8601a56e3c0c8b2394e5816dcc2d49b015218680
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 +----------------------------------------------------------------------+
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>
36 namespace HPHP {
37 ///////////////////////////////////////////////////////////////////////////////
39 struct Class;
40 struct Func;
41 struct ObjectData;
42 struct NamedEntity;
43 struct StringData;
44 struct Unit;
46 struct PreClassEmitter;
48 namespace Native { struct NativeDataInfo; }
50 ///////////////////////////////////////////////////////////////////////////////
52 using TraitNameSet = std::set<LowStringPtr,
53 string_data_lti>;
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.
70 * Hoistability:
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
83 * its Unit.
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
97 * split below.
100 struct PreClass : AtomicCountable {
101 friend struct PreClassEmitter;
102 using UpperBoundVec = VMCompactVector<TypeConstraint>;
103 using UpperBoundMap = vm_flat_map<const StringData*, UpperBoundVec>;
105 /////////////////////////////////////////////////////////////////////////////
106 // Types.
108 enum Hoistable {
109 NotHoistable,
110 Mergeable,
111 MaybeHoistable,
112 AlwaysHoistable,
116 * Instance property information.
118 struct Prop {
119 Prop(PreClass* preClass,
120 const StringData* name,
121 Attr attrs,
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; }
144 private:
145 LowStringPtr m_name;
146 LowStringPtr m_mangledName;
147 Attr m_attrs;
148 LowStringPtr m_userType;
149 LowStringPtr m_docComment;
150 TypedValue m_val;
151 RepoAuthType m_repoAuthType;
152 TypeConstraint m_typeConstraint;
153 UpperBoundVec m_ubs;
154 UserAttributeMap m_userAttributes;
158 * Class constant information.
160 struct Const {
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);
175 private:
176 LowStringPtr m_name;
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;") */
180 TypedValueAux m_val;
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 {
190 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);
204 private:
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 {
216 TraitAliasRule();
217 TraitAliasRule(const StringData* traitName,
218 const StringData* origMethodName,
219 const StringData* newMethodName,
220 Attr modifiers);
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;
243 private:
244 LowStringPtr m_traitName;
245 LowStringPtr m_origMethodName;
246 LowStringPtr m_newMethodName;
247 Attr m_modifiers;
251 * Trait and interface requirements.
253 * Represents a `require implements' or `require extends' declaration.
255 struct ClassRequirement {
256 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;
263 size_t hash() 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);
271 private:
272 static uintptr_t pack(const StringData* req, bool isExtends);
274 uintptr_t m_word{0};
277 private:
278 typedef IndexedStringMap<Func*,false,Slot> MethodMap;
279 typedef IndexedStringMap<Prop,true,Slot> PropMap;
280 typedef IndexedStringMap<Const,true,Slot> ConstMap;
282 public:
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);
296 ~PreClass();
298 void atomicRelease();
301 /////////////////////////////////////////////////////////////////////////////
302 // Direct data accessors.
305 * Basic info.
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
324 * traits).
326 * This value is only valid when trait methods are flattened; otherwise, it
327 * is -1.
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.
357 void
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)
383 #undef DEF_ACCESSORS
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 /////////////////////////////////////////////////////////////////////////////
396 // Other accessors.
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 /////////////////////////////////////////////////////////////////////////////
433 // Other methods.
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,
442 Attr attrs);
445 /////////////////////////////////////////////////////////////////////////////
446 // Data members.
448 private:
449 Unit* m_unit;
450 LowPtr<NamedEntity> m_namedEntity;
451 int m_line1;
452 int m_line2;
453 Id m_id;
454 Attr m_attrs;
455 Hoistable m_hoistable;
456 LowStringPtr m_name;
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};
469 MethodMap m_methods;
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_