Compute ambient coeffects and write to coeffects local
[hiphop-php.git] / hphp / runtime / vm / func.h
blobe66ba7538d8a9e53752911cbd1681253925f2c56
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 #pragma once
19 #include "hphp/runtime/base/atomic-countable.h"
20 #include "hphp/runtime/base/attr.h"
21 #include "hphp/runtime/base/datatype.h"
22 #include "hphp/runtime/base/rds.h"
23 #include "hphp/runtime/base/tracing.h"
24 #include "hphp/runtime/base/type-string.h"
25 #include "hphp/runtime/base/typed-value.h"
26 #include "hphp/runtime/base/user-attributes.h"
28 #include "hphp/runtime/vm/coeffects.h"
29 #include "hphp/runtime/vm/indexed-string-map.h"
30 #include "hphp/runtime/vm/iter.h"
31 #include "hphp/runtime/vm/reified-generics-info.h"
32 #include "hphp/runtime/vm/type-constraint.h"
33 #include "hphp/runtime/vm/unit.h"
35 #include "hphp/util/fixed-vector.h"
36 #include "hphp/util/low-ptr.h"
38 #include <atomic>
39 #include <utility>
40 #include <vector>
42 namespace HPHP {
43 ///////////////////////////////////////////////////////////////////////////////
45 struct ActRec;
46 struct Class;
47 struct NamedEntity;
48 struct PreClass;
49 struct StringData;
50 struct StructuredLogEntry;
51 template <typename T> struct AtomicLowPtrVector;
54 * Signature for native functions called by the hhvm using the hhvm
55 * calling convention that provides raw access to the ActRec.
57 using ArFunction = TypedValue* (*)(ActRec* ar);
60 * Signature for native functions expecting the platform ABI calling
61 * convention. This must always be casted to a proper signature before
62 * calling, so make something up to prevent accidental mixing with other
63 * function pointer types.
65 struct NativeArgs; // never defined
66 using NativeFunction = void(*)(NativeArgs*);
68 using StaticCoeffectNamesMap = CompactVector<LowStringPtr>;
70 ///////////////////////////////////////////////////////////////////////////////
71 // EH table.
74 * Exception handler table entry.
76 struct EHEnt {
77 Offset m_base;
78 Offset m_past;
79 int m_iterId;
80 int m_parentIndex;
81 Offset m_handler;
82 Offset m_end;
84 EHEnt()
85 : m_base()
86 , m_past()
87 , m_iterId()
88 , m_parentIndex()
89 , m_handler()
90 , m_end()
93 template<class SerDe> void serde(SerDe& sd);
96 template <typename T, size_t Expected, size_t Actual = sizeof(T)>
97 constexpr bool CheckSize() { static_assert(Expected == Actual); return true; };
99 ///////////////////////////////////////////////////////////////////////////////
101 * Metadata about a PHP function or method.
103 * The Func class cannot be safely extended, because variable amounts of memory
104 * associated with the Func are allocated before and after the actual object.
106 * All Funcs are also followed by a variable number of function prologue
107 * pointers. Six are statically allocated as part of the Func object, but more
108 * may follow, depending on the value of getMaxNumPrologues().
110 * +--------------------------------+ Func* address
111 * | Func object |
112 * | |
113 * | prologues at end of Func |
114 * +--------------------------------+ Func* address
115 * | [additional prologues] |
116 * +--------------------------------+ high address
119 struct Func final {
120 friend struct FuncEmitter;
121 friend struct FuncRepoProxy;
123 #ifndef USE_LOWPTR
124 // DO NOT access it directly, instead use Func::getFuncVec()
125 // Exposed in the header file for gdb python macros
126 static AtomicLowPtrVector<const Func> s_funcVec;
127 #endif
128 /////////////////////////////////////////////////////////////////////////////
129 // Types.
132 * Parameter default value info.
134 struct ParamInfo {
135 enum class Flags {
136 InOut, // Is this an `inout' parameter?
137 Variadic, // Is this a `...' parameter?
138 NativeArg, // Does this use a NativeArg?
139 AsVariant, // Native function takes as const Variant&
140 AsTypedValue // Native function takes as TypedValue
143 ParamInfo();
145 bool hasDefaultValue() const;
146 bool hasScalarDefaultValue() const;
147 bool isInOut() const;
148 bool isVariadic() const;
149 bool isNativeArg() const;
150 bool isTakenAsVariant() const;
151 bool isTakenAsTypedValue() const;
152 void setFlag(Flags flag);
154 template<class SerDe> void serde(SerDe& sd);
156 // Typehint for builtins.
157 MaybeDataType builtinType{folly::none};
158 // Flags as defined by the Flags enum.
159 uint8_t flags{0};
160 // DV initializer funclet offset.
161 Offset funcletOff{kInvalidOffset};
162 // Set to Uninit if there is no DV, or if there's a nonscalar DV.
163 TypedValue defaultValue;
164 // Eval-able PHP code.
165 LowStringPtr phpCode{nullptr};
166 // User-annotated type.
167 LowStringPtr userType{nullptr};
168 // offset of dvi funclet from cti section base.
169 Offset ctiFunclet{kInvalidOffset};
170 TypeConstraint typeConstraint;
171 UserAttributeMap userAttributes;
174 using ParamInfoVec = VMFixedVector<ParamInfo>;
175 using EHEntVec = VMFixedVector<EHEnt>;
176 using UpperBoundVec = VMCompactVector<TypeConstraint>;
177 using ParamUBMap = vm_flat_map<uint32_t, UpperBoundVec>;
178 using CoeffectRules = VMFixedVector<CoeffectRule>;
180 /////////////////////////////////////////////////////////////////////////////
181 // Creation and destruction.
183 Func(Unit& unit, const StringData* name, Attr attrs);
184 Func(Unit& unit, const StringData* name, Attr attrs,
185 const StringData *methCallerCls, const StringData *methCallerMeth);
186 ~Func();
189 * Allocate memory for a function, including the variable number of prologues
190 * that follow.
192 static void* allocFuncMem(int numParams);
195 * Destruct and free a Func*.
197 static void destroy(Func* func);
200 * Address of the end of the Func's variable-length memory allocation.
202 const void* mallocEnd() const;
205 * Duplicate this function.
207 * Funcs are cloned for a number of reasons---most notably, methods on
208 * Classes are cloned from the methods defined on their respective
209 * PreClasses.
211 * We also clone methods from traits when we transclude the trait in its user
212 * Classes in repo mode.
214 Func* clone(Class* cls, const StringData* name = nullptr) const;
217 * Reset this function's cls and attrs.
219 * Used to change the Class scope of a closure method.
221 void rescope(Class* ctx);
224 * Free up a PreFunc for re-use as a cloned Func.
226 * @requires: isPreFunc()
228 void freeClone();
231 * Verify that a Func's data is coherent.
233 * FIXME: Currently this method does almost nothing.
235 bool validate() const;
237 /////////////////////////////////////////////////////////////////////////////
238 // FuncId manipulation.
241 * Get this function's ID.
243 * We allocate a unique 32-bit ID to almost all Funcs. The Func* can be
244 * retrieved by using this ID as an index into a global vector. This lets
245 * the JIT store references to Funcs more compactly.
247 * Funcs which do not represent actual runtime functions (namely, Funcs on
248 * PreClasses) are not assigned an ID.
250 FuncId getFuncId() const;
253 * Reserve the next available FuncId for `this', and add `this' to the
254 * function table.
256 void setNewFuncId();
259 * The max FuncId num.
261 static FuncId::Int maxFuncIdNum();
264 * Lookup a Func* by its ID.
266 static const Func* fromFuncId(FuncId id);
269 * Whether `id' actually keys a Func*.
271 static bool isFuncIdValid(FuncId id);
273 /////////////////////////////////////////////////////////////////////////////
274 // Basic info. [const]
277 * The Unit the function is defined in.
279 Unit* unit() const;
282 * The various Class contexts of a method.
284 * cls(): The Class context of the method. This is usually the Class
285 * which implements the method, but for closure methods (i.e.,
286 * the __invoke() method on a closure object), it is instead the
287 * Class that the Closure object is scoped to.
289 * preClass(): The PreClass of the method's cls(). For closures, this still
290 * corresponds to the Closure subclass, rather than to the
291 * scoped Class.
293 * When isFromTrait() is true, preClass() refers to different
294 * entities in repo vs. non-repo mode. In repo mode, traits are
295 * flattened ahead of time, and preClass() refers to the class
296 * which imported the trait. In non-repo mode, trait methods
297 * are cloned into trait users, but preClass() will still refer
298 * to the trait which defined the method.
300 * baseCls(): The first Class in the inheritance hierarchy which declares
301 * this method.
303 * implCls(): The Class which implements the method. Just like cls(), but
304 * ignores closure scope (so it returns baseCls() for closures).
306 * It is possible for cls() to be nullptr on a method---this occurs when a
307 * closure method is scoped to a null class context (e.g., if the closure is
308 * created in a non-method function scope). In this case, only the `cls' is
309 * changed; the `preClass' and `baseCls' will continue to refer to the
310 * PreClass and Class of the closure object.
312 * The converse also occurs---a function can have a `cls' (and `baseCls')
313 * without being a method. This happens when a pseudomain is included from a
314 * class context.
316 * Consequently, none of these methods should be used to test whether the
317 * function is a method; for that purpose, see isMethod().
319 Class* cls() const;
320 PreClass* preClass() const;
321 bool hasBaseCls() const;
322 Class* baseCls() const;
323 Class* implCls() const;
325 int sn() const;
328 * The function's short name (e.g., foo).
330 const StringData* name() const;
331 String nameWithClosureName() const;
332 StrNR nameStr() const;
335 * A hash for this func that will remain constant across process restarts.
337 size_t stableHash() const;
340 * The function's fully class-qualified, name (e.g., C::foo).
342 const StringData* fullName() const;
343 String fullNameWithClosureName() const;
344 StrNR fullNameStr() const;
347 * The function's named entity. Only valid for non-methods.
349 * @requires: shared()->m_preClass == nullptr
351 NamedEntity* getNamedEntity();
352 const NamedEntity* getNamedEntity() const;
355 * meth_caller
357 const StringData* methCallerClsName() const;
358 const StringData* methCallerMethName() const;
360 /////////////////////////////////////////////////////////////////////////////
361 // File info. [const]
364 * The filename where the function was originally defined.
366 * In repo mode, we flatten traits into the classes they're used in, so we
367 * need this to track the original file for backtraces and errors.
369 const StringData* originalFilename() const;
372 * The original filename if it is defined, the unit's filename otherwise.
374 const StringData* filename() const;
377 * Start and end line of the function.
379 * It'd be nice if these were called lineStart and lineEnd or something, but
380 * we're not allowed to have nice things.
382 int line1() const;
383 int line2() const;
386 * The system- or user-defined doc comment accompanying the function.
388 const StringData* docComment() const;
390 /////////////////////////////////////////////////////////////////////////////
391 // Bytecode. [const]
394 * Get the function's main entrypoint.
396 PC entry() const;
397 Offset bclen() const;
399 PC loadBytecode();
402 * Whether a given PC or Offset (from the beginning of the unit) is within
403 * the function's bytecode stream.
405 bool contains(PC pc) const;
406 bool contains(Offset offset) const;
409 * Convert between PC and Offset from entry().
411 PC at(Offset off) const;
412 Offset offsetOf(PC pc) const;
415 * Get the Op at `instrOffset'.
417 Op getOp(Offset instrOffset) const;
420 * Is there a main or default value entrypoint at the given offset?
422 bool isEntry(Offset offset) const;
423 bool isDVEntry(Offset offset) const;
426 * Number of params required when entering at the given offset.
428 * Return -1 if an invalid offset is provided.
430 int getEntryNumParams(Offset offset) const;
431 int getDVEntryNumParams(Offset offset) const;
434 * Get the correct entrypoint (whether the main entry or a DV funclet) when
435 * `numArgsPassed' arguments are passed to the function.
437 * This is the DV funclet offset of the numArgsPassed-th parameter, or the
438 * next parameter that has a DV funclet.
440 Offset getEntryForNumArgs(int numArgsPassed) const;
442 // CTI entry points
443 Offset ctiEntry() const;
444 void setCtiFunclet(int i, Offset);
445 void setCtiEntry(Offset entry, uint32_t size);
447 /////////////////////////////////////////////////////////////////////////////
448 // Return type. [const]
451 * CPP builtin's return type. Returns folly::none if function is not a CPP
452 * builtin.
454 * There are a number of caveats regarding this value:
456 * - If the return type is folly::none, the return is a Variant.
458 * - If the return type is a string, array-like, object, ref, or resource
459 * type, null may also be returned.
461 * - Likewise, if the function is marked AttrParamCoerceModeNull, null
462 * might also be returned.
464 * - This list of caveats may be incorrect and/or incomplete.
466 MaybeDataType hniReturnType() const;
469 * Return type inferred by HHBBC's static analysis. TGen if no data is
470 * available.
472 RepoAuthType repoReturnType() const;
475 * For async functions, the statically inferred inner type of the returned
476 * WH based on HHBBC's analysis.
478 RepoAuthType repoAwaitedReturnType() const;
481 * For builtins, whether the return value is returned in registers (as
482 * opposed to indirect return, via tvBuiltinReturn).
484 * Not well-defined if this function is not a builtin.
486 bool isReturnByValue() const;
489 * The TypeConstraint of the return.
491 const TypeConstraint& returnTypeConstraint() const;
494 * The user-annotated Hack return type.
496 const StringData* returnUserType() const;
498 bool hasReturnWithMultiUBs() const;
499 const UpperBoundVec& returnUBs() const;
501 /////////////////////////////////////////////////////////////////////////////
502 // Parameters. [const]
505 * Const reference to the parameter info table.
507 * ParamInfo objects pulled from the table will also be const.
509 const ParamInfoVec& params() const;
512 * Number of parameters (including `...') accepted by the function.
514 uint32_t numParams() const;
517 * Number of parameters, not including `...', accepted by the function.
519 uint32_t numNonVariadicParams() const;
522 * Number of required parameters, i.e. all arguments starting from
523 * the returned position have default value.
525 uint32_t numRequiredParams() const;
528 * Whether the function is declared with a `...' parameter.
530 bool hasVariadicCaptureParam() const;
533 * Whether the arg-th parameter was declared inout.
535 bool isInOut(int32_t arg) const;
538 * Whether any of the parameters to this function are inout parameters.
540 bool takesInOutParams() const;
543 * Returns the number of inout parameters taken by func.
545 uint32_t numInOutParams() const;
548 * Returns the number of inout parameters for the given number of
549 * arguments.
551 uint32_t numInOutParamsForArgs(int32_t numArgs) const;
553 bool hasParamsWithMultiUBs() const;
555 const ParamUBMap& paramUBs() const;
557 /////////////////////////////////////////////////////////////////////////////
558 // Locals, iterators, and stack. [const]
561 * Number of locals, iterators, or named locals.
563 int numLocals() const;
564 int numIterators() const;
565 Id numNamedLocals() const;
568 * Find the integral ID assigned to a named local.
570 Id lookupVarId(const StringData* name) const;
573 * Returns the ID of coeffects and reified generics locals.
574 * Requires hasCoeffectRules() and hasReifiedGenerics() respectively
576 Id coeffectsLocalId() const;
577 Id reifiedGenericsLocalId() const;
580 * Find the name of the local with the given ID.
582 const StringData* localVarName(Id id) const;
585 * Array of named locals. Includes parameter names.
586 * May contain nullptrs for unammed locals that mixed in with named ones.
588 * Should not be indexed past numNamedLocals() - 1.
590 LowStringPtr const* localNames() const;
593 * Number of stack slots used by locals and iterator cells.
595 int numSlotsInFrame() const;
598 * Access to the maximum stack cells this function can use. This is
599 * used for stack overflow checks.
601 * The maximum cells for a function includes all its locals, all cells
602 * for its iterators, and all temporary eval stack slots. It does not
603 * include its own ActRec, because whoever called it must have(+) included
604 * the stack slot space reserved for this ActRec. The reason it must still
605 * count its parameter locals is that the caller may or may not pass any of
606 * the parameters, regardless of how many are declared.
608 * + Except in a re-entry situation. That must be handled
609 * specially in bytecode.cpp.
611 int maxStackCells() const;
614 * Checks if $this belong to a class that is not a subclass of cls().
616 bool hasForeignThis() const;
618 void setHasForeignThis(bool);
620 void registerInDataMap();
621 void deregisterInDataMap();
623 /////////////////////////////////////////////////////////////////////////////
624 // Definition context. [const]
627 * Is this function a method defined on a class?
629 * Note that trait methods may not satisfy isMethod().
631 bool isMethod() const;
634 * Was this function imported from a trait?
636 * Note that this returns false for a trait method in the trait it was
637 * originally declared.
639 bool isFromTrait() const;
642 * Is this function declared with `public', `static', or `abstract'?
644 bool isPublic() const;
645 bool isStatic() const;
646 bool isAbstract() const;
649 * Whether a function is called non-statically. Generally this means
650 * isStatic(), but eg static closures are still called with a valid
651 * this pointer.
653 bool isStaticInPrologue() const;
656 * Whether a method is guaranteed to have a valid this in the body.
657 * A method which is !isStatic() || isClosureBody() is guaranteed to
658 * be called with a valid this, but closures swap out the closure
659 * object for the closure context in the prologue, so may not have
660 * a this in the body.
662 bool hasThisInBody() const;
665 * Does this function have the __NoContext attribute?
667 bool hasNoContextAttr() const;
670 * Is this Func owned by a PreClass?
672 * A PreFunc may be "adopted" by a Class when clone() is called, but only the
673 * owning PreClass is allowed to free it.
675 bool isPreFunc() const;
678 * Is this func a memoization wrapper?
680 bool isMemoizeWrapper() const;
683 * Is this func a memoization wrapper with LSB parameter set?
685 bool isMemoizeWrapperLSB() const;
688 * Is this string the name of a memoize implementation.
690 static bool isMemoizeImplName(const StringData*);
693 * Is this function a memoization implementation.
695 bool isMemoizeImpl() const;
698 * Assuming this func is a memoization wrapper, the name of the function it is
699 * wrapping.
701 * Pre: isMemoizeWrapper()
703 const StringData* memoizeImplName() const;
706 * Given the name of a memoization wrapper function, return the generated name
707 * of the function it wraps. This is static so it can be used in contexts
708 * where the actual Func* is not available.
710 static const StringData* genMemoizeImplName(const StringData*);
713 * Given a meth_caller, return the class name or method name
715 static std::pair<const StringData*, const StringData*> getMethCallerNames(
716 const StringData* name);
718 /////////////////////////////////////////////////////////////////////////////
719 // Builtins. [const]
722 * Is the function a builtin, whether PHP or C++?
724 bool isBuiltin() const;
727 * Is this function a C++ builtin (ie HNI function)?.
729 * @implies: isBuiltin()
731 bool isCPPBuiltin() const;
734 * The function returned by arFuncPtr() takes an ActRec*, unpacks it,
735 * and usually dispatches to a nativeFuncPtr() with a specific signature.
737 * All C++ builtins have an ArFunction, with no exceptions.
739 * Most HNI functions share a single ArFunction, which performs
740 * unpacking and dispatch. The exception is HNI functions declared
741 * with NeedsActRec, which do not have NativeFunctions, but have unique
742 * ArFunctions which do all their work.
744 ArFunction arFuncPtr() const;
747 * The nativeFuncPtr is a type-punned function pointer to the unerlying
748 * function which takes the actual argument types, and does the actual work.
750 * These are the functions with names prefixed by f_ or t_.
752 * All C++ builtins have NativeFunctions, with the ironic exception of HNI
753 * functions declared with NeedsActRec.
755 NativeFunction nativeFuncPtr() const;
757 /////////////////////////////////////////////////////////////////////////////
758 // Closures. [const]
761 * Is this function the body (i.e., __invoke() method) of a Closure object?
763 * (All PHP anonymous functions are Closure objects.)
765 bool isClosureBody() const;
767 /////////////////////////////////////////////////////////////////////////////
768 // Resumables. [const]
771 * Is this function asynchronous? (May also be a generator.)
773 bool isAsync() const;
776 * Is this function a generator? (May also be async.)
778 bool isGenerator() const;
781 * Is this function a generator which yields both key and value?
783 * @implies: isGenerator()
785 bool isPairGenerator() const;
788 * @returns: !isGenerator() && isAsync()
790 bool isAsyncFunction() const;
793 * @returns: isGenerator() && !isAsync()
795 bool isNonAsyncGenerator() const;
798 * @returns: isGenerator() && isAsync()
800 bool isAsyncGenerator() const;
803 * Is this a resumable function?
805 * @returns: isGenerator() || isAsync()
807 bool isResumable() const;
809 /////////////////////////////////////////////////////////////////////////////
810 // Coeffects. [const]
813 * Names of the static coeffects on the function
814 * Used for reflection
816 StaticCoeffectNamesMap staticCoeffectNames() const;
819 * Is this the version of the function body with reactivity disabled via
820 * if (Rx\IS_ENABLED) ?
822 bool isRxDisabled() const;
825 * Does this function have coeffect rules?
827 bool hasCoeffectRules() const;
830 * List of rules for enforcing coeffects
832 const CoeffectRules& getCoeffectRules() const;
834 /////////////////////////////////////////////////////////////////////////////
835 // Methods. [const]
838 * Index of this function in the method table of its Class.
840 Slot methodSlot() const;
843 * Whether this function has a private implementation on a parent class.
845 bool hasPrivateAncestor() const;
847 /////////////////////////////////////////////////////////////////////////////
848 // Magic methods. [const]
851 * Is this a compiler-generated function?
853 * This includes special methods like 86pinit and 86sinit as well
854 * as all closures.
856 bool isGenerated() const;
859 * Is `name' the name of a special initializer function?
861 static bool isSpecial(const StringData* name);
863 /////////////////////////////////////////////////////////////////////////////
864 // Persistence. [const]
867 * Whether this function is uniquely named across the codebase.
869 * It's legal in PHP to define multiple functions in different pseudomains
870 * with the same name, so long as both are not required in the same request.
872 * Note that if EvalJitEnableRenameFunction is set, no Func is unique.
874 bool isUnique() const;
877 * Whether we can load this function once and persist it across requests.
879 * Persistence is possible when a Func is defined in a pseudomain that has no
880 * side-effects (except other persistent definitions).
882 * @implies: isUnique()
884 bool isPersistent() const;
886 bool isInterceptable() const;
889 * Given that func would be called when func->name() is invoked on cls,
890 * determine if it would also be called when invoked on any descendant
891 * of cls.
893 bool isImmutableFrom(const Class* cls) const;
895 /////////////////////////////////////////////////////////////////////////////
896 // Other attributes. [const]
899 * Get the system and coeffect attributes of the function.
901 Attr attrs() const;
902 StaticCoeffects staticCoeffects() const;
905 * Get the user-declared attributes of the function.
907 const UserAttributeMap& userAttributes() const;
910 * Whether to ignore this function's frame in backtraces.
912 bool isNoInjection() const;
915 * Whether this function's frame should be skipped when searching for context
916 * (e.g., array_map evaluates its callback in the context of its caller).
918 bool isSkipFrame() const;
921 * Whether this function's frame should be skipped with searching for a
922 * context for array provenance
924 bool isProvenanceSkipFrame() const;
927 * Whether the function can be constant-folded at callsites where it is
928 * passed constant arguments.
930 bool isFoldable() const;
933 * Supports async eager return optimization?
935 bool supportsAsyncEagerReturn() const;
938 * Is this func allowed to be called dynamically?
940 bool isDynamicallyCallable() const;
943 * If this function is called dynamically should we raise sampled warnings?
945 * N.B. When errors are enabled for dynamic calls this overrides that behavior
946 * for functions which specify it.
948 folly::Optional<int64_t> dynCallSampleRate() const;
951 * Is this a meth_caller func?
953 bool isMethCaller() const;
956 * Indicates that a function does not make any explicit calls to other PHP
957 * functions. It may still call other user-level functions via re-entry
958 * (e.g., for autoload), and it may make calls to builtins using FCallBuiltin.
960 bool isPhpLeafFn() const;
963 * Does this function has reified generics?
965 bool hasReifiedGenerics() const;
968 * Returns a ReifiedGenericsInfo containing how many generics this func has,
969 * indices of its reified generics, and which ones are soft reified
971 const ReifiedGenericsInfo& getReifiedGenericsInfo() const;
973 /////////////////////////////////////////////////////////////////////////////
974 // Unit table entries. [const]
976 const EHEntVec& ehtab() const;
979 * Find the first EHEnt that covers a given offset, or return null.
981 const EHEnt* findEH(Offset o) const;
984 * Same as non-static findEH(), but takes as an operand any ehtab-like
985 * container.
987 template<class Container>
988 static const typename Container::value_type*
989 findEH(const Container& ehtab, Offset o);
991 bool shouldSampleJit() const { return m_shouldSampleJit; }
993 /////////////////////////////////////////////////////////////////////////////
994 // JIT data.
997 * Get the RDS handle for the function with this function's name.
999 * We can burn these into the TC even when functions are not persistent,
1000 * since only a single name-to-function mapping will exist per request.
1002 rds::Handle funcHandle() const;
1005 * Get, set and reset the function body code pointer.
1007 unsigned char* getFuncBody() const;
1008 void setFuncBody(unsigned char* fb);
1009 void resetFuncBody();
1012 * Get and set the `index'-th function prologue.
1014 uint8_t* getPrologue(int index) const;
1015 void setPrologue(int index, unsigned char* tca);
1018 * Number of prologues allocated for the function.
1020 int numPrologues() const;
1023 * Reset a specific prologue, or all prologues.
1025 void resetPrologue(int numParams);
1027 /////////////////////////////////////////////////////////////////////////////
1028 // Pretty printer. [const]
1030 struct PrintOpts {
1031 PrintOpts()
1032 : name(true)
1033 , metadata(true)
1034 , startOffset(0)
1035 , stopOffset(kInvalidOffset)
1036 , showLines(true)
1037 , indentSize(1)
1040 PrintOpts& noName() {
1041 name = false;
1042 return *this;
1045 PrintOpts& noMetadata() {
1046 metadata = false;
1047 return *this;
1050 PrintOpts& noBytecode() {
1051 startOffset = kInvalidOffset;
1052 stopOffset = kInvalidOffset;
1053 return *this;
1056 PrintOpts& range(Offset start, Offset stop) {
1057 startOffset = start;
1058 stopOffset = stop;
1059 return *this;
1062 PrintOpts& noLineNumbers() {
1063 showLines = false;
1064 return *this;
1067 PrintOpts& indent(int i) {
1068 indentSize = i;
1069 return *this;
1072 bool name;
1073 bool metadata;
1074 Offset startOffset;
1075 Offset stopOffset;
1076 bool showLines;
1077 int indentSize;
1080 void prettyPrint(std::ostream& out, const PrintOpts& = PrintOpts()) const;
1082 void prettyPrintInstruction(std::ostream& out, Offset offset) const;
1085 * Print function attributes to out.
1087 static void print_attrs(std::ostream& out, Attr attrs);
1088 static void print_attrs(std::ostream& out, StaticCoeffects attrs);
1091 /////////////////////////////////////////////////////////////////////////////
1092 // Other methods.
1094 // You should avoid adding methods to this section. If the logic you're
1095 // implementing is specific to a particular subsystem, define it as a helper
1096 // there instead.
1098 // If you absolutely must add more methods to Func here, just follow these
1099 // simple guidelines:
1101 // (1) Don't add more methods to Func here.
1104 * Intercept hook flag.
1106 int8_t& maybeIntercepted() const;
1108 /////////////////////////////////////////////////////////////////////////////
1109 // Public setters.
1111 // TODO(#4504609): These setters are only used by Class at Class creation
1112 // time. We should refactor the creation path into a separate friend module
1113 // to avoid this garbage.
1115 // Having public setters here should be avoided, so try not to add any.
1117 void setAttrs(Attr attrs);
1118 void setStaticCoeffects(StaticCoeffects attrs);
1119 void setBaseCls(Class* baseCls);
1120 void setFuncHandle(rds::Link<LowPtr<Func>, rds::Mode::NonLocal> l);
1121 void setHasPrivateAncestor(bool b);
1122 void setMethodSlot(Slot s);
1123 void setGenerated(bool b);
1125 // Return true, and set the m_serialized flag, iff this Func hasn't
1126 // been serialized yet (see prof-data-serialize.cpp).
1127 bool serialize() const;
1129 // Returns true if this function has already been serialized.
1130 bool wasSerialized() const { return m_serialized; }
1132 /////////////////////////////////////////////////////////////////////////////
1133 // Offset accessors. [static]
1135 #define OFF(f) \
1136 static constexpr ptrdiff_t f##Off() { \
1137 return offsetof(Func, m_##f); \
1139 OFF(attrs)
1140 OFF(staticCoeffects)
1141 OFF(name)
1142 OFF(maxStackCells)
1143 OFF(maybeIntercepted)
1144 OFF(paramCounts)
1145 OFF(prologueTable)
1146 OFF(inoutBitVal)
1147 OFF(shared)
1148 OFF(unit)
1149 OFF(methCallerMethName)
1150 #undef OFF
1152 static constexpr ptrdiff_t clsOff() {
1153 return offsetof(Func, m_u);
1156 static constexpr ptrdiff_t methCallerClsNameOff() {
1157 return offsetof(Func, m_u);
1160 static constexpr ptrdiff_t sharedInOutBitPtrOff() {
1161 return offsetof(SharedData, m_inoutBitPtr);
1164 static constexpr ptrdiff_t sharedAllFlags() {
1165 return offsetof(SharedData, m_allFlags);
1168 static uint32_t reifiedGenericsMask() {
1169 ExtendedSharedData::Flags mask;
1170 mask.m_allFlags = 0;
1171 mask.m_hasReifiedGenerics = true;
1172 return mask.m_allFlags;
1175 /////////////////////////////////////////////////////////////////////////////
1176 // Lookup [static]
1179 * Define `func' for this request by initializing its RDS handle.
1181 static void def(Func* func, bool debugger);
1184 * Look up the defined Func in this request with name `name', or with the name
1185 * mapped to the NamedEntity `ne'.
1187 * Return nullptr if the function is not yet defined in this request.
1189 static Func* lookup(const NamedEntity* ne);
1190 static Func* lookup(const StringData* name);
1193 * Look up, or autoload and define, the Func in this request with name `name',
1194 * or with the name mapped to the NamedEntity `ne'.
1196 * @requires: NamedEntity::get(name) == ne
1198 static Func* load(const NamedEntity* ne, const StringData* name);
1199 static Func* load(const StringData* name);
1202 * bind (or rebind) a func to the NamedEntity corresponding to its
1203 * name.
1205 static void bind(Func* func);
1208 * Lookup the builtin in this request with name `name', or nullptr if none
1209 * exists. This does not access RDS so it is safe to use from within the
1210 * compiler. Note that does not mean imply that the name binding for the
1211 * builtin is immutable. The builtin could be renamed or intercepted.
1213 static Func* lookupBuiltin(const StringData* name);
1215 /////////////////////////////////////////////////////////////////////////////
1216 // SharedData.
1218 private:
1219 using NamedLocalsMap = IndexedStringMap<LowStringPtr, true, Id>;
1221 // Some 16-bit values in SharedData are stored as small deltas if they fit
1222 // under this limit. If not, they're set to the limit value and an
1223 // ExtendedSharedData will be allocated for the full-width field.
1224 static constexpr auto kSmallDeltaLimit = uint16_t(-1);
1227 * Properties shared by all clones of a Func.
1229 struct SharedData : AtomicCountable {
1230 SharedData(unsigned char const* bc, Offset bclen, PreClass* preClass,
1231 int sn, int line1, int line2, bool isPhpLeafFn,
1232 const StringData* docComment);
1233 ~SharedData();
1236 * Interface for AtomicCountable.
1238 void atomicRelease();
1240 Offset bclen() const;
1243 * Data fields are packed to minimize size. Try not to add anything new
1244 * here or reorder anything.
1246 // (There's a 32-bit integer in the AtomicCountable base class here.)
1247 std::atomic<unsigned char const*> m_bc{nullptr};
1248 PreClass* m_preClass;
1249 int m_line1;
1250 LowStringPtr m_docComment;
1251 // Bits 64 and up of the inout-ness guards (the first 64 bits are in
1252 // Func::m_inoutBitVal for faster access).
1253 uint64_t* m_inoutBitPtr;
1254 ParamInfoVec m_params;
1255 NamedLocalsMap m_localNames;
1256 EHEntVec m_ehtab;
1257 StaticCoeffectNamesMap m_staticCoeffectNames;
1260 * Up to 16 bits.
1262 union Flags {
1263 struct {
1264 bool m_isClosureBody : true;
1265 bool m_isAsync : true;
1266 bool m_isGenerator : true;
1267 bool m_isPairGenerator : true;
1268 bool m_isGenerated : true;
1269 bool m_hasExtendedSharedData : true;
1270 bool m_returnByValue : true; // only for builtins
1271 bool m_isMemoizeWrapper : true;
1272 bool m_isMemoizeWrapperLSB : true;
1273 bool m_isPhpLeafFn : true;
1274 bool m_hasReifiedGenerics : true;
1275 bool m_isRxDisabled : true;
1276 bool m_hasParamsWithMultiUBs : true;
1277 bool m_hasReturnWithMultiUBs : true;
1278 bool m_hasCoeffectRules : true;
1280 uint16_t m_allFlags;
1282 static_assert(sizeof(Flags) == sizeof(uint16_t));
1284 Flags m_allFlags;
1286 uint16_t m_sn;
1288 LowStringPtr m_retUserType;
1289 UserAttributeMap m_userAttributes;
1290 TypeConstraint m_retTypeConstraint; // NB: sizeof(TypeConstraint) == 12
1291 LowStringPtr m_originalFilename;
1292 RepoAuthType m_repoReturnType;
1293 RepoAuthType m_repoAwaitedReturnType;
1296 * The `line2' are likely to be small, particularly relative to m_line1,
1297 * so we encode each as a 16-bit difference.
1299 * If the delta doesn't fit, we need to have an ExtendedSharedData to hold
1300 * the real values---in that case, the field here that overflowed is set to
1301 * kSmallDeltaLimit and the corresponding field in ExtendedSharedData will
1302 * be valid.
1304 uint16_t m_line2Delta;
1307 * bclen is likely to be small. So we encode each as a 16-bit value
1309 * If the value doesn't fit, we need to have an ExtendedSharedData to hold
1310 * the real values---in that case, the field here that overflowed is set to
1311 * kSmallDeltaLimit and the corresponding field in ExtendedSharedData will
1312 * be valid.
1314 uint16_t m_bclenSmall;
1316 std::atomic<Offset> m_cti_base; // relative to CodeCache cti section
1317 uint32_t m_cti_size; // size of cti code
1318 uint16_t m_numLocals;
1319 uint16_t m_numIterators;
1320 mutable LockFreePtrWrapper<VMCompactVector<LineInfo>> m_lineMap;
1322 static_assert(CheckSize<SharedData, use_lowptr ? 152 : 184>(), "");
1325 * If this Func represents a native function or is exceptionally large
1326 * (line count or bytecode size), it requires extra information that most
1327 * Funcs don't need, so it's SharedData is actually one of these extended
1328 * SharedDatas.
1330 struct ExtendedSharedData : SharedData {
1331 template<class... Args>
1332 explicit ExtendedSharedData(Args&&... args)
1333 : SharedData(std::forward<Args>(args)...)
1335 m_allFlags.m_hasExtendedSharedData = true;
1337 ExtendedSharedData(const ExtendedSharedData&) = delete;
1338 ExtendedSharedData(ExtendedSharedData&&) = delete;
1340 MaybeDataType m_hniReturnType;
1341 ArFunction m_arFuncPtr;
1342 NativeFunction m_nativeFuncPtr;
1343 ReifiedGenericsInfo m_reifiedGenericsInfo;
1344 ParamUBMap m_paramUBs;
1345 UpperBoundVec m_returnUBs;
1346 CoeffectRules m_coeffectRules;
1347 Offset m_bclen; // Only read if SharedData::m_bclen is kSmallDeltaLimit
1348 int m_line2; // Only read if SharedData::m_line2 is kSmallDeltaLimit
1349 int m_sn; // Only read if SharedData::m_sn is kSmallDeltaLimit
1350 int64_t m_dynCallSampleRate;
1352 static_assert(CheckSize<ExtendedSharedData, use_lowptr ? 280 : 312>(), "");
1355 * SharedData accessors for internal use.
1357 const SharedData* shared() const { return m_shared.get(); }
1358 SharedData* shared() { return m_shared.get(); }
1361 * Returns ExtendedSharedData if we have one, or else a nullptr.
1363 const ExtendedSharedData* extShared() const;
1364 ExtendedSharedData* extShared();
1367 * We store 'detailed' line number information on a table on the side, because
1368 * in production modes for HHVM it's generally not useful (which keeps Func
1369 * smaller in that case)---this stuff is only used for the debugger, where we
1370 * can afford the lookup here. The normal Func m_lineMap is capable of
1371 * producing enough line number information for things needed in production
1372 * modes (backtraces, warnings, etc).
1375 struct ExtendedLineInfo {
1376 SourceLocTable sourceLocTable;
1379 * Map from source lines to a collection of all the bytecode ranges the line
1380 * encompasses.
1382 * The value type of the map is a list of offset ranges, so a single line
1383 * with several sub-statements may correspond to the bytecodes of all of the
1384 * sub-statements.
1386 * May not be initialized. Lookups need to check if it's empty() and if so
1387 * compute it from sourceLocTable.
1389 LineToOffsetRangeVecMap lineToOffsetRange;
1392 using ExtendedLineInfoCache = tbb::concurrent_hash_map<
1393 const SharedData*,
1394 ExtendedLineInfo,
1395 pointer_hash<SharedData>
1397 using LineTableStash = tbb::concurrent_hash_map<
1398 const SharedData*,
1399 LineTable,
1400 pointer_hash<SharedData>
1403 static ExtendedLineInfoCache s_extendedLineInfo;
1405 static LineTableStash s_lineTables;
1407 /////////////////////////////////////////////////////////////////////////////
1408 // Internal methods.
1410 // These are all used at emit-time, and should be outsourced to FuncEmitter.
1412 private:
1413 Func(const Func&) = default; // used for clone()
1414 Func& operator=(const Func&) = delete;
1415 void init(int numParams);
1416 void initPrologues(int numParams);
1417 void setFullName(int numParams);
1418 void appendParam(bool ref, const ParamInfo& info,
1419 std::vector<ParamInfo>& pBuilder);
1420 void finishedEmittingParams(std::vector<ParamInfo>& pBuilder);
1421 void setNamedEntity(const NamedEntity*);
1423 /////////////////////////////////////////////////////////////////////////////
1424 // Internal types.
1426 struct ClonedFlag {
1427 ClonedFlag() {}
1428 ClonedFlag(const ClonedFlag&) {}
1429 ClonedFlag& operator=(const ClonedFlag&) = delete;
1431 std::atomic_flag flag = ATOMIC_FLAG_INIT;
1435 * Wrapper around std::atomic<Attr> that pretends like it's not atomic.
1437 * Func::m_attrs is only accessed by multiple threads in the closure scoping
1438 * process for Closure classes, which is synchronized in Class::rescope().
1439 * This wrapper is just to make m_attrs copy-constructible, and there should
1440 * never be a race when copying.
1442 struct AtomicAttr {
1443 AtomicAttr() {}
1444 explicit AtomicAttr(Attr attrs) : m_attrs{attrs} {}
1446 AtomicAttr(const AtomicAttr& o)
1447 : m_attrs{o.m_attrs.load(std::memory_order_relaxed)}
1450 AtomicAttr& operator=(Attr attrs) {
1451 m_attrs.store(attrs, std::memory_order_relaxed);
1452 return *this;
1455 /* implicit */ operator Attr() const {
1456 return m_attrs.load(std::memory_order_relaxed);
1459 private:
1460 std::atomic<Attr> m_attrs;
1463 public:
1464 #ifdef USE_LOWPTR
1465 using low_storage_t = uint32_t;
1466 #else
1467 using low_storage_t = uintptr_t;
1468 #endif
1470 private:
1472 * Lowptr wrapper around std::atomic<Union> for Class* or StringData*
1474 struct UnionWrapper {
1475 union U {
1476 low_storage_t m_cls;
1477 low_storage_t m_methCallerClsName;
1479 std::atomic<U> m_u;
1481 // constructors
1482 explicit UnionWrapper(Class *cls)
1483 : m_u([](Class *cls){
1484 U u;
1485 u.m_cls = to_low(cls);
1486 return u; }(cls)) {}
1487 explicit UnionWrapper(const StringData *name)
1488 : m_u([](const StringData *n){
1489 U u;
1490 u.m_methCallerClsName = to_low(n, kMethCallerBit);
1491 return u; }(name)) {}
1492 /* implicit */ UnionWrapper(std::nullptr_t /*px*/)
1493 : m_u([](){
1494 U u;
1495 u.m_cls = 0;
1496 return u; }()) {}
1497 UnionWrapper(const UnionWrapper& r) :
1498 m_u(r.m_u.load()) {
1501 // Assignments
1502 UnionWrapper& operator=(UnionWrapper r) {
1503 m_u.store(r.m_u, std::memory_order_relaxed);
1504 return *this;
1507 // setter & getter
1508 void setCls(Class *cls) {
1509 U u;
1510 u.m_cls = to_low(cls);
1511 m_u.store(u, std::memory_order_relaxed);
1513 Class* cls() const {
1514 auto cls = m_u.load(std::memory_order_relaxed).m_cls;
1515 assertx(!(cls & kMethCallerBit));
1516 return reinterpret_cast<Class*>(cls);
1518 StringData* name() const {
1519 auto n = m_u.load(std::memory_order_relaxed).m_methCallerClsName;
1520 assertx(n & kMethCallerBit);
1521 return reinterpret_cast<StringData*>(n - kMethCallerBit);
1525 template <class T>
1526 static Func::low_storage_t to_low(T* px, Func::low_storage_t bit = 0) {
1527 Func::low_storage_t ones = ~0;
1528 auto ptr = reinterpret_cast<uintptr_t>(px) | bit;
1529 always_assert((ptr & ones) == ptr);
1530 return (Func::low_storage_t)(ptr);
1533 /////////////////////////////////////////////////////////////////////////////
1534 // Atomic Flags.
1536 public:
1537 enum Flags : uint8_t {
1538 None = 0,
1539 Optimized = 1 << 0,
1540 Locked = 1 << 1,
1544 * Wrapper around std::atomic<uint8_t> that enables it to be
1545 * copy constructable,
1547 struct AtomicFlags {
1548 AtomicFlags() {}
1550 AtomicFlags(const AtomicFlags&) {}
1551 AtomicFlags& operator=(const AtomicFlags&) = delete;
1553 bool set(Flags flags) {
1554 auto const prev = m_flags.fetch_or(flags, std::memory_order_release);
1555 return prev & flags;
1558 bool unset(Flags flags) {
1559 auto const prev =
1560 m_flags.fetch_and(~uint8_t(flags), std::memory_order_release);
1561 return prev & flags;
1564 bool check(Flags flags) const {
1565 return m_flags.load(std::memory_order_acquire) & flags;
1568 std::atomic<uint8_t> m_flags{Flags::None};
1571 inline AtomicFlags& atomicFlags() const {
1572 return m_atomicFlags;
1575 inline AtomicFlags& atomicFlags() {
1576 return m_atomicFlags;
1579 /////////////////////////////////////////////////////////////////////////////
1580 // Code locations. [const]
1583 * Get the line number corresponding to `offset'.
1585 * Return -1 if not found.
1587 int getLineNumber(Offset offset) const;
1590 * Get the SourceLoc corresponding to `offset'.
1592 * Return false if not found, else true.
1594 bool getSourceLoc(Offset offset, SourceLoc& sLoc) const;
1597 * Get the Offset range(s) corresponding to `offset'.
1599 * Return false if not found, else true.
1601 bool getOffsetRange(Offset offset, OffsetRange& range) const;
1603 void stashLineTable(LineTable table) const;
1605 void stashExtendedLineTable(SourceLocTable table) const;
1607 const SourceLocTable& getLocTable() const;
1609 LineToOffsetRangeVecMap getLineToOffsetRangeVecMap() const;
1611 const LineTable* getLineTable() const;
1613 private:
1614 const LineTable& loadLineTable() const;
1615 void cleanupLocationCache() const;
1617 /////////////////////////////////////////////////////////////////////////////
1618 // Constants.
1620 private:
1621 static constexpr int argToQword(int32_t arg) {
1622 return static_cast<uint32_t>(arg) / kBitsPerQword - 1;
1624 static constexpr int kBitsPerQword = 64;
1625 static constexpr int kMagic = 0xba5eba11;
1626 static constexpr intptr_t kNeedsFullName = 0x1;
1628 public:
1629 static std::atomic<bool> s_treadmill;
1630 static std::atomic<uint32_t> s_totalClonedClosures;
1632 // To conserve space, we use unions for pairs of mutually exclusive fields
1633 static auto constexpr kMethCallerBit = 0x1; // set for m_methCaller
1634 /////////////////////////////////////////////////////////////////////////////
1635 // Data members.
1637 // The fields of Func are organized in reverse order of frequency of use.
1638 // Do not re-order without checking perf!
1640 private:
1641 #ifndef NDEBUG
1642 // For asserts only.
1643 int m_magic;
1644 #endif
1645 AtomicLowPtr<uint8_t> m_funcBody{nullptr};
1646 mutable rds::Link<LowPtr<Func>, rds::Mode::NonLocal> m_cachedFunc;
1647 FuncId m_funcId{FuncId::Invalid};
1648 mutable AtomicLowPtr<const StringData> m_fullName{nullptr};
1649 LowStringPtr m_name{nullptr};
1651 union {
1652 // The first Class in the inheritance hierarchy that declared this method.
1653 // Note that this may be an abstract class that did not provide an
1654 // implementation.
1655 low_storage_t m_baseCls{0};
1656 // m_methCallerMethName can be accessed by meth_caller() only
1657 low_storage_t m_methCallerMethName;
1660 // m_u is used to represent
1661 // the Class that provided this method implementation, or
1662 // the class name provided by meth_caller()
1663 UnionWrapper m_u{nullptr};
1664 union {
1665 Slot m_methodSlot{0};
1666 LowPtr<const NamedEntity>::storage_type m_namedEntity;
1668 // Atomically-accessed intercept flag. -1, 0, or 1.
1669 // TODO(#1114385) intercept should work via invalidation.
1670 mutable int8_t m_maybeIntercepted;
1671 mutable ClonedFlag m_cloned;
1672 mutable AtomicFlags m_atomicFlags;
1673 bool m_isPreFunc : 1;
1674 bool m_hasPrivateAncestor : 1;
1675 bool m_shouldSampleJit : 1;
1676 bool m_serialized : 1;
1677 bool m_hasForeignThis : 1;
1678 bool m_registeredInDataMap : 1;
1679 // 2 free bits
1680 StaticCoeffects m_staticCoeffects{StaticCoeffects::none()};
1681 int16_t m_maxStackCells{0};
1682 uint64_t m_inoutBitVal{0};
1683 Unit* const m_unit;
1684 AtomicSharedPtr<SharedData> m_shared;
1685 // Initialized by Func::finishedEmittingParams. The least significant bit is
1686 // 1 if the last param is not variadic; the 31 most significant bits are the
1687 // total number of params (including the variadic param).
1688 uint32_t m_paramCounts{0};
1689 AtomicAttr m_attrs;
1690 // This must be the last field declared in this structure, and the Func class
1691 // should not be inherited from.
1692 AtomicLowPtr<uint8_t> m_prologueTable[1];
1694 static constexpr size_t kFuncSize = debug ? (use_lowptr ? 88 : 112)
1695 : (use_lowptr ? 80 : 104);
1696 static_assert(CheckSize<Func, kFuncSize>(), "");
1698 ///////////////////////////////////////////////////////////////////////////////
1701 * A prologue is identified by the called function and the number of arguments
1702 * that the prologue handles.
1704 struct PrologueID {
1705 PrologueID(FuncId funcId, uint32_t nargs)
1706 : m_funcId(funcId)
1707 , m_nargs(nargs)
1710 PrologueID(const Func* func, uint32_t nargs)
1711 : m_funcId(func->getFuncId())
1712 , m_nargs(nargs)
1715 PrologueID()
1718 FuncId funcId() const { return m_funcId; }
1719 uint32_t nargs() const { return m_nargs; }
1720 const Func* func() const { return Func::fromFuncId(m_funcId); }
1722 bool operator==(const PrologueID& other) const {
1723 return m_funcId == other.m_funcId && m_nargs == other.m_nargs;
1726 struct Hasher {
1727 size_t operator()(PrologueID pid) const {
1728 return pid.funcId().toInt() + (size_t(pid.nargs()) << 32);
1732 private:
1733 FuncId m_funcId{FuncId::Invalid};
1734 uint32_t m_nargs{0xffffffff};
1737 ///////////////////////////////////////////////////////////////////////////////
1740 * Log meta-information about func. Records attributes, number of locals,
1741 * parameters, static locals, class ref slots, frame cells, high watermark,
1742 * and iterators. Does not record function name or class.
1744 void logFunc(const Func* func, StructuredLogEntry& ent);
1746 inline tracing::Props traceProps(const Func* f) {
1747 return tracing::Props{}.add("func_name", f->fullName());
1751 * Throw an exception that func cannot be converted to type.
1753 [[noreturn]] void invalidFuncConversion(const char* type);
1755 ///////////////////////////////////////////////////////////////////////////////
1756 // Bytecode
1759 * Report capacity of RepoAuthoritative mode bytecode arena.
1761 * Returns 0 if !RuntimeOption::RepoAuthoritative.
1763 size_t hhbc_arena_capacity();
1765 const unsigned char*
1766 allocateBCRegion(const unsigned char* bc, size_t bclen);
1767 void freeBCRegion(const unsigned char* bc, size_t bclen);
1769 ///////////////////////////////////////////////////////////////////////////////
1773 #define incl_HPHP_VM_FUNC_INL_H_
1774 #include "hphp/runtime/vm/func-inl.h"
1775 #undef incl_HPHP_VM_FUNC_INL_H_