summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorYukihiro Matsumoto <[email protected]>2012-06-03 14:44:46 +0900
committerYukihiro Matsumoto <[email protected]>2012-06-03 14:44:46 +0900
commite88e30524ee878bf0bbf665c1a6bea11a60f07d4 (patch)
tree49b34187eef048835489a477c592bf81aa71ae41 /src
parent27c2416d201de968789917f2b6923d96ce1b953f (diff)
downloadmruby-e88e30524ee878bf0bbf665c1a6bea11a60f07d4.tar.gz
mruby-e88e30524ee878bf0bbf665c1a6bea11a60f07d4.zip
should have adjusted stack address kept in closures; close #222
Diffstat (limited to 'src')
-rw-r--r--src/vm.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/src/vm.c b/src/vm.c
index 865241a24..4f6deb877 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -42,11 +42,29 @@ stack_init(mrb_state *mrb)
}
static void
+envadjust(mrb_state *mrb, mrb_value *oldbase, mrb_value *newbase)
+{
+ mrb_callinfo *ci = mrb->cibase;
+
+ while (ci <= mrb->ci) {
+ struct REnv *e = ci->env;
+ if (e && e->cioff >= 0) {
+ int off = e->stack - oldbase;
+
+ e->stack = newbase + off;
+ }
+ ci++;
+ }
+}
+
+static void
stack_extend(mrb_state *mrb, int room, int keep)
{
int size, off;
if (mrb->stack + room >= mrb->stend) {
+ mrb_value *oldbase = mrb->stbase;
+
size = mrb->stend - mrb->stbase;
off = mrb->stack - mrb->stbase;
@@ -57,6 +75,7 @@ stack_extend(mrb_state *mrb, int room, int keep)
mrb->stbase = mrb_realloc(mrb, mrb->stbase, sizeof(mrb_value) * size);
mrb->stack = mrb->stbase + off;
mrb->stend = mrb->stbase + size;
+ envadjust(mrb, oldbase, mrb->stbase);
}
if (room > keep) {
memset(mrb->stack+keep, 0, sizeof(mrb_value) * (room-keep));