As a learning exercise, I'm trying to save the compiled state of a PHP file in order to execute it at a later time without having to go through zend_compile_file
again.
The first thing I did was write an extension that hooks zend_compile_file
. If the request is made on an uncompiled file (ie: file.php), it dumps the zend_op_array
data to another file (ie: compiled-file.php). If the request is made on such a compiled file, it loads the data into a new zend_op_array
and then returns it.
For simplicity sake, I have ignored everything related to classes and functions, so I don't expect my extension to works on a script that contains those. But other simpler scripts should work, I think?
Well, it works on very simple scripts, but often it just hangs and reach the maximum execution time limit. I've found that it always fails on false conditional branch. For example, this script would work:
<?php
$a = 10;
$b = 5;
if ($b < $a)
echo $a;
While this one would just hangs:
<?php
$a = 10;
$b = 5;
if ($b > $a)
echo $a;
My question: Am I correct in assuming that for simple scripts with no functions or classes, making a deep copy of zend_op_array
and returning it should be enough to replicate PHP compilation? If not, what are the other steps I should take to make it works?
Here are the relevant files of my extension: opdumper.c oploader.c
EDIT: I managed to "fix" my problem by changing this code:
void dump_znode_op(FILE* fp, znode_op node, zend_uchar type)
{
fwrite(&type, sizeof(type), 1, fp);
switch(type) {
case IS_UNDEF:
case IS_UNUSED:
break;
...
}
}
to this one:
void dump_znode_op(FILE* fp, znode_op node, zend_uchar type)
{
fwrite(&type, sizeof(type), 1, fp);
switch(type) {
case IS_UNDEF:
case IS_UNUSED:
fwrite(&(node.var), sizeof(node.var), 1, fp);
break;
...
}
}
(And of course, applying a similar fix to oploader.c)
Now I'm just even more confused... why would a znode_op with an IS_UNUSED
type care about its value!??
zend_get_opcode_flags()
to get extended information about what IS_UNUSED operands and extended_value are used for. I'd also recommend taking a look at github.com/php/php-src/blob/master/ext/opcache/…, which is an existing implementation of serialization to file. – Cytochrome