This commit disallows the use of trailing positional arguments
after argument unpacking was used. The following calls are no
longer valid:
fn(...$array, $var);
fn(...$array1, $var, ...$array2);
However, all of the following continue to be valid:
fn($var, ...$array);
fn(...$array1, ...$array2);
fn($var, ...$array1, ...$array2);
The reason behind this change is a stack allocation issue pointed
out by Dmitry: As of PHP 5.5 the stack necessary for pushing
arguments is precomputed and preallocated, as such the individual
SEND opcodes no longer verify that there is enough stack space.
The unpacked arguments will occupy some of that preallocated
space and as such following positional arguments could write past
a stack page boundary.
An alternative resolution for this issue is to ensure that there
is enough space for the remaining arguments in the UNPACK opcode.
However making this allocation precise (rather than using a
conversative over-estimate) would require some effort. Given that
this particular aspect of the feature wasn't very popular in the
first place, it doesn't seem worth the effort.
Instead of storing the argument number in the znode of the parameter
list, store it in fcall->arg_num. This mainly cleans up the parameter
parsing code, which previously had to duplicate all rules (this
becomes more excessive as more features are added, e.g. named params
would already require a minimum of 14 rules...)
Instead of directly pushing the zend_function* onto the
function_call_stack, push this structure. This allows us to store
additional data on this stack.
* upstream/PHP-5.6: (399 commits)
Fixed issue #115 (path issue when using phar). Fixed issue #149 (Phar mount points not working with OPcache enabled).
Added tests for PHAR/OPCahce incompatibilities
Update NEWS
Fixed bug #65947 (basename is no more working after fgetcsv in certain situation)
Update NEWS
Fixed Bug #66043 (Segfault calling bind_param() on mysqli)
NEWS entry
NEWS entry
Fix bug #65946 - pdo_sql_parser.c permanently converts values bound to strings
bump API versions
Add a couple more test cases to parse_url() tests
fix missing change from 'tcp_socket' to the more common 'server'
fix many parallel test issues
Cleanup temp test file
Revert "Fixed issue #115 (path issue when using phar)."
Update LiteSpeed SAPI code to V6.4
Fixed typo in Makefile.frag
updated NEWS
Remove outdate codes, make it clearer, although just a bit..
Update NEWS
...
Conflicts:
Zend/zend_compile.h
* The fetch_type and check_ns_name parameters of
zend_resolve_class_name were unused and are now removed.
* ZEND_FETCH_CLASS_GLOBAL is no longer used (no code actually
checking for it).
* The checks for usage of "namespace" as class name were
unnecessary as that situation can't occur anyways.
* generators: (70 commits)
Fix typos
Fix segfault when traversing a by-ref generator twice
Make sure that exception is thrown on rewind() after closing too
Remove implementation stubs for yield delegation
Fix several issues and allow rewind only at/before first yield
Run finally if generator is closed before finishing
Finally with return now works in generators too
Add dedicated opcode for returns from a generator
Disallow serialization and unserialization
Fix zts build (typo)
Drop Generator::close() method
Forgot to add test
Support trivial finally in generators (no yield, no return)
Fix implementation of Iterator interface
Add T_YIELD in tokenizer_data.c
Throw error also for return occuring before yield
Fix throwing of exceptions within a generator
Remove reference restrictions from foreach
Require parenthesis around yield expressions
Add some more tests
...
This is just an intial merge. It does not yet make generators and finally
work together.
Conflicts:
Zend/zend_language_scanner.c
Zend/zend_language_scanner_defs.h
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
Zend/zend_vm_execute.skl
Zend/zend_vm_opcodes.h
If yield is used in an expression context parenthesis are now required.
This ensures that the code is unambiguos.
Yield statements can still be used without parenthesis (which should be
the most common case).
Also yield expressions without value can be used without parenthesis,
too (this should be the most common case for coroutines).
If the yield expression is used in a context where parenthesis are required
anyway, no additional parenthesis have to be inserted.
Examples:
// Statements don't need parenthesis
yield $foo;
yield $foo => $bar;
// Yield without value doesn't need parenthesis either
$data = yield;
// Parentheses don't have to be duplicated
foo(yield $bar);
if (yield $bar) { ... }
// But we have to use parentheses here
$foo = (yield $bar);
This commit also fixes an issue with by-ref passing of $foo[0] like
variables. They previously weren't properly fetched for write.
Additionally this fixes valgrind warnings which were caused by access to
uninitialized memory in zend_is_function_or_method_call().
Generators are now automatically detected by the presence of a `yield`
expression in their body.
This removes the ZEND_SUSPEND_AND_RETURN_GENERATOR opcode. Instead
additional checks for ZEND_ACC_GENERATOR are added to the fcall_common
helper and zend_call_function.
This also adds a new function zend_generator_create_zval, which handles
the actual creation of the generator zval from an op array.
I feel like I should deglobalize the zend_create_execute_data_from_op_array
code a bit. It currently changes EG(current_execute_data) and
EG(opline_ptr) which is somewhat confusing (given the name).
Keys are yielded using the
yield $key => $value
syntax. Currently this is implemented as a statement only and not as an
expression, because conflicts arise considering nesting and use in arrays:
yield yield $a => $b;
// could be either
yield (yield $a) => $b;
// or
yield (yield $a => $b);
Once I find some way to resolve these conflicts this should be available
as an expression too.
Also the key yielding code is rather copy-and-past-y for the value yielding
code, so that should be factored out.
Yield now is an expression and the return value is the value passed to
$generator->send(). By default (i.e. if ->next() is called) the value is
NULL.
Unlike in Python ->send() can be run without priming the generator with a
->next() call first.
Generator functions have to specify the * (asterix) modifier after the
function keyword. If they do so the ZEND_ACC_GENERATOR flag is added to
the fn_flags.
. zend_function.pass_rest_by_reference is replaced by
ZEND_ACC_PASS_REST_BY_REFERENCE in zend_function.fn_flags
. zend_function.return_reference is replaced by ZEND_ACC_RETURN_REFERENCE
in zend_function.fn_flags
. zend_arg_info.required_num_args removed. it was needed only for internal
functions. Now the first arg_info for internal function (which has special
meaning) is represented by zend_internal_function_info structure.
. zend_op_array.size, size_var, size_literal, current_brk_cont,
backpatch_count moved into CG(context), because they are used only during
compilation.
. zend_op_array.start_op is moved into EG(start_op), because it's used
only for 'interactive' execution of single top-level op-array.
. zend_op_array.done_pass_two is replaced by ZEND_ACC_DONE_PASS_TWO in
zend_op_array.fn_flags.
. op_array.vars array is trimmed (reallocated) during pass_two.
. zend_class_entry.constants_updated is replaced by
ZEND_ACC_CONSTANTS_UPDATED in zend_class_entry.ce_flags
. the size of zend_class_entry is reduced by sharing the same memory space
by different information for internal and user classes.
See zend_class_inttry.info union.
# RFC http://wiki.php.net/rfc/horizontalreuse#traits_-_reuse_of_behavior
# Ok, here we go, I guess that will result in more discussion, which is fine
# by me. But now, the patch is here, and properly archived.
#
# See below a list of notes to the patch, it also includes a list of
# points which should be fixed
#
# Internals of the Traits Patch
# -----------------------------
#
# Open TODOs
# """"""""""
#
# - Reflection API
# - support for traits for internal classes
# - currently destroy_zend_class does not handle that case
#
# Introduced Structures
# """""""""""""""""""""
#
# Data structures to encode the composition information specified in the
# source:
# - zend_trait_method_reference
# - zend_trait_precedence
# - zend_trait_alias
#
# Changes
# """""""
#
# zend_class_entry
# - uses NULL terminated lists of pointers for
# - trait_aliases
# - trait_precedences
# - do you prefer an explicit counter?
# - the information is only necessary during class composition
# but might be interesting for reflection
# - did not want to blow up class further with not really necessary length counters
#
# added keywords
# - trait
# - insteadof
#
# Added opcodes
# ZEND_ADD_TRAIT
# - similar to ZEND_ADD_INTERFACE
# - adds the trait to the list of traits of a class, no actual composition done
# ZEND_BIND_TRAITS
# - emitted in zend_do_end_class_declaration
# - concludes the class definition and will initiate the trait composition
# when the class definition is encountered during runtime
#
# Added Flags
# ZEND_ACC_TRAIT = 0x120
# ZEND_ACC_IMPLEMENT_TRAITS = 0x400000
# ZEND_FETCH_CLASS_TRAIT = 14
#
# zend_vm_execute.h
# - not sure whether the handler initialization (ZEND_ADD_TRAIT_SPEC_HANDLER,
# ZEND_BIND_TRAITS_SPEC_HANDLER) is correct, maybe it should be more selective
#
# zend_compile.c
# - refactored do_inherit_method_check
# split into do_inherit_method_check and do_inheritance_check_on_method
# - added helper functions use a '_' as prefix and are not mentioned in the
# headers
# - _copy_functions
# prepare hash-maps of functions which should be merged into a class
# here the aliases are handled
# - _merge_functions
# builds a hash-table of the methods which need to be added to a class
# does the conflict detection
# - reused php_runkit_function_copy_ctor
# - it is not identical with the original code anymore, needed to update it
# think I fixed some bugs, not sure whether all have been reported back to runkit
# - has to be renamed, left the name for the moment, to make its origin obvious
# - here might be optimization potential
# - not sure whether everything needs to be copied
# - copying the literals might be broken
# - added it since the literals array is freed by efree and gave problems
# with doubled frees
# - all immutable parts of the zend_op array should not be copied
# - am not sure which parts are immutable
# - and not sure how to avoid doubled frees on the same arrays on shutdown
# - _merge_functions_to_class
# does the final merging with the target class to handle inherited
# and overridden methods
# - small helper for NULL terminated lists
# zend_init_list, zend_add_to_list
#
# zend_language_parser.y
# - reused class definition for traits
# - there should be something with regard to properties
# - if they get explicitly defined, it might be worthwhile to
# check that there are no collisions with other traits in a composition
# (however, I would not introduce elaborate language features to control that
# but a notice for such conflicts might be nice to the developers)
. ZEND_RECV now always has IS_CV as its result
. ZEND_CATCH now has to be used only with constant class names
. ZEND_FETCH_DIM_? may fetch array and dimension operans in a different order
. Improved syntax highlighting and consistency for variables in double-quoted strings and literal text in HEREDOCs and backticks. (Matt)
. Optimized interpolated strings to use one less opcode. (Matt)
- Renamed zend_do_fetch_class_name() to zend_do_build_full_name() (It is not used only for classes)
- Moved zend_resolve_class_name prototype to zend_compile.h
The following pseudo-code explains how it should be used in opcode cache.
function cache_compile_file($filename) {
if (!is_cached($filename)) {
...
orig_compiler_options = CG(compiler_optins);
CG(compiler_options) |= ZEND_COMPILE_IGNORE_INTERNAL_CLASSES |
ZEND_COMPILE_DELAYED_BINDING;
$op_array = orig_compile_file($filename);
CG(compiler_options) = orig_copiler_options;
...
} else {
$op_array = restore_from_cache($filename);
}
zend_do_delayed_early_binding($op_array);
}
- Fixed bug #36214 (__get method works properly only when conditional operator is used).
- Fixed bug #39449 (Overloaded array properties do not work correctly).
- Fixed bug #39990 (Cannot "foreach" over overloaded properties).
# This time i added:
# ZEND_FE_RESET_VARIABLE
# ZEND_FE_RESET_REFERENCE
# and dapted parser,compiler,executor,interfaces to handle these flags
# their purpose is to be able to pass whetehr foreach is done by ref to
# the current() handler so that it can error out in case it is not capable
# to comply to the requested return signature/protocol/semantics (weyp).
determine whether pass by ref is possible or pass by value is needed.
# This is usefull when functions take array or string parameters as
# expressions. In such a case force by ref is not applicable and the
# executor would copy the variable unnecessarily as soon as it is at least
# once referenced.
- Extensions which delete global variables need to use new special function
- delete_global_variable() (I'm about to rename it) to remove them.
- Will post to internals@ or via commit messages if there's anything else.
a) We specialize opcodes according to op_type fields. Each opcode has to
be marked with which op_type's it uses.
b) We support different execution methods. Function handlers, switch()
and goto dispatching. goto seems to be the fastest but it really
depends on the compiler and how well it optimizes. I suggest playing
around with optimization flags.
- Warning: Things might break so keep us posted on how things are going.
(Dmitry, Andi)