fn vm_send(&mut self) -> InvokeResult {
        let method_name = self.pc.read_id();
        let args_num = self.pc.read16() as usize;
        let flag = self.pc.read_argflag();
        let block = self.pc.read32();
        let cache_id = self.pc.read32();
        let use_value = true;
        let block = self.handle_block_arg(block, flag)?;
        let keyword = self.handle_hash_args(flag)?;
        let receiver = (self.sp() - args_num - 1)[0];
        let mut args = if flag.has_splat() {
            self.pop_args_to_args(args_num)
        } else {
            Args2::new(args_num)
        };
        if flag.has_delegate() {
            if let Some(v) = self.cur_delegate() {
                let ary = &**v.as_array().expect("Delegate arg must be Array or nil.");
                args.append(ary);
                self.stack.extend_from_slice(ary);
            }
        }
        args.block = block;
        args.kw_arg = keyword;
        self.send(method_name, receiver, &args, use_value, cache_id)
    }
Stack layout of arguments

+------+------+------+--+------+------+------+-------+
| self | arg0 | args |..| argn |  kw  |hashsp| block |
+------+------+------+--+------+------+------+-------+

argx:   arguments
kw:     [optional] keyword arguments (Hash object)
hashsp: [optional] hash splat arguments (Array of Hash object)
block:  [optional] block argument
ruruby/src/vm/executor/opt_core.rs