diff options
Diffstat (limited to 'Zend/zend_compile.c')
-rw-r--r-- | Zend/zend_compile.c | 99 |
1 files changed, 66 insertions, 33 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index babf39ff40..5dbb41f94d 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; } /* }}} */ @@ -272,7 +273,7 @@ static int lookup_cv(zend_op_array *op_array, zend_string* name TSRMLS_DC) /* {{ op_array->vars[i]->len == name->len && memcmp(op_array->vars[i]->val, name->val, name->len) == 0)) { zend_string_release(name); - return (int)(zend_intptr_t)EX_VAR_NUM_2(NULL, i); + return (int)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, i); } i++; } @@ -284,7 +285,7 @@ static int lookup_cv(zend_op_array *op_array, zend_string* name TSRMLS_DC) /* {{ } op_array->vars[i] = zend_new_interned_string(name TSRMLS_CC); - return (int)(zend_intptr_t)EX_VAR_NUM_2(NULL, i); + return (int)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, i); } /* }}} */ @@ -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); @@ -2109,7 +2110,8 @@ static zend_op *zend_delayed_compile_prop(znode *result, zend_ast *ast, uint32_t zend_compile_expr(&prop_node, prop_ast TSRMLS_CC); opline = zend_delayed_emit_op(result, ZEND_FETCH_OBJ_R, &obj_node, &prop_node TSRMLS_CC); - if (opline->op2_type == IS_CONST && Z_TYPE(CONSTANT(opline->op2.constant)) == IS_STRING) { + if (opline->op2_type == IS_CONST) { + convert_to_string(&CONSTANT(opline->op2.constant)); zend_alloc_polymorphic_cache_slot(opline->op2.constant TSRMLS_CC); } @@ -2477,7 +2479,12 @@ uint32_t zend_compile_args(zend_ast *ast, zend_function *fbc TSRMLS_DC) /* {{{ * if (fbc) { flags |= ZEND_ARG_COMPILE_TIME_BOUND; } - opline->extended_value = flags; + if ((flags & ZEND_ARG_COMPILE_TIME_BOUND) && !(flags & ZEND_ARG_SEND_BY_REF)) { + opline->opcode = ZEND_SEND_VAR; + opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND; + } else { + opline->extended_value = flags; + } } else if (fbc) { opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND; } @@ -2984,9 +2991,7 @@ void zend_compile_global_var(zend_ast *ast TSRMLS_DC) /* {{{ */ zend_compile_expr(&name_node, name_ast TSRMLS_CC); if (name_node.op_type == IS_CONST) { - if (Z_TYPE(name_node.u.constant) != IS_STRING) { - convert_to_string(&name_node.u.constant); - } + convert_to_string(&name_node.u.constant); } if (zend_try_compile_cv(&result, var_ast TSRMLS_CC) == SUCCESS) { @@ -3122,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, @@ -3427,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); @@ -3617,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); @@ -3629,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); } @@ -3830,8 +3845,7 @@ void zend_compile_params(zend_ast *ast TSRMLS_DC) /* {{{ */ zend_bool has_null_default = default_ast && (Z_TYPE(default_node.u.constant) == IS_NULL || (Z_TYPE(default_node.u.constant) == IS_CONSTANT - && strcasecmp(Z_STRVAL(default_node.u.constant), "NULL") == 0) - || Z_TYPE(default_node.u.constant) == IS_CONSTANT_AST); // ??? + && strcasecmp(Z_STRVAL(default_node.u.constant), "NULL") == 0)); op_array->fn_flags |= ZEND_ACC_HAS_TYPE_HINTS; arg_info->allow_null = has_null_default; @@ -3841,12 +3855,13 @@ void zend_compile_params(zend_ast *ast TSRMLS_DC) /* {{{ */ if (arg_info->type_hint == IS_ARRAY) { if (default_ast && !has_null_default && Z_TYPE(default_node.u.constant) != IS_ARRAY + && !Z_CONSTANT(default_node.u.constant) ) { zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " "with array type hint can only be an array or NULL"); } } else if (arg_info->type_hint == IS_CALLABLE && default_ast) { - if (!has_null_default) { + if (!has_null_default && !Z_CONSTANT(default_node.u.constant)) { zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " "with callable type hint can only be NULL"); } @@ -3866,7 +3881,7 @@ void zend_compile_params(zend_ast *ast TSRMLS_DC) /* {{{ */ zend_string_release(class_name); - if (default_ast && !has_null_default) { + if (default_ast && !has_null_default && !Z_CONSTANT(default_node.u.constant)) { zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters " "with a class type hint can only be NULL"); } @@ -5469,7 +5484,7 @@ void zend_compile_isset_or_empty(znode *result, zend_ast *ast TSRMLS_DC) /* {{{ zend_ast *var_ast = ast->child[0]; znode var_node; - zend_op *opline; + zend_op *opline = NULL; ZEND_ASSERT(ast->kind == ZEND_AST_ISSET || ast->kind == ZEND_AST_EMPTY); @@ -5520,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 @@ -5536,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; } /* }}} */ @@ -5701,8 +5720,21 @@ void zend_compile_resolve_class_name(znode *result, zend_ast *ast TSRMLS_DC) /* zend_error_noreturn(E_COMPILE_ERROR, "Cannot access self::class when no class scope is active"); } - result->op_type = IS_CONST; - ZVAL_STR_COPY(&result->u.constant, CG(active_class_entry)->name); + if (CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) { + zval class_str_zv; + zend_ast *class_str_ast, *class_const_ast; + + ZVAL_STRING(&class_str_zv, "class"); + class_str_ast = zend_ast_create_zval(&class_str_zv); + class_const_ast = zend_ast_create(ZEND_AST_CLASS_CONST, name_ast, class_str_ast); + + zend_compile_expr(result, class_const_ast TSRMLS_CC); + + zval_ptr_dtor(&class_str_zv); + } else { + result->op_type = IS_CONST; + ZVAL_STR_COPY(&result->u.constant, CG(active_class_entry)->name); + } break; case ZEND_FETCH_CLASS_STATIC: case ZEND_FETCH_CLASS_PARENT: @@ -5788,14 +5820,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, @@ -5926,10 +5958,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; |