Exemplo n.º 1
0
/* We ignore the topmost frame, the one calling 'callstack',
so that set-callstack doesn't get stuck in an infinite loop.

This means that if 'callstack' is called in tail position, we
will have popped a necessary frame... however this word is only
called by continuation implementation, and user code shouldn't
be calling it at all, so we leave it as it is for now. */
stack_frame *capture_start()
{
	stack_frame *frame = stack_chain->callstack_bottom - 1;
	while(frame >= stack_chain->callstack_top
		&& frame_successor(frame) >= stack_chain->callstack_top)
	{
		frame = frame_successor(frame);
	}
	return frame + 1;
}
Exemplo n.º 2
0
stack_frame *innermost_stack_frame(callstack *stack)
{
	stack_frame *top = stack->top();
	stack_frame *bottom = stack->bottom();
	stack_frame *frame = bottom - 1;

	while(frame >= top && frame_successor(frame) >= top)
		frame = frame_successor(frame);

	return frame;
}
Exemplo n.º 3
0
/* We ignore the two topmost frames, the 'callstack' primitive
frame itself, and the frame calling the 'callstack' primitive,
so that set-callstack doesn't get stuck in an infinite loop.

This means that if 'callstack' is called in tail position, we
will have popped a necessary frame... however this word is only
called by continuation implementation, and user code shouldn't
be calling it at all, so we leave it as it is for now. */
stack_frame *factor_vm::second_from_top_stack_frame(context *ctx)
{
	stack_frame *frame = ctx->callstack_bottom - 1;
	while(frame >= ctx->callstack_top
		&& frame_successor(frame) >= ctx->callstack_top
		&& frame_successor(frame_successor(frame)) >= ctx->callstack_top)
	{
		frame = frame_successor(frame);
	}
	return frame + 1;
}
Exemplo n.º 4
0
stack_frame *fix_callstack_top(stack_frame *top, stack_frame *bottom)
{
	stack_frame *frame = bottom - 1;

	while(frame >= top)
		frame = frame_successor(frame);

	return frame + 1;
}
Exemplo n.º 5
0
template<typename Iterator> void factor_vm::iterate_callstack(context *ctx, Iterator &iterator)
{
	stack_frame *frame = ctx->callstack_bottom - 1;

	while(frame >= ctx->callstack_top)
	{
		iterator(frame);
		frame = frame_successor(frame);
	}
}
Exemplo n.º 6
0
// callstack.hpp
template<typename TYPE> void factorvm::iterate_callstack(cell top, cell bottom, TYPE &iterator)
{
	stack_frame *frame = (stack_frame *)bottom - 1;

	while((cell)frame >= top)
	{
		iterator(frame,this);
		frame = frame_successor(frame);
	}
}
Exemplo n.º 7
0
template<typename T> void iterate_callstack(cell top, cell bottom, T &iterator)
{
	stack_frame *frame = (stack_frame *)bottom - 1;

	while((cell)frame >= top)
	{
		iterator(frame);
		frame = frame_successor(frame);
	}
}
Exemplo n.º 8
0
/* If 'stack' points into the middle of the frame, find the nearest valid stack
pointer where we can resume execution and hope to capture the call trace without
crashing. Also, make sure we have at least 'stack_reserved' bytes available so
that we don't run out of callstack space while handling the error. */
stack_frame *factor_vm::fix_callstack_top(stack_frame *stack)
{
	stack_frame *frame = ctx->callstack_bottom - 1;

	while(frame >= stack
		&& frame >= ctx->callstack_top
		&& (cell)frame >= ctx->callstack_seg->start + stack_reserved)
		frame = frame_successor(frame);

	return frame + 1;
}
Exemplo n.º 9
0
void factor_vm::dispatch_signal_handler(cell *sp, cell *pc, cell handler)
{
	if (!code->seg->in_segment_p(*pc) || *sp < ctx->callstack_seg->start + stack_reserved)
	{
		/* Fault came from foreign code or a callstack overflow, or we don't
		have enough callstack room to try the resumable handler. Cut the
		callstack down to the shallowest Factor stack frame that leaves room for
		the signal handler to do its thing, and launch the handler without going
		through the resumable subprimitive. */
		signal_resumable = false;
		stack_frame *frame = ctx->callstack_bottom - 1;

		while((cell)frame >= *sp
			&& frame >= ctx->callstack_top
			&& (cell)frame >= ctx->callstack_seg->start + stack_reserved)
		{
			frame = frame_successor(frame);
		}

		cell newsp = (cell)(frame+1);
		*sp = newsp;
		ctx->callstack_top = (stack_frame*)newsp;
		*pc = handler;
	} else {
		signal_resumable = true;
		// Fault came from Factor, and we've got a good callstack. Route the signal
		// handler through the resumable signal handler subprimitive.
		cell offset = *sp % 16;

		signal_handler_addr = handler;
		tagged<word> handler_word = tagged<word>(special_objects[SIGNAL_HANDLER_WORD]);

		/* True stack frames are always 16-byte aligned. Leaf procedures
		that don't create a stack frame will be out of alignment by sizeof(cell)
		bytes. */
		/* On architectures with a link register we would have to check for leafness
		by matching the PC to a word. We should also use FRAME_RETURN_ADDRESS instead
		of assuming the stack pointer is the right place to put the resume address. */
		if (offset == 0)
		{
			cell newsp = *sp - sizeof(cell);
			*sp = newsp;
			*(cell*)newsp = *pc;
		}
		else if (offset == 16 - sizeof(cell))
		{
			// Make a fake frame for the leaf procedure
			code_block *leaf_block = code->code_block_for_address(*pc);
			assert(leaf_block != NULL);

			cell newsp = *sp - 32;
			*(cell*)(newsp + 32 -   sizeof(cell)) = 32;
			*(cell*)(newsp + 32 - 2*sizeof(cell)) = (cell)leaf_block->entry_point();
			*(cell*) newsp                        = *pc;
			*sp = newsp;
			handler_word = tagged<word>(special_objects[LEAF_SIGNAL_HANDLER_WORD]);
		}
		else
			assert(false);

		*pc = (cell)handler_word->code->entry_point();
	}
}