From: Dmitry Stogov Date: Tue, 30 Jul 2013 18:31:37 +0000 (+0400) Subject: Improved implementation of NOP removal pass from O(n^2) to O(n) (hnw) X-Git-Tag: php-5.5.2RC1~5 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cb17c9951182690b75f57cdf1707609a8478af6f;p=php Improved implementation of NOP removal pass from O(n^2) to O(n) (hnw) --- diff --git a/ext/opcache/Optimizer/block_pass.c b/ext/opcache/Optimizer/block_pass.c index b8c381406b..7f874e7a4b 100644 --- a/ext/opcache/Optimizer/block_pass.c +++ b/ext/opcache/Optimizer/block_pass.c @@ -558,6 +558,52 @@ static void zend_rebuild_access_path(zend_cfg *cfg, zend_op_array *op_array, int convert_to_string((v)); \ } +static void strip_nop(zend_code_block *block) +{ + zend_op *opline = block->start_opline; + zend_op *end, *new_end; + int new_len = 0; + + /* remove leading NOPs */ + while (block->len > 0 && block->start_opline->opcode == ZEND_NOP) { + if (block->len == 1) { + /* this block is all NOPs, join with following block */ + if (block->follow_to) { + delete_code_block(block); + } + return; + } + block->start_opline++; + block->start_opline_no++; + block->len--; + } + + /* strip the inside NOPs */ + opline = new_end = block->start_opline; + end = opline + block->len; + + while (opline < end) { + zend_op *src; + int len = 0; + + while (opline < end && opline->opcode == ZEND_NOP) { + opline++; + } + src = opline; + + while (opline < end && opline->opcode != ZEND_NOP) { + opline++; + } + len = opline - src; + + /* move up non-NOP opcodes */ + memmove(new_end, src, len*sizeof(zend_op)); + + new_end += len; + } + block->len = new_end - block->start_opline; +} + static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, char *used_ext TSRMLS_DC) { zend_op *opline = block->start_opline; @@ -1168,45 +1214,7 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, opline++; } - /* remove leading NOPs */ - while (block->len > 0 && block->start_opline->opcode == ZEND_NOP) { - if (block->len == 1) { - /* this block is all NOPs, join with following block */ - if (block->follow_to) { - delete_code_block(block); - } - if (op_array->T) { - efree(Tsource); - } - return; - } - block->start_opline++; - block->start_opline_no++; - block->len--; - } - - /* strip the inside NOPs */ - opline = block->start_opline; - end = opline + block->len; - while (opline < end) { - if (opline->opcode == ZEND_NOP) { - zend_op *nop = opline + 1; - int noplen; - while (nop < end && nop->opcode == ZEND_NOP) { - nop++; - } - noplen = nop-opline; - if (nop < end) { - /* move up non-NOP opcodes */ - memmove(opline, nop, (end-nop)*sizeof(zend_op)); - } else { - /* all NOPs up to the end, do nothing */ - } - block->len -= noplen; - end = block->start_opline + block->len; - } - opline++; - } + strip_nop(block); if (op_array->T) { efree(Tsource);