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"
32 namespace HPHP
{ namespace SystemLib
{
33 /////////////////////////////////////////////////////////////////////////////
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
;
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
;
53 Object
createAndConstruct(Class
* cls
, const Variant
& args
) {
55 tvDecRefGen(g_context
->invokeFunc(cls
->getCtor(), args
, inst
.get()));
60 * Fast path for Errors and Exceptions that do not override the default
61 * constructor or message property initializer. Does not reenter VM.
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());
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
);
84 bool s_inited
= false;
85 bool s_anyNonPersistentBuiltins
= false;
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
;
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(
183 make_packed_array(code
,
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
,
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
) {
306 void setupNullCtor(Class
* cls
) {
307 assertx(!s_nullCtor
);
310 Unit::lookupFunc(makeStaticString("__SystemLib\\__86null"));
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
));
324 /////////////////////////////////////////////////////////////////////////////
325 }} // namespace HPHP::SystemLib