summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZeev Suraski <zeev@php.net>2003-07-31 09:06:11 +0000
committerZeev Suraski <zeev@php.net>2003-07-31 09:06:11 +0000
commitaccd6b623b417fe24ea94278620dd2b0f9b18cd8 (patch)
tree61f0173b53d55d80e7bdf45588c2738940cfbf0c
parentd95a6916de495623ac91214764450add35609a3a (diff)
downloadphp-git-accd6b623b417fe24ea94278620dd2b0f9b18cd8.tar.gz
Finish the array overloading patch
-rw-r--r--Zend/zend_compile.c5
-rw-r--r--Zend/zend_execute.c42
2 files changed, 39 insertions, 8 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 2158f938db..605e4e491d 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -247,13 +247,18 @@ void zend_do_binary_assign_op(zend_uchar op, znode *result, znode *op1, znode *o
*result = last_op->result;
break;
case ZEND_FETCH_DIM_RW:
+#if 1
last_op->opcode = op;
last_op->extended_value = ZEND_ASSIGN_DIM;
zend_do_op_data(opline, op2 TSRMLS_CC);
+ opline->op2.u.var = get_temporary_variable(CG(active_op_array));
+ opline->op2.u.EA.type = 0;
+ opline->op2.op_type = IS_VAR;
SET_UNUSED(opline->result);
*result = last_op->result;
break;
+#endif
default:
opline->opcode = op;
opline->op1 = *op1;
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 6179a7fe25..7b0a3ae54a 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -1519,24 +1519,46 @@ static inline int zend_binary_assign_op_obj_helper(int (*binary_op)(zval *result
}
-inline int zend_binary_assign_op_helper(void *binary_op_arg, ZEND_OPCODE_HANDLER_ARGS)
+inline int zend_binary_assign_op_helper(int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC), ZEND_OPCODE_HANDLER_ARGS)
{
zval **var_ptr;
- int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC);
+ zval *value;
+ zend_bool increment_opline = 0;
switch (EX(opline)->extended_value) {
case ZEND_ASSIGN_OBJ:
- case ZEND_ASSIGN_DIM:
- return zend_binary_assign_op_obj_helper(binary_op_arg, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ return zend_binary_assign_op_obj_helper(binary_op, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
+ break;
+ case ZEND_ASSIGN_DIM: {
+ zend_op *op_data = EX(opline)+1;
+ zval **object_ptr = get_obj_zval_ptr_ptr(&EX(opline)->op1, EX(Ts), BP_VAR_W TSRMLS_CC);
+
+ if ((*object_ptr)->type == IS_OBJECT) {
+ zend_assign_to_object(&EX(opline)->result, object_ptr, &EX(opline)->op2, &op_data->op1, EX(Ts), ZEND_ASSIGN_DIM TSRMLS_CC);
+ EX(opline)++;
+ NEXT_OPCODE();
+ } else {
+ zend_op *data_opline = EX(opline)+1;
+
+ (*object_ptr)->refcount++; /* undo the effect of get_obj_zval_ptr_ptr() */
+ zend_fetch_dimension_address(&data_opline->op2, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), BP_VAR_RW TSRMLS_CC);
+
+ value = get_zval_ptr(&data_opline->op1, EX(Ts), &EG(free_op1), BP_VAR_R);
+ var_ptr = get_zval_ptr_ptr(&data_opline->op2, EX(Ts), BP_VAR_RW);
+ EG(free_op2) = 0;
+ increment_opline = 1;
+// zend_assign_to_variable(&EX(opline)->result, &data_opline->op2, &data_opline->op1, value, (EG(free_op1)?IS_TMP_VAR:EX(opline)->op1.op_type), EX(Ts) TSRMLS_CC);
+ }
+ }
break;
default:
+ value = get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R);
+ var_ptr = get_zval_ptr_ptr(&EX(opline)->op1, EX(Ts), BP_VAR_RW);
+ EG(free_op1) = 0;
/* do nothing */
break;
}
- var_ptr = get_zval_ptr_ptr(&EX(opline)->op1, EX(Ts), BP_VAR_RW);
- binary_op = binary_op_arg;
-
if (!var_ptr) {
zend_error(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
}
@@ -1550,12 +1572,16 @@ inline int zend_binary_assign_op_helper(void *binary_op_arg, ZEND_OPCODE_HANDLER
SEPARATE_ZVAL_IF_NOT_REF(var_ptr);
- binary_op(*var_ptr, *var_ptr, get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R) TSRMLS_CC);
+ binary_op(*var_ptr, *var_ptr, value TSRMLS_CC);
EX_T(EX(opline)->result.u.var).var.ptr_ptr = var_ptr;
SELECTIVE_PZVAL_LOCK(*var_ptr, &EX(opline)->result);
+ FREE_OP(Ex(Ts), &EX(opline)->op1, EG(free_op1));
FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2));
AI_USE_PTR(EX_T(EX(opline)->result.u.var).var);
+ if (increment_opline) {
+ EX(opline)++;
+ }
NEXT_OPCODE();
}