summaryrefslogtreecommitdiff
path: root/Zend/zend_vm_def.h
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_vm_def.h')
-rw-r--r--Zend/zend_vm_def.h3331
1 files changed, 1925 insertions, 1406 deletions
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 6f9aca4b55..40b20f0d9c 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| Zend Engine |
+----------------------------------------------------------------------+
- | Copyright (c) 1998-2018 Zend Technologies Ltd. (http://www.zend.com) |
+ | 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 |
@@ -23,101 +23,159 @@
* php zend_vm_gen.php
*/
-ZEND_VM_COLD_CONSTCONST_HANDLER(1, ZEND_ADD, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
+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
zend_free_op free_op1, free_op2;
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 (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
+ 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)) {
- result = EX_VAR(opline->result.var);
- ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) + Z_DVAL_P(op2));
- ZEND_VM_NEXT_OPCODE();
+ 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, Z_DVAL_P(op1) + Z_DVAL_P(op2));
+ ZVAL_DOUBLE(result, d1 + d2);
ZEND_VM_NEXT_OPCODE();
} else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
- result = EX_VAR(opline->result.var);
- ZVAL_DOUBLE(result, Z_DVAL_P(op1) + ((double)Z_LVAL_P(op2)));
- ZEND_VM_NEXT_OPCODE();
+ 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 (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
- op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
+ if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) {
+ op_1 = ZVAL_UNDEFINED_OP1();
}
- if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
- op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
+ 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);
}
- add_function(EX_VAR(opline->result.var), op1, op2);
- FREE_OP1();
- FREE_OP2();
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_COLD_CONSTCONST_HANDLER(2, ZEND_SUB, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
+ZEND_VM_HOT_NOCONSTCONST_HANDLER(2, ZEND_SUB, CONST|TMPVARCV, CONST|TMPVARCV)
{
USE_OPLINE
zend_free_op free_op1, free_op2;
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 (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
+ 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)) {
- result = EX_VAR(opline->result.var);
- ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) - Z_DVAL_P(op2));
- ZEND_VM_NEXT_OPCODE();
+ 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, Z_DVAL_P(op1) - Z_DVAL_P(op2));
+ ZVAL_DOUBLE(result, d1 - d2);
ZEND_VM_NEXT_OPCODE();
} else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
- result = EX_VAR(opline->result.var);
- ZVAL_DOUBLE(result, Z_DVAL_P(op1) - ((double)Z_LVAL_P(op2)));
- ZEND_VM_NEXT_OPCODE();
+ 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 (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
- op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
+ if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) {
+ op_1 = ZVAL_UNDEFINED_OP1();
}
- if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
- op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
+ 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);
}
- sub_function(EX_VAR(opline->result.var), op1, op2);
- FREE_OP1();
- FREE_OP2();
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_COLD_CONSTCONST_HANDLER(3, ZEND_MUL, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(COMMUTATIVE))
+ZEND_VM_COLD_CONSTCONST_HANDLER(3, ZEND_MUL, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(COMMUTATIVE))
{
USE_OPLINE
zend_free_op free_op1, free_op2;
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 (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
+ 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;
@@ -126,33 +184,26 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(3, ZEND_MUL, CONST|TMPVAR|CV, CONST|TMPVAR|CV, S
Z_TYPE_INFO_P(result) = overflow ? IS_DOUBLE : IS_LONG;
ZEND_VM_NEXT_OPCODE();
} else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
- result = EX_VAR(opline->result.var);
- ZVAL_DOUBLE(result, ((double)Z_LVAL_P(op1)) * Z_DVAL_P(op2));
- ZEND_VM_NEXT_OPCODE();
+ 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, Z_DVAL_P(op1) * Z_DVAL_P(op2));
+ ZVAL_DOUBLE(result, d1 * d2);
ZEND_VM_NEXT_OPCODE();
} else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
- result = EX_VAR(opline->result.var);
- ZVAL_DOUBLE(result, Z_DVAL_P(op1) * ((double)Z_LVAL_P(op2)));
- ZEND_VM_NEXT_OPCODE();
+ d1 = Z_DVAL_P(op1);
+ d2 = (double)Z_LVAL_P(op2);
+ ZEND_VM_C_GOTO(mul_double);
}
}
- SAVE_OPLINE();
- if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
- op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
- }
- if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
- op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
- }
- mul_function(EX_VAR(opline->result.var), op1, op2);
- FREE_OP1();
- FREE_OP2();
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+ 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)
@@ -180,7 +231,28 @@ ZEND_VM_COLD_HELPER(zend_mod_by_zero_helper, ANY, ANY)
HANDLE_EXCEPTION();
}
-ZEND_VM_COLD_CONSTCONST_HANDLER(5, ZEND_MOD, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
+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
zend_free_op free_op1, free_op2;
@@ -188,7 +260,9 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(5, ZEND_MOD, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
+ 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)) {
@@ -203,20 +277,31 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(5, ZEND_MOD, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
}
}
+ 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 (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
- op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
+ if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) {
+ op_1 = ZVAL_UNDEFINED_OP1();
}
- if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
- op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
+ 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);
}
- mod_function(EX_VAR(opline->result.var), op1, op2);
- FREE_OP1();
- FREE_OP2();
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_COLD_CONSTCONST_HANDLER(6, ZEND_SL, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
+ZEND_VM_COLD_CONSTCONST_HANDLER(6, ZEND_SL, CONST|TMPVARCV, CONST|TMPVARCV)
{
USE_OPLINE
zend_free_op free_op1, free_op2;
@@ -224,27 +309,42 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(6, ZEND_SL, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)
+ 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));
+ /* 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 (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
- op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
+ if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) {
+ op_1 = ZVAL_UNDEFINED_OP1();
}
- if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
- op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
+ 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);
}
- shift_left_function(EX_VAR(opline->result.var), op1, op2);
- FREE_OP1();
- FREE_OP2();
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_COLD_CONSTCONST_HANDLER(7, ZEND_SR, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
+ZEND_VM_COLD_CONSTCONST_HANDLER(7, ZEND_SR, CONST|TMPVARCV, CONST|TMPVARCV)
{
USE_OPLINE
zend_free_op free_op1, free_op2;
@@ -252,27 +352,19 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(7, ZEND_SR, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)
+ 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();
}
- SAVE_OPLINE();
- if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
- op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
- }
- if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
- op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
- }
- shift_right_function(EX_VAR(opline->result.var), op1, op2);
- FREE_OP1();
- FREE_OP2();
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+ ZEND_VM_DISPATCH_TO_HELPER(zend_shift_right_helper, op_1, op1, op_2, op2);
}
-ZEND_VM_COLD_CONSTCONST_HANDLER(166, ZEND_POW, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
+ZEND_VM_COLD_CONSTCONST_HANDLER(12, ZEND_POW, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
{
USE_OPLINE
zend_free_op free_op1, free_op2;
@@ -308,14 +400,18 @@ ZEND_VM_HANDLER(8, ZEND_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(NO_CONST_
} else {
ZVAL_STR(EX_VAR(opline->result.var), op2_str);
}
- FREE_OP1();
+ 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);
}
- FREE_OP2();
+ 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);
@@ -323,24 +419,30 @@ ZEND_VM_HANDLER(8, ZEND_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(NO_CONST_
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);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
- FREE_OP2();
+ 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);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
- FREE_OP1();
- FREE_OP2();
+ 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 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
+ op1 = ZVAL_UNDEFINED_OP1();
}
if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
- op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
+ op2 = ZVAL_UNDEFINED_OP2();
}
concat_function(EX_VAR(opline->result.var), op1, op2);
FREE_OP1();
@@ -349,12 +451,12 @@ ZEND_VM_HANDLER(8, ZEND_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(NO_CONST_
}
}
-ZEND_VM_COLD_CONSTCONST_HANDLER(15, ZEND_IS_IDENTICAL, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV, SPEC(COMMUTATIVE))
+ZEND_VM_COLD_CONSTCONST_HANDLER(16, ZEND_IS_IDENTICAL, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV, SPEC(COMMUTATIVE))
{
USE_OPLINE
zend_free_op free_op1, free_op2;
zval *op1, *op2;
- int result;
+ zend_bool result;
SAVE_OPLINE();
op1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
@@ -367,12 +469,12 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(15, ZEND_IS_IDENTICAL, CONST|TMP|VAR|CV, CONST|T
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_COLD_CONSTCONST_HANDLER(16, ZEND_IS_NOT_IDENTICAL, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV, SPEC(COMMUTATIVE))
+ZEND_VM_COLD_CONSTCONST_HANDLER(17, ZEND_IS_NOT_IDENTICAL, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV, SPEC(COMMUTATIVE))
{
USE_OPLINE
zend_free_op free_op1, free_op2;
zval *op1, *op2;
- int result;
+ zend_bool result;
SAVE_OPLINE();
op1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
@@ -385,220 +487,354 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(16, ZEND_IS_NOT_IDENTICAL, CONST|TMP|VAR|CV, CON
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_COLD_CONSTCONST_HANDLER(17, ZEND_IS_EQUAL, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(COMMUTATIVE))
+ZEND_VM_HELPER(zend_is_equal_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();
+ }
+ compare_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);
+ }
+ if (UNEXPECTED(EG(exception))) {
+ HANDLE_EXCEPTION();
+ }
+ if (Z_LVAL_P(EX_VAR(opline->result.var)) == 0) {
+ ZEND_VM_SMART_BRANCH_TRUE();
+ ZVAL_TRUE(EX_VAR(opline->result.var));
+ ZEND_VM_NEXT_OPCODE();
+ } else {
+ ZEND_VM_SMART_BRANCH_FALSE();
+ ZVAL_FALSE(EX_VAR(opline->result.var));
+ ZEND_VM_NEXT_OPCODE();
+ }
+}
+
+ZEND_VM_COLD_CONSTCONST_HANDLER(18, ZEND_IS_EQUAL, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(SMART_BRANCH,COMMUTATIVE))
{
USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *op1, *op2, *result;
+ zval *op1, *op2;
+ double d1, d2;
op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
- do {
- int result;
-
- if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
- if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
- result = (Z_LVAL_P(op1) == Z_LVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
- result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2));
+ 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();
+ ZVAL_TRUE(EX_VAR(opline->result.var));
+ ZEND_VM_NEXT_OPCODE();
} else {
- break;
+ZEND_VM_C_LABEL(is_equal_false):
+ ZEND_VM_SMART_BRANCH_FALSE();
+ ZVAL_FALSE(EX_VAR(opline->result.var));
+ ZEND_VM_NEXT_OPCODE();
}
- } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
- if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
- result = (Z_DVAL_P(op1) == Z_DVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
- result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2)));
+ } 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 {
- break;
+ ZEND_VM_C_GOTO(is_equal_false);
}
- } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
- if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
- result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2));
- FREE_OP1();
- FREE_OP2();
+ } 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)) {
+ int 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 {
- break;
+ ZEND_VM_C_GOTO(is_equal_false);
}
- } else {
- break;
}
- ZEND_VM_SMART_BRANCH(result, 0);
- ZVAL_BOOL(EX_VAR(opline->result.var), result);
- ZEND_VM_NEXT_OPCODE();
- } while (0);
+ }
+ 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)
+{
+ USE_OPLINE
SAVE_OPLINE();
- if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
- op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
+ if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) {
+ op_1 = ZVAL_UNDEFINED_OP1();
}
- if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
- op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
+ if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) {
+ op_2 = ZVAL_UNDEFINED_OP2();
+ }
+ compare_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);
+ }
+ if (UNEXPECTED(EG(exception))) {
+ HANDLE_EXCEPTION();
+ }
+ if (Z_LVAL_P(EX_VAR(opline->result.var)) != 0) {
+ ZEND_VM_SMART_BRANCH_TRUE();
+ ZVAL_TRUE(EX_VAR(opline->result.var));
+ ZEND_VM_NEXT_OPCODE();
+ } else {
+ ZEND_VM_SMART_BRANCH_FALSE();
+ ZVAL_FALSE(EX_VAR(opline->result.var));
+ ZEND_VM_NEXT_OPCODE();
}
- result = EX_VAR(opline->result.var);
- compare_function(result, op1, op2);
- ZVAL_BOOL(result, Z_LVAL_P(result) == 0);
- FREE_OP1();
- FREE_OP2();
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_COLD_CONSTCONST_HANDLER(18, ZEND_IS_NOT_EQUAL, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(COMMUTATIVE))
+ZEND_VM_COLD_CONSTCONST_HANDLER(19, ZEND_IS_NOT_EQUAL, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(SMART_BRANCH,COMMUTATIVE))
{
USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *op1, *op2, *result;
+ zval *op1, *op2;
+ double d1, d2;
op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
- do {
- int result;
-
- if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
- if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
- result = (Z_LVAL_P(op1) != Z_LVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
- result = ((double)Z_LVAL_P(op1) != Z_DVAL_P(op2));
+ 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();
+ ZVAL_TRUE(EX_VAR(opline->result.var));
+ ZEND_VM_NEXT_OPCODE();
} else {
- break;
+ZEND_VM_C_LABEL(is_not_equal_false):
+ ZEND_VM_SMART_BRANCH_FALSE();
+ ZVAL_FALSE(EX_VAR(opline->result.var));
+ ZEND_VM_NEXT_OPCODE();
}
- } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
- if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
- result = (Z_DVAL_P(op1) != Z_DVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
- result = (Z_DVAL_P(op1) != ((double)Z_LVAL_P(op2)));
+ } 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 {
- break;
+ ZEND_VM_C_GOTO(is_not_equal_false);
}
- } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
- if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
- result = !zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2));
- FREE_OP1();
- FREE_OP2();
+ } 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)) {
+ int 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 {
- break;
+ ZEND_VM_C_GOTO(is_not_equal_false);
}
- } else {
- break;
}
- ZEND_VM_SMART_BRANCH(result, 0);
- ZVAL_BOOL(EX_VAR(opline->result.var), result);
- ZEND_VM_NEXT_OPCODE();
- } while (0);
+ }
+ 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)
+{
+ USE_OPLINE
SAVE_OPLINE();
- if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
- op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
+ if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) {
+ op_1 = ZVAL_UNDEFINED_OP1();
}
- if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
- op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
+ if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) {
+ op_2 = ZVAL_UNDEFINED_OP2();
+ }
+ compare_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);
+ }
+ if (UNEXPECTED(EG(exception))) {
+ HANDLE_EXCEPTION();
+ }
+ if (Z_LVAL_P(EX_VAR(opline->result.var)) < 0) {
+ ZEND_VM_SMART_BRANCH_TRUE();
+ ZVAL_TRUE(EX_VAR(opline->result.var));
+ ZEND_VM_NEXT_OPCODE();
+ } else {
+ ZEND_VM_SMART_BRANCH_FALSE();
+ ZVAL_FALSE(EX_VAR(opline->result.var));
+ ZEND_VM_NEXT_OPCODE();
}
- result = EX_VAR(opline->result.var);
- compare_function(result, op1, op2);
- ZVAL_BOOL(result, Z_LVAL_P(result) != 0);
- FREE_OP1();
- FREE_OP2();
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_COLD_CONSTCONST_HANDLER(19, ZEND_IS_SMALLER, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
+ZEND_VM_HOT_NOCONSTCONST_HANDLER(20, ZEND_IS_SMALLER, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH))
{
USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *op1, *op2, *result;
+ zval *op1, *op2;
+ double d1, d2;
op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
- do {
- int result;
-
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
- result = (Z_LVAL_P(op1) < Z_LVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
- result = ((double)Z_LVAL_P(op1) < Z_DVAL_P(op2));
+ 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();
+ ZVAL_TRUE(EX_VAR(opline->result.var));
+ ZEND_VM_NEXT_OPCODE();
} else {
- break;
+ZEND_VM_C_LABEL(is_smaller_false):
+ ZEND_VM_SMART_BRANCH_FALSE();
+ ZVAL_FALSE(EX_VAR(opline->result.var));
+ ZEND_VM_NEXT_OPCODE();
}
- } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
- result = (Z_DVAL_P(op1) < Z_DVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
- result = (Z_DVAL_P(op1) < ((double)Z_LVAL_P(op2)));
+ } 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 {
- break;
+ ZEND_VM_C_GOTO(is_smaller_false);
}
- } else {
- break;
+ } 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_SMART_BRANCH(result, 0);
- ZVAL_BOOL(EX_VAR(opline->result.var), result);
- ZEND_VM_NEXT_OPCODE();
- } while (0);
+ }
+ 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)
+{
+ USE_OPLINE
SAVE_OPLINE();
- if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
- op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
+ if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) {
+ op_1 = ZVAL_UNDEFINED_OP1();
}
- if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
- op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
+ if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) {
+ op_2 = ZVAL_UNDEFINED_OP2();
+ }
+ compare_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);
+ }
+ if (UNEXPECTED(EG(exception))) {
+ HANDLE_EXCEPTION();
+ }
+ if (Z_LVAL_P(EX_VAR(opline->result.var)) <= 0) {
+ ZEND_VM_SMART_BRANCH_TRUE();
+ ZVAL_TRUE(EX_VAR(opline->result.var));
+ ZEND_VM_NEXT_OPCODE();
+ } else {
+ ZEND_VM_SMART_BRANCH_FALSE();
+ ZVAL_FALSE(EX_VAR(opline->result.var));
+ ZEND_VM_NEXT_OPCODE();
}
- result = EX_VAR(opline->result.var);
- compare_function(result, op1, op2);
- ZVAL_BOOL(result, Z_LVAL_P(result) < 0);
- FREE_OP1();
- FREE_OP2();
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_COLD_CONSTCONST_HANDLER(20, ZEND_IS_SMALLER_OR_EQUAL, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
+ZEND_VM_HOT_NOCONSTCONST_HANDLER(21, ZEND_IS_SMALLER_OR_EQUAL, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH))
{
USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *op1, *op2, *result;
+ zval *op1, *op2;
+ double d1, d2;
op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
- do {
- int result;
-
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
- result = (Z_LVAL_P(op1) <= Z_LVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
- result = ((double)Z_LVAL_P(op1) <= Z_DVAL_P(op2));
+ 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 {
- break;
+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(op1) == IS_DOUBLE)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
- result = (Z_DVAL_P(op1) <= Z_DVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
- result = (Z_DVAL_P(op1) <= ((double)Z_LVAL_P(op2)));
+ } 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 {
- break;
+ ZEND_VM_C_GOTO(is_smaller_or_equal_false);
}
- } else {
- break;
+ } 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_SMART_BRANCH(result, 0);
- ZVAL_BOOL(EX_VAR(opline->result.var), result);
- ZEND_VM_NEXT_OPCODE();
- } while (0);
-
- SAVE_OPLINE();
- if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
- op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
- }
- if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
- op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
}
- result = EX_VAR(opline->result.var);
- compare_function(result, op1, op2);
- ZVAL_BOOL(result, Z_LVAL_P(result) <= 0);
- FREE_OP1();
- FREE_OP2();
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+ 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)
@@ -616,7 +852,28 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(170, ZEND_SPACESHIP, CONST|TMPVAR|CV, CONST|TMPV
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_COLD_CONSTCONST_HANDLER(9, ZEND_BW_OR, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(COMMUTATIVE))
+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_COLD_CONSTCONST_HANDLER(9, ZEND_BW_OR, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(COMMUTATIVE))
{
USE_OPLINE
zend_free_op free_op1, free_op2;
@@ -624,26 +881,39 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(9, ZEND_BW_OR, CONST|TMPVAR|CV, CONST|TMPVAR|CV,
op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)
+ 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 (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
- op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
+ if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) {
+ op_1 = ZVAL_UNDEFINED_OP1();
}
- if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
- op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
+ 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);
}
- bitwise_or_function(EX_VAR(opline->result.var), op1, op2);
- FREE_OP1();
- FREE_OP2();
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_COLD_CONSTCONST_HANDLER(10, ZEND_BW_AND, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(COMMUTATIVE))
+ZEND_VM_COLD_CONSTCONST_HANDLER(10, ZEND_BW_AND, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(COMMUTATIVE))
{
USE_OPLINE
zend_free_op free_op1, free_op2;
@@ -651,26 +921,39 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(10, ZEND_BW_AND, CONST|TMPVAR|CV, CONST|TMPVAR|C
op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)
+ 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 (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
- op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
+ if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) {
+ op_1 = ZVAL_UNDEFINED_OP1();
}
- if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
- op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
+ 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);
}
- bitwise_and_function(EX_VAR(opline->result.var), op1, op2);
- FREE_OP1();
- FREE_OP2();
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_COLD_CONSTCONST_HANDLER(11, ZEND_BW_XOR, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(COMMUTATIVE))
+ZEND_VM_COLD_CONSTCONST_HANDLER(11, ZEND_BW_XOR, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(COMMUTATIVE))
{
USE_OPLINE
zend_free_op free_op1, free_op2;
@@ -678,26 +961,18 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(11, ZEND_BW_XOR, CONST|TMPVAR|CV, CONST|TMPVAR|C
op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)
+ 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();
}
- SAVE_OPLINE();
- if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
- op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
- }
- if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
- op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
- }
- bitwise_xor_function(EX_VAR(opline->result.var), op1, op2);
- FREE_OP1();
- FREE_OP2();
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+ ZEND_VM_DISPATCH_TO_HELPER(zend_bw_xor_helper, op_1, op1, op_2, op2);
}
-ZEND_VM_COLD_CONSTCONST_HANDLER(14, ZEND_BOOL_XOR, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(COMMUTATIVE))
+ZEND_VM_COLD_CONSTCONST_HANDLER(15, ZEND_BOOL_XOR, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(COMMUTATIVE))
{
USE_OPLINE
zend_free_op free_op1, free_op2;
@@ -712,7 +987,7 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(14, ZEND_BOOL_XOR, CONST|TMPVAR|CV, CONST|TMPVAR
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_COLD_CONST_HANDLER(12, ZEND_BW_NOT, CONST|TMPVAR|CV, ANY)
+ZEND_VM_COLD_CONST_HANDLER(13, ZEND_BW_NOT, CONST|TMPVAR|CV, ANY)
{
USE_OPLINE
zend_free_op free_op1;
@@ -725,13 +1000,15 @@ ZEND_VM_COLD_CONST_HANDLER(12, ZEND_BW_NOT, CONST|TMPVAR|CV, ANY)
}
SAVE_OPLINE();
- bitwise_not_function(EX_VAR(opline->result.var),
- GET_OP1_ZVAL_PTR(BP_VAR_R));
+ if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
+ op1 = ZVAL_UNDEFINED_OP1();
+ }
+ bitwise_not_function(EX_VAR(opline->result.var), op1);
FREE_OP1();
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_COLD_CONST_HANDLER(13, ZEND_BOOL_NOT, CONST|TMPVAR|CV, ANY)
+ZEND_VM_COLD_CONST_HANDLER(14, ZEND_BOOL_NOT, CONST|TMPVAR|CV, ANY)
{
USE_OPLINE
zval *val;
@@ -746,7 +1023,7 @@ ZEND_VM_COLD_CONST_HANDLER(13, ZEND_BOOL_NOT, CONST|TMPVAR|CV, ANY)
ZVAL_TRUE(EX_VAR(opline->result.var));
if (OP1_TYPE == IS_CV && UNEXPECTED(orig_val_type == IS_UNDEF)) {
SAVE_OPLINE();
- GET_OP1_UNDEF_CV(val, BP_VAR_R);
+ ZVAL_UNDEFINED_OP1();
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
} else {
@@ -772,34 +1049,30 @@ ZEND_VM_COLD_HELPER(zend_this_not_in_object_context_helper, ANY, ANY)
HANDLE_EXCEPTION();
}
-ZEND_VM_COLD_HELPER(zend_abstract_method_helper, ANY, ANY, zend_function *fbc)
+ZEND_VM_COLD_HELPER(zend_undefined_function_helper, ANY, ANY)
{
USE_OPLINE
+ zval *function_name;
SAVE_OPLINE();
- zend_throw_error(NULL, "Cannot call abstract method %s::%s()", ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name));
- UNDEF_RESULT();
- HANDLE_EXCEPTION();
-}
-
-ZEND_VM_COLD_HELPER(zend_undefined_function_helper, ANY, ANY, 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_HELPER(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV, binary_op_type binary_op)
+ZEND_VM_HANDLER(28, ZEND_ASSIGN_OBJ_OP, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, OP)
{
USE_OPLINE
- zend_free_op free_op1, free_op2, free_op_data1;
+ zend_free_op free_op1, free_op2, free_op_data;
zval *object;
zval *property;
zval *value;
zval *zptr;
+ void **cache_slot;
+ zend_property_info *prop_info;
SAVE_OPLINE();
- object = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW);
+ object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
@@ -808,49 +1081,124 @@ ZEND_VM_HELPER(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV,
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
do {
- value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data1);
+ 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)) {
+ if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) {
object = Z_REFVAL_P(object);
- if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
- ZEND_VM_C_GOTO(assign_op_object);
- }
+ ZEND_VM_C_GOTO(assign_op_object);
}
- if (UNEXPECTED(!make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC))) {
+ if (OP1_TYPE == IS_CV
+ && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
+ ZVAL_UNDEFINED_OP1();
+ }
+ object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC);
+ if (UNEXPECTED(!object)) {
break;
}
}
- /* here we are sure we are dealing with an object */
ZEND_VM_C_LABEL(assign_op_object):
- if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
- && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL))) != NULL)) {
+ /* here we are sure we are dealing with an object */
+ cache_slot = (OP2_TYPE == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL;
+ if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, 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_DEREF(zptr);
+ 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);
- binary_op(zptr, zptr, value);
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_COPY(EX_VAR(opline->result.var), zptr);
}
}
} else {
- zend_assign_op_overloaded_property(object, property, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : NULL), value, binary_op OPLINE_CC EXECUTE_DATA_CC);
+ zend_assign_op_overloaded_property(object, property, cache_slot, value OPLINE_CC EXECUTE_DATA_CC);
}
} while (0);
- FREE_OP(free_op_data1);
+ FREE_OP_DATA();
FREE_OP2();
FREE_OP1_VAR_PTR();
/* assign_obj has two opcodes! */
ZEND_VM_NEXT_OPCODE_EX(1, 2);
}
-ZEND_VM_HELPER(zend_binary_assign_op_dim_helper, VAR|CV, CONST|TMPVAR|UNUSED|CV, binary_op_type binary_op)
+/* 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
+ zend_free_op free_op_data;
+ 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)) {
+ ZEND_ASSERT(EG(exception));
+ UNDEF_RESULT();
+ FREE_UNFETCHED_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(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
zend_free_op free_op1, free_op2, free_op_data1;
@@ -880,68 +1228,63 @@ ZEND_VM_C_LABEL(assign_dim_op_new_array):
if (UNEXPECTED(!var_ptr)) {
ZEND_VM_C_GOTO(assign_dim_op_ret_null);
}
- ZVAL_DEREF(var_ptr);
}
value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data1);
- binary_op(var_ptr, var_ptr, value);
+ 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(free_op_data1);
} 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);
}
- } else if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) {
- container = GET_OP1_UNDEF_CV(container, BP_VAR_RW);
-ZEND_VM_C_LABEL(assign_dim_op_convert_to_array):
- ZVAL_ARR(container, zend_new_array(8));
- ZEND_VM_C_GOTO(assign_dim_op_new_array);
}
dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
- value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data1);
if (OP2_TYPE == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) {
dim++;
}
- zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op EXECUTE_DATA_CC);
+ zend_binary_assign_op_obj_dim(container, dim OPLINE_CC EXECUTE_DATA_CC);
+ } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) {
+ if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) {
+ ZVAL_UNDEFINED_OP1();
+ }
+ ZVAL_ARR(container, zend_new_array(8));
+ ZEND_VM_C_GOTO(assign_dim_op_new_array);
} else {
- if (UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
- if (OP2_TYPE == IS_UNUSED) {
- zend_use_new_element_for_string();
- } else {
- zend_check_string_offset(dim, BP_VAR_RW EXECUTE_DATA_CC);
- zend_wrong_string_offset(EXECUTE_DATA_C);
- }
- UNDEF_RESULT();
- } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) {
- ZEND_VM_C_GOTO(assign_dim_op_convert_to_array);
- } else {
- if (UNEXPECTED(OP1_TYPE != IS_VAR || EXPECTED(!Z_ISERROR_P(container)))) {
- zend_use_scalar_as_array();
- }
+ zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC);
ZEND_VM_C_LABEL(assign_dim_op_ret_null):
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_NULL(EX_VAR(opline->result.var));
- }
+ FREE_UNFETCHED_OP_DATA();
+ if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+ ZVAL_NULL(EX_VAR(opline->result.var));
}
- value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, &free_op_data1);
}
}
FREE_OP2();
- FREE_OP(free_op_data1);
FREE_OP1_VAR_PTR();
ZEND_VM_NEXT_OPCODE_EX(1, 2);
}
-ZEND_VM_HELPER(zend_binary_assign_op_simple_helper, VAR|CV, CONST|TMPVAR|CV, binary_op_type binary_op)
+ZEND_VM_HANDLER(26, ZEND_ASSIGN_OP, VAR|CV, CONST|TMPVAR|CV, OP)
{
USE_OPLINE
zend_free_op free_op1, free_op2;
@@ -957,9 +1300,17 @@ ZEND_VM_HELPER(zend_binary_assign_op_simple_helper, VAR|CV, CONST|TMPVAR|CV, bin
ZVAL_NULL(EX_VAR(opline->result.var));
}
} else {
- ZVAL_DEREF(var_ptr);
-
- binary_op(var_ptr, var_ptr, value);
+ 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);
@@ -971,99 +1322,18 @@ ZEND_VM_HELPER(zend_binary_assign_op_simple_helper, VAR|CV, CONST|TMPVAR|CV, bin
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_INLINE_HELPER(zend_binary_assign_op_helper, VAR|UNUSED|THIS|CV, CONST|TMPVAR|UNUSED|NEXT|CV, SPEC(DIM_OBJ), binary_op_type binary_op)
-{
-#if defined(ZEND_VM_SPEC) && OP2_TYPE == IS_UNUSED
- ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_dim_helper, binary_op, binary_op);
-#else
-# if !defined(ZEND_VM_SPEC) || OP1_TYPE != IS_UNUSED
-# if !defined(ZEND_VM_SPEC)
- /* opline->extended_value checks are specialized, don't need opline */
- USE_OPLINE
-# endif
-
- if (EXPECTED(opline->extended_value == 0)) {
- ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_simple_helper, binary_op, binary_op);
- }
- if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
- ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_dim_helper, binary_op, binary_op);
- }
-# endif
-
- ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_obj_helper, binary_op, binary_op);
-#endif
-}
-
-ZEND_VM_HANDLER(23, ZEND_ASSIGN_ADD, VAR|UNUSED|THIS|CV, CONST|TMPVAR|UNUSED|NEXT|CV, DIM_OBJ|CACHE_SLOT, SPEC(DIM_OBJ))
-{
- ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_helper, binary_op, add_function);
-}
-
-ZEND_VM_HANDLER(24, ZEND_ASSIGN_SUB, VAR|UNUSED|THIS|CV, CONST|TMPVAR|UNUSED|NEXT|CV, DIM_OBJ|CACHE_SLOT, SPEC(DIM_OBJ))
-{
- ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_helper, binary_op, sub_function);
-}
-
-ZEND_VM_HANDLER(25, ZEND_ASSIGN_MUL, VAR|UNUSED|THIS|CV, CONST|TMPVAR|UNUSED|NEXT|CV, DIM_OBJ|CACHE_SLOT, SPEC(DIM_OBJ))
-{
- ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_helper, binary_op, mul_function);
-}
-
-ZEND_VM_HANDLER(26, ZEND_ASSIGN_DIV, VAR|UNUSED|THIS|CV, CONST|TMPVAR|UNUSED|NEXT|CV, DIM_OBJ|CACHE_SLOT, SPEC(DIM_OBJ))
-{
- ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_helper, binary_op, div_function);
-}
-
-ZEND_VM_HANDLER(27, ZEND_ASSIGN_MOD, VAR|UNUSED|THIS|CV, CONST|TMPVAR|UNUSED|NEXT|CV, DIM_OBJ|CACHE_SLOT, SPEC(DIM_OBJ))
-{
- ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_helper, binary_op, mod_function);
-}
-
-ZEND_VM_HANDLER(28, ZEND_ASSIGN_SL, VAR|UNUSED|THIS|CV, CONST|TMPVAR|UNUSED|NEXT|CV, DIM_OBJ|CACHE_SLOT, SPEC(DIM_OBJ))
-{
- ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_helper, binary_op, shift_left_function);
-}
-
-ZEND_VM_HANDLER(29, ZEND_ASSIGN_SR, VAR|UNUSED|THIS|CV, CONST|TMPVAR|UNUSED|NEXT|CV, DIM_OBJ|CACHE_SLOT, SPEC(DIM_OBJ))
-{
- ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_helper, binary_op, shift_right_function);
-}
-
-ZEND_VM_HANDLER(30, ZEND_ASSIGN_CONCAT, VAR|UNUSED|THIS|CV, CONST|TMPVAR|UNUSED|NEXT|CV, DIM_OBJ|CACHE_SLOT, SPEC(DIM_OBJ))
-{
- ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_helper, binary_op, concat_function);
-}
-
-ZEND_VM_HANDLER(31, ZEND_ASSIGN_BW_OR, VAR|UNUSED|THIS|CV, CONST|TMPVAR|UNUSED|NEXT|CV, DIM_OBJ|CACHE_SLOT, SPEC(DIM_OBJ))
-{
- ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_helper, binary_op, bitwise_or_function);
-}
-
-ZEND_VM_HANDLER(32, ZEND_ASSIGN_BW_AND, VAR|UNUSED|THIS|CV, CONST|TMPVAR|UNUSED|NEXT|CV, DIM_OBJ|CACHE_SLOT, SPEC(DIM_OBJ))
-{
- ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_helper, binary_op, bitwise_and_function);
-}
-
-ZEND_VM_HANDLER(33, ZEND_ASSIGN_BW_XOR, VAR|UNUSED|THIS|CV, CONST|TMPVAR|UNUSED|NEXT|CV, DIM_OBJ|CACHE_SLOT, SPEC(DIM_OBJ))
-{
- ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_helper, binary_op, bitwise_xor_function);
-}
-
-ZEND_VM_HANDLER(167, ZEND_ASSIGN_POW, VAR|UNUSED|THIS|CV, CONST|TMPVAR|UNUSED|NEXT|CV, DIM_OBJ|CACHE_SLOT, SPEC(DIM_OBJ))
-{
- ZEND_VM_DISPATCH_TO_HELPER(zend_binary_assign_op_helper, binary_op, pow_function);
-}
-
-ZEND_VM_HELPER(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV, int inc)
+ZEND_VM_HANDLER(132, ZEND_PRE_INC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT)
{
USE_OPLINE
zend_free_op free_op1, free_op2;
zval *object;
zval *property;
zval *zptr;
+ void **cache_slot;
+ zend_property_info *prop_info;
SAVE_OPLINE();
- object = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW);
+ object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
@@ -1073,47 +1343,38 @@ ZEND_VM_HELPER(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV,
do {
if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
- if (Z_ISREF_P(object)) {
+ if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) {
object = Z_REFVAL_P(object);
- if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
- ZEND_VM_C_GOTO(pre_incdec_object);
- }
+ ZEND_VM_C_GOTO(pre_incdec_object);
+ }
+ if (OP1_TYPE == IS_CV
+ && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
+ ZVAL_UNDEFINED_OP1();
}
- if (UNEXPECTED(!make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC))) {
+ object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC);
+ if (UNEXPECTED(!object)) {
break;
}
}
- /* here we are sure we are dealing with an object */
ZEND_VM_C_LABEL(pre_incdec_object):
- if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
- && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL))) != NULL)) {
+ /* here we are sure we are dealing with an object */
+ cache_slot = (OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL;
+ if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, 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 (EXPECTED(Z_TYPE_P(zptr) == IS_LONG)) {
- if (inc) {
- fast_long_increment_function(zptr);
- } else {
- fast_long_decrement_function(zptr);
- }
+ if (OP2_TYPE == IS_CONST) {
+ prop_info = (zend_property_info *) CACHED_PTR_EX(cache_slot + 2);
} else {
- ZVAL_DEREF(zptr);
-
- if (inc) {
- increment_function(zptr);
- } else {
- decrement_function(zptr);
- }
- }
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_COPY(EX_VAR(opline->result.var), zptr);
+ 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(object, property, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), inc OPLINE_CC EXECUTE_DATA_CC);
+ zend_pre_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC);
}
} while (0);
@@ -1122,26 +1383,23 @@ ZEND_VM_C_LABEL(pre_incdec_object):
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(132, ZEND_PRE_INC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT)
-{
- ZEND_VM_DISPATCH_TO_HELPER(zend_pre_incdec_property_helper, inc, 1);
-}
-
ZEND_VM_HANDLER(133, ZEND_PRE_DEC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT)
{
- ZEND_VM_DISPATCH_TO_HELPER(zend_pre_incdec_property_helper, inc, 0);
+ ZEND_VM_DISPATCH_TO_HANDLER(ZEND_PRE_INC_OBJ);
}
-ZEND_VM_HELPER(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV, int inc)
+ZEND_VM_HANDLER(134, ZEND_POST_INC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT)
{
USE_OPLINE
zend_free_op free_op1, free_op2;
zval *object;
zval *property;
zval *zptr;
+ void **cache_slot;
+ zend_property_info *prop_info;
SAVE_OPLINE();
- object = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW);
+ object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
@@ -1151,43 +1409,37 @@ ZEND_VM_HELPER(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV,
do {
if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
- if (Z_ISREF_P(object)) {
+ if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) {
object = Z_REFVAL_P(object);
- if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
- ZEND_VM_C_GOTO(post_incdec_object);
- }
+ ZEND_VM_C_GOTO(post_incdec_object);
}
- if (UNEXPECTED(!make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC))) {
+ if (OP1_TYPE == IS_CV
+ && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
+ ZVAL_UNDEFINED_OP1();
+ }
+ object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC);
+ if (UNEXPECTED(!object)) {
break;
}
}
- /* here we are sure we are dealing with an object */
ZEND_VM_C_LABEL(post_incdec_object):
- if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
- && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL))) != NULL)) {
+ /* here we are sure we are dealing with an object */
+ cache_slot = (OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL;
+ if (EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, cache_slot)) != NULL)) {
if (UNEXPECTED(Z_ISERROR_P(zptr))) {
ZVAL_NULL(EX_VAR(opline->result.var));
} else {
- if (EXPECTED(Z_TYPE_P(zptr) == IS_LONG)) {
- ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(zptr));
- if (inc) {
- fast_long_increment_function(zptr);
- } else {
- fast_long_decrement_function(zptr);
- }
+ if (OP2_TYPE == IS_CONST) {
+ prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
} else {
- ZVAL_DEREF(zptr);
- ZVAL_COPY(EX_VAR(opline->result.var), zptr);
- if (inc) {
- increment_function(zptr);
- } else {
- decrement_function(zptr);
- }
+ 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(object, property, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), inc OPLINE_CC EXECUTE_DATA_CC);
+ zend_post_incdec_overloaded_property(object, property, cache_slot OPLINE_CC EXECUTE_DATA_CC);
}
} while (0);
@@ -1196,17 +1448,62 @@ ZEND_VM_C_LABEL(post_incdec_object):
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(134, ZEND_POST_INC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT)
+ZEND_VM_HANDLER(135, ZEND_POST_DEC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT)
{
- ZEND_VM_DISPATCH_TO_HELPER(zend_post_incdec_property_helper, inc, 1);
+ ZEND_VM_DISPATCH_TO_HANDLER(ZEND_POST_INC_OBJ);
}
-ZEND_VM_HANDLER(135, ZEND_POST_DEC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT)
+/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */
+ZEND_VM_HANDLER(38, ZEND_PRE_INC_STATIC_PROP, ANY, ANY, CACHE_SLOT)
{
- ZEND_VM_DISPATCH_TO_HELPER(zend_post_incdec_property_helper, inc, 0);
+ 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, 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);
}
-ZEND_VM_HANDLER(34, ZEND_PRE_INC, VAR|CV, ANY, SPEC(RETVAL))
+/* 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, 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
zend_free_op free_op1;
@@ -1214,14 +1511,6 @@ ZEND_VM_HANDLER(34, ZEND_PRE_INC, VAR|CV, ANY, SPEC(RETVAL))
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();
- }
-
if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) {
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_NULL(EX_VAR(opline->result.var));
@@ -1231,11 +1520,21 @@ ZEND_VM_HANDLER(34, ZEND_PRE_INC, VAR|CV, ANY, SPEC(RETVAL))
SAVE_OPLINE();
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) {
- var_ptr = GET_OP1_UNDEF_CV(var_ptr, BP_VAR_RW);
+ ZVAL_NULL(var_ptr);
+ ZVAL_UNDEFINED_OP1();
}
- ZVAL_DEREF(var_ptr);
- increment_function(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);
@@ -1245,7 +1544,7 @@ ZEND_VM_HANDLER(34, ZEND_PRE_INC, VAR|CV, ANY, SPEC(RETVAL))
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(35, ZEND_PRE_DEC, VAR|CV, ANY, SPEC(RETVAL))
+ZEND_VM_HOT_HANDLER(34, ZEND_PRE_INC, VAR|CV, ANY, SPEC(RETVAL))
{
USE_OPLINE
zend_free_op free_op1;
@@ -1254,13 +1553,24 @@ ZEND_VM_HANDLER(35, ZEND_PRE_DEC, VAR|CV, ANY, SPEC(RETVAL))
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);
+ 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
+ zend_free_op free_op1;
+ zval *var_ptr;
+
+ var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
+
if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) {
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_NULL(EX_VAR(opline->result.var));
@@ -1270,11 +1580,22 @@ ZEND_VM_HANDLER(35, ZEND_PRE_DEC, VAR|CV, ANY, SPEC(RETVAL))
SAVE_OPLINE();
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) {
- var_ptr = GET_OP1_UNDEF_CV(var_ptr, BP_VAR_RW);
+ ZVAL_NULL(var_ptr);
+ ZVAL_UNDEFINED_OP1();
}
- ZVAL_DEREF(var_ptr);
- decrement_function(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);
@@ -1284,7 +1605,7 @@ ZEND_VM_HANDLER(35, ZEND_PRE_DEC, VAR|CV, ANY, SPEC(RETVAL))
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(36, ZEND_POST_INC, VAR|CV, ANY)
+ZEND_VM_HOT_HANDLER(35, ZEND_PRE_DEC, VAR|CV, ANY, SPEC(RETVAL))
{
USE_OPLINE
zend_free_op free_op1;
@@ -1293,11 +1614,24 @@ ZEND_VM_HANDLER(36, ZEND_POST_INC, VAR|CV, ANY)
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);
+ 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
+ zend_free_op free_op1;
+ zval *var_ptr;
+
+ var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
+
if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) {
ZVAL_NULL(EX_VAR(opline->result.var));
ZEND_VM_NEXT_OPCODE();
@@ -1305,18 +1639,30 @@ ZEND_VM_HANDLER(36, ZEND_POST_INC, VAR|CV, ANY)
SAVE_OPLINE();
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) {
- var_ptr = GET_OP1_UNDEF_CV(var_ptr, BP_VAR_RW);
+ ZVAL_NULL(var_ptr);
+ ZVAL_UNDEFINED_OP1();
}
- ZVAL_DEREF(var_ptr);
- ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
- increment_function(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_VAR_PTR();
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(37, ZEND_POST_DEC, VAR|CV, ANY)
+ZEND_VM_HOT_HANDLER(36, ZEND_POST_INC, VAR|CV, ANY)
{
USE_OPLINE
zend_free_op free_op1;
@@ -1326,10 +1672,21 @@ ZEND_VM_HANDLER(37, ZEND_POST_DEC, VAR|CV, ANY)
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);
+ 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
+ zend_free_op free_op1;
+ zval *var_ptr;
+
+ var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
+
if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) {
ZVAL_NULL(EX_VAR(opline->result.var));
ZEND_VM_NEXT_OPCODE();
@@ -1337,18 +1694,47 @@ ZEND_VM_HANDLER(37, ZEND_POST_DEC, VAR|CV, ANY)
SAVE_OPLINE();
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) {
- var_ptr = GET_OP1_UNDEF_CV(var_ptr, BP_VAR_RW);
+ ZVAL_NULL(var_ptr);
+ ZVAL_UNDEFINED_OP1();
}
- ZVAL_DEREF(var_ptr);
- ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
- decrement_function(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_VAR_PTR();
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(40, ZEND_ECHO, CONST|TMPVAR|CV, ANY)
+ZEND_VM_HOT_HANDLER(37, ZEND_POST_DEC, VAR|CV, ANY)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ 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
zend_free_op free_op1;
@@ -1369,7 +1755,7 @@ ZEND_VM_HANDLER(40, ZEND_ECHO, CONST|TMPVAR|CV, ANY)
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)) {
- GET_OP1_UNDEF_CV(z, BP_VAR_R);
+ ZVAL_UNDEFINED_OP1();
}
zend_string_release_ex(str, 0);
}
@@ -1397,9 +1783,14 @@ ZEND_VM_HELPER(zend_fetch_var_address_helper, CONST|TMPVAR|CV, UNUSED, int type)
tmp_name = NULL;
} else {
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) {
- GET_OP1_UNDEF_CV(varname, BP_VAR_R);
+ ZVAL_UNDEFINED_OP1();
+ }
+ name = zval_try_get_tmp_string(varname, &tmp_name);
+ if (UNEXPECTED(!name)) {
+ FREE_OP1();
+ ZVAL_UNDEF(EX_VAR(opline->result.var));
+ HANDLE_EXCEPTION();
}
- name = zval_get_tmp_string(varname, &tmp_name);
}
target_symbol_table = zend_get_target_symbol_table(opline->extended_value EXECUTE_DATA_CC);
@@ -1497,115 +1888,47 @@ 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);
}
-ZEND_VM_HELPER(zend_fetch_static_prop_helper, CONST|TMPVAR|CV, UNUSED|CONST|VAR, int type)
+/* 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
- zend_free_op free_op1;
- zval *varname;
- zval *retval;
- zend_string *name, *tmp_name;
- zend_class_entry *ce;
+ zval *prop;
SAVE_OPLINE();
- do {
- if (OP2_TYPE == IS_CONST) {
- if (OP1_TYPE == IS_CONST && EXPECTED((ce = CACHED_PTR(opline->extended_value)) != NULL)) {
- retval = CACHED_PTR(opline->extended_value + sizeof(void*));
- break;
- } else {
- zval *class_name = RT_CONSTANT(opline, opline->op2);
-
- if (UNEXPECTED((ce = CACHED_PTR(opline->extended_value)) == NULL)) {
- ce = zend_fetch_class_by_name(Z_STR_P(class_name), class_name + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(ce == NULL)) {
- FREE_UNFETCHED_OP1();
- retval = NULL;
- break;
- }
- if (OP1_TYPE != IS_CONST) {
- CACHE_PTR(opline->extended_value, ce);
- }
- }
- }
- } else {
- if (OP2_TYPE == IS_UNUSED) {
- ce = zend_fetch_class(NULL, opline->op2.num);
- if (UNEXPECTED(ce == NULL)) {
- FREE_UNFETCHED_OP1();
- retval = NULL;
- break;
- }
- } else {
- ce = Z_CE_P(EX_VAR(opline->op2.var));
- }
- if (OP1_TYPE == IS_CONST &&
- EXPECTED(CACHED_PTR(opline->extended_value) == ce)) {
- retval = CACHED_PTR(opline->extended_value + sizeof(void*));
- break;
- }
- }
-
- 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_cv(EX(opline)->op1.var EXECUTE_DATA_CC);
- }
- name = zval_get_tmp_string(varname, &tmp_name);
- }
-
- retval = zend_std_get_static_property(ce, name, type == BP_VAR_IS);
-
- if (OP1_TYPE != IS_CONST) {
- zend_tmp_string_release(tmp_name);
- }
-
- if (OP1_TYPE == IS_CONST && EXPECTED(retval)) {
- CACHE_POLYMORPHIC_PTR(opline->extended_value, ce, retval);
- }
-
- FREE_OP1();
- } while (0);
-
- if (UNEXPECTED(retval == NULL)) {
- if (EG(exception)) {
- ZVAL_UNDEF(EX_VAR(opline->result.var));
- HANDLE_EXCEPTION();
- } else {
- ZEND_ASSERT(type == BP_VAR_IS);
- retval = &EG(uninitialized_zval);
- }
+ if (UNEXPECTED(zend_fetch_static_property_address(&prop, NULL, opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS, type, opline->extended_value & ZEND_FETCH_OBJ_FLAGS 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), retval);
+ ZVAL_COPY_DEREF(EX_VAR(opline->result.var), prop);
} else {
- ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
+ ZVAL_INDIRECT(EX_VAR(opline->result.var), prop);
}
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(173, ZEND_FETCH_STATIC_PROP_R, CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR, CACHE_SLOT)
+/* 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);
}
-ZEND_VM_HANDLER(174, ZEND_FETCH_STATIC_PROP_W, CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR, CACHE_SLOT)
+/* 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_OBJ_WRITE|CACHE_SLOT)
{
ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper, type, BP_VAR_W);
}
-ZEND_VM_HANDLER(175, ZEND_FETCH_STATIC_PROP_RW, CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR, CACHE_SLOT)
+/* 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);
}
-ZEND_VM_HANDLER(177, ZEND_FETCH_STATIC_PROP_FUNC_ARG, CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR, CACHE_SLOT)
+/* 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)) ?
@@ -1613,12 +1936,14 @@ ZEND_VM_HANDLER(177, ZEND_FETCH_STATIC_PROP_FUNC_ARG, CONST|TMPVAR|CV, UNUSED|CL
ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper, type, fetch_type);
}
-ZEND_VM_HANDLER(178, ZEND_FETCH_STATIC_PROP_UNSET, CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR, CACHE_SLOT)
+/* 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);
}
-ZEND_VM_HANDLER(176, ZEND_FETCH_STATIC_PROP_IS, CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR, CACHE_SLOT)
+/* 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);
}
@@ -1627,7 +1952,7 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(81, ZEND_FETCH_DIM_R, CONST|TMPVAR|CV, CONST|TMP
{
USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *container, *dim, *value, *result;
+ zval *container, *dim, *value;
SAVE_OPLINE();
container = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
@@ -1636,8 +1961,7 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(81, ZEND_FETCH_DIM_R, CONST|TMPVAR|CV, CONST|TMP
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);
- result = EX_VAR(opline->result.var);
- ZVAL_COPY_DEREF(result, value);
+ 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)) {
@@ -1734,6 +2058,10 @@ ZEND_VM_COLD_HELPER(zend_use_undef_in_read_context_helper, ANY, ANY)
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);
@@ -1792,12 +2120,14 @@ ZEND_VM_HOT_OBJ_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMPVAR|UNUSED|THIS|CV, CONST
}
}
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
- GET_OP1_UNDEF_CV(container, BP_VAR_R);
+ ZVAL_UNDEFINED_OP1();
}
if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) {
- GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ ZVAL_UNDEFINED_OP2();
}
- ZEND_VM_C_GOTO(fetch_obj_r_no_object);
+ zend_wrong_property_read(offset);
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ ZEND_VM_C_GOTO(fetch_obj_r_finish);
} while (0);
}
@@ -1807,7 +2137,7 @@ ZEND_VM_HOT_OBJ_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMPVAR|UNUSED|THIS|CV, CONST
zval *retval;
if (OP2_TYPE == IS_CONST) {
- cache_slot = CACHE_ADDR(opline->extended_value);
+ 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);
@@ -1815,8 +2145,13 @@ ZEND_VM_HOT_OBJ_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMPVAR|UNUSED|THIS|CV, CONST
if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) {
retval = OBJ_PROP(zobj, prop_offset);
if (EXPECTED(Z_TYPE_INFO_P(retval) != IS_UNDEF)) {
- ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval);
- break;
+ 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)) {
if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) {
@@ -1830,8 +2165,12 @@ ZEND_VM_HOT_OBJ_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMPVAR|UNUSED|THIS|CV, CONST
(EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) &&
EXPECTED(p->key != NULL) &&
EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) {
- ZVAL_COPY_DEREF(EX_VAR(opline->result.var), &p->val);
- break;
+ 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);
@@ -1840,36 +2179,35 @@ ZEND_VM_HOT_OBJ_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMPVAR|UNUSED|THIS|CV, CONST
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));
- ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval);
- break;
+ 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);
+ }
}
}
}
} else if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(offset) == IS_UNDEF)) {
- GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ ZVAL_UNDEFINED_OP2();
}
- if (UNEXPECTED(zobj->handlers->read_property == NULL)) {
-ZEND_VM_C_LABEL(fetch_obj_r_no_object):
- zend_wrong_property_read(offset);
- ZVAL_NULL(EX_VAR(opline->result.var));
- } else {
- retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var));
+ retval = zobj->handlers->read_property(container, offset, BP_VAR_R, cache_slot, EX_VAR(opline->result.var));
- if (retval != EX_VAR(opline->result.var)) {
- ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval);
- } else if (UNEXPECTED(Z_ISREF_P(retval))) {
- zend_unwrap_reference(retval);
- }
+ 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, CACHE_SLOT)
+ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, FETCH_REF|DIM_OBJ_WRITE|CACHE_SLOT)
{
USE_OPLINE
zend_free_op free_op1, free_op2;
@@ -1884,7 +2222,10 @@ ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE
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_W OPLINE_CC);
+ 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 & ZEND_FETCH_OBJ_FLAGS, 1 OPLINE_CC EXECUTE_DATA_CC);
FREE_OP2();
if (OP1_TYPE == IS_VAR) {
FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op1, result);
@@ -1899,14 +2240,14 @@ ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACH
zval *property, *container, *result;
SAVE_OPLINE();
- container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW);
+ container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
}
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 OPLINE_CC);
+ 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(free_op1, result);
@@ -1941,7 +2282,8 @@ ZEND_VM_COLD_CONST_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMPVAR|UNUSED|THIS|CV, C
break;
}
}
- ZEND_VM_C_GOTO(fetch_obj_is_no_object);
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ ZEND_VM_C_GOTO(fetch_obj_is_finish);
} while (0);
}
@@ -1959,8 +2301,13 @@ ZEND_VM_COLD_CONST_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMPVAR|UNUSED|THIS|CV, C
if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) {
retval = OBJ_PROP(zobj, prop_offset);
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
- ZVAL_COPY(EX_VAR(opline->result.var), retval);
- break;
+ 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)) {
if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) {
@@ -1974,8 +2321,12 @@ ZEND_VM_COLD_CONST_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMPVAR|UNUSED|THIS|CV, C
(EXPECTED(p->h == ZSTR_H(Z_STR_P(offset))) &&
EXPECTED(p->key != NULL) &&
EXPECTED(zend_string_equal_content(p->key, Z_STR_P(offset)))))) {
- ZVAL_COPY(EX_VAR(opline->result.var), &p->val);
- break;
+ 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);
@@ -1984,39 +2335,43 @@ ZEND_VM_COLD_CONST_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMPVAR|UNUSED|THIS|CV, C
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));
- ZVAL_COPY(EX_VAR(opline->result.var), retval);
- break;
+ 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);
+ }
}
}
}
}
- if (UNEXPECTED(zobj->handlers->read_property == NULL)) {
-ZEND_VM_C_LABEL(fetch_obj_is_no_object):
- ZVAL_NULL(EX_VAR(opline->result.var));
- } else {
-
- retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var));
+ retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var));
- if (retval != EX_VAR(opline->result.var)) {
- ZVAL_COPY(EX_VAR(opline->result.var), retval);
- }
+ 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, CACHE_SLOT)
+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);
@@ -2030,7 +2385,7 @@ ZEND_VM_HANDLER(97, ZEND_FETCH_OBJ_UNSET, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, C
zval *container, *property, *result;
SAVE_OPLINE();
- container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET);
+ container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_UNSET);
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
@@ -2038,7 +2393,7 @@ ZEND_VM_HANDLER(97, ZEND_FETCH_OBJ_UNSET, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, C
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 OPLINE_CC);
+ 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(free_op1, result);
@@ -2059,7 +2414,7 @@ ZEND_VM_HANDLER(98, ZEND_FETCH_LIST_R, CONST|TMPVARCV, CONST|TMPVAR|CV)
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(198, ZEND_FETCH_LIST_W, VAR, CONST|TMPVAR|CV)
+ZEND_VM_HANDLER(155, ZEND_FETCH_LIST_W, VAR, CONST|TMPVAR|CV)
{
USE_OPLINE
zend_free_op free_op1, free_op2;
@@ -2083,7 +2438,7 @@ ZEND_VM_HANDLER(198, ZEND_FETCH_LIST_W, VAR, CONST|TMPVAR|CV)
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(136, ZEND_ASSIGN_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT, SPEC(OP_DATA=CONST|TMP|VAR|CV))
+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
zend_free_op free_op1, free_op2, free_op_data;
@@ -2100,34 +2455,52 @@ ZEND_VM_HANDLER(136, ZEND_ASSIGN_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE
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)) {
+ if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) {
object = Z_REFVAL_P(object);
- if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
- ZEND_VM_C_GOTO(assign_object);
- }
+ ZEND_VM_C_GOTO(assign_object);
}
- if (UNEXPECTED(!make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC))) {
- FREE_OP_DATA();
- ZEND_VM_C_GOTO(exit_assign_obj);
+ object = make_real_object(object, property OPLINE_CC EXECUTE_DATA_CC);
+ if (UNEXPECTED(!object)) {
+ value = &EG(uninitialized_zval);
+ ZEND_VM_C_GOTO(free_and_exit_assign_obj);
}
}
ZEND_VM_C_LABEL(assign_object):
if (OP2_TYPE == IS_CONST &&
EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(opline->extended_value))) {
- uintptr_t prop_offset = (uintptr_t)CACHED_PTR(opline->extended_value + sizeof(void*));
+ void **cache_slot = CACHE_ADDR(opline->extended_value);
+ uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1);
zend_object *zobj = Z_OBJ_P(object);
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)) {
+ zend_uchar orig_type = IS_UNDEF;
+
+ if (OP_DATA_TYPE == IS_CONST) {
+ orig_type = Z_TYPE_P(value);
+ }
+
+ value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC);
+
+ /* will remain valid, thus no need to check prop_info in future here */
+ if (OP_DATA_TYPE == IS_CONST && Z_TYPE_P(value) == orig_type) {
+ CACHE_PTR_EX(cache_slot + 2, NULL);
+ }
+ 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);
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_COPY(EX_VAR(opline->result.var), value);
+ 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);
}
- ZEND_VM_C_GOTO(exit_assign_obj);
}
} else {
if (EXPECTED(zobj->properties != NULL)) {
@@ -2181,18 +2554,13 @@ ZEND_VM_C_LABEL(fast_assign_obj):
}
}
- if (!Z_OBJ_HT_P(object)->write_property) {
- zend_wrong_property_assignment(property OPLINE_CC EXECUTE_DATA_CC);
- FREE_OP_DATA();
- ZEND_VM_C_GOTO(exit_assign_obj);
- }
-
if (OP_DATA_TYPE == IS_CV || OP_DATA_TYPE == IS_VAR) {
ZVAL_DEREF(value);
}
- Z_OBJ_HT_P(object)->write_property(object, property, value, (OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL);
+ value = Z_OBJ_HT_P(object)->write_property(object, property, value, (OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL);
+ZEND_VM_C_LABEL(free_and_exit_assign_obj):
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_COPY(EX_VAR(opline->result.var), value);
}
@@ -2204,30 +2572,62 @@ ZEND_VM_C_LABEL(exit_assign_obj):
ZEND_VM_NEXT_OPCODE_EX(1, 2);
}
-ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV, SPEC(OP_DATA=CONST|TMP|VAR|CV))
+/* 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
+ zend_free_op free_op_data;
+ 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_UNFETCHED_OP_DATA();
+ UNDEF_RESULT();
+ HANDLE_EXCEPTION();
+ }
+
+ value = GET_OP_DATA_ZVAL_PTR(BP_VAR_R);
+
+ if (UNEXPECTED(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
zend_free_op free_op1;
- zval *object_ptr;
+ zval *object_ptr, *orig_object_ptr;
zend_free_op free_op2, free_op_data;
zval *value;
zval *variable_ptr;
zval *dim;
SAVE_OPLINE();
- object_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
+ 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):
+ value = GET_OP_DATA_ZVAL_PTR(BP_VAR_R);
SEPARATE_ARRAY(object_ptr);
if (OP2_TYPE == IS_UNUSED) {
- value = GET_OP_DATA_ZVAL_PTR(BP_VAR_R);
if (OP_DATA_TYPE == IS_CV || OP_DATA_TYPE == IS_VAR) {
ZVAL_DEREF(value);
}
variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value);
if (UNEXPECTED(variable_ptr == NULL)) {
- FREE_OP_DATA();
zend_cannot_add_element();
ZEND_VM_C_GOTO(assign_dim_error);
} else if (OP_DATA_TYPE == IS_CV) {
@@ -2256,8 +2656,7 @@ ZEND_VM_C_LABEL(try_assign_dim_array):
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);
+ 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);
@@ -2283,9 +2682,7 @@ ZEND_VM_C_LABEL(try_assign_dim_array):
if (OP2_TYPE == IS_UNUSED) {
zend_use_new_element_for_string();
FREE_UNFETCHED_OP_DATA();
- FREE_OP1_VAR_PTR();
UNDEF_RESULT();
- HANDLE_EXCEPTION();
} else {
dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
value = GET_OP_DATA_ZVAL_PTR_DEREF(BP_VAR_R);
@@ -2293,8 +2690,16 @@ ZEND_VM_C_LABEL(try_assign_dim_array):
FREE_OP_DATA();
}
} else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) {
- ZVAL_ARR(object_ptr, zend_new_array(8));
- ZEND_VM_C_GOTO(try_assign_dim_array);
+ 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_UNFETCHED_OP_DATA();
+ UNDEF_RESULT();
+ } else {
+ ZVAL_ARR(object_ptr, zend_new_array(8));
+ ZEND_VM_C_GOTO(try_assign_dim_array);
+ }
} else {
if (OP1_TYPE != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) {
zend_use_scalar_as_array();
@@ -2315,7 +2720,7 @@ ZEND_VM_C_LABEL(assign_dim_error):
ZEND_VM_NEXT_OPCODE_EX(1, 2);
}
-ZEND_VM_HANDLER(38, ZEND_ASSIGN, VAR|CV, CONST|TMP|VAR|CV, SPEC(RETVAL))
+ZEND_VM_HANDLER(22, ZEND_ASSIGN, VAR|CV, CONST|TMP|VAR|CV, SPEC(RETVAL))
{
USE_OPLINE
zend_free_op free_op1, free_op2;
@@ -2332,7 +2737,7 @@ ZEND_VM_HANDLER(38, ZEND_ASSIGN, VAR|CV, CONST|TMP|VAR|CV, SPEC(RETVAL))
ZVAL_NULL(EX_VAR(opline->result.var));
}
} else {
- value = zend_assign_to_variable(variable_ptr, value, OP2_TYPE);
+ 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);
}
@@ -2343,7 +2748,7 @@ ZEND_VM_HANDLER(38, ZEND_ASSIGN, VAR|CV, CONST|TMP|VAR|CV, SPEC(RETVAL))
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV, SRC)
+ZEND_VM_HANDLER(30, ZEND_ASSIGN_REF, VAR|CV, VAR|CV, SRC)
{
USE_OPLINE
zend_free_op free_op1, free_op2;
@@ -2359,26 +2764,17 @@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV, SRC)
} else 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 overloaded object");
- FREE_OP1_VAR_PTR();
- FREE_OP2_VAR_PTR();
- UNDEF_RESULT();
- HANDLE_EXCEPTION();
+ 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 && UNEXPECTED(Z_ISERROR_P(value_ptr))) {
variable_ptr = &EG(uninitialized_zval);
} else if (OP2_TYPE == IS_VAR &&
opline->extended_value == ZEND_RETURNS_FUNCTION &&
UNEXPECTED(!Z_ISREF_P(value_ptr))) {
- if (UNEXPECTED(!zend_wrong_assign_to_variable_reference(variable_ptr, value_ptr, OP2_TYPE OPLINE_CC EXECUTE_DATA_CC))) {
- FREE_OP2_VAR_PTR();
- UNDEF_RESULT();
- HANDLE_EXCEPTION();
+ if (UNEXPECTED(!zend_wrong_assign_to_variable_reference(variable_ptr, value_ptr OPLINE_CC EXECUTE_DATA_CC))) {
+ variable_ptr = &EG(uninitialized_zval);
}
-
- /* op2 freed by assign_to_variable */
- FREE_OP1_VAR_PTR();
- ZEND_VM_NEXT_OPCODE();
} else {
zend_assign_to_variable_reference(variable_ptr, value_ptr);
}
@@ -2392,26 +2788,101 @@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV, SRC)
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
+ zend_free_op free_op1, free_op2, free_op_data;
+ zval *property, *container, *value_ptr;
+
+ SAVE_OPLINE();
+
+ container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
+
+ if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
+ ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
+ }
+
+ 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_VAR_PTR();
+ FREE_OP2();
+ FREE_OP_DATA_VAR_PTR();
+ 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
+ zend_free_op free_op_data;
+ 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_UNFETCHED_OP_DATA();
+ UNDEF_RESULT();
+ HANDLE_EXCEPTION();
+ }
+
+ value_ptr = GET_OP_DATA_ZVAL_PTR_PTR(BP_VAR_W);
+
+ if (OP_DATA_TYPE == IS_VAR && UNEXPECTED(Z_ISERROR_P(value_ptr))) {
+ prop = &EG(uninitialized_zval);
+ } else 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(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_VAR_PTR();
+ 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)) == 0)) {
EG(current_execute_data) = EX(prev_execute_data);
i_free_compiled_variables(execute_data);
- if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) {
- zend_object *object = Z_OBJ(execute_data->This);
-#if 0
- if (UNEXPECTED(EG(exception) != NULL) && (EX(opline)->op1.num & ZEND_CALL_CTOR)) {
-#else
- if (UNEXPECTED(EG(exception) != NULL) && (call_info & ZEND_CALL_CTOR)) {
+#ifdef ZEND_PREFER_RELOAD
+ call_info = EX_CALL_INFO();
#endif
- GC_DELREF(object);
- zend_object_store_ctor_failed(object);
- }
- OBJ_RELEASE(object);
+ 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)));
}
@@ -2429,6 +2900,9 @@ ZEND_VM_HOT_HELPER(zend_leave_helper, ANY, ANY)
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));
}
@@ -2438,16 +2912,7 @@ ZEND_VM_HOT_HELPER(zend_leave_helper, ANY, ANY)
zend_vm_stack_free_extra_args_ex(call_info, execute_data);
if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) {
- zend_object *object = Z_OBJ(execute_data->This);
-#if 0
- if (UNEXPECTED(EG(exception) != NULL) && (EX(opline)->op1.num & ZEND_CALL_CTOR)) {
-#else
- if (UNEXPECTED(EG(exception) != NULL) && (call_info & ZEND_CALL_CTOR)) {
-#endif
- GC_DELREF(object);
- zend_object_store_ctor_failed(object);
- }
- OBJ_RELEASE(object);
+ OBJ_RELEASE(Z_OBJ(execute_data->This));
} else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func)));
}
@@ -2467,6 +2932,9 @@ ZEND_VM_HOT_HELPER(zend_leave_helper, ANY, ANY)
zend_detach_symbol_table(execute_data);
destroy_op_array(&EX(func)->op_array);
efree_size(EX(func), sizeof(zend_op_array));
+#ifdef ZEND_PREFER_RELOAD
+ call_info = EX_CALL_INFO();
+#endif
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);
@@ -2483,6 +2951,9 @@ ZEND_VM_HOT_HELPER(zend_leave_helper, ANY, ANY)
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))) {
if (UNEXPECTED(call_info & ZEND_CALL_HAS_SYMBOL_TABLE)) {
zend_clean_and_cache_symbol_table(EX(symbol_table));
@@ -2533,7 +3004,7 @@ ZEND_VM_HOT_NOCONST_HANDLER(43, ZEND_JMPZ, CONST|TMPVAR|CV, JMP_ADDR)
} 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();
- GET_OP1_UNDEF_CV(val, BP_VAR_R);
+ ZVAL_UNDEFINED_OP1();
if (UNEXPECTED(EG(exception))) {
HANDLE_EXCEPTION();
}
@@ -2564,7 +3035,7 @@ ZEND_VM_HOT_NOCONST_HANDLER(44, ZEND_JMPNZ, CONST|TMPVAR|CV, JMP_ADDR)
} 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();
- GET_OP1_UNDEF_CV(val, BP_VAR_R);
+ ZVAL_UNDEFINED_OP1();
if (UNEXPECTED(EG(exception))) {
HANDLE_EXCEPTION();
}
@@ -2582,7 +3053,7 @@ ZEND_VM_HOT_NOCONST_HANDLER(44, ZEND_JMPNZ, CONST|TMPVAR|CV, JMP_ADDR)
ZEND_VM_JMP(opline);
}
-ZEND_VM_HOT_NOCONST_HANDLER(45, ZEND_JMPZNZ, CONST|TMPVAR|CV, JMP_ADDR, JMP_ADDR)
+ZEND_VM_HANDLER(45, ZEND_JMPZNZ, CONST|TMPVAR|CV, JMP_ADDR, JMP_ADDR)
{
USE_OPLINE
zend_free_op free_op1;
@@ -2596,7 +3067,7 @@ ZEND_VM_HOT_NOCONST_HANDLER(45, ZEND_JMPZNZ, CONST|TMPVAR|CV, JMP_ADDR, JMP_ADDR
} 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();
- GET_OP1_UNDEF_CV(val, BP_VAR_R);
+ ZVAL_UNDEFINED_OP1();
if (UNEXPECTED(EG(exception))) {
HANDLE_EXCEPTION();
}
@@ -2630,7 +3101,7 @@ ZEND_VM_COLD_CONST_HANDLER(46, ZEND_JMPZ_EX, CONST|TMPVAR|CV, JMP_ADDR)
ZVAL_FALSE(EX_VAR(opline->result.var));
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) {
SAVE_OPLINE();
- GET_OP1_UNDEF_CV(val, BP_VAR_R);
+ ZVAL_UNDEFINED_OP1();
if (UNEXPECTED(EG(exception))) {
HANDLE_EXCEPTION();
}
@@ -2667,7 +3138,7 @@ ZEND_VM_COLD_CONST_HANDLER(47, ZEND_JMPNZ_EX, CONST|TMPVAR|CV, JMP_ADDR)
ZVAL_FALSE(EX_VAR(opline->result.var));
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) {
SAVE_OPLINE();
- GET_OP1_UNDEF_CV(val, BP_VAR_R);
+ ZVAL_UNDEFINED_OP1();
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
} else {
ZEND_VM_NEXT_OPCODE();
@@ -2732,14 +3203,18 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(53, ZEND_FAST_CONCAT, CONST|TMPVAR|CV, CONST|TMP
} else {
ZVAL_STR(EX_VAR(opline->result.var), op2_str);
}
- FREE_OP1();
+ 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);
}
- FREE_OP2();
+ 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);
@@ -2747,14 +3222,20 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(53, ZEND_FAST_CONCAT, CONST|TMPVAR|CV, CONST|TMP
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);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
- FREE_OP2();
+ 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);
ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
- FREE_OP1();
- FREE_OP2();
+ 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();
}
@@ -2766,7 +3247,7 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(53, ZEND_FAST_CONCAT, CONST|TMPVAR|CV, CONST|TMP
op1_str = zend_string_copy(Z_STR_P(op1));
} else {
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
- GET_OP1_UNDEF_CV(op1, BP_VAR_R);
+ ZVAL_UNDEFINED_OP1();
}
op1_str = zval_get_string_func(op1);
}
@@ -2776,7 +3257,7 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(53, ZEND_FAST_CONCAT, CONST|TMPVAR|CV, CONST|TMP
op2_str = zend_string_copy(Z_STR_P(op2));
} else {
if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
- GET_OP2_UNDEF_CV(op2, BP_VAR_R);
+ ZVAL_UNDEFINED_OP2();
}
op2_str = zval_get_string_func(op2);
}
@@ -2847,7 +3328,7 @@ ZEND_VM_HANDLER(54, ZEND_ROPE_INIT, UNUSED, CONST|TMPVAR|CV, NUM)
} else {
SAVE_OPLINE();
if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) {
- GET_OP2_UNDEF_CV(var, BP_VAR_R);
+ ZVAL_UNDEFINED_OP2();
}
rope[0] = zval_get_string_func(var);
FREE_OP2();
@@ -2883,7 +3364,7 @@ ZEND_VM_HANDLER(55, ZEND_ROPE_ADD, TMP, CONST|TMPVAR|CV, NUM)
} else {
SAVE_OPLINE();
if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) {
- GET_OP2_UNDEF_CV(var, BP_VAR_R);
+ ZVAL_UNDEFINED_OP2();
}
rope[opline->extended_value] = zval_get_string_func(var);
FREE_OP2();
@@ -2921,7 +3402,7 @@ ZEND_VM_HANDLER(56, ZEND_ROPE_END, TMP, CONST|TMPVAR|CV, NUM)
} else {
SAVE_OPLINE();
if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) {
- GET_OP2_UNDEF_CV(var, BP_VAR_R);
+ ZVAL_UNDEFINED_OP2();
}
rope[opline->extended_value] = zval_get_string_func(var);
FREE_OP2();
@@ -2965,7 +3446,7 @@ ZEND_VM_HANDLER(109, ZEND_FETCH_CLASS, UNUSED|CLASS_FETCH, CONST|TMPVAR|UNUSED|C
if (UNEXPECTED(ce == NULL)) {
class_name = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
- ce = zend_fetch_class_by_name(Z_STR_P(class_name), class_name + 1, opline->op1.num);
+ ce = zend_fetch_class_by_name(Z_STR_P(class_name), Z_STR_P(class_name + 1), opline->op1.num);
CACHE_PTR(opline->extended_value, ce);
}
Z_CE_P(EX_VAR(opline->result.var)) = ce;
@@ -2981,7 +3462,7 @@ ZEND_VM_C_LABEL(try_class_name):
ZEND_VM_C_GOTO(try_class_name);
} else {
if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(class_name) == IS_UNDEF)) {
- GET_OP2_UNDEF_CV(class_name, BP_VAR_R);
+ ZVAL_UNDEFINED_OP2();
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -3027,7 +3508,7 @@ ZEND_VM_HOT_OBJ_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|THIS|CV,
break;
}
} else if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
- GET_OP2_UNDEF_CV(function_name, BP_VAR_R);
+ ZVAL_UNDEFINED_OP2();
if (UNEXPECTED(EG(exception) != NULL)) {
FREE_OP1();
HANDLE_EXCEPTION();
@@ -3050,7 +3531,7 @@ ZEND_VM_HOT_OBJ_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|THIS|CV,
}
}
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
- object = GET_OP1_UNDEF_CV(object, BP_VAR_R);
+ object = ZVAL_UNDEFINED_OP1();
if (UNEXPECTED(EG(exception) != NULL)) {
if (OP2_TYPE != IS_CONST) {
FREE_OP2();
@@ -3078,13 +3559,6 @@ ZEND_VM_HOT_OBJ_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|THIS|CV,
} else {
zend_object *orig_obj = obj;
- if (UNEXPECTED(obj->handlers->get_method == NULL)) {
- zend_throw_error(NULL, "Object does not support method calls");
- FREE_OP2();
- FREE_OP1();
- HANDLE_EXCEPTION();
- }
-
if (OP2_TYPE == IS_CONST) {
function_name = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
}
@@ -3109,7 +3583,7 @@ ZEND_VM_HOT_OBJ_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|THIS|CV,
/* Reset "object" to trigger reference counting */
object = NULL;
}
- if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
+ if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
}
@@ -3118,27 +3592,29 @@ ZEND_VM_HOT_OBJ_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|THIS|CV,
FREE_OP2();
}
- call_info = ZEND_CALL_NESTED_FUNCTION;
+ call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
- obj = NULL;
FREE_OP1();
if ((OP1_TYPE & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(EG(exception))) {
HANDLE_EXCEPTION();
}
+ /* call static method */
+ obj = (zend_object*)called_scope;
+ call_info = ZEND_CALL_NESTED_FUNCTION;
} else if (OP1_TYPE & (IS_VAR|IS_TMP_VAR|IS_CV)) {
- /* CV may be changed indirectly (e.g. when it's a reference) */
- call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS;
if (OP1_TYPE == IS_CV) {
GC_ADDREF(obj); /* For $this pointer */
} else if (free_op1 != object) {
GC_ADDREF(obj); /* For $this pointer */
FREE_OP1();
}
+ /* CV may be changed indirectly (e.g. when it's a reference) */
+ call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS;
}
call = zend_vm_stack_push_call_frame(call_info,
- fbc, opline->extended_value, called_scope, obj);
+ fbc, opline->extended_value, obj);
call->prev_execute_data = EX(call);
EX(call) = call;
@@ -3150,7 +3626,7 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR,
USE_OPLINE
zval *function_name;
zend_class_entry *ce;
- zend_object *object;
+ uint32_t call_info;
zend_function *fbc;
zend_execute_data *call;
@@ -3160,7 +3636,7 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR,
/* no function found. try a static method in class */
ce = CACHED_PTR(opline->result.num);
if (UNEXPECTED(ce == NULL)) {
- ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), RT_CONSTANT(opline, opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+ ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
if (UNEXPECTED(ce == NULL)) {
ZEND_ASSERT(EG(exception));
FREE_UNFETCHED_OP2();
@@ -3202,7 +3678,7 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR,
break;
}
} else if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
- GET_OP2_UNDEF_CV(function_name, BP_VAR_R);
+ ZVAL_UNDEFINED_OP2();
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -3231,7 +3707,7 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR,
EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc);
}
- if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
+ if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
if (OP2_TYPE != IS_CONST) {
@@ -3247,38 +3723,39 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR,
HANDLE_EXCEPTION();
}
fbc = ce->constructor;
- if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
+ if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
}
- object = NULL;
if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) {
- object = Z_OBJ(EX(This));
- ce = object->ce;
+ ce = (zend_class_entry*)Z_OBJ(EX(This));
+ call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
} else {
zend_non_static_method_call(fbc);
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
+ ZEND_VM_C_GOTO(check_parent_and_self);
}
- }
-
- if (OP1_TYPE == IS_UNUSED) {
+ } else {
+ZEND_VM_C_LABEL(check_parent_and_self):
/* previous opcode is ZEND_FETCH_CLASS */
- if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
- (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+ if (OP1_TYPE == IS_UNUSED
+ && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
+ (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) {
if (Z_TYPE(EX(This)) == IS_OBJECT) {
ce = Z_OBJCE(EX(This));
} else {
ce = Z_CE(EX(This));
}
}
+ call_info = ZEND_CALL_NESTED_FUNCTION;
}
- call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
- fbc, opline->extended_value, ce, object);
+ call = zend_vm_stack_push_call_frame(call_info,
+ fbc, opline->extended_value, ce);
call->prev_execute_data = EX(call);
EX(call) = call;
@@ -3297,16 +3774,16 @@ ZEND_VM_HOT_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST, NUM|CACHE_SLOT)
function_name = (zval*)RT_CONSTANT(opline, opline->op2);
func = zend_hash_find_ex(EG(function_table), Z_STR_P(function_name+1), 1);
if (UNEXPECTED(func == NULL)) {
- ZEND_VM_DISPATCH_TO_HELPER(zend_undefined_function_helper, function_name, function_name);
+ ZEND_VM_DISPATCH_TO_HELPER(zend_undefined_function_helper);
}
fbc = Z_FUNC_P(func);
- if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
- fbc = init_func_run_time_cache_ex(func);
+ if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
+ init_func_run_time_cache(&fbc->op_array);
}
CACHE_PTR(opline->result.num, fbc);
}
- call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
- fbc, opline->extended_value, NULL, NULL);
+ call = _zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
+ fbc, opline->extended_value, NULL);
call->prev_execute_data = EX(call);
EX(call) = call;
@@ -3335,7 +3812,7 @@ ZEND_VM_C_LABEL(try_function_name):
ZEND_VM_C_GOTO(try_function_name);
} else {
if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
- GET_OP2_UNDEF_CV(function_name, BP_VAR_R);
+ ZVAL_UNDEFINED_OP2();
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -3376,8 +3853,7 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM)
zend_fcall_info_cache fcc;
char *error = NULL;
zend_function *func;
- zend_class_entry *called_scope;
- zend_object *object;
+ void *object_or_called_scope;
zend_execute_data *call;
uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC;
@@ -3385,8 +3861,6 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM)
function_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) {
func = fcc.function_handler;
- called_scope = fcc.called_scope;
- object = fcc.object;
if (error) {
efree(error);
/* This is the only soft error is_callable() can generate */
@@ -3396,6 +3870,7 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM)
HANDLE_EXCEPTION();
}
}
+ object_or_called_scope = fcc.called_scope;
if (func->common.fn_flags & ZEND_ACC_CLOSURE) {
/* Delay closure destruction until its invocation */
GC_ADDREF(ZEND_CLOSURE_OBJECT(func));
@@ -3403,23 +3878,27 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM)
if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) {
call_info |= ZEND_CALL_FAKE_CLOSURE;
}
- } else if (object) {
- call_info |= ZEND_CALL_RELEASE_THIS;
- GC_ADDREF(object); /* For $this pointer */
+ if (fcc.object) {
+ object_or_called_scope = fcc.object;
+ call_info |= ZEND_CALL_HAS_THIS;
+ }
+ } else if (fcc.object) {
+ GC_ADDREF(fcc.object); /* For $this pointer */
+ object_or_called_scope = fcc.object;
+ call_info |= ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS;
}
FREE_OP2();
if ((OP2_TYPE & (IS_TMP_VAR|IS_VAR)) && UNEXPECTED(EG(exception))) {
if (call_info & ZEND_CALL_CLOSURE) {
zend_object_release(ZEND_CLOSURE_OBJECT(func));
- }
- if (call_info & ZEND_CALL_RELEASE_THIS) {
- zend_object_release(object);
+ } else if (call_info & ZEND_CALL_RELEASE_THIS) {
+ zend_object_release(fcc.object);
}
HANDLE_EXCEPTION();
}
- if (EXPECTED(func->type == ZEND_USER_FUNCTION) && UNEXPECTED(!func->op_array.run_time_cache)) {
+ if (EXPECTED(func->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&func->op_array))) {
init_func_run_time_cache(&func->op_array);
}
} else {
@@ -3430,12 +3909,11 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM)
HANDLE_EXCEPTION();
}
func = (zend_function*)&zend_pass_function;
- called_scope = NULL;
- object = NULL;
+ object_or_called_scope = NULL;
}
call = zend_vm_stack_push_call_frame(call_info,
- func, opline->extended_value, called_scope, object);
+ func, opline->extended_value, object_or_called_scope);
call->prev_execute_data = EX(call);
EX(call) = call;
@@ -3457,18 +3935,18 @@ ZEND_VM_HOT_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST, NUM|CACHE_SLOT)
if (func == NULL) {
func = zend_hash_find_ex(EG(function_table), Z_STR_P(func_name + 2), 1);
if (UNEXPECTED(func == NULL)) {
- ZEND_VM_DISPATCH_TO_HELPER(zend_undefined_function_helper, function_name, func_name);
+ ZEND_VM_DISPATCH_TO_HELPER(zend_undefined_function_helper);
}
}
fbc = Z_FUNC_P(func);
- if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
- fbc = init_func_run_time_cache_ex(func);
+ if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
+ init_func_run_time_cache(&fbc->op_array);
}
CACHE_PTR(opline->result.num, fbc);
}
- call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
- fbc, opline->extended_value, NULL, NULL);
+ call = _zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
+ fbc, opline->extended_value, NULL);
call->prev_execute_data = EX(call);
EX(call) = call;
@@ -3478,7 +3956,6 @@ ZEND_VM_HOT_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST, NUM|CACHE_SLOT)
ZEND_VM_HOT_HANDLER(61, ZEND_INIT_FCALL, NUM, CONST, NUM|CACHE_SLOT)
{
USE_OPLINE
- zend_free_op free_op2;
zval *fname;
zval *func;
zend_function *fbc;
@@ -3486,21 +3963,21 @@ ZEND_VM_HOT_HANDLER(61, ZEND_INIT_FCALL, NUM, CONST, NUM|CACHE_SLOT)
fbc = CACHED_PTR(opline->result.num);
if (UNEXPECTED(fbc == NULL)) {
- fname = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ fname = (zval*)RT_CONSTANT(opline, opline->op2);
func = zend_hash_find_ex(EG(function_table), Z_STR_P(fname), 1);
if (UNEXPECTED(func == NULL)) {
- ZEND_VM_DISPATCH_TO_HELPER(zend_undefined_function_helper, function_name, fname);
+ ZEND_VM_DISPATCH_TO_HELPER(zend_undefined_function_helper);
}
fbc = Z_FUNC_P(func);
- if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
- fbc = init_func_run_time_cache_ex(func);
+ if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
+ init_func_run_time_cache(&fbc->op_array);
}
CACHE_PTR(opline->result.num, fbc);
}
- call = zend_vm_stack_push_call_frame_ex(
+ call = _zend_vm_stack_push_call_frame_ex(
opline->op1.num, ZEND_CALL_NESTED_FUNCTION,
- fbc, opline->extended_value, NULL, NULL);
+ fbc, opline->extended_value, NULL);
call->prev_execute_data = EX(call);
EX(call) = call;
@@ -3540,7 +4017,7 @@ ZEND_VM_HOT_HANDLER(129, ZEND_DO_ICALL, ANY, ANY, SPEC(RETVAL))
zend_vm_stack_free_call_frame(call);
if (!RETURN_VALUE_USED(opline)) {
- zval_ptr_dtor(ret);
+ i_zval_ptr_dtor(ret);
}
if (UNEXPECTED(EG(exception) != NULL)) {
@@ -3565,13 +4042,12 @@ ZEND_VM_HOT_HANDLER(130, ZEND_DO_UCALL, ANY, ANY, SPEC(RETVAL))
ret = NULL;
if (RETURN_VALUE_USED(opline)) {
ret = EX_VAR(opline->result.var);
- ZVAL_NULL(ret);
}
call->prev_execute_data = execute_data;
execute_data = call;
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
- LOAD_OPLINE();
+ LOAD_OPLINE_EX();
ZEND_VM_ENTER_EX();
}
@@ -3590,13 +4066,12 @@ ZEND_VM_HOT_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL))
ret = NULL;
if (RETURN_VALUE_USED(opline)) {
ret = EX_VAR(opline->result.var);
- ZVAL_NULL(ret);
}
call->prev_execute_data = execute_data;
execute_data = call;
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
- LOAD_OPLINE();
+ LOAD_OPLINE_EX();
ZEND_VM_ENTER_EX();
} else {
@@ -3606,8 +4081,12 @@ ZEND_VM_HOT_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL))
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) {
zend_deprecated_function(fbc);
if (UNEXPECTED(EG(exception) != NULL)) {
- UNDEF_RESULT();
- HANDLE_EXCEPTION();
+ UNDEF_RESULT();
+ if (!RETURN_VALUE_USED(opline)) {
+ ret = &retval;
+ ZVAL_UNDEF(ret);
+ }
+ ZEND_VM_C_GOTO(fcall_by_name_end);
}
}
@@ -3616,10 +4095,12 @@ ZEND_VM_HOT_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL))
if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS)
&& UNEXPECTED(!zend_verify_internal_arg_types(fbc, call))) {
- zend_vm_stack_free_call_frame(call);
- zend_rethrow_exception(execute_data);
- UNDEF_RESULT();
- HANDLE_EXCEPTION();
+ UNDEF_RESULT();
+ if (!RETURN_VALUE_USED(opline)) {
+ ret = &retval;
+ ZVAL_UNDEF(ret);
+ }
+ ZEND_VM_C_GOTO(fcall_by_name_end);
}
ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval;
@@ -3637,11 +4118,13 @@ ZEND_VM_HOT_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL))
#endif
EG(current_execute_data) = execute_data;
+
+ZEND_VM_C_LABEL(fcall_by_name_end):
zend_vm_stack_free_args(call);
zend_vm_stack_free_call_frame(call);
if (!RETURN_VALUE_USED(opline)) {
- zval_ptr_dtor(ret);
+ i_zval_ptr_dtor(ret);
}
}
@@ -3658,20 +4141,25 @@ ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL))
USE_OPLINE
zend_execute_data *call = EX(call);
zend_function *fbc = call->func;
- zend_object *object;
zval *ret;
+ zval retval;
SAVE_OPLINE();
EX(call) = call->prev_execute_data;
if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) {
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) {
- ZEND_VM_DISPATCH_TO_HELPER(zend_abstract_method_helper, fbc, fbc);
- }
- if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) {
+ zend_abstract_method(fbc);
+ZEND_VM_C_LABEL(fcall_except):
+ UNDEF_RESULT();
+ if (!RETURN_VALUE_USED(opline)) {
+ ret = &retval;
+ ZVAL_UNDEF(ret);
+ }
+ ZEND_VM_C_GOTO(fcall_end);
+ } else {
zend_deprecated_function(fbc);
if (UNEXPECTED(EG(exception) != NULL)) {
- UNDEF_RESULT();
- HANDLE_EXCEPTION();
+ ZEND_VM_C_GOTO(fcall_except);
}
}
}
@@ -3680,7 +4168,6 @@ ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL))
ret = NULL;
if (RETURN_VALUE_USED(opline)) {
ret = EX_VAR(opline->result.var);
- ZVAL_NULL(ret);
}
call->prev_execute_data = execute_data;
@@ -3688,24 +4175,22 @@ ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL))
i_init_func_execute_data(&fbc->op_array, ret, 1 EXECUTE_DATA_CC);
if (EXPECTED(zend_execute_ex == execute_ex)) {
- LOAD_OPLINE();
+ LOAD_OPLINE_EX();
ZEND_VM_ENTER_EX();
} else {
+ SAVE_OPLINE_EX();
execute_data = EX(prev_execute_data);
LOAD_OPLINE();
ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
zend_execute_ex(call);
}
} else if (EXPECTED(fbc->type < ZEND_USER_FUNCTION)) {
- zval retval;
-
call->prev_execute_data = execute_data;
EG(current_execute_data) = call;
if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS)
&& UNEXPECTED(!zend_verify_internal_arg_types(fbc, call))) {
- UNDEF_RESULT();
- ZEND_VM_C_GOTO(fcall_end);
+ ZEND_VM_C_GOTO(fcall_except);
}
ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval;
@@ -3728,15 +4213,13 @@ ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL))
#endif
EG(current_execute_data) = execute_data;
- zend_vm_stack_free_args(call);
+ZEND_VM_C_LABEL(fcall_end):
+ zend_vm_stack_free_args(call);
if (!RETURN_VALUE_USED(opline)) {
- zval_ptr_dtor(ret);
+ i_zval_ptr_dtor(ret);
}
-
} else { /* ZEND_OVERLOADED_FUNCTION */
- zval retval;
-
ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval;
call->prev_execute_data = execute_data;
@@ -3751,18 +4234,8 @@ ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL))
}
}
-ZEND_VM_C_LABEL(fcall_end):
if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS)) {
- object = Z_OBJ(call->This);
-#if 0
- if (UNEXPECTED(EG(exception) != NULL) && (opline->op1.num & ZEND_CALL_CTOR)) {
-#else
- if (UNEXPECTED(EG(exception) != NULL) && (ZEND_CALL_INFO(call) & ZEND_CALL_CTOR)) {
-#endif
- GC_DELREF(object);
- zend_object_store_ctor_failed(object);
- }
- OBJ_RELEASE(object);
+ OBJ_RELEASE(Z_OBJ(call->This));
}
zend_vm_stack_free_call_frame(call);
@@ -3784,7 +4257,7 @@ ZEND_VM_COLD_CONST_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV
zend_verify_missing_return_type(EX(func), CACHE_ADDR(opline->op2.num));
} else {
/* prevents "undefined variable opline" errors */
-#if !defined(ZEND_VM_SPEC) || (OP1_TYPE != IS_UNUSED)
+#if !ZEND_VM_SPEC || (OP1_TYPE != IS_UNUSED)
zval *retval_ref, *retval_ptr;
zend_free_op free_op1;
zend_arg_info *ret_info = EX(func)->common.arg_info - 1;
@@ -3825,7 +4298,7 @@ ZEND_VM_COLD_CONST_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HOT_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY)
+ZEND_VM_INLINE_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY)
{
USE_OPLINE
zval *retval_ptr;
@@ -3836,7 +4309,7 @@ ZEND_VM_HOT_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY)
return_value = EX(return_value);
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) {
SAVE_OPLINE();
- retval_ptr = GET_OP1_UNDEF_CV(retval_ptr, BP_VAR_R);
+ retval_ptr = ZVAL_UNDEFINED_OP1();
if (return_value) {
ZVAL_NULL(return_value);
}
@@ -3856,25 +4329,29 @@ ZEND_VM_HOT_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY)
}
}
} else if (OP1_TYPE == IS_CV) {
- if (Z_OPT_REFCOUNTED_P(retval_ptr)) {
- if (EXPECTED(!Z_OPT_ISREF_P(retval_ptr))) {
- ZVAL_COPY_VALUE(return_value, retval_ptr);
- if (EXPECTED(!(EX_CALL_INFO() & ZEND_CALL_CODE))) {
- zend_refcounted *ref = Z_COUNTED_P(retval_ptr);
- if (GC_MAY_LEAK(ref)) {
- gc_possible_root(ref);
+ do {
+ if (Z_OPT_REFCOUNTED_P(retval_ptr)) {
+ if (EXPECTED(!Z_OPT_ISREF_P(retval_ptr))) {
+ if (EXPECTED(!(EX_CALL_INFO() & ZEND_CALL_CODE))) {
+ zend_refcounted *ref = Z_COUNTED_P(retval_ptr);
+ ZVAL_COPY_VALUE(return_value, retval_ptr);
+ if (GC_MAY_LEAK(ref)) {
+ gc_possible_root(ref);
+ }
+ ZVAL_NULL(retval_ptr);
+ break;
+ } else {
+ Z_ADDREF_P(retval_ptr);
}
- ZVAL_NULL(retval_ptr);
} else {
- Z_ADDREF_P(return_value);
+ retval_ptr = Z_REFVAL_P(retval_ptr);
+ if (Z_OPT_REFCOUNTED_P(retval_ptr)) {
+ Z_ADDREF_P(retval_ptr);
+ }
}
- } else {
- retval_ptr = Z_REFVAL_P(retval_ptr);
- ZVAL_COPY(return_value, retval_ptr);
}
- } else {
ZVAL_COPY_VALUE(return_value, retval_ptr);
- }
+ } while (0);
} else /* if (OP1_TYPE == IS_VAR) */ {
if (UNEXPECTED(Z_ISREF_P(retval_ptr))) {
zend_refcounted *ref = Z_COUNTED_P(retval_ptr);
@@ -3928,8 +4405,8 @@ ZEND_VM_COLD_CONST_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY, SRC)
retval_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
if (OP1_TYPE == IS_VAR) {
- if (retval_ptr == &EG(uninitialized_zval) ||
- (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(retval_ptr))) {
+ ZEND_ASSERT(retval_ptr != &EG(uninitialized_zval));
+ if (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(retval_ptr)) {
zend_error(E_NOTICE, "Only variable references should be returned by reference");
if (EX(return_value)) {
ZVAL_NEW_REF(EX(return_value), retval_ptr);
@@ -3955,7 +4432,7 @@ ZEND_VM_COLD_CONST_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY, SRC)
ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
}
-ZEND_VM_HANDLER(41, ZEND_GENERATOR_CREATE, ANY, ANY)
+ZEND_VM_HANDLER(139, ZEND_GENERATOR_CREATE, ANY, ANY)
{
zval *return_value = EX(return_value);
@@ -4000,7 +4477,7 @@ ZEND_VM_HANDLER(41, ZEND_GENERATOR_CREATE, ANY, ANY)
gen_execute_data->return_value = (zval*)generator;
call_info = Z_TYPE_INFO(EX(This));
if ((call_info & Z_TYPE_MASK) == IS_OBJECT
- && (!(call_info & ((ZEND_CALL_CLOSURE|ZEND_CALL_RELEASE_THIS) << ZEND_CALL_INFO_SHIFT))
+ && (!(call_info & (ZEND_CALL_CLOSURE|ZEND_CALL_RELEASE_THIS))
/* Bug #72523 */
|| UNEXPECTED(zend_execute_ex != execute_ex))) {
ZEND_ADD_CALL_FLAG_EX(call_info, ZEND_CALL_RELEASE_THIS);
@@ -4093,7 +4570,7 @@ ZEND_VM_COLD_CONST_HANDLER(108, ZEND_THROW, CONST|TMP|VAR|CV, ANY)
}
}
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
- GET_OP1_UNDEF_CV(value, BP_VAR_R);
+ ZVAL_UNDEFINED_OP1();
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -4130,7 +4607,7 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, JMP_ADDR, LAST_CATCH|CACHE_SLOT)
}
catch_ce = CACHED_PTR(opline->extended_value & ~ZEND_LAST_CATCH);
if (UNEXPECTED(catch_ce == NULL)) {
- catch_ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), RT_CONSTANT(opline, opline->op1) + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD);
+ catch_ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_NO_AUTOLOAD);
CACHE_PTR(opline->extended_value & ~ZEND_LAST_CATCH, catch_ce);
}
@@ -4154,17 +4631,15 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, JMP_ADDR, LAST_CATCH|CACHE_SLOT)
exception = EG(exception);
ex = EX_VAR(opline->result.var);
- if (UNEXPECTED(Z_ISREF_P(ex))) {
- ex = Z_REFVAL_P(ex);
- }
- zval_ptr_dtor(ex);
- ZVAL_OBJ(ex, EG(exception));
- if (UNEXPECTED(EG(exception) != exception)) {
- GC_ADDREF(EG(exception));
- HANDLE_EXCEPTION();
- } else {
+ {
+ /* Always perform a strict assignment. There is a reasonable expectation that if you
+ * write "catch (Exception $e)" then $e will actually be instanceof Exception. As such,
+ * we should not permit coercion to string here. */
+ zval tmp;
+ ZVAL_OBJ(&tmp, exception);
EG(exception) = NULL;
- ZEND_VM_NEXT_OPCODE();
+ zend_assign_to_variable(ex, &tmp, IS_TMP_VAR, /* strict */ 1);
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
}
@@ -4234,7 +4709,7 @@ ZEND_VM_HOT_HANDLER(117, ZEND_SEND_VAR, VAR|CV, NUM)
varptr = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) {
SAVE_OPLINE();
- GET_OP1_UNDEF_CV(varptr, BP_VAR_R);
+ ZVAL_UNDEFINED_OP1();
arg = ZEND_CALL_VAR(EX(call), opline->result.var);
ZVAL_NULL(arg);
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
@@ -4278,6 +4753,7 @@ ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR, NUM)
}
SAVE_OPLINE();
+ ZVAL_NEW_REF(arg, arg);
zend_error(E_NOTICE, "Only variables should be passed by reference");
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
@@ -4318,6 +4794,7 @@ ZEND_VM_HOT_SEND_HANDLER(50, ZEND_SEND_VAR_NO_REF_EX, VAR, NUM, SPEC(QUICK_ARG))
}
SAVE_OPLINE();
+ ZVAL_NEW_REF(arg, arg);
zend_error(E_NOTICE, "Only variables should be passed by reference");
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
@@ -4368,7 +4845,7 @@ ZEND_VM_C_LABEL(send_var_by_ref):
varptr = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) {
SAVE_OPLINE();
- GET_OP1_UNDEF_CV(varptr, BP_VAR_R);
+ ZVAL_UNDEFINED_OP1();
arg = ZEND_CALL_VAR(EX(call), opline->result.var);
ZVAL_NULL(arg);
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
@@ -4590,7 +5067,7 @@ ZEND_VM_C_LABEL(send_again):
ZEND_VM_C_GOTO(send_again);
} else {
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(args) == IS_UNDEF)) {
- GET_OP1_UNDEF_CV(args, BP_VAR_R);
+ ZVAL_UNDEFINED_OP1();
}
zend_error(E_WARNING, "Only arrays and Traversables can be unpacked");
}
@@ -4618,13 +5095,12 @@ ZEND_VM_HANDLER(119, ZEND_SEND_ARRAY, ANY, ANY, NUM)
zend_internal_type_error(EX_USES_STRICT_TYPES(), "call_user_func_array() expects parameter 2 to be array, %s given", zend_get_type_by_const(Z_TYPE_P(args)));
if (ZEND_CALL_INFO(EX(call)) & ZEND_CALL_CLOSURE) {
OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(call)->func));
- }
- if (Z_TYPE(EX(call)->This) == IS_OBJECT) {
+ } else if (ZEND_CALL_INFO(EX(call)) & ZEND_CALL_RELEASE_THIS) {
OBJ_RELEASE(Z_OBJ(EX(call)->This));
}
EX(call)->func = (zend_function*)&zend_pass_function;
Z_OBJ(EX(call)->This) = NULL;
- ZEND_SET_CALL_INFO(EX(call), 0, ZEND_CALL_INFO(EX(call)) & ~ZEND_CALL_RELEASE_THIS);
+ ZEND_CALL_INFO(EX(call)) &= ~(ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS);
FREE_UNFETCHED_OP2();
} else {
uint32_t arg_num;
@@ -4636,7 +5112,7 @@ ZEND_VM_C_LABEL(send_array):
ht = Z_ARRVAL_P(args);
if (OP2_TYPE != IS_UNUSED) {
zend_free_op free_op2;
- zval *op2 = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R);
+ zval *op2 = GET_OP2_ZVAL_PTR(BP_VAR_R);
uint32_t skip = opline->extended_value;
uint32_t count = zend_hash_num_elements(ht);
zend_long len = zval_get_long(op2);
@@ -4652,6 +5128,7 @@ ZEND_VM_C_LABEL(send_array):
arg_num = 1;
param = ZEND_CALL_ARG(EX(call), 1);
ZEND_HASH_FOREACH_VAL(ht, arg) {
+ zend_bool must_wrap = 0;
if (skip > 0) {
skip--;
continue;
@@ -4663,6 +5140,7 @@ ZEND_VM_C_LABEL(send_array):
/* By-value send is not allowed -- emit a warning,
* but still perform the call. */
zend_param_must_be_ref(EX(call)->func, arg_num);
+ must_wrap = 1;
}
}
} else {
@@ -4672,7 +5150,12 @@ ZEND_VM_C_LABEL(send_array):
arg = Z_REFVAL_P(arg);
}
}
- ZVAL_COPY(param, arg);
+ if (EXPECTED(!must_wrap)) {
+ ZVAL_COPY(param, arg);
+ } else {
+ Z_TRY_ADDREF_P(arg);
+ ZVAL_NEW_REF(param, arg);
+ }
ZEND_CALL_NUM_ARGS(EX(call))++;
arg_num++;
param++;
@@ -4684,12 +5167,14 @@ ZEND_VM_C_LABEL(send_array):
arg_num = 1;
param = ZEND_CALL_ARG(EX(call), 1);
ZEND_HASH_FOREACH_VAL(ht, arg) {
+ zend_bool must_wrap = 0;
if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
if (UNEXPECTED(!Z_ISREF_P(arg))) {
if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
/* By-value send is not allowed -- emit a warning,
* but still perform the call. */
zend_param_must_be_ref(EX(call)->func, arg_num);
+ must_wrap = 1;
}
}
} else {
@@ -4699,7 +5184,12 @@ ZEND_VM_C_LABEL(send_array):
arg = Z_REFVAL_P(arg);
}
}
- ZVAL_COPY(param, arg);
+ if (EXPECTED(!must_wrap)) {
+ ZVAL_COPY(param, arg);
+ } else {
+ Z_TRY_ADDREF_P(arg);
+ ZVAL_NEW_REF(param, arg);
+ }
ZEND_CALL_NUM_ARGS(EX(call))++;
arg_num++;
param++;
@@ -4717,15 +5207,14 @@ ZEND_VM_HANDLER(120, ZEND_SEND_USER, CONST|TMP|VAR|CV, NUM)
zend_free_op free_op1;
SAVE_OPLINE();
- arg = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
- param = ZEND_CALL_VAR(EX(call), opline->result.var);
if (UNEXPECTED(ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num))) {
zend_param_must_be_ref(EX(call)->func, opline->op2.num);
}
+ arg = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
+ param = ZEND_CALL_VAR(EX(call), opline->result.var);
ZVAL_COPY(param, arg);
-
FREE_OP1();
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
@@ -4739,11 +5228,11 @@ ZEND_VM_HOT_HANDLER(63, ZEND_RECV, NUM, UNUSED|CACHE_SLOT)
SAVE_OPLINE();
zend_missing_arg_error(execute_data);
HANDLE_EXCEPTION();
- } else if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
+ } else {
zval *param = EX_VAR(opline->result.var);
SAVE_OPLINE();
- if (UNEXPECTED(!zend_verify_arg_type(EX(func), arg_num, param, NULL, CACHE_ADDR(opline->op2.num)) || EG(exception))) {
+ if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, NULL, CACHE_ADDR(opline->op2.num)))) {
HANDLE_EXCEPTION();
}
}
@@ -4782,17 +5271,19 @@ ZEND_VM_HOT_HANDLER(64, ZEND_RECV_INIT, NUM, CONST, CACHE_SLOT)
ZVAL_COPY_VALUE(cache_val, param);
}
}
+ ZEND_VM_C_GOTO(recv_init_check_type);
} else {
ZVAL_COPY(param, default_value);
}
- }
-
- if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
- zval *default_value = RT_CONSTANT(opline, opline->op2);
+ } else {
+ZEND_VM_C_LABEL(recv_init_check_type):
+ if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
+ zval *default_value = RT_CONSTANT(opline, opline->op2);
- SAVE_OPLINE();
- if (UNEXPECTED(!zend_verify_arg_type(EX(func), arg_num, param, default_value, CACHE_ADDR(opline->extended_value)) || EG(exception))) {
- HANDLE_EXCEPTION();
+ SAVE_OPLINE();
+ if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, default_value, CACHE_ADDR(opline->extended_value)))) {
+ HANDLE_EXCEPTION();
+ }
}
}
@@ -4821,7 +5312,7 @@ ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, NUM, UNUSED|CACHE_SLOT)
if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
ZEND_ADD_CALL_FLAG(execute_data, ZEND_CALL_FREE_EXTRA_ARGS);
do {
- zend_verify_arg_type(EX(func), arg_num, param, NULL, CACHE_ADDR(opline->op2.num));
+ zend_verify_variadic_arg_type(EX(func), arg_num, param, NULL, CACHE_ADDR(opline->op2.num));
if (Z_OPT_REFCOUNTED_P(param)) Z_ADDREF_P(param);
ZEND_HASH_FILL_ADD(param);
param++;
@@ -4856,7 +5347,7 @@ ZEND_VM_COLD_CONST_HANDLER(52, ZEND_BOOL, CONST|TMPVAR|CV, ANY)
ZVAL_FALSE(EX_VAR(opline->result.var));
if (OP1_TYPE == IS_CV && UNEXPECTED(orig_val_type == IS_UNDEF)) {
SAVE_OPLINE();
- GET_OP1_UNDEF_CV(val, BP_VAR_R);
+ ZVAL_UNDEFINED_OP1();
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
} else {
@@ -4868,60 +5359,89 @@ ZEND_VM_COLD_CONST_HANDLER(52, ZEND_BOOL, CONST|TMPVAR|CV, ANY)
ZEND_VM_NEXT_OPCODE();
}
+ZEND_VM_HELPER(zend_case_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();
+ }
+ compare_function(EX_VAR(opline->result.var), op_1, op_2);
+ if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) {
+ zval_ptr_dtor_nogc(op_2);
+ }
+ if (UNEXPECTED(EG(exception))) {
+ HANDLE_EXCEPTION();
+ }
+ if (Z_LVAL_P(EX_VAR(opline->result.var)) == 0) {
+ ZEND_VM_SMART_BRANCH_TRUE();
+ ZVAL_TRUE(EX_VAR(opline->result.var));
+ ZEND_VM_NEXT_OPCODE();
+ } else {
+ ZEND_VM_SMART_BRANCH_FALSE();
+ ZVAL_FALSE(EX_VAR(opline->result.var));
+ ZEND_VM_NEXT_OPCODE();
+ }
+}
+
ZEND_VM_HANDLER(48, ZEND_CASE, TMPVAR, CONST|TMPVAR|CV)
{
USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *op1, *op2, *result;
+ zval *op1, *op2;
+ double d1, d2;
op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
- do {
- int result;
-
- if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
- if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
- result = (Z_LVAL_P(op1) == Z_LVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
- result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2));
+ 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(case_true):
+ ZEND_VM_SMART_BRANCH_TRUE();
+ ZVAL_TRUE(EX_VAR(opline->result.var));
+ ZEND_VM_NEXT_OPCODE();
} else {
- break;
+ZEND_VM_C_LABEL(case_false):
+ ZEND_VM_SMART_BRANCH_FALSE();
+ ZVAL_FALSE(EX_VAR(opline->result.var));
+ ZEND_VM_NEXT_OPCODE();
}
- } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
- if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
- result = (Z_DVAL_P(op1) == Z_DVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
- result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2)));
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
+ d1 = (double)Z_LVAL_P(op1);
+ d2 = Z_DVAL_P(op2);
+ ZEND_VM_C_GOTO(case_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(case_double):
+ if (d1 == d2) {
+ ZEND_VM_C_GOTO(case_true);
} else {
- break;
+ ZEND_VM_C_GOTO(case_false);
}
- } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
- if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
- result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2));
- FREE_OP2();
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
+ d1 = Z_DVAL_P(op1);
+ d2 = (double)Z_LVAL_P(op2);
+ ZEND_VM_C_GOTO(case_double);
+ }
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
+ int result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2));
+ FREE_OP2();
+ if (result) {
+ ZEND_VM_C_GOTO(case_true);
} else {
- break;
+ ZEND_VM_C_GOTO(case_false);
}
- } else {
- break;
}
- ZEND_VM_SMART_BRANCH(result, 0);
- ZVAL_BOOL(EX_VAR(opline->result.var), result);
- ZEND_VM_NEXT_OPCODE();
- } while (0);
-
- SAVE_OPLINE();
- if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
- op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
- }
- if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
- op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
}
- result = EX_VAR(opline->result.var);
- compare_function(result, op1, op2);
- ZVAL_BOOL(result, Z_LVAL_P(result) == 0);
- FREE_OP2();
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+ ZEND_VM_DISPATCH_TO_HELPER(zend_case_helper, op_1, op1, op_2, op2);
}
ZEND_VM_HANDLER(68, ZEND_NEW, UNUSED|CLASS_FETCH|CONST|VAR, UNUSED|CACHE_SLOT, NUM)
@@ -4936,7 +5456,7 @@ ZEND_VM_HANDLER(68, ZEND_NEW, UNUSED|CLASS_FETCH|CONST|VAR, UNUSED|CACHE_SLOT, N
if (OP1_TYPE == IS_CONST) {
ce = CACHED_PTR(opline->op2.num);
if (UNEXPECTED(ce == NULL)) {
- ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), RT_CONSTANT(opline, opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+ ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
if (UNEXPECTED(ce == NULL)) {
ZEND_ASSERT(EG(exception));
ZVAL_UNDEF(EX_VAR(opline->result.var));
@@ -4976,17 +5496,16 @@ ZEND_VM_HANDLER(68, ZEND_NEW, UNUSED|CLASS_FETCH|CONST|VAR, UNUSED|CACHE_SLOT, N
/* Perform a dummy function call */
call = zend_vm_stack_push_call_frame(
ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function,
- opline->extended_value, NULL, NULL);
+ opline->extended_value, NULL);
} else {
- if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!constructor->op_array.run_time_cache)) {
+ if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&constructor->op_array))) {
init_func_run_time_cache(&constructor->op_array);
}
/* We are not handling overloaded classes right now */
call = zend_vm_stack_push_call_frame(
- ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR,
+ ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS,
constructor,
opline->extended_value,
- ce,
Z_OBJ_P(result));
Z_ADDREF_P(result);
}
@@ -5023,7 +5542,7 @@ ZEND_VM_COLD_CONST_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY)
}
ZVAL_UNDEF(EX_VAR(opline->result.var));
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(obj) == IS_UNDEF)) {
- GET_OP1_UNDEF_CV(obj, BP_VAR_R);
+ ZVAL_UNDEFINED_OP1();
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -5044,23 +5563,12 @@ ZEND_VM_COLD_CONST_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY)
HANDLE_EXCEPTION();
}
- if (clone) {
- if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) {
- /* Ensure that if we're calling a private function, we're allowed to do so.
- */
- scope = EX(func)->op_array.scope;
- if (!zend_check_private(clone, scope, clone->common.function_name)) {
- zend_throw_error(NULL, "Call to private %s::__clone() from context '%s'", ZSTR_VAL(clone->common.scope->name), scope ? ZSTR_VAL(scope->name) : "");
- FREE_OP1();
- ZVAL_UNDEF(EX_VAR(opline->result.var));
- HANDLE_EXCEPTION();
- }
- } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) {
- /* Ensure that if we're calling a protected function, we're allowed to do so.
- */
- scope = EX(func)->op_array.scope;
- if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) {
- zend_throw_error(NULL, "Call to protected %s::__clone() from context '%s'", ZSTR_VAL(clone->common.scope->name), scope ? ZSTR_VAL(scope->name) : "");
+ if (clone && !(clone->common.fn_flags & ZEND_ACC_PUBLIC)) {
+ scope = EX(func)->op_array.scope;
+ if (clone->common.scope != scope) {
+ if (UNEXPECTED(clone->common.fn_flags & ZEND_ACC_PRIVATE)
+ || UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) {
+ zend_wrong_clone_call(clone, scope);
FREE_OP1();
ZVAL_UNDEF(EX_VAR(opline->result.var));
HANDLE_EXCEPTION();
@@ -5107,7 +5615,7 @@ ZEND_VM_HANDLER(181, ZEND_FETCH_CLASS_CONSTANT, VAR|CONST|UNUSED|CLASS_FETCH, CO
} else if (EXPECTED(CACHED_PTR(opline->extended_value))) {
ce = CACHED_PTR(opline->extended_value);
} else {
- ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), RT_CONSTANT(opline, opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+ ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
if (UNEXPECTED(ce == NULL)) {
ZEND_ASSERT(EG(exception));
ZVAL_UNDEF(EX_VAR(opline->result.var));
@@ -5237,8 +5745,12 @@ ZEND_VM_C_LABEL(num_index):
} else if (Z_TYPE_P(offset) == IS_TRUE) {
hval = 1;
ZEND_VM_C_GOTO(num_index);
+ } else if (Z_TYPE_P(offset) == IS_RESOURCE) {
+ zend_use_resource_as_offset(offset);
+ hval = Z_RES_HANDLE_P(offset);
+ ZEND_VM_C_GOTO(num_index);
} else if (OP2_TYPE == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
- GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ ZVAL_UNDEFINED_OP2();
str = ZSTR_EMPTY_ALLOC();
ZEND_VM_C_GOTO(str_index);
} else {
@@ -5255,7 +5767,114 @@ ZEND_VM_C_LABEL(num_index):
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(71, ZEND_INIT_ARRAY, CONST|TMP|VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV, ARRAY_INIT|REF)
+ZEND_VM_HANDLER(147, ZEND_ADD_ARRAY_UNPACK, ANY, ANY)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *op1;
+
+ SAVE_OPLINE();
+ op1 = GET_OP1_ZVAL_PTR(BP_VAR_R);
+
+ZEND_VM_C_LABEL(add_unpack_again):
+ if (EXPECTED(Z_TYPE_P(op1) == IS_ARRAY)) {
+ HashTable *ht = Z_ARRVAL_P(op1);
+ zval *val;
+ zend_string *key;
+
+ ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) {
+ if (key) {
+ zend_throw_error(NULL, "Cannot unpack array with string keys");
+ FREE_OP1();
+ HANDLE_EXCEPTION();
+ } else {
+ if (Z_ISREF_P(val) && Z_REFCOUNT_P(val) == 1) {
+ val = Z_REFVAL_P(val);
+ }
+ Z_TRY_ADDREF_P(val);
+ if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), val)) {
+ zend_cannot_add_element();
+ zval_ptr_dtor_nogc(val);
+ break;
+ }
+ }
+ } ZEND_HASH_FOREACH_END();
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_OBJECT)) {
+ zend_class_entry *ce = Z_OBJCE_P(op1);
+ zend_object_iterator *iter;
+
+ if (!ce || !ce->get_iterator) {
+ zend_throw_error(NULL, "Only arrays and Traversables can be unpacked");
+ } else {
+ iter = ce->get_iterator(ce, op1, 0);
+ if (UNEXPECTED(!iter)) {
+ FREE_OP1();
+ if (!EG(exception)) {
+ zend_throw_exception_ex(
+ NULL, 0, "Object of type %s did not create an Iterator", ZSTR_VAL(ce->name)
+ );
+ }
+ HANDLE_EXCEPTION();
+ }
+
+ if (iter->funcs->rewind) {
+ iter->funcs->rewind(iter);
+ }
+
+ for (; iter->funcs->valid(iter) == SUCCESS; ) {
+ zval *val;
+
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ break;
+ }
+
+ val = iter->funcs->get_current_data(iter);
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ break;
+ }
+
+ if (iter->funcs->get_current_key) {
+ zval key;
+ iter->funcs->get_current_key(iter, &key);
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ break;
+ }
+
+ if (UNEXPECTED(Z_TYPE(key) != IS_LONG)) {
+ zend_throw_error(NULL,
+ (Z_TYPE(key) == IS_STRING) ?
+ "Cannot unpack Traversable with string keys" :
+ "Cannot unpack Traversable with non-integer keys");
+ zval_ptr_dtor(&key);
+ break;
+ }
+ }
+
+ ZVAL_DEREF(val);
+ Z_TRY_ADDREF_P(val);
+
+ if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), val)) {
+ zend_cannot_add_element();
+ zval_ptr_dtor_nogc(val);
+ }
+
+ iter->funcs->move_forward(iter);
+ }
+
+ zend_iterator_dtor(iter);
+ }
+ } else if (EXPECTED(Z_ISREF_P(op1))) {
+ op1 = Z_REFVAL_P(op1);
+ ZEND_VM_C_GOTO(add_unpack_again);
+ } else {
+ zend_throw_error(NULL, "Only arrays and Traversables can be unpacked");
+ }
+
+ FREE_OP1();
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+}
+
+ZEND_VM_HANDLER(71, ZEND_INIT_ARRAY, CONST|TMP|VAR|CV|UNUSED, CONST|TMPVAR|UNUSED|NEXT|CV, ARRAY_INIT|REF)
{
zval *array;
uint32_t size;
@@ -5271,12 +5890,12 @@ ZEND_VM_HANDLER(71, ZEND_INIT_ARRAY, CONST|TMP|VAR|CV, CONST|TMPVAR|UNUSED|NEXT|
}
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_ADD_ARRAY_ELEMENT);
} else {
- ZVAL_EMPTY_ARRAY(array);
+ ZVAL_ARR(array, zend_new_array(0));
ZEND_VM_NEXT_OPCODE();
}
}
-ZEND_VM_COLD_CONST_HANDLER(21, ZEND_CAST, CONST|TMP|VAR|CV, ANY, TYPE)
+ZEND_VM_COLD_CONST_HANDLER(51, ZEND_CAST, CONST|TMP|VAR|CV, ANY, TYPE)
{
USE_OPLINE
zend_free_op free_op1;
@@ -5333,22 +5952,18 @@ ZEND_VM_COLD_CONST_HANDLER(21, ZEND_CAST, CONST|TMP|VAR|CV, ANY, TYPE)
} else {
ZVAL_EMPTY_ARRAY(result);
}
- } else if (Z_OBJ_HT_P(expr)->get_properties) {
- HashTable *obj_ht = Z_OBJ_HT_P(expr)->get_properties(expr);
+ } else {
+ HashTable *obj_ht = zend_get_properties_for(expr, ZEND_PROP_PURPOSE_ARRAY_CAST);
if (obj_ht) {
/* fast copy */
- obj_ht = zend_proptable_to_symtable(obj_ht,
+ ZVAL_ARR(result, zend_proptable_to_symtable(obj_ht,
(Z_OBJCE_P(expr)->default_properties_count ||
Z_OBJ_P(expr)->handlers != &std_object_handlers ||
- GC_IS_RECURSIVE(obj_ht)));
- ZVAL_ARR(result, obj_ht);
+ GC_IS_RECURSIVE(obj_ht))));
+ zend_release_properties(obj_ht);
} else {
ZVAL_EMPTY_ARRAY(result);
}
- } else {
- ZVAL_COPY_VALUE(result, expr);
- Z_ADDREF_P(result);
- convert_to_array(result);
}
} else {
ZVAL_OBJ(result, zend_objects_new(zend_standard_class_def));
@@ -5403,15 +6018,14 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMPVAR|CV, ANY, EVAL)
if (RETURN_VALUE_USED(opline)) {
return_value = EX_VAR(opline->result.var);
- ZVAL_NULL(return_value);
}
new_op_array->scope = EX(func)->op_array.scope;
- call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE,
+ call = zend_vm_stack_push_call_frame(
+ (Z_TYPE_INFO(EX(This)) & ZEND_CALL_HAS_THIS) | ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE,
(zend_function*)new_op_array, 0,
- Z_TYPE(EX(This)) != IS_OBJECT ? Z_CE(EX(This)) : NULL,
- Z_TYPE(EX(This)) == IS_OBJECT ? Z_OBJ(EX(This)) : NULL);
+ Z_PTR(EX(This)));
if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) {
call->symbol_table = EX(symbol_table);
@@ -5442,7 +6056,7 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMPVAR|CV, ANY, EVAL)
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(196, ZEND_UNSET_CV, CV, UNUSED)
+ZEND_VM_HANDLER(153, ZEND_UNSET_CV, CV, UNUSED)
{
USE_OPLINE
zval *var = EX_VAR(opline->op1.var);
@@ -5483,9 +6097,13 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMPVAR|CV, UNUSED, VAR_FETCH)
tmp_name = NULL;
} else {
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) {
- varname = GET_OP1_UNDEF_CV(varname, BP_VAR_R);
+ varname = ZVAL_UNDEFINED_OP1();
+ }
+ name = zval_try_get_tmp_string(varname, &tmp_name);
+ if (UNEXPECTED(!name)) {
+ FREE_OP1();
+ HANDLE_EXCEPTION();
}
- name = zval_get_tmp_string(varname, &tmp_name);
}
target_symbol_table = zend_get_target_symbol_table(opline->extended_value EXECUTE_DATA_CC);
@@ -5498,11 +6116,12 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMPVAR|CV, UNUSED, VAR_FETCH)
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_COLD_HANDLER(179, ZEND_UNSET_STATIC_PROP, CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR, CACHE_SLOT)
+/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */
+ZEND_VM_COLD_HANDLER(179, ZEND_UNSET_STATIC_PROP, ANY, ANY, CACHE_SLOT)
{
USE_OPLINE
zval *varname;
- zend_string *name, *tmp_name;
+ zend_string *name, *tmp_name = NULL;
zend_class_entry *ce;
zend_free_op free_op1;
@@ -5511,7 +6130,7 @@ ZEND_VM_COLD_HANDLER(179, ZEND_UNSET_STATIC_PROP, CONST|TMPVAR|CV, UNUSED|CLASS_
if (OP2_TYPE == IS_CONST) {
ce = CACHED_PTR(opline->extended_value);
if (UNEXPECTED(ce == NULL)) {
- ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)), RT_CONSTANT(opline, opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+ ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)), Z_STR_P(RT_CONSTANT(opline, opline->op2) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
if (UNEXPECTED(ce == NULL)) {
ZEND_ASSERT(EG(exception));
FREE_UNFETCHED_OP1();
@@ -5535,19 +6154,16 @@ ZEND_VM_COLD_HANDLER(179, ZEND_UNSET_STATIC_PROP, CONST|TMPVAR|CV, UNUSED|CLASS_
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)) {
- varname = GET_OP1_UNDEF_CV(varname, BP_VAR_R);
+ varname = ZVAL_UNDEFINED_OP1();
}
name = zval_get_tmp_string(varname, &tmp_name);
}
zend_std_unset_static_property(ce, name);
- if (OP1_TYPE != IS_CONST) {
- zend_tmp_string_release(tmp_name);
- }
+ zend_tmp_string_release(tmp_name);
FREE_OP1();
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
@@ -5609,7 +6225,7 @@ ZEND_VM_C_LABEL(num_index_dim):
hval = Z_RES_HANDLE_P(offset);
ZEND_VM_C_GOTO(num_index_dim);
} else if (OP2_TYPE == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
- GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ ZVAL_UNDEFINED_OP2();
key = ZSTR_EMPTY_ALLOC();
ZEND_VM_C_GOTO(str_index_dim);
} else {
@@ -5623,20 +6239,16 @@ ZEND_VM_C_LABEL(num_index_dim):
}
}
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
- container = GET_OP1_UNDEF_CV(container, BP_VAR_R);
+ container = ZVAL_UNDEFINED_OP1();
}
if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) {
- offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ offset = ZVAL_UNDEFINED_OP2();
}
if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
- if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) {
- zend_use_object_as_array();
- } else {
- if (OP2_TYPE == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) {
- offset++;
- }
- Z_OBJ_HT_P(container)->unset_dimension(container, offset);
+ if (OP2_TYPE == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) {
+ offset++;
}
+ Z_OBJ_HT_P(container)->unset_dimension(container, offset);
} else if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
zend_throw_error(NULL, "Cannot unset string offsets");
}
@@ -5655,7 +6267,7 @@ ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_S
zval *offset;
SAVE_OPLINE();
- container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET);
+ container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_UNSET);
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
}
@@ -5666,17 +6278,17 @@ ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_S
if (Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (Z_TYPE_P(container) != IS_OBJECT) {
+ if (OP1_TYPE == IS_CV
+ && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
+ ZVAL_UNDEFINED_OP1();
+ }
break;
}
} else {
break;
}
}
- if (Z_OBJ_HT_P(container)->unset_property) {
- Z_OBJ_HT_P(container)->unset_property(container, offset, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL));
- } else {
- zend_wrong_property_unset(offset);
- }
+ Z_OBJ_HT_P(container)->unset_property(container, offset, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL));
} while (0);
FREE_OP2();
@@ -5906,10 +6518,12 @@ ZEND_VM_C_LABEL(fe_fetch_r_exit):
value = Z_INDIRECT_P(value);
value_type = Z_TYPE_INFO_P(value);
if (EXPECTED(value_type != IS_UNDEF)
- && EXPECTED(zend_check_property_access(Z_OBJ_P(array), p->key) == SUCCESS)) {
+ && EXPECTED(zend_check_property_access(Z_OBJ_P(array), p->key, 0) == SUCCESS)) {
break;
}
- } else {
+ } else if (EXPECTED(Z_OBJCE_P(array)->default_properties_count == 0)
+ || !p->key
+ || zend_check_property_access(Z_OBJ_P(array), p->key, 1) == SUCCESS) {
break;
}
}
@@ -5974,7 +6588,7 @@ ZEND_VM_C_LABEL(fe_fetch_r_exit):
if (EXPECTED(OP2_TYPE == IS_CV)) {
zval *variable_ptr = EX_VAR(opline->op2.var);
- zend_assign_to_variable(variable_ptr, value, IS_CV);
+ zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES());
} else {
zval *res = EX_VAR(opline->op2.var);
zend_refcounted *gc = Z_COUNTED_P(value);
@@ -6056,10 +6670,21 @@ ZEND_VM_HANDLER(126, ZEND_FE_FETCH_RW, VAR, ANY, JMP_ADDR)
value = Z_INDIRECT_P(value);
value_type = Z_TYPE_INFO_P(value);
if (EXPECTED(value_type != IS_UNDEF)
- && EXPECTED(zend_check_property_access(Z_OBJ_P(array), p->key) == SUCCESS)) {
+ && EXPECTED(zend_check_property_access(Z_OBJ_P(array), p->key, 0) == SUCCESS)) {
+ if ((value_type & Z_TYPE_MASK) != IS_REFERENCE) {
+ zend_property_info *prop_info =
+ zend_get_typed_property_info_for_slot(Z_OBJ_P(array), value);
+ if (UNEXPECTED(prop_info)) {
+ ZVAL_NEW_REF(value, value);
+ ZEND_REF_ADD_TYPE_SOURCE(Z_REF_P(value), prop_info);
+ value_type = IS_REFERENCE_EX;
+ }
+ }
break;
}
- } else {
+ } else if (EXPECTED(Z_OBJCE_P(array)->default_properties_count == 0)
+ || !p->key
+ || zend_check_property_access(Z_OBJ_P(array), p->key, 1) == SUCCESS) {
break;
}
}
@@ -6145,7 +6770,7 @@ ZEND_VM_C_LABEL(fe_fetch_w_exit):
ref = Z_REF_P(value);
GC_ADDREF(ref);
- zval_ptr_dtor(variable_ptr);
+ i_zval_ptr_dtor(variable_ptr);
ZVAL_REF(variable_ptr, ref);
}
} else {
@@ -6155,28 +6780,36 @@ ZEND_VM_C_LABEL(fe_fetch_w_exit):
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HOT_HANDLER(197, ZEND_ISSET_ISEMPTY_CV, CV, UNUSED, ISSET, SPEC(ISSET))
+ZEND_VM_HOT_HANDLER(154, ZEND_ISSET_ISEMPTY_CV, CV, UNUSED, ISSET, SPEC(ISSET))
{
USE_OPLINE
zval *value;
- int result;
value = EX_VAR(opline->op1.var);
if (!(opline->extended_value & ZEND_ISEMPTY)) {
- result =
- Z_TYPE_P(value) > IS_NULL &&
- (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
+ if (Z_TYPE_P(value) > IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) {
+ ZEND_VM_SMART_BRANCH_TRUE();
+ ZVAL_TRUE(EX_VAR(opline->result.var));
+ ZEND_VM_NEXT_OPCODE();
+ } else {
+ ZEND_VM_SMART_BRANCH_FALSE();
+ ZVAL_FALSE(EX_VAR(opline->result.var));
+ ZEND_VM_NEXT_OPCODE();
+ }
} else {
+ int result;
+
SAVE_OPLINE();
result = !i_zend_is_true(value);
if (UNEXPECTED(EG(exception))) {
ZVAL_UNDEF(EX_VAR(opline->result.var));
HANDLE_EXCEPTION();
}
+ ZEND_VM_SMART_BRANCH(result, 0);
+ ZVAL_BOOL(EX_VAR(opline->result.var), result);
+ ZEND_VM_NEXT_OPCODE();
}
- ZEND_VM_SMART_BRANCH(result, 0);
- ZVAL_BOOL(EX_VAR(opline->result.var), result);
- ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMPVAR|CV, UNUSED, VAR_FETCH|ISSET)
@@ -6226,76 +6859,22 @@ ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMPVAR|CV, UNUSED, VAR_FETCH|
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(180, ZEND_ISSET_ISEMPTY_STATIC_PROP, CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR, ISSET|CACHE_SLOT)
+/* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */
+ZEND_VM_HANDLER(180, ZEND_ISSET_ISEMPTY_STATIC_PROP, ANY, CLASS_FETCH, ISSET|CACHE_SLOT)
{
USE_OPLINE
zval *value;
int result;
- zend_free_op free_op1;
- zval *varname;
- zend_string *name, *tmp_name;
- zend_class_entry *ce;
SAVE_OPLINE();
- if (OP2_TYPE == IS_CONST) {
- if (OP1_TYPE == IS_CONST && EXPECTED((ce = CACHED_PTR(opline->extended_value & ~ZEND_ISEMPTY)) != NULL)) {
- value = CACHED_PTR((opline->extended_value & ~ZEND_ISEMPTY) + sizeof(void*));
- ZEND_VM_C_GOTO(is_static_prop_return);
- } else if (UNEXPECTED((ce = CACHED_PTR(opline->extended_value & ~ZEND_ISEMPTY)) == NULL)) {
- ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)), RT_CONSTANT(opline, opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(ce == NULL)) {
- ZEND_ASSERT(EG(exception));
- ZVAL_UNDEF(EX_VAR(opline->result.var));
- HANDLE_EXCEPTION();
- }
- if (OP1_TYPE != IS_CONST) {
- CACHE_PTR(opline->extended_value & ~ZEND_ISEMPTY, ce);
- }
- }
- } else {
- if (OP2_TYPE == IS_UNUSED) {
- ce = zend_fetch_class(NULL, opline->op2.num);
- if (UNEXPECTED(ce == NULL)) {
- ZEND_ASSERT(EG(exception));
- FREE_UNFETCHED_OP1();
- ZVAL_UNDEF(EX_VAR(opline->result.var));
- HANDLE_EXCEPTION();
- }
- } else {
- ce = Z_CE_P(EX_VAR(opline->op2.var));
- }
- if (OP1_TYPE == IS_CONST &&
- EXPECTED(CACHED_PTR(opline->extended_value & ~ZEND_ISEMPTY) == ce)) {
-
- value = CACHED_PTR((opline->extended_value & ~ZEND_ISEMPTY) + sizeof(void*));
- ZEND_VM_C_GOTO(is_static_prop_return);
- }
- }
-
- varname = GET_OP1_ZVAL_PTR(BP_VAR_IS);
- if (OP1_TYPE == IS_CONST) {
- name = Z_STR_P(varname);
- } else {
- name = zval_get_tmp_string(varname, &tmp_name);
- }
- value = zend_std_get_static_property(ce, name, 1);
+ result = zend_fetch_static_property_address(&value, NULL, opline->extended_value & ~ZEND_ISEMPTY, BP_VAR_IS, 0 OPLINE_CC EXECUTE_DATA_CC);
- if (OP1_TYPE == IS_CONST && value) {
- CACHE_POLYMORPHIC_PTR(opline->extended_value & ~ZEND_ISEMPTY, ce, value);
- }
-
- if (OP1_TYPE != IS_CONST) {
- zend_tmp_string_release(tmp_name);
- }
- FREE_OP1();
-
-ZEND_VM_C_LABEL(is_static_prop_return):
if (!(opline->extended_value & ZEND_ISEMPTY)) {
- result = value && Z_TYPE_P(value) > IS_NULL &&
+ result = result == SUCCESS && Z_TYPE_P(value) > IS_NULL &&
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
} else {
- result = !value || !i_zend_is_true(value);
+ result = result != SUCCESS || !i_zend_is_true(value);
}
ZEND_VM_SMART_BRANCH(result, 1);
@@ -6347,6 +6926,14 @@ ZEND_VM_C_LABEL(num_index_prop):
/* > IS_NULL means not IS_UNDEF and not IS_NULL */
result = value != NULL && Z_TYPE_P(value) > IS_NULL &&
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
+
+ if (OP1_TYPE & (IS_CONST|IS_CV)) {
+ /* avoid exception check */
+ FREE_OP2();
+ ZEND_VM_SMART_BRANCH(result, 0);
+ ZVAL_BOOL(EX_VAR(opline->result.var), result);
+ ZEND_VM_NEXT_OPCODE();
+ }
} else {
result = (value == NULL || !i_zend_is_true(value));
}
@@ -6397,22 +6984,20 @@ ZEND_VM_COLD_CONST_HANDLER(148, ZEND_ISSET_ISEMPTY_PROP_OBJ, CONST|TMPVAR|UNUSED
if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
- ZEND_VM_C_GOTO(isset_no_object);
+ result = (opline->extended_value & ZEND_ISEMPTY);
+ ZEND_VM_C_GOTO(isset_object_finish);
}
} else {
- ZEND_VM_C_GOTO(isset_no_object);
+ result = (opline->extended_value & ZEND_ISEMPTY);
+ ZEND_VM_C_GOTO(isset_object_finish);
}
}
- if (UNEXPECTED(!Z_OBJ_HT_P(container)->has_property)) {
- zend_wrong_property_check(offset);
-ZEND_VM_C_LABEL(isset_no_object):
- result = (opline->extended_value & ZEND_ISEMPTY);
- } else {
- result =
- (opline->extended_value & ZEND_ISEMPTY) ^
- Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL));
- }
+ result =
+ (opline->extended_value & ZEND_ISEMPTY) ^
+ Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISEMPTY), ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL));
+
+ZEND_VM_C_LABEL(isset_object_finish):
FREE_OP2();
FREE_OP1();
ZEND_VM_SMART_BRANCH(result, 1);
@@ -6420,7 +7005,43 @@ ZEND_VM_C_LABEL(isset_no_object):
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_COLD_HANDLER(79, ZEND_EXIT, CONST|TMPVAR|UNUSED|CV, ANY)
+ZEND_VM_HANDLER(194, ZEND_ARRAY_KEY_EXISTS, CV|TMPVAR|CONST, CV|TMPVAR|CONST)
+{
+ USE_OPLINE
+
+ zend_free_op free_op1, free_op2;
+ zval *key, *subject;
+ HashTable *ht;
+ uint32_t result;
+
+ SAVE_OPLINE();
+
+ key = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
+ subject = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
+
+ if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) {
+ZEND_VM_C_LABEL(array_key_exists_array):
+ ht = Z_ARRVAL_P(subject);
+ result = zend_array_key_exists_fast(ht, key OPLINE_CC EXECUTE_DATA_CC);
+ } else {
+ if ((OP2_TYPE & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(subject))) {
+ subject = Z_REFVAL_P(subject);
+ if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) {
+ ZEND_VM_C_GOTO(array_key_exists_array);
+ }
+ }
+ result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC);
+ }
+
+ FREE_OP2();
+ FREE_OP1();
+ ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1);
+ Z_TYPE_INFO_P(EX_VAR(opline->result.var)) = result;
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+}
+
+/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */
+ZEND_VM_COLD_HANDLER(79, ZEND_EXIT, ANY, ANY)
{
USE_OPLINE
@@ -6542,7 +7163,7 @@ ZEND_VM_COLD_CONST_HANDLER(152, ZEND_JMP_SET, CONST|TMP|VAR|CV, JMP_ADDR)
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_COLD_CONST_HANDLER(169, ZEND_COALESCE, CONST|TMPVAR|CV, JMP_ADDR)
+ZEND_VM_COLD_CONST_HANDLER(169, ZEND_COALESCE, CONST|TMP|VAR|CV, JMP_ADDR)
{
USE_OPLINE
zend_free_op free_op1;
@@ -6582,7 +7203,7 @@ ZEND_VM_COLD_CONST_HANDLER(169, ZEND_COALESCE, CONST|TMPVAR|CV, JMP_ADDR)
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HOT_HANDLER(22, ZEND_QM_ASSIGN, CONST|TMP|VAR|CV, ANY)
+ZEND_VM_HOT_HANDLER(31, ZEND_QM_ASSIGN, CONST|TMP|VAR|CV, ANY)
{
USE_OPLINE
zend_free_op free_op1;
@@ -6592,7 +7213,7 @@ ZEND_VM_HOT_HANDLER(22, ZEND_QM_ASSIGN, CONST|TMP|VAR|CV, ANY)
value = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
SAVE_OPLINE();
- GET_OP1_UNDEF_CV(value, BP_VAR_R);
+ ZVAL_UNDEFINED_OP1();
ZVAL_NULL(result);
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
@@ -6657,106 +7278,81 @@ ZEND_VM_COLD_HANDLER(103, ZEND_EXT_FCALL_END, ANY, ANY)
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(139, ZEND_DECLARE_CLASS, CONST, ANY)
+ZEND_VM_HANDLER(144, ZEND_DECLARE_CLASS, CONST, ANY)
{
USE_OPLINE
SAVE_OPLINE();
- Z_CE_P(EX_VAR(opline->result.var)) = do_bind_class(&EX(func)->op_array, opline, EG(class_table), 0);
+ do_bind_class(RT_CONSTANT(opline, opline->op1), (OP2_TYPE == IS_CONST) ? Z_STR_P(RT_CONSTANT(opline, opline->op2)) : NULL);
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(140, ZEND_DECLARE_INHERITED_CLASS, CONST, CONST)
+ZEND_VM_HANDLER(145, ZEND_DECLARE_CLASS_DELAYED, CONST, CONST)
{
- zend_class_entry *parent;
USE_OPLINE
+ zval *lcname, *zv;
+ zend_class_entry *ce;
- SAVE_OPLINE();
- parent = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)),
- RT_CONSTANT(opline, opline->op2) + 1,
- ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(parent == NULL)) {
- ZEND_ASSERT(EG(exception));
- HANDLE_EXCEPTION();
- }
- Z_CE_P(EX_VAR(opline->result.var)) = do_bind_inherited_class(&EX(func)->op_array, opline, EG(class_table), parent, 0);
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
-}
-
-ZEND_VM_HANDLER(145, ZEND_DECLARE_INHERITED_CLASS_DELAYED, CONST, CONST)
-{
- USE_OPLINE
- zval *zce, *orig_zce;
- zend_class_entry *parent;
-
- SAVE_OPLINE();
- if ((zce = zend_hash_find_ex(EG(class_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)), 1)) == NULL ||
- ((orig_zce = zend_hash_find_ex(EG(class_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)+1), 1)) != NULL &&
- Z_CE_P(zce) != Z_CE_P(orig_zce))) {
- parent = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)),
- RT_CONSTANT(opline, opline->op2) + 1,
- ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(parent == NULL)) {
- ZEND_ASSERT(EG(exception));
- HANDLE_EXCEPTION();
+ ce = CACHED_PTR(opline->extended_value);
+ if (ce == NULL) {
+ lcname = RT_CONSTANT(opline, opline->op1);
+ zv = zend_hash_find_ex(EG(class_table), Z_STR_P(lcname + 1), 1);
+ if (zv) {
+ SAVE_OPLINE();
+ ce = Z_CE_P(zv);
+ zv = zend_hash_set_bucket_key(EG(class_table), (Bucket*)zv, Z_STR_P(lcname));
+ if (UNEXPECTED(!zv)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare %s %s, because the name is already in use", zend_get_object_type(ce), ZSTR_VAL(ce->name));
+ } else {
+ if (zend_do_link_class(ce, Z_STR_P(RT_CONSTANT(opline, opline->op2))) == FAILURE) {
+ /* Reload bucket pointer, the hash table may have been reallocated */
+ zv = zend_hash_find(EG(class_table), Z_STR_P(lcname));
+ zend_hash_set_bucket_key(EG(class_table), (Bucket *) zv, Z_STR_P(lcname + 1));
+ HANDLE_EXCEPTION();
+ }
+ }
}
- do_bind_inherited_class(&EX(func)->op_array, opline, EG(class_table), parent, 0);
+ CACHE_PTR(opline->extended_value, ce);
}
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(171, ZEND_DECLARE_ANON_CLASS, ANY, ANY, JMP_ADDR)
+ZEND_VM_HANDLER(146, ZEND_DECLARE_ANON_CLASS, ANY, ANY, CACHE_SLOT)
{
zval *zv;
zend_class_entry *ce;
USE_OPLINE
- SAVE_OPLINE();
- zv = zend_hash_find_ex(EG(class_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)), 1);
- ZEND_ASSERT(zv != NULL);
- ce = Z_CE_P(zv);
- Z_CE_P(EX_VAR(opline->result.var)) = ce;
-
- if (ce->ce_flags & ZEND_ACC_ANON_BOUND) {
- ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
- ZEND_VM_CONTINUE();
- }
-
- if (!(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLEMENT_INTERFACES|ZEND_ACC_IMPLEMENT_TRAITS))) {
- zend_verify_abstract_class(ce);
+ ce = CACHED_PTR(opline->extended_value);
+ if (UNEXPECTED(ce == NULL)) {
+ zend_string *rtd_key = Z_STR_P(RT_CONSTANT(opline, opline->op1));
+ zv = zend_hash_find_ex(EG(class_table), rtd_key, 1);
+ if (UNEXPECTED(zv == NULL)) {
+ SAVE_OPLINE();
+ do {
+ ZEND_ASSERT(EX(func)->op_array.fn_flags & ZEND_ACC_PRELOADED);
+ if (zend_preload_autoload
+ && zend_preload_autoload(EX(func)->op_array.filename) == SUCCESS) {
+ zv = zend_hash_find_ex(EG(class_table), rtd_key, 1);
+ if (EXPECTED(zv != NULL)) {
+ break;
+ }
+ }
+ zend_error_noreturn(E_ERROR, "Anonymous class wasn't preloaded");
+ } while (0);
+ }
+ ZEND_ASSERT(zv != NULL);
+ ce = Z_CE_P(zv);
+ if (!(ce->ce_flags & ZEND_ACC_LINKED)) {
+ SAVE_OPLINE();
+ if (zend_do_link_class(ce, (OP2_TYPE == IS_CONST) ? Z_STR_P(RT_CONSTANT(opline, opline->op2)) : NULL) == FAILURE) {
+ HANDLE_EXCEPTION();
+ }
+ }
+ CACHE_PTR(opline->extended_value, ce);
}
- ce->ce_flags |= ZEND_ACC_ANON_BOUND;
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
-}
-
-ZEND_VM_HANDLER(172, ZEND_DECLARE_ANON_INHERITED_CLASS, CONST, CONST, JMP_ADDR)
-{
- zval *zv;
- zend_class_entry *ce, *parent;
- USE_OPLINE
-
- SAVE_OPLINE();
- zv = zend_hash_find_ex(EG(class_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)), 1);
- ZEND_ASSERT(zv != NULL);
- ce = Z_CE_P(zv);
Z_CE_P(EX_VAR(opline->result.var)) = ce;
-
- if (ce->ce_flags & ZEND_ACC_ANON_BOUND) {
- ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
- ZEND_VM_CONTINUE();
- }
-
- parent = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)),
- RT_CONSTANT(opline, opline->op2) + 1,
- ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(parent == NULL)) {
- ZEND_ASSERT(EG(exception));
- HANDLE_EXCEPTION();
- }
-
- zend_do_inheritance(ce, parent);
- ce->ce_flags |= ZEND_ACC_ANON_BOUND;
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(141, ZEND_DECLARE_FUNCTION, ANY, ANY)
@@ -6764,7 +7360,7 @@ ZEND_VM_HANDLER(141, ZEND_DECLARE_FUNCTION, ANY, ANY)
USE_OPLINE
SAVE_OPLINE();
- do_bind_function(&EX(func)->op_array, opline, EG(function_table), 0);
+ do_bind_function(RT_CONSTANT(opline, opline->op1));
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
@@ -6800,7 +7396,7 @@ ZEND_VM_C_LABEL(try_instanceof):
if (OP2_TYPE == IS_CONST) {
ce = CACHED_PTR(opline->extended_value);
if (UNEXPECTED(ce == NULL)) {
- ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)), RT_CONSTANT(opline, opline->op2) + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD);
+ ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)), Z_STR_P(RT_CONSTANT(opline, opline->op2) + 1), ZEND_FETCH_CLASS_NO_AUTOLOAD);
if (EXPECTED(ce)) {
CACHE_PTR(opline->extended_value, ce);
}
@@ -6822,7 +7418,7 @@ ZEND_VM_C_LABEL(try_instanceof):
ZEND_VM_C_GOTO(try_instanceof);
} else {
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(expr) == IS_UNDEF)) {
- GET_OP1_UNDEF_CV(expr, BP_VAR_R);
+ ZVAL_UNDEFINED_OP1();
}
result = 0;
}
@@ -6846,60 +7442,6 @@ ZEND_VM_HOT_HANDLER(0, ZEND_NOP, ANY, ANY)
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(144, ZEND_ADD_INTERFACE, ANY, CONST, CACHE_SLOT)
-{
- USE_OPLINE
- zend_class_entry *ce = Z_CE_P(EX_VAR(opline->op1.var));
- zend_class_entry *iface;
-
- SAVE_OPLINE();
- iface = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)), RT_CONSTANT(opline, opline->op2) + 1, ZEND_FETCH_CLASS_INTERFACE);
- if (UNEXPECTED(iface == NULL)) {
- ZEND_ASSERT(EG(exception));
- HANDLE_EXCEPTION();
- }
-
- if (UNEXPECTED((iface->ce_flags & ZEND_ACC_INTERFACE) == 0)) {
- zend_error_noreturn(E_ERROR, "%s cannot implement %s - it is not an interface", ZSTR_VAL(ce->name), ZSTR_VAL(iface->name));
- }
- zend_do_implement_interface(ce, iface);
-
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
-}
-
-ZEND_VM_HANDLER(154, ZEND_ADD_TRAIT, ANY, ANY, CACHE_SLOT)
-{
- USE_OPLINE
- zend_class_entry *ce = Z_CE_P(EX_VAR(opline->op1.var));
- zend_class_entry *trait;
-
- SAVE_OPLINE();
- trait = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)),
- RT_CONSTANT(opline, opline->op2) + 1,
- ZEND_FETCH_CLASS_TRAIT);
- if (UNEXPECTED(trait == NULL)) {
- ZEND_ASSERT(EG(exception));
- HANDLE_EXCEPTION();
- }
- if (!(trait->ce_flags & ZEND_ACC_TRAIT)) {
- zend_error_noreturn(E_ERROR, "%s cannot use %s - it is not a trait", ZSTR_VAL(ce->name), ZSTR_VAL(trait->name));
- }
-
- zend_do_implement_trait(ce, trait);
-
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
-}
-
-ZEND_VM_HANDLER(155, ZEND_BIND_TRAITS, ANY, ANY)
-{
- USE_OPLINE
- zend_class_entry *ce = Z_CE_P(EX_VAR(opline->op1.var));
-
- SAVE_OPLINE();
- zend_do_bind_traits(ce);
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
-}
-
ZEND_VM_HELPER(zend_dispatch_try_catch_finally_helper, ANY, ANY, uint32_t try_catch_offset, uint32_t op_num)
{
/* May be NULL during generator closing (only finally blocks are executed) */
@@ -6956,6 +7498,10 @@ ZEND_VM_HELPER(zend_dispatch_try_catch_finally_helper, ANY, ANY, uint32_t try_ca
zend_generator_close(generator, 1);
ZEND_VM_RETURN();
} else {
+ /* We didn't execute RETURN, and have to initialize return_value */
+ if (EX(return_value)) {
+ ZVAL_UNDEF(EX(return_value));
+ }
ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
}
}
@@ -6994,15 +7540,13 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
if (throw_op->result_type & (IS_VAR | IS_TMP_VAR)) {
switch (throw_op->opcode) {
case ZEND_ADD_ARRAY_ELEMENT:
+ case ZEND_ADD_ARRAY_UNPACK:
case ZEND_ROPE_INIT:
case ZEND_ROPE_ADD:
break; /* exception while building structures, live range handling will free those */
case ZEND_FETCH_CLASS:
- case ZEND_DECLARE_CLASS:
- case ZEND_DECLARE_INHERITED_CLASS:
case ZEND_DECLARE_ANON_CLASS:
- case ZEND_DECLARE_ANON_INHERITED_CLASS:
break; /* return value is zend_class_entry pointer */
default:
@@ -7013,15 +7557,6 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
ZEND_VM_DISPATCH_TO_HELPER(zend_dispatch_try_catch_finally_helper, try_catch_offset, current_try_catch_offset, op_num, throw_op_num);
}
-ZEND_VM_HANDLER(146, ZEND_VERIFY_ABSTRACT_CLASS, ANY, ANY)
-{
- USE_OPLINE
-
- SAVE_OPLINE();
- zend_verify_abstract_class(Z_CE_P(EX_VAR(opline->op1.var)));
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
-}
-
ZEND_VM_HANDLER(150, ZEND_USER_OPCODE, ANY, ANY)
{
USE_OPLINE
@@ -7086,29 +7621,26 @@ ZEND_VM_HANDLER(143, ZEND_DECLARE_CONST, CONST, CONST)
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(153, ZEND_DECLARE_LAMBDA_FUNCTION, CONST, UNUSED)
+ZEND_VM_HANDLER(142, ZEND_DECLARE_LAMBDA_FUNCTION, CONST, UNUSED, CACHE_SLOT)
{
USE_OPLINE
+ zend_function *func;
zval *zfunc;
zval *object;
zend_class_entry *called_scope;
- zend_function *fbc;
-
- zfunc = zend_hash_find_ex(EG(function_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)), 1);
- ZEND_ASSERT(zfunc != NULL && Z_FUNC_P(zfunc)->type == ZEND_USER_FUNCTION);
- fbc = Z_PTR_P(zfunc);
- if (fbc->common.fn_flags & ZEND_ACC_IMMUTABLE) {
- zend_function *new_func = zend_arena_alloc(&CG(arena), sizeof(zend_op_array));
-
- memcpy(new_func, fbc, sizeof(zend_op_array));
- new_func->common.fn_flags &= ~ZEND_ACC_IMMUTABLE;
- Z_PTR_P(zfunc) = fbc = new_func;
+ func = CACHED_PTR(opline->extended_value);
+ if (UNEXPECTED(func == NULL)) {
+ zfunc = zend_hash_find_ex(EG(function_table), Z_STR_P(RT_CONSTANT(opline, opline->op1)), 1);
+ ZEND_ASSERT(zfunc != NULL);
+ func = Z_FUNC_P(zfunc);
+ ZEND_ASSERT(func->type == ZEND_USER_FUNCTION);
+ CACHE_PTR(opline->extended_value, func);
}
if (Z_TYPE(EX(This)) == IS_OBJECT) {
called_scope = Z_OBJCE(EX(This));
- if (UNEXPECTED((Z_FUNC_P(zfunc)->common.fn_flags & ZEND_ACC_STATIC) ||
+ if (UNEXPECTED((func->common.fn_flags & ZEND_ACC_STATIC) ||
(EX(func)->common.fn_flags & ZEND_ACC_STATIC))) {
object = NULL;
} else {
@@ -7118,7 +7650,7 @@ ZEND_VM_HANDLER(153, ZEND_DECLARE_LAMBDA_FUNCTION, CONST, UNUSED)
called_scope = Z_CE(EX(This));
object = NULL;
}
- zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc),
+ zend_create_closure(EX_VAR(opline->result.var), func,
EX(func)->op_array.scope, called_scope, object);
ZEND_VM_NEXT_OPCODE();
@@ -7192,20 +7724,23 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE
/* If a function call result is yielded and the function did
* not return by reference we throw a notice. */
- if (OP1_TYPE == IS_VAR &&
- (value_ptr == &EG(uninitialized_zval) ||
- (opline->extended_value == ZEND_RETURNS_FUNCTION &&
- !Z_ISREF_P(value_ptr)))) {
- zend_error(E_NOTICE, "Only variable references should be yielded by reference");
- ZVAL_COPY(&generator->value, value_ptr);
- } else {
+ do {
+ if (OP1_TYPE == IS_VAR) {
+ ZEND_ASSERT(value_ptr != &EG(uninitialized_zval));
+ if (opline->extended_value == ZEND_RETURNS_FUNCTION
+ && !Z_ISREF_P(value_ptr)) {
+ zend_error(E_NOTICE, "Only variable references should be yielded by reference");
+ ZVAL_COPY(&generator->value, value_ptr);
+ break;
+ }
+ }
if (Z_ISREF_P(value_ptr)) {
Z_ADDREF_P(value_ptr);
} else {
ZVAL_MAKE_REF_EX(value_ptr, 2);
}
ZVAL_REF(&generator->value, Z_REF_P(value_ptr));
- }
+ } while (0);
FREE_OP1_VAR_PTR();
}
@@ -7289,7 +7824,7 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE
ZEND_VM_RETURN();
}
-ZEND_VM_HANDLER(142, ZEND_YIELD_FROM, CONST|TMP|VAR|CV, ANY)
+ZEND_VM_HANDLER(166, ZEND_YIELD_FROM, CONST|TMP|VAR|CV, ANY)
{
USE_OPLINE
@@ -7456,7 +7991,7 @@ ZEND_VM_HOT_HANDLER(168, ZEND_BIND_GLOBAL, CV, CONST, CACHE_SLOT)
{
USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *varname;
+ zend_string *varname;
zval *value;
zval *variable_ptr;
uintptr_t idx;
@@ -7464,7 +7999,7 @@ ZEND_VM_HOT_HANDLER(168, ZEND_BIND_GLOBAL, CV, CONST, CACHE_SLOT)
ZEND_VM_REPEATABLE_OPCODE
- varname = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ varname = Z_STR_P(GET_OP2_ZVAL_PTR(BP_VAR_R));
/* We store "hash slot index" + 1 (NULL is a mark of uninitialized cache slot) */
idx = (uintptr_t)CACHED_PTR(opline->extended_value) - 1;
@@ -7472,19 +8007,19 @@ ZEND_VM_HOT_HANDLER(168, ZEND_BIND_GLOBAL, CV, CONST, CACHE_SLOT)
Bucket *p = (Bucket*)((char*)EG(symbol_table).arData + idx);
if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) &&
- (EXPECTED(p->key == Z_STR_P(varname)) ||
- (EXPECTED(p->h == ZSTR_H(Z_STR_P(varname))) &&
+ (EXPECTED(p->key == varname) ||
+ (EXPECTED(p->h == ZSTR_H(varname)) &&
EXPECTED(p->key != NULL) &&
- EXPECTED(zend_string_equal_content(p->key, Z_STR_P(varname)))))) {
+ EXPECTED(zend_string_equal_content(p->key, varname))))) {
value = (zval*)p; /* value = &p->val; */
ZEND_VM_C_GOTO(check_indirect);
}
}
- value = zend_hash_find_ex(&EG(symbol_table), Z_STR_P(varname), 1);
+ value = zend_hash_find_ex(&EG(symbol_table), varname, 1);
if (UNEXPECTED(value == NULL)) {
- value = zend_hash_add_new(&EG(symbol_table), Z_STR_P(varname), &EG(uninitialized_zval));
+ value = zend_hash_add_new(&EG(symbol_table), varname, &EG(uninitialized_zval));
idx = (char*)value - (char*)EG(symbol_table).arData;
/* Store "hash slot index" + 1 (NULL is a mark of uninitialized cache slot) */
CACHE_PTR(opline->extended_value, (void*)(idx + 1));
@@ -7560,7 +8095,7 @@ ZEND_VM_COLD_CONST_HANDLER(121, ZEND_STRLEN, CONST|TMPVAR|CV, ANY)
SAVE_OPLINE();
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
- value = GET_OP1_UNDEF_CV(value, BP_VAR_R);
+ value = ZVAL_UNDEFINED_OP1();
}
strict = EX_USES_STRICT_TYPES();
do {
@@ -7576,7 +8111,9 @@ ZEND_VM_COLD_CONST_HANDLER(121, ZEND_STRLEN, CONST|TMPVAR|CV, ANY)
}
zval_ptr_dtor(&tmp);
}
- zend_internal_type_error(strict, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
+ if (!EG(exception)) {
+ zend_internal_type_error(strict, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
+ }
ZVAL_NULL(EX_VAR(opline->result.var));
} while (0);
}
@@ -7606,10 +8143,11 @@ ZEND_VM_C_LABEL(type_check_resource):
} else if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
result = ((1 << IS_NULL) & opline->extended_value) != 0;
SAVE_OPLINE();
- GET_OP1_UNDEF_CV(value, BP_VAR_R);
- ZEND_VM_SMART_BRANCH(result, 1);
- ZVAL_BOOL(EX_VAR(opline->result.var), result);
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+ ZVAL_UNDEFINED_OP1();
+ if (UNEXPECTED(EG(exception))) {
+ ZVAL_UNDEF(EX_VAR(opline->result.var));
+ HANDLE_EXCEPTION();
+ }
}
if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) {
SAVE_OPLINE();
@@ -7628,29 +8166,27 @@ ZEND_VM_HOT_HANDLER(122, ZEND_DEFINED, CONST, ANY, CACHE_SLOT)
{
USE_OPLINE
zend_constant *c;
- int result;
c = CACHED_PTR(opline->extended_value);
- do {
- if (EXPECTED(c != NULL)) {
- if (!IS_SPECIAL_CACHE_VAL(c)) {
- result = 1;
- break;
- } else if (EXPECTED(zend_hash_num_elements(EG(zend_constants)) == DECODE_SPECIAL_CACHE_NUM(c))) {
- result = 0;
- break;
- }
- }
- if (zend_quick_check_constant(RT_CONSTANT(opline, opline->op1) OPLINE_CC EXECUTE_DATA_CC) != SUCCESS) {
- CACHE_PTR(opline->extended_value, ENCODE_SPECIAL_CACHE_NUM(zend_hash_num_elements(EG(zend_constants))));
- result = 0;
- } else {
- result = 1;
+ if (EXPECTED(c != NULL)) {
+ if (!IS_SPECIAL_CACHE_VAL(c)) {
+ZEND_VM_C_LABEL(defined_true):
+ ZEND_VM_SMART_BRANCH_TRUE();
+ ZVAL_TRUE(EX_VAR(opline->result.var));
+ ZEND_VM_NEXT_OPCODE();
+ } else if (EXPECTED(zend_hash_num_elements(EG(zend_constants)) == DECODE_SPECIAL_CACHE_NUM(c))) {
+ZEND_VM_C_LABEL(defined_false):
+ ZEND_VM_SMART_BRANCH_FALSE();
+ ZVAL_FALSE(EX_VAR(opline->result.var));
+ ZEND_VM_NEXT_OPCODE();
}
- } while (0);
- ZEND_VM_SMART_BRANCH(result, 0);
- ZVAL_BOOL(EX_VAR(opline->result.var), result);
- ZEND_VM_NEXT_OPCODE();
+ }
+ if (zend_quick_check_constant(RT_CONSTANT(opline, opline->op1) OPLINE_CC EXECUTE_DATA_CC) != SUCCESS) {
+ CACHE_PTR(opline->extended_value, ENCODE_SPECIAL_CACHE_NUM(zend_hash_num_elements(EG(zend_constants))));
+ ZEND_VM_C_GOTO(defined_false);
+ } else {
+ ZEND_VM_C_GOTO(defined_true);
+ }
}
ZEND_VM_HANDLER(151, ZEND_ASSERT_CHECK, ANY, JMP_ADDR)
@@ -7715,7 +8251,7 @@ ZEND_VM_HANDLER(157, ZEND_FETCH_CLASS_NAME, UNUSED|CLASS_FETCH, ANY)
ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY)
{
- zend_array *args;
+ zend_array *args = NULL;
zend_function *fbc = EX(func);
zval *ret = EX(return_value);
uint32_t call_info = EX_CALL_INFO() & (ZEND_CALL_NESTED | ZEND_CALL_TOP | ZEND_CALL_RELEASE_THIS);
@@ -7746,7 +8282,7 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY)
ZEND_CALL_NUM_ARGS(call) = 2;
ZVAL_STR(ZEND_CALL_ARG(call, 1), fbc->common.function_name);
- if (num_args) {
+ if (args) {
ZVAL_ARR(ZEND_CALL_ARG(call, 2), args);
} else {
ZVAL_EMPTY_ARRAY(ZEND_CALL_ARG(call, 2));
@@ -7755,15 +8291,16 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY)
fbc = call->func;
if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) {
- if (UNEXPECTED(!fbc->op_array.run_time_cache)) {
+ if (UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
init_func_run_time_cache(&fbc->op_array);
}
execute_data = call;
i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
if (EXPECTED(zend_execute_ex == execute_ex)) {
- LOAD_OPLINE();
+ LOAD_OPLINE_EX();
ZEND_VM_ENTER_EX();
} else {
+ SAVE_OPLINE_EX();
execute_data = EX(prev_execute_data);
LOAD_OPLINE();
ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
@@ -7786,10 +8323,10 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY)
}
if (ret == NULL) {
- ZVAL_NULL(&retval);
ret = &retval;
}
+ ZVAL_NULL(ret);
if (!zend_execute_internal) {
/* saves one function call if zend_execute_internal is not used */
fbc->internal_function.handler(call, ret);
@@ -7808,14 +8345,13 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY)
EG(current_execute_data) = call->prev_execute_data;
+ZEND_VM_C_LABEL(call_trampoline_end):
zend_vm_stack_free_args(call);
-
if (ret == &retval) {
zval_ptr_dtor(ret);
}
}
-ZEND_VM_C_LABEL(call_trampoline_end):
execute_data = EG(current_execute_data);
if (!EX(func) || !ZEND_USER_CODE(EX(func)->type) || (call_info & ZEND_CALL_TOP)) {
@@ -7855,9 +8391,9 @@ ZEND_VM_HANDLER(182, ZEND_BIND_LEXICAL, TMP, CV, REF)
}
} else {
var = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
- if (UNEXPECTED(Z_ISUNDEF_P(var))) {
+ if (UNEXPECTED(Z_ISUNDEF_P(var)) && !(opline->extended_value & ZEND_BIND_IMPLICIT)) {
SAVE_OPLINE();
- var = GET_OP2_UNDEF_CV(var, BP_VAR_R);
+ var = ZVAL_UNDEFINED_OP2();
if (UNEXPECTED(EG(exception))) {
HANDLE_EXCEPTION();
}
@@ -7866,11 +8402,12 @@ ZEND_VM_HANDLER(182, ZEND_BIND_LEXICAL, TMP, CV, REF)
Z_TRY_ADDREF_P(var);
}
- zend_closure_bind_var_ex(closure, (opline->extended_value & ~ZEND_BIND_REF), var);
+ zend_closure_bind_var_ex(closure,
+ (opline->extended_value & ~(ZEND_BIND_REF|ZEND_BIND_IMPLICIT)), var);
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(183, ZEND_BIND_STATIC, CV, CONST, REF)
+ZEND_VM_HANDLER(183, ZEND_BIND_STATIC, CV, UNUSED, REF)
{
USE_OPLINE
zend_free_op free_op1;
@@ -7879,18 +8416,22 @@ ZEND_VM_HANDLER(183, ZEND_BIND_STATIC, CV, CONST, REF)
zval *variable_ptr;
variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
- zval_ptr_dtor(variable_ptr);
-
- ht = EX(func)->op_array.static_variables;
- ZEND_ASSERT(ht != NULL);
- if (GC_REFCOUNT(ht) > 1) {
+ i_zval_ptr_dtor(variable_ptr);
+
+ ht = ZEND_MAP_PTR_GET(EX(func)->op_array.static_variables_ptr);
+ if (!ht) {
+ ZEND_ASSERT(EX(func)->op_array.fn_flags & (ZEND_ACC_IMMUTABLE|ZEND_ACC_PRELOADED));
+ ht = zend_array_dup(EX(func)->op_array.static_variables);
+ ZEND_MAP_PTR_SET(EX(func)->op_array.static_variables_ptr, ht);
+ } else if (GC_REFCOUNT(ht) > 1) {
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
GC_DELREF(ht);
}
- EX(func)->op_array.static_variables = ht = zend_array_dup(ht);
+ ht = zend_array_dup(ht);
+ ZEND_MAP_PTR_SET(EX(func)->op_array.static_variables_ptr, ht);
}
- value = (zval*)((char*)ht->arData + (opline->extended_value & ~ZEND_BIND_REF));
+ value = (zval*)((char*)ht->arData + (opline->extended_value & ~(ZEND_BIND_REF|ZEND_BIND_IMPLICIT)));
if (opline->extended_value & ZEND_BIND_REF) {
if (Z_TYPE_P(value) == IS_CONSTANT_AST) {
@@ -7905,6 +8446,7 @@ ZEND_VM_HANDLER(183, ZEND_BIND_STATIC, CV, CONST, REF)
GC_SET_REFCOUNT(ref, 2);
GC_TYPE_INFO(ref) = IS_REFERENCE;
ZVAL_COPY_VALUE(&ref->val, value);
+ ref->sources.ptr = NULL;
Z_REF_P(value) = ref;
Z_TYPE_INFO_P(value) = IS_REFERENCE_EX;
ZVAL_REF(variable_ptr, ref);
@@ -7951,13 +8493,13 @@ ZEND_VM_HANDLER(49, ZEND_CHECK_VAR, CV, UNUSED)
if (UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
SAVE_OPLINE();
- GET_OP1_UNDEF_CV(op1, BP_VAR_R);
+ ZVAL_UNDEFINED_OP1();
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(51, ZEND_MAKE_REF, VAR|CV, UNUSED)
+ZEND_VM_HANDLER(140, ZEND_MAKE_REF, VAR|CV, UNUSED)
{
USE_OPLINE
zval *op1 = EX_VAR(opline->op1.var);
@@ -8059,41 +8601,41 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(189, ZEND_IN_ARRAY, CONST|TMP|VAR|CV, CONST, NUM
zend_free_op free_op1;
zval *op1;
HashTable *ht = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2));
- int result;
+ zval *result;
SAVE_OPLINE();
op1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
- result = zend_hash_exists(ht, Z_STR_P(op1));
+ result = zend_hash_find_ex(ht, Z_STR_P(op1), OP1_TYPE == IS_CONST);
} else if (opline->extended_value) {
if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
- result = zend_hash_index_exists(ht, Z_LVAL_P(op1));
+ result = zend_hash_index_find(ht, Z_LVAL_P(op1));
} else {
- result = 0;
+ result = NULL;
}
} else if (Z_TYPE_P(op1) <= IS_FALSE) {
- result = zend_hash_exists(ht, ZSTR_EMPTY_ALLOC());
+ result = zend_hash_find_ex(ht, ZSTR_EMPTY_ALLOC(), 1);
} else {
zend_string *key;
- zval key_tmp, result_tmp;
+ zval key_tmp, result_tmp, *val;
- result = 0;
- ZEND_HASH_FOREACH_STR_KEY(ht, key) {
+ result = NULL;
+ ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) {
ZVAL_STR(&key_tmp, key);
compare_function(&result_tmp, op1, &key_tmp);
if (Z_LVAL(result_tmp) == 0) {
- result = 1;
+ result = val;
break;
}
} ZEND_HASH_FOREACH_END();
}
FREE_OP1();
ZEND_VM_SMART_BRANCH(result, 1);
- ZVAL_BOOL(EX_VAR(opline->result.var), result);
+ ZVAL_BOOL(EX_VAR(opline->result.var), result != NULL);
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_COLD_CONST_HANDLER(190, ZEND_COUNT, CONST|TMP|VAR|CV, UNUSED)
+ZEND_VM_COLD_CONST_HANDLER(190, ZEND_COUNT, CONST|TMPVAR|CV, UNUSED)
{
USE_OPLINE
zend_free_op free_op1;
@@ -8101,8 +8643,8 @@ ZEND_VM_COLD_CONST_HANDLER(190, ZEND_COUNT, CONST|TMP|VAR|CV, UNUSED)
zend_long count;
SAVE_OPLINE();
- op1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
- do {
+ op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
+ while (1) {
if (Z_TYPE_P(op1) == IS_ARRAY) {
count = zend_array_count(Z_ARRVAL_P(op1));
break;
@@ -8112,6 +8654,10 @@ ZEND_VM_COLD_CONST_HANDLER(190, ZEND_COUNT, CONST|TMP|VAR|CV, UNUSED)
if (SUCCESS == Z_OBJ_HT_P(op1)->count_elements(op1, &count)) {
break;
}
+ if (UNEXPECTED(EG(exception))) {
+ count = 0;
+ break;
+ }
}
/* if not and the object implements Countable we call its count() method */
@@ -8126,20 +8672,27 @@ ZEND_VM_COLD_CONST_HANDLER(190, ZEND_COUNT, CONST|TMP|VAR|CV, UNUSED)
/* If There's no handler and it doesn't implement Countable then add a warning */
count = 1;
- } else if (Z_TYPE_P(op1) == IS_NULL) {
+ } else if ((OP1_TYPE & (IS_VAR|IS_CV)) != 0 && Z_TYPE_P(op1) == IS_REFERENCE) {
+ op1 = Z_REFVAL_P(op1);
+ continue;
+ } else if (Z_TYPE_P(op1) <= IS_NULL) {
+ if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
+ ZVAL_UNDEFINED_OP1();
+ }
count = 0;
} else {
count = 1;
}
- zend_error(E_WARNING, "count(): Parameter must be an array or an object that implements Countable");
- } while (0);
+ zend_error(E_WARNING, "%s(): Parameter must be an array or an object that implements Countable", opline->extended_value ? "sizeof" : "count");
+ break;
+ }
ZVAL_LONG(EX_VAR(opline->result.var), count);
FREE_OP1();
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_COLD_CONST_HANDLER(191, ZEND_GET_CLASS, UNUSED|CONST|TMP|VAR|CV, UNUSED)
+ZEND_VM_COLD_CONST_HANDLER(191, ZEND_GET_CLASS, UNUSED|CONST|TMPVAR|CV, UNUSED)
{
USE_OPLINE
@@ -8158,12 +8711,21 @@ ZEND_VM_COLD_CONST_HANDLER(191, ZEND_GET_CLASS, UNUSED|CONST|TMP|VAR|CV, UNUSED)
zval *op1;
SAVE_OPLINE();
- op1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
- if (Z_TYPE_P(op1) == IS_OBJECT) {
- ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE_P(op1)->name);
- } else {
- zend_error(E_WARNING, "get_class() expects parameter 1 to be object, %s given", zend_get_type_by_const(Z_TYPE_P(op1)));
- ZVAL_FALSE(EX_VAR(opline->result.var));
+ op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
+ while (1) {
+ if (Z_TYPE_P(op1) == IS_OBJECT) {
+ ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE_P(op1)->name);
+ } else if ((OP1_TYPE & (IS_VAR|IS_CV)) != 0 && Z_TYPE_P(op1) == IS_REFERENCE) {
+ op1 = Z_REFVAL_P(op1);
+ continue;
+ } else {
+ if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
+ ZVAL_UNDEFINED_OP1();
+ }
+ zend_error(E_WARNING, "get_class() expects parameter 1 to be object, %s given", zend_get_type_by_const(Z_TYPE_P(op1)));
+ ZVAL_FALSE(EX_VAR(opline->result.var));
+ }
+ break;
}
FREE_OP1();
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
@@ -8208,7 +8770,7 @@ ZEND_VM_COLD_CONST_HANDLER(193, ZEND_GET_TYPE, CONST|TMP|VAR|CV, UNUSED)
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(194, ZEND_FUNC_NUM_ARGS, UNUSED, UNUSED)
+ZEND_VM_HANDLER(171, ZEND_FUNC_NUM_ARGS, UNUSED, UNUSED)
{
USE_OPLINE
@@ -8216,7 +8778,7 @@ ZEND_VM_HANDLER(194, ZEND_FUNC_NUM_ARGS, UNUSED, UNUSED)
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(195, ZEND_FUNC_GET_ARGS, UNUSED|CONST, UNUSED)
+ZEND_VM_HANDLER(172, ZEND_FUNC_GET_ARGS, UNUSED|CONST, UNUSED)
{
USE_OPLINE
zend_array *ht;
@@ -8253,10 +8815,11 @@ ZEND_VM_HANDLER(195, ZEND_FUNC_GET_ARGS, UNUSED|CONST, UNUSED)
if (Z_OPT_REFCOUNTED_P(q)) {
Z_ADDREF_P(q);
}
+ ZEND_HASH_FILL_SET(q);
} else {
- q = &EG(uninitialized_zval);
+ ZEND_HASH_FILL_SET_NULL();
}
- ZEND_HASH_FILL_ADD(q);
+ ZEND_HASH_FILL_NEXT();
p++;
i++;
}
@@ -8274,10 +8837,11 @@ ZEND_VM_HANDLER(195, ZEND_FUNC_GET_ARGS, UNUSED|CONST, UNUSED)
if (Z_OPT_REFCOUNTED_P(q)) {
Z_ADDREF_P(q);
}
+ ZEND_HASH_FILL_SET(q);
} else {
- q = &EG(uninitialized_zval);
+ ZEND_HASH_FILL_SET_NULL();
}
- ZEND_HASH_FILL_ADD(q);
+ ZEND_HASH_FILL_NEXT();
p++;
i++;
}
@@ -8289,6 +8853,16 @@ ZEND_VM_HANDLER(195, ZEND_FUNC_GET_ARGS, UNUSED|CONST, UNUSED)
ZEND_VM_NEXT_OPCODE();
}
+ZEND_VM_HANDLER(167, ZEND_COPY_TMP, TMPVAR, UNUSED)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *value = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ zval *result = EX_VAR(opline->result.var);
+ ZVAL_COPY(result, value);
+ ZEND_VM_NEXT_OPCODE();
+}
+
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_JMP, (OP_JMP_ADDR(op, op->op1) > op), ZEND_JMP_FORWARD, JMP_ADDR, ANY)
{
USE_OPLINE
@@ -8545,23 +9119,6 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_PRE_INC, (op1_info == MAY_BE_LONG), ZEND_PRE_
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_PRE_INC, (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)), ZEND_PRE_INC_LONG_OR_DOUBLE, 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);
- } else {
- Z_DVAL_P(var_ptr)++;
- }
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr);
- }
- ZEND_VM_NEXT_OPCODE();
-}
-
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_PRE_DEC, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG), ZEND_PRE_DEC_LONG_NO_OVERFLOW, CV, ANY, SPEC(RETVAL))
{
USE_OPLINE
@@ -8588,23 +9145,6 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_PRE_DEC, (op1_info == MAY_BE_LONG), ZEND_PRE_
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_PRE_DEC, (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)), ZEND_PRE_DEC_LONG_OR_DOUBLE, 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);
- } else {
- Z_DVAL_P(var_ptr)--;
- }
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr);
- }
- ZEND_VM_NEXT_OPCODE();
-}
-
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_POST_INC, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG), ZEND_POST_INC_LONG_NO_OVERFLOW, CV, ANY)
{
USE_OPLINE
@@ -8627,22 +9167,6 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_POST_INC, (op1_info == MAY_BE_LONG), ZEND_POS
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_POST_INC, (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)), ZEND_POST_INC_LONG_OR_DOUBLE, 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);
- } else {
- ZVAL_DOUBLE(EX_VAR(opline->result.var), Z_DVAL_P(var_ptr));
- Z_DVAL_P(var_ptr)++;
- }
- ZEND_VM_NEXT_OPCODE();
-}
-
ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_POST_DEC, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG), ZEND_POST_DEC_LONG_NO_OVERFLOW, CV, ANY)
{
USE_OPLINE
@@ -8665,19 +9189,14 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_POST_DEC, (op1_info == MAY_BE_LONG), ZEND_POS
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_POST_DEC, (op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE)), ZEND_POST_DEC_LONG_OR_DOUBLE, CV, ANY)
+ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_QM_ASSIGN, (op1_info == MAY_BE_LONG), ZEND_QM_ASSIGN_LONG, CONST|TMPVARCV, ANY)
{
USE_OPLINE
- zval *var_ptr;
+ zend_free_op free_op1;
+ zval *value;
- 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);
- } else {
- ZVAL_DOUBLE(EX_VAR(opline->result.var), Z_DVAL_P(var_ptr));
- Z_DVAL_P(var_ptr)--;
- }
+ value = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
+ ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(value));
ZEND_VM_NEXT_OPCODE();
}
@@ -8872,7 +9391,7 @@ ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_FE_FETCH_R, op->op2_type == IS_CV && (op1_inf
}
variable_ptr = EX_VAR(opline->op2.var);
- zend_assign_to_variable(variable_ptr, value, IS_CV);
+ zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES());
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}