Предварительная компиляция файлов PHP - PullRequest
0 голосов
/ 25 августа 2018

В качестве учебного упражнения я пытаюсь сохранить скомпилированное состояние файла PHP, чтобы выполнить его позднее, без необходимости повторного выполнения zend_compile_file.

Первое, что ясделал было написать расширение, которое перехватывает zend_compile_file.Если запрос сделан для некомпилированного файла (например, file.php), он выгружает данные zend_op_array в другой файл (например, compiled-file.php).Если запрос сделан для такого скомпилированного файла, он загружает данные в новый zend_op_array, а затем возвращает его.

Для простоты я проигнорировал все, что связано с классами и функциями, поэтому я неЯ не ожидаю, что мое расширение будет работать над сценарием, который содержит их.Но другие более простые сценарии должны работать, я думаю?

Ну, он работает на очень простых скриптах, но часто просто зависает и достигает максимального времени выполнения.Я обнаружил, что это всегда терпит неудачу на ложной условной ветви.Например, этот сценарий будет работать:

<?php
$a = 10;
$b = 5;
if ($b < $a)
    echo $a;

В то время как этот сценарий будет просто зависать:

<?php
$a = 10;
$b = 5;
if ($b > $a)
    echo $a;

Мой вопрос: правильно ли я предположить, что для простых сценариев без функций или классовсделать глубокую копию zend_op_array и вернуть ее должно быть достаточно для репликации компиляции PHP?Если нет, какие еще шаги я должен предпринять, чтобы он работал?

Вот соответствующие файлы моего расширения: opdumper.c oploader.c

РЕДАКТИРОВАТЬ: мне удалось «исправить» мою проблему, изменив этот код:

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;
        ...
    }
}

на этот:

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;
        ...
    }
}

(И, конечно, применяя аналогичныйисправить в oploader.c)

Теперь я просто еще больше запутался ... почему znode_op с типом IS_UNUSED заботится о его значении! ??

...