1use crate::ffi::{FfiCtx, FfiFactory};
6use crate::gc::{collect, GcContainer};
7use crate::objects::ClosureObj;
8use crate::stack::{RangeStack, Stack};
9use crate::value::*;
10use go_parser::Map;
11use std::cell::{Cell, RefCell};
12use std::cmp::Ordering;
13use std::rc::Rc;
14
15#[cfg(feature = "async")]
16use crate::channel;
17#[cfg(feature = "async")]
18use async_executor::LocalExecutor;
19#[cfg(feature = "async")]
20use futures_lite::future;
21
22macro_rules! restore_stack_ref {
24 ($self_:ident, $stack:ident, $stack_ref:ident) => {{
25 $stack_ref = $self_.stack.borrow_mut();
26 $stack = &mut $stack_ref;
27 }};
28}
29
30macro_rules! go_panic {
31 ($panic:ident, $msg:expr, $frame:ident, $code:ident) => {{
32 let mut data = PanicData::new($msg);
33 data.call_stack.push(($frame.func(), $frame.pc - 1));
34 $panic = Some(data);
35 $frame.pc = $code.len() as OpIndex - 1;
36 }};
37}
38
39macro_rules! go_panic_str {
40 ($panic:ident, $msg:expr, $frame:ident, $code:ident) => {{
41 let str_val = GosValue::with_str($msg);
42 let iface = GosValue::empty_iface_with_val(str_val);
43 go_panic!($panic, iface, $frame, $code);
44 }};
45}
46
47#[cfg(not(feature = "async"))]
48macro_rules! go_panic_no_async {
49 ($panic:ident, $frame:ident, $code:ident) => {{
50 go_panic_str!($panic, "Async features disabled", $frame, $code)
51 }};
52}
53
54macro_rules! panic_if_err {
55 ($result:expr, $panic:ident, $frame:ident, $code:ident) => {{
56 if let Err(e) = $result {
57 go_panic_str!($panic, e.as_str(), $frame, $code);
58 }
59 }};
60}
61
62#[cfg(feature = "async")]
63macro_rules! unwrap_recv_val {
64 ($chan:expr, $val:expr, $gcc:expr) => {
65 match $val {
66 Some(v) => (v, true),
67 None => ($chan.recv_zero.copy_semantic($gcc), false),
68 }
69 };
70}
71
72macro_rules! binary_op {
73 ($stack:expr, $op:tt, $inst:expr, $sb:expr, $consts:expr) => {{
74 let vdata = $stack
75 .read($inst.s0, $sb, $consts)
76 .data()
77 .$op($stack.read($inst.s1, $sb, $consts).data(), $inst.t0);
78 let val = GosValue::new($inst.t0, vdata);
79 $stack.set($inst.d + $sb, val);
80 }};
81}
82
83macro_rules! binary_op_assign {
84 ($stack:ident, $op:tt, $inst:expr, $sb:expr, $consts:expr) => {{
85 let right = unsafe { $stack.read($inst.s0, $sb, $consts).data().copy_non_ptr() };
86 let d = $stack.get_data_mut($inst.d + $sb);
87 *d = d.$op(&right, $inst.t0);
88 }};
89}
90
91macro_rules! shift_op {
92 ($stack:expr, $op:tt, $inst:expr, $sb:expr, $consts:expr) => {{
93 let right = $stack
94 .read($inst.s1, $sb, $consts)
95 .data()
96 .cast_copyable($inst.t1, ValueType::Uint32);
97 let vdata = $stack
98 .read($inst.s0, $sb, $consts)
99 .data()
100 .$op(right.as_uint32(), $inst.t0);
101 let val = GosValue::new($inst.t0, vdata);
102 $stack.set($inst.d + $sb, val);
103 }};
104}
105
106macro_rules! shift_op_assign {
107 ($stack:ident, $op:tt, $inst:expr, $sb:expr, $consts:expr) => {{
108 let right = $stack
109 .read($inst.s0, $sb, $consts)
110 .data()
111 .cast_copyable($inst.t1, ValueType::Uint32);
112 let d = $stack.get_data_mut($inst.d + $sb);
113 *d = d.$op(right.as_uint32(), $inst.t0);
114 }};
115}
116
117macro_rules! unary_op {
118 ($stack:expr, $op:tt, $inst:expr, $sb:expr, $consts:expr) => {{
119 let vdata = $stack.read($inst.s0, $sb, $consts).data().$op($inst.t0);
120 let val = GosValue::new($inst.t0, vdata);
121 $stack.set($inst.d + $sb, val);
122 }};
123}
124
125pub fn run(code: &Bytecode, ffi: &FfiFactory) -> Option<PanicData> {
127 let gcc = GcContainer::new();
128 let panic_data = Rc::new(RefCell::new(None));
129
130 #[cfg(not(feature = "async"))]
131 {
132 let ctx = Context::new(code, &gcc, ffi, panic_data.clone());
133 let first_frame = ctx.new_entry_frame(code.entry);
134 Fiber::new(ctx, Stack::new(), first_frame).main_loop();
135 }
136 #[cfg(feature = "async")]
137 {
138 let exec = Rc::new(LocalExecutor::new());
139 let ctx = Context::new(exec.clone(), code, &gcc, ffi, panic_data.clone());
140 let entry = ctx.new_entry_frame(code.entry);
141 ctx.spawn_fiber(Stack::new(), entry);
142 future::block_on(async {
143 loop {
144 if !exec.try_tick() {
145 break;
146 }
147 }
148 });
149 }
150 panic_data.replace(None)
151}
152
153#[derive(Clone, Debug)]
154struct Referers {
155 typ: ValueType,
156 weaks: Vec<WeakUpValue>,
157}
158
159#[derive(Clone, Debug)]
160struct CallFrame {
161 closure: ClosureObj,
162 pc: OpIndex,
163 stack_base: OpIndex,
164 var_ptrs: Option<Vec<UpValue>>,
165 referred_by: Option<Map<OpIndex, Referers>>,
167
168 defer_stack: Option<Vec<DeferredCall>>,
169}
170
171impl CallFrame {
172 fn with_closure(c: ClosureObj, sbase: OpIndex) -> CallFrame {
173 CallFrame {
174 closure: c,
175 pc: 0,
176 stack_base: sbase,
177 var_ptrs: None,
178 referred_by: None,
179 defer_stack: None,
180 }
181 }
182
183 fn add_referred_by(&mut self, index: OpIndex, typ: ValueType, uv: &UpValue) {
184 if self.referred_by.is_none() {
185 self.referred_by = Some(Map::new());
186 }
187 let map = self.referred_by.as_mut().unwrap();
188 let weak = uv.downgrade();
189 match map.get_mut(&index) {
190 Some(v) => {
191 debug_assert!(v.typ == typ);
192 v.weaks.push(weak);
193 }
194 None => {
195 map.insert(
196 index,
197 Referers {
198 typ: typ,
199 weaks: vec![weak],
200 },
201 );
202 }
203 }
204 }
205
206 #[inline]
207 fn func(&self) -> FunctionKey {
208 self.closure.as_gos().func
209 }
210
211 #[inline]
212 fn func_obj<'a>(&self, objs: &'a VMObjects) -> &'a FunctionObj {
213 let fkey = self.func();
214 &objs.functions[fkey]
215 }
216
217 #[inline]
218 fn on_drop(&mut self, stack: &Stack) {
219 if let Some(referred) = &self.referred_by {
220 for (ind, referrers) in referred {
221 if referrers.weaks.len() == 0 {
222 continue;
223 }
224 let val = stack.get(self.stack_base + *ind);
225 for weak in referrers.weaks.iter() {
226 if let Some(uv) = weak.upgrade() {
227 uv.close(val.clone());
228 }
229 }
230 }
231 }
232 }
233}
234
235#[derive(Clone, Debug)]
236struct DeferredCall {
237 frame: CallFrame,
238 vec: Vec<GosValue>,
239}
240
241#[derive(Debug)]
242enum Result {
243 Continue,
244 End,
245}
246
247#[derive(Debug)]
248pub struct PanicData {
249 pub msg: GosValue,
250 pub call_stack: Vec<(FunctionKey, OpIndex)>,
251}
252
253impl PanicData {
254 fn new(m: GosValue) -> PanicData {
255 PanicData {
256 msg: m,
257 call_stack: vec![],
258 }
259 }
260}
261
262#[derive(Clone)]
263struct Context<'a> {
264 #[cfg(feature = "async")]
265 exec: Rc<LocalExecutor<'a>>,
266 code: &'a Bytecode,
267 gcc: &'a GcContainer,
268 ffi_factory: &'a FfiFactory,
269 panic_data: Rc<RefCell<Option<PanicData>>>,
270 next_id: Cell<usize>,
271}
272
273impl<'a> Context<'a> {
274 fn new(
275 #[cfg(feature = "async")] exec: Rc<LocalExecutor<'a>>,
276 code: &'a Bytecode,
277 gcc: &'a GcContainer,
278 ffi_factory: &'a FfiFactory,
279 panic_data: Rc<RefCell<Option<PanicData>>>,
280 ) -> Context<'a> {
281 Context {
282 #[cfg(feature = "async")]
283 exec,
284 code,
285 gcc,
286 ffi_factory,
287 panic_data,
288 next_id: Cell::new(0),
289 }
290 }
291
292 fn new_entry_frame(&self, entry: FunctionKey) -> CallFrame {
293 let cls = ClosureObj::gos_from_func(entry, &self.code.objects.functions, None);
294 CallFrame::with_closure(cls, 0)
295 }
296
297 #[cfg(feature = "async")]
298 fn spawn_fiber(&self, stack: Stack, first_frame: CallFrame) {
299 let mut f = Fiber::new(self.clone(), stack, first_frame);
300 self.exec
301 .spawn(async move {
302 future::yield_now().await;
304 f.main_loop().await;
305 })
306 .detach();
307 }
308}
309
310struct Fiber<'a> {
311 stack: Rc<RefCell<Stack>>,
312 rstack: RangeStack,
313 frames: Vec<CallFrame>,
314 context: Context<'a>,
315 _id: usize,
316}
317
318impl<'a> Fiber<'a> {
319 pub fn _id(&self) -> usize {
320 self._id
321 }
322
323 fn new(context: Context<'a>, stack: Stack, first_frame: CallFrame) -> Fiber<'a> {
324 let _id = context.next_id.get();
325 context.next_id.set(_id + 1);
326 Fiber {
327 stack: Rc::new(RefCell::new(stack)),
328 rstack: RangeStack::new(),
329 frames: vec![first_frame],
330 context,
331 _id,
332 }
333 }
334
335 #[cfg_attr(feature = "async", go_pmacro::async_fn)]
336 fn main_loop(&mut self) {
337 let ctx = &self.context;
338 let gcc = ctx.gcc;
339 let objs: &VMObjects = &ctx.code.objects;
340 let caller: &ArrCaller = &objs.arr_slice_caller;
341 let consts = &ctx.code.consts;
342 let prim_meta: &PrimitiveMeta = &objs.prim_meta;
343 let ifaces = &ctx.code.ifaces;
344 let indices = &ctx.code.indices;
345 let mut frame_height = self.frames.len();
346 let fr = self.frames.last().unwrap();
347 let mut func = &objs.functions[fr.func()];
348 let mut sb = fr.stack_base;
349
350 let mut stack_mut_ref = self.stack.borrow_mut();
351 let mut stack: &mut Stack = &mut stack_mut_ref;
352 stack.set_vec(func.param_count(), func.local_zeros.clone());
354
355 let mut code = &func.code;
356
357 let mut total_inst = 0;
358 loop {
360 let mut frame = self.frames.last_mut().unwrap();
361 let mut result: Result = Result::Continue;
362 let mut panic: Option<PanicData> = None;
363 let yield_unit = 1024;
364 for _ in 0..yield_unit {
365 let inst = &code[frame.pc as usize];
366 let inst_op = inst.op0;
367 total_inst += 1;
368 frame.pc += 1;
370 match inst_op {
372 Opcode::DUPLICATE => {
375 stack.set(
377 sb + inst.d,
378 stack.read(inst.s0, sb, consts).copy_semantic(gcc),
379 )
380 }
381 Opcode::LOAD_SLICE => {
385 let slice = stack.read(inst.s0, sb, consts);
386 let index = stack.read(inst.s1, sb, consts).as_index();
387 match slice.slice_array_equivalent(index) {
388 Ok((array, i)) => match array.caller(caller).array_get(&array, i) {
389 Ok(val) => stack.set(sb + inst.d, val),
390 Err(e) => go_panic_str!(panic, e.as_str(), frame, code),
391 },
392 Err(e) => go_panic_str!(panic, e.as_str(), frame, code),
393 }
394 }
395 Opcode::STORE_SLICE => {
399 let dest = stack.read(inst.d, sb, consts);
400 let index = stack.read(inst.s0, sb, consts).as_index();
401 match dest.slice_array_equivalent(index) {
402 Ok((array, i)) => match inst.op1 {
403 Opcode::VOID => {
404 let val = stack.read(inst.s1, sb, consts).copy_semantic(gcc);
405 let result = array.caller(caller).array_set(&array, &val, i);
406 panic_if_err!(result, panic, frame, code);
407 }
408 _ => match array.caller(caller).array_get(&array, i) {
409 Ok(old) => {
410 let val = stack.read_and_op(
411 old.data(),
412 inst.t0,
413 inst.op1,
414 inst.s1,
415 sb,
416 &consts,
417 );
418 let result =
419 array.caller(caller).array_set(&array, &val, i);
420 panic_if_err!(result, panic, frame, code);
421 }
422 Err(e) => go_panic_str!(panic, e.as_str(), frame, code),
423 },
424 },
425 Err(e) => go_panic_str!(panic, e.as_str(), frame, code),
426 }
427 }
428 Opcode::LOAD_ARRAY => {
432 let array = stack.read(inst.s0, sb, consts);
433 let index = stack.read(inst.s1, sb, consts).as_index();
434 match array.caller(caller).array_get(&array, index) {
435 Ok(val) => stack.set(inst.d + sb, val),
436 Err(e) => go_panic_str!(panic, e.as_str(), frame, code),
437 }
438 }
439 Opcode::STORE_ARRAY => {
443 let array = stack.read(inst.d, sb, consts);
444 let index = stack.read(inst.s0, sb, consts).as_index();
445 match inst.op1 {
446 Opcode::VOID => {
447 let val = stack.read(inst.s1, sb, consts).copy_semantic(gcc);
448 let result = array.caller(caller).array_set(&array, &val, index);
449 panic_if_err!(result, panic, frame, code);
450 }
451 _ => match array.caller(caller).array_get(&array, index) {
452 Ok(old) => {
453 let val = stack.read_and_op(
454 old.data(),
455 inst.t0,
456 inst.op1,
457 inst.s1,
458 sb,
459 &consts,
460 );
461 let result =
462 array.caller(caller).array_set(&array, &val, index);
463 panic_if_err!(result, panic, frame, code);
464 }
465 Err(e) => go_panic_str!(panic, e.as_str(), frame, code),
466 },
467 }
468 }
469 Opcode::LOAD_MAP => {
475 let inst_ex = &code[frame.pc as usize];
476 frame.pc += 1;
477 let map = stack.read(inst.s0, sb, consts);
478 let key = stack.read(inst.s1, sb, consts);
479 let val = match map.as_map() {
480 Some(map) => map.0.get(&key),
481 None => None,
482 };
483 let (v, ok) = match val {
484 Some(v) => (v, true),
485 None => (stack.read(inst_ex.s0, sb, consts).copy_semantic(gcc), false),
486 };
487 stack.set(inst.d + sb, v);
488 if inst.t1 == ValueType::FlagB {
489 stack.set(inst_ex.d + sb, ok.into());
490 }
491 }
492 Opcode::STORE_MAP => {
497 let inst_ex = &code[frame.pc as usize];
498 frame.pc += 1;
499 let dest = stack.read(inst.d, sb, consts);
500 match dest.as_non_nil_map() {
501 Ok(map) => {
502 let key = stack.read(inst.s0, sb, consts);
503 match inst.op1 {
504 Opcode::VOID => {
505 let val =
506 stack.read(inst.s1, sb, consts).copy_semantic(gcc);
507 map.0.insert(key.clone(), val);
508 }
509 _ => {
510 let old = match map.0.get(&key) {
511 Some(v) => v,
512 None => stack.read(inst_ex.s0, sb, consts).clone(),
513 };
514 let val = stack.read_and_op(
515 old.data(),
516 inst.t0,
517 inst.op1,
518 inst.s1,
519 sb,
520 &consts,
521 );
522 map.0.insert(key.clone(), val);
523 }
524 }
525 }
526 Err(e) => go_panic_str!(panic, e.as_str(), frame, code),
527 }
528 }
529 Opcode::LOAD_STRUCT => {
533 let struct_ = stack.read(inst.s0, sb, consts);
534 let val = struct_.as_struct().0.borrow_fields()[inst.s1 as usize].clone();
535 stack.set(inst.d + sb, val);
536 }
537 Opcode::STORE_STRUCT => {
541 let dest = stack.read(inst.d, sb, consts);
542 match inst.op1 {
543 Opcode::VOID => {
544 let val = stack.read(inst.s1, sb, consts).copy_semantic(gcc);
545 dest.as_struct().0.borrow_fields_mut()[inst.s0 as usize] = val;
546 }
547 _ => {
548 let old =
549 &mut dest.as_struct().0.borrow_fields_mut()[inst.s0 as usize];
550 let val = stack.read_and_op(
551 old.data(),
552 inst.t0,
553 inst.op1,
554 inst.s1,
555 sb,
556 &consts,
557 );
558 *old = val;
559 }
560 }
561 }
562 Opcode::LOAD_EMBEDDED => {
566 let src = stack.read(inst.s0, sb, consts);
567 let (struct_, index) = get_struct_and_index(
568 src.clone(),
569 &indices[inst.s1 as usize],
570 stack,
571 objs,
572 );
573 match struct_ {
574 Ok(s) => {
575 let val = s.as_struct().0.borrow_fields()[index].clone();
576 stack.set(inst.d + sb, val);
577 }
578 Err(e) => go_panic_str!(panic, e.as_str(), frame, code),
579 }
580 }
581 Opcode::STORE_EMBEDDED => {
585 let dest = stack.read(inst.d, sb, consts);
586 let (struct_, index) = get_struct_and_index(
587 dest.clone(),
588 &indices[inst.s0 as usize],
589 stack,
590 objs,
591 );
592 match struct_ {
593 Ok(s) => match inst.op1 {
594 Opcode::VOID => {
595 let val = stack.read(inst.s1, sb, consts).copy_semantic(gcc);
596 s.as_struct().0.borrow_fields_mut()[index] = val;
597 }
598 _ => {
599 let old = &s.as_struct().0.borrow_fields()[index as usize];
600 let val = stack.read_and_op(
601 old.data(),
602 inst.t0,
603 inst.op1,
604 inst.s1,
605 sb,
606 &consts,
607 );
608 s.as_struct().0.borrow_fields_mut()[index as usize] = val;
609 }
610 },
611 Err(e) => go_panic_str!(panic, e.as_str(), frame, code),
612 }
613 }
614 Opcode::LOAD_PKG => {
618 let src = stack.read(inst.s0, sb, consts);
619 let index = inst.s1;
620 let pkg = &objs.packages[*src.as_package()];
621 let val = pkg.member(index).clone();
622 stack.set(inst.d + sb, val);
623 }
624 Opcode::STORE_PKG => {
628 let dest = stack.read(inst.d, sb, consts);
629 let index = inst.s0;
630
631 let pkg = &objs.packages[*dest.as_package()];
632 match inst.op1 {
633 Opcode::VOID => {
634 let val = stack.read(inst.s1, sb, consts).copy_semantic(gcc);
635 *pkg.member_mut(index) = val;
636 }
637 _ => {
638 let mut old = pkg.member_mut(index);
639 let val = stack.read_and_op(
640 old.data(),
641 inst.t0,
642 inst.op1,
643 inst.s1,
644 sb,
645 &consts,
646 );
647 *old = val;
648 }
649 }
650 }
651 Opcode::LOAD_POINTER => {
654 let src = stack.read(inst.s0, sb, consts);
655 match src.as_non_nil_pointer() {
656 Ok(p) => match p.deref(stack, &objs.packages) {
657 Ok(val) => stack.set(inst.d + sb, val),
658 Err(e) => go_panic_str!(panic, e.as_str(), frame, code),
659 },
660 Err(e) => go_panic_str!(panic, e.as_str(), frame, code),
661 }
662 }
663 Opcode::STORE_POINTER => {
666 let dest = stack.read(inst.d, sb, consts).clone();
667 let result = dest.as_non_nil_pointer().and_then(|p| {
668 let val = match inst.op1 {
669 Opcode::VOID => stack.read(inst.s0, sb, consts).copy_semantic(gcc),
670 _ => {
671 let old = p.deref(stack, &objs.packages)?;
672 stack.read_and_op(
673 old.data(),
674 inst.t0,
675 inst.op1,
676 inst.s0,
677 sb,
678 &consts,
679 )
680 }
681 };
682 match p {
683 PointerObj::UpVal(uv) => {
684 uv.set_value(val, stack);
685 Ok(())
686 }
687 PointerObj::SliceMember(s, index) => {
688 let index = *index as usize;
689 let (array, index) = s.slice_array_equivalent(index)?;
690 array.caller(caller).array_set(&array, &val, index)
691 }
692 PointerObj::StructField(s, index) => {
693 s.as_struct().0.borrow_fields_mut()[*index as usize] = val;
694 Ok(())
695 }
696 PointerObj::PkgMember(p, index) => {
697 let pkg = &objs.packages[*p];
698 *pkg.member_mut(*index) = val;
699 Ok(())
700 }
701 }
702 });
703 panic_if_err!(result, panic, frame, code);
704 }
705 Opcode::LOAD_UP_VALUE => {
708 let uvs = frame.var_ptrs.as_ref().unwrap();
709 let val = uvs[inst.s0 as usize].value(stack).into_owned();
710 stack.set(inst.d + sb, val);
711 }
712 Opcode::STORE_UP_VALUE => {
713 let uvs = frame.var_ptrs.as_ref().unwrap();
714 let uv = &uvs[inst.d as usize];
715 match inst.op1 {
716 Opcode::VOID => {
717 let val = stack.read(inst.s0, sb, consts).copy_semantic(gcc);
718 uv.set_value(val, stack);
719 }
720 _ => {
721 let old = uv.value(stack);
722 let val = stack.read_and_op(
723 old.data(),
724 inst.t0,
725 inst.op1,
726 inst.s0,
727 sb,
728 &consts,
729 );
730 uv.set_value(val, stack);
731 }
732 }
733 }
734 Opcode::ADD => binary_op!(stack, binary_op_add, inst, sb, consts),
735 Opcode::SUB => binary_op!(stack, binary_op_sub, inst, sb, consts),
736 Opcode::MUL => binary_op!(stack, binary_op_mul, inst, sb, consts),
737 Opcode::QUO => binary_op!(stack, binary_op_quo, inst, sb, consts),
738 Opcode::REM => binary_op!(stack, binary_op_rem, inst, sb, consts),
739 Opcode::AND => binary_op!(stack, binary_op_and, inst, sb, consts),
740 Opcode::OR => binary_op!(stack, binary_op_or, inst, sb, consts),
741 Opcode::XOR => binary_op!(stack, binary_op_xor, inst, sb, consts),
742 Opcode::AND_NOT => binary_op!(stack, binary_op_and_not, inst, sb, consts),
743 Opcode::SHL => shift_op!(stack, binary_op_shl, inst, sb, consts),
744 Opcode::SHR => shift_op!(stack, binary_op_shr, inst, sb, consts),
745 Opcode::ADD_ASSIGN => binary_op_assign!(stack, binary_op_add, inst, sb, consts),
746 Opcode::SUB_ASSIGN => binary_op_assign!(stack, binary_op_sub, inst, sb, consts),
747 Opcode::MUL_ASSIGN => binary_op_assign!(stack, binary_op_mul, inst, sb, consts),
748 Opcode::QUO_ASSIGN => binary_op_assign!(stack, binary_op_quo, inst, sb, consts),
749 Opcode::REM_ASSIGN => binary_op_assign!(stack, binary_op_rem, inst, sb, consts),
750 Opcode::AND_ASSIGN => binary_op_assign!(stack, binary_op_and, inst, sb, consts),
751 Opcode::OR_ASSIGN => binary_op_assign!(stack, binary_op_or, inst, sb, consts),
752 Opcode::XOR_ASSIGN => binary_op_assign!(stack, binary_op_xor, inst, sb, consts),
753 Opcode::AND_NOT_ASSIGN => {
754 binary_op_assign!(stack, binary_op_and_not, inst, sb, consts)
755 }
756 Opcode::SHL_ASSIGN => shift_op_assign!(stack, binary_op_shl, inst, sb, consts),
757 Opcode::SHR_ASSIGN => shift_op_assign!(stack, binary_op_shr, inst, sb, consts),
758 Opcode::INC => unsafe {
759 let v = stack.get_mut(inst.d + sb).data_mut();
760 *v = v.inc(inst.t0);
761 },
762 Opcode::DEC => unsafe {
763 let v = stack.get_mut(inst.d + sb).data_mut();
764 *v = v.dec(inst.t0);
765 },
766 Opcode::UNARY_SUB => unary_op!(stack, unary_negate, inst, sb, consts),
767 Opcode::UNARY_XOR => unary_op!(stack, unary_xor, inst, sb, consts),
768 Opcode::NOT => unary_op!(stack, logical_not, inst, sb, consts),
769 Opcode::EQL => {
770 let a = stack.read(inst.s0, sb, consts);
771 let b = stack.read(inst.s1, sb, consts);
772 let eq = if inst.t0.copyable() && inst.t0 == inst.t1 {
773 a.data().compare_eql(b.data(), inst.t0)
774 } else {
775 a.eq(b)
776 };
777 stack.set(inst.d + sb, eq.into());
778 }
779 Opcode::NEQ => {
780 let a = stack.read(inst.s0, sb, consts);
781 let b = stack.read(inst.s1, sb, consts);
782 let neq = if inst.t0.copyable() {
783 a.data().compare_neq(b.data(), inst.t0)
784 } else {
785 !a.eq(b)
786 };
787 stack.set(inst.d + sb, neq.into());
788 }
789 Opcode::LSS => {
790 let a = stack.read(inst.s0, sb, consts);
791 let b = stack.read(inst.s1, sb, consts);
792 let lss = if inst.t0.copyable() {
793 a.data().compare_lss(b.data(), inst.t0)
794 } else {
795 a.cmp(b) == Ordering::Less
796 };
797 stack.set(inst.d + sb, lss.into());
798 }
799 Opcode::GTR => {
800 let a = stack.read(inst.s0, sb, consts);
801 let b = stack.read(inst.s1, sb, consts);
802 let gtr = if inst.t0.copyable() {
803 a.data().compare_gtr(b.data(), inst.t0)
804 } else {
805 a.cmp(b) == Ordering::Greater
806 };
807 stack.set(inst.d + sb, gtr.into());
808 }
809 Opcode::LEQ => {
810 let a = stack.read(inst.s0, sb, consts);
811 let b = stack.read(inst.s1, sb, consts);
812 let leq = if inst.t0.copyable() {
813 a.data().compare_leq(b.data(), inst.t0)
814 } else {
815 a.cmp(b) != Ordering::Greater
816 };
817 stack.set(inst.d + sb, leq.into());
818 }
819 Opcode::GEQ => {
820 let a = stack.read(inst.s0, sb, consts);
821 let b = stack.read(inst.s1, sb, consts);
822 let geq = if inst.t0.copyable() {
823 a.data().compare_geq(b.data(), inst.t0)
824 } else {
825 a.cmp(b) != Ordering::Less
826 };
827 stack.set(inst.d + sb, geq.into());
828 }
829 Opcode::REF => {
830 let val = stack.read(inst.s0, sb, consts);
831 let boxed = PointerObj::new_closed_up_value(&val);
832 stack.set(inst.d + sb, GosValue::new_pointer(boxed));
833 }
834 Opcode::REF_UPVALUE => {
835 let uvs = frame.var_ptrs.as_ref().unwrap();
836 let upvalue = uvs[inst.s0 as usize].clone();
837 stack.set(
838 inst.d + sb,
839 GosValue::new_pointer(PointerObj::UpVal(upvalue.clone())),
840 );
841 }
842 Opcode::REF_SLICE_MEMBER => {
843 let arr_or_slice = stack.read(inst.s0, sb, consts).clone();
844 let index = stack.read(inst.s1, sb, consts).as_index() as OpIndex;
845 match PointerObj::new_slice_member_internal(
846 arr_or_slice,
847 index,
848 inst.t0,
849 caller.get(inst.t1),
850 ) {
851 Ok(p) => stack.set(inst.d + sb, GosValue::new_pointer(p)),
852 Err(e) => {
853 go_panic_str!(panic, e.as_str(), frame, code)
854 }
855 }
856 }
857 Opcode::REF_STRUCT_FIELD => {
858 let struct_ = stack.read(inst.s0, sb, consts).clone();
859 stack.set(
860 inst.d + sb,
861 GosValue::new_pointer(PointerObj::StructField(struct_, inst.s1)),
862 );
863 }
864 Opcode::REF_EMBEDDED => {
865 let src = stack.read(inst.s0, sb, consts);
866 let (struct_, index) = get_struct_and_index(
867 src.clone(),
868 &indices[inst.s1 as usize],
869 stack,
870 objs,
871 );
872 match struct_ {
873 Ok(target) => {
874 stack.set(
875 inst.d + sb,
876 GosValue::new_pointer(PointerObj::StructField(
877 target,
878 index as OpIndex,
879 )),
880 );
881 }
882 Err(e) => go_panic_str!(panic, e.as_str(), frame, code),
883 }
884 }
885 Opcode::REF_PKG_MEMBER => {
886 let pkg = *stack.read(inst.s0, sb, consts).as_package();
887 stack.set(
888 inst.d + sb,
889 GosValue::new_pointer(PointerObj::PkgMember(pkg, inst.s1)),
890 );
891 }
892 #[cfg(not(feature = "async"))]
893 Opcode::SEND => go_panic_no_async!(panic, frame, code),
894 #[cfg(feature = "async")]
895 Opcode::SEND => {
896 let chan = stack.read(inst.s0, sb, consts).as_channel().cloned();
897 let val = stack.read(inst.s1, sb, consts).clone();
898 drop(stack_mut_ref);
899 let re = match chan {
900 Some(c) => c.send(&val).await,
901 None => loop {
902 future::yield_now().await;
903 },
904 };
905 restore_stack_ref!(self, stack, stack_mut_ref);
906 panic_if_err!(re, panic, frame, code);
907 }
908 #[cfg(not(feature = "async"))]
909 Opcode::RECV => go_panic_no_async!(panic, frame, code),
910 #[cfg(feature = "async")]
911 Opcode::RECV => {
912 match stack.read(inst.s0, sb, consts).as_channel().cloned() {
913 Some(chan) => {
914 drop(stack_mut_ref);
915 let val = chan.recv().await;
916 restore_stack_ref!(self, stack, stack_mut_ref);
917 let (unwrapped, ok) = unwrap_recv_val!(chan, val, gcc);
918 stack.set(inst.d + sb, unwrapped);
919 if inst.t1 == ValueType::FlagB {
920 stack.set(inst.s1 + sb, ok.into());
921 }
922 }
923 None => loop {
924 future::yield_now().await;
925 },
926 };
927 }
928 Opcode::PACK_VARIADIC => {
929 let v = stack.move_vec(inst.s0 + sb, inst.s1 + sb);
930 let val = GosValue::slice_with_data(v, caller.get(inst.t0), gcc);
931 stack.set(inst.d + sb, val);
932 }
933 Opcode::CALL => {
937 let call_style = inst.t0;
938 let cls = stack
939 .read(inst.d, sb, consts)
940 .as_closure()
941 .unwrap()
942 .0
943 .clone();
944 let next_sb = sb + inst.s0;
945 match &cls {
946 ClosureObj::Gos(gosc) => {
947 let next_func = &objs.functions[gosc.func];
948 let mut returns_recv = next_func.ret_zeros.clone();
949 if let Some(r) = &gosc.recv {
950 returns_recv.push(r.clone());
953 }
954 stack.set_min_size(
955 (next_sb + next_func.max_write_index + 1) as usize,
956 );
957 stack.set_vec(next_sb, returns_recv);
958 }
959 _ => {}
960 }
961 let mut nframe = CallFrame::with_closure(cls.clone(), next_sb);
962
963 match cls {
964 ClosureObj::Gos(gosc) => {
965 let nfunc = &objs.functions[gosc.func];
966 if let Some(uvs) = gosc.uvs {
967 let mut ptrs: Vec<UpValue> =
968 Vec::with_capacity(nfunc.up_ptrs.len());
969 for (i, p) in nfunc.up_ptrs.iter().enumerate() {
970 ptrs.push(if p.is_local {
971 let uv = UpValue::new(p.clone_with_stack(
973 Rc::downgrade(&self.stack),
974 nframe.stack_base as OpIndex,
975 ));
976 nframe.add_referred_by(p.index, p.typ, &uv);
977 uv
978 } else {
979 uvs[&i].clone()
980 });
981 }
982 nframe.var_ptrs = Some(ptrs);
983 }
984 match call_style {
985 ValueType::FlagA => {
986 self.frames.push(nframe);
988 frame_height += 1;
989 frame = self.frames.last_mut().unwrap();
990 func = nfunc;
991 sb = frame.stack_base;
992 code = &func.code;
993 }
995 #[cfg(not(feature = "async"))]
996 ValueType::FlagB => go_panic_no_async!(panic, frame, code),
997 #[cfg(feature = "async")]
998 ValueType::FlagB => {
999 let begin = nframe.stack_base;
1001 let end = begin
1002 + nfunc.ret_count()
1003 + nfunc.param_count() as OpIndex;
1004 let vec = stack.move_vec(begin, end);
1005 let nstack = Stack::with_vec(vec);
1006 nframe.stack_base = 0;
1007 self.context.spawn_fiber(nstack, nframe);
1008 }
1009 ValueType::FlagC => {
1010 let begin = nframe.stack_base;
1012 let end = begin
1013 + nfunc.ret_count()
1014 + nfunc.param_count() as OpIndex;
1015 let vec = stack.move_vec(begin, end);
1016 let deferred = DeferredCall {
1017 frame: nframe,
1018 vec: vec,
1019 };
1020 frame.defer_stack.get_or_insert(vec![]).push(deferred);
1021 }
1022 _ => unreachable!(),
1023 }
1024 }
1025 ClosureObj::Ffi(ffic) => {
1026 let sig = objs.metas[ffic.meta.key].as_signature();
1027 let result_begin = nframe.stack_base;
1028 let param_begin = result_begin + 1 + sig.results.len() as OpIndex;
1029 let end = param_begin + sig.params.len() as OpIndex;
1030 let params = stack.move_vec(param_begin, end);
1031 drop(stack_mut_ref);
1033 let returns = {
1034 let mut ctx = FfiCtx {
1035 func_name: &ffic.func_name,
1036 vm_objs: objs,
1037 user_data: ctx.ffi_factory.user_data(),
1038 stack: &mut self.stack.borrow_mut(),
1039 gcc,
1040 array_slice_caller: caller,
1041 };
1042 if !ffic.is_async {
1043 ffic.ffi.call(&mut ctx, params)
1044 } else {
1045 #[cfg(not(feature = "async"))]
1046 {
1047 Err("Async features disabled".to_owned().into())
1048 }
1049 #[cfg(feature = "async")]
1050 ffic.ffi.async_call(&mut ctx, params).await
1051 }
1052 };
1053 restore_stack_ref!(self, stack, stack_mut_ref);
1054 match returns {
1055 Ok(result) => stack.set_vec(result_begin, result),
1056 Err(e) => {
1057 go_panic_str!(panic, e.as_str(), frame, code);
1058 }
1059 }
1060 }
1061 }
1062 }
1063 Opcode::RETURN => {
1064 let clear_stack = match inst.t0 {
1070 ValueType::FlagA => true,
1072 ValueType::FlagB => {
1074 let pkey = stack.read(inst.d, sb, consts).as_package();
1075 let pkg = &objs.packages[*pkey];
1076 let func = frame.func_obj(objs);
1078 let begin = sb;
1079 let end = begin + func.local_count();
1080 pkg.init_vars(stack.move_vec(begin, end));
1081 false
1082 }
1083 ValueType::FlagC => {
1085 if let Some(call) =
1086 frame.defer_stack.as_mut().map(|x| x.pop()).flatten()
1087 {
1088 frame.pc -= 1;
1090
1091 let call_vec_len = call.vec.len() as OpIndex;
1092 let cur_func = frame.func_obj(objs);
1093 let new_sb = sb
1095 + cur_func.ret_count()
1096 + cur_func.param_count()
1097 + cur_func.local_count();
1098 stack.set_vec(new_sb, call.vec);
1099 let nframe = call.frame;
1100
1101 self.frames.push(nframe);
1102 frame_height += 1;
1103 frame = self.frames.last_mut().unwrap();
1104 frame.stack_base = new_sb; let fkey = frame.func();
1106 func = &objs.functions[fkey];
1107 sb = frame.stack_base;
1108 code = &func.code;
1109 let index = new_sb + call_vec_len;
1111 stack.set_vec(index, func.local_zeros.clone());
1112 continue;
1113 }
1114 true
1115 }
1116 _ => unreachable!(),
1117 };
1118
1119 if clear_stack {
1120 frame.on_drop(&stack);
1128 let func = frame.func_obj(objs);
1129 let begin = sb + func.ret_count() as OpIndex;
1130 let end = begin + func.param_count() + func.local_count();
1131 stack.move_vec(begin, end);
1132 }
1133
1134 self.frames.pop();
1137 frame_height -= 1;
1138 if self.frames.is_empty() {
1139 dbg!(total_inst);
1140
1141 result = Result::End;
1142 break;
1143 }
1144 frame = self.frames.last_mut().unwrap();
1145 sb = frame.stack_base;
1146 func = &objs.functions[frame.func()];
1148 code = &func.code;
1149
1150 if let Some(p) = &mut panic {
1151 p.call_stack.push((frame.func(), frame.pc - 1));
1152 frame.pc = code.len() as OpIndex - 1;
1153 }
1154 }
1155 Opcode::JUMP => frame.pc += inst.d,
1156 Opcode::JUMP_IF => {
1157 if *stack.read(inst.s0, sb, consts).as_bool() {
1158 frame.pc += inst.d;
1159 }
1160 }
1161 Opcode::JUMP_IF_NOT => {
1162 if !*stack.read(inst.s0, sb, consts).as_bool() {
1163 frame.pc += inst.d;
1164 }
1165 }
1166 Opcode::SWITCH => {
1167 let t = inst.t0;
1168 let a = stack.read(inst.s0, sb, consts);
1169 let b = stack.read(inst.s1, sb, consts);
1170 let ok = if t.copyable() {
1171 a.data().compare_eql(b.data(), t)
1172 } else if t != ValueType::Metadata {
1173 a.eq(&b)
1174 } else {
1175 a.as_metadata().identical(b.as_metadata(), &objs.metas)
1176 };
1177 if ok {
1178 frame.pc += inst.d;
1179 }
1180 }
1181 #[cfg(not(feature = "async"))]
1182 Opcode::SELECT => go_panic_no_async!(panic, frame, code),
1183 #[cfg(feature = "async")]
1184 Opcode::SELECT => {
1185 let comm_count = inst.s0;
1186 let has_default = inst.t0 == ValueType::FlagE;
1187 let default_offset = has_default.then_some(inst.d);
1188 let mut comms = Vec::with_capacity(comm_count as usize);
1189 for _ in 0..comm_count {
1190 let entry = &code[frame.pc as usize];
1191 frame.pc += 1;
1192 let chan = stack.read(entry.s0, sb, consts).clone();
1193 let offset = entry.d;
1194 let flag = entry.t0;
1195 let typ = match &flag {
1196 ValueType::FlagA => {
1197 let val = stack.read(entry.s1, sb, consts).copy_semantic(gcc);
1198 channel::SelectCommType::Send(val)
1199 }
1200 ValueType::FlagB | ValueType::FlagC | ValueType::FlagD => {
1201 channel::SelectCommType::Recv(flag, entry.s1)
1202 }
1203 _ => unreachable!(),
1204 };
1205 comms.push(channel::SelectComm { typ, chan, offset });
1206 }
1207 let selector = channel::Selector::new(comms, default_offset);
1208
1209 drop(stack_mut_ref);
1210 let re = selector.select().await;
1211 restore_stack_ref!(self, stack, stack_mut_ref);
1212
1213 match re {
1214 Ok((i, val)) => {
1215 let block_offset = if i >= selector.comms.len() {
1216 selector.default_offset.unwrap()
1217 } else {
1218 let comm = &selector.comms[i];
1219 match comm.typ {
1220 channel::SelectCommType::Send(_) => {}
1221 channel::SelectCommType::Recv(flag, dst) => {
1222 let (unwrapped, ok) = unwrap_recv_val!(
1223 comm.chan.as_channel().as_ref().unwrap(),
1224 val,
1225 gcc
1226 );
1227 match flag {
1228 ValueType::FlagC => {
1229 stack.set(dst + sb, unwrapped);
1230 }
1231 ValueType::FlagD => {
1232 stack.set(dst + sb, unwrapped);
1233 stack.set(dst + 1 + sb, ok.into());
1234 }
1235 _ => {}
1236 }
1237 }
1238 }
1239 comm.offset
1240 };
1241 frame.pc += block_offset;
1243 }
1244 Err(e) => {
1245 go_panic_str!(panic, e.as_str(), frame, code);
1246 }
1247 }
1248 }
1249 Opcode::RANGE_INIT => {
1250 let target = stack.read(inst.s0, sb, consts);
1251 let re = self.rstack.range_init(target, inst.t0, caller.get(inst.t1));
1252 panic_if_err!(re, panic, frame, code);
1253 }
1254 Opcode::RANGE => {
1255 if self.rstack.range_body(
1256 inst.t0,
1257 caller.get(inst.t1),
1258 stack,
1259 inst.d + sb,
1260 inst.s1 + sb,
1261 ) {
1262 frame.pc += inst.s0;
1263 }
1264 }
1265 Opcode::LOAD_INIT_FUNC => {
1267 let src = stack.read(inst.s0, sb, consts);
1268 let index = *stack.read(inst.s1, sb, consts).as_int32();
1269 let pkg = &objs.packages[*src.as_package()];
1270 match pkg.init_func(index) {
1271 Some(f) => {
1272 stack.set(inst.d + sb, f.clone());
1273 stack.set(inst.s1 + sb, (index + 1).into());
1274 }
1275 None => {
1276 frame.pc += 2;
1277 }
1278 }
1279 }
1280 Opcode::BIND_METHOD => {
1281 let recv = stack.read(inst.s0, sb, consts).copy_semantic(gcc);
1282 let func = *stack.read(inst.s1, sb, consts).as_function();
1283 stack.set(
1284 inst.d + sb,
1285 GosValue::new_closure(
1286 ClosureObj::gos_from_func(func, &objs.functions, Some(recv)),
1287 gcc,
1288 ),
1289 );
1290 }
1291 Opcode::BIND_I_METHOD => {
1292 match stack.read(inst.s0, sb, consts).as_non_nil_interface() {
1293 Ok(iface) => {
1294 match bind_iface_method(iface, inst.s1 as usize, stack, objs, gcc) {
1295 Ok(cls) => stack.set(inst.d + sb, cls),
1296 Err(e) => go_panic_str!(panic, e.as_str(), frame, code),
1297 }
1298 }
1299 Err(e) => go_panic_str!(panic, e.as_str(), frame, code),
1300 }
1301 }
1302 Opcode::CAST => {
1303 let from_type = inst.t1;
1304 let to_type = inst.t0;
1305 let val = match to_type {
1306 ValueType::UintPtr => match from_type {
1307 ValueType::UnsafePtr => {
1308 let up =
1309 stack.read(inst.s0, sb, consts).as_unsafe_ptr().cloned();
1310 GosValue::new_uint_ptr(
1311 up.map_or(0, |x| x.as_rust_ptr() as *const () as usize),
1312 )
1313 }
1314 _ => stack
1315 .read(inst.s0, sb, consts)
1316 .cast_copyable(from_type, to_type),
1317 },
1318 _ if to_type.copyable() => stack
1319 .read(inst.s0, sb, consts)
1320 .cast_copyable(from_type, to_type),
1321 ValueType::Interface => {
1322 let binding = ifaces[inst.s1 as usize].clone();
1323 let under = stack.read(inst.s0, sb, consts).copy_semantic(gcc);
1324 GosValue::new_interface(InterfaceObj::with_value(
1325 under,
1326 Some(binding),
1327 ))
1328 }
1329 ValueType::String => match from_type {
1330 ValueType::Slice => match inst.op1_as_t() {
1331 ValueType::Int32 => {
1332 let s = match stack
1333 .read(inst.s0, sb, consts)
1334 .as_slice::<Elem32>()
1335 {
1336 Some(slice) => slice
1337 .0
1338 .as_rust_slice()
1339 .iter()
1340 .map(|x| char_from_i32(x.cell.get() as i32))
1341 .collect(),
1342 None => "".to_owned(),
1343 };
1344 GosValue::with_str(&s)
1345 }
1346 ValueType::Uint8 => {
1347 match stack.read(inst.s0, sb, consts).as_slice::<Elem8>() {
1348 Some(slice) => GosValue::new_string(slice.0.clone()),
1349 None => GosValue::with_str(""),
1350 }
1351 }
1352 _ => unreachable!(),
1353 },
1354 _ => {
1355 let val = stack
1356 .read(inst.s0, sb, consts)
1357 .cast_copyable(from_type, ValueType::Uint32);
1358 GosValue::with_str(&char_from_u32(*val.as_uint32()).to_string())
1359 }
1360 },
1361 ValueType::Slice => {
1362 let from = stack.read(inst.s0, sb, consts).as_string();
1363 match inst.op1_as_t() {
1364 ValueType::Int32 => {
1365 let data = from
1366 .as_str()
1367 .chars()
1368 .map(|x| (x as i32).into())
1369 .collect();
1370 GosValue::slice_with_data(
1371 data,
1372 caller.get(inst.op1_as_t()),
1373 gcc,
1374 )
1375 }
1376 ValueType::Uint8 => {
1377 GosValue::new_slice(from.clone(), ValueType::Uint8)
1378 }
1379 _ => unreachable!(),
1380 }
1381 }
1382 ValueType::Pointer => match from_type {
1383 ValueType::Pointer => stack.read(inst.s0, sb, consts).clone(),
1384 ValueType::UnsafePtr => {
1385 match stack.read(inst.s0, sb, consts).as_unsafe_ptr() {
1386 Some(p) => {
1387 match p.ptr().as_any().downcast_ref::<PointerHandle>() {
1388 Some(h) => {
1389 match h.ptr().cast(
1390 inst.op1_as_t(),
1391 &stack,
1392 &objs.packages,
1393 ) {
1394 Ok(p) => GosValue::new_pointer(p),
1395 Err(e) => {
1396 go_panic_str!(
1397 panic,
1398 e.as_str(),
1399 frame,
1400 code
1401 );
1402 continue;
1403 }
1404 }
1405 }
1406 None => {
1407 go_panic_str!(panic, "only a unsafe-pointer cast from a pointer can be cast back to a pointer", frame, code);
1408 continue;
1409 }
1410 }
1411 }
1412 None => GosValue::new_nil(ValueType::Pointer),
1413 }
1414 }
1415 _ => unimplemented!(),
1416 },
1417 ValueType::UnsafePtr => match from_type {
1418 ValueType::Pointer => {
1419 PointerHandle::new(stack.read(inst.s0, sb, consts))
1420 }
1421 _ => unimplemented!(),
1422 },
1423 _ => {
1424 dbg!(to_type);
1425 unimplemented!()
1426 }
1427 };
1428 stack.set(inst.d + sb, val);
1429 }
1430 Opcode::TYPE_ASSERT => {
1431 let val = stack.read(inst.s0, sb, consts);
1432 match type_assert(val, cst(consts, inst.s1), gcc, &objs.metas) {
1433 Ok((val, ok)) => {
1434 stack.set(inst.d + sb, val);
1435 if inst.t1 == ValueType::FlagB {
1436 let inst_ex = &code[frame.pc as usize];
1437 frame.pc += 1;
1438 stack.set(inst_ex.d + sb, ok.into());
1439 }
1440 }
1441 Err(e) => go_panic_str!(panic, e.as_str(), frame, code),
1442 }
1443 }
1444 Opcode::TYPE => {
1445 let iface_value = stack.read(inst.s0, sb, consts).clone();
1446 if inst.t0 != ValueType::FlagA {
1447 let meta = match iface_value.as_interface() {
1448 Some(iface) => match &iface as &InterfaceObj {
1449 InterfaceObj::Gos(_, b) => b.as_ref().unwrap().0,
1450 _ => prim_meta.none,
1451 },
1452 _ => prim_meta.none,
1453 };
1454 stack.set(inst.d + sb, GosValue::new_metadata(meta));
1455 } else {
1456 let (val, meta) = match iface_value.as_interface() {
1457 Some(iface) => match &iface as &InterfaceObj {
1458 InterfaceObj::Gos(v, b) => {
1459 (v.copy_semantic(gcc), b.as_ref().unwrap().0)
1460 }
1461 _ => (iface_value.clone(), prim_meta.none),
1462 },
1463 _ => (iface_value, prim_meta.none),
1464 };
1465 stack.set(inst.d + sb, GosValue::new_metadata(meta));
1466 stack.set(inst.s1 + sb, val);
1467 }
1468 }
1469 Opcode::IMPORT => {
1470 let pkey = *stack.read(inst.s0, sb, consts).as_package();
1471 if objs.packages[pkey].inited() {
1472 frame.pc += inst.d
1473 }
1474 }
1475 Opcode::SLICE => {
1476 let inst_ex = &code[frame.pc as usize];
1477 frame.pc += 1;
1478 let s = stack.read(inst.s0, sb, consts);
1479 let begin = *stack.read(inst.s1, sb, consts).as_int();
1480 let end = *stack.read(inst_ex.s0, sb, consts).as_int();
1481 let max = *stack.read(inst_ex.s1, sb, consts).as_int();
1482 let result = match inst.t0 {
1483 ValueType::Slice => s.caller(caller).slice_slice(s, begin, end, max),
1484 ValueType::String => GosValue::slice_string(s, begin, end, max),
1485 ValueType::Array => {
1486 GosValue::slice_array(s.clone(), begin, end, caller.get(inst.t1))
1487 }
1488 _ => unreachable!(),
1489 };
1490
1491 match result {
1492 Ok(v) => stack.set(inst.d + sb, v),
1493 Err(e) => go_panic_str!(panic, e.as_str(), frame, code),
1494 }
1495 }
1496 Opcode::CLOSURE => {
1497 let func = cst(consts, inst.s0);
1498 let mut val =
1499 ClosureObj::gos_from_func(*func.as_function(), &objs.functions, None);
1500 match &mut val {
1501 ClosureObj::Gos(gos) => {
1502 if let Some(uvs) = &mut gos.uvs {
1503 for (_, uv) in uvs.iter_mut() {
1506 let r: &mut UpValueState = &mut uv.inner.borrow_mut();
1507 if let UpValueState::Open(d) = r {
1508 for i in 1..frame_height {
1510 let index = frame_height - i;
1511 if self.frames[index].func() == d.func {
1512 let upframe = &mut self.frames[index];
1513 d.stack = Rc::downgrade(&self.stack);
1514 d.stack_base = upframe.stack_base as OpIndex;
1515 upframe.add_referred_by(d.index, d.typ, uv);
1516 break;
1518 }
1519 }
1520 }
1521 }
1522 frame = self.frames.last_mut().unwrap();
1523 }
1524 }
1525 _ => {}
1526 };
1527 stack.set(inst.d + sb, GosValue::new_closure(val, gcc));
1528 }
1529 Opcode::LITERAL => {
1530 let inst_ex = &code[frame.pc as usize];
1531 frame.pc += 1;
1532 let md = cst(consts, inst_ex.s0).as_metadata();
1533
1534 let begin = inst.s0 + sb;
1535 let count = inst.s1;
1536 let build_val = |m: &Meta| {
1537 let zero_val = m.zero(&objs.metas, gcc);
1538 let mut val = vec![];
1539 let mut cur_index = -1;
1540 for i in 0..count {
1541 let index = *stack.get(begin + i * 2).as_int32();
1542 let elem = stack.get(begin + 1 + i * 2).clone();
1543 if index < 0 {
1544 cur_index += 1;
1545 } else {
1546 cur_index = index;
1547 }
1548 let gap = cur_index - (val.len() as i32);
1549 if gap == 0 {
1550 val.push(elem);
1551 } else if gap > 0 {
1552 for _ in 0..gap {
1553 val.push(zero_val.clone());
1554 }
1555 val.push(elem);
1556 } else {
1557 val[cur_index as usize] = elem;
1558 }
1559 }
1560 (val, zero_val.typ())
1561 };
1562 let new_val = match &objs.metas[md.key] {
1563 MetadataType::Slice(m) => {
1564 let (val, typ) = build_val(m);
1565 GosValue::slice_with_data(val, caller.get(typ), gcc)
1566 }
1567 MetadataType::Array(m, _) => {
1568 let (val, typ) = build_val(m);
1569 GosValue::array_with_data(val, caller.get(typ), gcc)
1570 }
1571 MetadataType::Map(_, _) => {
1572 let map_val = GosValue::new_map(gcc);
1573 let map = map_val.as_map().unwrap();
1574 for i in 0..count {
1575 let k = stack.get(begin + i * 2).clone();
1576 let v = stack.get(begin + 1 + i * 2).clone();
1577 map.0.insert(k, v);
1578 }
1579 map_val
1580 }
1581 MetadataType::Struct(_) => {
1582 let struct_val = md.zero(&objs.metas, gcc);
1583 {
1584 let fields = &mut struct_val.as_struct().0.borrow_fields_mut();
1585 for i in 0..count {
1586 let index = *stack.get(begin + i * 2).as_uint();
1587 fields[index] = stack.get(begin + 1 + i * 2).clone();
1588 }
1589 }
1590 struct_val
1591 }
1592 _ => unreachable!(),
1593 };
1594 stack.set(inst.d + sb, new_val);
1595 }
1596 Opcode::NEW => {
1597 let md = stack.read(inst.s0, sb, consts).as_metadata();
1598 let v = md.into_value_category().zero(&objs.metas, gcc);
1599 let p = GosValue::new_pointer(PointerObj::UpVal(UpValue::new_closed(v)));
1600 stack.set(inst.d + sb, p);
1601 }
1602 Opcode::MAKE => {
1603 let md = stack.read(inst.s0, sb, consts).as_metadata();
1604 let val = match md.mtype_unwraped(&objs.metas) {
1605 MetadataType::Slice(vmeta) => {
1606 let (cap, len) = match inst.t0 {
1607 ValueType::FlagC => {
1609 let inst_ex = &code[frame.pc as usize];
1610 frame.pc += 1;
1611 (
1612 *stack.read(inst.s1, sb, consts).as_int() as usize,
1613 *stack.read(inst_ex.s0, sb, consts).as_int() as usize,
1614 )
1615 }
1616 ValueType::FlagB => {
1618 let len =
1619 *stack.read(inst.s1, sb, consts).as_int() as usize;
1620 (len, len)
1621 }
1622 _ => unreachable!(),
1623 };
1624 let zero = vmeta.zero(&objs.metas, gcc);
1625 GosValue::slice_with_size(
1626 len,
1627 cap,
1628 &zero,
1629 caller.get(zero.typ()),
1630 gcc,
1631 )
1632 }
1633 MetadataType::Map(_, _) => GosValue::new_map(gcc),
1634 #[cfg(not(feature = "async"))]
1635 MetadataType::Channel(_, _) => {
1636 go_panic_no_async!(panic, frame, code);
1637 GosValue::new_nil(ValueType::Void)
1638 }
1639 #[cfg(feature = "async")]
1640 MetadataType::Channel(_, val_meta) => {
1641 let cap = match inst.t0 {
1642 ValueType::FlagB => {
1644 *stack.read(inst.s1, sb, consts).as_int() as usize
1645 }
1646 ValueType::FlagA => 0,
1648 _ => unreachable!(),
1649 };
1650 let zero = val_meta.zero(&objs.metas, gcc);
1651 GosValue::new_channel(ChannelObj::new(cap, zero))
1652 }
1653 _ => unreachable!(),
1654 };
1655 stack.set(inst.d + sb, val);
1656 }
1657 Opcode::COMPLEX => {
1658 let val = match inst.t0 {
1662 ValueType::Float32 => {
1663 let r = *stack.read(inst.s0, sb, consts).as_float32();
1664 let i = *stack.read(inst.s1, sb, consts).as_float32();
1665 GosValue::new_complex64(r, i)
1666 }
1667 ValueType::Float64 => {
1668 let r = *stack.read(inst.s0, sb, consts).as_float64();
1669 let i = *stack.read(inst.s1, sb, consts).as_float64();
1670 GosValue::new_complex128(r, i)
1671 }
1672 _ => unreachable!(),
1673 };
1674 stack.set(inst.d + sb, val);
1675 }
1676 Opcode::REAL => {
1677 let complex = stack.read(inst.s0, sb, consts);
1678 let val = match inst.t0 {
1679 ValueType::Complex64 => GosValue::new_float32(complex.as_complex64().r),
1680 ValueType::Complex128 => {
1681 GosValue::new_float64(complex.as_complex128().r)
1682 }
1683 _ => unreachable!(),
1684 };
1685 stack.set(inst.d + sb, val);
1686 }
1687 Opcode::IMAG => {
1688 let complex = stack.read(inst.s0, sb, consts);
1689 let val = match inst.t0 {
1690 ValueType::Complex64 => GosValue::new_float32(complex.as_complex64().i),
1691 ValueType::Complex128 => {
1692 GosValue::new_float64(complex.as_complex128().i)
1693 }
1694 _ => unreachable!(),
1695 };
1696 stack.set(inst.d + sb, val);
1697 }
1698 Opcode::LEN => {
1699 let l = stack.read(inst.s0, sb, consts).len();
1700 stack.set(inst.d + sb, (l as isize).into());
1701 }
1702 Opcode::CAP => {
1703 let l = stack.read(inst.s0, sb, consts).cap();
1704 stack.set(inst.d + sb, (l as isize).into());
1705 }
1706 Opcode::APPEND => {
1707 let a = stack.read(inst.s0, sb, consts).clone();
1708 let b = if inst.t0 != ValueType::String {
1709 stack.read(inst.s1, sb, consts).clone()
1710 } else {
1711 let s = stack.read(inst.s1, sb, consts).as_string();
1713 let arr = GosValue::new_non_gc_array(
1714 ArrayObj::with_raw_data(s.as_rust_slice().to_vec()),
1715 ValueType::Uint8,
1716 );
1717 GosValue::slice_array(arr, 0, -1, caller.get(ValueType::Uint8)).unwrap()
1718 };
1719
1720 match caller.get(inst.t1).slice_append(a, b, gcc) {
1721 Ok(slice) => stack.set(inst.d + sb, slice),
1722 Err(e) => go_panic_str!(panic, e.as_str(), frame, code),
1723 };
1724 }
1725 Opcode::COPY => {
1726 let a = stack.read(inst.s0, sb, consts).clone();
1727 let b = stack.read(inst.s1, sb, consts).clone();
1728 let count = match inst.t0 {
1729 ValueType::String => {
1730 let string = b.as_string();
1731 match a.as_slice::<Elem8>() {
1732 Some(s) => s.0.copy_from(&string),
1733 None => 0,
1734 }
1735 }
1736 _ => caller.get(inst.t1).slice_copy_from(a, b),
1737 };
1738 stack.set(inst.d + sb, (count as isize).into());
1739 }
1740 Opcode::DELETE => {
1741 let map = stack.read(inst.s0, sb, consts);
1742 let key = stack.read(inst.s1, sb, consts);
1743 match map.as_map() {
1744 Some(m) => m.0.delete(key),
1745 None => {}
1746 }
1747 }
1748 #[cfg(not(feature = "async"))]
1749 Opcode::CLOSE => go_panic_no_async!(panic, frame, code),
1750 #[cfg(feature = "async")]
1751 Opcode::CLOSE => match stack.read(inst.s0, sb, consts).as_channel() {
1752 Some(c) => c.close(),
1753 None => {}
1754 },
1755 Opcode::PANIC => {
1756 let val = stack.read(inst.s0, sb, consts).clone();
1757 go_panic!(panic, val, frame, code);
1758 }
1759 Opcode::RECOVER => {
1760 let p = panic.take();
1761 let val = p.map_or(GosValue::new_nil(ValueType::Void), |x| {
1762 GosValue::new_interface(InterfaceObj::with_value(x.msg, None))
1763 });
1764 stack.set(inst.d + sb, val);
1765 }
1766 Opcode::ASSERT => {
1767 let ok = *stack.read(inst.s0, sb, consts).as_bool();
1768 if !ok {
1769 go_panic_str!(panic, "Opcode::ASSERT: not true!", frame, code);
1770 }
1771 }
1772 Opcode::FFI => {
1773 let val = {
1774 let itype = stack.read(inst.s0, sb, consts);
1775 let name = stack.read(inst.s1, sb, consts);
1776 let name_str = name.as_string().as_str();
1777 match self.context.ffi_factory.create(&name_str) {
1778 Ok(v) => {
1779 let meta = itype.as_metadata().underlying(&objs.metas).clone();
1780 GosValue::new_interface(InterfaceObj::Ffi(UnderlyingFfi::new(
1781 v, meta,
1782 )))
1783 }
1784 Err(e) => {
1785 go_panic_str!(panic, e.as_str(), frame, code);
1786 continue;
1787 }
1788 }
1789 };
1790 stack.set(inst.d + sb, val);
1791 }
1792 Opcode::VOID => unreachable!(),
1793 }
1794 } match result {
1796 Result::End => {
1797 *ctx.panic_data.borrow_mut() = panic.take();
1798 break;
1799 }
1800 Result::Continue => {
1801 drop(stack_mut_ref);
1802 #[cfg(feature = "async")]
1803 future::yield_now().await;
1804 restore_stack_ref!(self, stack, stack_mut_ref);
1805 }
1806 };
1807 } collect(gcc);
1810 }
1811}
1812
1813#[inline]
1814fn char_from_u32(u: u32) -> char {
1815 unsafe { char::from_u32_unchecked(u) }
1816}
1817
1818#[inline]
1819fn char_from_i32(i: i32) -> char {
1820 unsafe { char::from_u32_unchecked(i as u32) }
1821}
1822
1823#[inline]
1824fn deref_value(v: &GosValue, stack: &Stack, objs: &VMObjects) -> RuntimeResult<GosValue> {
1825 v.as_non_nil_pointer()?.deref(stack, &objs.packages)
1826}
1827
1828#[inline(always)]
1829fn cst(consts: &Vec<GosValue>, i: OpIndex) -> &GosValue {
1830 &consts[(-i - 1) as usize]
1831}
1832
1833#[inline]
1834fn type_assert(
1835 val: &GosValue,
1836 want_meta: &GosValue,
1837 gcc: &GcContainer,
1838 metas: &MetadataObjs,
1839) -> RuntimeResult<(GosValue, bool)> {
1840 let want_meta = want_meta.as_metadata();
1841 match val.as_interface() {
1842 Some(iface) => match &iface as &InterfaceObj {
1843 InterfaceObj::Gos(v, mb) => match mb {
1844 Some((meta, _)) => {
1845 if want_meta.identical(meta, metas) {
1846 Ok((v.copy_semantic(gcc), true))
1847 } else {
1848 Ok((want_meta.zero(metas, gcc), false))
1849 }
1850 }
1851 None => Err("No type info available for interface value"
1852 .to_owned()
1853 .into()),
1854 },
1855 InterfaceObj::Ffi(_) => Err("FFI interface do not support type assertion"
1856 .to_owned()
1857 .into()),
1858 },
1859 None => Ok((want_meta.zero(metas, gcc), false)),
1860 }
1861}
1862
1863#[inline(always)]
1864fn get_struct_and_index(
1865 val: GosValue,
1866 indices: &Vec<OpIndex>,
1867 stack: &mut Stack,
1868 objs: &VMObjects,
1869) -> (RuntimeResult<GosValue>, usize) {
1870 let (target, index) = {
1871 let val = get_embeded(val, &indices[..indices.len() - 1], stack, &objs.packages);
1872 (val, *indices.last().unwrap())
1873 };
1874 (
1875 match target {
1876 Ok(v) => match v.typ() {
1877 ValueType::Pointer => deref_value(&v, stack, objs),
1878 _ => Ok(v.clone()),
1879 },
1880 Err(e) => Err(e),
1881 },
1882 index as usize,
1883 )
1884}
1885
1886#[inline]
1887fn get_embeded(
1888 val: GosValue,
1889 indices: &[OpIndex],
1890 stack: &Stack,
1891 pkgs: &PackageObjs,
1892) -> RuntimeResult<GosValue> {
1893 let typ = val.typ();
1894 let mut cur_val: GosValue = val;
1895 if typ == ValueType::Pointer {
1896 cur_val = cur_val.as_non_nil_pointer()?.deref(stack, pkgs)?;
1897 }
1898 for &i in indices.iter() {
1899 let s = &cur_val.as_struct().0;
1900 let v = s.borrow_fields()[i as usize].clone();
1901 cur_val = v;
1902 }
1903 Ok(cur_val)
1904}
1905
1906#[inline]
1907fn cast_receiver(
1908 receiver: GosValue,
1909 b1: bool,
1910 stack: &Stack,
1911 objs: &VMObjects,
1912) -> RuntimeResult<GosValue> {
1913 let b0 = receiver.typ() == ValueType::Pointer;
1914 if b0 == b1 {
1915 Ok(receiver)
1916 } else if b1 {
1917 Ok(GosValue::new_pointer(PointerObj::UpVal(
1918 UpValue::new_closed(receiver.clone()),
1919 )))
1920 } else {
1921 deref_value(&receiver, stack, objs)
1922 }
1923}
1924
1925#[inline]
1926fn bind_iface_method(
1927 iface: &InterfaceObj,
1928 index: usize,
1929 stack: &Stack,
1930 objs: &VMObjects,
1931 gcc: &GcContainer,
1932) -> RuntimeResult<GosValue> {
1933 match iface {
1934 InterfaceObj::Gos(obj, b) => {
1935 let binding = &b.as_ref().unwrap().1[index];
1936 match binding {
1937 Binding4Runtime::Struct(func, ptr_recv, indices) => {
1938 let obj = match indices {
1939 None => obj.copy_semantic(gcc),
1940 Some(inds) => get_embeded(obj.clone(), inds, stack, &objs.packages)?
1941 .copy_semantic(gcc),
1942 };
1943 let obj = cast_receiver(obj, *ptr_recv, stack, objs)?;
1944 let cls = ClosureObj::gos_from_func(*func, &objs.functions, Some(obj));
1945 Ok(GosValue::new_closure(cls, gcc))
1946 }
1947 Binding4Runtime::Iface(i, indices) => {
1948 let bind = |obj: &GosValue| {
1949 bind_iface_method(&obj.as_interface().unwrap(), *i, stack, objs, gcc)
1950 };
1951 match indices {
1952 None => bind(&obj),
1953 Some(inds) => bind(&get_embeded(obj.clone(), inds, stack, &objs.packages)?),
1954 }
1955 }
1956 }
1957 }
1958 InterfaceObj::Ffi(ffi) => {
1959 let method = &objs.metas[ffi.meta.key].as_interface().infos()[index];
1960 let (func_name, meta) = (method.name.clone(), method.meta);
1961 let cls = FfiClosureObj {
1962 ffi: ffi.ffi_obj.clone(),
1963 is_async: func_name.starts_with("async"),
1964 func_name,
1965 meta,
1966 };
1967 Ok(GosValue::new_closure(ClosureObj::new_ffi(cls), gcc))
1968 }
1969 }
1970}