Skip to content

Commit b3bbb8f

Browse files
committed
Mark classes cached by opcache by ZEND_ACC_CACHED flag and prevent useless copying and desrpoying of immutable data.
1 parent c195fcd commit b3bbb8f

File tree

5 files changed

+43
-80
lines changed

5 files changed

+43
-80
lines changed

Zend/zend_compile.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ typedef struct _zend_oparray_context {
238238
/* op_array or class is preloaded | | | */
239239
#define ZEND_ACC_PRELOADED (1 << 10) /* X | X | | */
240240
/* | | | */
241-
/* Class Flags (unused: 22...) | | | */
241+
/* Class Flags (unused: 23...) | | | */
242242
/* =========== | | | */
243243
/* | | | */
244244
/* Special class types | | | */
@@ -287,6 +287,9 @@ typedef struct _zend_oparray_context {
287287
/* Whether this class was used in its unlinked state. | | | */
288288
#define ZEND_ACC_HAS_UNLINKED_USES (1 << 21) /* X | | | */
289289
/* | | | */
290+
/* stored in opcache (may be partially) | | | */
291+
#define ZEND_ACC_CACHED (1 << 22) /* X | | | */
292+
/* | | | */
290293
/* Function Flags (unused: 27-30) | | | */
291294
/* ============== | | | */
292295
/* | | | */

Zend/zend_inheritance.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1549,11 +1549,13 @@ static void zend_do_implement_interfaces(zend_class_entry *ce, zend_class_entry
15491549
}
15501550
}
15511551

1552-
for (i = 0; i < ce->num_interfaces; i++) {
1553-
zend_string_release_ex(ce->interface_names[i].name, 0);
1554-
zend_string_release_ex(ce->interface_names[i].lc_name, 0);
1552+
if (!(ce->ce_flags & ZEND_ACC_CACHED)) {
1553+
for (i = 0; i < ce->num_interfaces; i++) {
1554+
zend_string_release_ex(ce->interface_names[i].name, 0);
1555+
zend_string_release_ex(ce->interface_names[i].lc_name, 0);
1556+
}
1557+
efree(ce->interface_names);
15551558
}
1556-
efree(ce->interface_names);
15571559

15581560
ce->num_interfaces = num_interfaces;
15591561
ce->interfaces = interfaces;

Zend/zend_opcode.c

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -280,9 +280,37 @@ ZEND_API void destroy_zend_class(zval *zv)
280280
}
281281
switch (ce->type) {
282282
case ZEND_USER_CLASS:
283-
if (ce->parent_name && !(ce->ce_flags & ZEND_ACC_RESOLVED_PARENT)) {
284-
zend_string_release_ex(ce->parent_name, 0);
283+
if (!(ce->ce_flags & ZEND_ACC_CACHED)) {
284+
if (ce->parent_name && !(ce->ce_flags & ZEND_ACC_RESOLVED_PARENT)) {
285+
zend_string_release_ex(ce->parent_name, 0);
286+
}
287+
288+
zend_string_release_ex(ce->name, 0);
289+
zend_string_release_ex(ce->info.user.filename, 0);
290+
291+
if (ce->info.user.doc_comment) {
292+
zend_string_release_ex(ce->info.user.doc_comment, 0);
293+
}
294+
295+
if (ce->attributes) {
296+
zend_hash_release(ce->attributes);
297+
}
298+
299+
if (ce->num_interfaces > 0 && !(ce->ce_flags & ZEND_ACC_RESOLVED_INTERFACES)) {
300+
uint32_t i;
301+
302+
for (i = 0; i < ce->num_interfaces; i++) {
303+
zend_string_release_ex(ce->interface_names[i].name, 0);
304+
zend_string_release_ex(ce->interface_names[i].lc_name, 0);
305+
}
306+
efree(ce->interface_names);
307+
}
308+
309+
if (ce->num_traits > 0) {
310+
_destroy_zend_class_traits_info(ce);
311+
}
285312
}
313+
286314
if (ce->default_properties_table) {
287315
zval *p = ce->default_properties_table;
288316
zval *end = p + ce->default_properties_count;
@@ -325,7 +353,6 @@ ZEND_API void destroy_zend_class(zval *zv)
325353
}
326354
} ZEND_HASH_FOREACH_END();
327355
zend_hash_destroy(&ce->properties_info);
328-
zend_string_release_ex(ce->name, 0);
329356
zend_hash_destroy(&ce->function_table);
330357
if (zend_hash_num_elements(&ce->constants_table)) {
331358
zend_class_constant *c;
@@ -343,29 +370,9 @@ ZEND_API void destroy_zend_class(zval *zv)
343370
} ZEND_HASH_FOREACH_END();
344371
}
345372
zend_hash_destroy(&ce->constants_table);
346-
if (ce->num_interfaces > 0) {
347-
if (!(ce->ce_flags & ZEND_ACC_RESOLVED_INTERFACES)) {
348-
uint32_t i;
349-
350-
for (i = 0; i < ce->num_interfaces; i++) {
351-
zend_string_release_ex(ce->interface_names[i].name, 0);
352-
zend_string_release_ex(ce->interface_names[i].lc_name, 0);
353-
}
354-
}
373+
if (ce->num_interfaces > 0 && (ce->ce_flags & ZEND_ACC_RESOLVED_INTERFACES)) {
355374
efree(ce->interfaces);
356375
}
357-
zend_string_release_ex(ce->info.user.filename, 0);
358-
if (ce->info.user.doc_comment) {
359-
zend_string_release_ex(ce->info.user.doc_comment, 0);
360-
}
361-
if (ce->attributes) {
362-
zend_hash_release(ce->attributes);
363-
}
364-
365-
if (ce->num_traits > 0) {
366-
_destroy_zend_class_traits_info(ce);
367-
}
368-
369376
break;
370377
case ZEND_INTERNAL_CLASS:
371378
if (ce->default_properties_table) {

ext/opcache/zend_accelerator_util_funcs.c

Lines changed: 1 addition & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -333,13 +333,7 @@ static void zend_class_copy_ctor(zend_class_entry **pce)
333333
}
334334

335335
if (ce->num_interfaces) {
336-
zend_class_name *interface_names;
337-
338-
if (!(ce->ce_flags & ZEND_ACC_LINKED)) {
339-
interface_names = emalloc(sizeof(zend_class_name) * ce->num_interfaces);
340-
memcpy(interface_names, ce->interface_names, sizeof(zend_class_name) * ce->num_interfaces);
341-
ce->interface_names = interface_names;
342-
} else {
336+
if (ce->ce_flags & ZEND_ACC_LINKED) {
343337
zend_class_entry **interfaces = emalloc(sizeof(zend_class_entry*) * ce->num_interfaces);
344338
uint32_t i;
345339

@@ -367,50 +361,6 @@ static void zend_class_copy_ctor(zend_class_entry **pce)
367361
zend_update_inherited_handler(__debugInfo);
368362
zend_update_inherited_handler(__serialize);
369363
zend_update_inherited_handler(__unserialize);
370-
371-
/* 5.4 traits */
372-
if (ce->num_traits) {
373-
zend_class_name *trait_names = emalloc(sizeof(zend_class_name) * ce->num_traits);
374-
375-
memcpy(trait_names, ce->trait_names, sizeof(zend_class_name) * ce->num_traits);
376-
ce->trait_names = trait_names;
377-
378-
if (ce->trait_aliases) {
379-
zend_trait_alias **trait_aliases;
380-
int i = 0;
381-
382-
while (ce->trait_aliases[i]) {
383-
i++;
384-
}
385-
trait_aliases = emalloc(sizeof(zend_trait_alias*) * (i + 1));
386-
i = 0;
387-
while (ce->trait_aliases[i]) {
388-
trait_aliases[i] = emalloc(sizeof(zend_trait_alias));
389-
memcpy(trait_aliases[i], ce->trait_aliases[i], sizeof(zend_trait_alias));
390-
i++;
391-
}
392-
trait_aliases[i] = NULL;
393-
ce->trait_aliases = trait_aliases;
394-
}
395-
396-
if (ce->trait_precedences) {
397-
zend_trait_precedence **trait_precedences;
398-
int i = 0;
399-
400-
while (ce->trait_precedences[i]) {
401-
i++;
402-
}
403-
trait_precedences = emalloc(sizeof(zend_trait_precedence*) * (i + 1));
404-
i = 0;
405-
while (ce->trait_precedences[i]) {
406-
trait_precedences[i] = emalloc(sizeof(zend_trait_precedence) + (ce->trait_precedences[i]->num_excludes - 1) * sizeof(zend_string*));
407-
memcpy(trait_precedences[i], ce->trait_precedences[i], sizeof(zend_trait_precedence) + (ce->trait_precedences[i]->num_excludes - 1) * sizeof(zend_string*));
408-
i++;
409-
}
410-
trait_precedences[i] = NULL;
411-
ce->trait_precedences = trait_precedences;
412-
}
413-
}
414364
}
415365

416366
static void zend_accel_function_hash_copy(HashTable *target, HashTable *source)

ext/opcache/zend_persist.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -806,6 +806,7 @@ static void zend_persist_class_entry(zval *zv)
806806
ZCG(is_immutable_class) = 0;
807807
ce = Z_PTR_P(zv) = zend_shared_memdup_arena_put(ce, sizeof(zend_class_entry));
808808
}
809+
ce->ce_flags |= ZEND_ACC_CACHED;
809810
zend_accel_store_interned_string(ce->name);
810811
if (ce->parent_name && !(ce->ce_flags & ZEND_ACC_LINKED)) {
811812
zend_accel_store_interned_string(ce->parent_name);

0 commit comments

Comments
 (0)