guile/libguile/frames.c

491 lines
12 KiB
C
Raw Normal View History

/* Copyright 2001,2009-2015,2018
Free Software Foundation, Inc.
This file is part of Guile.
Guile is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Guile is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public
License along with Guile. If not, see
<https://www.gnu.org/licenses/>. */
2001-04-22 02:13:48 +00:00
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
2001-04-22 02:13:48 +00:00
#include <string.h>
#include "boolean.h"
#include "eval.h"
#include "extensions.h"
#include "gsubr.h"
#include "instructions.h"
#include "modules.h"
Devolve numbers.h from _scm.h. * libguile/_scm.h: Remove numbers.h. * libguile/array-handle.c: * libguile/array-map.c: * libguile/arrays.c: * libguile/backtrace.c: * libguile/bitvectors.c: * libguile/bytevectors.c: * libguile/chars.c: * libguile/continuations.c: * libguile/debug-malloc.c: * libguile/error.c: * libguile/eval.c: * libguile/filesys.c: * libguile/foreign-object.c: * libguile/foreign.c: * libguile/fports.c: * libguile/frames.c: * libguile/gc.c: * libguile/generalized-arrays.c: * libguile/gettext.c: * libguile/goops.c: * libguile/gsubr.c: * libguile/guardians.c: * libguile/hash.c: * libguile/hashtab.c: * libguile/hooks.c: * libguile/i18n.c: * libguile/instructions.c: * libguile/intrinsics.c: * libguile/ioext.c: * libguile/list.c: * libguile/memoize.c: * libguile/net_db.c: * libguile/options.c: * libguile/ports.c: * libguile/posix-w32.c: * libguile/posix.c: * libguile/procprop.c: * libguile/programs.c: * libguile/r6rs-ports.c: * libguile/random.c: * libguile/rdelim.c: * libguile/read.c: * libguile/regex-posix.c: * libguile/rw.c: * libguile/scmsigs.c: * libguile/simpos.c: * libguile/smob.c: * libguile/socket.c: * libguile/srcprop.c: * libguile/srfi-13.c: * libguile/srfi-14.c: * libguile/srfi-4.c: * libguile/stackchk.c: * libguile/stacks.c: * libguile/stime.c: * libguile/strings.c: * libguile/struct.c: * libguile/symbols.c: * libguile/threads.c: * libguile/throw.c: * libguile/vectors.c: * libguile/version.c: * libguile/vm.c: * libguile/vports.c: * libguile/weak-table.c: Add numbers.h.
2018-06-19 15:37:23 +02:00
#include "numbers.h"
#include "pairs.h"
#include "ports.h"
#include "symbols.h"
#include "threads.h"
#include "variable.h"
#include "version.h"
#include "vm.h"
2001-04-22 02:13:48 +00:00
#include "frames.h"
2001-04-22 02:13:48 +00:00
SCM
scm_c_make_frame (enum scm_vm_frame_kind kind, const struct scm_frame *frame)
2001-04-22 02:13:48 +00:00
{
replace frame implementation with VM frames * libguile/stacks.h: Rework so that a stack doesn't copy information out of VM frames, it just holds onto a VM frame, along with the stack id and length. VM frames are now the only representation of frames in Guile. (scm_t_info_frame, SCM_FRAME_N_SLOTS, SCM_FRAME_REF, SCM_FRAME_NUMBER) (SCM_FRAME_FLAGS, SCM_FRAME_SOURCE, SCM_FRAME_PROC, SCM_FRAME_ARGS) (SCM_FRAME_PREV, SCM_FRAME_NEXT) (SCM_FRAMEF_VOID, SCM_FRAMEF_REAL, SCM_FRAMEF_PROC) (SCM_FRAMEF_EVAL_ARGS, SCM_FRAMEF_OVERFLOW) (SCM_FRAME_VOID_P, SCM_FRAME_REAL_P, SCM_FRAME_PROC_P) (SCM_FRAME_EVAL_ARGS_P, SCM_FRAME_OVERFLOW_P): Remove these macros corresponding to the old frame implementation. (scm_frame_p scm_frame_source, scm_frame_procedure) (scm_frame_arguments): These definitions are now in frames.h. (scm_last_stack_frame): Remove declaration of previously-removed constructor. Probably should re-instate it though. (scm_frame_number, scm_frame_previous, scm_frame_next) (scm_frame_real_p, scm_frame_procedure_p, scm_frame_evaluating_args_p) (scm_frame_overflow_p) : Remove these procedures corresponding to the old stack implementation. * libguile/stacks.c: Update for new frames implementation. * libguile/frames.h: * libguile/frames.c: Rename functions operating on VM frames to have a scm_frame prefix, not scm_vm_frame -- because they really are the only frames we have. Rename corresponding Scheme functions too, from vm-frame-foo to frame-foo. * libguile/deprecated.h: Remove scm_stack and scm_info_frame data types. * libguile/vm.c (vm_dispatch_hook): Adapt to scm_c_make_frame name change. * module/system/vm/frame.scm: No need to export functions provided frames.c now, as we load those procedures into the default environment now. Rename functions, and remove a couple of outdated, unused functions. The bottom half of this file is still bitrotten, though. * libguile/backtrace.c: Rework to operate on the new frame representation. Also fix a bug displaying file names for compiled procedures. * libguile/init.c: Load the VM much earlier, just because we can. Also it allows us to have frames.[ch] loaded in time for stacks to be initialized, so that scm_frame_arguments can do the right thing.
2009-12-03 13:09:58 +01:00
struct scm_frame *p = scm_gc_malloc (sizeof (struct scm_frame),
"vmframe");
p->stack_holder = frame->stack_holder;
p->fp_offset = frame->fp_offset;
p->sp_offset = frame->sp_offset;
p->ip = frame->ip;
return scm_cell (scm_tc7_frame | (kind << 8), (scm_t_bits)p);
2001-04-22 02:13:48 +00:00
}
void
scm_i_frame_print (SCM frame, SCM port, scm_print_state *pstate)
{
scm_puts ("#<frame ", port);
scm_uintprint (SCM_UNPACK (frame), 16, port);
if (scm_module_system_booted_p)
{
SCM name = scm_frame_procedure_name (frame);
if (scm_is_true (name))
{
scm_putc (' ', port);
scm_write (name, port);
}
}
/* Don't write args, they can be ridiculously long. */
scm_puts (">", port);
}
VM stack grows downward Adapt VM stack to grow downward. This will make native compilation look more like the VM code, as we will be able to use native CALL instructions, taking proper advantage of the return address buffer. * libguile/continuations.c (scm_i_continuation_to_frame): Record offsets from stack top. * libguile/control.c (scm_i_prompt_pop_abort_args_x): Adapt for reversed order of arguments, and instead of relying on the abort to push on the number of arguments, make the caller save the stack depth, which allows us to compute the number of arguments ourselves. (reify_partial_continuation, scm_c_abort): Adapt to reversed stack order. * libguile/dynstack.c (scm_dynstack_wind_prompt): Since we wind the stack in a downward direction, subtract the reloc instead of adding it. * libguile/dynstack.h (SCM_F_DYNSTACK_PROMPT_ESCAPE_ONLY): Remove flag; instead rely on prompt-establishing code to save the stack depth. * libguile/eval.c (eval): Remove extraneous "volatile" declarations for variables that are not re-set between the setjmp and any longjmp. Adapt to save stack depth before instating the prompt. * libguile/foreign.c (scm_i_foreign_call): Adapt to receive arguments in reverse order. * libguile/frames.c (frame_stack_top, scm_i_frame_stack_top): Adapt to compute stack top instead of stack bottom. (scm_c_frame_closure): Adapt to stack growth change. (scm_frame_num_locals, scm_frame_local_ref, scm_frame_set_x): Use union data type to access stack. (RELOC): Reformat. (scm_c_frame_previous): Adapt to stack growth change. * libguile/frames.h: Adapt stack diagram to indicate that the stack grows up. (union scm_vm_stack_element): New data type used to access items on the stack. (SCM_FRAME_PREVIOUS_SP) (SCM_FRAME_RETURN_ADDRESS, SCM_FRAME_SET_RETURN_ADDRESS) (SCM_FRAME_DYNAMIC_LINK, SCM_FRAME_SET_DYNAMIC_LINK) (SCM_FRAME_LOCAL, SCM_FRAME_NUM_LOCALS): Adapt to stack representation change. (SCM_FRAME_SLOT): New helper. (SCM_VM_FRAME_FP, SCM_VM_FRAME_SP): Adapt to stack growth change. * libguile/stacks.c (scm_make_stack): Record offsets from top of stack. * libguile/throw.c (catch): Adapt to scm_i_prompt_pop_abort_args_x change. * libguile/vm-engine.c (ALLOC_FRAME, RESET_FRAME): (FRAME_LOCALS_COUNT_FROM): Adapt to stack growth change. (LOCAL_ADDRESS): Use SCM_FRAME_SLOT to get the address as the proper data type. (RETURN_ONE_VALUE, RETURN_VALUE_LIST): Adapt to stack growth change. (apply): Shuffling up the SMOB apply args can cause the stack to expand, so use ALLOC_FRAME instead of RESET_FRAME. (vm_engine): Adapt for stack growth change. * libguile/vm.c (vm_increase_sp, vm_push_sp, vm_restore_sp): Adapt to stack representation change. (scm_i_vm_cont_to_frame): Adapt to take offsets from the top. (scm_i_vm_capture_stack): Adapt to capture from the top. (vm_return_to_continuation_inner): Adapt for data type changes. (vm_return_to_continuation): Likewise, and instead of looping, just splat the saved arguments on with memcpy. (vm_dispatch_hook): Adapt to receive arguments in the reverse order. Adapt callers. (vm_abort): There is never a tail argument. Adapt to stack representation change. (vm_reinstate_partial_continuation) (vm_reinstate_partial_continuation_inner): Adapt to stack growth change. (allocate_stack, free_stack): Adapt to data type change. (expand_stack): Don't try to mremap(), as you can't grow a mapping from the bottom. Without knowing that there's a free mapping space right below the old stack, which there usually isn't on Linux, we have to copy. We can't use MAP_GROWSDOWN because Linux is buggy. (make_vm): Adapt to stack representation changes. (return_unused_stack_to_os): Round down instead of up, as the stack grows down. (scm_i_vm_mark_stack): Adapt to walk up the stack. (scm_i_vm_free_stack): Adapt to scm_vm changes. (vm_expand_stack_inner, reset_stack_limit, vm_expand_stack): Adapt to the stack growing down. (scm_call_n): Adapt to the stack growing down. Don't allow argv to point into the stack. * libguile/vm.h (struct scm_vm, struct scm_vm_cont): Adapt to hold the stack top and bottom.
2015-09-22 10:24:30 +00:00
static union scm_vm_stack_element*
frame_stack_top (enum scm_vm_frame_kind kind, const struct scm_frame *frame)
{
switch (kind)
{
VM stack grows downward Adapt VM stack to grow downward. This will make native compilation look more like the VM code, as we will be able to use native CALL instructions, taking proper advantage of the return address buffer. * libguile/continuations.c (scm_i_continuation_to_frame): Record offsets from stack top. * libguile/control.c (scm_i_prompt_pop_abort_args_x): Adapt for reversed order of arguments, and instead of relying on the abort to push on the number of arguments, make the caller save the stack depth, which allows us to compute the number of arguments ourselves. (reify_partial_continuation, scm_c_abort): Adapt to reversed stack order. * libguile/dynstack.c (scm_dynstack_wind_prompt): Since we wind the stack in a downward direction, subtract the reloc instead of adding it. * libguile/dynstack.h (SCM_F_DYNSTACK_PROMPT_ESCAPE_ONLY): Remove flag; instead rely on prompt-establishing code to save the stack depth. * libguile/eval.c (eval): Remove extraneous "volatile" declarations for variables that are not re-set between the setjmp and any longjmp. Adapt to save stack depth before instating the prompt. * libguile/foreign.c (scm_i_foreign_call): Adapt to receive arguments in reverse order. * libguile/frames.c (frame_stack_top, scm_i_frame_stack_top): Adapt to compute stack top instead of stack bottom. (scm_c_frame_closure): Adapt to stack growth change. (scm_frame_num_locals, scm_frame_local_ref, scm_frame_set_x): Use union data type to access stack. (RELOC): Reformat. (scm_c_frame_previous): Adapt to stack growth change. * libguile/frames.h: Adapt stack diagram to indicate that the stack grows up. (union scm_vm_stack_element): New data type used to access items on the stack. (SCM_FRAME_PREVIOUS_SP) (SCM_FRAME_RETURN_ADDRESS, SCM_FRAME_SET_RETURN_ADDRESS) (SCM_FRAME_DYNAMIC_LINK, SCM_FRAME_SET_DYNAMIC_LINK) (SCM_FRAME_LOCAL, SCM_FRAME_NUM_LOCALS): Adapt to stack representation change. (SCM_FRAME_SLOT): New helper. (SCM_VM_FRAME_FP, SCM_VM_FRAME_SP): Adapt to stack growth change. * libguile/stacks.c (scm_make_stack): Record offsets from top of stack. * libguile/throw.c (catch): Adapt to scm_i_prompt_pop_abort_args_x change. * libguile/vm-engine.c (ALLOC_FRAME, RESET_FRAME): (FRAME_LOCALS_COUNT_FROM): Adapt to stack growth change. (LOCAL_ADDRESS): Use SCM_FRAME_SLOT to get the address as the proper data type. (RETURN_ONE_VALUE, RETURN_VALUE_LIST): Adapt to stack growth change. (apply): Shuffling up the SMOB apply args can cause the stack to expand, so use ALLOC_FRAME instead of RESET_FRAME. (vm_engine): Adapt for stack growth change. * libguile/vm.c (vm_increase_sp, vm_push_sp, vm_restore_sp): Adapt to stack representation change. (scm_i_vm_cont_to_frame): Adapt to take offsets from the top. (scm_i_vm_capture_stack): Adapt to capture from the top. (vm_return_to_continuation_inner): Adapt for data type changes. (vm_return_to_continuation): Likewise, and instead of looping, just splat the saved arguments on with memcpy. (vm_dispatch_hook): Adapt to receive arguments in the reverse order. Adapt callers. (vm_abort): There is never a tail argument. Adapt to stack representation change. (vm_reinstate_partial_continuation) (vm_reinstate_partial_continuation_inner): Adapt to stack growth change. (allocate_stack, free_stack): Adapt to data type change. (expand_stack): Don't try to mremap(), as you can't grow a mapping from the bottom. Without knowing that there's a free mapping space right below the old stack, which there usually isn't on Linux, we have to copy. We can't use MAP_GROWSDOWN because Linux is buggy. (make_vm): Adapt to stack representation changes. (return_unused_stack_to_os): Round down instead of up, as the stack grows down. (scm_i_vm_mark_stack): Adapt to walk up the stack. (scm_i_vm_free_stack): Adapt to scm_vm changes. (vm_expand_stack_inner, reset_stack_limit, vm_expand_stack): Adapt to the stack growing down. (scm_call_n): Adapt to the stack growing down. Don't allow argv to point into the stack. * libguile/vm.h (struct scm_vm, struct scm_vm_cont): Adapt to hold the stack top and bottom.
2015-09-22 10:24:30 +00:00
case SCM_VM_FRAME_KIND_CONT:
{
struct scm_vm_cont *cont = frame->stack_holder;
return cont->stack_bottom + cont->stack_size;
}
case SCM_VM_FRAME_KIND_VM:
VM stack grows downward Adapt VM stack to grow downward. This will make native compilation look more like the VM code, as we will be able to use native CALL instructions, taking proper advantage of the return address buffer. * libguile/continuations.c (scm_i_continuation_to_frame): Record offsets from stack top. * libguile/control.c (scm_i_prompt_pop_abort_args_x): Adapt for reversed order of arguments, and instead of relying on the abort to push on the number of arguments, make the caller save the stack depth, which allows us to compute the number of arguments ourselves. (reify_partial_continuation, scm_c_abort): Adapt to reversed stack order. * libguile/dynstack.c (scm_dynstack_wind_prompt): Since we wind the stack in a downward direction, subtract the reloc instead of adding it. * libguile/dynstack.h (SCM_F_DYNSTACK_PROMPT_ESCAPE_ONLY): Remove flag; instead rely on prompt-establishing code to save the stack depth. * libguile/eval.c (eval): Remove extraneous "volatile" declarations for variables that are not re-set between the setjmp and any longjmp. Adapt to save stack depth before instating the prompt. * libguile/foreign.c (scm_i_foreign_call): Adapt to receive arguments in reverse order. * libguile/frames.c (frame_stack_top, scm_i_frame_stack_top): Adapt to compute stack top instead of stack bottom. (scm_c_frame_closure): Adapt to stack growth change. (scm_frame_num_locals, scm_frame_local_ref, scm_frame_set_x): Use union data type to access stack. (RELOC): Reformat. (scm_c_frame_previous): Adapt to stack growth change. * libguile/frames.h: Adapt stack diagram to indicate that the stack grows up. (union scm_vm_stack_element): New data type used to access items on the stack. (SCM_FRAME_PREVIOUS_SP) (SCM_FRAME_RETURN_ADDRESS, SCM_FRAME_SET_RETURN_ADDRESS) (SCM_FRAME_DYNAMIC_LINK, SCM_FRAME_SET_DYNAMIC_LINK) (SCM_FRAME_LOCAL, SCM_FRAME_NUM_LOCALS): Adapt to stack representation change. (SCM_FRAME_SLOT): New helper. (SCM_VM_FRAME_FP, SCM_VM_FRAME_SP): Adapt to stack growth change. * libguile/stacks.c (scm_make_stack): Record offsets from top of stack. * libguile/throw.c (catch): Adapt to scm_i_prompt_pop_abort_args_x change. * libguile/vm-engine.c (ALLOC_FRAME, RESET_FRAME): (FRAME_LOCALS_COUNT_FROM): Adapt to stack growth change. (LOCAL_ADDRESS): Use SCM_FRAME_SLOT to get the address as the proper data type. (RETURN_ONE_VALUE, RETURN_VALUE_LIST): Adapt to stack growth change. (apply): Shuffling up the SMOB apply args can cause the stack to expand, so use ALLOC_FRAME instead of RESET_FRAME. (vm_engine): Adapt for stack growth change. * libguile/vm.c (vm_increase_sp, vm_push_sp, vm_restore_sp): Adapt to stack representation change. (scm_i_vm_cont_to_frame): Adapt to take offsets from the top. (scm_i_vm_capture_stack): Adapt to capture from the top. (vm_return_to_continuation_inner): Adapt for data type changes. (vm_return_to_continuation): Likewise, and instead of looping, just splat the saved arguments on with memcpy. (vm_dispatch_hook): Adapt to receive arguments in the reverse order. Adapt callers. (vm_abort): There is never a tail argument. Adapt to stack representation change. (vm_reinstate_partial_continuation) (vm_reinstate_partial_continuation_inner): Adapt to stack growth change. (allocate_stack, free_stack): Adapt to data type change. (expand_stack): Don't try to mremap(), as you can't grow a mapping from the bottom. Without knowing that there's a free mapping space right below the old stack, which there usually isn't on Linux, we have to copy. We can't use MAP_GROWSDOWN because Linux is buggy. (make_vm): Adapt to stack representation changes. (return_unused_stack_to_os): Round down instead of up, as the stack grows down. (scm_i_vm_mark_stack): Adapt to walk up the stack. (scm_i_vm_free_stack): Adapt to scm_vm changes. (vm_expand_stack_inner, reset_stack_limit, vm_expand_stack): Adapt to the stack growing down. (scm_call_n): Adapt to the stack growing down. Don't allow argv to point into the stack. * libguile/vm.h (struct scm_vm, struct scm_vm_cont): Adapt to hold the stack top and bottom.
2015-09-22 10:24:30 +00:00
return ((struct scm_vm *) frame->stack_holder)->stack_top;
default:
abort ();
}
}
VM stack grows downward Adapt VM stack to grow downward. This will make native compilation look more like the VM code, as we will be able to use native CALL instructions, taking proper advantage of the return address buffer. * libguile/continuations.c (scm_i_continuation_to_frame): Record offsets from stack top. * libguile/control.c (scm_i_prompt_pop_abort_args_x): Adapt for reversed order of arguments, and instead of relying on the abort to push on the number of arguments, make the caller save the stack depth, which allows us to compute the number of arguments ourselves. (reify_partial_continuation, scm_c_abort): Adapt to reversed stack order. * libguile/dynstack.c (scm_dynstack_wind_prompt): Since we wind the stack in a downward direction, subtract the reloc instead of adding it. * libguile/dynstack.h (SCM_F_DYNSTACK_PROMPT_ESCAPE_ONLY): Remove flag; instead rely on prompt-establishing code to save the stack depth. * libguile/eval.c (eval): Remove extraneous "volatile" declarations for variables that are not re-set between the setjmp and any longjmp. Adapt to save stack depth before instating the prompt. * libguile/foreign.c (scm_i_foreign_call): Adapt to receive arguments in reverse order. * libguile/frames.c (frame_stack_top, scm_i_frame_stack_top): Adapt to compute stack top instead of stack bottom. (scm_c_frame_closure): Adapt to stack growth change. (scm_frame_num_locals, scm_frame_local_ref, scm_frame_set_x): Use union data type to access stack. (RELOC): Reformat. (scm_c_frame_previous): Adapt to stack growth change. * libguile/frames.h: Adapt stack diagram to indicate that the stack grows up. (union scm_vm_stack_element): New data type used to access items on the stack. (SCM_FRAME_PREVIOUS_SP) (SCM_FRAME_RETURN_ADDRESS, SCM_FRAME_SET_RETURN_ADDRESS) (SCM_FRAME_DYNAMIC_LINK, SCM_FRAME_SET_DYNAMIC_LINK) (SCM_FRAME_LOCAL, SCM_FRAME_NUM_LOCALS): Adapt to stack representation change. (SCM_FRAME_SLOT): New helper. (SCM_VM_FRAME_FP, SCM_VM_FRAME_SP): Adapt to stack growth change. * libguile/stacks.c (scm_make_stack): Record offsets from top of stack. * libguile/throw.c (catch): Adapt to scm_i_prompt_pop_abort_args_x change. * libguile/vm-engine.c (ALLOC_FRAME, RESET_FRAME): (FRAME_LOCALS_COUNT_FROM): Adapt to stack growth change. (LOCAL_ADDRESS): Use SCM_FRAME_SLOT to get the address as the proper data type. (RETURN_ONE_VALUE, RETURN_VALUE_LIST): Adapt to stack growth change. (apply): Shuffling up the SMOB apply args can cause the stack to expand, so use ALLOC_FRAME instead of RESET_FRAME. (vm_engine): Adapt for stack growth change. * libguile/vm.c (vm_increase_sp, vm_push_sp, vm_restore_sp): Adapt to stack representation change. (scm_i_vm_cont_to_frame): Adapt to take offsets from the top. (scm_i_vm_capture_stack): Adapt to capture from the top. (vm_return_to_continuation_inner): Adapt for data type changes. (vm_return_to_continuation): Likewise, and instead of looping, just splat the saved arguments on with memcpy. (vm_dispatch_hook): Adapt to receive arguments in the reverse order. Adapt callers. (vm_abort): There is never a tail argument. Adapt to stack representation change. (vm_reinstate_partial_continuation) (vm_reinstate_partial_continuation_inner): Adapt to stack growth change. (allocate_stack, free_stack): Adapt to data type change. (expand_stack): Don't try to mremap(), as you can't grow a mapping from the bottom. Without knowing that there's a free mapping space right below the old stack, which there usually isn't on Linux, we have to copy. We can't use MAP_GROWSDOWN because Linux is buggy. (make_vm): Adapt to stack representation changes. (return_unused_stack_to_os): Round down instead of up, as the stack grows down. (scm_i_vm_mark_stack): Adapt to walk up the stack. (scm_i_vm_free_stack): Adapt to scm_vm changes. (vm_expand_stack_inner, reset_stack_limit, vm_expand_stack): Adapt to the stack growing down. (scm_call_n): Adapt to the stack growing down. Don't allow argv to point into the stack. * libguile/vm.h (struct scm_vm, struct scm_vm_cont): Adapt to hold the stack top and bottom.
2015-09-22 10:24:30 +00:00
union scm_vm_stack_element*
scm_i_frame_stack_top (SCM frame)
#define FUNC_NAME "frame-stack-top"
{
SCM_VALIDATE_VM_FRAME (1, frame);
VM stack grows downward Adapt VM stack to grow downward. This will make native compilation look more like the VM code, as we will be able to use native CALL instructions, taking proper advantage of the return address buffer. * libguile/continuations.c (scm_i_continuation_to_frame): Record offsets from stack top. * libguile/control.c (scm_i_prompt_pop_abort_args_x): Adapt for reversed order of arguments, and instead of relying on the abort to push on the number of arguments, make the caller save the stack depth, which allows us to compute the number of arguments ourselves. (reify_partial_continuation, scm_c_abort): Adapt to reversed stack order. * libguile/dynstack.c (scm_dynstack_wind_prompt): Since we wind the stack in a downward direction, subtract the reloc instead of adding it. * libguile/dynstack.h (SCM_F_DYNSTACK_PROMPT_ESCAPE_ONLY): Remove flag; instead rely on prompt-establishing code to save the stack depth. * libguile/eval.c (eval): Remove extraneous "volatile" declarations for variables that are not re-set between the setjmp and any longjmp. Adapt to save stack depth before instating the prompt. * libguile/foreign.c (scm_i_foreign_call): Adapt to receive arguments in reverse order. * libguile/frames.c (frame_stack_top, scm_i_frame_stack_top): Adapt to compute stack top instead of stack bottom. (scm_c_frame_closure): Adapt to stack growth change. (scm_frame_num_locals, scm_frame_local_ref, scm_frame_set_x): Use union data type to access stack. (RELOC): Reformat. (scm_c_frame_previous): Adapt to stack growth change. * libguile/frames.h: Adapt stack diagram to indicate that the stack grows up. (union scm_vm_stack_element): New data type used to access items on the stack. (SCM_FRAME_PREVIOUS_SP) (SCM_FRAME_RETURN_ADDRESS, SCM_FRAME_SET_RETURN_ADDRESS) (SCM_FRAME_DYNAMIC_LINK, SCM_FRAME_SET_DYNAMIC_LINK) (SCM_FRAME_LOCAL, SCM_FRAME_NUM_LOCALS): Adapt to stack representation change. (SCM_FRAME_SLOT): New helper. (SCM_VM_FRAME_FP, SCM_VM_FRAME_SP): Adapt to stack growth change. * libguile/stacks.c (scm_make_stack): Record offsets from top of stack. * libguile/throw.c (catch): Adapt to scm_i_prompt_pop_abort_args_x change. * libguile/vm-engine.c (ALLOC_FRAME, RESET_FRAME): (FRAME_LOCALS_COUNT_FROM): Adapt to stack growth change. (LOCAL_ADDRESS): Use SCM_FRAME_SLOT to get the address as the proper data type. (RETURN_ONE_VALUE, RETURN_VALUE_LIST): Adapt to stack growth change. (apply): Shuffling up the SMOB apply args can cause the stack to expand, so use ALLOC_FRAME instead of RESET_FRAME. (vm_engine): Adapt for stack growth change. * libguile/vm.c (vm_increase_sp, vm_push_sp, vm_restore_sp): Adapt to stack representation change. (scm_i_vm_cont_to_frame): Adapt to take offsets from the top. (scm_i_vm_capture_stack): Adapt to capture from the top. (vm_return_to_continuation_inner): Adapt for data type changes. (vm_return_to_continuation): Likewise, and instead of looping, just splat the saved arguments on with memcpy. (vm_dispatch_hook): Adapt to receive arguments in the reverse order. Adapt callers. (vm_abort): There is never a tail argument. Adapt to stack representation change. (vm_reinstate_partial_continuation) (vm_reinstate_partial_continuation_inner): Adapt to stack growth change. (allocate_stack, free_stack): Adapt to data type change. (expand_stack): Don't try to mremap(), as you can't grow a mapping from the bottom. Without knowing that there's a free mapping space right below the old stack, which there usually isn't on Linux, we have to copy. We can't use MAP_GROWSDOWN because Linux is buggy. (make_vm): Adapt to stack representation changes. (return_unused_stack_to_os): Round down instead of up, as the stack grows down. (scm_i_vm_mark_stack): Adapt to walk up the stack. (scm_i_vm_free_stack): Adapt to scm_vm changes. (vm_expand_stack_inner, reset_stack_limit, vm_expand_stack): Adapt to the stack growing down. (scm_call_n): Adapt to the stack growing down. Don't allow argv to point into the stack. * libguile/vm.h (struct scm_vm, struct scm_vm_cont): Adapt to hold the stack top and bottom.
2015-09-22 10:24:30 +00:00
return frame_stack_top (SCM_VM_FRAME_KIND (frame),
SCM_VM_FRAME_DATA (frame));
}
#undef FUNC_NAME
2001-04-22 02:13:48 +00:00
/* Scheme interface */
replace frame implementation with VM frames * libguile/stacks.h: Rework so that a stack doesn't copy information out of VM frames, it just holds onto a VM frame, along with the stack id and length. VM frames are now the only representation of frames in Guile. (scm_t_info_frame, SCM_FRAME_N_SLOTS, SCM_FRAME_REF, SCM_FRAME_NUMBER) (SCM_FRAME_FLAGS, SCM_FRAME_SOURCE, SCM_FRAME_PROC, SCM_FRAME_ARGS) (SCM_FRAME_PREV, SCM_FRAME_NEXT) (SCM_FRAMEF_VOID, SCM_FRAMEF_REAL, SCM_FRAMEF_PROC) (SCM_FRAMEF_EVAL_ARGS, SCM_FRAMEF_OVERFLOW) (SCM_FRAME_VOID_P, SCM_FRAME_REAL_P, SCM_FRAME_PROC_P) (SCM_FRAME_EVAL_ARGS_P, SCM_FRAME_OVERFLOW_P): Remove these macros corresponding to the old frame implementation. (scm_frame_p scm_frame_source, scm_frame_procedure) (scm_frame_arguments): These definitions are now in frames.h. (scm_last_stack_frame): Remove declaration of previously-removed constructor. Probably should re-instate it though. (scm_frame_number, scm_frame_previous, scm_frame_next) (scm_frame_real_p, scm_frame_procedure_p, scm_frame_evaluating_args_p) (scm_frame_overflow_p) : Remove these procedures corresponding to the old stack implementation. * libguile/stacks.c: Update for new frames implementation. * libguile/frames.h: * libguile/frames.c: Rename functions operating on VM frames to have a scm_frame prefix, not scm_vm_frame -- because they really are the only frames we have. Rename corresponding Scheme functions too, from vm-frame-foo to frame-foo. * libguile/deprecated.h: Remove scm_stack and scm_info_frame data types. * libguile/vm.c (vm_dispatch_hook): Adapt to scm_c_make_frame name change. * module/system/vm/frame.scm: No need to export functions provided frames.c now, as we load those procedures into the default environment now. Rename functions, and remove a couple of outdated, unused functions. The bottom half of this file is still bitrotten, though. * libguile/backtrace.c: Rework to operate on the new frame representation. Also fix a bug displaying file names for compiled procedures. * libguile/init.c: Load the VM much earlier, just because we can. Also it allows us to have frames.[ch] loaded in time for stacks to be initialized, so that scm_frame_arguments can do the right thing.
2009-12-03 13:09:58 +01:00
SCM_DEFINE (scm_frame_p, "frame?", 1, 0, 0,
2001-04-22 02:13:48 +00:00
(SCM obj),
"")
replace frame implementation with VM frames * libguile/stacks.h: Rework so that a stack doesn't copy information out of VM frames, it just holds onto a VM frame, along with the stack id and length. VM frames are now the only representation of frames in Guile. (scm_t_info_frame, SCM_FRAME_N_SLOTS, SCM_FRAME_REF, SCM_FRAME_NUMBER) (SCM_FRAME_FLAGS, SCM_FRAME_SOURCE, SCM_FRAME_PROC, SCM_FRAME_ARGS) (SCM_FRAME_PREV, SCM_FRAME_NEXT) (SCM_FRAMEF_VOID, SCM_FRAMEF_REAL, SCM_FRAMEF_PROC) (SCM_FRAMEF_EVAL_ARGS, SCM_FRAMEF_OVERFLOW) (SCM_FRAME_VOID_P, SCM_FRAME_REAL_P, SCM_FRAME_PROC_P) (SCM_FRAME_EVAL_ARGS_P, SCM_FRAME_OVERFLOW_P): Remove these macros corresponding to the old frame implementation. (scm_frame_p scm_frame_source, scm_frame_procedure) (scm_frame_arguments): These definitions are now in frames.h. (scm_last_stack_frame): Remove declaration of previously-removed constructor. Probably should re-instate it though. (scm_frame_number, scm_frame_previous, scm_frame_next) (scm_frame_real_p, scm_frame_procedure_p, scm_frame_evaluating_args_p) (scm_frame_overflow_p) : Remove these procedures corresponding to the old stack implementation. * libguile/stacks.c: Update for new frames implementation. * libguile/frames.h: * libguile/frames.c: Rename functions operating on VM frames to have a scm_frame prefix, not scm_vm_frame -- because they really are the only frames we have. Rename corresponding Scheme functions too, from vm-frame-foo to frame-foo. * libguile/deprecated.h: Remove scm_stack and scm_info_frame data types. * libguile/vm.c (vm_dispatch_hook): Adapt to scm_c_make_frame name change. * module/system/vm/frame.scm: No need to export functions provided frames.c now, as we load those procedures into the default environment now. Rename functions, and remove a couple of outdated, unused functions. The bottom half of this file is still bitrotten, though. * libguile/backtrace.c: Rework to operate on the new frame representation. Also fix a bug displaying file names for compiled procedures. * libguile/init.c: Load the VM much earlier, just because we can. Also it allows us to have frames.[ch] loaded in time for stacks to be initialized, so that scm_frame_arguments can do the right thing.
2009-12-03 13:09:58 +01:00
#define FUNC_NAME s_scm_frame_p
2001-04-22 02:13:48 +00:00
{
return scm_from_bool (SCM_VM_FRAME_P (obj));
remove heap links in VM frames, incorporate vm frames into normal backtraces * doc/ref/vm.texi (Stack Layout): Update to remove references to the "heap link". * gdbinit: Update for "heap link" removal. * libguile/frames.c: * libguile/frames.h: Update macros and diagram for removal of "heap link". As part of this, we also remove "heap frames", replacing them with "vm frames", which are much like the interpreter's debug objects, but for VM stacks. That is to say, they don't actually hold the stack themselves, just the pointers into stack that's held by a continuation (either captured or current). * libguile/stacks.c (stack_depth, read_frames): Since a "stack" object is really a copy of information that comes from somewhere else, it makes sense to copy over info from the VM, just as `make-stack' does from the evaluator. The tricky bit is to figure out how to interleave VM and interpreter frames. We do that by starting in the interpreter, and whenever the current frame's procedure is actually a program, we switch to the VM stack, switching back when we reach a "bootstrap frame". The last bit is hacky, but it does work... (is_vm_bootstrap_frame): Hacky predicate to see if a VM frame is a bootstrap frame. (scm_make_stack): Accept a VM frame in addition to debug frames. Probably has some bugs in this case. But in the case that the arg is #t (a common case), do the right thing, capturing the top VM frame as well, and interleaving those frames appropriately on the stack. As an accident, we lost the ability to limit the number of frames in the backtrace. We could add that back, but personally I always want *all* frames in the trace... Narrowing still works fine, though there are some hiccups sometimes -- e.g. an outer cut to a procedure that does a tail-call in VM code will never find the cut, as it no longer exists in the continuation. * libguile/vm.h (struct scm_vm): So! Now that we have switched to save stacks in the normal make-stack, there's no more need for `this_frame' or `last_frame'. On the other hand, we can take this opportunity to fix tracing: when we're in a trace hook, we set `trace_frame' on the VM, so we know not to fire hooks when we're already in a hook. (struct scm_vm_cont): Expose this, as make-stack needs it to make VM frames from VM continuations. * libguile/vm.c (scm_vm_trace_frame): New function, gets the current trace frame. (vm_mark, make_vm): Hook up the trace frame. (vm_dispatch_hook): New hook dispatcher, with a dynwind so it does the right thing if the hook exits nonlocally. * libguile/vm-engine.c (vm_run): No more this_frame in the wind data. * libguile/vm-engine.h (RUN_HOOK): Run hooks through the dispatcher. (ALIGN_AS_NON_IMMEDIATE, POP_LIST_ON_STACK): Remove unused code. (NEW_FRAME): Adapt for no HL in the frame. * libguile/vm-i-system.c (goto/args, mv-call, return, return/values): Adapt for no HL in the frame. * module/system/vm/frame.scm: * module/system/vm/vm.scm: Beginnings of some reworkings, needs more thought.
2008-12-26 17:59:46 +01:00
}
#undef FUNC_NAME
/* Retrieve the local in slot 0, which may or may not actually be a
procedure, and may or may not actually be the procedure being
applied. If you want the procedure, look it up from the IP. */
SCM
scm_c_frame_closure (enum scm_vm_frame_kind kind, const struct scm_frame *frame)
{
VM stack grows downward Adapt VM stack to grow downward. This will make native compilation look more like the VM code, as we will be able to use native CALL instructions, taking proper advantage of the return address buffer. * libguile/continuations.c (scm_i_continuation_to_frame): Record offsets from stack top. * libguile/control.c (scm_i_prompt_pop_abort_args_x): Adapt for reversed order of arguments, and instead of relying on the abort to push on the number of arguments, make the caller save the stack depth, which allows us to compute the number of arguments ourselves. (reify_partial_continuation, scm_c_abort): Adapt to reversed stack order. * libguile/dynstack.c (scm_dynstack_wind_prompt): Since we wind the stack in a downward direction, subtract the reloc instead of adding it. * libguile/dynstack.h (SCM_F_DYNSTACK_PROMPT_ESCAPE_ONLY): Remove flag; instead rely on prompt-establishing code to save the stack depth. * libguile/eval.c (eval): Remove extraneous "volatile" declarations for variables that are not re-set between the setjmp and any longjmp. Adapt to save stack depth before instating the prompt. * libguile/foreign.c (scm_i_foreign_call): Adapt to receive arguments in reverse order. * libguile/frames.c (frame_stack_top, scm_i_frame_stack_top): Adapt to compute stack top instead of stack bottom. (scm_c_frame_closure): Adapt to stack growth change. (scm_frame_num_locals, scm_frame_local_ref, scm_frame_set_x): Use union data type to access stack. (RELOC): Reformat. (scm_c_frame_previous): Adapt to stack growth change. * libguile/frames.h: Adapt stack diagram to indicate that the stack grows up. (union scm_vm_stack_element): New data type used to access items on the stack. (SCM_FRAME_PREVIOUS_SP) (SCM_FRAME_RETURN_ADDRESS, SCM_FRAME_SET_RETURN_ADDRESS) (SCM_FRAME_DYNAMIC_LINK, SCM_FRAME_SET_DYNAMIC_LINK) (SCM_FRAME_LOCAL, SCM_FRAME_NUM_LOCALS): Adapt to stack representation change. (SCM_FRAME_SLOT): New helper. (SCM_VM_FRAME_FP, SCM_VM_FRAME_SP): Adapt to stack growth change. * libguile/stacks.c (scm_make_stack): Record offsets from top of stack. * libguile/throw.c (catch): Adapt to scm_i_prompt_pop_abort_args_x change. * libguile/vm-engine.c (ALLOC_FRAME, RESET_FRAME): (FRAME_LOCALS_COUNT_FROM): Adapt to stack growth change. (LOCAL_ADDRESS): Use SCM_FRAME_SLOT to get the address as the proper data type. (RETURN_ONE_VALUE, RETURN_VALUE_LIST): Adapt to stack growth change. (apply): Shuffling up the SMOB apply args can cause the stack to expand, so use ALLOC_FRAME instead of RESET_FRAME. (vm_engine): Adapt for stack growth change. * libguile/vm.c (vm_increase_sp, vm_push_sp, vm_restore_sp): Adapt to stack representation change. (scm_i_vm_cont_to_frame): Adapt to take offsets from the top. (scm_i_vm_capture_stack): Adapt to capture from the top. (vm_return_to_continuation_inner): Adapt for data type changes. (vm_return_to_continuation): Likewise, and instead of looping, just splat the saved arguments on with memcpy. (vm_dispatch_hook): Adapt to receive arguments in the reverse order. Adapt callers. (vm_abort): There is never a tail argument. Adapt to stack representation change. (vm_reinstate_partial_continuation) (vm_reinstate_partial_continuation_inner): Adapt to stack growth change. (allocate_stack, free_stack): Adapt to data type change. (expand_stack): Don't try to mremap(), as you can't grow a mapping from the bottom. Without knowing that there's a free mapping space right below the old stack, which there usually isn't on Linux, we have to copy. We can't use MAP_GROWSDOWN because Linux is buggy. (make_vm): Adapt to stack representation changes. (return_unused_stack_to_os): Round down instead of up, as the stack grows down. (scm_i_vm_mark_stack): Adapt to walk up the stack. (scm_i_vm_free_stack): Adapt to scm_vm changes. (vm_expand_stack_inner, reset_stack_limit, vm_expand_stack): Adapt to the stack growing down. (scm_call_n): Adapt to the stack growing down. Don't allow argv to point into the stack. * libguile/vm.h (struct scm_vm, struct scm_vm_cont): Adapt to hold the stack top and bottom.
2015-09-22 10:24:30 +00:00
union scm_vm_stack_element *fp, *sp;
VM stack grows downward Adapt VM stack to grow downward. This will make native compilation look more like the VM code, as we will be able to use native CALL instructions, taking proper advantage of the return address buffer. * libguile/continuations.c (scm_i_continuation_to_frame): Record offsets from stack top. * libguile/control.c (scm_i_prompt_pop_abort_args_x): Adapt for reversed order of arguments, and instead of relying on the abort to push on the number of arguments, make the caller save the stack depth, which allows us to compute the number of arguments ourselves. (reify_partial_continuation, scm_c_abort): Adapt to reversed stack order. * libguile/dynstack.c (scm_dynstack_wind_prompt): Since we wind the stack in a downward direction, subtract the reloc instead of adding it. * libguile/dynstack.h (SCM_F_DYNSTACK_PROMPT_ESCAPE_ONLY): Remove flag; instead rely on prompt-establishing code to save the stack depth. * libguile/eval.c (eval): Remove extraneous "volatile" declarations for variables that are not re-set between the setjmp and any longjmp. Adapt to save stack depth before instating the prompt. * libguile/foreign.c (scm_i_foreign_call): Adapt to receive arguments in reverse order. * libguile/frames.c (frame_stack_top, scm_i_frame_stack_top): Adapt to compute stack top instead of stack bottom. (scm_c_frame_closure): Adapt to stack growth change. (scm_frame_num_locals, scm_frame_local_ref, scm_frame_set_x): Use union data type to access stack. (RELOC): Reformat. (scm_c_frame_previous): Adapt to stack growth change. * libguile/frames.h: Adapt stack diagram to indicate that the stack grows up. (union scm_vm_stack_element): New data type used to access items on the stack. (SCM_FRAME_PREVIOUS_SP) (SCM_FRAME_RETURN_ADDRESS, SCM_FRAME_SET_RETURN_ADDRESS) (SCM_FRAME_DYNAMIC_LINK, SCM_FRAME_SET_DYNAMIC_LINK) (SCM_FRAME_LOCAL, SCM_FRAME_NUM_LOCALS): Adapt to stack representation change. (SCM_FRAME_SLOT): New helper. (SCM_VM_FRAME_FP, SCM_VM_FRAME_SP): Adapt to stack growth change. * libguile/stacks.c (scm_make_stack): Record offsets from top of stack. * libguile/throw.c (catch): Adapt to scm_i_prompt_pop_abort_args_x change. * libguile/vm-engine.c (ALLOC_FRAME, RESET_FRAME): (FRAME_LOCALS_COUNT_FROM): Adapt to stack growth change. (LOCAL_ADDRESS): Use SCM_FRAME_SLOT to get the address as the proper data type. (RETURN_ONE_VALUE, RETURN_VALUE_LIST): Adapt to stack growth change. (apply): Shuffling up the SMOB apply args can cause the stack to expand, so use ALLOC_FRAME instead of RESET_FRAME. (vm_engine): Adapt for stack growth change. * libguile/vm.c (vm_increase_sp, vm_push_sp, vm_restore_sp): Adapt to stack representation change. (scm_i_vm_cont_to_frame): Adapt to take offsets from the top. (scm_i_vm_capture_stack): Adapt to capture from the top. (vm_return_to_continuation_inner): Adapt for data type changes. (vm_return_to_continuation): Likewise, and instead of looping, just splat the saved arguments on with memcpy. (vm_dispatch_hook): Adapt to receive arguments in the reverse order. Adapt callers. (vm_abort): There is never a tail argument. Adapt to stack representation change. (vm_reinstate_partial_continuation) (vm_reinstate_partial_continuation_inner): Adapt to stack growth change. (allocate_stack, free_stack): Adapt to data type change. (expand_stack): Don't try to mremap(), as you can't grow a mapping from the bottom. Without knowing that there's a free mapping space right below the old stack, which there usually isn't on Linux, we have to copy. We can't use MAP_GROWSDOWN because Linux is buggy. (make_vm): Adapt to stack representation changes. (return_unused_stack_to_os): Round down instead of up, as the stack grows down. (scm_i_vm_mark_stack): Adapt to walk up the stack. (scm_i_vm_free_stack): Adapt to scm_vm changes. (vm_expand_stack_inner, reset_stack_limit, vm_expand_stack): Adapt to the stack growing down. (scm_call_n): Adapt to the stack growing down. Don't allow argv to point into the stack. * libguile/vm.h (struct scm_vm, struct scm_vm_cont): Adapt to hold the stack top and bottom.
2015-09-22 10:24:30 +00:00
fp = frame_stack_top (kind, frame) - frame->fp_offset;
sp = frame_stack_top (kind, frame) - frame->sp_offset;
if (SCM_FRAME_NUM_LOCALS (fp, sp) > 0)
return SCM_FRAME_LOCAL (fp, 0);
return SCM_BOOL_F;
}
static SCM frame_procedure_name_var;
static void
init_frame_procedure_name_var (void)
{
frame_procedure_name_var
= scm_c_private_lookup ("system vm frame", "frame-procedure-name");
}
SCM_DEFINE (scm_frame_procedure_name, "frame-procedure-name", 1, 0, 0,
(SCM frame),
"")
#define FUNC_NAME s_scm_frame_procedure_name
{
static scm_i_pthread_once_t once = SCM_I_PTHREAD_ONCE_INIT;
scm_i_pthread_once (&once, init_frame_procedure_name_var);
SCM_VALIDATE_VM_FRAME (1, frame);
return scm_call_1 (scm_variable_ref (frame_procedure_name_var), frame);
}
#undef FUNC_NAME
Fix thread-unsafe lazy initializations. * libguile/backtrace.c (print_exception_var): New static variable. (init_print_exception_var): New static function. (scm_print_exception): Remove thread-unsafe lazy initialization. Call 'init_print_exception_var' using 'scm_i_pthread_once'. Use 'print_exception_var'. * libguile/continuations.c (call_cc): New static variable. (init_call_cc): New static function. (scm_i_call_with_current_continuation): Remove thread-unsafe lazy initialization. Call 'init_call_cc' using 'scm_i_pthread_once'. * libguile/debug.c (local_eval_var): New static variable. (init_local_eval_var): New static function. (scm_local_eval): Remove lazy initialization using mutexes. Call 'init_local_eval_var' using 'scm_i_pthread_once'. Use 'scm_variable_ref' instead of 'SCM_VARIABLE_REF'. * libguile/eval.c (map_var, for_each_var): New static variables. (init_map_var, init_for_each_var): New static functions. (scm_map, scm_for_each): Remove thread-unsafe lazy initializations. Call 'init_map_var' (or 'init_for_each_var') using 'scm_i_pthread_once'. Use 'map_var' (or 'for_each_var'). * libguile/frames.c (frame_arguments_var): New static variable. (init_frame_arguments_var): New static function. (scm_frame_arguments): Remove thread-unsafe lazy initialization. Call 'init_frame_arguments_var' using 'scm_i_pthread_once'. Use 'frame_arguments_var'. Use 'scm_variable_ref' instead of 'SCM_VARIABLE_REF'. * libguile/goops.c (delayed_compile_var): New static variable. (init_delayed_compile_var): New static function. (make_dispatch_procedure): Remove thread-unsafe lazy initialization. Call 'init_delayed_compile_var' using 'scm_i_pthread_once'. Use 'delayed_compile_var'. Use 'scm_variable_ref' instead of 'SCM_VARIABLE_REF'. * libguile/instructions.c (instructions_by_name): New static variable. (init_instructions_by_name): New static function. (scm_lookup_instruction_by_name): Remove thread-unsafe lazy initialization. Call 'init_instructions_by_name' using 'scm_i_pthread_once'. * libguile/ports.c (current_warning_port_var) (current_warning_port_once): New static variables. (init_current_warning_port_var): New static function. (scm_current_warning_port): Remove lazy initialization using mutexes. Call 'init_current_warning_port_var' using 'scm_i_pthread_once'. Use 'current_warning_port_var'. (scm_set_current_warning_port): Remove thread-unsafe lazy initialization. Call 'init_current_warning_port_var' using 'scm_i_pthread_once'. Use 'current_warning_port_var'. * libguile/strings.c (null_stringbuf): New static variable. (init_null_stringbuf): New static function. (scm_i_make_string): Remove thread-unsafe lazy initialization. Call 'init_null_stringbuf' using 'scm_i_pthread_once'. * libguile/strports.c (eval_string_var, k_module): New static variables. (init_eval_string_var_and_k_module): New static function. (scm_eval_string_in_module): Remove lazy initialization using mutexes. Call 'init_eval_string_var_and_k_module' using 'scm_i_pthread_once'. Use 'eval_string_var'. * libguile/throw.c (CACHE_VAR): Remove incorrect macro. (catch_var, throw_var, with_throw_handler_var): New static variables. (scm_catch, scm_catch_with_pre_unwind_handler): Remove thread-unsafe lazy initialization. Use 'catch_var'. (init_with_throw_handler_var): New static function. (scm_with_throw_handler): Remove thread-unsafe lazy initialization. Call 'init_with_throw_handler_var' using 'scm_i_pthread_once'. Use 'with_throw_handler_var'. (scm_throw): Remove thread-unsafe lazy initialization. Use 'throw_var'. (scm_init_throw): Initialize 'catch_var' and 'throw_var'.
2014-01-23 11:37:36 -05:00
static SCM frame_arguments_var;
static void
init_frame_arguments_var (void)
{
frame_arguments_var
= scm_c_private_lookup ("system vm frame", "frame-arguments");
}
replace frame implementation with VM frames * libguile/stacks.h: Rework so that a stack doesn't copy information out of VM frames, it just holds onto a VM frame, along with the stack id and length. VM frames are now the only representation of frames in Guile. (scm_t_info_frame, SCM_FRAME_N_SLOTS, SCM_FRAME_REF, SCM_FRAME_NUMBER) (SCM_FRAME_FLAGS, SCM_FRAME_SOURCE, SCM_FRAME_PROC, SCM_FRAME_ARGS) (SCM_FRAME_PREV, SCM_FRAME_NEXT) (SCM_FRAMEF_VOID, SCM_FRAMEF_REAL, SCM_FRAMEF_PROC) (SCM_FRAMEF_EVAL_ARGS, SCM_FRAMEF_OVERFLOW) (SCM_FRAME_VOID_P, SCM_FRAME_REAL_P, SCM_FRAME_PROC_P) (SCM_FRAME_EVAL_ARGS_P, SCM_FRAME_OVERFLOW_P): Remove these macros corresponding to the old frame implementation. (scm_frame_p scm_frame_source, scm_frame_procedure) (scm_frame_arguments): These definitions are now in frames.h. (scm_last_stack_frame): Remove declaration of previously-removed constructor. Probably should re-instate it though. (scm_frame_number, scm_frame_previous, scm_frame_next) (scm_frame_real_p, scm_frame_procedure_p, scm_frame_evaluating_args_p) (scm_frame_overflow_p) : Remove these procedures corresponding to the old stack implementation. * libguile/stacks.c: Update for new frames implementation. * libguile/frames.h: * libguile/frames.c: Rename functions operating on VM frames to have a scm_frame prefix, not scm_vm_frame -- because they really are the only frames we have. Rename corresponding Scheme functions too, from vm-frame-foo to frame-foo. * libguile/deprecated.h: Remove scm_stack and scm_info_frame data types. * libguile/vm.c (vm_dispatch_hook): Adapt to scm_c_make_frame name change. * module/system/vm/frame.scm: No need to export functions provided frames.c now, as we load those procedures into the default environment now. Rename functions, and remove a couple of outdated, unused functions. The bottom half of this file is still bitrotten, though. * libguile/backtrace.c: Rework to operate on the new frame representation. Also fix a bug displaying file names for compiled procedures. * libguile/init.c: Load the VM much earlier, just because we can. Also it allows us to have frames.[ch] loaded in time for stacks to be initialized, so that scm_frame_arguments can do the right thing.
2009-12-03 13:09:58 +01:00
SCM_DEFINE (scm_frame_arguments, "frame-arguments", 1, 0, 0,
(SCM frame),
"")
#define FUNC_NAME s_scm_frame_arguments
remove heap links in VM frames, incorporate vm frames into normal backtraces * doc/ref/vm.texi (Stack Layout): Update to remove references to the "heap link". * gdbinit: Update for "heap link" removal. * libguile/frames.c: * libguile/frames.h: Update macros and diagram for removal of "heap link". As part of this, we also remove "heap frames", replacing them with "vm frames", which are much like the interpreter's debug objects, but for VM stacks. That is to say, they don't actually hold the stack themselves, just the pointers into stack that's held by a continuation (either captured or current). * libguile/stacks.c (stack_depth, read_frames): Since a "stack" object is really a copy of information that comes from somewhere else, it makes sense to copy over info from the VM, just as `make-stack' does from the evaluator. The tricky bit is to figure out how to interleave VM and interpreter frames. We do that by starting in the interpreter, and whenever the current frame's procedure is actually a program, we switch to the VM stack, switching back when we reach a "bootstrap frame". The last bit is hacky, but it does work... (is_vm_bootstrap_frame): Hacky predicate to see if a VM frame is a bootstrap frame. (scm_make_stack): Accept a VM frame in addition to debug frames. Probably has some bugs in this case. But in the case that the arg is #t (a common case), do the right thing, capturing the top VM frame as well, and interleaving those frames appropriately on the stack. As an accident, we lost the ability to limit the number of frames in the backtrace. We could add that back, but personally I always want *all* frames in the trace... Narrowing still works fine, though there are some hiccups sometimes -- e.g. an outer cut to a procedure that does a tail-call in VM code will never find the cut, as it no longer exists in the continuation. * libguile/vm.h (struct scm_vm): So! Now that we have switched to save stacks in the normal make-stack, there's no more need for `this_frame' or `last_frame'. On the other hand, we can take this opportunity to fix tracing: when we're in a trace hook, we set `trace_frame' on the VM, so we know not to fire hooks when we're already in a hook. (struct scm_vm_cont): Expose this, as make-stack needs it to make VM frames from VM continuations. * libguile/vm.c (scm_vm_trace_frame): New function, gets the current trace frame. (vm_mark, make_vm): Hook up the trace frame. (vm_dispatch_hook): New hook dispatcher, with a dynwind so it does the right thing if the hook exits nonlocally. * libguile/vm-engine.c (vm_run): No more this_frame in the wind data. * libguile/vm-engine.h (RUN_HOOK): Run hooks through the dispatcher. (ALIGN_AS_NON_IMMEDIATE, POP_LIST_ON_STACK): Remove unused code. (NEW_FRAME): Adapt for no HL in the frame. * libguile/vm-i-system.c (goto/args, mv-call, return, return/values): Adapt for no HL in the frame. * module/system/vm/frame.scm: * module/system/vm/vm.scm: Beginnings of some reworkings, needs more thought.
2008-12-26 17:59:46 +01:00
{
Fix thread-unsafe lazy initializations. * libguile/backtrace.c (print_exception_var): New static variable. (init_print_exception_var): New static function. (scm_print_exception): Remove thread-unsafe lazy initialization. Call 'init_print_exception_var' using 'scm_i_pthread_once'. Use 'print_exception_var'. * libguile/continuations.c (call_cc): New static variable. (init_call_cc): New static function. (scm_i_call_with_current_continuation): Remove thread-unsafe lazy initialization. Call 'init_call_cc' using 'scm_i_pthread_once'. * libguile/debug.c (local_eval_var): New static variable. (init_local_eval_var): New static function. (scm_local_eval): Remove lazy initialization using mutexes. Call 'init_local_eval_var' using 'scm_i_pthread_once'. Use 'scm_variable_ref' instead of 'SCM_VARIABLE_REF'. * libguile/eval.c (map_var, for_each_var): New static variables. (init_map_var, init_for_each_var): New static functions. (scm_map, scm_for_each): Remove thread-unsafe lazy initializations. Call 'init_map_var' (or 'init_for_each_var') using 'scm_i_pthread_once'. Use 'map_var' (or 'for_each_var'). * libguile/frames.c (frame_arguments_var): New static variable. (init_frame_arguments_var): New static function. (scm_frame_arguments): Remove thread-unsafe lazy initialization. Call 'init_frame_arguments_var' using 'scm_i_pthread_once'. Use 'frame_arguments_var'. Use 'scm_variable_ref' instead of 'SCM_VARIABLE_REF'. * libguile/goops.c (delayed_compile_var): New static variable. (init_delayed_compile_var): New static function. (make_dispatch_procedure): Remove thread-unsafe lazy initialization. Call 'init_delayed_compile_var' using 'scm_i_pthread_once'. Use 'delayed_compile_var'. Use 'scm_variable_ref' instead of 'SCM_VARIABLE_REF'. * libguile/instructions.c (instructions_by_name): New static variable. (init_instructions_by_name): New static function. (scm_lookup_instruction_by_name): Remove thread-unsafe lazy initialization. Call 'init_instructions_by_name' using 'scm_i_pthread_once'. * libguile/ports.c (current_warning_port_var) (current_warning_port_once): New static variables. (init_current_warning_port_var): New static function. (scm_current_warning_port): Remove lazy initialization using mutexes. Call 'init_current_warning_port_var' using 'scm_i_pthread_once'. Use 'current_warning_port_var'. (scm_set_current_warning_port): Remove thread-unsafe lazy initialization. Call 'init_current_warning_port_var' using 'scm_i_pthread_once'. Use 'current_warning_port_var'. * libguile/strings.c (null_stringbuf): New static variable. (init_null_stringbuf): New static function. (scm_i_make_string): Remove thread-unsafe lazy initialization. Call 'init_null_stringbuf' using 'scm_i_pthread_once'. * libguile/strports.c (eval_string_var, k_module): New static variables. (init_eval_string_var_and_k_module): New static function. (scm_eval_string_in_module): Remove lazy initialization using mutexes. Call 'init_eval_string_var_and_k_module' using 'scm_i_pthread_once'. Use 'eval_string_var'. * libguile/throw.c (CACHE_VAR): Remove incorrect macro. (catch_var, throw_var, with_throw_handler_var): New static variables. (scm_catch, scm_catch_with_pre_unwind_handler): Remove thread-unsafe lazy initialization. Use 'catch_var'. (init_with_throw_handler_var): New static function. (scm_with_throw_handler): Remove thread-unsafe lazy initialization. Call 'init_with_throw_handler_var' using 'scm_i_pthread_once'. Use 'with_throw_handler_var'. (scm_throw): Remove thread-unsafe lazy initialization. Use 'throw_var'. (scm_init_throw): Initialize 'catch_var' and 'throw_var'.
2014-01-23 11:37:36 -05:00
static scm_i_pthread_once_t once = SCM_I_PTHREAD_ONCE_INIT;
scm_i_pthread_once (&once, init_frame_arguments_var);
remove heap links in VM frames, incorporate vm frames into normal backtraces * doc/ref/vm.texi (Stack Layout): Update to remove references to the "heap link". * gdbinit: Update for "heap link" removal. * libguile/frames.c: * libguile/frames.h: Update macros and diagram for removal of "heap link". As part of this, we also remove "heap frames", replacing them with "vm frames", which are much like the interpreter's debug objects, but for VM stacks. That is to say, they don't actually hold the stack themselves, just the pointers into stack that's held by a continuation (either captured or current). * libguile/stacks.c (stack_depth, read_frames): Since a "stack" object is really a copy of information that comes from somewhere else, it makes sense to copy over info from the VM, just as `make-stack' does from the evaluator. The tricky bit is to figure out how to interleave VM and interpreter frames. We do that by starting in the interpreter, and whenever the current frame's procedure is actually a program, we switch to the VM stack, switching back when we reach a "bootstrap frame". The last bit is hacky, but it does work... (is_vm_bootstrap_frame): Hacky predicate to see if a VM frame is a bootstrap frame. (scm_make_stack): Accept a VM frame in addition to debug frames. Probably has some bugs in this case. But in the case that the arg is #t (a common case), do the right thing, capturing the top VM frame as well, and interleaving those frames appropriately on the stack. As an accident, we lost the ability to limit the number of frames in the backtrace. We could add that back, but personally I always want *all* frames in the trace... Narrowing still works fine, though there are some hiccups sometimes -- e.g. an outer cut to a procedure that does a tail-call in VM code will never find the cut, as it no longer exists in the continuation. * libguile/vm.h (struct scm_vm): So! Now that we have switched to save stacks in the normal make-stack, there's no more need for `this_frame' or `last_frame'. On the other hand, we can take this opportunity to fix tracing: when we're in a trace hook, we set `trace_frame' on the VM, so we know not to fire hooks when we're already in a hook. (struct scm_vm_cont): Expose this, as make-stack needs it to make VM frames from VM continuations. * libguile/vm.c (scm_vm_trace_frame): New function, gets the current trace frame. (vm_mark, make_vm): Hook up the trace frame. (vm_dispatch_hook): New hook dispatcher, with a dynwind so it does the right thing if the hook exits nonlocally. * libguile/vm-engine.c (vm_run): No more this_frame in the wind data. * libguile/vm-engine.h (RUN_HOOK): Run hooks through the dispatcher. (ALIGN_AS_NON_IMMEDIATE, POP_LIST_ON_STACK): Remove unused code. (NEW_FRAME): Adapt for no HL in the frame. * libguile/vm-i-system.c (goto/args, mv-call, return, return/values): Adapt for no HL in the frame. * module/system/vm/frame.scm: * module/system/vm/vm.scm: Beginnings of some reworkings, needs more thought.
2008-12-26 17:59:46 +01:00
Fix thread-unsafe lazy initializations. * libguile/backtrace.c (print_exception_var): New static variable. (init_print_exception_var): New static function. (scm_print_exception): Remove thread-unsafe lazy initialization. Call 'init_print_exception_var' using 'scm_i_pthread_once'. Use 'print_exception_var'. * libguile/continuations.c (call_cc): New static variable. (init_call_cc): New static function. (scm_i_call_with_current_continuation): Remove thread-unsafe lazy initialization. Call 'init_call_cc' using 'scm_i_pthread_once'. * libguile/debug.c (local_eval_var): New static variable. (init_local_eval_var): New static function. (scm_local_eval): Remove lazy initialization using mutexes. Call 'init_local_eval_var' using 'scm_i_pthread_once'. Use 'scm_variable_ref' instead of 'SCM_VARIABLE_REF'. * libguile/eval.c (map_var, for_each_var): New static variables. (init_map_var, init_for_each_var): New static functions. (scm_map, scm_for_each): Remove thread-unsafe lazy initializations. Call 'init_map_var' (or 'init_for_each_var') using 'scm_i_pthread_once'. Use 'map_var' (or 'for_each_var'). * libguile/frames.c (frame_arguments_var): New static variable. (init_frame_arguments_var): New static function. (scm_frame_arguments): Remove thread-unsafe lazy initialization. Call 'init_frame_arguments_var' using 'scm_i_pthread_once'. Use 'frame_arguments_var'. Use 'scm_variable_ref' instead of 'SCM_VARIABLE_REF'. * libguile/goops.c (delayed_compile_var): New static variable. (init_delayed_compile_var): New static function. (make_dispatch_procedure): Remove thread-unsafe lazy initialization. Call 'init_delayed_compile_var' using 'scm_i_pthread_once'. Use 'delayed_compile_var'. Use 'scm_variable_ref' instead of 'SCM_VARIABLE_REF'. * libguile/instructions.c (instructions_by_name): New static variable. (init_instructions_by_name): New static function. (scm_lookup_instruction_by_name): Remove thread-unsafe lazy initialization. Call 'init_instructions_by_name' using 'scm_i_pthread_once'. * libguile/ports.c (current_warning_port_var) (current_warning_port_once): New static variables. (init_current_warning_port_var): New static function. (scm_current_warning_port): Remove lazy initialization using mutexes. Call 'init_current_warning_port_var' using 'scm_i_pthread_once'. Use 'current_warning_port_var'. (scm_set_current_warning_port): Remove thread-unsafe lazy initialization. Call 'init_current_warning_port_var' using 'scm_i_pthread_once'. Use 'current_warning_port_var'. * libguile/strings.c (null_stringbuf): New static variable. (init_null_stringbuf): New static function. (scm_i_make_string): Remove thread-unsafe lazy initialization. Call 'init_null_stringbuf' using 'scm_i_pthread_once'. * libguile/strports.c (eval_string_var, k_module): New static variables. (init_eval_string_var_and_k_module): New static function. (scm_eval_string_in_module): Remove lazy initialization using mutexes. Call 'init_eval_string_var_and_k_module' using 'scm_i_pthread_once'. Use 'eval_string_var'. * libguile/throw.c (CACHE_VAR): Remove incorrect macro. (catch_var, throw_var, with_throw_handler_var): New static variables. (scm_catch, scm_catch_with_pre_unwind_handler): Remove thread-unsafe lazy initialization. Use 'catch_var'. (init_with_throw_handler_var): New static function. (scm_with_throw_handler): Remove thread-unsafe lazy initialization. Call 'init_with_throw_handler_var' using 'scm_i_pthread_once'. Use 'with_throw_handler_var'. (scm_throw): Remove thread-unsafe lazy initialization. Use 'throw_var'. (scm_init_throw): Initialize 'catch_var' and 'throw_var'.
2014-01-23 11:37:36 -05:00
SCM_VALIDATE_VM_FRAME (1, frame);
remove heap links in VM frames, incorporate vm frames into normal backtraces * doc/ref/vm.texi (Stack Layout): Update to remove references to the "heap link". * gdbinit: Update for "heap link" removal. * libguile/frames.c: * libguile/frames.h: Update macros and diagram for removal of "heap link". As part of this, we also remove "heap frames", replacing them with "vm frames", which are much like the interpreter's debug objects, but for VM stacks. That is to say, they don't actually hold the stack themselves, just the pointers into stack that's held by a continuation (either captured or current). * libguile/stacks.c (stack_depth, read_frames): Since a "stack" object is really a copy of information that comes from somewhere else, it makes sense to copy over info from the VM, just as `make-stack' does from the evaluator. The tricky bit is to figure out how to interleave VM and interpreter frames. We do that by starting in the interpreter, and whenever the current frame's procedure is actually a program, we switch to the VM stack, switching back when we reach a "bootstrap frame". The last bit is hacky, but it does work... (is_vm_bootstrap_frame): Hacky predicate to see if a VM frame is a bootstrap frame. (scm_make_stack): Accept a VM frame in addition to debug frames. Probably has some bugs in this case. But in the case that the arg is #t (a common case), do the right thing, capturing the top VM frame as well, and interleaving those frames appropriately on the stack. As an accident, we lost the ability to limit the number of frames in the backtrace. We could add that back, but personally I always want *all* frames in the trace... Narrowing still works fine, though there are some hiccups sometimes -- e.g. an outer cut to a procedure that does a tail-call in VM code will never find the cut, as it no longer exists in the continuation. * libguile/vm.h (struct scm_vm): So! Now that we have switched to save stacks in the normal make-stack, there's no more need for `this_frame' or `last_frame'. On the other hand, we can take this opportunity to fix tracing: when we're in a trace hook, we set `trace_frame' on the VM, so we know not to fire hooks when we're already in a hook. (struct scm_vm_cont): Expose this, as make-stack needs it to make VM frames from VM continuations. * libguile/vm.c (scm_vm_trace_frame): New function, gets the current trace frame. (vm_mark, make_vm): Hook up the trace frame. (vm_dispatch_hook): New hook dispatcher, with a dynwind so it does the right thing if the hook exits nonlocally. * libguile/vm-engine.c (vm_run): No more this_frame in the wind data. * libguile/vm-engine.h (RUN_HOOK): Run hooks through the dispatcher. (ALIGN_AS_NON_IMMEDIATE, POP_LIST_ON_STACK): Remove unused code. (NEW_FRAME): Adapt for no HL in the frame. * libguile/vm-i-system.c (goto/args, mv-call, return, return/values): Adapt for no HL in the frame. * module/system/vm/frame.scm: * module/system/vm/vm.scm: Beginnings of some reworkings, needs more thought.
2008-12-26 17:59:46 +01:00
Fix thread-unsafe lazy initializations. * libguile/backtrace.c (print_exception_var): New static variable. (init_print_exception_var): New static function. (scm_print_exception): Remove thread-unsafe lazy initialization. Call 'init_print_exception_var' using 'scm_i_pthread_once'. Use 'print_exception_var'. * libguile/continuations.c (call_cc): New static variable. (init_call_cc): New static function. (scm_i_call_with_current_continuation): Remove thread-unsafe lazy initialization. Call 'init_call_cc' using 'scm_i_pthread_once'. * libguile/debug.c (local_eval_var): New static variable. (init_local_eval_var): New static function. (scm_local_eval): Remove lazy initialization using mutexes. Call 'init_local_eval_var' using 'scm_i_pthread_once'. Use 'scm_variable_ref' instead of 'SCM_VARIABLE_REF'. * libguile/eval.c (map_var, for_each_var): New static variables. (init_map_var, init_for_each_var): New static functions. (scm_map, scm_for_each): Remove thread-unsafe lazy initializations. Call 'init_map_var' (or 'init_for_each_var') using 'scm_i_pthread_once'. Use 'map_var' (or 'for_each_var'). * libguile/frames.c (frame_arguments_var): New static variable. (init_frame_arguments_var): New static function. (scm_frame_arguments): Remove thread-unsafe lazy initialization. Call 'init_frame_arguments_var' using 'scm_i_pthread_once'. Use 'frame_arguments_var'. Use 'scm_variable_ref' instead of 'SCM_VARIABLE_REF'. * libguile/goops.c (delayed_compile_var): New static variable. (init_delayed_compile_var): New static function. (make_dispatch_procedure): Remove thread-unsafe lazy initialization. Call 'init_delayed_compile_var' using 'scm_i_pthread_once'. Use 'delayed_compile_var'. Use 'scm_variable_ref' instead of 'SCM_VARIABLE_REF'. * libguile/instructions.c (instructions_by_name): New static variable. (init_instructions_by_name): New static function. (scm_lookup_instruction_by_name): Remove thread-unsafe lazy initialization. Call 'init_instructions_by_name' using 'scm_i_pthread_once'. * libguile/ports.c (current_warning_port_var) (current_warning_port_once): New static variables. (init_current_warning_port_var): New static function. (scm_current_warning_port): Remove lazy initialization using mutexes. Call 'init_current_warning_port_var' using 'scm_i_pthread_once'. Use 'current_warning_port_var'. (scm_set_current_warning_port): Remove thread-unsafe lazy initialization. Call 'init_current_warning_port_var' using 'scm_i_pthread_once'. Use 'current_warning_port_var'. * libguile/strings.c (null_stringbuf): New static variable. (init_null_stringbuf): New static function. (scm_i_make_string): Remove thread-unsafe lazy initialization. Call 'init_null_stringbuf' using 'scm_i_pthread_once'. * libguile/strports.c (eval_string_var, k_module): New static variables. (init_eval_string_var_and_k_module): New static function. (scm_eval_string_in_module): Remove lazy initialization using mutexes. Call 'init_eval_string_var_and_k_module' using 'scm_i_pthread_once'. Use 'eval_string_var'. * libguile/throw.c (CACHE_VAR): Remove incorrect macro. (catch_var, throw_var, with_throw_handler_var): New static variables. (scm_catch, scm_catch_with_pre_unwind_handler): Remove thread-unsafe lazy initialization. Use 'catch_var'. (init_with_throw_handler_var): New static function. (scm_with_throw_handler): Remove thread-unsafe lazy initialization. Call 'init_with_throw_handler_var' using 'scm_i_pthread_once'. Use 'with_throw_handler_var'. (scm_throw): Remove thread-unsafe lazy initialization. Use 'throw_var'. (scm_init_throw): Initialize 'catch_var' and 'throw_var'.
2014-01-23 11:37:36 -05:00
return scm_call_1 (scm_variable_ref (frame_arguments_var), frame);
2001-04-22 02:13:48 +00:00
}
#undef FUNC_NAME
static SCM frame_call_representation_var;
static void
init_frame_call_representation_var (void)
{
frame_call_representation_var
= scm_c_private_lookup ("system vm frame", "frame-call-representation");
}
SCM scm_frame_call_representation (SCM frame)
#define FUNC_NAME "frame-call-representation"
{
static scm_i_pthread_once_t once = SCM_I_PTHREAD_ONCE_INIT;
scm_i_pthread_once (&once, init_frame_call_representation_var);
SCM_VALIDATE_VM_FRAME (1, frame);
return scm_call_1 (scm_variable_ref (frame_call_representation_var), frame);
}
#undef FUNC_NAME
SCM_DEFINE (scm_frame_source, "frame-source", 1, 0, 0,
(SCM frame),
"")
#define FUNC_NAME s_scm_frame_source
2001-04-22 02:13:48 +00:00
{
SCM_VALIDATE_VM_FRAME (1, frame);
remove heap links in VM frames, incorporate vm frames into normal backtraces * doc/ref/vm.texi (Stack Layout): Update to remove references to the "heap link". * gdbinit: Update for "heap link" removal. * libguile/frames.c: * libguile/frames.h: Update macros and diagram for removal of "heap link". As part of this, we also remove "heap frames", replacing them with "vm frames", which are much like the interpreter's debug objects, but for VM stacks. That is to say, they don't actually hold the stack themselves, just the pointers into stack that's held by a continuation (either captured or current). * libguile/stacks.c (stack_depth, read_frames): Since a "stack" object is really a copy of information that comes from somewhere else, it makes sense to copy over info from the VM, just as `make-stack' does from the evaluator. The tricky bit is to figure out how to interleave VM and interpreter frames. We do that by starting in the interpreter, and whenever the current frame's procedure is actually a program, we switch to the VM stack, switching back when we reach a "bootstrap frame". The last bit is hacky, but it does work... (is_vm_bootstrap_frame): Hacky predicate to see if a VM frame is a bootstrap frame. (scm_make_stack): Accept a VM frame in addition to debug frames. Probably has some bugs in this case. But in the case that the arg is #t (a common case), do the right thing, capturing the top VM frame as well, and interleaving those frames appropriately on the stack. As an accident, we lost the ability to limit the number of frames in the backtrace. We could add that back, but personally I always want *all* frames in the trace... Narrowing still works fine, though there are some hiccups sometimes -- e.g. an outer cut to a procedure that does a tail-call in VM code will never find the cut, as it no longer exists in the continuation. * libguile/vm.h (struct scm_vm): So! Now that we have switched to save stacks in the normal make-stack, there's no more need for `this_frame' or `last_frame'. On the other hand, we can take this opportunity to fix tracing: when we're in a trace hook, we set `trace_frame' on the VM, so we know not to fire hooks when we're already in a hook. (struct scm_vm_cont): Expose this, as make-stack needs it to make VM frames from VM continuations. * libguile/vm.c (scm_vm_trace_frame): New function, gets the current trace frame. (vm_mark, make_vm): Hook up the trace frame. (vm_dispatch_hook): New hook dispatcher, with a dynwind so it does the right thing if the hook exits nonlocally. * libguile/vm-engine.c (vm_run): No more this_frame in the wind data. * libguile/vm-engine.h (RUN_HOOK): Run hooks through the dispatcher. (ALIGN_AS_NON_IMMEDIATE, POP_LIST_ON_STACK): Remove unused code. (NEW_FRAME): Adapt for no HL in the frame. * libguile/vm-i-system.c (goto/args, mv-call, return, return/values): Adapt for no HL in the frame. * module/system/vm/frame.scm: * module/system/vm/vm.scm: Beginnings of some reworkings, needs more thought.
2008-12-26 17:59:46 +01:00
return scm_find_source_for_addr (scm_frame_instruction_pointer (frame));
2001-04-22 02:13:48 +00:00
}
#undef FUNC_NAME
2001-04-22 02:13:48 +00:00
static const char s_scm_frame_num_locals[] = "frame-num-locals";
static SCM
scm_frame_num_locals (SCM frame)
replace frame implementation with VM frames * libguile/stacks.h: Rework so that a stack doesn't copy information out of VM frames, it just holds onto a VM frame, along with the stack id and length. VM frames are now the only representation of frames in Guile. (scm_t_info_frame, SCM_FRAME_N_SLOTS, SCM_FRAME_REF, SCM_FRAME_NUMBER) (SCM_FRAME_FLAGS, SCM_FRAME_SOURCE, SCM_FRAME_PROC, SCM_FRAME_ARGS) (SCM_FRAME_PREV, SCM_FRAME_NEXT) (SCM_FRAMEF_VOID, SCM_FRAMEF_REAL, SCM_FRAMEF_PROC) (SCM_FRAMEF_EVAL_ARGS, SCM_FRAMEF_OVERFLOW) (SCM_FRAME_VOID_P, SCM_FRAME_REAL_P, SCM_FRAME_PROC_P) (SCM_FRAME_EVAL_ARGS_P, SCM_FRAME_OVERFLOW_P): Remove these macros corresponding to the old frame implementation. (scm_frame_p scm_frame_source, scm_frame_procedure) (scm_frame_arguments): These definitions are now in frames.h. (scm_last_stack_frame): Remove declaration of previously-removed constructor. Probably should re-instate it though. (scm_frame_number, scm_frame_previous, scm_frame_next) (scm_frame_real_p, scm_frame_procedure_p, scm_frame_evaluating_args_p) (scm_frame_overflow_p) : Remove these procedures corresponding to the old stack implementation. * libguile/stacks.c: Update for new frames implementation. * libguile/frames.h: * libguile/frames.c: Rename functions operating on VM frames to have a scm_frame prefix, not scm_vm_frame -- because they really are the only frames we have. Rename corresponding Scheme functions too, from vm-frame-foo to frame-foo. * libguile/deprecated.h: Remove scm_stack and scm_info_frame data types. * libguile/vm.c (vm_dispatch_hook): Adapt to scm_c_make_frame name change. * module/system/vm/frame.scm: No need to export functions provided frames.c now, as we load those procedures into the default environment now. Rename functions, and remove a couple of outdated, unused functions. The bottom half of this file is still bitrotten, though. * libguile/backtrace.c: Rework to operate on the new frame representation. Also fix a bug displaying file names for compiled procedures. * libguile/init.c: Load the VM much earlier, just because we can. Also it allows us to have frames.[ch] loaded in time for stacks to be initialized, so that scm_frame_arguments can do the right thing.
2009-12-03 13:09:58 +01:00
#define FUNC_NAME s_scm_frame_num_locals
runtime and debugging support for callee-parsed procedure args * libguile/objcodes.h: Bump for metadata format change. * libguile/frames.h: Rework so we don't frob the program's nargs, nlocs, etc at runtime. Instead we don't really know what's a local var, an argument, or an intermediate value. It's a little unfortunate, but this will allow for case-lambda, and eventually for good polymorphic generic dispatch; and the nlocs etc can be heuristically reconstructed. Such a reconstruction would be better done at the Scheme level, though. (SCM_FRAME_STACK_ADDRESS): New macro, the pointer to the base of the stack elements (not counting the program). (SCM_FRAME_UPPER_ADDRESS): Repurpose to be the address of the last element in the bookkeeping part of the stack -- i.e. to point to the return address. * libguile/vm-engine.h: * libguile/vm-i-system.c: Adapt to removal of stack_base. Though we still detect stack-smashing underflow, we don't do so as precisely as we did before, because now we only detect overwriting of the frame metadata. * libguile/vm-engine.c (vm_engine): Remove the stack_base variable. It is unnecessary, and difficult to keep track of in the face of case-lambda. Also fix miscommented "ra" and "mvra" pushes. Push the vp->ip as the first ra... * libguile/vm-i-system.c (halt): ...because here we can restore the vp->ip instead of setting ip to 0. Allows us to introspect ips all down the stack, including in recursive VM invocations. * libguile/frames.h: * libguile/frames.c (scm_vm_frame_stack): Removed, because it's getting more difficult to tell what's an argument and what's a temporary stack element. (scm_vm_frame_num_locals): New accessor. (scm_vm_frame_instruction_pointer): New accessor. (scm_vm_frame_arguments): Defer to an implementation in Scheme. (scm_vm_frame_num_locals scm_vm_frame_local_ref) (scm_vm_frame_local_set_x): Since we can get not-yet-active frames on the stack now, with our current calling convention, we have to add a heuristic here to jump over those frames -- because frames have pointers in them, not Scheme values. * libguile/programs.h: * libguile/programs.c (scm_program_arity): Remove, in favor of.. (scm_program_arities): ...this, which a list of arities, in a new format, occupying a slot in the metadata. * module/language/assembly/decompile-bytecode.scm (decode-load-program): Fix mv-call decompilation. * module/system/vm/frame.scm (vm-frame-bindings, vm-frame-binding-ref) (vm-frame-binding-set!): New functions, to access bindings by name in a frame. (vm-frame-arguments): Function now implemented in Scheme. Commented fairly extensively. * module/system/vm/program.scm (program-bindings-by-index) (program-bindings-for-ip): New accessors, parsing the program bindings metadata into something more useful. (program-arities, program-arguments): In a case-lambda world, we have to assume that programs can have multiple arities. But it's tough to detect this algorithmically; instead we're going to require that the program metadata include information about the arities, and the parts of the program that that metadata applies to. (program-lambda-list): New accessor. (write-program): Show multiple arities. * module/language/glil/compile-assembly.scm (glil->assembly): Add "arities" to the state of the compiler, and add arities entries as appropriate.
2009-09-27 19:25:58 -04:00
{
VM stack grows downward Adapt VM stack to grow downward. This will make native compilation look more like the VM code, as we will be able to use native CALL instructions, taking proper advantage of the return address buffer. * libguile/continuations.c (scm_i_continuation_to_frame): Record offsets from stack top. * libguile/control.c (scm_i_prompt_pop_abort_args_x): Adapt for reversed order of arguments, and instead of relying on the abort to push on the number of arguments, make the caller save the stack depth, which allows us to compute the number of arguments ourselves. (reify_partial_continuation, scm_c_abort): Adapt to reversed stack order. * libguile/dynstack.c (scm_dynstack_wind_prompt): Since we wind the stack in a downward direction, subtract the reloc instead of adding it. * libguile/dynstack.h (SCM_F_DYNSTACK_PROMPT_ESCAPE_ONLY): Remove flag; instead rely on prompt-establishing code to save the stack depth. * libguile/eval.c (eval): Remove extraneous "volatile" declarations for variables that are not re-set between the setjmp and any longjmp. Adapt to save stack depth before instating the prompt. * libguile/foreign.c (scm_i_foreign_call): Adapt to receive arguments in reverse order. * libguile/frames.c (frame_stack_top, scm_i_frame_stack_top): Adapt to compute stack top instead of stack bottom. (scm_c_frame_closure): Adapt to stack growth change. (scm_frame_num_locals, scm_frame_local_ref, scm_frame_set_x): Use union data type to access stack. (RELOC): Reformat. (scm_c_frame_previous): Adapt to stack growth change. * libguile/frames.h: Adapt stack diagram to indicate that the stack grows up. (union scm_vm_stack_element): New data type used to access items on the stack. (SCM_FRAME_PREVIOUS_SP) (SCM_FRAME_RETURN_ADDRESS, SCM_FRAME_SET_RETURN_ADDRESS) (SCM_FRAME_DYNAMIC_LINK, SCM_FRAME_SET_DYNAMIC_LINK) (SCM_FRAME_LOCAL, SCM_FRAME_NUM_LOCALS): Adapt to stack representation change. (SCM_FRAME_SLOT): New helper. (SCM_VM_FRAME_FP, SCM_VM_FRAME_SP): Adapt to stack growth change. * libguile/stacks.c (scm_make_stack): Record offsets from top of stack. * libguile/throw.c (catch): Adapt to scm_i_prompt_pop_abort_args_x change. * libguile/vm-engine.c (ALLOC_FRAME, RESET_FRAME): (FRAME_LOCALS_COUNT_FROM): Adapt to stack growth change. (LOCAL_ADDRESS): Use SCM_FRAME_SLOT to get the address as the proper data type. (RETURN_ONE_VALUE, RETURN_VALUE_LIST): Adapt to stack growth change. (apply): Shuffling up the SMOB apply args can cause the stack to expand, so use ALLOC_FRAME instead of RESET_FRAME. (vm_engine): Adapt for stack growth change. * libguile/vm.c (vm_increase_sp, vm_push_sp, vm_restore_sp): Adapt to stack representation change. (scm_i_vm_cont_to_frame): Adapt to take offsets from the top. (scm_i_vm_capture_stack): Adapt to capture from the top. (vm_return_to_continuation_inner): Adapt for data type changes. (vm_return_to_continuation): Likewise, and instead of looping, just splat the saved arguments on with memcpy. (vm_dispatch_hook): Adapt to receive arguments in the reverse order. Adapt callers. (vm_abort): There is never a tail argument. Adapt to stack representation change. (vm_reinstate_partial_continuation) (vm_reinstate_partial_continuation_inner): Adapt to stack growth change. (allocate_stack, free_stack): Adapt to data type change. (expand_stack): Don't try to mremap(), as you can't grow a mapping from the bottom. Without knowing that there's a free mapping space right below the old stack, which there usually isn't on Linux, we have to copy. We can't use MAP_GROWSDOWN because Linux is buggy. (make_vm): Adapt to stack representation changes. (return_unused_stack_to_os): Round down instead of up, as the stack grows down. (scm_i_vm_mark_stack): Adapt to walk up the stack. (scm_i_vm_free_stack): Adapt to scm_vm changes. (vm_expand_stack_inner, reset_stack_limit, vm_expand_stack): Adapt to the stack growing down. (scm_call_n): Adapt to the stack growing down. Don't allow argv to point into the stack. * libguile/vm.h (struct scm_vm, struct scm_vm_cont): Adapt to hold the stack top and bottom.
2015-09-22 10:24:30 +00:00
union scm_vm_stack_element *fp, *sp;
runtime and debugging support for callee-parsed procedure args * libguile/objcodes.h: Bump for metadata format change. * libguile/frames.h: Rework so we don't frob the program's nargs, nlocs, etc at runtime. Instead we don't really know what's a local var, an argument, or an intermediate value. It's a little unfortunate, but this will allow for case-lambda, and eventually for good polymorphic generic dispatch; and the nlocs etc can be heuristically reconstructed. Such a reconstruction would be better done at the Scheme level, though. (SCM_FRAME_STACK_ADDRESS): New macro, the pointer to the base of the stack elements (not counting the program). (SCM_FRAME_UPPER_ADDRESS): Repurpose to be the address of the last element in the bookkeeping part of the stack -- i.e. to point to the return address. * libguile/vm-engine.h: * libguile/vm-i-system.c: Adapt to removal of stack_base. Though we still detect stack-smashing underflow, we don't do so as precisely as we did before, because now we only detect overwriting of the frame metadata. * libguile/vm-engine.c (vm_engine): Remove the stack_base variable. It is unnecessary, and difficult to keep track of in the face of case-lambda. Also fix miscommented "ra" and "mvra" pushes. Push the vp->ip as the first ra... * libguile/vm-i-system.c (halt): ...because here we can restore the vp->ip instead of setting ip to 0. Allows us to introspect ips all down the stack, including in recursive VM invocations. * libguile/frames.h: * libguile/frames.c (scm_vm_frame_stack): Removed, because it's getting more difficult to tell what's an argument and what's a temporary stack element. (scm_vm_frame_num_locals): New accessor. (scm_vm_frame_instruction_pointer): New accessor. (scm_vm_frame_arguments): Defer to an implementation in Scheme. (scm_vm_frame_num_locals scm_vm_frame_local_ref) (scm_vm_frame_local_set_x): Since we can get not-yet-active frames on the stack now, with our current calling convention, we have to add a heuristic here to jump over those frames -- because frames have pointers in them, not Scheme values. * libguile/programs.h: * libguile/programs.c (scm_program_arity): Remove, in favor of.. (scm_program_arities): ...this, which a list of arities, in a new format, occupying a slot in the metadata. * module/language/assembly/decompile-bytecode.scm (decode-load-program): Fix mv-call decompilation. * module/system/vm/frame.scm (vm-frame-bindings, vm-frame-binding-ref) (vm-frame-binding-set!): New functions, to access bindings by name in a frame. (vm-frame-arguments): Function now implemented in Scheme. Commented fairly extensively. * module/system/vm/program.scm (program-bindings-by-index) (program-bindings-for-ip): New accessors, parsing the program bindings metadata into something more useful. (program-arities, program-arguments): In a case-lambda world, we have to assume that programs can have multiple arities. But it's tough to detect this algorithmically; instead we're going to require that the program metadata include information about the arities, and the parts of the program that that metadata applies to. (program-lambda-list): New accessor. (write-program): Show multiple arities. * module/language/glil/compile-assembly.scm (glil->assembly): Add "arities" to the state of the compiler, and add arities entries as appropriate.
2009-09-27 19:25:58 -04:00
SCM_VALIDATE_VM_FRAME (1, frame);
Frame pointer points to local 0 instead of local 1 * libguile/frames.h: Change so that fp points at local 0 instead of local 1, and clean up a bit. (struct scm_vm_frame): Remove program, and rename stack to locals. (SCM_FRAME_DATA_ADDRESS): Remove; it was redundant with SCM_FRAME_LOWER_ADDRESS. (SCM_FRAME_STACK_ADDRESS): Remove; replace with the new SCM_FRAME_LOCALS_ADDRESS. (SCM_FRAME_UPPER_ADDRESS): Remove; unused. (SCM_FRAME_NUM_LOCALS, SCM_FRAME_PREVIOUS_SP): New defines. (SCM_FRAME_BYTE_CAST, SCM_FRAME_STACK_CAST): Remove; unused; (SCM_FRAME_LOCAL): New define, replaces SCM_FRAME_VARIABLE. (SCM_FRAME_PROGRAM): Add cautionary commentary. * libguile/frames.c: Adapt static asserts. (scm_frame_num_locals, scm_frame_local_ref, scm_frame_local_set_x): Adapt. This means that frame-local-ref 0 now returns the procedure. * libguile/vm-engine.c (ALLOC_FRAME, RESET_FRAME) (FRAME_LOCALS_COUNT, LOCAL_REF, LOCAL_SET, RETURN_VALUE_LIST): Adapt to change in fp. (LOCAL_ADDRESS): New helper. (POP_CONTINUATION_HOOK): Reimplement, taking the previous FP as an argument. (ABORT_CONTINUATION_HOOK): Reimplement, taking no arguments. (RETURN_ONE_VALUE): Reimplement. (RETURN_VALUE_LIST): Adapt to FP change. (halt, return-values, subr-call, foreign-call, prompt) (continuation-call, compose-continuation, call/cc, abort): Adapt to FP change, mostly via using LOCAL_ADDRESS, etc abstractions instead of using the raw frame pointer. * libguile/control.c (reify_partial_continuation): Update for fp change. * libguile/vm.c (vm_reinstate_partial_continuation): Adapt to removal of SCM_FRAME_UPPER_ADDRESS. * module/system/vm/frame.scm (frame-call-representation): Adapt to frame-local-ref change. * module/system/vm/trace.scm (print-return): Remove unused frame-num-locals call.
2013-11-17 22:07:44 +01:00
fp = SCM_VM_FRAME_FP (frame);
sp = SCM_VM_FRAME_SP (frame);
Frame pointer points to local 0 instead of local 1 * libguile/frames.h: Change so that fp points at local 0 instead of local 1, and clean up a bit. (struct scm_vm_frame): Remove program, and rename stack to locals. (SCM_FRAME_DATA_ADDRESS): Remove; it was redundant with SCM_FRAME_LOWER_ADDRESS. (SCM_FRAME_STACK_ADDRESS): Remove; replace with the new SCM_FRAME_LOCALS_ADDRESS. (SCM_FRAME_UPPER_ADDRESS): Remove; unused. (SCM_FRAME_NUM_LOCALS, SCM_FRAME_PREVIOUS_SP): New defines. (SCM_FRAME_BYTE_CAST, SCM_FRAME_STACK_CAST): Remove; unused; (SCM_FRAME_LOCAL): New define, replaces SCM_FRAME_VARIABLE. (SCM_FRAME_PROGRAM): Add cautionary commentary. * libguile/frames.c: Adapt static asserts. (scm_frame_num_locals, scm_frame_local_ref, scm_frame_local_set_x): Adapt. This means that frame-local-ref 0 now returns the procedure. * libguile/vm-engine.c (ALLOC_FRAME, RESET_FRAME) (FRAME_LOCALS_COUNT, LOCAL_REF, LOCAL_SET, RETURN_VALUE_LIST): Adapt to change in fp. (LOCAL_ADDRESS): New helper. (POP_CONTINUATION_HOOK): Reimplement, taking the previous FP as an argument. (ABORT_CONTINUATION_HOOK): Reimplement, taking no arguments. (RETURN_ONE_VALUE): Reimplement. (RETURN_VALUE_LIST): Adapt to FP change. (halt, return-values, subr-call, foreign-call, prompt) (continuation-call, compose-continuation, call/cc, abort): Adapt to FP change, mostly via using LOCAL_ADDRESS, etc abstractions instead of using the raw frame pointer. * libguile/control.c (reify_partial_continuation): Update for fp change. * libguile/vm.c (vm_reinstate_partial_continuation): Adapt to removal of SCM_FRAME_UPPER_ADDRESS. * module/system/vm/frame.scm (frame-call-representation): Adapt to frame-local-ref change. * module/system/vm/trace.scm (print-return): Remove unused frame-num-locals call.
2013-11-17 22:07:44 +01:00
return scm_from_ptrdiff_t (SCM_FRAME_NUM_LOCALS (fp, sp));
runtime and debugging support for callee-parsed procedure args * libguile/objcodes.h: Bump for metadata format change. * libguile/frames.h: Rework so we don't frob the program's nargs, nlocs, etc at runtime. Instead we don't really know what's a local var, an argument, or an intermediate value. It's a little unfortunate, but this will allow for case-lambda, and eventually for good polymorphic generic dispatch; and the nlocs etc can be heuristically reconstructed. Such a reconstruction would be better done at the Scheme level, though. (SCM_FRAME_STACK_ADDRESS): New macro, the pointer to the base of the stack elements (not counting the program). (SCM_FRAME_UPPER_ADDRESS): Repurpose to be the address of the last element in the bookkeeping part of the stack -- i.e. to point to the return address. * libguile/vm-engine.h: * libguile/vm-i-system.c: Adapt to removal of stack_base. Though we still detect stack-smashing underflow, we don't do so as precisely as we did before, because now we only detect overwriting of the frame metadata. * libguile/vm-engine.c (vm_engine): Remove the stack_base variable. It is unnecessary, and difficult to keep track of in the face of case-lambda. Also fix miscommented "ra" and "mvra" pushes. Push the vp->ip as the first ra... * libguile/vm-i-system.c (halt): ...because here we can restore the vp->ip instead of setting ip to 0. Allows us to introspect ips all down the stack, including in recursive VM invocations. * libguile/frames.h: * libguile/frames.c (scm_vm_frame_stack): Removed, because it's getting more difficult to tell what's an argument and what's a temporary stack element. (scm_vm_frame_num_locals): New accessor. (scm_vm_frame_instruction_pointer): New accessor. (scm_vm_frame_arguments): Defer to an implementation in Scheme. (scm_vm_frame_num_locals scm_vm_frame_local_ref) (scm_vm_frame_local_set_x): Since we can get not-yet-active frames on the stack now, with our current calling convention, we have to add a heuristic here to jump over those frames -- because frames have pointers in them, not Scheme values. * libguile/programs.h: * libguile/programs.c (scm_program_arity): Remove, in favor of.. (scm_program_arities): ...this, which a list of arities, in a new format, occupying a slot in the metadata. * module/language/assembly/decompile-bytecode.scm (decode-load-program): Fix mv-call decompilation. * module/system/vm/frame.scm (vm-frame-bindings, vm-frame-binding-ref) (vm-frame-binding-set!): New functions, to access bindings by name in a frame. (vm-frame-arguments): Function now implemented in Scheme. Commented fairly extensively. * module/system/vm/program.scm (program-bindings-by-index) (program-bindings-for-ip): New accessors, parsing the program bindings metadata into something more useful. (program-arities, program-arguments): In a case-lambda world, we have to assume that programs can have multiple arities. But it's tough to detect this algorithmically; instead we're going to require that the program metadata include information about the arities, and the parts of the program that that metadata applies to. (program-lambda-list): New accessor. (write-program): Show multiple arities. * module/language/glil/compile-assembly.scm (glil->assembly): Add "arities" to the state of the compiler, and add arities entries as appropriate.
2009-09-27 19:25:58 -04:00
}
#undef FUNC_NAME
enum stack_item_representation
{
STACK_ITEM_SCM = 0,
STACK_ITEM_F64 = 1,
STACK_ITEM_U64 = 2,
STACK_ITEM_S64 = 3
};
static enum stack_item_representation
scm_to_stack_item_representation (SCM x, const char *subr, int pos)
{
if (scm_is_eq (x, scm_from_latin1_symbol ("scm")))
return STACK_ITEM_SCM;
if (scm_is_eq (x, scm_from_latin1_symbol ("f64")))
return STACK_ITEM_F64;
if (scm_is_eq (x, scm_from_latin1_symbol ("u64")))
return STACK_ITEM_U64;
if (scm_is_eq (x, scm_from_latin1_symbol ("s64")))
return STACK_ITEM_S64;
scm_wrong_type_arg (subr, pos, x);
return 0; /* Not reached. */
}
static const char s_scm_frame_local_ref[] = "frame-local-ref";
static SCM
scm_frame_local_ref (SCM frame, SCM index, SCM representation)
replace frame implementation with VM frames * libguile/stacks.h: Rework so that a stack doesn't copy information out of VM frames, it just holds onto a VM frame, along with the stack id and length. VM frames are now the only representation of frames in Guile. (scm_t_info_frame, SCM_FRAME_N_SLOTS, SCM_FRAME_REF, SCM_FRAME_NUMBER) (SCM_FRAME_FLAGS, SCM_FRAME_SOURCE, SCM_FRAME_PROC, SCM_FRAME_ARGS) (SCM_FRAME_PREV, SCM_FRAME_NEXT) (SCM_FRAMEF_VOID, SCM_FRAMEF_REAL, SCM_FRAMEF_PROC) (SCM_FRAMEF_EVAL_ARGS, SCM_FRAMEF_OVERFLOW) (SCM_FRAME_VOID_P, SCM_FRAME_REAL_P, SCM_FRAME_PROC_P) (SCM_FRAME_EVAL_ARGS_P, SCM_FRAME_OVERFLOW_P): Remove these macros corresponding to the old frame implementation. (scm_frame_p scm_frame_source, scm_frame_procedure) (scm_frame_arguments): These definitions are now in frames.h. (scm_last_stack_frame): Remove declaration of previously-removed constructor. Probably should re-instate it though. (scm_frame_number, scm_frame_previous, scm_frame_next) (scm_frame_real_p, scm_frame_procedure_p, scm_frame_evaluating_args_p) (scm_frame_overflow_p) : Remove these procedures corresponding to the old stack implementation. * libguile/stacks.c: Update for new frames implementation. * libguile/frames.h: * libguile/frames.c: Rename functions operating on VM frames to have a scm_frame prefix, not scm_vm_frame -- because they really are the only frames we have. Rename corresponding Scheme functions too, from vm-frame-foo to frame-foo. * libguile/deprecated.h: Remove scm_stack and scm_info_frame data types. * libguile/vm.c (vm_dispatch_hook): Adapt to scm_c_make_frame name change. * module/system/vm/frame.scm: No need to export functions provided frames.c now, as we load those procedures into the default environment now. Rename functions, and remove a couple of outdated, unused functions. The bottom half of this file is still bitrotten, though. * libguile/backtrace.c: Rework to operate on the new frame representation. Also fix a bug displaying file names for compiled procedures. * libguile/init.c: Load the VM much earlier, just because we can. Also it allows us to have frames.[ch] loaded in time for stacks to be initialized, so that scm_frame_arguments can do the right thing.
2009-12-03 13:09:58 +01:00
#define FUNC_NAME s_scm_frame_local_ref
2001-04-22 02:13:48 +00:00
{
VM stack grows downward Adapt VM stack to grow downward. This will make native compilation look more like the VM code, as we will be able to use native CALL instructions, taking proper advantage of the return address buffer. * libguile/continuations.c (scm_i_continuation_to_frame): Record offsets from stack top. * libguile/control.c (scm_i_prompt_pop_abort_args_x): Adapt for reversed order of arguments, and instead of relying on the abort to push on the number of arguments, make the caller save the stack depth, which allows us to compute the number of arguments ourselves. (reify_partial_continuation, scm_c_abort): Adapt to reversed stack order. * libguile/dynstack.c (scm_dynstack_wind_prompt): Since we wind the stack in a downward direction, subtract the reloc instead of adding it. * libguile/dynstack.h (SCM_F_DYNSTACK_PROMPT_ESCAPE_ONLY): Remove flag; instead rely on prompt-establishing code to save the stack depth. * libguile/eval.c (eval): Remove extraneous "volatile" declarations for variables that are not re-set between the setjmp and any longjmp. Adapt to save stack depth before instating the prompt. * libguile/foreign.c (scm_i_foreign_call): Adapt to receive arguments in reverse order. * libguile/frames.c (frame_stack_top, scm_i_frame_stack_top): Adapt to compute stack top instead of stack bottom. (scm_c_frame_closure): Adapt to stack growth change. (scm_frame_num_locals, scm_frame_local_ref, scm_frame_set_x): Use union data type to access stack. (RELOC): Reformat. (scm_c_frame_previous): Adapt to stack growth change. * libguile/frames.h: Adapt stack diagram to indicate that the stack grows up. (union scm_vm_stack_element): New data type used to access items on the stack. (SCM_FRAME_PREVIOUS_SP) (SCM_FRAME_RETURN_ADDRESS, SCM_FRAME_SET_RETURN_ADDRESS) (SCM_FRAME_DYNAMIC_LINK, SCM_FRAME_SET_DYNAMIC_LINK) (SCM_FRAME_LOCAL, SCM_FRAME_NUM_LOCALS): Adapt to stack representation change. (SCM_FRAME_SLOT): New helper. (SCM_VM_FRAME_FP, SCM_VM_FRAME_SP): Adapt to stack growth change. * libguile/stacks.c (scm_make_stack): Record offsets from top of stack. * libguile/throw.c (catch): Adapt to scm_i_prompt_pop_abort_args_x change. * libguile/vm-engine.c (ALLOC_FRAME, RESET_FRAME): (FRAME_LOCALS_COUNT_FROM): Adapt to stack growth change. (LOCAL_ADDRESS): Use SCM_FRAME_SLOT to get the address as the proper data type. (RETURN_ONE_VALUE, RETURN_VALUE_LIST): Adapt to stack growth change. (apply): Shuffling up the SMOB apply args can cause the stack to expand, so use ALLOC_FRAME instead of RESET_FRAME. (vm_engine): Adapt for stack growth change. * libguile/vm.c (vm_increase_sp, vm_push_sp, vm_restore_sp): Adapt to stack representation change. (scm_i_vm_cont_to_frame): Adapt to take offsets from the top. (scm_i_vm_capture_stack): Adapt to capture from the top. (vm_return_to_continuation_inner): Adapt for data type changes. (vm_return_to_continuation): Likewise, and instead of looping, just splat the saved arguments on with memcpy. (vm_dispatch_hook): Adapt to receive arguments in the reverse order. Adapt callers. (vm_abort): There is never a tail argument. Adapt to stack representation change. (vm_reinstate_partial_continuation) (vm_reinstate_partial_continuation_inner): Adapt to stack growth change. (allocate_stack, free_stack): Adapt to data type change. (expand_stack): Don't try to mremap(), as you can't grow a mapping from the bottom. Without knowing that there's a free mapping space right below the old stack, which there usually isn't on Linux, we have to copy. We can't use MAP_GROWSDOWN because Linux is buggy. (make_vm): Adapt to stack representation changes. (return_unused_stack_to_os): Round down instead of up, as the stack grows down. (scm_i_vm_mark_stack): Adapt to walk up the stack. (scm_i_vm_free_stack): Adapt to scm_vm changes. (vm_expand_stack_inner, reset_stack_limit, vm_expand_stack): Adapt to the stack growing down. (scm_call_n): Adapt to the stack growing down. Don't allow argv to point into the stack. * libguile/vm.h (struct scm_vm, struct scm_vm_cont): Adapt to hold the stack top and bottom.
2015-09-22 10:24:30 +00:00
union scm_vm_stack_element *fp, *sp;
remove heap links in VM frames, incorporate vm frames into normal backtraces * doc/ref/vm.texi (Stack Layout): Update to remove references to the "heap link". * gdbinit: Update for "heap link" removal. * libguile/frames.c: * libguile/frames.h: Update macros and diagram for removal of "heap link". As part of this, we also remove "heap frames", replacing them with "vm frames", which are much like the interpreter's debug objects, but for VM stacks. That is to say, they don't actually hold the stack themselves, just the pointers into stack that's held by a continuation (either captured or current). * libguile/stacks.c (stack_depth, read_frames): Since a "stack" object is really a copy of information that comes from somewhere else, it makes sense to copy over info from the VM, just as `make-stack' does from the evaluator. The tricky bit is to figure out how to interleave VM and interpreter frames. We do that by starting in the interpreter, and whenever the current frame's procedure is actually a program, we switch to the VM stack, switching back when we reach a "bootstrap frame". The last bit is hacky, but it does work... (is_vm_bootstrap_frame): Hacky predicate to see if a VM frame is a bootstrap frame. (scm_make_stack): Accept a VM frame in addition to debug frames. Probably has some bugs in this case. But in the case that the arg is #t (a common case), do the right thing, capturing the top VM frame as well, and interleaving those frames appropriately on the stack. As an accident, we lost the ability to limit the number of frames in the backtrace. We could add that back, but personally I always want *all* frames in the trace... Narrowing still works fine, though there are some hiccups sometimes -- e.g. an outer cut to a procedure that does a tail-call in VM code will never find the cut, as it no longer exists in the continuation. * libguile/vm.h (struct scm_vm): So! Now that we have switched to save stacks in the normal make-stack, there's no more need for `this_frame' or `last_frame'. On the other hand, we can take this opportunity to fix tracing: when we're in a trace hook, we set `trace_frame' on the VM, so we know not to fire hooks when we're already in a hook. (struct scm_vm_cont): Expose this, as make-stack needs it to make VM frames from VM continuations. * libguile/vm.c (scm_vm_trace_frame): New function, gets the current trace frame. (vm_mark, make_vm): Hook up the trace frame. (vm_dispatch_hook): New hook dispatcher, with a dynwind so it does the right thing if the hook exits nonlocally. * libguile/vm-engine.c (vm_run): No more this_frame in the wind data. * libguile/vm-engine.h (RUN_HOOK): Run hooks through the dispatcher. (ALIGN_AS_NON_IMMEDIATE, POP_LIST_ON_STACK): Remove unused code. (NEW_FRAME): Adapt for no HL in the frame. * libguile/vm-i-system.c (goto/args, mv-call, return, return/values): Adapt for no HL in the frame. * module/system/vm/frame.scm: * module/system/vm/vm.scm: Beginnings of some reworkings, needs more thought.
2008-12-26 17:59:46 +01:00
unsigned int i;
enum stack_item_representation repr;
remove heap links in VM frames, incorporate vm frames into normal backtraces * doc/ref/vm.texi (Stack Layout): Update to remove references to the "heap link". * gdbinit: Update for "heap link" removal. * libguile/frames.c: * libguile/frames.h: Update macros and diagram for removal of "heap link". As part of this, we also remove "heap frames", replacing them with "vm frames", which are much like the interpreter's debug objects, but for VM stacks. That is to say, they don't actually hold the stack themselves, just the pointers into stack that's held by a continuation (either captured or current). * libguile/stacks.c (stack_depth, read_frames): Since a "stack" object is really a copy of information that comes from somewhere else, it makes sense to copy over info from the VM, just as `make-stack' does from the evaluator. The tricky bit is to figure out how to interleave VM and interpreter frames. We do that by starting in the interpreter, and whenever the current frame's procedure is actually a program, we switch to the VM stack, switching back when we reach a "bootstrap frame". The last bit is hacky, but it does work... (is_vm_bootstrap_frame): Hacky predicate to see if a VM frame is a bootstrap frame. (scm_make_stack): Accept a VM frame in addition to debug frames. Probably has some bugs in this case. But in the case that the arg is #t (a common case), do the right thing, capturing the top VM frame as well, and interleaving those frames appropriately on the stack. As an accident, we lost the ability to limit the number of frames in the backtrace. We could add that back, but personally I always want *all* frames in the trace... Narrowing still works fine, though there are some hiccups sometimes -- e.g. an outer cut to a procedure that does a tail-call in VM code will never find the cut, as it no longer exists in the continuation. * libguile/vm.h (struct scm_vm): So! Now that we have switched to save stacks in the normal make-stack, there's no more need for `this_frame' or `last_frame'. On the other hand, we can take this opportunity to fix tracing: when we're in a trace hook, we set `trace_frame' on the VM, so we know not to fire hooks when we're already in a hook. (struct scm_vm_cont): Expose this, as make-stack needs it to make VM frames from VM continuations. * libguile/vm.c (scm_vm_trace_frame): New function, gets the current trace frame. (vm_mark, make_vm): Hook up the trace frame. (vm_dispatch_hook): New hook dispatcher, with a dynwind so it does the right thing if the hook exits nonlocally. * libguile/vm-engine.c (vm_run): No more this_frame in the wind data. * libguile/vm-engine.h (RUN_HOOK): Run hooks through the dispatcher. (ALIGN_AS_NON_IMMEDIATE, POP_LIST_ON_STACK): Remove unused code. (NEW_FRAME): Adapt for no HL in the frame. * libguile/vm-i-system.c (goto/args, mv-call, return, return/values): Adapt for no HL in the frame. * module/system/vm/frame.scm: * module/system/vm/vm.scm: Beginnings of some reworkings, needs more thought.
2008-12-26 17:59:46 +01:00
runtime and debugging support for callee-parsed procedure args * libguile/objcodes.h: Bump for metadata format change. * libguile/frames.h: Rework so we don't frob the program's nargs, nlocs, etc at runtime. Instead we don't really know what's a local var, an argument, or an intermediate value. It's a little unfortunate, but this will allow for case-lambda, and eventually for good polymorphic generic dispatch; and the nlocs etc can be heuristically reconstructed. Such a reconstruction would be better done at the Scheme level, though. (SCM_FRAME_STACK_ADDRESS): New macro, the pointer to the base of the stack elements (not counting the program). (SCM_FRAME_UPPER_ADDRESS): Repurpose to be the address of the last element in the bookkeeping part of the stack -- i.e. to point to the return address. * libguile/vm-engine.h: * libguile/vm-i-system.c: Adapt to removal of stack_base. Though we still detect stack-smashing underflow, we don't do so as precisely as we did before, because now we only detect overwriting of the frame metadata. * libguile/vm-engine.c (vm_engine): Remove the stack_base variable. It is unnecessary, and difficult to keep track of in the face of case-lambda. Also fix miscommented "ra" and "mvra" pushes. Push the vp->ip as the first ra... * libguile/vm-i-system.c (halt): ...because here we can restore the vp->ip instead of setting ip to 0. Allows us to introspect ips all down the stack, including in recursive VM invocations. * libguile/frames.h: * libguile/frames.c (scm_vm_frame_stack): Removed, because it's getting more difficult to tell what's an argument and what's a temporary stack element. (scm_vm_frame_num_locals): New accessor. (scm_vm_frame_instruction_pointer): New accessor. (scm_vm_frame_arguments): Defer to an implementation in Scheme. (scm_vm_frame_num_locals scm_vm_frame_local_ref) (scm_vm_frame_local_set_x): Since we can get not-yet-active frames on the stack now, with our current calling convention, we have to add a heuristic here to jump over those frames -- because frames have pointers in them, not Scheme values. * libguile/programs.h: * libguile/programs.c (scm_program_arity): Remove, in favor of.. (scm_program_arities): ...this, which a list of arities, in a new format, occupying a slot in the metadata. * module/language/assembly/decompile-bytecode.scm (decode-load-program): Fix mv-call decompilation. * module/system/vm/frame.scm (vm-frame-bindings, vm-frame-binding-ref) (vm-frame-binding-set!): New functions, to access bindings by name in a frame. (vm-frame-arguments): Function now implemented in Scheme. Commented fairly extensively. * module/system/vm/program.scm (program-bindings-by-index) (program-bindings-for-ip): New accessors, parsing the program bindings metadata into something more useful. (program-arities, program-arguments): In a case-lambda world, we have to assume that programs can have multiple arities. But it's tough to detect this algorithmically; instead we're going to require that the program metadata include information about the arities, and the parts of the program that that metadata applies to. (program-lambda-list): New accessor. (write-program): Show multiple arities. * module/language/glil/compile-assembly.scm (glil->assembly): Add "arities" to the state of the compiler, and add arities entries as appropriate.
2009-09-27 19:25:58 -04:00
SCM_VALIDATE_VM_FRAME (1, frame);
remove heap links in VM frames, incorporate vm frames into normal backtraces * doc/ref/vm.texi (Stack Layout): Update to remove references to the "heap link". * gdbinit: Update for "heap link" removal. * libguile/frames.c: * libguile/frames.h: Update macros and diagram for removal of "heap link". As part of this, we also remove "heap frames", replacing them with "vm frames", which are much like the interpreter's debug objects, but for VM stacks. That is to say, they don't actually hold the stack themselves, just the pointers into stack that's held by a continuation (either captured or current). * libguile/stacks.c (stack_depth, read_frames): Since a "stack" object is really a copy of information that comes from somewhere else, it makes sense to copy over info from the VM, just as `make-stack' does from the evaluator. The tricky bit is to figure out how to interleave VM and interpreter frames. We do that by starting in the interpreter, and whenever the current frame's procedure is actually a program, we switch to the VM stack, switching back when we reach a "bootstrap frame". The last bit is hacky, but it does work... (is_vm_bootstrap_frame): Hacky predicate to see if a VM frame is a bootstrap frame. (scm_make_stack): Accept a VM frame in addition to debug frames. Probably has some bugs in this case. But in the case that the arg is #t (a common case), do the right thing, capturing the top VM frame as well, and interleaving those frames appropriately on the stack. As an accident, we lost the ability to limit the number of frames in the backtrace. We could add that back, but personally I always want *all* frames in the trace... Narrowing still works fine, though there are some hiccups sometimes -- e.g. an outer cut to a procedure that does a tail-call in VM code will never find the cut, as it no longer exists in the continuation. * libguile/vm.h (struct scm_vm): So! Now that we have switched to save stacks in the normal make-stack, there's no more need for `this_frame' or `last_frame'. On the other hand, we can take this opportunity to fix tracing: when we're in a trace hook, we set `trace_frame' on the VM, so we know not to fire hooks when we're already in a hook. (struct scm_vm_cont): Expose this, as make-stack needs it to make VM frames from VM continuations. * libguile/vm.c (scm_vm_trace_frame): New function, gets the current trace frame. (vm_mark, make_vm): Hook up the trace frame. (vm_dispatch_hook): New hook dispatcher, with a dynwind so it does the right thing if the hook exits nonlocally. * libguile/vm-engine.c (vm_run): No more this_frame in the wind data. * libguile/vm-engine.h (RUN_HOOK): Run hooks through the dispatcher. (ALIGN_AS_NON_IMMEDIATE, POP_LIST_ON_STACK): Remove unused code. (NEW_FRAME): Adapt for no HL in the frame. * libguile/vm-i-system.c (goto/args, mv-call, return, return/values): Adapt for no HL in the frame. * module/system/vm/frame.scm: * module/system/vm/vm.scm: Beginnings of some reworkings, needs more thought.
2008-12-26 17:59:46 +01:00
SCM_VALIDATE_UINT_COPY (2, index, i);
repr = scm_to_stack_item_representation (representation, FUNC_NAME, SCM_ARG3);
remove heap links in VM frames, incorporate vm frames into normal backtraces * doc/ref/vm.texi (Stack Layout): Update to remove references to the "heap link". * gdbinit: Update for "heap link" removal. * libguile/frames.c: * libguile/frames.h: Update macros and diagram for removal of "heap link". As part of this, we also remove "heap frames", replacing them with "vm frames", which are much like the interpreter's debug objects, but for VM stacks. That is to say, they don't actually hold the stack themselves, just the pointers into stack that's held by a continuation (either captured or current). * libguile/stacks.c (stack_depth, read_frames): Since a "stack" object is really a copy of information that comes from somewhere else, it makes sense to copy over info from the VM, just as `make-stack' does from the evaluator. The tricky bit is to figure out how to interleave VM and interpreter frames. We do that by starting in the interpreter, and whenever the current frame's procedure is actually a program, we switch to the VM stack, switching back when we reach a "bootstrap frame". The last bit is hacky, but it does work... (is_vm_bootstrap_frame): Hacky predicate to see if a VM frame is a bootstrap frame. (scm_make_stack): Accept a VM frame in addition to debug frames. Probably has some bugs in this case. But in the case that the arg is #t (a common case), do the right thing, capturing the top VM frame as well, and interleaving those frames appropriately on the stack. As an accident, we lost the ability to limit the number of frames in the backtrace. We could add that back, but personally I always want *all* frames in the trace... Narrowing still works fine, though there are some hiccups sometimes -- e.g. an outer cut to a procedure that does a tail-call in VM code will never find the cut, as it no longer exists in the continuation. * libguile/vm.h (struct scm_vm): So! Now that we have switched to save stacks in the normal make-stack, there's no more need for `this_frame' or `last_frame'. On the other hand, we can take this opportunity to fix tracing: when we're in a trace hook, we set `trace_frame' on the VM, so we know not to fire hooks when we're already in a hook. (struct scm_vm_cont): Expose this, as make-stack needs it to make VM frames from VM continuations. * libguile/vm.c (scm_vm_trace_frame): New function, gets the current trace frame. (vm_mark, make_vm): Hook up the trace frame. (vm_dispatch_hook): New hook dispatcher, with a dynwind so it does the right thing if the hook exits nonlocally. * libguile/vm-engine.c (vm_run): No more this_frame in the wind data. * libguile/vm-engine.h (RUN_HOOK): Run hooks through the dispatcher. (ALIGN_AS_NON_IMMEDIATE, POP_LIST_ON_STACK): Remove unused code. (NEW_FRAME): Adapt for no HL in the frame. * libguile/vm-i-system.c (goto/args, mv-call, return, return/values): Adapt for no HL in the frame. * module/system/vm/frame.scm: * module/system/vm/vm.scm: Beginnings of some reworkings, needs more thought.
2008-12-26 17:59:46 +01:00
Frame pointer points to local 0 instead of local 1 * libguile/frames.h: Change so that fp points at local 0 instead of local 1, and clean up a bit. (struct scm_vm_frame): Remove program, and rename stack to locals. (SCM_FRAME_DATA_ADDRESS): Remove; it was redundant with SCM_FRAME_LOWER_ADDRESS. (SCM_FRAME_STACK_ADDRESS): Remove; replace with the new SCM_FRAME_LOCALS_ADDRESS. (SCM_FRAME_UPPER_ADDRESS): Remove; unused. (SCM_FRAME_NUM_LOCALS, SCM_FRAME_PREVIOUS_SP): New defines. (SCM_FRAME_BYTE_CAST, SCM_FRAME_STACK_CAST): Remove; unused; (SCM_FRAME_LOCAL): New define, replaces SCM_FRAME_VARIABLE. (SCM_FRAME_PROGRAM): Add cautionary commentary. * libguile/frames.c: Adapt static asserts. (scm_frame_num_locals, scm_frame_local_ref, scm_frame_local_set_x): Adapt. This means that frame-local-ref 0 now returns the procedure. * libguile/vm-engine.c (ALLOC_FRAME, RESET_FRAME) (FRAME_LOCALS_COUNT, LOCAL_REF, LOCAL_SET, RETURN_VALUE_LIST): Adapt to change in fp. (LOCAL_ADDRESS): New helper. (POP_CONTINUATION_HOOK): Reimplement, taking the previous FP as an argument. (ABORT_CONTINUATION_HOOK): Reimplement, taking no arguments. (RETURN_ONE_VALUE): Reimplement. (RETURN_VALUE_LIST): Adapt to FP change. (halt, return-values, subr-call, foreign-call, prompt) (continuation-call, compose-continuation, call/cc, abort): Adapt to FP change, mostly via using LOCAL_ADDRESS, etc abstractions instead of using the raw frame pointer. * libguile/control.c (reify_partial_continuation): Update for fp change. * libguile/vm.c (vm_reinstate_partial_continuation): Adapt to removal of SCM_FRAME_UPPER_ADDRESS. * module/system/vm/frame.scm (frame-call-representation): Adapt to frame-local-ref change. * module/system/vm/trace.scm (print-return): Remove unused frame-num-locals call.
2013-11-17 22:07:44 +01:00
fp = SCM_VM_FRAME_FP (frame);
runtime and debugging support for callee-parsed procedure args * libguile/objcodes.h: Bump for metadata format change. * libguile/frames.h: Rework so we don't frob the program's nargs, nlocs, etc at runtime. Instead we don't really know what's a local var, an argument, or an intermediate value. It's a little unfortunate, but this will allow for case-lambda, and eventually for good polymorphic generic dispatch; and the nlocs etc can be heuristically reconstructed. Such a reconstruction would be better done at the Scheme level, though. (SCM_FRAME_STACK_ADDRESS): New macro, the pointer to the base of the stack elements (not counting the program). (SCM_FRAME_UPPER_ADDRESS): Repurpose to be the address of the last element in the bookkeeping part of the stack -- i.e. to point to the return address. * libguile/vm-engine.h: * libguile/vm-i-system.c: Adapt to removal of stack_base. Though we still detect stack-smashing underflow, we don't do so as precisely as we did before, because now we only detect overwriting of the frame metadata. * libguile/vm-engine.c (vm_engine): Remove the stack_base variable. It is unnecessary, and difficult to keep track of in the face of case-lambda. Also fix miscommented "ra" and "mvra" pushes. Push the vp->ip as the first ra... * libguile/vm-i-system.c (halt): ...because here we can restore the vp->ip instead of setting ip to 0. Allows us to introspect ips all down the stack, including in recursive VM invocations. * libguile/frames.h: * libguile/frames.c (scm_vm_frame_stack): Removed, because it's getting more difficult to tell what's an argument and what's a temporary stack element. (scm_vm_frame_num_locals): New accessor. (scm_vm_frame_instruction_pointer): New accessor. (scm_vm_frame_arguments): Defer to an implementation in Scheme. (scm_vm_frame_num_locals scm_vm_frame_local_ref) (scm_vm_frame_local_set_x): Since we can get not-yet-active frames on the stack now, with our current calling convention, we have to add a heuristic here to jump over those frames -- because frames have pointers in them, not Scheme values. * libguile/programs.h: * libguile/programs.c (scm_program_arity): Remove, in favor of.. (scm_program_arities): ...this, which a list of arities, in a new format, occupying a slot in the metadata. * module/language/assembly/decompile-bytecode.scm (decode-load-program): Fix mv-call decompilation. * module/system/vm/frame.scm (vm-frame-bindings, vm-frame-binding-ref) (vm-frame-binding-set!): New functions, to access bindings by name in a frame. (vm-frame-arguments): Function now implemented in Scheme. Commented fairly extensively. * module/system/vm/program.scm (program-bindings-by-index) (program-bindings-for-ip): New accessors, parsing the program bindings metadata into something more useful. (program-arities, program-arguments): In a case-lambda world, we have to assume that programs can have multiple arities. But it's tough to detect this algorithmically; instead we're going to require that the program metadata include information about the arities, and the parts of the program that that metadata applies to. (program-lambda-list): New accessor. (write-program): Show multiple arities. * module/language/glil/compile-assembly.scm (glil->assembly): Add "arities" to the state of the compiler, and add arities entries as appropriate.
2009-09-27 19:25:58 -04:00
sp = SCM_VM_FRAME_SP (frame);
Frame pointer points to local 0 instead of local 1 * libguile/frames.h: Change so that fp points at local 0 instead of local 1, and clean up a bit. (struct scm_vm_frame): Remove program, and rename stack to locals. (SCM_FRAME_DATA_ADDRESS): Remove; it was redundant with SCM_FRAME_LOWER_ADDRESS. (SCM_FRAME_STACK_ADDRESS): Remove; replace with the new SCM_FRAME_LOCALS_ADDRESS. (SCM_FRAME_UPPER_ADDRESS): Remove; unused. (SCM_FRAME_NUM_LOCALS, SCM_FRAME_PREVIOUS_SP): New defines. (SCM_FRAME_BYTE_CAST, SCM_FRAME_STACK_CAST): Remove; unused; (SCM_FRAME_LOCAL): New define, replaces SCM_FRAME_VARIABLE. (SCM_FRAME_PROGRAM): Add cautionary commentary. * libguile/frames.c: Adapt static asserts. (scm_frame_num_locals, scm_frame_local_ref, scm_frame_local_set_x): Adapt. This means that frame-local-ref 0 now returns the procedure. * libguile/vm-engine.c (ALLOC_FRAME, RESET_FRAME) (FRAME_LOCALS_COUNT, LOCAL_REF, LOCAL_SET, RETURN_VALUE_LIST): Adapt to change in fp. (LOCAL_ADDRESS): New helper. (POP_CONTINUATION_HOOK): Reimplement, taking the previous FP as an argument. (ABORT_CONTINUATION_HOOK): Reimplement, taking no arguments. (RETURN_ONE_VALUE): Reimplement. (RETURN_VALUE_LIST): Adapt to FP change. (halt, return-values, subr-call, foreign-call, prompt) (continuation-call, compose-continuation, call/cc, abort): Adapt to FP change, mostly via using LOCAL_ADDRESS, etc abstractions instead of using the raw frame pointer. * libguile/control.c (reify_partial_continuation): Update for fp change. * libguile/vm.c (vm_reinstate_partial_continuation): Adapt to removal of SCM_FRAME_UPPER_ADDRESS. * module/system/vm/frame.scm (frame-call-representation): Adapt to frame-local-ref change. * module/system/vm/trace.scm (print-return): Remove unused frame-num-locals call.
2013-11-17 22:07:44 +01:00
if (i < SCM_FRAME_NUM_LOCALS (fp, sp))
{
union scm_vm_stack_element *item = SCM_FRAME_SLOT (fp, i);
switch (repr)
{
case STACK_ITEM_SCM:
return item->as_scm;
case STACK_ITEM_F64:
return scm_from_double (item->as_f64);
case STACK_ITEM_U64:
return scm_from_uint64 (item->as_u64);
case STACK_ITEM_S64:
return scm_from_int64 (item->as_s64);
default:
abort();
}
}
runtime and debugging support for callee-parsed procedure args * libguile/objcodes.h: Bump for metadata format change. * libguile/frames.h: Rework so we don't frob the program's nargs, nlocs, etc at runtime. Instead we don't really know what's a local var, an argument, or an intermediate value. It's a little unfortunate, but this will allow for case-lambda, and eventually for good polymorphic generic dispatch; and the nlocs etc can be heuristically reconstructed. Such a reconstruction would be better done at the Scheme level, though. (SCM_FRAME_STACK_ADDRESS): New macro, the pointer to the base of the stack elements (not counting the program). (SCM_FRAME_UPPER_ADDRESS): Repurpose to be the address of the last element in the bookkeeping part of the stack -- i.e. to point to the return address. * libguile/vm-engine.h: * libguile/vm-i-system.c: Adapt to removal of stack_base. Though we still detect stack-smashing underflow, we don't do so as precisely as we did before, because now we only detect overwriting of the frame metadata. * libguile/vm-engine.c (vm_engine): Remove the stack_base variable. It is unnecessary, and difficult to keep track of in the face of case-lambda. Also fix miscommented "ra" and "mvra" pushes. Push the vp->ip as the first ra... * libguile/vm-i-system.c (halt): ...because here we can restore the vp->ip instead of setting ip to 0. Allows us to introspect ips all down the stack, including in recursive VM invocations. * libguile/frames.h: * libguile/frames.c (scm_vm_frame_stack): Removed, because it's getting more difficult to tell what's an argument and what's a temporary stack element. (scm_vm_frame_num_locals): New accessor. (scm_vm_frame_instruction_pointer): New accessor. (scm_vm_frame_arguments): Defer to an implementation in Scheme. (scm_vm_frame_num_locals scm_vm_frame_local_ref) (scm_vm_frame_local_set_x): Since we can get not-yet-active frames on the stack now, with our current calling convention, we have to add a heuristic here to jump over those frames -- because frames have pointers in them, not Scheme values. * libguile/programs.h: * libguile/programs.c (scm_program_arity): Remove, in favor of.. (scm_program_arities): ...this, which a list of arities, in a new format, occupying a slot in the metadata. * module/language/assembly/decompile-bytecode.scm (decode-load-program): Fix mv-call decompilation. * module/system/vm/frame.scm (vm-frame-bindings, vm-frame-binding-ref) (vm-frame-binding-set!): New functions, to access bindings by name in a frame. (vm-frame-arguments): Function now implemented in Scheme. Commented fairly extensively. * module/system/vm/program.scm (program-bindings-by-index) (program-bindings-for-ip): New accessors, parsing the program bindings metadata into something more useful. (program-arities, program-arguments): In a case-lambda world, we have to assume that programs can have multiple arities. But it's tough to detect this algorithmically; instead we're going to require that the program metadata include information about the arities, and the parts of the program that that metadata applies to. (program-lambda-list): New accessor. (write-program): Show multiple arities. * module/language/glil/compile-assembly.scm (glil->assembly): Add "arities" to the state of the compiler, and add arities entries as appropriate.
2009-09-27 19:25:58 -04:00
SCM_OUT_OF_RANGE (SCM_ARG2, index);
2001-04-23 04:28:13 +00:00
}
#undef FUNC_NAME
2001-04-22 02:13:48 +00:00
static const char s_scm_frame_local_set_x[] = "frame-local-set!";
static SCM
scm_frame_local_set_x (SCM frame, SCM index, SCM val, SCM representation)
replace frame implementation with VM frames * libguile/stacks.h: Rework so that a stack doesn't copy information out of VM frames, it just holds onto a VM frame, along with the stack id and length. VM frames are now the only representation of frames in Guile. (scm_t_info_frame, SCM_FRAME_N_SLOTS, SCM_FRAME_REF, SCM_FRAME_NUMBER) (SCM_FRAME_FLAGS, SCM_FRAME_SOURCE, SCM_FRAME_PROC, SCM_FRAME_ARGS) (SCM_FRAME_PREV, SCM_FRAME_NEXT) (SCM_FRAMEF_VOID, SCM_FRAMEF_REAL, SCM_FRAMEF_PROC) (SCM_FRAMEF_EVAL_ARGS, SCM_FRAMEF_OVERFLOW) (SCM_FRAME_VOID_P, SCM_FRAME_REAL_P, SCM_FRAME_PROC_P) (SCM_FRAME_EVAL_ARGS_P, SCM_FRAME_OVERFLOW_P): Remove these macros corresponding to the old frame implementation. (scm_frame_p scm_frame_source, scm_frame_procedure) (scm_frame_arguments): These definitions are now in frames.h. (scm_last_stack_frame): Remove declaration of previously-removed constructor. Probably should re-instate it though. (scm_frame_number, scm_frame_previous, scm_frame_next) (scm_frame_real_p, scm_frame_procedure_p, scm_frame_evaluating_args_p) (scm_frame_overflow_p) : Remove these procedures corresponding to the old stack implementation. * libguile/stacks.c: Update for new frames implementation. * libguile/frames.h: * libguile/frames.c: Rename functions operating on VM frames to have a scm_frame prefix, not scm_vm_frame -- because they really are the only frames we have. Rename corresponding Scheme functions too, from vm-frame-foo to frame-foo. * libguile/deprecated.h: Remove scm_stack and scm_info_frame data types. * libguile/vm.c (vm_dispatch_hook): Adapt to scm_c_make_frame name change. * module/system/vm/frame.scm: No need to export functions provided frames.c now, as we load those procedures into the default environment now. Rename functions, and remove a couple of outdated, unused functions. The bottom half of this file is still bitrotten, though. * libguile/backtrace.c: Rework to operate on the new frame representation. Also fix a bug displaying file names for compiled procedures. * libguile/init.c: Load the VM much earlier, just because we can. Also it allows us to have frames.[ch] loaded in time for stacks to be initialized, so that scm_frame_arguments can do the right thing.
2009-12-03 13:09:58 +01:00
#define FUNC_NAME s_scm_frame_local_set_x
2001-04-23 04:28:13 +00:00
{
VM stack grows downward Adapt VM stack to grow downward. This will make native compilation look more like the VM code, as we will be able to use native CALL instructions, taking proper advantage of the return address buffer. * libguile/continuations.c (scm_i_continuation_to_frame): Record offsets from stack top. * libguile/control.c (scm_i_prompt_pop_abort_args_x): Adapt for reversed order of arguments, and instead of relying on the abort to push on the number of arguments, make the caller save the stack depth, which allows us to compute the number of arguments ourselves. (reify_partial_continuation, scm_c_abort): Adapt to reversed stack order. * libguile/dynstack.c (scm_dynstack_wind_prompt): Since we wind the stack in a downward direction, subtract the reloc instead of adding it. * libguile/dynstack.h (SCM_F_DYNSTACK_PROMPT_ESCAPE_ONLY): Remove flag; instead rely on prompt-establishing code to save the stack depth. * libguile/eval.c (eval): Remove extraneous "volatile" declarations for variables that are not re-set between the setjmp and any longjmp. Adapt to save stack depth before instating the prompt. * libguile/foreign.c (scm_i_foreign_call): Adapt to receive arguments in reverse order. * libguile/frames.c (frame_stack_top, scm_i_frame_stack_top): Adapt to compute stack top instead of stack bottom. (scm_c_frame_closure): Adapt to stack growth change. (scm_frame_num_locals, scm_frame_local_ref, scm_frame_set_x): Use union data type to access stack. (RELOC): Reformat. (scm_c_frame_previous): Adapt to stack growth change. * libguile/frames.h: Adapt stack diagram to indicate that the stack grows up. (union scm_vm_stack_element): New data type used to access items on the stack. (SCM_FRAME_PREVIOUS_SP) (SCM_FRAME_RETURN_ADDRESS, SCM_FRAME_SET_RETURN_ADDRESS) (SCM_FRAME_DYNAMIC_LINK, SCM_FRAME_SET_DYNAMIC_LINK) (SCM_FRAME_LOCAL, SCM_FRAME_NUM_LOCALS): Adapt to stack representation change. (SCM_FRAME_SLOT): New helper. (SCM_VM_FRAME_FP, SCM_VM_FRAME_SP): Adapt to stack growth change. * libguile/stacks.c (scm_make_stack): Record offsets from top of stack. * libguile/throw.c (catch): Adapt to scm_i_prompt_pop_abort_args_x change. * libguile/vm-engine.c (ALLOC_FRAME, RESET_FRAME): (FRAME_LOCALS_COUNT_FROM): Adapt to stack growth change. (LOCAL_ADDRESS): Use SCM_FRAME_SLOT to get the address as the proper data type. (RETURN_ONE_VALUE, RETURN_VALUE_LIST): Adapt to stack growth change. (apply): Shuffling up the SMOB apply args can cause the stack to expand, so use ALLOC_FRAME instead of RESET_FRAME. (vm_engine): Adapt for stack growth change. * libguile/vm.c (vm_increase_sp, vm_push_sp, vm_restore_sp): Adapt to stack representation change. (scm_i_vm_cont_to_frame): Adapt to take offsets from the top. (scm_i_vm_capture_stack): Adapt to capture from the top. (vm_return_to_continuation_inner): Adapt for data type changes. (vm_return_to_continuation): Likewise, and instead of looping, just splat the saved arguments on with memcpy. (vm_dispatch_hook): Adapt to receive arguments in the reverse order. Adapt callers. (vm_abort): There is never a tail argument. Adapt to stack representation change. (vm_reinstate_partial_continuation) (vm_reinstate_partial_continuation_inner): Adapt to stack growth change. (allocate_stack, free_stack): Adapt to data type change. (expand_stack): Don't try to mremap(), as you can't grow a mapping from the bottom. Without knowing that there's a free mapping space right below the old stack, which there usually isn't on Linux, we have to copy. We can't use MAP_GROWSDOWN because Linux is buggy. (make_vm): Adapt to stack representation changes. (return_unused_stack_to_os): Round down instead of up, as the stack grows down. (scm_i_vm_mark_stack): Adapt to walk up the stack. (scm_i_vm_free_stack): Adapt to scm_vm changes. (vm_expand_stack_inner, reset_stack_limit, vm_expand_stack): Adapt to the stack growing down. (scm_call_n): Adapt to the stack growing down. Don't allow argv to point into the stack. * libguile/vm.h (struct scm_vm, struct scm_vm_cont): Adapt to hold the stack top and bottom.
2015-09-22 10:24:30 +00:00
union scm_vm_stack_element *fp, *sp;
remove heap links in VM frames, incorporate vm frames into normal backtraces * doc/ref/vm.texi (Stack Layout): Update to remove references to the "heap link". * gdbinit: Update for "heap link" removal. * libguile/frames.c: * libguile/frames.h: Update macros and diagram for removal of "heap link". As part of this, we also remove "heap frames", replacing them with "vm frames", which are much like the interpreter's debug objects, but for VM stacks. That is to say, they don't actually hold the stack themselves, just the pointers into stack that's held by a continuation (either captured or current). * libguile/stacks.c (stack_depth, read_frames): Since a "stack" object is really a copy of information that comes from somewhere else, it makes sense to copy over info from the VM, just as `make-stack' does from the evaluator. The tricky bit is to figure out how to interleave VM and interpreter frames. We do that by starting in the interpreter, and whenever the current frame's procedure is actually a program, we switch to the VM stack, switching back when we reach a "bootstrap frame". The last bit is hacky, but it does work... (is_vm_bootstrap_frame): Hacky predicate to see if a VM frame is a bootstrap frame. (scm_make_stack): Accept a VM frame in addition to debug frames. Probably has some bugs in this case. But in the case that the arg is #t (a common case), do the right thing, capturing the top VM frame as well, and interleaving those frames appropriately on the stack. As an accident, we lost the ability to limit the number of frames in the backtrace. We could add that back, but personally I always want *all* frames in the trace... Narrowing still works fine, though there are some hiccups sometimes -- e.g. an outer cut to a procedure that does a tail-call in VM code will never find the cut, as it no longer exists in the continuation. * libguile/vm.h (struct scm_vm): So! Now that we have switched to save stacks in the normal make-stack, there's no more need for `this_frame' or `last_frame'. On the other hand, we can take this opportunity to fix tracing: when we're in a trace hook, we set `trace_frame' on the VM, so we know not to fire hooks when we're already in a hook. (struct scm_vm_cont): Expose this, as make-stack needs it to make VM frames from VM continuations. * libguile/vm.c (scm_vm_trace_frame): New function, gets the current trace frame. (vm_mark, make_vm): Hook up the trace frame. (vm_dispatch_hook): New hook dispatcher, with a dynwind so it does the right thing if the hook exits nonlocally. * libguile/vm-engine.c (vm_run): No more this_frame in the wind data. * libguile/vm-engine.h (RUN_HOOK): Run hooks through the dispatcher. (ALIGN_AS_NON_IMMEDIATE, POP_LIST_ON_STACK): Remove unused code. (NEW_FRAME): Adapt for no HL in the frame. * libguile/vm-i-system.c (goto/args, mv-call, return, return/values): Adapt for no HL in the frame. * module/system/vm/frame.scm: * module/system/vm/vm.scm: Beginnings of some reworkings, needs more thought.
2008-12-26 17:59:46 +01:00
unsigned int i;
enum stack_item_representation repr;
remove heap links in VM frames, incorporate vm frames into normal backtraces * doc/ref/vm.texi (Stack Layout): Update to remove references to the "heap link". * gdbinit: Update for "heap link" removal. * libguile/frames.c: * libguile/frames.h: Update macros and diagram for removal of "heap link". As part of this, we also remove "heap frames", replacing them with "vm frames", which are much like the interpreter's debug objects, but for VM stacks. That is to say, they don't actually hold the stack themselves, just the pointers into stack that's held by a continuation (either captured or current). * libguile/stacks.c (stack_depth, read_frames): Since a "stack" object is really a copy of information that comes from somewhere else, it makes sense to copy over info from the VM, just as `make-stack' does from the evaluator. The tricky bit is to figure out how to interleave VM and interpreter frames. We do that by starting in the interpreter, and whenever the current frame's procedure is actually a program, we switch to the VM stack, switching back when we reach a "bootstrap frame". The last bit is hacky, but it does work... (is_vm_bootstrap_frame): Hacky predicate to see if a VM frame is a bootstrap frame. (scm_make_stack): Accept a VM frame in addition to debug frames. Probably has some bugs in this case. But in the case that the arg is #t (a common case), do the right thing, capturing the top VM frame as well, and interleaving those frames appropriately on the stack. As an accident, we lost the ability to limit the number of frames in the backtrace. We could add that back, but personally I always want *all* frames in the trace... Narrowing still works fine, though there are some hiccups sometimes -- e.g. an outer cut to a procedure that does a tail-call in VM code will never find the cut, as it no longer exists in the continuation. * libguile/vm.h (struct scm_vm): So! Now that we have switched to save stacks in the normal make-stack, there's no more need for `this_frame' or `last_frame'. On the other hand, we can take this opportunity to fix tracing: when we're in a trace hook, we set `trace_frame' on the VM, so we know not to fire hooks when we're already in a hook. (struct scm_vm_cont): Expose this, as make-stack needs it to make VM frames from VM continuations. * libguile/vm.c (scm_vm_trace_frame): New function, gets the current trace frame. (vm_mark, make_vm): Hook up the trace frame. (vm_dispatch_hook): New hook dispatcher, with a dynwind so it does the right thing if the hook exits nonlocally. * libguile/vm-engine.c (vm_run): No more this_frame in the wind data. * libguile/vm-engine.h (RUN_HOOK): Run hooks through the dispatcher. (ALIGN_AS_NON_IMMEDIATE, POP_LIST_ON_STACK): Remove unused code. (NEW_FRAME): Adapt for no HL in the frame. * libguile/vm-i-system.c (goto/args, mv-call, return, return/values): Adapt for no HL in the frame. * module/system/vm/frame.scm: * module/system/vm/vm.scm: Beginnings of some reworkings, needs more thought.
2008-12-26 17:59:46 +01:00
runtime and debugging support for callee-parsed procedure args * libguile/objcodes.h: Bump for metadata format change. * libguile/frames.h: Rework so we don't frob the program's nargs, nlocs, etc at runtime. Instead we don't really know what's a local var, an argument, or an intermediate value. It's a little unfortunate, but this will allow for case-lambda, and eventually for good polymorphic generic dispatch; and the nlocs etc can be heuristically reconstructed. Such a reconstruction would be better done at the Scheme level, though. (SCM_FRAME_STACK_ADDRESS): New macro, the pointer to the base of the stack elements (not counting the program). (SCM_FRAME_UPPER_ADDRESS): Repurpose to be the address of the last element in the bookkeeping part of the stack -- i.e. to point to the return address. * libguile/vm-engine.h: * libguile/vm-i-system.c: Adapt to removal of stack_base. Though we still detect stack-smashing underflow, we don't do so as precisely as we did before, because now we only detect overwriting of the frame metadata. * libguile/vm-engine.c (vm_engine): Remove the stack_base variable. It is unnecessary, and difficult to keep track of in the face of case-lambda. Also fix miscommented "ra" and "mvra" pushes. Push the vp->ip as the first ra... * libguile/vm-i-system.c (halt): ...because here we can restore the vp->ip instead of setting ip to 0. Allows us to introspect ips all down the stack, including in recursive VM invocations. * libguile/frames.h: * libguile/frames.c (scm_vm_frame_stack): Removed, because it's getting more difficult to tell what's an argument and what's a temporary stack element. (scm_vm_frame_num_locals): New accessor. (scm_vm_frame_instruction_pointer): New accessor. (scm_vm_frame_arguments): Defer to an implementation in Scheme. (scm_vm_frame_num_locals scm_vm_frame_local_ref) (scm_vm_frame_local_set_x): Since we can get not-yet-active frames on the stack now, with our current calling convention, we have to add a heuristic here to jump over those frames -- because frames have pointers in them, not Scheme values. * libguile/programs.h: * libguile/programs.c (scm_program_arity): Remove, in favor of.. (scm_program_arities): ...this, which a list of arities, in a new format, occupying a slot in the metadata. * module/language/assembly/decompile-bytecode.scm (decode-load-program): Fix mv-call decompilation. * module/system/vm/frame.scm (vm-frame-bindings, vm-frame-binding-ref) (vm-frame-binding-set!): New functions, to access bindings by name in a frame. (vm-frame-arguments): Function now implemented in Scheme. Commented fairly extensively. * module/system/vm/program.scm (program-bindings-by-index) (program-bindings-for-ip): New accessors, parsing the program bindings metadata into something more useful. (program-arities, program-arguments): In a case-lambda world, we have to assume that programs can have multiple arities. But it's tough to detect this algorithmically; instead we're going to require that the program metadata include information about the arities, and the parts of the program that that metadata applies to. (program-lambda-list): New accessor. (write-program): Show multiple arities. * module/language/glil/compile-assembly.scm (glil->assembly): Add "arities" to the state of the compiler, and add arities entries as appropriate.
2009-09-27 19:25:58 -04:00
SCM_VALIDATE_VM_FRAME (1, frame);
remove heap links in VM frames, incorporate vm frames into normal backtraces * doc/ref/vm.texi (Stack Layout): Update to remove references to the "heap link". * gdbinit: Update for "heap link" removal. * libguile/frames.c: * libguile/frames.h: Update macros and diagram for removal of "heap link". As part of this, we also remove "heap frames", replacing them with "vm frames", which are much like the interpreter's debug objects, but for VM stacks. That is to say, they don't actually hold the stack themselves, just the pointers into stack that's held by a continuation (either captured or current). * libguile/stacks.c (stack_depth, read_frames): Since a "stack" object is really a copy of information that comes from somewhere else, it makes sense to copy over info from the VM, just as `make-stack' does from the evaluator. The tricky bit is to figure out how to interleave VM and interpreter frames. We do that by starting in the interpreter, and whenever the current frame's procedure is actually a program, we switch to the VM stack, switching back when we reach a "bootstrap frame". The last bit is hacky, but it does work... (is_vm_bootstrap_frame): Hacky predicate to see if a VM frame is a bootstrap frame. (scm_make_stack): Accept a VM frame in addition to debug frames. Probably has some bugs in this case. But in the case that the arg is #t (a common case), do the right thing, capturing the top VM frame as well, and interleaving those frames appropriately on the stack. As an accident, we lost the ability to limit the number of frames in the backtrace. We could add that back, but personally I always want *all* frames in the trace... Narrowing still works fine, though there are some hiccups sometimes -- e.g. an outer cut to a procedure that does a tail-call in VM code will never find the cut, as it no longer exists in the continuation. * libguile/vm.h (struct scm_vm): So! Now that we have switched to save stacks in the normal make-stack, there's no more need for `this_frame' or `last_frame'. On the other hand, we can take this opportunity to fix tracing: when we're in a trace hook, we set `trace_frame' on the VM, so we know not to fire hooks when we're already in a hook. (struct scm_vm_cont): Expose this, as make-stack needs it to make VM frames from VM continuations. * libguile/vm.c (scm_vm_trace_frame): New function, gets the current trace frame. (vm_mark, make_vm): Hook up the trace frame. (vm_dispatch_hook): New hook dispatcher, with a dynwind so it does the right thing if the hook exits nonlocally. * libguile/vm-engine.c (vm_run): No more this_frame in the wind data. * libguile/vm-engine.h (RUN_HOOK): Run hooks through the dispatcher. (ALIGN_AS_NON_IMMEDIATE, POP_LIST_ON_STACK): Remove unused code. (NEW_FRAME): Adapt for no HL in the frame. * libguile/vm-i-system.c (goto/args, mv-call, return, return/values): Adapt for no HL in the frame. * module/system/vm/frame.scm: * module/system/vm/vm.scm: Beginnings of some reworkings, needs more thought.
2008-12-26 17:59:46 +01:00
SCM_VALIDATE_UINT_COPY (2, index, i);
repr = scm_to_stack_item_representation (representation, FUNC_NAME, SCM_ARG3);
remove heap links in VM frames, incorporate vm frames into normal backtraces * doc/ref/vm.texi (Stack Layout): Update to remove references to the "heap link". * gdbinit: Update for "heap link" removal. * libguile/frames.c: * libguile/frames.h: Update macros and diagram for removal of "heap link". As part of this, we also remove "heap frames", replacing them with "vm frames", which are much like the interpreter's debug objects, but for VM stacks. That is to say, they don't actually hold the stack themselves, just the pointers into stack that's held by a continuation (either captured or current). * libguile/stacks.c (stack_depth, read_frames): Since a "stack" object is really a copy of information that comes from somewhere else, it makes sense to copy over info from the VM, just as `make-stack' does from the evaluator. The tricky bit is to figure out how to interleave VM and interpreter frames. We do that by starting in the interpreter, and whenever the current frame's procedure is actually a program, we switch to the VM stack, switching back when we reach a "bootstrap frame". The last bit is hacky, but it does work... (is_vm_bootstrap_frame): Hacky predicate to see if a VM frame is a bootstrap frame. (scm_make_stack): Accept a VM frame in addition to debug frames. Probably has some bugs in this case. But in the case that the arg is #t (a common case), do the right thing, capturing the top VM frame as well, and interleaving those frames appropriately on the stack. As an accident, we lost the ability to limit the number of frames in the backtrace. We could add that back, but personally I always want *all* frames in the trace... Narrowing still works fine, though there are some hiccups sometimes -- e.g. an outer cut to a procedure that does a tail-call in VM code will never find the cut, as it no longer exists in the continuation. * libguile/vm.h (struct scm_vm): So! Now that we have switched to save stacks in the normal make-stack, there's no more need for `this_frame' or `last_frame'. On the other hand, we can take this opportunity to fix tracing: when we're in a trace hook, we set `trace_frame' on the VM, so we know not to fire hooks when we're already in a hook. (struct scm_vm_cont): Expose this, as make-stack needs it to make VM frames from VM continuations. * libguile/vm.c (scm_vm_trace_frame): New function, gets the current trace frame. (vm_mark, make_vm): Hook up the trace frame. (vm_dispatch_hook): New hook dispatcher, with a dynwind so it does the right thing if the hook exits nonlocally. * libguile/vm-engine.c (vm_run): No more this_frame in the wind data. * libguile/vm-engine.h (RUN_HOOK): Run hooks through the dispatcher. (ALIGN_AS_NON_IMMEDIATE, POP_LIST_ON_STACK): Remove unused code. (NEW_FRAME): Adapt for no HL in the frame. * libguile/vm-i-system.c (goto/args, mv-call, return, return/values): Adapt for no HL in the frame. * module/system/vm/frame.scm: * module/system/vm/vm.scm: Beginnings of some reworkings, needs more thought.
2008-12-26 17:59:46 +01:00
Frame pointer points to local 0 instead of local 1 * libguile/frames.h: Change so that fp points at local 0 instead of local 1, and clean up a bit. (struct scm_vm_frame): Remove program, and rename stack to locals. (SCM_FRAME_DATA_ADDRESS): Remove; it was redundant with SCM_FRAME_LOWER_ADDRESS. (SCM_FRAME_STACK_ADDRESS): Remove; replace with the new SCM_FRAME_LOCALS_ADDRESS. (SCM_FRAME_UPPER_ADDRESS): Remove; unused. (SCM_FRAME_NUM_LOCALS, SCM_FRAME_PREVIOUS_SP): New defines. (SCM_FRAME_BYTE_CAST, SCM_FRAME_STACK_CAST): Remove; unused; (SCM_FRAME_LOCAL): New define, replaces SCM_FRAME_VARIABLE. (SCM_FRAME_PROGRAM): Add cautionary commentary. * libguile/frames.c: Adapt static asserts. (scm_frame_num_locals, scm_frame_local_ref, scm_frame_local_set_x): Adapt. This means that frame-local-ref 0 now returns the procedure. * libguile/vm-engine.c (ALLOC_FRAME, RESET_FRAME) (FRAME_LOCALS_COUNT, LOCAL_REF, LOCAL_SET, RETURN_VALUE_LIST): Adapt to change in fp. (LOCAL_ADDRESS): New helper. (POP_CONTINUATION_HOOK): Reimplement, taking the previous FP as an argument. (ABORT_CONTINUATION_HOOK): Reimplement, taking no arguments. (RETURN_ONE_VALUE): Reimplement. (RETURN_VALUE_LIST): Adapt to FP change. (halt, return-values, subr-call, foreign-call, prompt) (continuation-call, compose-continuation, call/cc, abort): Adapt to FP change, mostly via using LOCAL_ADDRESS, etc abstractions instead of using the raw frame pointer. * libguile/control.c (reify_partial_continuation): Update for fp change. * libguile/vm.c (vm_reinstate_partial_continuation): Adapt to removal of SCM_FRAME_UPPER_ADDRESS. * module/system/vm/frame.scm (frame-call-representation): Adapt to frame-local-ref change. * module/system/vm/trace.scm (print-return): Remove unused frame-num-locals call.
2013-11-17 22:07:44 +01:00
fp = SCM_VM_FRAME_FP (frame);
runtime and debugging support for callee-parsed procedure args * libguile/objcodes.h: Bump for metadata format change. * libguile/frames.h: Rework so we don't frob the program's nargs, nlocs, etc at runtime. Instead we don't really know what's a local var, an argument, or an intermediate value. It's a little unfortunate, but this will allow for case-lambda, and eventually for good polymorphic generic dispatch; and the nlocs etc can be heuristically reconstructed. Such a reconstruction would be better done at the Scheme level, though. (SCM_FRAME_STACK_ADDRESS): New macro, the pointer to the base of the stack elements (not counting the program). (SCM_FRAME_UPPER_ADDRESS): Repurpose to be the address of the last element in the bookkeeping part of the stack -- i.e. to point to the return address. * libguile/vm-engine.h: * libguile/vm-i-system.c: Adapt to removal of stack_base. Though we still detect stack-smashing underflow, we don't do so as precisely as we did before, because now we only detect overwriting of the frame metadata. * libguile/vm-engine.c (vm_engine): Remove the stack_base variable. It is unnecessary, and difficult to keep track of in the face of case-lambda. Also fix miscommented "ra" and "mvra" pushes. Push the vp->ip as the first ra... * libguile/vm-i-system.c (halt): ...because here we can restore the vp->ip instead of setting ip to 0. Allows us to introspect ips all down the stack, including in recursive VM invocations. * libguile/frames.h: * libguile/frames.c (scm_vm_frame_stack): Removed, because it's getting more difficult to tell what's an argument and what's a temporary stack element. (scm_vm_frame_num_locals): New accessor. (scm_vm_frame_instruction_pointer): New accessor. (scm_vm_frame_arguments): Defer to an implementation in Scheme. (scm_vm_frame_num_locals scm_vm_frame_local_ref) (scm_vm_frame_local_set_x): Since we can get not-yet-active frames on the stack now, with our current calling convention, we have to add a heuristic here to jump over those frames -- because frames have pointers in them, not Scheme values. * libguile/programs.h: * libguile/programs.c (scm_program_arity): Remove, in favor of.. (scm_program_arities): ...this, which a list of arities, in a new format, occupying a slot in the metadata. * module/language/assembly/decompile-bytecode.scm (decode-load-program): Fix mv-call decompilation. * module/system/vm/frame.scm (vm-frame-bindings, vm-frame-binding-ref) (vm-frame-binding-set!): New functions, to access bindings by name in a frame. (vm-frame-arguments): Function now implemented in Scheme. Commented fairly extensively. * module/system/vm/program.scm (program-bindings-by-index) (program-bindings-for-ip): New accessors, parsing the program bindings metadata into something more useful. (program-arities, program-arguments): In a case-lambda world, we have to assume that programs can have multiple arities. But it's tough to detect this algorithmically; instead we're going to require that the program metadata include information about the arities, and the parts of the program that that metadata applies to. (program-lambda-list): New accessor. (write-program): Show multiple arities. * module/language/glil/compile-assembly.scm (glil->assembly): Add "arities" to the state of the compiler, and add arities entries as appropriate.
2009-09-27 19:25:58 -04:00
sp = SCM_VM_FRAME_SP (frame);
Frame pointer points to local 0 instead of local 1 * libguile/frames.h: Change so that fp points at local 0 instead of local 1, and clean up a bit. (struct scm_vm_frame): Remove program, and rename stack to locals. (SCM_FRAME_DATA_ADDRESS): Remove; it was redundant with SCM_FRAME_LOWER_ADDRESS. (SCM_FRAME_STACK_ADDRESS): Remove; replace with the new SCM_FRAME_LOCALS_ADDRESS. (SCM_FRAME_UPPER_ADDRESS): Remove; unused. (SCM_FRAME_NUM_LOCALS, SCM_FRAME_PREVIOUS_SP): New defines. (SCM_FRAME_BYTE_CAST, SCM_FRAME_STACK_CAST): Remove; unused; (SCM_FRAME_LOCAL): New define, replaces SCM_FRAME_VARIABLE. (SCM_FRAME_PROGRAM): Add cautionary commentary. * libguile/frames.c: Adapt static asserts. (scm_frame_num_locals, scm_frame_local_ref, scm_frame_local_set_x): Adapt. This means that frame-local-ref 0 now returns the procedure. * libguile/vm-engine.c (ALLOC_FRAME, RESET_FRAME) (FRAME_LOCALS_COUNT, LOCAL_REF, LOCAL_SET, RETURN_VALUE_LIST): Adapt to change in fp. (LOCAL_ADDRESS): New helper. (POP_CONTINUATION_HOOK): Reimplement, taking the previous FP as an argument. (ABORT_CONTINUATION_HOOK): Reimplement, taking no arguments. (RETURN_ONE_VALUE): Reimplement. (RETURN_VALUE_LIST): Adapt to FP change. (halt, return-values, subr-call, foreign-call, prompt) (continuation-call, compose-continuation, call/cc, abort): Adapt to FP change, mostly via using LOCAL_ADDRESS, etc abstractions instead of using the raw frame pointer. * libguile/control.c (reify_partial_continuation): Update for fp change. * libguile/vm.c (vm_reinstate_partial_continuation): Adapt to removal of SCM_FRAME_UPPER_ADDRESS. * module/system/vm/frame.scm (frame-call-representation): Adapt to frame-local-ref change. * module/system/vm/trace.scm (print-return): Remove unused frame-num-locals call.
2013-11-17 22:07:44 +01:00
if (i < SCM_FRAME_NUM_LOCALS (fp, sp))
runtime and debugging support for callee-parsed procedure args * libguile/objcodes.h: Bump for metadata format change. * libguile/frames.h: Rework so we don't frob the program's nargs, nlocs, etc at runtime. Instead we don't really know what's a local var, an argument, or an intermediate value. It's a little unfortunate, but this will allow for case-lambda, and eventually for good polymorphic generic dispatch; and the nlocs etc can be heuristically reconstructed. Such a reconstruction would be better done at the Scheme level, though. (SCM_FRAME_STACK_ADDRESS): New macro, the pointer to the base of the stack elements (not counting the program). (SCM_FRAME_UPPER_ADDRESS): Repurpose to be the address of the last element in the bookkeeping part of the stack -- i.e. to point to the return address. * libguile/vm-engine.h: * libguile/vm-i-system.c: Adapt to removal of stack_base. Though we still detect stack-smashing underflow, we don't do so as precisely as we did before, because now we only detect overwriting of the frame metadata. * libguile/vm-engine.c (vm_engine): Remove the stack_base variable. It is unnecessary, and difficult to keep track of in the face of case-lambda. Also fix miscommented "ra" and "mvra" pushes. Push the vp->ip as the first ra... * libguile/vm-i-system.c (halt): ...because here we can restore the vp->ip instead of setting ip to 0. Allows us to introspect ips all down the stack, including in recursive VM invocations. * libguile/frames.h: * libguile/frames.c (scm_vm_frame_stack): Removed, because it's getting more difficult to tell what's an argument and what's a temporary stack element. (scm_vm_frame_num_locals): New accessor. (scm_vm_frame_instruction_pointer): New accessor. (scm_vm_frame_arguments): Defer to an implementation in Scheme. (scm_vm_frame_num_locals scm_vm_frame_local_ref) (scm_vm_frame_local_set_x): Since we can get not-yet-active frames on the stack now, with our current calling convention, we have to add a heuristic here to jump over those frames -- because frames have pointers in them, not Scheme values. * libguile/programs.h: * libguile/programs.c (scm_program_arity): Remove, in favor of.. (scm_program_arities): ...this, which a list of arities, in a new format, occupying a slot in the metadata. * module/language/assembly/decompile-bytecode.scm (decode-load-program): Fix mv-call decompilation. * module/system/vm/frame.scm (vm-frame-bindings, vm-frame-binding-ref) (vm-frame-binding-set!): New functions, to access bindings by name in a frame. (vm-frame-arguments): Function now implemented in Scheme. Commented fairly extensively. * module/system/vm/program.scm (program-bindings-by-index) (program-bindings-for-ip): New accessors, parsing the program bindings metadata into something more useful. (program-arities, program-arguments): In a case-lambda world, we have to assume that programs can have multiple arities. But it's tough to detect this algorithmically; instead we're going to require that the program metadata include information about the arities, and the parts of the program that that metadata applies to. (program-lambda-list): New accessor. (write-program): Show multiple arities. * module/language/glil/compile-assembly.scm (glil->assembly): Add "arities" to the state of the compiler, and add arities entries as appropriate.
2009-09-27 19:25:58 -04:00
{
union scm_vm_stack_element *item = SCM_FRAME_SLOT (fp, i);
switch (repr)
{
case STACK_ITEM_SCM:
item->as_scm = val;
break;
case STACK_ITEM_F64:
item->as_f64 = scm_to_double (val);
break;
case STACK_ITEM_U64:
item->as_u64 = scm_to_uint64 (val);
break;
case STACK_ITEM_S64:
item->as_s64 = scm_to_int64 (val);
break;
default:
abort();
}
return SCM_UNSPECIFIED;
runtime and debugging support for callee-parsed procedure args * libguile/objcodes.h: Bump for metadata format change. * libguile/frames.h: Rework so we don't frob the program's nargs, nlocs, etc at runtime. Instead we don't really know what's a local var, an argument, or an intermediate value. It's a little unfortunate, but this will allow for case-lambda, and eventually for good polymorphic generic dispatch; and the nlocs etc can be heuristically reconstructed. Such a reconstruction would be better done at the Scheme level, though. (SCM_FRAME_STACK_ADDRESS): New macro, the pointer to the base of the stack elements (not counting the program). (SCM_FRAME_UPPER_ADDRESS): Repurpose to be the address of the last element in the bookkeeping part of the stack -- i.e. to point to the return address. * libguile/vm-engine.h: * libguile/vm-i-system.c: Adapt to removal of stack_base. Though we still detect stack-smashing underflow, we don't do so as precisely as we did before, because now we only detect overwriting of the frame metadata. * libguile/vm-engine.c (vm_engine): Remove the stack_base variable. It is unnecessary, and difficult to keep track of in the face of case-lambda. Also fix miscommented "ra" and "mvra" pushes. Push the vp->ip as the first ra... * libguile/vm-i-system.c (halt): ...because here we can restore the vp->ip instead of setting ip to 0. Allows us to introspect ips all down the stack, including in recursive VM invocations. * libguile/frames.h: * libguile/frames.c (scm_vm_frame_stack): Removed, because it's getting more difficult to tell what's an argument and what's a temporary stack element. (scm_vm_frame_num_locals): New accessor. (scm_vm_frame_instruction_pointer): New accessor. (scm_vm_frame_arguments): Defer to an implementation in Scheme. (scm_vm_frame_num_locals scm_vm_frame_local_ref) (scm_vm_frame_local_set_x): Since we can get not-yet-active frames on the stack now, with our current calling convention, we have to add a heuristic here to jump over those frames -- because frames have pointers in them, not Scheme values. * libguile/programs.h: * libguile/programs.c (scm_program_arity): Remove, in favor of.. (scm_program_arities): ...this, which a list of arities, in a new format, occupying a slot in the metadata. * module/language/assembly/decompile-bytecode.scm (decode-load-program): Fix mv-call decompilation. * module/system/vm/frame.scm (vm-frame-bindings, vm-frame-binding-ref) (vm-frame-binding-set!): New functions, to access bindings by name in a frame. (vm-frame-arguments): Function now implemented in Scheme. Commented fairly extensively. * module/system/vm/program.scm (program-bindings-by-index) (program-bindings-for-ip): New accessors, parsing the program bindings metadata into something more useful. (program-arities, program-arguments): In a case-lambda world, we have to assume that programs can have multiple arities. But it's tough to detect this algorithmically; instead we're going to require that the program metadata include information about the arities, and the parts of the program that that metadata applies to. (program-lambda-list): New accessor. (write-program): Show multiple arities. * module/language/glil/compile-assembly.scm (glil->assembly): Add "arities" to the state of the compiler, and add arities entries as appropriate.
2009-09-27 19:25:58 -04:00
}
runtime and debugging support for callee-parsed procedure args * libguile/objcodes.h: Bump for metadata format change. * libguile/frames.h: Rework so we don't frob the program's nargs, nlocs, etc at runtime. Instead we don't really know what's a local var, an argument, or an intermediate value. It's a little unfortunate, but this will allow for case-lambda, and eventually for good polymorphic generic dispatch; and the nlocs etc can be heuristically reconstructed. Such a reconstruction would be better done at the Scheme level, though. (SCM_FRAME_STACK_ADDRESS): New macro, the pointer to the base of the stack elements (not counting the program). (SCM_FRAME_UPPER_ADDRESS): Repurpose to be the address of the last element in the bookkeeping part of the stack -- i.e. to point to the return address. * libguile/vm-engine.h: * libguile/vm-i-system.c: Adapt to removal of stack_base. Though we still detect stack-smashing underflow, we don't do so as precisely as we did before, because now we only detect overwriting of the frame metadata. * libguile/vm-engine.c (vm_engine): Remove the stack_base variable. It is unnecessary, and difficult to keep track of in the face of case-lambda. Also fix miscommented "ra" and "mvra" pushes. Push the vp->ip as the first ra... * libguile/vm-i-system.c (halt): ...because here we can restore the vp->ip instead of setting ip to 0. Allows us to introspect ips all down the stack, including in recursive VM invocations. * libguile/frames.h: * libguile/frames.c (scm_vm_frame_stack): Removed, because it's getting more difficult to tell what's an argument and what's a temporary stack element. (scm_vm_frame_num_locals): New accessor. (scm_vm_frame_instruction_pointer): New accessor. (scm_vm_frame_arguments): Defer to an implementation in Scheme. (scm_vm_frame_num_locals scm_vm_frame_local_ref) (scm_vm_frame_local_set_x): Since we can get not-yet-active frames on the stack now, with our current calling convention, we have to add a heuristic here to jump over those frames -- because frames have pointers in them, not Scheme values. * libguile/programs.h: * libguile/programs.c (scm_program_arity): Remove, in favor of.. (scm_program_arities): ...this, which a list of arities, in a new format, occupying a slot in the metadata. * module/language/assembly/decompile-bytecode.scm (decode-load-program): Fix mv-call decompilation. * module/system/vm/frame.scm (vm-frame-bindings, vm-frame-binding-ref) (vm-frame-binding-set!): New functions, to access bindings by name in a frame. (vm-frame-arguments): Function now implemented in Scheme. Commented fairly extensively. * module/system/vm/program.scm (program-bindings-by-index) (program-bindings-for-ip): New accessors, parsing the program bindings metadata into something more useful. (program-arities, program-arguments): In a case-lambda world, we have to assume that programs can have multiple arities. But it's tough to detect this algorithmically; instead we're going to require that the program metadata include information about the arities, and the parts of the program that that metadata applies to. (program-lambda-list): New accessor. (write-program): Show multiple arities. * module/language/glil/compile-assembly.scm (glil->assembly): Add "arities" to the state of the compiler, and add arities entries as appropriate.
2009-09-27 19:25:58 -04:00
SCM_OUT_OF_RANGE (SCM_ARG2, index);
}
#undef FUNC_NAME
remove heap links in VM frames, incorporate vm frames into normal backtraces * doc/ref/vm.texi (Stack Layout): Update to remove references to the "heap link". * gdbinit: Update for "heap link" removal. * libguile/frames.c: * libguile/frames.h: Update macros and diagram for removal of "heap link". As part of this, we also remove "heap frames", replacing them with "vm frames", which are much like the interpreter's debug objects, but for VM stacks. That is to say, they don't actually hold the stack themselves, just the pointers into stack that's held by a continuation (either captured or current). * libguile/stacks.c (stack_depth, read_frames): Since a "stack" object is really a copy of information that comes from somewhere else, it makes sense to copy over info from the VM, just as `make-stack' does from the evaluator. The tricky bit is to figure out how to interleave VM and interpreter frames. We do that by starting in the interpreter, and whenever the current frame's procedure is actually a program, we switch to the VM stack, switching back when we reach a "bootstrap frame". The last bit is hacky, but it does work... (is_vm_bootstrap_frame): Hacky predicate to see if a VM frame is a bootstrap frame. (scm_make_stack): Accept a VM frame in addition to debug frames. Probably has some bugs in this case. But in the case that the arg is #t (a common case), do the right thing, capturing the top VM frame as well, and interleaving those frames appropriately on the stack. As an accident, we lost the ability to limit the number of frames in the backtrace. We could add that back, but personally I always want *all* frames in the trace... Narrowing still works fine, though there are some hiccups sometimes -- e.g. an outer cut to a procedure that does a tail-call in VM code will never find the cut, as it no longer exists in the continuation. * libguile/vm.h (struct scm_vm): So! Now that we have switched to save stacks in the normal make-stack, there's no more need for `this_frame' or `last_frame'. On the other hand, we can take this opportunity to fix tracing: when we're in a trace hook, we set `trace_frame' on the VM, so we know not to fire hooks when we're already in a hook. (struct scm_vm_cont): Expose this, as make-stack needs it to make VM frames from VM continuations. * libguile/vm.c (scm_vm_trace_frame): New function, gets the current trace frame. (vm_mark, make_vm): Hook up the trace frame. (vm_dispatch_hook): New hook dispatcher, with a dynwind so it does the right thing if the hook exits nonlocally. * libguile/vm-engine.c (vm_run): No more this_frame in the wind data. * libguile/vm-engine.h (RUN_HOOK): Run hooks through the dispatcher. (ALIGN_AS_NON_IMMEDIATE, POP_LIST_ON_STACK): Remove unused code. (NEW_FRAME): Adapt for no HL in the frame. * libguile/vm-i-system.c (goto/args, mv-call, return, return/values): Adapt for no HL in the frame. * module/system/vm/frame.scm: * module/system/vm/vm.scm: Beginnings of some reworkings, needs more thought.
2008-12-26 17:59:46 +01:00
static const char s_scm_frame_return_values[] = "frame-return-values";
static SCM
scm_frame_return_values (SCM frame)
#define FUNC_NAME s_scm_frame_return_values
{
const uint32_t *ip;
union scm_vm_stack_element *fp, *sp;
SCM vals = SCM_EOL;
size_t n;
SCM_VALIDATE_VM_FRAME (1, frame);
ip = SCM_VM_FRAME_IP (frame);
fp = SCM_VM_FRAME_FP (frame);
sp = SCM_VM_FRAME_SP (frame);
if ((*ip & 0xff) != scm_op_return_values)
scm_wrong_type_arg_msg (FUNC_NAME, 1, frame, "not a return frame");
n = SCM_FRAME_NUM_LOCALS (fp, sp);
while (n--)
vals = scm_cons (SCM_FRAME_LOCAL (fp, n), vals);
return vals;
}
#undef FUNC_NAME
SCM_DEFINE (scm_frame_address, "frame-address", 1, 0, 0,
(SCM frame),
"Return the frame pointer for @var{frame}.")
#define FUNC_NAME s_scm_frame_address
{
SCM_VALIDATE_VM_FRAME (1, frame);
return scm_from_ptrdiff_t (SCM_VM_FRAME_FP_OFFSET (frame));
}
#undef FUNC_NAME
SCM_DEFINE (scm_frame_stack_pointer, "frame-stack-pointer", 1, 0, 0,
(SCM frame),
"")
#define FUNC_NAME s_scm_frame_stack_pointer
{
SCM_VALIDATE_VM_FRAME (1, frame);
return scm_from_ptrdiff_t (SCM_VM_FRAME_SP_OFFSET (frame));
}
#undef FUNC_NAME
replace frame implementation with VM frames * libguile/stacks.h: Rework so that a stack doesn't copy information out of VM frames, it just holds onto a VM frame, along with the stack id and length. VM frames are now the only representation of frames in Guile. (scm_t_info_frame, SCM_FRAME_N_SLOTS, SCM_FRAME_REF, SCM_FRAME_NUMBER) (SCM_FRAME_FLAGS, SCM_FRAME_SOURCE, SCM_FRAME_PROC, SCM_FRAME_ARGS) (SCM_FRAME_PREV, SCM_FRAME_NEXT) (SCM_FRAMEF_VOID, SCM_FRAMEF_REAL, SCM_FRAMEF_PROC) (SCM_FRAMEF_EVAL_ARGS, SCM_FRAMEF_OVERFLOW) (SCM_FRAME_VOID_P, SCM_FRAME_REAL_P, SCM_FRAME_PROC_P) (SCM_FRAME_EVAL_ARGS_P, SCM_FRAME_OVERFLOW_P): Remove these macros corresponding to the old frame implementation. (scm_frame_p scm_frame_source, scm_frame_procedure) (scm_frame_arguments): These definitions are now in frames.h. (scm_last_stack_frame): Remove declaration of previously-removed constructor. Probably should re-instate it though. (scm_frame_number, scm_frame_previous, scm_frame_next) (scm_frame_real_p, scm_frame_procedure_p, scm_frame_evaluating_args_p) (scm_frame_overflow_p) : Remove these procedures corresponding to the old stack implementation. * libguile/stacks.c: Update for new frames implementation. * libguile/frames.h: * libguile/frames.c: Rename functions operating on VM frames to have a scm_frame prefix, not scm_vm_frame -- because they really are the only frames we have. Rename corresponding Scheme functions too, from vm-frame-foo to frame-foo. * libguile/deprecated.h: Remove scm_stack and scm_info_frame data types. * libguile/vm.c (vm_dispatch_hook): Adapt to scm_c_make_frame name change. * module/system/vm/frame.scm: No need to export functions provided frames.c now, as we load those procedures into the default environment now. Rename functions, and remove a couple of outdated, unused functions. The bottom half of this file is still bitrotten, though. * libguile/backtrace.c: Rework to operate on the new frame representation. Also fix a bug displaying file names for compiled procedures. * libguile/init.c: Load the VM much earlier, just because we can. Also it allows us to have frames.[ch] loaded in time for stacks to be initialized, so that scm_frame_arguments can do the right thing.
2009-12-03 13:09:58 +01:00
SCM_DEFINE (scm_frame_instruction_pointer, "frame-instruction-pointer", 1, 0, 0,
runtime and debugging support for callee-parsed procedure args * libguile/objcodes.h: Bump for metadata format change. * libguile/frames.h: Rework so we don't frob the program's nargs, nlocs, etc at runtime. Instead we don't really know what's a local var, an argument, or an intermediate value. It's a little unfortunate, but this will allow for case-lambda, and eventually for good polymorphic generic dispatch; and the nlocs etc can be heuristically reconstructed. Such a reconstruction would be better done at the Scheme level, though. (SCM_FRAME_STACK_ADDRESS): New macro, the pointer to the base of the stack elements (not counting the program). (SCM_FRAME_UPPER_ADDRESS): Repurpose to be the address of the last element in the bookkeeping part of the stack -- i.e. to point to the return address. * libguile/vm-engine.h: * libguile/vm-i-system.c: Adapt to removal of stack_base. Though we still detect stack-smashing underflow, we don't do so as precisely as we did before, because now we only detect overwriting of the frame metadata. * libguile/vm-engine.c (vm_engine): Remove the stack_base variable. It is unnecessary, and difficult to keep track of in the face of case-lambda. Also fix miscommented "ra" and "mvra" pushes. Push the vp->ip as the first ra... * libguile/vm-i-system.c (halt): ...because here we can restore the vp->ip instead of setting ip to 0. Allows us to introspect ips all down the stack, including in recursive VM invocations. * libguile/frames.h: * libguile/frames.c (scm_vm_frame_stack): Removed, because it's getting more difficult to tell what's an argument and what's a temporary stack element. (scm_vm_frame_num_locals): New accessor. (scm_vm_frame_instruction_pointer): New accessor. (scm_vm_frame_arguments): Defer to an implementation in Scheme. (scm_vm_frame_num_locals scm_vm_frame_local_ref) (scm_vm_frame_local_set_x): Since we can get not-yet-active frames on the stack now, with our current calling convention, we have to add a heuristic here to jump over those frames -- because frames have pointers in them, not Scheme values. * libguile/programs.h: * libguile/programs.c (scm_program_arity): Remove, in favor of.. (scm_program_arities): ...this, which a list of arities, in a new format, occupying a slot in the metadata. * module/language/assembly/decompile-bytecode.scm (decode-load-program): Fix mv-call decompilation. * module/system/vm/frame.scm (vm-frame-bindings, vm-frame-binding-ref) (vm-frame-binding-set!): New functions, to access bindings by name in a frame. (vm-frame-arguments): Function now implemented in Scheme. Commented fairly extensively. * module/system/vm/program.scm (program-bindings-by-index) (program-bindings-for-ip): New accessors, parsing the program bindings metadata into something more useful. (program-arities, program-arguments): In a case-lambda world, we have to assume that programs can have multiple arities. But it's tough to detect this algorithmically; instead we're going to require that the program metadata include information about the arities, and the parts of the program that that metadata applies to. (program-lambda-list): New accessor. (write-program): Show multiple arities. * module/language/glil/compile-assembly.scm (glil->assembly): Add "arities" to the state of the compiler, and add arities entries as appropriate.
2009-09-27 19:25:58 -04:00
(SCM frame),
"")
replace frame implementation with VM frames * libguile/stacks.h: Rework so that a stack doesn't copy information out of VM frames, it just holds onto a VM frame, along with the stack id and length. VM frames are now the only representation of frames in Guile. (scm_t_info_frame, SCM_FRAME_N_SLOTS, SCM_FRAME_REF, SCM_FRAME_NUMBER) (SCM_FRAME_FLAGS, SCM_FRAME_SOURCE, SCM_FRAME_PROC, SCM_FRAME_ARGS) (SCM_FRAME_PREV, SCM_FRAME_NEXT) (SCM_FRAMEF_VOID, SCM_FRAMEF_REAL, SCM_FRAMEF_PROC) (SCM_FRAMEF_EVAL_ARGS, SCM_FRAMEF_OVERFLOW) (SCM_FRAME_VOID_P, SCM_FRAME_REAL_P, SCM_FRAME_PROC_P) (SCM_FRAME_EVAL_ARGS_P, SCM_FRAME_OVERFLOW_P): Remove these macros corresponding to the old frame implementation. (scm_frame_p scm_frame_source, scm_frame_procedure) (scm_frame_arguments): These definitions are now in frames.h. (scm_last_stack_frame): Remove declaration of previously-removed constructor. Probably should re-instate it though. (scm_frame_number, scm_frame_previous, scm_frame_next) (scm_frame_real_p, scm_frame_procedure_p, scm_frame_evaluating_args_p) (scm_frame_overflow_p) : Remove these procedures corresponding to the old stack implementation. * libguile/stacks.c: Update for new frames implementation. * libguile/frames.h: * libguile/frames.c: Rename functions operating on VM frames to have a scm_frame prefix, not scm_vm_frame -- because they really are the only frames we have. Rename corresponding Scheme functions too, from vm-frame-foo to frame-foo. * libguile/deprecated.h: Remove scm_stack and scm_info_frame data types. * libguile/vm.c (vm_dispatch_hook): Adapt to scm_c_make_frame name change. * module/system/vm/frame.scm: No need to export functions provided frames.c now, as we load those procedures into the default environment now. Rename functions, and remove a couple of outdated, unused functions. The bottom half of this file is still bitrotten, though. * libguile/backtrace.c: Rework to operate on the new frame representation. Also fix a bug displaying file names for compiled procedures. * libguile/init.c: Load the VM much earlier, just because we can. Also it allows us to have frames.[ch] loaded in time for stacks to be initialized, so that scm_frame_arguments can do the right thing.
2009-12-03 13:09:58 +01:00
#define FUNC_NAME s_scm_frame_instruction_pointer
runtime and debugging support for callee-parsed procedure args * libguile/objcodes.h: Bump for metadata format change. * libguile/frames.h: Rework so we don't frob the program's nargs, nlocs, etc at runtime. Instead we don't really know what's a local var, an argument, or an intermediate value. It's a little unfortunate, but this will allow for case-lambda, and eventually for good polymorphic generic dispatch; and the nlocs etc can be heuristically reconstructed. Such a reconstruction would be better done at the Scheme level, though. (SCM_FRAME_STACK_ADDRESS): New macro, the pointer to the base of the stack elements (not counting the program). (SCM_FRAME_UPPER_ADDRESS): Repurpose to be the address of the last element in the bookkeeping part of the stack -- i.e. to point to the return address. * libguile/vm-engine.h: * libguile/vm-i-system.c: Adapt to removal of stack_base. Though we still detect stack-smashing underflow, we don't do so as precisely as we did before, because now we only detect overwriting of the frame metadata. * libguile/vm-engine.c (vm_engine): Remove the stack_base variable. It is unnecessary, and difficult to keep track of in the face of case-lambda. Also fix miscommented "ra" and "mvra" pushes. Push the vp->ip as the first ra... * libguile/vm-i-system.c (halt): ...because here we can restore the vp->ip instead of setting ip to 0. Allows us to introspect ips all down the stack, including in recursive VM invocations. * libguile/frames.h: * libguile/frames.c (scm_vm_frame_stack): Removed, because it's getting more difficult to tell what's an argument and what's a temporary stack element. (scm_vm_frame_num_locals): New accessor. (scm_vm_frame_instruction_pointer): New accessor. (scm_vm_frame_arguments): Defer to an implementation in Scheme. (scm_vm_frame_num_locals scm_vm_frame_local_ref) (scm_vm_frame_local_set_x): Since we can get not-yet-active frames on the stack now, with our current calling convention, we have to add a heuristic here to jump over those frames -- because frames have pointers in them, not Scheme values. * libguile/programs.h: * libguile/programs.c (scm_program_arity): Remove, in favor of.. (scm_program_arities): ...this, which a list of arities, in a new format, occupying a slot in the metadata. * module/language/assembly/decompile-bytecode.scm (decode-load-program): Fix mv-call decompilation. * module/system/vm/frame.scm (vm-frame-bindings, vm-frame-binding-ref) (vm-frame-binding-set!): New functions, to access bindings by name in a frame. (vm-frame-arguments): Function now implemented in Scheme. Commented fairly extensively. * module/system/vm/program.scm (program-bindings-by-index) (program-bindings-for-ip): New accessors, parsing the program bindings metadata into something more useful. (program-arities, program-arguments): In a case-lambda world, we have to assume that programs can have multiple arities. But it's tough to detect this algorithmically; instead we're going to require that the program metadata include information about the arities, and the parts of the program that that metadata applies to. (program-lambda-list): New accessor. (write-program): Show multiple arities. * module/language/glil/compile-assembly.scm (glil->assembly): Add "arities" to the state of the compiler, and add arities entries as appropriate.
2009-09-27 19:25:58 -04:00
{
SCM_VALIDATE_VM_FRAME (1, frame);
Replace uses of scm_t_int8, scm_t_uintmax, etc with stdint types * libguile/bitvectors.c: * libguile/bitvectors.h: * libguile/bytevectors.c: * libguile/bytevectors.h: * libguile/chars.c: * libguile/continuations.c: * libguile/control.c: * libguile/conv-integer.i.c: * libguile/conv-uinteger.i.c: * libguile/dynstack.c: * libguile/dynstack.h: * libguile/foreign.c: * libguile/frames.c: * libguile/frames.h: * libguile/gc-inline.h: * libguile/gc.h: * libguile/gsubr.c: * libguile/gsubr.h: * libguile/hash.c: * libguile/i18n.c: * libguile/instructions.c: * libguile/intrinsics.c: * libguile/intrinsics.h: * libguile/loader.c: * libguile/loader.h: * libguile/numbers.c: * libguile/numbers.h: * libguile/pairs.c: * libguile/ports-internal.h: * libguile/ports.c: * libguile/ports.h: * libguile/posix.c: * libguile/print.c: * libguile/print.h: * libguile/programs.c: * libguile/programs.h: * libguile/r6rs-ports.c: * libguile/random.c: * libguile/random.h: * libguile/scm.h: * libguile/socket.c: * libguile/srfi-4.c: * libguile/srfi-4.h: * libguile/stacks.c: * libguile/stime.c: * libguile/strings.c: * libguile/struct.c: * libguile/struct.h: * libguile/symbols.c: * libguile/threads.c: * libguile/threads.h: * libguile/uniform.c: * libguile/vm-engine.c: * libguile/vm.c: * libguile/vm.h: * libguile/vports.c: * test-suite/standalone/test-conversion.c: * test-suite/standalone/test-ffi-lib.c: * test-suite/standalone/test-scm-take-u8vector.c: * test-suite/standalone/test-srfi-4.c: Replace e.g. scm_t_uint8 with uint8_t.
2018-06-21 08:39:03 +02:00
return scm_from_uintptr_t ((uintptr_t) SCM_VM_FRAME_IP (frame));
2001-04-22 02:13:48 +00:00
}
#undef FUNC_NAME
replace frame implementation with VM frames * libguile/stacks.h: Rework so that a stack doesn't copy information out of VM frames, it just holds onto a VM frame, along with the stack id and length. VM frames are now the only representation of frames in Guile. (scm_t_info_frame, SCM_FRAME_N_SLOTS, SCM_FRAME_REF, SCM_FRAME_NUMBER) (SCM_FRAME_FLAGS, SCM_FRAME_SOURCE, SCM_FRAME_PROC, SCM_FRAME_ARGS) (SCM_FRAME_PREV, SCM_FRAME_NEXT) (SCM_FRAMEF_VOID, SCM_FRAMEF_REAL, SCM_FRAMEF_PROC) (SCM_FRAMEF_EVAL_ARGS, SCM_FRAMEF_OVERFLOW) (SCM_FRAME_VOID_P, SCM_FRAME_REAL_P, SCM_FRAME_PROC_P) (SCM_FRAME_EVAL_ARGS_P, SCM_FRAME_OVERFLOW_P): Remove these macros corresponding to the old frame implementation. (scm_frame_p scm_frame_source, scm_frame_procedure) (scm_frame_arguments): These definitions are now in frames.h. (scm_last_stack_frame): Remove declaration of previously-removed constructor. Probably should re-instate it though. (scm_frame_number, scm_frame_previous, scm_frame_next) (scm_frame_real_p, scm_frame_procedure_p, scm_frame_evaluating_args_p) (scm_frame_overflow_p) : Remove these procedures corresponding to the old stack implementation. * libguile/stacks.c: Update for new frames implementation. * libguile/frames.h: * libguile/frames.c: Rename functions operating on VM frames to have a scm_frame prefix, not scm_vm_frame -- because they really are the only frames we have. Rename corresponding Scheme functions too, from vm-frame-foo to frame-foo. * libguile/deprecated.h: Remove scm_stack and scm_info_frame data types. * libguile/vm.c (vm_dispatch_hook): Adapt to scm_c_make_frame name change. * module/system/vm/frame.scm: No need to export functions provided frames.c now, as we load those procedures into the default environment now. Rename functions, and remove a couple of outdated, unused functions. The bottom half of this file is still bitrotten, though. * libguile/backtrace.c: Rework to operate on the new frame representation. Also fix a bug displaying file names for compiled procedures. * libguile/init.c: Load the VM much earlier, just because we can. Also it allows us to have frames.[ch] loaded in time for stacks to be initialized, so that scm_frame_arguments can do the right thing.
2009-12-03 13:09:58 +01:00
SCM_DEFINE (scm_frame_return_address, "frame-return-address", 1, 0, 0,
2001-04-22 02:13:48 +00:00
(SCM frame),
"")
replace frame implementation with VM frames * libguile/stacks.h: Rework so that a stack doesn't copy information out of VM frames, it just holds onto a VM frame, along with the stack id and length. VM frames are now the only representation of frames in Guile. (scm_t_info_frame, SCM_FRAME_N_SLOTS, SCM_FRAME_REF, SCM_FRAME_NUMBER) (SCM_FRAME_FLAGS, SCM_FRAME_SOURCE, SCM_FRAME_PROC, SCM_FRAME_ARGS) (SCM_FRAME_PREV, SCM_FRAME_NEXT) (SCM_FRAMEF_VOID, SCM_FRAMEF_REAL, SCM_FRAMEF_PROC) (SCM_FRAMEF_EVAL_ARGS, SCM_FRAMEF_OVERFLOW) (SCM_FRAME_VOID_P, SCM_FRAME_REAL_P, SCM_FRAME_PROC_P) (SCM_FRAME_EVAL_ARGS_P, SCM_FRAME_OVERFLOW_P): Remove these macros corresponding to the old frame implementation. (scm_frame_p scm_frame_source, scm_frame_procedure) (scm_frame_arguments): These definitions are now in frames.h. (scm_last_stack_frame): Remove declaration of previously-removed constructor. Probably should re-instate it though. (scm_frame_number, scm_frame_previous, scm_frame_next) (scm_frame_real_p, scm_frame_procedure_p, scm_frame_evaluating_args_p) (scm_frame_overflow_p) : Remove these procedures corresponding to the old stack implementation. * libguile/stacks.c: Update for new frames implementation. * libguile/frames.h: * libguile/frames.c: Rename functions operating on VM frames to have a scm_frame prefix, not scm_vm_frame -- because they really are the only frames we have. Rename corresponding Scheme functions too, from vm-frame-foo to frame-foo. * libguile/deprecated.h: Remove scm_stack and scm_info_frame data types. * libguile/vm.c (vm_dispatch_hook): Adapt to scm_c_make_frame name change. * module/system/vm/frame.scm: No need to export functions provided frames.c now, as we load those procedures into the default environment now. Rename functions, and remove a couple of outdated, unused functions. The bottom half of this file is still bitrotten, though. * libguile/backtrace.c: Rework to operate on the new frame representation. Also fix a bug displaying file names for compiled procedures. * libguile/init.c: Load the VM much earlier, just because we can. Also it allows us to have frames.[ch] loaded in time for stacks to be initialized, so that scm_frame_arguments can do the right thing.
2009-12-03 13:09:58 +01:00
#define FUNC_NAME s_scm_frame_return_address
2001-04-22 02:13:48 +00:00
{
remove heap links in VM frames, incorporate vm frames into normal backtraces * doc/ref/vm.texi (Stack Layout): Update to remove references to the "heap link". * gdbinit: Update for "heap link" removal. * libguile/frames.c: * libguile/frames.h: Update macros and diagram for removal of "heap link". As part of this, we also remove "heap frames", replacing them with "vm frames", which are much like the interpreter's debug objects, but for VM stacks. That is to say, they don't actually hold the stack themselves, just the pointers into stack that's held by a continuation (either captured or current). * libguile/stacks.c (stack_depth, read_frames): Since a "stack" object is really a copy of information that comes from somewhere else, it makes sense to copy over info from the VM, just as `make-stack' does from the evaluator. The tricky bit is to figure out how to interleave VM and interpreter frames. We do that by starting in the interpreter, and whenever the current frame's procedure is actually a program, we switch to the VM stack, switching back when we reach a "bootstrap frame". The last bit is hacky, but it does work... (is_vm_bootstrap_frame): Hacky predicate to see if a VM frame is a bootstrap frame. (scm_make_stack): Accept a VM frame in addition to debug frames. Probably has some bugs in this case. But in the case that the arg is #t (a common case), do the right thing, capturing the top VM frame as well, and interleaving those frames appropriately on the stack. As an accident, we lost the ability to limit the number of frames in the backtrace. We could add that back, but personally I always want *all* frames in the trace... Narrowing still works fine, though there are some hiccups sometimes -- e.g. an outer cut to a procedure that does a tail-call in VM code will never find the cut, as it no longer exists in the continuation. * libguile/vm.h (struct scm_vm): So! Now that we have switched to save stacks in the normal make-stack, there's no more need for `this_frame' or `last_frame'. On the other hand, we can take this opportunity to fix tracing: when we're in a trace hook, we set `trace_frame' on the VM, so we know not to fire hooks when we're already in a hook. (struct scm_vm_cont): Expose this, as make-stack needs it to make VM frames from VM continuations. * libguile/vm.c (scm_vm_trace_frame): New function, gets the current trace frame. (vm_mark, make_vm): Hook up the trace frame. (vm_dispatch_hook): New hook dispatcher, with a dynwind so it does the right thing if the hook exits nonlocally. * libguile/vm-engine.c (vm_run): No more this_frame in the wind data. * libguile/vm-engine.h (RUN_HOOK): Run hooks through the dispatcher. (ALIGN_AS_NON_IMMEDIATE, POP_LIST_ON_STACK): Remove unused code. (NEW_FRAME): Adapt for no HL in the frame. * libguile/vm-i-system.c (goto/args, mv-call, return, return/values): Adapt for no HL in the frame. * module/system/vm/frame.scm: * module/system/vm/vm.scm: Beginnings of some reworkings, needs more thought.
2008-12-26 17:59:46 +01:00
SCM_VALIDATE_VM_FRAME (1, frame);
return scm_from_uintptr_t ((uintptr_t) (SCM_FRAME_VIRTUAL_RETURN_ADDRESS
(SCM_VM_FRAME_FP (frame))));
2001-04-22 02:13:48 +00:00
}
#undef FUNC_NAME
replace frame implementation with VM frames * libguile/stacks.h: Rework so that a stack doesn't copy information out of VM frames, it just holds onto a VM frame, along with the stack id and length. VM frames are now the only representation of frames in Guile. (scm_t_info_frame, SCM_FRAME_N_SLOTS, SCM_FRAME_REF, SCM_FRAME_NUMBER) (SCM_FRAME_FLAGS, SCM_FRAME_SOURCE, SCM_FRAME_PROC, SCM_FRAME_ARGS) (SCM_FRAME_PREV, SCM_FRAME_NEXT) (SCM_FRAMEF_VOID, SCM_FRAMEF_REAL, SCM_FRAMEF_PROC) (SCM_FRAMEF_EVAL_ARGS, SCM_FRAMEF_OVERFLOW) (SCM_FRAME_VOID_P, SCM_FRAME_REAL_P, SCM_FRAME_PROC_P) (SCM_FRAME_EVAL_ARGS_P, SCM_FRAME_OVERFLOW_P): Remove these macros corresponding to the old frame implementation. (scm_frame_p scm_frame_source, scm_frame_procedure) (scm_frame_arguments): These definitions are now in frames.h. (scm_last_stack_frame): Remove declaration of previously-removed constructor. Probably should re-instate it though. (scm_frame_number, scm_frame_previous, scm_frame_next) (scm_frame_real_p, scm_frame_procedure_p, scm_frame_evaluating_args_p) (scm_frame_overflow_p) : Remove these procedures corresponding to the old stack implementation. * libguile/stacks.c: Update for new frames implementation. * libguile/frames.h: * libguile/frames.c: Rename functions operating on VM frames to have a scm_frame prefix, not scm_vm_frame -- because they really are the only frames we have. Rename corresponding Scheme functions too, from vm-frame-foo to frame-foo. * libguile/deprecated.h: Remove scm_stack and scm_info_frame data types. * libguile/vm.c (vm_dispatch_hook): Adapt to scm_c_make_frame name change. * module/system/vm/frame.scm: No need to export functions provided frames.c now, as we load those procedures into the default environment now. Rename functions, and remove a couple of outdated, unused functions. The bottom half of this file is still bitrotten, though. * libguile/backtrace.c: Rework to operate on the new frame representation. Also fix a bug displaying file names for compiled procedures. * libguile/init.c: Load the VM much earlier, just because we can. Also it allows us to have frames.[ch] loaded in time for stacks to be initialized, so that scm_frame_arguments can do the right thing.
2009-12-03 13:09:58 +01:00
SCM_DEFINE (scm_frame_dynamic_link, "frame-dynamic-link", 1, 0, 0,
2001-04-22 02:13:48 +00:00
(SCM frame),
"")
replace frame implementation with VM frames * libguile/stacks.h: Rework so that a stack doesn't copy information out of VM frames, it just holds onto a VM frame, along with the stack id and length. VM frames are now the only representation of frames in Guile. (scm_t_info_frame, SCM_FRAME_N_SLOTS, SCM_FRAME_REF, SCM_FRAME_NUMBER) (SCM_FRAME_FLAGS, SCM_FRAME_SOURCE, SCM_FRAME_PROC, SCM_FRAME_ARGS) (SCM_FRAME_PREV, SCM_FRAME_NEXT) (SCM_FRAMEF_VOID, SCM_FRAMEF_REAL, SCM_FRAMEF_PROC) (SCM_FRAMEF_EVAL_ARGS, SCM_FRAMEF_OVERFLOW) (SCM_FRAME_VOID_P, SCM_FRAME_REAL_P, SCM_FRAME_PROC_P) (SCM_FRAME_EVAL_ARGS_P, SCM_FRAME_OVERFLOW_P): Remove these macros corresponding to the old frame implementation. (scm_frame_p scm_frame_source, scm_frame_procedure) (scm_frame_arguments): These definitions are now in frames.h. (scm_last_stack_frame): Remove declaration of previously-removed constructor. Probably should re-instate it though. (scm_frame_number, scm_frame_previous, scm_frame_next) (scm_frame_real_p, scm_frame_procedure_p, scm_frame_evaluating_args_p) (scm_frame_overflow_p) : Remove these procedures corresponding to the old stack implementation. * libguile/stacks.c: Update for new frames implementation. * libguile/frames.h: * libguile/frames.c: Rename functions operating on VM frames to have a scm_frame prefix, not scm_vm_frame -- because they really are the only frames we have. Rename corresponding Scheme functions too, from vm-frame-foo to frame-foo. * libguile/deprecated.h: Remove scm_stack and scm_info_frame data types. * libguile/vm.c (vm_dispatch_hook): Adapt to scm_c_make_frame name change. * module/system/vm/frame.scm: No need to export functions provided frames.c now, as we load those procedures into the default environment now. Rename functions, and remove a couple of outdated, unused functions. The bottom half of this file is still bitrotten, though. * libguile/backtrace.c: Rework to operate on the new frame representation. Also fix a bug displaying file names for compiled procedures. * libguile/init.c: Load the VM much earlier, just because we can. Also it allows us to have frames.[ch] loaded in time for stacks to be initialized, so that scm_frame_arguments can do the right thing.
2009-12-03 13:09:58 +01:00
#define FUNC_NAME s_scm_frame_dynamic_link
2001-04-22 02:13:48 +00:00
{
remove heap links in VM frames, incorporate vm frames into normal backtraces * doc/ref/vm.texi (Stack Layout): Update to remove references to the "heap link". * gdbinit: Update for "heap link" removal. * libguile/frames.c: * libguile/frames.h: Update macros and diagram for removal of "heap link". As part of this, we also remove "heap frames", replacing them with "vm frames", which are much like the interpreter's debug objects, but for VM stacks. That is to say, they don't actually hold the stack themselves, just the pointers into stack that's held by a continuation (either captured or current). * libguile/stacks.c (stack_depth, read_frames): Since a "stack" object is really a copy of information that comes from somewhere else, it makes sense to copy over info from the VM, just as `make-stack' does from the evaluator. The tricky bit is to figure out how to interleave VM and interpreter frames. We do that by starting in the interpreter, and whenever the current frame's procedure is actually a program, we switch to the VM stack, switching back when we reach a "bootstrap frame". The last bit is hacky, but it does work... (is_vm_bootstrap_frame): Hacky predicate to see if a VM frame is a bootstrap frame. (scm_make_stack): Accept a VM frame in addition to debug frames. Probably has some bugs in this case. But in the case that the arg is #t (a common case), do the right thing, capturing the top VM frame as well, and interleaving those frames appropriately on the stack. As an accident, we lost the ability to limit the number of frames in the backtrace. We could add that back, but personally I always want *all* frames in the trace... Narrowing still works fine, though there are some hiccups sometimes -- e.g. an outer cut to a procedure that does a tail-call in VM code will never find the cut, as it no longer exists in the continuation. * libguile/vm.h (struct scm_vm): So! Now that we have switched to save stacks in the normal make-stack, there's no more need for `this_frame' or `last_frame'. On the other hand, we can take this opportunity to fix tracing: when we're in a trace hook, we set `trace_frame' on the VM, so we know not to fire hooks when we're already in a hook. (struct scm_vm_cont): Expose this, as make-stack needs it to make VM frames from VM continuations. * libguile/vm.c (scm_vm_trace_frame): New function, gets the current trace frame. (vm_mark, make_vm): Hook up the trace frame. (vm_dispatch_hook): New hook dispatcher, with a dynwind so it does the right thing if the hook exits nonlocally. * libguile/vm-engine.c (vm_run): No more this_frame in the wind data. * libguile/vm-engine.h (RUN_HOOK): Run hooks through the dispatcher. (ALIGN_AS_NON_IMMEDIATE, POP_LIST_ON_STACK): Remove unused code. (NEW_FRAME): Adapt for no HL in the frame. * libguile/vm-i-system.c (goto/args, mv-call, return, return/values): Adapt for no HL in the frame. * module/system/vm/frame.scm: * module/system/vm/vm.scm: Beginnings of some reworkings, needs more thought.
2008-12-26 17:59:46 +01:00
SCM_VALIDATE_VM_FRAME (1, frame);
/* fixme: munge fp if holder is a continuation */
return scm_from_uintptr_t
Replace uses of scm_t_int8, scm_t_uintmax, etc with stdint types * libguile/bitvectors.c: * libguile/bitvectors.h: * libguile/bytevectors.c: * libguile/bytevectors.h: * libguile/chars.c: * libguile/continuations.c: * libguile/control.c: * libguile/conv-integer.i.c: * libguile/conv-uinteger.i.c: * libguile/dynstack.c: * libguile/dynstack.h: * libguile/foreign.c: * libguile/frames.c: * libguile/frames.h: * libguile/gc-inline.h: * libguile/gc.h: * libguile/gsubr.c: * libguile/gsubr.h: * libguile/hash.c: * libguile/i18n.c: * libguile/instructions.c: * libguile/intrinsics.c: * libguile/intrinsics.h: * libguile/loader.c: * libguile/loader.h: * libguile/numbers.c: * libguile/numbers.h: * libguile/pairs.c: * libguile/ports-internal.h: * libguile/ports.c: * libguile/ports.h: * libguile/posix.c: * libguile/print.c: * libguile/print.h: * libguile/programs.c: * libguile/programs.h: * libguile/r6rs-ports.c: * libguile/random.c: * libguile/random.h: * libguile/scm.h: * libguile/socket.c: * libguile/srfi-4.c: * libguile/srfi-4.h: * libguile/stacks.c: * libguile/stime.c: * libguile/strings.c: * libguile/struct.c: * libguile/struct.h: * libguile/symbols.c: * libguile/threads.c: * libguile/threads.h: * libguile/uniform.c: * libguile/vm-engine.c: * libguile/vm.c: * libguile/vm.h: * libguile/vports.c: * test-suite/standalone/test-conversion.c: * test-suite/standalone/test-ffi-lib.c: * test-suite/standalone/test-scm-take-u8vector.c: * test-suite/standalone/test-srfi-4.c: Replace e.g. scm_t_uint8 with uint8_t.
2018-06-21 08:39:03 +02:00
((uintptr_t)
SCM_FRAME_DYNAMIC_LINK (SCM_VM_FRAME_FP (frame)));
2001-04-22 02:13:48 +00:00
}
#undef FUNC_NAME
int
scm_c_frame_previous (enum scm_vm_frame_kind kind, struct scm_frame *frame)
remove heap links in VM frames, incorporate vm frames into normal backtraces * doc/ref/vm.texi (Stack Layout): Update to remove references to the "heap link". * gdbinit: Update for "heap link" removal. * libguile/frames.c: * libguile/frames.h: Update macros and diagram for removal of "heap link". As part of this, we also remove "heap frames", replacing them with "vm frames", which are much like the interpreter's debug objects, but for VM stacks. That is to say, they don't actually hold the stack themselves, just the pointers into stack that's held by a continuation (either captured or current). * libguile/stacks.c (stack_depth, read_frames): Since a "stack" object is really a copy of information that comes from somewhere else, it makes sense to copy over info from the VM, just as `make-stack' does from the evaluator. The tricky bit is to figure out how to interleave VM and interpreter frames. We do that by starting in the interpreter, and whenever the current frame's procedure is actually a program, we switch to the VM stack, switching back when we reach a "bootstrap frame". The last bit is hacky, but it does work... (is_vm_bootstrap_frame): Hacky predicate to see if a VM frame is a bootstrap frame. (scm_make_stack): Accept a VM frame in addition to debug frames. Probably has some bugs in this case. But in the case that the arg is #t (a common case), do the right thing, capturing the top VM frame as well, and interleaving those frames appropriately on the stack. As an accident, we lost the ability to limit the number of frames in the backtrace. We could add that back, but personally I always want *all* frames in the trace... Narrowing still works fine, though there are some hiccups sometimes -- e.g. an outer cut to a procedure that does a tail-call in VM code will never find the cut, as it no longer exists in the continuation. * libguile/vm.h (struct scm_vm): So! Now that we have switched to save stacks in the normal make-stack, there's no more need for `this_frame' or `last_frame'. On the other hand, we can take this opportunity to fix tracing: when we're in a trace hook, we set `trace_frame' on the VM, so we know not to fire hooks when we're already in a hook. (struct scm_vm_cont): Expose this, as make-stack needs it to make VM frames from VM continuations. * libguile/vm.c (scm_vm_trace_frame): New function, gets the current trace frame. (vm_mark, make_vm): Hook up the trace frame. (vm_dispatch_hook): New hook dispatcher, with a dynwind so it does the right thing if the hook exits nonlocally. * libguile/vm-engine.c (vm_run): No more this_frame in the wind data. * libguile/vm-engine.h (RUN_HOOK): Run hooks through the dispatcher. (ALIGN_AS_NON_IMMEDIATE, POP_LIST_ON_STACK): Remove unused code. (NEW_FRAME): Adapt for no HL in the frame. * libguile/vm-i-system.c (goto/args, mv-call, return, return/values): Adapt for no HL in the frame. * module/system/vm/frame.scm: * module/system/vm/vm.scm: Beginnings of some reworkings, needs more thought.
2008-12-26 17:59:46 +01:00
{
VM stack grows downward Adapt VM stack to grow downward. This will make native compilation look more like the VM code, as we will be able to use native CALL instructions, taking proper advantage of the return address buffer. * libguile/continuations.c (scm_i_continuation_to_frame): Record offsets from stack top. * libguile/control.c (scm_i_prompt_pop_abort_args_x): Adapt for reversed order of arguments, and instead of relying on the abort to push on the number of arguments, make the caller save the stack depth, which allows us to compute the number of arguments ourselves. (reify_partial_continuation, scm_c_abort): Adapt to reversed stack order. * libguile/dynstack.c (scm_dynstack_wind_prompt): Since we wind the stack in a downward direction, subtract the reloc instead of adding it. * libguile/dynstack.h (SCM_F_DYNSTACK_PROMPT_ESCAPE_ONLY): Remove flag; instead rely on prompt-establishing code to save the stack depth. * libguile/eval.c (eval): Remove extraneous "volatile" declarations for variables that are not re-set between the setjmp and any longjmp. Adapt to save stack depth before instating the prompt. * libguile/foreign.c (scm_i_foreign_call): Adapt to receive arguments in reverse order. * libguile/frames.c (frame_stack_top, scm_i_frame_stack_top): Adapt to compute stack top instead of stack bottom. (scm_c_frame_closure): Adapt to stack growth change. (scm_frame_num_locals, scm_frame_local_ref, scm_frame_set_x): Use union data type to access stack. (RELOC): Reformat. (scm_c_frame_previous): Adapt to stack growth change. * libguile/frames.h: Adapt stack diagram to indicate that the stack grows up. (union scm_vm_stack_element): New data type used to access items on the stack. (SCM_FRAME_PREVIOUS_SP) (SCM_FRAME_RETURN_ADDRESS, SCM_FRAME_SET_RETURN_ADDRESS) (SCM_FRAME_DYNAMIC_LINK, SCM_FRAME_SET_DYNAMIC_LINK) (SCM_FRAME_LOCAL, SCM_FRAME_NUM_LOCALS): Adapt to stack representation change. (SCM_FRAME_SLOT): New helper. (SCM_VM_FRAME_FP, SCM_VM_FRAME_SP): Adapt to stack growth change. * libguile/stacks.c (scm_make_stack): Record offsets from top of stack. * libguile/throw.c (catch): Adapt to scm_i_prompt_pop_abort_args_x change. * libguile/vm-engine.c (ALLOC_FRAME, RESET_FRAME): (FRAME_LOCALS_COUNT_FROM): Adapt to stack growth change. (LOCAL_ADDRESS): Use SCM_FRAME_SLOT to get the address as the proper data type. (RETURN_ONE_VALUE, RETURN_VALUE_LIST): Adapt to stack growth change. (apply): Shuffling up the SMOB apply args can cause the stack to expand, so use ALLOC_FRAME instead of RESET_FRAME. (vm_engine): Adapt for stack growth change. * libguile/vm.c (vm_increase_sp, vm_push_sp, vm_restore_sp): Adapt to stack representation change. (scm_i_vm_cont_to_frame): Adapt to take offsets from the top. (scm_i_vm_capture_stack): Adapt to capture from the top. (vm_return_to_continuation_inner): Adapt for data type changes. (vm_return_to_continuation): Likewise, and instead of looping, just splat the saved arguments on with memcpy. (vm_dispatch_hook): Adapt to receive arguments in the reverse order. Adapt callers. (vm_abort): There is never a tail argument. Adapt to stack representation change. (vm_reinstate_partial_continuation) (vm_reinstate_partial_continuation_inner): Adapt to stack growth change. (allocate_stack, free_stack): Adapt to data type change. (expand_stack): Don't try to mremap(), as you can't grow a mapping from the bottom. Without knowing that there's a free mapping space right below the old stack, which there usually isn't on Linux, we have to copy. We can't use MAP_GROWSDOWN because Linux is buggy. (make_vm): Adapt to stack representation changes. (return_unused_stack_to_os): Round down instead of up, as the stack grows down. (scm_i_vm_mark_stack): Adapt to walk up the stack. (scm_i_vm_free_stack): Adapt to scm_vm changes. (vm_expand_stack_inner, reset_stack_limit, vm_expand_stack): Adapt to the stack growing down. (scm_call_n): Adapt to the stack growing down. Don't allow argv to point into the stack. * libguile/vm.h (struct scm_vm, struct scm_vm_cont): Adapt to hold the stack top and bottom.
2015-09-22 10:24:30 +00:00
union scm_vm_stack_element *this_fp, *new_fp, *new_sp;
union scm_vm_stack_element *stack_top = frame_stack_top (kind, frame);
again:
VM stack grows downward Adapt VM stack to grow downward. This will make native compilation look more like the VM code, as we will be able to use native CALL instructions, taking proper advantage of the return address buffer. * libguile/continuations.c (scm_i_continuation_to_frame): Record offsets from stack top. * libguile/control.c (scm_i_prompt_pop_abort_args_x): Adapt for reversed order of arguments, and instead of relying on the abort to push on the number of arguments, make the caller save the stack depth, which allows us to compute the number of arguments ourselves. (reify_partial_continuation, scm_c_abort): Adapt to reversed stack order. * libguile/dynstack.c (scm_dynstack_wind_prompt): Since we wind the stack in a downward direction, subtract the reloc instead of adding it. * libguile/dynstack.h (SCM_F_DYNSTACK_PROMPT_ESCAPE_ONLY): Remove flag; instead rely on prompt-establishing code to save the stack depth. * libguile/eval.c (eval): Remove extraneous "volatile" declarations for variables that are not re-set between the setjmp and any longjmp. Adapt to save stack depth before instating the prompt. * libguile/foreign.c (scm_i_foreign_call): Adapt to receive arguments in reverse order. * libguile/frames.c (frame_stack_top, scm_i_frame_stack_top): Adapt to compute stack top instead of stack bottom. (scm_c_frame_closure): Adapt to stack growth change. (scm_frame_num_locals, scm_frame_local_ref, scm_frame_set_x): Use union data type to access stack. (RELOC): Reformat. (scm_c_frame_previous): Adapt to stack growth change. * libguile/frames.h: Adapt stack diagram to indicate that the stack grows up. (union scm_vm_stack_element): New data type used to access items on the stack. (SCM_FRAME_PREVIOUS_SP) (SCM_FRAME_RETURN_ADDRESS, SCM_FRAME_SET_RETURN_ADDRESS) (SCM_FRAME_DYNAMIC_LINK, SCM_FRAME_SET_DYNAMIC_LINK) (SCM_FRAME_LOCAL, SCM_FRAME_NUM_LOCALS): Adapt to stack representation change. (SCM_FRAME_SLOT): New helper. (SCM_VM_FRAME_FP, SCM_VM_FRAME_SP): Adapt to stack growth change. * libguile/stacks.c (scm_make_stack): Record offsets from top of stack. * libguile/throw.c (catch): Adapt to scm_i_prompt_pop_abort_args_x change. * libguile/vm-engine.c (ALLOC_FRAME, RESET_FRAME): (FRAME_LOCALS_COUNT_FROM): Adapt to stack growth change. (LOCAL_ADDRESS): Use SCM_FRAME_SLOT to get the address as the proper data type. (RETURN_ONE_VALUE, RETURN_VALUE_LIST): Adapt to stack growth change. (apply): Shuffling up the SMOB apply args can cause the stack to expand, so use ALLOC_FRAME instead of RESET_FRAME. (vm_engine): Adapt for stack growth change. * libguile/vm.c (vm_increase_sp, vm_push_sp, vm_restore_sp): Adapt to stack representation change. (scm_i_vm_cont_to_frame): Adapt to take offsets from the top. (scm_i_vm_capture_stack): Adapt to capture from the top. (vm_return_to_continuation_inner): Adapt for data type changes. (vm_return_to_continuation): Likewise, and instead of looping, just splat the saved arguments on with memcpy. (vm_dispatch_hook): Adapt to receive arguments in the reverse order. Adapt callers. (vm_abort): There is never a tail argument. Adapt to stack representation change. (vm_reinstate_partial_continuation) (vm_reinstate_partial_continuation_inner): Adapt to stack growth change. (allocate_stack, free_stack): Adapt to data type change. (expand_stack): Don't try to mremap(), as you can't grow a mapping from the bottom. Without knowing that there's a free mapping space right below the old stack, which there usually isn't on Linux, we have to copy. We can't use MAP_GROWSDOWN because Linux is buggy. (make_vm): Adapt to stack representation changes. (return_unused_stack_to_os): Round down instead of up, as the stack grows down. (scm_i_vm_mark_stack): Adapt to walk up the stack. (scm_i_vm_free_stack): Adapt to scm_vm changes. (vm_expand_stack_inner, reset_stack_limit, vm_expand_stack): Adapt to the stack growing down. (scm_call_n): Adapt to the stack growing down. Don't allow argv to point into the stack. * libguile/vm.h (struct scm_vm, struct scm_vm_cont): Adapt to hold the stack top and bottom.
2015-09-22 10:24:30 +00:00
this_fp = stack_top - frame->fp_offset;
VM stack grows downward Adapt VM stack to grow downward. This will make native compilation look more like the VM code, as we will be able to use native CALL instructions, taking proper advantage of the return address buffer. * libguile/continuations.c (scm_i_continuation_to_frame): Record offsets from stack top. * libguile/control.c (scm_i_prompt_pop_abort_args_x): Adapt for reversed order of arguments, and instead of relying on the abort to push on the number of arguments, make the caller save the stack depth, which allows us to compute the number of arguments ourselves. (reify_partial_continuation, scm_c_abort): Adapt to reversed stack order. * libguile/dynstack.c (scm_dynstack_wind_prompt): Since we wind the stack in a downward direction, subtract the reloc instead of adding it. * libguile/dynstack.h (SCM_F_DYNSTACK_PROMPT_ESCAPE_ONLY): Remove flag; instead rely on prompt-establishing code to save the stack depth. * libguile/eval.c (eval): Remove extraneous "volatile" declarations for variables that are not re-set between the setjmp and any longjmp. Adapt to save stack depth before instating the prompt. * libguile/foreign.c (scm_i_foreign_call): Adapt to receive arguments in reverse order. * libguile/frames.c (frame_stack_top, scm_i_frame_stack_top): Adapt to compute stack top instead of stack bottom. (scm_c_frame_closure): Adapt to stack growth change. (scm_frame_num_locals, scm_frame_local_ref, scm_frame_set_x): Use union data type to access stack. (RELOC): Reformat. (scm_c_frame_previous): Adapt to stack growth change. * libguile/frames.h: Adapt stack diagram to indicate that the stack grows up. (union scm_vm_stack_element): New data type used to access items on the stack. (SCM_FRAME_PREVIOUS_SP) (SCM_FRAME_RETURN_ADDRESS, SCM_FRAME_SET_RETURN_ADDRESS) (SCM_FRAME_DYNAMIC_LINK, SCM_FRAME_SET_DYNAMIC_LINK) (SCM_FRAME_LOCAL, SCM_FRAME_NUM_LOCALS): Adapt to stack representation change. (SCM_FRAME_SLOT): New helper. (SCM_VM_FRAME_FP, SCM_VM_FRAME_SP): Adapt to stack growth change. * libguile/stacks.c (scm_make_stack): Record offsets from top of stack. * libguile/throw.c (catch): Adapt to scm_i_prompt_pop_abort_args_x change. * libguile/vm-engine.c (ALLOC_FRAME, RESET_FRAME): (FRAME_LOCALS_COUNT_FROM): Adapt to stack growth change. (LOCAL_ADDRESS): Use SCM_FRAME_SLOT to get the address as the proper data type. (RETURN_ONE_VALUE, RETURN_VALUE_LIST): Adapt to stack growth change. (apply): Shuffling up the SMOB apply args can cause the stack to expand, so use ALLOC_FRAME instead of RESET_FRAME. (vm_engine): Adapt for stack growth change. * libguile/vm.c (vm_increase_sp, vm_push_sp, vm_restore_sp): Adapt to stack representation change. (scm_i_vm_cont_to_frame): Adapt to take offsets from the top. (scm_i_vm_capture_stack): Adapt to capture from the top. (vm_return_to_continuation_inner): Adapt for data type changes. (vm_return_to_continuation): Likewise, and instead of looping, just splat the saved arguments on with memcpy. (vm_dispatch_hook): Adapt to receive arguments in the reverse order. Adapt callers. (vm_abort): There is never a tail argument. Adapt to stack representation change. (vm_reinstate_partial_continuation) (vm_reinstate_partial_continuation_inner): Adapt to stack growth change. (allocate_stack, free_stack): Adapt to data type change. (expand_stack): Don't try to mremap(), as you can't grow a mapping from the bottom. Without knowing that there's a free mapping space right below the old stack, which there usually isn't on Linux, we have to copy. We can't use MAP_GROWSDOWN because Linux is buggy. (make_vm): Adapt to stack representation changes. (return_unused_stack_to_os): Round down instead of up, as the stack grows down. (scm_i_vm_mark_stack): Adapt to walk up the stack. (scm_i_vm_free_stack): Adapt to scm_vm changes. (vm_expand_stack_inner, reset_stack_limit, vm_expand_stack): Adapt to the stack growing down. (scm_call_n): Adapt to the stack growing down. Don't allow argv to point into the stack. * libguile/vm.h (struct scm_vm, struct scm_vm_cont): Adapt to hold the stack top and bottom.
2015-09-22 10:24:30 +00:00
if (this_fp == stack_top)
return 0;
remove heap links in VM frames, incorporate vm frames into normal backtraces * doc/ref/vm.texi (Stack Layout): Update to remove references to the "heap link". * gdbinit: Update for "heap link" removal. * libguile/frames.c: * libguile/frames.h: Update macros and diagram for removal of "heap link". As part of this, we also remove "heap frames", replacing them with "vm frames", which are much like the interpreter's debug objects, but for VM stacks. That is to say, they don't actually hold the stack themselves, just the pointers into stack that's held by a continuation (either captured or current). * libguile/stacks.c (stack_depth, read_frames): Since a "stack" object is really a copy of information that comes from somewhere else, it makes sense to copy over info from the VM, just as `make-stack' does from the evaluator. The tricky bit is to figure out how to interleave VM and interpreter frames. We do that by starting in the interpreter, and whenever the current frame's procedure is actually a program, we switch to the VM stack, switching back when we reach a "bootstrap frame". The last bit is hacky, but it does work... (is_vm_bootstrap_frame): Hacky predicate to see if a VM frame is a bootstrap frame. (scm_make_stack): Accept a VM frame in addition to debug frames. Probably has some bugs in this case. But in the case that the arg is #t (a common case), do the right thing, capturing the top VM frame as well, and interleaving those frames appropriately on the stack. As an accident, we lost the ability to limit the number of frames in the backtrace. We could add that back, but personally I always want *all* frames in the trace... Narrowing still works fine, though there are some hiccups sometimes -- e.g. an outer cut to a procedure that does a tail-call in VM code will never find the cut, as it no longer exists in the continuation. * libguile/vm.h (struct scm_vm): So! Now that we have switched to save stacks in the normal make-stack, there's no more need for `this_frame' or `last_frame'. On the other hand, we can take this opportunity to fix tracing: when we're in a trace hook, we set `trace_frame' on the VM, so we know not to fire hooks when we're already in a hook. (struct scm_vm_cont): Expose this, as make-stack needs it to make VM frames from VM continuations. * libguile/vm.c (scm_vm_trace_frame): New function, gets the current trace frame. (vm_mark, make_vm): Hook up the trace frame. (vm_dispatch_hook): New hook dispatcher, with a dynwind so it does the right thing if the hook exits nonlocally. * libguile/vm-engine.c (vm_run): No more this_frame in the wind data. * libguile/vm-engine.h (RUN_HOOK): Run hooks through the dispatcher. (ALIGN_AS_NON_IMMEDIATE, POP_LIST_ON_STACK): Remove unused code. (NEW_FRAME): Adapt for no HL in the frame. * libguile/vm-i-system.c (goto/args, mv-call, return, return/values): Adapt for no HL in the frame. * module/system/vm/frame.scm: * module/system/vm/vm.scm: Beginnings of some reworkings, needs more thought.
2008-12-26 17:59:46 +01:00
new_fp = SCM_FRAME_DYNAMIC_LINK (this_fp);
if (new_fp >= stack_top)
return 0;
new_sp = SCM_FRAME_PREVIOUS_SP (this_fp);
VM stack grows downward Adapt VM stack to grow downward. This will make native compilation look more like the VM code, as we will be able to use native CALL instructions, taking proper advantage of the return address buffer. * libguile/continuations.c (scm_i_continuation_to_frame): Record offsets from stack top. * libguile/control.c (scm_i_prompt_pop_abort_args_x): Adapt for reversed order of arguments, and instead of relying on the abort to push on the number of arguments, make the caller save the stack depth, which allows us to compute the number of arguments ourselves. (reify_partial_continuation, scm_c_abort): Adapt to reversed stack order. * libguile/dynstack.c (scm_dynstack_wind_prompt): Since we wind the stack in a downward direction, subtract the reloc instead of adding it. * libguile/dynstack.h (SCM_F_DYNSTACK_PROMPT_ESCAPE_ONLY): Remove flag; instead rely on prompt-establishing code to save the stack depth. * libguile/eval.c (eval): Remove extraneous "volatile" declarations for variables that are not re-set between the setjmp and any longjmp. Adapt to save stack depth before instating the prompt. * libguile/foreign.c (scm_i_foreign_call): Adapt to receive arguments in reverse order. * libguile/frames.c (frame_stack_top, scm_i_frame_stack_top): Adapt to compute stack top instead of stack bottom. (scm_c_frame_closure): Adapt to stack growth change. (scm_frame_num_locals, scm_frame_local_ref, scm_frame_set_x): Use union data type to access stack. (RELOC): Reformat. (scm_c_frame_previous): Adapt to stack growth change. * libguile/frames.h: Adapt stack diagram to indicate that the stack grows up. (union scm_vm_stack_element): New data type used to access items on the stack. (SCM_FRAME_PREVIOUS_SP) (SCM_FRAME_RETURN_ADDRESS, SCM_FRAME_SET_RETURN_ADDRESS) (SCM_FRAME_DYNAMIC_LINK, SCM_FRAME_SET_DYNAMIC_LINK) (SCM_FRAME_LOCAL, SCM_FRAME_NUM_LOCALS): Adapt to stack representation change. (SCM_FRAME_SLOT): New helper. (SCM_VM_FRAME_FP, SCM_VM_FRAME_SP): Adapt to stack growth change. * libguile/stacks.c (scm_make_stack): Record offsets from top of stack. * libguile/throw.c (catch): Adapt to scm_i_prompt_pop_abort_args_x change. * libguile/vm-engine.c (ALLOC_FRAME, RESET_FRAME): (FRAME_LOCALS_COUNT_FROM): Adapt to stack growth change. (LOCAL_ADDRESS): Use SCM_FRAME_SLOT to get the address as the proper data type. (RETURN_ONE_VALUE, RETURN_VALUE_LIST): Adapt to stack growth change. (apply): Shuffling up the SMOB apply args can cause the stack to expand, so use ALLOC_FRAME instead of RESET_FRAME. (vm_engine): Adapt for stack growth change. * libguile/vm.c (vm_increase_sp, vm_push_sp, vm_restore_sp): Adapt to stack representation change. (scm_i_vm_cont_to_frame): Adapt to take offsets from the top. (scm_i_vm_capture_stack): Adapt to capture from the top. (vm_return_to_continuation_inner): Adapt for data type changes. (vm_return_to_continuation): Likewise, and instead of looping, just splat the saved arguments on with memcpy. (vm_dispatch_hook): Adapt to receive arguments in the reverse order. Adapt callers. (vm_abort): There is never a tail argument. Adapt to stack representation change. (vm_reinstate_partial_continuation) (vm_reinstate_partial_continuation_inner): Adapt to stack growth change. (allocate_stack, free_stack): Adapt to data type change. (expand_stack): Don't try to mremap(), as you can't grow a mapping from the bottom. Without knowing that there's a free mapping space right below the old stack, which there usually isn't on Linux, we have to copy. We can't use MAP_GROWSDOWN because Linux is buggy. (make_vm): Adapt to stack representation changes. (return_unused_stack_to_os): Round down instead of up, as the stack grows down. (scm_i_vm_mark_stack): Adapt to walk up the stack. (scm_i_vm_free_stack): Adapt to scm_vm changes. (vm_expand_stack_inner, reset_stack_limit, vm_expand_stack): Adapt to the stack growing down. (scm_call_n): Adapt to the stack growing down. Don't allow argv to point into the stack. * libguile/vm.h (struct scm_vm, struct scm_vm_cont): Adapt to hold the stack top and bottom.
2015-09-22 10:24:30 +00:00
frame->fp_offset = stack_top - new_fp;
frame->sp_offset = stack_top - new_sp;
frame->ip = SCM_FRAME_VIRTUAL_RETURN_ADDRESS (this_fp);
if (scm_i_vm_is_boot_continuation_code (frame->ip))
goto again;
return 1;
}
SCM_DEFINE (scm_frame_previous, "frame-previous", 1, 0, 0,
(SCM frame),
"")
#define FUNC_NAME s_scm_frame_previous
{
enum scm_vm_frame_kind kind;
struct scm_frame tmp;
SCM_VALIDATE_VM_FRAME (1, frame);
kind = SCM_VM_FRAME_KIND (frame);
memcpy (&tmp, SCM_VM_FRAME_DATA (frame), sizeof tmp);
if (!scm_c_frame_previous (SCM_VM_FRAME_KIND (frame), &tmp))
remove heap links in VM frames, incorporate vm frames into normal backtraces * doc/ref/vm.texi (Stack Layout): Update to remove references to the "heap link". * gdbinit: Update for "heap link" removal. * libguile/frames.c: * libguile/frames.h: Update macros and diagram for removal of "heap link". As part of this, we also remove "heap frames", replacing them with "vm frames", which are much like the interpreter's debug objects, but for VM stacks. That is to say, they don't actually hold the stack themselves, just the pointers into stack that's held by a continuation (either captured or current). * libguile/stacks.c (stack_depth, read_frames): Since a "stack" object is really a copy of information that comes from somewhere else, it makes sense to copy over info from the VM, just as `make-stack' does from the evaluator. The tricky bit is to figure out how to interleave VM and interpreter frames. We do that by starting in the interpreter, and whenever the current frame's procedure is actually a program, we switch to the VM stack, switching back when we reach a "bootstrap frame". The last bit is hacky, but it does work... (is_vm_bootstrap_frame): Hacky predicate to see if a VM frame is a bootstrap frame. (scm_make_stack): Accept a VM frame in addition to debug frames. Probably has some bugs in this case. But in the case that the arg is #t (a common case), do the right thing, capturing the top VM frame as well, and interleaving those frames appropriately on the stack. As an accident, we lost the ability to limit the number of frames in the backtrace. We could add that back, but personally I always want *all* frames in the trace... Narrowing still works fine, though there are some hiccups sometimes -- e.g. an outer cut to a procedure that does a tail-call in VM code will never find the cut, as it no longer exists in the continuation. * libguile/vm.h (struct scm_vm): So! Now that we have switched to save stacks in the normal make-stack, there's no more need for `this_frame' or `last_frame'. On the other hand, we can take this opportunity to fix tracing: when we're in a trace hook, we set `trace_frame' on the VM, so we know not to fire hooks when we're already in a hook. (struct scm_vm_cont): Expose this, as make-stack needs it to make VM frames from VM continuations. * libguile/vm.c (scm_vm_trace_frame): New function, gets the current trace frame. (vm_mark, make_vm): Hook up the trace frame. (vm_dispatch_hook): New hook dispatcher, with a dynwind so it does the right thing if the hook exits nonlocally. * libguile/vm-engine.c (vm_run): No more this_frame in the wind data. * libguile/vm-engine.h (RUN_HOOK): Run hooks through the dispatcher. (ALIGN_AS_NON_IMMEDIATE, POP_LIST_ON_STACK): Remove unused code. (NEW_FRAME): Adapt for no HL in the frame. * libguile/vm-i-system.c (goto/args, mv-call, return, return/values): Adapt for no HL in the frame. * module/system/vm/frame.scm: * module/system/vm/vm.scm: Beginnings of some reworkings, needs more thought.
2008-12-26 17:59:46 +01:00
return SCM_BOOL_F;
return scm_c_make_frame (kind, &tmp);
remove heap links in VM frames, incorporate vm frames into normal backtraces * doc/ref/vm.texi (Stack Layout): Update to remove references to the "heap link". * gdbinit: Update for "heap link" removal. * libguile/frames.c: * libguile/frames.h: Update macros and diagram for removal of "heap link". As part of this, we also remove "heap frames", replacing them with "vm frames", which are much like the interpreter's debug objects, but for VM stacks. That is to say, they don't actually hold the stack themselves, just the pointers into stack that's held by a continuation (either captured or current). * libguile/stacks.c (stack_depth, read_frames): Since a "stack" object is really a copy of information that comes from somewhere else, it makes sense to copy over info from the VM, just as `make-stack' does from the evaluator. The tricky bit is to figure out how to interleave VM and interpreter frames. We do that by starting in the interpreter, and whenever the current frame's procedure is actually a program, we switch to the VM stack, switching back when we reach a "bootstrap frame". The last bit is hacky, but it does work... (is_vm_bootstrap_frame): Hacky predicate to see if a VM frame is a bootstrap frame. (scm_make_stack): Accept a VM frame in addition to debug frames. Probably has some bugs in this case. But in the case that the arg is #t (a common case), do the right thing, capturing the top VM frame as well, and interleaving those frames appropriately on the stack. As an accident, we lost the ability to limit the number of frames in the backtrace. We could add that back, but personally I always want *all* frames in the trace... Narrowing still works fine, though there are some hiccups sometimes -- e.g. an outer cut to a procedure that does a tail-call in VM code will never find the cut, as it no longer exists in the continuation. * libguile/vm.h (struct scm_vm): So! Now that we have switched to save stacks in the normal make-stack, there's no more need for `this_frame' or `last_frame'. On the other hand, we can take this opportunity to fix tracing: when we're in a trace hook, we set `trace_frame' on the VM, so we know not to fire hooks when we're already in a hook. (struct scm_vm_cont): Expose this, as make-stack needs it to make VM frames from VM continuations. * libguile/vm.c (scm_vm_trace_frame): New function, gets the current trace frame. (vm_mark, make_vm): Hook up the trace frame. (vm_dispatch_hook): New hook dispatcher, with a dynwind so it does the right thing if the hook exits nonlocally. * libguile/vm-engine.c (vm_run): No more this_frame in the wind data. * libguile/vm-engine.h (RUN_HOOK): Run hooks through the dispatcher. (ALIGN_AS_NON_IMMEDIATE, POP_LIST_ON_STACK): Remove unused code. (NEW_FRAME): Adapt for no HL in the frame. * libguile/vm-i-system.c (goto/args, mv-call, return, return/values): Adapt for no HL in the frame. * module/system/vm/frame.scm: * module/system/vm/vm.scm: Beginnings of some reworkings, needs more thought.
2008-12-26 17:59:46 +01:00
}
#undef FUNC_NAME
remove heap links in VM frames, incorporate vm frames into normal backtraces * doc/ref/vm.texi (Stack Layout): Update to remove references to the "heap link". * gdbinit: Update for "heap link" removal. * libguile/frames.c: * libguile/frames.h: Update macros and diagram for removal of "heap link". As part of this, we also remove "heap frames", replacing them with "vm frames", which are much like the interpreter's debug objects, but for VM stacks. That is to say, they don't actually hold the stack themselves, just the pointers into stack that's held by a continuation (either captured or current). * libguile/stacks.c (stack_depth, read_frames): Since a "stack" object is really a copy of information that comes from somewhere else, it makes sense to copy over info from the VM, just as `make-stack' does from the evaluator. The tricky bit is to figure out how to interleave VM and interpreter frames. We do that by starting in the interpreter, and whenever the current frame's procedure is actually a program, we switch to the VM stack, switching back when we reach a "bootstrap frame". The last bit is hacky, but it does work... (is_vm_bootstrap_frame): Hacky predicate to see if a VM frame is a bootstrap frame. (scm_make_stack): Accept a VM frame in addition to debug frames. Probably has some bugs in this case. But in the case that the arg is #t (a common case), do the right thing, capturing the top VM frame as well, and interleaving those frames appropriately on the stack. As an accident, we lost the ability to limit the number of frames in the backtrace. We could add that back, but personally I always want *all* frames in the trace... Narrowing still works fine, though there are some hiccups sometimes -- e.g. an outer cut to a procedure that does a tail-call in VM code will never find the cut, as it no longer exists in the continuation. * libguile/vm.h (struct scm_vm): So! Now that we have switched to save stacks in the normal make-stack, there's no more need for `this_frame' or `last_frame'. On the other hand, we can take this opportunity to fix tracing: when we're in a trace hook, we set `trace_frame' on the VM, so we know not to fire hooks when we're already in a hook. (struct scm_vm_cont): Expose this, as make-stack needs it to make VM frames from VM continuations. * libguile/vm.c (scm_vm_trace_frame): New function, gets the current trace frame. (vm_mark, make_vm): Hook up the trace frame. (vm_dispatch_hook): New hook dispatcher, with a dynwind so it does the right thing if the hook exits nonlocally. * libguile/vm-engine.c (vm_run): No more this_frame in the wind data. * libguile/vm-engine.h (RUN_HOOK): Run hooks through the dispatcher. (ALIGN_AS_NON_IMMEDIATE, POP_LIST_ON_STACK): Remove unused code. (NEW_FRAME): Adapt for no HL in the frame. * libguile/vm-i-system.c (goto/args, mv-call, return, return/values): Adapt for no HL in the frame. * module/system/vm/frame.scm: * module/system/vm/vm.scm: Beginnings of some reworkings, needs more thought.
2008-12-26 17:59:46 +01:00
2001-04-22 02:13:48 +00:00
static void
scm_init_frames_builtins (void *unused)
{
scm_c_define_gsubr (s_scm_frame_num_locals, 1, 0, 0,
(scm_t_subr) scm_frame_num_locals);
scm_c_define_gsubr (s_scm_frame_local_ref, 3, 0, 0,
(scm_t_subr) scm_frame_local_ref);
scm_c_define_gsubr (s_scm_frame_local_set_x, 4, 0, 0,
(scm_t_subr) scm_frame_local_set_x);
scm_c_define_gsubr (s_scm_frame_return_values, 1, 0, 0,
(scm_t_subr) scm_frame_return_values);
}
big reorg of scheme modules -- e.g. programs.c -> (system vm program) This reorganization kills the ugly module-export-all hacks in bootstrap.scm and core.scm. In fact, it gets rid of core.scm entirely, breaking out its functionality into separate files. * module/system/vm/trace.scm: * module/system/vm/profile.scm: * module/system/vm/disasm.scm: * module/system/vm/debug.scm: * module/system/vm/conv.scm: * module/system/vm/assemble.scm: * module/system/repl/repl.scm: * module/system/repl/common.scm: * module/system/base/compile.scm: * module/system/repl/command.scm: Update for changes, and fix a bug in procedure-documentation. * module/system/vm/bootstrap.scm: Just call scm_bootstrap_vm, which handles setting load-compiled for us. * module/system/vm/core.scm: Removed, functionality folded into other modules. * module/system/vm/frame.scm: Export the C frame procedures here; also move scheme functions from core.scm here. * module/system/vm/instruction.scm: New file, exports procedures from instructions.c. * module/system/vm/objcode.scm: New file, exports procedures from objcodes.c. * module/system/vm/program.scm: New file, exports procedures from programs.c, and some scheme functions originally from core.scm. * module/system/vm/vm.scm: New file, from vm.c and core.scm. * src/Makefile.am (libguile_vm_la_SOURCES): Add bootstrap.h. * src/bootstrap.h: New file, prototypes scm_bootstrap_vm (), which the scm_init_* functions call. * src/frames.h: * src/frames.c (scm_init_frames): * src/frames.c (scm_bootstrap_frames): * src/vm.h: * src/instructions.h: * src/instructions.c (scm_init_instructions): * src/instructions.c (scm_bootstrap_instructions): * src/objcodes.h: * src/objcodes.c (scm_bootstrap_objcodes): * src/objcodes.c (scm_init_objcodes): * src/programs.h: * src/programs.c (scm_bootstrap_programs): * src/programs.c (scm_init_programs): * src/vm.c (scm_bootstrap_vm): * src/vm.c (scm_init_vm): Call scm_bootstrap_vm() before doing anything in an init function. Bootstrap_vm will call bootstrap_instructions(), etc to initialize types, then set load-compiled to point to load-compiled/vm. * src/vm.c (scm_load_compiled_with_vm): Code to load .go files, if they're present.
2008-08-07 13:11:27 +02:00
void
scm_init_frames (void)
{
2001-04-22 02:13:48 +00:00
#ifndef SCM_MAGIC_SNARFER
#include "frames.x"
2001-04-22 02:13:48 +00:00
#endif
scm_c_register_extension ("libguile-" SCM_EFFECTIVE_VERSION,
"scm_init_frames_builtins",
scm_init_frames_builtins,
NULL);
2001-04-22 02:13:48 +00:00
}