summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikic@php.net>2015-07-08 11:54:38 +0200
committerNikita Popov <nikic@php.net>2015-07-08 12:00:39 +0200
commited14019e8c0c852480eebc6fc552d8c3d939dce1 (patch)
treea53df843625070d8dd0652a0b3c5323cb5a60c09
parent249915f938f6880b68ab6c6a47952c509dc51604 (diff)
downloadphp-git-ed14019e8c0c852480eebc6fc552d8c3d939dce1.tar.gz
Add assertion in liveliness computation
Assert that a live-range does not start, while one for the same variable is already active. To satisfy this constraint, explicitly exclude writes from JMP_SET and COALESCE. They were previously also handled correctly, because their result variable was only killed after the second write to it after the false branch. This just makes it more explicit.
-rw-r--r--Zend/zend_opcode.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c
index f8d040468f..ae2b4bf353 100644
--- a/Zend/zend_opcode.c
+++ b/Zend/zend_opcode.c
@@ -941,9 +941,12 @@ static zend_always_inline uint32_t *generate_var_liveliness_info_ex(zend_op_arra
&& opline->opcode != ZEND_BOOL
&& opline->opcode != ZEND_JMPZ_EX
&& opline->opcode != ZEND_JMPNZ_EX
- /* these two consecutive ops appear on ternary,
- * the result of true branch is undefined for false branch */
+ /* These opcodes write the result of the true branch of a ternary, short
+ * ternary or coalesce and are immediately followed by the instructions
+ * for the false branch (where this result is not live) */
&& (opline->opcode != ZEND_QM_ASSIGN || (opline + 1)->opcode != ZEND_JMP)
+ && opline->opcode != ZEND_JMP_SET
+ && opline->opcode != ZEND_COALESCE
/* exception for opcache, it might nowhere use the temporary
* (anyway bool, so no need to free) */
&& opline->opcode != ZEND_CASE
@@ -959,14 +962,17 @@ static zend_always_inline uint32_t *generate_var_liveliness_info_ex(zend_op_arra
&& opline->opcode != ZEND_DECLARE_INHERITED_CLASS
&& opline->opcode != ZEND_DECLARE_INHERITED_CLASS_DELAYED
&& opline->opcode != ZEND_DECLARE_ANON_CLASS
- && opline->opcode != ZEND_DECLARE_ANON_INHERITED_CLASS) {
+ && opline->opcode != ZEND_DECLARE_ANON_INHERITED_CLASS
+ ) {
if (done_pass_two) {
var = EX_VAR_TO_NUM(opline->result.var) - op_array->last_var;
} else {
var = opline->result.var;
}
- /* Objects created via ZEND_NEW are only fully initialized after the DO_FCALL (constructor call) */
+ ZEND_ASSERT(Tstart[var] == (unsigned) -1);
if (opline->opcode == ZEND_NEW) {
+ /* Objects created via ZEND_NEW are only fully initialized
+ * after the DO_FCALL (constructor call) */
Tstart[var] = opline->op2.opline_num - 1;
} else {
Tstart[var] = opline - op_array->opcodes;