Actually it is moving code within the C core. When I said I moved the
code out of make-byte-code, I was talking about the C function
Fmake_byte_code defined in alloc.c. Here's a patch against 21.5.14 as a
text attachment:
alloc.c:
-- Added zeroing of args, max_args, min_args and args_in_array to
make_compiled_function.
-- Removed allocation and initialization of args array from Fmake_byte_code.
bytecode.c:
-- Added allocation and initialization of args array to
optimize_compiled_function.
eval.c:
-- Added call to optimize_compiled_function to function_argcount, to
force initialization of max_args.
The effect of this change is to delay the allocation and initialization
of these fields from object creation until first use. This has a minor
effect on performance, mostly to the good. On the plus side, functions
that are never called in a particular session never need their args
arrays created. On the negative side, the first call to a function takes
just a tiny bit longer than before. Also, this means that some work that
would have been done pre-dump gets delayed until user startup time.
Although I haven't measured this, I am confident that it is
insignificant. However, the motivation for this change has nothing to do
with potential performance improvements. This is in fact just a
convenient way of dodging a bug in the portable dumper, which seems to
cause the args array of at least one function to be misdumped. Note that
this bug remains unfixed in the dumper, and that it may still show
itself in some other context.
Stephen J. Turnbull wrote:
>>>>>"Eric" == Eric Benson
<eric_a_benson(a)yahoo.com> writes:
>>>>>
>>>>>
Eric> I moved this code to optimize_compiled_function instead, so
Eric> that the args array isn't created until the first time the
Eric> function is called. This should be better overall in almost
Eric> all cases, and it avoids this bug since the args arrays of
Eric> most functions don't even exist when pdump is called.
Work up a patch against 21.5. I doubt it will go into 21.4 any time
soon. Send it to xemacs-patches(a)xemacs.org. Don't forget change logs
(in lisp/ChangeLog and in src/ChangeLog).
In general we don't like moving stuff from Lisp to C, but since a fix
in Lisp here would require redumping anyway, it's almost like moving
code within the C core.
If possible, preserve the references to this thread in your patch post.
*** alloc.c~ 2003-03-08 18:37:53.000000000 -0800
--- alloc.c 2003-07-11 10:04:00.000000000 -0700
***************
*** 1509,1514 ****
--- 1509,1515 ----
f->instructions = Qzero;
f->constants = Qzero;
f->arglist = Qnil;
+ f->args = f->max_args = f->min_args = f->args_in_array = 0;
f->doc_and_interactive = Qnil;
#ifdef COMPILED_FUNCTION_ANNOTATION_HACK
f->annotated = Qnil;
***************
*** 1563,1610 ****
}
f->arglist = arglist;
- {
- int minargs = 0, maxargs = 0, totalargs = 0;
- int optional_p = 0, rest_p = 0, i = 0;
- {
- LIST_LOOP_2 (arg, arglist)
- {
- if (EQ (arg, Qand_optional))
- optional_p = 1;
- else if (EQ (arg, Qand_rest))
- rest_p = 1;
- else
- {
- if (rest_p)
- {
- maxargs = MANY;
- totalargs++;
- break;
- }
- if (!optional_p)
- minargs++;
- maxargs++;
- totalargs++;
- }
- }
- }
-
- if (totalargs)
- f->args = xnew_array (Lisp_Object, totalargs);
-
- {
- LIST_LOOP_2 (arg, arglist)
- {
- if (!EQ (arg, Qand_optional) && !EQ (arg, Qand_rest))
- f->args[i++] = arg;
- }
- }
-
- f->max_args = maxargs;
- f->min_args = minargs;
- f->args_in_array = totalargs;
- }
-
/* `instructions' is a string or a cons (string . int) for a
lazy-loaded function. */
if (CONSP (instructions))
--- 1564,1569 ----
*** bytecode.c~ 2003-01-13 00:46:23.000000000 -0800
--- bytecode.c 2003-07-11 09:05:10.000000000 -0700
***************
*** 1730,1735 ****
--- 1730,1777 ----
int varbind_count;
Opbyte *program;
+ {
+ int minargs = 0, maxargs = 0, totalargs = 0;
+ int optional_p = 0, rest_p = 0, i = 0;
+ {
+ LIST_LOOP_2 (arg, f->arglist)
+ {
+ if (EQ (arg, Qand_optional))
+ optional_p = 1;
+ else if (EQ (arg, Qand_rest))
+ rest_p = 1;
+ else
+ {
+ if (rest_p)
+ {
+ maxargs = MANY;
+ totalargs++;
+ break;
+ }
+ if (!optional_p)
+ minargs++;
+ maxargs++;
+ totalargs++;
+ }
+ }
+ }
+
+ if (totalargs)
+ f->args = xnew_array (Lisp_Object, totalargs);
+
+ {
+ LIST_LOOP_2 (arg, f->arglist)
+ {
+ if (!EQ (arg, Qand_optional) && !EQ (arg, Qand_rest))
+ f->args[i++] = arg;
+ }
+ }
+
+ f->max_args = maxargs;
+ f->min_args = minargs;
+ f->args_in_array = totalargs;
+ }
+
/* If we have not actually read the bytecode string
and constants vector yet, fetch them from the file. */
if (CONSP (f->instructions))
*** eval.c~ 2003-03-08 17:38:14.000000000 -0800
--- eval.c 2003-07-11 10:06:33.000000000 -0700
***************
*** 3966,3971 ****
--- 3966,3976 ----
{
Lisp_Compiled_Function *f = XCOMPILED_FUNCTION (function);
+ if (!OPAQUEP (f->instructions))
+ /* Lazily munge the instructions into a more efficient form */
+ /* Needed to set max_args */
+ optimize_compiled_function (function);
+
if (function_min_args_p)
return make_int (f->min_args);
else if (f->max_args == MANY)