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