]> git.lizzy.rs Git - rust.git/commitdiff
Make binding of fns with bounded type parameters work
authorMarijn Haverbeke <marijnh@gmail.com>
Fri, 6 Jan 2012 16:29:06 +0000 (17:29 +0100)
committerMarijn Haverbeke <marijnh@gmail.com>
Fri, 6 Jan 2012 16:40:05 +0000 (17:40 +0100)
Interns non-static dicts to heap-allocated equivalents so that they no
longer have stack scope.

Closes #1436

src/comp/back/upcall.rs
src/comp/middle/trans_closure.rs
src/comp/middle/trans_impl.rs
src/rt/rust_crate_cache.cpp
src/rt/rust_scheduler.h
src/rt/rust_upcall.cpp
src/rt/rustrt.def.in

index d488a0fa00d668edfdb3d27d03fcbdf65e044300..a6bf286a2a83218d4abe5fe40d67c0c07b68c908 100644 (file)
@@ -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 @@
      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 decl(llmod: ModuleRef, name: str, tys: [TypeRef], rv: TypeRef) ->
                  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:
index 7759072f0288486b15b168cb9057344ac768213b..4a43b2ead875b3c7286b25e28cb7b348d170507c 100644 (file)
@@ -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)
       }
     };
 
index daee48c86305831f15db0b5b3ad533015e71ee4a..1f3f43953667cd9a4c837a092c94bbd46375119c 100644 (file)
@@ -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])
index 47b402102f3b78ea3a2aa77c66eb44987a05d040..6fcb0fc699e43ce2cdd2e5eb6fe859f5ed617379 100644 (file)
@@ -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()
index 39fd4a07f8160df1a10b8a23d237c03ac3e1a803..75dce82d31813b885b7cbffff230c874956cb6a4 100644 (file)
 
 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:
 
index 7d64842994e8c93d64e51c0b74fc6b423a8a889a..6baac699e8f27c06dfed902b79845a034825646f 100644 (file)
@@ -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 {
index 8353483ebf243da3f06d91a1826855b19cde2cfe..86b41fcb256d880b8ad04d1982dc3cb09f611a00 100644 (file)
@@ -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