rt: Introduce a self-describing box representation and functions to create and free them

This commit is contained in:
Patrick Walton 2011-09-19 10:34:27 -07:00
parent 5f44a1356e
commit 3632629acc
3 changed files with 59 additions and 1 deletions

View File

@ -0,0 +1,18 @@
/* Rust box representation. */
#ifndef RUST_BOX_H
#define RUST_BOX_H
#include "rust_internal.h"
#include <stdint.h>
struct rust_box {
RUST_REFCOUNTED(rust_box)
type_desc *tydesc;
rust_box *gc_next;
rust_box *gc_prev;
uint8_t data[0];
};
#endif

View File

@ -10,6 +10,8 @@
#include "context.h"
#include "rust_obstack.h"
struct rust_box;
struct stk_seg {
unsigned int valgrind_id;
uintptr_t limit;
@ -57,7 +59,7 @@ rust_task : public kernel_owned<rust_task>, rust_cond
context ctx;
stk_seg *stk;
uintptr_t runtime_sp; // Runtime sp while task running.
void *gc_alloc_chain; // Linked list of GC allocations.
rust_box *gc_alloc_chain; // Linked list of GC allocations.
rust_scheduler *sched;
rust_crate_cache *cache;

View File

@ -1,3 +1,4 @@
#include "rust_box.h"
#include "rust_gc.h"
#include "rust_internal.h"
#include "rust_unwind.h"
@ -76,6 +77,25 @@ upcall_malloc(rust_task *task, size_t nbytes, type_desc *td) {
return (uintptr_t) p;
}
extern "C" CDECL rust_box *
upcall_malloc_box(rust_task *task, size_t nbytes, type_desc *td) {
LOG_UPCALL_ENTRY(task);
gc::maybe_gc(task);
rust_box *box = reinterpret_cast<rust_box *>
(task->malloc(nbytes + sizeof(rust_box), "tdesc", td));
box->ref_count = 1;
box->tydesc = td;
box->gc_prev = NULL;
if ((box->gc_next = task->gc_alloc_chain) != NULL)
box->gc_next->gc_prev = box;
task->gc_alloc_chain = box;
return box;
}
/**
* Called whenever an object's ref count drops to zero.
*/
@ -90,6 +110,24 @@ upcall_free(rust_task *task, void* ptr, uintptr_t is_gc) {
task->free(ptr, (bool) is_gc);
}
extern "C" CDECL void
upcall_free_box(rust_task *task, rust_box *box) {
LOG_UPCALL_ENTRY(task);
assert(!box->ref_count && "Box reference count is nonzero on free!");
if (box->gc_prev)
box->gc_prev->gc_next = box->gc_next;
else
task->gc_alloc_chain = box->gc_next;
if (box->gc_next)
box->gc_next->gc_prev = box->gc_prev;
box->tydesc->drop_glue(NULL, task, (void *)box->tydesc,
box->tydesc->first_param, box->data);
task->free(box, false);
}
extern "C" CDECL uintptr_t
upcall_shared_malloc(rust_task *task, size_t nbytes, type_desc *td) {
LOG_UPCALL_ENTRY(task);