Permalink
Cannot retrieve contributors at this time
10036 lines (8881 sloc)
283 KB
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
php-src/Zend/zend_vm_def.h
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
+----------------------------------------------------------------------+ | |
| Zend Engine | | |
+----------------------------------------------------------------------+ | |
| Copyright (c) Zend Technologies Ltd. (http://www.zend.com) | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 2.00 of the Zend license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
| available through the world-wide-web at the following url: | | |
| http://www.zend.com/license/2_00.txt. | | |
| If you did not receive a copy of the Zend license and are unable to | | |
| obtain it through the world-wide-web, please send a note to | | |
| license@zend.com so we can mail you a copy immediately. | | |
+----------------------------------------------------------------------+ | |
| Authors: Andi Gutmans <andi@php.net> | | |
| Zeev Suraski <zeev@php.net> | | |
| Dmitry Stogov <dmitry@php.net> | | |
+----------------------------------------------------------------------+ | |
*/ | |
/* If you change this file, please regenerate the zend_vm_execute.h and | |
* zend_vm_opcodes.h files by running: | |
* php zend_vm_gen.php | |
*/ | |
ZEND_VM_HELPER(zend_add_helper, ANY, ANY, zval *op_1, zval *op_2) | |
{ | |
USE_OPLINE | |
SAVE_OPLINE(); | |
if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) { | |
op_1 = ZVAL_UNDEFINED_OP1(); | |
} | |
if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { | |
op_2 = ZVAL_UNDEFINED_OP2(); | |
} | |
add_function(EX_VAR(opline->result.var), op_1, op_2); | |
if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zval_ptr_dtor_nogc(op_1); | |
} | |
if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zval_ptr_dtor_nogc(op_2); | |
} | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_HOT_NOCONSTCONST_HANDLER(1, ZEND_ADD, CONST|TMPVARCV, CONST|TMPVARCV) | |
{ | |
USE_OPLINE | |
zval *op1, *op2, *result; | |
double d1, d2; | |
op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); | |
op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); | |
if (ZEND_VM_SPEC && OP1_TYPE == IS_CONST && OP2_TYPE == IS_CONST) { | |
/* pass */ | |
} else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { | |
if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { | |
result = EX_VAR(opline->result.var); | |
fast_long_add_function(result, op1, op2); | |
ZEND_VM_NEXT_OPCODE(); | |
} else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { | |
d1 = (double)Z_LVAL_P(op1); | |
d2 = Z_DVAL_P(op2); | |
ZEND_VM_C_GOTO(add_double); | |
} | |
} else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { | |
if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { | |
d1 = Z_DVAL_P(op1); | |
d2 = Z_DVAL_P(op2); | |
ZEND_VM_C_LABEL(add_double): | |
result = EX_VAR(opline->result.var); | |
ZVAL_DOUBLE(result, d1 + d2); | |
ZEND_VM_NEXT_OPCODE(); | |
} else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { | |
d1 = Z_DVAL_P(op1); | |
d2 = (double)Z_LVAL_P(op2); | |
ZEND_VM_C_GOTO(add_double); | |
} | |
} | |
ZEND_VM_DISPATCH_TO_HELPER(zend_add_helper, op_1, op1, op_2, op2); | |
} | |
ZEND_VM_HELPER(zend_sub_helper, ANY, ANY, zval *op_1, zval *op_2) | |
{ | |
USE_OPLINE | |
SAVE_OPLINE(); | |
if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) { | |
op_1 = ZVAL_UNDEFINED_OP1(); | |
} | |
if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { | |
op_2 = ZVAL_UNDEFINED_OP2(); | |
} | |
sub_function(EX_VAR(opline->result.var), op_1, op_2); | |
if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zval_ptr_dtor_nogc(op_1); | |
} | |
if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zval_ptr_dtor_nogc(op_2); | |
} | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_HOT_NOCONSTCONST_HANDLER(2, ZEND_SUB, CONST|TMPVARCV, CONST|TMPVARCV) | |
{ | |
USE_OPLINE | |
zval *op1, *op2, *result; | |
double d1, d2; | |
op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); | |
op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); | |
if (ZEND_VM_SPEC && OP1_TYPE == IS_CONST && OP2_TYPE == IS_CONST) { | |
/* pass */ | |
} else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { | |
if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { | |
result = EX_VAR(opline->result.var); | |
fast_long_sub_function(result, op1, op2); | |
ZEND_VM_NEXT_OPCODE(); | |
} else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { | |
d1 = (double)Z_LVAL_P(op1); | |
d2 = Z_DVAL_P(op2); | |
ZEND_VM_C_GOTO(sub_double); | |
} | |
} else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { | |
if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { | |
d1 = Z_DVAL_P(op1); | |
d2 = Z_DVAL_P(op2); | |
ZEND_VM_C_LABEL(sub_double): | |
result = EX_VAR(opline->result.var); | |
ZVAL_DOUBLE(result, d1 - d2); | |
ZEND_VM_NEXT_OPCODE(); | |
} else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { | |
d1 = Z_DVAL_P(op1); | |
d2 = (double)Z_LVAL_P(op2); | |
ZEND_VM_C_GOTO(sub_double); | |
} | |
} | |
ZEND_VM_DISPATCH_TO_HELPER(zend_sub_helper, op_1, op1, op_2, op2); | |
} | |
ZEND_VM_HELPER(zend_mul_helper, ANY, ANY, zval *op_1, zval *op_2) | |
{ | |
USE_OPLINE | |
SAVE_OPLINE(); | |
if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) { | |
op_1 = ZVAL_UNDEFINED_OP1(); | |
} | |
if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { | |
op_2 = ZVAL_UNDEFINED_OP2(); | |
} | |
mul_function(EX_VAR(opline->result.var), op_1, op_2); | |
if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zval_ptr_dtor_nogc(op_1); | |
} | |
if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zval_ptr_dtor_nogc(op_2); | |
} | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_COLD_CONSTCONST_HANDLER(3, ZEND_MUL, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(COMMUTATIVE)) | |
{ | |
USE_OPLINE | |
zval *op1, *op2, *result; | |
double d1, d2; | |
op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); | |
op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); | |
if (ZEND_VM_SPEC && OP1_TYPE == IS_CONST && OP2_TYPE == IS_CONST) { | |
/* pass */ | |
} else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { | |
if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { | |
zend_long overflow; | |
result = EX_VAR(opline->result.var); | |
ZEND_SIGNED_MULTIPLY_LONG(Z_LVAL_P(op1), Z_LVAL_P(op2), Z_LVAL_P(result), Z_DVAL_P(result), overflow); | |
Z_TYPE_INFO_P(result) = overflow ? IS_DOUBLE : IS_LONG; | |
ZEND_VM_NEXT_OPCODE(); | |
} else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { | |
d1 = (double)Z_LVAL_P(op1); | |
d2 = Z_DVAL_P(op2); | |
ZEND_VM_C_GOTO(mul_double); | |
} | |
} else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { | |
if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { | |
d1 = Z_DVAL_P(op1); | |
d2 = Z_DVAL_P(op2); | |
ZEND_VM_C_LABEL(mul_double): | |
result = EX_VAR(opline->result.var); | |
ZVAL_DOUBLE(result, d1 * d2); | |
ZEND_VM_NEXT_OPCODE(); | |
} else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { | |
d1 = Z_DVAL_P(op1); | |
d2 = (double)Z_LVAL_P(op2); | |
ZEND_VM_C_GOTO(mul_double); | |
} | |
} | |
ZEND_VM_DISPATCH_TO_HELPER(zend_mul_helper, op_1, op1, op_2, op2); | |
} | |
ZEND_VM_COLD_CONSTCONST_HANDLER(4, ZEND_DIV, CONST|TMPVAR|CV, CONST|TMPVAR|CV) | |
{ | |
USE_OPLINE | |
zval *op1, *op2; | |
SAVE_OPLINE(); | |
op1 = GET_OP1_ZVAL_PTR(BP_VAR_R); | |
op2 = GET_OP2_ZVAL_PTR(BP_VAR_R); | |
div_function(EX_VAR(opline->result.var), op1, op2); | |
FREE_OP1(); | |
FREE_OP2(); | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_COLD_HELPER(zend_mod_by_zero_helper, ANY, ANY) | |
{ | |
USE_OPLINE | |
SAVE_OPLINE(); | |
zend_throw_exception_ex(zend_ce_division_by_zero_error, 0, "Modulo by zero"); | |
ZVAL_UNDEF(EX_VAR(opline->result.var)); | |
HANDLE_EXCEPTION(); | |
} | |
ZEND_VM_HELPER(zend_mod_helper, ANY, ANY, zval *op_1, zval *op_2) | |
{ | |
USE_OPLINE | |
SAVE_OPLINE(); | |
if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) { | |
op_1 = ZVAL_UNDEFINED_OP1(); | |
} | |
if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { | |
op_2 = ZVAL_UNDEFINED_OP2(); | |
} | |
mod_function(EX_VAR(opline->result.var), op_1, op_2); | |
if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zval_ptr_dtor_nogc(op_1); | |
} | |
if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zval_ptr_dtor_nogc(op_2); | |
} | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_COLD_CONSTCONST_HANDLER(5, ZEND_MOD, CONST|TMPVARCV, CONST|TMPVARCV) | |
{ | |
USE_OPLINE | |
zval *op1, *op2, *result; | |
op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); | |
op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); | |
if (ZEND_VM_SPEC && OP1_TYPE == IS_CONST && OP2_TYPE == IS_CONST) { | |
/* pass */ | |
} else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { | |
if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { | |
result = EX_VAR(opline->result.var); | |
if (UNEXPECTED(Z_LVAL_P(op2) == 0)) { | |
ZEND_VM_DISPATCH_TO_HELPER(zend_mod_by_zero_helper); | |
} else if (UNEXPECTED(Z_LVAL_P(op2) == -1)) { | |
/* Prevent overflow error/crash if op1==ZEND_LONG_MIN */ | |
ZVAL_LONG(result, 0); | |
} else { | |
ZVAL_LONG(result, Z_LVAL_P(op1) % Z_LVAL_P(op2)); | |
} | |
ZEND_VM_NEXT_OPCODE(); | |
} | |
} | |
ZEND_VM_DISPATCH_TO_HELPER(zend_mod_helper, op_1, op1, op_2, op2); | |
} | |
ZEND_VM_HELPER(zend_shift_left_helper, ANY, ANY, zval *op_1, zval *op_2) | |
{ | |
USE_OPLINE | |
SAVE_OPLINE(); | |
if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) { | |
op_1 = ZVAL_UNDEFINED_OP1(); | |
} | |
if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { | |
op_2 = ZVAL_UNDEFINED_OP2(); | |
} | |
shift_left_function(EX_VAR(opline->result.var), op_1, op_2); | |
if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zval_ptr_dtor_nogc(op_1); | |
} | |
if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zval_ptr_dtor_nogc(op_2); | |
} | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_COLD_CONSTCONST_HANDLER(6, ZEND_SL, CONST|TMPVARCV, CONST|TMPVARCV) | |
{ | |
USE_OPLINE | |
zval *op1, *op2; | |
op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); | |
op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); | |
if (ZEND_VM_SPEC && OP1_TYPE == IS_CONST && OP2_TYPE == IS_CONST) { | |
/* pass */ | |
} else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG) | |
&& EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG) | |
&& EXPECTED((zend_ulong)Z_LVAL_P(op2) < SIZEOF_ZEND_LONG * 8)) { | |
/* Perform shift on unsigned numbers to get well-defined wrap behavior. */ | |
ZVAL_LONG(EX_VAR(opline->result.var), | |
(zend_long) ((zend_ulong) Z_LVAL_P(op1) << Z_LVAL_P(op2))); | |
ZEND_VM_NEXT_OPCODE(); | |
} | |
ZEND_VM_DISPATCH_TO_HELPER(zend_shift_left_helper, op_1, op1, op_2, op2); | |
} | |
ZEND_VM_HELPER(zend_shift_right_helper, ANY, ANY, zval *op_1, zval *op_2) | |
{ | |
USE_OPLINE | |
SAVE_OPLINE(); | |
if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) { | |
op_1 = ZVAL_UNDEFINED_OP1(); | |
} | |
if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { | |
op_2 = ZVAL_UNDEFINED_OP2(); | |
} | |
shift_right_function(EX_VAR(opline->result.var), op_1, op_2); | |
if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zval_ptr_dtor_nogc(op_1); | |
} | |
if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zval_ptr_dtor_nogc(op_2); | |
} | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_COLD_CONSTCONST_HANDLER(7, ZEND_SR, CONST|TMPVARCV, CONST|TMPVARCV) | |
{ | |
USE_OPLINE | |
zval *op1, *op2; | |
op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); | |
op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); | |
if (ZEND_VM_SPEC && OP1_TYPE == IS_CONST && OP2_TYPE == IS_CONST) { | |
/* pass */ | |
} else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG) | |
&& EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG) | |
&& EXPECTED((zend_ulong)Z_LVAL_P(op2) < SIZEOF_ZEND_LONG * 8)) { | |
ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(op1) >> Z_LVAL_P(op2)); | |
ZEND_VM_NEXT_OPCODE(); | |
} | |
ZEND_VM_DISPATCH_TO_HELPER(zend_shift_right_helper, op_1, op1, op_2, op2); | |
} | |
ZEND_VM_COLD_CONSTCONST_HANDLER(12, ZEND_POW, CONST|TMPVAR|CV, CONST|TMPVAR|CV) | |
{ | |
USE_OPLINE | |
zval *op1, *op2; | |
SAVE_OPLINE(); | |
op1 = GET_OP1_ZVAL_PTR(BP_VAR_R); | |
op2 = GET_OP2_ZVAL_PTR(BP_VAR_R); | |
pow_function(EX_VAR(opline->result.var), op1, op2); | |
FREE_OP1(); | |
FREE_OP2(); | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_HANDLER(8, ZEND_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(NO_CONST_CONST)) | |
{ | |
USE_OPLINE | |
zval *op1, *op2; | |
op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); | |
op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); | |
if ((OP1_TYPE == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && | |
(OP2_TYPE == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { | |
zend_string *op1_str = Z_STR_P(op1); | |
zend_string *op2_str = Z_STR_P(op2); | |
zend_string *str; | |
uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(op1_str, op2_str); | |
if (OP1_TYPE != IS_CONST && UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { | |
if (OP2_TYPE == IS_CONST || OP2_TYPE == IS_CV) { | |
ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str); | |
} else { | |
ZVAL_STR(EX_VAR(opline->result.var), op2_str); | |
} | |
if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zend_string_release_ex(op1_str, 0); | |
} | |
} else if (OP2_TYPE != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { | |
if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_CV) { | |
ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); | |
} else { | |
ZVAL_STR(EX_VAR(opline->result.var), op1_str); | |
} | |
if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zend_string_release_ex(op2_str, 0); | |
} | |
} else if (OP1_TYPE != IS_CONST && OP1_TYPE != IS_CV && | |
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { | |
size_t len = ZSTR_LEN(op1_str); | |
if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) { | |
zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation"); | |
} | |
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); | |
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); | |
GC_ADD_FLAGS(str, flags); | |
ZVAL_NEW_STR(EX_VAR(opline->result.var), str); | |
if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zend_string_release_ex(op2_str, 0); | |
} | |
} else { | |
str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0); | |
memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str)); | |
memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); | |
GC_ADD_FLAGS(str, flags); | |
ZVAL_NEW_STR(EX_VAR(opline->result.var), str); | |
if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zend_string_release_ex(op1_str, 0); | |
} | |
if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zend_string_release_ex(op2_str, 0); | |
} | |
} | |
ZEND_VM_NEXT_OPCODE(); | |
} else { | |
SAVE_OPLINE(); | |
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) { | |
op1 = ZVAL_UNDEFINED_OP1(); | |
} | |
if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) { | |
op2 = ZVAL_UNDEFINED_OP2(); | |
} | |
concat_function(EX_VAR(opline->result.var), op1, op2); | |
FREE_OP1(); | |
FREE_OP2(); | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
} | |
ZEND_VM_COLD_CONSTCONST_HANDLER(16, ZEND_IS_IDENTICAL, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV, SPEC(COMMUTATIVE)) | |
{ | |
USE_OPLINE | |
zval *op1, *op2; | |
bool result; | |
SAVE_OPLINE(); | |
op1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R); | |
op2 = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R); | |
result = fast_is_identical_function(op1, op2); | |
FREE_OP1(); | |
FREE_OP2(); | |
ZEND_VM_SMART_BRANCH(result, 1); | |
} | |
ZEND_VM_HANDLER(196, ZEND_CASE_STRICT, TMP|VAR, CONST|TMP|VAR|CV) | |
{ | |
USE_OPLINE | |
zval *op1, *op2; | |
bool result; | |
SAVE_OPLINE(); | |
op1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R); | |
op2 = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R); | |
result = fast_is_identical_function(op1, op2); | |
FREE_OP2(); | |
ZEND_VM_SMART_BRANCH(result, 1); | |
} | |
ZEND_VM_COLD_CONSTCONST_HANDLER(17, ZEND_IS_NOT_IDENTICAL, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV, SPEC(COMMUTATIVE)) | |
{ | |
USE_OPLINE | |
zval *op1, *op2; | |
bool result; | |
SAVE_OPLINE(); | |
op1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R); | |
op2 = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R); | |
result = fast_is_not_identical_function(op1, op2); | |
FREE_OP1(); | |
FREE_OP2(); | |
ZEND_VM_SMART_BRANCH(result, 1); | |
} | |
ZEND_VM_HELPER(zend_is_equal_helper, ANY, ANY, zval *op_1, zval *op_2) | |
{ | |
int ret; | |
USE_OPLINE | |
SAVE_OPLINE(); | |
if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) { | |
op_1 = ZVAL_UNDEFINED_OP1(); | |
} | |
if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { | |
op_2 = ZVAL_UNDEFINED_OP2(); | |
} | |
ret = zend_compare(op_1, op_2); | |
if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zval_ptr_dtor_nogc(op_1); | |
} | |
if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zval_ptr_dtor_nogc(op_2); | |
} | |
ZEND_VM_SMART_BRANCH(ret == 0, 1); | |
} | |
ZEND_VM_COLD_CONSTCONST_HANDLER(18, ZEND_IS_EQUAL, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(SMART_BRANCH,COMMUTATIVE)) | |
{ | |
USE_OPLINE | |
zval *op1, *op2; | |
double d1, d2; | |
op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); | |
op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); | |
if (ZEND_VM_SPEC && OP1_TYPE == IS_CONST && OP2_TYPE == IS_CONST) { | |
/* pass */ | |
} else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { | |
if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { | |
if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) { | |
ZEND_VM_C_LABEL(is_equal_true): | |
ZEND_VM_SMART_BRANCH_TRUE(); | |
} else { | |
ZEND_VM_C_LABEL(is_equal_false): | |
ZEND_VM_SMART_BRANCH_FALSE(); | |
} | |
} else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { | |
d1 = (double)Z_LVAL_P(op1); | |
d2 = Z_DVAL_P(op2); | |
ZEND_VM_C_GOTO(is_equal_double); | |
} | |
} else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { | |
if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { | |
d1 = Z_DVAL_P(op1); | |
d2 = Z_DVAL_P(op2); | |
ZEND_VM_C_LABEL(is_equal_double): | |
if (d1 == d2) { | |
ZEND_VM_C_GOTO(is_equal_true); | |
} else { | |
ZEND_VM_C_GOTO(is_equal_false); | |
} | |
} else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { | |
d1 = Z_DVAL_P(op1); | |
d2 = (double)Z_LVAL_P(op2); | |
ZEND_VM_C_GOTO(is_equal_double); | |
} | |
} else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { | |
if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { | |
bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); | |
if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zval_ptr_dtor_str(op1); | |
} | |
if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zval_ptr_dtor_str(op2); | |
} | |
if (result) { | |
ZEND_VM_C_GOTO(is_equal_true); | |
} else { | |
ZEND_VM_C_GOTO(is_equal_false); | |
} | |
} | |
} | |
ZEND_VM_DISPATCH_TO_HELPER(zend_is_equal_helper, op_1, op1, op_2, op2); | |
} | |
ZEND_VM_HELPER(zend_is_not_equal_helper, ANY, ANY, zval *op_1, zval *op_2) | |
{ | |
int ret; | |
USE_OPLINE | |
SAVE_OPLINE(); | |
if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) { | |
op_1 = ZVAL_UNDEFINED_OP1(); | |
} | |
if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { | |
op_2 = ZVAL_UNDEFINED_OP2(); | |
} | |
ret = zend_compare(op_1, op_2); | |
if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zval_ptr_dtor_nogc(op_1); | |
} | |
if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zval_ptr_dtor_nogc(op_2); | |
} | |
ZEND_VM_SMART_BRANCH(ret != 0, 1); | |
} | |
ZEND_VM_COLD_CONSTCONST_HANDLER(19, ZEND_IS_NOT_EQUAL, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(SMART_BRANCH,COMMUTATIVE)) | |
{ | |
USE_OPLINE | |
zval *op1, *op2; | |
double d1, d2; | |
op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); | |
op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); | |
if (ZEND_VM_SPEC && OP1_TYPE == IS_CONST && OP2_TYPE == IS_CONST) { | |
/* pass */ | |
} else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { | |
if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { | |
if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) { | |
ZEND_VM_C_LABEL(is_not_equal_true): | |
ZEND_VM_SMART_BRANCH_TRUE(); | |
} else { | |
ZEND_VM_C_LABEL(is_not_equal_false): | |
ZEND_VM_SMART_BRANCH_FALSE(); | |
} | |
} else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { | |
d1 = (double)Z_LVAL_P(op1); | |
d2 = Z_DVAL_P(op2); | |
ZEND_VM_C_GOTO(is_not_equal_double); | |
} | |
} else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) { | |
if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) { | |
d1 = Z_DVAL_P(op1); | |
d2 = Z_DVAL_P(op2); | |
ZEND_VM_C_LABEL(is_not_equal_double): | |
if (d1 != d2) { | |
ZEND_VM_C_GOTO(is_not_equal_true); | |
} else { | |
ZEND_VM_C_GOTO(is_not_equal_false); | |
} | |
} else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) { | |
d1 = Z_DVAL_P(op1); | |
d2 = (double)Z_LVAL_P(op2); | |
ZEND_VM_C_GOTO(is_not_equal_double); | |
} | |
} else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) { | |
if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) { | |
bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2)); | |
if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zval_ptr_dtor_str(op1); | |
} | |
if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zval_ptr_dtor_str(op2); | |
} | |
if (!result) { | |
ZEND_VM_C_GOTO(is_not_equal_true); | |
} else { | |
ZEND_VM_C_GOTO(is_not_equal_false); | |
} | |
} | |
} | |
ZEND_VM_DISPATCH_TO_HELPER(zend_is_not_equal_helper, op_1, op1, op_2, op2); | |
} | |
ZEND_VM_HELPER(zend_is_smaller_helper, ANY, ANY, zval *op_1, zval *op_2) | |
{ | |
int ret; | |
USE_OPLINE | |
SAVE_OPLINE(); | |
if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) { | |
op_1 = ZVAL_UNDEFINED_OP1(); | |
} | |
if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { | |
op_2 = ZVAL_UNDEFINED_OP2(); | |
} | |
ret = zend_compare(op_1, op_2); | |
if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zval_ptr_dtor_nogc(op_1); | |
} | |
if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zval_ptr_dtor_nogc(op_2); | |
} | |
ZEND_VM_SMART_BRANCH(ret < 0, 1); | |
} | |
ZEND_VM_HOT_NOCONSTCONST_HANDLER(20, ZEND_IS_SMALLER, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH)) | |
{ | |
USE_OPLINE | |
zval *op1, *op2; | |
double d1, d2; | |
op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); | |
op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); | |
if (ZEND_VM_SPEC && OP1_TYPE == IS_CONST && OP2_TYPE == IS_CONST) { | |
/* pass */ | |
} else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { | |
if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { | |
if (EXPECTED(Z_LVAL_P(op1) < Z_LVAL_P(op2))) { | |
ZEND_VM_C_LABEL(is_smaller_true): | |
ZEND_VM_SMART_BRANCH_TRUE(); | |
} else { | |
ZEND_VM_C_LABEL(is_smaller_false): | |
ZEND_VM_SMART_BRANCH_FALSE(); | |
} | |
} else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { | |
d1 = (double)Z_LVAL_P(op1); | |
d2 = Z_DVAL_P(op2); | |
ZEND_VM_C_GOTO(is_smaller_double); | |
} | |
} else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { | |
if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { | |
d1 = Z_DVAL_P(op1); | |
d2 = Z_DVAL_P(op2); | |
ZEND_VM_C_LABEL(is_smaller_double): | |
if (d1 < d2) { | |
ZEND_VM_C_GOTO(is_smaller_true); | |
} else { | |
ZEND_VM_C_GOTO(is_smaller_false); | |
} | |
} else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { | |
d1 = Z_DVAL_P(op1); | |
d2 = (double)Z_LVAL_P(op2); | |
ZEND_VM_C_GOTO(is_smaller_double); | |
} | |
} | |
ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_helper, op_1, op1, op_2, op2); | |
} | |
ZEND_VM_HELPER(zend_is_smaller_or_equal_helper, ANY, ANY, zval *op_1, zval *op_2) | |
{ | |
int ret; | |
USE_OPLINE | |
SAVE_OPLINE(); | |
if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) { | |
op_1 = ZVAL_UNDEFINED_OP1(); | |
} | |
if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { | |
op_2 = ZVAL_UNDEFINED_OP2(); | |
} | |
ret = zend_compare(op_1, op_2); | |
if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zval_ptr_dtor_nogc(op_1); | |
} | |
if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zval_ptr_dtor_nogc(op_2); | |
} | |
ZEND_VM_SMART_BRANCH(ret <= 0, 1); | |
} | |
ZEND_VM_HOT_NOCONSTCONST_HANDLER(21, ZEND_IS_SMALLER_OR_EQUAL, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH)) | |
{ | |
USE_OPLINE | |
zval *op1, *op2; | |
double d1, d2; | |
op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); | |
op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); | |
if (ZEND_VM_SPEC && OP1_TYPE == IS_CONST && OP2_TYPE == IS_CONST) { | |
/* pass */ | |
} else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { | |
if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { | |
if (EXPECTED(Z_LVAL_P(op1) <= Z_LVAL_P(op2))) { | |
ZEND_VM_C_LABEL(is_smaller_or_equal_true): | |
ZEND_VM_SMART_BRANCH_TRUE(); | |
ZVAL_TRUE(EX_VAR(opline->result.var)); | |
ZEND_VM_NEXT_OPCODE(); | |
} else { | |
ZEND_VM_C_LABEL(is_smaller_or_equal_false): | |
ZEND_VM_SMART_BRANCH_FALSE(); | |
ZVAL_FALSE(EX_VAR(opline->result.var)); | |
ZEND_VM_NEXT_OPCODE(); | |
} | |
} else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { | |
d1 = (double)Z_LVAL_P(op1); | |
d2 = Z_DVAL_P(op2); | |
ZEND_VM_C_GOTO(is_smaller_or_equal_double); | |
} | |
} else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) { | |
if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) { | |
d1 = Z_DVAL_P(op1); | |
d2 = Z_DVAL_P(op2); | |
ZEND_VM_C_LABEL(is_smaller_or_equal_double): | |
if (d1 <= d2) { | |
ZEND_VM_C_GOTO(is_smaller_or_equal_true); | |
} else { | |
ZEND_VM_C_GOTO(is_smaller_or_equal_false); | |
} | |
} else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { | |
d1 = Z_DVAL_P(op1); | |
d2 = (double)Z_LVAL_P(op2); | |
ZEND_VM_C_GOTO(is_smaller_or_equal_double); | |
} | |
} | |
ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_or_equal_helper, op_1, op1, op_2, op2); | |
} | |
ZEND_VM_COLD_CONSTCONST_HANDLER(170, ZEND_SPACESHIP, CONST|TMPVAR|CV, CONST|TMPVAR|CV) | |
{ | |
USE_OPLINE | |
zval *op1, *op2; | |
SAVE_OPLINE(); | |
op1 = GET_OP1_ZVAL_PTR(BP_VAR_R); | |
op2 = GET_OP2_ZVAL_PTR(BP_VAR_R); | |
compare_function(EX_VAR(opline->result.var), op1, op2); | |
FREE_OP1(); | |
FREE_OP2(); | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_HELPER(zend_bw_or_helper, ANY, ANY, zval *op_1, zval *op_2) | |
{ | |
USE_OPLINE | |
SAVE_OPLINE(); | |
if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) { | |
op_1 = ZVAL_UNDEFINED_OP1(); | |
} | |
if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { | |
op_2 = ZVAL_UNDEFINED_OP2(); | |
} | |
bitwise_or_function(EX_VAR(opline->result.var), op_1, op_2); | |
if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zval_ptr_dtor_nogc(op_1); | |
} | |
if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zval_ptr_dtor_nogc(op_2); | |
} | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_HOT_NOCONSTCONST_HANDLER(9, ZEND_BW_OR, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(COMMUTATIVE)) | |
{ | |
USE_OPLINE | |
zval *op1, *op2; | |
op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); | |
op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); | |
if (ZEND_VM_SPEC && OP1_TYPE == IS_CONST && OP2_TYPE == IS_CONST) { | |
/* pass */ | |
} else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG) | |
&& EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { | |
ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(op1) | Z_LVAL_P(op2)); | |
ZEND_VM_NEXT_OPCODE(); | |
} | |
ZEND_VM_DISPATCH_TO_HELPER(zend_bw_or_helper, op_1, op1, op_2, op2); | |
} | |
ZEND_VM_HELPER(zend_bw_and_helper, ANY, ANY, zval *op_1, zval *op_2) | |
{ | |
USE_OPLINE | |
SAVE_OPLINE(); | |
if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) { | |
op_1 = ZVAL_UNDEFINED_OP1(); | |
} | |
if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { | |
op_2 = ZVAL_UNDEFINED_OP2(); | |
} | |
bitwise_and_function(EX_VAR(opline->result.var), op_1, op_2); | |
if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zval_ptr_dtor_nogc(op_1); | |
} | |
if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zval_ptr_dtor_nogc(op_2); | |
} | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_HOT_NOCONSTCONST_HANDLER(10, ZEND_BW_AND, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(COMMUTATIVE)) | |
{ | |
USE_OPLINE | |
zval *op1, *op2; | |
op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); | |
op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); | |
if (ZEND_VM_SPEC && OP1_TYPE == IS_CONST && OP2_TYPE == IS_CONST) { | |
/* pass */ | |
} else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG) | |
&& EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { | |
ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(op1) & Z_LVAL_P(op2)); | |
ZEND_VM_NEXT_OPCODE(); | |
} | |
ZEND_VM_DISPATCH_TO_HELPER(zend_bw_and_helper, op_1, op1, op_2, op2); | |
} | |
ZEND_VM_HELPER(zend_bw_xor_helper, ANY, ANY, zval *op_1, zval *op_2) | |
{ | |
USE_OPLINE | |
SAVE_OPLINE(); | |
if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) { | |
op_1 = ZVAL_UNDEFINED_OP1(); | |
} | |
if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) { | |
op_2 = ZVAL_UNDEFINED_OP2(); | |
} | |
bitwise_xor_function(EX_VAR(opline->result.var), op_1, op_2); | |
if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zval_ptr_dtor_nogc(op_1); | |
} | |
if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zval_ptr_dtor_nogc(op_2); | |
} | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_HOT_NOCONSTCONST_HANDLER(11, ZEND_BW_XOR, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(COMMUTATIVE)) | |
{ | |
USE_OPLINE | |
zval *op1, *op2; | |
op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); | |
op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); | |
if (ZEND_VM_SPEC && OP1_TYPE == IS_CONST && OP2_TYPE == IS_CONST) { | |
/* pass */ | |
} else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG) | |
&& EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) { | |
ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(op1) ^ Z_LVAL_P(op2)); | |
ZEND_VM_NEXT_OPCODE(); | |
} | |
ZEND_VM_DISPATCH_TO_HELPER(zend_bw_xor_helper, op_1, op1, op_2, op2); | |
} | |
ZEND_VM_COLD_CONSTCONST_HANDLER(15, ZEND_BOOL_XOR, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(COMMUTATIVE)) | |
{ | |
USE_OPLINE | |
zval *op1, *op2; | |
SAVE_OPLINE(); | |
op1 = GET_OP1_ZVAL_PTR(BP_VAR_R); | |
op2 = GET_OP2_ZVAL_PTR(BP_VAR_R); | |
boolean_xor_function(EX_VAR(opline->result.var), op1, op2); | |
FREE_OP1(); | |
FREE_OP2(); | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_HELPER(zend_bw_not_helper, ANY, ANY, zval *op_1) | |
{ | |
USE_OPLINE | |
SAVE_OPLINE(); | |
if (UNEXPECTED(Z_TYPE_P(op_1) == IS_UNDEF)) { | |
op_1 = ZVAL_UNDEFINED_OP1(); | |
} | |
bitwise_not_function(EX_VAR(opline->result.var), op_1); | |
FREE_OP1(); | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_HOT_NOCONST_HANDLER(13, ZEND_BW_NOT, CONST|TMPVARCV, ANY) | |
{ | |
USE_OPLINE | |
zval *op1; | |
op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); | |
if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) { | |
ZVAL_LONG(EX_VAR(opline->result.var), ~Z_LVAL_P(op1)); | |
ZEND_VM_NEXT_OPCODE(); | |
} | |
ZEND_VM_DISPATCH_TO_HELPER(zend_bw_not_helper, op_1, op1); | |
} | |
ZEND_VM_COLD_CONST_HANDLER(14, ZEND_BOOL_NOT, CONST|TMPVAR|CV, ANY) | |
{ | |
USE_OPLINE | |
zval *val; | |
val = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); | |
if (Z_TYPE_INFO_P(val) == IS_TRUE) { | |
ZVAL_FALSE(EX_VAR(opline->result.var)); | |
} else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) { | |
/* The result and op1 can be the same cv zval */ | |
const uint32_t orig_val_type = Z_TYPE_INFO_P(val); | |
ZVAL_TRUE(EX_VAR(opline->result.var)); | |
if (OP1_TYPE == IS_CV && UNEXPECTED(orig_val_type == IS_UNDEF)) { | |
SAVE_OPLINE(); | |
ZVAL_UNDEFINED_OP1(); | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
} else { | |
SAVE_OPLINE(); | |
ZVAL_BOOL(EX_VAR(opline->result.var), !i_zend_is_true(val)); | |
FREE_OP1(); | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_NEXT_OPCODE(); | |
} | |
ZEND_VM_COLD_HELPER(zend_this_not_in_object_context_helper, ANY, ANY) | |
{ | |
USE_OPLINE | |
SAVE_OPLINE(); | |
zend_throw_error(NULL, "Using $this when not in object context"); | |
UNDEF_RESULT(); | |
HANDLE_EXCEPTION(); | |
} | |
ZEND_VM_COLD_HELPER(zend_undefined_function_helper, ANY, ANY) | |
{ | |
USE_OPLINE | |
zval *function_name; | |
SAVE_OPLINE(); | |
function_name = RT_CONSTANT(opline, opline->op2); | |
zend_throw_error(NULL, "Call to undefined function %s()", Z_STRVAL_P(function_name)); | |
HANDLE_EXCEPTION(); | |
} | |
ZEND_VM_HANDLER(28, ZEND_ASSIGN_OBJ_OP, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, OP) | |
{ | |
USE_OPLINE | |
zval *object; | |
zval *property; | |
zval *value; | |
zval *zptr; | |
void **cache_slot; | |
zend_property_info *prop_info; | |
zend_object *zobj; | |
zend_string *name, *tmp_name; | |
SAVE_OPLINE(); | |
object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW); | |
property = GET_OP2_ZVAL_PTR(BP_VAR_R); | |
do { | |
value = GET_OP_DATA_ZVAL_PTR(BP_VAR_R); | |
if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { | |
if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { | |
object = Z_REFVAL_P(object); | |
ZEND_VM_C_GOTO(assign_op_object); | |
} | |
if (OP1_TYPE == IS_CV | |
&& UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { | |
ZVAL_UNDEFINED_OP1(); | |
} | |
zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); | |
break; | |
} | |
ZEND_VM_C_LABEL(assign_op_object): | |
/* here we are sure we are dealing with an object */ | |
zobj = Z_OBJ_P(object); | |
if (OP2_TYPE == IS_CONST) { | |
name = Z_STR_P(property); | |
} else { | |
name = zval_try_get_tmp_string(property, &tmp_name); | |
if (UNEXPECTED(!name)) { | |
UNDEF_RESULT(); | |
break; | |
} | |
} | |
cache_slot = (OP2_TYPE == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL; | |
if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { | |
if (UNEXPECTED(Z_ISERROR_P(zptr))) { | |
if (UNEXPECTED(RETURN_VALUE_USED(opline))) { | |
ZVAL_NULL(EX_VAR(opline->result.var)); | |
} | |
} else { | |
zval *orig_zptr = zptr; | |
zend_reference *ref; | |
do { | |
if (UNEXPECTED(Z_ISREF_P(zptr))) { | |
ref = Z_REF_P(zptr); | |
zptr = Z_REFVAL_P(zptr); | |
if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { | |
zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); | |
break; | |
} | |
} | |
if (OP2_TYPE == IS_CONST) { | |
prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); | |
} else { | |
prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), orig_zptr); | |
} | |
if (UNEXPECTED(prop_info)) { | |
/* special case for typed properties */ | |
zend_binary_assign_op_typed_prop(prop_info, zptr, value OPLINE_CC EXECUTE_DATA_CC); | |
} else { | |
zend_binary_op(zptr, zptr, value OPLINE_CC); | |
} | |
} while (0); | |
if (UNEXPECTED(RETURN_VALUE_USED(opline))) { | |
ZVAL_COPY(EX_VAR(opline->result.var), zptr); | |
} | |
} | |
} else { | |
zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC); | |
} | |
if (OP2_TYPE != IS_CONST) { | |
zend_tmp_string_release(tmp_name); | |
} | |
} while (0); | |
FREE_OP_DATA(); | |
FREE_OP2(); | |
FREE_OP1(); | |
/* assign_obj has two opcodes! */ | |
ZEND_VM_NEXT_OPCODE_EX(1, 2); | |
} | |
/* No specialization for op_types (CONST|TMP|VAR|CV, UNUSED|CONST|TMPVAR) */ | |
ZEND_VM_HANDLER(29, ZEND_ASSIGN_STATIC_PROP_OP, ANY, ANY, OP) | |
{ | |
/* This helper actually never will receive IS_VAR as second op, and has the same handling for VAR and TMP in the first op, but for interoperability with the other binary_assign_op helpers, it is necessary to "include" it */ | |
USE_OPLINE | |
zval *prop, *value; | |
zend_property_info *prop_info; | |
zend_reference *ref; | |
SAVE_OPLINE(); | |
if (UNEXPECTED(zend_fetch_static_property_address(&prop, &prop_info, (opline+1)->extended_value, BP_VAR_RW, 0 OPLINE_CC EXECUTE_DATA_CC) != SUCCESS)) { | |
UNDEF_RESULT(); | |
FREE_OP_DATA(); | |
HANDLE_EXCEPTION(); | |
} | |
value = GET_OP_DATA_ZVAL_PTR(BP_VAR_R); | |
do { | |
if (UNEXPECTED(Z_ISREF_P(prop))) { | |
ref = Z_REF_P(prop); | |
prop = Z_REFVAL_P(prop); | |
if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { | |
zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); | |
break; | |
} | |
} | |
if (UNEXPECTED(ZEND_TYPE_IS_SET(prop_info->type))) { | |
/* special case for typed properties */ | |
zend_binary_assign_op_typed_prop(prop_info, prop, value OPLINE_CC EXECUTE_DATA_CC); | |
} else { | |
zend_binary_op(prop, prop, value OPLINE_CC); | |
} | |
} while (0); | |
if (UNEXPECTED(RETURN_VALUE_USED(opline))) { | |
ZVAL_COPY(EX_VAR(opline->result.var), prop); | |
} | |
FREE_OP_DATA(); | |
/* assign_static_prop has two opcodes! */ | |
ZEND_VM_NEXT_OPCODE_EX(1, 2); | |
} | |
ZEND_VM_HANDLER(27, ZEND_ASSIGN_DIM_OP, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV, OP) | |
{ | |
USE_OPLINE | |
zval *var_ptr; | |
zval *value, *container, *dim; | |
HashTable *ht; | |
SAVE_OPLINE(); | |
container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW); | |
if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { | |
ZEND_VM_C_LABEL(assign_dim_op_array): | |
SEPARATE_ARRAY(container); | |
ht = Z_ARRVAL_P(container); | |
ZEND_VM_C_LABEL(assign_dim_op_new_array): | |
dim = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); | |
if (OP2_TYPE == IS_UNUSED) { | |
var_ptr = zend_hash_next_index_insert(ht, &EG(uninitialized_zval)); | |
if (UNEXPECTED(!var_ptr)) { | |
zend_cannot_add_element(); | |
ZEND_VM_C_GOTO(assign_dim_op_ret_null); | |
} | |
} else { | |
if (OP2_TYPE == IS_CONST) { | |
var_ptr = zend_fetch_dimension_address_inner_RW_CONST(ht, dim EXECUTE_DATA_CC); | |
} else { | |
var_ptr = zend_fetch_dimension_address_inner_RW(ht, dim EXECUTE_DATA_CC); | |
} | |
if (UNEXPECTED(!var_ptr)) { | |
ZEND_VM_C_GOTO(assign_dim_op_ret_null); | |
} | |
} | |
value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1); | |
do { | |
if (OP2_TYPE != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) { | |
zend_reference *ref = Z_REF_P(var_ptr); | |
var_ptr = Z_REFVAL_P(var_ptr); | |
if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { | |
zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); | |
break; | |
} | |
} | |
zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); | |
} while (0); | |
if (UNEXPECTED(RETURN_VALUE_USED(opline))) { | |
ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); | |
} | |
FREE_OP((opline+1)->op1_type, (opline+1)->op1.var); | |
} else { | |
if (EXPECTED(Z_ISREF_P(container))) { | |
container = Z_REFVAL_P(container); | |
if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { | |
ZEND_VM_C_GOTO(assign_dim_op_array); | |
} | |
} | |
if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { | |
zend_object *obj = Z_OBJ_P(container); | |
dim = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); | |
if (OP2_TYPE == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { | |
dim++; | |
} | |
zend_binary_assign_op_obj_dim(obj, dim OPLINE_CC EXECUTE_DATA_CC); | |
} else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) { | |
uint8_t old_type; | |
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) { | |
ZVAL_UNDEFINED_OP1(); | |
} | |
ht = zend_new_array(8); | |
old_type = Z_TYPE_P(container); | |
ZVAL_ARR(container, ht); | |
if (UNEXPECTED(old_type == IS_FALSE)) { | |
GC_ADDREF(ht); | |
zend_false_to_array_deprecated(); | |
if (UNEXPECTED(GC_DELREF(ht) == 0)) { | |
zend_array_destroy(ht); | |
ZEND_VM_C_GOTO(assign_dim_op_ret_null); | |
} | |
} | |
ZEND_VM_C_GOTO(assign_dim_op_new_array); | |
} else { | |
dim = GET_OP2_ZVAL_PTR(BP_VAR_R); | |
zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); | |
ZEND_VM_C_LABEL(assign_dim_op_ret_null): | |
FREE_OP_DATA(); | |
if (UNEXPECTED(RETURN_VALUE_USED(opline))) { | |
ZVAL_NULL(EX_VAR(opline->result.var)); | |
} | |
} | |
} | |
FREE_OP2(); | |
FREE_OP1(); | |
ZEND_VM_NEXT_OPCODE_EX(1, 2); | |
} | |
ZEND_VM_HANDLER(26, ZEND_ASSIGN_OP, VAR|CV, CONST|TMPVAR|CV, OP) | |
{ | |
USE_OPLINE | |
zval *var_ptr; | |
zval *value; | |
SAVE_OPLINE(); | |
value = GET_OP2_ZVAL_PTR(BP_VAR_R); | |
var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW); | |
do { | |
if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { | |
zend_reference *ref = Z_REF_P(var_ptr); | |
var_ptr = Z_REFVAL_P(var_ptr); | |
if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { | |
zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC); | |
break; | |
} | |
} | |
zend_binary_op(var_ptr, var_ptr, value OPLINE_CC); | |
} while (0); | |
if (UNEXPECTED(RETURN_VALUE_USED(opline))) { | |
ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); | |
} | |
FREE_OP2(); | |
FREE_OP1(); | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_HANDLER(132, ZEND_PRE_INC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT) | |
{ | |
USE_OPLINE | |
zval *object; | |
zval *property; | |
zval *zptr; | |
void **cache_slot; | |
zend_property_info *prop_info; | |
zend_object *zobj; | |
zend_string *name, *tmp_name; | |
SAVE_OPLINE(); | |
object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW); | |
property = GET_OP2_ZVAL_PTR(BP_VAR_R); | |
do { | |
if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { | |
if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { | |
object = Z_REFVAL_P(object); | |
ZEND_VM_C_GOTO(pre_incdec_object); | |
} | |
if (OP1_TYPE == IS_CV | |
&& UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { | |
ZVAL_UNDEFINED_OP1(); | |
} | |
zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); | |
break; | |
} | |
ZEND_VM_C_LABEL(pre_incdec_object): | |
/* here we are sure we are dealing with an object */ | |
zobj = Z_OBJ_P(object); | |
if (OP2_TYPE == IS_CONST) { | |
name = Z_STR_P(property); | |
} else { | |
name = zval_try_get_tmp_string(property, &tmp_name); | |
if (UNEXPECTED(!name)) { | |
UNDEF_RESULT(); | |
break; | |
} | |
} | |
cache_slot = (OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; | |
if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { | |
if (UNEXPECTED(Z_ISERROR_P(zptr))) { | |
if (UNEXPECTED(RETURN_VALUE_USED(opline))) { | |
ZVAL_NULL(EX_VAR(opline->result.var)); | |
} | |
} else { | |
if (OP2_TYPE == IS_CONST) { | |
prop_info = (zend_property_info *) CACHED_PTR_EX(cache_slot + 2); | |
} else { | |
prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), zptr); | |
} | |
zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); | |
} | |
} else { | |
zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); | |
} | |
if (OP2_TYPE != IS_CONST) { | |
zend_tmp_string_release(tmp_name); | |
} | |
} while (0); | |
FREE_OP2(); | |
FREE_OP1(); | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_HANDLER(133, ZEND_PRE_DEC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT) | |
{ | |
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_PRE_INC_OBJ); | |
} | |
ZEND_VM_HANDLER(134, ZEND_POST_INC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT) | |
{ | |
USE_OPLINE | |
zval *object; | |
zval *property; | |
zval *zptr; | |
void **cache_slot; | |
zend_property_info *prop_info; | |
zend_object *zobj; | |
zend_string *name, *tmp_name; | |
SAVE_OPLINE(); | |
object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW); | |
property = GET_OP2_ZVAL_PTR(BP_VAR_R); | |
do { | |
if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { | |
if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { | |
object = Z_REFVAL_P(object); | |
ZEND_VM_C_GOTO(post_incdec_object); | |
} | |
if (OP1_TYPE == IS_CV | |
&& UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { | |
ZVAL_UNDEFINED_OP1(); | |
} | |
zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC); | |
break; | |
} | |
ZEND_VM_C_LABEL(post_incdec_object): | |
/* here we are sure we are dealing with an object */ | |
zobj = Z_OBJ_P(object); | |
if (OP2_TYPE == IS_CONST) { | |
name = Z_STR_P(property); | |
} else { | |
name = zval_try_get_tmp_string(property, &tmp_name); | |
if (UNEXPECTED(!name)) { | |
ZVAL_UNDEF(EX_VAR(opline->result.var)); | |
break; | |
} | |
} | |
cache_slot = (OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL; | |
if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) { | |
if (UNEXPECTED(Z_ISERROR_P(zptr))) { | |
ZVAL_NULL(EX_VAR(opline->result.var)); | |
} else { | |
if (OP2_TYPE == IS_CONST) { | |
prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2); | |
} else { | |
prop_info = zend_object_fetch_property_type_info(Z_OBJ_P(object), zptr); | |
} | |
zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC); | |
} | |
} else { | |
zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC); | |
} | |
if (OP2_TYPE != IS_CONST) { | |
zend_tmp_string_release(tmp_name); | |
} | |
} while (0); | |
FREE_OP2(); | |
FREE_OP1(); | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_HANDLER(135, ZEND_POST_DEC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT) | |
{ | |
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_POST_INC_OBJ); | |
} | |
/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ | |
ZEND_VM_HANDLER(38, ZEND_PRE_INC_STATIC_PROP, ANY, ANY, CACHE_SLOT) | |
{ | |
USE_OPLINE | |
zval *prop; | |
zend_property_info *prop_info; | |
SAVE_OPLINE(); | |
if (zend_fetch_static_property_address(&prop, &prop_info, opline->extended_value, BP_VAR_RW, 0 OPLINE_CC EXECUTE_DATA_CC) != SUCCESS) { | |
UNDEF_RESULT(); | |
HANDLE_EXCEPTION(); | |
} | |
zend_pre_incdec_property_zval(prop, | |
ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC); | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ | |
ZEND_VM_HANDLER(39, ZEND_PRE_DEC_STATIC_PROP, ANY, ANY, CACHE_SLOT) | |
{ | |
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_PRE_INC_STATIC_PROP); | |
} | |
/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ | |
ZEND_VM_HANDLER(40, ZEND_POST_INC_STATIC_PROP, ANY, ANY, CACHE_SLOT) | |
{ | |
USE_OPLINE | |
zval *prop; | |
zend_property_info *prop_info; | |
SAVE_OPLINE(); | |
if (zend_fetch_static_property_address(&prop, &prop_info, opline->extended_value, BP_VAR_RW, 0 OPLINE_CC EXECUTE_DATA_CC) != SUCCESS) { | |
UNDEF_RESULT(); | |
HANDLE_EXCEPTION(); | |
} | |
zend_post_incdec_property_zval(prop, | |
ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC); | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ | |
ZEND_VM_HANDLER(41, ZEND_POST_DEC_STATIC_PROP, ANY, ANY, CACHE_SLOT) | |
{ | |
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_POST_INC_STATIC_PROP); | |
} | |
ZEND_VM_HELPER(zend_pre_inc_helper, VAR|CV, ANY) | |
{ | |
USE_OPLINE | |
zval *var_ptr; | |
var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW); | |
SAVE_OPLINE(); | |
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { | |
ZVAL_UNDEFINED_OP1(); | |
ZVAL_NULL(var_ptr); | |
} | |
do { | |
if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { | |
zend_reference *ref = Z_REF_P(var_ptr); | |
var_ptr = Z_REFVAL_P(var_ptr); | |
if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { | |
zend_incdec_typed_ref(ref, NULL OPLINE_CC EXECUTE_DATA_CC); | |
break; | |
} | |
} | |
increment_function(var_ptr); | |
} while (0); | |
if (UNEXPECTED(RETURN_VALUE_USED(opline))) { | |
ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); | |
} | |
FREE_OP1(); | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_HOT_HANDLER(34, ZEND_PRE_INC, VAR|CV, ANY, SPEC(RETVAL)) | |
{ | |
USE_OPLINE | |
zval *var_ptr; | |
var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW); | |
if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { | |
fast_long_increment_function(var_ptr); | |
if (UNEXPECTED(RETURN_VALUE_USED(opline))) { | |
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); | |
} | |
ZEND_VM_NEXT_OPCODE(); | |
} | |
ZEND_VM_DISPATCH_TO_HELPER(zend_pre_inc_helper); | |
} | |
ZEND_VM_HELPER(zend_pre_dec_helper, VAR|CV, ANY) | |
{ | |
USE_OPLINE | |
zval *var_ptr; | |
var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW); | |
SAVE_OPLINE(); | |
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { | |
ZVAL_UNDEFINED_OP1(); | |
ZVAL_NULL(var_ptr); | |
} | |
do { | |
if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { | |
zend_reference *ref = Z_REF_P(var_ptr); | |
var_ptr = Z_REFVAL_P(var_ptr); | |
if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { | |
zend_incdec_typed_ref(ref, NULL OPLINE_CC EXECUTE_DATA_CC); | |
break; | |
} | |
} | |
decrement_function(var_ptr); | |
} while (0); | |
if (UNEXPECTED(RETURN_VALUE_USED(opline))) { | |
ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); | |
} | |
FREE_OP1(); | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_HOT_HANDLER(35, ZEND_PRE_DEC, VAR|CV, ANY, SPEC(RETVAL)) | |
{ | |
USE_OPLINE | |
zval *var_ptr; | |
var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW); | |
if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { | |
fast_long_decrement_function(var_ptr); | |
if (UNEXPECTED(RETURN_VALUE_USED(opline))) { | |
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); | |
} | |
ZEND_VM_NEXT_OPCODE(); | |
} | |
ZEND_VM_DISPATCH_TO_HELPER(zend_pre_dec_helper); | |
} | |
ZEND_VM_HELPER(zend_post_inc_helper, VAR|CV, ANY) | |
{ | |
USE_OPLINE | |
zval *var_ptr; | |
var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW); | |
SAVE_OPLINE(); | |
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { | |
ZVAL_UNDEFINED_OP1(); | |
ZVAL_NULL(var_ptr); | |
} | |
do { | |
if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { | |
zend_reference *ref = Z_REF_P(var_ptr); | |
var_ptr = Z_REFVAL_P(var_ptr); | |
if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { | |
zend_incdec_typed_ref(ref, EX_VAR(opline->result.var) OPLINE_CC EXECUTE_DATA_CC); | |
break; | |
} | |
} | |
ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); | |
increment_function(var_ptr); | |
} while (0); | |
FREE_OP1(); | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_HOT_HANDLER(36, ZEND_POST_INC, VAR|CV, ANY) | |
{ | |
USE_OPLINE | |
zval *var_ptr; | |
var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW); | |
if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { | |
ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr)); | |
fast_long_increment_function(var_ptr); | |
ZEND_VM_NEXT_OPCODE(); | |
} | |
ZEND_VM_DISPATCH_TO_HELPER(zend_post_inc_helper); | |
} | |
ZEND_VM_HELPER(zend_post_dec_helper, VAR|CV, ANY) | |
{ | |
USE_OPLINE | |
zval *var_ptr; | |
var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW); | |
SAVE_OPLINE(); | |
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { | |
ZVAL_UNDEFINED_OP1(); | |
ZVAL_NULL(var_ptr); | |
} | |
do { | |
if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) { | |
zend_reference *ref = Z_REF_P(var_ptr); | |
var_ptr = Z_REFVAL_P(var_ptr); | |
if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) { | |
zend_incdec_typed_ref(ref, EX_VAR(opline->result.var) OPLINE_CC EXECUTE_DATA_CC); | |
break; | |
} | |
} | |
ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); | |
decrement_function(var_ptr); | |
} while (0); | |
FREE_OP1(); | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_HOT_HANDLER(37, ZEND_POST_DEC, VAR|CV, ANY) | |
{ | |
USE_OPLINE | |
zval *var_ptr; | |
var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW); | |
if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { | |
ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr)); | |
fast_long_decrement_function(var_ptr); | |
ZEND_VM_NEXT_OPCODE(); | |
} | |
ZEND_VM_DISPATCH_TO_HELPER(zend_post_dec_helper); | |
} | |
ZEND_VM_HANDLER(136, ZEND_ECHO, CONST|TMPVAR|CV, ANY) | |
{ | |
USE_OPLINE | |
zval *z; | |
SAVE_OPLINE(); | |
z = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); | |
if (Z_TYPE_P(z) == IS_STRING) { | |
zend_string *str = Z_STR_P(z); | |
if (ZSTR_LEN(str) != 0) { | |
zend_write(ZSTR_VAL(str), ZSTR_LEN(str)); | |
} | |
} else { | |
zend_string *str = zval_get_string_func(z); | |
if (ZSTR_LEN(str) != 0) { | |
zend_write(ZSTR_VAL(str), ZSTR_LEN(str)); | |
} else if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(z) == IS_UNDEF)) { | |
ZVAL_UNDEFINED_OP1(); | |
} | |
zend_string_release_ex(str, 0); | |
} | |
FREE_OP1(); | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_HELPER(zend_fetch_var_address_helper, CONST|TMPVAR|CV, UNUSED, int type) | |
{ | |
USE_OPLINE | |
zval *varname; | |
zval *retval; | |
zend_string *name, *tmp_name; | |
HashTable *target_symbol_table; | |
SAVE_OPLINE(); | |
varname = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); | |
if (OP1_TYPE == IS_CONST) { | |
name = Z_STR_P(varname); | |
} else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) { | |
name = Z_STR_P(varname); | |
tmp_name = NULL; | |
} else { | |
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) { | |
ZVAL_UNDEFINED_OP1(); | |
} | |
name = zval_try_get_tmp_string(varname, &tmp_name); | |
if (UNEXPECTED(!name)) { | |
if (!(opline->extended_value & ZEND_FETCH_GLOBAL_LOCK)) { | |
FREE_OP1(); | |
} | |
ZVAL_UNDEF(EX_VAR(opline->result.var)); | |
HANDLE_EXCEPTION(); | |
} | |
} | |
target_symbol_table = zend_get_target_symbol_table(opline->extended_value EXECUTE_DATA_CC); | |
retval = zend_hash_find_ex(target_symbol_table, name, OP1_TYPE == IS_CONST); | |
if (retval == NULL) { | |
if (UNEXPECTED(zend_string_equals(name, ZSTR_KNOWN(ZEND_STR_THIS)))) { | |
ZEND_VM_C_LABEL(fetch_this): | |
zend_fetch_this_var(type OPLINE_CC EXECUTE_DATA_CC); | |
if (OP1_TYPE != IS_CONST) { | |
zend_tmp_string_release(tmp_name); | |
} | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
if (type == BP_VAR_W) { | |
retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval)); | |
} else if (type == BP_VAR_IS || type == BP_VAR_UNSET) { | |
retval = &EG(uninitialized_zval); | |
} else { | |
zend_error(E_WARNING, "Undefined %svariable $%s", | |
(opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), ZSTR_VAL(name)); | |
if (type == BP_VAR_RW && !EG(exception)) { | |
retval = zend_hash_update(target_symbol_table, name, &EG(uninitialized_zval)); | |
} else { | |
retval = &EG(uninitialized_zval); | |
} | |
} | |
/* GLOBAL or $$name variable may be an INDIRECT pointer to CV */ | |
} else if (Z_TYPE_P(retval) == IS_INDIRECT) { | |
retval = Z_INDIRECT_P(retval); | |
if (Z_TYPE_P(retval) == IS_UNDEF) { | |
if (UNEXPECTED(zend_string_equals(name, ZSTR_KNOWN(ZEND_STR_THIS)))) { | |
ZEND_VM_C_GOTO(fetch_this); | |
} | |
if (type == BP_VAR_W) { | |
ZVAL_NULL(retval); | |
} else if (type == BP_VAR_IS || type == BP_VAR_UNSET) { | |
retval = &EG(uninitialized_zval); | |
} else { | |
zend_error(E_WARNING, "Undefined %svariable $%s", | |
(opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), ZSTR_VAL(name)); | |
if (type == BP_VAR_RW && !EG(exception)) { | |
ZVAL_NULL(retval); | |
} else { | |
retval = &EG(uninitialized_zval); | |
} | |
} | |
} | |
} | |
if (!(opline->extended_value & ZEND_FETCH_GLOBAL_LOCK)) { | |
FREE_OP1(); | |
} | |
if (OP1_TYPE != IS_CONST) { | |
zend_tmp_string_release(tmp_name); | |
} | |
ZEND_ASSERT(retval != NULL); | |
if (type == BP_VAR_R || type == BP_VAR_IS) { | |
ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); | |
} else { | |
ZVAL_INDIRECT(EX_VAR(opline->result.var), retval); | |
} | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_HANDLER(80, ZEND_FETCH_R, CONST|TMPVAR|CV, UNUSED, VAR_FETCH) | |
{ | |
ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper, type, BP_VAR_R); | |
} | |
ZEND_VM_HANDLER(83, ZEND_FETCH_W, CONST|TMPVAR|CV, UNUSED, VAR_FETCH) | |
{ | |
ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper, type, BP_VAR_W); | |
} | |
ZEND_VM_HANDLER(86, ZEND_FETCH_RW, CONST|TMPVAR|CV, UNUSED, VAR_FETCH) | |
{ | |
ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper, type, BP_VAR_RW); | |
} | |
ZEND_VM_HANDLER(92, ZEND_FETCH_FUNC_ARG, CONST|TMPVAR|CV, UNUSED, VAR_FETCH) | |
{ | |
int fetch_type = | |
(UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) ? | |
BP_VAR_W : BP_VAR_R; | |
ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper, type, fetch_type); | |
} | |
ZEND_VM_HANDLER(95, ZEND_FETCH_UNSET, CONST|TMPVAR|CV, UNUSED, VAR_FETCH) | |
{ | |
ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper, type, BP_VAR_UNSET); | |
} | |
ZEND_VM_HANDLER(89, ZEND_FETCH_IS, CONST|TMPVAR|CV, UNUSED, VAR_FETCH) | |
{ | |
ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper, type, BP_VAR_IS); | |
} | |
/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ | |
ZEND_VM_HELPER(zend_fetch_static_prop_helper, ANY, ANY, int type) | |
{ | |
USE_OPLINE | |
zval *prop; | |
SAVE_OPLINE(); | |
if (UNEXPECTED(zend_fetch_static_property_address(&prop, NULL, opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS, type, opline->extended_value OPLINE_CC EXECUTE_DATA_CC) != SUCCESS)) { | |
ZEND_ASSERT(EG(exception) || (type == BP_VAR_IS)); | |
prop = &EG(uninitialized_zval); | |
} | |
if (type == BP_VAR_R || type == BP_VAR_IS) { | |
ZVAL_COPY_DEREF(EX_VAR(opline->result.var), prop); | |
} else { | |
ZVAL_INDIRECT(EX_VAR(opline->result.var), prop); | |
} | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ | |
ZEND_VM_HANDLER(173, ZEND_FETCH_STATIC_PROP_R, ANY, CLASS_FETCH, CACHE_SLOT) | |
{ | |
ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper, type, BP_VAR_R); | |
} | |
/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ | |
ZEND_VM_HANDLER(174, ZEND_FETCH_STATIC_PROP_W, ANY, CLASS_FETCH, FETCH_REF|DIM_WRITE|CACHE_SLOT) | |
{ | |
ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper, type, BP_VAR_W); | |
} | |
/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ | |
ZEND_VM_HANDLER(175, ZEND_FETCH_STATIC_PROP_RW, ANY, CLASS_FETCH, CACHE_SLOT) | |
{ | |
ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper, type, BP_VAR_RW); | |
} | |
/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ | |
ZEND_VM_HANDLER(177, ZEND_FETCH_STATIC_PROP_FUNC_ARG, ANY, CLASS_FETCH, FETCH_REF|CACHE_SLOT) | |
{ | |
int fetch_type = | |
(UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) ? | |
BP_VAR_W : BP_VAR_R; | |
ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper, type, fetch_type); | |
} | |
/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ | |
ZEND_VM_HANDLER(178, ZEND_FETCH_STATIC_PROP_UNSET, ANY, CLASS_FETCH, CACHE_SLOT) | |
{ | |
ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper, type, BP_VAR_UNSET); | |
} | |
/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */ | |
ZEND_VM_HANDLER(176, ZEND_FETCH_STATIC_PROP_IS, ANY, CLASS_FETCH, CACHE_SLOT) | |
{ | |
ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper, type, BP_VAR_IS); | |
} | |
ZEND_VM_COLD_CONSTCONST_HANDLER(81, ZEND_FETCH_DIM_R, CONST|TMPVAR|CV, CONST|TMPVAR|CV) | |
{ | |
USE_OPLINE | |
zval *container, *dim, *value; | |
SAVE_OPLINE(); | |
container = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); | |
dim = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); | |
if (OP1_TYPE != IS_CONST) { | |
if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { | |
ZEND_VM_C_LABEL(fetch_dim_r_array): | |
value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, OP2_TYPE, BP_VAR_R EXECUTE_DATA_CC); | |
ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); | |
} else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) { | |
container = Z_REFVAL_P(container); | |
if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) { | |
ZEND_VM_C_GOTO(fetch_dim_r_array); | |
} else { | |
ZEND_VM_C_GOTO(fetch_dim_r_slow); | |
} | |
} else { | |
ZEND_VM_C_LABEL(fetch_dim_r_slow): | |
if (OP2_TYPE == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { | |
dim++; | |
} | |
zend_fetch_dimension_address_read_R_slow(container, dim OPLINE_CC EXECUTE_DATA_CC); | |
} | |
} else { | |
zend_fetch_dimension_address_read_R(container, dim, OP2_TYPE OPLINE_CC EXECUTE_DATA_CC); | |
} | |
FREE_OP2(); | |
FREE_OP1(); | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_HANDLER(84, ZEND_FETCH_DIM_W, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV) | |
{ | |
USE_OPLINE | |
zval *container; | |
SAVE_OPLINE(); | |
container = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); | |
zend_fetch_dimension_address_W(container, GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R), OP2_TYPE OPLINE_CC EXECUTE_DATA_CC); | |
FREE_OP2(); | |
if (OP1_TYPE == IS_VAR) { | |
FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); | |
} | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_HANDLER(87, ZEND_FETCH_DIM_RW, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV) | |
{ | |
USE_OPLINE | |
zval *container; | |
SAVE_OPLINE(); | |
container = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW); | |
zend_fetch_dimension_address_RW(container, GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R), OP2_TYPE OPLINE_CC EXECUTE_DATA_CC); | |
FREE_OP2(); | |
if (OP1_TYPE == IS_VAR) { | |
FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); | |
} | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_COLD_CONSTCONST_HANDLER(90, ZEND_FETCH_DIM_IS, CONST|TMPVAR|CV, CONST|TMPVAR|CV) | |
{ | |
USE_OPLINE | |
zval *container; | |
SAVE_OPLINE(); | |
container = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_IS); | |
zend_fetch_dimension_address_read_IS(container, GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R), OP2_TYPE OPLINE_CC EXECUTE_DATA_CC); | |
FREE_OP2(); | |
FREE_OP1(); | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_COLD_HELPER(zend_use_tmp_in_write_context_helper, ANY, ANY) | |
{ | |
USE_OPLINE | |
SAVE_OPLINE(); | |
zend_throw_error(NULL, "Cannot use temporary expression in write context"); | |
FREE_OP2(); | |
FREE_OP1(); | |
ZVAL_UNDEF(EX_VAR(opline->result.var)); | |
HANDLE_EXCEPTION(); | |
} | |
ZEND_VM_COLD_HELPER(zend_use_undef_in_read_context_helper, ANY, ANY) | |
{ | |
USE_OPLINE | |
SAVE_OPLINE(); | |
zend_throw_error(NULL, "Cannot use [] for reading"); | |
FREE_OP2(); | |
FREE_OP1(); | |
ZVAL_UNDEF(EX_VAR(opline->result.var)); | |
HANDLE_EXCEPTION(); | |
} | |
ZEND_VM_COLD_CONSTCONST_HANDLER(93, ZEND_FETCH_DIM_FUNC_ARG, CONST|TMP|VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV) | |
{ | |
#if !ZEND_VM_SPEC | |
USE_OPLINE | |
#endif | |
if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { | |
if ((OP1_TYPE & (IS_CONST|IS_TMP_VAR))) { | |
ZEND_VM_DISPATCH_TO_HELPER(zend_use_tmp_in_write_context_helper); | |
} | |
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_FETCH_DIM_W); | |
} else { | |
if (OP2_TYPE == IS_UNUSED) { | |
ZEND_VM_DISPATCH_TO_HELPER(zend_use_undef_in_read_context_helper); | |
} | |
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_FETCH_DIM_R); | |
} | |
} | |
ZEND_VM_HANDLER(96, ZEND_FETCH_DIM_UNSET, VAR|CV, CONST|TMPVAR|CV) | |
{ | |
USE_OPLINE | |
zval *container; | |
SAVE_OPLINE(); | |
container = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_UNSET); | |
zend_fetch_dimension_address_UNSET(container, GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R), OP2_TYPE OPLINE_CC EXECUTE_DATA_CC); | |
FREE_OP2(); | |
if (OP1_TYPE == IS_VAR) { | |
FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); | |
} | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_HOT_OBJ_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT) | |
{ | |
USE_OPLINE | |
zval *container; | |
void **cache_slot = NULL; | |
SAVE_OPLINE(); | |
container = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R); | |
if (OP1_TYPE == IS_CONST || | |
(OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { | |
do { | |
if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { | |
container = Z_REFVAL_P(container); | |
if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { | |
break; | |
} | |
} | |
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) { | |
ZVAL_UNDEFINED_OP1(); | |
} | |
zend_wrong_property_read(container, GET_OP2_ZVAL_PTR(BP_VAR_R)); | |
ZVAL_NULL(EX_VAR(opline->result.var)); | |
ZEND_VM_C_GOTO(fetch_obj_r_finish); | |
} while (0); | |
} | |
/* here we are sure we are dealing with an object */ | |
do { | |
zend_object *zobj = Z_OBJ_P(container); | |
zend_string *name, *tmp_name; | |
zval *retval; | |
if (OP2_TYPE == IS_CONST) { | |
cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */); | |
if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { | |
uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); | |
if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { | |
retval = OBJ_PROP(zobj, prop_offset); | |
if (EXPECTED(Z_TYPE_INFO_P(retval) != IS_UNDEF)) { | |
if (!ZEND_VM_SPEC || (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) != 0) { | |
ZEND_VM_C_GOTO(fetch_obj_r_copy); | |
} else { | |
ZEND_VM_C_LABEL(fetch_obj_r_fast_copy): | |
ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); | |
ZEND_VM_NEXT_OPCODE(); | |
} | |
} | |
} else if (EXPECTED(zobj->properties != NULL)) { | |
name = Z_STR_P(GET_OP2_ZVAL_PTR(BP_VAR_R)); | |
if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { | |
uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); | |
if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { | |
Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); | |
if (EXPECTED(p->key == name) || | |
(EXPECTED(p->h == ZSTR_H(name)) && | |
EXPECTED(p->key != NULL) && | |
EXPECTED(zend_string_equal_content(p->key, name)))) { | |
retval = &p->val; | |
if (!ZEND_VM_SPEC || (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) != 0) { | |
ZEND_VM_C_GOTO(fetch_obj_r_copy); | |
} else { | |
ZEND_VM_C_GOTO(fetch_obj_r_fast_copy); | |
} | |
} | |
} | |
CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); | |
} | |
retval = zend_hash_find_known_hash(zobj->properties, name); | |
if (EXPECTED(retval)) { | |
uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; | |
CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); | |
if (!ZEND_VM_SPEC || (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) != 0) { | |
ZEND_VM_C_GOTO(fetch_obj_r_copy); | |
} else { | |
ZEND_VM_C_GOTO(fetch_obj_r_fast_copy); | |
} | |
} | |
} | |
} | |
name = Z_STR_P(GET_OP2_ZVAL_PTR(BP_VAR_R)); | |
} else { | |
name = zval_try_get_tmp_string(GET_OP2_ZVAL_PTR(BP_VAR_R), &tmp_name); | |
if (UNEXPECTED(!name)) { | |
ZVAL_UNDEF(EX_VAR(opline->result.var)); | |
break; | |
} | |
} | |
#if ZEND_DEBUG | |
/* For non-standard object handlers, verify a declared property type in debug builds. | |
* Fetch prop_info before calling read_property(), as it may deallocate the object. */ | |
zend_property_info *prop_info = NULL; | |
if (zobj->handlers->read_property != zend_std_read_property) { | |
prop_info = zend_get_property_info(zobj->ce, name, /* silent */ true); | |
} | |
#endif | |
retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var)); | |
#if ZEND_DEBUG | |
if (!EG(exception) && prop_info && prop_info != ZEND_WRONG_PROPERTY_INFO | |
&& ZEND_TYPE_IS_SET(prop_info->type)) { | |
ZVAL_OPT_DEREF(retval); | |
zend_verify_property_type(prop_info, retval, /* strict */ true); | |
} | |
#endif | |
if (OP2_TYPE != IS_CONST) { | |
zend_tmp_string_release(tmp_name); | |
} | |
if (retval != EX_VAR(opline->result.var)) { | |
ZEND_VM_C_LABEL(fetch_obj_r_copy): | |
ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); | |
} else if (UNEXPECTED(Z_ISREF_P(retval))) { | |
zend_unwrap_reference(retval); | |
} | |
} while (0); | |
ZEND_VM_C_LABEL(fetch_obj_r_finish): | |
FREE_OP2(); | |
FREE_OP1(); | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, FETCH_REF|DIM_WRITE|CACHE_SLOT) | |
{ | |
USE_OPLINE | |
zval *property, *container, *result; | |
SAVE_OPLINE(); | |
container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); | |
property = GET_OP2_ZVAL_PTR(BP_VAR_R); | |
result = EX_VAR(opline->result.var); | |
zend_fetch_property_address( | |
result, container, OP1_TYPE, property, OP2_TYPE, | |
((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL), | |
BP_VAR_W, opline->extended_value, 1 OPLINE_CC EXECUTE_DATA_CC); | |
FREE_OP2(); | |
if (OP1_TYPE == IS_VAR) { | |
FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); | |
} | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT) | |
{ | |
USE_OPLINE | |
zval *property, *container, *result; | |
SAVE_OPLINE(); | |
container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW); | |
property = GET_OP2_ZVAL_PTR(BP_VAR_R); | |
result = EX_VAR(opline->result.var); | |
zend_fetch_property_address(result, container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, 1 OPLINE_CC EXECUTE_DATA_CC); | |
FREE_OP2(); | |
if (OP1_TYPE == IS_VAR) { | |
FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); | |
} | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_COLD_CONST_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT) | |
{ | |
USE_OPLINE | |
zval *container; | |
void **cache_slot = NULL; | |
SAVE_OPLINE(); | |
container = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_IS); | |
if (OP1_TYPE == IS_CONST || | |
(OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) { | |
do { | |
if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) { | |
container = Z_REFVAL_P(container); | |
if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { | |
break; | |
} | |
} | |
if (OP2_TYPE == IS_CV && Z_TYPE_P(EX_VAR(opline->op2.var)) == IS_UNDEF) { | |
ZVAL_UNDEFINED_OP2(); | |
} | |
ZVAL_NULL(EX_VAR(opline->result.var)); | |
ZEND_VM_C_GOTO(fetch_obj_is_finish); | |
} while (0); | |
} | |
/* here we are sure we are dealing with an object */ | |
do { | |
zend_object *zobj = Z_OBJ_P(container); | |
zend_string *name, *tmp_name; | |
zval *retval; | |
if (OP2_TYPE == IS_CONST) { | |
cache_slot = CACHE_ADDR(opline->extended_value); | |
if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) { | |
uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); | |
if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { | |
retval = OBJ_PROP(zobj, prop_offset); | |
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) { | |
if (!ZEND_VM_SPEC || (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) != 0) { | |
ZEND_VM_C_GOTO(fetch_obj_is_copy); | |
} else { | |
ZEND_VM_C_LABEL(fetch_obj_is_fast_copy): | |
ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); | |
ZEND_VM_NEXT_OPCODE(); | |
} | |
} | |
} else if (EXPECTED(zobj->properties != NULL)) { | |
name = Z_STR_P(GET_OP2_ZVAL_PTR(BP_VAR_R)); | |
if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) { | |
uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset); | |
if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) { | |
Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx); | |
if (EXPECTED(p->key == name) || | |
(EXPECTED(p->h == ZSTR_H(name)) && | |
EXPECTED(p->key != NULL) && | |
EXPECTED(zend_string_equal_content(p->key, name)))) { | |
retval = &p->val; | |
if (!ZEND_VM_SPEC || (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) != 0) { | |
ZEND_VM_C_GOTO(fetch_obj_is_copy); | |
} else { | |
ZEND_VM_C_GOTO(fetch_obj_is_fast_copy); | |
} | |
} | |
} | |
CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET); | |
} | |
retval = zend_hash_find_known_hash(zobj->properties, name); | |
if (EXPECTED(retval)) { | |
uintptr_t idx = (char*)retval - (char*)zobj->properties->arData; | |
CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx)); | |
if (!ZEND_VM_SPEC || (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) != 0) { | |
ZEND_VM_C_GOTO(fetch_obj_is_copy); | |
} else { | |
ZEND_VM_C_GOTO(fetch_obj_is_fast_copy); | |
} | |
} | |
} | |
} | |
name = Z_STR_P(GET_OP2_ZVAL_PTR(BP_VAR_R)); | |
} else { | |
name = zval_try_get_tmp_string(GET_OP2_ZVAL_PTR(BP_VAR_R), &tmp_name); | |
if (UNEXPECTED(!name)) { | |
ZVAL_UNDEF(EX_VAR(opline->result.var)); | |
break; | |
} | |
} | |
retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var)); | |
if (OP2_TYPE != IS_CONST) { | |
zend_tmp_string_release(tmp_name); | |
} | |
if (retval != EX_VAR(opline->result.var)) { | |
ZEND_VM_C_LABEL(fetch_obj_is_copy): | |
ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval); | |
} else if (UNEXPECTED(Z_ISREF_P(retval))) { | |
zend_unwrap_reference(retval); | |
} | |
} while (0); | |
ZEND_VM_C_LABEL(fetch_obj_is_finish): | |
FREE_OP2(); | |
FREE_OP1(); | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_COLD_CONST_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, CONST|TMP|VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, FETCH_REF|CACHE_SLOT) | |
{ | |
#if !ZEND_VM_SPEC | |
USE_OPLINE | |
#endif | |
if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) { | |
/* Behave like FETCH_OBJ_W */ | |
if ((OP1_TYPE & (IS_CONST|IS_TMP_VAR))) { | |
ZEND_VM_DISPATCH_TO_HELPER(zend_use_tmp_in_write_context_helper); | |
} | |
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_FETCH_OBJ_W); | |
} else { | |
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_FETCH_OBJ_R); | |
} | |
} | |
ZEND_VM_HANDLER(97, ZEND_FETCH_OBJ_UNSET, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT) | |
{ | |
USE_OPLINE | |
zval *container, *property, *result; | |
SAVE_OPLINE(); | |
container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_UNSET); | |
property = GET_OP2_ZVAL_PTR(BP_VAR_R); | |
result = EX_VAR(opline->result.var); | |
zend_fetch_property_address(result, container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, 1 OPLINE_CC EXECUTE_DATA_CC); | |
FREE_OP2(); | |
if (OP1_TYPE == IS_VAR) { | |
FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var); | |
} | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_HANDLER(98, ZEND_FETCH_LIST_R, CONST|TMPVARCV, CONST|TMPVAR|CV) | |
{ | |
USE_OPLINE | |
zval *container; | |
SAVE_OPLINE(); | |
container = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); | |
zend_fetch_dimension_address_LIST_r(container, GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R), OP2_TYPE OPLINE_CC EXECUTE_DATA_CC); | |
FREE_OP2(); | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_HANDLER(155, ZEND_FETCH_LIST_W, VAR, CONST|TMPVAR|CV) | |
{ | |
USE_OPLINE | |
zval *container, *dim; | |
SAVE_OPLINE(); | |
container = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); | |
dim = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); | |
if (OP1_TYPE == IS_VAR | |
&& Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT | |
&& UNEXPECTED(!Z_ISREF_P(container)) | |
) { | |
zend_error(E_NOTICE, "Attempting to set reference to non referenceable value"); | |
zend_fetch_dimension_address_LIST_r(container, dim, OP2_TYPE OPLINE_CC EXECUTE_DATA_CC); | |
} else { | |
zend_fetch_dimension_address_W(container, dim, OP2_TYPE OPLINE_CC EXECUTE_DATA_CC); | |
} | |
FREE_OP2(); | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_HANDLER(24, ZEND_ASSIGN_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT, SPEC(OP_DATA=CONST|TMP|VAR|CV)) | |
{ | |
USE_OPLINE | |
zval *object, *value, tmp; | |
zend_object *zobj; | |
zend_string *name, *tmp_name; | |
SAVE_OPLINE(); | |
object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); | |
value = GET_OP_DATA_ZVAL_PTR(BP_VAR_R); | |
if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { | |
if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) { | |
object = Z_REFVAL_P(object); | |
ZEND_VM_C_GOTO(assign_object); | |
} | |
zend_throw_non_object_error(object, GET_OP2_ZVAL_PTR(BP_VAR_R) OPLINE_CC EXECUTE_DATA_CC); | |
value = &EG(uninitialized_zval); | |
ZEND_VM_C_GOTO(free_and_exit_assign_obj); | |
} | |
ZEND_VM_C_LABEL(assign_object): | |
zobj = Z_OBJ_P(object); | |
if (OP2_TYPE == IS_CONST) { | |
if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) { | |
void **cache_slot = CACHE_ADDR(opline->extended_value); | |
uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1); | |
zval *property_val; | |
if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) { | |
property_val = OBJ_PROP(zobj, prop_offset); | |
if (Z_TYPE_P(property_val) != IS_UNDEF) { | |
zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2); | |
if (UNEXPECTED(prop_info != NULL)) { | |
value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC); | |
ZEND_VM_C_GOTO(free_and_exit_assign_obj); | |
} else { | |
ZEND_VM_C_LABEL(fast_assign_obj): | |
value = zend_assign_to_variable(property_val, value, OP_DATA_TYPE, EX_USES_STRICT_TYPES()); | |
if (UNEXPECTED(RETURN_VALUE_USED(opline))) { | |
ZVAL_COPY(EX_VAR(opline->result.var), value); | |
} | |
ZEND_VM_C_GOTO(exit_assign_obj); | |
} | |
} | |
} else { | |
name = Z_STR_P(GET_OP2_ZVAL_PTR(BP_VAR_R)); | |
if (EXPECTED(zobj->properties != NULL)) { | |
if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { | |
if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { | |
GC_DELREF(zobj->properties); | |
} | |
zobj->properties = zend_array_dup(zobj->properties); | |
} | |
property_val = zend_hash_find_known_hash(zobj->properties, name); | |
if (property_val) { | |
ZEND_VM_C_GOTO(fast_assign_obj); | |
} | |
} | |
if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) { | |
if (EXPECTED(zobj->properties == NULL)) { | |
rebuild_object_properties(zobj); | |
} | |
if (OP_DATA_TYPE == IS_CONST) { | |
if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) { | |
Z_ADDREF_P(value); | |
} | |
} else if (OP_DATA_TYPE != IS_TMP_VAR) { | |
if (Z_ISREF_P(value)) { | |
if (OP_DATA_TYPE == IS_VAR) { | |
zend_reference *ref = Z_REF_P(value); | |
if (GC_DELREF(ref) == 0) { | |
ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); | |
efree_size(ref, sizeof(zend_reference)); | |
value = &tmp; | |
} else { | |
value = Z_REFVAL_P(value); | |
Z_TRY_ADDREF_P(value); | |
} | |
} else { | |
value = Z_REFVAL_P(value); | |
Z_TRY_ADDREF_P(value); | |
} | |
} else if (OP_DATA_TYPE == IS_CV) { | |
Z_TRY_ADDREF_P(value); | |
} | |
} | |
zend_hash_add_new(zobj->properties, name, value); | |
if (UNEXPECTED(RETURN_VALUE_USED(opline))) { | |
ZVAL_COPY(EX_VAR(opline->result.var), value); | |
} | |
ZEND_VM_C_GOTO(exit_assign_obj); | |
} | |
} | |
} | |
name = Z_STR_P(GET_OP2_ZVAL_PTR(BP_VAR_R)); | |
} else { | |
name = zval_try_get_tmp_string(GET_OP2_ZVAL_PTR(BP_VAR_R), &tmp_name); | |
if (UNEXPECTED(!name)) { | |
FREE_OP_DATA(); | |
UNDEF_RESULT(); | |
ZEND_VM_C_GOTO(exit_assign_obj); | |
} | |
} | |
if (OP_DATA_TYPE == IS_CV || OP_DATA_TYPE == IS_VAR) { | |
ZVAL_DEREF(value); | |
} | |
value = zobj->handlers->write_property(zobj, name, value, (OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL); | |
if (OP2_TYPE != IS_CONST) { | |
zend_tmp_string_release(tmp_name); | |
} | |
ZEND_VM_C_LABEL(free_and_exit_assign_obj): | |
if (UNEXPECTED(RETURN_VALUE_USED(opline))) { | |
ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value); | |
} | |
FREE_OP_DATA(); | |
ZEND_VM_C_LABEL(exit_assign_obj): | |
FREE_OP2(); | |
FREE_OP1(); | |
/* assign_obj has two opcodes! */ | |
ZEND_VM_NEXT_OPCODE_EX(1, 2); | |
} | |
/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ | |
ZEND_VM_HANDLER(25, ZEND_ASSIGN_STATIC_PROP, ANY, ANY, CACHE_SLOT, SPEC(OP_DATA=CONST|TMP|VAR|CV)) | |
{ | |
USE_OPLINE | |
zval *prop, *value; | |
zend_property_info *prop_info; | |
SAVE_OPLINE(); | |
if (zend_fetch_static_property_address(&prop, &prop_info, opline->extended_value, BP_VAR_W, 0 OPLINE_CC EXECUTE_DATA_CC) != SUCCESS) { | |
FREE_OP_DATA(); | |
UNDEF_RESULT(); | |
HANDLE_EXCEPTION(); | |
} | |
value = GET_OP_DATA_ZVAL_PTR(BP_VAR_R); | |
if (UNEXPECTED(ZEND_TYPE_IS_SET(prop_info->type))) { | |
value = zend_assign_to_typed_prop(prop_info, prop, value EXECUTE_DATA_CC); | |
FREE_OP_DATA(); | |
} else { | |
value = zend_assign_to_variable(prop, value, OP_DATA_TYPE, EX_USES_STRICT_TYPES()); | |
} | |
if (UNEXPECTED(RETURN_VALUE_USED(opline))) { | |
ZVAL_COPY(EX_VAR(opline->result.var), value); | |
} | |
/* assign_static_prop has two opcodes! */ | |
ZEND_VM_NEXT_OPCODE_EX(1, 2); | |
} | |
ZEND_VM_HANDLER(23, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV, SPEC(OP_DATA=CONST|TMP|VAR|CV)) | |
{ | |
USE_OPLINE | |
zval *object_ptr, *orig_object_ptr; | |
zval *value; | |
zval *variable_ptr; | |
zval *dim; | |
SAVE_OPLINE(); | |
orig_object_ptr = object_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); | |
if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { | |
ZEND_VM_C_LABEL(try_assign_dim_array): | |
SEPARATE_ARRAY(object_ptr); | |
if (OP2_TYPE == IS_UNUSED) { | |
value = GET_OP_DATA_ZVAL_PTR_UNDEF(BP_VAR_R); | |
if (OP_DATA_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) { | |
HashTable *ht = Z_ARRVAL_P(object_ptr); | |
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { | |
GC_ADDREF(ht); | |
} | |
value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); | |
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) { | |
zend_array_destroy(ht); | |
ZEND_VM_C_GOTO(assign_dim_error); | |
} | |
} | |
if (OP_DATA_TYPE == IS_CV || OP_DATA_TYPE == IS_VAR) { | |
ZVAL_DEREF(value); | |
} | |
value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value); | |
if (UNEXPECTED(value == NULL)) { | |
zend_cannot_add_element(); | |
ZEND_VM_C_GOTO(assign_dim_error); | |
} else if (OP_DATA_TYPE == IS_CV) { | |
if (Z_REFCOUNTED_P(value)) { | |
Z_ADDREF_P(value); | |
} | |
} else if (OP_DATA_TYPE == IS_VAR) { | |
zval *free_op_data = EX_VAR((opline+1)->op1.var); | |
if (Z_ISREF_P(free_op_data)) { | |
if (Z_REFCOUNTED_P(value)) { | |
Z_ADDREF_P(value); | |
} | |
zval_ptr_dtor_nogc(free_op_data); | |
} | |
} else if (OP_DATA_TYPE == IS_CONST) { | |
if (UNEXPECTED(Z_REFCOUNTED_P(value))) { | |
Z_ADDREF_P(value); | |
} | |
} | |
} else { | |
dim = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); | |
if (OP2_TYPE == IS_CONST) { | |
variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); | |
} else { | |
variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC); | |
} | |
if (UNEXPECTED(variable_ptr == NULL)) { | |
ZEND_VM_C_GOTO(assign_dim_error); | |
} | |
value = GET_OP_DATA_ZVAL_PTR(BP_VAR_R); | |
value = zend_assign_to_variable(variable_ptr, value, OP_DATA_TYPE, EX_USES_STRICT_TYPES()); | |
} | |
if (UNEXPECTED(RETURN_VALUE_USED(opline))) { | |
ZVAL_COPY(EX_VAR(opline->result.var), value); | |
} | |
} else { | |
if (EXPECTED(Z_ISREF_P(object_ptr))) { | |
object_ptr = Z_REFVAL_P(object_ptr); | |
if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { | |
ZEND_VM_C_GOTO(try_assign_dim_array); | |
} | |
} | |
if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { | |
zend_object *obj = Z_OBJ_P(object_ptr); | |
GC_ADDREF(obj); | |
dim = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); | |
if (OP2_TYPE == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) { | |
dim = ZVAL_UNDEFINED_OP2(); | |
} else if (OP2_TYPE == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) { | |
dim++; | |
} | |
value = GET_OP_DATA_ZVAL_PTR_UNDEF(BP_VAR_R); | |
if (OP_DATA_TYPE == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) { | |
value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC); | |
} else if (OP_DATA_TYPE & (IS_CV|IS_VAR)) { | |
ZVAL_DEREF(value); | |
} | |
zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC); | |
FREE_OP_DATA(); | |
if (UNEXPECTED(GC_DELREF(obj) == 0)) { | |
zend_objects_store_del(obj); | |
} | |
} else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { | |
if (OP2_TYPE == IS_UNUSED) { | |
zend_use_new_element_for_string(); | |
FREE_OP_DATA(); | |
UNDEF_RESULT(); | |
} else { | |
dim = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); | |
value = GET_OP_DATA_ZVAL_PTR_UNDEF(BP_VAR_R); | |
zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC); | |
FREE_OP_DATA(); | |
} | |
} else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { | |
if (Z_ISREF_P(orig_object_ptr) | |
&& ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr)) | |
&& !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) { | |
dim = GET_OP2_ZVAL_PTR(BP_VAR_R); | |
FREE_OP_DATA(); | |
UNDEF_RESULT(); | |
} else { | |
HashTable *ht = zend_new_array(8); | |
uint8_t old_type = Z_TYPE_P(object_ptr); | |
ZVAL_ARR(object_ptr, ht); | |
if (UNEXPECTED(old_type == IS_FALSE)) { | |
GC_ADDREF(ht); | |
zend_false_to_array_deprecated(); | |
if (UNEXPECTED(GC_DELREF(ht) == 0)) { | |
zend_array_destroy(ht); | |
ZEND_VM_C_GOTO(assign_dim_error); | |
} | |
} | |
ZEND_VM_C_GOTO(try_assign_dim_array); | |
} | |
} else { | |
zend_use_scalar_as_array(); | |
dim = GET_OP2_ZVAL_PTR(BP_VAR_R); | |
ZEND_VM_C_LABEL(assign_dim_error): | |
FREE_OP_DATA(); | |
if (UNEXPECTED(RETURN_VALUE_USED(opline))) { | |
ZVAL_NULL(EX_VAR(opline->result.var)); | |
} | |
} | |
} | |
if (OP2_TYPE != IS_UNUSED) { | |
FREE_OP2(); | |
} | |
FREE_OP1(); | |
/* assign_dim has two opcodes! */ | |
ZEND_VM_NEXT_OPCODE_EX(1, 2); | |
} | |
ZEND_VM_HANDLER(22, ZEND_ASSIGN, VAR|CV, CONST|TMP|VAR|CV, SPEC(RETVAL)) | |
{ | |
USE_OPLINE | |
zval *value; | |
zval *variable_ptr; | |
SAVE_OPLINE(); | |
value = GET_OP2_ZVAL_PTR(BP_VAR_R); | |
variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); | |
value = zend_assign_to_variable(variable_ptr, value, OP2_TYPE, EX_USES_STRICT_TYPES()); | |
if (UNEXPECTED(RETURN_VALUE_USED(opline))) { | |
ZVAL_COPY(EX_VAR(opline->result.var), value); | |
} | |
FREE_OP1(); | |
/* zend_assign_to_variable() always takes care of op2, never free it! */ | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_HANDLER(30, ZEND_ASSIGN_REF, VAR|CV, VAR|CV, SRC) | |
{ | |
USE_OPLINE | |
zval *variable_ptr; | |
zval *value_ptr; | |
SAVE_OPLINE(); | |
value_ptr = GET_OP2_ZVAL_PTR_PTR(BP_VAR_W); | |
variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); | |
if (OP1_TYPE == IS_VAR && | |
UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) { | |
zend_throw_error(NULL, "Cannot assign by reference to an array dimension of an object"); | |
variable_ptr = &EG(uninitialized_zval); | |
} else if (OP2_TYPE == IS_VAR && | |
opline->extended_value == ZEND_RETURNS_FUNCTION && | |
UNEXPECTED(!Z_ISREF_P(value_ptr))) { | |
variable_ptr = zend_wrong_assign_to_variable_reference( | |
variable_ptr, value_ptr OPLINE_CC EXECUTE_DATA_CC); | |
} else { | |
zend_assign_to_variable_reference(variable_ptr, value_ptr); | |
} | |
if (UNEXPECTED(RETURN_VALUE_USED(opline))) { | |
ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); | |
} | |
FREE_OP2(); | |
FREE_OP1(); | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_HANDLER(32, ZEND_ASSIGN_OBJ_REF, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT|SRC, SPEC(OP_DATA=VAR|CV)) | |
{ | |
USE_OPLINE | |
zval *property, *container, *value_ptr; | |
SAVE_OPLINE(); | |
container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); | |
property = GET_OP2_ZVAL_PTR(BP_VAR_R); | |
value_ptr = GET_OP_DATA_ZVAL_PTR_PTR(BP_VAR_W); | |
if (ZEND_VM_SPEC) { | |
if (OP1_TYPE == IS_UNUSED) { | |
if (OP2_TYPE == IS_CONST) { | |
zend_assign_to_property_reference_this_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); | |
} else { | |
zend_assign_to_property_reference_this_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); | |
} | |
} else { | |
if (OP2_TYPE == IS_CONST) { | |
zend_assign_to_property_reference_var_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); | |
} else { | |
zend_assign_to_property_reference_var_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC); | |
} | |
} | |
} else { | |
zend_assign_to_property_reference(container, OP1_TYPE, property, OP2_TYPE, value_ptr OPLINE_CC EXECUTE_DATA_CC); | |
} | |
FREE_OP1(); | |
FREE_OP2(); | |
FREE_OP_DATA(); | |
ZEND_VM_NEXT_OPCODE_EX(1, 2); | |
} | |
/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */ | |
ZEND_VM_HANDLER(33, ZEND_ASSIGN_STATIC_PROP_REF, ANY, ANY, CACHE_SLOT|SRC) | |
{ | |
USE_OPLINE | |
zval *prop, *value_ptr; | |
zend_property_info *prop_info; | |
SAVE_OPLINE(); | |
if (zend_fetch_static_property_address(&prop, &prop_info, opline->extended_value & ~ZEND_RETURNS_FUNCTION, BP_VAR_W, 0 OPLINE_CC EXECUTE_DATA_CC) != SUCCESS) { | |
FREE_OP_DATA(); | |
UNDEF_RESULT(); | |
HANDLE_EXCEPTION(); | |
} | |
value_ptr = GET_OP_DATA_ZVAL_PTR_PTR(BP_VAR_W); | |
if (OP_DATA_TYPE == IS_VAR && (opline->extended_value & ZEND_RETURNS_FUNCTION) && UNEXPECTED(!Z_ISREF_P(value_ptr))) { | |
if (UNEXPECTED(!zend_wrong_assign_to_variable_reference(prop, value_ptr OPLINE_CC EXECUTE_DATA_CC))) { | |
prop = &EG(uninitialized_zval); | |
} | |
} else if (UNEXPECTED(ZEND_TYPE_IS_SET(prop_info->type))) { | |
prop = zend_assign_to_typed_property_reference(prop_info, prop, value_ptr EXECUTE_DATA_CC); | |
} else { | |
zend_assign_to_variable_reference(prop, value_ptr); | |
} | |
if (UNEXPECTED(RETURN_VALUE_USED(opline))) { | |
ZVAL_COPY(EX_VAR(opline->result.var), prop); | |
} | |
FREE_OP_DATA(); | |
ZEND_VM_NEXT_OPCODE_EX(1, 2); | |
} | |
ZEND_VM_HOT_HELPER(zend_leave_helper, ANY, ANY) | |
{ | |
zend_execute_data *old_execute_data; | |
uint32_t call_info = EX_CALL_INFO(); | |
SAVE_OPLINE(); | |
if (EXPECTED((call_info & (ZEND_CALL_CODE|ZEND_CALL_TOP|ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS|ZEND_CALL_ALLOCATED|ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) == 0)) { | |
EG(current_execute_data) = EX(prev_execute_data); | |
i_free_compiled_variables(execute_data); | |
#ifdef ZEND_PREFER_RELOAD | |
call_info = EX_CALL_INFO(); | |
#endif | |
if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) { | |
OBJ_RELEASE(Z_OBJ(execute_data->This)); | |
} else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { | |
OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func))); | |
} | |
EG(vm_stack_top) = (zval*)execute_data; | |
execute_data = EX(prev_execute_data); | |
if (UNEXPECTED(EG(exception) != NULL)) { | |
zend_rethrow_exception(execute_data); | |
HANDLE_EXCEPTION_LEAVE(); | |
} | |
LOAD_NEXT_OPLINE(); | |
ZEND_VM_LEAVE(); | |
} else if (EXPECTED((call_info & (ZEND_CALL_CODE|ZEND_CALL_TOP)) == 0)) { | |
EG(current_execute_data) = EX(prev_execute_data); | |
i_free_compiled_variables(execute_data); | |
#ifdef ZEND_PREFER_RELOAD | |
call_info = EX_CALL_INFO(); | |
#endif | |
if (UNEXPECTED(call_info & ZEND_CALL_HAS_SYMBOL_TABLE)) { | |
zend_clean_and_cache_symbol_table(EX(symbol_table)); | |
} | |
if (UNEXPECTED(call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) { | |
zend_free_extra_named_params(EX(extra_named_params)); | |
} | |
/* Free extra args before releasing the closure, | |
* as that may free the op_array. */ | |
zend_vm_stack_free_extra_args_ex(call_info, execute_data); | |
if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) { | |
OBJ_RELEASE(Z_OBJ(execute_data->This)); | |
} else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { | |
OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func))); | |
} | |
old_execute_data = execute_data; | |
execute_data = EX(prev_execute_data); | |
zend_vm_stack_free_call_frame_ex(call_info, old_execute_data); | |
if (UNEXPECTED(EG(exception) != NULL)) { | |
zend_rethrow_exception(execute_data); | |
HANDLE_EXCEPTION_LEAVE(); | |
} | |
LOAD_NEXT_OPLINE(); | |
ZEND_VM_LEAVE(); | |
} else if (EXPECTED((call_info & ZEND_CALL_TOP) == 0)) { | |
if (EX(func)->op_array.last_var > 0) { | |
zend_detach_symbol_table(execute_data); | |
call_info |= ZEND_CALL_NEEDS_REATTACH; | |
} | |
zend_destroy_static_vars(&EX(func)->op_array); | |
destroy_op_array(&EX(func)->op_array); | |
efree_size(EX(func), sizeof(zend_op_array)); | |
old_execute_data = execute_data; | |
execute_data = EG(current_execute_data) = EX(prev_execute_data); | |
zend_vm_stack_free_call_frame_ex(call_info, old_execute_data); | |
if (call_info & ZEND_CALL_NEEDS_REATTACH) { | |
if (EX(func)->op_array.last_var > 0) { | |
zend_attach_symbol_table(execute_data); | |
} else { | |
ZEND_ADD_CALL_FLAG(execute_data, ZEND_CALL_NEEDS_REATTACH); | |
} | |
} | |
if (UNEXPECTED(EG(exception) != NULL)) { | |
zend_rethrow_exception(execute_data); | |
HANDLE_EXCEPTION_LEAVE(); | |
} | |
LOAD_NEXT_OPLINE(); | |
ZEND_VM_LEAVE(); | |
} else { | |
if (EXPECTED((call_info & ZEND_CALL_CODE) == 0)) { | |
EG(current_execute_data) = EX(prev_execute_data); | |
i_free_compiled_variables(execute_data); | |
#ifdef ZEND_PREFER_RELOAD | |
call_info = EX_CALL_INFO(); | |
#endif | |
if (UNEXPECTED(call_info & (ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS|ZEND_CALL_HAS_EXTRA_NAMED_PARAMS))) { | |
if (UNEXPECTED(call_info & ZEND_CALL_HAS_SYMBOL_TABLE)) { | |
zend_clean_and_cache_symbol_table(EX(symbol_table)); | |
} | |
zend_vm_stack_free_extra_args_ex(call_info, execute_data); | |
if (UNEXPECTED(call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) { | |
zend_free_extra_named_params(EX(extra_named_params)); | |
} | |
} | |
if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) { | |
OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func))); | |
} | |
ZEND_VM_RETURN(); | |
} else /* if (call_kind == ZEND_CALL_TOP_CODE) */ { | |
zend_array *symbol_table = EX(symbol_table); | |
if (EX(func)->op_array.last_var > 0) { | |
zend_detach_symbol_table(execute_data); | |
call_info |= ZEND_CALL_NEEDS_REATTACH; | |
} | |
if (call_info & ZEND_CALL_NEEDS_REATTACH) { | |
old_execute_data = EX(prev_execute_data); | |
while (old_execute_data) { | |
if (old_execute_data->func && (ZEND_CALL_INFO(old_execute_data) & ZEND_CALL_HAS_SYMBOL_TABLE)) { | |
if (old_execute_data->symbol_table == symbol_table) { | |
if (old_execute_data->func->op_array.last_var > 0) { | |
zend_attach_symbol_table(old_execute_data); | |
} else { | |
ZEND_ADD_CALL_FLAG(old_execute_data, ZEND_CALL_NEEDS_REATTACH); | |
} | |
} | |
break; | |
} | |
old_execute_data = old_execute_data->prev_execute_data; | |
} | |
} | |
EG(current_execute_data) = EX(prev_execute_data); | |
ZEND_VM_RETURN(); | |
} | |
} | |
} | |
ZEND_VM_HOT_HANDLER(42, ZEND_JMP, JMP_ADDR, ANY) | |
{ | |
USE_OPLINE | |
ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op1), 0); | |
} | |
ZEND_VM_HOT_NOCONST_HANDLER(43, ZEND_JMPZ, CONST|TMPVAR|CV, JMP_ADDR) | |
{ | |
USE_OPLINE | |
zval *val; | |
uint8_t op1_type; | |
val = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); | |
if (Z_TYPE_INFO_P(val) == IS_TRUE) { | |
ZEND_VM_NEXT_OPCODE(); | |
} else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) { | |
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) { | |
SAVE_OPLINE(); | |
ZVAL_UNDEFINED_OP1(); | |
if (UNEXPECTED(EG(exception))) { | |
HANDLE_EXCEPTION(); | |
} | |
} | |
ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); | |
} | |
SAVE_OPLINE(); | |
op1_type = OP1_TYPE; | |
if (i_zend_is_true(val)) { | |
opline++; | |
} else { | |
opline = OP_JMP_ADDR(opline, opline->op2); | |
} | |
if (op1_type & (IS_TMP_VAR|IS_VAR)) { | |
zval_ptr_dtor_nogc(val); | |
} | |
ZEND_VM_JMP(opline); | |
} | |
ZEND_VM_HOT_NOCONST_HANDLER(44, ZEND_JMPNZ, CONST|TMPVAR|CV, JMP_ADDR) | |
{ | |
USE_OPLINE | |
zval *val; | |
uint8_t op1_type; | |
val = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); | |
if (Z_TYPE_INFO_P(val) == IS_TRUE) { | |
ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); | |
} else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) { | |
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) { | |
SAVE_OPLINE(); | |
ZVAL_UNDEFINED_OP1(); | |
if (UNEXPECTED(EG(exception))) { | |
HANDLE_EXCEPTION(); | |
} | |
} | |
ZEND_VM_NEXT_OPCODE(); | |
} | |
SAVE_OPLINE(); | |
op1_type = OP1_TYPE; | |
if (i_zend_is_true(val)) { | |
opline = OP_JMP_ADDR(opline, opline->op2); | |
} else { | |
opline++; | |
} | |
if (op1_type & (IS_TMP_VAR|IS_VAR)) { | |
zval_ptr_dtor_nogc(val); | |
} | |
ZEND_VM_JMP(opline); | |
} | |
ZEND_VM_COLD_CONST_HANDLER(46, ZEND_JMPZ_EX, CONST|TMPVAR|CV, JMP_ADDR) | |
{ | |
USE_OPLINE | |
zval *val; | |
bool ret; | |
val = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); | |
if (Z_TYPE_INFO_P(val) == IS_TRUE) { | |
ZVAL_TRUE(EX_VAR(opline->result.var)); | |
ZEND_VM_NEXT_OPCODE(); | |
} else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) { | |
ZVAL_FALSE(EX_VAR(opline->result.var)); | |
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) { | |
SAVE_OPLINE(); | |
ZVAL_UNDEFINED_OP1(); | |
if (UNEXPECTED(EG(exception))) { | |
HANDLE_EXCEPTION(); | |
} | |
} | |
ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); | |
} | |
SAVE_OPLINE(); | |
ret = i_zend_is_true(val); | |
FREE_OP1(); | |
if (ret) { | |
ZVAL_TRUE(EX_VAR(opline->result.var)); | |
opline++; | |
} else { | |
ZVAL_FALSE(EX_VAR(opline->result.var)); | |
opline = OP_JMP_ADDR(opline, opline->op2); | |
} | |
ZEND_VM_JMP(opline); | |
} | |
ZEND_VM_COLD_CONST_HANDLER(47, ZEND_JMPNZ_EX, CONST|TMPVAR|CV, JMP_ADDR) | |
{ | |
USE_OPLINE | |
zval *val; | |
bool ret; | |
val = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); | |
if (Z_TYPE_INFO_P(val) == IS_TRUE) { | |
ZVAL_TRUE(EX_VAR(opline->result.var)); | |
ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0); | |
} else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) { | |
ZVAL_FALSE(EX_VAR(opline->result.var)); | |
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) { | |
SAVE_OPLINE(); | |
ZVAL_UNDEFINED_OP1(); | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} else { | |
ZEND_VM_NEXT_OPCODE(); | |
} | |
} | |
SAVE_OPLINE(); | |
ret = i_zend_is_true(val); | |
FREE_OP1(); | |
if (ret) { | |
ZVAL_TRUE(EX_VAR(opline->result.var)); | |
opline = OP_JMP_ADDR(opline, opline->op2); | |
} else { | |
ZVAL_FALSE(EX_VAR(opline->result.var)); | |
opline++; | |
} | |
ZEND_VM_JMP(opline); | |
} | |
ZEND_VM_HANDLER(70, ZEND_FREE, TMPVAR, ANY) | |
{ | |
USE_OPLINE | |
SAVE_OPLINE(); | |
zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_HOT_HANDLER(127, ZEND_FE_FREE, TMPVAR, ANY) | |
{ | |
zval *var; | |
USE_OPLINE | |
var = EX_VAR(opline->op1.var); | |
if (Z_TYPE_P(var) != IS_ARRAY) { | |
SAVE_OPLINE(); | |
if (Z_FE_ITER_P(var) != (uint32_t)-1) { | |
zend_hash_iterator_del(Z_FE_ITER_P(var)); | |
} | |
zval_ptr_dtor_nogc(var); | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
/* This is freeing an array. Use an inlined version of zval_ptr_dtor_nogc. */ | |
/* PHP only needs to save the opline and check for an exception if the last reference to the array was garbage collected (destructors of elements in the array could throw an exception) */ | |
if (Z_REFCOUNTED_P(var) && !Z_DELREF_P(var)) { | |
SAVE_OPLINE(); | |
rc_dtor_func(Z_COUNTED_P(var)); | |
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); | |
} | |
ZEND_VM_NEXT_OPCODE(); | |
} | |
ZEND_VM_COLD_CONSTCONST_HANDLER(53, ZEND_FAST_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV) | |
{ | |
USE_OPLINE | |
zval *op1, *op2; | |
zend_string *op1_str, *op2_str, *str; | |
op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); | |
op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); | |
if ((OP1_TYPE == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) && | |
(OP2_TYPE == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) { | |
zend_string *op1_str = Z_STR_P(op1); | |
zend_string *op2_str = Z_STR_P(op2); | |
zend_string *str; | |
uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(op1_str, op2_str); | |
if (OP1_TYPE != IS_CONST && UNEXPECTED(ZSTR_LEN(op1_str) == 0)) { | |
if (OP2_TYPE == IS_CONST || OP2_TYPE == IS_CV) { | |
ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str); | |
} else { | |
ZVAL_STR(EX_VAR(opline->result.var), op2_str); | |
} | |
if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zend_string_release_ex(op1_str, 0); | |
} | |
} else if (OP2_TYPE != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) { | |
if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_CV) { | |
ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str); | |
} else { | |
ZVAL_STR(EX_VAR(opline->result.var), op1_str); | |
} | |
if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zend_string_release_ex(op2_str, 0); | |
} | |
} else if (OP1_TYPE != IS_CONST && OP1_TYPE != IS_CV && | |
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) { | |
size_t len = ZSTR_LEN(op1_str); | |
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0); | |
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1); | |
GC_ADD_FLAGS(str, flags); | |
ZVAL_NEW_STR(EX_VAR(opline->result.var), str); | |
if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) { | |
zend_string_release_ex(op2_str, 0); | |
} | |