> Intuitively, I would expect this:
>
> {
>      let $x = new Foo;
>      $x->bar();
> }
> somethingElse();
>
> to be equivalent to this:
>
> let $x = new Foo;
> $x->bar();
> unset($x);
> somethingElse();

If this feature freed variables when going out of scope,
it would be compiled more like the following (if there were multiple lets):

JavaScript doesn't have destructors, but PHP does, which makes the 
implementation a tiny bit more complex.

```
try {
    $x = new Foo();
    $otherLet = new Other();
    $x->bar();
} finally {
    // try/finally is useful if unset($otherLet) could throw from __destruct
    try {
        unset($otherLet);
    } finally {
        unset($x);
    }
}
somethingElse();
```

Actually, thinking about this again, performance is hopefully less of a concern.
I could safely avoid using `try/finally` if this was outside of a `try` block,
as long as this was in a function scope instead of a global scope.
(All variable go out of scope for uncaught exceptions)
This idea is still a work in progress.

It would definitely be useful to free immediately for objects (or arrays with 
objects) which call `__destruct`
when the reference count goes to 0, such as RAII patterns.

My concern about adding an extra `unset()` is that it would add some 
performance overhead,
discouraging using this feature, but opcache should be able to optimize the 
unset out when unnecessary.

I touched on the reasons for avoiding `try` blocks earlier, but hopefully 
they're not needed.
The global scope is less likely to be vital to performance in most cases.

> - Freeing it immediately would likely require the equivalent of a try{} 
> finally{} to handle exceptions.
>   try statements prevent opcache from optimizing a function, the last time I 
> checked.

See 
https://github.com/php/php-src/blob/43443857b74503246ee4ca25859b302ed0ebc078/ext/opcache/Optimizer/dfa_pass.c#L42-L49
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to