diff options
| author | Nikita Popov <nikita.ppv@gmail.com> | 2018-02-16 21:25:49 +0100 |
|---|---|---|
| committer | Nikita Popov <nikita.ppv@gmail.com> | 2018-02-16 21:30:48 +0100 |
| commit | b0af9ac7331e3efa0dcee4f43b2ba8b1e4e52f2f (patch) | |
| tree | 5b40edba9eee94ab22fe494ce0c919b3ffdfebe4 /ext/opcache | |
| parent | 07ad75ca9603b8b0195ddcd90229ae9dbe650900 (diff) | |
| download | php-git-b0af9ac7331e3efa0dcee4f43b2ba8b1e4e52f2f.tar.gz | |
Avoid live range references in opcodes
Don't store the live range of the freed variable for FREE_ON_RETURN
frees, instead look it up at runtime. As this is an extremely
unlikely codepath (in particular, it requires a loop variable with
a throwing destructor), saving the runtime lookup of the live range
is not worth the extra complexity this adds everywhere else.
Diffstat (limited to 'ext/opcache')
| -rw-r--r-- | ext/opcache/Optimizer/block_pass.c | 24 | ||||
| -rw-r--r-- | ext/opcache/Optimizer/zend_dump.c | 4 | ||||
| -rw-r--r-- | ext/opcache/Optimizer/zend_optimizer.c | 20 |
3 files changed, 4 insertions, 44 deletions
diff --git a/ext/opcache/Optimizer/block_pass.c b/ext/opcache/Optimizer/block_pass.c index 97e44fe0b2..b402cce276 100644 --- a/ext/opcache/Optimizer/block_pass.c +++ b/ext/opcache/Optimizer/block_pass.c @@ -347,10 +347,6 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array src->opcode != ZEND_FETCH_DIM_R && src->opcode != ZEND_FETCH_OBJ_R && src->opcode != ZEND_NEW) { - if (opline->extended_value & ZEND_FREE_ON_RETURN) { - /* mark as removed (empty live range) */ - op_array->live_range[opline->op2.num].var = (uint32_t)-1; - } src->result_type = IS_UNUSED; MAKE_NOP(opline); } @@ -1040,10 +1036,6 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array, zend_op /* adjust loop jump targets & remove unused live range entries */ if (op_array->last_live_range) { int i, j; - uint32_t *map; - ALLOCA_FLAG(use_heap); - - map = (uint32_t *)do_alloca(sizeof(uint32_t) * op_array->last_live_range, use_heap); for (i = 0, j = 0; i < op_array->last_live_range; i++) { if (op_array->live_range[i].var == (uint32_t)-1) { @@ -1062,7 +1054,6 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array, zend_op } op_array->live_range[i].start = start_op; op_array->live_range[i].end = end_op; - map[i] = j; if (i != j) { op_array->live_range[j] = op_array->live_range[i]; } @@ -1071,23 +1062,12 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array, zend_op } if (i != j) { - if ((op_array->last_live_range = j)) { - zend_op *opline = new_opcodes; - zend_op *end = opline + len; - while (opline != end) { - if ((opline->opcode == ZEND_FREE || opline->opcode == ZEND_FE_FREE) && - opline->extended_value == ZEND_FREE_ON_RETURN) { - ZEND_ASSERT(opline->op2.num < (uint32_t) i); - opline->op2.num = map[opline->op2.num]; - } - opline++; - } - } else { + op_array->last_live_range = j; + if (j == 0) { efree(op_array->live_range); op_array->live_range = NULL; } } - free_alloca(map, use_heap); } /* adjust early binding list */ diff --git a/ext/opcache/Optimizer/zend_dump.c b/ext/opcache/Optimizer/zend_dump.c index 7fb55355fd..e4516b59cc 100644 --- a/ext/opcache/Optimizer/zend_dump.c +++ b/ext/opcache/Optimizer/zend_dump.c @@ -118,10 +118,6 @@ static void zend_dump_unused_op(const zend_op *opline, znode_op op, uint32_t fla if (op.num != (uint32_t)-1) { fprintf(stderr, " try-catch(%u)", op.num); } - } else if (ZEND_VM_OP_LIVE_RANGE == (flags & ZEND_VM_OP_MASK)) { - if (opline->extended_value & ZEND_FREE_ON_RETURN) { - fprintf(stderr, " live-range(%u)", op.num); - } } else if (ZEND_VM_OP_THIS == (flags & ZEND_VM_OP_MASK)) { fprintf(stderr, " THIS"); } else if (ZEND_VM_OP_NEXT == (flags & ZEND_VM_OP_MASK)) { diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c index 07860f3998..ffc04854e2 100644 --- a/ext/opcache/Optimizer/zend_optimizer.c +++ b/ext/opcache/Optimizer/zend_optimizer.c @@ -566,14 +566,9 @@ void zend_optimizer_remove_live_range(zend_op_array *op_array, uint32_t var) if (op_array->last_live_range) { int i = 0; int j = 0; - uint32_t *map; - ALLOCA_FLAG(use_heap); - - map = (uint32_t *)do_alloca(sizeof(uint32_t) * op_array->last_live_range, use_heap); do { if ((op_array->live_range[i].var & ~ZEND_LIVE_MASK) != var) { - map[i] = j; if (i != j) { op_array->live_range[j] = op_array->live_range[i]; } @@ -582,23 +577,12 @@ void zend_optimizer_remove_live_range(zend_op_array *op_array, uint32_t var) i++; } while (i < op_array->last_live_range); if (i != j) { - if ((op_array->last_live_range = j)) { - zend_op *opline = op_array->opcodes; - zend_op *end = opline + op_array->last; - - while (opline != end) { - if ((opline->opcode == ZEND_FREE || opline->opcode == ZEND_FE_FREE) && - opline->extended_value == ZEND_FREE_ON_RETURN) { - opline->op2.num = map[opline->op2.num]; - } - opline++; - } - } else { + op_array->last_live_range = j; + if (j == 0) { efree(op_array->live_range); op_array->live_range = NULL; } } - free_alloca(map, use_heap); } } |
