diff options
| author | Dmitry Stogov <dmitry@zend.com> | 2018-02-05 19:41:47 +0300 |
|---|---|---|
| committer | Dmitry Stogov <dmitry@zend.com> | 2018-02-05 19:41:47 +0300 |
| commit | ca035f26aa296acf553f289e2d459fd052367db2 (patch) | |
| tree | dcf38faa85759c7c076f3a11371a422ca7f5bee2 /ext | |
| parent | 070a0091b39b1196fe66bf2ba3c52ad4533f5497 (diff) | |
| download | php-git-ca035f26aa296acf553f289e2d459fd052367db2.tar.gz | |
Moved "zval.u2.cache_slot" into free room of "zend_op"
Diffstat (limited to 'ext')
| -rw-r--r-- | ext/opcache/Optimizer/block_pass.c | 2 | ||||
| -rw-r--r-- | ext/opcache/Optimizer/compact_literals.c | 565 | ||||
| -rw-r--r-- | ext/opcache/Optimizer/dfa_pass.c | 2 | ||||
| -rw-r--r-- | ext/opcache/Optimizer/optimize_func_calls.c | 2 | ||||
| -rw-r--r-- | ext/opcache/Optimizer/sccp.c | 4 | ||||
| -rw-r--r-- | ext/opcache/Optimizer/zend_cfg.c | 4 | ||||
| -rw-r--r-- | ext/opcache/Optimizer/zend_dump.c | 2 | ||||
| -rw-r--r-- | ext/opcache/Optimizer/zend_optimizer.c | 117 | ||||
| -rw-r--r-- | ext/opcache/zend_file_cache.c | 4 | ||||
| -rw-r--r-- | ext/opcache/zend_persist.c | 2 |
10 files changed, 491 insertions, 213 deletions
diff --git a/ext/opcache/Optimizer/block_pass.c b/ext/opcache/Optimizer/block_pass.c index 65007a9455..9c0fd96471 100644 --- a/ext/opcache/Optimizer/block_pass.c +++ b/ext/opcache/Optimizer/block_pass.c @@ -965,7 +965,7 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array, zend_op ZEND_SET_OP_JMP_ADDR(opline, opline->op2, new_opcodes + blocks[b->successors[0]].start); break; case ZEND_CATCH: - if (opline->extended_value != ZEND_LAST_CATCH) { + if (!(opline->extended_value & ZEND_LAST_CATCH)) { ZEND_SET_OP_JMP_ADDR(opline, opline->op2, new_opcodes + blocks[b->successors[0]].start); } break; diff --git a/ext/opcache/Optimizer/compact_literals.c b/ext/opcache/Optimizer/compact_literals.c index 63102beaac..b74df321f1 100644 --- a/ext/opcache/Optimizer/compact_literals.c +++ b/ext/opcache/Optimizer/compact_literals.c @@ -42,76 +42,77 @@ #define LITERAL_PROPERTY 0x0900 #define LITERAL_GLOBAL 0x0A00 -#define LITERAL_EX_CLASS 0x4000 -#define LITERAL_EX_OBJ 0x2000 -#define LITERAL_MAY_MERGE 0x1000 #define LITERAL_KIND_MASK 0x0f00 #define LITERAL_NUM_RELATED_MASK 0x000f -#define LITERAL_NUM_SLOTS_MASK 0x00f0 -#define LITERAL_NUM_SLOTS_SHIFT 4 #define LITERAL_NUM_RELATED(info) (info & LITERAL_NUM_RELATED_MASK) -#define LITERAL_NUM_SLOTS(info) ((info & LITERAL_NUM_SLOTS_MASK) >> LITERAL_NUM_SLOTS_SHIFT) typedef struct _literal_info { uint32_t flags; /* bitmask (see defines above) */ - union { - int num; /* variable number or class name literal number */ - } u; } literal_info; -#define LITERAL_FLAGS(kind, slots, related) \ - ((kind) | ((slots) << LITERAL_NUM_SLOTS_SHIFT) | (related)) - -#define LITERAL_INFO(n, kind, merge, slots, related) do { \ - info[n].flags = (((merge) ? LITERAL_MAY_MERGE : 0) | LITERAL_FLAGS(kind, slots, related)); \ - } while (0) - -#define LITERAL_INFO_CLASS(n, kind, merge, slots, related, _num) do { \ - info[n].flags = (LITERAL_EX_CLASS | ((merge) ? LITERAL_MAY_MERGE : 0) | LITERAL_FLAGS(kind, slots, related)); \ - info[n].u.num = (_num); \ +#define LITERAL_INFO(n, kind, related) do { \ + info[n].flags = ((kind) | (related)); \ } while (0) -#define LITERAL_INFO_OBJ(n, kind, merge, slots, related) do { \ - info[n].flags = (LITERAL_EX_OBJ | ((merge) ? LITERAL_MAY_MERGE : 0) | LITERAL_FLAGS(kind, slots, related)); \ - info[n].u.num = (uint32_t)-1; \ - } while (0) - -static void optimizer_literal_obj_info(literal_info *info, - zend_uchar op_type, - znode_op op, - int constant, - uint32_t kind, - uint32_t slots, - uint32_t related, - zend_op_array *op_array) +static zend_bool class_name_type_hint(const zend_op_array *op_array, uint32_t arg_num) { - /* For now we merge only $this object properties and methods. - * In general it's also possible to do it for any CV variable as well, - * but it would require complex dataflow and/or type analysis. - */ - if (Z_TYPE(op_array->literals[constant]) == IS_STRING && - op_type == IS_UNUSED) { - LITERAL_INFO_OBJ(constant, kind, 1, slots, related); + zend_arg_info *arg_info; + + if (arg_num > 0) { + if (op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) { + if (EXPECTED(arg_num <= op_array->num_args)) { + arg_info = &op_array->arg_info[arg_num-1]; + } else if (UNEXPECTED(op_array->fn_flags & ZEND_ACC_VARIADIC)) { + arg_info = &op_array->arg_info[op_array->num_args]; + } else { + return 0; + } + return ZEND_TYPE_IS_CLASS(arg_info->type); + } } else { - LITERAL_INFO(constant, kind, 0, slots, related); + arg_info = op_array->arg_info - 1; + return ZEND_TYPE_IS_CLASS(arg_info->type); } + return 0; } -static void optimizer_literal_class_info(literal_info *info, - zend_uchar op_type, - znode_op op, - int constant, - uint32_t kind, - uint32_t slots, - uint32_t related, - zend_op_array *op_array) +static uint32_t add_static_slot(HashTable *hash, + zend_op_array *op_array, + uint32_t op1, + uint32_t op2, + uint32_t kind, + int *cache_size) { - if (op_type == IS_CONST) { - LITERAL_INFO_CLASS(constant, kind, 1, slots, related, op.constant); + uint32_t ret; + zend_string *key; + size_t key_len; + zval *class_name = &op_array->literals[op1]; + zval *prop_name = &op_array->literals[op2]; + zval *pos, tmp; + + key_len = Z_STRLEN_P(class_name) + sizeof("::") - 1 + Z_STRLEN_P(prop_name); + key = zend_string_alloc(key_len, 0); + memcpy(ZSTR_VAL(key), Z_STRVAL_P(class_name), Z_STRLEN_P(class_name)); + memcpy(ZSTR_VAL(key) + Z_STRLEN_P(class_name), "::", sizeof("::") - 1); + memcpy(ZSTR_VAL(key) + Z_STRLEN_P(class_name) + sizeof("::") - 1, + Z_STRVAL_P(prop_name), + Z_STRLEN_P(prop_name) + 1); + + ZSTR_H(key) = zend_hash_func(ZSTR_VAL(key), ZSTR_LEN(key)); + ZSTR_H(key) += kind; + + pos = zend_hash_find(hash, key); + if (pos) { + ret = Z_LVAL_P(pos); } else { - LITERAL_INFO(constant, kind, 0, slots, related); + ret = *cache_size; + *cache_size += 2 * sizeof(void *); + ZVAL_LONG(&tmp, ret); + zend_hash_add(hash, key, &tmp); } + zend_string_release(key); + return ret; } void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx *ctx) @@ -127,9 +128,9 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx HashTable hash; zend_string *key = NULL; void *checkpoint = zend_arena_checkpoint(ctx->arena); + int *const_slot, *class_slot, *func_slot, *bind_var_slot, *property_slot, *method_slot; if (op_array->last_literal) { - cache_size = 0; info = (literal_info*)zend_arena_calloc(&ctx->arena, op_array->last_literal, sizeof(literal_info)); /* Mark literals of specific types */ @@ -138,66 +139,48 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx while (opline < end) { switch (opline->opcode) { case ZEND_INIT_FCALL: - LITERAL_INFO(opline->op2.constant, LITERAL_FUNC, 1, 1, 1); + LITERAL_INFO(opline->op2.constant, LITERAL_FUNC, 1); break; case ZEND_INIT_FCALL_BY_NAME: - LITERAL_INFO(opline->op2.constant, LITERAL_FUNC, 1, 1, 2); + LITERAL_INFO(opline->op2.constant, LITERAL_FUNC, 2); break; case ZEND_INIT_NS_FCALL_BY_NAME: - LITERAL_INFO(opline->op2.constant, LITERAL_FUNC, 1, 1, 3); + LITERAL_INFO(opline->op2.constant, LITERAL_FUNC, 3); break; case ZEND_INIT_METHOD_CALL: if (opline->op1_type == IS_CONST) { - LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 1, 0, 1); + LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 1); } if (opline->op2_type == IS_CONST) { - optimizer_literal_obj_info( - info, - opline->op1_type, - opline->op1, - opline->op2.constant, - LITERAL_METHOD, 2, 2, - op_array); + LITERAL_INFO(opline->op2.constant, LITERAL_METHOD, 2); } break; case ZEND_INIT_STATIC_METHOD_CALL: if (opline->op1_type == IS_CONST) { - LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 1, 1, 2); + LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 2); } if (opline->op2_type == IS_CONST) { - optimizer_literal_class_info( - info, - opline->op1_type, - opline->op1, - opline->op2.constant, - LITERAL_STATIC_METHOD, (opline->op1_type == IS_CONST) ? 1 : 2, 2, - op_array); + LITERAL_INFO(opline->op2.constant, LITERAL_STATIC_METHOD, 2); } break; case ZEND_CATCH: - LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 1, 1, 2); + LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 2); break; case ZEND_DEFINED: - LITERAL_INFO(opline->op1.constant, LITERAL_CONST, 1, 1, 2); + LITERAL_INFO(opline->op1.constant, LITERAL_CONST, 2); break; case ZEND_FETCH_CONSTANT: if ((opline->op1.num & (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) == (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) { - LITERAL_INFO(opline->op2.constant, LITERAL_CONST, 1, 1, 5); + LITERAL_INFO(opline->op2.constant, LITERAL_CONST, 5); } else { - LITERAL_INFO(opline->op2.constant, LITERAL_CONST, 1, 1, 3); + LITERAL_INFO(opline->op2.constant, LITERAL_CONST, 3); } break; case ZEND_FETCH_CLASS_CONSTANT: if (opline->op1_type == IS_CONST) { - LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 1, 1, 2); + LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 2); } - optimizer_literal_class_info( - info, - opline->op1_type, - opline->op1, - opline->op2.constant, - LITERAL_CLASS_CONST, (opline->op1_type == IS_CONST) ? 1 : 2, 1, - op_array); + LITERAL_INFO(opline->op2.constant, LITERAL_CLASS_CONST, 1); break; case ZEND_FETCH_STATIC_PROP_R: case ZEND_FETCH_STATIC_PROP_W: @@ -208,16 +191,10 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx case ZEND_UNSET_STATIC_PROP: case ZEND_ISSET_ISEMPTY_STATIC_PROP: if (opline->op2_type == IS_CONST) { - LITERAL_INFO(opline->op2.constant, LITERAL_CLASS, 1, 1, 2); + LITERAL_INFO(opline->op2.constant, LITERAL_CLASS, 2); } if (opline->op1_type == IS_CONST) { - optimizer_literal_class_info( - info, - opline->op2_type, - opline->op2, - opline->op1.constant, - LITERAL_STATIC_PROPERTY, 2, 1, - op_array); + LITERAL_INFO(opline->op1.constant, LITERAL_STATIC_PROPERTY, 1); } break; case ZEND_FETCH_CLASS: @@ -225,12 +202,12 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx case ZEND_ADD_TRAIT: case ZEND_INSTANCEOF: if (opline->op2_type == IS_CONST) { - LITERAL_INFO(opline->op2.constant, LITERAL_CLASS, 1, 1, 2); + LITERAL_INFO(opline->op2.constant, LITERAL_CLASS, 2); } break; case ZEND_NEW: if (opline->op1_type == IS_CONST) { - LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 1, 1, 2); + LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 2); } break; case ZEND_ASSIGN_OBJ: @@ -247,13 +224,7 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx case ZEND_POST_DEC_OBJ: case ZEND_ISSET_ISEMPTY_PROP_OBJ: if (opline->op2_type == IS_CONST) { - optimizer_literal_obj_info( - info, - opline->op1_type, - opline->op1, - opline->op2.constant, - LITERAL_PROPERTY, 2, 1, - op_array); + LITERAL_INFO(opline->op2.constant, LITERAL_PROPERTY, 1); } break; case ZEND_ASSIGN_ADD: @@ -270,47 +241,30 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx case ZEND_ASSIGN_BW_XOR: if (opline->op2_type == IS_CONST) { if (opline->extended_value == ZEND_ASSIGN_OBJ) { - optimizer_literal_obj_info( - info, - opline->op1_type, - opline->op1, - opline->op2.constant, - LITERAL_PROPERTY, 2, 1, - op_array); + LITERAL_INFO(opline->op2.constant, LITERAL_PROPERTY, 1); } else { - LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 1, 0, 1); + LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 1); } } break; case ZEND_BIND_GLOBAL: - LITERAL_INFO(opline->op2.constant, LITERAL_GLOBAL, 0, 1, 1); + LITERAL_INFO(opline->op2.constant, LITERAL_GLOBAL, 1); break; case ZEND_RECV_INIT: - LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 0, 0, 1); - if (Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) != (uint32_t)-1) { - Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = cache_size; - cache_size += sizeof(void *); - } + LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 1); break; case ZEND_DECLARE_FUNCTION: case ZEND_DECLARE_CLASS: case ZEND_DECLARE_INHERITED_CLASS: case ZEND_DECLARE_INHERITED_CLASS_DELAYED: - LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 0, 0, 2); + LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 2); break; - case ZEND_RECV: - case ZEND_RECV_VARIADIC: - case ZEND_VERIFY_RETURN_TYPE: - if (opline->op2.num != (uint32_t)-1) { - opline->op2.num = cache_size; - cache_size += sizeof(void *); - } default: if (opline->op1_type == IS_CONST) { - LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 1, 0, 1); + LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 1); } if (opline->op2_type == IS_CONST) { - LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 1, 0, 1); + LITERAL_INFO(opline->op2.constant, LITERAL_VALUE, 1); } break; } @@ -350,26 +304,15 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx } switch (Z_TYPE(op_array->literals[i])) { case IS_NULL: - /* Only checking MAY_MERGE for IS_NULL here - * is because only IS_NULL can be default value for class type hinting(RECV_INIT). */ - if ((info[i].flags & LITERAL_MAY_MERGE)) { - if (l_null < 0) { - l_null = j; - if (i != j) { - op_array->literals[j] = op_array->literals[i]; - info[j] = info[i]; - } - j++; - } - map[i] = l_null; - } else { - map[i] = j; + if (l_null < 0) { + l_null = j; if (i != j) { op_array->literals[j] = op_array->literals[i]; info[j] = info[i]; } j++; } + map[i] = l_null; break; case IS_FALSE: if (l_false < 0) { @@ -422,34 +365,20 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx } break; case IS_STRING: - if (info[i].flags & LITERAL_MAY_MERGE) { - if (info[i].flags & LITERAL_EX_OBJ) { - int key_len = sizeof("$this->") - 1 + Z_STRLEN(op_array->literals[i]); - key = zend_string_alloc(key_len, 0); - memcpy(ZSTR_VAL(key), "$this->", sizeof("$this->") - 1); - memcpy(ZSTR_VAL(key) + sizeof("$this->") - 1, Z_STRVAL(op_array->literals[i]), Z_STRLEN(op_array->literals[i]) + 1); - ZSTR_LEN(key) = key_len; - } else if (info[i].flags & LITERAL_EX_CLASS) { - int key_len; - zval *class_name = &op_array->literals[(info[i].u.num < i) ? map[info[i].u.num] : info[i].u.num]; - key_len = Z_STRLEN_P(class_name) + sizeof("::") - 1 + Z_STRLEN(op_array->literals[i]); - key = zend_string_alloc(key_len, 0); - memcpy(ZSTR_VAL(key), Z_STRVAL_P(class_name), Z_STRLEN_P(class_name)); - memcpy(ZSTR_VAL(key) + Z_STRLEN_P(class_name), "::", sizeof("::") - 1); - memcpy(ZSTR_VAL(key) + Z_STRLEN_P(class_name) + sizeof("::") - 1, - Z_STRVAL(op_array->literals[i]), - Z_STRLEN(op_array->literals[i]) + 1); - } else { - key = zend_string_init(Z_STRVAL(op_array->literals[i]), Z_STRLEN(op_array->literals[i]), 0); - } - ZSTR_H(key) = zend_hash_func(ZSTR_VAL(key), ZSTR_LEN(key)); - ZSTR_H(key) += info[i].flags; + if (LITERAL_NUM_RELATED(info[i].flags) == 1) { + key = zend_string_copy(Z_STR(op_array->literals[i])); + } else { + key = zend_string_init(Z_STRVAL(op_array->literals[i]), Z_STRLEN(op_array->literals[i]), 0); + ZSTR_H(key) = ZSTR_HASH(Z_STR(op_array->literals[i])) + + LITERAL_NUM_RELATED(info[i].flags) - 1; } - if ((info[i].flags & LITERAL_MAY_MERGE) && - (pos = zend_hash_find(&hash, key)) != NULL && - Z_TYPE(op_array->literals[i]) == Z_TYPE(op_array->literals[Z_LVAL_P(pos)]) && - info[i].flags == info[Z_LVAL_P(pos)].flags) { - + pos = zend_hash_find(&hash, key); + if (pos != NULL && + Z_TYPE(op_array->literals[Z_LVAL_P(pos)]) == IS_STRING && + LITERAL_NUM_RELATED(info[i].flags) == LITERAL_NUM_RELATED(info[Z_LVAL_P(pos)].flags) && + (LITERAL_NUM_RELATED(info[i].flags) != 2 || + ((info[i].flags & LITERAL_KIND_MASK) != LITERAL_VALUE && + (info[Z_LVAL_P(pos)].flags & LITERAL_KIND_MASK) != LITERAL_VALUE))) { zend_string_release(key); map[i] = Z_LVAL_P(pos); zval_ptr_dtor_nogc(&op_array->literals[i]); @@ -461,19 +390,13 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx } } else { map[i] = j; - if (info[i].flags & LITERAL_MAY_MERGE) { - ZVAL_LONG(&zv, j); - zend_hash_add_new(&hash, key, &zv); - zend_string_release(key); - } + ZVAL_LONG(&zv, j); + zend_hash_add_new(&hash, key, &zv); + zend_string_release(key); if (i != j) { op_array->literals[j] = op_array->literals[i]; info[j] = info[i]; } - if (LITERAL_NUM_SLOTS(info[i].flags)) { - Z_CACHE_SLOT(op_array->literals[j]) = cache_size; - cache_size += LITERAL_NUM_SLOTS(info[i].flags) * sizeof(void*); - } j++; n = LITERAL_NUM_RELATED(info[i].flags); while (n > 1) { @@ -511,11 +434,19 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx break; } } - zend_hash_destroy(&hash); + zend_hash_clean(&hash); op_array->last_literal = j; - op_array->cache_size = cache_size; - /* Update opcodes to use new literals table */ + const_slot = zend_arena_alloc(&ctx->arena, j * 6 * sizeof(int)); + memset(const_slot, -1, j * 6 * sizeof(int)); + class_slot = const_slot + j; + func_slot = class_slot + j; + bind_var_slot = func_slot + j; + property_slot = bind_var_slot + j; + method_slot = property_slot + j; + + /* Update opcodes to use new literals table */ + cache_size = 0; opline = op_array->opcodes; end = opline + op_array->last; while (opline < end) { @@ -525,8 +456,288 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx if (opline->op2_type == IS_CONST) { opline->op2.constant = map[opline->op2.constant]; } + switch (opline->opcode) { + case ZEND_RECV_INIT: + if (class_name_type_hint(op_array, opline->op1.num)) { + opline->extended_value = cache_size; + cache_size += sizeof(void *); + } + break; + case ZEND_RECV: + case ZEND_RECV_VARIADIC: + if (class_name_type_hint(op_array, opline->op1.num)) { + opline->op2.num = cache_size; + cache_size += sizeof(void *); + } + break; + case ZEND_VERIFY_RETURN_TYPE: + if (class_name_type_hint(op_array, 0)) { + opline->op2.num = cache_size; + cache_size += sizeof(void *); + } + break; + case ZEND_ASSIGN_ADD: + case ZEND_ASSIGN_SUB: + case ZEND_ASSIGN_MUL: + case ZEND_ASSIGN_DIV: + case ZEND_ASSIGN_POW: + case ZEND_ASSIGN_MOD: + case ZEND_ASSIGN_SL: + case ZEND_ASSIGN_SR: + case ZEND_ASSIGN_CONCAT: + case ZEND_ASSIGN_BW_OR: + case ZEND_ASSIGN_BW_AND: + case ZEND_ASSIGN_BW_XOR: + if (opline->extended_value != ZEND_ASSIGN_OBJ) { + break; + } + if (opline->op2_type == IS_CONST) { + // op2 property + if (opline->op1_type == IS_UNUSED && + property_slot[opline->op2.constant] >= 0) { + (opline+1)->extended_value = property_slot[opline->op2.constant]; + } else { + (opline+1)->extended_value = cache_size; + cache_size += 2 * sizeof(void *); + if (opline->op1_type == IS_UNUSED) { + property_slot[opline->op2.constant] = (opline+1)->extended_value; + } + } + } + break; + case ZEND_ASSIGN_OBJ: + case ZEND_FETCH_OBJ_R: + case ZEND_FETCH_OBJ_W: + case ZEND_FETCH_OBJ_RW: + case ZEND_FETCH_OBJ_IS: + case ZEND_FETCH_OBJ_UNSET: + case ZEND_FETCH_OBJ_FUNC_ARG: + case ZEND_UNSET_OBJ: + case ZEND_PRE_INC_OBJ: + case ZEND_PRE_DEC_OBJ: + case ZEND_POST_INC_OBJ: + case ZEND_POST_DEC_OBJ: + if (opline->op2_type == IS_CONST) { + // op2 property + if (opline->op1_type == IS_UNUSED && + property_slot[opline->op2.constant] >= 0) { + opline->extended_value = property_slot[opline->op2.constant]; + } else { + opline->extended_value = cache_size; + cache_size += 2 * sizeof(void *); + if (opline->op1_type == IS_UNUSED) { + property_slot[opline->op2.constant] = opline->extended_value; + } + } + } + break; + case ZEND_ISSET_ISEMPTY_PROP_OBJ: + if (opline->op2_type == IS_CONST) { + // op2 property + if (opline->op1_type == IS_UNUSED && + property_slot[opline->op2.constant] >= 0) { + opline->extended_value = property_slot[opline->op2.constant] | (opline->extended_value & ZEND_ISSET); + } else { + opline->extended_value = cache_size | (opline->extended_value & ZEND_ISSET); + cache_size += 2 * sizeof(void *); + if (opline->op1_type == IS_UNUSED) { + property_slot[opline->op2.constant] = opline->extended_value & ~ZEND_ISSET; + } + } + } + break; + case ZEND_INIT_FCALL: + case ZEND_INIT_FCALL_BY_NAME: + case ZEND_INIT_NS_FCALL_BY_NAME: + // op2 func + if (func_slot[opline->op2.constant] >= 0) { + opline->result.num = func_slot[opline->op2.constant]; + } else { + opline->result.num = cache_size; + cache_size += sizeof(void *); + func_slot[opline->op2.constant] = opline->result.num; + } + break; + case ZEND_INIT_METHOD_CALL: + if (opline->op2_type == IS_CONST) { + // op2 method + if (opline->op1_type == IS_UNUSED && + method_slot[opline->op2.constant] >= 0) { + opline->result.num = method_slot[opline->op2.constant]; + } else { + opline->result.num = cache_size; + cache_size += 2 * sizeof(void *); + if (opline->op1_type == IS_UNUSED) { + method_slot[opline->op2.constant] = opline->result.num; + } + } + } + break; + case ZEND_INIT_STATIC_METHOD_CALL: + if (opline->op2_type == IS_CONST) { + // op2 static method + if (opline->op1_type == IS_CONST) { + opline->result.num = add_static_slot(&hash, op_array, + opline->op1.constant, + opline->op2.constant, + LITERAL_STATIC_METHOD, + &cache_size); + } else { + opline->result.num = cache_size; + cache_size += 2 * sizeof(void *); + } + } else if (opline->op1_type == IS_CONST) { + // op1 class + if (class_slot[opline->op1.constant] >= 0) { + opline->result.num = class_slot[opline->op1.constant]; + } else { + opline->result.num = cache_size; + cache_size += sizeof(void *); + class_slot[opline->op1.constant] = opline->result.num; + } + } + break; + case ZEND_DEFINED: + // op1 const + if (const_slot[opline->op1.constant] >= 0) { + opline->extended_value = const_slot[opline->op1.constant]; + } else { + opline->extended_value = cache_size; + cache_size += sizeof(void *); + const_slot[opline->op1.constant] = opline->extended_value; + } + break; + case ZEND_FETCH_CONSTANT: + // op2 const + if (const_slot[opline->op2.constant] >= 0) { + opline->extended_value = const_slot[opline->op2.constant]; + } else { + opline->extended_value = cache_size; + cache_size += sizeof(void *); + const_slot[opline->op2.constant] = opline->extended_value; + } + break; + case ZEND_FETCH_CLASS_CONSTANT: + if (opline->op1_type == IS_CONST) { + // op1/op2 class_const + opline->extended_value = add_static_slot(&hash, op_array, + opline->op1.constant, + opline->op2.constant, + LITERAL_CLASS_CONST, + &cache_size); + } else { + opline->extended_value = cache_size; + cache_size += 2 * sizeof(void *); + } + break; + case ZEND_FETCH_STATIC_PROP_R: + case ZEND_FETCH_STATIC_PROP_W: + case ZEND_FETCH_STATIC_PROP_RW: + case ZEND_FETCH_STATIC_PROP_IS: + case ZEND_FETCH_STATIC_PROP_UNSET: + case ZEND_FETCH_STATIC_PROP_FUNC_ARG: + case ZEND_UNSET_STATIC_PROP: + if (opline->op1_type == IS_CONST) { + // op1 static property + if (opline->op2_type == IS_CONST) { + opline->extended_value = add_static_slot(&hash, op_array, + opline->op2.constant, + opline->op1.constant, + LITERAL_STATIC_PROPERTY, + &cache_size); + } else { + opline->extended_value = cache_size; + cache_size += 2 * sizeof(void *); + } + } else if (opline->op2_type == IS_CONST) { + // op2 class + if (class_slot[opline->op2.constant] >= 0) { + opline->extended_value = class_slot[opline->op2.constant]; + } else { + opline->extended_value = cache_size; + cache_size += sizeof(void *); + class_slot[opline->op2.constant] = opline->extended_value; + } + } + break; + case ZEND_ISSET_ISEMPTY_STATIC_PROP: + if (opline->op1_type == IS_CONST) { + // op1 static property + if (opline->op2_type == IS_CONST) { + opline->extended_value = add_static_slot(&hash, op_array, + opline->op2.constant, + opline->op1.constant, + LITERAL_STATIC_PROPERTY, + &cache_size) | (opline->extended_value & ZEND_ISSET); + } else { + opline->extended_value = cache_size | (opline->extended_value & ZEND_ISSET); + cache_size += 2 * sizeof(void *); + } + } else if (opline->op2_type == IS_CONST) { + // op2 class + if (class_slot[opline->op2.constant] >= 0) { + opline->extended_value = class_slot[opline->op2.constant] | (opline->extended_value & ZEND_ISSET); + } else { + opline->extended_value = cache_size | (opline->extended_value & ZEND_ISSET); + cache_size += sizeof(void *); + class_slot[opline->op2.constant] = opline->extended_value & ~ZEND_ISSET; + } + } + break; + case ZEND_FETCH_CLASS: + case ZEND_ADD_INTERFACE: + case ZEND_ADD_TRAIT: + case ZEND_INSTANCEOF: + if (opline->op2_type == IS_CONST) { + // op2 class + if (class_slot[opline->op2.constant] >= 0) { + opline->extended_value = class_slot[opline->op2.constant]; + } else { + opline->extended_value = cache_size; + cache_size += sizeof(void *); + class_slot[opline->op2.constant] = opline->extended_value; + } + } + break; + case ZEND_NEW: + if (opline->op1_type == IS_CONST) { + // op1 class + if (class_slot[opline->op1.constant] >= 0) { + opline->op2.num = class_slot[opline->op1.constant]; + } else { + opline->op2.num = cache_size; + cache_size += sizeof(void *); + class_slot[opline->op1.constant] = opline->op2.num; + } + } + break; + case ZEND_CATCH: + if (opline->op1_type == IS_CONST) { + // op1 class + if (class_slot[opline->op1.constant] >= 0) { + opline->extended_value = class_slot[opline->op1.constant] | (opline->extended_value & ZEND_LAST_CATCH); + } else { + opline->extended_value = cache_size | (opline->extended_value & ZEND_LAST_CATCH); + cache_size += sizeof(void *); + class_slot[opline->op1.constant] = opline->extended_value & ~ZEND_LAST_CATCH; + } + } + break; + case ZEND_BIND_GLOBAL: + // op2 bind var + if (bind_var_slot[opline->op2.constant] >= 0) { + opline->extended_value = bind_var_slot[opline->op2.constant]; + } else { + opline->extended_value = cache_size; + cache_size += sizeof(void *); + bind_var_slot[opline->op2.constant] = opline->extended_value; + } + break; + } opline++; } + op_array->cache_size = cache_size; + zend_hash_destroy(&hash); zend_arena_release(&ctx->arena, checkpoint); #if DEBUG_COMPACT_LITERALS diff --git a/ext/opcache/Optimizer/dfa_pass.c b/ext/opcache/Optimizer/dfa_pass.c index 13aec486f6..4a7ba6ba69 100644 --- a/ext/opcache/Optimizer/dfa_pass.c +++ b/ext/opcache/Optimizer/dfa_pass.c @@ -552,7 +552,7 @@ static void zend_ssa_replace_control_link(zend_op_array *op_array, zend_ssa *ssa } break; case ZEND_CATCH: - if (opline->extended_value != ZEND_LAST_CATCH) { + if (!(opline->extended_value & ZEND_LAST_CATCH)) { if (ZEND_OP2_JMP_ADDR(opline) == op_array->opcodes + old->start) { ZEND_SET_OP_JMP_ADDR(opline, opline->op2, op_array->opcodes + dst->start); } diff --git a/ext/opcache/Optimizer/optimize_func_calls.c b/ext/opcache/Optimizer/optimize_func_calls.c index 32de6ba35c..1642994765 100644 --- a/ext/opcache/Optimizer/optimize_func_calls.c +++ b/ext/opcache/Optimizer/optimize_func_calls.c @@ -193,14 +193,12 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx) } else if (fcall->opcode == ZEND_INIT_FCALL_BY_NAME) { fcall->opcode = ZEND_INIT_FCALL; fcall->op1.num = zend_vm_calc_used_stack(fcall->extended_value, call_stack[call].func); - Z_CACHE_SLOT(op_array->literals[fcall->op2.constant + 1]) = Z_CACHE_SLOT(op_array->literals[fcall->op2.constant]); literal_dtor(&ZEND_OP2_LITERAL(fcall)); fcall->op2.constant = fcall->op2.constant + 1; opline->opcode = zend_get_call_op(fcall, call_stack[call].func); } else if (fcall->opcode == ZEND_INIT_NS_FCALL_BY_NAME) { fcall->opcode = ZEND_INIT_FCALL; fcall->op1.num = zend_vm_calc_used_stack(fcall->extended_value, call_stack[call].func); - Z_CACHE_SLOT(op_array->literals[fcall->op2.constant + 1]) = Z_CACHE_SLOT(op_array->literals[fcall->op2.constant]); literal_dtor(&op_array->literals[fcall->op2.constant]); literal_dtor(&op_array->literals[fcall->op2.constant + 2]); fcall->op2.constant = fcall->op2.constant + 1; diff --git a/ext/opcache/Optimizer/sccp.c b/ext/opcache/Optimizer/sccp.c index 1b2623c307..ca5b2213f0 100644 --- a/ext/opcache/Optimizer/sccp.c +++ b/ext/opcache/Optimizer/sccp.c @@ -438,7 +438,7 @@ static inline int ct_eval_isset_dim(zval *result, uint32_t extended_value, zval // TODO return FAILURE; } else { - ZVAL_BOOL(result, extended_value != ZEND_ISSET); + ZVAL_BOOL(result, !(extended_value & ZEND_ISSET)); return SUCCESS; } } @@ -592,7 +592,7 @@ static inline int ct_eval_isset_obj(zval *result, uint32_t extended_value, zval } return SUCCESS; } else { - ZVAL_BOOL(result, extended_value != ZEND_ISSET); + ZVAL_BOOL(result, !(extended_value & ZEND_ISSET)); return SUCCESS; } } diff --git a/ext/opcache/Optimizer/zend_cfg.c b/ext/opcache/Optimizer/zend_cfg.c index a2d021516d..6c29b37c41 100644 --- a/ext/opcache/Optimizer/zend_cfg.c +++ b/ext/opcache/Optimizer/zend_cfg.c @@ -385,7 +385,7 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b BB_START(i + 1); break; case ZEND_CATCH: - if (opline->extended_value != ZEND_LAST_CATCH) { + if (!(opline->extended_value & ZEND_LAST_CATCH)) { BB_START(OP_JMP_ADDR(opline, opline->op2) - op_array->opcodes); } BB_START(i + 1); @@ -546,7 +546,7 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b block->successors[1] = j + 1; break; case ZEND_CATCH: - if (opline->extended_value != ZEND_LAST_CATCH) { + if (!(opline->extended_value & ZEND_LAST_CATCH)) { block->successors_count = 2; block->successors[0] = block_map[OP_JMP_ADDR(opline, opline->op2) - op_array->opcodes]; block->successors[1] = j + 1; diff --git a/ext/opcache/Optimizer/zend_dump.c b/ext/opcache/Optimizer/zend_dump.c index 22e149ae55..7fb55355fd 100644 --- a/ext/opcache/Optimizer/zend_dump.c +++ b/ext/opcache/Optimizer/zend_dump.c @@ -674,7 +674,7 @@ static void zend_dump_op(const zend_op_array *op_array, const zend_basic_block * } else { uint32_t op2_flags = ZEND_VM_OP2_FLAGS(flags); if (ZEND_VM_OP_JMP_ADDR == (op2_flags & ZEND_VM_OP_MASK)) { - if (opline->opcode != ZEND_CATCH || opline->extended_value != ZEND_LAST_CATCH) { + if (opline->opcode != ZEND_CATCH || !(opline->extended_value & ZEND_LAST_CATCH)) { if (b) { fprintf(stderr, " BB%d", b->successors[n++]); } else { diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c index f9b21ff19e..07860f3998 100644 --- a/ext/opcache/Optimizer/zend_optimizer.c +++ b/ext/opcache/Optimizer/zend_optimizer.c @@ -206,7 +206,6 @@ int zend_optimizer_add_literal(zend_op_array *op_array, zval *zv) op_array->last_literal++; op_array->literals = (zval*)erealloc(op_array->literals, op_array->last_literal * sizeof(zval)); ZVAL_COPY_VALUE(&op_array->literals[i], zv); - Z_CACHE_SLOT(op_array->literals[i]) = -1; return i; } @@ -232,13 +231,10 @@ static inline void drop_leading_backslash(zval *val) { } } -static inline void alloc_cache_slots_op1(zend_op_array *op_array, zend_op *opline, uint32_t num) { - Z_CACHE_SLOT(op_array->literals[opline->op1.constant]) = op_array->cache_size; - op_array->cache_size += num * sizeof(void *); -} -static inline void alloc_cache_slots_op2(zend_op_array *op_array, zend_op *opline, uint32_t num) { - Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = op_array->cache_size; +static inline uint32_t alloc_cache_slots(zend_op_array *op_array, uint32_t num) { + uint32_t ret = op_array->cache_size; op_array->cache_size += num * sizeof(void *); + return ret; } #define REQUIRES_STRING(val) do { \ @@ -275,15 +271,43 @@ int zend_optimizer_update_op1_const(zend_op_array *op_array, case ZEND_RETURN_BY_REF: case ZEND_INSTANCEOF: return 0; - case ZEND_INIT_STATIC_METHOD_CALL: case ZEND_CATCH: - case ZEND_FETCH_CLASS_CONSTANT: + REQUIRES_STRING(val); + drop_leading_backslash(val); + opline->op1.constant = zend_optimizer_add_literal(op_array, val); + opline->extended_value = alloc_cache_slots(op_array, 1) | (opline->extended_value & ZEND_LAST_CATCH); + zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val))); + break; case ZEND_DEFINED: + REQUIRES_STRING(val); + drop_leading_backslash(val); + opline->op1.constant = zend_optimizer_add_literal(op_array, val); + opline->extended_value = alloc_cache_slots(op_array, 1); + zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val))); + break; case ZEND_NEW: REQUIRES_STRING(val); drop_leading_backslash(val); opline->op1.constant = zend_optimizer_add_literal(op_array, val); - alloc_cache_slots_op1(op_array, opline, 1); + opline->op2.num = alloc_cache_slots(op_array, 1); + zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val))); + break; + case ZEND_INIT_STATIC_METHOD_CALL: + REQUIRES_STRING(val); + drop_leading_backslash(val); + opline->op1.constant = zend_optimizer_add_literal(op_array, val); + if (opline->op2_type != IS_CONST) { + opline->result.num = alloc_cache_slots(op_array, 1); + } + zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val))); + break; + case ZEND_FETCH_CLASS_CONSTANT: + REQUIRES_STRING(val); + drop_leading_backslash(val); + opline->op1.constant = zend_optimizer_add_literal(op_array, val); + if (opline->op2_type != IS_CONST) { + opline->extended_value = alloc_cache_slots(op_array, 1); + } zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val))); break; case ZEND_FETCH_STATIC_PROP_R: @@ -292,9 +316,23 @@ int zend_optimizer_update_op1_const(zend_op_array *op_array, case ZEND_FETCH_STATIC_PROP_IS: case ZEND_FETCH_STATIC_PROP_UNSET: case ZEND_FETCH_STATIC_PROP_FUNC_ARG: + case ZEND_UNSET_STATIC_PROP: TO_STRING_NOWARN(val); opline->op1.constant = zend_optimizer_add_literal(op_array, val); - alloc_cache_slots_op1(op_array, opline, 2); + if (opline->op2_type == IS_CONST && opline->extended_value + sizeof(void*) == op_array->cache_size) { + op_array->cache_size += sizeof(void *); + } else { + opline->extended_value = alloc_cache_slots(op_array, 2); + } + break; + case ZEND_ISSET_ISEMPTY_STATIC_PROP: + TO_STRING_NOWARN(val); + opline->op1.constant = zend_optimizer_add_literal(op_array, val); + if (opline->op2_type == IS_CONST && (opline->extended_value & ~ZEND_ISSET) + sizeof(void*) == op_array->cache_size) { + op_array->cache_size += sizeof(void *); + } else { + opline->extended_value = alloc_cache_slots(op_array, 2) | (opline->extended_value & ZEND_ISSET); + } break; case ZEND_SEND_VAR: opline->opcode = ZEND_SEND_VAL; @@ -351,11 +389,22 @@ int zend_optimizer_update_op2_const(zend_op_array *op_array, (opline + 1)->op2.var == opline->result.var) { return 0; } - case ZEND_INIT_FCALL_BY_NAME: - /*case ZEND_INIT_NS_FCALL_BY_NAME:*/ case ZEND_ADD_INTERFACE: case ZEND_ADD_TRAIT: case ZEND_INSTANCEOF: + REQUIRES_STRING(val); + drop_leading_backslash(val); + opline->op2.constant = zend_optimizer_add_literal(op_array, val); + zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val))); + opline->extended_value = alloc_cache_slots(op_array, 1); + break; + case ZEND_INIT_FCALL_BY_NAME: + REQUIRES_STRING(val); + drop_leading_backslash(val); + opline->op2.constant = zend_optimizer_add_literal(op_array, val); + zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val))); + opline->result.num = alloc_cache_slots(op_array, 1); + break; case ZEND_FETCH_STATIC_PROP_R: case ZEND_FETCH_STATIC_PROP_W: case ZEND_FETCH_STATIC_PROP_RW: @@ -363,12 +412,22 @@ int zend_optimizer_update_op2_const(zend_op_array *op_array, case ZEND_FETCH_STATIC_PROP_UNSET: case ZEND_FETCH_STATIC_PROP_FUNC_ARG: case ZEND_UNSET_STATIC_PROP: + REQUIRES_STRING(val); + drop_leading_backslash(val); + opline->op2.constant = zend_optimizer_add_literal(op_array, val); + zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val))); + if (opline->op1_type != IS_CONST) { + opline->extended_value = alloc_cache_slots(op_array, 1); + } + break; case ZEND_ISSET_ISEMPTY_STATIC_PROP: REQUIRES_STRING(val); drop_leading_backslash(val); opline->op2.constant = zend_optimizer_add_literal(op_array, val); zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val))); - alloc_cache_slots_op2(op_array, opline, 1); + if (opline->op1_type != IS_CONST) { + opline->extended_value = alloc_cache_slots(op_array, 1) | (opline->extended_value & ZEND_ISSET); + } break; case ZEND_INIT_FCALL: REQUIRES_STRING(val); @@ -380,7 +439,7 @@ int zend_optimizer_update_op2_const(zend_op_array *op_array, val = &tmp; } opline->op2.constant = zend_optimizer_add_literal(op_array, val); - alloc_cache_slots_op2(op_array, opline, 1); + opline->result.num = alloc_cache_slots(op_array, 1); break; case ZEND_INIT_DYNAMIC_CALL: if (Z_TYPE_P(val) == IS_STRING) { @@ -398,19 +457,25 @@ int zend_optimizer_update_op2_const(zend_op_array *op_array, drop_leading_backslash(val); opline->op2.constant = zend_optimizer_add_literal(op_array, val); zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val))); - alloc_cache_slots_op2(op_array, opline, 1); + opline->result.num = alloc_cache_slots(op_array, 1); } else { opline->op2.constant = zend_optimizer_add_literal(op_array, val); } break; case ZEND_INIT_METHOD_CALL: + REQUIRES_STRING(val); + opline->op2.constant = zend_optimizer_add_literal(op_array, val); + zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val))); + opline->result.num = alloc_cache_slots(op_array, 2); + break; case ZEND_INIT_STATIC_METHOD_CALL: REQUIRES_STRING(val); opline->op2.constant = zend_optimizer_add_literal(op_array, val); zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val))); - alloc_cache_slots_op2(op_array, opline, 2); + if (opline->op1_type != IS_CONST) { + opline->result.num = alloc_cache_slots(op_array, 2); + } break; - /*case ZEND_FETCH_CLASS_CONSTANT:*/ case ZEND_ASSIGN_OBJ: case ZEND_FETCH_OBJ_R: case ZEND_FETCH_OBJ_W: @@ -423,10 +488,14 @@ int zend_optimizer_update_op2_const(zend_op_array *op_array, case ZEND_PRE_DEC_OBJ: case ZEND_POST_INC_OBJ: case ZEND_POST_DEC_OBJ: + TO_STRING_NOWARN(val); + opline->op2.constant = zend_optimizer_add_literal(op_array, val); + opline->extended_value = alloc_cache_slots(op_array, 2); + break; case ZEND_ISSET_ISEMPTY_PROP_OBJ: TO_STRING_NOWARN(val); opline->op2.constant = zend_optimizer_add_literal(op_array, val); - alloc_cache_slots_op2(op_array, opline, 2); + opline->extended_value = alloc_cache_slots(op_array, 2) | (opline->extended_value & ZEND_ISSET); break; case ZEND_ASSIGN_ADD: case ZEND_ASSIGN_SUB: @@ -443,7 +512,7 @@ int zend_optimizer_update_op2_const(zend_op_array *op_array, if (opline->extended_value == ZEND_ASSIGN_OBJ) { TO_STRING_NOWARN(val); opline->op2.constant = zend_optimizer_add_literal(op_array, val); - alloc_cache_slots_op2(op_array, opline, 2); + (opline+1)->extended_value = alloc_cache_slots(op_array, 2); } else { opline->op2.constant = zend_optimizer_add_literal(op_array, val); } @@ -766,7 +835,7 @@ void zend_optimizer_migrate_jump(zend_op_array *op_array, zend_op *new_opline, z new_opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, new_opline, ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value)); break; case ZEND_CATCH: - if (opline->extended_value != ZEND_LAST_CATCH) { + if (!(opline->extended_value & ZEND_LAST_CATCH)) { ZEND_SET_OP_JMP_ADDR(new_opline, new_opline->op2, ZEND_OP2_JMP_ADDR(opline)); } break; @@ -806,7 +875,7 @@ void zend_optimizer_shift_jump(zend_op_array *op_array, zend_op *opline, uint32_ ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP2_JMP_ADDR(opline) - shiftlist[ZEND_OP2_JMP_ADDR(opline) - op_array->opcodes]); break; case ZEND_CATCH: - if (opline->extended_value != ZEND_LAST_CATCH) { + if (!(opline->extended_value & ZEND_LAST_CATCH)) { ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP2_JMP_ADDR(opline) - shiftlist[ZEND_OP2_JMP_ADDR(opline) - op_array->opcodes]); } break; @@ -1174,7 +1243,7 @@ static void zend_redo_pass_two(zend_op_array *op_array) opline->op2.jmp_addr = &op_array->opcodes[opline->op2.jmp_addr - old_opcodes]; break; case ZEND_CATCH: - if (opline->extended_value != ZEND_LAST_CATCH) { + if (!(opline->extended_value & ZEND_LAST_CATCH)) { opline->op2.jmp_addr = &op_array->opcodes[opline->op2.jmp_addr - old_opcodes]; } break; @@ -1260,7 +1329,7 @@ static void zend_redo_pass_two_ex(zend_op_array *op_array, zend_ssa *ssa) opline->op2.jmp_addr = &op_array->opcodes[opline->op2.jmp_addr - old_opcodes]; break; case ZEND_CATCH: - if (opline->extended_value != ZEND_LAST_CATCH) { + if (!(opline->extended_value & ZEND_LAST_CATCH)) { opline->op2.jmp_addr = &op_array->opcodes[opline->op2.jmp_addr - old_opcodes]; } break; diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c index db926a5172..de54949901 100644 --- a/ext/opcache/zend_file_cache.c +++ b/ext/opcache/zend_file_cache.c @@ -447,7 +447,7 @@ static void zend_file_cache_serialize_op_array(zend_op_array *op_arra SERIALIZE_PTR(opline->op2.jmp_addr); break; case ZEND_CATCH: - if (opline->extended_value != ZEND_LAST_CATCH) { + if (!(opline->extended_value & ZEND_LAST_CATCH)) { SERIALIZE_PTR(opline->op2.jmp_addr); } break; @@ -1053,7 +1053,7 @@ static void zend_file_cache_unserialize_op_array(zend_op_array *op_arr UNSERIALIZE_PTR(opline->op2.jmp_addr); break; case ZEND_CATCH: - if (opline->extended_value != ZEND_LAST_CATCH) { + if (!(opline->extended_value & ZEND_LAST_CATCH)) { UNSERIALIZE_PTR(opline->op2.jmp_addr); } break; diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index a2549308ad..8c16538207 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -453,7 +453,7 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc opline->op2.jmp_addr = &new_opcodes[opline->op2.jmp_addr - op_array->opcodes]; break; case ZEND_CATCH: - if (opline->extended_value != ZEND_LAST_CATCH) { + if (!(opline->extended_value & ZEND_LAST_CATCH)) { opline->op2.jmp_addr = &new_opcodes[opline->op2.jmp_addr - op_array->opcodes]; } break; |
