Expose in_loop in Tast_env
[hiphop-php.git] / hphp / system / systemlib.cpp
blob888a4fd9c0df2ffb400f810785bdaa4afe68c183
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 #include "hphp/system/systemlib.h"
18 #include "hphp/runtime/base/array-init.h"
19 #include "hphp/runtime/base/builtin-functions.h"
20 #include "hphp/runtime/base/execution-context.h"
21 #include "hphp/runtime/base/init-fini-node.h"
22 #include "hphp/runtime/base/object-data.h"
23 #include "hphp/runtime/base/type-object.h"
24 #include "hphp/runtime/base/type-string.h"
25 #include "hphp/runtime/base/type-variant.h"
26 #include "hphp/runtime/base/types.h"
27 #include "hphp/runtime/vm/class.h"
28 #include "hphp/runtime/vm/unit.h"
30 #include <vector>
32 namespace HPHP { namespace SystemLib {
33 /////////////////////////////////////////////////////////////////////////////
35 namespace {
37 const StaticString s_message("message");
38 const StaticString s_code("code");
39 const Slot s_messageIdx{0};
40 const Slot s_codeIdx{2};
42 DEBUG_ONLY bool throwable_has_expected_props() {
43 auto const erCls = s_ErrorClass;
44 auto const exCls = s_ExceptionClass;
45 return
46 erCls->lookupDeclProp(s_message.get()) == s_messageIdx &&
47 exCls->lookupDeclProp(s_message.get()) == s_messageIdx &&
48 erCls->lookupDeclProp(s_code.get()) == s_codeIdx &&
49 exCls->lookupDeclProp(s_code.get()) == s_codeIdx;
52 ALWAYS_INLINE
53 Object createAndConstruct(Class* cls, const Variant& args) {
54 Object inst{cls};
55 tvDecRefGen(g_context->invokeFunc(cls->getCtor(), args, inst.get()));
56 return inst;
59 /**
60 * Fast path for Errors and Exceptions that do not override the default
61 * constructor or message property initializer. Does not reenter VM.
63 ALWAYS_INLINE
64 Object createAndConstructThrowable(Class* cls, const Variant& message) {
65 assertx(throwable_has_expected_props());
66 assertx(cls->getCtor() == s_ErrorClass->getCtor() ||
67 cls->getCtor() == s_ExceptionClass->getCtor());
69 Object inst{cls};
70 if (debug) {
71 DEBUG_ONLY auto const code_prop = inst->propRvalAtOffset(s_codeIdx);
72 assertx(isIntType(code_prop.type()));
73 assertx(code_prop.val().num == 0);
75 auto const message_prop = inst->propLvalAtOffset(s_messageIdx);
76 assertx(isStringType(message_prop.type()));
77 assertx(message_prop.val().pstr == staticEmptyString());
78 cellDup(*message.asCell(), message_prop);
79 return inst;
84 bool s_inited = false;
85 bool s_anyNonPersistentBuiltins = false;
86 std::string s_source;
87 Unit* s_unit = nullptr;
88 Unit* s_hhas_unit = nullptr;
89 Unit* s_nativeFuncUnit = nullptr;
90 Unit* s_nativeClassUnit = nullptr;
91 Func* s_nullFunc = nullptr;
92 Func* s_nullCtor = nullptr;
94 /////////////////////////////////////////////////////////////////////////////
96 #define DEFINE_SYSTEMLIB_CLASS(cls) \
97 Class* s_ ## cls ## Class = nullptr;
98 SYSTEMLIB_CLASSES(DEFINE_SYSTEMLIB_CLASS)
99 #undef DEFINE_SYSTEMLIB_CLASS
101 Class* s_ThrowableClass;
102 Class* s_BaseExceptionClass;
103 Class* s_ErrorClass;
104 Class* s_ArithmeticErrorClass;
105 Class* s_ArgumentCountErrorClass;
106 Class* s_AssertionErrorClass;
107 Class* s_DivisionByZeroErrorClass;
108 Class* s_ParseErrorClass;
109 Class* s_TypeErrorClass;
111 Object AllocStdClassObject() {
112 return Object{s_stdclassClass};
115 Object AllocPinitSentinel() {
116 return Object{s_pinitSentinelClass};
119 Object AllocExceptionObject(const Variant& message) {
120 return createAndConstructThrowable(s_ExceptionClass, message);
123 Object AllocErrorObject(const Variant& message) {
124 return createAndConstructThrowable(s_ErrorClass, message);
127 Object AllocArithmeticErrorObject(const Variant& message) {
128 return createAndConstructThrowable(s_ArithmeticErrorClass, message);
131 Object AllocArgumentCountErrorObject(const Variant& message) {
132 return createAndConstructThrowable(s_ArgumentCountErrorClass, message);
135 Object AllocDivisionByZeroErrorObject(const Variant& message) {
136 return createAndConstructThrowable(s_DivisionByZeroErrorClass, message);
139 Object AllocParseErrorObject(const Variant& message) {
140 return createAndConstructThrowable(s_ParseErrorClass, message);
143 Object AllocTypeErrorObject(const Variant& message) {
144 return createAndConstructThrowable(s_TypeErrorClass, message);
147 Object AllocBadMethodCallExceptionObject(const Variant& message) {
148 return createAndConstructThrowable(s_BadMethodCallExceptionClass, message);
151 Object AllocInvalidArgumentExceptionObject(const Variant& message) {
152 return createAndConstructThrowable(s_InvalidArgumentExceptionClass, message);
155 Object AllocTypeAssertionExceptionObject(const Variant& message) {
156 return createAndConstructThrowable(s_TypeAssertionExceptionClass, message);
159 Object AllocRuntimeExceptionObject(const Variant& message) {
160 return createAndConstructThrowable(s_RuntimeExceptionClass, message);
163 Object AllocOutOfBoundsExceptionObject(const Variant& message) {
164 return createAndConstructThrowable(s_OutOfBoundsExceptionClass, message);
167 Object AllocInvalidOperationExceptionObject(const Variant& message) {
168 return createAndConstructThrowable(s_InvalidOperationExceptionClass, message);
171 Object AllocDOMExceptionObject(const Variant& message) {
172 return createAndConstructThrowable(s_DOMExceptionClass, message);
175 Object AllocSoapFaultObject(const Variant& code,
176 const Variant& message,
177 const Variant& actor /* = uninit_variant */,
178 const Variant& detail /* = uninit_variant */,
179 const Variant& name /* = uninit_variant */,
180 const Variant& header /* = uninit_variant */) {
181 return createAndConstruct(
182 s_SoapFaultClass,
183 make_packed_array(code,
184 message,
185 actor,
186 detail,
187 name,
188 header
193 Object AllocLazyKVZipIterableObject(const Variant& mp) {
194 return createAndConstruct(s_LazyKVZipIterableClass,
195 make_packed_array(mp));
198 Object AllocLazyIterableViewObject(const Variant& iterable) {
199 return createAndConstruct(s_LazyIterableViewClass,
200 make_packed_array(iterable));
203 Object AllocLazyKeyedIterableViewObject(const Variant& iterable) {
204 return createAndConstruct(s_LazyKeyedIterableViewClass,
205 make_packed_array(iterable));
208 void throwExceptionObject(const Variant& message) {
209 throw_object(AllocExceptionObject(message));
212 void throwErrorObject(const Variant& message) {
213 throw_object(AllocErrorObject(message));
216 void throwArithmeticErrorObject(const Variant& message) {
217 throw_object(AllocArithmeticErrorObject(message));
220 void throwArgumentCountErrorObject(const Variant& message) {
221 throw_object(AllocArgumentCountErrorObject(message));
224 void throwDivisionByZeroErrorObject(const Variant& message) {
225 throw_object(AllocDivisionByZeroErrorObject(message));
228 void throwParseErrorObject(const Variant& message) {
229 throw_object(AllocParseErrorObject(message));
232 void throwTypeErrorObject(const Variant& message) {
233 throw_object(AllocTypeErrorObject(message));
236 void throwBadMethodCallExceptionObject(const Variant& message) {
237 throw_object(AllocBadMethodCallExceptionObject(message));
240 void throwInvalidArgumentExceptionObject(const Variant& message) {
241 throw_object(AllocInvalidArgumentExceptionObject(message));
244 void throwTypeAssertionExceptionObject(const Variant& message) {
245 throw_object(AllocTypeAssertionExceptionObject(message));
248 void throwRuntimeExceptionObject(const Variant& message) {
249 throw_object(AllocRuntimeExceptionObject(message));
252 void throwOutOfBoundsExceptionObject(const Variant& message) {
253 throw_object(AllocOutOfBoundsExceptionObject(message));
256 void throwInvalidOperationExceptionObject(const Variant& message) {
257 throw_object(AllocInvalidOperationExceptionObject(message));
260 void throwDOMExceptionObject(const Variant& message) {
261 throw_object(AllocDOMExceptionObject(message));
264 void throwSoapFaultObject(const Variant& code,
265 const Variant& message,
266 const Variant& actor /* = uninit_variant */,
267 const Variant& detail /* = uninit_variant */,
268 const Variant& name /* = uninit_variant */,
269 const Variant& header /* = uninit_variant */) {
270 throw_object(Object{AllocSoapFaultObject(code, message,
271 actor, detail,
272 name, header)});
275 #define ALLOC_OBJECT_STUB(name) \
276 Object Alloc##name##Object() { \
277 return Object{s_##name##Class}; \
280 ALLOC_OBJECT_STUB(Directory);
281 ALLOC_OBJECT_STUB(PDOException);
283 #undef ALLOC_OBJECT_STUB
285 /////////////////////////////////////////////////////////////////////////////
287 static std::vector<Unit*> s_persistent_units;
289 /* To be called during process startup ONLY, before threads are spun up.
290 * Typically this will be called by HPHP::Extension::moduleInit to load an
291 * extension-specific systemlib file, or to load the main systemlib.
293 void addPersistentUnit(Unit* unit) {
294 s_persistent_units.push_back(unit);
297 /* Typically called between requests in non-RepoAuthoritative mode
298 * when function renaming is enabled.
300 void mergePersistentUnits() {
301 for (auto unit : s_persistent_units) {
302 unit->merge();
306 void setupNullCtor(Class* cls) {
307 assertx(!s_nullCtor);
308 if (!s_nullFunc) {
309 s_nullFunc =
310 Unit::lookupFunc(makeStaticString("__SystemLib\\__86null"));
311 assertx(s_nullFunc);
314 auto clone = s_nullFunc->clone(cls, makeStaticString("86ctor"));
315 clone->setNewFuncId();
316 clone->setAttrs(static_cast<Attr>(
317 AttrPublic | AttrNoInjection |
318 AttrPhpLeafFn | AttrSkipFrame |
319 AttrRequiresThis | AttrHasForeignThis |
320 AttrDynamicallyCallable));
321 s_nullCtor = clone;
324 /////////////////////////////////////////////////////////////////////////////
325 }} // namespace HPHP::SystemLib