Commit 71aefd55 authored by qinsoon's avatar qinsoon

Merge branch 'master' into gc-rewrite

parents 211e3976 0f303eca
......@@ -13,15 +13,12 @@
# limitations under the License.
set -e
if [ -z "$MU_ZEBU" ]
then
export MU_ZEBU=$PWD
fi
export MU_ZEBU=$(dirname $0)
export MU_LOG_LEVEL=none
export RUST_TEST_THREADS=1
export RUST_BACKTRACE=0
export PYTHONPATH="$MU_ZEBU/tests/test_jit/mu-client-pypy/:$MU_ZEBU/tests/test_jit/RPySOM/src"
export LD_LIBRARY_PATH="$MU_ZEBU/tests/test_jit/:$MU_ZEBU/tests/test_jit:$LD_LIBRARY_PATH"
export LD_LIBRARY_PATH="$MU_ZEBU/target/$ZEBU_BUILD:$MU_ZEBU/tests/test_jit/:$MU_ZEBU/tests/test_jit/emit/:$LD_LIBRARY_PATH"
export ZEBU_BUILD=release
rm -rf $MU_ZEBU/emit
......@@ -56,4 +53,7 @@ else
git -C ./RPySOM submodule update
fi
shopt -s extglob
pytest ./test_!(pypy).py -v --color=yes 2>&1 | tee $MU_ZEBU/pytest_out.txt
pytest ./test_!(pypy).py -v --color=yes 2>&1 | tee $MU_ZEBU/pytest_jit_out.txt
cd $MU_ZEBU/tests/test_muc
pytest ./test_*.py -v --color=yes 2>&1 | tee $MU_ZEBU/pytest_muc_out.txt
......@@ -3638,7 +3638,8 @@ use std::collections::HashMap;
pub fn emit_context_with_reloc(
vm: &VM,
symbols: HashMap<Address, MuName>,
fields: HashMap<Address, MuName>
fields: HashMap<Address, MuName>,
primordial_threadlocal: Option<Address>
) {
use std::path;
use std::io::prelude::*;
......@@ -3664,23 +3665,24 @@ pub fn emit_context_with_reloc(
// data
writeln!(file, ".data").unwrap();
// persist heap - we traverse the heap from globals
{
let primordial_threadlocal = {
use runtime::mm;
// persist globals
let global_locs_lock = vm.global_locations().read().unwrap();
let global_lock = vm.globals().read().unwrap();
// a map from address to ID
let global_addr_id_map = {
let mut map: LinkedHashMap<Address, MuID> = LinkedHashMap::new();
for (id, global_loc) in global_locs_lock.iter() {
map.insert(global_loc.to_address(), *id);
}
map
};
// get address of all globals so we can traverse heap from them
// dump heap from globals
let global_addrs: Vec<Address> =
global_locs_lock.values().map(|x| x.to_address()).collect();
debug!("going to dump these globals: {:?}", global_addrs);
......@@ -3789,6 +3791,11 @@ pub fn emit_context_with_reloc(
offset += POINTER_SIZE;
}
}
primordial_threadlocal.map(|a| relocatable_refs.get(&a).unwrap().clone())
};
{
let mut lock = vm.primordial_threadlocal.write().unwrap();
*lock = primordial_threadlocal;
}
// serialize vm
......@@ -3830,7 +3837,7 @@ fn write_obj_header(f: &mut File, obj: &ObjectEncode) {
}
pub fn emit_context(vm: &VM) {
emit_context_with_reloc(vm, hashmap!{}, hashmap!{});
emit_context_with_reloc(vm, hashmap!{}, hashmap!{}, None);
}
fn write_data_bytes(f: &mut File, from: Address, to: Address) {
......
......@@ -4161,7 +4161,8 @@ use std::collections::HashMap;
pub fn emit_context_with_reloc(
vm: &VM,
symbols: HashMap<Address, MuName>,
fields: HashMap<Address, MuName>
fields: HashMap<Address, MuName>,
primordial_threadlocal: Option<Address>
) {
// creates emit directy, and file
debug!("---Emit VM Context---");
......@@ -4188,7 +4189,7 @@ pub fn emit_context_with_reloc(
file.write("\t.data\n".as_bytes()).unwrap();
// persist heap - we traverse the heap from globals
{
let primordial_threadlocal = {
use runtime::mm;
let global_locs_lock = vm.global_locations().read().unwrap();
......@@ -4314,8 +4315,13 @@ pub fn emit_context_with_reloc(
offset += POINTER_SIZE;
}
}
}
primordial_threadlocal.map(|a| relocatable_refs.get(&a).unwrap().clone())
};
{
let mut lock = vm.primordial_threadlocal.write().unwrap();
*lock = primordial_threadlocal;
}
// serialize vm, and put it to boot image
// currently using rustc_serialize to persist vm as json string.
// Deserializing from this is extremely slow, we need to fix this. See Issue #41
......@@ -4346,7 +4352,7 @@ pub fn emit_context_with_reloc(
/// emit vm context for current session,
/// without consideration about relocation symbols/fields from the client
pub fn emit_context(vm: &VM) {
emit_context_with_reloc(vm, hashmap!{}, hashmap!{});
emit_context_with_reloc(vm, hashmap!{}, hashmap!{}, None);
}
/// writes header for a dumped object
......
......@@ -454,6 +454,43 @@ impl<'a> GraphColoring<'a> {
} else {
trace!("Coalescing disabled...");
}
trace!("Build freeze cost for each node...");
// we try to avoid freeze a node that is involved in many moves
for n in self.ig.nodes() {
// freeze_cost(n) = SUM ((spill_cost(src) + spill_cost(dst)) for m (mov src->dst)
// in movelist[n])
let closure = {
let mut ret = LinkedHashSet::new();
let mut worklist = LinkedHashSet::new();
worklist.insert(n);
while !worklist.is_empty() {
let n = worklist.pop_front().unwrap();
for m in self.get_movelist(n).iter() {
if !ret.contains(&m.from) {
ret.insert(m.from);
worklist.insert(m.from);
}
if !ret.contains(&m.to) {
ret.insert(m.to);
worklist.insert(m.to);
}
}
}
ret
};
let mut freeze_cost = 0f32;
for related_node in closure.iter() {
freeze_cost += self.ig.get_spill_cost(*related_node);
}
self.ig.set_freeze_cost(n, freeze_cost);
trace!(" {} closure: {:?}", n, closure);
trace!(" freeze cost = {}", freeze_cost);
}
}
fn make_work_list(&mut self) {
......@@ -836,13 +873,7 @@ impl<'a> GraphColoring<'a> {
let mut candidate = None;
let mut candidate_cost = f32::MAX;
for &n in self.worklist_freeze.iter() {
// freeze_cost(n) = SUM ((spill_cost(src) + spill_cost(dst)) for m (mov src->dst)
// in movelist[n])
let mut freeze_cost = 0f32;
for m in self.get_movelist(n).iter() {
freeze_cost += self.ig.get_spill_cost(m.from);
freeze_cost += self.ig.get_spill_cost(m.to);
}
let freeze_cost = self.ig.get_freeze_cost(n);
if freeze_cost < candidate_cost {
candidate = Some(n);
......
......@@ -39,7 +39,9 @@ pub struct Node {
/// temp register group (which machine register class we should assign)
group: backend::RegGroup,
/// cost to spill this temp
spill_cost: f32
spill_cost: f32,
/// cost to freeze this temp
freeze_cost: f32
}
impl fmt::Debug for Node {
......@@ -143,7 +145,8 @@ impl InterferenceGraph {
temp: reg_id,
color: None,
group: backend::RegGroup::get_from_ty(entry.ty()),
spill_cost: 0.0f32
spill_cost: 0.0f32,
freeze_cost: 0f32
};
self.nodes.insert(reg_id, node);
......@@ -162,7 +165,7 @@ impl InterferenceGraph {
fn spillcost_heuristic(ty: NodeType, loop_depth: usize) -> f32 {
const DEF_WEIGHT: f32 = 1f32;
const USE_WEIGHT: f32 = 1f32;
const COPY_WEIGHT: f32 = 0.5f32;
const COPY_WEIGHT: f32 = 2f32;
let loop_depth = loop_depth as i32;
......@@ -284,6 +287,16 @@ impl InterferenceGraph {
self.nodes.get(&reg).unwrap().spill_cost
}
/// sets the freeze cost of a node
pub fn set_freeze_cost(&mut self, reg: MuID, cost: f32) {
self.nodes.get_mut(&reg).unwrap().freeze_cost = cost;
}
/// gets the freeze cost of a node
pub fn get_freeze_cost(&self, reg: MuID) -> f32 {
self.nodes.get(&reg).unwrap().freeze_cost
}
/// are two nodes the same node?
fn is_same_node(&self, reg1: MuID, reg2: MuID) -> bool {
reg1 == reg2
......
......@@ -313,8 +313,13 @@ pub extern "C" fn mu_main(
args
};
// FIXME: currently assumes no user defined thread local - See Issue #48
thread::MuThread::new_thread_normal(stack, unsafe { Address::zero() }, args, vm.clone());
let threadlocal = vm.primordial_threadlocal
.read()
.unwrap()
.as_ref()
.map(|name| resolve_symbol(Arc::new(name.clone())))
.unwrap_or(unsafe { Address::zero() });
thread::MuThread::new_thread_normal(stack, threadlocal, args, vm.clone());
loop {
let thread = vm.pop_join_handle();
......
......@@ -123,6 +123,7 @@ pub struct VM {
/// a map from callsite address to CompiledCallsite
compiled_callsite_table: RwLock<HashMap<Address, CompiledCallsite>>, // 896
pub primordial_threadlocal: RwLock<Option<String>>,
/// Nnmber of callsites in the callsite tables
callsite_count: AtomicUsize,
......@@ -172,6 +173,7 @@ unsafe impl rodal::Dump for VM {
RwLock::new(rodal::EmptyHashMap::<Address, CompiledCallsite>::new());
dumper.dump_object_here(&compiled_callsite_table);
dumper.dump_object(&self.primordial_threadlocal);
dumper.dump_object(&self.callsite_count);
dumper.dump_padding(&self.pending_joins);
......@@ -248,6 +250,7 @@ impl<'a> VM {
gc_id_map: RwLock::new(HashMap::new()),
aot_pending_funcref_store: RwLock::new(HashMap::new()),
compiled_callsite_table: RwLock::new(HashMap::new()),
primordial_threadlocal: RwLock::new(None),
callsite_count: ATOMIC_USIZE_INIT,
pending_joins: Mutex::new(LinkedList::new())
};
......@@ -1178,11 +1181,6 @@ impl<'a> VM {
whitelist_funcs
};
if primordial_threadlocal.is_some() {
// we are going to need to persist this threadlocal
unimplemented!()
}
let has_primordial_func = primordial_func.is_some();
let has_primordial_stack = primordial_stack.is_some();
......@@ -1235,7 +1233,12 @@ impl<'a> VM {
};
// emit context (persist vm, etc)
backend::emit_context_with_reloc(self, symbols, fields);
backend::emit_context_with_reloc(
self,
symbols,
fields,
primordial_threadlocal.map(|x| x.v.as_ref().1)
);
// link
self.link_boot_image(whitelist_funcs, extra_sources_to_link, output_file);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment