On 27/10/2019 02:12, Mike Schinkel wrote:
While reading the [RFC] Union Types v2 thread and comments from Dmitry[1], and especially 
Benjamin[2] who suggested "building a static analysis tool which could prove that 
certain type checks would never fail, and prime OpCache" it occurred to me that a 
PHP pre-compiler could potentially be used to resolve numerous issues the community has 
been debating.


I chose the phrase "static analysis tool" deliberately, because I wanted to think about the minimum requirements for such a tool, rather than its long-term possibilities. The basic requirements are fairly straight-forward:

- a static analyser that can infer types in a PHP program; we know that's possible from a number of third-party tools, although they do rely on docblock comments for things the language doesn't (yet) let you define - the ability to generate OpCodes for some code and store it to disk; this is more or less what OpCache does if enabled for CLI mode

However, combining those usefully may not be that easy.

The first problem is that OpCache is designed to work one file at a time, because a program can load any combination of files at run-time. Static analysers, on the other hand, need to process a whole directory at a time, so that calls can be matched to definitions; multiple definitions of the same function or class tend to cause problems, even though only one is loaded at run-time. So we'd probably need some built-in definition of a "package", which could be analysed and compiled as one unit, and didn't rely on any run-time loading.

The second problem is that, as I understand it, type checks aren't actually separate OpCodes, so eliminating them from the compiled program may not be that easy. There are some cases where you can just eliminate the type check from a definition, e.g.:

class A {
    private int $x=1;
    private function foo(int $x) { }
    public function bar() {
       $this->foo($this->x);
    }
}

Since we know that function foo is only ever called with the correctly typed argument, we can compile it as though it had no type declaration. However, in the seemingly obvious case Benjamin gave, the optimisation isn't so easy:

function x(): int {}
function y(int $foo) {}
y(x());

We can't eliminate the type check for all calls to x(), or for all calls to y(), but we want to eliminate the duplicate check for that particular line. So the OpCodes need to represent that somehow. I've no idea how easy or hard that would be.


In order to extend this to a full compiler, we need at least one more thing: a stable compilation target. What I mean by that is that if I distribute a package in binary form, it needs to run on a reasonably large range of PHP versions and installations. My understanding is that the OpCodes in the Zend VM are not designed to be stable across versions, so you can't just ship today's OpCache output like you would a Java class file or .net assembly. Again, I don't know how much effort it would be to make the VM work as such a stable target.


4. Ability to deprecate features for pre-compiled code while still supporting 
them when not precompiled.


Unlike P++, Editions, or Strict Mode, this would undeniably define that the deprecated features were "the wrong way". If the engine had to support the feature anyway, I'm not sure what the advantage would be of tying it to "compiled vs non-compiled", rather than opting in via a declare() statement or package config.


Regards,

--
Rowan Tommins (né Collins)
[IMSoP]

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to