2 +----------------------------------------------------------------------+
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 +----------------------------------------------------------------------+
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"
44 ///////////////////////////////////////////////////////////////////////////////
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 ///////////////////////////////////////////////////////////////////////////////
75 * Exception handler table entry.
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
116 * | prologues at end of Func |
117 * +--------------------------------+ Func* address
118 * | [additional prologues] |
119 * +--------------------------------+ high address
123 friend struct FuncEmitter
;
124 friend struct UnitEmitter
;
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
;
131 /////////////////////////////////////////////////////////////////////////////
135 * Parameter default value info.
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
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.
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
);
194 * Allocate memory for a function, including the variable number of prologues
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
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()
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;
259 * Reserve the next available FuncId for `this', and add `this' to the
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.
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
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
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
323 * Consequently, none of these methods should be used to test whether the
324 * function is a method; for that purpose, see isMethod().
327 PreClass
* preClass() const;
328 bool hasBaseCls() const;
329 Class
* baseCls() const;
330 Class
* implCls() 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;
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.
393 * The system- or user-defined doc comment accompanying the function.
395 const StringData
* docComment() const;
397 /////////////////////////////////////////////////////////////////////////////
401 * Get the function's main entrypoint.
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;
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
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
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
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
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 /////////////////////////////////////////////////////////////////////////////
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 /////////////////////////////////////////////////////////////////////////////
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 /////////////////////////////////////////////////////////////////////////////
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
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
930 bool isImmutableFrom(const Class
* cls
) const;
932 /////////////////////////////////////////////////////////////////////////////
933 // Other attributes. [const]
936 * Get the system and coeffect attributes of the function.
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
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 /////////////////////////////////////////////////////////////////////////////
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]
1071 , stopOffset(kInvalidOffset
)
1076 PrintOpts
& noName() {
1081 PrintOpts
& noMetadata() {
1086 PrintOpts
& noBytecode() {
1087 startOffset
= kInvalidOffset
;
1088 stopOffset
= kInvalidOffset
;
1092 PrintOpts
& range(Offset start
, Offset stop
) {
1093 startOffset
= start
;
1098 PrintOpts
& noLineNumbers() {
1103 PrintOpts
& indent(int i
) {
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 /////////////////////////////////////////////////////////////////////////////
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
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
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 /////////////////////////////////////////////////////////////////////////////
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]
1195 static constexpr ptrdiff_t f##Off() { \
1196 return offsetof(Func, m_##f); \
1199 OFF(requiredCoeffects
)
1207 OFF(methCallerMethName
)
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 /////////////////////////////////////////////////////////////////////////////
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 /////////////////////////////////////////////////////////////////////////////
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
);
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
;
1307 ParamInfoVec m_params
;
1308 NamedLocalsMap m_localNames
;
1310 StaticCoeffectNamesMap m_staticCoeffectNames
;
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));
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
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
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
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
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
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
<
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.
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
*);
1472 /////////////////////////////////////////////////////////////////////////////
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.
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
);
1504 /* implicit */ operator Attr() const {
1505 return m_attrs
.load(std::memory_order_relaxed
);
1509 std::atomic
<Attr
> m_attrs
;
1514 using low_storage_t
= uint32_t;
1516 using low_storage_t
= uintptr_t;
1521 * Lowptr wrapper around std::atomic<Union> for Class* or StringData*
1523 struct UnionWrapper
{
1525 low_storage_t m_cls
;
1526 low_storage_t m_methCallerClsName
;
1531 explicit UnionWrapper(Class
*cls
)
1532 : m_u([](Class
*cls
){
1534 u
.m_cls
= to_low(cls
);
1535 return u
; }(cls
)) {}
1536 explicit UnionWrapper(const StringData
*name
)
1537 : m_u([](const StringData
*n
){
1539 u
.m_methCallerClsName
= to_low(n
, kMethCallerBit
);
1540 return u
; }(name
)) {}
1541 /* implicit */ UnionWrapper(std::nullptr_t
/*px*/)
1546 UnionWrapper(const UnionWrapper
& r
) :
1551 UnionWrapper
& operator=(UnionWrapper r
) {
1552 m_u
.store(r
.m_u
, std::memory_order_relaxed
);
1557 void setCls(Class
*cls
) {
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
);
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 /////////////////////////////////////////////////////////////////////////////
1586 enum Flags
: uint8_t {
1590 MaybeIntercepted
= 1 << 2,
1594 * Wrapper around std::atomic<uint8_t> that enables it to be
1595 * copy constructable,
1597 struct 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
) {
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;
1666 const LineTable
& getOrLoadLineTable() const;
1668 /////////////////////////////////////////////////////////////////////////////
1672 static constexpr int kMagic
= 0xba5eba11;
1673 static constexpr intptr_t kNeedsFullName
= 0x1;
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 /////////////////////////////////////////////////////////////////////////////
1687 // The fields of Func are organized in reverse order of frequency of use.
1688 // Do not re-order without checking perf!
1692 // For asserts only.
1695 AtomicLowPtr
<uint8_t> m_funcEntry
{nullptr};
1697 FuncId m_funcId
{FuncId::Invalid
};
1699 mutable AtomicLowPtr
<const StringData
> m_fullName
{nullptr};
1700 LowStringPtr m_name
{nullptr};
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
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};
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};
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};
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.
1755 PrologueID(FuncId funcId
, uint32_t nargs
)
1760 PrologueID(const Func
* func
, uint32_t nargs
)
1761 : m_funcId(func
->getFuncId())
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
;
1777 bool operator()(const PrologueID
& pid1
,
1778 const PrologueID
& pid2
) const {
1779 return pid1
== pid2
;
1784 size_t operator()(PrologueID pid
) const {
1785 return pid
.funcId().toInt() + (size_t(pid
.nargs()) << 32);
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 ///////////////////////////////////////////////////////////////////////////////
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_