Skip to content
Browse files

Use IS_CV for dirrent access to $this variable

  • Loading branch information...
1 parent 06cef68 commit 5521912b153ab6fd457ea4ce9ea3a7656f09b038 Dmitry Stogov committed May 7, 2008
Showing with 134 additions and 81 deletions.
  1. +1 −0 NEWS
  2. +77 −37 Zend/zend_compile.c
  3. +4 −3 Zend/zend_compile.h
  4. +7 −6 Zend/zend_execute_API.c
  5. +24 −24 Zend/zend_language_parser.y
  6. +1 −1 Zend/zend_opcode.c
  7. +1 −1 Zend/zend_vm_def.h
  8. +10 −5 Zend/zend_vm_execute.h
  9. +9 −4 Zend/zend_vm_execute.skl
View
1 NEWS
@@ -109,6 +109,7 @@ PHP NEWS
- Added native support for asinh(), acosh(), atanh(), log1p() and expm1() (Kalle)
- Improved PHP runtime speed and memory usage:
+ . Use IS_CV for direct access to $this variable. (Dmitry)
. Use ZEND_FREE() opcode instead of ZEND_SWITCH_FREE(IS_TMP_VAR). (Dmitry)
. Lazy EG(active_symbol_table) initialization. (Dmitry)
. Optimized ZEND_RETURN opcode to not allocate and copy return value if it is
View
114 Zend/zend_compile.c
@@ -562,12 +562,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) {
@@ -632,18 +636,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;
@@ -897,11 +907,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);
@@ -912,12 +924,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_STRVAL(opline_ptr->op1.u.constant), Z_STRLEN(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), estrndup("this", sizeof("this")-1), sizeof("this")-1);
+ }
}
- 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) {
@@ -948,10 +984,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;
}
}
@@ -1348,7 +1382,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_STRLEN(varname->u.constant) == sizeof("this")-1) &&
@@ -1455,7 +1494,7 @@ void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC)
int last_op_number;
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;
@@ -1977,17 +2016,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;
}
}
@@ -2066,9 +2105,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);
}
}
@@ -3491,15 +3530,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));
@@ -4124,7 +4164,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);
for (i=1; i<num_references->u.constant.value.lval; i++) {
fetch_simple_variable_ex(result, variable, 0, ZEND_FETCH_R TSRMLS_CC);
*variable = *result;
@@ -4170,7 +4210,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);
@@ -4246,7 +4286,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 */
@@ -4356,7 +4396,7 @@ void zend_do_foreach_cont(znode *foreach_token, znode *open_brackets_token, znod
value_node = opline->result;
if (assign_by_ref) {
- zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC);
+ zend_do_end_variable_parse(value, BP_VAR_W, 0 TSRMLS_CC);
/* Mark FE_FETCH as IS_VAR as it holds the data directly as a value */
zend_do_assign_ref(NULL, value, &value_node TSRMLS_CC);
} else {
View
7 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;
zend_uint line_start;
@@ -396,7 +397,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);
View
13 Zend/zend_execute_API.c
@@ -1811,12 +1811,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_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_hash_quick_update(EG(active_symbol_table),
View
48 Zend/zend_language_parser.y
@@ -275,7 +275,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:
@@ -567,21 +567,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);}
| 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); }
@@ -647,16 +647,16 @@ function_call:
| class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING '(' { $4.u.opline_num = zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); }
function_call_parameter_list
')' { zend_do_end_function_call($4.u.opline_num?NULL:&$3, &$$, &$6, $4.u.opline_num, $4.u.opline_num 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_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);}
- | 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);}
;
@@ -680,7 +680,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); }
;
@@ -779,17 +779,17 @@ 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;
+ 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;
+ variable { zend_do_end_variable_parse(&$1, BP_VAR_RW, 0 TSRMLS_CC); $$ = $1;
zend_check_writable_variable(&$1); }
;
@@ -830,7 +830,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;; }
;
base_variable_with_function_calls:
@@ -865,7 +865,7 @@ dim_offset:
object_property:
object_dim_list { $$ = $1; }
- | variable_without_objects { zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); } { znode tmp_znode; zend_do_pop_object(&tmp_znode TSRMLS_CC); zend_do_fetch_property(&$$, &tmp_znode, &$1 TSRMLS_CC);}
+ | variable_without_objects { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); } { znode tmp_znode; zend_do_pop_object(&tmp_znode TSRMLS_CC); zend_do_fetch_property(&$$, &tmp_znode, &$1 TSRMLS_CC);}
;
object_dim_list:
@@ -914,7 +914,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); }
View
2 Zend/zend_opcode.c
@@ -95,7 +95,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;
View
2 Zend/zend_vm_def.h
@@ -2390,7 +2390,7 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, ANY, CV)
} else {
zend_compiled_variable *cv = &CV_DEF_OF(opline->op2.u.var);
zend_hash_quick_update(EG(active_symbol_table), 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();
View
15 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_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_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));
+ }
}
}
@@ -1080,7 +1085,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_hash_quick_update(EG(active_symbol_table), 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();
View
13 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_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_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));
+ }
}
}

0 comments on commit 5521912

Please sign in to comment.
Something went wrong with that request. Please try again.