Skip to content
Browse files

- Allow passing references which are returned from functions and new

- statements to be passed by reference.
  • Loading branch information...
1 parent aa11144 commit 8d9082563a92c4f93d561e93e6eca7594e275c01 @andigutmans andigutmans committed Nov 27, 2000
Showing with 63 additions and 38 deletions.
  1. +22 −17 Zend/zend_compile.c
  2. +2 −0 Zend/zend_compile.h
  3. +39 −21 Zend/zend_execute.c
View
39 Zend/zend_compile.c
@@ -916,6 +916,7 @@ void zend_do_pass_param(znode *param, int op, int offset CLS_DC)
unsigned char *arg_types;
int original_op=op;
zend_function **function_ptr_ptr, *function_ptr;
+ int send_by_reference;
zend_stack_top(&CG(function_call_stack), (void **) &function_ptr_ptr);
@@ -939,20 +940,13 @@ void zend_do_pass_param(znode *param, int op, int offset CLS_DC)
arg_types = NULL;
}
- if (op==ZEND_SEND_VAL) {
- switch (param->op_type) {
- case IS_CONST: /* constants behave like variables when passed to functions,
- * as far as reference counting is concerned. Treat them
- * as if they were variables here.
- */
- break;
- case IS_VAR:
- op = ZEND_SEND_VAR_NO_REF;
- break;
- }
+ send_by_reference = ARG_SHOULD_BE_SENT_BY_REF(offset, 1, arg_types)?ZEND_ARG_SEND_BY_REF:0;
+
+ if (op == ZEND_SEND_VAL && param->op_type == IS_VAR) {
+ op = ZEND_SEND_VAR_NO_REF;
}
- if (op!=ZEND_SEND_VAR_NO_REF
- && ARG_SHOULD_BE_SENT_BY_REF(offset, 1, arg_types)) {
+
+ if (op!=ZEND_SEND_VAR_NO_REF && send_by_reference == ZEND_ARG_SEND_BY_REF) {
/* change to passing by reference */
switch (param->op_type) {
case IS_VAR:
@@ -964,9 +958,11 @@ void zend_do_pass_param(znode *param, int op, int offset CLS_DC)
}
}
- if (original_op==ZEND_SEND_VAR) {
+ if (original_op == ZEND_SEND_VAR) {
switch(op) {
case ZEND_SEND_VAR_NO_REF:
+ zend_do_end_variable_parse(BP_VAR_R, 0 CLS_CC);
+ break;
case ZEND_SEND_VAR:
if (function_ptr) {
zend_do_end_variable_parse(BP_VAR_R, 0 CLS_CC);
@@ -981,10 +977,19 @@ void zend_do_pass_param(znode *param, int op, int offset CLS_DC)
}
opline = get_next_op(CG(active_op_array) CLS_CC);
- if (function_ptr) {
- opline->extended_value = ZEND_DO_FCALL;
+
+ if (op == ZEND_SEND_VAR_NO_REF) {
+ if (function_ptr) {
+ opline->extended_value = ZEND_ARG_COMPILE_TIME_BOUND | send_by_reference;
+ } else {
+ opline->extended_value = 0;
+ }
} else {
- opline->extended_value = ZEND_DO_FCALL_BY_NAME;
+ if (function_ptr) {
+ opline->extended_value = ZEND_DO_FCALL;
+ } else {
+ opline->extended_value = ZEND_DO_FCALL_BY_NAME;
+ }
}
opline->opcode = op;
opline->op1 = *param;
View
2 Zend/zend_compile.h
@@ -597,6 +597,8 @@ int zendlex(znode *zendlval CLS_DC);
#define ZEND_MEMBER_FUNC_CALL 1<<0
#define ZEND_CTOR_CALL 1<<1
+#define ZEND_ARG_SEND_BY_REF (1<<0)
+#define ZEND_ARG_COMPILE_TIME_BOUND (1<<1)
#define AI_USE_PTR(ai) \
if ((ai).ptr_ptr) { \
View
60 Zend/zend_execute.c
@@ -1656,37 +1656,55 @@ binary_assign_op_addr: {
zend_ptr_stack_push(&EG(argument_stack), valptr);
}
NEXT_OPCODE();
- case ZEND_SEND_VAR:
case ZEND_SEND_VAR_NO_REF:
- if (opline->extended_value==ZEND_DO_FCALL_BY_NAME
- && ARG_SHOULD_BE_SENT_BY_REF(opline->op2.u.opline_num, fbc, fbc->common.arg_types)) {
- if (opline->opcode==ZEND_SEND_VAR_NO_REF) {
- zend_error(E_ERROR, "Only variables can be passed by reference");
+ if (opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) { /* Had function_ptr at compile_time */
+ if (!(opline->extended_value & ZEND_ARG_SEND_BY_REF)) {
+ goto send_by_var;
}
- goto send_by_ref;
+ } else if (!ARG_SHOULD_BE_SENT_BY_REF(opline->op2.u.opline_num, fbc, fbc->common.arg_types)) {
+ goto send_by_var;
}
{
zval *varptr;
varptr = get_zval_ptr(&opline->op1, Ts, &EG(free_op1), BP_VAR_R);
- if (varptr == &EG(uninitialized_zval)) {
- ALLOC_ZVAL(varptr);
- INIT_ZVAL(*varptr);
- varptr->refcount = 0;
- } else if (PZVAL_IS_REF(varptr)) {
- zval *original_var = varptr;
-
- ALLOC_ZVAL(varptr);
- *varptr = *original_var;
- varptr->is_ref = 0;
- varptr->refcount = 0;
- zval_copy_ctor(varptr);
+ if (varptr != &EG(uninitialized_zval) && (PZVAL_IS_REF(varptr) || varptr->refcount == 1)) {
+ varptr->is_ref = 1;
+ varptr->refcount++;
+ zend_ptr_stack_push(&EG(argument_stack), varptr);
+ NEXT_OPCODE();
}
- varptr->refcount++;
- zend_ptr_stack_push(&EG(argument_stack), varptr);
- FREE_OP(&opline->op1, EG(free_op1)); /* for string offsets */
+ zend_error(E_ERROR, "Only variables can be passed by reference");
}
NEXT_OPCODE();
+ case ZEND_SEND_VAR:
+ if ((opline->extended_value == ZEND_DO_FCALL_BY_NAME)
+ && ARG_SHOULD_BE_SENT_BY_REF(opline->op2.u.opline_num, fbc, fbc->common.arg_types)) {
+ goto send_by_ref;
+ }
+send_by_var:
+ {
+ zval *varptr;
+ varptr = get_zval_ptr(&opline->op1, Ts, &EG(free_op1), BP_VAR_R);
+
+ if (varptr == &EG(uninitialized_zval)) {
+ ALLOC_ZVAL(varptr);
+ INIT_ZVAL(*varptr);
+ varptr->refcount = 0;
+ } else if (PZVAL_IS_REF(varptr)) {
+ zval *original_var = varptr;
+
+ ALLOC_ZVAL(varptr);
+ *varptr = *original_var;
+ varptr->is_ref = 0;
+ varptr->refcount = 0;
+ zval_copy_ctor(varptr);
+ }
+ varptr->refcount++;
+ zend_ptr_stack_push(&EG(argument_stack), varptr);
+ FREE_OP(&opline->op1, EG(free_op1)); /* for string offsets */
+ }
+ NEXT_OPCODE();
send_by_ref:
case ZEND_SEND_REF: {
zval **varptr_ptr;

0 comments on commit 8d90825

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