diff options
Diffstat (limited to 'Zend')
149 files changed, 14796 insertions, 5843 deletions
diff --git a/Zend/Makefile.am b/Zend/Makefile.am index 5ec4590fef..6417f3eb14 100644 --- a/Zend/Makefile.am +++ b/Zend/Makefile.am @@ -17,7 +17,8 @@ libZend_la_SOURCES=\ zend_objects_API.c zend_ts_hash.c zend_stream.c \ zend_default_classes.c \ zend_iterators.c zend_interfaces.c zend_exceptions.c \ - zend_strtod.c zend_closures.c zend_float.c zend_string.c zend_signal.c + zend_strtod.c zend_closures.c zend_float.c zend_string.c zend_signal.c \ + zend_generators.c libZend_la_LDFLAGS = libZend_la_LIBADD = @ZEND_EXTRA_LIBS@ @@ -31,7 +32,7 @@ zend_ini_scanner.lo: zend_ini_parser.h # Language parser/scanner rules zend_language_scanner.c: $(srcdir)/zend_language_scanner.l - $(RE2C) $(RE2C_FLAGS) --case-inverted -cbdFt $(srcdir)/zend_language_scanner_defs.h -o$@ $(srcdir)/zend_language_scanner.l + $(RE2C) $(RE2C_FLAGS) --no-generation-date --case-inverted -cbdFt $(srcdir)/zend_language_scanner_defs.h -o$@ $(srcdir)/zend_language_scanner.l zend_language_parser.h: zend_language_parser.c zend_language_parser.c: $(srcdir)/zend_language_parser.y @@ -43,7 +44,7 @@ zend_ini_parser.c: $(srcdir)/zend_ini_parser.y $(YACC) -p ini_ -v -d $(srcdir)/zend_ini_parser.y -o zend_ini_parser.c zend_ini_scanner.c: $(srcdir)/zend_ini_scanner.l - $(RE2C) $(RE2C_FLAGS) --case-inverted -cbdFt $(srcdir)/zend_ini_scanner_defs.h -o$@ $(srcdir)/zend_ini_scanner.l + $(RE2C) $(RE2C_FLAGS) --no-generation-date --case-inverted -cbdFt $(srcdir)/zend_ini_scanner_defs.h -o$@ $(srcdir)/zend_ini_scanner.l zend_ini_parser.h: zend_ini_parser.c diff --git a/Zend/Zend.dsp b/Zend/Zend.dsp index ebe01978c4..23ebd4532b 100644 --- a/Zend/Zend.dsp +++ b/Zend/Zend.dsp @@ -159,6 +159,10 @@ SOURCE=.\zend_float.c # End Source File
# Begin Source File
+SOURCE=.\zend_generators.c
+# End Source File
+# Begin Source File
+
SOURCE=.\zend_hash.c
# End Source File
# Begin Source File
diff --git a/Zend/ZendTS.dsp b/Zend/ZendTS.dsp index 3494cd4e17..3be2c58bed 100644 --- a/Zend/ZendTS.dsp +++ b/Zend/ZendTS.dsp @@ -185,6 +185,10 @@ SOURCE=.\zend_extensions.c # End Source File
# Begin Source File
+SOURCE=.\zend_generators.c
+# End Source File
+# Begin Source File
+
SOURCE=.\zend_hash.c
# End Source File
# Begin Source File
diff --git a/Zend/tests/bug18556.phpt b/Zend/tests/bug18556.phpt new file mode 100644 index 0000000000..036abb2ada --- /dev/null +++ b/Zend/tests/bug18556.phpt @@ -0,0 +1,37 @@ +--TEST-- +Bug #18556 (Setting locale to 'tr_TR' lowercases class names) +--FILE-- +<?php +$g_lang = 'tr_TR'; +putenv("LANG=$g_lang"); +setlocale(LC_ALL, $g_lang); + +class InfoBlob { + var $foo; + function InfoBlob() { + $this->foo = "Foo"; + } +} + +echo "Instantiating an infoBlob with a lowercase i\n"; +$foobar = new infoBlob(); +echo $foobar->foo; +echo "\nInstantiating an InfoBlob with an uppercase I\n"; +$foobar = new InfoBlob(); +echo $foobar->foo; +echo "\n"; +setlocale(LC_ALL, "tr_TR.utf8"); +foreach(get_declared_classes() as $class) +{ + if(!class_exists($class)) + echo "$class No Longer Exists!\n"; + +} +echo "Done.\n"; +?> +--EXPECT-- +Instantiating an infoBlob with a lowercase i +Foo +Instantiating an InfoBlob with an uppercase I +Foo +Done. diff --git a/Zend/tests/bug60738.phpt b/Zend/tests/bug60738.phpt new file mode 100644 index 0000000000..e4080715ec --- /dev/null +++ b/Zend/tests/bug60738.phpt @@ -0,0 +1,22 @@ +--TEST-- +Bug #60738 Allow 'set_error_handler' to handle NULL +--FILE-- +<?php + +var_dump(set_error_handler( + function() { echo 'Intercepted error!', "\n"; } +)); + +trigger_error('Error!'); + +var_dump(set_error_handler(null)); + +trigger_error('Error!'); +?> +--EXPECTF-- +NULL +Intercepted error! +object(Closure)#1 (0) { +} + +Notice: Error! in %s on line %d diff --git a/Zend/tests/bug60738_variation.phpt b/Zend/tests/bug60738_variation.phpt new file mode 100644 index 0000000000..d7cf00ecdb --- /dev/null +++ b/Zend/tests/bug60738_variation.phpt @@ -0,0 +1,23 @@ +--TEST-- +Bug #60738 Allow 'set_error_handler' to handle NULL +--FILE-- +<?php + +var_dump(set_exception_handler( + function() { echo 'Intercepted exception!', "\n"; } +)); + +var_dump(set_exception_handler(null)); + +throw new Exception('Exception!'); +?> +--EXPECTF-- +NULL +object(Closure)#1 (0) { +} + +Fatal error: Uncaught exception 'Exception' with message 'Exception!' in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d + diff --git a/Zend/tests/bug61681.phpt b/Zend/tests/bug61681.phpt new file mode 100644 index 0000000000..acc0275398 --- /dev/null +++ b/Zend/tests/bug61681.phpt @@ -0,0 +1,11 @@ +--TEST-- +Bug #61681: Malformed grammar +--FILE-- +<?php +$la = "ooxx"; + +echo "${substr('laruence', 0, 2)}"; + +?> +--EXPECT-- +ooxx diff --git a/Zend/tests/bug62991.phpt b/Zend/tests/bug62991.phpt new file mode 100644 index 0000000000..cb4ff93359 --- /dev/null +++ b/Zend/tests/bug62991.phpt @@ -0,0 +1,50 @@ +--TEST-- +Bug #62991 (Segfault with generator and closure) +--FILE-- +<?php + +function test( array $array ) +{ + $closure = function() use ( $array ) { + print_r( $array ); + yield "hi"; + }; + return $closure(); +} + +function test2( array $array ) +{ + $closure = function() use ( $array ) { + print_r( $array ); + yield "hi"; + }; + return $closure; // if you return the $closure and call it outside this function it works. +} + +$generator = test(array( 1, 2, 3 ) ); +foreach($generator as $something) { +} + +$generator = test2(array( 1, 2, 3 ) ); +foreach($generator() as $something) { +} + + +$generator = test2(array( 1, 2, 3 ) ); + +echo "okey\n"; +?> +--EXPECT-- +Array +( + [0] => 1 + [1] => 2 + [2] => 3 +) +Array +( + [0] => 1 + [1] => 2 + [2] => 3 +) +okey diff --git a/Zend/tests/bug63741.phpt b/Zend/tests/bug63741.phpt new file mode 100644 index 0000000000..fc04c9e79c --- /dev/null +++ b/Zend/tests/bug63741.phpt @@ -0,0 +1,50 @@ +--TEST-- +Bug #63741 (Crash when autoloading from spl) +--FILE-- +<?php +file_put_contents(dirname(__FILE__)."/bug63741.tmp.php", +<<<'EOT' +<?php +if (isset($autoloading)) +{ + class ClassToLoad + { + static function func () + { + print "OK!\n"; + } + } + return; +} +else +{ + class autoloader + { + static function autoload($classname) + { + print "autoloading...\n"; + $autoloading = true; + include __FILE__; + } + } + + spl_autoload_register(["autoloader", "autoload"]); + + function start() + { + ClassToLoad::func(); + } + + start(); +} +?> +EOT +); + +include dirname(__FILE__)."/bug63741.tmp.php"; +?> +--CLEAN-- +<?php unlink(dirname(__FILE__)."/bug63741.tmp.php"); ?> +--EXPECT-- +autoloading... +OK! diff --git a/Zend/tests/catch_finally_001.phpt b/Zend/tests/catch_finally_001.phpt new file mode 100644 index 0000000000..0c3f597a0a --- /dev/null +++ b/Zend/tests/catch_finally_001.phpt @@ -0,0 +1,32 @@ +--TEST-- +Try catch finally (basic test) +--FILE-- +<?php +function foo ($throw = FALSE) { + try { + echo "try\n"; + if ($throw) { + throw new Exception("ex"); + } + } catch (Exception $e) { + echo "catch\n"; + } finally { + echo "finally\n"; + } + + echo "end\n"; +} + +foo(); +echo "\n"; +foo(true); +?> +--EXPECTF-- +try +finally +end + +try +catch +finally +end diff --git a/Zend/tests/catch_finally_002.phpt b/Zend/tests/catch_finally_002.phpt new file mode 100644 index 0000000000..c54477ff8c --- /dev/null +++ b/Zend/tests/catch_finally_002.phpt @@ -0,0 +1,21 @@ +--TEST-- +Try catch finally (basic test with return) +--FILE-- +<?php +function foo () { + try { + echo "try\n"; + return 1; + } catch (Exception $e) { + } finally { + echo "finally\n"; + } + return 2; +} + +var_dump(foo()); +?> +--EXPECTF-- +try +finally +int(1) diff --git a/Zend/tests/catch_finally_003.phpt b/Zend/tests/catch_finally_003.phpt new file mode 100644 index 0000000000..24e468d335 --- /dev/null +++ b/Zend/tests/catch_finally_003.phpt @@ -0,0 +1,40 @@ +--TEST-- +Try catch finally (with multi-returns) +--FILE-- +<?php +function dummy($msg) { + var_dump($msg); +} + +function foo ($a) { + try { + dummy("try"); + return $a; + } catch (Exception $e) { + throw $e; + } finally { + dummy("finally"); + return "finally"; + } + return "end"; +} + +function &bar($a) { + try { + echo "try\n"; + throw new Exception("ex"); + } catch (Exception $e) { + } finally { + return $a; + } + return ($c = "end"); +} +var_dump(foo("para")); +var_dump(bar("para")); +?> +--EXPECTF-- +string(3) "try" +string(7) "finally" +string(7) "finally" +try +string(4) "para" diff --git a/Zend/tests/catch_finally_004.phpt b/Zend/tests/catch_finally_004.phpt new file mode 100644 index 0000000000..a2c22beab1 --- /dev/null +++ b/Zend/tests/catch_finally_004.phpt @@ -0,0 +1,41 @@ +--TEST-- +Try catch finally (nesting try-catch-finally) +--FILE-- +<?php + +function throw_exception($msg) { + throw new Exception($msg); +} + +function foo (&$ex) { + try { + echo "1"; + try { + echo "2"; + throw_exception("try"); + } catch (Exception $e) { + echo "3"; + throw_exception("catch"); + } finally { + echo "4"; + throw_exception("finally"); + } + } catch (Exception $e) { + $ex = $e; + echo "3"; + } finally { + echo "2"; + } + return 1; +} + +var_dump(foo($ex)); + +do { + var_dump($ex->getMessage()); +} while ($ex = $ex->getPrevious()); +?> +--EXPECT-- +123432int(1) +string(7) "finally" +string(5) "catch" diff --git a/Zend/tests/catch_finally_005.phpt b/Zend/tests/catch_finally_005.phpt new file mode 100644 index 0000000000..c2fd55df27 --- /dev/null +++ b/Zend/tests/catch_finally_005.phpt @@ -0,0 +1,21 @@ +--TEST-- +Try catch finally (with multi-returns and exception) +--FILE-- +<?php +function foo ($a) { + try { + throw new Exception("ex"); + } catch (PdoException $e) { + die("error"); + } catch (Exception $e) { + return 2; + } finally { + return 3; + } + return 1; +} + +var_dump(foo("para")); +?> +--EXPECTF-- +int(3) diff --git a/Zend/tests/catch_finally_006.phpt b/Zend/tests/catch_finally_006.phpt new file mode 100644 index 0000000000..216219b6a5 --- /dev/null +++ b/Zend/tests/catch_finally_006.phpt @@ -0,0 +1,28 @@ +--TEST-- +Try catch finally (re-throw exception in catch block) +--FILE-- +<?php +function foo ($a) { + try { + throw new Exception("ex"); + } catch (Exception $e) { + var_dump($a); + throw $e; + } finally { + var_dump("finally"); + return "return"; + } + return 1; +} + +try { + var_dump(foo("para")); +} catch (Exception $e) { + "caught exception" . PHP_EOL; + var_dump($e->getMessage()); +} +?> +--EXPECT-- +string(4) "para" +string(7) "finally" +string(6) "return" diff --git a/Zend/tests/const_dereference_001.phpt b/Zend/tests/const_dereference_001.phpt new file mode 100644 index 0000000000..5fe6e4d433 --- /dev/null +++ b/Zend/tests/const_dereference_001.phpt @@ -0,0 +1,21 @@ +--TEST-- +Const array deference +--FILE-- +<?php +error_reporting(E_ALL); + +var_dump(array(1, 2, 3, 4,) [3]); +var_dump(array(1, 2, 3, 4,) ['foo']); +var_dump(array(array(1,2,3), array(4, 5, 6))[1][2]); + +foreach (array(array(1, 2, 3))[0] as $var) { + echo $var; +} +?> +--EXPECTF-- +int(4) + +Notice: Undefined index: foo in %sconst_dereference_001.php on line %d +NULL +int(6) +123 diff --git a/Zend/tests/const_dereference_002.phpt b/Zend/tests/const_dereference_002.phpt new file mode 100644 index 0000000000..ff89519755 --- /dev/null +++ b/Zend/tests/const_dereference_002.phpt @@ -0,0 +1,18 @@ +--TEST-- +Const string dereference +--FILE-- +<?php +error_reporting(E_ALL); + +var_dump("foobar"[3]); +var_dump("foobar"[2][0]); +var_dump("foobar"["foo"]["bar"]); + +--EXPECTF-- +string(1) "b" +string(1) "o" + +Warning: Illegal string offset 'foo' in %sconst_dereference_002.php on line %d + +Warning: Illegal string offset 'bar' in %sconst_dereference_002.php on line %d +string(1) "f" diff --git a/Zend/tests/const_dereference_003.phpt b/Zend/tests/const_dereference_003.phpt new file mode 100644 index 0000000000..810ad14b8e --- /dev/null +++ b/Zend/tests/const_dereference_003.phpt @@ -0,0 +1,21 @@ +--TEST-- +Const array deference +--FILE-- +<?php +error_reporting(E_ALL); + +var_dump([1, 2, 3, 4,][3]); +var_dump([1, 2, 3, 4]['foo']); +var_dump([array(1,2,3), [4, 5, 6]][1][2]); + +foreach (array([1, 2, 3])[0] as $var) { + echo $var; +} +?> +--EXPECTF-- +int(4) + +Notice: Undefined index: foo in %sconst_dereference_003.php on line %d +NULL +int(6) +123 diff --git a/Zend/tests/empty_with_expr.phpt b/Zend/tests/empty_with_expr.phpt new file mode 100644 index 0000000000..582eb3d2d0 --- /dev/null +++ b/Zend/tests/empty_with_expr.phpt @@ -0,0 +1,32 @@ +--TEST-- +empty() with arbitrary expressions +--FILE-- +<?php + +function getEmptyArray() { return []; } +function getNonEmptyArray() { return [1, 2, 3]; } + +var_dump(empty([])); +var_dump(empty([1, 2, 3])); + +var_dump(empty(getEmptyArray())); +var_dump(empty(getNonEmptyArray())); + +var_dump(empty([] + [])); +var_dump(empty([1, 2, 3] + [])); + +var_dump(empty("string")); +var_dump(empty("")); +var_dump(empty(true)); +var_dump(empty(false)); +--EXPECT-- +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(false) +bool(true) +bool(false) +bool(true) diff --git a/Zend/tests/errmsg_043.phpt b/Zend/tests/errmsg_043.phpt deleted file mode 100644 index 3de8bc2062..0000000000 --- a/Zend/tests/errmsg_043.phpt +++ /dev/null @@ -1,12 +0,0 @@ ---TEST-- -errmsg: cannot create references to temp array ---FILE-- -<?php - -foreach (array(1,2,3) as $k=>&$v) { -} - -echo "Done\n"; -?> ---EXPECTF-- -Fatal error: Cannot create references to elements of a temporary array expression in %s on line %d diff --git a/Zend/tests/foreach_list_001.phpt b/Zend/tests/foreach_list_001.phpt new file mode 100644 index 0000000000..a318f1aad9 --- /dev/null +++ b/Zend/tests/foreach_list_001.phpt @@ -0,0 +1,43 @@ +--TEST-- +foreach with list syntax +--FILE-- +<?php + +foreach(array(array(1,2), array(3,4)) as list($a, $b)) { + var_dump($a . $b); +} + +$array = array( + array('a', 'b'), + array('c', 'd'), +); + +foreach ($array as list($a, $b)) { + var_dump($a . $b); +} + + +$multi = array( + array(array(1,2), array(3,4)), + array(array(5,6), array(7,8)), +); + +foreach ($multi as list(list($a, $b), list($c, $d))) { + var_dump($a . $b . $c . $d); +} + +foreach ($multi as $key => list(list($a, $b), list($c, $d))) { + var_dump($key . $a . $b . $c . $d); +} + + +?> +--EXPECT-- +string(2) "12" +string(2) "34" +string(2) "ab" +string(2) "cd" +string(4) "1234" +string(4) "5678" +string(5) "01234" +string(5) "15678" diff --git a/Zend/tests/foreach_list_002.phpt b/Zend/tests/foreach_list_002.phpt new file mode 100644 index 0000000000..251870ba09 --- /dev/null +++ b/Zend/tests/foreach_list_002.phpt @@ -0,0 +1,26 @@ +--TEST-- +foreach with freak lists +--FILE-- +<?php + +foreach (array(array(1,2), array(3,4)) as list($a, )) { + var_dump($a); +} + +$array = [['a', 'b'], 'c', 'd']; + +foreach($array as list(list(), $a)) { + var_dump($a); +} + +?> +--EXPECTF-- +int(1) +int(3) +string(1) "b" + +Notice: Uninitialized string offset: 1 in %sforeach_list_002.php on line %d +string(0) "" + +Notice: Uninitialized string offset: 1 in %sforeach_list_002.php on line %d +string(0) "" diff --git a/Zend/tests/foreach_list_003.phpt b/Zend/tests/foreach_list_003.phpt new file mode 100644 index 0000000000..8674ecd754 --- /dev/null +++ b/Zend/tests/foreach_list_003.phpt @@ -0,0 +1,13 @@ +--TEST-- +foreach with list key +--FILE-- +<?php + +$array = [['a', 'b'], 'c', 'd']; + +foreach($array as list($key) => list(list(), $a)) { +} + +?> +--EXPECTF-- +Fatal error: Cannot use list as key element in %sforeach_list_003.php on line %d diff --git a/Zend/tests/foreach_list_004.phpt b/Zend/tests/foreach_list_004.phpt new file mode 100644 index 0000000000..fd48e8a1f3 --- /dev/null +++ b/Zend/tests/foreach_list_004.phpt @@ -0,0 +1,13 @@ +--TEST-- +foreach with empty list +--FILE-- +<?php + +$array = [['a', 'b'], 'c', 'd']; + +foreach($array as $key => list()) { +} + +?> +--EXPECTF-- +Fatal error: Cannot use empty list in %sforeach_list_004.php on line %d diff --git a/Zend/tests/foreach_temp_array_expr_with_refs.phpt b/Zend/tests/foreach_temp_array_expr_with_refs.phpt new file mode 100644 index 0000000000..8978b7b011 --- /dev/null +++ b/Zend/tests/foreach_temp_array_expr_with_refs.phpt @@ -0,0 +1,18 @@ +--TEST-- +Temporary array expressions can be iterated by reference +--FILE-- +<?php + +$a = 'a'; +$b = 'b'; + +foreach ([&$a, &$b] as &$value) { + $value .= '-foo'; +} + +var_dump($a, $b); + +?> +--EXPECT-- +string(5) "a-foo" +string(5) "b-foo" diff --git a/Zend/tests/generators/auto_incrementing_keys.phpt b/Zend/tests/generators/auto_incrementing_keys.phpt new file mode 100644 index 0000000000..acfb2f2ce0 --- /dev/null +++ b/Zend/tests/generators/auto_incrementing_keys.phpt @@ -0,0 +1,22 @@ +--TEST-- +Generator keys are auto-incrementing by default +--FILE-- +<?php + +function gen() { + yield 'foo'; + yield 'bar'; + yield 5 => 'rab'; + yield 'oof'; +} + +foreach (gen() as $k => $v) { + echo $k, ' => ', $v, "\n"; +} + +?> +--EXPECT-- +0 => foo +1 => bar +5 => rab +6 => oof diff --git a/Zend/tests/generators/backtrace.phpt b/Zend/tests/generators/backtrace.phpt new file mode 100644 index 0000000000..5fed1d467e --- /dev/null +++ b/Zend/tests/generators/backtrace.phpt @@ -0,0 +1,27 @@ +--TEST-- +Printing the stack trace in a generator +--FILE-- +<?php + +function f1() { + debug_print_backtrace(); +} + +function f2($arg1, $arg2) { + f1(); + yield; // force generator +} + +function f3($gen) { + $gen->rewind(); // trigger run +} + +$gen = f2('foo', 'bar'); +f3($gen); + +?> +--EXPECTF-- +#0 f1() called at [%s:%d] +#1 f2(foo, bar) +#2 Generator->rewind() called at [%s:%d] +#3 f3(Generator Object ()) called at [%s:%d] diff --git a/Zend/tests/generators/bug63066.phpt b/Zend/tests/generators/bug63066.phpt new file mode 100644 index 0000000000..8c4c8b4a84 --- /dev/null +++ b/Zend/tests/generators/bug63066.phpt @@ -0,0 +1,16 @@ +--TEST-- +Bug #63066 (Calling an undefined method in a generator results in a seg fault) +--FILE-- +<?php +function gen($o) +{ + yield 'foo'; + $o->fatalError(); +} + +foreach(gen(new stdClass()) as $value) + echo $value, "\n"; +--EXPECTF-- +foo + +Fatal error: Call to undefined method stdClass::fatalError() in %sbug63066.php on line 5 diff --git a/Zend/tests/generators/clone.phpt b/Zend/tests/generators/clone.phpt new file mode 100644 index 0000000000..36811dfe6e --- /dev/null +++ b/Zend/tests/generators/clone.phpt @@ -0,0 +1,32 @@ +--TEST-- +Generators can be cloned +--FILE-- +<?php + +function firstN($end) { + for ($i = 0; $i < $end; ++$i) { + yield $i; + } +} + +$g1 = firstN(5); +var_dump($g1->current()); +$g1->next(); + +$g2 = clone $g1; +var_dump($g2->current()); +$g2->next(); + +var_dump($g2->current()); +var_dump($g1->current()); + +$g1->next(); +var_dump($g1->current()); + +?> +--EXPECT-- +int(0) +int(1) +int(2) +int(1) +int(2) diff --git a/Zend/tests/generators/clone_after_object_call.phpt b/Zend/tests/generators/clone_after_object_call.phpt new file mode 100644 index 0000000000..0a424268cc --- /dev/null +++ b/Zend/tests/generators/clone_after_object_call.phpt @@ -0,0 +1,20 @@ +--TEST-- +Cloning a generator after an object method was called +--FILE-- +<?php + +class A { public function b() { } } + +function gen() { + $a = new A; + $a->b(); + yield; +} + +$g1 = gen(); +$g1->rewind(); +$g2 = clone $g1; + +echo "Done"; +--EXPECT-- +Done diff --git a/Zend/tests/generators/clone_with_foreach.phpt b/Zend/tests/generators/clone_with_foreach.phpt new file mode 100644 index 0000000000..b05ed07312 --- /dev/null +++ b/Zend/tests/generators/clone_with_foreach.phpt @@ -0,0 +1,33 @@ +--TEST-- +Cloning a generator with a foreach loop properly adds a ref for the loop var +--FILE-- +<?php + +function gen() { + foreach ([1, 2, 3] as $i) { + yield $i; + } +} + +$g1 = gen(); +var_dump($g1->current()); + +$g2 = clone $g1; +var_dump($g2->current()); + +$g1->next(); +$g2->next(); +var_dump($g1->current()); +var_dump($g2->current()); + +unset($g1); +$g2->next(); +var_dump($g2->current()); + +?> +--EXPECT-- +int(1) +int(1) +int(2) +int(2) +int(3) diff --git a/Zend/tests/generators/clone_with_stack.phpt b/Zend/tests/generators/clone_with_stack.phpt new file mode 100644 index 0000000000..5a8e6d842c --- /dev/null +++ b/Zend/tests/generators/clone_with_stack.phpt @@ -0,0 +1,18 @@ +--TEST-- +A generator with an active stack can be cloned +--FILE-- +<?php + +function gen() { + var_dump(str_repeat("x", yield)); +} + +$g1 = gen(); +$g1->rewind(); +$g2 = clone $g1; +unset($g1); +$g2->send(10); + +?> +--EXPECT-- +string(10) "xxxxxxxxxx" diff --git a/Zend/tests/generators/clone_with_symbol_table.phpt b/Zend/tests/generators/clone_with_symbol_table.phpt new file mode 100644 index 0000000000..e1fefebd8f --- /dev/null +++ b/Zend/tests/generators/clone_with_symbol_table.phpt @@ -0,0 +1,27 @@ +--TEST-- +A generator using a symbol table can be cloned +--FILE-- +<?php + +function gen() { + // force compiled variable for $foo + $foo = 'foo'; + + // force symbol table + extract(['foo' => 'bar']); + + // interrupt + yield; + + var_dump($foo); +} + +$g1 = gen(); +$g1->rewind(); +$g2 = clone $g1; +unset($g1); +$g2->next(); + +?> +--EXPECT-- +string(3) "bar" diff --git a/Zend/tests/generators/clone_with_this.phpt b/Zend/tests/generators/clone_with_this.phpt new file mode 100644 index 0000000000..b242d851eb --- /dev/null +++ b/Zend/tests/generators/clone_with_this.phpt @@ -0,0 +1,24 @@ +--TEST-- +Cloning a generator method (with $this) +--FILE-- +<?php + +class Test { + protected $foo; + + public function gen() { + $this->foo = 'bar'; + yield; // interrupt + var_dump($this->foo); + } +} + +$g1 = (new Test)->gen(); +$g1->rewind(); // goto yield +$g2 = clone $g1; +unset($g1); +$g2->next(); + +?> +--EXPECT-- +string(3) "bar" diff --git a/Zend/tests/generators/dynamic_call.phpt b/Zend/tests/generators/dynamic_call.phpt new file mode 100644 index 0000000000..d564540952 --- /dev/null +++ b/Zend/tests/generators/dynamic_call.phpt @@ -0,0 +1,19 @@ +--TEST-- +It's possible to invoke a generator dynamically +--FILE-- +<?php + +function gen($foo, $bar) { + yield $foo; + yield $bar; +} + +$gen = call_user_func('gen', 'bar', 'foo'); +foreach ($gen as $value) { + var_dump($value); +} + +?> +--EXPECT-- +string(3) "bar" +string(3) "foo" diff --git a/Zend/tests/generators/errors/generator_cannot_return_before_yield_error.phpt b/Zend/tests/generators/errors/generator_cannot_return_before_yield_error.phpt new file mode 100644 index 0000000000..ad618d20ba --- /dev/null +++ b/Zend/tests/generators/errors/generator_cannot_return_before_yield_error.phpt @@ -0,0 +1,13 @@ +--TEST-- +Generators cannot return values (even before yield) +--FILE-- +<?php + +function gen() { + return $foo; + yield; +} + +?> +--EXPECTF-- +Fatal error: Generators cannot return values using "return" in %s on line 4 diff --git a/Zend/tests/generators/errors/generator_cannot_return_error.phpt b/Zend/tests/generators/errors/generator_cannot_return_error.phpt new file mode 100644 index 0000000000..51149062a7 --- /dev/null +++ b/Zend/tests/generators/errors/generator_cannot_return_error.phpt @@ -0,0 +1,13 @@ +--TEST-- +Generators cannot return values +--FILE-- +<?php + +function gen() { + yield; + return $abc; +} + +?> +--EXPECTF-- +Fatal error: Generators cannot return values using "return" in %s on line 5 diff --git a/Zend/tests/generators/errors/generator_extend_error.phpt b/Zend/tests/generators/errors/generator_extend_error.phpt new file mode 100644 index 0000000000..550f16ae03 --- /dev/null +++ b/Zend/tests/generators/errors/generator_extend_error.phpt @@ -0,0 +1,10 @@ +--TEST-- +The Generator class cannot be extended +--FILE-- +<?php + +class ExtendedGenerator extends Generator { } + +?> +--EXPECTF-- +Fatal error: Class ExtendedGenerator may not inherit from final class (Generator) in %s on line %d diff --git a/Zend/tests/generators/errors/generator_instantiate_error.phpt b/Zend/tests/generators/errors/generator_instantiate_error.phpt new file mode 100644 index 0000000000..f8941c087a --- /dev/null +++ b/Zend/tests/generators/errors/generator_instantiate_error.phpt @@ -0,0 +1,10 @@ +--TEST-- +It's not possible to directly instantiate the Generator class +--FILE-- +<?php + +new Generator; + +?> +--EXPECTF-- +Catchable fatal error: The "Generator" class is reserved for internal use and cannot be manually instantiated in %s on line %d diff --git a/Zend/tests/generators/errors/non_ref_generator_iterated_by_ref_error.phpt b/Zend/tests/generators/errors/non_ref_generator_iterated_by_ref_error.phpt new file mode 100644 index 0000000000..de5b22f6ba --- /dev/null +++ b/Zend/tests/generators/errors/non_ref_generator_iterated_by_ref_error.phpt @@ -0,0 +1,18 @@ +--TEST-- +Non-ref generators cannot be iterated by-ref +--FILE-- +<?php + +function gen() { yield; } + +$gen = gen(); +foreach ($gen as &$value) { } + +?> +--EXPECTF-- +Fatal error: Uncaught exception 'Exception' with message 'You can only iterate a generator by-reference if it declared that it yields by-reference' in %s:%d +Stack trace: +#0 %s(%d): unknown() +#1 {main} + thrown in %s on line %d + diff --git a/Zend/tests/generators/errors/resume_running_generator_error.phpt b/Zend/tests/generators/errors/resume_running_generator_error.phpt new file mode 100644 index 0000000000..567d72f3f9 --- /dev/null +++ b/Zend/tests/generators/errors/resume_running_generator_error.phpt @@ -0,0 +1,17 @@ +--TEST-- +It is not possible to resume an already running generator +--FILE-- +<?php + +function gen() { + $gen = yield; + $gen->next(); +} + +$gen = gen(); +$gen->send($gen); +$gen->next(); + +?> +--EXPECTF-- +Fatal error: Cannot resume an already running generator in %s on line %d diff --git a/Zend/tests/generators/errors/serialize_unserialize_error.phpt b/Zend/tests/generators/errors/serialize_unserialize_error.phpt new file mode 100644 index 0000000000..a8470b0a63 --- /dev/null +++ b/Zend/tests/generators/errors/serialize_unserialize_error.phpt @@ -0,0 +1,46 @@ +--TEST-- +Generators can't be serialized or unserialized +--FILE-- +<?php + +function gen() { yield; } + +$gen = gen(); + +try { + serialize($gen); +} catch (Exception $e) { + echo $e, "\n\n"; +} + +try { + var_dump(unserialize('O:9:"Generator":0:{}')); +} catch (Exception $e) { + echo $e, "\n\n"; +} + +try { + var_dump(unserialize('C:9:"Generator":0:{}')); +} catch (Exception $e) { + echo $e; +} + +?> +--EXPECTF-- +exception 'Exception' with message 'Serialization of 'Generator' is not allowed' in %s:%d +Stack trace: +#0 %s(%d): serialize(Object(Generator)) +#1 {main} + +exception 'Exception' with message 'Unserialization of 'Generator' is not allowed' in %s:%d +Stack trace: +#0 [internal function]: Generator->__wakeup() +#1 %s(%d): unserialize('O:9:"Generator"...') +#2 {main} + + +Notice: unserialize(): Error at offset 19 of 20 bytes in %s on line %d +exception 'Exception' with message 'Unserialization of 'Generator' is not allowed' in %s:%d +Stack trace: +#0 %s(%d): unserialize('C:9:"Generator"...') +#1 {main} diff --git a/Zend/tests/generators/errors/yield_const_by_ref_error.phpt b/Zend/tests/generators/errors/yield_const_by_ref_error.phpt new file mode 100644 index 0000000000..e79f83e24a --- /dev/null +++ b/Zend/tests/generators/errors/yield_const_by_ref_error.phpt @@ -0,0 +1,16 @@ +--TEST-- +A notice is thrown when yielding a constant value by reference +--FILE-- +<?php + +function &gen() { + yield "foo"; +} + +$gen = gen(); +var_dump($gen->current()); + +?> +--EXPECTF-- +Notice: Only variable references should be yielded by reference in %s on line %d +string(3) "foo" diff --git a/Zend/tests/generators/errors/yield_in_force_closed_finally_error.phpt b/Zend/tests/generators/errors/yield_in_force_closed_finally_error.phpt new file mode 100644 index 0000000000..aada676a68 --- /dev/null +++ b/Zend/tests/generators/errors/yield_in_force_closed_finally_error.phpt @@ -0,0 +1,29 @@ +--TEST-- +yield cannot be used in a finally block when the generator is force-closed +--FILE-- +<?php + +function gen() { + try { + echo "before yield\n"; + yield; + echo "after yield\n"; + } finally { + echo "before yield in finally\n"; + yield; + echo "after yield in finally\n"; + } + + echo "after finally\n"; +} + +$gen = gen(); +$gen->rewind(); +unset($gen); + +?> +--EXPECTF-- +before yield +before yield in finally + +Fatal error: Cannot yield from finally in a force-closed generator in %s on line %d diff --git a/Zend/tests/generators/errors/yield_non_ref_function_call_by_ref_error.phpt b/Zend/tests/generators/errors/yield_non_ref_function_call_by_ref_error.phpt new file mode 100644 index 0000000000..4b8563331c --- /dev/null +++ b/Zend/tests/generators/errors/yield_non_ref_function_call_by_ref_error.phpt @@ -0,0 +1,20 @@ +--TEST-- +Yielding the result of a non-ref function call throw a notice +--FILE-- +<?php + +function foo() { + return "bar"; +} + +function &gen() { + yield foo(); +} + +$gen = gen(); +var_dump($gen->current()); + +?> +--EXPECTF-- +Notice: Only variable references should be yielded by reference in %s on line %d +string(3) "bar" diff --git a/Zend/tests/generators/errors/yield_outside_function_error.phpt b/Zend/tests/generators/errors/yield_outside_function_error.phpt new file mode 100644 index 0000000000..f999c1c03b --- /dev/null +++ b/Zend/tests/generators/errors/yield_outside_function_error.phpt @@ -0,0 +1,10 @@ +--TEST-- +Yield cannot be used outside of functions +--FILE-- +<?php + +yield "Test"; + +?> +--EXPECTF-- +Fatal error: The "yield" expression can only be used inside a function in %s on line %d diff --git a/Zend/tests/generators/fibonacci.phpt b/Zend/tests/generators/fibonacci.phpt new file mode 100644 index 0000000000..35b31352ff --- /dev/null +++ b/Zend/tests/generators/fibonacci.phpt @@ -0,0 +1,36 @@ +--TEST-- +Creating an infinite fibonacci list using a generator +--FILE-- +<?php + +function fib() { + list($a, $b) = [1, 1]; + while (true) { + yield $b; + list($a, $b) = [$b, $a + $b]; + } +} + +foreach (fib() as $n) { + if ($n > 1000) break; + + var_dump($n); +} + +?> +--EXPECT-- +int(1) +int(2) +int(3) +int(5) +int(8) +int(13) +int(21) +int(34) +int(55) +int(89) +int(144) +int(233) +int(377) +int(610) +int(987) diff --git a/Zend/tests/generators/finally/finally_ran_on_close.phpt b/Zend/tests/generators/finally/finally_ran_on_close.phpt new file mode 100644 index 0000000000..04a0561c87 --- /dev/null +++ b/Zend/tests/generators/finally/finally_ran_on_close.phpt @@ -0,0 +1,30 @@ +--TEST-- +finally is run even if a generator is closed mid-execution +--FILE-- +<?php + +function gen() { + try { + try { + echo "before yield\n"; + yield; + echo "after yield\n"; + } finally { + echo "finally run\n"; + } + echo "code after finally\n"; + } finally { + echo "second finally run\n"; + } + echo "code after second finally\n"; +} + +$gen = gen(); +$gen->rewind(); +unset($gen); + +?> +--EXPECT-- +before yield +finally run +second finally run diff --git a/Zend/tests/generators/finally/return_return.phpt b/Zend/tests/generators/finally/return_return.phpt new file mode 100644 index 0000000000..02e2739de7 --- /dev/null +++ b/Zend/tests/generators/finally/return_return.phpt @@ -0,0 +1,33 @@ +--TEST-- +try { return } finally { return } in generator +--FILE-- +<?php + +function gen() { + try { + try { + echo "before return\n"; + return; + echo "after return\n"; + } finally { + echo "before return in inner finally\n"; + return; + echo "after return in inner finally\n"; + } + } finally { + echo "outer finally run\n"; + } + + echo "code after finally\n"; + + yield; // force generator +} + +$gen = gen(); +$gen->rewind(); // force run + +?> +--EXPECTF-- +before return +before return in inner finally +outer finally run diff --git a/Zend/tests/generators/finally/return_yield.phpt b/Zend/tests/generators/finally/return_yield.phpt new file mode 100644 index 0000000000..c4f3485987 --- /dev/null +++ b/Zend/tests/generators/finally/return_yield.phpt @@ -0,0 +1,18 @@ +--TEST-- +try { return } finally { yield } +--FILE-- +<?php +function foo($f, $t) { + for ($i = $f; $i <= $t; $i++) { + try { + return; + } finally { + yield $i; + } + } +} +foreach (foo(1, 5) as $x) { + echo $x, "\n"; +} +--EXPECT-- +1 diff --git a/Zend/tests/generators/finally/throw_yield.phpt b/Zend/tests/generators/finally/throw_yield.phpt new file mode 100644 index 0000000000..2013c3ee14 --- /dev/null +++ b/Zend/tests/generators/finally/throw_yield.phpt @@ -0,0 +1,24 @@ +--TEST-- +try { throw } finally { yield } +--FILE-- +<?php +function foo($f, $t) { + for ($i = $f; $i <= $t; $i++) { + try { + throw new Exception; + } finally { + yield $i; + } + } +} +foreach (foo(1, 5) as $x) { + echo $x, "\n"; +} +--EXPECTF-- +1 + +Fatal error: Uncaught exception 'Exception' in %s:%d +Stack trace: +#0 %s(%d): foo(1, 5) +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/generators/finally/yield_return.phpt b/Zend/tests/generators/finally/yield_return.phpt new file mode 100644 index 0000000000..e3e1bec357 --- /dev/null +++ b/Zend/tests/generators/finally/yield_return.phpt @@ -0,0 +1,18 @@ +--TEST-- +try { yield } finally { return } +--FILE-- +<?php +function foo($f, $t) { + for ($i = $f; $i <= $t; $i++) { + try { + yield $i; + } finally { + return; + } + } +} +foreach (foo(1, 5) as $x) { + echo $x, "\n"; +} +--EXPECT-- +1 diff --git a/Zend/tests/generators/finally/yield_throw.phpt b/Zend/tests/generators/finally/yield_throw.phpt new file mode 100644 index 0000000000..0ead4501af --- /dev/null +++ b/Zend/tests/generators/finally/yield_throw.phpt @@ -0,0 +1,24 @@ +--TEST-- +try { yield } finally { throw } +--FILE-- +<?php +function foo($f, $t) { + for ($i = $f; $i <= $t; $i++) { + try { + yield $i; + } finally { + throw new Exception; + } + } +} +foreach (foo(1, 5) as $x) { + echo $x, "\n"; +} +--EXPECTF-- +1 + +Fatal error: Uncaught exception 'Exception' in %s:%d +Stack trace: +#0 %s(%d): foo(1, 5) +#1 {main} + thrown in %s on line %d diff --git a/Zend/tests/generators/finally/yield_yield.phpt b/Zend/tests/generators/finally/yield_yield.phpt new file mode 100644 index 0000000000..76610ef1a4 --- /dev/null +++ b/Zend/tests/generators/finally/yield_yield.phpt @@ -0,0 +1,22 @@ +--TEST-- +Try { yield } finally { yield } +--FILE-- +<?php + +function foo() { + try { + echo "1"; + yield "2"; + echo "3"; + } finally { + echo "4"; + yield "5"; + echo "6"; + } + echo "7"; +} +foreach (foo() as $x) { + echo $x; +} +--EXPECT-- +1234567 diff --git a/Zend/tests/generators/func_get_args.phpt b/Zend/tests/generators/func_get_args.phpt new file mode 100644 index 0000000000..f8d3fa7c14 --- /dev/null +++ b/Zend/tests/generators/func_get_args.phpt @@ -0,0 +1,21 @@ +--TEST-- +func_get_args() can be used inside generator functions +--FILE-- +<?php + +function gen() { + var_dump(func_get_args()); + yield; // trigger generator +} + +$gen = gen("foo", "bar"); +$gen->rewind(); + +?> +--EXPECT-- +array(2) { + [0]=> + string(3) "foo" + [1]=> + string(3) "bar" +} diff --git a/Zend/tests/generators/generator_closure.phpt b/Zend/tests/generators/generator_closure.phpt new file mode 100644 index 0000000000..bf80066015 --- /dev/null +++ b/Zend/tests/generators/generator_closure.phpt @@ -0,0 +1,20 @@ +--TEST-- +Closures can be generators +--FILE-- +<?php + +$genFactory = function() { + yield 1; + yield 2; + yield 3; +}; + +foreach ($genFactory() as $value) { + var_dump($value); +} + +?> +--EXPECT-- +int(1) +int(2) +int(3) diff --git a/Zend/tests/generators/generator_closure_with_this.phpt b/Zend/tests/generators/generator_closure_with_this.phpt new file mode 100644 index 0000000000..d5a4861e80 --- /dev/null +++ b/Zend/tests/generators/generator_closure_with_this.phpt @@ -0,0 +1,20 @@ +--TEST-- +Non-static closures can be generators +--FILE-- +<?php + +class Test { + public function getGenFactory() { + return function() { + yield $this; + }; + } +} + +$genFactory = (new Test)->getGenFactory(); +var_dump($genFactory()->current()); + +?> +--EXPECT-- +object(Test)#1 (0) { +} diff --git a/Zend/tests/generators/generator_in_multipleiterator.phpt b/Zend/tests/generators/generator_in_multipleiterator.phpt new file mode 100644 index 0000000000..611dbc9652 --- /dev/null +++ b/Zend/tests/generators/generator_in_multipleiterator.phpt @@ -0,0 +1,37 @@ +--TEST-- +Generators work properly in MultipleIterator +--FILE-- +<?php + +function gen1() { + yield 'a'; + yield 'aa'; +} + +function gen2() { + yield 'b'; + yield 'bb'; +} + +$it = new MultipleIterator; +$it->attachIterator(gen1()); +$it->attachIterator(gen2()); + +foreach ($it as $values) { + var_dump($values); +} + +?> +--EXPECT-- +array(2) { + [0]=> + string(1) "a" + [1]=> + string(1) "b" +} +array(2) { + [0]=> + string(2) "aa" + [1]=> + string(2) "bb" +} diff --git a/Zend/tests/generators/generator_method.phpt b/Zend/tests/generators/generator_method.phpt new file mode 100644 index 0000000000..b8196c171e --- /dev/null +++ b/Zend/tests/generators/generator_method.phpt @@ -0,0 +1,29 @@ +--TEST-- +Methods can be generators +--FILE-- +<?php + +class Test implements IteratorAggregate { + protected $data; + + public function __construct(array $data) { + $this->data = $data; + } + + public function getIterator() { + foreach ($this->data as $value) { + yield $value; + } + } +} + +$test = new Test(['foo', 'bar', 'baz']); +foreach ($test as $value) { + var_dump($value); +} + +?> +--EXPECT-- +string(3) "foo" +string(3) "bar" +string(3) "baz" diff --git a/Zend/tests/generators/generator_method_by_ref.phpt b/Zend/tests/generators/generator_method_by_ref.phpt new file mode 100644 index 0000000000..cfe52fe67f --- /dev/null +++ b/Zend/tests/generators/generator_method_by_ref.phpt @@ -0,0 +1,44 @@ +--TEST-- +Generator methods can yield by reference +--FILE-- +<?php + +class Test implements IteratorAggregate { + protected $data; + + public function __construct(array $data) { + $this->data = $data; + } + + public function getData() { + return $this->data; + } + + public function &getIterator() { + foreach ($this->data as $key => &$value) { + yield $key => $value; + } + } +} + +$test = new Test([1, 2, 3, 4, 5]); +foreach ($test as &$value) { + $value *= -1; +} + +var_dump($test->getData()); + +?> +--EXPECT-- +array(5) { + [0]=> + int(-1) + [1]=> + int(-2) + [2]=> + int(-3) + [3]=> + int(-4) + [4]=> + &int(-5) +} diff --git a/Zend/tests/generators/generator_returns_generator.phpt b/Zend/tests/generators/generator_returns_generator.phpt new file mode 100644 index 0000000000..ad332a3be9 --- /dev/null +++ b/Zend/tests/generators/generator_returns_generator.phpt @@ -0,0 +1,18 @@ +--TEST-- +A generator function returns a Generator object +--FILE-- +<?php + +function gen() { + // execution is suspended here, so the following never gets run: + echo "Foo"; + // trigger a generator + yield; +} + +$generator = gen(); +var_dump($generator instanceof Generator); + +?> +--EXPECT-- +bool(true) diff --git a/Zend/tests/generators/generator_rewind.phpt b/Zend/tests/generators/generator_rewind.phpt new file mode 100644 index 0000000000..c4b5bbbdf4 --- /dev/null +++ b/Zend/tests/generators/generator_rewind.phpt @@ -0,0 +1,62 @@ +--TEST-- +A generator can only be rewinded before or at the first yield +--FILE-- +<?php + +function gen() { + echo "before yield\n"; + yield; + echo "after yield\n"; + yield; +} + +$gen = gen(); +$gen->rewind(); +$gen->rewind(); +$gen->next(); + +try { + $gen->rewind(); +} catch (Exception $e) { + echo "\n", $e, "\n\n"; +} + +function &gen2() { + $foo = 'bar'; + yield $foo; + yield $foo; +} + +$gen = gen2(); +foreach ($gen as $v) { } +try { + foreach ($gen as $v) { } +} catch (Exception $e) { + echo $e, "\n\n"; +} + +function gen3() { + echo "in generator\n"; + + if (false) yield; +} + +$gen = gen3(); +$gen->rewind(); + +?> +--EXPECTF-- +before yield +after yield + +exception 'Exception' with message 'Cannot rewind a generator that was already run' in %s:%d +Stack trace: +#0 %s(%d): Generator->rewind() +#1 {main} + +exception 'Exception' with message 'Cannot traverse an already closed generator' in %s:%d +Stack trace: +#0 %s(%d): unknown() +#1 {main} + +in generator diff --git a/Zend/tests/generators/generator_send.phpt b/Zend/tests/generators/generator_send.phpt new file mode 100644 index 0000000000..074d815389 --- /dev/null +++ b/Zend/tests/generators/generator_send.phpt @@ -0,0 +1,22 @@ +--TEST-- +Values can be sent back to the generator +--FILE-- +<?php + +function gen() { + var_dump(yield "yield foo"); + var_dump(yield "yield bar"); +} + +$gen = gen(); +var_dump($gen->current()); +$gen->send("send bar"); +var_dump($gen->current()); +$gen->send("send foo"); + +?> +--EXPECT-- +string(9) "yield foo" +string(8) "send bar" +string(9) "yield bar" +string(8) "send foo" diff --git a/Zend/tests/generators/generator_static_method.phpt b/Zend/tests/generators/generator_static_method.phpt new file mode 100644 index 0000000000..cd9b450a76 --- /dev/null +++ b/Zend/tests/generators/generator_static_method.phpt @@ -0,0 +1,29 @@ +--TEST-- +A static method can be a generator +--FILE-- +<?php + +class Test { + public static function gen() { + var_dump(get_class()); + var_dump(get_called_class()); + yield 1; + yield 2; + yield 3; + } +} + +class ExtendedTest extends Test { +} + +foreach (ExtendedTest::gen() as $i) { + var_dump($i); +} + +?> +--EXPECT-- +string(4) "Test" +string(12) "ExtendedTest" +int(1) +int(2) +int(3) diff --git a/Zend/tests/generators/generator_throwing_during_function_call.phpt b/Zend/tests/generators/generator_throwing_during_function_call.phpt new file mode 100644 index 0000000000..bd0d2448b7 --- /dev/null +++ b/Zend/tests/generators/generator_throwing_during_function_call.phpt @@ -0,0 +1,32 @@ +--TEST-- +Stack is cleaned up properly when an exception is thrown during a function call +--FILE-- +<?php + +function throwException() { + throw new Exception('test'); +} + +function gen() { + yield 'foo'; + strlen("foo", "bar", throwException()); + yield 'bar'; +} + +$gen = gen(); + +var_dump($gen->current()); + +try { + $gen->next(); +} catch (Exception $e) { + echo 'Caught exception with message "', $e->getMessage(), '"', "\n"; +} + +var_dump($gen->current()); + +?> +--EXPECT-- +string(3) "foo" +Caught exception with message "test" +NULL diff --git a/Zend/tests/generators/generator_throwing_exception.phpt b/Zend/tests/generators/generator_throwing_exception.phpt new file mode 100644 index 0000000000..f537c3fc77 --- /dev/null +++ b/Zend/tests/generators/generator_throwing_exception.phpt @@ -0,0 +1,28 @@ +--TEST-- +Generators can throw exceptions +--FILE-- +<?php + +function gen() { + yield 'foo'; + throw new Exception('test'); + yield 'bar'; +} + +$gen = gen(); + +var_dump($gen->current()); + +try { + $gen->next(); +} catch (Exception $e) { + echo 'Caught exception with message "', $e->getMessage(), '"', "\n"; +} + +var_dump($gen->current()); + +?> +--EXPECT-- +string(3) "foo" +Caught exception with message "test" +NULL diff --git a/Zend/tests/generators/generator_throwing_in_foreach.phpt b/Zend/tests/generators/generator_throwing_in_foreach.phpt new file mode 100644 index 0000000000..dbf20c2ca1 --- /dev/null +++ b/Zend/tests/generators/generator_throwing_in_foreach.phpt @@ -0,0 +1,20 @@ +--TEST-- +Exceptions throwing by generators during foreach iteration are properly handled +--FILE-- +<?php + +function gen() { + throw new Exception("foo"); + yield; // force generator +} + +foreach (gen() as $value) { } + +?> +--EXPECTF-- +Fatal error: Uncaught exception 'Exception' with message 'foo' in %s:%d +Stack trace: +#0 %s(%d): gen() +#1 {main} + thrown in %s on line %d + diff --git a/Zend/tests/generators/generator_with_keys.phpt b/Zend/tests/generators/generator_with_keys.phpt new file mode 100644 index 0000000000..efb377679e --- /dev/null +++ b/Zend/tests/generators/generator_with_keys.phpt @@ -0,0 +1,26 @@ +--TEST-- +Generators can also yield keys +--FILE-- +<?php + +function reverse(array $array) { + end($array); + while (null !== $key = key($array)) { + yield $key => current($array); + prev($array); + } +} + +$array = [ + 'foo' => 'bar', + 'bar' => 'foo', +]; + +foreach (reverse($array) as $key => $value) { + echo $key, ' => ', $value, "\n"; +} + +?> +--EXPECT-- +bar => foo +foo => bar diff --git a/Zend/tests/generators/ignored_send_leak.phpt b/Zend/tests/generators/ignored_send_leak.phpt new file mode 100644 index 0000000000..352ba406ba --- /dev/null +++ b/Zend/tests/generators/ignored_send_leak.phpt @@ -0,0 +1,17 @@ +--TEST-- +Ignoring a sent value shouldn't leak memory +--FILE-- +<?php + +function gen() { + yield; +} + +$gen = gen(); +$gen->send(NULL); + +echo "DONE"; + +?> +--EXPECT-- +DONE diff --git a/Zend/tests/generators/nested_method_calls.phpt b/Zend/tests/generators/nested_method_calls.phpt new file mode 100644 index 0000000000..98aee2e60b --- /dev/null +++ b/Zend/tests/generators/nested_method_calls.phpt @@ -0,0 +1,39 @@ +--TEST-- +Yield can be used in nested method calls +--FILE-- +<?php + +class A { + function foo() { + echo "Called A::foo\n"; + } +} + +class B { + function foo() { + echo "Called B::foo\n"; + } +} + +function gen($obj) { + $obj->foo($obj->foo(yield)); +} + +$g1 = gen(new A); +$g1->current(); + +$g2 = gen(new B); +$g2->current(); + +$g1->next(); + +$g3 = clone $g2; +unset($g2); +$g3->next(); + +?> +--EXPECT-- +Called A::foo +Called A::foo +Called B::foo +Called B::foo diff --git a/Zend/tests/generators/no_foreach_var_leaks.phpt b/Zend/tests/generators/no_foreach_var_leaks.phpt new file mode 100644 index 0000000000..62743895eb --- /dev/null +++ b/Zend/tests/generators/no_foreach_var_leaks.phpt @@ -0,0 +1,19 @@ +--TEST-- +foreach() (and other) variables aren't leaked on premature close +--FILE-- +<?php + +function gen(array $array) { + foreach ($array as $value) { + yield $value; + } +} + +$gen = gen(['Foo', 'Bar']); +var_dump($gen->current()); + +// generator is closed here, without running SWITCH_FREE + +?> +--EXPECT-- +string(3) "Foo" diff --git a/Zend/tests/generators/send_after_close.phpt b/Zend/tests/generators/send_after_close.phpt new file mode 100644 index 0000000000..806baf8cee --- /dev/null +++ b/Zend/tests/generators/send_after_close.phpt @@ -0,0 +1,14 @@ +--TEST-- +Calls to send() after close should do nothing +--FILE-- +<?php + +function gen() { var_dump(yield); } + +$gen = gen(); +$gen->send('foo'); +$gen->send('bar'); + +?> +--EXPECT-- +string(3) "foo" diff --git a/Zend/tests/generators/send_returns_current.phpt b/Zend/tests/generators/send_returns_current.phpt new file mode 100644 index 0000000000..27ba74bc1b --- /dev/null +++ b/Zend/tests/generators/send_returns_current.phpt @@ -0,0 +1,20 @@ +--TEST-- +$generator->send() returns the yielded value +--FILE-- +<?php + +function reverseEchoGenerator() { + $data = yield; + while (true) { + $data = (yield strrev($data)); + } +} + +$gen = reverseEchoGenerator(); +var_dump($gen->send('foo')); +var_dump($gen->send('bar')); + +?> +--EXPECT-- +string(3) "oof" +string(3) "rab" diff --git a/Zend/tests/generators/throw_already_closed.phpt b/Zend/tests/generators/throw_already_closed.phpt new file mode 100644 index 0000000000..e918e540ab --- /dev/null +++ b/Zend/tests/generators/throw_already_closed.phpt @@ -0,0 +1,23 @@ +--TEST-- +Generator::throw() on an already closed generator +--FILE-- +<?php + +function gen() { + yield; +} + +$gen = gen(); +$gen->next(); +$gen->next(); +var_dump($gen->valid()); +$gen->throw(new Exception('test')); + +?> +--EXPECTF-- +bool(false) + +Fatal error: Uncaught exception 'Exception' with message 'test' in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/generators/throw_caught.phpt b/Zend/tests/generators/throw_caught.phpt new file mode 100644 index 0000000000..0c3f8e9b2d --- /dev/null +++ b/Zend/tests/generators/throw_caught.phpt @@ -0,0 +1,25 @@ +--TEST-- +Generator::throw() where the exception is caught in the generator +--FILE-- +<?php + +function gen() { + try { + yield; + } catch (RuntimeException $e) { + echo $e, "\n\n"; + } + + yield 'result'; +} + +$gen = gen(); +var_dump($gen->throw(new RuntimeException('Test'))); + +?> +--EXPECTF-- +exception 'RuntimeException' with message 'Test' in %s:%d +Stack trace: +#0 {main} + +string(6) "result" diff --git a/Zend/tests/generators/throw_not_an_exception.phpt b/Zend/tests/generators/throw_not_an_exception.phpt new file mode 100644 index 0000000000..d93903e215 --- /dev/null +++ b/Zend/tests/generators/throw_not_an_exception.phpt @@ -0,0 +1,15 @@ +--TEST-- +Generator::throw() with something that's not an exception +--FILE-- +<?php + +function gen() { + yield; +} + +$gen = gen(); +$gen->throw(new stdClass); + +?> +--EXPECTF-- +Fatal error: Exceptions must be valid objects derived from the Exception base class in %s on line %d diff --git a/Zend/tests/generators/throw_rethrow.phpt b/Zend/tests/generators/throw_rethrow.phpt new file mode 100644 index 0000000000..267f5f0db8 --- /dev/null +++ b/Zend/tests/generators/throw_rethrow.phpt @@ -0,0 +1,32 @@ +--TEST-- +Generator::throw() where the generator throws a different exception +--FILE-- +<?php + +function gen() { + try { + yield; + } catch (RuntimeException $e) { + echo 'Caught: ', $e, "\n\n"; + + throw new LogicException('new throw'); + } +} + +$gen = gen(); +var_dump($gen->throw(new RuntimeException('throw'))); + +?> +--EXPECTF-- +Caught: exception 'RuntimeException' with message 'throw' in %s:%d +Stack trace: +#0 {main} + + +Fatal error: Uncaught exception 'LogicException' with message 'new throw' in %s:%d +Stack trace: +#0 [internal function]: gen() +#1 %s(%d): Generator->throw(Object(RuntimeException)) +#2 {main} + thrown in %s on line %d + diff --git a/Zend/tests/generators/throw_uncaught.phpt b/Zend/tests/generators/throw_uncaught.phpt new file mode 100644 index 0000000000..f06cff1b8e --- /dev/null +++ b/Zend/tests/generators/throw_uncaught.phpt @@ -0,0 +1,19 @@ +--TEST-- +Generator::throw() where the exception is not caught in the generator +--FILE-- +<?php + +function gen() { + yield 'thisThrows'; + yield 'notReached'; +} + +$gen = gen(); +var_dump($gen->throw(new RuntimeException('test'))); + +?> +--EXPECTF-- +Fatal error: Uncaught exception 'RuntimeException' with message 'test' in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/tests/generators/unused_return_value.phpt b/Zend/tests/generators/unused_return_value.phpt new file mode 100644 index 0000000000..ddce64542c --- /dev/null +++ b/Zend/tests/generators/unused_return_value.phpt @@ -0,0 +1,13 @@ +--TEST-- +There shouldn't be any leaks when the genertor's return value isn't used +--FILE-- +<?php + +function gen($foo) { yield; } + +gen('foo'); // return value not used + +?> +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/tests/generators/xrange.phpt b/Zend/tests/generators/xrange.phpt new file mode 100644 index 0000000000..4d8b60fa90 --- /dev/null +++ b/Zend/tests/generators/xrange.phpt @@ -0,0 +1,23 @@ +--TEST-- +Simple generator xrange() test +--FILE-- +<?php + +function xrange($start, $end, $step = 1) { + for ($i = $start; $i <= $end; $i += $step) { + yield $i; + } +} + +foreach (xrange(10, 20, 2) as $i) { + var_dump($i); +} + +?> +--EXPECT-- +int(10) +int(12) +int(14) +int(16) +int(18) +int(20) diff --git a/Zend/tests/generators/yield_array_key.phpt b/Zend/tests/generators/yield_array_key.phpt new file mode 100644 index 0000000000..5afba00de8 --- /dev/null +++ b/Zend/tests/generators/yield_array_key.phpt @@ -0,0 +1,18 @@ +--TEST-- +Array keys can be yielded from generators +--FILE-- +<?php + +function gen() { + yield [] => 1; +} + +$gen = gen(); +var_dump($gen->key()); +var_dump($gen->current()); + +?> +--EXPECT-- +array(0) { +} +int(1) diff --git a/Zend/tests/generators/yield_array_offset_by_ref.phpt b/Zend/tests/generators/yield_array_offset_by_ref.phpt new file mode 100644 index 0000000000..544108e64d --- /dev/null +++ b/Zend/tests/generators/yield_array_offset_by_ref.phpt @@ -0,0 +1,26 @@ +--TEST-- +Array offsets can be yielded by reference +--FILE-- +<?php + +function &gen(array &$array) { + yield $array[0]; +} + +$array = [1, 2, 3]; +$gen = gen($array); +foreach ($gen as &$val) { + $val *= -1; +} +var_dump($array); + +?> +--EXPECT-- +array(3) { + [0]=> + &int(-1) + [1]=> + int(2) + [2]=> + int(3) +} diff --git a/Zend/tests/generators/yield_by_reference.phpt b/Zend/tests/generators/yield_by_reference.phpt new file mode 100644 index 0000000000..dba0791c0d --- /dev/null +++ b/Zend/tests/generators/yield_by_reference.phpt @@ -0,0 +1,42 @@ +--TEST-- +Generators can yield by-reference +--FILE-- +<?php + +function &iter(array &$array) { + foreach ($array as $key => &$value) { + yield $key => $value; + } +} + +$array = [1, 2, 3]; +$iter = iter($array); +foreach ($iter as &$value) { + $value *= -1; +} +var_dump($array); + +$array = [1, 2, 3]; +foreach (iter($array) as &$value) { + $value *= -1; +} +var_dump($array); + +?> +--EXPECT-- +array(3) { + [0]=> + int(-1) + [1]=> + int(-2) + [2]=> + &int(-3) +} +array(3) { + [0]=> + int(-1) + [1]=> + int(-2) + [2]=> + &int(-3) +} diff --git a/Zend/tests/generators/yield_closure.phpt b/Zend/tests/generators/yield_closure.phpt new file mode 100644 index 0000000000..e380b29946 --- /dev/null +++ b/Zend/tests/generators/yield_closure.phpt @@ -0,0 +1,17 @@ +--TEST-- +Generator shouldn't crash if last yielded value is a closure +--FILE-- +<?php + +function gen() { + yield function() {}; +} + +$gen = gen(); +$gen->next(); + +echo "Done!"; + +?> +--EXPECT-- +Done! diff --git a/Zend/tests/generators/yield_during_function_call.phpt b/Zend/tests/generators/yield_during_function_call.phpt new file mode 100644 index 0000000000..21071f9fb4 --- /dev/null +++ b/Zend/tests/generators/yield_during_function_call.phpt @@ -0,0 +1,15 @@ +--TEST-- +"yield" can occur during a function call +--FILE-- +<?php + +function gen() { + var_dump(str_repeat("x", yield)); +} + +$gen = gen(); +$gen->send(10); + +?> +--EXPECT-- +string(10) "xxxxxxxxxx" diff --git a/Zend/tests/generators/yield_during_method_call.phpt b/Zend/tests/generators/yield_during_method_call.phpt new file mode 100644 index 0000000000..5fbe84fff5 --- /dev/null +++ b/Zend/tests/generators/yield_during_method_call.phpt @@ -0,0 +1,35 @@ +--TEST-- +Yield can be used during a method call +--FILE-- +<?php + +class A { + public function b($c) { + echo $c, "\n"; + } +} + +function gen() { + $a = new A; + $a->b(yield); +} + +$gen = gen(); +$gen->send('foo'); + +// test resource cleanup +$gen = gen(); +$gen->rewind(); +unset($gen); + +// test cloning +$g1 = gen(); +$g1->rewind(); +$g2 = clone $g1; +unset($g1); +$g2->send('bar'); + +?> +--EXPECT-- +foo +bar diff --git a/Zend/tests/generators/yield_in_finally.phpt b/Zend/tests/generators/yield_in_finally.phpt new file mode 100644 index 0000000000..805484ad1d --- /dev/null +++ b/Zend/tests/generators/yield_in_finally.phpt @@ -0,0 +1,29 @@ +--TEST-- +yield can be used in finally (apart from forced closes) +--FILE-- +<?php + +function gen() { + try { + echo "before return\n"; + return; + echo "after return\n"; + } finally { + echo "before yield\n"; + yield "yielded value"; + echo "after yield\n"; + } + + echo "after finally\n"; +} + +$gen = gen(); +var_dump($gen->current()); +$gen->next(); + +?> +--EXPECTF-- +before return +before yield +string(%d) "yielded value" +after yield diff --git a/Zend/tests/generators/yield_in_parenthesis.phpt b/Zend/tests/generators/yield_in_parenthesis.phpt new file mode 100644 index 0000000000..4a603f4cc1 --- /dev/null +++ b/Zend/tests/generators/yield_in_parenthesis.phpt @@ -0,0 +1,23 @@ +--TEST-- +No additional parenthesis are required around yield if they are already present +--FILE-- +<?php + +function gen() { + if (yield $foo); elseif (yield $foo); + if (yield $foo): elseif (yield $foo): endif; + while (yield $foo); + do {} while (yield $foo); + switch (yield $foo) {} + (yield $foo); + die(yield $foo); + func(yield $foo); + $foo->func(yield $foo); + new Foo(yield $foo); +} + +echo "Done"; + +?> +--EXPECT-- +Done diff --git a/Zend/tests/generators/yield_ref_function_call_by_reference.phpt b/Zend/tests/generators/yield_ref_function_call_by_reference.phpt new file mode 100644 index 0000000000..e371affd92 --- /dev/null +++ b/Zend/tests/generators/yield_ref_function_call_by_reference.phpt @@ -0,0 +1,24 @@ +--TEST-- +The result of a by-ref function call can be yielded just fine +--FILE-- +<?php + +function &nop(&$var) { + return $var; +} + +function &gen(&$var) { + yield nop($var); +} + +$var = "foo"; +$gen = gen($var); +foreach ($gen as &$varRef) { + $varRef = "bar"; +} + +var_dump($var); + +?> +--EXPECT-- +string(3) "bar" diff --git a/Zend/tests/generators/yield_without_value.phpt b/Zend/tests/generators/yield_without_value.phpt new file mode 100644 index 0000000000..510c755bd3 --- /dev/null +++ b/Zend/tests/generators/yield_without_value.phpt @@ -0,0 +1,27 @@ +--TEST-- +yield can be used without a value +--FILE-- +<?php + +function recv() { + while (true) { + var_dump(yield); + } +} + +$reciever = recv(); +var_dump($reciever->current()); +$reciever->send(1); +var_dump($reciever->current()); +$reciever->send(2); +var_dump($reciever->current()); +$reciever->send(3); + +?> +--EXPECT-- +NULL +int(1) +NULL +int(2) +NULL +int(3) diff --git a/Zend/tests/isset_expr_error.phpt b/Zend/tests/isset_expr_error.phpt new file mode 100644 index 0000000000..27fc6cd8d3 --- /dev/null +++ b/Zend/tests/isset_expr_error.phpt @@ -0,0 +1,8 @@ +--TEST-- +Error message for isset(func()) +--FILE-- +<?php +isset(1 + 1); +?> +--EXPECTF-- +Fatal error: Cannot use isset() on the result of an expression (you can use "null !== expression" instead) in %s on line %d diff --git a/Zend/tests/isset_func_error.phpt b/Zend/tests/isset_func_error.phpt new file mode 100644 index 0000000000..7d1036def8 --- /dev/null +++ b/Zend/tests/isset_func_error.phpt @@ -0,0 +1,8 @@ +--TEST-- +Error message for isset(func()) +--FILE-- +<?php +isset(abc()); +?> +--EXPECTF-- +Fatal error: Cannot use isset() on the result of a function call (you can use "null !== func()" instead) in %s on line %d diff --git a/Zend/tests/offset_assign.phpt b/Zend/tests/offset_assign.phpt index 6a00591095..721516f53c 100644 --- a/Zend/tests/offset_assign.phpt +++ b/Zend/tests/offset_assign.phpt @@ -3,11 +3,11 @@ Crash on $x['x']['y'] += 1 when $x is string --FILE-- <?php $x = "a"; -$x['x']['y'] += 1; +$x['x']['y'] += 1; echo "Done\n"; ?> ---EXPECTF-- +--EXPECTF-- Warning: Illegal string offset 'x' in %soffset_assign.php on line %d Fatal error: Cannot use string offset as an array in %soffset_assign.php on line %d diff --git a/Zend/tests/offset_string.phpt b/Zend/tests/offset_string.phpt index f7cb81bb20..c546b37183 100644 --- a/Zend/tests/offset_string.phpt +++ b/Zend/tests/offset_string.phpt @@ -27,7 +27,7 @@ var_dump($str[$arr]); echo "Done\n"; ?> ---EXPECTF-- +--EXPECTF-- string(1) "i" Notice: String offset cast occurred in %s on line %d diff --git a/Zend/tests/try_catch_finally_001.phpt b/Zend/tests/try_catch_finally_001.phpt new file mode 100644 index 0000000000..3d478f461a --- /dev/null +++ b/Zend/tests/try_catch_finally_001.phpt @@ -0,0 +1,36 @@ +--TEST-- +Try catch finally +--FILE-- +<?php + +class AE extends Exception {}; +class BE extends Exception {}; + +function foo () { + try { + try { + try { + throw new Exception("try"); + } catch (AE $e) { + echo "0"; + die("error"); + } finally { + echo "1"; + } + } finally { + echo "2"; + } + } catch (BE $e) { + die("error"); + } catch (Exception $e) { + echo "3"; + } finally { + echo "4"; + } + return 1; +} + +var_dump(foo()); +?> +--EXPECTF-- +1234int(1) diff --git a/Zend/tests/try_catch_finally_002.phpt b/Zend/tests/try_catch_finally_002.phpt new file mode 100644 index 0000000000..79efcb3de8 --- /dev/null +++ b/Zend/tests/try_catch_finally_002.phpt @@ -0,0 +1,42 @@ +--TEST-- +Try catch finally catch(multi catch blocks) +--FILE-- +<?php + +class AE extends Exception {}; +class BE extends Exception {}; + +function foo () { + try { + try { + try { + try { + echo "1"; + throw new Exception("try"); + } catch (AE $e) { + die("error"); + } finally { + echo "2"; + } + } finally { + echo "3"; + } + } catch (BE $e) { + die("error"); + } finally { + echo "4"; + } + } catch (Exception $e) { + echo "5"; + } catch (AE $e) { + die("error"); + } finally { + echo "6"; + } + return 7; +} + +var_dump(foo()); +?> +--EXPECTF-- +123456int(7) diff --git a/Zend/tests/try_catch_finally_003.phpt b/Zend/tests/try_catch_finally_003.phpt new file mode 100644 index 0000000000..7ec8ec82db --- /dev/null +++ b/Zend/tests/try_catch_finally_003.phpt @@ -0,0 +1,36 @@ +--TEST-- +Try catch finally (multi catch blocks with return) +--FILE-- +<?php + +class AE extends Exception {}; +class BE extends Exception {}; + +function foo () { + try { + try { + try { + throw new Exception("try"); + } catch (AE $e) { + die("error"); + } finally { + echo "1"; + } + } finally { + echo "2"; + } + } catch (BE $e) { + die("error"); + } catch (Exception $e) { + echo "3"; + } finally { + echo "4"; + return 4; + } + return 5; +} + +var_dump(foo()); +?> +--EXPECTF-- +1234int(4) diff --git a/Zend/tests/try_catch_finally_004.phpt b/Zend/tests/try_catch_finally_004.phpt new file mode 100644 index 0000000000..eb8d0966a1 --- /dev/null +++ b/Zend/tests/try_catch_finally_004.phpt @@ -0,0 +1,30 @@ +--TEST-- +Try catch finally (re-throw exception in catch block) +--CREDITS-- +adoy +--FILE-- +<?php +function dummy($msg) { + var_dump($msg); +} +try { + try { + var_dump("try"); + return; + } catch (Exception $e) { + dummy("catch"); + throw $e; + } finally { + dummy("finally"); + } +} catch (Exception $e) { + dummy("catch2"); +} finally { + dummy("finally2"); +} +var_dump("end"); +?> +--EXPECTF-- +string(3) "try" +string(7) "finally" +string(8) "finally2" diff --git a/Zend/tests/try_catch_finally_005.phpt b/Zend/tests/try_catch_finally_005.phpt new file mode 100644 index 0000000000..dafeb6bbe0 --- /dev/null +++ b/Zend/tests/try_catch_finally_005.phpt @@ -0,0 +1,52 @@ +--TEST-- +Try catch finally (break / cont in try block) +--CREDITS-- +adoy +--FILE-- +<?php +for ($i = 0; $i < 100 ; $i ++) { + try { + break; + } finally { + var_dump("break"); + } +} + + +for ($i = 0; $i < 2; $i ++) { + try { + continue; + } finally { + var_dump("continue1"); + } +} + +for ($i = 0; $i < 3; $i ++) { + try { + try { + continue; + } finally { + var_dump("continue2"); + if ($i == 1) { + throw new Exception("continue exception"); + } + } + } catch (Exception $e) { + var_dump("cactched"); + } finally { + var_dump("finally"); + } +} + +?> +--EXPECTF-- +string(5) "break" +string(9) "continue1" +string(9) "continue1" +string(9) "continue2" +string(7) "finally" +string(9) "continue2" +string(8) "cactched" +string(7) "finally" +string(9) "continue2" +string(7) "finally" diff --git a/Zend/tests/try_catch_finally_006.phpt b/Zend/tests/try_catch_finally_006.phpt new file mode 100644 index 0000000000..dab6af6a58 --- /dev/null +++ b/Zend/tests/try_catch_finally_006.phpt @@ -0,0 +1,39 @@ +--TEST-- +Try catch finally (goto in try/catch block) +--CREDITS-- +adoy +--FILE-- +<?php +function foo($ex = NULL) { + try { + try { + goto label; + } finally { + var_dump("finally1"); + if ($ex) throw $ex; + } + } catch (Exception $e) { + var_dump("catched"); + if ($ex) return "return1"; + } finally { + var_dump("finally2"); + } + +label: + var_dump("label"); + return "return2"; +} + +var_dump(foo()); +var_dump(foo(new Exception())); + +?> +--EXPECTF-- +string(8) "finally1" +string(8) "finally2" +string(5) "label" +string(7) "return2" +string(8) "finally1" +string(7) "catched" +string(8) "finally2" +string(7) "return1" diff --git a/Zend/tests/try_catch_finally_007.phpt b/Zend/tests/try_catch_finally_007.phpt new file mode 100644 index 0000000000..ad33c68131 --- /dev/null +++ b/Zend/tests/try_catch_finally_007.phpt @@ -0,0 +1,46 @@ +--TEST-- +Try catch finally (goto in try/catch block) +--CREDITS-- +adoy +--FILE-- +<?php +function foo($ret = FALSE) { + try { + try { + do { + goto label; + } while(0); + foreach (array() as $val) { + continue; + } + } finally { + var_dump("finally1"); + throw new Exception("exception"); + } + } catch (Exception $e) { + goto local; +local: + var_dump("catched"); + if ($ret) return "return"; + } finally { + var_dump("finally2"); + } + +label: + var_dump("label"); +} + +var_dump(foo()); +var_dump(foo(true)); + +?> +--EXPECTF-- +string(8) "finally1" +string(7) "catched" +string(8) "finally2" +string(5) "label" +NULL +string(8) "finally1" +string(7) "catched" +string(8) "finally2" +string(6) "return" diff --git a/Zend/tests/try_finally_001.phpt b/Zend/tests/try_finally_001.phpt new file mode 100644 index 0000000000..0f740872c2 --- /dev/null +++ b/Zend/tests/try_finally_001.phpt @@ -0,0 +1,22 @@ +--TEST-- +Try finally (basic test) +--FILE-- +<?php +function foo ($a) { + try { + throw new Exception("ex"); + } finally { + var_dump($a); + } +} + +foo("finally"); +?> +--EXPECTF-- +string(7) "finally" + +Fatal error: Uncaught exception 'Exception' with message 'ex' %s +Stack trace: +#0 %stry_finally_001.php(%d): foo('finally') +#1 {main} + thrown in %stry_finally_001.php on line %d diff --git a/Zend/tests/try_finally_002.phpt b/Zend/tests/try_finally_002.phpt new file mode 100644 index 0000000000..99a34f62fb --- /dev/null +++ b/Zend/tests/try_finally_002.phpt @@ -0,0 +1,23 @@ +--TEST-- +Try finally (re-throw exception in finally block) +--FILE-- +<?php +function foo () { + try { + throw new Exception("try"); + } finally { + throw new Exception("finally"); + } +} + +try { + foo(); +} catch (Exception $e) { + do { + var_dump($e->getMessage()); + } while ($e = $e->getPrevious()); +} +?> +--EXPECT-- +string(7) "finally" +string(3) "try" diff --git a/Zend/tests/try_finally_003.phpt b/Zend/tests/try_finally_003.phpt new file mode 100644 index 0000000000..c1294911bd --- /dev/null +++ b/Zend/tests/try_finally_003.phpt @@ -0,0 +1,27 @@ +--TEST-- +Try finally (call sequence test) +--FILE-- +<?php +function foo () { + try { + echo "1"; + try { + echo "2"; + throw new Exception("ex"); + } finally { + echo "3"; + } + } finally { + echo "4"; + } +} + +foo(); +?> +--EXPECTF-- +1234 +Fatal error: Uncaught exception 'Exception' with message 'ex' %s +Stack trace: +#0 %stry_finally_003.php(%d): foo() +#1 {main} + thrown in %stry_finally_003.php on line %d diff --git a/Zend/tests/try_finally_004.phpt b/Zend/tests/try_finally_004.phpt new file mode 100644 index 0000000000..08930a40c5 --- /dev/null +++ b/Zend/tests/try_finally_004.phpt @@ -0,0 +1,14 @@ +--TEST-- +Try finally (without catch/finally block) +--FILE-- +<?php +function foo () { + try { + echo "3"; + } +} + +foo(); +?> +--EXPECTF-- +Fatal error: Cannot use try without catch or finally in %stry_finally_004.php on line %d diff --git a/Zend/tests/try_finally_005.phpt b/Zend/tests/try_finally_005.phpt new file mode 100644 index 0000000000..8664d6b1bf --- /dev/null +++ b/Zend/tests/try_finally_005.phpt @@ -0,0 +1,17 @@ +--TEST-- +Try finally (with long goto) +--FILE-- +<?php +function foo () { + try { + } finally { + goto label; + } +label: + return 1; +} + +foo(); +?> +--EXPECTF-- +Fatal error: jump out of a finally block is disallowed in %stry_finally_005.php on line %d diff --git a/Zend/tests/try_finally_006.phpt b/Zend/tests/try_finally_006.phpt new file mode 100644 index 0000000000..f53e6b5bc1 --- /dev/null +++ b/Zend/tests/try_finally_006.phpt @@ -0,0 +1,26 @@ +--TEST-- +Try finally (with near goto) +--FILE-- +<?php +function foo () { + $jmp = 1; + try { + } finally { +previous: + if ($jmp) { + goto label; + echo "dummy"; +label: + echo "label\n"; + $jmp = 0; + goto previous; + } + echo "okey"; + } +} + +foo(); +?> +--EXPECTF-- +label +okey diff --git a/Zend/tests/try_finally_007.phpt b/Zend/tests/try_finally_007.phpt new file mode 100644 index 0000000000..634937495c --- /dev/null +++ b/Zend/tests/try_finally_007.phpt @@ -0,0 +1,22 @@ +--TEST-- +Try finally (with goto previous label) +--FILE-- +<?php +function foo () { + try { +label: + echo "label"; + try { + } finally { + goto label; + echo "dummy"; + } + } catch (Exception $e) { + } finally { + } +} + +foo(); +?> +--EXPECTF-- +Fatal error: jump out of a finally block is disallowed in %stry_finally_007.php on line %d diff --git a/Zend/tests/try_finally_008.phpt b/Zend/tests/try_finally_008.phpt new file mode 100644 index 0000000000..cee37aedab --- /dev/null +++ b/Zend/tests/try_finally_008.phpt @@ -0,0 +1,21 @@ +--TEST-- +Try finally (with break in do...while) +--FILE-- +<?php +function foo () { + do { + try { + try { + } finally { + break; + } + } catch (Exception $e) { + } finally { + } + } while (0); +} + +foo(); +?> +--EXPECTF-- +Fatal error: jump out of a finally block is disallowed in %stry_finally_008.php on line %d diff --git a/Zend/tests/try_finally_009.phpt b/Zend/tests/try_finally_009.phpt new file mode 100644 index 0000000000..b29930a75e --- /dev/null +++ b/Zend/tests/try_finally_009.phpt @@ -0,0 +1,23 @@ +--TEST-- +Try finally (with for continue) +--FILE-- +<?php +function foo () { + for($i = 0; $i < 5; $i++) { + do { + try { + try { + } finally { + } + } catch (Exception $e) { + } finally { + continue; + } + } while (0); + } +} + +foo(); +?> +--EXPECTF-- +Fatal error: jump out of a finally block is disallowed in %stry_finally_009.php on line %d diff --git a/Zend/tests/try_finally_010.phpt b/Zend/tests/try_finally_010.phpt new file mode 100644 index 0000000000..bbac8dd1e5 --- /dev/null +++ b/Zend/tests/try_finally_010.phpt @@ -0,0 +1,30 @@ +--TEST-- +Try finally (function call in the finaly block after exception) +--FILE-- +<?php +function foo() { + echo "4"; +} +function bar() { + try { + echo "2"; + throw new Exception(); + echo "x"; + } catch (MyEx $ex) { + echo "x"; + } finally { + echo "3"; + foo(); + echo "5"; + } +} +try { + echo "1"; + bar(); + echo "x"; +} catch (Exception $ex) { + echo "6"; +} +echo "\n"; +--EXPECT-- +123456 diff --git a/Zend/zend.c b/Zend/zend.c index fc443d95b9..d71d7cb5c8 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -683,11 +683,11 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions TS #if HAVE_DTRACE /* build with dtrace support */ zend_compile_file = dtrace_compile_file; - zend_execute = dtrace_execute; + zend_execute_ex = dtrace_execute_ex; zend_execute_internal = dtrace_execute_internal; #else zend_compile_file = compile_file; - zend_execute = execute; + zend_execute_ex = execute_ex; zend_execute_internal = NULL; #endif /* HAVE_SYS_SDT_H */ zend_compile_string = compile_string; diff --git a/Zend/zend.h b/Zend/zend.h index b6c1a5b8a6..aed03d8715 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -22,7 +22,7 @@ #ifndef ZEND_H #define ZEND_H -#define ZEND_VERSION "2.4.0" +#define ZEND_VERSION "2.5.0-dev" #define ZEND_ENGINE_2 @@ -133,6 +133,11 @@ char *alloca (); # endif #endif +/* Compatibility with non-clang compilers */ +#ifndef __has_attribute +# define __has_attribute(x) 0 +#endif + /* GCC x.y.z supplies __GNUC__ = x and __GNUC_MINOR__ = y */ #ifdef __GNUC__ # define ZEND_GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__) @@ -146,6 +151,14 @@ char *alloca (); # define ZEND_ATTRIBUTE_MALLOC #endif +#if ZEND_GCC_VERSION >= 4003 || __has_attribute(alloc_size) +# define ZEND_ATTRIBUTE_ALLOC_SIZE(X) __attribute__ ((alloc_size(X))) +# define ZEND_ATTRIBUTE_ALLOC_SIZE2(X,Y) __attribute__ ((alloc_size(X,Y))) +#else +# define ZEND_ATTRIBUTE_ALLOC_SIZE(X) +# define ZEND_ATTRIBUTE_ALLOC_SIZE2(X,Y) +#endif + #if ZEND_GCC_VERSION >= 2007 # define ZEND_ATTRIBUTE_FORMAT(type, idx, first) __attribute__ ((format(type, idx, first))) #else @@ -212,6 +225,7 @@ char *alloca (); #define ZEND_FILE_LINE_EMPTY_CC , ZEND_FILE_LINE_EMPTY_C #define ZEND_FILE_LINE_ORIG_RELAY_C __zend_orig_filename, __zend_orig_lineno #define ZEND_FILE_LINE_ORIG_RELAY_CC , ZEND_FILE_LINE_ORIG_RELAY_C +#define ZEND_ASSERT(c) assert(c) #else #define ZEND_FILE_LINE_D #define ZEND_FILE_LINE_DC @@ -225,6 +239,7 @@ char *alloca (); #define ZEND_FILE_LINE_EMPTY_CC #define ZEND_FILE_LINE_ORIG_RELAY_C #define ZEND_FILE_LINE_ORIG_RELAY_CC +#define ZEND_ASSERT(c) #endif /* ZEND_DEBUG */ #ifdef ZTS @@ -263,10 +278,10 @@ static const char long_min_digits[] = "9223372036854775808"; #define MAX_LENGTH_OF_DOUBLE 32 -#undef SUCCESS -#undef FAILURE -#define SUCCESS 0 -#define FAILURE -1 /* this MUST stay a negative number, or it may affect functions! */ +typedef enum { + SUCCESS = 0, + FAILURE = -1, /* this MUST stay a negative number, or it may affect functions! */ +} ZEND_RESULT_CODE; #include "zend_hash.h" #include "zend_ts_hash.h" @@ -436,8 +451,6 @@ struct _zend_trait_precedence { zend_trait_method_reference *trait_method; zend_class_entry** exclude_from_classes; - - union _zend_function* function; /* FIXME: kept in 5.4 for BC, not used */ }; typedef struct _zend_trait_precedence zend_trait_precedence; @@ -454,8 +467,6 @@ struct _zend_trait_alias { * modifiers to be set on trait method */ zend_uint modifiers; - - union _zend_function* function; /* FIXME: kept in 5.4 for BC, not used */ }; typedef struct _zend_trait_alias zend_trait_alias; diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index 605e396463..1cc2c67833 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -658,9 +658,9 @@ static unsigned int _mem_block_end_magic = 0; #define ZEND_MM_LARGE_BUCKET_INDEX(S) zend_mm_high_bit(S) -static void *_zend_mm_alloc_int(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC; +static void *_zend_mm_alloc_int(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC ZEND_ATTRIBUTE_ALLOC_SIZE(2); static void _zend_mm_free_int(zend_mm_heap *heap, void *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); -static void *_zend_mm_realloc_int(zend_mm_heap *heap, void *p, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); +static void *_zend_mm_realloc_int(zend_mm_heap *heap, void *p, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_ALLOC_SIZE(3); static inline unsigned int zend_mm_high_bit(size_t _size) { diff --git a/Zend/zend_alloc.h b/Zend/zend_alloc.h index d456f90d4c..0b4e74d897 100644 --- a/Zend/zend_alloc.h +++ b/Zend/zend_alloc.h @@ -54,12 +54,12 @@ BEGIN_EXTERN_C() ZEND_API char *zend_strndup(const char *s, unsigned int length) ZEND_ATTRIBUTE_MALLOC; -ZEND_API void *_emalloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC; +ZEND_API void *_emalloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC ZEND_ATTRIBUTE_ALLOC_SIZE(1); ZEND_API void *_safe_emalloc(size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC; ZEND_API void *_safe_malloc(size_t nmemb, size_t size, size_t offset) ZEND_ATTRIBUTE_MALLOC; ZEND_API void _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); -ZEND_API void *_ecalloc(size_t nmemb, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC; -ZEND_API void *_erealloc(void *ptr, size_t size, int allow_failure ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); +ZEND_API void *_ecalloc(size_t nmemb, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC ZEND_ATTRIBUTE_ALLOC_SIZE2(1,2); +ZEND_API void *_erealloc(void *ptr, size_t size, int allow_failure ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_ALLOC_SIZE(2); ZEND_API void *_safe_erealloc(void *ptr, size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); ZEND_API void *_safe_realloc(void *ptr, size_t nmemb, size_t size, size_t offset); ZEND_API char *_estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC; diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index fcd1deac67..7bbb04785e 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -1512,7 +1512,6 @@ ZEND_FUNCTION(trigger_error) ZEND_FUNCTION(set_error_handler) { zval *error_handler; - zend_bool had_orig_error_handler=0; char *error_handler_name = NULL; long error_type = E_ALL; @@ -1520,38 +1519,31 @@ ZEND_FUNCTION(set_error_handler) return; } - if (!zend_is_callable(error_handler, 0, &error_handler_name TSRMLS_CC)) { - zend_error(E_WARNING, "%s() expects the argument (%s) to be a valid callback", - get_active_function_name(TSRMLS_C), error_handler_name?error_handler_name:"unknown"); + if (Z_TYPE_P(error_handler) != IS_NULL) { /* NULL == unset */ + if (!zend_is_callable(error_handler, 0, &error_handler_name TSRMLS_CC)) { + zend_error(E_WARNING, "%s() expects the argument (%s) to be a valid callback", + get_active_function_name(TSRMLS_C), error_handler_name?error_handler_name:"unknown"); + efree(error_handler_name); + return; + } efree(error_handler_name); - return; } - efree(error_handler_name); if (EG(user_error_handler)) { - had_orig_error_handler = 1; - *return_value = *EG(user_error_handler); - zval_copy_ctor(return_value); - INIT_PZVAL(return_value); + RETVAL_ZVAL(EG(user_error_handler), 1, 0); + zend_stack_push(&EG(user_error_handlers_error_reporting), &EG(user_error_handler_error_reporting), sizeof(EG(user_error_handler_error_reporting))); zend_ptr_stack_push(&EG(user_error_handlers), EG(user_error_handler)); } - ALLOC_ZVAL(EG(user_error_handler)); - if (!zend_is_true(error_handler)) { /* unset user-defined handler */ - FREE_ZVAL(EG(user_error_handler)); + if (Z_TYPE_P(error_handler) == IS_NULL) { /* unset user-defined handler */ EG(user_error_handler) = NULL; - RETURN_TRUE; + return; } + ALLOC_ZVAL(EG(user_error_handler)); + MAKE_COPY_ZVAL(&error_handler, EG(user_error_handler)); EG(user_error_handler_error_reporting) = (int)error_type; - *EG(user_error_handler) = *error_handler; - zval_copy_ctor(EG(user_error_handler)); - INIT_PZVAL(EG(user_error_handler)); - - if (!had_orig_error_handler) { - RETURN_NULL(); - } } /* }}} */ @@ -1585,7 +1577,6 @@ ZEND_FUNCTION(set_exception_handler) { zval *exception_handler; char *exception_handler_name = NULL; - zend_bool had_orig_exception_handler=0; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &exception_handler) == FAILURE) { return; @@ -1602,24 +1593,18 @@ ZEND_FUNCTION(set_exception_handler) } if (EG(user_exception_handler)) { - had_orig_exception_handler = 1; - *return_value = *EG(user_exception_handler); - zval_copy_ctor(return_value); + RETVAL_ZVAL(EG(user_exception_handler), 1, 0); + zend_ptr_stack_push(&EG(user_exception_handlers), EG(user_exception_handler)); } - ALLOC_ZVAL(EG(user_exception_handler)); if (Z_TYPE_P(exception_handler) == IS_NULL) { /* unset user-defined handler */ - FREE_ZVAL(EG(user_exception_handler)); EG(user_exception_handler) = NULL; - RETURN_TRUE; + return; } + ALLOC_ZVAL(EG(user_exception_handler)); MAKE_COPY_ZVAL(&exception_handler, EG(user_exception_handler)) - - if (!had_orig_exception_handler) { - RETURN_NULL(); - } } /* }}} */ diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 8f4f9c47b8..101662cfe7 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -179,6 +179,9 @@ void zend_init_compiler_context(TSRMLS_D) /* {{{ */ CG(context).literals_size = 0; CG(context).current_brk_cont = -1; CG(context).backpatch_count = 0; + CG(context).nested_calls = 0; + CG(context).used_stack = 0; + CG(context).in_finally = 0; CG(context).labels = NULL; } /* }}} */ @@ -285,7 +288,7 @@ ZEND_API zend_bool zend_is_compiling(TSRMLS_D) /* {{{ */ static zend_uint get_temporary_variable(zend_op_array *op_array) /* {{{ */ { - return (op_array->T)++ * ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)); + return (zend_uint)EX_TMP_VAR_NUM(0, (op_array->T)++); } /* }}} */ @@ -1723,7 +1726,7 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n } { - /* Push a seperator to the switch and foreach stacks */ + /* Push a seperator to the switch stack */ zend_switch_entry switch_entry; switch_entry.cond.op_type = IS_UNUSED; @@ -1731,16 +1734,16 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n switch_entry.control_var = 0; zend_stack_push(&CG(switch_cond_stack), (void *) &switch_entry, sizeof(switch_entry)); + } - { - /* Foreach stack separator */ - zend_op dummy_opline; + { + /* Push a separator to the foreach stack */ + zend_op dummy_opline; - dummy_opline.result_type = IS_UNUSED; - dummy_opline.op1_type = IS_UNUSED; + dummy_opline.result_type = IS_UNUSED; + dummy_opline.op1_type = IS_UNUSED; - zend_stack_push(&CG(foreach_copy_stack), (void *) &dummy_opline, sizeof(zend_op)); - } + zend_stack_push(&CG(foreach_copy_stack), (void *) &dummy_opline, sizeof(zend_op)); } if (CG(doc_comment)) { @@ -1950,6 +1953,9 @@ int zend_do_begin_function_call(znode *function_name, zend_bool check_namespace function_name->u.constant.value.str.val = lcname; zend_stack_push(&CG(function_call_stack), (void *) &function, sizeof(zend_function *)); + if (CG(context).nested_calls + 1 > CG(active_op_array)->nested_calls) { + CG(active_op_array)->nested_calls = CG(context).nested_calls + 1; + } zend_do_extended_fcall_begin(TSRMLS_C); return 0; } @@ -1988,11 +1994,13 @@ void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC) /* {{{ */ GET_POLYMORPHIC_CACHE_SLOT(last_op->op2.constant); } last_op->opcode = ZEND_INIT_METHOD_CALL; - SET_UNUSED(last_op->result); + last_op->result_type = IS_UNUSED; + last_op->result.num = CG(context).nested_calls; Z_LVAL(left_bracket->u.constant) = ZEND_INIT_FCALL_BY_NAME; } else { zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); opline->opcode = ZEND_INIT_FCALL_BY_NAME; + opline->result.num = CG(context).nested_calls; SET_UNUSED(opline->op1); if (left_bracket->op_type == IS_CONST) { opline->op2_type = IS_CONST; @@ -2004,6 +2012,9 @@ void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC) /* {{{ */ } zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *)); + if (++CG(context).nested_calls > CG(active_op_array)->nested_calls) { + CG(active_op_array)->nested_calls = CG(context).nested_calls; + } zend_do_extended_fcall_begin(TSRMLS_C); } /* }}} */ @@ -2031,12 +2042,14 @@ void zend_do_begin_dynamic_function_call(znode *function_name, int ns_call TSRML /* In run-time PHP will check for function with full name and internal function with short name */ opline->opcode = ZEND_INIT_NS_FCALL_BY_NAME; + opline->result.num = CG(context).nested_calls; SET_UNUSED(opline->op1); opline->op2_type = IS_CONST; opline->op2.constant = zend_add_ns_func_name_literal(CG(active_op_array), &function_name->u.constant TSRMLS_CC); GET_CACHE_SLOT(opline->op2.constant); } else { opline->opcode = ZEND_INIT_FCALL_BY_NAME; + opline->result.num = CG(context).nested_calls; SET_UNUSED(opline->op1); if (function_name->op_type == IS_CONST) { opline->op2_type = IS_CONST; @@ -2048,6 +2061,9 @@ void zend_do_begin_dynamic_function_call(znode *function_name, int ns_call TSRML } zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *)); + if (++CG(context).nested_calls > CG(active_op_array)->nested_calls) { + CG(active_op_array)->nested_calls = CG(context).nested_calls; + } zend_do_extended_fcall_begin(TSRMLS_C); } /* }}} */ @@ -2395,6 +2411,7 @@ int zend_do_begin_class_member_function_call(znode *class_name, znode *method_na opline->extended_value = class_node.EA ; } opline->opcode = ZEND_INIT_STATIC_METHOD_CALL; + opline->result.num = CG(context).nested_calls; if (class_node.op_type == IS_CONST) { opline->op1_type = IS_CONST; opline->op1.constant = @@ -2416,6 +2433,9 @@ int zend_do_begin_class_member_function_call(znode *class_name, znode *method_na } zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *)); + if (++CG(context).nested_calls > CG(active_op_array)->nested_calls) { + CG(active_op_array)->nested_calls = CG(context).nested_calls; + } zend_do_extended_fcall_begin(TSRMLS_C); return 1; /* Dynamic */ } @@ -2436,21 +2456,29 @@ void zend_do_end_function_call(znode *function_name, znode *result, const znode if (!is_method && !is_dynamic_fcall && function_name->op_type==IS_CONST) { opline->opcode = ZEND_DO_FCALL; SET_NODE(opline->op1, function_name); + SET_UNUSED(opline->op2); + opline->op2.num = CG(context).nested_calls; CALCULATE_LITERAL_HASH(opline->op1.constant); GET_CACHE_SLOT(opline->op1.constant); } else { opline->opcode = ZEND_DO_FCALL_BY_NAME; SET_UNUSED(opline->op1); + SET_UNUSED(opline->op2); + opline->op2.num = --CG(context).nested_calls; } } opline->result.var = get_temporary_variable(CG(active_op_array)); opline->result_type = IS_VAR; - GET_NODE(result, opline->result) ; - SET_UNUSED(opline->op2); + GET_NODE(result, opline->result); zend_stack_del_top(&CG(function_call_stack)); opline->extended_value = Z_LVAL(argument_list->u.constant); + + if (CG(context).used_stack + 1 > CG(active_op_array)->used_stack) { + CG(active_op_array)->used_stack = CG(context).used_stack + 1; + } + CG(context).used_stack -= Z_LVAL(argument_list->u.constant); } /* }}} */ @@ -2558,6 +2586,10 @@ void zend_do_pass_param(znode *param, zend_uchar op, int offset TSRMLS_DC) /* {{ SET_NODE(opline->op1, param); opline->op2.opline_num = offset; SET_UNUSED(opline->op2); + + if (++CG(context).used_stack > CG(active_op_array)->used_stack) { + CG(active_op_array)->used_stack = CG(context).used_stack; + } } /* }}} */ @@ -2612,9 +2644,12 @@ void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC) /* {{{ */ { zend_op *opline; int start_op_number, end_op_number; + zend_bool returns_reference = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0; + + /* The error for use of return inside a generator is thrown in pass_two. */ if (do_end_vparse) { - if ((CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) && !zend_is_function_or_method_call(expr)) { + if (returns_reference && !zend_is_function_or_method_call(expr)) { zend_do_end_variable_parse(expr, BP_VAR_W, 0 TSRMLS_CC); } else { zend_do_end_variable_parse(expr, BP_VAR_R, 0 TSRMLS_CC); @@ -2637,9 +2672,16 @@ void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC) /* {{{ */ start_op_number++; } + if (CG(context).in_finally) { + opline = get_next_op(CG(active_op_array) TSRMLS_CC); + opline->opcode = ZEND_DISCARD_EXCEPTION; + SET_UNUSED(opline->op1); + SET_UNUSED(opline->op2); + } + opline = get_next_op(CG(active_op_array) TSRMLS_CC); - opline->opcode = (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) ? ZEND_RETURN_BY_REF : ZEND_RETURN; + opline->opcode = returns_reference ? ZEND_RETURN_BY_REF : ZEND_RETURN; if (expr) { SET_NODE(opline->op1, expr); @@ -2656,12 +2698,59 @@ void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC) /* {{{ */ } /* }}} */ +void zend_do_yield(znode *result, znode *value, const znode *key, zend_bool is_variable TSRMLS_DC) /* {{{ */ +{ + zend_op *opline; + + if (!CG(active_op_array)->function_name) { + zend_error(E_COMPILE_ERROR, "The \"yield\" expression can only be used inside a function"); + } + + CG(active_op_array)->fn_flags |= ZEND_ACC_GENERATOR; + + if (is_variable) { + if ((CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) && !zend_is_function_or_method_call(value)) { + zend_do_end_variable_parse(value, BP_VAR_W, 0 TSRMLS_CC); + } else { + zend_do_end_variable_parse(value, BP_VAR_R, 0 TSRMLS_CC); + } + } + + opline = get_next_op(CG(active_op_array) TSRMLS_CC); + + opline->opcode = ZEND_YIELD; + + if (value) { + SET_NODE(opline->op1, value); + + if (is_variable && zend_is_function_or_method_call(value)) { + opline->extended_value = ZEND_RETURNS_FUNCTION; + } + } else { + SET_UNUSED(opline->op1); + } + + if (key) { + SET_NODE(opline->op2, key); + } else { + SET_UNUSED(opline->op2); + } + + opline->result_type = IS_TMP_VAR; + opline->result.var = get_temporary_variable(CG(active_op_array)); + GET_NODE(result, opline->result); +} +/* }}} */ + static int zend_add_try_element(zend_uint try_op TSRMLS_DC) /* {{{ */ { int try_catch_offset = CG(active_op_array)->last_try_catch++; CG(active_op_array)->try_catch_array = erealloc(CG(active_op_array)->try_catch_array, sizeof(zend_try_catch_element)*CG(active_op_array)->last_try_catch); CG(active_op_array)->try_catch_array[try_catch_offset].try_op = try_op; + CG(active_op_array)->try_catch_array[try_catch_offset].catch_op = 0; + CG(active_op_array)->try_catch_array[try_catch_offset].finally_op = 0; + CG(active_op_array)->try_catch_array[try_catch_offset].finally_end = 0; return try_catch_offset; } /* }}} */ @@ -2678,7 +2767,7 @@ void zend_do_first_catch(znode *open_parentheses TSRMLS_DC) /* {{{ */ } /* }}} */ -void zend_initialize_try_catch_element(const znode *try_token TSRMLS_DC) /* {{{ */ +void zend_initialize_try_catch_element(znode *catch_token TSRMLS_DC) /* {{{ */ { int jmp_op_number = get_next_op_number(CG(active_op_array)); zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); @@ -2695,7 +2784,7 @@ void zend_initialize_try_catch_element(const znode *try_token TSRMLS_DC) /* {{{ zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr); zend_llist_add_element(jmp_list_ptr, &jmp_op_number); - zend_add_catch_element(try_token->u.op.opline_num, get_next_op_number(CG(active_op_array)) TSRMLS_CC); + catch_token->EA = get_next_op_number(CG(active_op_array)); } /* }}} */ @@ -2721,7 +2810,29 @@ void zend_do_try(znode *try_token TSRMLS_DC) /* {{{ */ } /* }}} */ -void zend_do_begin_catch(znode *try_token, znode *class_name, znode *catch_var, znode *first_catch TSRMLS_DC) /* {{{ */ +void zend_do_finally(znode *finally_token TSRMLS_DC) /* {{{ */ +{ + zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); + + finally_token->u.op.opline_num = get_next_op_number(CG(active_op_array)); + /* call the the "finally" block */ + opline->opcode = ZEND_FAST_CALL; + SET_UNUSED(opline->op1); + opline->op1.opline_num = finally_token->u.op.opline_num + 1; + SET_UNUSED(opline->op2); + /* jump to code after the "finally" block, + * the actual jump address is going to be set in zend_do_end_finally() + */ + opline = get_next_op(CG(active_op_array) TSRMLS_CC); + opline->opcode = ZEND_JMP; + SET_UNUSED(opline->op1); + SET_UNUSED(opline->op2); + + CG(context).in_finally++; +} +/* }}} */ + +void zend_do_begin_catch(znode *catch_token, znode *class_name, znode *catch_var, znode *first_catch TSRMLS_DC) /* {{{ */ { long catch_op_number; zend_op *opline; @@ -2749,11 +2860,11 @@ void zend_do_begin_catch(znode *try_token, znode *class_name, znode *catch_var, Z_STRVAL(catch_var->u.constant) = (char*)CG(active_op_array)->vars[opline->op2.var].name; opline->result.num = 0; /* 1 means it's the last catch in the block */ - try_token->u.op.opline_num = catch_op_number; + catch_token->u.op.opline_num = catch_op_number; } /* }}} */ -void zend_do_end_catch(const znode *try_token TSRMLS_DC) /* {{{ */ +void zend_do_end_catch(znode *catch_token TSRMLS_DC) /* {{{ */ { int jmp_op_number = get_next_op_number(CG(active_op_array)); zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); @@ -2767,7 +2878,38 @@ void zend_do_end_catch(const znode *try_token TSRMLS_DC) /* {{{ */ zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr); zend_llist_add_element(jmp_list_ptr, &jmp_op_number); - CG(active_op_array)->opcodes[try_token->u.op.opline_num].extended_value = get_next_op_number(CG(active_op_array)); + CG(active_op_array)->opcodes[catch_token->u.op.opline_num].extended_value = get_next_op_number(CG(active_op_array)); +} +/* }}} */ + +void zend_do_bind_catch(znode *try_token, znode *catch_token TSRMLS_DC) /* {{{ */ { + if (catch_token->op_type != IS_UNUSED) { + zend_add_catch_element(try_token->u.op.opline_num, catch_token->EA TSRMLS_CC); + } +} +/* }}} */ + +void zend_do_end_finally(znode *try_token, znode* catch_token, znode *finally_token TSRMLS_DC) /* {{{ */ +{ + if (catch_token->op_type == IS_UNUSED && finally_token->op_type == IS_UNUSED) { + zend_error(E_COMPILE_ERROR, "Cannot use try without catch or finally"); + } + if (finally_token->op_type != IS_UNUSED) { + zend_op *opline; + + CG(active_op_array)->try_catch_array[try_token->u.op.opline_num].finally_op = finally_token->u.op.opline_num + 1; + CG(active_op_array)->try_catch_array[try_token->u.op.opline_num].finally_end = get_next_op_number(CG(active_op_array)); + CG(active_op_array)->has_finally_block = 1; + + opline = get_next_op(CG(active_op_array) TSRMLS_CC); + opline->opcode = ZEND_FAST_RET; + SET_UNUSED(opline->op1); + SET_UNUSED(opline->op2); + + CG(active_op_array)->opcodes[finally_token->u.op.opline_num].op1.opline_num = get_next_op_number(CG(active_op_array)); + + CG(context).in_finally--; + } } /* }}} */ @@ -4312,8 +4454,6 @@ void zend_add_trait_alias(znode *method_reference, znode *modifiers, znode *alia } else { trait_alias->alias = NULL; } - trait_alias->function = NULL; - zend_add_to_list(&ce->trait_aliases, trait_alias TSRMLS_CC); } /* }}} */ @@ -4326,8 +4466,6 @@ void zend_add_trait_precedence(znode *method_reference, znode *trait_list TSRMLS trait_precedence->trait_method = (zend_trait_method_reference*)method_reference->u.op.ptr; trait_precedence->exclude_from_classes = (zend_class_entry**) trait_list->u.op.ptr; - trait_precedence->function = NULL; - zend_add_to_list(&ce->trait_precedences, trait_precedence TSRMLS_CC); } /* }}} */ @@ -5274,12 +5412,16 @@ void zend_do_begin_new_object(znode *new_token, znode *class_type TSRMLS_DC) /* new_token->u.op.opline_num = get_next_op_number(CG(active_op_array)); opline = get_next_op(CG(active_op_array) TSRMLS_CC); opline->opcode = ZEND_NEW; + opline->extended_value = CG(context).nested_calls; opline->result_type = IS_VAR; opline->result.var = get_temporary_variable(CG(active_op_array)); SET_NODE(opline->op1, class_type); SET_UNUSED(opline->op2); zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(unsigned char *)); + if (++CG(context).nested_calls > CG(active_op_array)->nested_calls) { + CG(active_op_array)->nested_calls = CG(context).nested_calls; + } } /* }}} */ @@ -5492,6 +5634,13 @@ void zend_do_shell_exec(znode *result, const znode *cmd TSRMLS_DC) /* {{{ */ opline->extended_value = 1; SET_UNUSED(opline->op2); GET_NODE(result, opline->result); + + if (CG(context).nested_calls + 1 > CG(active_op_array)->nested_calls) { + CG(active_op_array)->nested_calls = CG(context).nested_calls + 1; + } + if (CG(context).used_stack + 2 > CG(active_op_array)->used_stack) { + CG(active_op_array)->used_stack = CG(context).used_stack + 2; + } } /* }}} */ @@ -5936,7 +6085,16 @@ void zend_do_isset_or_isempty(int type, znode *result, znode *variable TSRMLS_DC zend_do_end_variable_parse(variable, BP_VAR_IS, 0 TSRMLS_CC); - zend_check_writable_variable(variable); + if (zend_is_function_or_method_call(variable)) { + if (type == ZEND_ISEMPTY) { + /* empty(func()) can be transformed to !func() */ + zend_do_unary_op(ZEND_BOOL_NOT, result, variable TSRMLS_CC); + } else { + zend_error(E_COMPILE_ERROR, "Cannot use isset() on the result of a function call (you can use \"null !== func()\" instead)"); + } + + return; + } if (variable->op_type == IS_CV) { last_op = get_next_op(CG(active_op_array) TSRMLS_CC); @@ -6083,15 +6241,18 @@ void zend_do_foreach_cont(znode *foreach_token, const znode *open_brackets_token opline->extended_value |= ZEND_FE_FETCH_WITH_KEY; } - if ((key->op_type != IS_UNUSED) && (key->EA & ZEND_PARSED_REFERENCE_VARIABLE)) { - zend_error(E_COMPILE_ERROR, "Key element cannot be a reference"); + if ((key->op_type != IS_UNUSED)) { + if (key->EA & ZEND_PARSED_REFERENCE_VARIABLE) { + zend_error(E_COMPILE_ERROR, "Key element cannot be a reference"); + } + if (key->EA & ZEND_PARSED_LIST_EXPR) { + zend_error(E_COMPILE_ERROR, "Cannot use list as key element"); + } } if (value->EA & ZEND_PARSED_REFERENCE_VARIABLE) { assign_by_ref = 1; - if (!(opline-1)->extended_value) { - zend_error(E_COMPILE_ERROR, "Cannot create references to elements of a temporary array expression"); - } + /* Mark extended_value for assign-by-reference */ opline->extended_value |= ZEND_FE_FETCH_BYREF; CG(active_op_array)->opcodes[foreach_token->u.op.opline_num].extended_value |= ZEND_FE_RESET_REFERENCE; @@ -6120,13 +6281,21 @@ void zend_do_foreach_cont(znode *foreach_token, const znode *open_brackets_token GET_NODE(&value_node, opline->result); - if (assign_by_ref) { - zend_do_end_variable_parse(value, BP_VAR_W, 0 TSRMLS_CC); - /* Mark FE_FETCH as IS_VAR as it holds the data directly as a value */ - zend_do_assign_ref(NULL, value, &value_node TSRMLS_CC); - } else { - zend_do_assign(&dummy, value, &value_node TSRMLS_CC); + if (value->EA & ZEND_PARSED_LIST_EXPR) { + if (!CG(list_llist).head) { + zend_error(E_COMPILE_ERROR, "Cannot use empty list"); + } + zend_do_list_end(&dummy, &value_node TSRMLS_CC); zend_do_free(&dummy TSRMLS_CC); + } else { + if (assign_by_ref) { + zend_do_end_variable_parse(value, BP_VAR_W, 0 TSRMLS_CC); + /* Mark FE_FETCH as IS_VAR as it holds the data directly as a value */ + zend_do_assign_ref(NULL, value, &value_node TSRMLS_CC); + } else { + zend_do_assign(&dummy, value, &value_node TSRMLS_CC); + zend_do_free(&dummy TSRMLS_CC); + } } if (key->op_type != IS_UNUSED) { @@ -6555,9 +6724,6 @@ again: case T_OPEN_TAG_WITH_ECHO: retval = T_ECHO; break; - case T_END_HEREDOC: - efree(Z_STRVAL(zendlval->u.constant)); - break; } INIT_PZVAL(&zendlval->u.constant); diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 50ee3a4d7f..d2ab0607b5 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -59,6 +59,9 @@ typedef struct _zend_compiler_context { int literals_size; int current_brk_cont; int backpatch_count; + int nested_calls; + int used_stack; + int in_finally; HashTable *labels; } zend_compiler_context; @@ -80,7 +83,7 @@ typedef union _znode_op { zend_op *jmp_addr; zval *zv; zend_literal *literal; - void *ptr; /* Used for passing pointers from the compile to execution phase, currently used for traits */ + void *ptr; /* Used for passing pointers from the compile to execution phase, currently used for traits */ } znode_op; typedef struct _znode { /* used only during compilation */ @@ -132,6 +135,8 @@ typedef struct _zend_label { typedef struct _zend_try_catch_element { zend_uint try_op; zend_uint catch_op; /* ketchup! */ + zend_uint finally_op; + zend_uint finally_end; } zend_try_catch_element; #if SIZEOF_LONG == 8 @@ -194,6 +199,7 @@ typedef struct _zend_try_catch_element { #define ZEND_ACC_CLOSURE 0x100000 +#define ZEND_ACC_GENERATOR 0x800000 /* function flag for internal user call handlers __call, __callstatic */ #define ZEND_ACC_CALL_VIA_HANDLER 0x200000 @@ -274,11 +280,15 @@ struct _zend_op_array { zend_uint T; + zend_uint nested_calls; + zend_uint used_stack; + zend_brk_cont_element *brk_cont_array; int last_brk_cont; zend_try_catch_element *try_catch_array; int last_try_catch; + zend_bool has_finally_block; /* static variables support */ HashTable *static_variables; @@ -363,15 +373,19 @@ typedef struct _list_llist_element { union _temp_variable; +typedef struct _call_slot { + zend_function *fbc; + zval *object; + zend_class_entry *called_scope; + zend_bool is_ctor_call; + zend_bool is_ctor_result_used; +} call_slot; + struct _zend_execute_data { struct _zend_op *opline; zend_function_state function_state; - zend_function *fbc; /* Function Being Called */ - zend_class_entry *called_scope; zend_op_array *op_array; zval *object; - union _temp_variable *Ts; - zval ***CVs; HashTable *symbol_table; struct _zend_execute_data *prev_execute_data; zval *old_error_reporting; @@ -380,11 +394,18 @@ struct _zend_execute_data { zend_class_entry *current_scope; zend_class_entry *current_called_scope; zval *current_this; - zval *current_object; + struct _zend_op *fast_ret; /* used by FAST_CALL/FAST_RET (finally keyword) */ + call_slot *call_slots; + call_slot *call; }; #define EX(element) execute_data.element +#define EX_TMP_VAR(ex, n) ((temp_variable*)(((char*)(ex)) + ((int)(n)))) +#define EX_TMP_VAR_NUM(ex, n) (EX_TMP_VAR(ex, 0) - (1 + (n))) + +#define EX_CV_NUM(ex, n) (((zval***)(((char*)(ex))+ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data))))+(n)) + #define IS_CONST (1<<0) #define IS_TMP_VAR (1<<1) @@ -489,6 +510,7 @@ void zend_do_build_full_name(znode *result, znode *prefix, znode *name, int is_c int zend_do_begin_class_member_function_call(znode *class_name, znode *method_name TSRMLS_DC); void zend_do_end_function_call(znode *function_name, znode *result, const znode *argument_list, int is_method, int is_dynamic_fcall TSRMLS_DC); void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC); +void zend_do_yield(znode *result, znode *value, const znode *key, zend_bool is_variable TSRMLS_DC); void zend_do_handle_exception(TSRMLS_D); void zend_do_begin_lambda_function_declaration(znode *result, znode *function_token, int return_reference, int is_static TSRMLS_DC); @@ -496,7 +518,10 @@ void zend_do_fetch_lexical_variable(znode *varname, zend_bool is_ref TSRMLS_DC); void zend_do_try(znode *try_token TSRMLS_DC); void zend_do_begin_catch(znode *try_token, znode *catch_class, znode *catch_var, znode *first_catch TSRMLS_DC); -void zend_do_end_catch(const znode *try_token TSRMLS_DC); +void zend_do_bind_catch(znode *try_token, znode *catch_token TSRMLS_DC); +void zend_do_end_catch(znode *catch_token TSRMLS_DC); +void zend_do_finally(znode *finally_token TSRMLS_DC); +void zend_do_end_finally(znode *try_token, znode* catch_token, znode *finally_token TSRMLS_DC); void zend_do_throw(const znode *expr TSRMLS_DC); ZEND_API int do_bind_function(const zend_op_array *op_array, zend_op *opline, HashTable *function_table, zend_bool compile_time); @@ -659,7 +684,7 @@ void print_op_array(zend_op_array *op_array, int optimizations); ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC); zend_brk_cont_element *get_next_brk_cont_element(zend_op_array *op_array); void zend_do_first_catch(znode *open_parentheses TSRMLS_DC); -void zend_initialize_try_catch_element(const znode *try_token TSRMLS_DC); +void zend_initialize_try_catch_element(znode *catch_token TSRMLS_DC); void zend_do_mark_last_catch(const znode *first_catch, const znode *last_additional_catch TSRMLS_DC); ZEND_API zend_bool zend_is_compiling(TSRMLS_D); ZEND_API char *zend_make_compiled_string_description(const char *name TSRMLS_DC); @@ -715,6 +740,7 @@ int zend_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC); #define ZEND_PARSED_VARIABLE (1<<4) #define ZEND_PARSED_REFERENCE_VARIABLE (1<<5) #define ZEND_PARSED_NEW (1<<6) +#define ZEND_PARSED_LIST_EXPR (1<<7) /* unset types */ @@ -810,6 +836,9 @@ int zend_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC); #define ZEND_RETURNS_FUNCTION 1<<0 #define ZEND_RETURNS_NEW 1<<1 +#define ZEND_FAST_RET_TO_CATCH 1 +#define ZEND_FAST_RET_TO_FINALLY 2 + END_EXTERN_C() #define ZEND_CLONE_FUNC_NAME "__clone" diff --git a/Zend/zend_default_classes.c b/Zend/zend_default_classes.c index 43d8e631db..46b00eac4e 100644 --- a/Zend/zend_default_classes.c +++ b/Zend/zend_default_classes.c @@ -25,6 +25,7 @@ #include "zend_interfaces.h" #include "zend_exceptions.h" #include "zend_closures.h" +#include "zend_generators.h" ZEND_API void zend_register_default_classes(TSRMLS_D) @@ -33,6 +34,7 @@ ZEND_API void zend_register_default_classes(TSRMLS_D) zend_register_default_exception(TSRMLS_C); zend_register_iterator_wrapper(TSRMLS_C); zend_register_closure_ce(TSRMLS_C); + zend_register_generator_ce(TSRMLS_C); } /* diff --git a/Zend/zend_dtrace.c b/Zend/zend_dtrace.c index 5b2d0d2dfe..165172ad1e 100644 --- a/Zend/zend_dtrace.c +++ b/Zend/zend_dtrace.c @@ -44,7 +44,7 @@ ZEND_API zend_op_array *dtrace_compile_file(zend_file_handle *file_handle, int t } /* We wrap the execute function to have fire the execute-entry/return and function-entry/return probes */ -ZEND_API void dtrace_execute(zend_op_array *op_array TSRMLS_DC) +ZEND_API void dtrace_execute_ex(zend_execute_data *execute_data TSRMLS_DC) { int lineno; char *scope, *filename, *funcname, *classname; @@ -72,7 +72,7 @@ ZEND_API void dtrace_execute(zend_op_array *op_array TSRMLS_DC) DTRACE_FUNCTION_ENTRY(funcname, filename, lineno, classname, scope); } - execute(op_array TSRMLS_CC); + execute_ex(execute_data TSRMLS_CC); if (DTRACE_FUNCTION_RETURN_ENABLED() && funcname != NULL) { DTRACE_FUNCTION_RETURN(funcname, filename, lineno, classname, scope); @@ -83,7 +83,7 @@ ZEND_API void dtrace_execute(zend_op_array *op_array TSRMLS_DC) } } -ZEND_API void dtrace_execute_internal(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC) +ZEND_API void dtrace_execute_internal(zend_execute_data *execute_data_ptr, zend_fcall_info *fci, int return_value_used TSRMLS_DC) { int lineno; char *filename; @@ -96,7 +96,7 @@ ZEND_API void dtrace_execute_internal(zend_execute_data *execute_data_ptr, int r DTRACE_EXECUTE_ENTRY(filename, lineno); } - execute_internal(execute_data_ptr, return_value_used TSRMLS_CC); + execute_internal(execute_data_ptr, fci, return_value_used TSRMLS_CC); if (DTRACE_EXECUTE_RETURN_ENABLED()) { DTRACE_EXECUTE_RETURN(filename, lineno); diff --git a/Zend/zend_dtrace.h b/Zend/zend_dtrace.h index 65d19ef346..26008afb6b 100644 --- a/Zend/zend_dtrace.h +++ b/Zend/zend_dtrace.h @@ -32,11 +32,11 @@ extern "C" { #ifdef HAVE_DTRACE ZEND_API zend_op_array *(*zend_dtrace_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC); ZEND_API void (*zend_dtrace_execute)(zend_op_array *op_array TSRMLS_DC); -ZEND_API void (*zend_dtrace_execute_internal)(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC); +ZEND_API void (*zend_dtrace_execute_internal)(zend_execute_data *execute_data_ptr, zend_fcall_info *fci, int return_value_used TSRMLS_DC); ZEND_API zend_op_array *dtrace_compile_file(zend_file_handle *file_handle, int type TSRMLS_DC); -ZEND_API void dtrace_execute(zend_op_array *op_array TSRMLS_DC); -ZEND_API void dtrace_execute_internal(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC); +ZEND_API void dtrace_execute_ex(zend_execute_data *execute_data TSRMLS_DC); +ZEND_API void dtrace_execute_internal(zend_execute_data *execute_data_ptr, zend_fcall_info *fci, int return_value_used TSRMLS_DC); #include <zend_dtrace_gen.h> #endif /* HAVE_DTRACE */ diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 276ad382fb..49a241d9a1 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -35,6 +35,7 @@ #include "zend_exceptions.h" #include "zend_interfaces.h" #include "zend_closures.h" +#include "zend_generators.h" #include "zend_vm.h" #include "zend_dtrace.h" @@ -49,10 +50,10 @@ typedef int (*incdec_t)(zval *); -#define get_zval_ptr(op_type, node, Ts, should_free, type) _get_zval_ptr(op_type, node, Ts, should_free, type TSRMLS_CC) -#define get_zval_ptr_ptr(op_type, node, Ts, should_free, type) _get_zval_ptr_ptr(op_type, node, Ts, should_free, type TSRMLS_CC) -#define get_obj_zval_ptr(op_type, node, Ts, should_free, type) _get_obj_zval_ptr(op_type, node, Ts, should_free, type TSRMLS_CC) -#define get_obj_zval_ptr_ptr(op_type, node, Ts, should_free, type) _get_obj_zval_ptr_ptr(op_type, node, Ts, should_free, type TSRMLS_CC) +#define get_zval_ptr(op_type, node, ex, should_free, type) _get_zval_ptr(op_type, node, ex, should_free, type TSRMLS_CC) +#define get_zval_ptr_ptr(op_type, node, ex, should_free, type) _get_zval_ptr_ptr(op_type, node, ex, should_free, type TSRMLS_CC) +#define get_obj_zval_ptr(op_type, node, ex, should_free, type) _get_obj_zval_ptr(op_type, node, ex, should_free, type TSRMLS_CC) +#define get_obj_zval_ptr_ptr(op_type, node, ex, should_free, type) _get_obj_zval_ptr_ptr(op_type, node, ex, should_free, type TSRMLS_CC) /* Prototypes */ static void zend_extension_statement_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC); @@ -61,8 +62,8 @@ static void zend_extension_fcall_end_handler(const zend_extension *extension, ze #define RETURN_VALUE_USED(opline) (!((opline)->result_type & EXT_TYPE_UNUSED)) -#define T(offset) (*(temp_variable *)((char *) Ts + offset)) -#define CV(var) CVs[var] +#define EX_T(offset) (*EX_TMP_VAR(execute_data, offset)) +#define EX_CV(var) (*EX_CV_NUM(execute_data, var)) #define TEMP_VAR_STACK_LIMIT 2000 @@ -85,11 +86,10 @@ static zend_always_inline void zend_pzval_unlock_func(zval *z, zend_free_op *sho static zend_always_inline void zend_pzval_unlock_free_func(zval *z TSRMLS_DC) { if (!Z_DELREF_P(z)) { - if (z != &EG(uninitialized_zval)) { - GC_REMOVE_ZVAL_FROM_BUFFER(z); - zval_dtor(z); - efree(z); - } + ZEND_ASSERT(z != &EG(uninitialized_zval)); + GC_REMOVE_ZVAL_FROM_BUFFER(z); + zval_dtor(z); + efree(z); } } @@ -153,7 +153,6 @@ static zend_always_inline void zend_pzval_unlock_free_func(zval *z TSRMLS_DC) /* End of zend_execute_locks.h */ -#define CV_OF(i) (EG(current_execute_data)->CVs[i]) #define CV_DEF_OF(i) (EG(active_op_array)->vars[i]) #define CTOR_CALL_BIT 0x1 @@ -167,19 +166,22 @@ static zend_always_inline void zend_pzval_unlock_free_func(zval *z TSRMLS_DC) #define DECODE_CTOR(ce) \ ((zend_class_entry*)(((zend_uintptr_t)(ce)) & ~(CTOR_CALL_BIT|CTOR_USED_BIT))) -ZEND_API zval** zend_get_compiled_variable_value(const zend_execute_data *execute_data_ptr, zend_uint var) +#undef EX +#define EX(element) execute_data->element + +ZEND_API zval** zend_get_compiled_variable_value(const zend_execute_data *execute_data, zend_uint var) { - return execute_data_ptr->CVs[var]; + return EX_CV(var); } -static zend_always_inline zval *_get_zval_ptr_tmp(zend_uint var, const temp_variable *Ts, zend_free_op *should_free TSRMLS_DC) +static zend_always_inline zval *_get_zval_ptr_tmp(zend_uint var, const zend_execute_data *execute_data, zend_free_op *should_free TSRMLS_DC) { - return should_free->var = &T(var).tmp_var; + return should_free->var = &EX_T(var).tmp_var; } -static zend_always_inline zval *_get_zval_ptr_var(zend_uint var, const temp_variable *Ts, zend_free_op *should_free TSRMLS_DC) +static zend_always_inline zval *_get_zval_ptr_var(zend_uint var, const zend_execute_data *execute_data, zend_free_op *should_free TSRMLS_DC) { - zval *ptr = T(var).var.ptr; + zval *ptr = EX_T(var).var.ptr; PZVAL_UNLOCK(ptr, should_free); return ptr; @@ -205,7 +207,7 @@ static zend_never_inline zval **_get_zval_cv_lookup(zval ***ptr, zend_uint var, case BP_VAR_W: Z_ADDREF(EG(uninitialized_zval)); if (!EG(active_symbol_table)) { - *ptr = (zval**)EG(current_execute_data)->CVs + (EG(active_op_array)->last_var + var); + *ptr = (zval**)EX_CV_NUM(EG(current_execute_data), EG(active_op_array)->last_var + var); **ptr = &EG(uninitialized_zval); } else { zend_hash_quick_update(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, &EG(uninitialized_zval_ptr), sizeof(zval *), (void **)ptr); @@ -257,7 +259,7 @@ static zend_never_inline zval **_get_zval_cv_lookup_BP_VAR_RW(zval ***ptr, zend_ if (!EG(active_symbol_table)) { Z_ADDREF(EG(uninitialized_zval)); - *ptr = (zval**)EG(current_execute_data)->CVs + (EG(active_op_array)->last_var + var); + *ptr = (zval**)EX_CV_NUM(EG(current_execute_data), EG(active_op_array)->last_var + var); **ptr = &EG(uninitialized_zval); zend_error(E_NOTICE, "Undefined variable: %s", cv->name); } else if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **)ptr)==FAILURE) { @@ -274,7 +276,7 @@ static zend_never_inline zval **_get_zval_cv_lookup_BP_VAR_W(zval ***ptr, zend_u if (!EG(active_symbol_table)) { Z_ADDREF(EG(uninitialized_zval)); - *ptr = (zval**)EG(current_execute_data)->CVs + (EG(active_op_array)->last_var + var); + *ptr = (zval**)EX_CV_NUM(EG(current_execute_data), EG(active_op_array)->last_var + var); **ptr = &EG(uninitialized_zval); } else if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **)ptr)==FAILURE) { Z_ADDREF(EG(uninitialized_zval)); @@ -285,7 +287,7 @@ static zend_never_inline zval **_get_zval_cv_lookup_BP_VAR_W(zval ***ptr, zend_u static zend_always_inline zval *_get_zval_ptr_cv(zend_uint var, int type TSRMLS_DC) { - zval ***ptr = &CV_OF(var); + zval ***ptr = EX_CV_NUM(EG(current_execute_data), var); if (UNEXPECTED(*ptr == NULL)) { return *_get_zval_cv_lookup(ptr, var, type TSRMLS_CC); @@ -293,9 +295,9 @@ static zend_always_inline zval *_get_zval_ptr_cv(zend_uint var, int type TSRMLS_ return **ptr; } -static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_R(zval ***CVs, zend_uint var TSRMLS_DC) +static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_R(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC) { - zval ***ptr = &CV(var); + zval ***ptr = EX_CV_NUM(execute_data, var); if (UNEXPECTED(*ptr == NULL)) { return *_get_zval_cv_lookup_BP_VAR_R(ptr, var TSRMLS_CC); @@ -303,9 +305,9 @@ static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_R(zval ***CVs, zend_uint return **ptr; } -static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_UNSET(zval ***CVs, zend_uint var TSRMLS_DC) +static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_UNSET(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC) { - zval ***ptr = &CV(var); + zval ***ptr = EX_CV_NUM(execute_data, var); if (UNEXPECTED(*ptr == NULL)) { return *_get_zval_cv_lookup_BP_VAR_UNSET(ptr, var TSRMLS_CC); @@ -313,9 +315,9 @@ static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_UNSET(zval ***CVs, zend_ return **ptr; } -static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_IS(zval ***CVs, zend_uint var TSRMLS_DC) +static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_IS(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC) { - zval ***ptr = &CV(var); + zval ***ptr = EX_CV_NUM(execute_data, var); if (UNEXPECTED(*ptr == NULL)) { return *_get_zval_cv_lookup_BP_VAR_IS(ptr, var TSRMLS_CC); @@ -323,9 +325,9 @@ static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_IS(zval ***CVs, zend_uin return **ptr; } -static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_RW(zval ***CVs, zend_uint var TSRMLS_DC) +static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_RW(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC) { - zval ***ptr = &CV(var); + zval ***ptr = EX_CV_NUM(execute_data, var); if (UNEXPECTED(*ptr == NULL)) { return *_get_zval_cv_lookup_BP_VAR_RW(ptr, var TSRMLS_CC); @@ -333,9 +335,9 @@ static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_RW(zval ***CVs, zend_uin return **ptr; } -static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_W(zval ***CVs, zend_uint var TSRMLS_DC) +static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_W(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC) { - zval ***ptr = &CV(var); + zval ***ptr = EX_CV_NUM(execute_data, var); if (UNEXPECTED(*ptr == NULL)) { return *_get_zval_cv_lookup_BP_VAR_W(ptr, var TSRMLS_CC); @@ -343,7 +345,7 @@ static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_W(zval ***CVs, zend_uint return **ptr; } -static inline zval *_get_zval_ptr(int op_type, const znode_op *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC) +static inline zval *_get_zval_ptr(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC) { /* should_free->is_var = 0; */ switch (op_type) { @@ -352,11 +354,11 @@ static inline zval *_get_zval_ptr(int op_type, const znode_op *node, const temp_ return node->zv; break; case IS_TMP_VAR: - should_free->var = TMP_FREE(&T(node->var).tmp_var); - return &T(node->var).tmp_var; + should_free->var = TMP_FREE(&EX_T(node->var).tmp_var); + return &EX_T(node->var).tmp_var; break; case IS_VAR: - return _get_zval_ptr_var(node->var, Ts, should_free TSRMLS_CC); + return _get_zval_ptr_var(node->var, execute_data, should_free TSRMLS_CC); break; case IS_UNUSED: should_free->var = 0; @@ -371,22 +373,22 @@ static inline zval *_get_zval_ptr(int op_type, const znode_op *node, const temp_ return NULL; } -static zend_always_inline zval **_get_zval_ptr_ptr_var(zend_uint var, const temp_variable *Ts, zend_free_op *should_free TSRMLS_DC) +static zend_always_inline zval **_get_zval_ptr_ptr_var(zend_uint var, const zend_execute_data *execute_data, zend_free_op *should_free TSRMLS_DC) { - zval** ptr_ptr = T(var).var.ptr_ptr; + zval** ptr_ptr = EX_T(var).var.ptr_ptr; if (EXPECTED(ptr_ptr != NULL)) { PZVAL_UNLOCK(*ptr_ptr, should_free); } else { /* string offset */ - PZVAL_UNLOCK(T(var).str_offset.str, should_free); + PZVAL_UNLOCK(EX_T(var).str_offset.str, should_free); } return ptr_ptr; } static zend_always_inline zval **_get_zval_ptr_ptr_cv(zend_uint var, int type TSRMLS_DC) { - zval ***ptr = &CV_OF(var); + zval ***ptr = EX_CV_NUM(EG(current_execute_data), var); if (UNEXPECTED(*ptr == NULL)) { return _get_zval_cv_lookup(ptr, var, type TSRMLS_CC); @@ -394,9 +396,9 @@ static zend_always_inline zval **_get_zval_ptr_ptr_cv(zend_uint var, int type TS return *ptr; } -static zend_always_inline zval **_get_zval_ptr_ptr_cv_BP_VAR_R(zval ***CVs, zend_uint var TSRMLS_DC) +static zend_always_inline zval **_get_zval_ptr_ptr_cv_BP_VAR_R(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC) { - zval ***ptr = &CV(var); + zval ***ptr = EX_CV_NUM(execute_data, var); if (UNEXPECTED(*ptr == NULL)) { return _get_zval_cv_lookup_BP_VAR_R(ptr, var TSRMLS_CC); @@ -404,9 +406,9 @@ static zend_always_inline zval **_get_zval_ptr_ptr_cv_BP_VAR_R(zval ***CVs, zend return *ptr; } -static zend_always_inline zval **_get_zval_ptr_ptr_cv_BP_VAR_UNSET(zval ***CVs, zend_uint var TSRMLS_DC) +static zend_always_inline zval **_get_zval_ptr_ptr_cv_BP_VAR_UNSET(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC) { - zval ***ptr = &CV(var); + zval ***ptr = EX_CV_NUM(execute_data, var); if (UNEXPECTED(*ptr == NULL)) { return _get_zval_cv_lookup_BP_VAR_UNSET(ptr, var TSRMLS_CC); @@ -414,9 +416,9 @@ static zend_always_inline zval **_get_zval_ptr_ptr_cv_BP_VAR_UNSET(zval ***CVs, return *ptr; } -static zend_always_inline zval **_get_zval_ptr_ptr_cv_BP_VAR_IS(zval ***CVs, zend_uint var TSRMLS_DC) +static zend_always_inline zval **_get_zval_ptr_ptr_cv_BP_VAR_IS(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC) { - zval ***ptr = &CV(var); + zval ***ptr = EX_CV_NUM(execute_data, var); if (UNEXPECTED(*ptr == NULL)) { return _get_zval_cv_lookup_BP_VAR_IS(ptr, var TSRMLS_CC); @@ -424,9 +426,9 @@ static zend_always_inline zval **_get_zval_ptr_ptr_cv_BP_VAR_IS(zval ***CVs, zen return *ptr; } -static zend_always_inline zval **_get_zval_ptr_ptr_cv_BP_VAR_RW(zval ***CVs, zend_uint var TSRMLS_DC) +static zend_always_inline zval **_get_zval_ptr_ptr_cv_BP_VAR_RW(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC) { - zval ***ptr = &CV(var); + zval ***ptr = EX_CV_NUM(execute_data, var); if (UNEXPECTED(*ptr == NULL)) { return _get_zval_cv_lookup_BP_VAR_RW(ptr, var TSRMLS_CC); @@ -434,9 +436,9 @@ static zend_always_inline zval **_get_zval_ptr_ptr_cv_BP_VAR_RW(zval ***CVs, zen return *ptr; } -static zend_always_inline zval **_get_zval_ptr_ptr_cv_BP_VAR_W(zval ***CVs, zend_uint var TSRMLS_DC) +static zend_always_inline zval **_get_zval_ptr_ptr_cv_BP_VAR_W(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC) { - zval ***ptr = &CV(var); + zval ***ptr = EX_CV_NUM(execute_data, var); if (UNEXPECTED(*ptr == NULL)) { return _get_zval_cv_lookup_BP_VAR_W(ptr, var TSRMLS_CC); @@ -444,13 +446,13 @@ static zend_always_inline zval **_get_zval_ptr_ptr_cv_BP_VAR_W(zval ***CVs, zend return *ptr; } -static inline zval **_get_zval_ptr_ptr(int op_type, const znode_op *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC) +static inline zval **_get_zval_ptr_ptr(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC) { if (op_type == IS_CV) { should_free->var = 0; return _get_zval_ptr_ptr_cv(node->var, type TSRMLS_CC); } else if (op_type == IS_VAR) { - return _get_zval_ptr_ptr_var(node->var, Ts, should_free TSRMLS_CC); + return _get_zval_ptr_ptr_var(node->var, execute_data, should_free TSRMLS_CC); } else { should_free->var = 0; return NULL; @@ -467,7 +469,7 @@ static zend_always_inline zval *_get_obj_zval_ptr_unused(TSRMLS_D) } } -static inline zval **_get_obj_zval_ptr_ptr(int op_type, const znode_op *op, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC) +static inline zval **_get_obj_zval_ptr_ptr(int op_type, const znode_op *op, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC) { if (op_type == IS_UNUSED) { if (EXPECTED(EG(This) != NULL)) { @@ -479,7 +481,7 @@ static inline zval **_get_obj_zval_ptr_ptr(int op_type, const znode_op *op, cons zend_error_noreturn(E_ERROR, "Using $this when not in object context"); } } - return get_zval_ptr_ptr(op_type, op, Ts, should_free, type); + return get_zval_ptr_ptr(op_type, op, execute_data, should_free, type); } static zend_always_inline zval **_get_obj_zval_ptr_ptr_unused(TSRMLS_D) @@ -492,7 +494,7 @@ static zend_always_inline zval **_get_obj_zval_ptr_ptr_unused(TSRMLS_D) } } -static inline zval *_get_obj_zval_ptr(int op_type, znode_op *op, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC) +static inline zval *_get_obj_zval_ptr(int op_type, znode_op *op, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC) { if (op_type == IS_UNUSED) { if (EXPECTED(EG(This) != NULL)) { @@ -502,7 +504,7 @@ static inline zval *_get_obj_zval_ptr(int op_type, znode_op *op, const temp_vari zend_error_noreturn(E_ERROR, "Using $this when not in object context"); } } - return get_zval_ptr(op_type, op, Ts, should_free, type); + return get_zval_ptr(op_type, op, execute_data, should_free, type); } static void zend_assign_to_variable_reference(zval **variable_ptr_ptr, zval **value_ptr_ptr TSRMLS_DC) @@ -653,11 +655,11 @@ static inline int zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zva return 1; } -static inline void zend_assign_to_object(zval **retval, zval **object_ptr, zval *property_name, int value_type, znode_op *value_op, const temp_variable *Ts, int opcode, const zend_literal *key TSRMLS_DC) +static inline void zend_assign_to_object(zval **retval, zval **object_ptr, zval *property_name, int value_type, znode_op *value_op, const zend_execute_data *execute_data, int opcode, const zend_literal *key TSRMLS_DC) { zval *object = *object_ptr; zend_free_op free_value; - zval *value = get_zval_ptr(value_type, value_op, Ts, &free_value, BP_VAR_R); + zval *value = get_zval_ptr(value_type, value_op, execute_data, &free_value, BP_VAR_R); if (Z_TYPE_P(object) != IS_OBJECT) { if (object == &EG(error_zval)) { @@ -1409,7 +1411,7 @@ static void zend_fetch_property_address(temp_variable *result, zval **container_ } } -static inline zend_brk_cont_element* zend_brk_cont(int nest_levels, int array_offset, const zend_op_array *op_array, const temp_variable *Ts TSRMLS_DC) +static inline zend_brk_cont_element* zend_brk_cont(int nest_levels, int array_offset, const zend_op_array *op_array, const zend_execute_data *execute_data TSRMLS_DC) { int original_nest_levels = nest_levels; zend_brk_cont_element *jmp_to; @@ -1425,12 +1427,12 @@ static inline zend_brk_cont_element* zend_brk_cont(int nest_levels, int array_of switch (brk_opline->opcode) { case ZEND_SWITCH_FREE: if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) { - zval_ptr_dtor(&T(brk_opline->op1.var).var.ptr); + zval_ptr_dtor(&EX_T(brk_opline->op1.var).var.ptr); } break; case ZEND_FREE: if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) { - zendi_zval_dtor(T(brk_opline->op1.var).tmp_var); + zendi_zval_dtor(EX_T(brk_opline->op1.var).tmp_var); } break; } @@ -1474,11 +1476,212 @@ static int zend_check_symbol(zval **pz TSRMLS_DC) ZEND_API opcode_handler_t *zend_opcode_handlers; -ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC) +ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, zend_fcall_info *fci, int return_value_used TSRMLS_DC) +{ + if(fci != NULL) { + ((zend_internal_function *) execute_data_ptr->function_state.function)->handler(fci->param_count, + *fci->retval_ptr_ptr, fci->retval_ptr_ptr, fci->object_ptr, 1 TSRMLS_CC); + + } else { + zval **return_value_ptr = &EX_TMP_VAR(execute_data_ptr, execute_data_ptr->opline->result.var)->var.ptr; + ((zend_internal_function *) execute_data_ptr->function_state.function)->handler(execute_data_ptr->opline->extended_value, *return_value_ptr, + (execute_data_ptr->function_state.function->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)?return_value_ptr:NULL, + execute_data_ptr->object, return_value_used TSRMLS_CC); + } +} + +void zend_clean_and_cache_symbol_table(HashTable *symbol_table TSRMLS_DC) /* {{{ */ +{ + if (EG(symtable_cache_ptr) >= EG(symtable_cache_limit)) { + zend_hash_destroy(symbol_table); + FREE_HASHTABLE(symbol_table); + } else { + /* clean before putting into the cache, since clean + could call dtors, which could use cached hash */ + zend_hash_clean(symbol_table); + *(++EG(symtable_cache_ptr)) = symbol_table; + } +} +/* }}} */ + +static zend_always_inline void i_free_compiled_variables(zend_execute_data *execute_data) /* {{{ */ +{ + zval ***cv = EX_CV_NUM(execute_data, 0); + zval ***end = cv + EX(op_array)->last_var; + while (cv != end) { + if (*cv) { + zval_ptr_dtor(*cv); + } + cv++; + } +} +/* }}} */ + +void zend_free_compiled_variables(zend_execute_data *execute_data) /* {{{ */ +{ + i_free_compiled_variables(execute_data); +} +/* }}} */ + +/* + * Stack Frame Layout (the whole stack frame is allocated at once) + * ================== + * + * +========================================+ + * | zend_execute_data |<---+ + * | EX(function_state).arguments |--+ | + * | ... | | | + * | ARGUMENT [1] | | | + * | ... | | | + * | ARGUMENT [ARGS_NUMBER] | | | + * | ARGS_NUMBER |<-+ | + * +========================================+ | + * | + * +========================================+ | + * | TMP_VAR[op_arrat->T-1] | | + * | ... | | + * EX_TMP_VAR_NUM(0) ----> | TMP_VAR[0] | | + * +----------------------------------------+ | + * EG(current_execute_data) -> | zend_execute_data | | + * | EX(prev_execute_data) |----+ + * +----------------------------------------+ + * EX_CV_NUM(0) ---------> | CV[0] |--+ + * | ... | | + * | CV[op_array->last_var-1] | | + * +----------------------------------------+ | + * | Optional slot for CV[0] zval* |<-+ + * | ... | + * | ...for CV [op_array->last_var-1] zval* | + * +----------------------------------------+ + * EX(call_slots) -> | CALL_SLOT[0] | + * | ... | + * | CALL_SLOT[op_array->nested_calls-1] | + * +----------------------------------------+ + * zend_vm_stack_frame_base -> | ARGUMENTS STACK [0] | + * | ... | + * zend_vm_stack_top --------> | ... | + * | ... | + * | ARGUMENTS STACK [op_array->used_stack] | + * +----------------------------------------+ + */ + +static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array(zend_op_array *op_array, zend_bool nested TSRMLS_DC) /* {{{ */ +{ + zend_execute_data *execute_data; + + /* + * When allocating the execute_data, memory for compiled variables and + * temporary variables is also allocated before and after the actual + * zend_execute_data struct. In addition we also allocate space to store + * information about syntactically nested called functions and actual + * parameters. op_array->last_var specifies the number of compiled + * variables and op_array->T is the number of temporary variables. If there + * is no symbol table, then twice as much memory is allocated for compiled + * variables. In that case the first half contains zval**s and the second + * half the actual zval*s (which would otherwise be in the symbol table). + */ + size_t execute_data_size = ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data)); + size_t CVs_size = ZEND_MM_ALIGNED_SIZE(sizeof(zval **) * op_array->last_var * (EG(active_symbol_table) ? 1 : 2)); + size_t Ts_size = ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * op_array->T; + size_t call_slots_size = ZEND_MM_ALIGNED_SIZE(sizeof(call_slot)) * op_array->nested_calls; + size_t stack_size = ZEND_MM_ALIGNED_SIZE(sizeof(zval*)) * op_array->used_stack; + size_t total_size = execute_data_size + Ts_size + CVs_size + call_slots_size + stack_size; + + /* + * Normally the execute_data is allocated on the VM stack (because it does + * not actually do any allocation and thus is faster). For generators + * though this behavior would be suboptimal, because the (rather large) + * structure would have to be copied back and forth every time execution is + * suspended or resumed. That's why for generators the execution context + * is allocated using a separate VM stack, thus allowing to save and + * restore it simply by replacing a pointer. The same segment also keeps + * a copy of previous execute_data and passed parameters. + */ + if (UNEXPECTED((op_array->fn_flags & ZEND_ACC_GENERATOR) != 0)) { + /* Prepend the regular stack frame with a copy of prev_execute_data + * and the passed arguments + */ + int args_count = zend_vm_stack_get_args_count_ex(EG(current_execute_data)); + size_t args_size = ZEND_MM_ALIGNED_SIZE(sizeof(zval*)) * (args_count + 1); + + total_size += args_size + execute_data_size; + + EG(argument_stack) = zend_vm_stack_new_page((total_size + (sizeof(void*) - 1)) / sizeof(void*)); + EG(argument_stack)->prev = NULL; + execute_data = (zend_execute_data*)((char*)ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + args_size + execute_data_size + Ts_size); + + /* copy prev_execute_data */ + EX(prev_execute_data) = (zend_execute_data*)((char*)ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + args_size); + memset(EX(prev_execute_data), 0, sizeof(zend_execute_data)); + EX(prev_execute_data)->function_state.function = (zend_function*)op_array; + EX(prev_execute_data)->function_state.arguments = (void**)((char*)ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval*)) * args_count); + + /* copy arguments */ + *EX(prev_execute_data)->function_state.arguments = (void*)(zend_uintptr_t)args_count; + if (args_count > 0) { + zval **arg_src = (zval**)zend_vm_stack_get_arg_ex(EG(current_execute_data), 1); + zval **arg_dst = (zval**)zend_vm_stack_get_arg_ex(EX(prev_execute_data), 1); + int i; + + for (i = 0; i < args_count; i++) { + arg_dst[i] = arg_src[i]; + Z_ADDREF_P(arg_dst[i]); + } + } + } else { + execute_data = zend_vm_stack_alloc(total_size TSRMLS_CC); + execute_data = (zend_execute_data*)((char*)execute_data + Ts_size); + EX(prev_execute_data) = EG(current_execute_data); + } + + memset(EX_CV_NUM(execute_data, 0), 0, sizeof(zval **) * op_array->last_var); + + EX(call_slots) = (call_slot*)((char *)execute_data + execute_data_size + CVs_size); + + + EX(op_array) = op_array; + + EG(argument_stack)->top = zend_vm_stack_frame_base(execute_data); + + EX(object) = NULL; + EX(current_this) = NULL; + EX(old_error_reporting) = NULL; + EX(symbol_table) = EG(active_symbol_table); + EX(call) = NULL; + EG(current_execute_data) = execute_data; + EX(nested) = nested; + + if (!op_array->run_time_cache && op_array->last_cache_slot) { + op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*)); + } + + if (op_array->this_var != -1 && EG(This)) { + Z_ADDREF_P(EG(This)); /* For $this pointer */ + if (!EG(active_symbol_table)) { + EX_CV(op_array->this_var) = (zval **) EX_CV_NUM(execute_data, op_array->last_var + op_array->this_var); + *EX_CV(op_array->this_var) = EG(This); + } else { + if (zend_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), (void **) EX_CV_NUM(execute_data, op_array->this_var))==FAILURE) { + Z_DELREF_P(EG(This)); + } + } + } + + EX(opline) = UNEXPECTED((op_array->fn_flags & ZEND_ACC_INTERACTIVE) != 0) && EG(start_op) ? EG(start_op) : op_array->opcodes; + EG(opline_ptr) = &EX(opline); + + EX(function_state).function = (zend_function *) op_array; + EX(function_state).arguments = NULL; + + return execute_data; +} +/* }}} */ + +zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_array, zend_bool nested TSRMLS_DC) /* {{{ */ { - zval **return_value_ptr = &(*(temp_variable *)((char *) execute_data_ptr->Ts + execute_data_ptr->opline->result.var)).var.ptr; - ((zend_internal_function *) execute_data_ptr->function_state.function)->handler(execute_data_ptr->opline->extended_value, *return_value_ptr, (execute_data_ptr->function_state.function->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)?return_value_ptr:NULL, execute_data_ptr->object, return_value_used TSRMLS_CC); + return i_create_execute_data_from_op_array(op_array, nested TSRMLS_CC); } +/* }}} */ #define ZEND_VM_NEXT_OPCODE() \ CHECK_SYMBOL_TABLES() \ @@ -1512,7 +1715,7 @@ ZEND_API int zend_set_user_opcode_handler(zend_uchar opcode, user_opcode_handler { if (opcode != ZEND_USER_OPCODE) { if (handler == NULL) { - /* restore the original handler */ + /* restore the original handler */ zend_user_opcodes[opcode] = opcode; } else { zend_user_opcodes[opcode] = ZEND_USER_OPCODE; @@ -1528,12 +1731,12 @@ ZEND_API user_opcode_handler_t zend_get_user_opcode_handler(zend_uchar opcode) return zend_user_opcode_handlers[opcode]; } -ZEND_API zval *zend_get_zval_ptr(int op_type, const znode_op *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC) { - return get_zval_ptr(op_type, node, Ts, should_free, type); +ZEND_API zval *zend_get_zval_ptr(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC) { + return get_zval_ptr(op_type, node, execute_data, should_free, type); } -ZEND_API zval **zend_get_zval_ptr_ptr(int op_type, const znode_op *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC) { - return get_zval_ptr_ptr(op_type, node, Ts, should_free, type); +ZEND_API zval **zend_get_zval_ptr_ptr(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC) { + return get_zval_ptr_ptr(op_type, node, execute_data, should_free, type); } /* diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 19eaeeb402..a17f10b312 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -5,7 +5,7 @@ | Copyright (c) 1998-2013 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | - | that is bundled with this package in the file LICENSE, and is | + | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.zend.com/license/2_00.txt. | | If you did not receive a copy of the Zend license and are unable to | @@ -49,24 +49,18 @@ typedef union _temp_variable { BEGIN_EXTERN_C() -ZEND_API extern void (*zend_execute)(zend_op_array *op_array TSRMLS_DC); -ZEND_API extern void (*zend_execute_internal)(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC); +struct _zend_fcall_info; +ZEND_API extern void (*zend_execute_ex)(zend_execute_data *execute_data TSRMLS_DC); +ZEND_API extern void (*zend_execute_internal)(zend_execute_data *execute_data_ptr, struct _zend_fcall_info *fci, int return_value_used TSRMLS_DC); void init_executor(TSRMLS_D); void shutdown_executor(TSRMLS_D); void shutdown_destructors(TSRMLS_D); -ZEND_API void execute(zend_op_array *op_array TSRMLS_DC); -ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC); +zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_array, zend_bool nested TSRMLS_DC); +ZEND_API void zend_execute(zend_op_array *op_array TSRMLS_DC); +ZEND_API void execute_ex(zend_execute_data *execute_data TSRMLS_DC); +ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, struct _zend_fcall_info *fci, int return_value_used TSRMLS_DC); ZEND_API int zend_is_true(zval *op); -#define safe_free_zval_ptr(p) safe_free_zval_ptr_rel(p ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) -static zend_always_inline void safe_free_zval_ptr_rel(zval *p ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) -{ - TSRMLS_FETCH(); - - if (p!=EG(uninitialized_zval_ptr)) { - FREE_ZVAL_REL(p); - } -} ZEND_API int zend_lookup_class(const char *name, int name_length, zend_class_entry ***ce TSRMLS_DC); ZEND_API int zend_lookup_class_ex(const char *name, int name_length, const zend_literal *key, int use_autoload, zend_class_entry ***ce TSRMLS_DC); ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC); @@ -82,11 +76,10 @@ static zend_always_inline void i_zval_ptr_dtor(zval *zval_ptr ZEND_FILE_LINE_DC) if (!Z_DELREF_P(zval_ptr)) { TSRMLS_FETCH(); - if (zval_ptr != &EG(uninitialized_zval)) { - GC_REMOVE_ZVAL_FROM_BUFFER(zval_ptr); - zval_dtor(zval_ptr); - efree_rel(zval_ptr); - } + ZEND_ASSERT(zval_ptr != &EG(uninitialized_zval)); + GC_REMOVE_ZVAL_FROM_BUFFER(zval_ptr); + zval_dtor(zval_ptr); + efree_rel(zval_ptr); } else { TSRMLS_FETCH(); @@ -219,12 +212,6 @@ static zend_always_inline void **zend_vm_stack_top(TSRMLS_D) static zend_always_inline void zend_vm_stack_push(void *ptr TSRMLS_DC) { - ZEND_VM_STACK_GROW_IF_NEEDED(1); - *(EG(argument_stack)->top++) = ptr; -} - -static zend_always_inline void zend_vm_stack_push_nocheck(void *ptr TSRMLS_DC) -{ *(EG(argument_stack)->top++) = ptr; } @@ -232,11 +219,6 @@ static zend_always_inline void *zend_vm_stack_pop(TSRMLS_D) { void *el = *(--EG(argument_stack)->top); - if (UNEXPECTED(EG(argument_stack)->top == ZEND_VM_STACK_ELEMETS(EG(argument_stack)))) { - zend_vm_stack p = EG(argument_stack); - EG(argument_stack) = p->prev; - efree(p); - } return el; } @@ -269,8 +251,14 @@ static zend_always_inline void *zend_vm_stack_alloc(size_t size TSRMLS_DC) return ret; } +static zend_always_inline void** zend_vm_stack_frame_base(zend_execute_data *ex) +{ + return (void**)((char*)ex->call_slots + + ZEND_MM_ALIGNED_SIZE(sizeof(call_slot)) * ex->op_array->nested_calls); +} + static zend_always_inline void zend_vm_stack_free_int(void *ptr TSRMLS_DC) -{ +{ if (UNEXPECTED(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == (void**)ptr)) { zend_vm_stack p = EG(argument_stack); @@ -282,7 +270,7 @@ static zend_always_inline void zend_vm_stack_free_int(void *ptr TSRMLS_DC) } static zend_always_inline void zend_vm_stack_free(void *ptr TSRMLS_DC) -{ +{ if (UNEXPECTED(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == (void**)ptr)) { zend_vm_stack p = EG(argument_stack); @@ -299,51 +287,36 @@ static zend_always_inline void zend_vm_stack_free(void *ptr TSRMLS_DC) } } -static zend_always_inline void** zend_vm_stack_push_args(int count TSRMLS_DC) -{ - - if (UNEXPECTED(EG(argument_stack)->top - ZEND_VM_STACK_ELEMETS(EG(argument_stack)) < count) || - UNEXPECTED(EG(argument_stack)->top == EG(argument_stack)->end)) { - zend_vm_stack p = EG(argument_stack); - - zend_vm_stack_extend(count + 1 TSRMLS_CC); - - EG(argument_stack)->top += count; - *(EG(argument_stack)->top) = (void*)(zend_uintptr_t)count; - while (count-- > 0) { - void *data = *(--p->top); - - if (UNEXPECTED(p->top == ZEND_VM_STACK_ELEMETS(p))) { - zend_vm_stack r = p; - - EG(argument_stack)->prev = p->prev; - p = p->prev; - efree(r); - } - *(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) + count) = data; - } - return EG(argument_stack)->top++; - } - *(EG(argument_stack)->top) = (void*)(zend_uintptr_t)count; - return EG(argument_stack)->top++; -} - -static zend_always_inline void zend_vm_stack_clear_multiple(TSRMLS_D) +static zend_always_inline void zend_vm_stack_clear_multiple(int nested TSRMLS_DC) { void **p = EG(argument_stack)->top - 1; - int delete_count = (int)(zend_uintptr_t) *p; + void **end = p - (int)(zend_uintptr_t)*p; - while (--delete_count>=0) { + while (p != end) { zval *q = *(zval **)(--p); *p = NULL; i_zval_ptr_dtor(q ZEND_FILE_LINE_CC); } - zend_vm_stack_free_int(p TSRMLS_CC); + if (nested) { + EG(argument_stack)->top = p; + } else { + zend_vm_stack_free_int(p TSRMLS_CC); + } } -static zend_always_inline zval** zend_vm_stack_get_arg(int requested_arg TSRMLS_DC) +static zend_always_inline int zend_vm_stack_get_args_count_ex(zend_execute_data *ex) { - void **p = EG(current_execute_data)->prev_execute_data->function_state.arguments; + if (ex) { + void **p = ex->function_state.arguments; + return (int)(zend_uintptr_t) *p; + } else { + return 0; + } +} + +static zend_always_inline zval** zend_vm_stack_get_arg_ex(zend_execute_data *ex, int requested_arg) +{ + void **p = ex->function_state.arguments; int arg_count = (int)(zend_uintptr_t) *p; if (UNEXPECTED(requested_arg > arg_count)) { @@ -352,25 +325,14 @@ static zend_always_inline zval** zend_vm_stack_get_arg(int requested_arg TSRMLS_ return (zval**)p - arg_count + requested_arg - 1; } -static zend_always_inline void zend_arg_types_stack_2_pop(zend_ptr_stack *stack, zval **object, zend_function **fbc) +static zend_always_inline int zend_vm_stack_get_args_count(TSRMLS_D) { - void *a, *b; - - zend_ptr_stack_2_pop(stack, &a, &b); - - *object = (zval *) a; - *fbc = (zend_function *) b; + return zend_vm_stack_get_args_count_ex(EG(current_execute_data)->prev_execute_data); } -static zend_always_inline void zend_arg_types_stack_3_pop(zend_ptr_stack *stack, zend_class_entry **called_scope, zval **object, zend_function **fbc) +static zend_always_inline zval** zend_vm_stack_get_arg(int requested_arg TSRMLS_DC) { - void *a, *b, *c; - - zend_ptr_stack_3_pop(stack, &a, &b, &c); - - *called_scope = (zend_class_entry *) a; - *object = (zval *) b; - *fbc = (zend_function *) c; + return zend_vm_stack_get_arg_ex(EG(current_execute_data)->prev_execute_data, requested_arg); } void execute_new_code(TSRMLS_D); @@ -426,11 +388,14 @@ typedef struct _zend_free_op { /* int is_var; */ } zend_free_op; -ZEND_API zval *zend_get_zval_ptr(int op_type, const znode_op *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC); -ZEND_API zval **zend_get_zval_ptr_ptr(int op_type, const znode_op *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC); +ZEND_API zval *zend_get_zval_ptr(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC); +ZEND_API zval **zend_get_zval_ptr_ptr(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type TSRMLS_DC); ZEND_API int zend_do_fcall(ZEND_OPCODE_HANDLER_ARGS); +void zend_clean_and_cache_symbol_table(HashTable *symbol_table TSRMLS_DC); +void zend_free_compiled_variables(zend_execute_data *execute_data); + #define CACHED_PTR(num) \ EG(active_op_array)->run_time_cache[(num)] diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index a38504fbb4..f099784a42 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -31,14 +31,15 @@ #include "zend_extensions.h" #include "zend_exceptions.h" #include "zend_closures.h" +#include "zend_generators.h" #include "zend_vm.h" #include "zend_float.h" #ifdef HAVE_SYS_TIME_H #include <sys/time.h> #endif -ZEND_API void (*zend_execute)(zend_op_array *op_array TSRMLS_DC); -ZEND_API void (*zend_execute_internal)(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC); +ZEND_API void (*zend_execute_ex)(zend_execute_data *execute_data TSRMLS_DC); +ZEND_API void (*zend_execute_internal)(zend_execute_data *execute_data_ptr, zend_fcall_info *fci, int return_value_used TSRMLS_DC); /* true globals */ ZEND_API const zend_fcall_info empty_fcall_info = { 0, NULL, NULL, NULL, NULL, 0, NULL, NULL, 0 }; @@ -136,7 +137,6 @@ void init_executor(TSRMLS_D) /* {{{ */ INIT_ZVAL(EG(error_zval)); EG(uninitialized_zval_ptr)=&EG(uninitialized_zval); EG(error_zval_ptr)=&EG(error_zval); - zend_ptr_stack_init(&EG(arg_types_stack)); /* destroys stack frame, therefore makes core dumps worthless */ #if 0&&ZEND_DEBUG original_sigsegv_handler = signal(SIGSEGV, zend_handle_sigsegv); @@ -292,10 +292,10 @@ void shutdown_executor(TSRMLS_D) /* {{{ */ } zend_end_try(); zend_try { - zend_vm_stack_destroy(TSRMLS_C); - zend_objects_store_free_object_storage(&EG(objects_store) TSRMLS_CC); + zend_vm_stack_destroy(TSRMLS_C); + /* Destroy all op arrays */ if (EG(full_tables_cleanup)) { zend_hash_reverse_apply(EG(function_table), (apply_func_t) clean_non_persistent_function_full TSRMLS_CC); @@ -323,7 +323,6 @@ void shutdown_executor(TSRMLS_D) /* {{{ */ zend_hash_destroy(&EG(included_files)); - zend_ptr_stack_destroy(&EG(arg_types_stack)); zend_stack_destroy(&EG(user_error_handlers_error_reporting)); zend_ptr_stack_destroy(&EG(user_error_handlers)); zend_ptr_stack_destroy(&EG(user_exception_handlers)); @@ -406,7 +405,7 @@ ZEND_API const char *zend_get_executed_filename(TSRMLS_D) /* {{{ */ ZEND_API uint zend_get_executed_lineno(TSRMLS_D) /* {{{ */ { - if(EG(exception) && EG(opline_ptr) && active_opline->opcode == ZEND_HANDLE_EXCEPTION && + if(EG(exception) && EG(opline_ptr) && active_opline->opcode == ZEND_HANDLE_EXCEPTION && active_opline->lineno == 0 && EG(opline_before_exception)) { return EG(opline_before_exception)->lineno; } @@ -426,27 +425,7 @@ ZEND_API zend_bool zend_is_executing(TSRMLS_D) /* {{{ */ ZEND_API void _zval_ptr_dtor(zval **zval_ptr ZEND_FILE_LINE_DC) /* {{{ */ { -#if DEBUG_ZEND>=2 - printf("Reducing refcount for %x (%x): %d->%d\n", *zval_ptr, zval_ptr, Z_REFCOUNT_PP(zval_ptr), Z_REFCOUNT_PP(zval_ptr) - 1); -#endif - Z_DELREF_PP(zval_ptr); - if (Z_REFCOUNT_PP(zval_ptr) == 0) { - TSRMLS_FETCH(); - - if (*zval_ptr != &EG(uninitialized_zval)) { - GC_REMOVE_ZVAL_FROM_BUFFER(*zval_ptr); - zval_dtor(*zval_ptr); - efree_rel(*zval_ptr); - } - } else { - TSRMLS_FETCH(); - - if (Z_REFCOUNT_PP(zval_ptr) == 1) { - Z_UNSET_ISREF_PP(zval_ptr); - } - - GC_ZVAL_CHECK_POSSIBLE_ROOT(*zval_ptr); - } + i_zval_ptr_dtor(*zval_ptr ZEND_FILE_LINE_RELAY_CC); } /* }}} */ @@ -600,7 +579,7 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco zend_hash_init(tmp_ht, zend_hash_num_elements(Z_ARRVAL_P(p)), NULL, ZVAL_PTR_DTOR, 0); zend_hash_copy(tmp_ht, Z_ARRVAL_P(p), (copy_ctor_func_t) zval_deep_copy, (void *) &tmp, sizeof(zval *)); Z_ARRVAL_P(p) = tmp_ht; - } + } /* First go over the array and see if there are any constant indices */ zend_hash_internal_pointer_reset(Z_ARRVAL_P(p)); @@ -861,8 +840,8 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS !ARG_MAY_BE_SENT_BY_REF(EX(function_state).function, i + 1)) { if (i || UNEXPECTED(ZEND_VM_STACK_ELEMETS(EG(argument_stack)) == (EG(argument_stack)->top))) { /* hack to clean up the stack */ - zend_vm_stack_push_nocheck((void *) (zend_uintptr_t)i TSRMLS_CC); - zend_vm_stack_clear_multiple(TSRMLS_C); + zend_vm_stack_push((void *) (zend_uintptr_t)i TSRMLS_CC); + zend_vm_stack_clear_multiple(0 TSRMLS_CC); } zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given", @@ -898,11 +877,11 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS *param = **(fci->params[i]); INIT_PZVAL(param); } - zend_vm_stack_push_nocheck(param TSRMLS_CC); + zend_vm_stack_push(param TSRMLS_CC); } EX(function_state).arguments = zend_vm_stack_top(TSRMLS_C); - zend_vm_stack_push_nocheck((void*)(zend_uintptr_t)fci->param_count TSRMLS_CC); + zend_vm_stack_push((void*)(zend_uintptr_t)fci->param_count TSRMLS_CC); current_scope = EG(scope); EG(scope) = calling_scope; @@ -955,17 +934,15 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS EG(return_value_ptr_ptr) = fci->retval_ptr_ptr; EG(active_op_array) = (zend_op_array *) EX(function_state).function; original_opline_ptr = EG(opline_ptr); - zend_execute(EG(active_op_array) TSRMLS_CC); + + if (EG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) { + *fci->retval_ptr_ptr = zend_generator_create_zval(EG(active_op_array) TSRMLS_CC); + } else { + zend_execute(EG(active_op_array) TSRMLS_CC); + } + if (!fci->symbol_table && EG(active_symbol_table)) { - if (EG(symtable_cache_ptr)>=EG(symtable_cache_limit)) { - zend_hash_destroy(EG(active_symbol_table)); - FREE_HASHTABLE(EG(active_symbol_table)); - } else { - /* clean before putting into the cache, since clean - could call dtors, which could use cached hash */ - zend_hash_clean(EG(active_symbol_table)); - *(++EG(symtable_cache_ptr)) = EG(active_symbol_table); - } + zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC); } EG(active_symbol_table) = calling_symbol_table; EG(active_op_array) = original_op_array; @@ -977,7 +954,12 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS if (EX(function_state).function->common.scope) { EG(scope) = EX(function_state).function->common.scope; } - ((zend_internal_function *) EX(function_state).function)->handler(fci->param_count, *fci->retval_ptr_ptr, fci->retval_ptr_ptr, fci->object_ptr, 1 TSRMLS_CC); + if(EXPECTED(zend_execute_internal == NULL)) { + /* saves one function call if zend_execute_internal is not used */ + ((zend_internal_function *) EX(function_state).function)->handler(fci->param_count, *fci->retval_ptr_ptr, fci->retval_ptr_ptr, fci->object_ptr, 1 TSRMLS_CC); + } else { + zend_execute_internal(&execute_data, fci, 1 TSRMLS_CC); + } /* We shouldn't fix bad extensions here, because it can break proper ones (Bug #34045) if (!EX(function_state).function->common.return_reference) @@ -1013,7 +995,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS *fci->retval_ptr_ptr = NULL; } } - zend_vm_stack_clear_multiple(TSRMLS_C); + zend_vm_stack_clear_multiple(0 TSRMLS_CC); if (EG(This)) { zval_ptr_dtor(&EG(This)); @@ -1312,9 +1294,9 @@ void execute_new_code(TSRMLS_D) /* {{{ */ ZEND_VM_SET_OPCODE_HANDLER(opline); opline++; } - + zend_release_labels(TSRMLS_C); - + EG(return_value_ptr_ptr) = NULL; EG(active_op_array) = CG(active_op_array); orig_interactive = CG(interactive); @@ -1337,11 +1319,11 @@ ZEND_API void zend_timeout(int dummy) /* {{{ */ if (zend_on_timeout) { #ifdef ZEND_SIGNALS - /* + /* We got here because we got a timeout signal, so we are in a signal handler at this point. However, we want to be able to timeout any user-supplied shutdown functions, so pretend we are not in a signal handler while we are - calling these + calling these */ SIGG(running) = 0; #endif @@ -1590,7 +1572,7 @@ check_fetch_type: zend_error(E_ERROR, "Trait '%s' not found", class_name); } else { zend_error(E_ERROR, "Class '%s' not found", class_name); - } + } } } return NULL; @@ -1613,7 +1595,7 @@ zend_class_entry *zend_fetch_class_by_name(const char *class_name, uint class_na zend_error(E_ERROR, "Trait '%s' not found", class_name); } else { zend_error(E_ERROR, "Class '%s' not found", class_name); - } + } } } return NULL; @@ -1687,7 +1669,7 @@ ZEND_API void zend_reset_all_cv(HashTable *symbol_table TSRMLS_DC) /* {{{ */ for (ex = EG(current_execute_data); ex; ex = ex->prev_execute_data) { if (ex->op_array && ex->symbol_table == symbol_table) { for (i = 0; i < ex->op_array->last_var; i++) { - ex->CVs[i] = NULL; + *EX_CV_NUM(ex, i) = NULL; } } } @@ -1706,7 +1688,7 @@ ZEND_API void zend_delete_variable(zend_execute_data *ex, HashTable *ht, const c if (ex->op_array->vars[i].hash_value == hash_value && ex->op_array->vars[i].name_len == name_len && !memcmp(ex->op_array->vars[i].name, name, name_len)) { - ex->CVs[i] = NULL; + *EX_CV_NUM(ex, i) = NULL; break; } } @@ -1730,7 +1712,7 @@ ZEND_API int zend_delete_global_variable_ex(const char *name, int name_len, ulon ex->op_array->vars[i].name_len == name_len && !memcmp(ex->op_array->vars[i].name, name, name_len) ) { - ex->CVs[i] = NULL; + *EX_CV_NUM(ex, i) = NULL; break; } } @@ -1754,7 +1736,7 @@ ZEND_API void zend_rebuild_symbol_table(TSRMLS_D) /* {{{ */ zend_execute_data *ex; if (!EG(active_symbol_table)) { - + /* Search for last called user function */ ex = EG(current_execute_data); while (ex && !ex->op_array) { @@ -1777,20 +1759,20 @@ ZEND_API void zend_rebuild_symbol_table(TSRMLS_D) /* {{{ */ ex->symbol_table = EG(active_symbol_table); if (ex->op_array->this_var != -1 && - !ex->CVs[ex->op_array->this_var] && + !*EX_CV_NUM(ex, ex->op_array->this_var) && EG(This)) { - ex->CVs[ex->op_array->this_var] = (zval**)ex->CVs + ex->op_array->last_var + ex->op_array->this_var; - *ex->CVs[ex->op_array->this_var] = EG(This); + *EX_CV_NUM(ex, ex->op_array->this_var) = (zval**)EX_CV_NUM(ex, ex->op_array->last_var + ex->op_array->this_var); + **EX_CV_NUM(ex, ex->op_array->this_var) = EG(This); } for (i = 0; i < ex->op_array->last_var; i++) { - if (ex->CVs[i]) { + if (*EX_CV_NUM(ex, i)) { zend_hash_quick_update(EG(active_symbol_table), ex->op_array->vars[i].name, ex->op_array->vars[i].name_len + 1, ex->op_array->vars[i].hash_value, - (void**)ex->CVs[i], + (void**)*EX_CV_NUM(ex, i), sizeof(zval*), - (void**)&ex->CVs[i]); + (void**)EX_CV_NUM(ex, i)); } } } diff --git a/Zend/zend_extensions.h b/Zend/zend_extensions.h index efab29d67e..83cad7f38d 100644 --- a/Zend/zend_extensions.h +++ b/Zend/zend_extensions.h @@ -28,7 +28,7 @@ /* The first number is the engine version and the rest is the date. * This way engine 2/3 API no. is always greater than engine 1 API no.. */ -#define ZEND_EXTENSION_API_NO 220100525 +#define ZEND_EXTENSION_API_NO 220121212 typedef struct _zend_extension_version_info { int zend_extension_api_no; diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c new file mode 100644 index 0000000000..c6c18a7075 --- /dev/null +++ b/Zend/zend_generators.c @@ -0,0 +1,871 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2013 Zend Technologies Ltd. (http://www.zend.com) | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.00 of the Zend license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.zend.com/license/2_00.txt. | + | If you did not receive a copy of the Zend license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@zend.com so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Nikita Popov <nikic@php.net> | + +----------------------------------------------------------------------+ +*/ + +/* $Id$ */ + +#include "zend.h" +#include "zend_API.h" +#include "zend_interfaces.h" +#include "zend_exceptions.h" +#include "zend_generators.h" + +ZEND_API zend_class_entry *zend_ce_generator; +static zend_object_handlers zend_generator_handlers; + +ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished_execution TSRMLS_DC) /* {{{ */ +{ + if (generator->value) { + zval_ptr_dtor(&generator->value); + generator->value = NULL; + } + + if (generator->key) { + zval_ptr_dtor(&generator->key); + generator->key = NULL; + } + + if (generator->execute_data) { + zend_execute_data *execute_data = generator->execute_data; + zend_op_array *op_array = execute_data->op_array; + + if (!finished_execution) { + if (op_array->has_finally_block) { + /* -1 required because we want the last run opcode, not the + * next to-be-run one. */ + zend_uint op_num = execute_data->opline - op_array->opcodes - 1; + zend_uint finally_op_num = 0; + + /* Find next finally block */ + int i; + for (i = 0; i < op_array->last_try_catch; i++) { + zend_try_catch_element *try_catch = &op_array->try_catch_array[i]; + + if (op_num < try_catch->try_op) { + break; + } + + if (op_num < try_catch->finally_op) { + finally_op_num = try_catch->finally_op; + } + } + + /* If a finally block was found we jump directly to it and + * resume the generator. Furthermore we abort this close call + * because the generator will already be closed somewhere in + * the resume. */ + if (finally_op_num) { + execute_data->opline = &op_array->opcodes[finally_op_num]; + execute_data->fast_ret = NULL; + generator->flags |= ZEND_GENERATOR_FORCED_CLOSE; + zend_generator_resume(generator TSRMLS_CC); + return; + } + } + } + + if (!execute_data->symbol_table) { + zend_free_compiled_variables(execute_data); + } else { + zend_clean_and_cache_symbol_table(execute_data->symbol_table TSRMLS_CC); + } + + if (execute_data->current_this) { + zval_ptr_dtor(&execute_data->current_this); + } + + /* If the generator is closed before it can finish execution (reach + * a return statement) we have to free loop variables manually, as + * we don't know whether the SWITCH_FREE / FREE opcodes have run */ + if (!finished_execution) { + /* -1 required because we want the last run opcode, not the + * next to-be-run one. */ + zend_uint op_num = execute_data->opline - op_array->opcodes - 1; + + int i; + for (i = 0; i < op_array->last_brk_cont; ++i) { + zend_brk_cont_element *brk_cont = op_array->brk_cont_array + i; + + if (brk_cont->start < 0) { + continue; + } else if (brk_cont->start > op_num) { + break; + } else if (brk_cont->brk > op_num) { + zend_op *brk_opline = op_array->opcodes + brk_cont->brk; + + switch (brk_opline->opcode) { + case ZEND_SWITCH_FREE: + { + temp_variable *var = EX_TMP_VAR(execute_data, brk_opline->op1.var); + zval_ptr_dtor(&var->var.ptr); + } + break; + case ZEND_FREE: + { + temp_variable *var = EX_TMP_VAR(execute_data, brk_opline->op1.var); + zval_dtor(&var->tmp_var); + } + break; + } + } + } + } + + /* Clear any backed up stack arguments */ + if (generator->stack != EG(argument_stack)) { + void **stack_frame = zend_vm_stack_frame_base(execute_data); + while (generator->stack->top != stack_frame) { + zval_ptr_dtor((zval**)stack_frame); + stack_frame++; + } + } + + while (execute_data->call >= execute_data->call_slots) { + if (execute_data->call->object) { + zval_ptr_dtor(&execute_data->call->object); + } + execute_data->call--; + } + + /* We have added an additional stack frame in prev_execute_data, so we + * have to free it. It also contains the arguments passed to the + * generator (for func_get_args) so those have to be freed too. */ + { + zend_execute_data *prev_execute_data = execute_data->prev_execute_data; + void **arguments = prev_execute_data->function_state.arguments; + + if (arguments) { + int arguments_count = (int) (zend_uintptr_t) *arguments; + zval **arguments_start = (zval **) (arguments - arguments_count); + int i; + + for (i = 0; i < arguments_count; ++i) { + zval_ptr_dtor(arguments_start + i); + } + } + } + + /* Free a clone of closure */ + if (op_array->fn_flags & ZEND_ACC_CLOSURE) { + destroy_op_array(op_array TSRMLS_CC); + efree(op_array); + } + + efree(generator->stack); + if (generator->stack == EG(argument_stack)) { + /* abnormal exit for running generator */ + EG(argument_stack) = NULL; + } + generator->execute_data = NULL; + } +} +/* }}} */ + +static void zend_generator_free_storage(zend_generator *generator TSRMLS_DC) /* {{{ */ +{ + zend_generator_close(generator, 0 TSRMLS_CC); + + zend_object_std_dtor(&generator->std TSRMLS_CC); + efree(generator); +} +/* }}} */ + +static void zend_generator_clone_storage(zend_generator *orig, zend_generator **clone_ptr TSRMLS_DC) /* {{{ */ +{ + zend_generator *clone = emalloc(sizeof(zend_generator)); + memcpy(clone, orig, sizeof(zend_generator)); + + if (orig->execute_data) { + /* Create a few shorter aliases to the old execution data */ + zend_execute_data *execute_data = orig->execute_data; + zend_op_array *op_array = execute_data->op_array; + HashTable *symbol_table = execute_data->symbol_table; + zend_execute_data *current_execute_data; + zend_op **opline_ptr; + HashTable *current_symbol_table; + zend_vm_stack current_stack; + zval *current_this; + void **stack_frame, **orig_stack_frame; + + /* Create new execution context. We have to back up and restore + * EG(current_execute_data), EG(opline_ptr), EG(active_symbol_table) + * and EG(This) here because the function modifies or uses them */ + current_execute_data = EG(current_execute_data); + EG(current_execute_data) = execute_data->prev_execute_data; + opline_ptr = EG(opline_ptr); + current_symbol_table = EG(active_symbol_table); + EG(active_symbol_table) = execute_data->symbol_table; + current_this = EG(This); + EG(This) = NULL; + current_stack = EG(argument_stack); + clone->execute_data = zend_create_execute_data_from_op_array(op_array, 0 TSRMLS_CC); + clone->stack = EG(argument_stack); + EG(argument_stack) = current_stack; + EG(This) = current_this; + EG(active_symbol_table) = current_symbol_table; + EG(current_execute_data) = current_execute_data; + EG(opline_ptr) = opline_ptr; + + /* copy */ + clone->execute_data->opline = execute_data->opline; + clone->execute_data->function_state = execute_data->function_state; + clone->execute_data->object = execute_data->object; + clone->execute_data->current_scope = execute_data->current_scope; + clone->execute_data->current_called_scope = execute_data->current_called_scope; + clone->execute_data->fast_ret = execute_data->fast_ret; + + if (!symbol_table) { + int i; + + /* Copy compiled variables */ + for (i = 0; i < op_array->last_var; i++) { + if (*EX_CV_NUM(execute_data, i)) { + *EX_CV_NUM(clone->execute_data, i) = (zval **) EX_CV_NUM(clone->execute_data, op_array->last_var + i); + **EX_CV_NUM(clone->execute_data, i) = *(zval **) EX_CV_NUM(execute_data, op_array->last_var + i); + Z_ADDREF_PP(*EX_CV_NUM(clone->execute_data, i)); + } + } + } else { + /* Copy symbol table */ + ALLOC_HASHTABLE(clone->execute_data->symbol_table); + zend_hash_init(clone->execute_data->symbol_table, zend_hash_num_elements(symbol_table), NULL, ZVAL_PTR_DTOR, 0); + zend_hash_copy(clone->execute_data->symbol_table, symbol_table, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); + + /* Update zval** pointers for compiled variables */ + { + int i; + for (i = 0; i < op_array->last_var; i++) { + if (zend_hash_quick_find(clone->execute_data->symbol_table, op_array->vars[i].name, op_array->vars[i].name_len + 1, op_array->vars[i].hash_value, (void **) EX_CV_NUM(clone->execute_data, i)) == FAILURE) { + *EX_CV_NUM(clone->execute_data, i) = NULL; + } + } + } + } + + /* Copy nested-calls stack */ + if (execute_data->call) { + clone->execute_data->call = clone->execute_data->call_slots + + (execute_data->call - execute_data->call_slots); + } else { + clone->execute_data->call = NULL; + } + memcpy(clone->execute_data->call_slots, execute_data->call_slots, ZEND_MM_ALIGNED_SIZE(sizeof(call_slot)) * op_array->nested_calls); + if (clone->execute_data->call >= clone->execute_data->call_slots) { + call_slot *call = clone->execute_data->call; + + while (call >= clone->execute_data->call_slots) { + if (call->object) { + Z_ADDREF_P(call->object); + } + call--; + } + } + + /* Copy the temporary variables */ + memcpy(EX_TMP_VAR_NUM(clone->execute_data, op_array->T-1), EX_TMP_VAR_NUM(execute_data, op_array->T-1), ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * op_array->T); + + /* Copy arguments passed on stack */ + stack_frame = zend_vm_stack_frame_base(clone->execute_data); + orig_stack_frame = zend_vm_stack_frame_base(execute_data); + clone->stack->top = stack_frame + (orig->stack->top - orig_stack_frame); + if (clone->stack->top != stack_frame) { + memcpy(stack_frame, orig_stack_frame, ZEND_MM_ALIGNED_SIZE(sizeof(zval*)) * (orig->stack->top - orig_stack_frame)); + while (clone->stack->top != stack_frame) { + Z_ADDREF_PP((zval**)stack_frame); + stack_frame++; + } + } + + /* Add references to loop variables */ + { + zend_uint op_num = execute_data->opline - op_array->opcodes; + + int i; + for (i = 0; i < op_array->last_brk_cont; ++i) { + zend_brk_cont_element *brk_cont = op_array->brk_cont_array + i; + + if (brk_cont->start < 0) { + continue; + } else if (brk_cont->start > op_num) { + break; + } else if (brk_cont->brk > op_num) { + zend_op *brk_opline = op_array->opcodes + brk_cont->brk; + + if (brk_opline->opcode == ZEND_SWITCH_FREE) { + temp_variable *var = EX_TMP_VAR(execute_data, brk_opline->op1.var); + + Z_ADDREF_P(var->var.ptr); + } + } + } + } + + /* Update the send_target to use the temporary variable with the same + * offset as the original generator, but in our temporary variable + * memory segment. */ + if (orig->send_target) { + size_t offset = (char *) orig->send_target - (char *)execute_data; + clone->send_target = EX_TMP_VAR(clone->execute_data, offset); + zval_copy_ctor(&clone->send_target->tmp_var); + } + + if (execute_data->current_this) { + clone->execute_data->current_this = execute_data->current_this; + Z_ADDREF_P(execute_data->current_this); + } + } + + /* The value and key are known not to be references, so simply add refs */ + if (orig->value) { + Z_ADDREF_P(orig->value); + } + + if (orig->key) { + Z_ADDREF_P(orig->key); + } + + *clone_ptr = clone; +} +/* }}} */ + +static zend_object_value zend_generator_create(zend_class_entry *class_type TSRMLS_DC) /* {{{ */ +{ + zend_generator *generator; + zend_object_value object; + + generator = emalloc(sizeof(zend_generator)); + memset(generator, 0, sizeof(zend_generator)); + + /* The key will be incremented on first use, so it'll start at 0 */ + generator->largest_used_integer_key = -1; + + zend_object_std_init(&generator->std, class_type TSRMLS_CC); + + object.handle = zend_objects_store_put(generator, NULL, + (zend_objects_free_object_storage_t) zend_generator_free_storage, + (zend_objects_store_clone_t) zend_generator_clone_storage + TSRMLS_CC + ); + object.handlers = &zend_generator_handlers; + + return object; +} +/* }}} */ + +/* Requires globals EG(scope), EG(current_scope), EG(This), + * EG(active_symbol_table) and EG(current_execute_data). */ +ZEND_API zval *zend_generator_create_zval(zend_op_array *op_array TSRMLS_DC) /* {{{ */ +{ + zval *return_value; + zend_generator *generator; + zend_execute_data *current_execute_data; + zend_op **opline_ptr; + HashTable *current_symbol_table; + zend_execute_data *execute_data; + zend_vm_stack current_stack = EG(argument_stack); + + /* Create a clone of closure, because it may be destroyed */ + if (op_array->fn_flags & ZEND_ACC_CLOSURE) { + zend_op_array *op_array_copy = (zend_op_array*)emalloc(sizeof(zend_op_array)); + *op_array_copy = *op_array; + function_add_ref((zend_function *) op_array_copy); + op_array = op_array_copy; + } + + /* Create new execution context. We have to back up and restore + * EG(current_execute_data), EG(opline_ptr) and EG(active_symbol_table) + * here because the function modifies or uses them */ + current_execute_data = EG(current_execute_data); + opline_ptr = EG(opline_ptr); + current_symbol_table = EG(active_symbol_table); + EG(active_symbol_table) = NULL; + execute_data = zend_create_execute_data_from_op_array(op_array, 0 TSRMLS_CC); + EG(active_symbol_table) = current_symbol_table; + EG(current_execute_data) = current_execute_data; + EG(opline_ptr) = opline_ptr; + + ALLOC_INIT_ZVAL(return_value); + object_init_ex(return_value, zend_ce_generator); + + if (EG(This)) { + Z_ADDREF_P(EG(This)); + } + + /* Back up executor globals. */ + execute_data->current_scope = EG(scope); + execute_data->current_called_scope = EG(called_scope); + execute_data->symbol_table = EG(active_symbol_table); + execute_data->current_this = EG(This); + + /* Save execution context in generator object. */ + generator = (zend_generator *) zend_object_store_get_object(return_value TSRMLS_CC); + generator->execute_data = execute_data; + generator->stack = EG(argument_stack); + EG(argument_stack) = current_stack; + + return return_value; +} +/* }}} */ + +static zend_function *zend_generator_get_constructor(zval *object TSRMLS_DC) /* {{{ */ +{ + zend_error(E_RECOVERABLE_ERROR, "The \"Generator\" class is reserved for internal use and cannot be manually instantiated"); + + return NULL; +} +/* }}} */ + +ZEND_API void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{ */ +{ + /* The generator is already closed, thus can't resume */ + if (!generator->execute_data) { + return; + } + + if (generator->flags & ZEND_GENERATOR_CURRENTLY_RUNNING) { + zend_error(E_ERROR, "Cannot resume an already running generator"); + } + + /* Drop the AT_FIRST_YIELD flag */ + generator->flags &= ~ZEND_GENERATOR_AT_FIRST_YIELD; + + { + /* Backup executor globals */ + zval **original_return_value_ptr_ptr = EG(return_value_ptr_ptr); + zend_execute_data *original_execute_data = EG(current_execute_data); + zend_op **original_opline_ptr = EG(opline_ptr); + zend_op_array *original_active_op_array = EG(active_op_array); + HashTable *original_active_symbol_table = EG(active_symbol_table); + zval *original_This = EG(This); + zend_class_entry *original_scope = EG(scope); + zend_class_entry *original_called_scope = EG(called_scope); + zend_vm_stack original_stack = EG(argument_stack); + + /* We (mis)use the return_value_ptr_ptr to provide the generator object + * to the executor, so YIELD will be able to set the yielded value */ + EG(return_value_ptr_ptr) = (zval **) generator; + + /* Set executor globals */ + EG(current_execute_data) = generator->execute_data; + EG(opline_ptr) = &generator->execute_data->opline; + EG(active_op_array) = generator->execute_data->op_array; + EG(active_symbol_table) = generator->execute_data->symbol_table; + EG(This) = generator->execute_data->current_this; + EG(scope) = generator->execute_data->current_scope; + EG(called_scope) = generator->execute_data->current_called_scope; + EG(argument_stack) = generator->stack; + + /* We want the backtrace to look as if the generator function was + * called from whatever method we are current running (e.g. next()). + * The first prev_execute_data contains an additional stack frame, + * which makes the generator function show up in the backtrace and + * makes the arguments available to func_get_args(). So we have to + * set the prev_execute_data of that prev_execute_data :) */ + generator->execute_data->prev_execute_data->prev_execute_data = original_execute_data; + + /* Resume execution */ + generator->flags |= ZEND_GENERATOR_CURRENTLY_RUNNING; + zend_execute_ex(generator->execute_data TSRMLS_CC); + generator->flags &= ~ZEND_GENERATOR_CURRENTLY_RUNNING; + + /* Restore executor globals */ + EG(return_value_ptr_ptr) = original_return_value_ptr_ptr; + EG(current_execute_data) = original_execute_data; + EG(opline_ptr) = original_opline_ptr; + EG(active_op_array) = original_active_op_array; + EG(active_symbol_table) = original_active_symbol_table; + EG(This) = original_This; + EG(scope) = original_scope; + EG(called_scope) = original_called_scope; + EG(argument_stack) = original_stack; + + /* If an exception was thrown in the generator we have to internally + * rethrow it in the parent scope. */ + if (UNEXPECTED(EG(exception) != NULL)) { + zend_throw_exception_internal(NULL TSRMLS_CC); + } + } +} +/* }}} */ + +static void zend_generator_ensure_initialized(zend_generator *generator TSRMLS_DC) /* {{{ */ +{ + if (generator->execute_data && !generator->value) { + zend_generator_resume(generator TSRMLS_CC); + generator->flags |= ZEND_GENERATOR_AT_FIRST_YIELD; + } +} +/* }}} */ + +static void zend_generator_rewind(zend_generator *generator TSRMLS_DC) /* {{{ */ +{ + zend_generator_ensure_initialized(generator TSRMLS_CC); + + if (!(generator->flags & ZEND_GENERATOR_AT_FIRST_YIELD)) { + zend_throw_exception(NULL, "Cannot rewind a generator that was already run", 0 TSRMLS_CC); + } +} +/* }}} */ + +/* {{{ proto void Generator::rewind() + * Rewind the generator */ +ZEND_METHOD(Generator, rewind) +{ + zend_generator *generator; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + generator = (zend_generator *) zend_object_store_get_object(getThis() TSRMLS_CC); + + zend_generator_rewind(generator TSRMLS_CC); +} +/* }}} */ + +/* {{{ proto bool Generator::valid() + * Check whether the generator is valid */ +ZEND_METHOD(Generator, valid) +{ + zend_generator *generator; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + generator = (zend_generator *) zend_object_store_get_object(getThis() TSRMLS_CC); + + zend_generator_ensure_initialized(generator TSRMLS_CC); + + RETURN_BOOL(generator->value != NULL); +} +/* }}} */ + +/* {{{ proto mixed Generator::current() + * Get the current value */ +ZEND_METHOD(Generator, current) +{ + zend_generator *generator; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + generator = (zend_generator *) zend_object_store_get_object(getThis() TSRMLS_CC); + + zend_generator_ensure_initialized(generator TSRMLS_CC); + + if (generator->value) { + RETURN_ZVAL(generator->value, 1, 0); + } +} +/* }}} */ + +/* {{{ proto mixed Generator::key() + * Get the current key */ +ZEND_METHOD(Generator, key) +{ + zend_generator *generator; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + generator = (zend_generator *) zend_object_store_get_object(getThis() TSRMLS_CC); + + zend_generator_ensure_initialized(generator TSRMLS_CC); + + if (generator->key) { + RETURN_ZVAL(generator->key, 1, 0); + } +} +/* }}} */ + +/* {{{ proto void Generator::next() + * Advances the generator */ +ZEND_METHOD(Generator, next) +{ + zend_generator *generator; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + generator = (zend_generator *) zend_object_store_get_object(getThis() TSRMLS_CC); + + zend_generator_ensure_initialized(generator TSRMLS_CC); + + zend_generator_resume(generator TSRMLS_CC); +} +/* }}} */ + +/* {{{ proto mixed Generator::send(mixed $value) + * Sends a value to the generator */ +ZEND_METHOD(Generator, send) +{ + zval *value; + zend_generator *generator; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &value) == FAILURE) { + return; + } + + generator = (zend_generator *) zend_object_store_get_object(getThis() TSRMLS_CC); + + zend_generator_ensure_initialized(generator TSRMLS_CC); + + /* The generator is already closed, thus can't send anything */ + if (!generator->execute_data) { + return; + } + + /* Put sent value into the TMP_VAR slot */ + MAKE_COPY_ZVAL(&value, &generator->send_target->tmp_var); + + zend_generator_resume(generator TSRMLS_CC); + + if (generator->value) { + RETURN_ZVAL(generator->value, 1, 0); + } +} +/* }}} */ + +/* {{{ proto mixed Generator::throw(Exception $exception) + * Throws an exception into the generator */ +ZEND_METHOD(Generator, throw) +{ + zval *exception, *exception_copy; + zend_generator *generator; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &exception) == FAILURE) { + return; + } + + ALLOC_ZVAL(exception_copy); + MAKE_COPY_ZVAL(&exception, exception_copy); + + generator = (zend_generator *) zend_object_store_get_object(getThis() TSRMLS_CC); + + if (generator->execute_data) { + /* Throw the exception in the context of the generator */ + zend_execute_data *current_execute_data = EG(current_execute_data); + EG(current_execute_data) = generator->execute_data; + + zend_throw_exception_object(exception_copy TSRMLS_CC); + + EG(current_execute_data) = current_execute_data; + + zend_generator_resume(generator TSRMLS_CC); + + if (generator->value) { + RETURN_ZVAL(generator->value, 1, 0); + } + } else { + /* If the generator is already closed throw the exception in the + * current context */ + zend_throw_exception_object(exception_copy TSRMLS_CC); + } +} +/* }}} */ + +/* {{{ proto void Generator::__wakeup() + * Throws an Exception as generators can't be serialized */ +ZEND_METHOD(Generator, __wakeup) +{ + /* Just specifying the zend_class_unserialize_deny handler is not enough, + * because it is only invoked for C unserialization. For O the error has + * to be thrown in __wakeup. */ + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + zend_throw_exception(NULL, "Unserialization of 'Generator' is not allowed", 0 TSRMLS_CC); +} +/* }}} */ + +/* get_iterator implementation */ + +static void zend_generator_iterator_dtor(zend_object_iterator *iterator TSRMLS_DC) /* {{{ */ +{ + zval *object = ((zend_generator_iterator *) iterator)->object; + + zval_ptr_dtor(&object); +} +/* }}} */ + +static int zend_generator_iterator_valid(zend_object_iterator *iterator TSRMLS_DC) /* {{{ */ +{ + zend_generator *generator = (zend_generator *) iterator->data; + + zend_generator_ensure_initialized(generator TSRMLS_CC); + + return generator->value != NULL ? SUCCESS : FAILURE; +} +/* }}} */ + +static void zend_generator_iterator_get_data(zend_object_iterator *iterator, zval ***data TSRMLS_DC) /* {{{ */ +{ + zend_generator *generator = (zend_generator *) iterator->data; + + zend_generator_ensure_initialized(generator TSRMLS_CC); + + if (generator->value) { + *data = &generator->value; + } else { + *data = NULL; + } +} +/* }}} */ + +static int zend_generator_iterator_get_key(zend_object_iterator *iterator, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) /* {{{ */ +{ + zend_generator *generator = (zend_generator *) iterator->data; + + zend_generator_ensure_initialized(generator TSRMLS_CC); + + if (!generator->key) { + return HASH_KEY_NON_EXISTANT; + } + + if (Z_TYPE_P(generator->key) == IS_LONG) { + *int_key = Z_LVAL_P(generator->key); + return HASH_KEY_IS_LONG; + } + + if (Z_TYPE_P(generator->key) == IS_STRING) { + *str_key = estrndup(Z_STRVAL_P(generator->key), Z_STRLEN_P(generator->key)); + *str_key_len = Z_STRLEN_P(generator->key) + 1; + return HASH_KEY_IS_STRING; + } + + /* Waiting for Etienne's patch to allow arbitrary zval keys. Until then + * error out on non-int and non-string keys. */ + zend_error_noreturn(E_ERROR, "Currently only int and string keys can be yielded"); + return HASH_KEY_NON_EXISTANT; /* Nerver reached */ +} +/* }}} */ + +static void zend_generator_iterator_move_forward(zend_object_iterator *iterator TSRMLS_DC) /* {{{ */ +{ + zend_generator *generator = (zend_generator *) iterator->data; + + zend_generator_ensure_initialized(generator TSRMLS_CC); + + zend_generator_resume(generator TSRMLS_CC); +} +/* }}} */ + +static void zend_generator_iterator_rewind(zend_object_iterator *iterator TSRMLS_DC) /* {{{ */ +{ + zend_generator *generator = (zend_generator *) iterator->data; + + zend_generator_rewind(generator TSRMLS_CC); +} +/* }}} */ + +static zend_object_iterator_funcs zend_generator_iterator_functions = { + zend_generator_iterator_dtor, + zend_generator_iterator_valid, + zend_generator_iterator_get_data, + zend_generator_iterator_get_key, + zend_generator_iterator_move_forward, + zend_generator_iterator_rewind +}; + +zend_object_iterator *zend_generator_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) /* {{{ */ +{ + zend_generator_iterator *iterator; + zend_generator *generator; + + generator = (zend_generator *) zend_object_store_get_object(object TSRMLS_CC); + + if (!generator->execute_data) { + zend_throw_exception(NULL, "Cannot traverse an already closed generator", 0 TSRMLS_CC); + return NULL; + } + + if (by_ref && !(generator->execute_data->op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + zend_throw_exception(NULL, "You can only iterate a generator by-reference if it declared that it yields by-reference", 0 TSRMLS_CC); + return NULL; + } + + iterator = &generator->iterator; + iterator->intern.funcs = &zend_generator_iterator_functions; + iterator->intern.data = (void *) generator; + + /* We have to keep a reference to the generator object zval around, + * otherwise the generator may be destroyed during iteration. */ + Z_ADDREF_P(object); + iterator->object = object; + + return (zend_object_iterator *) iterator; +} +/* }}} */ + +ZEND_BEGIN_ARG_INFO(arginfo_generator_void, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_generator_send, 0, 0, 1) + ZEND_ARG_INFO(0, value) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_generator_throw, 0, 0, 1) + ZEND_ARG_INFO(0, exception) +ZEND_END_ARG_INFO() + +static const zend_function_entry generator_functions[] = { + ZEND_ME(Generator, rewind, arginfo_generator_void, ZEND_ACC_PUBLIC) + ZEND_ME(Generator, valid, arginfo_generator_void, ZEND_ACC_PUBLIC) + ZEND_ME(Generator, current, arginfo_generator_void, ZEND_ACC_PUBLIC) + ZEND_ME(Generator, key, arginfo_generator_void, ZEND_ACC_PUBLIC) + ZEND_ME(Generator, next, arginfo_generator_void, ZEND_ACC_PUBLIC) + ZEND_ME(Generator, send, arginfo_generator_send, ZEND_ACC_PUBLIC) + ZEND_ME(Generator, throw, arginfo_generator_throw, ZEND_ACC_PUBLIC) + ZEND_ME(Generator, __wakeup, arginfo_generator_void, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + +void zend_register_generator_ce(TSRMLS_D) /* {{{ */ +{ + zend_class_entry ce; + + INIT_CLASS_ENTRY(ce, "Generator", generator_functions); + zend_ce_generator = zend_register_internal_class(&ce TSRMLS_CC); + zend_ce_generator->ce_flags |= ZEND_ACC_FINAL_CLASS; + zend_ce_generator->create_object = zend_generator_create; + zend_ce_generator->serialize = zend_class_serialize_deny; + zend_ce_generator->unserialize = zend_class_unserialize_deny; + + /* get_iterator has to be assigned *after* implementing the inferface */ + zend_class_implements(zend_ce_generator TSRMLS_CC, 1, zend_ce_iterator); + zend_ce_generator->get_iterator = zend_generator_get_iterator; + zend_ce_generator->iterator_funcs.funcs = &zend_generator_iterator_functions; + + memcpy(&zend_generator_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + zend_generator_handlers.get_constructor = zend_generator_get_constructor; + zend_generator_handlers.clone_obj = zend_objects_store_clone_obj; +} +/* }}} */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ diff --git a/Zend/zend_generators.h b/Zend/zend_generators.h new file mode 100644 index 0000000000..9f37b93c45 --- /dev/null +++ b/Zend/zend_generators.h @@ -0,0 +1,77 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2013 Zend Technologies Ltd. (http://www.zend.com) | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.00 of the Zend license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.zend.com/license/2_00.txt. | + | If you did not receive a copy of the Zend license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@zend.com so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Nikita Popov <nikic@php.net> | + +----------------------------------------------------------------------+ +*/ + +/* $Id$ */ + +#ifndef ZEND_GENERATORS_H +#define ZEND_GENERATORS_H + +BEGIN_EXTERN_C() +extern ZEND_API zend_class_entry *zend_ce_generator; +END_EXTERN_C() + +typedef struct _zend_generator_iterator { + zend_object_iterator intern; + + /* The generator object zval has to be stored, because the iterator is + * holding a ref to it, which has to be dtored. */ + zval *object; +} zend_generator_iterator; + +typedef struct _zend_generator { + zend_object std; + + zend_generator_iterator iterator; + + /* The suspended execution context. */ + zend_execute_data *execute_data; + + /* The separate stack used by generator */ + zend_vm_stack stack; + + /* Current value */ + zval *value; + /* Current key */ + zval *key; + /* Variable to put sent value into */ + temp_variable *send_target; + /* Largest used integer key for auto-incrementing keys */ + long largest_used_integer_key; + + /* ZEND_GENERATOR_* flags */ + zend_uchar flags; +} zend_generator; + +static const zend_uchar ZEND_GENERATOR_CURRENTLY_RUNNING = 0x1; +static const zend_uchar ZEND_GENERATOR_FORCED_CLOSE = 0x2; +static const zend_uchar ZEND_GENERATOR_AT_FIRST_YIELD = 0x4; + +void zend_register_generator_ce(TSRMLS_D); +ZEND_API zval *zend_generator_create_zval(zend_op_array *op_array TSRMLS_DC); +ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished_execution TSRMLS_DC); +ZEND_API void zend_generator_resume(zend_generator *generator TSRMLS_DC); + +#endif + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index 58392c199b..800bdc7f66 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -89,9 +89,6 @@ struct _zend_compiler_globals { int zend_lineno; - char *heredoc; - int heredoc_len; - zend_op_array *active_op_array; HashTable *function_table; /* function symbol table */ @@ -170,8 +167,6 @@ struct _zend_executor_globals { zval error_zval; zval *error_zval_ptr; - zend_ptr_stack arg_types_stack; - /* symbol table cache */ HashTable *symtable_cache[SYMTABLE_CACHE_SIZE]; HashTable **symtable_cache_limit; @@ -297,6 +292,7 @@ struct _zend_php_scanner_globals { unsigned char *yy_limit; int yy_state; zend_stack state_stack; + zend_ptr_stack heredoc_label_stack; /* original (unfiltered) script */ unsigned char *script_org; diff --git a/Zend/zend_highlight.c b/Zend/zend_highlight.c index ad299e3590..c789cb719a 100644 --- a/Zend/zend_highlight.c +++ b/Zend/zend_highlight.c @@ -153,8 +153,6 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini efree(token.value.str.val); break; } - } else if (token_type == T_END_HEREDOC) { - efree(token.value.str.val); } token.type = 0; } @@ -188,7 +186,6 @@ ZEND_API void zend_strip(TSRMLS_D) case T_END_HEREDOC: zend_write((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng)); - efree(token.value.str.val); /* read the following character, either newline or ; */ if (lex_scan(&token TSRMLS_CC) != T_WHITESPACE) { zend_write((char*)LANG_SCNG(yy_text), LANG_SCNG(yy_leng)); diff --git a/Zend/zend_ini_scanner.c b/Zend/zend_ini_scanner.c index 5f483de522..35d9763bd9 100644 --- a/Zend/zend_ini_scanner.c +++ b/Zend/zend_ini_scanner.c @@ -1,4 +1,4 @@ -/* Generated by re2c 0.13.5 on Fri Nov 16 18:24:06 2012 */ +/* Generated by re2c 0.13.5 */ #line 1 "Zend/zend_ini_scanner.l" /* +----------------------------------------------------------------------+ diff --git a/Zend/zend_ini_scanner_defs.h b/Zend/zend_ini_scanner_defs.h index 1fe4c0cd44..287d7bc1fb 100644 --- a/Zend/zend_ini_scanner_defs.h +++ b/Zend/zend_ini_scanner_defs.h @@ -1,4 +1,4 @@ -/* Generated by re2c 0.13.5 on Fri Nov 16 18:24:06 2012 */ +/* Generated by re2c 0.13.5 */ #line 3 "Zend/zend_ini_scanner_defs.h" enum YYCONDTYPE { diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 1f5d73296f..781d806fe7 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -68,6 +68,8 @@ static YYSIZE_T zend_yytnamerr(char*, const char*); %token T_LOGICAL_AND "and (T_LOGICAL_AND)" %right T_PRINT %token T_PRINT "print (T_PRINT)" +%right T_YIELD +%token T_YIELD "yield (T_YIELD)" %left '=' T_PLUS_EQUAL T_MINUS_EQUAL T_MUL_EQUAL T_DIV_EQUAL T_CONCAT_EQUAL T_MOD_EQUAL T_AND_EQUAL T_OR_EQUAL T_XOR_EQUAL T_SL_EQUAL T_SR_EQUAL %token T_PLUS_EQUAL "+= (T_PLUS_EQUAL)" %token T_MINUS_EQUAL "-= (T_MINUS_EQUAL)" @@ -160,6 +162,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*); %token T_RETURN "return (T_RETURN)" %token T_TRY "try (T_TRY)" %token T_CATCH "catch (T_CATCH)" +%token T_FINALLY "finally (T_FINALLY)" %token T_THROW "throw (T_THROW)" %token T_USE "use (T_USE)" %token T_INSTEADOF "insteadof (T_INSTEADOF)" @@ -276,10 +279,10 @@ statement: unticked_statement: '{' inner_statement_list '}' - | T_IF '(' expr ')' { zend_do_if_cond(&$3, &$4 TSRMLS_CC); } statement { zend_do_if_after_statement(&$4, 1 TSRMLS_CC); } elseif_list else_single { zend_do_if_end(TSRMLS_C); } - | T_IF '(' expr ')' ':' { zend_do_if_cond(&$3, &$4 TSRMLS_CC); } inner_statement_list { zend_do_if_after_statement(&$4, 1 TSRMLS_CC); } new_elseif_list new_else_single T_ENDIF ';' { zend_do_if_end(TSRMLS_C); } - | T_WHILE '(' { $1.u.op.opline_num = get_next_op_number(CG(active_op_array)); } expr ')' { zend_do_while_cond(&$4, &$5 TSRMLS_CC); } while_statement { zend_do_while_end(&$1, &$5 TSRMLS_CC); } - | T_DO { $1.u.op.opline_num = get_next_op_number(CG(active_op_array)); zend_do_do_while_begin(TSRMLS_C); } statement T_WHILE '(' { $5.u.op.opline_num = get_next_op_number(CG(active_op_array)); } expr ')' ';' { zend_do_do_while_end(&$1, &$5, &$7 TSRMLS_CC); } + | T_IF parenthesis_expr { zend_do_if_cond(&$2, &$1 TSRMLS_CC); } statement { zend_do_if_after_statement(&$1, 1 TSRMLS_CC); } elseif_list else_single { zend_do_if_end(TSRMLS_C); } + | T_IF parenthesis_expr ':' { zend_do_if_cond(&$2, &$1 TSRMLS_CC); } inner_statement_list { zend_do_if_after_statement(&$1, 1 TSRMLS_CC); } new_elseif_list new_else_single T_ENDIF ';' { zend_do_if_end(TSRMLS_C); } + | T_WHILE { $1.u.op.opline_num = get_next_op_number(CG(active_op_array)); } parenthesis_expr { zend_do_while_cond(&$3, &$$ TSRMLS_CC); } while_statement { zend_do_while_end(&$1, &$4 TSRMLS_CC); } + | T_DO { $1.u.op.opline_num = get_next_op_number(CG(active_op_array)); zend_do_do_while_begin(TSRMLS_C); } statement T_WHILE { $4.u.op.opline_num = get_next_op_number(CG(active_op_array)); } parenthesis_expr ';' { zend_do_do_while_end(&$1, &$4, &$6 TSRMLS_CC); } | T_FOR '(' for_expr @@ -289,7 +292,7 @@ unticked_statement: for_expr ')' { zend_do_free(&$9 TSRMLS_CC); zend_do_for_before_statement(&$4, &$7 TSRMLS_CC); } for_statement { zend_do_for_end(&$7 TSRMLS_CC); } - | T_SWITCH '(' expr ')' { zend_do_switch_cond(&$3 TSRMLS_CC); } switch_case_list { zend_do_switch_end(&$6 TSRMLS_CC); } + | T_SWITCH parenthesis_expr { zend_do_switch_cond(&$2 TSRMLS_CC); } switch_case_list { zend_do_switch_end(&$4 TSRMLS_CC); } | T_BREAK ';' { zend_do_brk_cont(ZEND_BRK, NULL TSRMLS_CC); } | T_BREAK expr ';' { zend_do_brk_cont(ZEND_BRK, &$2 TSRMLS_CC); } | T_CONTINUE ';' { zend_do_brk_cont(ZEND_CONT, NULL TSRMLS_CC); } @@ -297,6 +300,7 @@ unticked_statement: | T_RETURN ';' { zend_do_return(NULL, 0 TSRMLS_CC); } | T_RETURN expr_without_variable ';' { zend_do_return(&$2, 0 TSRMLS_CC); } | T_RETURN variable ';' { zend_do_return(&$2, 1 TSRMLS_CC); } + | yield_expr ';' { zend_do_free(&$1 TSRMLS_CC); } | T_GLOBAL global_var_list ';' | T_STATIC static_var_list ';' | T_ECHO echo_expr_list ';' @@ -309,20 +313,29 @@ unticked_statement: foreach_statement { zend_do_foreach_end(&$1, &$4 TSRMLS_CC); } | T_FOREACH '(' expr_without_variable T_AS { zend_do_foreach_begin(&$1, &$2, &$3, &$4, 0 TSRMLS_CC); } - variable foreach_optional_arg ')' { zend_check_writable_variable(&$6); zend_do_foreach_cont(&$1, &$2, &$4, &$6, &$7 TSRMLS_CC); } + foreach_variable foreach_optional_arg ')' { zend_do_foreach_cont(&$1, &$2, &$4, &$6, &$7 TSRMLS_CC); } foreach_statement { zend_do_foreach_end(&$1, &$4 TSRMLS_CC); } | T_DECLARE { $1.u.op.opline_num = get_next_op_number(CG(active_op_array)); zend_do_declare_begin(TSRMLS_C); } '(' declare_list ')' declare_statement { zend_do_declare_end(&$1 TSRMLS_CC); } | ';' /* empty statement */ | T_TRY { zend_do_try(&$1 TSRMLS_CC); } '{' inner_statement_list '}' - T_CATCH '(' { zend_initialize_try_catch_element(&$1 TSRMLS_CC); } - fully_qualified_class_name { zend_do_first_catch(&$7 TSRMLS_CC); } - T_VARIABLE ')' { zend_do_begin_catch(&$1, &$9, &$11, &$7 TSRMLS_CC); } - '{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); } - additional_catches { zend_do_mark_last_catch(&$7, &$18 TSRMLS_CC); } + catch_statement { zend_do_bind_catch(&$1, &$6 TSRMLS_CC); } + finally_statement { zend_do_end_finally(&$1, &$6, &$8 TSRMLS_CC); } | T_THROW expr ';' { zend_do_throw(&$2 TSRMLS_CC); } | T_GOTO T_STRING ';' { zend_do_goto(&$2 TSRMLS_CC); } ; +catch_statement: + /* empty */ { $$.op_type = IS_UNUSED; } + | T_CATCH '(' { zend_initialize_try_catch_element(&$1 TSRMLS_CC); } + fully_qualified_class_name { zend_do_first_catch(&$2 TSRMLS_CC); } + T_VARIABLE ')' { zend_do_begin_catch(&$1, &$4, &$6, &$2 TSRMLS_CC); } + '{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); } + additional_catches { zend_do_mark_last_catch(&$2, &$13 TSRMLS_CC); $$ = $1;} + +finally_statement: + /* empty */ { $$.op_type = IS_UNUSED; } + | T_FINALLY { zend_do_finally(&$1 TSRMLS_CC); } '{' inner_statement_list '}' { $$ = $1; } +; additional_catches: non_empty_additional_catches { $$ = $1; } @@ -334,12 +347,10 @@ non_empty_additional_catches: | non_empty_additional_catches additional_catch { $$ = $2; } ; - additional_catch: T_CATCH '(' fully_qualified_class_name { $$.u.op.opline_num = get_next_op_number(CG(active_op_array)); } T_VARIABLE ')' { zend_do_begin_catch(&$1, &$3, &$5, NULL TSRMLS_CC); } '{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); } ; - unset_variables: unset_variable | unset_variables ',' unset_variable @@ -357,7 +368,6 @@ class_declaration_statement: unticked_class_declaration_statement { DO_TICKS(); } ; - is_reference: /* empty */ { $$.op_type = ZEND_RETURN_VAL; } | '&' { $$.op_type = ZEND_RETURN_REF; } @@ -366,7 +376,8 @@ is_reference: unticked_function_declaration_statement: function is_reference T_STRING { zend_do_begin_function_declaration(&$1, &$3, 0, $2.op_type, NULL TSRMLS_CC); } - '(' parameter_list ')' '{' inner_statement_list '}' { zend_do_end_function_declaration(&$1 TSRMLS_CC); } + '(' parameter_list ')' + '{' inner_statement_list '}' { zend_do_end_function_declaration(&$1 TSRMLS_CC); } ; unticked_class_declaration_statement: @@ -421,10 +432,10 @@ foreach_optional_arg: | T_DOUBLE_ARROW foreach_variable { $$ = $2; } ; - foreach_variable: variable { zend_check_writable_variable(&$1); $$ = $1; } | '&' variable { zend_check_writable_variable(&$2); $$ = $2; $$.EA |= ZEND_PARSED_REFERENCE_VARIABLE; } + | T_LIST '(' { zend_do_list_init(TSRMLS_C); } assignment_list ')' { $$ = $1; $$.EA = ZEND_PARSED_LIST_EXPR; } ; for_statement: @@ -481,13 +492,13 @@ while_statement: elseif_list: /* empty */ - | elseif_list T_ELSEIF '(' expr ')' { zend_do_if_cond(&$4, &$5 TSRMLS_CC); } statement { zend_do_if_after_statement(&$5, 0 TSRMLS_CC); } + | elseif_list T_ELSEIF parenthesis_expr { zend_do_if_cond(&$3, &$2 TSRMLS_CC); } statement { zend_do_if_after_statement(&$2, 0 TSRMLS_CC); } ; new_elseif_list: /* empty */ - | new_elseif_list T_ELSEIF '(' expr ')' ':' { zend_do_if_cond(&$4, &$5 TSRMLS_CC); } inner_statement_list { zend_do_if_after_statement(&$5, 0 TSRMLS_CC); } + | new_elseif_list T_ELSEIF parenthesis_expr ':' { zend_do_if_cond(&$3, &$2 TSRMLS_CC); } inner_statement_list { zend_do_if_after_statement(&$2, 0 TSRMLS_CC); } ; @@ -530,8 +541,9 @@ optional_class_type: function_call_parameter_list: - non_empty_function_call_parameter_list { $$ = $1; } - | /* empty */ { Z_LVAL($$.u.constant) = 0; } + '(' ')' { Z_LVAL($$.u.constant) = 0; } + | '(' non_empty_function_call_parameter_list ')' { $$ = $2; } + | '(' yield_expr ')' { Z_LVAL($$.u.constant) = 1; zend_do_pass_param(&$2, ZEND_SEND_VAL, Z_LVAL($$.u.constant) TSRMLS_CC); } ; @@ -576,8 +588,9 @@ class_statement: variable_modifiers { CG(access_type) = Z_LVAL($1.u.constant); } class_variable_declaration ';' | class_constant_declaration ';' | trait_use_statement - | method_modifiers function is_reference T_STRING { zend_do_begin_function_declaration(&$2, &$4, 1, $3.op_type, &$1 TSRMLS_CC); } '(' - parameter_list ')' method_body { zend_do_abstract_method(&$4, &$1, &$9 TSRMLS_CC); zend_do_end_function_declaration(&$2 TSRMLS_CC); } + | method_modifiers function is_reference T_STRING { zend_do_begin_function_declaration(&$2, &$4, 1, $3.op_type, &$1 TSRMLS_CC); } + '(' parameter_list ')' + method_body { zend_do_abstract_method(&$4, &$1, &$9 TSRMLS_CC); zend_do_end_function_declaration(&$2 TSRMLS_CC); } ; trait_use_statement: @@ -770,7 +783,7 @@ expr_without_variable: | expr '>' expr { zend_do_binary_op(ZEND_IS_SMALLER, &$$, &$3, &$1 TSRMLS_CC); } | expr T_IS_GREATER_OR_EQUAL expr { zend_do_binary_op(ZEND_IS_SMALLER_OR_EQUAL, &$$, &$3, &$1 TSRMLS_CC); } | expr T_INSTANCEOF class_name_reference { zend_do_instanceof(&$$, &$1, &$3, 0 TSRMLS_CC); } - | '(' expr ')' { $$ = $2; } + | parenthesis_expr { $$ = $1; } | new_expr { $$ = $1; } | '(' new_expr ')' { $$ = $2; } instance_call { $$ = $5; } | expr '?' { zend_do_begin_qm_op(&$1, &$2 TSRMLS_CC); } @@ -789,16 +802,35 @@ expr_without_variable: | T_EXIT exit_expr { zend_do_exit(&$$, &$2 TSRMLS_CC); } | '@' { zend_do_begin_silence(&$1 TSRMLS_CC); } expr { zend_do_end_silence(&$1 TSRMLS_CC); $$ = $3; } | scalar { $$ = $1; } - | T_ARRAY '(' array_pair_list ')' { $$ = $3; } - | '[' array_pair_list ']' { $$ = $2; } + | combined_scalar_offset { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); } + | combined_scalar { $$ = $1; } | '`' backticks_expr '`' { zend_do_shell_exec(&$$, &$2 TSRMLS_CC); } | T_PRINT expr { zend_do_print(&$$, &$2 TSRMLS_CC); } - | function is_reference '(' { zend_do_begin_lambda_function_declaration(&$$, &$1, $2.op_type, 0 TSRMLS_CC); } - parameter_list ')' lexical_vars '{' inner_statement_list '}' { zend_do_end_function_declaration(&$1 TSRMLS_CC); $$ = $4; } - | T_STATIC function is_reference '(' { zend_do_begin_lambda_function_declaration(&$$, &$2, $3.op_type, 1 TSRMLS_CC); } - parameter_list ')' lexical_vars '{' inner_statement_list '}' { zend_do_end_function_declaration(&$2 TSRMLS_CC); $$ = $5; } + | T_YIELD { zend_do_yield(&$$, NULL, NULL, 0 TSRMLS_CC); } + | function is_reference { zend_do_begin_lambda_function_declaration(&$$, &$1, $2.op_type, 0 TSRMLS_CC); } + '(' parameter_list ')' lexical_vars + '{' inner_statement_list '}' { zend_do_end_function_declaration(&$1 TSRMLS_CC); $$ = $3; } + | T_STATIC function is_reference { zend_do_begin_lambda_function_declaration(&$$, &$2, $3.op_type, 1 TSRMLS_CC); } + '(' parameter_list ')' lexical_vars + '{' inner_statement_list '}' { zend_do_end_function_declaration(&$2 TSRMLS_CC); $$ = $4; } ; +yield_expr: + T_YIELD expr_without_variable { zend_do_yield(&$$, &$2, NULL, 0 TSRMLS_CC); } + | T_YIELD variable { zend_do_yield(&$$, &$2, NULL, 1 TSRMLS_CC); } + | T_YIELD expr T_DOUBLE_ARROW expr_without_variable { zend_do_yield(&$$, &$4, &$2, 0 TSRMLS_CC); } + | T_YIELD expr T_DOUBLE_ARROW variable { zend_do_yield(&$$, &$4, &$2, 1 TSRMLS_CC); } +; + +combined_scalar_offset: + combined_scalar '[' dim_offset ']' { zend_do_begin_variable_parse(TSRMLS_C); fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); } + | combined_scalar_offset '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); } + | T_CONSTANT_ENCAPSED_STRING '[' dim_offset ']' { $1.EA = 0; zend_do_begin_variable_parse(TSRMLS_C); fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); } + +combined_scalar: + T_ARRAY '(' array_pair_list ')' { $$ = $3; } + | '[' array_pair_list ']' { $$ = $2; } + function: T_FUNCTION { $$.u.op.opline_num = CG(zend_lineno); } ; @@ -816,30 +848,22 @@ lexical_var_list: ; function_call: - namespace_name '(' { $2.u.op.opline_num = zend_do_begin_function_call(&$1, 1 TSRMLS_CC); } - function_call_parameter_list - ')' { zend_do_end_function_call(&$1, &$$, &$4, 0, $2.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); } - | T_NAMESPACE T_NS_SEPARATOR namespace_name '(' { $1.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$1.u.constant); zend_do_build_namespace_name(&$1, &$1, &$3 TSRMLS_CC); $4.u.op.opline_num = zend_do_begin_function_call(&$1, 0 TSRMLS_CC); } - function_call_parameter_list - ')' { zend_do_end_function_call(&$1, &$$, &$6, 0, $4.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); } - | T_NS_SEPARATOR namespace_name '(' { $3.u.op.opline_num = zend_do_begin_function_call(&$2, 0 TSRMLS_CC); } - function_call_parameter_list - ')' { zend_do_end_function_call(&$2, &$$, &$5, 0, $3.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); } - | class_name T_PAAMAYIM_NEKUDOTAYIM variable_name '(' { $4.u.op.opline_num = zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); } - function_call_parameter_list - ')' { zend_do_end_function_call($4.u.op.opline_num?NULL:&$3, &$$, &$6, $4.u.op.opline_num, $4.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} - | class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects '(' { zend_do_end_variable_parse(&$3, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); } - function_call_parameter_list - ')' { zend_do_end_function_call(NULL, &$$, &$6, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} - | variable_class_name T_PAAMAYIM_NEKUDOTAYIM variable_name '(' { zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); } - function_call_parameter_list - ')' { zend_do_end_function_call(NULL, &$$, &$6, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} - | variable_class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects '(' { zend_do_end_variable_parse(&$3, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); } - function_call_parameter_list - ')' { zend_do_end_function_call(NULL, &$$, &$6, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} - | variable_without_objects '(' { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_dynamic_function_call(&$1, 0 TSRMLS_CC); } - function_call_parameter_list ')' - { zend_do_end_function_call(&$1, &$$, &$4, 0, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} + namespace_name { $$.u.op.opline_num = zend_do_begin_function_call(&$1, 1 TSRMLS_CC); } + function_call_parameter_list { zend_do_end_function_call(&$1, &$$, &$3, 0, $2.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); } + | T_NAMESPACE T_NS_SEPARATOR namespace_name { $1.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$1.u.constant); zend_do_build_namespace_name(&$1, &$1, &$3 TSRMLS_CC); $$.u.op.opline_num = zend_do_begin_function_call(&$1, 0 TSRMLS_CC); } + function_call_parameter_list { zend_do_end_function_call(&$1, &$$, &$5, 0, $4.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); } + | T_NS_SEPARATOR namespace_name { $$.u.op.opline_num = zend_do_begin_function_call(&$2, 0 TSRMLS_CC); } + function_call_parameter_list { zend_do_end_function_call(&$2, &$$, &$4, 0, $3.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); } + | class_name T_PAAMAYIM_NEKUDOTAYIM variable_name { $$.u.op.opline_num = zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); } + function_call_parameter_list { zend_do_end_function_call($4.u.op.opline_num?NULL:&$3, &$$, &$5, $4.u.op.opline_num, $4.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} + | class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects { zend_do_end_variable_parse(&$3, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); } + function_call_parameter_list { zend_do_end_function_call(NULL, &$$, &$5, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} + | variable_class_name T_PAAMAYIM_NEKUDOTAYIM variable_name { zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); } + function_call_parameter_list { zend_do_end_function_call(NULL, &$$, &$5, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} + | variable_class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects { zend_do_end_variable_parse(&$3, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); } + function_call_parameter_list { zend_do_end_function_call(NULL, &$$, &$5, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} + | variable_without_objects { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_dynamic_function_call(&$1, 0 TSRMLS_CC); } + function_call_parameter_list { zend_do_end_function_call(&$1, &$$, &$3, 0, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} ; class_name: @@ -884,7 +908,7 @@ dynamic_class_name_variable_property: exit_expr: /* empty */ { memset(&$$, 0, sizeof(znode)); $$.op_type = IS_UNUSED; } | '(' ')' { memset(&$$, 0, sizeof(znode)); $$.op_type = IS_UNUSED; } - | '(' expr ')' { $$ = $2; } + | parenthesis_expr { $$ = $1; } ; backticks_expr: @@ -895,8 +919,8 @@ backticks_expr: ctor_arguments: - /* empty */ { Z_LVAL($$.u.constant)=0; } - | '(' function_call_parameter_list ')' { $$ = $2; } + /* empty */ { Z_LVAL($$.u.constant) = 0; } + | function_call_parameter_list { $$ = $1; } ; @@ -911,8 +935,8 @@ common_scalar: | T_METHOD_C { $$ = $1; } | T_FUNC_C { $$ = $1; } | T_NS_C { $$ = $1; } - | T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC { $$ = $2; CG(heredoc) = Z_STRVAL($1.u.constant); CG(heredoc_len) = Z_STRLEN($1.u.constant); } - | T_START_HEREDOC T_END_HEREDOC { ZVAL_EMPTY_STRING(&$$.u.constant); INIT_PZVAL(&$$.u.constant); $$.op_type = IS_CONST; CG(heredoc) = Z_STRVAL($1.u.constant); CG(heredoc_len) = Z_STRLEN($1.u.constant); } + | T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC { $$ = $2; } + | T_START_HEREDOC T_END_HEREDOC { ZVAL_EMPTY_STRING(&$$.u.constant); INIT_PZVAL(&$$.u.constant); $$.op_type = IS_CONST; } ; @@ -941,7 +965,7 @@ scalar: | T_NS_SEPARATOR namespace_name { char *tmp = estrndup(Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); memcpy(&(tmp[1]), Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); tmp[0] = '\\'; efree(Z_STRVAL($2.u.constant)); Z_STRVAL($2.u.constant) = tmp; ++Z_STRLEN($2.u.constant); zend_do_fetch_constant(&$$, NULL, &$2, ZEND_RT, 0 TSRMLS_CC); } | common_scalar { $$ = $1; } | '"' encaps_list '"' { $$ = $2; } - | T_START_HEREDOC encaps_list T_END_HEREDOC { $$ = $2; CG(heredoc) = Z_STRVAL($1.u.constant); CG(heredoc_len) = Z_STRLEN($1.u.constant); } + | T_START_HEREDOC encaps_list T_END_HEREDOC { $$ = $2; } | T_CLASS_C { if (Z_TYPE($1.u.constant) == IS_CONSTANT) {zend_do_fetch_constant(&$$, NULL, &$1, ZEND_RT, 1 TSRMLS_CC);} else {$$ = $1;} } ; @@ -968,6 +992,11 @@ expr: | expr_without_variable { $$ = $1; } ; +parenthesis_expr: + '(' expr ')' { $$ = $2; } + | '(' yield_expr ')' { $$ = $2; } +; + r_variable: variable { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); $$ = $1; } @@ -1007,9 +1036,8 @@ array_method_dereference: ; method: - '(' { zend_do_pop_object(&$1 TSRMLS_CC); zend_do_begin_method_call(&$1 TSRMLS_CC); } - function_call_parameter_list ')' - { zend_do_end_function_call(&$1, &$$, &$3, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); } + { zend_do_pop_object(&$$ TSRMLS_CC); zend_do_begin_method_call(&$$ TSRMLS_CC); } + function_call_parameter_list { zend_do_end_function_call(&$1, &$$, &$2, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); } ; method_or_not: @@ -1149,6 +1177,7 @@ encaps_var_offset: internal_functions_in_yacc: T_ISSET '(' isset_variables ')' { $$ = $3; } | T_EMPTY '(' variable ')' { zend_do_isset_or_isempty(ZEND_ISEMPTY, &$$, &$3 TSRMLS_CC); } + | T_EMPTY '(' expr_without_variable ')' { zend_do_unary_op(ZEND_BOOL_NOT, &$$, &$3 TSRMLS_CC); } | T_INCLUDE expr { zend_do_include_or_eval(ZEND_INCLUDE, &$$, &$2 TSRMLS_CC); } | T_INCLUDE_ONCE expr { zend_do_include_or_eval(ZEND_INCLUDE_ONCE, &$$, &$2 TSRMLS_CC); } | T_EVAL '(' expr ')' { zend_do_include_or_eval(ZEND_EVAL, &$$, &$3 TSRMLS_CC); } @@ -1157,8 +1186,13 @@ internal_functions_in_yacc: ; isset_variables: - variable { zend_do_isset_or_isempty(ZEND_ISSET, &$$, &$1 TSRMLS_CC); } - | isset_variables ',' { zend_do_boolean_and_begin(&$1, &$2 TSRMLS_CC); } variable { znode tmp; zend_do_isset_or_isempty(ZEND_ISSET, &tmp, &$4 TSRMLS_CC); zend_do_boolean_and_end(&$$, &$1, &tmp, &$2 TSRMLS_CC); } + isset_variable { $$ = $1; } + | isset_variables ',' { zend_do_boolean_and_begin(&$1, &$2 TSRMLS_CC); } isset_variable { zend_do_boolean_and_end(&$$, &$1, &$4, &$2 TSRMLS_CC); } +; + +isset_variable: + variable { zend_do_isset_or_isempty(ZEND_ISSET, &$$, &$1 TSRMLS_CC); } + | expr_without_variable { zend_error(E_COMPILE_ERROR, "Cannot use isset() on the result of an expression (you can use \"null !== expression\" instead)"); } ; class_constant: diff --git a/Zend/zend_language_scanner.c b/Zend/zend_language_scanner.c index 40fb574559..f2ba6bf9d4 100644 --- a/Zend/zend_language_scanner.c +++ b/Zend/zend_language_scanner.c @@ -1,4 +1,4 @@ -/* Generated by re2c 0.13.5 on Wed Nov 14 17:46:56 2012 */ +/* Generated by re2c 0.13.5 */ #line 1 "Zend/zend_language_scanner.l" /* +----------------------------------------------------------------------+ @@ -180,22 +180,23 @@ static void yy_scan_buffer(char *str, unsigned int len TSRMLS_DC) void startup_scanner(TSRMLS_D) { CG(parse_error) = 0; - CG(heredoc) = NULL; - CG(heredoc_len) = 0; CG(doc_comment) = NULL; CG(doc_comment_len) = 0; zend_stack_init(&SCNG(state_stack)); + zend_ptr_stack_init(&SCNG(heredoc_label_stack)); +} + +static void heredoc_label_dtor(zend_heredoc_label *heredoc_label) { + efree(heredoc_label->label); } void shutdown_scanner(TSRMLS_D) { - if (CG(heredoc)) { - efree(CG(heredoc)); - CG(heredoc_len)=0; - } CG(parse_error) = 0; - zend_stack_destroy(&SCNG(state_stack)); RESET_DOC_COMMENT(); + zend_stack_destroy(&SCNG(state_stack)); + zend_ptr_stack_clean(&SCNG(heredoc_label_stack), (void (*)(void *)) &heredoc_label_dtor, 1); + zend_ptr_stack_destroy(&SCNG(heredoc_label_stack)); } ZEND_API void zend_save_lexical_state(zend_lex_state *lex_state TSRMLS_DC) @@ -210,6 +211,9 @@ ZEND_API void zend_save_lexical_state(zend_lex_state *lex_state TSRMLS_DC) lex_state->state_stack = SCNG(state_stack); zend_stack_init(&SCNG(state_stack)); + lex_state->heredoc_label_stack = SCNG(heredoc_label_stack); + zend_ptr_stack_init(&SCNG(heredoc_label_stack)); + lex_state->in = SCNG(yy_in); lex_state->yy_state = YYSTATE; lex_state->filename = zend_get_compiled_filename(TSRMLS_C); @@ -236,6 +240,10 @@ ZEND_API void zend_restore_lexical_state(zend_lex_state *lex_state TSRMLS_DC) zend_stack_destroy(&SCNG(state_stack)); SCNG(state_stack) = lex_state->state_stack; + zend_ptr_stack_clean(&SCNG(heredoc_label_stack), (void (*)(void *)) &heredoc_label_dtor, 1); + zend_ptr_stack_destroy(&SCNG(heredoc_label_stack)); + SCNG(heredoc_label_stack) = lex_state->heredoc_label_stack; + SCNG(yy_in) = lex_state->in; YYSETCONDITION(lex_state->yy_state); CG(zend_lineno) = lex_state->lineno; @@ -252,12 +260,6 @@ ZEND_API void zend_restore_lexical_state(zend_lex_state *lex_state TSRMLS_DC) SCNG(input_filter) = lex_state->input_filter; SCNG(output_filter) = lex_state->output_filter; SCNG(script_encoding) = lex_state->script_encoding; - - if (CG(heredoc)) { - efree(CG(heredoc)); - CG(heredoc) = NULL; - CG(heredoc_len) = 0; - } } ZEND_API void zend_destroy_file_handle(zend_file_handle *file_handle TSRMLS_DC) @@ -1000,7 +1002,7 @@ restart: yymore_restart: -#line 1004 "Zend/zend_language_scanner.c" +#line 1006 "Zend/zend_language_scanner.c" { YYCTYPE yych; unsigned int yyaccept = 0; @@ -1099,7 +1101,7 @@ yyc_INITIAL: yy3: YYDEBUG(3, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1792 "Zend/zend_language_scanner.l" +#line 1803 "Zend/zend_language_scanner.l" { if (YYCURSOR > YYLIMIT) { return 0; @@ -1159,7 +1161,7 @@ inline_html: HANDLE_NEWLINES(yytext, yyleng); return T_INLINE_HTML; } -#line 1163 "Zend/zend_language_scanner.c" +#line 1165 "Zend/zend_language_scanner.c" yy4: YYDEBUG(4, *YYCURSOR); yych = *++YYCURSOR; @@ -1177,7 +1179,7 @@ yy5: yy6: YYDEBUG(6, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1780 "Zend/zend_language_scanner.l" +#line 1791 "Zend/zend_language_scanner.l" { if (CG(short_tags)) { zendlval->value.str.val = yytext; /* no copying - intentional */ @@ -1189,14 +1191,14 @@ yy6: goto inline_char_handler; } } -#line 1193 "Zend/zend_language_scanner.c" +#line 1195 "Zend/zend_language_scanner.c" yy7: YYDEBUG(7, *YYCURSOR); ++YYCURSOR; if ((yych = *YYCURSOR) == '=') goto yy43; YYDEBUG(8, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1757 "Zend/zend_language_scanner.l" +#line 1768 "Zend/zend_language_scanner.l" { if (CG(asp_tags)) { zendlval->value.str.val = yytext; /* no copying - intentional */ @@ -1208,7 +1210,7 @@ yy7: goto inline_char_handler; } } -#line 1212 "Zend/zend_language_scanner.c" +#line 1214 "Zend/zend_language_scanner.c" yy9: YYDEBUG(9, *YYCURSOR); yych = *++YYCURSOR; @@ -1394,7 +1396,7 @@ yy35: ++YYCURSOR; YYDEBUG(38, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1717 "Zend/zend_language_scanner.l" +#line 1728 "Zend/zend_language_scanner.l" { YYCTYPE *bracket = (YYCTYPE*)zend_memrchr(yytext, '<', yyleng - (sizeof("script language=php>") - 1)); @@ -1411,7 +1413,7 @@ yy35: BEGIN(ST_IN_SCRIPTING); return T_OPEN_TAG; } -#line 1415 "Zend/zend_language_scanner.c" +#line 1417 "Zend/zend_language_scanner.c" yy39: YYDEBUG(39, *YYCURSOR); yych = *++YYCURSOR; @@ -1438,7 +1440,7 @@ yy43: ++YYCURSOR; YYDEBUG(44, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1735 "Zend/zend_language_scanner.l" +#line 1746 "Zend/zend_language_scanner.l" { if (CG(asp_tags)) { zendlval->value.str.val = yytext; /* no copying - intentional */ @@ -1450,13 +1452,13 @@ yy43: goto inline_char_handler; } } -#line 1454 "Zend/zend_language_scanner.c" +#line 1456 "Zend/zend_language_scanner.c" yy45: YYDEBUG(45, *YYCURSOR); ++YYCURSOR; YYDEBUG(46, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1748 "Zend/zend_language_scanner.l" +#line 1759 "Zend/zend_language_scanner.l" { zendlval->value.str.val = yytext; /* no copying - intentional */ zendlval->value.str.len = yyleng; @@ -1464,7 +1466,7 @@ yy45: BEGIN(ST_IN_SCRIPTING); return T_OPEN_TAG_WITH_ECHO; } -#line 1468 "Zend/zend_language_scanner.c" +#line 1470 "Zend/zend_language_scanner.c" yy47: YYDEBUG(47, *YYCURSOR); yych = *++YYCURSOR; @@ -1491,7 +1493,7 @@ yy50: yy51: YYDEBUG(51, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1770 "Zend/zend_language_scanner.l" +#line 1781 "Zend/zend_language_scanner.l" { zendlval->value.str.val = yytext; /* no copying - intentional */ zendlval->value.str.len = yyleng; @@ -1500,7 +1502,7 @@ yy51: BEGIN(ST_IN_SCRIPTING); return T_OPEN_TAG; } -#line 1504 "Zend/zend_language_scanner.c" +#line 1506 "Zend/zend_language_scanner.c" yy52: YYDEBUG(52, *YYCURSOR); ++YYCURSOR; @@ -1571,7 +1573,7 @@ yyc_ST_BACKQUOTE: yy56: YYDEBUG(56, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2243 "Zend/zend_language_scanner.l" +#line 2254 "Zend/zend_language_scanner.l" { if (YYCURSOR > YYLIMIT) { return 0; @@ -1612,7 +1614,7 @@ yy56: zend_scan_escape_string(zendlval, yytext, yyleng, '`' TSRMLS_CC); return T_ENCAPSED_AND_WHITESPACE; } -#line 1616 "Zend/zend_language_scanner.c" +#line 1618 "Zend/zend_language_scanner.c" yy57: YYDEBUG(57, *YYCURSOR); yych = *++YYCURSOR; @@ -1623,12 +1625,12 @@ yy58: ++YYCURSOR; YYDEBUG(59, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2187 "Zend/zend_language_scanner.l" +#line 2198 "Zend/zend_language_scanner.l" { BEGIN(ST_IN_SCRIPTING); return '`'; } -#line 1632 "Zend/zend_language_scanner.c" +#line 1634 "Zend/zend_language_scanner.c" yy60: YYDEBUG(60, *YYCURSOR); yych = *++YYCURSOR; @@ -1638,14 +1640,14 @@ yy61: ++YYCURSOR; YYDEBUG(62, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2174 "Zend/zend_language_scanner.l" +#line 2185 "Zend/zend_language_scanner.l" { zendlval->value.lval = (long) '{'; yy_push_state(ST_IN_SCRIPTING TSRMLS_CC); yyless(1); return T_CURLY_OPEN; } -#line 1649 "Zend/zend_language_scanner.c" +#line 1651 "Zend/zend_language_scanner.c" yy63: YYDEBUG(63, *YYCURSOR); yyaccept = 0; @@ -1661,24 +1663,24 @@ yy63: yy65: YYDEBUG(65, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1874 "Zend/zend_language_scanner.l" +#line 1885 "Zend/zend_language_scanner.l" { zend_copy_value(zendlval, (yytext+1), (yyleng-1)); zendlval->type = IS_STRING; return T_VARIABLE; } -#line 1671 "Zend/zend_language_scanner.c" +#line 1673 "Zend/zend_language_scanner.c" yy66: YYDEBUG(66, *YYCURSOR); ++YYCURSOR; YYDEBUG(67, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1451 "Zend/zend_language_scanner.l" +#line 1461 "Zend/zend_language_scanner.l" { yy_push_state(ST_LOOKING_FOR_VARNAME TSRMLS_CC); return T_DOLLAR_OPEN_CURLY_BRACES; } -#line 1682 "Zend/zend_language_scanner.c" +#line 1684 "Zend/zend_language_scanner.c" yy68: YYDEBUG(68, *YYCURSOR); yych = *++YYCURSOR; @@ -1692,7 +1694,7 @@ yy70: ++YYCURSOR; YYDEBUG(71, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1866 "Zend/zend_language_scanner.l" +#line 1877 "Zend/zend_language_scanner.l" { yyless(yyleng - 1); yy_push_state(ST_VAR_OFFSET TSRMLS_CC); @@ -1700,7 +1702,7 @@ yy70: zendlval->type = IS_STRING; return T_VARIABLE; } -#line 1704 "Zend/zend_language_scanner.c" +#line 1706 "Zend/zend_language_scanner.c" yy72: YYDEBUG(72, *YYCURSOR); yych = *++YYCURSOR; @@ -1718,7 +1720,7 @@ yy73: ++YYCURSOR; YYDEBUG(74, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1856 "Zend/zend_language_scanner.l" +#line 1867 "Zend/zend_language_scanner.l" { yyless(yyleng - 3); yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC); @@ -1726,7 +1728,7 @@ yy73: zendlval->type = IS_STRING; return T_VARIABLE; } -#line 1730 "Zend/zend_language_scanner.c" +#line 1732 "Zend/zend_language_scanner.c" } /* *********************************** */ yyc_ST_DOUBLE_QUOTES: @@ -1794,7 +1796,7 @@ yy77: yy78: YYDEBUG(78, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2193 "Zend/zend_language_scanner.l" +#line 2204 "Zend/zend_language_scanner.l" { if (GET_DOUBLE_QUOTES_SCANNED_LENGTH()) { YYCURSOR += GET_DOUBLE_QUOTES_SCANNED_LENGTH() - 1; @@ -1843,7 +1845,7 @@ double_quotes_scan_done: zend_scan_escape_string(zendlval, yytext, yyleng, '"' TSRMLS_CC); return T_ENCAPSED_AND_WHITESPACE; } -#line 1847 "Zend/zend_language_scanner.c" +#line 1849 "Zend/zend_language_scanner.c" yy79: YYDEBUG(79, *YYCURSOR); yych = *++YYCURSOR; @@ -1854,12 +1856,12 @@ yy80: ++YYCURSOR; YYDEBUG(81, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2182 "Zend/zend_language_scanner.l" +#line 2193 "Zend/zend_language_scanner.l" { BEGIN(ST_IN_SCRIPTING); return '"'; } -#line 1863 "Zend/zend_language_scanner.c" +#line 1865 "Zend/zend_language_scanner.c" yy82: YYDEBUG(82, *YYCURSOR); yych = *++YYCURSOR; @@ -1869,14 +1871,14 @@ yy83: ++YYCURSOR; YYDEBUG(84, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2174 "Zend/zend_language_scanner.l" +#line 2185 "Zend/zend_language_scanner.l" { zendlval->value.lval = (long) '{'; yy_push_state(ST_IN_SCRIPTING TSRMLS_CC); yyless(1); return T_CURLY_OPEN; } -#line 1880 "Zend/zend_language_scanner.c" +#line 1882 "Zend/zend_language_scanner.c" yy85: YYDEBUG(85, *YYCURSOR); yyaccept = 0; @@ -1892,24 +1894,24 @@ yy85: yy87: YYDEBUG(87, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1874 "Zend/zend_language_scanner.l" +#line 1885 "Zend/zend_language_scanner.l" { zend_copy_value(zendlval, (yytext+1), (yyleng-1)); zendlval->type = IS_STRING; return T_VARIABLE; } -#line 1902 "Zend/zend_language_scanner.c" +#line 1904 "Zend/zend_language_scanner.c" yy88: YYDEBUG(88, *YYCURSOR); ++YYCURSOR; YYDEBUG(89, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1451 "Zend/zend_language_scanner.l" +#line 1461 "Zend/zend_language_scanner.l" { yy_push_state(ST_LOOKING_FOR_VARNAME TSRMLS_CC); return T_DOLLAR_OPEN_CURLY_BRACES; } -#line 1913 "Zend/zend_language_scanner.c" +#line 1915 "Zend/zend_language_scanner.c" yy90: YYDEBUG(90, *YYCURSOR); yych = *++YYCURSOR; @@ -1923,7 +1925,7 @@ yy92: ++YYCURSOR; YYDEBUG(93, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1866 "Zend/zend_language_scanner.l" +#line 1877 "Zend/zend_language_scanner.l" { yyless(yyleng - 1); yy_push_state(ST_VAR_OFFSET TSRMLS_CC); @@ -1931,7 +1933,7 @@ yy92: zendlval->type = IS_STRING; return T_VARIABLE; } -#line 1935 "Zend/zend_language_scanner.c" +#line 1937 "Zend/zend_language_scanner.c" yy94: YYDEBUG(94, *YYCURSOR); yych = *++YYCURSOR; @@ -1949,7 +1951,7 @@ yy95: ++YYCURSOR; YYDEBUG(96, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1856 "Zend/zend_language_scanner.l" +#line 1867 "Zend/zend_language_scanner.l" { yyless(yyleng - 3); yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC); @@ -1957,7 +1959,7 @@ yy95: zendlval->type = IS_STRING; return T_VARIABLE; } -#line 1961 "Zend/zend_language_scanner.c" +#line 1963 "Zend/zend_language_scanner.c" } /* *********************************** */ yyc_ST_END_HEREDOC: @@ -1968,19 +1970,20 @@ yyc_ST_END_HEREDOC: ++YYCURSOR; YYDEBUG(100, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2161 "Zend/zend_language_scanner.l" +#line 2171 "Zend/zend_language_scanner.l" { - YYCURSOR += CG(heredoc_len) - 1; - yyleng = CG(heredoc_len); + zend_heredoc_label *heredoc_label = zend_ptr_stack_pop(&SCNG(heredoc_label_stack)); + + YYCURSOR += heredoc_label->length - 1; + yyleng = heredoc_label->length; + + heredoc_label_dtor(heredoc_label); + efree(heredoc_label); - Z_STRVAL_P(zendlval) = CG(heredoc); - Z_STRLEN_P(zendlval) = CG(heredoc_len); - CG(heredoc) = NULL; - CG(heredoc_len) = 0; BEGIN(ST_IN_SCRIPTING); return T_END_HEREDOC; } -#line 1984 "Zend/zend_language_scanner.c" +#line 1987 "Zend/zend_language_scanner.c" /* *********************************** */ yyc_ST_HEREDOC: { @@ -2042,10 +2045,12 @@ yy103: yy104: YYDEBUG(104, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2285 "Zend/zend_language_scanner.l" +#line 2296 "Zend/zend_language_scanner.l" { int newline = 0; + zend_heredoc_label *heredoc_label = zend_ptr_stack_top(&SCNG(heredoc_label_stack)); + if (YYCURSOR > YYLIMIT) { return 0; } @@ -2061,8 +2066,8 @@ yy104: /* fall through */ case '\n': /* Check for ending label on the next line */ - if (IS_LABEL_START(*YYCURSOR) && CG(heredoc_len) < YYLIMIT - YYCURSOR && !memcmp(YYCURSOR, CG(heredoc), CG(heredoc_len))) { - YYCTYPE *end = YYCURSOR + CG(heredoc_len); + if (IS_LABEL_START(*YYCURSOR) && heredoc_label->length < YYLIMIT - YYCURSOR && !memcmp(YYCURSOR, heredoc_label->label, heredoc_label->length)) { + YYCTYPE *end = YYCURSOR + heredoc_label->length; if (*end == ';') { end++; @@ -2113,7 +2118,7 @@ heredoc_scan_done: zend_scan_escape_string(zendlval, yytext, yyleng - newline, 0 TSRMLS_CC); return T_ENCAPSED_AND_WHITESPACE; } -#line 2117 "Zend/zend_language_scanner.c" +#line 2122 "Zend/zend_language_scanner.c" yy105: YYDEBUG(105, *YYCURSOR); yych = *++YYCURSOR; @@ -2128,14 +2133,14 @@ yy107: ++YYCURSOR; YYDEBUG(108, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2174 "Zend/zend_language_scanner.l" +#line 2185 "Zend/zend_language_scanner.l" { zendlval->value.lval = (long) '{'; yy_push_state(ST_IN_SCRIPTING TSRMLS_CC); yyless(1); return T_CURLY_OPEN; } -#line 2139 "Zend/zend_language_scanner.c" +#line 2144 "Zend/zend_language_scanner.c" yy109: YYDEBUG(109, *YYCURSOR); yyaccept = 0; @@ -2151,24 +2156,24 @@ yy109: yy111: YYDEBUG(111, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1874 "Zend/zend_language_scanner.l" +#line 1885 "Zend/zend_language_scanner.l" { zend_copy_value(zendlval, (yytext+1), (yyleng-1)); zendlval->type = IS_STRING; return T_VARIABLE; } -#line 2161 "Zend/zend_language_scanner.c" +#line 2166 "Zend/zend_language_scanner.c" yy112: YYDEBUG(112, *YYCURSOR); ++YYCURSOR; YYDEBUG(113, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1451 "Zend/zend_language_scanner.l" +#line 1461 "Zend/zend_language_scanner.l" { yy_push_state(ST_LOOKING_FOR_VARNAME TSRMLS_CC); return T_DOLLAR_OPEN_CURLY_BRACES; } -#line 2172 "Zend/zend_language_scanner.c" +#line 2177 "Zend/zend_language_scanner.c" yy114: YYDEBUG(114, *YYCURSOR); yych = *++YYCURSOR; @@ -2182,7 +2187,7 @@ yy116: ++YYCURSOR; YYDEBUG(117, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1866 "Zend/zend_language_scanner.l" +#line 1877 "Zend/zend_language_scanner.l" { yyless(yyleng - 1); yy_push_state(ST_VAR_OFFSET TSRMLS_CC); @@ -2190,7 +2195,7 @@ yy116: zendlval->type = IS_STRING; return T_VARIABLE; } -#line 2194 "Zend/zend_language_scanner.c" +#line 2199 "Zend/zend_language_scanner.c" yy118: YYDEBUG(118, *YYCURSOR); yych = *++YYCURSOR; @@ -2208,7 +2213,7 @@ yy119: ++YYCURSOR; YYDEBUG(120, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1856 "Zend/zend_language_scanner.l" +#line 1867 "Zend/zend_language_scanner.l" { yyless(yyleng - 3); yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC); @@ -2216,7 +2221,7 @@ yy119: zendlval->type = IS_STRING; return T_VARIABLE; } -#line 2220 "Zend/zend_language_scanner.c" +#line 2225 "Zend/zend_language_scanner.c" } /* *********************************** */ yyc_ST_IN_SCRIPTING: @@ -2288,32 +2293,32 @@ yyc_ST_IN_SCRIPTING: case 0x1C: case 0x1D: case 0x1E: - case 0x1F: goto yy183; + case 0x1F: goto yy184; case '\t': case '\n': case '\r': - case ' ': goto yy139; - case '!': goto yy152; - case '"': goto yy179; - case '#': goto yy175; - case '$': goto yy164; - case '%': goto yy158; - case '&': goto yy159; - case '\'': goto yy177; - case '(': goto yy146; + case ' ': goto yy140; + case '!': goto yy153; + case '"': goto yy180; + case '#': goto yy176; + case '$': goto yy165; + case '%': goto yy159; + case '&': goto yy160; + case '\'': goto yy178; + case '(': goto yy147; case ')': case ',': case ';': case '@': case '[': case ']': - case '~': goto yy165; - case '*': goto yy155; - case '+': goto yy151; - case '-': goto yy137; - case '.': goto yy157; - case '/': goto yy156; - case '0': goto yy171; + case '~': goto yy166; + case '*': goto yy156; + case '+': goto yy152; + case '-': goto yy138; + case '.': goto yy158; + case '/': goto yy157; + case '0': goto yy172; case '1': case '2': case '3': @@ -2322,16 +2327,16 @@ yyc_ST_IN_SCRIPTING: case '6': case '7': case '8': - case '9': goto yy173; - case ':': goto yy141; - case '<': goto yy153; - case '=': goto yy149; - case '>': goto yy154; - case '?': goto yy166; + case '9': goto yy174; + case ':': goto yy142; + case '<': goto yy154; + case '=': goto yy150; + case '>': goto yy155; + case '?': goto yy167; case 'A': - case 'a': goto yy132; + case 'a': goto yy133; case 'B': - case 'b': goto yy134; + case 'b': goto yy135; case 'C': case 'c': goto yy127; case 'D': @@ -2341,39 +2346,41 @@ yyc_ST_IN_SCRIPTING: case 'F': case 'f': goto yy126; case 'G': - case 'g': goto yy135; + case 'g': goto yy136; case 'I': - case 'i': goto yy130; + case 'i': goto yy131; case 'L': - case 'l': goto yy150; + case 'l': goto yy151; case 'N': - case 'n': goto yy144; + case 'n': goto yy145; case 'O': - case 'o': goto yy162; + case 'o': goto yy163; case 'P': - case 'p': goto yy136; + case 'p': goto yy137; case 'R': case 'r': goto yy128; case 'S': - case 's': goto yy133; + case 's': goto yy134; case 'T': - case 't': goto yy129; + case 't': goto yy130; case 'U': - case 'u': goto yy147; + case 'u': goto yy148; case 'V': - case 'v': goto yy145; + case 'v': goto yy146; case 'W': - case 'w': goto yy131; + case 'w': goto yy132; case 'X': - case 'x': goto yy163; - case '\\': goto yy142; - case '^': goto yy161; - case '_': goto yy148; - case '`': goto yy181; - case '{': goto yy167; - case '|': goto yy160; - case '}': goto yy169; - default: goto yy174; + case 'x': goto yy164; + case 'Y': + case 'y': goto yy129; + case '\\': goto yy143; + case '^': goto yy162; + case '_': goto yy149; + case '`': goto yy182; + case '{': goto yy168; + case '|': goto yy161; + case '}': goto yy170; + default: goto yy175; } yy123: YYDEBUG(123, *YYCURSOR); @@ -2381,49 +2388,49 @@ yy123: YYDEBUG(-1, yych); switch ((yych = *YYCURSOR)) { case 'C': - case 'c': goto yy726; + case 'c': goto yy735; case 'L': - case 'l': goto yy727; + case 'l': goto yy736; case 'M': - case 'm': goto yy728; + case 'm': goto yy737; case 'N': - case 'n': goto yy729; + case 'n': goto yy738; case 'V': - case 'v': goto yy730; + case 'v': goto yy739; case 'X': - case 'x': goto yy731; - default: goto yy186; + case 'x': goto yy740; + default: goto yy187; } yy124: YYDEBUG(124, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1897 "Zend/zend_language_scanner.l" +#line 1908 "Zend/zend_language_scanner.l" { zend_copy_value(zendlval, yytext, yyleng); zendlval->type = IS_STRING; return T_STRING; } -#line 2407 "Zend/zend_language_scanner.c" +#line 2414 "Zend/zend_language_scanner.c" yy125: YYDEBUG(125, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'O') { if (yych <= 'H') { - if (yych == 'E') goto yy708; - goto yy186; + if (yych == 'E') goto yy717; + goto yy187; } else { - if (yych <= 'I') goto yy709; - if (yych <= 'N') goto yy186; - goto yy710; + if (yych <= 'I') goto yy718; + if (yych <= 'N') goto yy187; + goto yy719; } } else { if (yych <= 'h') { - if (yych == 'e') goto yy708; - goto yy186; + if (yych == 'e') goto yy717; + goto yy187; } else { - if (yych <= 'i') goto yy709; - if (yych == 'o') goto yy710; - goto yy186; + if (yych <= 'i') goto yy718; + if (yych == 'o') goto yy719; + goto yy187; } } yy126: @@ -2431,21 +2438,21 @@ yy126: yych = *++YYCURSOR; if (yych <= 'U') { if (yych <= 'N') { - if (yych == 'I') goto yy687; - goto yy186; + if (yych == 'I') goto yy693; + goto yy187; } else { - if (yych <= 'O') goto yy688; - if (yych <= 'T') goto yy186; - goto yy689; + if (yych <= 'O') goto yy694; + if (yych <= 'T') goto yy187; + goto yy695; } } else { if (yych <= 'n') { - if (yych == 'i') goto yy687; - goto yy186; + if (yych == 'i') goto yy693; + goto yy187; } else { - if (yych <= 'o') goto yy688; - if (yych == 'u') goto yy689; - goto yy186; + if (yych <= 'o') goto yy694; + if (yych == 'u') goto yy695; + goto yy187; } } yy127: @@ -2453,196 +2460,202 @@ yy127: yych = *++YYCURSOR; if (yych <= 'O') { if (yych <= 'K') { - if (yych == 'A') goto yy652; - goto yy186; + if (yych == 'A') goto yy658; + goto yy187; } else { - if (yych <= 'L') goto yy653; - if (yych <= 'N') goto yy186; - goto yy654; + if (yych <= 'L') goto yy659; + if (yych <= 'N') goto yy187; + goto yy660; } } else { if (yych <= 'k') { - if (yych == 'a') goto yy652; - goto yy186; + if (yych == 'a') goto yy658; + goto yy187; } else { - if (yych <= 'l') goto yy653; - if (yych == 'o') goto yy654; - goto yy186; + if (yych <= 'l') goto yy659; + if (yych == 'o') goto yy660; + goto yy187; } } yy128: YYDEBUG(128, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy634; - if (yych == 'e') goto yy634; - goto yy186; + if (yych == 'E') goto yy640; + if (yych == 'e') goto yy640; + goto yy187; yy129: YYDEBUG(129, *YYCURSOR); yych = *++YYCURSOR; + if (yych == 'I') goto yy635; + if (yych == 'i') goto yy635; + goto yy187; +yy130: + YYDEBUG(130, *YYCURSOR); + yych = *++YYCURSOR; if (yych <= 'R') { - if (yych == 'H') goto yy622; - if (yych <= 'Q') goto yy186; - goto yy623; + if (yych == 'H') goto yy623; + if (yych <= 'Q') goto yy187; + goto yy624; } else { if (yych <= 'h') { - if (yych <= 'g') goto yy186; - goto yy622; + if (yych <= 'g') goto yy187; + goto yy623; } else { - if (yych == 'r') goto yy623; - goto yy186; + if (yych == 'r') goto yy624; + goto yy187; } } -yy130: - YYDEBUG(130, *YYCURSOR); +yy131: + YYDEBUG(131, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'S') { if (yych <= 'L') { - if (yych == 'F') goto yy569; - goto yy186; + if (yych == 'F') goto yy570; + goto yy187; } else { - if (yych <= 'M') goto yy571; - if (yych <= 'N') goto yy572; - if (yych <= 'R') goto yy186; - goto yy573; + if (yych <= 'M') goto yy572; + if (yych <= 'N') goto yy573; + if (yych <= 'R') goto yy187; + goto yy574; } } else { if (yych <= 'm') { - if (yych == 'f') goto yy569; - if (yych <= 'l') goto yy186; - goto yy571; + if (yych == 'f') goto yy570; + if (yych <= 'l') goto yy187; + goto yy572; } else { - if (yych <= 'n') goto yy572; - if (yych == 's') goto yy573; - goto yy186; + if (yych <= 'n') goto yy573; + if (yych == 's') goto yy574; + goto yy187; } } -yy131: - YYDEBUG(131, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'H') goto yy564; - if (yych == 'h') goto yy564; - goto yy186; yy132: YYDEBUG(132, *YYCURSOR); yych = *++YYCURSOR; + if (yych == 'H') goto yy565; + if (yych == 'h') goto yy565; + goto yy187; +yy133: + YYDEBUG(133, *YYCURSOR); + yych = *++YYCURSOR; if (yych <= 'S') { if (yych <= 'M') { - if (yych == 'B') goto yy546; - goto yy186; + if (yych == 'B') goto yy547; + goto yy187; } else { - if (yych <= 'N') goto yy547; - if (yych <= 'Q') goto yy186; - if (yych <= 'R') goto yy548; - goto yy549; + if (yych <= 'N') goto yy548; + if (yych <= 'Q') goto yy187; + if (yych <= 'R') goto yy549; + goto yy550; } } else { if (yych <= 'n') { - if (yych == 'b') goto yy546; - if (yych <= 'm') goto yy186; - goto yy547; + if (yych == 'b') goto yy547; + if (yych <= 'm') goto yy187; + goto yy548; } else { - if (yych <= 'q') goto yy186; - if (yych <= 'r') goto yy548; - if (yych <= 's') goto yy549; - goto yy186; + if (yych <= 'q') goto yy187; + if (yych <= 'r') goto yy549; + if (yych <= 's') goto yy550; + goto yy187; } } -yy133: - YYDEBUG(133, *YYCURSOR); +yy134: + YYDEBUG(134, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'W') { - if (yych == 'T') goto yy534; - if (yych <= 'V') goto yy186; - goto yy535; + if (yych == 'T') goto yy535; + if (yych <= 'V') goto yy187; + goto yy536; } else { if (yych <= 't') { - if (yych <= 's') goto yy186; - goto yy534; + if (yych <= 's') goto yy187; + goto yy535; } else { - if (yych == 'w') goto yy535; - goto yy186; + if (yych == 'w') goto yy536; + goto yy187; } } -yy134: - YYDEBUG(134, *YYCURSOR); +yy135: + YYDEBUG(135, *YYCURSOR); yyaccept = 0; yych = *(YYMARKER = ++YYCURSOR); if (yych <= ';') { if (yych <= '"') { - if (yych <= '!') goto yy186; - goto yy526; + if (yych <= '!') goto yy187; + goto yy527; } else { - if (yych == '\'') goto yy527; - goto yy186; + if (yych == '\'') goto yy528; + goto yy187; } } else { if (yych <= 'R') { - if (yych <= '<') goto yy525; - if (yych <= 'Q') goto yy186; - goto yy528; + if (yych <= '<') goto yy526; + if (yych <= 'Q') goto yy187; + goto yy529; } else { - if (yych == 'r') goto yy528; - goto yy186; + if (yych == 'r') goto yy529; + goto yy187; } } -yy135: - YYDEBUG(135, *YYCURSOR); +yy136: + YYDEBUG(136, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'O') { - if (yych == 'L') goto yy515; - if (yych <= 'N') goto yy186; - goto yy516; + if (yych == 'L') goto yy516; + if (yych <= 'N') goto yy187; + goto yy517; } else { if (yych <= 'l') { - if (yych <= 'k') goto yy186; - goto yy515; + if (yych <= 'k') goto yy187; + goto yy516; } else { - if (yych == 'o') goto yy516; - goto yy186; + if (yych == 'o') goto yy517; + goto yy187; } } -yy136: - YYDEBUG(136, *YYCURSOR); +yy137: + YYDEBUG(137, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'U') { - if (yych == 'R') goto yy491; - if (yych <= 'T') goto yy186; - goto yy492; + if (yych == 'R') goto yy492; + if (yych <= 'T') goto yy187; + goto yy493; } else { if (yych <= 'r') { - if (yych <= 'q') goto yy186; - goto yy491; + if (yych <= 'q') goto yy187; + goto yy492; } else { - if (yych == 'u') goto yy492; - goto yy186; + if (yych == 'u') goto yy493; + goto yy187; } } -yy137: - YYDEBUG(137, *YYCURSOR); +yy138: + YYDEBUG(138, *YYCURSOR); ++YYCURSOR; if ((yych = *YYCURSOR) <= '<') { - if (yych == '-') goto yy487; + if (yych == '-') goto yy488; } else { - if (yych <= '=') goto yy485; - if (yych <= '>') goto yy489; + if (yych <= '=') goto yy486; + if (yych <= '>') goto yy490; } -yy138: - YYDEBUG(138, *YYCURSOR); +yy139: + YYDEBUG(139, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1440 "Zend/zend_language_scanner.l" +#line 1450 "Zend/zend_language_scanner.l" { return yytext[0]; } -#line 2637 "Zend/zend_language_scanner.c" -yy139: - YYDEBUG(139, *YYCURSOR); - ++YYCURSOR; - yych = *YYCURSOR; - goto yy484; +#line 2650 "Zend/zend_language_scanner.c" yy140: YYDEBUG(140, *YYCURSOR); + ++YYCURSOR; + yych = *YYCURSOR; + goto yy485; +yy141: + YYDEBUG(141, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1171 "Zend/zend_language_scanner.l" +#line 1181 "Zend/zend_language_scanner.l" { zendlval->value.str.val = yytext; /* no copying - intentional */ zendlval->value.str.len = yyleng; @@ -2650,261 +2663,261 @@ yy140: HANDLE_NEWLINES(yytext, yyleng); return T_WHITESPACE; } -#line 2654 "Zend/zend_language_scanner.c" -yy141: - YYDEBUG(141, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == ':') goto yy481; - goto yy138; +#line 2667 "Zend/zend_language_scanner.c" yy142: YYDEBUG(142, *YYCURSOR); - ++YYCURSOR; + yych = *++YYCURSOR; + if (yych == ':') goto yy482; + goto yy139; +yy143: YYDEBUG(143, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(144, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1200 "Zend/zend_language_scanner.l" +#line 1210 "Zend/zend_language_scanner.l" { return T_NS_SEPARATOR; } -#line 2669 "Zend/zend_language_scanner.c" -yy144: - YYDEBUG(144, *YYCURSOR); +#line 2682 "Zend/zend_language_scanner.c" +yy145: + YYDEBUG(145, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'E') { - if (yych == 'A') goto yy469; - if (yych <= 'D') goto yy186; - goto yy470; + if (yych == 'A') goto yy470; + if (yych <= 'D') goto yy187; + goto yy471; } else { if (yych <= 'a') { - if (yych <= '`') goto yy186; - goto yy469; + if (yych <= '`') goto yy187; + goto yy470; } else { - if (yych == 'e') goto yy470; - goto yy186; + if (yych == 'e') goto yy471; + goto yy187; } } -yy145: - YYDEBUG(145, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'A') goto yy466; - if (yych == 'a') goto yy466; - goto yy186; yy146: YYDEBUG(146, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'A') goto yy467; + if (yych == 'a') goto yy467; + goto yy187; +yy147: + YYDEBUG(147, *YYCURSOR); yyaccept = 1; yych = *(YYMARKER = ++YYCURSOR); if (yych <= 'S') { if (yych <= 'D') { if (yych <= ' ') { - if (yych == '\t') goto yy391; - if (yych <= 0x1F) goto yy138; - goto yy391; + if (yych == '\t') goto yy392; + if (yych <= 0x1F) goto yy139; + goto yy392; } else { - if (yych <= '@') goto yy138; - if (yych == 'C') goto yy138; - goto yy391; + if (yych <= '@') goto yy139; + if (yych == 'C') goto yy139; + goto yy392; } } else { if (yych <= 'I') { - if (yych == 'F') goto yy391; - if (yych <= 'H') goto yy138; - goto yy391; + if (yych == 'F') goto yy392; + if (yych <= 'H') goto yy139; + goto yy392; } else { - if (yych == 'O') goto yy391; - if (yych <= 'Q') goto yy138; - goto yy391; + if (yych == 'O') goto yy392; + if (yych <= 'Q') goto yy139; + goto yy392; } } } else { if (yych <= 'f') { if (yych <= 'b') { - if (yych == 'U') goto yy391; - if (yych <= '`') goto yy138; - goto yy391; + if (yych == 'U') goto yy392; + if (yych <= '`') goto yy139; + goto yy392; } else { - if (yych == 'd') goto yy391; - if (yych <= 'e') goto yy138; - goto yy391; + if (yych == 'd') goto yy392; + if (yych <= 'e') goto yy139; + goto yy392; } } else { if (yych <= 'o') { - if (yych == 'i') goto yy391; - if (yych <= 'n') goto yy138; - goto yy391; + if (yych == 'i') goto yy392; + if (yych <= 'n') goto yy139; + goto yy392; } else { if (yych <= 's') { - if (yych <= 'q') goto yy138; - goto yy391; + if (yych <= 'q') goto yy139; + goto yy392; } else { - if (yych == 'u') goto yy391; - goto yy138; + if (yych == 'u') goto yy392; + goto yy139; } } } } -yy147: - YYDEBUG(147, *YYCURSOR); +yy148: + YYDEBUG(148, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'S') { - if (yych == 'N') goto yy382; - if (yych <= 'R') goto yy186; - goto yy383; + if (yych == 'N') goto yy383; + if (yych <= 'R') goto yy187; + goto yy384; } else { if (yych <= 'n') { - if (yych <= 'm') goto yy186; - goto yy382; + if (yych <= 'm') goto yy187; + goto yy383; } else { - if (yych == 's') goto yy383; - goto yy186; + if (yych == 's') goto yy384; + goto yy187; } } -yy148: - YYDEBUG(148, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == '_') goto yy300; - goto yy186; yy149: YYDEBUG(149, *YYCURSOR); yych = *++YYCURSOR; - if (yych <= '<') goto yy138; - if (yych <= '=') goto yy294; - if (yych <= '>') goto yy296; - goto yy138; + if (yych == '_') goto yy301; + goto yy187; yy150: YYDEBUG(150, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'I') goto yy290; - if (yych == 'i') goto yy290; - goto yy186; + if (yych <= '<') goto yy139; + if (yych <= '=') goto yy295; + if (yych <= '>') goto yy297; + goto yy139; yy151: YYDEBUG(151, *YYCURSOR); yych = *++YYCURSOR; - if (yych == '+') goto yy288; - if (yych == '=') goto yy286; - goto yy138; + if (yych == 'I') goto yy291; + if (yych == 'i') goto yy291; + goto yy187; yy152: YYDEBUG(152, *YYCURSOR); yych = *++YYCURSOR; - if (yych == '=') goto yy283; - goto yy138; + if (yych == '+') goto yy289; + if (yych == '=') goto yy287; + goto yy139; yy153: YYDEBUG(153, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == '=') goto yy284; + goto yy139; +yy154: + YYDEBUG(154, *YYCURSOR); yyaccept = 1; yych = *(YYMARKER = ++YYCURSOR); if (yych <= ';') { - if (yych == '/') goto yy255; - goto yy138; + if (yych == '/') goto yy256; + goto yy139; } else { - if (yych <= '<') goto yy253; - if (yych <= '=') goto yy256; - if (yych <= '>') goto yy258; - goto yy138; + if (yych <= '<') goto yy254; + if (yych <= '=') goto yy257; + if (yych <= '>') goto yy259; + goto yy139; } -yy154: - YYDEBUG(154, *YYCURSOR); - yych = *++YYCURSOR; - if (yych <= '<') goto yy138; - if (yych <= '=') goto yy249; - if (yych <= '>') goto yy247; - goto yy138; yy155: YYDEBUG(155, *YYCURSOR); yych = *++YYCURSOR; - if (yych == '=') goto yy245; - goto yy138; + if (yych <= '<') goto yy139; + if (yych <= '=') goto yy250; + if (yych <= '>') goto yy248; + goto yy139; yy156: YYDEBUG(156, *YYCURSOR); yych = *++YYCURSOR; - if (yych <= '.') { - if (yych == '*') goto yy237; - goto yy138; - } else { - if (yych <= '/') goto yy239; - if (yych == '=') goto yy240; - goto yy138; - } + if (yych == '=') goto yy246; + goto yy139; yy157: YYDEBUG(157, *YYCURSOR); yych = *++YYCURSOR; - if (yych <= '/') goto yy138; - if (yych <= '9') goto yy233; - if (yych == '=') goto yy235; - goto yy138; + if (yych <= '.') { + if (yych == '*') goto yy238; + goto yy139; + } else { + if (yych <= '/') goto yy240; + if (yych == '=') goto yy241; + goto yy139; + } yy158: YYDEBUG(158, *YYCURSOR); yych = *++YYCURSOR; - if (yych <= '<') goto yy138; - if (yych <= '=') goto yy229; - if (yych <= '>') goto yy227; - goto yy138; + if (yych <= '/') goto yy139; + if (yych <= '9') goto yy234; + if (yych == '=') goto yy236; + goto yy139; yy159: YYDEBUG(159, *YYCURSOR); yych = *++YYCURSOR; - if (yych == '&') goto yy223; - if (yych == '=') goto yy225; - goto yy138; + if (yych <= '<') goto yy139; + if (yych <= '=') goto yy230; + if (yych <= '>') goto yy228; + goto yy139; yy160: YYDEBUG(160, *YYCURSOR); yych = *++YYCURSOR; - if (yych == '=') goto yy221; - if (yych == '|') goto yy219; - goto yy138; + if (yych == '&') goto yy224; + if (yych == '=') goto yy226; + goto yy139; yy161: YYDEBUG(161, *YYCURSOR); yych = *++YYCURSOR; - if (yych == '=') goto yy217; - goto yy138; + if (yych == '=') goto yy222; + if (yych == '|') goto yy220; + goto yy139; yy162: YYDEBUG(162, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'R') goto yy215; - if (yych == 'r') goto yy215; - goto yy186; + if (yych == '=') goto yy218; + goto yy139; yy163: YYDEBUG(163, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'O') goto yy212; - if (yych == 'o') goto yy212; - goto yy186; + if (yych == 'R') goto yy216; + if (yych == 'r') goto yy216; + goto yy187; yy164: YYDEBUG(164, *YYCURSOR); yych = *++YYCURSOR; - if (yych <= '_') { - if (yych <= '@') goto yy138; - if (yych <= 'Z') goto yy209; - if (yych <= '^') goto yy138; - goto yy209; - } else { - if (yych <= '`') goto yy138; - if (yych <= 'z') goto yy209; - if (yych <= '~') goto yy138; - goto yy209; - } + if (yych == 'O') goto yy213; + if (yych == 'o') goto yy213; + goto yy187; yy165: YYDEBUG(165, *YYCURSOR); yych = *++YYCURSOR; - goto yy138; + if (yych <= '_') { + if (yych <= '@') goto yy139; + if (yych <= 'Z') goto yy210; + if (yych <= '^') goto yy139; + goto yy210; + } else { + if (yych <= '`') goto yy139; + if (yych <= 'z') goto yy210; + if (yych <= '~') goto yy139; + goto yy210; + } yy166: YYDEBUG(166, *YYCURSOR); yych = *++YYCURSOR; - if (yych == '>') goto yy205; - goto yy138; + goto yy139; yy167: YYDEBUG(167, *YYCURSOR); - ++YYCURSOR; + yych = *++YYCURSOR; + if (yych == '>') goto yy206; + goto yy139; +yy168: YYDEBUG(168, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(169, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1445 "Zend/zend_language_scanner.l" +#line 1455 "Zend/zend_language_scanner.l" { yy_push_state(ST_IN_SCRIPTING TSRMLS_CC); return '{'; } -#line 2902 "Zend/zend_language_scanner.c" -yy169: - YYDEBUG(169, *YYCURSOR); - ++YYCURSOR; +#line 2915 "Zend/zend_language_scanner.c" +yy170: YYDEBUG(170, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(171, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1457 "Zend/zend_language_scanner.l" +#line 1467 "Zend/zend_language_scanner.l" { RESET_DOC_COMMENT(); if (!zend_stack_is_empty(&SCNG(state_stack))) { @@ -2912,35 +2925,35 @@ yy169: } return '}'; } -#line 2916 "Zend/zend_language_scanner.c" -yy171: - YYDEBUG(171, *YYCURSOR); +#line 2929 "Zend/zend_language_scanner.c" +yy172: + YYDEBUG(172, *YYCURSOR); yyaccept = 2; yych = *(YYMARKER = ++YYCURSOR); if (yych <= 'E') { if (yych <= '9') { - if (yych == '.') goto yy187; - if (yych >= '0') goto yy190; + if (yych == '.') goto yy188; + if (yych >= '0') goto yy191; } else { - if (yych == 'B') goto yy198; - if (yych >= 'E') goto yy192; + if (yych == 'B') goto yy199; + if (yych >= 'E') goto yy193; } } else { if (yych <= 'b') { - if (yych == 'X') goto yy197; - if (yych >= 'b') goto yy198; + if (yych == 'X') goto yy198; + if (yych >= 'b') goto yy199; } else { if (yych <= 'e') { - if (yych >= 'e') goto yy192; + if (yych >= 'e') goto yy193; } else { - if (yych == 'x') goto yy197; + if (yych == 'x') goto yy198; } } } -yy172: - YYDEBUG(172, *YYCURSOR); +yy173: + YYDEBUG(173, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1507 "Zend/zend_language_scanner.l" +#line 1518 "Zend/zend_language_scanner.l" { if (yyleng < MAX_LENGTH_OF_LONG - 1) { /* Won't overflow */ zendlval->value.lval = strtol(yytext, NULL, 0); @@ -2961,35 +2974,35 @@ yy172: zendlval->type = IS_LONG; return T_LNUMBER; } -#line 2965 "Zend/zend_language_scanner.c" -yy173: - YYDEBUG(173, *YYCURSOR); +#line 2978 "Zend/zend_language_scanner.c" +yy174: + YYDEBUG(174, *YYCURSOR); yyaccept = 2; yych = *(YYMARKER = ++YYCURSOR); if (yych <= '9') { - if (yych == '.') goto yy187; - if (yych <= '/') goto yy172; - goto yy190; + if (yych == '.') goto yy188; + if (yych <= '/') goto yy173; + goto yy191; } else { if (yych <= 'E') { - if (yych <= 'D') goto yy172; - goto yy192; + if (yych <= 'D') goto yy173; + goto yy193; } else { - if (yych == 'e') goto yy192; - goto yy172; + if (yych == 'e') goto yy193; + goto yy173; } } -yy174: - YYDEBUG(174, *YYCURSOR); - yych = *++YYCURSOR; - goto yy186; yy175: YYDEBUG(175, *YYCURSOR); - ++YYCURSOR; + yych = *++YYCURSOR; + goto yy187; yy176: YYDEBUG(176, *YYCURSOR); + ++YYCURSOR; +yy177: + YYDEBUG(177, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1904 "Zend/zend_language_scanner.l" +#line 1915 "Zend/zend_language_scanner.l" { while (YYCURSOR < YYLIMIT) { switch (*YYCURSOR++) { @@ -3023,14 +3036,14 @@ yy176: return T_COMMENT; } -#line 3027 "Zend/zend_language_scanner.c" -yy177: - YYDEBUG(177, *YYCURSOR); - ++YYCURSOR; +#line 3040 "Zend/zend_language_scanner.c" yy178: YYDEBUG(178, *YYCURSOR); + ++YYCURSOR; +yy179: + YYDEBUG(179, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1995 "Zend/zend_language_scanner.l" +#line 2006 "Zend/zend_language_scanner.l" { register char *s, *t; char *end; @@ -3098,14 +3111,14 @@ yy178: } return T_CONSTANT_ENCAPSED_STRING; } -#line 3102 "Zend/zend_language_scanner.c" -yy179: - YYDEBUG(179, *YYCURSOR); - ++YYCURSOR; +#line 3115 "Zend/zend_language_scanner.c" yy180: YYDEBUG(180, *YYCURSOR); + ++YYCURSOR; +yy181: + YYDEBUG(181, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2064 "Zend/zend_language_scanner.l" +#line 2075 "Zend/zend_language_scanner.l" { int bprefix = (yytext[0] != '"') ? 1 : 0; @@ -3146,24 +3159,24 @@ yy180: BEGIN(ST_DOUBLE_QUOTES); return '"'; } -#line 3150 "Zend/zend_language_scanner.c" -yy181: - YYDEBUG(181, *YYCURSOR); - ++YYCURSOR; +#line 3163 "Zend/zend_language_scanner.c" +yy182: YYDEBUG(182, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(183, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2155 "Zend/zend_language_scanner.l" +#line 2165 "Zend/zend_language_scanner.l" { BEGIN(ST_BACKQUOTE); return '`'; } -#line 3161 "Zend/zend_language_scanner.c" -yy183: - YYDEBUG(183, *YYCURSOR); - ++YYCURSOR; +#line 3174 "Zend/zend_language_scanner.c" +yy184: YYDEBUG(184, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(185, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2413 "Zend/zend_language_scanner.l" +#line 2428 "Zend/zend_language_scanner.l" { if (YYCURSOR > YYLIMIT) { return 0; @@ -3172,132 +3185,132 @@ yy183: zend_error(E_COMPILE_WARNING,"Unexpected character in input: '%c' (ASCII=%d) state=%d", yytext[0], yytext[0], YYSTATE); goto restart; } -#line 3176 "Zend/zend_language_scanner.c" -yy185: - YYDEBUG(185, *YYCURSOR); +#line 3189 "Zend/zend_language_scanner.c" +yy186: + YYDEBUG(186, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; -yy186: - YYDEBUG(186, *YYCURSOR); +yy187: + YYDEBUG(187, *YYCURSOR); if (yybm[0+yych] & 4) { - goto yy185; + goto yy186; } goto yy124; -yy187: - YYDEBUG(187, *YYCURSOR); +yy188: + YYDEBUG(188, *YYCURSOR); yyaccept = 3; YYMARKER = ++YYCURSOR; YYFILL(3); yych = *YYCURSOR; - YYDEBUG(188, *YYCURSOR); + YYDEBUG(189, *YYCURSOR); if (yybm[0+yych] & 8) { - goto yy187; + goto yy188; } - if (yych == 'E') goto yy192; - if (yych == 'e') goto yy192; -yy189: - YYDEBUG(189, *YYCURSOR); + if (yych == 'E') goto yy193; + if (yych == 'e') goto yy193; +yy190: + YYDEBUG(190, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1572 "Zend/zend_language_scanner.l" +#line 1583 "Zend/zend_language_scanner.l" { zendlval->value.dval = zend_strtod(yytext, NULL); zendlval->type = IS_DOUBLE; return T_DNUMBER; } -#line 3209 "Zend/zend_language_scanner.c" -yy190: - YYDEBUG(190, *YYCURSOR); +#line 3222 "Zend/zend_language_scanner.c" +yy191: + YYDEBUG(191, *YYCURSOR); yyaccept = 2; YYMARKER = ++YYCURSOR; YYFILL(3); yych = *YYCURSOR; - YYDEBUG(191, *YYCURSOR); + YYDEBUG(192, *YYCURSOR); if (yych <= '9') { - if (yych == '.') goto yy187; - if (yych <= '/') goto yy172; - goto yy190; + if (yych == '.') goto yy188; + if (yych <= '/') goto yy173; + goto yy191; } else { if (yych <= 'E') { - if (yych <= 'D') goto yy172; + if (yych <= 'D') goto yy173; } else { - if (yych != 'e') goto yy172; + if (yych != 'e') goto yy173; } } -yy192: - YYDEBUG(192, *YYCURSOR); +yy193: + YYDEBUG(193, *YYCURSOR); yych = *++YYCURSOR; if (yych <= ',') { - if (yych == '+') goto yy194; + if (yych == '+') goto yy195; } else { - if (yych <= '-') goto yy194; - if (yych <= '/') goto yy193; - if (yych <= '9') goto yy195; + if (yych <= '-') goto yy195; + if (yych <= '/') goto yy194; + if (yych <= '9') goto yy196; } -yy193: - YYDEBUG(193, *YYCURSOR); +yy194: + YYDEBUG(194, *YYCURSOR); YYCURSOR = YYMARKER; if (yyaccept <= 2) { if (yyaccept <= 1) { if (yyaccept <= 0) { goto yy124; } else { - goto yy138; + goto yy139; } } else { - goto yy172; + goto yy173; } } else { if (yyaccept <= 4) { if (yyaccept <= 3) { - goto yy189; + goto yy190; } else { - goto yy238; + goto yy239; } } else { - goto yy254; + goto yy255; } } -yy194: - YYDEBUG(194, *YYCURSOR); - yych = *++YYCURSOR; - if (yych <= '/') goto yy193; - if (yych >= ':') goto yy193; yy195: YYDEBUG(195, *YYCURSOR); + yych = *++YYCURSOR; + if (yych <= '/') goto yy194; + if (yych >= ':') goto yy194; +yy196: + YYDEBUG(196, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(196, *YYCURSOR); - if (yych <= '/') goto yy189; - if (yych <= '9') goto yy195; - goto yy189; -yy197: YYDEBUG(197, *YYCURSOR); - yych = *++YYCURSOR; - if (yybm[0+yych] & 32) { - goto yy202; - } - goto yy193; + if (yych <= '/') goto yy190; + if (yych <= '9') goto yy196; + goto yy190; yy198: YYDEBUG(198, *YYCURSOR); yych = *++YYCURSOR; - if (yybm[0+yych] & 16) { - goto yy199; + if (yybm[0+yych] & 32) { + goto yy203; } - goto yy193; + goto yy194; yy199: YYDEBUG(199, *YYCURSOR); + yych = *++YYCURSOR; + if (yybm[0+yych] & 16) { + goto yy200; + } + goto yy194; +yy200: + YYDEBUG(200, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(200, *YYCURSOR); + YYDEBUG(201, *YYCURSOR); if (yybm[0+yych] & 16) { - goto yy199; + goto yy200; } - YYDEBUG(201, *YYCURSOR); + YYDEBUG(202, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1482 "Zend/zend_language_scanner.l" +#line 1493 "Zend/zend_language_scanner.l" { char *bin = yytext + 2; /* Skip "0b" */ int len = yyleng - 2; @@ -3322,19 +3335,19 @@ yy199: return T_DNUMBER; } } -#line 3326 "Zend/zend_language_scanner.c" -yy202: - YYDEBUG(202, *YYCURSOR); +#line 3339 "Zend/zend_language_scanner.c" +yy203: + YYDEBUG(203, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(203, *YYCURSOR); + YYDEBUG(204, *YYCURSOR); if (yybm[0+yych] & 32) { - goto yy202; + goto yy203; } - YYDEBUG(204, *YYCURSOR); + YYDEBUG(205, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1528 "Zend/zend_language_scanner.l" +#line 1539 "Zend/zend_language_scanner.l" { char *hex = yytext + 2; /* Skip "0x" */ int len = yyleng - 2; @@ -3359,16 +3372,16 @@ yy202: return T_DNUMBER; } } -#line 3363 "Zend/zend_language_scanner.c" -yy205: - YYDEBUG(205, *YYCURSOR); - ++YYCURSOR; - if ((yych = *YYCURSOR) == '\n') goto yy207; - if (yych == '\r') goto yy208; +#line 3376 "Zend/zend_language_scanner.c" yy206: YYDEBUG(206, *YYCURSOR); + ++YYCURSOR; + if ((yych = *YYCURSOR) == '\n') goto yy208; + if (yych == '\r') goto yy209; +yy207: + YYDEBUG(207, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1972 "Zend/zend_language_scanner.l" +#line 1983 "Zend/zend_language_scanner.l" { zendlval->value.str.val = yytext; /* no copying - intentional */ zendlval->value.str.len = yyleng; @@ -3376,137 +3389,137 @@ yy206: BEGIN(INITIAL); return T_CLOSE_TAG; /* implicit ';' at php-end tag */ } -#line 3380 "Zend/zend_language_scanner.c" -yy207: - YYDEBUG(207, *YYCURSOR); - yych = *++YYCURSOR; - goto yy206; +#line 3393 "Zend/zend_language_scanner.c" yy208: YYDEBUG(208, *YYCURSOR); yych = *++YYCURSOR; - if (yych == '\n') goto yy207; - goto yy206; + goto yy207; yy209: YYDEBUG(209, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == '\n') goto yy208; + goto yy207; +yy210: + YYDEBUG(210, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(210, *YYCURSOR); + YYDEBUG(211, *YYCURSOR); if (yych <= '^') { if (yych <= '9') { - if (yych >= '0') goto yy209; + if (yych >= '0') goto yy210; } else { - if (yych <= '@') goto yy211; - if (yych <= 'Z') goto yy209; + if (yych <= '@') goto yy212; + if (yych <= 'Z') goto yy210; } } else { if (yych <= '`') { - if (yych <= '_') goto yy209; + if (yych <= '_') goto yy210; } else { - if (yych <= 'z') goto yy209; - if (yych >= 0x7F) goto yy209; + if (yych <= 'z') goto yy210; + if (yych >= 0x7F) goto yy210; } } -yy211: - YYDEBUG(211, *YYCURSOR); +yy212: + YYDEBUG(212, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1874 "Zend/zend_language_scanner.l" +#line 1885 "Zend/zend_language_scanner.l" { zend_copy_value(zendlval, (yytext+1), (yyleng-1)); zendlval->type = IS_STRING; return T_VARIABLE; } -#line 3420 "Zend/zend_language_scanner.c" -yy212: - YYDEBUG(212, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'R') goto yy213; - if (yych != 'r') goto yy186; +#line 3433 "Zend/zend_language_scanner.c" yy213: YYDEBUG(213, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'R') goto yy214; + if (yych != 'r') goto yy187; +yy214: + YYDEBUG(214, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(214, *YYCURSOR); + YYDEBUG(215, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1428 "Zend/zend_language_scanner.l" +#line 1438 "Zend/zend_language_scanner.l" { return T_LOGICAL_XOR; } -#line 3438 "Zend/zend_language_scanner.c" -yy215: - YYDEBUG(215, *YYCURSOR); +#line 3451 "Zend/zend_language_scanner.c" +yy216: + YYDEBUG(216, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(216, *YYCURSOR); + YYDEBUG(217, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1420 "Zend/zend_language_scanner.l" +#line 1430 "Zend/zend_language_scanner.l" { return T_LOGICAL_OR; } -#line 3451 "Zend/zend_language_scanner.c" -yy217: - YYDEBUG(217, *YYCURSOR); - ++YYCURSOR; +#line 3464 "Zend/zend_language_scanner.c" +yy218: YYDEBUG(218, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(219, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1408 "Zend/zend_language_scanner.l" +#line 1418 "Zend/zend_language_scanner.l" { return T_XOR_EQUAL; } -#line 3461 "Zend/zend_language_scanner.c" -yy219: - YYDEBUG(219, *YYCURSOR); - ++YYCURSOR; +#line 3474 "Zend/zend_language_scanner.c" +yy220: YYDEBUG(220, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(221, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1412 "Zend/zend_language_scanner.l" +#line 1422 "Zend/zend_language_scanner.l" { return T_BOOLEAN_OR; } -#line 3471 "Zend/zend_language_scanner.c" -yy221: - YYDEBUG(221, *YYCURSOR); - ++YYCURSOR; +#line 3484 "Zend/zend_language_scanner.c" +yy222: YYDEBUG(222, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(223, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1404 "Zend/zend_language_scanner.l" +#line 1414 "Zend/zend_language_scanner.l" { return T_OR_EQUAL; } -#line 3481 "Zend/zend_language_scanner.c" -yy223: - YYDEBUG(223, *YYCURSOR); - ++YYCURSOR; +#line 3494 "Zend/zend_language_scanner.c" +yy224: YYDEBUG(224, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(225, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1416 "Zend/zend_language_scanner.l" +#line 1426 "Zend/zend_language_scanner.l" { return T_BOOLEAN_AND; } -#line 3491 "Zend/zend_language_scanner.c" -yy225: - YYDEBUG(225, *YYCURSOR); - ++YYCURSOR; +#line 3504 "Zend/zend_language_scanner.c" +yy226: YYDEBUG(226, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(227, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1400 "Zend/zend_language_scanner.l" +#line 1410 "Zend/zend_language_scanner.l" { return T_AND_EQUAL; } -#line 3501 "Zend/zend_language_scanner.c" -yy227: - YYDEBUG(227, *YYCURSOR); - ++YYCURSOR; - if ((yych = *YYCURSOR) == '\n') goto yy231; - if (yych == '\r') goto yy232; +#line 3514 "Zend/zend_language_scanner.c" yy228: YYDEBUG(228, *YYCURSOR); + ++YYCURSOR; + if ((yych = *YYCURSOR) == '\n') goto yy232; + if (yych == '\r') goto yy233; +yy229: + YYDEBUG(229, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1981 "Zend/zend_language_scanner.l" +#line 1992 "Zend/zend_language_scanner.l" { if (CG(asp_tags)) { BEGIN(INITIAL); @@ -3519,61 +3532,61 @@ yy228: return yytext[0]; } } -#line 3523 "Zend/zend_language_scanner.c" -yy229: - YYDEBUG(229, *YYCURSOR); - ++YYCURSOR; +#line 3536 "Zend/zend_language_scanner.c" +yy230: YYDEBUG(230, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(231, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1388 "Zend/zend_language_scanner.l" +#line 1398 "Zend/zend_language_scanner.l" { return T_MOD_EQUAL; } -#line 3533 "Zend/zend_language_scanner.c" -yy231: - YYDEBUG(231, *YYCURSOR); - yych = *++YYCURSOR; - goto yy228; +#line 3546 "Zend/zend_language_scanner.c" yy232: YYDEBUG(232, *YYCURSOR); yych = *++YYCURSOR; - if (yych == '\n') goto yy231; - goto yy228; + goto yy229; yy233: YYDEBUG(233, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == '\n') goto yy232; + goto yy229; +yy234: + YYDEBUG(234, *YYCURSOR); yyaccept = 3; YYMARKER = ++YYCURSOR; YYFILL(3); yych = *YYCURSOR; - YYDEBUG(234, *YYCURSOR); + YYDEBUG(235, *YYCURSOR); if (yych <= 'D') { - if (yych <= '/') goto yy189; - if (yych <= '9') goto yy233; - goto yy189; + if (yych <= '/') goto yy190; + if (yych <= '9') goto yy234; + goto yy190; } else { - if (yych <= 'E') goto yy192; - if (yych == 'e') goto yy192; - goto yy189; + if (yych <= 'E') goto yy193; + if (yych == 'e') goto yy193; + goto yy190; } -yy235: - YYDEBUG(235, *YYCURSOR); - ++YYCURSOR; +yy236: YYDEBUG(236, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(237, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1384 "Zend/zend_language_scanner.l" +#line 1394 "Zend/zend_language_scanner.l" { return T_CONCAT_EQUAL; } -#line 3568 "Zend/zend_language_scanner.c" -yy237: - YYDEBUG(237, *YYCURSOR); - yyaccept = 4; - yych = *(YYMARKER = ++YYCURSOR); - if (yych == '*') goto yy242; +#line 3581 "Zend/zend_language_scanner.c" yy238: YYDEBUG(238, *YYCURSOR); + yyaccept = 4; + yych = *(YYMARKER = ++YYCURSOR); + if (yych == '*') goto yy243; +yy239: + YYDEBUG(239, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1938 "Zend/zend_language_scanner.l" +#line 1949 "Zend/zend_language_scanner.l" { int doc_com; @@ -3607,316 +3620,313 @@ yy238: return T_COMMENT; } -#line 3611 "Zend/zend_language_scanner.c" -yy239: - YYDEBUG(239, *YYCURSOR); - yych = *++YYCURSOR; - goto yy176; +#line 3624 "Zend/zend_language_scanner.c" yy240: YYDEBUG(240, *YYCURSOR); - ++YYCURSOR; + yych = *++YYCURSOR; + goto yy177; +yy241: YYDEBUG(241, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(242, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1380 "Zend/zend_language_scanner.l" +#line 1390 "Zend/zend_language_scanner.l" { return T_DIV_EQUAL; } -#line 3625 "Zend/zend_language_scanner.c" -yy242: - YYDEBUG(242, *YYCURSOR); +#line 3638 "Zend/zend_language_scanner.c" +yy243: + YYDEBUG(243, *YYCURSOR); yych = *++YYCURSOR; if (yybm[0+yych] & 64) { - goto yy243; + goto yy244; } - goto yy193; -yy243: - YYDEBUG(243, *YYCURSOR); + goto yy194; +yy244: + YYDEBUG(244, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(244, *YYCURSOR); + YYDEBUG(245, *YYCURSOR); if (yybm[0+yych] & 64) { - goto yy243; + goto yy244; } - goto yy238; -yy245: - YYDEBUG(245, *YYCURSOR); - ++YYCURSOR; + goto yy239; +yy246: YYDEBUG(246, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(247, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1376 "Zend/zend_language_scanner.l" +#line 1386 "Zend/zend_language_scanner.l" { return T_MUL_EQUAL; } -#line 3652 "Zend/zend_language_scanner.c" -yy247: - YYDEBUG(247, *YYCURSOR); - ++YYCURSOR; - if ((yych = *YYCURSOR) == '=') goto yy251; +#line 3665 "Zend/zend_language_scanner.c" +yy248: YYDEBUG(248, *YYCURSOR); + ++YYCURSOR; + if ((yych = *YYCURSOR) == '=') goto yy252; + YYDEBUG(249, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1436 "Zend/zend_language_scanner.l" +#line 1446 "Zend/zend_language_scanner.l" { return T_SR; } -#line 3663 "Zend/zend_language_scanner.c" -yy249: - YYDEBUG(249, *YYCURSOR); - ++YYCURSOR; +#line 3676 "Zend/zend_language_scanner.c" +yy250: YYDEBUG(250, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(251, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1364 "Zend/zend_language_scanner.l" +#line 1374 "Zend/zend_language_scanner.l" { return T_IS_GREATER_OR_EQUAL; } -#line 3673 "Zend/zend_language_scanner.c" -yy251: - YYDEBUG(251, *YYCURSOR); - ++YYCURSOR; +#line 3686 "Zend/zend_language_scanner.c" +yy252: YYDEBUG(252, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(253, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1396 "Zend/zend_language_scanner.l" +#line 1406 "Zend/zend_language_scanner.l" { return T_SR_EQUAL; } -#line 3683 "Zend/zend_language_scanner.c" -yy253: - YYDEBUG(253, *YYCURSOR); - yyaccept = 5; - yych = *(YYMARKER = ++YYCURSOR); - if (yych <= ';') goto yy254; - if (yych <= '<') goto yy269; - if (yych <= '=') goto yy267; +#line 3696 "Zend/zend_language_scanner.c" yy254: YYDEBUG(254, *YYCURSOR); + yyaccept = 5; + yych = *(YYMARKER = ++YYCURSOR); + if (yych <= ';') goto yy255; + if (yych <= '<') goto yy270; + if (yych <= '=') goto yy268; +yy255: + YYDEBUG(255, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1432 "Zend/zend_language_scanner.l" +#line 1442 "Zend/zend_language_scanner.l" { return T_SL; } -#line 3698 "Zend/zend_language_scanner.c" -yy255: - YYDEBUG(255, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'S') goto yy260; - if (yych == 's') goto yy260; - goto yy193; +#line 3711 "Zend/zend_language_scanner.c" yy256: YYDEBUG(256, *YYCURSOR); - ++YYCURSOR; + yych = *++YYCURSOR; + if (yych == 'S') goto yy261; + if (yych == 's') goto yy261; + goto yy194; +yy257: YYDEBUG(257, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(258, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1360 "Zend/zend_language_scanner.l" +#line 1370 "Zend/zend_language_scanner.l" { return T_IS_SMALLER_OR_EQUAL; } -#line 3714 "Zend/zend_language_scanner.c" -yy258: - YYDEBUG(258, *YYCURSOR); - ++YYCURSOR; +#line 3727 "Zend/zend_language_scanner.c" yy259: YYDEBUG(259, *YYCURSOR); + ++YYCURSOR; +yy260: + YYDEBUG(260, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1356 "Zend/zend_language_scanner.l" +#line 1366 "Zend/zend_language_scanner.l" { return T_IS_NOT_EQUAL; } -#line 3725 "Zend/zend_language_scanner.c" -yy260: - YYDEBUG(260, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'C') goto yy261; - if (yych != 'c') goto yy193; +#line 3738 "Zend/zend_language_scanner.c" yy261: YYDEBUG(261, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'R') goto yy262; - if (yych != 'r') goto yy193; + if (yych == 'C') goto yy262; + if (yych != 'c') goto yy194; yy262: YYDEBUG(262, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'I') goto yy263; - if (yych != 'i') goto yy193; + if (yych == 'R') goto yy263; + if (yych != 'r') goto yy194; yy263: YYDEBUG(263, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'P') goto yy264; - if (yych != 'p') goto yy193; + if (yych == 'I') goto yy264; + if (yych != 'i') goto yy194; yy264: YYDEBUG(264, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy265; - if (yych != 't') goto yy193; + if (yych == 'P') goto yy265; + if (yych != 'p') goto yy194; yy265: YYDEBUG(265, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'T') goto yy266; + if (yych != 't') goto yy194; +yy266: + YYDEBUG(266, *YYCURSOR); ++YYCURSOR; YYFILL(3); yych = *YYCURSOR; - YYDEBUG(266, *YYCURSOR); + YYDEBUG(267, *YYCURSOR); if (yych <= '\r') { - if (yych <= 0x08) goto yy193; - if (yych <= '\n') goto yy265; - if (yych <= '\f') goto yy193; - goto yy265; + if (yych <= 0x08) goto yy194; + if (yych <= '\n') goto yy266; + if (yych <= '\f') goto yy194; + goto yy266; } else { if (yych <= ' ') { - if (yych <= 0x1F) goto yy193; - goto yy265; + if (yych <= 0x1F) goto yy194; + goto yy266; } else { - if (yych == '>') goto yy205; - goto yy193; + if (yych == '>') goto yy206; + goto yy194; } } -yy267: - YYDEBUG(267, *YYCURSOR); - ++YYCURSOR; +yy268: YYDEBUG(268, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(269, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1392 "Zend/zend_language_scanner.l" +#line 1402 "Zend/zend_language_scanner.l" { return T_SL_EQUAL; } -#line 3780 "Zend/zend_language_scanner.c" -yy269: - YYDEBUG(269, *YYCURSOR); +#line 3793 "Zend/zend_language_scanner.c" +yy270: + YYDEBUG(270, *YYCURSOR); ++YYCURSOR; YYFILL(2); yych = *YYCURSOR; - YYDEBUG(270, *YYCURSOR); + YYDEBUG(271, *YYCURSOR); if (yybm[0+yych] & 128) { - goto yy269; + goto yy270; } if (yych <= 'Z') { if (yych <= '&') { - if (yych == '"') goto yy274; - goto yy193; + if (yych == '"') goto yy275; + goto yy194; } else { - if (yych <= '\'') goto yy273; - if (yych <= '@') goto yy193; + if (yych <= '\'') goto yy274; + if (yych <= '@') goto yy194; } } else { if (yych <= '`') { - if (yych != '_') goto yy193; + if (yych != '_') goto yy194; } else { - if (yych <= 'z') goto yy271; - if (yych <= '~') goto yy193; + if (yych <= 'z') goto yy272; + if (yych <= '~') goto yy194; } } -yy271: - YYDEBUG(271, *YYCURSOR); +yy272: + YYDEBUG(272, *YYCURSOR); ++YYCURSOR; YYFILL(2); yych = *YYCURSOR; - YYDEBUG(272, *YYCURSOR); + YYDEBUG(273, *YYCURSOR); if (yych <= '@') { if (yych <= '\f') { - if (yych == '\n') goto yy278; - goto yy193; + if (yych == '\n') goto yy279; + goto yy194; } else { - if (yych <= '\r') goto yy280; - if (yych <= '/') goto yy193; - if (yych <= '9') goto yy271; - goto yy193; + if (yych <= '\r') goto yy281; + if (yych <= '/') goto yy194; + if (yych <= '9') goto yy272; + goto yy194; } } else { if (yych <= '_') { - if (yych <= 'Z') goto yy271; - if (yych <= '^') goto yy193; - goto yy271; + if (yych <= 'Z') goto yy272; + if (yych <= '^') goto yy194; + goto yy272; } else { - if (yych <= '`') goto yy193; - if (yych <= 'z') goto yy271; - if (yych <= '~') goto yy193; - goto yy271; + if (yych <= '`') goto yy194; + if (yych <= 'z') goto yy272; + if (yych <= '~') goto yy194; + goto yy272; } } -yy273: - YYDEBUG(273, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == '\'') goto yy193; - if (yych <= '/') goto yy282; - if (yych <= '9') goto yy193; - goto yy282; yy274: YYDEBUG(274, *YYCURSOR); yych = *++YYCURSOR; - if (yych == '"') goto yy193; - if (yych <= '/') goto yy276; - if (yych <= '9') goto yy193; - goto yy276; + if (yych == '\'') goto yy194; + if (yych <= '/') goto yy283; + if (yych <= '9') goto yy194; + goto yy283; yy275: YYDEBUG(275, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == '"') goto yy194; + if (yych <= '/') goto yy277; + if (yych <= '9') goto yy194; + goto yy277; +yy276: + YYDEBUG(276, *YYCURSOR); ++YYCURSOR; YYFILL(3); yych = *YYCURSOR; -yy276: - YYDEBUG(276, *YYCURSOR); +yy277: + YYDEBUG(277, *YYCURSOR); if (yych <= 'Z') { if (yych <= '/') { - if (yych != '"') goto yy193; + if (yych != '"') goto yy194; } else { - if (yych <= '9') goto yy275; - if (yych <= '@') goto yy193; - goto yy275; + if (yych <= '9') goto yy276; + if (yych <= '@') goto yy194; + goto yy276; } } else { if (yych <= '`') { - if (yych == '_') goto yy275; - goto yy193; + if (yych == '_') goto yy276; + goto yy194; } else { - if (yych <= 'z') goto yy275; - if (yych <= '~') goto yy193; - goto yy275; + if (yych <= 'z') goto yy276; + if (yych <= '~') goto yy194; + goto yy276; } } -yy277: - YYDEBUG(277, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == '\n') goto yy278; - if (yych == '\r') goto yy280; - goto yy193; yy278: YYDEBUG(278, *YYCURSOR); - ++YYCURSOR; + yych = *++YYCURSOR; + if (yych == '\n') goto yy279; + if (yych == '\r') goto yy281; + goto yy194; yy279: YYDEBUG(279, *YYCURSOR); + ++YYCURSOR; +yy280: + YYDEBUG(280, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2106 "Zend/zend_language_scanner.l" +#line 2117 "Zend/zend_language_scanner.l" { char *s; int bprefix = (yytext[0] != '<') ? 1 : 0; - - /* save old heredoc label */ - Z_STRVAL_P(zendlval) = CG(heredoc); - Z_STRLEN_P(zendlval) = CG(heredoc_len); + zend_heredoc_label *heredoc_label = emalloc(sizeof(zend_heredoc_label)); CG(zend_lineno)++; - CG(heredoc_len) = yyleng-bprefix-3-1-(yytext[yyleng-2]=='\r'?1:0); + heredoc_label->length = yyleng-bprefix-3-1-(yytext[yyleng-2]=='\r'?1:0); s = yytext+bprefix+3; while ((*s == ' ') || (*s == '\t')) { s++; - CG(heredoc_len)--; + heredoc_label->length--; } if (*s == '\'') { s++; - CG(heredoc_len) -= 2; + heredoc_label->length -= 2; BEGIN(ST_NOWDOC); } else { if (*s == '"') { s++; - CG(heredoc_len) -= 2; + heredoc_label->length -= 2; } BEGIN(ST_HEREDOC); } - CG(heredoc) = estrndup(s, CG(heredoc_len)); + heredoc_label->label = estrndup(s, heredoc_label->length); /* Check for ending label on the next line */ - if (CG(heredoc_len) < YYLIMIT - YYCURSOR && !memcmp(YYCURSOR, s, CG(heredoc_len))) { - YYCTYPE *end = YYCURSOR + CG(heredoc_len); + if (heredoc_label->length < YYLIMIT - YYCURSOR && !memcmp(YYCURSOR, s, heredoc_label->length)) { + YYCTYPE *end = YYCURSOR + heredoc_label->length; if (*end == ';') { end++; @@ -3927,257 +3937,259 @@ yy279: } } + zend_ptr_stack_push(&SCNG(heredoc_label_stack), (void *) heredoc_label); + return T_START_HEREDOC; } -#line 3933 "Zend/zend_language_scanner.c" -yy280: - YYDEBUG(280, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == '\n') goto yy278; - goto yy279; +#line 3945 "Zend/zend_language_scanner.c" yy281: YYDEBUG(281, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == '\n') goto yy279; + goto yy280; +yy282: + YYDEBUG(282, *YYCURSOR); ++YYCURSOR; YYFILL(3); yych = *YYCURSOR; -yy282: - YYDEBUG(282, *YYCURSOR); +yy283: + YYDEBUG(283, *YYCURSOR); if (yych <= 'Z') { if (yych <= '/') { - if (yych == '\'') goto yy277; - goto yy193; + if (yych == '\'') goto yy278; + goto yy194; } else { - if (yych <= '9') goto yy281; - if (yych <= '@') goto yy193; - goto yy281; + if (yych <= '9') goto yy282; + if (yych <= '@') goto yy194; + goto yy282; } } else { if (yych <= '`') { - if (yych == '_') goto yy281; - goto yy193; + if (yych == '_') goto yy282; + goto yy194; } else { - if (yych <= 'z') goto yy281; - if (yych <= '~') goto yy193; - goto yy281; + if (yych <= 'z') goto yy282; + if (yych <= '~') goto yy194; + goto yy282; } } -yy283: - YYDEBUG(283, *YYCURSOR); - yych = *++YYCURSOR; - if (yych != '=') goto yy259; +yy284: YYDEBUG(284, *YYCURSOR); - ++YYCURSOR; + yych = *++YYCURSOR; + if (yych != '=') goto yy260; YYDEBUG(285, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(286, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1348 "Zend/zend_language_scanner.l" +#line 1358 "Zend/zend_language_scanner.l" { return T_IS_NOT_IDENTICAL; } -#line 3977 "Zend/zend_language_scanner.c" -yy286: - YYDEBUG(286, *YYCURSOR); - ++YYCURSOR; +#line 3989 "Zend/zend_language_scanner.c" +yy287: YYDEBUG(287, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(288, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1368 "Zend/zend_language_scanner.l" +#line 1378 "Zend/zend_language_scanner.l" { return T_PLUS_EQUAL; } -#line 3987 "Zend/zend_language_scanner.c" -yy288: - YYDEBUG(288, *YYCURSOR); - ++YYCURSOR; +#line 3999 "Zend/zend_language_scanner.c" +yy289: YYDEBUG(289, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(290, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1336 "Zend/zend_language_scanner.l" +#line 1346 "Zend/zend_language_scanner.l" { return T_INC; } -#line 3997 "Zend/zend_language_scanner.c" -yy290: - YYDEBUG(290, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'S') goto yy291; - if (yych != 's') goto yy186; +#line 4009 "Zend/zend_language_scanner.c" yy291: YYDEBUG(291, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy292; - if (yych != 't') goto yy186; + if (yych == 'S') goto yy292; + if (yych != 's') goto yy187; yy292: YYDEBUG(292, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'T') goto yy293; + if (yych != 't') goto yy187; +yy293: + YYDEBUG(293, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(293, *YYCURSOR); + YYDEBUG(294, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1324 "Zend/zend_language_scanner.l" +#line 1334 "Zend/zend_language_scanner.l" { return T_LIST; } -#line 4020 "Zend/zend_language_scanner.c" -yy294: - YYDEBUG(294, *YYCURSOR); - ++YYCURSOR; - if ((yych = *YYCURSOR) == '=') goto yy298; +#line 4032 "Zend/zend_language_scanner.c" +yy295: YYDEBUG(295, *YYCURSOR); + ++YYCURSOR; + if ((yych = *YYCURSOR) == '=') goto yy299; + YYDEBUG(296, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1352 "Zend/zend_language_scanner.l" +#line 1362 "Zend/zend_language_scanner.l" { return T_IS_EQUAL; } -#line 4031 "Zend/zend_language_scanner.c" -yy296: - YYDEBUG(296, *YYCURSOR); - ++YYCURSOR; +#line 4043 "Zend/zend_language_scanner.c" +yy297: YYDEBUG(297, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(298, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1320 "Zend/zend_language_scanner.l" +#line 1330 "Zend/zend_language_scanner.l" { return T_DOUBLE_ARROW; } -#line 4041 "Zend/zend_language_scanner.c" -yy298: - YYDEBUG(298, *YYCURSOR); - ++YYCURSOR; +#line 4053 "Zend/zend_language_scanner.c" +yy299: YYDEBUG(299, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(300, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1344 "Zend/zend_language_scanner.l" +#line 1354 "Zend/zend_language_scanner.l" { return T_IS_IDENTICAL; } -#line 4051 "Zend/zend_language_scanner.c" -yy300: - YYDEBUG(300, *YYCURSOR); +#line 4063 "Zend/zend_language_scanner.c" +yy301: + YYDEBUG(301, *YYCURSOR); yych = *++YYCURSOR; YYDEBUG(-1, yych); switch (yych) { case 'C': - case 'c': goto yy302; + case 'c': goto yy303; case 'D': - case 'd': goto yy307; + case 'd': goto yy308; case 'F': - case 'f': goto yy304; + case 'f': goto yy305; case 'H': - case 'h': goto yy301; + case 'h': goto yy302; case 'L': - case 'l': goto yy306; + case 'l': goto yy307; case 'M': - case 'm': goto yy305; + case 'm': goto yy306; case 'N': - case 'n': goto yy308; + case 'n': goto yy309; case 'T': - case 't': goto yy303; - default: goto yy186; + case 't': goto yy304; + default: goto yy187; } -yy301: - YYDEBUG(301, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'A') goto yy369; - if (yych == 'a') goto yy369; - goto yy186; yy302: YYDEBUG(302, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy362; - if (yych == 'l') goto yy362; - goto yy186; + if (yych == 'A') goto yy370; + if (yych == 'a') goto yy370; + goto yy187; yy303: YYDEBUG(303, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'R') goto yy355; - if (yych == 'r') goto yy355; - goto yy186; + if (yych == 'L') goto yy363; + if (yych == 'l') goto yy363; + goto yy187; yy304: YYDEBUG(304, *YYCURSOR); yych = *++YYCURSOR; + if (yych == 'R') goto yy356; + if (yych == 'r') goto yy356; + goto yy187; +yy305: + YYDEBUG(305, *YYCURSOR); + yych = *++YYCURSOR; if (yych <= 'U') { - if (yych == 'I') goto yy339; - if (yych <= 'T') goto yy186; - goto yy340; + if (yych == 'I') goto yy340; + if (yych <= 'T') goto yy187; + goto yy341; } else { if (yych <= 'i') { - if (yych <= 'h') goto yy186; - goto yy339; + if (yych <= 'h') goto yy187; + goto yy340; } else { - if (yych == 'u') goto yy340; - goto yy186; + if (yych == 'u') goto yy341; + goto yy187; } } -yy305: - YYDEBUG(305, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'E') goto yy331; - if (yych == 'e') goto yy331; - goto yy186; yy306: YYDEBUG(306, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'I') goto yy325; - if (yych == 'i') goto yy325; - goto yy186; + if (yych == 'E') goto yy332; + if (yych == 'e') goto yy332; + goto yy187; yy307: YYDEBUG(307, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'I') goto yy320; - if (yych == 'i') goto yy320; - goto yy186; + if (yych == 'I') goto yy326; + if (yych == 'i') goto yy326; + goto yy187; yy308: YYDEBUG(308, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy309; - if (yych != 'a') goto yy186; + if (yych == 'I') goto yy321; + if (yych == 'i') goto yy321; + goto yy187; yy309: YYDEBUG(309, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'M') goto yy310; - if (yych != 'm') goto yy186; + if (yych == 'A') goto yy310; + if (yych != 'a') goto yy187; yy310: YYDEBUG(310, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy311; - if (yych != 'e') goto yy186; + if (yych == 'M') goto yy311; + if (yych != 'm') goto yy187; yy311: YYDEBUG(311, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'S') goto yy312; - if (yych != 's') goto yy186; + if (yych == 'E') goto yy312; + if (yych != 'e') goto yy187; yy312: YYDEBUG(312, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'P') goto yy313; - if (yych != 'p') goto yy186; + if (yych == 'S') goto yy313; + if (yych != 's') goto yy187; yy313: YYDEBUG(313, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy314; - if (yych != 'a') goto yy186; + if (yych == 'P') goto yy314; + if (yych != 'p') goto yy187; yy314: YYDEBUG(314, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy315; - if (yych != 'c') goto yy186; + if (yych == 'A') goto yy315; + if (yych != 'a') goto yy187; yy315: YYDEBUG(315, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy316; - if (yych != 'e') goto yy186; + if (yych == 'C') goto yy316; + if (yych != 'c') goto yy187; yy316: YYDEBUG(316, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '_') goto yy186; + if (yych == 'E') goto yy317; + if (yych != 'e') goto yy187; +yy317: YYDEBUG(317, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '_') goto yy186; + if (yych != '_') goto yy187; YYDEBUG(318, *YYCURSOR); + yych = *++YYCURSOR; + if (yych != '_') goto yy187; + YYDEBUG(319, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(319, *YYCURSOR); + YYDEBUG(320, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1707 "Zend/zend_language_scanner.l" +#line 1718 "Zend/zend_language_scanner.l" { if (CG(current_namespace)) { *zendlval = *CG(current_namespace); @@ -4187,27 +4199,27 @@ yy316: } return T_NS_C; } -#line 4191 "Zend/zend_language_scanner.c" -yy320: - YYDEBUG(320, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'R') goto yy321; - if (yych != 'r') goto yy186; +#line 4203 "Zend/zend_language_scanner.c" yy321: YYDEBUG(321, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '_') goto yy186; + if (yych == 'R') goto yy322; + if (yych != 'r') goto yy187; +yy322: YYDEBUG(322, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '_') goto yy186; + if (yych != '_') goto yy187; YYDEBUG(323, *YYCURSOR); + yych = *++YYCURSOR; + if (yych != '_') goto yy187; + YYDEBUG(324, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(324, *YYCURSOR); + YYDEBUG(325, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1680 "Zend/zend_language_scanner.l" +#line 1691 "Zend/zend_language_scanner.l" { char *filename = zend_get_compiled_filename(TSRMLS_C); const size_t filename_len = strlen(filename); @@ -4234,73 +4246,73 @@ yy321: zendlval->type = IS_STRING; return T_DIR; } -#line 4238 "Zend/zend_language_scanner.c" -yy325: - YYDEBUG(325, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'N') goto yy326; - if (yych != 'n') goto yy186; +#line 4250 "Zend/zend_language_scanner.c" yy326: YYDEBUG(326, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy327; - if (yych != 'e') goto yy186; + if (yych == 'N') goto yy327; + if (yych != 'n') goto yy187; yy327: YYDEBUG(327, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '_') goto yy186; + if (yych == 'E') goto yy328; + if (yych != 'e') goto yy187; +yy328: YYDEBUG(328, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '_') goto yy186; + if (yych != '_') goto yy187; YYDEBUG(329, *YYCURSOR); + yych = *++YYCURSOR; + if (yych != '_') goto yy187; + YYDEBUG(330, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(330, *YYCURSOR); + YYDEBUG(331, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1662 "Zend/zend_language_scanner.l" +#line 1673 "Zend/zend_language_scanner.l" { zendlval->value.lval = CG(zend_lineno); zendlval->type = IS_LONG; return T_LINE; } -#line 4269 "Zend/zend_language_scanner.c" -yy331: - YYDEBUG(331, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'T') goto yy332; - if (yych != 't') goto yy186; +#line 4281 "Zend/zend_language_scanner.c" yy332: YYDEBUG(332, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'H') goto yy333; - if (yych != 'h') goto yy186; + if (yych == 'T') goto yy333; + if (yych != 't') goto yy187; yy333: YYDEBUG(333, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'O') goto yy334; - if (yych != 'o') goto yy186; + if (yych == 'H') goto yy334; + if (yych != 'h') goto yy187; yy334: YYDEBUG(334, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'D') goto yy335; - if (yych != 'd') goto yy186; + if (yych == 'O') goto yy335; + if (yych != 'o') goto yy187; yy335: YYDEBUG(335, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '_') goto yy186; + if (yych == 'D') goto yy336; + if (yych != 'd') goto yy187; +yy336: YYDEBUG(336, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '_') goto yy186; + if (yych != '_') goto yy187; YYDEBUG(337, *YYCURSOR); + yych = *++YYCURSOR; + if (yych != '_') goto yy187; + YYDEBUG(338, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(338, *YYCURSOR); + YYDEBUG(339, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1641 "Zend/zend_language_scanner.l" +#line 1652 "Zend/zend_language_scanner.l" { const char *class_name = CG(active_class_entry) ? CG(active_class_entry)->name : NULL; const char *func_name = CG(active_op_array)? CG(active_op_array)->function_name : NULL; @@ -4321,58 +4333,58 @@ yy335: zendlval->type = IS_STRING; return T_METHOD_C; } -#line 4325 "Zend/zend_language_scanner.c" -yy339: - YYDEBUG(339, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'L') goto yy350; - if (yych == 'l') goto yy350; - goto yy186; +#line 4337 "Zend/zend_language_scanner.c" yy340: YYDEBUG(340, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'N') goto yy341; - if (yych != 'n') goto yy186; + if (yych == 'L') goto yy351; + if (yych == 'l') goto yy351; + goto yy187; yy341: YYDEBUG(341, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy342; - if (yych != 'c') goto yy186; + if (yych == 'N') goto yy342; + if (yych != 'n') goto yy187; yy342: YYDEBUG(342, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy343; - if (yych != 't') goto yy186; + if (yych == 'C') goto yy343; + if (yych != 'c') goto yy187; yy343: YYDEBUG(343, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'I') goto yy344; - if (yych != 'i') goto yy186; + if (yych == 'T') goto yy344; + if (yych != 't') goto yy187; yy344: YYDEBUG(344, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'O') goto yy345; - if (yych != 'o') goto yy186; + if (yych == 'I') goto yy345; + if (yych != 'i') goto yy187; yy345: YYDEBUG(345, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'N') goto yy346; - if (yych != 'n') goto yy186; + if (yych == 'O') goto yy346; + if (yych != 'o') goto yy187; yy346: YYDEBUG(346, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '_') goto yy186; + if (yych == 'N') goto yy347; + if (yych != 'n') goto yy187; +yy347: YYDEBUG(347, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '_') goto yy186; + if (yych != '_') goto yy187; YYDEBUG(348, *YYCURSOR); + yych = *++YYCURSOR; + if (yych != '_') goto yy187; + YYDEBUG(349, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(349, *YYCURSOR); + YYDEBUG(350, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1625 "Zend/zend_language_scanner.l" +#line 1636 "Zend/zend_language_scanner.l" { const char *func_name = NULL; @@ -4388,27 +4400,27 @@ yy346: zendlval->type = IS_STRING; return T_FUNC_C; } -#line 4392 "Zend/zend_language_scanner.c" -yy350: - YYDEBUG(350, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'E') goto yy351; - if (yych != 'e') goto yy186; +#line 4404 "Zend/zend_language_scanner.c" yy351: YYDEBUG(351, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '_') goto yy186; + if (yych == 'E') goto yy352; + if (yych != 'e') goto yy187; +yy352: YYDEBUG(352, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '_') goto yy186; + if (yych != '_') goto yy187; YYDEBUG(353, *YYCURSOR); + yych = *++YYCURSOR; + if (yych != '_') goto yy187; + YYDEBUG(354, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(354, *YYCURSOR); + YYDEBUG(355, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1668 "Zend/zend_language_scanner.l" +#line 1679 "Zend/zend_language_scanner.l" { char *filename = zend_get_compiled_filename(TSRMLS_C); @@ -4420,37 +4432,37 @@ yy351: zendlval->type = IS_STRING; return T_FILE; } -#line 4424 "Zend/zend_language_scanner.c" -yy355: - YYDEBUG(355, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'A') goto yy356; - if (yych != 'a') goto yy186; +#line 4436 "Zend/zend_language_scanner.c" yy356: YYDEBUG(356, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'I') goto yy357; - if (yych != 'i') goto yy186; + if (yych == 'A') goto yy357; + if (yych != 'a') goto yy187; yy357: YYDEBUG(357, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy358; - if (yych != 't') goto yy186; + if (yych == 'I') goto yy358; + if (yych != 'i') goto yy187; yy358: YYDEBUG(358, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '_') goto yy186; + if (yych == 'T') goto yy359; + if (yych != 't') goto yy187; +yy359: YYDEBUG(359, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '_') goto yy186; + if (yych != '_') goto yy187; YYDEBUG(360, *YYCURSOR); + yych = *++YYCURSOR; + if (yych != '_') goto yy187; + YYDEBUG(361, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(361, *YYCURSOR); + YYDEBUG(362, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1605 "Zend/zend_language_scanner.l" +#line 1616 "Zend/zend_language_scanner.l" { const char *trait_name = NULL; @@ -4470,37 +4482,37 @@ yy358: return T_TRAIT_C; } -#line 4474 "Zend/zend_language_scanner.c" -yy362: - YYDEBUG(362, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'A') goto yy363; - if (yych != 'a') goto yy186; +#line 4486 "Zend/zend_language_scanner.c" yy363: YYDEBUG(363, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'S') goto yy364; - if (yych != 's') goto yy186; + if (yych == 'A') goto yy364; + if (yych != 'a') goto yy187; yy364: YYDEBUG(364, *YYCURSOR); yych = *++YYCURSOR; if (yych == 'S') goto yy365; - if (yych != 's') goto yy186; + if (yych != 's') goto yy187; yy365: YYDEBUG(365, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '_') goto yy186; + if (yych == 'S') goto yy366; + if (yych != 's') goto yy187; +yy366: YYDEBUG(366, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '_') goto yy186; + if (yych != '_') goto yy187; YYDEBUG(367, *YYCURSOR); + yych = *++YYCURSOR; + if (yych != '_') goto yy187; + YYDEBUG(368, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(368, *YYCURSOR); + YYDEBUG(369, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1578 "Zend/zend_language_scanner.l" +#line 1589 "Zend/zend_language_scanner.l" { const char *class_name = NULL; @@ -4527,2648 +4539,2709 @@ yy365: } return T_CLASS_C; } -#line 4531 "Zend/zend_language_scanner.c" -yy369: - YYDEBUG(369, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'L') goto yy370; - if (yych != 'l') goto yy186; +#line 4543 "Zend/zend_language_scanner.c" yy370: YYDEBUG(370, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy371; - if (yych != 't') goto yy186; + if (yych == 'L') goto yy371; + if (yych != 'l') goto yy187; yy371: YYDEBUG(371, *YYCURSOR); yych = *++YYCURSOR; - if (yych != '_') goto yy186; + if (yych == 'T') goto yy372; + if (yych != 't') goto yy187; +yy372: YYDEBUG(372, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy373; - if (yych != 'c') goto yy186; -yy373: + if (yych != '_') goto yy187; YYDEBUG(373, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'O') goto yy374; - if (yych != 'o') goto yy186; + if (yych == 'C') goto yy374; + if (yych != 'c') goto yy187; yy374: YYDEBUG(374, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'M') goto yy375; - if (yych != 'm') goto yy186; + if (yych == 'O') goto yy375; + if (yych != 'o') goto yy187; yy375: YYDEBUG(375, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'P') goto yy376; - if (yych != 'p') goto yy186; + if (yych == 'M') goto yy376; + if (yych != 'm') goto yy187; yy376: YYDEBUG(376, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'I') goto yy377; - if (yych != 'i') goto yy186; + if (yych == 'P') goto yy377; + if (yych != 'p') goto yy187; yy377: YYDEBUG(377, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy378; - if (yych != 'l') goto yy186; + if (yych == 'I') goto yy378; + if (yych != 'i') goto yy187; yy378: YYDEBUG(378, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy379; - if (yych != 'e') goto yy186; + if (yych == 'L') goto yy379; + if (yych != 'l') goto yy187; yy379: YYDEBUG(379, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'R') goto yy380; - if (yych != 'r') goto yy186; + if (yych == 'E') goto yy380; + if (yych != 'e') goto yy187; yy380: YYDEBUG(380, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'R') goto yy381; + if (yych != 'r') goto yy187; +yy381: + YYDEBUG(381, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(381, *YYCURSOR); + YYDEBUG(382, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1288 "Zend/zend_language_scanner.l" +#line 1298 "Zend/zend_language_scanner.l" { return T_HALT_COMPILER; } -#line 4597 "Zend/zend_language_scanner.c" -yy382: - YYDEBUG(382, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'S') goto yy386; - if (yych == 's') goto yy386; - goto yy186; +#line 4609 "Zend/zend_language_scanner.c" yy383: YYDEBUG(383, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy384; - if (yych != 'e') goto yy186; + if (yych == 'S') goto yy387; + if (yych == 's') goto yy387; + goto yy187; yy384: YYDEBUG(384, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'E') goto yy385; + if (yych != 'e') goto yy187; +yy385: + YYDEBUG(385, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(385, *YYCURSOR); + YYDEBUG(386, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1268 "Zend/zend_language_scanner.l" +#line 1278 "Zend/zend_language_scanner.l" { return T_USE; } -#line 4621 "Zend/zend_language_scanner.c" -yy386: - YYDEBUG(386, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'E') goto yy387; - if (yych != 'e') goto yy186; +#line 4633 "Zend/zend_language_scanner.c" yy387: YYDEBUG(387, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy388; - if (yych != 't') goto yy186; + if (yych == 'E') goto yy388; + if (yych != 'e') goto yy187; yy388: YYDEBUG(388, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'T') goto yy389; + if (yych != 't') goto yy187; +yy389: + YYDEBUG(389, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(389, *YYCURSOR); + YYDEBUG(390, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1316 "Zend/zend_language_scanner.l" +#line 1326 "Zend/zend_language_scanner.l" { return T_UNSET; } -#line 4644 "Zend/zend_language_scanner.c" -yy390: - YYDEBUG(390, *YYCURSOR); +#line 4656 "Zend/zend_language_scanner.c" +yy391: + YYDEBUG(391, *YYCURSOR); ++YYCURSOR; YYFILL(7); yych = *YYCURSOR; -yy391: - YYDEBUG(391, *YYCURSOR); +yy392: + YYDEBUG(392, *YYCURSOR); if (yych <= 'S') { if (yych <= 'D') { if (yych <= ' ') { - if (yych == '\t') goto yy390; - if (yych <= 0x1F) goto yy193; - goto yy390; + if (yych == '\t') goto yy391; + if (yych <= 0x1F) goto yy194; + goto yy391; } else { if (yych <= 'A') { - if (yych <= '@') goto yy193; - goto yy395; + if (yych <= '@') goto yy194; + goto yy396; } else { - if (yych <= 'B') goto yy393; - if (yych <= 'C') goto yy193; - goto yy398; + if (yych <= 'B') goto yy394; + if (yych <= 'C') goto yy194; + goto yy399; } } } else { if (yych <= 'I') { - if (yych == 'F') goto yy399; - if (yych <= 'H') goto yy193; - goto yy400; + if (yych == 'F') goto yy400; + if (yych <= 'H') goto yy194; + goto yy401; } else { if (yych <= 'O') { - if (yych <= 'N') goto yy193; - goto yy394; + if (yych <= 'N') goto yy194; + goto yy395; } else { - if (yych <= 'Q') goto yy193; - if (yych <= 'R') goto yy397; - goto yy396; + if (yych <= 'Q') goto yy194; + if (yych <= 'R') goto yy398; + goto yy397; } } } } else { if (yych <= 'f') { if (yych <= 'a') { - if (yych == 'U') goto yy392; - if (yych <= '`') goto yy193; - goto yy395; + if (yych == 'U') goto yy393; + if (yych <= '`') goto yy194; + goto yy396; } else { if (yych <= 'c') { - if (yych <= 'b') goto yy393; - goto yy193; + if (yych <= 'b') goto yy394; + goto yy194; } else { - if (yych <= 'd') goto yy398; - if (yych <= 'e') goto yy193; - goto yy399; + if (yych <= 'd') goto yy399; + if (yych <= 'e') goto yy194; + goto yy400; } } } else { if (yych <= 'q') { if (yych <= 'i') { - if (yych <= 'h') goto yy193; - goto yy400; + if (yych <= 'h') goto yy194; + goto yy401; } else { - if (yych == 'o') goto yy394; - goto yy193; + if (yych == 'o') goto yy395; + goto yy194; } } else { if (yych <= 's') { - if (yych <= 'r') goto yy397; - goto yy396; + if (yych <= 'r') goto yy398; + goto yy397; } else { - if (yych != 'u') goto yy193; + if (yych != 'u') goto yy194; } } } } -yy392: - YYDEBUG(392, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'N') goto yy459; - if (yych == 'n') goto yy459; - goto yy193; yy393: YYDEBUG(393, *YYCURSOR); yych = *++YYCURSOR; + if (yych == 'N') goto yy460; + if (yych == 'n') goto yy460; + goto yy194; +yy394: + YYDEBUG(394, *YYCURSOR); + yych = *++YYCURSOR; if (yych <= 'O') { - if (yych == 'I') goto yy446; - if (yych <= 'N') goto yy193; - goto yy447; + if (yych == 'I') goto yy447; + if (yych <= 'N') goto yy194; + goto yy448; } else { if (yych <= 'i') { - if (yych <= 'h') goto yy193; - goto yy446; + if (yych <= 'h') goto yy194; + goto yy447; } else { - if (yych == 'o') goto yy447; - goto yy193; + if (yych == 'o') goto yy448; + goto yy194; } } -yy394: - YYDEBUG(394, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'B') goto yy438; - if (yych == 'b') goto yy438; - goto yy193; yy395: YYDEBUG(395, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'R') goto yy431; - if (yych == 'r') goto yy431; - goto yy193; + if (yych == 'B') goto yy439; + if (yych == 'b') goto yy439; + goto yy194; yy396: YYDEBUG(396, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy423; - if (yych == 't') goto yy423; - goto yy193; + if (yych == 'R') goto yy432; + if (yych == 'r') goto yy432; + goto yy194; yy397: YYDEBUG(397, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy421; - if (yych == 'e') goto yy421; - goto yy193; + if (yych == 'T') goto yy424; + if (yych == 't') goto yy424; + goto yy194; yy398: YYDEBUG(398, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'O') goto yy417; - if (yych == 'o') goto yy417; - goto yy193; + if (yych == 'E') goto yy422; + if (yych == 'e') goto yy422; + goto yy194; yy399: YYDEBUG(399, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy410; - if (yych == 'l') goto yy410; - goto yy193; + if (yych == 'O') goto yy418; + if (yych == 'o') goto yy418; + goto yy194; yy400: YYDEBUG(400, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'N') goto yy401; - if (yych != 'n') goto yy193; + if (yych == 'L') goto yy411; + if (yych == 'l') goto yy411; + goto yy194; yy401: YYDEBUG(401, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy402; - if (yych != 't') goto yy193; + if (yych == 'N') goto yy402; + if (yych != 'n') goto yy194; yy402: YYDEBUG(402, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy403; - if (yych != 'e') goto yy405; + if (yych == 'T') goto yy403; + if (yych != 't') goto yy194; yy403: YYDEBUG(403, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'G') goto yy408; - if (yych == 'g') goto yy408; - goto yy193; + if (yych == 'E') goto yy404; + if (yych != 'e') goto yy406; yy404: YYDEBUG(404, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'G') goto yy409; + if (yych == 'g') goto yy409; + goto yy194; +yy405: + YYDEBUG(405, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; -yy405: - YYDEBUG(405, *YYCURSOR); +yy406: + YYDEBUG(406, *YYCURSOR); if (yych <= 0x1F) { - if (yych == '\t') goto yy404; - goto yy193; + if (yych == '\t') goto yy405; + goto yy194; } else { - if (yych <= ' ') goto yy404; - if (yych != ')') goto yy193; + if (yych <= ' ') goto yy405; + if (yych != ')') goto yy194; } - YYDEBUG(406, *YYCURSOR); - ++YYCURSOR; YYDEBUG(407, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(408, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1216 "Zend/zend_language_scanner.l" +#line 1226 "Zend/zend_language_scanner.l" { return T_INT_CAST; } -#line 4820 "Zend/zend_language_scanner.c" -yy408: - YYDEBUG(408, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'E') goto yy409; - if (yych != 'e') goto yy193; +#line 4832 "Zend/zend_language_scanner.c" yy409: YYDEBUG(409, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'R') goto yy404; - if (yych == 'r') goto yy404; - goto yy193; + if (yych == 'E') goto yy410; + if (yych != 'e') goto yy194; yy410: YYDEBUG(410, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'O') goto yy411; - if (yych != 'o') goto yy193; + if (yych == 'R') goto yy405; + if (yych == 'r') goto yy405; + goto yy194; yy411: YYDEBUG(411, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy412; - if (yych != 'a') goto yy193; + if (yych == 'O') goto yy412; + if (yych != 'o') goto yy194; yy412: YYDEBUG(412, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy413; - if (yych != 't') goto yy193; + if (yych == 'A') goto yy413; + if (yych != 'a') goto yy194; yy413: YYDEBUG(413, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'T') goto yy414; + if (yych != 't') goto yy194; +yy414: + YYDEBUG(414, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(414, *YYCURSOR); + YYDEBUG(415, *YYCURSOR); if (yych <= 0x1F) { - if (yych == '\t') goto yy413; - goto yy193; + if (yych == '\t') goto yy414; + goto yy194; } else { - if (yych <= ' ') goto yy413; - if (yych != ')') goto yy193; + if (yych <= ' ') goto yy414; + if (yych != ')') goto yy194; } - YYDEBUG(415, *YYCURSOR); - ++YYCURSOR; YYDEBUG(416, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(417, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1220 "Zend/zend_language_scanner.l" +#line 1230 "Zend/zend_language_scanner.l" { return T_DOUBLE_CAST; } -#line 4868 "Zend/zend_language_scanner.c" -yy417: - YYDEBUG(417, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'U') goto yy418; - if (yych != 'u') goto yy193; +#line 4880 "Zend/zend_language_scanner.c" yy418: YYDEBUG(418, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'B') goto yy419; - if (yych != 'b') goto yy193; + if (yych == 'U') goto yy419; + if (yych != 'u') goto yy194; yy419: YYDEBUG(419, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy420; - if (yych != 'l') goto yy193; + if (yych == 'B') goto yy420; + if (yych != 'b') goto yy194; yy420: YYDEBUG(420, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy413; - if (yych == 'e') goto yy413; - goto yy193; + if (yych == 'L') goto yy421; + if (yych != 'l') goto yy194; yy421: YYDEBUG(421, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy422; - if (yych != 'a') goto yy193; + if (yych == 'E') goto yy414; + if (yych == 'e') goto yy414; + goto yy194; yy422: YYDEBUG(422, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy413; - if (yych == 'l') goto yy413; - goto yy193; + if (yych == 'A') goto yy423; + if (yych != 'a') goto yy194; yy423: YYDEBUG(423, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'R') goto yy424; - if (yych != 'r') goto yy193; + if (yych == 'L') goto yy414; + if (yych == 'l') goto yy414; + goto yy194; yy424: YYDEBUG(424, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'I') goto yy425; - if (yych != 'i') goto yy193; + if (yych == 'R') goto yy425; + if (yych != 'r') goto yy194; yy425: YYDEBUG(425, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'N') goto yy426; - if (yych != 'n') goto yy193; + if (yych == 'I') goto yy426; + if (yych != 'i') goto yy194; yy426: YYDEBUG(426, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'G') goto yy427; - if (yych != 'g') goto yy193; + if (yych == 'N') goto yy427; + if (yych != 'n') goto yy194; yy427: YYDEBUG(427, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'G') goto yy428; + if (yych != 'g') goto yy194; +yy428: + YYDEBUG(428, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(428, *YYCURSOR); + YYDEBUG(429, *YYCURSOR); if (yych <= 0x1F) { - if (yych == '\t') goto yy427; - goto yy193; + if (yych == '\t') goto yy428; + goto yy194; } else { - if (yych <= ' ') goto yy427; - if (yych != ')') goto yy193; + if (yych <= ' ') goto yy428; + if (yych != ')') goto yy194; } - YYDEBUG(429, *YYCURSOR); - ++YYCURSOR; YYDEBUG(430, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(431, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1224 "Zend/zend_language_scanner.l" +#line 1234 "Zend/zend_language_scanner.l" { return T_STRING_CAST; } -#line 4942 "Zend/zend_language_scanner.c" -yy431: - YYDEBUG(431, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'R') goto yy432; - if (yych != 'r') goto yy193; +#line 4954 "Zend/zend_language_scanner.c" yy432: YYDEBUG(432, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy433; - if (yych != 'a') goto yy193; + if (yych == 'R') goto yy433; + if (yych != 'r') goto yy194; yy433: YYDEBUG(433, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'Y') goto yy434; - if (yych != 'y') goto yy193; + if (yych == 'A') goto yy434; + if (yych != 'a') goto yy194; yy434: YYDEBUG(434, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'Y') goto yy435; + if (yych != 'y') goto yy194; +yy435: + YYDEBUG(435, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(435, *YYCURSOR); + YYDEBUG(436, *YYCURSOR); if (yych <= 0x1F) { - if (yych == '\t') goto yy434; - goto yy193; + if (yych == '\t') goto yy435; + goto yy194; } else { - if (yych <= ' ') goto yy434; - if (yych != ')') goto yy193; + if (yych <= ' ') goto yy435; + if (yych != ')') goto yy194; } - YYDEBUG(436, *YYCURSOR); - ++YYCURSOR; YYDEBUG(437, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(438, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1228 "Zend/zend_language_scanner.l" +#line 1238 "Zend/zend_language_scanner.l" { return T_ARRAY_CAST; } -#line 4979 "Zend/zend_language_scanner.c" -yy438: - YYDEBUG(438, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'J') goto yy439; - if (yych != 'j') goto yy193; +#line 4991 "Zend/zend_language_scanner.c" yy439: YYDEBUG(439, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy440; - if (yych != 'e') goto yy193; + if (yych == 'J') goto yy440; + if (yych != 'j') goto yy194; yy440: YYDEBUG(440, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy441; - if (yych != 'c') goto yy193; + if (yych == 'E') goto yy441; + if (yych != 'e') goto yy194; yy441: YYDEBUG(441, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy442; - if (yych != 't') goto yy193; + if (yych == 'C') goto yy442; + if (yych != 'c') goto yy194; yy442: YYDEBUG(442, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'T') goto yy443; + if (yych != 't') goto yy194; +yy443: + YYDEBUG(443, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(443, *YYCURSOR); + YYDEBUG(444, *YYCURSOR); if (yych <= 0x1F) { - if (yych == '\t') goto yy442; - goto yy193; + if (yych == '\t') goto yy443; + goto yy194; } else { - if (yych <= ' ') goto yy442; - if (yych != ')') goto yy193; + if (yych <= ' ') goto yy443; + if (yych != ')') goto yy194; } - YYDEBUG(444, *YYCURSOR); - ++YYCURSOR; YYDEBUG(445, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(446, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1232 "Zend/zend_language_scanner.l" +#line 1242 "Zend/zend_language_scanner.l" { return T_OBJECT_CAST; } -#line 5021 "Zend/zend_language_scanner.c" -yy446: - YYDEBUG(446, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'N') goto yy456; - if (yych == 'n') goto yy456; - goto yy193; +#line 5033 "Zend/zend_language_scanner.c" yy447: YYDEBUG(447, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'O') goto yy448; - if (yych != 'o') goto yy193; + if (yych == 'N') goto yy457; + if (yych == 'n') goto yy457; + goto yy194; yy448: YYDEBUG(448, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy449; - if (yych != 'l') goto yy193; + if (yych == 'O') goto yy449; + if (yych != 'o') goto yy194; yy449: YYDEBUG(449, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy454; - if (yych == 'e') goto yy454; - goto yy451; + if (yych == 'L') goto yy450; + if (yych != 'l') goto yy194; yy450: YYDEBUG(450, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'E') goto yy455; + if (yych == 'e') goto yy455; + goto yy452; +yy451: + YYDEBUG(451, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; -yy451: - YYDEBUG(451, *YYCURSOR); +yy452: + YYDEBUG(452, *YYCURSOR); if (yych <= 0x1F) { - if (yych == '\t') goto yy450; - goto yy193; + if (yych == '\t') goto yy451; + goto yy194; } else { - if (yych <= ' ') goto yy450; - if (yych != ')') goto yy193; + if (yych <= ' ') goto yy451; + if (yych != ')') goto yy194; } - YYDEBUG(452, *YYCURSOR); - ++YYCURSOR; YYDEBUG(453, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(454, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1236 "Zend/zend_language_scanner.l" +#line 1246 "Zend/zend_language_scanner.l" { return T_BOOL_CAST; } -#line 5066 "Zend/zend_language_scanner.c" -yy454: - YYDEBUG(454, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'A') goto yy455; - if (yych != 'a') goto yy193; +#line 5078 "Zend/zend_language_scanner.c" yy455: YYDEBUG(455, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'N') goto yy450; - if (yych == 'n') goto yy450; - goto yy193; + if (yych == 'A') goto yy456; + if (yych != 'a') goto yy194; yy456: YYDEBUG(456, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy457; - if (yych != 'a') goto yy193; + if (yych == 'N') goto yy451; + if (yych == 'n') goto yy451; + goto yy194; yy457: YYDEBUG(457, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'R') goto yy458; - if (yych != 'r') goto yy193; + if (yych == 'A') goto yy458; + if (yych != 'a') goto yy194; yy458: YYDEBUG(458, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'Y') goto yy427; - if (yych == 'y') goto yy427; - goto yy193; + if (yych == 'R') goto yy459; + if (yych != 'r') goto yy194; yy459: YYDEBUG(459, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'S') goto yy460; - if (yych != 's') goto yy193; + if (yych == 'Y') goto yy428; + if (yych == 'y') goto yy428; + goto yy194; yy460: YYDEBUG(460, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy461; - if (yych != 'e') goto yy193; + if (yych == 'S') goto yy461; + if (yych != 's') goto yy194; yy461: YYDEBUG(461, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy462; - if (yych != 't') goto yy193; + if (yych == 'E') goto yy462; + if (yych != 'e') goto yy194; yy462: YYDEBUG(462, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'T') goto yy463; + if (yych != 't') goto yy194; +yy463: + YYDEBUG(463, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(463, *YYCURSOR); + YYDEBUG(464, *YYCURSOR); if (yych <= 0x1F) { - if (yych == '\t') goto yy462; - goto yy193; + if (yych == '\t') goto yy463; + goto yy194; } else { - if (yych <= ' ') goto yy462; - if (yych != ')') goto yy193; + if (yych <= ' ') goto yy463; + if (yych != ')') goto yy194; } - YYDEBUG(464, *YYCURSOR); - ++YYCURSOR; YYDEBUG(465, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(466, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1240 "Zend/zend_language_scanner.l" +#line 1250 "Zend/zend_language_scanner.l" { return T_UNSET_CAST; } -#line 5130 "Zend/zend_language_scanner.c" -yy466: - YYDEBUG(466, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'R') goto yy467; - if (yych != 'r') goto yy186; +#line 5142 "Zend/zend_language_scanner.c" yy467: YYDEBUG(467, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'R') goto yy468; + if (yych != 'r') goto yy187; +yy468: + YYDEBUG(468, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(468, *YYCURSOR); + YYDEBUG(469, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1212 "Zend/zend_language_scanner.l" +#line 1222 "Zend/zend_language_scanner.l" { return T_VAR; } -#line 5148 "Zend/zend_language_scanner.c" -yy469: - YYDEBUG(469, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'M') goto yy473; - if (yych == 'm') goto yy473; - goto yy186; +#line 5160 "Zend/zend_language_scanner.c" yy470: YYDEBUG(470, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'W') goto yy471; - if (yych != 'w') goto yy186; + if (yych == 'M') goto yy474; + if (yych == 'm') goto yy474; + goto yy187; yy471: YYDEBUG(471, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'W') goto yy472; + if (yych != 'w') goto yy187; +yy472: + YYDEBUG(472, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(472, *YYCURSOR); + YYDEBUG(473, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1204 "Zend/zend_language_scanner.l" +#line 1214 "Zend/zend_language_scanner.l" { return T_NEW; } -#line 5172 "Zend/zend_language_scanner.c" -yy473: - YYDEBUG(473, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'E') goto yy474; - if (yych != 'e') goto yy186; +#line 5184 "Zend/zend_language_scanner.c" yy474: YYDEBUG(474, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'S') goto yy475; - if (yych != 's') goto yy186; + if (yych == 'E') goto yy475; + if (yych != 'e') goto yy187; yy475: YYDEBUG(475, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'P') goto yy476; - if (yych != 'p') goto yy186; + if (yych == 'S') goto yy476; + if (yych != 's') goto yy187; yy476: YYDEBUG(476, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy477; - if (yych != 'a') goto yy186; + if (yych == 'P') goto yy477; + if (yych != 'p') goto yy187; yy477: YYDEBUG(477, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy478; - if (yych != 'c') goto yy186; + if (yych == 'A') goto yy478; + if (yych != 'a') goto yy187; yy478: YYDEBUG(478, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy479; - if (yych != 'e') goto yy186; + if (yych == 'C') goto yy479; + if (yych != 'c') goto yy187; yy479: YYDEBUG(479, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'E') goto yy480; + if (yych != 'e') goto yy187; +yy480: + YYDEBUG(480, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(480, *YYCURSOR); + YYDEBUG(481, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1264 "Zend/zend_language_scanner.l" +#line 1274 "Zend/zend_language_scanner.l" { return T_NAMESPACE; } -#line 5215 "Zend/zend_language_scanner.c" -yy481: - YYDEBUG(481, *YYCURSOR); - ++YYCURSOR; +#line 5227 "Zend/zend_language_scanner.c" +yy482: YYDEBUG(482, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(483, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1196 "Zend/zend_language_scanner.l" +#line 1206 "Zend/zend_language_scanner.l" { return T_PAAMAYIM_NEKUDOTAYIM; } -#line 5225 "Zend/zend_language_scanner.c" -yy483: - YYDEBUG(483, *YYCURSOR); +#line 5237 "Zend/zend_language_scanner.c" +yy484: + YYDEBUG(484, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; -yy484: - YYDEBUG(484, *YYCURSOR); +yy485: + YYDEBUG(485, *YYCURSOR); if (yych <= '\f') { - if (yych <= 0x08) goto yy140; - if (yych <= '\n') goto yy483; - goto yy140; + if (yych <= 0x08) goto yy141; + if (yych <= '\n') goto yy484; + goto yy141; } else { - if (yych <= '\r') goto yy483; - if (yych == ' ') goto yy483; - goto yy140; + if (yych <= '\r') goto yy484; + if (yych == ' ') goto yy484; + goto yy141; } -yy485: - YYDEBUG(485, *YYCURSOR); - ++YYCURSOR; +yy486: YYDEBUG(486, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(487, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1372 "Zend/zend_language_scanner.l" +#line 1382 "Zend/zend_language_scanner.l" { return T_MINUS_EQUAL; } -#line 5251 "Zend/zend_language_scanner.c" -yy487: - YYDEBUG(487, *YYCURSOR); - ++YYCURSOR; +#line 5263 "Zend/zend_language_scanner.c" +yy488: YYDEBUG(488, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(489, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1340 "Zend/zend_language_scanner.l" +#line 1350 "Zend/zend_language_scanner.l" { return T_DEC; } -#line 5261 "Zend/zend_language_scanner.c" -yy489: - YYDEBUG(489, *YYCURSOR); - ++YYCURSOR; +#line 5273 "Zend/zend_language_scanner.c" +yy490: YYDEBUG(490, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(491, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1166 "Zend/zend_language_scanner.l" +#line 1176 "Zend/zend_language_scanner.l" { yy_push_state(ST_LOOKING_FOR_PROPERTY TSRMLS_CC); return T_OBJECT_OPERATOR; } -#line 5272 "Zend/zend_language_scanner.c" -yy491: - YYDEBUG(491, *YYCURSOR); +#line 5284 "Zend/zend_language_scanner.c" +yy492: + YYDEBUG(492, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'O') { - if (yych == 'I') goto yy498; - if (yych <= 'N') goto yy186; - goto yy499; + if (yych == 'I') goto yy499; + if (yych <= 'N') goto yy187; + goto yy500; } else { if (yych <= 'i') { - if (yych <= 'h') goto yy186; - goto yy498; + if (yych <= 'h') goto yy187; + goto yy499; } else { - if (yych == 'o') goto yy499; - goto yy186; + if (yych == 'o') goto yy500; + goto yy187; } } -yy492: - YYDEBUG(492, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'B') goto yy493; - if (yych != 'b') goto yy186; yy493: YYDEBUG(493, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy494; - if (yych != 'l') goto yy186; + if (yych == 'B') goto yy494; + if (yych != 'b') goto yy187; yy494: YYDEBUG(494, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'I') goto yy495; - if (yych != 'i') goto yy186; + if (yych == 'L') goto yy495; + if (yych != 'l') goto yy187; yy495: YYDEBUG(495, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy496; - if (yych != 'c') goto yy186; + if (yych == 'I') goto yy496; + if (yych != 'i') goto yy187; yy496: YYDEBUG(496, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'C') goto yy497; + if (yych != 'c') goto yy187; +yy497: + YYDEBUG(497, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(497, *YYCURSOR); + YYDEBUG(498, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1312 "Zend/zend_language_scanner.l" +#line 1322 "Zend/zend_language_scanner.l" { return T_PUBLIC; } -#line 5321 "Zend/zend_language_scanner.c" -yy498: - YYDEBUG(498, *YYCURSOR); +#line 5333 "Zend/zend_language_scanner.c" +yy499: + YYDEBUG(499, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'V') { - if (yych == 'N') goto yy507; - if (yych <= 'U') goto yy186; - goto yy508; + if (yych == 'N') goto yy508; + if (yych <= 'U') goto yy187; + goto yy509; } else { if (yych <= 'n') { - if (yych <= 'm') goto yy186; - goto yy507; + if (yych <= 'm') goto yy187; + goto yy508; } else { - if (yych == 'v') goto yy508; - goto yy186; + if (yych == 'v') goto yy509; + goto yy187; } } -yy499: - YYDEBUG(499, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'T') goto yy500; - if (yych != 't') goto yy186; yy500: YYDEBUG(500, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy501; - if (yych != 'e') goto yy186; + if (yych == 'T') goto yy501; + if (yych != 't') goto yy187; yy501: YYDEBUG(501, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy502; - if (yych != 'c') goto yy186; + if (yych == 'E') goto yy502; + if (yych != 'e') goto yy187; yy502: YYDEBUG(502, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy503; - if (yych != 't') goto yy186; + if (yych == 'C') goto yy503; + if (yych != 'c') goto yy187; yy503: YYDEBUG(503, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy504; - if (yych != 'e') goto yy186; + if (yych == 'T') goto yy504; + if (yych != 't') goto yy187; yy504: YYDEBUG(504, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'D') goto yy505; - if (yych != 'd') goto yy186; + if (yych == 'E') goto yy505; + if (yych != 'e') goto yy187; yy505: YYDEBUG(505, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'D') goto yy506; + if (yych != 'd') goto yy187; +yy506: + YYDEBUG(506, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(506, *YYCURSOR); + YYDEBUG(507, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1308 "Zend/zend_language_scanner.l" +#line 1318 "Zend/zend_language_scanner.l" { return T_PROTECTED; } -#line 5380 "Zend/zend_language_scanner.c" -yy507: - YYDEBUG(507, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'T') goto yy513; - if (yych == 't') goto yy513; - goto yy186; +#line 5392 "Zend/zend_language_scanner.c" yy508: YYDEBUG(508, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy509; - if (yych != 'a') goto yy186; + if (yych == 'T') goto yy514; + if (yych == 't') goto yy514; + goto yy187; yy509: YYDEBUG(509, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy510; - if (yych != 't') goto yy186; + if (yych == 'A') goto yy510; + if (yych != 'a') goto yy187; yy510: YYDEBUG(510, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy511; - if (yych != 'e') goto yy186; + if (yych == 'T') goto yy511; + if (yych != 't') goto yy187; yy511: YYDEBUG(511, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'E') goto yy512; + if (yych != 'e') goto yy187; +yy512: + YYDEBUG(512, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(512, *YYCURSOR); + YYDEBUG(513, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1304 "Zend/zend_language_scanner.l" +#line 1314 "Zend/zend_language_scanner.l" { return T_PRIVATE; } -#line 5414 "Zend/zend_language_scanner.c" -yy513: - YYDEBUG(513, *YYCURSOR); +#line 5426 "Zend/zend_language_scanner.c" +yy514: + YYDEBUG(514, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(514, *YYCURSOR); + YYDEBUG(515, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1142 "Zend/zend_language_scanner.l" +#line 1152 "Zend/zend_language_scanner.l" { return T_PRINT; } -#line 5427 "Zend/zend_language_scanner.c" -yy515: - YYDEBUG(515, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'O') goto yy520; - if (yych == 'o') goto yy520; - goto yy186; +#line 5439 "Zend/zend_language_scanner.c" yy516: YYDEBUG(516, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy517; - if (yych != 't') goto yy186; + if (yych == 'O') goto yy521; + if (yych == 'o') goto yy521; + goto yy187; yy517: YYDEBUG(517, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'O') goto yy518; - if (yych != 'o') goto yy186; + if (yych == 'T') goto yy518; + if (yych != 't') goto yy187; yy518: YYDEBUG(518, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'O') goto yy519; + if (yych != 'o') goto yy187; +yy519: + YYDEBUG(519, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(519, *YYCURSOR); + YYDEBUG(520, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1134 "Zend/zend_language_scanner.l" +#line 1144 "Zend/zend_language_scanner.l" { return T_GOTO; } -#line 5456 "Zend/zend_language_scanner.c" -yy520: - YYDEBUG(520, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'B') goto yy521; - if (yych != 'b') goto yy186; +#line 5468 "Zend/zend_language_scanner.c" yy521: YYDEBUG(521, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy522; - if (yych != 'a') goto yy186; + if (yych == 'B') goto yy522; + if (yych != 'b') goto yy187; yy522: YYDEBUG(522, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy523; - if (yych != 'l') goto yy186; + if (yych == 'A') goto yy523; + if (yych != 'a') goto yy187; yy523: YYDEBUG(523, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'L') goto yy524; + if (yych != 'l') goto yy187; +yy524: + YYDEBUG(524, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(524, *YYCURSOR); + YYDEBUG(525, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1276 "Zend/zend_language_scanner.l" +#line 1286 "Zend/zend_language_scanner.l" { return T_GLOBAL; } -#line 5484 "Zend/zend_language_scanner.c" -yy525: - YYDEBUG(525, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == '<') goto yy533; - goto yy193; +#line 5496 "Zend/zend_language_scanner.c" yy526: YYDEBUG(526, *YYCURSOR); yych = *++YYCURSOR; - goto yy180; + if (yych == '<') goto yy534; + goto yy194; yy527: YYDEBUG(527, *YYCURSOR); yych = *++YYCURSOR; - goto yy178; + goto yy181; yy528: YYDEBUG(528, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy529; - if (yych != 'e') goto yy186; + goto yy179; yy529: YYDEBUG(529, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy530; - if (yych != 'a') goto yy186; + if (yych == 'E') goto yy530; + if (yych != 'e') goto yy187; yy530: YYDEBUG(530, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'K') goto yy531; - if (yych != 'k') goto yy186; + if (yych == 'A') goto yy531; + if (yych != 'a') goto yy187; yy531: YYDEBUG(531, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'K') goto yy532; + if (yych != 'k') goto yy187; +yy532: + YYDEBUG(532, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(532, *YYCURSOR); + YYDEBUG(533, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1126 "Zend/zend_language_scanner.l" +#line 1136 "Zend/zend_language_scanner.l" { return T_BREAK; } -#line 5525 "Zend/zend_language_scanner.c" -yy533: - YYDEBUG(533, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == '<') goto yy269; - goto yy193; +#line 5537 "Zend/zend_language_scanner.c" yy534: YYDEBUG(534, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy541; - if (yych == 'a') goto yy541; - goto yy186; + if (yych == '<') goto yy270; + goto yy194; yy535: YYDEBUG(535, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'I') goto yy536; - if (yych != 'i') goto yy186; + if (yych == 'A') goto yy542; + if (yych == 'a') goto yy542; + goto yy187; yy536: YYDEBUG(536, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy537; - if (yych != 't') goto yy186; + if (yych == 'I') goto yy537; + if (yych != 'i') goto yy187; yy537: YYDEBUG(537, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy538; - if (yych != 'c') goto yy186; + if (yych == 'T') goto yy538; + if (yych != 't') goto yy187; yy538: YYDEBUG(538, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'H') goto yy539; - if (yych != 'h') goto yy186; + if (yych == 'C') goto yy539; + if (yych != 'c') goto yy187; yy539: YYDEBUG(539, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'H') goto yy540; + if (yych != 'h') goto yy187; +yy540: + YYDEBUG(540, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(540, *YYCURSOR); + YYDEBUG(541, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1110 "Zend/zend_language_scanner.l" +#line 1120 "Zend/zend_language_scanner.l" { return T_SWITCH; } -#line 5569 "Zend/zend_language_scanner.c" -yy541: - YYDEBUG(541, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'T') goto yy542; - if (yych != 't') goto yy186; +#line 5581 "Zend/zend_language_scanner.c" yy542: YYDEBUG(542, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'I') goto yy543; - if (yych != 'i') goto yy186; + if (yych == 'T') goto yy543; + if (yych != 't') goto yy187; yy543: YYDEBUG(543, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy544; - if (yych != 'c') goto yy186; + if (yych == 'I') goto yy544; + if (yych != 'i') goto yy187; yy544: YYDEBUG(544, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'C') goto yy545; + if (yych != 'c') goto yy187; +yy545: + YYDEBUG(545, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(545, *YYCURSOR); + YYDEBUG(546, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1292 "Zend/zend_language_scanner.l" +#line 1302 "Zend/zend_language_scanner.l" { return T_STATIC; } -#line 5597 "Zend/zend_language_scanner.c" -yy546: - YYDEBUG(546, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'S') goto yy557; - if (yych == 's') goto yy557; - goto yy186; +#line 5609 "Zend/zend_language_scanner.c" yy547: YYDEBUG(547, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'D') goto yy555; - if (yych == 'd') goto yy555; - goto yy186; + if (yych == 'S') goto yy558; + if (yych == 's') goto yy558; + goto yy187; yy548: YYDEBUG(548, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'R') goto yy551; - if (yych == 'r') goto yy551; - goto yy186; + if (yych == 'D') goto yy556; + if (yych == 'd') goto yy556; + goto yy187; yy549: YYDEBUG(549, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'R') goto yy552; + if (yych == 'r') goto yy552; + goto yy187; +yy550: + YYDEBUG(550, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(550, *YYCURSOR); + YYDEBUG(551, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1106 "Zend/zend_language_scanner.l" +#line 1116 "Zend/zend_language_scanner.l" { return T_AS; } -#line 5628 "Zend/zend_language_scanner.c" -yy551: - YYDEBUG(551, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'A') goto yy552; - if (yych != 'a') goto yy186; +#line 5640 "Zend/zend_language_scanner.c" yy552: YYDEBUG(552, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'Y') goto yy553; - if (yych != 'y') goto yy186; + if (yych == 'A') goto yy553; + if (yych != 'a') goto yy187; yy553: YYDEBUG(553, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'Y') goto yy554; + if (yych != 'y') goto yy187; +yy554: + YYDEBUG(554, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(554, *YYCURSOR); + YYDEBUG(555, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1328 "Zend/zend_language_scanner.l" +#line 1338 "Zend/zend_language_scanner.l" { return T_ARRAY; } -#line 5651 "Zend/zend_language_scanner.c" -yy555: - YYDEBUG(555, *YYCURSOR); +#line 5663 "Zend/zend_language_scanner.c" +yy556: + YYDEBUG(556, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(556, *YYCURSOR); + YYDEBUG(557, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1424 "Zend/zend_language_scanner.l" +#line 1434 "Zend/zend_language_scanner.l" { return T_LOGICAL_AND; } -#line 5664 "Zend/zend_language_scanner.c" -yy557: - YYDEBUG(557, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'T') goto yy558; - if (yych != 't') goto yy186; +#line 5676 "Zend/zend_language_scanner.c" yy558: YYDEBUG(558, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'R') goto yy559; - if (yych != 'r') goto yy186; + if (yych == 'T') goto yy559; + if (yych != 't') goto yy187; yy559: YYDEBUG(559, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy560; - if (yych != 'a') goto yy186; + if (yych == 'R') goto yy560; + if (yych != 'r') goto yy187; yy560: YYDEBUG(560, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy561; - if (yych != 'c') goto yy186; + if (yych == 'A') goto yy561; + if (yych != 'a') goto yy187; yy561: YYDEBUG(561, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy562; - if (yych != 't') goto yy186; + if (yych == 'C') goto yy562; + if (yych != 'c') goto yy187; yy562: YYDEBUG(562, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'T') goto yy563; + if (yych != 't') goto yy187; +yy563: + YYDEBUG(563, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(563, *YYCURSOR); + YYDEBUG(564, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1296 "Zend/zend_language_scanner.l" +#line 1306 "Zend/zend_language_scanner.l" { return T_ABSTRACT; } -#line 5702 "Zend/zend_language_scanner.c" -yy564: - YYDEBUG(564, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'I') goto yy565; - if (yych != 'i') goto yy186; +#line 5714 "Zend/zend_language_scanner.c" yy565: YYDEBUG(565, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy566; - if (yych != 'l') goto yy186; + if (yych == 'I') goto yy566; + if (yych != 'i') goto yy187; yy566: YYDEBUG(566, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy567; - if (yych != 'e') goto yy186; + if (yych == 'L') goto yy567; + if (yych != 'l') goto yy187; yy567: YYDEBUG(567, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'E') goto yy568; + if (yych != 'e') goto yy187; +yy568: + YYDEBUG(568, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(568, *YYCURSOR); + YYDEBUG(569, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1066 "Zend/zend_language_scanner.l" +#line 1076 "Zend/zend_language_scanner.l" { return T_WHILE; } -#line 5730 "Zend/zend_language_scanner.c" -yy569: - YYDEBUG(569, *YYCURSOR); +#line 5742 "Zend/zend_language_scanner.c" +yy570: + YYDEBUG(570, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(570, *YYCURSOR); + YYDEBUG(571, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1050 "Zend/zend_language_scanner.l" +#line 1060 "Zend/zend_language_scanner.l" { return T_IF; } -#line 5743 "Zend/zend_language_scanner.c" -yy571: - YYDEBUG(571, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'P') goto yy613; - if (yych == 'p') goto yy613; - goto yy186; +#line 5755 "Zend/zend_language_scanner.c" yy572: YYDEBUG(572, *YYCURSOR); yych = *++YYCURSOR; + if (yych == 'P') goto yy614; + if (yych == 'p') goto yy614; + goto yy187; +yy573: + YYDEBUG(573, *YYCURSOR); + yych = *++YYCURSOR; if (yych <= 'T') { if (yych <= 'C') { - if (yych <= 'B') goto yy186; - goto yy580; + if (yych <= 'B') goto yy187; + goto yy581; } else { - if (yych <= 'R') goto yy186; - if (yych <= 'S') goto yy578; - goto yy579; + if (yych <= 'R') goto yy187; + if (yych <= 'S') goto yy579; + goto yy580; } } else { if (yych <= 'r') { - if (yych == 'c') goto yy580; - goto yy186; + if (yych == 'c') goto yy581; + goto yy187; } else { - if (yych <= 's') goto yy578; - if (yych <= 't') goto yy579; - goto yy186; + if (yych <= 's') goto yy579; + if (yych <= 't') goto yy580; + goto yy187; } } -yy573: - YYDEBUG(573, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'S') goto yy574; - if (yych != 's') goto yy186; yy574: YYDEBUG(574, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy575; - if (yych != 'e') goto yy186; + if (yych == 'S') goto yy575; + if (yych != 's') goto yy187; yy575: YYDEBUG(575, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy576; - if (yych != 't') goto yy186; + if (yych == 'E') goto yy576; + if (yych != 'e') goto yy187; yy576: YYDEBUG(576, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'T') goto yy577; + if (yych != 't') goto yy187; +yy577: + YYDEBUG(577, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(577, *YYCURSOR); + YYDEBUG(578, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1280 "Zend/zend_language_scanner.l" +#line 1290 "Zend/zend_language_scanner.l" { return T_ISSET; } -#line 5799 "Zend/zend_language_scanner.c" -yy578: - YYDEBUG(578, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'T') goto yy599; - if (yych == 't') goto yy599; - goto yy186; +#line 5811 "Zend/zend_language_scanner.c" yy579: YYDEBUG(579, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy592; - if (yych == 'e') goto yy592; - goto yy186; + if (yych == 'T') goto yy600; + if (yych == 't') goto yy600; + goto yy187; yy580: YYDEBUG(580, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy581; - if (yych != 'l') goto yy186; + if (yych == 'E') goto yy593; + if (yych == 'e') goto yy593; + goto yy187; yy581: YYDEBUG(581, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'U') goto yy582; - if (yych != 'u') goto yy186; + if (yych == 'L') goto yy582; + if (yych != 'l') goto yy187; yy582: YYDEBUG(582, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'D') goto yy583; - if (yych != 'd') goto yy186; + if (yych == 'U') goto yy583; + if (yych != 'u') goto yy187; yy583: YYDEBUG(583, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy584; - if (yych != 'e') goto yy186; + if (yych == 'D') goto yy584; + if (yych != 'd') goto yy187; yy584: YYDEBUG(584, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'E') goto yy585; + if (yych != 'e') goto yy187; +yy585: + YYDEBUG(585, *YYCURSOR); ++YYCURSOR; if ((yych = *YYCURSOR) <= '^') { if (yych <= '9') { - if (yych >= '0') goto yy185; + if (yych >= '0') goto yy186; } else { - if (yych <= '@') goto yy585; - if (yych <= 'Z') goto yy185; + if (yych <= '@') goto yy586; + if (yych <= 'Z') goto yy186; } } else { if (yych <= '`') { - if (yych <= '_') goto yy586; + if (yych <= '_') goto yy587; } else { - if (yych <= 'z') goto yy185; - if (yych >= 0x7F) goto yy185; + if (yych <= 'z') goto yy186; + if (yych >= 0x7F) goto yy186; } } -yy585: - YYDEBUG(585, *YYCURSOR); +yy586: + YYDEBUG(586, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1248 "Zend/zend_language_scanner.l" +#line 1258 "Zend/zend_language_scanner.l" { return T_INCLUDE; } -#line 5857 "Zend/zend_language_scanner.c" -yy586: - YYDEBUG(586, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'O') goto yy587; - if (yych != 'o') goto yy186; +#line 5869 "Zend/zend_language_scanner.c" yy587: YYDEBUG(587, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'N') goto yy588; - if (yych != 'n') goto yy186; + if (yych == 'O') goto yy588; + if (yych != 'o') goto yy187; yy588: YYDEBUG(588, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy589; - if (yych != 'c') goto yy186; + if (yych == 'N') goto yy589; + if (yych != 'n') goto yy187; yy589: YYDEBUG(589, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy590; - if (yych != 'e') goto yy186; + if (yych == 'C') goto yy590; + if (yych != 'c') goto yy187; yy590: YYDEBUG(590, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'E') goto yy591; + if (yych != 'e') goto yy187; +yy591: + YYDEBUG(591, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(591, *YYCURSOR); + YYDEBUG(592, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1252 "Zend/zend_language_scanner.l" +#line 1262 "Zend/zend_language_scanner.l" { return T_INCLUDE_ONCE; } -#line 5890 "Zend/zend_language_scanner.c" -yy592: - YYDEBUG(592, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'R') goto yy593; - if (yych != 'r') goto yy186; +#line 5902 "Zend/zend_language_scanner.c" yy593: YYDEBUG(593, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'F') goto yy594; - if (yych != 'f') goto yy186; + if (yych == 'R') goto yy594; + if (yych != 'r') goto yy187; yy594: YYDEBUG(594, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy595; - if (yych != 'a') goto yy186; + if (yych == 'F') goto yy595; + if (yych != 'f') goto yy187; yy595: YYDEBUG(595, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy596; - if (yych != 'c') goto yy186; + if (yych == 'A') goto yy596; + if (yych != 'a') goto yy187; yy596: YYDEBUG(596, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy597; - if (yych != 'e') goto yy186; + if (yych == 'C') goto yy597; + if (yych != 'c') goto yy187; yy597: YYDEBUG(597, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'E') goto yy598; + if (yych != 'e') goto yy187; +yy598: + YYDEBUG(598, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(598, *YYCURSOR); + YYDEBUG(599, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1150 "Zend/zend_language_scanner.l" +#line 1160 "Zend/zend_language_scanner.l" { return T_INTERFACE; } -#line 5928 "Zend/zend_language_scanner.c" -yy599: - YYDEBUG(599, *YYCURSOR); +#line 5940 "Zend/zend_language_scanner.c" +yy600: + YYDEBUG(600, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'E') { - if (yych == 'A') goto yy600; - if (yych <= 'D') goto yy186; - goto yy601; + if (yych == 'A') goto yy601; + if (yych <= 'D') goto yy187; + goto yy602; } else { if (yych <= 'a') { - if (yych <= '`') goto yy186; + if (yych <= '`') goto yy187; } else { - if (yych == 'e') goto yy601; - goto yy186; + if (yych == 'e') goto yy602; + goto yy187; } } -yy600: - YYDEBUG(600, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'N') goto yy607; - if (yych == 'n') goto yy607; - goto yy186; yy601: YYDEBUG(601, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy602; - if (yych != 'a') goto yy186; + if (yych == 'N') goto yy608; + if (yych == 'n') goto yy608; + goto yy187; yy602: YYDEBUG(602, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'D') goto yy603; - if (yych != 'd') goto yy186; + if (yych == 'A') goto yy603; + if (yych != 'a') goto yy187; yy603: YYDEBUG(603, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'O') goto yy604; - if (yych != 'o') goto yy186; + if (yych == 'D') goto yy604; + if (yych != 'd') goto yy187; yy604: YYDEBUG(604, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'F') goto yy605; - if (yych != 'f') goto yy186; + if (yych == 'O') goto yy605; + if (yych != 'o') goto yy187; yy605: YYDEBUG(605, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'F') goto yy606; + if (yych != 'f') goto yy187; +yy606: + YYDEBUG(606, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(606, *YYCURSOR); + YYDEBUG(607, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1272 "Zend/zend_language_scanner.l" +#line 1282 "Zend/zend_language_scanner.l" { return T_INSTEADOF; } -#line 5982 "Zend/zend_language_scanner.c" -yy607: - YYDEBUG(607, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'C') goto yy608; - if (yych != 'c') goto yy186; +#line 5994 "Zend/zend_language_scanner.c" yy608: YYDEBUG(608, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy609; - if (yych != 'e') goto yy186; + if (yych == 'C') goto yy609; + if (yych != 'c') goto yy187; yy609: YYDEBUG(609, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'O') goto yy610; - if (yych != 'o') goto yy186; + if (yych == 'E') goto yy610; + if (yych != 'e') goto yy187; yy610: YYDEBUG(610, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'F') goto yy611; - if (yych != 'f') goto yy186; + if (yych == 'O') goto yy611; + if (yych != 'o') goto yy187; yy611: YYDEBUG(611, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'F') goto yy612; + if (yych != 'f') goto yy187; +yy612: + YYDEBUG(612, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(612, *YYCURSOR); + YYDEBUG(613, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1102 "Zend/zend_language_scanner.l" +#line 1112 "Zend/zend_language_scanner.l" { return T_INSTANCEOF; } -#line 6015 "Zend/zend_language_scanner.c" -yy613: - YYDEBUG(613, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'L') goto yy614; - if (yych != 'l') goto yy186; +#line 6027 "Zend/zend_language_scanner.c" yy614: YYDEBUG(614, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy615; - if (yych != 'e') goto yy186; + if (yych == 'L') goto yy615; + if (yych != 'l') goto yy187; yy615: YYDEBUG(615, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'M') goto yy616; - if (yych != 'm') goto yy186; + if (yych == 'E') goto yy616; + if (yych != 'e') goto yy187; yy616: YYDEBUG(616, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy617; - if (yych != 'e') goto yy186; + if (yych == 'M') goto yy617; + if (yych != 'm') goto yy187; yy617: YYDEBUG(617, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'N') goto yy618; - if (yych != 'n') goto yy186; + if (yych == 'E') goto yy618; + if (yych != 'e') goto yy187; yy618: YYDEBUG(618, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy619; - if (yych != 't') goto yy186; + if (yych == 'N') goto yy619; + if (yych != 'n') goto yy187; yy619: YYDEBUG(619, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'S') goto yy620; - if (yych != 's') goto yy186; + if (yych == 'T') goto yy620; + if (yych != 't') goto yy187; yy620: YYDEBUG(620, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'S') goto yy621; + if (yych != 's') goto yy187; +yy621: + YYDEBUG(621, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(621, *YYCURSOR); + YYDEBUG(622, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1162 "Zend/zend_language_scanner.l" +#line 1172 "Zend/zend_language_scanner.l" { return T_IMPLEMENTS; } -#line 6063 "Zend/zend_language_scanner.c" -yy622: - YYDEBUG(622, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'R') goto yy630; - if (yych == 'r') goto yy630; - goto yy186; +#line 6075 "Zend/zend_language_scanner.c" yy623: YYDEBUG(623, *YYCURSOR); yych = *++YYCURSOR; + if (yych == 'R') goto yy631; + if (yych == 'r') goto yy631; + goto yy187; +yy624: + YYDEBUG(624, *YYCURSOR); + yych = *++YYCURSOR; if (yych <= 'Y') { - if (yych == 'A') goto yy626; - if (yych <= 'X') goto yy186; + if (yych == 'A') goto yy627; + if (yych <= 'X') goto yy187; } else { if (yych <= 'a') { - if (yych <= '`') goto yy186; - goto yy626; + if (yych <= '`') goto yy187; + goto yy627; } else { - if (yych != 'y') goto yy186; + if (yych != 'y') goto yy187; } } - YYDEBUG(624, *YYCURSOR); + YYDEBUG(625, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(625, *YYCURSOR); + YYDEBUG(626, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1038 "Zend/zend_language_scanner.l" +#line 1044 "Zend/zend_language_scanner.l" { return T_TRY; } -#line 6095 "Zend/zend_language_scanner.c" -yy626: - YYDEBUG(626, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'I') goto yy627; - if (yych != 'i') goto yy186; +#line 6107 "Zend/zend_language_scanner.c" yy627: YYDEBUG(627, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy628; - if (yych != 't') goto yy186; + if (yych == 'I') goto yy628; + if (yych != 'i') goto yy187; yy628: YYDEBUG(628, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'T') goto yy629; + if (yych != 't') goto yy187; +yy629: + YYDEBUG(629, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(629, *YYCURSOR); + YYDEBUG(630, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1154 "Zend/zend_language_scanner.l" +#line 1164 "Zend/zend_language_scanner.l" { return T_TRAIT; } -#line 6118 "Zend/zend_language_scanner.c" -yy630: - YYDEBUG(630, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'O') goto yy631; - if (yych != 'o') goto yy186; +#line 6130 "Zend/zend_language_scanner.c" yy631: YYDEBUG(631, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'W') goto yy632; - if (yych != 'w') goto yy186; + if (yych == 'O') goto yy632; + if (yych != 'o') goto yy187; yy632: YYDEBUG(632, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'W') goto yy633; + if (yych != 'w') goto yy187; +yy633: + YYDEBUG(633, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(633, *YYCURSOR); + YYDEBUG(634, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1046 "Zend/zend_language_scanner.l" +#line 1056 "Zend/zend_language_scanner.l" { return T_THROW; } -#line 6141 "Zend/zend_language_scanner.c" -yy634: - YYDEBUG(634, *YYCURSOR); - yych = *++YYCURSOR; - if (yych <= 'T') { - if (yych == 'Q') goto yy636; - if (yych <= 'S') goto yy186; - } else { - if (yych <= 'q') { - if (yych <= 'p') goto yy186; - goto yy636; - } else { - if (yych != 't') goto yy186; - } - } +#line 6153 "Zend/zend_language_scanner.c" +yy635: YYDEBUG(635, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'U') goto yy648; - if (yych == 'u') goto yy648; - goto yy186; + if (yych == 'E') goto yy636; + if (yych != 'e') goto yy187; yy636: YYDEBUG(636, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'U') goto yy637; - if (yych != 'u') goto yy186; + if (yych == 'L') goto yy637; + if (yych != 'l') goto yy187; yy637: YYDEBUG(637, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'I') goto yy638; - if (yych != 'i') goto yy186; + if (yych == 'D') goto yy638; + if (yych != 'd') goto yy187; yy638: YYDEBUG(638, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'R') goto yy639; - if (yych != 'r') goto yy186; -yy639: + ++YYCURSOR; + if (yybm[0+(yych = *YYCURSOR)] & 4) { + goto yy186; + } YYDEBUG(639, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'E') goto yy640; - if (yych != 'e') goto yy186; + yyleng = YYCURSOR - SCNG(yy_text); +#line 1040 "Zend/zend_language_scanner.l" + { + return T_YIELD; +} +#line 6181 "Zend/zend_language_scanner.c" yy640: YYDEBUG(640, *YYCURSOR); - ++YYCURSOR; - if ((yych = *YYCURSOR) <= '^') { - if (yych <= '9') { - if (yych >= '0') goto yy185; - } else { - if (yych <= '@') goto yy641; - if (yych <= 'Z') goto yy185; - } + yych = *++YYCURSOR; + if (yych <= 'T') { + if (yych == 'Q') goto yy642; + if (yych <= 'S') goto yy187; } else { - if (yych <= '`') { - if (yych <= '_') goto yy642; + if (yych <= 'q') { + if (yych <= 'p') goto yy187; + goto yy642; } else { - if (yych <= 'z') goto yy185; - if (yych >= 0x7F) goto yy185; + if (yych != 't') goto yy187; } } -yy641: YYDEBUG(641, *YYCURSOR); - yyleng = YYCURSOR - SCNG(yy_text); -#line 1256 "Zend/zend_language_scanner.l" - { - return T_REQUIRE; -} -#line 6206 "Zend/zend_language_scanner.c" + yych = *++YYCURSOR; + if (yych == 'U') goto yy654; + if (yych == 'u') goto yy654; + goto yy187; yy642: YYDEBUG(642, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'O') goto yy643; - if (yych != 'o') goto yy186; + if (yych == 'U') goto yy643; + if (yych != 'u') goto yy187; yy643: YYDEBUG(643, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'N') goto yy644; - if (yych != 'n') goto yy186; + if (yych == 'I') goto yy644; + if (yych != 'i') goto yy187; yy644: YYDEBUG(644, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy645; - if (yych != 'c') goto yy186; + if (yych == 'R') goto yy645; + if (yych != 'r') goto yy187; yy645: YYDEBUG(645, *YYCURSOR); yych = *++YYCURSOR; if (yych == 'E') goto yy646; - if (yych != 'e') goto yy186; + if (yych != 'e') goto yy187; yy646: YYDEBUG(646, *YYCURSOR); ++YYCURSOR; - if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + if ((yych = *YYCURSOR) <= '^') { + if (yych <= '9') { + if (yych >= '0') goto yy186; + } else { + if (yych <= '@') goto yy647; + if (yych <= 'Z') goto yy186; + } + } else { + if (yych <= '`') { + if (yych <= '_') goto yy648; + } else { + if (yych <= 'z') goto yy186; + if (yych >= 0x7F) goto yy186; + } } +yy647: YYDEBUG(647, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1260 "Zend/zend_language_scanner.l" +#line 1266 "Zend/zend_language_scanner.l" { - return T_REQUIRE_ONCE; + return T_REQUIRE; } -#line 6239 "Zend/zend_language_scanner.c" +#line 6246 "Zend/zend_language_scanner.c" yy648: YYDEBUG(648, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'R') goto yy649; - if (yych != 'r') goto yy186; + if (yych == 'O') goto yy649; + if (yych != 'o') goto yy187; yy649: YYDEBUG(649, *YYCURSOR); yych = *++YYCURSOR; if (yych == 'N') goto yy650; - if (yych != 'n') goto yy186; + if (yych != 'n') goto yy187; yy650: YYDEBUG(650, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'C') goto yy651; + if (yych != 'c') goto yy187; +yy651: + YYDEBUG(651, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'E') goto yy652; + if (yych != 'e') goto yy187; +yy652: + YYDEBUG(652, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(651, *YYCURSOR); + YYDEBUG(653, *YYCURSOR); + yyleng = YYCURSOR - SCNG(yy_text); +#line 1270 "Zend/zend_language_scanner.l" + { + return T_REQUIRE_ONCE; +} +#line 6279 "Zend/zend_language_scanner.c" +yy654: + YYDEBUG(654, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'R') goto yy655; + if (yych != 'r') goto yy187; +yy655: + YYDEBUG(655, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'N') goto yy656; + if (yych != 'n') goto yy187; +yy656: + YYDEBUG(656, *YYCURSOR); + ++YYCURSOR; + if (yybm[0+(yych = *YYCURSOR)] & 4) { + goto yy186; + } + YYDEBUG(657, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1034 "Zend/zend_language_scanner.l" +#line 1036 "Zend/zend_language_scanner.l" { return T_RETURN; } -#line 6262 "Zend/zend_language_scanner.c" -yy652: - YYDEBUG(652, *YYCURSOR); +#line 6302 "Zend/zend_language_scanner.c" +yy658: + YYDEBUG(658, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'T') { if (yych <= 'L') { - if (yych <= 'K') goto yy186; - goto yy675; + if (yych <= 'K') goto yy187; + goto yy681; } else { - if (yych <= 'R') goto yy186; - if (yych <= 'S') goto yy674; - goto yy673; + if (yych <= 'R') goto yy187; + if (yych <= 'S') goto yy680; + goto yy679; } } else { if (yych <= 'r') { - if (yych == 'l') goto yy675; - goto yy186; + if (yych == 'l') goto yy681; + goto yy187; } else { - if (yych <= 's') goto yy674; - if (yych <= 't') goto yy673; - goto yy186; + if (yych <= 's') goto yy680; + if (yych <= 't') goto yy679; + goto yy187; } } -yy653: - YYDEBUG(653, *YYCURSOR); +yy659: + YYDEBUG(659, *YYCURSOR); yych = *++YYCURSOR; if (yych <= 'O') { - if (yych == 'A') goto yy665; - if (yych <= 'N') goto yy186; - goto yy666; + if (yych == 'A') goto yy671; + if (yych <= 'N') goto yy187; + goto yy672; } else { if (yych <= 'a') { - if (yych <= '`') goto yy186; - goto yy665; + if (yych <= '`') goto yy187; + goto yy671; } else { - if (yych == 'o') goto yy666; - goto yy186; + if (yych == 'o') goto yy672; + goto yy187; } } -yy654: - YYDEBUG(654, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'N') goto yy655; - if (yych != 'n') goto yy186; -yy655: - YYDEBUG(655, *YYCURSOR); - yych = *++YYCURSOR; - if (yych <= 'T') { - if (yych <= 'R') goto yy186; - if (yych >= 'T') goto yy657; - } else { - if (yych <= 'r') goto yy186; - if (yych <= 's') goto yy656; - if (yych <= 't') goto yy657; - goto yy186; - } -yy656: - YYDEBUG(656, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'T') goto yy663; - if (yych == 't') goto yy663; - goto yy186; -yy657: - YYDEBUG(657, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'I') goto yy658; - if (yych != 'i') goto yy186; -yy658: - YYDEBUG(658, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'N') goto yy659; - if (yych != 'n') goto yy186; -yy659: - YYDEBUG(659, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'U') goto yy660; - if (yych != 'u') goto yy186; yy660: YYDEBUG(660, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy661; - if (yych != 'e') goto yy186; + if (yych == 'N') goto yy661; + if (yych != 'n') goto yy187; yy661: YYDEBUG(661, *YYCURSOR); - ++YYCURSOR; - if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + yych = *++YYCURSOR; + if (yych <= 'T') { + if (yych <= 'R') goto yy187; + if (yych >= 'T') goto yy663; + } else { + if (yych <= 'r') goto yy187; + if (yych <= 's') goto yy662; + if (yych <= 't') goto yy663; + goto yy187; } +yy662: YYDEBUG(662, *YYCURSOR); - yyleng = YYCURSOR - SCNG(yy_text); -#line 1130 "Zend/zend_language_scanner.l" - { - return T_CONTINUE; -} -#line 6356 "Zend/zend_language_scanner.c" + yych = *++YYCURSOR; + if (yych == 'T') goto yy669; + if (yych == 't') goto yy669; + goto yy187; yy663: YYDEBUG(663, *YYCURSOR); - ++YYCURSOR; - if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; - } + yych = *++YYCURSOR; + if (yych == 'I') goto yy664; + if (yych != 'i') goto yy187; +yy664: YYDEBUG(664, *YYCURSOR); - yyleng = YYCURSOR - SCNG(yy_text); -#line 1030 "Zend/zend_language_scanner.l" - { - return T_CONST; -} -#line 6369 "Zend/zend_language_scanner.c" + yych = *++YYCURSOR; + if (yych == 'N') goto yy665; + if (yych != 'n') goto yy187; yy665: YYDEBUG(665, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'S') goto yy670; - if (yych == 's') goto yy670; - goto yy186; + if (yych == 'U') goto yy666; + if (yych != 'u') goto yy187; yy666: YYDEBUG(666, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'N') goto yy667; - if (yych != 'n') goto yy186; + if (yych == 'E') goto yy667; + if (yych != 'e') goto yy187; yy667: YYDEBUG(667, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'E') goto yy668; - if (yych != 'e') goto yy186; -yy668: - YYDEBUG(668, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(669, *YYCURSOR); + YYDEBUG(668, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1208 "Zend/zend_language_scanner.l" +#line 1140 "Zend/zend_language_scanner.l" { - return T_CLONE; + return T_CONTINUE; } -#line 6398 "Zend/zend_language_scanner.c" -yy670: - YYDEBUG(670, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'S') goto yy671; - if (yych != 's') goto yy186; -yy671: - YYDEBUG(671, *YYCURSOR); +#line 6396 "Zend/zend_language_scanner.c" +yy669: + YYDEBUG(669, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(672, *YYCURSOR); + YYDEBUG(670, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1146 "Zend/zend_language_scanner.l" +#line 1032 "Zend/zend_language_scanner.l" { - return T_CLASS; + return T_CONST; } -#line 6416 "Zend/zend_language_scanner.c" +#line 6409 "Zend/zend_language_scanner.c" +yy671: + YYDEBUG(671, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'S') goto yy676; + if (yych == 's') goto yy676; + goto yy187; +yy672: + YYDEBUG(672, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'N') goto yy673; + if (yych != 'n') goto yy187; yy673: YYDEBUG(673, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy684; - if (yych == 'c') goto yy684; - goto yy186; + if (yych == 'E') goto yy674; + if (yych != 'e') goto yy187; yy674: YYDEBUG(674, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'E') goto yy682; - if (yych == 'e') goto yy682; - goto yy186; -yy675: + ++YYCURSOR; + if (yybm[0+(yych = *YYCURSOR)] & 4) { + goto yy186; + } YYDEBUG(675, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'L') goto yy676; - if (yych != 'l') goto yy186; + yyleng = YYCURSOR - SCNG(yy_text); +#line 1218 "Zend/zend_language_scanner.l" + { + return T_CLONE; +} +#line 6438 "Zend/zend_language_scanner.c" yy676: YYDEBUG(676, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy677; - if (yych != 'a') goto yy186; + if (yych == 'S') goto yy677; + if (yych != 's') goto yy187; yy677: YYDEBUG(677, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'B') goto yy678; - if (yych != 'b') goto yy186; -yy678: + ++YYCURSOR; + if (yybm[0+(yych = *YYCURSOR)] & 4) { + goto yy186; + } YYDEBUG(678, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'L') goto yy679; - if (yych != 'l') goto yy186; + yyleng = YYCURSOR - SCNG(yy_text); +#line 1156 "Zend/zend_language_scanner.l" + { + return T_CLASS; +} +#line 6456 "Zend/zend_language_scanner.c" yy679: YYDEBUG(679, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy680; - if (yych != 'e') goto yy186; + if (yych == 'C') goto yy690; + if (yych == 'c') goto yy690; + goto yy187; yy680: YYDEBUG(680, *YYCURSOR); - ++YYCURSOR; - if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; - } + yych = *++YYCURSOR; + if (yych == 'E') goto yy688; + if (yych == 'e') goto yy688; + goto yy187; +yy681: YYDEBUG(681, *YYCURSOR); - yyleng = YYCURSOR - SCNG(yy_text); -#line 1332 "Zend/zend_language_scanner.l" - { - return T_CALLABLE; -} -#line 6466 "Zend/zend_language_scanner.c" + yych = *++YYCURSOR; + if (yych == 'L') goto yy682; + if (yych != 'l') goto yy187; yy682: YYDEBUG(682, *YYCURSOR); - ++YYCURSOR; - if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; - } + yych = *++YYCURSOR; + if (yych == 'A') goto yy683; + if (yych != 'a') goto yy187; +yy683: YYDEBUG(683, *YYCURSOR); - yyleng = YYCURSOR - SCNG(yy_text); -#line 1118 "Zend/zend_language_scanner.l" - { - return T_CASE; -} -#line 6479 "Zend/zend_language_scanner.c" + yych = *++YYCURSOR; + if (yych == 'B') goto yy684; + if (yych != 'b') goto yy187; yy684: YYDEBUG(684, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'H') goto yy685; - if (yych != 'h') goto yy186; + if (yych == 'L') goto yy685; + if (yych != 'l') goto yy187; yy685: YYDEBUG(685, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'E') goto yy686; + if (yych != 'e') goto yy187; +yy686: + YYDEBUG(686, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(686, *YYCURSOR); + YYDEBUG(687, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1042 "Zend/zend_language_scanner.l" +#line 1342 "Zend/zend_language_scanner.l" { - return T_CATCH; + return T_CALLABLE; } -#line 6497 "Zend/zend_language_scanner.c" -yy687: - YYDEBUG(687, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'N') goto yy704; - if (yych == 'n') goto yy704; - goto yy186; +#line 6506 "Zend/zend_language_scanner.c" yy688: YYDEBUG(688, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'R') goto yy697; - if (yych == 'r') goto yy697; - goto yy186; -yy689: + ++YYCURSOR; + if (yybm[0+(yych = *YYCURSOR)] & 4) { + goto yy186; + } YYDEBUG(689, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'N') goto yy690; - if (yych != 'n') goto yy186; + yyleng = YYCURSOR - SCNG(yy_text); +#line 1128 "Zend/zend_language_scanner.l" + { + return T_CASE; +} +#line 6519 "Zend/zend_language_scanner.c" yy690: YYDEBUG(690, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy691; - if (yych != 'c') goto yy186; + if (yych == 'H') goto yy691; + if (yych != 'h') goto yy187; yy691: YYDEBUG(691, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'T') goto yy692; - if (yych != 't') goto yy186; -yy692: + ++YYCURSOR; + if (yybm[0+(yych = *YYCURSOR)] & 4) { + goto yy186; + } YYDEBUG(692, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'I') goto yy693; - if (yych != 'i') goto yy186; + yyleng = YYCURSOR - SCNG(yy_text); +#line 1048 "Zend/zend_language_scanner.l" + { + return T_CATCH; +} +#line 6537 "Zend/zend_language_scanner.c" yy693: YYDEBUG(693, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'O') goto yy694; - if (yych != 'o') goto yy186; + if (yych == 'N') goto yy710; + if (yych == 'n') goto yy710; + goto yy187; yy694: YYDEBUG(694, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'N') goto yy695; - if (yych != 'n') goto yy186; + if (yych == 'R') goto yy703; + if (yych == 'r') goto yy703; + goto yy187; yy695: YYDEBUG(695, *YYCURSOR); - ++YYCURSOR; - if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; - } + yych = *++YYCURSOR; + if (yych == 'N') goto yy696; + if (yych != 'n') goto yy187; +yy696: YYDEBUG(696, *YYCURSOR); - yyleng = YYCURSOR - SCNG(yy_text); -#line 1026 "Zend/zend_language_scanner.l" - { - return T_FUNCTION; -} -#line 6552 "Zend/zend_language_scanner.c" + yych = *++YYCURSOR; + if (yych == 'C') goto yy697; + if (yych != 'c') goto yy187; yy697: YYDEBUG(697, *YYCURSOR); - ++YYCURSOR; - if ((yych = *YYCURSOR) <= '^') { - if (yych <= '@') { - if (yych <= '/') goto yy698; - if (yych <= '9') goto yy185; - } else { - if (yych == 'E') goto yy699; - if (yych <= 'Z') goto yy185; - } - } else { - if (yych <= 'd') { - if (yych != '`') goto yy185; - } else { - if (yych <= 'e') goto yy699; - if (yych <= 'z') goto yy185; - if (yych >= 0x7F) goto yy185; - } - } + yych = *++YYCURSOR; + if (yych == 'T') goto yy698; + if (yych != 't') goto yy187; yy698: YYDEBUG(698, *YYCURSOR); - yyleng = YYCURSOR - SCNG(yy_text); -#line 1078 "Zend/zend_language_scanner.l" - { - return T_FOR; -} -#line 6580 "Zend/zend_language_scanner.c" + yych = *++YYCURSOR; + if (yych == 'I') goto yy699; + if (yych != 'i') goto yy187; yy699: YYDEBUG(699, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy700; - if (yych != 'a') goto yy186; + if (yych == 'O') goto yy700; + if (yych != 'o') goto yy187; yy700: YYDEBUG(700, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy701; - if (yych != 'c') goto yy186; + if (yych == 'N') goto yy701; + if (yych != 'n') goto yy187; yy701: YYDEBUG(701, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'H') goto yy702; - if (yych != 'h') goto yy186; -yy702: - YYDEBUG(702, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(703, *YYCURSOR); + YYDEBUG(702, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1086 "Zend/zend_language_scanner.l" +#line 1028 "Zend/zend_language_scanner.l" { - return T_FOREACH; + return T_FUNCTION; } -#line 6608 "Zend/zend_language_scanner.c" +#line 6592 "Zend/zend_language_scanner.c" +yy703: + YYDEBUG(703, *YYCURSOR); + ++YYCURSOR; + if ((yych = *YYCURSOR) <= '^') { + if (yych <= '@') { + if (yych <= '/') goto yy704; + if (yych <= '9') goto yy186; + } else { + if (yych == 'E') goto yy705; + if (yych <= 'Z') goto yy186; + } + } else { + if (yych <= 'd') { + if (yych != '`') goto yy186; + } else { + if (yych <= 'e') goto yy705; + if (yych <= 'z') goto yy186; + if (yych >= 0x7F) goto yy186; + } + } yy704: YYDEBUG(704, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'A') goto yy705; - if (yych != 'a') goto yy186; + yyleng = YYCURSOR - SCNG(yy_text); +#line 1088 "Zend/zend_language_scanner.l" + { + return T_FOR; +} +#line 6620 "Zend/zend_language_scanner.c" yy705: YYDEBUG(705, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy706; - if (yych != 'l') goto yy186; + if (yych == 'A') goto yy706; + if (yych != 'a') goto yy187; yy706: YYDEBUG(706, *YYCURSOR); - ++YYCURSOR; - if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; - } + yych = *++YYCURSOR; + if (yych == 'C') goto yy707; + if (yych != 'c') goto yy187; +yy707: YYDEBUG(707, *YYCURSOR); - yyleng = YYCURSOR - SCNG(yy_text); -#line 1300 "Zend/zend_language_scanner.l" - { - return T_FINAL; -} -#line 6631 "Zend/zend_language_scanner.c" + yych = *++YYCURSOR; + if (yych == 'H') goto yy708; + if (yych != 'h') goto yy187; yy708: YYDEBUG(708, *YYCURSOR); - yych = *++YYCURSOR; - if (yych <= 'F') { - if (yych == 'C') goto yy714; - if (yych <= 'E') goto yy186; - goto yy715; - } else { - if (yych <= 'c') { - if (yych <= 'b') goto yy186; - goto yy714; - } else { - if (yych == 'f') goto yy715; - goto yy186; - } - } -yy709: - YYDEBUG(709, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'E') goto yy712; - if (yych == 'e') goto yy712; - goto yy186; -yy710: - YYDEBUG(710, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(711, *YYCURSOR); + YYDEBUG(709, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1074 "Zend/zend_language_scanner.l" +#line 1096 "Zend/zend_language_scanner.l" { - return T_DO; + return T_FOREACH; } -#line 6666 "Zend/zend_language_scanner.c" +#line 6648 "Zend/zend_language_scanner.c" +yy710: + YYDEBUG(710, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'A') goto yy711; + if (yych != 'a') goto yy187; +yy711: + YYDEBUG(711, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'L') goto yy712; + if (yych != 'l') goto yy187; yy712: YYDEBUG(712, *YYCURSOR); ++YYCURSOR; - if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + if ((yych = *YYCURSOR) <= '^') { + if (yych <= '@') { + if (yych <= '/') goto yy713; + if (yych <= '9') goto yy186; + } else { + if (yych == 'L') goto yy714; + if (yych <= 'Z') goto yy186; + } + } else { + if (yych <= 'k') { + if (yych != '`') goto yy186; + } else { + if (yych <= 'l') goto yy714; + if (yych <= 'z') goto yy186; + if (yych >= 0x7F) goto yy186; + } } +yy713: YYDEBUG(713, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1022 "Zend/zend_language_scanner.l" +#line 1310 "Zend/zend_language_scanner.l" { - return T_EXIT; + return T_FINAL; } -#line 6679 "Zend/zend_language_scanner.c" +#line 6686 "Zend/zend_language_scanner.c" yy714: YYDEBUG(714, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy721; - if (yych == 'l') goto yy721; - goto yy186; + if (yych == 'Y') goto yy715; + if (yych != 'y') goto yy187; yy715: YYDEBUG(715, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'A') goto yy716; - if (yych != 'a') goto yy186; -yy716: + ++YYCURSOR; + if (yybm[0+(yych = *YYCURSOR)] & 4) { + goto yy186; + } YYDEBUG(716, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'U') goto yy717; - if (yych != 'u') goto yy186; + yyleng = YYCURSOR - SCNG(yy_text); +#line 1052 "Zend/zend_language_scanner.l" + { + return T_FINALLY; +} +#line 6704 "Zend/zend_language_scanner.c" yy717: YYDEBUG(717, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy718; - if (yych != 'l') goto yy186; + if (yych <= 'F') { + if (yych == 'C') goto yy723; + if (yych <= 'E') goto yy187; + goto yy724; + } else { + if (yych <= 'c') { + if (yych <= 'b') goto yy187; + goto yy723; + } else { + if (yych == 'f') goto yy724; + goto yy187; + } + } yy718: YYDEBUG(718, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy719; - if (yych != 't') goto yy186; + if (yych == 'E') goto yy721; + if (yych == 'e') goto yy721; + goto yy187; yy719: YYDEBUG(719, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } YYDEBUG(720, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1122 "Zend/zend_language_scanner.l" +#line 1084 "Zend/zend_language_scanner.l" { - return T_DEFAULT; + return T_DO; } -#line 6718 "Zend/zend_language_scanner.c" +#line 6739 "Zend/zend_language_scanner.c" yy721: YYDEBUG(721, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'A') goto yy722; - if (yych != 'a') goto yy186; -yy722: + ++YYCURSOR; + if (yybm[0+(yych = *YYCURSOR)] & 4) { + goto yy186; + } YYDEBUG(722, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'R') goto yy723; - if (yych != 'r') goto yy186; + yyleng = YYCURSOR - SCNG(yy_text); +#line 1024 "Zend/zend_language_scanner.l" + { + return T_EXIT; +} +#line 6752 "Zend/zend_language_scanner.c" yy723: YYDEBUG(723, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy724; - if (yych != 'e') goto yy186; + if (yych == 'L') goto yy730; + if (yych == 'l') goto yy730; + goto yy187; yy724: YYDEBUG(724, *YYCURSOR); - ++YYCURSOR; - if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; - } + yych = *++YYCURSOR; + if (yych == 'A') goto yy725; + if (yych != 'a') goto yy187; +yy725: YYDEBUG(725, *YYCURSOR); - yyleng = YYCURSOR - SCNG(yy_text); -#line 1094 "Zend/zend_language_scanner.l" - { - return T_DECLARE; -} -#line 6746 "Zend/zend_language_scanner.c" + yych = *++YYCURSOR; + if (yych == 'U') goto yy726; + if (yych != 'u') goto yy187; yy726: YYDEBUG(726, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'H') goto yy788; - if (yych == 'h') goto yy788; - goto yy186; + if (yych == 'L') goto yy727; + if (yych != 'l') goto yy187; yy727: YYDEBUG(727, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'S') goto yy782; - if (yych == 's') goto yy782; - goto yy186; + if (yych == 'T') goto yy728; + if (yych != 't') goto yy187; yy728: YYDEBUG(728, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'P') goto yy778; - if (yych == 'p') goto yy778; - goto yy186; -yy729: + ++YYCURSOR; + if (yybm[0+(yych = *YYCURSOR)] & 4) { + goto yy186; + } YYDEBUG(729, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'D') goto yy744; - if (yych == 'd') goto yy744; - goto yy186; + yyleng = YYCURSOR - SCNG(yy_text); +#line 1132 "Zend/zend_language_scanner.l" + { + return T_DEFAULT; +} +#line 6791 "Zend/zend_language_scanner.c" yy730: YYDEBUG(730, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy741; - if (yych == 'a') goto yy741; - goto yy186; + if (yych == 'A') goto yy731; + if (yych != 'a') goto yy187; yy731: YYDEBUG(731, *YYCURSOR); yych = *++YYCURSOR; - if (yych <= 'T') { - if (yych == 'I') goto yy732; - if (yych <= 'S') goto yy186; - goto yy733; - } else { - if (yych <= 'i') { - if (yych <= 'h') goto yy186; - } else { - if (yych == 't') goto yy733; - goto yy186; - } - } + if (yych == 'R') goto yy732; + if (yych != 'r') goto yy187; yy732: YYDEBUG(732, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy739; - if (yych == 't') goto yy739; - goto yy186; + if (yych == 'E') goto yy733; + if (yych != 'e') goto yy187; yy733: YYDEBUG(733, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'E') goto yy734; - if (yych != 'e') goto yy186; -yy734: + ++YYCURSOR; + if (yybm[0+(yych = *YYCURSOR)] & 4) { + goto yy186; + } YYDEBUG(734, *YYCURSOR); - yych = *++YYCURSOR; - if (yych == 'N') goto yy735; - if (yych != 'n') goto yy186; + yyleng = YYCURSOR - SCNG(yy_text); +#line 1104 "Zend/zend_language_scanner.l" + { + return T_DECLARE; +} +#line 6819 "Zend/zend_language_scanner.c" yy735: YYDEBUG(735, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'D') goto yy736; - if (yych != 'd') goto yy186; + if (yych == 'H') goto yy797; + if (yych == 'h') goto yy797; + goto yy187; yy736: YYDEBUG(736, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'S') goto yy737; - if (yych != 's') goto yy186; + if (yych == 'S') goto yy791; + if (yych == 's') goto yy791; + goto yy187; yy737: YYDEBUG(737, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'P') goto yy787; + if (yych == 'p') goto yy787; + goto yy187; +yy738: + YYDEBUG(738, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'D') goto yy753; + if (yych == 'd') goto yy753; + goto yy187; +yy739: + YYDEBUG(739, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'A') goto yy750; + if (yych == 'a') goto yy750; + goto yy187; +yy740: + YYDEBUG(740, *YYCURSOR); + yych = *++YYCURSOR; + if (yych <= 'T') { + if (yych == 'I') goto yy741; + if (yych <= 'S') goto yy187; + goto yy742; + } else { + if (yych <= 'i') { + if (yych <= 'h') goto yy187; + } else { + if (yych == 't') goto yy742; + goto yy187; + } + } +yy741: + YYDEBUG(741, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'T') goto yy748; + if (yych == 't') goto yy748; + goto yy187; +yy742: + YYDEBUG(742, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'E') goto yy743; + if (yych != 'e') goto yy187; +yy743: + YYDEBUG(743, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'N') goto yy744; + if (yych != 'n') goto yy187; +yy744: + YYDEBUG(744, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'D') goto yy745; + if (yych != 'd') goto yy187; +yy745: + YYDEBUG(745, *YYCURSOR); + yych = *++YYCURSOR; + if (yych == 'S') goto yy746; + if (yych != 's') goto yy187; +yy746: + YYDEBUG(746, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(738, *YYCURSOR); + YYDEBUG(747, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1158 "Zend/zend_language_scanner.l" +#line 1168 "Zend/zend_language_scanner.l" { return T_EXTENDS; } -#line 6830 "Zend/zend_language_scanner.c" -yy739: - YYDEBUG(739, *YYCURSOR); +#line 6903 "Zend/zend_language_scanner.c" +yy748: + YYDEBUG(748, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(740, *YYCURSOR); + YYDEBUG(749, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1018 "Zend/zend_language_scanner.l" +#line 1020 "Zend/zend_language_scanner.l" { return T_EXIT; } -#line 6843 "Zend/zend_language_scanner.c" -yy741: - YYDEBUG(741, *YYCURSOR); +#line 6916 "Zend/zend_language_scanner.c" +yy750: + YYDEBUG(750, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy742; - if (yych != 'l') goto yy186; -yy742: - YYDEBUG(742, *YYCURSOR); + if (yych == 'L') goto yy751; + if (yych != 'l') goto yy187; +yy751: + YYDEBUG(751, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(743, *YYCURSOR); + YYDEBUG(752, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1244 "Zend/zend_language_scanner.l" +#line 1254 "Zend/zend_language_scanner.l" { return T_EVAL; } -#line 6861 "Zend/zend_language_scanner.c" -yy744: - YYDEBUG(744, *YYCURSOR); +#line 6934 "Zend/zend_language_scanner.c" +yy753: + YYDEBUG(753, *YYCURSOR); yych = *++YYCURSOR; YYDEBUG(-1, yych); switch (yych) { case 'D': - case 'd': goto yy745; + case 'd': goto yy754; case 'F': - case 'f': goto yy746; + case 'f': goto yy755; case 'I': - case 'i': goto yy747; + case 'i': goto yy756; case 'S': - case 's': goto yy748; + case 's': goto yy757; case 'W': - case 'w': goto yy749; - default: goto yy186; + case 'w': goto yy758; + default: goto yy187; } -yy745: - YYDEBUG(745, *YYCURSOR); +yy754: + YYDEBUG(754, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy771; - if (yych == 'e') goto yy771; - goto yy186; -yy746: - YYDEBUG(746, *YYCURSOR); + if (yych == 'E') goto yy780; + if (yych == 'e') goto yy780; + goto yy187; +yy755: + YYDEBUG(755, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'O') goto yy763; - if (yych == 'o') goto yy763; - goto yy186; -yy747: - YYDEBUG(747, *YYCURSOR); + if (yych == 'O') goto yy772; + if (yych == 'o') goto yy772; + goto yy187; +yy756: + YYDEBUG(756, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'F') goto yy761; - if (yych == 'f') goto yy761; - goto yy186; -yy748: - YYDEBUG(748, *YYCURSOR); + if (yych == 'F') goto yy770; + if (yych == 'f') goto yy770; + goto yy187; +yy757: + YYDEBUG(757, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'W') goto yy755; - if (yych == 'w') goto yy755; - goto yy186; -yy749: - YYDEBUG(749, *YYCURSOR); + if (yych == 'W') goto yy764; + if (yych == 'w') goto yy764; + goto yy187; +yy758: + YYDEBUG(758, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'H') goto yy750; - if (yych != 'h') goto yy186; -yy750: - YYDEBUG(750, *YYCURSOR); + if (yych == 'H') goto yy759; + if (yych != 'h') goto yy187; +yy759: + YYDEBUG(759, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'I') goto yy751; - if (yych != 'i') goto yy186; -yy751: - YYDEBUG(751, *YYCURSOR); + if (yych == 'I') goto yy760; + if (yych != 'i') goto yy187; +yy760: + YYDEBUG(760, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy752; - if (yych != 'l') goto yy186; -yy752: - YYDEBUG(752, *YYCURSOR); + if (yych == 'L') goto yy761; + if (yych != 'l') goto yy187; +yy761: + YYDEBUG(761, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy753; - if (yych != 'e') goto yy186; -yy753: - YYDEBUG(753, *YYCURSOR); + if (yych == 'E') goto yy762; + if (yych != 'e') goto yy187; +yy762: + YYDEBUG(762, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(754, *YYCURSOR); + YYDEBUG(763, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1070 "Zend/zend_language_scanner.l" +#line 1080 "Zend/zend_language_scanner.l" { return T_ENDWHILE; } -#line 6935 "Zend/zend_language_scanner.c" -yy755: - YYDEBUG(755, *YYCURSOR); +#line 7008 "Zend/zend_language_scanner.c" +yy764: + YYDEBUG(764, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'I') goto yy756; - if (yych != 'i') goto yy186; -yy756: - YYDEBUG(756, *YYCURSOR); + if (yych == 'I') goto yy765; + if (yych != 'i') goto yy187; +yy765: + YYDEBUG(765, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy757; - if (yych != 't') goto yy186; -yy757: - YYDEBUG(757, *YYCURSOR); + if (yych == 'T') goto yy766; + if (yych != 't') goto yy187; +yy766: + YYDEBUG(766, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy758; - if (yych != 'c') goto yy186; -yy758: - YYDEBUG(758, *YYCURSOR); + if (yych == 'C') goto yy767; + if (yych != 'c') goto yy187; +yy767: + YYDEBUG(767, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'H') goto yy759; - if (yych != 'h') goto yy186; -yy759: - YYDEBUG(759, *YYCURSOR); + if (yych == 'H') goto yy768; + if (yych != 'h') goto yy187; +yy768: + YYDEBUG(768, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(760, *YYCURSOR); + YYDEBUG(769, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1114 "Zend/zend_language_scanner.l" +#line 1124 "Zend/zend_language_scanner.l" { return T_ENDSWITCH; } -#line 6968 "Zend/zend_language_scanner.c" -yy761: - YYDEBUG(761, *YYCURSOR); +#line 7041 "Zend/zend_language_scanner.c" +yy770: + YYDEBUG(770, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(762, *YYCURSOR); + YYDEBUG(771, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1058 "Zend/zend_language_scanner.l" +#line 1068 "Zend/zend_language_scanner.l" { return T_ENDIF; } -#line 6981 "Zend/zend_language_scanner.c" -yy763: - YYDEBUG(763, *YYCURSOR); +#line 7054 "Zend/zend_language_scanner.c" +yy772: + YYDEBUG(772, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'R') goto yy764; - if (yych != 'r') goto yy186; -yy764: - YYDEBUG(764, *YYCURSOR); + if (yych == 'R') goto yy773; + if (yych != 'r') goto yy187; +yy773: + YYDEBUG(773, *YYCURSOR); ++YYCURSOR; if ((yych = *YYCURSOR) <= '^') { if (yych <= '@') { - if (yych <= '/') goto yy765; - if (yych <= '9') goto yy185; + if (yych <= '/') goto yy774; + if (yych <= '9') goto yy186; } else { - if (yych == 'E') goto yy766; - if (yych <= 'Z') goto yy185; + if (yych == 'E') goto yy775; + if (yych <= 'Z') goto yy186; } } else { if (yych <= 'd') { - if (yych != '`') goto yy185; + if (yych != '`') goto yy186; } else { - if (yych <= 'e') goto yy766; - if (yych <= 'z') goto yy185; - if (yych >= 0x7F) goto yy185; + if (yych <= 'e') goto yy775; + if (yych <= 'z') goto yy186; + if (yych >= 0x7F) goto yy186; } } -yy765: - YYDEBUG(765, *YYCURSOR); +yy774: + YYDEBUG(774, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1082 "Zend/zend_language_scanner.l" +#line 1092 "Zend/zend_language_scanner.l" { return T_ENDFOR; } -#line 7014 "Zend/zend_language_scanner.c" -yy766: - YYDEBUG(766, *YYCURSOR); +#line 7087 "Zend/zend_language_scanner.c" +yy775: + YYDEBUG(775, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy767; - if (yych != 'a') goto yy186; -yy767: - YYDEBUG(767, *YYCURSOR); + if (yych == 'A') goto yy776; + if (yych != 'a') goto yy187; +yy776: + YYDEBUG(776, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy768; - if (yych != 'c') goto yy186; -yy768: - YYDEBUG(768, *YYCURSOR); + if (yych == 'C') goto yy777; + if (yych != 'c') goto yy187; +yy777: + YYDEBUG(777, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'H') goto yy769; - if (yych != 'h') goto yy186; -yy769: - YYDEBUG(769, *YYCURSOR); + if (yych == 'H') goto yy778; + if (yych != 'h') goto yy187; +yy778: + YYDEBUG(778, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(770, *YYCURSOR); + YYDEBUG(779, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1090 "Zend/zend_language_scanner.l" +#line 1100 "Zend/zend_language_scanner.l" { return T_ENDFOREACH; } -#line 7042 "Zend/zend_language_scanner.c" -yy771: - YYDEBUG(771, *YYCURSOR); +#line 7115 "Zend/zend_language_scanner.c" +yy780: + YYDEBUG(780, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'C') goto yy772; - if (yych != 'c') goto yy186; -yy772: - YYDEBUG(772, *YYCURSOR); + if (yych == 'C') goto yy781; + if (yych != 'c') goto yy187; +yy781: + YYDEBUG(781, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'L') goto yy773; - if (yych != 'l') goto yy186; -yy773: - YYDEBUG(773, *YYCURSOR); + if (yych == 'L') goto yy782; + if (yych != 'l') goto yy187; +yy782: + YYDEBUG(782, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'A') goto yy774; - if (yych != 'a') goto yy186; -yy774: - YYDEBUG(774, *YYCURSOR); + if (yych == 'A') goto yy783; + if (yych != 'a') goto yy187; +yy783: + YYDEBUG(783, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'R') goto yy775; - if (yych != 'r') goto yy186; -yy775: - YYDEBUG(775, *YYCURSOR); + if (yych == 'R') goto yy784; + if (yych != 'r') goto yy187; +yy784: + YYDEBUG(784, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy776; - if (yych != 'e') goto yy186; -yy776: - YYDEBUG(776, *YYCURSOR); + if (yych == 'E') goto yy785; + if (yych != 'e') goto yy187; +yy785: + YYDEBUG(785, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(777, *YYCURSOR); + YYDEBUG(786, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1098 "Zend/zend_language_scanner.l" +#line 1108 "Zend/zend_language_scanner.l" { return T_ENDDECLARE; } -#line 7080 "Zend/zend_language_scanner.c" -yy778: - YYDEBUG(778, *YYCURSOR); +#line 7153 "Zend/zend_language_scanner.c" +yy787: + YYDEBUG(787, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'T') goto yy779; - if (yych != 't') goto yy186; -yy779: - YYDEBUG(779, *YYCURSOR); + if (yych == 'T') goto yy788; + if (yych != 't') goto yy187; +yy788: + YYDEBUG(788, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'Y') goto yy780; - if (yych != 'y') goto yy186; -yy780: - YYDEBUG(780, *YYCURSOR); + if (yych == 'Y') goto yy789; + if (yych != 'y') goto yy187; +yy789: + YYDEBUG(789, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(781, *YYCURSOR); + YYDEBUG(790, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1284 "Zend/zend_language_scanner.l" +#line 1294 "Zend/zend_language_scanner.l" { return T_EMPTY; } -#line 7103 "Zend/zend_language_scanner.c" -yy782: - YYDEBUG(782, *YYCURSOR); +#line 7176 "Zend/zend_language_scanner.c" +yy791: + YYDEBUG(791, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'E') goto yy783; - if (yych != 'e') goto yy186; -yy783: - YYDEBUG(783, *YYCURSOR); + if (yych == 'E') goto yy792; + if (yych != 'e') goto yy187; +yy792: + YYDEBUG(792, *YYCURSOR); ++YYCURSOR; if ((yych = *YYCURSOR) <= '^') { if (yych <= '@') { - if (yych <= '/') goto yy784; - if (yych <= '9') goto yy185; + if (yych <= '/') goto yy793; + if (yych <= '9') goto yy186; } else { - if (yych == 'I') goto yy785; - if (yych <= 'Z') goto yy185; + if (yych == 'I') goto yy794; + if (yych <= 'Z') goto yy186; } } else { if (yych <= 'h') { - if (yych != '`') goto yy185; + if (yych != '`') goto yy186; } else { - if (yych <= 'i') goto yy785; - if (yych <= 'z') goto yy185; - if (yych >= 0x7F) goto yy185; + if (yych <= 'i') goto yy794; + if (yych <= 'z') goto yy186; + if (yych >= 0x7F) goto yy186; } } -yy784: - YYDEBUG(784, *YYCURSOR); +yy793: + YYDEBUG(793, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1062 "Zend/zend_language_scanner.l" +#line 1072 "Zend/zend_language_scanner.l" { return T_ELSE; } -#line 7136 "Zend/zend_language_scanner.c" -yy785: - YYDEBUG(785, *YYCURSOR); +#line 7209 "Zend/zend_language_scanner.c" +yy794: + YYDEBUG(794, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'F') goto yy786; - if (yych != 'f') goto yy186; -yy786: - YYDEBUG(786, *YYCURSOR); + if (yych == 'F') goto yy795; + if (yych != 'f') goto yy187; +yy795: + YYDEBUG(795, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(787, *YYCURSOR); + YYDEBUG(796, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1054 "Zend/zend_language_scanner.l" +#line 1064 "Zend/zend_language_scanner.l" { return T_ELSEIF; } -#line 7154 "Zend/zend_language_scanner.c" -yy788: - YYDEBUG(788, *YYCURSOR); +#line 7227 "Zend/zend_language_scanner.c" +yy797: + YYDEBUG(797, *YYCURSOR); yych = *++YYCURSOR; - if (yych == 'O') goto yy789; - if (yych != 'o') goto yy186; -yy789: - YYDEBUG(789, *YYCURSOR); + if (yych == 'O') goto yy798; + if (yych != 'o') goto yy187; +yy798: + YYDEBUG(798, *YYCURSOR); ++YYCURSOR; if (yybm[0+(yych = *YYCURSOR)] & 4) { - goto yy185; + goto yy186; } - YYDEBUG(790, *YYCURSOR); + YYDEBUG(799, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1138 "Zend/zend_language_scanner.l" +#line 1148 "Zend/zend_language_scanner.l" { return T_ECHO; } -#line 7172 "Zend/zend_language_scanner.c" +#line 7245 "Zend/zend_language_scanner.c" } /* *********************************** */ yyc_ST_LOOKING_FOR_PROPERTY: @@ -7207,41 +7280,41 @@ yyc_ST_LOOKING_FOR_PROPERTY: 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, }; - YYDEBUG(791, *YYCURSOR); + YYDEBUG(800, *YYCURSOR); YYFILL(2); yych = *YYCURSOR; if (yych <= '-') { if (yych <= '\r') { - if (yych <= 0x08) goto yy799; - if (yych <= '\n') goto yy793; - if (yych <= '\f') goto yy799; + if (yych <= 0x08) goto yy808; + if (yych <= '\n') goto yy802; + if (yych <= '\f') goto yy808; } else { - if (yych == ' ') goto yy793; - if (yych <= ',') goto yy799; - goto yy795; + if (yych == ' ') goto yy802; + if (yych <= ',') goto yy808; + goto yy804; } } else { if (yych <= '_') { - if (yych <= '@') goto yy799; - if (yych <= 'Z') goto yy797; - if (yych <= '^') goto yy799; - goto yy797; + if (yych <= '@') goto yy808; + if (yych <= 'Z') goto yy806; + if (yych <= '^') goto yy808; + goto yy806; } else { - if (yych <= '`') goto yy799; - if (yych <= 'z') goto yy797; - if (yych <= '~') goto yy799; - goto yy797; + if (yych <= '`') goto yy808; + if (yych <= 'z') goto yy806; + if (yych <= '~') goto yy808; + goto yy806; } } -yy793: - YYDEBUG(793, *YYCURSOR); +yy802: + YYDEBUG(802, *YYCURSOR); ++YYCURSOR; yych = *YYCURSOR; - goto yy805; -yy794: - YYDEBUG(794, *YYCURSOR); + goto yy814; +yy803: + YYDEBUG(803, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1171 "Zend/zend_language_scanner.l" +#line 1181 "Zend/zend_language_scanner.l" { zendlval->value.str.val = yytext; /* no copying - intentional */ zendlval->value.str.len = yyleng; @@ -7249,73 +7322,73 @@ yy794: HANDLE_NEWLINES(yytext, yyleng); return T_WHITESPACE; } -#line 7253 "Zend/zend_language_scanner.c" -yy795: - YYDEBUG(795, *YYCURSOR); +#line 7326 "Zend/zend_language_scanner.c" +yy804: + YYDEBUG(804, *YYCURSOR); ++YYCURSOR; - if ((yych = *YYCURSOR) == '>') goto yy802; -yy796: - YYDEBUG(796, *YYCURSOR); + if ((yych = *YYCURSOR) == '>') goto yy811; +yy805: + YYDEBUG(805, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1190 "Zend/zend_language_scanner.l" +#line 1200 "Zend/zend_language_scanner.l" { yyless(0); yy_pop_state(TSRMLS_C); goto restart; } -#line 7267 "Zend/zend_language_scanner.c" -yy797: - YYDEBUG(797, *YYCURSOR); +#line 7340 "Zend/zend_language_scanner.c" +yy806: + YYDEBUG(806, *YYCURSOR); ++YYCURSOR; yych = *YYCURSOR; - goto yy801; -yy798: - YYDEBUG(798, *YYCURSOR); + goto yy810; +yy807: + YYDEBUG(807, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1183 "Zend/zend_language_scanner.l" +#line 1193 "Zend/zend_language_scanner.l" { yy_pop_state(TSRMLS_C); zend_copy_value(zendlval, yytext, yyleng); zendlval->type = IS_STRING; return T_STRING; } -#line 7283 "Zend/zend_language_scanner.c" -yy799: - YYDEBUG(799, *YYCURSOR); +#line 7356 "Zend/zend_language_scanner.c" +yy808: + YYDEBUG(808, *YYCURSOR); yych = *++YYCURSOR; - goto yy796; -yy800: - YYDEBUG(800, *YYCURSOR); + goto yy805; +yy809: + YYDEBUG(809, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; -yy801: - YYDEBUG(801, *YYCURSOR); +yy810: + YYDEBUG(810, *YYCURSOR); if (yybm[0+yych] & 64) { - goto yy800; + goto yy809; } - goto yy798; -yy802: - YYDEBUG(802, *YYCURSOR); + goto yy807; +yy811: + YYDEBUG(811, *YYCURSOR); ++YYCURSOR; - YYDEBUG(803, *YYCURSOR); + YYDEBUG(812, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1179 "Zend/zend_language_scanner.l" +#line 1189 "Zend/zend_language_scanner.l" { return T_OBJECT_OPERATOR; } -#line 7308 "Zend/zend_language_scanner.c" -yy804: - YYDEBUG(804, *YYCURSOR); +#line 7381 "Zend/zend_language_scanner.c" +yy813: + YYDEBUG(813, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; -yy805: - YYDEBUG(805, *YYCURSOR); +yy814: + YYDEBUG(814, *YYCURSOR); if (yybm[0+yych] & 128) { - goto yy804; + goto yy813; } - goto yy794; + goto yy803; } /* *********************************** */ yyc_ST_LOOKING_FOR_VARNAME: @@ -7354,73 +7427,99 @@ yyc_ST_LOOKING_FOR_VARNAME: 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, }; - YYDEBUG(806, *YYCURSOR); + YYDEBUG(815, *YYCURSOR); YYFILL(2); yych = *YYCURSOR; if (yych <= '_') { - if (yych <= '@') goto yy810; - if (yych <= 'Z') goto yy808; - if (yych <= '^') goto yy810; + if (yych <= '@') goto yy819; + if (yych <= 'Z') goto yy817; + if (yych <= '^') goto yy819; } else { - if (yych <= '`') goto yy810; - if (yych <= 'z') goto yy808; - if (yych <= '~') goto yy810; + if (yych <= '`') goto yy819; + if (yych <= 'z') goto yy817; + if (yych <= '~') goto yy819; } -yy808: - YYDEBUG(808, *YYCURSOR); - ++YYCURSOR; - yych = *YYCURSOR; - goto yy813; -yy809: - YYDEBUG(809, *YYCURSOR); - yyleng = YYCURSOR - SCNG(yy_text); -#line 1466 "Zend/zend_language_scanner.l" - { - zend_copy_value(zendlval, yytext, yyleng); - zendlval->type = IS_STRING; - yy_pop_state(TSRMLS_C); - yy_push_state(ST_IN_SCRIPTING TSRMLS_CC); - return T_STRING_VARNAME; -} -#line 7386 "Zend/zend_language_scanner.c" -yy810: - YYDEBUG(810, *YYCURSOR); - ++YYCURSOR; - YYDEBUG(811, *YYCURSOR); +yy817: + YYDEBUG(817, *YYCURSOR); + yyaccept = 0; + yych = *(YYMARKER = ++YYCURSOR); + if (yych <= '_') { + if (yych <= '@') { + if (yych <= '/') goto yy818; + if (yych <= '9') goto yy821; + } else { + if (yych <= '[') goto yy821; + if (yych >= '_') goto yy821; + } + } else { + if (yych <= '|') { + if (yych <= '`') goto yy818; + if (yych <= 'z') goto yy821; + } else { + if (yych != '~') goto yy821; + } + } +yy818: + YYDEBUG(818, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1475 "Zend/zend_language_scanner.l" +#line 1486 "Zend/zend_language_scanner.l" { yyless(0); yy_pop_state(TSRMLS_C); yy_push_state(ST_IN_SCRIPTING TSRMLS_CC); goto restart; } -#line 7399 "Zend/zend_language_scanner.c" -yy812: - YYDEBUG(812, *YYCURSOR); +#line 7473 "Zend/zend_language_scanner.c" +yy819: + YYDEBUG(819, *YYCURSOR); + yych = *++YYCURSOR; + goto yy818; +yy820: + YYDEBUG(820, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; -yy813: - YYDEBUG(813, *YYCURSOR); +yy821: + YYDEBUG(821, *YYCURSOR); if (yybm[0+yych] & 128) { - goto yy812; + goto yy820; } - goto yy809; + if (yych == '[') goto yy823; + if (yych == '}') goto yy823; + YYDEBUG(822, *YYCURSOR); + YYCURSOR = YYMARKER; + goto yy818; +yy823: + YYDEBUG(823, *YYCURSOR); + ++YYCURSOR; + YYDEBUG(824, *YYCURSOR); + yyleng = YYCURSOR - SCNG(yy_text); +#line 1476 "Zend/zend_language_scanner.l" + { + yyless(yyleng - 1); + zend_copy_value(zendlval, yytext, yyleng); + zendlval->type = IS_STRING; + yy_pop_state(TSRMLS_C); + yy_push_state(ST_IN_SCRIPTING TSRMLS_CC); + return T_STRING_VARNAME; +} +#line 7507 "Zend/zend_language_scanner.c" } /* *********************************** */ yyc_ST_NOWDOC: - YYDEBUG(814, *YYCURSOR); + YYDEBUG(825, *YYCURSOR); YYFILL(1); yych = *YYCURSOR; - YYDEBUG(816, *YYCURSOR); + YYDEBUG(827, *YYCURSOR); ++YYCURSOR; - YYDEBUG(817, *YYCURSOR); + YYDEBUG(828, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2357 "Zend/zend_language_scanner.l" +#line 2370 "Zend/zend_language_scanner.l" { int newline = 0; + zend_heredoc_label *heredoc_label = zend_ptr_stack_top(&SCNG(heredoc_label_stack)); + if (YYCURSOR > YYLIMIT) { return 0; } @@ -7436,8 +7535,8 @@ yyc_ST_NOWDOC: /* fall through */ case '\n': /* Check for ending label on the next line */ - if (IS_LABEL_START(*YYCURSOR) && CG(heredoc_len) < YYLIMIT - YYCURSOR && !memcmp(YYCURSOR, CG(heredoc), CG(heredoc_len))) { - YYCTYPE *end = YYCURSOR + CG(heredoc_len); + if (IS_LABEL_START(*YYCURSOR) && heredoc_label->length < YYLIMIT - YYCURSOR && !memcmp(YYCURSOR, heredoc_label->label, heredoc_label->length)) { + YYCTYPE *end = YYCURSOR + heredoc_label->length; if (*end == ';') { end++; @@ -7472,7 +7571,7 @@ nowdoc_scan_done: HANDLE_NEWLINES(yytext, yyleng - newline); return T_ENCAPSED_AND_WHITESPACE; } -#line 7476 "Zend/zend_language_scanner.c" +#line 7575 "Zend/zend_language_scanner.c" /* *********************************** */ yyc_ST_VAR_OFFSET: { @@ -7510,76 +7609,76 @@ yyc_ST_VAR_OFFSET: 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, }; - YYDEBUG(818, *YYCURSOR); + YYDEBUG(829, *YYCURSOR); YYFILL(3); yych = *YYCURSOR; if (yych <= '/') { if (yych <= ' ') { if (yych <= '\f') { - if (yych <= 0x08) goto yy832; - if (yych <= '\n') goto yy828; - goto yy832; + if (yych <= 0x08) goto yy843; + if (yych <= '\n') goto yy839; + goto yy843; } else { - if (yych <= '\r') goto yy828; - if (yych <= 0x1F) goto yy832; - goto yy828; + if (yych <= '\r') goto yy839; + if (yych <= 0x1F) goto yy843; + goto yy839; } } else { if (yych <= '$') { - if (yych <= '"') goto yy827; - if (yych <= '#') goto yy828; - goto yy823; + if (yych <= '"') goto yy838; + if (yych <= '#') goto yy839; + goto yy834; } else { - if (yych == '\'') goto yy828; - goto yy827; + if (yych == '\'') goto yy839; + goto yy838; } } } else { if (yych <= '\\') { if (yych <= '@') { - if (yych <= '0') goto yy820; - if (yych <= '9') goto yy822; - goto yy827; + if (yych <= '0') goto yy831; + if (yych <= '9') goto yy833; + goto yy838; } else { - if (yych <= 'Z') goto yy830; - if (yych <= '[') goto yy827; - goto yy828; + if (yych <= 'Z') goto yy841; + if (yych <= '[') goto yy838; + goto yy839; } } else { if (yych <= '_') { - if (yych <= ']') goto yy825; - if (yych <= '^') goto yy827; - goto yy830; + if (yych <= ']') goto yy836; + if (yych <= '^') goto yy838; + goto yy841; } else { - if (yych <= '`') goto yy827; - if (yych <= 'z') goto yy830; - if (yych <= '~') goto yy827; - goto yy830; + if (yych <= '`') goto yy838; + if (yych <= 'z') goto yy841; + if (yych <= '~') goto yy838; + goto yy841; } } } -yy820: - YYDEBUG(820, *YYCURSOR); +yy831: + YYDEBUG(831, *YYCURSOR); yyaccept = 0; yych = *(YYMARKER = ++YYCURSOR); if (yych <= 'W') { if (yych <= '9') { - if (yych >= '0') goto yy844; + if (yych >= '0') goto yy855; } else { - if (yych == 'B') goto yy841; + if (yych == 'B') goto yy852; } } else { if (yych <= 'b') { - if (yych <= 'X') goto yy843; - if (yych >= 'b') goto yy841; + if (yych <= 'X') goto yy854; + if (yych >= 'b') goto yy852; } else { - if (yych == 'x') goto yy843; + if (yych == 'x') goto yy854; } } -yy821: - YYDEBUG(821, *YYCURSOR); +yy832: + YYDEBUG(832, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1553 "Zend/zend_language_scanner.l" +#line 1564 "Zend/zend_language_scanner.l" { /* Offset could be treated as a long */ if (yyleng < MAX_LENGTH_OF_LONG - 1 || (yyleng == MAX_LENGTH_OF_LONG - 1 && strcmp(yytext, long_min_digits) < 0)) { zendlval->value.lval = strtol(yytext, NULL, 10); @@ -7591,81 +7690,81 @@ yy821: } return T_NUM_STRING; } -#line 7595 "Zend/zend_language_scanner.c" -yy822: - YYDEBUG(822, *YYCURSOR); +#line 7694 "Zend/zend_language_scanner.c" +yy833: + YYDEBUG(833, *YYCURSOR); yych = *++YYCURSOR; - goto yy840; -yy823: - YYDEBUG(823, *YYCURSOR); + goto yy851; +yy834: + YYDEBUG(834, *YYCURSOR); ++YYCURSOR; if ((yych = *YYCURSOR) <= '_') { - if (yych <= '@') goto yy824; - if (yych <= 'Z') goto yy836; - if (yych >= '_') goto yy836; + if (yych <= '@') goto yy835; + if (yych <= 'Z') goto yy847; + if (yych >= '_') goto yy847; } else { - if (yych <= '`') goto yy824; - if (yych <= 'z') goto yy836; - if (yych >= 0x7F) goto yy836; + if (yych <= '`') goto yy835; + if (yych <= 'z') goto yy847; + if (yych >= 0x7F) goto yy847; } -yy824: - YYDEBUG(824, *YYCURSOR); +yy835: + YYDEBUG(835, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1885 "Zend/zend_language_scanner.l" +#line 1896 "Zend/zend_language_scanner.l" { /* Only '[' can be valid, but returning other tokens will allow a more explicit parse error */ return yytext[0]; } -#line 7620 "Zend/zend_language_scanner.c" -yy825: - YYDEBUG(825, *YYCURSOR); +#line 7719 "Zend/zend_language_scanner.c" +yy836: + YYDEBUG(836, *YYCURSOR); ++YYCURSOR; - YYDEBUG(826, *YYCURSOR); + YYDEBUG(837, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1880 "Zend/zend_language_scanner.l" +#line 1891 "Zend/zend_language_scanner.l" { yy_pop_state(TSRMLS_C); return ']'; } -#line 7631 "Zend/zend_language_scanner.c" -yy827: - YYDEBUG(827, *YYCURSOR); +#line 7730 "Zend/zend_language_scanner.c" +yy838: + YYDEBUG(838, *YYCURSOR); yych = *++YYCURSOR; - goto yy824; -yy828: - YYDEBUG(828, *YYCURSOR); + goto yy835; +yy839: + YYDEBUG(839, *YYCURSOR); ++YYCURSOR; - YYDEBUG(829, *YYCURSOR); + YYDEBUG(840, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1890 "Zend/zend_language_scanner.l" +#line 1901 "Zend/zend_language_scanner.l" { /* Invalid rule to return a more explicit parse error with proper line number */ yyless(0); yy_pop_state(TSRMLS_C); return T_ENCAPSED_AND_WHITESPACE; } -#line 7648 "Zend/zend_language_scanner.c" -yy830: - YYDEBUG(830, *YYCURSOR); +#line 7747 "Zend/zend_language_scanner.c" +yy841: + YYDEBUG(841, *YYCURSOR); ++YYCURSOR; yych = *YYCURSOR; - goto yy835; -yy831: - YYDEBUG(831, *YYCURSOR); + goto yy846; +yy842: + YYDEBUG(842, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1897 "Zend/zend_language_scanner.l" +#line 1908 "Zend/zend_language_scanner.l" { zend_copy_value(zendlval, yytext, yyleng); zendlval->type = IS_STRING; return T_STRING; } -#line 7663 "Zend/zend_language_scanner.c" -yy832: - YYDEBUG(832, *YYCURSOR); +#line 7762 "Zend/zend_language_scanner.c" +yy843: + YYDEBUG(843, *YYCURSOR); ++YYCURSOR; - YYDEBUG(833, *YYCURSOR); + YYDEBUG(844, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 2413 "Zend/zend_language_scanner.l" +#line 2428 "Zend/zend_language_scanner.l" { if (YYCURSOR > YYLIMIT) { return 0; @@ -7674,118 +7773,118 @@ yy832: zend_error(E_COMPILE_WARNING,"Unexpected character in input: '%c' (ASCII=%d) state=%d", yytext[0], yytext[0], YYSTATE); goto restart; } -#line 7678 "Zend/zend_language_scanner.c" -yy834: - YYDEBUG(834, *YYCURSOR); +#line 7777 "Zend/zend_language_scanner.c" +yy845: + YYDEBUG(845, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; -yy835: - YYDEBUG(835, *YYCURSOR); +yy846: + YYDEBUG(846, *YYCURSOR); if (yybm[0+yych] & 16) { - goto yy834; + goto yy845; } - goto yy831; -yy836: - YYDEBUG(836, *YYCURSOR); + goto yy842; +yy847: + YYDEBUG(847, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(837, *YYCURSOR); + YYDEBUG(848, *YYCURSOR); if (yych <= '^') { if (yych <= '9') { - if (yych >= '0') goto yy836; + if (yych >= '0') goto yy847; } else { - if (yych <= '@') goto yy838; - if (yych <= 'Z') goto yy836; + if (yych <= '@') goto yy849; + if (yych <= 'Z') goto yy847; } } else { if (yych <= '`') { - if (yych <= '_') goto yy836; + if (yych <= '_') goto yy847; } else { - if (yych <= 'z') goto yy836; - if (yych >= 0x7F) goto yy836; + if (yych <= 'z') goto yy847; + if (yych >= 0x7F) goto yy847; } } -yy838: - YYDEBUG(838, *YYCURSOR); +yy849: + YYDEBUG(849, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1874 "Zend/zend_language_scanner.l" +#line 1885 "Zend/zend_language_scanner.l" { zend_copy_value(zendlval, (yytext+1), (yyleng-1)); zendlval->type = IS_STRING; return T_VARIABLE; } -#line 7720 "Zend/zend_language_scanner.c" -yy839: - YYDEBUG(839, *YYCURSOR); +#line 7819 "Zend/zend_language_scanner.c" +yy850: + YYDEBUG(850, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; -yy840: - YYDEBUG(840, *YYCURSOR); +yy851: + YYDEBUG(851, *YYCURSOR); if (yybm[0+yych] & 32) { - goto yy839; + goto yy850; } - goto yy821; -yy841: - YYDEBUG(841, *YYCURSOR); + goto yy832; +yy852: + YYDEBUG(852, *YYCURSOR); yych = *++YYCURSOR; if (yybm[0+yych] & 128) { - goto yy849; + goto yy860; } -yy842: - YYDEBUG(842, *YYCURSOR); +yy853: + YYDEBUG(853, *YYCURSOR); YYCURSOR = YYMARKER; - goto yy821; -yy843: - YYDEBUG(843, *YYCURSOR); + goto yy832; +yy854: + YYDEBUG(854, *YYCURSOR); yych = *++YYCURSOR; if (yybm[0+yych] & 64) { - goto yy847; + goto yy858; } - goto yy842; -yy844: - YYDEBUG(844, *YYCURSOR); + goto yy853; +yy855: + YYDEBUG(855, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(845, *YYCURSOR); - if (yych <= '/') goto yy846; - if (yych <= '9') goto yy844; -yy846: - YYDEBUG(846, *YYCURSOR); + YYDEBUG(856, *YYCURSOR); + if (yych <= '/') goto yy857; + if (yych <= '9') goto yy855; +yy857: + YYDEBUG(857, *YYCURSOR); yyleng = YYCURSOR - SCNG(yy_text); -#line 1565 "Zend/zend_language_scanner.l" +#line 1576 "Zend/zend_language_scanner.l" { /* Offset must be treated as a string */ zendlval->value.str.val = (char *)estrndup(yytext, yyleng); zendlval->value.str.len = yyleng; zendlval->type = IS_STRING; return T_NUM_STRING; } -#line 7767 "Zend/zend_language_scanner.c" -yy847: - YYDEBUG(847, *YYCURSOR); +#line 7866 "Zend/zend_language_scanner.c" +yy858: + YYDEBUG(858, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(848, *YYCURSOR); + YYDEBUG(859, *YYCURSOR); if (yybm[0+yych] & 64) { - goto yy847; + goto yy858; } - goto yy846; -yy849: - YYDEBUG(849, *YYCURSOR); + goto yy857; +yy860: + YYDEBUG(860, *YYCURSOR); ++YYCURSOR; YYFILL(1); yych = *YYCURSOR; - YYDEBUG(850, *YYCURSOR); + YYDEBUG(861, *YYCURSOR); if (yybm[0+yych] & 128) { - goto yy849; + goto yy860; } - goto yy846; + goto yy857; } } -#line 2422 "Zend/zend_language_scanner.l" +#line 2437 "Zend/zend_language_scanner.l" } diff --git a/Zend/zend_language_scanner.h b/Zend/zend_language_scanner.h index 826ad7aba6..03ca911262 100644 --- a/Zend/zend_language_scanner.h +++ b/Zend/zend_language_scanner.h @@ -31,6 +31,7 @@ typedef struct _zend_lex_state { unsigned char *yy_limit; int yy_state; zend_stack state_stack; + zend_ptr_stack heredoc_label_stack; zend_file_handle *in; uint lineno; @@ -50,6 +51,10 @@ typedef struct _zend_lex_state { const zend_encoding *script_encoding; } zend_lex_state; +typedef struct _zend_heredoc_label { + char *label; + int length; +} zend_heredoc_label; BEGIN_EXTERN_C() int zend_compare_file_handles(zend_file_handle *fh1, zend_file_handle *fh2); diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l index cc54557b3b..d44ba20e1b 100644 --- a/Zend/zend_language_scanner.l +++ b/Zend/zend_language_scanner.l @@ -178,22 +178,23 @@ static void yy_scan_buffer(char *str, unsigned int len TSRMLS_DC) void startup_scanner(TSRMLS_D) { CG(parse_error) = 0; - CG(heredoc) = NULL; - CG(heredoc_len) = 0; CG(doc_comment) = NULL; CG(doc_comment_len) = 0; zend_stack_init(&SCNG(state_stack)); + zend_ptr_stack_init(&SCNG(heredoc_label_stack)); +} + +static void heredoc_label_dtor(zend_heredoc_label *heredoc_label) { + efree(heredoc_label->label); } void shutdown_scanner(TSRMLS_D) { - if (CG(heredoc)) { - efree(CG(heredoc)); - CG(heredoc_len)=0; - } CG(parse_error) = 0; - zend_stack_destroy(&SCNG(state_stack)); RESET_DOC_COMMENT(); + zend_stack_destroy(&SCNG(state_stack)); + zend_ptr_stack_clean(&SCNG(heredoc_label_stack), (void (*)(void *)) &heredoc_label_dtor, 1); + zend_ptr_stack_destroy(&SCNG(heredoc_label_stack)); } ZEND_API void zend_save_lexical_state(zend_lex_state *lex_state TSRMLS_DC) @@ -208,6 +209,9 @@ ZEND_API void zend_save_lexical_state(zend_lex_state *lex_state TSRMLS_DC) lex_state->state_stack = SCNG(state_stack); zend_stack_init(&SCNG(state_stack)); + lex_state->heredoc_label_stack = SCNG(heredoc_label_stack); + zend_ptr_stack_init(&SCNG(heredoc_label_stack)); + lex_state->in = SCNG(yy_in); lex_state->yy_state = YYSTATE; lex_state->filename = zend_get_compiled_filename(TSRMLS_C); @@ -234,6 +238,10 @@ ZEND_API void zend_restore_lexical_state(zend_lex_state *lex_state TSRMLS_DC) zend_stack_destroy(&SCNG(state_stack)); SCNG(state_stack) = lex_state->state_stack; + zend_ptr_stack_clean(&SCNG(heredoc_label_stack), (void (*)(void *)) &heredoc_label_dtor, 1); + zend_ptr_stack_destroy(&SCNG(heredoc_label_stack)); + SCNG(heredoc_label_stack) = lex_state->heredoc_label_stack; + SCNG(yy_in) = lex_state->in; YYSETCONDITION(lex_state->yy_state); CG(zend_lineno) = lex_state->lineno; @@ -250,12 +258,6 @@ ZEND_API void zend_restore_lexical_state(zend_lex_state *lex_state TSRMLS_DC) SCNG(input_filter) = lex_state->input_filter; SCNG(output_filter) = lex_state->output_filter; SCNG(script_encoding) = lex_state->script_encoding; - - if (CG(heredoc)) { - efree(CG(heredoc)); - CG(heredoc) = NULL; - CG(heredoc_len) = 0; - } } ZEND_API void zend_destroy_file_handle(zend_file_handle *file_handle TSRMLS_DC) @@ -1035,6 +1037,10 @@ NEWLINE ("\r"|"\n"|"\r\n") return T_RETURN; } +<ST_IN_SCRIPTING>"yield" { + return T_YIELD; +} + <ST_IN_SCRIPTING>"try" { return T_TRY; } @@ -1043,6 +1049,10 @@ NEWLINE ("\r"|"\n"|"\r\n") return T_CATCH; } +<ST_IN_SCRIPTING>"finally" { + return T_FINALLY; +} + <ST_IN_SCRIPTING>"throw" { return T_THROW; } @@ -1463,7 +1473,8 @@ NEWLINE ("\r"|"\n"|"\r\n") } -<ST_LOOKING_FOR_VARNAME>{LABEL} { +<ST_LOOKING_FOR_VARNAME>{LABEL}[[}] { + yyless(yyleng - 1); zend_copy_value(zendlval, yytext, yyleng); zendlval->type = IS_STRING; yy_pop_state(TSRMLS_C); @@ -2106,38 +2117,35 @@ inline_html: <ST_IN_SCRIPTING>b?"<<<"{TABS_AND_SPACES}({LABEL}|([']{LABEL}['])|(["]{LABEL}["])){NEWLINE} { char *s; int bprefix = (yytext[0] != '<') ? 1 : 0; - - /* save old heredoc label */ - Z_STRVAL_P(zendlval) = CG(heredoc); - Z_STRLEN_P(zendlval) = CG(heredoc_len); + zend_heredoc_label *heredoc_label = emalloc(sizeof(zend_heredoc_label)); CG(zend_lineno)++; - CG(heredoc_len) = yyleng-bprefix-3-1-(yytext[yyleng-2]=='\r'?1:0); + heredoc_label->length = yyleng-bprefix-3-1-(yytext[yyleng-2]=='\r'?1:0); s = yytext+bprefix+3; while ((*s == ' ') || (*s == '\t')) { s++; - CG(heredoc_len)--; + heredoc_label->length--; } if (*s == '\'') { s++; - CG(heredoc_len) -= 2; + heredoc_label->length -= 2; BEGIN(ST_NOWDOC); } else { if (*s == '"') { s++; - CG(heredoc_len) -= 2; + heredoc_label->length -= 2; } BEGIN(ST_HEREDOC); } - CG(heredoc) = estrndup(s, CG(heredoc_len)); + heredoc_label->label = estrndup(s, heredoc_label->length); /* Check for ending label on the next line */ - if (CG(heredoc_len) < YYLIMIT - YYCURSOR && !memcmp(YYCURSOR, s, CG(heredoc_len))) { - YYCTYPE *end = YYCURSOR + CG(heredoc_len); + if (heredoc_label->length < YYLIMIT - YYCURSOR && !memcmp(YYCURSOR, s, heredoc_label->length)) { + YYCTYPE *end = YYCURSOR + heredoc_label->length; if (*end == ';') { end++; @@ -2148,6 +2156,8 @@ inline_html: } } + zend_ptr_stack_push(&SCNG(heredoc_label_stack), (void *) heredoc_label); + return T_START_HEREDOC; } @@ -2159,13 +2169,14 @@ inline_html: <ST_END_HEREDOC>{ANY_CHAR} { - YYCURSOR += CG(heredoc_len) - 1; - yyleng = CG(heredoc_len); + zend_heredoc_label *heredoc_label = zend_ptr_stack_pop(&SCNG(heredoc_label_stack)); + + YYCURSOR += heredoc_label->length - 1; + yyleng = heredoc_label->length; + + heredoc_label_dtor(heredoc_label); + efree(heredoc_label); - Z_STRVAL_P(zendlval) = CG(heredoc); - Z_STRLEN_P(zendlval) = CG(heredoc_len); - CG(heredoc) = NULL; - CG(heredoc_len) = 0; BEGIN(ST_IN_SCRIPTING); return T_END_HEREDOC; } @@ -2285,6 +2296,8 @@ double_quotes_scan_done: <ST_HEREDOC>{ANY_CHAR} { int newline = 0; + zend_heredoc_label *heredoc_label = zend_ptr_stack_top(&SCNG(heredoc_label_stack)); + if (YYCURSOR > YYLIMIT) { return 0; } @@ -2300,8 +2313,8 @@ double_quotes_scan_done: /* fall through */ case '\n': /* Check for ending label on the next line */ - if (IS_LABEL_START(*YYCURSOR) && CG(heredoc_len) < YYLIMIT - YYCURSOR && !memcmp(YYCURSOR, CG(heredoc), CG(heredoc_len))) { - YYCTYPE *end = YYCURSOR + CG(heredoc_len); + if (IS_LABEL_START(*YYCURSOR) && heredoc_label->length < YYLIMIT - YYCURSOR && !memcmp(YYCURSOR, heredoc_label->label, heredoc_label->length)) { + YYCTYPE *end = YYCURSOR + heredoc_label->length; if (*end == ';') { end++; @@ -2357,6 +2370,8 @@ heredoc_scan_done: <ST_NOWDOC>{ANY_CHAR} { int newline = 0; + zend_heredoc_label *heredoc_label = zend_ptr_stack_top(&SCNG(heredoc_label_stack)); + if (YYCURSOR > YYLIMIT) { return 0; } @@ -2372,8 +2387,8 @@ heredoc_scan_done: /* fall through */ case '\n': /* Check for ending label on the next line */ - if (IS_LABEL_START(*YYCURSOR) && CG(heredoc_len) < YYLIMIT - YYCURSOR && !memcmp(YYCURSOR, CG(heredoc), CG(heredoc_len))) { - YYCTYPE *end = YYCURSOR + CG(heredoc_len); + if (IS_LABEL_START(*YYCURSOR) && heredoc_label->length < YYLIMIT - YYCURSOR && !memcmp(YYCURSOR, heredoc_label->label, heredoc_label->length)) { + YYCTYPE *end = YYCURSOR + heredoc_label->length; if (*end == ';') { end++; diff --git a/Zend/zend_language_scanner_defs.h b/Zend/zend_language_scanner_defs.h index 9bde2a0e14..5926e3c61d 100644 --- a/Zend/zend_language_scanner_defs.h +++ b/Zend/zend_language_scanner_defs.h @@ -1,4 +1,4 @@ -/* Generated by re2c 0.13.5 on Wed Nov 14 17:46:56 2012 */ +/* Generated by re2c 0.13.5 */ #line 3 "Zend/zend_language_scanner_defs.h" enum YYCONDTYPE { diff --git a/Zend/zend_llist.c b/Zend/zend_llist.c index 8aa369b502..20f847c781 100644 --- a/Zend/zend_llist.c +++ b/Zend/zend_llist.c @@ -91,15 +91,13 @@ ZEND_API void zend_llist_prepend_element(zend_llist *l, void *element) ZEND_API void zend_llist_del_element(zend_llist *l, void *element, int (*compare)(void *element1, void *element2)) { zend_llist_element *current=l->head; - zend_llist_element *next; while (current) { - next = current->next; if (compare(current->data, element)) { DEL_LLIST_ELEMENT(current, l); break; } - current = next; + current = current->next; } } diff --git a/Zend/zend_modules.h b/Zend/zend_modules.h index 1e420347f5..d4adcf5aac 100644 --- a/Zend/zend_modules.h +++ b/Zend/zend_modules.h @@ -33,7 +33,7 @@ #define ZEND_MODULE_INFO_FUNC_ARGS zend_module_entry *zend_module TSRMLS_DC #define ZEND_MODULE_INFO_FUNC_ARGS_PASSTHRU zend_module TSRMLS_CC -#define ZEND_MODULE_API_NO 20100525 +#define ZEND_MODULE_API_NO 20121212 #ifdef ZTS #define USING_ZTS 1 #else diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index e673f0197c..db0a40035b 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -70,6 +70,9 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz op_array->T = 0; + op_array->nested_calls = 0; + op_array->used_stack = 0; + op_array->function_name = NULL; op_array->filename = zend_get_compiled_filename(TSRMLS_C); op_array->doc_comment = NULL; @@ -87,6 +90,7 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz op_array->static_variables = NULL; op_array->last_try_catch = 0; + op_array->has_finally_block = 0; op_array->this_var = -1; @@ -479,6 +483,170 @@ static void zend_extension_op_array_handler(zend_extension *extension, zend_op_a } } +static void zend_check_finally_breakout(zend_op_array *op_array, zend_uint op_num, zend_uint dst_num TSRMLS_DC) +{ + zend_uint i; + + for (i = 0; i < op_array->last_try_catch; i++) { + if (op_array->try_catch_array[i].try_op > op_num) { + break; + } + if ((op_num >= op_array->try_catch_array[i].finally_op + && op_num <= op_array->try_catch_array[i].finally_end) + && (dst_num > op_array->try_catch_array[i].finally_end + || dst_num < op_array->try_catch_array[i].finally_op)) { + CG(in_compilation) = 1; + CG(active_op_array) = op_array; + CG(zend_lineno) = op_array->opcodes[op_num].lineno; + zend_error(E_COMPILE_ERROR, "jump out of a finally block is disallowed"); + } + } +} + +static void zend_resolve_finally_call(zend_op_array *op_array, zend_uint op_num, zend_uint dst_num TSRMLS_DC) +{ + zend_uint start_op; + zend_op *opline; + zend_uint i = op_array->last_try_catch; + + if (dst_num != (zend_uint)-1) { + zend_check_finally_breakout(op_array, op_num, dst_num TSRMLS_CC); + } + + /* the backward order is mater */ + while (i > 0) { + i--; + if (op_array->try_catch_array[i].finally_op && + op_num >= op_array->try_catch_array[i].try_op && + op_num < op_array->try_catch_array[i].finally_op - 1 && + (dst_num < op_array->try_catch_array[i].try_op || + dst_num > op_array->try_catch_array[i].finally_end)) { + /* we have a jump out of try block that needs executing finally */ + + /* generate a FAST_CALL to finally block */ + start_op = get_next_op_number(op_array); + + opline = get_next_op(op_array TSRMLS_CC); + opline->opcode = ZEND_FAST_CALL; + SET_UNUSED(opline->op1); + SET_UNUSED(opline->op2); + opline->op1.opline_num = op_array->try_catch_array[i].finally_op; + if (op_array->try_catch_array[i].catch_op) { + opline->extended_value = 1; + opline->op2.opline_num = op_array->try_catch_array[i].catch_op; + } + + /* generate a sequence of FAST_CALL to upward finally block */ + while (i > 0) { + i--; + if (op_array->try_catch_array[i].finally_op && + op_num >= op_array->try_catch_array[i].try_op && + op_num < op_array->try_catch_array[i].finally_op - 1 && + (dst_num < op_array->try_catch_array[i].try_op || + dst_num > op_array->try_catch_array[i].finally_end)) { + + opline = get_next_op(op_array TSRMLS_CC); + opline->opcode = ZEND_FAST_CALL; + SET_UNUSED(opline->op1); + SET_UNUSED(opline->op2); + opline->op1.opline_num = op_array->try_catch_array[i].finally_op; + } + } + + /* Finish the sequence with original opcode */ + opline = get_next_op(op_array TSRMLS_CC); + *opline = op_array->opcodes[op_num]; + + /* Replace original opcode with jump to this sequence */ + opline = op_array->opcodes + op_num; + opline->opcode = ZEND_JMP; + SET_UNUSED(opline->op1); + SET_UNUSED(opline->op2); + opline->op1.opline_num = start_op; + + break; + } + } +} + +static void zend_resolve_finally_ret(zend_op_array *op_array, zend_uint op_num TSRMLS_DC) +{ + int i; + zend_uint catch_op_num = 0, finally_op_num = 0; + + for (i = 0; i < op_array->last_try_catch; i++) { + if (op_array->try_catch_array[i].try_op > op_num) { + break; + } + if (op_num < op_array->try_catch_array[i].finally_op) { + finally_op_num = op_array->try_catch_array[i].finally_op; + } + if (op_num < op_array->try_catch_array[i].catch_op) { + catch_op_num = op_array->try_catch_array[i].catch_op; + } + } + + if (finally_op_num && (!catch_op_num || catch_op_num >= finally_op_num)) { + /* in case of unhandled exception return to upward finally block */ + op_array->opcodes[op_num].extended_value = ZEND_FAST_RET_TO_FINALLY; + op_array->opcodes[op_num].op2.opline_num = finally_op_num; + } else if (catch_op_num) { + /* in case of unhandled exception return to upward catch block */ + op_array->opcodes[op_num].extended_value = ZEND_FAST_RET_TO_CATCH; + op_array->opcodes[op_num].op2.opline_num = catch_op_num; + } +} + +static void zend_resolve_finally_calls(zend_op_array *op_array TSRMLS_DC) +{ + zend_uint i; + zend_op *opline; + + for (i = 0; i < op_array->last; i++) { + opline = op_array->opcodes + i; + switch (opline->opcode) { + case ZEND_RETURN: + case ZEND_RETURN_BY_REF: + case ZEND_GENERATOR_RETURN: + zend_resolve_finally_call(op_array, i, (zend_uint)-1 TSRMLS_CC); + break; + case ZEND_BRK: + case ZEND_CONT: + { + int nest_levels, array_offset; + zend_brk_cont_element *jmp_to; + + nest_levels = Z_LVAL(op_array->literals[opline->op2.constant].constant); + array_offset = opline->op1.opline_num; + do { + jmp_to = &op_array->brk_cont_array[array_offset]; + if (nest_levels > 1) { + array_offset = jmp_to->parent; + } + } while (--nest_levels > 0); + zend_resolve_finally_call(op_array, i, opline->opcode == ZEND_BRK ? jmp_to->brk : jmp_to->cont TSRMLS_CC); + break; + } + case ZEND_GOTO: + if (Z_TYPE(op_array->literals[opline->op2.constant].constant) != IS_LONG) { + zend_uint num = opline->op2.constant; + opline->op2.zv = &op_array->literals[opline->op2.constant].constant; + zend_resolve_goto_label(op_array, opline, 1 TSRMLS_CC); + opline->op2.constant = num; + } + /* break omitted intentionally */ + case ZEND_JMP: + zend_resolve_finally_call(op_array, i, opline->op1.opline_num TSRMLS_CC); + break; + case ZEND_FAST_RET: + zend_resolve_finally_ret(op_array, i TSRMLS_CC); + break; + default: + break; + } + } +} + ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC) { zend_op *opline, *end; @@ -486,6 +654,9 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC) if (op_array->type!=ZEND_USER_FUNCTION && op_array->type!=ZEND_EVAL_CODE) { return 0; } + if (op_array->has_finally_block) { + zend_resolve_finally_calls(op_array TSRMLS_CC); + } if (CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO) { zend_update_extended_info(op_array TSRMLS_CC); } @@ -522,6 +693,7 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC) } /* break omitted intentionally */ case ZEND_JMP: + case ZEND_FAST_CALL: opline->op1.jmp_addr = &op_array->opcodes[opline->op1.opline_num]; break; case ZEND_JMPZ: @@ -532,6 +704,17 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC) case ZEND_JMP_SET_VAR: opline->op2.jmp_addr = &op_array->opcodes[opline->op2.opline_num]; break; + case ZEND_RETURN: + case ZEND_RETURN_BY_REF: + if (op_array->fn_flags & ZEND_ACC_GENERATOR) { + if (opline->op1_type != IS_CONST || Z_TYPE_P(opline->op1.zv) != IS_NULL) { + CG(zend_lineno) = opline->lineno; + zend_error(E_COMPILE_ERROR, "Generators cannot return values using \"return\""); + } + + opline->opcode = ZEND_GENERATOR_RETURN; + } + break; } ZEND_VM_SET_OPCODE_HANDLER(opline); opline++; diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 594f1f1057..bccccd96be 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -42,6 +42,43 @@ static _locale_t current_locale = NULL; #define TYPE_PAIR(t1,t2) (((t1) << 4) | (t2)) +static const unsigned char tolower_map[256] = { +0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, +0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, +0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f, +0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, +0x40,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f, +0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x5b,0x5c,0x5d,0x5e,0x5f, +0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f, +0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f, +0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f, +0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f, +0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf, +0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf, +0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf, +0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf, +0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef, +0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff +}; + +#define zend_tolower_ascii(c) (tolower_map[(unsigned char)(c)]) + +/** + * Functions using locale lowercase: + zend_binary_strncasecmp_l + zend_binary_strcasecmp_l + zend_binary_zval_strcasecmp + zend_binary_zval_strncasecmp + string_compare_function_ex + string_case_compare_function + * Functions using ascii lowercase: + zend_str_tolower_copy + zend_str_tolower_dup + zend_str_tolower + zend_binary_strcasecmp + zend_binary_strncasecmp + */ + ZEND_API int zend_atoi(const char *str, int str_len) /* {{{ */ { int retval; @@ -1911,7 +1948,7 @@ ZEND_API char *zend_str_tolower_copy(char *dest, const char *source, unsigned in register unsigned char *end = str + length; while (str < end) { - *result++ = zend_tolower((int)*str++); + *result++ = zend_tolower_ascii(*str++); } *result = '\0'; @@ -1931,7 +1968,7 @@ ZEND_API void zend_str_tolower(char *str, unsigned int length) /* {{{ */ register unsigned char *end = p + length; while (p < end) { - *p = zend_tolower((int)*p); + *p = zend_tolower_ascii(*p); p++; } } @@ -1980,6 +2017,49 @@ ZEND_API int zend_binary_strcasecmp(const char *s1, uint len1, const char *s2, u len = MIN(len1, len2); while (len--) { + c1 = zend_tolower_ascii(*(unsigned char *)s1++); + c2 = zend_tolower_ascii(*(unsigned char *)s2++); + if (c1 != c2) { + return c1 - c2; + } + } + + return len1 - len2; +} +/* }}} */ + +ZEND_API int zend_binary_strncasecmp(const char *s1, uint len1, const char *s2, uint len2, uint length) /* {{{ */ +{ + int len; + int c1, c2; + + if (s1 == s2) { + return 0; + } + len = MIN(length, MIN(len1, len2)); + while (len--) { + c1 = zend_tolower_ascii(*(unsigned char *)s1++); + c2 = zend_tolower_ascii(*(unsigned char *)s2++); + if (c1 != c2) { + return c1 - c2; + } + } + + return MIN(length, len1) - MIN(length, len2); +} +/* }}} */ + +ZEND_API int zend_binary_strcasecmp_l(const char *s1, uint len1, const char *s2, uint len2) /* {{{ */ +{ + int len; + int c1, c2; + + if (s1 == s2) { + return 0; + } + + len = MIN(len1, len2); + while (len--) { c1 = zend_tolower((int)*(unsigned char *)s1++); c2 = zend_tolower((int)*(unsigned char *)s2++); if (c1 != c2) { @@ -1991,7 +2071,7 @@ ZEND_API int zend_binary_strcasecmp(const char *s1, uint len1, const char *s2, u } /* }}} */ -ZEND_API int zend_binary_strncasecmp(const char *s1, uint len1, const char *s2, uint len2, uint length) /* {{{ */ +ZEND_API int zend_binary_strncasecmp_l(const char *s1, uint len1, const char *s2, uint len2, uint length) /* {{{ */ { int len; int c1, c2; @@ -2026,13 +2106,13 @@ ZEND_API int zend_binary_zval_strncmp(zval *s1, zval *s2, zval *s3) /* {{{ */ ZEND_API int zend_binary_zval_strcasecmp(zval *s1, zval *s2) /* {{{ */ { - return zend_binary_strcasecmp(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2)); + return zend_binary_strcasecmp_l(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2)); } /* }}} */ ZEND_API int zend_binary_zval_strncasecmp(zval *s1, zval *s2, zval *s3) /* {{{ */ { - return zend_binary_strncasecmp(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2), Z_LVAL_P(s3)); + return zend_binary_strncasecmp_l(Z_STRVAL_P(s1), Z_STRLEN_P(s1), Z_STRVAL_P(s2), Z_STRLEN_P(s2), Z_LVAL_P(s3)); } /* }}} */ @@ -2067,7 +2147,7 @@ ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2) /* {{{ */ } else if (ret2!=IS_DOUBLE) { if (oflow1) { ZVAL_LONG(result, oflow1); - return; + return; } dval2 = (double) lval2; } else if (dval1 == dval2 && !zend_finite(dval1)) { diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h index 02a96dd26e..d3f5e5a3d1 100644 --- a/Zend/zend_operators.h +++ b/Zend/zend_operators.h @@ -340,6 +340,7 @@ ZEND_API int zend_binary_strcmp(const char *s1, uint len1, const char *s2, uint ZEND_API int zend_binary_strncmp(const char *s1, uint len1, const char *s2, uint len2, uint length); ZEND_API int zend_binary_strcasecmp(const char *s1, uint len1, const char *s2, uint len2); ZEND_API int zend_binary_strncasecmp(const char *s1, uint len1, const char *s2, uint len2, uint length); +ZEND_API int zend_binary_strncasecmp_l(const char *s1, uint len1, const char *s2, uint len2, uint length); ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2); ZEND_API void zend_compare_symbol_tables(zval *result, HashTable *ht1, HashTable *ht2 TSRMLS_DC); diff --git a/Zend/zend_ptr_stack.c b/Zend/zend_ptr_stack.c index 7d2fa2d297..9dbdb3ddd7 100644 --- a/Zend/zend_ptr_stack.c +++ b/Zend/zend_ptr_stack.c @@ -110,7 +110,6 @@ ZEND_API int zend_ptr_stack_num_elements(zend_ptr_stack *stack) { return stack->top; } - /* * Local variables: * tab-width: 4 diff --git a/Zend/zend_ptr_stack.h b/Zend/zend_ptr_stack.h index e2e7705764..1099240796 100644 --- a/Zend/zend_ptr_stack.h +++ b/Zend/zend_ptr_stack.h @@ -111,6 +111,11 @@ static zend_always_inline void *zend_ptr_stack_pop(zend_ptr_stack *stack) return *(--stack->top_element); } +static inline void *zend_ptr_stack_top(zend_ptr_stack *stack) +{ + return stack->elements[stack->top - 1]; +} + #endif /* ZEND_PTR_STACK_H */ /* diff --git a/Zend/zend_signal.c b/Zend/zend_signal.c index f61ae0b176..6105fb1119 100644 --- a/Zend/zend_signal.c +++ b/Zend/zend_signal.c @@ -215,7 +215,7 @@ ZEND_API int zend_sigaction(int signo, const struct sigaction *act, struct sigac sa.sa_mask = global_sigmask; if (sigaction(signo, &sa, NULL) < 0) { - zend_error(E_WARNING, "Error installing signal handler for %d", signo); + zend_error(E_ERROR, "Error installing signal handler for %d", signo); } /* unsure this signal is not blocked */ @@ -267,7 +267,7 @@ static int zend_signal_register(int signo, void (*handler)(int, siginfo_t*, void sa.sa_mask = global_sigmask; if (sigaction(signo, &sa, NULL) < 0) { - zend_error(E_WARNING, "Error installing signal handler for %d", signo); + zend_error(E_ERROR, "Error installing signal handler for %d", signo); } return SUCCESS; diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index b7fa907073..82826c904a 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -334,7 +334,7 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMP|VAR zval **object_ptr = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW); zval *object; zval *property = GET_OP2_ZVAL_PTR(BP_VAR_R); - zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); + zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); int have_get_ptr = 0; if (OP1_TYPE == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -465,8 +465,8 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_helper, VAR|UNUSED|CV, CONST|TMP|VAR|UNU zval *dim = GET_OP2_ZVAL_PTR(BP_VAR_R); zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, OP2_TYPE, BP_VAR_RW TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } } break; @@ -1161,7 +1161,7 @@ ZEND_VM_HANDLER(92, ZEND_FETCH_FUNC_ARG, CONST|TMP|VAR|CV, UNUSED|CONST|VAR) USE_OPLINE ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, - ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R); + ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R); } ZEND_VM_HANDLER(95, ZEND_FETCH_UNSET, CONST|TMP|VAR|CV, UNUSED|CONST|VAR) @@ -1174,7 +1174,7 @@ ZEND_VM_HANDLER(89, ZEND_FETCH_IS, CONST|TMP|VAR|CV, UNUSED|CONST|VAR) ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_IS); } -ZEND_VM_HANDLER(81, ZEND_FETCH_DIM_R, VAR|CV, CONST|TMP|VAR|CV) +ZEND_VM_HANDLER(81, ZEND_FETCH_DIM_R, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV) { USE_OPLINE zend_free_op free_op1, free_op2; @@ -1187,10 +1187,19 @@ ZEND_VM_HANDLER(81, ZEND_FETCH_DIM_R, VAR|CV, CONST|TMP|VAR|CV) EX_T(opline->op1.var).var.ptr_ptr) { PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); } - container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_R); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE, BP_VAR_R TSRMLS_CC); - FREE_OP2(); - FREE_OP1_VAR_PTR(); + + if (OP1_TYPE == IS_TMP_VAR || OP1_TYPE == IS_CONST) { + zval *container = GET_OP1_ZVAL_PTR(BP_VAR_R); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), &container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE, BP_VAR_R TSRMLS_CC); + FREE_OP2(); + FREE_OP1(); + } else { + container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_R); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE, BP_VAR_R TSRMLS_CC); + FREE_OP2(); + FREE_OP1_VAR_PTR(); + } + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -1274,7 +1283,7 @@ ZEND_VM_HANDLER(93, ZEND_FETCH_DIM_FUNC_ARG, VAR|CV, CONST|TMP|VAR|UNUSED|CV) SAVE_OPLINE(); - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W); if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -1321,6 +1330,7 @@ ZEND_VM_HANDLER(96, ZEND_FETCH_DIM_UNSET, VAR|CV, CONST|TMP|VAR|CV) FREE_OP1_VAR_PTR(); if (UNEXPECTED(EX_T(opline->result.var).var.ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_NEXT_OPCODE(); } else { zend_free_op free_res; zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr; @@ -1510,7 +1520,7 @@ ZEND_VM_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, VAR|UNUSED|CV, CONST|TMP|VAR|CV) { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1, free_op2; zval *property; @@ -1627,7 +1637,7 @@ ZEND_VM_HANDLER(136, ZEND_ASSIGN_OBJ, VAR|UNUSED|CV, CONST|TMP|VAR|CV) if (OP1_TYPE == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((OP2_TYPE == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((OP2_TYPE == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (IS_OP2_TMP_FREE()) { zval_ptr_dtor(&property_name); } else { @@ -1659,7 +1669,7 @@ ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMP|VAR|UNUSED|CV) if (IS_OP2_TMP_FREE()) { MAKE_REAL_ZVAL_PTR(property_name); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_DIM, ((OP2_TYPE == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((OP2_TYPE == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (IS_OP2_TMP_FREE()) { zval_ptr_dtor(&property_name); } else { @@ -1674,8 +1684,8 @@ ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMP|VAR|UNUSED|CV) zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), object_ptr, dim, OP2_TYPE, BP_VAR_W TSRMLS_CC); FREE_OP2(); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); if (UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) { if (RETURN_VALUE_USED(opline)) { @@ -1831,6 +1841,266 @@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV) ZEND_VM_NEXT_OPCODE(); } +ZEND_VM_HELPER(zend_leave_helper, ANY, ANY) +{ + zend_bool nested = EX(nested); + zend_op_array *op_array = EX(op_array); + + EG(current_execute_data) = EX(prev_execute_data); + EG(opline_ptr) = NULL; + if (!EG(active_symbol_table)) { + i_free_compiled_variables(execute_data); + } + + zend_vm_stack_free((char*)execute_data - (ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * op_array->T) TSRMLS_CC); + + if ((op_array->fn_flags & ZEND_ACC_CLOSURE) && op_array->prototype) { + zval_ptr_dtor((zval**)&op_array->prototype); + } + + if (nested) { + execute_data = EG(current_execute_data); + } + if (nested) { + USE_OPLINE + + LOAD_REGS(); + LOAD_OPLINE(); + if (UNEXPECTED(opline->opcode == ZEND_INCLUDE_OR_EVAL)) { + + EX(function_state).function = (zend_function *) EX(op_array); + EX(function_state).arguments = NULL; + + EG(opline_ptr) = &EX(opline); + EG(active_op_array) = EX(op_array); + EG(return_value_ptr_ptr) = EX(original_return_value); + destroy_op_array(op_array TSRMLS_CC); + efree(op_array); + if (UNEXPECTED(EG(exception) != NULL)) { + zend_throw_exception_internal(NULL TSRMLS_CC); + HANDLE_EXCEPTION_LEAVE(); + } + + ZEND_VM_INC_OPCODE(); + ZEND_VM_LEAVE(); + } else { + EG(opline_ptr) = &EX(opline); + EG(active_op_array) = EX(op_array); + EG(return_value_ptr_ptr) = EX(original_return_value); + if (EG(active_symbol_table)) { + zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC); + } + EG(active_symbol_table) = EX(symbol_table); + + EX(function_state).function = (zend_function *) EX(op_array); + EX(function_state).arguments = NULL; + + if (EG(This)) { + if (UNEXPECTED(EG(exception) != NULL) && EX(call)->is_ctor_call) { + if (EX(call)->is_ctor_result_used) { + Z_DELREF_P(EG(This)); + } + if (Z_REFCOUNT_P(EG(This)) == 1) { + zend_object_store_ctor_failed(EG(This) TSRMLS_CC); + } + } + zval_ptr_dtor(&EG(This)); + } + EG(This) = EX(current_this); + EG(scope) = EX(current_scope); + EG(called_scope) = EX(current_called_scope); + + EX(call)--; + + zend_vm_stack_clear_multiple(1 TSRMLS_CC); + + if (UNEXPECTED(EG(exception) != NULL)) { + zend_throw_exception_internal(NULL TSRMLS_CC); + if (RETURN_VALUE_USED(opline) && EX_T(opline->result.var).var.ptr) { + zval_ptr_dtor(&EX_T(opline->result.var).var.ptr); + } + HANDLE_EXCEPTION_LEAVE(); + } + + ZEND_VM_INC_OPCODE(); + ZEND_VM_LEAVE(); + } + } + ZEND_VM_RETURN(); +} + +ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY) +{ + USE_OPLINE + zend_bool should_change_scope = 0; + zend_function *fbc = EX(function_state).function; + + SAVE_OPLINE(); + EX(object) = EX(call)->object; + if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) { + zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", fbc->common.scope->name, fbc->common.function_name); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); /* Never reached */ + } + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) { + zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated", + fbc->common.scope ? fbc->common.scope->name : "", + fbc->common.scope ? "::" : "", + fbc->common.function_name); + } + } + if (fbc->common.scope && + !(fbc->common.fn_flags & ZEND_ACC_STATIC) && + !EX(object)) { + + if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + /* FIXME: output identifiers properly */ + zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically", fbc->common.scope->name, fbc->common.function_name); + } else { + /* FIXME: output identifiers properly */ + /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ + zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically", fbc->common.scope->name, fbc->common.function_name); + } + } + + if (fbc->type == ZEND_USER_FUNCTION || fbc->common.scope) { + should_change_scope = 1; + EX(current_this) = EG(This); + EX(current_scope) = EG(scope); + EX(current_called_scope) = EG(called_scope); + EG(This) = EX(object); + EG(scope) = (fbc->type == ZEND_USER_FUNCTION || !EX(object)) ? fbc->common.scope : NULL; + EG(called_scope) = EX(call)->called_scope; + } + + EX(function_state).arguments = zend_vm_stack_top(TSRMLS_C); + zend_vm_stack_push((void*)(zend_uintptr_t)opline->extended_value TSRMLS_CC); + LOAD_OPLINE(); + + if (fbc->type == ZEND_INTERNAL_FUNCTION) { + temp_variable *ret = &EX_T(opline->result.var); + + MAKE_STD_ZVAL(ret->var.ptr); + ZVAL_NULL(ret->var.ptr); + ret->var.ptr_ptr = &ret->var.ptr; + ret->var.fcall_returned_reference = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0; + + if (fbc->common.arg_info) { + zend_uint i=0; + zval **p = (zval**)EX(function_state).arguments; + ulong arg_count = opline->extended_value; + + while (arg_count>0) { + zend_verify_arg_type(fbc, ++i, *(p-arg_count), 0 TSRMLS_CC); + arg_count--; + } + } + + if (!zend_execute_internal) { + /* saves one function call if zend_execute_internal is not used */ + fbc->internal_function.handler(opline->extended_value, ret->var.ptr, (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? &ret->var.ptr : NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC); + } else { + zend_execute_internal(execute_data, NULL, RETURN_VALUE_USED(opline) TSRMLS_CC); + } + + if (!RETURN_VALUE_USED(opline)) { + zval_ptr_dtor(&ret->var.ptr); + } + } else if (fbc->type == ZEND_USER_FUNCTION) { + EX(original_return_value) = EG(return_value_ptr_ptr); + EG(active_symbol_table) = NULL; + EG(active_op_array) = &fbc->op_array; + EG(return_value_ptr_ptr) = NULL; + if (RETURN_VALUE_USED(opline)) { + temp_variable *ret = &EX_T(opline->result.var); + + ret->var.ptr = NULL; + EG(return_value_ptr_ptr) = &ret->var.ptr; + ret->var.ptr_ptr = &ret->var.ptr; + ret->var.fcall_returned_reference = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0; + } + + if (UNEXPECTED((EG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) { + if (RETURN_VALUE_USED(opline)) { + EX_T(opline->result.var).var.ptr = zend_generator_create_zval(EG(active_op_array) TSRMLS_CC); + } + } else if (EXPECTED(zend_execute_ex == execute_ex)) { + if (EXPECTED(EG(exception) == NULL)) { + ZEND_VM_ENTER(); + } + } else { + zend_execute(EG(active_op_array) TSRMLS_CC); + } + + EG(opline_ptr) = &EX(opline); + EG(active_op_array) = EX(op_array); + EG(return_value_ptr_ptr) = EX(original_return_value); + if (EG(active_symbol_table)) { + zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC); + } + EG(active_symbol_table) = EX(symbol_table); + } else { /* ZEND_OVERLOADED_FUNCTION */ + MAKE_STD_ZVAL(EX_T(opline->result.var).var.ptr); + ZVAL_NULL(EX_T(opline->result.var).var.ptr); + + /* Not sure what should be done here if it's a static method */ + if (EXPECTED(EX(object) != NULL)) { + Z_OBJ_HT_P(EX(object))->call_method(fbc->common.function_name, opline->extended_value, EX_T(opline->result.var).var.ptr, &EX_T(opline->result.var).var.ptr, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC); + } else { + zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object"); + } + + if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) { + efree((char*)fbc->common.function_name); + } + efree(fbc); + + if (!RETURN_VALUE_USED(opline)) { + zval_ptr_dtor(&EX_T(opline->result.var).var.ptr); + } else { + Z_UNSET_ISREF_P(EX_T(opline->result.var).var.ptr); + Z_SET_REFCOUNT_P(EX_T(opline->result.var).var.ptr, 1); + EX_T(opline->result.var).var.fcall_returned_reference = 0; + EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr; + } + } + + EX(function_state).function = (zend_function *) EX(op_array); + EX(function_state).arguments = NULL; + + if (should_change_scope) { + if (EG(This)) { + if (UNEXPECTED(EG(exception) != NULL) && EX(call)->is_ctor_call) { + if (EX(call)->is_ctor_result_used) { + Z_DELREF_P(EG(This)); + } + if (Z_REFCOUNT_P(EG(This)) == 1) { + zend_object_store_ctor_failed(EG(This) TSRMLS_CC); + } + } + zval_ptr_dtor(&EG(This)); + } + EG(This) = EX(current_this); + EG(scope) = EX(current_scope); + EG(called_scope) = EX(current_called_scope); + } + + EX(call)--; + + zend_vm_stack_clear_multiple(1 TSRMLS_CC); + + if (UNEXPECTED(EG(exception) != NULL)) { + zend_throw_exception_internal(NULL TSRMLS_CC); + if (RETURN_VALUE_USED(opline) && EX_T(opline->result.var).var.ptr) { + zval_ptr_dtor(&EX_T(opline->result.var).var.ptr); + } + HANDLE_EXCEPTION(); + } + + ZEND_VM_NEXT_OPCODE(); +} + ZEND_VM_HANDLER(42, ZEND_JMP, ANY, ANY) { USE_OPLINE @@ -1839,7 +2109,7 @@ ZEND_VM_HANDLER(42, ZEND_JMP, ANY, ANY) printf("Jumping to %d\n", opline->op1.opline_num); #endif ZEND_VM_SET_OPCODE(opline->op1.jmp_addr); - ZEND_VM_CONTINUE(); /* CHECK_ME */ + ZEND_VM_CONTINUE(); } ZEND_VM_HANDLER(43, ZEND_JMPZ, CONST|TMP|VAR|CV, ANY) @@ -2124,7 +2394,9 @@ ZEND_VM_HANDLER(109, ZEND_FETCH_CLASS, ANY, CONST|TMP|VAR|UNUSED|CV) USE_OPLINE SAVE_OPLINE(); - EG(exception) = NULL; + if (EG(exception)) { + zend_exception_save(TSRMLS_C); + } if (OP2_TYPE == IS_UNUSED) { EX_T(opline->result.var).class_entry = zend_fetch_class(NULL, 0, opline->extended_value TSRMLS_CC); CHECK_EXCEPTION(); @@ -2161,9 +2433,9 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV) char *function_name_strval; int function_name_strlen; zend_free_op free_op1, free_op2; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); function_name = GET_OP2_ZVAL_PTR(BP_VAR_R); @@ -2175,49 +2447,51 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV) function_name_strval = Z_STRVAL_P(function_name); function_name_strlen = Z_STRLEN_P(function_name); - EX(object) = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_R); + call->object = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_R); - if (EXPECTED(EX(object) != NULL) && - EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) { - EX(called_scope) = Z_OBJCE_P(EX(object)); + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); if (OP2_TYPE != IS_CONST || - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) { - zval *object = EX(object); + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; - if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) { + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { zend_error_noreturn(E_ERROR, "Object does not support method calls"); } /* First, locate the function. */ - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((OP2_TYPE == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((OP2_TYPE == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); } if (OP2_TYPE == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(EX(object) == object)) { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc)); + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); } } } else { zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } + call->is_ctor_call = 0; + EX(call) = call; FREE_OP2(); FREE_OP1_IF_VAR(); @@ -2231,9 +2505,9 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS USE_OPLINE zval *function_name; zend_class_entry *ce; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); if (OP1_TYPE == IS_CONST) { /* no function found. try a static method in class */ @@ -2247,24 +2521,24 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS } CACHE_PTR(opline->op1.literal->cache_slot, ce); } - EX(called_scope) = ce; + call->called_scope = ce; } else { ce = EX_T(opline->op1.var).class_entry; if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) { - EX(called_scope) = EG(called_scope); + call->called_scope = EG(called_scope); } else { - EX(called_scope) = ce; + call->called_scope = ce; } } if (OP1_TYPE == IS_CONST && OP2_TYPE == IS_CONST && CACHED_PTR(opline->op2.literal->cache_slot)) { - EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot); + call->fbc = CACHED_PTR(opline->op2.literal->cache_slot); } else if (OP1_TYPE != IS_CONST && OP2_TYPE == IS_CONST && - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { /* do nothing */ } else if (OP2_TYPE != IS_UNUSED) { char *function_name_strval = NULL; @@ -2287,20 +2561,20 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS if (function_name_strval) { if (ce->get_static_method) { - EX(fbc) = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + call->fbc = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); } else { - EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((OP2_TYPE == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + call->fbc = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((OP2_TYPE == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); } - if (UNEXPECTED(EX(fbc) == NULL)) { + if (UNEXPECTED(call->fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval); } if (OP2_TYPE == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { if (OP1_TYPE == IS_CONST) { - CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc)); + CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } else { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc)); + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, call->fbc); } } } @@ -2314,29 +2588,31 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMP|VAR|UNUS if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name); } - EX(fbc) = ce->constructor; + call->fbc = ce->constructor; } - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { - EX(object) = NULL; + if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) { + call->object = NULL; } else { if (EG(This) && Z_OBJ_HT_P(EG(This))->get_class_entry && !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { /* We are calling method of the other (incompatible) class, but passing $this. This is done for compatibility with php-4. */ - if (EX(fbc)->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } else { /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } } - if ((EX(object) = EG(This))) { - Z_ADDREF_P(EX(object)); - EX(called_scope) = Z_OBJCE_P(EX(object)); + if ((call->object = EG(This))) { + Z_ADDREF_P(call->object); + call->called_scope = Z_OBJCE_P(call->object); } } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -2346,19 +2622,22 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV) { USE_OPLINE zval *function_name; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); + call_slot *call = EX(call_slots) + opline->result.num; if (OP2_TYPE == IS_CONST) { function_name = (zval*)(opline->op2.literal+1); if (CACHED_PTR(opline->op2.literal->cache_slot)) { - EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot); - } else if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name)+1, Z_HASH_P(function_name), (void **) &EX(fbc)) == FAILURE)) { + call->fbc = CACHED_PTR(opline->op2.literal->cache_slot); + } else if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name)+1, Z_HASH_P(function_name), (void **) &call->fbc) == FAILURE)) { SAVE_OPLINE(); zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv)); } else { - CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc)); + CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } - EX(object) = NULL; + call->object = NULL; + call->called_scope = NULL; + call->is_ctor_call = 0; + EX(call) = call; /*CHECK_EXCEPTION();*/ ZEND_VM_NEXT_OPCODE(); } else { @@ -2378,28 +2657,33 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV) } else { lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen); } - if (UNEXPECTED(zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &EX(fbc)) == FAILURE)) { + if (UNEXPECTED(zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &call->fbc) == FAILURE)) { zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval); } efree(lcname); FREE_OP2(); - EX(object) = NULL; + call->object = NULL; + call->called_scope = NULL; + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else if (OP2_TYPE != IS_CONST && OP2_TYPE != IS_TMP_VAR && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) && Z_OBJ_HANDLER_P(function_name, get_closure) && - Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &EX(called_scope), &EX(fbc), &EX(object) TSRMLS_CC) == SUCCESS) { - if (EX(object)) { - Z_ADDREF_P(EX(object)); + Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &call->called_scope, &call->fbc, &call->object TSRMLS_CC) == SUCCESS) { + if (call->object) { + Z_ADDREF_P(call->object); } if (OP2_TYPE == IS_VAR && OP2_FREE && - EX(fbc)->common.fn_flags & ZEND_ACC_CLOSURE) { + call->fbc->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ - EX(fbc)->common.prototype = (zend_function*)function_name; + call->fbc->common.prototype = (zend_function*)function_name; } else { FREE_OP2(); } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else if (OP2_TYPE != IS_CONST && @@ -2430,46 +2714,49 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV) CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } - EX(called_scope) = ce; - EX(object) = NULL; + call->called_scope = ce; + call->object = NULL; if (ce->get_static_method) { - EX(fbc) = ce->get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method) TSRMLS_CC); + call->fbc = ce->get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method) TSRMLS_CC); } else { - EX(fbc) = zend_std_get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC); + call->fbc = zend_std_get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC); } } else { - EX(object) = *obj; - ce = EX(called_scope) = Z_OBJCE_PP(obj); + call->object = *obj; + ce = call->called_scope = Z_OBJCE_PP(obj); - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), Z_STRVAL_PP(method)); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_PP(method)); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } } - if (UNEXPECTED(EX(fbc) == NULL)) { + if (UNEXPECTED(call->fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, Z_STRVAL_PP(method)); } + call->is_ctor_call = 0; + EX(call) = call; FREE_OP2(); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { zend_error_noreturn(E_ERROR, "Function name must be a string"); + ZEND_VM_NEXT_OPCODE(); /* Never reached */ } } } @@ -2479,324 +2766,33 @@ ZEND_VM_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST) { USE_OPLINE zend_literal *func_name; - - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); + call_slot *call = EX(call_slots) + opline->result.num; func_name = opline->op2.literal + 1; if (CACHED_PTR(opline->op2.literal->cache_slot)) { - EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot); - } else if (zend_hash_quick_find(EG(function_table), Z_STRVAL(func_name->constant), Z_STRLEN(func_name->constant)+1, func_name->hash_value, (void **) &EX(fbc))==FAILURE) { + call->fbc = CACHED_PTR(opline->op2.literal->cache_slot); + } else if (zend_hash_quick_find(EG(function_table), Z_STRVAL(func_name->constant), Z_STRLEN(func_name->constant)+1, func_name->hash_value, (void **) &call->fbc)==FAILURE) { func_name++; - if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL(func_name->constant), Z_STRLEN(func_name->constant)+1, func_name->hash_value, (void **) &EX(fbc))==FAILURE)) { + if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL(func_name->constant), Z_STRLEN(func_name->constant)+1, func_name->hash_value, (void **) &call->fbc)==FAILURE)) { SAVE_OPLINE(); zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv)); } else { - CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc)); + CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } } else { - CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc)); - } - - EX(object) = NULL; - ZEND_VM_NEXT_OPCODE(); -} - -ZEND_VM_HELPER(zend_leave_helper, ANY, ANY) -{ - zend_bool nested; - zend_op_array *op_array = EX(op_array); - - EG(current_execute_data) = EX(prev_execute_data); - EG(opline_ptr) = NULL; - if (!EG(active_symbol_table)) { - zval ***cv = EX_CVs(); - zval ***end = cv + op_array->last_var; - while (cv != end) { - if (*cv) { - zval_ptr_dtor(*cv); - } - cv++; - } - } - - if ((op_array->fn_flags & ZEND_ACC_CLOSURE) && op_array->prototype) { - zval_ptr_dtor((zval**)&op_array->prototype); - } - - nested = EX(nested); - - zend_vm_stack_free(execute_data TSRMLS_CC); - - if (nested) { - execute_data = EG(current_execute_data); - } - if (nested) { - USE_OPLINE - - LOAD_REGS(); - LOAD_OPLINE(); - if (UNEXPECTED(opline->opcode == ZEND_INCLUDE_OR_EVAL)) { - - EX(function_state).function = (zend_function *) EX(op_array); - EX(function_state).arguments = NULL; - EX(object) = EX(current_object); - - EG(opline_ptr) = &EX(opline); - EG(active_op_array) = EX(op_array); - EG(return_value_ptr_ptr) = EX(original_return_value); - destroy_op_array(op_array TSRMLS_CC); - efree(op_array); - if (UNEXPECTED(EG(exception) != NULL)) { - zend_throw_exception_internal(NULL TSRMLS_CC); - HANDLE_EXCEPTION_LEAVE(); - } else if (RETURN_VALUE_USED(opline)) { - if (!EX_T(opline->result.var).var.ptr) { /* there was no return statement */ - zval *retval; - - ALLOC_ZVAL(retval); - ZVAL_BOOL(retval, 1); - INIT_PZVAL(retval); - EX_T(opline->result.var).var.ptr = retval; - } - } - - ZEND_VM_INC_OPCODE(); - ZEND_VM_LEAVE(); - } else { - - EG(opline_ptr) = &EX(opline); - EG(active_op_array) = EX(op_array); - EG(return_value_ptr_ptr) = EX(original_return_value); - if (EG(active_symbol_table)) { - if (EG(symtable_cache_ptr)>=EG(symtable_cache_limit)) { - zend_hash_destroy(EG(active_symbol_table)); - FREE_HASHTABLE(EG(active_symbol_table)); - } else { - /* clean before putting into the cache, since clean - could call dtors, which could use cached hash */ - zend_hash_clean(EG(active_symbol_table)); - *(++EG(symtable_cache_ptr)) = EG(active_symbol_table); - } - } - EG(active_symbol_table) = EX(symbol_table); - - EX(function_state).function = (zend_function *) EX(op_array); - EX(function_state).arguments = NULL; - - if (EG(This)) { - if (UNEXPECTED(EG(exception) != NULL) && IS_CTOR_CALL(EX(called_scope))) { - if (IS_CTOR_USED(EX(called_scope))) { - Z_DELREF_P(EG(This)); - } - if (Z_REFCOUNT_P(EG(This)) == 1) { - zend_object_store_ctor_failed(EG(This) TSRMLS_CC); - } - } - zval_ptr_dtor(&EG(This)); - } - EG(This) = EX(current_this); - EG(scope) = EX(current_scope); - EG(called_scope) = EX(current_called_scope); - - EX(object) = EX(current_object); - EX(called_scope) = DECODE_CTOR(EX(called_scope)); - - zend_vm_stack_clear_multiple(TSRMLS_C); - - if (UNEXPECTED(EG(exception) != NULL)) { - zend_throw_exception_internal(NULL TSRMLS_CC); - if (RETURN_VALUE_USED(opline) && EX_T(opline->result.var).var.ptr) { - zval_ptr_dtor(&EX_T(opline->result.var).var.ptr); - } - HANDLE_EXCEPTION_LEAVE(); - } - - ZEND_VM_INC_OPCODE(); - ZEND_VM_LEAVE(); - } - } - ZEND_VM_RETURN(); -} - -ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY) -{ - USE_OPLINE - zend_bool should_change_scope = 0; - zend_function *fbc = EX(function_state).function; - - SAVE_OPLINE(); - if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) { - if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) { - zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", fbc->common.scope->name, fbc->common.function_name); - CHECK_EXCEPTION(); - ZEND_VM_NEXT_OPCODE(); /* Never reached */ - } - if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) { - zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated", - fbc->common.scope ? fbc->common.scope->name : "", - fbc->common.scope ? "::" : "", - fbc->common.function_name); - } - } - if (fbc->common.scope && - !(fbc->common.fn_flags & ZEND_ACC_STATIC) && - !EX(object)) { - - if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - /* FIXME: output identifiers properly */ - zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically", fbc->common.scope->name, fbc->common.function_name); - } else { - /* FIXME: output identifiers properly */ - /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically", fbc->common.scope->name, fbc->common.function_name); - } - } - - if (fbc->type == ZEND_USER_FUNCTION || fbc->common.scope) { - should_change_scope = 1; - EX(current_this) = EG(This); - EX(current_scope) = EG(scope); - EX(current_called_scope) = EG(called_scope); - EG(This) = EX(object); - EG(scope) = (fbc->type == ZEND_USER_FUNCTION || !EX(object)) ? fbc->common.scope : NULL; - EG(called_scope) = EX(called_scope); - } - - zend_arg_types_stack_3_pop(&EG(arg_types_stack), &EX(called_scope), &EX(current_object), &EX(fbc)); - EX(function_state).arguments = zend_vm_stack_push_args(opline->extended_value TSRMLS_CC); - LOAD_OPLINE(); - - if (fbc->type == ZEND_INTERNAL_FUNCTION) { - temp_variable *ret = &EX_T(opline->result.var); - - MAKE_STD_ZVAL(ret->var.ptr); - ZVAL_NULL(ret->var.ptr); - ret->var.ptr_ptr = &ret->var.ptr; - ret->var.fcall_returned_reference = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0; - - if (fbc->common.arg_info) { - zend_uint i=0; - zval **p = (zval**)EX(function_state).arguments; - ulong arg_count = opline->extended_value; - - while (arg_count>0) { - zend_verify_arg_type(fbc, ++i, *(p-arg_count), 0 TSRMLS_CC); - arg_count--; - } - } - - if (!zend_execute_internal) { - /* saves one function call if zend_execute_internal is not used */ - fbc->internal_function.handler(opline->extended_value, ret->var.ptr, (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? &ret->var.ptr : NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC); - } else { - zend_execute_internal(EXECUTE_DATA, RETURN_VALUE_USED(opline) TSRMLS_CC); - } - - if (!RETURN_VALUE_USED(opline)) { - zval_ptr_dtor(&ret->var.ptr); - } - } else if (fbc->type == ZEND_USER_FUNCTION) { - EX(original_return_value) = EG(return_value_ptr_ptr); - EG(active_symbol_table) = NULL; - EG(active_op_array) = &fbc->op_array; - EG(return_value_ptr_ptr) = NULL; - if (RETURN_VALUE_USED(opline)) { - temp_variable *ret = &EX_T(opline->result.var); - - ret->var.ptr = NULL; - EG(return_value_ptr_ptr) = &ret->var.ptr; - ret->var.ptr_ptr = &ret->var.ptr; - ret->var.fcall_returned_reference = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0; - } - - if (EXPECTED(zend_execute == execute)) { - if (EXPECTED(EG(exception) == NULL)) { - ZEND_VM_ENTER(); - } - } else { - zend_execute(EG(active_op_array) TSRMLS_CC); - } - - EG(opline_ptr) = &EX(opline); - EG(active_op_array) = EX(op_array); - EG(return_value_ptr_ptr) = EX(original_return_value); - if (EG(active_symbol_table)) { - if (EG(symtable_cache_ptr)>=EG(symtable_cache_limit)) { - zend_hash_destroy(EG(active_symbol_table)); - FREE_HASHTABLE(EG(active_symbol_table)); - } else { - /* clean before putting into the cache, since clean - could call dtors, which could use cached hash */ - zend_hash_clean(EG(active_symbol_table)); - *(++EG(symtable_cache_ptr)) = EG(active_symbol_table); - } - } - EG(active_symbol_table) = EX(symbol_table); - } else { /* ZEND_OVERLOADED_FUNCTION */ - MAKE_STD_ZVAL(EX_T(opline->result.var).var.ptr); - ZVAL_NULL(EX_T(opline->result.var).var.ptr); - - /* Not sure what should be done here if it's a static method */ - if (EXPECTED(EX(object) != NULL)) { - Z_OBJ_HT_P(EX(object))->call_method(fbc->common.function_name, opline->extended_value, EX_T(opline->result.var).var.ptr, &EX_T(opline->result.var).var.ptr, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC); - } else { - zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object"); - } - - if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) { - efree((char*)fbc->common.function_name); - } - efree(fbc); - - if (!RETURN_VALUE_USED(opline)) { - zval_ptr_dtor(&EX_T(opline->result.var).var.ptr); - } else { - Z_UNSET_ISREF_P(EX_T(opline->result.var).var.ptr); - Z_SET_REFCOUNT_P(EX_T(opline->result.var).var.ptr, 1); - EX_T(opline->result.var).var.fcall_returned_reference = 0; - EX_T(opline->result.var).var.ptr_ptr = &EX_T(opline->result.var).var.ptr; - } - } - - EX(function_state).function = (zend_function *) EX(op_array); - EX(function_state).arguments = NULL; - - if (should_change_scope) { - if (EG(This)) { - if (UNEXPECTED(EG(exception) != NULL) && IS_CTOR_CALL(EX(called_scope))) { - if (IS_CTOR_USED(EX(called_scope))) { - Z_DELREF_P(EG(This)); - } - if (Z_REFCOUNT_P(EG(This)) == 1) { - zend_object_store_ctor_failed(EG(This) TSRMLS_CC); - } - } - zval_ptr_dtor(&EG(This)); - } - EG(This) = EX(current_this); - EG(scope) = EX(current_scope); - EG(called_scope) = EX(current_called_scope); - } - - EX(object) = EX(current_object); - EX(called_scope) = DECODE_CTOR(EX(called_scope)); - - zend_vm_stack_clear_multiple(TSRMLS_C); - - if (UNEXPECTED(EG(exception) != NULL)) { - zend_throw_exception_internal(NULL TSRMLS_CC); - if (RETURN_VALUE_USED(opline) && EX_T(opline->result.var).var.ptr) { - zval_ptr_dtor(&EX_T(opline->result.var).var.ptr); - } - HANDLE_EXCEPTION(); + CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } + call->object = NULL; + call->called_scope = NULL; + call->is_ctor_call = 0; + EX(call) = call; ZEND_VM_NEXT_OPCODE(); } ZEND_VM_HANDLER(61, ZEND_DO_FCALL_BY_NAME, ANY, ANY) { - EX(function_state).function = EX(fbc); + EX(function_state).function = EX(call)->fbc; ZEND_VM_DISPATCH_TO_HELPER(zend_do_fcall_common_helper); } @@ -2805,8 +2801,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, CONST, ANY) USE_OPLINE zend_free_op free_op1; zval *fname = GET_OP1_ZVAL_PTR(BP_VAR_R); - - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); + call_slot *call = EX(call_slots) + opline->op2.num; if (CACHED_PTR(opline->op1.literal->cache_slot)) { EX(function_state).function = CACHED_PTR(opline->op1.literal->cache_slot); @@ -2816,7 +2811,11 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, CONST, ANY) } else { CACHE_PTR(opline->op1.literal->cache_slot, EX(function_state).function); } - EX(object) = NULL; + call->fbc = EX(function_state).function; + call->object = NULL; + call->called_scope = NULL; + call->is_ctor_call = 0; + EX(call) = call; FREE_OP1(); @@ -2837,6 +2836,9 @@ ZEND_VM_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY) FREE_OP1(); } } else if (!IS_OP1_TMP_FREE()) { /* Not a temp var */ + if (*EG(return_value_ptr_ptr)) { + zval_ptr_dtor(EG(return_value_ptr_ptr)); + } if (OP1_TYPE == IS_CONST || (PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) { zval *ret; @@ -2858,6 +2860,10 @@ ZEND_VM_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY) } else { zval *ret; + if (*EG(return_value_ptr_ptr)) { + zval_ptr_dtor(EG(return_value_ptr_ptr)); + } + ALLOC_ZVAL(ret); INIT_PZVAL_COPY(ret, retval_ptr); *EG(return_value_ptr_ptr) = ret; @@ -2876,6 +2882,10 @@ ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY) SAVE_OPLINE(); do { + if (EG(return_value_ptr_ptr) && *EG(return_value_ptr_ptr)) { + zval_ptr_dtor(EG(return_value_ptr_ptr)); + } + if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR) { /* Not supposed to happen, but we'll allow it */ zend_error(E_NOTICE, "Only variable references should be returned by reference"); @@ -2934,6 +2944,18 @@ ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY) ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); } +ZEND_VM_HANDLER(161, ZEND_GENERATOR_RETURN, ANY, ANY) +{ + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + /* Close the generator to free up resources */ + zend_generator_close(generator, 1 TSRMLS_CC); + + /* Pass execution back to handling code */ + ZEND_VM_RETURN(); +} + ZEND_VM_HANDLER(108, ZEND_THROW, CONST|TMP|VAR|CV, ANY) { USE_OPLINE @@ -3005,7 +3027,7 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, CV) if (EX_CV(opline->op2.var)) { zval_ptr_dtor(EX_CV(opline->op2.var)); } - EX_CV(opline->op2.var) = (zval**)EX_CVs() + (EX(op_array)->last_var + opline->op2.var); + EX_CV(opline->op2.var) = (zval**)EX_CV_NUM(execute_data, EX(op_array)->last_var + opline->op2.var); *EX_CV(opline->op2.var) = EG(exception); } else { zend_compiled_variable *cv = &CV_DEF_OF(opline->op2.var); @@ -3027,7 +3049,7 @@ ZEND_VM_HANDLER(65, ZEND_SEND_VAL, CONST|TMP, ANY) SAVE_OPLINE(); if (opline->extended_value==ZEND_DO_FCALL_BY_NAME - && ARG_MUST_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) { + && ARG_MUST_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.opline_num)) { zend_error_noreturn(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.opline_num); } { @@ -3088,7 +3110,7 @@ ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR|CV, ANY) if (!(opline->extended_value & ZEND_ARG_SEND_BY_REF)) { ZEND_VM_DISPATCH_TO_HELPER(zend_send_by_var_helper); } - } else if (!ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) { + } else if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.opline_num)) { ZEND_VM_DISPATCH_TO_HELPER(zend_send_by_var_helper); } @@ -3114,7 +3136,7 @@ ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR|CV, ANY) if ((opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) ? !(opline->extended_value & ZEND_ARG_SEND_SILENT) : - !ARG_MAY_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) { + !ARG_MAY_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.opline_num)) { zend_error(E_STRICT, "Only variables should be passed by reference"); } ALLOC_ZVAL(valptr); @@ -3150,7 +3172,7 @@ ZEND_VM_HANDLER(67, ZEND_SEND_REF, VAR|CV, ANY) ZEND_VM_NEXT_OPCODE(); } - if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION && !ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) { + if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION && !ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.opline_num)) { ZEND_VM_DISPATCH_TO_HELPER(zend_send_by_var_helper); } @@ -3169,7 +3191,7 @@ ZEND_VM_HANDLER(66, ZEND_SEND_VAR, VAR|CV, ANY) USE_OPLINE if ((opline->extended_value == ZEND_DO_FCALL_BY_NAME) - && ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) { + && ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.opline_num)) { ZEND_VM_DISPATCH_TO_HANDLER(ZEND_SEND_REF); } SAVE_OPLINE(); @@ -3207,7 +3229,7 @@ ZEND_VM_HANDLER(63, ZEND_RECV, ANY, ANY) zval **var_ptr; zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, *param, opline->extended_value TSRMLS_CC); - var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->result.var TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC); Z_DELREF_PP(var_ptr); *var_ptr = *param; Z_ADDREF_PP(var_ptr); @@ -3243,7 +3265,7 @@ ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST) } zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, assignment_value, opline->extended_value TSRMLS_CC); - var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->result.var TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC); Z_DELREF_PP(var_ptr); *var_ptr = assignment_value; @@ -3273,7 +3295,7 @@ ZEND_VM_HANDLER(50, ZEND_BRK, ANY, CONST) SAVE_OPLINE(); el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->op1.opline_num, - EX(op_array), EX_Ts() TSRMLS_CC); + EX(op_array), execute_data TSRMLS_CC); FREE_OP2(); ZEND_VM_JMP(EX(op_array)->opcodes + el->brk); } @@ -3285,7 +3307,7 @@ ZEND_VM_HANDLER(51, ZEND_CONT, ANY, CONST) SAVE_OPLINE(); el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->op1.opline_num, - EX(op_array), EX_Ts() TSRMLS_CC); + EX(op_array), execute_data TSRMLS_CC); FREE_OP2(); ZEND_VM_JMP(EX(op_array)->opcodes + el->cont); } @@ -3298,7 +3320,7 @@ ZEND_VM_HANDLER(100, ZEND_GOTO, ANY, CONST) SAVE_OPLINE(); el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->extended_value, - EX(op_array), EX_Ts() TSRMLS_CC); + EX(op_array), execute_data TSRMLS_CC); brk_opline = EX(op_array)->opcodes + el->brk; @@ -3375,17 +3397,20 @@ ZEND_VM_HANDLER(68, ZEND_NEW, ANY, ANY) } ZEND_VM_JMP(EX(op_array)->opcodes + opline->op2.opline_num); } else { + call_slot *call = EX(call_slots) + opline->extended_value; + if (RETURN_VALUE_USED(opline)) { PZVAL_LOCK(object_zval); AI_SET_PTR(&EX_T(opline->result.var), object_zval); } - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), ENCODE_CTOR(EX(called_scope), RETURN_VALUE_USED(opline))); - /* We are not handling overloaded classes right now */ - EX(object) = object_zval; - EX(fbc) = constructor; - EX(called_scope) = EX_T(opline->op1.var).class_entry; + call->fbc = constructor; + call->object = object_zval; + call->called_scope = EX_T(opline->op1.var).class_entry; + call->is_ctor_call = 1; + call->is_ctor_result_used = RETURN_VALUE_USED(opline); + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -3712,7 +3737,7 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY) zend_op_array *new_op_array=NULL; zend_free_op free_op1; zval *inc_filename; - zval *tmp_inc_filename = NULL; + zval *tmp_inc_filename = NULL; zend_bool failure_retval=0; SAVE_OPLINE(); @@ -3804,8 +3829,6 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY) EG(return_value_ptr_ptr) = NULL; } - EX(current_object) = EX(object); - EX(function_state).function = (zend_function *) new_op_array; EX(object) = NULL; @@ -3813,14 +3836,13 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY) zend_rebuild_symbol_table(TSRMLS_C); } - if (EXPECTED(zend_execute == execute)) { + if (EXPECTED(zend_execute_ex == execute_ex)) { ZEND_VM_ENTER(); } else { zend_execute(new_op_array TSRMLS_CC); } EX(function_state).function = (zend_function *) EX(op_array); - EX(object) = EX(current_object); EG(opline_ptr) = &EX(opline); EG(active_op_array) = EX(op_array); @@ -3830,15 +3852,6 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY) if (UNEXPECTED(EG(exception) != NULL)) { zend_throw_exception_internal(NULL TSRMLS_CC); HANDLE_EXCEPTION(); - } else if (RETURN_VALUE_USED(opline)) { - if (!EX_T(opline->result.var).var.ptr) { /* there was no return statement */ - zval *retval; - - ALLOC_ZVAL(retval); - ZVAL_BOOL(retval, 1); - INIT_PZVAL(retval); - EX_T(opline->result.var).var.ptr = retval; - } } } else if (RETURN_VALUE_USED(opline)) { @@ -3915,7 +3928,7 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR) ulong hash_value = zend_inline_hash_func(varname->value.str.val, varname->value.str.len+1); target_symbol_table = zend_get_target_symbol_table(opline->extended_value & ZEND_FETCH_TYPE_MASK TSRMLS_CC); - zend_delete_variable(EXECUTE_DATA, target_symbol_table, varname->value.str.val, varname->value.str.len+1, hash_value TSRMLS_CC); + zend_delete_variable(execute_data, target_symbol_table, varname->value.str.val, varname->value.str.len+1, hash_value TSRMLS_CC); } if (OP1_TYPE != IS_CONST && varname == &tmp) { @@ -4992,13 +5005,15 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) { zend_uint op_num = EG(opline_before_exception)-EG(active_op_array)->opcodes; int i; - zend_uint catch_op_num = 0; - int catched = 0; - zval restored_error_reporting; + zend_uint catch_op_num = 0, finally_op_num = 0; + void **stack_frame; - void **stack_frame = (void**)(((char*)EX_Ts()) + - (ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * EX(op_array)->T)); + /* Figure out where the next stack frame (which maybe contains pushed + * arguments that have to be dtor'ed) starts */ + stack_frame = zend_vm_stack_frame_base(execute_data); + /* If the exception was thrown during a function call there might be + * arguments pushed to the stack that have to be dtor'ed. */ while (zend_vm_stack_top(TSRMLS_C) != stack_frame) { zval *stack_zval_p = zend_vm_stack_pop(TSRMLS_C); zval_ptr_dtor(&stack_zval_p); @@ -5008,27 +5023,32 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) if (EG(active_op_array)->try_catch_array[i].try_op > op_num) { /* further blocks will not be relevant... */ break; - } else if (op_num < EG(active_op_array)->try_catch_array[i].catch_op) { + } + if (op_num < EG(active_op_array)->try_catch_array[i].catch_op) { catch_op_num = EX(op_array)->try_catch_array[i].catch_op; - catched = 1; + } + if (op_num < EG(active_op_array)->try_catch_array[i].finally_op) { + finally_op_num = EX(op_array)->try_catch_array[i].finally_op; } } - while (EX(fbc)) { - EX(called_scope) = (zend_class_entry*)zend_ptr_stack_pop(&EG(arg_types_stack)); - if (EX(object)) { - if (IS_CTOR_CALL(EX(called_scope))) { - if (IS_CTOR_USED(EX(called_scope))) { - Z_DELREF_P(EX(object)); - } - if (Z_REFCOUNT_P(EX(object)) == 1) { - zend_object_store_ctor_failed(EX(object) TSRMLS_CC); + if (EX(call) >= EX(call_slots)) { + call_slot *call = EX(call); + do { + if (call->object) { + if (call->is_ctor_call) { + if (call->is_ctor_result_used) { + Z_DELREF_P(call->object); + } + if (Z_REFCOUNT_P(call->object) == 1) { + zend_object_store_ctor_failed(call->object TSRMLS_CC); + } } + zval_ptr_dtor(&call->object); } - zval_ptr_dtor(&EX(object)); - } - EX(called_scope) = DECODE_CTOR(EX(called_scope)); - zend_arg_types_stack_2_pop(&EG(arg_types_stack), &EX(object), &EX(fbc)); + call--; + } while (call >= EX(call_slots)); + EX(call) = NULL; } for (i=0; i<EX(op_array)->last_brk_cont; i++) { @@ -5038,7 +5058,7 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) /* further blocks will not be relevant... */ break; } else if (op_num < EX(op_array)->brk_cont_array[i].brk) { - if (!catched || + if (!catch_op_num || catch_op_num >= EX(op_array)->brk_cont_array[i].brk) { zend_op *brk_opline = &EX(op_array)->opcodes[EX(op_array)->brk_cont_array[i].brk]; @@ -5060,6 +5080,8 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) /* restore previous error_reporting value */ if (!EG(error_reporting) && EX(old_error_reporting) != NULL && Z_LVAL_P(EX(old_error_reporting)) != 0) { + zval restored_error_reporting; + Z_TYPE(restored_error_reporting) = IS_LONG; Z_LVAL(restored_error_reporting) = Z_LVAL_P(EX(old_error_reporting)); convert_to_string(&restored_error_reporting); @@ -5068,12 +5090,21 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) } EX(old_error_reporting) = NULL; - if (!catched) { - ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); - } else { + if (finally_op_num && (!catch_op_num || catch_op_num >= finally_op_num)) { + zend_exception_save(TSRMLS_C); + EX(fast_ret) = NULL; + ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); + ZEND_VM_CONTINUE(); + } else if (catch_op_num) { ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_op_num]); - ZEND_VM_CONTINUE(); - } + ZEND_VM_CONTINUE(); + } else { + if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) { + ZEND_VM_DISPATCH_TO_HANDLER(ZEND_GENERATOR_RETURN); + } else { + ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); + } + } } ZEND_VM_HANDLER(146, ZEND_VERIFY_ABSTRACT_CLASS, ANY, ANY) @@ -5099,7 +5130,11 @@ ZEND_VM_HANDLER(150, ZEND_USER_OPCODE, ANY, ANY) case ZEND_USER_OPCODE_CONTINUE: ZEND_VM_CONTINUE(); case ZEND_USER_OPCODE_RETURN: - ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); + if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) { + ZEND_VM_DISPATCH_TO_HANDLER(ZEND_GENERATOR_RETURN); + } else { + ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); + } case ZEND_USER_OPCODE_ENTER: ZEND_VM_ENTER(); case ZEND_USER_OPCODE_LEAVE: @@ -5164,7 +5199,7 @@ ZEND_VM_HANDLER(153, ZEND_DECLARE_LAMBDA_FUNCTION, CONST, UNUSED) zend_error_noreturn(E_ERROR, "Base lambda function for closure not found"); } - zend_create_closure(&EX_T(opline->result.var).tmp_var, op_array, EG(scope), EG(This) TSRMLS_CC); + zend_create_closure(&EX_T(opline->result.var).tmp_var, (zend_function *) op_array, EG(scope), EG(This) TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -5178,8 +5213,8 @@ ZEND_VM_HANDLER(156, ZEND_SEPARATE, VAR, UNUSED) SAVE_OPLINE(); var_ptr = EX_T(opline->op1.var).var.ptr; if (Z_TYPE_P(var_ptr) != IS_OBJECT && - !PZVAL_IS_REF(var_ptr) && - Z_REFCOUNT_P(var_ptr) > 1) { + !PZVAL_IS_REF(var_ptr) && + Z_REFCOUNT_P(var_ptr) > 1) { Z_DELREF_P(var_ptr); ALLOC_ZVAL(new_zv); @@ -5191,4 +5226,212 @@ ZEND_VM_HANDLER(156, ZEND_SEPARATE, VAR, UNUSED) ZEND_VM_NEXT_OPCODE(); } +ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSED) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (OP1_TYPE != IS_UNUSED) { + zend_free_op free_op1; + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = GET_OP1_ZVAL_PTR(BP_VAR_R); + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!IS_OP1_TMP_FREE()) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W); + + if (OP1_TYPE == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (OP1_TYPE == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + FREE_OP1_IF_VAR(); + } + } else { + zval *value = GET_OP1_ZVAL_PTR(BP_VAR_R); + + /* Consts, temporary variables and references need copying */ + if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!IS_OP1_TMP_FREE()) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + FREE_OP1_IF_VAR(); + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (OP2_TYPE != IS_UNUSED) { + zend_free_op free_op2; + zval *key = GET_OP2_ZVAL_PTR(BP_VAR_R); + + /* Consts, temporary variables and references need copying */ + if (OP2_TYPE == IS_CONST || OP2_TYPE == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!IS_OP2_TMP_FREE()) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + FREE_OP2_IF_VAR(); + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + +ZEND_VM_HANDLER(159, ZEND_DISCARD_EXCEPTION, ANY, ANY) +{ + if (EG(prev_exception) != NULL) { + /* discard the previously thrown exception */ + zval_ptr_dtor(&EG(prev_exception)); + EG(prev_exception) = NULL; + } + + ZEND_VM_NEXT_OPCODE(); +} + +ZEND_VM_HANDLER(162, ZEND_FAST_CALL, ANY, ANY) +{ + USE_OPLINE + + if (opline->extended_value && + UNEXPECTED(EG(prev_exception) != NULL)) { + /* in case of unhandled exception jump to catch block instead of finally */ + ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]); + ZEND_VM_CONTINUE(); + } + EX(fast_ret) = opline + 1; + ZEND_VM_SET_OPCODE(opline->op1.jmp_addr); + ZEND_VM_CONTINUE(); +} + +ZEND_VM_HANDLER(163, ZEND_FAST_RET, ANY, ANY) +{ + if (EX(fast_ret)) { + ZEND_VM_SET_OPCODE(EX(fast_ret)); + ZEND_VM_CONTINUE(); + } else { + /* special case for unhandled exceptions */ + USE_OPLINE + + if (opline->extended_value == ZEND_FAST_RET_TO_FINALLY) { + ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]); + ZEND_VM_CONTINUE(); + } else if (opline->extended_value == ZEND_FAST_RET_TO_CATCH) { + zend_exception_restore(TSRMLS_C); + ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]); + ZEND_VM_CONTINUE(); + } else if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) { + zend_exception_restore(TSRMLS_C); + ZEND_VM_DISPATCH_TO_HANDLER(ZEND_GENERATOR_RETURN); + } else { + zend_exception_restore(TSRMLS_C); + ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); + } + } +} + ZEND_VM_EXPORT_HELPER(zend_do_fcall, zend_do_fcall_common_helper) diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 2680d85242..23f6187ae7 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -326,79 +326,25 @@ static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, zend_op* o #define ZEND_VM_DISPATCH(opcode, opline) return zend_vm_get_opcode_handler(opcode, opline)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); #define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data TSRMLS_CC -#undef EX -#define EX(element) execute_data->element -#undef EX_CV -#define EX_CV(var) EX(CVs)[var] -#undef EX_CVs -#define EX_CVs() EX(CVs) -#undef EX_T -#define EX_T(offset) (*(temp_variable *)((char *) EX(Ts) + offset)) -#undef EX_Ts -#define EX_Ts() EX(Ts) - - -ZEND_API void execute(zend_op_array *op_array TSRMLS_DC) +ZEND_API void execute_ex(zend_execute_data *execute_data TSRMLS_DC) { DCL_OPLINE - zend_execute_data *execute_data; - zend_bool nested = 0; - zend_bool original_in_execution = EG(in_execution); + zend_bool original_in_execution; - if (EG(exception)) { - return; - } + original_in_execution = EG(in_execution); EG(in_execution) = 1; + if (0) { zend_vm_enter: - /* Initialize execute_data */ - execute_data = (zend_execute_data *)zend_vm_stack_alloc( - ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data)) + - ZEND_MM_ALIGNED_SIZE(sizeof(zval**) * op_array->last_var * (EG(active_symbol_table) ? 1 : 2)) + - ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * op_array->T TSRMLS_CC); - - EX(CVs) = (zval***)((char*)execute_data + ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data))); - memset(EX(CVs), 0, sizeof(zval**) * op_array->last_var); - EX(Ts) = (temp_variable *)(((char*)EX(CVs)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval**) * op_array->last_var * (EG(active_symbol_table) ? 1 : 2))); - EX(fbc) = NULL; - EX(called_scope) = NULL; - EX(object) = NULL; - EX(old_error_reporting) = NULL; - EX(op_array) = op_array; - EX(symbol_table) = EG(active_symbol_table); - EX(prev_execute_data) = EG(current_execute_data); - EG(current_execute_data) = execute_data; - EX(nested) = nested; - nested = 1; - - LOAD_REGS(); - - if (!op_array->run_time_cache && op_array->last_cache_slot) { - op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*)); + execute_data = i_create_execute_data_from_op_array(EG(active_op_array), 1 TSRMLS_CC); } - if (op_array->this_var != -1 && EG(This)) { - Z_ADDREF_P(EG(This)); /* For $this pointer */ - if (!EG(active_symbol_table)) { - EX_CV(op_array->this_var) = (zval**)EX_CVs() + (op_array->last_var + op_array->this_var); - *EX_CV(op_array->this_var) = EG(This); - } else { - if (zend_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), (void**)&EX_CV(op_array->this_var))==FAILURE) { - Z_DELREF_P(EG(This)); - } - } - } - - EX(opline) = UNEXPECTED((op_array->fn_flags & ZEND_ACC_INTERACTIVE) != 0) && EG(start_op) ? EG(start_op) : op_array->opcodes; - EG(opline_ptr) = &EX(opline); + LOAD_REGS(); LOAD_OPLINE(); - EX(function_state).function = (zend_function *) op_array; - EX(function_state).arguments = NULL; - while (1) { int ret; #ifdef ZEND_WIN32 @@ -413,10 +359,11 @@ zend_vm_enter: EG(in_execution) = original_in_execution; return; case 2: - op_array = EG(active_op_array); goto zend_vm_enter; + break; case 3: execute_data = EG(current_execute_data); + break; default: break; } @@ -426,59 +373,31 @@ zend_vm_enter: zend_error_noreturn(E_ERROR, "Arrived at end of main loop which shouldn't happen"); } -static int ZEND_FASTCALL ZEND_JMP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +ZEND_API void zend_execute(zend_op_array *op_array TSRMLS_DC) { - USE_OPLINE - -#if DEBUG_ZEND>=2 - printf("Jumping to %d\n", opline->op1.opline_num); -#endif - ZEND_VM_SET_OPCODE(opline->op1.jmp_addr); - ZEND_VM_CONTINUE(); /* CHECK_ME */ -} - -static int ZEND_FASTCALL ZEND_INIT_STRING_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - USE_OPLINE - zval *tmp = &EX_T(opline->result.var).tmp_var; - - SAVE_OPLINE(); - tmp->value.str.val = emalloc(1); - tmp->value.str.val[0] = 0; - tmp->value.str.len = 0; - Z_SET_REFCOUNT_P(tmp, 1); - tmp->type = IS_STRING; - Z_UNSET_ISREF_P(tmp); - /*CHECK_EXCEPTION();*/ - ZEND_VM_NEXT_OPCODE(); + if (EG(exception)) { + return; + } + zend_execute_ex(i_create_execute_data_from_op_array(op_array, 0 TSRMLS_CC) TSRMLS_CC); } static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) { - zend_bool nested; + zend_bool nested = EX(nested); zend_op_array *op_array = EX(op_array); EG(current_execute_data) = EX(prev_execute_data); EG(opline_ptr) = NULL; if (!EG(active_symbol_table)) { - zval ***cv = EX_CVs(); - zval ***end = cv + op_array->last_var; - while (cv != end) { - if (*cv) { - zval_ptr_dtor(*cv); - } - cv++; - } + i_free_compiled_variables(execute_data); } + zend_vm_stack_free((char*)execute_data - (ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * op_array->T) TSRMLS_CC); + if ((op_array->fn_flags & ZEND_ACC_CLOSURE) && op_array->prototype) { zval_ptr_dtor((zval**)&op_array->prototype); } - nested = EX(nested); - - zend_vm_stack_free(execute_data TSRMLS_CC); - if (nested) { execute_data = EG(current_execute_data); } @@ -491,7 +410,6 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) EX(function_state).function = (zend_function *) EX(op_array); EX(function_state).arguments = NULL; - EX(object) = EX(current_object); EG(opline_ptr) = &EX(opline); EG(active_op_array) = EX(op_array); @@ -501,34 +419,16 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) if (UNEXPECTED(EG(exception) != NULL)) { zend_throw_exception_internal(NULL TSRMLS_CC); HANDLE_EXCEPTION_LEAVE(); - } else if (RETURN_VALUE_USED(opline)) { - if (!EX_T(opline->result.var).var.ptr) { /* there was no return statement */ - zval *retval; - - ALLOC_ZVAL(retval); - ZVAL_BOOL(retval, 1); - INIT_PZVAL(retval); - EX_T(opline->result.var).var.ptr = retval; - } } ZEND_VM_INC_OPCODE(); ZEND_VM_LEAVE(); } else { - EG(opline_ptr) = &EX(opline); EG(active_op_array) = EX(op_array); EG(return_value_ptr_ptr) = EX(original_return_value); if (EG(active_symbol_table)) { - if (EG(symtable_cache_ptr)>=EG(symtable_cache_limit)) { - zend_hash_destroy(EG(active_symbol_table)); - FREE_HASHTABLE(EG(active_symbol_table)); - } else { - /* clean before putting into the cache, since clean - could call dtors, which could use cached hash */ - zend_hash_clean(EG(active_symbol_table)); - *(++EG(symtable_cache_ptr)) = EG(active_symbol_table); - } + zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC); } EG(active_symbol_table) = EX(symbol_table); @@ -536,8 +436,8 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) EX(function_state).arguments = NULL; if (EG(This)) { - if (UNEXPECTED(EG(exception) != NULL) && IS_CTOR_CALL(EX(called_scope))) { - if (IS_CTOR_USED(EX(called_scope))) { + if (UNEXPECTED(EG(exception) != NULL) && EX(call)->is_ctor_call) { + if (EX(call)->is_ctor_result_used) { Z_DELREF_P(EG(This)); } if (Z_REFCOUNT_P(EG(This)) == 1) { @@ -550,10 +450,9 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) EG(scope) = EX(current_scope); EG(called_scope) = EX(current_called_scope); - EX(object) = EX(current_object); - EX(called_scope) = DECODE_CTOR(EX(called_scope)); + EX(call)--; - zend_vm_stack_clear_multiple(TSRMLS_C); + zend_vm_stack_clear_multiple(1 TSRMLS_CC); if (UNEXPECTED(EG(exception) != NULL)) { zend_throw_exception_internal(NULL TSRMLS_CC); @@ -577,6 +476,7 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR zend_function *fbc = EX(function_state).function; SAVE_OPLINE(); + EX(object) = EX(call)->object; if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) { if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) { zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", fbc->common.scope->name, fbc->common.function_name); @@ -611,11 +511,11 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR EX(current_called_scope) = EG(called_scope); EG(This) = EX(object); EG(scope) = (fbc->type == ZEND_USER_FUNCTION || !EX(object)) ? fbc->common.scope : NULL; - EG(called_scope) = EX(called_scope); + EG(called_scope) = EX(call)->called_scope; } - zend_arg_types_stack_3_pop(&EG(arg_types_stack), &EX(called_scope), &EX(current_object), &EX(fbc)); - EX(function_state).arguments = zend_vm_stack_push_args(opline->extended_value TSRMLS_CC); + EX(function_state).arguments = zend_vm_stack_top(TSRMLS_C); + zend_vm_stack_push((void*)(zend_uintptr_t)opline->extended_value TSRMLS_CC); LOAD_OPLINE(); if (fbc->type == ZEND_INTERNAL_FUNCTION) { @@ -641,7 +541,7 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR /* saves one function call if zend_execute_internal is not used */ fbc->internal_function.handler(opline->extended_value, ret->var.ptr, (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? &ret->var.ptr : NULL, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC); } else { - zend_execute_internal(execute_data, RETURN_VALUE_USED(opline) TSRMLS_CC); + zend_execute_internal(execute_data, NULL, RETURN_VALUE_USED(opline) TSRMLS_CC); } if (!RETURN_VALUE_USED(opline)) { @@ -661,7 +561,11 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR ret->var.fcall_returned_reference = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0; } - if (EXPECTED(zend_execute == execute)) { + if (UNEXPECTED((EG(active_op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) { + if (RETURN_VALUE_USED(opline)) { + EX_T(opline->result.var).var.ptr = zend_generator_create_zval(EG(active_op_array) TSRMLS_CC); + } + } else if (EXPECTED(zend_execute_ex == execute_ex)) { if (EXPECTED(EG(exception) == NULL)) { ZEND_VM_ENTER(); } @@ -673,22 +577,14 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR EG(active_op_array) = EX(op_array); EG(return_value_ptr_ptr) = EX(original_return_value); if (EG(active_symbol_table)) { - if (EG(symtable_cache_ptr)>=EG(symtable_cache_limit)) { - zend_hash_destroy(EG(active_symbol_table)); - FREE_HASHTABLE(EG(active_symbol_table)); - } else { - /* clean before putting into the cache, since clean - could call dtors, which could use cached hash */ - zend_hash_clean(EG(active_symbol_table)); - *(++EG(symtable_cache_ptr)) = EG(active_symbol_table); - } + zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC); } EG(active_symbol_table) = EX(symbol_table); } else { /* ZEND_OVERLOADED_FUNCTION */ MAKE_STD_ZVAL(EX_T(opline->result.var).var.ptr); ZVAL_NULL(EX_T(opline->result.var).var.ptr); - /* Not sure what should be done here if it's a static method */ + /* Not sure what should be done here if it's a static method */ if (EXPECTED(EX(object) != NULL)) { Z_OBJ_HT_P(EX(object))->call_method(fbc->common.function_name, opline->extended_value, EX_T(opline->result.var).var.ptr, &EX_T(opline->result.var).var.ptr, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC); } else { @@ -715,8 +611,8 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR if (should_change_scope) { if (EG(This)) { - if (UNEXPECTED(EG(exception) != NULL) && IS_CTOR_CALL(EX(called_scope))) { - if (IS_CTOR_USED(EX(called_scope))) { + if (UNEXPECTED(EG(exception) != NULL) && EX(call)->is_ctor_call) { + if (EX(call)->is_ctor_result_used) { Z_DELREF_P(EG(This)); } if (Z_REFCOUNT_P(EG(This)) == 1) { @@ -730,10 +626,9 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR EG(called_scope) = EX(current_called_scope); } - EX(object) = EX(current_object); - EX(called_scope) = DECODE_CTOR(EX(called_scope)); + EX(call)--; - zend_vm_stack_clear_multiple(TSRMLS_C); + zend_vm_stack_clear_multiple(1 TSRMLS_CC); if (UNEXPECTED(EG(exception) != NULL)) { zend_throw_exception_internal(NULL TSRMLS_CC); @@ -746,12 +641,51 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_JMP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + +#if DEBUG_ZEND>=2 + printf("Jumping to %d\n", opline->op1.opline_num); +#endif + ZEND_VM_SET_OPCODE(opline->op1.jmp_addr); + ZEND_VM_CONTINUE(); +} + +static int ZEND_FASTCALL ZEND_INIT_STRING_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *tmp = &EX_T(opline->result.var).tmp_var; + + SAVE_OPLINE(); + tmp->value.str.val = emalloc(1); + tmp->value.str.val[0] = 0; + tmp->value.str.len = 0; + Z_SET_REFCOUNT_P(tmp, 1); + tmp->type = IS_STRING; + Z_UNSET_ISREF_P(tmp); + /*CHECK_EXCEPTION();*/ + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - EX(function_state).function = EX(fbc); + EX(function_state).function = EX(call)->fbc; return zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +static int ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + /* Close the generator to free up resources */ + zend_generator_close(generator, 1 TSRMLS_CC); + + /* Pass execution back to handling code */ + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL ZEND_RECV_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -783,7 +717,7 @@ static int ZEND_FASTCALL ZEND_RECV_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zval **var_ptr; zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, *param, opline->extended_value TSRMLS_CC); - var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->result.var TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC); Z_DELREF_PP(var_ptr); *var_ptr = *param; Z_ADDREF_PP(var_ptr); @@ -823,17 +757,20 @@ static int ZEND_FASTCALL ZEND_NEW_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } ZEND_VM_JMP(EX(op_array)->opcodes + opline->op2.opline_num); } else { + call_slot *call = EX(call_slots) + opline->extended_value; + if (RETURN_VALUE_USED(opline)) { PZVAL_LOCK(object_zval); AI_SET_PTR(&EX_T(opline->result.var), object_zval); } - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), ENCODE_CTOR(EX(called_scope), RETURN_VALUE_USED(opline))); - /* We are not handling overloaded classes right now */ - EX(object) = object_zval; - EX(fbc) = constructor; - EX(called_scope) = EX_T(opline->op1.var).class_entry; + call->fbc = constructor; + call->object = object_zval; + call->called_scope = EX_T(opline->op1.var).class_entry; + call->is_ctor_call = 1; + call->is_ctor_result_used = RETURN_VALUE_USED(opline); + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -1033,13 +970,15 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER { zend_uint op_num = EG(opline_before_exception)-EG(active_op_array)->opcodes; int i; - zend_uint catch_op_num = 0; - int catched = 0; - zval restored_error_reporting; + zend_uint catch_op_num = 0, finally_op_num = 0; + void **stack_frame; - void **stack_frame = (void**)(((char*)EX_Ts()) + - (ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * EX(op_array)->T)); + /* Figure out where the next stack frame (which maybe contains pushed + * arguments that have to be dtor'ed) starts */ + stack_frame = zend_vm_stack_frame_base(execute_data); + /* If the exception was thrown during a function call there might be + * arguments pushed to the stack that have to be dtor'ed. */ while (zend_vm_stack_top(TSRMLS_C) != stack_frame) { zval *stack_zval_p = zend_vm_stack_pop(TSRMLS_C); zval_ptr_dtor(&stack_zval_p); @@ -1049,27 +988,32 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER if (EG(active_op_array)->try_catch_array[i].try_op > op_num) { /* further blocks will not be relevant... */ break; - } else if (op_num < EG(active_op_array)->try_catch_array[i].catch_op) { + } + if (op_num < EG(active_op_array)->try_catch_array[i].catch_op) { catch_op_num = EX(op_array)->try_catch_array[i].catch_op; - catched = 1; + } + if (op_num < EG(active_op_array)->try_catch_array[i].finally_op) { + finally_op_num = EX(op_array)->try_catch_array[i].finally_op; } } - while (EX(fbc)) { - EX(called_scope) = (zend_class_entry*)zend_ptr_stack_pop(&EG(arg_types_stack)); - if (EX(object)) { - if (IS_CTOR_CALL(EX(called_scope))) { - if (IS_CTOR_USED(EX(called_scope))) { - Z_DELREF_P(EX(object)); - } - if (Z_REFCOUNT_P(EX(object)) == 1) { - zend_object_store_ctor_failed(EX(object) TSRMLS_CC); + if (EX(call) >= EX(call_slots)) { + call_slot *call = EX(call); + do { + if (call->object) { + if (call->is_ctor_call) { + if (call->is_ctor_result_used) { + Z_DELREF_P(call->object); + } + if (Z_REFCOUNT_P(call->object) == 1) { + zend_object_store_ctor_failed(call->object TSRMLS_CC); + } } + zval_ptr_dtor(&call->object); } - zval_ptr_dtor(&EX(object)); - } - EX(called_scope) = DECODE_CTOR(EX(called_scope)); - zend_arg_types_stack_2_pop(&EG(arg_types_stack), &EX(object), &EX(fbc)); + call--; + } while (call >= EX(call_slots)); + EX(call) = NULL; } for (i=0; i<EX(op_array)->last_brk_cont; i++) { @@ -1079,7 +1023,7 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER /* further blocks will not be relevant... */ break; } else if (op_num < EX(op_array)->brk_cont_array[i].brk) { - if (!catched || + if (!catch_op_num || catch_op_num >= EX(op_array)->brk_cont_array[i].brk) { zend_op *brk_opline = &EX(op_array)->opcodes[EX(op_array)->brk_cont_array[i].brk]; @@ -1101,6 +1045,8 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER /* restore previous error_reporting value */ if (!EG(error_reporting) && EX(old_error_reporting) != NULL && Z_LVAL_P(EX(old_error_reporting)) != 0) { + zval restored_error_reporting; + Z_TYPE(restored_error_reporting) = IS_LONG; Z_LVAL(restored_error_reporting) = Z_LVAL_P(EX(old_error_reporting)); convert_to_string(&restored_error_reporting); @@ -1109,12 +1055,21 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER } EX(old_error_reporting) = NULL; - if (!catched) { - return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else { + if (finally_op_num && (!catch_op_num || catch_op_num >= finally_op_num)) { + zend_exception_save(TSRMLS_C); + EX(fast_ret) = NULL; + ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); + ZEND_VM_CONTINUE(); + } else if (catch_op_num) { ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_op_num]); - ZEND_VM_CONTINUE(); - } + ZEND_VM_CONTINUE(); + } else { + if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) { + return ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else { + return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } + } } static int ZEND_FASTCALL ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -1140,7 +1095,11 @@ static int ZEND_FASTCALL ZEND_USER_OPCODE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS case ZEND_USER_OPCODE_CONTINUE: ZEND_VM_CONTINUE(); case ZEND_USER_OPCODE_RETURN: - return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) { + return ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else { + return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } case ZEND_USER_OPCODE_ENTER: ZEND_VM_ENTER(); case ZEND_USER_OPCODE_LEAVE: @@ -1152,12 +1111,66 @@ static int ZEND_FASTCALL ZEND_USER_OPCODE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS } } +static int ZEND_FASTCALL ZEND_DISCARD_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + if (EG(prev_exception) != NULL) { + /* discard the previously thrown exception */ + zval_ptr_dtor(&EG(prev_exception)); + EG(prev_exception) = NULL; + } + + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_FAST_CALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + if (opline->extended_value && + UNEXPECTED(EG(prev_exception) != NULL)) { + /* in case of unhandled exception jump to catch block instead of finally */ + ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]); + ZEND_VM_CONTINUE(); + } + EX(fast_ret) = opline + 1; + ZEND_VM_SET_OPCODE(opline->op1.jmp_addr); + ZEND_VM_CONTINUE(); +} + +static int ZEND_FASTCALL ZEND_FAST_RET_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + if (EX(fast_ret)) { + ZEND_VM_SET_OPCODE(EX(fast_ret)); + ZEND_VM_CONTINUE(); + } else { + /* special case for unhandled exceptions */ + USE_OPLINE + + if (opline->extended_value == ZEND_FAST_RET_TO_FINALLY) { + ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]); + ZEND_VM_CONTINUE(); + } else if (opline->extended_value == ZEND_FAST_RET_TO_CATCH) { + zend_exception_restore(TSRMLS_C); + ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]); + ZEND_VM_CONTINUE(); + } else if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) { + zend_exception_restore(TSRMLS_C); + return ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else { + zend_exception_restore(TSRMLS_C); + return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } + } +} + static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE SAVE_OPLINE(); - EG(exception) = NULL; + if (EG(exception)) { + zend_exception_save(TSRMLS_C); + } if (IS_CONST == IS_UNUSED) { EX_T(opline->result.var).class_entry = zend_fetch_class(NULL, 0, opline->extended_value TSRMLS_CC); CHECK_EXCEPTION(); @@ -1190,19 +1203,22 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE { USE_OPLINE zval *function_name; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); + call_slot *call = EX(call_slots) + opline->result.num; if (IS_CONST == IS_CONST) { function_name = (zval*)(opline->op2.literal+1); if (CACHED_PTR(opline->op2.literal->cache_slot)) { - EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot); - } else if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name)+1, Z_HASH_P(function_name), (void **) &EX(fbc)) == FAILURE)) { + call->fbc = CACHED_PTR(opline->op2.literal->cache_slot); + } else if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name)+1, Z_HASH_P(function_name), (void **) &call->fbc) == FAILURE)) { SAVE_OPLINE(); zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv)); } else { - CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc)); + CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } - EX(object) = NULL; + call->object = NULL; + call->called_scope = NULL; + call->is_ctor_call = 0; + EX(call) = call; /*CHECK_EXCEPTION();*/ ZEND_VM_NEXT_OPCODE(); } else { @@ -1222,28 +1238,33 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE } else { lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen); } - if (UNEXPECTED(zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &EX(fbc)) == FAILURE)) { + if (UNEXPECTED(zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &call->fbc) == FAILURE)) { zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval); } efree(lcname); - EX(object) = NULL; + call->object = NULL; + call->called_scope = NULL; + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else if (IS_CONST != IS_CONST && IS_CONST != IS_TMP_VAR && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) && Z_OBJ_HANDLER_P(function_name, get_closure) && - Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &EX(called_scope), &EX(fbc), &EX(object) TSRMLS_CC) == SUCCESS) { - if (EX(object)) { - Z_ADDREF_P(EX(object)); + Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &call->called_scope, &call->fbc, &call->object TSRMLS_CC) == SUCCESS) { + if (call->object) { + Z_ADDREF_P(call->object); } if (IS_CONST == IS_VAR && 0 && - EX(fbc)->common.fn_flags & ZEND_ACC_CLOSURE) { + call->fbc->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ - EX(fbc)->common.prototype = (zend_function*)function_name; + call->fbc->common.prototype = (zend_function*)function_name; } else { } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else if (IS_CONST != IS_CONST && @@ -1274,46 +1295,49 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } - EX(called_scope) = ce; - EX(object) = NULL; + call->called_scope = ce; + call->object = NULL; if (ce->get_static_method) { - EX(fbc) = ce->get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method) TSRMLS_CC); + call->fbc = ce->get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method) TSRMLS_CC); } else { - EX(fbc) = zend_std_get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC); + call->fbc = zend_std_get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC); } } else { - EX(object) = *obj; - ce = EX(called_scope) = Z_OBJCE_PP(obj); + call->object = *obj; + ce = call->called_scope = Z_OBJCE_PP(obj); - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), Z_STRVAL_PP(method)); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_PP(method)); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } } - if (UNEXPECTED(EX(fbc) == NULL)) { + if (UNEXPECTED(call->fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, Z_STRVAL_PP(method)); } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { zend_error_noreturn(E_ERROR, "Function name must be a string"); + ZEND_VM_NEXT_OPCODE(); /* Never reached */ } } } @@ -1323,25 +1347,27 @@ static int ZEND_FASTCALL ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPC { USE_OPLINE zend_literal *func_name; - - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); + call_slot *call = EX(call_slots) + opline->result.num; func_name = opline->op2.literal + 1; if (CACHED_PTR(opline->op2.literal->cache_slot)) { - EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot); - } else if (zend_hash_quick_find(EG(function_table), Z_STRVAL(func_name->constant), Z_STRLEN(func_name->constant)+1, func_name->hash_value, (void **) &EX(fbc))==FAILURE) { + call->fbc = CACHED_PTR(opline->op2.literal->cache_slot); + } else if (zend_hash_quick_find(EG(function_table), Z_STRVAL(func_name->constant), Z_STRLEN(func_name->constant)+1, func_name->hash_value, (void **) &call->fbc)==FAILURE) { func_name++; - if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL(func_name->constant), Z_STRLEN(func_name->constant)+1, func_name->hash_value, (void **) &EX(fbc))==FAILURE)) { + if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL(func_name->constant), Z_STRLEN(func_name->constant)+1, func_name->hash_value, (void **) &call->fbc)==FAILURE)) { SAVE_OPLINE(); zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv)); } else { - CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc)); + CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } } else { - CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc)); + CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } - EX(object) = NULL; + call->object = NULL; + call->called_scope = NULL; + call->is_ctor_call = 0; + EX(call) = call; ZEND_VM_NEXT_OPCODE(); } @@ -1371,7 +1397,7 @@ static int ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ } zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, assignment_value, opline->extended_value TSRMLS_CC); - var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->result.var TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC); Z_DELREF_PP(var_ptr); *var_ptr = assignment_value; @@ -1386,7 +1412,7 @@ static int ZEND_FASTCALL ZEND_BRK_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->op1.opline_num, - EX(op_array), EX_Ts() TSRMLS_CC); + EX(op_array), execute_data TSRMLS_CC); ZEND_VM_JMP(EX(op_array)->opcodes + el->brk); } @@ -1398,7 +1424,7 @@ static int ZEND_FASTCALL ZEND_CONT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->op1.opline_num, - EX(op_array), EX_Ts() TSRMLS_CC); + EX(op_array), execute_data TSRMLS_CC); ZEND_VM_JMP(EX(op_array)->opcodes + el->cont); } @@ -1411,7 +1437,7 @@ static int ZEND_FASTCALL ZEND_GOTO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->extended_value, - EX(op_array), EX_Ts() TSRMLS_CC); + EX(op_array), execute_data TSRMLS_CC); brk_opline = EX(op_array)->opcodes + el->brk; @@ -1462,14 +1488,16 @@ static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ USE_OPLINE SAVE_OPLINE(); - EG(exception) = NULL; + if (EG(exception)) { + zend_exception_save(TSRMLS_C); + } if (IS_TMP_VAR == IS_UNUSED) { EX_T(opline->result.var).class_entry = zend_fetch_class(NULL, 0, opline->extended_value TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { zend_free_op free_op2; - zval *class_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *class_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_TMP_VAR == IS_CONST) { if (CACHED_PTR(opline->op2.literal->cache_slot)) { @@ -1496,19 +1524,22 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H { USE_OPLINE zval *function_name; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); + call_slot *call = EX(call_slots) + opline->result.num; if (IS_TMP_VAR == IS_CONST) { function_name = (zval*)(opline->op2.literal+1); if (CACHED_PTR(opline->op2.literal->cache_slot)) { - EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot); - } else if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name)+1, Z_HASH_P(function_name), (void **) &EX(fbc)) == FAILURE)) { + call->fbc = CACHED_PTR(opline->op2.literal->cache_slot); + } else if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name)+1, Z_HASH_P(function_name), (void **) &call->fbc) == FAILURE)) { SAVE_OPLINE(); zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv)); } else { - CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc)); + CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } - EX(object) = NULL; + call->object = NULL; + call->called_scope = NULL; + call->is_ctor_call = 0; + EX(call) = call; /*CHECK_EXCEPTION();*/ ZEND_VM_NEXT_OPCODE(); } else { @@ -1517,7 +1548,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H zend_free_op free_op2; SAVE_OPLINE(); - function_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + function_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { function_name_strval = Z_STRVAL_P(function_name); @@ -1528,28 +1559,33 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H } else { lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen); } - if (UNEXPECTED(zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &EX(fbc)) == FAILURE)) { + if (UNEXPECTED(zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &call->fbc) == FAILURE)) { zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval); } efree(lcname); zval_dtor(free_op2.var); - EX(object) = NULL; + call->object = NULL; + call->called_scope = NULL; + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else if (IS_TMP_VAR != IS_CONST && IS_TMP_VAR != IS_TMP_VAR && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) && Z_OBJ_HANDLER_P(function_name, get_closure) && - Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &EX(called_scope), &EX(fbc), &EX(object) TSRMLS_CC) == SUCCESS) { - if (EX(object)) { - Z_ADDREF_P(EX(object)); + Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &call->called_scope, &call->fbc, &call->object TSRMLS_CC) == SUCCESS) { + if (call->object) { + Z_ADDREF_P(call->object); } if (IS_TMP_VAR == IS_VAR && 1 && - EX(fbc)->common.fn_flags & ZEND_ACC_CLOSURE) { + call->fbc->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ - EX(fbc)->common.prototype = (zend_function*)function_name; + call->fbc->common.prototype = (zend_function*)function_name; } else { zval_dtor(free_op2.var); } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else if (IS_TMP_VAR != IS_CONST && @@ -1580,46 +1616,49 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } - EX(called_scope) = ce; - EX(object) = NULL; + call->called_scope = ce; + call->object = NULL; if (ce->get_static_method) { - EX(fbc) = ce->get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method) TSRMLS_CC); + call->fbc = ce->get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method) TSRMLS_CC); } else { - EX(fbc) = zend_std_get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC); + call->fbc = zend_std_get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC); } } else { - EX(object) = *obj; - ce = EX(called_scope) = Z_OBJCE_PP(obj); + call->object = *obj; + ce = call->called_scope = Z_OBJCE_PP(obj); - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), Z_STRVAL_PP(method)); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_PP(method)); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } } - if (UNEXPECTED(EX(fbc) == NULL)) { + if (UNEXPECTED(call->fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, Z_STRVAL_PP(method)); } + call->is_ctor_call = 0; + EX(call) = call; zval_dtor(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { zend_error_noreturn(E_ERROR, "Function name must be a string"); + ZEND_VM_NEXT_OPCODE(); /* Never reached */ } } } @@ -1630,14 +1669,16 @@ static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ USE_OPLINE SAVE_OPLINE(); - EG(exception) = NULL; + if (EG(exception)) { + zend_exception_save(TSRMLS_C); + } if (IS_VAR == IS_UNUSED) { EX_T(opline->result.var).class_entry = zend_fetch_class(NULL, 0, opline->extended_value TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { zend_free_op free_op2; - zval *class_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *class_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_VAR == IS_CONST) { if (CACHED_PTR(opline->op2.literal->cache_slot)) { @@ -1664,19 +1705,22 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H { USE_OPLINE zval *function_name; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); + call_slot *call = EX(call_slots) + opline->result.num; if (IS_VAR == IS_CONST) { function_name = (zval*)(opline->op2.literal+1); if (CACHED_PTR(opline->op2.literal->cache_slot)) { - EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot); - } else if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name)+1, Z_HASH_P(function_name), (void **) &EX(fbc)) == FAILURE)) { + call->fbc = CACHED_PTR(opline->op2.literal->cache_slot); + } else if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name)+1, Z_HASH_P(function_name), (void **) &call->fbc) == FAILURE)) { SAVE_OPLINE(); zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv)); } else { - CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc)); + CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } - EX(object) = NULL; + call->object = NULL; + call->called_scope = NULL; + call->is_ctor_call = 0; + EX(call) = call; /*CHECK_EXCEPTION();*/ ZEND_VM_NEXT_OPCODE(); } else { @@ -1685,7 +1729,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H zend_free_op free_op2; SAVE_OPLINE(); - function_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { function_name_strval = Z_STRVAL_P(function_name); @@ -1696,28 +1740,33 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H } else { lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen); } - if (UNEXPECTED(zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &EX(fbc)) == FAILURE)) { + if (UNEXPECTED(zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &call->fbc) == FAILURE)) { zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval); } efree(lcname); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; - EX(object) = NULL; + call->object = NULL; + call->called_scope = NULL; + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else if (IS_VAR != IS_CONST && IS_VAR != IS_TMP_VAR && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) && Z_OBJ_HANDLER_P(function_name, get_closure) && - Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &EX(called_scope), &EX(fbc), &EX(object) TSRMLS_CC) == SUCCESS) { - if (EX(object)) { - Z_ADDREF_P(EX(object)); + Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &call->called_scope, &call->fbc, &call->object TSRMLS_CC) == SUCCESS) { + if (call->object) { + Z_ADDREF_P(call->object); } if (IS_VAR == IS_VAR && (free_op2.var != NULL) && - EX(fbc)->common.fn_flags & ZEND_ACC_CLOSURE) { + call->fbc->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ - EX(fbc)->common.prototype = (zend_function*)function_name; + call->fbc->common.prototype = (zend_function*)function_name; } else { if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else if (IS_VAR != IS_CONST && @@ -1748,46 +1797,49 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } - EX(called_scope) = ce; - EX(object) = NULL; + call->called_scope = ce; + call->object = NULL; if (ce->get_static_method) { - EX(fbc) = ce->get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method) TSRMLS_CC); + call->fbc = ce->get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method) TSRMLS_CC); } else { - EX(fbc) = zend_std_get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC); + call->fbc = zend_std_get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC); } } else { - EX(object) = *obj; - ce = EX(called_scope) = Z_OBJCE_PP(obj); + call->object = *obj; + ce = call->called_scope = Z_OBJCE_PP(obj); - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), Z_STRVAL_PP(method)); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_PP(method)); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } } - if (UNEXPECTED(EX(fbc) == NULL)) { + if (UNEXPECTED(call->fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, Z_STRVAL_PP(method)); } + call->is_ctor_call = 0; + EX(call) = call; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { zend_error_noreturn(E_ERROR, "Function name must be a string"); + ZEND_VM_NEXT_OPCODE(); /* Never reached */ } } } @@ -1798,7 +1850,9 @@ static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDL USE_OPLINE SAVE_OPLINE(); - EG(exception) = NULL; + if (EG(exception)) { + zend_exception_save(TSRMLS_C); + } if (IS_UNUSED == IS_UNUSED) { EX_T(opline->result.var).class_entry = zend_fetch_class(NULL, 0, opline->extended_value TSRMLS_CC); CHECK_EXCEPTION(); @@ -1832,14 +1886,16 @@ static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A USE_OPLINE SAVE_OPLINE(); - EG(exception) = NULL; + if (EG(exception)) { + zend_exception_save(TSRMLS_C); + } if (IS_CV == IS_UNUSED) { EX_T(opline->result.var).class_entry = zend_fetch_class(NULL, 0, opline->extended_value TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { - zval *class_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + zval *class_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_CV == IS_CONST) { if (CACHED_PTR(opline->op2.literal->cache_slot)) { @@ -1865,19 +1921,22 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA { USE_OPLINE zval *function_name; - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); + call_slot *call = EX(call_slots) + opline->result.num; if (IS_CV == IS_CONST) { function_name = (zval*)(opline->op2.literal+1); if (CACHED_PTR(opline->op2.literal->cache_slot)) { - EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot); - } else if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name)+1, Z_HASH_P(function_name), (void **) &EX(fbc)) == FAILURE)) { + call->fbc = CACHED_PTR(opline->op2.literal->cache_slot); + } else if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(function_name), Z_STRLEN_P(function_name)+1, Z_HASH_P(function_name), (void **) &call->fbc) == FAILURE)) { SAVE_OPLINE(); zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(opline->op2.zv)); } else { - CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc)); + CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } - EX(object) = NULL; + call->object = NULL; + call->called_scope = NULL; + call->is_ctor_call = 0; + EX(call) = call; /*CHECK_EXCEPTION();*/ ZEND_VM_NEXT_OPCODE(); } else { @@ -1886,7 +1945,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA SAVE_OPLINE(); - function_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { function_name_strval = Z_STRVAL_P(function_name); @@ -1897,28 +1956,33 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA } else { lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen); } - if (UNEXPECTED(zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &EX(fbc)) == FAILURE)) { + if (UNEXPECTED(zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &call->fbc) == FAILURE)) { zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval); } efree(lcname); - EX(object) = NULL; + call->object = NULL; + call->called_scope = NULL; + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else if (IS_CV != IS_CONST && IS_CV != IS_TMP_VAR && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) && Z_OBJ_HANDLER_P(function_name, get_closure) && - Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &EX(called_scope), &EX(fbc), &EX(object) TSRMLS_CC) == SUCCESS) { - if (EX(object)) { - Z_ADDREF_P(EX(object)); + Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &call->called_scope, &call->fbc, &call->object TSRMLS_CC) == SUCCESS) { + if (call->object) { + Z_ADDREF_P(call->object); } if (IS_CV == IS_VAR && 0 && - EX(fbc)->common.fn_flags & ZEND_ACC_CLOSURE) { + call->fbc->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ - EX(fbc)->common.prototype = (zend_function*)function_name; + call->fbc->common.prototype = (zend_function*)function_name; } else { } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else if (IS_CV != IS_CONST && @@ -1949,46 +2013,49 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } - EX(called_scope) = ce; - EX(object) = NULL; + call->called_scope = ce; + call->object = NULL; if (ce->get_static_method) { - EX(fbc) = ce->get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method) TSRMLS_CC); + call->fbc = ce->get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method) TSRMLS_CC); } else { - EX(fbc) = zend_std_get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC); + call->fbc = zend_std_get_static_method(ce, Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC); } } else { - EX(object) = *obj; - ce = EX(called_scope) = Z_OBJCE_PP(obj); + call->object = *obj; + ce = call->called_scope = Z_OBJCE_PP(obj); - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), Z_STRVAL_PP(method)); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, Z_STRVAL_PP(method), Z_STRLEN_PP(method), NULL TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), Z_STRVAL_PP(method)); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } } - if (UNEXPECTED(EX(fbc) == NULL)) { + if (UNEXPECTED(call->fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, Z_STRVAL_PP(method)); } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } else { zend_error_noreturn(E_ERROR, "Function name must be a string"); + ZEND_VM_NEXT_OPCODE(); /* Never reached */ } } } @@ -2219,8 +2286,7 @@ static int ZEND_FASTCALL ZEND_DO_FCALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A USE_OPLINE zval *fname = opline->op1.zv; - - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); + call_slot *call = EX(call_slots) + opline->op2.num; if (CACHED_PTR(opline->op1.literal->cache_slot)) { EX(function_state).function = CACHED_PTR(opline->op1.literal->cache_slot); @@ -2230,7 +2296,11 @@ static int ZEND_FASTCALL ZEND_DO_FCALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A } else { CACHE_PTR(opline->op1.literal->cache_slot, EX(function_state).function); } - EX(object) = NULL; + call->fbc = EX(function_state).function; + call->object = NULL; + call->called_scope = NULL; + call->is_ctor_call = 0; + EX(call) = call; return zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } @@ -2249,6 +2319,9 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG } } else if (!0) { /* Not a temp var */ + if (*EG(return_value_ptr_ptr)) { + zval_ptr_dtor(EG(return_value_ptr_ptr)); + } if (IS_CONST == IS_CONST || (PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) { zval *ret; @@ -2270,6 +2343,10 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG } else { zval *ret; + if (*EG(return_value_ptr_ptr)) { + zval_ptr_dtor(EG(return_value_ptr_ptr)); + } + ALLOC_ZVAL(ret); INIT_PZVAL_COPY(ret, retval_ptr); *EG(return_value_ptr_ptr) = ret; @@ -2288,6 +2365,10 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); do { + if (EG(return_value_ptr_ptr) && *EG(return_value_ptr_ptr)) { + zval_ptr_dtor(EG(return_value_ptr_ptr)); + } + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { /* Not supposed to happen, but we'll allow it */ zend_error(E_NOTICE, "Only variable references should be returned by reference"); @@ -2378,7 +2459,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); if (opline->extended_value==ZEND_DO_FCALL_BY_NAME - && ARG_MUST_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) { + && ARG_MUST_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.opline_num)) { zend_error_noreturn(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.opline_num); } { @@ -2542,7 +2623,7 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HA zend_op_array *new_op_array=NULL; zval *inc_filename; - zval *tmp_inc_filename = NULL; + zval *tmp_inc_filename = NULL; zend_bool failure_retval=0; SAVE_OPLINE(); @@ -2634,8 +2715,6 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HA EG(return_value_ptr_ptr) = NULL; } - EX(current_object) = EX(object); - EX(function_state).function = (zend_function *) new_op_array; EX(object) = NULL; @@ -2643,14 +2722,13 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HA zend_rebuild_symbol_table(TSRMLS_C); } - if (EXPECTED(zend_execute == execute)) { + if (EXPECTED(zend_execute_ex == execute_ex)) { ZEND_VM_ENTER(); } else { zend_execute(new_op_array TSRMLS_CC); } EX(function_state).function = (zend_function *) EX(op_array); - EX(object) = EX(current_object); EG(opline_ptr) = &EX(opline); EG(active_op_array) = EX(op_array); @@ -2660,15 +2738,6 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HA if (UNEXPECTED(EG(exception) != NULL)) { zend_throw_exception_internal(NULL TSRMLS_CC); HANDLE_EXCEPTION(); - } else if (RETURN_VALUE_USED(opline)) { - if (!EX_T(opline->result.var).var.ptr) { /* there was no return statement */ - zval *retval; - - ALLOC_ZVAL(retval); - ZVAL_BOOL(retval, 1); - INIT_PZVAL(retval); - EX_T(opline->result.var).var.ptr = retval; - } } } else if (RETURN_VALUE_USED(opline)) { @@ -3377,7 +3446,7 @@ static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CONST_CONST_HANDLER(ZEND_OPCO { USE_OPLINE - return zend_fetch_var_address_helper_SPEC_CONST_CONST(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_CONST_CONST(ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -3390,6 +3459,36 @@ static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HAN return zend_fetch_var_address_helper_SPEC_CONST_CONST(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval **container; + + SAVE_OPLINE(); + + if ((opline->extended_value & ZEND_FETCH_ADD_LOCK) && + IS_CONST != IS_CV && + EX_T(opline->op1.var).var.ptr_ptr) { + PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); + } + + if (IS_CONST == IS_TMP_VAR || IS_CONST == IS_CONST) { + zval *container = opline->op1.zv; + zend_fetch_dimension_address_read(&EX_T(opline->result.var), &container, opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC); + + + } else { + container = NULL; + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC); + + + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_FETCH_DIM_TMP_VAR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -3419,9 +3518,9 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER( USE_OPLINE zval *function_name; zend_class_entry *ce; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); if (IS_CONST == IS_CONST) { /* no function found. try a static method in class */ @@ -3435,24 +3534,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER( } CACHE_PTR(opline->op1.literal->cache_slot, ce); } - EX(called_scope) = ce; + call->called_scope = ce; } else { ce = EX_T(opline->op1.var).class_entry; if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) { - EX(called_scope) = EG(called_scope); + call->called_scope = EG(called_scope); } else { - EX(called_scope) = ce; + call->called_scope = ce; } } if (IS_CONST == IS_CONST && IS_CONST == IS_CONST && CACHED_PTR(opline->op2.literal->cache_slot)) { - EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot); + call->fbc = CACHED_PTR(opline->op2.literal->cache_slot); } else if (IS_CONST != IS_CONST && IS_CONST == IS_CONST && - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { /* do nothing */ } else if (IS_CONST != IS_UNUSED) { char *function_name_strval = NULL; @@ -3475,20 +3574,20 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER( if (function_name_strval) { if (ce->get_static_method) { - EX(fbc) = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + call->fbc = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); } else { - EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + call->fbc = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); } - if (UNEXPECTED(EX(fbc) == NULL)) { + if (UNEXPECTED(call->fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval); } if (IS_CONST == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { if (IS_CONST == IS_CONST) { - CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc)); + CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } else { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc)); + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, call->fbc); } } } @@ -3502,29 +3601,31 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER( if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name); } - EX(fbc) = ce->constructor; + call->fbc = ce->constructor; } - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { - EX(object) = NULL; + if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) { + call->object = NULL; } else { if (EG(This) && Z_OBJ_HT_P(EG(This))->get_class_entry && !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { /* We are calling method of the other (incompatible) class, but passing $this. This is done for compatibility with php-4. */ - if (EX(fbc)->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } else { /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } } - if ((EX(object) = EG(This))) { - Z_ADDREF_P(EX(object)); - EX(called_scope) = Z_OBJCE_P(EX(object)); + if ((call->object = EG(This))) { + Z_ADDREF_P(call->object); + call->called_scope = Z_OBJCE_P(call->object); } } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -3940,6 +4041,159 @@ static int ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCOD ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_CONST != IS_UNUSED) { + + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = opline->op1.zv; + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = NULL; + + if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_CONST == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = opline->op1.zv; + + /* Consts, temporary variables and references need copying */ + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_CONST != IS_UNUSED) { + + zval *key = opline->op2.zv; + + /* Consts, temporary variables and references need copying */ + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL ZEND_ADD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -3948,7 +4202,7 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_add_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -3963,7 +4217,7 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_sub_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -3978,7 +4232,7 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_mul_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -3993,7 +4247,7 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_div_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -4008,7 +4262,7 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_mod_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -4023,7 +4277,7 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); shift_left_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -4038,7 +4292,7 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); shift_right_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -4053,7 +4307,7 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); concat_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -4068,7 +4322,7 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); is_identical_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -4084,7 +4338,7 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CONST_TMP_HANDLER(ZEND_OPCO SAVE_OPLINE(); is_identical_function(result, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); Z_LVAL_P(result) = !Z_LVAL_P(result); zval_dtor(free_op2.var); @@ -4101,7 +4355,7 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); ZVAL_BOOL(result, fast_equal_function(result, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -4117,7 +4371,7 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); ZVAL_BOOL(result, fast_not_equal_function(result, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -4133,7 +4387,7 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_function(result, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -4149,7 +4403,7 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMP_HANDLER(ZEND_O SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -4164,7 +4418,7 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); bitwise_or_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -4179,7 +4433,7 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); bitwise_and_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -4194,7 +4448,7 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); bitwise_xor_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -4209,21 +4463,51 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); boolean_xor_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op2; + zval **container; + + SAVE_OPLINE(); + + if ((opline->extended_value & ZEND_FETCH_ADD_LOCK) && + IS_CONST != IS_CV && + EX_T(opline->op1.var).var.ptr_ptr) { + PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); + } + + if (IS_CONST == IS_TMP_VAR || IS_CONST == IS_CONST) { + zval *container = opline->op1.zv; + zend_fetch_dimension_address_read(&EX_T(opline->result.var), &container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_R TSRMLS_CC); + zval_dtor(free_op2.var); + + } else { + container = NULL; + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_R TSRMLS_CC); + zval_dtor(free_op2.var); + + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; zend_class_entry *ce; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); if (IS_CONST == IS_CONST) { /* no function found. try a static method in class */ @@ -4237,24 +4521,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZE } CACHE_PTR(opline->op1.literal->cache_slot, ce); } - EX(called_scope) = ce; + call->called_scope = ce; } else { ce = EX_T(opline->op1.var).class_entry; if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) { - EX(called_scope) = EG(called_scope); + call->called_scope = EG(called_scope); } else { - EX(called_scope) = ce; + call->called_scope = ce; } } if (IS_CONST == IS_CONST && IS_TMP_VAR == IS_CONST && CACHED_PTR(opline->op2.literal->cache_slot)) { - EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot); + call->fbc = CACHED_PTR(opline->op2.literal->cache_slot); } else if (IS_CONST != IS_CONST && IS_TMP_VAR == IS_CONST && - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { /* do nothing */ } else if (IS_TMP_VAR != IS_UNUSED) { char *function_name_strval = NULL; @@ -4265,7 +4549,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZE function_name_strval = Z_STRVAL_P(opline->op2.zv); function_name_strlen = Z_STRLEN_P(opline->op2.zv); } else { - function_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + function_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { zend_error_noreturn(E_ERROR, "Function name must be a string"); @@ -4277,20 +4561,20 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZE if (function_name_strval) { if (ce->get_static_method) { - EX(fbc) = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + call->fbc = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); } else { - EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + call->fbc = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); } - if (UNEXPECTED(EX(fbc) == NULL)) { + if (UNEXPECTED(call->fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval); } if (IS_TMP_VAR == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { if (IS_CONST == IS_CONST) { - CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc)); + CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } else { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc)); + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, call->fbc); } } } @@ -4304,29 +4588,31 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZE if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name); } - EX(fbc) = ce->constructor; + call->fbc = ce->constructor; } - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { - EX(object) = NULL; + if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) { + call->object = NULL; } else { if (EG(This) && Z_OBJ_HT_P(EG(This))->get_class_entry && !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { /* We are calling method of the other (incompatible) class, but passing $this. This is done for compatibility with php-4. */ - if (EX(fbc)->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } else { /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } } - if ((EX(object) = EG(This))) { - Z_ADDREF_P(EX(object)); - EX(called_scope) = Z_OBJCE_P(EX(object)); + if ((call->object = EG(This))) { + Z_ADDREF_P(call->object); + call->called_scope = Z_OBJCE_P(call->object); } } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -4343,7 +4629,7 @@ static int ZEND_FASTCALL ZEND_CASE_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_A } is_equal_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -4388,7 +4674,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMP_HANDLER(ZEND_OPC if (IS_TMP_VAR != IS_UNUSED) { zend_free_op free_op2; - zval *offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); ulong hval; switch (Z_TYPE_P(offset)) { @@ -4450,6 +4736,159 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HAN } } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_CONST != IS_UNUSED) { + + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = opline->op1.zv; + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = NULL; + + if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_CONST == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = opline->op1.zv; + + /* Consts, temporary variables and references need copying */ + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_TMP_VAR != IS_UNUSED) { + zend_free_op free_op2; + zval *key = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!1) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL ZEND_ADD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -4458,7 +4897,7 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_add_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -4473,7 +4912,7 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_sub_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -4488,7 +4927,7 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_mul_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -4503,7 +4942,7 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_div_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -4518,7 +4957,7 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_mod_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -4533,7 +4972,7 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); shift_left_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -4548,7 +4987,7 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); shift_right_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -4563,7 +5002,7 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); concat_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -4578,7 +5017,7 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); is_identical_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -4594,7 +5033,7 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CONST_VAR_HANDLER(ZEND_OPCO SAVE_OPLINE(); is_identical_function(result, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); Z_LVAL_P(result) = !Z_LVAL_P(result); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; @@ -4611,7 +5050,7 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); ZVAL_BOOL(result, fast_equal_function(result, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -4627,7 +5066,7 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); ZVAL_BOOL(result, fast_not_equal_function(result, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -4643,7 +5082,7 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_function(result, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -4659,7 +5098,7 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_VAR_HANDLER(ZEND_O SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -4674,7 +5113,7 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); bitwise_or_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -4689,7 +5128,7 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); bitwise_and_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -4704,7 +5143,7 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); bitwise_xor_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -4719,7 +5158,7 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); boolean_xor_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -4877,7 +5316,7 @@ static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE { USE_OPLINE - return zend_fetch_var_address_helper_SPEC_CONST_VAR(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_CONST_VAR(ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -4890,14 +5329,44 @@ static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDL return zend_fetch_var_address_helper_SPEC_CONST_VAR(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op2; + zval **container; + + SAVE_OPLINE(); + + if ((opline->extended_value & ZEND_FETCH_ADD_LOCK) && + IS_CONST != IS_CV && + EX_T(opline->op1.var).var.ptr_ptr) { + PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); + } + + if (IS_CONST == IS_TMP_VAR || IS_CONST == IS_CONST) { + zval *container = opline->op1.zv; + zend_fetch_dimension_address_read(&EX_T(opline->result.var), &container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_R TSRMLS_CC); + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + + } else { + container = NULL; + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_R TSRMLS_CC); + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *function_name; zend_class_entry *ce; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); if (IS_CONST == IS_CONST) { /* no function found. try a static method in class */ @@ -4911,24 +5380,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE } CACHE_PTR(opline->op1.literal->cache_slot, ce); } - EX(called_scope) = ce; + call->called_scope = ce; } else { ce = EX_T(opline->op1.var).class_entry; if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) { - EX(called_scope) = EG(called_scope); + call->called_scope = EG(called_scope); } else { - EX(called_scope) = ce; + call->called_scope = ce; } } if (IS_CONST == IS_CONST && IS_VAR == IS_CONST && CACHED_PTR(opline->op2.literal->cache_slot)) { - EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot); + call->fbc = CACHED_PTR(opline->op2.literal->cache_slot); } else if (IS_CONST != IS_CONST && IS_VAR == IS_CONST && - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { /* do nothing */ } else if (IS_VAR != IS_UNUSED) { char *function_name_strval = NULL; @@ -4939,7 +5408,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE function_name_strval = Z_STRVAL_P(opline->op2.zv); function_name_strlen = Z_STRLEN_P(opline->op2.zv); } else { - function_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { zend_error_noreturn(E_ERROR, "Function name must be a string"); @@ -4951,20 +5420,20 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE if (function_name_strval) { if (ce->get_static_method) { - EX(fbc) = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + call->fbc = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); } else { - EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + call->fbc = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); } - if (UNEXPECTED(EX(fbc) == NULL)) { + if (UNEXPECTED(call->fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval); } if (IS_VAR == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { if (IS_CONST == IS_CONST) { - CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc)); + CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } else { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc)); + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, call->fbc); } } } @@ -4978,29 +5447,31 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZE if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name); } - EX(fbc) = ce->constructor; + call->fbc = ce->constructor; } - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { - EX(object) = NULL; + if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) { + call->object = NULL; } else { if (EG(This) && Z_OBJ_HT_P(EG(This))->get_class_entry && !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { /* We are calling method of the other (incompatible) class, but passing $this. This is done for compatibility with php-4. */ - if (EX(fbc)->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } else { /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } } - if ((EX(object) = EG(This))) { - Z_ADDREF_P(EX(object)); - EX(called_scope) = Z_OBJCE_P(EX(object)); + if ((call->object = EG(This))) { + Z_ADDREF_P(call->object); + call->called_scope = Z_OBJCE_P(call->object); } } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -5017,7 +5488,7 @@ static int ZEND_FASTCALL ZEND_CASE_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_A } is_equal_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -5062,7 +5533,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_VAR_HANDLER(ZEND_OPC if (IS_VAR != IS_UNUSED) { zend_free_op free_op2; - zval *offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); ulong hval; switch (Z_TYPE_P(offset)) { @@ -5285,6 +5756,160 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPC ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_CONST != IS_UNUSED) { + + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = opline->op1.zv; + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = NULL; + + if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_CONST == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = opline->op1.zv; + + /* Consts, temporary variables and references need copying */ + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_VAR != IS_UNUSED) { + zend_free_op free_op2; + zval *key = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_UNUSED(int type, ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -5436,7 +6061,7 @@ static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER(ZEND_OPC { USE_OPLINE - return zend_fetch_var_address_helper_SPEC_CONST_UNUSED(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_CONST_UNUSED(ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -5454,9 +6079,9 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER USE_OPLINE zval *function_name; zend_class_entry *ce; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); if (IS_CONST == IS_CONST) { /* no function found. try a static method in class */ @@ -5470,24 +6095,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER } CACHE_PTR(opline->op1.literal->cache_slot, ce); } - EX(called_scope) = ce; + call->called_scope = ce; } else { ce = EX_T(opline->op1.var).class_entry; if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) { - EX(called_scope) = EG(called_scope); + call->called_scope = EG(called_scope); } else { - EX(called_scope) = ce; + call->called_scope = ce; } } if (IS_CONST == IS_CONST && IS_UNUSED == IS_CONST && CACHED_PTR(opline->op2.literal->cache_slot)) { - EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot); + call->fbc = CACHED_PTR(opline->op2.literal->cache_slot); } else if (IS_CONST != IS_CONST && IS_UNUSED == IS_CONST && - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { /* do nothing */ } else if (IS_UNUSED != IS_UNUSED) { char *function_name_strval = NULL; @@ -5510,20 +6135,20 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER if (function_name_strval) { if (ce->get_static_method) { - EX(fbc) = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + call->fbc = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); } else { - EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_UNUSED == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + call->fbc = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_UNUSED == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); } - if (UNEXPECTED(EX(fbc) == NULL)) { + if (UNEXPECTED(call->fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval); } if (IS_UNUSED == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { if (IS_CONST == IS_CONST) { - CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc)); + CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } else { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc)); + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, call->fbc); } } } @@ -5537,29 +6162,31 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name); } - EX(fbc) = ce->constructor; + call->fbc = ce->constructor; } - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { - EX(object) = NULL; + if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) { + call->object = NULL; } else { if (EG(This) && Z_OBJ_HT_P(EG(This))->get_class_entry && !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { /* We are calling method of the other (incompatible) class, but passing $this. This is done for compatibility with php-4. */ - if (EX(fbc)->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } else { /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } } - if ((EX(object) = EG(This))) { - Z_ADDREF_P(EX(object)); - EX(called_scope) = Z_OBJCE_P(EX(object)); + if ((call->object = EG(This))) { + Z_ADDREF_P(call->object); + call->called_scope = Z_OBJCE_P(call->object); } } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -5838,12 +6465,165 @@ static int ZEND_FASTCALL ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_UNUSED_HANDLER zend_error_noreturn(E_ERROR, "Base lambda function for closure not found"); } - zend_create_closure(&EX_T(opline->result.var).tmp_var, op_array, EG(scope), EG(This) TSRMLS_CC); + zend_create_closure(&EX_T(opline->result.var).tmp_var, (zend_function *) op_array, EG(scope), EG(This) TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_CONST != IS_UNUSED) { + + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = opline->op1.zv; + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = NULL; + + if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_CONST == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = opline->op1.zv; + + /* Consts, temporary variables and references need copying */ + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_UNUSED != IS_UNUSED) { + + zval *key = NULL; + + /* Consts, temporary variables and references need copying */ + if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL ZEND_ADD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -5852,7 +6632,7 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); fast_add_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -5867,7 +6647,7 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); fast_sub_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -5882,7 +6662,7 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); fast_mul_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -5897,7 +6677,7 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); fast_div_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -5912,7 +6692,7 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); fast_mod_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -5927,7 +6707,7 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); shift_left_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -5942,7 +6722,7 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); shift_right_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -5957,7 +6737,7 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); concat_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -5972,7 +6752,7 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HA SAVE_OPLINE(); is_identical_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -5988,7 +6768,7 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CONST_CV_HANDLER(ZEND_OPCOD SAVE_OPLINE(); is_identical_function(result, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); Z_LVAL_P(result) = !Z_LVAL_P(result); @@ -6005,7 +6785,7 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLE SAVE_OPLINE(); ZVAL_BOOL(result, fast_equal_function(result, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC)); CHECK_EXCEPTION(); @@ -6021,7 +6801,7 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HA SAVE_OPLINE(); ZVAL_BOOL(result, fast_not_equal_function(result, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC)); CHECK_EXCEPTION(); @@ -6037,7 +6817,7 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_function(result, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC)); CHECK_EXCEPTION(); @@ -6053,7 +6833,7 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_CV_HANDLER(ZEND_OP SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC)); CHECK_EXCEPTION(); @@ -6068,7 +6848,7 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); bitwise_or_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -6083,7 +6863,7 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); bitwise_and_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -6098,7 +6878,7 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); bitwise_xor_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -6113,9 +6893,39 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLE SAVE_OPLINE(); boolean_xor_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); + + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval **container; + + SAVE_OPLINE(); + + if ((opline->extended_value & ZEND_FETCH_ADD_LOCK) && + IS_CONST != IS_CV && + EX_T(opline->op1.var).var.ptr_ptr) { + PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); + } + + if (IS_CONST == IS_TMP_VAR || IS_CONST == IS_CONST) { + zval *container = opline->op1.zv; + zend_fetch_dimension_address_read(&EX_T(opline->result.var), &container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_R TSRMLS_CC); + } else { + container = NULL; + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_R TSRMLS_CC); + + + } + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -6125,9 +6935,9 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN USE_OPLINE zval *function_name; zend_class_entry *ce; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); if (IS_CONST == IS_CONST) { /* no function found. try a static method in class */ @@ -6141,24 +6951,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN } CACHE_PTR(opline->op1.literal->cache_slot, ce); } - EX(called_scope) = ce; + call->called_scope = ce; } else { ce = EX_T(opline->op1.var).class_entry; if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) { - EX(called_scope) = EG(called_scope); + call->called_scope = EG(called_scope); } else { - EX(called_scope) = ce; + call->called_scope = ce; } } if (IS_CONST == IS_CONST && IS_CV == IS_CONST && CACHED_PTR(opline->op2.literal->cache_slot)) { - EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot); + call->fbc = CACHED_PTR(opline->op2.literal->cache_slot); } else if (IS_CONST != IS_CONST && IS_CV == IS_CONST && - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { /* do nothing */ } else if (IS_CV != IS_UNUSED) { char *function_name_strval = NULL; @@ -6169,7 +6979,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN function_name_strval = Z_STRVAL_P(opline->op2.zv); function_name_strlen = Z_STRLEN_P(opline->op2.zv); } else { - function_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { zend_error_noreturn(E_ERROR, "Function name must be a string"); @@ -6181,20 +6991,20 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN if (function_name_strval) { if (ce->get_static_method) { - EX(fbc) = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + call->fbc = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); } else { - EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + call->fbc = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); } - if (UNEXPECTED(EX(fbc) == NULL)) { + if (UNEXPECTED(call->fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval); } if (IS_CV == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { if (IS_CONST == IS_CONST) { - CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc)); + CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } else { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc)); + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, call->fbc); } } } @@ -6208,29 +7018,31 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEN if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name); } - EX(fbc) = ce->constructor; + call->fbc = ce->constructor; } - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { - EX(object) = NULL; + if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) { + call->object = NULL; } else { if (EG(This) && Z_OBJ_HT_P(EG(This))->get_class_entry && !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { /* We are calling method of the other (incompatible) class, but passing $this. This is done for compatibility with php-4. */ - if (EX(fbc)->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } else { /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } } - if ((EX(object) = EG(This))) { - Z_ADDREF_P(EX(object)); - EX(called_scope) = Z_OBJCE_P(EX(object)); + if ((call->object = EG(This))) { + Z_ADDREF_P(call->object); + call->called_scope = Z_OBJCE_P(call->object); } } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -6280,7 +7092,7 @@ static int ZEND_FASTCALL ZEND_CATCH_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_A if (EX_CV(opline->op2.var)) { zval_ptr_dtor(EX_CV(opline->op2.var)); } - EX_CV(opline->op2.var) = (zval**)EX_CVs() + (EX(op_array)->last_var + opline->op2.var); + EX_CV(opline->op2.var) = (zval**)EX_CV_NUM(execute_data, EX(op_array)->last_var + opline->op2.var); *EX_CV(opline->op2.var) = EG(exception); } else { zend_compiled_variable *cv = &CV_DEF_OF(opline->op2.var); @@ -6307,7 +7119,7 @@ static int ZEND_FASTCALL ZEND_CASE_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_AR } is_equal_function(&EX_T(opline->result.var).tmp_var, opline->op1.zv, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -6351,7 +7163,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CV_HANDLER(ZEND_OPCO if (IS_CV != IS_UNUSED) { - zval *offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); ulong hval; switch (Z_TYPE_P(offset)) { @@ -6413,6 +7225,159 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HAND } } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_CONST != IS_UNUSED) { + + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = opline->op1.zv; + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = NULL; + + if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_CONST == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = opline->op1.zv; + + /* Consts, temporary variables and references need copying */ + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_CV != IS_UNUSED) { + + zval *key = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL ZEND_BW_NOT_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -6420,7 +7385,7 @@ static int ZEND_FASTCALL ZEND_BW_NOT_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); bitwise_not_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -6433,7 +7398,7 @@ static int ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); boolean_not_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -6447,7 +7412,7 @@ static int ZEND_FASTCALL ZEND_ECHO_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zval *z; SAVE_OPLINE(); - z = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + z = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && @@ -6486,7 +7451,7 @@ static int ZEND_FASTCALL ZEND_JMPZ_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) int ret; SAVE_OPLINE(); - val = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + val = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) { ret = Z_LVAL_P(val); @@ -6516,7 +7481,7 @@ static int ZEND_FASTCALL ZEND_JMPNZ_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) int ret; SAVE_OPLINE(); - val = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + val = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) { ret = Z_LVAL_P(val); @@ -6546,7 +7511,7 @@ static int ZEND_FASTCALL ZEND_JMPZNZ_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) int retval; SAVE_OPLINE(); - val = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + val = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) { retval = Z_LVAL_P(val); @@ -6580,7 +7545,7 @@ static int ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS int retval; SAVE_OPLINE(); - val = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + val = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) { retval = Z_LVAL_P(val); @@ -6611,7 +7576,7 @@ static int ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG int retval; SAVE_OPLINE(); - val = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + val = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) { retval = Z_LVAL_P(val); @@ -6655,13 +7620,16 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_free_op free_op1; SAVE_OPLINE(); - retval_ptr = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + retval_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (!EG(return_value_ptr_ptr)) { if (IS_TMP_VAR == IS_TMP_VAR) { zval_dtor(free_op1.var); } } else if (!1) { /* Not a temp var */ + if (*EG(return_value_ptr_ptr)) { + zval_ptr_dtor(EG(return_value_ptr_ptr)); + } if (IS_TMP_VAR == IS_CONST || (PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) { zval *ret; @@ -6683,6 +7651,10 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } else { zval *ret; + if (*EG(return_value_ptr_ptr)) { + zval_ptr_dtor(EG(return_value_ptr_ptr)); + } + ALLOC_ZVAL(ret); INIT_PZVAL_COPY(ret, retval_ptr); *EG(return_value_ptr_ptr) = ret; @@ -6701,11 +7673,15 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLE SAVE_OPLINE(); do { + if (EG(return_value_ptr_ptr) && *EG(return_value_ptr_ptr)) { + zval_ptr_dtor(EG(return_value_ptr_ptr)); + } + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { /* Not supposed to happen, but we'll allow it */ zend_error(E_NOTICE, "Only variable references should be returned by reference"); - retval_ptr = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + retval_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (!EG(return_value_ptr_ptr)) { if (IS_TMP_VAR == IS_TMP_VAR) { zval_dtor(free_op1.var); @@ -6766,7 +7742,7 @@ static int ZEND_FASTCALL ZEND_THROW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_free_op free_op1; SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) { zend_error_noreturn(E_ERROR, "Can only throw objects"); @@ -6791,7 +7767,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); if (opline->extended_value==ZEND_DO_FCALL_BY_NAME - && ARG_MUST_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) { + && ARG_MUST_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.opline_num)) { zend_error_noreturn(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.opline_num); } { @@ -6799,7 +7775,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG zval *value; zend_free_op free_op1; - value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); ALLOC_ZVAL(valptr); INIT_PZVAL_COPY(valptr, value); @@ -6821,7 +7797,7 @@ static int ZEND_FASTCALL ZEND_BOOL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); /* PHP 3.0 returned "" for false and 1 for true, here we use 0 and 1 for now */ - ZVAL_BOOL(retval, i_zend_is_true(_get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC))); + ZVAL_BOOL(retval, i_zend_is_true(_get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC))); zval_dtor(free_op1.var); CHECK_EXCEPTION(); @@ -6838,7 +7814,7 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_object_clone_obj_t clone_call; SAVE_OPLINE(); - obj = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + obj = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR == IS_CONST || UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT)) { @@ -6899,7 +7875,7 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zval *result = &EX_T(opline->result.var).tmp_var; SAVE_OPLINE(); - expr = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + expr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (opline->extended_value != IS_STRING) { ZVAL_COPY_VALUE(result, expr); @@ -6956,11 +7932,11 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HAND zend_op_array *new_op_array=NULL; zend_free_op free_op1; zval *inc_filename; - zval *tmp_inc_filename = NULL; + zval *tmp_inc_filename = NULL; zend_bool failure_retval=0; SAVE_OPLINE(); - inc_filename = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + inc_filename = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (inc_filename->type!=IS_STRING) { MAKE_STD_ZVAL(tmp_inc_filename); @@ -7048,8 +8024,6 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HAND EG(return_value_ptr_ptr) = NULL; } - EX(current_object) = EX(object); - EX(function_state).function = (zend_function *) new_op_array; EX(object) = NULL; @@ -7057,14 +8031,13 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HAND zend_rebuild_symbol_table(TSRMLS_C); } - if (EXPECTED(zend_execute == execute)) { + if (EXPECTED(zend_execute_ex == execute_ex)) { ZEND_VM_ENTER(); } else { zend_execute(new_op_array TSRMLS_CC); } EX(function_state).function = (zend_function *) EX(op_array); - EX(object) = EX(current_object); EG(opline_ptr) = &EX(opline); EG(active_op_array) = EX(op_array); @@ -7074,15 +8047,6 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HAND if (UNEXPECTED(EG(exception) != NULL)) { zend_throw_exception_internal(NULL TSRMLS_CC); HANDLE_EXCEPTION(); - } else if (RETURN_VALUE_USED(opline)) { - if (!EX_T(opline->result.var).var.ptr) { /* there was no return statement */ - zval *retval; - - ALLOC_ZVAL(retval); - ZVAL_BOOL(retval, 1); - INIT_PZVAL(retval); - EX_T(opline->result.var).var.ptr = retval; - } } } else if (RETURN_VALUE_USED(opline)) { @@ -7137,7 +8101,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG Z_ADDREF_P(array_ptr); } } else { - array_ptr = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + array_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (1) { /* IS_TMP_VAR */ zval *tmp; @@ -7246,7 +8210,7 @@ static int ZEND_FASTCALL ZEND_EXIT_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); if (IS_TMP_VAR != IS_UNUSED) { zend_free_op free_op1; - zval *ptr = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval *ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (Z_TYPE_P(ptr) == IS_LONG) { EG(exit_status) = Z_LVAL_P(ptr); @@ -7296,7 +8260,7 @@ static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS zval *value; SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (i_zend_is_true(value)) { ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value); @@ -7322,7 +8286,7 @@ static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ zval *value, *ret; SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (i_zend_is_true(value)) { if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) { @@ -7357,7 +8321,7 @@ static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR zval *value; SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value); if (!1) { @@ -7375,7 +8339,7 @@ static int ZEND_FASTCALL ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLE zval *value, *ret; SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) { Z_ADDREF_P(value); @@ -7403,7 +8367,7 @@ static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_A zend_bool result; SAVE_OPLINE(); - expr = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + expr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (Z_TYPE_P(expr) == IS_OBJECT && Z_OBJ_HT_P(expr)->get_class_entry) { result = instanceof_function(Z_OBJCE_P(expr), EX_T(opline->op2.var).class_entry TSRMLS_CC); @@ -7423,7 +8387,7 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_add_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); zval_dtor(free_op1.var); @@ -7438,7 +8402,7 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_sub_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); zval_dtor(free_op1.var); @@ -7453,7 +8417,7 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_mul_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); zval_dtor(free_op1.var); @@ -7468,7 +8432,7 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_div_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); zval_dtor(free_op1.var); @@ -7483,7 +8447,7 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_mod_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); zval_dtor(free_op1.var); @@ -7498,7 +8462,7 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); shift_left_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); zval_dtor(free_op1.var); @@ -7513,7 +8477,7 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); shift_right_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); zval_dtor(free_op1.var); @@ -7528,7 +8492,7 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); concat_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); zval_dtor(free_op1.var); @@ -7543,7 +8507,7 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); is_identical_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); zval_dtor(free_op1.var); @@ -7559,7 +8523,7 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCO SAVE_OPLINE(); is_identical_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); Z_LVAL_P(result) = !Z_LVAL_P(result); zval_dtor(free_op1.var); @@ -7576,7 +8540,7 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); ZVAL_BOOL(result, fast_equal_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC)); zval_dtor(free_op1.var); @@ -7592,7 +8556,7 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); ZVAL_BOOL(result, fast_not_equal_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC)); zval_dtor(free_op1.var); @@ -7608,7 +8572,7 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC)); zval_dtor(free_op1.var); @@ -7624,7 +8588,7 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMP_CONST_HANDLER(ZEND_O SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC)); zval_dtor(free_op1.var); @@ -7639,7 +8603,7 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); bitwise_or_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); zval_dtor(free_op1.var); @@ -7654,7 +8618,7 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); bitwise_and_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); zval_dtor(free_op1.var); @@ -7669,7 +8633,7 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); bitwise_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); zval_dtor(free_op1.var); @@ -7684,7 +8648,7 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); boolean_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); zval_dtor(free_op1.var); @@ -7703,7 +8667,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_CONST(int type, ulong hash_value; SAVE_OPLINE(); - varname = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + varname = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(varname) != IS_STRING)) { ZVAL_COPY_VALUE(&tmp_varname, varname); @@ -7843,7 +8807,7 @@ static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE { USE_OPLINE - return zend_fetch_var_address_helper_SPEC_TMP_CONST(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_TMP_CONST(ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -7856,6 +8820,36 @@ static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDL return zend_fetch_var_address_helper_SPEC_TMP_CONST(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval **container; + + SAVE_OPLINE(); + + if ((opline->extended_value & ZEND_FETCH_ADD_LOCK) && + IS_TMP_VAR != IS_CV && + EX_T(opline->op1.var).var.ptr_ptr) { + PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); + } + + if (IS_TMP_VAR == IS_TMP_VAR || IS_TMP_VAR == IS_CONST) { + zval *container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), &container, opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC); + + zval_dtor(free_op1.var); + } else { + container = NULL; + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC); + + + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_FETCH_DIM_TMP_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -7863,7 +8857,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_TMP_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPC zval *container; SAVE_OPLINE(); - container = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) { PZVAL_LOCK(&EG(uninitialized_zval)); @@ -7933,9 +8927,9 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CONST_HANDLER(ZEND_OPCO char *function_name_strval; int function_name_strlen; zend_free_op free_op1; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); function_name = opline->op2.zv; @@ -7947,49 +8941,51 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CONST_HANDLER(ZEND_OPCO function_name_strval = Z_STRVAL_P(function_name); function_name_strlen = Z_STRLEN_P(function_name); - EX(object) = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + call->object = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (EXPECTED(EX(object) != NULL) && - EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) { - EX(called_scope) = Z_OBJCE_P(EX(object)); + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); if (IS_CONST != IS_CONST || - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) { - zval *object = EX(object); + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; - if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) { + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { zend_error_noreturn(E_ERROR, "Object does not support method calls"); } /* First, locate the function. */ - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); } if (IS_CONST == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(EX(object) == object)) { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc)); + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); } } } else { zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); @@ -8006,7 +9002,7 @@ static int ZEND_FASTCALL ZEND_CASE_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_A PZVAL_LOCK(EX_T(opline->op1.var).var.ptr); } is_equal_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); CHECK_EXCEPTION(); @@ -8030,7 +9026,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER(ZEND_OPC expr_ptr = *expr_ptr_ptr; Z_ADDREF_P(expr_ptr); } else { - expr_ptr=_get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + expr_ptr=_get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (1) { /* temporary variable */ zval *new_expr; @@ -8137,7 +9133,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HAND ZEND_VM_NEXT_OPCODE(); } - varname = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + varname = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, varname); @@ -8213,7 +9209,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPC } else { HashTable *target_symbol_table; zend_free_op free_op1; - zval tmp, *varname = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval tmp, *varname = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, varname); @@ -8274,6 +9270,159 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPC ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_TMP_VAR != IS_UNUSED) { + zend_free_op free_op1; + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!1) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = NULL; + + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_TMP_VAR == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!1) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_CONST != IS_UNUSED) { + + zval *key = opline->op2.zv; + + /* Consts, temporary variables and references need copying */ + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL ZEND_ADD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -8281,8 +9430,8 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_add_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -8296,8 +9445,8 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_sub_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -8311,8 +9460,8 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_mul_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -8326,8 +9475,8 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_div_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -8341,8 +9490,8 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_mod_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -8356,8 +9505,8 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_left_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -8371,8 +9520,8 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_right_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -8386,8 +9535,8 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); concat_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -8401,8 +9550,8 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); is_identical_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -8417,8 +9566,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE SAVE_OPLINE(); is_identical_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); Z_LVAL_P(result) = !Z_LVAL_P(result); zval_dtor(free_op1.var); zval_dtor(free_op2.var); @@ -8434,8 +9583,8 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); ZVAL_BOOL(result, fast_equal_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op1.var); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -8450,8 +9599,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); ZVAL_BOOL(result, fast_not_equal_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op1.var); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -8466,8 +9615,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op1.var); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -8482,8 +9631,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMP_TMP_HANDLER(ZEND_OPC SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op1.var); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -8497,8 +9646,8 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); bitwise_or_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -8512,8 +9661,8 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); bitwise_and_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -8527,8 +9676,8 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); bitwise_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -8542,14 +9691,44 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); boolean_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); zval_dtor(free_op2.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1, free_op2; + zval **container; + + SAVE_OPLINE(); + + if ((opline->extended_value & ZEND_FETCH_ADD_LOCK) && + IS_TMP_VAR != IS_CV && + EX_T(opline->op1.var).var.ptr_ptr) { + PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); + } + + if (IS_TMP_VAR == IS_TMP_VAR || IS_TMP_VAR == IS_CONST) { + zval *container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), &container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_R TSRMLS_CC); + zval_dtor(free_op2.var); + zval_dtor(free_op1.var); + } else { + container = NULL; + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_R TSRMLS_CC); + zval_dtor(free_op2.var); + + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -8560,7 +9739,7 @@ static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ int use_copy = 0; SAVE_OPLINE(); - var = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + var = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_TMP_VAR == IS_UNUSED) { /* Initialize for erealloc in add_string_to_string */ @@ -8602,11 +9781,11 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE char *function_name_strval; int function_name_strlen; zend_free_op free_op1, free_op2; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); - function_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + function_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_TMP_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -8616,49 +9795,51 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE function_name_strval = Z_STRVAL_P(function_name); function_name_strlen = Z_STRLEN_P(function_name); - EX(object) = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + call->object = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (EXPECTED(EX(object) != NULL) && - EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) { - EX(called_scope) = Z_OBJCE_P(EX(object)); + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); if (IS_TMP_VAR != IS_CONST || - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) { - zval *object = EX(object); + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; - if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) { + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { zend_error_noreturn(E_ERROR, "Object does not support method calls"); } /* First, locate the function. */ - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); } if (IS_TMP_VAR == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(EX(object) == object)) { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc)); + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); } } } else { zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } + call->is_ctor_call = 0; + EX(call) = call; zval_dtor(free_op2.var); @@ -8676,8 +9857,8 @@ static int ZEND_FASTCALL ZEND_CASE_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG PZVAL_LOCK(EX_T(opline->op1.var).var.ptr); } is_equal_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -8701,7 +9882,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMP_HANDLER(ZEND_OPCOD expr_ptr = *expr_ptr_ptr; Z_ADDREF_P(expr_ptr); } else { - expr_ptr=_get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + expr_ptr=_get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (1) { /* temporary variable */ zval *new_expr; @@ -8722,7 +9903,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMP_HANDLER(ZEND_OPCOD if (IS_TMP_VAR != IS_UNUSED) { zend_free_op free_op2; - zval *offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); ulong hval; switch (Z_TYPE_P(offset)) { @@ -8784,6 +9965,159 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDL } } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_TMP_VAR != IS_UNUSED) { + zend_free_op free_op1; + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!1) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = NULL; + + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_TMP_VAR == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!1) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_TMP_VAR != IS_UNUSED) { + zend_free_op free_op2; + zval *key = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!1) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL ZEND_ADD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -8791,8 +10125,8 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_add_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -8806,8 +10140,8 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_sub_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -8821,8 +10155,8 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_mul_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -8836,8 +10170,8 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_div_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -8851,8 +10185,8 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_mod_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -8866,8 +10200,8 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_left_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -8881,8 +10215,8 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_right_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -8896,8 +10230,8 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); concat_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -8911,8 +10245,8 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); is_identical_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -8927,8 +10261,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE SAVE_OPLINE(); is_identical_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); Z_LVAL_P(result) = !Z_LVAL_P(result); zval_dtor(free_op1.var); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; @@ -8944,8 +10278,8 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); ZVAL_BOOL(result, fast_equal_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op1.var); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -8960,8 +10294,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); ZVAL_BOOL(result, fast_not_equal_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op1.var); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -8976,8 +10310,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op1.var); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -8992,8 +10326,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMP_VAR_HANDLER(ZEND_OPC SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op1.var); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -9007,8 +10341,8 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); bitwise_or_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -9022,8 +10356,8 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); bitwise_and_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -9037,8 +10371,8 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); bitwise_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -9052,8 +10386,8 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); boolean_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -9071,7 +10405,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_VAR(int type, ZE ulong hash_value; SAVE_OPLINE(); - varname = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + varname = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(varname) != IS_STRING)) { ZVAL_COPY_VALUE(&tmp_varname, varname); @@ -9211,7 +10545,7 @@ static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_H { USE_OPLINE - return zend_fetch_var_address_helper_SPEC_TMP_VAR(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_TMP_VAR(ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -9224,6 +10558,36 @@ static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER return zend_fetch_var_address_helper_SPEC_TMP_VAR(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1, free_op2; + zval **container; + + SAVE_OPLINE(); + + if ((opline->extended_value & ZEND_FETCH_ADD_LOCK) && + IS_TMP_VAR != IS_CV && + EX_T(opline->op1.var).var.ptr_ptr) { + PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); + } + + if (IS_TMP_VAR == IS_TMP_VAR || IS_TMP_VAR == IS_CONST) { + zval *container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), &container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_R TSRMLS_CC); + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + zval_dtor(free_op1.var); + } else { + container = NULL; + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_R TSRMLS_CC); + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -9234,7 +10598,7 @@ static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ int use_copy = 0; SAVE_OPLINE(); - var = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + var = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_TMP_VAR == IS_UNUSED) { /* Initialize for erealloc in add_string_to_string */ @@ -9276,11 +10640,11 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE char *function_name_strval; int function_name_strlen; zend_free_op free_op1, free_op2; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); - function_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -9290,49 +10654,51 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE function_name_strval = Z_STRVAL_P(function_name); function_name_strlen = Z_STRLEN_P(function_name); - EX(object) = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + call->object = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (EXPECTED(EX(object) != NULL) && - EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) { - EX(called_scope) = Z_OBJCE_P(EX(object)); + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); if (IS_VAR != IS_CONST || - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) { - zval *object = EX(object); + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; - if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) { + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { zend_error_noreturn(E_ERROR, "Object does not support method calls"); } /* First, locate the function. */ - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); } if (IS_VAR == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(EX(object) == object)) { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc)); + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); } } } else { zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } + call->is_ctor_call = 0; + EX(call) = call; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; @@ -9350,8 +10716,8 @@ static int ZEND_FASTCALL ZEND_CASE_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG PZVAL_LOCK(EX_T(opline->op1.var).var.ptr); } is_equal_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -9375,7 +10741,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_VAR_HANDLER(ZEND_OPCOD expr_ptr = *expr_ptr_ptr; Z_ADDREF_P(expr_ptr); } else { - expr_ptr=_get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + expr_ptr=_get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (1) { /* temporary variable */ zval *new_expr; @@ -9396,7 +10762,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_VAR_HANDLER(ZEND_OPCOD if (IS_VAR != IS_UNUSED) { zend_free_op free_op2; - zval *offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); ulong hval; switch (Z_TYPE_P(offset)) { @@ -9482,7 +10848,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLE ZEND_VM_NEXT_OPCODE(); } - varname = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + varname = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, varname); @@ -9558,7 +10924,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCOD } else { HashTable *target_symbol_table; zend_free_op free_op1; - zval tmp, *varname = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval tmp, *varname = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, varname); @@ -9619,6 +10985,160 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCOD ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_TMP_VAR != IS_UNUSED) { + zend_free_op free_op1; + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!1) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = NULL; + + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_TMP_VAR == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!1) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_VAR != IS_UNUSED) { + zend_free_op free_op2; + zval *key = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_UNUSED(int type, ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -9630,7 +11150,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP_UNUSED(int type, ulong hash_value; SAVE_OPLINE(); - varname = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + varname = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(varname) != IS_STRING)) { ZVAL_COPY_VALUE(&tmp_varname, varname); @@ -9770,7 +11290,7 @@ static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCOD { USE_OPLINE - return zend_fetch_var_address_helper_SPEC_TMP_UNUSED(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_TMP_UNUSED(ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -9800,7 +11320,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OP expr_ptr = *expr_ptr_ptr; Z_ADDREF_P(expr_ptr); } else { - expr_ptr=_get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + expr_ptr=_get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (1) { /* temporary variable */ zval *new_expr; @@ -9907,7 +11427,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HAN ZEND_VM_NEXT_OPCODE(); } - varname = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + varname = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, varname); @@ -9983,7 +11503,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OP } else { HashTable *target_symbol_table; zend_free_op free_op1; - zval tmp, *varname = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval tmp, *varname = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_TMP_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, varname); @@ -10044,6 +11564,159 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_UNUSED_HANDLER(ZEND_OP ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_TMP_VAR != IS_UNUSED) { + zend_free_op free_op1; + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!1) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = NULL; + + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_TMP_VAR == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!1) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_UNUSED != IS_UNUSED) { + + zval *key = NULL; + + /* Consts, temporary variables and references need copying */ + if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL ZEND_ADD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -10051,8 +11724,8 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_add_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); CHECK_EXCEPTION(); @@ -10066,8 +11739,8 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_sub_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); CHECK_EXCEPTION(); @@ -10081,8 +11754,8 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_mul_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); CHECK_EXCEPTION(); @@ -10096,8 +11769,8 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_div_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); CHECK_EXCEPTION(); @@ -10111,8 +11784,8 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_mod_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); CHECK_EXCEPTION(); @@ -10126,8 +11799,8 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_left_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); CHECK_EXCEPTION(); @@ -10141,8 +11814,8 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_right_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); CHECK_EXCEPTION(); @@ -10156,8 +11829,8 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); concat_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); CHECK_EXCEPTION(); @@ -10171,8 +11844,8 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); is_identical_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); CHECK_EXCEPTION(); @@ -10187,8 +11860,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_ SAVE_OPLINE(); is_identical_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); Z_LVAL_P(result) = !Z_LVAL_P(result); zval_dtor(free_op1.var); @@ -10204,8 +11877,8 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); ZVAL_BOOL(result, fast_equal_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op1.var); CHECK_EXCEPTION(); @@ -10220,8 +11893,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); ZVAL_BOOL(result, fast_not_equal_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op1.var); CHECK_EXCEPTION(); @@ -10236,8 +11909,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLE SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op1.var); CHECK_EXCEPTION(); @@ -10252,8 +11925,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMP_CV_HANDLER(ZEND_OPCO SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op1.var); CHECK_EXCEPTION(); @@ -10267,8 +11940,8 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); bitwise_or_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); CHECK_EXCEPTION(); @@ -10282,8 +11955,8 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); bitwise_and_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); CHECK_EXCEPTION(); @@ -10297,8 +11970,8 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); bitwise_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); CHECK_EXCEPTION(); @@ -10312,14 +11985,44 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); boolean_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op1.var); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval **container; + + SAVE_OPLINE(); + + if ((opline->extended_value & ZEND_FETCH_ADD_LOCK) && + IS_TMP_VAR != IS_CV && + EX_T(opline->op1.var).var.ptr_ptr) { + PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); + } + + if (IS_TMP_VAR == IS_TMP_VAR || IS_TMP_VAR == IS_CONST) { + zval *container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), &container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_R TSRMLS_CC); + + zval_dtor(free_op1.var); + } else { + container = NULL; + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_R TSRMLS_CC); + + + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -10330,7 +12033,7 @@ static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_A int use_copy = 0; SAVE_OPLINE(); - var = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + var = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_TMP_VAR == IS_UNUSED) { /* Initialize for erealloc in add_string_to_string */ @@ -10371,11 +12074,11 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_ char *function_name_strval; int function_name_strlen; zend_free_op free_op1; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); - function_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_CV != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -10385,49 +12088,51 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_ function_name_strval = Z_STRVAL_P(function_name); function_name_strlen = Z_STRLEN_P(function_name); - EX(object) = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + call->object = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (EXPECTED(EX(object) != NULL) && - EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) { - EX(called_scope) = Z_OBJCE_P(EX(object)); + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); if (IS_CV != IS_CONST || - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) { - zval *object = EX(object); + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; - if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) { + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { zend_error_noreturn(E_ERROR, "Object does not support method calls"); } /* First, locate the function. */ - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); } if (IS_CV == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(EX(object) == object)) { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc)); + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); } } } else { zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); @@ -10444,8 +12149,8 @@ static int ZEND_FASTCALL ZEND_CASE_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS PZVAL_LOCK(EX_T(opline->op1.var).var.ptr); } is_equal_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -10468,7 +12173,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE expr_ptr = *expr_ptr_ptr; Z_ADDREF_P(expr_ptr); } else { - expr_ptr=_get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + expr_ptr=_get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (1) { /* temporary variable */ zval *new_expr; @@ -10489,7 +12194,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE if (IS_CV != IS_UNUSED) { - zval *offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); ulong hval; switch (Z_TYPE_P(offset)) { @@ -10551,6 +12256,159 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLE } } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_TMP_VAR != IS_UNUSED) { + zend_free_op free_op1; + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!1) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = NULL; + + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_TMP_VAR == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!1) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_CV != IS_UNUSED) { + + zval *key = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL ZEND_BW_NOT_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -10558,7 +12416,7 @@ static int ZEND_FASTCALL ZEND_BW_NOT_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); bitwise_not_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -10571,7 +12429,7 @@ static int ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); boolean_not_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -10584,7 +12442,7 @@ static int ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS zval **var_ptr; SAVE_OPLINE(); - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); @@ -10631,7 +12489,7 @@ static int ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS zval **var_ptr; SAVE_OPLINE(); - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); @@ -10678,7 +12536,7 @@ static int ZEND_FASTCALL ZEND_POST_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG zval **var_ptr, *retval; SAVE_OPLINE(); - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); @@ -10721,7 +12579,7 @@ static int ZEND_FASTCALL ZEND_POST_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG zval **var_ptr, *retval; SAVE_OPLINE(); - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); @@ -10765,7 +12623,7 @@ static int ZEND_FASTCALL ZEND_ECHO_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zval *z; SAVE_OPLINE(); - z = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + z = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && @@ -10804,7 +12662,7 @@ static int ZEND_FASTCALL ZEND_JMPZ_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) int ret; SAVE_OPLINE(); - val = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + val = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) { ret = Z_LVAL_P(val); @@ -10834,7 +12692,7 @@ static int ZEND_FASTCALL ZEND_JMPNZ_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) int ret; SAVE_OPLINE(); - val = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + val = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) { ret = Z_LVAL_P(val); @@ -10864,7 +12722,7 @@ static int ZEND_FASTCALL ZEND_JMPZNZ_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) int retval; SAVE_OPLINE(); - val = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + val = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) { retval = Z_LVAL_P(val); @@ -10898,7 +12756,7 @@ static int ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS int retval; SAVE_OPLINE(); - val = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + val = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) { retval = Z_LVAL_P(val); @@ -10929,7 +12787,7 @@ static int ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG int retval; SAVE_OPLINE(); - val = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + val = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) { retval = Z_LVAL_P(val); @@ -10973,13 +12831,16 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_free_op free_op1; SAVE_OPLINE(); - retval_ptr = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + retval_ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (!EG(return_value_ptr_ptr)) { if (IS_VAR == IS_TMP_VAR) { if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; } } else if (!0) { /* Not a temp var */ + if (*EG(return_value_ptr_ptr)) { + zval_ptr_dtor(EG(return_value_ptr_ptr)); + } if (IS_VAR == IS_CONST || (PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) { zval *ret; @@ -11001,6 +12862,10 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } else { zval *ret; + if (*EG(return_value_ptr_ptr)) { + zval_ptr_dtor(EG(return_value_ptr_ptr)); + } + ALLOC_ZVAL(ret); INIT_PZVAL_COPY(ret, retval_ptr); *EG(return_value_ptr_ptr) = ret; @@ -11019,11 +12884,15 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLE SAVE_OPLINE(); do { + if (EG(return_value_ptr_ptr) && *EG(return_value_ptr_ptr)) { + zval_ptr_dtor(EG(return_value_ptr_ptr)); + } + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { /* Not supposed to happen, but we'll allow it */ zend_error(E_NOTICE, "Only variable references should be returned by reference"); - retval_ptr = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + retval_ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (!EG(return_value_ptr_ptr)) { if (IS_VAR == IS_TMP_VAR) { if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -11045,7 +12914,7 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLE break; } - retval_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + retval_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(retval_ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference"); @@ -11085,7 +12954,7 @@ static int ZEND_FASTCALL ZEND_THROW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_free_op free_op1; SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) { zend_error_noreturn(E_ERROR, "Can only throw objects"); @@ -11109,7 +12978,7 @@ static int ZEND_FASTCALL zend_send_by_var_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_AR USE_OPLINE zval *varptr; zend_free_op free_op1; - varptr = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + varptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (varptr == &EG(uninitialized_zval)) { ALLOC_ZVAL(varptr); @@ -11143,7 +13012,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND if (!(opline->extended_value & ZEND_ARG_SEND_BY_REF)) { return zend_send_by_var_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } - } else if (!ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) { + } else if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.opline_num)) { return zend_send_by_var_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } @@ -11154,7 +13023,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND varptr = EX_T(opline->op1.var).var.ptr; PZVAL_UNLOCK_EX(varptr, &free_op1, 0); } else { - varptr = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + varptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); } if ((!(opline->extended_value & ZEND_ARG_SEND_FUNCTION) || EX_T(opline->op1.var).var.fcall_returned_reference) && @@ -11169,7 +13038,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND if ((opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) ? !(opline->extended_value & ZEND_ARG_SEND_SILENT) : - !ARG_MAY_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) { + !ARG_MAY_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.opline_num)) { zend_error(E_STRICT, "Only variables should be passed by reference"); } ALLOC_ZVAL(valptr); @@ -11192,7 +13061,7 @@ static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG zval *varptr; SAVE_OPLINE(); - varptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + varptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(varptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Only variables can be passed by reference"); @@ -11205,7 +13074,7 @@ static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG ZEND_VM_NEXT_OPCODE(); } - if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION && !ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) { + if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION && !ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.opline_num)) { return zend_send_by_var_helper_SPEC_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } @@ -11224,7 +13093,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG USE_OPLINE if ((opline->extended_value == ZEND_DO_FCALL_BY_NAME) - && ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) { + && ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.opline_num)) { return ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } SAVE_OPLINE(); @@ -11239,7 +13108,7 @@ static int ZEND_FASTCALL ZEND_BOOL_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); /* PHP 3.0 returned "" for false and 1 for true, here we use 0 and 1 for now */ - ZVAL_BOOL(retval, i_zend_is_true(_get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC))); + ZVAL_BOOL(retval, i_zend_is_true(_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC))); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -11266,7 +13135,7 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_object_clone_obj_t clone_call; SAVE_OPLINE(); - obj = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + obj = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_CONST || UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT)) { @@ -11327,7 +13196,7 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zval *result = &EX_T(opline->result.var).tmp_var; SAVE_OPLINE(); - expr = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + expr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (opline->extended_value != IS_STRING) { ZVAL_COPY_VALUE(result, expr); @@ -11384,11 +13253,11 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND zend_op_array *new_op_array=NULL; zend_free_op free_op1; zval *inc_filename; - zval *tmp_inc_filename = NULL; + zval *tmp_inc_filename = NULL; zend_bool failure_retval=0; SAVE_OPLINE(); - inc_filename = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + inc_filename = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (inc_filename->type!=IS_STRING) { MAKE_STD_ZVAL(tmp_inc_filename); @@ -11476,8 +13345,6 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND EG(return_value_ptr_ptr) = NULL; } - EX(current_object) = EX(object); - EX(function_state).function = (zend_function *) new_op_array; EX(object) = NULL; @@ -11485,14 +13352,13 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND zend_rebuild_symbol_table(TSRMLS_C); } - if (EXPECTED(zend_execute == execute)) { + if (EXPECTED(zend_execute_ex == execute_ex)) { ZEND_VM_ENTER(); } else { zend_execute(new_op_array TSRMLS_CC); } EX(function_state).function = (zend_function *) EX(op_array); - EX(object) = EX(current_object); EG(opline_ptr) = &EX(opline); EG(active_op_array) = EX(op_array); @@ -11502,15 +13368,6 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND if (UNEXPECTED(EG(exception) != NULL)) { zend_throw_exception_internal(NULL TSRMLS_CC); HANDLE_EXCEPTION(); - } else if (RETURN_VALUE_USED(opline)) { - if (!EX_T(opline->result.var).var.ptr) { /* there was no return statement */ - zval *retval; - - ALLOC_ZVAL(retval); - ZVAL_BOOL(retval, 1); - INIT_PZVAL(retval); - EX_T(opline->result.var).var.ptr = retval; - } } } else if (RETURN_VALUE_USED(opline)) { @@ -11538,7 +13395,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && (opline->extended_value & ZEND_FE_RESET_VARIABLE)) { - array_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + array_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (array_ptr_ptr == NULL || array_ptr_ptr == &EG(uninitialized_zval_ptr)) { MAKE_STD_ZVAL(array_ptr); ZVAL_NULL(array_ptr); @@ -11565,7 +13422,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG Z_ADDREF_P(array_ptr); } } else { - array_ptr = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + array_ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (0) { /* IS_TMP_VAR */ zval *tmp; @@ -11817,7 +13674,7 @@ static int ZEND_FASTCALL ZEND_EXIT_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); if (IS_VAR != IS_UNUSED) { zend_free_op free_op1; - zval *ptr = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval *ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (Z_TYPE_P(ptr) == IS_LONG) { EG(exit_status) = Z_LVAL_P(ptr); @@ -11838,7 +13695,7 @@ static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS zval *value; SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (i_zend_is_true(value)) { ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value); @@ -11864,7 +13721,7 @@ static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ zval *value, *ret; SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (i_zend_is_true(value)) { if (IS_VAR == IS_VAR || IS_VAR == IS_CV) { @@ -11899,7 +13756,7 @@ static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR zval *value; SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value); if (!0) { @@ -11917,7 +13774,7 @@ static int ZEND_FASTCALL ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLE zval *value, *ret; SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR || IS_VAR == IS_CV) { Z_ADDREF_P(value); @@ -11946,7 +13803,7 @@ static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_A zend_bool result; SAVE_OPLINE(); - expr = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + expr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (Z_TYPE_P(expr) == IS_OBJECT && Z_OBJ_HT_P(expr)->get_class_entry) { result = instanceof_function(Z_OBJCE_P(expr), EX_T(opline->op2.var).class_entry TSRMLS_CC); @@ -11966,7 +13823,7 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_add_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -11981,7 +13838,7 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_sub_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -11996,7 +13853,7 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_mul_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -12011,7 +13868,7 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_div_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -12026,7 +13883,7 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); fast_mod_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -12041,7 +13898,7 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); shift_left_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -12056,7 +13913,7 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); shift_right_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -12071,7 +13928,7 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); concat_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -12086,7 +13943,7 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); is_identical_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -12102,7 +13959,7 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCO SAVE_OPLINE(); is_identical_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); Z_LVAL_P(result) = !Z_LVAL_P(result); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -12119,7 +13976,7 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); ZVAL_BOOL(result, fast_equal_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC)); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -12135,7 +13992,7 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); ZVAL_BOOL(result, fast_not_equal_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC)); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -12151,7 +14008,7 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC)); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -12167,7 +14024,7 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_VAR_CONST_HANDLER(ZEND_O SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC)); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -12182,7 +14039,7 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); bitwise_or_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -12197,7 +14054,7 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); bitwise_and_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -12212,7 +14069,7 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); bitwise_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -12227,7 +14084,7 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); boolean_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -12239,10 +14096,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(int (*b { USE_OPLINE zend_free_op free_op1, free_op_data1; - zval **object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval **object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zval *object; zval *property = opline->op2.zv; - zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); + zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); int have_get_ptr = 0; if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -12360,7 +14217,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_CONST(int (*binar return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); break; case ZEND_ASSIGN_DIM: { - zval **container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval **container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -12373,14 +14230,14 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_CONST(int (*binar zval *dim = opline->op2.zv; zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_CONST, BP_VAR_RW TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } } break; default: value = opline->op2.zv; - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); /* do nothing */ break; } @@ -12502,7 +14359,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CONST(incdec_t int have_get_ptr = 0; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); property = opline->op2.zv; retval = &EX_T(opline->result.var).var.ptr; @@ -12606,7 +14463,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CONST(incdec_ int have_get_ptr = 0; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); property = opline->op2.zv; retval = &EX_T(opline->result.var).tmp_var; @@ -12708,7 +14565,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_CONST(int type, ulong hash_value; SAVE_OPLINE(); - varname = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(varname) != IS_STRING)) { ZVAL_COPY_VALUE(&tmp_varname, varname); @@ -12848,7 +14705,7 @@ static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE { USE_OPLINE - return zend_fetch_var_address_helper_SPEC_VAR_CONST(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_VAR_CONST(ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -12874,10 +14731,19 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HA EX_T(opline->op1.var).var.ptr_ptr) { PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); } - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC); - if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + if (IS_VAR == IS_TMP_VAR || IS_VAR == IS_CONST) { + zval *container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), &container, opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC); + + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + } else { + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC); + + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + } + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -12889,7 +14755,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HA zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -12923,7 +14789,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_H zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -12945,7 +14811,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_H zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, opline->op2.zv, IS_CONST, BP_VAR_IS TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -12961,8 +14827,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OP SAVE_OPLINE(); - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } @@ -12974,7 +14840,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OP if (IS_CONST == IS_UNUSED) { zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); } - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC); } @@ -12990,7 +14856,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCOD zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_CV) { if (container != &EG(uninitialized_zval_ptr)) { @@ -13008,6 +14874,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCOD if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (UNEXPECTED(EX_T(opline->result.var).var.ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_NEXT_OPCODE(); } else { zend_free_op free_res; zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr; @@ -13032,7 +14899,7 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_CONST( zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = opline->op2.zv; if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || @@ -13089,7 +14956,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HA if (0) { MAKE_REAL_ZVAL_PTR(property); } - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -13129,7 +14996,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); property = opline->op2.zv; - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property); @@ -13160,7 +15027,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_H zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = opline->op2.zv; if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || @@ -13197,7 +15064,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OP { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1; zval *property; @@ -13205,7 +15072,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OP SAVE_OPLINE(); property = opline->op2.zv; - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property); @@ -13238,7 +15105,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCOD zval *property; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); property = opline->op2.zv; if (IS_VAR == IS_CV) { @@ -13281,7 +15148,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN zval *property_name; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); property_name = opline->op2.zv; if (0) { @@ -13290,7 +15157,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (0) { zval_ptr_dtor(&property_name); } else { @@ -13310,7 +15177,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN zval **object_ptr; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -13322,7 +15189,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN if (0) { MAKE_REAL_ZVAL_PTR(property_name); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_DIM, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (0) { zval_ptr_dtor(&property_name); } else { @@ -13336,8 +15203,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), object_ptr, dim, IS_CONST, BP_VAR_W TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); if (UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) { if (RETURN_VALUE_USED(opline)) { @@ -13392,7 +15259,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); value = opline->op2.zv; - variable_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + variable_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T(opline->op1.var), value, IS_CONST TSRMLS_CC)) { @@ -13445,9 +15312,9 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCO char *function_name_strval; int function_name_strlen; zend_free_op free_op1; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); function_name = opline->op2.zv; @@ -13459,49 +15326,51 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCO function_name_strval = Z_STRVAL_P(function_name); function_name_strlen = Z_STRLEN_P(function_name); - EX(object) = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + call->object = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (EXPECTED(EX(object) != NULL) && - EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) { - EX(called_scope) = Z_OBJCE_P(EX(object)); + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); if (IS_CONST != IS_CONST || - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) { - zval *object = EX(object); + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; - if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) { + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { zend_error_noreturn(E_ERROR, "Object does not support method calls"); } /* First, locate the function. */ - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); } if (IS_CONST == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(EX(object) == object)) { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc)); + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); } } } else { zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } + call->is_ctor_call = 0; + EX(call) = call; if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -13514,9 +15383,9 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE USE_OPLINE zval *function_name; zend_class_entry *ce; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); if (IS_VAR == IS_CONST) { /* no function found. try a static method in class */ @@ -13530,24 +15399,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE } CACHE_PTR(opline->op1.literal->cache_slot, ce); } - EX(called_scope) = ce; + call->called_scope = ce; } else { ce = EX_T(opline->op1.var).class_entry; if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) { - EX(called_scope) = EG(called_scope); + call->called_scope = EG(called_scope); } else { - EX(called_scope) = ce; + call->called_scope = ce; } } if (IS_VAR == IS_CONST && IS_CONST == IS_CONST && CACHED_PTR(opline->op2.literal->cache_slot)) { - EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot); + call->fbc = CACHED_PTR(opline->op2.literal->cache_slot); } else if (IS_VAR != IS_CONST && IS_CONST == IS_CONST && - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { /* do nothing */ } else if (IS_CONST != IS_UNUSED) { char *function_name_strval = NULL; @@ -13570,20 +15439,20 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE if (function_name_strval) { if (ce->get_static_method) { - EX(fbc) = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + call->fbc = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); } else { - EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + call->fbc = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); } - if (UNEXPECTED(EX(fbc) == NULL)) { + if (UNEXPECTED(call->fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval); } if (IS_CONST == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { if (IS_VAR == IS_CONST) { - CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc)); + CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } else { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc)); + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, call->fbc); } } } @@ -13597,29 +15466,31 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZE if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name); } - EX(fbc) = ce->constructor; + call->fbc = ce->constructor; } - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { - EX(object) = NULL; + if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) { + call->object = NULL; } else { if (EG(This) && Z_OBJ_HT_P(EG(This))->get_class_entry && !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { /* We are calling method of the other (incompatible) class, but passing $this. This is done for compatibility with php-4. */ - if (EX(fbc)->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } else { /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } } - if ((EX(object) = EG(This))) { - Z_ADDREF_P(EX(object)); - EX(called_scope) = Z_OBJCE_P(EX(object)); + if ((call->object = EG(This))) { + Z_ADDREF_P(call->object); + call->called_scope = Z_OBJCE_P(call->object); } } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -13635,7 +15506,7 @@ static int ZEND_FASTCALL ZEND_CASE_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_A PZVAL_LOCK(EX_T(opline->op1.var).var.ptr); } is_equal_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), opline->op2.zv TSRMLS_CC); CHECK_EXCEPTION(); @@ -13742,7 +15613,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPC SAVE_OPLINE(); if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && opline->extended_value) { - zval **expr_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval **expr_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); @@ -13751,7 +15622,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPC expr_ptr = *expr_ptr_ptr; Z_ADDREF_P(expr_ptr); } else { - expr_ptr=_get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + expr_ptr=_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (0) { /* temporary variable */ zval *new_expr; @@ -13858,7 +15729,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND ZEND_VM_NEXT_OPCODE(); } - varname = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, varname); @@ -13919,7 +15790,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND ulong hval; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } @@ -14018,7 +15889,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAND zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = opline->op2.zv; if (IS_VAR != IS_VAR || container) { @@ -14075,7 +15946,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_CONST_HANDLER(ZEND_OPC } else { HashTable *target_symbol_table; zend_free_op free_op1; - zval tmp, *varname = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval tmp, *varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, varname); @@ -14147,7 +16018,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_CONST( zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); offset = opline->op2.zv; @@ -14290,6 +16161,161 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_CONST_HANDLER(ZEN return zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_CONST(1, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_VAR != IS_UNUSED) { + zend_free_op free_op1; + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_VAR == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + } + } else { + zval *value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_CONST != IS_UNUSED) { + + zval *key = opline->op2.zv; + + /* Consts, temporary variables and references need copying */ + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL ZEND_ADD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -14297,8 +16323,8 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_add_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -14312,8 +16338,8 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_sub_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -14327,8 +16353,8 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_mul_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -14342,8 +16368,8 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_div_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -14357,8 +16383,8 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_mod_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -14372,8 +16398,8 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_left_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -14387,8 +16413,8 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_right_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -14402,8 +16428,8 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); concat_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -14417,8 +16443,8 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); is_identical_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -14433,8 +16459,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE SAVE_OPLINE(); is_identical_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); Z_LVAL_P(result) = !Z_LVAL_P(result); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; zval_dtor(free_op2.var); @@ -14450,8 +16476,8 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); ZVAL_BOOL(result, fast_equal_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -14466,8 +16492,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); ZVAL_BOOL(result, fast_not_equal_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -14482,8 +16508,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -14498,8 +16524,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_VAR_TMP_HANDLER(ZEND_OPC SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -14513,8 +16539,8 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); bitwise_or_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -14528,8 +16554,8 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); bitwise_and_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -14543,8 +16569,8 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); bitwise_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -14558,8 +16584,8 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); boolean_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -14570,10 +16596,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(int (*bin { USE_OPLINE zend_free_op free_op1, free_op2, free_op_data1; - zval **object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval **object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zval *object; - zval *property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); + zval *property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); int have_get_ptr = 0; if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -14691,7 +16717,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_TMP(int (*binary_ return zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); break; case ZEND_ASSIGN_DIM: { - zval **container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval **container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -14701,17 +16727,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_TMP(int (*binary_ } return zend_binary_assign_op_obj_helper_SPEC_VAR_TMP(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { - zval *dim = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_TMP_VAR, BP_VAR_RW TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } } break; default: - value = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + value = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); /* do nothing */ break; } @@ -14834,8 +16860,8 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_TMP(incdec_t i int have_get_ptr = 0; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = &EX_T(opline->result.var).var.ptr; if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -14938,8 +16964,8 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_TMP(incdec_t int have_get_ptr = 0; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = &EX_T(opline->result.var).tmp_var; if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -15042,10 +17068,19 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAND EX_T(opline->op1.var).var.ptr_ptr) { PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); } - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_R TSRMLS_CC); - zval_dtor(free_op2.var); - if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + + if (IS_VAR == IS_TMP_VAR || IS_VAR == IS_CONST) { + zval *container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), &container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_R TSRMLS_CC); + zval_dtor(free_op2.var); + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + } else { + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_R TSRMLS_CC); + zval_dtor(free_op2.var); + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + } + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -15057,12 +17092,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAND zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_W TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_W TSRMLS_CC); zval_dtor(free_op2.var); if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); @@ -15091,12 +17126,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAN zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_RW TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_RW TSRMLS_CC); zval_dtor(free_op2.var); if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); @@ -15113,8 +17148,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAN zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_IS TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_IS TSRMLS_CC); zval_dtor(free_op2.var); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -15129,12 +17164,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TMP_HANDLER(ZEND_OPCO SAVE_OPLINE(); - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_W TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_W TSRMLS_CC); if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); } @@ -15142,8 +17177,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TMP_HANDLER(ZEND_OPCO if (IS_TMP_VAR == IS_UNUSED) { zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); } - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_R TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_R TSRMLS_CC); } zval_dtor(free_op2.var); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -15158,7 +17193,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_ zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_CV) { if (container != &EG(uninitialized_zval_ptr)) { @@ -15168,7 +17203,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_UNSET TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_UNSET TSRMLS_CC); zval_dtor(free_op2.var); if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); @@ -15176,6 +17211,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (UNEXPECTED(EX_T(opline->result.var).var.ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_NEXT_OPCODE(); } else { zend_free_op free_res; zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr; @@ -15200,8 +17236,8 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_TMP(ZE zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -15247,7 +17283,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAND zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_VAR == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) { PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); @@ -15257,7 +17293,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAND if (1) { MAKE_REAL_ZVAL_PTR(property); } - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -15296,8 +17332,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAN zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (1) { MAKE_REAL_ZVAL_PTR(property); @@ -15328,8 +17364,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HAN zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -15365,15 +17401,15 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMP_HANDLER(ZEND_OPCO { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1, free_op2; zval *property; zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (1) { MAKE_REAL_ZVAL_PTR(property); @@ -15406,8 +17442,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_ zval *property; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_VAR == IS_CV) { if (container != &EG(uninitialized_zval_ptr)) { @@ -15449,8 +17485,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL zval *property_name; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - property_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + property_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (1) { MAKE_REAL_ZVAL_PTR(property_name); @@ -15458,7 +17494,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (1) { zval_ptr_dtor(&property_name); } else { @@ -15478,19 +17514,19 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL zval **object_ptr; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } if (Z_TYPE_PP(object_ptr) == IS_OBJECT) { zend_free_op free_op2; - zval *property_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *property_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (1) { MAKE_REAL_ZVAL_PTR(property_name); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_DIM, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (1) { zval_ptr_dtor(&property_name); } else { @@ -15499,14 +17535,14 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL } else { zend_free_op free_op2, free_op_data1, free_op_data2; zval *value; - zval *dim = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zval **variable_ptr_ptr; zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), object_ptr, dim, IS_TMP_VAR, BP_VAR_W TSRMLS_CC); zval_dtor(free_op2.var); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); if (UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) { if (RETURN_VALUE_USED(opline)) { @@ -15560,8 +17596,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_A zval **variable_ptr_ptr; SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - variable_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + value = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + variable_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T(opline->op1.var), value, IS_TMP_VAR TSRMLS_CC)) { @@ -15614,11 +17650,11 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE char *function_name_strval; int function_name_strlen; zend_free_op free_op1, free_op2; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); - function_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + function_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_TMP_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -15628,49 +17664,51 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE function_name_strval = Z_STRVAL_P(function_name); function_name_strlen = Z_STRLEN_P(function_name); - EX(object) = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + call->object = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (EXPECTED(EX(object) != NULL) && - EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) { - EX(called_scope) = Z_OBJCE_P(EX(object)); + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); if (IS_TMP_VAR != IS_CONST || - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) { - zval *object = EX(object); + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; - if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) { + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { zend_error_noreturn(E_ERROR, "Object does not support method calls"); } /* First, locate the function. */ - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); } if (IS_TMP_VAR == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(EX(object) == object)) { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc)); + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); } } } else { zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } + call->is_ctor_call = 0; + EX(call) = call; zval_dtor(free_op2.var); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -15684,9 +17722,9 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND USE_OPLINE zval *function_name; zend_class_entry *ce; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); if (IS_VAR == IS_CONST) { /* no function found. try a static method in class */ @@ -15700,24 +17738,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND } CACHE_PTR(opline->op1.literal->cache_slot, ce); } - EX(called_scope) = ce; + call->called_scope = ce; } else { ce = EX_T(opline->op1.var).class_entry; if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) { - EX(called_scope) = EG(called_scope); + call->called_scope = EG(called_scope); } else { - EX(called_scope) = ce; + call->called_scope = ce; } } if (IS_VAR == IS_CONST && IS_TMP_VAR == IS_CONST && CACHED_PTR(opline->op2.literal->cache_slot)) { - EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot); + call->fbc = CACHED_PTR(opline->op2.literal->cache_slot); } else if (IS_VAR != IS_CONST && IS_TMP_VAR == IS_CONST && - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { /* do nothing */ } else if (IS_TMP_VAR != IS_UNUSED) { char *function_name_strval = NULL; @@ -15728,7 +17766,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND function_name_strval = Z_STRVAL_P(opline->op2.zv); function_name_strlen = Z_STRLEN_P(opline->op2.zv); } else { - function_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + function_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { zend_error_noreturn(E_ERROR, "Function name must be a string"); @@ -15740,20 +17778,20 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND if (function_name_strval) { if (ce->get_static_method) { - EX(fbc) = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + call->fbc = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); } else { - EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + call->fbc = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); } - if (UNEXPECTED(EX(fbc) == NULL)) { + if (UNEXPECTED(call->fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval); } if (IS_TMP_VAR == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { if (IS_VAR == IS_CONST) { - CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc)); + CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } else { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc)); + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, call->fbc); } } } @@ -15767,29 +17805,31 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name); } - EX(fbc) = ce->constructor; + call->fbc = ce->constructor; } - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { - EX(object) = NULL; + if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) { + call->object = NULL; } else { if (EG(This) && Z_OBJ_HT_P(EG(This))->get_class_entry && !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { /* We are calling method of the other (incompatible) class, but passing $this. This is done for compatibility with php-4. */ - if (EX(fbc)->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } else { /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } } - if ((EX(object) = EG(This))) { - Z_ADDREF_P(EX(object)); - EX(called_scope) = Z_OBJCE_P(EX(object)); + if ((call->object = EG(This))) { + Z_ADDREF_P(call->object); + call->called_scope = Z_OBJCE_P(call->object); } } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -15805,8 +17845,8 @@ static int ZEND_FASTCALL ZEND_CASE_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG PZVAL_LOCK(EX_T(opline->op1.var).var.ptr); } is_equal_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -15821,7 +17861,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMP_HANDLER(ZEND_OPCOD SAVE_OPLINE(); if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && opline->extended_value) { - zval **expr_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval **expr_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); @@ -15830,7 +17870,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMP_HANDLER(ZEND_OPCOD expr_ptr = *expr_ptr_ptr; Z_ADDREF_P(expr_ptr); } else { - expr_ptr=_get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + expr_ptr=_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (0) { /* temporary variable */ zval *new_expr; @@ -15851,7 +17891,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMP_HANDLER(ZEND_OPCOD if (IS_TMP_VAR != IS_UNUSED) { zend_free_op free_op2; - zval *offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); ulong hval; switch (Z_TYPE_P(offset)) { @@ -15922,11 +17962,11 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLE ulong hval; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } - offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_VAR != IS_VAR || container) { switch (Z_TYPE_PP(container)) { @@ -16021,8 +18061,8 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLE zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_VAR != IS_VAR || container) { if (IS_VAR == IS_CV && container != &EG(uninitialized_zval_ptr)) { @@ -16065,9 +18105,9 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_TMP(in zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) { HashTable *ht; @@ -16208,6 +18248,161 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_TMP_HANDLER(ZEND_ return zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_TMP(1, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_VAR != IS_UNUSED) { + zend_free_op free_op1; + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_VAR == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + } + } else { + zval *value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_TMP_VAR != IS_UNUSED) { + zend_free_op free_op2; + zval *key = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!1) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL ZEND_ADD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -16215,8 +18410,8 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_add_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -16230,8 +18425,8 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_sub_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -16245,8 +18440,8 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_mul_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -16260,8 +18455,8 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_div_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -16275,8 +18470,8 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); fast_mod_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -16290,8 +18485,8 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_left_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -16305,8 +18500,8 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_right_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -16320,8 +18515,8 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); concat_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -16335,8 +18530,8 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); is_identical_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -16351,8 +18546,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE SAVE_OPLINE(); is_identical_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); Z_LVAL_P(result) = !Z_LVAL_P(result); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; @@ -16368,8 +18563,8 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); ZVAL_BOOL(result, fast_equal_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -16384,8 +18579,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); ZVAL_BOOL(result, fast_not_equal_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -16400,8 +18595,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -16416,8 +18611,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_VAR_VAR_HANDLER(ZEND_OPC SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -16431,8 +18626,8 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); bitwise_or_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -16446,8 +18641,8 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); bitwise_and_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -16461,8 +18656,8 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); bitwise_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -16476,8 +18671,8 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); boolean_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -16488,10 +18683,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(int (*bin { USE_OPLINE zend_free_op free_op1, free_op2, free_op_data1; - zval **object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval **object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zval *object; - zval *property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); + zval *property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); int have_get_ptr = 0; if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -16609,7 +18804,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_VAR(int (*binary_ return zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); break; case ZEND_ASSIGN_DIM: { - zval **container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval **container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -16619,17 +18814,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_VAR(int (*binary_ } return zend_binary_assign_op_obj_helper_SPEC_VAR_VAR(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { - zval *dim = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_VAR, BP_VAR_RW TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } } break; default: - value = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + value = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); /* do nothing */ break; } @@ -16752,8 +18947,8 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_VAR(incdec_t i int have_get_ptr = 0; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = &EX_T(opline->result.var).var.ptr; if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -16856,8 +19051,8 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_VAR(incdec_t int have_get_ptr = 0; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = &EX_T(opline->result.var).tmp_var; if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -16958,7 +19153,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_VAR(int type, ZE ulong hash_value; SAVE_OPLINE(); - varname = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(varname) != IS_STRING)) { ZVAL_COPY_VALUE(&tmp_varname, varname); @@ -17098,7 +19293,7 @@ static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_H { USE_OPLINE - return zend_fetch_var_address_helper_SPEC_VAR_VAR(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_VAR_VAR(ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -17124,10 +19319,19 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAND EX_T(opline->op1.var).var.ptr_ptr) { PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); } - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_R TSRMLS_CC); - if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; - if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + + if (IS_VAR == IS_TMP_VAR || IS_VAR == IS_CONST) { + zval *container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), &container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_R TSRMLS_CC); + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + } else { + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_R TSRMLS_CC); + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + } + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -17139,12 +19343,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAND zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_W TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_W TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); @@ -17173,12 +19377,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAN zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_RW TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_RW TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); @@ -17195,8 +19399,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAN zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_IS TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_IS TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -17211,12 +19415,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_VAR_HANDLER(ZEND_OPCO SAVE_OPLINE(); - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_W TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_W TSRMLS_CC); if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); } @@ -17224,8 +19428,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_VAR_HANDLER(ZEND_OPCO if (IS_VAR == IS_UNUSED) { zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); } - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_R TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_R TSRMLS_CC); } if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -17240,7 +19444,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_ zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_CV) { if (container != &EG(uninitialized_zval_ptr)) { @@ -17250,7 +19454,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_ if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_UNSET TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_UNSET TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); @@ -17258,6 +19462,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (UNEXPECTED(EX_T(opline->result.var).var.ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_NEXT_OPCODE(); } else { zend_free_op free_res; zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr; @@ -17282,8 +19487,8 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_VAR(ZE zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -17329,7 +19534,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAND zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_VAR == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) { PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); @@ -17339,7 +19544,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAND if (0) { MAKE_REAL_ZVAL_PTR(property); } - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -17378,8 +19583,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAN zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property); @@ -17410,8 +19615,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HAN zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -17447,15 +19652,15 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_VAR_HANDLER(ZEND_OPCO { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1, free_op2; zval *property; zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property); @@ -17488,8 +19693,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_ zval *property; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_VAR == IS_CV) { if (container != &EG(uninitialized_zval_ptr)) { @@ -17531,8 +19736,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL zval *property_name; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - property_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property_name); @@ -17540,7 +19745,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (0) { zval_ptr_dtor(&property_name); } else { @@ -17560,19 +19765,19 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL zval **object_ptr; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } if (Z_TYPE_PP(object_ptr) == IS_OBJECT) { zend_free_op free_op2; - zval *property_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property_name); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_DIM, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (0) { zval_ptr_dtor(&property_name); } else { @@ -17581,14 +19786,14 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL } else { zend_free_op free_op2, free_op_data1, free_op_data2; zval *value; - zval *dim = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zval **variable_ptr_ptr; zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), object_ptr, dim, IS_VAR, BP_VAR_W TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); if (UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) { if (RETURN_VALUE_USED(opline)) { @@ -17642,8 +19847,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_A zval **variable_ptr_ptr; SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - variable_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + value = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + variable_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T(opline->op1.var), value, IS_VAR TSRMLS_CC)) { @@ -17698,7 +19903,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL zval **value_ptr_ptr; SAVE_OPLINE(); - value_ptr_ptr = _get_zval_ptr_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + value_ptr_ptr = _get_zval_ptr_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_VAR == IS_VAR && value_ptr_ptr && @@ -17721,7 +19926,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object"); } - variable_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + variable_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if ((IS_VAR == IS_VAR && UNEXPECTED(value_ptr_ptr == NULL)) || (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL))) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); @@ -17751,11 +19956,11 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE char *function_name_strval; int function_name_strlen; zend_free_op free_op1, free_op2; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); - function_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -17765,49 +19970,51 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE function_name_strval = Z_STRVAL_P(function_name); function_name_strlen = Z_STRLEN_P(function_name); - EX(object) = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + call->object = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (EXPECTED(EX(object) != NULL) && - EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) { - EX(called_scope) = Z_OBJCE_P(EX(object)); + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); if (IS_VAR != IS_CONST || - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) { - zval *object = EX(object); + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; - if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) { + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { zend_error_noreturn(E_ERROR, "Object does not support method calls"); } /* First, locate the function. */ - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); } if (IS_VAR == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(EX(object) == object)) { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc)); + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); } } } else { zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } + call->is_ctor_call = 0; + EX(call) = call; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -17821,9 +20028,9 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND USE_OPLINE zval *function_name; zend_class_entry *ce; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); if (IS_VAR == IS_CONST) { /* no function found. try a static method in class */ @@ -17837,24 +20044,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND } CACHE_PTR(opline->op1.literal->cache_slot, ce); } - EX(called_scope) = ce; + call->called_scope = ce; } else { ce = EX_T(opline->op1.var).class_entry; if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) { - EX(called_scope) = EG(called_scope); + call->called_scope = EG(called_scope); } else { - EX(called_scope) = ce; + call->called_scope = ce; } } if (IS_VAR == IS_CONST && IS_VAR == IS_CONST && CACHED_PTR(opline->op2.literal->cache_slot)) { - EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot); + call->fbc = CACHED_PTR(opline->op2.literal->cache_slot); } else if (IS_VAR != IS_CONST && IS_VAR == IS_CONST && - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { /* do nothing */ } else if (IS_VAR != IS_UNUSED) { char *function_name_strval = NULL; @@ -17865,7 +20072,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND function_name_strval = Z_STRVAL_P(opline->op2.zv); function_name_strlen = Z_STRLEN_P(opline->op2.zv); } else { - function_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { zend_error_noreturn(E_ERROR, "Function name must be a string"); @@ -17877,20 +20084,20 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND if (function_name_strval) { if (ce->get_static_method) { - EX(fbc) = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + call->fbc = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); } else { - EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + call->fbc = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); } - if (UNEXPECTED(EX(fbc) == NULL)) { + if (UNEXPECTED(call->fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval); } if (IS_VAR == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { if (IS_VAR == IS_CONST) { - CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc)); + CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } else { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc)); + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, call->fbc); } } } @@ -17904,29 +20111,31 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name); } - EX(fbc) = ce->constructor; + call->fbc = ce->constructor; } - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { - EX(object) = NULL; + if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) { + call->object = NULL; } else { if (EG(This) && Z_OBJ_HT_P(EG(This))->get_class_entry && !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { /* We are calling method of the other (incompatible) class, but passing $this. This is done for compatibility with php-4. */ - if (EX(fbc)->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } else { /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } } - if ((EX(object) = EG(This))) { - Z_ADDREF_P(EX(object)); - EX(called_scope) = Z_OBJCE_P(EX(object)); + if ((call->object = EG(This))) { + Z_ADDREF_P(call->object); + call->called_scope = Z_OBJCE_P(call->object); } } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -17942,8 +20151,8 @@ static int ZEND_FASTCALL ZEND_CASE_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG PZVAL_LOCK(EX_T(opline->op1.var).var.ptr); } is_equal_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -17958,7 +20167,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_VAR_HANDLER(ZEND_OPCOD SAVE_OPLINE(); if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && opline->extended_value) { - zval **expr_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval **expr_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); @@ -17967,7 +20176,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_VAR_HANDLER(ZEND_OPCOD expr_ptr = *expr_ptr_ptr; Z_ADDREF_P(expr_ptr); } else { - expr_ptr=_get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + expr_ptr=_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (0) { /* temporary variable */ zval *new_expr; @@ -17988,7 +20197,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_VAR_HANDLER(ZEND_OPCOD if (IS_VAR != IS_UNUSED) { zend_free_op free_op2; - zval *offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); ulong hval; switch (Z_TYPE_P(offset)) { @@ -18074,7 +20283,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE ZEND_VM_NEXT_OPCODE(); } - varname = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, varname); @@ -18135,11 +20344,11 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE ulong hval; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } - offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_VAR != IS_VAR || container) { switch (Z_TYPE_PP(container)) { @@ -18234,8 +20443,8 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLE zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_VAR != IS_VAR || container) { if (IS_VAR == IS_CV && container != &EG(uninitialized_zval_ptr)) { @@ -18291,7 +20500,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_VAR_HANDLER(ZEND_OPCOD } else { HashTable *target_symbol_table; zend_free_op free_op1; - zval tmp, *varname = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval tmp, *varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, varname); @@ -18363,9 +20572,9 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_VAR(in zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) { HashTable *ht; @@ -18506,14 +20715,170 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_VAR_HANDLER(ZEND_ return zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_VAR(1, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_VAR != IS_UNUSED) { + zend_free_op free_op1; + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_VAR == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + } + } else { + zval *value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_VAR != IS_UNUSED) { + zend_free_op free_op2; + zval *key = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1, free_op_data1; - zval **object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval **object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zval *object; zval *property = NULL; - zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); + zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); int have_get_ptr = 0; if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -18631,7 +20996,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_UNUSED(int (*bina return zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); break; case ZEND_ASSIGN_DIM: { - zval **container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval **container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -18644,14 +21009,14 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_UNUSED(int (*bina zval *dim = NULL; zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_UNUSED, BP_VAR_RW TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } } break; default: value = NULL; - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); /* do nothing */ break; } @@ -18773,7 +21138,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR_UNUSED(int type, ulong hash_value; SAVE_OPLINE(); - varname = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(varname) != IS_STRING)) { ZVAL_COPY_VALUE(&tmp_varname, varname); @@ -18913,7 +21278,7 @@ static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCOD { USE_OPLINE - return zend_fetch_var_address_helper_SPEC_VAR_UNUSED(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_VAR_UNUSED(ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -18933,7 +21298,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_H zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -18967,7 +21332,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_ zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -18990,8 +21355,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_UNUSED_HANDLER(ZEND_O SAVE_OPLINE(); - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } @@ -19003,7 +21368,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_UNUSED_HANDLER(ZEND_O if (IS_UNUSED == IS_UNUSED) { zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); } - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, NULL, IS_UNUSED, BP_VAR_R TSRMLS_CC); } @@ -19019,7 +21384,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HA zval **object_ptr; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -19031,7 +21396,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HA if (0) { MAKE_REAL_ZVAL_PTR(property_name); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_DIM, ((IS_UNUSED == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_UNUSED == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (0) { zval_ptr_dtor(&property_name); } else { @@ -19045,8 +21410,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HA zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), object_ptr, dim, IS_UNUSED, BP_VAR_W TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); if (UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) { if (RETURN_VALUE_USED(opline)) { @@ -19097,9 +21462,9 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z USE_OPLINE zval *function_name; zend_class_entry *ce; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); if (IS_VAR == IS_CONST) { /* no function found. try a static method in class */ @@ -19113,24 +21478,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z } CACHE_PTR(opline->op1.literal->cache_slot, ce); } - EX(called_scope) = ce; + call->called_scope = ce; } else { ce = EX_T(opline->op1.var).class_entry; if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) { - EX(called_scope) = EG(called_scope); + call->called_scope = EG(called_scope); } else { - EX(called_scope) = ce; + call->called_scope = ce; } } if (IS_VAR == IS_CONST && IS_UNUSED == IS_CONST && CACHED_PTR(opline->op2.literal->cache_slot)) { - EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot); + call->fbc = CACHED_PTR(opline->op2.literal->cache_slot); } else if (IS_VAR != IS_CONST && IS_UNUSED == IS_CONST && - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { /* do nothing */ } else if (IS_UNUSED != IS_UNUSED) { char *function_name_strval = NULL; @@ -19153,20 +21518,20 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z if (function_name_strval) { if (ce->get_static_method) { - EX(fbc) = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + call->fbc = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); } else { - EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_UNUSED == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + call->fbc = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_UNUSED == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); } - if (UNEXPECTED(EX(fbc) == NULL)) { + if (UNEXPECTED(call->fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval); } if (IS_UNUSED == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { if (IS_VAR == IS_CONST) { - CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc)); + CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } else { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc)); + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, call->fbc); } } } @@ -19180,29 +21545,31 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(Z if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name); } - EX(fbc) = ce->constructor; + call->fbc = ce->constructor; } - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { - EX(object) = NULL; + if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) { + call->object = NULL; } else { if (EG(This) && Z_OBJ_HT_P(EG(This))->get_class_entry && !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { /* We are calling method of the other (incompatible) class, but passing $this. This is done for compatibility with php-4. */ - if (EX(fbc)->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } else { /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } } - if ((EX(object) = EG(This))) { - Z_ADDREF_P(EX(object)); - EX(called_scope) = Z_OBJCE_P(EX(object)); + if ((call->object = EG(This))) { + Z_ADDREF_P(call->object); + call->called_scope = Z_OBJCE_P(call->object); } } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -19216,7 +21583,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER(ZEND_OP SAVE_OPLINE(); if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && opline->extended_value) { - zval **expr_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval **expr_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); @@ -19225,7 +21592,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER(ZEND_OP expr_ptr = *expr_ptr_ptr; Z_ADDREF_P(expr_ptr); } else { - expr_ptr=_get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + expr_ptr=_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (0) { /* temporary variable */ zval *new_expr; @@ -19332,7 +21699,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HAN ZEND_VM_NEXT_OPCODE(); } - varname = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, varname); @@ -19408,7 +21775,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_UNUSED_HANDLER(ZEND_OP } else { HashTable *target_symbol_table; zend_free_op free_op1; - zval tmp, *varname = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval tmp, *varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, varname); @@ -19477,8 +21844,8 @@ static int ZEND_FASTCALL ZEND_SEPARATE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); var_ptr = EX_T(opline->op1.var).var.ptr; if (Z_TYPE_P(var_ptr) != IS_OBJECT && - !PZVAL_IS_REF(var_ptr) && - Z_REFCOUNT_P(var_ptr) > 1) { + !PZVAL_IS_REF(var_ptr) && + Z_REFCOUNT_P(var_ptr) > 1) { Z_DELREF_P(var_ptr); ALLOC_ZVAL(new_zv); @@ -19490,6 +21857,161 @@ static int ZEND_FASTCALL ZEND_SEPARATE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HAND ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_VAR != IS_UNUSED) { + zend_free_op free_op1; + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_VAR == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + } + } else { + zval *value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_UNUSED != IS_UNUSED) { + + zval *key = NULL; + + /* Consts, temporary variables and references need copying */ + if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL ZEND_ADD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -19497,8 +22019,8 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_add_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -19512,8 +22034,8 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_sub_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -19527,8 +22049,8 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_mul_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -19542,8 +22064,8 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_div_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -19557,8 +22079,8 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_mod_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -19572,8 +22094,8 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_left_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -19587,8 +22109,8 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_right_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -19602,8 +22124,8 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); concat_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -19617,8 +22139,8 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); is_identical_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -19633,8 +22155,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_ SAVE_OPLINE(); is_identical_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); Z_LVAL_P(result) = !Z_LVAL_P(result); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -19650,8 +22172,8 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); ZVAL_BOOL(result, fast_equal_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC)); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -19666,8 +22188,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); ZVAL_BOOL(result, fast_not_equal_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC)); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -19682,8 +22204,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC)); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -19698,8 +22220,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_VAR_CV_HANDLER(ZEND_OPCO SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC)); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -19713,8 +22235,8 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); bitwise_or_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -19728,8 +22250,8 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); bitwise_and_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -19743,8 +22265,8 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); bitwise_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -19758,8 +22280,8 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); boolean_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -19770,10 +22292,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CV(int (*bina { USE_OPLINE zend_free_op free_op1, free_op_data1; - zval **object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval **object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); zval *object; - zval *property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); - zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); + zval *property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); int have_get_ptr = 0; if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -19891,7 +22413,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_CV(int (*binary_o return zend_binary_assign_op_obj_helper_SPEC_VAR_CV(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); break; case ZEND_ASSIGN_DIM: { - zval **container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval **container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -19901,17 +22423,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_CV(int (*binary_o } return zend_binary_assign_op_obj_helper_SPEC_VAR_CV(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { - zval *dim = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + zval *dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_CV, BP_VAR_RW TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } } break; default: - value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); - var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); /* do nothing */ break; } @@ -20033,8 +22555,8 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CV(incdec_t in int have_get_ptr = 0; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); retval = &EX_T(opline->result.var).var.ptr; if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -20137,8 +22659,8 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CV(incdec_t i int have_get_ptr = 0; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); retval = &EX_T(opline->result.var).tmp_var; if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -20241,10 +22763,19 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDL EX_T(opline->op1.var).var.ptr_ptr) { PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); } - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_R TSRMLS_CC); - if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + if (IS_VAR == IS_TMP_VAR || IS_VAR == IS_CONST) { + zval *container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), &container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_R TSRMLS_CC); + + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + } else { + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_R TSRMLS_CC); + + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + } + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -20256,12 +22787,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDL zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_W TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_W TSRMLS_CC); if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); @@ -20290,12 +22821,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HAND zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_RW TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_RW TSRMLS_CC); if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); @@ -20312,8 +22843,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HAND zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_IS TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_IS TSRMLS_CC); if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; CHECK_EXCEPTION(); @@ -20328,12 +22859,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCOD SAVE_OPLINE(); - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_W TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_W TSRMLS_CC); if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); } @@ -20341,8 +22872,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCOD if (IS_CV == IS_UNUSED) { zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); } - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_R TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_R TSRMLS_CC); } if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -20357,7 +22888,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_H zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_CV) { if (container != &EG(uninitialized_zval_ptr)) { @@ -20367,7 +22898,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_H if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_UNSET TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_UNSET TSRMLS_CC); if (IS_VAR == IS_VAR && (free_op1.var != NULL) && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); @@ -20375,6 +22906,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_H if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; if (UNEXPECTED(EX_T(opline->result.var).var.ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_NEXT_OPCODE(); } else { zend_free_op free_res; zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr; @@ -20399,8 +22931,8 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_VAR_CV(ZEN zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -20446,7 +22978,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDL zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_VAR == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) { PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); @@ -20456,7 +22988,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDL if (0) { MAKE_REAL_ZVAL_PTR(property); } - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -20495,8 +23027,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HAND zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property); @@ -20527,8 +23059,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HAND zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -20564,15 +23096,15 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCOD { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1; zval *property; zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property); @@ -20605,8 +23137,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_H zval *property; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_VAR == IS_CV) { if (container != &EG(uninitialized_zval_ptr)) { @@ -20648,8 +23180,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE zval *property_name; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - property_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property_name); @@ -20657,7 +23189,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (0) { zval_ptr_dtor(&property_name); } else { @@ -20677,19 +23209,19 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE zval **object_ptr; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } if (Z_TYPE_PP(object_ptr) == IS_OBJECT) { - zval *property_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + zval *property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property_name); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_DIM, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (0) { zval_ptr_dtor(&property_name); } else { @@ -20698,13 +23230,13 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE } else { zend_free_op free_op_data1, free_op_data2; zval *value; - zval *dim = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + zval *dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); zval **variable_ptr_ptr; zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), object_ptr, dim, IS_CV, BP_VAR_W TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); if (UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) { if (RETURN_VALUE_USED(opline)) { @@ -20758,8 +23290,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_AR zval **variable_ptr_ptr; SAVE_OPLINE(); - value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); - variable_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + variable_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T(opline->op1.var), value, IS_CV TSRMLS_CC)) { @@ -20813,7 +23345,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE zval **value_ptr_ptr; SAVE_OPLINE(); - value_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op2.var TSRMLS_CC); + value_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op2.var TSRMLS_CC); if (IS_CV == IS_VAR && value_ptr_ptr && @@ -20836,7 +23368,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object"); } - variable_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + variable_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if ((IS_CV == IS_VAR && UNEXPECTED(value_ptr_ptr == NULL)) || (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL))) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); @@ -20865,11 +23397,11 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_ char *function_name_strval; int function_name_strlen; zend_free_op free_op1; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); - function_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_CV != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -20879,49 +23411,51 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_ function_name_strval = Z_STRVAL_P(function_name); function_name_strlen = Z_STRLEN_P(function_name); - EX(object) = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + call->object = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - if (EXPECTED(EX(object) != NULL) && - EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) { - EX(called_scope) = Z_OBJCE_P(EX(object)); + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); if (IS_CV != IS_CONST || - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) { - zval *object = EX(object); + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; - if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) { + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { zend_error_noreturn(E_ERROR, "Object does not support method calls"); } /* First, locate the function. */ - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); } if (IS_CV == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(EX(object) == object)) { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc)); + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); } } } else { zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } + call->is_ctor_call = 0; + EX(call) = call; if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -20934,9 +23468,9 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_ USE_OPLINE zval *function_name; zend_class_entry *ce; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); if (IS_VAR == IS_CONST) { /* no function found. try a static method in class */ @@ -20950,24 +23484,24 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_ } CACHE_PTR(opline->op1.literal->cache_slot, ce); } - EX(called_scope) = ce; + call->called_scope = ce; } else { ce = EX_T(opline->op1.var).class_entry; if (opline->extended_value == ZEND_FETCH_CLASS_PARENT || opline->extended_value == ZEND_FETCH_CLASS_SELF) { - EX(called_scope) = EG(called_scope); + call->called_scope = EG(called_scope); } else { - EX(called_scope) = ce; + call->called_scope = ce; } } if (IS_VAR == IS_CONST && IS_CV == IS_CONST && CACHED_PTR(opline->op2.literal->cache_slot)) { - EX(fbc) = CACHED_PTR(opline->op2.literal->cache_slot); + call->fbc = CACHED_PTR(opline->op2.literal->cache_slot); } else if (IS_VAR != IS_CONST && IS_CV == IS_CONST && - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce))) { /* do nothing */ } else if (IS_CV != IS_UNUSED) { char *function_name_strval = NULL; @@ -20978,7 +23512,7 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_ function_name_strval = Z_STRVAL_P(opline->op2.zv); function_name_strlen = Z_STRLEN_P(opline->op2.zv); } else { - function_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { zend_error_noreturn(E_ERROR, "Function name must be a string"); @@ -20990,20 +23524,20 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_ if (function_name_strval) { if (ce->get_static_method) { - EX(fbc) = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + call->fbc = ce->get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); } else { - EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + call->fbc = zend_std_get_static_method(ce, function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); } - if (UNEXPECTED(EX(fbc) == NULL)) { + if (UNEXPECTED(call->fbc == NULL)) { zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval); } if (IS_CV == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) { if (IS_VAR == IS_CONST) { - CACHE_PTR(opline->op2.literal->cache_slot, EX(fbc)); + CACHE_PTR(opline->op2.literal->cache_slot, call->fbc); } else { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, EX(fbc)); + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, ce, call->fbc); } } } @@ -21017,29 +23551,31 @@ static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_ if (EG(This) && Z_OBJCE_P(EG(This)) != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) { zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name); } - EX(fbc) = ce->constructor; + call->fbc = ce->constructor; } - if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { - EX(object) = NULL; + if (call->fbc->common.fn_flags & ZEND_ACC_STATIC) { + call->object = NULL; } else { if (EG(This) && Z_OBJ_HT_P(EG(This))->get_class_entry && !instanceof_function(Z_OBJCE_P(EG(This)), ce TSRMLS_CC)) { /* We are calling method of the other (incompatible) class, but passing $this. This is done for compatibility with php-4. */ - if (EX(fbc)->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { - zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + if (call->fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) { + zend_error(E_STRICT, "Non-static method %s::%s() should not be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } else { /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */ - zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", EX(fbc)->common.scope->name, EX(fbc)->common.function_name); + zend_error_noreturn(E_ERROR, "Non-static method %s::%s() cannot be called statically, assuming $this from incompatible context", call->fbc->common.scope->name, call->fbc->common.function_name); } } - if ((EX(object) = EG(This))) { - Z_ADDREF_P(EX(object)); - EX(called_scope) = Z_OBJCE_P(EX(object)); + if ((call->object = EG(This))) { + Z_ADDREF_P(call->object); + call->called_scope = Z_OBJCE_P(call->object); } } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -21055,8 +23591,8 @@ static int ZEND_FASTCALL ZEND_CASE_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS PZVAL_LOCK(EX_T(opline->op1.var).var.ptr); } is_equal_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -21070,7 +23606,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE SAVE_OPLINE(); if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && opline->extended_value) { - zval **expr_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + zval **expr_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); @@ -21079,7 +23615,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE expr_ptr = *expr_ptr_ptr; Z_ADDREF_P(expr_ptr); } else { - expr_ptr=_get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + expr_ptr=_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (0) { /* temporary variable */ zval *new_expr; @@ -21100,7 +23636,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE if (IS_CV != IS_UNUSED) { - zval *offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); ulong hval; switch (Z_TYPE_P(offset)) { @@ -21171,11 +23707,11 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER ulong hval; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); if (IS_VAR == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } - offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_VAR != IS_VAR || container) { switch (Z_TYPE_PP(container)) { @@ -21270,8 +23806,8 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); - offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_VAR != IS_VAR || container) { if (IS_VAR == IS_CV && container != &EG(uninitialized_zval_ptr)) { @@ -21314,9 +23850,9 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_CV(int zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC); + container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); - offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) { HashTable *ht; @@ -21457,6 +23993,161 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_CV_HANDLER(ZEND_O return zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_CV(1, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_VAR != IS_UNUSED) { + zend_free_op free_op1; + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_VAR == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + } + } else { + zval *value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_CV != IS_UNUSED) { + + zval *key = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -21549,7 +24240,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(int zval **object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); zval *object; zval *property = opline->op2.zv; - zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); + zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); int have_get_ptr = 0; if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -21679,8 +24370,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_CONST(int (*bi zval *dim = opline->op2.zv; zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_CONST, BP_VAR_RW TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } } break; @@ -22174,7 +24865,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CONST_HANDLER(ZEND { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1; zval *property; @@ -22266,7 +24957,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_ if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (0) { zval_ptr_dtor(&property_name); } else { @@ -22332,9 +25023,9 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_O char *function_name_strval; int function_name_strlen; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); function_name = opline->op2.zv; @@ -22346,49 +25037,51 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_O function_name_strval = Z_STRVAL_P(function_name); function_name_strlen = Z_STRLEN_P(function_name); - EX(object) = _get_obj_zval_ptr_unused(TSRMLS_C); + call->object = _get_obj_zval_ptr_unused(TSRMLS_C); - if (EXPECTED(EX(object) != NULL) && - EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) { - EX(called_scope) = Z_OBJCE_P(EX(object)); + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); if (IS_CONST != IS_CONST || - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) { - zval *object = EX(object); + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; - if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) { + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { zend_error_noreturn(E_ERROR, "Object does not support method calls"); } /* First, locate the function. */ - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); } if (IS_CONST == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(EX(object) == object)) { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc)); + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); } } } else { zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); @@ -22792,14 +25485,167 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CONST_HANDLER( return zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_CONST(1, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_UNUSED != IS_UNUSED) { + + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = NULL; + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = NULL; + + if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_UNUSED == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = NULL; + + /* Consts, temporary variables and references need copying */ + if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_CONST != IS_UNUSED) { + + zval *key = opline->op2.zv; + + /* Consts, temporary variables and references need copying */ + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op2, free_op_data1; zval **object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); zval *object; - zval *property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); + zval *property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); int have_get_ptr = 0; if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -22926,16 +25772,16 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_TMP(int (*bina } return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMP(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { - zval *dim = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_TMP_VAR, BP_VAR_RW TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } } break; default: - value = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + value = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); var_ptr = NULL; /* do nothing */ break; @@ -23060,7 +25906,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_TMP(incdec_ SAVE_OPLINE(); object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = &EX_T(opline->result.var).var.ptr; if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -23164,7 +26010,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_TMP(incdec SAVE_OPLINE(); object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = &EX_T(opline->result.var).tmp_var; if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -23264,7 +26110,7 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_TMP SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(TSRMLS_C); - offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -23309,7 +26155,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_H zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_UNUSED == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) { PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); @@ -23357,7 +26203,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_ zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); if (1) { @@ -23390,7 +26236,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_ SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(TSRMLS_C); - offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -23425,14 +26271,14 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMP_HANDLER(ZEND_O { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1, free_op2; zval *property; zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); if (1) { @@ -23467,7 +26313,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCO SAVE_OPLINE(); container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_UNUSED == IS_CV) { if (container != &EG(uninitialized_zval_ptr)) { @@ -23509,7 +26355,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HA SAVE_OPLINE(); object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - property_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + property_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (1) { MAKE_REAL_ZVAL_PTR(property_name); @@ -23517,7 +26363,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HA if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (1) { zval_ptr_dtor(&property_name); } else { @@ -23540,7 +26386,7 @@ static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDL int use_copy = 0; SAVE_OPLINE(); - var = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + var = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_UNUSED == IS_UNUSED) { /* Initialize for erealloc in add_string_to_string */ @@ -23582,11 +26428,11 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPC char *function_name_strval; int function_name_strlen; zend_free_op free_op2; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); - function_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + function_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_TMP_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -23596,49 +26442,51 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPC function_name_strval = Z_STRVAL_P(function_name); function_name_strlen = Z_STRLEN_P(function_name); - EX(object) = _get_obj_zval_ptr_unused(TSRMLS_C); + call->object = _get_obj_zval_ptr_unused(TSRMLS_C); - if (EXPECTED(EX(object) != NULL) && - EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) { - EX(called_scope) = Z_OBJCE_P(EX(object)); + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); if (IS_TMP_VAR != IS_CONST || - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) { - zval *object = EX(object); + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; - if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) { + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { zend_error_noreturn(E_ERROR, "Object does not support method calls"); } /* First, locate the function. */ - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); } if (IS_TMP_VAR == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(EX(object) == object)) { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc)); + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); } } } else { zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } + call->is_ctor_call = 0; + EX(call) = call; zval_dtor(free_op2.var); @@ -23673,7 +26521,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HAN if (IS_UNUSED == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } - offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_UNUSED != IS_VAR || container) { switch (Z_TYPE_PP(container)) { @@ -23768,7 +26616,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_UNUSED != IS_VAR || container) { if (IS_UNUSED == IS_CV && container != &EG(uninitialized_zval_ptr)) { @@ -23812,7 +26660,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_TMP SAVE_OPLINE(); container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) { HashTable *ht; @@ -23951,14 +26799,167 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_TMP_HANDLER(ZE return zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_TMP(1, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_UNUSED != IS_UNUSED) { + + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = NULL; + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = NULL; + + if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_UNUSED == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = NULL; + + /* Consts, temporary variables and references need copying */ + if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_TMP_VAR != IS_UNUSED) { + zend_free_op free_op2; + zval *key = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!1) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op2, free_op_data1; zval **object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); zval *object; - zval *property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); + zval *property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); int have_get_ptr = 0; if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -24085,16 +27086,16 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_VAR(int (*bina } return zend_binary_assign_op_obj_helper_SPEC_UNUSED_VAR(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { - zval *dim = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_VAR, BP_VAR_RW TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } } break; default: - value = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + value = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); var_ptr = NULL; /* do nothing */ break; @@ -24219,7 +27220,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_VAR(incdec_ SAVE_OPLINE(); object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = &EX_T(opline->result.var).var.ptr; if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -24323,7 +27324,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_VAR(incdec SAVE_OPLINE(); object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = &EX_T(opline->result.var).tmp_var; if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -24423,7 +27424,7 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_VAR SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(TSRMLS_C); - offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -24468,7 +27469,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_H zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_UNUSED == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) { PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); @@ -24516,7 +27517,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_ zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); if (0) { @@ -24549,7 +27550,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_ SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(TSRMLS_C); - offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -24584,14 +27585,14 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_VAR_HANDLER(ZEND_O { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1, free_op2; zval *property; zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); if (0) { @@ -24626,7 +27627,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCO SAVE_OPLINE(); container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_UNUSED == IS_CV) { if (container != &EG(uninitialized_zval_ptr)) { @@ -24668,7 +27669,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HA SAVE_OPLINE(); object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - property_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property_name); @@ -24676,7 +27677,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HA if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (0) { zval_ptr_dtor(&property_name); } else { @@ -24699,7 +27700,7 @@ static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDL int use_copy = 0; SAVE_OPLINE(); - var = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + var = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_UNUSED == IS_UNUSED) { /* Initialize for erealloc in add_string_to_string */ @@ -24741,11 +27742,11 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPC char *function_name_strval; int function_name_strlen; zend_free_op free_op2; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); - function_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -24755,49 +27756,51 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPC function_name_strval = Z_STRVAL_P(function_name); function_name_strlen = Z_STRLEN_P(function_name); - EX(object) = _get_obj_zval_ptr_unused(TSRMLS_C); + call->object = _get_obj_zval_ptr_unused(TSRMLS_C); - if (EXPECTED(EX(object) != NULL) && - EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) { - EX(called_scope) = Z_OBJCE_P(EX(object)); + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); if (IS_VAR != IS_CONST || - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) { - zval *object = EX(object); + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; - if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) { + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { zend_error_noreturn(E_ERROR, "Object does not support method calls"); } /* First, locate the function. */ - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); } if (IS_VAR == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(EX(object) == object)) { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc)); + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); } } } else { zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } + call->is_ctor_call = 0; + EX(call) = call; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; @@ -24832,7 +27835,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HAN if (IS_UNUSED == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } - offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_UNUSED != IS_VAR || container) { switch (Z_TYPE_PP(container)) { @@ -24927,7 +27930,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_UNUSED != IS_VAR || container) { if (IS_UNUSED == IS_CV && container != &EG(uninitialized_zval_ptr)) { @@ -24971,7 +27974,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_VAR SAVE_OPLINE(); container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) { HashTable *ht; @@ -25110,6 +28113,160 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_VAR_HANDLER(ZE return zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_VAR(1, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_UNUSED != IS_UNUSED) { + + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = NULL; + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = NULL; + + if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_UNUSED == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = NULL; + + /* Consts, temporary variables and references need copying */ + if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_VAR != IS_UNUSED) { + zend_free_op free_op2; + zval *key = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -25117,7 +28274,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(int zval **object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); zval *object; zval *property = NULL; - zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); + zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); int have_get_ptr = 0; if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -25247,8 +28404,8 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_UNUSED(int (*b zval *dim = NULL; zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_UNUSED, BP_VAR_RW TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } } break; @@ -25379,14 +28536,167 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE } } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_UNUSED != IS_UNUSED) { + + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = NULL; + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = NULL; + + if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_UNUSED == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = NULL; + + /* Consts, temporary variables and references need copying */ + if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_UNUSED != IS_UNUSED) { + + zval *key = NULL; + + /* Consts, temporary variables and references need copying */ + if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op_data1; zval **object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); zval *object; - zval *property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); - zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); + zval *property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); int have_get_ptr = 0; if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -25513,16 +28823,16 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_UNUSED_CV(int (*binar } return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { - zval *dim = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + zval *dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_CV, BP_VAR_RW TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } } break; default: - value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); var_ptr = NULL; /* do nothing */ break; @@ -25646,7 +28956,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CV(incdec_t SAVE_OPLINE(); object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); retval = &EX_T(opline->result.var).var.ptr; if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -25750,7 +29060,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CV(incdec_ SAVE_OPLINE(); object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); retval = &EX_T(opline->result.var).tmp_var; if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -25850,7 +29160,7 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_UNUSED_CV( SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(TSRMLS_C); - offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -25895,7 +29205,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HA zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_UNUSED == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) { PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); @@ -25943,7 +29253,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_H zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); if (0) { @@ -25976,7 +29286,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); container = _get_obj_zval_ptr_unused(TSRMLS_C); - offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -26011,14 +29321,14 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CV_HANDLER(ZEND_OP { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1; zval *property; zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); if (0) { @@ -26053,7 +29363,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CV_HANDLER(ZEND_OPCOD SAVE_OPLINE(); container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_UNUSED == IS_CV) { if (container != &EG(uninitialized_zval_ptr)) { @@ -26095,7 +29405,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HAN SAVE_OPLINE(); object_ptr = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - property_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property_name); @@ -26103,7 +29413,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HAN if (IS_UNUSED == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (0) { zval_ptr_dtor(&property_name); } else { @@ -26126,7 +29436,7 @@ static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLE int use_copy = 0; SAVE_OPLINE(); - var = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + var = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_UNUSED == IS_UNUSED) { /* Initialize for erealloc in add_string_to_string */ @@ -26167,11 +29477,11 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCO char *function_name_strval; int function_name_strlen; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); - function_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_CV != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -26181,49 +29491,51 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCO function_name_strval = Z_STRVAL_P(function_name); function_name_strlen = Z_STRLEN_P(function_name); - EX(object) = _get_obj_zval_ptr_unused(TSRMLS_C); + call->object = _get_obj_zval_ptr_unused(TSRMLS_C); - if (EXPECTED(EX(object) != NULL) && - EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) { - EX(called_scope) = Z_OBJCE_P(EX(object)); + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); if (IS_CV != IS_CONST || - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) { - zval *object = EX(object); + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; - if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) { + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { zend_error_noreturn(E_ERROR, "Object does not support method calls"); } /* First, locate the function. */ - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); } if (IS_CV == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(EX(object) == object)) { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc)); + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); } } } else { zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); @@ -26257,7 +29569,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HAND if (IS_UNUSED == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } - offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_UNUSED != IS_VAR || container) { switch (Z_TYPE_PP(container)) { @@ -26352,7 +29664,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_UNUSED != IS_VAR || container) { if (IS_UNUSED == IS_CV && container != &EG(uninitialized_zval_ptr)) { @@ -26396,7 +29708,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_CV( SAVE_OPLINE(); container = _get_obj_zval_ptr_ptr_unused(TSRMLS_C); - offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) { HashTable *ht; @@ -26535,6 +29847,159 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CV_HANDLER(ZEN return zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_CV(1, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_UNUSED != IS_UNUSED) { + + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = NULL; + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = NULL; + + if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_UNUSED == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = NULL; + + /* Consts, temporary variables and references need copying */ + if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_CV != IS_UNUSED) { + + zval *key = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL ZEND_BW_NOT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -26542,7 +30007,7 @@ static int ZEND_FASTCALL ZEND_BW_NOT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); bitwise_not_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -26555,7 +30020,7 @@ static int ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); boolean_not_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -26568,7 +30033,7 @@ static int ZEND_FASTCALL ZEND_PRE_INC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zval **var_ptr; SAVE_OPLINE(); - var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); @@ -26614,7 +30079,7 @@ static int ZEND_FASTCALL ZEND_PRE_DEC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zval **var_ptr; SAVE_OPLINE(); - var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); @@ -26660,7 +30125,7 @@ static int ZEND_FASTCALL ZEND_POST_INC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS zval **var_ptr, *retval; SAVE_OPLINE(); - var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); @@ -26702,7 +30167,7 @@ static int ZEND_FASTCALL ZEND_POST_DEC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS zval **var_ptr, *retval; SAVE_OPLINE(); - var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); @@ -26745,7 +30210,7 @@ static int ZEND_FASTCALL ZEND_ECHO_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zval *z; SAVE_OPLINE(); - z = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + z = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV != IS_CONST && UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && @@ -26783,7 +30248,7 @@ static int ZEND_FASTCALL ZEND_JMPZ_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) int ret; SAVE_OPLINE(); - val = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + val = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) { ret = Z_LVAL_P(val); @@ -26813,7 +30278,7 @@ static int ZEND_FASTCALL ZEND_JMPNZ_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) int ret; SAVE_OPLINE(); - val = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + val = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) { ret = Z_LVAL_P(val); @@ -26843,7 +30308,7 @@ static int ZEND_FASTCALL ZEND_JMPZNZ_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) int retval; SAVE_OPLINE(); - val = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + val = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) { retval = Z_LVAL_P(val); @@ -26877,7 +30342,7 @@ static int ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) int retval; SAVE_OPLINE(); - val = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + val = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) { retval = Z_LVAL_P(val); @@ -26908,7 +30373,7 @@ static int ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS int retval; SAVE_OPLINE(); - val = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + val = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_TMP_VAR && EXPECTED(Z_TYPE_P(val) == IS_BOOL)) { retval = Z_LVAL_P(val); @@ -26938,13 +30403,16 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); - retval_ptr = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + retval_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (!EG(return_value_ptr_ptr)) { if (IS_CV == IS_TMP_VAR) { } } else if (!0) { /* Not a temp var */ + if (*EG(return_value_ptr_ptr)) { + zval_ptr_dtor(EG(return_value_ptr_ptr)); + } if (IS_CV == IS_CONST || (PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) { zval *ret; @@ -26966,6 +30434,10 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } else { zval *ret; + if (*EG(return_value_ptr_ptr)) { + zval_ptr_dtor(EG(return_value_ptr_ptr)); + } + ALLOC_ZVAL(ret); INIT_PZVAL_COPY(ret, retval_ptr); *EG(return_value_ptr_ptr) = ret; @@ -26984,11 +30456,15 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); do { + if (EG(return_value_ptr_ptr) && *EG(return_value_ptr_ptr)) { + zval_ptr_dtor(EG(return_value_ptr_ptr)); + } + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { /* Not supposed to happen, but we'll allow it */ zend_error(E_NOTICE, "Only variable references should be returned by reference"); - retval_ptr = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + retval_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (!EG(return_value_ptr_ptr)) { if (IS_CV == IS_TMP_VAR) { @@ -27010,7 +30486,7 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER break; } - retval_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + retval_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(retval_ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference"); @@ -27049,7 +30525,7 @@ static int ZEND_FASTCALL ZEND_THROW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); - value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) { zend_error_noreturn(E_ERROR, "Can only throw objects"); @@ -27073,7 +30549,7 @@ static int ZEND_FASTCALL zend_send_by_var_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARG USE_OPLINE zval *varptr; - varptr = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + varptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (varptr == &EG(uninitialized_zval)) { ALLOC_ZVAL(varptr); @@ -27107,7 +30583,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL if (!(opline->extended_value & ZEND_ARG_SEND_BY_REF)) { return zend_send_by_var_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } - } else if (!ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) { + } else if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.opline_num)) { return zend_send_by_var_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } @@ -27118,7 +30594,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL varptr = EX_T(opline->op1.var).var.ptr; PZVAL_UNLOCK_EX(varptr, &free_op1, 0); } else { - varptr = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + varptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); } if ((!(opline->extended_value & ZEND_ARG_SEND_FUNCTION) || EX_T(opline->op1.var).var.fcall_returned_reference) && @@ -27133,7 +30609,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL if ((opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) ? !(opline->extended_value & ZEND_ARG_SEND_SILENT) : - !ARG_MAY_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) { + !ARG_MAY_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.opline_num)) { zend_error(E_STRICT, "Only variables should be passed by reference"); } ALLOC_ZVAL(valptr); @@ -27156,7 +30632,7 @@ static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS zval *varptr; SAVE_OPLINE(); - varptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + varptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(varptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Only variables can be passed by reference"); @@ -27169,7 +30645,7 @@ static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS ZEND_VM_NEXT_OPCODE(); } - if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION && !ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) { + if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION && !ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.opline_num)) { return zend_send_by_var_helper_SPEC_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } @@ -27187,7 +30663,7 @@ static int ZEND_FASTCALL ZEND_SEND_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS USE_OPLINE if ((opline->extended_value == ZEND_DO_FCALL_BY_NAME) - && ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), opline->op2.opline_num)) { + && ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, opline->op2.opline_num)) { return ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } SAVE_OPLINE(); @@ -27202,7 +30678,7 @@ static int ZEND_FASTCALL ZEND_BOOL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); /* PHP 3.0 returned "" for false and 1 for true, here we use 0 and 1 for now */ - ZVAL_BOOL(retval, i_zend_is_true(_get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC))); + ZVAL_BOOL(retval, i_zend_is_true(_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC))); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -27218,7 +30694,7 @@ static int ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_object_clone_obj_t clone_call; SAVE_OPLINE(); - obj = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + obj = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_CONST || UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT)) { @@ -27279,7 +30755,7 @@ static int ZEND_FASTCALL ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zval *result = &EX_T(opline->result.var).tmp_var; SAVE_OPLINE(); - expr = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + expr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (opline->extended_value != IS_STRING) { ZVAL_COPY_VALUE(result, expr); @@ -27336,11 +30812,11 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL zend_op_array *new_op_array=NULL; zval *inc_filename; - zval *tmp_inc_filename = NULL; + zval *tmp_inc_filename = NULL; zend_bool failure_retval=0; SAVE_OPLINE(); - inc_filename = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + inc_filename = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (inc_filename->type!=IS_STRING) { MAKE_STD_ZVAL(tmp_inc_filename); @@ -27428,8 +30904,6 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL EG(return_value_ptr_ptr) = NULL; } - EX(current_object) = EX(object); - EX(function_state).function = (zend_function *) new_op_array; EX(object) = NULL; @@ -27437,14 +30911,13 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL zend_rebuild_symbol_table(TSRMLS_C); } - if (EXPECTED(zend_execute == execute)) { + if (EXPECTED(zend_execute_ex == execute_ex)) { ZEND_VM_ENTER(); } else { zend_execute(new_op_array TSRMLS_CC); } EX(function_state).function = (zend_function *) EX(op_array); - EX(object) = EX(current_object); EG(opline_ptr) = &EX(opline); EG(active_op_array) = EX(op_array); @@ -27454,15 +30927,6 @@ static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL if (UNEXPECTED(EG(exception) != NULL)) { zend_throw_exception_internal(NULL TSRMLS_CC); HANDLE_EXCEPTION(); - } else if (RETURN_VALUE_USED(opline)) { - if (!EX_T(opline->result.var).var.ptr) { /* there was no return statement */ - zval *retval; - - ALLOC_ZVAL(retval); - ZVAL_BOOL(retval, 1); - INIT_PZVAL(retval); - EX_T(opline->result.var).var.ptr = retval; - } } } else if (RETURN_VALUE_USED(opline)) { @@ -27490,7 +30954,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS if ((IS_CV == IS_CV || IS_CV == IS_VAR) && (opline->extended_value & ZEND_FE_RESET_VARIABLE)) { - array_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + array_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (array_ptr_ptr == NULL || array_ptr_ptr == &EG(uninitialized_zval_ptr)) { MAKE_STD_ZVAL(array_ptr); ZVAL_NULL(array_ptr); @@ -27517,7 +30981,7 @@ static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS Z_ADDREF_P(array_ptr); } } else { - array_ptr = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + array_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (0) { /* IS_TMP_VAR */ zval *tmp; @@ -27626,7 +31090,7 @@ static int ZEND_FASTCALL ZEND_EXIT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); if (IS_CV != IS_UNUSED) { - zval *ptr = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + zval *ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (Z_TYPE_P(ptr) == IS_LONG) { EG(exit_status) = Z_LVAL_P(ptr); @@ -27647,7 +31111,7 @@ static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zval *value; SAVE_OPLINE(); - value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (i_zend_is_true(value)) { ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value); @@ -27672,7 +31136,7 @@ static int ZEND_FASTCALL ZEND_JMP_SET_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_A zval *value, *ret; SAVE_OPLINE(); - value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (i_zend_is_true(value)) { if (IS_CV == IS_VAR || IS_CV == IS_CV) { @@ -27706,7 +31170,7 @@ static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG zval *value; SAVE_OPLINE(); - value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value); if (!0) { @@ -27724,7 +31188,7 @@ static int ZEND_FASTCALL ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER zval *value, *ret; SAVE_OPLINE(); - value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR || IS_CV == IS_CV) { Z_ADDREF_P(value); @@ -27752,7 +31216,7 @@ static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_AR zend_bool result; SAVE_OPLINE(); - expr = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + expr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (Z_TYPE_P(expr) == IS_OBJECT && Z_OBJ_HT_P(expr)->get_class_entry) { result = instanceof_function(Z_OBJCE_P(expr), EX_T(opline->op2.var).class_entry TSRMLS_CC); @@ -27772,7 +31236,7 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); fast_add_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC); @@ -27787,7 +31251,7 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); fast_sub_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC); @@ -27802,7 +31266,7 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); fast_mul_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC); @@ -27817,7 +31281,7 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); fast_div_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC); @@ -27832,7 +31296,7 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); fast_mod_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC); @@ -27847,7 +31311,7 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); shift_left_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC); @@ -27862,7 +31326,7 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); shift_right_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC); @@ -27877,7 +31341,7 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); concat_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC); @@ -27892,7 +31356,7 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HA SAVE_OPLINE(); is_identical_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC); @@ -27908,7 +31372,7 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CONST_HANDLER(ZEND_OPCOD SAVE_OPLINE(); is_identical_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC); Z_LVAL_P(result) = !Z_LVAL_P(result); @@ -27925,7 +31389,7 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLE SAVE_OPLINE(); ZVAL_BOOL(result, fast_equal_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC)); @@ -27941,7 +31405,7 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HA SAVE_OPLINE(); ZVAL_BOOL(result, fast_not_equal_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC)); @@ -27957,7 +31421,7 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC)); @@ -27973,7 +31437,7 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CV_CONST_HANDLER(ZEND_OP SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC)); @@ -27988,7 +31452,7 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); bitwise_or_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC); @@ -28003,7 +31467,7 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); bitwise_and_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC); @@ -28018,7 +31482,7 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); bitwise_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC); @@ -28033,7 +31497,7 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLE SAVE_OPLINE(); boolean_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC); @@ -28045,10 +31509,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CONST(int (*bi { USE_OPLINE zend_free_op free_op_data1; - zval **object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + zval **object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); zval *object; zval *property = opline->op2.zv; - zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); + zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); int have_get_ptr = 0; if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -28165,7 +31629,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CONST(int (*binary return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); break; case ZEND_ASSIGN_DIM: { - zval **container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + zval **container = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -28178,14 +31642,14 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CONST(int (*binary zval *dim = opline->op2.zv; zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_CONST, BP_VAR_RW TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } } break; default: value = opline->op2.zv; - var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); /* do nothing */ break; } @@ -28307,7 +31771,7 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CONST(incdec_t int have_get_ptr = 0; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); property = opline->op2.zv; retval = &EX_T(opline->result.var).var.ptr; @@ -28411,7 +31875,7 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CONST(incdec_t int have_get_ptr = 0; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); property = opline->op2.zv; retval = &EX_T(opline->result.var).tmp_var; @@ -28513,7 +31977,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_CONST(int type, Z ulong hash_value; SAVE_OPLINE(); - varname = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV != IS_CONST && UNEXPECTED(Z_TYPE_P(varname) != IS_STRING)) { ZVAL_COPY_VALUE(&tmp_varname, varname); @@ -28653,7 +32117,7 @@ static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_ { USE_OPLINE - return zend_fetch_var_address_helper_SPEC_CV_CONST(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_CV_CONST(ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -28679,9 +32143,18 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAN EX_T(opline->op1.var).var.ptr_ptr) { PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); } - container = _get_zval_ptr_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC); + if (IS_CV == IS_TMP_VAR || IS_CV == IS_CONST) { + zval *container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), &container, opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC); + + + } else { + container = _get_zval_ptr_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC); + + + } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -28694,7 +32167,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAN zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -28727,7 +32200,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HA zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -28749,7 +32222,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HA zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, opline->op2.zv, IS_CONST, BP_VAR_IS TSRMLS_CC); @@ -28765,8 +32238,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPC SAVE_OPLINE(); - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { - container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } @@ -28778,7 +32251,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPC if (IS_CONST == IS_UNUSED) { zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); } - container = _get_zval_ptr_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, opline->op2.zv, IS_CONST, BP_VAR_R TSRMLS_CC); } @@ -28794,7 +32267,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_CV) { if (container != &EG(uninitialized_zval_ptr)) { @@ -28812,6 +32285,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE if (UNEXPECTED(EX_T(opline->result.var).var.ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_NEXT_OPCODE(); } else { zend_free_op free_res; zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr; @@ -28836,7 +32310,7 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_CONST(Z zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); offset = opline->op2.zv; if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || @@ -28892,7 +32366,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAN if (0) { MAKE_REAL_ZVAL_PTR(property); } - container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -28931,7 +32405,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HA SAVE_OPLINE(); property = opline->op2.zv; - container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property); @@ -28962,7 +32436,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HA zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); offset = opline->op2.zv; if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || @@ -28998,7 +32472,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPC { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1; zval *property; @@ -29006,7 +32480,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPC SAVE_OPLINE(); property = opline->op2.zv; - container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property); @@ -29039,7 +32513,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE zval *property; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); property = opline->op2.zv; if (IS_CV == IS_CV) { @@ -29081,7 +32555,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND zval *property_name; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); property_name = opline->op2.zv; if (0) { @@ -29090,7 +32564,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (0) { zval_ptr_dtor(&property_name); } else { @@ -29110,7 +32584,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND zval **object_ptr; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -29122,7 +32596,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND if (0) { MAKE_REAL_ZVAL_PTR(property_name); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_DIM, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CONST == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (0) { zval_ptr_dtor(&property_name); } else { @@ -29136,8 +32610,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), object_ptr, dim, IS_CONST, BP_VAR_W TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); if (UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) { if (RETURN_VALUE_USED(opline)) { @@ -29192,7 +32666,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); value = opline->op2.zv; - variable_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + variable_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T(opline->op1.var), value, IS_CONST TSRMLS_CC)) { @@ -29243,9 +32717,9 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCOD char *function_name_strval; int function_name_strlen; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); function_name = opline->op2.zv; @@ -29257,49 +32731,51 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCOD function_name_strval = Z_STRVAL_P(function_name); function_name_strlen = Z_STRLEN_P(function_name); - EX(object) = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + call->object = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - if (EXPECTED(EX(object) != NULL) && - EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) { - EX(called_scope) = Z_OBJCE_P(EX(object)); + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); if (IS_CONST != IS_CONST || - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) { - zval *object = EX(object); + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; - if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) { + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { zend_error_noreturn(E_ERROR, "Object does not support method calls"); } /* First, locate the function. */ - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((IS_CONST == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); } if (IS_CONST == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(EX(object) == object)) { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc)); + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); } } } else { zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); @@ -29316,7 +32792,7 @@ static int ZEND_FASTCALL ZEND_CASE_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR PZVAL_LOCK(EX_T(opline->op1.var).var.ptr); } is_equal_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), opline->op2.zv TSRMLS_CC); CHECK_EXCEPTION(); @@ -29331,7 +32807,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER(ZEND_OPCO SAVE_OPLINE(); if ((IS_CV == IS_VAR || IS_CV == IS_CV) && opline->extended_value) { - zval **expr_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + zval **expr_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); @@ -29340,7 +32816,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER(ZEND_OPCO expr_ptr = *expr_ptr_ptr; Z_ADDREF_P(expr_ptr); } else { - expr_ptr=_get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + expr_ptr=_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (0) { /* temporary variable */ zval *new_expr; @@ -29447,7 +32923,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL ZEND_VM_NEXT_OPCODE(); } - varname = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, varname); @@ -29508,7 +32984,7 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL ulong hval; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } @@ -29606,7 +33082,7 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDL zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); offset = opline->op2.zv; if (IS_CV != IS_VAR || container) { @@ -29662,7 +33138,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCO } else { HashTable *target_symbol_table; - zval tmp, *varname = _get_zval_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC); + zval tmp, *varname = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, varname); @@ -29734,7 +33210,7 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_CONST(i zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); offset = opline->op2.zv; @@ -29875,6 +33351,159 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CONST_HANDLER(ZEND return zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_CONST(1, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_CV != IS_UNUSED) { + + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + + if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_CV == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_CONST != IS_UNUSED) { + + zval *key = opline->op2.zv; + + /* Consts, temporary variables and references need copying */ + if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL ZEND_ADD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -29882,8 +33511,8 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_add_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -29897,8 +33526,8 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_sub_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -29912,8 +33541,8 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_mul_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -29927,8 +33556,8 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_div_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -29942,8 +33571,8 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_mod_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -29957,8 +33586,8 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_left_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -29972,8 +33601,8 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_right_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -29987,8 +33616,8 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); concat_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -30002,8 +33631,8 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); is_identical_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -30018,8 +33647,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_ SAVE_OPLINE(); is_identical_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); Z_LVAL_P(result) = !Z_LVAL_P(result); zval_dtor(free_op2.var); @@ -30035,8 +33664,8 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); ZVAL_BOOL(result, fast_equal_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -30051,8 +33680,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); ZVAL_BOOL(result, fast_not_equal_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -30067,8 +33696,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -30083,8 +33712,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CV_TMP_HANDLER(ZEND_OPCO SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -30098,8 +33727,8 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); bitwise_or_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -30113,8 +33742,8 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); bitwise_and_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -30128,8 +33757,8 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); bitwise_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -30143,8 +33772,8 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); boolean_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -30155,10 +33784,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_TMP(int (*bina { USE_OPLINE zend_free_op free_op2, free_op_data1; - zval **object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + zval **object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); zval *object; - zval *property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); + zval *property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); int have_get_ptr = 0; if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -30275,7 +33904,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_TMP(int (*binary_o return zend_binary_assign_op_obj_helper_SPEC_CV_TMP(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); break; case ZEND_ASSIGN_DIM: { - zval **container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + zval **container = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -30285,17 +33914,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_TMP(int (*binary_o } return zend_binary_assign_op_obj_helper_SPEC_CV_TMP(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { - zval *dim = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_TMP_VAR, BP_VAR_RW TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } } break; default: - value = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + value = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); /* do nothing */ break; } @@ -30418,8 +34047,8 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_TMP(incdec_t in int have_get_ptr = 0; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); - property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = &EX_T(opline->result.var).var.ptr; if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -30522,8 +34151,8 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_TMP(incdec_t i int have_get_ptr = 0; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); - property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = &EX_T(opline->result.var).tmp_var; if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -30626,9 +34255,18 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDL EX_T(opline->op1.var).var.ptr_ptr) { PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); } - container = _get_zval_ptr_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_R TSRMLS_CC); - zval_dtor(free_op2.var); + + if (IS_CV == IS_TMP_VAR || IS_CV == IS_CONST) { + zval *container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), &container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_R TSRMLS_CC); + zval_dtor(free_op2.var); + + } else { + container = _get_zval_ptr_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_R TSRMLS_CC); + zval_dtor(free_op2.var); + + } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -30641,12 +34279,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDL zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_W TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_W TSRMLS_CC); zval_dtor(free_op2.var); if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); @@ -30674,12 +34312,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HAND zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_RW TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_RW TSRMLS_CC); zval_dtor(free_op2.var); if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); @@ -30696,8 +34334,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HAND zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_IS TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_IS TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -30712,12 +34350,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_TMP_HANDLER(ZEND_OPCOD SAVE_OPLINE(); - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { - container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_W TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_W TSRMLS_CC); if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); } @@ -30725,8 +34363,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_TMP_HANDLER(ZEND_OPCOD if (IS_TMP_VAR == IS_UNUSED) { zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); } - container = _get_zval_ptr_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_R TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_R TSRMLS_CC); } zval_dtor(free_op2.var); @@ -30741,7 +34379,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_H zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_CV) { if (container != &EG(uninitialized_zval_ptr)) { @@ -30751,7 +34389,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_H if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_UNSET TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR, BP_VAR_UNSET TSRMLS_CC); zval_dtor(free_op2.var); if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); @@ -30759,6 +34397,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_H if (UNEXPECTED(EX_T(opline->result.var).var.ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_NEXT_OPCODE(); } else { zend_free_op free_res; zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr; @@ -30783,8 +34422,8 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_TMP(ZEN zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); - offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -30829,7 +34468,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDL zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_CV == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) { PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); @@ -30839,7 +34478,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDL if (1) { MAKE_REAL_ZVAL_PTR(property); } - container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -30877,8 +34516,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HAND zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (1) { MAKE_REAL_ZVAL_PTR(property); @@ -30909,8 +34548,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HAND zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC); - offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + container = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -30945,15 +34584,15 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMP_HANDLER(ZEND_OPCOD { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1, free_op2; zval *property; zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (1) { MAKE_REAL_ZVAL_PTR(property); @@ -30986,8 +34625,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_H zval *property; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC); - property = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_CV == IS_CV) { if (container != &EG(uninitialized_zval_ptr)) { @@ -31028,8 +34667,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE zval *property_name; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); - property_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + property_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (1) { MAKE_REAL_ZVAL_PTR(property_name); @@ -31037,7 +34676,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (1) { zval_ptr_dtor(&property_name); } else { @@ -31057,19 +34696,19 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE zval **object_ptr; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } if (Z_TYPE_PP(object_ptr) == IS_OBJECT) { zend_free_op free_op2; - zval *property_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *property_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (1) { MAKE_REAL_ZVAL_PTR(property_name); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_DIM, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_TMP_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (1) { zval_ptr_dtor(&property_name); } else { @@ -31078,14 +34717,14 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE } else { zend_free_op free_op2, free_op_data1, free_op_data2; zval *value; - zval *dim = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *dim = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zval **variable_ptr_ptr; zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), object_ptr, dim, IS_TMP_VAR, BP_VAR_W TSRMLS_CC); zval_dtor(free_op2.var); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); if (UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) { if (RETURN_VALUE_USED(opline)) { @@ -31139,8 +34778,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR zval **variable_ptr_ptr; SAVE_OPLINE(); - value = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - variable_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + value = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + variable_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T(opline->op1.var), value, IS_TMP_VAR TSRMLS_CC)) { @@ -31191,11 +34830,11 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_ char *function_name_strval; int function_name_strlen; zend_free_op free_op2; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); - function_name = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + function_name = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_TMP_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -31205,49 +34844,51 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_ function_name_strval = Z_STRVAL_P(function_name); function_name_strlen = Z_STRLEN_P(function_name); - EX(object) = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + call->object = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - if (EXPECTED(EX(object) != NULL) && - EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) { - EX(called_scope) = Z_OBJCE_P(EX(object)); + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); if (IS_TMP_VAR != IS_CONST || - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) { - zval *object = EX(object); + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; - if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) { + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { zend_error_noreturn(E_ERROR, "Object does not support method calls"); } /* First, locate the function. */ - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((IS_TMP_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); } if (IS_TMP_VAR == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(EX(object) == object)) { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc)); + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); } } } else { zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } + call->is_ctor_call = 0; + EX(call) = call; zval_dtor(free_op2.var); @@ -31265,8 +34906,8 @@ static int ZEND_FASTCALL ZEND_CASE_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS PZVAL_LOCK(EX_T(opline->op1.var).var.ptr); } is_equal_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); zval_dtor(free_op2.var); CHECK_EXCEPTION(); @@ -31281,7 +34922,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMP_HANDLER(ZEND_OPCODE SAVE_OPLINE(); if ((IS_CV == IS_VAR || IS_CV == IS_CV) && opline->extended_value) { - zval **expr_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + zval **expr_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); @@ -31290,7 +34931,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMP_HANDLER(ZEND_OPCODE expr_ptr = *expr_ptr_ptr; Z_ADDREF_P(expr_ptr); } else { - expr_ptr=_get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + expr_ptr=_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (0) { /* temporary variable */ zval *new_expr; @@ -31311,7 +34952,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMP_HANDLER(ZEND_OPCODE if (IS_TMP_VAR != IS_UNUSED) { zend_free_op free_op2; - zval *offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); ulong hval; switch (Z_TYPE_P(offset)) { @@ -31382,11 +35023,11 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER ulong hval; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } - offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_CV != IS_VAR || container) { switch (Z_TYPE_PP(container)) { @@ -31480,8 +35121,8 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC); - offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_CV != IS_VAR || container) { if (IS_CV == IS_CV && container != &EG(uninitialized_zval_ptr)) { @@ -31523,9 +35164,9 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_TMP(int zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); - offset = _get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) { HashTable *ht; @@ -31664,6 +35305,159 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_TMP_HANDLER(ZEND_O return zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_TMP(1, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_CV != IS_UNUSED) { + + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + + if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_CV == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_TMP_VAR != IS_UNUSED) { + zend_free_op free_op2; + zval *key = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!1) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL ZEND_ADD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -31671,8 +35465,8 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_add_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -31686,8 +35480,8 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_sub_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -31701,8 +35495,8 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_mul_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -31716,8 +35510,8 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_div_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -31731,8 +35525,8 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_mod_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -31746,8 +35540,8 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_left_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -31761,8 +35555,8 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_right_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -31776,8 +35570,8 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); concat_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -31791,8 +35585,8 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); is_identical_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -31807,8 +35601,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_ SAVE_OPLINE(); is_identical_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); Z_LVAL_P(result) = !Z_LVAL_P(result); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; @@ -31824,8 +35618,8 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); ZVAL_BOOL(result, fast_equal_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -31840,8 +35634,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HAND SAVE_OPLINE(); ZVAL_BOOL(result, fast_not_equal_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -31856,8 +35650,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -31872,8 +35666,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CV_VAR_HANDLER(ZEND_OPCO SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC)); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -31887,8 +35681,8 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); bitwise_or_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -31902,8 +35696,8 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); bitwise_and_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -31917,8 +35711,8 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR SAVE_OPLINE(); bitwise_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -31932,8 +35726,8 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ SAVE_OPLINE(); boolean_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -31944,10 +35738,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_VAR(int (*bina { USE_OPLINE zend_free_op free_op2, free_op_data1; - zval **object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + zval **object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); zval *object; - zval *property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); + zval *property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); int have_get_ptr = 0; if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -32064,7 +35858,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_VAR(int (*binary_o return zend_binary_assign_op_obj_helper_SPEC_CV_VAR(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); break; case ZEND_ASSIGN_DIM: { - zval **container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + zval **container = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -32074,17 +35868,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_VAR(int (*binary_o } return zend_binary_assign_op_obj_helper_SPEC_CV_VAR(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { - zval *dim = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_VAR, BP_VAR_RW TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } } break; default: - value = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + value = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); /* do nothing */ break; } @@ -32207,8 +36001,8 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_VAR(incdec_t in int have_get_ptr = 0; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); - property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = &EX_T(opline->result.var).var.ptr; if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -32311,8 +36105,8 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_VAR(incdec_t i int have_get_ptr = 0; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); - property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); retval = &EX_T(opline->result.var).tmp_var; if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -32413,7 +36207,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_VAR(int type, ZEN ulong hash_value; SAVE_OPLINE(); - varname = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV != IS_CONST && UNEXPECTED(Z_TYPE_P(varname) != IS_STRING)) { ZVAL_COPY_VALUE(&tmp_varname, varname); @@ -32553,7 +36347,7 @@ static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HA { USE_OPLINE - return zend_fetch_var_address_helper_SPEC_CV_VAR(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_CV_VAR(ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -32579,9 +36373,18 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDL EX_T(opline->op1.var).var.ptr_ptr) { PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); } - container = _get_zval_ptr_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_R TSRMLS_CC); - if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + + if (IS_CV == IS_TMP_VAR || IS_CV == IS_CONST) { + zval *container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), &container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_R TSRMLS_CC); + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + + } else { + container = _get_zval_ptr_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_R TSRMLS_CC); + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + + } CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -32594,12 +36397,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDL zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_W TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_W TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); @@ -32627,12 +36430,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HAND zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_RW TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_RW TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); @@ -32649,8 +36452,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HAND zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_IS TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_IS TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -32665,12 +36468,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_VAR_HANDLER(ZEND_OPCOD SAVE_OPLINE(); - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { - container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_W TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_W TSRMLS_CC); if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); } @@ -32678,8 +36481,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_VAR_HANDLER(ZEND_OPCOD if (IS_VAR == IS_UNUSED) { zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); } - container = _get_zval_ptr_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_R TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_R TSRMLS_CC); } if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; @@ -32694,7 +36497,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_H zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_CV) { if (container != &EG(uninitialized_zval_ptr)) { @@ -32704,7 +36507,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_H if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_UNSET TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR, BP_VAR_UNSET TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); @@ -32712,6 +36515,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_H if (UNEXPECTED(EX_T(opline->result.var).var.ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_NEXT_OPCODE(); } else { zend_free_op free_res; zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr; @@ -32736,8 +36540,8 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_VAR(ZEN zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); - offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -32782,7 +36586,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDL zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_CV == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) { PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); @@ -32792,7 +36596,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDL if (0) { MAKE_REAL_ZVAL_PTR(property); } - container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -32830,8 +36634,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HAND zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property); @@ -32862,8 +36666,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HAND zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC); - offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + container = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -32898,15 +36702,15 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_VAR_HANDLER(ZEND_OPCOD { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1, free_op2; zval *property; zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property); @@ -32939,8 +36743,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_H zval *property; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC); - property = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); + property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_CV == IS_CV) { if (container != &EG(uninitialized_zval_ptr)) { @@ -32981,8 +36785,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE zval *property_name; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); - property_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property_name); @@ -32990,7 +36794,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (0) { zval_ptr_dtor(&property_name); } else { @@ -33010,19 +36814,19 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE zval **object_ptr; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } if (Z_TYPE_PP(object_ptr) == IS_OBJECT) { zend_free_op free_op2; - zval *property_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property_name); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_DIM, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_VAR == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (0) { zval_ptr_dtor(&property_name); } else { @@ -33031,14 +36835,14 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE } else { zend_free_op free_op2, free_op_data1, free_op_data2; zval *value; - zval *dim = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); zval **variable_ptr_ptr; zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), object_ptr, dim, IS_VAR, BP_VAR_W TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); if (UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) { if (RETURN_VALUE_USED(opline)) { @@ -33092,8 +36896,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR zval **variable_ptr_ptr; SAVE_OPLINE(); - value = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); - variable_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + value = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + variable_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T(opline->op1.var), value, IS_VAR TSRMLS_CC)) { @@ -33146,7 +36950,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE zval **value_ptr_ptr; SAVE_OPLINE(); - value_ptr_ptr = _get_zval_ptr_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + value_ptr_ptr = _get_zval_ptr_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_VAR == IS_VAR && value_ptr_ptr && @@ -33169,7 +36973,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object"); } - variable_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + variable_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if ((IS_VAR == IS_VAR && UNEXPECTED(value_ptr_ptr == NULL)) || (IS_CV == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL))) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); @@ -33198,11 +37002,11 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_ char *function_name_strval; int function_name_strlen; zend_free_op free_op2; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); - function_name = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -33212,49 +37016,51 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_ function_name_strval = Z_STRVAL_P(function_name); function_name_strlen = Z_STRLEN_P(function_name); - EX(object) = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + call->object = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - if (EXPECTED(EX(object) != NULL) && - EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) { - EX(called_scope) = Z_OBJCE_P(EX(object)); + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); if (IS_VAR != IS_CONST || - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) { - zval *object = EX(object); + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; - if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) { + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { zend_error_noreturn(E_ERROR, "Object does not support method calls"); } /* First, locate the function. */ - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((IS_VAR == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); } if (IS_VAR == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(EX(object) == object)) { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc)); + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); } } } else { zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } + call->is_ctor_call = 0; + EX(call) = call; if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; @@ -33272,8 +37078,8 @@ static int ZEND_FASTCALL ZEND_CASE_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS PZVAL_LOCK(EX_T(opline->op1.var).var.ptr); } is_equal_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC) TSRMLS_CC); if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; CHECK_EXCEPTION(); @@ -33288,7 +37094,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_VAR_HANDLER(ZEND_OPCODE SAVE_OPLINE(); if ((IS_CV == IS_VAR || IS_CV == IS_CV) && opline->extended_value) { - zval **expr_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + zval **expr_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); @@ -33297,7 +37103,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_VAR_HANDLER(ZEND_OPCODE expr_ptr = *expr_ptr_ptr; Z_ADDREF_P(expr_ptr); } else { - expr_ptr=_get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + expr_ptr=_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (0) { /* temporary variable */ zval *new_expr; @@ -33318,7 +37124,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_VAR_HANDLER(ZEND_OPCODE if (IS_VAR != IS_UNUSED) { zend_free_op free_op2; - zval *offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + zval *offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); ulong hval; switch (Z_TYPE_P(offset)) { @@ -33404,7 +37210,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER ZEND_VM_NEXT_OPCODE(); } - varname = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, varname); @@ -33465,11 +37271,11 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER ulong hval; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } - offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_CV != IS_VAR || container) { switch (Z_TYPE_PP(container)) { @@ -33563,8 +37369,8 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC); - offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (IS_CV != IS_VAR || container) { if (IS_CV == IS_CV && container != &EG(uninitialized_zval_ptr)) { @@ -33619,7 +37425,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE } else { HashTable *target_symbol_table; - zval tmp, *varname = _get_zval_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC); + zval tmp, *varname = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, varname); @@ -33691,9 +37497,9 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_VAR(int zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); - offset = _get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) { HashTable *ht; @@ -33832,14 +37638,168 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_VAR_HANDLER(ZEND_O return zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_VAR(1, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_CV != IS_UNUSED) { + + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + + if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_CV == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_VAR != IS_UNUSED) { + zend_free_op free_op2; + zval *key = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + if (free_op2.var) {zval_ptr_dtor(&free_op2.var);}; + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op_data1; - zval **object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + zval **object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); zval *object; zval *property = NULL; - zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); + zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); int have_get_ptr = 0; if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -33956,7 +37916,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_UNUSED(int (*binar return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); break; case ZEND_ASSIGN_DIM: { - zval **container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + zval **container = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -33969,14 +37929,14 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_UNUSED(int (*binar zval *dim = NULL; zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_UNUSED, BP_VAR_RW TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } } break; default: value = NULL; - var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); /* do nothing */ break; } @@ -34098,7 +38058,7 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_UNUSED(int type, ulong hash_value; SAVE_OPLINE(); - varname = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV != IS_CONST && UNEXPECTED(Z_TYPE_P(varname) != IS_STRING)) { ZVAL_COPY_VALUE(&tmp_varname, varname); @@ -34238,7 +38198,7 @@ static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE { USE_OPLINE - return zend_fetch_var_address_helper_SPEC_CV_UNUSED(ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + return zend_fetch_var_address_helper_SPEC_CV_UNUSED(ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))?BP_VAR_W:BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -34258,7 +38218,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HA zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -34291,7 +38251,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_H zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -34314,8 +38274,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNUSED_HANDLER(ZEND_OP SAVE_OPLINE(); - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { - container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } @@ -34327,7 +38287,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNUSED_HANDLER(ZEND_OP if (IS_UNUSED == IS_UNUSED) { zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); } - container = _get_zval_ptr_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, NULL, IS_UNUSED, BP_VAR_R TSRMLS_CC); } @@ -34343,7 +38303,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAN zval **object_ptr; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -34355,7 +38315,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAN if (0) { MAKE_REAL_ZVAL_PTR(property_name); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_DIM, ((IS_UNUSED == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_UNUSED == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (0) { zval_ptr_dtor(&property_name); } else { @@ -34369,8 +38329,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAN zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), object_ptr, dim, IS_UNUSED, BP_VAR_W TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); if (UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) { if (RETURN_VALUE_USED(opline)) { @@ -34424,7 +38384,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER(ZEND_OPC SAVE_OPLINE(); if ((IS_CV == IS_VAR || IS_CV == IS_CV) && opline->extended_value) { - zval **expr_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + zval **expr_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); @@ -34433,7 +38393,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER(ZEND_OPC expr_ptr = *expr_ptr_ptr; Z_ADDREF_P(expr_ptr); } else { - expr_ptr=_get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + expr_ptr=_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (0) { /* temporary variable */ zval *new_expr; @@ -34540,7 +38500,7 @@ static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAND ZEND_VM_NEXT_OPCODE(); } - varname = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, varname); @@ -34616,7 +38576,7 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPC } else { HashTable *target_symbol_table; - zval tmp, *varname = _get_zval_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC); + zval tmp, *varname = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) { ZVAL_COPY_VALUE(&tmp, varname); @@ -34677,6 +38637,159 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPC ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_CV != IS_UNUSED) { + + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + + if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_CV == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_UNUSED != IS_UNUSED) { + + zval *key = NULL; + + /* Consts, temporary variables and references need copying */ + if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL ZEND_ADD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -34684,8 +38797,8 @@ static int ZEND_FASTCALL ZEND_ADD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_add_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -34699,8 +38812,8 @@ static int ZEND_FASTCALL ZEND_SUB_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_sub_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -34714,8 +38827,8 @@ static int ZEND_FASTCALL ZEND_MUL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_mul_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -34729,8 +38842,8 @@ static int ZEND_FASTCALL ZEND_DIV_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_div_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -34744,8 +38857,8 @@ static int ZEND_FASTCALL ZEND_MOD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); fast_mod_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -34759,8 +38872,8 @@ static int ZEND_FASTCALL ZEND_SL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_left_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -34774,8 +38887,8 @@ static int ZEND_FASTCALL ZEND_SR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) SAVE_OPLINE(); shift_right_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -34789,8 +38902,8 @@ static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); concat_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -34804,8 +38917,8 @@ static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); is_identical_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -34820,8 +38933,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_H SAVE_OPLINE(); is_identical_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); Z_LVAL_P(result) = !Z_LVAL_P(result); @@ -34837,8 +38950,8 @@ static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); ZVAL_BOOL(result, fast_equal_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC)); CHECK_EXCEPTION(); @@ -34853,8 +38966,8 @@ static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDL SAVE_OPLINE(); ZVAL_BOOL(result, fast_not_equal_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC)); CHECK_EXCEPTION(); @@ -34869,8 +38982,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC)); CHECK_EXCEPTION(); @@ -34885,8 +38998,8 @@ static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CV_CV_HANDLER(ZEND_OPCOD SAVE_OPLINE(); ZVAL_BOOL(result, fast_is_smaller_or_equal_function(result, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC)); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC)); CHECK_EXCEPTION(); @@ -34900,8 +39013,8 @@ static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS SAVE_OPLINE(); bitwise_or_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -34915,8 +39028,8 @@ static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); bitwise_and_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -34930,8 +39043,8 @@ static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG SAVE_OPLINE(); bitwise_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -34945,8 +39058,8 @@ static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_A SAVE_OPLINE(); boolean_xor_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); @@ -34957,10 +39070,10 @@ static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CV(int (*binar { USE_OPLINE zend_free_op free_op_data1; - zval **object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + zval **object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); zval *object; - zval *property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); - zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); + zval *property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + zval *value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); int have_get_ptr = 0; if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -35077,7 +39190,7 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CV(int (*binary_op return zend_binary_assign_op_obj_helper_SPEC_CV_CV(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); break; case ZEND_ASSIGN_DIM: { - zval **container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + zval **container = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -35087,17 +39200,17 @@ static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CV(int (*binary_op } return zend_binary_assign_op_obj_helper_SPEC_CV_CV(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { - zval *dim = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + zval *dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), container, dim, IS_CV, BP_VAR_RW TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + var_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); } } break; default: - value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); - var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + var_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); /* do nothing */ break; } @@ -35219,8 +39332,8 @@ static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CV(incdec_t inc int have_get_ptr = 0; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); - property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); retval = &EX_T(opline->result.var).var.ptr; if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -35323,8 +39436,8 @@ static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CV(incdec_t in int have_get_ptr = 0; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); - property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); retval = &EX_T(opline->result.var).tmp_var; if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { @@ -35427,10 +39540,19 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLE EX_T(opline->op1.var).var.ptr_ptr) { PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); } - container = _get_zval_ptr_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_R TSRMLS_CC); + + if (IS_CV == IS_TMP_VAR || IS_CV == IS_CONST) { + zval *container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), &container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_R TSRMLS_CC); + + + } else { + container = _get_zval_ptr_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_R TSRMLS_CC); + } + CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } @@ -35442,12 +39564,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLE zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_W TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_W TSRMLS_CC); if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); @@ -35475,12 +39597,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDL zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_RW TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_RW TSRMLS_CC); if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); @@ -35497,8 +39619,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDL zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_IS TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_IS TSRMLS_CC); CHECK_EXCEPTION(); @@ -35513,12 +39635,12 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE SAVE_OPLINE(); - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { - container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_W TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_W TSRMLS_CC); if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); } @@ -35526,8 +39648,8 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE if (IS_CV == IS_UNUSED) { zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); } - container = _get_zval_ptr_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); - zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_R TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + zend_fetch_dimension_address_read(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_R TSRMLS_CC); } @@ -35542,7 +39664,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HA zval **container; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_CV) { if (container != &EG(uninitialized_zval_ptr)) { @@ -35552,7 +39674,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HA if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_UNSET TSRMLS_CC); + zend_fetch_dimension_address(&EX_T(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV, BP_VAR_UNSET TSRMLS_CC); if (IS_CV == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) { EXTRACT_ZVAL_PTR(&EX_T(opline->result.var)); @@ -35560,6 +39682,7 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HA if (UNEXPECTED(EX_T(opline->result.var).var.ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot unset string offsets"); + ZEND_VM_NEXT_OPCODE(); } else { zend_free_op free_res; zval **retval_ptr = EX_T(opline->result.var).var.ptr_ptr; @@ -35584,8 +39707,8 @@ static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CV_CV(ZEND zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); - offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -35630,7 +39753,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLE zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_CV == IS_VAR && (opline->extended_value & ZEND_FETCH_ADD_LOCK)) { PZVAL_LOCK(*EX_T(opline->op1.var).var.ptr_ptr); @@ -35640,7 +39763,7 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLE if (0) { MAKE_REAL_ZVAL_PTR(property); } - container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -35678,8 +39801,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDL zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); - container = _get_zval_ptr_ptr_cv_BP_VAR_RW(EX_CVs(), opline->op1.var TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property); @@ -35710,8 +39833,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDL zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC); - offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + container = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { @@ -35746,15 +39869,15 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE { USE_OPLINE - if (ARG_SHOULD_BE_SENT_BY_REF(EX(fbc), (opline->extended_value & ZEND_FETCH_ARG_MASK))) { + if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->fbc, (opline->extended_value & ZEND_FETCH_ARG_MASK))) { /* Behave like FETCH_OBJ_W */ zend_free_op free_op1; zval *property; zval **container; SAVE_OPLINE(); - property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); - container = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property); @@ -35787,8 +39910,8 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HA zval *property; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC); - property = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); + property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_CV == IS_CV) { if (container != &EG(uninitialized_zval_ptr)) { @@ -35829,8 +39952,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER zval *property_name; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); - property_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property_name); @@ -35838,7 +39961,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_OBJ, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_OBJ, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (0) { zval_ptr_dtor(&property_name); } else { @@ -35858,19 +39981,19 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER zval **object_ptr; SAVE_OPLINE(); - object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + object_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); } if (Z_TYPE_PP(object_ptr) == IS_OBJECT) { - zval *property_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + zval *property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (0) { MAKE_REAL_ZVAL_PTR(property_name); } - zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), ZEND_ASSIGN_DIM, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); + zend_assign_to_object(RETURN_VALUE_USED(opline)?&EX_T(opline->result.var).var.ptr:NULL, object_ptr, property_name, (opline+1)->op1_type, &(opline+1)->op1, execute_data, ZEND_ASSIGN_DIM, ((IS_CV == IS_CONST) ? opline->op2.literal : NULL) TSRMLS_CC); if (0) { zval_ptr_dtor(&property_name); } else { @@ -35879,13 +40002,13 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER } else { zend_free_op free_op_data1, free_op_data2; zval *value; - zval *dim = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + zval *dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); zval **variable_ptr_ptr; zend_fetch_dimension_address(&EX_T((opline+1)->op2.var), object_ptr, dim, IS_CV, BP_VAR_W TSRMLS_CC); - value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, EX_Ts(), &free_op_data1, BP_VAR_R); - variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, EX_Ts(), &free_op_data2 TSRMLS_CC); + value = get_zval_ptr((opline+1)->op1_type, &(opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + variable_ptr_ptr = _get_zval_ptr_ptr_var((opline+1)->op2.var, execute_data, &free_op_data2 TSRMLS_CC); if (UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T((opline+1)->op2.var), value, (opline+1)->op1_type TSRMLS_CC)) { if (RETURN_VALUE_USED(opline)) { @@ -35939,8 +40062,8 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG zval **variable_ptr_ptr; SAVE_OPLINE(); - value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); - variable_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + variable_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL)) { if (zend_assign_to_string_offset(&EX_T(opline->op1.var), value, IS_CV TSRMLS_CC)) { @@ -35992,7 +40115,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER zval **value_ptr_ptr; SAVE_OPLINE(); - value_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op2.var TSRMLS_CC); + value_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op2.var TSRMLS_CC); if (IS_CV == IS_VAR && value_ptr_ptr && @@ -36015,7 +40138,7 @@ static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object"); } - variable_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + variable_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if ((IS_CV == IS_VAR && UNEXPECTED(value_ptr_ptr == NULL)) || (IS_CV == IS_VAR && UNEXPECTED(variable_ptr_ptr == NULL))) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects"); @@ -36043,11 +40166,11 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_H char *function_name_strval; int function_name_strlen; + call_slot *call = EX(call_slots) + opline->result.num; SAVE_OPLINE(); - zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(called_scope)); - function_name = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_CV != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { @@ -36057,49 +40180,51 @@ static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_H function_name_strval = Z_STRVAL_P(function_name); function_name_strlen = Z_STRLEN_P(function_name); - EX(object) = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + call->object = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); - if (EXPECTED(EX(object) != NULL) && - EXPECTED(Z_TYPE_P(EX(object)) == IS_OBJECT)) { - EX(called_scope) = Z_OBJCE_P(EX(object)); + if (EXPECTED(call->object != NULL) && + EXPECTED(Z_TYPE_P(call->object) == IS_OBJECT)) { + call->called_scope = Z_OBJCE_P(call->object); if (IS_CV != IS_CONST || - (EX(fbc) = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope))) == NULL) { - zval *object = EX(object); + (call->fbc = CACHED_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope)) == NULL) { + zval *object = call->object; - if (UNEXPECTED(Z_OBJ_HT_P(EX(object))->get_method == NULL)) { + if (UNEXPECTED(Z_OBJ_HT_P(call->object)->get_method == NULL)) { zend_error_noreturn(E_ERROR, "Object does not support method calls"); } /* First, locate the function. */ - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); - if (UNEXPECTED(EX(fbc) == NULL)) { - zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval); + call->fbc = Z_OBJ_HT_P(call->object)->get_method(&call->object, function_name_strval, function_name_strlen, ((IS_CV == IS_CONST) ? (opline->op2.literal + 1) : NULL) TSRMLS_CC); + if (UNEXPECTED(call->fbc == NULL)) { + zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(call->object), function_name_strval); } if (IS_CV == IS_CONST && - EXPECTED(EX(fbc)->type <= ZEND_USER_FUNCTION) && - EXPECTED((EX(fbc)->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && - EXPECTED(EX(object) == object)) { - CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, EX(called_scope), EX(fbc)); + EXPECTED(call->fbc->type <= ZEND_USER_FUNCTION) && + EXPECTED((call->fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) && + EXPECTED(call->object == object)) { + CACHE_POLYMORPHIC_PTR(opline->op2.literal->cache_slot, call->called_scope, call->fbc); } } } else { zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); } - if ((EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) != 0) { - EX(object) = NULL; + if ((call->fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) { + call->object = NULL; } else { - if (!PZVAL_IS_REF(EX(object))) { - Z_ADDREF_P(EX(object)); /* For $this pointer */ + if (!PZVAL_IS_REF(call->object)) { + Z_ADDREF_P(call->object); /* For $this pointer */ } else { zval *this_ptr; ALLOC_ZVAL(this_ptr); - INIT_PZVAL_COPY(this_ptr, EX(object)); + INIT_PZVAL_COPY(this_ptr, call->object); zval_copy_ctor(this_ptr); - EX(object) = this_ptr; + call->object = this_ptr; } } + call->is_ctor_call = 0; + EX(call) = call; CHECK_EXCEPTION(); @@ -36116,8 +40241,8 @@ static int ZEND_FASTCALL ZEND_CASE_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) PZVAL_LOCK(EX_T(opline->op1.var).var.ptr); } is_equal_function(&EX_T(opline->result.var).tmp_var, - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC), - _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC) TSRMLS_CC); + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC), + _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC) TSRMLS_CC); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); @@ -36131,7 +40256,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_ SAVE_OPLINE(); if ((IS_CV == IS_VAR || IS_CV == IS_CV) && opline->extended_value) { - zval **expr_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC); + zval **expr_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr_ptr == NULL)) { zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets"); @@ -36140,7 +40265,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_ expr_ptr = *expr_ptr_ptr; Z_ADDREF_P(expr_ptr); } else { - expr_ptr=_get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC); + expr_ptr=_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); if (0) { /* temporary variable */ zval *new_expr; @@ -36161,7 +40286,7 @@ static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_ if (IS_CV != IS_UNUSED) { - zval *offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); ulong hval; switch (Z_TYPE_P(offset)) { @@ -36232,11 +40357,11 @@ static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ ulong hval; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_CV && container != &EG(uninitialized_zval_ptr)) { SEPARATE_ZVAL_IF_NOT_REF(container); } - offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_CV != IS_VAR || container) { switch (Z_TYPE_PP(container)) { @@ -36330,8 +40455,8 @@ static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(EX_CVs(), opline->op1.var TSRMLS_CC); - offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (IS_CV != IS_VAR || container) { if (IS_CV == IS_CV && container != &EG(uninitialized_zval_ptr)) { @@ -36373,9 +40498,9 @@ static int ZEND_FASTCALL zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_CV(int zval *offset; SAVE_OPLINE(); - container = _get_zval_ptr_ptr_cv_BP_VAR_IS(EX_CVs(), opline->op1.var TSRMLS_CC); + container = _get_zval_ptr_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var TSRMLS_CC); - offset = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op2.var TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); if (Z_TYPE_PP(container) == IS_ARRAY && !prop_dim) { HashTable *ht; @@ -36514,9 +40639,163 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CV_HANDLER(ZEND_OP return zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_CV(1, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) { + zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator"); + } + + /* Destroy the previously yielded value */ + if (generator->value) { + zval_ptr_dtor(&generator->value); + } + + /* Destroy the previously yielded key */ + if (generator->key) { + zval_ptr_dtor(&generator->key); + } + + /* Set the new yielded value */ + if (IS_CV != IS_UNUSED) { + + + if (EX(op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + /* Constants and temporary variables aren't yieldable by reference, + * but we still allow them with a notice. */ + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + zval *value, *copy; + + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + zval **value_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + + if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) { + zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference"); + } + + /* If a function call result is yielded and the function did + * not return by reference we throw a notice. */ + if (IS_CV == IS_VAR && !Z_ISREF_PP(value_ptr) + && !(opline->extended_value == ZEND_RETURNS_FUNCTION + && EX_T(opline->op1.var).var.fcall_returned_reference) + && EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) { + zend_error(E_NOTICE, "Only variable references should be yielded by reference"); + + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } else { + SEPARATE_ZVAL_TO_MAKE_IS_REF(value_ptr); + Z_ADDREF_PP(value_ptr); + generator->value = *value_ptr; + } + + } + } else { + zval *value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR + || (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->value = copy; + } else { + Z_ADDREF_P(value); + generator->value = value; + } + + } + } else { + /* If no value was specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator->value = &EG(uninitialized_zval); + } + + /* Set the new yielded key */ + if (IS_CV != IS_UNUSED) { + + zval *key = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + + /* Consts, temporary variables and references need copying */ + if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR + || (PZVAL_IS_REF(key) && Z_REFCOUNT_P(key) > 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, key); + + /* Temporary variables don't need ctor copying */ + if (!0) { + zval_copy_ctor(copy); + } + + generator->key = copy; + } else { + Z_ADDREF_P(key); + generator->key = key; + } + + if (Z_TYPE_P(generator->key) == IS_LONG + && Z_LVAL_P(generator->key) > generator->largest_used_integer_key + ) { + generator->largest_used_integer_key = Z_LVAL_P(generator->key); + } + + } else { + /* If no key was specified we use auto-increment keys */ + generator->largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator->key); + ZVAL_LONG(generator->key, generator->largest_used_integer_key); + } + + /* If a value is sent it should go into the result var */ + generator->send_target = &EX_T(opline->result.var); + + /* Initialize the sent value to NULL */ + EX_T(opline->result.var).tmp_var = EG(uninitialized_zval); + + /* We increment to the next op, so we are at the correct position when the + * generator is resumed. */ + ZEND_VM_INC_OPCODE(); + + /* The GOTO VM uses a local opline variable. We need to set the opline + * variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + + ZEND_VM_RETURN(); +} + static int ZEND_FASTCALL ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { zend_error_noreturn(E_ERROR, "Invalid opcode %d/%d/%d.", OPLINE->opcode, OPLINE->op1_type, OPLINE->op2_type); + ZEND_VM_NEXT_OPCODE(); /* Never reached */ } @@ -38548,16 +42827,16 @@ void zend_init_opcodes_handlers(void) ZEND_FETCH_R_SPEC_CV_VAR_HANDLER, ZEND_FETCH_R_SPEC_CV_UNUSED_HANDLER, ZEND_NULL_HANDLER, + ZEND_FETCH_DIM_R_SPEC_CONST_CONST_HANDLER, + ZEND_FETCH_DIM_R_SPEC_CONST_TMP_HANDLER, + ZEND_FETCH_DIM_R_SPEC_CONST_VAR_HANDLER, ZEND_NULL_HANDLER, + ZEND_FETCH_DIM_R_SPEC_CONST_CV_HANDLER, + ZEND_FETCH_DIM_R_SPEC_TMP_CONST_HANDLER, + ZEND_FETCH_DIM_R_SPEC_TMP_TMP_HANDLER, + ZEND_FETCH_DIM_R_SPEC_TMP_VAR_HANDLER, ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, + ZEND_FETCH_DIM_R_SPEC_TMP_CV_HANDLER, ZEND_FETCH_DIM_R_SPEC_VAR_CONST_HANDLER, ZEND_FETCH_DIM_R_SPEC_VAR_TMP_HANDLER, ZEND_FETCH_DIM_R_SPEC_VAR_VAR_HANDLER, @@ -40498,6 +44777,131 @@ void zend_init_opcodes_handlers(void) ZEND_JMP_SET_VAR_SPEC_CV_HANDLER, ZEND_JMP_SET_VAR_SPEC_CV_HANDLER, ZEND_JMP_SET_VAR_SPEC_CV_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_YIELD_SPEC_CONST_CONST_HANDLER, + ZEND_YIELD_SPEC_CONST_TMP_HANDLER, + ZEND_YIELD_SPEC_CONST_VAR_HANDLER, + ZEND_YIELD_SPEC_CONST_UNUSED_HANDLER, + ZEND_YIELD_SPEC_CONST_CV_HANDLER, + ZEND_YIELD_SPEC_TMP_CONST_HANDLER, + ZEND_YIELD_SPEC_TMP_TMP_HANDLER, + ZEND_YIELD_SPEC_TMP_VAR_HANDLER, + ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER, + ZEND_YIELD_SPEC_TMP_CV_HANDLER, + ZEND_YIELD_SPEC_VAR_CONST_HANDLER, + ZEND_YIELD_SPEC_VAR_TMP_HANDLER, + ZEND_YIELD_SPEC_VAR_VAR_HANDLER, + ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER, + ZEND_YIELD_SPEC_VAR_CV_HANDLER, + ZEND_YIELD_SPEC_UNUSED_CONST_HANDLER, + ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER, + ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER, + ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDLER, + ZEND_YIELD_SPEC_UNUSED_CV_HANDLER, + ZEND_YIELD_SPEC_CV_CONST_HANDLER, + ZEND_YIELD_SPEC_CV_TMP_HANDLER, + ZEND_YIELD_SPEC_CV_VAR_HANDLER, + ZEND_YIELD_SPEC_CV_UNUSED_HANDLER, + ZEND_YIELD_SPEC_CV_CV_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, ZEND_NULL_HANDLER }; zend_opcode_handlers = (opcode_handler_t*)labels; diff --git a/Zend/zend_vm_execute.skl b/Zend/zend_vm_execute.skl index 6d1b2e70e7..13fd88e2d8 100644 --- a/Zend/zend_vm_execute.skl +++ b/Zend/zend_vm_execute.skl @@ -1,67 +1,25 @@ {%DEFINES%} -ZEND_API void {%EXECUTOR_NAME%}(zend_op_array *op_array TSRMLS_DC) +ZEND_API void {%EXECUTOR_NAME%}_ex(zend_execute_data *execute_data TSRMLS_DC) { DCL_OPLINE - zend_execute_data *execute_data; - zend_bool nested = 0; + zend_bool original_in_execution; + {%HELPER_VARS%} - {%EXECUTION_STATUS%} {%INTERNAL_LABELS%} - if (EG(exception)) { - return; - } - + original_in_execution = EG(in_execution); EG(in_execution) = 1; + if (0) { zend_vm_enter: - /* Initialize execute_data */ - execute_data = (zend_execute_data *)zend_vm_stack_alloc( - ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data)) + - ZEND_MM_ALIGNED_SIZE(sizeof(zval**) * op_array->last_var * (EG(active_symbol_table) ? 1 : 2)) + - ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * op_array->T TSRMLS_CC); - - EX(CVs) = (zval***)((char*)execute_data + ZEND_MM_ALIGNED_SIZE(sizeof(zend_execute_data))); - memset(EX(CVs), 0, sizeof(zval**) * op_array->last_var); - EX(Ts) = (temp_variable *)(((char*)EX(CVs)) + ZEND_MM_ALIGNED_SIZE(sizeof(zval**) * op_array->last_var * (EG(active_symbol_table) ? 1 : 2))); - EX(fbc) = NULL; - EX(called_scope) = NULL; - EX(object) = NULL; - EX(old_error_reporting) = NULL; - EX(op_array) = op_array; - EX(symbol_table) = EG(active_symbol_table); - EX(prev_execute_data) = EG(current_execute_data); - EG(current_execute_data) = execute_data; - EX(nested) = nested; - nested = 1; - - LOAD_REGS(); - - if (!op_array->run_time_cache && op_array->last_cache_slot) { - op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*)); + execute_data = i_create_execute_data_from_op_array(EG(active_op_array), 1 TSRMLS_CC); } - if (op_array->this_var != -1 && EG(This)) { - Z_ADDREF_P(EG(This)); /* For $this pointer */ - if (!EG(active_symbol_table)) { - EX_CV(op_array->this_var) = (zval**)EX_CVs() + (op_array->last_var + op_array->this_var); - *EX_CV(op_array->this_var) = EG(This); - } else { - if (zend_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), (void**)&EX_CV(op_array->this_var))==FAILURE) { - Z_DELREF_P(EG(This)); - } - } - } - - EX(opline) = UNEXPECTED((op_array->fn_flags & ZEND_ACC_INTERACTIVE) != 0) && EG(start_op) ? EG(start_op) : op_array->opcodes; - EG(opline_ptr) = &EX(opline); + LOAD_REGS(); LOAD_OPLINE(); - EX(function_state).function = (zend_function *) op_array; - EX(function_state).arguments = NULL; - while (1) { {%ZEND_VM_CONTINUE_LABEL%} #ifdef ZEND_WIN32 @@ -78,6 +36,14 @@ zend_vm_enter: zend_error_noreturn(E_ERROR, "Arrived at end of main loop which shouldn't happen"); } +ZEND_API void zend_{%EXECUTOR_NAME%}(zend_op_array *op_array TSRMLS_DC) +{ + if (EG(exception)) { + return; + } + zend_{%EXECUTOR_NAME%}_ex(i_create_execute_data_from_op_array(op_array, 0 TSRMLS_CC) TSRMLS_CC); +} + {%EXTERNAL_EXECUTOR%} void {%INITIALIZER_NAME%}(void) diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php index 97dc0e8bed..63d0cf73f0 100644 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -118,75 +118,75 @@ $op2_free = array( ); $op1_get_zval_ptr = array( - "ANY" => "get_zval_ptr(opline->op1_type, &opline->op1, EX_Ts(), &free_op1, \\1)", - "TMP" => "_get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC)", - "VAR" => "_get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC)", + "ANY" => "get_zval_ptr(opline->op1_type, &opline->op1, execute_data, &free_op1, \\1)", + "TMP" => "_get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC)", + "VAR" => "_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC)", "CONST" => "opline->op1.zv", "UNUSED" => "NULL", - "CV" => "_get_zval_ptr_cv_\\1(EX_CVs(), opline->op1.var TSRMLS_CC)", + "CV" => "_get_zval_ptr_cv_\\1(execute_data, opline->op1.var TSRMLS_CC)", ); $op2_get_zval_ptr = array( - "ANY" => "get_zval_ptr(opline->op2_type, &opline->op2, EX_Ts(), &free_op2, \\1)", - "TMP" => "_get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC)", - "VAR" => "_get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC)", + "ANY" => "get_zval_ptr(opline->op2_type, &opline->op2, execute_data, &free_op2, \\1)", + "TMP" => "_get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC)", + "VAR" => "_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC)", "CONST" => "opline->op2.zv", "UNUSED" => "NULL", - "CV" => "_get_zval_ptr_cv_\\1(EX_CVs(), opline->op2.var TSRMLS_CC)", + "CV" => "_get_zval_ptr_cv_\\1(execute_data, opline->op2.var TSRMLS_CC)", ); $op1_get_zval_ptr_ptr = array( - "ANY" => "get_zval_ptr_ptr(opline->op1_type, &opline->op1, EX_Ts(), &free_op1, \\1)", + "ANY" => "get_zval_ptr_ptr(opline->op1_type, &opline->op1, execute_data, &free_op1, \\1)", "TMP" => "NULL", - "VAR" => "_get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC)", + "VAR" => "_get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC)", "CONST" => "NULL", "UNUSED" => "NULL", - "CV" => "_get_zval_ptr_ptr_cv_\\1(EX_CVs(), opline->op1.var TSRMLS_CC)", + "CV" => "_get_zval_ptr_ptr_cv_\\1(execute_data, opline->op1.var TSRMLS_CC)", ); $op2_get_zval_ptr_ptr = array( - "ANY" => "get_zval_ptr_ptr(opline->op2_type, &opline->op2, EX_Ts(), &free_op2, \\1)", + "ANY" => "get_zval_ptr_ptr(opline->op2_type, &opline->op2, execute_data, &free_op2, \\1)", "TMP" => "NULL", - "VAR" => "_get_zval_ptr_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC)", + "VAR" => "_get_zval_ptr_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC)", "CONST" => "NULL", "UNUSED" => "NULL", - "CV" => "_get_zval_ptr_ptr_cv_\\1(EX_CVs(), opline->op2.var TSRMLS_CC)", + "CV" => "_get_zval_ptr_ptr_cv_\\1(execute_data, opline->op2.var TSRMLS_CC)", ); $op1_get_obj_zval_ptr = array( - "ANY" => "get_obj_zval_ptr(opline->op1_type, &opline->op1, EX_Ts(), &free_op1, \\1)", - "TMP" => "_get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC)", - "VAR" => "_get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC)", + "ANY" => "get_obj_zval_ptr(opline->op1_type, &opline->op1, execute_data, &free_op1, \\1)", + "TMP" => "_get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC)", + "VAR" => "_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC)", "CONST" => "opline->op1.zv", "UNUSED" => "_get_obj_zval_ptr_unused(TSRMLS_C)", - "CV" => "_get_zval_ptr_cv_\\1(EX_CVs(), opline->op1.var TSRMLS_CC)", + "CV" => "_get_zval_ptr_cv_\\1(execute_data, opline->op1.var TSRMLS_CC)", ); $op2_get_obj_zval_ptr = array( - "ANY" => "get_obj_zval_ptr(opline->op2_type, &opline->op2, EX_Ts(), &free_op2, \\1)", - "TMP" => "_get_zval_ptr_tmp(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC)", - "VAR" => "_get_zval_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC)", + "ANY" => "get_obj_zval_ptr(opline->op2_type, &opline->op2, execute_data, &free_op2, \\1)", + "TMP" => "_get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC)", + "VAR" => "_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC)", "CONST" => "opline->op2.zv", "UNUSED" => "_get_obj_zval_ptr_unused(TSRMLS_C)", - "CV" => "_get_zval_ptr_cv_\\1(EX_CVs(), opline->op2.var TSRMLS_CC)", + "CV" => "_get_zval_ptr_cv_\\1(execute_data, opline->op2.var TSRMLS_CC)", ); $op1_get_obj_zval_ptr_ptr = array( - "ANY" => "get_obj_zval_ptr_ptr(opline->op1_type, &opline->op1, EX_Ts(), &free_op1, \\1)", + "ANY" => "get_obj_zval_ptr_ptr(opline->op1_type, &opline->op1, execute_data, &free_op1, \\1)", "TMP" => "NULL", - "VAR" => "_get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC)", + "VAR" => "_get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC)", "CONST" => "NULL", "UNUSED" => "_get_obj_zval_ptr_ptr_unused(TSRMLS_C)", - "CV" => "_get_zval_ptr_ptr_cv_\\1(EX_CVs(), opline->op1.var TSRMLS_CC)", + "CV" => "_get_zval_ptr_ptr_cv_\\1(execute_data, opline->op1.var TSRMLS_CC)", ); $op2_get_obj_zval_ptr_ptr = array( - "ANY" => "get_obj_zval_ptr_ptr(opline->op2_type, &opline->op2, EX_Ts(), &free_op2, \\1)", + "ANY" => "get_obj_zval_ptr_ptr(opline->op2_type, &opline->op2, execute_data, &free_op2, \\1)", "TMP" => "NULL", - "VAR" => "_get_zval_ptr_ptr_var(opline->op2.var, EX_Ts(), &free_op2 TSRMLS_CC)", + "VAR" => "_get_zval_ptr_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC)", "CONST" => "NULL", "UNUSED" => "_get_obj_zval_ptr_ptr_unused(TSRMLS_C)", - "CV" => "_get_zval_ptr_ptr_cv_\\1(EX_CVs(), opline->op2.var TSRMLS_CC)", + "CV" => "_get_zval_ptr_ptr_cv_\\1(execute_data, opline->op2.var TSRMLS_CC)", ); $op1_is_tmp_free = array( @@ -387,52 +387,67 @@ function gen_code($f, $spec, $kind, $export, $code, $op1, $op2, $name) { // Updating code according to selected threading model switch($kind) { case ZEND_VM_KIND_CALL: - $code = preg_replace( + $code = preg_replace_callback( array( "/EXECUTE_DATA/m", "/ZEND_VM_DISPATCH_TO_HANDLER\(\s*([A-Z_]*)\s*\)/m", - "/ZEND_VM_DISPATCH_TO_HELPER\(\s*([A-Za-z_]*)\s*\)/me", - "/ZEND_VM_DISPATCH_TO_HELPER_EX\(\s*([A-Za-z_]*)\s*,\s*[A-Za-z_]*\s*,\s*(.*)\s*\);/me", - ), - array( - "execute_data", - "return \\1".($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2]."_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)", - "'return '.helper_name('\\1',$spec,'$op1','$op2').'(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)'", - "'return '.helper_name('\\1',$spec,'$op1','$op2').'(\\2, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);'", + "/ZEND_VM_DISPATCH_TO_HELPER\(\s*([A-Za-z_]*)\s*\)/m", + "/ZEND_VM_DISPATCH_TO_HELPER_EX\(\s*([A-Za-z_]*)\s*,\s*[A-Za-z_]*\s*,\s*(.*)\s*\);/m", ), + function($matches) use ($spec, $prefix, $op1, $op2) { + if (strncasecmp($matches[0], "EXECUTE_DATA", strlen("EXECUTE_DATA")) == 0) { + return "execute_data"; + } else if (strncasecmp($matches[0], "ZEND_VM_DISPATCH_TO_HANDLER", strlen("ZEND_VM_DISPATCH_TO_HANDLER")) == 0) { + return "return " . $matches[1] . ($spec?"_SPEC":"") . $prefix[$op1] . $prefix[$op2] . "_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)"; + } else if (strncasecmp($matches[0], "ZEND_VM_DISPATCH_TO_HELPER_EX", strlen("ZEND_VM_DISPATCH_TO_HELPER_EX")) == 0) { + return "return " . helper_name($matches[1], $spec, $op1, $op2) . "(" . $matches[2]. ", ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);"; + } else { + return "return " . helper_name($matches[1], $spec, $op1, $op2) . "(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)"; + } + }, $code); break; case ZEND_VM_KIND_SWITCH: - $code = preg_replace( + $code = preg_replace_callback( array( "/EXECUTE_DATA/m", "/ZEND_VM_DISPATCH_TO_HANDLER\(\s*([A-Z_]*)\s*\)/m", - "/ZEND_VM_DISPATCH_TO_HELPER\(\s*([A-Za-z_]*)\s*\)/me", - "/ZEND_VM_DISPATCH_TO_HELPER_EX\(\s*([A-Za-z_]*)\s*,\s*([A-Za-z_]*)\s*,\s*(.*)\s*\);/me", - ), - array( - "execute_data", - "goto \\1".($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2]."_LABEL", - "'goto '.helper_name('\\1',$spec,'$op1','$op2')", - "'\\2 = \\3; goto '.helper_name('\\1',$spec,'$op1','$op2').';'", + "/ZEND_VM_DISPATCH_TO_HELPER\(\s*([A-Za-z_]*)\s*\)/m", + "/ZEND_VM_DISPATCH_TO_HELPER_EX\(\s*([A-Za-z_]*)\s*,\s*([A-Za-z_]*)\s*,\s*(.*)\s*\);/m", ), - $code); + function($matches) use ($spec, $prefix, $op1, $op2) { + if (strncasecmp($matches[0], "EXECUTE_DATA", strlen("EXECUTE_DATA")) == 0) { + return "execute_data"; + } else if (strncasecmp($matches[0], "ZEND_VM_DISPATCH_TO_HANDLER", strlen("ZEND_VM_DISPATCH_TO_HANDLER")) == 0) { + return "goto " . $matches[1] . ($spec?"_SPEC":"") . $prefix[$op1] . $prefix[$op2] . "_LABEL"; + } else if (strncasecmp($matches[0], "ZEND_VM_DISPATCH_TO_HELPER_EX", strlen("ZEND_VM_DISPATCH_TO_HELPER_EX")) == 0) { + return $matches[2] . " = " . $matches[3] . "; goto " . helper_name($matches[1], $spec, $op1, $op2) . ";"; + } else { + return "goto " . helper_name($matches[1], $spec, $op1, $op2); + } + }, + $code); break; case ZEND_VM_KIND_GOTO: - $code = preg_replace( + $code = preg_replace_callback( array( "/EXECUTE_DATA/m", "/ZEND_VM_DISPATCH_TO_HANDLER\(\s*([A-Z_]*)\s*\)/m", - "/ZEND_VM_DISPATCH_TO_HELPER\(\s*([A-Za-z_]*)\s*\)/me", - "/ZEND_VM_DISPATCH_TO_HELPER_EX\(\s*([A-Za-z_]*)\s*,\s*([A-Za-z_]*)\s*,\s*(.*)\s*\);/me", + "/ZEND_VM_DISPATCH_TO_HELPER\(\s*([A-Za-z_]*)\s*\)/m", + "/ZEND_VM_DISPATCH_TO_HELPER_EX\(\s*([A-Za-z_]*)\s*,\s*([A-Za-z_]*)\s*,\s*(.*)\s*\);/m", ), - array( - "execute_data", - "goto \\1".($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2]."_HANDLER", - "'goto '.helper_name('\\1',$spec,'$op1','$op2')", - "'\\2 = \\3; goto '.helper_name('\\1',$spec,'$op1','$op2').';'", - ), - $code); + function($matches) use ($spec, $prefix, $op1, $op2) { + if (strncasecmp($matches[0], "EXECUTE_DATA", strlen("EXECUTE_DATA")) == 0) { + return "execute_data"; + } else if (strncasecmp($matches[0], "ZEND_VM_DISPATCH_TO_HANDLER", strlen("ZEND_VM_DISPATCH_TO_HANDLER")) == 0) { + return "goto " . $matches[1] . ($spec?"_SPEC":"") . $prefix[$op1] . $prefix[$op2] . "_HANDLER"; + } else if (strncasecmp($matches[0], "ZEND_VM_DISPATCH_TO_HELPER_EX", strlen("ZEND_VM_DISPATCH_TO_HELPER_EX")) == 0) { + return $matches[2] . " = " . $matches[3] . "; goto " . helper_name($matches[1], $spec, $op1, $op2) . ";"; + } else { + return "goto " . helper_name($matches[1], $spec, $op1, $op2); + } + }, + $code); break; } @@ -695,6 +710,7 @@ function gen_null_handler($f) { out($f,"static int ZEND_FASTCALL ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n"); out($f,"{\n"); out($f,"\tzend_error_noreturn(E_ERROR, \"Invalid opcode %d/%d/%d.\", OPLINE->opcode, OPLINE->op1_type, OPLINE->op2_type);\n"); + out($f,"\tZEND_VM_NEXT_OPCODE(); /* Never reached */\n"); out($f,"}\n\n"); } } @@ -769,10 +785,12 @@ function gen_executor_code($f, $spec, $kind, $prolog) { case ZEND_VM_KIND_SWITCH: out($f,"default:\n"); out($f,"\tzend_error_noreturn(E_ERROR, \"Invalid opcode %d/%d/%d.\", OPLINE->opcode, OPLINE->op1_type, OPLINE->op2_type);\n"); + out($f,"\tZEND_VM_NEXT_OPCODE(); /* Never reached */\n"); break; case ZEND_VM_KIND_GOTO: out($f,"ZEND_NULL_HANDLER:\n"); out($f,"\tzend_error_noreturn(E_ERROR, \"Invalid opcode %d/%d/%d.\", OPLINE->opcode, OPLINE->op1_type, OPLINE->op2_type);\n"); + out($f,"\tZEND_VM_NEXT_OPCODE(); /* Never reached */\n"); break; } } @@ -824,16 +842,6 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name, out($f,"#define ZEND_VM_LEAVE() return 3\n"); out($f,"#define ZEND_VM_DISPATCH(opcode, opline) return zend_vm_get_opcode_handler(opcode, opline)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n\n"); out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data TSRMLS_CC\n"); - out($f,"#undef EX\n"); - out($f,"#define EX(element) execute_data->element\n\n"); - out($f,"#undef EX_CV\n"); - out($f,"#define EX_CV(var) EX(CVs)[var]\n"); - out($f,"#undef EX_CVs\n"); - out($f,"#define EX_CVs() EX(CVs)\n"); - out($f,"#undef EX_T\n"); - out($f,"#define EX_T(offset) (*(temp_variable *)((char *) EX(Ts) + offset))\n"); - out($f,"#undef EX_Ts\n"); - out($f,"#define EX_Ts() EX(Ts)\n\n"); break; case ZEND_VM_KIND_SWITCH: out($f,"\n"); @@ -853,23 +861,13 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name, out($f,"#define CHECK_EXCEPTION() LOAD_OPLINE()\n"); out($f,"#define HANDLE_EXCEPTION() LOAD_OPLINE(); ZEND_VM_CONTINUE()\n"); out($f,"#define HANDLE_EXCEPTION_LEAVE() LOAD_OPLINE(); ZEND_VM_LEAVE()\n"); - out($f,"#define LOAD_REGS() do {Ts = EX(Ts); CVs = EX(CVs);} while (0)\n"); + out($f,"#define LOAD_REGS()\n"); out($f,"#define ZEND_VM_CONTINUE() goto zend_vm_continue\n"); out($f,"#define ZEND_VM_RETURN() EG(in_execution) = original_in_execution; return\n"); - out($f,"#define ZEND_VM_ENTER() op_array = EG(active_op_array); goto zend_vm_enter\n"); + out($f,"#define ZEND_VM_ENTER() goto zend_vm_enter\n"); out($f,"#define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n"); out($f,"#define ZEND_VM_DISPATCH(opcode, opline) dispatch_handler = zend_vm_get_opcode_handler(opcode, opline); goto zend_vm_dispatch;\n\n"); out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data TSRMLS_CC\n"); - out($f,"#undef EX\n"); - out($f,"#define EX(element) execute_data->element\n\n"); - out($f,"#undef EX_CV\n"); - out($f,"#define EX_CV(var) CVs[var]\n"); - out($f,"#undef EX_CVs\n"); - out($f,"#define EX_CVs() CVs\n"); - out($f,"#undef EX_T\n"); - out($f,"#define EX_T(offset) T(offset)\n"); - out($f,"#undef EX_Ts\n"); - out($f,"#define EX_Ts() Ts\n\n"); break; case ZEND_VM_KIND_GOTO: out($f,"\n"); @@ -889,23 +887,13 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name, out($f,"#define CHECK_EXCEPTION() if (UNEXPECTED(EG(exception) != NULL)) goto ZEND_HANDLE_EXCEPTION_SPEC_HANDLER\n"); out($f,"#define HANDLE_EXCEPTION() goto ZEND_HANDLE_EXCEPTION_SPEC_HANDLER\n"); out($f,"#define HANDLE_EXCEPTION_LEAVE() goto ZEND_HANDLE_EXCEPTION_SPEC_HANDLER\n"); - out($f,"#define LOAD_REGS() do {Ts = EX(Ts); CVs = EX(CVs);} while (0)\n"); + out($f,"#define LOAD_REGS()\n"); out($f,"#define ZEND_VM_CONTINUE() goto *(void**)(OPLINE->handler)\n"); out($f,"#define ZEND_VM_RETURN() EG(in_execution) = original_in_execution; return\n"); - out($f,"#define ZEND_VM_ENTER() op_array = EG(active_op_array); goto zend_vm_enter\n"); + out($f,"#define ZEND_VM_ENTER() goto zend_vm_enter\n"); out($f,"#define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n"); out($f,"#define ZEND_VM_DISPATCH(opcode, opline) goto *(void**)(zend_vm_get_opcode_handler(opcode, opline));\n\n"); out($f,"#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data TSRMLS_CC\n"); - out($f,"#undef EX\n"); - out($f,"#define EX(element) execute_data->element\n\n"); - out($f,"#undef EX_CV\n"); - out($f,"#define EX_CV(var) CVs[var]\n"); - out($f,"#undef EX_CVs\n"); - out($f,"#define EX_CVs() CVs\n"); - out($f,"#undef EX_T\n"); - out($f,"#define EX_T(offset) T(offset)\n\n"); - out($f,"#undef EX_Ts\n"); - out($f,"#define EX_Ts() Ts\n\n"); break; } break; @@ -914,8 +902,6 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name, break; case "HELPER_VARS": if ($kind != ZEND_VM_KIND_CALL) { - out($f,$m[1]."temp_variable *Ts;\n"); - out($f,$m[1]."zval ***CVs;\n"); if ($kind == ZEND_VM_KIND_SWITCH) { out($f,$m[1]."opcode_handler_t dispatch_handler;\n"); } @@ -927,19 +913,12 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name, skip_blanks($f, $m[1], $m[3]."\n"); } break; - case "EXECUTION_STATUS": - if ($kind != ZEND_VM_KIND_GOTO) { - out($f, $m[1] . "zend_bool original_in_execution = EG(in_execution);\n"); - } else { - out($f, $m[1] . "zend_bool original_in_execution = op_array? EG(in_execution) : 0;\n"); - } - break; case "INTERNAL_LABELS": if ($kind == ZEND_VM_KIND_GOTO) { // Emit array of labels of opcode handlers and code for // zend_opcode_handlers initialization $prolog = $m[1]; - out($f,$prolog."if (op_array == NULL) {\n"); + out($f,$prolog."if (execute_data == NULL) {\n"); out($f,$prolog."\tstatic const opcode_handler_t labels[] = {\n"); gen_labels($f, $spec, $kind, $prolog."\t\t"); out($f,$prolog."\t};\n"); @@ -983,10 +962,11 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name, $m[1]."\t\tEG(in_execution) = original_in_execution;\n". $m[1]."\t\treturn;\n". $m[1]."\tcase 2:\n" . - $m[1]."\t\top_array = EG(active_op_array);\n". $m[1]."\t\tgoto zend_vm_enter;\n". + $m[1]."\t\tbreak;\n" . $m[1]."\tcase 3:\n" . $m[1]."\t\texecute_data = EG(current_execute_data);\n". + $m[1]."\t\tbreak;\n" . $m[1]."\tdefault:\n". $m[1]."\t\tbreak;\n". $m[1]."}".$m[3]."\n"); @@ -1013,9 +993,9 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name, $prolog = $m[1]; if ($kind == ZEND_VM_KIND_GOTO) { // Labels are defined in the executor itself, so we call it - // with op_array NULL and it sets zend_opcode_handlers array + // with execute_data NULL and it sets zend_opcode_handlers array out($f,$prolog."TSRMLS_FETCH();\n"); - out($f,$prolog."zend_execute(NULL TSRMLS_CC);\n"); + out($f,$prolog.$executor_name."_ex(NULL TSRMLS_CC);\n"); } else { if ($old) { // Reserving space for user-defined opcodes @@ -1189,7 +1169,7 @@ function gen_vm($def, $skel) { // Generate opcode #defines (zend_vm_opcodes.h) $code_len = strlen((string)$max_opcode); - $f = fopen("zend_vm_opcodes.h", "w+") or die("ERROR: Cannot create zend_vm_opcodes.h\n"); + $f = fopen(__DIR__ . "/zend_vm_opcodes.h", "w+") or die("ERROR: Cannot create zend_vm_opcodes.h\n"); // Insert header out($f, $GLOBALS['header_text']); @@ -1203,8 +1183,8 @@ function gen_vm($def, $skel) { echo "zend_vm_opcodes.h generated successfully.\n"; // Generate zend_vm_execute.h - $f = fopen("zend_vm_execute.h", "w+") or die("ERROR: Cannot create zend_vm_execute.h\n"); - $executor_file = realpath("zend_vm_execute.h"); + $f = fopen(__DIR__ . "/zend_vm_execute.h", "w+") or die("ERROR: Cannot create zend_vm_execute.h\n"); + $executor_file = realpath(__DIR__ . "/zend_vm_execute.h"); // Insert header out($f, $GLOBALS['header_text']); @@ -1232,14 +1212,6 @@ function gen_vm($def, $skel) { // Generate un-specialized executor if (ZEND_VM_OLD_EXECUTOR) { out($f,"\n/* Old executor */\n\n"); - out($f,"#undef EX\n"); - out($f,"#define EX(element) execute_data.element\n\n"); - out($f,"#undef EX_CV\n"); - out($f,"#define EX_CV(var) EX(CVs)[var]\n"); - out($f,"#undef EX_CVs\n"); - out($f,"#define EX_CVs() EX(CVs)\n"); - out($f,"#undef EX_T\n"); - out($f,"#define EX_T(offset) (*(temp_variable *)((char *) EX(Ts) + offset))\n\n"); out($f,"#undef ZEND_VM_CONTINUE\n\n"); out($f,"#undef ZEND_VM_RETURN\n\n"); out($f,"#undef ZEND_VM_ENTER\n\n"); @@ -1312,14 +1284,6 @@ function gen_vm($def, $skel) { out($f,"#define CHECK_EXCEPTION() LOAD_OPLINE()\n"); out($f,"#define HANDLE_EXCEPTION() LOAD_OPLINE(); ZEND_VM_CONTINUE()\n"); out($f,"#define HANDLE_EXCEPTION_LEAVE() LOAD_OPLINE(); ZEND_VM_LEAVE()\n"); - out($f,"#undef EX\n"); - out($f,"#define EX(element) execute_data->element\n\n"); - out($f,"#undef EX_CV\n"); - out($f,"#define EX_CV(var) EX(CVs)[var]\n"); - out($f,"#undef EX_CVs\n"); - out($f,"#define EX_CVs() EX(CVs)\n"); - out($f,"#undef EX_T\n"); - out($f,"#define EX_T(offset) (*(temp_variable *)((char *) EX(Ts) + offset))\n\n"); out($f,"#undef ZEND_VM_CONTINUE\n"); out($f,"#undef ZEND_VM_RETURN\n"); out($f,"#undef ZEND_VM_ENTER\n"); @@ -1447,6 +1411,6 @@ if (!defined("ZEND_VM_LINES")) { define("ZEND_VM_LINES", 0); } -gen_vm("zend_vm_def.h", "zend_vm_execute.skl"); +gen_vm(__DIR__ . "/zend_vm_def.h", __DIR__ . "/zend_vm_execute.skl"); ?> diff --git a/Zend/zend_vm_opcodes.h b/Zend/zend_vm_opcodes.h index 94e69abf1e..859258a440 100644 --- a/Zend/zend_vm_opcodes.h +++ b/Zend/zend_vm_opcodes.h @@ -159,3 +159,8 @@ #define ZEND_SEPARATE 156 #define ZEND_QM_ASSIGN_VAR 157 #define ZEND_JMP_SET_VAR 158 +#define ZEND_DISCARD_EXCEPTION 159 +#define ZEND_YIELD 160 +#define ZEND_GENERATOR_RETURN 161 +#define ZEND_FAST_CALL 162 +#define ZEND_FAST_RET 163 |