Commit: 276847cabae95f9ab35dd253ed6fde6b9e6b3f86
Author: Dmitry Stogov <dmi...@zend.com> Thu, 11 Apr 2013 15:18:35
+0400
Parents: 88e14d01bf2ad68aff481f7be08eb670bf2c35ed
Branches: master
Link:
http://git.php.net/?p=php-src.git;a=commitdiff;h=276847cabae95f9ab35dd253ed6fde6b9e6b3f86
Log:
Added script level constant replacement
Changed paths:
M ext/opcache/Optimizer/pass1_5.c
M ext/opcache/Optimizer/zend_optimizer.c
M ext/opcache/Optimizer/zend_optimizer.h
M ext/opcache/ZendAccelerator.c
M ext/opcache/ZendAccelerator.h
diff --git a/ext/opcache/Optimizer/pass1_5.c b/ext/opcache/Optimizer/pass1_5.c
index dc9e731..3a32970 100644
--- a/ext/opcache/Optimizer/pass1_5.c
+++ b/ext/opcache/Optimizer/pass1_5.c
@@ -10,6 +10,7 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
int i = 0;
zend_op *opline = op_array->opcodes;
zend_op *end = opline + op_array->last;
+ zend_bool collect_constants = (op_array == &script->main_op_array);
while (opline < end) {
switch (opline->opcode) {
@@ -357,7 +358,9 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
zval c;
if
(!zend_get_persistent_constant(Z_STRVAL(ZEND_OP2_LITERAL(opline)),
Z_STRLEN(ZEND_OP2_LITERAL(opline)), &c, 1 TSRMLS_CC)) {
- break;
+ if (!*constants ||
!zend_optimizer_get_collected_constant(*constants, &ZEND_OP2_LITERAL(opline),
&c)) {
+ break;
+ }
}
literal_dtor(&ZEND_OP2_LITERAL(opline));
ZEND_OP1_TYPE(opline) = IS_CONST;
@@ -388,6 +391,71 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
}
}
break;
+ case ZEND_DO_FCALL:
+ /* define("name", scalar); */
+ if (collect_constants &&
+ opline->extended_value == 2 &&
+ ZEND_OP1_TYPE(opline) == IS_CONST &&
+ Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING &&
+ Z_STRLEN(ZEND_OP1_LITERAL(opline)) ==
sizeof("define")-1 &&
+
zend_binary_strcasecmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)),
Z_STRLEN(ZEND_OP1_LITERAL(opline)), "define", sizeof("define")-1) == 0 &&
+ (opline-1)->opcode == ZEND_SEND_VAL &&
+ ZEND_OP1_TYPE(opline-1) == IS_CONST &&
+ (Z_TYPE(ZEND_OP1_LITERAL(opline-1)) <= IS_BOOL ||
+ Z_TYPE(ZEND_OP1_LITERAL(opline-1)) == IS_STRING) &&
+ (opline-2)->opcode == ZEND_SEND_VAL &&
+ ZEND_OP1_TYPE(opline-2) == IS_CONST &&
+ Z_TYPE(ZEND_OP1_LITERAL(opline-2)) == IS_STRING) {
+ zend_optimizer_collect_constant(constants,
&ZEND_OP1_LITERAL(opline-2), &ZEND_OP1_LITERAL(opline-1));
+ }
+ break;
+#if ZEND_EXTENSION_API_NO > PHP_5_2_X_API_NO
+ case ZEND_DECLARE_CONST:
+ if (collect_constants &&
+ Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING &&
+ (Z_TYPE(ZEND_OP2_LITERAL(opline)) <= IS_BOOL ||
+ Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING)) {
+ zend_optimizer_collect_constant(constants,
&ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline));
+ }
+ break;
+#endif
+
+ case ZEND_RETURN:
+#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
+ case ZEND_RETURN_BY_REF:
+#endif
+#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
+ case ZEND_GENERATOR_RETURN:
+#endif
+ case ZEND_EXIT:
+ case ZEND_THROW:
+ case ZEND_CATCH:
+ case ZEND_BRK:
+ case ZEND_CONT:
+#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
+ case ZEND_GOTO:
+#endif
+#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
+ case ZEND_FAST_CALL:
+ case ZEND_FAST_RET:
+#endif
+ case ZEND_JMP:
+ case ZEND_JMPZNZ:
+ case ZEND_JMPZ:
+ case ZEND_JMPNZ:
+ case ZEND_JMPZ_EX:
+ case ZEND_JMPNZ_EX:
+ case ZEND_FE_RESET:
+ case ZEND_FE_FETCH:
+ case ZEND_NEW:
+#if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
+ case ZEND_JMP_SET:
+#endif
+#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
+ case ZEND_JMP_SET_VAR:
+#endif
+ collect_constants = 0;
+ break;
}
opline++;
i++;
diff --git a/ext/opcache/Optimizer/zend_optimizer.c
b/ext/opcache/Optimizer/zend_optimizer.c
index b574ecc..92f5f4a 100644
--- a/ext/opcache/Optimizer/zend_optimizer.c
+++ b/ext/opcache/Optimizer/zend_optimizer.c
@@ -24,28 +24,47 @@
#include "zend_API.h"
#include "zend_constants.h"
#include "zend_execute.h"
+#include "zend_vm.h"
#define OPTIMIZATION_LEVEL \
ZCG(accel_directives).optimization_level
+static void zend_optimizer_zval_dtor_wrapper(zval *zvalue)
+{
+ zval_dtor(zvalue);
+}
+
+static void zend_optimizer_collect_constant(HashTable **constants, zval *name,
zval* value)
+{
+ zval val;
+
+ if (!*constants) {
+ *constants = emalloc(sizeof(HashTable));
+ zend_hash_init(*constants, 16, NULL, (void (*)(void
*))zend_optimizer_zval_dtor_wrapper, 0);
+ }
+ val = *value;
+ zval_copy_ctor(&val);
+ zend_hash_add(*constants, Z_STRVAL_P(name), Z_STRLEN_P(name)+1,
(void**)&val, sizeof(zval), NULL);
+}
+
+static int zend_optimizer_get_collected_constant(HashTable *constants, zval
*name, zval* value)
+{
+ zval *val;
+
+ if (zend_hash_find(constants, Z_STRVAL_P(name), Z_STRLEN_P(name)+1,
(void**)&val) == SUCCESS) {
+ *value = *val;
+ zval_copy_ctor(value);
+ return 1;
+ }
+ return 0;
+}
+
#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
int zend_optimizer_add_literal(zend_op_array *op_array, const zval *zv
TSRMLS_DC)
{
int i = op_array->last_literal;
op_array->last_literal++;
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
- {
- if (i >= CG(context).literals_size) {
- CG(context).literals_size += 16; /* FIXME */
- op_array->literals =
(zend_literal*)erealloc(op_array->literals, CG(context).literals_size *
sizeof(zend_literal));
- }
- }
-#else
- if (i >= op_array->size_literal) {
- op_array->size_literal += 16; /* FIXME */
- op_array->literals =
(zend_literal*)erealloc(op_array->literals, op_array->size_literal *
sizeof(zend_literal));
- }
-#endif
+ op_array->literals = (zend_literal*)erealloc(op_array->literals,
op_array->last_literal * sizeof(zend_literal));
op_array->literals[i].constant = *zv;
Z_SET_REFCOUNT(op_array->literals[i].constant, 2);
Z_SET_ISREF(op_array->literals[i].constant);
@@ -92,7 +111,9 @@ int zend_optimizer_add_literal(zend_op_array *op_array,
const zval *zv TSRMLS_DC
#include "Optimizer/block_pass.c"
#include "Optimizer/optimize_temp_vars_5.c"
-void zend_optimizer(zend_op_array *op_array TSRMLS_DC)
+static void zend_optimize(zend_op_array *op_array,
+ zend_persistent_script *script,
+ HashTable **constants TSRMLS_DC)
{
if (op_array->type == ZEND_EVAL_CODE ||
(op_array->fn_flags & ZEND_ACC_INTERACTIVE)) {
@@ -137,3 +158,133 @@ void zend_optimizer(zend_op_array *op_array TSRMLS_DC)
*/
#include "Optimizer/pass10.c"
}
+
+static void zend_accel_optimize(zend_op_array *op_array,
+ zend_persistent_script *script,
+ HashTable **constants TSRMLS_DC)
+{
+ zend_op *opline, *end;
+
+ /* Revert pass_two() */
+ opline = op_array->opcodes;
+ end = opline + op_array->last;
+ while (opline < end) {
+#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
+ if (opline->op1_type == IS_CONST) {
+ opline->op1.constant = opline->op1.literal -
op_array->literals;
+ }
+ if (opline->op2_type == IS_CONST) {
+ opline->op2.constant = opline->op2.literal -
op_array->literals;
+ }
+#endif
+ switch (opline->opcode) {
+ case ZEND_JMP:
+#if ZEND_EXTENSION_API_NO > PHP_5_2_X_API_NO
+ case ZEND_GOTO:
+#endif
+#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
+ case ZEND_FAST_CALL:
+#endif
+ ZEND_OP1(opline).opline_num =
ZEND_OP1(opline).jmp_addr - op_array->opcodes;
+ break;
+ case ZEND_JMPZ:
+ case ZEND_JMPNZ:
+ case ZEND_JMPZ_EX:
+ case ZEND_JMPNZ_EX:
+#if ZEND_EXTENSION_API_NO > PHP_5_2_X_API_NO
+ case ZEND_JMP_SET:
+#endif
+#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
+ case ZEND_JMP_SET_VAR:
+#endif
+ ZEND_OP2(opline).opline_num =
ZEND_OP2(opline).jmp_addr - op_array->opcodes;
+ break;
+ }
+ opline++;
+ }
+
+ /* Do actual optimizations */
+ zend_optimize(op_array, script, constants TSRMLS_CC);
+
+ /* Redo pass_two() */
+ opline = op_array->opcodes;
+ end = opline + op_array->last;
+ while (opline < end) {
+#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
+ if (opline->op1_type == IS_CONST) {
+ opline->op1.zv =
&op_array->literals[opline->op1.constant].constant;
+ }
+ if (opline->op2_type == IS_CONST) {
+ opline->op2.zv =
&op_array->literals[opline->op2.constant].constant;
+ }
+#endif
+ switch (opline->opcode) {
+ case ZEND_JMP:
+#if ZEND_EXTENSION_API_NO > PHP_5_2_X_API_NO
+ case ZEND_GOTO:
+#endif
+#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
+ case ZEND_FAST_CALL:
+#endif
+ ZEND_OP1(opline).jmp_addr =
&op_array->opcodes[ZEND_OP1(opline).opline_num];
+ break;
+ case ZEND_JMPZ:
+ case ZEND_JMPNZ:
+ case ZEND_JMPZ_EX:
+ case ZEND_JMPNZ_EX:
+#if ZEND_EXTENSION_API_NO > PHP_5_2_X_API_NO
+ case ZEND_JMP_SET:
+#endif
+#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
+ case ZEND_JMP_SET_VAR:
+#endif
+ ZEND_OP2(opline).jmp_addr =
&op_array->opcodes[ZEND_OP2(opline).opline_num];
+ break;
+ }
+ ZEND_VM_SET_OPCODE_HANDLER(opline);
+ opline++;
+ }
+}
+
+int zend_accel_script_optimize(zend_persistent_script *script TSRMLS_DC)
+{
+ Bucket *p, *q;
+ HashTable *constants = NULL;
+
+ zend_accel_optimize(&script->main_op_array, script, &constants
TSRMLS_CC);
+
+ p = script->function_table.pListHead;
+ while (p) {
+ zend_op_array *op_array = (zend_op_array*)p->pData;
+ zend_accel_optimize(op_array, script, &constants TSRMLS_CC);
+ p = p->pListNext;
+ }
+
+ p = script->class_table.pListHead;
+ while (p) {
+ zend_class_entry *ce = (zend_class_entry*)p->pDataPtr;
+ q = ce->function_table.pListHead;
+ while (q) {
+ zend_op_array *op_array = (zend_op_array*)q->pData;
+ if (op_array->scope == ce) {
+ zend_accel_optimize(op_array, script,
&constants TSRMLS_CC);
+ } else if (op_array->type == ZEND_USER_FUNCTION) {
+ zend_op_array *orig_op_array;
+ if
(zend_hash_find(&op_array->scope->function_table, q->arKey, q->nKeyLength,
(void**)&orig_op_array) == SUCCESS) {
+ HashTable *ht =
op_array->static_variables;
+ *op_array = *orig_op_array;
+ op_array->static_variables = ht;
+ }
+ }
+ q = q->pListNext;
+ }
+ p = p->pListNext;
+ }
+
+ if (constants) {
+ zend_hash_destroy(constants);
+ efree(constants);
+ }
+
+ return 1;
+}
diff --git a/ext/opcache/Optimizer/zend_optimizer.h
b/ext/opcache/Optimizer/zend_optimizer.h
index 98275a2..1775994 100644
--- a/ext/opcache/Optimizer/zend_optimizer.h
+++ b/ext/opcache/Optimizer/zend_optimizer.h
@@ -44,6 +44,4 @@
#define DEFAULT_OPTIMIZATION_LEVEL "0xFFFFFFFF"
-void zend_optimizer(zend_op_array *op_array TSRMLS_DC);
-
#endif
diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c
index b62f245..9a6c763 100644
--- a/ext/opcache/ZendAccelerator.c
+++ b/ext/opcache/ZendAccelerator.c
@@ -1126,6 +1126,10 @@ static zend_persistent_script
*cache_script_in_shared_memory(zend_persistent_scr
return new_persistent_script;
}
+ if (!zend_accel_script_optimize(new_persistent_script TSRMLS_CC)) {
+ return new_persistent_script;
+ }
+
/* exclusive lock */
zend_shared_alloc_lock(TSRMLS_C);
@@ -2731,19 +2735,6 @@ void accelerator_shm_read_unlock(TSRMLS_D)
}
}
-static void accel_op_array_handler(zend_op_array *op_array)
-{
- TSRMLS_FETCH();
-
- if (ZCG(enabled) &&
- accel_startup_ok &&
- ZCSG(accelerator_enabled) &&
- !ZSMMG(memory_exhausted) &&
- !ZCSG(restart_pending)) {
- zend_optimizer(op_array TSRMLS_CC);
- }
-}
-
ZEND_EXT_API zend_extension zend_extension_entry = {
ACCELERATOR_PRODUCT_NAME, /* name */
ACCELERATOR_VERSION, /* version */
@@ -2755,7 +2746,7 @@ ZEND_EXT_API zend_extension zend_extension_entry = {
accel_activate, /*
per-script activation */
accel_deactivate, /*
per-script deactivation */
NULL,
/* message handler */
- accel_op_array_handler, /* op_array
handler */
+ NULL,
/* op_array handler */
NULL,
/* extended statement handler */
NULL,
/* extended fcall begin handler */
NULL,
/* extended fcall end handler */
diff --git a/ext/opcache/ZendAccelerator.h b/ext/opcache/ZendAccelerator.h
index 85f9570..063c951 100644
--- a/ext/opcache/ZendAccelerator.h
+++ b/ext/opcache/ZendAccelerator.h
@@ -319,6 +319,7 @@ extern char *zps_api_failure_reason;
void zend_accel_schedule_restart(zend_accel_restart_reason reason TSRMLS_DC);
void zend_accel_schedule_restart_if_necessary(zend_accel_restart_reason reason
TSRMLS_DC);
int zend_accel_invalidate(const char *filename, int filename_len, zend_bool
force TSRMLS_DC);
+int zend_accel_script_optimize(zend_persistent_script *persistent_script
TSRMLS_DC);
int accelerator_shm_read_lock(TSRMLS_D);
void accelerator_shm_read_unlock(TSRMLS_D);
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php