1#![allow(dead_code)]
2use super::channel;
3use super::ffi::FfiFactory;
4use super::gc::{gc, GcoVec};
5use super::instruction::*;
6use super::metadata::*;
7use super::objects::{u64_to_key, ClosureObj, GosHashMap};
8use super::stack::{RangeStack, Stack};
9use super::value::*;
10use super::vm_util;
11use async_executor::LocalExecutor;
12use futures_lite::future;
13use goscript_parser::FileSet;
14use std::cell::{Cell, RefCell};
15use std::collections::HashMap;
16use std::convert::TryInto;
17use std::pin::Pin;
18use std::ptr;
19use std::rc::Rc;
20use std::str;
21
22#[derive(Debug)]
23pub struct ByteCode {
24 pub objects: Pin<Box<VMObjects>>,
25 pub packages: Vec<PackageKey>,
26 pub ifaces: Vec<(GosMetadata, Option<Rc<Vec<FunctionKey>>>)>,
27 pub entry: FunctionKey,
28}
29
30#[derive(Clone, Debug)]
31struct Referers {
32 typ: ValueType,
33 weaks: Vec<WeakUpValue>,
34}
35
36#[derive(Clone, Debug)]
37struct CallFrame {
38 closure: Rc<(RefCell<ClosureObj>, RCount)>,
39 pc: usize,
40 stack_base: usize,
41 var_ptrs: Option<Vec<UpValue>>,
45 referred_by: Option<HashMap<OpIndex, Referers>>,
47
48 defer_stack: Option<Vec<DeferredCall>>,
49}
50
51impl CallFrame {
52 fn with_closure(c: Rc<(RefCell<ClosureObj>, RCount)>, sbase: usize) -> CallFrame {
53 CallFrame {
54 closure: c,
55 pc: 0,
56 stack_base: sbase,
57 var_ptrs: None,
58 referred_by: None,
59 defer_stack: None,
60 }
61 }
62
63 fn add_referred_by(&mut self, index: OpIndex, typ: ValueType, uv: &UpValue) {
64 if self.referred_by.is_none() {
65 self.referred_by = Some(HashMap::new());
66 }
67 let map = self.referred_by.as_mut().unwrap();
68 let weak = uv.downgrade();
69 match map.get_mut(&index) {
70 Some(v) => {
71 debug_assert!(v.typ == typ);
72 v.weaks.push(weak);
73 }
74 None => {
75 map.insert(
76 index,
77 Referers {
78 typ: typ,
79 weaks: vec![weak],
80 },
81 );
82 }
83 }
84 }
85
86 #[inline]
87 fn func(&self) -> FunctionKey {
88 self.closure.0.borrow().func.unwrap()
89 }
90
91 #[inline]
92 fn closure(&self) -> &Rc<(RefCell<ClosureObj>, RCount)> {
93 &self.closure
94 }
95
96 #[inline]
97 fn ret_count(&self, objs: &VMObjects) -> usize {
98 let fkey = self.func();
99 objs.functions[fkey].ret_count()
100 }
101
102 #[inline]
103 fn on_drop(&mut self, stack: &Stack) {
104 if let Some(referred) = &self.referred_by {
105 for (ind, referrers) in referred {
106 if referrers.weaks.len() == 0 {
107 continue;
108 }
109 let val = stack.get_with_type(Stack::offset(self.stack_base, *ind), referrers.typ);
110 for weak in referrers.weaks.iter() {
111 if let Some(uv) = weak.upgrade() {
112 uv.close(val.clone());
113 }
114 }
115 }
116 }
117 }
118}
119
120#[derive(Clone, Debug)]
121struct DeferredCall {
122 frame: CallFrame,
123 stack_c: Vec<GosValue64>,
124 stack_rc: Vec<GosValue>,
125}
126
127#[derive(Debug)]
128enum Result {
129 Continue,
130 End,
131}
132
133#[derive(Debug)]
134struct PanicData {
135 msg: GosValue,
136 call_stack: Vec<(FunctionKey, usize)>,
137}
138
139impl PanicData {
140 fn new(m: GosValue) -> PanicData {
141 PanicData {
142 msg: m,
143 call_stack: vec![],
144 }
145 }
146}
147
148#[derive(Clone)]
149struct Context<'a> {
150 exec: Rc<LocalExecutor<'a>>,
151 code: &'a ByteCode,
152 gcv: &'a GcoVec,
153 ffi_factory: &'a FfiFactory,
154 fs: Option<&'a FileSet>,
155}
156
157impl<'a> Context<'a> {
158 fn new(
159 exec: Rc<LocalExecutor<'a>>,
160 code: &'a ByteCode,
161 gcv: &'a GcoVec,
162 ffi_factory: &'a FfiFactory,
163 fs: Option<&'a FileSet>,
164 ) -> Context<'a> {
165 Context {
166 exec: exec,
167 code: code,
168 gcv: gcv,
169 ffi_factory: ffi_factory,
170 fs: fs,
171 }
172 }
173
174 fn new_entry_frame(&self, entry: FunctionKey) -> CallFrame {
175 let cls = GosValue::new_closure(entry, &self.code.objects.functions);
176 CallFrame::with_closure(cls.as_closure().clone(), 0)
177 }
178
179 fn spawn_fiber(&self, stack: Stack, first_frame: CallFrame) {
180 let mut f = Fiber::new(self.clone(), stack, first_frame);
181 self.exec
182 .spawn(async move {
183 future::yield_now().await;
185 f.main_loop().await;
186 })
187 .detach();
188 }
189}
190
191pub struct Fiber<'a> {
192 stack: Rc<RefCell<Stack>>,
193 rstack: RangeStack,
194 frames: Vec<CallFrame>,
195 next_frames: Vec<CallFrame>,
196 context: Context<'a>,
197}
198
199impl<'a> Fiber<'a> {
200 fn new(c: Context<'a>, stack: Stack, first_frame: CallFrame) -> Fiber<'a> {
201 Fiber {
202 stack: Rc::new(RefCell::new(stack)),
203 rstack: RangeStack::new(),
204 frames: vec![first_frame],
205 next_frames: Vec::new(),
206 context: c,
207 }
208 }
209
210 async fn main_loop(&mut self) {
211 let ctx = &self.context;
212 let gcv = ctx.gcv;
213 let objs: &VMObjects = &ctx.code.objects;
214 let metadata: &Metadata = &objs.metadata;
215 let pkgs = &ctx.code.packages;
216 let ifaces = &ctx.code.ifaces;
217 let frame = self.frames.last_mut().unwrap();
218 let mut func = &objs.functions[frame.func()];
219
220 let mut stack_mut_ref = self.stack.borrow_mut();
221 let mut stack: &mut Stack = &mut stack_mut_ref;
222 stack.append(&mut func.local_zeros.clone());
224
225 let mut consts = &func.consts;
226 let mut code = func.code();
227 let mut stack_base = frame.stack_base;
228 let mut frame_height = self.frames.len();
229
230 let mut total_inst = 0;
231 loop {
233 let mut frame = self.frames.last_mut().unwrap();
234 let mut result: Result = Result::Continue;
235 let mut panic: Option<PanicData> = None;
236 let yield_unit = 1024;
237 for _ in 0..yield_unit {
238 let inst = code[frame.pc];
239 let inst_op = inst.op();
240 total_inst += 1;
241 frame.pc += 1;
243 match inst_op {
245 Opcode::PUSH_CONST => {
246 let index = inst.imm();
247 let gos_val = &consts[index as usize];
248 stack.push(gos_val.deep_clone(gcv));
252 }
253 Opcode::PUSH_NIL => stack.push_nil(),
254 Opcode::PUSH_FALSE => stack.push_bool(false),
255 Opcode::PUSH_TRUE => stack.push_bool(true),
256 Opcode::PUSH_IMM => stack.push_int32_as(inst.imm(), inst.t0()),
257 Opcode::POP => {
258 stack.pop_discard_n(inst.imm() as usize);
259 }
260 Opcode::LOAD_LOCAL => {
261 let index = Stack::offset(stack_base, inst.imm());
262 stack.push_from_index(index, inst.t0()); }
264 Opcode::STORE_LOCAL => {
265 let (rhs_index, index) = inst.imm824();
266 let s_index = Stack::offset(stack_base, index);
267 store_local!(stack, s_index, rhs_index, inst.t0(), gcv);
268 }
269 Opcode::LOAD_UPVALUE => {
270 let index = inst.imm();
271 let upvalue = frame.var_ptrs.as_ref().unwrap()[index as usize].clone();
272 let val = load_up_value!(upvalue, self, stack, self.frames);
273 stack.push(val);
274 frame = self.frames.last_mut().unwrap();
275 }
276 Opcode::STORE_UPVALUE => {
277 let (rhs_index, index) = inst.imm824();
278 let upvalue = frame.var_ptrs.as_ref().unwrap()[index as usize].clone();
279 store_up_value!(
280 upvalue,
281 self,
282 stack,
283 self.frames,
284 rhs_index,
285 inst.t0(),
286 gcv
287 );
288 frame = self.frames.last_mut().unwrap();
289 }
290 Opcode::LOAD_INDEX => {
291 let ind = stack.pop_with_type(inst.t1());
292 let val = &stack.pop_with_type(inst.t0());
293 if inst.t2_as_index() == 0 {
294 match vm_util::load_index(val, &ind) {
295 Ok(v) => stack.push(v),
296 Err(e) => {
297 go_panic_str!(panic, &objs.metadata, e, frame, code);
298 }
299 }
300 } else {
301 vm_util::push_index_comma_ok(stack, val, &ind);
302 }
303 }
304 Opcode::LOAD_INDEX_IMM => {
305 let val = &stack.pop_with_type(inst.t0());
306 let index = inst.imm() as usize;
307 if inst.t2_as_index() == 0 {
308 match vm_util::load_index_int(val, index) {
309 Ok(v) => stack.push(v),
310 Err(e) => {
311 go_panic_str!(panic, metadata, e, frame, code);
312 }
313 }
314 } else {
315 vm_util::push_index_comma_ok(
316 stack,
317 val,
318 &GosValue::Int(index as isize),
319 );
320 }
321 }
322 Opcode::STORE_INDEX => {
323 let (rhs_index, index) = inst.imm824();
324 let s_index = Stack::offset(stack.len(), index);
325 let key = stack.get_with_type(s_index + 1, inst.t2());
326 let target = &stack.get_with_type(s_index, inst.t1());
327 vm_util::store_index(stack, target, &key, rhs_index, inst.t0(), gcv);
328 }
329 Opcode::STORE_INDEX_IMM => {
330 let (rhs_index, imm) = inst.imm824();
332 let index = inst.t2_as_index();
333 let s_index = Stack::offset(stack.len(), index);
334 let target = &stack.get_with_type(s_index, inst.t1());
335 if let Err(e) = vm_util::store_index_int(
336 stack,
337 target,
338 imm as usize,
339 rhs_index,
340 inst.t0(),
341 gcv,
342 ) {
343 go_panic_str!(panic, metadata, e, frame, code);
344 }
345 }
346 Opcode::LOAD_FIELD => {
347 let ind = stack.pop_with_type(inst.t1());
348 let val = stack.pop_with_type(inst.t0());
349 stack.push(vm_util::load_field(&val, &ind, objs));
350 }
351 Opcode::LOAD_STRUCT_FIELD => {
352 let ind = inst.imm();
353 let mut target = stack.pop_with_type(inst.t0());
354 if let GosValue::Pointer(_) = &target {
355 target = deref_value!(target, self, stack, self.frames, objs);
356 frame = self.frames.last_mut().unwrap();
357 }
358 let val = match &target {
359 GosValue::Named(n) => {
360 n.0.as_struct().0.borrow().fields[ind as usize].clone()
361 }
362 GosValue::Struct(sval) => sval.0.borrow().fields[ind as usize].clone(),
363 _ => {
364 dbg!(&target);
365 unreachable!()
366 }
367 };
368
369 stack.push(val);
370 }
371 Opcode::BIND_METHOD => {
372 let val = stack.pop_with_type(inst.t0());
373 let func = *consts[inst.imm() as usize].as_function();
374 stack.push(GosValue::Closure(Rc::new((
375 RefCell::new(ClosureObj::new_gos(
376 func,
377 &objs.functions,
378 Some(val.copy_semantic(gcv)),
379 )),
380 Cell::new(0),
381 ))));
382 }
383 Opcode::BIND_INTERFACE_METHOD => {
384 let val = stack.pop_with_type(inst.t0());
385 let val = match &val {
386 GosValue::Named(n) => n.0.clone(),
387 GosValue::Interface(_) => val,
388 _ => unreachable!(),
389 };
390 let borrowed = val.as_interface().borrow();
391 let cls = match borrowed.underlying() {
392 IfaceUnderlying::Gos(val, funcs) => {
393 let func = funcs.as_ref().unwrap()[inst.imm() as usize];
394 let cls = ClosureObj::new_gos(
395 func,
396 &objs.functions,
397 Some(val.copy_semantic(gcv)),
398 );
399 GosValue::Closure(Rc::new((RefCell::new(cls), Cell::new(0))))
400 }
401 IfaceUnderlying::Ffi(ffi) => {
402 let (name, meta) = ffi.methods[inst.imm() as usize].clone();
403 let cls = FfiClosureObj {
404 ffi: ffi.ffi_obj.clone(),
405 func_name: name,
406 meta: meta,
407 };
408 GosValue::Closure(Rc::new((
409 RefCell::new(ClosureObj::new_ffi(cls)),
410 Cell::new(0),
411 )))
412 }
413 IfaceUnderlying::None => {
414 let msg = "access nil interface".to_string();
415 go_panic_str!(panic, metadata, msg, frame, code);
416 continue;
417 }
418 };
419 stack.push(cls);
420 }
421 Opcode::STORE_FIELD => {
422 let (rhs_index, _) = inst.imm824();
423 let index = inst.t2_as_index();
424 let s_index = Stack::offset(stack.len(), index);
425 let key = stack.get_with_type(s_index + 1, inst.t2());
426 let target = stack.get_with_type(s_index, inst.t1());
427 match target {
428 GosValue::Pointer(_) => {
429 let unboxed = deref_value!(target, self, stack, self.frames, objs);
430 frame = self.frames.last_mut().unwrap();
431 vm_util::store_field(
432 stack,
433 &unboxed,
434 &key,
435 rhs_index,
436 inst.t0(),
437 &objs.metas,
438 gcv,
439 );
440 }
441 _ => vm_util::store_field(
442 stack,
443 &target,
444 &key,
445 rhs_index,
446 inst.t0(),
447 &objs.metas,
448 gcv,
449 ),
450 };
451 }
452 Opcode::STORE_STRUCT_FIELD => {
453 let (rhs_index, imm) = inst.imm824();
454 let index = inst.t2_as_index();
455 let s_index = Stack::offset(stack.len(), index);
456 let mut target = stack.get_with_type(s_index, inst.t1());
457 if let GosValue::Pointer(_) = &target {
458 target = deref_value!(target, self, stack, self.frames, objs);
459 frame = self.frames.last_mut().unwrap();
460 }
461 match &target {
462 GosValue::Named(n) => {
463 let field =
464 &mut n.0.as_struct().0.borrow_mut().fields[imm as usize];
465 stack.store_val(field, rhs_index, inst.t0(), gcv);
466 }
467 GosValue::Struct(s) => {
468 let field = &mut s.0.borrow_mut().fields[imm as usize];
469 stack.store_val(field, rhs_index, inst.t0(), gcv);
470 }
471 _ => {
472 dbg!(&target);
473 unreachable!()
474 }
475 }
476 }
477 Opcode::LOAD_PKG_FIELD => {
478 let index = inst.imm();
479 let pkg_key = read_imm_pkg!(code, frame, objs);
480 let pkg = &objs.packages[pkg_key];
481 stack.push(pkg.member(index).clone());
482 }
483 Opcode::STORE_PKG_FIELD => {
484 let (rhs_index, imm) = inst.imm824();
485 let pkg = &objs.packages[read_imm_pkg!(code, frame, objs)];
486 stack.store_val(&mut pkg.member_mut(imm), rhs_index, inst.t0(), gcv);
487 }
488 Opcode::STORE_DEREF => {
489 let (rhs_index, index) = inst.imm824();
490 let s_index = Stack::offset(stack.len(), index);
491 match stack.get_with_type(s_index, ValueType::Pointer) {
492 GosValue::Pointer(b) => {
493 let r: &PointerObj = &b;
494 match r {
495 PointerObj::UpVal(uv) => {
496 store_up_value!(
497 uv,
498 self,
499 stack,
500 self.frames,
501 rhs_index,
502 inst.t0(),
503 gcv
504 );
505 frame = self.frames.last_mut().unwrap();
506 }
507 PointerObj::Struct(r, _) => {
508 let rhs_s_index = Stack::offset(stack.len(), rhs_index);
509 let val = stack.get_with_type(rhs_s_index, inst.t0());
510 let mref: &mut StructObj = &mut r.0.borrow_mut();
511 *mref = val.try_get_struct().unwrap().0.borrow().clone();
512 }
513 PointerObj::Array(a, _) => {
514 let rhs_s_index = Stack::offset(stack.len(), rhs_index);
515 let val = stack.get_with_type(rhs_s_index, inst.t0());
516 a.0.set_from(&val.as_array().0);
517 }
518 PointerObj::Slice(r, _) => {
519 let rhs_s_index = Stack::offset(stack.len(), rhs_index);
520 let val = stack.get_with_type(rhs_s_index, inst.t0());
521 r.0.set_from(&val.as_slice().0);
522 }
523 PointerObj::Map(r, _) => {
524 let rhs_s_index = Stack::offset(stack.len(), rhs_index);
525 let val = stack.get_with_type(rhs_s_index, inst.t0());
526 let mref: &mut GosHashMap = &mut r.0.borrow_data_mut();
527 *mref = val.try_get_map().unwrap().0.borrow_data().clone();
528 }
529 PointerObj::SliceMember(s, index) => {
530 let vborrow = s.0.borrow_data();
531 let target: &mut GosValue = &mut vborrow
532 [s.0.begin() + *index as usize]
533 .borrow_mut();
534 stack.store_val(target, rhs_index, inst.t0(), gcv);
535 }
536 PointerObj::StructField(s, index) => {
537 let target: &mut GosValue =
538 &mut s.0.borrow_mut().fields[*index as usize];
539 stack.store_val(target, rhs_index, inst.t0(), gcv);
540 }
541 PointerObj::PkgMember(p, index) => {
542 let target: &mut GosValue =
543 &mut objs.packages[*p].member_mut(*index);
544 stack.store_val(target, rhs_index, inst.t0(), gcv);
545 }
546 PointerObj::Released => unreachable!(),
547 };
548 }
549 _ => unreachable!(),
550 }
551 }
552 Opcode::CAST => {
553 let (target, mapping) = inst.imm824();
554 let rhs_s_index = Stack::offset(stack.len(), target);
555 match inst.t0() {
556 ValueType::Interface => {
557 let iface = ifaces[mapping as usize].clone();
558 let under = stack.get_with_type(rhs_s_index, inst.t1());
559 let val = match &objs.metas[iface.0.as_non_ptr()] {
560 MetadataType::Named(_, md) => GosValue::Named(Box::new((
561 GosValue::new_iface(
562 *md,
563 IfaceUnderlying::Gos(under, iface.1),
564 ),
565 iface.0,
566 ))),
567 MetadataType::Interface(_) => GosValue::new_iface(
568 iface.0,
569 IfaceUnderlying::Gos(under, iface.1),
570 ),
571 _ => unreachable!(),
572 };
573 stack.set(rhs_s_index, val);
574 }
575 ValueType::Str => {
576 let result = match inst.t1() {
577 ValueType::Slice => {
578 let slice = stack.get_rc(rhs_s_index).as_slice();
579 match inst.t2() {
580 ValueType::Int32 => slice
581 .0
582 .borrow_data()
583 .iter()
584 .map(|x| {
585 vm_util::char_from_i32(*(x.borrow().as_int32()))
586 })
587 .collect(),
588 ValueType::Uint8 => {
589 let buf: Vec<u8> = slice
590 .0
591 .borrow_data()
592 .iter()
593 .map(|x| *(x.borrow().as_uint8()))
594 .collect();
595 str::from_utf8(&buf).unwrap().to_string()
597 }
598 _ => unreachable!(),
599 }
600 }
601 _ => {
602 let target = stack.get_c_mut(rhs_s_index);
603 target.to_uint32(inst.t1());
604 vm_util::char_from_u32(target.get_uint32()).to_string()
605 }
606 };
607 stack.set(rhs_s_index, GosValue::new_str(result));
608 }
609 ValueType::Slice => {
610 let from = stack.get_rc(rhs_s_index).as_str();
611 let result = match inst.t2() {
612 ValueType::Int32 => (
613 objs.metadata.mint32,
614 from.as_str()
615 .chars()
616 .map(|x| GosValue::Int32(x as i32))
617 .collect(),
618 ),
619 ValueType::Uint8 => (
620 objs.metadata.muint8,
621 from.as_str().bytes().map(|x| GosValue::Uint8(x)).collect(),
622 ),
623 _ => unreachable!(),
624 };
625 stack.set(
626 rhs_s_index,
627 GosValue::slice_with_val(result.1, result.0, gcv),
628 )
629 }
630 ValueType::Uint => stack.get_c_mut(rhs_s_index).to_uint(inst.t1()),
631 ValueType::Uint8 => stack.get_c_mut(rhs_s_index).to_uint8(inst.t1()),
632 ValueType::Uint16 => stack.get_c_mut(rhs_s_index).to_uint16(inst.t1()),
633 ValueType::Uint32 => stack.get_c_mut(rhs_s_index).to_uint32(inst.t1()),
634 ValueType::Uint64 => stack.get_c_mut(rhs_s_index).to_uint64(inst.t1()),
635 ValueType::Int => stack.get_c_mut(rhs_s_index).to_int(inst.t1()),
636 ValueType::Int8 => stack.get_c_mut(rhs_s_index).to_int8(inst.t1()),
637 ValueType::Int16 => stack.get_c_mut(rhs_s_index).to_int16(inst.t1()),
638 ValueType::Int32 => stack.get_c_mut(rhs_s_index).to_int32(inst.t1()),
639 ValueType::Int64 => stack.get_c_mut(rhs_s_index).to_int64(inst.t1()),
640 ValueType::Float32 => {
641 stack.get_c_mut(rhs_s_index).to_float32(inst.t1())
642 }
643 ValueType::Float64 => {
644 stack.get_c_mut(rhs_s_index).to_float64(inst.t1())
645 }
646 _ => {
647 dbg!(inst.t0());
649 unimplemented!()
650 }
651 }
652 }
653 Opcode::ADD => stack.add(inst.t0()),
654 Opcode::SUB => stack.sub(inst.t0()),
655 Opcode::MUL => stack.mul(inst.t0()),
656 Opcode::QUO => stack.quo(inst.t0()),
657 Opcode::REM => stack.rem(inst.t0()),
658 Opcode::AND => stack.and(inst.t0()),
659 Opcode::OR => stack.or(inst.t0()),
660 Opcode::XOR => stack.xor(inst.t0()),
661 Opcode::AND_NOT => stack.and_not(inst.t0()),
662 Opcode::SHL => stack.shl(inst.t0(), inst.t1()),
663 Opcode::SHR => stack.shr(inst.t0(), inst.t1()),
664 Opcode::UNARY_ADD => {}
665 Opcode::UNARY_SUB => stack.unary_negate(inst.t0()),
666 Opcode::UNARY_XOR => stack.unary_xor(inst.t0()),
667 Opcode::NOT => stack.logical_not(inst.t0()),
668 Opcode::EQL => stack.compare_eql(inst.t0()),
669 Opcode::LSS => stack.compare_lss(inst.t0()),
670 Opcode::GTR => stack.compare_gtr(inst.t0()),
671 Opcode::NEQ => stack.compare_neq(inst.t0()),
672 Opcode::LEQ => stack.compare_leq(inst.t0()),
673 Opcode::GEQ => stack.compare_geq(inst.t0()),
674 Opcode::SEND => {
675 let val = stack.pop_with_type(inst.t0());
676 let chan = stack.pop_rc();
677 drop(stack_mut_ref);
678 let re = chan.as_channel().send(&val).await;
679 restore_stack_ref!(self, stack, stack_mut_ref);
680 if let Err(e) = re {
681 go_panic_str!(panic, metadata, e, frame, code);
682 }
683 }
684 Opcode::RECV => {
685 let chan_val = stack.pop_rc();
686 let chan = chan_val.as_channel();
687 drop(stack_mut_ref);
688 let val = chan.recv().await;
689 restore_stack_ref!(self, stack, stack_mut_ref);
690 let (unwrapped, ok) = unwrap_recv_val!(chan, val, objs.metas, gcv);
691 stack.push(unwrapped);
692 if inst.t1() == ValueType::FlagA {
693 stack.push(GosValue::Bool(ok));
694 }
695 }
696 Opcode::REF_UPVALUE => {
697 let index = inst.imm();
698 let upvalue = frame.var_ptrs.as_ref().unwrap()[index as usize].clone();
699 stack.push(GosValue::new_pointer(PointerObj::UpVal(upvalue.clone())));
700 }
701 Opcode::REF_LOCAL => {
702 let t = inst.t0();
703 let val = if inst.imm() >= 0 {
704 let s_index = Stack::offset(stack_base, inst.imm());
705 stack.get_with_type(s_index, t)
706 } else {
707 stack.pop_with_type(t)
708 };
709 let boxed = PointerObj::new_local(val);
710 stack.push(GosValue::new_pointer(boxed));
711 }
712 Opcode::REF_SLICE_MEMBER => {
713 let index = stack.pop_int();
714 let typ = inst.t0();
715 let mut slice = stack.pop_with_type(typ);
716 if typ == ValueType::Array {
718 slice = GosValue::slice_with_array(&slice, 0, -1, gcv);
719 }
720 stack.push(GosValue::new_pointer(PointerObj::SliceMember(
721 slice.as_slice().clone(),
722 index.try_into().unwrap(),
723 )));
724 }
725 Opcode::REF_STRUCT_FIELD => {
726 let struct_ = stack.pop_with_type(inst.t0());
727 let struct_ = match &struct_ {
728 GosValue::Named(n) => n.0.clone(),
729 GosValue::Struct(_) => struct_,
730 _ => unreachable!(),
731 };
732 stack.push(GosValue::new_pointer(PointerObj::StructField(
733 struct_.as_struct().clone(),
734 inst.imm(),
735 )));
736 }
737 Opcode::REF_PKG_MEMBER => {
738 let pkg = read_imm_pkg!(code, frame, objs);
739 stack.push(GosValue::new_pointer(PointerObj::PkgMember(
740 pkg,
741 inst.imm(),
742 )));
743 }
744 Opcode::REF_LITERAL => {
745 let v = stack.pop_with_type(inst.t0());
746 stack.push(GosValue::new_pointer(PointerObj::UpVal(
747 UpValue::new_closed(v),
748 )))
749 }
750 Opcode::DEREF => {
751 let boxed = stack.pop_with_type(inst.t0());
752 let val = deref_value!(boxed, self, stack, self.frames, objs);
753 stack.push(val);
754 frame = self.frames.last_mut().unwrap();
755 }
756 Opcode::PRE_CALL => {
757 let val = stack.pop_with_type(ValueType::Closure);
758 let cls_rc = val.as_closure();
759 let cls: &ClosureObj = &*cls_rc.0.borrow();
760 let next_frame = CallFrame::with_closure(cls_rc.clone(), stack.len());
761 match cls.func {
762 Some(key) => {
763 let next_func = &objs.functions[key];
764 stack.append(&mut next_func.ret_zeros.clone());
765 if let Some(r) = &cls.recv {
766 stack.push(r.clone());
769 }
770 }
771 None => {} }
773 self.next_frames.push(next_frame);
774 }
775 Opcode::CALL => {
776 let mut nframe = self.next_frames.pop().unwrap();
777 let ref_cls = nframe.closure().clone();
778 let cls: &ClosureObj = &ref_cls.0.borrow();
779 let call_style = inst.t0();
780 let pack = inst.t1() == ValueType::FlagA;
781 if pack {
782 let sig = &objs.metas[cls.meta.as_non_ptr()].as_signature();
783 let (meta, v_meta) = sig.variadic.unwrap();
784 let vt = v_meta.get_value_type(&objs.metas);
785 let index =
786 nframe.stack_base + sig.params.len() + sig.results.len() - 1;
787 stack.pack_variadic(index, meta, vt, gcv);
788 }
789 match cls.func {
790 Some(key) => {
791 let nfunc = &objs.functions[key];
792 if let Some(uvs) = &cls.uvs {
793 let mut ptrs: Vec<UpValue> =
794 Vec::with_capacity(nfunc.up_ptrs.len());
795 for (i, p) in nfunc.up_ptrs.iter().enumerate() {
796 ptrs.push(if p.is_up_value {
797 uvs[&i].clone()
798 } else {
799 let uv = UpValue::new(p.clone_with_stack(
801 Rc::downgrade(&self.stack),
802 nframe.stack_base as OpIndex,
803 ));
804 nframe.add_referred_by(p.index, p.typ, &uv);
805 uv
806 });
807 }
808 nframe.var_ptrs = Some(ptrs);
809 }
810 match call_style {
811 ValueType::Zero => {
812 self.frames.push(nframe);
814 frame_height += 1;
815 frame = self.frames.last_mut().unwrap();
816 func = nfunc;
817 stack_base = frame.stack_base;
818 consts = &func.consts;
819 code = func.code();
820 debug_assert!(func.local_count() == func.local_zeros.len());
824 stack.append(&mut func.local_zeros.clone());
826 }
827 ValueType::FlagA => {
828 nframe.stack_base = 0;
830 let nstack = Stack::move_from(stack, nfunc.param_count());
831 self.context.spawn_fiber(nstack, nframe);
832 }
833 ValueType::FlagB => {
834 let (c, rc) = stack.pop_n(nfunc.param_count());
835 let deferred = DeferredCall {
836 frame: nframe,
837 stack_c: c,
838 stack_rc: rc,
839 };
840 frame.defer_stack.get_or_insert(vec![]).push(deferred);
841 }
842 _ => unreachable!(),
843 }
844 }
845 None => {
846 let call = cls.ffi.as_ref().unwrap();
847 let ptypes = &objs.metas[call.meta.as_non_ptr()]
848 .as_signature()
849 .params_type;
850 let params = stack.pop_with_type_n(ptypes);
851 drop(stack_mut_ref);
853 let mut returns = call.ffi.borrow().call(&call.func_name, params);
854 restore_stack_ref!(self, stack, stack_mut_ref);
855 stack.append(&mut returns);
856 }
857 }
858 }
859 Opcode::RETURN => {
860 match inst.t0() {
865 ValueType::Zero => {
867 stack.truncate(stack_base + frame.ret_count(objs));
868 }
869 ValueType::FlagA => {
871 let index = inst.imm() as usize;
872 let pkey = pkgs[index];
873 let pkg = &objs.packages[pkey];
874 let count = pkg.var_count();
875 debug_assert!(stack.len() == stack_base + count);
877 stack.init_pkg_vars(pkg, count);
879 }
880 ValueType::FlagB => {
882 match frame.defer_stack.as_mut().map(|x| x.pop()).flatten() {
883 Some(call) => {
884 frame.pc -= 1;
886
887 stack.push_n(call.stack_c, call.stack_rc);
888 let nframe = call.frame;
889
890 self.frames.push(nframe);
891 frame_height += 1;
892 frame = self.frames.last_mut().unwrap();
893 let fkey = frame.closure.0.borrow().func.unwrap();
894 func = &objs.functions[fkey];
895 stack_base = frame.stack_base;
896 consts = &func.consts;
897 code = func.code();
898 debug_assert!(func.local_count() == func.local_zeros.len());
899 stack.append(&mut func.local_zeros.clone());
900 continue;
901 }
902 None => {
903 stack.truncate(stack_base + frame.ret_count(objs));
904 }
905 }
906 }
907 _ => unreachable!(),
908 }
909
910 frame.on_drop(&stack);
911 drop(frame);
912 self.frames.pop();
913 frame_height -= 1;
914 if self.frames.is_empty() {
915 dbg!(total_inst);
916 result = Result::End;
925 break;
926 }
927 frame = self.frames.last_mut().unwrap();
928 stack_base = frame.stack_base;
929 func = &objs.functions[frame.func()];
931 consts = &func.consts;
932 code = func.code();
933
934 if let Some(p) = &mut panic {
935 p.call_stack.push((frame.func(), frame.pc - 1));
936 frame.pc = code.len() - 1;
937 }
938 }
939
940 Opcode::JUMP => {
941 frame.pc = Stack::offset(frame.pc, inst.imm());
942 }
943 Opcode::JUMP_IF => {
944 if stack.pop_bool() {
945 frame.pc = Stack::offset(frame.pc, inst.imm());
946 }
947 }
948 Opcode::JUMP_IF_NOT => {
949 if !stack.pop_bool() {
950 frame.pc = Stack::offset(frame.pc, inst.imm());
951 }
952 }
953 Opcode::SWITCH => {
954 if stack.switch_cmp(inst.t0(), objs) {
955 frame.pc = Stack::offset(frame.pc, inst.imm());
956 }
957 }
958 Opcode::SELECT => {
959 let blocks = inst.imm();
960 let begin = frame.pc - 1;
961 let mut end = begin + blocks as usize;
962 let end_code = &code[end - 1];
963 let default_offset = match end_code.t0() {
964 ValueType::FlagE => {
965 end -= 1;
966 Some(end_code.imm())
967 }
968 _ => None,
969 };
970 let comms = code[begin..end]
971 .iter()
972 .enumerate()
973 .rev()
974 .map(|(i, sel_code)| {
975 let offset = if i == 0 { 0 } else { sel_code.imm() };
976 let flag = sel_code.t0();
977 match &flag {
978 ValueType::FlagA => {
979 let val = stack.pop_with_type(sel_code.t1());
980 let chan = stack.pop_rc();
981 channel::SelectComm::Send(chan, val, offset)
982 }
983 ValueType::FlagB | ValueType::FlagC | ValueType::FlagD => {
984 let chan = stack.pop_rc();
985 channel::SelectComm::Recv(chan, flag, offset)
986 }
987 _ => unreachable!(),
988 }
989 })
990 .collect();
991 let selector = channel::Selector::new(comms, default_offset);
992
993 drop(stack_mut_ref);
994 let re = selector.select().await;
995 restore_stack_ref!(self, stack, stack_mut_ref);
996
997 match re {
998 Ok((i, val)) => {
999 let block_offset = if i >= selector.comms.len() {
1000 selector.default_offset.unwrap()
1001 } else {
1002 match &selector.comms[i] {
1003 channel::SelectComm::Send(_, _, offset) => *offset,
1004 channel::SelectComm::Recv(c, flag, offset) => {
1005 let (unwrapped, ok) = unwrap_recv_val!(
1006 c.as_channel(),
1007 val,
1008 objs.metas,
1009 gcv
1010 );
1011 match flag {
1012 ValueType::FlagC => {
1013 stack.push(unwrapped);
1014 }
1015 ValueType::FlagD => {
1016 stack.push(unwrapped);
1017 stack.push_bool(ok);
1018 }
1019 _ => {}
1020 }
1021 *offset
1022 }
1023 }
1024 };
1025 frame.pc = Stack::offset(frame.pc, (blocks - 1) + block_offset);
1027 }
1028 Err(e) => {
1029 go_panic_str!(panic, &objs.metadata, e, frame, code);
1030 }
1031 }
1032 }
1033 Opcode::RANGE_INIT => {
1034 let len = stack.len();
1035 let t = stack.get_with_type(len - 1, inst.t0());
1036 self.rstack.range_init(&t);
1037 stack.pop_discard();
1038 }
1039 Opcode::RANGE => {
1041 let offset = inst.imm();
1042 if self.rstack.range_body(inst.t0(), stack) {
1043 frame.pc = Stack::offset(frame.pc, offset);
1044 }
1045 }
1046
1047 Opcode::TYPE_ASSERT => {
1048 let val = match stack.pop_interface().borrow().underlying() {
1049 IfaceUnderlying::Gos(v, _) => v.copy_semantic(gcv),
1050 _ => GosValue::new_nil(),
1051 };
1052 let meta = GosValue::Metadata(val.get_meta(objs, stack));
1053 stack.push(val);
1054 let ok = &consts[inst.imm() as usize] == &meta;
1055 let do_try = inst.t2_as_index() > 0;
1056 if !do_try {
1057 if !ok {
1058 unimplemented!()
1060 }
1061 } else {
1062 stack.push_bool(ok);
1063 }
1064 }
1065 Opcode::TYPE => {
1066 let val = match stack.pop_interface().borrow().underlying() {
1067 IfaceUnderlying::Gos(v, _) => v.copy_semantic(gcv),
1068 _ => GosValue::new_nil(),
1069 };
1070 stack.push(GosValue::Metadata(val.get_meta(objs, stack)));
1071 if inst.t2_as_index() > 0 {
1072 let index = inst.imm();
1073 let s_index = Stack::offset(stack_base, index);
1074 stack.set(s_index, val);
1075 }
1076 }
1077 Opcode::IMPORT => {
1078 let pkey = pkgs[inst.imm() as usize];
1079 stack.push(GosValue::Bool(!objs.packages[pkey].inited()));
1080 }
1081 Opcode::SLICE | Opcode::SLICE_FULL => {
1082 let max = if inst_op == Opcode::SLICE_FULL {
1083 stack.pop_int()
1084 } else {
1085 -1
1086 };
1087 let end = stack.pop_int();
1088 let begin = stack.pop_int();
1089 let target = stack.pop_with_type(inst.t0());
1090 let result = match &target {
1091 GosValue::Slice(sl) => GosValue::Slice(Rc::new((
1092 sl.0.slice(begin, end, max),
1093 Cell::new(0),
1094 ))),
1095 GosValue::Str(s) => GosValue::Str(Rc::new(s.slice(begin, end))),
1096 GosValue::Array(_) => {
1097 GosValue::slice_with_array(&target, begin, end, gcv)
1098 }
1099 _ => unreachable!(),
1100 };
1101 stack.push(result);
1102 }
1103 Opcode::LITERAL => {
1104 let index = inst.imm();
1105 let param = &consts[index as usize];
1106 let new_val = match param {
1107 GosValue::Function(fkey) => {
1108 let mut val = ClosureObj::new_gos(*fkey, &objs.functions, None);
1110 if let Some(uvs) = &mut val.uvs {
1111 drop(frame);
1112 for (_, uv) in uvs.iter_mut() {
1113 let r: &mut UpValueState = &mut uv.inner.borrow_mut();
1114 if let UpValueState::Open(d) = r {
1115 for i in 1..frame_height {
1117 let index = frame_height - i;
1118 if self.frames[index].func() == d.func {
1119 let upframe = &mut self.frames[index];
1120 d.stack = Rc::downgrade(&self.stack);
1121 d.stack_base = upframe.stack_base as OpIndex;
1122 upframe.add_referred_by(d.index, d.typ, uv);
1123 break;
1125 }
1126 }
1127 }
1128 }
1130 frame = self.frames.last_mut().unwrap();
1131 }
1132 GosValue::new_runtime_closure(val, gcv)
1133 }
1134 GosValue::Metadata(md) => {
1135 let umd = md.get_underlying(&objs.metas);
1136 let (key, mc) = umd.unwrap_non_ptr();
1137 let count = stack.pop_int32();
1138 let val = match &objs.metas[key] {
1139 MetadataType::SliceOrArray(asm, _) => {
1140 let elem_type = asm.get_value_type(&objs.metas);
1141 let zero_val = asm.zero_val(&objs.metas, gcv);
1142 let mut val = vec![];
1143 let mut cur_index = -1;
1144 for _ in 0..count {
1145 let i = stack.pop_int();
1146 let elem = stack.pop_with_type(elem_type);
1147 if i < 0 {
1148 cur_index += 1;
1149 } else {
1150 cur_index = i;
1151 }
1152 let gap = cur_index - (val.len() as isize);
1153 if gap == 0 {
1154 val.push(elem);
1155 } else if gap > 0 {
1156 for _ in 0..gap {
1157 val.push(zero_val.clone());
1158 }
1159 val.push(elem);
1160 } else {
1161 val[cur_index as usize] = elem;
1162 }
1163 }
1164 match mc {
1165 MetaCategory::Default => {
1166 GosValue::slice_with_val(val, *md, gcv)
1167 }
1168 MetaCategory::Array => {
1169 GosValue::array_with_val(val, *md, gcv)
1170 }
1171 _ => unreachable!(),
1172 }
1173 }
1174 MetadataType::Map(km, vm) => {
1175 let gosv =
1176 GosValue::new_map(*md, zero_val!(vm, objs, gcv), gcv);
1177 let map = gosv.as_map();
1178 let tk = km.get_value_type(&objs.metas);
1179 let tv = vm.get_value_type(&objs.metas);
1180 for _ in 0..count {
1181 let k = stack.pop_with_type(tk);
1182 let v = stack.pop_with_type(tv);
1183 map.0.insert(k, v);
1184 }
1185 gosv
1186 }
1187 MetadataType::Struct(f, zero) => {
1188 let struct_val = zero.copy_semantic(gcv);
1189 let mut sref = struct_val.as_struct().0.borrow_mut();
1190 for _ in 0..count {
1191 let index = stack.pop_uint();
1192 let tv = f.fields[index].get_value_type(&objs.metas);
1193 sref.fields[index] = stack.pop_with_type(tv);
1194 }
1195 drop(sref);
1196 struct_val
1197 }
1198 _ => unreachable!(),
1199 };
1200 if umd == *md {
1201 val
1202 } else {
1203 GosValue::Named(Box::new((val, *md)))
1204 }
1205 }
1206 _ => unimplemented!(),
1207 };
1208 stack.push(new_val);
1209 }
1210
1211 Opcode::NEW => {
1212 let param = stack.pop_with_type(inst.t0());
1213 let new_val = match param {
1214 GosValue::Metadata(md) => {
1215 let v = md.default_val(&objs.metas, gcv);
1216 GosValue::new_pointer(PointerObj::UpVal(UpValue::new_closed(v)))
1217 }
1218 _ => unimplemented!(),
1219 };
1220 stack.push(new_val);
1221 }
1222 Opcode::MAKE => {
1223 let index = inst.imm();
1224 let i = Stack::offset(stack.len(), index - 1);
1225 let meta_val = stack.get_with_type(i, ValueType::Metadata);
1226 let meta = meta_val.as_meta();
1227 let metadata = &objs.metas[meta.as_non_ptr()];
1228 let val = match metadata {
1229 MetadataType::SliceOrArray(vmeta, _) => {
1230 let (cap, len) = match index {
1231 -2 => (stack.pop_int() as usize, stack.pop_int() as usize),
1232 -1 => {
1233 let len = stack.pop_int() as usize;
1234 (len, len)
1235 }
1236 _ => unreachable!(),
1237 };
1238 GosValue::new_slice(
1239 len,
1240 cap,
1241 *meta,
1242 Some(&zero_val!(vmeta, objs, gcv)),
1243 gcv,
1244 )
1245 }
1246 MetadataType::Map(_, v) => {
1247 let default = zero_val!(v, objs, gcv);
1248 GosValue::new_map(*meta, default, gcv)
1249 }
1250 MetadataType::Channel(_, _) => {
1251 let cap = match index {
1252 -1 => stack.pop_int() as usize,
1253 0 => 0,
1254 _ => unreachable!(),
1255 };
1256 GosValue::new_channel(*meta, cap)
1257 }
1258 _ => unreachable!(),
1259 };
1260 stack.pop_discard();
1261 stack.push(val);
1262 }
1263 Opcode::LEN => {
1264 let l = match &stack.pop_with_type(inst.t0()) {
1265 GosValue::Slice(slice) => slice.0.len(),
1266 GosValue::Map(map) => map.0.len(),
1267 GosValue::Str(sval) => sval.len(),
1268 GosValue::Channel(chan) => chan.len(),
1269 _ => unreachable!(),
1270 };
1271 stack.push(GosValue::Int(l as isize));
1272 }
1273 Opcode::CAP => {
1274 let l = match &stack.pop_with_type(inst.t0()) {
1275 GosValue::Slice(slice) => slice.0.cap(),
1276 GosValue::Channel(chan) => chan.cap(),
1277 _ => unreachable!(),
1278 };
1279 stack.push(GosValue::Int(l as isize));
1280 }
1281 Opcode::APPEND => {
1282 let index = Stack::offset(stack.len(), inst.imm());
1283 let a = stack.get_with_type(index - 2, ValueType::Slice);
1284 let vala = a.as_slice();
1285 stack.pack_variadic(index, vala.0.meta, inst.t1(), gcv);
1286 let b = stack.pop_with_type(ValueType::Slice);
1287 let valb = b.as_slice();
1288 vala.0
1289 .borrow_data_mut()
1290 .append(&mut valb.0.borrow_data().clone());
1291 }
1292 Opcode::CLOSE => {
1293 let chan = stack.pop_with_type(ValueType::Channel);
1294 chan.as_channel().close();
1295 }
1296 Opcode::PANIC => {
1297 let val = stack.pop_rc();
1298 go_panic!(panic, val, frame, code);
1299 }
1300 Opcode::RECOVER => {
1301 let p = panic.take();
1302 let val = p.map_or(GosValue::new_nil(), |x| x.msg);
1303 stack.push(val);
1304 }
1305 Opcode::ASSERT => {
1306 if !stack.pop_bool() {
1307 let msg = "Opcode::ASSERT: not true!".to_string();
1308 go_panic_str!(panic, metadata, msg, frame, code);
1309 }
1310 }
1311 Opcode::FFI => {
1312 let meta = stack.pop_with_type(ValueType::Metadata);
1313 let total_params = inst.imm();
1314 let index = Stack::offset(stack.len(), -total_params);
1315 let itype = stack.get_with_type(index, ValueType::Metadata);
1316 let name = stack.get_with_type(index + 1, ValueType::Str);
1317 let name_str = name.as_str().as_str();
1318 let ptypes = &objs.metas[meta.as_meta().as_non_ptr()]
1319 .as_signature()
1320 .params_type[2..];
1321 let params = stack.pop_with_type_n(ptypes);
1322 let v = match self.context.ffi_factory.create_by_name(name_str, params) {
1323 Ok(v) => {
1324 let meta = itype.as_meta().get_underlying(&objs.metas).clone();
1325 let info = objs.metas[meta.as_non_ptr()]
1326 .as_interface()
1327 .iface_ffi_info();
1328 GosValue::new_iface(
1329 meta,
1330 IfaceUnderlying::Ffi(UnderlyingFfi::new(v, info)),
1331 )
1332 }
1333 Err(e) => {
1334 go_panic_str!(panic, metadata, e, frame, code);
1335 continue;
1336 }
1337 };
1338 stack.push(v);
1339 }
1340 _ => {
1341 dbg!(inst_op);
1342 unimplemented!();
1343 }
1344 };
1345 } match result {
1348 Result::End => {
1349 if let Some(p) = panic {
1350 println!("panic: {}", p.msg);
1351 if let Some(files) = self.context.fs {
1352 for (fkey, pc) in p.call_stack.iter() {
1353 let func = &objs.functions[*fkey];
1354 if let Some(p) = func.pos()[*pc] {
1355 println!("{}", files.position(p));
1356 } else {
1357 println!("<no debug info available>");
1358 }
1359 }
1360 }
1361
1362 if let GosValue::Str(s) =
1364 p.msg.as_interface().borrow().underlying_value().unwrap()
1365 {
1366 if s.as_str().starts_with("Opcode::ASSERT") {
1367 panic!("ASSERT");
1368 }
1369 }
1370 }
1371 break;
1372 }
1373 Result::Continue => {
1374 drop(stack_mut_ref);
1375 future::yield_now().await;
1376 restore_stack_ref!(self, stack, stack_mut_ref);
1377 }
1378 };
1379 } stack.clear_rc_garbage();
1382 gc(gcv);
1383 }
1384}
1385
1386pub struct GosVM<'a> {
1387 code: ByteCode,
1388 gcv: GcoVec,
1389 ffi: &'a FfiFactory,
1390 fs: Option<&'a FileSet>,
1391}
1392
1393impl<'a> GosVM<'a> {
1394 pub fn new(bc: ByteCode, ffi: &'a FfiFactory, fs: Option<&'a FileSet>) -> GosVM<'a> {
1395 GosVM {
1396 code: bc,
1397 gcv: GcoVec::new(),
1398 ffi: ffi,
1399 fs: fs,
1400 }
1401 }
1402
1403 pub fn run(&self) {
1404 let exec = Rc::new(LocalExecutor::new());
1405 let ctx = Context::new(exec.clone(), &self.code, &self.gcv, self.ffi, self.fs);
1406 let entry = ctx.new_entry_frame(self.code.entry);
1407 ctx.spawn_fiber(Stack::new(), entry);
1408
1409 future::block_on(async {
1410 loop {
1411 if !exec.try_tick() {
1412 break;
1413 }
1414 }
1415 });
1416 }
1417}
1418
1419#[cfg(test)]
1420mod test {}