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.

To protect your data, the CISO officer has suggested users to enable 2FA as soon as possible.
Currently 2.6% of users enabled 2FA.

Commit 3e13746f authored by Javad Ebrahimian Amiri's avatar Javad Ebrahimian Amiri
Browse files

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.