From 7d260b7099469778113d458fccd765b7e5218a80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Grubbstr=C3=B6m=20=28Grubba=29?= <grubba@grubba.org> Date: Mon, 23 Mar 2015 20:56:54 +0100 Subject: [PATCH] Runtime: Fixed over optimization in F_APPEND_ARRAY. Setters expect to be called when the corresponding variable is modified... This behaviour caused Roxen's test-suite to fail due to change triggers not being called. --- src/array.c | 16 +++++++++++----- src/testsuite.in | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 5 deletions(-) diff --git a/src/array.c b/src/array.c index 067d5658eb..70da9c0257 100644 --- a/src/array.c +++ b/src/array.c @@ -448,6 +448,7 @@ void o_append_array(INT32 args) { struct svalue *lval = Pike_sp - args; struct svalue *val = lval + 2; + int lval_type; #ifdef PIKE_DEBUG if (args < 3) { Pike_fatal("Too few arguments to o_append_array(): %d\n", args); @@ -455,7 +456,7 @@ void o_append_array(INT32 args) #endif args -= 3; /* Note: val should always be a zero here! */ - lvalue_to_svalue_no_free(val, lval); + lval_type = lvalue_to_svalue_no_free(val, lval); if (TYPEOF(*val) == T_ARRAY) { struct svalue tmp; @@ -464,10 +465,15 @@ void o_append_array(INT32 args) element and do not do the assign. This can be done because the lvalue already has the array as it's value. */ - if( v->refs == 2 ) - { - if( v->real_item+v->malloced_size >= v->item+v->size+args ) - { + if( (v->refs == 2) && (lval_type != PIKE_T_GET_SET) ) { + if ((TYPEOF(*lval) == T_OBJECT) && + lval->u.object->prog && + ((FIND_LFUN(lval->u.object->prog, LFUN_ASSIGN_INDEX) >= 0) || + (FIND_LFUN(lval->u.object->prog, LFUN_ASSIGN_ARROW) >= 0))) { + /* There's a function controlling assignments in this object, + * so we can't alter the array in place. + */ + } else if( v->real_item+v->malloced_size >= v->item+v->size+args ) { struct svalue *from = val+1; int i; for( i = 0; i<args; i++,from++ ) diff --git a/src/testsuite.in b/src/testsuite.in index 91009427aa..e8ac2a8774 100644 --- a/src/testsuite.in +++ b/src/testsuite.in @@ -4112,6 +4112,52 @@ test_any([[ return has_index(a->_modified, "foo"); ]], 1) +test_any([[ + // Since the addition of F_APPEND_ARRAY the setter is not being + // called anymore. Instead, the array _data is modified in place. + class A(array _data) { + int counter; + + void `foo=(mixed v) { + counter += !!v; + _data = v; + } + + mixed `foo() { + return _data; + } + }; + + object a = A(({})); + + for (int i = 0; i < 6; i++) { + a->foo += ({ i }); + } + + return a->counter; +]], 6) + +test_any([[ + // Since the addition of F_APPEND_ARRAY the setter is not being + // called anymore. Instead, the array _data is modified in place. + class A(array foo) { + int counter; + + mixed `->=(string sym, mixed v) { + counter += !!v; + return ::`->=(sym, v); + } + }; + + object a = A(({})); + + for (int i = 0; i < 6; i++) { + a->foo += ({ i }); + } + + return a->counter; +]], 6) + test_any([[ // Triggered fatal since object_equal_p did not handle // getter/setter identifier correctly -- GitLab