Support custom passes in Optimizer

This commit is contained in:
codinghuang 2021-01-31 18:51:13 +08:00 committed by Joe Watkins
parent e2e770c442
commit 2f710f5bb2
No known key found for this signature in database
GPG key ID: F9BA0ADA31CBD89E
4 changed files with 78 additions and 0 deletions

View file

@ -31,6 +31,15 @@
#include "zend_inference.h"
#include "zend_dump.h"
#ifndef ZEND_OPTIMIZER_MAX_REGISTERED_PASSES
# define ZEND_OPTIMIZER_MAX_REGISTERED_PASSES 32
#endif
struct {
zend_optimizer_pass_t pass[ZEND_OPTIMIZER_MAX_REGISTERED_PASSES];
int last;
} zend_optimizer_registered_passes = {{NULL}, 0};
static void zend_optimizer_zval_dtor_wrapper(zval *zvalue)
{
zval_ptr_dtor_nogc(zvalue);
@ -1402,6 +1411,16 @@ static void step_dump_after_optimizer(zend_op_array *op_array, void *context) {
zend_dump_op_array(op_array, ZEND_DUMP_LIVE_RANGES, "after optimizer", NULL);
}
static void zend_optimizer_call_registered_passes(zend_script *script, void *ctx) {
for (int i = 0; i < zend_optimizer_registered_passes.last; i++) {
if (!zend_optimizer_registered_passes.pass[i]) {
continue;
}
zend_optimizer_registered_passes.pass[i](script, ctx);
}
}
ZEND_API int zend_optimize_script(zend_script *script, zend_long optimization_level, zend_long debug_level)
{
zend_class_entry *ce;
@ -1541,6 +1560,8 @@ ZEND_API int zend_optimize_script(zend_script *script, zend_long optimization_le
} ZEND_HASH_FOREACH_END();
} ZEND_HASH_FOREACH_END();
zend_optimizer_call_registered_passes(script, &ctx);
if ((debug_level & ZEND_DUMP_AFTER_OPTIMIZER) &&
(ZEND_OPTIMIZER_PASS_7 & optimization_level)) {
zend_foreach_op_array(script, step_dump_after_optimizer, NULL);
@ -1554,6 +1575,27 @@ ZEND_API int zend_optimize_script(zend_script *script, zend_long optimization_le
return 1;
}
ZEND_API int zend_optimizer_register_pass(zend_optimizer_pass_t pass)
{
if (!pass) {
return -1;
}
if (zend_optimizer_registered_passes.last == ZEND_OPTIMIZER_MAX_REGISTERED_PASSES) {
return -1;
}
zend_optimizer_registered_passes.pass[
zend_optimizer_registered_passes.last++] = pass;
return zend_optimizer_registered_passes.last;
}
ZEND_API void zend_optimizer_unregister_pass(int idx)
{
zend_optimizer_registered_passes.pass[idx-1] = NULL;
}
int zend_optimizer_startup(void)
{
return zend_func_info_startup();

View file

@ -89,8 +89,12 @@ typedef struct _zend_script {
uint32_t first_early_binding_opline; /* the linked list of delayed declarations */
} zend_script;
typedef void (*zend_optimizer_pass_t)(zend_script *, void *context);
BEGIN_EXTERN_C()
ZEND_API int zend_optimize_script(zend_script *script, zend_long optimization_level, zend_long debug_level);
ZEND_API int zend_optimizer_register_pass(zend_optimizer_pass_t pass);
ZEND_API void zend_optimizer_unregister_pass(int idx);
int zend_optimizer_startup(void);
int zend_optimizer_shutdown(void);
END_EXTERN_C()

View file

@ -28,6 +28,7 @@
#include "zend_observer.h"
#include "zend_smart_str.h"
#include "zend_fibers.h"
#include "Zend/Optimizer/zend_optimizer.h"
ZEND_BEGIN_MODULE_GLOBALS(zend_test)
int observer_enabled;
@ -43,6 +44,7 @@ ZEND_BEGIN_MODULE_GLOBALS(zend_test)
int observer_nesting_depth;
int observer_fiber_switch;
int replace_zend_execute_ex;
int register_passes;
ZEND_END_MODULE_GLOBALS(zend_test)
ZEND_DECLARE_MODULE_GLOBALS(zend_test)
@ -86,6 +88,16 @@ static ZEND_FUNCTION(zend_test_void_return)
ZEND_PARSE_PARAMETERS_NONE();
}
static void pass1(zend_script *script, void *context)
{
php_printf("pass1\n");
}
static void pass2(zend_script *script, void *context)
{
php_printf("pass2\n");
}
static ZEND_FUNCTION(zend_test_deprecated)
{
zval *arg1;
@ -365,6 +377,7 @@ PHP_INI_BEGIN()
STD_PHP_INI_ENTRY("zend_test.observer.show_opcode_in_user_handler", "", PHP_INI_SYSTEM, OnUpdateString, observer_show_opcode_in_user_handler, zend_zend_test_globals, zend_test_globals)
STD_PHP_INI_BOOLEAN("zend_test.observer.fiber_switch", "0", PHP_INI_SYSTEM, OnUpdateBool, observer_fiber_switch, zend_zend_test_globals, zend_test_globals)
STD_PHP_INI_BOOLEAN("zend_test.replace_zend_execute_ex", "0", PHP_INI_SYSTEM, OnUpdateBool, replace_zend_execute_ex, zend_zend_test_globals, zend_test_globals)
STD_PHP_INI_BOOLEAN("zend_test.register_passes", "0", PHP_INI_SYSTEM, OnUpdateBool, register_passes, zend_zend_test_globals, zend_test_globals)
PHP_INI_END()
static zend_observer_fcall_handlers observer_fcall_init(zend_execute_data *execute_data);
@ -503,6 +516,11 @@ PHP_MINIT_FUNCTION(zend_test)
zend_observer_fiber_switch_register(fiber_suspend_observer);
}
if (ZT_G(register_passes)) {
zend_optimizer_register_pass(pass1);
zend_optimizer_register_pass(pass2);
}
return SUCCESS;
}

View file

@ -0,0 +1,14 @@
--TEST--
Optimizer: Pass Registration
--EXTENSIONS--
opcache
--INI--
opcache.enable_cli=1
zend_test.register_passes=1
--FILE--
<?php
?>
--EXPECT--
pass1
pass2