Blob Blame History Raw
--- 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,