Created
April 14, 2017 10:21
-
-
Save krakjoe/9213861ffb2a9950a5abbceb2b8543cf to your computer and use it in GitHub Desktop.
7.1.0 ... 7.1.4 ext/opcache
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/ext/opcache/Optimizer/block_pass.c b/ext/opcache/Optimizer/block_pass.c | |
index 77b02cc99f..38c2ecb124 100644 | |
--- a/ext/opcache/Optimizer/block_pass.c | |
+++ b/ext/opcache/Optimizer/block_pass.c | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend OPcache | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
@@ -157,17 +157,23 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array | |
src = VAR_SOURCE(opline->op1); | |
if (src && | |
src->opcode == ZEND_QM_ASSIGN && | |
- src->op1_type == IS_CONST) { | |
- | |
+ src->op1_type == IS_CONST | |
+ ) { | |
znode_op op1 = opline->op1; | |
- zval c = ZEND_OP1_LITERAL(src); | |
- | |
- zval_copy_ctor(&c); | |
- if (zend_optimizer_update_op1_const(op_array, opline, &c)) { | |
- zend_optimizer_remove_live_range(op_array, op1.var); | |
+ if (opline->opcode == ZEND_VERIFY_RETURN_TYPE) { | |
+ COPY_NODE(opline->result, opline->op1); | |
+ COPY_NODE(opline->op1, src->op1); | |
VAR_SOURCE(op1) = NULL; | |
- literal_dtor(&ZEND_OP1_LITERAL(src)); | |
MAKE_NOP(src); | |
+ } else { | |
+ zval c = ZEND_OP1_LITERAL(src); | |
+ zval_copy_ctor(&c); | |
+ if (zend_optimizer_update_op1_const(op_array, opline, &c)) { | |
+ zend_optimizer_remove_live_range(op_array, op1.var); | |
+ VAR_SOURCE(op1) = NULL; | |
+ literal_dtor(&ZEND_OP1_LITERAL(src)); | |
+ MAKE_NOP(src); | |
+ } | |
} | |
} | |
} | |
@@ -1788,6 +1794,11 @@ void zend_optimize_cfg(zend_op_array *op_array, zend_optimizer_ctx *ctx) | |
return; | |
} | |
+ if (cfg.blocks_count * (op_array->last_var + op_array->T) > 64 * 1024 * 1024) { | |
+ zend_arena_release(&ctx->arena, checkpoint); | |
+ return; | |
+ } | |
+ | |
if (ctx->debug_level & ZEND_DUMP_BEFORE_BLOCK_PASS) { | |
zend_dump_op_array(op_array, ZEND_DUMP_CFG, "before block pass", &cfg); | |
} | |
diff --git a/ext/opcache/Optimizer/compact_literals.c b/ext/opcache/Optimizer/compact_literals.c | |
index 445b579f59..6d549220ab 100644 | |
--- a/ext/opcache/Optimizer/compact_literals.c | |
+++ b/ext/opcache/Optimizer/compact_literals.c | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend OPcache | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
@@ -292,7 +292,7 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx | |
case ZEND_DECLARE_CLASS: | |
case ZEND_DECLARE_INHERITED_CLASS: | |
case ZEND_DECLARE_INHERITED_CLASS_DELAYED: | |
- LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 1, 0, 2); | |
+ LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 0, 0, 2); | |
break; | |
case ZEND_RECV: | |
case ZEND_RECV_VARIADIC: | |
diff --git a/ext/opcache/Optimizer/dfa_pass.c b/ext/opcache/Optimizer/dfa_pass.c | |
index b7a0f065f7..55915e70a9 100644 | |
--- a/ext/opcache/Optimizer/dfa_pass.c | |
+++ b/ext/opcache/Optimizer/dfa_pass.c | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend OPcache | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
@@ -356,6 +356,12 @@ static zend_bool opline_supports_assign_contraction( | |
return opline->op1_type != IS_CV || opline->op1.var != cv_var; | |
} | |
+ if (opline->opcode == ZEND_INIT_ARRAY) { | |
+ /* INIT_ARRAY initializes the result array before reading key/value. */ | |
+ return (opline->op1_type != IS_CV || opline->op1.var != cv_var) | |
+ && (opline->op2_type != IS_CV || opline->op2.var != cv_var); | |
+ } | |
+ | |
return 1; | |
} | |
@@ -569,19 +575,23 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx | |
// op_1: VERIFY_RETURN_TYPE #orig_var.CV [T] -> #v.CV [T] => NOP | |
int orig_var = ssa->ops[op_1].op1_use; | |
- int ret = ssa->vars[v].use_chain; | |
+ if (zend_ssa_unlink_use_chain(ssa, op_1, orig_var)) { | |
- ssa->vars[orig_var].use_chain = ret; | |
- ssa->ops[ret].op1_use = orig_var; | |
+ int ret = ssa->vars[v].use_chain; | |
- ssa->vars[v].definition = -1; | |
- ssa->vars[v].use_chain = -1; | |
+ ssa->ops[ret].op1_use = orig_var; | |
+ ssa->ops[ret].op1_use_chain = ssa->vars[orig_var].use_chain; | |
+ ssa->vars[orig_var].use_chain = ret; | |
- ssa->ops[op_1].op1_def = -1; | |
- ssa->ops[op_1].op1_use = -1; | |
+ ssa->vars[v].definition = -1; | |
+ ssa->vars[v].use_chain = -1; | |
- MAKE_NOP(opline); | |
- remove_nops = 1; | |
+ ssa->ops[op_1].op1_def = -1; | |
+ ssa->ops[op_1].op1_use = -1; | |
+ | |
+ MAKE_NOP(opline); | |
+ remove_nops = 1; | |
+ } | |
} else if (ssa->ops[op_1].op1_def == v | |
&& !RETURN_VALUE_USED(opline) | |
diff --git a/ext/opcache/Optimizer/nop_removal.c b/ext/opcache/Optimizer/nop_removal.c | |
index 3ebbdad8cf..c7ff73a61b 100644 | |
--- a/ext/opcache/Optimizer/nop_removal.c | |
+++ b/ext/opcache/Optimizer/nop_removal.c | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend OPcache | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
diff --git a/ext/opcache/Optimizer/optimize_func_calls.c b/ext/opcache/Optimizer/optimize_func_calls.c | |
index 3480a9a6ee..5d477c1a73 100644 | |
--- a/ext/opcache/Optimizer/optimize_func_calls.c | |
+++ b/ext/opcache/Optimizer/optimize_func_calls.c | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend OPcache | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
diff --git a/ext/opcache/Optimizer/optimize_temp_vars_5.c b/ext/opcache/Optimizer/optimize_temp_vars_5.c | |
index f0e5747dc6..08ab915e92 100644 | |
--- a/ext/opcache/Optimizer/optimize_temp_vars_5.c | |
+++ b/ext/opcache/Optimizer/optimize_temp_vars_5.c | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend OPcache | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
diff --git a/ext/opcache/Optimizer/pass1_5.c b/ext/opcache/Optimizer/pass1_5.c | |
index e8399ccc90..ee883f447a 100644 | |
--- a/ext/opcache/Optimizer/pass1_5.c | |
+++ b/ext/opcache/Optimizer/pass1_5.c | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend OPcache | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
diff --git a/ext/opcache/Optimizer/pass2.c b/ext/opcache/Optimizer/pass2.c | |
index c24d87a4ad..41ab7c6045 100644 | |
--- a/ext/opcache/Optimizer/pass2.c | |
+++ b/ext/opcache/Optimizer/pass2.c | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend OPcache | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
diff --git a/ext/opcache/Optimizer/pass3.c b/ext/opcache/Optimizer/pass3.c | |
index ce04e4f7cb..e5d032cd29 100644 | |
--- a/ext/opcache/Optimizer/pass3.c | |
+++ b/ext/opcache/Optimizer/pass3.c | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend OPcache | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
diff --git a/ext/opcache/Optimizer/zend_call_graph.c b/ext/opcache/Optimizer/zend_call_graph.c | |
index e892c35672..5800a220bc 100644 | |
--- a/ext/opcache/Optimizer/zend_call_graph.c | |
+++ b/ext/opcache/Optimizer/zend_call_graph.c | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend Engine, Call Graph | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
@@ -266,6 +266,29 @@ int zend_build_call_graph(zend_arena **arena, zend_script *script, uint32_t buil | |
} | |
/* }}} */ | |
+zend_call_info **zend_build_call_map(zend_arena **arena, zend_func_info *info, zend_op_array *op_array) /* {{{ */ | |
+{ | |
+ zend_call_info **map, *call; | |
+ if (!info->callee_info) { | |
+ /* Don't build call map if function contains no calls */ | |
+ return NULL; | |
+ } | |
+ | |
+ map = zend_arena_calloc(arena, sizeof(zend_call_info *), op_array->last); | |
+ for (call = info->callee_info; call; call = call->next_callee) { | |
+ int i; | |
+ map[call->caller_init_opline - op_array->opcodes] = call; | |
+ map[call->caller_call_opline - op_array->opcodes] = call; | |
+ for (i = 0; i < call->num_args; i++) { | |
+ if (call->arg_info[i].opline) { | |
+ map[call->arg_info[i].opline - op_array->opcodes] = call; | |
+ } | |
+ } | |
+ } | |
+ return map; | |
+} | |
+/* }}} */ | |
+ | |
/* | |
* Local variables: | |
* tab-width: 4 | |
diff --git a/ext/opcache/Optimizer/zend_call_graph.h b/ext/opcache/Optimizer/zend_call_graph.h | |
index a5f47f12f0..49c7217c40 100644 | |
--- a/ext/opcache/Optimizer/zend_call_graph.h | |
+++ b/ext/opcache/Optimizer/zend_call_graph.h | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend Engine, Call Graph | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
@@ -51,6 +51,7 @@ struct _zend_func_info { | |
zend_ssa ssa; /* Static Single Assignmnt Form */ | |
zend_call_info *caller_info; /* where this function is called from */ | |
zend_call_info *callee_info; /* which functions are called from this one */ | |
+ zend_call_info **call_map; /* Call info associated with init/call/send opnum */ | |
int num_args; /* (-1 - unknown) */ | |
zend_recv_arg_info *arg_info; | |
zend_ssa_var_info return_info; | |
@@ -69,6 +70,7 @@ typedef struct _zend_call_graph { | |
BEGIN_EXTERN_C() | |
int zend_build_call_graph(zend_arena **arena, zend_script *script, uint32_t build_flags, zend_call_graph *call_graph); | |
+zend_call_info **zend_build_call_map(zend_arena **arena, zend_func_info *info, zend_op_array *op_array); | |
int zend_analyze_calls(zend_arena **arena, zend_script *script, uint32_t build_flags, zend_op_array *op_array, zend_func_info *func_info); | |
END_EXTERN_C() | |
diff --git a/ext/opcache/Optimizer/zend_cfg.c b/ext/opcache/Optimizer/zend_cfg.c | |
index f39f9650ae..2163d7c3a2 100644 | |
--- a/ext/opcache/Optimizer/zend_cfg.c | |
+++ b/ext/opcache/Optimizer/zend_cfg.c | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend Engine, CFG - Control Flow Graph | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
@@ -135,12 +135,11 @@ static void zend_mark_reachable_blocks(const zend_op_array *op_array, zend_cfg * | |
b->flags |= ZEND_BB_GEN_VAR; | |
b = blocks + block_map[live_range->end]; | |
b->flags |= ZEND_BB_KILL_VAR; | |
- if (!(b->flags & ZEND_BB_REACHABLE)) { | |
+ if (!(b->flags & (ZEND_BB_REACHABLE|ZEND_BB_UNREACHABLE_FREE))) { | |
if (cfg->split_at_live_ranges) { | |
changed = 1; | |
zend_mark_reachable(op_array->opcodes, cfg, b); | |
} else { | |
- ZEND_ASSERT(!(b->flags & ZEND_BB_UNREACHABLE_FREE)); | |
ZEND_ASSERT(b->start == live_range->end); | |
b->flags |= ZEND_BB_UNREACHABLE_FREE; | |
} | |
@@ -750,31 +749,51 @@ static int dominates(zend_basic_block *blocks, int a, int b) /* {{{ */ | |
} | |
/* }}} */ | |
+typedef struct { | |
+ int id; | |
+ int level; | |
+} block_info; | |
+static int compare_block_level(const block_info *a, const block_info *b) { | |
+ return b->level - a->level; | |
+} | |
+static void swap_blocks(block_info *a, block_info *b) { | |
+ block_info tmp = *a; | |
+ *a = *b; | |
+ *b = tmp; | |
+} | |
+ | |
int zend_cfg_identify_loops(const zend_op_array *op_array, zend_cfg *cfg, uint32_t *flags) /* {{{ */ | |
{ | |
- int i, j, k; | |
- int depth; | |
+ int i, j, k, n; | |
+ int depth, time; | |
zend_basic_block *blocks = cfg->blocks; | |
- int *dj_spanning_tree; | |
+ int *entry_times, *exit_times; | |
zend_worklist work; | |
int flag = ZEND_FUNC_NO_LOOPS; | |
+ block_info *sorted_blocks; | |
ALLOCA_FLAG(list_use_heap) | |
ALLOCA_FLAG(tree_use_heap) | |
+ ALLOCA_FLAG(sorted_blocks_use_heap) | |
ZEND_WORKLIST_ALLOCA(&work, cfg->blocks_count, list_use_heap); | |
- dj_spanning_tree = do_alloca(sizeof(int) * cfg->blocks_count, tree_use_heap); | |
- for (i = 0; i < cfg->blocks_count; i++) { | |
- dj_spanning_tree[i] = -1; | |
- } | |
+ /* We don't materialize the DJ spanning tree explicitly, as we are only interested in ancestor | |
+ * queries. These are implemented by checking entry/exit times of the DFS search. */ | |
+ entry_times = do_alloca(2 * sizeof(int) * cfg->blocks_count, tree_use_heap); | |
+ exit_times = entry_times + cfg->blocks_count; | |
+ memset(entry_times, -1, 2 * sizeof(int) * cfg->blocks_count); | |
+ | |
zend_worklist_push(&work, 0); | |
+ time = 0; | |
while (zend_worklist_len(&work)) { | |
next: | |
i = zend_worklist_peek(&work); | |
+ if (entry_times[i] == -1) { | |
+ entry_times[i] = time++; | |
+ } | |
/* Visit blocks immediately dominated by i. */ | |
for (j = blocks[i].children; j >= 0; j = blocks[j].next_child) { | |
if (zend_worklist_push(&work, j)) { | |
- dj_spanning_tree[j] = i; | |
goto next; | |
} | |
} | |
@@ -786,72 +805,67 @@ int zend_cfg_identify_loops(const zend_op_array *op_array, zend_cfg *cfg, uint32 | |
} else if (blocks[succ].idom == i) { | |
continue; | |
} else if (zend_worklist_push(&work, succ)) { | |
- dj_spanning_tree[succ] = i; | |
goto next; | |
} | |
} | |
+ exit_times[i] = time++; | |
zend_worklist_pop(&work); | |
} | |
+ /* Sort blocks by decreasing level, which is the order in which we want to process them */ | |
+ sorted_blocks = do_alloca(sizeof(block_info) * cfg->blocks_count, sorted_blocks_use_heap); | |
+ for (i = 0; i < cfg->blocks_count; i++) { | |
+ sorted_blocks[i].id = i; | |
+ sorted_blocks[i].level = blocks[i].level; | |
+ } | |
+ zend_sort(sorted_blocks, cfg->blocks_count, sizeof(block_info), | |
+ (compare_func_t) compare_block_level, (swap_func_t) swap_blocks); | |
+ | |
/* Identify loops. See Sreedhar et al, "Identifying Loops Using DJ | |
Graphs". */ | |
- for (i = 0, depth = 0; i < cfg->blocks_count; i++) { | |
- if (blocks[i].level > depth) { | |
- depth = blocks[i].level; | |
- } | |
- } | |
- for (; depth >= 0; depth--) { | |
- for (i = 0; i < cfg->blocks_count; i++) { | |
- if (blocks[i].level != depth) { | |
+ for (n = 0; n < cfg->blocks_count; n++) { | |
+ i = sorted_blocks[n].id; | |
+ | |
+ zend_bitset_clear(work.visited, zend_bitset_len(cfg->blocks_count)); | |
+ for (j = 0; j < blocks[i].predecessors_count; j++) { | |
+ int pred = cfg->predecessors[blocks[i].predecessor_offset + j]; | |
+ | |
+ /* A join edge is one for which the predecessor does not | |
+ immediately dominate the successor. */ | |
+ if (blocks[i].idom == pred) { | |
continue; | |
} | |
- zend_bitset_clear(work.visited, zend_bitset_len(cfg->blocks_count)); | |
- for (j = 0; j < blocks[i].predecessors_count; j++) { | |
- int pred = cfg->predecessors[blocks[i].predecessor_offset + j]; | |
- /* A join edge is one for which the predecessor does not | |
- immediately dominate the successor. */ | |
- if (blocks[i].idom == pred) { | |
- continue; | |
- } | |
- | |
- /* In a loop back-edge (back-join edge), the successor dominates | |
- the predecessor. */ | |
- if (dominates(blocks, i, pred)) { | |
- blocks[i].flags |= ZEND_BB_LOOP_HEADER; | |
+ /* In a loop back-edge (back-join edge), the successor dominates | |
+ the predecessor. */ | |
+ if (dominates(blocks, i, pred)) { | |
+ blocks[i].flags |= ZEND_BB_LOOP_HEADER; | |
+ flag &= ~ZEND_FUNC_NO_LOOPS; | |
+ zend_worklist_push(&work, pred); | |
+ } else { | |
+ /* Otherwise it's a cross-join edge. See if it's a branch | |
+ to an ancestor on the DJ spanning tree. */ | |
+ if (entry_times[pred] > entry_times[i] && exit_times[pred] < exit_times[i]) { | |
+ blocks[i].flags |= ZEND_BB_IRREDUCIBLE_LOOP; | |
+ flag |= ZEND_FUNC_IRREDUCIBLE; | |
flag &= ~ZEND_FUNC_NO_LOOPS; | |
- zend_worklist_push(&work, pred); | |
- } else { | |
- /* Otherwise it's a cross-join edge. See if it's a branch | |
- to an ancestor on the dominator spanning tree. */ | |
- int dj_parent = pred; | |
- while (dj_parent >= 0) { | |
- if (dj_parent == i) { | |
- /* An sp-back edge: mark as irreducible. */ | |
- blocks[i].flags |= ZEND_BB_IRREDUCIBLE_LOOP; | |
- flag |= ZEND_FUNC_IRREDUCIBLE; | |
- flag &= ~ZEND_FUNC_NO_LOOPS; | |
- break; | |
- } else { | |
- dj_parent = dj_spanning_tree[dj_parent]; | |
- } | |
- } | |
} | |
} | |
- while (zend_worklist_len(&work)) { | |
- j = zend_worklist_pop(&work); | |
- if (blocks[j].loop_header < 0 && j != i) { | |
- blocks[j].loop_header = i; | |
- for (k = 0; k < blocks[j].predecessors_count; k++) { | |
- zend_worklist_push(&work, cfg->predecessors[blocks[j].predecessor_offset + k]); | |
- } | |
+ } | |
+ while (zend_worklist_len(&work)) { | |
+ j = zend_worklist_pop(&work); | |
+ if (blocks[j].loop_header < 0 && j != i) { | |
+ blocks[j].loop_header = i; | |
+ for (k = 0; k < blocks[j].predecessors_count; k++) { | |
+ zend_worklist_push(&work, cfg->predecessors[blocks[j].predecessor_offset + k]); | |
} | |
} | |
} | |
} | |
- free_alloca(dj_spanning_tree, tree_use_heap); | |
+ free_alloca(sorted_blocks, sorted_blocks_use_heap); | |
+ free_alloca(entry_times, tree_use_heap); | |
ZEND_WORKLIST_FREE_ALLOCA(&work, list_use_heap); | |
*flags |= flag; | |
diff --git a/ext/opcache/Optimizer/zend_cfg.h b/ext/opcache/Optimizer/zend_cfg.h | |
index 4f570b7fd6..7b80d83f11 100644 | |
--- a/ext/opcache/Optimizer/zend_cfg.h | |
+++ b/ext/opcache/Optimizer/zend_cfg.h | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend Engine, CFG - Control Flow Graph | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
diff --git a/ext/opcache/Optimizer/zend_dfg.c b/ext/opcache/Optimizer/zend_dfg.c | |
index 6c52d6eb58..374c8146c8 100644 | |
--- a/ext/opcache/Optimizer/zend_dfg.c | |
+++ b/ext/opcache/Optimizer/zend_dfg.c | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend Engine, DFG - Data Flow Graph | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
diff --git a/ext/opcache/Optimizer/zend_dfg.h b/ext/opcache/Optimizer/zend_dfg.h | |
index 5ed8cfc5d0..06ee46be32 100644 | |
--- a/ext/opcache/Optimizer/zend_dfg.h | |
+++ b/ext/opcache/Optimizer/zend_dfg.h | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend Engine, DFG - Data Flow Graph | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
diff --git a/ext/opcache/Optimizer/zend_dump.c b/ext/opcache/Optimizer/zend_dump.c | |
index cd07309df8..2167fa6e6b 100644 | |
--- a/ext/opcache/Optimizer/zend_dump.c | |
+++ b/ext/opcache/Optimizer/zend_dump.c | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend Engine, Bytecode Visualisation | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
diff --git a/ext/opcache/Optimizer/zend_dump.h b/ext/opcache/Optimizer/zend_dump.h | |
index 38b955c3a1..11646d9a82 100644 | |
--- a/ext/opcache/Optimizer/zend_dump.h | |
+++ b/ext/opcache/Optimizer/zend_dump.h | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend Engine, Bytecode Visualisation | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
diff --git a/ext/opcache/Optimizer/zend_func_info.c b/ext/opcache/Optimizer/zend_func_info.c | |
index 60954e0c19..7a1e65f625 100644 | |
--- a/ext/opcache/Optimizer/zend_func_info.c | |
+++ b/ext/opcache/Optimizer/zend_func_info.c | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend Engine, Func Info | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
diff --git a/ext/opcache/Optimizer/zend_func_info.h b/ext/opcache/Optimizer/zend_func_info.h | |
index 13fae8ff0b..a126bef708 100644 | |
--- a/ext/opcache/Optimizer/zend_func_info.h | |
+++ b/ext/opcache/Optimizer/zend_func_info.h | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend Engine, Func Info | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
diff --git a/ext/opcache/Optimizer/zend_inference.c b/ext/opcache/Optimizer/zend_inference.c | |
index d0e5d84e89..f572616567 100644 | |
--- a/ext/opcache/Optimizer/zend_inference.c | |
+++ b/ext/opcache/Optimizer/zend_inference.c | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend Engine, e-SSA based Type & Range Inference | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
@@ -58,6 +58,20 @@ | |
#define LOG_NEG_RANGE(...) | |
#endif | |
+/* Pop elements in unspecified order from worklist until it is empty */ | |
+#define WHILE_WORKLIST(worklist, len, i) do { \ | |
+ zend_bool _done = 0; \ | |
+ while (!_done) { \ | |
+ _done = 1; \ | |
+ ZEND_BITSET_FOREACH(worklist, len, i) { \ | |
+ zend_bitset_excl(worklist, i); \ | |
+ _done = 0; | |
+ | |
+#define WHILE_WORKLIST_END() \ | |
+ } ZEND_BITSET_FOREACH_END(); \ | |
+ } \ | |
+} while (0) | |
+ | |
#define CHECK_SCC_VAR(var2) \ | |
do { \ | |
if (!ssa->vars[var2].no_val) { \ | |
@@ -269,9 +283,7 @@ int zend_ssa_find_false_dependencies(const zend_op_array *op_array, zend_ssa *ss | |
} | |
} | |
- while (!zend_bitset_empty(worklist, zend_bitset_len(ssa_vars_count))) { | |
- i = zend_bitset_first(worklist, zend_bitset_len(ssa_vars_count)); | |
- zend_bitset_excl(worklist, i); | |
+ WHILE_WORKLIST(worklist, zend_bitset_len(ssa_vars_count), i) { | |
if (ssa_vars[i].definition_phi) { | |
/* mark all possible sources as used */ | |
p = ssa_vars[i].definition_phi; | |
@@ -289,7 +301,7 @@ int zend_ssa_find_false_dependencies(const zend_op_array *op_array, zend_ssa *ss | |
} | |
} | |
} | |
- } | |
+ } WHILE_WORKLIST_END(); | |
free_alloca(worklist, use_heap); | |
@@ -500,11 +512,266 @@ static void zend_ssa_range_and(zend_long a, zend_long b, zend_long c, zend_long | |
} | |
} | |
+/* Get the normal op corresponding to a compound assignment op */ | |
+static inline zend_uchar get_compound_assign_op(zend_uchar opcode) { | |
+ switch (opcode) { | |
+ case ZEND_ASSIGN_ADD: return ZEND_ADD; | |
+ case ZEND_ASSIGN_SUB: return ZEND_SUB; | |
+ case ZEND_ASSIGN_MUL: return ZEND_MUL; | |
+ case ZEND_ASSIGN_DIV: return ZEND_DIV; | |
+ case ZEND_ASSIGN_MOD: return ZEND_MOD; | |
+ case ZEND_ASSIGN_SL: return ZEND_SL; | |
+ case ZEND_ASSIGN_SR: return ZEND_SR; | |
+ case ZEND_ASSIGN_CONCAT: return ZEND_CONCAT; | |
+ case ZEND_ASSIGN_BW_OR: return ZEND_BW_OR; | |
+ case ZEND_ASSIGN_BW_AND: return ZEND_BW_AND; | |
+ case ZEND_ASSIGN_BW_XOR: return ZEND_BW_XOR; | |
+ case ZEND_ASSIGN_POW: return ZEND_POW; | |
+ EMPTY_SWITCH_DEFAULT_CASE() | |
+ } | |
+} | |
+ | |
+static int zend_inference_calc_binary_op_range( | |
+ const zend_op_array *op_array, zend_ssa *ssa, | |
+ zend_op *opline, zend_ssa_op *ssa_op, zend_uchar opcode, zend_ssa_range *tmp) { | |
+ zend_long op1_min, op2_min, op1_max, op2_max, t1, t2, t3, t4; | |
+ | |
+ switch (opcode) { | |
+ case ZEND_ADD: | |
+ if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) { | |
+ op1_min = OP1_MIN_RANGE(); | |
+ op2_min = OP2_MIN_RANGE(); | |
+ op1_max = OP1_MAX_RANGE(); | |
+ op2_max = OP2_MAX_RANGE(); | |
+ tmp->min = op1_min + op2_min; | |
+ tmp->max = op1_max + op2_max; | |
+ if (OP1_RANGE_UNDERFLOW() || | |
+ OP2_RANGE_UNDERFLOW() || | |
+ (op1_min < 0 && op2_min < 0 && tmp->min >= 0)) { | |
+ tmp->underflow = 1; | |
+ tmp->min = ZEND_LONG_MIN; | |
+ } | |
+ if (OP1_RANGE_OVERFLOW() || | |
+ OP2_RANGE_OVERFLOW() || | |
+ (op1_max > 0 && op2_max > 0 && tmp->max <= 0)) { | |
+ tmp->overflow = 1; | |
+ tmp->max = ZEND_LONG_MAX; | |
+ } | |
+ return 1; | |
+ } | |
+ break; | |
+ case ZEND_SUB: | |
+ if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) { | |
+ op1_min = OP1_MIN_RANGE(); | |
+ op2_min = OP2_MIN_RANGE(); | |
+ op1_max = OP1_MAX_RANGE(); | |
+ op2_max = OP2_MAX_RANGE(); | |
+ tmp->min = op1_min - op2_max; | |
+ tmp->max = op1_max - op2_min; | |
+ if (OP1_RANGE_UNDERFLOW() || | |
+ OP2_RANGE_OVERFLOW() || | |
+ (op1_min < 0 && op2_max > 0 && tmp->min >= 0)) { | |
+ tmp->underflow = 1; | |
+ tmp->min = ZEND_LONG_MIN; | |
+ } | |
+ if (OP1_RANGE_OVERFLOW() || | |
+ OP2_RANGE_UNDERFLOW() || | |
+ (op1_max > 0 && op2_min < 0 && tmp->max <= 0)) { | |
+ tmp->overflow = 1; | |
+ tmp->max = ZEND_LONG_MAX; | |
+ } | |
+ return 1; | |
+ } | |
+ break; | |
+ case ZEND_MUL: | |
+ if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) { | |
+ op1_min = OP1_MIN_RANGE(); | |
+ op2_min = OP2_MIN_RANGE(); | |
+ op1_max = OP1_MAX_RANGE(); | |
+ op2_max = OP2_MAX_RANGE(); | |
+ t1 = op1_min * op2_min; | |
+ t2 = op1_min * op2_max; | |
+ t3 = op1_max * op2_min; | |
+ t4 = op1_max * op2_max; | |
+ // FIXME: more careful overflow checks? | |
+ if (OP1_RANGE_UNDERFLOW() || | |
+ OP2_RANGE_UNDERFLOW() || | |
+ OP1_RANGE_OVERFLOW() || | |
+ OP2_RANGE_OVERFLOW() || | |
+ (double)t1 != (double)op1_min * (double)op2_min || | |
+ (double)t2 != (double)op1_min * (double)op2_max || | |
+ (double)t3 != (double)op1_max * (double)op2_min || | |
+ (double)t4 != (double)op1_max * (double)op2_max) { | |
+ tmp->underflow = 1; | |
+ tmp->overflow = 1; | |
+ tmp->min = ZEND_LONG_MIN; | |
+ tmp->max = ZEND_LONG_MAX; | |
+ } else { | |
+ tmp->min = MIN(MIN(t1, t2), MIN(t3, t4)); | |
+ tmp->max = MAX(MAX(t1, t2), MAX(t3, t4)); | |
+ } | |
+ return 1; | |
+ } | |
+ break; | |
+ case ZEND_DIV: | |
+ if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) { | |
+ op1_min = OP1_MIN_RANGE(); | |
+ op2_min = OP2_MIN_RANGE(); | |
+ op1_max = OP1_MAX_RANGE(); | |
+ op2_max = OP2_MAX_RANGE(); | |
+ if (op2_min <= 0 && op2_max >= 0) { | |
+ break; | |
+ } | |
+ if (op1_min == ZEND_LONG_MIN && op2_max == -1) { | |
+ /* Avoid ill-defined division, which may trigger SIGFPE. */ | |
+ break; | |
+ } | |
+ t1 = op1_min / op2_min; | |
+ t2 = op1_min / op2_max; | |
+ t3 = op1_max / op2_min; | |
+ t4 = op1_max / op2_max; | |
+ // FIXME: more careful overflow checks? | |
+ if (OP1_RANGE_UNDERFLOW() || | |
+ OP2_RANGE_UNDERFLOW() || | |
+ OP1_RANGE_OVERFLOW() || | |
+ OP2_RANGE_OVERFLOW() || | |
+ t1 != (zend_long)((double)op1_min / (double)op2_min) || | |
+ t2 != (zend_long)((double)op1_min / (double)op2_max) || | |
+ t3 != (zend_long)((double)op1_max / (double)op2_min) || | |
+ t4 != (zend_long)((double)op1_max / (double)op2_max)) { | |
+ tmp->underflow = 1; | |
+ tmp->overflow = 1; | |
+ tmp->min = ZEND_LONG_MIN; | |
+ tmp->max = ZEND_LONG_MAX; | |
+ } else { | |
+ tmp->min = MIN(MIN(t1, t2), MIN(t3, t4)); | |
+ tmp->max = MAX(MAX(t1, t2), MAX(t3, t4)); | |
+ } | |
+ return 1; | |
+ } | |
+ break; | |
+ case ZEND_MOD: | |
+ if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) { | |
+ if (OP1_RANGE_UNDERFLOW() || | |
+ OP2_RANGE_UNDERFLOW() || | |
+ OP1_RANGE_OVERFLOW() || | |
+ OP2_RANGE_OVERFLOW()) { | |
+ tmp->min = ZEND_LONG_MIN; | |
+ tmp->max = ZEND_LONG_MAX; | |
+ } else { | |
+ op1_min = OP1_MIN_RANGE(); | |
+ op2_min = OP2_MIN_RANGE(); | |
+ op1_max = OP1_MAX_RANGE(); | |
+ op2_max = OP2_MAX_RANGE(); | |
+ if (op2_min == 0 || op2_max == 0) { | |
+ /* avoid division by zero */ | |
+ break; | |
+ } | |
+ t1 = (op2_min == -1) ? 0 : (op1_min % op2_min); | |
+ t2 = (op2_max == -1) ? 0 : (op1_min % op2_max); | |
+ t3 = (op2_min == -1) ? 0 : (op1_max % op2_min); | |
+ t4 = (op2_max == -1) ? 0 : (op1_max % op2_max); | |
+ tmp->min = MIN(MIN(t1, t2), MIN(t3, t4)); | |
+ tmp->max = MAX(MAX(t1, t2), MAX(t3, t4)); | |
+ } | |
+ return 1; | |
+ } | |
+ break; | |
+ case ZEND_SL: | |
+ if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) { | |
+ if (OP1_RANGE_UNDERFLOW() || | |
+ OP2_RANGE_UNDERFLOW() || | |
+ OP1_RANGE_OVERFLOW() || | |
+ OP2_RANGE_OVERFLOW()) { | |
+ tmp->min = ZEND_LONG_MIN; | |
+ tmp->max = ZEND_LONG_MAX; | |
+ } else { | |
+ op1_min = OP1_MIN_RANGE(); | |
+ op2_min = OP2_MIN_RANGE(); | |
+ op1_max = OP1_MAX_RANGE(); | |
+ op2_max = OP2_MAX_RANGE(); | |
+ t1 = op1_min << op2_min; | |
+ t2 = op1_min << op2_max; | |
+ t3 = op1_max << op2_min; | |
+ t4 = op1_max << op2_max; | |
+ tmp->min = MIN(MIN(t1, t2), MIN(t3, t4)); | |
+ tmp->max = MAX(MAX(t1, t2), MAX(t3, t4)); | |
+ } | |
+ return 1; | |
+ } | |
+ break; | |
+ case ZEND_SR: | |
+ if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) { | |
+ if (OP1_RANGE_UNDERFLOW() || | |
+ OP2_RANGE_UNDERFLOW() || | |
+ OP1_RANGE_OVERFLOW() || | |
+ OP2_RANGE_OVERFLOW()) { | |
+ tmp->min = ZEND_LONG_MIN; | |
+ tmp->max = ZEND_LONG_MAX; | |
+ } else { | |
+ op1_min = OP1_MIN_RANGE(); | |
+ op2_min = OP2_MIN_RANGE(); | |
+ op1_max = OP1_MAX_RANGE(); | |
+ op2_max = OP2_MAX_RANGE(); | |
+ t1 = op1_min >> op2_min; | |
+ t2 = op1_min >> op2_max; | |
+ t3 = op1_max >> op2_min; | |
+ t4 = op1_max >> op2_max; | |
+ tmp->min = MIN(MIN(t1, t2), MIN(t3, t4)); | |
+ tmp->max = MAX(MAX(t1, t2), MAX(t3, t4)); | |
+ } | |
+ return 1; | |
+ } | |
+ break; | |
+ case ZEND_BW_OR: | |
+ if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) { | |
+ if (OP1_RANGE_UNDERFLOW() || | |
+ OP2_RANGE_UNDERFLOW() || | |
+ OP1_RANGE_OVERFLOW() || | |
+ OP2_RANGE_OVERFLOW()) { | |
+ tmp->min = ZEND_LONG_MIN; | |
+ tmp->max = ZEND_LONG_MAX; | |
+ } else { | |
+ op1_min = OP1_MIN_RANGE(); | |
+ op2_min = OP2_MIN_RANGE(); | |
+ op1_max = OP1_MAX_RANGE(); | |
+ op2_max = OP2_MAX_RANGE(); | |
+ zend_ssa_range_or(op1_min, op1_max, op2_min, op2_max, tmp); | |
+ } | |
+ return 1; | |
+ } | |
+ break; | |
+ case ZEND_BW_AND: | |
+ if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) { | |
+ if (OP1_RANGE_UNDERFLOW() || | |
+ OP2_RANGE_UNDERFLOW() || | |
+ OP1_RANGE_OVERFLOW() || | |
+ OP2_RANGE_OVERFLOW()) { | |
+ tmp->min = ZEND_LONG_MIN; | |
+ tmp->max = ZEND_LONG_MAX; | |
+ } else { | |
+ op1_min = OP1_MIN_RANGE(); | |
+ op2_min = OP2_MIN_RANGE(); | |
+ op1_max = OP1_MAX_RANGE(); | |
+ op2_max = OP2_MAX_RANGE(); | |
+ zend_ssa_range_and(op1_min, op1_max, op2_min, op2_max, tmp); | |
+ } | |
+ return 1; | |
+ } | |
+ break; | |
+ case ZEND_BW_XOR: | |
+ // TODO | |
+ break; | |
+ EMPTY_SWITCH_DEFAULT_CASE() | |
+ } | |
+ return 0; | |
+} | |
+ | |
int zend_inference_calc_range(const zend_op_array *op_array, zend_ssa *ssa, int var, int widening, int narrowing, zend_ssa_range *tmp) | |
{ | |
uint32_t line; | |
zend_op *opline; | |
- zend_long op1_min, op2_min, op1_max, op2_max, t1, t2, t3, t4; | |
+ zend_long op1_min, op2_min, op1_max, op2_max; | |
if (ssa->vars[var].definition_phi) { | |
zend_ssa_phi *p = ssa->vars[var].definition_phi; | |
@@ -633,241 +900,21 @@ int zend_inference_calc_range(const zend_op_array *op_array, zend_ssa *ssa, int | |
tmp->overflow = 0; | |
switch (opline->opcode) { | |
case ZEND_ADD: | |
- if (ssa->ops[line].result_def == var) { | |
- if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) { | |
- op1_min = OP1_MIN_RANGE(); | |
- op2_min = OP2_MIN_RANGE(); | |
- op1_max = OP1_MAX_RANGE(); | |
- op2_max = OP2_MAX_RANGE(); | |
- tmp->min = op1_min + op2_min; | |
- tmp->max = op1_max + op2_max; | |
- if (OP1_RANGE_UNDERFLOW() || | |
- OP2_RANGE_UNDERFLOW() || | |
- (op1_min < 0 && op2_min < 0 && tmp->min >= 0)) { | |
- tmp->underflow = 1; | |
- tmp->min = ZEND_LONG_MIN; | |
- } | |
- if (OP1_RANGE_OVERFLOW() || | |
- OP2_RANGE_OVERFLOW() || | |
- (op1_max > 0 && op2_max > 0 && tmp->max <= 0)) { | |
- tmp->overflow = 1; | |
- tmp->max = ZEND_LONG_MAX; | |
- } | |
- return 1; | |
- } | |
- } | |
- break; | |
case ZEND_SUB: | |
- if (ssa->ops[line].result_def == var) { | |
- if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) { | |
- op1_min = OP1_MIN_RANGE(); | |
- op2_min = OP2_MIN_RANGE(); | |
- op1_max = OP1_MAX_RANGE(); | |
- op2_max = OP2_MAX_RANGE(); | |
- tmp->min = op1_min - op2_max; | |
- tmp->max = op1_max - op2_min; | |
- if (OP1_RANGE_UNDERFLOW() || | |
- OP2_RANGE_OVERFLOW() || | |
- (op1_min < 0 && op2_max > 0 && tmp->min >= 0)) { | |
- tmp->underflow = 1; | |
- tmp->min = ZEND_LONG_MIN; | |
- } | |
- if (OP1_RANGE_OVERFLOW() || | |
- OP2_RANGE_UNDERFLOW() || | |
- (op1_max > 0 && op2_min < 0 && tmp->max <= 0)) { | |
- tmp->overflow = 1; | |
- tmp->max = ZEND_LONG_MAX; | |
- } | |
- return 1; | |
- } | |
- } | |
- break; | |
case ZEND_MUL: | |
- if (ssa->ops[line].result_def == var) { | |
- if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) { | |
- op1_min = OP1_MIN_RANGE(); | |
- op2_min = OP2_MIN_RANGE(); | |
- op1_max = OP1_MAX_RANGE(); | |
- op2_max = OP2_MAX_RANGE(); | |
- t1 = op1_min * op2_min; | |
- t2 = op1_min * op2_max; | |
- t3 = op1_max * op2_min; | |
- t4 = op1_max * op2_max; | |
- // FIXME: more careful overflow checks? | |
- if (OP1_RANGE_UNDERFLOW() || | |
- OP2_RANGE_UNDERFLOW() || | |
- OP1_RANGE_OVERFLOW() || | |
- OP2_RANGE_OVERFLOW() || | |
- (double)t1 != (double)op1_min * (double)op2_min || | |
- (double)t2 != (double)op1_min * (double)op2_max || | |
- (double)t3 != (double)op1_max * (double)op2_min || | |
- (double)t4 != (double)op1_max * (double)op2_max) { | |
- tmp->underflow = 1; | |
- tmp->overflow = 1; | |
- tmp->min = ZEND_LONG_MIN; | |
- tmp->max = ZEND_LONG_MAX; | |
- } else { | |
- tmp->min = MIN(MIN(t1, t2), MIN(t3, t4)); | |
- tmp->max = MAX(MAX(t1, t2), MAX(t3, t4)); | |
- } | |
- return 1; | |
- } | |
- } | |
- break; | |
case ZEND_DIV: | |
- if (ssa->ops[line].result_def == var) { | |
- if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) { | |
- op1_min = OP1_MIN_RANGE(); | |
- op2_min = OP2_MIN_RANGE(); | |
- op1_max = OP1_MAX_RANGE(); | |
- op2_max = OP2_MAX_RANGE(); | |
- if (op2_min <= 0 && op2_max >= 0) { | |
- break; | |
- } | |
- t1 = op1_min / op2_min; | |
- t2 = op1_min / op2_max; | |
- t3 = op1_max / op2_min; | |
- t4 = op1_max / op2_max; | |
- // FIXME: more careful overflow checks? | |
- if (OP1_RANGE_UNDERFLOW() || | |
- OP2_RANGE_UNDERFLOW() || | |
- OP1_RANGE_OVERFLOW() || | |
- OP2_RANGE_OVERFLOW() || | |
- t1 != (zend_long)((double)op1_min / (double)op2_min) || | |
- t2 != (zend_long)((double)op1_min / (double)op2_max) || | |
- t3 != (zend_long)((double)op1_max / (double)op2_min) || | |
- t4 != (zend_long)((double)op1_max / (double)op2_max)) { | |
- tmp->underflow = 1; | |
- tmp->overflow = 1; | |
- tmp->min = ZEND_LONG_MIN; | |
- tmp->max = ZEND_LONG_MAX; | |
- } else { | |
- tmp->min = MIN(MIN(t1, t2), MIN(t3, t4)); | |
- tmp->max = MAX(MAX(t1, t2), MAX(t3, t4)); | |
- } | |
- return 1; | |
- } | |
- } | |
- break; | |
case ZEND_MOD: | |
- if (ssa->ops[line].result_def == var) { | |
- if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) { | |
- if (OP1_RANGE_UNDERFLOW() || | |
- OP2_RANGE_UNDERFLOW() || | |
- OP1_RANGE_OVERFLOW() || | |
- OP2_RANGE_OVERFLOW()) { | |
- tmp->min = ZEND_LONG_MIN; | |
- tmp->max = ZEND_LONG_MAX; | |
- } else { | |
- op1_min = OP1_MIN_RANGE(); | |
- op2_min = OP2_MIN_RANGE(); | |
- op1_max = OP1_MAX_RANGE(); | |
- op2_max = OP2_MAX_RANGE(); | |
- if (op2_min == 0 || op2_max == 0) { | |
- /* avoid division by zero */ | |
- break; | |
- } | |
- t1 = (op2_min == -1) ? 0 : (op1_min % op2_min); | |
- t2 = (op2_max == -1) ? 0 : (op1_min % op2_max); | |
- t3 = (op2_min == -1) ? 0 : (op1_max % op2_min); | |
- t4 = (op2_max == -1) ? 0 : (op1_max % op2_max); | |
- tmp->min = MIN(MIN(t1, t2), MIN(t3, t4)); | |
- tmp->max = MAX(MAX(t1, t2), MAX(t3, t4)); | |
- } | |
- } | |
- } | |
- break; | |
case ZEND_SL: | |
- if (ssa->ops[line].result_def == var) { | |
- if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) { | |
- if (OP1_RANGE_UNDERFLOW() || | |
- OP2_RANGE_UNDERFLOW() || | |
- OP1_RANGE_OVERFLOW() || | |
- OP2_RANGE_OVERFLOW()) { | |
- tmp->min = ZEND_LONG_MIN; | |
- tmp->max = ZEND_LONG_MAX; | |
- } else { | |
- op1_min = OP1_MIN_RANGE(); | |
- op2_min = OP2_MIN_RANGE(); | |
- op1_max = OP1_MAX_RANGE(); | |
- op2_max = OP2_MAX_RANGE(); | |
- t1 = op1_min << op2_min; | |
- t2 = op1_min << op2_max; | |
- t3 = op1_max << op2_min; | |
- t4 = op1_max << op2_max; | |
- tmp->min = MIN(MIN(t1, t2), MIN(t3, t4)); | |
- tmp->max = MAX(MAX(t1, t2), MAX(t3, t4)); | |
- } | |
- return 1; | |
- } | |
- } | |
- break; | |
case ZEND_SR: | |
- if (ssa->ops[line].result_def == var) { | |
- if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) { | |
- if (OP1_RANGE_UNDERFLOW() || | |
- OP2_RANGE_UNDERFLOW() || | |
- OP1_RANGE_OVERFLOW() || | |
- OP2_RANGE_OVERFLOW()) { | |
- tmp->min = ZEND_LONG_MIN; | |
- tmp->max = ZEND_LONG_MAX; | |
- } else { | |
- op1_min = OP1_MIN_RANGE(); | |
- op2_min = OP2_MIN_RANGE(); | |
- op1_max = OP1_MAX_RANGE(); | |
- op2_max = OP2_MAX_RANGE(); | |
- t1 = op1_min >> op2_min; | |
- t2 = op1_min >> op2_max; | |
- t3 = op1_max >> op2_min; | |
- t4 = op1_max >> op2_max; | |
- tmp->min = MIN(MIN(t1, t2), MIN(t3, t4)); | |
- tmp->max = MAX(MAX(t1, t2), MAX(t3, t4)); | |
- } | |
- return 1; | |
- } | |
- } | |
- break; | |
case ZEND_BW_OR: | |
- if (ssa->ops[line].result_def == var) { | |
- if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) { | |
- if (OP1_RANGE_UNDERFLOW() || | |
- OP2_RANGE_UNDERFLOW() || | |
- OP1_RANGE_OVERFLOW() || | |
- OP2_RANGE_OVERFLOW()) { | |
- tmp->min = ZEND_LONG_MIN; | |
- tmp->max = ZEND_LONG_MAX; | |
- } else { | |
- op1_min = OP1_MIN_RANGE(); | |
- op2_min = OP2_MIN_RANGE(); | |
- op1_max = OP1_MAX_RANGE(); | |
- op2_max = OP2_MAX_RANGE(); | |
- zend_ssa_range_or(op1_min, op1_max, op2_min, op2_max, tmp); | |
- } | |
- return 1; | |
- } | |
- } | |
- break; | |
case ZEND_BW_AND: | |
+ case ZEND_BW_XOR: | |
if (ssa->ops[line].result_def == var) { | |
- if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) { | |
- if (OP1_RANGE_UNDERFLOW() || | |
- OP2_RANGE_UNDERFLOW() || | |
- OP1_RANGE_OVERFLOW() || | |
- OP2_RANGE_OVERFLOW()) { | |
- tmp->min = ZEND_LONG_MIN; | |
- tmp->max = ZEND_LONG_MAX; | |
- } else { | |
- op1_min = OP1_MIN_RANGE(); | |
- op2_min = OP2_MIN_RANGE(); | |
- op1_max = OP1_MAX_RANGE(); | |
- op2_max = OP2_MAX_RANGE(); | |
- zend_ssa_range_and(op1_min, op1_max, op2_min, op2_max, tmp); | |
- } | |
- return 1; | |
- } | |
+ return zend_inference_calc_binary_op_range( | |
+ op_array, ssa, opline, &ssa->ops[line], opline->opcode, tmp); | |
} | |
break; | |
-// case ZEND_BW_XOR: | |
+ | |
case ZEND_BW_NOT: | |
if (ssa->ops[line].result_def == var) { | |
if (OP1_HAS_RANGE()) { | |
@@ -1229,349 +1276,25 @@ int zend_inference_calc_range(const zend_op_array *op_array, zend_ssa *ssa, int | |
} | |
break; | |
case ZEND_ASSIGN_ADD: | |
- if (opline->extended_value == 0) { | |
- if (ssa->ops[line].op1_def == var || ssa->ops[line].result_def == var) { | |
- if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) { | |
- op1_min = OP1_MIN_RANGE(); | |
- op2_min = OP2_MIN_RANGE(); | |
- op1_max = OP1_MAX_RANGE(); | |
- op2_max = OP2_MAX_RANGE(); | |
- tmp->min = op1_min + op2_min; | |
- tmp->max = op1_max + op2_max; | |
- if (OP1_RANGE_UNDERFLOW() || | |
- OP2_RANGE_UNDERFLOW() || | |
- (op1_min < 0 && op2_min < 0 && tmp->min >= 0)) { | |
- tmp->underflow = 1; | |
- tmp->min = ZEND_LONG_MIN; | |
- } | |
- if (OP1_RANGE_OVERFLOW() || | |
- OP2_RANGE_OVERFLOW() || | |
- (op1_max > 0 && op2_max > 0 && tmp->max <= 0)) { | |
- tmp->overflow = 1; | |
- tmp->max = ZEND_LONG_MAX; | |
- } | |
- return 1; | |
- } | |
- } | |
- } else if ((opline+1)->opcode == ZEND_OP_DATA) { | |
- if (ssa->ops[line+1].op1_def == var) { | |
- opline++; | |
- if (OP1_HAS_RANGE()) { | |
- tmp->min = OP1_MIN_RANGE(); | |
- tmp->max = OP1_MAX_RANGE(); | |
- tmp->underflow = OP1_RANGE_UNDERFLOW(); | |
- tmp->overflow = OP1_RANGE_OVERFLOW(); | |
- return 1; | |
- } | |
- } | |
- } | |
- break; | |
case ZEND_ASSIGN_SUB: | |
- if (opline->extended_value == 0) { | |
- if (ssa->ops[line].op1_def == var || ssa->ops[line].result_def == var) { | |
- if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) { | |
- op1_min = OP1_MIN_RANGE(); | |
- op2_min = OP2_MIN_RANGE(); | |
- op1_max = OP1_MAX_RANGE(); | |
- op2_max = OP2_MAX_RANGE(); | |
- tmp->min = op1_min - op2_max; | |
- tmp->max = op1_max - op2_min; | |
- if (OP1_RANGE_UNDERFLOW() || | |
- OP2_RANGE_OVERFLOW() || | |
- (op1_min < 0 && op2_max > 0 && tmp->min >= 0)) { | |
- tmp->underflow = 1; | |
- tmp->min = ZEND_LONG_MIN; | |
- } | |
- if (OP1_RANGE_OVERFLOW() || | |
- OP2_RANGE_UNDERFLOW() || | |
- (op1_max > 0 && op2_min < 0 && tmp->max <= 0)) { | |
- tmp->overflow = 1; | |
- tmp->max = ZEND_LONG_MAX; | |
- } | |
- return 1; | |
- } | |
- } | |
- } else if ((opline+1)->opcode == ZEND_OP_DATA) { | |
- if (ssa->ops[line+1].op1_def == var) { | |
- opline++; | |
- if (OP1_HAS_RANGE()) { | |
- tmp->min = OP1_MIN_RANGE(); | |
- tmp->max = OP1_MAX_RANGE(); | |
- tmp->underflow = OP1_RANGE_UNDERFLOW(); | |
- tmp->overflow = OP1_RANGE_OVERFLOW(); | |
- return 1; | |
- } | |
- } | |
- } | |
- break; | |
case ZEND_ASSIGN_MUL: | |
- if (opline->extended_value == 0) { | |
- if (ssa->ops[line].op1_def == var || ssa->ops[line].result_def == var) { | |
- if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) { | |
- op1_min = OP1_MIN_RANGE(); | |
- op2_min = OP2_MIN_RANGE(); | |
- op1_max = OP1_MAX_RANGE(); | |
- op2_max = OP2_MAX_RANGE(); | |
- t1 = op1_min * op2_min; | |
- t2 = op1_min * op2_max; | |
- t3 = op1_max * op2_min; | |
- t4 = op1_max * op2_max; | |
- // FIXME: more careful overflow checks? | |
- if (OP1_RANGE_UNDERFLOW() || | |
- OP2_RANGE_UNDERFLOW() || | |
- OP1_RANGE_OVERFLOW() || | |
- OP2_RANGE_OVERFLOW() || | |
- (double)t1 != (double)op1_min * (double)op2_min || | |
- (double)t2 != (double)op1_min * (double)op2_min || | |
- (double)t3 != (double)op1_min * (double)op2_min || | |
- (double)t4 != (double)op1_min * (double)op2_min) { | |
- tmp->underflow = 1; | |
- tmp->overflow = 1; | |
- tmp->min = ZEND_LONG_MIN; | |
- tmp->max = ZEND_LONG_MAX; | |
- } else { | |
- tmp->min = MIN(MIN(t1, t2), MIN(t3, t4)); | |
- tmp->max = MAX(MAX(t1, t2), MAX(t3, t4)); | |
- } | |
- return 1; | |
- } | |
- } | |
- } else if ((opline+1)->opcode == ZEND_OP_DATA) { | |
- if (ssa->ops[line+1].op1_def == var) { | |
- if (OP1_HAS_RANGE()) { | |
- opline++; | |
- tmp->min = OP1_MIN_RANGE(); | |
- tmp->max = OP1_MAX_RANGE(); | |
- tmp->underflow = OP1_RANGE_UNDERFLOW(); | |
- tmp->overflow = OP1_RANGE_OVERFLOW(); | |
- return 1; | |
- } | |
- } | |
- } | |
- break; | |
case ZEND_ASSIGN_DIV: | |
- if (opline->extended_value == 0) { | |
- if (ssa->ops[line].op1_def == var || ssa->ops[line].result_def == var) { | |
- if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) { | |
- op1_min = OP1_MIN_RANGE(); | |
- op2_min = OP2_MIN_RANGE(); | |
- op1_max = OP1_MAX_RANGE(); | |
- op2_max = OP2_MAX_RANGE(); | |
- if (op2_min <= 0 && op2_max >= 0) { | |
- break; | |
- } | |
- t1 = op1_min / op2_min; | |
- t2 = op1_min / op2_max; | |
- t3 = op1_max / op2_min; | |
- t4 = op1_max / op2_max; | |
- // FIXME: more careful overflow checks? | |
- if (OP1_RANGE_UNDERFLOW() || | |
- OP2_RANGE_UNDERFLOW() || | |
- OP1_RANGE_OVERFLOW() || | |
- OP2_RANGE_OVERFLOW() || | |
- t1 != (zend_long)((double)op1_min / (double)op2_min) || | |
- t2 != (zend_long)((double)op1_min / (double)op2_max) || | |
- t3 != (zend_long)((double)op1_max / (double)op2_min) || | |
- t4 != (zend_long)((double)op1_max / (double)op2_max)) { | |
- tmp->underflow = 1; | |
- tmp->overflow = 1; | |
- tmp->min = ZEND_LONG_MIN; | |
- tmp->max = ZEND_LONG_MAX; | |
- } else { | |
- tmp->min = MIN(MIN(t1, t2), MIN(t3, t4)); | |
- tmp->max = MAX(MAX(t1, t2), MAX(t3, t4)); | |
- } | |
- return 1; | |
- } | |
- } | |
- } else if ((opline+1)->opcode == ZEND_OP_DATA) { | |
- if (ssa->ops[line+1].op1_def == var) { | |
- if (OP1_HAS_RANGE()) { | |
- opline++; | |
- tmp->min = OP1_MIN_RANGE(); | |
- tmp->max = OP1_MAX_RANGE(); | |
- tmp->underflow = OP1_RANGE_UNDERFLOW(); | |
- tmp->overflow = OP1_RANGE_OVERFLOW(); | |
- return 1; | |
- } | |
- } | |
- } | |
- break; | |
case ZEND_ASSIGN_MOD: | |
- if (opline->extended_value == 0) { | |
- if (ssa->ops[line].op1_def == var || ssa->ops[line].result_def == var) { | |
- if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) { | |
- if (OP1_RANGE_UNDERFLOW() || | |
- OP2_RANGE_UNDERFLOW() || | |
- OP1_RANGE_OVERFLOW() || | |
- OP2_RANGE_OVERFLOW()) { | |
- tmp->min = ZEND_LONG_MIN; | |
- tmp->max = ZEND_LONG_MAX; | |
- } else { | |
- op1_min = OP1_MIN_RANGE(); | |
- op2_min = OP2_MIN_RANGE(); | |
- op1_max = OP1_MAX_RANGE(); | |
- op2_max = OP2_MAX_RANGE(); | |
- if (op2_min == 0 || op2_max == 0) { | |
- /* avoid division by zero */ | |
- break; | |
- } | |
- t1 = op1_min % op2_min; | |
- t2 = op1_min % op2_max; | |
- t3 = op1_max % op2_min; | |
- t4 = op1_max % op2_max; | |
- tmp->min = MIN(MIN(t1, t2), MIN(t3, t4)); | |
- tmp->max = MAX(MAX(t1, t2), MAX(t3, t4)); | |
- } | |
- return 1; | |
- } | |
- } | |
- } else if ((opline+1)->opcode == ZEND_OP_DATA) { | |
- if (ssa->ops[line+1].op1_def == var) { | |
- if (OP1_HAS_RANGE()) { | |
- opline++; | |
- tmp->min = OP1_MIN_RANGE(); | |
- tmp->max = OP1_MAX_RANGE(); | |
- tmp->underflow = OP1_RANGE_UNDERFLOW(); | |
- tmp->overflow = OP1_RANGE_OVERFLOW(); | |
- return 1; | |
- } | |
- } | |
- } | |
- break; | |
case ZEND_ASSIGN_SL: | |
- if (opline->extended_value == 0) { | |
- if (ssa->ops[line].op1_def == var || ssa->ops[line].result_def == var) { | |
- if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) { | |
- if (OP1_RANGE_UNDERFLOW() || | |
- OP2_RANGE_UNDERFLOW() || | |
- OP1_RANGE_OVERFLOW() || | |
- OP2_RANGE_OVERFLOW()) { | |
- tmp->min = ZEND_LONG_MIN; | |
- tmp->max = ZEND_LONG_MAX; | |
- } else { | |
- op1_min = OP1_MIN_RANGE(); | |
- op2_min = OP2_MIN_RANGE(); | |
- op1_max = OP1_MAX_RANGE(); | |
- op2_max = OP2_MAX_RANGE(); | |
- t1 = op1_min << op2_min; | |
- t2 = op1_min << op2_max; | |
- t3 = op1_max << op2_min; | |
- t4 = op1_max << op2_max; | |
- tmp->min = MIN(MIN(t1, t2), MIN(t3, t4)); | |
- tmp->max = MAX(MAX(t1, t2), MAX(t3, t4)); | |
- } | |
- return 1; | |
- } | |
- } | |
- } else if ((opline+1)->opcode == ZEND_OP_DATA) { | |
- if (ssa->ops[line+1].op1_def == var) { | |
- if (OP1_HAS_RANGE()) { | |
- opline++; | |
- tmp->min = OP1_MIN_RANGE(); | |
- tmp->max = OP1_MAX_RANGE(); | |
- tmp->underflow = OP1_RANGE_UNDERFLOW(); | |
- tmp->overflow = OP1_RANGE_OVERFLOW(); | |
- return 1; | |
- } | |
- } | |
- } | |
- break; | |
case ZEND_ASSIGN_SR: | |
- if (opline->extended_value == 0) { | |
- if (ssa->ops[line].op1_def == var || ssa->ops[line].result_def == var) { | |
- if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) { | |
- if (OP1_RANGE_UNDERFLOW() || | |
- OP2_RANGE_UNDERFLOW() || | |
- OP1_RANGE_OVERFLOW() || | |
- OP2_RANGE_OVERFLOW()) { | |
- tmp->min = ZEND_LONG_MIN; | |
- tmp->max = ZEND_LONG_MAX; | |
- } else { | |
- op1_min = OP1_MIN_RANGE(); | |
- op2_min = OP2_MIN_RANGE(); | |
- op1_max = OP1_MAX_RANGE(); | |
- op2_max = OP2_MAX_RANGE(); | |
- t1 = op1_min >> op2_min; | |
- t2 = op1_min >> op2_max; | |
- t3 = op1_max >> op2_min; | |
- t4 = op1_max >> op2_max; | |
- tmp->min = MIN(MIN(t1, t2), MIN(t3, t4)); | |
- tmp->max = MAX(MAX(t1, t2), MAX(t3, t4)); | |
- } | |
- return 1; | |
- } | |
- } | |
- } else if ((opline+1)->opcode == ZEND_OP_DATA) { | |
- if (ssa->ops[line+1].op1_def == var) { | |
- if (OP1_HAS_RANGE()) { | |
- opline++; | |
- tmp->min = OP1_MIN_RANGE(); | |
- tmp->max = OP1_MAX_RANGE(); | |
- tmp->underflow = OP1_RANGE_UNDERFLOW(); | |
- tmp->overflow = OP1_RANGE_OVERFLOW(); | |
- return 1; | |
- } | |
- } | |
- } | |
- break; | |
case ZEND_ASSIGN_BW_OR: | |
- if (opline->extended_value == 0) { | |
- if (ssa->ops[line].op1_def == var || ssa->ops[line].result_def == var) { | |
- if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) { | |
- if (OP1_RANGE_UNDERFLOW() || | |
- OP2_RANGE_UNDERFLOW() || | |
- OP1_RANGE_OVERFLOW() || | |
- OP2_RANGE_OVERFLOW()) { | |
- tmp->min = ZEND_LONG_MIN; | |
- tmp->max = ZEND_LONG_MAX; | |
- } else { | |
- op1_min = OP1_MIN_RANGE(); | |
- op2_min = OP2_MIN_RANGE(); | |
- op1_max = OP1_MAX_RANGE(); | |
- op2_max = OP2_MAX_RANGE(); | |
- zend_ssa_range_or(op1_min, op1_max, op2_min, op2_max, tmp); | |
- } | |
- return 1; | |
- } | |
- } | |
- } else if ((opline+1)->opcode == ZEND_OP_DATA) { | |
- if (ssa->ops[line+1].op1_def == var) { | |
- if (OP1_HAS_RANGE()) { | |
- opline++; | |
- tmp->min = OP1_MIN_RANGE(); | |
- tmp->max = OP1_MAX_RANGE(); | |
- tmp->underflow = OP1_RANGE_UNDERFLOW(); | |
- tmp->overflow = OP1_RANGE_OVERFLOW(); | |
- return 1; | |
- } | |
- } | |
- } | |
- break; | |
case ZEND_ASSIGN_BW_AND: | |
+ case ZEND_ASSIGN_BW_XOR: | |
if (opline->extended_value == 0) { | |
if (ssa->ops[line].op1_def == var || ssa->ops[line].result_def == var) { | |
- if (OP1_HAS_RANGE() && OP2_HAS_RANGE()) { | |
- if (OP1_RANGE_UNDERFLOW() || | |
- OP2_RANGE_UNDERFLOW() || | |
- OP1_RANGE_OVERFLOW() || | |
- OP2_RANGE_OVERFLOW()) { | |
- tmp->min = ZEND_LONG_MIN; | |
- tmp->max = ZEND_LONG_MAX; | |
- } else { | |
- op1_min = OP1_MIN_RANGE(); | |
- op2_min = OP2_MIN_RANGE(); | |
- op1_max = OP1_MAX_RANGE(); | |
- op2_max = OP2_MAX_RANGE(); | |
- zend_ssa_range_and(op1_min, op1_max, op2_min, op2_max, tmp); | |
- } | |
- return 1; | |
- } | |
+ return zend_inference_calc_binary_op_range( | |
+ op_array, ssa, opline, &ssa->ops[line], | |
+ get_compound_assign_op(opline->opcode), tmp); | |
} | |
} else if ((opline+1)->opcode == ZEND_OP_DATA) { | |
if (ssa->ops[line+1].op1_def == var) { | |
+ opline++; | |
if (OP1_HAS_RANGE()) { | |
- opline++; | |
tmp->min = OP1_MIN_RANGE(); | |
tmp->max = OP1_MAX_RANGE(); | |
tmp->underflow = OP1_RANGE_UNDERFLOW(); | |
@@ -1581,7 +1304,6 @@ int zend_inference_calc_range(const zend_op_array *op_array, zend_ssa *ssa, int | |
} | |
} | |
break; | |
-// case ZEND_ASSIGN_BW_XOR: | |
// case ZEND_ASSIGN_CONCAT: | |
case ZEND_OP_DATA: | |
if ((opline-1)->opcode == ZEND_ASSIGN_DIM || | |
@@ -1647,21 +1369,24 @@ int zend_inference_calc_range(const zend_op_array *op_array, zend_ssa *ssa, int | |
case ZEND_DO_ICALL: | |
case ZEND_DO_UCALL: | |
case ZEND_DO_FCALL_BY_NAME: | |
- if (ssa->ops[line].result_def == var && ZEND_FUNC_INFO(op_array)) { | |
+ if (ssa->ops[line].result_def == var) { | |
zend_func_info *func_info = ZEND_FUNC_INFO(op_array); | |
- zend_call_info *call_info = func_info->callee_info; | |
+ zend_call_info *call_info; | |
+ if (!func_info || !func_info->call_map) { | |
+ break; | |
+ } | |
- while (call_info && call_info->caller_call_opline != opline) { | |
- call_info = call_info->next_callee; | |
+ call_info = func_info->call_map[opline - op_array->opcodes]; | |
+ if (!call_info) { | |
+ break; | |
} | |
- if (call_info) { | |
- if (call_info->callee_func->type == ZEND_USER_FUNCTION) { | |
- func_info = ZEND_FUNC_INFO(&call_info->callee_func->op_array); | |
- if (func_info && func_info->return_info.has_range) { | |
- *tmp = func_info->return_info.range; | |
- return 1; | |
- } | |
+ if (call_info->callee_func->type == ZEND_USER_FUNCTION) { | |
+ func_info = ZEND_FUNC_INFO(&call_info->callee_func->op_array); | |
+ if (func_info && func_info->return_info.has_range) { | |
+ *tmp = func_info->return_info.range; | |
+ return 1; | |
} | |
+ } | |
//TODO: we can't use type inference for internal functions at this point ??? | |
#if 0 | |
uint32_t type; | |
@@ -1684,7 +1409,6 @@ int zend_inference_calc_range(const zend_op_array *op_array, zend_ssa *ssa, int | |
return 1; | |
} | |
#endif | |
- } | |
} | |
break; | |
// FIXME: support for more opcodes | |
@@ -1856,9 +1580,7 @@ static void zend_infer_ranges_warmup(const zend_op_array *op_array, zend_ssa *ss | |
memset(visited, 0, sizeof(zend_ulong) * worklist_len); | |
- while (!zend_bitset_empty(worklist, worklist_len)) { | |
- j = zend_bitset_first(worklist, worklist_len); | |
- zend_bitset_excl(worklist, j); | |
+ WHILE_WORKLIST(worklist, worklist_len, j) { | |
if (zend_inference_calc_range(op_array, ssa, j, 0, 0, &tmp)) { | |
#ifdef NEG_RANGE | |
if (!has_inner_cycles && | |
@@ -1913,7 +1635,7 @@ static void zend_infer_ranges_warmup(const zend_op_array *op_array, zend_ssa *ss | |
FOR_EACH_VAR_USAGE(j, ADD_SCC_VAR_1); | |
} | |
} | |
- } | |
+ } WHILE_WORKLIST_END(); | |
} | |
free_alloca(worklist, use_heap); | |
} | |
@@ -1930,11 +1652,11 @@ static int zend_infer_ranges(const zend_op_array *op_array, zend_ssa *ssa) /* {{ | |
ALLOCA_FLAG(use_heap); | |
worklist = do_alloca( | |
- sizeof(zend_ulong) * worklist_len + | |
- sizeof(int) * ssa->vars_count + | |
+ ZEND_MM_ALIGNED_SIZE(sizeof(zend_ulong) * worklist_len) + | |
+ ZEND_MM_ALIGNED_SIZE(sizeof(int) * ssa->vars_count) + | |
sizeof(int) * ssa->sccs, use_heap); | |
- next_scc_var = (int*)(worklist + worklist_len); | |
- scc_var = next_scc_var + ssa->vars_count; | |
+ next_scc_var = (int*)((char*)worklist + ZEND_MM_ALIGNED_SIZE(sizeof(zend_ulong) * worklist_len)); | |
+ scc_var = (int*)((char*)next_scc_var + ZEND_MM_ALIGNED_SIZE(sizeof(int) * ssa->vars_count)); | |
LOG_SSA_RANGE("Range Inference\n"); | |
@@ -1976,13 +1698,11 @@ static int zend_infer_ranges(const zend_op_array *op_array, zend_ssa *ssa) /* {{ | |
#endif | |
/* widening */ | |
- while (!zend_bitset_empty(worklist, worklist_len)) { | |
- j = zend_bitset_first(worklist, worklist_len); | |
- zend_bitset_excl(worklist, j); | |
+ WHILE_WORKLIST(worklist, worklist_len, j) { | |
if (zend_ssa_range_widening(op_array, ssa, j, scc)) { | |
FOR_EACH_VAR_USAGE(j, ADD_SCC_VAR); | |
} | |
- } | |
+ } WHILE_WORKLIST_END(); | |
/* Add all SCC entry variables into worklist for narrowing */ | |
for (j = scc_var[scc]; j >= 0; j = next_scc_var[j]) { | |
@@ -1993,9 +1713,7 @@ static int zend_infer_ranges(const zend_op_array *op_array, zend_ssa *ssa) /* {{ | |
} | |
/* narrowing */ | |
- while (!zend_bitset_empty(worklist, worklist_len)) { | |
- j = zend_bitset_first(worklist, worklist_len); | |
- zend_bitset_excl(worklist, j); | |
+ WHILE_WORKLIST(worklist, worklist_len, j) { | |
if (zend_ssa_range_narrowing(op_array, ssa, j, scc)) { | |
FOR_EACH_VAR_USAGE(j, ADD_SCC_VAR); | |
#ifdef SYM_RANGE | |
@@ -2007,7 +1725,7 @@ static int zend_infer_ranges(const zend_op_array *op_array, zend_ssa *ssa) /* {{ | |
} | |
#endif | |
} | |
- } | |
+ } WHILE_WORKLIST_END(); | |
} | |
} | |
@@ -2358,25 +2076,6 @@ static uint32_t binary_op_result_type( | |
return tmp; | |
} | |
-/* Get the normal op corresponding to a compound assignment op */ | |
-static inline zend_uchar get_compound_assign_op(zend_uchar opcode) { | |
- switch (opcode) { | |
- case ZEND_ASSIGN_ADD: return ZEND_ADD; | |
- case ZEND_ASSIGN_SUB: return ZEND_SUB; | |
- case ZEND_ASSIGN_MUL: return ZEND_MUL; | |
- case ZEND_ASSIGN_DIV: return ZEND_DIV; | |
- case ZEND_ASSIGN_MOD: return ZEND_MOD; | |
- case ZEND_ASSIGN_SL: return ZEND_SL; | |
- case ZEND_ASSIGN_SR: return ZEND_SR; | |
- case ZEND_ASSIGN_CONCAT: return ZEND_CONCAT; | |
- case ZEND_ASSIGN_BW_OR: return ZEND_BW_OR; | |
- case ZEND_ASSIGN_BW_AND: return ZEND_BW_AND; | |
- case ZEND_ASSIGN_BW_XOR: return ZEND_BW_XOR; | |
- case ZEND_ASSIGN_POW: return ZEND_POW; | |
- EMPTY_SWITCH_DEFAULT_CASE() | |
- } | |
-} | |
- | |
static inline zend_class_entry *get_class_entry(const zend_script *script, zend_string *lcname) { | |
zend_class_entry *ce = script ? zend_hash_find_ptr(&script->class_table, lcname) : NULL; | |
if (ce) { | |
@@ -3435,13 +3134,10 @@ static void zend_update_type_info(const zend_op_array *op_array, | |
zend_func_info *func_info = ZEND_FUNC_INFO(op_array); | |
zend_call_info *call_info; | |
- if (!func_info) { | |
+ if (!func_info || !func_info->call_map) { | |
goto unknown_opcode; | |
} | |
- call_info = func_info->callee_info; | |
- while (call_info && call_info->caller_call_opline != opline) { | |
- call_info = call_info->next_callee; | |
- } | |
+ call_info = func_info->call_map[opline - op_array->opcodes]; | |
if (!call_info) { | |
goto unknown_opcode; | |
} | |
@@ -3476,6 +3172,7 @@ static void zend_update_type_info(const zend_op_array *op_array, | |
case ZEND_VERIFY_RETURN_TYPE: | |
if (t1 & MAY_BE_REF) { | |
tmp = t1; | |
+ ce = NULL; | |
} else { | |
zend_arg_info *ret_info = op_array->arg_info - 1; | |
@@ -3577,9 +3274,7 @@ int zend_infer_types_ex(const zend_op_array *op_array, const zend_script *script | |
int i, j; | |
uint32_t tmp; | |
- while (!zend_bitset_empty(worklist, zend_bitset_len(ssa_vars_count))) { | |
- j = zend_bitset_first(worklist, zend_bitset_len(ssa_vars_count)); | |
- zend_bitset_excl(worklist, j); | |
+ WHILE_WORKLIST(worklist, zend_bitset_len(ssa_vars_count), j) { | |
if (ssa_vars[j].definition_phi) { | |
zend_ssa_phi *p = ssa_vars[j].definition_phi; | |
if (p->pi >= 0) { | |
@@ -3636,7 +3331,7 @@ int zend_infer_types_ex(const zend_op_array *op_array, const zend_script *script | |
i = ssa_vars[j].definition; | |
zend_update_type_info(op_array, ssa, script, worklist, i); | |
} | |
- } | |
+ } WHILE_WORKLIST_END(); | |
return SUCCESS; | |
} | |
@@ -3862,18 +3557,14 @@ static int is_recursive_tail_call(const zend_op_array *op_array, | |
{ | |
zend_func_info *info = ZEND_FUNC_INFO(op_array); | |
- if (info->ssa.ops && info->ssa.vars && | |
+ if (info->ssa.ops && info->ssa.vars && info->call_map && | |
info->ssa.ops[opline - op_array->opcodes].op1_use >= 0 && | |
info->ssa.vars[info->ssa.ops[opline - op_array->opcodes].op1_use].definition >= 0) { | |
zend_op *op = op_array->opcodes + info->ssa.vars[info->ssa.ops[opline - op_array->opcodes].op1_use].definition; | |
if (op->opcode == ZEND_DO_UCALL) { | |
- zend_call_info *call_info = info->callee_info; | |
- | |
- while (call_info && call_info->caller_call_opline != op) { | |
- call_info = call_info->next_callee; | |
- } | |
+ zend_call_info *call_info = info->call_map[op - op_array->opcodes]; | |
if (call_info && op_array == &call_info->callee_func->op_array) { | |
return 1; | |
} | |
@@ -4195,7 +3886,7 @@ void zend_inference_check_recursive_dependencies(zend_op_array *op_array) | |
zend_func_info *info = ZEND_FUNC_INFO(op_array); | |
zend_call_info *call_info; | |
zend_bitset worklist; | |
- int worklist_len; | |
+ int worklist_len, i; | |
ALLOCA_FLAG(use_heap); | |
if (!info->ssa.var_info || !(info->flags & ZEND_FUNC_RECURSIVE)) { | |
@@ -4212,14 +3903,12 @@ void zend_inference_check_recursive_dependencies(zend_op_array *op_array) | |
} | |
call_info = call_info->next_callee; | |
} | |
- while (!zend_bitset_empty(worklist, worklist_len)) { | |
- int i = zend_bitset_first(worklist, worklist_len); | |
- zend_bitset_excl(worklist, i); | |
+ WHILE_WORKLIST(worklist, worklist_len, i) { | |
if (!info->ssa.var_info[i].recursive) { | |
info->ssa.var_info[i].recursive = 1; | |
add_usages(op_array, &info->ssa, worklist, i); | |
} | |
- } | |
+ } WHILE_WORKLIST_END(); | |
free_alloca(worklist, use_heap); | |
} | |
diff --git a/ext/opcache/Optimizer/zend_inference.h b/ext/opcache/Optimizer/zend_inference.h | |
index 4febc99cea..25b5cba4ca 100644 | |
--- a/ext/opcache/Optimizer/zend_inference.h | |
+++ b/ext/opcache/Optimizer/zend_inference.h | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend Engine, e-SSA based Type & Range Inference | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c | |
index c88821e0e3..08ac084713 100644 | |
--- a/ext/opcache/Optimizer/zend_optimizer.c | |
+++ b/ext/opcache/Optimizer/zend_optimizer.c | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend OPcache | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
@@ -200,6 +200,11 @@ int zend_optimizer_update_op1_const(zend_op_array *op_array, | |
case ZEND_SEND_VAR_NO_REF_EX: | |
zval_ptr_dtor(val); | |
return 0; | |
+ case ZEND_VERIFY_RETURN_TYPE: | |
+ /* This would require a non-local change. | |
+ * zend_optimizer_replace_by_const() supports this. */ | |
+ zval_ptr_dtor(val); | |
+ return 0; | |
case ZEND_CONCAT: | |
case ZEND_FAST_CONCAT: | |
case ZEND_FETCH_R: | |
@@ -446,12 +451,27 @@ int zend_optimizer_replace_by_const(zend_op_array *op_array, | |
break; | |
/* In most cases IS_TMP_VAR operand may be used only once. | |
* The operands are usually destroyed by the opcode handler. | |
- * ZEND_CASE is an exception, that keeps operand unchanged, | |
- * and allows its reuse. The number of ZEND_CASE instructions | |
+ * ZEND_CASE and ZEND_FETCH_LIST are exceptions, they keeps operand | |
+ * unchanged, and allows its reuse. these instructions | |
* usually terminated by ZEND_FREE that finally kills the value. | |
*/ | |
- case ZEND_FREE: | |
- case ZEND_CASE: { | |
+ case ZEND_FETCH_LIST: { | |
+ zend_op *m = opline; | |
+ do { | |
+ if (m->opcode == ZEND_FETCH_LIST && | |
+ ZEND_OP1_TYPE(m) == type && | |
+ ZEND_OP1(m).var == var) { | |
+ zend_optimizer_update_op1_const(op_array, m, val); | |
+ } | |
+ m++; | |
+ } while (m->opcode != ZEND_FREE || ZEND_OP1_TYPE(m) != type || ZEND_OP1(m).var != var); | |
+ ZEND_ASSERT(m->opcode == ZEND_FREE && ZEND_OP1_TYPE(m) == type && ZEND_OP1(m).var == var); | |
+ MAKE_NOP(m); | |
+ zend_optimizer_remove_live_range(op_array, var); | |
+ return 1; | |
+ } | |
+ case ZEND_CASE: | |
+ case ZEND_FREE: { | |
zend_op *m, *n; | |
int brk = op_array->last_live_range; | |
zend_bool in_switch = 0; | |
@@ -501,7 +521,6 @@ int zend_optimizer_replace_by_const(zend_op_array *op_array, | |
} | |
case ZEND_VERIFY_RETURN_TYPE: { | |
zend_arg_info *ret_info = op_array->arg_info - 1; | |
- ZEND_ASSERT((opline + 1)->opcode == ZEND_RETURN || (opline + 1)->opcode == ZEND_RETURN_BY_REF); | |
if (ret_info->class_name | |
|| ret_info->type_hint == IS_CALLABLE | |
|| !ZEND_SAME_FAKE_TYPE(ret_info->type_hint, Z_TYPE_P(val)) | |
@@ -510,7 +529,13 @@ int zend_optimizer_replace_by_const(zend_op_array *op_array, | |
return 0; | |
} | |
MAKE_NOP(opline); | |
- opline++; | |
+ | |
+ /* zend_handle_loops_and_finally may inserts other oplines */ | |
+ do { | |
+ ++opline; | |
+ } while (opline->opcode != ZEND_RETURN && opline->opcode != ZEND_RETURN_BY_REF); | |
+ ZEND_ASSERT(ZEND_OP1(opline).var == var); | |
+ | |
break; | |
} | |
default: | |
@@ -953,9 +978,10 @@ int zend_optimize_script(zend_script *script, zend_long optimization_level, zend | |
} | |
for (i = 0; i < call_graph.op_arrays_count; i++) { | |
- if (call_graph.op_arrays[i]->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { | |
- func_info = ZEND_FUNC_INFO(call_graph.op_arrays[i]); | |
- if (func_info) { | |
+ func_info = ZEND_FUNC_INFO(call_graph.op_arrays[i]); | |
+ if (func_info) { | |
+ func_info->call_map = zend_build_call_map(&ctx.arena, func_info, call_graph.op_arrays[i]); | |
+ if (call_graph.op_arrays[i]->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) { | |
zend_init_func_return_info(call_graph.op_arrays[i], script, &func_info->return_info); | |
} | |
} | |
diff --git a/ext/opcache/Optimizer/zend_optimizer.h b/ext/opcache/Optimizer/zend_optimizer.h | |
index 41896b0afe..69c89d7234 100644 | |
--- a/ext/opcache/Optimizer/zend_optimizer.h | |
+++ b/ext/opcache/Optimizer/zend_optimizer.h | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend OPcache | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
diff --git a/ext/opcache/Optimizer/zend_optimizer_internal.h b/ext/opcache/Optimizer/zend_optimizer_internal.h | |
index e2e9823c78..90297ad816 100644 | |
--- a/ext/opcache/Optimizer/zend_optimizer_internal.h | |
+++ b/ext/opcache/Optimizer/zend_optimizer_internal.h | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend OPcache | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
diff --git a/ext/opcache/Optimizer/zend_ssa.c b/ext/opcache/Optimizer/zend_ssa.c | |
index 80de03b698..c902e51766 100644 | |
--- a/ext/opcache/Optimizer/zend_ssa.c | |
+++ b/ext/opcache/Optimizer/zend_ssa.c | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend Engine, SSA - Static Single Assignment Form | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
@@ -77,12 +77,12 @@ static zend_ssa_phi *add_pi( | |
} | |
phi = zend_arena_calloc(arena, 1, | |
- sizeof(zend_ssa_phi) + | |
- sizeof(int) * ssa->cfg.blocks[to].predecessors_count + | |
+ ZEND_MM_ALIGNED_SIZE(sizeof(zend_ssa_phi)) + | |
+ ZEND_MM_ALIGNED_SIZE(sizeof(int) * ssa->cfg.blocks[to].predecessors_count) + | |
sizeof(void*) * ssa->cfg.blocks[to].predecessors_count); | |
- phi->sources = (int*)(((char*)phi) + sizeof(zend_ssa_phi)); | |
+ phi->sources = (int*)(((char*)phi) + ZEND_MM_ALIGNED_SIZE(sizeof(zend_ssa_phi))); | |
memset(phi->sources, 0xff, sizeof(int) * ssa->cfg.blocks[to].predecessors_count); | |
- phi->use_chains = (zend_ssa_phi**)(((char*)phi->sources) + sizeof(int) * ssa->cfg.blocks[to].predecessors_count); | |
+ phi->use_chains = (zend_ssa_phi**)(((char*)phi->sources) + ZEND_MM_ALIGNED_SIZE(sizeof(int) * ssa->cfg.blocks[to].predecessors_count)); | |
phi->pi = from; | |
phi->var = var; | |
@@ -947,13 +947,13 @@ int zend_build_ssa(zend_arena **arena, const zend_script *script, const zend_op_ | |
if (!zend_bitset_empty(phi + j * set_size, set_size)) { | |
ZEND_BITSET_REVERSE_FOREACH(phi + j * set_size, set_size, i) { | |
zend_ssa_phi *phi = zend_arena_calloc(arena, 1, | |
- sizeof(zend_ssa_phi) + | |
- sizeof(int) * blocks[j].predecessors_count + | |
+ ZEND_MM_ALIGNED_SIZE(sizeof(zend_ssa_phi)) + | |
+ ZEND_MM_ALIGNED_SIZE(sizeof(int) * blocks[j].predecessors_count) + | |
sizeof(void*) * blocks[j].predecessors_count); | |
- phi->sources = (int*)(((char*)phi) + sizeof(zend_ssa_phi)); | |
+ phi->sources = (int*)(((char*)phi) + ZEND_MM_ALIGNED_SIZE(sizeof(zend_ssa_phi))); | |
memset(phi->sources, 0xff, sizeof(int) * blocks[j].predecessors_count); | |
- phi->use_chains = (zend_ssa_phi**)(((char*)phi->sources) + sizeof(int) * ssa->cfg.blocks[j].predecessors_count); | |
+ phi->use_chains = (zend_ssa_phi**)(((char*)phi->sources) + ZEND_MM_ALIGNED_SIZE(sizeof(int) * ssa->cfg.blocks[j].predecessors_count)); | |
phi->pi = -1; | |
phi->var = i; | |
diff --git a/ext/opcache/Optimizer/zend_ssa.h b/ext/opcache/Optimizer/zend_ssa.h | |
index 653a61fc10..5e03f8ba69 100644 | |
--- a/ext/opcache/Optimizer/zend_ssa.h | |
+++ b/ext/opcache/Optimizer/zend_ssa.h | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend Engine, SSA - Static Single Assignment Form | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
diff --git a/ext/opcache/Optimizer/zend_worklist.h b/ext/opcache/Optimizer/zend_worklist.h | |
index a1db05482b..73c0bca854 100644 | |
--- a/ext/opcache/Optimizer/zend_worklist.h | |
+++ b/ext/opcache/Optimizer/zend_worklist.h | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend Engine | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
@@ -77,10 +77,10 @@ typedef struct _zend_worklist { | |
} zend_worklist; | |
#define ZEND_WORKLIST_ALLOCA(w, _len, use_heap) do { \ | |
- (w)->stack.buf = (int*)do_alloca(sizeof(int) * _len + sizeof(zend_ulong) * zend_bitset_len(_len), use_heap); \ | |
+ (w)->stack.buf = (int*)do_alloca(ZEND_MM_ALIGNED_SIZE(sizeof(int) * _len) + sizeof(zend_ulong) * zend_bitset_len(_len), use_heap); \ | |
(w)->stack.len = 0; \ | |
(w)->stack.capacity = _len; \ | |
- (w)->visited = (zend_bitset)((w)->stack.buf + _len); \ | |
+ (w)->visited = (zend_bitset)((char*)(w)->stack.buf + ZEND_MM_ALIGNED_SIZE(sizeof(int) * _len)); \ | |
memset((w)->visited, 0, sizeof(zend_ulong) * zend_bitset_len(_len)); \ | |
} while (0) | |
diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c | |
index 0a2304bbc9..d316fd83f4 100644 | |
--- a/ext/opcache/ZendAccelerator.c | |
+++ b/ext/opcache/ZendAccelerator.c | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend OPcache | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
@@ -118,6 +118,8 @@ static zend_string *(*accelerator_orig_zend_resolve_path)(const char *filename, | |
static void (*orig_chdir)(INTERNAL_FUNCTION_PARAMETERS) = NULL; | |
static ZEND_INI_MH((*orig_include_path_on_modify)) = NULL; | |
+static void accel_gen_system_id(void); | |
+ | |
#ifdef ZEND_WIN32 | |
# define INCREMENT(v) InterlockedIncrement64(&ZCSG(v)) | |
# define DECREMENT(v) InterlockedDecrement64(&ZCSG(v)) | |
@@ -585,7 +587,7 @@ static void accel_use_shm_interned_strings(void) | |
for (j = 0; j < ce->constants_table.nNumUsed; j++) { | |
q = ce->constants_table.arData + j; | |
- if (!Z_TYPE(q->val) == IS_UNDEF) continue; | |
+ if (Z_TYPE(q->val) == IS_UNDEF) continue; | |
if (q->key) { | |
q->key = accel_new_interned_string(q->key); | |
} | |
@@ -595,7 +597,7 @@ static void accel_use_shm_interned_strings(void) | |
/* constant hash keys */ | |
for (idx = 0; idx < EG(zend_constants)->nNumUsed; idx++) { | |
p = EG(zend_constants)->arData + idx; | |
- if (!Z_TYPE(p->val) == IS_UNDEF) continue; | |
+ if (Z_TYPE(p->val) == IS_UNDEF) continue; | |
if (p->key) { | |
p->key = accel_new_interned_string(p->key); | |
} | |
@@ -1777,10 +1779,10 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type) | |
file_handle->type == ZEND_HANDLE_FILENAME && | |
UNEXPECTED(access(ZSTR_VAL(persistent_script->script.filename), R_OK) != 0)) { | |
if (type == ZEND_REQUIRE) { | |
- zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename TSRMLS_CC); | |
+ zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename); | |
zend_bailout(); | |
} else { | |
- zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename TSRMLS_CC); | |
+ zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename); | |
} | |
return NULL; | |
} | |
@@ -2557,6 +2559,9 @@ static void accel_globals_ctor(zend_accel_globals *accel_globals) | |
ZEND_TSRMLS_CACHE_UPDATE(); | |
#endif | |
memset(accel_globals, 0, sizeof(zend_accel_globals)); | |
+ | |
+ /* TODO refactor to init this just once. */ | |
+ accel_gen_system_id(); | |
} | |
static void accel_globals_internal_func_dtor(zval *zv) | |
@@ -2941,11 +2946,18 @@ void accel_shutdown(void) | |
void zend_accel_schedule_restart(zend_accel_restart_reason reason) | |
{ | |
+ const char *zend_accel_restart_reason_text[ACCEL_RESTART_USER + 1] = { | |
+ "out of memory", | |
+ "hash overflow", | |
+ "user", | |
+ }; | |
+ | |
if (ZCSG(restart_pending)) { | |
/* don't schedule twice */ | |
return; | |
} | |
- zend_accel_error(ACCEL_LOG_DEBUG, "Restart Scheduled!"); | |
+ zend_accel_error(ACCEL_LOG_DEBUG, "Restart Scheduled! Reason: %s", | |
+ zend_accel_restart_reason_text[reason]); | |
HANDLE_BLOCK_INTERRUPTIONS(); | |
SHM_UNPROTECT(); | |
@@ -3011,7 +3023,7 @@ ZEND_EXT_API zend_extension zend_extension_entry = { | |
PHP_VERSION, /* version */ | |
"Zend Technologies", /* author */ | |
"http://www.zend.com/", /* URL */ | |
- "Copyright (c) 1999-2016", /* copyright */ | |
+ "Copyright (c) 1999-2017", /* copyright */ | |
accel_startup, /* startup */ | |
NULL, /* shutdown */ | |
accel_activate, /* per-script activation */ | |
diff --git a/ext/opcache/ZendAccelerator.h b/ext/opcache/ZendAccelerator.h | |
index aa357ecab2..c527911926 100644 | |
--- a/ext/opcache/ZendAccelerator.h | |
+++ b/ext/opcache/ZendAccelerator.h | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend OPcache | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
diff --git a/ext/opcache/shared_alloc_mmap.c b/ext/opcache/shared_alloc_mmap.c | |
index 2c3dc58125..24e40c2ae0 100644 | |
--- a/ext/opcache/shared_alloc_mmap.c | |
+++ b/ext/opcache/shared_alloc_mmap.c | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend OPcache | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
diff --git a/ext/opcache/shared_alloc_posix.c b/ext/opcache/shared_alloc_posix.c | |
index 994f3ca609..94854f1c9d 100644 | |
--- a/ext/opcache/shared_alloc_posix.c | |
+++ b/ext/opcache/shared_alloc_posix.c | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend OPcache | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
diff --git a/ext/opcache/shared_alloc_shm.c b/ext/opcache/shared_alloc_shm.c | |
index 6e23ded836..36b93b0fef 100644 | |
--- a/ext/opcache/shared_alloc_shm.c | |
+++ b/ext/opcache/shared_alloc_shm.c | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend OPcache | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
diff --git a/ext/opcache/shared_alloc_win32.c b/ext/opcache/shared_alloc_win32.c | |
index cdfd90c14b..0cf65cf90a 100644 | |
--- a/ext/opcache/shared_alloc_win32.c | |
+++ b/ext/opcache/shared_alloc_win32.c | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend OPcache | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
@@ -102,6 +102,9 @@ static char *get_mmap_base_file(void) | |
} | |
GetTempPath(MAXPATHLEN, windir); | |
l = strlen(windir); | |
+ if ('\\' == windir[l-1]) { | |
+ l--; | |
+ } | |
snprintf(windir + l, sizeof(windir) - l - 1, "\\%s@%s@%.32s", ACCEL_FILEMAP_BASE, uname, ZCG(system_id)); | |
free(uname); | |
diff --git a/ext/opcache/tests/blacklist-win32.phpt b/ext/opcache/tests/blacklist-win32.phpt | |
index 1e479b6c2e..fab0698f7f 100644 | |
--- a/ext/opcache/tests/blacklist-win32.phpt | |
+++ b/ext/opcache/tests/blacklist-win32.phpt | |
@@ -18,7 +18,7 @@ $conf[4] = preg_replace("!^\\Q".dirname(__FILE__)."\\E!", "__DIR__", $conf[4]); | |
print_r($conf); | |
include("blacklist.inc"); | |
$status = opcache_get_status(); | |
-print_r(count($status['scripts'])); | |
+print_r(count($status['scripts']) > 0); | |
?> | |
--EXPECTF-- | |
Array | |
diff --git a/ext/opcache/tests/bug73583.phpt b/ext/opcache/tests/bug73583.phpt | |
new file mode 100644 | |
index 0000000000..e947b451c9 | |
--- /dev/null | |
+++ b/ext/opcache/tests/bug73583.phpt | |
@@ -0,0 +1,19 @@ | |
+--TEST-- | |
+Bug #73583 (Segfaults when conditionally declared class and function have the same name) | |
+--INI-- | |
+opcache.enable=1 | |
+opcache.enable_cli=1 | |
+opcache.optimization_level=0x4ff | |
+opcache.file_update_protection=0 | |
+--SKIPIF-- | |
+<?php require_once('skipif.inc'); ?> | |
+--FILE-- | |
+<?php | |
+if (true) { | |
+ class A { } | |
+ function A() { } | |
+ function A() { } | |
+} | |
+?> | |
+--EXPECTF-- | |
+Fatal error: Cannot redeclare A() (previously declared in %sbug73583.php:4) in %sbug73583.php on line 5 | |
diff --git a/ext/opcache/tests/bug73654.phpt b/ext/opcache/tests/bug73654.phpt | |
new file mode 100644 | |
index 0000000000..164e10829c | |
--- /dev/null | |
+++ b/ext/opcache/tests/bug73654.phpt | |
@@ -0,0 +1,17 @@ | |
+--TEST-- | |
+Bug #73654: Segmentation fault in zend_call_function | |
+--FILE-- | |
+<?php | |
+echo xyz(); | |
+ | |
+function x () : string { | |
+ return 'x'; | |
+} | |
+ | |
+function xyz() : string { | |
+ return x().'yz'; | |
+} | |
+ | |
+?> | |
+--EXPECT-- | |
+xyz | |
diff --git a/ext/opcache/tests/bug73668.phpt b/ext/opcache/tests/bug73668.phpt | |
new file mode 100644 | |
index 0000000000..aac5c9e65c | |
--- /dev/null | |
+++ b/ext/opcache/tests/bug73668.phpt | |
@@ -0,0 +1,8 @@ | |
+--TEST-- | |
+Bug #73668: "SIGFPE Arithmetic exception" in opcache when divide by minus 1 | |
+--FILE-- | |
+<?php | |
+$a/-1; | |
+?> | |
+--EXPECTF-- | |
+Notice: Undefined variable: a in %s on line %d | |
diff --git a/ext/opcache/tests/bug73746.phpt b/ext/opcache/tests/bug73746.phpt | |
new file mode 100644 | |
index 0000000000..c97833abcc | |
--- /dev/null | |
+++ b/ext/opcache/tests/bug73746.phpt | |
@@ -0,0 +1,28 @@ | |
+--TEST-- | |
+Bug #73746 (Method that returns string returns UNKNOWN:0 instead) | |
+--FILE-- | |
+<?php | |
+namespace Core\Bundle\Service\Property\Room\Rooms; | |
+ | |
+class CountryMapping | |
+{ | |
+ const CZ = 'CZ'; | |
+ const EN = 'EN'; | |
+ | |
+ public function get(string $countryIsoCode = null) : string // Works correctly if return type is removed | |
+ { | |
+ switch (strtoupper($countryIsoCode)) { | |
+ case 'CZ': | |
+ case 'SK': | |
+ return self::CZ; // Works correctly if changed to CountryMapping::CZ | |
+ default: | |
+ return self::EN; // Works correctly if changed to CountryMapping::EN | |
+ } | |
+ } | |
+} | |
+ | |
+$mapping = new CountryMapping(); | |
+var_dump($mapping->get('CZ')); | |
+?> | |
+--EXPECT-- | |
+string(2) "CZ" | |
diff --git a/ext/opcache/tests/bug73789.phpt b/ext/opcache/tests/bug73789.phpt | |
new file mode 100644 | |
index 0000000000..142d5229f9 | |
--- /dev/null | |
+++ b/ext/opcache/tests/bug73789.phpt | |
@@ -0,0 +1,30 @@ | |
+--TEST-- | |
+Bug #73789 (Strange behavior of class constants in switch/case block) | |
+--FILE-- | |
+<?php | |
+class Lexer | |
+{ | |
+ const T_NONE = 1; | |
+ const T_STRING = 2; | |
+ const T_DOT = 8; | |
+ public function getType($value): int | |
+ { | |
+ $type = self::T_NONE; | |
+ switch (true) { | |
+ case ctype_alpha($value[0]): | |
+ $name = 'Lexer::T_' . strtoupper($value); | |
+ $type = constant($name); | |
+ if ($type > 100) { | |
+ return $type; | |
+ } | |
+ return self::T_STRING; | |
+ case $value === '.': | |
+ return self::T_DOT; | |
+ default: | |
+ } | |
+ return $type; | |
+ } | |
+} | |
+var_dump((new Lexer())->getType("dot")); | |
+--EXPECT-- | |
+int(2) | |
diff --git a/ext/opcache/tests/bug73847.phpt b/ext/opcache/tests/bug73847.phpt | |
new file mode 100644 | |
index 0000000000..7010dfbfb7 | |
--- /dev/null | |
+++ b/ext/opcache/tests/bug73847.phpt | |
@@ -0,0 +1,44 @@ | |
+--TEST-- | |
+Bug #73847: Recursion when a variable is redefined as array | |
+--FILE-- | |
+<?php | |
+function test() { | |
+ $a = 42; | |
+ $a = array($a); | |
+ var_dump($a); | |
+ | |
+ $a = 42; | |
+ $a = array($a => 24); | |
+ var_dump($a); | |
+ | |
+ $a = 42; | |
+ $a = array($a, 24); | |
+ var_dump($a); | |
+ | |
+ $a = 42; | |
+ $a = array(24, $a); | |
+ var_dump($a); | |
+} | |
+test(); | |
+?> | |
+--EXPECT-- | |
+array(1) { | |
+ [0]=> | |
+ int(42) | |
+} | |
+array(1) { | |
+ [42]=> | |
+ int(24) | |
+} | |
+array(2) { | |
+ [0]=> | |
+ int(42) | |
+ [1]=> | |
+ int(24) | |
+} | |
+array(2) { | |
+ [0]=> | |
+ int(24) | |
+ [1]=> | |
+ int(42) | |
+} | |
diff --git a/ext/opcache/tests/bug74019.phpt b/ext/opcache/tests/bug74019.phpt | |
new file mode 100644 | |
index 0000000000..210e223c82 | |
--- /dev/null | |
+++ b/ext/opcache/tests/bug74019.phpt | |
@@ -0,0 +1,25 @@ | |
+--TEST-- | |
+Bug #74019 (Segfault with list) | |
+--INI-- | |
+opcache.enable=1 | |
+opcache.enable_cli=1 | |
+--SKIPIF-- | |
+<?php require_once('skipif.inc'); ?> | |
+--FILE-- | |
+<?php | |
+ | |
+class A { | |
+ public function seg() { | |
+ list($a, $b) = A::CONSTS; | |
+ var_dump($a, $b); | |
+ return; | |
+ } | |
+ const CONSTS = [1, 2]; | |
+} | |
+ | |
+$a = new A; | |
+$a->seg(); | |
+?> | |
+--EXPECT-- | |
+int(1) | |
+int(2) | |
diff --git a/ext/opcache/tests/bug74152.phpt b/ext/opcache/tests/bug74152.phpt | |
new file mode 100644 | |
index 0000000000..f51c26b621 | |
--- /dev/null | |
+++ b/ext/opcache/tests/bug74152.phpt | |
@@ -0,0 +1,27 @@ | |
+--TEST-- | |
+Bug #74152 (if statement says true to a null variable) | |
+--INI-- | |
+opcache.enable=1 | |
+opcache.enable_cli=1 | |
+opcache.optimization_level=-1 | |
+--SKIPIF-- | |
+<?php require_once('skipif.inc'); ?> | |
+--FILE-- | |
+<?php | |
+ | |
+$foo = 'foo'; | |
+ | |
+$bar = null; | |
+ | |
+switch ($foo) { | |
+default: | |
+case 'foo': | |
+ if ($bar) { | |
+ echo 'true'; | |
+ } else { | |
+ echo 'false'; | |
+ } | |
+} | |
+?> | |
+--EXPECT-- | |
+false | |
diff --git a/ext/opcache/tests/issue0115.phpt b/ext/opcache/tests/issue0115.phpt | |
index 0dfdd9f0eb..26d99080eb 100644 | |
--- a/ext/opcache/tests/issue0115.phpt | |
+++ b/ext/opcache/tests/issue0115.phpt | |
@@ -16,28 +16,28 @@ require "phar://this/index.php"; | |
__HALT_COMPILER(); ?>'; | |
$p = new Phar(__DIR__ . '/issue0115_1.phar.php', 0, 'this'); | |
$p['index.php'] = '<?php | |
-echo "Hello from Index 1.\n"; | |
-require_once "phar://this/hello.php"; | |
+ echo "Hello from Index 1.\n"; | |
+ require_once "phar://this/hello.php"; | |
'; | |
-$p['hello.php'] = "Hello World 1!\n"; | |
+$p['hello.php'] = "Hello World 1!\n"; | |
$p->setStub($stub); | |
unset($p); | |
$p = new Phar(__DIR__ . '/issue0115_2.phar.php', 0, 'this'); | |
$p['index.php'] = '<?php | |
-echo "Hello from Index 2.\n"; | |
-require_once "phar://this/hello.php"; | |
+ echo "Hello from Index 2.\n"; | |
+ require_once "phar://this/hello.php"; | |
'; | |
-$p['hello.php'] = "Hello World 2!\n"; | |
+$p['hello.php'] = "Hello World 2!\n"; | |
$p->setStub($stub); | |
unset($p); | |
include "php_cli_server.inc"; | |
-php_cli_server_start('-d opcache.enable=1 -d opcache.enable_cli=1'); | |
+php_cli_server_start('-d opcache.enable=1 -d opcache.enable_cli=1 -d extension=phar.'.PHP_SHLIB_SUFFIX); | |
echo file_get_contents('http://' . PHP_CLI_SERVER_ADDRESS . '/issue0115_1.phar.php'); | |
echo file_get_contents('http://' . PHP_CLI_SERVER_ADDRESS . '/issue0115_2.phar.php'); | |
?> | |
--CLEAN-- | |
-<?php | |
+<?php | |
@unlink(__DIR__ . '/issue0115_1.phar.php'); | |
@unlink(__DIR__ . '/issue0115_2.phar.php'); | |
?> | |
diff --git a/ext/opcache/tests/issue0149.phpt b/ext/opcache/tests/issue0149.phpt | |
index 8c7f1bb7e0..ba57623fce 100644 | |
--- a/ext/opcache/tests/issue0149.phpt | |
+++ b/ext/opcache/tests/issue0149.phpt | |
@@ -20,13 +20,13 @@ $p->setStub($stub); | |
unset($p); | |
include "php_cli_server.inc"; | |
-php_cli_server_start('-d opcache.enable=1 -d opcache.enable_cli=1'); | |
+php_cli_server_start('-d opcache.enable=1 -d opcache.enable_cli=1 -d extension=phar.'.PHP_SHLIB_SUFFIX); | |
echo file_get_contents('http://' . PHP_CLI_SERVER_ADDRESS . '/issue0149.phar.php'); | |
echo file_get_contents('http://' . PHP_CLI_SERVER_ADDRESS . '/issue0149.phar.php'); | |
echo file_get_contents('http://' . PHP_CLI_SERVER_ADDRESS . '/issue0149.phar.php'); | |
?> | |
--CLEAN-- | |
-<?php | |
+<?php | |
@unlink(__DIR__ . '/issue0149.phar.php'); | |
?> | |
--EXPECT-- | |
diff --git a/ext/opcache/tests/log_verbosity_bug.phpt b/ext/opcache/tests/log_verbosity_bug.phpt | |
index 725b8889f4..2e5d7a9add 100644 | |
--- a/ext/opcache/tests/log_verbosity_bug.phpt | |
+++ b/ext/opcache/tests/log_verbosity_bug.phpt | |
@@ -7,6 +7,7 @@ The process should die regardless of the log_verbosity_level. | |
--INI-- | |
opcache.enable=1 | |
opcache.enable_cli=1 | |
+opcache.file_cache_only=0 | |
opcache.memory_consumption=999999999 | |
opcache.log_verbosity_level=-1 | |
--SKIPIF-- | |
diff --git a/ext/opcache/tests/php_cli_server.inc b/ext/opcache/tests/php_cli_server.inc | |
index 0878bfafc0..456ed663b8 100644 | |
--- a/ext/opcache/tests/php_cli_server.inc | |
+++ b/ext/opcache/tests/php_cli_server.inc | |
@@ -20,28 +20,51 @@ function php_cli_server_start($ini = "") { | |
$cmd = "exec {$php_executable} -t {$doc_root} $ini -S " . PHP_CLI_SERVER_ADDRESS . " 2>/dev/null"; | |
$handle = proc_open($cmd, $descriptorspec, $pipes, $doc_root); | |
} | |
- | |
+ | |
// note: even when server prints 'Listening on localhost:8964...Press Ctrl-C to quit.' | |
// it might not be listening yet...need to wait until fsockopen() call returns | |
- $i = 0; | |
- while (($i++ < 30) && !($fp = @fsockopen(PHP_CLI_SERVER_HOSTNAME, PHP_CLI_SERVER_PORT))) { | |
- usleep(10000); | |
- } | |
+ $error = "Unable to connect to server\n"; | |
+ for ($i=0; $i < 60; $i++) { | |
+ usleep(50000); // 50ms per try | |
+ $status = proc_get_status($handle); | |
+ $fp = @fsockopen(PHP_CLI_SERVER_HOSTNAME, PHP_CLI_SERVER_PORT); | |
+ // Failure, the server is no longer running | |
+ if (!($status && $status['running'])) { | |
+ $error = "Server is not running\n"; | |
+ break; | |
+ } | |
+ // Success, Connected to servers | |
+ if ($fp) { | |
+ $error = ''; | |
+ break; | |
+ } | |
+ } | |
- if ($fp) { | |
- fclose($fp); | |
- } | |
+ if ($fp) { | |
+ fclose($fp); | |
+ } | |
+ | |
+ if ($error) { | |
+ echo $error; | |
+ proc_terminate($handle); | |
+ exit(1); | |
+ } | |
register_shutdown_function( | |
function($handle) { | |
proc_terminate($handle); | |
+ /* Wait for server to shutdown */ | |
+ for ($i = 0; $i < 60; $i++) { | |
+ $status = proc_get_status($handle); | |
+ if (!($status && $status['running'])) { | |
+ break; | |
+ } | |
+ usleep(50000); | |
+ } | |
}, | |
- $handle | |
- ); | |
- // don't bother sleeping, server is already up | |
- // server can take a variable amount of time to be up, so just sleeping a guessed amount of time | |
- // does not work. this is why tests sometimes pass and sometimes fail. to get a reliable pass | |
- // sleeping doesn't work. | |
+ $handle | |
+ ); | |
+ | |
} | |
?> | |
diff --git a/ext/opcache/tests/basic_logging.phpt b/ext/opcache/tests/zzz_basic_logging.phpt | |
similarity index 77% | |
rename from ext/opcache/tests/basic_logging.phpt | |
rename to ext/opcache/tests/zzz_basic_logging.phpt | |
index c62ea039a5..f0ecd6fbaa 100644 | |
--- a/ext/opcache/tests/basic_logging.phpt | |
+++ b/ext/opcache/tests/zzz_basic_logging.phpt | |
@@ -7,13 +7,18 @@ outputs the correct logging at the highest log_verbosity_level | |
--INI-- | |
opcache.enable=1 | |
opcache.enable_cli=1 | |
+opcache.file_cache_only=0 | |
opcache.log_verbosity_level=4 | |
--SKIPIF-- | |
<?php require_once('skipif.inc'); ?> | |
--FILE-- | |
<?php | |
echo "Foo Bar\n"; | |
+opcache_reset(); | |
+echo "Opcache reset"; | |
?> | |
--EXPECTF-- | |
%s Message Cached script '%sbasic_logging%s' | |
Foo Bar | |
+%s Debug Restart Scheduled! Reason: user | |
+Opcache reset | |
diff --git a/ext/opcache/zend_accelerator_blacklist.c b/ext/opcache/zend_accelerator_blacklist.c | |
index db61e1e9d3..bb4a5d22c8 100644 | |
--- a/ext/opcache/zend_accelerator_blacklist.c | |
+++ b/ext/opcache/zend_accelerator_blacklist.c | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend OPcache | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
diff --git a/ext/opcache/zend_accelerator_blacklist.h b/ext/opcache/zend_accelerator_blacklist.h | |
index 13197a661c..863f9ed165 100644 | |
--- a/ext/opcache/zend_accelerator_blacklist.h | |
+++ b/ext/opcache/zend_accelerator_blacklist.h | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend OPcache | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
diff --git a/ext/opcache/zend_accelerator_debug.c b/ext/opcache/zend_accelerator_debug.c | |
index 12f80ab79b..4932999b62 100644 | |
--- a/ext/opcache/zend_accelerator_debug.c | |
+++ b/ext/opcache/zend_accelerator_debug.c | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend OPcache | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
diff --git a/ext/opcache/zend_accelerator_debug.h b/ext/opcache/zend_accelerator_debug.h | |
index 4b8d82b4ac..6445254232 100644 | |
--- a/ext/opcache/zend_accelerator_debug.h | |
+++ b/ext/opcache/zend_accelerator_debug.h | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend OPcache | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
diff --git a/ext/opcache/zend_accelerator_hash.c b/ext/opcache/zend_accelerator_hash.c | |
index 7ec64cec1f..803dc6a25e 100644 | |
--- a/ext/opcache/zend_accelerator_hash.c | |
+++ b/ext/opcache/zend_accelerator_hash.c | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend OPcache | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
diff --git a/ext/opcache/zend_accelerator_hash.h b/ext/opcache/zend_accelerator_hash.h | |
index 3aa2451d1c..1c5b82280a 100644 | |
--- a/ext/opcache/zend_accelerator_hash.h | |
+++ b/ext/opcache/zend_accelerator_hash.h | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend OPcache | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
diff --git a/ext/opcache/zend_accelerator_module.c b/ext/opcache/zend_accelerator_module.c | |
index 6eace96398..bd83855e7d 100644 | |
--- a/ext/opcache/zend_accelerator_module.c | |
+++ b/ext/opcache/zend_accelerator_module.c | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend OPcache | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
@@ -107,8 +107,6 @@ static ZEND_INI_MH(OnUpdateMemoryConsumption) | |
#else | |
char *base = (char *) ts_resource(*((int *) mh_arg2)); | |
#endif | |
- zend_long megabyte, overflow; | |
- double dummy; | |
/* keep the compiler happy */ | |
(void)entry; (void)mh_arg2; (void)mh_arg3; (void)stage; | |
@@ -132,10 +130,10 @@ static ZEND_INI_MH(OnUpdateMemoryConsumption) | |
ini_entry->value = zend_string_init(new_new_value, 1, 1); | |
} | |
- megabyte = 1024 * 1024; | |
- ZEND_SIGNED_MULTIPLY_LONG(memsize, megabyte, *p, dummy, overflow); | |
- if (UNEXPECTED(overflow)) { | |
+ if (UNEXPECTED(memsize > ZEND_ULONG_MAX / (1024 * 1024))) { | |
*p = ZEND_ULONG_MAX; | |
+ } else { | |
+ *p = memsize * (1024 * 1024); | |
} | |
return SUCCESS; | |
} | |
@@ -287,9 +285,9 @@ ZEND_INI_BEGIN() | |
STD_PHP_INI_BOOLEAN("opcache.revalidate_path" , "0", PHP_INI_ALL , OnUpdateBool, accel_directives.revalidate_path , zend_accel_globals, accel_globals) | |
STD_PHP_INI_ENTRY("opcache.log_verbosity_level" , "1" , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.log_verbosity_level, zend_accel_globals, accel_globals) | |
- STD_PHP_INI_ENTRY("opcache.memory_consumption" , "64" , PHP_INI_SYSTEM, OnUpdateMemoryConsumption, accel_directives.memory_consumption, zend_accel_globals, accel_globals) | |
- STD_PHP_INI_ENTRY("opcache.interned_strings_buffer", "4" , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.interned_strings_buffer, zend_accel_globals, accel_globals) | |
- STD_PHP_INI_ENTRY("opcache.max_accelerated_files" , "2000", PHP_INI_SYSTEM, OnUpdateMaxAcceleratedFiles, accel_directives.max_accelerated_files, zend_accel_globals, accel_globals) | |
+ STD_PHP_INI_ENTRY("opcache.memory_consumption" , "128" , PHP_INI_SYSTEM, OnUpdateMemoryConsumption, accel_directives.memory_consumption, zend_accel_globals, accel_globals) | |
+ STD_PHP_INI_ENTRY("opcache.interned_strings_buffer", "8" , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.interned_strings_buffer, zend_accel_globals, accel_globals) | |
+ STD_PHP_INI_ENTRY("opcache.max_accelerated_files" , "10000", PHP_INI_SYSTEM, OnUpdateMaxAcceleratedFiles, accel_directives.max_accelerated_files, zend_accel_globals, accel_globals) | |
STD_PHP_INI_ENTRY("opcache.max_wasted_percentage" , "5" , PHP_INI_SYSTEM, OnUpdateMaxWastedPercentage, accel_directives.max_wasted_percentage, zend_accel_globals, accel_globals) | |
STD_PHP_INI_ENTRY("opcache.consistency_checks" , "0" , PHP_INI_ALL , OnUpdateLong, accel_directives.consistency_checks, zend_accel_globals, accel_globals) | |
STD_PHP_INI_ENTRY("opcache.force_restart_timeout" , "180" , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.force_restart_timeout, zend_accel_globals, accel_globals) | |
@@ -306,7 +304,7 @@ ZEND_INI_BEGIN() | |
STD_PHP_INI_ENTRY("opcache.optimization_level" , DEFAULT_OPTIMIZATION_LEVEL , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.optimization_level, zend_accel_globals, accel_globals) | |
STD_PHP_INI_ENTRY("opcache.opt_debug_level" , "0" , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.opt_debug_level, zend_accel_globals, accel_globals) | |
STD_PHP_INI_BOOLEAN("opcache.enable_file_override" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.file_override_enabled, zend_accel_globals, accel_globals) | |
- STD_PHP_INI_BOOLEAN("opcache.enable_cli" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.enable_cli, zend_accel_globals, accel_globals) | |
+ STD_PHP_INI_BOOLEAN("opcache.enable_cli" , "1" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.enable_cli, zend_accel_globals, accel_globals) | |
STD_PHP_INI_ENTRY("opcache.error_log" , "" , PHP_INI_SYSTEM, OnUpdateString, accel_directives.error_log, zend_accel_globals, accel_globals) | |
STD_PHP_INI_ENTRY("opcache.restrict_api" , "" , PHP_INI_SYSTEM, OnUpdateString, accel_directives.restrict_api, zend_accel_globals, accel_globals) | |
diff --git a/ext/opcache/zend_accelerator_module.h b/ext/opcache/zend_accelerator_module.h | |
index f519eba718..00321ceb67 100644 | |
--- a/ext/opcache/zend_accelerator_module.h | |
+++ b/ext/opcache/zend_accelerator_module.h | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend OPcache | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
diff --git a/ext/opcache/zend_accelerator_util_funcs.c b/ext/opcache/zend_accelerator_util_funcs.c | |
index 61c9c15d2b..3d845f389e 100644 | |
--- a/ext/opcache/zend_accelerator_util_funcs.c | |
+++ b/ext/opcache/zend_accelerator_util_funcs.c | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend OPcache | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
diff --git a/ext/opcache/zend_accelerator_util_funcs.h b/ext/opcache/zend_accelerator_util_funcs.h | |
index 4cfd77d4ed..ef5f0eb9e2 100644 | |
--- a/ext/opcache/zend_accelerator_util_funcs.h | |
+++ b/ext/opcache/zend_accelerator_util_funcs.h | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend OPcache | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c | |
index 6d34851352..dea427fcaf 100644 | |
--- a/ext/opcache/zend_file_cache.c | |
+++ b/ext/opcache/zend_file_cache.c | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend OPcache | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
@@ -359,6 +359,25 @@ static void zend_file_cache_serialize_op_array(zend_op_array *op_arra | |
zend_file_cache_serialize_hash(ht, script, info, buf, zend_file_cache_serialize_zval); | |
} | |
+ if (op_array->scope && !IS_SERIALIZED(op_array->opcodes)) { | |
+ if (UNEXPECTED(zend_shared_alloc_get_xlat_entry(op_array->opcodes))) { | |
+ op_array->refcount = (uint32_t*)(intptr_t)-1; | |
+ SERIALIZE_PTR(op_array->literals); | |
+ SERIALIZE_PTR(op_array->opcodes); | |
+ SERIALIZE_PTR(op_array->arg_info); | |
+ SERIALIZE_PTR(op_array->vars); | |
+ SERIALIZE_STR(op_array->function_name); | |
+ SERIALIZE_STR(op_array->filename); | |
+ SERIALIZE_PTR(op_array->live_range); | |
+ SERIALIZE_PTR(op_array->scope); | |
+ SERIALIZE_STR(op_array->doc_comment); | |
+ SERIALIZE_PTR(op_array->try_catch_array); | |
+ SERIALIZE_PTR(op_array->prototype); | |
+ return; | |
+ } | |
+ zend_shared_alloc_register_xlat_entry(op_array->opcodes, op_array->opcodes); | |
+ } | |
+ | |
if (op_array->literals && !IS_SERIALIZED(op_array->literals)) { | |
zval *p, *end; | |
@@ -937,6 +956,22 @@ static void zend_file_cache_unserialize_op_array(zend_op_array *op_arr | |
script, buf, zend_file_cache_unserialize_zval, ZVAL_PTR_DTOR); | |
} | |
+ if (op_array->refcount) { | |
+ op_array->refcount = NULL; | |
+ UNSERIALIZE_PTR(op_array->literals); | |
+ UNSERIALIZE_PTR(op_array->opcodes); | |
+ UNSERIALIZE_PTR(op_array->arg_info); | |
+ UNSERIALIZE_PTR(op_array->vars); | |
+ UNSERIALIZE_STR(op_array->function_name); | |
+ UNSERIALIZE_STR(op_array->filename); | |
+ UNSERIALIZE_PTR(op_array->live_range); | |
+ UNSERIALIZE_PTR(op_array->scope); | |
+ UNSERIALIZE_STR(op_array->doc_comment); | |
+ UNSERIALIZE_PTR(op_array->try_catch_array); | |
+ UNSERIALIZE_PTR(op_array->prototype); | |
+ return; | |
+ } | |
+ | |
if (op_array->literals && !IS_UNSERIALIZED(op_array->literals)) { | |
zval *p, *end; | |
diff --git a/ext/opcache/zend_file_cache.h b/ext/opcache/zend_file_cache.h | |
index 69e8acd1d3..a47410dda4 100644 | |
--- a/ext/opcache/zend_file_cache.h | |
+++ b/ext/opcache/zend_file_cache.h | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend OPcache | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c | |
index 24a3d21ca2..9574e43d6f 100644 | |
--- a/ext/opcache/zend_persist.c | |
+++ b/ext/opcache/zend_persist.c | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend OPcache | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
@@ -33,6 +33,18 @@ | |
#define zend_accel_memdup(p, size) \ | |
_zend_shared_memdup((void*)p, size, 0) | |
+#ifdef HAVE_OPCACHE_FILE_CACHE | |
+#define zend_set_str_gc_flags(str) do { \ | |
+ if (ZCG(accel_directives).file_cache_only) { \ | |
+ GC_FLAGS(str) = IS_STR_INTERNED; \ | |
+ } else { \ | |
+ GC_FLAGS(str) = IS_STR_INTERNED | IS_STR_PERMANENT; \ | |
+ } \ | |
+} while (0) | |
+#else | |
+#define zend_set_str_gc_flags(str) GC_FLAGS(str) = IS_STR_INTERNED | IS_STR_PERMANENT | |
+#endif | |
+ | |
#define zend_accel_store_string(str) do { \ | |
zend_string *new_str = zend_shared_alloc_get_xlat_entry(str); \ | |
if (new_str) { \ | |
@@ -43,13 +55,13 @@ | |
zend_string_release(str); \ | |
str = new_str; \ | |
zend_string_hash_val(str); \ | |
- GC_FLAGS(str) = IS_STR_INTERNED | IS_STR_PERMANENT; \ | |
+ zend_set_str_gc_flags(str); \ | |
} \ | |
} while (0) | |
#define zend_accel_memdup_string(str) do { \ | |
str = zend_accel_memdup(str, _ZSTR_STRUCT_SIZE(ZSTR_LEN(str))); \ | |
zend_string_hash_val(str); \ | |
- GC_FLAGS(str) = IS_STR_INTERNED | IS_STR_PERMANENT; \ | |
+ zend_set_str_gc_flags(str); \ | |
} while (0) | |
#define zend_accel_store_interned_string(str) do { \ | |
if (!IS_ACCEL_INTERNED(str)) { \ | |
diff --git a/ext/opcache/zend_persist.h b/ext/opcache/zend_persist.h | |
index a03689ee44..cb98cee187 100644 | |
--- a/ext/opcache/zend_persist.h | |
+++ b/ext/opcache/zend_persist.h | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend OPcache | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c | |
index 84cd417204..d4f1e56c4f 100644 | |
--- a/ext/opcache/zend_persist_calc.c | |
+++ b/ext/opcache/zend_persist_calc.c | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend OPcache | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
diff --git a/ext/opcache/zend_shared_alloc.c b/ext/opcache/zend_shared_alloc.c | |
index 92e1ed7b1a..b7940ad39b 100644 | |
--- a/ext/opcache/zend_shared_alloc.c | |
+++ b/ext/opcache/zend_shared_alloc.c | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend OPcache | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | | |
diff --git a/ext/opcache/zend_shared_alloc.h b/ext/opcache/zend_shared_alloc.h | |
index 03b82d16ac..55acefe664 100644 | |
--- a/ext/opcache/zend_shared_alloc.h | |
+++ b/ext/opcache/zend_shared_alloc.h | |
@@ -2,7 +2,7 @@ | |
+----------------------------------------------------------------------+ | |
| Zend OPcache | | |
+----------------------------------------------------------------------+ | |
- | Copyright (c) 1998-2016 The PHP Group | | |
+ | Copyright (c) 1998-2017 The PHP Group | | |
+----------------------------------------------------------------------+ | |
| This source file is subject to version 3.01 of the PHP license, | | |
| that is bundled with this package in the file LICENSE, and is | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment