Skip to content

Commit b569fca

Browse files
committed
Cache FFI types and scopes in opcache SHM
1 parent 2057141 commit b569fca

File tree

6 files changed

+318
-90
lines changed

6 files changed

+318
-90
lines changed

Zend/zend.c

+4-4
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,10 @@ ZEND_ATTRIBUTE_NONNULL ZEND_API zend_result (*zend_random_bytes)(void *bytes, si
9898
ZEND_ATTRIBUTE_NONNULL ZEND_API void (*zend_random_bytes_insecure)(zend_random_bytes_insecure_state *state, void *bytes, size_t size) = NULL;
9999

100100
ZEND_API zend_class_entry *zend_ffi_cdata_ce = NULL;
101-
ZEND_API zend_ffi* (*zend_ffi_cache_cdef_get)(zend_string *cdef) = NULL;
102-
ZEND_API zend_ffi* (*zend_ffi_cache_cdef_add)(zend_string *cdef, zend_ffi *ffi) = NULL;
103-
ZEND_API zend_result (*zend_ffi_cache_type_get)(zend_string *str, zend_ffi_dcl *dcl) = NULL;
104-
ZEND_API zend_result (*zend_ffi_cache_type_add)(zend_string *str, zend_ffi_dcl *dcl) = NULL;
101+
ZEND_API zend_ffi_dcl* (*zend_ffi_cache_type_get)(zend_string *str) = NULL;
102+
ZEND_API zend_ffi_dcl* (*zend_ffi_cache_type_add)(zend_string *str, zend_ffi_dcl *dcl) = NULL;
103+
ZEND_API zend_ffi_scope* (*zend_ffi_cache_scope_get)(zend_string *str) = NULL;
104+
ZEND_API zend_ffi_scope* (*zend_ffi_cache_scope_add)(zend_string *str, zend_ffi_scope *scope) = NULL;
105105

106106
/* This callback must be signal handler safe! */
107107
void (*zend_on_timeout)(int seconds);

Zend/zend.h

+5-5
Original file line numberDiff line numberDiff line change
@@ -391,13 +391,13 @@ extern ZEND_API zend_utility_values zend_uv;
391391
/* FFI/OPCache interopability API */
392392
extern ZEND_API zend_class_entry *zend_ffi_cdata_ce;
393393

394-
typedef struct _zend_ffi zend_ffi;
395394
typedef struct _zend_ffi_dcl zend_ffi_dcl;
395+
typedef struct _zend_ffi_scope zend_ffi_scope;
396396

397-
ZEND_API extern zend_ffi* (*zend_ffi_cache_cdef_get)(zend_string *cdef);
398-
ZEND_API extern zend_ffi* (*zend_ffi_cache_cdef_add)(zend_string *cdef, zend_ffi *ffi);
399-
ZEND_API extern zend_result (*zend_ffi_cache_type_get)(zend_string *str, zend_ffi_dcl *dcl);
400-
ZEND_API extern zend_result (*zend_ffi_cache_type_add)(zend_string *str, zend_ffi_dcl *dcl);
397+
ZEND_API extern zend_ffi_dcl* (*zend_ffi_cache_type_get)(zend_string *str);
398+
ZEND_API extern zend_ffi_dcl* (*zend_ffi_cache_type_add)(zend_string *str, zend_ffi_dcl *dcl);
399+
ZEND_API extern zend_ffi_scope* (*zend_ffi_cache_scope_get)(zend_string *str);
400+
ZEND_API extern zend_ffi_scope* (*zend_ffi_cache_scope_add)(zend_string *str, zend_ffi_scope *scope);
401401

402402

403403
/* If DTrace is available and enabled */

Zend/zend_types.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -822,7 +822,7 @@ static zend_always_inline uint32_t zval_gc_info(uint32_t gc_type_info) {
822822
#define IS_STR_PERMANENT (1<<8) /* relives request boundary */
823823
#define IS_STR_VALID_UTF8 (1<<9) /* valid UTF-8 according to PCRE */
824824
#define IS_STR_FFI_TYPE (1<<10) /* intrned string associated with FFI type */
825-
#define IS_STR_FFI_DECL (1<<11) /* intrned string associated with FFI declaration object */
825+
#define IS_STR_FFI_SCOPE (1<<11) /* intrned string associated with FFI declaration object */
826826

827827
/* array flags */
828828
#define IS_ARRAY_IMMUTABLE GC_IMMUTABLE

ext/ffi/ffi.c

+67-53
Original file line numberDiff line numberDiff line change
@@ -60,50 +60,16 @@
6060

6161
ZEND_DECLARE_MODULE_GLOBALS(ffi)
6262

63-
typedef enum _zend_ffi_tag_kind {
64-
ZEND_FFI_TAG_ENUM,
65-
ZEND_FFI_TAG_STRUCT,
66-
ZEND_FFI_TAG_UNION
67-
} zend_ffi_tag_kind;
68-
6963
static const char *zend_ffi_tag_kind_name[3] = {"enum", "struct", "union"};
7064

71-
72-
typedef struct _zend_ffi_tag {
73-
zend_ffi_tag_kind kind;
74-
zend_ffi_type *type;
75-
} zend_ffi_tag;
76-
7765
#include "ffi_arginfo.h"
7866

79-
typedef enum _zend_ffi_symbol_kind {
80-
ZEND_FFI_SYM_TYPE,
81-
ZEND_FFI_SYM_CONST,
82-
ZEND_FFI_SYM_VAR,
83-
ZEND_FFI_SYM_FUNC
84-
} zend_ffi_symbol_kind;
85-
86-
typedef struct _zend_ffi_symbol {
87-
zend_ffi_symbol_kind kind;
88-
bool is_const;
89-
zend_ffi_type *type;
90-
union {
91-
void *addr;
92-
int64_t value;
93-
};
94-
} zend_ffi_symbol;
95-
96-
typedef struct _zend_ffi_scope {
97-
HashTable *symbols;
98-
HashTable *tags;
99-
} zend_ffi_scope;
100-
10167
typedef struct _zend_ffi {
10268
zend_object std;
10369
DL_HANDLE lib;
10470
HashTable *symbols;
10571
HashTable *tags;
106-
bool persistent;
72+
bool persistent;
10773
} zend_ffi;
10874

10975
#define ZEND_FFI_TYPE_MAKE_OWNED(t) \
@@ -128,7 +94,7 @@ static zend_internal_function zend_ffi_cast_fn;
12894
static zend_internal_function zend_ffi_type_fn;
12995

13096
/* forward declarations */
131-
//???static void _zend_ffi_type_dtor(zend_ffi_type *type);
97+
static void _zend_ffi_type_dtor(zend_ffi_type *type);
13298
static void zend_ffi_finalize_type(zend_ffi_dcl *dcl);
13399
static bool zend_ffi_is_same_type(zend_ffi_type *type1, zend_ffi_type *type2);
134100
static zend_ffi_type *zend_ffi_remember_type(zend_ffi_type *type);
@@ -2205,7 +2171,7 @@ static zend_object *zend_ffi_new(zend_class_entry *class_type) /* {{{ */
22052171
}
22062172
/* }}} */
22072173

2208-
ZEND_API void _zend_ffi_type_dtor(zend_ffi_type *type) /* {{{ */
2174+
static void _zend_ffi_type_dtor(zend_ffi_type *type) /* {{{ */
22092175
{
22102176
type = ZEND_FFI_TYPE(type);
22112177

@@ -2885,6 +2851,7 @@ ZEND_METHOD(FFI, cdef) /* {{{ */
28852851
DL_HANDLE handle = NULL;
28862852
char *err;
28872853
void *addr;
2854+
bool persistent = false;
28882855

28892856
ZEND_FFI_VALIDATE_API_RESTRICTION();
28902857
ZEND_PARSE_PARAMETERS_START(0, 2)
@@ -2922,9 +2889,14 @@ ZEND_METHOD(FFI, cdef) /* {{{ */
29222889
FFI_G(tags) = NULL;
29232890

29242891
if (code && ZSTR_LEN(code)) {
2925-
if (zend_ffi_cache_cdef_get) {
2926-
ffi = zend_ffi_cache_cdef_get(code);
2927-
if (ffi) {
2892+
if (zend_ffi_cache_scope_get) {
2893+
zend_ffi_scope *scope = zend_ffi_cache_scope_get(code);
2894+
if (scope) {
2895+
ffi = (zend_ffi*)zend_ffi_new(zend_ffi_ce);
2896+
ffi->lib = handle;
2897+
ffi->symbols = scope->symbols;
2898+
ffi->tags = scope->tags;
2899+
ffi->persistent = true;
29282900
RETURN_OBJ(&ffi->std);
29292901
}
29302902
}
@@ -2971,16 +2943,37 @@ ZEND_METHOD(FFI, cdef) /* {{{ */
29712943
}
29722944
} ZEND_HASH_FOREACH_END();
29732945
}
2946+
2947+
if (zend_ffi_cache_scope_add) {
2948+
zend_ffi_scope scope, *cached_scope;
2949+
2950+
scope.symbols = FFI_G(symbols);
2951+
scope.tags = FFI_G(tags);
2952+
cached_scope = zend_ffi_cache_scope_add(code, &scope);
2953+
if (cached_scope) {
2954+
if (FFI_G(symbols)) {
2955+
zend_hash_destroy(FFI_G(symbols));
2956+
efree(FFI_G(symbols));
2957+
FFI_G(symbols) = NULL;
2958+
}
2959+
if (FFI_G(tags)) {
2960+
zend_hash_destroy(FFI_G(tags));
2961+
efree(FFI_G(tags));
2962+
FFI_G(tags) = NULL;
2963+
}
2964+
FFI_G(symbols) = cached_scope->symbols;
2965+
FFI_G(tags) = cached_scope->tags;
2966+
persistent = true;
2967+
}
2968+
}
2969+
29742970
}
29752971

29762972
ffi = (zend_ffi*)zend_ffi_new(zend_ffi_ce);
29772973
ffi->lib = handle;
29782974
ffi->symbols = FFI_G(symbols);
29792975
ffi->tags = FFI_G(tags);
2980-
2981-
if (zend_ffi_cache_cdef_add) {
2982-
ffi = zend_ffi_cache_cdef_add(code, ffi);
2983-
}
2976+
ffi->persistent = persistent;
29842977

29852978
FFI_G(symbols) = NULL;
29862979
FFI_G(tags) = NULL;
@@ -3711,6 +3704,7 @@ ZEND_METHOD(FFI, new) /* {{{ */
37113704

37123705
if (type_def) {
37133706
zend_ffi_dcl dcl = ZEND_FFI_ATTR_INIT;
3707+
zend_ffi_dcl *cached_dcl;
37143708

37153709
if (!is_static_call) {
37163710
zend_ffi *ffi = (zend_ffi*)Z_OBJ(EX(This));
@@ -3726,8 +3720,8 @@ ZEND_METHOD(FFI, new) /* {{{ */
37263720
FFI_G(default_type_attr) = 0;
37273721

37283722
if (zend_ffi_cache_type_get
3729-
&& zend_ffi_cache_type_get(type_def, &dcl) == SUCCESS) {
3730-
/* pass */
3723+
&& (cached_dcl = zend_ffi_cache_type_get(type_def))) {
3724+
memcpy(&dcl, cached_dcl, sizeof(zend_ffi_dcl));
37313725
} else if (zend_ffi_parse_type(ZSTR_VAL(type_def), ZSTR_LEN(type_def), &dcl) == FAILURE) {
37323726
zend_ffi_type_dtor(dcl.type);
37333727
if (clean_tags && FFI_G(tags)) {
@@ -3754,7 +3748,13 @@ ZEND_METHOD(FFI, new) /* {{{ */
37543748
FFI_G(tags) = NULL;
37553749

37563750
if (zend_ffi_cache_type_add) {
3757-
zend_ffi_cache_type_add(type_def, &dcl);
3751+
cached_dcl = zend_ffi_cache_type_add(type_def, &dcl);
3752+
if (cached_dcl) {
3753+
if (ZEND_FFI_TYPE_IS_OWNED(dcl.type)) {
3754+
_zend_ffi_type_dtor(dcl.type);
3755+
}
3756+
memcpy(&dcl, cached_dcl, sizeof(zend_ffi_dcl));
3757+
}
37583758
}
37593759
}
37603760

@@ -3868,6 +3868,7 @@ ZEND_METHOD(FFI, cast) /* {{{ */
38683868

38693869
if (type_def) {
38703870
zend_ffi_dcl dcl = ZEND_FFI_ATTR_INIT;
3871+
zend_ffi_dcl *cached_dcl;
38713872

38723873
if (!is_static_call) {
38733874
zend_ffi *ffi = (zend_ffi*)Z_OBJ(EX(This));
@@ -3883,8 +3884,8 @@ ZEND_METHOD(FFI, cast) /* {{{ */
38833884
FFI_G(default_type_attr) = 0;
38843885

38853886
if (zend_ffi_cache_type_get
3886-
&& zend_ffi_cache_type_get(type_def, &dcl) == SUCCESS) {
3887-
/* pass */
3887+
&& (cached_dcl = zend_ffi_cache_type_get(type_def))) {
3888+
memcpy(&dcl, cached_dcl, sizeof(zend_ffi_dcl));
38883889
} else if (zend_ffi_parse_type(ZSTR_VAL(type_def), ZSTR_LEN(type_def), &dcl) == FAILURE) {
38893890
zend_ffi_type_dtor(dcl.type);
38903891
if (clean_tags && FFI_G(tags)) {
@@ -3911,7 +3912,13 @@ ZEND_METHOD(FFI, cast) /* {{{ */
39113912
FFI_G(tags) = NULL;
39123913

39133914
if (zend_ffi_cache_type_add) {
3914-
zend_ffi_cache_type_add(type_def, &dcl);
3915+
cached_dcl = zend_ffi_cache_type_add(type_def, &dcl);
3916+
if (cached_dcl) {
3917+
if (ZEND_FFI_TYPE_IS_OWNED(dcl.type)) {
3918+
_zend_ffi_type_dtor(dcl.type);
3919+
}
3920+
memcpy(&dcl, cached_dcl, sizeof(zend_ffi_dcl));
3921+
}
39153922
}
39163923
}
39173924

@@ -4033,6 +4040,7 @@ ZEND_METHOD(FFI, type) /* {{{ */
40334040
{
40344041
zend_ffi_ctype *ctype;
40354042
zend_ffi_dcl dcl = ZEND_FFI_ATTR_INIT;
4043+
zend_ffi_dcl *cached_dcl;
40364044
zend_string *type_def;
40374045
bool is_static_call = Z_TYPE(EX(This)) != IS_OBJECT;
40384046

@@ -4062,8 +4070,8 @@ ZEND_METHOD(FFI, type) /* {{{ */
40624070
FFI_G(default_type_attr) = 0;
40634071

40644072
if (zend_ffi_cache_type_get
4065-
&& zend_ffi_cache_type_get(type_def, &dcl) == SUCCESS) {
4066-
/* pass */
4073+
&& (cached_dcl = zend_ffi_cache_type_get(type_def))) {
4074+
memcpy(&dcl, cached_dcl, sizeof(zend_ffi_dcl));
40674075
} else if (zend_ffi_parse_type(ZSTR_VAL(type_def), ZSTR_LEN(type_def), &dcl) == FAILURE) {
40684076
zend_ffi_type_dtor(dcl.type);
40694077
if (clean_tags && FFI_G(tags)) {
@@ -4089,7 +4097,13 @@ ZEND_METHOD(FFI, type) /* {{{ */
40894097
FFI_G(symbols) = NULL;
40904098
FFI_G(tags) = NULL;
40914099
if (zend_ffi_cache_type_add) {
4092-
zend_ffi_cache_type_add(type_def, &dcl);
4100+
cached_dcl = zend_ffi_cache_type_add(type_def, &dcl);
4101+
if (cached_dcl) {
4102+
if (ZEND_FFI_TYPE_IS_OWNED(dcl.type)) {
4103+
_zend_ffi_type_dtor(dcl.type);
4104+
}
4105+
memcpy(&dcl, cached_dcl, sizeof(zend_ffi_dcl));
4106+
}
40934107
}
40944108
}
40954109

ext/ffi/php_ffi.h

+33-2
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,39 @@ typedef struct _zend_ffi_ctype {
360360
zend_ffi_type *type;
361361
} zend_ffi_ctype;
362362

363+
typedef enum _zend_ffi_tag_kind {
364+
ZEND_FFI_TAG_ENUM,
365+
ZEND_FFI_TAG_STRUCT,
366+
ZEND_FFI_TAG_UNION
367+
} zend_ffi_tag_kind;
368+
369+
typedef struct _zend_ffi_tag {
370+
zend_ffi_tag_kind kind;
371+
zend_ffi_type *type;
372+
} zend_ffi_tag;
373+
374+
typedef enum _zend_ffi_symbol_kind {
375+
ZEND_FFI_SYM_TYPE,
376+
ZEND_FFI_SYM_CONST,
377+
ZEND_FFI_SYM_VAR,
378+
ZEND_FFI_SYM_FUNC
379+
} zend_ffi_symbol_kind;
380+
381+
typedef struct _zend_ffi_symbol {
382+
zend_ffi_symbol_kind kind;
383+
bool is_const;
384+
zend_ffi_type *type;
385+
union {
386+
void *addr;
387+
int64_t value;
388+
};
389+
} zend_ffi_symbol;
390+
391+
typedef struct _zend_ffi_scope {
392+
HashTable *symbols;
393+
HashTable *tags;
394+
} zend_ffi_scope;
395+
363396
#define ZEND_FFI_TYPE_OWNED (1<<0)
364397

365398
#define ZEND_FFI_TYPE(t) \
@@ -368,6 +401,4 @@ typedef struct _zend_ffi_ctype {
368401
#define ZEND_FFI_TYPE_IS_OWNED(t) \
369402
(((uintptr_t)(t)) & ZEND_FFI_TYPE_OWNED)
370403

371-
ZEND_API void _zend_ffi_type_dtor(zend_ffi_type *type);
372-
373404
#endif /* PHP_FFI_H */

0 commit comments

Comments
 (0)