Basic JIT support for Records
[hiphop-php.git] / hphp / runtime / vm / unit.h
blobd10db21d481cb25ad4ab727e3a489bfc13a0540d
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/md5.h"
39 #include "hphp/util/mutex.h"
40 #include "hphp/util/service-data.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 * MD5 of the Unit.
349 MD5 md5() const;
352 * File and directory paths.
354 const StringData* filepath() const;
355 const StringData* dirpath() const;
358 * Was this unit created in response to an internal compiler error?
360 bool isICE() const;
362 /////////////////////////////////////////////////////////////////////////////
363 // Bytecode. [const]
366 * Start and size of the bytecode for the Unit.
368 PC entry() const;
369 Offset bclen() const;
372 * Convert between PC and Offset from entry().
374 PC at(Offset off) const;
375 Offset offsetOf(PC pc) const;
378 * Is `pc' in this Unit?
380 bool contains(PC pc) const;
383 * Get the Op at `instrOffset'.
385 Op getOp(Offset instrOffset) const;
387 /////////////////////////////////////////////////////////////////////////////
388 // Code locations. [const]
391 * Get the line number corresponding to `pc'.
393 * Return -1 if not found.
395 int getLineNumber(Offset pc) const;
398 * Get the SourceLoc corresponding to `pc'.
400 * Return false if not found, else true.
402 bool getSourceLoc(Offset pc, SourceLoc& sLoc) const;
405 * Get the Offset range(s) corresponding to `pc' or `line'.
407 * Return false if not found, else true.
409 bool getOffsetRange(Offset pc, OffsetRange& range) const;
410 bool getOffsetRanges(int line, OffsetRangeVec& offsets) const;
413 * Get next line with executable code starting from input `line'.
415 * Return -1 if not found.
417 int getNearestLineWithCode(int line) const;
420 * Return the Func* for the code at offset `pc'.
422 * Return nullptr if the offset is not in a Func body (but this should be
423 * impossible).
425 const Func* getFunc(Offset pc) const;
427 /////////////////////////////////////////////////////////////////////////////
428 // Litstrs and NamedEntitys. [const]
431 * Size of the Unit's litstr table.
433 * This excludes litstrs that are instead found in the global table---thus,
434 * it is not a source of truth for the number of litstrs a Unit needs, only
435 * those it happens to own.
437 size_t numLitstrs() const;
440 * Is `id' a valid litstr in LitstrTable or the Unit's local
441 * NamedEntityPairTable?
443 bool isLitstrId(Id id) const;
446 * Dispatch to either the global LitstrTable or the Unit's local
447 * NamedEntityPairTable, depending on whether `id' is global.
449 * @see: NamedEntityPairTable
451 StringData* lookupLitstrId(Id id) const;
452 const NamedEntity* lookupNamedEntityId(Id id) const;
453 NamedEntityPair lookupNamedEntityPairId(Id id) const;
455 /////////////////////////////////////////////////////////////////////////////
456 // Arrays. [const]
459 * Size of the Unit's scalar array table.
461 size_t numArrays() const;
464 * Look up a scalar array by ID.
466 const ArrayData* lookupArrayId(Id id) const;
469 * Look up a RepoAuthType::Array by ID
471 const RepoAuthType::Array* lookupArrayTypeId(Id id) const;
473 /////////////////////////////////////////////////////////////////////////////
474 // Funcs, PreClasses, and Records. [const]
477 * Look up a Func or PreClass or Record by ID.
479 Func* lookupFuncId(Id id) const;
480 PreClass* lookupPreClassId(Id id) const;
481 Record* lookupRecordId(Id id) const;
484 * Range over all Funcs or PreClasses or Records in the Unit.
486 FuncRange funcs() const;
487 folly::Range<PreClassPtr*> preclasses();
488 folly::Range<const PreClassPtr*> preclasses() const;
489 folly::Range<RecordPtr*> records();
490 folly::Range<const RecordPtr*> records() const;
493 * Get a pseudomain for the Unit with the context class `cls'.
495 * We clone the toplevel pseudomain for each context class and cache the
496 * results in m_pseudoMainCache.
498 Func* getMain(Class* cls) const;
500 // Return the cached EntryPoint
501 Func* getCachedEntryPoint() const;
504 * Visit all functions and methods in this unit.
506 template<class Fn> void forEachFunc(Fn fn) const;
508 /////////////////////////////////////////////////////////////////////////////
509 // Func lookup. [static]
512 * Define `func' for this request by initializing its RDS handle.
514 static void defFunc(Func* func, bool debugger);
517 * Look up the defined Func in this request with name `name', or with the name
518 * mapped to the NamedEntity `ne'.
520 * Return nullptr if the function is not yet defined in this request.
522 static Func* lookupFunc(const NamedEntity* ne);
523 static Func* lookupFunc(const StringData* name);
526 * Look up, or autoload and define, the Func in this request with name `name',
527 * or with the name mapped to the NamedEntity `ne'.
529 * @requires: NamedEntity::get(name) == ne
531 static Func* loadFunc(const NamedEntity* ne, const StringData* name);
532 static Func* loadFunc(const StringData* name);
535 * bind (or rebind) a func to the NamedEntity corresponding to its
536 * name.
538 static void bindFunc(Func* func);
541 * Lookup the builtin in this request with name `name', or nullptr if none
542 * exists. This does not access RDS so it is safe to use from within the
543 * compiler. Note that does not mean imply that the name binding for the
544 * builtin is immutable. The builtin could be renamed or intercepted.
546 static Func* lookupBuiltin(const StringData* name);
548 /////////////////////////////////////////////////////////////////////////////
549 // Class lookup. [static]
552 * Define a new Class from `preClass' for this request.
554 * Raises a fatal error in various conditions (e.g., Class already defined,
555 * parent Class not defined, etc.) if `failIsFatal' is set).
557 * Also always fatals if a type alias already exists in this request with the
558 * same name as that of `preClass', regardless of the value of `failIsFatal'.
560 static Class* defClass(const PreClass* preClass, bool failIsFatal = true);
563 * Define a closure from preClass. Closures have unique names, so unlike
564 * defClass, this is a one time operation.
566 static Class* defClosure(const PreClass* preClass);
569 * Set the NamedEntity for `alias' to refer to the class `original' in this
570 * request.
572 * Raises a warning and returns false if `alias' already refers to a
573 * Class in this request, or if original is not loaded, and autoload
574 * is false, or it can't be autoloaded. Returns true otherwise.
576 static bool aliasClass(const StringData* original, const StringData* alias,
577 bool autoload);
580 * Look up the Class in this request with name `name', or with the name
581 * mapped to the NamedEntity `ne'.
583 * Return nullptr if the class is not yet defined in this request.
585 static Class* lookupClass(const NamedEntity* ne);
586 static Class* lookupClass(const StringData* name);
589 * Finds a class which is guaranteed to be unique in the specified
590 * context. The class has not necessarily been loaded in the
591 * current request.
593 * Return nullptr if there is no such class.
595 static const Class* lookupUniqueClassInContext(const NamedEntity* ne,
596 const Class* ctx);
597 static const Class* lookupUniqueClassInContext(const StringData* name,
598 const Class* ctx);
601 * Look up, or autoload and define, the Class in this request with name
602 * `name', or with the name mapped to the NamedEntity `ne'.
604 * @requires: NamedEntity::get(name) == ne
606 static Class* loadClass(const NamedEntity* ne, const StringData* name);
607 static Class* loadClass(const StringData* name);
610 * Autoload the Class with name `name' and bind it `ne' in this request.
612 * @requires: NamedEntity::get(name) == ne
614 static Class* loadMissingClass(const NamedEntity* ne, const StringData* name);
617 * Same as lookupClass(), but if `tryAutoload' is set, call and return
618 * loadMissingClass().
620 static Class* getClass(const NamedEntity* ne, const StringData* name,
621 bool tryAutoload);
622 static Class* getClass(const StringData* name, bool tryAutoload);
625 * Whether a Class with name `name' of type `kind' has been defined in this
626 * request, autoloading it if `autoload' is set.
628 static bool classExists(const StringData* name,
629 bool autoload, ClassKind kind);
631 /////////////////////////////////////////////////////////////////////////////
632 // Record lookup. [static]
635 * Define a new Record from `record' for this request.
637 * Raises a fatal error in various conditions (e.g., Record already defined,
638 * etc.) if `failIsFatal' is set).
640 * Also always fatals if a type alias already exists in this request with the
641 * same name as that of `record', regardless of the value of `failIsFatal'.
643 static Record* defRecord(Record* record, bool failIsFatal = true);
646 * Look up the Record in this request with name `name', or with the name
647 * mapped to the NamedEntity `ne'.
649 * Return nullptr if the record is not yet defined in this request.
651 static Record* lookupRecord(const NamedEntity* ne);
652 static Record* lookupRecord(const StringData* name);
655 * Look up, or autoload and define, the Record in this request with name
656 * `name', or with the name mapped to the NamedEntity `ne'.
658 * @requires: NamedEntity::get(name) == ne
660 static Record* loadRecord(const StringData* name);
662 /////////////////////////////////////////////////////////////////////////////
663 // Constant lookup. [static]
666 * Look up the value of the defined constant in this request with name
667 * `cnsName'.
669 * Return nullptr if no such constant is defined.
671 static tv_rval lookupCns(const StringData* cnsName);
674 * Look up the value of the persistent constant with name `cnsName'.
676 * Return nullptr if no such constant exists, or the constant is not
677 * persistent.
679 static const Cell* lookupPersistentCns(const StringData* cnsName);
682 * Look up, or autoload and define, the value of the constant with name
683 * `cnsName' for this request.
685 static tv_rval loadCns(const StringData* cnsName);
688 * Define a constant (either request-local or persistent) with name `cnsName'
689 * and value `value'.
691 * May raise notices or warnings if a constant with the given name is already
692 * defined or if value is invalid.
694 static bool defCns(const StringData* cnsName, const TypedValue* value);
697 * Define a constant with name `cnsName' with a magic callback. The
698 * Cell should be KindOfUninit, with a Native::ConstantCallback in
699 * its m_data.pref.
701 * The canonical examples are STDIN, STDOUT, and STDERR.
703 static bool defNativeConstantCallback(const StringData* cnsName, Cell cell);
705 /////////////////////////////////////////////////////////////////////////////
706 // Type aliases.
708 folly::Range<TypeAlias*> typeAliases();
709 folly::Range<const TypeAlias*> typeAliases() const;
712 * Look up without autoloading a type alias named `name'. Returns nullptr
713 * if one cannot be found.
715 * If the type alias is found and `persistent' is provided, it will be set to
716 * whether or not the TypeAliasReq's RDS handle is persistent.
718 static const TypeAliasReq* lookupTypeAlias(const StringData* name,
719 bool* persistent = nullptr);
722 * Look up or attempt to autoload a type alias named `name'. Returns nullptr
723 * if one cannot be found or autoloaded.
725 * If the type alias is found and `persistent' is provided, it will be set to
726 * whether or not the TypeAliasReq's RDS handle is persistent.
728 static const TypeAliasReq* loadTypeAlias(const StringData* name,
729 bool* persistent = nullptr);
732 * Define the type alias given by `id', binding it to the appropriate
733 * NamedEntity for this request.
735 * returns true iff the bound type alias is persistent.
737 bool defTypeAlias(Id id);
739 /////////////////////////////////////////////////////////////////////////////
740 // File attributes.
742 const UserAttributeMap& fileAttributes() const;
744 /////////////////////////////////////////////////////////////////////////////
745 // Merge.
748 * Merge the Unit if it is not already merged.
750 void merge();
753 * Is it sufficient to merge the Unit, and skip invoking its pseudomain?
755 bool isMergeOnly() const;
758 * Is this Unit empty---i.e., does it define nothing and have no
759 * side-effects?
761 bool isEmpty() const;
764 * Get the return value of the pseudomain, or KindOfUninit if not
765 * known.
767 * @requires: isMergeOnly()
769 const TypedValue* getMainReturn() const;
771 /////////////////////////////////////////////////////////////////////////////
772 // Info arrays. [static]
775 * Generate class info arrays.
777 static Array getClassesInfo();
778 static Array getInterfacesInfo();
779 static Array getTraitsInfo();
782 * Generate function info arrays.
784 static Array getUserFunctions();
785 static Array getSystemFunctions();
787 /////////////////////////////////////////////////////////////////////////////
788 // Pretty printer. [const]
790 struct PrintOpts {
791 PrintOpts()
792 : startOffset(kInvalidOffset)
793 , stopOffset(kInvalidOffset)
794 , showLines(true)
795 , showFuncs(true)
796 , indentSize(1)
799 PrintOpts& range(Offset start, Offset stop) {
800 startOffset = start;
801 stopOffset = stop;
802 return *this;
805 PrintOpts& noLineNumbers() {
806 showLines = false;
807 return *this;
810 PrintOpts& noFuncs() {
811 showFuncs = false;
812 return *this;
815 PrintOpts& indent(int i) {
816 indentSize = i;
817 return *this;
820 Offset startOffset;
821 Offset stopOffset;
822 bool showLines;
823 bool showFuncs;
824 int indentSize;
827 void prettyPrint(std::ostream&, PrintOpts = PrintOpts()) const;
828 std::string toString() const;
830 /////////////////////////////////////////////////////////////////////////////
831 // Other methods.
834 * Is this Unit a compile-time fatal?
836 * A compile-time fatal is encoded as a pseudomain that contains precisely:
838 * String <id>; Fatal;
840 * Decode enough of pseudomain to determine whether it contains a
841 * compile-time fatal, and if so, extract the error message and line number.
843 * Parse-time fatals are a subset of compile-time fatals.
845 bool compileTimeFatal(const StringData*& msg, int& line) const;
846 bool parseFatal(const StringData*& msg, int& line) const;
849 * Get or set whether this Unit is interpret-only.
851 * This is used by the debugger to signal to the JIT that eval'd commands
852 * should not be jitted.
854 bool isInterpretOnly() const;
855 void setInterpretOnly();
858 * Replace the Unit?
860 void* replaceUnit() const;
863 * Does this unit correspond to a file with "<?hh" at the top, irrespective of
864 * EnableHipHopSyntax?
866 bool isHHFile() const;
869 * Should calls from this unit use strict types? (This is always true for HH
870 * units).
872 * With strict types enabled only lossless int->float conversions are allowed
874 bool useStrictTypes() const;
877 * Should calls from this unit to builtins use strict types?
879 * This is true for PHP7 files with declare(strict_types=1), but not for Hack
880 * files or force_hh */
881 bool useStrictTypesForBuiltins() const;
883 UserAttributeMap metaData() const;
885 // Return true, and set the m_serialized flag, iff this Unit hasn't
886 // been serialized yet (see prof-data-serialize.cpp).
887 bool serialize() const {
888 if (m_serialized) return false;
889 const_cast<Unit*>(this)->m_serialized = true;
890 return true;
893 /////////////////////////////////////////////////////////////////////////////
894 // Offset accessors. [static]
896 static constexpr ptrdiff_t bcOff() {
897 return offsetof(Unit, m_bc);
900 /////////////////////////////////////////////////////////////////////////////
901 // Internal methods.
903 private:
904 void initialMerge();
905 template<bool debugger>
906 void mergeImpl(MergeInfo* mi);
907 UnitExtended* getExtended();
908 const UnitExtended* getExtended() const;
909 MergeInfo* mergeInfo() const {
910 return m_mergeInfo.load(std::memory_order_acquire);
913 /////////////////////////////////////////////////////////////////////////////
914 // Data members.
916 // These are organized in reverse order of frequency of use. Do not re-order
917 // without checking perf!
918 private:
919 unsigned char const* m_bc{nullptr};
920 Offset m_bclen{0};
921 LowStringPtr m_filepath{nullptr};
922 std::atomic<MergeInfo*> m_mergeInfo{nullptr};
924 int8_t m_repoId{-1};
926 * m_mergeState is read without a lock, but only written to under
927 * unitInitLock (see unit.cpp).
929 std::atomic<uint8_t> m_mergeState{MergeState::Unmerged};
930 bool m_mergeOnly: 1;
931 bool m_interpretOnly : 1;
932 bool m_isHHFile : 1;
933 bool m_useStrictTypes : 1;
934 bool m_useStrictTypesForBuiltins : 1;
935 bool m_extended : 1;
936 bool m_serialized : 1;
937 bool m_ICE : 1; // was this unit the result of an internal compiler error
938 LowStringPtr m_dirpath{nullptr};
940 TypedValue m_mainReturn;
941 PreClassPtrVec m_preClasses;
942 TypeAliasVec m_typeAliases;
943 CompactVector<RecordPtr> m_records;
945 * Cached the EntryPoint for an unit, since compactMergeInfo() inside of
946 * mergeImpl will drop the original EP.
948 Func* m_cachedEntryPoint{nullptr};
951 * The remaining fields are cold, and arbitrarily ordered.
954 int64_t m_sn{-1}; // Note: could be 32-bit
955 MD5 m_md5;
956 VMFixedVector<const ArrayData*> m_arrays;
957 mutable PseudoMainCacheMap* m_pseudoMainCache{nullptr};
958 mutable LockFreePtrWrapper<VMCompactVector<LineInfo>> m_lineMap;
959 UserAttributeMap m_metaData;
960 UserAttributeMap m_fileAttributes;
963 struct UnitExtended : Unit {
964 friend struct Unit;
965 friend struct UnitEmitter;
967 UnitExtended() { m_extended = true; }
969 NamedEntityPairTable m_namedInfo;
970 ArrayTypeTable m_arrayTypeTable;
971 FuncTable m_funcTable;
974 ///////////////////////////////////////////////////////////////////////////////
977 #define incl_HPHP_VM_UNIT_INL_H_
978 #include "hphp/runtime/vm/unit-inl.h"
979 #undef incl_HPHP_VM_UNIT_INL_H_
981 #endif // incl_HPHP_VM_UNIT_H_