[pure-lang-svn] SF.net SVN: pure-lang: [94] pure/trunk
Status: Beta
Brought to you by:
agraef
|
From: <ag...@us...> - 2008-05-17 19:45:21
|
Revision: 94
http://pure-lang.svn.sourceforge.net/pure-lang/?rev=94&view=rev
Author: agraef
Date: 2008-05-17 12:45:28 -0700 (Sat, 17 May 2008)
Log Message:
-----------
Fixed broken pure_free_internal routine.
Modified Paths:
--------------
pure/trunk/ChangeLog
pure/trunk/runtime.cc
Modified: pure/trunk/ChangeLog
===================================================================
--- pure/trunk/ChangeLog 2008-05-17 12:43:37 UTC (rev 93)
+++ pure/trunk/ChangeLog 2008-05-17 19:45:28 UTC (rev 94)
@@ -1,5 +1,8 @@
2008-05-17 Albert Graef <Dr....@t-...>
+ * runtime.cc (pure_free_internal): Fixed a glitch which was
+ causing big memleaks. Reported by Libor Spacek.
+
* interpreter.cc (define): Fixed error messages.
* interpreter.cc, runtime.h: Reorganize pure_expr data structure
@@ -18,11 +21,10 @@
Please note that the typename 'long' *always* denotes signed 64
bit integers in Pure's extern declarations, even if the C 'long'
type is actually 32 bit (as it usually is even on most 64 bit
- systems).
+ systems). Also note that at present 'long' is still converted
+ to/from Pure (32 bit) ints only, marshalling from/to Pure bigints
+ is not supported yet.
- FIXME: At present 'long' is still converted to/from Pure (32 bit)
- ints only, marshalling from/to Pure bigints is not supported yet.
-
2008-05-16 Albert Graef <Dr....@t-...>
* runtime.h: Fix compilation problems when header gets included
Modified: pure/trunk/runtime.cc
===================================================================
--- pure/trunk/runtime.cc 2008-05-17 12:43:37 UTC (rev 93)
+++ pure/trunk/runtime.cc 2008-05-17 19:45:28 UTC (rev 94)
@@ -22,21 +22,37 @@
// Debug expression allocations.
#if DEBUG>2
set<pure_expr*> mem_allocations;
-#define MEMDEBUG_NEW(x) mem_allocations.insert(x); \
+#if DEBUG>9
+#define MEMDEBUG_NEW(x) mem_allocations.insert(x); \
cerr << "NEW: " << (void*)x << ": " << x << endl;
-#define MEMDEBUG_FREE(x) mem_allocations.erase(x); \
+#define MEMDEBUG_FREE(x) mem_allocations.erase(x); \
cerr << "FREE: " << (void*)x << ": " << x << endl;
+#else
+#define MEMDEBUG_NEW(x) mem_allocations.insert(x);
+#define MEMDEBUG_FREE(x) mem_allocations.erase(x);
+#endif
#define MEMDEBUG_INIT mem_allocations.clear();
-#define MEMDEBUG_SUMMARY cerr << "SUMMARY:\n"; \
- for (set<pure_expr*>::iterator x = mem_allocations.begin(); \
- x != mem_allocations.end(); x++) \
- cerr << (void*)(*x) << ": " << (*x) << endl; \
- mem_allocations.clear();
+#define MEMDEBUG_SUMMARY(ret) mem_mark(ret); \
+ if (!mem_allocations.empty()) { cerr << "POSSIBLE LEAKS:\n"; \
+ for (set<pure_expr*>::iterator x = mem_allocations.begin(); \
+ x != mem_allocations.end(); x++) \
+ cerr << (void*)(*x) << " (refc = " << (*x)->refc << "): " \
+ << (*x) << endl; \
+ mem_allocations.clear(); \
+ }
+static void mem_mark(pure_expr *x)
+{
+ mem_allocations.erase(x);
+ if (x->tag == EXPR::APP) {
+ mem_mark(x->data.x[0]);
+ mem_mark(x->data.x[1]);
+ }
+}
#else
#define MEMDEBUG_NEW(x)
#define MEMDEBUG_FREE(x)
#define MEMDEBUG_INIT
-#define MEMDEBUG_SUMMARY
+#define MEMDEBUG_SUMMARY(ret)
#endif
// Expression pointers are allocated in larger chunks for better performance.
@@ -115,30 +131,25 @@
delete x->data.clos;
}
+#if 1
+
+/* This is implemented (mostly) non-recursively to prevent stack overflows,
+ using the xp field to form a stack on the fly. */
+
static inline
void pure_free_internal(pure_expr *x)
{
assert(x && "pure_free: null expression");
assert(x->refc > 0 && "pure_free: unreferenced expression");
assert(!x->xp && "pure_free: corrupt expression data");
- // Implemented (mostly) non-recursively to prevent stack overflows, using
- // the xp field to form a stack on the fly.
- pure_expr *xp;
+ pure_expr *xp = 0, *y;
loop:
-#if DEBUG>2
- if (x->tag >= 0 && x->data.clos)
- cerr << "pure_free: " << (x->data.clos->local?"local":"global")
- << " closure " << x << " (" << (void*)x << "), refc = "
- << x->refc << endl;
-#endif
if (--x->refc == 0) {
switch (x->tag) {
case EXPR::APP:
- xp = x->data.x[0];
- assert(!xp->xp);
- xp->xp = x->data.x[1];
- free_expr(x);
- x = xp;
+ y = x->data.x[0];
+ assert(!x->xp);
+ x->xp = xp; xp = x; x = y;
goto loop;
case EXPR::INT:
case EXPR::DBL:
@@ -158,17 +169,54 @@
if (x->data.clos) pure_free_clos(x);
break;
}
- xp = x->xp; x->xp = 0;
- free_expr(x);
- } else {
- xp = x->xp; x->xp = 0;
}
+ while (xp && x == xp->data.x[1]) {
+ if (x->refc == 0) free_expr(x);
+ x = xp; xp = x->xp;
+ }
+ if (x->refc == 0) free_expr(x);
if (xp) {
- x = xp;
+ x = xp->data.x[1];
goto loop;
}
}
+#else
+
+/* This version is only included here for reference and debugging purposes,
+ normal builds should use the non-recursive version above. */
+
+static
+void pure_free_internal(pure_expr *x)
+{
+ if (--x->refc == 0) {
+ switch (x->tag) {
+ case EXPR::APP:
+ pure_free_internal(x->data.x[0]);
+ pure_free_internal(x->data.x[1]);
+ break;
+ case EXPR::INT:
+ case EXPR::DBL:
+ break;
+ case EXPR::BIGINT:
+ mpz_clear(x->data.z);
+ break;
+ case EXPR::STR:
+ free(x->data.s);
+ break;
+ case EXPR::PTR:
+ break;
+ default:
+ assert(x->tag >= 0);
+ if (x->data.clos) pure_free_clos(x);
+ break;
+ }
+ free_expr(x);
+ }
+}
+
+#endif
+
static void inline
pure_unref_internal(pure_expr *x)
{
@@ -594,13 +642,13 @@
if (tmps != e) pure_freenew(tmps);
tmps = next;
}
- MEMDEBUG_SUMMARY
+ MEMDEBUG_SUMMARY(e)
return 0;
} else {
pure_expr *res = fp();
// normal return
interp.estk.pop_front();
- MEMDEBUG_SUMMARY
+ MEMDEBUG_SUMMARY(res)
#if DEBUG>1
pure_expr *tmps = interp.tmps;
while (tmps) {
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|