Index: apc_optimizer.c =================================================================== RCS file: /repository/pecl/apc/apc_optimizer.c,v retrieving revision 3.35 diff -u -r3.35 apc_optimizer.c --- apc_optimizer.c 8 Jun 2006 07:51:53 -0000 3.35 +++ apc_optimizer.c 24 Aug 2006 20:21:42 -0000 @@ -474,6 +474,67 @@ clear_zend_op(&ops[cadr(p)]); } +#ifdef ZEND_ENGINE_2 +static void rewrite_array_merge(zend_op* ops, Pair* p TSRMLS_DC) +{ + zend_op* first; + zend_op* second; + zval *tmp; + + HashTable *ht; + + first = &ops[car(p)]; + second = &ops[cadr(p)]; + + + if(first->opcode == ZEND_INIT_ARRAY) { + ALLOC_HASHTABLE(ht); + zend_hash_init(ht, 0, NULL, ZVAL_PTR_DTOR, 1); + + ALLOC_ZVAL(tmp); + *tmp = first->op1.u.constant; + zval_copy_ctor(tmp); + tmp->refcount = 1; + tmp->is_ref = 0; + zend_hash_update(ht, first->op2.u.constant.value.str.val, first->op2.u.constant.value.str.len + 1, + (void *) &tmp, sizeof(zval *), NULL); + } + else if(first->opcode == ZEND_QM_ASSIGN + && second->result.op_type == IS_TMP_VAR + && first->result.op_type == IS_TMP_VAR + && first->result.u.var == second->result.u.var + ) { + ht = first->op1.u.constant.value.ht; + first->op1.u.constant.value.ht = NULL; /* prevent clobbering in clear_zend_op */ + } + else if(first->opcode == ZEND_QM_ASSIGN + && second->op1.op_type == IS_TMP_VAR + && first->result.op_type == IS_TMP_VAR + && first->result.u.var == second->op1.u.var) { + second->op1 = first->op1; + first->op1.u.constant.value.ht = NULL; /* prevent clobbering in clear_zend_op */ + clear_zend_op(first); + return; + } + + ALLOC_ZVAL(tmp); + *tmp = second->op1.u.constant; + zval_copy_ctor(tmp); + tmp->refcount = 1; + tmp->is_ref = 0; + zend_hash_update(ht, second->op2.u.constant.value.str.val, second->op2.u.constant.value.str.len + 1, + (void *) &tmp, sizeof(zval *), NULL); + second->opcode = ZEND_QM_ASSIGN; + second->extended_value = 0; + second->op1.op_type = IS_CONST; + second->op1.u.constant.type = IS_ARRAY; + second->op1.u.constant.value.ht = ht; + second->op1.u.constant.refcount = 1; + second->op2.op_type = IS_UNUSED; + clear_zend_op(first); +} +#endif + /* }}} */ /* {{{ peephole helper functions */ @@ -956,6 +1017,72 @@ /* }}} */ +#ifdef ZEND_ENGINE_2 +/* {{{ peephole_array_merge */ +static Pair* peephole_array_merge(zend_op* ops, int i, int num_ops) +{ + int j; + + j = next_op(ops, i, num_ops); + if (j == num_ops) { + return NULL; + } + + /* + * INIT_ARRAY ~i,v,k + * ADD_ARRAY_ELEMENT ~i,v,k + */ + if(ops[i].opcode == ZEND_INIT_ARRAY + && ops[j].opcode == ZEND_ADD_ARRAY_ELEMENT + && ops[i].result.op_type == IS_TMP_VAR + && ops[i].op1.op_type == IS_CONST + && ops[i].op2.op_type == IS_CONST + && ops[j].result.op_type == IS_TMP_VAR + && ops[j].op1.op_type == IS_CONST + && ops[j].op2.op_type == IS_CONST + && ops[j].op2.u.constant.type == IS_STRING /* only for string hashes */ + && ops[i].result.u.var == ops[j].result.u.var) { + + return cons(i, cons(j, 0)); + } + /* + * QM_ASSIGN ~i, + * ADD_ARRAY_ELEMENT ~i,v,k + */ + if(ops[i].opcode == ZEND_QM_ASSIGN + && ops[j].opcode == ZEND_ADD_ARRAY_ELEMENT + && ops[i].result.op_type == IS_TMP_VAR + && ops[i].op1.op_type == IS_CONST + && ops[i].op2.op_type == IS_UNUSED + && ops[j].result.op_type == IS_TMP_VAR + && ops[j].op1.op_type == IS_CONST + && ops[j].op2.op_type == IS_CONST + && ops[j].op2.u.constant.type == IS_STRING /* only for string hashes */ + && ops[i].result.u.var == ops[j].result.u.var) { + return cons(i, cons(j, 0)); + } + /* + * QM_ASSIGN ~i, + * ADD_ARRAY_ELEMENT ~j,~i,k + */ + if(ops[i].opcode == ZEND_QM_ASSIGN + && ops[j].opcode == ZEND_ADD_ARRAY_ELEMENT + && ops[i].result.op_type == IS_TMP_VAR + && ops[i].op1.op_type == IS_CONST + && ops[i].op1.u.constant.type == IS_ARRAY /* only for arrays */ + && ops[i].op2.op_type == IS_UNUSED + && ops[j].result.op_type == IS_TMP_VAR + && ops[j].op1.op_type == IS_TMP_VAR + && ops[j].op2.op_type == IS_CONST + && ops[j].op2.u.constant.type == IS_STRING /* only for string hashes */ + && ops[i].result.u.var == ops[j].op1.u.var) { + return cons(i, cons(j, 0)); + } + return NULL; +} +/* }}} */ +#endif + #ifdef ZEND_ENGINE_2_1 /* we need these unless the apc optimizer is installed as op_array_handler */ /* {{{ apc_restore_opline_num */ @@ -1040,6 +1167,7 @@ } Pair** jumps; int i; + int k; int jump_array_size; if (!op_array->opcodes) { @@ -1059,6 +1187,7 @@ OPTIMIZE1(constant_resolve); #ifdef ZEND_ENGINE_2_1 OPTIMIZE1(class_constant_resolve); + OPTIMIZE1(array_merge); #endif OPTIMIZE1(needless_jmp); OPTIMIZE2(inc); @@ -1070,6 +1199,16 @@ OPTIMIZE2(needless_bool); } +#ifdef ZEND_ENGINE_2_1 + /* merge three (1+2) levels down */ + for (k = 0; k < 2 ; k++) { + for (i = 0; i < op_array->last; i++) { + Pair* p; + OPTIMIZE1(array_merge); + } + } +#endif + op_array->last = compress_ops(op_array, jumps); destroy_jump_array(jumps, jump_array_size); apc_do_pass_two(op_array);