--- src/gapstate.h.orig 2018-11-01 16:56:12.000000000 -0600
+++ src/gapstate.h 2019-02-07 13:15:02.178599668 -0700
@@ -97,6 +97,9 @@ typedef struct GAPState {
UInt1 StateSlots[STATE_SLOTS_SIZE];
+ /* For libgap-api.c */
+ Int EnterStackCount;
+
/* Allocation */
#if !defined(USE_GASMAN)
#define MAX_GC_PREFIX_DESC 4
--- src/gasman.c.orig 2018-11-01 16:56:12.000000000 -0600
+++ src/gasman.c 2019-02-07 13:15:02.181599631 -0700
@@ -1193,6 +1193,12 @@ void SetExtraMarkFuncBags(TNumExtraMarkF
}
+
+void _MarkStackBottomBags(void* StackBottom) {
+ StackBottomBags = StackBottom;
+}
+
+
void InitBags (
UInt initial_size,
Bag * stack_bottom,
--- src/gasman.h.orig 2018-11-01 16:56:12.000000000 -0600
+++ src/gasman.h 2019-02-07 13:15:02.182599619 -0700
@@ -982,6 +982,21 @@ extern void InitCollectFuncB
typedef void (*TNumExtraMarkFuncBags)(void);
extern void SetExtraMarkFuncBags(TNumExtraMarkFuncBags func);
+
+#ifdef __GNUC__
+#define MarkStackBottomBags() \
+ _MarkStackBottomBags(__builtin_frame_address(0));
+/*
+#else
+ * TODO: Detect the best stack frame detection technique at configure time
+ *
+#define MarkStackBottomBags() \
+ register void* rbp asm("rbp"); \
+ _MarkStackBottomBags(rbp);
+*/
+#endif
+extern void _MarkStackBottomBags(void* StackBottom);
+
/****************************************************************************
**
*F InitBags(...) . . . . . . . . . . . . . . . . . . . . . initialize Gasman
--- src/libgap-api.c.orig 2018-11-01 16:56:12.000000000 -0600
+++ src/libgap-api.c 2019-02-07 13:15:02.183599607 -0700
@@ -10,6 +10,8 @@
#include "lists.h"
#include "streams.h"
#include "stringobj.h"
+#include "system.h"
+
//
// Setup and initialisation
@@ -60,3 +62,28 @@ Obj GAP_EvalString(const char * cmd)
res = READ_ALL_COMMANDS(instream, False, True, viewObjFunc);
return res;
}
+
+inline syJmp_buf * _GAP_GetReadJmpError(void)
+{
+ return &(STATE(ReadJmpError));
+}
+
+inline Int _GAP_GetEnterStackCount(void)
+{
+ return STATE(EnterStackCount);
+}
+
+inline void _GAP_IncEnterStackCount(void)
+{
+ STATE(EnterStackCount)++;
+}
+
+inline void _GAP_DecEnterStackCount(void)
+{
+ STATE(EnterStackCount)--;
+}
+
+inline void _GAP_SetEnterStackCount(Int count)
+{
+ STATE(EnterStackCount) = count;
+}
--- src/libgap-api.h.orig 2018-11-01 16:56:12.000000000 -0600
+++ src/libgap-api.h 2019-02-07 13:15:02.183599607 -0700
@@ -5,9 +5,93 @@
#include "gap.h"
-typedef void (*CallbackFunc)(void);
+#ifdef __GNUC__
+#define unlikely(x) __builtin_expect(!!(x), 0)
+#else
+#define unlikely(x) (x)
+#endif
-// Initialisation and finalization
+
+#ifndef GAP_ENTER_DEBUG
+#define GAP_ENTER_DEBUG 0
+#endif
+
+
+extern syJmp_buf * _GAP_GetReadJmpError(void);
+extern Int _GAP_GetEnterStackCount(void);
+extern void _GAP_IncEnterStackCount(void);
+extern void _GAP_DecEnterStackCount(void);
+extern void _GAP_SetEnterStackCount(Int count);
+
+
+#if GAP_ENTER_DEBUG
+#define GAP_ENTER_DEBUG_MESSAGE(message, file, line) \
+ fprintf(stderr, "%s: %d; %s:%d\n", message, _GAP_EnterStackCount, file, line);
+#else
+#define GAP_ENTER_DEBUG_MESSAGE(message, file, line)
+#endif
+
+
+#define GAP_EnterStack() \
+ GAP_ENTER_DEBUG_MESSAGE("EnterStack", __FILE__, __LINE__); \
+ Int _gap_tmp_enter_stack_count = _GAP_GetEnterStackCount(); \
+ if (_gap_tmp_enter_stack_count < 0) { \
+ _GAP_SetEnterStackCount(-_gap_tmp_enter_stack_count); \
+ } else { \
+ if (_gap_tmp_enter_stack_count == 0) { \
+ MarkStackBottomBags(); \
+ } \
+ _GAP_IncEnterStackCount(); \
+ }
+
+
+#define GAP_LeaveStack() \
+ _GAP_DecEnterStackCount(); \
+ GAP_ENTER_DEBUG_MESSAGE("LeaveStack", __FILE__, __LINE__);
+
+
+static inline int _GAP_Error_Prejmp(const char* file, int line) {
+#if GAP_ENTER_DEBUG
+ GAP_ENTER_DEBUG_MESSAGE("Error_Prejmp", file, line);
+#endif
+ if (_GAP_GetEnterStackCount() > 0) {
+ return 1;
+ }
+ return 0;
+}
+
+
+static inline int _GAP_Error_Postjmp(int JumpRet)
+{
+ if (unlikely(JumpRet != 0)) {
+ /* This only should have been called from the outer-most
+ * GAP_EnterStack() call so make sure it resets the EnterStackCount; We
+ * set EnterStackCount to its negative which indicates to
+ * GAP_EnterStack that we just returned from a long jump and should
+ * reset EnterStackCount to its value at the return point rather than
+ * increment it again */
+ Int tmp_count = _GAP_GetEnterStackCount();
+ if (tmp_count > 0) {
+ _GAP_SetEnterStackCount(-tmp_count);
+ }
+ return 0;
+ }
+
+ return 1;
+}
+
+#define GAP_Error_Setjmp() (_GAP_Error_Prejmp(__FILE__, __LINE__) || \
+ _GAP_Error_Postjmp(sySetjmp(*_GAP_GetReadJmpError())))
+
+
+#define GAP_Enter() GAP_Error_Setjmp(); GAP_EnterStack()
+#define GAP_Leave() GAP_LeaveStack()
+
+
+////
+//// Setup and initialisation
+////
+typedef void (*CallbackFunc)(void);
void GAP_Initialize(int argc,
char ** argv,