Quick-sort works using ealloc/delete on rtmu

parent 8c9e0cb0
......@@ -59,3 +59,4 @@ num-traits = "*"
built = "*"
mu_gc = { path = "src/gc"}
cfg-if = "*"
rand = "*"
\ No newline at end of file
......@@ -130,10 +130,13 @@ impl Instruction {
| Move(_)
| PrintHex(_)
| PrintBool(_)
| PrintTime(_)
| SetRetval(_)
| GetVMThreadLocal
| KillStack(_)
| CurrentStack
| RandF(_,_)
| RandI(_,_)
| SwapStackExpr { .. } => false,
}
}
......@@ -203,6 +206,7 @@ impl Instruction {
| CommonInst_GetAddr(_)
| PrintHex(_)
| PrintBool(_)
| PrintTime(_)
| SetRetval(_)
| KillStack(_) => true,
BinOp(_, _, _)
......@@ -230,6 +234,8 @@ impl Instruction {
| GetVMThreadLocal
| GetPriority(_)
| GetTime
| RandF(_,_)
| RandI(_,_)
| AffinityIsset(_, _) => false,
// | AffinityEqual(_, _)
}
......@@ -314,10 +320,13 @@ impl Instruction {
| Move(_)
| PrintHex(_)
| PrintBool(_)
| PrintTime(_)
| SetRetval(_)
| GetVMThreadLocal
| KillStack(_)
| CurrentStack
| RandI(_,_)
| RandF(_,_)
| SwapStackExpr { .. }
| SwapStackKill { .. } => false,
}
......@@ -411,10 +420,13 @@ impl Instruction {
| Move(_)
| PrintHex(_)
| PrintBool(_)
| PrintTime(_)
| SetRetval(_)
| GetVMThreadLocal
| KillStack(_)
| CurrentStack
| RandF(_,_)
| RandI(_,_)
| SwapStackExpr { .. }
| SwapStackKill { .. } => None,
}
......@@ -489,6 +501,7 @@ impl Instruction {
Move(_) |
PrintHex(_) |
PrintBool(_) |
PrintTime(_) |
SetRetval(_) |
GetVMThreadLocal |
KillStack(_) |
......@@ -1020,10 +1033,16 @@ impl Instruction {
&Instruction_::PrintBool(i) => {
format!("PRINTBOOL<{}> {}", ops[i].ty(), ops[i])
}
&Instruction_::PrintTime(i) => {
format!("PRINTTIME<{}> {}", ops[i].ty(), ops[i])
}
// set retval
&Instruction_::SetRetval(val) => format!("SETRETVAL {}", ops[val]),
&Instruction_::RandI(min, max) => format!("RandI ({}, {})", ops[min], ops[max]),
&Instruction_::RandF(min, max) => format!("RandF ({}, {})", ops[min], ops[max]),
// get vm thread local
&Instruction_::GetVMThreadLocal => format!("GETVMTHREADLOCAL")
}
}
}
......@@ -1424,10 +1443,15 @@ pub enum Instruction_ {
/// internal use: print op as hex value
PrintHex(OpIndex),
PrintBool(OpIndex),
PrintTime(OpIndex),
/// internal use: set return value for main
SetRetval(OpIndex),
/// internal use: get zebu thread local
GetVMThreadLocal
GetVMThreadLocal,
/// Int64 random genenrator
RandI(OpIndex, OpIndex),
/// f64 random generator
RandF(OpIndex, OpIndex)
}
fn format_value_types(value: &Option<Vec<P<Value>>>) -> String {
......
......@@ -3174,6 +3174,23 @@ impl<'a> InstructionSelection {
);
}
Instruction_::PrintTime(time) => {
trace!("instsel on PRINTTIME");
let ref ops = inst.ops;
let ref op = ops[time];
self.emit_runtime_entry(
&entrypoints::PRINT_TIME,
vec![op.clone_value()],
None,
Some(node),
f_content,
f_context,
vm
);
}
Instruction_::SetRetval(index) => {
trace!("instsel on SETRETVAL");
......@@ -3195,6 +3212,57 @@ impl<'a> InstructionSelection {
);
}
Instruction_::RandI(min, max) => {
trace!("instsel on RandI");
let ref ops = inst.ops;
let ref min = ops[min];
let ref max = ops[max];
assert!(self.match_ireg(min));
assert!(self.match_ireg(max));
let res = self.get_result_value(node);
let tmp_min = self.emit_ireg(min, f_content, f_context, vm);
let tmp_max = self.emit_ireg(max, f_content, f_context, vm);
self.emit_runtime_entry(
&entrypoints::RAND_INT64,
vec![tmp_min, tmp_max],
Some(vec![res.clone()]),
Some(node),
f_content,
f_context,
vm
);
}
Instruction_::RandF(min, max) => {
trace!("instsel on RandF");
let ref ops = inst.ops;
let ref min = ops[min];
let ref max = ops[max];
assert!(self.match_fpreg(min));
assert!(self.match_fpreg(max));
let res = self.get_result_value(node);
let tmp_min = self.emit_fpreg(min, f_content, f_context, vm);
let tmp_max = self.emit_fpreg(max, f_content, f_context, vm);
self.emit_runtime_entry(
&entrypoints::RAND_F64,
vec![tmp_min, tmp_max],
Some(vec![res.clone()]),
Some(node),
f_content,
f_context,
vm
);
}
_ => unimplemented!()
} // main switch
}
......
......@@ -736,8 +736,10 @@ pub fn estimate_insts_for_ir(inst: &Instruction) -> usize {
// others
Move(_) => 0,
PrintHex(_) | PrintBool(_) => 10,
PrintHex(_) | PrintBool(_) | PrintTime(_) => 10,
SetRetval(_) => 10,
RandI(_,_) => 10,
RandF(_,_) => 10,
GetVMThreadLocal => 10,
ExnInstruction { ref inner, .. } => estimate_insts_for_ir(&inner),
}
......
......@@ -77,7 +77,7 @@ impl CompilerPass for InjectRuntime {
for node in body_copy {
let inst: &Instruction = node.as_inst();
trace!("check instruction: {:?}", inst);
trace!("check instruction: {:#?}", inst);
match inst.v {
Instruction_::New(ref ty) => {
let ty_info = vm.get_backend_type_info(ty.id());
......
......@@ -58,6 +58,7 @@ fn is_suitable_child(inst: &Instruction) -> bool {
| ExnInstruction { .. }
| PrintHex(_)
| PrintBool(_)
| PrintTime(_)
| SetRetval(_)
| KillStack(_)
| CurrentStack
......@@ -108,6 +109,8 @@ fn is_suitable_child(inst: &Instruction) -> bool {
| CmpXchg { .. }
| AtomicRMW { .. }
| Store { .. }
| RandF(_,_)
| RandI(_,_)
| GetVMThreadLocal => false,
BinOp(_, _, _)
......
......@@ -38,6 +38,7 @@ pub extern crate mu_utils as utils;
extern crate core;
pub extern crate mu_gc as gc;
extern crate proc_macro;
extern crate rand;
pub mod compiler;
pub mod linkutils;
......
......@@ -22,6 +22,7 @@ use vm::VM;
use std::path::PathBuf;
use std::process::Command;
use std::sync::Arc;
/// links generated code for the given functions, static library of Zebu,
/// and a main function to produce an executable of the given name
......@@ -445,3 +446,23 @@ pub fn run_test_2f(
);
self::super::exec_path(executable);
}
///
/// # Arguments:
///
/// * func_names: is a vector of String pointers, each representing a function name.
/// the `func_names[0]` is the primordial function's name
/// and the `func_names[1]` is the tester function's name
/// and `func_names[2..]` are names of other dependent functions
///
pub fn run_test_generic(
vm: &VM,
func_names: Vec<Arc<String>>,
) {
let output_name = (*func_names[0]).clone() + "_" + (*func_names[1].clone()).as_str();
let executable = link_test_primordial(
func_names,
output_name.as_str(),
vm
);
self::super::exec_path(executable);
}
\ No newline at end of file
......@@ -476,9 +476,24 @@ lazy_static! {
vec![UINT1_TYPE.clone()],
vec![]
);
pub static ref PRINT_TIME: RuntimeEntrypoint = RuntimeEntrypoint::new(
"muentry_print_time",
vec![UINT64_TYPE.clone()],
vec![]
);
pub static ref MEM_ZERO: RuntimeEntrypoint = RuntimeEntrypoint::new(
"muentry_mem_zero",
vec![IREF_VOID_TYPE.clone(), UINT64_TYPE.clone()],
vec![]
);
pub static ref RAND_INT64: RuntimeEntrypoint = RuntimeEntrypoint::new(
"muentry_rand_int64",
vec![UINT64_TYPE.clone(), UINT64_TYPE.clone()],
vec![UINT64_TYPE.clone()]
);
pub static ref RAND_F64: RuntimeEntrypoint = RuntimeEntrypoint::new(
"muentry_rand_f64",
vec![DOUBLE_TYPE.clone(), DOUBLE_TYPE.clone()],
vec![DOUBLE_TYPE.clone()]
);
}
......@@ -13,6 +13,7 @@
// limitations under the License.
use std::collections::HashSet;
use std::collections::HashMap;
use std::sync::RwLock;
use super::mm_rtmu_std::*;
......@@ -21,6 +22,8 @@ use super::*;
lazy_static! {
pub static ref EMM_ROOTS: RwLock<HashSet<usize>> =
RwLock::new(HashSet::new());
pub static ref EMM_MAP: RwLock<HashMap<usize, usize>> =
RwLock::new(HashMap::new());
}
impl fmt::Debug for EMM_ROOTS {
......@@ -363,7 +366,13 @@ pub extern "C" fn muentry_ralloc_hybrid_traced(
#[no_mangle]
pub extern "C" fn muentry_ealloc(size: usize) -> Address {
let emm_backstore = Box::new(EMMBackStore::new(size, None));
Address::from_mut_ptr(Box::into_raw(emm_backstore))
let raw_ptr = Address::from_mut_ptr(emm_backstore.sysbackstore);
let bs_ptr = Address::from_mut_ptr(Box::into_raw(emm_backstore));
let mut map = EMM_MAP.write().unwrap();
map.insert(raw_ptr.as_usize(), bs_ptr.as_usize());
raw_ptr
}
#[no_mangle]
......@@ -375,13 +384,22 @@ pub extern "C" fn muentry_ealloc_hybrid(
let size = fixed_len + var_len * var_unit_len;
trace!("=== EALLOCHYBRID size #{}===", size);
let emm_backstore = Box::new(EMMBackStore::new(size, None));
Address::from_mut_ptr(Box::into_raw(emm_backstore))
let raw_ptr = Address::from_mut_ptr(emm_backstore.sysbackstore);
let bs_ptr = Address::from_mut_ptr(Box::into_raw(emm_backstore));
let mut map = EMM_MAP.write().unwrap();
map.insert(raw_ptr.as_usize(), bs_ptr.as_usize());
raw_ptr
}
#[no_mangle]
pub extern "C" fn muentry_edelete(backstore: Address) {
pub extern "C" fn muentry_edelete(raw_ptr: Address) {
let map = EMM_MAP.read().unwrap();
let bs_ptr = unsafe { Address::from_usize(*map.get(&raw_ptr.as_usize()).unwrap()) };
let mut emm_backstore: Box<EMMBackStore> =
unsafe { Box::from_raw(backstore.to_ptr_mut() as *mut EMMBackStore) };
unsafe { Box::from_raw(bs_ptr.to_ptr_mut() as *mut EMMBackStore) };
emm_backstore.delete()
}
......@@ -396,7 +414,13 @@ pub extern "C" fn muentry_ealloc_traced(_type: MuID) -> Address {
let iref_list = ty_info.get_iref_offsets(&vm, None);
emm_backstore.add_gcroots(&iref_list);
Address::from_mut_ptr(Box::into_raw(emm_backstore))
let raw_ptr = Address::from_mut_ptr(emm_backstore.sysbackstore);
let bs_ptr = Address::from_mut_ptr(Box::into_raw(emm_backstore));
let mut map = EMM_MAP.write().unwrap();
map.insert(raw_ptr.as_usize(), bs_ptr.as_usize());
raw_ptr
}
#[no_mangle]
......@@ -413,7 +437,13 @@ pub extern "C" fn muentry_ealloc_hybrid_traced(
let iref_list = ty_info.get_iref_offsets(&vm, Some(var_len));
emm_backstore.add_gcroots(&iref_list);
Address::from_mut_ptr(Box::into_raw(emm_backstore))
let raw_ptr = Address::from_mut_ptr(emm_backstore.sysbackstore);
let bs_ptr = Address::from_mut_ptr(Box::into_raw(emm_backstore));
let mut map = EMM_MAP.write().unwrap();
map.insert(raw_ptr.as_usize(), bs_ptr.as_usize());
raw_ptr
}
#[no_mangle]
......
......@@ -45,6 +45,7 @@ pub mod mm;
/// thread management: stack, thread
//#[cfg(feature = "realtime")]
pub mod thread;
pub mod mu_rand;
#[cfg(feature = "realtime")]
pub mod time;
......@@ -368,6 +369,13 @@ pub extern "C" fn muentry_print_bool(x: bool) {
println!("PRINTBOOL: {}", x);
}
#[no_mangle]
pub extern "C" fn muentry_print_time(x: u64) {
println!("*****************************");
println!("Time: {} nano-seconds", x);
println!("*****************************");
}
#[no_mangle]
pub unsafe extern "C" fn muentry_mem_zero(dest: *mut u8, size: usize) {
std::ptr::write_bytes(dest, 0, size);
......
// Copyright 2017 The Australian National University
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
extern crate rand;
use rand::Rng;
#[no_mangle]
pub extern "C" fn muentry_rand_int64(min: u64, max: u64) -> u64 {
let mut rng = rand::thread_rng();
let res = rng.gen_range(min, max);
if cfg!(debug_assertions) {
debug!("RandI({},{}) = {}", min, max, res);
}
res
}
#[no_mangle]
pub extern "C" fn muentry_rand_f64(min: f64, max: f64) -> f64 {
let mut rng = rand::thread_rng();
let res = rng.gen_range(min, max);
if cfg!(debug_assertions) {
debug!("RandI({},{}) = {}", min, max, res);
}
res
}
\ No newline at end of file
This diff is collapsed.
......@@ -29,6 +29,9 @@ mod test_compiler;
mod test_ir;
mod test_runtime;
#[cfg(feature = "realtime")]
mod rtmu_benchmarks;
mod common {
use std::fmt;
......
// Copyright 2019 The Australian National University
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
mod test_rt_mu_rand;
mod test_rt_quicksort;
\ No newline at end of file
// Copyright 2019 The Australian National University
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
extern crate libloading;
extern crate log;
extern crate mu;
use self::mu::ast::inst::*;
use self::mu::ast::ir::*;
use self::mu::ast::op::CmpOp;
use self::mu::ast::types::*;
use self::mu::compiler::*;
use self::mu::utils::LinkedHashMap;
use self::mu::vm::*;
use self::mu::linkutils;
use self::mu::linkutils::aot;
use std::sync::Arc;
#[test]
fn test_rt_mu_rand_i() {
build_and_run_test!(func, new_rand_i_tester1, new_rand_i);
}
fn new_rand_i() -> VM {
let vm = VM::new_with_opts("--aot-link-static");
typedef! ((vm) int64 = mu_int(64));
funcsig! ((vm) sig = (int64, int64) -> (int64));
funcdecl! ((vm) <sig> func);
funcdef! ((vm) <sig> func VERSION func_v1);
block! ((vm, func_v1) blk_entry);
// a = NEW <rtattr>
ssa! ((vm, func_v1) <int64> min);
ssa! ((vm, func_v1) <int64> max);
ssa! ((vm, func_v1) <int64> res);
inst! ((vm, func_v1) blk_entry_rand:
res = RANDI min, max
);
inst! ((vm, func_v1) blk_entry_print_rand:
PRINTHEX res
);
inst! ((vm, func_v1) blk_entry_ret:
RET (res)
);
define_block! ((vm, func_v1) blk_entry(min, max) {
blk_entry_rand, blk_entry_print_rand,
blk_entry_ret
});
define_func_ver!((vm) func_v1 (entry: blk_entry) {blk_entry});
emit_test!((vm)
TESTER new_rand_i_tester1,
TESTEE func,
INPUTS int64(0), int64(0xFF),
EXPECTED ULT int64(0xFF),
);
vm
}
#[test]
fn test_rt_mu_rand_f() {
build_and_run_test!(func, new_rand_f_tester1, new_rand_f);
}
fn new_rand_f() -> VM {
let vm = VM::new_with_opts("--aot-link-static");
typedef! ((vm) f64_t = mu_double);
funcsig! ((vm) sig = (f64_t, f64_t) -> (f64_t));
funcdecl! ((vm) <sig> func);
funcdef! ((vm) <sig> func VERSION func_v1);
block! ((vm, func_v1) blk_entry);
// a = NEW <rtattr>
ssa! ((vm, func_v1) <f64_t> min);
ssa! ((vm, func_v1) <f64_t> max);
ssa! ((vm, func_v1) <f64_t> res);
inst! ((vm, func_v1) blk_entry_rand:
res = RANDF min, max
);
// inst! ((vm, func_v1) blk_entry_print_rand:
// PRINTHEX res
// );
inst! ((vm, func_v1) blk_entry_ret:
RET (res)
);
define_block! ((vm, func_v1) blk_entry(min, max) {
blk_entry_rand,
blk_entry_ret
});
define_func_ver!((vm) func_v1 (entry: blk_entry) {blk_entry});
emit_test!((vm)
TESTER new_rand_f_tester1,
TESTEE func,
INPUTS f64_t(0.0), f64_t(1.0),
EXPECTED FULT f64_t(1.0),
);
vm
}
This diff is collapsed.
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