|
|
|
@ -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;
|
|
|
|
|
# ifdef ZEND_ENGINE_2_5
|
|
|
|
|
lastfinallybbid = BBID_INVALID;
|
|
|
|
|
# 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;
|
|
|
|
|
/* {{{ 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 = bb->finally;
|
|
|
|
|
BBID_TO_OPNUM(finally_op);
|
|
|
|
|
# endif
|
|
|
|
|
}
|
|
|
|
|
# undef BBID_TO_OPNUM(name)
|
|
|
|
|
}
|
|
|
|
|
/* it is impossible to have last bb catched */
|
|
|
|
|
/* }}} */
|
|
|
|
|
#endif /* ZEND_ENGINE_2 */
|
|
|
|
|
}
|
|
|
|
|
/* }}} */
|
|
|
|
|