Commit:    2bfb523f45cc0c64b5b63f9ad7fb6ec7c701d695
Author:    Dmitry Stogov <dmi...@zend.com>         Thu, 18 Apr 2013 10:48:16 
+0400
Parents:   36d343c0c44da754957cfcb9b9544acdf0a9e229
Branches:  master

Link:       
http://git.php.net/?p=php-src.git;a=commitdiff;h=2bfb523f45cc0c64b5b63f9ad7fb6ec7c701d695

Log:
Merge identical constants (and related cache_slots) in op_array->literals table.

Changed paths:
  A  ext/opcache/Optimizer/compact_literals.c
  M  ext/opcache/Optimizer/zend_optimizer.c
  M  ext/opcache/Optimizer/zend_optimizer.h
  A  ext/opcache/tests/compact_literals.phpt

diff --git a/ext/opcache/Optimizer/compact_literals.c 
b/ext/opcache/Optimizer/compact_literals.c
new file mode 100644
index 0000000..b292413
--- /dev/null
+++ b/ext/opcache/Optimizer/compact_literals.c
@@ -0,0 +1,481 @@
+/* pass 11
+ * - compact literals table
+ */
+#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
+
+#define DEBUG_COMPACT_LITERALS 0
+
+#define LITERAL_VALUE                        0x0100
+#define LITERAL_FUNC                         0x0200
+#define LITERAL_CLASS                        0x0300
+#define LITERAL_CONST                        0x0400
+#define LITERAL_CLASS_CONST                  0x0500
+#define LITERAL_STATIC_METHOD                0x0600
+#define LITERAL_STATIC_PROPERTY              0x0700
+#define LITERAL_METHOD                       0x0800
+#define LITERAL_PROPERTY                     0x0900
+
+#define LITERAL_EX_CLASS                     0x4000
+#define LITERAL_EX_OBJ                       0x2000
+#define LITERAL_MAY_MERGE                    0x1000
+#define LITERAL_KIND_MASK                    0x0f00
+#define LITERAL_NUM_RELATED_MASK             0x000f
+#define LITERAL_NUM_SLOTS_MASK               0x00f0
+#define LITERAL_NUM_SLOTS_SHIFT              4
+
+#define LITERAL_NUM_RELATED(info) (info & LITERAL_NUM_RELATED_MASK)
+#define LITERAL_NUM_SLOTS(info)   ((info & LITERAL_NUM_SLOTS_MASK) >> 
LITERAL_NUM_SLOTS_SHIFT)
+
+typedef struct _literal_info {
+       zend_uint  flags; /* bitmask (see defines above) */
+       union {
+               int    num;   /* variable number or class name literal number */
+       } u;
+} literal_info;
+
+#define LITERAL_FLAGS(kind, slots, related) \
+       ((kind) | ((slots) << LITERAL_NUM_SLOTS_SHIFT) | (related))
+
+#define LITERAL_INFO(n, kind, merge, slots, related) do { \
+               info[n].flags = (((merge) ? LITERAL_MAY_MERGE : 0) | 
LITERAL_FLAGS(kind, slots, related)); \
+       } while (0)
+
+#define LITERAL_INFO_CLASS(n, kind, merge, slots, related, _num) do { \
+               info[n].flags = (LITERAL_EX_CLASS | ((merge) ? 
LITERAL_MAY_MERGE : 0) | LITERAL_FLAGS(kind, slots, related)); \
+               info[n].u.num = (_num); \
+       } while (0)
+
+#define LITERAL_INFO_OBJ(n, kind, merge, slots, related, _num) do { \
+               info[n].flags = (LITERAL_EX_OBJ | ((merge) ? LITERAL_MAY_MERGE 
: 0) | LITERAL_FLAGS(kind, slots, related)); \
+               info[n].u.num = (_num); \
+       } while (0)
+
+static void optimizer_literal_obj_info(literal_info   *info,
+                                       zend_uchar      op_type,
+                                       znode_op        op,
+                                       int             constant,
+                                       zend_uint       kind,
+                                       zend_uint       slots,
+                                       zend_uint       related,
+                                       zend_op_array  *op_array)
+{
+       /* For now we merge only $this object properties and methods.
+        * In general it's also possible to do it for any CV variable as well,
+        * but it would require complex dataflow and/or type analysis.
+        */
+       if (Z_TYPE(op_array->literals[constant].constant) == IS_STRING &&
+           op_type == IS_UNUSED) {
+               LITERAL_INFO_OBJ(constant, kind, 1, slots, related, 
op_array->this_var);
+       } else {
+               LITERAL_INFO(constant, kind, 0, slots, related);
+       }
+}
+
+static void optimizer_literal_class_info(literal_info   *info,
+                                         zend_uchar      op_type,
+                                         znode_op        op,
+                                         int             constant,
+                                         zend_uint       kind,
+                                         zend_uint       slots,
+                                         zend_uint       related,
+                                         zend_op_array  *op_array)
+{
+       if (op_type == IS_CONST) {
+               LITERAL_INFO_CLASS(constant, kind, 1, slots, related, 
op.constant);
+       } else {
+               LITERAL_INFO(constant, kind, 0, slots, related);
+       }
+}
+
+static void optimizer_compact_literals(zend_op_array *op_array TSRMLS_DC)
+{
+       zend_op *opline, *end;
+       int i, j, n, *pos, *map, cache_slots;
+       ulong h;
+       literal_info *info;
+       int l_null = -1;
+       int l_false = -1;
+       int l_true = -1;
+       HashTable hash;
+       char *key;
+       int key_len;
+
+       if (op_array->last_literal) {
+               info = (literal_info*)ecalloc(op_array->last_literal, 
sizeof(literal_info));
+
+           /* Mark literals of specific types */
+               opline = op_array->opcodes;
+               end = opline + op_array->last;
+               while (opline < end) {
+                       switch (opline->opcode) {
+                               case ZEND_DO_FCALL:
+                                       LITERAL_INFO(opline->op1.constant, 
LITERAL_FUNC, 1, 1, 1);
+                                       break;
+                               case ZEND_INIT_FCALL_BY_NAME:
+                                       if (ZEND_OP2_TYPE(opline) == IS_CONST) {
+                                               
LITERAL_INFO(opline->op2.constant, LITERAL_FUNC, 1, 1, 2);
+                                       }
+                                       break;
+                               case ZEND_INIT_NS_FCALL_BY_NAME:
+                                       LITERAL_INFO(opline->op2.constant, 
LITERAL_FUNC, 1, 1, 3);
+                                       break;
+                               case ZEND_INIT_METHOD_CALL:
+                                       if (ZEND_OP2_TYPE(opline) == IS_CONST) {
+                                               optimizer_literal_obj_info(
+                                                       info,
+                                                       opline->op1_type,
+                                                       opline->op1,
+                                                       opline->op2.constant,
+                                                       LITERAL_METHOD, 2, 2,
+                                                       op_array);
+                                       }
+                                       break;
+                               case ZEND_INIT_STATIC_METHOD_CALL:
+                                       if (ZEND_OP1_TYPE(opline) == IS_CONST) {
+                                               
LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 1, 1, 2);
+                                       }
+                                       if (ZEND_OP2_TYPE(opline) == IS_CONST) {
+                                               optimizer_literal_class_info(
+                                                       info,
+                                                       opline->op1_type,
+                                                       opline->op1,
+                                                       opline->op2.constant,
+                                                       LITERAL_STATIC_METHOD, 
(ZEND_OP1_TYPE(opline) == IS_CONST) ? 1 : 2, 2,
+                                                       op_array);
+                                       }
+                                       break;
+                               case ZEND_CATCH:
+                                       LITERAL_INFO(opline->op1.constant, 
LITERAL_CLASS, 1, 1, 2);
+                                       break;
+                               case ZEND_FETCH_CONSTANT:
+                                       if (ZEND_OP1_TYPE(opline) == IS_UNUSED) 
{
+                                               if ((opline->extended_value & 
(IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) == 
(IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) {
+                                                       
LITERAL_INFO(opline->op2.constant, LITERAL_CONST, 1, 1, 5);
+                                               } else {
+                                                       
LITERAL_INFO(opline->op2.constant, LITERAL_CONST, 1, 1, 3);
+                                               }
+                                       } else {
+                                               if (ZEND_OP1_TYPE(opline) == 
IS_CONST) {
+                                                       
LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 1, 1, 2);
+                                               }
+                                               optimizer_literal_class_info(
+                                                       info,
+                                                       opline->op1_type,
+                                                       opline->op1,
+                                                       opline->op2.constant,
+                                                       LITERAL_CLASS_CONST, 
(ZEND_OP1_TYPE(opline) == IS_CONST) ? 1 : 2, 1,
+                                                       op_array);
+                                       }
+                                       break;
+                               case ZEND_FETCH_R:
+                               case ZEND_FETCH_W:
+                               case ZEND_FETCH_RW:
+                               case ZEND_FETCH_IS:
+                               case ZEND_FETCH_UNSET:
+                               case ZEND_FETCH_FUNC_ARG:
+                               case ZEND_UNSET_VAR:
+                               case ZEND_ISSET_ISEMPTY_VAR:
+                                       if (ZEND_OP2_TYPE(opline) == IS_UNUSED) 
{
+                                               if (ZEND_OP1_TYPE(opline) == 
IS_CONST) {
+                                                       
LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 1, 0, 1);
+                                               }
+                                       } else {
+                                               if (ZEND_OP2_TYPE(opline) == 
IS_CONST) {
+                                                       
LITERAL_INFO(opline->op2.constant, LITERAL_CLASS, 1, 1, 2);
+                                               }
+                                               if (ZEND_OP1_TYPE(opline) == 
IS_CONST) {
+                                                       
optimizer_literal_class_info(
+                                                               info,
+                                                               
opline->op2_type,
+                                                               opline->op2,
+                                                               
opline->op1.constant,
+                                                               
LITERAL_STATIC_PROPERTY, 2, 1,
+                                                               op_array);
+                                               }
+                                       }
+                                       break;
+                               case ZEND_FETCH_CLASS:
+                               case ZEND_ADD_INTERFACE:
+                               case ZEND_ADD_TRAIT:
+                                       if (ZEND_OP2_TYPE(opline) == IS_CONST) {
+                                               
LITERAL_INFO(opline->op2.constant, LITERAL_CLASS, 1, 1, 2);
+                                       }
+                                       break;
+                               case ZEND_ASSIGN_OBJ:
+                               case ZEND_FETCH_OBJ_R:
+                               case ZEND_FETCH_OBJ_W:
+                               case ZEND_FETCH_OBJ_RW:
+                               case ZEND_FETCH_OBJ_IS:
+                               case ZEND_FETCH_OBJ_UNSET:
+                               case ZEND_FETCH_OBJ_FUNC_ARG:
+                               case ZEND_UNSET_OBJ:
+                               case ZEND_PRE_INC_OBJ:
+                               case ZEND_PRE_DEC_OBJ:
+                               case ZEND_POST_INC_OBJ:
+                               case ZEND_POST_DEC_OBJ:
+                               case ZEND_ISSET_ISEMPTY_PROP_OBJ:
+                                       if (ZEND_OP2_TYPE(opline) == IS_CONST) {
+                                               optimizer_literal_obj_info(
+                                                       info,
+                                                       opline->op1_type,
+                                                       opline->op1,
+                                                       opline->op2.constant,
+                                                       LITERAL_PROPERTY, 2, 1,
+                                                       op_array);
+                                       }
+                                       break;
+                               case ZEND_ASSIGN_ADD:
+                               case ZEND_ASSIGN_SUB:
+                               case ZEND_ASSIGN_MUL:
+                               case ZEND_ASSIGN_DIV:
+                               case ZEND_ASSIGN_MOD:
+                               case ZEND_ASSIGN_SL:
+                               case ZEND_ASSIGN_SR:
+                               case ZEND_ASSIGN_CONCAT:
+                               case ZEND_ASSIGN_BW_OR:
+                               case ZEND_ASSIGN_BW_AND:
+                               case ZEND_ASSIGN_BW_XOR:
+                                       if (ZEND_OP2_TYPE(opline) == IS_CONST) {
+                                               if (opline->extended_value == 
ZEND_ASSIGN_OBJ) {
+                                                       
optimizer_literal_obj_info(
+                                                               info,
+                                                               
opline->op1_type,
+                                                               opline->op1,
+                                                               
opline->op2.constant,
+                                                               
LITERAL_PROPERTY, 2, 1,
+                                                               op_array);
+                                               } else {
+                                                       
LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 1, 0, 1);
+                                               }
+                                       }
+                                       break;
+                               default:
+                                       if (ZEND_OP1_TYPE(opline) == IS_CONST) {
+                                               
LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 1, 0, 1);
+                                       }
+                                       if (ZEND_OP2_TYPE(opline) == IS_CONST) {
+                                               
LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 1, 0, 1);
+                                       }
+                                       break;
+                       }
+                       opline++;
+               }
+
+#if DEBUG_COMPACT_LITERALS
+               {
+                       int i, use_copy;
+                       fprintf(stderr, "File %s func %s\n", op_array->filename,
+                                       op_array->function_name? 
op_array->function_name : "main");
+                       fprintf(stderr, "Literlas table size %d\n", 
op_array->last_literal);
+
+                       for (i = 0; i < op_array->last_literal; i++) {
+                               zval zv = op_array->literals[i].constant;
+                               
zend_make_printable_zval(&op_array->literals[i].constant, &zv, &use_copy);
+                               fprintf(stderr, "Literal %d, val (%d):%s\n", i, 
Z_STRLEN(zv), Z_STRVAL(zv));
+                               if (use_copy) {
+                                       zval_dtor(&zv);
+                               }
+                       }
+                       fflush(stderr);
+               }
+#endif
+
+               /* Merge equal constants */
+               j = 0; cache_slots = 0;
+               zend_hash_init(&hash, 16, NULL, NULL, 0);
+               map = (int*)ecalloc(op_array->last_literal, sizeof(int));
+               for (i = 0; i < op_array->last_literal; i++) {
+                       if (!info[i].flags) {
+                               /* unsed literal */
+                               zval_dtor(&op_array->literals[i].constant);
+                               continue;
+                       }
+                       switch (Z_TYPE(op_array->literals[i].constant)) {
+                               case IS_NULL:
+                                       if (l_null < 0) {
+                                               l_null = j;
+                                               if (i != j) {
+                                                       op_array->literals[j] = 
op_array->literals[i];
+                                                       info[j] = info[i];
+                                               }
+                                               j++;
+                                       }
+                                       map[i] = l_null;
+                                       break;
+                               case IS_BOOL:
+                                       if 
(Z_LVAL(op_array->literals[i].constant)) {
+                                               if (l_true < 0) {
+                                                       l_true = j;
+                                                       if (i != j) {
+                                                               
op_array->literals[j] = op_array->literals[i];
+                                                               info[j] = 
info[i];
+                                                       }
+                                                       j++;
+                                               }
+                                               map[i] = l_true;
+                                       } else {
+                                               if (l_false < 0) {
+                                                       l_false = j;
+                                                       if (i != j) {
+                                                               
op_array->literals[j] = op_array->literals[i];
+                                                               info[j] = 
info[i];
+                                                       }
+                                                       j++;
+                                               }
+                                               map[i] = l_false;
+                                       }
+                                       break;
+                               case IS_LONG:
+                                       if (zend_hash_index_find(&hash, 
Z_LVAL(op_array->literals[i].constant), (void**)&pos) == SUCCESS) {
+                                               map[i] = *pos;
+                                       } else {
+                                               map[i] = j;
+                                               zend_hash_index_update(&hash, 
Z_LVAL(op_array->literals[i].constant), (void**)&j, sizeof(int), NULL);
+                                               if (i != j) {
+                                                       op_array->literals[j] = 
op_array->literals[i];
+                                                       info[j] = info[i];
+                                               }
+                                               j++;
+                                       }
+                                       break;
+                               case IS_DOUBLE:
+                                       if (zend_hash_find(&hash, 
(char*)&Z_DVAL(op_array->literals[i].constant), sizeof(double), (void**)&pos) 
== SUCCESS) {
+                                               map[i] = *pos;
+                                       } else {
+                                               map[i] = j;
+                                               zend_hash_add(&hash, 
(char*)&Z_DVAL(op_array->literals[i].constant), sizeof(double), (void**)&j, 
sizeof(int), NULL);
+                                               if (i != j) {
+                                                       op_array->literals[j] = 
op_array->literals[i];
+                                                       info[j] = info[i];
+                                               }
+                                               j++;
+                                       }
+                                       break;
+                               case IS_STRING:
+                               case IS_CONSTANT:
+                                       if (info[i].flags & LITERAL_MAY_MERGE) {
+                                               if (info[i].flags & 
LITERAL_EX_OBJ) {
+                                                       key_len = 
MAX_LENGTH_OF_LONG + sizeof("->") + Z_STRLEN(op_array->literals[i].constant);
+                                                       key = emalloc(key_len);
+                                                       key_len = snprintf(key, 
key_len-1, "%d->%s", info[i].u.num, Z_STRVAL(op_array->literals[i].constant));
+                                               } else if (info[i].flags & 
LITERAL_EX_CLASS) {
+                                                       zval *class_name = 
&op_array->literals[(info[i].u.num < i) ? map[info[i].u.num] : 
info[i].u.num].constant;
+                                                       key_len = 
Z_STRLEN_P(class_name) + sizeof("::") + 
Z_STRLEN(op_array->literals[i].constant);
+                                                       key = emalloc(key_len);
+                                                       memcpy(key, 
Z_STRVAL_P(class_name), Z_STRLEN_P(class_name));
+                                                       memcpy(key + 
Z_STRLEN_P(class_name), "::", sizeof("::") - 1);
+                                                       memcpy(key + 
Z_STRLEN_P(class_name) + sizeof("::") - 1,
+                                                               
Z_STRVAL(op_array->literals[i].constant),
+                                                               
Z_STRLEN(op_array->literals[i].constant) + 1);
+                                               } else {
+                                                       key = 
Z_STRVAL(op_array->literals[i].constant);
+                                                       key_len = 
Z_STRLEN(op_array->literals[i].constant)+1;
+                                               }
+                                               h = zend_hash_func(key, 
key_len);
+                                               h += info[i].flags;
+                                       }
+                                       if ((info[i].flags & LITERAL_MAY_MERGE) 
&&
+                                               zend_hash_quick_find(&hash, 
key, key_len, h, (void**)&pos) == SUCCESS &&
+                                               
Z_TYPE(op_array->literals[i].constant) == 
Z_TYPE(op_array->literals[*pos].constant) &&
+                                               info[i].flags == 
info[*pos].flags) {
+
+                                               if (info[i].flags & 
(LITERAL_EX_OBJ|LITERAL_EX_CLASS)) {
+                                                       efree(key);
+                                               }
+                                               map[i] = *pos;
+                                               
zval_dtor(&op_array->literals[i].constant);
+                                               n = 
LITERAL_NUM_RELATED(info[i].flags);
+                                               while (n > 1) {
+                                                       i++;
+                                                       
zval_dtor(&op_array->literals[i].constant);
+                                                       n--;
+                                               }
+                                       } else {
+                                               map[i] = j;
+                                               if (info[i].flags & 
LITERAL_MAY_MERGE) {
+                                                       
zend_hash_quick_add(&hash, key, key_len, h, (void**)&j, sizeof(int), NULL);
+                                                       if (info[i].flags & 
(LITERAL_EX_OBJ|LITERAL_EX_CLASS)) {
+                                                               efree(key);
+                                                       }
+                                               }
+                                               if (i != j) {
+                                                       op_array->literals[j] = 
op_array->literals[i];
+                                                       info[j] = info[i];
+                                               }
+                                               if 
(!op_array->literals[j].hash_value) {
+                                                       if 
(IS_INTERNED(Z_STRVAL(op_array->literals[j].constant))) {
+                                                               
op_array->literals[j].hash_value = 
INTERNED_HASH(Z_STRVAL(op_array->literals[j].constant));
+                                                       } else {
+                                                               
op_array->literals[j].hash_value = 
zend_hash_func(Z_STRVAL(op_array->literals[j].constant), 
Z_STRLEN(op_array->literals[j].constant)+1);
+                                                       }
+                                               }
+                                               if 
(LITERAL_NUM_SLOTS(info[i].flags)) {
+                                                       
op_array->literals[j].cache_slot = cache_slots;
+                                                       cache_slots += 
LITERAL_NUM_SLOTS(info[i].flags);
+                                               }
+                                               j++;
+                                               n = 
LITERAL_NUM_RELATED(info[i].flags);
+                                               while (n > 1) {
+                                                       i++;
+                                                       if (i != j) 
op_array->literals[j] = op_array->literals[i];
+                                                       if 
(!op_array->literals[j].hash_value) {
+                                                               if 
(IS_INTERNED(Z_STRVAL(op_array->literals[j].constant))) {
+                                                                       
op_array->literals[j].hash_value = 
INTERNED_HASH(Z_STRVAL(op_array->literals[j].constant));
+                                                               } else {
+                                                                       
op_array->literals[j].hash_value = 
zend_hash_func(Z_STRVAL(op_array->literals[j].constant), 
Z_STRLEN(op_array->literals[j].constant)+1);
+                                                               }
+                                                       }
+                                                       j++;
+                                                       n--;
+                                               }
+                                       }
+                                       break;
+                               default:
+                                       /* don't merge other types */
+                                       map[i] = j;
+                                       if (i != j) {
+                                               op_array->literals[j] = 
op_array->literals[i];
+                                               info[j] = info[i];
+                                       }
+                                       j++;
+                                       break;
+                       }
+               }
+               zend_hash_destroy(&hash);
+               op_array->last_literal = j;
+               op_array->last_cache_slot = cache_slots;
+
+           /* Update opcodes to use new literals table */
+               opline = op_array->opcodes;
+               end = opline + op_array->last;
+               while (opline < end) {
+                       if (ZEND_OP1_TYPE(opline) == IS_CONST) {
+                               opline->op1.constant = 
map[opline->op1.constant];
+                       }
+                       if (ZEND_OP2_TYPE(opline) == IS_CONST) {
+                               opline->op2.constant = 
map[opline->op2.constant];
+                       }
+                       opline++;
+               }
+               efree(map);
+               efree(info);
+
+#if DEBUG_COMPACT_LITERALS
+               {
+                       int i, use_copy;
+                       fprintf(stderr, "Optimized literlas table size %d\n", 
op_array->last_literal);
+
+                       for (i = 0; i < op_array->last_literal; i++) {
+                               zval zv = op_array->literals[i].constant;
+                               
zend_make_printable_zval(&op_array->literals[i].constant, &zv, &use_copy);
+                               fprintf(stderr, "Literal %d, val (%d):%s\n", i, 
Z_STRLEN(zv), Z_STRVAL(zv));
+                               if (use_copy) {
+                                       zval_dtor(&zv);
+                               }
+                       }
+                       fflush(stderr);
+               }
+#endif
+       }
+}
+#endif
diff --git a/ext/opcache/Optimizer/zend_optimizer.c 
b/ext/opcache/Optimizer/zend_optimizer.c
index b2148e1..fc0066e 100644
--- a/ext/opcache/Optimizer/zend_optimizer.c
+++ b/ext/opcache/Optimizer/zend_optimizer.c
@@ -112,6 +112,7 @@ int zend_optimizer_add_literal(zend_op_array *op_array, 
const zval *zv TSRMLS_DC
 #include "Optimizer/nop_removal.c"
 #include "Optimizer/block_pass.c"
 #include "Optimizer/optimize_temp_vars_5.c"
+#include "Optimizer/compact_literals.c"
 
 static void zend_optimize(zend_op_array           *op_array,
                           zend_persistent_script  *script,
@@ -150,7 +151,7 @@ static void zend_optimize(zend_op_array           *op_array,
         */
 #include "Optimizer/pass5.c"
 
-        /* pass 9:
+       /* pass 9:
         * - Optimize temp variables usage
         */
 #include "Optimizer/pass9.c"
@@ -159,6 +160,15 @@ static void zend_optimize(zend_op_array           
*op_array,
         * - remove NOPs
         */
 #include "Optimizer/pass10.c"
+
+#if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
+       /* pass 11:
+        * - Compact literals table 
+        */
+       if (ZEND_OPTIMIZER_PASS_11 & OPTIMIZATION_LEVEL) {
+               optimizer_compact_literals(op_array TSRMLS_CC);
+       }
+#endif
 }
 
 static void zend_accel_optimize(zend_op_array           *op_array,
diff --git a/ext/opcache/Optimizer/zend_optimizer.h 
b/ext/opcache/Optimizer/zend_optimizer.h
index 1775994..4be37ba 100644
--- a/ext/opcache/Optimizer/zend_optimizer.h
+++ b/ext/opcache/Optimizer/zend_optimizer.h
@@ -35,7 +35,7 @@
 #define ZEND_OPTIMIZER_PASS_8          (1<<7)   
 #define ZEND_OPTIMIZER_PASS_9          (1<<8)   /* TMP VAR usage               
 */
 #define ZEND_OPTIMIZER_PASS_10         (1<<9)   /* NOP removal                 
*/
-#define ZEND_OPTIMIZER_PASS_11         (1<<10)
+#define ZEND_OPTIMIZER_PASS_11         (1<<10)  /* Merge equal constants       
*/
 #define ZEND_OPTIMIZER_PASS_12         (1<<11)
 #define ZEND_OPTIMIZER_PASS_13         (1<<12)
 #define ZEND_OPTIMIZER_PASS_14         (1<<13)
diff --git a/ext/opcache/tests/compact_literals.phpt 
b/ext/opcache/tests/compact_literals.phpt
new file mode 100644
index 0000000..a691b91
--- /dev/null
+++ b/ext/opcache/tests/compact_literals.phpt
@@ -0,0 +1,215 @@
+--TEST--
+Test with compact literals
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+opcache.optimization_level=-1
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+
+echo "array key hash" . ":" . PHP_EOL;
+$array = array(
+       "1" => "one",
+       "2" => "two",
+       "one" => 1,
+       "two" => 2,
+);
+
+unset($array["one"]);
+unset($array["2"]);
+
+print_r($array);
+
+echo "funcion define" . ":" . PHP_EOL;
+if (!function_exists("dummy")) {
+       function dummy() {
+               var_dump(__FUNCTION__);
+       }
+}
+
+dummy();
+
+$dummy = function () { var_dump("lambda" . "dummy"); };
+$dummy();
+
+if (!class_exists("A")) {
+       class A {
+               public static $name = "A";
+               public static function say($n = "name") {
+                       var_dump(static::$name);
+               }
+       }
+}
+
+class B extends A {
+       public static $name = "B";
+}
+
+if (!class_exists("C")) {
+       class C extends B {
+               public static $name = "C";
+       }
+}
+
+A::say();
+B::Say();
+A::say();
+B::say();
+C::say();
+
+function get_eol_define() {
+       define("MY_EOL", PHP_EOL);
+}
+get_eol_define();
+define("EOL", MY_EOL);
+
+echo "constants define" . ":" . EOL; 
+
+echo "define " . "TEST" . EOL;
+define("TEST", "TEST");
+
+class E {
+       public static $E="EP";
+       const E="E";
+       const TEST="NULL";
+}
+
+class F {
+       const F="F";
+       public static $E="FEP";
+       const E="FE";
+       const TEST="FALSE";
+       public static $F = "FP";
+}
+
+var_dump(TEST);        //"TEST"
+var_dump(E::E);        //"E"
+var_dump(F::E);        //"FE"
+var_dump(F::F);        //"F"
+var_dump(E::TEST);  //"NULL"
+var_dump(F::TEST);  //"FALSE"
+var_dump(E::$E);       //"EP"
+var_dumP(F::$F);    //"FP"
+var_dumP(F::$E);    //"FEP"
+
+echo "propertes and methods" . EOL;
+
+class CH {
+       const H = "H";
+       public function h() {
+               var_dump(self::H);
+       }
+}
+
+class CI {
+       const H = "I";
+       public function h() {
+               var_dump(self::H);
+       }
+}
+
+function change(&$obj) {
+       $obj = new CH;
+}
+
+function geti() {
+       return new CI;
+}
+
+$h = new CH;
+
+echo "-->H" . PHP_EOL;
+$h->H();
+var_dump($h::H);
+var_dump(CH::H);
+
+$h->H();
+var_dump($h::H);
+var_dump(CH::H);
+
+echo "-->I" . PHP_EOL;
+$h = new CI;
+$h->H();
+var_dump($h::H);
+var_dump(CI::H);
+$h->H();
+var_dump($h::H);
+var_dump(CI::H);
+
+echo "-->H" . PHP_EOL;
+change($h);
+
+$h->H();
+var_dump($h::H);
+var_dump(CH::H);
+
+$h->H();
+var_dump($h::H);
+var_dump(CH::H);
+
+echo "-->I" . PHP_EOL;
+$h = geti(); 
+$h->H();
+var_dump($h::H);
+var_dump(CI::H);
+$h->H();
+var_dump($h::H);
+var_dump(CI::H);
+?>
+--EXPECT--
+array key hash:
+Array
+(
+    [1] => one
+    [two] => 2
+)
+funcion define:
+string(5) "dummy"
+string(11) "lambdadummy"
+string(1) "A"
+string(1) "B"
+string(1) "A"
+string(1) "B"
+string(1) "C"
+constants define:
+define TEST
+string(4) "TEST"
+string(1) "E"
+string(2) "FE"
+string(1) "F"
+string(4) "NULL"
+string(5) "FALSE"
+string(2) "EP"
+string(2) "FP"
+string(3) "FEP"
+propertes and methods
+-->H
+string(1) "H"
+string(1) "H"
+string(1) "H"
+string(1) "H"
+string(1) "H"
+string(1) "H"
+-->I
+string(1) "I"
+string(1) "I"
+string(1) "I"
+string(1) "I"
+string(1) "I"
+string(1) "I"
+-->H
+string(1) "H"
+string(1) "H"
+string(1) "H"
+string(1) "H"
+string(1) "H"
+string(1) "H"
+-->I
+string(1) "I"
+string(1) "I"
+string(1) "I"
+string(1) "I"
+string(1) "I"
+string(1) "I"
-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to