No more RefData struct
[hiphop-php.git] / hphp / runtime / vm / native.h
blob16afbb516e673a10123c6cb064035c6382c1c13a
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 +----------------------------------------------------------------------+
16 #ifndef incl_HPHP_RUNTIME_VM_NATIVE_H
17 #define incl_HPHP_RUNTIME_VM_NATIVE_H
19 #include "hphp/runtime/base/type-string.h"
20 #include "hphp/runtime/base/typed-value.h"
21 #include "hphp/runtime/base/tv-mutate.h"
22 #include "hphp/runtime/base/tv-variant.h"
24 #include "hphp/runtime/vm/func.h"
25 #include "hphp/runtime/vm/class-meth-data-ref.h"
26 #include "hphp/util/abi-cxx.h"
28 #include <type_traits>
30 namespace HPHP {
31 struct ActRec;
32 struct Class;
33 struct FuncEmitter;
34 struct Object;
35 struct Extension;
38 /* Macros related to declaring/registering internal implementations
39 * of <<__Native>> global functions.
41 * Declare a function in ext_foo.h using:
42 * ReturnType HHVM_FUNCTION(functionName, parameterList...)
43 * For example:
44 * int64_t HHVM_FUNCTION(sum, int64_t a, int64_t b) {
45 * return a + b;
46 * }
48 * Then register it from your Extension's moduleLoad() hook:
49 * void moduleLoad(const IniSetting::Map& ini, Hdf config) override {
50 * HHVM_FE(sum);
51 * }
53 * To finish exposing it to PHP, add an entry to Systemlib
54 * using matching hack typehints:
55 * <?php
56 * <<__Native>>
57 * function sum(int $a, int $b): int;
59 ****************************************************************************
61 * For functions with variadic args or other "special" handling,
62 * declare the prototype as a BuiltinFuncPtr:
63 * TypedValue* HHVM_FN(sum)(ActRec* ar) { ... }
64 * And declare it in Systemlib with the "ActRec" subattribute
65 * <?php
66 * <<__Native("ActRec")>>
67 * function sum(int $a, int $b): int;
68 * Registering the function in moduleLoad() remains the same.
70 ****************************************************************************
72 * If, for whatever reason, the standard declaration doesn't work,
73 * you may declare the function directly as:
74 * ReturnType localSymbolName(parameterList...)
75 * For example:
76 * int64_t my_sum_function(int64_t a, int64_t b) {
77 * return a + b;
78 * }
80 * In which case you will need to use a different macro in moduleLoad()
81 * virtual moduleLoad(const IniSetting::Map& ini, Hdf config) {
82 * HHVM_NAME_FE(sum, my_sum_function)
83 * }
84 * Or an explicit call to registerNativeFunc()
85 * static const StaticString s_sum("sum");
86 * virtual moduleLoad(const IniSetting::Map& ini, Hdf config) {
87 * Native::registerNativeFunc(s_sum, (void*)my_sum_function);
88 * }
90 ****************************************************************************
92 * The macros HHVM_FALIAS, HHVM_MALIAS, and HHVM_STATIC_MALIAS allow
93 * giving different names to the C++ implementation and the exported
94 * C++ function. This ca be useful for creating multiple names for one
95 * function or for registering functions that live in a namespace.
98 #define HHVM_FN(fn) f_ ## fn
99 #define HHVM_FUNCTION(fn, ...) \
100 HHVM_FN(fn)(__VA_ARGS__)
101 #define HHVM_NAMED_FE_STR(fn, fimpl, functable) \
102 do { \
103 String name{makeStaticString(fn)}; \
104 registerExtensionFunction(name); \
105 Native::registerNativeFunc(functable, name, fimpl); \
106 } while(0)
107 #define HHVM_NAMED_FE(fn, fimpl)\
108 HHVM_NAMED_FE_STR(#fn, fimpl, nativeFuncs())
109 #define HHVM_FE(fn) \
110 HHVM_NAMED_FE_STR(#fn, HHVM_FN(fn), nativeFuncs())
111 #define HHVM_FALIAS(fn, falias)\
112 HHVM_NAMED_FE_STR(#fn, HHVM_FN(falias), nativeFuncs())
114 /* Macros related to declaring/registering internal implementations
115 * of <<__Native>> class instance methods.
117 * See the definition of function macros above for general explanation.
118 * These macros only differ in the following ways:
119 * - They accept a classname in addition to the function name
120 * - The registered name of the function is "ClassName->FunctionName"
121 * - Prototypes include a prepended ObjectData* const parameter (named this_)
123 #define HHVM_MN(cn,fn) c_ ## cn ## _ni_ ## fn
124 #define HHVM_METHOD(cn, fn, ...) \
125 HHVM_MN(cn,fn)(ObjectData* const this_, ##__VA_ARGS__)
126 #define HHVM_NAMED_ME(cn,fn,mimpl) \
127 Native::registerNativeFunc(nativeFuncs(), #cn "->" #fn, mimpl)
128 #define HHVM_ME(cn,fn) HHVM_NAMED_ME(cn,fn, HHVM_MN(cn,fn))
129 #define HHVM_MALIAS(cn,fn,calias,falias) \
130 HHVM_NAMED_ME(cn,fn,HHVM_MN(calias,falias))
132 /* special case when we're registering info for a method defined in
133 * s_systemNativeFuncs, instead of the current Extension
135 #define HHVM_SYS_FE(fn)\
136 HHVM_NAMED_FE_STR(#fn, HHVM_FN(fn), Native::s_systemNativeFuncs)
137 #define HHVM_NAMED_SYS_ME(cn,fn,mimpl) Native::registerNativeFunc(\
138 Native::s_systemNativeFuncs, #cn "->" #fn, mimpl)
139 #define HHVM_SYS_ME(cn,fn) HHVM_NAMED_SYS_ME(cn,fn, HHVM_MN(cn,fn))
141 /* Macros related to declaring/registering internal implementations
142 * of <<__Native>> class static methods.
144 * See the definition of function macros above for general explanation.
145 * These macros only differ in the following ways:
146 * - They accept a classname in addition to the function name
147 * - The registered name of the function is "ClassName::FunctionName"
148 * - Prototypes include a prepended const Class* parameter (named self_)
150 #define HHVM_STATIC_MN(cn,fn) c_ ## cn ## _ns_ ## fn
151 #define HHVM_STATIC_METHOD(cn, fn, ...) \
152 HHVM_STATIC_MN(cn,fn)(const Class *self_, ##__VA_ARGS__)
153 #define HHVM_NAMED_STATIC_ME(cn,fn,mimpl) \
154 Native::registerNativeFunc(nativeFuncs(), #cn "::" #fn, mimpl)
155 #define HHVM_STATIC_ME(cn,fn) HHVM_NAMED_STATIC_ME(cn,fn,HHVM_STATIC_MN(cn,fn))
156 #define HHVM_STATIC_MALIAS(cn,fn,calias,falias) \
157 HHVM_NAMED_STATIC_ME(cn,fn,HHVM_STATIC_MN(calias,falias))
159 /* Macros related to declaring/registering constants. Note that the
160 * HHVM_RCC_* macros expect a StaticString to be present via s_##class_name.
162 #define HHVM_RC_STR(const_name, const_value) \
163 Native::registerConstant<KindOfString>( \
164 makeStaticString(#const_name), makeStaticString(const_value));
165 #define HHVM_RC_INT(const_name, const_value) \
166 Native::registerConstant<KindOfInt64>( \
167 makeStaticString(#const_name), int64_t{const_value});
168 #define HHVM_RC_DBL(const_name, const_value) \
169 Native::registerConstant<KindOfDouble>( \
170 makeStaticString(#const_name), double{const_value});
171 #define HHVM_RC_BOOL(const_name, const_value) \
172 Native::registerConstant<KindOfBoolean>( \
173 makeStaticString(#const_name), bool{const_value});
175 #define HHVM_RC_STR_SAME(const_name) \
176 Native::registerConstant<KindOfString>( \
177 makeStaticString(#const_name), makeStaticString(const_name));
178 #define HHVM_RC_INT_SAME(const_name) \
179 Native::registerConstant<KindOfInt64>( \
180 makeStaticString(#const_name), int64_t{const_name});
181 #define HHVM_RC_DBL_SAME(const_name) \
182 Native::registerConstant<KindOfDouble>( \
183 makeStaticString(#const_name), double{const_name});
184 #define HHVM_RC_BOOL_SAME(const_name) \
185 Native::registerConstant<KindOfBoolean>( \
186 makeStaticString(#const_name), bool{const_name});
188 #define HHVM_RCC_STR(class_name, const_name, const_value) \
189 Native::registerClassConstant<KindOfString>(s_##class_name.get(), \
190 makeStaticString(#const_name), makeStaticString(const_value));
191 #define HHVM_RCC_INT(class_name, const_name, const_value) \
192 Native::registerClassConstant<KindOfInt64>(s_##class_name.get(), \
193 makeStaticString(#const_name), int64_t{const_value});
194 #define HHVM_RCC_DBL(class_name, const_name, const_value) \
195 Native::registerClassConstant<KindOfDouble>(s_##class_name.get(), \
196 makeStaticString(#const_name), double{const_value});
197 #define HHVM_RCC_BOOL(class_name, const_name, const_value) \
198 Native::registerClassConstant<KindOfBoolean>(s_##class_name.get(), \
199 makeStaticString(#const_name), bool{const_value});
201 // Register a dynamic constant. This will not be optimized by hhbbc
202 #define HHVM_RC_DYNAMIC(const_name, const_value_cell) \
203 Native::registerConstant(makeStaticString(#const_name), \
204 const_value_cell, true);
206 namespace HPHP { namespace Native {
207 //////////////////////////////////////////////////////////////////////////////
209 // Maximum number of args for a native function call
211 // To paraphrase you-know-who, "32 args should be enough for anybody"
213 // Note: If changing this number, update native-func-caller.h
214 // using make_native-func-caller.php
215 const int kMaxBuiltinArgs = 32;
217 inline int maxFCallBuiltinArgs() {
218 return kMaxBuiltinArgs;
221 enum Attr {
222 AttrNone = 0,
224 // Methods whose implementation is generated by HackC.
225 AttrOpCodeImpl = (1u << 0),
229 * Prepare function call arguments to match their expected
230 * types on a native function/method call.
232 * Uses typehints in Func and tvCast*InPlace
234 void coerceFCallArgs(TypedValue* args,
235 int32_t numArgs, int32_t numNonDefault,
236 const Func* func);
239 * Dispatches a call to the native function bound to <func>
240 * If <ctx> is not nullptr, it is prepended to <args> when
241 * calling.
243 void callFunc(const Func* func, const void* ctx,
244 const TypedValue* args, int32_t numNonDefault,
245 TypedValue& ret, bool isFCallBuiltin);
247 #define NATIVE_TYPES \
248 /* kind arg type return type */ \
249 X(Int32, int32_t, int32_t) \
250 X(Int64, int64_t, int64_t) \
251 X(Double, double, double) \
252 X(Bool, bool, bool) \
253 X(Object, const Object&, Object) \
254 X(String, const String&, String) \
255 X(Array, const Array&, Array) \
256 X(Resource, const Resource&, Resource) \
257 X(Func, Func*, Func*) \
258 X(Class, const Class*, const Class*) \
259 X(ClsMeth, ClsMethDataRef, ClsMethDataRef) \
260 X(Mixed, const Variant&, Variant) \
261 X(ObjectArg, ObjectArg, ObjectArg) \
262 X(StringArg, StringArg, StringArg) \
263 X(ArrayArg, ArrayArg, ArrayArg) \
264 X(ResourceArg,ResourceArg, ResourceArg) \
265 X(MixedTV, TypedValue, TypedValue) \
266 X(This, ObjectData*, ObjectData*) \
267 X(Void, void, void) \
268 X(IntIO, int64_t&, int64_t&) \
269 X(DoubleIO, double&, double&) \
270 X(BoolIO, bool&, bool&) \
271 X(ObjectIO, Object&, Object&) \
272 X(StringIO, String&, String&) \
273 X(ArrayIO, Array&, Array&) \
274 X(ResourceIO, Resource&, Resource&) \
275 X(FuncIO, Func*&, Func*&) \
276 X(ClassIO, Class*&, Class*&) \
277 X(ClsMethIO, ClsMethDataRef&, ClsMethDataRef&)\
278 X(MixedIO, Variant&, Variant&) \
279 /**/
281 template <class T>
282 struct NativeArg {
284 * Delete move assignment operator to make this non-copyable.
286 NativeArg& operator=(NativeArg&&) = delete;
287 T* operator->() { return m_px; }
288 T* get() { return m_px; }
289 bool operator!() const { return m_px == nullptr; }
290 bool isNull() const { return m_px == nullptr; }
291 private:
293 * To be able to pass the values of this class as function parameters
294 * by value, define default copy constructor (See Itanium C++ ABI p3.1.1).
295 * Make it private to satisfy the non-copyable requirement.
297 NativeArg(const NativeArg&) = default;
298 T* m_px;
302 using ObjectArg = Native::NativeArg<ObjectData>;
303 using StringArg = Native::NativeArg<StringData>;
304 using ArrayArg = Native::NativeArg<ArrayData>;
305 using ResourceArg = Native::NativeArg<ResourceData>;
307 namespace Native {
309 struct NativeSig {
310 enum class Type : uint8_t {
311 #define X(name, ...) name,
312 NATIVE_TYPES
313 #undef X
316 NativeSig() : ret(Type::Void) {}
318 NativeSig(Type ret, const std::vector<Type>& args)
319 : ret(ret), args(args)
322 NativeSig(Type ret, std::vector<Type>&& args)
323 : ret(ret), args(std::move(args))
326 NativeSig(NativeSig&&) = default;
327 NativeSig(const NativeSig&) = default;
329 NativeSig& operator=(const NativeSig&) = default;
330 NativeSig& operator=(NativeSig&&) = default;
332 template<class Ret>
333 explicit NativeSig(Ret (*ptr)());
335 template<class Ret, class... Args>
336 explicit NativeSig(Ret (*ptr)(Args...));
338 bool operator==(const NativeSig& other) const {
339 return ret == other.ret && args == other.args;
342 std::string toString(const char* classname, const char* fname) const;
344 Type ret;
345 std::vector<Type> args;
348 namespace detail {
350 template<class T> struct native_arg_type {};
351 template<class T> struct native_ret_type {};
352 template<class T> struct known_native_arg : std::false_type {};
354 #define X(name, argTy, retTy) \
355 template<> struct native_ret_type<retTy> \
356 : std::integral_constant<NativeSig::Type,NativeSig::Type::name> \
357 {}; \
358 template<> struct native_arg_type<argTy> \
359 : std::integral_constant<NativeSig::Type,NativeSig::Type::name> \
360 {}; \
361 template<> struct known_native_arg<argTy> : std::true_type {};
363 NATIVE_TYPES
365 #undef X
367 template<class... Args> struct all_known_arg_type {};
368 template<class A> struct all_known_arg_type<A> : known_native_arg<A> {};
370 template<class A, class... Rest>
371 struct all_known_arg_type<A,Rest...>
372 : std::integral_constant<
373 bool,
374 known_native_arg<A>::value && all_known_arg_type<Rest...>::value
378 template<class T> struct understandable_sig : std::false_type {};
379 template<class R> struct understandable_sig<R (*)()> : std::true_type {};
380 template<class R, class... Args>
381 struct understandable_sig<R (*)(Args...)>
382 : all_known_arg_type<Args...>
385 template<class... Args>
386 std::vector<NativeSig::Type> build_args() {
387 return {
388 native_arg_type<Args>::value...
394 template <class Ret>
395 NativeSig::NativeSig(Ret (*/*ptr*/)())
396 : ret(detail::native_ret_type<Ret>::value) {}
398 template <class Ret, class... Args>
399 NativeSig::NativeSig(Ret (*/*ptr*/)(Args...))
400 : ret(detail::native_ret_type<Ret>::value),
401 args(detail::build_args<Args...>()) {}
403 #undef NATIVE_TYPES
405 // NativeFunctionInfo carries around a NativeSig describing the real signature,
406 // and a type-erased NativeFunction ptr.
407 struct NativeFunctionInfo {
408 NativeFunctionInfo() : ptr(nullptr) {}
410 // generate the signature using template magic
411 template<typename Func>
412 explicit NativeFunctionInfo(Func f)
413 : sig(f)
414 , ptr(reinterpret_cast<NativeFunction>(f))
417 // trust the given signature
418 template<typename Func>
419 NativeFunctionInfo(NativeSig sig, Func f)
420 : sig(sig)
421 , ptr(reinterpret_cast<NativeFunction>(f))
424 explicit operator bool() const { return ptr != nullptr; }
426 bool operator==(const NativeFunctionInfo& other) const {
427 return ptr == other.ptr && sig == other.sig;
430 NativeSig sig;
431 NativeFunction ptr;
435 * Known output types for inout parameters on builtins and optional default
436 * values to be passed to builtins which use inout paramaters purely as out
437 * values, ignoring their inputs.
439 MaybeDataType builtinOutType(const TypeConstraint&, const UserAttributeMap&);
440 MaybeDataType builtinOutType(const Func* builtin, uint32_t i);
441 folly::Optional<TypedValue> builtinInValue(const Func* builtin, uint32_t i);
443 /////////////////////////////////////////////////////////////////////////////
446 * Returns a specialization of either functionWrapper or methodWrapper
448 * functionWrapper() Unpacks args and coerces types according
449 * to Func typehints. Calls C++ function in the form:
450 * ret f_foo(type arg1, type arg2, ...)
451 * Marshalls return into TypedValue.
453 * methodWrapper() behaves the same as functionWrapper(),
454 * but also prepends either an ObjectData* (instance) or Class* (static)
455 * argument to the signature. i.e.:
456 * ret c_class_ni_method(ObjectData* this_, type arg1, type arg2, ...)
457 * ret c_class_ns_method(Class* self_, type arg1, type arg2, ...)
459 void getFunctionPointers(const NativeFunctionInfo& info,
460 int nativeAttrs,
461 ArFunction& bif,
462 NativeFunction& nif);
465 * Fallback method bound to declared methods with no matching
466 * internal implementation.
468 TypedValue* unimplementedWrapper(ActRec* ar);
470 /////////////////////////////////////////////////////////////////////////////
473 * registerNativeFunc() and getNativeFunction() use a provided
474 * FuncTable that is a case insensitive map of "name" to function pointer.
476 * Extensions should generally add items to this map using the HHVM_FE/ME
477 * macros above. The function name (key) must be a static string.
480 struct FuncTable;
481 void registerNativeFunc(FuncTable&, const StringData*,
482 const NativeFunctionInfo&);
484 // Helper accepting a C-string name
485 template <class Fun> typename
486 std::enable_if<!std::is_member_function_pointer<Fun>::value, void>::type
487 registerNativeFunc(FuncTable& nativeFuncs, const char* name, Fun func) {
488 static_assert(
489 std::is_pointer<Fun>::value &&
490 std::is_function<typename std::remove_pointer<Fun>::type>::value,
491 "You can only register pointers to functions."
493 static_assert(
494 detail::understandable_sig<Fun>::value,
495 "Arguments on builtin function were not understood types"
497 registerNativeFunc(nativeFuncs, makeStaticString(name),
498 NativeFunctionInfo(func));
501 // Helper accepting a possibly nonstatic HPHP::String name
502 template <class Fun> typename
503 std::enable_if<!std::is_member_function_pointer<Fun>::value, void>::type
504 registerNativeFunc(FuncTable& nativeFuncs, const String& name, Fun func) {
505 static_assert(
506 std::is_pointer<Fun>::value &&
507 std::is_function<typename std::remove_pointer<Fun>::type>::value,
508 "You can only register pointers to functions."
510 static_assert(
511 detail::understandable_sig<Fun>::value,
512 "Arguments on builtin function were not understood types"
514 registerNativeFunc(nativeFuncs, makeStaticString(name),
515 NativeFunctionInfo(func));
518 // Specializations of registerNativeFunc for taking pointers to member
519 // functions and making them look like HNI wrapper funcs.
521 // This allows invoking object method calls directly, but ONLY for specialized
522 // subclasses of ObjectData.
524 // This API is limited to: Closure, Asio, and Collections. Do not use it if
525 // you are not implementing one of these
526 template<class Ret, class Cls> typename
527 std::enable_if<std::is_base_of<ObjectData, Cls>::value, void>::type
528 registerNativeFunc(FuncTable& nativeFuncs, const char* name,
529 Ret (Cls::*func)()) {
530 registerNativeFunc(nativeFuncs, name,
531 (Ret (*)(ObjectData*))getMethodPtr(func));
534 template<class Ret, class Cls, class... Args> typename
535 std::enable_if<std::is_base_of<ObjectData, Cls>::value, void>::type
536 registerNativeFunc(FuncTable& nativeFuncs, const char* name,
537 Ret (Cls::*func)(Args...)) {
538 registerNativeFunc(
539 nativeFuncs, name, (Ret (*)(ObjectData*, Args...))getMethodPtr(func)
543 template<class Ret, class Cls> typename
544 std::enable_if<std::is_base_of<ObjectData, Cls>::value, void>::type
545 registerNativeFunc(FuncTable& nativeFuncs, const char* name,
546 Ret (Cls::*func)() const) {
547 registerNativeFunc(nativeFuncs, name,
548 (Ret (*)(ObjectData*))getMethodPtr(func));
551 template<class Ret, class Cls, class... Args> typename
552 std::enable_if<std::is_base_of<ObjectData, Cls>::value, void>::type
553 registerNativeFunc(FuncTable& nativeFuncs, const char* name,
554 Ret (Cls::*func)(Args...) const) {
555 registerNativeFunc(
556 nativeFuncs, name, (Ret (*)(ObjectData*, Args...))getMethodPtr(func)
560 /////////////////////////////////////////////////////////////////////////////
562 const char* checkTypeFunc(const NativeSig& sig,
563 const TypeConstraint& retType,
564 const FuncEmitter* func);
566 // NativeFunctionInfo for native funcs and methods defined under
567 // system/php, separate from normal extensions.
568 extern FuncTable s_systemNativeFuncs;
570 // A permanently empty table, used in contexts were no native bindings
571 // are possible (most ordinary code).
572 extern const FuncTable s_noNativeFuncs;
574 String fullName(const StringData* fname, const StringData* cname,
575 bool isStatic);
577 NativeFunctionInfo getNativeFunction(const FuncTable& nativeFuncs,
578 const StringData* fname,
579 const StringData* cname = nullptr,
580 bool isStatic = false);
582 NativeFunctionInfo getNativeFunction(const FuncTable& nativeFuncs,
583 const char* fname,
584 const char* cname = nullptr,
585 bool isStatic = false);
587 //////////////////////////////////////////////////////////////////////////////
588 // Global constants
590 typedef std::map<const StringData*,TypedValueAux> ConstantMap;
591 extern ConstantMap s_constant_map;
593 inline
594 bool registerConstant(const StringData* cnsName, Cell cns,
595 bool dynamic = false) {
596 assertx(cellIsPlausible(cns) && cns.m_type != KindOfUninit);
597 auto& dst = s_constant_map[cnsName];
598 *static_cast<Cell*>(&dst) = cns;
599 dst.dynamic() = dynamic;
600 return bindPersistentCns(cnsName, cns);
603 template<DataType DType>
604 typename std::enable_if<
605 !std::is_same<typename DataTypeCPPType<DType>::type,void>::value,
606 bool>::type
607 registerConstant(const StringData* cnsName,
608 typename DataTypeCPPType<DType>::type val) {
609 return registerConstant(cnsName, make_tv<DType>(val));
612 template<DataType DType>
613 typename std::enable_if<
614 std::is_same<typename DataTypeCPPType<DType>::type,void>::value,
615 bool>::type
616 registerConstant(const StringData* cnsName) {
617 return registerConstant(cnsName, make_tv<DType>());
620 inline
621 const ConstantMap& getConstants() {
622 return s_constant_map;
625 using ConstantCallback = const Variant& (*)();
626 bool registerConstant(const StringData*, ConstantCallback);
628 //////////////////////////////////////////////////////////////////////////////
629 // Class Constants
631 typedef hphp_hash_map<const StringData*, ConstantMap,
632 string_data_hash, string_data_isame> ClassConstantMapMap;
633 extern ClassConstantMapMap s_class_constant_map;
635 inline
636 bool registerClassConstant(const StringData *clsName,
637 const StringData *cnsName,
638 Cell cns) {
639 assertx(cellIsPlausible(cns));
640 auto &cls = s_class_constant_map[clsName];
641 assertx(cls.find(cnsName) == cls.end());
642 *static_cast<Cell*>(&cls[cnsName]) = cns;
643 return true;
646 template<DataType DType>
647 typename std::enable_if<
648 !std::is_same<typename DataTypeCPPType<DType>::type,void>::value,
649 bool>::type
650 registerClassConstant(const StringData* clsName,
651 const StringData* cnsName,
652 typename DataTypeCPPType<DType>::type val) {
653 return registerClassConstant(clsName, cnsName, make_tv<DType>(val));
656 template<DataType DType>
657 typename std::enable_if<
658 std::is_same<typename DataTypeCPPType<DType>::type,void>::value,
659 bool>::type
660 registerClassConstant(const StringData* clsName,
661 const StringData* cnsName) {
662 return registerClassConstant(clsName, cnsName, make_tv<DType>());
665 inline
666 const ConstantMap* getClassConstants(const StringData* clsName) {
667 auto clsit = s_class_constant_map.find(const_cast<StringData*>(clsName));
668 if (clsit == s_class_constant_map.end()) {
669 return nullptr;
671 return &clsit->second;
674 //////////////////////////////////////////////////////////////////////////////
675 }} // namespace HPHP::Native
677 #endif