Commit 25edf86a authored by qinsoon's avatar qinsoon

[wip] vm mod

parent 9db8ac97
......@@ -15,21 +15,28 @@
use ast::ir::*;
use ast::ptr::*;
use ast::types::*;
use utils::BitSize;
use utils::Address;
use std::fmt;
pub type APIHandleResult = Box<APIHandle>;
pub type APIHandleArg<'a> = &'a APIHandle;
/// APIHandle represents the opaque handle type that the client uses to
/// communicate with Mu. Handles can refer to values, functions, signatures,
/// etc that client can inspect/query from the VM.
#[derive(Clone)]
pub struct APIHandle {
pub id: MuID,
pub v: APIHandleValue
}
/// when we returning an API handle to the client, we create a Box<APIHandle>,
/// then api_impl will turn it into a raw pointer, and pass the pointer the the client.
/// Thus Rust allocates the handle, but will not reclaim it. When the client explicitly
/// deletes a value, we turn the pointer back to a box type, and let Rust drop it.
pub type APIHandleResult = Box<APIHandle>;
/// when client pass a handle (*const APIHandle) to the VM, we treat it as a reference
/// to APIHandle.
pub type APIHandleArg<'a> = &'a APIHandle;
impl fmt::Display for APIHandle {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(f, "{:?}", self)
......@@ -44,43 +51,76 @@ impl fmt::Debug for APIHandle {
#[derive(Clone)]
pub enum APIHandleValue {
/// (int value, bit length)
Int(u64, BitSize),
/// float value
Float(f32),
/// double value
Double(f64),
/// unsafe pointer (type, address)
UPtr(P<MuType>, Address), // uptr<T>
/// unsafe function pointer (type, address)
UFP (P<MuType>, Address), // ufuncptr<sig>
// SeqValue
/// struct value (a vector of field values)
Struct(Vec<APIHandleValue>),
/// array value (a vector of element values)
Array (Vec<APIHandleValue>),
/// vector value (a vector of element values)
Vector(Vec<APIHandleValue>),
// GenRef
Ref (P<MuType>, Address), // referenced type
/// reference value (type, address)
Ref (P<MuType>, Address),
/// internal reference value (type, address)
IRef(P<MuType>, Address),
/// tagref value (stored as 64-bit integers)
TagRef64(u64),
/// function reference (as ID)
FuncRef(MuID),
/// Mu thread reference
ThreadRef,
/// Mu stack reference
StackRef,
FCRef, // frame cursor ref
/// frame cursor reference
FCRef,
// GenRef->IR
/// Mu bundle
// TODO: unused
Bundle,
// GenRef->IR->Child
/// Mu type (as ID)
Type(MuID),
/// Mu signature (as ID)
FuncSig(MuID),
/// Mu function version (as ID)
FuncVer(MuID),
/// basic block
// TODO: unused
BB,
/// instruction
// TODO: unused
Inst,
// GenRef->IR->Child->Var->Global
/// global cell (as ID)
Global(MuID),
/// exposed function
// TODO: unused
ExpFunc,
// GenRef->IR->Child->Var->Local
/// normal parameter
// TODO: unused
NorParam,
/// exceptional parameter
// TODO: unused
ExcParam,
/// instruction result value
// TODO: unused
InstRes,
}
......@@ -125,6 +165,7 @@ impl fmt::Debug for APIHandleValue {
}
impl APIHandleValue {
/// matches the handle as ref or iref
pub fn as_ref_or_iref(&self) -> (P<MuType>, Address) {
match self {
&APIHandleValue::Ref(ref ty, addr)
......@@ -133,6 +174,7 @@ impl APIHandleValue {
}
}
/// matches the handle as ref
pub fn as_ref(&self) -> (P<MuType>, Address) {
match self {
&APIHandleValue::Ref(ref ty, addr) => (ty.clone(), addr),
......@@ -140,6 +182,7 @@ impl APIHandleValue {
}
}
/// matches the handle as iref
pub fn as_iref(&self) -> (P<MuType>, Address) {
match self {
&APIHandleValue::IRef(ref ty, addr) => (ty.clone(), addr),
......@@ -147,6 +190,7 @@ impl APIHandleValue {
}
}
/// matches iref/ref/uptr/ufp handles and extracts address
pub fn as_address(&self) -> Address {
match self {
&APIHandleValue::IRef (_, addr)
......@@ -157,6 +201,7 @@ impl APIHandleValue {
}
}
/// matches the handle as int
pub fn as_int(&self) -> u64 {
match self {
&APIHandleValue::Int(val, _) => val,
......@@ -164,6 +209,7 @@ impl APIHandleValue {
}
}
/// matches the handle as float
pub fn as_float(&self) -> f32 {
match self {
&APIHandleValue::Float(val) => val,
......@@ -171,6 +217,7 @@ impl APIHandleValue {
}
}
/// matches the handle as double
pub fn as_double(&self) -> f64 {
match self {
&APIHandleValue::Double(val) => val,
......@@ -178,6 +225,7 @@ impl APIHandleValue {
}
}
/// matches the handle as unsafe pointer
pub fn as_uptr(&self) -> (P<MuType>, Address) {
match self {
&APIHandleValue::UPtr(ref ty, addr) => (ty.clone(), addr),
......@@ -185,6 +233,7 @@ impl APIHandleValue {
}
}
/// matches the handle as unsafe function pointer
pub fn as_ufp(&self) -> (P<MuType>, Address) {
match self {
&APIHandleValue::UFP(ref ty, addr) => (ty.clone(), addr),
......@@ -192,13 +241,15 @@ impl APIHandleValue {
}
}
/// matches the handle as function reference
pub fn as_funcref(&self) -> MuID {
match self {
&APIHandleValue::FuncRef(id) => id,
_ => panic!("expected FuncRef")
}
}
/// matches the handle as tag reference's value)
pub fn as_tr64(&self) -> u64 {
match self {
&APIHandleValue::TagRef64(val) => val,
......
......@@ -12,11 +12,18 @@
// See the License for the specific language governing permissions and
// limitations under the License.
/// vm module: storing metadata, implementing APIs
mod vm;
/// re-export VM. VM stores metadata for a running Zebu instance,
/// which includes types, globals, functions/IRs, compiled functions
/// and other runtime table (exception table etc)
pub use vm::vm::VM;
/// vm_options defines commandline flags to create a new Zebu instance
mod vm_options;
/// api module implements the C functions in muapi.h exposed as Mu API
pub mod api;
pub mod handle;
pub use vm::vm::VM;
pub use vm::vm_options::VMOptions;
/// handle type for client. This handle type is opaque to the client
mod handle;
......@@ -46,8 +46,25 @@ use std::sync::atomic::{AtomicUsize, AtomicBool, ATOMIC_BOOL_INIT, ATOMIC_USIZE_
// such as STRUCT_TAG_MAP
// possibly INTERNAL_ID in ir.rs, internal types, etc
/// The VM struct. This stores metadata for the currently running Zebu instance.
/// This struct gets persisted in the boot image, and when the boot image is loaded,
/// everything should be back to the same status as before persisting.
/// This struct is usually used as Arc<VM> so it can be shared among threads. The
/// Arc<VM> is stored in every thread local of a Mu thread, so that they can refer
/// to the VM easily.
/// We are using fine-grained lock on VM to allow mutability on different fields in VM.
/// Also we use two-level locks for some data structures such as MuFunction/
/// MuFunctionVersion/CompiledFunction so that we can mutate on two
/// different functions/funcvers/etc at the same time.
// FIXME: However, there are problems with this design, and we will need to rethink.
// See Issue #2.
// FIXME: besides fields in VM, there are some 'globals' we need to persist
// such as STRUCT_TAG_MAP, INTERNAL_ID and internal types from ir crate. The point is
// ir crate should be independent and self-contained. But when persisting the 'world',
// besides persisting VM struct (containing most of the 'world'), we also need to
// specifically persist those globals.
pub struct VM {
// ---serialize---
// ---serialize these fields---
// 0
next_id: AtomicUsize,
// 1
......
......@@ -84,10 +84,15 @@ impl VMOptions {
info!("parsed as {:?}", ret);
// at the moment disable collection for debugging
// also because currently GC is buggy, and we are going to rewrite the GC
// See Issue #12
ret.flag_gc_disable_collection = true;
// at the moment always emit debug info
ret.flag_emit_debug_info = true;
// always disable register validation
// register validation is buggy. See Issue #19
ret.flag_disable_regalloc_validate = true;
ret
......
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