use xjbutil::boxed_slice;
use xjbutil::slice_arena::SliceArena;
use xjbutil::void::Void;
use crate::builtins::object::Object;
use crate::data::Value;
use crate::data::traits::StaticBase;
use crate::data::tyck::TyckInfoPool;
use crate::ffi::{FFIException, Signature};
use crate::ffi::sync_fn::{FunctionBase, OwnershipGuard, VMContext, value_into_ref};
use crate::vm::al31f::alloc::Alloc;
use crate::vm::al31f::compiled::{CompiledFunction, CompiledProgram, ExceptionHandlingBlock};
use crate::vm::al31f::insc::Insc;
#[cfg(feature = "async")] use crate::data::exception::ExceptionInner;
#[cfg(feature = "async")] use crate::ffi::async_fn::{
AsyncFunctionBase,
AsyncReturnType,
AsyncVMContext,
Promise
};
#[cfg(feature = "async")] use crate::ffi::async_fn::LockedCtx;
#[cfg(feature = "async")] use crate::std47::futures::SLEEP_MS_BIND;
#[cfg(feature = "async")] use crate::std47::io::PRINT_BIND;
pub fn basic_program<A: Alloc>() -> CompiledProgram<A> {
let (slice_arena, code) = unsafe {
let slice_arena: SliceArena<8192, 8> = SliceArena::new();
let code: Box<[Insc]> = boxed_slice![
Insc::AddInt(0, 1, 0),
Insc::Return(slice_arena.unsafe_make(&[0]))
];
(slice_arena, code)
};
CompiledProgram {
slice_arena,
code,
const_pool: boxed_slice![],
init_proc: 0,
functions: boxed_slice![
CompiledFunction::new(0, 2, 1, 2, boxed_slice![])
],
ffi_funcs: boxed_slice![],
#[cfg(feature = "async")]
async_ffi_funcs: boxed_slice![],
}
}
pub fn basic_fn_call_program<A: Alloc>() -> CompiledProgram<A> {
let (slice_arena, code) = unsafe {
let arena: SliceArena<8192, 8> = SliceArena::new();
let code: Box<[Insc]> = boxed_slice![
Insc::MakeIntConst(1, 0), Insc::MakeIntConst(2, 1), Insc::Call(1, arena.unsafe_make(&[0, 1]), arena.unsafe_make(&[0])),
Insc::Return(arena.unsafe_make(&[0])),
Insc::AddInt(0, 1, 0), Insc::Return(arena.unsafe_make(&[0])) ];
(arena, code)
};
CompiledProgram {
slice_arena,
code,
const_pool: boxed_slice![],
init_proc: 0,
functions: boxed_slice![
CompiledFunction::new(0, 0, 1, 2, boxed_slice![]), CompiledFunction::new(4, 2, 1, 2, boxed_slice![]), ],
ffi_funcs: boxed_slice![],
#[cfg(feature = "async")]
async_ffi_funcs: boxed_slice![],
}
}
pub fn fibonacci_program<A: Alloc>() -> CompiledProgram<A> {
let (slice_arena, code) = unsafe {
let arena: SliceArena<8192, 8> = SliceArena::new();
let code: Box<[Insc]> = boxed_slice![
Insc::MakeIntConst(0, 1), Insc::LeInt(0, 1, 2), Insc::JumpIfTrue(2, 12), Insc::MakeIntConst(1, 1), Insc::EqValue(0, 1, 2), Insc::JumpIfTrue(2, 12), Insc::SubInt(0, 1, 2), Insc::MakeIntConst(2, 1), Insc::SubInt(0, 1, 3), Insc::Call(0, arena.unsafe_make(&[2]),
arena.unsafe_make(&[2])), Insc::Call(0, arena.unsafe_make(&[3]),
arena.unsafe_make(&[3])), Insc::AddInt(2, 3, 1), Insc::ReturnOne(1) ];
(arena, code)
};
CompiledProgram {
slice_arena,
code,
const_pool: boxed_slice![],
init_proc: 0,
functions: boxed_slice![
CompiledFunction::new(0, 1, 1, 4, boxed_slice![])
],
ffi_funcs: boxed_slice![],
#[cfg(feature = "async")]
async_ffi_funcs: boxed_slice![],
}
}
pub fn alloc_1m_program<A: Alloc>() -> CompiledProgram<A> {
let (slice_arena, code) = {
let arena: SliceArena<8192, 8> = SliceArena::new();
let code: Box<[Insc]> = boxed_slice![
Insc::MakeIntConst(0, 0), Insc::MakeIntConst(1, 1), Insc::MakeIntConst(10_000_000, 2), Insc::EqValue(0, 2, 3), Insc::JumpIfTrue(3, 8), Insc::CreateObject(3), Insc::SubInt(2, 1, 2), Insc::Jump(3), Insc::ReturnNothing ];
(arena, code)
};
CompiledProgram {
slice_arena,
code,
const_pool: boxed_slice![],
init_proc: 0,
functions: boxed_slice![
CompiledFunction::new(0, 0, 0, 4, boxed_slice![])
],
ffi_funcs: boxed_slice![],
#[cfg(feature = "async")]
async_ffi_funcs: boxed_slice![],
}
}
pub fn exception_program<A: Alloc>() -> CompiledProgram<A> {
let (slice_arena, code) = unsafe {
let arena: SliceArena<8192, 8> = SliceArena::new();
let code: Box<[Insc]> = boxed_slice![
Insc::MakeIntConst(12345, 0), Insc::Call(1, arena.unsafe_make(&[]),
arena.unsafe_make(&[])), Insc::ReturnOne(0),
Insc::MakeIntConst(114514, 0), Insc::ReturnOne(0),
Insc::Call(2, arena.unsafe_make(&[]),
arena.unsafe_make(&[])), Insc::ReturnNothing,
Insc::CreateObject(0), Insc::Raise(0) ];
(arena, code)
};
CompiledProgram {
slice_arena,
code,
const_pool: boxed_slice![],
init_proc: 0,
functions: boxed_slice![
CompiledFunction::new_with_exc(0, 0, 1, 1, boxed_slice![], boxed_slice![
ExceptionHandlingBlock::new(0, 2, <Void as StaticBase<Object>>::type_id(), 3)
]),
CompiledFunction::new(5, 0, 0, 0, boxed_slice![]),
CompiledFunction::new(7, 0, 0, 1, boxed_slice![])
],
ffi_funcs: boxed_slice![],
#[cfg(feature = "async")]
async_ffi_funcs: boxed_slice![]
}
}
pub fn exception_no_eh_program<A: Alloc>() -> CompiledProgram<A> {
let (slice_arena, code) = unsafe {
let arena: SliceArena<8192, 8> = SliceArena::new();
let code: Box<[Insc]> = boxed_slice![
Insc::Call(1, arena.unsafe_make(&[]), arena.unsafe_make(&[0])),
Insc::ReturnOne(0),
Insc::CreateObject(0), Insc::Raise(0), ];
(arena, code)
};
CompiledProgram {
slice_arena,
code,
const_pool: boxed_slice![],
init_proc: 0,
functions: boxed_slice![
CompiledFunction::new(0, 0, 1, 1, boxed_slice![]),
CompiledFunction::new(2, 0, 1, 1, boxed_slice![])
],
ffi_funcs: boxed_slice![],
#[cfg(feature = "async")]
async_ffi_funcs: boxed_slice![]
}
}
#[inline(never)] fn ffi_function(x: &Object, y: &Object, z: &Object) {
assert_eq!(x as *const Object as usize, y as *const Object as usize);
assert_eq!(y as *const Object as usize, z as *const Object as usize);
}
#[allow(non_camel_case_types)]
struct Pr47Binder_ffi_function();
impl FunctionBase for Pr47Binder_ffi_function {
fn signature(_tyck_info_pool: &mut TyckInfoPool) -> Signature {
todo!()
}
unsafe fn call_rtlc<CTX: VMContext>(
_context: &mut CTX,
args: &[Value],
rets: &[*mut Value]
) -> Result<(), FFIException> {
debug_assert_eq!(args.len(), 3);
debug_assert_eq!(rets.len(), 0);
let (a1, g1): (&Object, Option<OwnershipGuard>) = value_into_ref(*args.get_unchecked(0))?;
let (a2, g2): (&Object, Option<OwnershipGuard>) = value_into_ref(*args.get_unchecked(1))?;
let (a3, g3): (&Object, Option<OwnershipGuard>) = value_into_ref(*args.get_unchecked(2))?;
ffi_function(a1, a2, a3);
std::mem::drop(g3);
std::mem::drop(g2);
std::mem::drop(g1);
Ok(())
}
unsafe fn call_unchecked<CTX: VMContext>(
_context: &mut CTX,
_args: &[Value],
_rets: &[*mut Value]
) -> Result<(), FFIException> {
todo!()
}
}
const PR47BINDER_FFI_FUNCTION: &'static Pr47Binder_ffi_function = &Pr47Binder_ffi_function();
pub fn ffi_call_program<A: Alloc>() -> CompiledProgram<A> {
let (slice_arena, code) = unsafe {
let arena: SliceArena<8192, 8> = SliceArena::new();
let code: Box<[Insc]> = boxed_slice![
Insc::CreateObject(0), Insc::FFICallRtlc(0, arena.unsafe_make(&[0, 0, 0]),
arena.unsafe_make(&[])),
Insc::ReturnNothing ];
(arena, code)
};
CompiledProgram {
slice_arena,
code,
const_pool: boxed_slice![],
init_proc: 0,
functions: boxed_slice![
CompiledFunction::new(0, 0, 0, 1, boxed_slice![])
],
ffi_funcs: boxed_slice![PR47BINDER_FFI_FUNCTION as _],
#[cfg(feature="async")] async_ffi_funcs: boxed_slice![]
}
}
pub fn bench_raw_iter_program<A: Alloc>() -> CompiledProgram<A> {
let (slice_arena, code) = {
let arena: SliceArena<8192, 8> = SliceArena::new();
let code: Box<[Insc]> = boxed_slice![
Insc::MakeIntConst(0, 0), Insc::MakeIntConst(100_000_000, 1), Insc::MakeIntConst(1, 2), Insc::EqValue(0, 1, 3), Insc::JumpIfTrue(3, 7), Insc::AddInt(0, 2, 0), Insc::Jump(3), Insc::ReturnNothing ];
(arena, code)
};
CompiledProgram {
slice_arena,
code,
const_pool: boxed_slice![],
init_proc: 0,
functions: boxed_slice![
CompiledFunction::new(0, 0, 0, 5, boxed_slice![])
],
ffi_funcs: boxed_slice![],
#[cfg(feature="async")] async_ffi_funcs: boxed_slice![]
}
}
pub fn bench_ffi_call_program<A: Alloc>() -> CompiledProgram<A> {
let (slice_arena, code) = unsafe {
let arena: SliceArena<8192, 8> = SliceArena::new();
let code: Box<[Insc]> = boxed_slice![
Insc::MakeIntConst(0, 0), Insc::MakeIntConst(100_000_000, 1), Insc::MakeIntConst(1, 2), Insc::CreateObject(3), Insc::EqValue(0, 1, 4), Insc::JumpIfTrue(4, 9), Insc::FFICallRtlc(0, arena.unsafe_make(&[3, 3, 3]),
arena.unsafe_make(&[])),
Insc::AddInt(0, 2, 0), Insc::Jump(4), Insc::ReturnNothing ];
(arena, code)
};
CompiledProgram {
slice_arena,
code,
const_pool: boxed_slice![],
init_proc: 0,
functions: boxed_slice![
CompiledFunction::new(0, 0, 0, 5, boxed_slice![])
],
ffi_funcs: boxed_slice![PR47BINDER_FFI_FUNCTION as _],
#[cfg(feature="async")] async_ffi_funcs: boxed_slice![]
}
}
#[inline(never)] fn ffi_function2(a: i64, b: i64) -> i64 {
a + b
}
#[allow(non_camel_case_types)]
struct Pr47Binder_ffi_function2();
impl FunctionBase for Pr47Binder_ffi_function2 {
fn signature(_tyck_info_pool: &mut TyckInfoPool) -> Signature {
unimplemented!()
}
unsafe fn call_rtlc<CTX: VMContext>(
_context: &mut CTX,
args: &[Value],
rets: &[*mut Value]
) -> Result<(), FFIException> {
debug_assert_eq!(args.len(), 2);
debug_assert_eq!(rets.len(), 1);
let a1: i64 = args.get_unchecked(0).vt_data.inner.int_value;
let a2: i64 = args.get_unchecked(1).vt_data.inner.int_value;
let ret: i64 = ffi_function2(a1, a2);
*(*rets.get_unchecked(0)) = Value::new_int(ret);
Ok(())
}
unsafe fn call_unchecked<CTX: VMContext>(
_context: &mut CTX,
_args: &[Value],
_rets: &[*mut Value]
) -> Result<(), FFIException> {
todo!()
}
}
const PR47_BINDER_FFI_FUNCTION2: &'static Pr47Binder_ffi_function2 = &Pr47Binder_ffi_function2();
pub fn ffi_call_program2<A: Alloc>() -> CompiledProgram<A> {
let (slice_arena, code) = unsafe {
let arena: SliceArena<8192, 8> = SliceArena::new();
let code: Box<[Insc]> = boxed_slice![
Insc::FFICallRtlc(0, arena.unsafe_make(&[0, 1]),
arena.unsafe_make(&[0])),
Insc::ReturnOne(0) ];
(arena, code)
};
CompiledProgram {
slice_arena,
code,
const_pool: boxed_slice![],
init_proc: 0,
functions: boxed_slice![
CompiledFunction::new(0, 2, 1, 2, boxed_slice![])
],
ffi_funcs: boxed_slice![PR47_BINDER_FFI_FUNCTION2 as _],
#[cfg(feature="async")] async_ffi_funcs: boxed_slice![]
}
}
pub fn bench_ffi_call_program2<A: Alloc>() -> CompiledProgram<A> {
let (slice_arena, code) = unsafe {
let arena: SliceArena<8192, 8> = SliceArena::new();
let code: Box<[Insc]> = boxed_slice![
Insc::MakeIntConst(0, 0), Insc::MakeIntConst(10_000, 1), Insc::EqValue(0, 1, 2), Insc::JumpIfTrue(2, 15), Insc::MakeIntConst(0, 3), Insc::EqValue(3, 1, 2), Insc::JumpIfTrue(2, 13), Insc::AddInt(0, 3, 4), Insc::FFICallRtlc(0, arena.unsafe_make(&[0, 3]), arena.unsafe_make(&[5])),
Insc::EqValue(4, 5, 2), Insc::JumpIfFalse(2, 16), Insc::IncrInt(3), Insc::Jump(5), Insc::IncrInt(0), Insc::Jump(2), Insc::ReturnNothing, Insc::CreateObject(0), Insc::Raise(0) ];
(arena, code)
};
CompiledProgram {
slice_arena,
code,
const_pool: boxed_slice![],
init_proc: 0,
functions: boxed_slice![
CompiledFunction::new(0, 0, 0, 6, boxed_slice![])
],
ffi_funcs: boxed_slice![PR47_BINDER_FFI_FUNCTION2 as _],
#[cfg(feature="async")] async_ffi_funcs: boxed_slice![]
}
}
#[cfg(feature = "async")]
#[inline(never)] async fn async_ffi_function() -> Result<String, std::io::Error> {
#[cfg(feature = "async-astd")]
return async_std::fs::read_to_string("./Cargo.toml").await;
#[cfg(feature = "async-tokio")]
tokio::fs::read_to_string("./Cargo.toml").await
}
#[cfg(feature = "async")]
#[allow(non_camel_case_types)]
struct Pr47Binder_async_ffi_function();
#[cfg(feature = "async")]
impl AsyncFunctionBase for Pr47Binder_async_ffi_function {
fn signature(_tyck_info_pool: &mut TyckInfoPool) -> Signature {
unimplemented!()
}
unsafe fn call_rtlc<LC: LockedCtx, ACTX: AsyncVMContext<Locked=LC>> (
_context: &ACTX,
_args: &[Value]
) -> Result<Promise<LC>, FFIException> {
struct AsyncRet {
r: Result<String, std::io::Error>
}
impl<LC: LockedCtx> AsyncReturnType<LC> for AsyncRet {
fn is_err(&self) -> bool {
self.r.is_err()
}
fn resolve(self: Box<Self>, locked_ctx: &mut LC, dests: &[*mut Value])
-> Result<usize, ExceptionInner>
{
match self.r {
Ok(data) => {
let value: Value = Value::new_owned(data);
unsafe {
locked_ctx.add_heap_managed(value);
**dests.get_unchecked(0) = value;
}
Ok(1)
},
Err(e) => {
let err_value: Value = Value::new_owned(e);
locked_ctx.add_heap_managed(err_value);
Err(ExceptionInner::Checked(err_value))
}
}
}
}
let fut = async move {
let r: Result<String, std::io::Error> = async_ffi_function().await;
Box::new(AsyncRet { r }) as Box<dyn AsyncReturnType<LC>>
};
Ok(Promise(Box::pin(fut)))
}
}
#[cfg(feature = "async")]
const PR47BINDER_ASYNC_FFI_FUNCTION: &'static Pr47Binder_async_ffi_function
= &Pr47Binder_async_ffi_function();
#[cfg(feature = "async")]
pub fn async_ffi_call_program<A: Alloc>() -> CompiledProgram<A> {
let (slice_arena, code) = unsafe {
let arena: SliceArena<8192, 8> = SliceArena::new();
let code: Box<[Insc]> = boxed_slice![
Insc::FFICallAsync(0, arena.unsafe_make(&[]), 0),
Insc::Await(0, arena.unsafe_make(&[0])), Insc::ReturnOne(0) ];
(arena, code)
};
CompiledProgram {
slice_arena,
code,
const_pool: boxed_slice![],
init_proc: 0,
functions: boxed_slice![
CompiledFunction::new(0, 0, 1, 1, boxed_slice![])
],
ffi_funcs: boxed_slice![],
async_ffi_funcs: boxed_slice![PR47BINDER_ASYNC_FFI_FUNCTION as _]
}
}
#[cfg(all(feature = "async", feature = "al31f-builtin-ops"))]
pub fn async_spawn_program<A: Alloc>() -> CompiledProgram<A> {
let string1: String = "string1\n".into();
let string1: Value = Value::new_owned(string1);
let string2: String = "string2\n".into();
let string2: Value = Value::new_owned(string2);
let string3: String = "string3\n".into();
let string3: Value = Value::new_owned(string3);
let string4: String = "string4\n".into();
let string4: Value = Value::new_owned(string4);
let (slice_arena, code) = unsafe {
let arena: SliceArena<8192, 8> = SliceArena::new();
let code: Box<[Insc]> = boxed_slice![
Insc::MakeIntConst(1, 0), Insc::Spawn(1, arena.unsafe_make(&[])), Insc::Await(0, arena.unsafe_make(&[0])), Insc::LoadConst(0, 1), Insc::FFICallRtlc(0, arena.unsafe_make(&[1]),
arena.unsafe_make(&[])),
Insc::MakeIntConst(1000, 1), Insc::FFICallAsync(0, arena.unsafe_make(&[1]),
1),
Insc::Await(1, arena.unsafe_make(&[])), Insc::LoadConst(1, 1), Insc::FFICallRtlc(0, arena.unsafe_make(&[1]),
arena.unsafe_make(&[])),
Insc::Await(0, arena.unsafe_make(&[])), Insc::ReturnNothing,
Insc::LoadConst(2, 0), Insc::FFICallRtlc(0, arena.unsafe_make(&[0]),
arena.unsafe_make(&[])),
Insc::MakeIntConst(1000, 0), Insc::FFICallAsync(0, arena.unsafe_make(&[0]),
0),
Insc::Await(0, arena.unsafe_make(&[])), Insc::LoadConst(3, 0), Insc::FFICallRtlc(0, arena.unsafe_make(&[0]),
arena.unsafe_make(&[])),
Insc::ReturnNothing ];
(arena, code)
};
CompiledProgram {
slice_arena,
code,
const_pool: boxed_slice![string1, string2, string3, string4],
init_proc: 0,
functions: boxed_slice![
CompiledFunction::new(0, 0, 0, 2, boxed_slice![]),
CompiledFunction::new(12, 0, 0, 1, boxed_slice![])
],
ffi_funcs: boxed_slice![PRINT_BIND as _],
async_ffi_funcs: boxed_slice![SLEEP_MS_BIND as _]
}
}