Writing the PHP Virtual Machine in Rust (With a Lot of Help from AI)

MyKiwi1 pts0 comments

Writing the PHP Virtual Machine in Rust (with a lot of help from AI) - JoliCode

Accéder au contenu principal

A few years ago, if someone had told me to rewrite the PHP engine in Rust, I would probably have laughed . Not because it is technically impossible, but because such a project traditionally requires years of reading C code, reverse engineering decades of optimizations, and an intimidating amount of perseverance.

Today, Large Language Models have changed how we approach ambitious engineering projects. They do not magically produce production-ready software, but they dramatically reduce the cost of understanding unfamiliar codebases, exploring implementation strategies, and validating ideas.

Projects like Bun and the React Compiler show that revisiting mature ecosystems has become more realistic, not because AI replaces engineers, but because it multiplies their capacity.

This is the story of building a new PHP Virtual Machine in Rust, what worked, what failed, and why the goal was never to create yet another PHP interpreter.

Section intitulée the-first-prototype-surprisingly-easy-and-terribly-slowThe first prototype: surprisingly easy and terribly slow

Like many AI-assisted projects, the first version began with an intentionally naive approach. Without studying the PHP source code in depth, we asked the model to generate a VM from its own knowledge, then guided it with examples and corrections whenever something failed.

Before long, we had a functional prototype capable of executing a meaningful subset of PHP, but it was incredibly slow. That was hardly surprising: the generated implementation favored correctness over performance.

Furthermore it generated a stack vm where PHP is a registry vm

I believe that this difference would have been very painful at some point. Those kinds of differences can make some behavior don’t work the same way, like destruction orders of values, or timing of errors emission. Given the current PHP ecosystem, I’m pretty sure that some existing libraries rely on those orders. Since the goal is to mimic a real migration of PHP, I believe that we should respect that.

The prototype (done in one day) only proved that the idea was viable, but it was clearly not the final architecture.

Section intitulée copying-php-exactly-was-not-the-goalCopying PHP exactly was not the goal

At that point, one option was to follow the path Bun took with its rewrite and reproduce the original implementation as closely as possible. This has obvious advantages: PHP’s engine contains more than twenty years of knowledge and optimization from hundreds of contributors, and reproducing its architecture often means reproducing its performance.

Such rewrite generally breaks the target language way of doing things, look at [https://github.com/oven-sh/bun/pull/30412](the Bun rewrite pull request). It is full of unsafe, which, in my opinion, completely defeats the purpose of using Rust and makes this PR a complete nonsense.

The purpose of the project was not simply to rewrite Zend Engine in another language, but to understand how PHP works and explore what its VM might look like if designed from the beginning around Rust’s philosophy.

That meant embracing ownership, avoiding global mutable state, minimizing unsafe code, and taking advantage of the language rather than constantly fighting it. Otherwise, there would be little point in choosing Rust.

Section intitulée learning-from-php-instead-of-copying-itLearning from PHP instead of copying it

Not copying PHP does not mean ignoring it. A significant part of the project involved reading Zend Engine code, asking AI why particular mechanisms existed, tracing historical decisions, and discussing alternative implementations.

I learned a lot on how PHP works, why it works that way, and how to implement similar behavior in Rust.

Those conversations often revealed that an optimization reflected older CPU behavior, that strange-looking code avoided an allocation on a critical path, or that Rust offered a more natural implementation. Just as often, they showed that PHP had already found the best solution years ago.

The objective gradually shifted from rewriting PHP to understanding why it became what it is today.

Section intitulée building-the-vm-i-always-wantedBuilding the VM I always wanted

Studying the engine also gave me an opportunity to experiment with ideas I had wanted to see in PHP for years.

Section intitulée respecting-ownership-and-avoiding-global-stateRespecting ownership and avoiding global state

One of the first constraints was to follow the Rust way of doing things: avoid global mutable state. Instead, the VM is designed to be a self-contained object that can be instantiated multiple times, each with its own state.

This makes the architecture easier to reason about while allowing multiple independent VMs to run within the same thread. It also simplifies testing and...

rust from years rewrite engine code

Related Articles