lbarnaud Tue, 18 Oct 2011 19:42:42 +0000 Revision: http://svn.php.net/viewvc?view=revision&revision=318191
Log: Improved ternary operator performance when returning arrays Changed paths: U php/php-src/branches/PHP_5_4/NEWS U php/php-src/branches/PHP_5_4/Zend/micro_bench.php U php/php-src/branches/PHP_5_4/Zend/zend_compile.c U php/php-src/branches/PHP_5_4/Zend/zend_execute_API.c U php/php-src/branches/PHP_5_4/Zend/zend_opcode.c U php/php-src/branches/PHP_5_4/Zend/zend_vm_def.h U php/php-src/branches/PHP_5_4/Zend/zend_vm_execute.h U php/php-src/branches/PHP_5_4/Zend/zend_vm_opcodes.h U php/php-src/trunk/Zend/micro_bench.php U php/php-src/trunk/Zend/zend_compile.c U php/php-src/trunk/Zend/zend_execute_API.c U php/php-src/trunk/Zend/zend_opcode.c U php/php-src/trunk/Zend/zend_vm_def.h U php/php-src/trunk/Zend/zend_vm_execute.h U php/php-src/trunk/Zend/zend_vm_opcodes.h
Modified: php/php-src/branches/PHP_5_4/NEWS =================================================================== --- php/php-src/branches/PHP_5_4/NEWS 2011-10-18 14:54:32 UTC (rev 318190) +++ php/php-src/branches/PHP_5_4/NEWS 2011-10-18 19:42:42 UTC (rev 318191) @@ -3,6 +3,7 @@ ?? ??? 2011, PHP 5.4.0 RC1 - General improvements: . Improve the warning message of incompatible arguments. (Laruence) + . Improve ternary operator performance when returning arrays. (Arnaud, Dmitry) - Core: Modified: php/php-src/branches/PHP_5_4/Zend/micro_bench.php =================================================================== --- php/php-src/branches/PHP_5_4/Zend/micro_bench.php 2011-10-18 14:54:32 UTC (rev 318190) +++ php/php-src/branches/PHP_5_4/Zend/micro_bench.php 2011-10-18 19:42:42 UTC (rev 318191) @@ -202,6 +202,35 @@ } } +function issetor($n) { + $val = array(0,1,2,3,4,5,6,7,8,9); + for ($i = 0; $i < $n; ++$i) { + $x = $val ?: null; + } +} + +function issetor2($n) { + $f = false; $j = 0; + for ($i = 0; $i < $n; ++$i) { + $x = $f ?: $j + 1; + } +} + +function ternary($n) { + $val = array(0,1,2,3,4,5,6,7,8,9); + $f = false; + for ($i = 0; $i < $n; ++$i) { + $x = $f ? null : $val; + } +} + +function ternary2($n) { + $f = false; $j = 0; + for ($i = 0; $i < $n; ++$i) { + $x = $f ? $f : $j + 1; + } +} + /*****/ function empty_loop($n) { @@ -318,4 +347,12 @@ $t = end_test($t, '$x = $hash[\'v\']', $overhead); read_str_offset(N); $t = end_test($t, '$x = $str[0]', $overhead); +issetor(N); +$t = end_test($t, '$x = $a ?: null', $overhead); +issetor2(N); +$t = end_test($t, '$x = $f ?: tmp', $overhead); +ternary(N); +$t = end_test($t, '$x = $f ? $f : $a', $overhead); +ternary2(N); +$t = end_test($t, '$x = $f ? $f : tmp', $overhead); total($t0, "Total"); Modified: php/php-src/branches/PHP_5_4/Zend/zend_compile.c =================================================================== --- php/php-src/branches/PHP_5_4/Zend/zend_compile.c 2011-10-18 14:54:32 UTC (rev 318190) +++ php/php-src/branches/PHP_5_4/Zend/zend_compile.c 2011-10-18 19:42:42 UTC (rev 318191) @@ -1469,7 +1469,8 @@ && opline->result.var == op1->u.op.var) { if (opline->opcode == ZEND_FETCH_R || opline->opcode == ZEND_FETCH_DIM_R || - opline->opcode == ZEND_FETCH_OBJ_R) { + opline->opcode == ZEND_FETCH_OBJ_R || + opline->opcode == ZEND_QM_ASSIGN_VAR) { /* It's very rare and useless case. It's better to use additional FREE opcode and simplify the FETCH handlers their selves */ @@ -6308,8 +6309,13 @@ int op_number = get_next_op_number(CG(active_op_array)); zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); - opline->opcode = ZEND_JMP_SET; - opline->result_type = IS_TMP_VAR; + if (value->op_type == IS_VAR || value->op_type == IS_CV) { + opline->opcode = ZEND_JMP_SET_VAR; + opline->result_type = IS_VAR; + } else { + opline->opcode = ZEND_JMP_SET; + opline->result_type = IS_TMP_VAR; + } opline->result.var = get_temporary_variable(CG(active_op_array)); SET_NODE(opline->op1, value); SET_UNUSED(opline->op2); @@ -6326,9 +6332,20 @@ { zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); - opline->opcode = ZEND_QM_ASSIGN; + SET_NODE(opline->result, colon_token); + if (colon_token->op_type == IS_TMP_VAR) { + if (false_value->op_type == IS_VAR || false_value->op_type == IS_CV) { + CG(active_op_array)->opcodes[jmp_token->u.op.opline_num].opcode = ZEND_JMP_SET_VAR; + CG(active_op_array)->opcodes[jmp_token->u.op.opline_num].result_type = IS_VAR; + opline->opcode = ZEND_QM_ASSIGN_VAR; + opline->result_type = IS_VAR; + } else { + opline->opcode = ZEND_QM_ASSIGN; + } + } else { + opline->opcode = ZEND_QM_ASSIGN_VAR; + } opline->extended_value = 0; - SET_NODE(opline->result, colon_token); SET_NODE(opline->op1, false_value); SET_UNUSED(opline->op2); @@ -6363,8 +6380,13 @@ CG(active_op_array)->opcodes[qm_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array))+1; /* jmp over the ZEND_JMP */ - opline->opcode = ZEND_QM_ASSIGN; - opline->result_type = IS_TMP_VAR; + if (true_value->op_type == IS_VAR || true_value->op_type == IS_CV) { + opline->opcode = ZEND_QM_ASSIGN_VAR; + opline->result_type = IS_VAR; + } else { + opline->opcode = ZEND_QM_ASSIGN; + opline->result_type = IS_TMP_VAR; + } opline->result.var = get_temporary_variable(CG(active_op_array)); SET_NODE(opline->op1, true_value); SET_UNUSED(opline->op2); @@ -6383,8 +6405,19 @@ { zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); - opline->opcode = ZEND_QM_ASSIGN; SET_NODE(opline->result, qm_token); + if (qm_token->op_type == IS_TMP_VAR) { + if (false_value->op_type == IS_VAR || false_value->op_type == IS_CV) { + CG(active_op_array)->opcodes[colon_token->u.op.opline_num - 1].opcode = ZEND_QM_ASSIGN_VAR; + CG(active_op_array)->opcodes[colon_token->u.op.opline_num - 1].result_type = IS_VAR; + opline->opcode = ZEND_QM_ASSIGN_VAR; + opline->result_type = IS_VAR; + } else { + opline->opcode = ZEND_QM_ASSIGN; + } + } else { + opline->opcode = ZEND_QM_ASSIGN_VAR; + } SET_NODE(opline->op1, false_value); SET_UNUSED(opline->op2); Modified: php/php-src/branches/PHP_5_4/Zend/zend_execute_API.c =================================================================== --- php/php-src/branches/PHP_5_4/Zend/zend_execute_API.c 2011-10-18 14:54:32 UTC (rev 318190) +++ php/php-src/branches/PHP_5_4/Zend/zend_execute_API.c 2011-10-18 19:42:42 UTC (rev 318191) @@ -1299,6 +1299,7 @@ case ZEND_JMPZ_EX: case ZEND_JMPNZ_EX: case ZEND_JMP_SET: + case ZEND_JMP_SET_VAR: opline->op2.jmp_addr = &CG(active_op_array)->opcodes[opline->op2.opline_num]; break; } Modified: php/php-src/branches/PHP_5_4/Zend/zend_opcode.c =================================================================== --- php/php-src/branches/PHP_5_4/Zend/zend_opcode.c 2011-10-18 14:54:32 UTC (rev 318190) +++ php/php-src/branches/PHP_5_4/Zend/zend_opcode.c 2011-10-18 19:42:42 UTC (rev 318191) @@ -529,6 +529,7 @@ case ZEND_JMPZ_EX: case ZEND_JMPNZ_EX: case ZEND_JMP_SET: + case ZEND_JMP_SET_VAR: opline->op2.jmp_addr = &op_array->opcodes[opline->op2.opline_num]; break; } Modified: php/php-src/branches/PHP_5_4/Zend/zend_vm_def.h =================================================================== --- php/php-src/branches/PHP_5_4/Zend/zend_vm_def.h 2011-10-18 14:54:32 UTC (rev 318190) +++ php/php-src/branches/PHP_5_4/Zend/zend_vm_def.h 2011-10-18 19:42:42 UTC (rev 318191) @@ -4661,8 +4661,10 @@ if (i_zend_is_true(value)) { ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value); - zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var); - FREE_OP1(); + if (!IS_OP1_TMP_FREE()) { + zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var); + } + FREE_OP1_IF_VAR(); #if DEBUG_ZEND>=2 printf("Conditional jmp to %d\n", opline->op2.opline_num); #endif @@ -4674,6 +4676,41 @@ ZEND_VM_NEXT_OPCODE(); } +ZEND_VM_HANDLER(158, ZEND_JMP_SET_VAR, CONST|TMP|VAR|CV, ANY) +{ + USE_OPLINE + zend_free_op free_op1; + zval *value, *ret; + + SAVE_OPLINE(); + value = GET_OP1_ZVAL_PTR(BP_VAR_R); + + if (i_zend_is_true(value)) { + if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) { + Z_ADDREF_P(value); + EX_T(opline->result.var).var.ptr = value; + EX_T(opline->result.var).var.ptr_ptr = NULL; + } else { + ALLOC_ZVAL(ret); + INIT_PZVAL_COPY(ret, value); + EX_T(opline->result.var).var.ptr = ret; + EX_T(opline->result.var).var.ptr_ptr = NULL; + if (!IS_OP1_TMP_FREE()) { + zval_copy_ctor(EX_T(opline->result.var).var.ptr); + } + } + FREE_OP1_IF_VAR(); +#if DEBUG_ZEND>=2 + printf("Conditional jmp to %d\n", opline->op2.opline_num); +#endif + ZEND_VM_JMP(opline->op2.jmp_addr); + } + + FREE_OP1(); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + ZEND_VM_HANDLER(22, ZEND_QM_ASSIGN, CONST|TMP|VAR|CV, ANY) { USE_OPLINE @@ -4692,6 +4729,34 @@ ZEND_VM_NEXT_OPCODE(); } +ZEND_VM_HANDLER(157, ZEND_QM_ASSIGN_VAR, CONST|TMP|VAR|CV, ANY) +{ + USE_OPLINE + zend_free_op free_op1; + zval *value, *ret; + + SAVE_OPLINE(); + value = GET_OP1_ZVAL_PTR(BP_VAR_R); + + if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) { + Z_ADDREF_P(value); + EX_T(opline->result.var).var.ptr = value; + EX_T(opline->result.var).var.ptr_ptr = NULL; + } else { + ALLOC_ZVAL(ret); + INIT_PZVAL_COPY(ret, value); + EX_T(opline->result.var).var.ptr = ret; + EX_T(opline->result.var).var.ptr_ptr = NULL; + if (!IS_OP1_TMP_FREE()) { + zval_copy_ctor(EX_T(opline->result.var).var.ptr); + } + } + + FREE_OP1_IF_VAR(); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + ZEND_VM_HANDLER(101, ZEND_EXT_STMT, ANY, ANY) { SAVE_OPLINE(); Modified: php/php-src/branches/PHP_5_4/Zend/zend_vm_execute.h =================================================================== --- php/php-src/branches/PHP_5_4/Zend/zend_vm_execute.h 2011-10-18 14:54:32 UTC (rev 318190) +++ php/php-src/branches/PHP_5_4/Zend/zend_vm_execute.h 2011-10-18 19:42:42 UTC (rev 318191) @@ -2836,7 +2836,9 @@ if (i_zend_is_true(value)) { ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value); - zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var); + if (!0) { + zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var); + } #if DEBUG_ZEND>=2 printf("Conditional jmp to %d\n", opline->op2.opline_num); @@ -2848,6 +2850,40 @@ ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *value, *ret; + + SAVE_OPLINE(); + value = opline->op1.zv; + + if (i_zend_is_true(value)) { + if (IS_CONST == IS_VAR || IS_CONST == IS_CV) { + Z_ADDREF_P(value); + EX_T(opline->result.var).var.ptr = value; + EX_T(opline->result.var).var.ptr_ptr = NULL; + } else { + ALLOC_ZVAL(ret); + INIT_PZVAL_COPY(ret, value); + EX_T(opline->result.var).var.ptr = ret; + EX_T(opline->result.var).var.ptr_ptr = NULL; + if (!0) { + zval_copy_ctor(EX_T(opline->result.var).var.ptr); + } + } + +#if DEBUG_ZEND>=2 + printf("Conditional jmp to %d\n", opline->op2.opline_num); +#endif + ZEND_VM_JMP(opline->op2.jmp_addr); + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -2866,6 +2902,33 @@ ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *value, *ret; + + SAVE_OPLINE(); + value = opline->op1.zv; + + if (IS_CONST == IS_VAR || IS_CONST == IS_CV) { + Z_ADDREF_P(value); + EX_T(opline->result.var).var.ptr = value; + EX_T(opline->result.var).var.ptr_ptr = NULL; + } else { + ALLOC_ZVAL(ret); + INIT_PZVAL_COPY(ret, value); + EX_T(opline->result.var).var.ptr = ret; + EX_T(opline->result.var).var.ptr_ptr = NULL; + if (!0) { + zval_copy_ctor(EX_T(opline->result.var).var.ptr); + } + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_ADD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -7132,8 +7195,10 @@ if (i_zend_is_true(value)) { ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value); - zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var); - zval_dtor(free_op1.var); + if (!1) { + zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var); + } + #if DEBUG_ZEND>=2 printf("Conditional jmp to %d\n", opline->op2.opline_num); #endif @@ -7145,6 +7210,41 @@ ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *value, *ret; + + SAVE_OPLINE(); + value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + + if (i_zend_is_true(value)) { + if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) { + Z_ADDREF_P(value); + EX_T(opline->result.var).var.ptr = value; + EX_T(opline->result.var).var.ptr_ptr = NULL; + } else { + ALLOC_ZVAL(ret); + INIT_PZVAL_COPY(ret, value); + EX_T(opline->result.var).var.ptr = ret; + EX_T(opline->result.var).var.ptr_ptr = NULL; + if (!1) { + zval_copy_ctor(EX_T(opline->result.var).var.ptr); + } + } + +#if DEBUG_ZEND>=2 + printf("Conditional jmp to %d\n", opline->op2.opline_num); +#endif + ZEND_VM_JMP(opline->op2.jmp_addr); + } + + zval_dtor(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -7163,6 +7263,33 @@ ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *value, *ret; + + SAVE_OPLINE(); + value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + + if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) { + Z_ADDREF_P(value); + EX_T(opline->result.var).var.ptr = value; + EX_T(opline->result.var).var.ptr_ptr = NULL; + } else { + ALLOC_ZVAL(ret); + INIT_PZVAL_COPY(ret, value); + EX_T(opline->result.var).var.ptr = ret; + EX_T(opline->result.var).var.ptr_ptr = NULL; + if (!1) { + zval_copy_ctor(EX_T(opline->result.var).var.ptr); + } + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -11539,7 +11666,9 @@ if (i_zend_is_true(value)) { ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value); - zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var); + if (!0) { + zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var); + } if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; #if DEBUG_ZEND>=2 printf("Conditional jmp to %d\n", opline->op2.opline_num); @@ -11552,6 +11681,41 @@ ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *value, *ret; + + SAVE_OPLINE(); + value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + + if (i_zend_is_true(value)) { + if (IS_VAR == IS_VAR || IS_VAR == IS_CV) { + Z_ADDREF_P(value); + EX_T(opline->result.var).var.ptr = value; + EX_T(opline->result.var).var.ptr_ptr = NULL; + } else { + ALLOC_ZVAL(ret); + INIT_PZVAL_COPY(ret, value); + EX_T(opline->result.var).var.ptr = ret; + EX_T(opline->result.var).var.ptr_ptr = NULL; + if (!0) { + zval_copy_ctor(EX_T(opline->result.var).var.ptr); + } + } + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; +#if DEBUG_ZEND>=2 + printf("Conditional jmp to %d\n", opline->op2.opline_num); +#endif + ZEND_VM_JMP(opline->op2.jmp_addr); + } + + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -11570,6 +11734,34 @@ ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *value, *ret; + + SAVE_OPLINE(); + value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + + if (IS_VAR == IS_VAR || IS_VAR == IS_CV) { + Z_ADDREF_P(value); + EX_T(opline->result.var).var.ptr = value; + EX_T(opline->result.var).var.ptr_ptr = NULL; + } else { + ALLOC_ZVAL(ret); + INIT_PZVAL_COPY(ret, value); + EX_T(opline->result.var).var.ptr = ret; + EX_T(opline->result.var).var.ptr_ptr = NULL; + if (!0) { + zval_copy_ctor(EX_T(opline->result.var).var.ptr); + } + } + + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -27127,7 +27319,9 @@ if (i_zend_is_true(value)) { ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value); - zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var); + if (!0) { + zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var); + } #if DEBUG_ZEND>=2 printf("Conditional jmp to %d\n", opline->op2.opline_num); @@ -27139,6 +27333,40 @@ ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *value, *ret; + + SAVE_OPLINE(); + value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + + if (i_zend_is_true(value)) { + if (IS_CV == IS_VAR || IS_CV == IS_CV) { + Z_ADDREF_P(value); + EX_T(opline->result.var).var.ptr = value; + EX_T(opline->result.var).var.ptr_ptr = NULL; + } else { + ALLOC_ZVAL(ret); + INIT_PZVAL_COPY(ret, value); + EX_T(opline->result.var).var.ptr = ret; + EX_T(opline->result.var).var.ptr_ptr = NULL; + if (!0) { + zval_copy_ctor(EX_T(opline->result.var).var.ptr); + } + } + +#if DEBUG_ZEND>=2 + printf("Conditional jmp to %d\n", opline->op2.opline_num); +#endif + ZEND_VM_JMP(opline->op2.jmp_addr); + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -27157,6 +27385,33 @@ ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *value, *ret; + + SAVE_OPLINE(); + value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + + if (IS_CV == IS_VAR || IS_CV == IS_CV) { + Z_ADDREF_P(value); + EX_T(opline->result.var).var.ptr = value; + EX_T(opline->result.var).var.ptr_ptr = NULL; + } else { + ALLOC_ZVAL(ret); + INIT_PZVAL_COPY(ret, value); + EX_T(opline->result.var).var.ptr = ret; + EX_T(opline->result.var).var.ptr_ptr = NULL; + if (!0) { + zval_copy_ctor(EX_T(opline->result.var).var.ptr); + } + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -39759,6 +40014,56 @@ ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER, + ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER, + ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER, + ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER, + ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER, + ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER, + ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER, + ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER, + ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER, + ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER, + ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER, + ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER, + ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER, + ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER, + ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER, + ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_JMP_SET_VAR_SPEC_CV_HANDLER, + ZEND_JMP_SET_VAR_SPEC_CV_HANDLER, + ZEND_JMP_SET_VAR_SPEC_CV_HANDLER, + ZEND_JMP_SET_VAR_SPEC_CV_HANDLER, + ZEND_JMP_SET_VAR_SPEC_CV_HANDLER, ZEND_NULL_HANDLER }; zend_opcode_handlers = (opcode_handler_t*)labels; Modified: php/php-src/branches/PHP_5_4/Zend/zend_vm_opcodes.h =================================================================== --- php/php-src/branches/PHP_5_4/Zend/zend_vm_opcodes.h 2011-10-18 14:54:32 UTC (rev 318190) +++ php/php-src/branches/PHP_5_4/Zend/zend_vm_opcodes.h 2011-10-18 19:42:42 UTC (rev 318191) @@ -157,3 +157,5 @@ #define ZEND_ADD_TRAIT 154 #define ZEND_BIND_TRAITS 155 #define ZEND_SEPARATE 156 +#define ZEND_QM_ASSIGN_VAR 157 +#define ZEND_JMP_SET_VAR 158 Modified: php/php-src/trunk/Zend/micro_bench.php =================================================================== --- php/php-src/trunk/Zend/micro_bench.php 2011-10-18 14:54:32 UTC (rev 318190) +++ php/php-src/trunk/Zend/micro_bench.php 2011-10-18 19:42:42 UTC (rev 318191) @@ -202,6 +202,35 @@ } } +function issetor($n) { + $val = array(0,1,2,3,4,5,6,7,8,9); + for ($i = 0; $i < $n; ++$i) { + $x = $val ?: null; + } +} + +function issetor2($n) { + $f = false; $j = 0; + for ($i = 0; $i < $n; ++$i) { + $x = $f ?: $j + 1; + } +} + +function ternary($n) { + $val = array(0,1,2,3,4,5,6,7,8,9); + $f = false; + for ($i = 0; $i < $n; ++$i) { + $x = $f ? null : $val; + } +} + +function ternary2($n) { + $f = false; $j = 0; + for ($i = 0; $i < $n; ++$i) { + $x = $f ? $f : $j + 1; + } +} + /*****/ function empty_loop($n) { @@ -318,4 +347,12 @@ $t = end_test($t, '$x = $hash[\'v\']', $overhead); read_str_offset(N); $t = end_test($t, '$x = $str[0]', $overhead); +issetor(N); +$t = end_test($t, '$x = $a ?: null', $overhead); +issetor2(N); +$t = end_test($t, '$x = $f ?: tmp', $overhead); +ternary(N); +$t = end_test($t, '$x = $f ? $f : $a', $overhead); +ternary2(N); +$t = end_test($t, '$x = $f ? $f : tmp', $overhead); total($t0, "Total"); Modified: php/php-src/trunk/Zend/zend_compile.c =================================================================== --- php/php-src/trunk/Zend/zend_compile.c 2011-10-18 14:54:32 UTC (rev 318190) +++ php/php-src/trunk/Zend/zend_compile.c 2011-10-18 19:42:42 UTC (rev 318191) @@ -1469,7 +1469,8 @@ && opline->result.var == op1->u.op.var) { if (opline->opcode == ZEND_FETCH_R || opline->opcode == ZEND_FETCH_DIM_R || - opline->opcode == ZEND_FETCH_OBJ_R) { + opline->opcode == ZEND_FETCH_OBJ_R || + opline->opcode == ZEND_QM_ASSIGN_VAR) { /* It's very rare and useless case. It's better to use additional FREE opcode and simplify the FETCH handlers their selves */ @@ -6308,8 +6309,13 @@ int op_number = get_next_op_number(CG(active_op_array)); zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); - opline->opcode = ZEND_JMP_SET; - opline->result_type = IS_TMP_VAR; + if (value->op_type == IS_VAR || value->op_type == IS_CV) { + opline->opcode = ZEND_JMP_SET_VAR; + opline->result_type = IS_VAR; + } else { + opline->opcode = ZEND_JMP_SET; + opline->result_type = IS_TMP_VAR; + } opline->result.var = get_temporary_variable(CG(active_op_array)); SET_NODE(opline->op1, value); SET_UNUSED(opline->op2); @@ -6326,9 +6332,20 @@ { zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); - opline->opcode = ZEND_QM_ASSIGN; + SET_NODE(opline->result, colon_token); + if (colon_token->op_type == IS_TMP_VAR) { + if (false_value->op_type == IS_VAR || false_value->op_type == IS_CV) { + CG(active_op_array)->opcodes[jmp_token->u.op.opline_num].opcode = ZEND_JMP_SET_VAR; + CG(active_op_array)->opcodes[jmp_token->u.op.opline_num].result_type = IS_VAR; + opline->opcode = ZEND_QM_ASSIGN_VAR; + opline->result_type = IS_VAR; + } else { + opline->opcode = ZEND_QM_ASSIGN; + } + } else { + opline->opcode = ZEND_QM_ASSIGN_VAR; + } opline->extended_value = 0; - SET_NODE(opline->result, colon_token); SET_NODE(opline->op1, false_value); SET_UNUSED(opline->op2); @@ -6363,8 +6380,13 @@ CG(active_op_array)->opcodes[qm_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array))+1; /* jmp over the ZEND_JMP */ - opline->opcode = ZEND_QM_ASSIGN; - opline->result_type = IS_TMP_VAR; + if (true_value->op_type == IS_VAR || true_value->op_type == IS_CV) { + opline->opcode = ZEND_QM_ASSIGN_VAR; + opline->result_type = IS_VAR; + } else { + opline->opcode = ZEND_QM_ASSIGN; + opline->result_type = IS_TMP_VAR; + } opline->result.var = get_temporary_variable(CG(active_op_array)); SET_NODE(opline->op1, true_value); SET_UNUSED(opline->op2); @@ -6383,8 +6405,19 @@ { zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); - opline->opcode = ZEND_QM_ASSIGN; SET_NODE(opline->result, qm_token); + if (qm_token->op_type == IS_TMP_VAR) { + if (false_value->op_type == IS_VAR || false_value->op_type == IS_CV) { + CG(active_op_array)->opcodes[colon_token->u.op.opline_num - 1].opcode = ZEND_QM_ASSIGN_VAR; + CG(active_op_array)->opcodes[colon_token->u.op.opline_num - 1].result_type = IS_VAR; + opline->opcode = ZEND_QM_ASSIGN_VAR; + opline->result_type = IS_VAR; + } else { + opline->opcode = ZEND_QM_ASSIGN; + } + } else { + opline->opcode = ZEND_QM_ASSIGN_VAR; + } SET_NODE(opline->op1, false_value); SET_UNUSED(opline->op2); Modified: php/php-src/trunk/Zend/zend_execute_API.c =================================================================== --- php/php-src/trunk/Zend/zend_execute_API.c 2011-10-18 14:54:32 UTC (rev 318190) +++ php/php-src/trunk/Zend/zend_execute_API.c 2011-10-18 19:42:42 UTC (rev 318191) @@ -1299,6 +1299,7 @@ case ZEND_JMPZ_EX: case ZEND_JMPNZ_EX: case ZEND_JMP_SET: + case ZEND_JMP_SET_VAR: opline->op2.jmp_addr = &CG(active_op_array)->opcodes[opline->op2.opline_num]; break; } Modified: php/php-src/trunk/Zend/zend_opcode.c =================================================================== --- php/php-src/trunk/Zend/zend_opcode.c 2011-10-18 14:54:32 UTC (rev 318190) +++ php/php-src/trunk/Zend/zend_opcode.c 2011-10-18 19:42:42 UTC (rev 318191) @@ -529,6 +529,7 @@ case ZEND_JMPZ_EX: case ZEND_JMPNZ_EX: case ZEND_JMP_SET: + case ZEND_JMP_SET_VAR: opline->op2.jmp_addr = &op_array->opcodes[opline->op2.opline_num]; break; } Modified: php/php-src/trunk/Zend/zend_vm_def.h =================================================================== --- php/php-src/trunk/Zend/zend_vm_def.h 2011-10-18 14:54:32 UTC (rev 318190) +++ php/php-src/trunk/Zend/zend_vm_def.h 2011-10-18 19:42:42 UTC (rev 318191) @@ -4661,8 +4661,10 @@ if (i_zend_is_true(value)) { ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value); - zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var); - FREE_OP1(); + if (!IS_OP1_TMP_FREE()) { + zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var); + } + FREE_OP1_IF_VAR(); #if DEBUG_ZEND>=2 printf("Conditional jmp to %d\n", opline->op2.opline_num); #endif @@ -4674,6 +4676,41 @@ ZEND_VM_NEXT_OPCODE(); } +ZEND_VM_HANDLER(158, ZEND_JMP_SET_VAR, CONST|TMP|VAR|CV, ANY) +{ + USE_OPLINE + zend_free_op free_op1; + zval *value, *ret; + + SAVE_OPLINE(); + value = GET_OP1_ZVAL_PTR(BP_VAR_R); + + if (i_zend_is_true(value)) { + if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) { + Z_ADDREF_P(value); + EX_T(opline->result.var).var.ptr = value; + EX_T(opline->result.var).var.ptr_ptr = NULL; + } else { + ALLOC_ZVAL(ret); + INIT_PZVAL_COPY(ret, value); + EX_T(opline->result.var).var.ptr = ret; + EX_T(opline->result.var).var.ptr_ptr = NULL; + if (!IS_OP1_TMP_FREE()) { + zval_copy_ctor(EX_T(opline->result.var).var.ptr); + } + } + FREE_OP1_IF_VAR(); +#if DEBUG_ZEND>=2 + printf("Conditional jmp to %d\n", opline->op2.opline_num); +#endif + ZEND_VM_JMP(opline->op2.jmp_addr); + } + + FREE_OP1(); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + ZEND_VM_HANDLER(22, ZEND_QM_ASSIGN, CONST|TMP|VAR|CV, ANY) { USE_OPLINE @@ -4692,6 +4729,34 @@ ZEND_VM_NEXT_OPCODE(); } +ZEND_VM_HANDLER(157, ZEND_QM_ASSIGN_VAR, CONST|TMP|VAR|CV, ANY) +{ + USE_OPLINE + zend_free_op free_op1; + zval *value, *ret; + + SAVE_OPLINE(); + value = GET_OP1_ZVAL_PTR(BP_VAR_R); + + if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) { + Z_ADDREF_P(value); + EX_T(opline->result.var).var.ptr = value; + EX_T(opline->result.var).var.ptr_ptr = NULL; + } else { + ALLOC_ZVAL(ret); + INIT_PZVAL_COPY(ret, value); + EX_T(opline->result.var).var.ptr = ret; + EX_T(opline->result.var).var.ptr_ptr = NULL; + if (!IS_OP1_TMP_FREE()) { + zval_copy_ctor(EX_T(opline->result.var).var.ptr); + } + } + + FREE_OP1_IF_VAR(); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + ZEND_VM_HANDLER(101, ZEND_EXT_STMT, ANY, ANY) { SAVE_OPLINE(); Modified: php/php-src/trunk/Zend/zend_vm_execute.h =================================================================== --- php/php-src/trunk/Zend/zend_vm_execute.h 2011-10-18 14:54:32 UTC (rev 318190) +++ php/php-src/trunk/Zend/zend_vm_execute.h 2011-10-18 19:42:42 UTC (rev 318191) @@ -2836,7 +2836,9 @@ if (i_zend_is_true(value)) { ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value); - zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var); + if (!0) { + zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var); + } #if DEBUG_ZEND>=2 printf("Conditional jmp to %d\n", opline->op2.opline_num); @@ -2848,6 +2850,40 @@ ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *value, *ret; + + SAVE_OPLINE(); + value = opline->op1.zv; + + if (i_zend_is_true(value)) { + if (IS_CONST == IS_VAR || IS_CONST == IS_CV) { + Z_ADDREF_P(value); + EX_T(opline->result.var).var.ptr = value; + EX_T(opline->result.var).var.ptr_ptr = NULL; + } else { + ALLOC_ZVAL(ret); + INIT_PZVAL_COPY(ret, value); + EX_T(opline->result.var).var.ptr = ret; + EX_T(opline->result.var).var.ptr_ptr = NULL; + if (!0) { + zval_copy_ctor(EX_T(opline->result.var).var.ptr); + } + } + +#if DEBUG_ZEND>=2 + printf("Conditional jmp to %d\n", opline->op2.opline_num); +#endif + ZEND_VM_JMP(opline->op2.jmp_addr); + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -2866,6 +2902,33 @@ ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *value, *ret; + + SAVE_OPLINE(); + value = opline->op1.zv; + + if (IS_CONST == IS_VAR || IS_CONST == IS_CV) { + Z_ADDREF_P(value); + EX_T(opline->result.var).var.ptr = value; + EX_T(opline->result.var).var.ptr_ptr = NULL; + } else { + ALLOC_ZVAL(ret); + INIT_PZVAL_COPY(ret, value); + EX_T(opline->result.var).var.ptr = ret; + EX_T(opline->result.var).var.ptr_ptr = NULL; + if (!0) { + zval_copy_ctor(EX_T(opline->result.var).var.ptr); + } + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_ADD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -7132,8 +7195,10 @@ if (i_zend_is_true(value)) { ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value); - zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var); - zval_dtor(free_op1.var); + if (!1) { + zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var); + } + #if DEBUG_ZEND>=2 printf("Conditional jmp to %d\n", opline->op2.opline_num); #endif @@ -7145,6 +7210,41 @@ ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *value, *ret; + + SAVE_OPLINE(); + value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + + if (i_zend_is_true(value)) { + if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) { + Z_ADDREF_P(value); + EX_T(opline->result.var).var.ptr = value; + EX_T(opline->result.var).var.ptr_ptr = NULL; + } else { + ALLOC_ZVAL(ret); + INIT_PZVAL_COPY(ret, value); + EX_T(opline->result.var).var.ptr = ret; + EX_T(opline->result.var).var.ptr_ptr = NULL; + if (!1) { + zval_copy_ctor(EX_T(opline->result.var).var.ptr); + } + } + +#if DEBUG_ZEND>=2 + printf("Conditional jmp to %d\n", opline->op2.opline_num); +#endif + ZEND_VM_JMP(opline->op2.jmp_addr); + } + + zval_dtor(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -7163,6 +7263,33 @@ ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *value, *ret; + + SAVE_OPLINE(); + value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + + if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) { + Z_ADDREF_P(value); + EX_T(opline->result.var).var.ptr = value; + EX_T(opline->result.var).var.ptr_ptr = NULL; + } else { + ALLOC_ZVAL(ret); + INIT_PZVAL_COPY(ret, value); + EX_T(opline->result.var).var.ptr = ret; + EX_T(opline->result.var).var.ptr_ptr = NULL; + if (!1) { + zval_copy_ctor(EX_T(opline->result.var).var.ptr); + } + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -11539,7 +11666,9 @@ if (i_zend_is_true(value)) { ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value); - zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var); + if (!0) { + zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var); + } if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; #if DEBUG_ZEND>=2 printf("Conditional jmp to %d\n", opline->op2.opline_num); @@ -11552,6 +11681,41 @@ ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *value, *ret; + + SAVE_OPLINE(); + value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + + if (i_zend_is_true(value)) { + if (IS_VAR == IS_VAR || IS_VAR == IS_CV) { + Z_ADDREF_P(value); + EX_T(opline->result.var).var.ptr = value; + EX_T(opline->result.var).var.ptr_ptr = NULL; + } else { + ALLOC_ZVAL(ret); + INIT_PZVAL_COPY(ret, value); + EX_T(opline->result.var).var.ptr = ret; + EX_T(opline->result.var).var.ptr_ptr = NULL; + if (!0) { + zval_copy_ctor(EX_T(opline->result.var).var.ptr); + } + } + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; +#if DEBUG_ZEND>=2 + printf("Conditional jmp to %d\n", opline->op2.opline_num); +#endif + ZEND_VM_JMP(opline->op2.jmp_addr); + } + + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -11570,6 +11734,34 @@ ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *value, *ret; + + SAVE_OPLINE(); + value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + + if (IS_VAR == IS_VAR || IS_VAR == IS_CV) { + Z_ADDREF_P(value); + EX_T(opline->result.var).var.ptr = value; + EX_T(opline->result.var).var.ptr_ptr = NULL; + } else { + ALLOC_ZVAL(ret); + INIT_PZVAL_COPY(ret, value); + EX_T(opline->result.var).var.ptr = ret; + EX_T(opline->result.var).var.ptr_ptr = NULL; + if (!0) { + zval_copy_ctor(EX_T(opline->result.var).var.ptr); + } + } + + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -27127,7 +27319,9 @@ if (i_zend_is_true(value)) { ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value); - zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var); + if (!0) { + zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var); + } #if DEBUG_ZEND>=2 printf("Conditional jmp to %d\n", opline->op2.opline_num); @@ -27139,6 +27333,40 @@ ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *value, *ret; + + SAVE_OPLINE(); + value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + + if (i_zend_is_true(value)) { + if (IS_CV == IS_VAR || IS_CV == IS_CV) { + Z_ADDREF_P(value); + EX_T(opline->result.var).var.ptr = value; + EX_T(opline->result.var).var.ptr_ptr = NULL; + } else { + ALLOC_ZVAL(ret); + INIT_PZVAL_COPY(ret, value); + EX_T(opline->result.var).var.ptr = ret; + EX_T(opline->result.var).var.ptr_ptr = NULL; + if (!0) { + zval_copy_ctor(EX_T(opline->result.var).var.ptr); + } + } + +#if DEBUG_ZEND>=2 + printf("Conditional jmp to %d\n", opline->op2.opline_num); +#endif + ZEND_VM_JMP(opline->op2.jmp_addr); + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -27157,6 +27385,33 @@ ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *value, *ret; + + SAVE_OPLINE(); + value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + + if (IS_CV == IS_VAR || IS_CV == IS_CV) { + Z_ADDREF_P(value); + EX_T(opline->result.var).var.ptr = value; + EX_T(opline->result.var).var.ptr_ptr = NULL; + } else { + ALLOC_ZVAL(ret); + INIT_PZVAL_COPY(ret, value); + EX_T(opline->result.var).var.ptr = ret; + EX_T(opline->result.var).var.ptr_ptr = NULL; + if (!0) { + zval_copy_ctor(EX_T(opline->result.var).var.ptr); + } + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -39759,6 +40014,56 @@ ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER, + ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER, + ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER, + ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER, + ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER, + ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER, + ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER, + ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER, + ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER, + ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER, + ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER, + ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER, + ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER, + ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER, + ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER, + ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER, + ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_JMP_SET_VAR_SPEC_CV_HANDLER, + ZEND_JMP_SET_VAR_SPEC_CV_HANDLER, + ZEND_JMP_SET_VAR_SPEC_CV_HANDLER, + ZEND_JMP_SET_VAR_SPEC_CV_HANDLER, + ZEND_JMP_SET_VAR_SPEC_CV_HANDLER, ZEND_NULL_HANDLER }; zend_opcode_handlers = (opcode_handler_t*)labels; Modified: php/php-src/trunk/Zend/zend_vm_opcodes.h =================================================================== --- php/php-src/trunk/Zend/zend_vm_opcodes.h 2011-10-18 14:54:32 UTC (rev 318190) +++ php/php-src/trunk/Zend/zend_vm_opcodes.h 2011-10-18 19:42:42 UTC (rev 318191) @@ -157,3 +157,5 @@ #define ZEND_ADD_TRAIT 154 #define ZEND_BIND_TRAITS 155 #define ZEND_SEPARATE 156 +#define ZEND_QM_ASSIGN_VAR 157 +#define ZEND_JMP_SET_VAR 158
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php