/src/php-src/Zend/Optimizer/nop_removal.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | +----------------------------------------------------------------------+ |
3 | | | Zend OPcache | |
4 | | +----------------------------------------------------------------------+ |
5 | | | Copyright (c) The PHP Group | |
6 | | +----------------------------------------------------------------------+ |
7 | | | This source file is subject to version 3.01 of the PHP license, | |
8 | | | that is bundled with this package in the file LICENSE, and is | |
9 | | | available through the world-wide-web at the following url: | |
10 | | | https://www.php.net/license/3_01.txt | |
11 | | | If you did not receive a copy of the PHP license and are unable to | |
12 | | | obtain it through the world-wide-web, please send a note to | |
13 | | | license@php.net so we can mail you a copy immediately. | |
14 | | +----------------------------------------------------------------------+ |
15 | | | Authors: Andi Gutmans <andi@php.net> | |
16 | | | Zeev Suraski <zeev@php.net> | |
17 | | | Stanislav Malyshev <stas@zend.com> | |
18 | | | Dmitry Stogov <dmitry@php.net> | |
19 | | +----------------------------------------------------------------------+ |
20 | | */ |
21 | | |
22 | | /* pass 10: |
23 | | * - remove NOPs |
24 | | */ |
25 | | |
26 | | #include "Optimizer/zend_optimizer.h" |
27 | | #include "Optimizer/zend_optimizer_internal.h" |
28 | | #include "zend_API.h" |
29 | | #include "zend_constants.h" |
30 | | #include "zend_execute.h" |
31 | | #include "zend_vm.h" |
32 | | |
33 | | void zend_optimizer_nop_removal(zend_op_array *op_array, zend_optimizer_ctx *ctx) |
34 | 0 | { |
35 | 0 | zend_op *end, *opline; |
36 | 0 | uint32_t new_count, i, shift; |
37 | 0 | int j; |
38 | 0 | uint32_t *shiftlist; |
39 | 0 | ALLOCA_FLAG(use_heap); |
40 | |
|
41 | 0 | shiftlist = (uint32_t *)do_alloca(sizeof(uint32_t) * op_array->last, use_heap); |
42 | 0 | i = new_count = shift = 0; |
43 | 0 | end = op_array->opcodes + op_array->last; |
44 | 0 | for (opline = op_array->opcodes; opline < end; opline++) { |
45 | | |
46 | | /* Kill JMP-over-NOP-s */ |
47 | 0 | if (opline->opcode == ZEND_JMP && ZEND_OP1_JMP_ADDR(opline) > op_array->opcodes + i) { |
48 | | /* check if there are only NOPs under the branch */ |
49 | 0 | zend_op *target = ZEND_OP1_JMP_ADDR(opline) - 1; |
50 | |
|
51 | 0 | while (target->opcode == ZEND_NOP) { |
52 | 0 | target--; |
53 | 0 | } |
54 | 0 | if (target == opline) { |
55 | | /* only NOPs */ |
56 | 0 | opline->opcode = ZEND_NOP; |
57 | 0 | } |
58 | 0 | } |
59 | |
|
60 | 0 | shiftlist[i++] = shift; |
61 | 0 | if (opline->opcode == ZEND_NOP) { |
62 | 0 | shift++; |
63 | 0 | } else { |
64 | 0 | if (shift) { |
65 | 0 | zend_op *new_opline = op_array->opcodes + new_count; |
66 | |
|
67 | 0 | *new_opline = *opline; |
68 | 0 | zend_optimizer_migrate_jump(op_array, new_opline, opline); |
69 | 0 | } |
70 | 0 | new_count++; |
71 | 0 | } |
72 | 0 | } |
73 | |
|
74 | 0 | if (shift) { |
75 | 0 | op_array->last = new_count; |
76 | 0 | end = op_array->opcodes + op_array->last; |
77 | | |
78 | | /* update JMPs */ |
79 | 0 | for (opline = op_array->opcodes; opline<end; opline++) { |
80 | 0 | zend_optimizer_shift_jump(op_array, opline, shiftlist); |
81 | 0 | } |
82 | | |
83 | | /* update try/catch array */ |
84 | 0 | for (j = 0; j < op_array->last_try_catch; j++) { |
85 | 0 | op_array->try_catch_array[j].try_op -= shiftlist[op_array->try_catch_array[j].try_op]; |
86 | 0 | op_array->try_catch_array[j].catch_op -= shiftlist[op_array->try_catch_array[j].catch_op]; |
87 | 0 | if (op_array->try_catch_array[j].finally_op) { |
88 | 0 | op_array->try_catch_array[j].finally_op -= shiftlist[op_array->try_catch_array[j].finally_op]; |
89 | 0 | op_array->try_catch_array[j].finally_end -= shiftlist[op_array->try_catch_array[j].finally_end]; |
90 | 0 | } |
91 | 0 | } |
92 | 0 | } |
93 | 0 | free_alloca(shiftlist, use_heap); |
94 | 0 | } |