]> gitweb.factorcode.org Git - factor.git/blobdiff - vm/callstack.hpp
webapps.wiki: adding search bar
[factor.git] / vm / callstack.hpp
old mode 100755 (executable)
new mode 100644 (file)
index 8104beb..ebb19f2
-namespace factor
-{
+namespace factor {
 
-inline static cell callstack_object_size(cell size)
-{
-       return sizeof(callstack) + size;
+inline static cell callstack_object_size(cell size) {
+  return sizeof(callstack) + 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, typename Fixup>
-inline void factor_vm::iterate_callstack_object_reversed(callstack *stack_,
-       Iterator &iterator, Fixup &fixup)
-{
-       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);
-
-               void *fixed_addr = Fixup::translated_code_block_map
-                       ? (void*)fixup.translate_code((code_block*)addr)
-                       : addr;
-               code_block *owner = code->code_block_for_address((cell)fixed_addr);
-               cell frame_size = owner->stack_frame_size_for_address((cell)fixed_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;
-               void *fixed_entry_point =
-                       (void*)fixup.translate_code((code_block*)frame->entry_point);
-               FACTOR_ASSERT(owner->entry_point() == fixed_entry_point);
-               FACTOR_ASSERT(frame_size == frame->size);
-#endif
-
-               iterator(frame_top, frame_size, owner, fixed_addr);
-               frame_offset += frame_size;
-       }
+// This is a little tricky. The iterator may allocate memory, so we
+// keep the callstack in a GC root and use relative offsets
+// Allocates memory
+template <typename Iterator, typename Fixup>
+inline void factor_vm::iterate_callstack_object(callstack* stack_,
+                                                Iterator& iterator,
+                                                Fixup& fixup) {
+  data_root<callstack> stack(stack_, this);
+  fixnum frame_length = untag_fixnum(stack->length);
+  fixnum frame_offset = 0;
+
+  while (frame_offset < frame_length) {
+    cell frame_top = stack->frame_top_at(frame_offset);
+    cell addr = *(cell*)frame_top;
+    cell fixed_addr = Fixup::translated_code_block_map
+                          ? (cell)fixup.translate_code((code_block*)addr)
+                          : addr;
+    code_block* owner = code->code_block_for_address(fixed_addr);
+
+    cell frame_size = owner->stack_frame_size_for_address(fixed_addr);
+
+    iterator(frame_top, frame_size, owner, fixed_addr);
+    frame_offset += frame_size;
+  }
+  FACTOR_ASSERT(frame_offset == frame_length);
 }
 
-template<typename Iterator>
-inline void factor_vm::iterate_callstack_object_reversed(callstack *stack_, Iterator &iterator)
-{
-       no_fixup none;
-       iterate_callstack_object_reversed(stack_, iterator, none);
+// Allocates memory
+template <typename Iterator>
+inline void factor_vm::iterate_callstack_object(callstack* stack,
+                                                Iterator& iterator) {
+  no_fixup none;
+  iterate_callstack_object(stack, iterator, none);
 }
 
-template<typename Iterator, typename Fixup>
-inline void factor_vm::iterate_callstack_reversed(context *ctx, Iterator &iterator, Fixup &fixup)
-{
-       if (ctx->callstack_top == ctx->callstack_bottom)
-               return;
-
-       char *frame_top = (char*)ctx->callstack_top;
-
-       while (frame_top < (char*)ctx->callstack_bottom)
-       {
-               void *addr = frame_return_address((void*)frame_top);
-               FACTOR_ASSERT(addr != 0);
-               void *fixed_addr = Fixup::translated_code_block_map
-                       ? (void*)fixup.translate_code((code_block*)addr)
-                       : addr;
-
-               code_block *owner = code->code_block_for_address((cell)fixed_addr);
-               code_block *fixed_owner = Fixup::translated_code_block_map
-                       ? owner
-                       : fixup.translate_code(owner);
-
-               cell frame_size = fixed_owner->stack_frame_size_for_address((cell)fixed_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;
-               void *fixed_entry_point = Fixup::translated_code_block_map
-                       ? (void*)fixup.translate_code((code_block*)frame->entry_point)
-                       : frame->entry_point;
-               FACTOR_ASSERT(owner->entry_point() == fixed_entry_point);
-               FACTOR_ASSERT(frame_size == frame->size);
-#endif
-               void *fixed_addr_for_iter = Fixup::translated_code_block_map
-                       ? fixed_addr
-                       : addr;
-
-               iterator(frame_top, frame_size, owner, fixed_addr_for_iter);
-               frame_top += frame_size;
-       }
+// Iterates the callstack from innermost to outermost
+// callframe. Allocates memory
+template <typename Iterator, typename Fixup>
+void factor_vm::iterate_callstack(context* ctx, Iterator& iterator,
+                                  Fixup& fixup) {
+
+  cell top = ctx->callstack_top;
+  cell bottom = ctx->callstack_bottom;
+  // When we are translating the code block maps, all callstacks must
+  // be empty.
+  FACTOR_ASSERT(!Fixup::translated_code_block_map || top == bottom);
+
+  while (top < bottom) {
+    cell addr = *(cell*)top;
+    FACTOR_ASSERT(addr != 0);
+
+    // Only the address is valid, if the code heap has been compacted,
+    // owner might not point to a real code block.
+    code_block* owner = code->code_block_for_address(addr);
+    code_block* fixed_owner = fixup.translate_code(owner);
+
+    cell delta = addr - (cell)owner - sizeof(code_block);
+    cell natural_frame_size = fixed_owner->stack_frame_size();
+    cell size = LEAF_FRAME_SIZE;
+    if (natural_frame_size > 0 && delta > 0)
+      size = natural_frame_size;
+
+    iterator(top, size, owner, addr);
+    top += size;
+  }
+  FACTOR_ASSERT(top == bottom);
 }
 
-template<typename Iterator>
-inline void factor_vm::iterate_callstack_reversed(context *ctx, Iterator &iterator)
-{
-       no_fixup none;
-       iterate_callstack_reversed(ctx, iterator, none);
+// Allocates memory
+template <typename Iterator>
+inline void factor_vm::iterate_callstack(context* ctx, Iterator& iterator) {
+  no_fixup none;
+  iterate_callstack(ctx, iterator, none);
 }
 
-
 }