diff options
Diffstat (limited to 'Zend/zend_opcode.c')
-rw-r--r-- | Zend/zend_opcode.c | 450 |
1 files changed, 220 insertions, 230 deletions
diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index d6b015be9e..c1e3adb3ec 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -5,7 +5,7 @@ | Copyright (c) 1998-2015 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 | + | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.zend.com/license/2_00.txt. | | If you did not receive a copy of the Zend license and are unable to | @@ -29,37 +29,30 @@ #include "zend_vm.h" -static void zend_extension_op_array_ctor_handler(zend_extension *extension, zend_op_array *op_array TSRMLS_DC) +static void zend_extension_op_array_ctor_handler(zend_extension *extension, zend_op_array *op_array) { if (extension->op_array_ctor) { extension->op_array_ctor(op_array); } } -static void zend_extension_op_array_dtor_handler(zend_extension *extension, zend_op_array *op_array TSRMLS_DC) +static void zend_extension_op_array_dtor_handler(zend_extension *extension, zend_op_array *op_array) { if (extension->op_array_dtor) { extension->op_array_dtor(op_array); } } -static void op_array_alloc_ops(zend_op_array *op_array, zend_uint size) +static void op_array_alloc_ops(zend_op_array *op_array, uint32_t size) { op_array->opcodes = erealloc(op_array->opcodes, size * sizeof(zend_op)); } -void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_size TSRMLS_DC) +void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_size) { op_array->type = type; - if (CG(interactive)) { - /* We must avoid a realloc() on the op_array in interactive mode, since pointers to constants - * will become invalid - */ - initial_ops_size = INITIAL_INTERACTIVE_OP_ARRAY_SIZE; - } - - op_array->refcount = (zend_uint *) emalloc(sizeof(zend_uint)); + op_array->refcount = (uint32_t *) emalloc(sizeof(uint32_t)); *op_array->refcount = 1; op_array->last = 0; op_array->opcodes = NULL; @@ -70,19 +63,16 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz op_array->T = 0; - op_array->nested_calls = 0; - op_array->used_stack = 0; - op_array->function_name = NULL; - op_array->filename = zend_get_compiled_filename(TSRMLS_C); + op_array->filename = zend_get_compiled_filename(); op_array->doc_comment = NULL; - op_array->doc_comment_len = 0; op_array->arg_info = NULL; op_array->num_args = 0; op_array->required_num_args = 0; op_array->scope = NULL; + op_array->prototype = NULL; op_array->brk_cont_array = NULL; op_array->try_catch_array = NULL; @@ -90,11 +80,10 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz op_array->static_variables = NULL; op_array->last_try_catch = 0; - op_array->has_finally_block = 0; op_array->this_var = -1; - op_array->fn_flags = CG(interactive)?ZEND_ACC_INTERACTIVE:0; + op_array->fn_flags = 0; op_array->early_binding = -1; @@ -106,153 +95,128 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz memset(op_array->reserved, 0, ZEND_MAX_RESERVED_RESOURCES * sizeof(void*)); - zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_ctor_handler, op_array TSRMLS_CC); + zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_ctor_handler, op_array); } -ZEND_API void destroy_zend_function(zend_function *function TSRMLS_DC) +ZEND_API void destroy_zend_function(zend_function *function) { - switch (function->type) { - case ZEND_USER_FUNCTION: - destroy_op_array((zend_op_array *) function TSRMLS_CC); - break; - case ZEND_INTERNAL_FUNCTION: - /* do nothing */ - break; + if (function->type == ZEND_USER_FUNCTION) { + destroy_op_array(&function->op_array); + } else { + ZEND_ASSERT(function->type == ZEND_INTERNAL_FUNCTION); + ZEND_ASSERT(function->common.function_name); + zend_string_release(function->common.function_name); } } -ZEND_API void zend_function_dtor(zend_function *function) +ZEND_API void zend_function_dtor(zval *zv) { - TSRMLS_FETCH(); + zend_function *function = Z_PTR_P(zv); - destroy_zend_function(function TSRMLS_CC); -} - -static void zend_cleanup_op_array_data(zend_op_array *op_array) -{ - if (op_array->static_variables) { - zend_hash_clean(op_array->static_variables); - } -} - -ZEND_API int zend_cleanup_function_data(zend_function *function TSRMLS_DC) -{ if (function->type == ZEND_USER_FUNCTION) { - zend_cleanup_op_array_data((zend_op_array *) function); - return ZEND_HASH_APPLY_KEEP; + ZEND_ASSERT(function->common.function_name); + destroy_op_array(&function->op_array); + /* op_arrays are allocated on arena, so we don't have to free them */ +//??? efree_size(function, sizeof(zend_op_array)); } else { - return ZEND_HASH_APPLY_STOP; + ZEND_ASSERT(function->type == ZEND_INTERNAL_FUNCTION); + ZEND_ASSERT(function->common.function_name); + zend_string_release(function->common.function_name); + if (!(function->common.fn_flags & ZEND_ACC_ARENA_ALLOCATED)) { + pefree(function, 1); + } } } -ZEND_API int zend_cleanup_function_data_full(zend_function *function TSRMLS_DC) +ZEND_API void zend_cleanup_op_array_data(zend_op_array *op_array) { - if (function->type == ZEND_USER_FUNCTION) { - zend_cleanup_op_array_data((zend_op_array *) function); + if (op_array->static_variables) { + zend_hash_clean(op_array->static_variables); } - return 0; } -static inline void cleanup_user_class_data(zend_class_entry *ce TSRMLS_DC) +ZEND_API void zend_cleanup_user_class_data(zend_class_entry *ce) { /* Clean all parts that can contain run-time data */ /* Note that only run-time accessed data need to be cleaned up, pre-defined data can not contain objects and thus are not probelmatic */ if (ce->ce_flags & ZEND_HAS_STATIC_IN_METHODS) { - zend_hash_apply(&ce->function_table, (apply_func_t) zend_cleanup_function_data_full TSRMLS_CC); + zend_function *func; + + ZEND_HASH_FOREACH_PTR(&ce->function_table, func) { + if (func->type == ZEND_USER_FUNCTION) { + zend_cleanup_op_array_data((zend_op_array *) func); + } + } ZEND_HASH_FOREACH_END(); } if (ce->static_members_table) { + zval *static_members = ce->static_members_table; + int count = ce->default_static_members_count; int i; - for (i = 0; i < ce->default_static_members_count; i++) { - if (ce->static_members_table[i]) { - zval *p = ce->static_members_table[i]; - ce->static_members_table[i] = NULL; - zval_ptr_dtor(&p); - } + ce->default_static_members_count = 0; + ce->default_static_members_table = ce->static_members_table = NULL; + for (i = 0; i < count; i++) { + zval_ptr_dtor(&static_members[i]); } - ce->static_members_table = NULL; + efree(static_members); } } -static inline void cleanup_internal_class_data(zend_class_entry *ce TSRMLS_DC) +ZEND_API void zend_cleanup_internal_class_data(zend_class_entry *ce) { if (CE_STATIC_MEMBERS(ce)) { + zval *static_members = CE_STATIC_MEMBERS(ce); int i; - - for (i = 0; i < ce->default_static_members_count; i++) { - zval_ptr_dtor(&CE_STATIC_MEMBERS(ce)[i]); - } - efree(CE_STATIC_MEMBERS(ce)); + #ifdef ZTS CG(static_members_table)[(zend_intptr_t)(ce->static_members_table)] = NULL; #else ce->static_members_table = NULL; #endif + for (i = 0; i < ce->default_static_members_count; i++) { + zval_ptr_dtor(&static_members[i]); + } + efree(static_members); } } -ZEND_API void zend_cleanup_internal_class_data(zend_class_entry *ce TSRMLS_DC) -{ - cleanup_internal_class_data(ce TSRMLS_CC); -} - -ZEND_API int zend_cleanup_user_class_data(zend_class_entry **pce TSRMLS_DC) -{ - if ((*pce)->type == ZEND_USER_CLASS) { - cleanup_user_class_data(*pce TSRMLS_CC); - return ZEND_HASH_APPLY_KEEP; - } else { - return ZEND_HASH_APPLY_STOP; - } -} - -ZEND_API int zend_cleanup_class_data(zend_class_entry **pce TSRMLS_DC) -{ - if ((*pce)->type == ZEND_USER_CLASS) { - cleanup_user_class_data(*pce TSRMLS_CC); - } else { - cleanup_internal_class_data(*pce TSRMLS_CC); - } - return 0; -} - void _destroy_zend_class_traits_info(zend_class_entry *ce) { if (ce->num_traits > 0 && ce->traits) { efree(ce->traits); } - + if (ce->trait_aliases) { size_t i = 0; while (ce->trait_aliases[i]) { if (ce->trait_aliases[i]->trait_method) { if (ce->trait_aliases[i]->trait_method->method_name) { - efree((char*)ce->trait_aliases[i]->trait_method->method_name); + zend_string_release(ce->trait_aliases[i]->trait_method->method_name); } if (ce->trait_aliases[i]->trait_method->class_name) { - efree((char*)ce->trait_aliases[i]->trait_method->class_name); + zend_string_release(ce->trait_aliases[i]->trait_method->class_name); } efree(ce->trait_aliases[i]->trait_method); } - + if (ce->trait_aliases[i]->alias) { - efree((char*)ce->trait_aliases[i]->alias); + zend_string_release(ce->trait_aliases[i]->alias); } - + efree(ce->trait_aliases[i]); i++; } - + efree(ce->trait_aliases); } if (ce->trait_precedences) { size_t i = 0; - + while (ce->trait_precedences[i]) { - efree((char*)ce->trait_precedences[i]->trait_method->method_name); - efree((char*)ce->trait_precedences[i]->trait_method->class_name); + zend_string_release(ce->trait_precedences[i]->trait_method->method_name); + zend_string_release(ce->trait_precedences[i]->trait_method->class_name); efree(ce->trait_precedences[i]->trait_method); if (ce->trait_precedences[i]->exclude_from_classes) { @@ -266,10 +230,10 @@ void _destroy_zend_class_traits_info(zend_class_entry *ce) } } -ZEND_API void destroy_zend_class(zend_class_entry **pce) +ZEND_API void destroy_zend_class(zval *zv) { - zend_class_entry *ce = *pce; - + zend_class_entry *ce = Z_PTR_P(zv); + if (--ce->refcount > 0) { return; } @@ -279,7 +243,7 @@ ZEND_API void destroy_zend_class(zend_class_entry **pce) int i; for (i = 0; i < ce->default_properties_count; i++) { - if (ce->default_properties_table[i]) { + if (Z_TYPE(ce->default_properties_table[i]) != IS_UNDEF) { zval_ptr_dtor(&ce->default_properties_table[i]); } } @@ -289,33 +253,32 @@ ZEND_API void destroy_zend_class(zend_class_entry **pce) int i; for (i = 0; i < ce->default_static_members_count; i++) { - if (ce->default_static_members_table[i]) { + if (Z_TYPE(ce->default_static_members_table[i]) != IS_UNDEF) { zval_ptr_dtor(&ce->default_static_members_table[i]); } } efree(ce->default_static_members_table); } zend_hash_destroy(&ce->properties_info); - str_efree(ce->name); + zend_string_release(ce->name); zend_hash_destroy(&ce->function_table); zend_hash_destroy(&ce->constants_table); if (ce->num_interfaces > 0 && ce->interfaces) { efree(ce->interfaces); } if (ce->info.user.doc_comment) { - efree((char*)ce->info.user.doc_comment); + zend_string_release(ce->info.user.doc_comment); } - + _destroy_zend_class_traits_info(ce); - - efree(ce); + break; case ZEND_INTERNAL_CLASS: if (ce->default_properties_table) { int i; for (i = 0; i < ce->default_properties_count; i++) { - if (ce->default_properties_table[i]) { + if (Z_TYPE(ce->default_properties_table[i]) != IS_UNDEF) { zval_internal_ptr_dtor(&ce->default_properties_table[i]); } } @@ -330,7 +293,7 @@ ZEND_API void destroy_zend_class(zend_class_entry **pce) free(ce->default_static_members_table); } zend_hash_destroy(&ce->properties_info); - str_free(ce->name); + zend_string_release(ce->name); zend_hash_destroy(&ce->function_table); zend_hash_destroy(&ce->constants_table); if (ce->num_interfaces > 0) { @@ -341,23 +304,25 @@ ZEND_API void destroy_zend_class(zend_class_entry **pce) } } -void zend_class_add_ref(zend_class_entry **ce) +void zend_class_add_ref(zval *zv) { - (*ce)->refcount++; + zend_class_entry *ce = Z_PTR_P(zv); + + ce->refcount++; } -ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC) +ZEND_API void destroy_op_array(zend_op_array *op_array) { - zend_literal *literal = op_array->literals; - zend_literal *end; - zend_uint i; + zval *literal = op_array->literals; + zval *end; + uint32_t i; if (op_array->static_variables) { zend_hash_destroy(op_array->static_variables); FREE_HASHTABLE(op_array->static_variables); } - if (op_array->run_time_cache) { + if (op_array->run_time_cache && !op_array->function_name) { efree(op_array->run_time_cache); } @@ -365,13 +330,13 @@ ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC) return; } - efree(op_array->refcount); + efree_size(op_array->refcount, sizeof(*(op_array->refcount))); if (op_array->vars) { i = op_array->last_var; while (i > 0) { i--; - str_efree(op_array->vars[i].name); + zend_string_release(op_array->vars[i]); } efree(op_array->vars); } @@ -379,7 +344,7 @@ ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC) if (literal) { end = literal + op_array->last_literal; while (literal < end) { - zval_dtor(&literal->constant); + zval_ptr_dtor_nogc(literal); literal++; } efree(op_array->literals); @@ -387,10 +352,10 @@ ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC) efree(op_array->opcodes); if (op_array->function_name) { - efree((char*)op_array->function_name); + zend_string_release(op_array->function_name); } if (op_array->doc_comment) { - efree((char*)op_array->doc_comment); + zend_string_release(op_array->doc_comment); } if (op_array->brk_cont_array) { efree(op_array->brk_cont_array); @@ -399,45 +364,52 @@ ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC) efree(op_array->try_catch_array); } if (op_array->fn_flags & ZEND_ACC_DONE_PASS_TWO) { - zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_dtor_handler, op_array TSRMLS_CC); + zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_dtor_handler, op_array); } if (op_array->arg_info) { - for (i=0; i<op_array->num_args; i++) { - str_efree(op_array->arg_info[i].name); - if (op_array->arg_info[i].class_name) { - str_efree(op_array->arg_info[i].class_name); + int32_t num_args = op_array->num_args; + zend_arg_info *arg_info = op_array->arg_info; + int32_t i; + + if (op_array->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { + arg_info--; + num_args++; + } + if (op_array->fn_flags & ZEND_ACC_VARIADIC) { + num_args++; + } + for (i = 0 ; i < num_args; i++) { + if (arg_info[i].name) { + zend_string_release(arg_info[i].name); + } + if (arg_info[i].class_name) { + zend_string_release(arg_info[i].class_name); } } - efree(op_array->arg_info); + efree(arg_info); } } -void init_op(zend_op *op TSRMLS_DC) +void init_op(zend_op *op) { memset(op, 0, sizeof(zend_op)); op->lineno = CG(zend_lineno); SET_UNUSED(op->result); } -zend_op *get_next_op(zend_op_array *op_array TSRMLS_DC) +zend_op *get_next_op(zend_op_array *op_array) { - zend_uint next_op_num = op_array->last++; + uint32_t next_op_num = op_array->last++; zend_op *next_op; if (next_op_num >= CG(context).opcodes_size) { - if (op_array->fn_flags & ZEND_ACC_INTERACTIVE) { - /* we messed up */ - zend_printf("Ran out of opcode space!\n" - "You should probably consider writing this huge script into a file!\n"); - zend_bailout(); - } CG(context).opcodes_size *= 4; op_array_alloc_ops(op_array, CG(context).opcodes_size); } - + next_op = &(op_array->opcodes[next_op_num]); - - init_op(next_op TSRMLS_CC); + + init_op(next_op); return next_op; } @@ -454,7 +426,7 @@ zend_brk_cont_element *get_next_brk_cont_element(zend_op_array *op_array) return &op_array->brk_cont_array[op_array->last_brk_cont-1]; } -static void zend_update_extended_info(zend_op_array *op_array TSRMLS_DC) +static void zend_update_extended_info(zend_op_array *op_array) { zend_op *opline = op_array->opcodes, *end=opline+op_array->last; @@ -477,16 +449,16 @@ static void zend_update_extended_info(zend_op_array *op_array TSRMLS_DC) } } -static void zend_extension_op_array_handler(zend_extension *extension, zend_op_array *op_array TSRMLS_DC) +static void zend_extension_op_array_handler(zend_extension *extension, zend_op_array *op_array) { if (extension->op_array_handler) { extension->op_array_handler(op_array); } } -static void zend_check_finally_breakout(zend_op_array *op_array, zend_uint op_num, zend_uint dst_num TSRMLS_DC) +static void zend_check_finally_breakout(zend_op_array *op_array, uint32_t op_num, uint32_t dst_num) { - zend_uint i; + int i; for (i = 0; i < op_array->last_try_catch; i++) { if ((op_num < op_array->try_catch_array[i].finally_op || @@ -497,25 +469,25 @@ static void zend_check_finally_breakout(zend_op_array *op_array, zend_uint op_nu CG(active_op_array) = op_array; CG(zend_lineno) = op_array->opcodes[op_num].lineno; zend_error_noreturn(E_COMPILE_ERROR, "jump into a finally block is disallowed"); - } else if ((op_num >= op_array->try_catch_array[i].finally_op + } else if ((op_num >= op_array->try_catch_array[i].finally_op && op_num <= op_array->try_catch_array[i].finally_end) - && (dst_num > op_array->try_catch_array[i].finally_end + && (dst_num > op_array->try_catch_array[i].finally_end || dst_num < op_array->try_catch_array[i].finally_op)) { CG(in_compilation) = 1; CG(active_op_array) = op_array; CG(zend_lineno) = op_array->opcodes[op_num].lineno; zend_error_noreturn(E_COMPILE_ERROR, "jump out of a finally block is disallowed"); } - } + } } -static void zend_adjust_fast_call(zend_op_array *op_array, zend_uint fast_call, zend_uint start, zend_uint end TSRMLS_DC) +static void zend_adjust_fast_call(zend_op_array *op_array, uint32_t fast_call, uint32_t start, uint32_t end) { int i; - zend_uint op_num = 0; + uint32_t op_num = 0; for (i = 0; i < op_array->last_try_catch; i++) { - if (op_array->try_catch_array[i].finally_op > start + if (op_array->try_catch_array[i].finally_op > start && op_array->try_catch_array[i].finally_end < end) { op_num = op_array->try_catch_array[i].finally_op; start = op_array->try_catch_array[i].finally_end; @@ -530,10 +502,10 @@ static void zend_adjust_fast_call(zend_op_array *op_array, zend_uint fast_call, } } -static void zend_resolve_fast_call(zend_op_array *op_array, zend_uint fast_call, zend_uint op_num TSRMLS_DC) +static void zend_resolve_fast_call(zend_op_array *op_array, uint32_t fast_call, uint32_t op_num) { int i; - zend_uint finally_op_num = 0; + uint32_t finally_op_num = 0; for (i = 0; i < op_array->last_try_catch; i++) { if (op_num >= op_array->try_catch_array[i].finally_op @@ -549,17 +521,17 @@ static void zend_resolve_fast_call(zend_op_array *op_array, zend_uint fast_call, op_array->opcodes[fast_call].extended_value = ZEND_FAST_CALL_FROM_FINALLY; op_array->opcodes[fast_call].op2.opline_num = finally_op_num - 2; } - } + } } -static void zend_resolve_finally_call(zend_op_array *op_array, zend_uint op_num, zend_uint dst_num TSRMLS_DC) +static void zend_resolve_finally_call(zend_op_array *op_array, uint32_t op_num, uint32_t dst_num) { - zend_uint start_op; + uint32_t start_op; zend_op *opline; - zend_uint i = op_array->last_try_catch; + uint32_t i = op_array->last_try_catch; - if (dst_num != (zend_uint)-1) { - zend_check_finally_breakout(op_array, op_num, dst_num TSRMLS_CC); + if (dst_num != (uint32_t)-1) { + zend_check_finally_breakout(op_array, op_num, dst_num); } /* the backward order is mater */ @@ -571,29 +543,38 @@ static void zend_resolve_finally_call(zend_op_array *op_array, zend_uint 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 = get_next_op(op_array); 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, op_array->try_catch_array[i].finally_op, - op_array->try_catch_array[i].finally_end TSRMLS_CC); + op_array->try_catch_array[i].finally_end); if (op_array->try_catch_array[i].catch_op) { opline->extended_value = ZEND_FAST_CALL_FROM_CATCH; opline->op2.opline_num = op_array->try_catch_array[i].catch_op; opline->op1.opline_num = get_next_op_number(op_array); /* generate a FAST_CALL to hole CALL_FROM_FINALLY */ - opline = get_next_op(op_array TSRMLS_CC); + opline = get_next_op(op_array); 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); + zend_resolve_fast_call(op_array, start_op + 1, op_array->try_catch_array[i].finally_op - 2); } else { - zend_resolve_fast_call(op_array, start_op, op_array->try_catch_array[i].finally_op - 2 TSRMLS_CC); + zend_resolve_fast_call(op_array, start_op, op_array->try_catch_array[i].finally_op - 2); } opline->op1.opline_num = op_array->try_catch_array[i].finally_op; @@ -606,8 +587,10 @@ static void zend_resolve_finally_call(zend_op_array *op_array, zend_uint op_num, (dst_num < op_array->try_catch_array[i].try_op || dst_num > op_array->try_catch_array[i].finally_end)) { - opline = get_next_op(op_array TSRMLS_CC); + opline = get_next_op(op_array); 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; @@ -615,7 +598,7 @@ static void zend_resolve_finally_call(zend_op_array *op_array, zend_uint op_num, } /* Finish the sequence with original opcode */ - opline = get_next_op(op_array TSRMLS_CC); + opline = get_next_op(op_array); *opline = op_array->opcodes[op_num]; /* Replace original opcode with jump to this sequence */ @@ -627,13 +610,13 @@ static void zend_resolve_finally_call(zend_op_array *op_array, zend_uint op_num, break; } - } + } } -static void zend_resolve_finally_ret(zend_op_array *op_array, zend_uint op_num TSRMLS_DC) +static void zend_resolve_finally_ret(zend_op_array *op_array, uint32_t op_num) { int i; - zend_uint catch_op_num = 0, finally_op_num = 0; + uint32_t catch_op_num = 0, finally_op_num = 0; for (i = 0; i < op_array->last_try_catch; i++) { if (op_array->try_catch_array[i].try_op > op_num) { @@ -658,9 +641,9 @@ static void zend_resolve_finally_ret(zend_op_array *op_array, zend_uint op_num T } } -static void zend_resolve_finally_calls(zend_op_array *op_array TSRMLS_DC) +static void zend_resolve_finally_calls(zend_op_array *op_array) { - zend_uint i, j; + uint32_t i, j; zend_op *opline; for (i = 0, j = op_array->last; i < j; i++) { @@ -669,7 +652,7 @@ static void zend_resolve_finally_calls(zend_op_array *op_array TSRMLS_DC) case ZEND_RETURN: case ZEND_RETURN_BY_REF: case ZEND_GENERATOR_RETURN: - zend_resolve_finally_call(op_array, i, (zend_uint)-1 TSRMLS_CC); + zend_resolve_finally_call(op_array, i, (uint32_t)-1); break; case ZEND_BRK: case ZEND_CONT: @@ -677,7 +660,7 @@ static void zend_resolve_finally_calls(zend_op_array *op_array TSRMLS_DC) int nest_levels, array_offset; zend_brk_cont_element *jmp_to; - nest_levels = Z_LVAL(op_array->literals[opline->op2.constant].constant); + nest_levels = Z_LVAL(op_array->literals[opline->op2.constant]); if ((array_offset = opline->op1.opline_num) != -1) { do { jmp_to = &op_array->brk_cont_array[array_offset]; @@ -685,26 +668,27 @@ static void zend_resolve_finally_calls(zend_op_array *op_array TSRMLS_DC) array_offset = jmp_to->parent; } } while (--nest_levels > 0); - zend_resolve_finally_call(op_array, i, opline->opcode == ZEND_BRK ? jmp_to->brk : jmp_to->cont TSRMLS_CC); + zend_resolve_finally_call(op_array, i, opline->opcode == ZEND_BRK ? jmp_to->brk : jmp_to->cont); break; } } case ZEND_GOTO: - if (Z_TYPE(op_array->literals[opline->op2.constant].constant) != IS_LONG) { - zend_uint num = opline->op2.constant; - opline->op2.zv = &op_array->literals[opline->op2.constant].constant; - zend_resolve_goto_label(op_array, opline, 1 TSRMLS_CC); - opline->op2.constant = num; + if (Z_TYPE_P(CT_CONSTANT_EX(op_array, opline->op2.constant)) != IS_LONG) { + uint32_t num = opline->op2.constant; + + ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline->op2); + zend_resolve_goto_label(op_array, opline, 1); + opline->op2.constant = num; } /* break omitted intentionally */ case ZEND_JMP: - zend_resolve_finally_call(op_array, i, opline->op1.opline_num TSRMLS_CC); + zend_resolve_finally_call(op_array, i, opline->op1.opline_num); break; case ZEND_FAST_CALL: - zend_resolve_fast_call(op_array, i, i TSRMLS_CC); + zend_resolve_fast_call(op_array, i, i); break; case ZEND_FAST_RET: - zend_resolve_finally_ret(op_array, i TSRMLS_CC); + zend_resolve_finally_ret(op_array, i); break; default: break; @@ -712,67 +696,91 @@ static void zend_resolve_finally_calls(zend_op_array *op_array TSRMLS_DC) } } -ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC) +ZEND_API int pass_two(zend_op_array *op_array) { zend_op *opline, *end; - if (op_array->type!=ZEND_USER_FUNCTION && op_array->type!=ZEND_EVAL_CODE) { + if (!ZEND_USER_CODE(op_array->type)) { return 0; } - if (op_array->has_finally_block) { - zend_resolve_finally_calls(op_array TSRMLS_CC); + if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) { + zend_resolve_finally_calls(op_array); } if (CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO) { - zend_update_extended_info(op_array TSRMLS_CC); + zend_update_extended_info(op_array); } if (CG(compiler_options) & ZEND_COMPILE_HANDLE_OP_ARRAY) { - zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_handler, op_array TSRMLS_CC); + zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_handler, op_array); } - if (!(op_array->fn_flags & ZEND_ACC_INTERACTIVE) && CG(context).vars_size != op_array->last_var) { - op_array->vars = (zend_compiled_variable *) erealloc(op_array->vars, sizeof(zend_compiled_variable)*op_array->last_var); + if (CG(context).vars_size != op_array->last_var) { + op_array->vars = (zend_string**) erealloc(op_array->vars, sizeof(zend_string*)*op_array->last_var); CG(context).vars_size = op_array->last_var; } - if (!(op_array->fn_flags & ZEND_ACC_INTERACTIVE) && CG(context).opcodes_size != op_array->last) { + if (CG(context).opcodes_size != op_array->last) { op_array->opcodes = (zend_op *) erealloc(op_array->opcodes, sizeof(zend_op)*op_array->last); CG(context).opcodes_size = op_array->last; } - if (!(op_array->fn_flags & ZEND_ACC_INTERACTIVE) && CG(context).literals_size != op_array->last_literal) { - op_array->literals = (zend_literal*)erealloc(op_array->literals, sizeof(zend_literal) * op_array->last_literal); + if (CG(context).literals_size != op_array->last_literal) { + op_array->literals = (zval*)erealloc(op_array->literals, sizeof(zval) * op_array->last_literal); CG(context).literals_size = op_array->last_literal; } - opline = op_array->opcodes; end = opline + op_array->last; while (opline < end) { if (opline->op1_type == IS_CONST) { - opline->op1.zv = &op_array->literals[opline->op1.constant].constant; + ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline->op1); + } else if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) { + opline->op1.var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + opline->op1.var); } if (opline->op2_type == IS_CONST) { - opline->op2.zv = &op_array->literals[opline->op2.constant].constant; + ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline->op2); + } else if (opline->op2_type & (IS_VAR|IS_TMP_VAR)) { + opline->op2.var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + opline->op2.var); + } + if (opline->result_type & (IS_VAR|IS_TMP_VAR)) { + opline->result.var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + opline->result.var); } switch (opline->opcode) { + case ZEND_DECLARE_INHERITED_CLASS: + case ZEND_DECLARE_INHERITED_CLASS_DELAYED: + opline->extended_value = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + opline->extended_value); + break; case ZEND_GOTO: - if (Z_TYPE_P(opline->op2.zv) != IS_LONG) { - zend_resolve_goto_label(op_array, opline, 1 TSRMLS_CC); + if (Z_TYPE_P(RT_CONSTANT(op_array, opline->op2)) != IS_LONG) { + zend_resolve_goto_label(op_array, opline, 1); } /* break omitted intentionally */ case ZEND_JMP: case ZEND_FAST_CALL: - opline->op1.jmp_addr = &op_array->opcodes[opline->op1.opline_num]; + ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op1); break; + case ZEND_JMPZNZ: + /* absolute index to relative offset */ + opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline->extended_value); + /* break omitted intentionally */ case ZEND_JMPZ: case ZEND_JMPNZ: case ZEND_JMPZ_EX: case ZEND_JMPNZ_EX: case ZEND_JMP_SET: - case ZEND_JMP_SET_VAR: - opline->op2.jmp_addr = &op_array->opcodes[opline->op2.opline_num]; + case ZEND_COALESCE: + case ZEND_NEW: + case ZEND_FE_RESET_R: + case ZEND_FE_RESET_RW: + case ZEND_FE_FETCH_R: + case ZEND_FE_FETCH_RW: + ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op2); + break; + case ZEND_VERIFY_RETURN_TYPE: + if (op_array->fn_flags & ZEND_ACC_GENERATOR) { + MAKE_NOP(opline); + } break; case ZEND_RETURN: case ZEND_RETURN_BY_REF: if (op_array->fn_flags & ZEND_ACC_GENERATOR) { - if (opline->op1_type != IS_CONST || Z_TYPE_P(opline->op1.zv) != IS_NULL) { + if (opline->op1_type != IS_CONST || Z_TYPE_P(RT_CONSTANT(op_array, opline->op1)) != IS_NULL) { CG(zend_lineno) = opline->lineno; zend_error_noreturn(E_COMPILE_ERROR, "Generators cannot return values using \"return\""); } @@ -789,11 +797,16 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC) return 0; } -int print_class(zend_class_entry *class_entry TSRMLS_DC) +int pass_two_wrapper(zval *el) +{ + return pass_two((zend_op_array *) Z_PTR_P(el)); +} + +int print_class(zend_class_entry *class_entry) { - printf("Class %s:\n", class_entry->name); - zend_hash_apply(&class_entry->function_table, (apply_func_t) pass_two TSRMLS_CC); - printf("End of class %s.\n\n", class_entry->name); + printf("Class %s:\n", class_entry->name->val); + zend_hash_apply(&class_entry->function_table, pass_two_wrapper); + printf("End of class %s.\n\n", class_entry->name->val); return 0; } @@ -802,13 +815,10 @@ ZEND_API unary_op_type get_unary_op(int opcode) switch (opcode) { case ZEND_BW_NOT: return (unary_op_type) bitwise_not_function; - break; case ZEND_BOOL_NOT: return (unary_op_type) boolean_not_function; - break; default: return (unary_op_type) NULL; - break; } } @@ -818,74 +828,54 @@ ZEND_API binary_op_type get_binary_op(int opcode) case ZEND_ADD: case ZEND_ASSIGN_ADD: return (binary_op_type) add_function; - break; case ZEND_SUB: case ZEND_ASSIGN_SUB: return (binary_op_type) sub_function; - break; case ZEND_MUL: case ZEND_ASSIGN_MUL: return (binary_op_type) mul_function; - break; case ZEND_POW: return (binary_op_type) pow_function; - break; case ZEND_DIV: case ZEND_ASSIGN_DIV: return (binary_op_type) div_function; - break; case ZEND_MOD: case ZEND_ASSIGN_MOD: return (binary_op_type) mod_function; - break; case ZEND_SL: case ZEND_ASSIGN_SL: return (binary_op_type) shift_left_function; - break; case ZEND_SR: case ZEND_ASSIGN_SR: return (binary_op_type) shift_right_function; - break; case ZEND_CONCAT: case ZEND_ASSIGN_CONCAT: return (binary_op_type) concat_function; - break; case ZEND_IS_IDENTICAL: return (binary_op_type) is_identical_function; - break; case ZEND_IS_NOT_IDENTICAL: return (binary_op_type) is_not_identical_function; - break; case ZEND_IS_EQUAL: return (binary_op_type) is_equal_function; - break; case ZEND_IS_NOT_EQUAL: return (binary_op_type) is_not_equal_function; - break; case ZEND_IS_SMALLER: return (binary_op_type) is_smaller_function; - break; case ZEND_IS_SMALLER_OR_EQUAL: return (binary_op_type) is_smaller_or_equal_function; - break; case ZEND_BW_OR: case ZEND_ASSIGN_BW_OR: return (binary_op_type) bitwise_or_function; - break; case ZEND_BW_AND: case ZEND_ASSIGN_BW_AND: return (binary_op_type) bitwise_and_function; - break; case ZEND_BW_XOR: case ZEND_ASSIGN_BW_XOR: return (binary_op_type) bitwise_xor_function; - break; case ZEND_BOOL_XOR: return (binary_op_type) boolean_xor_function; - break; default: return (binary_op_type) NULL; - break; } } |