about summary refs log tree commit diff
path: root/src/rt/rust_cc.cpp
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2011-10-21 15:06:02 -0700
committerBrian Anderson <banderson@mozilla.com>2011-10-21 16:07:40 -0700
commit7ab6315f5fe51e9620e48fa4118d44b780e1c828 (patch)
treecd955a2f68bd2788afeeea4bc26ccebb3fe3afbb /src/rt/rust_cc.cpp
parent2d713215a8fba320b2e5472d1ae6924e5a9d263c (diff)
downloadrust-7ab6315f5fe51e9620e48fa4118d44b780e1c828.tar.gz
rust-7ab6315f5fe51e9620e48fa4118d44b780e1c828.zip
Free vectors during cc sweep
Diffstat (limited to 'src/rt/rust_cc.cpp')
-rw-r--r--src/rt/rust_cc.cpp129
1 files changed, 126 insertions, 3 deletions
diff --git a/src/rt/rust_cc.cpp b/src/rt/rust_cc.cpp
index 2e3ff89291c..8982a4a312e 100644
--- a/src/rt/rust_cc.cpp
+++ b/src/rt/rust_cc.cpp
@@ -422,18 +422,141 @@ mark::do_mark(rust_task *task, const std::vector<void *> &roots,
     }
 }
 
+class sweep : public shape::data<sweep,shape::ptr> {
+    friend class shape::data<sweep,shape::ptr>;
+
+    sweep(const sweep &other, const shape::ptr &in_dp)
+	: shape::data<sweep,shape::ptr>(other.task, other.align,
+					other.sp, other.params,
+					other.tables, in_dp) {}
+
+    sweep(const sweep &other,
+	  const uint8_t *in_sp,
+	  const shape::type_param *in_params,
+	  const rust_shape_tables *in_tables = NULL)
+	: shape::data<sweep,shape::ptr>(other.task,
+					other.align,
+					in_sp,
+					in_params,
+					in_tables ? in_tables : other.tables,
+					other.dp) {}
+
+    sweep(const sweep &other,
+	  const uint8_t *in_sp,
+	  const shape::type_param *in_params,
+	  const rust_shape_tables *in_tables,
+	  shape::ptr in_dp)
+	: shape::data<sweep,shape::ptr>(other.task,
+					other.align,
+					in_sp,
+					in_params,
+					in_tables,
+					in_dp) {}
+
+    sweep(rust_task *in_task,
+	  bool in_align,
+	  const uint8_t *in_sp,
+	  const shape::type_param *in_params,
+	  const rust_shape_tables *in_tables,
+	  uint8_t *in_data)
+	: shape::data<sweep,shape::ptr>(in_task, in_align, in_sp,
+					in_params, in_tables, in_data) {}
+
+    void walk_vec(bool is_pod, uint16_t sp_size) {
+	void *vec = shape::get_dp<void *>(dp);
+	walk_vec(is_pod, get_vec_data_range(dp));
+	task->kernel->free(vec);
+    }
+
+    void walk_vec(bool is_pod,
+		  const std::pair<shape::ptr,shape::ptr> &data_range) {
+	sweep sub(*this, data_range.first);
+	shape::ptr data_end = sub.end_dp = data_range.second;
+	while (sub.dp < data_end) {
+	    sub.walk_reset();
+	    sub.align = true;
+	}
+    }
+
+    void walk_tag(shape::tag_info &tinfo, uint32_t tag_variant) {
+        shape::data<sweep,shape::ptr>::walk_variant(tinfo, tag_variant);
+    }
+
+    void walk_box() {
+	shape::data<sweep,shape::ptr>::walk_box_contents();
+    }
+
+    void walk_fn() {
+	return;
+    }
+
+    void walk_obj() {
+        shape::data<sweep,shape::ptr>::walk_obj_contents(dp);
+    }
+
+    void walk_res(const shape::rust_fn *dtor, unsigned n_params,
+                  const shape::type_param *params, const uint8_t *end_sp,
+                  bool live) {
+        while (this->sp != end_sp) {
+            this->walk();
+            align = true;
+        }
+    }
+
+    void walk_subcontext(sweep &sub) { sub.walk(); }
+
+    void walk_box_contents(sweep &sub, shape::ptr &ref_count_dp) {
+	return;
+    }
+
+    void walk_struct(const uint8_t *end_sp) {
+        while (this->sp != end_sp) {
+            this->walk();
+            align = true;
+        }
+    }
+
+    void walk_variant(shape::tag_info &tinfo, uint32_t variant_id,
+                      const std::pair<const uint8_t *,const uint8_t *>
+                      variant_ptr_and_end) {
+	sweep sub(*this, variant_ptr_and_end.first, tinfo.params);
+
+	const uint8_t *variant_end = variant_ptr_and_end.second;
+	while (sub.sp < variant_end) {
+	    sub.walk();
+	    align = true;
+	}
+    }
+
+    template<typename T>
+    inline void walk_number() { /* no-op */ }
+
+public:
+    static void do_sweep(rust_task *task, const std::set<void *> &marked);
+};
 
 void
-sweep(rust_task *task, const std::set<void *> &marked) {
+sweep::do_sweep(rust_task *task, const std::set<void *> &marked) {
     std::map<void *,const type_desc *>::iterator
         begin(task->local_allocs.begin()), end(task->local_allocs.end());
     while (begin != end) {
         void *alloc = begin->first;
+
         if (marked.find(alloc) == marked.end()) {
             LOG(task, gc, "object is part of a cycle: %p", alloc);
 
-            // FIXME: Run the destructor, *if* it's a resource.
+	    const type_desc *tydesc = begin->second;
+            uint8_t *p = reinterpret_cast<uint8_t *>(alloc);
+            shape::arena arena;
+            shape::type_param *params =
+                shape::type_param::from_tydesc_and_data(tydesc, p, arena);
+
+	    sweep sweep(task, true, tydesc->shape,
+			params, tydesc->shape_tables,
+			p + sizeof(uintptr_t));
+	    sweep.walk();
 
+            // FIXME: Run the destructor, *if* it's a resource.
             task->free(alloc);
         }
         ++begin;
@@ -455,7 +578,7 @@ do_cc(rust_task *task) {
     std::set<void *> marked;
     mark::do_mark(task, roots, marked);
 
-    sweep(task, marked);
+    sweep::do_sweep(task, marked);
 }
 
 void