Remove .hh_file from hhas
[hiphop-php.git] / hphp / runtime / vm / interp-helpers.h
blobe874b3716df6538d74c1ab63bc641e6646d11056
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_VM_INTERP_HELPERS_H_
18 #define incl_HPHP_VM_INTERP_HELPERS_H_
20 #include "hphp/runtime/base/builtin-functions.h"
21 #include "hphp/runtime/base/exceptions.h"
22 #include "hphp/runtime/base/runtime-error.h"
23 #include "hphp/runtime/base/runtime-option.h"
24 #include "hphp/runtime/base/request-info.h"
25 #include "hphp/runtime/vm/act-rec.h"
26 #include "hphp/runtime/vm/bytecode.h"
27 #include "hphp/runtime/vm/func.h"
28 #include "hphp/runtime/vm/hhbc.h"
29 #include "hphp/runtime/vm/runtime.h"
30 #include "hphp/runtime/vm/rx.h"
31 #include "hphp/util/text-util.h"
32 #include "hphp/util/trace.h"
34 #include <folly/Random.h>
36 namespace HPHP {
38 inline void callerInOutChecks(const Func* func, const FCallArgs& fca) {
39 for (auto i = 0; i < fca.numArgs; ++i) {
40 auto const inout = func->isInOut(i);
41 if (inout != fca.isInOut(i)) {
42 SystemLib::throwInvalidArgumentExceptionObject(
43 formatParamInOutMismatch(func->fullName()->data(), i, inout));
48 inline void callerDynamicCallChecks(const Func* func,
49 bool allowDynCallNoPointer = false) {
50 auto dynCallable = func->isDynamicallyCallable();
51 if (dynCallable) {
52 if (allowDynCallNoPointer) return;
53 if (!RO::EvalForbidDynamicCallsWithAttr) return;
55 auto level = func->isMethod()
56 ? (func->isStatic()
57 ? RO::EvalForbidDynamicCallsToClsMeth
58 : RO::EvalForbidDynamicCallsToInstMeth)
59 : RO::EvalForbidDynamicCallsToFunc;
60 if (level <= 0) return;
62 if (auto const rate = func->dynCallSampleRate()) {
63 if (folly::Random::rand32(*rate) != 0) return;
64 level = 1;
67 auto error_msg = dynCallable ?
68 Strings::FUNCTION_CALLED_DYNAMICALLY_WITH_ATTRIBUTE :
69 Strings::FUNCTION_CALLED_DYNAMICALLY_WITHOUT_ATTRIBUTE;
70 if (level >= 3 || (level >= 2 && !dynCallable)) {
71 std::string msg;
72 string_printf(msg, error_msg, func->fullName()->data());
73 throw_invalid_operation_exception(makeStaticString(msg));
75 raise_notice(error_msg, func->fullName()->data());
78 inline void callerDynamicConstructChecks(const Class* cls) {
79 auto level = RO::EvalForbidDynamicConstructs;
80 if (level <= 0 || cls->isDynamicallyConstructible()) return;
82 if (auto const rate = cls->dynConstructSampleRate()) {
83 if (folly::Random::rand32(*rate) != 0) return;
84 level = 1;
87 if (level >= 2) {
88 std::string msg;
89 string_printf(
90 msg,
91 Strings::CLASS_CONSTRUCTED_DYNAMICALLY,
92 cls->name()->data()
94 throw_invalid_operation_exception(makeStaticString(msg));
95 } else {
96 raise_notice(
97 Strings::CLASS_CONSTRUCTED_DYNAMICALLY,
98 cls->name()->data()
103 inline void calleeDynamicCallChecks(const Func* func, bool dynamicCall,
104 bool allowDynCallNoPointer = false) {
105 if (!dynamicCall) return;
106 if (func->isDynamicallyCallable() && allowDynCallNoPointer) return;
108 auto error_msg = func->isDynamicallyCallable() ?
109 Strings::FUNCTION_CALLED_DYNAMICALLY_WITH_ATTRIBUTE :
110 Strings::FUNCTION_CALLED_DYNAMICALLY_WITHOUT_ATTRIBUTE;
112 if (RuntimeOption::EvalNoticeOnBuiltinDynamicCalls && func->isBuiltin()) {
113 raise_notice(
114 error_msg,
115 func->fullName()->data()
121 * Check if a call from `caller` to `callee` satisfies reactivity constraints.
122 * Returns true if yes, otherwise raise a warning and return false or raise
123 * an exception.
125 inline bool callerRxChecks(const ActRec* caller, const Func* callee) {
126 if (RuntimeOption::EvalRxEnforceCalls <= 0) return true;
127 // Conditional reactivity is not tracked yet, so assume the caller has minimum
128 // and the callee has maximum possible level of reactivity.
129 auto const callerLevel = caller->rxMinLevel();
130 if (!rxEnforceCallsInLevel(callerLevel)) return true;
132 auto const minReqCalleeLevel = rxRequiredCalleeLevel(callerLevel);
133 if (LIKELY(callee->rxLevel() >= minReqCalleeLevel)) return true;
134 raiseRxCallViolation(caller, callee);
135 return false;
139 * This helper only does a stack overflow check for the native stack.
140 * Both native and VM stack overflows are independently possible.
142 inline void checkNativeStack() {
143 // Check whether we're going out of bounds of our native stack.
144 if (LIKELY(stack_in_bounds())) return;
145 TRACE_MOD(Trace::gc, 1, "Maximum stack depth exceeded.\n");
146 throw_stack_overflow();
150 * This helper does a stack overflow check on *both* the native stack
151 * and the VM stack.
153 * In some cases for re-entry, we're checking for space other than
154 * just the callee, and `extraCells' may need to be passed with a
155 * non-zero value. (We over-check in these situations, but it's fine.)
157 ALWAYS_INLINE
158 void checkStack(Stack& stk, const Func* f, int32_t extraCells) {
160 * Check whether func's maximum stack usage would overflow the stack.
161 * Both native and VM stack overflows are independently possible.
163 * All stack checks are inflated by kStackCheckPadding to ensure
164 * there is space both for calling leaf functions /and/ for
165 * re-entry. (See kStackCheckReenterPadding and
166 * kStackCheckLeafPadding.)
168 auto limit = f->maxStackCells() + kStackCheckPadding + extraCells;
169 if (LIKELY(stack_in_bounds() && !stk.wouldOverflow(limit))) return;
170 TRACE_MOD(Trace::gc, 1, "Maximum stack depth exceeded.\n");
171 throw_stack_overflow();
175 #endif