Offload rarely-used members of Class to Class::ExtraData
[hiphop-php.git] / hphp / runtime / vm / class.h
blobb7eab43a49d3e173d7fe4b8211203d5b9d9c66c1
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"
27 #include "hphp/runtime/vm/fixed-string-map.h"
28 #include "hphp/runtime/vm/indexed-string-map.h"
29 #include "hphp/runtime/vm/instance-bits.h"
30 #include "hphp/runtime/vm/preclass.h"
32 #include "hphp/util/default-ptr.h"
34 #include <boost/range/iterator_range.hpp>
36 #include <list>
37 #include <memory>
38 #include <utility>
39 #include <vector>
41 namespace HPHP {
42 ///////////////////////////////////////////////////////////////////////////////
44 struct Class;
45 struct ClassInfo;
46 struct Func;
47 struct HhbcExtClassInfo;
48 struct StringData;
50 namespace Native { struct NativeDataInfo; }
52 ///////////////////////////////////////////////////////////////////////////////
54 using ClassPtr = AtomicSmartPtr<Class>;
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 using iterator = TypedValueAux*;
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 constexpr 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 types.
189 using MethodMap = FixedStringMap<Slot, false, Slot>;
190 using MethodMapBuilder = FixedStringMapBuilder<Func*, Slot, false, Slot>;
191 using InterfaceMap = IndexedStringMap<LowClassPtr, true, int>;
192 using RequirementMap = IndexedStringMap<
193 const PreClass::ClassRequirement*, true, int>;
195 using TraitAliasVec = std::vector<PreClass::TraitAliasRule::NamePair>;
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 LowFuncPtr* 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;
445 static void getMethodNames(const Class* cls, const Class* ctx, Array& result);
447 /////////////////////////////////////////////////////////////////////////////
448 // Property metadata. [const]
450 // Unless otherwise specified, the terms "declared instance properties" and
451 // "static properties" both refer to properties declared on this class as
452 // well as those declared on its ancestors. Note that this includes private
453 // properties in both cases.
456 * Number of declared instance properties or static properties.
458 size_t numDeclProperties() const;
459 size_t numStaticProperties() const;
462 * Number of declared instance properties that are actually accessible from
463 * this class's context.
465 * Only really used when iterating over an object's properties.
467 uint32_t declPropNumAccessible() const;
470 * The info vector for declared instance properties or static properties.
472 const Prop* declProperties() const;
473 const SProp* staticProperties() const;
476 * Look up the index of a declared instance property or static property.
478 * Return kInvalidSlot if no such property exists.
480 Slot lookupDeclProp(const StringData* propName) const;
481 Slot lookupSProp(const StringData* sPropName) const;
484 * The RepoAuthType of the declared instance property or static property at
485 * `index' in the corresponding table.
487 RepoAuthType declPropRepoAuthType(Slot index) const;
488 RepoAuthType staticPropRepoAuthType(Slot index) const;
491 * Whether this class has any properties that require deep initialization.
493 * Deep initialization means that the property cannot simply be memcpy'd when
494 * creating new objects.
496 bool hasDeepInitProps() const;
499 /////////////////////////////////////////////////////////////////////////////
500 // Property initialization. [const]
503 * Whether this Class requires initialization, either because of nonscalar
504 * instance property initializers, or simply due to having static properties.
506 bool needInitialization() const;
509 * Perform request-local initialization.
511 * For declared instance properties, this means creating a request-local copy
512 * of this Class's PropInitVec. This is necessary in order to accommodate
513 * non-scalar defaults (e.g., class constants), which not be consistent
514 * across requests.
516 * For static properties, this means setting up request-local memory for the
517 * actual static properties, if necessary, and initializing them to their
518 * default values.
520 void initialize() const;
521 void initProps() const;
522 void initSProps() const;
525 * PropInitVec for this class's declared properties, with default values for
526 * scalars only.
528 * This is the base from which the request-local copy is made.
530 const PropInitVec& declPropInit() const;
533 * Vector of 86pinit non-scalar instance property initializer functions.
535 * These are invoked during initProps() to populate the copied PropInitVec.
537 const std::vector<const Func*>& pinitVec() const;
540 /////////////////////////////////////////////////////////////////////////////
541 // Property storage. [const]
544 * Initialize the RDS handles for the request-local PropInitVec and for the
545 * static properties.
547 void initPropHandle() const;
548 void initSPropHandles() const;
551 * RDS handle of the request-local PropInitVec.
553 RDS::Handle propHandle() const;
556 * RDS handle for the static properties' is-initialized flag.
558 RDS::Handle sPropInitHandle() const;
561 * RDS handle for the static property at `index'.
563 RDS::Handle sPropHandle(Slot index) const;
566 * Get the PropInitVec for the current request.
568 PropInitVec* getPropData() const;
571 * Get the value of the static variable at `index' for the current request.
573 TypedValue* getSPropData(Slot index) const;
576 /////////////////////////////////////////////////////////////////////////////
577 // Property lookup and accessibility. [const]
580 * Get the slot and accessibility of the declared instance property `key' on
581 * this class from the context `ctx'.
583 * Accessibility refers to the public/protected/private attribute of the
584 * property. The value of `accessible' is output by reference.
586 * Return kInvalidInd iff the property was not declared on this class or any
587 * ancestor. Note that if `accessible' is true, then the property must
588 * exist.
590 Slot getDeclPropIndex(Class* ctx, const StringData* key,
591 bool& accessible) const;
594 * Get the slot, visibility, and accessibility of the static property
595 * `sPropName on this class from the context `ctx'.
597 * Visibility refers to whether or not the property exists at all.
598 * Accessibility refers to the public/protected/private attribute of the
599 * property.
601 * Both `visible' and `accessible' are output by reference.
603 * Return kInvalidInd (and set `visible' to false) iff the property does not
604 * exist. Note also that if `accessible' is true, then the property must
605 * exist.
607 Slot findSProp(Class* ctx, const StringData* sPropName,
608 bool& visible, bool& accessible) const;
611 * Get the request-local value of the static property `sPropName', as well as
612 * its visibility and accessibility, from the context `ctx'.
614 * The behavior is identical to that of findSProp(), except substituting
615 * nullptr for kInvalidInd.
617 * May perform initialization.
619 TypedValue* getSProp(Class* ctx, const StringData* sPropName,
620 bool& visible, bool& accessible) const;
623 * Identical to getSProp(), but the output is boxed.
625 * Used by the ext_zend_compat layer.
627 RefData* zGetSProp(Class* ctx, const StringData* sPropName,
628 bool& visible, bool& accessible) const;
631 * Return whether or not the declared instance property described by `prop'
632 * is accessible from the context `ctx'.
634 static bool IsPropAccessible(const Prop& prop, Class* ctx);
637 /////////////////////////////////////////////////////////////////////////////
638 // Constants. [const]
641 * Number of class constants.
643 size_t numConstants() const;
646 * The info vector for this class's constants.
648 const Const* constants() const;
651 * Whether this class has a constant named `clsCnsName'.
653 bool hasConstant(const StringData* clsCnsName) const;
656 * Look up the actual value of a class constant. Perform dynamic
657 * initialization if necessary.
659 * Return a Cell containing KindOfUninit if this class has no such constant.
661 * The returned Cell is guaranteed not to hold a reference counted object (it
662 * may, however, be KindOfString for a static string).
664 Cell clsCnsGet(const StringData* clsCnsName) const;
667 * Look up a class constant's TypedValue if it doesn't require dynamic
668 * initialization. The index of the constant is output via `clsCnsInd'.
670 * Return nullptr if this class has no constant of the given name.
672 * The TypedValue represents the constant's value iff it is a scalar,
673 * otherwise it has m_type set to KindOfUninit. Non-scalar class constants
674 * need to run 86cinit code to determine their value at runtime.
676 const Cell* cnsNameToTV(const StringData* clsCnsName, Slot& clsCnsInd) const;
679 * Provide the current runtime type of this class constant.
681 * This has predictive value for the translator.
683 DataType clsCnsType(const StringData* clsCnsName) const;
686 /////////////////////////////////////////////////////////////////////////////
687 // Interfaces and traits.
690 * Interfaces this class declared in its "implements" clause.
692 boost::iterator_range<const ClassPtr*> declInterfaces() const;
695 * All interfaces implemented by this class, including those declared in
696 * traits.
698 const InterfaceMap& allInterfaces() const;
701 * Start and end offsets in m_methods of methods that come from used traits.
703 * The trait methods are precisely in [m_traitsBeginIdx, m_traitsEndIdx).
705 Slot traitsBeginIdx() const;
706 Slot traitsEndIdx() const;
709 * Traits used by this class.
711 * In RepoAuthoritative mode, we flatten all traits into their users in the
712 * compile phase, which leaves m_usedTraits empty as a result.
714 const std::vector<ClassPtr>& usedTraitClasses() const;
717 * Trait alias rules.
719 * This is only used by reflection.
721 const TraitAliasVec& traitAliases() const;
724 * All trait and interface requirements imposed on this class, including
725 * those imposed by traits.
727 const RequirementMap& allRequirements() const;
730 /////////////////////////////////////////////////////////////////////////////
731 // Objects. [const]
734 * Offset of the declared instance property at `index' on an ObjectData
735 * instantiated from this class.
737 size_t declPropOffset(Slot index) const;
740 * Whether instances of this class need to call a custom __init__ when
741 * created.
743 bool callsCustomInstanceInit() const;
746 /////////////////////////////////////////////////////////////////////////////
747 // Other methods.
749 // Avoiding adding methods to this section.
752 * Whether this class can be made persistent---i.e., if AttrPersistent is set
753 * and all parents, interfaces, and traits for this class are persistent.
755 bool verifyPersistent() const;
758 * Get and set the RDS handle for the class with this class's name.
760 * We can burn these into the TC even when classes are not persistent, since
761 * only a single name-to-class mapping will exist per request.
763 RDS::Handle classHandle() const;
764 void setClassHandle(RDS::Link<Class*> link) const;
767 * Get and set the RDS-cached class with this class's name.
769 Class* getCached() const;
770 void setCached();
773 * Set the instance bits on this class.
775 * The instance bits are a bitfield cache for instanceof checks. During
776 * warmup, we profile the classes and interfaces most commonly checked
777 * against in instanceof checks. Then we cache whether or not this Class
778 * satisifes the check in the corresponding bit.
780 void setInstanceBits();
781 void setInstanceBitsAndParents();
784 * NativeData type declared in <<__NativeData("Type")>>.
786 const Native::NativeDataInfo* getNativeDataInfo() const;
789 * Get the underlying enum base type if this is an enum.
791 DataType enumBaseTy() const;
794 /////////////////////////////////////////////////////////////////////////////
795 // Offset accessors. [static]
797 #define OFF(f) \
798 static constexpr ptrdiff_t f##Off() { \
799 return offsetof(Class, m_##f); \
801 OFF(classVec)
802 OFF(classVecLen)
803 OFF(instanceBits)
804 OFF(invoke)
805 OFF(preClass)
806 OFF(propDataCache)
807 #undef OFF
810 /////////////////////////////////////////////////////////////////////////////
811 // ExtraData.
813 private:
814 struct ExtraData {
815 ExtraData() {}
818 * Vector of (new name, original name) pairs, representing trait aliases.
820 TraitAliasVec m_traitAliases;
823 * In RepoAuthoritative mode, we rely on trait flattening in the compile
824 * phase to import the contents of traits. As a result, m_usedTraits is
825 * always empty.
827 std::vector<ClassPtr> m_usedTraits;
830 * Only used by reflection for method ordering. Whenever we have no traits
831 * (e.g., in repo mode, where traits are flattened), these will both be 0.
833 Slot m_traitsBeginIdx{0};
834 Slot m_traitsEndIdx{0};
837 * Builtin-specific data.
839 BuiltinCtorFunction m_instanceCtor{nullptr};
840 BuiltinDtorFunction m_instanceDtor{nullptr};
841 const ClassInfo* m_clsInfo{nullptr};
842 uint32_t m_builtinODTailSize{0};
845 * Objects with the <<__NativeData("T")>> UA are allocated with extra space
846 * prior to the ObjectData structure itself.
848 const Native::NativeDataInfo *m_nativeDataInfo{nullptr};
852 * Allocate the ExtraData; done only when necessary.
854 void allocExtraData();
857 /////////////////////////////////////////////////////////////////////////////
858 // Internal types.
860 private:
861 using ConstMap = IndexedStringMap<Const,true,Slot>;
862 using PropMap = IndexedStringMap<Prop,true,Slot>;
863 using SPropMap = IndexedStringMap<SProp,true,Slot>;
865 struct TraitMethod {
866 TraitMethod(Class* trait, Func* method, Attr modifiers)
867 : m_trait(trait)
868 , m_method(method)
869 , m_modifiers(modifiers)
872 LowClassPtr m_trait;
873 Func* m_method;
874 Attr m_modifiers;
877 using TraitMethodList = std::list<TraitMethod>;
878 using MethodToTraitListMap = hphp_hash_map<LowStringPtr,
879 TraitMethodList,
880 string_data_hash,
881 string_data_isame>;
884 /////////////////////////////////////////////////////////////////////////////
885 // Private methods.
887 private:
888 Class(PreClass* preClass,
889 Class* parent,
890 std::vector<ClassPtr>&& usedTraits,
891 unsigned classVecLen,
892 unsigned funcVecLen);
893 ~Class();
895 bool needsInitSProps() const;
897 void importTraitMethod(const TraitMethod& traitMethod,
898 const StringData* methName,
899 MethodMapBuilder& curMethodMap);
900 Class* findSingleTraitWithMethod(const StringData* methName);
901 void setImportTraitMethodModifiers(TraitMethodList& methList,
902 Class* traitCls,
903 Attr modifiers);
904 void importTraitMethods(MethodMapBuilder& curMethodMap);
905 void addTraitPropInitializers(bool staticProps);
906 void applyTraitRules(MethodToTraitListMap& importMethToTraitMap);
907 void applyTraitPrecRule(const PreClass::TraitPrecRule& rule,
908 MethodToTraitListMap& importMethToTraitMap);
909 void applyTraitAliasRule(const PreClass::TraitAliasRule& rule,
910 MethodToTraitListMap& importMethToTraitMap);
911 void importTraitProps(int idxOffset,
912 PropMap::Builder& curPropMap,
913 SPropMap::Builder& curSPropMap);
914 void importTraitInstanceProp(Class* trait,
915 Prop& traitProp,
916 TypedValue& traitPropVal,
917 const int idxOffset,
918 PropMap::Builder& curPropMap);
919 void importTraitStaticProp(Class* trait,
920 SProp& traitProp,
921 const int idxOffset,
922 PropMap::Builder& curPropMap,
923 SPropMap::Builder& curSPropMap);
924 void addTraitAlias(const StringData* traitName,
925 const StringData* origMethName,
926 const StringData* newMethName);
928 void checkInterfaceMethods();
929 void methodOverrideCheck(const Func* parentMethod, const Func* method);
931 static bool compatibleTraitPropInit(TypedValue& tv1, TypedValue& tv2);
932 void removeSpareTraitAbstractMethods(
933 MethodToTraitListMap& importMethToTraitMap);
935 void setParent();
936 void setSpecial();
937 void setMethods();
938 void setODAttributes();
939 void setConstants();
940 void setProperties();
941 void setInitializers();
942 void setInterfaces();
943 void setClassVec();
944 void setFuncVec(MethodMapBuilder& builder);
945 void setRequirements();
946 void setEnumType();
947 void checkRequirementConstraints() const;
948 void raiseUnsatisfiedRequirement(const PreClass::ClassRequirement*) const;
949 void setNativeDataInfo();
951 template<bool setParents> void setInstanceBitsImpl();
952 void addInterfacesFromUsedTraits(InterfaceMap::Builder& builder) const;
955 /////////////////////////////////////////////////////////////////////////////
956 // Static data members.
958 public:
960 * A hashtable that maps class names to structures containing C++ function
961 * pointers for the class's methods and constructors.
963 static hphp_hash_map<const StringData*,
964 const HhbcExtClassInfo*,
965 string_data_hash,
966 string_data_isame> s_extClassHash;
969 * Callback which, if set, runs during setMethods().
971 static void (*MethodCreateHook)(Class* cls, MethodMapBuilder& builder);
974 /////////////////////////////////////////////////////////////////////////////
975 // Data members.
977 // Ordered by usage frequency. Do not re-order for cosmetic reasons.
979 // The ordering is reverse order of hotness because m_classVec is relatively
980 // hot, and must be the last member.
982 public:
983 Class* m_nextClass{nullptr}; // used by NamedEntity
985 private:
986 default_ptr<ExtraData> m_extra;
988 RequirementMap m_requirements;
989 std::unique_ptr<ClassPtr[]> m_declInterfaces;
990 size_t m_numDeclInterfaces{0};
991 mutable RDS::Link<Array> m_nonScalarConstantCache{RDS::kInvalidHandle};
993 LowFuncPtr m_toString;
994 LowFuncPtr m_invoke; // __invoke, iff non-static (or closure)
996 ConstMap m_constants;
997 ClassPtr m_parent;
998 int32_t m_declPropNumAccessible;
999 mutable RDS::Link<Class*> m_cachedClass{RDS::kInvalidHandle};
1001 // Vector of 86pinit() methods that need to be called to complete instance
1002 // property initialization, and a pointer to a 86sinit() method that needs to
1003 // be called to complete static property initialization (or NULL). Such
1004 // initialization is triggered only once, the first time one of the following
1005 // happens:
1006 // - An instance of this class is created.
1007 // - A static property of this class is accessed.
1008 std::vector<const Func*> m_sinitVec;
1009 LowFuncPtr m_ctor;
1010 LowFuncPtr m_dtor;
1011 PropInitVec m_declPropInit;
1012 std::vector<const Func*> m_pinitVec;
1013 SPropMap m_staticProperties;
1014 mutable RDS::Link<PropInitVec*> m_propDataCache{RDS::kInvalidHandle};
1015 PreClassPtr m_preClass;
1016 InterfaceMap m_interfaces;
1017 // Bitmap of parent classes and implemented interfaces. Each bit corresponds
1018 // to a commonly used class name, determined during the profiling warmup
1019 // requests.
1020 InstanceBits::BitSet m_instanceBits;
1021 MethodMap m_methods;
1023 // Static properties are stored in RDS. There are three phases of sprop
1024 // initialization:
1025 // 1. The array of links is itself allocated on Class creation.
1026 // 2. The links are bound either when codegen needs the handle value, or when
1027 // initSProps() is called in any request. Afterwards, m_sPropCacheInit is
1028 // bound, defaulting to false.
1029 // 3. The RDS value at m_sPropCacheInit is set to true when initSProps() is
1030 // called, and the values are actually initialized.
1031 mutable RDS::Link<TypedValue>* m_sPropCache{nullptr};
1032 mutable RDS::Link<bool> m_sPropCacheInit{RDS::kInvalidHandle};
1034 unsigned m_classVecLen;
1035 unsigned m_funcVecLen;
1037 // Each ObjectData is created with enough trailing space to directly store
1038 // the vector of declared properties. To look up a property by name and
1039 // determine whether it is declared, use m_declPropMap. If the declared
1040 // property index is already known (as may be the case when executing via the
1041 // TC), property metadata in m_declPropInfo can be directly accessed.
1043 // m_declPropInit is indexed by the Slot values from m_declProperties, and
1044 // contains initialization information.
1045 PropMap m_declProperties;
1047 DataType m_enumBaseTy;
1048 int32_t m_ODAttrs;
1050 unsigned m_needInitialization : 1; // requires initialization,
1051 // due to [ps]init or simply
1052 // having static members
1053 unsigned m_completelyUnused : 1; // keep things in the same place
1054 unsigned m_callsCustomInstanceInit : 1; // should we always call __init__
1055 // on new instances?
1056 unsigned m_hasDeepInitProps : 1;
1057 unsigned m_attrCopy : 28; // cache of m_preClass->attrs().
1060 * Vector of Class pointers that encodes the inheritance hierarchy, including
1061 * this Class as the last element.
1063 LowClassPtr m_classVec[1]; // Dynamically sized; must come last.
1066 ///////////////////////////////////////////////////////////////////////////////
1069 * Global lock used during class loading.
1071 extern Mutex g_classesMutex;
1073 ///////////////////////////////////////////////////////////////////////////////
1076 * Class kinds---classes, interfaces, traits, and enums.
1078 * "Normal class" refers to any classes that are not interfaces, traits, enums.
1080 enum class ClassKind {
1081 Class = AttrNone,
1082 Interface = AttrInterface,
1083 Trait = AttrTrait,
1084 Enum = AttrEnum
1087 Attr classKindAsAttr(ClassKind kind);
1089 bool isTrait(const Class* cls);
1090 bool isInterface(const Class* cls);
1091 bool isEnum(const Class* cls);
1092 bool isAbstract(const Class* cls);
1093 bool isNormalClass(const Class* cls);
1096 * Whether a class is persistent /and/ has a persistent RDS handle. You
1097 * probably mean this instead of cls->isPersistent(), which only checks the
1098 * attributes.
1100 * A persistent class can end up with a non-persistent RDS handle if we had to
1101 * allocate the handle before we loaded the class.
1103 bool classHasPersistentRDS(const Class* cls);
1106 * Return the class that "owns" f. This will normally be f->cls(), but for
1107 * Funcs with static locals, f may have been cloned into a derived class.
1109 * @requires: RuntimeOption::EvalPerfDataMap
1111 const Class* getOwningClassForFunc(const Func* f);
1113 ///////////////////////////////////////////////////////////////////////////////
1116 #define incl_HPHP_VM_CLASS_INL_H_
1117 #include "hphp/runtime/vm/class-inl.h"
1118 #undef incl_HPHP_VM_CLASS_INL_H_
1120 #endif // incl_HPHP_VM_CLASS_H_