diff options
Diffstat (limited to 'Zend/zend_opcode.c')
-rw-r--r-- | Zend/zend_opcode.c | 148 |
1 files changed, 60 insertions, 88 deletions
diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 2cf32b9c0a..bffe9e2d6e 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -78,15 +78,13 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz op_array->scope = NULL; op_array->prototype = NULL; - op_array->brk_cont_array = NULL; + op_array->live_range = NULL; op_array->try_catch_array = NULL; - op_array->last_brk_cont = 0; + op_array->last_live_range = 0; op_array->static_variables = NULL; op_array->last_try_catch = 0; - op_array->this_var = -1; - op_array->fn_flags = 0; op_array->early_binding = -1; @@ -287,7 +285,19 @@ ZEND_API void destroy_zend_class(zval *zv) zend_hash_destroy(&ce->properties_info); zend_string_release(ce->name); zend_hash_destroy(&ce->function_table); - zend_hash_destroy(&ce->constants_table); + if (zend_hash_num_elements(&ce->constants_table)) { + zend_class_constant *c; + + ZEND_HASH_FOREACH_PTR(&ce->constants_table, c) { + if (c->ce == ce) { + zval_ptr_dtor(&c->value); + if (c->doc_comment) { + zend_string_release(c->doc_comment); + } + } + } ZEND_HASH_FOREACH_END(); + zend_hash_destroy(&ce->constants_table); + } if (ce->num_interfaces > 0 && ce->interfaces) { efree(ce->interfaces); } @@ -322,7 +332,17 @@ ZEND_API void destroy_zend_class(zval *zv) zend_hash_destroy(&ce->properties_info); zend_string_release(ce->name); zend_hash_destroy(&ce->function_table); - zend_hash_destroy(&ce->constants_table); + if (zend_hash_num_elements(&ce->constants_table)) { + zend_class_constant *c; + + ZEND_HASH_FOREACH_PTR(&ce->constants_table, c) { + zval_internal_ptr_dtor(&c->value); + if (c->doc_comment && c->ce == ce) { + zend_string_release(c->doc_comment); + } + } ZEND_HASH_FOREACH_END(); + zend_hash_destroy(&ce->constants_table); + } if (ce->num_interfaces > 0) { free(ce->interfaces); } @@ -387,8 +407,8 @@ ZEND_API void destroy_op_array(zend_op_array *op_array) if (op_array->doc_comment) { zend_string_release(op_array->doc_comment); } - if (op_array->brk_cont_array) { - efree(op_array->brk_cont_array); + if (op_array->live_range) { + efree(op_array->live_range); } if (op_array->try_catch_array) { efree(op_array->try_catch_array); @@ -445,16 +465,16 @@ zend_op *get_next_op(zend_op_array *op_array) return next_op; } -int get_next_op_number(zend_op_array *op_array) +uint32_t get_next_op_number(zend_op_array *op_array) { return op_array->last; } -zend_brk_cont_element *get_next_brk_cont_element(zend_op_array *op_array) +zend_brk_cont_element *get_next_brk_cont_element(void) { - op_array->last_brk_cont++; - op_array->brk_cont_array = erealloc(op_array->brk_cont_array, sizeof(zend_brk_cont_element)*op_array->last_brk_cont); - return &op_array->brk_cont_array[op_array->last_brk_cont-1]; + CG(context).last_brk_cont++; + CG(context).brk_cont_array = erealloc(CG(context).brk_cont_array, sizeof(zend_brk_cont_element) * CG(context).last_brk_cont); + return &CG(context).brk_cont_array[CG(context).last_brk_cont-1]; } static void zend_update_extended_info(zend_op_array *op_array) @@ -512,60 +532,12 @@ static void zend_check_finally_breakout(zend_op_array *op_array, uint32_t op_num } } -static void zend_resolve_fast_call(zend_op_array *op_array, uint32_t op_num) -{ - int i; - 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 - && op_num < op_array->try_catch_array[i].finally_end) { - finally_op_num = op_array->try_catch_array[i].finally_op; - } - } - - if (finally_op_num) { - /* Must be ZEND_FAST_CALL */ - ZEND_ASSERT(op_array->opcodes[finally_op_num - 2].opcode == ZEND_FAST_CALL); - op_array->opcodes[op_num].extended_value = ZEND_FAST_CALL_FROM_FINALLY; - op_array->opcodes[op_num].op2.opline_num = finally_op_num - 2; - } -} - -static void zend_resolve_finally_ret(zend_op_array *op_array, uint32_t op_num) -{ - int i; - 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) { - break; - } - if (op_num < op_array->try_catch_array[i].finally_op) { - finally_op_num = op_array->try_catch_array[i].finally_op; - } - if (op_num < op_array->try_catch_array[i].catch_op) { - catch_op_num = op_array->try_catch_array[i].catch_op; - } - } - - if (finally_op_num && (!catch_op_num || catch_op_num >= finally_op_num)) { - /* in case of unhandled exception return to upward finally block */ - op_array->opcodes[op_num].extended_value = ZEND_FAST_RET_TO_FINALLY; - op_array->opcodes[op_num].op2.opline_num = finally_op_num; - } else if (catch_op_num) { - /* in case of unhandled exception return to upward catch block */ - op_array->opcodes[op_num].extended_value = ZEND_FAST_RET_TO_CATCH; - op_array->opcodes[op_num].op2.opline_num = catch_op_num; - } -} - static uint32_t zend_get_brk_cont_target(const zend_op_array *op_array, const zend_op *opline) { int nest_levels = opline->op2.num; int array_offset = opline->op1.num; zend_brk_cont_element *jmp_to; do { - jmp_to = &op_array->brk_cont_array[array_offset]; + jmp_to = &CG(context).brk_cont_array[array_offset]; if (nest_levels > 1) { array_offset = jmp_to->parent; } @@ -608,19 +580,8 @@ ZEND_API int pass_two(zend_op_array *op_array) switch (opline->opcode) { case ZEND_FAST_CALL: opline->op1.opline_num = op_array->try_catch_array[opline->op1.num].finally_op; - zend_resolve_fast_call(op_array, opline - op_array->opcodes); ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op1); break; - case ZEND_FAST_RET: - zend_resolve_finally_ret(op_array, opline - op_array->opcodes); - break; - case ZEND_DECLARE_ANON_INHERITED_CLASS: - ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op1); - /* break omitted intentionally */ - 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_BRK: case ZEND_CONT: { @@ -642,7 +603,6 @@ ZEND_API int pass_two(zend_op_array *op_array) } /* break omitted intentionally */ case ZEND_JMP: - case ZEND_DECLARE_ANON_CLASS: ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op1); break; case ZEND_JMPZNZ: @@ -655,29 +615,31 @@ ZEND_API int pass_two(zend_op_array *op_array) case ZEND_JMPNZ_EX: case ZEND_JMP_SET: case ZEND_COALESCE: - case ZEND_NEW: case ZEND_FE_RESET_R: case ZEND_FE_RESET_RW: + ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op2); + break; case ZEND_ASSERT_CHECK: + { + /* If result of assert is unused, result of check is unused as well */ + zend_op *call = &op_array->opcodes[opline->op2.opline_num - 1]; + if (call->opcode == ZEND_EXT_FCALL_END) { + call--; + } + if (call->result_type == IS_UNUSED) { + opline->result_type = IS_UNUSED; + } ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op2); break; + } + case ZEND_DECLARE_ANON_CLASS: + case ZEND_DECLARE_ANON_INHERITED_CLASS: + case ZEND_CATCH: case ZEND_FE_FETCH_R: case ZEND_FE_FETCH_RW: + /* absolute index to relative offset */ opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline->extended_value); break; - case ZEND_VERIFY_RETURN_TYPE: - if (op_array->fn_flags & ZEND_ACC_GENERATOR) { - if (opline->op1_type != IS_UNUSED) { - zend_op *ret = opline; - do ret++; while (ret->opcode != ZEND_RETURN); - - ret->op1 = opline->op1; - ret->op1_type = opline->op1_type; - } - - MAKE_NOP(opline); - } - break; case ZEND_RETURN: case ZEND_RETURN_BY_REF: if (op_array->fn_flags & ZEND_ACC_GENERATOR) { @@ -702,6 +664,16 @@ ZEND_API int pass_two(zend_op_array *op_array) opline++; } + if (op_array->live_range) { + int i; + + for (i = 0; i < op_array->last_live_range; i++) { + op_array->live_range[i].var = + (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + (op_array->live_range[i].var / sizeof(zval))) | + (op_array->live_range[i].var & ZEND_LIVE_MASK); + } + } + op_array->fn_flags |= ZEND_ACC_DONE_PASS_TWO; return 0; } |