62#define VAR_SOURCE(op) Tsource[VAR_NUM(op.var)]
63#define SET_VAR_SOURCE(opline) Tsource[VAR_NUM(opline->result.var)] = opline
84 strip_leading_nops(op_array, b);
115 return block->successors[block->successors_count - 1];
119 return block->successors[block->successors_count - 1];
129 return block->successors[block->successors_count - (opline->
opcode ==
ZEND_MATCH ? 1 : 2)];
139 if (block->len == 0) {
145 strip_leading_nops(op_array, block);
148 opline = op_array->
opcodes + block->start;
149 end = opline + block->len;
150 while (opline <
end) {
185 zval_ptr_dtor_nogc(&c);
210 zval_ptr_dtor_nogc(&c);
230 if (last_op == opline - 1) {
304 if (src < op_array->opcodes + block->start) {
319 if (src >= op_array->
opcodes + block->start &&
354 Z_LVAL(OPLINE_OP2_LITERAL(sv)) == 1
356 zval *
arg = &OPLINE_OP1_LITERAL(sv);
359 if((flen ==
sizeof(
"function_exists")-1 &&
zend_binary_strcasecmp(fname, flen,
"function_exists",
sizeof(
"function_exists")-1) == 0) ||
360 (flen ==
sizeof(
"is_callable")-1 &&
zend_binary_strcasecmp(fname, flen,
"is_callable",
sizeof(
"is_callable")-1) == 0)
370 }
else if(flen ==
sizeof(
"constant")-1 &&
zend_binary_strcasecmp(fname, flen,
"constant",
sizeof(
"constant")-1) == 0) {
380 }
else if(flen ==
sizeof(
"extension_loaded")-1 &&
zend_binary_strcasecmp(fname, flen,
"extension_loaded",
sizeof(
"extension_loaded")-1) == 0) {
410 int target = get_const_switch_target(cfg, op_array, block, opline, &
ZEND_OP1_LITERAL(opline));
416 block->successors_count = 1;
417 block->successors[0] = target;
435 goto optimize_constant_binary_op;
476 goto optimize_const_unary_op;
598 block->successors_count = 1;
603 block->successors[0] = block->successors[1];
656 block->successors_count = 1;
657 block->successors[0] = block->successors[1];
684 goto optimize_constant_binary_op;
815optimize_constant_binary_op:
832optimize_const_unary_op:
877 while (op < opline) {
944 for (b = blocks; b <
end; b++) {
970 for (; op <
end; op++) {
982 opline = new_opcodes;
985 for (b = blocks; b <
end; b++) {
988 b->
start = opline - new_opcodes;
995 op_array->
opcodes = new_opcodes;
998 for (b = blocks; b <
end; b++) {
1003 switch (opline->
opcode) {
1086 zend_op *opline = new_opcodes;
1088 while (opline <
end) {
1090 opline->
op2.
num != (uint32_t)-1 &&
1091 opline->
op2.
num < (uint32_t)
j) {
1118 target_block = cfg->
blocks + b;
1120 block->successors[
n] = b;
1123 return target_block;
1134 target_block = cfg->
blocks + b;
1136 block->successors[
n] = b;
1139 return target_block;
1148 if (next_block ==
end) {
1163static zend_always_inline bool in_hitlist(
int target,
int *jmp_hitlist,
int jmp_hitlist_count)
1167 for (i = 0; i < jmp_hitlist_count; i++) {
1168 if (jmp_hitlist[i] == target) {
1175#define CHECK_LOOP(target) \
1176 if (EXPECTED(!in_hitlist(target, jmp_hitlist, jmp_hitlist_count))) { \
1177 jmp_hitlist[jmp_hitlist_count++] = target; \
1187 int next, jmp_hitlist_count;
1189 if (block->len == 0) {
1193 last_op = op_array->
opcodes + block->start + block->len - 1;
1194 switch (last_op->
opcode) {
1196 jmp_hitlist_count = 0;
1198 target_block = get_target_block(cfg, block, 0, opt_count);
1199 while (target_block->
len == 1) {
1208 block->successors[0] =
next;
1210 target_block = get_target_block(cfg, block, 0, opt_count);
1213 next_block = get_next_block(cfg, block);
1214 if (target_block == next_block) {
1219 }
else if (target_block->
len == 1) {
1232 block->successors_count = 0;
1241 jmp_hitlist_count = 0;
1243 target_block = get_target_block(cfg, block, 0, opt_count);
1244 while (target_block->
len == 1) {
1251 block->successors[0] =
next;
1256 target_block = get_target_block(cfg, block, 0, opt_count);
1262 jmp_hitlist_count = 0;
1264 target_block = get_target_block(cfg, block, 0, opt_count);
1265 while (target_block->
len == 1) {
1271 }
else if (target->opcode == last_op->
opcode &&
1283 block->successors[0] =
next;
1285 target_block = get_target_block(cfg, block, 0, opt_count);
1288 follow_block = get_follow_block(cfg, block, 1, opt_count);
1289 if (target_block == follow_block) {
1295 block->successors_count = 1;
1297 }
else if (follow_block->
len == 1) {
1300 if (block->successors[0] == follow_block->
successors[0]) {
1306 block->successors[0] = follow_block - cfg->
blocks;
1311 next_block = get_next_block(cfg, follow_block);
1313 if (target_block == next_block) {
1318 block->successors[0] = follow_block->
successors[0];
1319 block->successors[1] = next_block - cfg->
blocks;
1323 follow_block->
len = 0;
1336 jmp_hitlist_count = 0;
1338 target_block = get_target_block(cfg, block, 0, opt_count);
1339 while (target_block->
len == 1) {
1345 }
else if (target->opcode == last_op->
opcode-3 &&
1350 }
else if (target->opcode == last_op->
opcode &&
1351 target->result.var == last_op->
result.
var &&
1362 target->result.var == last_op->
result.
var &&
1367 }
else if (target->opcode ==
ZEND_BOOL &&
1381 last_op->
result.
var = target->result.var;
1387 block->successors[0] =
next;
1389 target_block = get_target_block(cfg, block, 0, opt_count);
1392 follow_block = get_follow_block(cfg, block, 1, opt_count);
1393 if (target_block == follow_block) {
1397 block->successors_count = 1;
1414 uint32_t bitset_len;
1421 if (op_array->
T == 0) {
1426 checkpoint = zend_arena_checkpoint(ctx->
arena);
1427 bitset_len = zend_bitset_len(op_array->
last_var + op_array->
T);
1430 zend_bitset_clear(defined_here, bitset_len);
1438 opline = op_array->
opcodes + block->start;
1439 end = opline + block->len;
1443 zend_bitset_clear(defined_here, bitset_len);
1446 while (opline<
end) {
1449 if (!zend_bitset_in(defined_here, var_num)) {
1450 zend_bitset_incl(used_ext, var_num);
1458 zend_bitset_incl(defined_here, var_num);
1459 }
else if (!zend_bitset_in(defined_here, var_num)) {
1460 zend_bitset_incl(used_ext, var_num);
1464 if (!zend_bitset_in(defined_here, var_num)) {
1465 zend_bitset_incl(used_ext, var_num);
1471 zend_bitset_incl(defined_here, var_num);
1474 switch (opline->
opcode) {
1479 if (!zend_bitset_in(defined_here, var_num)) {
1480 zend_bitset_incl(used_ext, var_num);
1484 zend_bitset_incl(defined_here, var_num);
1495 for (i = op_array->
last_var; i< op_array->
T; i++) {
1496 if (zend_bitset_in(used_ext, i)) {
1498 fprintf(stderr,
"NON-LOCAL-VARS: %d", i);
1510 usage = defined_here;
1520 opline =
end + block->len - 1;
1525 zend_bitset_copy(
usage, used_ext, bitset_len);
1526 }
else if (block->successors_count > 1) {
1527 zend_bitset_union(
usage, used_ext, bitset_len);
1531 while (opline >=
end) {
1535 switch (opline->
opcode) {
1576 switch (opline->
opcode) {
1589 switch (opline->
opcode) {
1610 zend_arena_release(&ctx->
arena, checkpoint);
1624 prev &&
prev->successors_count == 1 &&
prev->successors[0] == i)
1631 for (bb =
prev + 1; bb != b; bb++) {
1678 uint32_t bitset_len;
1686 checkpoint = zend_arena_checkpoint(ctx->
arena);
1690 zend_arena_release(&ctx->
arena, checkpoint);
1698 bitset_len = zend_bitset_len(op_array->
last_var + op_array->
T);
1709 zend_bitset_clear(
usage, bitset_len);
1710 zend_t_usage(&cfg, op_array,
usage, ctx);
1713 for (b = blocks; b <
end; b++) {
1723 zend_optimize_block(b, op_array,
usage, &cfg, Tsource, &opt_count);
1727 for (b = blocks; b <
end; b++) {
1732 if (!zend_optimizer_is_loop_var_free(opline)) {
1738 strip_nops(op_array, b);
1745 for (b = blocks; b <
end; b++) {
1747 zend_jmp_optimization(b, op_array, &cfg, jmp_hitlist, &opt_count);
1755 zend_merge_blocks(op_array, &cfg, &opt_count);
1757 if (opt_count == 0) {
1762 assemble_code_blocks(&cfg, op_array, ctx);
1769 zend_arena_release(&ctx->
arena, checkpoint);
fprintf($stream, string $format, mixed ... $values)
prev(array|object &$array)
copy(string $from, string $to, $context=null)
#define SET_VAR_SOURCE(opline)
#define CHECK_LOOP(target)
void zend_optimize_cfg(zend_op_array *op_array, zend_optimizer_ctx *ctx)
bool zend_optimizer_get_persistent_constant(zend_string *name, zval *result, int copy)
memset(ptr, 0, type->size)
#define pass(a, b, c, mul)
unsigned const char * end
int successors_storage[2]
zend_basic_block * blocks
zend_try_catch_element * try_catch_array
ZEND_API HashTable module_registry
#define ZEND_BITSET_ELM_SIZE
ZEND_API void zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t build_flags, zend_cfg *cfg)
void zend_cfg_remark_reachable_blocks(const zend_op_array *op_array, zend_cfg *cfg)
struct _zend_basic_block zend_basic_block
#define ZEND_BB_REACHABLE
#define ZEND_BB_UNREACHABLE_FREE
struct _zend_cfg zend_cfg
#define ZEND_BB_PROTECTED
#define ZEND_SET_OP_JMP_ADDR(opline, node, val)
#define ZEND_OFFSET_TO_OPLINE_NUM(op_array, base, offset)
struct _zend_op_array zend_op_array
#define ZEND_COMPILE_WITH_FILE_CACHE
#define ZEND_OPLINE_TO_OFFSET(opline, target)
#define ZEND_ACC_HAS_FINALLY_BLOCK
#define ZEND_CONSTANT_FLAGS(c)
#define CONST_NO_FILE_CACHE
struct _zend_constant zend_constant
ZEND_API void zend_dump_op_array(const zend_op_array *op_array, uint32_t dump_flags, const char *msg, const void *data)
#define ZEND_DUMP_HIDE_UNREACHABLE
union _zend_function zend_function
ZEND_API zval *ZEND_FASTCALL zend_hash_find(const HashTable *ht, zend_string *key)
ZEND_API zval *ZEND_FASTCALL zend_hash_index_find(const HashTable *ht, zend_ulong h)
#define ZEND_HASH_FOREACH_END()
#define ZEND_HASH_FOREACH_VAL(ht, _val)
struct _zend_string zend_string
ZEND_API int ZEND_FASTCALL zend_binary_strcasecmp(const char *s1, size_t len1, const char *s2, size_t len2)
ZEND_API bool ZEND_FASTCALL zend_is_true(const zval *op)
#define convert_to_string(op)
bool zend_optimizer_update_op1_const(zend_op_array *op_array, zend_op *opline, zval *val)
zend_result zend_optimizer_eval_strlen(zval *result, const zval *op1)
int zend_optimizer_add_literal(zend_op_array *op_array, const zval *zv)
zend_result zend_optimizer_eval_binary_op(zval *result, uint8_t opcode, zval *op1, zval *op2)
zend_result zend_optimizer_eval_cast(zval *result, uint32_t type, zval *op1)
void zend_optimizer_convert_to_free_op1(zend_op_array *op_array, zend_op *opline)
zend_result zend_optimizer_eval_unary_op(zval *result, uint8_t opcode, zval *op1)
bool zend_optimizer_update_op2_const(zend_op_array *op_array, zend_op *opline, zval *val)
#define ZEND_DUMP_AFTER_BLOCK_PASS
#define ZEND_DUMP_BLOCK_PASS_VARS
#define ZEND_DUMP_BEFORE_BLOCK_PASS
#define INV_EX_COND_EX(op)
#define ZEND_OP1_LITERAL(opline)
#define ZEND_OP2_LITERAL(opline)
#define SAME_VAR(op1, op2)
struct _zend_optimizer_ctx zend_optimizer_ctx
#define COPY_NODE(target, src)
#define LITERAL_BOOL(op, val)
#define ALLOCA_FLAG(name)
#define do_alloca(p, use_heap)
#define zend_always_inline
#define free_alloca(p, use_heap)
ZEND_API zend_new_interned_string_func_t zend_new_interned_string
#define Z_TRY_ADDREF_P(pz)
struct _zend_array HashTable
#define Z_REFCOUNTED(zval)
#define Z_TYPE_INFO(zval)
#define ZVAL_COPY_VALUE(z, v)
function(EX_VAR(opline->result.var))
#define ZEND_IS_IDENTICAL
#define ZEND_FETCH_CONSTANT
#define ZEND_ASSIGN_DIM_OP
#define ZEND_ISSET_ISEMPTY_CV
#define ZEND_VERIFY_RETURN_TYPE
#define ZEND_FETCH_LIST_R
#define ZEND_FETCH_LIST_W
#define ZEND_ASSERT_CHECK
#define ZEND_RETURN_BY_REF
#define ZEND_SWITCH_STRING
#define ZEND_FETCH_STATIC_PROP_R
#define ZEND_PRE_DEC_STATIC_PROP
#define ZEND_ASSIGN_STATIC_PROP_OP
#define ZEND_POST_INC_STATIC_PROP
#define ZEND_IS_NOT_EQUAL
#define ZEND_IS_NOT_IDENTICAL
#define ZEND_POST_DEC_OBJ
#define ZEND_ISSET_ISEMPTY_PROP_OBJ
#define ZEND_ADD_ARRAY_ELEMENT
#define ZEND_ISSET_ISEMPTY_STATIC_PROP
#define ZEND_ASSIGN_STATIC_PROP
#define ZEND_IS_SMALLER_OR_EQUAL
#define ZEND_POST_DEC_STATIC_PROP
#define ZEND_PRE_INC_STATIC_PROP
#define ZEND_DECLARE_LAMBDA_FUNCTION
#define ZEND_ISSET_ISEMPTY_DIM_OBJ
#define ZEND_ISSET_ISEMPTY_VAR
#define ZEND_BIND_INIT_STATIC_OR_JMP
#define ZEND_GENERATOR_RETURN
#define ZEND_ADD_ARRAY_UNPACK
#define ZEND_ARRAY_KEY_EXISTS
#define ZEND_JMP_FRAMELESS
#define ZEND_ASSIGN_OBJ_OP
#define ZEND_FETCH_CLASS_CONSTANT
#define ZEND_POST_INC_OBJ
#define ZEND_DO_FCALL_BY_NAME