Skip to content

Commit 6755808

Browse files
committed
Optimize strlen() and in_array() opcodes
- Don't save the opline or check for exceptions if it isn't needed. (only affects temporary expressions, not $cv) - Be more specific about the way to free string operands ```php // test_strlen(10000000): .402 -> .387 at 2.5GHz function test_strlen(int $n) { $total = 0; for ($i = 0; $i < $n; $i++) { $total += strlen((string)$i); } return $total; } // test_in_array(40000000): .54 -> .44 at 2.5GHz function test_in_array(int $n) { $total = 0; for ($i = 0; $i < $n; $i++) { if (in_array($i, [1, 50, 100], true)) { $total += $i; } } return $total; } ```
1 parent 2ede8db commit 6755808

File tree

2 files changed

+240
-82
lines changed

2 files changed

+240
-82
lines changed

Zend/zend_vm_def.h

Lines changed: 49 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7823,7 +7823,9 @@ ZEND_VM_COLD_CONST_HANDLER(121, ZEND_STRLEN, CONST|TMPVAR|CV, ANY)
78237823
value = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
78247824
if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) {
78257825
ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value));
7826-
FREE_OP1();
7826+
if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) {
7827+
zval_ptr_dtor_str(value);
7828+
}
78277829
ZEND_VM_NEXT_OPCODE();
78287830
} else {
78297831
zend_bool strict;
@@ -8330,33 +8332,63 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(189, ZEND_IN_ARRAY, CONST|TMP|VAR|CV, CONST, NUM
83308332
HashTable *ht = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2));
83318333
zval *result;
83328334

8333-
SAVE_OPLINE();
8334-
op1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
8335+
op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
83358336
if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
83368337
result = zend_hash_find_ex(ht, Z_STR_P(op1), OP1_TYPE == IS_CONST);
8338+
if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) {
8339+
zval_ptr_dtor_str(op1);
8340+
}
8341+
ZEND_VM_SMART_BRANCH(result, 0);
83378342
} else if (opline->extended_value) {
83388343
if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
83398344
result = zend_hash_index_find(ht, Z_LVAL_P(op1));
8340-
} else {
8345+
ZEND_VM_SMART_BRANCH(result, 0);
8346+
}
8347+
if (OP1_TYPE & (IS_CV | IS_VAR)) {
8348+
SAVE_OPLINE();
8349+
if ((OP1_TYPE & IS_CV) && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
8350+
ZVAL_UNDEFINED_OP1();
8351+
ZEND_VM_SMART_BRANCH(0, 1);
8352+
}
83418353
result = NULL;
8354+
ZVAL_DEREF(op1);
8355+
if (Z_TYPE_P(op1) == IS_STRING) {
8356+
result = zend_hash_find_ex(ht, Z_STR_P(op1), OP1_TYPE == IS_CONST);
8357+
} else if (Z_TYPE_P(op1) == IS_LONG) {
8358+
result = zend_hash_index_find(ht, Z_LVAL_P(op1));
8359+
}
8360+
FREE_OP1();
8361+
ZEND_VM_SMART_BRANCH(result, OP1_TYPE & IS_VAR);
83428362
}
8363+
ZEND_VM_SMART_BRANCH(0, 0);
83438364
} else if (Z_TYPE_P(op1) <= IS_FALSE) {
8365+
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
8366+
SAVE_OPLINE();
8367+
ZVAL_UNDEFINED_OP1();
8368+
result = zend_hash_find_ex(ht, ZSTR_EMPTY_ALLOC(), 1);
8369+
FREE_OP1();
8370+
ZEND_VM_SMART_BRANCH(result, 1);
8371+
}
83448372
result = zend_hash_find_ex(ht, ZSTR_EMPTY_ALLOC(), 1);
8345-
} else {
8346-
zend_string *key;
8347-
zval key_tmp, *val;
8348-
8349-
result = NULL;
8350-
ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) {
8351-
ZVAL_STR(&key_tmp, key);
8352-
if (zend_compare(op1, &key_tmp) == 0) {
8353-
result = val;
8354-
break;
8355-
}
8356-
} ZEND_HASH_FOREACH_END();
8373+
ZEND_VM_SMART_BRANCH(result, 0);
8374+
}
8375+
SAVE_OPLINE();
8376+
zend_string *key;
8377+
zval key_tmp, *val;
8378+
if (OP1_TYPE & (IS_CV | IS_VAR)) {
8379+
ZVAL_DEREF(op1);
83578380
}
8381+
8382+
result = NULL;
8383+
ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) {
8384+
ZVAL_STR(&key_tmp, key);
8385+
if (zend_compare(op1, &key_tmp) == 0) {
8386+
result = val;
8387+
break;
8388+
}
8389+
} ZEND_HASH_FOREACH_END();
83588390
FREE_OP1();
8359-
ZEND_VM_SMART_BRANCH(result, 1);
8391+
ZEND_VM_SMART_BRANCH(result, OP1_TYPE & (IS_TMP_VAR|IS_VAR));
83608392
}
83618393

83628394
ZEND_VM_COLD_CONST_HANDLER(190, ZEND_COUNT, CONST|TMPVAR|CV, UNUSED)

0 commit comments

Comments
 (0)