PageRenderTime 49ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/hphp/runtime/ext/std/ext_std_function.cpp

https://gitlab.com/alvinahmadov2/hhvm
C++ | 292 lines | 225 code | 37 blank | 30 comment | 25 complexity | 6ecf3dcf70451e6493f6e6c1d9750829 MD5 | raw file
  1. /*
  2. +----------------------------------------------------------------------+
  3. | HipHop for PHP |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 2010-2015 Facebook, Inc. (http://www.facebook.com) |
  6. | Copyright (c) 1997-2010 The PHP Group |
  7. +----------------------------------------------------------------------+
  8. | This source file is subject to version 3.01 of the PHP license, |
  9. | that is bundled with this package in the file LICENSE, and is |
  10. | available through the world-wide-web at the following url: |
  11. | http://www.php.net/license/3_01.txt |
  12. | If you did not receive a copy of the PHP license and are unable to |
  13. | obtain it through the world-wide-web, please send a note to |
  14. | license@php.net so we can mail you a copy immediately. |
  15. +----------------------------------------------------------------------+
  16. */
  17. #include "hphp/runtime/ext/std/ext_std_function.h"
  18. #include <algorithm>
  19. #include <vector>
  20. #include "hphp/runtime/base/array-init.h"
  21. #include "hphp/runtime/base/autoload-handler.h"
  22. #include "hphp/runtime/ext/json/ext_json.h"
  23. #include "hphp/runtime/base/class-info.h"
  24. #include "hphp/runtime/base/libevent-http-client.h"
  25. #include "hphp/runtime/server/http-protocol.h"
  26. #include "hphp/runtime/vm/runtime.h"
  27. #include "hphp/runtime/vm/jit/translator.h"
  28. #include "hphp/runtime/vm/jit/translator-inline.h"
  29. #include "hphp/util/exception.h"
  30. namespace HPHP {
  31. ///////////////////////////////////////////////////////////////////////////////
  32. using std::string;
  33. const StaticString
  34. s_internal("internal"),
  35. s_user("user");
  36. Array HHVM_FUNCTION(get_defined_functions) {
  37. return make_map_array(s_internal, Unit::getSystemFunctions(),
  38. s_user, Unit::getUserFunctions());
  39. }
  40. bool HHVM_FUNCTION(function_exists, const String& function_name,
  41. bool autoload /* = true */) {
  42. return
  43. function_exists(function_name) ||
  44. (autoload &&
  45. AutoloadHandler::s_instance->autoloadFunc(function_name.get()) &&
  46. function_exists(function_name));
  47. }
  48. bool HHVM_FUNCTION(is_callable, const Variant& v, bool syntax /* = false */,
  49. OutputArg name /* = null */) {
  50. return is_callable(v, syntax, name.get());
  51. }
  52. Variant HHVM_FUNCTION(call_user_func, const Variant& function,
  53. const Array& params /* = null_array */) {
  54. return vm_call_user_func(function, params);
  55. }
  56. Variant HHVM_FUNCTION(call_user_func_array, const Variant& function,
  57. const Array& params) {
  58. return vm_call_user_func(function, params);
  59. }
  60. Variant HHVM_FUNCTION(check_user_func_async, const Variant& handles,
  61. int timeout /* = -1 */) {
  62. raise_error("%s is no longer supported", __func__);
  63. return init_null();
  64. }
  65. Variant HHVM_FUNCTION(end_user_func_async, const Object& handle,
  66. int default_strategy /*= k_GLOBAL_STATE_IGNORE*/,
  67. const Variant& additional_strategies /* = null */) {
  68. raise_error("%s is no longer supported", __func__);
  69. return init_null();
  70. }
  71. Variant HHVM_FUNCTION(forward_static_call_array, const Variant& function,
  72. const Array& params) {
  73. return HHVM_FN(forward_static_call)(function, params);
  74. }
  75. Variant HHVM_FUNCTION(forward_static_call, const Variant& function,
  76. const Array& params /* = null_array */) {
  77. // Setting the bound parameter to true tells vm_call_user_func()
  78. // propogate the current late bound class
  79. return vm_call_user_func(function, params, true);
  80. }
  81. String HHVM_FUNCTION(create_function, const String& args, const String& code) {
  82. return g_context->createFunction(args, code);
  83. }
  84. ///////////////////////////////////////////////////////////////////////////////
  85. ALWAYS_INLINE
  86. static Variant func_get_arg_impl(int arg_num) {
  87. CallerFrame cf;
  88. ActRec* ar = cf.actRecForArgs();
  89. if (ar == nullptr) {
  90. return false;
  91. }
  92. if (ar->func()->isPseudoMain()) {
  93. raise_warning(
  94. "func_get_arg(): Called from the global scope - no function context"
  95. );
  96. return false;
  97. }
  98. if (arg_num < 0) {
  99. raise_warning(
  100. "func_get_arg(): The argument number should be >= 0"
  101. );
  102. return false;
  103. }
  104. if (arg_num >= ar->numArgs()) {
  105. raise_warning(
  106. "func_get_arg(): Argument %d not passed to function", arg_num
  107. );
  108. return false;
  109. }
  110. const int numParams = ar->m_func->numNonVariadicParams();
  111. if (arg_num < numParams) {
  112. // Formal parameter. Value is on the stack.
  113. TypedValue* loc =
  114. (TypedValue*)(uintptr_t(ar) - (arg_num + 1) * sizeof(TypedValue));
  115. return tvAsVariant(loc);
  116. }
  117. const int numArgs = ar->numArgs();
  118. const int extraArgs = numArgs - numParams;
  119. // Not a formal parameter. Value is potentially in the
  120. // ExtraArgs/VarEnv.
  121. const int extraArgNum = arg_num - numParams;
  122. if (extraArgNum < extraArgs) {
  123. return tvAsVariant(ar->getExtraArg(extraArgNum));
  124. }
  125. return false;
  126. }
  127. Variant HHVM_FUNCTION(func_get_arg, int arg_num) {
  128. raise_disallowed_dynamic_call(
  129. "func_get_arg should not be called dynamically");
  130. return func_get_arg_impl(arg_num);
  131. }
  132. Variant HHVM_FUNCTION(SystemLib_func_get_arg_sl, int arg_num) {
  133. return func_get_arg_impl(arg_num);
  134. }
  135. Array hhvm_get_frame_args(const ActRec* ar, int offset) {
  136. if (ar == nullptr) {
  137. return Array();
  138. }
  139. int numParams = ar->func()->numNonVariadicParams();
  140. int numArgs = ar->numArgs();
  141. bool variadic = ar->func()->hasVariadicCaptureParam() &&
  142. !(ar->func()->attrs() & AttrMayUseVV);
  143. auto local = reinterpret_cast<TypedValue*>(
  144. uintptr_t(ar) - sizeof(TypedValue)
  145. );
  146. if (variadic && numArgs > numParams) {
  147. auto arr = local - numParams;
  148. if (isArrayType(arr->m_type) && arr->m_data.parr->isPacked()) {
  149. numArgs = numParams + arr->m_data.parr->size();
  150. } else {
  151. numArgs = numParams;
  152. }
  153. }
  154. local -= offset;
  155. PackedArrayInit retInit(std::max(numArgs - offset, 0));
  156. for (int i = offset; i < numArgs; ++i) {
  157. if (i < numParams) {
  158. // This corresponds to one of the function's formal parameters, so it's
  159. // on the stack.
  160. retInit.append(tvAsCVarRef(local));
  161. --local;
  162. } else if (variadic) {
  163. retInit.append(tvAsCVarRef(local).asCArrRef()[i - numParams]);
  164. } else {
  165. // This is not a formal parameter, so it's in the ExtraArgs.
  166. retInit.append(tvAsCVarRef(ar->getExtraArg(i - numParams)));
  167. }
  168. }
  169. return retInit.toArray();
  170. }
  171. #define FUNC_GET_ARGS_IMPL(offset) do { \
  172. EagerCallerFrame cf; \
  173. ActRec* ar = cf.actRecForArgs(); \
  174. if (!ar || ar->func()->isPseudoMain()) { \
  175. raise_warning( \
  176. "func_get_args(): Called from the global scope - no function context" \
  177. ); \
  178. return false; \
  179. } \
  180. return hhvm_get_frame_args(ar, offset); \
  181. } while(0)
  182. Variant HHVM_FUNCTION(func_get_args) {
  183. raise_disallowed_dynamic_call(
  184. "func_get_args should not be called dynamically");
  185. FUNC_GET_ARGS_IMPL(0);
  186. }
  187. // __SystemLib\func_get_args_sl
  188. Variant HHVM_FUNCTION(SystemLib_func_get_args_sl) {
  189. FUNC_GET_ARGS_IMPL(0);
  190. }
  191. // __SystemLib\func_slice_args
  192. Variant HHVM_FUNCTION(SystemLib_func_slice_args, int offset) {
  193. if (offset < 0) {
  194. offset = 0;
  195. }
  196. FUNC_GET_ARGS_IMPL(offset);
  197. }
  198. ALWAYS_INLINE
  199. static int64_t func_num_args_impl() {
  200. EagerCallerFrame cf;
  201. ActRec* ar = cf.actRecForArgs();
  202. if (ar == nullptr) {
  203. return -1;
  204. }
  205. if (ar->func()->isPseudoMain()) {
  206. raise_warning(
  207. "func_num_args(): Called from the global scope - no function context"
  208. );
  209. return -1;
  210. }
  211. return ar->numArgs();
  212. }
  213. int64_t HHVM_FUNCTION(func_num_args) {
  214. raise_disallowed_dynamic_call(
  215. "func_num_args should not be called dynamically");
  216. return func_num_args_impl();
  217. }
  218. int64_t HHVM_FUNCTION(SystemLib_func_num_arg_) {
  219. return func_num_args_impl();
  220. }
  221. ///////////////////////////////////////////////////////////////////////////////
  222. void HHVM_FUNCTION(register_postsend_function, const Variant& function,
  223. const Array& params /* = null_array */) {
  224. g_context->registerShutdownFunction(function, params,
  225. ExecutionContext::PostSend);
  226. }
  227. void HHVM_FUNCTION(register_shutdown_function, const Variant& function,
  228. const Array& params /* = null_array */) {
  229. g_context->registerShutdownFunction(function, params,
  230. ExecutionContext::ShutDown);
  231. }
  232. void StandardExtension::initFunction() {
  233. HHVM_FE(get_defined_functions);
  234. HHVM_FE(function_exists);
  235. HHVM_FE(is_callable);
  236. HHVM_FE(call_user_func);
  237. HHVM_FE(call_user_func_array);
  238. HHVM_FE(check_user_func_async);
  239. HHVM_FE(end_user_func_async);
  240. HHVM_FE(forward_static_call_array);
  241. HHVM_FE(forward_static_call);
  242. HHVM_FE(create_function);
  243. HHVM_FE(func_get_arg);
  244. HHVM_FALIAS(__SystemLib\\func_get_arg_sl, SystemLib_func_get_arg_sl);
  245. HHVM_FE(func_get_args);
  246. HHVM_FALIAS(__SystemLib\\func_get_args_sl, SystemLib_func_get_args_sl);
  247. HHVM_FALIAS(__SystemLib\\func_slice_args, SystemLib_func_slice_args);
  248. HHVM_FE(func_num_args);
  249. HHVM_FALIAS(__SystemLib\\func_num_arg_, SystemLib_func_num_arg_);
  250. HHVM_FE(register_postsend_function);
  251. HHVM_FE(register_shutdown_function);
  252. loadSystemlib("std_function");
  253. }
  254. ///////////////////////////////////////////////////////////////////////////////
  255. } // namespace HPHP