about summary refs log tree commit diff
path: root/src/rt/rust_crate_cache.cpp
diff options
context:
space:
mode:
authorGraydon Hoare <graydon@mozilla.com>2010-06-23 21:03:09 -0700
committerGraydon Hoare <graydon@mozilla.com>2010-06-23 21:03:09 -0700
commitd6b7c96c3eb29b9244ece0c046d3f372ff432d04 (patch)
treeb425187e232966063ffc2f0d14c04a55d8f004ef /src/rt/rust_crate_cache.cpp
parentc01efc669f09508b55eced32d3c88702578a7c3e (diff)
downloadrust-d6b7c96c3eb29b9244ece0c046d3f372ff432d04.tar.gz
rust-d6b7c96c3eb29b9244ece0c046d3f372ff432d04.zip
Populate tree.
Diffstat (limited to 'src/rt/rust_crate_cache.cpp')
-rw-r--r--src/rt/rust_crate_cache.cpp306
1 files changed, 306 insertions, 0 deletions
diff --git a/src/rt/rust_crate_cache.cpp b/src/rt/rust_crate_cache.cpp
new file mode 100644
index 00000000000..fa10b91b97f
--- /dev/null
+++ b/src/rt/rust_crate_cache.cpp
@@ -0,0 +1,306 @@
+
+#include "rust_internal.h"
+
+rust_crate_cache::lib::lib(rust_dom *dom, char const *name)
+    : handle(0),
+      dom(dom)
+{
+#if defined(__WIN32__)
+    handle = (uintptr_t)LoadLibrary(_T(name));
+#else
+    handle = (uintptr_t)dlopen(name, RTLD_LOCAL|RTLD_LAZY);
+#endif
+    dom->log(rust_log::CACHE, "loaded library '%s' as 0x%"  PRIxPTR,
+             name, handle);
+}
+
+rust_crate_cache::lib::~lib() {
+    dom->log(rust_log::CACHE, "~rust_crate_cache::lib(0x%" PRIxPTR ")",
+             handle);
+    if (handle) {
+#if defined(__WIN32__)
+        FreeLibrary((HMODULE)handle);
+#else
+        dlclose((void*)handle);
+#endif
+    }
+}
+
+uintptr_t
+rust_crate_cache::lib::get_handle() {
+    return handle;
+}
+
+
+
+rust_crate_cache::c_sym::c_sym(rust_dom *dom, lib *library, char const *name)
+    : val(0),
+      library(library),
+      dom(dom)
+{
+    library->ref();
+    uintptr_t handle = library->get_handle();
+    if (handle) {
+#if defined(__WIN32__)
+        val = (uintptr_t)GetProcAddress((HMODULE)handle, _T(name));
+#else
+        val = (uintptr_t)dlsym((void*)handle, name);
+#endif
+        dom->log(rust_log::CACHE, "resolved symbol '%s' to 0x%"  PRIxPTR,
+                 name, val);
+    } else {
+        dom->log(rust_log::CACHE, "unresolved symbol '%s', null lib handle",
+                 name);
+    }
+}
+
+rust_crate_cache::c_sym::~c_sym() {
+    dom->log(rust_log::CACHE,
+            "~rust_crate_cache::c_sym(0x%" PRIxPTR ")", val);
+    library->deref();
+}
+
+uintptr_t
+rust_crate_cache::c_sym::get_val() {
+    return val;
+}
+
+
+
+rust_crate_cache::rust_sym::rust_sym(rust_dom *dom,
+                                     rust_crate const *curr_crate,
+                                     c_sym *crate_sym,
+                                     char const **path)
+    : val(0),
+      crate_sym(crate_sym),
+      dom(dom)
+{
+    crate_sym->ref();
+    typedef rust_crate_reader::die die;
+    rust_crate const *crate = (rust_crate*)crate_sym->get_val();
+    if (!crate) {
+        dom->log(rust_log::CACHE,
+                 "failed to resolve symbol, null crate symbol");
+        return;
+    }
+    rust_crate_reader rdr(dom, crate);
+    bool found_root = false;
+    bool found_leaf = false;
+    for (die d = rdr.dies.first_die();
+         !(found_root || d.is_null());
+         d = d.next_sibling()) {
+
+        die t1 = d;
+        die t2 = d;
+        for (char const **c = crate_rel(curr_crate, path);
+             (*c
+              && !t1.is_null()
+              && t1.find_child_by_name(crate_rel(curr_crate, *c), t2));
+             ++c, t1=t2) {
+            dom->log(rust_log::DWARF|rust_log::CACHE,
+                    "matched die <0x%"  PRIxPTR
+                    ">, child '%s' = die<0x%" PRIxPTR ">",
+                    t1.off, crate_rel(curr_crate, *c), t2.off);
+            found_root = found_root || true;
+            if (!*(c+1) && t2.find_num_attr(DW_AT_low_pc, val)) {
+                dom->log(rust_log::DWARF|rust_log::CACHE,
+                         "found relative address: 0x%"  PRIxPTR, val);
+                dom->log(rust_log::DWARF|rust_log::CACHE,
+                         "plus image-base 0x%"  PRIxPTR,
+                         crate->get_image_base());
+                val += crate->get_image_base();
+                found_leaf = true;
+                break;
+            }
+        }
+        if (found_root || found_leaf)
+            break;
+    }
+    if (found_leaf) {
+        dom->log(rust_log::CACHE, "resolved symbol to 0x%"  PRIxPTR, val);
+    } else {
+        dom->log(rust_log::CACHE, "failed to resolve symbol");
+    }
+}
+
+rust_crate_cache::rust_sym::~rust_sym() {
+    dom->log(rust_log::CACHE,
+             "~rust_crate_cache::rust_sym(0x%" PRIxPTR ")", val);
+    crate_sym->deref();
+}
+
+uintptr_t
+rust_crate_cache::rust_sym::get_val() {
+    return val;
+}
+
+
+
+rust_crate_cache::lib *
+rust_crate_cache::get_lib(size_t n, char const *name)
+{
+    I(dom, n < crate->n_libs);
+    lib *library = libs[n];
+    if (!library) {
+        library = new (dom) lib(dom, name);
+        libs[n] = library;
+    }
+    return library;
+}
+
+rust_crate_cache::c_sym *
+rust_crate_cache::get_c_sym(size_t n, lib *library, char const *name)
+{
+    I(dom, n < crate->n_c_syms);
+    c_sym *sym = c_syms[n];
+    dom->log(rust_log::CACHE, "cached C symbol %s = 0x%" PRIxPTR, name, sym);
+    if (!sym) {
+        sym = new (dom) c_sym(dom, library, name);
+        c_syms[n] = sym;
+    }
+    return sym;
+}
+
+rust_crate_cache::rust_sym *
+rust_crate_cache::get_rust_sym(size_t n,
+                               rust_dom *dom,
+                               rust_crate const *curr_crate,
+                               c_sym *crate_sym,
+                               char const **path)
+{
+    I(dom, n < crate->n_rust_syms);
+    rust_sym *sym = rust_syms[n];
+    if (!sym) {
+        sym = new (dom) rust_sym(dom, curr_crate, crate_sym, path);
+        rust_syms[n] = sym;
+    }
+    return sym;
+}
+
+static inline void
+adjust_disp(uintptr_t &disp, const void *oldp, const void *newp)
+{
+    if (disp) {
+        disp += (uintptr_t)oldp;
+        disp -= (uintptr_t)newp;
+    }
+}
+
+type_desc *
+rust_crate_cache::get_type_desc(size_t size,
+                                size_t align,
+                                size_t n_descs,
+                                type_desc const **descs)
+{
+    I(dom, n_descs > 1);
+    type_desc *td = NULL;
+    size_t keysz = n_descs * sizeof(type_desc*);
+    HASH_FIND(hh, this->type_descs, descs, keysz, td);
+    if (td) {
+        dom->log(rust_log::CACHE, "rust_crate_cache::get_type_desc hit");
+        return td;
+    }
+    dom->log(rust_log::CACHE, "rust_crate_cache::get_type_desc miss");
+    td = (type_desc*) dom->malloc(sizeof(type_desc) + keysz);
+    if (!td)
+        return NULL;
+    // By convention, desc 0 is the root descriptor.
+    // but we ignore the size and alignment of it and use the
+    // passed-in, computed values.
+    memcpy(td, descs[0], sizeof(type_desc));
+    td->first_param = &td->descs[1];
+    td->size = size;
+    td->align = align;
+    for (size_t i = 0; i < n_descs; ++i) {
+        dom->log(rust_log::CACHE,
+                 "rust_crate_cache::descs[%" PRIdPTR "] = 0x%" PRIxPTR,
+                 i, descs[i]);
+        td->descs[i] = descs[i];
+    }
+    adjust_disp(td->copy_glue_off, descs[0], td);
+    adjust_disp(td->drop_glue_off, descs[0], td);
+    adjust_disp(td->free_glue_off, descs[0], td);
+    adjust_disp(td->mark_glue_off, descs[0], td);
+    adjust_disp(td->obj_drop_glue_off, descs[0], td);
+    HASH_ADD(hh, this->type_descs, descs, keysz, td);
+    return td;
+}
+
+rust_crate_cache::rust_crate_cache(rust_dom *dom,
+                                   rust_crate const *crate)
+    : rust_syms((rust_sym**)
+                dom->calloc(sizeof(rust_sym*) * crate->n_rust_syms)),
+      c_syms((c_sym**) dom->calloc(sizeof(c_sym*) * crate->n_c_syms)),
+      libs((lib**) dom->calloc(sizeof(lib*) * crate->n_libs)),
+      type_descs(NULL),
+      crate(crate),
+      dom(dom),
+      idx(0)
+{
+    I(dom, rust_syms);
+    I(dom, c_syms);
+    I(dom, libs);
+}
+
+void
+rust_crate_cache::flush() {
+    dom->log(rust_log::CACHE, "rust_crate_cache::flush()");
+    for (size_t i = 0; i < crate->n_rust_syms; ++i) {
+        rust_sym *s = rust_syms[i];
+        if (s) {
+            dom->log(rust_log::CACHE,
+                     "rust_crate_cache::flush() deref rust_sym %"
+                     PRIdPTR " (rc=%" PRIdPTR ")", i, s->refcnt);
+            s->deref();
+        }
+        rust_syms[i] = NULL;
+    }
+
+    for (size_t i = 0; i < crate->n_c_syms; ++i) {
+        c_sym *s = c_syms[i];
+        if (s) {
+            dom->log(rust_log::CACHE,
+                     "rust_crate_cache::flush() deref c_sym %"
+                     PRIdPTR " (rc=%" PRIdPTR ")", i, s->refcnt);
+            s->deref();
+        }
+        c_syms[i] = NULL;
+    }
+
+    for (size_t i = 0; i < crate->n_libs; ++i) {
+        lib *l = libs[i];
+        if (l) {
+            dom->log(rust_log::CACHE, "rust_crate_cache::flush() deref lib %"
+                     PRIdPTR " (rc=%" PRIdPTR ")", i, l->refcnt);
+            l->deref();
+        }
+        libs[i] = NULL;
+    }
+
+    while (type_descs) {
+        type_desc *d = type_descs;
+        HASH_DEL(type_descs, d);
+        dom->log(rust_log::MEM,
+                 "rust_crate_cache::flush() tydesc %" PRIxPTR, d);
+        dom->free(d);
+    }
+}
+
+rust_crate_cache::~rust_crate_cache()
+{
+    flush();
+    dom->free(rust_syms);
+    dom->free(c_syms);
+    dom->free(libs);
+}
+
+//
+// Local Variables:
+// mode: C++
+// fill-column: 78;
+// indent-tabs-mode: nil
+// c-basic-offset: 4
+// buffer-file-coding-system: utf-8-unix
+// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
+// End:
+//