Made run_time_cache to keep "offset" to dynamic properties Buckets (instead of index).

This commit is contained in:
Dmitry Stogov 2017-10-24 10:28:19 +03:00
parent 8f804a2128
commit 59a7944bc6
5 changed files with 286 additions and 288 deletions

View file

@ -1883,7 +1883,7 @@ static zend_always_inline void zend_fetch_property_address(zval *result, zval *c
}
if (prop_op_type == IS_CONST &&
EXPECTED(Z_OBJCE_P(container) == CACHED_PTR_EX(cache_slot))) {
uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR_EX(cache_slot + 1);
intptr_t prop_offset = (intptr_t)CACHED_PTR_EX(cache_slot + 1);
zend_object *zobj = Z_OBJ_P(container);
zval *retval;

View file

@ -286,7 +286,7 @@ static zend_always_inline zend_bool is_derived_class(zend_class_entry *child_cla
}
/* }}} */
static zend_always_inline uint32_t zend_get_property_offset(zend_class_entry *ce, zend_string *member, int silent, void **cache_slot) /* {{{ */
static zend_always_inline intptr_t zend_get_property_offset(zend_class_entry *ce, zend_string *member, int silent, void **cache_slot) /* {{{ */
{
zval *zv;
zend_property_info *property_info = NULL;
@ -294,7 +294,7 @@ static zend_always_inline uint32_t zend_get_property_offset(zend_class_entry *ce
zend_class_entry *scope;
if (cache_slot && EXPECTED(ce == CACHED_PTR_EX(cache_slot))) {
return (uint32_t)(intptr_t)CACHED_PTR_EX(cache_slot + 1);
return (intptr_t)CACHED_PTR_EX(cache_slot + 1);
}
if (UNEXPECTED(ZSTR_VAL(member)[0] == '\0' && ZSTR_LEN(member) != 0)) {
@ -352,7 +352,7 @@ static zend_always_inline uint32_t zend_get_property_offset(zend_class_entry *ce
} else if (UNEXPECTED(property_info == NULL)) {
exit_dynamic:
if (cache_slot) {
CACHE_POLYMORPHIC_PTR_EX(cache_slot, ce, (void*)(intptr_t)ZEND_DYNAMIC_PROPERTY_OFFSET);
CACHE_POLYMORPHIC_PTR_EX(cache_slot, ce, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET);
}
return ZEND_DYNAMIC_PROPERTY_OFFSET;
} else if (UNEXPECTED(property_info == ZEND_WRONG_PROPERTY_INFO)) {
@ -544,7 +544,7 @@ zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_
zend_object *zobj;
zval tmp_member;
zval *retval;
uint32_t property_offset;
intptr_t property_offset;
zobj = Z_OBJ_P(object);
@ -570,10 +570,10 @@ zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_
} else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(property_offset))) {
if (EXPECTED(zobj->properties != NULL)) {
if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(property_offset)) {
uint32_t idx = ZEND_DECODE_DYN_PROP_OFFSET(property_offset);
intptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(property_offset);
if (EXPECTED(idx < zobj->properties->nNumUsed)) {
Bucket *p = zobj->properties->arData + idx;
if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) {
Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx);
if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) &&
(EXPECTED(p->key == Z_STR_P(member)) ||
@ -585,14 +585,13 @@ zval *zend_std_read_property(zval *object, zval *member, int type, void **cache_
goto exit;
}
}
CACHE_PTR_EX(cache_slot + 1, (void*)(uintptr_t)ZEND_DYNAMIC_PROPERTY_OFFSET);
CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET);
}
retval = zend_hash_find(zobj->properties, Z_STR_P(member));
if (EXPECTED(retval)) {
if (cache_slot) {
uint32_t idx = ((char*)retval - (char*)zobj->properties->arData) / sizeof(Bucket);
/* Store "hash slot index" + 2 (NULL is a mark of uninitialized cache slot) */
CACHE_PTR_EX(cache_slot + 1, (void*)(uintptr_t)ZEND_ENCODE_DYN_PROP_OFFSET(idx));
intptr_t idx = (char*)retval - (char*)zobj->properties->arData;
CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx));
}
goto exit;
}
@ -673,7 +672,7 @@ ZEND_API void zend_std_write_property(zval *object, zval *member, zval *value, v
zend_object *zobj;
zval tmp_member;
zval *variable_ptr;
uint32_t property_offset;
intptr_t property_offset;
zobj = Z_OBJ_P(object);
@ -851,7 +850,7 @@ static zval *zend_std_get_property_ptr_ptr(zval *object, zval *member, int type,
zend_object *zobj;
zend_string *name;
zval *retval = NULL;
uint32_t property_offset;
intptr_t property_offset;
zobj = Z_OBJ_P(object);
if (EXPECTED(Z_TYPE_P(member) == IS_STRING)) {
@ -922,7 +921,7 @@ static void zend_std_unset_property(zval *object, zval *member, void **cache_slo
{
zend_object *zobj;
zval tmp_member;
uint32_t property_offset;
intptr_t property_offset;
zobj = Z_OBJ_P(object);
@ -1497,7 +1496,7 @@ static int zend_std_has_property(zval *object, zval *member, int has_set_exists,
int result;
zval *value = NULL;
zval tmp_member;
uint32_t property_offset;
intptr_t property_offset;
zobj = Z_OBJ_P(object);
@ -1518,10 +1517,10 @@ static int zend_std_has_property(zval *object, zval *member, int has_set_exists,
} else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(property_offset))) {
if (EXPECTED(zobj->properties != NULL)) {
if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(property_offset)) {
uint32_t idx = ZEND_DECODE_DYN_PROP_OFFSET(property_offset);
intptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(property_offset);
if (EXPECTED(idx < zobj->properties->nNumUsed)) {
Bucket *p = zobj->properties->arData + idx;
if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) {
Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx);
if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) &&
(EXPECTED(p->key == Z_STR_P(member)) ||
@ -1533,14 +1532,13 @@ static int zend_std_has_property(zval *object, zval *member, int has_set_exists,
goto found;
}
}
CACHE_PTR_EX(cache_slot + 1, (void*)(uintptr_t)ZEND_DYNAMIC_PROPERTY_OFFSET);
CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET);
}
value = zend_hash_find(zobj->properties, Z_STR_P(member));
if (value) {
if (cache_slot) {
uint32_t idx = ((char*)value - (char*)zobj->properties->arData) / sizeof(Bucket);
/* Store "hash slot index" + 2 (NULL is a mark of uninitialized cache slot) */
CACHE_PTR_EX(cache_slot + 1, (void*)(uintptr_t)ZEND_ENCODE_DYN_PROP_OFFSET(idx));
intptr_t idx = (char*)value - (char*)zobj->properties->arData;
CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx));
}
found:
switch (has_set_exists) {

View file

@ -25,17 +25,17 @@
struct _zend_property_info;
#define ZEND_WRONG_PROPERTY_INFO \
((struct _zend_property_info*)((zend_intptr_t)-1))
((struct _zend_property_info*)((intptr_t)-1))
#define ZEND_DYNAMIC_PROPERTY_OFFSET ((uint32_t)(-1))
#define ZEND_DYNAMIC_PROPERTY_OFFSET ((intptr_t)(-1))
#define IS_VALID_PROPERTY_OFFSET(offset) ((int32_t)(offset) > 0)
#define IS_WRONG_PROPERTY_OFFSET(offset) ((int32_t)(offset) == 0)
#define IS_DYNAMIC_PROPERTY_OFFSET(offset) ((int32_t)(offset) < 0)
#define IS_VALID_PROPERTY_OFFSET(offset) ((intptr_t)(offset) > 0)
#define IS_WRONG_PROPERTY_OFFSET(offset) ((intptr_t)(offset) == 0)
#define IS_DYNAMIC_PROPERTY_OFFSET(offset) ((intptr_t)(offset) < 0)
#define IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(offset) (offset == ZEND_DYNAMIC_PROPERTY_OFFSET)
#define ZEND_DECODE_DYN_PROP_OFFSET(offset) ((uint32_t)(-(int32_t)(offset) - 2))
#define ZEND_ENCODE_DYN_PROP_OFFSET(idx) ((uint32_t)(-(idx + 2)))
#define ZEND_DECODE_DYN_PROP_OFFSET(offset) (-(intptr_t)(offset) - 2)
#define ZEND_ENCODE_DYN_PROP_OFFSET(offset) (-((intptr_t)(offset) + 2))
/* The following rule applies to read_property() and read_dimension() implementations:

View file

@ -1792,7 +1792,7 @@ ZEND_VM_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMP|VAR|UNUSED|THIS|CV, CONST|TMPVAR
cache_slot = CACHE_ADDR(Z_CACHE_SLOT_P(offset));
if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) {
uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR_EX(cache_slot + 1);
intptr_t prop_offset = (intptr_t)CACHED_PTR_EX(cache_slot + 1);
if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) {
retval = OBJ_PROP(zobj, prop_offset);
@ -1802,10 +1802,10 @@ ZEND_VM_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMP|VAR|UNUSED|THIS|CV, CONST|TMPVAR
}
} else if (EXPECTED(zobj->properties != NULL)) {
if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) {
uint32_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset);
intptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset);
if (EXPECTED(idx < zobj->properties->nNumUsed)) {
Bucket *p = zobj->properties->arData + idx;
if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) {
Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx);
if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) &&
(EXPECTED(p->key == Z_STR_P(offset)) ||
@ -1817,12 +1817,12 @@ ZEND_VM_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMP|VAR|UNUSED|THIS|CV, CONST|TMPVAR
break;
}
}
CACHE_PTR_EX(cache_slot + 1, (void*)(uintptr_t)ZEND_DYNAMIC_PROPERTY_OFFSET);
CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET);
}
retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
if (EXPECTED(retval)) {
uint32_t idx = ((char*)retval - (char*)zobj->properties->arData) / sizeof(Bucket);
CACHE_PTR_EX(cache_slot + 1, (void*)(uintptr_t)ZEND_ENCODE_DYN_PROP_OFFSET(idx));
intptr_t idx = (char*)retval - (char*)zobj->properties->arData;
CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx));
ZVAL_COPY_UNREF(EX_VAR(opline->result.var), retval);
break;
}
@ -1937,7 +1937,7 @@ ZEND_VM_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR
cache_slot = CACHE_ADDR(Z_CACHE_SLOT_P(offset));
if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) {
uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR_EX(cache_slot + 1);
intptr_t prop_offset = (intptr_t)CACHED_PTR_EX(cache_slot + 1);
if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) {
retval = OBJ_PROP(zobj, prop_offset);
@ -1947,10 +1947,10 @@ ZEND_VM_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR
}
} else if (EXPECTED(zobj->properties != NULL)) {
if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) {
uint32_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset);
intptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset);
if (EXPECTED(idx < zobj->properties->nNumUsed)) {
Bucket *p = zobj->properties->arData + idx;
if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) {
Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx);
if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) &&
(EXPECTED(p->key == Z_STR_P(offset)) ||
@ -1962,12 +1962,12 @@ ZEND_VM_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR
break;
}
}
CACHE_PTR_EX(cache_slot + 1, (void*)(uintptr_t)ZEND_DYNAMIC_PROPERTY_OFFSET);
CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET);
}
retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
if (EXPECTED(retval)) {
uint32_t idx = ((char*)retval - (char*)zobj->properties->arData) / sizeof(Bucket);
CACHE_PTR_EX(cache_slot + 1, (void*)(uintptr_t)ZEND_ENCODE_DYN_PROP_OFFSET(idx));
intptr_t idx = (char*)retval - (char*)zobj->properties->arData;
CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx));
ZVAL_COPY(EX_VAR(opline->result.var), retval);
break;
}
@ -2126,7 +2126,7 @@ ZEND_VM_HANDLER(136, ZEND_ASSIGN_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, SPEC(
if (OP2_TYPE == IS_CONST &&
EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property)))) {
uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property) + sizeof(void*));
intptr_t prop_offset = (intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property) + sizeof(void*));
zend_object *zobj = Z_OBJ_P(object);
zval *property_val;
@ -7568,7 +7568,7 @@ ZEND_VM_HOT_HANDLER(168, ZEND_BIND_GLOBAL, CV, CONST)
zval *varname;
zval *value;
zval *variable_ptr;
uint32_t idx;
intptr_t idx;
zend_reference *ref;
ZEND_VM_REPEATABLE_OPCODE
@ -7576,9 +7576,9 @@ ZEND_VM_HOT_HANDLER(168, ZEND_BIND_GLOBAL, CV, CONST)
varname = GET_OP2_ZVAL_PTR(BP_VAR_R);
/* We store "hash slot index" + 1 (NULL is a mark of uninitialized cache slot) */
idx = (uint32_t)(uintptr_t)CACHED_PTR(Z_CACHE_SLOT_P(varname)) - 1;
if (EXPECTED(idx < EG(symbol_table).nNumUsed)) {
Bucket *p = EG(symbol_table).arData + idx;
idx = (intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(varname)) - 1;
if (EXPECTED(idx < EG(symbol_table).nNumUsed * sizeof(Bucket))) {
Bucket *p = (Bucket*)((char*)EG(symbol_table).arData + idx);
if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) &&
(EXPECTED(p->key == Z_STR_P(varname)) ||
@ -7587,7 +7587,7 @@ ZEND_VM_HOT_HANDLER(168, ZEND_BIND_GLOBAL, CV, CONST)
EXPECTED(ZSTR_LEN(p->key) == Z_STRLEN_P(varname)) &&
EXPECTED(memcmp(ZSTR_VAL(p->key), Z_STRVAL_P(varname), Z_STRLEN_P(varname)) == 0)))) {
value = &EG(symbol_table).arData[idx].val;
value = (zval*)p; /* value = &p->val; */
ZEND_VM_C_GOTO(check_indirect);
}
}
@ -7595,13 +7595,13 @@ ZEND_VM_HOT_HANDLER(168, ZEND_BIND_GLOBAL, CV, CONST)
value = zend_hash_find(&EG(symbol_table), Z_STR_P(varname));
if (UNEXPECTED(value == NULL)) {
value = zend_hash_add_new(&EG(symbol_table), Z_STR_P(varname), &EG(uninitialized_zval));
idx = ((char*)value - (char*)EG(symbol_table).arData) / sizeof(Bucket);
idx = (char*)value - (char*)EG(symbol_table).arData;
/* Store "hash slot index" + 1 (NULL is a mark of uninitialized cache slot) */
CACHE_PTR(Z_CACHE_SLOT_P(varname), (void*)(uintptr_t)(idx + 1));
CACHE_PTR(Z_CACHE_SLOT_P(varname), (void*)(idx + 1));
} else {
idx = ((char*)value - (char*)EG(symbol_table).arData) / sizeof(Bucket);
idx = (char*)value - (char*)EG(symbol_table).arData;
/* Store "hash slot index" + 1 (NULL is a mark of uninitialized cache slot) */
CACHE_PTR(Z_CACHE_SLOT_P(varname), (void*)(uintptr_t)(idx + 1));
CACHE_PTR(Z_CACHE_SLOT_P(varname), (void*)(idx + 1));
ZEND_VM_C_LABEL(check_indirect):
/* GLOBAL variable may be an INDIRECT pointer to CV */
if (UNEXPECTED(Z_TYPE_P(value) == IS_INDIRECT)) {

File diff suppressed because it is too large Load diff