Skip to content
Permalink
master
Switch branches/tags

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?
Go to file
 
 
Cannot retrieve contributors at this time
/*
+----------------------------------------------------------------------+
| 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);
}