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.h231
1 files changed, 138 insertions, 93 deletions
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 60983e516f..95968d8ac6 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -385,7 +385,7 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMP|VAR
zval *value = Z_OBJ_HT_P(z)->get(z, &rv TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- zval_dtor(z);
+ zend_objects_store_del(Z_OBJ_P(z) TSRMLS_CC);
}
ZVAL_COPY_VALUE(z, value);
}
@@ -711,7 +711,7 @@ ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR|
zval *value = Z_OBJ_HT_P(z)->get(z, &rv TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- zval_dtor(z);
+ zend_objects_store_del(Z_OBJ_P(z) TSRMLS_CC);
}
ZVAL_COPY_VALUE(z, value);
}
@@ -798,7 +798,7 @@ ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMP|VAR
zval *value = Z_OBJ_HT_P(z)->get(z, &rv TSRMLS_CC);
if (Z_REFCOUNT_P(z) == 0) {
- zval_dtor(z);
+ zend_objects_store_del(Z_OBJ_P(z) TSRMLS_CC);
}
ZVAL_COPY_VALUE(z, value);
}
@@ -1199,7 +1199,7 @@ ZEND_VM_HANDLER(84, ZEND_FETCH_DIM_W, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
ZVAL_DEREF(container);
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R), OP2_TYPE TSRMLS_CC);
FREE_OP2();
- if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
+ if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
FREE_OP1_VAR_PTR();
@@ -1222,7 +1222,7 @@ ZEND_VM_HANDLER(87, ZEND_FETCH_DIM_RW, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
ZVAL_DEREF(container);
zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R), OP2_TYPE TSRMLS_CC);
FREE_OP2();
- if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
+ if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
FREE_OP1_VAR_PTR();
@@ -1263,7 +1263,7 @@ ZEND_VM_HANDLER(93, ZEND_FETCH_DIM_FUNC_ARG, CONST|TMP|VAR|CV, CONST|TMP|VAR|UNU
}
ZVAL_DEREF(container);
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R), OP2_TYPE TSRMLS_CC);
- if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
+ if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
FREE_OP2();
@@ -1296,7 +1296,7 @@ ZEND_VM_HANDLER(96, ZEND_FETCH_DIM_UNSET, VAR|CV, CONST|TMP|VAR|CV)
ZVAL_DEREF(container);
zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R), OP2_TYPE TSRMLS_CC);
FREE_OP2();
- if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
+ if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
FREE_OP1_VAR_PTR();
@@ -1324,11 +1324,33 @@ ZEND_VM_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV)
zval *retval;
/* here we are sure we are dealing with an object */
- retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC);
+ do {
+ if (OP2_TYPE == IS_CONST &&
+ EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) {
+ zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1);
+ zend_object *zobj = Z_OBJ_P(container);
+
+ if (EXPECTED(prop_info)) {
+ retval = OBJ_PROP(zobj, prop_info->offset);
+ if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), retval);
+ break;
+ }
+ } else if (EXPECTED(zobj->properties != NULL)) {
+ retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
+ if (EXPECTED(retval)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), retval);
+ break;
+ }
+ }
+ }
- if (retval != EX_VAR(opline->result.var)) {
- ZVAL_COPY(EX_VAR(opline->result.var), retval);
- }
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC);
+
+ if (retval != EX_VAR(opline->result.var)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), retval);
+ }
+ } while (0);
}
FREE_OP2();
@@ -1352,9 +1374,9 @@ ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC);
+ zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC);
FREE_OP2();
- if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
+ if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
FREE_OP1_VAR_PTR();
@@ -1376,9 +1398,9 @@ ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC);
+ zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW TSRMLS_CC);
FREE_OP2();
- if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
+ if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
FREE_OP1_VAR_PTR();
@@ -1405,11 +1427,33 @@ ZEND_VM_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV
zval *retval;
/* here we are sure we are dealing with an object */
- retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC);
+ do {
+ if (OP2_TYPE == IS_CONST &&
+ EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) {
+ zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1);
+ zend_object *zobj = Z_OBJ_P(container);
+
+ if (EXPECTED(prop_info)) {
+ retval = OBJ_PROP(zobj, prop_info->offset);
+ if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), retval);
+ break;
+ }
+ } else if (EXPECTED(zobj->properties != NULL)) {
+ retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
+ if (EXPECTED(retval)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), retval);
+ break;
+ }
+ }
+ }
- if (retval != EX_VAR(opline->result.var)) {
- ZVAL_COPY(EX_VAR(opline->result.var), retval);
- }
+ retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var) TSRMLS_CC);
+
+ if (retval != EX_VAR(opline->result.var)) {
+ ZVAL_COPY(EX_VAR(opline->result.var), retval);
+ }
+ } while (0);
}
FREE_OP2();
@@ -1438,9 +1482,9 @@ ZEND_VM_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|
if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC);
+ zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W TSRMLS_CC);
FREE_OP2();
- if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
+ if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
FREE_OP1_VAR_PTR();
@@ -1464,9 +1508,9 @@ ZEND_VM_HANDLER(97, ZEND_FETCH_OBJ_UNSET, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
}
- zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC);
+ zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? (EX(run_time_cache) + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET TSRMLS_CC);
FREE_OP2();
- if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1.var)) {
+ if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1)) {
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
}
FREE_OP1_VAR_PTR();
@@ -2036,7 +2080,7 @@ ZEND_VM_HANDLER(56, ZEND_ADD_VAR, TMP|UNUSED, TMP|VAR|CV)
add_string_to_string(str, str, var);
if (use_copy) {
- zval_dtor(var);
+ zend_string_release(Z_STR_P(var));
}
/* original comment, possibly problematic:
* FREE_OP is missing intentionally here - we're always working on the same temporary variable
@@ -2631,7 +2675,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
zval *p = ZEND_CALL_ARG(call, 1);
for (i = 0; i < call->num_args; ++i) {
- zend_verify_arg_type(fbc, i + 1, p TSRMLS_CC);
+ zend_verify_arg_type(fbc, i + 1, p, NULL TSRMLS_CC);
p++;
}
if (UNEXPECTED(EG(exception) != NULL)) {
@@ -2936,9 +2980,7 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, CV)
}
exception = EG(exception);
- if (Z_REFCOUNTED_P(EX_VAR(opline->op2.var))) {
- zval_ptr_dtor(EX_VAR(opline->op2.var));
- }
+ zval_ptr_dtor(EX_VAR(opline->op2.var));
ZVAL_OBJ(EX_VAR(opline->op2.var), EG(exception));
if (UNEXPECTED(EG(exception) != exception)) {
GC_REFCOUNT(EG(exception))++;
@@ -3018,11 +3060,8 @@ ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR|CV, ANY)
zval *varptr, *arg;
SAVE_OPLINE();
- if (opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) { /* Had function_ptr at compile_time */
- if (!(opline->extended_value & ZEND_ARG_SEND_BY_REF)) {
- ZEND_VM_DISPATCH_TO_HANDLER(ZEND_SEND_VAR);
- }
- } else {
+
+ if (!(opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND)) {
if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_SEND_VAR);
}
@@ -3037,20 +3076,18 @@ ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR|CV, ANY)
if (OP1_TYPE == IS_CV) {
Z_ADDREF_P(varptr);
}
- arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
- EX(call)->num_args = opline->op2.num;
- ZVAL_COPY_VALUE(arg, varptr);
} else {
if ((opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) ?
!(opline->extended_value & ZEND_ARG_SEND_SILENT) :
!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
zend_error(E_STRICT, "Only variables should be passed by reference");
}
- arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
- EX(call)->num_args = opline->op2.num;
- ZVAL_COPY(arg, varptr);
- FREE_OP1_IF_VAR();
}
+
+ arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
+ EX(call)->num_args = opline->op2.num;
+ ZVAL_COPY_VALUE(arg, varptr);
+
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -3080,12 +3117,11 @@ ZEND_VM_HANDLER(67, ZEND_SEND_REF, VAR|CV, ANY)
ZVAL_COPY_VALUE(arg, varptr);
} else if (OP1_TYPE == IS_VAR &&
UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) {
- ZVAL_COPY_VALUE(arg, varptr);
- ZVAL_MAKE_REF(arg);
+ ZVAL_NEW_REF(arg, varptr);
} else {
- ZVAL_MAKE_REF(varptr);
- Z_ADDREF_P(varptr);
- ZVAL_REF(arg, Z_REF_P(varptr));
+ ZVAL_NEW_REF(arg, varptr);
+ Z_ADDREF_P(arg);
+ ZVAL_REF(varptr, Z_REF_P(arg));
}
FREE_OP1_VAR_PTR();
@@ -3231,7 +3267,7 @@ ZEND_VM_C_LABEL(send_again):
if (Z_TYPE(key) == IS_STRING) {
zend_error(E_RECOVERABLE_ERROR,
"Cannot unpack Traversable with string keys");
- zval_dtor(&key);
+ zend_string_release(Z_STR(key));
ZEND_VM_C_GOTO(unpack_iter_dtor);
}
@@ -3490,7 +3526,7 @@ ZEND_VM_HANDLER(63, ZEND_RECV, ANY, ANY)
} else if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
zval *param = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
- zend_verify_arg_type(EX(func), arg_num, param TSRMLS_CC);
+ zend_verify_arg_type(EX(func), arg_num, param, NULL TSRMLS_CC);
CHECK_EXCEPTION();
}
@@ -3501,15 +3537,20 @@ ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST)
{
USE_OPLINE
uint32_t arg_num = opline->op1.num;
- zval *param;
+ zval *param, default_val = {{0}};
SAVE_OPLINE();
+ if (Z_OPT_CONSTANT_P(opline->op2.zv)) {
+ ZVAL_COPY_VALUE(&default_val, opline->op2.zv);
+ zval_update_constant(&default_val, 0 TSRMLS_CC);
+ }
+
param = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
if (arg_num > EX(num_args)) {
- ZVAL_COPY_VALUE(param, opline->op2.zv);
- if (Z_OPT_CONSTANT_P(param)) {
- zval_update_constant(param, 0 TSRMLS_CC);
+ if (Z_TYPE(default_val) != IS_UNDEF) {
+ *param = default_val;
} else {
+ ZVAL_COPY_VALUE(param, opline->op2.zv);
/* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
if (UNEXPECTED(Z_OPT_COPYABLE_P(param))) {
zval_copy_ctor_func(param);
@@ -3518,7 +3559,11 @@ ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST)
}
if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
- zend_verify_arg_type(EX(func), arg_num, param TSRMLS_CC);
+ zend_verify_arg_type(EX(func), arg_num, param, Z_TYPE(default_val) == IS_UNDEF ? NULL : &default_val TSRMLS_CC);
+ }
+
+ if (Z_TYPE(default_val) != IS_UNDEF && arg_num <= EX(num_args)) {
+ zval_dtor(&default_val);
}
CHECK_EXCEPTION();
@@ -3543,7 +3588,7 @@ ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, ANY, ANY)
param = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T);
if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
do {
- zend_verify_arg_type(EX(func), arg_num, param TSRMLS_CC);
+ zend_verify_arg_type(EX(func), arg_num, param, NULL TSRMLS_CC);
zend_hash_next_index_insert_new(Z_ARRVAL_P(params), param);
if (Z_REFCOUNTED_P(param)) Z_ADDREF_P(param);
param++;
@@ -3674,7 +3719,7 @@ ZEND_VM_HANDLER(68, ZEND_NEW, CONST|VAR, ANY)
if (RETURN_VALUE_USED(opline)) {
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), &object_zval);
} else {
- zval_ptr_dtor(&object_zval);
+ OBJ_RELEASE(Z_OBJ(object_zval));
}
ZEND_VM_JMP(opline->op2.jmp_addr);
} else {
@@ -3752,7 +3797,7 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMP|VAR|UNUSED|CV, ANY)
if (EXPECTED(EG(exception) == NULL)) {
ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj TSRMLS_CC));
if (!RETURN_VALUE_USED(opline) || UNEXPECTED(EG(exception) != NULL)) {
- zval_ptr_dtor(EX_VAR(opline->result.var));
+ OBJ_RELEASE(Z_OBJ_P(EX_VAR(opline->result.var)));
}
}
FREE_OP1_IF_VAR();
@@ -4159,7 +4204,7 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY)
}
}
if (Z_TYPE(tmp_inc_filename) != IS_UNDEF) {
- zval_ptr_dtor(&tmp_inc_filename);
+ zend_string_release(Z_STR(tmp_inc_filename));
}
FREE_OP1();
if (UNEXPECTED(EG(exception) != NULL)) {
@@ -4250,8 +4295,8 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR)
} else {
ce = zend_fetch_class_by_name(Z_STR_P(opline->op2.zv), opline->op2.zv + 1, 0 TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
- if (OP1_TYPE != IS_CONST) {
- zval_dtor(&tmp);
+ if (OP1_TYPE != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
+ zend_string_release(Z_STR(tmp));
}
FREE_OP1();
HANDLE_EXCEPTION();
@@ -4270,8 +4315,8 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR)
zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
}
- if (OP1_TYPE != IS_CONST) {
- zval_dtor(&tmp);
+ if (OP1_TYPE != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
+ zend_string_release(Z_STR(tmp));
}
FREE_OP1();
CHECK_EXCEPTION();
@@ -4854,6 +4899,7 @@ ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR)
zend_free_op free_op1;
zval tmp, *varname = GET_OP1_ZVAL_PTR(BP_VAR_IS);
+ ZVAL_UNDEF(&tmp);
if (OP1_TYPE != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
ZVAL_STR(&tmp, zval_get_string(varname));
varname = &tmp;
@@ -4882,8 +4928,8 @@ ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR)
value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname));
}
- if (OP1_TYPE != IS_CONST && varname == &tmp) {
- zval_dtor(&tmp);
+ if (OP1_TYPE != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
+ zend_string_release(Z_STR(tmp));
}
FREE_OP1();
@@ -4982,7 +5028,7 @@ ZEND_VM_C_LABEL(num_index_prop):
result = 0;
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
- if (OP1_TYPE == IS_CV || OP1_TYPE == IS_VAR) {
+ if (OP2_TYPE == IS_CV || OP2_TYPE == IS_VAR) {
ZVAL_DEREF(offset);
}
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
@@ -5860,23 +5906,39 @@ ZEND_VM_HANDLER(168, ZEND_BIND_GLOBAL, CV, CONST)
zval *varname;
zval *value;
zval *variable_ptr;
- Bucket *p;
uint32_t idx;
SAVE_OPLINE();
varname = GET_OP2_ZVAL_PTR(BP_VAR_R);
- idx = (uint32_t)(uintptr_t)CACHED_PTR(Z_CACHE_SLOT_P(varname));
- /* index 0 can't be cached (NULL is a mark of uninitialized cache slot) */
- p = EG(symbol_table).ht.arData + idx;
- if (EXPECTED(idx > 0) &&
- EXPECTED(idx < EG(symbol_table).ht.nNumUsed) &&
- EXPECTED(Z_TYPE(p->val) != IS_UNDEF) &&
- (EXPECTED(p->key == Z_STR_P(varname)) ||
- (EXPECTED(p->h == Z_STR_P(varname)->h) &&
- EXPECTED(p->key != NULL) &&
- EXPECTED(p->key->len == Z_STRLEN_P(varname)) &&
- EXPECTED(memcmp(p->key->val, Z_STRVAL_P(varname), Z_STRLEN_P(varname)) == 0)))) {
- value = &EG(symbol_table).ht.arData[idx].val;
+
+ /* We store "hash slot index" + 1 (NULL is a mark of uninitialized cache slot) */
+ idx = (uint32_t)(uintptr_t)CACHED_PTR(Z_CACHE_SLOT_P(varname)) - 1;
+ if (EXPECTED(idx < EG(symbol_table).ht.nNumUsed)) {
+ Bucket *p = EG(symbol_table).ht.arData + idx;
+
+ if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) &&
+ (EXPECTED(p->key == Z_STR_P(varname)) ||
+ (EXPECTED(p->h == Z_STR_P(varname)->h) &&
+ EXPECTED(p->key != NULL) &&
+ EXPECTED(p->key->len == Z_STRLEN_P(varname)) &&
+ EXPECTED(memcmp(p->key->val, Z_STRVAL_P(varname), Z_STRLEN_P(varname)) == 0)))) {
+
+ value = &EG(symbol_table).ht.arData[idx].val;
+ ZEND_VM_C_GOTO(check_indirect);
+ }
+ }
+
+ value = zend_hash_find(&EG(symbol_table).ht, Z_STR_P(varname));
+ if (UNEXPECTED(value == NULL)) {
+ value = zend_hash_add_new(&EG(symbol_table).ht, Z_STR_P(varname), &EG(uninitialized_zval));
+ idx = ((char*)value - (char*)EG(symbol_table).ht.arData) / sizeof(Bucket);
+ /* Store "hash slot index" + 1 (NULL is a mark of uninitialized cache slot) */
+ CACHE_PTR(Z_CACHE_SLOT_P(varname), (void*)(uintptr_t)(idx + 1));
+ } else {
+ idx = ((char*)value - (char*)EG(symbol_table).ht.arData) / sizeof(Bucket);
+ /* Store "hash slot index" + 1 (NULL is a mark of uninitialized cache slot) */
+ CACHE_PTR(Z_CACHE_SLOT_P(varname), (void*)(uintptr_t)(idx + 1));
+ZEND_VM_C_LABEL(check_indirect):
/* GLOBAL variable may be an INDIRECT pointer to CV */
if (UNEXPECTED(Z_TYPE_P(value) == IS_INDIRECT)) {
value = Z_INDIRECT_P(value);
@@ -5884,23 +5946,6 @@ ZEND_VM_HANDLER(168, ZEND_BIND_GLOBAL, CV, CONST)
ZVAL_NULL(value);
}
}
- } else {
- value = zend_hash_find(&EG(symbol_table).ht, Z_STR_P(varname));
- if (UNEXPECTED(value == NULL)) {
- value = zend_hash_add_new(&EG(symbol_table).ht, Z_STR_P(varname), &EG(uninitialized_zval));
- idx = ((char*)value - (char*)EG(symbol_table).ht.arData) / sizeof(Bucket);
- CACHE_PTR(Z_CACHE_SLOT_P(varname), (void*)(uintptr_t)idx);
- } else {
- idx = ((char*)value - (char*)EG(symbol_table).ht.arData) / sizeof(Bucket);
- CACHE_PTR(Z_CACHE_SLOT_P(varname), (void*)(uintptr_t)idx);
- /* GLOBAL variable may be an INDIRECT pointer to CV */
- if (UNEXPECTED(Z_TYPE_P(value) == IS_INDIRECT)) {
- value = Z_INDIRECT_P(value);
- if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
- ZVAL_NULL(value);
- }
- }
- }
}
variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);