aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTeddy <ted.sybil@gmail.com>2013-08-12 21:34:55 +0800
committerTeddy <ted.sybil@gmail.com>2013-08-12 21:34:55 +0800
commitd4d9eee6bef1bc9169e765c9bf3d2382a70198c2 (patch)
tree045c3eff6ab6a83554ee2cb46651a19b144ff868
parent55d1072441582936d119ed04fd8c532c2760b9d4 (diff)
...
-rw-r--r--eval.cpp11
-rw-r--r--gc.cpp30
-rw-r--r--gc.h3
-rw-r--r--types.cpp10
4 files changed, 39 insertions, 15 deletions
diff --git a/eval.cpp b/eval.cpp
index e21ae7b..7370187 100644
--- a/eval.cpp
+++ b/eval.cpp
@@ -110,13 +110,11 @@ inline bool make_exec(Pair *ptr) {
}
inline void push(Pair * &pc, FrameObj ** &top_ptr, Environment *envt) {
- gc.attach(pc);
// if (pc->car == NULL)
// puts("oops");
if (pc->car->is_simple_obj()) // Not an opt invocation
{
- *top_ptr = envt->get_obj(pc->car); // Objectify the symbol
- top_ptr++;
+ *top_ptr++ = gc.attach(envt->get_obj(pc->car)); // Objectify the symbol
pc = pc->next; // Move to the next instruction
// if (pc == empty_list)
// puts("oops");
@@ -152,6 +150,7 @@ EvalObj *Evaluator::run_expr(Pair *prog) {
Continuation *cont = NULL;
// envt is this->envt
push(pc, top_ptr, envt);
+ gc.attach(prog);
while((*eval_stack)->is_ret_addr())
{
@@ -163,7 +162,11 @@ EvalObj *Evaluator::run_expr(Pair *prog) {
{
Pair *args = empty_list;
while (!(*(--top_ptr))->is_ret_addr())
- args = new Pair(static_cast<EvalObj*>(*top_ptr), args);
+ {
+ EvalObj* obj = static_cast<EvalObj*>(*top_ptr);
+ gc.expose(obj);
+ args = new Pair(obj, args);
+ }
//< static_cast because the while condition
RetAddr *ret_addr = static_cast<RetAddr*>(*top_ptr);
if (!ret_addr->addr)
diff --git a/gc.cpp b/gc.cpp
index a5fdc48..5aed8b8 100644
--- a/gc.cpp
+++ b/gc.cpp
@@ -13,39 +13,46 @@ GarbageCollector::GarbageCollector() {
mapping.clear();
pend_cnt = 0;
pending_list = NULL;
+ collecting = false;
}
GarbageCollector::PendingEntry::PendingEntry(
EvalObj *_obj, PendingEntry *_next) : obj(_obj), next(_next) {}
-void GarbageCollector::expose(EvalObj *ptr, bool delay) {
+void GarbageCollector::expose(EvalObj *ptr) {
bool flag = mapping.count(ptr);
if (flag)
{
- if (!--mapping[ptr] && !delay)
+#ifdef GC_DEBUG
+ fprintf(stderr, "GC: 0x%llx exposed. count = %lu \"%s\"\n",
+ (ull)ptr, mapping[ptr], ptr->ext_repr().c_str());
+#endif
+ if (!--mapping[ptr] && collecting)
{
#ifdef GC_DEBUG
fprintf(stderr, "GC: 0x%llx pending. \n", (ull)ptr);
#endif
pending_list = new PendingEntry(ptr, pending_list);
- if (++pend_cnt == GC_QUEUE_SIZE >> 1)
- force(); // the gc queue may overflow
- }
+ }
}
}
void GarbageCollector::force() {
EvalObj **l = gcq, **r = l;
- for (PendingEntry *p = pending_list, *np; p; p = np)
+/* for (PendingEntry *p = pending_list, *np; p; p = np)
{
np = p->next;
*r++ = p->obj;
delete p;
} // fetch the pending pointers in the list
// clear the list
- pending_list = NULL;
+ pending_list = NULL; */
+ for (EvalObj2Int::iterator it = mapping.begin();
+ it != mapping.end(); it++)
+ if (it->second == 0) *r++ = it->first;
+ collecting = true;
#ifdef GC_DEBUG
size_t cnt = 0;
fprintf(stderr, "GC: Forcing the clear process...\n");
@@ -57,6 +64,7 @@ void GarbageCollector::force() {
cnt++;
#endif
delete *l;
+ mapping.erase(*l);
// maybe it's a complex structure,
// so that more pointers are reported
for (PendingEntry *p = pending_list, *np; p; p = np)
@@ -70,8 +78,14 @@ void GarbageCollector::force() {
pending_list = NULL;
}
#ifdef GC_DEBUG
- fprintf(stderr, "GC: Forced clear, %lu objects are freed\n", cnt);
+ fprintf(stderr, "GC: Forced clear, %lu objects are freed, "
+ "%lu remains\n", cnt, mapping.size());
+/* for (EvalObj2Int::iterator it = mapping.begin();
+ it != mapping.end(); it++)
+ fprintf(stderr, "%llx => %lu\n", (ull)it->first, it->second);
+ */
#endif
+ collecting = false;
}
EvalObj *GarbageCollector::attach(EvalObj *ptr) {
diff --git a/gc.h b/gc.h
index c017156..8380210 100644
--- a/gc.h
+++ b/gc.h
@@ -19,11 +19,12 @@ class GarbageCollector {
EvalObj2Int mapping;
size_t pend_cnt;
PendingEntry *pending_list;
+ bool collecting;
public:
GarbageCollector();
void force();
- void expose(EvalObj *ptr, bool delay = false);
+ void expose(EvalObj *ptr);
EvalObj *attach(EvalObj *ptr);
};
diff --git a/types.cpp b/types.cpp
index 1548805..84106df 100644
--- a/types.cpp
+++ b/types.cpp
@@ -90,9 +90,13 @@ Pair *ProcObj::call(Pair *args, Environment * &genvt,
genvt = _envt;
cont = _cont;
- *top_ptr++ = new RetAddr(NULL); // Mark the entrance of a cont
+
+ gc.expose(static_cast<EvalObj*>(*(top_ptr + 1))); // release opt obj
+ delete *top_ptr; // release ret addr
+
+ *top_ptr++ = new RetAddr(NULL); // Mark the entrance of a cont
gc.expose(args);
- return body; // Move pc to the proc entry point
+ return body; // Move pc to the proc entry point
}
ReprCons *ProcObj::get_repr_cons() {
@@ -222,6 +226,8 @@ BuiltinProcObj::BuiltinProcObj(BuiltinProc f, string _name) :
Continuation * &cont, FrameObj ** &top_ptr) {
Pair *ret_addr = static_cast<RetAddr*>(*top_ptr)->addr;
+ gc.expose(static_cast<EvalObj*>(*(top_ptr + 1)));
+ delete *top_ptr;
*top_ptr++ = handler(TO_PAIR(args->cdr), name);
gc.expose(args);
return ret_addr->next; // Move to the next instruction