83 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			C++
		
	
	
			
		
		
	
	
			83 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			C++
		
	
	
namespace factor {
 | 
						|
 | 
						|
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 */
 | 
						|
/* 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);
 | 
						|
}
 | 
						|
 | 
						|
/* 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);
 | 
						|
}
 | 
						|
 | 
						|
/* 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);
 | 
						|
}
 | 
						|
 | 
						|
/* Allocates memory */
 | 
						|
template <typename Iterator>
 | 
						|
inline void factor_vm::iterate_callstack(context* ctx, Iterator& iterator) {
 | 
						|
  no_fixup none;
 | 
						|
  iterate_callstack(ctx, iterator, none);
 | 
						|
}
 | 
						|
 | 
						|
}
 |