Skip to content

Commit e0ee9f2

Browse files
committed
Cache FFI scope created by FFI::load()
1 parent 3e43ed6 commit e0ee9f2

File tree

1 file changed

+49
-12
lines changed

1 file changed

+49
-12
lines changed

ext/ffi/ffi.c

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2966,7 +2966,6 @@ ZEND_METHOD(FFI, cdef) /* {{{ */
29662966
persistent = true;
29672967
}
29682968
}
2969-
29702969
}
29712970

29722971
ffi = (zend_ffi*)zend_ffi_new(zend_ffi_ce);
@@ -3167,7 +3166,8 @@ static zend_ffi *zend_ffi_load(const char *filename, bool preload) /* {{{ */
31673166
{
31683167
struct stat buf;
31693168
int fd;
3170-
char *code, *code_pos, *scope_name, *lib, *err;
3169+
zend_string *code;
3170+
char *code_pos, *scope_name, *lib, *err;
31713171
size_t code_size, scope_name_len;
31723172
zend_ffi *ffi;
31733173
DL_HANDLE handle = NULL;
@@ -3176,6 +3176,7 @@ static zend_ffi *zend_ffi_load(const char *filename, bool preload) /* {{{ */
31763176
zend_ffi_symbol *sym;
31773177
zend_ffi_tag *tag;
31783178
void *addr;
3179+
bool persistent = false;
31793180

31803181
if (stat(filename, &buf) != 0) {
31813182
if (preload) {
@@ -3196,24 +3197,36 @@ static zend_ffi *zend_ffi_load(const char *filename, bool preload) /* {{{ */
31963197
}
31973198

31983199
code_size = buf.st_size;
3199-
code = emalloc(code_size + 1);
3200+
code = zend_string_alloc(code_size, 0);
32003201
int open_flags = O_RDONLY;
32013202
#ifdef PHP_WIN32
32023203
open_flags |= _O_BINARY;
32033204
#endif
32043205
fd = open(filename, open_flags, 0);
3205-
if (fd < 0 || read(fd, code, code_size) != code_size) {
3206+
if (fd < 0 || read(fd, ZSTR_VAL(code), code_size) != code_size) {
32063207
if (preload) {
32073208
zend_error(E_WARNING, "FFI: Failed pre-loading '%s', cannot read_file", filename);
32083209
} else {
32093210
zend_throw_error(zend_ffi_exception_ce, "Failed loading '%s', cannot read_file", filename);
32103211
}
3211-
efree(code);
3212+
zend_string_release(code);
32123213
close(fd);
32133214
return NULL;
32143215
}
32153216
close(fd);
3216-
code[code_size] = 0;
3217+
ZSTR_VAL(code)[code_size] = 0;
3218+
3219+
if (!preload && zend_ffi_cache_scope_get) {
3220+
zend_ffi_scope *scope = zend_ffi_cache_scope_get(code);
3221+
if (scope) {
3222+
ffi = (zend_ffi*)zend_ffi_new(zend_ffi_ce);
3223+
ffi->lib = handle;
3224+
ffi->symbols = scope->symbols;
3225+
ffi->tags = scope->tags;
3226+
ffi->persistent = true;
3227+
return ffi;
3228+
}
3229+
}
32173230

32183231
FFI_G(symbols) = NULL;
32193232
FFI_G(tags) = NULL;
@@ -3225,13 +3238,13 @@ static zend_ffi *zend_ffi_load(const char *filename, bool preload) /* {{{ */
32253238
scope_name = NULL;
32263239
scope_name_len = 0;
32273240
lib = NULL;
3228-
code_pos = zend_ffi_parse_directives(filename, code, &scope_name, &lib, preload);
3241+
code_pos = zend_ffi_parse_directives(filename, ZSTR_VAL(code), &scope_name, &lib, preload);
32293242
if (!code_pos) {
3230-
efree(code);
3243+
zend_string_release(code);
32313244
FFI_G(persistent) = 0;
32323245
return NULL;
32333246
}
3234-
code_size -= code_pos - code;
3247+
code_size -= code_pos - ZSTR_VAL(code);
32353248

32363249
if (zend_ffi_parse_decl(code_pos, code_size) == FAILURE) {
32373250
if (preload) {
@@ -3414,21 +3427,45 @@ static zend_ffi *zend_ffi_load(const char *filename, bool preload) /* {{{ */
34143427
ffi->tags = scope->tags;
34153428
ffi->persistent = 1;
34163429
} else {
3430+
if (zend_ffi_cache_scope_add) {
3431+
zend_ffi_scope scope, *cached_scope;
3432+
3433+
scope.symbols = FFI_G(symbols);
3434+
scope.tags = FFI_G(tags);
3435+
cached_scope = zend_ffi_cache_scope_add(code, &scope);
3436+
if (cached_scope) {
3437+
if (FFI_G(symbols)) {
3438+
zend_hash_destroy(FFI_G(symbols));
3439+
efree(FFI_G(symbols));
3440+
FFI_G(symbols) = NULL;
3441+
}
3442+
if (FFI_G(tags)) {
3443+
zend_hash_destroy(FFI_G(tags));
3444+
efree(FFI_G(tags));
3445+
FFI_G(tags) = NULL;
3446+
}
3447+
FFI_G(symbols) = cached_scope->symbols;
3448+
FFI_G(tags) = cached_scope->tags;
3449+
persistent = true;
3450+
}
3451+
}
3452+
34173453
ffi = (zend_ffi*)zend_ffi_new(zend_ffi_ce);
34183454
ffi->lib = handle;
34193455
ffi->symbols = FFI_G(symbols);
34203456
ffi->tags = FFI_G(tags);
3457+
ffi->persistent = persistent;
34213458
}
34223459

3423-
efree(code);
3460+
zend_string_release(code);
34243461
FFI_G(symbols) = NULL;
34253462
FFI_G(tags) = NULL;
3426-
FFI_G(persistent) = 0;
3463+
FFI_G(persistent) = persistent;
34273464

34283465
return ffi;
34293466

34303467
cleanup:
3431-
efree(code);
3468+
zend_string_release(code);
34323469
if (FFI_G(symbols)) {
34333470
zend_hash_destroy(FFI_G(symbols));
34343471
pefree(FFI_G(symbols), preload);

0 commit comments

Comments
 (0)