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.h157
1 files changed, 88 insertions, 69 deletions
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index ada20ca308..2bc80faa4e 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -1170,22 +1170,18 @@ ZEND_VM_HANDLER(81, ZEND_FETCH_DIM_R, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV)
SAVE_OPLINE();
- if ((opline->extended_value & ZEND_FETCH_ADD_LOCK) &&
- OP1_TYPE != IS_CV &&
- EX_T(opline->op1.var).var.ptr_ptr) {
- PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr);
- }
-
if (OP1_TYPE == IS_TMP_VAR || OP1_TYPE == IS_CONST) {
zval *container = GET_OP1_ZVAL_PTR(BP_VAR_R);
zend_fetch_dimension_address_read(&EX_T(opline->result.var), &container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE, BP_VAR_R TSRMLS_CC);
FREE_OP2();
FREE_OP1();
} else {
- container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_R);
+ container = GET_OP1_ZVAL_PTR_PTR_FAST(BP_VAR_R);
zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE, BP_VAR_R TSRMLS_CC);
FREE_OP2();
- FREE_OP1_VAR_PTR();
+ if (OP1_TYPE == IS_VAR && !(opline->extended_value & ZEND_FETCH_ADD_LOCK)) {
+ FREE_OP1_VAR_PTR_FAST();
+ }
}
CHECK_EXCEPTION();
@@ -1255,10 +1251,10 @@ ZEND_VM_HANDLER(90, ZEND_FETCH_DIM_IS, VAR|CV, CONST|TMP|VAR|CV)
zval **container;
SAVE_OPLINE();
- container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_IS);
+ container = GET_OP1_ZVAL_PTR_PTR_FAST(BP_VAR_IS);
zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE, BP_VAR_IS TSRMLS_CC);
FREE_OP2();
- FREE_OP1_VAR_PTR();
+ FREE_OP1_VAR_PTR_FAST();
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -1280,15 +1276,17 @@ ZEND_VM_HANDLER(93, ZEND_FETCH_DIM_FUNC_ARG, VAR|CV, CONST|TMP|VAR|UNUSED|CV)
if (OP1_TYPE == IS_VAR && OP1_FREE && READY_TO_DESTROY(free_op1.var)) {
EXTRACT_ZVAL_PTR(&EX_T(opline->result.var));
}
+ FREE_OP2();
+ FREE_OP1_VAR_PTR();
} else {
if (OP2_TYPE == IS_UNUSED) {
zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
}
- container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_R);
+ container = GET_OP1_ZVAL_PTR_PTR_FAST(BP_VAR_R);
zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE, BP_VAR_R TSRMLS_CC);
+ FREE_OP2();
+ FREE_OP1_VAR_PTR_FAST();
}
- FREE_OP2();
- FREE_OP1_VAR_PTR();
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -1928,14 +1926,15 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) {
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) {
zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", fbc->common.scope->name, fbc->common.function_name);
- CHECK_EXCEPTION();
- ZEND_VM_NEXT_OPCODE(); /* Never reached */
}
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) {
zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated",
fbc->common.scope ? fbc->common.scope->name : "",
fbc->common.scope ? "::" : "",
fbc->common.function_name);
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
+ }
}
}
if (fbc->common.scope &&
@@ -1945,6 +1944,9 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
/* FIXME: output identifiers properly */
zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically", fbc->common.scope->name, fbc->common.function_name);
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
+ }
} else {
/* FIXME: output identifiers properly */
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
@@ -1988,7 +1990,7 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
if (!zend_execute_internal) {
/* saves one function call if zend_execute_internal is not used */
- fbc->internal_function.handler(opline->extended_value, ret->var.ptr, (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? &ret->var.ptr : NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);
+ fbc->internal_function.handler(opline->extended_value, ret->var.ptr, &ret->var.ptr, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC);
} else {
zend_execute_internal(execute_data, NULL, RETURN_VALUE_USED(opline) TSRMLS_CC);
}
@@ -2607,7 +2609,7 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS
/* We are calling method of the other (incompatible) class,
but passing $this. This is done for compatibility with php-4. */
if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
- zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name);
+ zend_error(E_DEPRECATED, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name);
} else {
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name);
@@ -2682,7 +2684,7 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV)
if (call->object) {
Z_ADDREF_P(call->object);
}
- if (OP2_TYPE == IS_VAR && OP2_FREE &&
+ if (OP2_TYPE == IS_VAR && OP2_FREE && Z_REFCOUNT_P(function_name) == 1 &&
call->fbc->common.fn_flags & ZEND_ACC_CLOSURE) {
/* Delay closure destruction until its invocation */
call->fbc->common.prototype = (zend_function*)function_name;
@@ -2842,9 +2844,7 @@ ZEND_VM_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY)
retval_ptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
if (!EG(return_value_ptr_ptr)) {
- if (OP1_TYPE == IS_TMP_VAR) {
- FREE_OP1();
- }
+ FREE_OP1();
} else {
if (OP1_TYPE == IS_CONST ||
OP1_TYPE == IS_TMP_VAR ||
@@ -2857,18 +2857,23 @@ ZEND_VM_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY)
zval_copy_ctor(ret);
}
*EG(return_value_ptr_ptr) = ret;
+ FREE_OP1_IF_VAR();
} else if ((OP1_TYPE == IS_CV || OP1_TYPE == IS_VAR) &&
retval_ptr == &EG(uninitialized_zval)) {
zval *ret;
+ if (OP1_TYPE == IS_VAR) {
+ Z_DELREF_P(retval_ptr);
+ }
ALLOC_INIT_ZVAL(ret);
*EG(return_value_ptr_ptr) = ret;
} else {
*EG(return_value_ptr_ptr) = retval_ptr;
- Z_ADDREF_P(retval_ptr);
+ if (OP1_TYPE == IS_CV) {
+ Z_ADDREF_P(retval_ptr);
+ }
}
}
- FREE_OP1_IF_VAR();
ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
}
@@ -2939,7 +2944,7 @@ ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY)
}
} while (0);
- FREE_OP1_IF_VAR();
+ FREE_OP1_VAR_PTR();
ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
}
@@ -3082,21 +3087,26 @@ ZEND_VM_HELPER(zend_send_by_var_helper, VAR|CV, ANY)
varptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
if (varptr == &EG(uninitialized_zval)) {
- ALLOC_ZVAL(varptr);
- INIT_ZVAL(*varptr);
- Z_SET_REFCOUNT_P(varptr, 0);
+ if (OP1_TYPE == IS_VAR) {
+ Z_DELREF_P(varptr);
+ }
+ ALLOC_INIT_ZVAL(varptr);
} else if (PZVAL_IS_REF(varptr)) {
- zval *original_var = varptr;
+ if (OP1_TYPE == IS_CV ||
+ (OP1_TYPE == IS_VAR && Z_REFCOUNT_P(varptr) > 2)) {
+ zval *original_var = varptr;
- ALLOC_ZVAL(varptr);
- ZVAL_COPY_VALUE(varptr, original_var);
- Z_UNSET_ISREF_P(varptr);
- Z_SET_REFCOUNT_P(varptr, 0);
- zval_copy_ctor(varptr);
+ ALLOC_ZVAL(varptr);
+ INIT_PZVAL_COPY(varptr, original_var);
+ zval_copy_ctor(varptr);
+ FREE_OP1();
+ } else {
+ Z_UNSET_ISREF_P(varptr);
+ }
+ } else if (OP1_TYPE == IS_CV) {
+ Z_ADDREF_P(varptr);
}
- Z_ADDREF_P(varptr);
zend_vm_stack_push(varptr TSRMLS_CC);
- FREE_OP1(); /* for string offsets */
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
@@ -3117,22 +3127,15 @@ ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR|CV, ANY)
ZEND_VM_DISPATCH_TO_HELPER(zend_send_by_var_helper);
}
- if (OP1_TYPE == IS_VAR &&
- (opline->extended_value & ZEND_ARG_SEND_FUNCTION) &&
- EX_T(opline->op1.var).var.fcall_returned_reference &&
- EX_T(opline->op1.var).var.ptr) {
- varptr = EX_T(opline->op1.var).var.ptr;
- PZVAL_UNLOCK_EX(varptr, &free_op1, 0);
- } else {
- varptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
- }
+ varptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
if ((!(opline->extended_value & ZEND_ARG_SEND_FUNCTION) ||
EX_T(opline->op1.var).var.fcall_returned_reference) &&
varptr != &EG(uninitialized_zval) &&
- (PZVAL_IS_REF(varptr) ||
- (Z_REFCOUNT_P(varptr) == 1 && (OP1_TYPE == IS_CV || free_op1.var)))) {
+ (PZVAL_IS_REF(varptr) || Z_REFCOUNT_P(varptr) == 1)) {
Z_SET_ISREF_P(varptr);
- Z_ADDREF_P(varptr);
+ if (OP1_TYPE == IS_CV) {
+ Z_ADDREF_P(varptr);
+ }
zend_vm_stack_push(varptr TSRMLS_CC);
} else {
zval *valptr;
@@ -3147,9 +3150,9 @@ ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR|CV, ANY)
if (!IS_OP1_TMP_FREE()) {
zval_copy_ctor(valptr);
}
+ FREE_OP1_IF_VAR();
zend_vm_stack_push(valptr TSRMLS_CC);
}
- FREE_OP1_IF_VAR();
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -3348,9 +3351,6 @@ ZEND_VM_HANDLER(48, ZEND_CASE, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV)
zend_free_op free_op1, free_op2;
SAVE_OPLINE();
- if (OP1_TYPE==IS_VAR) {
- PZVAL_LOCK(EX_T(opline->op1.var).var.ptr);
- }
is_equal_function(&EX_T(opline->result.var).tmp_var,
GET_OP1_ZVAL_PTR(BP_VAR_R),
GET_OP2_ZVAL_PTR(BP_VAR_R) TSRMLS_CC);
@@ -3614,7 +3614,8 @@ ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMP|VAR|UNUS
INIT_PZVAL_COPY(new_expr, expr_ptr);
expr_ptr = new_expr;
zendi_zval_copy_ctor(*expr_ptr);
- } else {
+ FREE_OP1_IF_VAR();
+ } else if (OP1_TYPE == IS_CV) {
Z_ADDREF_P(expr_ptr);
}
}
@@ -3662,8 +3663,6 @@ ZEND_VM_C_LABEL(num_index):
}
if ((OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) && opline->extended_value) {
FREE_OP1_VAR_PTR();
- } else {
- FREE_OP1_IF_VAR();
}
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
@@ -4152,19 +4151,27 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY)
} else if (Z_TYPE_P(array_ptr) == IS_OBJECT) {
ce = Z_OBJCE_P(array_ptr);
if (!ce || !ce->get_iterator) {
- Z_ADDREF_P(array_ptr);
+ if (OP1_TYPE == IS_CV) {
+ Z_ADDREF_P(array_ptr);
+ }
}
} else if (OP1_TYPE == IS_CONST ||
- ((OP1_TYPE == IS_CV || OP1_TYPE == IS_VAR) &&
+ (OP1_TYPE == IS_CV &&
+ !Z_ISREF_P(array_ptr) &&
+ Z_REFCOUNT_P(array_ptr) > 1) ||
+ (OP1_TYPE == IS_VAR &&
!Z_ISREF_P(array_ptr) &&
- Z_REFCOUNT_P(array_ptr) > 1)) {
+ Z_REFCOUNT_P(array_ptr) > 2)) {
zval *tmp;
+ if (OP1_TYPE == IS_VAR) {
+ Z_DELREF_P(array_ptr);
+ }
ALLOC_ZVAL(tmp);
INIT_PZVAL_COPY(tmp, array_ptr);
zval_copy_ctor(tmp);
array_ptr = tmp;
- } else {
+ } else if (OP1_TYPE == IS_CV) {
Z_ADDREF_P(array_ptr);
}
}
@@ -4172,10 +4179,15 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY)
if (ce && ce->get_iterator) {
iter = ce->get_iterator(ce, array_ptr, opline->extended_value & ZEND_FE_RESET_REFERENCE TSRMLS_CC);
+ if (OP1_TYPE == IS_VAR && !(opline->extended_value & ZEND_FE_RESET_VARIABLE)) {
+ FREE_OP1_IF_VAR();
+ }
if (iter && EXPECTED(EG(exception) == NULL)) {
array_ptr = zend_iterator_wrap(iter TSRMLS_CC);
} else {
- FREE_OP1_IF_VAR();
+ if (OP1_TYPE == IS_VAR && opline->extended_value & ZEND_FE_RESET_VARIABLE) {
+ FREE_OP1_VAR_PTR();
+ }
if (!EG(exception)) {
zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Object of type %s did not create an Iterator", ce->name);
}
@@ -4192,14 +4204,18 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY)
iter->funcs->rewind(iter TSRMLS_CC);
if (UNEXPECTED(EG(exception) != NULL)) {
zval_ptr_dtor(&array_ptr);
- FREE_OP1_IF_VAR();
+ if (OP1_TYPE == IS_VAR && opline->extended_value & ZEND_FE_RESET_VARIABLE) {
+ FREE_OP1_VAR_PTR();
+ }
HANDLE_EXCEPTION();
}
}
is_empty = iter->funcs->valid(iter TSRMLS_CC) != SUCCESS;
if (UNEXPECTED(EG(exception) != NULL)) {
zval_ptr_dtor(&array_ptr);
- FREE_OP1_IF_VAR();
+ if (OP1_TYPE == IS_VAR && opline->extended_value & ZEND_FE_RESET_VARIABLE) {
+ FREE_OP1_VAR_PTR();
+ }
HANDLE_EXCEPTION();
}
iter->index = -1; /* will be set to 0 before using next handler */
@@ -4229,7 +4245,9 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY)
is_empty = 1;
}
- FREE_OP1_IF_VAR();
+ if (OP1_TYPE == IS_VAR && opline->extended_value & ZEND_FE_RESET_VARIABLE) {
+ FREE_OP1_VAR_PTR();
+ }
if (is_empty) {
ZEND_VM_JMP(EX(op_array)->opcodes+opline->op2.opline_num);
} else {
@@ -4465,7 +4483,7 @@ ZEND_VM_HELPER_EX(zend_isset_isempty_dim_prop_obj_handler, VAR|UNUSED|CV, CONST|
zval *offset;
SAVE_OPLINE();
- container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_IS);
+ container = GET_OP1_OBJ_ZVAL_PTR_PTR_FAST(BP_VAR_IS);
offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
@@ -4592,7 +4610,7 @@ ZEND_VM_C_LABEL(num_index_prop):
Z_LVAL(EX_T(opline->result.var).tmp_var) = !result;
}
- FREE_OP1_VAR_PTR();
+ FREE_OP1_VAR_PTR_FAST();
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
@@ -5294,14 +5312,14 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE
generator->value = *value_ptr;
}
- FREE_OP1_IF_VAR();
+ FREE_OP1_VAR_PTR();
}
} else {
zval *value = GET_OP1_ZVAL_PTR(BP_VAR_R);
/* Consts, temporary variables and references need copying */
if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR
- || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0)
+ || PZVAL_IS_REF(value)
) {
zval *copy;
@@ -5314,12 +5332,13 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE
}
generator->value = copy;
+ FREE_OP1_IF_VAR();
} else {
- Z_ADDREF_P(value);
+ if (OP1_TYPE == IS_CV) {
+ Z_ADDREF_P(value);
+ }
generator->value = value;
}
-
- FREE_OP1_IF_VAR();
}
} else {
/* If no value was specified yield null */