Skip to content

Commit 3d11743

Browse files
committed
Inline "array" part of FE_FETCH_R handler into HYBRID VM
1 parent 278d452 commit 3d11743

File tree

2 files changed

+267
-207
lines changed

2 files changed

+267
-207
lines changed

Zend/zend_vm_def.h

Lines changed: 121 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -6668,7 +6668,7 @@ ZEND_VM_COLD_CONST_HANDLER(125, ZEND_FE_RESET_RW, CONST|TMP|VAR|CV, JMP_ADDR)
66686668
}
66696669
}
66706670

6671-
ZEND_VM_HANDLER(78, ZEND_FE_FETCH_R, VAR, ANY, JMP_ADDR)
6671+
ZEND_VM_HELPER(zend_fe_fetch_object_helper, ANY, ANY)
66726672
{
66736673
USE_OPLINE
66746674
zval *array;
@@ -6677,126 +6677,98 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH_R, VAR, ANY, JMP_ADDR)
66776677
HashTable *fe_ht;
66786678
HashPosition pos;
66796679
Bucket *p;
6680+
zend_object_iterator *iter;
66806681

66816682
array = EX_VAR(opline->op1.var);
66826683
SAVE_OPLINE();
6683-
if (EXPECTED(Z_TYPE_P(array) == IS_ARRAY)) {
6684-
fe_ht = Z_ARRVAL_P(array);
6685-
pos = Z_FE_POS_P(array);
6684+
6685+
ZEND_ASSERT(Z_TYPE_P(array) == IS_OBJECT);
6686+
if ((iter = zend_iterator_unwrap(array)) == NULL) {
6687+
/* plain object */
6688+
6689+
fe_ht = Z_OBJPROP_P(array);
6690+
pos = zend_hash_iterator_pos(Z_FE_ITER_P(array), fe_ht);
66866691
p = fe_ht->arData + pos;
66876692
while (1) {
66886693
if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
66896694
/* reached end of iteration */
6690-
ZEND_VM_C_LABEL(fe_fetch_r_exit):
6691-
ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
6692-
ZEND_VM_CONTINUE();
6695+
ZEND_VM_C_GOTO(fe_fetch_r_exit);
66936696
}
66946697
pos++;
66956698
value = &p->val;
66966699
value_type = Z_TYPE_INFO_P(value);
6697-
ZEND_ASSERT(value_type != IS_INDIRECT);
66986700
if (EXPECTED(value_type != IS_UNDEF)) {
6699-
break;
6701+
if (UNEXPECTED(value_type == IS_INDIRECT)) {
6702+
value = Z_INDIRECT_P(value);
6703+
value_type = Z_TYPE_INFO_P(value);
6704+
if (EXPECTED(value_type != IS_UNDEF)
6705+
&& EXPECTED(zend_check_property_access(Z_OBJ_P(array), p->key, 0) == SUCCESS)) {
6706+
break;
6707+
}
6708+
} else if (EXPECTED(Z_OBJCE_P(array)->default_properties_count == 0)
6709+
|| !p->key
6710+
|| zend_check_property_access(Z_OBJ_P(array), p->key, 1) == SUCCESS) {
6711+
break;
6712+
}
67006713
}
67016714
p++;
67026715
}
6703-
Z_FE_POS_P(array) = pos;
6716+
EG(ht_iterators)[Z_FE_ITER_P(array)].pos = pos;
67046717
if (RETURN_VALUE_USED(opline)) {
6705-
if (!p->key) {
6718+
if (UNEXPECTED(!p->key)) {
67066719
ZVAL_LONG(EX_VAR(opline->result.var), p->h);
6707-
} else {
6720+
} else if (ZSTR_VAL(p->key)[0]) {
67086721
ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key);
6722+
} else {
6723+
const char *class_name, *prop_name;
6724+
size_t prop_name_len;
6725+
zend_unmangle_property_name_ex(
6726+
p->key, &class_name, &prop_name, &prop_name_len);
6727+
ZVAL_STRINGL(EX_VAR(opline->result.var), prop_name, prop_name_len);
67096728
}
67106729
}
67116730
} else {
6712-
zend_object_iterator *iter;
6713-
6714-
ZEND_ASSERT(Z_TYPE_P(array) == IS_OBJECT);
6715-
if ((iter = zend_iterator_unwrap(array)) == NULL) {
6716-
/* plain object */
6717-
6718-
fe_ht = Z_OBJPROP_P(array);
6719-
pos = zend_hash_iterator_pos(Z_FE_ITER_P(array), fe_ht);
6720-
p = fe_ht->arData + pos;
6721-
while (1) {
6722-
if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
6723-
/* reached end of iteration */
6724-
ZEND_VM_C_GOTO(fe_fetch_r_exit);
6725-
}
6726-
pos++;
6727-
value = &p->val;
6728-
value_type = Z_TYPE_INFO_P(value);
6729-
if (EXPECTED(value_type != IS_UNDEF)) {
6730-
if (UNEXPECTED(value_type == IS_INDIRECT)) {
6731-
value = Z_INDIRECT_P(value);
6732-
value_type = Z_TYPE_INFO_P(value);
6733-
if (EXPECTED(value_type != IS_UNDEF)
6734-
&& EXPECTED(zend_check_property_access(Z_OBJ_P(array), p->key, 0) == SUCCESS)) {
6735-
break;
6736-
}
6737-
} else if (EXPECTED(Z_OBJCE_P(array)->default_properties_count == 0)
6738-
|| !p->key
6739-
|| zend_check_property_access(Z_OBJ_P(array), p->key, 1) == SUCCESS) {
6740-
break;
6741-
}
6742-
}
6743-
p++;
6744-
}
6745-
EG(ht_iterators)[Z_FE_ITER_P(array)].pos = pos;
6746-
if (RETURN_VALUE_USED(opline)) {
6747-
if (UNEXPECTED(!p->key)) {
6748-
ZVAL_LONG(EX_VAR(opline->result.var), p->h);
6749-
} else if (ZSTR_VAL(p->key)[0]) {
6750-
ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key);
6751-
} else {
6752-
const char *class_name, *prop_name;
6753-
size_t prop_name_len;
6754-
zend_unmangle_property_name_ex(
6755-
p->key, &class_name, &prop_name, &prop_name_len);
6756-
ZVAL_STRINGL(EX_VAR(opline->result.var), prop_name, prop_name_len);
6757-
}
6731+
const zend_object_iterator_funcs *funcs = iter->funcs;
6732+
if (EXPECTED(++iter->index > 0)) {
6733+
/* This could cause an endless loop if index becomes zero again.
6734+
* In case that ever happens we need an additional flag. */
6735+
funcs->move_forward(iter);
6736+
if (UNEXPECTED(EG(exception) != NULL)) {
6737+
UNDEF_RESULT();
6738+
HANDLE_EXCEPTION();
67586739
}
6759-
} else {
6760-
const zend_object_iterator_funcs *funcs = iter->funcs;
6761-
if (EXPECTED(++iter->index > 0)) {
6762-
/* This could cause an endless loop if index becomes zero again.
6763-
* In case that ever happens we need an additional flag. */
6764-
funcs->move_forward(iter);
6740+
if (UNEXPECTED(funcs->valid(iter) == FAILURE)) {
6741+
/* reached end of iteration */
67656742
if (UNEXPECTED(EG(exception) != NULL)) {
67666743
UNDEF_RESULT();
67676744
HANDLE_EXCEPTION();
67686745
}
6769-
if (UNEXPECTED(funcs->valid(iter) == FAILURE)) {
6770-
/* reached end of iteration */
6771-
if (UNEXPECTED(EG(exception) != NULL)) {
6772-
UNDEF_RESULT();
6773-
HANDLE_EXCEPTION();
6774-
}
6775-
ZEND_VM_C_GOTO(fe_fetch_r_exit);
6776-
}
6777-
}
6778-
value = funcs->get_current_data(iter);
6779-
if (UNEXPECTED(EG(exception) != NULL)) {
6780-
UNDEF_RESULT();
6781-
HANDLE_EXCEPTION();
6782-
}
6783-
if (!value) {
6784-
/* failure in get_current_data */
6785-
ZEND_VM_C_GOTO(fe_fetch_r_exit);
6746+
ZEND_VM_C_LABEL(fe_fetch_r_exit):
6747+
ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
6748+
ZEND_VM_CONTINUE();
67866749
}
6787-
if (RETURN_VALUE_USED(opline)) {
6788-
if (funcs->get_current_key) {
6789-
funcs->get_current_key(iter, EX_VAR(opline->result.var));
6790-
if (UNEXPECTED(EG(exception) != NULL)) {
6791-
UNDEF_RESULT();
6792-
HANDLE_EXCEPTION();
6793-
}
6794-
} else {
6795-
ZVAL_LONG(EX_VAR(opline->result.var), iter->index);
6750+
}
6751+
value = funcs->get_current_data(iter);
6752+
if (UNEXPECTED(EG(exception) != NULL)) {
6753+
UNDEF_RESULT();
6754+
HANDLE_EXCEPTION();
6755+
}
6756+
if (!value) {
6757+
/* failure in get_current_data */
6758+
ZEND_VM_C_GOTO(fe_fetch_r_exit);
6759+
}
6760+
if (RETURN_VALUE_USED(opline)) {
6761+
if (funcs->get_current_key) {
6762+
funcs->get_current_key(iter, EX_VAR(opline->result.var));
6763+
if (UNEXPECTED(EG(exception) != NULL)) {
6764+
UNDEF_RESULT();
6765+
HANDLE_EXCEPTION();
67966766
}
6767+
} else {
6768+
ZVAL_LONG(EX_VAR(opline->result.var), iter->index);
67976769
}
6798-
value_type = Z_TYPE_INFO_P(value);
67996770
}
6771+
value_type = Z_TYPE_INFO_P(value);
68006772
}
68016773

68026774
if (EXPECTED(OP2_TYPE == IS_CV)) {
@@ -6814,6 +6786,64 @@ ZEND_VM_C_LABEL(fe_fetch_r_exit):
68146786
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
68156787
}
68166788

6789+
ZEND_VM_HOT_HANDLER(78, ZEND_FE_FETCH_R, VAR, ANY, JMP_ADDR)
6790+
{
6791+
USE_OPLINE
6792+
zval *array;
6793+
zval *value;
6794+
uint32_t value_type;
6795+
HashTable *fe_ht;
6796+
HashPosition pos;
6797+
Bucket *p;
6798+
6799+
array = EX_VAR(opline->op1.var);
6800+
if (UNEXPECTED(Z_TYPE_P(array) != IS_ARRAY)) {
6801+
ZEND_VM_DISPATCH_TO_HELPER(zend_fe_fetch_object_helper);
6802+
}
6803+
fe_ht = Z_ARRVAL_P(array);
6804+
pos = Z_FE_POS_P(array);
6805+
p = fe_ht->arData + pos;
6806+
while (1) {
6807+
if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
6808+
/* reached end of iteration */
6809+
ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
6810+
ZEND_VM_CONTINUE();
6811+
}
6812+
pos++;
6813+
value = &p->val;
6814+
value_type = Z_TYPE_INFO_P(value);
6815+
ZEND_ASSERT(value_type != IS_INDIRECT);
6816+
if (EXPECTED(value_type != IS_UNDEF)) {
6817+
break;
6818+
}
6819+
p++;
6820+
}
6821+
Z_FE_POS_P(array) = pos;
6822+
if (RETURN_VALUE_USED(opline)) {
6823+
if (!p->key) {
6824+
ZVAL_LONG(EX_VAR(opline->result.var), p->h);
6825+
} else {
6826+
ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key);
6827+
}
6828+
}
6829+
6830+
if (EXPECTED(OP2_TYPE == IS_CV)) {
6831+
zval *variable_ptr = EX_VAR(opline->op2.var);
6832+
SAVE_OPLINE();
6833+
zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES());
6834+
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
6835+
} else {
6836+
zval *res = EX_VAR(opline->op2.var);
6837+
zend_refcounted *gc = Z_COUNTED_P(value);
6838+
6839+
ZVAL_COPY_VALUE_EX(res, value, gc, value_type);
6840+
if (Z_TYPE_INFO_REFCOUNTED(value_type)) {
6841+
GC_ADDREF(gc);
6842+
}
6843+
ZEND_VM_NEXT_OPCODE();
6844+
}
6845+
}
6846+
68176847
ZEND_VM_HANDLER(126, ZEND_FE_FETCH_RW, VAR, ANY, JMP_ADDR)
68186848
{
68196849
USE_OPLINE

0 commit comments

Comments
 (0)