Skip to content

Avoid @prefer-ref arguments #16961

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft

Conversation

dstogov
Copy link
Member

@dstogov dstogov commented Nov 27, 2024

No description provided.

@@ -542,9 +542,9 @@ static zend_never_inline zend_ffi_cdata *zend_ffi_cdata_to_zval_slow_ret(void *p
}
/* }}} */

static zend_always_inline void zend_ffi_cdata_to_zval(zend_ffi_cdata *cdata, void *ptr, zend_ffi_type *type, int read_type, zval *rv, zend_ffi_flags flags, bool is_ret, bool debug_union) /* {{{ */
static zend_always_inline void zend_ffi_cdata_to_zval(zend_ffi_cdata *cdata, void *ptr, zend_ffi_type *type, int convert, zval *rv, zend_ffi_flags flags, bool is_ret, bool debug_union) /* {{{ */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like this is now just used as a boolean flag?

Suggested change
static zend_always_inline void zend_ffi_cdata_to_zval(zend_ffi_cdata *cdata, void *ptr, zend_ffi_type *type, int convert, zval *rv, zend_ffi_flags flags, bool is_ret, bool debug_union) /* {{{ */
static zend_always_inline void zend_ffi_cdata_to_zval(zend_ffi_cdata *cdata, void *ptr, zend_ffi_type *type, bool convert, zval *rv, zend_ffi_flags flags, bool is_ret, bool debug_union) /* {{{ */

|| EX(opline)->opcode == ZEND_FETCH_DIM_FUNC_ARG)
&& EX(call)->func
&& EX(call)->func->type == ZEND_INTERNAL_FUNCTION
&& EX(call)->func->internal_function.module == &ffi_module_entry) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a note that this will unfortunately not work with frameless calls, since they do not create a stack frame.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. may be you see a better (simpler) possible test.

Ideally, we might add some flag to opline->extended_value for FETCH_DIM/OBJ_R/FUNC_ARG at compile time.
This is possible for frame-less functions, but not possible for indirect calls. ($f = "FFI::type"; $f($x)).

|| EX(opline)->opcode == ZEND_FETCH_DIM_FUNC_ARG)
&& EX(call)->func
&& EX(call)->func->type == ZEND_INTERNAL_FUNCTION
&& EX(call)->func->internal_function.module == &ffi_module_entry) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There might be an issue (I didn't test it) when passing a value from an FFI value to one of the FFI functions that are currently not @prefer-ref. For example:

\FFI::memset($x, $y['z'], 42);

If $y is a CData, $y['z'] will return another CData object to represent the offset. This would throw a type error, at least with strict_types=1. Luckily, it doesn't look like there are many such cases. In theory, they could also be solved by accepting CData explicitly, and fetching the value internally.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right again. We should check that the result of FETCH_DIM/OBJ used as an operand of SEND or FRAMELESS_CALL and make a final decision taking into account the called function and parameter. The test becomes too complex...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had the same thought. This would be trivial for FETCH_DIM_R. It only uses flags in extended_value. FETCH_OBJ_R contains the cache slot offset in extended_value. However, it also stores ZEND_FETCH_REF (1), so we already remove it through a bitwise op when fetching the cache slot. We could either use 2, as the cache slot offset is a multiple of 4 on 32-bit, and 8 on 64-bit. Hence, there shouldn't be any performance overhead.

Reserving an engine flag for an optional extension does feel a bit unfortunate. That said, we likely could still use higher flags (1 << 31) when we need to.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants