Browse Source

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
3.0
Xuefer 11 years ago
parent
commit
4271653af9
  1. 1
      ChangeLog
  2. 144
      Decompiler.class.php
  3. 1
      NEWS
  4. 12
      coverager.c
  5. 59
      optimizer.c
  6. 196
      processor/processor.m4
  7. 76
      utils.c
  8. 70
      xcache.c
  9. 29
      xcache.h

1
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

144
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);
}

1
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

12
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;
}
/* }}} */

59
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;

196
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

76
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

70
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)