Skip to content

Commit f5044a1

Browse files
Majkl578dstogov
authored andcommitted
Implement ZEND_ARRAY_KEY_EXISTS opcode to speed up array_key_exists()
1 parent 9bd4aab commit f5044a1

File tree

8 files changed

+1298
-538
lines changed

8 files changed

+1298
-538
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ PHP NEWS
22
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
33
?? ??? ????, PHP 7.4.0alpha1
44

5+
- Core:
6+
. Implemented request #76148 (Add array_key_exists() to the list of
7+
specially compiled functions). (Majkl578)
8+
59
- CURL:
610
. Fixed bug #76480 (Use curl_multi_wait() so that timeouts are respected).
711
(Pierrick)

Zend/zend_compile.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2088,6 +2088,7 @@ ZEND_API int zend_is_smart_branch(zend_op *opline) /* {{{ */
20882088
case ZEND_TYPE_CHECK:
20892089
case ZEND_DEFINED:
20902090
case ZEND_IN_ARRAY:
2091+
case ZEND_ARRAY_KEY_EXISTS:
20912092
return 1;
20922093
default:
20932094
return 0;
@@ -3758,6 +3759,22 @@ int zend_compile_func_get_args(znode *result, zend_ast_list *args) /* {{{ */
37583759
}
37593760
/* }}} */
37603761

3762+
int zend_compile_func_array_key_exists(znode *result, zend_ast_list *args) /* {{{ */
3763+
{
3764+
znode subject, needle;
3765+
3766+
if (args->children != 2) {
3767+
return FAILURE;
3768+
}
3769+
3770+
zend_compile_expr(&needle, args->child[0]);
3771+
zend_compile_expr(&subject, args->child[1]);
3772+
3773+
zend_emit_op_tmp(result, ZEND_ARRAY_KEY_EXISTS, &needle, &subject);
3774+
return SUCCESS;
3775+
}
3776+
/* }}} */
3777+
37613778
int zend_compile_func_array_slice(znode *result, zend_ast_list *args) /* {{{ */
37623779
{
37633780
if (CG(active_op_array)->function_name
@@ -3869,6 +3886,8 @@ int zend_try_compile_special_func(znode *result, zend_string *lcname, zend_ast_l
38693886
return zend_compile_func_get_args(result, args);
38703887
} else if (zend_string_equals_literal(lcname, "array_slice")) {
38713888
return zend_compile_func_array_slice(result, args);
3889+
} else if (zend_string_equals_literal(lcname, "array_key_exists")) {
3890+
return zend_compile_func_array_key_exists(result, args);
38723891
} else {
38733892
return FAILURE;
38743893
}

Zend/zend_vm_def.h

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6370,6 +6370,69 @@ ZEND_VM_C_LABEL(isset_object_finish):
63706370
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
63716371
}
63726372

6373+
ZEND_VM_HANDLER(199, ZEND_ARRAY_KEY_EXISTS, CV|TMPVAR|CONST, CV|TMPVAR|CONST)
6374+
{
6375+
USE_OPLINE
6376+
6377+
zend_free_op free_op1, free_op2;
6378+
zval *key, *subject;
6379+
HashTable* ht;
6380+
int result;
6381+
6382+
SAVE_OPLINE();
6383+
6384+
key = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
6385+
subject = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
6386+
6387+
ZEND_VM_C_LABEL(try_again_subject):
6388+
if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) {
6389+
ht = Z_ARRVAL_P(subject);
6390+
} else if (UNEXPECTED(Z_TYPE_P(subject) == IS_OBJECT)) {
6391+
ht = Z_OBJPROP_P(subject);
6392+
} else if (Z_ISREF_P(subject)) {
6393+
subject = Z_REFVAL_P(subject);
6394+
ZEND_VM_C_GOTO(try_again_subject);
6395+
} else {
6396+
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(key) == IS_UNDEF)) {
6397+
ZVAL_UNDEFINED_OP1();
6398+
}
6399+
if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(subject) == IS_UNDEF)) {
6400+
subject = ZVAL_UNDEFINED_OP2();
6401+
}
6402+
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)));
6403+
FREE_OP2();
6404+
FREE_OP1();
6405+
ZVAL_NULL(EX_VAR(opline->result.var));
6406+
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
6407+
}
6408+
6409+
ZEND_VM_C_LABEL(try_again_key):
6410+
if (EXPECTED(Z_TYPE_P(key) == IS_STRING)) {
6411+
result = zend_symtable_exists_ind(ht, Z_STR_P(key));
6412+
} else if (EXPECTED(Z_TYPE_P(key) == IS_LONG)) {
6413+
result = zend_hash_index_exists(ht, Z_LVAL_P(key));
6414+
} else if (UNEXPECTED(Z_TYPE_P(key) == IS_NULL)) {
6415+
result = zend_hash_exists_ind(ht, ZSTR_EMPTY_ALLOC());
6416+
} else if (Z_TYPE_P(key) <= IS_NULL) {
6417+
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(key) == IS_UNDEF)) {
6418+
ZVAL_UNDEFINED_OP1();
6419+
}
6420+
result = zend_hash_exists_ind(ht, ZSTR_EMPTY_ALLOC());
6421+
} else if (Z_ISREF_P(key)) {
6422+
key = Z_REFVAL_P(key);
6423+
ZEND_VM_C_GOTO(try_again_key);
6424+
} else {
6425+
zend_error(E_WARNING, "array_key_exists(): The first argument should be either a string or an integer");
6426+
result = 0;
6427+
}
6428+
6429+
FREE_OP2();
6430+
FREE_OP1();
6431+
ZEND_VM_SMART_BRANCH(result, 1);
6432+
ZVAL_BOOL(EX_VAR(opline->result.var), result);
6433+
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
6434+
}
6435+
63736436
ZEND_VM_COLD_HANDLER(79, ZEND_EXIT, CONST|TMPVAR|UNUSED|CV, ANY)
63746437
{
63756438
USE_OPLINE

0 commit comments

Comments
 (0)