From 787f20a2550318a65bff6d69599afde562949a8a Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Sun, 15 Sep 2013 21:41:02 +0200 Subject: [PATCH 1/5] Use slice representation for child crate maps --- src/librustc/middle/trans/base.rs | 22 ++- src/libstd/rt/crate_map.rs | 232 ++++++++++++++++-------------- src/libstd/rt/logging.rs | 19 ++- 3 files changed, 152 insertions(+), 121 deletions(-) diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 2c0497283c19c..e39a7b74de030 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -2949,6 +2949,7 @@ pub fn create_module_map(ccx: &mut CrateContext) -> ValueRef { pub fn decl_crate_map(sess: session::Session, mapmeta: LinkMeta, llmod: ModuleRef) -> ValueRef { + let targ_cfg = sess.targ_cfg; let int_type = Type::int(targ_cfg.arch); let mut n_subcrates = 1; @@ -2959,9 +2960,10 @@ pub fn decl_crate_map(sess: session::Session, mapmeta: LinkMeta, } else { ~"toplevel" }; + let sym_name = ~"_rust_crate_map_" + mapname; - let arrtype = Type::array(&int_type, n_subcrates as u64); - let maptype = Type::struct_([Type::i32(), int_type, arrtype], false); + let vectype = Type::struct_([int_type, int_type], false); + let maptype = Type::struct_([Type::i32(), int_type, vectype], false); let map = do sym_name.with_c_str |buf| { unsafe { llvm::LLVMAddGlobal(llmod, maptype.to_ref(), buf) @@ -2996,14 +2998,24 @@ pub fn fill_crate_map(ccx: &mut CrateContext, map: ValueRef) { subcrates.push(p2i(ccx, cr)); i += 1; } - subcrates.push(C_int(ccx, 0)); - unsafe { + let maptype = Type::array(&ccx.int_type, subcrates.len() as u64); + let vec_elements = do "_crate_map_child_vectors".with_c_str |buf| { + llvm::LLVMAddGlobal(ccx.llmod, maptype.to_ref(), buf) + }; + lib::llvm::SetLinkage(vec_elements, lib::llvm::InternalLinkage); + + llvm::LLVMSetInitializer(vec_elements, C_array(ccx.int_type, subcrates)); let mod_map = create_module_map(ccx); + llvm::LLVMSetInitializer(map, C_struct( [C_i32(1), p2i(ccx, mod_map), - C_array(ccx.int_type, subcrates)])); + C_struct( + [p2i(ccx, vec_elements), + C_int(ccx, (subcrates.len() * 8) as int) + ]) + ])); } } diff --git a/src/libstd/rt/crate_map.rs b/src/libstd/rt/crate_map.rs index 2844cc81892dd..e9ee0709d0132 100644 --- a/src/libstd/rt/crate_map.rs +++ b/src/libstd/rt/crate_map.rs @@ -8,13 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - -use libc::c_char; -use ptr; -use ptr::RawPtr; -use vec; -use hashmap::HashSet; +use cast::transmute; use container::MutableSet; +use hashmap::HashSet; +use libc::c_char; // Need to tell the linker on OS X to not barf on undefined symbols // and instead look them up at runtime, which we need to resolve @@ -34,14 +31,15 @@ pub struct ModEntry { name: *c_char, log_level: *mut u32 } + struct CrateMapV0 { - entries: *ModEntry, - children: [*CrateMap, ..1] + entries: &static [ModEntry], + children: &'static [&'static CrateMap] } struct CrateMap { version: i32, - entries: *ModEntry, + entries: &static [ModEntry], /// a dynamically sized struct, where all pointers to children are listed adjacent /// to the struct, terminated with NULL children: [*CrateMap, ..1] @@ -71,153 +69,175 @@ pub fn get_crate_map() -> *CrateMap { sym as *CrateMap } -unsafe fn version(crate_map: *CrateMap) -> i32 { - match (*crate_map).version { +fn version(crate_map: &'static CrateMap) -> i32 { + match crate_map.version { 1 => return 1, _ => return 0 } } -unsafe fn entries(crate_map: *CrateMap) -> *ModEntry { +#[cfg(not(stage0))] +fn entries(crate_map: &'static CrateMap) -> *ModEntry { match version(crate_map) { 0 => { - let v0 = crate_map as (*CrateMapV0); - return (*v0).entries; + unsafe { + let v0: &'static CrateMapV0 = transmute(crate_map); + return v0.entries; + } } 1 => return (*crate_map).entries, _ => fail2!("Unknown crate map version!") } } -unsafe fn iterator(crate_map: *CrateMap) -> **CrateMap { +#[cfg(not(stage0))] +fn iterator(crate_map: &'static CrateMap) -> &'static [&'static CrateMap] { match version(crate_map) { 0 => { - let v0 = crate_map as (*CrateMapV0); - return vec::raw::to_ptr((*v0).children); + unsafe { + let v0: &'static CrateMapV0 = transmute(crate_map); + return v0.children; + } } 1 => return vec::raw::to_ptr((*crate_map).children), _ => fail2!("Unknown crate map version!") } } -unsafe fn iter_module_map(mod_entries: *ModEntry, f: &fn(*mut ModEntry)) { +fn iter_module_map(mod_entries: *ModEntry, f: &fn(&mut ModEntry)) { let mut curr = mod_entries; - while !(*curr).name.is_null() { - f(curr as *mut ModEntry); - curr = curr.offset(1); + unsafe { + while !(*curr).name.is_null() { + f(transmute(curr)); + curr = curr.offset(1); + } } } -unsafe fn do_iter_crate_map(crate_map: *CrateMap, f: &fn(*mut ModEntry), + + +#[cfg(not(stage0))] +fn do_iter_crate_map(crate_map: &'static CrateMap, f: &fn(&mut ModEntry), visited: &mut HashSet<*CrateMap>) { - if visited.insert(crate_map) { - iter_module_map(entries(crate_map), |x| f(x)); + if visited.insert(crate_map as *CrateMap) { + iter_module_map(crate_map.entries, |x| f(x)); let child_crates = iterator(crate_map); - do ptr::array_each(child_crates) |child| { - do_iter_crate_map(child, |x| f(x), visited); + + let mut i = 0; + while i < child_crates.len() { + do_iter_crate_map(child_crates[i], |x| f(x), visited); + i = i + 1; } } } +#[cfg(stage0)] /// Iterates recursively over `crate_map` and all child crate maps -pub unsafe fn iter_crate_map(crate_map: *CrateMap, f: &fn(*mut ModEntry)) { +pub fn iter_crate_map(crate_map: *u8, f: &fn(&mut ModEntry)) { +} + +#[cfg(not(stage0))] +/// Iterates recursively over `crate_map` and all child crate maps +pub fn iter_crate_map(crate_map: &'static CrateMap, f: &fn(&mut ModEntry)) { // XXX: use random numbers as keys from the OS-level RNG when there is a nice // way to do this let mut v: HashSet<*CrateMap> = HashSet::with_capacity_and_keys(0, 0, 32); - do_iter_crate_map(crate_map, f, &mut v); -} - -#[test] -fn iter_crate_map_duplicates() { - use c_str::ToCStr; - use cast::transmute; - - struct CrateMapT3 { - version: i32, - entries: *ModEntry, - children: [*CrateMap, ..3] - } - unsafe { - let mod_name1 = "c::m1".to_c_str(); - let mut level3: u32 = 3; - - let entries: ~[ModEntry] = ~[ - ModEntry { name: mod_name1.with_ref(|buf| buf), log_level: &mut level3}, - ModEntry { name: ptr::null(), log_level: ptr::mut_null()} - ]; - let child_crate = CrateMap { - version: 1, - entries: vec::raw::to_ptr(entries), - children: [ptr::null()] - }; - - let root_crate = CrateMapT3 { - version: 1, - entries: vec::raw::to_ptr([ModEntry { name: ptr::null(), log_level: ptr::mut_null()}]), - children: [&child_crate as *CrateMap, &child_crate as *CrateMap, ptr::null()] - }; - - let mut cnt = 0; - do iter_crate_map(transmute(&root_crate)) |entry| { - assert!(*(*entry).log_level == 3); - cnt += 1; - } - assert!(cnt == 1); + do_iter_crate_map(transmute(crate_map), f, &mut v); } } -#[test] -fn iter_crate_map_follow_children() { +#[cfg(test)] +mod tests { use c_str::ToCStr; use cast::transmute; + use ptr; + use vec; + + use rt::crate_map::{ModEntry, iter_crate_map}; - struct CrateMapT2 { + struct CrateMap<'self> { version: i32, entries: *ModEntry, - children: [*CrateMap, ..2] + /// a dynamically sized struct, where all pointers to children are listed adjacent + /// to the struct, terminated with NULL + children: &'self [&'self CrateMap<'self>] } - unsafe { - let mod_name1 = "c::m1".to_c_str(); - let mod_name2 = "c::m2".to_c_str(); - let mut level2: u32 = 2; - let mut level3: u32 = 3; - let child_crate2 = CrateMap { - version: 1, - entries: vec::raw::to_ptr([ - ModEntry { name: mod_name1.with_ref(|buf| buf), log_level: &mut level2}, - ModEntry { name: mod_name2.with_ref(|buf| buf), log_level: &mut level3}, - ModEntry { name: ptr::null(), log_level: ptr::mut_null()} - ]), - children: [ptr::null()] - }; + #[test] + fn iter_crate_map_duplicates() { + unsafe { + let mod_name1 = "c::m1".to_c_str(); + let mut level3: u32 = 3; - let child_crate1 = CrateMapT2 { - version: 1, - entries: vec::raw::to_ptr([ - ModEntry { name: "t::f1".with_c_str(|buf| buf), log_level: &mut 1}, + let entries: ~[ModEntry] = ~[ + ModEntry { name: mod_name1.with_ref(|buf| buf), log_level: &mut level3}, ModEntry { name: ptr::null(), log_level: ptr::mut_null()} - ]), - children: [&child_crate2 as *CrateMap, ptr::null()] - }; - - let child_crate1_ptr: *CrateMap = transmute(&child_crate1); - let root_crate = CrateMapT2 { - version: 1, - entries: vec::raw::to_ptr([ - ModEntry { name: "t::f1".with_c_str(|buf| buf), log_level: &mut 0}, - ModEntry { name: ptr::null(), log_level: ptr::mut_null()} - ]), - children: [child_crate1_ptr, ptr::null()] - }; + ]; + + let child_crate = CrateMap { + version: 1, + entries: vec::raw::to_ptr(entries), + children: [] + }; + + let root_crate = CrateMap { + version: 1, + entries: vec::raw::to_ptr([ModEntry { name: ptr::null(), log_level: ptr::mut_null()}]), + children: [&child_crate, &child_crate] + }; + + let mut cnt = 0; + do iter_crate_map(transmute(&root_crate)) |entry| { + assert!(*entry.log_level == 3); + cnt += 1; + } + assert!(cnt == 1); + } + } - let mut cnt = 0; - do iter_crate_map(transmute(&root_crate)) |entry| { - assert!(*(*entry).log_level == cnt); - cnt += 1; + #[test] + fn iter_crate_map_follow_children() { + unsafe { + let mod_name1 = "c::m1".to_c_str(); + let mod_name2 = "c::m2".to_c_str(); + let mut level2: u32 = 2; + let mut level3: u32 = 3; + let child_crate2 = CrateMap { + version: 1, + entries: vec::raw::to_ptr([ + ModEntry { name: mod_name1.with_ref(|buf| buf), log_level: &mut level2}, + ModEntry { name: mod_name2.with_ref(|buf| buf), log_level: &mut level3}, + ModEntry { name: ptr::null(), log_level: ptr::mut_null()} + ]), + children: [] + }; + + let child_crate1 = CrateMap { + version: 1, + entries: vec::raw::to_ptr([ + ModEntry { name: "t::f1".to_c_str().with_ref(|buf| buf), log_level: &mut 1}, + ModEntry { name: ptr::null(), log_level: ptr::mut_null()} + ]), + children: [&child_crate2] + }; + + let root_crate = CrateMap { + version: 1, + entries: vec::raw::to_ptr([ + ModEntry { name: "t::f1".to_c_str().with_ref(|buf| buf), log_level: &mut 0}, + ModEntry { name: ptr::null(), log_level: ptr::mut_null()} + ]), + children: [&child_crate1] + }; + + let mut cnt = 0; + do iter_crate_map(transmute(&root_crate)) |entry| { + assert!(*entry.log_level == cnt); + cnt += 1; + } + assert!(cnt == 4); } - assert!(cnt == 4); } } diff --git a/src/libstd/rt/logging.rs b/src/libstd/rt/logging.rs index 299aa1175a74c..0903171f1c15d 100644 --- a/src/libstd/rt/logging.rs +++ b/src/libstd/rt/logging.rs @@ -20,6 +20,7 @@ use str::StrSlice; use str::raw::from_c_str; use u32; use vec::ImmutableVector; +use send_str::{SendStr, SendStrOwned, SendStrStatic}; use cast::transmute; struct LogDirective { @@ -110,7 +111,7 @@ fn parse_logging_spec(spec: ~str) -> ~[LogDirective]{ /// Set the log level of an entry in the crate map depending on the vector /// of log directives -fn update_entry(dirs: &[LogDirective], entry: *mut ModEntry) -> u32 { +fn update_entry(dirs: &[LogDirective], entry: &mut ModEntry) -> u32 { let mut new_lvl: u32 = DEFAULT_LOG_LEVEL; let mut longest_match = -1i; unsafe { @@ -123,7 +124,7 @@ fn update_entry(dirs: &[LogDirective], entry: *mut ModEntry) -> u32 { } } Some(ref dir_name) => { - let name = from_c_str((*entry).name); + let name = from_c_str(entry.name); let len = dir_name.len() as int; if name.starts_with(*dir_name) && len >= longest_match { @@ -133,7 +134,7 @@ fn update_entry(dirs: &[LogDirective], entry: *mut ModEntry) -> u32 { } }; } - *(*entry).log_level = new_lvl; + *entry.log_level = new_lvl; } if longest_match >= 0 { return 1; } else { return 0; } } @@ -147,8 +148,8 @@ fn update_log_settings(crate_map: *u8, settings: ~str) { if settings == ~"::help" || settings == ~"?" { dumb_println("\nCrate log map:\n"); unsafe { - do iter_crate_map(transmute(crate_map)) |entry: *mut ModEntry| { - dumb_println(" "+from_c_str((*entry).name)); + do iter_crate_map(crate_map) |entry| { + dumb_println(" "+from_c_str(entry.name)); } exit(1); } @@ -157,11 +158,9 @@ fn update_log_settings(crate_map: *u8, settings: ~str) { } let mut n_matches: u32 = 0; - unsafe { - do iter_crate_map(transmute(crate_map)) |entry: *mut ModEntry| { - let m = update_entry(dirs, entry); - n_matches += m; - } + do iter_crate_map(crate_map) |entry| { + let m = update_entry(dirs, entry); + n_matches += m; } if n_matches < (dirs.len() as u32) { From 9ef4463b2a7d2c41fbc1072779951b445c80f95b Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Fri, 27 Sep 2013 22:43:41 +0200 Subject: [PATCH 2/5] Use slice representation for module entries in CrateMap Relaxe lifetime of CrateMap as well. --- src/librustc/middle/trans/base.rs | 26 +++---- src/libstd/rt/crate_map.rs | 122 ++++++++++-------------------- src/libstd/rt/logging.rs | 12 ++- 3 files changed, 60 insertions(+), 100 deletions(-) diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index e39a7b74de030..98de8293b6086 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -2911,9 +2911,9 @@ pub fn decl_gc_metadata(ccx: &mut CrateContext, llmod_id: &str) { } } -pub fn create_module_map(ccx: &mut CrateContext) -> ValueRef { +pub fn create_module_map(ccx: &mut CrateContext) -> (ValueRef, uint) { let elttype = Type::struct_([ccx.int_type, ccx.int_type], false); - let maptype = Type::array(&elttype, (ccx.module_data.len() + 1) as u64); + let maptype = Type::array(&elttype, ccx.module_data.len() as u64); let map = do "_rust_mod_map".with_c_str |buf| { unsafe { llvm::LLVMAddGlobal(ccx.llmod, maptype.to_ref(), buf) @@ -2938,18 +2938,15 @@ pub fn create_module_map(ccx: &mut CrateContext) -> ValueRef { let elt = C_struct([s_ptr, v_ptr]); elts.push(elt); } - let term = C_struct([C_int(ccx, 0), C_int(ccx, 0)]); - elts.push(term); unsafe { llvm::LLVMSetInitializer(map, C_array(elttype, elts)); } - return map; + return (map, keys.len()); } pub fn decl_crate_map(sess: session::Session, mapmeta: LinkMeta, llmod: ModuleRef) -> ValueRef { - let targ_cfg = sess.targ_cfg; let int_type = Type::int(targ_cfg.arch); let mut n_subcrates = 1; @@ -2962,8 +2959,8 @@ pub fn decl_crate_map(sess: session::Session, mapmeta: LinkMeta, }; let sym_name = ~"_rust_crate_map_" + mapname; - let vectype = Type::struct_([int_type, int_type], false); - let maptype = Type::struct_([Type::i32(), int_type, vectype], false); + let slicetype = Type::struct_([int_type, int_type], false); + let maptype = Type::struct_([Type::i32(), slicetype, slicetype], false); let map = do sym_name.with_c_str |buf| { unsafe { llvm::LLVMAddGlobal(llmod, maptype.to_ref(), buf) @@ -3006,14 +3003,17 @@ pub fn fill_crate_map(ccx: &mut CrateContext, map: ValueRef) { lib::llvm::SetLinkage(vec_elements, lib::llvm::InternalLinkage); llvm::LLVMSetInitializer(vec_elements, C_array(ccx.int_type, subcrates)); - let mod_map = create_module_map(ccx); + let (mod_map, mod_count) = create_module_map(ccx); llvm::LLVMSetInitializer(map, C_struct( [C_i32(1), - p2i(ccx, mod_map), - C_struct( - [p2i(ccx, vec_elements), - C_int(ccx, (subcrates.len() * 8) as int) + C_struct([ + p2i(ccx, mod_map), + C_int(ccx, (mod_count * 16) as int) + ]), + C_struct([ + p2i(ccx, vec_elements), + C_int(ccx, (subcrates.len() * 8) as int) ]) ])); } diff --git a/src/libstd/rt/crate_map.rs b/src/libstd/rt/crate_map.rs index e9ee0709d0132..499516bb4fd37 100644 --- a/src/libstd/rt/crate_map.rs +++ b/src/libstd/rt/crate_map.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use cast::transmute; +#[cfg(not(stage0))] use cast::transmute; use container::MutableSet; use hashmap::HashSet; use libc::c_char; +use option::{Some, None}; +use vec::ImmutableVector; // Need to tell the linker on OS X to not barf on undefined symbols // and instead look them up at runtime, which we need to resolve @@ -24,7 +26,7 @@ extern {} extern { #[weak_linkage] #[link_name = "_rust_crate_map_toplevel"] - static CRATE_MAP: CrateMap; + static CRATE_MAP: CrateMap<'static>; } pub struct ModEntry { @@ -32,28 +34,28 @@ pub struct ModEntry { log_level: *mut u32 } -struct CrateMapV0 { - entries: &static [ModEntry], - children: &'static [&'static CrateMap] +pub struct CrateMapV0<'self> { + entries: &'self [ModEntry], + children: &'self [&'self CrateMap<'self>] } -struct CrateMap { +pub struct CrateMap<'self> { version: i32, - entries: &static [ModEntry], + entries: &'self [ModEntry], /// a dynamically sized struct, where all pointers to children are listed adjacent /// to the struct, terminated with NULL - children: [*CrateMap, ..1] + children: &'self [&'self CrateMap<'self>] } #[cfg(not(windows))] -pub fn get_crate_map() -> *CrateMap { - &'static CRATE_MAP as *CrateMap +pub fn get_crate_map() -> &'static CrateMap<'static> { + &'static CRATE_MAP } #[cfg(windows)] #[fixed_stack_segment] #[inline(never)] -pub fn get_crate_map() -> *CrateMap { +pub fn get_crate_map() -> &'static CrateMap<'static> { use c_str::ToCStr; use unstable::dynamic_lib::dl; @@ -65,11 +67,10 @@ pub fn get_crate_map() -> *CrateMap { dl::close(module); sym }; - - sym as *CrateMap + sym } -fn version(crate_map: &'static CrateMap) -> i32 { +fn version(crate_map: &CrateMap) -> i32 { match crate_map.version { 1 => return 1, _ => return 0 @@ -77,12 +78,13 @@ fn version(crate_map: &'static CrateMap) -> i32 { } #[cfg(not(stage0))] -fn entries(crate_map: &'static CrateMap) -> *ModEntry { +fn get_entries_and_children<'a>(crate_map: &'a CrateMap<'a>) -> + (&'a [ModEntry], &'a [&'a CrateMap<'a>]) { match version(crate_map) { 0 => { unsafe { - let v0: &'static CrateMapV0 = transmute(crate_map); - return v0.entries; + let v0: &'a CrateMapV0<'a> = transmute(crate_map); + return (v0.entries, v0.children); } } 1 => return (*crate_map).entries, @@ -91,79 +93,43 @@ fn entries(crate_map: &'static CrateMap) -> *ModEntry { } #[cfg(not(stage0))] -fn iterator(crate_map: &'static CrateMap) -> &'static [&'static CrateMap] { - match version(crate_map) { - 0 => { - unsafe { - let v0: &'static CrateMapV0 = transmute(crate_map); - return v0.children; - } - } - 1 => return vec::raw::to_ptr((*crate_map).children), - _ => fail2!("Unknown crate map version!") - } -} - -fn iter_module_map(mod_entries: *ModEntry, f: &fn(&mut ModEntry)) { - let mut curr = mod_entries; - - unsafe { - while !(*curr).name.is_null() { - f(transmute(curr)); - curr = curr.offset(1); - } +fn iter_module_map(mod_entries: &[ModEntry], f: &fn(&ModEntry)) { + for entry in mod_entries.iter() { + f(entry); } } - - #[cfg(not(stage0))] -fn do_iter_crate_map(crate_map: &'static CrateMap, f: &fn(&mut ModEntry), - visited: &mut HashSet<*CrateMap>) { +fn do_iter_crate_map<'a>(crate_map: &'a CrateMap<'a>, f: &fn(&ModEntry), + visited: &mut HashSet<*CrateMap<'a>>) { if visited.insert(crate_map as *CrateMap) { - iter_module_map(crate_map.entries, |x| f(x)); - let child_crates = iterator(crate_map); - - let mut i = 0; - while i < child_crates.len() { - do_iter_crate_map(child_crates[i], |x| f(x), visited); - i = i + 1; + let (entries, children) = get_entries_and_children(crate_map); + iter_module_map(entries, |x| f(x)); + for child in children.iter() { + do_iter_crate_map(*child, |x| f(x), visited); } } } #[cfg(stage0)] /// Iterates recursively over `crate_map` and all child crate maps -pub fn iter_crate_map(crate_map: *u8, f: &fn(&mut ModEntry)) { +pub fn iter_crate_map<'a>(crate_map: &'a CrateMap<'a>, f: &fn(&ModEntry)) { } #[cfg(not(stage0))] /// Iterates recursively over `crate_map` and all child crate maps -pub fn iter_crate_map(crate_map: &'static CrateMap, f: &fn(&mut ModEntry)) { +pub fn iter_crate_map<'a>(crate_map: &'a CrateMap<'a>, f: &fn(&ModEntry)) { // XXX: use random numbers as keys from the OS-level RNG when there is a nice // way to do this - let mut v: HashSet<*CrateMap> = HashSet::with_capacity_and_keys(0, 0, 32); - unsafe { - do_iter_crate_map(transmute(crate_map), f, &mut v); - } + let mut v: HashSet<*CrateMap<'a>> = HashSet::with_capacity_and_keys(0, 0, 32); + do_iter_crate_map(crate_map, f, &mut v); } #[cfg(test)] mod tests { use c_str::ToCStr; use cast::transmute; - use ptr; - use vec; - - use rt::crate_map::{ModEntry, iter_crate_map}; - - struct CrateMap<'self> { - version: i32, - entries: *ModEntry, - /// a dynamically sized struct, where all pointers to children are listed adjacent - /// to the struct, terminated with NULL - children: &'self [&'self CrateMap<'self>] - } + use rt::crate_map::{CrateMap, ModEntry, iter_crate_map}; #[test] fn iter_crate_map_duplicates() { @@ -171,20 +137,19 @@ mod tests { let mod_name1 = "c::m1".to_c_str(); let mut level3: u32 = 3; - let entries: ~[ModEntry] = ~[ + let entries = [ ModEntry { name: mod_name1.with_ref(|buf| buf), log_level: &mut level3}, - ModEntry { name: ptr::null(), log_level: ptr::mut_null()} ]; let child_crate = CrateMap { version: 1, - entries: vec::raw::to_ptr(entries), + entries: entries, children: [] }; let root_crate = CrateMap { version: 1, - entries: vec::raw::to_ptr([ModEntry { name: ptr::null(), log_level: ptr::mut_null()}]), + entries: [], children: [&child_crate, &child_crate] }; @@ -206,29 +171,26 @@ mod tests { let mut level3: u32 = 3; let child_crate2 = CrateMap { version: 1, - entries: vec::raw::to_ptr([ + entries: [ ModEntry { name: mod_name1.with_ref(|buf| buf), log_level: &mut level2}, ModEntry { name: mod_name2.with_ref(|buf| buf), log_level: &mut level3}, - ModEntry { name: ptr::null(), log_level: ptr::mut_null()} - ]), + ], children: [] }; let child_crate1 = CrateMap { version: 1, - entries: vec::raw::to_ptr([ + entries: [ ModEntry { name: "t::f1".to_c_str().with_ref(|buf| buf), log_level: &mut 1}, - ModEntry { name: ptr::null(), log_level: ptr::mut_null()} - ]), + ], children: [&child_crate2] }; let root_crate = CrateMap { version: 1, - entries: vec::raw::to_ptr([ + entries: [ ModEntry { name: "t::f1".to_c_str().with_ref(|buf| buf), log_level: &mut 0}, - ModEntry { name: ptr::null(), log_level: ptr::mut_null()} - ]), + ], children: [&child_crate1] }; diff --git a/src/libstd/rt/logging.rs b/src/libstd/rt/logging.rs index 0903171f1c15d..8d85f72056e46 100644 --- a/src/libstd/rt/logging.rs +++ b/src/libstd/rt/logging.rs @@ -14,14 +14,12 @@ use libc::{uintptr_t, exit}; use option::{Some, None, Option}; use rt; use rt::util::dumb_println; -use rt::crate_map::{ModEntry, iter_crate_map}; -use rt::crate_map::get_crate_map; +use rt::crate_map::{ModEntry, CrateMap, iter_crate_map, get_crate_map}; use str::StrSlice; use str::raw::from_c_str; use u32; use vec::ImmutableVector; -use send_str::{SendStr, SendStrOwned, SendStrStatic}; -use cast::transmute; +#[cfg(test)] use cast::transmute; struct LogDirective { name: Option<~str>, @@ -111,7 +109,7 @@ fn parse_logging_spec(spec: ~str) -> ~[LogDirective]{ /// Set the log level of an entry in the crate map depending on the vector /// of log directives -fn update_entry(dirs: &[LogDirective], entry: &mut ModEntry) -> u32 { +fn update_entry(dirs: &[LogDirective], entry: &ModEntry) -> u32 { let mut new_lvl: u32 = DEFAULT_LOG_LEVEL; let mut longest_match = -1i; unsafe { @@ -142,7 +140,7 @@ fn update_entry(dirs: &[LogDirective], entry: &mut ModEntry) -> u32 { #[fixed_stack_segment] #[inline(never)] /// Set log level for every entry in crate_map according to the sepecification /// in settings -fn update_log_settings(crate_map: *u8, settings: ~str) { +fn update_log_settings(crate_map: &CrateMap, settings: ~str) { let mut dirs = ~[]; if settings.len() > 0 { if settings == ~"::help" || settings == ~"?" { @@ -206,7 +204,7 @@ impl rt::io::Writer for StdErrLogger { pub fn init() { use os; - let crate_map = get_crate_map() as *u8; + let crate_map = get_crate_map(); let log_spec = os::getenv("RUST_LOG"); match log_spec { From 5dd1145c9b5e4ee12d6ef6d5d87bcbe0941b174b Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Sun, 29 Sep 2013 14:23:58 +0200 Subject: [PATCH 3/5] Use &'self str instead of raw char pointer in ModEntry --- src/librustc/middle/trans/base.rs | 30 ++++---- src/libstd/rt/crate_map.rs | 114 ++++++++++++++---------------- src/libstd/rt/logging.rs | 112 ++++++++++++----------------- 3 files changed, 116 insertions(+), 140 deletions(-) diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 98de8293b6086..c7ae68ec446ec 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -54,7 +54,7 @@ use middle::trans::glue; use middle::trans::inline; use middle::trans::llrepr::LlvmRepr; use middle::trans::machine; -use middle::trans::machine::{llalign_of_min, llsize_of}; +use middle::trans::machine::{llalign_of_min, llsize_of, llsize_of_alloc}; use middle::trans::meth; use middle::trans::monomorphize; use middle::trans::tvec; @@ -2911,8 +2911,9 @@ pub fn decl_gc_metadata(ccx: &mut CrateContext, llmod_id: &str) { } } -pub fn create_module_map(ccx: &mut CrateContext) -> (ValueRef, uint) { - let elttype = Type::struct_([ccx.int_type, ccx.int_type], false); +pub fn create_module_map(ccx: &mut CrateContext) -> (ValueRef, uint, uint) { + let str_slice_type = Type::struct_([Type::i8p(), ccx.int_type], false); + let elttype = Type::struct_([str_slice_type, ccx.int_type], false); let maptype = Type::array(&elttype, ccx.module_data.len() as u64); let map = do "_rust_mod_map".with_c_str |buf| { unsafe { @@ -2931,17 +2932,18 @@ pub fn create_module_map(ccx: &mut CrateContext) -> (ValueRef, uint) { } for key in keys.iter() { - let val = *ccx.module_data.find_equiv(key).unwrap(); - let s_const = C_cstr(ccx, *key); - let s_ptr = p2i(ccx, s_const); - let v_ptr = p2i(ccx, val); - let elt = C_struct([s_ptr, v_ptr]); - elts.push(elt); + let val = *ccx.module_data.find_equiv(key).unwrap(); + let v_ptr = p2i(ccx, val); + let elt = C_struct([ + C_estr_slice(ccx, *key), + v_ptr + ]); + elts.push(elt); } unsafe { llvm::LLVMSetInitializer(map, C_array(elttype, elts)); } - return (map, keys.len()); + return (map, keys.len(), llsize_of_alloc(ccx, elttype)); } @@ -3003,17 +3005,19 @@ pub fn fill_crate_map(ccx: &mut CrateContext, map: ValueRef) { lib::llvm::SetLinkage(vec_elements, lib::llvm::InternalLinkage); llvm::LLVMSetInitializer(vec_elements, C_array(ccx.int_type, subcrates)); - let (mod_map, mod_count) = create_module_map(ccx); + let (mod_map, mod_count, mod_struct_size) = create_module_map(ccx); llvm::LLVMSetInitializer(map, C_struct( [C_i32(1), C_struct([ p2i(ccx, mod_map), - C_int(ccx, (mod_count * 16) as int) + // byte size of the module map array, an entry consists of two integers + C_int(ccx, ((mod_count * mod_struct_size) as int)) ]), C_struct([ p2i(ccx, vec_elements), - C_int(ccx, (subcrates.len() * 8) as int) + // byte size of the subcrates array, an entry consists of an integer + C_int(ccx, (subcrates.len() * llsize_of_alloc(ccx, ccx.int_type)) as int) ]) ])); } diff --git a/src/libstd/rt/crate_map.rs b/src/libstd/rt/crate_map.rs index 499516bb4fd37..3120d69d5dfdd 100644 --- a/src/libstd/rt/crate_map.rs +++ b/src/libstd/rt/crate_map.rs @@ -11,7 +11,6 @@ #[cfg(not(stage0))] use cast::transmute; use container::MutableSet; use hashmap::HashSet; -use libc::c_char; use option::{Some, None}; use vec::ImmutableVector; @@ -29,19 +28,19 @@ extern { static CRATE_MAP: CrateMap<'static>; } -pub struct ModEntry { - name: *c_char, +pub struct ModEntry<'self> { + name: &'self str, log_level: *mut u32 } pub struct CrateMapV0<'self> { - entries: &'self [ModEntry], + entries: &'self [ModEntry<'self>], children: &'self [&'self CrateMap<'self>] } pub struct CrateMap<'self> { version: i32, - entries: &'self [ModEntry], + entries: &'self [ModEntry<'self>], /// a dynamically sized struct, where all pointers to children are listed adjacent /// to the struct, terminated with NULL children: &'self [&'self CrateMap<'self>] @@ -79,7 +78,7 @@ fn version(crate_map: &CrateMap) -> i32 { #[cfg(not(stage0))] fn get_entries_and_children<'a>(crate_map: &'a CrateMap<'a>) -> - (&'a [ModEntry], &'a [&'a CrateMap<'a>]) { + (&'a [ModEntry<'a>], &'a [&'a CrateMap<'a>]) { match version(crate_map) { 0 => { unsafe { @@ -127,34 +126,31 @@ pub fn iter_crate_map<'a>(crate_map: &'a CrateMap<'a>, f: &fn(&ModEntry)) { #[cfg(test)] mod tests { - use c_str::ToCStr; - use cast::transmute; use rt::crate_map::{CrateMap, ModEntry, iter_crate_map}; #[test] fn iter_crate_map_duplicates() { + let mut level3: u32 = 3; + + let entries = [ + ModEntry { name: "c::m1", log_level: &mut level3}, + ]; + + let child_crate = CrateMap { + version: 1, + entries: entries, + children: [] + }; + + let root_crate = CrateMap { + version: 1, + entries: [], + children: [&child_crate, &child_crate] + }; + + let mut cnt = 0; unsafe { - let mod_name1 = "c::m1".to_c_str(); - let mut level3: u32 = 3; - - let entries = [ - ModEntry { name: mod_name1.with_ref(|buf| buf), log_level: &mut level3}, - ]; - - let child_crate = CrateMap { - version: 1, - entries: entries, - children: [] - }; - - let root_crate = CrateMap { - version: 1, - entries: [], - children: [&child_crate, &child_crate] - }; - - let mut cnt = 0; - do iter_crate_map(transmute(&root_crate)) |entry| { + do iter_crate_map(&root_crate) |entry| { assert!(*entry.log_level == 3); cnt += 1; } @@ -164,38 +160,36 @@ mod tests { #[test] fn iter_crate_map_follow_children() { + let mut level2: u32 = 2; + let mut level3: u32 = 3; + let child_crate2 = CrateMap { + version: 1, + entries: [ + ModEntry { name: "c::m1", log_level: &mut level2}, + ModEntry { name: "c::m2", log_level: &mut level3}, + ], + children: [] + }; + + let child_crate1 = CrateMap { + version: 1, + entries: [ + ModEntry { name: "t::f1", log_level: &mut 1}, + ], + children: [&child_crate2] + }; + + let root_crate = CrateMap { + version: 1, + entries: [ + ModEntry { name: "t::f2", log_level: &mut 0}, + ], + children: [&child_crate1] + }; + + let mut cnt = 0; unsafe { - let mod_name1 = "c::m1".to_c_str(); - let mod_name2 = "c::m2".to_c_str(); - let mut level2: u32 = 2; - let mut level3: u32 = 3; - let child_crate2 = CrateMap { - version: 1, - entries: [ - ModEntry { name: mod_name1.with_ref(|buf| buf), log_level: &mut level2}, - ModEntry { name: mod_name2.with_ref(|buf| buf), log_level: &mut level3}, - ], - children: [] - }; - - let child_crate1 = CrateMap { - version: 1, - entries: [ - ModEntry { name: "t::f1".to_c_str().with_ref(|buf| buf), log_level: &mut 1}, - ], - children: [&child_crate2] - }; - - let root_crate = CrateMap { - version: 1, - entries: [ - ModEntry { name: "t::f1".to_c_str().with_ref(|buf| buf), log_level: &mut 0}, - ], - children: [&child_crate1] - }; - - let mut cnt = 0; - do iter_crate_map(transmute(&root_crate)) |entry| { + do iter_crate_map(&root_crate) |entry| { assert!(*entry.log_level == cnt); cnt += 1; } diff --git a/src/libstd/rt/logging.rs b/src/libstd/rt/logging.rs index 8d85f72056e46..cf917d1c412c5 100644 --- a/src/libstd/rt/logging.rs +++ b/src/libstd/rt/logging.rs @@ -16,7 +16,6 @@ use rt; use rt::util::dumb_println; use rt::crate_map::{ModEntry, CrateMap, iter_crate_map, get_crate_map}; use str::StrSlice; -use str::raw::from_c_str; use u32; use vec::ImmutableVector; #[cfg(test)] use cast::transmute; @@ -112,28 +111,26 @@ fn parse_logging_spec(spec: ~str) -> ~[LogDirective]{ fn update_entry(dirs: &[LogDirective], entry: &ModEntry) -> u32 { let mut new_lvl: u32 = DEFAULT_LOG_LEVEL; let mut longest_match = -1i; - unsafe { - for dir in dirs.iter() { - match dir.name { - None => { - if longest_match == -1 { - longest_match = 0; - new_lvl = dir.level; - } + for dir in dirs.iter() { + match dir.name { + None => { + if longest_match == -1 { + longest_match = 0; + new_lvl = dir.level; } - Some(ref dir_name) => { - let name = from_c_str(entry.name); - let len = dir_name.len() as int; - if name.starts_with(*dir_name) && - len >= longest_match { - longest_match = len; - new_lvl = dir.level; - } + } + Some(ref dir_name) => { + let name = entry.name; + let len = dir_name.len() as int; + if name.starts_with(*dir_name) && + len >= longest_match { + longest_match = len; + new_lvl = dir.level; } - }; - } - *entry.log_level = new_lvl; + } + }; } + unsafe { *entry.log_level = new_lvl; } if longest_match >= 0 { return 1; } else { return 0; } } @@ -144,13 +141,11 @@ fn update_log_settings(crate_map: &CrateMap, settings: ~str) { let mut dirs = ~[]; if settings.len() > 0 { if settings == ~"::help" || settings == ~"?" { - dumb_println("\nCrate log map:\n"); - unsafe { - do iter_crate_map(crate_map) |entry| { - dumb_println(" "+from_c_str(entry.name)); - } - exit(1); + dumb_println("\nCrate log map:\n"); + do iter_crate_map(crate_map) |entry| { + dumb_println(" "+entry.name); } + unsafe { exit(1); } } dirs = parse_logging_spec(settings); } @@ -288,88 +283,71 @@ fn parse_logging_spec_global() { // Tests for update_entry #[test] fn update_entry_match_full_path() { - use c_str::ToCStr; let dirs = ~[LogDirective {name: Some(~"crate1::mod1"), level: 2 }, LogDirective {name: Some(~"crate2"), level: 3}]; let level = &mut 0; unsafe { - do "crate1::mod1".with_c_str |ptr| { - let entry= &ModEntry {name: ptr, log_level: level}; - let m = update_entry(dirs, transmute(entry)); - assert!(*entry.log_level == 2); - assert!(m == 1); - } + let entry= &ModEntry {name:"crate1::mod1", log_level: level}; + let m = update_entry(dirs, transmute(entry)); + assert!(*entry.log_level == 2); + assert!(m == 1); } } #[test] fn update_entry_no_match() { - use c_str::ToCStr; let dirs = ~[LogDirective {name: Some(~"crate1::mod1"), level: 2 }, LogDirective {name: Some(~"crate2"), level: 3}]; let level = &mut 0; unsafe { - do "crate3::mod1".with_c_str |ptr| { - let entry= &ModEntry {name: ptr, log_level: level}; - let m = update_entry(dirs, transmute(entry)); - assert!(*entry.log_level == DEFAULT_LOG_LEVEL); - assert!(m == 0); - } + let entry= &ModEntry {name: "crate3::mod1", log_level: level}; + let m = update_entry(dirs, transmute(entry)); + assert!(*entry.log_level == DEFAULT_LOG_LEVEL); + assert!(m == 0); } } #[test] fn update_entry_match_beginning() { - use c_str::ToCStr; let dirs = ~[LogDirective {name: Some(~"crate1::mod1"), level: 2 }, LogDirective {name: Some(~"crate2"), level: 3}]; let level = &mut 0; unsafe { - do "crate2::mod1".with_c_str |ptr| { - let entry= &ModEntry {name: ptr, log_level: level}; - let m = update_entry(dirs, transmute(entry)); - assert!(*entry.log_level == 3); - assert!(m == 1); - } + let entry= &ModEntry {name: "crate2::mod1", log_level: level}; + let m = update_entry(dirs, transmute(entry)); + assert!(*entry.log_level == 3); + assert!(m == 1); } } #[test] fn update_entry_match_beginning_longest_match() { - use c_str::ToCStr; let dirs = ~[LogDirective {name: Some(~"crate1::mod1"), level: 2 }, LogDirective {name: Some(~"crate2"), level: 3}, LogDirective {name: Some(~"crate2::mod"), level: 4}]; let level = &mut 0; unsafe { - do "crate2::mod1".with_c_str |ptr| { - let entry = &ModEntry {name: ptr, log_level: level}; - let m = update_entry(dirs, transmute(entry)); - assert!(*entry.log_level == 4); - assert!(m == 1); - } + let entry = &ModEntry {name: "crate2::mod1", log_level: level}; + let m = update_entry(dirs, transmute(entry)); + assert!(*entry.log_level == 4); + assert!(m == 1); } } #[test] fn update_entry_match_default() { - use c_str::ToCStr; let dirs = ~[LogDirective {name: Some(~"crate1::mod1"), level: 2 }, LogDirective {name: None, level: 3} ]; let level = &mut 0; unsafe { - do "crate1::mod1".with_c_str |ptr| { - let entry= &ModEntry {name: ptr, log_level: level}; - let m = update_entry(dirs, transmute(entry)); - assert!(*entry.log_level == 2); - assert!(m == 1); - } - do "crate2::mod2".with_c_str |ptr| { - let entry= &ModEntry {name: ptr, log_level: level}; - let m = update_entry(dirs, transmute(entry)); - assert!(*entry.log_level == 3); - assert!(m == 1); - } + let entry= &ModEntry {name: "crate1::mod1", log_level: level}; + let m = update_entry(dirs, transmute(entry)); + assert!(*entry.log_level == 2); + assert!(m == 1); + let entry= &ModEntry {name: "crate2::mod2", log_level: level}; + let m = update_entry(dirs, transmute(entry)); + assert!(*entry.log_level == 3); + assert!(m == 1); } } From b7b4f7a5e2982c8412fe71a9534f6f62435f9bc3 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Tue, 1 Oct 2013 23:53:56 +0200 Subject: [PATCH 4/5] Add code for older crate map versions, bumped crate map version number --- src/librustc/middle/trans/base.rs | 2 +- src/libstd/rt/crate_map.rs | 209 ++++++++++++++++++++++++------ 2 files changed, 172 insertions(+), 39 deletions(-) diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index c7ae68ec446ec..16ac802ee1571 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -3008,7 +3008,7 @@ pub fn fill_crate_map(ccx: &mut CrateContext, map: ValueRef) { let (mod_map, mod_count, mod_struct_size) = create_module_map(ccx); llvm::LLVMSetInitializer(map, C_struct( - [C_i32(1), + [C_i32(2), C_struct([ p2i(ccx, mod_map), // byte size of the module map array, an entry consists of two integers diff --git a/src/libstd/rt/crate_map.rs b/src/libstd/rt/crate_map.rs index 3120d69d5dfdd..ef1bfb1e5e9dc 100644 --- a/src/libstd/rt/crate_map.rs +++ b/src/libstd/rt/crate_map.rs @@ -8,12 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[cfg(not(stage0))] use cast::transmute; +//#[cfg(not(stage0))] use cast::transmute; use container::MutableSet; use hashmap::HashSet; use option::{Some, None}; use vec::ImmutableVector; +/// Imports for old crate map versions +use cast::transmute; +use libc::c_char; +use ptr; +use str::raw::from_c_str; +use vec; + // Need to tell the linker on OS X to not barf on undefined symbols // and instead look them up at runtime, which we need to resolve // the crate_map properly. @@ -28,14 +35,27 @@ extern { static CRATE_MAP: CrateMap<'static>; } -pub struct ModEntry<'self> { - name: &'self str, +/// structs for old crate map versions +pub struct ModEntryV0 { + name: *c_char, log_level: *mut u32 } +pub struct CrateMapV0 { + entries: *ModEntryV0, + children: [*CrateMapV0, ..1] +} -pub struct CrateMapV0<'self> { - entries: &'self [ModEntry<'self>], - children: &'self [&'self CrateMap<'self>] +pub struct CrateMapV1 { + version: i32, + entries: *ModEntryV0, + /// a dynamically sized struct, where all pointers to children are listed adjacent + /// to the struct, terminated with NULL + children: [*CrateMapV1, ..1] +} + +pub struct ModEntry<'self> { + name: &'self str, + log_level: *mut u32 } pub struct CrateMap<'self> { @@ -46,6 +66,8 @@ pub struct CrateMap<'self> { children: &'self [&'self CrateMap<'self>] } + + #[cfg(not(windows))] pub fn get_crate_map() -> &'static CrateMap<'static> { &'static CRATE_MAP @@ -71,51 +93,60 @@ pub fn get_crate_map() -> &'static CrateMap<'static> { fn version(crate_map: &CrateMap) -> i32 { match crate_map.version { + 2 => return 2, 1 => return 1, _ => return 0 } } -#[cfg(not(stage0))] -fn get_entries_and_children<'a>(crate_map: &'a CrateMap<'a>) -> - (&'a [ModEntry<'a>], &'a [&'a CrateMap<'a>]) { - match version(crate_map) { - 0 => { - unsafe { - let v0: &'a CrateMapV0<'a> = transmute(crate_map); - return (v0.entries, v0.children); - } - } - 1 => return (*crate_map).entries, - _ => fail2!("Unknown crate map version!") - } -} - -#[cfg(not(stage0))] fn iter_module_map(mod_entries: &[ModEntry], f: &fn(&ModEntry)) { for entry in mod_entries.iter() { f(entry); } } -#[cfg(not(stage0))] +unsafe fn iter_module_map_v0(entries: *ModEntryV0, f: &fn(&ModEntry)) { + let mut curr = entries; + while !(*curr).name.is_null() { + let mod_entry = ModEntry { name: from_c_str((*curr).name), log_level: (*curr).log_level }; + f(&mod_entry); + curr = curr.offset(1); + } +} + fn do_iter_crate_map<'a>(crate_map: &'a CrateMap<'a>, f: &fn(&ModEntry), visited: &mut HashSet<*CrateMap<'a>>) { if visited.insert(crate_map as *CrateMap) { - let (entries, children) = get_entries_and_children(crate_map); - iter_module_map(entries, |x| f(x)); - for child in children.iter() { - do_iter_crate_map(*child, |x| f(x), visited); + match version(crate_map) { + 2 => { + let (entries, children) = (crate_map.entries, crate_map.children); + iter_module_map(entries, |x| f(x)); + for child in children.iter() { + do_iter_crate_map(*child, |x| f(x), visited); + } + }, + /// code for old crate map versions + 1 => unsafe { + let v1: *CrateMapV1 = transmute(crate_map); + iter_module_map_v0((*v1).entries, |x| f(x)); + let children = vec::raw::to_ptr((*v1).children); + do ptr::array_each(children) |child| { + do_iter_crate_map(transmute(child), |x| f(x), visited); + } + }, + 0 => unsafe { + let v0: *CrateMapV0 = transmute(crate_map); + iter_module_map_v0((*v0).entries, |x| f(x)); + let children = vec::raw::to_ptr((*v0).children); + do ptr::array_each(children) |child| { + do_iter_crate_map(transmute(child), |x| f(x), visited); + } + }, + _ => fail2!("invalid crate map version") } } } -#[cfg(stage0)] -/// Iterates recursively over `crate_map` and all child crate maps -pub fn iter_crate_map<'a>(crate_map: &'a CrateMap<'a>, f: &fn(&ModEntry)) { -} - -#[cfg(not(stage0))] /// Iterates recursively over `crate_map` and all child crate maps pub fn iter_crate_map<'a>(crate_map: &'a CrateMap<'a>, f: &fn(&ModEntry)) { // XXX: use random numbers as keys from the OS-level RNG when there is a nice @@ -137,13 +168,13 @@ mod tests { ]; let child_crate = CrateMap { - version: 1, + version: 2, entries: entries, children: [] }; let root_crate = CrateMap { - version: 1, + version: 2, entries: [], children: [&child_crate, &child_crate] }; @@ -163,7 +194,7 @@ mod tests { let mut level2: u32 = 2; let mut level3: u32 = 3; let child_crate2 = CrateMap { - version: 1, + version: 2, entries: [ ModEntry { name: "c::m1", log_level: &mut level2}, ModEntry { name: "c::m2", log_level: &mut level3}, @@ -172,7 +203,7 @@ mod tests { }; let child_crate1 = CrateMap { - version: 1, + version: 2, entries: [ ModEntry { name: "t::f1", log_level: &mut 1}, ], @@ -180,7 +211,7 @@ mod tests { }; let root_crate = CrateMap { - version: 1, + version: 2, entries: [ ModEntry { name: "t::f2", log_level: &mut 0}, ], @@ -196,4 +227,106 @@ mod tests { assert!(cnt == 4); } } + + + /// Tests for old crate map versions + #[test] + fn iter_crate_map_duplicates_v1() { + use c_str::ToCStr; + use cast::transmute; + use ptr; + use rt::crate_map::{CrateMapV1, ModEntryV0, iter_crate_map}; + use vec; + + struct CrateMapT3 { + version: i32, + entries: *ModEntryV0, + children: [*CrateMapV1, ..3] + } + + unsafe { + let mod_name1 = "c::m1".to_c_str(); + let mut level3: u32 = 3; + + let entries: ~[ModEntryV0] = ~[ + ModEntryV0 { name: mod_name1.with_ref(|buf| buf), log_level: &mut level3}, + ModEntryV0 { name: ptr::null(), log_level: ptr::mut_null()} + ]; + let child_crate = CrateMapV1 { + version: 1, + entries: vec::raw::to_ptr(entries), + children: [ptr::null()] + }; + + let root_crate = CrateMapT3 { + version: 1, + entries: vec::raw::to_ptr([ModEntryV0 { name: ptr::null(), log_level: ptr::mut_null()}]), + children: [&child_crate as *CrateMapV1, &child_crate as *CrateMapV1, ptr::null()] + }; + + let mut cnt = 0; + do iter_crate_map(transmute(&root_crate)) |entry| { + assert!(*(*entry).log_level == 3); + cnt += 1; + } + assert!(cnt == 1); + } + } + + #[test] + fn iter_crate_map_follow_children_v1() { + use c_str::ToCStr; + use cast::transmute; + use ptr; + use rt::crate_map::{CrateMapV1, ModEntryV0, iter_crate_map}; + use vec; + + struct CrateMapT2 { + version: i32, + entries: *ModEntryV0, + children: [*CrateMapV1, ..2] + } + + unsafe { + let mod_name1 = "c::m1".to_c_str(); + let mod_name2 = "c::m2".to_c_str(); + let mut level2: u32 = 2; + let mut level3: u32 = 3; + let child_crate2 = CrateMapV1 { + version: 1, + entries: vec::raw::to_ptr([ + ModEntryV0 { name: mod_name1.with_ref(|buf| buf), log_level: &mut level2}, + ModEntryV0 { name: mod_name2.with_ref(|buf| buf), log_level: &mut level3}, + ModEntryV0 { name: ptr::null(), log_level: ptr::mut_null()} + ]), + children: [ptr::null()] + }; + + let child_crate1 = CrateMapT2 { + version: 1, + entries: vec::raw::to_ptr([ + ModEntryV0 { name: "t::f1".with_c_str(|buf| buf), log_level: &mut 1}, + ModEntryV0 { name: ptr::null(), log_level: ptr::mut_null()} + ]), + children: [&child_crate2 as *CrateMapV1, ptr::null()] + }; + + let child_crate1_ptr: *CrateMapV1 = transmute(&child_crate1); + let root_crate = CrateMapT2 { + version: 1, + entries: vec::raw::to_ptr([ + ModEntryV0 { name: "t::f1".with_c_str(|buf| buf), log_level: &mut 0}, + ModEntryV0 { name: ptr::null(), log_level: ptr::mut_null()} + ]), + children: [child_crate1_ptr, ptr::null()] + }; + + let mut cnt = 0; + do iter_crate_map(transmute(&root_crate)) |entry| { + assert!(*(*entry).log_level == cnt); + cnt += 1; + } + assert!(cnt == 4); + } + } } From 23176fc567086715aab062a24e2b68e1f54ce5ba Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Thu, 3 Oct 2013 10:13:13 +0200 Subject: [PATCH 5/5] get_crate_map returns an Option --- src/libstd/rt/crate_map.rs | 39 +++++++++++++++++++++++--------------- src/libstd/rt/logging.rs | 26 +++++++++++++++++-------- 2 files changed, 42 insertions(+), 23 deletions(-) diff --git a/src/libstd/rt/crate_map.rs b/src/libstd/rt/crate_map.rs index ef1bfb1e5e9dc..061c2e53c7c17 100644 --- a/src/libstd/rt/crate_map.rs +++ b/src/libstd/rt/crate_map.rs @@ -8,10 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//#[cfg(not(stage0))] use cast::transmute; use container::MutableSet; use hashmap::HashSet; -use option::{Some, None}; +use option::{Some, None, Option}; use vec::ImmutableVector; /// Imports for old crate map versions @@ -61,22 +60,23 @@ pub struct ModEntry<'self> { pub struct CrateMap<'self> { version: i32, entries: &'self [ModEntry<'self>], - /// a dynamically sized struct, where all pointers to children are listed adjacent - /// to the struct, terminated with NULL children: &'self [&'self CrateMap<'self>] } - - #[cfg(not(windows))] -pub fn get_crate_map() -> &'static CrateMap<'static> { - &'static CRATE_MAP +pub fn get_crate_map() -> Option<&'static CrateMap<'static>> { + let ptr: (*CrateMap) = &'static CRATE_MAP; + if ptr.is_null() { + return None; + } else { + return Some(&'static CRATE_MAP); + } } #[cfg(windows)] #[fixed_stack_segment] #[inline(never)] -pub fn get_crate_map() -> &'static CrateMap<'static> { +pub fn get_crate_map() -> Option<&'static CrateMap<'static>> { use c_str::ToCStr; use unstable::dynamic_lib::dl; @@ -88,7 +88,14 @@ pub fn get_crate_map() -> &'static CrateMap<'static> { dl::close(module); sym }; - sym + let ptr: (*CrateMap) = sym as *CrateMap; + if ptr.is_null() { + return None; + } else { + unsafe { + return Some(transmute(sym)); + } + } } fn version(crate_map: &CrateMap) -> i32 { @@ -106,9 +113,9 @@ fn iter_module_map(mod_entries: &[ModEntry], f: &fn(&ModEntry)) { } unsafe fn iter_module_map_v0(entries: *ModEntryV0, f: &fn(&ModEntry)) { - let mut curr = entries; + let mut curr = entries; while !(*curr).name.is_null() { - let mod_entry = ModEntry { name: from_c_str((*curr).name), log_level: (*curr).log_level }; + let mod_entry = ModEntry { name: from_c_str((*curr).name), log_level: (*curr).log_level }; f(&mod_entry); curr = curr.offset(1); } @@ -125,7 +132,7 @@ fn do_iter_crate_map<'a>(crate_map: &'a CrateMap<'a>, f: &fn(&ModEntry), do_iter_crate_map(*child, |x| f(x), visited); } }, - /// code for old crate map versions + // code for old crate map versions 1 => unsafe { let v1: *CrateMapV1 = transmute(crate_map); iter_module_map_v0((*v1).entries, |x| f(x)); @@ -142,7 +149,7 @@ fn do_iter_crate_map<'a>(crate_map: &'a CrateMap<'a>, f: &fn(&ModEntry), do_iter_crate_map(transmute(child), |x| f(x), visited); } }, - _ => fail2!("invalid crate map version") + _ => fail2!("invalid crate map version") } } } @@ -260,7 +267,9 @@ mod tests { let root_crate = CrateMapT3 { version: 1, - entries: vec::raw::to_ptr([ModEntryV0 { name: ptr::null(), log_level: ptr::mut_null()}]), + entries: vec::raw::to_ptr([ + ModEntryV0 { name: ptr::null(), log_level: ptr::mut_null()} + ]), children: [&child_crate as *CrateMapV1, &child_crate as *CrateMapV1, ptr::null()] }; diff --git a/src/libstd/rt/logging.rs b/src/libstd/rt/logging.rs index cf917d1c412c5..8b8e2762381c1 100644 --- a/src/libstd/rt/logging.rs +++ b/src/libstd/rt/logging.rs @@ -199,15 +199,25 @@ impl rt::io::Writer for StdErrLogger { pub fn init() { use os; - let crate_map = get_crate_map(); - let log_spec = os::getenv("RUST_LOG"); - match log_spec { - Some(spec) => { - update_log_settings(crate_map, spec); - } - None => { - update_log_settings(crate_map, ~""); + match get_crate_map() { + Some(crate_map) => { + match log_spec { + Some(spec) => { + update_log_settings(crate_map, spec); + } + None => { + update_log_settings(crate_map, ~""); + } + } + }, + _ => { + match log_spec { + Some(_) => { + dumb_println("warning: RUST_LOG set, but no crate map found."); + }, + None => {} + } } } }