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-c2e55f420ca73.0
parent
2e9dd4df93
commit
4271653af9
|
@ -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
|
||||
|
|
|
@ -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
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
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
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;
|
||||
|
|
|
@ -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
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
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 |