1 /* Copyright (C) 1995,1996,1998,1999,2000,2001, 2003, 2004, 2006, 2009, 2010, 2011 Free Software Foundation, Inc.
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public License
5 * as published by the Free Software Foundation; either version 3 of
6 * the License, or (at your option) any later version.
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
28 #include "libguile/_scm.h"
30 #include "libguile/async.h"
31 #include "libguile/goops.h"
32 #include "libguile/instructions.h"
33 #include "libguile/objcodes.h"
34 #include "libguile/programs.h"
40 #include "libguile/smob.h"
42 #include "libguile/bdw-gc.h"
43 #include <gc/gc_mark.h>
48 /* scm_smobs scm_numsmob
49 * implement a fixed sized array of smob records.
50 * Indexes into this table are used when generating type
51 * tags for smobjects (if you know a tag you can get an index and conversely).
54 #define MAX_SMOB_COUNT SCM_I_MAX_SMOB_TYPE_COUNT
57 scm_smob_descriptor scm_smobs
[MAX_SMOB_COUNT
];
60 scm_assert_smob_type (scm_t_bits tag
, SCM val
)
62 if (!SCM_SMOB_PREDICATE (tag
, val
))
63 scm_wrong_type_arg_msg (NULL
, 0, val
, scm_smobs
[SCM_TC2SMOBNUM(tag
)].name
);
69 /* This function is vestigial. It used to be the mark function's
70 responsibility to set the mark bit on the smob or port, but now the
71 generic marking routine in gc.c takes care of that, and a zero
72 pointer for a mark function means "don't bother". So you never
75 However, we leave it here because it's harmless to call it, and
76 people out there have smob code that uses it, and there's no reason
77 to make their links fail. */
80 scm_mark0 (SCM ptr SCM_UNUSED
)
86 /* Dirk::FIXME: The name markcdr is misleading, since the term cdr should only
87 be used for real pairs. */
90 return SCM_CELL_OBJECT_1 (ptr
);
98 scm_free0 (SCM ptr SCM_UNUSED
)
108 scm_smob_print (SCM exp
, SCM port
, scm_print_state
*pstate SCM_UNUSED
)
110 long n
= SCM_SMOBNUM (exp
);
111 scm_puts ("#<", port
);
112 scm_puts (SCM_SMOBNAME (n
) ? SCM_SMOBNAME (n
) : "smob", port
);
113 scm_putc (' ', port
);
114 if (scm_smobs
[n
].size
)
115 scm_uintprint (SCM_CELL_WORD_1 (exp
), 16, port
);
117 scm_uintprint (SCM_UNPACK (exp
), 16, port
);
118 scm_putc ('>', port
);
126 #ifdef WORDS_BIGENDIAN
127 #define OBJCODE_HEADER 0, 0, 0, 16, 0, 0, 0, 40
128 #define META_HEADER 0, 0, 0, 32, 0, 0, 0, 0
130 #define OBJCODE_HEADER 16, 0, 0, 0, 40, 0, 0, 0
131 #define META_HEADER 32, 0, 0, 0, 0, 0, 0, 0
134 /* This code is the same as in gsubr.c, except we use smob_call instead of
137 /* A: req; B: opt; C: rest */
140 /* 0 */ scm_op_assert_nargs_ee, 0, nreq, /* assert number of args */ \
141 /* 3 */ scm_op_object_ref, 0, /* push the foreign object wrapping the subr pointer */ \
142 /* 5 */ scm_op_smob_call, nreq, /* and call (will return value as well) */ \
143 /* 7 */ scm_op_nop, \
144 /* 8 */ scm_op_nop, scm_op_nop, scm_op_nop, scm_op_nop, \
145 /* 12 */ scm_op_nop, scm_op_nop, scm_op_nop, scm_op_nop, \
146 /* 16 */ META (3, 7, nreq, 0, 0)
150 /* 0 */ scm_op_bind_optionals, 0, nopt, /* bind optionals */ \
151 /* 3 */ scm_op_assert_nargs_ee, 0, nopt, /* assert number of args */ \
152 /* 6 */ scm_op_object_ref, 0, /* push the foreign object wrapping the smob pointer */ \
153 /* 8 */ scm_op_smob_call, nopt, /* and call (will return value as well) */ \
154 /* 10 */ scm_op_nop, scm_op_nop, \
155 /* 12 */ scm_op_nop, scm_op_nop, scm_op_nop, scm_op_nop, \
156 /* 16 */ META (6, 10, 0, nopt, 0)
160 /* 0 */ scm_op_push_rest, 0, 0, /* cons all args into a list */ \
161 /* 3 */ scm_op_object_ref, 0, /* push the foreign object wrapping the smob pointer */ \
162 /* 5 */ scm_op_smob_call, 1, /* and call (will return value as well) */ \
163 /* 7 */ scm_op_nop, \
164 /* 8 */ scm_op_nop, scm_op_nop, scm_op_nop, scm_op_nop, \
165 /* 12 */ scm_op_nop, scm_op_nop, scm_op_nop, scm_op_nop, \
166 /* 16 */ META (3, 7, 0, 0, 1)
168 #define AB(nreq, nopt) \
170 /* 0 */ scm_op_assert_nargs_ge, 0, nreq, /* assert number of args */ \
171 /* 3 */ scm_op_bind_optionals, 0, nreq+nopt, /* bind optionals */ \
172 /* 6 */ scm_op_assert_nargs_ee, 0, nreq+nopt, /* assert number of args */ \
173 /* 9 */ scm_op_object_ref, 0, /* push the foreign object wrapping the smob pointer */ \
174 /* 11 */ scm_op_smob_call, nreq+nopt, /* and call (will return value as well) */ \
175 /* 13 */ scm_op_nop, scm_op_nop, scm_op_nop, \
176 /* 16 */ META (9, 13, nreq, nopt, 0)
180 /* 0 */ scm_op_assert_nargs_ge, 0, nreq, /* assert number of args */ \
181 /* 3 */ scm_op_push_rest, 0, nreq, /* cons rest list */ \
182 /* 6 */ scm_op_object_ref, 0, /* push the foreign object wrapping the smob pointer */ \
183 /* 8 */ scm_op_smob_call, nreq+1, /* and call (will return value as well) */ \
184 /* 10 */ scm_op_nop, scm_op_nop, \
185 /* 12 */ scm_op_nop, scm_op_nop, scm_op_nop, scm_op_nop, \
186 /* 16 */ META (6, 10, nreq, 0, 1)
190 /* 0 */ scm_op_bind_optionals, 0, nopt, /* bind optionals */ \
191 /* 3 */ scm_op_push_rest, 0, nopt, /* cons rest list */ \
192 /* 6 */ scm_op_object_ref, 0, /* push the foreign object wrapping the smob pointer */ \
193 /* 8 */ scm_op_smob_call, nopt+1, /* and call (will return value as well) */ \
194 /* 10 */ scm_op_nop, scm_op_nop, \
195 /* 12 */ scm_op_nop, scm_op_nop, scm_op_nop, scm_op_nop, \
196 /* 16 */ META (6, 10, 0, nopt, 1)
198 #define ABC(nreq, nopt) \
200 /* 0 */ scm_op_assert_nargs_ge, 0, nreq, /* assert number of args */ \
201 /* 3 */ scm_op_bind_optionals, 0, nreq+nopt, /* bind optionals */ \
202 /* 6 */ scm_op_push_rest, 0, nreq+nopt, /* cons rest list */ \
203 /* 9 */ scm_op_object_ref, 0, /* push the foreign object wrapping the smob pointer */ \
204 /* 11 */ scm_op_smob_call, nreq+nopt+1, /* and call (will return value as well) */ \
205 /* 13 */ scm_op_nop, scm_op_nop, scm_op_nop, \
206 /* 16 */ META (9, 13, nreq, nopt, 1)
208 #define META(start, end, nreq, nopt, rest) \
210 /* 0 */ scm_op_make_eol, /* bindings */ \
211 /* 1 */ scm_op_make_eol, /* sources */ \
212 /* 2 */ scm_op_make_int8, start, scm_op_make_int8, end, /* arity: from ip N to ip N */ \
213 /* 6 */ scm_op_make_int8, nreq, /* the arity is N required args */ \
214 /* 8 */ scm_op_make_int8, nopt, /* N optionals */ \
215 /* 10 */ rest ? scm_op_make_true : scm_op_make_false, /* maybe a rest arg */ \
216 /* 11 */ scm_op_list, 0, 5, /* make a list of those 5 vals */ \
217 /* 14 */ scm_op_list, 0, 1, /* and the arities will be a list of that one list */ \
218 /* 17 */ scm_op_load_symbol, 0, 0, 4, 'n', 'a', 'm', 'e', /* `name' */ \
219 /* 25 */ scm_op_object_ref, 1, /* the name from the object table */ \
220 /* 27 */ scm_op_cons, /* make a pair for the properties */ \
221 /* 28 */ scm_op_list, 0, 4, /* pack bindings, sources, and arities into list */ \
222 /* 31 */ scm_op_return /* and return */ \
227 scm_t_uint64 dummy
; /* ensure 8-byte alignment; perhaps there's a better way */
228 const scm_t_uint8 bytes
[16 * (sizeof (struct scm_objcode
) + 16
229 + sizeof (struct scm_objcode
) + 32)];
233 /* Use the elisp macros from gsubr.c */
234 /* C-u 3 M-x generate-bytecodes RET */
240 A(2), AB(1,1), B(2), AC(1), BC(1),
242 A(3), AB(2,1), AB(1,2), B(3), AC(2), ABC(1,1), BC(2)
253 #undef OBJCODE_HEADER
257 #define STATIC_OBJCODE_TAG \
258 SCM_PACK (SCM_MAKE_OBJCODE_TAG (SCM_OBJCODE_TYPE_STATIC, 0))
262 scm_t_uint64 dummy
; /* alignment */
263 scm_t_cell cells
[16 * 2]; /* 4*4 double cells */
266 /* C-u 3 M-x generate-objcode-cells RET */
269 { STATIC_OBJCODE_TAG
, SCM_PACK (raw_bytecode
.bytes
+ 0) },
270 { SCM_BOOL_F
, SCM_PACK (0) },
273 { STATIC_OBJCODE_TAG
, SCM_PACK (raw_bytecode
.bytes
+ 64) },
274 { SCM_BOOL_F
, SCM_PACK (0) },
275 { STATIC_OBJCODE_TAG
, SCM_PACK (raw_bytecode
.bytes
+ 128) },
276 { SCM_BOOL_F
, SCM_PACK (0) },
278 { STATIC_OBJCODE_TAG
, SCM_PACK (raw_bytecode
.bytes
+ 192) },
279 { SCM_BOOL_F
, SCM_PACK (0) },
282 { STATIC_OBJCODE_TAG
, SCM_PACK (raw_bytecode
.bytes
+ 256) },
283 { SCM_BOOL_F
, SCM_PACK (0) },
284 { STATIC_OBJCODE_TAG
, SCM_PACK (raw_bytecode
.bytes
+ 320) },
285 { SCM_BOOL_F
, SCM_PACK (0) },
286 { STATIC_OBJCODE_TAG
, SCM_PACK (raw_bytecode
.bytes
+ 384) },
287 { SCM_BOOL_F
, SCM_PACK (0) },
289 { STATIC_OBJCODE_TAG
, SCM_PACK (raw_bytecode
.bytes
+ 448) },
290 { SCM_BOOL_F
, SCM_PACK (0) },
291 { STATIC_OBJCODE_TAG
, SCM_PACK (raw_bytecode
.bytes
+ 512) },
292 { SCM_BOOL_F
, SCM_PACK (0) },
295 { STATIC_OBJCODE_TAG
, SCM_PACK (raw_bytecode
.bytes
+ 576) },
296 { SCM_BOOL_F
, SCM_PACK (0) },
297 { STATIC_OBJCODE_TAG
, SCM_PACK (raw_bytecode
.bytes
+ 640) },
298 { SCM_BOOL_F
, SCM_PACK (0) },
299 { STATIC_OBJCODE_TAG
, SCM_PACK (raw_bytecode
.bytes
+ 704) },
300 { SCM_BOOL_F
, SCM_PACK (0) },
301 { STATIC_OBJCODE_TAG
, SCM_PACK (raw_bytecode
.bytes
+ 768) },
302 { SCM_BOOL_F
, SCM_PACK (0) },
304 { STATIC_OBJCODE_TAG
, SCM_PACK (raw_bytecode
.bytes
+ 832) },
305 { SCM_BOOL_F
, SCM_PACK (0) },
306 { STATIC_OBJCODE_TAG
, SCM_PACK (raw_bytecode
.bytes
+ 896) },
307 { SCM_BOOL_F
, SCM_PACK (0) },
308 { STATIC_OBJCODE_TAG
, SCM_PACK (raw_bytecode
.bytes
+ 960) },
309 { SCM_BOOL_F
, SCM_PACK (0) }
313 static const SCM scm_smob_objcode_trampolines
[16] = {
314 /* C-u 3 M-x generate-objcodes RET */
316 SCM_PACK (objcode_cells
.cells
+0),
319 SCM_PACK (objcode_cells
.cells
+2),
320 SCM_PACK (objcode_cells
.cells
+4),
321 SCM_PACK (objcode_cells
.cells
+6),
324 SCM_PACK (objcode_cells
.cells
+8),
325 SCM_PACK (objcode_cells
.cells
+10),
326 SCM_PACK (objcode_cells
.cells
+12),
327 SCM_PACK (objcode_cells
.cells
+14),
328 SCM_PACK (objcode_cells
.cells
+16),
331 SCM_PACK (objcode_cells
.cells
+18),
332 SCM_PACK (objcode_cells
.cells
+20),
333 SCM_PACK (objcode_cells
.cells
+22),
334 SCM_PACK (objcode_cells
.cells
+24),
335 SCM_PACK (objcode_cells
.cells
+26),
336 SCM_PACK (objcode_cells
.cells
+28),
337 SCM_PACK (objcode_cells
.cells
+30)
340 /* (nargs * nargs) + nopt + rest * (nargs + 1) */
341 #define SCM_SMOB_OBJCODE_TRAMPOLINE(nreq,nopt,rest) \
342 scm_smob_objcode_trampolines[(nreq + nopt + rest) * (nreq + nopt + rest) \
343 + nopt + rest * (nreq + nopt + rest + 1)]
346 scm_smob_objcode_trampoline (unsigned int nreq
, unsigned int nopt
,
349 if (SCM_UNLIKELY (rest
> 1 || nreq
+ nopt
+ rest
> 3))
350 scm_out_of_range ("make-smob", scm_from_uint (nreq
+ nopt
+ rest
));
352 return SCM_SMOB_OBJCODE_TRAMPOLINE (nreq
, nopt
, rest
);
358 scm_make_smob_type (char const *name
, size_t size
)
359 #define FUNC_NAME "scm_make_smob_type"
363 SCM_CRITICAL_SECTION_START
;
364 new_smob
= scm_numsmob
;
365 if (scm_numsmob
!= MAX_SMOB_COUNT
)
367 SCM_CRITICAL_SECTION_END
;
369 if (new_smob
== MAX_SMOB_COUNT
)
370 scm_misc_error (FUNC_NAME
, "maximum number of smobs exceeded", SCM_EOL
);
372 scm_smobs
[new_smob
].name
= name
;
373 scm_smobs
[new_smob
].size
= size
;
375 /* Make a class object if Goops is present. */
376 if (SCM_UNPACK (scm_smob_class
[0]) != 0)
377 scm_smob_class
[new_smob
] = scm_make_extended_class (name
, 0);
379 return scm_tc7_smob
+ new_smob
* 256;
385 scm_set_smob_mark (scm_t_bits tc
, SCM (*mark
) (SCM
))
387 scm_smobs
[SCM_TC2SMOBNUM (tc
)].mark
= mark
;
391 scm_set_smob_free (scm_t_bits tc
, size_t (*free
) (SCM
))
393 scm_smobs
[SCM_TC2SMOBNUM (tc
)].free
= free
;
397 scm_set_smob_print (scm_t_bits tc
, int (*print
) (SCM
, SCM
, scm_print_state
*))
399 scm_smobs
[SCM_TC2SMOBNUM (tc
)].print
= print
;
403 scm_set_smob_equalp (scm_t_bits tc
, SCM (*equalp
) (SCM
, SCM
))
405 scm_smobs
[SCM_TC2SMOBNUM (tc
)].equalp
= equalp
;
409 scm_set_smob_apply (scm_t_bits tc
, SCM (*apply
) (),
410 unsigned int req
, unsigned int opt
, unsigned int rst
)
412 scm_smobs
[SCM_TC2SMOBNUM (tc
)].apply
= apply
;
413 scm_smobs
[SCM_TC2SMOBNUM (tc
)].apply_trampoline_objcode
414 = scm_smob_objcode_trampoline (req
, opt
, rst
);
416 if (SCM_UNPACK (scm_smob_class
[0]) != 0)
417 scm_i_inherit_applicable (scm_smob_class
[SCM_TC2SMOBNUM (tc
)]);
420 static SCM tramp_weak_map
= SCM_BOOL_F
;
421 static scm_i_pthread_mutex_t tramp_lock
= SCM_I_PTHREAD_MUTEX_INITIALIZER
;
424 scm_i_smob_apply_trampoline (SCM smob
)
428 scm_i_pthread_mutex_lock (&tramp_lock
);
429 tramp
= scm_hashq_ref (tramp_weak_map
, smob
, SCM_BOOL_F
);
430 scm_i_pthread_mutex_unlock (&tramp_lock
);
432 if (scm_is_true (tramp
))
439 name
= SCM_SMOBNAME (SCM_SMOBNUM (smob
));
442 objtable
= scm_c_make_vector (2, SCM_UNDEFINED
);
443 SCM_SIMPLE_VECTOR_SET (objtable
, 0, smob
);
444 SCM_SIMPLE_VECTOR_SET (objtable
, 1, scm_from_locale_symbol (name
));
445 tramp
= scm_make_program (SCM_SMOB_DESCRIPTOR (smob
).apply_trampoline_objcode
,
446 objtable
, SCM_BOOL_F
);
448 /* Race conditions (between the ref and this set!) cannot cause
450 scm_i_pthread_mutex_lock (&tramp_lock
);
451 scm_hashq_set_x (tramp_weak_map
, smob
, tramp
);
452 scm_i_pthread_mutex_unlock (&tramp_lock
);
458 scm_make_smob (scm_t_bits tc
)
460 scm_t_bits n
= SCM_TC2SMOBNUM (tc
);
461 size_t size
= scm_smobs
[n
].size
;
462 scm_t_bits data
= (size
> 0
463 ? (scm_t_bits
) scm_gc_malloc (size
, SCM_SMOBNAME (n
))
466 SCM_RETURN_NEWSMOB (tc
, data
);
471 /* Marking SMOBs using user-supplied mark procedures. */
474 /* The GC kind used for SMOB types that provide a custom mark procedure. */
475 static int smob_gc_kind
;
478 /* The generic SMOB mark procedure that gets called for SMOBs allocated with
479 `scm_i_new_smob_with_mark_proc ()'. */
480 static struct GC_ms_entry
*
481 smob_mark (GC_word
*addr
, struct GC_ms_entry
*mark_stack_ptr
,
482 struct GC_ms_entry
*mark_stack_limit
, GC_word env
)
485 register scm_t_bits tc
, smobnum
;
487 cell
= PTR2SCM (addr
);
489 if (SCM_TYP7 (cell
) != scm_tc7_smob
)
490 /* It is likely that the GC passed us a pointer to a free-list element
491 which we must ignore (see warning in `gc/gc_mark.h'). */
492 return mark_stack_ptr
;
494 tc
= SCM_CELL_WORD_0 (cell
);
495 smobnum
= SCM_TC2SMOBNUM (tc
);
497 if (smobnum
>= scm_numsmob
)
498 /* The first word looks corrupt. */
501 mark_stack_ptr
= GC_MARK_AND_PUSH (SCM2PTR (SCM_CELL_OBJECT_1 (cell
)),
503 mark_stack_limit
, NULL
);
504 mark_stack_ptr
= GC_MARK_AND_PUSH (SCM2PTR (SCM_CELL_OBJECT_2 (cell
)),
506 mark_stack_limit
, NULL
);
507 mark_stack_ptr
= GC_MARK_AND_PUSH (SCM2PTR (SCM_CELL_OBJECT_3 (cell
)),
509 mark_stack_limit
, NULL
);
511 if (scm_smobs
[smobnum
].mark
)
515 SCM_I_CURRENT_THREAD
->current_mark_stack_ptr
= mark_stack_ptr
;
516 SCM_I_CURRENT_THREAD
->current_mark_stack_limit
= mark_stack_limit
;
518 /* Invoke the SMOB's mark procedure, which will in turn invoke
519 `scm_gc_mark ()', which may modify `current_mark_stack_ptr'. */
520 obj
= scm_smobs
[smobnum
].mark (cell
);
522 mark_stack_ptr
= SCM_I_CURRENT_THREAD
->current_mark_stack_ptr
;
525 /* Mark the returned object. */
526 mark_stack_ptr
= GC_MARK_AND_PUSH (SCM2PTR (obj
),
528 mark_stack_limit
, NULL
);
530 SCM_I_CURRENT_THREAD
->current_mark_stack_limit
= NULL
;
531 SCM_I_CURRENT_THREAD
->current_mark_stack_ptr
= NULL
;
534 return mark_stack_ptr
;
538 /* Mark object O. We assume that this function is only called during the
539 mark phase, i.e., from within `smob_mark ()' or one of its
544 #define CURRENT_MARK_PTR \
545 ((struct GC_ms_entry *)(SCM_I_CURRENT_THREAD->current_mark_stack_ptr))
546 #define CURRENT_MARK_LIMIT \
547 ((struct GC_ms_entry *)(SCM_I_CURRENT_THREAD->current_mark_stack_limit))
551 /* At this point, the `current_mark_*' fields of the current thread
552 must be defined (they are set in `smob_mark ()'). */
553 register struct GC_ms_entry
*mark_stack_ptr
;
555 if (!CURRENT_MARK_PTR
)
556 /* The function was not called from a mark procedure. */
559 mark_stack_ptr
= GC_MARK_AND_PUSH (SCM2PTR (o
),
560 CURRENT_MARK_PTR
, CURRENT_MARK_LIMIT
,
562 SCM_I_CURRENT_THREAD
->current_mark_stack_ptr
= mark_stack_ptr
;
564 #undef CURRENT_MARK_PTR
565 #undef CURRENT_MARK_LIMIT
568 /* Return a SMOB with typecode TC. The SMOB type corresponding to TC may
569 provide a custom mark procedure and it will be honored. */
571 scm_i_new_smob_with_mark_proc (scm_t_bits tc
, scm_t_bits data1
,
572 scm_t_bits data2
, scm_t_bits data3
)
574 /* Return a double cell. */
575 SCM cell
= SCM_PACK (GC_generic_malloc (2 * sizeof (scm_t_cell
),
578 SCM_SET_CELL_WORD_3 (cell
, data3
);
579 SCM_SET_CELL_WORD_2 (cell
, data2
);
580 SCM_SET_CELL_WORD_1 (cell
, data1
);
581 SCM_SET_CELL_WORD_0 (cell
, tc
);
587 /* Finalize SMOB by calling its SMOB type's free function, if any. */
589 scm_i_finalize_smob (GC_PTR ptr
, GC_PTR data
)
592 size_t (* free_smob
) (SCM
);
594 smob
= PTR2SCM (ptr
);
596 printf ("finalizing SMOB %p (smobnum: %u)\n",
597 ptr
, SCM_SMOBNUM (smob
));
600 free_smob
= scm_smobs
[SCM_SMOBNUM (smob
)].free
;
607 scm_smob_prehistory ()
611 smob_gc_kind
= GC_new_kind (GC_new_free_list (),
612 GC_MAKE_PROC (GC_new_proc (smob_mark
), 0),
614 /* Clear new objects. As of version 7.1, libgc
615 doesn't seem to support passing 0 here. */
619 for (i
= 0; i
< MAX_SMOB_COUNT
; ++i
)
621 scm_smobs
[i
].name
= 0;
622 scm_smobs
[i
].size
= 0;
623 scm_smobs
[i
].mark
= 0;
624 scm_smobs
[i
].free
= 0;
625 scm_smobs
[i
].print
= scm_smob_print
;
626 scm_smobs
[i
].equalp
= 0;
627 scm_smobs
[i
].apply
= 0;
628 scm_smobs
[i
].apply_trampoline_objcode
= SCM_BOOL_F
;
631 tramp_weak_map
= scm_make_weak_key_hash_table (SCM_UNDEFINED
);