]> gitweb.factorcode.org Git - factor.git/commitdiff
vm: reversed callstack iteration
authorJoe Groff <arcata@gmail.com>
Fri, 2 Dec 2011 17:11:34 +0000 (09:11 -0800)
committerJoe Groff <arcata@gmail.com>
Wed, 14 Dec 2011 17:56:47 +0000 (09:56 -0800)
vm/callstack.cpp
vm/callstack.hpp
vm/code_blocks.cpp
vm/code_blocks.hpp
vm/cpu-x86.hpp
vm/debug.cpp
vm/gc.cpp
vm/layouts.hpp
vm/slot_visitor.hpp
vm/vm.hpp

index 9f2dc01cfe8b1f63095e27a515e9225ac2116144..b766be0399d1fb8d98c794d6c27a7acd90b0ca1f 100755 (executable)
@@ -108,25 +108,7 @@ void factor_vm::set_frame_offset(stack_frame *frame, cell offset)
 
 cell factor_vm::frame_scan(stack_frame *frame)
 {
-       switch(frame_type(frame))
-       {
-       case code_block_unoptimized:
-               {
-                       tagged<object> obj(frame_executing(frame));
-                       if(obj.type_p(WORD_TYPE))
-                               obj = obj.as<word>()->def;
-
-                       if(obj.type_p(QUOTATION_TYPE))
-                               return tag_fixnum(quot_code_offset_to_scan(obj.value(),frame_offset(frame)));
-                       else
-                               return false_object;
-               }
-       case code_block_optimized:
-               return false_object;
-       default:
-               critical_error("Bad frame type",frame_type(frame));
-               return false_object;
-       }
+       return frame_code(frame)->scan(this, FRAME_RETURN_ADDRESS(frame,this));
 }
 
 struct stack_frame_accumulator {
index 2c70936f8814dd5541705add90259c06a2df4146..7d167e9fe80f38e3ac69b0a6c73f775194d7dff4 100755 (executable)
@@ -8,6 +8,34 @@ inline static cell callstack_object_size(cell size)
 
 /* This is a little tricky. The iterator may allocate memory, so we
 keep the callstack in a GC root and use relative offsets */
+template<typename Iterator>
+void factor_vm::iterate_callstack_object_reversed(callstack *stack_, Iterator &iterator)
+{
+       data_root<callstack> stack(stack_,this);
+       fixnum frame_length = factor::untag_fixnum(stack->length);
+       fixnum frame_offset = 0;
+
+       while(frame_offset < frame_length)
+       {
+               void *frame_top = stack->frame_top_at(frame_offset);
+               void *addr = frame_return_address(frame_top);
+
+               code_block *owner = code->code_block_for_address(addr);
+               cell frame_size = owner->stack_frame_size_for_address(addr);
+
+#ifdef FACTOR_DEBUG
+               // check our derived owner and frame size against the ones stored in the frame
+               // by the function prolog
+               stack_frame *frame = (stack_frame*)((char*)frame_top + frame_size) - 1;
+               FACTOR_ASSERT(owner->entry_point() == frame->entry_point);
+               FACTOR_ASSERT(frame_size == frame->size);
+#endif
+
+               iterator(owner, addr);
+               frame_offset += frame_size;
+       }
+}
+
 template<typename Iterator> void factor_vm::iterate_callstack_object(callstack *stack_, Iterator &iterator)
 {
        data_root<callstack> stack(stack_,this);
@@ -21,56 +49,37 @@ template<typename Iterator> void factor_vm::iterate_callstack_object(callstack *
        }
 }
 
-inline void factor_vm::verify_callstack(context *ctx, cell pc)
+template<typename Iterator>
+void factor_vm::iterate_callstack_reversed(context *ctx, Iterator &iterator)
 {
-       if (pc == 0)
-       {
-               std::cout << "null return address" << std::endl;
+       if (ctx->callstack_top == ctx->callstack_bottom)
                return;
-       }
 
-       unsigned char *frame_top = (unsigned char*)ctx->callstack_top;
-       cell addr = pc;
+       char *frame_top = (char*)ctx->callstack_top;
 
-       while(frame_top < (unsigned char*)ctx->callstack_bottom)
+       while (frame_top < (char*)ctx->callstack_bottom)
        {
-               std::cout << std::endl;
-               std::cout << "address " << (void*)addr << std::endl;
-               code_block *owner = code->code_block_for_address(addr);
-               std::cout << "owner " << (void*)owner->entry_point() << " ";
-               print_obj(owner->owner);
-               std::cout << std::endl;
-               cell frame_size = owner->stack_frame_size_for_address(addr);
-               std::cout << "frame size " << (void*)frame_size << std::endl;
+               void *addr = frame_return_address((void*)frame_top);
+               FACTOR_ASSERT(addr != 0);
+
+               code_block *owner = code->code_block_for_address((cell)addr);
+               cell frame_size = owner->stack_frame_size_for_address((cell)addr);
+
+#ifdef FACTOR_DEBUG
+               // check our derived owner and frame size against the ones stored in the frame
+               // by the function prolog
+               stack_frame *frame = (stack_frame*)(frame_top + frame_size) - 1;
+               FACTOR_ASSERT(owner->entry_point() == frame->entry_point);
+               FACTOR_ASSERT(frame_size == frame->size);
+#endif
+
                frame_top += frame_size;
-               stack_frame *frame = (stack_frame*)frame_top - 1;
-               if (owner->entry_point() != frame->entry_point)
-               {
-                       std::cout << "unexpected frame owner " << (void*)frame->entry_point << " ";
-                       print_obj(((code_block*)frame->entry_point - 1)->owner);
-                       std::cout << std::endl;
-               }
-               if (frame_size != frame->size)
-                       std::cout << "unexpected frame size " << frame->size << std::endl;
-               // XXX x86
-               addr = *(cell*)frame_top;
+               iterator(owner, addr);
        }
 }
 
-inline void factor_vm::verify_callstack(context *ctx)
-{
-       /*
-       std::cout << std::endl << std::endl
-               << "callstack " << (void*)ctx->callstack_top
-               << " to " << (void*)ctx->callstack_bottom << std::endl;
-
-       // XXX x86-centric
-       cell return_address = *((cell*)ctx->callstack_top);
-       verify_callstack(ctx, return_address);
-       */
-}
-
-template<typename Iterator> void factor_vm::iterate_callstack(context *ctx, Iterator &iterator)
+template<typename Iterator>
+void factor_vm::iterate_callstack(context *ctx, Iterator &iterator)
 {
        stack_frame *frame = ctx->callstack_bottom - 1;
 
index 9610205797fac44922b7476fc7f0052249a991fc..c2f572bdbad0534833d00806c52cf8c994e78aac 100755 (executable)
@@ -3,6 +3,29 @@
 namespace factor
 {
 
+cell code_block::scan(factor_vm *vm, void *addr) const
+{
+       switch(type())
+       {
+       case code_block_unoptimized:
+               {
+                       tagged<object> obj(owner);
+                       if(obj.type_p(WORD_TYPE))
+                               obj = obj.as<word>()->def;
+
+                       if(obj.type_p(QUOTATION_TYPE))
+                               return tag_fixnum(vm->quot_code_offset_to_scan(obj.value(),offset(addr)));
+                       else
+                               return false_object;
+               }
+       case code_block_optimized:
+               return false_object;
+       default:
+               critical_error("Bad frame type",type());
+               return false_object;
+       }
+}
+
 cell factor_vm::compute_entry_point_address(cell obj)
 {
        switch(tagged<object>(obj).type())
index 34aeed787de0113a5f4c9f754219f459e49b77de..ed74c50de59d378a02d4d1c5c46a5f417aed93df 100644 (file)
@@ -121,6 +121,13 @@ struct code_block
                        }
                }
        }
+
+       cell offset(void *addr) const
+       {
+               return (char*)addr - (char*)entry_point();
+       }
+
+       cell scan(factor_vm *vm, void *addr) const;
 };
 
 VM_C_API void undefined_symbol(void);
index 8cda442889cf7932dbd304ba2bcf24ffa631749e..542d3a8c088c7f487ae1fafd60ba1ff397ed5ce9 100755 (executable)
@@ -3,6 +3,16 @@ namespace factor
 
 #define FRAME_RETURN_ADDRESS(frame,vm) *(void **)(vm->frame_successor(frame) + 1)
 
+inline static void* frame_return_address(void *frame_top)
+{
+       return *(void**)frame_top;
+}
+
+inline static void set_frame_return_address(void *frame_top, cell return_address)
+{
+       *(cell*)frame_top = return_address;
+}
+
 #define CALLSTACK_BOTTOM(ctx) (stack_frame *)(ctx->callstack_seg->end - sizeof(cell) * 5)
 
 inline static void flush_icache(cell start, cell len) {}
index 6d363a84cc76760676fdde13c31028ce3520a6e5..204dcf365ff49dff573fe1bc7f7ac04154c7a118 100755 (executable)
@@ -220,23 +220,23 @@ struct stack_frame_printer {
        factor_vm *parent;
 
        explicit stack_frame_printer(factor_vm *parent_) : parent(parent_) {}
-       void operator()(stack_frame *frame)
+       void operator()(code_block *owner, void *addr)
        {
-               std::cout << "frame: " << std::hex << (cell)frame << std::dec << std::endl;
+               std::cout << std::endl;
                std::cout << "executing: ";
-               parent->print_obj(parent->frame_executing(frame));
+               parent->print_obj(owner->owner);
                std::cout << std::endl;
                std::cout << "scan: ";
-               parent->print_obj(parent->frame_scan(frame));
+               parent->print_obj(owner->scan(parent, addr));
                std::cout << std::endl;
                std::cout << "word/quot addr: ";
-               std::cout << std::hex << (cell)parent->frame_executing(frame) << std::dec;
+               std::cout << std::hex << (cell)owner->owner << std::dec;
                std::cout << std::endl;
                std::cout << "word/quot xt: ";
-               std::cout << std::hex << (cell)frame->entry_point << std::dec;
+               std::cout << std::hex << (cell)owner->entry_point() << std::dec;
                std::cout << std::endl;
                std::cout << "return address: ";
-               std::cout << std::hex << (cell)FRAME_RETURN_ADDRESS(frame,parent) << std::dec;
+               std::cout << std::hex << (cell)addr << std::dec;
                std::cout << std::endl;
        }
 };
@@ -247,8 +247,7 @@ void factor_vm::print_callstack()
        if (ctx)
        {
                stack_frame_printer printer(this);
-               verify_callstack(ctx);
-               iterate_callstack(ctx,printer);
+               iterate_callstack_reversed(ctx,printer);
        }
        else
                std::cout << "*** Context not initialized" << std::endl;
index 0a9dee2e4363c43ad0ba4a7e07ee3553d626aa69..177bb970afa91fad80393cc668fa71b13236187a 100755 (executable)
--- a/vm/gc.cpp
+++ b/vm/gc.cpp
@@ -257,7 +257,6 @@ void factor_vm::scrub_context(context *ctx)
 {
        call_frame_scrubber scrubber(this,ctx);
        iterate_callstack(ctx,scrubber);
-       verify_callstack(ctx);
 }
 
 void factor_vm::scrub_contexts()
index 9c6e2e7e3b7842762f3c3353a1236a69992662fd..d6c11a611d931e59b518ce8cccbabcdb41bd16f4 100644 (file)
@@ -366,6 +366,11 @@ struct callstack : public object {
                return (stack_frame *)((char *)(this + 1) + offset);
        }
 
+       void *frame_top_at(cell offset) const
+       {
+               return (void *)((char *)(this + 1) + offset);
+       }
+
        stack_frame *top() const { return (stack_frame *)(this + 1); }
        stack_frame *bottom() const { return (stack_frame *)((cell)(this + 1) + untag_fixnum(length)); }
 };
index 5c0b3367f394fea7e0a74f30cb546f1b373ab395..5e8cbe10d055d1356b3c9a9a9530738627a29629 100755 (executable)
@@ -378,7 +378,6 @@ template<typename Fixup>
 void slot_visitor<Fixup>::visit_callstack(context *ctx)
 {
        call_frame_slot_visitor<Fixup> call_frame_visitor(parent,this);
-       parent->verify_callstack(ctx);
        parent->iterate_callstack(ctx,call_frame_visitor);
 }
 
index 54519d4d9ad66d04575abd12d3cb04736ac76b2f..968d2d8dd4dc47b19b4d7db9b889ef798dd1be18 100755 (executable)
--- a/vm/vm.hpp
+++ b/vm/vm.hpp
@@ -184,7 +184,6 @@ struct factor_vm
                std::set<context *>::const_iterator end = active_contexts.end();
                while(begin != end)
                {
-                       verify_callstack(*begin);
                        iterate_callstack(*begin++,iter);
                }
        }
@@ -623,6 +622,7 @@ struct factor_vm
 
        // callstack
        template<typename Iterator> void iterate_callstack_object(callstack *stack_, Iterator &iterator);
+       template<typename Iterator> void iterate_callstack_object_reversed(callstack *stack_, Iterator &iterator);
        void check_frame(stack_frame *frame);
        callstack *allot_callstack(cell size);
        stack_frame *second_from_top_stack_frame(context *ctx);
@@ -643,8 +643,7 @@ struct factor_vm
        void primitive_innermost_stack_frame_scan();
        void primitive_set_innermost_stack_frame_quot();
        void primitive_callstack_bounds();
-       void verify_callstack(context *ctx);
-       void verify_callstack(context *ctx, cell pc);
+       template<typename Iterator> void iterate_callstack_reversed(context *ctx, Iterator &iterator);
        template<typename Iterator> void iterate_callstack(context *ctx, Iterator &iterator);
 
        // cpu-*