}
break;
- case ZEND_INIT_FCALL_BY_NAME:
- if (opline->extended_value == 0 /* not method */ &&
- ZEND_OP1_TYPE(opline) == IS_UNUSED &&
- ZEND_OP2_TYPE(opline) == IS_CONST) {
- if ((opline + 1)->opcode == ZEND_DO_FCALL_BY_NAME &&
- (opline + 1)->extended_value == 0) {
- (opline + 1)->opcode = ZEND_DO_FCALL;
- COPY_NODE((opline + 1)->op1, opline->op2);
- zend_str_tolower(Z_STRVAL(ZEND_OP1_LITERAL(opline + 1)), Z_STRLEN(ZEND_OP1_LITERAL(opline + 1)));
+ 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
- Z_HASH_P(&ZEND_OP1_LITERAL(opline + 1)) = zend_hash_func(Z_STRVAL(ZEND_OP1_LITERAL(opline + 1)), Z_STRLEN(ZEND_OP1_LITERAL(opline + 1)) + 1);
- op_array->literals[(opline + 1)->op1.constant].cache_slot = op_array->last_cache_slot++;
+ case ZEND_RETURN_BY_REF:
#endif
- MAKE_NOP(opline);
- }
- }
+#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;
+
+ #if ZEND_EXTENSION_API_NO >= PHP_5_5_X_API_NO
+ case ZEND_FETCH_R:
+ case ZEND_FETCH_W:
+ case ZEND_FETCH_RW:
+ case ZEND_FETCH_FUNC_ARG:
+ case ZEND_FETCH_IS:
+ case ZEND_FETCH_UNSET:
+ if (opline != op_array->opcodes &&
+ (opline-1)->opcode == ZEND_BEGIN_SILENCE &&
+ (opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_LOCAL &&
+ opline->op1_type == IS_CONST &&
+ opline->op2_type == IS_UNUSED &&
+ Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING &&
+ (Z_STRLEN(ZEND_OP1_LITERAL(opline)) != sizeof("this")-1 ||
+ memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)), "this", sizeof("this")) != 0)) {
+
+ int var = opline->result.var;
+ int level = 0;
+ zend_op *op = opline + 1;
+
+ while (op < end) {
+ if (op->opcode == ZEND_BEGIN_SILENCE) {
+ level++;
+ } else if (op->opcode == ZEND_END_SILENCE) {
+ if (level == 0) {
+ break;
+ } else {
+ level--;
+ }
+ }
+ if (op->op1_type == IS_VAR && op->op1.var == var) {
+ op->op1_type = IS_CV;
+ op->op1.var = zend_optimizer_lookup_cv(op_array,
+ Z_STRVAL(ZEND_OP1_LITERAL(opline)),
+ Z_STRLEN(ZEND_OP1_LITERAL(opline)));
+ MAKE_NOP(opline);
+ break;
+ } else if (op->op2_type == IS_VAR && op->op2.var == var) {
+ op->op2_type = IS_CV;
+ op->op2.var = zend_optimizer_lookup_cv(op_array,
+ Z_STRVAL(ZEND_OP1_LITERAL(opline)),
+ Z_STRLEN(ZEND_OP1_LITERAL(opline)));
+ MAKE_NOP(opline);
+ break;
+ }
+ op++;
+ }
+ }
+ break;
+ #endif
+
}
opline++;
i++;
#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_5_X_API_NO\r
+ static int zend_optimizer_lookup_cv(zend_op_array *op_array, char* name, int name_len)\r
+ {\r
+ int i = 0;\r
+ ulong hash_value = zend_inline_hash_func(name, name_len+1);\r
+ \r
+ while (i < op_array->last_var) {\r
+ if (op_array->vars[i].name == name ||\r
+ (op_array->vars[i].hash_value == hash_value &&\r
+ op_array->vars[i].name_len == name_len &&\r
+ memcmp(op_array->vars[i].name, name, name_len) == 0)) {\r
+ return i;\r
+ }\r
+ i++;\r
+ }\r
+ i = op_array->last_var;\r
+ op_array->last_var++;\r
+ op_array->vars = erealloc(op_array->vars, op_array->last_var * sizeof(zend_compiled_variable));\r
+ if (IS_INTERNED(name)) {\r
+ op_array->vars[i].name = name;\r
+ } else {\r
+ op_array->vars[i].name = estrndup(name, name_len);\r
+ }\r
+ op_array->vars[i].name_len = name_len;\r
+ op_array->vars[i].hash_value = hash_value;\r
+ return i;\r
+ }\r
+ #endif\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