Index: /trunk/ChangeLog
===================================================================
--- /trunk/ChangeLog	(revision 715)
+++ /trunk/ChangeLog	(revision 716)
@@ -12,4 +12,5 @@
 1.3.2 2011-??-??
 ========
+ * PHP_6: initial catch up with php 6 literals and trait
  * disassembler: DECLARE_INHERITED_CLASS/DELAYED class not found
  * disassembler: don't dump builtin functions
Index: /trunk/Decompiler.class.php
===================================================================
--- /trunk/Decompiler.class.php	(revision 715)
+++ /trunk/Decompiler.class.php	(revision 716)
@@ -28,5 +28,5 @@
 
 	if (is_array($src)) {
-		die_error('array str');
+		exit('array str');
 		$src = new Decompiler_Array($src, $indent);
 		return $src->__toString();
@@ -36,5 +36,5 @@
 		if (!method_exists($src, '__toString')) {
 			var_dump($src);
-			die_error('no __toString');
+			exit('no __toString');
 		}
 		return $src->__toString();
@@ -426,20 +426,20 @@
 		switch ($op['op_type']) {
 		case XC_IS_CONST:
-			return str(value($op['u.constant']));
+			return str(value($op['constant']));
 
 		case XC_IS_VAR:
 		case XC_IS_TMP_VAR:
 			$T = &$EX['Ts'];
-			$ret = $T[$op['u.var']];
+			$ret = $T[$op['var']];
 			if ($tostr) {
 				$ret = str($ret, $EX);
 			}
 			if ($free) {
-				unset($T[$op['u.var']]);
+				unset($T[$op['var']]);
 			}
 			return $ret;
 
 		case XC_IS_CV:
-			$var = $op['u.var'];
+			$var = $op['var'];
 			$var = $EX['op_array']['vars'][$var];
 			return '$' . $var['name'];
@@ -448,4 +448,17 @@
 			return null;
 		}
+	}
+	// }}}
+	function removeKeyPrefix($array, $prefix) // {{{
+	{
+		$prefixLen = strlen($prefix);
+		$ret = array();
+		foreach ($array as $key => $value) {
+			if (substr($key, 0, $prefixLen) == $prefix) {
+				$key = substr($key, $prefixLen);
+			}
+			$ret[$key] = $value;
+		}
+		return $ret;
 	}
 	// }}}
@@ -458,7 +471,35 @@
 		}
 		$EX['indent'] = '';
-		//for ($i = 0, $cnt = count($opcodes); $i < $cnt; $i ++) {
-		//	$opcodes[$i]['opcode'] = xcache_get_fixed_opcode($opcodes[$i]['opcode'], $i);
-		//}
+		for ($i = 0, $cnt = count($opcodes); $i < $cnt; $i ++) {
+			if (function_exists('xcache_get_fixed_opcode')) {
+				$opcodes[$i]['opcode'] = xcache_get_fixed_opcode($opcodes[$i]['opcode'], $i);
+			}
+			if (isset($opcodes[$i]['op1'])) {
+				$opcodes[$i]['op1'] = $this->removeKeyPrefix($opcodes[$i]['op1'], 'u.');
+				$opcodes[$i]['op2'] = $this->removeKeyPrefix($opcodes[$i]['op2'], 'u.');
+				$opcodes[$i]['result'] = $this->removeKeyPrefix($opcodes[$i]['result'], 'u.');
+			}
+			else {
+				$op = array(
+					'op1' => array(),
+					'op2' => array(),
+					'op3' => array(),
+				);
+				foreach ($opcodes[$i] as $name => $value) {
+					if (preg_match('!^(op1|op2|result)\\.(.*)!', $name, $m)) {
+						list(, $which, $field) = $m;
+						$op[$which][$field] = $value;
+					}
+					else if (preg_match('!^(op1|op2|result)_type$!', $name, $m)) {
+						list(, $which) = $m;
+						$op[$which]['op_type'] = $value;
+					}
+					else {
+						$op[$name] = $value;
+					}
+				}
+				$opcodes[$i] = $op;
+			}
+		}
 		// {{{ build jmp array
 		for ($i = 0, $cnt = count($opcodes); $i < $cnt; $i ++) {
@@ -474,5 +515,5 @@
 			switch ($op['opcode']) {
 			case XC_JMP:
-				$target = $op['op1']['u.var'];
+				$target = $op['op1']['var'];
 				$op['jmpouts'] = array($target);
 				$opcodes[$target]['jmpins'][] = $i;
@@ -480,5 +521,5 @@
 
 			case XC_JMPZNZ:
-				$jmpz = $op['op2']['u.opline_num'];
+				$jmpz = $op['op2']['opline_num'];
 				$jmpnz = $op['extended_value'];
 				$op['jmpouts'] = array($jmpz, $jmpnz);
@@ -494,5 +535,5 @@
 			case XC_FE_FETCH:
 			// case XC_JMP_NO_CTOR:
-				$target = $op['op2']['u.opline_num'];
+				$target = $op['op2']['opline_num'];
 				//if (!isset($target)) {
 				//	$this->dumpop($op, $EX);
@@ -581,5 +622,5 @@
 		if ($op['opcode'] == XC_FE_FETCH) {
 			$opline = $next;
-			$next = $op['op2']['u.opline_num'];
+			$next = $op['op2']['opline_num'];
 			$end = $next - 1;
 
@@ -600,10 +641,10 @@
 		/*
 		if ($op['opcode'] == XC_JMPZ) {
-			$target = $op2['u.opline_num'];
+			$target = $op2['opline_num'];
 			if ($line + 1) {
 				$nextblock = $EX['nextbbs'][$next];
 				$jmpop = end($nextblock);
 				if ($jmpop['opcode'] == XC_JMP) {
-					$ifendline = $op2['u.opline_num'];
+					$ifendline = $op2['opline_num'];
 					if ($ifendline >= $line) {
 						$cond = $op['cond'];
@@ -650,5 +691,5 @@
 				}
 
-				$var = $fromop['result']['u.var'];
+				$var = $fromop['result']['var'];
 				var_dump($EX['Ts'][$var]);
 				$EX['Ts'][$var] = '(' . $fromop['and_or'] . " $opstr " . $EX['Ts'][$var] . ')';
@@ -712,5 +753,5 @@
 
 			$resvar = null;
-			if (($res['u.EA.type'] & EXT_TYPE_UNUSED) || $res['op_type'] == XC_IS_UNUSED) {
+			if (isset($res['EA.type']) && ($res['EA.type'] & EXT_TYPE_UNUSED) || $res['op_type'] == XC_IS_UNUSED) {
 				$istmpres = false;
 			}
@@ -743,5 +784,5 @@
 				case XC_NEW: // {{{
 					array_push($EX['arg_types_stack'], array($EX['object'], $EX['fbc']));
-					$EX['object'] = (int) $res['u.var'];
+					$EX['object'] = (int) $res['var'];
 					$EX['fbc'] = 'new ' . $this->unquoteName($this->getOpVal($op1, $EX));
 					if (PHP_VERSION < 5) {
@@ -761,5 +802,5 @@
 					}
 					else {
-						$class = $op2['u.constant'];
+						$class = $op2['constant'];
 						if (is_object($class)) {
 							$class = get_class($class);
@@ -771,13 +812,13 @@
 				case XC_FETCH_CONSTANT: // {{{
 					if ($op1['op_type'] == XC_IS_CONST) {
-						$resvar = $op1['u.constant'];
+						$resvar = $op1['constant'];
 					}
 					else if ($op1['op_type'] == XC_IS_UNUSED) {
-						$resvar = $op2['u.constant'];
+						$resvar = $op2['constant'];
 					}
 					else {
-						$class = $T[$op1['u.var']];
+						$class = $T[$op1['var']];
 						assert($class[0] == 'class');
-						$resvar = $class[1] . '::' . $op2['u.constant'];
+						$resvar = $class[1] . '::' . $op2['constant'];
 					}
 					break;
@@ -792,5 +833,5 @@
 				case XC_UNSET_VAR:
 					$rvalue = $this->getOpVal($op1, $EX);
-					$fetchtype = $op2[PHP_VERSION < 5 ? 'u.fetch_type' : 'u.EA.type'];
+					$fetchtype = $op2[PHP_VERSION < 5 ? 'fetch_type' : 'EA.type'];
 					switch ($fetchtype) {
 					case ZEND_FETCH_STATIC_MEMBER:
@@ -838,10 +879,10 @@
 
 							$src = new Decompiler_ListBox($list);
-							if (!isset($op1['u.var'])) {
+							if (!isset($op1['var'])) {
 								$this->dumpop($op, $EX);
 								var_dump($op);
-								die('missing u.var');
+								die('missing var');
 							}
-							$T[$op1['u.var']] = $src;
+							$T[$op1['var']] = $src;
 							unset($list);
 						}
@@ -883,5 +924,5 @@
 						$type = $rvalue->iskey ? 'fe_key' : 'fe_as';
 						$rvalue->obj[$type] = $lvalue;
-						unset($T[$op2['u.var']]);
+						unset($T[$op2['var']]);
 						break;
 					}
@@ -969,5 +1010,5 @@
 							$rvalue = "${" . $rvalue . "}";
 						}
-						if ($op2['u.EA.type'] == ZEND_FETCH_STATIC_MEMBER) {
+						if ($op2['EA.type'] == ZEND_FETCH_STATIC_MEMBER) {
 							$class = $this->getOpVal($op2, $EX);
 							$rvalue = $class . '::' . $rvalue;
@@ -983,5 +1024,5 @@
 					}
 
-					switch (PHP_VERSION < 5 ? $op['op2']['u.var'] /* u.constant */ : $ext) {
+					switch ((PHP_VERSION < 5 ? $op['op2']['var'] /* constant */ : $ext) & (ZEND_ISSET|ZEND_ISEMPTY)) {
 					case ZEND_ISSET:
 						$rvalue = "isset($rvalue)";
@@ -990,7 +1031,4 @@
 						$rvalue = "empty($rvalue)";
 						break;
-					default:
-						$this->dumpop($op, $EX);
-						die_error('1');
 					}
 					$resvar = $rvalue;
@@ -1027,5 +1065,5 @@
 
 					if ($opc == XC_INIT_FCALL_BY_FUNC) {
-						$which = $op1['u.var'];
+						$which = $op1['var'];
 						$EX['fbc'] = $EX['op_array']['funcs'][$which]['name'];
 					}
@@ -1036,5 +1074,5 @@
 					// }}}
 				case XC_DO_FCALL_BY_FUNC:
-					$which = $op1['u.var'];
+					$which = $op1['var'];
 					$fname = $EX['op_array']['funcs'][$which]['name'];
 					$args = $this->popargs($EX, $ext);
@@ -1069,5 +1107,5 @@
 					// }}}
 				case XC_VERIFY_ABSTRACT_CLASS: // {{{
-					//unset($T[$op1['u.var']]);
+					//unset($T[$op1['var']]);
 					break;
 					// }}}
@@ -1075,5 +1113,5 @@
 				case XC_DECLARE_INHERITED_CLASS:
 				case XC_DECLARE_INHERITED_CLASS_DELAYED: // {{{
-					$key = $op1['u.constant'];
+					$key = $op1['constant'];
 					if (!isset($this->dc['class_table'][$key])) {
 						echo 'class not found: ', $key, 'existing classes are:', "\n";
@@ -1094,5 +1132,5 @@
 					while ($i + 2 < $ic
 					 && $opcodes[$i + 2]['opcode'] == XC_ADD_INTERFACE
-					 && $opcodes[$i + 2]['op1']['u.var'] == $res['u.var']
+					 && $opcodes[$i + 2]['op1']['var'] == $res['var']
 					 && $opcodes[$i + 1]['opcode'] == XC_FETCH_CLASS) {
 						$fetchop = &$opcodes[$i + 1];
@@ -1160,8 +1198,8 @@
 						$offset = $this->getOpVal($op2, $EX);
 						if (isset($offset)) {
-							$T[$res['u.var']]->value[$offset] = $rvalue;
+							$T[$res['var']]->value[$offset] = $rvalue;
 						}
 						else {
-							$T[$res['u.var']]->value[] = $rvalue;
+							$T[$res['var']]->value[] = $rvalue;
 						}
 					}
@@ -1197,5 +1235,5 @@
 					// }}}
 				case XC_INCLUDE_OR_EVAL: // {{{
-					$type = $op2['u.var']; // hack
+					$type = $op2['var']; // hack
 					$keyword = $this->includeTypes[$type];
 					$resvar = "$keyword(" . $this->getOpVal($op1, $EX) . ")";
@@ -1210,5 +1248,5 @@
 					$fe = new Decompiler_ForeachBox($op);
 					$fe->iskey = false;
-					$T[$res['u.var']] = $fe;
+					$T[$res['var']] = $fe;
 
 					++ $i;
@@ -1218,19 +1256,19 @@
 
 						$res = $opcodes[$i]['result'];
-						$T[$res['u.var']] = $fe;
+						$T[$res['var']] = $fe;
 					}
 					break;
 					// }}}
 				case XC_SWITCH_FREE: // {{{
-					// unset($T[$op1['u.var']]);
+					// unset($T[$op1['var']]);
 					break;
 					// }}}
 				case XC_FREE: // {{{
-					$free = $T[$op1['u.var']];
+					$free = $T[$op1['var']];
 					if (!is_a($free, 'Decompiler_Array') && !is_a($free, 'Decompiler_Box')) {
 						$op['php'] = is_object($free) ? $free : $this->unquote($free, '(', ')');
 						$lastphpop = &$op;
 					}
-					unset($T[$op1['u.var']], $free);
+					unset($T[$op1['var']], $free);
 					break;
 					// }}}
@@ -1258,5 +1296,5 @@
 					}
 					if ($opc == XC_JMPZ_EX || $opc == XC_JMPNZ_EX || $opc == XC_JMPZ) {
-						$targetop = &$EX['opcodes'][$op2['u.opline_num']];
+						$targetop = &$EX['opcodes'][$op2['opline_num']];
 						if ($opc == XC_JMPNZ_EX) {
 							$targetop['cond_true'][] = str($rvalue);
@@ -1286,5 +1324,5 @@
 					$lvalue = $this->getOpVal($op['result'], $EX);
 					if ($opc == XC_RECV_INIT) {
-						$default = value($op['op2']['u.constant']);
+						$default = value($op['op2']['constant']);
 					}
 					else {
@@ -1372,6 +1410,6 @@
 			if (isset($resvar)) {
 				if ($istmpres) {
-					$T[$res['u.var']] = $resvar;
-					$lastresvar = &$T[$res['u.var']];
+					$T[$res['var']] = $resvar;
+					$lastresvar = &$T[$res['var']];
 				}
 				else {
@@ -1419,9 +1457,9 @@
 			switch ($op[$k]['op_type']) {
 			case XC_IS_UNUSED:
-				$d[$kk] = '*UNUSED* ' . $op[$k]['u.opline_num'];
+				$d[$kk] = '*UNUSED* ' . $op[$k]['opline_num'];
 				break;
 
 			case XC_IS_VAR:
-				$d[$kk] = '$' . $op[$k]['u.var'];
+				$d[$kk] = '$' . $op[$k]['var'];
 				if ($kk != 'res') {
 					$d[$kk] .= ':' . $this->getOpVal($op[$k], $EX);
@@ -1430,5 +1468,5 @@
 
 			case XC_IS_TMP_VAR:
-				$d[$kk] = '#' . $op[$k]['u.var'];
+				$d[$kk] = '#' . $op[$k]['var'];
 				if ($kk != 'res') {
 					$d[$kk] .= ':' . $this->getOpVal($op[$k], $EX);
Index: /trunk/NEWS
===================================================================
--- /trunk/NEWS	(revision 715)
+++ /trunk/NEWS	(revision 716)
@@ -4,4 +4,5 @@
 1.3.2 2011-??-??
 ========
+ * PHP_6: catch up with php 6 devel
  * memory leak on recompile
  * disassembler fixes and updates for new PHP
Index: /trunk/coverager.c
===================================================================
--- /trunk/coverager.c	(revision 715)
+++ /trunk/coverager.c	(revision 716)
@@ -379,13 +379,11 @@
 static int xc_coverager_get_op_array_size_no_tail(zend_op_array *op_array) /* {{{ */
 {
-	zend_uint size;
-
-	size = op_array->size;
+	zend_uint last = op_array->last;
 	do {
 next_op:
-		if (size == 0) {
+		if (last == 0) {
 			break;
 		}
-		switch (op_array->opcodes[size - 1].opcode) {
+		switch (op_array->opcodes[last - 1].opcode) {
 #ifdef ZEND_HANDLE_EXCEPTION
 			case ZEND_HANDLE_EXCEPTION:
@@ -393,9 +391,9 @@
 			case ZEND_RETURN:
 			case ZEND_EXT_STMT:
-				size --;
+				--last;
 				goto next_op;
 		}
 	} while (0);
-	return size;
+	return last;
 }
 /* }}} */
Index: /trunk/optimizer.c
===================================================================
--- /trunk/optimizer.c	(revision 715)
+++ /trunk/optimizer.c	(revision 716)
@@ -64,13 +64,13 @@
 			continue;
 		}
-		if (opline->op2.op_type != IS_CONST
-		 || opline->op2.u.constant.type != IS_LONG) {
+		if (Z_OP_TYPE(opline->op2) != IS_CONST
+		 || Z_OP_CONSTANT(opline->op2).type != IS_LONG) {
 			return FAILURE;
 		}
 
-		nest_levels = opline->op2.u.constant.value.lval;
+		nest_levels = Z_OP_CONSTANT(opline->op2).value.lval;
 		original_nest_levels = nest_levels;
 
-		array_offset = opline->op1.u.opline_num;
+		array_offset = Z_OP(opline->op1).opline_num;
 		do {
 			if (array_offset == -1) {
@@ -96,10 +96,10 @@
 		/* rewrite to jmp */
 		if (opline->opcode == ZEND_BRK) {
-			opline->op1.u.opline_num = jmp_to->brk;
+			Z_OP(opline->op1).opline_num = jmp_to->brk;
 		}
 		else {
-			opline->op1.u.opline_num = jmp_to->cont;
-		}
-		opline->op2.op_type = IS_UNUSED;
+			Z_OP(opline->op1).opline_num = jmp_to->cont;
+		}
+		Z_OP_TYPE(opline->op2) = IS_UNUSED;
 		opline->opcode = ZEND_JMP;
 	}
@@ -143,9 +143,9 @@
 
 	case ZEND_JMP:
-		fi->jmpout_op1 = opline->op1.u.opline_num;
+		fi->jmpout_op1 = Z_OP(opline->op1).opline_num;
 		return SUCCESS; /* no fall */
 
 	case ZEND_JMPZNZ:
-		fi->jmpout_op2 = opline->op2.u.opline_num;
+		fi->jmpout_op2 = Z_OP(opline->op2).opline_num;
 		fi->jmpout_ext = (int) opline->extended_value;
 		return SUCCESS; /* no fall */
@@ -168,5 +168,5 @@
 #endif      
 	case ZEND_FE_FETCH:
-		fi->jmpout_op2 = opline->op2.u.opline_num;
+		fi->jmpout_op2 = Z_OP(opline->op2).opline_num;
 		break;
 
@@ -186,13 +186,14 @@
 /* }}} */
 #ifdef XCACHE_DEBUG
-static void op_snprint(char *buf, int size, znode *op) /* {{{ */
-{
-	switch (op->op_type) {
+static void op_snprint(char *buf, int size, zend_uchar op_type, znode_op *op) /* {{{ */
+{
+	switch (op_type) {
 	case IS_CONST:
 		{
 			zval result;
-			zval *zv = &op->u.constant;
+			zval *zv = &Z_OP_CONSTANT(*op);
 			TSRMLS_FETCH();
 
+			/* TODO: update for PHP 6 */
 			php_start_ob_buffer(NULL, 0, 1 TSRMLS_CC);
 			php_var_export(&zv, 1 TSRMLS_CC);
@@ -206,15 +207,15 @@
 
 	case IS_TMP_VAR:
-		snprintf(buf, size, "t@%d", op->u.var);
+		snprintf(buf, size, "t@%d", Z_OP(*op).var);
 		break;
 
 	case XCACHE_IS_CV:
 	case IS_VAR:
-		snprintf(buf, size, "v@%d", op->u.var);
+		snprintf(buf, size, "v@%d", Z_OP(*op).var);
 		break;
 
 	case IS_UNUSED:
-		if (op->u.opline_num) {
-			snprintf(buf, size, "u#%d", op->u.opline_num);
+		if (Z_OP(*op).opline_num) {
+			snprintf(buf, size, "u#%d", Z_OP(op).opline_num);
 		}
 		else {
@@ -224,5 +225,5 @@
 
 	default:
-		snprintf(buf, size, "%d %d", op->op_type, op->u.var);
+		snprintf(buf, size, "%d %d", op->op_type, Z_OP(op).var);
 	}
 }
@@ -235,7 +236,7 @@
 		char buf_1[20];
 		char buf_2[20];
-		op_snprint(buf_r, sizeof(buf_r), &opline->result);
-		op_snprint(buf_1, sizeof(buf_1), &opline->op1);
-		op_snprint(buf_2, sizeof(buf_2), &opline->op2);
+		op_snprint(buf_r, sizeof(buf_r), Z_OP_TYPE(opline->result), &opline->result);
+		op_snprint(buf_1, sizeof(buf_1), Z_OP_TYPE(opline->op1),    &opline->op1);
+		op_snprint(buf_2, sizeof(buf_2), Z_OP_TYPE(opline->op2),    &opline->op2);
 		fprintf(stderr,
 				"%3d %3d"
@@ -451,10 +452,10 @@
 		if (op_get_flowinfo(&fi, opline) == SUCCESS) {
 			if (fi.jmpout_op1 != XC_OPNUM_INVALID) {
-				opline->op1.u.opline_num = bbids[fi.jmpout_op1];
-				assert(opline->op1.u.opline_num != BBID_INVALID);
+				Z_OP(opline->op1).opline_num = bbids[fi.jmpout_op1];
+				assert(Z_OP(opline->op1).opline_num != BBID_INVALID);
 			}
 			if (fi.jmpout_op2 != XC_OPNUM_INVALID) {
-				opline->op2.u.opline_num = bbids[fi.jmpout_op2];
-				assert(opline->op2.u.opline_num != BBID_INVALID);
+				Z_OP(opline->op2).opline_num = bbids[fi.jmpout_op2];
+				assert(Z_OP(opline->op2).opline_num != BBID_INVALID);
 			}
 			if (fi.jmpout_ext != XC_OPNUM_INVALID) {
@@ -499,10 +500,10 @@
 		if (op_get_flowinfo(&fi, last) == SUCCESS) {
 			if (fi.jmpout_op1 != XC_OPNUM_INVALID) {
-				last->op1.u.opline_num = bbs_get(bbs, fi.jmpout_op1)->opnum;
-				assert(last->op1.u.opline_num != BBID_INVALID);
+				Z_OP(last->op1).opline_num = bbs_get(bbs, fi.jmpout_op1)->opnum;
+				assert(Z_OP(last->op1).opline_num != BBID_INVALID);
 			}
 			if (fi.jmpout_op2 != XC_OPNUM_INVALID) {
-				last->op2.u.opline_num = bbs_get(bbs, fi.jmpout_op2)->opnum;
-				assert(last->op2.u.opline_num != BBID_INVALID);
+				Z_OP(last->op2).opline_num = bbs_get(bbs, fi.jmpout_op2)->opnum;
+				assert(Z_OP(last->op2).opline_num != BBID_INVALID);
 			}
 			if (fi.jmpout_ext != XC_OPNUM_INVALID) {
Index: /trunk/processor/processor.m4
===================================================================
--- /trunk/processor/processor.m4	(revision 715)
+++ /trunk/processor/processor.m4	(revision 716)
@@ -223,9 +223,15 @@
 	DISPATCH(zend_uint, class_name_len)
 	PROC_ZSTRING_L(, class_name, class_name_len)
+#ifdef ZEND_ENGINE_2_4
+	DISPATCH(zend_uchar, type_hint)
+#else
 	DISPATCH(zend_bool, array_type_hint)
+#endif
 	DISPATCH(zend_bool, allow_null)
 	DISPATCH(zend_bool, pass_by_reference)
+#ifndef ZEND_ENGINE_2_4
 	DISPATCH(zend_bool, return_reference)
 	DISPATCH(int, required_num_args)
+#endif
 ')
 #endif
@@ -273,4 +279,7 @@
 	PROC_ZSTRING_L(, name, name_length)
 	DISPATCH(ulong, h)
+#ifdef ZEND_ENGINE_2_4
+	DISPATCH(int, offset)
+#endif
 #ifdef ZEND_ENGINE_2_1
 	DISPATCH(int, doc_comment_len)
@@ -307,31 +316,57 @@
 	STRUCT_P(int, refcount)
 #endif
+#ifndef ZEND_ENGINE_2_4
 	DISPATCH(zend_bool, constants_updated)
+#endif
 #ifdef ZEND_ENGINE_2
 	DISPATCH(zend_uint, ce_flags)
 #endif
 
-	STRUCT(HashTable, default_properties, HashTable_zval_ptr)
+#ifdef ZEND_ENGINE_2_4
+	DISPATCH(int, default_properties_count)
+	STRUCT_ARRAY(default_properties_count, zval, default_properties_table)
+	DISPATCH(int, default_static_members_count)
+	STRUCT_ARRAY(default_static_members_count, zval, default_static_members_table)
+	IFCOPY(`dst->static_members_table = &dst->default_static_members_table;')
+	DONE(static_members_table)
+#else
 	IFCOPY(`dst->builtin_functions = src->builtin_functions;')
 	DONE(builtin_functions)
-#ifdef ZEND_ENGINE_2
+	STRUCT(HashTable, default_properties, HashTable_zval_ptr)
+#	ifdef ZEND_ENGINE_2
 	STRUCT(HashTable, properties_info, HashTable_zend_property_info)
-#	ifdef ZEND_ENGINE_2_1
+#		ifdef ZEND_ENGINE_2_1
 	STRUCT(HashTable, default_static_members, HashTable_zval_ptr)
 	IFCOPY(`dst->static_members = &dst->default_static_members;')
 	DONE(static_members)
-#	else
+#		else
 	STRUCT_P(HashTable, static_members, HashTable_zval_ptr)
-#	endif
+#		endif
+#	endif
+#endif /* ZEND_ENGINE_2_4 */
+
+#ifdef ZEND_ENGINE_2
 	STRUCT(HashTable, constants_table, HashTable_zval_ptr)
 
 	dnl runtime binding: ADD_INTERFACE will deal with it
+	dnl runtime binding: ADD_TRAIT will deal with it
 	IFRESTORE(`
 		if (src->num_interfaces) {
 			CALLOC(dst->interfaces, zend_class_entry*, src->num_interfaces)
 			DONE(`interfaces')
+#	ifdef ZEND_ENGINE_2_4
+			CALLOC(dst->traits, zend_class_entry*, src->num_traits)
+			DONE(`traits')
+			DONE(`trait_aliases')
+			DONE(`trait_precedences')
+#	endif
 		}
 		else {
-			COPYNULL(interfaces)
+			COPYNULL(`interfaces')
+#	ifdef ZEND_ENGINE_2_4
+			COPYNULL(`traits')
+			COPYNULL(`trait_aliases')
+			COPYNULL(`trait_precedences')
+#	endif
 		}
 	')
@@ -351,7 +386,17 @@
 			*/
 			DONE(`interfaces')
+#	ifdef ZEND_ENGINE_2_4
+			DONE(`traits')
+			DONE(`trait_aliases')
+			DONE(`trait_precedences')
+#	endif
 		}
 		else {
-			COPYNULL(interfaces)
+			COPYNULL(`interfaces')
+#	ifdef ZEND_ENGINE_2_4
+			COPYNULL(`traits')
+			COPYNULL(`trait_aliases')
+			COPYNULL(`trait_precedences')
+#	endif
 		}
 	')
@@ -359,15 +404,35 @@
 		IFDASM(`', `
 			DONE(`interfaces')
+#	ifdef ZEND_ENGINE_2_4
+			DONE(`traits')
+			DONE(`trait_aliases')
+			DONE(`trait_precedences')
+#	endif
 		')
 	')
 	DISPATCH(zend_uint, num_interfaces)
-
+#	ifdef ZEND_ENGINE_2_4
+	DISPATCH(zend_uint, num_traits)
+#	endif
+
+#	ifdef ZEND_ENGINE_2_4
+	DISABLECHECK(`
+	IFRESTORE(`dst->info.user.filename = processor->entry_src->filepath;', `PROC_STRING(info.user.filename)')
+	DISPATCH(zend_uint, info.user.line_start)
+	DISPATCH(zend_uint, info.user.line_end)
+	DISPATCH(zend_uint, info.user.doc_comment_len)
+	PROC_ZSTRING_L(, info.user.doc_comment, info.user.doc_comment_len)
+	')
+	DONE(info)
+#	else
 	IFRESTORE(`dst->filename = processor->entry_src->filepath;DONE(filename)', `PROC_STRING(filename)')
 	DISPATCH(zend_uint, line_start)
 	DISPATCH(zend_uint, line_end)
-#ifdef ZEND_ENGINE_2_1
+#		ifdef ZEND_ENGINE_2_1
 	DISPATCH(zend_uint, doc_comment_len)
 	PROC_ZSTRING_L(, doc_comment, doc_comment_len)
-#endif
+#		endif
+#	endif
+
 	/* # NOT DONE */
 	COPY(serialize_func)
@@ -377,7 +442,7 @@
 	COPY(get_iterator)
 	COPY(interface_gets_implemented)
-#ifdef ZEND_ENGINE_2_3
+#	ifdef ZEND_ENGINE_2_3
 	COPY(get_static_method)
-#endif
+#	endif
 	COPY(serialize)
 	COPY(unserialize)
@@ -389,18 +454,20 @@
 	COPY(__set)
 /* should be >5.1 */
-#ifdef ZEND_ENGINE_2_1
+#	ifdef ZEND_ENGINE_2_1
 	COPY(__unset)
 	COPY(__isset)
-# if defined(ZEND_ENGINE_2_2) || PHP_MAJOR_VERSION >= 6
+#	 if defined(ZEND_ENGINE_2_2) || PHP_MAJOR_VERSION >= 6
 	COPY(__tostring)
-# endif
-#endif
+#	 endif
+#	endif
 	COPY(__call)
-#ifdef ZEND_CALLSTATIC_FUNC_NAME
+#	ifdef ZEND_CALLSTATIC_FUNC_NAME
 	COPY(__callstatic)
-#endif
+#	endif
+#	ifndef ZEND_ENGINE_2_4
 	/* # NOT DONE */
 	COPY(module)
-#else
+#	endif
+#else /* ZEND_ENGINE_2 */
 	COPY(handle_function_call)
 	COPY(handle_property_get)
@@ -416,4 +483,50 @@
 ')
 dnl }}}
+#ifdef ZEND_ENGINE_2_4
+undefine(`UNION_znode_op')
+define(`UNION_znode_op', `dnl {{{
+	assert(src->$1_type == IS_CONST ||
+		src->$1_type == IS_VAR ||
+		src->$1_type == IS_CV ||
+		src->$1_type == IS_TMP_VAR ||
+		src->$1_type == IS_UNUSED);
+	dnl dirty dispatch
+	DISABLECHECK(`
+	switch (src->$1_type) {
+		case IS_CONST:
+			dnl TODO: fix me, use literals
+			IFDASM(`{
+				zval *zv;
+				ALLOC_INIT_ZVAL(zv);
+				*zv = ((zend_literal *) src->$1.ptr)->constant;
+				zval_copy_ctor(zv);
+				add_assoc_zval_ex(dst, ZEND_STRS("$1.constant"), zv);
+				}
+			', `
+				DISPATCH(zend_uint, $1.constant)
+			')
+			break;
+		IFCOPY(`
+			IFNOTMEMCPY(`
+				default:
+					*dst = *src;
+			')
+		', `
+		case IS_VAR:
+		case IS_TMP_VAR:
+		case IS_CV:
+			DISPATCH(zend_uint, $1.var)
+			break;
+		case IS_UNUSED:
+			IFDASM(`DISPATCH(zend_uint, $1.var)')
+			DISPATCH(zend_uint, $1.opline_num)
+			break;
+		')
+	}
+	')
+	DONE($1)
+')
+dnl }}}
+#else
 DEF_STRUCT_P_FUNC(`znode', , `dnl {{{
 	DISPATCH(int, op_type)
@@ -460,15 +573,30 @@
 	')
 	DONE(u)
+#if 0
+	DONE(EA)
+#endif
 #undef XCACHE_IS_CV
 ')
 dnl }}}
+#endif
 DEF_STRUCT_P_FUNC(`zend_op', , `dnl {{{
 	DISPATCH(zend_uchar, opcode)
+#ifdef ZEND_ENGINE_2_4
+	UNION_znode_op(result)
+	UNION_znode_op(op1)
+	UNION_znode_op(op2)
+#else
 	STRUCT(znode, result)
 	STRUCT(znode, op1)
 	STRUCT(znode, op2)
+#endif
 	DISPATCH(ulong, extended_value)
 	DISPATCH(uint, lineno)
 #ifdef ZEND_ENGINE_2_1
+#ifdef ZEND_ENGINE_2_4
+	DISPATCH(zend_uchar, op1_type)
+	DISPATCH(zend_uchar, op2_type)
+	DISPATCH(zend_uchar, result_type)
+#endif
 	IFCOPY(`
 		switch (src->opcode) {
@@ -477,5 +605,5 @@
 #endif
 			case ZEND_JMP:
-				dst->op1.u.jmp_addr = processor->active_opcodes_dst + (src->op1.u.jmp_addr - processor->active_opcodes_src);
+				Z_OP(dst->op1).jmp_addr = processor->active_opcodes_dst + (Z_OP(src->op1).jmp_addr - processor->active_opcodes_src);
 				break;
 
@@ -487,5 +615,5 @@
 			case ZEND_JMP_SET:
 #endif
-				dst->op2.u.jmp_addr = processor->active_opcodes_dst + (src->op2.u.jmp_addr - processor->active_opcodes_src);
+				Z_OP(dst->op2).jmp_addr = processor->active_opcodes_dst + (Z_OP(src->op2).jmp_addr - processor->active_opcodes_src);
 				break;
 
@@ -498,4 +626,12 @@
 ')
 dnl }}}
+#ifdef ZEND_ENGINE_2_4
+DEF_STRUCT_P_FUNC(`zend_literal', , `dnl {{{
+	STRUCT(zval, constant)
+	DISPATCH(zend_ulong, hash_value)
+	DISPATCH(zend_uint,  cache_slot)
+')
+dnl }}}
+#endif
 DEF_STRUCT_P_FUNC(`zend_op_array', , `dnl {{{
 	IFRESTORE(`
@@ -552,5 +688,7 @@
 	DISPATCH(zend_uint, num_args)
 	DISPATCH(zend_uint, required_num_args)
+#	ifndef ZEND_ENGINE_2_4
 	DISPATCH(zend_bool, pass_rest_by_reference)
+#	endif
 #else
 	if (src->arg_types) {
@@ -583,5 +721,7 @@
 	}
 #endif
+#ifndef ZEND_ENGINE_2_4
 	DISPATCH(unsigned char, return_reference)
+#endif
 	/* END of common elements */
 #ifdef IS_UNICODE
@@ -600,10 +740,14 @@
 	popdef(`AFTER_ALLOC')
 	DISPATCH(zend_uint, last)
+#ifndef ZEND_ENGINE_2_4
 	IFCOPY(`dst->size = src->last;DONE(size)', `DISPATCH(zend_uint, size)')
+#endif
 
 #ifdef IS_CV
 	STRUCT_ARRAY(last_var, zend_compiled_variable, vars)
 	DISPATCH(int, last_var)
+#	ifndef ZEND_ENGINE_2_4
 	IFCOPY(`dst->size_var = src->last_var;DONE(size_var)', `DISPATCH(zend_uint, size_var)')
+#	endif
 #else
 	dnl zend_cv.m4 is illegal to be made public, don not ask me for it
@@ -617,5 +761,7 @@
 	STRUCT_ARRAY(last_brk_cont, zend_brk_cont_element, brk_cont_array)
 	DISPATCH(zend_uint, last_brk_cont)
+#ifndef ZEND_ENGINE_2_4
 	DISPATCH(zend_uint, current_brk_cont)
+#endif
 #ifndef ZEND_ENGINE_2
 	DISPATCH(zend_bool, uses_globals)
@@ -629,11 +775,15 @@
 	STRUCT_P(HashTable, static_variables, HashTable_zval_ptr)
 
+#ifndef ZEND_ENGINE_2_4
 	COPY(start_op)
 	DISPATCH(int, backpatch_count)
+#endif
 #ifdef ZEND_ENGINE_2_3
 	DISPATCH(zend_uint, this_var)
 #endif
 
+#ifndef ZEND_ENGINE_2_4
 	DISPATCH(zend_bool, done_pass_two)
+#endif
 	/* 5.0 <= ver < 5.3 */
 #if defined(ZEND_ENGINE_2) && !defined(ZEND_ENGINE_2_3)
@@ -697,4 +847,12 @@
 			')
 	')
+#ifdef ZEND_ENGINE_2_4
+	DISPATCH(int, last_literal)
+	IFRESTORE(`COPY(literals)', `STRUCT_ARRAY(last_literal, zend_literal, literals)')
+
+	COPYNULL(run_time_cache)
+	COPYNULL(last_cache_slot)
+#endif
+
 #endif
 
Index: /trunk/utils.c
===================================================================
--- /trunk/utils.c	(revision 715)
+++ /trunk/utils.c	(revision 716)
@@ -20,6 +20,6 @@
 
 #define OP_ZVAL_DTOR(op) do { \
-	Z_UNSET_ISREF((op).u.constant); \
-	zval_dtor(&(op).u.constant); \
+	Z_UNSET_ISREF(Z_OP_CONSTANT(op)); \
+	zval_dtor(&Z_OP_CONSTANT(op)); \
 } while(0)
 xc_compile_result_t *xc_compile_result_init(xc_compile_result_t *cr, /* {{{ */
@@ -135,7 +135,9 @@
 	zend_op *opline, *end;
 
+#ifndef ZEND_ENGINE_2_4
 	if (!op_array->done_pass_two) {
 		return 0;
 	}
+#endif
 
 	opline = op_array->opcodes;
@@ -148,6 +150,6 @@
 #endif
 			case ZEND_JMP:
-				opline->op1.u.opline_num = opline->op1.u.jmp_addr - op_array->opcodes;
-				assert(opline->op1.u.opline_num < op_array->last);
+				Z_OP(opline->op1).opline_num = Z_OP(opline->op1).jmp_addr - op_array->opcodes;
+				assert(Z_OP(opline->op1).opline_num < op_array->last);
 				break;
 			case ZEND_JMPZ:
@@ -158,6 +160,6 @@
 			case ZEND_JMP_SET:
 #endif
-				opline->op2.u.opline_num = opline->op2.u.jmp_addr - op_array->opcodes;
-				assert(opline->op2.u.opline_num < op_array->last);
+				Z_OP(opline->op2).opline_num = Z_OP(opline->op2).jmp_addr - op_array->opcodes;
+				assert(Z_OP(opline->op2).opline_num < op_array->last);
 				break;
 		}
@@ -165,5 +167,7 @@
 		opline++;
 	}
+#ifndef ZEND_ENGINE_2_4
 	op_array->done_pass_two = 0;
+#endif
 
 	return 0;
@@ -174,7 +178,9 @@
 	zend_op *opline, *end;
 
+#ifndef ZEND_ENGINE_2_4
 	if (op_array->done_pass_two) {
 		return 0;
 	}
+#endif
 
 	/*
@@ -186,12 +192,12 @@
 	end = opline + op_array->last;
 	while (opline < end) {
-		if (opline->op1.op_type == IS_CONST) {
-			Z_SET_ISREF(opline->op1.u.constant);
-			Z_SET_REFCOUNT(opline->op1.u.constant, 2); /* Make sure is_ref won't be reset */
-
-		}
-		if (opline->op2.op_type == IS_CONST) {
-			Z_SET_ISREF(opline->op2.u.constant);
-			Z_SET_REFCOUNT(opline->op2.u.constant, 2);
+		if (Z_OP_TYPE(opline->op1) == IS_CONST) {
+			Z_SET_ISREF(Z_OP_CONSTANT(opline->op1));
+			Z_SET_REFCOUNT(Z_OP_CONSTANT(opline->op1), 2); /* Make sure is_ref won't be reset */
+
+		}
+		if (Z_OP_TYPE(opline->op2) == IS_CONST) {
+			Z_SET_ISREF(Z_OP_CONSTANT(opline->op2));
+			Z_SET_REFCOUNT(Z_OP_CONSTANT(opline->op2), 2);
 		}
 #ifdef ZEND_ENGINE_2_1
@@ -201,6 +207,6 @@
 #endif
 			case ZEND_JMP:
-				assert(opline->op1.u.opline_num < op_array->last);
-				opline->op1.u.jmp_addr = op_array->opcodes + opline->op1.u.opline_num;
+				assert(Z_OP(opline->op1).opline_num < op_array->last);
+				Z_OP(opline->op1).jmp_addr = op_array->opcodes + Z_OP(opline->op1).opline_num;
 				break;
 			case ZEND_JMPZ:
@@ -211,6 +217,6 @@
 			case ZEND_JMP_SET:
 #endif
-				assert(opline->op2.u.opline_num < op_array->last);
-				opline->op2.u.jmp_addr = op_array->opcodes + opline->op2.u.opline_num;
+				assert(Z_OP(opline->op2).opline_num < op_array->last);
+				Z_OP(opline->op2).jmp_addr = op_array->opcodes + Z_OP(opline->op2).opline_num;
 				break;
 		}
@@ -220,5 +226,7 @@
 	}
 
+#ifndef ZEND_ENGINE_2_4
 	op_array->done_pass_two = 1;
+#endif
 	return 0;
 }
@@ -226,11 +234,11 @@
 
 #ifdef HAVE_XCACHE_OPCODE_SPEC_DEF
-static void xc_fix_opcode_ex_znode(int tofix, xc_op_spec_t spec, znode *znode, int type TSRMLS_DC) /* {{{ */
+static void xc_fix_opcode_ex_znode(int tofix, xc_op_spec_t spec, zend_uchar *op_type, znode_op *op, int type TSRMLS_DC) /* {{{ */
 {
 #ifdef ZEND_ENGINE_2
-	if ((znode->op_type != IS_UNUSED && (spec == OPSPEC_UCLASS || spec == OPSPEC_CLASS)) ||
+	if ((*op_type != IS_UNUSED && (spec == OPSPEC_UCLASS || spec == OPSPEC_CLASS)) ||
 			spec == OPSPEC_FETCH) {
 		if (tofix) {
-			switch (znode->op_type) {
+			switch (*op_type) {
 			case IS_VAR:
 			case IS_TMP_VAR:
@@ -239,17 +247,17 @@
 			default:
 				/* TODO: data lost, find a way to keep it */
-				/* assert(znode->op_type == IS_CONST); */
-				znode->op_type = IS_TMP_VAR;
+				/* assert(*op_type == IS_CONST); */
+				*op_type = IS_TMP_VAR;
 			}
 		}
 	}
-	switch (znode->op_type) {
+	switch (*op_type) {
 	case IS_TMP_VAR:
 	case IS_VAR:
 		if (tofix) {
-			znode->u.var /= sizeof(temp_variable);
+			Z_OP(*op).var /= sizeof(temp_variable);
 		}
 		else {
-			znode->u.var *= sizeof(temp_variable);
+			Z_OP(*op).var *= sizeof(temp_variable);
 		}
 	}
@@ -270,7 +278,7 @@
 			spec = xc_get_opcode_spec(opline->opcode);
 
-			xc_fix_opcode_ex_znode(tofix, spec->op1, &opline->op1, 0 TSRMLS_CC);
-			xc_fix_opcode_ex_znode(tofix, spec->op2, &opline->op2, 1 TSRMLS_CC);
-			xc_fix_opcode_ex_znode(tofix, spec->res, &opline->result, 2 TSRMLS_CC);
+			xc_fix_opcode_ex_znode(tofix, spec->op1, &Z_OP_TYPE(opline->op1),    &opline->op1, 0 TSRMLS_CC);
+			xc_fix_opcode_ex_znode(tofix, spec->op2, &Z_OP_TYPE(opline->op2),    &opline->op2, 1 TSRMLS_CC);
+			xc_fix_opcode_ex_znode(tofix, spec->res, &Z_OP_TYPE(opline->result), &opline->result, 2 TSRMLS_CC);
 		}
 	}
@@ -304,9 +312,9 @@
 #endif
 			case ZEND_JMP:
-				next = begin + opline->op1.u.opline_num;
+				next = begin + Z_OP(opline->op1).opline_num;
 				break;
 
 			case ZEND_JMPZNZ:
-				next = begin + max(opline->op2.u.opline_num, opline->extended_value);
+				next = begin + max(Z_OP(opline->op2).opline_num, opline->extended_value);
 				break;
 
@@ -318,5 +326,5 @@
 			case ZEND_JMP_SET:
 #endif
-				next = begin + opline->op2.u.opline_num;
+				next = begin + Z_OP(opline->op2).opline_num;
 				break;
 
@@ -371,5 +379,5 @@
 			}
 
-			parent_name = &(opline - 1)->op2.u.constant;
+			parent_name = &(Z_OP_CONSTANT((opline - 1)->op2));
 			TRACE("binding with parent %s", Z_STRVAL_P(parent_name));
 			if (zend_lookup_class(Z_STRVAL_P(parent_name), Z_STRLEN_P(parent_name), &pce TSRMLS_CC) == FAILURE) {
@@ -387,5 +395,5 @@
 			zend_op *fetch_class_opline = opline - 1;
 
-			TRACE("%s %p", Z_STRVAL(fetch_class_opline->op2.u.constant), Z_STRVAL(fetch_class_opline->op2.u.constant));
+			TRACE("%s %p", Z_STRVAL(Z_OP_CONSTANT(fetch_class_opline->op2)), Z_STRVAL(Z_OP_CONSTANT(fetch_class_opline->op2)));
 			OP_ZVAL_DTOR(fetch_class_opline->op2);
 			fetch_class_opline->opcode = ZEND_NOP;
@@ -421,5 +429,5 @@
 	}
 
-	zend_hash_del(class_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len);
+	zend_hash_del(class_table, Z_OP_CONSTANT(opline->op1).value.str.val, Z_OP_CONSTANT(opline->op1).value.str.len);
 	OP_ZVAL_DTOR(opline->op1);
 	OP_ZVAL_DTOR(opline->op2);
@@ -512,5 +520,5 @@
 				ZESW(&stored_ce_ptr, NULL)
 				) == FAILURE) {
-		CG(zend_lineno) = ZESW(0, cep->line_start);
+		CG(zend_lineno) = ZESW(0, Z_CLASS_INFO(*cep).line_start);
 #ifdef IS_UNICODE
 		zend_error(E_ERROR, "Cannot redeclare class %R", type, cep->name);
Index: /trunk/xcache.c
===================================================================
--- /trunk/xcache.c	(revision 715)
+++ /trunk/xcache.c	(revision 716)
@@ -1154,6 +1154,6 @@
 	xc_entry_data_php_t *php = (xc_entry_data_php_t *) data;
 
-	class_name = opline->op1.u.constant.value.str.val;
-	class_len  = opline->op1.u.constant.value.str.len;
+	class_name = Z_OP_CONSTANT(opline->op1).value.str.val;
+	class_len  = Z_OP_CONSTANT(opline->op1).value.str.len;
 	if (zend_hash_find(CG(class_table), class_name, class_len, (void **) &cest) == FAILURE) {
 		assert(0);
@@ -1196,5 +1196,5 @@
 
 #define XCACHE_CHECK_OP(type, op) \
-	if (zend_binary_strcmp(Z_STRVAL(opline->op.u.constant), Z_STRLEN(opline->op.u.constant), xce->type##path, xce->type##path_len) == 0) { \
+	if (zend_binary_strcmp(Z_STRVAL(Z_OP_CONSTANT(opline->op)), Z_STRLEN(Z_OP_CONSTANT(opline->op)), xce->type##path, xce->type##path_len) == 0) { \
 		usage->type##path_used = 1; \
 		oplineinfo |= xcache_##op##_is_##type; \
@@ -1202,5 +1202,5 @@
 
 #define XCACHE_U_CHECK_OP(type, op) \
-	if (zend_u_##binary_strcmp(Z_USTRVAL(opline->op.u.constant), Z_USTRLEN(opline->op.u.constant), xce->u##type##path, xce->u##type##path_len) == 0) { \
+	if (zend_u_##binary_strcmp(Z_USTRVAL(Z_OP_CONSTANT(opline->op)), Z_USTRLEN(Z_OP_CONSTANT(opline->op)), xce->u##type##path, xce->u##type##path_len) == 0) { \
 		usage->u##type##path_used = 1; \
 		oplineinfo |= xcache_##op##_is_##type; \
@@ -1210,6 +1210,6 @@
 		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) {
+		if (Z_OP_TYPE(opline->op1) == IS_CONST) {
+			if (Z_TYPE(Z_OP_CONSTANT(opline->op1)) == IS_STRING) {
 				XCACHE_CHECK_OP(file, op1)
 				else XCACHE_CHECK_OP(dir, op1)
@@ -1217,5 +1217,5 @@
 
 #ifdef IS_UNICODE
-			else if (Z_TYPE(opline->op1.u.constant) == IS_UNICODE) {
+			else if (Z_TYPE(Z_OP_CONSTANT(opline->op1)) == IS_UNICODE) {
 				XCACHE_U_CHECK_OP(file, op1)
 				else XCACHE_U_CHECK_OP(dir, op1)
@@ -1223,6 +1223,6 @@
 #endif
 		}
-		if (opline->op2.op_type == IS_CONST) {
-			if (Z_TYPE(opline->op2.u.constant) == IS_STRING) {
+		if (Z_OP_TYPE(opline->op2) == IS_CONST) {
+			if (Z_TYPE(Z_OP_CONSTANT(opline->op2)) == IS_STRING) {
 				XCACHE_CHECK_OP(file, op2)
 				else XCACHE_CHECK_OP(dir, op2)
@@ -1230,5 +1230,5 @@
 
 #ifdef IS_UNICODE
-			else if (Z_TYPE(opline->op2.u.constant) == IS_UNICODE) {
+			else if (Z_TYPE(Z_OP_CONSTANT(opline->op2)) == IS_UNICODE) {
 				XCACHE_U_CHECK_OP(file, op2)
 				else XCACHE_U_CHECK_OP(dir, op2)
@@ -1259,17 +1259,17 @@
 		zend_op *opline = &op_array->opcodes[oplineno];
 		if ((oplineinfo & xcache_op1_is_file)) {
-			assert(opline->op1.op_type == IS_CONST);
+			assert(Z_OP_TYPE(opline->op1) == IS_CONST);
 			if (copy) {
-				efree(Z_STRVAL(opline->op1.u.constant));
-			}
-			if (Z_TYPE(opline->op1.u.constant) == IS_STRING) {
+				efree(Z_STRVAL(Z_OP_CONSTANT(opline->op1)));
+			}
+			if (Z_TYPE(Z_OP_CONSTANT(opline->op1)) == IS_STRING) {
 				assert(xce->filepath);
-				ZVAL_STRINGL(&opline->op1.u.constant, xce->filepath, xce->filepath_len, copy);
+				ZVAL_STRINGL(&Z_OP_CONSTANT(opline->op1), xce->filepath, xce->filepath_len, copy);
 				TRACE("fixing op1 to %s", xce->filepath);
 			}
 #ifdef IS_UNICODE
-			else if (Z_TYPE(opline->op1.u.constant) == IS_UNICODE) {
+			else if (Z_TYPE(Z_OP_CONSTANT(opline->op1)) == IS_UNICODE) {
 				assert(xce->ufilepath);
-				ZVAL_UNICODEL(&opline->op1.u.constant, xce->ufilepath, xce->ufilepath_len, copy);
+				ZVAL_UNICODEL(&Z_OP_CONSTANT(opline->op1), xce->ufilepath, xce->ufilepath_len, copy);
 			}
 #endif
@@ -1279,17 +1279,17 @@
 		}
 		else if ((oplineinfo & xcache_op1_is_dir)) {
-			assert(opline->op1.op_type == IS_CONST);
+			assert(Z_OP_TYPE(opline->op1) == IS_CONST);
 			if (copy) {
-				efree(Z_STRVAL(opline->op1.u.constant));
-			}
-			if (Z_TYPE(opline->op1.u.constant) == IS_STRING) {
+				efree(Z_STRVAL(Z_OP_CONSTANT(opline->op1)));
+			}
+			if (Z_TYPE(Z_OP_CONSTANT(opline->op1)) == IS_STRING) {
 				assert(xce->dirpath);
 				TRACE("fixing op1 to %s", xce->dirpath);
-				ZVAL_STRINGL(&opline->op1.u.constant, xce->dirpath, xce->dirpath_len, copy);
+				ZVAL_STRINGL(&Z_OP_CONSTANT(opline->op1), xce->dirpath, xce->dirpath_len, copy);
 			}
 #ifdef IS_UNICODE
-			else if (Z_TYPE(opline->op1.u.constant) == IS_UNICODE) {
+			else if (Z_TYPE(Z_OP_CONSTANT(opline->op1)) == IS_UNICODE) {
 				assert(!xce->udirpath);
-				ZVAL_UNICODEL(&opline->op1.u.constant, xce->udirpath, xce->udirpath_len, copy);
+				ZVAL_UNICODEL(&Z_OP_CONSTANT(opline->op1), xce->udirpath, xce->udirpath_len, copy);
 			}
 #endif
@@ -1300,17 +1300,17 @@
 
 		if ((oplineinfo & xcache_op2_is_file)) {
-			assert(opline->op2.op_type == IS_CONST);
+			assert(Z_OP_TYPE(opline->op2) == IS_CONST);
 			if (copy) {
-				efree(Z_STRVAL(opline->op2.u.constant));
-			}
-			if (Z_TYPE(opline->op2.u.constant) == IS_STRING) {
+				efree(Z_STRVAL(Z_OP_CONSTANT(opline->op2)));
+			}
+			if (Z_TYPE(Z_OP_CONSTANT(opline->op2)) == IS_STRING) {
 				assert(xce->filepath);
 				TRACE("fixing op2 to %s", xce->filepath);
-				ZVAL_STRINGL(&opline->op2.u.constant, xce->filepath, xce->filepath_len, copy);
+				ZVAL_STRINGL(&Z_OP_CONSTANT(opline->op2), xce->filepath, xce->filepath_len, copy);
 			}
 #ifdef IS_UNICODE
-			else if (Z_TYPE(opline->op2.u.constant) == IS_UNICODE) {
+			else if (Z_TYPE(Z_OP_CONSTANT(opline->op2)) == IS_UNICODE) {
 				assert(xce->ufilepath);
-				ZVAL_UNICODEL(&opline->op2.u.constant, xce->ufilepath, xce->ufilepath_len, copy);
+				ZVAL_UNICODEL(&Z_OP_CONSTANT(opline->op2), xce->ufilepath, xce->ufilepath_len, copy);
 			}
 #endif
@@ -1320,17 +1320,17 @@
 		}
 		else if ((oplineinfo & xcache_op2_is_dir)) {
-			assert(opline->op2.op_type == IS_CONST);
+			assert(Z_OP_TYPE(opline->op2) == IS_CONST);
 			if (copy) {
-				efree(Z_STRVAL(opline->op2.u.constant));
-			}
-			if (Z_TYPE(opline->op2.u.constant) == IS_STRING) {
+				efree(Z_STRVAL(Z_OP_CONSTANT(opline->op2)));
+			}
+			if (Z_TYPE(Z_OP_CONSTANT(opline->op2)) == IS_STRING) {
 				assert(!xce->dirpath);
 				TRACE("fixing op2 to %s", xce->dirpath);
-				ZVAL_STRINGL(&opline->op2.u.constant, xce->dirpath, xce->dirpath_len, copy);
+				ZVAL_STRINGL(&Z_OP_CONSTANT(opline->op2), xce->dirpath, xce->dirpath_len, copy);
 			}
 #ifdef IS_UNICODE
-			else if (Z_TYPE(opline->op2.u.constant) == IS_UNICODE) {
+			else if (Z_TYPE(Z_OP_CONSTANT(opline->op2)) == IS_UNICODE) {
 				assert(!xce->udirpath);
-				ZVAL_UNICODEL(&opline->op2.u.constant, xce->udirpath, xce->udirpath_len, copy);
+				ZVAL_UNICODEL(&Z_OP_CONSTANT(opline->op2), xce->udirpath, xce->udirpath_len, copy);
 			}
 #endif
@@ -3055,5 +3055,5 @@
 }
 /* }}} */
-static function_entry xcache_functions[] = /* {{{ */
+static zend_function_entry xcache_functions[] = /* {{{ */
 {
 	PHP_FE(xcache_count,             NULL)
Index: /trunk/xcache.h
===================================================================
--- /trunk/xcache.h	(revision 715)
+++ /trunk/xcache.h	(revision 716)
@@ -22,12 +22,15 @@
 
 #define HAVE_INODE
-#if !defined(ZEND_ENGINE_2_1) && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 1 || PHP_MAJOR_VERSION > 5)
+#if !defined(ZEND_ENGINE_2_4) && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 3 && PHP_RELEASE_VERSION >= 99 || PHP_MAJOR_VERSION > 5)
+#	define ZEND_ENGINE_2_4
+#endif
+#if !defined(ZEND_ENGINE_2_3) && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 3 || defined(ZEND_ENGINE_2_4))
+#	define ZEND_ENGINE_2_3
+#endif
+#if !defined(ZEND_ENGINE_2_2) && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 2 || defined(ZEND_ENGINE_2_3))
+#	define ZEND_ENGINE_2_2
+#endif
+#if !defined(ZEND_ENGINE_2_1) && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 1 || defined(ZEND_ENGINE_2_2))
 #	define ZEND_ENGINE_2_1
-#endif
-#if !defined(ZEND_ENGINE_2_2) && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 2 || PHP_MAJOR_VERSION > 5)
-#	define ZEND_ENGINE_2_2
-#endif
-#if !defined(ZEND_ENGINE_2_3) && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3 || PHP_MAJOR_VERSION > 5)
-#	define ZEND_ENGINE_2_3
 #endif
 
@@ -89,4 +92,20 @@
 #	define add_assoc_null_ex my_add_assoc_null_ex
 #endif
+
+#ifdef ZEND_ENGINE_2_4
+#	define Z_OP(op) (op)
+#	define Z_OP_CONSTANT(op) (op).literal->constant
+#	define Z_OP_TYPE(op) op##_##type
+
+#	define Z_CLASS_INFO(className) (className).info.user
+#else
+#	define Z_OP(op) (op).u
+#	define Z_OP_CONSTANT(op) (op).u.constant
+#	define Z_OP_TYPE(op) (op).op_type
+typedef znode znode_op;
+
+#	define Z_CLASS_INFO(className) (className)
+#endif
+
 /* }}} */
 
