-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Implement ZEND_ARRAY_KEY_EXISTS opcode to speed up array_key_exists() #3360
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6370,6 +6370,69 @@ ZEND_VM_C_LABEL(isset_object_finish): | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | ||
} | ||
|
||
ZEND_VM_HANDLER(199, ZEND_ARRAY_KEY_EXISTS, CV|TMPVAR|CONST, CV|TMPVAR|CONST) | ||
{ | ||
USE_OPLINE | ||
|
||
zend_free_op free_op1, free_op2; | ||
zval *key, *subject; | ||
HashTable* ht; | ||
int result; | ||
|
||
SAVE_OPLINE(); | ||
|
||
key = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); | ||
subject = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); | ||
|
||
ZEND_VM_C_LABEL(try_again_subject): | ||
if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) { | ||
ht = Z_ARRVAL_P(subject); | ||
} else if (UNEXPECTED(Z_TYPE_P(subject) == IS_OBJECT)) { | ||
ht = Z_OBJPROP_P(subject); | ||
} else if (Z_ISREF_P(subject)) { | ||
subject = Z_REFVAL_P(subject); | ||
ZEND_VM_C_GOTO(try_again_subject); | ||
} else { | ||
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(key) == IS_UNDEF)) { | ||
ZVAL_UNDEFINED_OP1(); | ||
} | ||
if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(subject) == IS_UNDEF)) { | ||
subject = ZVAL_UNDEFINED_OP2(); | ||
} | ||
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))); | ||
FREE_OP2(); | ||
FREE_OP1(); | ||
ZVAL_NULL(EX_VAR(opline->result.var)); | ||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | ||
} | ||
|
||
ZEND_VM_C_LABEL(try_again_key): | ||
if (EXPECTED(Z_TYPE_P(key) == IS_STRING)) { | ||
result = zend_symtable_exists_ind(ht, Z_STR_P(key)); | ||
} else if (EXPECTED(Z_TYPE_P(key) == IS_LONG)) { | ||
result = zend_hash_index_exists(ht, Z_LVAL_P(key)); | ||
} else if (UNEXPECTED(Z_TYPE_P(key) == IS_NULL)) { | ||
result = zend_hash_exists_ind(ht, ZSTR_EMPTY_ALLOC()); | ||
} else if (Z_TYPE_P(key) <= IS_NULL) { | ||
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(key) == IS_UNDEF)) { | ||
ZVAL_UNDEFINED_OP1(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Must be OP2_TYPE ans ZVAL_UNDEFINED_OP2. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems, you changed OP1->OP2 in wrong place. I'll take care about this and merge. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, my bad. Everything is fine. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Key is OP1 and haystack is OP2 so it should be fine. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah. My mistake. It's already merged into master. |
||
} | ||
result = zend_hash_exists_ind(ht, ZSTR_EMPTY_ALLOC()); | ||
} else if (Z_ISREF_P(key)) { | ||
key = Z_REFVAL_P(key); | ||
ZEND_VM_C_GOTO(try_again_key); | ||
} else { | ||
zend_error(E_WARNING, "array_key_exists(): The first argument should be either a string or an integer"); | ||
result = 0; | ||
} | ||
|
||
FREE_OP2(); | ||
FREE_OP1(); | ||
ZEND_VM_SMART_BRANCH(result, 1); | ||
Majkl578 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
ZVAL_BOOL(EX_VAR(opline->result.var), result); | ||
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. array_key_exists() is a function that would benefit from smart branch handling. See https://github.com/Majkl578/php-src/blob/2265ca4f783b9e5e3a575ebe8c3b1f21f3009015/Zend/zend_vm_def.h#L8085 how this is done for ZEND_IN_ARRAY. You'll also have to add it to https://github.com/php/php-src/blob/master/Zend/zend_compile.c#L2181. |
||
} | ||
|
||
ZEND_VM_COLD_HANDLER(79, ZEND_EXIT, CONST|TMPVAR|UNUSED|CV, ANY) | ||
{ | ||
USE_OPLINE | ||
|
Uh oh!
There was an error while loading. Please reload this page.