1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-20 11:40:18 +02:00

clean up (system vm frames), add locals command to debugger

* libguile/frames.c (scm_init_frames): No need to bootstrap the VM here,
  it should be already bootstrapped by init.c.
  (scm_bootstrap_frames): No need to register an extension, as
  scm_init_frames is called by init.c.

* module/system/vm/frame.scm: Don't load the scm_init_frames extension,
  as the primitives from frames.c are loaded by Guile's init.
  (frame-bindings): Change to return bindings, as can be accessed by the
  binding: accessors from program.scm.
  (frame-lookup-binding): Revive and make this one work with current
  code.
  (frame-binding-set!):
  (frame-binding-ref): Use the new frame-lookup-binding. Perhaps these
  should handle boxing and unboxing, though.
  (frame-source): New accessor, returns a source object.
  (frame-call-representation): Change to return a full list, as
  truncated-print can truncate for us.
  (frame-environment, frame-object-binding, frame-object-name): Update
  not to take an address, as the address is part of the frame.
  (frame-variable-exists?, frame-variable-ref, frame-variable-set!)
  (frame-local-variables, frame-program-name, print-frame)
  (print-frame-chain-as-backtrace, frame-file, frame-line-number)
  (make-frame-chain, bootstrap-frame?, frame-number, frame-address):
  Remove these outdated functions.

* module/system/vm/debug.scm (debugger-repl): Use
  frame-call-representation, and ~@y.
  (locals): New command, prints local variables in a frame.
This commit is contained in:
Andy Wingo 2009-12-29 14:09:50 +01:00
parent b8596c08ac
commit 1c5e812258
3 changed files with 56 additions and 159 deletions

View file

@ -304,15 +304,11 @@ scm_bootstrap_frames (void)
{
scm_tc16_frame = scm_make_smob_type ("frame", 0);
scm_set_smob_print (scm_tc16_frame, frame_print);
scm_c_register_extension ("libguile", "scm_init_frames",
(scm_t_extension_init_func)scm_init_frames, NULL);
}
void
scm_init_frames (void)
{
scm_bootstrap_vm ();
#ifndef SCM_MAGIC_SNARFER
#include "libguile/frames.x"
#endif

View file

@ -115,11 +115,12 @@
((zero? idx) walk)
(else (lp (1+ idx) (frame-previous walk))))))
(define (show-frame)
; #2 0x009600e0 in do_std_select (args=0xbfffd9e0) at threads.c:1668
; 1668 select (select_args->nfds,
(let ((p (frame-procedure cur)))
(format #t "#~2a 0x~8,'0x in ~s~%" index (frame-instruction-pointer cur)
(cons (or (procedure-name p) p) (frame-arguments cur)))))
;; #2 0x009600e0 in do_std_select (args=0xbfffd9e0) at threads.c:1668
;; 1668 select (select_args->nfds,
(format #t "#~2a 0x~8,'0x in ~60@y~%"
index
(frame-instruction-pointer cur)
(frame-call-representation cur)))
(define-syntax define-command
(syntax-rules ()
@ -207,6 +208,20 @@ With an argument, select a frame by index, then show it."
"Show some information about locally-bound variables in the selected frame."
(format #t "~a\n" (frame-bindings cur)))
(define-command ((commands locals))
"Show locally-bound variables in the selected frame."
(for-each
(lambda (binding)
(format #t "~4d: ~a~:[~; (boxed)~]: ~20t~60@y\n"
(binding:index binding)
(binding:name binding)
(binding:boxed? binding)
(let ((x (frame-local-ref cur (binding:index binding))))
(if (binding:boxed? binding)
(variable-ref x)
x))))
(frame-bindings cur)))
(define-command ((commands quit q continue cont c))
"Quit the debugger and let the program continue executing."
(throw 'quit))

View file

@ -24,45 +24,35 @@
#:use-module (system vm instruction)
#:use-module (system vm objcode)
#:use-module ((srfi srfi-1) #:select (fold))
#:export (frame-local-ref frame-local-set!
frame-instruction-pointer
frame-return-address frame-mv-return-address
frame-dynamic-link
frame-num-locals
frame-bindings frame-binding-ref frame-binding-set!
; frame-arguments
frame-number frame-address
make-frame-chain
print-frame print-frame-chain-as-backtrace
frame-local-variables
#:export (frame-bindings
frame-lookup-binding
frame-binding-ref frame-binding-set!
frame-source frame-call-representation
frame-environment
frame-variable-exists? frame-variable-ref frame-variable-set!
frame-object-name
frame-local-ref frame-local-set!
frame-return-address frame-program
frame-dynamic-link heap-frame?))
(load-extension "libguile" "scm_init_frames")
frame-object-binding frame-object-name))
(define (frame-bindings frame)
(map (lambda (b)
(cons (binding:name b) (binding:index b)))
(program-bindings-for-ip (frame-procedure frame)
(frame-instruction-pointer frame))))
(program-bindings-for-ip (frame-procedure frame)
(frame-instruction-pointer frame)))
(define (frame-lookup-binding frame var)
(let lp ((bindings (frame-bindings frame)))
(cond ((null? bindings)
(error "variable not bound in frame" var frame))
((eq? (binding:name (car bindings)) var)
(car bindings))
(else
(lp (cdr bindings))))))
(define (frame-binding-set! frame var val)
(let ((i (assq-ref (frame-bindings frame) var)))
(if i
(frame-local-set! frame i val)
(error "variable not bound in frame" var frame))))
(frame-local-set! frame
(binding:index (frame-lookup-binding frame var))
val))
(define (frame-binding-ref frame var)
(let ((i (assq-ref (frame-bindings frame) var)))
(if i
(frame-local-ref frame i)
(error "variable not bound in frame" var frame))))
(frame-local-ref frame
(binding:index (frame-lookup-binding frame var))))
;; Basically there are two cases to deal with here:
;;
@ -103,138 +93,34 @@
(frame-local-ref frame i))
(iota (frame-num-locals frame))))))
;;;
;;; Frame chain
;;;
(define frame-number (make-object-property))
(define frame-address (make-object-property))
;; FIXME: the header.
(define (bootstrap-frame? frame)
(let ((code (objcode->bytecode (program-objcode (frame-program frame)))))
(and (= (uniform-vector-ref code (1- (uniform-vector-length code)))
(instruction->opcode 'halt)))))
(define (make-frame-chain frame addr)
(define (make-rest)
(make-frame-chain (frame-dynamic-link frame)
(frame-return-address frame)))
(cond
((or (eq? frame #t) (eq? frame #f))
;; handle #f or #t dynamic links
'())
((bootstrap-frame? frame)
(make-rest))
(else
(let ((chain (make-rest)))
(set! (frame-number frame) (length chain))
(set! (frame-address frame)
(- addr (program-base (frame-program frame))))
(cons frame chain)))))
;;;
;;; Pretty printing
;;;
(define (frame-line-number frame)
(let ((addr (frame-address frame)))
(cond ((assv addr (program-sources (frame-program frame)))
=> source:line)
(else (format #f "@~a" addr)))))
(define (frame-file frame prev)
(let ((sources (program-sources (frame-program frame))))
(if (null? sources)
prev
(or (source:file (car sources))
"current input"))))
(define (print-frame frame)
(format #t "~4@a: ~a ~s\n" (frame-line-number frame) (frame-number frame)
(frame-call-representation frame)))
(define (frame-source frame)
(program-source (frame-procedure frame)
(frame-instruction-pointer frame)))
(define (frame-call-representation frame)
(define (abbrev x)
(cond ((list? x)
(if (> (length x) 4)
(list (abbrev (car x)) (abbrev (cadr x)) '...)
(map abbrev x)))
((pair? x)
(cons (abbrev (car x)) (abbrev (cdr x))))
((vector? x)
(case (vector-length x)
((0) x)
((1) (vector (abbrev (vector-ref x 0))))
(else (vector (abbrev (vector-ref x 0)) '...))))
(else x)))
(abbrev (cons (frame-program-name frame) (frame-arguments frame))))
(let ((p (frame-procedure frame)))
(cons (or (procedure-name p) p) (frame-arguments frame))))
(define (print-frame-chain-as-backtrace frames)
(if (null? frames)
(format #t "No backtrace available.\n")
(begin
(format #t "VM backtrace:\n")
(fold (lambda (frame file)
(let ((new-file (frame-file frame file)))
(if (not (equal? new-file file))
(format #t "In ~a:\n" new-file))
(print-frame frame)
new-file))
'no-file
frames))))
(define (frame-program-name frame)
(let ((prog (frame-program frame))
(link (frame-dynamic-link frame)))
(or (program-name prog)
(object-property prog 'name)
(and (heap-frame? link) (frame-address link)
(frame-object-name link (1- (frame-address link)) prog))
(hash-fold (lambda (s v d) (if (and (variable-bound? v)
(eq? prog (variable-ref v)))
s d))
prog (module-obarray (current-module))))))
;;; Frames
;;; Misc
;;;
(define (frame-local-variables frame)
(let* ((prog (frame-program frame))
(arity (program-arity prog)))
(do ((n (+ (arity:nargs arity) (arity:nlocs arity) -1) (1- n))
(l '() (cons (frame-local-ref frame n) l)))
((< n 0) l))))
(define (frame-environment frame)
(map (lambda (binding)
(cons (binding:name binding) (frame-binding-ref frame binding)))
(frame-bindings frame)))
(define (frame-lookup-binding frame addr sym)
(assq sym (reverse (frame-bindings frame addr))))
(define (frame-object-binding frame addr obj)
(do ((bs (frame-bindings frame addr) (cdr bs)))
(define (frame-object-binding frame obj)
(do ((bs (frame-bindings frame) (cdr bs)))
((or (null? bs) (eq? obj (frame-binding-ref frame (car bs))))
(and (pair? bs) (car bs)))))
(define (frame-environment frame addr)
(map (lambda (binding)
(cons (binding:name binding) (frame-binding-ref frame binding)))
(frame-bindings frame addr)))
(define (frame-variable-exists? frame addr sym)
(if (frame-lookup-binding frame addr sym) #t #f))
(define (frame-variable-ref frame addr sym)
(cond ((frame-lookup-binding frame addr sym) =>
(lambda (binding) (frame-binding-ref frame binding)))
(else (error "Unknown variable:" sym))))
(define (frame-variable-set! frame addr sym val)
(cond ((frame-lookup-binding frame addr sym) =>
(lambda (binding) (frame-binding-set! frame binding val)))
(else (error "Unknown variable:" sym))))
(define (frame-object-name frame addr obj)
(cond ((frame-object-binding frame addr obj) => binding:name)
(define (frame-object-name frame obj)
(cond ((frame-object-binding frame obj) => binding:name)
(else #f)))