Skip to content

Commit 6aea64c

Browse files
committed
Reuse single map_ptr slot for indentical class names
1 parent 89c55af commit 6aea64c

File tree

4 files changed

+58
-14
lines changed

4 files changed

+58
-14
lines changed

ext/opcache/ZendAccelerator.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,7 @@ zend_string* ZEND_FASTCALL accel_new_interned_string(zend_string *str)
505505
hash_slot = STRTAB_HASH_TO_SLOT(&ZCSG(interned_strings), h);
506506
STRTAB_COLLISION(s) = *hash_slot;
507507
*hash_slot = STRTAB_STR_TO_POS(&ZCSG(interned_strings), s);
508-
GC_SET_REFCOUNT(s, 1);
508+
GC_SET_REFCOUNT(s, 2);
509509
GC_TYPE_INFO(s) = GC_STRING | ((IS_STR_INTERNED | IS_STR_PERMANENT) << GC_FLAGS_SHIFT);
510510
ZSTR_H(s) = h;
511511
ZSTR_LEN(s) = ZSTR_LEN(str);

ext/opcache/ZendAccelerator.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,8 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type);
329329

330330
zend_string* ZEND_FASTCALL accel_new_interned_string(zend_string *str);
331331

332+
uint32_t zend_accel_get_type_map_ptr(zend_string *type_name, zend_class_entry *scope);
333+
332334
/* memory write protection */
333335
#define SHM_PROTECT() \
334336
do { \

ext/opcache/zend_file_cache.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,7 +1190,7 @@ static void zend_file_cache_unserialize_attribute(zval *zv, zend_persistent_scri
11901190
}
11911191

11921192
static void zend_file_cache_unserialize_type(
1193-
zend_type *type, zend_persistent_script *script, void *buf)
1193+
zend_type *type, zend_class_entry *scope, zend_persistent_script *script, void *buf)
11941194
{
11951195
if (ZEND_TYPE_HAS_LIST(*type)) {
11961196
zend_type_list *list = ZEND_TYPE_LIST(*type);
@@ -1199,16 +1199,21 @@ static void zend_file_cache_unserialize_type(
11991199

12001200
zend_type *list_type;
12011201
ZEND_TYPE_LIST_FOREACH(list, list_type) {
1202-
zend_file_cache_unserialize_type(list_type, script, buf);
1202+
zend_file_cache_unserialize_type(list_type, scope, script, buf);
12031203
} ZEND_TYPE_LIST_FOREACH_END();
12041204
} else if (ZEND_TYPE_HAS_NAME(*type)) {
12051205
zend_string *type_name = ZEND_TYPE_NAME(*type);
12061206
UNSERIALIZE_STR(type_name);
12071207
ZEND_TYPE_SET_PTR(*type, type_name);
12081208
if (!(script->corrupted)) {
1209-
// TODO: we may use single map_ptr slot for each class name ???
1210-
type->type_mask |= _ZEND_TYPE_CACHE_BIT;
1211-
type->ce_cache__ptr = (uint32_t)(uintptr_t)zend_map_ptr_new();
1209+
uint32_t ptr = zend_accel_get_type_map_ptr(type_name, scope);
1210+
1211+
if (ptr) {
1212+
type->type_mask |= _ZEND_TYPE_CACHE_BIT;
1213+
type->ce_cache__ptr = ptr;
1214+
} else {
1215+
type->type_mask &= ~_ZEND_TYPE_CACHE_BIT;
1216+
}
12121217
} else {
12131218
type->type_mask &= ~_ZEND_TYPE_CACHE_BIT;
12141219
}
@@ -1362,7 +1367,7 @@ static void zend_file_cache_unserialize_op_array(zend_op_array *op_arr
13621367
if (!IS_UNSERIALIZED(p->name)) {
13631368
UNSERIALIZE_STR(p->name);
13641369
}
1365-
zend_file_cache_unserialize_type(&p->type, script, buf);
1370+
zend_file_cache_unserialize_type(&p->type, op_array->scope, script, buf);
13661371
p++;
13671372
}
13681373
}
@@ -1421,7 +1426,7 @@ static void zend_file_cache_unserialize_prop_info(zval *zv,
14211426
UNSERIALIZE_STR(prop->doc_comment);
14221427
}
14231428
UNSERIALIZE_ATTRIBUTES(prop->attributes);
1424-
zend_file_cache_unserialize_type(&prop->type, script, buf);
1429+
zend_file_cache_unserialize_type(&prop->type, prop->ce, script, buf);
14251430
}
14261431
}
14271432
}

ext/opcache/zend_persist.c

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#endif
3737

3838
#define zend_set_str_gc_flags(str) do { \
39+
GC_SET_REFCOUNT(str, 2); \
3940
if (file_cache_only) { \
4041
GC_TYPE_INFO(str) = GC_STRING | (IS_STR_INTERNED << GC_FLAGS_SHIFT); \
4142
} else { \
@@ -290,7 +291,40 @@ static HashTable *zend_persist_attributes(HashTable *attributes)
290291
return ptr;
291292
}
292293

293-
static void zend_persist_type(zend_type *type) {
294+
uint32_t zend_accel_get_type_map_ptr(zend_string *type_name, zend_class_entry *scope)
295+
{
296+
uint32_t ret;
297+
298+
if (zend_string_equals_literal_ci(type_name, "self")) {
299+
if (!scope) {
300+
return 0;
301+
}
302+
type_name = scope->name;
303+
} else if (zend_string_equals_literal_ci(type_name, "parent")) {
304+
if (!scope || !scope->parent) {
305+
return 0;
306+
}
307+
if (scope->ce_flags & ZEND_ACC_RESOLVED_PARENT) {
308+
type_name = scope->parent->name;
309+
} else {
310+
type_name = scope->parent_name;
311+
}
312+
}
313+
314+
ZEND_ASSERT(GC_FLAGS(type_name) & GC_IMMUTABLE);
315+
ZEND_ASSERT(GC_FLAGS(type_name) & IS_STR_PERMANENT);
316+
ret = GC_REFCOUNT(type_name);
317+
318+
/* We use type.name.gc.refcount to keep map_ptr of corresponding type */
319+
if (ret <= 2) {
320+
ret = (uint32_t)(uintptr_t)zend_map_ptr_new();
321+
ZEND_ASSERT(ret > 2);
322+
GC_SET_REFCOUNT(type_name, ret);
323+
}
324+
return ret;
325+
}
326+
327+
static void zend_persist_type(zend_type *type, zend_class_entry *scope) {
294328
if (ZEND_TYPE_HAS_LIST(*type)) {
295329
zend_type_list *list = ZEND_TYPE_LIST(*type);
296330
if (ZEND_TYPE_USES_ARENA(*type)) {
@@ -309,9 +343,12 @@ static void zend_persist_type(zend_type *type) {
309343
zend_accel_store_interned_string(type_name);
310344
ZEND_TYPE_SET_PTR(*single_type, type_name);
311345
if (!ZCG(current_persistent_script)->corrupted) {
312-
// TODO: we may use single map_ptr slot for each class name ???
313-
single_type->type_mask |= _ZEND_TYPE_CACHE_BIT;
314-
single_type->ce_cache__ptr = (uint32_t)(uintptr_t)zend_map_ptr_new();
346+
uint32_t ptr = zend_accel_get_type_map_ptr(type_name, scope);
347+
348+
if (ptr) {
349+
single_type->type_mask |= _ZEND_TYPE_CACHE_BIT;
350+
single_type->ce_cache__ptr = ptr;
351+
}
315352
}
316353
}
317354
} ZEND_TYPE_FOREACH_END();
@@ -584,7 +621,7 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
584621
if (arg_info[i].name) {
585622
zend_accel_store_interned_string(arg_info[i].name);
586623
}
587-
zend_persist_type(&arg_info[i].type);
624+
zend_persist_type(&arg_info[i].type, op_array->scope);
588625
}
589626
if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
590627
arg_info++;
@@ -743,7 +780,7 @@ static zend_property_info *zend_persist_property_info(zend_property_info *prop)
743780
if (prop->attributes) {
744781
prop->attributes = zend_persist_attributes(prop->attributes);
745782
}
746-
zend_persist_type(&prop->type);
783+
zend_persist_type(&prop->type, ce);
747784
return prop;
748785
}
749786

0 commit comments

Comments
 (0)