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) {
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;
}
}
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++;
#include "zend_API.h"\r
#include "zend_constants.h"\r
#include "zend_execute.h"\r
+#include "zend_vm.h"\r
\r
#define OPTIMIZATION_LEVEL \\r
ZCG(accel_directives).optimization_level\r
\r
+static void zend_optimizer_zval_dtor_wrapper(zval *zvalue)\r
+{\r
+ zval_dtor(zvalue);\r
+}\r
+\r
+static void zend_optimizer_collect_constant(HashTable **constants, zval *name, zval* value)\r
+{\r
+ zval val;\r
+\r
+ if (!*constants) {\r
+ *constants = emalloc(sizeof(HashTable));\r
+ zend_hash_init(*constants, 16, NULL, (void (*)(void *))zend_optimizer_zval_dtor_wrapper, 0);\r
+ }\r
+ val = *value;\r
+ zval_copy_ctor(&val);\r
+ zend_hash_add(*constants, Z_STRVAL_P(name), Z_STRLEN_P(name)+1, (void**)&val, sizeof(zval), NULL);\r
+}\r
+\r
+static int zend_optimizer_get_collected_constant(HashTable *constants, zval *name, zval* value)\r
+{\r
+ zval *val;\r
+\r
+ if (zend_hash_find(constants, Z_STRVAL_P(name), Z_STRLEN_P(name)+1, (void**)&val) == SUCCESS) {\r
+ *value = *val;\r
+ zval_copy_ctor(value);\r
+ return 1;\r
+ }\r
+ return 0;\r
+}\r
+\r
#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO\r
int zend_optimizer_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC)\r
{\r
int i = op_array->last_literal;\r
op_array->last_literal++;\r
-#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO\r
- {\r
- if (i >= CG(context).literals_size) {\r
- CG(context).literals_size += 16; /* FIXME */\r
- op_array->literals = (zend_literal*)erealloc(op_array->literals, CG(context).literals_size * sizeof(zend_literal));\r
- }\r
- }\r
-#else\r
- if (i >= op_array->size_literal) {\r
- op_array->size_literal += 16; /* FIXME */\r
- op_array->literals = (zend_literal*)erealloc(op_array->literals, op_array->size_literal * sizeof(zend_literal));\r
- }\r
-#endif\r
+ op_array->literals = (zend_literal*)erealloc(op_array->literals, op_array->last_literal * sizeof(zend_literal));\r
op_array->literals[i].constant = *zv;\r
Z_SET_REFCOUNT(op_array->literals[i].constant, 2);\r
Z_SET_ISREF(op_array->literals[i].constant);\r
#include "Optimizer/block_pass.c"\r
#include "Optimizer/optimize_temp_vars_5.c"\r
\r
-void zend_optimizer(zend_op_array *op_array TSRMLS_DC)\r
+static void zend_optimize(zend_op_array *op_array,\r
+ zend_persistent_script *script,\r
+ HashTable **constants TSRMLS_DC)\r
{\r
if (op_array->type == ZEND_EVAL_CODE ||\r
(op_array->fn_flags & ZEND_ACC_INTERACTIVE)) {\r
*/\r
#include "Optimizer/pass10.c"\r
}\r
+\r
+static void zend_accel_optimize(zend_op_array *op_array,\r
+ zend_persistent_script *script,\r
+ HashTable **constants TSRMLS_DC)\r
+{\r
+ zend_op *opline, *end;\r
+\r
+ /* Revert pass_two() */\r
+ opline = op_array->opcodes;\r
+ end = opline + op_array->last;\r
+ while (opline < end) {\r
+#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO\r
+ if (opline->op1_type == IS_CONST) {\r
+ opline->op1.constant = opline->op1.literal - op_array->literals;\r
+ }\r
+ if (opline->op2_type == IS_CONST) {\r
+ opline->op2.constant = opline->op2.literal - op_array->literals;\r
+ }\r
+#endif\r
+ switch (opline->opcode) {\r
+ case ZEND_JMP:\r
+#if ZEND_EXTENSION_API_NO > PHP_5_2_X_API_NO\r
+ case ZEND_GOTO:\r
+#endif\r
+#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO\r
+ case ZEND_FAST_CALL:\r
+#endif\r
+ ZEND_OP1(opline).opline_num = ZEND_OP1(opline).jmp_addr - op_array->opcodes;\r
+ break;\r
+ case ZEND_JMPZ:\r
+ case ZEND_JMPNZ:\r
+ case ZEND_JMPZ_EX:\r
+ case ZEND_JMPNZ_EX:\r
+#if ZEND_EXTENSION_API_NO > PHP_5_2_X_API_NO\r
+ case ZEND_JMP_SET:\r
+#endif\r
+#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO\r
+ case ZEND_JMP_SET_VAR:\r
+#endif\r
+ ZEND_OP2(opline).opline_num = ZEND_OP2(opline).jmp_addr - op_array->opcodes;\r
+ break;\r
+ }\r
+ opline++;\r
+ }\r
+\r
+ /* Do actual optimizations */\r
+ zend_optimize(op_array, script, constants TSRMLS_CC); \r
+ \r
+ /* Redo pass_two() */\r
+ opline = op_array->opcodes;\r
+ end = opline + op_array->last;\r
+ while (opline < end) {\r
+#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO\r
+ if (opline->op1_type == IS_CONST) {\r
+ opline->op1.zv = &op_array->literals[opline->op1.constant].constant;\r
+ }\r
+ if (opline->op2_type == IS_CONST) {\r
+ opline->op2.zv = &op_array->literals[opline->op2.constant].constant;\r
+ }\r
+#endif\r
+ switch (opline->opcode) {\r
+ case ZEND_JMP:\r
+#if ZEND_EXTENSION_API_NO > PHP_5_2_X_API_NO\r
+ case ZEND_GOTO:\r
+#endif\r
+#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO\r
+ case ZEND_FAST_CALL:\r
+#endif\r
+ ZEND_OP1(opline).jmp_addr = &op_array->opcodes[ZEND_OP1(opline).opline_num];\r
+ break;\r
+ case ZEND_JMPZ:\r
+ case ZEND_JMPNZ:\r
+ case ZEND_JMPZ_EX:\r
+ case ZEND_JMPNZ_EX:\r
+#if ZEND_EXTENSION_API_NO > PHP_5_2_X_API_NO\r
+ case ZEND_JMP_SET:\r
+#endif\r
+#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO\r
+ case ZEND_JMP_SET_VAR:\r
+#endif\r
+ ZEND_OP2(opline).jmp_addr = &op_array->opcodes[ZEND_OP2(opline).opline_num];\r
+ break;\r
+ }\r
+ ZEND_VM_SET_OPCODE_HANDLER(opline);\r
+ opline++;\r
+ }\r
+}\r
+\r
+int zend_accel_script_optimize(zend_persistent_script *script TSRMLS_DC)\r
+{\r
+ Bucket *p, *q;\r
+ HashTable *constants = NULL;\r
+\r
+ zend_accel_optimize(&script->main_op_array, script, &constants TSRMLS_CC);\r
+\r
+ p = script->function_table.pListHead;\r
+ while (p) {\r
+ zend_op_array *op_array = (zend_op_array*)p->pData;\r
+ zend_accel_optimize(op_array, script, &constants TSRMLS_CC);\r
+ p = p->pListNext;\r
+ }\r
+\r
+ p = script->class_table.pListHead;\r
+ while (p) {\r
+ zend_class_entry *ce = (zend_class_entry*)p->pDataPtr;\r
+ q = ce->function_table.pListHead;\r
+ while (q) {\r
+ zend_op_array *op_array = (zend_op_array*)q->pData;\r
+ if (op_array->scope == ce) {\r
+ zend_accel_optimize(op_array, script, &constants TSRMLS_CC);\r
+ } else if (op_array->type == ZEND_USER_FUNCTION) {\r
+ zend_op_array *orig_op_array;\r
+ if (zend_hash_find(&op_array->scope->function_table, q->arKey, q->nKeyLength, (void**)&orig_op_array) == SUCCESS) {\r
+ HashTable *ht = op_array->static_variables;\r
+ *op_array = *orig_op_array;\r
+ op_array->static_variables = ht;\r
+ }\r
+ }\r
+ q = q->pListNext;\r
+ }\r
+ p = p->pListNext;\r
+ }\r
+\r
+ if (constants) {\r
+ zend_hash_destroy(constants);\r
+ efree(constants);\r
+ }\r
+\r
+ return 1;\r
+}\r
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);
}
}
-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 */
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 */