diff options
Diffstat (limited to 'interpret.h')
-rw-r--r-- | interpret.h | 68 |
1 files changed, 57 insertions, 11 deletions
diff --git a/interpret.h b/interpret.h index 74f56c73..2901f60e 100644 --- a/interpret.h +++ b/interpret.h @@ -23,7 +23,19 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ - +#define UNFIELD(l, r) \ +{ \ + /* if was a field, turn it into a var */ \ + if ((r->flags & FIELD) == 0) { \ + l = r; \ + } else if (r->valref == 1) { \ + r->flags &= ~FIELD; \ + l = r; \ + } else { \ + l = dupnode(r); \ + DEREF(r); \ + } \ +} int r_interpret(INSTRUCTION *code) { @@ -340,7 +352,16 @@ uninitialized_scalar: lhs = r_get_field(t1, (Func_ptr *) 0, true); decr_sp(); DEREF(t1); - r = dupnode(*lhs); /* can't use UPREF here */ + if (do_old_mem) { + r = dupnode(*lhs); + } else { + /* only for $0, up ref count */ + if (*lhs == fields_arr[0]) { + r = *lhs; + UPREF(r); + } else + r = dupnode(*lhs); + } PUSH(r); break; @@ -631,7 +652,12 @@ mod: } unref(*lhs); - *lhs = POP_SCALAR(); + if (do_old_mem) { + *lhs = POP_SCALAR(); + } else { + r = POP_SCALAR(); + UNFIELD(*lhs, r); + } /* execute post-assignment routine if any */ if (t1->astore != NULL) @@ -649,11 +675,21 @@ mod: lhs = get_lhs(pc->memory, false); unref(*lhs); r = pc->initval; /* constant initializer */ - if (r == NULL) - *lhs = POP_SCALAR(); - else { - UPREF(r); - *lhs = r; + if (do_old_mem) { + if (r == NULL) + *lhs = POP_SCALAR(); + else { + UPREF(r); + *lhs = r; + } + } else { + if (r != NULL) { + UPREF(r); + *lhs = r; + } else { + r = POP_SCALAR(); + UNFIELD(*lhs, r); + } } break; @@ -669,7 +705,12 @@ mod: decr_sp(); DEREF(t1); unref(*lhs); - *lhs = POP_SCALAR(); + if (do_old_mem) { + *lhs = POP_SCALAR(); + } else { + r = POP_SCALAR(); + UNFIELD(*lhs, r); + } assert(assign != NULL); assign(); } @@ -723,8 +764,13 @@ mod: lhs = POP_ADDRESS(); r = TOP_SCALAR(); unref(*lhs); - *lhs = r; - UPREF(r); + if (do_old_mem) { + *lhs = r; + UPREF(r); + } else { + UPREF(r); + UNFIELD(*lhs, r); + } REPLACE(r); break; |