This change was originall only done for 'master'. Xdebug bundles this file as
it requires it, but PHP 7.2/7.3 don't have it bundled. By doing "phpize" with
master, it updates the file introducing a local diff. By fixing it in older
versions, that problem goes away.
This changes ClassInfo::createIncludeElement() such that it takes the $query
argument as-is for the xpointer attribute value. Special characters, like
" and &, are used as-is so be careful not to break the resulting XML.
This prevents serialization and unserialization of a class and its
children in a way that does not depend on the zend_class_serialize_deny
and zend_class_unserialize_deny handlers that will be going away
in PHP 9 together with the Serializable interface.
In stubs, `@not-serializable` can be used to set this flag.
This patch only uses the new flag for a handful of Zend classes,
converting the remainder is left for later.
Closes GH-7249.
Fixes bug #81111.
E.g. `build/gen_stub.php *.stub.php` will generate `*_arginfo.h`
from multiple files.
Previously, gen_stub.php would silently ignore files after the first file.
Invoking gen_stub.php with no arguments will continue to process the entire
directory.
Adjust FS in order_by_dep.awk to only each whitespace around (,)
rather than any whitespace. Thus a leading indent does not result
in a separate element.
1. one **hybrid** solution of register usage
After the discussion with Dmitry, we may want to propose one hybrid
solution of register usage.
1) Following the x86 implementation, we define REG0/1/2 to be the
scratch registers. Clever tricks are utilized in x86 implementation for
better register allocation. Note that we define REG0/1/2 as x8/9/10. One
reason is that R0 and FCARG1 should be distinguished.
2) Temporary registers are also reserved(i.e. they are excluded from the
candidates of register allocator), and they would be used due to the
different addressing modes in AArch64.
2. update the 'make clean' target.
3. remove the unnecessary AArch64 related macros in zend_jit_internal.h.
[ci skip]
Change-Id: I627157b88b2344530d705751eb7f73a223ed83e5
CustomizedGitHooks: yes
SUMMARY
We implemented a prototype of PHP JIT/arm64. Briefly speaking,
1. build system
Changes to the build system are made so that PHP JIT can be successfully
built and run on ARM-based machine.
Major change lies in file zend_jit_arm64.dasc, where the handler for
each opcode is generated into machine code. Note that this file is just
copied from zend_jit_x86.dasc and the *unimplemented* parts are
substitued with 'brk' instruction for future work.
2. registers
AArch64 registers are defined in file zend_jit_arm64.h. From our
perspectives, the register usage is quite different from the x86
implementation due to the different ABI, number of registers and
addressing modes.
We had many confusions on this part, and will discuss it in details in
the final section.
3. opcodes
Several opcodes are partially supported, including INIT_FCALL, DO_UCALL,
DO_ICALL, RETURN, ADD, PRE_INC, JMP, QM_ASSIGN, etc. Hence, simple use
scenarios such as user function call, loops, addition with integer and
floating point numbers can be supported.
18 micro test cases are added under 'ext/opcache/tests/jit/arm64/'. Note
that majority of these test cases are design for functional JIT, and
cases 'hot_func_*.phpt' and 'loop_002.phpt' can trigger tracing JIT.
4. test
Our local test environment is an ARM-based server with Ubuntu 20.04 and
GCC-10. Note that both HYBRID and CALL VM modes are supported. We
suggest running the JIT test cases using the following command. Out of
all 130 test cases, 66 cases can be passed currently.
```
$ make test TESTS='-d opcache.jit=1203 ext/opcache/tests/jit/'
```
DETAILS
1. I-cache flush
Instruction cache must be flushed for the JIT-ed code on AArch64. See
macro JIT_CACHE_FLUSH in file 'zend_jit_internal.h'.
2. Disassembler
Add initialization and jump target parse operations for AArch64 backed.
See the updates in file 'zend_jit_disasm.c'.
3. redzone
Enable redzone for AArch64. See the update in zend_vm_opcodes.h.
Redzone is designated to prevent 'vm_stack_data' from being optimized
out by compilers. It's worth noting that this 16-byte redzone might be
reused as temporary use(treated as extra stack space) for HYBRID mode.
4. stack space reservation
The definitions of HYBRID_SPAD, SPAD and NR_SPAD are a bit tricky for
x86/64.
In AArch64, HYBRID_SPAD and SPAD are both defined as 16. These 16 bytes
are pre-allocated for tempoerary usage along the exuection of JIT-ed
code. Take line 4185 in file zend_jit_arm64.dasc as an example. NR_SPAD
is defined as 48, out of which 32 bytes to save FP/IP/LR registers.
Note that we choose to always reserve HYBRID_SPAD bytes in HYBRID mode,
no matter whether redzone is used or not, for the sake of safety.
5. stack alignment
In AArch64 the stack pointer should be 16-byte aligned. Since shadow
stack is used for JIT, it's easy to guarantee the stack alignment, via
simply moving SP with an offset like 16 or a multiple of 16. That's why
NR_SPAD is defined as 48 and we use 32 of them to save FP/IP/LR
registers which only occupies 24 bytes.
6. global registers
x27 and x28 are reserved as global registers. See the updates in file
zend_jit_vm_helpers.c
7. function prologue for CALL mode
Two callee-saved registers x27 and x28 should saved in function
zend_jit_prologue() in file zend_jit_arm64.dasc. Besides the LR, i.e.
x30, should also be saved since runtime C helper functions(such as
zend_jit_find_func_helper) might be invoked along the execution of
JIT-ed code.
8. regset
Minor changes are done to regset operations particularly for AArch64.
See the updates in file zend_jit_internal.h.
REGISTER USAGE
In this section, we will first talk about our understanding on register
usage and then demonstrate our design.
1. Register usage for HYBRID/CALL modes
Registers are used similarly between HYBRID mode and CALL mode.
One difference is how FP and IP are saved. In HYBRID mode, they are
assigned to global registers, while in CALL mode they are saved/restored
on the VM stack explicitly in prologue/epilogue.
The other difference is that LR register should also be saved/restored
in CALL mode since JIT-ed code are invoked as normal functions.
2. Register usage for functional/tracing JIT
The way registers are used differs a lot between functional JIT and
tracing JIT.
For functional JIT, runtime C code (e.g. helper functions) would be
invoked along the execution of JIT-ed code. As the operands for *most*
opcodes are accessed via the stack slot, i.e. FP + offset. Hence there
is no need to save/restore local(caller-saved) registers before/after
invoking runtime C code.
Exception lies in Phi node and registers might be allocated for these
nodes. Currently I don't fully understand the reason, why registers are
allocated for Phi functions, because I suppose for different versions of
SSA variables at the Phi function, their postions on the stack slot
should be identical(in other words, access via the stack slot is enough
and there is no need to allocate registers).
For tracing JIT, runtime information are recorded for traces(before the
JIT compilation), and the data types and control flows are concrete as
well. Hence it's would be faster to conduct operations and computations
via registers rather than stack slots(as functional JIT does) for these
collected hot paths. Besides, runtime C code can be invoked for tracing
JIT, however this only happends for deoptimization and all registers are
saved to stack in advance.
3. Candidates for register allocator
1) opcode candidates
Function zend_jit_opline_supports_reg() determines the candidate opcodes
which can use CPU registers.
2) register candidates
Registers in set "ZEND_REGSET_FP + ZEND_REGSET_GP - ZEND_REGSET_FIXED -
ZEND_REGSET_PRESERVED" are available for register allocator.
Note that registers from ZEND_REGSET_FIXED are reserved for special
purpose, such as the stack pointer, and they are excluded from register
allocation process.
Note that registers from ZEND_REGSET_PRESERVED are callee-saved based on
the ABI and it's safe to not use them either.
4. Temporary registers
Temporary registers are needed by some opcodes to save intermediate
computation results.
1) Functions zend_jit_get_def_scratch_regset() and
zend_jit_get_scratch_regset() return which registers might be clobbered
by some opcodes. Hence register allocator would spill these scratch
registers if necessary when encountering these opcodes.
2) Macro ZEND_REGSET_LOW_PRIORITY denotes a set of registers which would
be allocated with low priority, and these registers can be used as
temporary usage to avoid conflicts to its best.
5. Compared to the x86 implementation, in JIT/arm64
1) Called-saved FP registers are included into ZEND_REGSET_PRESERVED for
AArch64.
2) We follow the logic of function zend_jit_opline_supports_reg().
3) We reserve 4 GPRs and 2 FPRs out from register allocator and use them
as temporary registers in particular. Note that these 6 registers are
included in set ZEND_REGSET_FIXED.
Since they are reserved, may-clobbered registers can be removed for most
opcodes except for function calls. Besides, low-priority registers are
defined as empty since all candidate registers are of the same priority.
See the updates in function zend_jit_get_scratch_regset() and macro
ZEND_REGSET_LOW_PRIORITY.
6. Why we reserve registers for temporary usage?
1) Addressing mode in AArch64 needs more temporary registers.
The addressing mode is different from x86 and tempory registers might be
*always* needed for most opcodes. For instance, an immediate must be
first moved into one register before storing into memory in AArch64,
whereas in x86 this immediate can be stored directly.
2) There are more registers in AArch64.
Compared to the solution in JIT/x86(that is, temporary registers are
reserved on demand, i.e. different registers for different opcodes under
different conditions), our solution seems a coarse-granularity and
brute-force solution, and the execution performance might be downgraded
to some extent since the number of candidate registers used for
allocation becomes less.
We suppose the performance loss might be acceptable since there are more
registers in AArch64.
3) Based on my understanding, scratch registers defined in x86 are
excluded from candidates for register allocator with *low possibility*,
and it can still allocate these registers. Special handling should be
conducted, such as checking 'reg != ZREG_R0'.
Hence, as we see it, it's simpler to reserve some temporary registers
exclusively. See the updates in function zend_jit_math_long_long() for
instance. TMP1 can be used directly without checking.
Co-Developed-by: Nick Gasson <Nick.Gasson@arm.com>
Not removing this causes build failure when reconfiguring and rebuilding after a `make clean`, e.g. enabling/disabling ZTS.
This makes https://bugs.php.net/bug.php?id=80561 more bearable. Ideally it would be rebuilt automatically on configuration change if necessary, but I have no idea how to implement this.
Closes GH-6702.
This makes --verify also check @implementation-alias. Failures are
ignored using @no-verify instead. Some mistakes have been made that
would have been caught by this...
Closes GH-6615.
Some functions have multiple aliases, while the $aliasMap can
only record one.
Methodsynopsis generation probably shouldn't use it either, but
at least that case seems to only be interested in whether there
is an alias at all.
This closes the last hole in the supported types for internal
function arginfo types. It's now possible to represent unions of
multiple classes. This is done by storing them as TypeA|TypeB and
PHP will then convert this into an appropriate union type list.
Closes GH-6581.
The current behavior has been introduced 20 years ago in
f9e375f493 as part of a larger change.
It's not clear to me why special treatement of -lpthread is necessary
here.
This flag generates an arginfo file that discards all type and
default value information. As such, it is compatible with old
(and very old) PHP versions.
Intended for use by extensions to generate one arginfo file for
PHP 8 and one for older versions.
Currently compiler flags passed by extensions using the standard
``PHP_NEW_EXTENSION`` and ``PHP_ADD_SOURCES`` m4 macros are prepended
before the ones defined by ``Zend/Zend.m4``.
This was not really an issue before as ``Zend.m4`` only included
``-Wall`` but since the addition of ``-Wextra`` various issue about
disabling flags have been brought up.
A preliminary attempt was done in commit 5c1cf7669b
but this turns out to be more or less irrelevant.
The root issue is that ``PHP_NEW_EXTENSION`` and ``PHP_ADD_SOURCES`` call the
``PHP_ADD_SOURCES_X`` macro and pass their flags as the 3rd argument which prepends
the flags. There exists a 6th argument for this macro which appends them but from a
cursory look at https://heap.space/search?full=PHP_ADD_SOURCES_X&project=php-src
this is not used. Moreover, the comment describing this macro explicitly informs
that this macro should not be used directly.
As such we drop the 6th argument of ``PHP_ADD_SOURCES_X`` and move the `special-flags`
argument to be appended instead of prepended.
Closes GH-6204
Given that this executes a random function with zero parameters,
actually executing the code doesn't make sense.
This should fix the imap + asan build.
With named arguments in php 8.0, it's important that php's modules
or PECL extensions using gen_stub.php don't generate functions
with duplicate names.
Warn if a parameter name is repeated,
even if the last occurrence is a variadic parameter
Closes GH-6035
PHP-Parser 4.3.0 failed to recognize that the `match` keyword could be
used as a class constant name.
4.9.0 also adds support for keywords in namespaced names.
See https://github.com/nikic/PHP-Parser/releases
So forcing regeneration of spl_iterators.stub.php failed.
PECL extensions using gen_stub.php would also be affected
by the same issue.
```
ext/spl/spl_iterators.stub.php
public function __construct(Iterator $iterator, string $regex,
int $mode = self::MATCH, int $flags = 0, int $preg_flags = 0) {}
```
Testing: I successfully regenerated stubs by setting forceRegeneration to true
and running `touch **/*.stub.php; make`.
The stubs did not change, as expected.
Closes GH-6036
Since libxml version 2.9.0 external entity loading is disabled by default.
Bumping the version requirement means that XML processing in PHP is no
longer vulnerable to XXE processing attacks by default.
The hash is used to check whether the arginfo file needs to be
regenerated. PHP-Parser will only be downloaded if this is actually
necessary.
This ensures that release artifacts will never try to regenerate
stubs and thus fetch PHP-Parser, as long as you do not modify any
files.
Closes GH-5739.
- Fix typo in build/php.m4
- Nothing uses HAVE_INTTYPES_H; so remove check for header file
- Nothing defines ZEND_ACCONFIG_H_NO_C_PROTOS; so remove #ifndef
- `format_money` was removed in 2019, so <monetary.h> no longer needed
- Nothing uses HAVE_NETDB_H; so remove check for header file
- Nothing checks HAVE_TERMIOS_H; so remove check for header file
(This was actually added when Wez Furlong was adding the original implementation of
PTY support in `proc_open`, since replaced.)
- Nothing checks HAVE_SYS_AUXV_H; so remove check for header file
- PHP_BUILD_DATE variable is not used for anything, so remove it
This variable was added to the Makefile, but from there, was not used for anything.
The comments suggest it was intended to allow 'reproducible builds'. Presumably,
this means that if a bug is found in a PHP binary somewhere, one could look at the
Makefile which it was built from, see the date, and then could check the same
code version out from source control. But... there can easily be multiple commits
to the repo in the same day. Also, what makes us think that the Makefile which a
binary was built from will be easily available?
Besides, ext/standard/info.c already embeds the build date and time in each binary...
but it does it using `__DATE__` and `__TIME__` (see `php_print_info`).
- Nothing checks HAVE_FINITE; so don't check for function
- Grammar fix to comment in build/php.m4
- Nothing sets $php_ldflags_add_usr_lib variable in configure, so remove conditional
This was added in 2002, when Rasmus was having difficulty building PHP on some
host and needed to have /usr/lib in the rpath. It was never documented and
probably has never been used by anyone else.
lcov is emitting several errors for generated regex files that have no code
coverage data. The fix is to add the files to the lcov exlusion list.
This is not an issue for CI because it uses gcovr to generate code coverage.
The errors:
Processing ext/date/lib/parse_date.gcda
geninfo: WARNING: could not open /home/code/vendor/php/php-src/parse_date.re
geninfo: WARNING: could not open /home/code/vendor/php/php-src/<stdout>
geninfo: WARNING: some exclusion markers may be ignored
Processing ext/date/lib/parse_tz.gcda
Processing ext/date/lib/tm2unixtime.gcda
Processing ext/date/lib/parse_iso_intervals.gcda
geninfo: WARNING: could not open /home/code/vendor/php/php-src/<stdout>
geninfo: WARNING: could not open /home/code/vendor/php/php-src/parse_iso_intervals.re
geninfo: WARNING: some exclusion markers may be ignored
...
genhtml: ERROR: cannot read /home/code/vendor/php/php-src/parse_date.re
Processing file /home/code/vendor/php/php-src/parse_date.re
make: *** [Makefile:443: lcov-html] Error 2
Closes GH-5568.
I reverted this previously for 7.4 because of bug #78769. Relanding
it now for master, because I still believe that this change is
right, and if it causes complications, those indicate a bug elsewhere.
---
These were checking whether the instruction set is supported by
the host CPU, however they were only used to condition on whether
this instruction set is targeted at all. It would still use dynamic
dispatch (e.g. based on ifunc resolvers) to select the actual
implementation. Whether the target is guaranteed to support the
instruction set without dispatch is determined based on pre-defined
macros like __SSE2__.
This removes the configure-time builtin cpu checks to remove
confusion. Additionally this allows targeting an architecture that
is newer than the host architecture.
We have to actually determine the proper `SIZEOF_OFF_T`.
Interestingly, it is `4` on Windows x64.
We also have to prevent the redefinition in pg_config.h. The clean
solution would likely be to not include pg_config.h at all, but that's
out of scope for BC reasons for now.
- Support for "-shared" option is taken from libtool-2.0 that is already at lease 15 years old.
- Change PHP build system to use "-shared" instead of "--tag=disable-static".
For whatever reason, php 8 would not have loaded the subsequent classes when
running `php build/gen_stub.php path/to/filename.php`.
I assume it didn't load the classes immediately because there's a possibility
the code before it would throw.
(Probably because __toString was added recently and prevents early binding)
Also, fix a typo
Closes GH-5369
Closes GH-5353. From now on, PHP will have reflection information
about default values of parameters of internal functions.
Co-authored-by: Nikita Popov <nikita.ppv@gmail.com>
If @generate-function-entries is specified in the stub file,
also generate function entries for the extension.
Currently limited to free functions only.
First, fix 5547d36120: the definition of
YFLAGS was not passed into the Makefile: AC_SUBST does not suffice, we
need PHP_SUBST_OLD. While at it, allow to pass variable and value at
the same time.
Then pass -Wall to bison, rather than only -Wempty-rules.
Use %precedence where associativity is useless.
Remove useless %precedence.
GH-5138
The annotation %empty is properly enforced: warnings when it's
missing, and errors when it's inappropriate. Support for %empty was
introduced in Bison 3.0.
Pass -Wempty-rule to Bison.
Closes GH-5134
Remove the check of PHP_OPENSSL inside SETUP_OPENSSL. It's the
responsibility of the caller to determine whether they want to
enable openssl or not. This makes SSL detection in IMAP work,
which uses a different option.
Additionally also clarify that --with-openssl-dir cannot actually
be used to specify an OpenSSL directory -- these options just
serve as a way to enable OpenSSL in extensions without also
enabling the OpenSSL extension. They need to be renamed to
something clearer in master.
Closes GH-5091.
This reverts commit edccf32f7f.
This was reported to cause issues for as yet unknown reasons in
bug #78769. As this was intended as code cleanup, revert this from
7.4 at least. May reapply it to master later.