From 610b276c861cd67522becc2484e18d7863dd84ce Mon Sep 17 00:00:00 2001 From: Slava Pestov Date: Wed, 20 May 2009 18:52:21 -0500 Subject: [PATCH] callstack>array primitive was not GC safe --- vm/callstack.cpp | 36 +++++++++++++++++------------------- vm/callstack.hpp | 14 ++++++++++++-- vm/layouts.hpp | 5 +++++ 3 files changed, 34 insertions(+), 21 deletions(-) diff --git a/vm/callstack.cpp b/vm/callstack.cpp index 608a5c39e5..38fb1e2b33 100755 --- a/vm/callstack.cpp +++ b/vm/callstack.cpp @@ -107,8 +107,9 @@ stack_frame *frame_successor(stack_frame *frame) /* Allocates memory */ cell frame_scan(stack_frame *frame) { - if(frame_type(frame) == QUOTATION_TYPE) + switch(frame_type(frame)) { + case QUOTATION_TYPE: cell quot = frame_executing(frame); if(quot == F) return F; @@ -120,28 +121,27 @@ cell frame_scan(stack_frame *frame) return tag_fixnum(quot_code_offset_to_scan( quot,(cell)(return_addr - quot_xt))); } - } - else + case WORD_TYPE: + return F; + default: + critical_error("Bad frame type",frame_type(frame)); return F; + } } namespace { -struct stack_frame_counter { - cell count; - stack_frame_counter() : count(0) {} - void operator()(stack_frame *frame) { count += 2; } -}; - struct stack_frame_accumulator { - cell index; - gc_root frames; - stack_frame_accumulator(cell count) : index(0), frames(allot_array(count,F)) {} + growable_array frames; + void operator()(stack_frame *frame) { - set_array_nth(frames.untagged(),index++,frame_executing(frame)); - set_array_nth(frames.untagged(),index++,frame_scan(frame)); + gc_root executing(frame_executing(frame)); + gc_root scan(frame_scan(frame)); + + frames.add(executing.value()); + frames.add(scan.value()); } }; @@ -151,13 +151,11 @@ PRIMITIVE(callstack_to_array) { gc_root callstack(dpop()); - stack_frame_counter counter; - iterate_callstack_object(callstack.untagged(),counter); - - stack_frame_accumulator accum(counter.count); + stack_frame_accumulator accum; iterate_callstack_object(callstack.untagged(),accum); + accum.frames.trim(); - dpush(accum.frames.value()); + dpush(accum.frames.elements.value()); } stack_frame *innermost_stack_frame(callstack *stack) diff --git a/vm/callstack.hpp b/vm/callstack.hpp index d92e5f69e0..a3cc058e2b 100755 --- a/vm/callstack.hpp +++ b/vm/callstack.hpp @@ -33,9 +33,19 @@ template void iterate_callstack(cell top, cell bottom, T &iterator) } } -template void iterate_callstack_object(callstack *stack, T &iterator) +/* This is a little tricky. The iterator may allocate memory, so we +keep the callstack in a GC root and use relative offsets */ +template void iterate_callstack_object(callstack *stack_, T &iterator) { - iterate_callstack((cell)stack->top(),(cell)stack->bottom(),iterator); + gc_root stack(stack_); + fixnum frame_offset = untag_fixnum(stack->length) - sizeof(stack_frame); + + while(frame_offset >= 0) + { + stack_frame *frame = stack->frame_at(frame_offset); + frame_offset -= frame->size; + iterator(frame); + } } } diff --git a/vm/layouts.hpp b/vm/layouts.hpp index 3fe89cb558..7736143c50 100755 --- a/vm/layouts.hpp +++ b/vm/layouts.hpp @@ -309,6 +309,11 @@ struct callstack : public object { /* tagged */ cell length; + stack_frame *frame_at(cell offset) + { + return (stack_frame *)((char *)(this + 1) + offset); + } + stack_frame *top() { return (stack_frame *)(this + 1); } stack_frame *bottom() { return (stack_frame *)((cell)(this + 1) + untag_fixnum(length)); } }; -- 2.34.1