summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2018-02-16 21:47:00 +0100
committerNikita Popov <nikita.ppv@gmail.com>2018-02-16 21:51:50 +0100
commit7ff186434e82ee7be7c59d0db9a976641cf7b09c (patch)
tree7f859f4d55c3ef08114c993f5c1027d6997c9dd8
parentb0af9ac7331e3efa0dcee4f43b2ba8b1e4e52f2f (diff)
downloadphp-git-7ff186434e82ee7be7c59d0db9a976641cf7b09c.tar.gz
Explicitly sort live ranges by start opnum
Instead of moving live ranges around to maintain the start opnum invariant, add an explicit sorting step in pass two.
-rw-r--r--Zend/zend_compile.c48
-rw-r--r--Zend/zend_opcode.c16
2 files changed, 18 insertions, 46 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 1190cef1b4..9ce33737af 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -605,50 +605,6 @@ static uint32_t zend_start_live_range(zend_op_array *op_array, uint32_t start) /
}
/* }}} */
-static uint32_t zend_start_live_range_ex(zend_op_array *op_array, uint32_t start) /* {{{ */
-{
- if (op_array->last_live_range == 0 ||
- op_array->live_range[op_array->last_live_range - 1].start <= start) {
- return zend_start_live_range(op_array, start);
- } else {
- /* Live ranges have to be sorted by "start" field */
- uint32_t n = op_array->last_live_range;
-
- /* move early ranges to make a room */
- op_array->last_live_range = n + 1;
- op_array->live_range = erealloc(op_array->live_range, sizeof(zend_live_range) * op_array->last_live_range);
- do {
- op_array->live_range[n] = op_array->live_range[n-1];
- n--;
- } while (n != 0 && op_array->live_range[n-1].start > start);
-
- /* initialize new range */
- op_array->live_range[n].start = start;
-
- /* update referens to live-ranges from stack */
- if (!zend_stack_is_empty(&CG(loop_var_stack))) {
- zend_loop_var *loop_var = zend_stack_top(&CG(loop_var_stack));
- zend_loop_var *base = zend_stack_base(&CG(loop_var_stack));
-
- for (; loop_var >= base; loop_var--) {
- if (loop_var->opcode == ZEND_RETURN) {
- /* Stack separator */
- break;
- } else if (loop_var->opcode == ZEND_FREE ||
- loop_var->opcode == ZEND_FE_FREE) {
- if (loop_var->u.live_range_offset >= n) {
- loop_var->u.live_range_offset++;
- } else {
- break;
- }
- }
- }
- }
- return n;
- }
-}
-/* }}} */
-
static void zend_end_live_range(zend_op_array *op_array, uint32_t offset, uint32_t end, uint32_t kind, uint32_t var) /* {{{ */
{
zend_live_range *range = op_array->live_range + offset;
@@ -2041,7 +1997,7 @@ static void zend_find_live_range(zend_op *opline, zend_uchar type, uint32_t var)
}
zend_end_live_range(CG(active_op_array),
- zend_start_live_range_ex(CG(active_op_array),
+ zend_start_live_range(CG(active_op_array),
def + 1 - CG(active_op_array)->opcodes),
opline - CG(active_op_array)->opcodes,
ZEND_LIVE_TMPVAR, var);
@@ -7944,7 +7900,7 @@ static void zend_compile_encaps_list(znode *result, zend_ast *ast) /* {{{ */
GET_NODE(result, opline->result);
} else {
uint32_t var;
- uint32_t range = zend_start_live_range_ex(CG(active_op_array), rope_init_lineno);
+ uint32_t range = zend_start_live_range(CG(active_op_array), rope_init_lineno);
init_opline->extended_value = j;
opline->opcode = ZEND_ROPE_END;
diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c
index 48f1e4785c..11194bc51c 100644
--- a/Zend/zend_opcode.c
+++ b/Zend/zend_opcode.c
@@ -27,6 +27,7 @@
#include "zend_compile.h"
#include "zend_extensions.h"
#include "zend_API.h"
+#include "zend_sort.h"
#include "zend_vm.h"
@@ -553,6 +554,20 @@ static uint32_t zend_get_brk_cont_target(const zend_op_array *op_array, const ze
return opline->opcode == ZEND_BRK ? jmp_to->brk : jmp_to->cont;
}
+/* Live ranges must be sorted by increasing start opline */
+static int cmp_live_range(const zend_live_range *a, const zend_live_range *b) {
+ return a->start - b->start;
+}
+static void swap_live_range(zend_live_range *a, zend_live_range *b) {
+ zend_live_range tmp = *a;
+ *a = *b;
+ *b = tmp;
+}
+static void zend_sort_live_ranges(zend_op_array *op_array) {
+ zend_sort(op_array->live_range, op_array->last_live_range, sizeof(zend_live_range),
+ (compare_func_t) cmp_live_range, (swap_func_t) swap_live_range);
+}
+
ZEND_API int pass_two(zend_op_array *op_array)
{
zend_op *opline, *end;
@@ -707,6 +722,7 @@ ZEND_API int pass_two(zend_op_array *op_array)
if (op_array->live_range) {
int i;
+ zend_sort_live_ranges(op_array);
for (i = 0; i < op_array->last_live_range; i++) {
op_array->live_range[i].var =
(uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + (op_array->live_range[i].var / sizeof(zval))) |