1
0
Fork 0

rewrite try/catch handling to fix nested try/catch

git-svn-id: svn://svn.lighttpd.net/xcache/trunk@1405 c26eb9a1-5813-0410-bd6c-c2e55f420ca7
This commit is contained in:
Xuefer 2013-09-26 09:33:09 +00:00
parent 58624130fa
commit 7df0fab8f6
2 changed files with 29 additions and 122 deletions

View File

@ -11,6 +11,8 @@ ChangeLog
* improved support for PHP_4 ~ PHP_5_4, also added support for PHP_5_5
* admin
* make mkpassword.php easier for noob
* optimizer
* rewrite try/catch handling to fix nested try/catch
3.0.4 2013-09-??
ChangeLog

View File

@ -44,12 +44,6 @@ typedef struct _bb_t {
int size;
bbid_t fall;
#ifdef ZEND_ENGINE_2
bbid_t catch;
#endif
#ifdef ZEND_ENGINE_2_5
bbid_t finally;
#endif
zend_uint opnum; /* opnum after joining basic block */
} bb_t;
@ -314,12 +308,6 @@ static bb_t *bb_new_ex(zend_op *opcodes, int count) /* {{{ */
bb_t *bb = (bb_t *) ecalloc(sizeof(bb_t), 1);
bb->fall = BBID_INVALID;
#ifdef ZEND_ENGINE_2
bb->catch = BBID_INVALID;
#endif
#ifdef ZEND_ENGINE_2_5
bb->finally = BBID_INVALID;
#endif
if (opcodes) {
bb->alloc = 0;
@ -350,23 +338,16 @@ static void bb_print(bb_t *bb, zend_op_array *op_array) /* {{{ */
int line = bb->opcodes - op_array->opcodes;
op_flowinfo_t fi;
zend_op *last = bb->opcodes + bb->count - 1;
bbid_t catchbbid = ZESW(BBID_INVALID, bb->catch);
bbid_t finallybbid;
#ifdef ZEND_ENGINE_2_5
finallybbid = BBID_INVALID;
#else
finallybbid = bb->finally;
#endif
op_get_flowinfo(&fi, last);
fprintf(stderr,
"\n==== #%-3d cnt:%-3d lno:%-3d"
" %c%c"
" op1:%-3d op2:%-3d ext:%-3d fal:%-3d cat:%-3d fnl:%-3d %s ====\n"
" op1:%-3d op2:%-3d ext:%-3d fal:%-3d %s ====\n"
, bb->id, bb->count, bb->alloc ? -1 : line
, bb->used ? 'U' : ' ', bb->alloc ? 'A' : ' '
, fi.jmpout_op1, fi.jmpout_op2, fi.jmpout_ext, bb->fall, catchbbid, finallybbid, xc_get_opcode(last->opcode)
, fi.jmpout_op1, fi.jmpout_op2, fi.jmpout_ext, bb->fall, xc_get_opcode(last->opcode)
);
op_print(op_array, line, bb->opcodes, last + 1);
}
@ -427,12 +408,6 @@ static int bbs_build_from(bbs_t *bbs, zend_op_array *op_array, int count) /* {{{
typedef struct {
zend_bool isbbhead;
bbid_t bbid;
#ifdef ZEND_ENGINE_2
bbid_t catchbbid;
#endif
#ifdef ZEND_ENGINE_2_5
bbid_t finallybbid;
#endif
} oplineinfo_t;
oplineinfo_t *oplineinfos = xc_do_alloca(count * sizeof(oplineinfo_t), opline_infos_use_heap);
@ -459,11 +434,14 @@ static int bbs_build_from(bbs_t *bbs, zend_op_array *op_array, int count) /* {{{
#ifdef ZEND_ENGINE_2
/* mark try start */
for (i = 0; i < op_array->last_try_catch; i ++) {
oplineinfos[op_array->try_catch_array[i].try_op].isbbhead = 1;
oplineinfos[op_array->try_catch_array[i].catch_op].isbbhead = 1;
#ifdef ZEND_ENGINE_2_5
oplineinfos[op_array->try_catch_array[i].finally_op].isbbhead = 1;
#endif
# define MARK_OP_BB_HEAD(name) \
oplineinfos[op_array->try_catch_array[i].name].isbbhead = 1
MARK_OP_BB_HEAD(try_op);
MARK_OP_BB_HEAD(catch_op);
# ifdef ZEND_ENGINE_2_5
MARK_OP_BB_HEAD(finally_op);
# endif
# undef MARK_OP_BB_HEAD
}
#endif
/* }}} */
@ -482,34 +460,17 @@ static int bbs_build_from(bbs_t *bbs, zend_op_array *op_array, int count) /* {{{
}
/* }}} */
#ifdef ZEND_ENGINE_2
/* {{{ fill op lines with catch id */
for (i = 0; i < count; i ++) {
oplineinfos[i].catchbbid = BBID_INVALID;
# ifdef ZEND_ENGINE_2_5
oplineinfos[i].finallybbid = BBID_INVALID;
# endif
}
/* {{{ convert try_catch_array.* from oplinenum to bbid */
for (i = 0; i < op_array->last_try_catch; i ++) {
zend_uint j;
zend_try_catch_element *e = &op_array->try_catch_array[i];
zend_uint end = e->catch_op != 0 ? e->catch_op : e->finally_op;
for (j = e->try_op; j < end; j ++) {
oplineinfos[j].catchbbid = e->catch_op == 0 ? BBID_INVALID : oplineinfos[e->catch_op ].bbid;
# define OPNUM_TO_BBID(name) \
op_array->try_catch_array[i].name = oplineinfos[op_array->try_catch_array[i].name].bbid;
OPNUM_TO_BBID(try_op);
OPNUM_TO_BBID(catch_op);
# ifdef ZEND_ENGINE_2_5
oplineinfos[j].finallybbid = e->finally_op == 0 ? BBID_INVALID : oplineinfos[e->finally_op].bbid;
OPNUM_TO_BBID(finally_op);
# endif
}
# undef OPNUM_TO_BBID
}
#ifdef XCACHE_DEBUG
for (i = 0; i < count; i ++) {
# ifdef ZEND_ENGINE_2_5
TRACE("catch/finallybbids[%d] = %d, %d", i, oplineinfos[i].catchbbid, oplineinfos[i].finallybbid);
# else
TRACE("catchbbids[%d] = %d", i, oplineinfos[i].catchbbid);
# endif
}
#endif
/* }}} */
#endif
/* {{{ create basic blocks */
@ -523,12 +484,6 @@ static int bbs_build_from(bbs_t *bbs, zend_op_array *op_array, int count) /* {{{
opline = op_array->opcodes + start;
bb = bbs_new_bb_ex(bbs, opline, i - start);
#ifdef ZEND_ENGINE_2
bb->catch = oplineinfos[start].catchbbid;
#endif
#ifdef ZEND_ENGINE_2_5
bb->finally = oplineinfos[start].finallybbid;
#endif
/* last */
opline = bb->opcodes + bb->count - 1;
@ -566,12 +521,7 @@ static int bbs_build_from(bbs_t *bbs, zend_op_array *op_array, int count) /* {{{
static void bbs_restore_opnum(bbs_t *bbs, zend_op_array *op_array) /* {{{ */
{
int bbid;
#ifdef ZEND_ENGINE_2
bbid_t lastcatchbbid;
#endif
#ifdef ZEND_ENGINE_2_5
bbid_t lastfinallybbid;
#endif
zend_uint i;
for (bbid = 0; bbid < bbs_count(bbs); bbid ++) {
op_flowinfo_t fi;
@ -595,63 +545,18 @@ static void bbs_restore_opnum(bbs_t *bbs, zend_op_array *op_array) /* {{{ */
}
#ifdef ZEND_ENGINE_2
lastcatchbbid = BBID_INVALID;
/* {{{ convert try_catch_array from bbid to oplinenum */
for (i = 0; i < op_array->last_try_catch; i ++) {
# define BBID_TO_OPNUM(name) \
op_array->try_catch_array[i].name = bbs_get(bbs, op_array->try_catch_array[i].name)->opnum;
BBID_TO_OPNUM(try_op);
BBID_TO_OPNUM(catch_op);
# ifdef ZEND_ENGINE_2_5
lastfinallybbid = BBID_INVALID;
BBID_TO_OPNUM(finally_op);
# endif
op_array->last_try_catch = 0;
for (bbid = 0; bbid < bbs_count(bbs); bbid ++) {
bb_t *bb = bbs_get(bbs, bbid);
if (lastcatchbbid != bb->catch
# ifdef ZEND_ENGINE_2_5
|| lastfinallybbid != bb->finally
# endif
) {
if (bb->catch != BBID_INVALID
# ifdef ZEND_ENGINE_2_5
|| bb->finally != BBID_INVALID
# endif
) {
zend_uint try_op = bbs_get(bbs, bbid)->opnum;
zend_uint catch_op = bb->catch == BBID_INVALID ? 0 : bbs_get(bbs, bb->catch )->opnum;
# ifdef ZEND_ENGINE_2_5
zend_uint finally_op = bb->finally == BBID_INVALID ? 0 : bbs_get(bbs, bb->finally)->opnum;
# endif
zend_bool already_in_try_catch = 0;
int j;
for (j = 0; j < op_array->last_try_catch; ++j) {
zend_try_catch_element *element = &op_array->try_catch_array[j];
if (try_op >= element->try_op && try_op < element->catch_op
&& catch_op == element->catch_op
# ifdef ZEND_ENGINE_2_5
&& finally_op == element->finally_op
# endif
) {
already_in_try_catch = 1;
break;
}
}
if (!already_in_try_catch) {
int try_catch_offset = op_array->last_try_catch ++;
op_array->try_catch_array = erealloc(op_array->try_catch_array, sizeof(zend_try_catch_element) * op_array->last_try_catch);
op_array->try_catch_array[try_catch_offset].try_op = try_op;
op_array->try_catch_array[try_catch_offset].catch_op = catch_op;
# ifdef ZEND_ENGINE_2_5
op_array->try_catch_array[try_catch_offset].finally_op = finally_op;
# endif
}
}
lastcatchbbid = bb->catch;
# ifdef ZEND_ENGINE_2_5
lastfinallybbid = bb->finally;
# endif
}
# undef BBID_TO_OPNUM(name)
}
/* it is impossible to have last bb catched */
/* }}} */
#endif /* ZEND_ENGINE_2 */
}
/* }}} */