File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -795,6 +795,17 @@ static void zend_do_free(znode *op1) /* {{{ */
795795 case ZEND_PRE_DEC :
796796 SET_UNUSED (opline -> result );
797797 return ;
798+ case ZEND_FRAMELESS_ICALL_0 :
799+ case ZEND_FRAMELESS_ICALL_1 :
800+ case ZEND_FRAMELESS_ICALL_2 :
801+ case ZEND_FRAMELESS_ICALL_3 : {
802+ const zend_type return_type = ZEND_FLF_FUNC (opline )-> common .arg_info [-1 ].type ;
803+ if (!ZEND_TYPE_IS_COMPLEX (return_type )
804+ && !(ZEND_TYPE_PURE_MASK (return_type ) & (MAY_BE_STRING |MAY_BE_ARRAY |MAY_BE_OBJECT |MAY_BE_RESOURCE |MAY_BE_REF ))) {
805+ return ;
806+ }
807+ break ;
808+ }
798809 }
799810 }
800811
@@ -816,9 +827,11 @@ static void zend_do_free(znode *op1) /* {{{ */
816827 } else {
817828 /* Frameless calls usually use the return value, so always emit a free. This should be
818829 * faster than checking RETURN_VALUE_USED inside the handler. */
819- // FIXME: We may actually look at the function signature to determine whether a free
820- // is necessary.
821- zend_emit_op (NULL , ZEND_FREE , op1 , NULL );
830+ const zend_type return_type = ZEND_FLF_FUNC (opline )-> common .arg_info [-1 ].type ;
831+ if (ZEND_TYPE_IS_COMPLEX (return_type )
832+ || (ZEND_TYPE_PURE_MASK (return_type ) & (MAY_BE_STRING |MAY_BE_ARRAY |MAY_BE_OBJECT |MAY_BE_RESOURCE |MAY_BE_REF ))) {
833+ zend_emit_op (NULL , ZEND_FREE , op1 , NULL );
834+ }
822835 }
823836 } else {
824837 while (opline >= CG (active_op_array )-> opcodes ) {
Original file line number Diff line number Diff line change 1+ --TEST--
2+ Frameless returning non-RC types can omit free at compile-time
3+ --EXTENSIONS--
4+ opcache
5+ --INI--
6+ opcache.enable=1
7+ opcache.enable_cli=1
8+ opcache.opt_debug_level=0x10000
9+ --FILE--
10+ <?php
11+
12+ function test (array $ array ) {
13+ class_exists ('Foo ' );
14+ preg_match ('(foo) ' , 'foo ' );
15+ implode (', ' , $ array );
16+ }
17+
18+ ?>
19+ --EXPECTF--
20+ $_main:
21+ ; (lines=%d, args=0, vars=0, tmps=%d)
22+ ; (before optimizer)
23+ ; %s
24+ ; return [] RANGE[0..0]
25+ 0000 RETURN int(1)
26+
27+ test:
28+ ; (lines=%d, args=1, vars=1, tmps=%d)
29+ ; (before optimizer)
30+ ; %s
31+ ; return [] RANGE[0..0]
32+ 0000 CV0($array) = RECV 1
33+ 0001 T1 = FRAMELESS_ICALL_1(class_exists) string("Foo")
34+ 0002 T2 = FRAMELESS_ICALL_2(preg_match) string("(foo)") string("foo")
35+ 0003 T3 = FRAMELESS_ICALL_2(implode) string(", ") CV0($array)
36+ 0004 FREE T3
37+ 0005 RETURN null
You can’t perform that action at this time.
0 commit comments