# Parameter parsing for zval type?

- Thread: https://externals.io/message/87708
- Original archive: https://news-web.php.net/php.internals/87708
- Started by Matt Wilmas on 2015-08-11T17:20:44+00:00
- Messages: 9
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #87708 — Matt Wilmas — 2015-08-11T17:20:44+00:00

URL: https://externals.io/message/87708#87708

Hi Dmitry, all,

Help me understand this. :-)  It's been more puzzling to me recently since 
just coming to the part of optimizing traditional ZPP (sharing part with 
FAST_ZPP...).

With the FAST_ZPP inline macros, why is there a Z_PARAM_ZVAL and 
Z_PARAM_ZVAL_DEREF?  It seems the zpp 'z' specifier is always like 
ZVAL_DEREF, right?  So Z_PARAM_ZVAL has no equivalent in traditional zpp. 
At the very least, this would seem to suggest a difference in 
behavior/functionality.  But I haven't found any (or bug reports, if tests 
didn't cover something).

At first I assumed Z_PARAM_ZVAL would keep IS_REFERENCE types, since it 
doesn't do ZVAL_DEREF(), but this obviously isn't happening with references. 
(It seems they're getting DEREF()'d in VM when sending params, I guess...?)

So is there never a need for ZVAL_DEREF() when parsing params?  Shouldn't 
have 2 FAST_ZPP ZVAL types?  Otherwise, why the inconsistency zpp's 'z'?

What am I missing, if anything??  Thanks!


- Matt

---

## #87712 — Matt Wilmas — 2015-08-11T18:00:05+00:00

URL: https://externals.io/message/87708#87712 · In reply to: #87708

Hi again,

----- Original Message -----
From: "Matt Wilmas"
Sent: Tuesday, August 11, 2015

> Hi Dmitry, all,
>
> Help me understand this. :-)  It's been more puzzling to me recently since 
> just coming to the part of optimizing traditional ZPP (sharing part with 
> FAST_ZPP...).
>
> With the FAST_ZPP inline macros, why is there a Z_PARAM_ZVAL and 
> Z_PARAM_ZVAL_DEREF?  It seems the zpp 'z' specifier is always like 
> ZVAL_DEREF, right?  So Z_PARAM_ZVAL has no equivalent in traditional zpp. 
> At the very least, this would seem to suggest a difference in 
> behavior/functionality.  But I haven't found any (or bug reports, if tests 
> didn't cover something).

Oops!  No, plain zpp 'z' does not have ZVAL_DEREF() applied, of course.  But 
it's also using zend_parse_arg_zval_DEREF(), which is wrong... (in the case 
of "z!" with reference to IS_NULL?).

> At first I assumed Z_PARAM_ZVAL would keep IS_REFERENCE types, since it 
> doesn't do ZVAL_DEREF(), but this obviously isn't happening with 
> references. (It seems they're getting DEREF()'d in VM when sending params, 
> I guess...?)

Still stands though that IS_REFERENCE doesn't seem to get through anyway 
(and would break functions).  Is any ZVAL_DEREF() *not* necessary?


- Matt

---

## #87713 — Dmitry Stogov — 2015-08-11T19:02:54+00:00

URL: https://externals.io/message/87708#87713 · In reply to: #87712

Hi Matt,


On Tue, Aug 11, 2015 at 9:00 PM, Matt Wilmas <php_lists@realplain.com>
wrote:

> Hi again,
>
> ----- Original Message -----
> From: "Matt Wilmas"
> Sent: Tuesday, August 11, 2015
>
> Hi Dmitry, all,
> > […]
>
> Oops!  No, plain zpp 'z' does not have ZVAL_DEREF() applied, of course.
> But it's also using zend_parse_arg_zval_DEREF(), which is wrong... (in the
> case of "z!" with reference to IS_NULL?).


Sorry. I don't understand you without context. If you think something is
wrong in current implementation - please, demonstrate it with test cases,
examples or code references. If you talk about your code, then show it.

Thanks. Dmitry.


> At first I assumed Z_PARAM_ZVAL would keep IS_REFERENCE types, since it
> > […]
>
> Still stands though that IS_REFERENCE doesn't seem to get through anyway
> (and would break functions).  Is any ZVAL_DEREF() *not* necessary?
>
>
> - Matt

---

## #87717 — Matt Wilmas — 2015-08-11T20:10:50+00:00

URL: https://externals.io/message/87708#87717 · In reply to: #87713

Hi Dmitry,

----- Original Message -----
From: "Dmitry Stogov"
Sent: Tuesday, August 11, 2015

> Hi Matt,
>
>
> On Tue, Aug 11, 2015 at 9:00 PM, Matt Wilmas <php_lists@realplain.com>
> wrote:
>
> > […]
>
>
> Sorry. I don't understand you without context. If you think something is
> wrong in current implementation - please, demonstrate it with test cases,
> examples or code references. If you talk about your code, then show it.

Sorry, thought I gave enough context and code references!  I can't 
demonstrate with a test case, which is why I'm asking about it. :-)

No, not my code changes (you'll have plenty of code to see soon).  I'm fine 
replicating the current logic exactly, as I have, but the logic of these 
couple parts doesn't make sense, to me.  Let me try to simplify with couple 
examples...

Look at e.g. `is_numeric()` or `strpos()` (needle).  Plain zval param parsing, 
so NO ZVAL_DEREF() occurs (FAST_ZPP or traditional).  These 2 example 
functions don't handle IS_REFERENCE type, so they would break.

Or is there no way for them (or any function?) to get a IS_REFERENCE?  Then 
*why* is there ZVAL_DEREF() in param parsing functions?  We could remove it!

Which is it...?

> Thanks. Dmitry.

Thanks,
Matt

---

## #87718 — Nikita Popov — 2015-08-11T20:15:01+00:00

URL: https://externals.io/message/87708#87718 · In reply to: #87717

On Tue, Aug 11, 2015 at 10:10 PM, Matt Wilmas <php_lists@realplain.com>
wrote:

> Hi Dmitry,
>
>
> ----- Original Message -----
> From: "Dmitry Stogov"
> Sent: Tuesday, August 11, 2015
>
> Hi Matt,
> > […]
>
> Sorry, thought I gave enough context and code references!  I can't
> demonstrate with a test case, which is why I'm asking about it. :-)
>
> No, not my code changes (you'll have plenty of code to see soon).  I'm
> fine replicating the current logic exactly, as I have, but the logic of
> these couple parts doesn't make sense, to me.  Let me try to simplify with
> couple examples...
>
> Look at e.g. `is_numeric()` or `strpos()` (needle).  Plain zval param parsing,
> so NO ZVAL_DEREF() occurs (FAST_ZPP or traditional).  These 2 example
> functions don't handle IS_REFERENCE type, so they would break.
>
> Or is there no way for them (or any function?) to get a IS_REFERENCE?
> Then *why* is there ZVAL_DEREF() in param parsing functions?  We could
> remove it!
>
> Which is it...?
>

Functions accepting references are specially marked in arginfo. Normal
function argument can never be IS_REFERENCE. Reference arguments are always
IS_REFERENCE. There is also a rarely used mixed mode where both are
possible. For DEREF-or-not distinction is irrelevant for normal arguments,
it's only important if an argument is already marked to accept a ref.

Nikita

---

## #87719 — Dmitry Stogov — 2015-08-11T20:27:48+00:00

URL: https://externals.io/message/87708#87719 · In reply to: #87717

On Tue, Aug 11, 2015 at 11:10 PM, Matt Wilmas <php_lists@realplain.com>
wrote:

> Hi Dmitry,
>
>
> ----- Original Message -----
> From: "Dmitry Stogov"
> Sent: Tuesday, August 11, 2015
>
> Hi Matt,
> > […]
>
> Sorry, thought I gave enough context and code references!  I can't
> demonstrate with a test case, which is why I'm asking about it. :-)
>
> No, not my code changes (you'll have plenty of code to see soon).  I'm
> fine replicating the current logic exactly, as I have, but the logic of
> these couple parts doesn't make sense, to me.  Let me try to simplify with
> couple examples...
>
> Look at e.g. `is_numeric()` or `strpos()` (needle).  Plain zval param parsing,
> so NO ZVAL_DEREF() occurs (FAST_ZPP or traditional).  These 2 example
> functions don't handle IS_REFERENCE type, so they would break.
>
> Or is there no way for them (or any function?) to get a IS_REFERENCE?
> Then *why* is there ZVAL_DEREF() in param parsing functions?  We could
> remove it!
>

We probably may remove ZVAL_DEREF() for functions arguments passed by
value, but we don't know if argument was passed by value or by reference in
ZPP functions. Actually, in FAST_ZPP for scalars we may probably assume
passing by value and remove ZVAL_DEREF(), but I'm not sure if this is 100%
safe.

Thanks. Dmitry.


>
> Which is it...?
>
> Thanks. Dmitry.
> > […]
>
> Thanks,
> Matt

---

## #87735 — Matt Wilmas — 2015-08-12T22:10:44+00:00

URL: https://externals.io/message/87708#87735 · In reply to: #87718

Hi Nikita,

----- Original Message -----
From: "Nikita Popov"
Sent: Tuesday, August 11, 2015

> On Tue, Aug 11, 2015 at 10:10 PM, Matt Wilmas <php_lists@realplain.com>
> wrote:
>
> > […]
>
> Functions accepting references are specially marked in arginfo. Normal
> function argument can never be IS_REFERENCE. Reference arguments are 
> always
> IS_REFERENCE. There is also a rarely used mixed mode where both are
> possible. For DEREF-or-not distinction is irrelevant for normal arguments,
> it's only important if an argument is already marked to accept a ref.

Thanks.  Yeah, OK, I see ZEND_SEND_REF creates a reference (if not already), 
which allows the ref'd var to be "recovered" later with ZVAL_DEREF() while 
parsing.  I guess that's right!

I *think* any by-reference argument also needs to be separated during 
parsing (to not affect anything else).  Is that correct logic?  If so, we 
can say that DEREF is only needed if also separating (which only applies to 
array/string/plain zval types, AFAIK).

But what is the "rarely used mixed mode where both are possible?"

> Nikita

Thanks,
Matt

---

## #87736 — Matt Wilmas — 2015-08-12T22:12:46+00:00

URL: https://externals.io/message/87708#87736 · In reply to: #87719

H Dmitry,

----- Original Message -----
From: "Dmitry Stogov"
Sent: Tuesday, August 11, 2015

> On Tue, Aug 11, 2015 at 11:10 PM, Matt Wilmas <php_lists@realplain.com>
> wrote:
>
> > […]
>
> We probably may remove ZVAL_DEREF() for functions arguments passed by
> value, but we don't know if argument was passed by value or by reference 
> in
> ZPP functions. Actually, in FAST_ZPP for scalars we may probably assume
> passing by value and remove ZVAL_DEREF(), but I'm not sure if this is 100%
> safe.

Yes, speaking of scalars, I had already noticed that it doesn't make sense 
to have a "separate" argument for the FAST_ZPP scalar _EX macros, as there's 
nothing to separate (same with traditional '/') on simple values.  I was 
changing those macros, and don't think they're used anyway.

Also, I think those simple/scalar types wouldn't be used with by-reference 
arguments (?), as there would be nothing to update...

Like I said in reply to Nikita, it seems like separating is needed for 
by-reference args, so only need DEREF if *also* separating?  It looks like 
that was the idea with Z_PARAM_ZVAL_EX().  And for other types, separating 
only applies to arrays or strings, I believe.

As far as not 100% safe, you mean IS_REFERENCE type causing an error about 
wrong type?  Shouldn't that only happen if developer indicated by-ref arg, 
but then used wrong type in parsing?

On the other hand, it seems like always using ZVAL_DEREF() won't hurt 
anything? e.g. part of my confusion was that I thought IS_REFERENCE was 
wanting to be *kept* in some cases (after parsing), but it seems to not be 
the case. :-)

Speaking of confusion, it also seems the DEREF stuff is unnecessary in 
type.c:php_is_type(), for example.

> Thanks. Dmitry.

Thanks,
Matt

---

## #87760 — Dmitry Stogov — 2015-08-17T08:33:10+00:00

URL: https://externals.io/message/87708#87760 · In reply to: #87736

On Thu, Aug 13, 2015 at 1:12 AM, Matt Wilmas <php_lists@realplain.com>
wrote:

> H Dmitry,
>
> ----- Original Message -----
> From: "Dmitry Stogov"
> Sent: Tuesday, August 11, 2015
>
> On Tue, Aug 11, 2015 at 11:10 PM, Matt Wilmas <php_lists@realplain.com>
> > […]
>
> Yes, speaking of scalars, I had already noticed that it doesn't make sense
> to have a "separate" argument for the FAST_ZPP scalar _EX macros, as
> there's nothing to separate (same with traditional '/') on simple values.
> I was changing those macros, and don't think they're used anyway.
>
> Also, I think those simple/scalar types wouldn't be used with by-reference
> arguments (?), as there would be nothing to update...
>
> Like I said in reply to Nikita, it seems like separating is needed for
> by-reference args, so only need DEREF if *also* separating?  It looks like
> that was the idea with Z_PARAM_ZVAL_EX().  And for other types, separating
> only applies to arrays or strings, I believe.
>
> As far as not 100% safe, you mean IS_REFERENCE type causing an error about
> wrong type?  Shouldn't that only happen if developer indicated by-ref arg,
> but then used wrong type in parsing?
>

At least this case. We may change ZVAL_DEREF(...) into
ZEND_ASSERT(!Z_ISREF_P(...)), to prevent silence crashes.

Thanks. Dmitry.


>
> On the other hand, it seems like always using ZVAL_DEREF() won't hurt
> anything? e.g. part of my confusion was that I thought IS_REFERENCE was
> wanting to be *kept* in some cases (after parsing), but it seems to not be
> the case. :-)
>
> Speaking of confusion, it also seems the DEREF stuff is unnecessary in
> type.c:php_is_type(), for example.
>
> Thanks. Dmitry.
> > […]
>
> Thanks,
> Matt
