[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Multiple values for R4RS.



    Perhaps each procedure is responsible for coping with wrong number of
    arguments passed in.  Somewhere in the procedure's code are
    instructions that perform the check.  The information is there, but
    with a sufficiently clever compiler -- the sort of implementation I
    find most interesting -- finding that information could be
    impractical, if not intractable.  

With a sufficiently clever compiler, the information should not be in
the code, since all checks have been done at compile time :-)

The MIT compiler used to output instructions to do arity checks at
runtime, but now the dynamic linker checks for arity mismatches when
definitions or assignments occur, thus rendering the runtime check a
waste of time in most of the cases.  The only cases where arity needs
to be checked at runtime in (compiled) MIT Scheme are things like

((car some-pair) arg1 arg2 arg3)

where the shape of the car of SOME-PAIR is not known at compile time.

The arity information is present in fixed format in "external
procedures" so that the linker (a fixed program) can check for
mismatches and create the appropriate trampolines at run time.  The
information is encoded so that the runtime check in cases like the
above is very fast when the number of arguments passed matches exactly
the number of arguments expected, and can be coded in-line, although
we don't do it right now.

The arity information only makes the output code be slightly larger in
a few cases, but hardly affects the time performance.  Except for
garbage collection time (compiled code objects are slightly larger),
and closure creation time (the closures must contain the arity
information if they are passed to "unknown" places), the time penalty
is very small, and I suspect that on the average, it is smaller than
in your model.  

In our implementation we multiplex this information with debugging
information (how many words are on the stack "on top" of a return
address, the kind of compiled entry point this is, etc), and it takes
16 bits per external entry point (whether a compiled procedure,
expression, return address or other), which we feel is not an excesive
space penalty.

Another possibility is to encode the arity information redundantly.
One encoding is for the actual runtime check, the other for ACCEPTS?
or similar procedures.  Note that this redundant encoding need not
take any space in the runtime image, since the compiler can produce
another object when compiling code, associating PCs to arities, and
this can be kept on an external "file", loaded only when someone uses
ACCEPTS?

In general, I find that implementation efficiency arguments based on
details of particular implementation strategies don't carry much
weight because two days later someone finds a different implementation
strategy that jiggles the trade-offs, but maintains the semantics.

Note that I don't need ACCEPTS? to be particularly efficient, since it
will only be used to provide an expensive portability hook.
Implementations that are sincerely interested in supporting less
strict return arity checking will want to provide a more efficient
primitive mechanism.