PHP 7.3 INTERNALS UPGRADE NOTES 1. Internal API changes a. array_init() and array_init_size() b. Run-time constant operand addressing c. Array/Object recursion protection d. HASH_FLAG_PERSISTENT e. AST and IS_CONSTANT f. GC_REFCOUNT() g. zend_get_parameters() h. zend_register_persistent_resource() i. RAND_RANGE() j. cast_object() with _IS_NUMBER k. zend_fcall_info_cache.initialized l. php_hrtime_current() m. zend_cpu_supports() n. IS_TYPE_COPYABLE o. IS_UNUSED p. VM instruction operands (FETCH_CLASS, FETCH_CONSTANT, CATCH) q. sapi_cli_single_write() r. php_url s. zend_function.reserved[] t. zif_handler u. GC_G v. php_add[c]slashes w. zend_class_entry.iterator_funcs x. Class declaration opcodes (DECLARE_INHERITED_CLASS ...) y. zend_constant z. HAVE_ST_BLKSIZE and HAVE_ST_RDEV aa. RETSIGTYPE bb. php_setcookie 2. Build system changes a. Unix build system changes b. Windows build system changes 3. Module changes ======================== 1. Internal API changes ======================== a. array_init() and array_init_size() are not functions anymore. They don't return any values. b. In 64-bit builds PHP-7.2 and below used relative run-time constant operand addressing. E.g. opline->op1.constant kept an offset from start of literals table - op_array->literals. To speedup access op_array->literals was cached in execute_data->literals. So the resulting address calculated as EX(literals) + opline->op1.constant. Now at run-time literals allocated close to opcodes, and addressed relatively from current opline. This eliminates load of EX(literals) on each constant access as well as EX(literals) initialization on each call. As result some related macros were removed (ZEND_EX_USE_LITERALS, EX_LOAD_LITERALS, EX_LITERALS, RT_CONSTANT_EX, EX_CONSTANT) or changed (RT_CONSTANT, ZEND_PASS_TWO_UPDATE_CONSTANT, ZEND_PASS_TWO_UNDO_CONSTANT). This change may affect only some "system" extensions. EX_LITERALS, RT_CONSTANT_EX, EX_CONSTANT should be substituted by RT_CONSTANT, and now use "opline" (instead of "op_array") as first argument. c. Protection from recursion during processing circular data structures was refactored. HashTable.nApplyCount and IS_OBJ_APPLY_COUNT are replaced by single flag GC_PROTECTED. Corresponding macros Z_OBJ_APPLY_COUNT, Z_OBJ_INC_APPLY_COUNT, Z_OBJ_DEC_APPLY_COUNT, ZEND_HASH_GET_APPLY_COUNT, ZEND_HASH_INC_APPLY_COUNT, ZEND_HASH_DEC_APPLY_COUNT are replaced with GC_IS_RECURSIVE, GC_PROTECT_RECURSION, GC_UNPROTECT_RECURSION, Z_IS_RECURSIVE, Z_PROTECT_RECURSION, Z_UNPROTECT_RECURSION. HASH_FLAG_APPLY_PROTECTION flag and ZEND_HASH_APPLY_PROTECTION() macro are removed. All mutable arrays should use recursion protection. Corresponding checks should be replaced by Z_REFCOUNTED() or !(GC_FLAGS(p) & GC_IMMUTABLE). d. HASH_FLAG_PERSISTENT renamed into IS_ARRAY_PERSISTENT and moved into GC_FLAGS (to be consistent with IS_STR_PERSISTENT). e. zend_ast_ref structure is changed to use only one allocation. zend_ast_copy() now returns zend_ast_ref (instead of zend_asr). zend_ast_destroy_and_free() is removed. ZVAL_NEW_AST() is replaced by ZVAL_AST(). IS_CONSTANT type and Z_CONST_FLAGS() are removed. Now constants are always represented using IS_CONSTANT_AST (ZEND_AST_CONSTANT kind). AST node attributes are used instead of constant flags. IS_TYPE_CONSTANT flag is removed, but Z_CONSTANT() macro is kept for compatibility. f. GC_REFCOUNT() is turned into inline function and can't be modified direcly. All reference-counting operations should be done through corresponding macros GC_SET_REFCOUNT(), GC_ADDREF() and GC_DELREF(). GC_REFCOUNT(p)++ should be changed into GC_ADDREF(p), GC_REFCOUNT(p)-- into GC_DELREF(p), GC_REFCOUNT(p) = 1 into GC_SET_REFCOUNT(p, 1). g. The zend_get_parameters() and zend_get_parameters_ex() functions were removed. Instead zend_parse_parameters() should be used. h. New functions zend_register_persistent_resource() or zend_register_persistent_resource_ex() should beused to register persistent resources, instead of manual insertion into EG(persistent_list). i. The RAND_RANGE() macro has been removed. php_mt_rand_range() should be used instead. j. The cast_object() object handler now also accepts the _IS_NUMBER type. The handler should return either an integer or float value in this case, whichever is more appropriate. k. zend_fcall_info_cache.initialized is removed. zend_fcall_info_cache is initialized if zend_fcall_info_cache.function_handler is set. l. php_hrtime_current() delivers the number of nanoseconds since an uncertain point in the past. m. zend_cpu_supports() determines if a feature is supported by current cpu. Also serial inline zend_cpu_supports_xxx() are added, which is designed for ifunc resolver function, as resolver function should not depend on any external function. n. IS_TYPE_COPYABLE flag is removed. IS_STRING zvals didn't need to be duplication by zval_copy_ctor(), ZVAL_DUP() and SEPARATE_ZVAL*() macros. Interned strings didn't set IS_TYPE_COPYABLE, so they aren't affected at all. Now instead of checking for IS_TYPE_COPYABLE, engine checks for IS_ARRAY type (it may be IS_TYPE_REFCOUNTED or not). All the related macros: Z_COPYABLE..., Z_IMMUTABLE... are kept for compatibility. o. IS_UNUSED became zero and can't be used as a bitmask (there were no such usages in PHP sources). p. Operands of few VM instructions were changed - FETCH_CLASS op1, op2, result - FETCH_CONSTANT op1, op2, result - CATCH ext, op1, op2, result q. sapi_cli_single_write() now returns ssize_t instead of size_t. r. fields of php_url struct change from char * to zend_string * s. Special purpose zend_functions marked by ZEND_ACC_CALL_VIA_TRAMPOLINE or ZEND_ACC_FAKE_CLOSURE flags use reserved[0] for internal purpose. Third party extensions must not modify reserved[] fields of these functions. t. For internal functions the typedef zif_handler has been introduced. It is recommended to use this from now on, instead of defining own handler types. u. The GC globals (GC_G) are now private. Use the new zend_gc_get_status() to retrieve status information of the GC. v. The should_free argument of the php_add[c]slashes functions has been removed. It is now always the caller's responsibility to free the passed string. w. zend_class_entry.iterator_funcs have been replaced by iterator_funcs_ptr. You don't have to set its value, setting parent.funcs in the get_iterator function is enough. x. Class declaration opcode formats were changed - DECLARE_INHERITED_CLASS and DECLARE_ANON_INHERITED_CLASS now encode parent class name in second operand directly (as IS_CONST operand). Previously, parent class was fetched by the prior FETCH_CLASS opcode. - ADD_INTERFACE and ADD_TRAIT don't use run-time cache to keep interface or trait. These instructions are executed once, and caching is useless. y. zend_constant.flags and zend_constant.module_number are packed into reserved space inside zend_constant.value. They should be accessed using ZEND_CONSTANT_FLAGS(), ZEND_CONSTANT_MODULE_NUMBER() and ZEND_CONSTANT_SET_FLAGS() macros. z. HAVE_ST_BLKSIZE must be replaced with HAVE_STRUCT_STAT_ST_BLKSIZE and HAVE_ST_RDEV must be replaced with HAVE_STRUCT_STAT_ST_RDEV. aa. RETSIGTYPE has been removed from the generated php_config.h and should be replaced with void. bb. php_setcookie() now expects an additional samesite argument, and the url_encode parameter has been moved to the end. The signature is now: int php_setcookie(zend_string *name, zend_string *value, time_t expires, zend_string *path, zend_string *domain, int secure, int httponly, zend_string *samesite, int url_encode); ======================== 2. Build system changes ======================== a. Unix build system changes - PHP_PROG_LEX, TSRM_CHECK_GCC_ARG, and LIBZEND_CPLUSPLUS_CHECKS Autoconf macros have been removed. - Minimum Autoconf version is 2.68+ for generating the configure script. b. Windows build system changes - ZEND_WIN32_FORCE_INLINE doesn't affect C++ anymore. zend_always_inline is still usable in C++, but anything else inlining related is up to compiler. - ZEND_WIN32_KEEP_INLINE was removed, it was only needed for C++ convenience and is now default behavior with C++. - New configure option --enable-native-intrinsics accepts a list of the intrinsic optimizations to enable. It affects both the code generation and the explicit optimizations guarded by preprocessor macros. - The configure option --with-codegen-arch accepts only ia32 as a value. Use it, to produce builds suitable for older processors without SSE2 or even SSE support. ======================== 3. Module changes ========================