1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-10 22:10:21 +02:00

Parse bytecode to determine minimum arity

* libguile/programs.c (try_parse_arity): New helper, to parse bytecode
  to determine the minimum arity of a function in a cheaper way than
  grovelling through the debug info.  Should speed up all thunk? checks
  and similar.
  (scm_i_program_arity): Simplify.
* libguile/gsubr.h:
* libguile/gsubr.c (scm_i_primitive_arity):
* libguile/foreign.h:
* libguile/foreign.c (scm_i_foreign_arity):
This commit is contained in:
Andy Wingo 2016-06-24 14:15:38 +02:00
parent 5ca24b6ba1
commit d848af9a16
5 changed files with 58 additions and 66 deletions

View file

@ -792,25 +792,6 @@ get_foreign_stub_code (unsigned int nargs)
return &foreign_stub_code[nargs * 2];
}
/* Given a foreign procedure, determine its minimum arity. */
int
scm_i_foreign_arity (SCM foreign, int *req, int *opt, int *rest)
{
const scm_t_uint32 *code = SCM_PROGRAM_CODE (foreign);
if (code < foreign_stub_code)
return 0;
if (code > (foreign_stub_code
+ (sizeof(foreign_stub_code) / sizeof(scm_t_uint32))))
return 0;
*req = (code - foreign_stub_code) / 2;
*opt = 0;
*rest = 0;
return 1;
}
static SCM
cif_to_procedure (SCM cif, SCM func_ptr)
{

View file

@ -101,8 +101,6 @@ SCM_API SCM scm_procedure_to_pointer (SCM return_type, SCM func_ptr,
SCM arg_types);
SCM_INTERNAL SCM scm_i_foreign_call (SCM foreign,
const union scm_vm_stack_element *argv);
SCM_INTERNAL int scm_i_foreign_arity (SCM foreign,
int *req, int *opt, int *rest);

View file

@ -262,37 +262,6 @@ scm_i_primitive_code_p (const scm_t_uint32 *code)
return 1;
}
/* Given a program that is a primitive, determine its minimum arity.
This is possible because each primitive's code is 4 32-bit words
long, and they are laid out contiguously in an ordered pattern. */
int
scm_i_primitive_arity (SCM prim, int *req, int *opt, int *rest)
{
const scm_t_uint32 *code = SCM_PROGRAM_CODE (prim);
unsigned idx, nargs, base, next;
if (!scm_i_primitive_code_p (code))
return 0;
idx = (code - subr_stub_code) / 4;
nargs = -1;
next = 0;
do
{
base = next;
nargs++;
next = (nargs + 1) * (nargs + 1);
}
while (idx >= next);
*rest = (next - idx) < (idx - base);
*req = *rest ? (next - 1) - idx : (base + nargs) - idx;
*opt = *rest ? idx - (next - nargs) : idx - base;
return 1;
}
scm_t_uintptr
scm_i_primitive_call_ip (SCM subr)
{

View file

@ -55,7 +55,6 @@
SCM_INTERNAL int scm_i_primitive_code_p (const scm_t_uint32 *code);
SCM_INTERNAL int scm_i_primitive_arity (SCM subr, int *req, int *opt, int *rest);
SCM_INTERNAL scm_t_uintptr scm_i_primitive_call_ip (SCM subr);
union scm_vm_stack_element;

View file

@ -22,6 +22,7 @@
#include <string.h>
#include "_scm.h"
#include "instructions.h"
#include "modules.h"
#include "programs.h"
#include "procprop.h" /* scm_sym_name */
@ -236,25 +237,69 @@ SCM_DEFINE (scm_program_free_variable_set_x, "program-free-variable-set!", 3, 0,
}
#undef FUNC_NAME
/* It's hacky, but it manages to cover all of the non-keyword cases. */
static int
try_parse_arity (SCM program, int *req, int *opt, int *rest)
{
scm_t_uint32 *code = SCM_PROGRAM_CODE (program);
scm_t_uint32 slots, min;
switch (code[0] & 0xff) {
case scm_op_assert_nargs_ee:
slots = code[0] >> 8;
*req = slots - 1;
*opt = 0;
*rest = 0;
return 1;
case scm_op_assert_nargs_le:
slots = code[0] >> 8;
*req = 0;
*opt = slots - 1;
*rest = 0;
return 1;
case scm_op_bind_rest:
slots = code[0] >> 8;
*req = 0;
*opt = slots - 1;
*rest = 1;
return 1;
case scm_op_assert_nargs_ge:
min = code[0] >> 8;
switch (code[1] & 0xff) {
case scm_op_assert_nargs_le:
slots = code[1] >> 8;
*req = min - 1;
*opt = slots - 1 - *req;
*rest = 0;
return 1;
case scm_op_bind_rest:
slots = code[1] >> 8;
*req = min - 1;
*opt = slots - min;
*rest = 1;
return 1;
default:
return 0;
}
case scm_op_continuation_call:
case scm_op_compose_continuation:
*req = 0;
*opt = 0;
*rest = 1;
return 1;
default:
return 0;
}
}
int
scm_i_program_arity (SCM program, int *req, int *opt, int *rest)
{
static SCM program_minimum_arity = SCM_BOOL_F;
SCM l;
if (SCM_PRIMITIVE_P (program))
return scm_i_primitive_arity (program, req, opt, rest);
if (SCM_PROGRAM_IS_FOREIGN (program))
return scm_i_foreign_arity (program, req, opt, rest);
if (SCM_PROGRAM_IS_CONTINUATION (program)
|| SCM_PROGRAM_IS_PARTIAL_CONTINUATION (program))
{
*req = *opt = 0;
*rest = 1;
return 1;
}
if (try_parse_arity (program, req, opt, rest))
return 1;
if (scm_is_false (program_minimum_arity) && scm_module_system_booted_p)
program_minimum_arity =