Fix refcounting in arReturn() and stop leaking static strings.
[hiphop-php.git] / hphp / runtime / vm / class.h
blobcc9f528b0b70754eaa6f7590750bf1c84dd658ba
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2014 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_CLASS_H_
18 #define incl_HPHP_VM_CLASS_H_
20 #include "hphp/runtime/base/types.h"
21 #include "hphp/runtime/base/attr.h"
22 #include "hphp/runtime/base/rds.h"
23 #include "hphp/runtime/base/repo-auth-type.h"
24 #include "hphp/runtime/base/type-array.h"
25 #include "hphp/runtime/base/type-string.h"
26 #include "hphp/runtime/base/typed-value.h"
28 #include "hphp/runtime/vm/fixed-string-map.h"
29 #include "hphp/runtime/vm/indexed-string-map.h"
30 #include "hphp/runtime/vm/instance-bits.h"
31 #include "hphp/runtime/vm/preclass.h"
33 #include <boost/range/iterator_range.hpp>
35 #include <list>
36 #include <memory>
37 #include <utility>
38 #include <vector>
40 namespace HPHP {
41 ///////////////////////////////////////////////////////////////////////////////
43 struct Class;
44 struct ClassInfo;
45 struct ClassInfoVM;
46 struct Func;
47 struct HhbcExtClassInfo;
48 struct StringData;
50 namespace Native { struct NativeDataInfo; }
52 ///////////////////////////////////////////////////////////////////////////////
54 typedef AtomicSmartPtr<Class> ClassPtr;
57 * Class represents the full definition of a user class in a given request
58 * context.
60 * See PreClass for more on the distinction.
62 * The method table is allocated at negative offset from the start of the Class
63 * object, and the method slot is used as the negative offset from the object
64 * to index into the method table.
66 * +------------+
67 * Func Slot n (offset -(n+1)) --> | |
68 * ....
69 * | |
70 * +------------+
71 * Func Slot 1 (offset -2) ------> | |
72 * +------------+
73 * Func Slot 0 (offset -1) ------> | |
74 * Class* -----------------------> +------------+
75 * | |
76 * ....
77 * | |
78 * +------------+
80 struct Class : AtomicCountable {
82 /////////////////////////////////////////////////////////////////////////////
83 // Types.
86 * Class availability.
88 * @see: Class::avail()
90 enum class Avail {
91 False,
92 True,
93 Fail
97 * Instance property information.
99 struct Prop {
100 // m_name is "" for inaccessible properties (i.e. private properties
101 // declared by parents).
102 LowStringPtr m_name;
103 LowStringPtr m_mangledName;
104 LowStringPtr m_originalMangledName;
105 // First parent class that declares this property.
106 LowClassPtr m_class;
107 Attr m_attrs;
108 LowStringPtr m_typeConstraint;
109 // When built in RepoAuthoritative mode, this is a control-flow
110 // insensitive, always-true type assertion for this property. (It may be
111 // Gen if there was nothing interesting known.)
112 RepoAuthType m_repoAuthType;
113 LowStringPtr m_docComment;
114 int m_idx;
118 * Static property information.
120 struct SProp {
121 LowStringPtr m_name;
122 Attr m_attrs;
123 LowStringPtr m_typeConstraint;
124 LowStringPtr m_docComment;
125 // Most derived class that declared this property.
126 LowClassPtr m_class;
127 // Used if (m_class == this).
128 TypedValue m_val;
129 RepoAuthType m_repoAuthType;
130 int m_idx;
134 * Class constant information.
136 struct Const {
137 // Most derived class that declared this constant.
138 LowClassPtr m_class;
139 LowStringPtr m_name;
140 TypedValue m_val;
141 LowStringPtr m_phpCode;
142 LowStringPtr m_typeConstraint;
146 * Initialization vector for declared properties.
148 * This is a vector which contains default values for all of a Class's
149 * declared instance properties. It is used when instantiating new objects
150 * from a Class.
152 struct PropInitVec {
153 PropInitVec();
154 ~PropInitVec();
156 const PropInitVec& operator=(const PropInitVec&);
158 typedef TypedValueAux* iterator;
160 iterator begin();
161 iterator end();
162 size_t size() const;
164 TypedValueAux& operator[](size_t i);
165 const TypedValueAux& operator[](size_t i) const;
167 void push_back(const TypedValue& v);
170 * Make a smart-allocated copy of `src'.
172 static PropInitVec* allocWithSmartAllocator(const PropInitVec& src);
174 static size_t dataOff() {
175 return offsetof(PropInitVec, m_data);
178 private:
179 PropInitVec(const PropInitVec&);
181 TypedValueAux* m_data;
182 unsigned m_size;
183 bool m_smart;
187 * Container typedefs.
189 typedef std::vector<std::pair<LowStringPtr,LowStringPtr>> TraitAliasVec;
191 typedef FixedStringMap<Slot, false, Slot> MethodMap;
192 typedef FixedStringMapBuilder<Func*, Slot, false, Slot> MethodMapBuilder;
193 typedef IndexedStringMap<LowClassPtr, true, int> InterfaceMap;
194 typedef IndexedStringMap<
195 const PreClass::ClassRequirement*, true, int> RequirementMap;
198 /////////////////////////////////////////////////////////////////////////////
199 // Creation and destruction.
202 * Allocate a new Class object.
204 * Eventually deallocated using atomicRelease(), but can go through some
205 * phase changes before that (see destroy()).
207 static Class* newClass(PreClass* preClass, Class* parent);
210 * Called when a Class becomes unreachable.
212 * This may happen before its refcount hits zero if it is still referred to
213 * by any of:
214 * - its NamedEntity;
215 * - any derived Class;
216 * - any Class that implements it (for interfaces); or
217 * - any Class that uses it (for traits)
219 * Such referring classes must also be logically dead at the time destroy()
220 * is called. However, since we don't have back pointers to find them,
221 * instead we leave the Class in a zombie state. When we try to instantiate
222 * one of its referrers, we will notice that it depends on a zombie and
223 * destroy *that*, releasing its reference to this Class.
225 void destroy();
228 * Called when the (atomic) refcount hits zero.
230 * The Class is completely dead at this point, and its memory is freed
231 * immediately.
233 void atomicRelease();
235 private:
237 * Free any references to child classes, interfaces, and traits.
239 * releaseRefs() is called when a Class is put into the zombie state. It's
240 * safe to call multiple times, so it is also called from the destructor (in
241 * case we bypassed the zombie state).
243 void releaseRefs();
245 public:
247 * Whether this class has been logically destroyed, but needed to be
248 * preserved due to outstanding references.
250 bool isZombie() const;
253 * Check whether a Class from a previous request is available to be defined.
254 * The caller should check that it has the same PreClass that is being
255 * defined. Being available means that the parent, the interfaces, and the
256 * traits are already defined (or become defined via autoload, if tryAutoload
257 * is true).
259 * @returns: Avail::True: if it's available
260 * Avail::Fail: if at least one of the parent, interfaces, and
261 * traits is not defined at all at this point
262 * Avail::False: if at least one of the parent, interfaces, and
263 * traits is defined but does not correspond to this
264 * particular Class*
266 * The parent parameter is used for two purposes: first, it lets us avoid
267 * looking up the active parent class for each potential Class*; and second,
268 * it is used on Fail to return the problem class so the caller can report
269 * the error correctly.
271 Avail avail(Class*& parent, bool tryAutoload = false) const;
274 /////////////////////////////////////////////////////////////////////////////
275 // Pre- and post-allocations. [const]
278 * The start of malloc'd memory for `this' (i.e., including the method
279 * table).
281 Func** mallocPtrFromThis() const;
284 * Pointer to the array of Class pointers, allocated immediately after
285 * `this', which contain this class's inheritance hierarchy (including `this'
286 * as the last element).
288 const LowClassPtr* classVec() const;
291 * The size of the classVec.
293 unsigned classVecLen() const;
296 /////////////////////////////////////////////////////////////////////////////
297 // Ancestry. [const]
300 * Determine if this represents a non-strict subtype of `cls'.
302 * Returns uint64_t instead of bool because it's called directly from the TC.
304 uint64_t classof(const Class* cls) const;
307 * Whether this class implements an interface called `name'.
309 bool ifaceofDirect(const StringData* name) const;
312 * Assuming this and cls are both regular classes (not interfaces or traits),
313 * return their lowest common ancestor, or nullptr if they're unrelated.
315 const Class* commonAncestor(const Class* cls) const;
318 /////////////////////////////////////////////////////////////////////////////
319 // Basic info. [const]
322 * The name, PreClass, and parent class of this class.
324 const StringData* name() const;
325 const PreClass* preClass() const;
326 Class* parent() const;
329 * Uncounted String names of this class and of its parent.
331 StrNR nameStr() const;
332 StrNR parentStr() const;
335 * The attributes on this class.
337 Attr attrs() const;
340 * ObjectData attributes, to be set during instance initialization.
342 int getODAttrs() const;
345 * Whether we can load this class once and persist it across requests.
347 * Persistence is possible when a Class is uniquely named and is defined in a
348 * pseudomain that has no side-effects (except other persistent definitions).
350 * A class which satisfies isPersistent() may not actually /be/ persistent,
351 * if we had to allocate its RDS handle before we loaded the class.
353 * @see: classHasPersistentRDS()
355 bool isPersistent() const;
358 /////////////////////////////////////////////////////////////////////////////
359 // Magic methods. [const]
362 * Get the constructor, destructor, or __toString() method on this class, or
363 * nullptr if no such method exists.
365 * DeclaredCtor refers to a user-declared __construct() or ClassName(), as
366 * opposed to the default 86ctor() method generated by the compiler.
368 const Func* getCtor() const;
369 const Func* getDeclaredCtor() const;
370 const Func* getDtor() const;
371 const Func* getToString() const;
374 /////////////////////////////////////////////////////////////////////////////
375 // Builtin classes. [const]
378 * Is the class a builtin, whether PHP or C++?
380 bool isBuiltin() const;
383 * Return the ClassInfo for a C++ extension class.
385 const ClassInfo* clsInfo() const;
388 * Custom initialization and destruction routines for C++ extension classes.
390 * instanceCtor() returns true iff the class is a C++ extension class.
392 BuiltinCtorFunction instanceCtor() const;
393 BuiltinDtorFunction instanceDtor() const;
396 * This value is the pointer adjustment from an ObjectData* to get to the
397 * property vector, for a builtin class. In other words, it's the number of
398 * bytes of subclass data following the ObjectData subobject.
400 int32_t builtinODTailSize() const;
403 * Whether this C++ extension class has opted into serialization.
405 * @requires: instanceCtor()
407 bool isCppSerializable() const;
410 * Whether this is a class for a Hack collection.
412 bool isCollectionClass() const;
415 /////////////////////////////////////////////////////////////////////////////
416 // Methods.
419 * Number of methods on this class.
421 * Note that this may differ from m_funcVecLen, since numMethods() is the
422 * exact number of methods, and m_funcVecLen is only required to be an upper
423 * bound.
425 * In particular, outside of RepoAuth mode, trait methods are not transcluded
426 * into the Classes which use them, and we are conservative when initially
427 * counting methods since we do not resolve trait precedence first.
429 size_t numMethods() const;
432 * Get or set a method by its index in the funcVec, which is allocated
433 * contiguously before `this' in memory.
435 Func* getMethod(Slot idx) const;
436 void setMethod(Slot idx, Func* func);
439 * Look up a method by name.
441 * Return null if no such method exists.
443 Func* lookupMethod(const StringData* methName) const;
446 * Find the first class in the inheritance hierarchy which defines the method
447 * called `methName'. Return null if no such method is defined anywhere in
448 * the hierarchy.
450 * For trait methods, the base class is the one that uses/imports the trait.
452 Class* findMethodBaseClass(const StringData* methName);
455 * Whether this class (as opposed to some parent class) declared the given
456 * method.
458 * For trait methods, the class declaring the method is the one that
459 * uses/imports the trait.
461 bool declaredMethod(const Func* method);
464 /////////////////////////////////////////////////////////////////////////////
465 // Property metadata. [const]
467 // Unless otherwise specified, the terms "declared instance properties" and
468 // "static properties" both refer to properties declared on this class as
469 // well as those declared on its ancestors. Note that this includes private
470 // properties in both cases.
473 * Number of declared instance properties or static properties.
475 size_t numDeclProperties() const;
476 size_t numStaticProperties() const;
479 * Number of declared instance properties that are actually accessible from
480 * this class's context.
482 * Only really used when iterating over an object's properties.
484 uint32_t declPropNumAccessible() const;
487 * The info vector for declared instance properties or static properties.
489 const Prop* declProperties() const;
490 const SProp* staticProperties() const;
493 * Look up the index of a declared instance property or static property.
495 * Return kInvalidSlot if no such property exists.
497 Slot lookupDeclProp(const StringData* propName) const;
498 Slot lookupSProp(const StringData* sPropName) const;
501 * The RepoAuthType of the declared instance property or static property at
502 * `index' in the corresponding table.
504 RepoAuthType declPropRepoAuthType(Slot index) const;
505 RepoAuthType staticPropRepoAuthType(Slot index) const;
508 * Whether this class has any properties that require deep initialization.
510 * Deep initialization means that the property cannot simply be memcpy'd when
511 * creating new objects.
513 bool hasDeepInitProps() const;
516 /////////////////////////////////////////////////////////////////////////////
517 // Property initialization. [const]
520 * Whether this Class requires initialization, either because of nonscalar
521 * instance property initializers, or simply due to having static properties.
523 bool needInitialization() const;
526 * Perform request-local initialization.
528 * For declared instance properties, this means creating a request-local copy
529 * of this Class's PropInitVec. This is necessary in order to accommodate
530 * non-scalar defaults (e.g., class constants), which not be consistent
531 * across requests.
533 * For static properties, this means setting up request-local memory for the
534 * actual static properties, if necessary, and initializing them to their
535 * default values.
537 void initialize() const;
538 void initProps() const;
539 void initSProps() const;
542 * PropInitVec for this class's declared properties, with default values for
543 * scalars only.
545 * This is the base from which the request-local copy is made.
547 const PropInitVec& declPropInit() const;
550 * Vector of 86pinit non-scalar instance property initializer functions.
552 * These are invoked during initProps() to populate the copied PropInitVec.
554 const std::vector<const Func*>& pinitVec() const;
557 /////////////////////////////////////////////////////////////////////////////
558 // Property storage. [const]
561 * Initialize the RDS handles for the request-local PropInitVec and for the
562 * static properties.
564 void initPropHandle() const;
565 void initSPropHandles() const;
568 * RDS handle of the request-local PropInitVec.
570 RDS::Handle propHandle() const;
573 * RDS handle for the static properties' is-initialized flag.
575 RDS::Handle sPropInitHandle() const;
578 * RDS handle for the static property at `index'.
580 RDS::Handle sPropHandle(Slot index) const;
583 * Get the PropInitVec for the current request.
585 PropInitVec* getPropData() const;
588 * Get the value of the static variable at `index' for the current request.
590 TypedValue* getSPropData(Slot index) const;
593 /////////////////////////////////////////////////////////////////////////////
594 // Property lookup and accessibility. [const]
597 * Get the slot and accessibility of the declared instance property `key' on
598 * this class from the context `ctx'.
600 * Accessibility refers to the public/protected/private attribute of the
601 * property. The value of `accessible' is output by reference.
603 * Return kInvalidInd iff the property was not declared on this class or any
604 * ancestor. Note that if `accessible' is true, then the property must
605 * exist.
607 Slot getDeclPropIndex(Class* ctx, const StringData* key,
608 bool& accessible) const;
611 * Get the slot, visibility, and accessibility of the static property
612 * `sPropName on this class from the context `ctx'.
614 * Visibility refers to whether or not the property exists at all.
615 * Accessibility refers to the public/protected/private attribute of the
616 * property.
618 * Both `visible' and `accessible' are output by reference.
620 * Return kInvalidInd (and set `visible' to false) iff the property does not
621 * exist. Note also that if `accessible' is true, then the property must
622 * exist.
624 Slot findSProp(Class* ctx, const StringData* sPropName,
625 bool& visible, bool& accessible) const;
628 * Get the request-local value of the static property `sPropName', as well as
629 * its visibility and accessibility, from the context `ctx'.
631 * The behavior is identical to that of findSProp(), except substituting
632 * nullptr for kInvalidInd.
634 * May perform initialization.
636 TypedValue* getSProp(Class* ctx, const StringData* sPropName,
637 bool& visible, bool& accessible) const;
640 * Identical to getSProp(), but the output is boxed.
642 * Used by the ext_zend_compat layer.
644 RefData* zGetSProp(Class* ctx, const StringData* sPropName,
645 bool& visible, bool& accessible) const;
648 * Return whether or not the declared instance property described by `prop'
649 * is accessible from the context `ctx'.
651 static bool IsPropAccessible(const Prop& prop, Class* ctx);
654 /////////////////////////////////////////////////////////////////////////////
655 // Constants. [const]
658 * Number of class constants.
660 size_t numConstants() const;
663 * The info vector for this class's constants.
665 const Const* constants() const;
668 * Whether this class has a constant named `clsCnsName'.
670 bool hasConstant(const StringData* clsCnsName) const;
673 * Look up the actual value of a class constant. Perform dynamic
674 * initialization if necessary.
676 * Return a Cell containing KindOfUninit if this class has no such constant.
678 * The returned Cell is guaranteed not to hold a reference counted object (it
679 * may, however, be KindOfString for a static string).
681 Cell clsCnsGet(const StringData* clsCnsName) const;
684 * Look up a class constant's TypedValue if it doesn't require dynamic
685 * initialization. The index of the constant is output via `clsCnsInd'.
687 * Return nullptr if this class has no constant of the given name.
689 * The TypedValue represents the constant's value iff it is a scalar,
690 * otherwise it has m_type set to KindOfUninit. Non-scalar class constants
691 * need to run 86cinit code to determine their value at runtime.
693 const Cell* cnsNameToTV(const StringData* clsCnsName, Slot& clsCnsInd) const;
696 * Provide the current runtime type of this class constant.
698 * This has predictive value for the translator.
700 DataType clsCnsType(const StringData* clsCnsName) const;
703 /////////////////////////////////////////////////////////////////////////////
704 // Interfaces and traits.
707 * Interfaces this class declared in its "implements" clause.
709 boost::iterator_range<const ClassPtr*> declInterfaces() const;
712 * All interfaces implemented by this class, including those declared in
713 * traits.
715 const InterfaceMap& allInterfaces() const;
718 * Start and end offsets in m_methods of methods that come from used traits.
720 * The trait methods are precisely in [m_traitsBeginIdx, m_traitsEndIdx).
722 Slot traitsBeginIdx() const;
723 Slot traitsEndIdx() const;
726 * Traits used by this class.
728 * In RepoAuthoritative mode, we flatten all traits into their users in the
729 * compile phase, which leaves m_usedTraits empty as a result.
731 const std::vector<ClassPtr>& usedTraitClasses() const;
734 * Vector of (new name, original name) pairs representing trait aliases.
736 * Not const due to memoization; this is only used for reflection.
738 const TraitAliasVec& traitAliases();
741 * All trait and interface requirements imposed on this class, including
742 * those imposed by traits.
744 const RequirementMap& allRequirements() const;
747 /////////////////////////////////////////////////////////////////////////////
748 // Objects. [const]
751 * Offset of the declared instance property at `index' on an ObjectData
752 * instantiated from this class.
754 size_t declPropOffset(Slot index) const;
757 * Whether instances of this class need to call a custom __init__ when
758 * created.
760 bool callsCustomInstanceInit() const;
763 /////////////////////////////////////////////////////////////////////////////
764 // Other methods.
766 // Avoiding adding methods to this section.
769 * Whether this class can be made persistent---i.e., if AttrPersistent is set
770 * and all parents, interfaces, and traits for this class are persistent.
772 bool verifyPersistent() const;
775 * Populate the ClassInfoVM for this class in `ci'.
777 void getClassInfo(ClassInfoVM* ci);
780 * Get and set the RDS handle for the class with this class's name.
782 * We can burn these into the TC even when classes are not persistent, since
783 * only a single name-to-class mapping will exist per request.
785 RDS::Handle classHandle() const;
786 void setClassHandle(RDS::Link<Class*> link) const;
789 * Get and set the RDS-cached class with this class's name.
791 Class* getCached() const;
792 void setCached();
795 * Set the instance bits on this class.
797 * The instance bits are a bitfield cache for instanceof checks. During
798 * warmup, we profile the classes and interfaces most commonly checked
799 * against in instanceof checks. Then we cache whether or not this Class
800 * satisifes the check in the corresponding bit.
802 void setInstanceBits();
803 void setInstanceBitsAndParents();
806 * NativeData type declared in <<__NativeData("Type")>>.
808 const Native::NativeDataInfo* getNativeDataInfo() const;
811 * Get the underlying enum base type if this is an enum.
813 DataType enumBaseTy() const;
816 /////////////////////////////////////////////////////////////////////////////
817 // Offset accessors. [static]
819 #define OFF(f) \
820 static constexpr ptrdiff_t f##Off() { \
821 return offsetof(Class, m_##f); \
823 OFF(classVec)
824 OFF(classVecLen)
825 OFF(instanceBits)
826 OFF(invoke)
827 OFF(preClass)
828 OFF(propDataCache)
829 #undef OFF
832 /////////////////////////////////////////////////////////////////////////////
833 // Internal types.
835 private:
836 typedef IndexedStringMap<Const,true,Slot> ConstMap;
837 typedef IndexedStringMap<Prop,true,Slot> PropMap;
838 typedef IndexedStringMap<SProp,true,Slot> SPropMap;
840 struct TraitMethod {
841 TraitMethod(Class* trait, Func* method, Attr modifiers)
842 : m_trait(trait)
843 , m_method(method)
844 , m_modifiers(modifiers)
847 LowClassPtr m_trait;
848 Func* m_method;
849 Attr m_modifiers;
852 typedef std::list<TraitMethod> TraitMethodList;
853 typedef hphp_hash_map<LowStringPtr,
854 TraitMethodList,
855 string_data_hash,
856 string_data_isame> MethodToTraitListMap;
859 /////////////////////////////////////////////////////////////////////////////
860 // Private methods.
862 private:
863 Class(PreClass* preClass,
864 Class* parent,
865 std::vector<ClassPtr>&& usedTraits,
866 unsigned classVecLen,
867 unsigned funcVecLen);
868 ~Class();
870 bool needsInitSProps() const;
872 void importTraitMethod(const TraitMethod& traitMethod,
873 const StringData* methName,
874 MethodMapBuilder& curMethodMap);
875 Class* findSingleTraitWithMethod(const StringData* methName);
876 void setImportTraitMethodModifiers(TraitMethodList& methList,
877 Class* traitCls,
878 Attr modifiers);
879 void importTraitMethods(MethodMapBuilder& curMethodMap);
880 void addTraitPropInitializers(bool staticProps);
881 void applyTraitRules(MethodToTraitListMap& importMethToTraitMap);
882 void applyTraitPrecRule(const PreClass::TraitPrecRule& rule,
883 MethodToTraitListMap& importMethToTraitMap);
884 void applyTraitAliasRule(const PreClass::TraitAliasRule& rule,
885 MethodToTraitListMap& importMethToTraitMap);
886 void importTraitProps(int idxOffset,
887 PropMap::Builder& curPropMap,
888 SPropMap::Builder& curSPropMap);
889 void importTraitInstanceProp(Class* trait,
890 Prop& traitProp,
891 TypedValue& traitPropVal,
892 const int idxOffset,
893 PropMap::Builder& curPropMap);
894 void importTraitStaticProp(Class* trait,
895 SProp& traitProp,
896 const int idxOffset,
897 PropMap::Builder& curPropMap,
898 SPropMap::Builder& curSPropMap);
899 void addTraitAlias(const StringData* traitName,
900 const StringData* origMethName,
901 const StringData* newMethName);
903 void checkInterfaceMethods();
904 void methodOverrideCheck(const Func* parentMethod, const Func* method);
906 static bool compatibleTraitPropInit(TypedValue& tv1, TypedValue& tv2);
907 void removeSpareTraitAbstractMethods(
908 MethodToTraitListMap& importMethToTraitMap);
910 void setParent();
911 void setSpecial();
912 void setMethods();
913 void setODAttributes();
914 void setConstants();
915 void setProperties();
916 void setInitializers();
917 void setInterfaces();
918 void setClassVec();
919 void setFuncVec(MethodMapBuilder& builder);
920 void setRequirements();
921 void setEnumType();
922 void checkRequirementConstraints() const;
923 void raiseUnsatisfiedRequirement(const PreClass::ClassRequirement*) const;
924 void setNativeDataInfo();
926 template<bool setParents> void setInstanceBitsImpl();
927 void addInterfacesFromUsedTraits(InterfaceMap::Builder& builder) const;
930 /////////////////////////////////////////////////////////////////////////////
931 // Static data members.
933 public:
935 * A hashtable that maps class names to structures containing C++ function
936 * pointers for the class's methods and constructors.
938 static hphp_hash_map<const StringData*,
939 const HhbcExtClassInfo*,
940 string_data_hash,
941 string_data_isame> s_extClassHash;
944 * Callback which, if set, runs during setMethods().
946 static void (*MethodCreateHook)(Class* cls, MethodMapBuilder& builder);
949 /////////////////////////////////////////////////////////////////////////////
950 // Data members.
952 // Ordered by usage frequency. Do not re-order for cosmetic reasons.
954 // The ordering is reverse order of hotness because m_classVec is relatively
955 // hot, and must be the last member.
957 public:
958 Class* m_nextClass{nullptr}; // used by NamedEntity
960 private:
961 DataType m_enumBaseTy;
963 // Objects with the <<__NativeData("T")>> UA are allocated with extra space
964 // prior to the ObjectData structure itself.
965 const Native::NativeDataInfo *m_nativeDataInfo{nullptr};
966 std::unique_ptr<ClassPtr[]> m_declInterfaces;
968 TraitAliasVec m_traitAliases;
970 Slot m_traitsBeginIdx{0};
971 Slot m_traitsEndIdx{0};
972 mutable RDS::Link<Array> m_nonScalarConstantCache{RDS::kInvalidHandle};
973 size_t m_numDeclInterfaces{0};
974 Func* m_toString;
976 // In RepoAuthoritative mode, we rely on trait flattening in the compile
977 // phase to import the contents of traits. As a result, m_usedTraits is
978 // always empty.
979 std::vector<ClassPtr> m_usedTraits;
980 ConstMap m_constants;
981 ClassPtr m_parent;
982 int32_t m_declPropNumAccessible;
983 mutable RDS::Link<Class*> m_cachedClass{RDS::kInvalidHandle};
985 // Vector of 86pinit() methods that need to be called to complete instance
986 // property initialization, and a pointer to a 86sinit() method that needs to
987 // be called to complete static property initialization (or NULL). Such
988 // initialization is triggered only once, the first time one of the following
989 // happens:
990 // - An instance of this class is created.
991 // - A static property of this class is accessed.
992 std::vector<const Func*> m_sinitVec;
993 const ClassInfo* m_clsInfo{nullptr};
994 Func* m_invoke; // __invoke, iff non-static (or closure)
995 Func* m_ctor;
996 PropInitVec m_declPropInit;
997 std::vector<const Func*> m_pinitVec;
998 SPropMap m_staticProperties;
999 BuiltinCtorFunction m_instanceCtor{nullptr};
1000 mutable RDS::Link<PropInitVec*> m_propDataCache{RDS::kInvalidHandle};
1001 uint32_t m_builtinODTailSize{0};
1002 PreClassPtr m_preClass;
1003 InterfaceMap m_interfaces;
1004 RequirementMap m_requirements;
1005 // Bitmap of parent classes and implemented interfaces. Each bit corresponds
1006 // to a commonly used class name, determined during the profiling warmup
1007 // requests.
1008 InstanceBits::BitSet m_instanceBits;
1009 BuiltinDtorFunction m_instanceDtor{nullptr};
1010 Func* m_dtor;
1011 MethodMap m_methods;
1013 // Static properties are stored in RDS. There are three phases of sprop
1014 // initialization:
1015 // 1. The array of links is itself allocated on Class creation.
1016 // 2. The links are bound either when codegen needs the handle value, or when
1017 // initSProps() is called in any request. Afterwards, m_sPropCacheInit is
1018 // bound, defaulting to false.
1019 // 3. The RDS value at m_sPropCacheInit is set to true when initSProps() is
1020 // called, and the values are actually initialized.
1021 mutable RDS::Link<TypedValue>* m_sPropCache{nullptr};
1022 mutable RDS::Link<bool> m_sPropCacheInit{RDS::kInvalidHandle};
1024 unsigned m_classVecLen;
1025 unsigned m_funcVecLen;
1027 // Each ObjectData is created with enough trailing space to directly store
1028 // the vector of declared properties. To look up a property by name and
1029 // determine whether it is declared, use m_declPropMap. If the declared
1030 // property index is already known (as may be the case when executing via the
1031 // TC), property metadata in m_declPropInfo can be directly accessed.
1033 // m_declPropInit is indexed by the Slot values from m_declProperties, and
1034 // contains initialization information.
1035 PropMap m_declProperties;
1037 int32_t m_ODAttrs;
1038 unsigned m_needInitialization : 1; // requires initialization,
1039 // due to [ps]init or simply
1040 // having static members
1041 unsigned m_completelyUnused : 1; // keep things in the same place
1042 unsigned m_callsCustomInstanceInit : 1; // should we always call __init__
1043 // on new instances?
1044 unsigned m_hasDeepInitProps : 1;
1045 unsigned m_attrCopy : 28; // cache of m_preClass->attrs().
1047 // Vector of Class pointers that encodes the inheritance hierarchy,
1048 // including this Class as the last element.
1049 LowClassPtr m_classVec[1]; // Dynamically sized; must come last.
1052 ///////////////////////////////////////////////////////////////////////////////
1055 * Class kinds---classes, interfaces, traits, and enums.
1057 * "Normal class" refers to any classes that are not interfaces, traits, enums.
1059 enum class ClassKind {
1060 Class = AttrNone,
1061 Interface = AttrInterface,
1062 Trait = AttrTrait,
1063 Enum = AttrEnum
1066 Attr classKindAsAttr(ClassKind kind);
1068 bool isTrait(const Class* cls);
1069 bool isInterface(const Class* cls);
1070 bool isEnum(const Class* cls);
1071 bool isAbstract(const Class* cls);
1072 bool isNormalClass(const Class* cls);
1075 * Whether a class is persistent /and/ has a persistent RDS handle. You
1076 * probably mean this instead of cls->isPersistent(), which only checks the
1077 * attributes.
1079 * A persistent class can end up with a non-persistent RDS handle if we had to
1080 * allocate the handle before we loaded the class.
1082 bool classHasPersistentRDS(const Class* cls);
1085 * Return the class that "owns" f. This will normally be f->cls(), but for
1086 * Funcs with static locals, f may have been cloned into a derived class.
1088 * @requires: RuntimeOption::EvalPerfDataMap
1090 const Class* getOwningClassForFunc(const Func* f);
1092 ///////////////////////////////////////////////////////////////////////////////
1095 #define incl_HPHP_VM_CLASS_INL_H_
1096 #include "hphp/runtime/vm/class-inl.h"
1097 #undef incl_HPHP_VM_CLASS_INL_H_
1099 #endif // incl_HPHP_VM_CLASS_H_