Skip to content

Commit 2265ca4

Browse files
committed
Implement ZEND_ARRAY_KEY_EXISTS opcode to speed up array_key_exists()
1 parent 23ae6ca commit 2265ca4

File tree

8 files changed

+1191
-530
lines changed

8 files changed

+1191
-530
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ PHP NEWS
1616
logging. (Philip Prindeville)
1717
. Fixed bug #63217 (Constant numeric strings become integers when used as
1818
ArrayAccess offset). (Rudi Theunissen)
19+
. Implement ZEND_ARRAY_KEY_EXISTS opcode to speed up array_key_exists().
20+
(Majkl578)
1921

2022
- DOM:
2123
. Fixed bug #76285 (DOMDocument::formatOutput attribute sometimes ignored).

Zend/zend_compile.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3876,6 +3876,22 @@ int zend_compile_func_get_args(znode *result, zend_ast_list *args) /* {{{ */
38763876
}
38773877
/* }}} */
38783878

3879+
int zend_compile_func_array_key_exists(znode *result, zend_ast_list *args) /* {{{ */
3880+
{
3881+
if (args->children != 2) {
3882+
return FAILURE;
3883+
}
3884+
3885+
znode subject, needle;
3886+
3887+
zend_compile_expr(&needle, args->child[0]);
3888+
zend_compile_expr(&subject, args->child[1]);
3889+
3890+
zend_emit_op_tmp(result, ZEND_ARRAY_KEY_EXISTS, &needle, &subject);
3891+
return SUCCESS;
3892+
}
3893+
/* }}} */
3894+
38793895
int zend_compile_func_array_slice(znode *result, zend_ast_list *args) /* {{{ */
38803896
{
38813897
if (CG(active_op_array)->function_name
@@ -3983,6 +3999,8 @@ int zend_try_compile_special_func(znode *result, zend_string *lcname, zend_ast_l
39833999
return zend_compile_func_get_args(result, args);
39844000
} else if (zend_string_equals_literal(lcname, "array_slice")) {
39854001
return zend_compile_func_array_slice(result, args);
4002+
} else if (zend_string_equals_literal(lcname, "array_key_exists")) {
4003+
return zend_compile_func_array_key_exists(result, args);
39864004
} else {
39874005
return FAILURE;
39884006
}

Zend/zend_vm_def.h

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6373,6 +6373,60 @@ ZEND_VM_C_LABEL(isset_no_object):
63736373
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
63746374
}
63756375

6376+
ZEND_VM_HANDLER(199, ZEND_ARRAY_KEY_EXISTS, CV|TMPVAR|CONST, CV|TMPVAR|CONST)
6377+
{
6378+
USE_OPLINE
6379+
6380+
zend_free_op free_op1, free_op2;
6381+
zval *subject, *key;
6382+
int result;
6383+
6384+
SAVE_OPLINE();
6385+
6386+
subject = GET_OP2_ZVAL_PTR(BP_VAR_R);
6387+
key = GET_OP1_ZVAL_PTR(BP_VAR_R);
6388+
6389+
if (UNEXPECTED(Z_ISREF_P(subject))) {
6390+
subject = Z_REFVAL_P(subject);
6391+
}
6392+
if (UNEXPECTED(Z_ISREF_P(key))) {
6393+
key = Z_REFVAL_P(key);
6394+
}
6395+
6396+
if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) {
6397+
if (EXPECTED(Z_TYPE_P(key) == IS_STRING)) {
6398+
result = zend_symtable_exists_ind(Z_ARRVAL_P(subject), Z_STR_P(key));
6399+
} else if (EXPECTED(Z_TYPE_P(key) == IS_LONG)) {
6400+
result = zend_hash_index_exists(Z_ARRVAL_P(subject), Z_LVAL_P(key));
6401+
} else if (UNEXPECTED(Z_TYPE_P(key) == IS_NULL)) {
6402+
result = zend_symtable_exists_ind(Z_ARRVAL_P(subject), ZSTR_EMPTY_ALLOC());
6403+
} else {
6404+
zend_error(E_WARNING, "array_key_exists(): The first argument should be either a string or an integer");
6405+
result = 0;
6406+
}
6407+
ZVAL_BOOL(EX_VAR(opline->result.var), result);
6408+
} else if (UNEXPECTED(Z_TYPE_P(subject) == IS_OBJECT)) {
6409+
if (EXPECTED(Z_TYPE_P(key) == IS_STRING)) {
6410+
result = zend_symtable_exists_ind(Z_OBJPROP_P(subject), Z_STR_P(key));
6411+
} else if (EXPECTED(Z_TYPE_P(key) == IS_LONG)) {
6412+
result = zend_hash_index_exists(Z_OBJPROP_P(subject), Z_LVAL_P(key));
6413+
} else if (UNEXPECTED(Z_TYPE_P(key) == IS_NULL)) {
6414+
result = zend_symtable_exists_ind(Z_OBJPROP_P(subject), ZSTR_EMPTY_ALLOC());
6415+
} else {
6416+
zend_error(E_WARNING, "array_key_exists(): The first argument should be either a string or an integer");
6417+
result = 0;
6418+
}
6419+
ZVAL_BOOL(EX_VAR(opline->result.var), result);
6420+
} else {
6421+
zend_internal_type_error(EX_USES_STRICT_TYPES(), "array_key_exists() expects parameter 2 to be array, %s given", zend_get_type_by_const(Z_TYPE_P(subject)));
6422+
ZVAL_NULL(EX_VAR(opline->result.var));
6423+
}
6424+
6425+
FREE_OP2();
6426+
FREE_OP1();
6427+
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
6428+
}
6429+
63766430
ZEND_VM_COLD_HANDLER(79, ZEND_EXIT, CONST|TMPVAR|UNUSED|CV, ANY)
63776431
{
63786432
USE_OPLINE

0 commit comments

Comments
 (0)