From: Dmitry Stogov Date: Tue, 23 Jun 2020 14:16:44 +0000 (+0300) Subject: Reduce amount of "cold" code generated for FETCH_OBJ_* instructions X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6ac16882d405be7ae496eda6afe70c77d83ed56b;p=php Reduce amount of "cold" code generated for FETCH_OBJ_* instructions --- diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index a394c4af0f..bc58e56daf 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -1241,15 +1241,16 @@ static void ZEND_FASTCALL zend_jit_verify_return_slow(zval *arg, const zend_op_a } } -static void ZEND_FASTCALL zend_jit_fetch_obj_r_slow(zend_object *zobj, zval *offset, zval *result, uint32_t cache_slot) +static void ZEND_FASTCALL zend_jit_fetch_obj_r_slow(zend_object *zobj) { zval *retval; zend_execute_data *execute_data = EG(current_execute_data); - zend_string *name, *tmp_name; + const zend_op *opline = EX(opline); + zend_string *name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + zval *result = EX_VAR(opline->result.var); + void **cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS); - name = zval_get_tmp_string(offset, &tmp_name); - retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, CACHE_ADDR(cache_slot), result); - zend_tmp_string_release(tmp_name); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, result); if (retval != result) { ZVAL_COPY_DEREF(result, retval); } else if (UNEXPECTED(Z_ISREF_P(retval))) { @@ -1257,10 +1258,15 @@ static void ZEND_FASTCALL zend_jit_fetch_obj_r_slow(zend_object *zobj, zval *off } } -static void ZEND_FASTCALL zend_jit_fetch_obj_r_dynamic(zend_object *zobj, intptr_t prop_offset, zval *offset, zval *result, uint32_t cache_slot) +static void ZEND_FASTCALL zend_jit_fetch_obj_r_dynamic(zend_object *zobj, intptr_t prop_offset) { if (zobj->properties) { zval *retval; + zend_execute_data *execute_data = EG(current_execute_data); + const zend_op *opline = EX(opline); + zend_string *name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + zval *result = EX_VAR(opline->result.var); + void **cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS); if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { intptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); @@ -1269,39 +1275,40 @@ static void ZEND_FASTCALL zend_jit_fetch_obj_r_dynamic(zend_object *zobj, intptr Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(ZSTR_LEN(p->key) == Z_STRLEN_P(offset)) && - EXPECTED(memcmp(ZSTR_VAL(p->key), Z_STRVAL_P(offset), Z_STRLEN_P(offset)) == 0)))) { + EXPECTED(ZSTR_LEN(p->key) == ZSTR_LEN(name)) && + EXPECTED(memcmp(ZSTR_VAL(p->key), ZSTR_VAL(name), ZSTR_LEN(name)) == 0)))) { ZVAL_COPY_DEREF(result, &p->val); return; } } - CACHE_PTR_EX((void**)((char*)EG(current_execute_data)->run_time_cache + cache_slot) + 1, (void*)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)); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { intptr_t idx = (char*)retval - (char*)zobj->properties->arData; - CACHE_PTR_EX((void**)((char*)EG(current_execute_data)->run_time_cache + cache_slot) + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); ZVAL_COPY_DEREF(result, retval); return; } } - zend_jit_fetch_obj_r_slow(zobj, offset, result, cache_slot); + zend_jit_fetch_obj_r_slow(zobj); } -static void ZEND_FASTCALL zend_jit_fetch_obj_is_slow(zend_object *zobj, zval *offset, zval *result, uint32_t cache_slot) +static void ZEND_FASTCALL zend_jit_fetch_obj_is_slow(zend_object *zobj) { zval *retval; zend_execute_data *execute_data = EG(current_execute_data); - zend_string *name, *tmp_name; + const zend_op *opline = EX(opline); + zend_string *name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + zval *result = EX_VAR(opline->result.var); + void **cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS); - name = zval_get_tmp_string(offset, &tmp_name); - retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, CACHE_ADDR(cache_slot), result); - zend_tmp_string_release(tmp_name); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, result); if (retval != result) { ZVAL_COPY_DEREF(result, retval); } else if (UNEXPECTED(Z_ISREF_P(retval))) { @@ -1309,10 +1316,15 @@ static void ZEND_FASTCALL zend_jit_fetch_obj_is_slow(zend_object *zobj, zval *of } } -static void ZEND_FASTCALL zend_jit_fetch_obj_is_dynamic(zend_object *zobj, intptr_t prop_offset, zval *offset, zval *result, uint32_t cache_slot) +static void ZEND_FASTCALL zend_jit_fetch_obj_is_dynamic(zend_object *zobj, intptr_t prop_offset) { if (zobj->properties) { zval *retval; + zend_execute_data *execute_data = EG(current_execute_data); + const zend_op *opline = EX(opline); + zend_string *name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + zval *result = EX_VAR(opline->result.var); + void **cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS); if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { intptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); @@ -1321,28 +1333,28 @@ static void ZEND_FASTCALL zend_jit_fetch_obj_is_dynamic(zend_object *zobj, intpt Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) && - (EXPECTED(p->key == Z_STR_P(offset)) || - (EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) && + (EXPECTED(p->key == name) || + (EXPECTED(p->h == ZSTR_H(name)) && EXPECTED(p->key != NULL) && - EXPECTED(ZSTR_LEN(p->key) == Z_STRLEN_P(offset)) && - EXPECTED(memcmp(ZSTR_VAL(p->key), Z_STRVAL_P(offset), Z_STRLEN_P(offset)) == 0)))) { + EXPECTED(ZSTR_LEN(p->key) == ZSTR_LEN(name)) && + EXPECTED(memcmp(ZSTR_VAL(p->key), ZSTR_VAL(name), ZSTR_LEN(name)) == 0)))) { ZVAL_COPY_DEREF(result, &p->val); return; } } - CACHE_PTR_EX((void**)((char*)EG(current_execute_data)->run_time_cache + cache_slot) + 1, (void*)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)); + retval = zend_hash_find_ex(zobj->properties, name, 1); if (EXPECTED(retval)) { intptr_t idx = (char*)retval - (char*)zobj->properties->arData; - CACHE_PTR_EX((void**)((char*)EG(current_execute_data)->run_time_cache + cache_slot) + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); + CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); ZVAL_COPY(result, retval); return; } } - zend_jit_fetch_obj_is_slow(zobj, offset, result, cache_slot); + zend_jit_fetch_obj_is_slow(zobj); } static zend_always_inline zend_bool promotes_to_array(zval *val) { @@ -1437,26 +1449,27 @@ static zend_never_inline zend_bool zend_handle_fetch_obj_flags( return 1; } -static void ZEND_FASTCALL zend_jit_fetch_obj_w_slow(zend_object *zobj, zval *offset, zval *result, uint32_t cache_slot) +static void ZEND_FASTCALL zend_jit_fetch_obj_w_slow(zend_object *zobj) { zval *retval; zend_execute_data *execute_data = EG(current_execute_data); - const zend_op *opline = execute_data->opline; - zend_string *name, *tmp_name; + const zend_op *opline = EX(opline); + zend_string *name = Z_STR_P(RT_CONSTANT(opline, opline->op2)); + zval *result = EX_VAR(opline->result.var); + void **cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS); - name = zval_get_tmp_string(offset, &tmp_name); - retval = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_W, CACHE_ADDR(cache_slot)); + retval = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_W, cache_slot); if (NULL == retval) { - retval = zobj->handlers->read_property(zobj, name, BP_VAR_W, CACHE_ADDR(cache_slot), result); + retval = zobj->handlers->read_property(zobj, name, BP_VAR_W, cache_slot, result); if (retval == result) { if (UNEXPECTED(Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1)) { ZVAL_UNREF(retval); } - goto end; + return; } } else if (UNEXPECTED(Z_ISERROR_P(retval))) { ZVAL_ERROR(result); - goto end; + return; } ZVAL_INDIRECT(result, retval); @@ -1469,13 +1482,13 @@ static void ZEND_FASTCALL zend_jit_fetch_obj_w_slow(zend_object *zobj, zval *off zend_property_info *prop_info = NULL; if (opline->op2_type == IS_CONST) { - prop_info = CACHED_PTR_EX(CACHE_ADDR(cache_slot) + 2); + prop_info = CACHED_PTR_EX(cache_slot + 2); if (!prop_info) { break; } } if (UNEXPECTED(!zend_handle_fetch_obj_flags(result, retval, zobj, prop_info, flags))) { - goto end; + return; } } } while (0); @@ -1483,9 +1496,6 @@ static void ZEND_FASTCALL zend_jit_fetch_obj_w_slow(zend_object *zobj, zval *off if (UNEXPECTED(Z_TYPE_P(retval) == IS_UNDEF)) { ZVAL_NULL(retval); } - -end: - zend_tmp_string_release(tmp_name); } static void ZEND_FASTCALL zend_jit_check_array_promotion(zval *val, zend_property_info *prop) diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index dd6b075d2e..0b339be895 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -10984,15 +10984,6 @@ static int zend_jit_fetch_obj(dasm_State **Dst, const zend_op *opline, const zen if (JIT_G(trigger) != ZEND_JIT_ON_HOT_TRACE || offset == ZEND_WRONG_PROPERTY_OFFSET) { |5: - | LOAD_ADDR FCARG2a, member - |.if X64 - | LOAD_ZVAL_ADDR CARG3, res_addr - | mov CARG4, (opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) - |.else - | sub r4, 8 - | push (opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) - | PUSH_ZVAL_ADDR res_addr, r0 - |.endif | SAVE_VALID_OPLINE opline, r0 if (opline->opcode == ZEND_FETCH_OBJ_W) { | EXT_CALL zend_jit_fetch_obj_w_slow, r0 @@ -11001,9 +10992,6 @@ static int zend_jit_fetch_obj(dasm_State **Dst, const zend_op *opline, const zen } else { | EXT_CALL zend_jit_fetch_obj_is_slow, r0 } - |.if not(X64) - | add r4, 8 - |.endif | jmp >9 } @@ -11045,29 +11033,12 @@ static int zend_jit_fetch_obj(dasm_State **Dst, const zend_op *opline, const zen && opline->opcode != ZEND_FETCH_OBJ_W) { |8: | mov FCARG2a, r0 - |.if X64WIN - | LOAD_ADDR CARG3, member - | LOAD_ZVAL_ADDR CARG4, res_addr - | mov aword A5, (opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) - |.elif X64 - | LOAD_ADDR CARG3, member - | LOAD_ZVAL_ADDR CARG4, res_addr - | mov CARG5, (opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) - |.else - | sub r4, 4 - | push (opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) - | PUSH_ZVAL_ADDR res_addr, r0 - | PUSH_ADDR member, r0 - |.endif | SAVE_VALID_OPLINE opline, r0 if (opline->opcode != ZEND_FETCH_OBJ_IS) { | EXT_CALL zend_jit_fetch_obj_r_dynamic, r0 } else { | EXT_CALL zend_jit_fetch_obj_is_dynamic, r0 } - |.if not(X64) - | add r4, 4 - |.endif | jmp >9 }