summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@php.net>2008-05-07 12:04:58 +0000
committerDmitry Stogov <dmitry@php.net>2008-05-07 12:04:58 +0000
commit37691b0cd046e6490ecc42a411bd313aa0423c08 (patch)
treefaf1adcc5cff44bde887d712bd80e42d80e9f8cb
parent0f5f61c071dcd23954933d8c75909c1b0f3d8c9f (diff)
downloadphp-git-37691b0cd046e6490ecc42a411bd313aa0423c08.tar.gz
Use IS_CV for dirrent access to $this variable
-rw-r--r--Zend/zend_compile.c114
-rw-r--r--Zend/zend_compile.h7
-rw-r--r--Zend/zend_execute_API.c13
-rw-r--r--Zend/zend_language_parser.y48
-rw-r--r--Zend/zend_opcode.c2
-rw-r--r--Zend/zend_vm_def.h2
-rw-r--r--Zend/zend_vm_execute.h15
-rw-r--r--Zend/zend_vm_execute.skl13
8 files changed, 133 insertions, 81 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index fe16738cd5..b090bc6d9e 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -640,12 +640,16 @@ void zend_do_assign(znode *result, znode *variable, znode *value TSRMLS_DC) /* {
}
}
- zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC);
+ zend_do_end_variable_parse(variable, BP_VAR_W, 0 TSRMLS_CC);
last_op_number = get_next_op_number(CG(active_op_array));
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- if (variable->op_type == IS_VAR) {
+ if (variable->op_type == IS_CV) {
+ if (variable->u.var == CG(active_op_array)->this_var) {
+ zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
+ }
+ } else if (variable->op_type == IS_VAR) {
int n = 0;
while (last_op_number - n > 0) {
@@ -712,18 +716,24 @@ static inline zend_bool zend_is_function_or_method_call(znode *variable) /* {{{
void zend_do_assign_ref(znode *result, znode *lvar, znode *rvar TSRMLS_DC) /* {{{ */
{
- int last_op_number = get_next_op_number(CG(active_op_array));
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
-
- if (last_op_number > 0) {
- zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number-1];
+ zend_op *opline;
- if (lvar->op_type == IS_VAR &&
- opline_is_fetch_this(last_op TSRMLS_CC)) {
- zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
- }
- }
+ if (lvar->op_type == IS_CV) {
+ if (lvar->u.var == CG(active_op_array)->this_var) {
+ zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
+ }
+ } else if (lvar->op_type == IS_VAR) {
+ int last_op_number = get_next_op_number(CG(active_op_array));
+
+ if (last_op_number > 0) {
+ opline = &CG(active_op_array)->opcodes[last_op_number-1];
+ if (opline_is_fetch_this(opline TSRMLS_CC)) {
+ zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
+ }
+ }
+ }
+ opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_ASSIGN_REF;
if (zend_is_function_or_method_call(rvar)) {
opline->extended_value = ZEND_RETURNS_FUNCTION;
@@ -979,11 +989,13 @@ void zend_do_begin_variable_parse(TSRMLS_D) /* {{{ */
}
/* }}} */
-void zend_do_end_variable_parse(int type, int arg_offset TSRMLS_DC) /* {{{ */
+void zend_do_end_variable_parse(znode *variable, int type, int arg_offset TSRMLS_DC) /* {{{ */
{
zend_llist *fetch_list_ptr;
zend_llist_element *le;
- zend_op *opline, *opline_ptr=NULL;
+ zend_op *opline = NULL;
+ zend_op *opline_ptr;
+ zend_uint this_var = -1;
zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
@@ -994,12 +1006,36 @@ void zend_do_end_variable_parse(int type, int arg_offset TSRMLS_DC) /* {{{ */
if (le) {
opline_ptr = (zend_op *)le->data;
if (opline_is_fetch_this(opline_ptr TSRMLS_CC)) {
- CG(active_op_array)->uses_this = 1;
+ /* convert to FETCH_?(this) into IS_CV */
+ if (CG(active_op_array)->last == 0 ||
+ CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode != ZEND_BEGIN_SILENCE) {
+
+ this_var = opline_ptr->result.u.var;
+ if (CG(active_op_array)->this_var == -1) {
+ CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), Z_TYPE(opline_ptr->op1.u.constant), Z_UNIVAL(opline_ptr->op1.u.constant), Z_UNILEN(opline_ptr->op1.u.constant));
+ } else {
+ efree(Z_STRVAL(opline_ptr->op1.u.constant));
+ }
+ le = le->next;
+ if (variable->op_type == IS_VAR &&
+ variable->u.var == this_var) {
+ variable->op_type = IS_CV;
+ variable->u.var = CG(active_op_array)->this_var;
+ }
+ } else if (CG(active_op_array)->this_var == -1) {
+ CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), Z_TYPE(opline_ptr->op1.u.constant), ezstrndup(Z_TYPE(opline_ptr->op1.u.constant), Z_UNIVAL(opline_ptr->op1.u.constant), Z_UNILEN(opline_ptr->op1.u.constant)), Z_UNILEN(opline_ptr->op1.u.constant));
+ }
}
- while (1) {
+ while (le) {
+ opline_ptr = (zend_op *)le->data;
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
memcpy(opline, opline_ptr, sizeof(zend_op));
+ if (opline->op1.op_type == IS_VAR &&
+ opline->op1.u.var == this_var) {
+ opline->op1.op_type = IS_CV;
+ opline->op1.u.var = CG(active_op_array)->this_var;
+ }
switch (type) {
case BP_VAR_R:
if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2.op_type == IS_UNUSED) {
@@ -1030,10 +1066,8 @@ void zend_do_end_variable_parse(int type, int arg_offset TSRMLS_DC) /* {{{ */
break;
}
le = le->next;
- if (le == NULL) break;
- opline_ptr = (zend_op *)le->data;
}
- if (type == BP_VAR_W && arg_offset) {
+ if (opline && type == BP_VAR_W && arg_offset) {
opline->extended_value = ZEND_FETCH_MAKE_REF;
}
}
@@ -1465,7 +1499,12 @@ void zend_do_receive_arg(zend_uchar op, znode *var, znode *offset, znode *initia
return;
}
- if (CG(active_op_array)->scope &&
+ if (var->op_type == IS_CV &&
+ var->u.var == CG(active_op_array)->this_var &&
+ (CG(active_op_array)->fn_flags & ZEND_ACC_STATIC) == 0) {
+ zend_error(E_COMPILE_ERROR, "Cannot re-assign $this");
+ } else if (var->op_type == IS_VAR &&
+ CG(active_op_array)->scope &&
((CG(active_op_array)->fn_flags & ZEND_ACC_STATIC) == 0) &&
(Z_TYPE(varname->u.constant) == IS_STRING || Z_TYPE(varname->u.constant) == IS_UNICODE) &&
Z_UNILEN(varname->u.constant) == (sizeof("this")-1) &&
@@ -1584,7 +1623,7 @@ void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC) /* {{{ */
unsigned int len;
unsigned char *ptr = NULL;
- zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC);
+ zend_do_end_variable_parse(left_bracket, BP_VAR_R, 0 TSRMLS_CC);
zend_do_begin_variable_parse(TSRMLS_C);
last_op_number = get_next_op_number(CG(active_op_array))-1;
@@ -2082,17 +2121,17 @@ void zend_do_pass_param(znode *param, zend_uchar op, int offset TSRMLS_DC) /* {{
if (original_op == ZEND_SEND_VAR) {
switch (op) {
case ZEND_SEND_VAR_NO_REF:
- zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC);
+ zend_do_end_variable_parse(param, BP_VAR_R, 0 TSRMLS_CC);
break;
case ZEND_SEND_VAR:
if (function_ptr) {
- zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC);
+ zend_do_end_variable_parse(param, BP_VAR_R, 0 TSRMLS_CC);
} else {
- zend_do_end_variable_parse(BP_VAR_FUNC_ARG, offset TSRMLS_CC);
+ zend_do_end_variable_parse(param, BP_VAR_FUNC_ARG, offset TSRMLS_CC);
}
break;
case ZEND_SEND_REF:
- zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC);
+ zend_do_end_variable_parse(param, BP_VAR_W, 0 TSRMLS_CC);
break;
}
}
@@ -2173,9 +2212,9 @@ void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC) /* {{{ */
if (do_end_vparse) {
if (CG(active_op_array)->return_reference && !zend_is_function_or_method_call(expr)) {
- zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC);
+ zend_do_end_variable_parse(expr, BP_VAR_W, 0 TSRMLS_CC);
} else {
- zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC);
+ zend_do_end_variable_parse(expr, BP_VAR_R, 0 TSRMLS_CC);
}
}
@@ -3720,15 +3759,16 @@ void zend_do_fetch_property(znode *result, znode *object, znode *property TSRMLS
{
zend_op opline;
zend_llist *fetch_list_ptr;
- zend_op *opline_ptr=NULL;
zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);
- if (fetch_list_ptr->count == 1) {
- zend_llist_element *le;
-
- le = fetch_list_ptr->head;
- opline_ptr = (zend_op *) le->data;
+ if (object->op_type == IS_CV) {
+ if (object->u.var == CG(active_op_array)->this_var) {
+ SET_UNUSED(*object); /* this means $this for objects */
+ }
+ } else if (fetch_list_ptr->count == 1) {
+ zend_llist_element *le = fetch_list_ptr->head;
+ zend_op *opline_ptr = (zend_op *) le->data;
if (opline_is_fetch_this(opline_ptr TSRMLS_CC)) {
efree(Z_STRVAL(opline_ptr->op1.u.constant));
@@ -4377,7 +4417,7 @@ void zend_do_indirect_references(znode *result, znode *num_references, znode *va
{
int i;
- zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC);
+ zend_do_end_variable_parse(variable, BP_VAR_R, 0 TSRMLS_CC);
zend_do_normalization(variable, variable TSRMLS_CC);
for (i=1; i<Z_LVAL(num_references->u.constant); i++) {
fetch_simple_variable_ex(result, variable, 0, ZEND_FETCH_R TSRMLS_CC);
@@ -4425,7 +4465,7 @@ void zend_do_isset_or_isempty(int type, znode *result, znode *variable TSRMLS_DC
{
zend_op *last_op;
- zend_do_end_variable_parse(BP_VAR_IS, 0 TSRMLS_CC);
+ zend_do_end_variable_parse(variable, BP_VAR_IS, 0 TSRMLS_CC);
zend_check_writable_variable(variable);
@@ -4501,7 +4541,7 @@ void zend_do_foreach_begin(znode *foreach_token, znode *open_brackets_token, zno
}
/* save the location of FETCH_W instruction(s) */
open_brackets_token->u.opline_num = get_next_op_number(CG(active_op_array));
- zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC);
+ zend_do_end_variable_parse(array, BP_VAR_W, 0 TSRMLS_CC);
if (CG(active_op_array)->last > 0 &&
CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode == ZEND_FETCH_OBJ_W) {
/* Only lock the container if we are fetching from a real container and not $this */
@@ -4612,7 +4652,7 @@ void zend_do_foreach_cont(znode *foreach_token, znode *open_brackets_token, znod
if (assign_by_ref) {
/* Mark FE_FETCH as IS_VAR as it holds the data directly as a value */
- zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC);
+ zend_do_end_variable_parse(value, BP_VAR_W, 0 TSRMLS_CC);
zend_do_assign_ref(NULL, value, &value_node TSRMLS_CC);
} else {
zend_do_assign(&dummy, value, &value_node TSRMLS_CC);
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index 9605002c2a..1c1ed444ee 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -197,6 +197,8 @@ struct _zend_op_array {
unsigned char return_reference;
/* END of common elements */
+ zend_bool done_pass_two;
+
zend_uint *refcount;
zend_op *opcodes;
@@ -220,8 +222,7 @@ struct _zend_op_array {
zend_op *start_op;
int backpatch_count;
- zend_bool done_pass_two;
- zend_bool uses_this;
+ zend_uint this_var;
char *filename;
char *script_encoding;
@@ -405,7 +406,7 @@ void zend_do_pre_incdec(znode *result, znode *op1, zend_uchar op TSRMLS_DC);
void zend_do_post_incdec(znode *result, znode *op1, zend_uchar op TSRMLS_DC);
void zend_do_begin_variable_parse(TSRMLS_D);
-void zend_do_end_variable_parse(int type, int arg_offset TSRMLS_DC);
+void zend_do_end_variable_parse(znode *variable, int type, int arg_offset TSRMLS_DC);
void zend_check_writable_variable(znode *variable);
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index 0657fb10b2..df4700acb6 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -2037,12 +2037,13 @@ ZEND_API void zend_rebuild_symbol_table(TSRMLS_D) /* {{{ */
}
if (EG(current_execute_data) && EG(current_execute_data)->op_array) {
EG(current_execute_data)->symbol_table = EG(active_symbol_table);
- if (EG(current_execute_data)->op_array->uses_this && EG(This)) {
- Z_ADDREF_P(EG(This)); /* For $this pointer */
- if (zend_ascii_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), NULL)==FAILURE) {
- Z_DELREF_P(EG(This));
- }
- }
+
+ if (EG(current_execute_data)->op_array->this_var != -1 &&
+ !EG(current_execute_data)->CVs[EG(current_execute_data)->op_array->this_var] &&
+ EG(This)) {
+ EG(current_execute_data)->CVs[EG(current_execute_data)->op_array->this_var] = (zval**)EG(current_execute_data)->CVs + EG(current_execute_data)->op_array->last_var + EG(current_execute_data)->op_array->this_var;
+ *EG(current_execute_data)->CVs[EG(current_execute_data)->op_array->this_var] = EG(This);
+ }
for (i = 0; i < EG(current_execute_data)->op_array->last_var; i++) {
if (EG(current_execute_data)->CVs[i]) {
zend_u_hash_quick_update(EG(active_symbol_table),
diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y
index ea7640edef..ed6aec35ba 100644
--- a/Zend/zend_language_parser.y
+++ b/Zend/zend_language_parser.y
@@ -277,7 +277,7 @@ unset_variables:
;
unset_variable:
- variable { zend_do_end_variable_parse(BP_VAR_UNSET, 0 TSRMLS_CC); zend_do_unset(&$1 TSRMLS_CC); }
+ variable { zend_do_end_variable_parse(&$1, BP_VAR_UNSET, 0 TSRMLS_CC); zend_do_unset(&$1 TSRMLS_CC); }
;
function_declaration_statement:
@@ -569,21 +569,21 @@ non_empty_for_expr:
expr_without_variable:
T_LIST '(' { zend_do_list_init(TSRMLS_C); } assignment_list ')' '=' expr { zend_do_list_end(&$$, &$7 TSRMLS_CC); }
| variable '=' expr { zend_check_writable_variable(&$1); zend_do_assign(&$$, &$1, &$3 TSRMLS_CC); }
- | variable '=' '&' variable { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_W, 1 TSRMLS_CC); zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$4 TSRMLS_CC); }
- | variable '=' '&' T_NEW class_name_reference { zend_error(E_DEPRECATED, "Assigning the return value of new by reference is deprecated"); zend_check_writable_variable(&$1); zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$4, &$5 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$3, &$4, &$7 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$3 TSRMLS_CC); }
+ | variable '=' '&' variable { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$4, BP_VAR_W, 1 TSRMLS_CC); zend_do_end_variable_parse(&$1, BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$4 TSRMLS_CC); }
+ | variable '=' '&' T_NEW class_name_reference { zend_error(E_DEPRECATED, "Assigning the return value of new by reference is deprecated"); zend_check_writable_variable(&$1); zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$4, &$5 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$3, &$4, &$7 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); zend_do_end_variable_parse(&$1, BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$3 TSRMLS_CC); }
| T_NEW class_name_reference { zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$1, &$2 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$$, &$1, &$4 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); $$.u.EA.type = ZEND_PARSED_NEW; }
| T_CLONE expr { zend_do_clone(&$$, &$2 TSRMLS_CC); }
- | variable T_PLUS_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_ADD, &$$, &$1, &$3 TSRMLS_CC); }
- | variable T_MINUS_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SUB, &$$, &$1, &$3 TSRMLS_CC); }
- | variable T_MUL_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_MUL, &$$, &$1, &$3 TSRMLS_CC); }
- | variable T_DIV_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_DIV, &$$, &$1, &$3 TSRMLS_CC); }
- | variable T_CONCAT_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_CONCAT, &$$, &$1, &$3 TSRMLS_CC); }
- | variable T_MOD_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_MOD, &$$, &$1, &$3 TSRMLS_CC); }
- | variable T_AND_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_BW_AND, &$$, &$1, &$3 TSRMLS_CC); }
- | variable T_OR_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_BW_OR, &$$, &$1, &$3 TSRMLS_CC); }
- | variable T_XOR_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_BW_XOR, &$$, &$1, &$3 TSRMLS_CC); }
- | variable T_SL_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SL, &$$, &$1, &$3 TSRMLS_CC); }
- | variable T_SR_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SR, &$$, &$1, &$3 TSRMLS_CC); }
+ | variable T_PLUS_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_ADD, &$$, &$1, &$3 TSRMLS_CC); }
+ | variable T_MINUS_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SUB, &$$, &$1, &$3 TSRMLS_CC); }
+ | variable T_MUL_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_MUL, &$$, &$1, &$3 TSRMLS_CC); }
+ | variable T_DIV_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_DIV, &$$, &$1, &$3 TSRMLS_CC); }
+ | variable T_CONCAT_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_CONCAT, &$$, &$1, &$3 TSRMLS_CC); }
+ | variable T_MOD_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_MOD, &$$, &$1, &$3 TSRMLS_CC); }
+ | variable T_AND_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_BW_AND, &$$, &$1, &$3 TSRMLS_CC); }
+ | variable T_OR_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_BW_OR, &$$, &$1, &$3 TSRMLS_CC); }
+ | variable T_XOR_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_BW_XOR, &$$, &$1, &$3 TSRMLS_CC); }
+ | variable T_SL_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SL, &$$, &$1, &$3 TSRMLS_CC); }
+ | variable T_SR_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SR, &$$, &$1, &$3 TSRMLS_CC); }
| rw_variable T_INC { zend_do_post_incdec(&$$, &$1, ZEND_POST_INC TSRMLS_CC); }
| T_INC rw_variable { zend_do_pre_incdec(&$$, &$2, ZEND_PRE_INC TSRMLS_CC); }
| rw_variable T_DEC { zend_do_post_incdec(&$$, &$1, ZEND_POST_DEC TSRMLS_CC); }
@@ -654,13 +654,13 @@ function_call:
| variable_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING '(' { zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
function_call_parameter_list
')' { zend_do_end_function_call(NULL, &$$, &$6, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
- | variable_class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects '(' { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
+ | variable_class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects '(' { zend_do_end_variable_parse(&$3, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
function_call_parameter_list
')' { zend_do_end_function_call(NULL, &$$, &$6, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
- | class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects '(' { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
+ | class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects '(' { zend_do_end_variable_parse(&$3, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
function_call_parameter_list
')' { zend_do_end_function_call(NULL, &$$, &$6, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
- | variable_without_objects '(' { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_dynamic_function_call(&$1, 0 TSRMLS_CC); }
+ | variable_without_objects '(' { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_dynamic_function_call(&$1, 0 TSRMLS_CC); }
function_call_parameter_list ')'
{ zend_do_end_function_call(&$1, &$$, &$4, 0, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);}
;
@@ -683,7 +683,7 @@ fully_qualified_class_name:
class_name_reference:
class_name { zend_do_fetch_class(&$$, &$1 TSRMLS_CC); }
- | dynamic_class_name_reference { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_fetch_class(&$$, &$1 TSRMLS_CC); }
+ | dynamic_class_name_reference { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); zend_do_fetch_class(&$$, &$1 TSRMLS_CC); }
;
@@ -784,16 +784,16 @@ expr:
r_variable:
- variable { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); $$ = $1; }
+ variable { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); $$ = $1; }
;
w_variable:
- variable { zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); $$ = $1; zend_check_writable_variable(&$1); }
+ variable { zend_do_end_variable_parse(&$1, BP_VAR_W, 0 TSRMLS_CC); $$ = $1; zend_check_writable_variable(&$1); }
;
rw_variable:
- variable { zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); $$ = $1; zend_check_writable_variable(&$1); }
+ variable { zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); $$ = $1; zend_check_writable_variable(&$1); }
;
variable:
@@ -832,7 +832,7 @@ static_member:
;
variable_class_name:
- reference_variable { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); $$=$1;}
+ reference_variable { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); $$=$1;}
;
@@ -868,7 +868,7 @@ dim_offset:
object_property:
object_dim_list { $$ = $1; }
- | variable_without_objects { znode tmp_znode; zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_pop_object(&tmp_znode TSRMLS_CC); zend_do_fetch_property(&$$, &tmp_znode, &$1 TSRMLS_CC);}
+ | variable_without_objects { znode tmp_znode; zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); zend_do_pop_object(&tmp_znode TSRMLS_CC); zend_do_fetch_property(&$$, &tmp_znode, &$1 TSRMLS_CC);}
;
object_dim_list:
@@ -917,7 +917,7 @@ non_empty_array_pair_list:
;
encaps_list:
- encaps_list encaps_var { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_add_variable(&$$, &$1, &$2 TSRMLS_CC); }
+ encaps_list encaps_var { zend_do_end_variable_parse(&$2, BP_VAR_R, 0 TSRMLS_CC); zend_do_add_variable(&$$, &$1, &$2 TSRMLS_CC); }
| encaps_list T_ENCAPSED_AND_WHITESPACE { zend_do_add_string(&$$, &$1, &$2 TSRMLS_CC); }
| /* empty */ { zend_do_init_string(&$$ TSRMLS_CC); }
diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c
index e58b54bc37..a5da22afe5 100644
--- a/Zend/zend_opcode.c
+++ b/Zend/zend_opcode.c
@@ -101,7 +101,7 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz
op_array->return_reference = 0;
op_array->done_pass_two = 0;
- op_array->uses_this = 0;
+ op_array->this_var = -1;
op_array->start_op = NULL;
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index e3fae90397..6ee4697ac9 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -2454,7 +2454,7 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, ANY, CV)
} else {
zend_compiled_variable *cv = &CV_DEF_OF(opline->op2.u.var);
zend_u_hash_quick_update(EG(active_symbol_table), ZEND_STR_TYPE, cv->name, cv->name_len+1, cv->hash_value,
- &EG(exception), sizeof(zval *), NULL);
+ &EG(exception), sizeof(zval *), (void**)&EX(CVs)[opline->op2.u.var]);
}
EG(exception) = NULL;
ZEND_VM_NEXT_OPCODE();
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 381ac17dd1..56dbeedab7 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -69,10 +69,15 @@ ZEND_API void execute(zend_op_array *op_array TSRMLS_DC)
ZEND_VM_SET_OPCODE(op_array->opcodes);
}
- if (op_array->uses_this && EG(This) && EG(active_symbol_table)) {
- Z_ADDREF_P(EG(This)); /* For $this pointer */
- if (zend_ascii_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), NULL)==FAILURE) {
- Z_DELREF_P(EG(This));
+ if (op_array->this_var != -1 && EG(This)) {
+ Z_ADDREF_P(EG(This)); /* For $this pointer */
+ if (!EG(active_symbol_table)) {
+ EX(CVs)[op_array->this_var] = (zval**)EX(CVs) + (op_array->last_var + op_array->this_var);
+ *EX(CVs)[op_array->this_var] = EG(This);
+ } else {
+ if (zend_ascii_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), (void**)&EX(CVs)[op_array->this_var])==FAILURE) {
+ Z_DELREF_P(EG(This));
+ }
}
}
@@ -1060,7 +1065,7 @@ static int ZEND_CATCH_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
} else {
zend_compiled_variable *cv = &CV_DEF_OF(opline->op2.u.var);
zend_u_hash_quick_update(EG(active_symbol_table), ZEND_STR_TYPE, cv->name, cv->name_len+1, cv->hash_value,
- &EG(exception), sizeof(zval *), NULL);
+ &EG(exception), sizeof(zval *), (void**)&EX(CVs)[opline->op2.u.var]);
}
EG(exception) = NULL;
ZEND_VM_NEXT_OPCODE();
diff --git a/Zend/zend_vm_execute.skl b/Zend/zend_vm_execute.skl
index 911b01f7f3..9d86777219 100644
--- a/Zend/zend_vm_execute.skl
+++ b/Zend/zend_vm_execute.skl
@@ -37,10 +37,15 @@ ZEND_API void {%EXECUTOR_NAME%}(zend_op_array *op_array TSRMLS_DC)
ZEND_VM_SET_OPCODE(op_array->opcodes);
}
- if (op_array->uses_this && EG(This) && EG(active_symbol_table)) {
- Z_ADDREF_P(EG(This)); /* For $this pointer */
- if (zend_ascii_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), NULL)==FAILURE) {
- Z_DELREF_P(EG(This));
+ if (op_array->this_var != -1 && EG(This)) {
+ Z_ADDREF_P(EG(This)); /* For $this pointer */
+ if (!EG(active_symbol_table)) {
+ EX(CVs)[op_array->this_var] = (zval**)EX(CVs) + (op_array->last_var + op_array->this_var);
+ *EX(CVs)[op_array->this_var] = EG(This);
+ } else {
+ if (zend_ascii_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), (void**)&EX(CVs)[op_array->this_var])==FAILURE) {
+ Z_DELREF_P(EG(This));
+ }
}
}