New variable Free_primitive is set during primitive invocations to
the value of Free on entry, so that Primitive_GC can find the total
amount of space requested so far from the GC, rather than the amount
currently being requested. Avoids endless GC loops, particularly in,
e.g., bignum primitives.
#endif
extern SCHEME_OBJECT * Free;
+extern SCHEME_OBJECT * Free_primitive;
extern SCHEME_OBJECT * heap_alloc_limit;
extern SCHEME_OBJECT * heap_start;
extern SCHEME_OBJECT * heap_end;
{ \
void * PRIMITIVE_APPLY_INTERNAL_position = dstack_position; \
SET_PRIMITIVE (primitive); \
+ Free_primitive = Free; \
SET_VAL \
((* (Primitive_Procedure_Table [PRIMITIVE_NUMBER (primitive)])) \
()); \
(PRIMITIVE_NAME (primitive))); \
Microcode_Termination (TERM_EXIT); \
} \
+ Free_primitive = 0; \
SET_PRIMITIVE (SHARP_F); \
} while (0)
#define Primitive_GC(Amount) do \
{ \
- REQUEST_GC (Amount); \
+ if (Free_primitive < heap_start) \
+ { \
+ outf_fatal \
+ ("\nMicrocode requested primitive GC outside primitive!\n"); \
+ Microcode_Termination (TERM_EXIT); \
+ } \
+ if (Free < Free_primitive) \
+ { \
+ outf_fatal ("\nFree has gone backwards!\n"); \
+ Microcode_Termination (TERM_EXIT); \
+ } \
+ REQUEST_GC ((Amount) + (Free - Free_primitive)); \
signal_interrupt_from_primitive (); \
} while (0)
/* next free word in heap */
SCHEME_OBJECT * Free;
+/* value of Free on entry to primitive, or 0 if not in primitive */
+SCHEME_OBJECT * Free_primitive = 0;
+
/* strict limit for Free */
SCHEME_OBJECT * heap_alloc_limit;