03
  B   lY>eJ}@?q1hn_I|+aamJq@;pNi1h =w    /* 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_liter