Skip to content

Commit

Permalink
Use IS_CV for dirrent access to $this variable
Browse files Browse the repository at this point in the history
  • Loading branch information
dstogov committed May 7, 2008
1 parent 06cef68 commit 5521912
Show file tree
Hide file tree
Showing 9 changed files with 134 additions and 81 deletions.
1 change: 1 addition & 0 deletions NEWS
Expand Up @@ -109,6 +109,7 @@ PHP NEWS
- Added native support for asinh(), acosh(), atanh(), log1p() and expm1() (Kalle) - Added native support for asinh(), acosh(), atanh(), log1p() and expm1() (Kalle)


- Improved PHP runtime speed and memory usage: - 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) . Use ZEND_FREE() opcode instead of ZEND_SWITCH_FREE(IS_TMP_VAR). (Dmitry)
. Lazy EG(active_symbol_table) initialization. (Dmitry) . Lazy EG(active_symbol_table) initialization. (Dmitry)
. Optimized ZEND_RETURN opcode to not allocate and copy return value if it is . Optimized ZEND_RETURN opcode to not allocate and copy return value if it is
Expand Down
114 changes: 77 additions & 37 deletions Zend/zend_compile.c
Expand Up @@ -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)); last_op_number = get_next_op_number(CG(active_op_array));
opline = get_next_op(CG(active_op_array) TSRMLS_CC); 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; int n = 0;


while (last_op_number - n > 0) { while (last_op_number - n > 0) {
Expand Down Expand Up @@ -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) 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;
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];


if (lvar->op_type == IS_VAR && if (lvar->op_type == IS_CV) {
opline_is_fetch_this(last_op TSRMLS_CC)) { if (lvar->u.var == CG(active_op_array)->this_var) {
zend_error(E_COMPILE_ERROR, "Cannot re-assign $this"); 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; opline->opcode = ZEND_ASSIGN_REF;
if (zend_is_function_or_method_call(rvar)) { if (zend_is_function_or_method_call(rvar)) {
opline->extended_value = ZEND_RETURNS_FUNCTION; opline->extended_value = ZEND_RETURNS_FUNCTION;
Expand Down Expand Up @@ -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 *fetch_list_ptr;
zend_llist_element *le; 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); zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);


Expand All @@ -912,12 +924,36 @@ void zend_do_end_variable_parse(int type, int arg_offset TSRMLS_DC)
if (le) { if (le) {
opline_ptr = (zend_op *)le->data; opline_ptr = (zend_op *)le->data;
if (opline_is_fetch_this(opline_ptr TSRMLS_CC)) { 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); opline = get_next_op(CG(active_op_array) TSRMLS_CC);
memcpy(opline, opline_ptr, sizeof(zend_op)); 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) { switch (type) {
case BP_VAR_R: case BP_VAR_R:
if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2.op_type == IS_UNUSED) { if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2.op_type == IS_UNUSED) {
Expand Down Expand Up @@ -948,10 +984,8 @@ void zend_do_end_variable_parse(int type, int arg_offset TSRMLS_DC)
break; break;
} }
le = le->next; 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; opline->extended_value = ZEND_FETCH_MAKE_REF;
} }
} }
Expand Down Expand Up @@ -1348,7 +1382,12 @@ void zend_do_receive_arg(zend_uchar op, znode *var, znode *offset, znode *initia
return; 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) && ((CG(active_op_array)->fn_flags & ZEND_ACC_STATIC) == 0) &&
(Z_TYPE(varname->u.constant) == IS_STRING) && (Z_TYPE(varname->u.constant) == IS_STRING) &&
(Z_STRLEN(varname->u.constant) == sizeof("this")-1) && (Z_STRLEN(varname->u.constant) == sizeof("this")-1) &&
Expand Down Expand Up @@ -1455,7 +1494,7 @@ void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC)
int last_op_number; int last_op_number;
unsigned char *ptr = NULL; 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); zend_do_begin_variable_parse(TSRMLS_C);


last_op_number = get_next_op_number(CG(active_op_array))-1; last_op_number = get_next_op_number(CG(active_op_array))-1;
Expand Down Expand Up @@ -1977,17 +2016,17 @@ void zend_do_pass_param(znode *param, zend_uchar op, int offset TSRMLS_DC)
if (original_op == ZEND_SEND_VAR) { if (original_op == ZEND_SEND_VAR) {
switch (op) { switch (op) {
case ZEND_SEND_VAR_NO_REF: 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; break;
case ZEND_SEND_VAR: case ZEND_SEND_VAR:
if (function_ptr) { 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 { } 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; break;
case ZEND_SEND_REF: 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; break;
} }
} }
Expand Down Expand Up @@ -2066,9 +2105,9 @@ void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC)


if (do_end_vparse) { if (do_end_vparse) {
if (CG(active_op_array)->return_reference && !zend_is_function_or_method_call(expr)) { 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 { } else {
zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); zend_do_end_variable_parse(expr, BP_VAR_R, 0 TSRMLS_CC);
} }
} }


Expand Down Expand Up @@ -3491,15 +3530,16 @@ void zend_do_fetch_property(znode *result, znode *object, znode *property TSRMLS
{ {
zend_op opline; zend_op opline;
zend_llist *fetch_list_ptr; zend_llist *fetch_list_ptr;
zend_op *opline_ptr=NULL;


zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr); zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr);


if (fetch_list_ptr->count == 1) { if (object->op_type == IS_CV) {
zend_llist_element *le; if (object->u.var == CG(active_op_array)->this_var) {

SET_UNUSED(*object); /* this means $this for objects */
le = fetch_list_ptr->head; }
opline_ptr = (zend_op *) le->data; } 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)) { if (opline_is_fetch_this(opline_ptr TSRMLS_CC)) {
efree(Z_STRVAL(opline_ptr->op1.u.constant)); efree(Z_STRVAL(opline_ptr->op1.u.constant));
Expand Down Expand Up @@ -4124,7 +4164,7 @@ void zend_do_indirect_references(znode *result, znode *num_references, znode *va
{ {
int i; 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++) { for (i=1; i<num_references->u.constant.value.lval; i++) {
fetch_simple_variable_ex(result, variable, 0, ZEND_FETCH_R TSRMLS_CC); fetch_simple_variable_ex(result, variable, 0, ZEND_FETCH_R TSRMLS_CC);
*variable = *result; *variable = *result;
Expand Down Expand Up @@ -4170,7 +4210,7 @@ void zend_do_isset_or_isempty(int type, znode *result, znode *variable TSRMLS_DC
{ {
zend_op *last_op; 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); zend_check_writable_variable(variable);


Expand Down Expand Up @@ -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) */ /* save the location of FETCH_W instruction(s) */
open_brackets_token->u.opline_num = get_next_op_number(CG(active_op_array)); 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 && if (CG(active_op_array)->last > 0 &&
CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode == ZEND_FETCH_OBJ_W) { 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 */ /* Only lock the container if we are fetching from a real container and not $this */
Expand Down Expand Up @@ -4356,7 +4396,7 @@ void zend_do_foreach_cont(znode *foreach_token, znode *open_brackets_token, znod
value_node = opline->result; value_node = opline->result;


if (assign_by_ref) { 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 */ /* 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); zend_do_assign_ref(NULL, value, &value_node TSRMLS_CC);
} else { } else {
Expand Down
7 changes: 4 additions & 3 deletions Zend/zend_compile.h
Expand Up @@ -197,6 +197,8 @@ struct _zend_op_array {
unsigned char return_reference; unsigned char return_reference;
/* END of common elements */ /* END of common elements */


zend_bool done_pass_two;

zend_uint *refcount; zend_uint *refcount;


zend_op *opcodes; zend_op *opcodes;
Expand All @@ -220,8 +222,7 @@ struct _zend_op_array {
zend_op *start_op; zend_op *start_op;
int backpatch_count; int backpatch_count;


zend_bool done_pass_two; zend_uint this_var;
zend_bool uses_this;


char *filename; char *filename;
zend_uint line_start; zend_uint line_start;
Expand Down Expand Up @@ -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_post_incdec(znode *result, znode *op1, zend_uchar op TSRMLS_DC);


void zend_do_begin_variable_parse(TSRMLS_D); 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); void zend_check_writable_variable(znode *variable);


Expand Down
13 changes: 7 additions & 6 deletions Zend/zend_execute_API.c
Expand Up @@ -1811,12 +1811,13 @@ ZEND_API void zend_rebuild_symbol_table(TSRMLS_D) /* {{{ */
} }
if (EG(current_execute_data) && EG(current_execute_data)->op_array) { if (EG(current_execute_data) && EG(current_execute_data)->op_array) {
EG(current_execute_data)->symbol_table = EG(active_symbol_table); 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 (EG(current_execute_data)->op_array->this_var != -1 &&
if (zend_hash_add(EG(active_symbol_table), "this", sizeof("this"), &EG(This), sizeof(zval *), NULL)==FAILURE) { !EG(current_execute_data)->CVs[EG(current_execute_data)->op_array->this_var] &&
Z_DELREF_P(EG(This)); 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++) { for (i = 0; i < EG(current_execute_data)->op_array->last_var; i++) {
if (EG(current_execute_data)->CVs[i]) { if (EG(current_execute_data)->CVs[i]) {
zend_hash_quick_update(EG(active_symbol_table), zend_hash_quick_update(EG(active_symbol_table),
Expand Down

0 comments on commit 5521912

Please sign in to comment.