mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-19 10:10:23 +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 <string.h>
|
||||||
#include "vm-bootstrap.h"
|
#include "vm-bootstrap.h"
|
||||||
#include "instructions.h"
|
#include "instructions.h"
|
||||||
|
#include "modules.h"
|
||||||
#include "programs.h"
|
#include "programs.h"
|
||||||
#include "vm.h"
|
#include "vm.h"
|
||||||
|
|
||||||
|
@ -69,6 +70,7 @@ scm_c_make_program (void *addr, size_t size, SCM holder)
|
||||||
p->objs = zero_vector;
|
p->objs = zero_vector;
|
||||||
p->external = SCM_EOL;
|
p->external = SCM_EOL;
|
||||||
p->holder = holder;
|
p->holder = holder;
|
||||||
|
p->module = scm_current_module ();
|
||||||
|
|
||||||
/* If nobody holds bytecode's address, then allocate a new memory */
|
/* If nobody holds bytecode's address, then allocate a new memory */
|
||||||
if (SCM_FALSEP (holder))
|
if (SCM_FALSEP (holder))
|
||||||
|
@ -99,6 +101,7 @@ program_mark (SCM obj)
|
||||||
scm_gc_mark (p->meta);
|
scm_gc_mark (p->meta);
|
||||||
scm_gc_mark (p->objs);
|
scm_gc_mark (p->objs);
|
||||||
scm_gc_mark (p->external);
|
scm_gc_mark (p->external);
|
||||||
|
scm_gc_mark (p->module);
|
||||||
return p->holder;
|
return p->holder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,6 +187,16 @@ SCM_DEFINE (scm_program_objects, "program-objects", 1, 0, 0,
|
||||||
}
|
}
|
||||||
#undef FUNC_NAME
|
#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_DEFINE (scm_program_external, "program-external", 1, 0, 0,
|
||||||
(SCM program),
|
(SCM program),
|
||||||
"")
|
"")
|
||||||
|
|
|
@ -57,6 +57,7 @@ struct scm_program {
|
||||||
unsigned char nlocs; /* the number of local variables */
|
unsigned char nlocs; /* the number of local variables */
|
||||||
unsigned char nexts; /* the number of external variables */
|
unsigned char nexts; /* the number of external variables */
|
||||||
scm_byte_t *base; /* program base address */
|
scm_byte_t *base; /* program base address */
|
||||||
|
SCM module; /* resolve bindings with respect to this module */
|
||||||
SCM meta; /* meta data */
|
SCM meta; /* meta data */
|
||||||
SCM objs; /* constant objects */
|
SCM objs; /* constant objects */
|
||||||
SCM external; /* external environment */
|
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_arity (SCM program);
|
||||||
extern SCM scm_program_meta (SCM program);
|
extern SCM scm_program_meta (SCM program);
|
||||||
extern SCM scm_program_objects (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 (SCM program);
|
||||||
extern SCM scm_program_external_set_x (SCM program, SCM external);
|
extern SCM scm_program_external_set_x (SCM program, SCM external);
|
||||||
extern SCM scm_program_bytecode (SCM program);
|
extern SCM scm_program_bytecode (SCM program);
|
||||||
|
|
|
@ -172,16 +172,6 @@ VM_DEFINE_INSTRUCTION (link_now, "link-now", 0, 1, 1)
|
||||||
NEXT;
|
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")
|
VM_DEFINE_LOADER (define, "define")
|
||||||
{
|
{
|
||||||
SCM sym;
|
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)
|
VM_DEFINE_INSTRUCTION (late_variable_ref, "late-variable-ref", 1, 0, 1)
|
||||||
{
|
{
|
||||||
unsigned objnum = FETCH ();
|
unsigned objnum = FETCH ();
|
||||||
SCM pair_or_var;
|
SCM sym_or_var;
|
||||||
CHECK_OBJECT (objnum);
|
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 ();
|
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 */
|
/* might longjmp */
|
||||||
SCM mod = scm_resolve_module (SCM_CAR (pair_or_var));
|
sym_or_var = scm_module_lookup (bp->module, sym_or_var);
|
||||||
pair_or_var = scm_module_lookup (mod, SCM_CDR (pair_or_var));
|
|
||||||
}
|
}
|
||||||
else
|
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;
|
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;
|
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)
|
VM_DEFINE_INSTRUCTION (late_variable_set, "late-variable-set", 1, 1, 0)
|
||||||
{
|
{
|
||||||
unsigned objnum = FETCH ();
|
unsigned objnum = FETCH ();
|
||||||
SCM pair_or_var;
|
SCM sym_or_var;
|
||||||
CHECK_OBJECT (objnum);
|
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 ();
|
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 */
|
/* might longjmp */
|
||||||
SCM mod = scm_resolve_module (SCM_CAR (pair_or_var));
|
sym_or_var = scm_module_lookup (bp->module, sym_or_var);
|
||||||
pair_or_var = scm_module_lookup (mod, SCM_CDR (pair_or_var));
|
|
||||||
}
|
}
|
||||||
else
|
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 ();
|
DROP ();
|
||||||
NEXT;
|
NEXT;
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,21 +161,9 @@
|
||||||
;; "external" so that it goes on the heap.
|
;; "external" so that it goes on the heap.
|
||||||
;;
|
;;
|
||||||
;; If the variable is not found lexically, it is a toplevel variable,
|
;; 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
|
;; which will be looked up at runtime with respect to the module that
|
||||||
;; current at compile-time. The variable will be resolved when it is
|
;; was current when the lambda was bound, at runtime. The variable will
|
||||||
;; first used.
|
;; 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.
|
|
||||||
(define (ghil-lookup env sym)
|
(define (ghil-lookup env sym)
|
||||||
(let loop ((e env))
|
(let loop ((e env))
|
||||||
(record-case e
|
(record-case e
|
||||||
|
|
|
@ -285,9 +285,7 @@
|
||||||
;; dump bytecode
|
;; dump bytecode
|
||||||
(push-code! `(load-program ,bytes)))
|
(push-code! `(load-program ,bytes)))
|
||||||
((<vlink-later> module name)
|
((<vlink-later> module name)
|
||||||
(dump! module)
|
(dump! name))
|
||||||
(dump! name)
|
|
||||||
(push-code! '(link-later)))
|
|
||||||
((<vlink-now> name)
|
((<vlink-now> name)
|
||||||
(dump! name)
|
(dump! name)
|
||||||
(push-code! '(link-now)))
|
(push-code! '(link-now)))
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
|
|
||||||
program-arity program-external-set! program-meta
|
program-arity program-external-set! program-meta
|
||||||
program-bytecode program? program-objects
|
program-bytecode program? program-objects
|
||||||
program-base program-external))
|
program-module program-base program-external))
|
||||||
|
|
||||||
(dynamic-call "scm_init_programs" (dynamic-link "libguile"))
|
(dynamic-call "scm_init_programs" (dynamic-link "libguile"))
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue