Skip to content

Commit 7802cf8

Browse files
committed
Added specialized FE_FETCH_R handler for iteration over array
1 parent 31a2198 commit 7802cf8

File tree

2 files changed

+269
-7
lines changed

2 files changed

+269
-7
lines changed

Zend/zend_vm_def.h

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8749,6 +8749,57 @@ ZEND_VM_C_LABEL(send_var_by_ref_simple):
87498749
ZEND_VM_NEXT_OPCODE();
87508750
}
87518751

8752+
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_FE_FETCH_R, op->op2_type == IS_CV && (op1_info & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)) == MAY_BE_ARRAY, ZEND_FE_FETCH_R_SIMPLE, VAR, CV, JMP_ADDR, SPEC(RETVAL))
8753+
{
8754+
USE_OPLINE
8755+
zval *array;
8756+
zval *value, *variable_ptr;
8757+
uint32_t value_type;
8758+
HashTable *fe_ht;
8759+
HashPosition pos;
8760+
Bucket *p;
8761+
8762+
array = EX_VAR(opline->op1.var);
8763+
SAVE_OPLINE();
8764+
fe_ht = Z_ARRVAL_P(array);
8765+
pos = Z_FE_POS_P(array);
8766+
p = fe_ht->arData + pos;
8767+
while (1) {
8768+
if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
8769+
/* reached end of iteration */
8770+
ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
8771+
ZEND_VM_CONTINUE();
8772+
}
8773+
value = &p->val;
8774+
value_type = Z_TYPE_INFO_P(value);
8775+
if (EXPECTED(value_type != IS_UNDEF)) {
8776+
if (UNEXPECTED(value_type == IS_INDIRECT)) {
8777+
value = Z_INDIRECT_P(value);
8778+
value_type = Z_TYPE_INFO_P(value);
8779+
if (EXPECTED(value_type != IS_UNDEF)) {
8780+
break;
8781+
}
8782+
} else {
8783+
break;
8784+
}
8785+
}
8786+
pos++;
8787+
p++;
8788+
}
8789+
Z_FE_POS_P(array) = pos + 1;
8790+
if (RETURN_VALUE_USED(opline)) {
8791+
if (!p->key) {
8792+
ZVAL_LONG(EX_VAR(opline->result.var), p->h);
8793+
} else {
8794+
ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key);
8795+
}
8796+
}
8797+
8798+
variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(opline->op2.var EXECUTE_DATA_CC);
8799+
zend_assign_to_variable(variable_ptr, value, IS_CV);
8800+
ZEND_VM_NEXT_OPCODE();
8801+
}
8802+
87528803
ZEND_VM_DEFINE_OP(137, ZEND_OP_DATA);
87538804

87548805
ZEND_VM_HELPER(zend_interrupt_helper, ANY, ANY)

Zend/zend_vm_execute.h

Lines changed: 218 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17357,7 +17357,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SIMPLE
1735717357
ZEND_VM_NEXT_OPCODE();
1735817358
}
1735917359

17360-
1736117360
static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SIMPLE_SPEC_VAR_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
1736217361
{
1736317362
USE_OPLINE
@@ -17386,7 +17385,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SIMPLE
1738617385
ZEND_VM_NEXT_OPCODE();
1738717386
}
1738817387

17389-
1739017388
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
1739117389
{
1739217390
USE_OPLINE
@@ -24209,6 +24207,110 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND
2420924207
ZEND_VM_RETURN();
2421024208
}
2421124209

24210+
static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
24211+
{
24212+
USE_OPLINE
24213+
zval *array;
24214+
zval *value, *variable_ptr;
24215+
uint32_t value_type;
24216+
HashTable *fe_ht;
24217+
HashPosition pos;
24218+
Bucket *p;
24219+
24220+
array = EX_VAR(opline->op1.var);
24221+
SAVE_OPLINE();
24222+
fe_ht = Z_ARRVAL_P(array);
24223+
pos = Z_FE_POS_P(array);
24224+
p = fe_ht->arData + pos;
24225+
while (1) {
24226+
if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
24227+
/* reached end of iteration */
24228+
ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
24229+
ZEND_VM_CONTINUE();
24230+
}
24231+
value = &p->val;
24232+
value_type = Z_TYPE_INFO_P(value);
24233+
if (EXPECTED(value_type != IS_UNDEF)) {
24234+
if (UNEXPECTED(value_type == IS_INDIRECT)) {
24235+
value = Z_INDIRECT_P(value);
24236+
value_type = Z_TYPE_INFO_P(value);
24237+
if (EXPECTED(value_type != IS_UNDEF)) {
24238+
break;
24239+
}
24240+
} else {
24241+
break;
24242+
}
24243+
}
24244+
pos++;
24245+
p++;
24246+
}
24247+
Z_FE_POS_P(array) = pos + 1;
24248+
if (0) {
24249+
if (!p->key) {
24250+
ZVAL_LONG(EX_VAR(opline->result.var), p->h);
24251+
} else {
24252+
ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key);
24253+
}
24254+
}
24255+
24256+
variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(opline->op2.var EXECUTE_DATA_CC);
24257+
zend_assign_to_variable(variable_ptr, value, IS_CV);
24258+
ZEND_VM_NEXT_OPCODE();
24259+
}
24260+
24261+
24262+
static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
24263+
{
24264+
USE_OPLINE
24265+
zval *array;
24266+
zval *value, *variable_ptr;
24267+
uint32_t value_type;
24268+
HashTable *fe_ht;
24269+
HashPosition pos;
24270+
Bucket *p;
24271+
24272+
array = EX_VAR(opline->op1.var);
24273+
SAVE_OPLINE();
24274+
fe_ht = Z_ARRVAL_P(array);
24275+
pos = Z_FE_POS_P(array);
24276+
p = fe_ht->arData + pos;
24277+
while (1) {
24278+
if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
24279+
/* reached end of iteration */
24280+
ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
24281+
ZEND_VM_CONTINUE();
24282+
}
24283+
value = &p->val;
24284+
value_type = Z_TYPE_INFO_P(value);
24285+
if (EXPECTED(value_type != IS_UNDEF)) {
24286+
if (UNEXPECTED(value_type == IS_INDIRECT)) {
24287+
value = Z_INDIRECT_P(value);
24288+
value_type = Z_TYPE_INFO_P(value);
24289+
if (EXPECTED(value_type != IS_UNDEF)) {
24290+
break;
24291+
}
24292+
} else {
24293+
break;
24294+
}
24295+
}
24296+
pos++;
24297+
p++;
24298+
}
24299+
Z_FE_POS_P(array) = pos + 1;
24300+
if (1) {
24301+
if (!p->key) {
24302+
ZVAL_LONG(EX_VAR(opline->result.var), p->h);
24303+
} else {
24304+
ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key);
24305+
}
24306+
}
24307+
24308+
variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(opline->op2.var EXECUTE_DATA_CC);
24309+
zend_assign_to_variable(variable_ptr, value, IS_CV);
24310+
ZEND_VM_NEXT_OPCODE();
24311+
}
24312+
24313+
2421224314
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMPVAR(binary_op_type binary_op ZEND_OPCODE_HANDLER_ARGS_DC)
2421324315
{
2421424316
USE_OPLINE
@@ -34152,7 +34254,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SIMPLE
3415234254
ZEND_VM_NEXT_OPCODE();
3415334255
}
3415434256

34155-
3415634257
static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
3415734258
{
3415834259
USE_OPLINE
@@ -34181,7 +34282,6 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SIMPLE
3418134282
ZEND_VM_NEXT_OPCODE();
3418234283
}
3418334284

34184-
3418534285
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
3418634286
{
3418734287
USE_OPLINE
@@ -58905,6 +59005,56 @@ ZEND_API void execute_ex(zend_execute_data *ex)
5890559005
(void*)&&ZEND_NULL_LABEL,
5890659006
(void*)&&ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_LABEL,
5890759007
(void*)&&ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_QUICK_LABEL,
59008+
(void*)&&ZEND_NULL_LABEL,
59009+
(void*)&&ZEND_NULL_LABEL,
59010+
(void*)&&ZEND_NULL_LABEL,
59011+
(void*)&&ZEND_NULL_LABEL,
59012+
(void*)&&ZEND_NULL_LABEL,
59013+
(void*)&&ZEND_NULL_LABEL,
59014+
(void*)&&ZEND_NULL_LABEL,
59015+
(void*)&&ZEND_NULL_LABEL,
59016+
(void*)&&ZEND_NULL_LABEL,
59017+
(void*)&&ZEND_NULL_LABEL,
59018+
(void*)&&ZEND_NULL_LABEL,
59019+
(void*)&&ZEND_NULL_LABEL,
59020+
(void*)&&ZEND_NULL_LABEL,
59021+
(void*)&&ZEND_NULL_LABEL,
59022+
(void*)&&ZEND_NULL_LABEL,
59023+
(void*)&&ZEND_NULL_LABEL,
59024+
(void*)&&ZEND_NULL_LABEL,
59025+
(void*)&&ZEND_NULL_LABEL,
59026+
(void*)&&ZEND_NULL_LABEL,
59027+
(void*)&&ZEND_NULL_LABEL,
59028+
(void*)&&ZEND_NULL_LABEL,
59029+
(void*)&&ZEND_NULL_LABEL,
59030+
(void*)&&ZEND_NULL_LABEL,
59031+
(void*)&&ZEND_NULL_LABEL,
59032+
(void*)&&ZEND_NULL_LABEL,
59033+
(void*)&&ZEND_NULL_LABEL,
59034+
(void*)&&ZEND_NULL_LABEL,
59035+
(void*)&&ZEND_NULL_LABEL,
59036+
(void*)&&ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_UNUSED_LABEL,
59037+
(void*)&&ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_USED_LABEL,
59038+
(void*)&&ZEND_NULL_LABEL,
59039+
(void*)&&ZEND_NULL_LABEL,
59040+
(void*)&&ZEND_NULL_LABEL,
59041+
(void*)&&ZEND_NULL_LABEL,
59042+
(void*)&&ZEND_NULL_LABEL,
59043+
(void*)&&ZEND_NULL_LABEL,
59044+
(void*)&&ZEND_NULL_LABEL,
59045+
(void*)&&ZEND_NULL_LABEL,
59046+
(void*)&&ZEND_NULL_LABEL,
59047+
(void*)&&ZEND_NULL_LABEL,
59048+
(void*)&&ZEND_NULL_LABEL,
59049+
(void*)&&ZEND_NULL_LABEL,
59050+
(void*)&&ZEND_NULL_LABEL,
59051+
(void*)&&ZEND_NULL_LABEL,
59052+
(void*)&&ZEND_NULL_LABEL,
59053+
(void*)&&ZEND_NULL_LABEL,
59054+
(void*)&&ZEND_NULL_LABEL,
59055+
(void*)&&ZEND_NULL_LABEL,
59056+
(void*)&&ZEND_NULL_LABEL,
59057+
(void*)&&ZEND_NULL_LABEL,
5890859058
(void*)&&ZEND_NULL_LABEL
5890959059
};
5891059060
zend_opcode_handlers = (const void **) labels;
@@ -60583,6 +60733,12 @@ ZEND_API void execute_ex(zend_execute_data *ex)
6058360733
HYBRID_CASE(ZEND_YIELD_SPEC_VAR_CV):
6058460734
ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
6058560735
HYBRID_BREAK();
60736+
HYBRID_CASE(ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_UNUSED):
60737+
ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
60738+
HYBRID_BREAK();
60739+
HYBRID_CASE(ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_USED):
60740+
ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
60741+
HYBRID_BREAK();
6058660742
HYBRID_CASE(ZEND_ASSIGN_ADD_SPEC_VAR_TMPVAR):
6058760743
ZEND_ASSIGN_ADD_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
6058860744
HYBRID_BREAK();
@@ -67783,6 +67939,56 @@ void zend_init_opcodes_handlers(void)
6778367939
ZEND_NULL_HANDLER,
6778467940
ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_HANDLER,
6778567941
ZEND_SEND_VAR_EX_SIMPLE_SPEC_CV_QUICK_HANDLER,
67942+
ZEND_NULL_HANDLER,
67943+
ZEND_NULL_HANDLER,
67944+
ZEND_NULL_HANDLER,
67945+
ZEND_NULL_HANDLER,
67946+
ZEND_NULL_HANDLER,
67947+
ZEND_NULL_HANDLER,
67948+
ZEND_NULL_HANDLER,
67949+
ZEND_NULL_HANDLER,
67950+
ZEND_NULL_HANDLER,
67951+
ZEND_NULL_HANDLER,
67952+
ZEND_NULL_HANDLER,
67953+
ZEND_NULL_HANDLER,
67954+
ZEND_NULL_HANDLER,
67955+
ZEND_NULL_HANDLER,
67956+
ZEND_NULL_HANDLER,
67957+
ZEND_NULL_HANDLER,
67958+
ZEND_NULL_HANDLER,
67959+
ZEND_NULL_HANDLER,
67960+
ZEND_NULL_HANDLER,
67961+
ZEND_NULL_HANDLER,
67962+
ZEND_NULL_HANDLER,
67963+
ZEND_NULL_HANDLER,
67964+
ZEND_NULL_HANDLER,
67965+
ZEND_NULL_HANDLER,
67966+
ZEND_NULL_HANDLER,
67967+
ZEND_NULL_HANDLER,
67968+
ZEND_NULL_HANDLER,
67969+
ZEND_NULL_HANDLER,
67970+
ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_UNUSED_HANDLER,
67971+
ZEND_FE_FETCH_R_SIMPLE_SPEC_VAR_CV_RETVAL_USED_HANDLER,
67972+
ZEND_NULL_HANDLER,
67973+
ZEND_NULL_HANDLER,
67974+
ZEND_NULL_HANDLER,
67975+
ZEND_NULL_HANDLER,
67976+
ZEND_NULL_HANDLER,
67977+
ZEND_NULL_HANDLER,
67978+
ZEND_NULL_HANDLER,
67979+
ZEND_NULL_HANDLER,
67980+
ZEND_NULL_HANDLER,
67981+
ZEND_NULL_HANDLER,
67982+
ZEND_NULL_HANDLER,
67983+
ZEND_NULL_HANDLER,
67984+
ZEND_NULL_HANDLER,
67985+
ZEND_NULL_HANDLER,
67986+
ZEND_NULL_HANDLER,
67987+
ZEND_NULL_HANDLER,
67988+
ZEND_NULL_HANDLER,
67989+
ZEND_NULL_HANDLER,
67990+
ZEND_NULL_HANDLER,
67991+
ZEND_NULL_HANDLER,
6778667992
ZEND_NULL_HANDLER
6778767993
};
6778867994
static const uint32_t specs[] = {
@@ -67886,7 +68092,7 @@ void zend_init_opcodes_handlers(void)
6788668092
2257 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
6788768093
2282 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
6788868094
2307 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
67889-
4821,
68095+
4871,
6789068096
2332,
6789168097
2333,
6789268098
2334,
@@ -67971,7 +68177,7 @@ void zend_init_opcodes_handlers(void)
6797168177
3531 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
6797268178
3556 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
6797368179
3581 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
67974-
4821,
68180+
4871,
6797568181
3606 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
6797668182
3631 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
6797768183
3656 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
@@ -67982,7 +68188,7 @@ void zend_init_opcodes_handlers(void)
6798268188
3781 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
6798368189
3806 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
6798468190
3831 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
67985-
4821
68191+
4871
6798668192
};
6798768193
#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)
6798868194
zend_opcode_handler_funcs = labels;
@@ -68356,6 +68562,11 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
6835668562
spec = 4811 | SPEC_RULE_OP1 | SPEC_RULE_QUICK_ARG;
6835768563
}
6835868564
break;
68565+
case ZEND_FE_FETCH_R:
68566+
if (op->op2_type == IS_CV && (op1_info & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)) == MAY_BE_ARRAY) {
68567+
spec = 4821 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_RETVAL;
68568+
}
68569+
break;
6835968570
case ZEND_FETCH_DIM_R:
6836068571
if (!(op2_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF))) {
6836168572
spec = 4781 | SPEC_RULE_OP1 | SPEC_RULE_OP2;

0 commit comments

Comments
 (0)