Back out "Implement Dynamically Enforced Implicit Context"
[hiphop-php.git] / hphp / runtime / vm / func.h
blob176848376ec5d4f4be97feef7bedc6db1109d5f2
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/repo-file.h"
33 #include "hphp/runtime/vm/type-constraint.h"
34 #include "hphp/runtime/vm/unit.h"
36 #include "hphp/util/fixed-vector.h"
37 #include "hphp/util/low-ptr.h"
39 #include <atomic>
40 #include <utility>
41 #include <vector>
43 namespace HPHP {
44 ///////////////////////////////////////////////////////////////////////////////
46 struct ActRec;
47 struct Class;
48 struct NamedEntity;
49 struct PreClass;
50 struct StringData;
51 struct StructuredLogEntry;
52 template <typename T> struct AtomicLowPtrVector;
55 * Signature for native functions called by the hhvm using the hhvm
56 * calling convention that provides raw access to the ActRec.
58 using ArFunction = TypedValue* (*)(ActRec* ar);
61 * Signature for native functions expecting the platform ABI calling
62 * convention. This must always be casted to a proper signature before
63 * calling, so make something up to prevent accidental mixing with other
64 * function pointer types.
66 struct NativeArgs; // never defined
67 using NativeFunction = void(*)(NativeArgs*);
69 using StaticCoeffectNamesMap = CompactVector<LowStringPtr>;
71 ///////////////////////////////////////////////////////////////////////////////
72 // EH table.
75 * Exception handler table entry.
77 struct EHEnt {
78 Offset m_base;
79 Offset m_past;
80 int m_iterId;
81 int m_parentIndex;
82 Offset m_handler;
83 Offset m_end;
85 EHEnt()
86 : m_base()
87 , m_past()
88 , m_iterId()
89 , m_parentIndex()
90 , m_handler()
91 , m_end()
94 template<class SerDe> void serde(SerDe& sd);
97 ///////////////////////////////////////////////////////////////////////////////
99 template <typename T, size_t Expected, size_t Actual = sizeof(T)>
100 constexpr bool CheckSize() { static_assert(Expected == Actual); return true; };
102 ///////////////////////////////////////////////////////////////////////////////
104 * Metadata about a PHP function or method.
106 * The Func class cannot be safely extended, because variable amounts of memory
107 * associated with the Func are allocated before and after the actual object.
109 * All Funcs are also followed by a variable number of function prologue
110 * pointers. Six are statically allocated as part of the Func object, but more
111 * may follow, depending on the value of getMaxNumPrologues().
113 * +--------------------------------+ Func* address
114 * | Func object |
115 * | |
116 * | prologues at end of Func |
117 * +--------------------------------+ Func* address
118 * | [additional prologues] |
119 * +--------------------------------+ high address
122 struct Func final {
123 friend struct FuncEmitter;
124 friend struct UnitEmitter;
126 #ifndef USE_LOWPTR
127 // DO NOT access it directly, instead use Func::getFuncVec()
128 // Exposed in the header file for gdb python macros
129 static AtomicLowPtrVector<const Func> s_funcVec;
130 #endif
131 /////////////////////////////////////////////////////////////////////////////
132 // Types.
135 * Parameter default value info.
137 struct ParamInfo {
138 enum class Flags {
139 InOut, // Is this an `inout' parameter?
140 Readonly, // Is this a `readonly` parameter?
141 Variadic, // Is this a `...' parameter?
142 NativeArg, // Does this use a NativeArg?
143 AsVariant, // Native function takes as const Variant&
144 AsTypedValue // Native function takes as TypedValue
147 ParamInfo();
149 bool hasDefaultValue() const;
150 bool hasScalarDefaultValue() const;
151 bool isInOut() const;
152 bool isReadonly() const;
153 bool isVariadic() const;
154 bool isNativeArg() const;
155 bool isTakenAsVariant() const;
156 bool isTakenAsTypedValue() const;
157 void setFlag(Flags flag);
159 template<class SerDe> void serde(SerDe& sd);
161 // Typehint for builtins.
162 MaybeDataType builtinType{std::nullopt};
163 // Flags as defined by the Flags enum.
164 uint8_t flags{0};
165 // DV initializer funclet offset.
166 Offset funcletOff{kInvalidOffset};
167 // Set to Uninit if there is no DV, or if there's a nonscalar DV.
168 TypedValue defaultValue;
169 // Eval-able PHP code.
170 LowStringPtr phpCode{nullptr};
171 // User-annotated type.
172 LowStringPtr userType{nullptr};
173 // offset of dvi funclet from cti section base.
174 Offset ctiFunclet{kInvalidOffset};
175 TypeConstraint typeConstraint;
176 UserAttributeMap userAttributes;
179 using ParamInfoVec = VMFixedVector<ParamInfo>;
180 using EHEntVec = VMFixedVector<EHEnt>;
181 using UpperBoundVec = VMCompactVector<TypeConstraint>;
182 using ParamUBMap = vm_flat_map<uint32_t, UpperBoundVec>;
183 using CoeffectRules = VMFixedVector<CoeffectRule>;
185 /////////////////////////////////////////////////////////////////////////////
186 // Creation and destruction.
188 Func(Unit& unit, const StringData* name, Attr attrs);
189 Func(Unit& unit, const StringData* name, Attr attrs,
190 const StringData *methCallerCls, const StringData *methCallerMeth);
191 ~Func();
194 * Allocate memory for a function, including the variable number of prologues
195 * that follow.
197 static void* allocFuncMem(int numParams);
200 * Destruct and free a Func*.
202 static void destroy(Func* func);
205 * Address of the end of the Func's variable-length memory allocation.
207 const void* mallocEnd() const;
210 * Duplicate this function.
212 * Funcs are cloned for a number of reasons---most notably, methods on
213 * Classes are cloned from the methods defined on their respective
214 * PreClasses.
216 * We also clone methods from traits when we transclude the trait in its user
217 * Classes in repo mode.
219 Func* clone(Class* cls, const StringData* name = nullptr) const;
222 * Reset this function's cls and attrs.
224 * Used to change the Class scope of a closure method.
226 void rescope(Class* ctx);
229 * Free up a PreFunc for re-use as a cloned Func.
231 * @requires: isPreFunc()
233 void freeClone();
236 * Verify that a Func's data is coherent.
238 * FIXME: Currently this method does almost nothing.
240 bool validate() const;
242 /////////////////////////////////////////////////////////////////////////////
243 // FuncId manipulation.
246 * Get this function's ID.
248 * We allocate a unique 32-bit ID to almost all Funcs. The Func* can be
249 * retrieved by using this ID as an index into a global vector. This lets
250 * the JIT store references to Funcs more compactly.
252 * Funcs which do not represent actual runtime functions (namely, Funcs on
253 * PreClasses) are not assigned an ID.
255 FuncId getFuncId() const;
257 private:
259 * Reserve the next available FuncId for `this', and add `this' to the
260 * function table.
262 void setNewFuncId();
264 public:
266 * The max FuncId num.
268 static FuncId::Int maxFuncIdNum();
271 * Lookup a Func* by its ID.
273 static const Func* fromFuncId(FuncId id);
276 * Whether `id' actually keys a Func*.
278 static bool isFuncIdValid(FuncId id);
280 /////////////////////////////////////////////////////////////////////////////
281 // Basic info. [const]
284 * The Unit the function is defined in.
286 Unit* unit() const;
289 * The various Class contexts of a method.
291 * cls(): The Class context of the method. This is usually the Class
292 * which implements the method, but for closure methods (i.e.,
293 * the __invoke() method on a closure object), it is instead the
294 * Class that the Closure object is scoped to.
296 * preClass(): The PreClass of the method's cls(). For closures, this still
297 * corresponds to the Closure subclass, rather than to the
298 * scoped Class.
300 * When isFromTrait() is true, preClass() refers to different
301 * entities in repo vs. non-repo mode. In repo mode, traits are
302 * flattened ahead of time, and preClass() refers to the class
303 * which imported the trait. In non-repo mode, trait methods
304 * are cloned into trait users, but preClass() will still refer
305 * to the trait which defined the method.
307 * baseCls(): The first Class in the inheritance hierarchy which declares
308 * this method.
310 * implCls(): The Class which implements the method. Just like cls(), but
311 * ignores closure scope (so it returns baseCls() for closures).
313 * It is possible for cls() to be nullptr on a method---this occurs when a
314 * closure method is scoped to a null class context (e.g., if the closure is
315 * created in a non-method function scope). In this case, only the `cls' is
316 * changed; the `preClass' and `baseCls' will continue to refer to the
317 * PreClass and Class of the closure object.
319 * The converse also occurs---a function can have a `cls' (and `baseCls')
320 * without being a method. This happens when a pseudomain is included from a
321 * class context.
323 * Consequently, none of these methods should be used to test whether the
324 * function is a method; for that purpose, see isMethod().
326 Class* cls() const;
327 PreClass* preClass() const;
328 bool hasBaseCls() const;
329 Class* baseCls() const;
330 Class* implCls() const;
332 int sn() const;
335 * The function's short name (e.g., foo).
337 const StringData* name() const;
338 String nameWithClosureName() const;
339 StrNR nameStr() const;
342 * A hash for this func that will remain constant across process restarts.
344 size_t stableHash() const;
347 * The function's fully class-qualified, name (e.g., C::foo).
349 const StringData* fullName() const;
350 String fullNameWithClosureName() const;
351 StrNR fullNameStr() const;
354 * The function's named entity. Only valid for non-methods.
356 * @requires: shared()->m_preClass == nullptr
358 NamedEntity* getNamedEntity();
359 const NamedEntity* getNamedEntity() const;
362 * meth_caller
364 const StringData* methCallerClsName() const;
365 const StringData* methCallerMethName() const;
367 /////////////////////////////////////////////////////////////////////////////
368 // File info. [const]
371 * The filename where the function was originally defined.
373 * In repo mode, we flatten traits into the classes they're used in, so we
374 * need this to track the original file for backtraces and errors.
376 const StringData* originalFilename() const;
379 * The original filename if it is defined, the unit's filename otherwise.
381 const StringData* filename() const;
384 * Start and end line of the function.
386 * It'd be nice if these were called lineStart and lineEnd or something, but
387 * we're not allowed to have nice things.
389 int line1() const;
390 int line2() const;
393 * The system- or user-defined doc comment accompanying the function.
395 const StringData* docComment() const;
397 /////////////////////////////////////////////////////////////////////////////
398 // Bytecode. [const]
401 * Get the function's main entrypoint.
403 PC entry() const;
404 Offset bclen() const;
407 * Whether a given PC or Offset (from the beginning of the unit) is within
408 * the function's bytecode stream.
410 bool contains(PC pc) const;
411 bool contains(Offset offset) const;
414 * Convert between PC and Offset from entry().
416 PC at(Offset off) const;
417 Offset offsetOf(PC pc) const;
420 * Get the Op at `instrOffset'.
422 Op getOp(Offset instrOffset) const;
425 * Is there a main or default value entrypoint at the given offset?
427 bool isEntry(Offset offset) const;
428 bool isDVEntry(Offset offset) const;
431 * Number of params required when entering at the given offset.
433 * Return -1 if an invalid offset is provided.
435 int getEntryNumParams(Offset offset) const;
436 int getDVEntryNumParams(Offset offset) const;
439 * Get the correct entrypoint (whether the main entry or a DV funclet) when
440 * `numArgsPassed' arguments are passed to the function.
442 * This is the DV funclet offset of the numArgsPassed-th parameter, or the
443 * next parameter that has a DV funclet.
445 Offset getEntryForNumArgs(int numArgsPassed) const;
447 // CTI entry points
448 Offset ctiEntry() const;
449 void setCtiFunclet(int i, Offset);
450 void setCtiEntry(Offset entry, uint32_t size);
452 /////////////////////////////////////////////////////////////////////////////
453 // Return type. [const]
456 * Return type inferred by HHBBC's static analysis. TGen if no data is
457 * available.
459 RepoAuthType repoReturnType() const;
462 * For async functions, the statically inferred inner type of the returned
463 * WH based on HHBBC's analysis.
465 RepoAuthType repoAwaitedReturnType() const;
468 * For builtins, whether the return value is returned in registers (as
469 * opposed to indirect return, via tvBuiltinReturn).
471 * Not well-defined if this function is not a builtin.
473 bool isReturnByValue() const;
476 * The TypeConstraint of the return.
478 const TypeConstraint& returnTypeConstraint() const;
481 * The user-annotated Hack return type.
483 const StringData* returnUserType() const;
485 bool hasReturnWithMultiUBs() const;
486 const UpperBoundVec& returnUBs() const;
488 /////////////////////////////////////////////////////////////////////////////
489 // Parameters. [const]
492 * Const reference to the parameter info table.
494 * ParamInfo objects pulled from the table will also be const.
496 const ParamInfoVec& params() const;
499 * Number of parameters (including `...') accepted by the function.
501 uint32_t numParams() const;
504 * Number of parameters, not including `...', accepted by the function.
506 uint32_t numNonVariadicParams() const;
509 * Number of required parameters, i.e. all arguments starting from
510 * the returned position have default value.
512 uint32_t numRequiredParams() const;
515 * Whether the function is declared with a `...' parameter.
517 bool hasVariadicCaptureParam() const;
520 * Whether the arg-th parameter was declared inout.
522 bool isInOut(int32_t arg) const;
525 * Return the raw m_inoutBits field.
527 uint64_t inOutBits() const;
530 * Whether the arg-th parameter was declared readonly.
532 bool isReadonly(int32_t arg) const;
535 * Whether any of the parameters to this function are inout parameters.
537 bool takesInOutParams() const;
540 * Returns the number of inout parameters taken by func.
542 uint32_t numInOutParams() const;
545 * Returns the number of inout parameters for the given number of
546 * arguments.
548 uint32_t numInOutParamsForArgs(int32_t numArgs) const;
550 bool hasParamsWithMultiUBs() const;
552 const ParamUBMap& paramUBs() const;
554 /////////////////////////////////////////////////////////////////////////////
555 // Locals, iterators, and stack. [const]
558 * Number of locals, iterators, closure use locals or named locals.
560 int numLocals() const;
561 int numIterators() const;
562 uint32_t numClosureUseLocals() const;
563 Id numNamedLocals() const;
566 * Find the integral ID assigned to a named local.
568 Id lookupVarId(const StringData* name) const;
571 * Number of initialized locals at FuncEntry.
573 uint32_t numFuncEntryInputs() const;
576 * Returns the ID of coeffects and reified generics locals.
577 * Requires hasCoeffectRules() and hasReifiedGenerics() respectively
579 uint32_t coeffectsLocalId() const;
580 uint32_t reifiedGenericsLocalId() const;
583 * Returns the ID of the first closure use local.
585 uint32_t firstClosureUseLocalId() const;
588 * Returns the ID of the first regular local, i.e. a first local that is not
589 * a parameter, reified generics, coeffects or closure use local.
591 uint32_t firstRegularLocalId() const;
595 * Find the name of the local with the given ID.
597 const StringData* localVarName(Id id) const;
600 * Array of named locals. Includes parameter names.
601 * May contain nullptrs for unammed locals that mixed in with named ones.
603 * Should not be indexed past numNamedLocals() - 1.
605 LowStringPtr const* localNames() const;
608 * Number of stack slots used by locals and iterator cells.
610 int numSlotsInFrame() const;
613 * Access to the maximum stack cells this function can use. This is
614 * used for stack overflow checks.
616 * The maximum cells for a function includes all its locals, all cells
617 * for its iterators, and all temporary eval stack slots. It does not
618 * include its own ActRec, because whoever called it must have(+) included
619 * the stack slot space reserved for this ActRec. The reason it must still
620 * count its parameter locals is that the caller may or may not pass any of
621 * the parameters, regardless of how many are declared.
623 * + Except in a re-entry situation. That must be handled
624 * specially in bytecode.cpp.
626 int maxStackCells() const;
629 * Checks if $this belong to a class that is not a subclass of cls().
631 bool hasForeignThis() const;
633 void setHasForeignThis(bool);
635 void registerInDataMap();
636 void deregisterInDataMap();
638 /////////////////////////////////////////////////////////////////////////////
639 // Definition context. [const]
642 * Is this function a method defined on a class?
644 * Note that trait methods may not satisfy isMethod().
646 bool isMethod() const;
649 * Was this function imported from a trait?
651 * Note that this returns false for a trait method in the trait it was
652 * originally declared.
654 bool isFromTrait() const;
657 * Is this function declared with `public', `static', or `abstract'?
659 bool isPublic() const;
660 bool isStatic() const;
661 bool isAbstract() const;
664 * Is this function declared as internal to its module?
666 bool isInternal() const;
669 * What module does this function belong to?
671 const StringData* moduleName() const;
674 * Whether a function is called non-statically. Generally this means
675 * isStatic(), but eg static closures are still called with a valid
676 * this pointer.
678 bool isStaticInPrologue() const;
681 * Whether a method is guaranteed to have a valid this in the body.
682 * A method which is !isStatic() || isClosureBody() is guaranteed to
683 * be called with a valid this, but closures swap out the closure
684 * object for the closure context in the prologue, so may not have
685 * a this in the body.
687 bool hasThisInBody() const;
690 * Is this Func owned by a PreClass?
692 * A PreFunc may be "adopted" by a Class when clone() is called, but only the
693 * owning PreClass is allowed to free it.
695 bool isPreFunc() const;
698 * Is this func a memoization wrapper?
700 bool isMemoizeWrapper() const;
703 * Is this func a memoization wrapper with LSB parameter set?
705 bool isMemoizeWrapperLSB() const;
707 bool isKeyedByImplicitContextMemoize() const;
710 * Is this string the name of a memoize implementation.
712 static bool isMemoizeImplName(const StringData*);
715 * Is this function a memoization implementation.
717 bool isMemoizeImpl() const;
720 * Assuming this func is a memoization wrapper, the name of the function it is
721 * wrapping.
723 * Pre: isMemoizeWrapper()
725 const StringData* memoizeImplName() const;
728 * Given the name of a memoization wrapper function, return the generated name
729 * of the function it wraps. This is static so it can be used in contexts
730 * where the actual Func* is not available.
732 static const StringData* genMemoizeImplName(const StringData*);
735 * Returns the number of local slots used for the memoization key calculation.
737 size_t numKeysForMemoize() const;
740 * Given a meth_caller, return the class name or method name
742 static std::pair<const StringData*, const StringData*> getMethCallerNames(
743 const StringData* name);
745 /////////////////////////////////////////////////////////////////////////////
746 // Builtins. [const]
749 * Is the function a builtin, whether PHP or C++?
751 bool isBuiltin() const;
754 * Is this function a C++ builtin (ie HNI function)?.
756 * @implies: isBuiltin()
758 bool isCPPBuiltin() const;
761 * The function returned by arFuncPtr() takes an ActRec*, unpacks it,
762 * and usually dispatches to a nativeFuncPtr() with a specific signature.
764 * All C++ builtins have an ArFunction, with no exceptions.
766 * Most HNI functions share a single ArFunction, which performs
767 * unpacking and dispatch. The exception is HNI functions declared
768 * with NeedsActRec, which do not have NativeFunctions, but have unique
769 * ArFunctions which do all their work.
771 ArFunction arFuncPtr() const;
774 * The nativeFuncPtr is a type-punned function pointer to the unerlying
775 * function which takes the actual argument types, and does the actual work.
777 * These are the functions with names prefixed by f_ or t_.
779 * All C++ builtins have NativeFunctions, with the ironic exception of HNI
780 * functions declared with NeedsActRec.
782 NativeFunction nativeFuncPtr() const;
784 /////////////////////////////////////////////////////////////////////////////
785 // Closures. [const]
788 * Is this function the body (i.e., __invoke() method) of a Closure object?
790 * (All PHP anonymous functions are Closure objects.)
792 bool isClosureBody() const;
794 /////////////////////////////////////////////////////////////////////////////
795 // Resumables. [const]
798 * Is this function asynchronous? (May also be a generator.)
800 bool isAsync() const;
803 * Is this function a generator? (May also be async.)
805 bool isGenerator() const;
808 * Is this function a generator which yields both key and value?
810 * @implies: isGenerator()
812 bool isPairGenerator() const;
815 * @returns: !isGenerator() && isAsync()
817 bool isAsyncFunction() const;
820 * @returns: isGenerator() && !isAsync()
822 bool isNonAsyncGenerator() const;
825 * @returns: isGenerator() && isAsync()
827 bool isAsyncGenerator() const;
830 * Is this a resumable function?
832 * @returns: isGenerator() || isAsync()
834 bool isResumable() const;
836 /////////////////////////////////////////////////////////////////////////////
837 // Coeffects. [const]
840 * Returns the runtime representation of coeffects
842 RuntimeCoeffects requiredCoeffects() const;
843 RuntimeCoeffects coeffectEscapes() const;
846 * Sets required coeffects
848 void setRequiredCoeffects(RuntimeCoeffects);
851 * Names of the static coeffects on the function
852 * Used for reflection
854 StaticCoeffectNamesMap staticCoeffectNames() const;
857 * Does this function use coeffects local to store its ambient coeffects?
859 bool hasCoeffectsLocal() const;
862 * Does this function have coeffect rules?
864 bool hasCoeffectRules() const;
867 * List of rules for enforcing coeffects
869 const CoeffectRules& getCoeffectRules() const;
871 /////////////////////////////////////////////////////////////////////////////
872 // Methods. [const]
875 * Index of this function in the method table of its Class.
877 Slot methodSlot() const;
880 * Whether this function has a private implementation on a parent class.
882 bool hasPrivateAncestor() const;
884 /////////////////////////////////////////////////////////////////////////////
885 // Magic methods. [const]
888 * Is this a compiler-generated function?
890 * This includes special methods like 86pinit and 86sinit as well
891 * as all closures.
893 bool isGenerated() const;
896 * Is `name' the name of a special initializer function?
898 static bool isSpecial(const StringData* name);
900 /////////////////////////////////////////////////////////////////////////////
901 // Persistence. [const]
904 * Whether this function is uniquely named across the codebase.
906 * It's legal in PHP to define multiple functions in different pseudomains
907 * with the same name, so long as both are not required in the same request.
909 * Note that if EvalJitEnableRenameFunction is set, no Func is unique.
911 bool isUnique() const;
914 * Whether we can load this function once and persist it across requests.
916 * Persistence is possible when a Func is defined in a pseudomain that has no
917 * side-effects (except other persistent definitions).
919 * @implies: isUnique()
921 bool isPersistent() const;
923 bool isInterceptable() const;
926 * Given that func would be called when func->name() is invoked on cls,
927 * determine if it would also be called when invoked on any descendant
928 * of cls.
930 bool isImmutableFrom(const Class* cls) const;
932 /////////////////////////////////////////////////////////////////////////////
933 // Other attributes. [const]
936 * Get the system and coeffect attributes of the function.
938 Attr attrs() const;
941 * Get the user-declared attributes of the function.
943 const UserAttributeMap& userAttributes() const;
946 * Whether to ignore this function's frame in backtraces.
948 bool isNoInjection() const;
951 * Whether this function's frame should be skipped when searching for context
952 * (e.g., array_map evaluates its callback in the context of its caller).
954 bool isSkipFrame() const;
957 * Whether this function's frame should be skipped with searching for a
958 * context for array provenance
960 bool isProvenanceSkipFrame() const;
963 * Whether the function can be constant-folded at callsites where it is
964 * passed constant arguments.
966 bool isFoldable() const;
969 * Supports async eager return optimization?
971 bool supportsAsyncEagerReturn() const;
974 * Is this func allowed to be called dynamically?
976 bool isDynamicallyCallable() const;
979 * If this function is called dynamically should we raise sampled warnings?
981 * N.B. When errors are enabled for dynamic calls this overrides that behavior
982 * for functions which specify it.
984 Optional<int64_t> dynCallSampleRate() const;
987 * Is this a meth_caller func?
989 bool isMethCaller() const;
992 * Indicates that a function does not make any explicit calls to other PHP
993 * functions. It may still call other user-level functions via re-entry
994 * (e.g., for autoload), and it may make calls to builtins using FCallBuiltin.
996 bool isPhpLeafFn() const;
999 * Does this function has reified generics?
1001 bool hasReifiedGenerics() const;
1004 * Returns a ReifiedGenericsInfo containing how many generics this func has,
1005 * indices of its reified generics, and which ones are soft reified
1007 const ReifiedGenericsInfo& getReifiedGenericsInfo() const;
1009 /////////////////////////////////////////////////////////////////////////////
1010 // Unit table entries. [const]
1012 const EHEntVec& ehtab() const;
1015 * Find the first EHEnt that covers a given offset, or return null.
1017 const EHEnt* findEH(Offset o) const;
1020 * Same as non-static findEH(), but takes as an operand any ehtab-like
1021 * container.
1023 template<class Container>
1024 static const typename Container::value_type*
1025 findEH(const Container& ehtab, Offset o);
1027 bool shouldSampleJit() const { return m_shouldSampleJit; }
1029 /////////////////////////////////////////////////////////////////////////////
1030 // JIT data.
1033 * Get the RDS handle for the function with this function's name.
1035 * We can burn these into the TC even when functions are not persistent,
1036 * since only a single name-to-function mapping will exist per request.
1038 rds::Handle funcHandle() const;
1041 * Get, set and reset the function body code pointer.
1043 jit::TCA getFuncEntry() const;
1044 void setFuncEntry(jit::TCA funcEntry);
1045 void resetFuncEntry();
1048 * Get and set the `index'-th function prologue.
1050 uint8_t* getPrologue(int index) const;
1051 void setPrologue(int index, unsigned char* tca);
1054 * Number of prologues allocated for the function.
1056 int numPrologues() const;
1059 * Reset a specific prologue, or all prologues.
1061 void resetPrologue(int numParams);
1063 /////////////////////////////////////////////////////////////////////////////
1064 // Pretty printer. [const]
1066 struct PrintOpts {
1067 PrintOpts()
1068 : name(true)
1069 , metadata(true)
1070 , startOffset(0)
1071 , stopOffset(kInvalidOffset)
1072 , showLines(true)
1073 , indentSize(1)
1076 PrintOpts& noName() {
1077 name = false;
1078 return *this;
1081 PrintOpts& noMetadata() {
1082 metadata = false;
1083 return *this;
1086 PrintOpts& noBytecode() {
1087 startOffset = kInvalidOffset;
1088 stopOffset = kInvalidOffset;
1089 return *this;
1092 PrintOpts& range(Offset start, Offset stop) {
1093 startOffset = start;
1094 stopOffset = stop;
1095 return *this;
1098 PrintOpts& noLineNumbers() {
1099 showLines = false;
1100 return *this;
1103 PrintOpts& indent(int i) {
1104 indentSize = i;
1105 return *this;
1108 bool name;
1109 bool metadata;
1110 Offset startOffset;
1111 Offset stopOffset;
1112 bool showLines;
1113 int indentSize;
1116 void prettyPrint(std::ostream& out, const PrintOpts& = PrintOpts()) const;
1119 * Print function attributes to out.
1121 static void print_attrs(std::ostream& out, Attr attrs);
1124 /////////////////////////////////////////////////////////////////////////////
1125 // Other methods.
1127 // You should avoid adding methods to this section. If the logic you're
1128 // implementing is specific to a particular subsystem, define it as a helper
1129 // there instead.
1131 // If you absolutely must add more methods to Func here, just follow these
1132 // simple guidelines:
1134 // (1) Don't add more methods to Func here.
1137 * Intercept hook flag.
1139 bool maybeIntercepted() const;
1140 void setMaybeIntercepted();
1143 * When function call based coverage is enabled for the current request,
1144 * records a call to `this`. The no check version asserts that function
1145 * coverage has already been enabled and the function is both eligible to be
1146 * covered and has not yet been seen.
1148 void recordCall() const;
1149 void recordCallNoCheck() const;
1152 * EnableCoverage enables recording of called functions for the current
1153 * request.
1155 static void EnableCoverage();
1158 * GetCoverage returns a keyset of called functions and disables further
1159 * coverage for the current request until reenabled by EnableCoverage.
1161 static Array GetCoverage();
1164 * RDS based counter (uint32_t) that when zero indicates coverage is disabled
1165 * and when non-zero indicates an index which can be used to short circuit
1166 * tests that functions have been covered.
1168 static rds::Handle GetCoverageIndex();
1171 * Get an RDS counter (uint32_t) that can be compared against GetCoverageIndex
1172 * to determine if the function has been covered in the current request.
1174 rds::Handle getCoverageHandle() const;
1176 /////////////////////////////////////////////////////////////////////////////
1177 // Public setters.
1179 // TODO(#4504609): These setters are only used by Class at Class creation
1180 // time. We should refactor the creation path into a separate friend module
1181 // to avoid this garbage.
1183 // Having public setters here should be avoided, so try not to add any.
1185 void setAttrs(Attr attrs);
1186 void setBaseCls(Class* baseCls);
1187 void setHasPrivateAncestor(bool b);
1188 void setMethodSlot(Slot s);
1189 void setGenerated(bool b);
1191 /////////////////////////////////////////////////////////////////////////////
1192 // Offset accessors. [static]
1194 #define OFF(f) \
1195 static constexpr ptrdiff_t f##Off() { \
1196 return offsetof(Func, m_##f); \
1198 OFF(attrs)
1199 OFF(requiredCoeffects)
1200 OFF(name)
1201 OFF(maxStackCells)
1202 OFF(paramCounts)
1203 OFF(prologueTable)
1204 OFF(inoutBits)
1205 OFF(shared)
1206 OFF(unit)
1207 OFF(methCallerMethName)
1208 #undef OFF
1210 static constexpr ptrdiff_t clsOff() {
1211 return offsetof(Func, m_u);
1214 static constexpr ptrdiff_t methCallerClsNameOff() {
1215 return offsetof(Func, m_u);
1218 static constexpr ptrdiff_t sharedAllFlags() {
1219 return offsetof(SharedData, m_allFlags);
1222 static uint32_t reifiedGenericsMask() {
1223 ExtendedSharedData::Flags mask;
1224 mask.m_allFlags = 0;
1225 mask.m_hasReifiedGenerics = true;
1226 return mask.m_allFlags;
1229 /////////////////////////////////////////////////////////////////////////////
1230 // Lookup [static]
1233 * Define `func' for this request by initializing its RDS handle.
1235 static void def(Func* func);
1238 * Look up the defined Func in this request with name `name', or with the name
1239 * mapped to the NamedEntity `ne'.
1241 * Return nullptr if the function is not yet defined in this request.
1243 static Func* lookup(const NamedEntity* ne);
1244 static Func* lookup(const StringData* name);
1247 * Look up, or autoload and define, the Func in this request with name `name',
1248 * or with the name mapped to the NamedEntity `ne'.
1250 * @requires: NamedEntity::get(name) == ne
1252 static Func* load(const NamedEntity* ne, const StringData* name);
1253 static Func* load(const StringData* name);
1256 * Same as Func::load but also checks for module boundary violations
1258 static Func* resolve(const NamedEntity* ne, const StringData* name,
1259 const Func* callerFunc);
1260 static Func* resolve(const StringData* name, const Func* callerFunc);
1263 * Lookup the builtin in this request with name `name', or nullptr if none
1264 * exists. This does not access RDS so it is safe to use from within the
1265 * compiler. Note that does not mean imply that the name binding for the
1266 * builtin is immutable. The builtin could be renamed or intercepted.
1268 static Func* lookupBuiltin(const StringData* name);
1270 /////////////////////////////////////////////////////////////////////////////
1271 // SharedData.
1273 private:
1274 using NamedLocalsMap = IndexedStringMap<LowStringPtr, Id>;
1276 using BCPtr = TokenOrPtr<unsigned char>;
1277 using LineTablePtr = TokenOrPtr<LineTable>;
1279 // Some 16-bit values in SharedData are stored as small deltas if they fit
1280 // under this limit. If not, they're set to the limit value and an
1281 // ExtendedSharedData will be allocated for the full-width field.
1282 static constexpr auto kSmallDeltaLimit = uint16_t(-1);
1285 * Properties shared by all clones of a Func.
1287 struct SharedData : AtomicCountable {
1288 SharedData(BCPtr bc, Offset bclen, PreClass* preClass,
1289 int sn, int line1, int line2, bool isPhpLeafFn);
1290 ~SharedData();
1293 * Interface for AtomicCountable.
1295 void atomicRelease();
1297 Offset bclen() const;
1300 * Data fields are packed to minimize size. Try not to add anything new
1301 * here or reorder anything.
1303 // (There's a 32-bit integer in the AtomicCountable base class here.)
1304 LockFreePtrWrapper<BCPtr> m_bc;
1305 PreClass* m_preClass;
1306 int m_line1;
1307 ParamInfoVec m_params;
1308 NamedLocalsMap m_localNames;
1309 EHEntVec m_ehtab;
1310 StaticCoeffectNamesMap m_staticCoeffectNames;
1313 * Up to 16 bits.
1315 union Flags {
1316 struct {
1317 bool m_isClosureBody : true;
1318 bool m_isAsync : true;
1319 bool m_isGenerator : true;
1320 bool m_isPairGenerator : true;
1321 bool m_isGenerated : true;
1322 bool m_hasExtendedSharedData : true;
1323 bool m_returnByValue : true; // only for builtins
1324 bool m_isMemoizeWrapper : true;
1325 bool m_isMemoizeWrapperLSB : true;
1326 bool m_isKeyedByImplicitContextMemoize : true;
1327 bool m_isPhpLeafFn : true;
1328 bool m_hasReifiedGenerics : true;
1329 bool m_hasParamsWithMultiUBs : true;
1330 bool m_hasReturnWithMultiUBs : true;
1332 uint16_t m_allFlags;
1334 static_assert(sizeof(Flags) == sizeof(uint16_t));
1336 Flags m_allFlags;
1338 uint16_t m_sn;
1340 LowStringPtr m_retUserType;
1341 UserAttributeMap m_userAttributes;
1342 TypeConstraint m_retTypeConstraint; // NB: sizeof(TypeConstraint) == 12
1343 LowStringPtr m_originalFilename;
1344 RepoAuthType m_repoReturnType;
1345 RepoAuthType m_repoAwaitedReturnType;
1348 * The `line2' are likely to be small, particularly relative to m_line1,
1349 * so we encode each as a 16-bit difference.
1351 * If the delta doesn't fit, we need to have an ExtendedSharedData to hold
1352 * the real values---in that case, the field here that overflowed is set to
1353 * kSmallDeltaLimit and the corresponding field in ExtendedSharedData will
1354 * be valid.
1356 uint16_t m_line2Delta;
1359 * bclen is likely to be small. So we encode each as a 16-bit value
1361 * If the value doesn't fit, we need to have an ExtendedSharedData to hold
1362 * the real values---in that case, the field here that overflowed is set to
1363 * kSmallDeltaLimit and the corresponding field in ExtendedSharedData will
1364 * be valid.
1366 uint16_t m_bclenSmall;
1368 std::atomic<Offset> m_cti_base; // relative to CodeCache cti section
1369 uint32_t m_cti_size; // size of cti code
1370 uint16_t m_numLocals;
1371 uint16_t m_numIterators;
1373 mutable LockFreePtrWrapper<VMCompactVector<LineInfo>> m_lineMap;
1374 mutable LockFreePtrWrapper<LineTablePtr> m_lineTable;
1376 static_assert(CheckSize<SharedData, use_lowptr ? 160 : 184>(), "");
1379 * If this Func represents a native function or is exceptionally large
1380 * (line count or bytecode size), it requires extra information that most
1381 * Funcs don't need, so it's SharedData is actually one of these extended
1382 * SharedDatas.
1384 struct ExtendedSharedData : SharedData {
1385 template<class... Args>
1386 explicit ExtendedSharedData(Args&&... args)
1387 : SharedData(std::forward<Args>(args)...)
1389 m_allFlags.m_hasExtendedSharedData = true;
1391 ExtendedSharedData(const ExtendedSharedData&) = delete;
1392 ExtendedSharedData(ExtendedSharedData&&) = delete;
1393 ~ExtendedSharedData();
1395 ArFunction m_arFuncPtr;
1396 NativeFunction m_nativeFuncPtr;
1397 ReifiedGenericsInfo m_reifiedGenericsInfo;
1398 ParamUBMap m_paramUBs;
1399 UpperBoundVec m_returnUBs;
1400 CoeffectRules m_coeffectRules;
1401 Offset m_bclen; // Only read if SharedData::m_bclen is kSmallDeltaLimit
1402 int m_line2; // Only read if SharedData::m_line2 is kSmallDeltaLimit
1403 int m_sn; // Only read if SharedData::m_sn is kSmallDeltaLimit
1404 RuntimeCoeffects m_coeffectEscapes{RuntimeCoeffects::none()};
1405 int64_t m_dynCallSampleRate;
1406 LowStringPtr m_docComment;
1408 static_assert(CheckSize<ExtendedSharedData, use_lowptr ? 288 : 312>(), "");
1411 * SharedData accessors for internal use.
1413 const SharedData* shared() const { return m_shared.get(); }
1414 SharedData* shared() { return m_shared.get(); }
1417 * Returns ExtendedSharedData if we have one, or else a nullptr.
1419 const ExtendedSharedData* extShared() const;
1420 ExtendedSharedData* extShared();
1423 * We store 'detailed' line number information on a table on the side, because
1424 * in production modes for HHVM it's generally not useful (which keeps Func
1425 * smaller in that case)---this stuff is only used for the debugger, where we
1426 * can afford the lookup here. The normal Func m_lineMap is capable of
1427 * producing enough line number information for things needed in production
1428 * modes (backtraces, warnings, etc).
1431 struct ExtendedLineInfo {
1432 SourceLocTable sourceLocTable;
1435 * Map from source lines to a collection of all the bytecode ranges the line
1436 * encompasses.
1438 * The value type of the map is a list of offset ranges, so a single line
1439 * with several sub-statements may correspond to the bytecodes of all of the
1440 * sub-statements.
1442 * May not be initialized. Lookups need to check if it's empty() and if so
1443 * compute it from sourceLocTable.
1445 LineToOffsetRangeVecMap lineToOffsetRange;
1448 using ExtendedLineInfoCache = tbb::concurrent_hash_map<
1449 const SharedData*,
1450 ExtendedLineInfo,
1451 pointer_hash<SharedData>
1454 static ExtendedLineInfoCache s_extendedLineInfo;
1456 /////////////////////////////////////////////////////////////////////////////
1457 // Internal methods.
1459 // These are all used at emit-time, and should be outsourced to FuncEmitter.
1461 private:
1462 Func(const Func&) = default; // used for clone()
1463 Func& operator=(const Func&) = delete;
1464 void init(int numParams);
1465 void initPrologues(int numParams);
1466 void setFullName(int numParams);
1467 void finishedEmittingParams(std::vector<ParamInfo>& pBuilder);
1468 void setNamedEntity(const NamedEntity*);
1470 PC loadBytecode();
1472 /////////////////////////////////////////////////////////////////////////////
1473 // Internal types.
1475 struct ClonedFlag {
1476 ClonedFlag() {}
1477 ClonedFlag(const ClonedFlag&) {}
1478 ClonedFlag& operator=(const ClonedFlag&) = delete;
1480 std::atomic_flag flag = ATOMIC_FLAG_INIT;
1484 * Wrapper around std::atomic<Attr> that pretends like it's not atomic.
1486 * Func::m_attrs is only accessed by multiple threads in the closure scoping
1487 * process for Closure classes, which is synchronized in Class::rescope().
1488 * This wrapper is just to make m_attrs copy-constructible, and there should
1489 * never be a race when copying.
1491 struct AtomicAttr {
1492 AtomicAttr() {}
1493 explicit AtomicAttr(Attr attrs) : m_attrs{attrs} {}
1495 AtomicAttr(const AtomicAttr& o)
1496 : m_attrs{o.m_attrs.load(std::memory_order_relaxed)}
1499 AtomicAttr& operator=(Attr attrs) {
1500 m_attrs.store(attrs, std::memory_order_relaxed);
1501 return *this;
1504 /* implicit */ operator Attr() const {
1505 return m_attrs.load(std::memory_order_relaxed);
1508 private:
1509 std::atomic<Attr> m_attrs;
1512 public:
1513 #ifdef USE_LOWPTR
1514 using low_storage_t = uint32_t;
1515 #else
1516 using low_storage_t = uintptr_t;
1517 #endif
1519 private:
1521 * Lowptr wrapper around std::atomic<Union> for Class* or StringData*
1523 struct UnionWrapper {
1524 union U {
1525 low_storage_t m_cls;
1526 low_storage_t m_methCallerClsName;
1528 std::atomic<U> m_u;
1530 // constructors
1531 explicit UnionWrapper(Class *cls)
1532 : m_u([](Class *cls){
1533 U u;
1534 u.m_cls = to_low(cls);
1535 return u; }(cls)) {}
1536 explicit UnionWrapper(const StringData *name)
1537 : m_u([](const StringData *n){
1538 U u;
1539 u.m_methCallerClsName = to_low(n, kMethCallerBit);
1540 return u; }(name)) {}
1541 /* implicit */ UnionWrapper(std::nullptr_t /*px*/)
1542 : m_u([](){
1543 U u;
1544 u.m_cls = 0;
1545 return u; }()) {}
1546 UnionWrapper(const UnionWrapper& r) :
1547 m_u(r.m_u.load()) {
1550 // Assignments
1551 UnionWrapper& operator=(UnionWrapper r) {
1552 m_u.store(r.m_u, std::memory_order_relaxed);
1553 return *this;
1556 // setter & getter
1557 void setCls(Class *cls) {
1558 U u;
1559 u.m_cls = to_low(cls);
1560 m_u.store(u, std::memory_order_relaxed);
1562 Class* cls() const {
1563 auto cls = m_u.load(std::memory_order_relaxed).m_cls;
1564 assertx(!(cls & kMethCallerBit));
1565 return reinterpret_cast<Class*>(cls);
1567 StringData* name() const {
1568 auto n = m_u.load(std::memory_order_relaxed).m_methCallerClsName;
1569 assertx(n & kMethCallerBit);
1570 return reinterpret_cast<StringData*>(n - kMethCallerBit);
1574 template <class T>
1575 static Func::low_storage_t to_low(T* px, Func::low_storage_t bit = 0) {
1576 Func::low_storage_t ones = ~0;
1577 auto ptr = reinterpret_cast<uintptr_t>(px) | bit;
1578 always_assert((ptr & ones) == ptr);
1579 return (Func::low_storage_t)(ptr);
1582 /////////////////////////////////////////////////////////////////////////////
1583 // Atomic Flags.
1585 public:
1586 enum Flags : uint8_t {
1587 None = 0,
1588 Optimized = 1 << 0,
1589 Locked = 1 << 1,
1590 MaybeIntercepted = 1 << 2,
1594 * Wrapper around std::atomic<uint8_t> that enables it to be
1595 * copy constructable,
1597 struct AtomicFlags {
1598 AtomicFlags() {}
1600 AtomicFlags(const AtomicFlags&) {}
1601 AtomicFlags& operator=(const AtomicFlags&) = delete;
1603 bool set(Flags flags) {
1604 auto const prev = m_flags.fetch_or(flags, std::memory_order_release);
1605 return prev & flags;
1608 bool unset(Flags flags) {
1609 auto const prev =
1610 m_flags.fetch_and(~uint8_t(flags), std::memory_order_release);
1611 return prev & flags;
1614 bool check(Flags flags) const {
1615 return m_flags.load(std::memory_order_acquire) & flags;
1618 std::atomic<uint8_t> m_flags{Flags::None};
1621 inline AtomicFlags& atomicFlags() const {
1622 return m_atomicFlags;
1625 inline AtomicFlags& atomicFlags() {
1626 return m_atomicFlags;
1629 /////////////////////////////////////////////////////////////////////////////
1630 // Code locations. [const]
1633 * Get the line number corresponding to `offset'.
1635 * Return -1 if not found.
1637 int getLineNumber(Offset offset) const;
1640 * Get the SourceLoc corresponding to `offset'.
1642 * Return false if not found, else true.
1644 bool getSourceLoc(Offset offset, SourceLoc& sLoc) const;
1647 * Get the Offset range(s) corresponding to `offset'.
1649 * Return false if not found, else true.
1651 bool getOffsetRange(Offset offset, OffsetRange& range) const;
1653 void setLineTable(LineTable);
1654 void setLineTable(LineTablePtr::Token);
1656 void stashExtendedLineTable(SourceLocTable table) const;
1658 const SourceLocTable& getLocTable() const;
1660 LineToOffsetRangeVecMap getLineToOffsetRangeVecMap() const;
1662 const LineTable* getLineTable() const;
1663 LineTable getOrLoadLineTableCopy() const;
1665 private:
1666 const LineTable& getOrLoadLineTable() const;
1668 /////////////////////////////////////////////////////////////////////////////
1669 // Constants.
1671 private:
1672 static constexpr int kMagic = 0xba5eba11;
1673 static constexpr intptr_t kNeedsFullName = 0x1;
1675 public:
1676 // Use by m_inoutBits
1677 static constexpr uint32_t kInoutFastCheckBits = 31;
1679 static std::atomic<bool> s_treadmill;
1680 static std::atomic<uint32_t> s_totalClonedClosures;
1682 // To conserve space, we use unions for pairs of mutually exclusive fields
1683 static auto constexpr kMethCallerBit = 0x1; // set for m_methCaller
1684 /////////////////////////////////////////////////////////////////////////////
1685 // Data members.
1687 // The fields of Func are organized in reverse order of frequency of use.
1688 // Do not re-order without checking perf!
1690 private:
1691 #ifndef NDEBUG
1692 // For asserts only.
1693 int m_magic;
1694 #endif
1695 AtomicLowPtr<uint8_t> m_funcEntry{nullptr};
1696 #ifndef USE_LOWPTR
1697 FuncId m_funcId{FuncId::Invalid};
1698 #endif
1699 mutable AtomicLowPtr<const StringData> m_fullName{nullptr};
1700 LowStringPtr m_name{nullptr};
1702 union {
1703 // The first Class in the inheritance hierarchy that declared this method.
1704 // Note that this may be an abstract class that did not provide an
1705 // implementation.
1706 low_storage_t m_baseCls{0};
1707 // m_methCallerMethName can be accessed by meth_caller() only
1708 low_storage_t m_methCallerMethName;
1711 // m_u is used to represent
1712 // the Class that provided this method implementation, or
1713 // the class name provided by meth_caller()
1714 UnionWrapper m_u{nullptr};
1715 union {
1716 Slot m_methodSlot{0};
1717 LowPtr<const NamedEntity>::storage_type m_namedEntity;
1719 mutable ClonedFlag m_cloned;
1720 mutable AtomicFlags m_atomicFlags;
1721 bool m_isPreFunc : 1;
1722 bool m_hasPrivateAncestor : 1;
1723 bool m_shouldSampleJit : 1;
1724 bool m_hasForeignThis : 1;
1725 bool m_registeredInDataMap : 1;
1726 // 3 free bits + 1 free byte
1727 RuntimeCoeffects m_requiredCoeffects{RuntimeCoeffects::none()};
1728 int16_t m_maxStackCells{0};
1729 Unit* const m_unit;
1730 AtomicSharedPtr<SharedData> m_shared;
1731 // The lower 31 bits represent inout-ness of the corresponding parameter. The
1732 // highest bit is set if there is an inout parameter beyond the 0..31 range.
1733 // Initialized by Func::finishedEmittingParams.
1734 uint32_t m_inoutBits{0};
1735 // Initialized by Func::finishedEmittingParams. The least significant bit is
1736 // 1 if the last param is not variadic; the 31 most significant bits are the
1737 // total number of params (including the variadic param).
1738 uint32_t m_paramCounts{0};
1739 AtomicAttr m_attrs;
1740 // This must be the last field declared in this structure, and the Func class
1741 // should not be inherited from.
1742 AtomicLowPtr<uint8_t> m_prologueTable[1];
1744 static constexpr size_t kFuncSize = debug ? (use_lowptr ? 72 : 112)
1745 : (use_lowptr ? 64 : 104);
1746 static_assert(CheckSize<Func, kFuncSize>(), "");
1748 ///////////////////////////////////////////////////////////////////////////////
1751 * A prologue is identified by the called function and the number of arguments
1752 * that the prologue handles.
1754 struct PrologueID {
1755 PrologueID(FuncId funcId, uint32_t nargs)
1756 : m_funcId(funcId)
1757 , m_nargs(nargs)
1760 PrologueID(const Func* func, uint32_t nargs)
1761 : m_funcId(func->getFuncId())
1762 , m_nargs(nargs)
1765 PrologueID()
1768 FuncId funcId() const { return m_funcId; }
1769 uint32_t nargs() const { return m_nargs; }
1770 const Func* func() const { return Func::fromFuncId(m_funcId); }
1772 bool operator==(const PrologueID& other) const {
1773 return m_funcId == other.m_funcId && m_nargs == other.m_nargs;
1776 struct Eq {
1777 bool operator()(const PrologueID& pid1,
1778 const PrologueID& pid2) const {
1779 return pid1 == pid2;
1783 struct Hasher {
1784 size_t operator()(PrologueID pid) const {
1785 return pid.funcId().toInt() + (size_t(pid.nargs()) << 32);
1789 private:
1790 FuncId m_funcId{FuncId::Invalid};
1791 uint32_t m_nargs{0xffffffff};
1794 std::string show(PrologueID pid);
1796 ///////////////////////////////////////////////////////////////////////////////
1799 * Log meta-information about func. Records attributes, number of locals,
1800 * parameters, static locals, class ref slots, frame cells, high watermark,
1801 * and iterators. Does not record function name or class.
1803 void logFunc(const Func* func, StructuredLogEntry& ent);
1805 inline tracing::Props traceProps(const Func* f) {
1806 return tracing::Props{}.add("func_name", f->fullName());
1810 * Throw an exception that func cannot be converted to type.
1812 [[noreturn]] void invalidFuncConversion(const char* type);
1814 ///////////////////////////////////////////////////////////////////////////////
1815 // Bytecode
1818 * Report capacity of RepoAuthoritative mode bytecode arena.
1820 * Returns 0 if !RuntimeOption::RepoAuthoritative.
1822 size_t hhbc_arena_capacity();
1824 unsigned char* allocateBCRegion(const unsigned char* bc, size_t bclen);
1825 void freeBCRegion(const unsigned char* bc, size_t bclen);
1827 ///////////////////////////////////////////////////////////////////////////////
1831 #define incl_HPHP_VM_FUNC_INL_H_
1832 #include "hphp/runtime/vm/func-inl.h"
1833 #undef incl_HPHP_VM_FUNC_INL_H_