--- embedaddon/php/Zend/zend_opcode.c 2012/02/21 23:47:52 1.1 +++ embedaddon/php/Zend/zend_opcode.c 2012/05/29 12:34:36 1.1.1.2 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_opcode.c,v 1.1 2012/02/21 23:47:52 misho Exp $ */ +/* $Id: zend_opcode.c,v 1.1.1.2 2012/05/29 12:34:36 misho Exp $ */ #include @@ -43,31 +43,28 @@ static void zend_extension_op_array_dtor_handler(zend_ } } -static void op_array_alloc_ops(zend_op_array *op_array) +static void op_array_alloc_ops(zend_op_array *op_array, zend_uint size) { - op_array->opcodes = erealloc(op_array->opcodes, (op_array->size)*sizeof(zend_op)); + 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) { op_array->type = type; - op_array->backpatch_count = 0; 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 = 8192; + initial_ops_size = INITIAL_INTERACTIVE_OP_ARRAY_SIZE; } op_array->refcount = (zend_uint *) emalloc(sizeof(zend_uint)); *op_array->refcount = 1; - op_array->size = initial_ops_size; op_array->last = 0; op_array->opcodes = NULL; - op_array_alloc_ops(op_array); + op_array_alloc_ops(op_array, initial_ops_size); - op_array->size_var = 0; /* FIXME:??? */ op_array->last_var = 0; op_array->vars = NULL; @@ -87,22 +84,22 @@ void init_op_array(zend_op_array *op_array, zend_uchar op_array->brk_cont_array = NULL; op_array->try_catch_array = NULL; op_array->last_brk_cont = 0; - op_array->current_brk_cont = -1; op_array->static_variables = NULL; op_array->last_try_catch = 0; - op_array->return_reference = 0; - op_array->done_pass_two = 0; - op_array->this_var = -1; - op_array->start_op = NULL; - op_array->fn_flags = CG(interactive)?ZEND_ACC_INTERACTIVE:0; op_array->early_binding = -1; + op_array->last_literal = 0; + op_array->literals = NULL; + + op_array->run_time_cache = NULL; + op_array->last_cache_slot = 0; + 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); @@ -152,29 +149,118 @@ ZEND_API int zend_cleanup_function_data_full(zend_func return 0; } -ZEND_API int zend_cleanup_class_data(zend_class_entry **pce TSRMLS_DC) +static inline void cleanup_user_class_data(zend_class_entry *ce TSRMLS_DC) { - if ((*pce)->type == ZEND_USER_CLASS) { - /* 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 */ - zend_hash_apply(&(*pce)->function_table, (apply_func_t) zend_cleanup_function_data_full TSRMLS_CC); - if ((*pce)->static_members) { - zend_hash_clean((*pce)->static_members); - (*pce)->static_members = NULL; + /* 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); + } + if (ce->static_members_table) { + int i; + + for (i = 0; i < ce->default_static_members_count; i++) { + if (ce->static_members_table[i]) { + zval_ptr_dtor(&ce->static_members_table[i]); + ce->static_members_table[i] = NULL; + } } - } else if (CE_STATIC_MEMBERS(*pce)) { - zend_hash_destroy(CE_STATIC_MEMBERS(*pce)); - FREE_HASHTABLE(CE_STATIC_MEMBERS(*pce)); + ce->static_members_table = NULL; + } +} + +static inline void cleanup_internal_class_data(zend_class_entry *ce TSRMLS_DC) +{ + if (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)[(zend_intptr_t)((*pce)->static_members)] = NULL; + CG(static_members_table)[(zend_intptr_t)(ce->static_members_table)] = NULL; #else - (*pce)->static_members = NULL; + ce->static_members_table = NULL; #endif } +} + +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); + } + if (ce->trait_aliases[i]->trait_method->class_name) { + efree((char*)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); + } + + 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); + efree(ce->trait_precedences[i]->trait_method); + + if (ce->trait_precedences[i]->exclude_from_classes) { + efree(ce->trait_precedences[i]->exclude_from_classes); + } + + efree(ce->trait_precedences[i]); + i++; + } + efree(ce->trait_precedences); + } +} + ZEND_API void destroy_zend_class(zend_class_entry **pce) { zend_class_entry *ce = *pce; @@ -184,33 +270,67 @@ ZEND_API void destroy_zend_class(zend_class_entry **pc } switch (ce->type) { case ZEND_USER_CLASS: - zend_hash_destroy(&ce->default_properties); + if (ce->default_properties_table) { + int i; + + for (i = 0; i < ce->default_properties_count; i++) { + if (ce->default_properties_table[i]) { + zval_ptr_dtor(&ce->default_properties_table[i]); + } + } + efree(ce->default_properties_table); + } + if (ce->default_static_members_table) { + int i; + + for (i = 0; i < ce->default_static_members_count; i++) { + if (ce->default_static_members_table[i]) { + zval_ptr_dtor(&ce->default_static_members_table[i]); + } + } + efree(ce->default_static_members_table); + } zend_hash_destroy(&ce->properties_info); - zend_hash_destroy(&ce->default_static_members); - efree(ce->name); + str_efree(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->doc_comment) { - efree(ce->doc_comment); + if (ce->info.user.doc_comment) { + efree((char*)ce->info.user.doc_comment); } + + _destroy_zend_class_traits_info(ce); + efree(ce); break; case ZEND_INTERNAL_CLASS: - zend_hash_destroy(&ce->default_properties); + if (ce->default_properties_table) { + int i; + + for (i = 0; i < ce->default_properties_count; i++) { + if (ce->default_properties_table[i]) { + zval_internal_ptr_dtor(&ce->default_properties_table[i]); + } + } + free(ce->default_properties_table); + } + if (ce->default_static_members_table) { + int i; + + for (i = 0; i < ce->default_static_members_count; i++) { + zval_internal_ptr_dtor(&ce->default_static_members_table[i]); + } + free(ce->default_static_members_table); + } zend_hash_destroy(&ce->properties_info); - zend_hash_destroy(&ce->default_static_members); - free(ce->name); + str_free(ce->name); zend_hash_destroy(&ce->function_table); zend_hash_destroy(&ce->constants_table); if (ce->num_interfaces > 0) { free(ce->interfaces); } - if (ce->doc_comment) { - free(ce->doc_comment); - } free(ce); break; } @@ -223,8 +343,8 @@ void zend_class_add_ref(zend_class_entry **ce) ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC) { - zend_op *opline = op_array->opcodes; - zend_op *end = op_array->opcodes+op_array->last; + zend_literal *literal = op_array->literals; + zend_literal *end; zend_uint i; if (op_array->static_variables) { @@ -232,6 +352,10 @@ ZEND_API void destroy_op_array(zend_op_array *op_array FREE_HASHTABLE(op_array->static_variables); } + if (op_array->run_time_cache) { + efree(op_array->run_time_cache); + } + if (--(*op_array->refcount)>0) { return; } @@ -242,33 +366,26 @@ ZEND_API void destroy_op_array(zend_op_array *op_array i = op_array->last_var; while (i > 0) { i--; - efree(op_array->vars[i].name); + str_efree(op_array->vars[i].name); } efree(op_array->vars); } - while (oplineop1.op_type==IS_CONST) { -#if DEBUG_ZEND>2 - printf("Reducing refcount for %x 1=>0 (destroying)\n", &opline->op1.u.constant); -#endif - zval_dtor(&opline->op1.u.constant); + if (literal) { + end = literal + op_array->last_literal; + while (literal < end) { + zval_dtor(&literal->constant); + literal++; } - if (opline->op2.op_type==IS_CONST) { -#if DEBUG_ZEND>2 - printf("Reducing refcount for %x 1=>0 (destroying)\n", &opline->op2.u.constant); -#endif - zval_dtor(&opline->op2.u.constant); - } - opline++; + efree(op_array->literals); } efree(op_array->opcodes); if (op_array->function_name) { - efree(op_array->function_name); + efree((char*)op_array->function_name); } if (op_array->doc_comment) { - efree(op_array->doc_comment); + efree((char*)op_array->doc_comment); } if (op_array->brk_cont_array) { efree(op_array->brk_cont_array); @@ -276,14 +393,14 @@ ZEND_API void destroy_op_array(zend_op_array *op_array if (op_array->try_catch_array) { efree(op_array->try_catch_array); } - if (op_array->done_pass_two) { + 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); } if (op_array->arg_info) { for (i=0; inum_args; i++) { - efree((char*)op_array->arg_info[i].name); + str_efree(op_array->arg_info[i].name); if (op_array->arg_info[i].class_name) { - efree((char*)op_array->arg_info[i].class_name); + str_efree(op_array->arg_info[i].class_name); } } efree(op_array->arg_info); @@ -302,15 +419,15 @@ zend_op *get_next_op(zend_op_array *op_array TSRMLS_DC zend_uint next_op_num = op_array->last++; zend_op *next_op; - if (next_op_num >= op_array->size) { + 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(); } - op_array->size *= 4; - op_array_alloc_ops(op_array); + CG(context).opcodes_size *= 4; + op_array_alloc_ops(op_array, CG(context).opcodes_size); } next_op = &(op_array->opcodes[next_op_num]); @@ -376,44 +493,51 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_D zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_handler, op_array TSRMLS_CC); } - if (!(op_array->fn_flags & ZEND_ACC_INTERACTIVE) && op_array->size != op_array->last) { + 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); + CG(context).vars_size = op_array->last_var; + } + if (!(op_array->fn_flags & ZEND_ACC_INTERACTIVE) && CG(context).opcodes_size != op_array->last) { op_array->opcodes = (zend_op *) erealloc(op_array->opcodes, sizeof(zend_op)*op_array->last); - op_array->size = 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); + CG(context).literals_size = op_array->last_literal; + } opline = op_array->opcodes; end = opline + op_array->last; while (opline < end) { - if (opline->op1.op_type == IS_CONST) { - Z_SET_ISREF(opline->op1.u.constant); - Z_SET_REFCOUNT(opline->op1.u.constant, 2); /* Make sure is_ref won't be reset */ + if (opline->op1_type == IS_CONST) { + opline->op1.zv = &op_array->literals[opline->op1.constant].constant; } - if (opline->op2.op_type == IS_CONST) { - Z_SET_ISREF(opline->op2.u.constant); - Z_SET_REFCOUNT(opline->op2.u.constant, 2); + if (opline->op2_type == IS_CONST) { + opline->op2.zv = &op_array->literals[opline->op2.constant].constant; } switch (opline->opcode) { case ZEND_GOTO: - if (Z_TYPE(opline->op2.u.constant) != IS_LONG) { + if (Z_TYPE_P(opline->op2.zv) != IS_LONG) { zend_resolve_goto_label(op_array, opline, 1 TSRMLS_CC); } /* break omitted intentionally */ case ZEND_JMP: - opline->op1.u.jmp_addr = &op_array->opcodes[opline->op1.u.opline_num]; + opline->op1.jmp_addr = &op_array->opcodes[opline->op1.opline_num]; break; case ZEND_JMPZ: case ZEND_JMPNZ: case ZEND_JMPZ_EX: case ZEND_JMPNZ_EX: case ZEND_JMP_SET: - opline->op2.u.jmp_addr = &op_array->opcodes[opline->op2.u.opline_num]; + case ZEND_JMP_SET_VAR: + opline->op2.jmp_addr = &op_array->opcodes[opline->op2.opline_num]; break; } ZEND_VM_SET_OPCODE_HANDLER(opline); opline++; } - - op_array->done_pass_two = 1; + + op_array->fn_flags |= ZEND_ACC_DONE_PASS_TWO; return 0; }