Stream: git-wasmtime

Topic: wasmtime / issue #7937 Cranelift: call imported function ...


view this post on Zulip Wasmtime GitHub notifications bot (Feb 14 2024 at 13:27):

meijies opened issue #7937:

Hi everyone.

summary

This is asking for help/advices. I am trying generate a func named "call" and it will call a rust function named "add_wrapper". the signature of add_wrapper is extern "C" fn add_wrapper(lhs: *mut dyn Datum, rhs: *mut dyn Datum) -> *const ArrayRef. When I debug the test case, a "signal SIGSEGV" occurs at second println statement of add_wrapper function!

test code.

use arrow::{
    array::{Array, ArrayRef, Datum, Int32Array},
    compute::kernels::numeric,
};
use cranelift::{codegen::ir::UserFuncName, prelude::*};
use cranelift_jit::{JITBuilder, JITModule};
use cranelift_module::{DataDescription, Linkage, Module};
use std::mem;

pub(crate) struct JIT {
    func_ctx: FunctionBuilderContext,
    ctx: codegen::Context,
    data_description: DataDescription,
    module: JITModule,
}

extern "C" fn add_wrapper(lhs: *mut dyn Datum, rhs: *mut dyn Datum) -> *const ArrayRef {
    let lhs = unsafe { Box::from_raw(lhs) };
    let rhs = unsafe { Box::from_raw(rhs) };
    let (l, l_scalar) = lhs.get();
    let (r, r_scalar) = rhs.get();
    println!("{:?}, {:?}", l.data_type(), l_scalar);
    println!("{:?}, {:?}", r.data_type(), r_scalar);
    let res = numeric::add(lhs.as_ref(), rhs.as_ref()).unwrap();
    &res as *const ArrayRef
}

impl Default for JIT {
    fn default() -> Self {
        let mut flag_builder = settings::builder();
        flag_builder.set("use_colocated_libcalls", "false").unwrap();
        flag_builder.set("is_pic", "false").unwrap();

        // build isa
        let isa_builder = cranelift_native::builder().unwrap_or_else(|msg| {
            panic!("host machine is not supported: {}", msg);
        });
        let isa = isa_builder
            .finish(settings::Flags::new(flag_builder))
            .unwrap();

        // build module
        let mut builder = JITBuilder::with_isa(isa, cranelift_module::default_libcall_names());
        let addr: *const u8 = add_wrapper as *const u8;
        builder.symbol("add", addr);

        let module = JITModule::new(builder);
        Self {
            func_ctx: FunctionBuilderContext::new(),
            ctx: module.make_context(),
            data_description: DataDescription::new(),
            module,
        }
    }
}

impl JIT {
    pub fn compile(&mut self) {
        let mut sig_call = self.module.make_signature();
        let pointer = self.module.target_config().pointer_type();

        let mut sig_add = self.module.make_signature();
        sig_add.params.push(AbiParam::new(pointer));
        sig_add.params.push(AbiParam::new(pointer));
        sig_add.returns.push(AbiParam::new(pointer));
        let func_add = self
            .module
            .declare_function("add", Linkage::Import, &sig_add)
            .unwrap();

        sig_call.params.push(AbiParam::new(pointer));
        sig_call.params.push(AbiParam::new(pointer));
        sig_call.returns.push(AbiParam::new(pointer));
        let func_call = self
            .module
            .declare_function("call", Linkage::Local, &sig_call)
            .unwrap();

        self.ctx.func.signature = sig_call;
        self.ctx.func.name = UserFuncName::user(0, func_call.as_u32());
        {
            let mut func_builder = FunctionBuilder::new(&mut self.ctx.func, &mut self.func_ctx);
            let ebb = func_builder.create_block();
            func_builder.switch_to_block(ebb);
            func_builder.append_block_params_for_function_params(ebb);
            let func_add_local = self
                .module
                .declare_func_in_func(func_add, &mut func_builder.func);
            let lhs = func_builder.block_params(ebb)[0];
            let rhs = func_builder.block_params(ebb)[1];
            let call = func_builder.ins().call(func_add_local, &[lhs, rhs]);
            let value = {
                let result = func_builder.inst_results(call);
                assert_eq!(result.len(), 1);
                result[0].clone()
            };
            func_builder.ins().return_(&[value]);
            func_builder.seal_all_blocks();
            func_builder.finalize();
        }
        self.module
            .define_function(func_call, &mut self.ctx)
            .unwrap();
        self.module.clear_context(&mut self.ctx);
        self.module.finalize_definitions().unwrap();
        let code_call = self.module.get_finalized_function(func_call);
        let call = unsafe {
            mem::transmute::<_, extern "C" fn(*mut dyn Datum, *mut dyn Datum) -> *const ArrayRef>(
                code_call,
            )
        };
        let mut a1 = Int32Array::from(vec![1, 2, 3, 4, 5]);
        let mut a2 = Int32Array::from(vec![1, 2, 3, 4, 5]);
        let result = call(&mut a1 as *mut dyn Datum, &mut a2 as *mut dyn Datum);
        println!("{:?}", result);
    }
}

#[cfg(test)]
mod tests {

    use super::JIT;

    #[test]
    fn test_jit() {
        let mut jit = JIT::default();
        jit.compile();
    }
}

debug info.

<img width="1652" alt="Screenshot 2024-02-14 at 21 23 54" src="https://github.com/bytecodealliance/wasmtime/assets/13784260/9807365d-63d0-421e-b403-1825b7cf2965">

view this post on Zulip Wasmtime GitHub notifications bot (Feb 14 2024 at 13:45):

bjorn3 commented on issue #7937:

Trait objects don't have a stable abi. Current rustc will pass it as two arguments rather than one. One fix here would be to do pass *mut *mut dyn Datum or *mut Box<dyn Datum> instead. (double indirection such that the outer pointer is a thin pointer)

view this post on Zulip Wasmtime GitHub notifications bot (Feb 14 2024 at 15:46):

meijies closed issue #7937:

Hi everyone.

summary

This is asking for help/advices. I am trying generate a func named "call" and it will call a rust function named "add_wrapper". the signature of add_wrapper is extern "C" fn add_wrapper(lhs: *mut dyn Datum, rhs: *mut dyn Datum) -> *const ArrayRef. When I debug the test case, a "signal SIGSEGV" occurs at second println statement of add_wrapper function!

test code.

use arrow::{
    array::{Array, ArrayRef, Datum, Int32Array},
    compute::kernels::numeric,
};
use cranelift::{codegen::ir::UserFuncName, prelude::*};
use cranelift_jit::{JITBuilder, JITModule};
use cranelift_module::{DataDescription, Linkage, Module};
use std::mem;

pub(crate) struct JIT {
    func_ctx: FunctionBuilderContext,
    ctx: codegen::Context,
    data_description: DataDescription,
    module: JITModule,
}

extern "C" fn add_wrapper(lhs: *mut dyn Datum, rhs: *mut dyn Datum) -> *const ArrayRef {
    let lhs = unsafe { Box::from_raw(lhs) };
    let rhs = unsafe { Box::from_raw(rhs) };
    let (l, l_scalar) = lhs.get();
    let (r, r_scalar) = rhs.get();
    println!("{:?}, {:?}", l.data_type(), l_scalar);
    println!("{:?}, {:?}", r.data_type(), r_scalar);
    let res = numeric::add(lhs.as_ref(), rhs.as_ref()).unwrap();
    &res as *const ArrayRef
}

impl Default for JIT {
    fn default() -> Self {
        let mut flag_builder = settings::builder();
        flag_builder.set("use_colocated_libcalls", "false").unwrap();
        flag_builder.set("is_pic", "false").unwrap();

        // build isa
        let isa_builder = cranelift_native::builder().unwrap_or_else(|msg| {
            panic!("host machine is not supported: {}", msg);
        });
        let isa = isa_builder
            .finish(settings::Flags::new(flag_builder))
            .unwrap();

        // build module
        let mut builder = JITBuilder::with_isa(isa, cranelift_module::default_libcall_names());
        let addr: *const u8 = add_wrapper as *const u8;
        builder.symbol("add", addr);

        let module = JITModule::new(builder);
        Self {
            func_ctx: FunctionBuilderContext::new(),
            ctx: module.make_context(),
            data_description: DataDescription::new(),
            module,
        }
    }
}

impl JIT {
    pub fn compile(&mut self) {
        let mut sig_call = self.module.make_signature();
        let pointer = self.module.target_config().pointer_type();

        let mut sig_add = self.module.make_signature();
        sig_add.params.push(AbiParam::new(pointer));
        sig_add.params.push(AbiParam::new(pointer));
        sig_add.returns.push(AbiParam::new(pointer));
        let func_add = self
            .module
            .declare_function("add", Linkage::Import, &sig_add)
            .unwrap();

        sig_call.params.push(AbiParam::new(pointer));
        sig_call.params.push(AbiParam::new(pointer));
        sig_call.returns.push(AbiParam::new(pointer));
        let func_call = self
            .module
            .declare_function("call", Linkage::Local, &sig_call)
            .unwrap();

        self.ctx.func.signature = sig_call;
        self.ctx.func.name = UserFuncName::user(0, func_call.as_u32());
        {
            let mut func_builder = FunctionBuilder::new(&mut self.ctx.func, &mut self.func_ctx);
            let ebb = func_builder.create_block();
            func_builder.switch_to_block(ebb);
            func_builder.append_block_params_for_function_params(ebb);
            let func_add_local = self
                .module
                .declare_func_in_func(func_add, &mut func_builder.func);
            let lhs = func_builder.block_params(ebb)[0];
            let rhs = func_builder.block_params(ebb)[1];
            let call = func_builder.ins().call(func_add_local, &[lhs, rhs]);
            let value = {
                let result = func_builder.inst_results(call);
                assert_eq!(result.len(), 1);
                result[0].clone()
            };
            func_builder.ins().return_(&[value]);
            func_builder.seal_all_blocks();
            func_builder.finalize();
        }
        self.module
            .define_function(func_call, &mut self.ctx)
            .unwrap();
        self.module.clear_context(&mut self.ctx);
        self.module.finalize_definitions().unwrap();
        let code_call = self.module.get_finalized_function(func_call);
        let call = unsafe {
            mem::transmute::<_, extern "C" fn(*mut dyn Datum, *mut dyn Datum) -> *const ArrayRef>(
                code_call,
            )
        };
        let mut a1 = Int32Array::from(vec![1, 2, 3, 4, 5]);
        let mut a2 = Int32Array::from(vec![1, 2, 3, 4, 5]);
        let result = call(&mut a1 as *mut dyn Datum, &mut a2 as *mut dyn Datum);
        println!("{:?}", result);
    }
}

#[cfg(test)]
mod tests {

    use super::JIT;

    #[test]
    fn test_jit() {
        let mut jit = JIT::default();
        jit.compile();
    }
}

debug info.

<img width="1652" alt="Screenshot 2024-02-14 at 21 23 54" src="https://github.com/bytecodealliance/wasmtime/assets/13784260/9807365d-63d0-421e-b403-1825b7cf2965">

view this post on Zulip Wasmtime GitHub notifications bot (Feb 14 2024 at 17:19):

meijies commented on issue #7937:

@bjorn3 Thanks, but I meet another issue, the return result of jit generated func is different from add_wrapper and it seems to point to an invalid address {pointer:0x0000000000000070, vtable:(0) &[]}.

updated code.

use arrow::{
    array::{Array, ArrayRef, Datum, Int32Array},
    compute::kernels::numeric,
};
use cranelift::{codegen::ir::UserFuncName, prelude::*};
use cranelift_jit::{JITBuilder, JITModule};
use cranelift_module::{DataDescription, Linkage, Module};
use std::{
    mem::{self, forget},
    sync::Arc,
};

pub(crate) struct JIT {
    func_ctx: FunctionBuilderContext,
    ctx: codegen::Context,
    data_description: DataDescription,
    module: JITModule,
}

extern "C" fn add_wrapper(
    lhs: *mut Arc<dyn Datum>,
    rhs: *mut Arc<dyn Datum>,
) -> *mut Arc<dyn Array> {
    let lhs_ref = unsafe { lhs.read() };
    let rhs_ref = unsafe { rhs.read() };
    let mut res = numeric::add(lhs_ref.as_ref(), rhs_ref.as_ref()).unwrap();
    println!("{:?}", res.clone());
    &mut res as *mut ArrayRef
}

impl Default for JIT {
    fn default() -> Self {
        let mut flag_builder = settings::builder();
        flag_builder.set("use_colocated_libcalls", "false").unwrap();
        flag_builder.set("is_pic", "false").unwrap();

        // build isa
        let isa_builder = cranelift_native::builder().unwrap_or_else(|msg| {
            panic!("host machine is not supported: {}", msg);
        });
        let isa = isa_builder
            .finish(settings::Flags::new(flag_builder))
            .unwrap();

        // build module
        let mut builder = JITBuilder::with_isa(isa, cranelift_module::default_libcall_names());
        let addr: *const u8 = add_wrapper as *const u8;
        builder.symbol("add", addr);

        let module = JITModule::new(builder);
        Self {
            func_ctx: FunctionBuilderContext::new(),
            ctx: module.make_context(),
            data_description: DataDescription::new(),
            module,
        }
    }
}

impl JIT {
    pub fn compile(&mut self) {
        let mut sig_call = self.module.make_signature();
        let pointer = self.module.target_config().pointer_type();

        let mut sig_add = self.module.make_signature();
        sig_add.params.push(AbiParam::new(pointer));
        sig_add.params.push(AbiParam::new(pointer));
        sig_add.returns.push(AbiParam::new(pointer));
        let func_add = self
            .module
            .declare_function("add", Linkage::Import, &sig_add)
            .unwrap();

        sig_call.params.push(AbiParam::new(pointer));
        sig_call.params.push(AbiParam::new(pointer));
        sig_call.returns.push(AbiParam::new(pointer));
        let func_call = self
            .module
            .declare_function("call", Linkage::Local, &sig_call)
            .unwrap();

        self.ctx.func.signature = sig_call;
        self.ctx.func.name = UserFuncName::user(0, func_call.as_u32());
        {
            let mut func_builder = FunctionBuilder::new(&mut self.ctx.func, &mut self.func_ctx);
            let ebb = func_builder.create_block();
            func_builder.switch_to_block(ebb);
            func_builder.append_block_params_for_function_params(ebb);
            let func_add_local = self
                .module
                .declare_func_in_func(func_add, &mut func_builder.func);
            let lhs = func_builder.block_params(ebb)[0];
            let rhs = func_builder.block_params(ebb)[1];
            let call = func_builder.ins().call(func_add_local, &[lhs, rhs]);
            let value = {
                let result = func_builder.inst_results(call);
                assert_eq!(result.len(), 1);
                result[0].clone()
            };
            func_builder.ins().return_(&[value]);
            func_builder.seal_all_blocks();
            func_builder.finalize();
        }
        self.module
            .define_function(func_call, &mut self.ctx)
            .unwrap();
        self.module.clear_context(&mut self.ctx);
        self.module.finalize_definitions().unwrap();
        let code_call = self.module.get_finalized_function(func_call);
        let call = unsafe {
            mem::transmute::<
                _,
                extern "C" fn(*mut Arc<dyn Datum>, *mut Arc<dyn Datum>) -> *mut Arc<dyn Array>,
            >(code_call)
        };
        let a1: Arc<dyn Datum> = Arc::new(Int32Array::from(vec![1, 2, 3, 4, 5]));
        let a2: Arc<dyn Datum> = Arc::new(Int32Array::from(vec![1, 2, 3, 4, 5]));
        let result = call(
            &mut a1.clone() as *mut Arc<dyn Datum>,
            &mut a2.clone() as *mut Arc<dyn Datum>,
        );

        let result = unsafe { result.read() };
        println!("{:?}", result.clone());
    }
}

#[cfg(test)]
mod tests {

    use super::JIT;

    #[test]
    fn test_jit() {
        let mut jit = JIT::default();
        jit.compile();
    }
}

view this post on Zulip Wasmtime GitHub notifications bot (Feb 14 2024 at 17:20):

meijies edited a comment on issue #7937:

@bjorn3 Thanks, but I meet another issue, the return result of jit generated func is different from add_wrapper and it seems to point to an invalid address {pointer:0x0000000000000070, vtable:(0) &[]}. error occurs at last line of compile function.

updated code.

use arrow::{
    array::{Array, ArrayRef, Datum, Int32Array},
    compute::kernels::numeric,
};
use cranelift::{codegen::ir::UserFuncName, prelude::*};
use cranelift_jit::{JITBuilder, JITModule};
use cranelift_module::{DataDescription, Linkage, Module};
use std::{
    mem::{self, forget},
    sync::Arc,
};

pub(crate) struct JIT {
    func_ctx: FunctionBuilderContext,
    ctx: codegen::Context,
    data_description: DataDescription,
    module: JITModule,
}

extern "C" fn add_wrapper(
    lhs: *mut Arc<dyn Datum>,
    rhs: *mut Arc<dyn Datum>,
) -> *mut Arc<dyn Array> {
    let lhs_ref = unsafe { lhs.read() };
    let rhs_ref = unsafe { rhs.read() };
    let mut res = numeric::add(lhs_ref.as_ref(), rhs_ref.as_ref()).unwrap();
    println!("{:?}", res.clone());
    &mut res as *mut ArrayRef
}

impl Default for JIT {
    fn default() -> Self {
        let mut flag_builder = settings::builder();
        flag_builder.set("use_colocated_libcalls", "false").unwrap();
        flag_builder.set("is_pic", "false").unwrap();

        // build isa
        let isa_builder = cranelift_native::builder().unwrap_or_else(|msg| {
            panic!("host machine is not supported: {}", msg);
        });
        let isa = isa_builder
            .finish(settings::Flags::new(flag_builder))
            .unwrap();

        // build module
        let mut builder = JITBuilder::with_isa(isa, cranelift_module::default_libcall_names());
        let addr: *const u8 = add_wrapper as *const u8;
        builder.symbol("add", addr);

        let module = JITModule::new(builder);
        Self {
            func_ctx: FunctionBuilderContext::new(),
            ctx: module.make_context(),
            data_description: DataDescription::new(),
            module,
        }
    }
}

impl JIT {
    pub fn compile(&mut self) {
        let mut sig_call = self.module.make_signature();
        let pointer = self.module.target_config().pointer_type();

        let mut sig_add = self.module.make_signature();
        sig_add.params.push(AbiParam::new(pointer));
        sig_add.params.push(AbiParam::new(pointer));
        sig_add.returns.push(AbiParam::new(pointer));
        let func_add = self
            .module
            .declare_function("add", Linkage::Import, &sig_add)
            .unwrap();

        sig_call.params.push(AbiParam::new(pointer));
        sig_call.params.push(AbiParam::new(pointer));
        sig_call.returns.push(AbiParam::new(pointer));
        let func_call = self
            .module
            .declare_function("call", Linkage::Local, &sig_call)
            .unwrap();

        self.ctx.func.signature = sig_call;
        self.ctx.func.name = UserFuncName::user(0, func_call.as_u32());
        {
            let mut func_builder = FunctionBuilder::new(&mut self.ctx.func, &mut self.func_ctx);
            let ebb = func_builder.create_block();
            func_builder.switch_to_block(ebb);
            func_builder.append_block_params_for_function_params(ebb);
            let func_add_local = self
                .module
                .declare_func_in_func(func_add, &mut func_builder.func);
            let lhs = func_builder.block_params(ebb)[0];
            let rhs = func_builder.block_params(ebb)[1];
            let call = func_builder.ins().call(func_add_local, &[lhs, rhs]);
            let value = {
                let result = func_builder.inst_results(call);
                assert_eq!(result.len(), 1);
                result[0].clone()
            };
            func_builder.ins().return_(&[value]);
            func_builder.seal_all_blocks();
            func_builder.finalize();
        }
        self.module
            .define_function(func_call, &mut self.ctx)
            .unwrap();
        self.module.clear_context(&mut self.ctx);
        self.module.finalize_definitions().unwrap();
        let code_call = self.module.get_finalized_function(func_call);
        let call = unsafe {
            mem::transmute::<
                _,
                extern "C" fn(*mut Arc<dyn Datum>, *mut Arc<dyn Datum>) -> *mut Arc<dyn Array>,
            >(code_call)
        };
        let a1: Arc<dyn Datum> = Arc::new(Int32Array::from(vec![1, 2, 3, 4, 5]));
        let a2: Arc<dyn Datum> = Arc::new(Int32Array::from(vec![1, 2, 3, 4, 5]));
        let result = call(
            &mut a1.clone() as *mut Arc<dyn Datum>,
            &mut a2.clone() as *mut Arc<dyn Datum>,
        );

        let result = unsafe { result.read() };
        println!("{:?}", result.clone());
    }
}

#[cfg(test)]
mod tests {

    use super::JIT;

    #[test]
    fn test_jit() {
        let mut jit = JIT::default();
        jit.compile();
    }
}

view this post on Zulip Wasmtime GitHub notifications bot (Feb 14 2024 at 17:23):

meijies edited a comment on issue #7937:

@bjorn3 Thanks, but I meet another issue, the return result of jit generated func is different from add_wrapper and it seems to point to an invalid address {pointer:0x0000000000000070, vtable:(0) &[]}. error occurs at last line of compile function.

updated code.

use arrow::{
    array::{Array, ArrayRef, Datum, Int32Array},
    compute::kernels::numeric,
};
use cranelift::{codegen::ir::UserFuncName, prelude::*};
use cranelift_jit::{JITBuilder, JITModule};
use cranelift_module::{DataDescription, Linkage, Module};
use std::{
    mem::{self, forget},
    sync::Arc,
};

pub(crate) struct JIT {
    func_ctx: FunctionBuilderContext,
    ctx: codegen::Context,
    data_description: DataDescription,
    module: JITModule,
}

extern "C" fn add_wrapper(
    lhs: *mut Arc<dyn Datum>,
    rhs: *mut Arc<dyn Datum>,
) -> *mut Arc<dyn Array> {
    let lhs_ref = unsafe { lhs.read() };
    let rhs_ref = unsafe { rhs.read() };
    let mut res = numeric::add(lhs_ref.as_ref(), rhs_ref.as_ref()).unwrap();
    println!("{:?}", res.clone());
    &mut res as *mut ArrayRef
}

impl Default for JIT {
    fn default() -> Self {
        let mut flag_builder = settings::builder();
        flag_builder.set("use_colocated_libcalls", "false").unwrap();
        flag_builder.set("is_pic", "false").unwrap();

        // build isa
        let isa_builder = cranelift_native::builder().unwrap_or_else(|msg| {
            panic!("host machine is not supported: {}", msg);
        });
        let isa = isa_builder
            .finish(settings::Flags::new(flag_builder))
            .unwrap();

        // build module
        let mut builder = JITBuilder::with_isa(isa, cranelift_module::default_libcall_names());
        let addr: *const u8 = add_wrapper as *const u8;
        builder.symbol("add", addr);

        let module = JITModule::new(builder);
        Self {
            func_ctx: FunctionBuilderContext::new(),
            ctx: module.make_context(),
            data_description: DataDescription::new(),
            module,
        }
    }
}

impl JIT {
    pub fn compile(&mut self) {
        let mut sig_call = self.module.make_signature();
        let pointer = self.module.target_config().pointer_type();

        let mut sig_add = self.module.make_signature();
        sig_add.params.push(AbiParam::new(pointer));
        sig_add.params.push(AbiParam::new(pointer));
        sig_add.returns.push(AbiParam::new(pointer));
        let func_add = self
            .module
            .declare_function("add", Linkage::Import, &sig_add)
            .unwrap();

        sig_call.params.push(AbiParam::new(pointer));
        sig_call.params.push(AbiParam::new(pointer));
        sig_call.returns.push(AbiParam::new(pointer));
        let func_call = self
            .module
            .declare_function("call", Linkage::Local, &sig_call)
            .unwrap();

        self.ctx.func.signature = sig_call;
        self.ctx.func.name = UserFuncName::user(0, func_call.as_u32());
        {
            let mut func_builder = FunctionBuilder::new(&mut self.ctx.func, &mut self.func_ctx);
            let ebb = func_builder.create_block();
            func_builder.switch_to_block(ebb);
            func_builder.append_block_params_for_function_params(ebb);
            let func_add_local = self
                .module
                .declare_func_in_func(func_add, &mut func_builder.func);
            let lhs = func_builder.block_params(ebb)[0];
            let rhs = func_builder.block_params(ebb)[1];
            let call = func_builder.ins().call(func_add_local, &[lhs, rhs]);
            let value = {
                let result = func_builder.inst_results(call);
                assert_eq!(result.len(), 1);
                result[0].clone()
            };
            func_builder.ins().return_(&[value]);
            func_builder.seal_all_blocks();
            func_builder.finalize();
        }
        self.module
            .define_function(func_call, &mut self.ctx)
            .unwrap();
        self.module.clear_context(&mut self.ctx);
        self.module.finalize_definitions().unwrap();
        let code_call = self.module.get_finalized_function(func_call);
        let call = unsafe {
            mem::transmute::<
                _,
                extern "C" fn(*mut Arc<dyn Datum>, *mut Arc<dyn Datum>) -> *mut Arc<dyn Array>,
            >(code_call)
        };
        let a1: Arc<dyn Datum> = Arc::new(Int32Array::from(vec![1, 2, 3, 4, 5]));
        let a2: Arc<dyn Datum> = Arc::new(Int32Array::from(vec![1, 2, 3, 4, 5]));
        let result = call(
            &mut a1.clone() as *mut Arc<dyn Datum>,
            &mut a2.clone() as *mut Arc<dyn Datum>,
        );

        let result = unsafe { result.read() };
        println!("{:?}", result.clone());
    }
}

#[cfg(test)]
mod tests {

    use super::JIT;

    #[test]
    fn test_jit() {
        let mut jit = JIT::default();
        jit.compile();
    }
}

debug info

<img width="1627" alt="Screenshot 2024-02-15 at 01 22 44" src="https://github.com/bytecodealliance/wasmtime/assets/13784260/867f3eba-efb8-4764-8591-df5eb6af2b1b">

view this post on Zulip Wasmtime GitHub notifications bot (Feb 14 2024 at 17:59):

bjorn3 commented on issue #7937:

At least one issue I see is that you are having a double free. &mut a1.clone() as *mut Arc<dyn Datum> would increment the refcount in the clone and decrement it again after it gets dropped. At the same time however unsafe { lhs.read() } inside add_wrapper constructs an Arc without incrementing the refcount, but then decrements it at the end. Furthermore the &mut res as *mut ArrayRef inside add_wrapper will drop the res at the end of the function and thus cause the value to be freed, but then after the call, unsafe { result.read() }; will try to get an Arc again. In addition it will not even keep the ArrayRef value itself alive, so you are returning a dangling pointer to a dangling Arc. To avoid the refcount issues you could use Arc::into_raw() on one side and Arc::from_raw() on the other side. For the issue with &mut res as *mut ArrayRef, the easiest solution is likely to change add_wrapper to instead take as argument the location where the ArrayRef (or rather *mut dyn Array after calling Arc::into_raw()) should be written and pass this into call.


Last updated: Oct 23 2024 at 20:03 UTC