summaryrefslogtreecommitdiff
path: root/Zend/zend_compile.c
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_compile.c')
-rw-r--r--Zend/zend_compile.c114
1 files changed, 70 insertions, 44 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 3d9b2e77c6..9127c110bd 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -64,18 +64,20 @@ typedef struct _zend_loop_var {
} u;
} zend_loop_var;
-static inline void zend_alloc_cache_slot(uint32_t literal) {
+static inline uint32_t zend_alloc_cache_slot(void) {
zend_op_array *op_array = CG(active_op_array);
- Z_CACHE_SLOT(op_array->literals[literal]) = op_array->cache_size;
+ uint32_t ret = op_array->cache_size;
op_array->cache_size += sizeof(void*);
+ return ret;
}
#define POLYMORPHIC_CACHE_SLOT_SIZE 2
-static inline void zend_alloc_polymorphic_cache_slot(uint32_t literal) {
+static inline uint32_t zend_alloc_polymorphic_cache_slot(void) {
zend_op_array *op_array = CG(active_op_array);
- Z_CACHE_SLOT(op_array->literals[literal]) = op_array->cache_size;
+ uint32_t ret = op_array->cache_size;
op_array->cache_size += POLYMORPHIC_CACHE_SLOT_SIZE * sizeof(void*);
+ return ret;
}
ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type);
@@ -453,7 +455,6 @@ static inline void zend_insert_literal(zend_op_array *op_array, zval *zv, int li
zval_make_interned_string(zv);
}
ZVAL_COPY_VALUE(CT_CONSTANT_EX(op_array, literal_position), zv);
- Z_CACHE_SLOT(op_array->literals[literal_position]) = -1;
}
/* }}} */
@@ -531,8 +532,6 @@ static int zend_add_class_name_literal(zend_op_array *op_array, zend_string *nam
zend_string *lc_name = zend_string_tolower(name);
zend_add_literal_string(op_array, &lc_name);
- zend_alloc_cache_slot(ret);
-
return ret;
}
/* }}} */
@@ -2026,7 +2025,34 @@ static void zend_find_live_range(zend_op *opline, zend_uchar type, uint32_t var)
} else if (def->opcode == ZEND_NEW) {
/* Objects created via ZEND_NEW are only fully initialized
* after the DO_FCALL (constructor call) */
- def = CG(active_op_array)->opcodes + def->op2.opline_num - 1;
+ int level = 0;
+ while (def + 1 != opline) {
+ def++;
+ if (def->opcode == ZEND_DO_FCALL) {
+ if (level == 0) {
+ break;
+ }
+ level--;
+ } else {
+ switch(def->opcode) {
+ case ZEND_INIT_FCALL:
+ case ZEND_INIT_FCALL_BY_NAME:
+ case ZEND_INIT_NS_FCALL_BY_NAME:
+ case ZEND_INIT_DYNAMIC_CALL:
+ case ZEND_INIT_USER_CALL:
+ case ZEND_INIT_METHOD_CALL:
+ case ZEND_INIT_STATIC_METHOD_CALL:
+ case ZEND_NEW:
+ level++;
+ break;
+ case ZEND_DO_ICALL:
+ case ZEND_DO_UCALL:
+ case ZEND_DO_FCALL_BY_NAME:
+ level--;
+ break;
+ }
+ }
+ }
if (def + 1 == opline) {
break;
}
@@ -2507,6 +2533,7 @@ static zend_op *zend_compile_class_ref(znode *result, zend_ast *name_ast, int th
opline->op2_type = IS_CONST;
opline->op2.constant = zend_add_class_name_literal(CG(active_op_array),
zend_resolve_class_name(name, type));
+ opline->extended_value = zend_alloc_cache_slot();
} else {
zend_ensure_valid_class_fetch_type(fetch_type);
}
@@ -2742,7 +2769,7 @@ static zend_op *zend_delayed_compile_prop(znode *result, zend_ast *ast, uint32_t
opline = zend_delayed_emit_op(result, ZEND_FETCH_OBJ_R, &obj_node, &prop_node);
if (opline->op2_type == IS_CONST) {
convert_to_string(CT_CONSTANT(opline->op2));
- zend_alloc_polymorphic_cache_slot(opline->op2.constant);
+ opline->extended_value = zend_alloc_polymorphic_cache_slot();
}
zend_adjust_for_fetch_type(opline, type);
@@ -2777,12 +2804,15 @@ zend_op *zend_compile_static_prop(znode *result, zend_ast *ast, uint32_t type, i
}
if (opline->op1_type == IS_CONST) {
convert_to_string(CT_CONSTANT(opline->op1));
- zend_alloc_polymorphic_cache_slot(opline->op1.constant);
+ opline->extended_value = zend_alloc_polymorphic_cache_slot();
}
if (class_node.op_type == IS_CONST) {
opline->op2_type = IS_CONST;
opline->op2.constant = zend_add_class_name_literal(
CG(active_op_array), Z_STR(class_node.u.constant));
+ if (opline->op1_type != IS_CONST) {
+ opline->extended_value = zend_alloc_polymorphic_cache_slot();
+ }
} else {
SET_NODE(opline->op2, &class_node);
}
@@ -3148,7 +3178,7 @@ void zend_compile_compound_assign(znode *result, zend_ast *ast) /* {{{ */
znode var_node, expr_node;
zend_op *opline;
- uint32_t offset;
+ uint32_t offset, cache_slot;
zend_ensure_writable_variable(var_ast);
@@ -3178,10 +3208,12 @@ void zend_compile_compound_assign(znode *result, zend_ast *ast) /* {{{ */
zend_compile_expr(&expr_node, expr_ast);
opline = zend_delayed_compile_end(offset);
+ cache_slot = opline->extended_value;
opline->opcode = opcode;
opline->extended_value = ZEND_ASSIGN_OBJ;
- zend_emit_op_data(&expr_node);
+ opline = zend_emit_op_data(&expr_node);
+ opline->extended_value = cache_slot;
return;
EMPTY_SWITCH_DEFAULT_CASE()
}
@@ -3385,7 +3417,7 @@ void zend_compile_ns_call(znode *result, znode *name_node, zend_ast *args_ast) /
opline->op2_type = IS_CONST;
opline->op2.constant = zend_add_ns_func_name_literal(
CG(active_op_array), Z_STR(name_node->u.constant));
- zend_alloc_cache_slot(opline->op2.constant);
+ opline->result.num = zend_alloc_cache_slot();
zend_compile_call_common(result, args_ast, NULL);
}
@@ -3406,7 +3438,8 @@ void zend_compile_dynamic_call(znode *result, znode *name_node, zend_ast *args_a
opline->op1.constant = zend_add_class_name_literal(CG(active_op_array), class);
opline->op2_type = IS_CONST;
opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), method);
- zend_alloc_cache_slot(opline->op2.constant);
+ /* 2 slots, for class and method */
+ opline->result.num = zend_alloc_polymorphic_cache_slot();
zval_ptr_dtor(&name_node->u.constant);
} else {
zend_op *opline = get_next_op(CG(active_op_array));
@@ -3415,7 +3448,7 @@ void zend_compile_dynamic_call(znode *result, znode *name_node, zend_ast *args_a
SET_UNUSED(opline->op1);
opline->op2_type = IS_CONST;
opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), str);
- zend_alloc_cache_slot(opline->op2.constant);
+ opline->result.num = zend_alloc_cache_slot();
}
} else {
zend_emit_op(NULL, ZEND_INIT_DYNAMIC_CALL, NULL, name_node);
@@ -3521,7 +3554,7 @@ int zend_compile_func_defined(znode *result, zend_ast_list *args) /* {{{ */
opline = zend_emit_op_tmp(result, ZEND_DEFINED, NULL, NULL);
opline->op1_type = IS_CONST;
LITERAL_STR(opline->op1, name);
- zend_alloc_cache_slot(opline->op1.constant);
+ opline->extended_value = zend_alloc_cache_slot();
/* Lowercase constant name in a separate literal */
{
@@ -3595,7 +3628,7 @@ static int zend_try_compile_ct_bound_init_user_func(zend_ast *name_ast, uint32_t
opline->op1.num = zend_vm_calc_used_stack(num_args, fbc);
opline->op2_type = IS_CONST;
LITERAL_STR(opline->op2, lcname);
- zend_alloc_cache_slot(opline->op2.constant);
+ opline->result.num = zend_alloc_cache_slot();
return SUCCESS;
}
@@ -3715,7 +3748,7 @@ static int zend_compile_assert(znode *result, zend_ast_list *args, zend_string *
opline->op2.constant = zend_add_ns_func_name_literal(
CG(active_op_array), name);
}
- zend_alloc_cache_slot(opline->op2.constant);
+ opline->result.num = zend_alloc_cache_slot();
if (args->children == 1 &&
(args->child[0]->kind != ZEND_AST_ZVAL ||
@@ -4075,7 +4108,7 @@ void zend_compile_call(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
ZVAL_NEW_STR(&name_node.u.constant, lcname);
opline = zend_emit_op(NULL, ZEND_INIT_FCALL, NULL, &name_node);
- zend_alloc_cache_slot(opline->op2.constant);
+ opline->result.num = zend_alloc_cache_slot();
zend_compile_call_common(result, args_ast, fbc);
}
@@ -4109,7 +4142,7 @@ void zend_compile_method_call(znode *result, zend_ast *ast, uint32_t type) /* {{
opline->op2_type = IS_CONST;
opline->op2.constant = zend_add_func_name_literal(CG(active_op_array),
Z_STR(method_node.u.constant));
- zend_alloc_polymorphic_cache_slot(opline->op2.constant);
+ opline->result.num = zend_alloc_polymorphic_cache_slot();
} else {
SET_NODE(opline->op2, &method_node);
}
@@ -4170,12 +4203,11 @@ void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type) /* {{
opline->op2_type = IS_CONST;
opline->op2.constant = zend_add_func_name_literal(CG(active_op_array),
Z_STR(method_node.u.constant));
+ opline->result.num = zend_alloc_polymorphic_cache_slot();
+ } else {
if (opline->op1_type == IS_CONST) {
- zend_alloc_cache_slot(opline->op2.constant);
- } else {
- zend_alloc_polymorphic_cache_slot(opline->op2.constant);
+ opline->result.num = zend_alloc_cache_slot();
}
- } else {
SET_NODE(opline->op2, &method_node);
}
zend_check_live_ranges(opline);
@@ -4238,17 +4270,13 @@ void zend_compile_new(znode *result, zend_ast *ast) /* {{{ */
opline->op1_type = IS_CONST;
opline->op1.constant = zend_add_class_name_literal(
CG(active_op_array), Z_STR(class_node.u.constant));
+ opline->op2.num = zend_alloc_cache_slot();
} else {
SET_NODE(opline->op1, &class_node);
}
zend_compile_call_common(&ctor_result, args_ast, NULL);
zend_do_free(&ctor_result);
-
- /* We save the position of DO_FCALL for convenience in find_live_range().
- * This info is not preserved for runtime. */
- opline = &CG(active_op_array)->opcodes[opnum];
- opline->op2.opline_num = get_next_op_number(CG(active_op_array));
}
/* }}} */
@@ -4279,7 +4307,7 @@ void zend_compile_global_var(zend_ast *ast) /* {{{ */
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use $this as global variable");
} else if (zend_try_compile_cv(&result, var_ast) == SUCCESS) {
zend_op *opline = zend_emit_op(NULL, ZEND_BIND_GLOBAL, &result, &name_node);
- zend_alloc_cache_slot(opline->op2.constant);
+ opline->extended_value = zend_alloc_cache_slot();
} else {
/* name_ast should be evaluated only. FETCH_GLOBAL_LOCK instructs FETCH_W
* to not free the name_node operand, so it can be reused in the following
@@ -5209,6 +5237,7 @@ void zend_compile_try(zend_ast *ast) /* {{{ */
opline->op1_type = IS_CONST;
opline->op1.constant = zend_add_class_name_literal(CG(active_op_array),
zend_resolve_class_name_ast(class_ast));
+ opline->extended_value = zend_alloc_cache_slot();
if (zend_string_equals_literal(var_name, "this")) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
@@ -5218,7 +5247,7 @@ void zend_compile_try(zend_ast *ast) /* {{{ */
opline->result.var = lookup_cv(CG(active_op_array), var_name);
if (is_last_catch && is_last_class) {
- opline->extended_value = ZEND_LAST_CATCH;
+ opline->extended_value |= ZEND_LAST_CATCH;
}
if (!is_last_class) {
@@ -5675,9 +5704,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */
/* Allocate cache slot to speed-up run-time class resolution */
if (opline->opcode == ZEND_RECV_INIT) {
if (ZEND_TYPE_IS_CLASS(arg_info->type)) {
- zend_alloc_cache_slot(opline->op2.constant);
- } else {
- Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = -1;
+ opline->extended_value = zend_alloc_cache_slot();
}
} else {
if (ZEND_TYPE_IS_CLASS(arg_info->type)) {
@@ -5688,9 +5715,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */
}
}
} else {
- if (opline->opcode == ZEND_RECV_INIT) {
- Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = -1;
- } else {
+ if (opline->opcode != ZEND_RECV_INIT) {
opline->op2.num = -1;
}
}
@@ -6272,6 +6297,7 @@ void zend_compile_use_trait(zend_ast *ast) /* {{{ */
opline->op2_type = IS_CONST;
opline->op2.constant = zend_add_class_name_literal(CG(active_op_array),
zend_resolve_class_name_ast(trait_ast));
+ opline->extended_value = zend_alloc_cache_slot();
ce->num_traits++;
}
@@ -6314,6 +6340,7 @@ void zend_compile_implements(znode *class_node, zend_ast *ast) /* {{{ */
opline->op2_type = IS_CONST;
opline->op2.constant = zend_add_class_name_literal(CG(active_op_array),
zend_resolve_class_name_ast(class_ast));
+ opline->extended_value = zend_alloc_cache_slot();
CG(active_class_entry)->num_interfaces++;
}
@@ -7515,6 +7542,7 @@ void zend_compile_instanceof(znode *result, zend_ast *ast) /* {{{ */
opline->op2_type = IS_CONST;
opline->op2.constant = zend_add_class_name_literal(
CG(active_op_array), Z_STR(class_node.u.constant));
+ opline->extended_value = zend_alloc_cache_slot();
} else {
SET_NODE(opline->op2, &class_node);
}
@@ -7586,7 +7614,9 @@ void zend_compile_isset_or_empty(znode *result, zend_ast *ast) /* {{{ */
}
result->op_type = opline->result_type = IS_TMP_VAR;
- opline->extended_value |= ast->kind == ZEND_AST_ISSET ? ZEND_ISSET : 0;
+ if (ast->kind == ZEND_AST_ISSET) {
+ opline->extended_value |= ZEND_ISSET;
+ }
}
/* }}} */
@@ -7749,7 +7779,7 @@ void zend_compile_const(znode *result, zend_ast *ast) /* {{{ */
CG(active_op_array), resolved_name, 0);
}
}
- zend_alloc_cache_slot(opline->op2.constant);
+ opline->extended_value = zend_alloc_cache_slot();
}
/* }}} */
@@ -7801,11 +7831,7 @@ void zend_compile_class_const(znode *result, zend_ast *ast) /* {{{ */
zend_set_class_name_op1(opline, &class_node);
- if (opline->op1_type == IS_CONST) {
- zend_alloc_cache_slot(opline->op2.constant);
- } else {
- zend_alloc_polymorphic_cache_slot(opline->op2.constant);
- }
+ opline->extended_value = zend_alloc_polymorphic_cache_slot();
}
/* }}} */