summaryrefslogtreecommitdiff
path: root/Zend
diff options
context:
space:
mode:
authorAnatol Belski <ab@php.net>2014-11-27 15:59:43 +0100
committerAnatol Belski <ab@php.net>2014-11-27 15:59:43 +0100
commit864cd82acef03b75b994f3fd98d9b4a51a99204a (patch)
tree4edfbcc6ce5d2f6fa6da9908503119c70ad868b5 /Zend
parent81a24f054b934ccb1be77049dd9c244283efcba7 (diff)
parent4dcc8a63715b1bb42518e9c217ea493007016932 (diff)
downloadphp-git-864cd82acef03b75b994f3fd98d9b4a51a99204a.tar.gz
Merge remote-tracking branch 'origin/master' into native-tls
* origin/master: updated NEWS refactored the mbstring config.w32 Update NEWS Fixed compilation warnings Fixed bug #68504 --with-libmbfl configure option not present on Windows Changed "finally" handling. Removed EX(fast_ret) and EX(delayed_exception). Allocate and use additional IS_TMP_VAR slot on VM stack instead. the darwin specific test fails for me with the same output which is the expected for the original test I couldn't find anybody who managed to see this test passing, but I found a bunch of other reports on qa.php.net/reports and on google which do see this test failing on mac. if this change causes you to have this test failing on Mac, please drop me a mail so we can improve the current test so it passes for everybody. #68446 is fixed Reimplemented silence operator (@) handling on exceptions. Now each silence region is stored in op_array->brk_cont_array. On exception ZEND_HANDLE_EXCEPTION handler traverse this array and restore original EG(error_reporting) if exception occured inside a "silence" region. remove the NEWS entries for the reverted stuff typo fix go back with phpdbg to the state of 5.6.3, reverting the controversial commits(remote debugging/xml protocol) 5.5.21 now New label length test Fix ext/filter/tests/033.phpt Fix filter_list test FILTER_VALIDATE_DOMAIN and RFC conformance for FILTER_VALIDATE_URL Conflicts: ext/mbstring/config.w32
Diffstat (limited to 'Zend')
-rw-r--r--Zend/zend_alloc.c13
-rw-r--r--Zend/zend_compile.c54
-rw-r--r--Zend/zend_compile.h5
-rw-r--r--Zend/zend_execute.c30
-rw-r--r--Zend/zend_gc.c2
-rw-r--r--Zend/zend_generators.c8
-rw-r--r--Zend/zend_indent.c2
-rw-r--r--Zend/zend_opcode.c11
-rw-r--r--Zend/zend_vm_def.h80
-rw-r--r--Zend/zend_vm_execute.h80
10 files changed, 174 insertions, 111 deletions
diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c
index 3041857dc6..1614690414 100644
--- a/Zend/zend_alloc.c
+++ b/Zend/zend_alloc.c
@@ -2130,6 +2130,7 @@ ZEND_API void* ZEND_FASTCALL _emalloc_huge(size_t size)
return zend_mm_alloc_huge(AG(mm_heap), size);
}
+#if ZEND_DEBUG
# define _ZEND_BIN_FREE(_num, _size, _elements, _pages, x, y) \
ZEND_API void ZEND_FASTCALL _efree_ ## _size(void *ptr) { \
TSRMLS_FETCH(); \
@@ -2144,6 +2145,18 @@ ZEND_API void* ZEND_FASTCALL _emalloc_huge(size_t size)
zend_mm_free_small(AG(mm_heap), ptr, _num); \
} \
}
+#else
+# define _ZEND_BIN_FREE(_num, _size, _elements, _pages, x, y) \
+ ZEND_API void ZEND_FASTCALL _efree_ ## _size(void *ptr) { \
+ TSRMLS_FETCH(); \
+ ZEND_MM_CUSTOM_DEALLOCATOR(ptr); \
+ { \
+ zend_mm_chunk *chunk = (zend_mm_chunk*)ZEND_MM_ALIGNED_BASE(ptr, ZEND_MM_CHUNK_SIZE); \
+ ZEND_MM_CHECK(chunk->heap == AG(mm_heap), "zend_mm_heap corrupted"); \
+ zend_mm_free_small(AG(mm_heap), ptr, _num); \
+ } \
+ }
+#endif
ZEND_MM_BINS_INFO(_ZEND_BIN_FREE, x, y)
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 55be6176bf..5d409c7518 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -159,6 +159,7 @@ void zend_init_compiler_context(TSRMLS_D) /* {{{ */
CG(context).current_brk_cont = -1;
CG(context).backpatch_count = 0;
CG(context).in_finally = 0;
+ CG(context).fast_call_var = -1;
CG(context).labels = NULL;
}
/* }}} */
@@ -1810,7 +1811,7 @@ static inline uint32_t zend_delayed_compile_begin(TSRMLS_D) /* {{{ */
static zend_op *zend_delayed_compile_end(uint32_t offset TSRMLS_DC) /* {{{ */
{
- zend_op *opline, *oplines = zend_stack_base(&CG(delayed_oplines_stack));
+ zend_op *opline = NULL, *oplines = zend_stack_base(&CG(delayed_oplines_stack));
uint32_t i, count = zend_stack_count(&CG(delayed_oplines_stack));
ZEND_ASSERT(count > offset);
@@ -3126,7 +3127,9 @@ void zend_compile_return(zend_ast *ast TSRMLS_DC) /* {{{ */
zend_free_foreach_and_switch_variables(TSRMLS_C);
if (CG(context).in_finally) {
- zend_emit_op(NULL, ZEND_DISCARD_EXCEPTION, NULL, NULL TSRMLS_CC);
+ opline = zend_emit_op(NULL, ZEND_DISCARD_EXCEPTION, NULL, NULL TSRMLS_CC);
+ opline->op1_type = IS_TMP_VAR;
+ opline->op1.var = CG(context).fast_call_var;
}
opline = zend_emit_op(NULL, by_ref ? ZEND_RETURN_BY_REF : ZEND_RETURN,
@@ -3431,7 +3434,7 @@ void zend_compile_if(zend_ast *ast TSRMLS_DC) /* {{{ */
{
zend_ast_list *list = zend_ast_get_list(ast);
uint32_t i;
- uint32_t *jmp_opnums;
+ uint32_t *jmp_opnums = NULL;
if (list->children > 1) {
jmp_opnums = safe_emalloc(sizeof(uint32_t), list->children - 1, 0);
@@ -3621,8 +3624,15 @@ void zend_compile_try(zend_ast *ast TSRMLS_DC) /* {{{ */
if (finally_ast) {
uint32_t opnum_jmp = get_next_op_number(CG(active_op_array)) + 1;
+ if (!(CG(active_op_array)->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK)) {
+ CG(active_op_array)->fn_flags |= ZEND_ACC_HAS_FINALLY_BLOCK;
+ CG(context).fast_call_var = get_temporary_variable(CG(active_op_array));
+ }
+
opline = zend_emit_op(NULL, ZEND_FAST_CALL, NULL, NULL TSRMLS_CC);
opline->op1.opline_num = opnum_jmp + 1;
+ opline->result_type = IS_TMP_VAR;
+ opline->result.var = CG(context).fast_call_var;
zend_emit_op(NULL, ZEND_JMP, NULL, NULL TSRMLS_CC);
@@ -3633,9 +3643,10 @@ void zend_compile_try(zend_ast *ast TSRMLS_DC) /* {{{ */
CG(active_op_array)->try_catch_array[try_catch_offset].finally_op = opnum_jmp + 1;
CG(active_op_array)->try_catch_array[try_catch_offset].finally_end
= get_next_op_number(CG(active_op_array));
- CG(active_op_array)->fn_flags |= ZEND_ACC_HAS_FINALLY_BLOCK;
- zend_emit_op(NULL, ZEND_FAST_RET, NULL, NULL TSRMLS_CC);
+ opline = zend_emit_op(NULL, ZEND_FAST_RET, NULL, NULL TSRMLS_CC);
+ opline->op1_type = IS_TMP_VAR;
+ opline->op1.var = CG(context).fast_call_var;
zend_update_jump_target_to_next(opnum_jmp TSRMLS_CC);
}
@@ -5524,13 +5535,11 @@ void zend_compile_silence(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
{
zend_ast *expr_ast = ast->child[0];
znode silence_node;
- uint32_t opline_num;
- zend_op *begin_silence, *end_silence;
+ uint32_t begin_opline_num, end_opline_num;
+ zend_brk_cont_element *brk_cont_element;
- opline_num = get_next_op_number(CG(active_op_array));
- begin_silence = zend_emit_op_tmp(&silence_node, ZEND_BEGIN_SILENCE, NULL, NULL TSRMLS_CC);
- /* pair BEGIN_SILENCE and END_SILENCE opcodes */
- begin_silence->op2.num = opline_num;
+ begin_opline_num = get_next_op_number(CG(active_op_array));
+ zend_emit_op_tmp(&silence_node, ZEND_BEGIN_SILENCE, NULL, NULL TSRMLS_CC);
if (expr_ast->kind == ZEND_AST_VAR) {
/* For @$var we need to force a FETCH instruction, otherwise the CV access will
@@ -5540,9 +5549,15 @@ void zend_compile_silence(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
zend_compile_expr(result, expr_ast TSRMLS_CC);
}
- end_silence = zend_emit_op(NULL, ZEND_END_SILENCE, &silence_node, NULL TSRMLS_CC);
- /* pair BEGIN_SILENCE and END_SILENCE opcodes */
- end_silence->op2.num = opline_num;
+ end_opline_num = get_next_op_number(CG(active_op_array));
+ zend_emit_op(NULL, ZEND_END_SILENCE, &silence_node, NULL TSRMLS_CC);
+
+ /* Store BEGIN_SILENCE/END_SILENCE pair to restore previous
+ * EG(error_reporting) value on exception */
+ brk_cont_element = get_next_brk_cont_element(CG(active_op_array));
+ brk_cont_element->start = begin_opline_num;
+ brk_cont_element->cont = brk_cont_element->brk = end_opline_num;
+ brk_cont_element->parent = -1;
}
/* }}} */
@@ -5792,14 +5807,14 @@ void zend_compile_encaps_list(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
void zend_compile_magic_const(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ */
{
- zend_class_entry *ce = CG(active_class_entry);
-
if (zend_try_ct_eval_magic_const(&result->u.constant, ast TSRMLS_CC)) {
result->op_type = IS_CONST;
return;
}
- ZEND_ASSERT(ast->attr == T_CLASS_C && ce && ZEND_CE_IS_TRAIT(ce));
+ ZEND_ASSERT(ast->attr == T_CLASS_C &&
+ CG(active_class_entry) &&
+ ZEND_CE_IS_TRAIT(CG(active_class_entry)));
{
zend_ast *const_ast = zend_ast_create(ZEND_AST_CONST,
@@ -5930,10 +5945,11 @@ void zend_compile_const_expr_resolve_class_name(zend_ast **ast_ptr TSRMLS_DC) /*
void zend_compile_const_expr_magic_const(zend_ast **ast_ptr TSRMLS_DC) /* {{{ */
{
zend_ast *ast = *ast_ptr;
- zend_class_entry *ce = CG(active_class_entry);
/* Other cases already resolved by constant folding */
- ZEND_ASSERT(ast->attr == T_CLASS_C && ce && ZEND_CE_IS_TRAIT(ce));
+ ZEND_ASSERT(ast->attr == T_CLASS_C &&
+ CG(active_class_entry) &&
+ ZEND_CE_IS_TRAIT(CG(active_class_entry)));
{
zval const_zv;
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index f9a66a37d8..4cf60c6181 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -52,6 +52,7 @@ typedef struct _zend_compiler_context {
int current_brk_cont;
int backpatch_count;
int in_finally;
+ uint32_t fast_call_var;
HashTable *labels;
} zend_compiler_context;
@@ -376,10 +377,6 @@ struct _zend_execute_data {
zval *return_value;
zend_class_entry *scope; /* function scope (self) */
zend_array *symbol_table;
- const zend_op *fast_ret; /* used by FAST_CALL/FAST_RET (finally keyword) */
- zend_object *delayed_exception;
- uint32_t silence_op_num;
- uint32_t old_error_reporting;
};
#define VM_FRAME_KIND_MASK 0x000000ff
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 6c8ebca707..2fbd1d5011 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -558,20 +558,24 @@ ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, uin
fclass = "";
}
- if (arg && zf->common.type == ZEND_USER_FUNCTION) {
- ZVAL_COPY_VALUE(&old_arg, arg);
- ZVAL_UNDEF(arg);
- }
+ if (zf->common.type == ZEND_USER_FUNCTION) {
+ if (arg) {
+ ZVAL_COPY_VALUE(&old_arg, arg);
+ ZVAL_UNDEF(arg);
+ }
- if (zf->common.type == ZEND_USER_FUNCTION && ptr && ptr->func && ZEND_USER_CODE(ptr->func->common.type)) {
- zend_error(error_type, "Argument %d passed to %s%s%s() must %s%s, %s%s given, called in %s on line %d and defined", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind, ptr->func->op_array.filename->val, ptr->opline->lineno);
+ if (ptr && ptr->func && ZEND_USER_CODE(ptr->func->common.type)) {
+ zend_error(error_type, "Argument %d passed to %s%s%s() must %s%s, %s%s given, called in %s on line %d and defined", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind, ptr->func->op_array.filename->val, ptr->opline->lineno);
+ } else {
+ zend_error(error_type, "Argument %d passed to %s%s%s() must %s%s, %s%s given", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind);
+ }
+
+ if (arg) {
+ ZVAL_COPY_VALUE(arg, &old_arg);
+ }
} else {
zend_error(error_type, "Argument %d passed to %s%s%s() must %s%s, %s%s given", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind);
}
-
- if (arg && zf->common.type == ZEND_USER_FUNCTION) {
- ZVAL_COPY_VALUE(arg, &old_arg);
- }
}
static int is_null_constant(zval *default_value TSRMLS_DC)
@@ -1485,8 +1489,6 @@ static zend_always_inline void i_init_func_execute_data(zend_execute_data *execu
EX(opline) = op_array->opcodes;
EX(call) = NULL;
EX(return_value) = return_value;
- EX(delayed_exception) = NULL;
- EX(silence_op_num) = -1;
/* Handle arguments */
first_extra_arg = op_array->num_args;
@@ -1552,8 +1554,6 @@ static zend_always_inline void i_init_code_execute_data(zend_execute_data *execu
EX(call) = NULL;
EX(return_value) = return_value;
EX(scope) = EG(scope);
- EX(delayed_exception) = NULL;
- EX(silence_op_num) = -1;
zend_attach_symbol_table(execute_data);
@@ -1579,8 +1579,6 @@ static zend_always_inline void i_init_execute_data(zend_execute_data *execute_da
EX(call) = NULL;
EX(return_value) = return_value;
EX(scope) = EG(scope);
- EX(delayed_exception) = NULL;
- EX(silence_op_num) = -1;
if (UNEXPECTED(EX(symbol_table) != NULL)) {
zend_attach_symbol_table(execute_data);
diff --git a/Zend/zend_gc.c b/Zend/zend_gc.c
index e47b5350d4..f6aad866a7 100644
--- a/Zend/zend_gc.c
+++ b/Zend/zend_gc.c
@@ -641,7 +641,7 @@ static int gc_collect_roots(TSRMLS_D)
static void gc_remove_nested_data_from_buffer(zend_refcounted *ref TSRMLS_DC)
{
- HashTable *ht;
+ HashTable *ht = NULL;
uint idx;
Bucket *p;
diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c
index b38657f7b7..ef0b520eb0 100644
--- a/Zend/zend_generators.c
+++ b/Zend/zend_generators.c
@@ -133,7 +133,7 @@ static void zend_generator_dtor_storage(zend_object *object TSRMLS_DC) /* {{{ */
{
zend_generator *generator = (zend_generator*) object;
zend_execute_data *ex = generator->execute_data;
- uint32_t op_num, finally_op_num;
+ uint32_t op_num, finally_op_num, finally_op_end;
int i;
if (!ex || !(ex->func->op_array.fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK)) {
@@ -146,6 +146,7 @@ static void zend_generator_dtor_storage(zend_object *object TSRMLS_DC) /* {{{ */
/* Find next finally block */
finally_op_num = 0;
+ finally_op_end = 0;
for (i = 0; i < ex->func->op_array.last_try_catch; i++) {
zend_try_catch_element *try_catch = &ex->func->op_array.try_catch_array[i];
@@ -155,14 +156,17 @@ static void zend_generator_dtor_storage(zend_object *object TSRMLS_DC) /* {{{ */
if (op_num < try_catch->finally_op) {
finally_op_num = try_catch->finally_op;
+ finally_op_end = try_catch->finally_end;
}
}
/* If a finally block was found we jump directly to it and
* resume the generator. */
if (finally_op_num) {
+ zval *fast_call = EX_VAR_2(ex, ex->func->op_array.opcodes[finally_op_end].op1.var);
+
+ fast_call->u2.lineno = (uint32_t)-1;
ex->opline = &ex->func->op_array.opcodes[finally_op_num];
- ex->fast_ret = NULL;
generator->flags |= ZEND_GENERATOR_FORCED_CLOSE;
zend_generator_resume(generator TSRMLS_CC);
}
diff --git a/Zend/zend_indent.c b/Zend/zend_indent.c
index 93c10108f8..b5884c72c0 100644
--- a/Zend/zend_indent.c
+++ b/Zend/zend_indent.c
@@ -31,7 +31,7 @@
#define zendleng LANG_SCNG(yy_leng)
-static void handle_whitespace(int *emit_whitespace)
+static void handle_whitespace(unsigned int *emit_whitespace)
{
unsigned char c;
int i;
diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c
index 5902abd4c5..1bbd35f40f 100644
--- a/Zend/zend_opcode.c
+++ b/Zend/zend_opcode.c
@@ -532,12 +532,19 @@ static void zend_resolve_finally_call(zend_op_array *op_array, uint32_t op_num,
(dst_num < op_array->try_catch_array[i].try_op ||
dst_num > op_array->try_catch_array[i].finally_end)) {
/* we have a jump out of try block that needs executing finally */
+ uint32_t fast_call_var;
+
+ /* Must be ZEND_FAST_RET */
+ ZEND_ASSERT(op_array->opcodes[op_array->try_catch_array[i].finally_end].opcode == ZEND_FAST_RET);
+ fast_call_var = op_array->opcodes[op_array->try_catch_array[i].finally_end].op1.var;
/* generate a FAST_CALL to finally block */
start_op = get_next_op_number(op_array);
opline = get_next_op(op_array TSRMLS_CC);
opline->opcode = ZEND_FAST_CALL;
+ opline->result_type = IS_TMP_VAR;
+ opline->result.var = fast_call_var;
SET_UNUSED(opline->op1);
SET_UNUSED(opline->op2);
zend_adjust_fast_call(op_array, start_op,
@@ -550,6 +557,8 @@ static void zend_resolve_finally_call(zend_op_array *op_array, uint32_t op_num,
/* generate a FAST_CALL to hole CALL_FROM_FINALLY */
opline = get_next_op(op_array TSRMLS_CC);
opline->opcode = ZEND_FAST_CALL;
+ opline->result_type = IS_TMP_VAR;
+ opline->result.var = fast_call_var;
SET_UNUSED(opline->op1);
SET_UNUSED(opline->op2);
zend_resolve_fast_call(op_array, start_op + 1, op_array->try_catch_array[i].finally_op - 2 TSRMLS_CC);
@@ -569,6 +578,8 @@ static void zend_resolve_finally_call(zend_op_array *op_array, uint32_t op_num,
opline = get_next_op(op_array TSRMLS_CC);
opline->opcode = ZEND_FAST_CALL;
+ opline->result_type = IS_TMP_VAR;
+ opline->result.var = fast_call_var;
SET_UNUSED(opline->op1);
SET_UNUSED(opline->op2);
opline->op1.opline_num = op_array->try_catch_array[i].finally_op;
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 223f43dda7..760f5f99f7 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -5113,10 +5113,6 @@ ZEND_VM_HANDLER(57, ZEND_BEGIN_SILENCE, ANY, ANY)
SAVE_OPLINE();
ZVAL_LONG(EX_VAR(opline->result.var), EG(error_reporting));
- if (EX(silence_op_num) == -1) {
- EX(silence_op_num) = opline->op2.num;
- EX(old_error_reporting) = EG(error_reporting);
- }
if (EG(error_reporting)) {
do {
@@ -5154,9 +5150,6 @@ ZEND_VM_HANDLER(58, ZEND_END_SILENCE, TMP, ANY)
if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(opline->op1.var)) != 0) {
EG(error_reporting) = Z_LVAL_P(EX_VAR(opline->op1.var));
}
- if (EX(silence_op_num) == opline->op2.num) {
- EX(silence_op_num) = -1;
- }
ZEND_VM_NEXT_OPCODE();
}
@@ -5476,6 +5469,7 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
}
if (op_num < EX(func)->op_array.try_catch_array[i].finally_op) {
finally_op_num = EX(func)->op_array.try_catch_array[i].finally_op;
+ finally_op_end = EX(func)->op_array.try_catch_array[i].finally_end;
}
if (op_num >= EX(func)->op_array.try_catch_array[i].finally_op &&
op_num < EX(func)->op_array.try_catch_array[i].finally_end) {
@@ -5522,40 +5516,47 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
}
+ } else if (brk_opline->opcode == ZEND_END_SILENCE) {
+ /* restore previous error_reporting value */
+ if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(brk_opline->op1.var)) != 0) {
+ EG(error_reporting) = Z_LVAL_P(EX_VAR(brk_opline->op1.var));
+ }
}
}
}
}
- /* restore previous error_reporting value */
- if (!EG(error_reporting) && EX(silence_op_num) != -1 && EX(old_error_reporting) != 0) {
- EG(error_reporting) = EX(old_error_reporting);
- }
- EX(silence_op_num) = -1;
-
if (finally_op_num && (!catch_op_num || catch_op_num >= finally_op_num)) {
- if (EX(delayed_exception)) {
- zend_exception_set_previous(EG(exception), EX(delayed_exception) TSRMLS_CC);
+ zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[finally_op_end].op1.var);
+
+ if (Z_OBJ_P(fast_call)) {
+ zend_exception_set_previous(EG(exception), Z_OBJ_P(fast_call) TSRMLS_CC);
}
- EX(delayed_exception) = EG(exception);
+ Z_OBJ_P(fast_call) = EG(exception);
EG(exception) = NULL;
- EX(fast_ret) = NULL;
+ fast_call->u2.lineno = (uint32_t)-1;
ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[finally_op_num]);
ZEND_VM_CONTINUE();
} else if (catch_op_num) {
if (finally_op_end && catch_op_num > finally_op_end) {
/* we are going out of current finally scope */
- if (EX(delayed_exception)) {
- zend_exception_set_previous(EG(exception), EX(delayed_exception) TSRMLS_CC);
- EX(delayed_exception) = NULL;
+ zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[finally_op_end].op1.var);
+
+ if (Z_OBJ_P(fast_call)) {
+ zend_exception_set_previous(EG(exception), Z_OBJ_P(fast_call) TSRMLS_CC);
+ Z_OBJ_P(fast_call) = NULL;
}
}
ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[catch_op_num]);
ZEND_VM_CONTINUE();
} else {
- if (EX(delayed_exception)) {
- zend_exception_set_previous(EG(exception), EX(delayed_exception) TSRMLS_CC);
- EX(delayed_exception) = NULL;
+ if (finally_op_end) {
+ zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[finally_op_end].op1.var);
+
+ if (Z_OBJ_P(fast_call)) {
+ zend_exception_set_previous(EG(exception), Z_OBJ_P(fast_call) TSRMLS_CC);
+ Z_OBJ_P(fast_call) = NULL;
+ }
}
if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_GENERATOR_RETURN);
@@ -5815,10 +5816,14 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE
ZEND_VM_HANDLER(159, ZEND_DISCARD_EXCEPTION, ANY, ANY)
{
- if (EX(delayed_exception) != NULL) {
+ USE_OPLINE
+ zval *fast_call = EX_VAR(opline->op1.var);
+
+ /* check for delayed exception */
+ if (Z_OBJ_P(fast_call) != NULL) {
/* discard the previously thrown exception */
- OBJ_RELEASE(EX(delayed_exception));
- EX(delayed_exception) = NULL;
+ OBJ_RELEASE(Z_OBJ_P(fast_call));
+ Z_OBJ_P(fast_call) = NULL;
}
ZEND_VM_NEXT_OPCODE();
@@ -5827,6 +5832,7 @@ ZEND_VM_HANDLER(159, ZEND_DISCARD_EXCEPTION, ANY, ANY)
ZEND_VM_HANDLER(162, ZEND_FAST_CALL, ANY, ANY)
{
USE_OPLINE
+ zval *fast_call = EX_VAR(opline->result.var);
if ((opline->extended_value & ZEND_FAST_CALL_FROM_CATCH) &&
UNEXPECTED(EG(prev_exception) != NULL)) {
@@ -5834,18 +5840,24 @@ ZEND_VM_HANDLER(162, ZEND_FAST_CALL, ANY, ANY)
ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]);
ZEND_VM_CONTINUE();
}
- EX(fast_ret) = opline;
- EX(delayed_exception) = NULL;
+ /* set no delayed exception */
+ Z_OBJ_P(fast_call) = NULL;
+ /* set return address */
+ fast_call->u2.lineno = opline - EX(func)->op_array.opcodes;
ZEND_VM_SET_OPCODE(opline->op1.jmp_addr);
ZEND_VM_CONTINUE();
}
ZEND_VM_HANDLER(163, ZEND_FAST_RET, ANY, ANY)
{
- if (EX(fast_ret)) {
- ZEND_VM_SET_OPCODE(EX(fast_ret) + 1);
- if ((EX(fast_ret)->extended_value & ZEND_FAST_CALL_FROM_FINALLY)) {
- EX(fast_ret) = &EX(func)->op_array.opcodes[EX(fast_ret)->op2.opline_num];
+ USE_OPLINE
+ zval *fast_call = EX_VAR(opline->op1.var);
+
+ if (fast_call->u2.lineno != (uint32_t)-1) {
+ const zend_op *fast_ret = EX(func)->op_array.opcodes + fast_call->u2.lineno;
+ ZEND_VM_SET_OPCODE(fast_ret + 1);
+ if (fast_ret->extended_value & ZEND_FAST_CALL_FROM_FINALLY) {
+ fast_call->u2.lineno = fast_ret->op2.opline_num;
}
ZEND_VM_CONTINUE();
} else {
@@ -5856,8 +5868,8 @@ ZEND_VM_HANDLER(163, ZEND_FAST_RET, ANY, ANY)
ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]);
ZEND_VM_CONTINUE();
} else {
- EG(exception) = EX(delayed_exception);
- EX(delayed_exception) = NULL;
+ EG(exception) = Z_OBJ_P(fast_call);
+ Z_OBJ_P(fast_call) = NULL;
if (opline->extended_value == ZEND_FAST_RET_TO_CATCH) {
ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]);
ZEND_VM_CONTINUE();
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 5210484370..dc3ee25c52 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -1029,10 +1029,6 @@ static int ZEND_FASTCALL ZEND_BEGIN_SILENCE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_AR
SAVE_OPLINE();
ZVAL_LONG(EX_VAR(opline->result.var), EG(error_reporting));
- if (EX(silence_op_num) == -1) {
- EX(silence_op_num) = opline->op2.num;
- EX(old_error_reporting) = EG(error_reporting);
- }
if (EG(error_reporting)) {
do {
@@ -1218,6 +1214,7 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER
}
if (op_num < EX(func)->op_array.try_catch_array[i].finally_op) {
finally_op_num = EX(func)->op_array.try_catch_array[i].finally_op;
+ finally_op_end = EX(func)->op_array.try_catch_array[i].finally_end;
}
if (op_num >= EX(func)->op_array.try_catch_array[i].finally_op &&
op_num < EX(func)->op_array.try_catch_array[i].finally_end) {
@@ -1264,40 +1261,47 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER
if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
}
+ } else if (brk_opline->opcode == ZEND_END_SILENCE) {
+ /* restore previous error_reporting value */
+ if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(brk_opline->op1.var)) != 0) {
+ EG(error_reporting) = Z_LVAL_P(EX_VAR(brk_opline->op1.var));
+ }
}
}
}
}
- /* restore previous error_reporting value */
- if (!EG(error_reporting) && EX(silence_op_num) != -1 && EX(old_error_reporting) != 0) {
- EG(error_reporting) = EX(old_error_reporting);
- }
- EX(silence_op_num) = -1;
-
if (finally_op_num && (!catch_op_num || catch_op_num >= finally_op_num)) {
- if (EX(delayed_exception)) {
- zend_exception_set_previous(EG(exception), EX(delayed_exception) TSRMLS_CC);
+ zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[finally_op_end].op1.var);
+
+ if (Z_OBJ_P(fast_call)) {
+ zend_exception_set_previous(EG(exception), Z_OBJ_P(fast_call) TSRMLS_CC);
}
- EX(delayed_exception) = EG(exception);
+ Z_OBJ_P(fast_call) = EG(exception);
EG(exception) = NULL;
- EX(fast_ret) = NULL;
+ fast_call->u2.lineno = (uint32_t)-1;
ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[finally_op_num]);
ZEND_VM_CONTINUE();
} else if (catch_op_num) {
if (finally_op_end && catch_op_num > finally_op_end) {
/* we are going out of current finally scope */
- if (EX(delayed_exception)) {
- zend_exception_set_previous(EG(exception), EX(delayed_exception) TSRMLS_CC);
- EX(delayed_exception) = NULL;
+ zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[finally_op_end].op1.var);
+
+ if (Z_OBJ_P(fast_call)) {
+ zend_exception_set_previous(EG(exception), Z_OBJ_P(fast_call) TSRMLS_CC);
+ Z_OBJ_P(fast_call) = NULL;
}
}
ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[catch_op_num]);
ZEND_VM_CONTINUE();
} else {
- if (EX(delayed_exception)) {
- zend_exception_set_previous(EG(exception), EX(delayed_exception) TSRMLS_CC);
- EX(delayed_exception) = NULL;
+ if (finally_op_end) {
+ zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[finally_op_end].op1.var);
+
+ if (Z_OBJ_P(fast_call)) {
+ zend_exception_set_previous(EG(exception), Z_OBJ_P(fast_call) TSRMLS_CC);
+ Z_OBJ_P(fast_call) = NULL;
+ }
}
if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
return ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
@@ -1348,10 +1352,14 @@ static int ZEND_FASTCALL ZEND_USER_OPCODE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS
static int ZEND_FASTCALL ZEND_DISCARD_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- if (EX(delayed_exception) != NULL) {
+ USE_OPLINE
+ zval *fast_call = EX_VAR(opline->op1.var);
+
+ /* check for delayed exception */
+ if (Z_OBJ_P(fast_call) != NULL) {
/* discard the previously thrown exception */
- OBJ_RELEASE(EX(delayed_exception));
- EX(delayed_exception) = NULL;
+ OBJ_RELEASE(Z_OBJ_P(fast_call));
+ Z_OBJ_P(fast_call) = NULL;
}
ZEND_VM_NEXT_OPCODE();
@@ -1360,6 +1368,7 @@ static int ZEND_FASTCALL ZEND_DISCARD_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLE
static int ZEND_FASTCALL ZEND_FAST_CALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
+ zval *fast_call = EX_VAR(opline->result.var);
if ((opline->extended_value & ZEND_FAST_CALL_FROM_CATCH) &&
UNEXPECTED(EG(prev_exception) != NULL)) {
@@ -1367,18 +1376,24 @@ static int ZEND_FASTCALL ZEND_FAST_CALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]);
ZEND_VM_CONTINUE();
}
- EX(fast_ret) = opline;
- EX(delayed_exception) = NULL;
+ /* set no delayed exception */
+ Z_OBJ_P(fast_call) = NULL;
+ /* set return address */
+ fast_call->u2.lineno = opline - EX(func)->op_array.opcodes;
ZEND_VM_SET_OPCODE(opline->op1.jmp_addr);
ZEND_VM_CONTINUE();
}
static int ZEND_FASTCALL ZEND_FAST_RET_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- if (EX(fast_ret)) {
- ZEND_VM_SET_OPCODE(EX(fast_ret) + 1);
- if ((EX(fast_ret)->extended_value & ZEND_FAST_CALL_FROM_FINALLY)) {
- EX(fast_ret) = &EX(func)->op_array.opcodes[EX(fast_ret)->op2.opline_num];
+ USE_OPLINE
+ zval *fast_call = EX_VAR(opline->op1.var);
+
+ if (fast_call->u2.lineno != (uint32_t)-1) {
+ const zend_op *fast_ret = EX(func)->op_array.opcodes + fast_call->u2.lineno;
+ ZEND_VM_SET_OPCODE(fast_ret + 1);
+ if (fast_ret->extended_value & ZEND_FAST_CALL_FROM_FINALLY) {
+ fast_call->u2.lineno = fast_ret->op2.opline_num;
}
ZEND_VM_CONTINUE();
} else {
@@ -1389,8 +1404,8 @@ static int ZEND_FASTCALL ZEND_FAST_RET_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]);
ZEND_VM_CONTINUE();
} else {
- EG(exception) = EX(delayed_exception);
- EX(delayed_exception) = NULL;
+ EG(exception) = Z_OBJ_P(fast_call);
+ Z_OBJ_P(fast_call) = NULL;
if (opline->extended_value == ZEND_FAST_RET_TO_CATCH) {
ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]);
ZEND_VM_CONTINUE();
@@ -10251,9 +10266,6 @@ static int ZEND_FASTCALL ZEND_END_SILENCE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_
if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(opline->op1.var)) != 0) {
EG(error_reporting) = Z_LVAL_P(EX_VAR(opline->op1.var));
}
- if (EX(silence_op_num) == opline->op2.num) {
- EX(silence_op_num) = -1;
- }
ZEND_VM_NEXT_OPCODE();
}