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;
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,
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:
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)
}
};
}
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);
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])
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)
{
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()
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,
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:
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 {
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