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 +----------------------------------------------------------------------+
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"
29 #include "hphp/runtime/vm/rx.h"
33 namespace HPHP
{ namespace SystemLib
{
34 /////////////////////////////////////////////////////////////////////////////
38 const StaticString
s_message("message");
39 const StaticString
s_code("code");
40 const Slot s_messageIdx
{0};
41 const Slot s_codeIdx
{2};
43 DEBUG_ONLY
bool throwable_has_expected_props() {
44 auto const erCls
= s_ErrorClass
;
45 auto const exCls
= s_ExceptionClass
;
46 if (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 // Check that we have the expected type-hints on these props so we don't need
53 // to verify anything.
55 erCls
->declPropTypeConstraint(s_messageIdx
).isString() &&
56 exCls
->declPropTypeConstraint(s_messageIdx
).isString() &&
57 erCls
->declPropTypeConstraint(s_codeIdx
).isInt() &&
58 exCls
->declPropTypeConstraint(s_codeIdx
).isInt();
62 Object
createAndConstruct(Class
* cls
, const Array
& args
) {
64 tvDecRefGen(g_context
->invokeFunc(cls
->getCtor(), args
, inst
.get()));
69 * Fast path for Errors and Exceptions that do not override the default
70 * constructor or message property initializer. Does not reenter VM.
73 Object
createAndConstructThrowable(Class
* cls
, const Variant
& message
) {
74 assertx(throwable_has_expected_props());
75 assertx(cls
->getCtor() == s_ErrorClass
->getCtor() ||
76 cls
->getCtor() == s_ExceptionClass
->getCtor());
80 DEBUG_ONLY
auto const code_prop
= inst
->propRvalAtOffset(s_codeIdx
);
81 assertx(isIntType(code_prop
.type()));
82 assertx(code_prop
.val().num
== 0);
84 auto const message_prop
= inst
->propLvalAtOffset(s_messageIdx
);
85 assertx(isStringType(message_prop
.type()));
86 assertx(message_prop
.val().pstr
== staticEmptyString());
87 tvDup(*message
.asTypedValue(), message_prop
);
93 bool s_inited
= false;
94 bool s_anyNonPersistentBuiltins
= false;
96 Unit
* s_unit
= nullptr;
97 Unit
* s_hhas_unit
= nullptr;
98 Func
* s_nullFunc
= nullptr;
99 Func
* s_singleArgNullFunc
= nullptr;
100 Func
* s_nullCtor
= nullptr;
102 /////////////////////////////////////////////////////////////////////////////
104 #define DEFINE_SYSTEMLIB_CLASS(cls) \
105 Class* s_ ## cls ## Class = nullptr;
106 SYSTEMLIB_CLASSES(DEFINE_SYSTEMLIB_CLASS
)
107 #undef DEFINE_SYSTEMLIB_CLASS
109 #define DEFINE_SYSTEMLIB_HH_CLASS(cls) \
110 Class* s_HH_ ## cls ## Class = nullptr;
111 SYSTEMLIB_HH_CLASSES(DEFINE_SYSTEMLIB_HH_CLASS
)
112 #undef DEFINE_SYSTEMLIB_HH_CLASS
114 Class
* s_ThrowableClass
;
115 Class
* s_BaseExceptionClass
;
117 Class
* s_ArithmeticErrorClass
;
118 Class
* s_ArgumentCountErrorClass
;
119 Class
* s_AssertionErrorClass
;
120 Class
* s_DivisionByZeroErrorClass
;
121 Class
* s_ParseErrorClass
;
122 Class
* s_TypeErrorClass
;
124 Object
AllocStdClassObject() {
125 return Object
{s_stdclassClass
};
128 Object
AllocPinitSentinel() {
129 return Object
{s_pinitSentinelClass
};
132 Object
AllocExceptionObject(const Variant
& message
) {
133 return createAndConstructThrowable(s_ExceptionClass
, message
);
136 Object
AllocErrorObject(const Variant
& message
) {
137 return createAndConstructThrowable(s_ErrorClass
, message
);
140 Object
AllocArithmeticErrorObject(const Variant
& message
) {
141 return createAndConstructThrowable(s_ArithmeticErrorClass
, message
);
144 Object
AllocArgumentCountErrorObject(const Variant
& message
) {
145 return createAndConstructThrowable(s_ArgumentCountErrorClass
, message
);
148 Object
AllocDivisionByZeroErrorObject(const Variant
& message
) {
149 return createAndConstructThrowable(s_DivisionByZeroErrorClass
, message
);
152 Object
AllocParseErrorObject(const Variant
& message
) {
153 return createAndConstructThrowable(s_ParseErrorClass
, message
);
156 Object
AllocTypeErrorObject(const Variant
& message
) {
157 return createAndConstructThrowable(s_TypeErrorClass
, message
);
160 Object
AllocBadMethodCallExceptionObject(const Variant
& message
) {
161 return createAndConstructThrowable(s_BadMethodCallExceptionClass
, message
);
164 Object
AllocInvalidArgumentExceptionObject(const Variant
& message
) {
165 return createAndConstructThrowable(s_InvalidArgumentExceptionClass
, message
);
168 Object
AllocTypeAssertionExceptionObject(const Variant
& message
) {
169 return createAndConstructThrowable(s_TypeAssertionExceptionClass
, message
);
172 Object
AllocRuntimeExceptionObject(const Variant
& message
) {
173 return createAndConstructThrowable(s_RuntimeExceptionClass
, message
);
176 Object
AllocOutOfBoundsExceptionObject(const Variant
& message
) {
177 return createAndConstructThrowable(s_OutOfBoundsExceptionClass
, message
);
180 Object
AllocInvalidOperationExceptionObject(const Variant
& message
) {
181 return createAndConstructThrowable(s_InvalidOperationExceptionClass
, message
);
184 Object
AllocDOMExceptionObject(const Variant
& message
) {
185 return createAndConstructThrowable(s_DOMExceptionClass
, message
);
188 Object
AllocDivisionByZeroExceptionObject() {
189 return createAndConstructThrowable(s_DivisionByZeroExceptionClass
,
190 Strings::DIVISION_BY_ZERO
);
193 Object
AllocSoapFaultObject(const Variant
& code
,
194 const Variant
& message
,
195 const Variant
& actor
/* = uninit_variant */,
196 const Variant
& detail
/* = uninit_variant */,
197 const Variant
& name
/* = uninit_variant */,
198 const Variant
& header
/* = uninit_variant */) {
199 return createAndConstruct(
201 make_varray(code
, message
, actor
, detail
, name
, header
)
205 Object
AllocLazyKVZipIterableObject(const Variant
& mp
) {
206 return createAndConstruct(s_LazyKVZipIterableClass
,
210 Object
AllocLazyIterableViewObject(const Variant
& iterable
) {
211 return createAndConstruct(s_LazyIterableViewClass
,
212 make_varray(iterable
));
215 Object
AllocLazyKeyedIterableViewObject(const Variant
& iterable
) {
216 return createAndConstruct(s_LazyKeyedIterableViewClass
,
217 make_varray(iterable
));
220 void throwExceptionObject(const Variant
& message
) {
221 throw_object(AllocExceptionObject(message
));
224 void throwErrorObject(const Variant
& message
) {
225 throw_object(AllocErrorObject(message
));
228 void throwArithmeticErrorObject(const Variant
& message
) {
229 throw_object(AllocArithmeticErrorObject(message
));
232 void throwArgumentCountErrorObject(const Variant
& message
) {
233 throw_object(AllocArgumentCountErrorObject(message
));
236 void throwDivisionByZeroErrorObject(const Variant
& message
) {
237 throw_object(AllocDivisionByZeroErrorObject(message
));
240 void throwParseErrorObject(const Variant
& message
) {
241 throw_object(AllocParseErrorObject(message
));
244 void throwTypeErrorObject(const Variant
& message
) {
245 throw_object(AllocTypeErrorObject(message
));
248 void throwBadMethodCallExceptionObject(const Variant
& message
) {
249 throw_object(AllocBadMethodCallExceptionObject(message
));
252 void throwInvalidArgumentExceptionObject(const Variant
& message
) {
253 throw_object(AllocInvalidArgumentExceptionObject(message
));
256 void throwTypeAssertionExceptionObject(const Variant
& message
) {
257 throw_object(AllocTypeAssertionExceptionObject(message
));
260 void throwRuntimeExceptionObject(const Variant
& message
) {
261 throw_object(AllocRuntimeExceptionObject(message
));
264 void throwOutOfBoundsExceptionObject(const Variant
& message
) {
265 throw_object(AllocOutOfBoundsExceptionObject(message
));
268 void throwInvalidOperationExceptionObject(const Variant
& message
) {
269 throw_object(AllocInvalidOperationExceptionObject(message
));
272 void throwDOMExceptionObject(const Variant
& message
) {
273 throw_object(AllocDOMExceptionObject(message
));
276 void throwDivisionByZeroExceptionObject() {
277 throw_object(AllocDivisionByZeroExceptionObject());
280 void throwSoapFaultObject(const Variant
& code
,
281 const Variant
& message
,
282 const Variant
& actor
/* = uninit_variant */,
283 const Variant
& detail
/* = uninit_variant */,
284 const Variant
& name
/* = uninit_variant */,
285 const Variant
& header
/* = uninit_variant */) {
286 throw_object(Object
{AllocSoapFaultObject(code
, message
,
291 #define ALLOC_OBJECT_STUB(name) \
292 Object Alloc##name##Object() { \
293 return Object{s_##name##Class}; \
296 ALLOC_OBJECT_STUB(Directory
);
297 ALLOC_OBJECT_STUB(PDOException
);
299 #undef ALLOC_OBJECT_STUB
301 /////////////////////////////////////////////////////////////////////////////
303 static std::vector
<Unit
*> s_persistent_units
;
305 /* To be called during process startup ONLY, before threads are spun up.
306 * Typically this will be called by HPHP::Extension::moduleInit to load an
307 * extension-specific systemlib file, or to load the main systemlib.
309 void addPersistentUnit(Unit
* unit
) {
310 s_persistent_units
.push_back(unit
);
313 /* Typically called between requests in non-RepoAuthoritative mode
314 * when function renaming is enabled.
316 void mergePersistentUnits() {
317 for (auto unit
: s_persistent_units
) {
324 Func
* setupNullClsMethod(Func
* f
, Class
* cls
, StringData
* name
) {
325 assertx(f
&& f
->isPhpLeafFn());
326 auto clone
= f
->clone(cls
, name
);
327 clone
->setNewFuncId();
328 clone
->setAttrs(static_cast<Attr
>(
329 AttrPublic
| AttrNoInjection
| AttrDynamicallyCallable
) |
330 rxMakeAttr(RxLevel::Rx
, false));
334 Func
* setup86ctorMethod(Class
* cls
) {
337 Unit::lookupFunc(makeStaticString("__SystemLib\\__86null"));
339 return setupNullClsMethod(s_nullFunc
, cls
, s_86ctor
.get());
342 Func
* setup86ReifiedInitMethod(Class
* cls
) {
343 if (!s_singleArgNullFunc
) {
344 s_singleArgNullFunc
=
345 Unit::lookupFunc(makeStaticString("__SystemLib\\__86single_arg_null"));
347 return setupNullClsMethod(s_singleArgNullFunc
, cls
, s_86reifiedinit
.get());
352 void setupNullCtor(Class
* cls
) {
353 assertx(!s_nullCtor
);
354 s_nullCtor
= setup86ctorMethod(cls
);
355 s_nullCtor
->setHasForeignThis(true);
358 Func
* getNull86reifiedinit(Class
* cls
) {
359 auto f
= setup86ReifiedInitMethod(cls
);
361 f
->setGenerated(true);
365 /////////////////////////////////////////////////////////////////////////////
366 }} // namespace HPHP::SystemLib