Index: /trunk/processor/dispatch.m4
===================================================================
--- /trunk/processor/dispatch.m4	(revision 661)
+++ /trunk/processor/dispatch.m4	(revision 662)
@@ -28,2 +28,31 @@
 	)
 ')
+dnl {{{ DISPATCH_ARRAY(1:count, 2:type, 3:elm)
+define(`DISPATCH_ARRAY', `
+	if (src->$3) {
+		int i;
+		IFDASM(`
+			zval *arr;
+			ALLOC_INIT_ZVAL(arr);
+			array_init(arr);
+			for (i = 0; i < src->$1; i ++) {
+				ifelse(
+					`$2', `zend_bool', `add_assoc_bool_ex(arr, ZEND_STRS("$3"), src->$3[i] ? 1 : 0);'
+				, `', `', `add_assoc_long_ex(arr, ZEND_STRS("$3"), src->$3[i]);')
+			}
+			add_assoc_zval_ex(dst, ZEND_STRS("$3"), arr);
+		', `
+			COPY_N_EX($@)
+			for (i = 0; i < src->$1; i ++) {
+				DISABLECHECK(`
+					DISPATCH(`$2', `$3[i]', `$4')
+				')
+			}
+		')dnl IFDASM
+		DONE(`$3')
+	}
+	else {
+		COPYNULL(`$3')
+	}
+')
+dnl }}}
Index: /trunk/processor/head.m4
===================================================================
--- /trunk/processor/head.m4	(revision 661)
+++ /trunk/processor/head.m4	(revision 662)
@@ -69,5 +69,5 @@
 	const xc_cache_t          *cache;
 	const zend_class_entry *cache_ce;
-	zend_uint cache_class_num;
+	zend_uint cache_class_index;
 
 	const zend_op          *active_opcodes_src;
@@ -75,5 +75,7 @@
 	const zend_class_entry *active_class_entry_src;
 	zend_class_entry       *active_class_entry_dst;
-	zend_uint               active_class_num;
+	zend_uint                 active_class_index;
+	zend_uint                 active_op_array_index;
+	const xc_op_array_info_t *active_op_array_infos_src;
 
 	zend_bool readonly_protection; /* wheather it's present */
@@ -186,5 +188,5 @@
 
 	if (processor->cache_ce == ce) {
-		return processor->cache_class_num;
+		return processor->cache_class_index + 1;
 	}
 	for (i = 0; i < php->classinfo_cnt; i ++) {
@@ -192,5 +194,5 @@
 		if (ZCEP_REFCOUNT_PTR(ceptr) == ZCEP_REFCOUNT_PTR(ce)) {
 			processor->cache_ce = ceptr;
-			processor->cache_class_num = i + 1;
+			processor->cache_class_index = i + 1;
 			return i + 1;
 		}
@@ -199,4 +201,5 @@
 	return (zend_ulong) -1;
 }
+define(`xc_get_class_num', `xc_get_class_numNOTDEFINED')
 /* }}} */
 /* {{{ xc_get_class */
@@ -204,8 +207,9 @@
 static zend_class_entry *xc_get_class(xc_processor_t *processor, zend_ulong class_num) {
 	/* must be parent or currrent class */
-	assert(class_num <= processor->active_class_num);
+	assert(class_num <= processor->active_class_index + 1);
 	return CestToCePtr(processor->php_dst->classinfos[class_num - 1].cest);
 }
 #endif
+define(`xc_get_class', `xc_get_classNOTDEFINED')
 /* }}} */
 #ifdef ZEND_ENGINE_2
Index: /trunk/processor/main.m4
===================================================================
--- /trunk/processor/main.m4	(revision 661)
+++ /trunk/processor/main.m4	(revision 662)
@@ -150,9 +150,23 @@
 define(`COPY', `IFNOTMEMCPY(`IFCOPY(`dst->$1 = src->$1;')')DONE(`$1')')
 dnl }}}
+dnl {{{ COPY_N_EX
+define(`COPY_N_EX', `
+	ALLOC(`dst->$3', `$2', `src->$1')
+	IFCOPY(`
+		memcpy(dst->$3, src->$3, sizeof(dst->$3[0]) * src->$1);
+		')
+')
+dnl }}}
+dnl {{{ COPY_N
+define(`COPY_N', `COPY_N_EX(`$1',`$2')DONE(`$1')')
+dnl }}}
 dnl {{{ COPYPOINTER
 define(`COPYPOINTER', `COPY(`$1')')
 dnl }}}
+dnl {{{ COPYARRAY_EX
+define(`COPYARRAY_EX', `IFNOTMEMCPY(`IFCOPY(`memcpy(dst->$1, src->$1, sizeof(dst->$1));')')')
+dnl }}}
 dnl {{{ COPYARRAY
-define(`COPYARRAY', `IFNOTMEMCPY(`IFCOPY(`memcpy(dst->$1, src->$1, sizeof(dst->$1));')')DONE(`$1')')
+define(`COPYARRAY', `COPYARRAY_EX(`$1',`$2')DONE(`$1')')
 dnl }}}
 dnl {{{ SETNULL_EX
@@ -244,6 +258,10 @@
 define(`IFNOTMEMCPY', `ifdef(`USEMEMCPY', `', `$1')')
 REDEF(`KIND', `calc') include(srcdir`/processor/processor.m4')
+pushdef(`xc_get_class_num', ``xc_get_class_num'($@)')
 REDEF(`KIND', `store') include(srcdir`/processor/processor.m4')
+popdef(`xc_get_class_num')
+pushdef(`xc_get_class', ``xc_get_class'($@)')
 REDEF(`KIND', `restore') include(srcdir`/processor/processor.m4')
+popdef(`xc_get_class')
 
 REDEF(`IFNOTMEMCPY', `$1')
Index: /trunk/processor/processor.m4
===================================================================
--- /trunk/processor/processor.m4	(revision 661)
+++ /trunk/processor/processor.m4	(revision 662)
@@ -339,4 +339,5 @@
 		if (src->num_interfaces) {
 			/*
+			int i;
 			zval *arr;
 			ALLOC_INIT_ZVAL(arr);
@@ -499,8 +500,8 @@
 DEF_STRUCT_P_FUNC(`zend_op_array', , `dnl {{{
 	IFRESTORE(`
+	const xc_op_array_info_t *op_array_info = &processor->active_op_array_infos_src[processor->active_op_array_index];
 	dnl shadow copy must NOT meet:
 	dnl readonly_protection=on
 	dnl main op_array && have early binding
-	zend_uint ii;
 #ifdef ZEND_COMPILE_DELAYED_BINDING
 	zend_bool need_early_binding = 0;
@@ -508,5 +509,8 @@
 	zend_bool need_early_binding = processor->php_src->have_early_binding;
 #endif
-	if (!processor->readonly_protection && !(src == processor->php_src->op_array && need_early_binding)) {
+	zend_bool shallow_copy = !processor->readonly_protection && !(src == processor->php_src->op_array && need_early_binding);
+	if (shallow_copy) {
+		zend_bool gc_arg_info = 0;
+		int gc_opcodes        = 0;
 		/* really fast shallow copy */
 		memcpy(dst, src, sizeof(src[0]));
@@ -515,7 +519,21 @@
 		STRUCT_P(HashTable, static_variables, HashTable_zval_ptr)
 #ifdef ZEND_ENGINE_2
-		STRUCT_ARRAY_I(num_args, zend_arg_info, arg_info)
-		xc_gc_add_op_array(dst TSRMLS_CC);
-#endif
+		STRUCT_ARRAY(num_args, zend_arg_info, arg_info)
+		gc_arg_info = 1;
+#endif
+		if (op_array_info->oplineinfo_cnt) {
+			gc_opcodes = 1;
+			COPY_N_EX(last, zend_op, opcodes)
+		}
+		if (gc_arg_info || gc_opcodes) {
+			xc_gc_op_array_t gc_op_array;
+#ifdef ZEND_ENGINE_2
+			gc_op_array.num_args = gc_arg_info ? dst->num_args : 0;
+			gc_op_array.arg_info = gc_arg_info ? dst->arg_info : NULL;
+#endif
+			gc_op_array.last     = gc_opcodes > 1 ? dst->last : 0;
+			gc_op_array.opcodes  = gc_opcodes ? dst->opcodes : NULL;
+			xc_gc_add_op_array(&gc_op_array TSRMLS_CC);
+		}
 		define(`SKIPASSERT_ONCE')
 	}
@@ -524,6 +542,4 @@
 	do {
 	dnl RESTORE is done above!
-	zend_uint ii;
-	int i;
 
 	/* Common elements */
@@ -532,5 +548,5 @@
 #ifdef ZEND_ENGINE_2
 	DISPATCH(zend_uint, fn_flags)
-	STRUCT_ARRAY_I(num_args, zend_arg_info, arg_info)
+	STRUCT_ARRAY(num_args, zend_arg_info, arg_info)
 	DISPATCH(zend_uint, num_args)
 	DISPATCH(zend_uint, required_num_args)
@@ -541,5 +557,4 @@
 		IFCOPY(`memcpy(dst->arg_types, src->arg_types, sizeof(src->arg_types[0]) * (src->arg_types[0]+1));')
 		IFDASM(`do {
-			zend_uint ii;
 			int i;
 			zval *zv;
@@ -581,5 +596,5 @@
 		processor->active_opcodes_src = src->opcodes;
 	')')
-	STRUCT_ARRAY_I(last, zend_op, opcodes)
+	STRUCT_ARRAY(last, zend_op, opcodes)
 	popdef(`AFTER_ALLOC')
 	DISPATCH(zend_uint, last)
@@ -599,5 +614,5 @@
 	DISPATCH(zend_uint, T)
 
-	STRUCT_ARRAY_I(last_brk_cont, zend_brk_cont_element, brk_cont_array)
+	STRUCT_ARRAY(last_brk_cont, zend_brk_cont_element, brk_cont_array)
 	DISPATCH(zend_uint, last_brk_cont)
 	DISPATCH(zend_uint, current_brk_cont)
@@ -649,4 +664,5 @@
 #endif
 	} while (0);
+	IFRESTORE(`xc_fix_op_array_info(processor->php_src, dst, !shallow_copy, op_array_info TSRMLS_CC);')
 
 #ifdef ZEND_ENGINE_2
@@ -713,4 +729,9 @@
 dnl }}}
 #endif
+DEF_STRUCT_P_FUNC(`xc_op_array_info_t', , `dnl {{{
+	DISPATCH(zend_uint, oplineinfo_cnt)
+	DISPATCH_ARRAY(oplineinfo_cnt, int, oplineinfos)
+')
+dnl }}}
 DEF_STRUCT_P_FUNC(`xc_funcinfo_t', , `dnl {{{
 	DISPATCH(zend_uint, key_size)
@@ -722,4 +743,11 @@
 	')
 	DISPATCH(ulong, h)
+	IFRESTORE(`COPY(op_array_info)', `
+		STRUCT(xc_op_array_info_t, op_array_info)
+	')
+	IFRESTORE(`
+		processor->active_op_array_infos_src = &dst->op_array_info;
+		processor->active_op_array_index = 0;
+	')
 	STRUCT(zend_function, func)
 ')
@@ -734,4 +762,12 @@
 	')
 	DISPATCH(ulong, h)
+	DISPATCH(zend_uint, methodinfo_cnt)
+	IFRESTORE(`COPY(methodinfos)', `
+		STRUCT_ARRAY(methodinfo_cnt, xc_op_array_info_t, methodinfos)
+	')
+	IFRESTORE(`
+		processor->active_op_array_infos_src = dst->methodinfos;
+		processor->active_op_array_index = 0;
+	')
 #ifdef ZEND_ENGINE_2
 	STRUCT_P(zend_class_entry, cest)
@@ -767,6 +803,4 @@
 #endif
 DEF_STRUCT_P_FUNC(`xc_entry_data_php_t', , `dnl {{{
-	zend_uint i;
-
 	IFCOPY(`
 		processor->php_dst = dst;
@@ -785,4 +819,22 @@
 	DISPATCH(size_t, size)
 
+	DISPATCH(int, filepath_len)
+	IFRESTORE(`COPY(filepath)', `PROC_STRING_L(filepath, filepath_len)')
+	DISPATCH(int, dirpath_len)
+	IFRESTORE(`COPY(dirpath)', `PROC_STRING_L(dirpath, dirpath_len)')
+#ifdef IS_UNICODE
+	DISPATCH(int, ufilepath_len)
+	IFRESTORE(`COPY(ufilepath)', `PROC_USTRING_L(ufilepath, ufilepath_len)')
+	DISPATCH(int, udirpath_len)
+	IFRESTORE(`COPY(udirpath)', `PROC_USTRING_L(udirpath, udirpath_len)')
+#endif
+
+	IFRESTORE(`COPY(op_array_info)', `
+		STRUCT(xc_op_array_info_t, op_array_info)
+	')
+	IFRESTORE(`
+		processor->active_op_array_infos_src = &dst->op_array_info;
+		processor->active_op_array_index = 0;
+	')
 	STRUCT_P(zend_op_array, op_array)
 
@@ -796,11 +848,5 @@
 
 	DISPATCH(zend_uint, classinfo_cnt)
-	pushdef(`BEFORE_LOOP', `
-		IFCOPY(`
-			processor->active_class_num = i + 1;
-		')
-	')
-	STRUCT_ARRAY(classinfo_cnt, xc_classinfo_t, classinfos)
-	popdef(`BEFORE_LOOP')
+	STRUCT_ARRAY(classinfo_cnt, xc_classinfo_t, classinfos, , IFRESTORE(`processor->active_class_index'))
 #ifdef ZEND_ENGINE_2_1
 	DISPATCH(zend_uint, autoglobal_cnt)
@@ -879,5 +925,5 @@
 		switch (src->type) {
 		case XC_TYPE_PHP:
-			IFCALCCOPY(`DONE(data.php)', `STRUCT_P(xc_entry_data_php_t, data.php)')
+			IFCALCCOPY(`COPY(data.php)', `STRUCT_P(xc_entry_data_php_t, data.php)')
 			break;
 
Index: /trunk/processor/string.m4
===================================================================
--- /trunk/processor/string.m4	(revision 661)
+++ /trunk/processor/string.m4	(revision 662)
@@ -7,10 +7,10 @@
 			STRTYPE, `zstr_char', `char',
 			`',      `',          `UChar'))
-	pushdef(`ISTYPE', ifelse(STRTYPE,`zstr_uchar',IS_UNICODE,IS_STRING))
+	pushdef(`ISTYPE', ifelse(PTRTYPE,`UChar',IS_UNICODE,IS_STRING))
 	pushdef(`UNI_STRLEN', ifelse(
 			STRTYPE, `zstr_uchar', `xc_zstrlen_uchar',
 			STRTYPE, `zstr_char',  `xc_zstrlen_char',
 			`',      `',           `strlen'))
-	pushdef(`SRCSTR', ifelse(STRTYPE,`char',`ZSTR($2)',`$2'))
+	pushdef(`SRCSTR', ifelse(STRTYPE,`char',`ZSTR($2)',STRTYPE,`UChar',`ZSTR($2)',`$2'))
 	pushdef(`SRCPTR', ifelse(
 			STRTYPE, `zstr_uchar', `ZSTR_U($2)',
@@ -88,7 +88,10 @@
 dnl PROC_STRING_N(1:name, 2:size, 3:type)
 define(`PROC_STRING_N', `DBG(`$0($*)') DONE(`$1')`'PROC_STRING_N_EX(`dst->$1', `src->$1', `src->$2', `$1', `char')')
+define(`PROC_USTRING_N', `DBG(`$0($*)') DONE(`$1')`'PROC_STRING_N_EX(`dst->$1', `src->$1', `src->$2', `$1', `UChar')')
 
 define(`PROC_STRING_L', `DBG(`$0($*)') PROC_STRING_N(`$1', `$2 + 1')')
+define(`PROC_USTRING_L', `DBG(`$0($*)') PROC_USTRING_N(`$1', `$2 + 1')')
 define(`PROC_STRING',   `DBG(`$0($*)') DONE(`$1')`'PROC_STRING_N_EX(`dst->$1', `src->$1', `strlen(src->$1) + 1', `$1', `char')')
+define(`PROC_USTRING',  `DBG(`$0($*)') DONE(`$1')`'PROC_STRING_N_EX(`dst->$1', `src->$1', `strlen(src->$1) + 1', `$1', `UChar')')
 
 dnl {{{ PROC_ZSTRING_N(1:type, 2:name, 3:size, 4:size_type)
Index: /trunk/processor/struct.m4
===================================================================
--- /trunk/processor/struct.m4	(revision 661)
+++ /trunk/processor/struct.m4	(revision 662)
@@ -165,14 +165,10 @@
 ')
 dnl }}}
-dnl {{{ STRUCT_ARRAY_I(1:count, 2:type, 3:elm, 4:name=type)
-define(`STRUCT_ARRAY_I', `
-pushdef(`i', `ii')
-STRUCT_ARRAY(`$1', `$2', `$3', `$4')
-popdef(`i')
-')
-dnl }}}
-dnl {{{ STRUCT_ARRAY(1:count, 2:type, 3:elm, 4:name=type)
+dnl {{{ STRUCT_ARRAY(1:count, 2:type, 3:elm, 4:name=type, 5:loopcounter)
 define(`STRUCT_ARRAY', `
 	if (src->$3) {
+		ifelse(
+			`$5', `', `int i; pushdef(`LOOPCOUNTER', `i')',
+			`', `', `pushdef(`LOOPCOUNTER', `$5')')
 		pushdefFUNC_NAME(`$2', `$4')
 		IFDASM(`
@@ -180,10 +176,10 @@
 			ALLOC_INIT_ZVAL(arr);
 			array_init(arr);
-			for (i = 0; i < src->$1; i ++) {
+			for (LOOPCOUNTER = 0; LOOPCOUNTER < src->$1; LOOPCOUNTER ++) {
 				zval *zv;
 
 				ALLOC_INIT_ZVAL(zv);
 				array_init(zv);
-				FUNC_NAME (zv, &(src->$3[i]) TSRMLS_CC);
+				FUNC_NAME (zv, &(src->$3[LOOPCOUNTER]) TSRMLS_CC);
 				add_next_index_zval(arr, zv);
 			}
@@ -192,8 +188,7 @@
 			ALLOC(`dst->$3', `$2', `src->$1')
 			ifdef(`AFTER_ALLOC', AFTER_ALLOC)
-			for (i = 0; i < src->$1; i ++) {
+			for (LOOPCOUNTER = 0; LOOPCOUNTER < src->$1; LOOPCOUNTER ++) {
 				DISABLECHECK(`
-					ifdef(`BEFORE_LOOP', `BEFORE_LOOP')
-					STRUCT(`$2', `$3[i]', `$4')
+					STRUCT(`$2', `$3[LOOPCOUNTER]', `$4')
 				')
 			}
@@ -201,4 +196,5 @@
 		DONE(`$3')
 		popdef(`FUNC_NAME')
+		popdef(`LOOPCOUNTER')
 	}
 	else {
Index: /trunk/utils.h
===================================================================
--- /trunk/utils.h	(revision 661)
+++ /trunk/utils.h	(revision 662)
@@ -38,7 +38,4 @@
 
 #	define IFDEBUG(x) do { } while (0)
-#   ifndef NDEBUG
-#       define NDEBUG
-#   endif
 #endif /* XCACHE_DEBUG */
 #include <assert.h>
@@ -132,2 +129,51 @@
 void xc_copy_internal_zend_constants(HashTable *target, HashTable *source);
 #endif
+
+typedef struct {
+	zend_uint size;
+	zend_uint cnt;
+	void *data;
+} xc_vector_t;
+
+#define xc_vector_init(type, vector) do { \
+	(vector)->cnt = 0;     \
+	(vector)->size = 0;    \
+	(vector)->data = NULL; \
+} while (0)
+
+#define xc_vector_add(type, vector, value) do { \
+	if ((vector)->cnt == (vector)->size) { \
+		if ((vector)->size) { \
+			(vector)->size <<= 1; \
+			(vector)->data = erealloc((vector)->data, sizeof(type) * (vector)->size); \
+		} \
+		else { \
+			(vector)->size = 8; \
+			(vector)->data = emalloc(sizeof(type) * (vector)->size); \
+		} \
+	} \
+	((type *) (vector)->data)[(vector)->cnt++] = value; \
+} while (0)
+
+static inline void *xc_vector_detach_impl(xc_vector_t *vector)
+{
+	void *data = vector->data;
+	vector->data = NULL;
+	vector->size = 0;
+	vector->cnt = 0;
+	return data;
+}
+
+#define xc_vector_detach(type, vector) ((type *) xc_vector_detach_impl(vector))
+
+static inline void xc_vector_free_impl(xc_vector_t *vector TSRMLS_DC)
+{
+	if (vector->data) {
+		efree(vector->data);
+	}
+	vector->size = 0;
+	vector->cnt = 0;
+}
+
+#define xc_vector_free(type, vector) xc_vector_free_impl(vector TSRMLS_CC)
+
Index: /trunk/xcache.c
===================================================================
--- /trunk/xcache.c	(revision 661)
+++ /trunk/xcache.c	(revision 662)
@@ -37,4 +37,12 @@
 #include "opcode_spec.h"
 #include "utils.h"
+
+#ifndef ZEND_ENGINE_2_3
+ZEND_API size_t zend_dirname(char *path, size_t len)
+{
+	php_dirname(path, len);
+	return strlen(path);
+}
+#endif
 
 #define VAR_ENTRY_EXPIRED(pentry) ((pentry)->ttl && XG(request_time) > pentry->ctime + (pentry)->ttl)
@@ -1005,4 +1013,5 @@
 	{
 		/* hash on filename, let's expand it to real path */
+		/* FIXME */
 		filename = expand_filepath(filename, opened_path_buffer TSRMLS_CC);
 		if (filename == NULL) {
@@ -1108,6 +1117,197 @@
 /* }}} */
 #endif
+
+/* {{{ Constant Usage */
+#define xcache_op1_is_file 1
+#define xcache_op1_is_dir  2
+#define xcache_op2_is_file 4
+#define xcache_op2_is_dir  8
+typedef struct {
+	zend_bool filepath_used;
+	zend_bool dirpath_used;
+	zend_bool ufilepath_used;
+	zend_bool udirpath_used;
+} xc_const_usage_t;
+/* }}} */
+static void xc_collect_op_array_info(xc_entry_data_php_t *php, xc_const_usage_t *usage, xc_op_array_info_t *op_array_info, zend_op_array *op_array TSRMLS_DC) /* {{{ */
+{
+	int oplineno;
+	xc_vector_t vector_int;
+
+	xc_vector_init(int, &vector_int);
+
+#define XCACHE_CHECK_OP(type, op) \
+	if (zend_binary_strcmp(Z_STRVAL(opline->op.u.constant), Z_STRLEN(opline->op.u.constant), php->type##path, php->type##path_len) == 0) { \
+		usage->type##path_used = 1; \
+		oplineinfo |= xcache_##op##_is_##type; \
+	}
+
+#define XCACHE_U_CHECK_OP(type, op) \
+	if (zend_u_##binary_strcmp(Z_USTRVAL(opline->op.u.constant), Z_USTRLEN(opline->op.u.constant), php->u##type##path, php->u##type##path_len) == 0) { \
+		usage->u##type##path_used = 1; \
+		oplineinfo |= xcache_##op##_is_##type; \
+	}
+
+	for (oplineno = 0; oplineno < op_array->last; oplineno++) {
+		zend_op *opline = &op_array->opcodes[oplineno];
+		int oplineinfo = 0;
+		if (opline->op1.op_type == IS_CONST) {
+			if (Z_TYPE(opline->op1.u.constant) == IS_STRING) {
+				XCACHE_CHECK_OP(file, op1)
+				else XCACHE_CHECK_OP(dir, op1)
+			}
+
+#ifdef IS_UNICODE
+			else if (Z_TYPE(opline->op1.u.constant) == IS_UNICODE) {
+				XCACHE_U_CHECK_OP(file, op1)
+				else XCACHE_U_CHECK_OP(dir, op1)
+			}
+#endif
+		}
+		if (opline->op2.op_type == IS_CONST) {
+			if (Z_TYPE(opline->op2.u.constant) == IS_STRING) {
+				XCACHE_CHECK_OP(file, op2)
+				else XCACHE_CHECK_OP(dir, op2)
+			}
+
+#ifdef IS_UNICODE
+			else if (Z_TYPE(opline->op2.u.constant) == IS_UNICODE) {
+				XCACHE_U_CHECK_OP(file, op2)
+				else XCACHE_U_CHECK_OP(dir, op2)
+			}
+#endif
+		}
+		if (oplineinfo) {
+			xc_vector_add(int, &vector_int, oplineno);
+			xc_vector_add(int, &vector_int, oplineinfo);
+		}
+	}
+
+	op_array_info->oplineinfo_cnt = vector_int.cnt;
+	op_array_info->oplineinfos    = xc_vector_detach(int, &vector_int);
+	xc_vector_free(int, &vector_int);
+}
+/* }}} */
+void xc_fix_op_array_info(const xc_entry_data_php_t *php, zend_op_array *op_array, int copy, const xc_op_array_info_t *op_array_info TSRMLS_DC) /* {{{ */
+{
+	int i;
+	if (!op_array_info->oplineinfo_cnt) {
+		return;
+	}
+
+	for (i = 0; i < op_array_info->oplineinfo_cnt; i += 2) {
+		int oplineno = op_array_info->oplineinfos[i];
+		int oplineinfo = op_array_info->oplineinfos[i + 1];
+		zend_op *opline = &op_array->opcodes[oplineno];
+		if ((oplineinfo & xcache_op1_is_file)) {
+			assert(opline->op1.op_type == IS_CONST);
+			if (copy) {
+				efree(Z_STRVAL(opline->op1.u.constant));
+			}
+			if (Z_TYPE(opline->op1.u.constant) == IS_STRING) {
+				assert(php->filepath);
+				ZVAL_STRINGL(&opline->op1.u.constant, php->filepath, php->filepath_len, copy);
+			}
+#ifdef IS_UNICODE
+			else if (Z_TYPE(opline->op1.u.constant) == IS_UNICODE) {
+				assert(php->ufilepath);
+				ZVAL_UNICODEL(&opline->op1.u.constant, php->ufilepath, php->ufilepath_len, copy);
+			}
+#endif
+			else {
+				assert(0);
+			}
+		}
+		else if ((oplineinfo & xcache_op1_is_dir)) {
+			assert(opline->op1.op_type == IS_CONST);
+			if (copy) {
+				efree(Z_STRVAL(opline->op1.u.constant));
+			}
+			if (Z_TYPE(opline->op1.u.constant) == IS_STRING) {
+				assert(php->dirpath);
+				ZVAL_STRINGL(&opline->op1.u.constant, php->dirpath, php->dirpath_len, copy);
+			}
+#ifdef IS_UNICODE
+			else if (Z_TYPE(opline->op1.u.constant) == IS_UNICODE) {
+				assert(!php->udirpath);
+				ZVAL_UNICODEL(&opline->op1.u.constant, php->udirpath, php->udirpath_len, copy);
+			}
+#endif
+			else {
+				assert(0);
+			}
+		}
+
+		if ((oplineinfo & xcache_op2_is_file)) {
+			assert(opline->op2.op_type == IS_CONST);
+			if (copy) {
+				efree(Z_STRVAL(opline->op2.u.constant));
+			}
+			if (Z_TYPE(opline->op2.u.constant) == IS_STRING) {
+				assert(php->filepath);
+				ZVAL_STRINGL(&opline->op2.u.constant, php->filepath, php->filepath_len, copy);
+			}
+#ifdef IS_UNICODE
+			else if (Z_TYPE(opline->op2.u.constant) == IS_UNICODE) {
+				assert(php->ufilepath);
+				ZVAL_UNICODEL(&opline->op2.u.constant, php->ufilepath, php->ufilepath_len, copy);
+			}
+#endif
+			else {
+				assert(0);
+			}
+		}
+		else if ((oplineinfo & xcache_op2_is_dir)) {
+			assert(opline->op2.op_type == IS_CONST);
+			if (copy) {
+				efree(Z_STRVAL(opline->op2.u.constant));
+			}
+			if (Z_TYPE(opline->op2.u.constant) == IS_STRING) {
+				assert(!php->dirpath);
+				ZVAL_STRINGL(&opline->op2.u.constant, php->dirpath, php->dirpath_len, copy);
+			}
+#ifdef IS_UNICODE
+			else if (Z_TYPE(opline->op2.u.constant) == IS_UNICODE) {
+				assert(!php->udirpath);
+				ZVAL_UNICODEL(&opline->op2.u.constant, php->udirpath, php->udirpath_len, copy);
+			}
+#endif
+			else {
+				assert(0);
+			}
+		}
+	}
+}
+/* }}} */
+static void xc_free_op_array_info(xc_op_array_info_t *op_array_info TSRMLS_DC) /* {{{ */
+{
+	if (op_array_info->oplineinfos) {
+		efree(op_array_info->oplineinfos);
+	}
+}
+/* }}} */
 static void xc_free_php(xc_entry_data_php_t *php TSRMLS_DC) /* {{{ */
 {
+	int i;
+	if (php->classinfos) {
+		for (i = 0; i < php->classinfo_cnt; i ++) {
+			xc_classinfo_t *classinfo = &php->classinfos[i];
+			int j;
+			for (j = 0; j < classinfo->methodinfo_cnt; j ++) {
+				xc_free_op_array_info(&classinfo->methodinfos[j] TSRMLS_CC);
+			}
+
+			if (classinfo->methodinfos) {
+				efree(classinfo->methodinfos);
+			}
+		}
+	}
+	if (php->funcinfos) {
+		for (i = 0; i < php->funcinfo_cnt; i ++) {
+			xc_free_op_array_info(&php->funcinfos[i].op_array_info TSRMLS_CC);
+		}
+	}
+	xc_free_op_array_info(&php->op_array_info TSRMLS_CC);
+
 #define X_FREE(var) do {\
 	if (php->var) { \
@@ -1116,4 +1316,10 @@
 } while (0)
 
+	X_FREE(dirpath);
+#ifdef IS_UNICODE
+	X_FREE(ufilepath);
+	X_FREE(udirpath);
+#endif
+
 #ifdef ZEND_ENGINE_2_1
 	X_FREE(autoglobals);
@@ -1132,4 +1338,5 @@
 	int old_constinfo_cnt, old_funcinfo_cnt, old_classinfo_cnt;
 	zend_bool catched = 0;
+	xc_const_usage_t const_usage;
 
 	/* {{{ compile */
@@ -1162,4 +1369,5 @@
 	/* }}} */
 	/* {{{ prepare */
+	zend_restore_compiled_filename(h->opened_path ? h->opened_path : h->filename TSRMLS_CC);
 	php->op_array      = op_array;
 
@@ -1206,4 +1414,16 @@
 #endif
 #undef X_ALLOC
+	/* }}} */
+
+	/* {{{ file/dir path init */
+	memset(&const_usage, 0, sizeof(const_usage));
+	php->filepath     = zend_get_compiled_filename(TSRMLS_C);
+	php->filepath_len = strlen(php->filepath);
+	php->dirpath      = estrndup(php->filepath, php->filepath_len);
+	php->dirpath_len  = zend_dirname(php->dirpath, php->filepath_len);
+#ifdef IS_UNICODE
+	zend_string_to_unicode(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), &php->ufilepath, &php->ufilepath_len, php->filepath, php->filepath_len TSRMLS_CC);
+	zend_string_to_unicode(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), &php->udirpath,  &php->udirpath_len,  php->dirpath,  php->dirpath_len TSRMLS_CC);
+#endif
 	/* }}} */
 	/* {{{ shallow copy, pointers only */ {
@@ -1242,4 +1462,31 @@
 		b = CG(class_table)->pListHead;    COPY_H(xc_classinfo_t, classinfos, classinfo_cnt, cest,     xc_cest_t);
 
+		for (i = 0; i < php->classinfo_cnt; i ++) {
+			xc_classinfo_t *classinfo = &php->classinfos[i];
+			zend_class_entry *ce = CestToCePtr(classinfo->cest);
+			classinfo->methodinfo_cnt = ce->function_table.nTableSize;
+			if (classinfo->methodinfo_cnt) {
+				int j;
+
+				ECALLOC_N(classinfo->methodinfos, classinfo->methodinfo_cnt);
+				if (!classinfo->methodinfos) {
+					goto err_alloc;
+				}
+
+				for (j = 0, b = ce->function_table.pListHead; b; j ++, b = b->pListNext) {
+					xc_collect_op_array_info(php, &const_usage, &classinfo->methodinfos[j], (zend_op_array *) b->pData TSRMLS_CC);
+				}
+			}
+			else {
+				classinfo->methodinfos = NULL;
+			}
+		}
+
+		for (i = 0; i < php->funcinfo_cnt; i ++) {
+			xc_collect_op_array_info(php, &const_usage, &php->funcinfos[i].op_array_info, (zend_op_array *) &php->funcinfos[i].func TSRMLS_CC);
+		}
+
+		xc_collect_op_array_info(php, &const_usage, &php->op_array_info, php->op_array TSRMLS_CC);
+
 #undef COPY_H
 
@@ -1271,4 +1518,22 @@
 	}
 	/* }}} */
+	/* {{{ file/dir path free unused */
+#define X_FREE_UNUSED(var) \
+	if (!const_usage.var##path_used) { \
+		efree(php->var##path); \
+		php->var##path = NULL; \
+		php->var##path_len = 0; \
+	}
+	if (!const_usage.filepath_used) {
+		php->filepath = NULL;
+		php->filepath_len = 0;
+	}
+	X_FREE_UNUSED(dir)
+#ifdef IS_UNICODE
+	X_FREE_UNUSED(ufile)
+	X_FREE_UNUSED(udir)
+#endif
+#undef X_FREE_UNUSED
+	/* }}} */
 #ifdef E_STRICT
 	php->compilererrors = ((xc_sandbox_t *) XG(sandbox))->compilererrors;
@@ -1467,4 +1732,6 @@
 		php.autoglobals = NULL;
 #endif
+		memset(&php.op_array_info, 0, sizeof(php.op_array_info));
+
 		zend_try {
 			op_array = xc_compile_php(&php, h, type TSRMLS_CC);
@@ -1638,19 +1905,7 @@
 /* }}} */
 
-#ifdef ZEND_ENGINE_2
-/* {{{ xc_gc_op_array_t */
-typedef struct {
-	zend_uint num_args;
-	zend_arg_info *arg_info;
-} xc_gc_op_array_t;
-/* }}} */
-void xc_gc_add_op_array(zend_op_array *op_array TSRMLS_DC) /* {{{ */
-{
-	xc_gc_op_array_t gc_op_array;
-	gc_op_array.num_args = op_array->num_args;
-	gc_op_array.arg_info = op_array->arg_info;
-#ifdef ZEND_ENGINE_2
-	zend_llist_add_element(&XG(gc_op_arrays), (void *) &gc_op_array);
-#endif
+void xc_gc_add_op_array(xc_gc_op_array_t *gc_op_array TSRMLS_DC) /* {{{ */
+{
+	zend_llist_add_element(&XG(gc_op_arrays), (void *) gc_op_array);
 }
 /* }}} */
@@ -1659,4 +1914,5 @@
 	xc_gc_op_array_t *op_array = (xc_gc_op_array_t *) pDest;
 	zend_uint i;
+#ifdef ZEND_ENGINE_2
 	if (op_array->arg_info) {
 		for (i = 0; i < op_array->num_args; i++) {
@@ -1668,7 +1924,10 @@
 		efree(op_array->arg_info);
 	}
-}
-/* }}} */
-#endif
+#endif
+	if (op_array->opcodes) {
+		efree(op_array->opcodes);
+	}
+}
+/* }}} */
 
 /* module helper function */
Index: /trunk/xcache.h
===================================================================
--- /trunk/xcache.h	(revision 661)
+++ /trunk/xcache.h	(revision 662)
@@ -62,4 +62,8 @@
 #ifndef IS_CONSTANT_TYPE_MASK
 #	define IS_CONSTANT_TYPE_MASK (~IS_CONSTANT_INDEX)
+#endif
+
+#ifndef ZEND_ENGINE_2_3
+#define zend_dirname(path, len) xc_dirname(path, len)
 #endif
 
@@ -238,4 +242,10 @@
 } xc_cache_t;
 /* }}} */
+/* {{{ xc_op_array_info_t */
+typedef struct {
+	zend_uint oplineinfo_cnt;
+	int *oplineinfos;
+} xc_op_array_info_t;
+/* }}} */
 /* {{{ xc_classinfo_t */
 typedef struct {
@@ -246,4 +256,6 @@
 	zend_uint key_size;
 	ulong     h;
+	zend_uint methodinfo_cnt;
+	xc_op_array_info_t *methodinfos;
 	xc_cest_t cest;
 #ifndef ZEND_COMPILE_DELAYED_BINDING
@@ -273,4 +285,5 @@
 	zend_uint key_size;
 	ulong     h;
+	xc_op_array_info_t op_array_info;
 	zend_function func;
 } xc_funcinfo_t;
@@ -311,4 +324,16 @@
 	size_t     size;
 
+	int    filepath_len;
+	char  *filepath;
+	int    dirpath_len;
+	char  *dirpath;
+#ifdef IS_UNICODE
+	UChar *ufilepath;
+	int    ufilepath_len;
+	UChar *udirpath;
+	int    udirpath_len;
+#endif
+
+	xc_op_array_info_t op_array_info;
 	zend_op_array *op_array;
 
@@ -387,5 +412,16 @@
 int xc_is_ro(const void *p);
 int xc_is_shm(const void *p);
-void xc_gc_add_op_array(zend_op_array *op_array TSRMLS_DC);
+/* {{{ xc_gc_op_array_t */
+typedef struct {
+#ifdef ZEND_ENGINE_2
+	zend_uint num_args;
+	zend_arg_info *arg_info;
+#endif
+	zend_uint last;
+	zend_op *opcodes;
+} xc_gc_op_array_t;
+/* }}} */
+void xc_gc_add_op_array(xc_gc_op_array_t *gc_op_array TSRMLS_DC);
+void xc_fix_op_array_info(const xc_entry_data_php_t *php, zend_op_array *op_array, int shallow_copied, const xc_op_array_info_t *op_array_info TSRMLS_DC);
 
 #endif /* __XCACHE_H */
Index: /trunk/xcache_globals.h
===================================================================
--- /trunk/xcache_globals.h	(revision 661)
+++ /trunk/xcache_globals.h	(revision 662)
@@ -18,7 +18,5 @@
 	long   var_ttl;
 
-#ifdef ZEND_ENGINE_2
 	zend_llist gc_op_arrays;
-#endif
 
 #ifdef HAVE_XCACHE_CONSTANT
