The "nothing to do" case would never be hit because the switch block
would execute if the opcode is ZEND_ASSIGN_STATIC_PROP_OP,
not ZEND_ASSIGN_STATIC_PROP. This meant that we were falling through to
the else block. Fix this by correcting the check condition.
We're in the case of ZEND_JMPZ_EX or ZEND_JMPNZ_EX. The opcode gets
overwritten and only after the overwriting gets checked if we're in a
JMPZ or JMPNZ case. This results in a wrong optimization.
Close GH-10329
&& and || should always evaluate to a boolean instead of the lhs/rhs.
This optimization never gets triggered for any of our tests.
Additionally, even if triggered this instruction gets optimized away
because the else branch of the JMP instruction will overwrite the tmp
value.
- running: true if garbage collection is currently running
- protected: true if the garbage collector is protected and root
additions are forbidden
- full: true if the garbage collector buffer size exceeds GC_MAX_BUF_SIZE
- buffer_size: current garbage collector buffer size
Documentation for existing fields:
- runs: the number of times the garbage collector has been run
- collected: the number of objects collected
- threshold: the number of roots in the buffer which will trigger
garbage collection
- roots: the current number of roots in the buffer
Updated manual example output:
array(8) {
["running"]=>
bool(false)
["protected"]=>
bool(false)
["full"]=>
bool(false)
["runs"]=>
int(5)
["collected"]=>
int(100002)
["threshold"]=>
int(50001)
["buffer_size"]=>
int(131072)
["roots"]=>
int(0)
}
These values not always converted to IS_LONG (e.g. by -- and ++) and
this leads to incorrect range inferene and later to incorrect JIT code
generation.
This avoids a possible significant performance penalty, when some leaf function was observed, deep in the stack.
As a side effect, we are not iterating over prev_execute_data anymore and thus, non-observed fake frames, possibly on stack, cannot have any impact on the observer anymore (especially within zend_observer_fcall_end_all).
Saving the previous observer happens now directly on the VM stack. If there is any observer, function frames are allocated an extra zval (the last temporary), which will, on observed frames, contain the previous observed frame address.