No more RefData struct
[hiphop-php.git] / hphp / runtime / vm / unit.h
blob4c79b888fe4162a31f175a8afff5119b3947467a
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_UNIT_H_
18 #define incl_HPHP_VM_UNIT_H_
20 #include "hphp/parser/location.h"
22 #include "hphp/runtime/base/typed-value.h"
23 #include "hphp/runtime/base/repo-auth-type-array.h"
24 #include "hphp/runtime/vm/class.h"
25 #include "hphp/runtime/vm/containers.h"
26 #include "hphp/runtime/vm/hhbc.h"
27 #include "hphp/runtime/vm/named-entity.h"
28 #include "hphp/runtime/vm/named-entity-pair-table.h"
29 #include "hphp/runtime/vm/preclass.h"
30 #include "hphp/runtime/vm/record.h"
31 #include "hphp/runtime/vm/type-alias.h"
33 #include "hphp/util/compact-vector.h"
34 #include "hphp/util/fixed-vector.h"
35 #include "hphp/util/functional.h"
36 #include "hphp/util/hash-map.h"
37 #include "hphp/util/lock-free-ptr-wrapper.h"
38 #include "hphp/util/mutex.h"
39 #include "hphp/util/service-data.h"
40 #include "hphp/util/sha1.h"
42 #include <map>
43 #include <ostream>
44 #include <string>
45 #include <vector>
46 #include <atomic>
48 namespace HPHP {
49 ///////////////////////////////////////////////////////////////////////////////
51 struct Array;
52 struct ArrayData;
53 struct Class;
54 struct Func;
55 struct PreClass;
56 struct String;
57 struct StringData;
58 struct UnitExtended;
60 ///////////////////////////////////////////////////////////////////////////////
61 // Unit enums.
64 * Where was a given Unit defined from?
66 enum class UnitOrigin {
67 File = 0,
68 Eval = 1
71 ///////////////////////////////////////////////////////////////////////////////
72 // Location tables.
75 * Delimiter pairs for a location in the source code.
77 struct SourceLoc {
79 * Constructors.
81 SourceLoc() {}
82 explicit SourceLoc(const Location::Range& l);
85 * Reset to, or check for, the invalid state.
87 void reset();
88 bool valid() const;
91 * Set to a parser Location.
93 void setLoc(const Location::Range* l);
96 * Equality.
98 bool same(const SourceLoc* l) const;
99 bool operator==(const SourceLoc& l) const;
102 * Start and end lines and characters.
104 * The default {1, 1, 1, 1} is an invalid sentinel value.
106 int line0{1};
107 int char0{1};
108 int line1{1};
109 int char1{1};
113 * Pair of (base, past) offsets.
115 struct OffsetRange {
116 OffsetRange() {}
118 OffsetRange(Offset base, Offset past)
119 : base(base)
120 , past(past)
123 Offset base{0};
124 Offset past{0};
127 using OffsetRangeVec = std::vector<OffsetRange>;
130 * Generic entry for representing many-to-one mappings of Offset -> T.
132 * Each entry's `pastOffset' is expected to be the offset just past the range
133 * of offsets which logically map to its `val'. In this way, by maintaining a
134 * relatively sparse set of entries in a vector, we can use least upper bound
135 * searches on an offset key to find its corresponding T.
137 * The values of `pastOffset' in such a table are expected to be sorted and
138 * unique, but the values of `val' need not be.
140 template<typename T>
141 struct TableEntry {
143 * Constructors.
145 TableEntry()
146 : m_pastOffset()
147 , m_val()
150 TableEntry(Offset pastOffset, T val)
151 : m_pastOffset(pastOffset)
152 , m_val(val)
156 * Accessors.
158 Offset pastOffset() const;
159 T val() const;
162 * Comparison.
164 bool operator<(const TableEntry& other) const;
166 template<class SerDe> void serde(SerDe& sd);
168 private:
169 Offset m_pastOffset{0};
170 T m_val;
174 * Table specializations.
176 using LineEntry = TableEntry<int>;
177 using SourceLocEntry = TableEntry<SourceLoc>;
178 using LineInfo = std::pair<OffsetRange, int>;
180 using LineTable = std::vector<LineEntry>;
181 using SourceLocTable = std::vector<SourceLocEntry>;
182 using FuncTable = VMCompactVector<const Func*>;
185 * Get the line number or SourceLoc for Offset `pc' in `table'.
187 int getLineNumber(const LineTable& table, Offset pc);
188 bool getSourceLoc(const SourceLocTable& table, Offset pc, SourceLoc& sLoc);
189 void stashLineTable(const Unit* unit, LineTable table);
190 void stashExtendedLineTable(const Unit* unit, SourceLocTable table);
192 const SourceLocTable& getSourceLocTable(const Unit*);
195 * Sum of all Unit::m_bclen
197 extern ServiceData::ExportedTimeSeries* g_hhbc_size;
199 ///////////////////////////////////////////////////////////////////////////////
202 * Metadata about a compilation unit.
204 * Contains the list of PreClasses and global functions, along with a special
205 * function called the 'pseudomain', which is logically invoked (modulo
206 * optimizations that avoid it) during execution when the unit is included or
207 * required.
209 struct Unit {
210 friend struct UnitExtended;
211 friend struct UnitEmitter;
212 friend struct UnitRepoProxy;
214 /////////////////////////////////////////////////////////////////////////////
215 // Types.
217 private:
219 * The Unit's current merge state.
221 * Merging is the process by which functions, classes, and constants defined
222 * in a pseudomain are added to the unit in advance (or, optimistically,
223 * instead of) running the pseudomain's code. This is necessary for
224 * correctness in a number of cases---e.g., toplevel functions defined in the
225 * pseudomain need to be available before the line where the definition
226 * occurs.
228 * Whenever we want to evaluate a Unit, we call merge() on it, and then
229 * invoke its pseudomain only if necessary.
231 enum MergeState : uint8_t {
232 Unmerged = 0,
233 Merging = 1 << 0,
234 Merged = 1 << 1,
235 UniqueFuncs = 1 << 2,
236 NeedsCompact = 1 << 3,
237 Empty = 1 << 5
240 public:
242 * Information on all the mergeable defs within a Unit.
244 * Allocated with a variable-length pointer array in m_mergeables, structured
245 * as follows:
246 * - the Unit's pseudomain
247 * - hoistable functions (i.e., toplevel functions that need to be available
248 * from the beginning of the pseudomain)
249 * - all other mergeable objects, with the bottom three bits of the pointer
250 * tagged with a MergeKind
252 struct MergeInfo {
253 using FuncRange = folly::Range<Func* const*>;
254 using MutableFuncRange = folly::Range<Func**>;
257 * Allocate a new MergeInfo with `num' mergeables.
259 static MergeInfo* alloc(size_t num);
262 * Iterators.
264 * funcHoistableBegin() is in (funcBegin, funcEnd].
266 Func** funcBegin() const;
267 Func** funcEnd() const;
268 Func** funcHoistableBegin() const;
271 * Ranges.
273 * All ranges end at funcEnd().
275 FuncRange funcs() const;
276 MutableFuncRange mutableFuncs() const;
277 MutableFuncRange nonMainFuncs() const;
280 * Get a reference or pointer to the mergeable at index `idx'.
282 void*& mergeableObj(int idx);
283 void** mergeableData(int idx);
285 unsigned m_firstHoistableFunc;
286 unsigned m_firstHoistablePreClass;
287 unsigned m_firstMergeablePreClass;
288 unsigned m_mergeablesSize;
289 void* m_mergeables[1];
293 * Type of a mergeable object.
295 * This is encoded in the lowest three bits of a pointer to the object.
297 enum class MergeKind {
298 Class = 0, // Class is required to be 0 for correctness.
299 UniqueDefinedClass = 1,
300 Define = 2, // Toplevel scalar define.
301 PersistentDefine = 3, // Cross-request persistent toplevel defines.
302 Global = 4, // Global variable declarations.
303 TypeAlias = 5,
304 ReqDoc = 6,
305 Done = 7,
306 // We cannot add more kinds here; this has to fit in 3 bits.
310 * Range types.
312 using FuncRange = MergeInfo::FuncRange;
313 using MutableFuncRange = MergeInfo::MutableFuncRange;
316 * Cache for pseudomains for this unit, keyed by Class context.
318 using PseudoMainCacheMap = hphp_hash_map<
319 const Class*, Func*, pointer_hash<Class>
322 using PreClassPtrVec = VMCompactVector<PreClassPtr>;
323 using TypeAliasVec = VMFixedVector<TypeAlias>;
325 /////////////////////////////////////////////////////////////////////////////
326 // Construction and destruction.
328 Unit();
329 ~Unit();
332 * New and delete using low memory.
334 void* operator new(size_t sz);
335 void operator delete(void* p, size_t sz);
337 /////////////////////////////////////////////////////////////////////////////
338 // Basic accessors. [const]
341 * Repo ID and serial number.
343 int repoID() const;
344 int64_t sn() const;
347 * SHA1 of the source code for Unit.
349 SHA1 sha1() const;
352 * SHA1 of the bytecode for Unit.
354 SHA1 bcSha1() const;
357 * File and directory paths.
359 const StringData* filepath() const;
360 const StringData* dirpath() const;
363 * Was this unit created in response to an internal compiler error?
365 bool isICE() const;
367 /////////////////////////////////////////////////////////////////////////////
368 // Bytecode. [const]
371 * Start and size of the bytecode for the Unit.
373 PC entry() const;
374 Offset bclen() const;
377 * Convert between PC and Offset from entry().
379 PC at(Offset off) const;
380 Offset offsetOf(PC pc) const;
383 * Is `pc' in this Unit?
385 bool contains(PC pc) const;
388 * Get the Op at `instrOffset'.
390 Op getOp(Offset instrOffset) const;
392 /////////////////////////////////////////////////////////////////////////////
393 // Code locations. [const]
396 * Get the line number corresponding to `pc'.
398 * Return -1 if not found.
400 int getLineNumber(Offset pc) const;
403 * Get the SourceLoc corresponding to `pc'.
405 * Return false if not found, else true.
407 bool getSourceLoc(Offset pc, SourceLoc& sLoc) const;
410 * Get the Offset range(s) corresponding to `pc' or `line'.
412 * Return false if not found, else true.
414 bool getOffsetRange(Offset pc, OffsetRange& range) const;
415 bool getOffsetRanges(int line, OffsetRangeVec& offsets) const;
418 * Get next line with executable code starting from input `line'.
420 * Return -1 if not found.
422 int getNearestLineWithCode(int line) const;
425 * Return the Func* for the code at offset `pc'.
427 * Return nullptr if the offset is not in a Func body (but this should be
428 * impossible).
430 const Func* getFunc(Offset pc) const;
432 /////////////////////////////////////////////////////////////////////////////
433 // Litstrs and NamedEntitys. [const]
436 * Size of the Unit's litstr table.
438 * This excludes litstrs that are instead found in the global table---thus,
439 * it is not a source of truth for the number of litstrs a Unit needs, only
440 * those it happens to own.
442 size_t numLitstrs() const;
445 * Is `id' a valid litstr in LitstrTable or the Unit's local
446 * NamedEntityPairTable?
448 bool isLitstrId(Id id) const;
451 * Dispatch to either the global LitstrTable or the Unit's local
452 * NamedEntityPairTable, depending on whether `id' is global.
454 * @see: NamedEntityPairTable
456 StringData* lookupLitstrId(Id id) const;
457 const NamedEntity* lookupNamedEntityId(Id id) const;
458 NamedEntityPair lookupNamedEntityPairId(Id id) const;
460 /////////////////////////////////////////////////////////////////////////////
461 // Arrays. [const]
464 * Size of the Unit's scalar array table.
466 size_t numArrays() const;
469 * Look up a scalar array by ID.
471 const ArrayData* lookupArrayId(Id id) const;
474 * Look up a RepoAuthType::Array by ID
476 const RepoAuthType::Array* lookupArrayTypeId(Id id) const;
478 /////////////////////////////////////////////////////////////////////////////
479 // Funcs, PreClasses, and RecordDescs. [const]
482 * Look up a Func or PreClass or PreRecordDesc by ID.
484 Func* lookupFuncId(Id id) const;
485 PreClass* lookupPreClassId(Id id) const;
486 PreRecordDesc* lookupPreRecordId(Id id) const;
489 * Range over all Funcs or PreClasses or RecordDescs in the Unit.
491 FuncRange funcs() const;
492 folly::Range<PreClassPtr*> preclasses();
493 folly::Range<const PreClassPtr*> preclasses() const;
494 folly::Range<PreRecordDescPtr*> prerecords();
495 folly::Range<const PreRecordDescPtr*> prerecords() const;
498 * Get a pseudomain for the Unit with the context class `cls'.
500 * We clone the toplevel pseudomain for each context class and cache the
501 * results in m_pseudoMainCache.
503 Func* getMain(Class* cls, bool hasThis) const;
505 // Return the cached EntryPoint
506 Func* getCachedEntryPoint() const;
509 * Visit all functions and methods in this unit.
511 template<class Fn> void forEachFunc(Fn fn) const;
513 /////////////////////////////////////////////////////////////////////////////
514 // Func lookup. [static]
517 * Define `func' for this request by initializing its RDS handle.
519 static void defFunc(Func* func, bool debugger);
522 * Look up the defined Func in this request with name `name', or with the name
523 * mapped to the NamedEntity `ne'.
525 * Return nullptr if the function is not yet defined in this request.
527 static Func* lookupFunc(const NamedEntity* ne);
528 static Func* lookupFunc(const StringData* name);
531 * Look up, or autoload and define, the Func in this request with name `name',
532 * or with the name mapped to the NamedEntity `ne'.
534 * @requires: NamedEntity::get(name) == ne
536 static Func* loadFunc(const NamedEntity* ne, const StringData* name);
537 static Func* loadFunc(const StringData* name);
540 * bind (or rebind) a func to the NamedEntity corresponding to its
541 * name.
543 static void bindFunc(Func* func);
546 * Lookup the builtin in this request with name `name', or nullptr if none
547 * exists. This does not access RDS so it is safe to use from within the
548 * compiler. Note that does not mean imply that the name binding for the
549 * builtin is immutable. The builtin could be renamed or intercepted.
551 static Func* lookupBuiltin(const StringData* name);
553 /////////////////////////////////////////////////////////////////////////////
554 // Class lookup. [static]
557 * Define a new Class from `preClass' for this request.
559 * Raises a fatal error in various conditions (e.g., Class already defined,
560 * parent Class not defined, etc.) if `failIsFatal' is set).
562 * Also always fatals if a type alias already exists in this request with the
563 * same name as that of `preClass', regardless of the value of `failIsFatal'.
565 static Class* defClass(const PreClass* preClass, bool failIsFatal = true);
568 * Define a closure from preClass. Closures have unique names, so unlike
569 * defClass, this is a one time operation.
571 static Class* defClosure(const PreClass* preClass);
574 * Set the NamedEntity for `alias' to refer to the class `original' in this
575 * request.
577 * Raises a warning and returns false if `alias' already refers to a
578 * Class in this request, or if original is not loaded, and autoload
579 * is false, or it can't be autoloaded. Returns true otherwise.
581 static bool aliasClass(const StringData* original, const StringData* alias,
582 bool autoload);
585 * Look up the Class in this request with name `name', or with the name
586 * mapped to the NamedEntity `ne'.
588 * Return nullptr if the class is not yet defined in this request.
590 static Class* lookupClass(const NamedEntity* ne);
591 static Class* lookupClass(const StringData* name);
594 * Finds a class which is guaranteed to be unique in the specified
595 * context. The class has not necessarily been loaded in the
596 * current request.
598 * Return nullptr if there is no such class.
600 static const Class* lookupUniqueClassInContext(const NamedEntity* ne,
601 const Class* ctx);
602 static const Class* lookupUniqueClassInContext(const StringData* name,
603 const Class* ctx);
606 * Look up, or autoload and define, the Class in this request with name
607 * `name', or with the name mapped to the NamedEntity `ne'.
609 * @requires: NamedEntity::get(name) == ne
611 static Class* loadClass(const NamedEntity* ne, const StringData* name);
612 static Class* loadClass(const StringData* name);
615 * Autoload the Class with name `name' and bind it `ne' in this request.
617 * @requires: NamedEntity::get(name) == ne
619 static Class* loadMissingClass(const NamedEntity* ne, const StringData* name);
622 * Same as lookupClass(), but if `tryAutoload' is set, call and return
623 * loadMissingClass().
625 static Class* getClass(const NamedEntity* ne, const StringData* name,
626 bool tryAutoload);
627 static Class* getClass(const StringData* name, bool tryAutoload);
630 * Whether a Class with name `name' of type `kind' has been defined in this
631 * request, autoloading it if `autoload' is set.
633 static bool classExists(const StringData* name,
634 bool autoload, ClassKind kind);
636 /////////////////////////////////////////////////////////////////////////////
637 // RecordDesc lookup. [static]
640 * Define a new RecordDesc from `record' for this request.
642 * Raises a fatal error in various conditions (e.g., RecordDesc already
643 * defined, etc.) if `failIsFatal' is set).
645 * Also always fatals if a type alias already exists in this request with the
646 * same name as that of `record', regardless of the value of `failIsFatal'.
648 static RecordDesc* defRecordDesc(PreRecordDesc* record,
649 bool failIsFatal = true);
652 * Look up the RecordDesc in this request with name `name', or with the name
653 * mapped to the NamedEntity `ne'.
655 * Return nullptr if the record is not yet defined in this request.
657 static RecordDesc* lookupRecordDesc(const NamedEntity* ne);
658 static RecordDesc* lookupRecordDesc(const StringData* name);
661 * Finds a record which is guaranteed to be unique.
662 * The record has not necessarily been loaded in the current request.
664 * Return nullptr if there is no such record.
666 static const RecordDesc* lookupUniqueRecDesc(const StringData* name);
669 * Autoload the RecordDesc with name `name' and bind it `ne' in this request.
671 * @requires: NamedEntity::get(name) == ne
673 static RecordDesc* loadMissingRecordDesc(const NamedEntity* ne,
674 const StringData* name);
677 * Same as lookupRecordDesc(), but if `tryAutoload' is set, call and return
678 * loadMissingRecordDesc().
680 static RecordDesc* getRecordDesc(const NamedEntity* ne,
681 const StringData* name,
682 bool tryAutoload);
683 static RecordDesc* getRecordDesc(const StringData* name, bool tryAutoload);
685 /////////////////////////////////////////////////////////////////////////////
686 // Constant lookup. [static]
689 * Look up the value of the defined constant in this request with name
690 * `cnsName'.
692 * Return nullptr if no such constant is defined.
694 static tv_rval lookupCns(const StringData* cnsName);
697 * Look up the value of the persistent constant with name `cnsName'.
699 * Return nullptr if no such constant exists, or the constant is not
700 * persistent.
702 static const Cell* lookupPersistentCns(const StringData* cnsName);
705 * Look up, or autoload and define, the value of the constant with name
706 * `cnsName' for this request.
708 static tv_rval loadCns(const StringData* cnsName);
711 * Define a constant (either request-local or persistent) with name `cnsName'
712 * and value `value'.
714 * May raise notices or warnings if a constant with the given name is already
715 * defined or if value is invalid.
717 static bool defCns(const StringData* cnsName, const TypedValue* value);
720 * Define a constant with name `cnsName' with a magic callback. The
721 * Cell should be KindOfUninit, with a Native::ConstantCallback in
722 * its m_data.pcnt.
724 * The canonical examples are STDIN, STDOUT, and STDERR.
726 static bool defNativeConstantCallback(const StringData* cnsName, Cell cell);
728 /////////////////////////////////////////////////////////////////////////////
729 // Type aliases.
731 folly::Range<TypeAlias*> typeAliases();
732 folly::Range<const TypeAlias*> typeAliases() const;
735 * Look up without autoloading a type alias named `name'. Returns nullptr
736 * if one cannot be found.
738 * If the type alias is found and `persistent' is provided, it will be set to
739 * whether or not the TypeAliasReq's RDS handle is persistent.
741 static const TypeAliasReq* lookupTypeAlias(const StringData* name,
742 bool* persistent = nullptr);
745 * Look up or attempt to autoload a type alias named `name'. Returns nullptr
746 * if one cannot be found or autoloaded.
748 * If the type alias is found and `persistent' is provided, it will be set to
749 * whether or not the TypeAliasReq's RDS handle is persistent.
751 static const TypeAliasReq* loadTypeAlias(const StringData* name,
752 bool* persistent = nullptr);
755 * Define the type alias given by `id', binding it to the appropriate
756 * NamedEntity for this request.
758 * returns true iff the bound type alias is persistent.
760 bool defTypeAlias(Id id);
762 /////////////////////////////////////////////////////////////////////////////
763 // File attributes.
765 const UserAttributeMap& fileAttributes() const;
767 /////////////////////////////////////////////////////////////////////////////
768 // Merge.
771 * Merge the Unit if it is not already merged.
773 void merge();
776 * Is it sufficient to merge the Unit, and skip invoking its pseudomain?
778 bool isMergeOnly() const;
781 * Is this Unit empty---i.e., does it define nothing and have no
782 * side-effects?
784 bool isEmpty() const;
787 * Get the return value of the pseudomain, or KindOfUninit if not
788 * known.
790 * @requires: isMergeOnly()
792 const TypedValue* getMainReturn() const;
794 /////////////////////////////////////////////////////////////////////////////
795 // Info arrays. [static]
798 * Generate class info arrays.
800 static Array getClassesInfo();
801 static Array getInterfacesInfo();
802 static Array getTraitsInfo();
805 * Generate function info arrays.
807 static Array getUserFunctions();
808 static Array getSystemFunctions();
810 /////////////////////////////////////////////////////////////////////////////
811 // Pretty printer. [const]
813 struct PrintOpts {
814 PrintOpts()
815 : startOffset(kInvalidOffset)
816 , stopOffset(kInvalidOffset)
817 , showLines(true)
818 , showFuncs(true)
819 , indentSize(1)
822 PrintOpts& range(Offset start, Offset stop) {
823 startOffset = start;
824 stopOffset = stop;
825 return *this;
828 PrintOpts& noLineNumbers() {
829 showLines = false;
830 return *this;
833 PrintOpts& noFuncs() {
834 showFuncs = false;
835 return *this;
838 PrintOpts& indent(int i) {
839 indentSize = i;
840 return *this;
843 Offset startOffset;
844 Offset stopOffset;
845 bool showLines;
846 bool showFuncs;
847 int indentSize;
850 void prettyPrint(std::ostream&, PrintOpts = PrintOpts()) const;
851 std::string toString() const;
853 /////////////////////////////////////////////////////////////////////////////
854 // Other methods.
857 * Is this Unit a compile-time fatal?
859 * A compile-time fatal is encoded as a pseudomain that contains precisely:
861 * String <id>; Fatal;
863 * Decode enough of pseudomain to determine whether it contains a
864 * compile-time fatal, and if so, extract the error message and line number.
866 * Parse-time fatals are a subset of compile-time fatals.
868 bool compileTimeFatal(const StringData*& msg, int& line) const;
869 bool parseFatal(const StringData*& msg, int& line) const;
872 * Get or set whether this Unit is interpret-only.
874 * This is used by the debugger to signal to the JIT that eval'd commands
875 * should not be jitted.
877 bool isInterpretOnly() const;
878 void setInterpretOnly();
881 * Replace the Unit?
883 void* replaceUnit() const;
886 * Does this unit correspond to a file with "<?hh" at the top?
888 bool isHHFile() const;
890 UserAttributeMap metaData() const;
892 // Return true, and set the m_serialized flag, iff this Unit hasn't
893 // been serialized yet (see prof-data-serialize.cpp).
894 bool serialize() const {
895 if (m_serialized) return false;
896 const_cast<Unit*>(this)->m_serialized = true;
897 return true;
900 /////////////////////////////////////////////////////////////////////////////
901 // Offset accessors. [static]
903 static constexpr ptrdiff_t bcOff() {
904 return offsetof(Unit, m_bc);
907 /////////////////////////////////////////////////////////////////////////////
908 // Internal methods.
910 private:
911 void initialMerge();
912 template<bool debugger>
913 void mergeImpl(MergeInfo* mi);
914 UnitExtended* getExtended();
915 const UnitExtended* getExtended() const;
916 MergeInfo* mergeInfo() const {
917 return m_mergeInfo.load(std::memory_order_acquire);
920 /////////////////////////////////////////////////////////////////////////////
921 // Data members.
923 // These are organized in reverse order of frequency of use. Do not re-order
924 // without checking perf!
925 private:
926 unsigned char const* m_bc{nullptr};
927 Offset m_bclen{0};
928 LowStringPtr m_filepath{nullptr};
929 std::atomic<MergeInfo*> m_mergeInfo{nullptr};
931 int8_t m_repoId{-1};
933 * m_mergeState is read without a lock, but only written to under
934 * unitInitLock (see unit.cpp).
936 std::atomic<uint8_t> m_mergeState{MergeState::Unmerged};
937 bool m_mergeOnly: 1;
938 bool m_interpretOnly : 1;
939 bool m_isHHFile : 1;
940 bool m_extended : 1;
941 bool m_serialized : 1;
942 bool m_ICE : 1; // was this unit the result of an internal compiler error
943 LowStringPtr m_dirpath{nullptr};
945 TypedValue m_mainReturn;
946 PreClassPtrVec m_preClasses;
947 TypeAliasVec m_typeAliases;
948 CompactVector<PreRecordDescPtr> m_preRecords;
950 * Cached the EntryPoint for an unit, since compactMergeInfo() inside of
951 * mergeImpl will drop the original EP.
953 Func* m_cachedEntryPoint{nullptr};
956 * The remaining fields are cold, and arbitrarily ordered.
959 int64_t m_sn{-1}; // Note: could be 32-bit
960 SHA1 m_sha1;
961 SHA1 m_bcSha1;
962 VMFixedVector<const ArrayData*> m_arrays;
963 mutable PseudoMainCacheMap* m_pseudoMainCache{nullptr};
964 mutable LockFreePtrWrapper<VMCompactVector<LineInfo>> m_lineMap;
965 UserAttributeMap m_metaData;
966 UserAttributeMap m_fileAttributes;
969 struct UnitExtended : Unit {
970 friend struct Unit;
971 friend struct UnitEmitter;
973 UnitExtended() { m_extended = true; }
975 NamedEntityPairTable m_namedInfo;
976 ArrayTypeTable m_arrayTypeTable;
977 FuncTable m_funcTable;
980 ///////////////////////////////////////////////////////////////////////////////
983 #define incl_HPHP_VM_UNIT_INL_H_
984 #include "hphp/runtime/vm/unit-inl.h"
985 #undef incl_HPHP_VM_UNIT_INL_H_
987 #endif // incl_HPHP_VM_UNIT_H_