mirror of
https://github.com/php/php-src.git
synced 2025-08-16 14:08:47 +02:00
Used string with biased hash for double deduplication
Rather than using a separate hash table for doubles, use the same biases hash approach we use for everything else. Either way works fine, but there doesn't seem to be any strong reason to use a different approach for doubles than we use for other cases.
This commit is contained in:
parent
83e0a5d2a7
commit
cc506a81e1
1 changed files with 17 additions and 13 deletions
|
@ -100,6 +100,13 @@ static uint32_t add_static_slot(HashTable *hash,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void bias_key(zend_string *key, uint32_t bias)
|
||||||
|
{
|
||||||
|
/* Add a bias to the hash so we can distinguish string keys
|
||||||
|
* that would otherwise be the same. */
|
||||||
|
ZSTR_H(key) = zend_string_hash_val(key) + bias;
|
||||||
|
}
|
||||||
|
|
||||||
static zend_string *create_str_cache_key(zval *literal, uint8_t num_related)
|
static zend_string *create_str_cache_key(zval *literal, uint8_t num_related)
|
||||||
{
|
{
|
||||||
ZEND_ASSERT(Z_TYPE_P(literal) == IS_STRING);
|
ZEND_ASSERT(Z_TYPE_P(literal) == IS_STRING);
|
||||||
|
@ -124,9 +131,7 @@ static zend_string *create_str_cache_key(zval *literal, uint8_t num_related)
|
||||||
ZEND_ASSERT(0 && "Currently not needed");
|
ZEND_ASSERT(0 && "Currently not needed");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add a bias to the hash so we can distinguish keys
|
bias_key(key, num_related - 1);
|
||||||
* that would otherwise be the same after concatenation. */
|
|
||||||
ZSTR_H(key) = zend_string_hash_val(key) + num_related - 1;
|
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,7 +146,7 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
|
||||||
int l_false = -1;
|
int l_false = -1;
|
||||||
int l_true = -1;
|
int l_true = -1;
|
||||||
int l_empty_arr = -1;
|
int l_empty_arr = -1;
|
||||||
HashTable hash, double_hash;
|
HashTable hash;
|
||||||
zend_string *key = NULL;
|
zend_string *key = NULL;
|
||||||
void *checkpoint = zend_arena_checkpoint(ctx->arena);
|
void *checkpoint = zend_arena_checkpoint(ctx->arena);
|
||||||
int *const_slot, *class_slot, *func_slot, *bind_var_slot, *property_slot, *method_slot;
|
int *const_slot, *class_slot, *func_slot, *bind_var_slot, *property_slot, *method_slot;
|
||||||
|
@ -285,8 +290,6 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
|
||||||
/* Merge equal constants */
|
/* Merge equal constants */
|
||||||
j = 0;
|
j = 0;
|
||||||
zend_hash_init(&hash, op_array->last_literal, NULL, NULL, 0);
|
zend_hash_init(&hash, op_array->last_literal, NULL, NULL, 0);
|
||||||
/* Use separate hashtable for doubles stored as string keys, to avoid collisions. */
|
|
||||||
zend_hash_init(&double_hash, 0, NULL, NULL, 0);
|
|
||||||
map = (int*)zend_arena_alloc(&ctx->arena, op_array->last_literal * sizeof(int));
|
map = (int*)zend_arena_alloc(&ctx->arena, op_array->last_literal * sizeof(int));
|
||||||
memset(map, 0, op_array->last_literal * sizeof(int));
|
memset(map, 0, op_array->last_literal * sizeof(int));
|
||||||
for (i = 0; i < op_array->last_literal; i++) {
|
for (i = 0; i < op_array->last_literal; i++) {
|
||||||
|
@ -349,10 +352,9 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
|
||||||
} else {
|
} else {
|
||||||
ZEND_ASSERT(info[i].num_related == 2);
|
ZEND_ASSERT(info[i].num_related == 2);
|
||||||
key = zend_string_init(Z_STRVAL(op_array->literals[i+1]), Z_STRLEN(op_array->literals[i+1]), 0);
|
key = zend_string_init(Z_STRVAL(op_array->literals[i+1]), Z_STRLEN(op_array->literals[i+1]), 0);
|
||||||
ZSTR_H(key) = ZSTR_HASH(Z_STR(op_array->literals[i+1])) + 100 +
|
bias_key(key, 100 + info[i].num_related - 1);
|
||||||
info[i].num_related - 1;
|
if ((pos = zend_hash_find(&hash, key)) != NULL) {
|
||||||
if ((pos = zend_hash_find(&hash, key)) != NULL
|
ZEND_ASSERT(info[Z_LVAL_P(pos)].num_related == 2);
|
||||||
&& info[Z_LVAL_P(pos)].num_related == 2) {
|
|
||||||
map[i] = Z_LVAL_P(pos);
|
map[i] = Z_LVAL_P(pos);
|
||||||
zval_ptr_dtor_nogc(&op_array->literals[i+1]);
|
zval_ptr_dtor_nogc(&op_array->literals[i+1]);
|
||||||
} else {
|
} else {
|
||||||
|
@ -373,18 +375,21 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
|
||||||
break;
|
break;
|
||||||
case IS_DOUBLE:
|
case IS_DOUBLE:
|
||||||
ZEND_ASSERT(info[i].num_related == 1);
|
ZEND_ASSERT(info[i].num_related == 1);
|
||||||
if ((pos = zend_hash_str_find(&double_hash, (char*)&Z_DVAL(op_array->literals[i]), sizeof(double))) != NULL) {
|
key = zend_string_init((char*)&Z_DVAL(op_array->literals[i]), sizeof(double), 0);
|
||||||
|
bias_key(key, 200);
|
||||||
|
if ((pos = zend_hash_find(&hash, key))) {
|
||||||
map[i] = Z_LVAL_P(pos);
|
map[i] = Z_LVAL_P(pos);
|
||||||
} else {
|
} else {
|
||||||
map[i] = j;
|
map[i] = j;
|
||||||
ZVAL_LONG(&zv, j);
|
ZVAL_LONG(&zv, j);
|
||||||
zend_hash_str_add_new(&double_hash, (char*)&Z_DVAL(op_array->literals[i]), sizeof(double), &zv);
|
zend_hash_add_new(&hash, key, &zv);
|
||||||
if (i != j) {
|
if (i != j) {
|
||||||
op_array->literals[j] = op_array->literals[i];
|
op_array->literals[j] = op_array->literals[i];
|
||||||
info[j] = info[i];
|
info[j] = info[i];
|
||||||
}
|
}
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
|
zend_string_release_ex(key, 0);
|
||||||
break;
|
break;
|
||||||
case IS_STRING: {
|
case IS_STRING: {
|
||||||
key = create_str_cache_key(&op_array->literals[i], info[i].num_related);
|
key = create_str_cache_key(&op_array->literals[i], info[i].num_related);
|
||||||
|
@ -452,7 +457,6 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
|
||||||
|
|
||||||
/* Only clean "hash", as it will be reused in the loop below. */
|
/* Only clean "hash", as it will be reused in the loop below. */
|
||||||
zend_hash_clean(&hash);
|
zend_hash_clean(&hash);
|
||||||
zend_hash_destroy(&double_hash);
|
|
||||||
op_array->last_literal = j;
|
op_array->last_literal = j;
|
||||||
|
|
||||||
const_slot = zend_arena_alloc(&ctx->arena, j * 6 * sizeof(int));
|
const_slot = zend_arena_alloc(&ctx->arena, j * 6 * sizeof(int));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue