Skip to content

Commit 8c844a9

Browse files
committed
improve performance of wrap_generic_callable
nr_php_wrap_generic_callable is used to create transient wraprecs for callables which don't require to be named. This assumption makes it possible to stay DRY and reuse nr_php_zval_to_function in lieu of complex pattern matching for the type of callable. On top of that it improves performance as it now uses nr_php_wrap_callable always instead of sometimes using nr_php_wrap_user_function
1 parent 9106341 commit 8c844a9

File tree

1 file changed

+42
-80
lines changed

1 file changed

+42
-80
lines changed

agent/php_wrapper.c

Lines changed: 42 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,41 @@
77
#include "php_user_instrument.h"
88
#include "php_wrapper.h"
99
#include "util_logging.h"
10+
static char* Z_TYPE_STR(zval* zv) {
11+
switch (Z_TYPE_P(zv)) {
12+
case IS_NULL:
13+
return "IS_NULL";
14+
15+
case IS_STRING:
16+
return "IS_STRING";
17+
18+
case IS_LONG:
19+
return "IS_LONG";
20+
21+
#if ZEND_MODULE_API_NO >= ZEND_7_0_X_API_NO /* PHP7+ */
22+
case IS_TRUE:
23+
return "IS_TRUE";
24+
25+
case IS_FALSE:
26+
return "IS_FALSE";
27+
#else
28+
case IS_BOOL:
29+
return "IS_BOOL";
30+
#endif /* PHP7 */
31+
32+
case IS_DOUBLE:
33+
return "IS_DOUBLE";
34+
35+
case IS_OBJECT:
36+
return "IS_OBJECT";
37+
38+
case IS_ARRAY:
39+
return "IS_ARRAY";
40+
41+
default:
42+
return "UNKNOWN";
43+
}
44+
}
1045

1146
#if ZEND_MODULE_API_NO >= ZEND_8_0_X_API_NO
1247
static void nr_php_wraprec_add_before_after_clean_callbacks(
@@ -196,92 +231,19 @@ nruserfn_t* nr_php_wrap_callable(zend_function* callable,
196231
*/
197232
nruserfn_t* nr_php_wrap_generic_callable(zval* callable,
198233
nrspecialfn_t callback TSRMLS_DC) {
199-
#if ZEND_MODULE_API_NO < ZEND_7_0_X_API_NO
200-
char* name = NULL;
201-
#else
202-
zend_string* name = NULL;
203-
#endif
204-
zend_fcall_info_cache fcc;
205-
zend_fcall_info fci;
234+
zend_function* zf = nr_php_zval_to_function(callable);
206235

207-
nr_wrap_user_function_options_t options = {
208-
NR_WRAPREC_IS_TRANSIENT,
209-
NR_WRAPREC_NO_INSTRUMENTED_FUNCTION_METRIC
210-
};
211-
212-
/* not calling nr_zend_is_callable because we want to additionally populate
213-
* name */
214-
if (zend_is_callable(callable, 0, &name TSRMLS_CC)) {
215-
#if ZEND_MODULE_API_NO >= ZEND_7_0_X_API_NO
216-
again:
217-
#endif
218-
/* see php source code's zend_is_callable_at_frame function to see from
219-
* where these switch cases are derived */
220-
switch (Z_TYPE_P(callable)) {
221-
/* wrapping a string name of a callable */
222-
case IS_STRING:
223-
#if ZEND_MODULE_API_NO >= ZEND_8_0_X_API_NO \
224-
&& !defined OVERWRITE_ZEND_EXECUTE_DATA
225-
return nr_php_wrap_user_function_before_after_clean_with_options(
226-
ZEND_STRING_VALUE(name), ZEND_STRING_LEN(name), callback,
227-
NULL, NULL, &options);
228-
#else
229-
return nr_php_wrap_user_function_with_options(
230-
ZEND_STRING_VALUE(name), ZEND_STRING_LEN(name), callback,
231-
&options TSRMLS_CC);
232-
#endif
233-
234-
/* wrapping an array where [0] is an object and [1] is the method to
235-
* invoke the previous zend_is_callable has created the commbined
236-
* object::method name for us to wrap */
237-
case IS_ARRAY:
238-
#if ZEND_MODULE_API_NO >= ZEND_8_0_X_API_NO \
239-
&& !defined OVERWRITE_ZEND_EXECUTE_DATA
240-
return nr_php_wrap_user_function_before_after_clean_with_options(
241-
ZEND_STRING_VALUE(name), ZEND_STRING_LEN(name), callback,
242-
NULL, NULL, &options);
243-
#else
244-
return nr_php_wrap_user_function_with_options(
245-
ZEND_STRING_VALUE(name), ZEND_STRING_LEN(name), callback,
246-
&options TSRMLS_CC);
247-
#endif
248-
249-
/* wrapping a closure. Need to initialize fcall info in order to wrap the
250-
* underlying zend_function object */
251-
case IS_OBJECT:
252-
if (SUCCESS
253-
== zend_fcall_info_init(callable, 0, &fci, &fcc, NULL,
254-
NULL TSRMLS_CC)) {
255-
/* nr_php_wrap_callable already sets the transience field for us */
236+
if (NULL != zf) {
256237
#if ZEND_MODULE_API_NO >= ZEND_8_0_X_API_NO \
257238
&& !defined OVERWRITE_ZEND_EXECUTE_DATA
258-
return nr_php_wrap_callable_before_after_clean(
259-
fcc.function_handler, callback, NULL, NULL);
239+
return nr_php_wrap_callable_before_after_clean(zf, callback, NULL, NULL);
260240
#else
261-
return nr_php_wrap_callable(fcc.function_handler, callback TSRMLS_CC);
241+
return nr_php_wrap_callable(zf, callback TSRMLS_CC);
262242
#endif
263-
}
264-
nrl_verbosedebug(NRL_INSTRUMENT,
265-
"Failed to initialize fcall info when wrapping");
266-
break;
267-
268-
/* unwrap references */
269-
/* PHP 5.x handles references in a different manner that do not need to
270-
* be unwrapped */
271-
#if ZEND_MODULE_API_NO >= ZEND_7_0_X_API_NO
272-
case IS_REFERENCE:
273-
callable = Z_REFVAL_P(callable);
274-
goto again;
275-
#endif
276-
}
277-
}
278-
if (NULL != name) {
279-
nrl_verbosedebug(NRL_INSTRUMENT, "Failed to wrap callable: %s",
280-
ZEND_STRING_VALUE(name));
281-
} else {
282-
nrl_verbosedebug(NRL_INSTRUMENT,
283-
"Failed to wrap callable with unknown name");
284243
}
244+
nrl_verbosedebug(NRL_INSTRUMENT,
245+
"Failed to cast to callable: Z_TYPE(callable)=%s",
246+
Z_TYPE_STR(callable));
285247
return NULL;
286248
}
287249

0 commit comments

Comments
 (0)