News for hackers. Stuff that matters.
Re:PHP 8 to Add a JIT by chrisseaton on Sunday March 31, 2019 @11:49AM (#19536179)
This is the RFC with more technical details https://wiki.php.net/rfc/jit.

I believe their plan is to emit low-level code directly via DynAsm, without their own intermediate representation.

This kind of approach has been tried again and again and again and every project doing this either not got the results they wanted and given up or has had to go back and add a proper intermediate representation.

Examples include Rust adding MIR before emitting LLVM, Rubinius trying to emit LLVM directly from Ruby and not getting good results so giving up, JRuby adding an IR before emitting Java byte code, Dropbox's Pyston implementation of Python that emitted LLVM directly where they gave up entirely, etc, etc, etc.

Low level backends are not going to do the kind of key optimisations such as scalar replacement of aggregates that are table stakes for making a dynamic language perform well - they just don't have the high-level semantic model of the language needed to do it.

Maybe they've got some new ideas, or maybe simplicity is a key constraint for them, but I predict from experience that they will need an intermediate representation to get the results that they want.

Re:PHP 8 to Add a JIT by beberlei on Sunday March 31, 2019 @12:15PM (#19536338)
Not sure if this qualifies as intermediate representation in the LLVM sense, but PHP has opcodes already, it is not fully interpreted anymore (like it was in PHP 3).

These opcodes are used for optimizations and cached for the lifetime of the PHP process (across multiple requests).

Re:PHP 8 to Add a JIT by pas on Sunday March 31, 2019 @12:42PM (#19536522)
That's probably too low-level. Usually an AST is needed that is void of all syntactic sugar, yet can express the required data flows and dependencies so the trivial substitutions/replacements/caching and refactorings can be done at this level.

Lower level bytecode lacks these higher level references (it usually has a lot of indices that index into raw lookup tables, but no real symbols that refer to results of computations and other variables).

Re:PHP 8 to Add a JIT by readittwice on Sunday March 31, 2019 @04:43PM (#19538247)
Not sure why you think this is the case: there are numerous JITs/VMs that optimize starting from bytecode e.g. all JVMs, WebAssembly, V8, JSC,...

Can you point me to some paper/reference about this? AFAIK it doesn't matter whether you have an AST or bytecode. Optimizations are done on an IR anyways.

Re:PHP 8 to Add a JIT by tyingq on Sunday March 31, 2019 @01:29PM (#19536857)
There does appear to be an internal AST in php7: https://github.com/nikic/php-ast
Re:PHP 8 to Add a JIT by jashmatthews on Sunday March 31, 2019 @01:54PM (#19537034)
LuaJIT and WebKit both produce their IR from the bytecode, IIUC.
Re:PHP 8 to Add a JIT by ryanmccullagh on Sunday March 31, 2019 @01:33PM (#19536877)
PHP has had an AST for years now.
Re:PHP 8 to Add a JIT by pas on Sunday March 31, 2019 @06:26PM (#19538833)
Of course, but the opcode is lower level than that. And that was what the parent comment mentioned.
Re:PHP 8 to Add a JIT by WalterGR on Monday April 01, 2019 @01:51PM (#19546017)
Usually an AST is needed that is void of all syntactic sugar,

That’s how I’ve always see “AST” used, but not the following:

yet can express the required data flows and dependencies so the trivial substitutions/replacements/caching and refactorings can be done at this level.

Is what you describe some flavor of ‘augmented’ AST? Does that have a name other than AST?

Re:PHP 8 to Add a JIT by wvenable on Sunday March 31, 2019 @01:28PM (#19536850)
> making a dynamic language perform well

Perhaps the advantage here is that PHP really all that dynamic. PHP is much closer in design to taking Java and compiling it on every request than it is like Python or Ruby.

Re:PHP 8 to Add a JIT by skrebbel on Sunday March 31, 2019 @01:54PM (#19537031)
Well, you can do

    $moo = "hello";
    $zork = "moo";
    echo $$zork; // hello
It doesn't get much more dynamic than that.
Re:PHP 8 to Add a JIT by wvenable on Sunday March 31, 2019 @03:42PM (#19537855)
It can. Python, for example, builds up classes at runtime. PHP builds up classes at compile time. There are plenty of other examples. PHP is really dynamic through eval() but that's more rare.

Although PHP does support the above syntax, it's actually pretty rare in production code. PHP can be optimized like JavaScript is: perform direct variable/member access but provide a slow path for these kinds of dynamic lookups.

Re:PHP 8 to Add a JIT by viraptor on Sunday March 31, 2019 @04:44PM (#19538258)
You can't just wave away the impact of having eval though. Just the fact that it exists means you need to keep around some supporting state like variable names. You can't do full constant folding and eliminate all intermediate steps for example if there a chance a runtime-created code will reach into your frame and want them back.
Re:PHP 8 to Add a JIT by wvenable on Sunday March 31, 2019 @05:32PM (#19538553)
eval() is scoped to the current block. If you even just ignored JITing any function with eval() in it then you'd still get quite far.
Re:PHP 8 to Add a JIT by rujuladanh on Sunday March 31, 2019 @04:58PM (#19538340)
Similar things are done by JS engines and others nowadays. They optimize and keep the original stuff in case assumptions stop holding.
Re:PHP 8 to Add a JIT by bufferoverflow on Monday April 01, 2019 @07:22PM (#19549395)
You can do this in PHP:

    <?php
    eval('class Hello {public static function you(){echo "Yes!";}}');
    Hello::you();
or this:

    <?php
    file_put_contents('c.php', '<?php class Hello {public static function you(){echo "Yes!";}}');
    require('c.php');
    Hello::you();
Thus generating a class at runtime-ish.
Re:PHP 8 to Add a JIT by keithnoizu on Sunday March 31, 2019 @05:31PM (#19538543)
I used to use that pattern $$ frequently for library code.
Re:PHP 8 to Add a JIT by EGreg on Sunday March 31, 2019 @10:20PM (#19539896)
I wish PHP had classes spread across several files like ASP.NET.
Re:PHP 8 to Add a JIT by edoceo on Sunday March 31, 2019 @10:44PM (#19540004)
The PHP way for that is Traits
Re:PHP 8 to Add a JIT by wvenable on Sunday March 31, 2019 @11:23PM (#19540198)
I think he means partial classes in C#. Great for code generators.
Re:PHP 8 to Add a JIT by kyberias on Sunday March 31, 2019 @01:56PM (#19537046)
That looks it merely needs some reflection support (variable name lookup).
Re:PHP 8 to Add a JIT by chrisseaton on Sunday March 31, 2019 @02:06PM (#19537117)
The whole point of a JIT is that you don't do naive variable name lookup.

With a proper intermediate representation you'd connect that $$ variable lookup directly to the original variable's edge.

Re:PHP 8 to Add a JIT by chessturk on Sunday March 31, 2019 @02:01PM (#19537079)
Isn't reflection slow as hell?

If not please correct me.

Re:PHP 8 to Add a JIT by a1369209993 on Sunday March 31, 2019 @03:14PM (#19537631)
It's less fast than direct lookups, but if the compiler supports it properly, it shouldn't be any slower than a associative array lookup.

  echo $FOO[$BAR];
  echo $$BAZ;
  >>>
  
  push FOO.ptr
  push BAR.ptr
  call hash_get
  push ax
  call print
  
  push local_table // static per compiled scope
  push BAZ.ptr
  call hash_get
  push [ax+24] // entry->value
  call print
You'd probably want to add error handling (to both cases) and accessing a global variable that didn't exist when the code was compiled will likely be slow, but if becomes a preformance bottleneck you can always rewrite it to something easier to compile.
Re:PHP 8 to Add a JIT by inglor on Sunday March 31, 2019 @04:22PM (#19538117)
And of course a smart JIT compiler can even put the variable access lookup in an inline cache on the function so that in the future it's a direct type + key = offset calculation rather than a memory lookup and the hash_get call is avoided.
Re:PHP 8 to Add a JIT by a1369209993 on Sunday March 31, 2019 @05:37PM (#19538580)
True. I was aiming for the simplest example that could pass as real general-case-ish assembly; there's plenty of room for improvement.
Re:PHP 8 to Add a JIT by Tarean on Sunday March 31, 2019 @02:06PM (#19537110)
It's also very much frowned upon so a slow path is fine.

The _get and _set magic methods (called when getting/setting missing properties) are quite common especially for frameworks.

Re:PHP 8 to Add a JIT by steveklabnik on Sunday March 31, 2019 @02:12PM (#19537148)
(Rust had an AST and HIR before MIR happened, incidentally.)
Re:PHP 8 to Add a JIT by farlee on Sunday March 31, 2019 @02:17PM (#19537184)
I respect that the PHP maintainers recognize that it is not enough to accept a working JIT implementation - they have to understand and maintain it. Speed is one thing, but long term maintenance is more important.

> use DynAsm (developed for LuaJIT project) for generation of native code

But at the very least, this exercise will ensure that DynAsm will be actively used by a few people. So even if this PHP JIT effort fails, the underlying JIT technology will be more widely understood and hopefully better documented for other projects.

Re:PHP 8 to Add a JIT by readittwice on Sunday March 31, 2019 @04:33PM (#19538180)
True, however I would argue that having an IR in general makes the code easier to understand and maintain. Especially if you add more optimizations.
Re:PHP 8 to Add a JIT by yazr on Sunday March 31, 2019 @05:55PM (#19538674)
> key optimisations such as scalar replacement of aggregates

Can u give an example or link to a relevant article. Context: my area is more of high-level program (e.g. shape) analysis

Re:PHP 8 to Add a JIT by ufo on Sunday March 31, 2019 @06:31PM (#19538858)
Scalar replacement of aggregates means replacing an object allocated on the heap (for example, Point p = new Point) by local variables corresponding to its fields (double x, double y)

Removing the object allocation saves time and puts less pressure on the GC. Replacing the instance variables with local variables may also allow the compiler to optimize some things that it would not have attempted to optimize before. For example, storing them on machine registers.

Re:PHP 8 to Add a JIT by chrisseaton on Sunday March 31, 2019 @07:29PM (#19539164)
Right, and in a language where you are predominantly using strings, arrays, maps, unless you can remove and optimise through these data structures you spend your whole time allocating them, collecting them, doing lookup in them and you won't have any opportunity to apply other optimisations. You need to be able to understand these data structures at the level of an IR - DynASM or LLVM aren't going to remove a call to a lookup routine for you.
Re:PHP 8 to Add a JIT by yazr on Sunday March 31, 2019 @08:34PM (#19539446)
I understand that a JIT engine cant do this, due to speed.

But would be surprised that a LLVM compiler with a custom-designed heuristic for specific optimizations cant manage this.

These problems may be polynomial etc etc, but MOST of the code generated should follow common patterns

I will have to give this some thought.

Thanks for the reply (also GP)

Re:PHP 8 to Add a JIT by chrisseaton on Sunday March 31, 2019 @08:39PM (#19539461)
> I understand that a JIT engine cant do this, due to speed.

Most serious JIT engines do! For example V8, LuaJIT, Graal, C2.

> But would be surprised that a LLVM compiler with a custom-designed heuristic for specific optimizations cant manage this.

Rubinius for example tried writing custom optimisations like you're describing and didn't get very far. LLVM is not designed for these kind of optimisations - it understands memory reads and writes, not high-level semantic information about arrays and objects.

In practice, it just doesn't seem to work.

As I say I think it's a bare minimum for making a dynamic language genuinely fast. I gave a lecture about this https://www.youtube.com/watch?v=b1NTaVQPt1E.

Re:PHP 8 to Add a JIT by dman on Sunday March 31, 2019 @11:56AM (#19536237)
Chris - any recommendations on a good simple IR to study?
Re:PHP 8 to Add a JIT by chrisseaton on Sunday March 31, 2019 @12:01PM (#19536274)
MIR is probably a good example as it solves the problem I'm suggesting they'll encounter https://blog.rust-lang.org/2016/04/19/MIR.html.

Ideal is also a classic https://www.oracle.com/technetwork/java/javase/tech/c2-ir95-....

Re:PHP 8 to Add a JIT by dman on Sunday March 31, 2019 @12:04PM (#19536286)
Thanks!