mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-19 02:00:26 +02:00
rework late binding resolution to be simpler and more efficient
* libguile/programs.h (struct scm_program): * libguile/programs.c (scm_c_make_program): Record the current module when making a program. This replaces the per-late binding recorded module in the generated code, which should be more efficient, both in terms of garbage, and in not calling resolve-module. (program-module): New accessor. * module/system/vm/program.scm: Add program-module to exports. * libguile/vm-i-loader.c (link-later): Remove this instruction, since now the entry in the object table is just a symbol, and can be loaded with load-symbol. * libguile/vm-i-system.c (late-variable-ref, late-variable-set): Rework so as to look up in the module of the current program. The logic could be condensed quite a bit if scm_module_lookup () knew what to do with mod==#f. * module/system/vm/assemble.scm (dump-object!): Dump <vlink-later> just as load-symbol, as mentioned in the note on link-later. * module/system/il/ghil.scm: Update comment to reflect the new reality.
This commit is contained in:
parent
7618201efd
commit
8e3670748f
7 changed files with 40 additions and 51 deletions
|
@ -46,6 +46,7 @@
|
|||
#include <string.h>
|
||||
#include "vm-bootstrap.h"
|
||||
#include "instructions.h"
|
||||
#include "modules.h"
|
||||
#include "programs.h"
|
||||
#include "vm.h"
|
||||
|
||||
|
@ -69,6 +70,7 @@ scm_c_make_program (void *addr, size_t size, SCM holder)
|
|||
p->objs = zero_vector;
|
||||
p->external = SCM_EOL;
|
||||
p->holder = holder;
|
||||
p->module = scm_current_module ();
|
||||
|
||||
/* If nobody holds bytecode's address, then allocate a new memory */
|
||||
if (SCM_FALSEP (holder))
|
||||
|
@ -99,6 +101,7 @@ program_mark (SCM obj)
|
|||
scm_gc_mark (p->meta);
|
||||
scm_gc_mark (p->objs);
|
||||
scm_gc_mark (p->external);
|
||||
scm_gc_mark (p->module);
|
||||
return p->holder;
|
||||
}
|
||||
|
||||
|
@ -184,6 +187,16 @@ SCM_DEFINE (scm_program_objects, "program-objects", 1, 0, 0,
|
|||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
SCM_DEFINE (scm_program_module, "program-module", 1, 0, 0,
|
||||
(SCM program),
|
||||
"")
|
||||
#define FUNC_NAME s_scm_program_module
|
||||
{
|
||||
SCM_VALIDATE_PROGRAM (1, program);
|
||||
return SCM_PROGRAM_DATA (program)->module;
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
SCM_DEFINE (scm_program_external, "program-external", 1, 0, 0,
|
||||
(SCM program),
|
||||
"")
|
||||
|
|
|
@ -57,6 +57,7 @@ struct scm_program {
|
|||
unsigned char nlocs; /* the number of local variables */
|
||||
unsigned char nexts; /* the number of external variables */
|
||||
scm_byte_t *base; /* program base address */
|
||||
SCM module; /* resolve bindings with respect to this module */
|
||||
SCM meta; /* meta data */
|
||||
SCM objs; /* constant objects */
|
||||
SCM external; /* external environment */
|
||||
|
@ -77,6 +78,7 @@ extern SCM scm_program_base (SCM program);
|
|||
extern SCM scm_program_arity (SCM program);
|
||||
extern SCM scm_program_meta (SCM program);
|
||||
extern SCM scm_program_objects (SCM program);
|
||||
extern SCM scm_program_module (SCM program);
|
||||
extern SCM scm_program_external (SCM program);
|
||||
extern SCM scm_program_external_set_x (SCM program, SCM external);
|
||||
extern SCM scm_program_bytecode (SCM program);
|
||||
|
|
|
@ -172,16 +172,6 @@ VM_DEFINE_INSTRUCTION (link_now, "link-now", 0, 1, 1)
|
|||
NEXT;
|
||||
}
|
||||
|
||||
VM_DEFINE_INSTRUCTION (link_later, "link-later", 0, 2, 1)
|
||||
{
|
||||
SCM modname, sym;
|
||||
POP (sym);
|
||||
POP (modname);
|
||||
SYNC_REGISTER ();
|
||||
PUSH (scm_cons (modname, sym));
|
||||
NEXT;
|
||||
}
|
||||
|
||||
VM_DEFINE_LOADER (define, "define")
|
||||
{
|
||||
SCM sym;
|
||||
|
|
|
@ -262,34 +262,33 @@ VM_DEFINE_INSTRUCTION (variable_ref, "variable-ref", 0, 0, 1)
|
|||
VM_DEFINE_INSTRUCTION (late_variable_ref, "late-variable-ref", 1, 0, 1)
|
||||
{
|
||||
unsigned objnum = FETCH ();
|
||||
SCM pair_or_var;
|
||||
SCM sym_or_var;
|
||||
CHECK_OBJECT (objnum);
|
||||
pair_or_var = OBJECT_REF (objnum);
|
||||
sym_or_var = OBJECT_REF (objnum);
|
||||
|
||||
if (!SCM_VARIABLEP (pair_or_var))
|
||||
if (!SCM_VARIABLEP (sym_or_var))
|
||||
{
|
||||
SYNC_REGISTER ();
|
||||
if (SCM_LIKELY (scm_module_system_booted_p))
|
||||
if (SCM_LIKELY (scm_module_system_booted_p && SCM_NFALSEP (bp->module)))
|
||||
{
|
||||
/* either one of these calls might longjmp */
|
||||
SCM mod = scm_resolve_module (SCM_CAR (pair_or_var));
|
||||
pair_or_var = scm_module_lookup (mod, SCM_CDR (pair_or_var));
|
||||
/* might longjmp */
|
||||
sym_or_var = scm_module_lookup (bp->module, sym_or_var);
|
||||
}
|
||||
else
|
||||
{
|
||||
pair_or_var = scm_lookup (SCM_CDR (pair_or_var));
|
||||
sym_or_var = scm_sym2var (sym_or_var, SCM_BOOL_F, SCM_BOOL_F);
|
||||
}
|
||||
|
||||
if (!VARIABLE_BOUNDP (pair_or_var))
|
||||
if (!VARIABLE_BOUNDP (sym_or_var))
|
||||
{
|
||||
err_args = SCM_LIST1 (pair_or_var);
|
||||
err_args = SCM_LIST1 (sym_or_var);
|
||||
goto vm_error_unbound;
|
||||
}
|
||||
|
||||
OBJECT_SET (objnum, pair_or_var);
|
||||
OBJECT_SET (objnum, sym_or_var);
|
||||
}
|
||||
|
||||
PUSH (VARIABLE_REF (pair_or_var));
|
||||
PUSH (VARIABLE_REF (sym_or_var));
|
||||
NEXT;
|
||||
}
|
||||
|
||||
|
@ -327,28 +326,27 @@ VM_DEFINE_INSTRUCTION (variable_set, "variable-set", 0, 1, 0)
|
|||
VM_DEFINE_INSTRUCTION (late_variable_set, "late-variable-set", 1, 1, 0)
|
||||
{
|
||||
unsigned objnum = FETCH ();
|
||||
SCM pair_or_var;
|
||||
SCM sym_or_var;
|
||||
CHECK_OBJECT (objnum);
|
||||
pair_or_var = OBJECT_REF (objnum);
|
||||
sym_or_var = OBJECT_REF (objnum);
|
||||
|
||||
if (!SCM_VARIABLEP (pair_or_var))
|
||||
if (!SCM_VARIABLEP (sym_or_var))
|
||||
{
|
||||
SYNC_BEFORE_GC ();
|
||||
if (SCM_LIKELY (scm_module_system_booted_p))
|
||||
if (SCM_LIKELY (scm_module_system_booted_p && SCM_NFALSEP (bp->module)))
|
||||
{
|
||||
/* either one of these calls might longjmp */
|
||||
SCM mod = scm_resolve_module (SCM_CAR (pair_or_var));
|
||||
pair_or_var = scm_module_lookup (mod, SCM_CDR (pair_or_var));
|
||||
/* might longjmp */
|
||||
sym_or_var = scm_module_lookup (bp->module, sym_or_var);
|
||||
}
|
||||
else
|
||||
{
|
||||
pair_or_var = scm_lookup (SCM_CDR (pair_or_var));
|
||||
sym_or_var = scm_sym2var (sym_or_var, SCM_BOOL_F, SCM_BOOL_F);
|
||||
}
|
||||
|
||||
OBJECT_SET (objnum, pair_or_var);
|
||||
OBJECT_SET (objnum, sym_or_var);
|
||||
}
|
||||
|
||||
VARIABLE_SET (pair_or_var, *sp);
|
||||
VARIABLE_SET (sym_or_var, *sp);
|
||||
DROP ();
|
||||
NEXT;
|
||||
}
|
||||
|
|
|
@ -161,21 +161,9 @@
|
|||
;; "external" so that it goes on the heap.
|
||||
;;
|
||||
;; If the variable is not found lexically, it is a toplevel variable,
|
||||
;; which will be looked up at runtime with respect to the module that is
|
||||
;; current at compile-time. The variable will be resolved when it is
|
||||
;; first used.
|
||||
;;
|
||||
;; You might think that you want to look up all variables with respect
|
||||
;; to the current runtime module, but you would have to associate the
|
||||
;; current module with a closure, so that lazy lookup is done with
|
||||
;; respect to the proper module. We could do that -- it would probably
|
||||
;; cons less at runtime.
|
||||
;;
|
||||
;; This toplevel lookup strategy can exhibit weird effects in the case
|
||||
;; of a call to set-current-module inside a closure -- specifically,
|
||||
;; looking up any needed bindings for the rest of the closure in the
|
||||
;; compilation module instead of the runtime module -- but such things
|
||||
;; are both unspecified in the scheme standard.
|
||||
;; which will be looked up at runtime with respect to the module that
|
||||
;; was current when the lambda was bound, at runtime. The variable will
|
||||
;; be resolved when it is first used.
|
||||
(define (ghil-lookup env sym)
|
||||
(let loop ((e env))
|
||||
(record-case e
|
||||
|
|
|
@ -285,9 +285,7 @@
|
|||
;; dump bytecode
|
||||
(push-code! `(load-program ,bytes)))
|
||||
((<vlink-later> module name)
|
||||
(dump! module)
|
||||
(dump! name)
|
||||
(push-code! '(link-later)))
|
||||
(dump! name))
|
||||
((<vlink-now> name)
|
||||
(dump! name)
|
||||
(push-code! '(link-now)))
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
|
||||
program-arity program-external-set! program-meta
|
||||
program-bytecode program? program-objects
|
||||
program-base program-external))
|
||||
program-module program-base program-external))
|
||||
|
||||
(dynamic-call "scm_init_programs" (dynamic-link "libguile"))
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue