Skip to content

Commit 7cf1c27

Browse files
committed
Merge branch 'PHP-8.0'
* PHP-8.0: Fixed bug #81046
2 parents 671fd3f + c446d68 commit 7cf1c27

File tree

2 files changed

+55
-10
lines changed

2 files changed

+55
-10
lines changed

Zend/Optimizer/compact_literals.c

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,41 @@ static uint32_t add_static_slot(HashTable *hash,
112112
return ret;
113113
}
114114

115+
static zend_string *create_str_cache_key(zval *literal, uint32_t flags)
116+
{
117+
ZEND_ASSERT(Z_TYPE_P(literal) == IS_STRING);
118+
uint32_t num_related = LITERAL_NUM_RELATED(flags);
119+
if (num_related == 1) {
120+
return zend_string_copy(Z_STR_P(literal));
121+
}
122+
if ((flags & LITERAL_KIND_MASK) == LITERAL_VALUE) {
123+
/* Don't merge LITERAL_VALUE that has related literals */
124+
return NULL;
125+
}
126+
127+
/* Concatenate all the related literals for the cache key. */
128+
zend_string *key;
129+
if (num_related == 2) {
130+
ZEND_ASSERT(Z_TYPE_P(literal + 1) == IS_STRING);
131+
key = zend_string_concat2(
132+
Z_STRVAL_P(literal), Z_STRLEN_P(literal),
133+
Z_STRVAL_P(literal + 1), Z_STRLEN_P(literal + 1));
134+
} else if (num_related == 3) {
135+
ZEND_ASSERT(Z_TYPE_P(literal + 1) == IS_STRING && Z_TYPE_P(literal + 2) == IS_STRING);
136+
key = zend_string_concat3(
137+
Z_STRVAL_P(literal), Z_STRLEN_P(literal),
138+
Z_STRVAL_P(literal + 1), Z_STRLEN_P(literal + 1),
139+
Z_STRVAL_P(literal + 2), Z_STRLEN_P(literal + 2));
140+
} else {
141+
ZEND_ASSERT(0 && "Currently not needed");
142+
}
143+
144+
/* Add a bias to the hash so we can distinguish keys
145+
* that would otherwise be the same after concatenation. */
146+
ZSTR_H(key) = zend_string_hash_val(key) + num_related - 1;
147+
return key;
148+
}
149+
115150
void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx *ctx)
116151
{
117152
zend_op *opline, *end;
@@ -403,16 +438,7 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
403438
}
404439
break;
405440
case IS_STRING: {
406-
if (LITERAL_NUM_RELATED(info[i].flags) == 1) {
407-
key = zend_string_copy(Z_STR(op_array->literals[i]));
408-
} else if ((info[i].flags & LITERAL_KIND_MASK) != LITERAL_VALUE) {
409-
key = zend_string_init(Z_STRVAL(op_array->literals[i]), Z_STRLEN(op_array->literals[i]), 0);
410-
ZSTR_H(key) = ZSTR_HASH(Z_STR(op_array->literals[i])) +
411-
LITERAL_NUM_RELATED(info[i].flags) - 1;
412-
} else {
413-
/* Don't merge LITERAL_VALUE that has related literals */
414-
key = NULL;
415-
}
441+
key = create_str_cache_key(&op_array->literals[i], info[i].flags);
416442
if (key && (pos = zend_hash_find(&hash, key)) != NULL &&
417443
Z_TYPE(op_array->literals[Z_LVAL_P(pos)]) == IS_STRING &&
418444
LITERAL_NUM_RELATED(info[i].flags) == LITERAL_NUM_RELATED(info[Z_LVAL_P(pos)].flags) &&

ext/opcache/tests/bug81046.phpt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
Bug #81046: Literal compaction merges non-equal related literals
3+
--FILE--
4+
<?php
5+
6+
class Test {
7+
static function methoD() {
8+
echo "Method called\n";
9+
}
10+
}
11+
12+
const methoD = 1;
13+
var_dump(methoD);
14+
test::methoD();
15+
16+
?>
17+
--EXPECT--
18+
int(1)
19+
Method called

0 commit comments

Comments
 (0)