From 4271653af9ec87df3f3edb04f6917230eb03ffa4 Mon Sep 17 00:00:00 2001 From: Xuefer Date: Sat, 9 Apr 2011 07:07:48 +0000 Subject: [PATCH] PHP 6: initial catch up with php 6 literals and trait git-svn-id: svn://svn.lighttpd.net/xcache/trunk@716 c26eb9a1-5813-0410-bd6c-c2e55f420ca7 --- ChangeLog | 1 + Decompiler.class.php | 144 +++++++++++++++++++----------- NEWS | 1 + coverager.c | 12 ++- optimizer.c | 59 +++++++------ processor/processor.m4 | 196 +++++++++++++++++++++++++++++++++++++---- utils.c | 76 +++++++++------- xcache.c | 70 +++++++-------- xcache.h | 29 ++++-- 9 files changed, 406 insertions(+), 182 deletions(-) diff --git a/ChangeLog b/ChangeLog index a2f134f..5085310 100644 --- a/ChangeLog +++ b/ChangeLog @@ -11,6 +11,7 @@ ChangeLog 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 * fix win32 build against win32 native gnu tools diff --git a/Decompiler.class.php b/Decompiler.class.php index cda0c04..3b27a9c 100644 --- a/Decompiler.class.php +++ b/Decompiler.class.php @@ -27,7 +27,7 @@ function str($src, $indent = '') // {{{ */ if (is_array($src)) { - die_error('array str'); + exit('array str'); $src = new Decompiler_Array($src, $indent); return $src->__toString(); } @@ -35,7 +35,7 @@ function str($src, $indent = '') // {{{ if (is_object($src)) { if (!method_exists($src, '__toString')) { var_dump($src); - die_error('no __toString'); + exit('no __toString'); } return $src->__toString(); } @@ -425,22 +425,22 @@ class Decompiler { 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']; @@ -449,6 +449,19 @@ class Decompiler } } // }}} + 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; + } + // }}} function &dop_array($op_array, $indent = '') // {{{ { $opcodes = &$op_array['opcodes']; @@ -457,9 +470,37 @@ class Decompiler unset($opcodes[$last]); } $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 ++) { $op = &$opcodes[$i]; @@ -473,13 +514,13 @@ class Decompiler $op['line'] = $i; switch ($op['opcode']) { case XC_JMP: - $target = $op['op1']['u.var']; + $target = $op['op1']['var']; $op['jmpouts'] = array($target); $opcodes[$target]['jmpins'][] = $i; break; case XC_JMPZNZ: - $jmpz = $op['op2']['u.opline_num']; + $jmpz = $op['op2']['opline_num']; $jmpnz = $op['extended_value']; $op['jmpouts'] = array($jmpz, $jmpnz); $opcodes[$jmpz]['jmpins'][] = $i; @@ -493,7 +534,7 @@ class Decompiler // case XC_FE_RESET: 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); // var_dump($op); exit; @@ -580,7 +621,7 @@ class Decompiler } if ($op['opcode'] == XC_FE_FETCH) { $opline = $next; - $next = $op['op2']['u.opline_num']; + $next = $op['op2']['opline_num']; $end = $next - 1; ob_start(); @@ -599,12 +640,12 @@ class Decompiler } /* 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']; echo "{$indent}if ($cond) {\n"; @@ -649,7 +690,7 @@ class Decompiler default: continue 2; } - $var = $fromop['result']['u.var']; + $var = $fromop['result']['var']; var_dump($EX['Ts'][$var]); $EX['Ts'][$var] = '(' . $fromop['and_or'] . " $opstr " . $EX['Ts'][$var] . ')'; } @@ -711,7 +752,7 @@ class Decompiler // $this->dumpop($op, $EX); //var_dump($op); $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; } else { @@ -742,7 +783,7 @@ class Decompiler switch ($opc) { 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) { $resvar = '$new object$'; @@ -760,7 +801,7 @@ class Decompiler } } else { - $class = $op2['u.constant']; + $class = $op2['constant']; if (is_object($class)) { $class = get_class($class); } @@ -770,15 +811,15 @@ class Decompiler // }}} 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; // }}} @@ -791,7 +832,7 @@ class Decompiler case XC_FETCH_IS: 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: $class = $this->getOpVal($op2, $EX); @@ -837,12 +878,12 @@ class Decompiler $list = new Decompiler_List($this->getOpVal($op1, $EX, false)); $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); } $dim = new Decompiler_Dim($src); @@ -882,7 +923,7 @@ class Decompiler if (is_a($rvalue, 'Decompiler_ForeachBox')) { $type = $rvalue->iskey ? 'fe_key' : 'fe_as'; $rvalue->obj[$type] = $lvalue; - unset($T[$op2['u.var']]); + unset($T[$op2['var']]); break; } if (is_a($rvalue, "Decompiler_DimBox")) { @@ -968,7 +1009,7 @@ class Decompiler else { $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; } @@ -982,16 +1023,13 @@ class Decompiler $rvalue = $container . "[$dim]"; } - 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)"; break; case ZEND_ISEMPTY: $rvalue = "empty($rvalue)"; break; - default: - $this->dumpop($op, $EX); - die_error('1'); } $resvar = $rvalue; break; @@ -1026,7 +1064,7 @@ class Decompiler } if ($opc == XC_INIT_FCALL_BY_FUNC) { - $which = $op1['u.var']; + $which = $op1['var']; $EX['fbc'] = $EX['op_array']['funcs'][$which]['name']; } else { @@ -1035,7 +1073,7 @@ class Decompiler break; // }}} 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); $resvar = $fname . "($args)"; @@ -1068,13 +1106,13 @@ class Decompiler break; // }}} case XC_VERIFY_ABSTRACT_CLASS: // {{{ - //unset($T[$op1['u.var']]); + //unset($T[$op1['var']]); break; // }}} case XC_DECLARE_CLASS: 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"; var_dump(array_keys($this->dc['class_table'])); @@ -1093,7 +1131,7 @@ class Decompiler 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]; $impl = $this->unquoteName($this->getOpVal($fetchop['op2'], $EX)); @@ -1159,10 +1197,10 @@ class Decompiler if ($opc == XC_ADD_ARRAY_ELEMENT) { $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; } } else { @@ -1196,7 +1234,7 @@ class Decompiler break; // }}} case XC_INCLUDE_OR_EVAL: // {{{ - $type = $op2['u.var']; // hack + $type = $op2['var']; // hack $keyword = $this->includeTypes[$type]; $resvar = "$keyword(" . $this->getOpVal($op1, $EX) . ")"; break; @@ -1209,7 +1247,7 @@ class Decompiler $op['fe_src'] = $this->getOpVal($op1, $EX); $fe = new Decompiler_ForeachBox($op); $fe->iskey = false; - $T[$res['u.var']] = $fe; + $T[$res['var']] = $fe; ++ $i; if (($ext & ZEND_FE_FETCH_WITH_KEY)) { @@ -1217,21 +1255,21 @@ class Decompiler $fe->iskey = true; $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; // }}} case XC_JMP_NO_CTOR: @@ -1257,7 +1295,7 @@ class Decompiler var_dump($op);// exit; } 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); } @@ -1285,7 +1323,7 @@ class Decompiler $offset = $this->getOpVal($op1, $EX); $lvalue = $this->getOpVal($op['result'], $EX); if ($opc == XC_RECV_INIT) { - $default = value($op['op2']['u.constant']); + $default = value($op['op2']['constant']); } else { $default = null; @@ -1371,8 +1409,8 @@ class Decompiler } if (isset($resvar)) { if ($istmpres) { - $T[$res['u.var']] = $resvar; - $lastresvar = &$T[$res['u.var']]; + $T[$res['var']] = $resvar; + $lastresvar = &$T[$res['var']]; } else { $op['php'] = $resvar; @@ -1418,18 +1456,18 @@ class Decompiler foreach (array('op1' => 'op1', 'op2' => 'op2', 'result' => 'res') as $k => $kk) { 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); } break; 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); } diff --git a/NEWS b/NEWS index 53db1eb..a6ffe6f 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,7 @@ 1.3.2 2011-??-?? ======== + * PHP_6: catch up with php 6 devel * memory leak on recompile * disassembler fixes and updates for new PHP * win32 build fix diff --git a/coverager.c b/coverager.c index 9dfa601..3fc143a 100644 --- a/coverager.c +++ b/coverager.c @@ -378,25 +378,23 @@ static void xc_coverager_add_hits(HashTable *cov, long line, long hits TSRMLS_DC 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: #endif case ZEND_RETURN: case ZEND_EXT_STMT: - size --; + --last; goto next_op; } } while (0); - return size; + return last; } /* }}} */ diff --git a/optimizer.c b/optimizer.c index bf192e9..d928f3d 100644 --- a/optimizer.c +++ b/optimizer.c @@ -63,15 +63,15 @@ static int op_array_convert_switch(zend_op_array *op_array) /* {{{ */ if (opline->opcode != ZEND_BRK && opline->opcode != ZEND_CONT) { 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) { /* this is a runtime error in ZE @@ -95,12 +95,12 @@ static int op_array_convert_switch(zend_op_array *op_array) /* {{{ */ /* 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; + Z_OP(opline->op1).opline_num = jmp_to->cont; } - opline->op2.op_type = IS_UNUSED; + Z_OP_TYPE(opline->op2) = IS_UNUSED; opline->opcode = ZEND_JMP; } @@ -142,11 +142,11 @@ static int op_get_flowinfo(op_flowinfo_t *fi, zend_op *opline) /* {{{ */ return SUCCESS; /* no fall */ 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 */ @@ -167,7 +167,7 @@ static int op_get_flowinfo(op_flowinfo_t *fi, zend_op *opline) /* {{{ */ case ZEND_FE_RESET: #endif case ZEND_FE_FETCH: - fi->jmpout_op2 = opline->op2.u.opline_num; + fi->jmpout_op2 = Z_OP(opline->op2).opline_num; break; #ifdef ZEND_CATCH @@ -185,15 +185,16 @@ static int op_get_flowinfo(op_flowinfo_t *fi, zend_op *opline) /* {{{ */ } /* }}} */ #ifdef XCACHE_DEBUG -static void op_snprint(char *buf, int size, znode *op) /* {{{ */ +static void op_snprint(char *buf, int size, zend_uchar op_type, znode_op *op) /* {{{ */ { - switch (op->op_type) { + 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); @@ -205,17 +206,17 @@ static void op_snprint(char *buf, int size, znode *op) /* {{{ */ break; 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 { snprintf(buf, size, "-"); @@ -223,7 +224,7 @@ static void op_snprint(char *buf, int size, znode *op) /* {{{ */ break; default: - snprintf(buf, size, "%d %d", op->op_type, op->u.var); + snprintf(buf, size, "%d %d", op->op_type, Z_OP(op).var); } } /* }}} */ @@ -234,9 +235,9 @@ static void op_print(int line, zend_op *first, zend_op *end) /* {{{ */ char buf_r[20]; 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" " %-25s%-5s%-20s%-20s%5lu\r\n" @@ -450,12 +451,12 @@ static int bbs_build_from(bbs_t *bbs, zend_op_array *op_array, int count) /* {{{ opline = pbb->opcodes + pbb->count - 1; 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) { opline->extended_value = bbids[fi.jmpout_ext]; @@ -498,12 +499,12 @@ static void bbs_restore_opnum(bbs_t *bbs, zend_op_array *op_array) /* {{{ */ 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) { last->extended_value = bbs_get(bbs, fi.jmpout_ext)->opnum; diff --git a/processor/processor.m4 b/processor/processor.m4 index 2f8cfc9..c3c1f94 100644 --- a/processor/processor.m4 +++ b/processor/processor.m4 @@ -222,11 +222,17 @@ DEF_STRUCT_P_FUNC(`zend_arg_info', , ` PROC_ZSTRING_L(, name, name_len) 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 dnl }}} @@ -272,6 +278,9 @@ DEF_STRUCT_P_FUNC(`zend_property_info', , ` DISPATCH(int, name_length) 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) PROC_ZSTRING_L(, doc_comment, doc_comment_len) @@ -306,33 +315,59 @@ DEF_STRUCT_P_FUNC(`zend_class_entry', , `dnl {{{ #else 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 /* 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 } ') IFDASM(` @@ -350,25 +385,55 @@ DEF_STRUCT_P_FUNC(`zend_class_entry', , `dnl {{{ add_assoc_zval_ex(dst, ZEND_STRS("interfaces"), arr); */ 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 } ') IFRESTORE(`', ` 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) COPY(unserialize_func) @@ -376,9 +441,9 @@ DEF_STRUCT_P_FUNC(`zend_class_entry', , `dnl {{{ COPY(create_object) 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) /* deal with it inside xc_fix_method */ @@ -388,20 +453,22 @@ DEF_STRUCT_P_FUNC(`zend_class_entry', , `dnl {{{ COPY(__get) 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) COPY(handle_property_set) @@ -415,6 +482,52 @@ DEF_STRUCT_P_FUNC(`zend_class_entry', , `dnl {{{ ') ') 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) @@ -459,24 +572,39 @@ DEF_STRUCT_P_FUNC(`znode', , `dnl {{{ } ') 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) { #ifdef ZEND_GOTO case ZEND_GOTO: #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; case ZEND_JMPZ: @@ -486,7 +614,7 @@ DEF_STRUCT_P_FUNC(`zend_op', , `dnl {{{ #ifdef ZEND_JMP_SET 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; default: @@ -497,6 +625,14 @@ DEF_STRUCT_P_FUNC(`zend_op', , `dnl {{{ #endif ') 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(` const xc_op_array_info_t *op_array_info = &processor->active_op_array_infos_src[processor->active_op_array_index]; @@ -551,7 +687,9 @@ DEF_STRUCT_P_FUNC(`zend_op_array', , `dnl {{{ STRUCT_ARRAY(num_args, zend_arg_info, arg_info) 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) { ALLOC(dst->arg_types, zend_uchar, src->arg_types[0] + 1) @@ -582,7 +720,9 @@ DEF_STRUCT_P_FUNC(`zend_op_array', , `dnl {{{ ') } #endif +#ifndef ZEND_ENGINE_2_4 DISPATCH(unsigned char, return_reference) +#endif /* END of common elements */ #ifdef IS_UNICODE dnl SETNULL(u_twin) @@ -599,12 +739,16 @@ DEF_STRUCT_P_FUNC(`zend_op_array', , `dnl {{{ STRUCT_ARRAY(last, zend_op, opcodes) 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 IFDASM(` @@ -616,7 +760,9 @@ DEF_STRUCT_P_FUNC(`zend_op_array', , `dnl {{{ 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) #endif @@ -628,13 +774,17 @@ DEF_STRUCT_P_FUNC(`zend_op_array', , `dnl {{{ 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) DISPATCH(zend_bool, uses_this) @@ -696,6 +846,14 @@ DEF_STRUCT_P_FUNC(`zend_op_array', , `dnl {{{ COPYNULL(prototype) ') ') +#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 #ifdef ZEND_ENGINE_2 diff --git a/utils.c b/utils.c index 15c4498..68d221d 100644 --- a/utils.c +++ b/utils.c @@ -19,8 +19,8 @@ #endif #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, /* {{{ */ zend_op_array *op_array, @@ -134,9 +134,11 @@ int xc_undo_pass_two(zend_op_array *op_array TSRMLS_DC) /* {{{ */ { zend_op *opline, *end; +#ifndef ZEND_ENGINE_2_4 if (!op_array->done_pass_two) { return 0; } +#endif opline = op_array->opcodes; end = opline + op_array->last; @@ -147,8 +149,8 @@ int xc_undo_pass_two(zend_op_array *op_array TSRMLS_DC) /* {{{ */ case ZEND_GOTO: #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: case ZEND_JMPNZ: @@ -157,14 +159,16 @@ int xc_undo_pass_two(zend_op_array *op_array TSRMLS_DC) /* {{{ */ #ifdef ZEND_JMP_SET 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; } #endif opline++; } +#ifndef ZEND_ENGINE_2_4 op_array->done_pass_two = 0; +#endif return 0; } @@ -173,9 +177,11 @@ int xc_redo_pass_two(zend_op_array *op_array TSRMLS_DC) /* {{{ */ { zend_op *opline, *end; +#ifndef ZEND_ENGINE_2_4 if (op_array->done_pass_two) { return 0; } +#endif /* op_array->opcodes = (zend_op *) erealloc(op_array->opcodes, sizeof(zend_op)*op_array->last); @@ -185,14 +191,14 @@ int xc_redo_pass_two(zend_op_array *op_array TSRMLS_DC) /* {{{ */ opline = op_array->opcodes; 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 (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 (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->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 switch (opline->opcode) { @@ -200,8 +206,8 @@ int xc_redo_pass_two(zend_op_array *op_array TSRMLS_DC) /* {{{ */ case ZEND_GOTO: #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: case ZEND_JMPNZ: @@ -210,8 +216,8 @@ int xc_redo_pass_two(zend_op_array *op_array TSRMLS_DC) /* {{{ */ #ifdef ZEND_JMP_SET 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; } ZEND_VM_SET_OPCODE_HANDLER(opline); @@ -219,38 +225,40 @@ int xc_redo_pass_two(zend_op_array *op_array TSRMLS_DC) /* {{{ */ opline++; } +#ifndef ZEND_ENGINE_2_4 op_array->done_pass_two = 1; +#endif return 0; } /* }}} */ #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: break; 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); } } #endif @@ -269,9 +277,9 @@ static void xc_fix_opcode_ex(zend_op_array *op_array, int tofix TSRMLS_DC) /* {{ const xc_opcode_spec_t *spec; 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); } } } @@ -303,11 +311,11 @@ int xc_foreach_early_binding_class(zend_op_array *op_array, void (*callback)(zen case ZEND_GOTO: #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; case ZEND_JMPZ: @@ -317,7 +325,7 @@ int xc_foreach_early_binding_class(zend_op_array *op_array, void (*callback)(zen #ifdef ZEND_JMP_SET case ZEND_JMP_SET: #endif - next = begin + opline->op2.u.opline_num; + next = begin + Z_OP(opline->op2).opline_num; break; case ZEND_RETURN: @@ -370,7 +378,7 @@ static int xc_do_early_binding(zend_op_array *op_array, HashTable *class_table, return FAILURE; } - 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) { return FAILURE; @@ -386,7 +394,7 @@ static int xc_do_early_binding(zend_op_array *op_array, HashTable *class_table, && (opline - 1)->opcode == ZEND_FETCH_CLASS) { 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; ZEND_VM_SET_OPCODE_HANDLER(fetch_class_opline); @@ -420,7 +428,7 @@ static int xc_do_early_binding(zend_op_array *op_array, HashTable *class_table, return FAILURE; } - 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); opline->opcode = ZEND_NOP; @@ -511,7 +519,7 @@ ZESW(xc_cest_t *, void) xc_install_class(char *filename, xc_cest_t *cest, int op cest, sizeof(xc_cest_t), 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); #else diff --git a/xcache.c b/xcache.c index f9a7686..aeaec88 100644 --- a/xcache.c +++ b/xcache.c @@ -1153,8 +1153,8 @@ static void xc_cache_early_binding_class_cb(zend_op *opline, int oplineno, void xc_cest_t cest; 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); } @@ -1195,13 +1195,13 @@ static void xc_collect_op_array_info(xc_entry_t *xce, xc_entry_data_php_t *php, 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), 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; \ } #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; \ } @@ -1209,27 +1209,27 @@ static void xc_collect_op_array_info(xc_entry_t *xce, xc_entry_data_php_t *php, 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) { + 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) } #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) } #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) } #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) } @@ -1258,19 +1258,19 @@ void xc_fix_op_array_info(const xc_entry_t *xce, const xc_entry_data_php_t *php, 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); + assert(Z_OP_TYPE(opline->op1) == IS_CONST); if (copy) { - efree(Z_STRVAL(opline->op1.u.constant)); + efree(Z_STRVAL(Z_OP_CONSTANT(opline->op1))); } - if (Z_TYPE(opline->op1.u.constant) == IS_STRING) { + 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 else { @@ -1278,19 +1278,19 @@ void xc_fix_op_array_info(const xc_entry_t *xce, const xc_entry_data_php_t *php, } } 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)); + efree(Z_STRVAL(Z_OP_CONSTANT(opline->op1))); } - if (Z_TYPE(opline->op1.u.constant) == IS_STRING) { + 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 else { @@ -1299,19 +1299,19 @@ void xc_fix_op_array_info(const xc_entry_t *xce, const xc_entry_data_php_t *php, } 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)); + efree(Z_STRVAL(Z_OP_CONSTANT(opline->op2))); } - if (Z_TYPE(opline->op2.u.constant) == IS_STRING) { + 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 else { @@ -1319,19 +1319,19 @@ void xc_fix_op_array_info(const xc_entry_t *xce, const xc_entry_data_php_t *php, } } 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)); + efree(Z_STRVAL(Z_OP_CONSTANT(opline->op2))); } - if (Z_TYPE(opline->op2.u.constant) == IS_STRING) { + 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 else { @@ -3054,7 +3054,7 @@ PHP_FUNCTION(xcache_is_autoglobal) RETURN_BOOL(zend_hash_exists(CG(auto_globals), name, name_len + 1)); } /* }}} */ -static function_entry xcache_functions[] = /* {{{ */ +static zend_function_entry xcache_functions[] = /* {{{ */ { PHP_FE(xcache_count, NULL) PHP_FE(xcache_info, NULL) diff --git a/xcache.h b/xcache.h index 26aaae4..f1bf6a8 100644 --- a/xcache.h +++ b/xcache.h @@ -21,14 +21,17 @@ #include "lock.h" #define HAVE_INODE -#if !defined(ZEND_ENGINE_2_1) && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 1 || PHP_MAJOR_VERSION > 5) -# define ZEND_ENGINE_2_1 +#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 || PHP_MAJOR_VERSION > 5) +#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_3) && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3 || PHP_MAJOR_VERSION > 5) -# define ZEND_ENGINE_2_3 +#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 #define NOTHING @@ -88,6 +91,22 @@ static inline void my_add_assoc_null_ex(zval *arg, char *key, uint key_len) # undef add_assoc_null_ex # 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 + /* }}} */ /* unicode */