WARNING! Access to this system is limited to authorised users only.
Unauthorised users may be subject to prosecution.
Unauthorised access to this system is a criminal offence under Australian law (Federal Crimes Act 1914 Part VIA)
It is a criminal offence to:
(1) Obtain access to data without authority. -Penalty 2 years imprisonment.
(2) Damage, delete, alter or insert data without authority. -Penalty 10 years imprisonment.
User activity is monitored and recorded. Anyone using this system expressly consents to such monitoring and recording.

Commit 71aefd55 authored by qinsoon's avatar qinsoon
Browse files

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