Make binding of fns with bounded type parameters work
Interns non-static dicts to heap-allocated equivalents so that they no longer have stack scope. Closes #1436
This commit is contained in:
parent
d23e2052e0
commit
822acdd170
@ -2,7 +2,7 @@
|
||||
import driver::session;
|
||||
import middle::trans;
|
||||
import middle::trans_common::{T_fn, T_i1, T_i8, T_i32,
|
||||
T_int, T_nil,
|
||||
T_int, T_nil, T_dict,
|
||||
T_opaque_vec, T_ptr,
|
||||
T_size_t, T_void};
|
||||
import lib::llvm::type_names;
|
||||
@ -20,6 +20,7 @@ type upcalls =
|
||||
create_shared_type_desc: ValueRef,
|
||||
free_shared_type_desc: ValueRef,
|
||||
get_type_desc: ValueRef,
|
||||
intern_dict: ValueRef,
|
||||
vec_grow: ValueRef,
|
||||
vec_push: ValueRef,
|
||||
cmp_type: ValueRef,
|
||||
@ -76,6 +77,8 @@ fn declare_upcalls(targ_cfg: @session::config,
|
||||
size_t, size_t,
|
||||
T_ptr(T_ptr(tydesc_type)), int_t],
|
||||
T_ptr(tydesc_type)),
|
||||
intern_dict:
|
||||
d("intern_dict", [size_t, T_ptr(T_dict())], T_ptr(T_dict())),
|
||||
vec_grow:
|
||||
dv("vec_grow", [T_ptr(T_ptr(opaque_vec_t)), int_t]),
|
||||
vec_push:
|
||||
|
@ -461,18 +461,24 @@ fn trans_bind_1(cx: @block_ctxt, outgoing_fty: ty::t,
|
||||
let (outgoing_fty_real, lltydescs, param_bounds) = alt f_res.generic {
|
||||
none. { (outgoing_fty, [], @[]) }
|
||||
some(ginfo) {
|
||||
for bounds in *ginfo.param_bounds {
|
||||
let tds = [], orig = 0u;
|
||||
vec::iter2(ginfo.tydescs, *ginfo.param_bounds) {|td, bounds|
|
||||
tds += [td];
|
||||
for bound in *bounds {
|
||||
alt bound {
|
||||
ty::bound_iface(_) {
|
||||
fail "FIXME[impl] binding bounded types not implemented";
|
||||
let dict = trans_impl::get_dict(
|
||||
bcx, option::get(ginfo.origins)[orig]);
|
||||
tds += [PointerCast(bcx, dict.val, val_ty(td))];
|
||||
orig += 1u;
|
||||
bcx = dict.bcx;
|
||||
}
|
||||
_ {}
|
||||
}
|
||||
}
|
||||
}
|
||||
lazily_emit_all_generic_info_tydesc_glues(cx, ginfo);
|
||||
(ginfo.item_type, ginfo.tydescs, ginfo.param_bounds)
|
||||
(ginfo.item_type, tds, ginfo.param_bounds)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -143,9 +143,10 @@ fn dict_is_static(tcx: ty::ctxt, origin: typeck::dict_origin) -> bool {
|
||||
}
|
||||
|
||||
fn get_dict(bcx: @block_ctxt, origin: typeck::dict_origin) -> result {
|
||||
let ccx = bcx_ccx(bcx);
|
||||
alt origin {
|
||||
typeck::dict_static(impl_did, tys, sub_origins) {
|
||||
if dict_is_static(bcx_tcx(bcx), origin) {
|
||||
if dict_is_static(ccx.tcx, origin) {
|
||||
ret rslt(bcx, get_static_dict(bcx, origin));
|
||||
}
|
||||
let {bcx, ptrs} = get_dict_ptrs(bcx, origin);
|
||||
@ -155,7 +156,10 @@ fn get_dict(bcx: @block_ctxt, origin: typeck::dict_origin) -> result {
|
||||
Store(bcx, PointerCast(bcx, ptr, pty), GEPi(bcx, dict, [0, i]));
|
||||
i += 1;
|
||||
}
|
||||
rslt(bcx, PointerCast(bcx, dict, T_ptr(T_dict())))
|
||||
dict = Call(bcx, ccx.upcalls.intern_dict,
|
||||
[C_uint(ccx, vec::len(ptrs)),
|
||||
PointerCast(bcx, dict, T_ptr(T_dict()))]);
|
||||
rslt(bcx, dict)
|
||||
}
|
||||
typeck::dict_param(n_param, n_bound) {
|
||||
rslt(bcx, option::get(bcx.fcx.lltyparams[n_param].dicts)[n_bound])
|
||||
|
@ -45,8 +45,30 @@ rust_crate_cache::get_type_desc(size_t size,
|
||||
return td;
|
||||
}
|
||||
|
||||
void**
|
||||
rust_crate_cache::get_dict(size_t n_fields, void** dict) {
|
||||
rust_hashable_dict *found = NULL;
|
||||
uintptr_t key = 0;
|
||||
for (size_t i = 0; i < n_fields; ++i) key ^= (uintptr_t)dict[i];
|
||||
size_t keysz = sizeof(uintptr_t);
|
||||
HASH_FIND(hh, this->dicts, &key, keysz, found);
|
||||
if (found) { printf("found!\n"); return &(found->fields[0]); }
|
||||
printf("not found\n");
|
||||
size_t dictsz = n_fields * sizeof(void*);
|
||||
found = (rust_hashable_dict*)
|
||||
sched->kernel->malloc(keysz + sizeof(UT_hash_handle) + dictsz,
|
||||
"crate cache dict");
|
||||
if (!found) return NULL;
|
||||
found->key = key;
|
||||
void** retptr = &(found->fields[0]);
|
||||
memcpy(retptr, dict, dictsz);
|
||||
HASH_ADD(hh, this->dicts, key, keysz, found);
|
||||
return retptr;
|
||||
}
|
||||
|
||||
rust_crate_cache::rust_crate_cache(rust_scheduler *sched)
|
||||
: type_descs(NULL),
|
||||
dicts(NULL),
|
||||
sched(sched),
|
||||
idx(0)
|
||||
{
|
||||
@ -62,6 +84,11 @@ rust_crate_cache::flush() {
|
||||
DLOG(sched, mem, "rust_crate_cache::flush() tydesc %" PRIxPTR, d);
|
||||
sched->kernel->free(d);
|
||||
}
|
||||
while (dicts) {
|
||||
rust_hashable_dict *d = dicts;
|
||||
HASH_DEL(dicts, d);
|
||||
sched->kernel->free(d);
|
||||
}
|
||||
}
|
||||
|
||||
rust_crate_cache::~rust_crate_cache()
|
||||
|
@ -11,6 +11,12 @@
|
||||
|
||||
struct rust_scheduler;
|
||||
|
||||
struct rust_hashable_dict {
|
||||
uintptr_t key;
|
||||
UT_hash_handle hh;
|
||||
void* fields[0];
|
||||
};
|
||||
|
||||
class rust_crate_cache {
|
||||
public:
|
||||
type_desc *get_type_desc(size_t size,
|
||||
@ -18,10 +24,12 @@ public:
|
||||
size_t n_descs,
|
||||
type_desc const **descs,
|
||||
uintptr_t n_obj_params);
|
||||
void** get_dict(size_t n_fields, void** dict);
|
||||
|
||||
private:
|
||||
|
||||
type_desc *type_descs;
|
||||
rust_hashable_dict *dicts;
|
||||
|
||||
public:
|
||||
|
||||
|
@ -336,6 +336,32 @@ upcall_get_type_desc(void *curr_crate, // ignored, legacy compat.
|
||||
return args.retval;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* Called to get a heap-allocated dict. These are interned and kept
|
||||
* around indefinitely
|
||||
*/
|
||||
|
||||
struct s_intern_dict_args {
|
||||
size_t n_fields;
|
||||
void** dict;
|
||||
void** res;
|
||||
};
|
||||
|
||||
extern "C" CDECL void
|
||||
upcall_s_intern_dict(s_intern_dict_args *args) {
|
||||
rust_task *task = rust_scheduler::get_task();
|
||||
LOG_UPCALL_ENTRY(task);
|
||||
rust_crate_cache *cache = task->get_crate_cache();
|
||||
args->res = cache->get_dict(args->n_fields, args->dict);
|
||||
}
|
||||
|
||||
extern "C" CDECL void**
|
||||
upcall_intern_dict(size_t n_fields, void** dict) {
|
||||
s_intern_dict_args args = {n_fields, dict, 0 };
|
||||
UPCALL_SWITCH_STACK(&args, upcall_s_intern_dict);
|
||||
return args.res;
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
struct s_vec_grow_args {
|
||||
|
@ -62,6 +62,7 @@ upcall_free
|
||||
upcall_create_shared_type_desc
|
||||
upcall_free_shared_type_desc
|
||||
upcall_get_type_desc
|
||||
upcall_intern_dict
|
||||
upcall_log_type
|
||||
upcall_malloc
|
||||
upcall_rust_personality
|
||||
|
Loading…
x
Reference in New Issue
Block a user