go_vm/
objects.rs

1// Copyright 2022 The Goscript Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5#![macro_use]
6
7#[cfg(feature = "async")]
8use crate::channel::Channel;
9use crate::ffi::Ffi;
10use crate::gc::GcContainer;
11use crate::instruction::{Instruction, OpIndex, ValueType};
12use crate::metadata::*;
13use crate::stack::Stack;
14use crate::value::*;
15
16#[cfg(feature = "serde_borsh")]
17use borsh::{
18    maybestd::io::Result as BorshResult, maybestd::io::Write as BorshWrite, BorshDeserialize,
19    BorshSerialize,
20};
21use go_parser::{Map, MapIter, PiggyVecKey};
22use std::any::Any;
23use std::borrow::Cow;
24use std::cell::{Cell, Ref, RefCell, RefMut};
25use std::cmp::Ordering;
26use std::fmt::{self, Debug, Display, Write};
27use std::hash::{Hash, Hasher};
28use std::marker::PhantomData;
29use std::ops::Range;
30use std::rc::{Rc, Weak};
31use std::{panic, ptr, str};
32
33// ----------------------------------------------------------------------------
34// MapObj
35
36pub type GosMap = Map<GosValue, GosValue>;
37
38pub type GosMapIter<'a> = MapIter<'a, GosValue, GosValue>;
39
40#[derive(Debug)]
41pub struct MapObj {
42    map: RefCell<GosMap>,
43}
44
45impl MapObj {
46    #[inline]
47    pub fn new() -> MapObj {
48        Self::with_data(Map::new())
49    }
50
51    #[inline]
52    pub fn with_data(data: GosMap) -> MapObj {
53        MapObj {
54            map: RefCell::new(data),
55        }
56    }
57
58    #[inline]
59    pub fn insert(&self, key: GosValue, val: GosValue) -> Option<GosValue> {
60        self.borrow_data_mut().insert(key, val)
61    }
62
63    #[inline]
64    pub fn get(&self, key: &GosValue) -> Option<GosValue> {
65        let borrow = self.borrow_data();
66        let val = borrow.get(key);
67        match val {
68            Some(v) => Some(v.clone()),
69            None => None,
70        }
71    }
72
73    #[inline]
74    pub fn delete(&self, key: &GosValue) {
75        let mut mref = self.borrow_data_mut();
76        mref.remove(key);
77    }
78
79    #[inline]
80    pub fn len(&self) -> usize {
81        self.borrow_data().len()
82    }
83
84    #[inline]
85    pub fn borrow_data_mut(&self) -> RefMut<GosMap> {
86        self.map.borrow_mut()
87    }
88
89    #[inline]
90    pub fn borrow_data(&self) -> Ref<GosMap> {
91        self.map.borrow()
92    }
93
94    #[inline]
95    pub fn clone_inner(&self) -> RefCell<GosMap> {
96        self.map.clone()
97    }
98}
99
100impl Clone for MapObj {
101    fn clone(&self) -> Self {
102        MapObj {
103            map: self.map.clone(),
104        }
105    }
106}
107
108impl PartialEq for MapObj {
109    fn eq(&self, _other: &MapObj) -> bool {
110        unreachable!()
111    }
112}
113
114impl Eq for MapObj {}
115
116impl Display for MapObj {
117    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118        f.write_str("map[")?;
119        for (i, kv) in self.map.borrow().iter().enumerate() {
120            if i > 0 {
121                f.write_char(' ')?;
122            }
123            let v: &GosValue = &kv.1;
124            write!(f, "{}:{}", kv.0, v)?
125        }
126        f.write_char(']')
127    }
128}
129
130// ----------------------------------------------------------------------------
131// ArrayObj
132
133/// Element is used to store GosValue in Typed containers to save memomry
134pub trait Element: Clone + Hash + Debug {
135    fn from_value(val: GosValue) -> Self;
136
137    fn into_value(self, t: ValueType) -> GosValue;
138
139    fn set_value(&self, val: &GosValue);
140
141    fn need_gc() -> bool {
142        false
143    }
144
145    fn copy_or_clone_slice(dst: &mut [Self], src: &[Self]) {
146        dst.clone_from_slice(src)
147    }
148}
149
150#[derive(Clone, PartialEq, Eq, Debug, PartialOrd, Ord)]
151pub struct GosElem {
152    cell: RefCell<GosValue>,
153}
154
155impl GosElem {
156    /// for gc
157    pub fn ref_sub_one(&self) {
158        self.cell.borrow().ref_sub_one();
159    }
160
161    /// for gc
162    pub fn mark_dirty(&self, queue: &mut RCQueue) {
163        self.cell.borrow().mark_dirty(queue);
164    }
165
166    pub fn borrow(&self) -> Ref<GosValue> {
167        self.cell.borrow()
168    }
169
170    pub fn borrow_mut(&self) -> RefMut<GosValue> {
171        self.cell.borrow_mut()
172    }
173}
174
175impl std::fmt::Display for GosElem {
176    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
177        std::fmt::Display::fmt(&self.cell.borrow(), f)
178    }
179}
180
181impl Hash for GosElem {
182    fn hash<H: Hasher>(&self, state: &mut H) {
183        self.cell.borrow().hash(state)
184    }
185}
186
187impl Element for GosElem {
188    #[inline]
189    fn from_value(val: GosValue) -> Self {
190        GosElem {
191            cell: RefCell::new(val),
192        }
193    }
194
195    #[inline]
196    fn into_value(self, t: ValueType) -> GosValue {
197        let v = self.cell.into_inner();
198        assert!(v.typ() == t);
199        v
200    }
201
202    #[inline]
203    fn set_value(&self, val: &GosValue) {
204        self.cell.replace(val.clone());
205    }
206
207    #[inline]
208    fn need_gc() -> bool {
209        true
210    }
211}
212
213/// Cell is much cheaper than RefCell, used to store basic types
214#[cfg_attr(feature = "serde_borsh", derive(BorshDeserialize, BorshSerialize))]
215#[derive(Clone, PartialEq, Eq, Debug, PartialOrd, Ord)]
216pub struct CellElem<T>
217where
218    T: Copy + PartialEq,
219{
220    pub cell: Cell<T>,
221}
222
223impl<T> CellElem<T>
224where
225    T: Copy + PartialEq,
226{
227    #[inline]
228    pub fn into_inner(self) -> T {
229        self.cell.into_inner()
230    }
231
232    #[inline]
233    pub fn slice_into_inner<U>(inner_slice: &[Self]) -> &[U] {
234        assert!(core::mem::size_of::<T>() == core::mem::size_of::<U>());
235        unsafe { std::mem::transmute(inner_slice) }
236    }
237
238    #[inline]
239    pub fn slice_into_inner_mut<U>(inner_slice: &mut [Self]) -> &mut [U] {
240        assert!(core::mem::size_of::<T>() == core::mem::size_of::<U>());
241        unsafe { std::mem::transmute(inner_slice) }
242    }
243
244    #[inline]
245    pub fn slice_ref_into_inner<U>(inner_slice: Ref<[Self]>) -> Ref<[U]> {
246        assert!(core::mem::size_of::<T>() == core::mem::size_of::<U>());
247        unsafe { std::mem::transmute(inner_slice) }
248    }
249
250    #[inline]
251    pub fn slice_ref_into_inner_mut<U>(inner_slice: RefMut<[Self]>) -> RefMut<[U]> {
252        assert!(core::mem::size_of::<T>() == core::mem::size_of::<U>());
253        unsafe { std::mem::transmute(inner_slice) }
254    }
255
256    #[inline]
257    fn clone_slice(dst: &mut [Self], src: &[Self]) {
258        let d: &mut [T] = Self::slice_into_inner_mut(dst);
259        let s: &[T] = &Self::slice_into_inner(src);
260        d.copy_from_slice(s)
261    }
262}
263
264pub trait CellData: Copy + PartialEq + Hash + Debug {
265    fn from_value(val: &GosValue) -> Self;
266
267    fn into_value(self, t: ValueType) -> GosValue;
268}
269
270macro_rules! impl_cell_data {
271    ($typ:ty, $as:tt, $value_type:tt, $new:tt) => {
272        impl CellData for $typ {
273            fn from_value(val: &GosValue) -> Self {
274                *val.$as()
275            }
276
277            fn into_value(self, t: ValueType) -> GosValue {
278                GosValue::new(t, ValueData::$new(self))
279            }
280        }
281    };
282}
283
284impl_cell_data!(u8, as_uint8, Uint8, new_uint8);
285impl_cell_data!(u16, as_uint16, Uint16, new_uint16);
286impl_cell_data!(u32, as_uint32, Uint32, new_uint32);
287impl_cell_data!(u64, as_uint64, Uint64, new_uint64);
288impl_cell_data!(usize, as_uint, Uint, new_uint);
289
290pub type Elem8 = CellElem<u8>;
291pub type Elem16 = CellElem<u16>;
292pub type Elem32 = CellElem<u32>;
293pub type Elem64 = CellElem<u64>;
294pub type ElemWord = CellElem<usize>;
295
296/// This can be used when any version of Slice/Array returns the same thing
297/// kind of unsafe
298pub type AnyElem = CellElem<u8>;
299
300impl<T> Hash for CellElem<T>
301where
302    T: CellData,
303{
304    fn hash<H: Hasher>(&self, state: &mut H) {
305        let d = self.cell.get();
306        d.hash(state)
307    }
308}
309
310impl<T> Element for CellElem<T>
311where
312    T: CellData,
313{
314    #[inline]
315    fn from_value(val: GosValue) -> Self {
316        CellElem {
317            cell: Cell::new(T::from_value(&val)),
318        }
319    }
320
321    #[inline]
322    fn into_value(self, t: ValueType) -> GosValue {
323        self.cell.get().into_value(t)
324    }
325
326    #[inline]
327    fn set_value(&self, val: &GosValue) {
328        self.cell.set(T::from_value(val));
329    }
330
331    #[inline]
332    fn copy_or_clone_slice(dst: &mut [Self], src: &[Self]) {
333        Self::clone_slice(dst, src)
334    }
335}
336
337pub struct ArrayObj<T> {
338    vec: RefCell<Vec<T>>,
339}
340
341pub type GosArrayObj = ArrayObj<GosElem>;
342
343impl<T> ArrayObj<T>
344where
345    T: Element,
346{
347    pub(crate) fn with_size(
348        size: usize,
349        cap: usize,
350        val: &GosValue,
351        gcos: &GcContainer,
352    ) -> ArrayObj<T> {
353        assert!(cap >= size);
354        let mut v = Vec::with_capacity(cap);
355        for _ in 0..size {
356            v.push(T::from_value(val.copy_semantic(gcos)))
357        }
358        ArrayObj {
359            vec: RefCell::new(v),
360        }
361    }
362
363    pub fn with_data(data: Vec<GosValue>) -> ArrayObj<T> {
364        ArrayObj {
365            vec: RefCell::new(data.into_iter().map(|x| T::from_value(x)).collect()),
366        }
367    }
368
369    pub fn with_raw_data(data: Vec<T>) -> ArrayObj<T> {
370        ArrayObj {
371            vec: RefCell::new(data),
372        }
373    }
374
375    #[inline(always)]
376    pub fn len(&self) -> usize {
377        self.borrow_data().len()
378    }
379
380    #[inline(always)]
381    pub fn borrow_data_mut(&self) -> std::cell::RefMut<Vec<T>> {
382        self.vec.borrow_mut()
383    }
384
385    #[inline(always)]
386    pub fn borrow_data(&self) -> std::cell::Ref<Vec<T>> {
387        self.vec.borrow()
388    }
389
390    #[inline]
391    pub fn as_rust_slice(&self) -> Ref<[T]> {
392        Ref::map(self.borrow_data(), |x| &x[..])
393    }
394
395    #[inline]
396    pub fn as_rust_slice_mut(&self) -> RefMut<[T]> {
397        RefMut::map(self.borrow_data_mut(), |x| &mut x[..])
398    }
399
400    #[inline(always)]
401    pub fn index_elem(&self, i: usize) -> T {
402        self.borrow_data()[i].clone()
403    }
404
405    #[inline(always)]
406    pub fn get(&self, i: usize, t: ValueType) -> RuntimeResult<GosValue> {
407        if i >= self.len() {
408            return Err(format!("index {} out of range", i).to_owned().into());
409        }
410        Ok(self.borrow_data()[i].clone().into_value(t))
411    }
412
413    #[inline(always)]
414    pub fn set(&self, i: usize, val: &GosValue) -> RuntimeResult<()> {
415        if i >= self.len() {
416            return Err(format!("index {} out of range", i).to_owned().into());
417        }
418        Ok(self.borrow_data()[i].set_value(&val))
419    }
420
421    #[inline]
422    pub fn size_of_data(&self) -> usize {
423        std::mem::size_of::<T>() * self.len()
424    }
425}
426
427impl<T> ArrayObj<CellElem<T>>
428where
429    T: CellData,
430{
431    #[inline]
432    pub fn as_raw_slice<U>(&self) -> Ref<[U]> {
433        CellElem::<T>::slice_ref_into_inner(self.as_rust_slice())
434    }
435
436    #[inline]
437    pub fn as_raw_slice_mut<U>(&self) -> RefMut<[U]> {
438        CellElem::<T>::slice_ref_into_inner_mut(self.as_rust_slice_mut())
439    }
440}
441
442impl<T> Hash for ArrayObj<T>
443where
444    T: Element,
445{
446    fn hash<H: Hasher>(&self, state: &mut H) {
447        for e in self.borrow_data().iter() {
448            e.hash(state);
449        }
450    }
451}
452
453impl<T> Eq for ArrayObj<T> where T: Element + PartialEq {}
454
455impl<T> PartialEq for ArrayObj<T>
456where
457    T: Element + PartialEq,
458{
459    fn eq(&self, b: &ArrayObj<T>) -> bool {
460        if self.borrow_data().len() != b.borrow_data().len() {
461            return false;
462        }
463        let bdata = b.borrow_data();
464        for (i, e) in self.borrow_data().iter().enumerate() {
465            if e != bdata.get(i).unwrap() {
466                return false;
467            }
468        }
469        true
470    }
471}
472
473impl<T> PartialOrd for ArrayObj<T>
474where
475    T: Element + PartialEq + Ord,
476{
477    #[inline]
478    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
479        Some(self.cmp(other))
480    }
481}
482
483impl<T> Ord for ArrayObj<T>
484where
485    T: Element + PartialEq + Ord,
486{
487    fn cmp(&self, other: &Self) -> Ordering {
488        let a = self.borrow_data();
489        let b = other.borrow_data();
490        let order = a.len().cmp(&b.len());
491        if order != Ordering::Equal {
492            return order;
493        }
494        for (i, elem) in self.borrow_data().iter().enumerate() {
495            let order = elem.cmp(&b[i]);
496            if order != Ordering::Equal {
497                return order;
498            }
499        }
500
501        Ordering::Equal
502    }
503}
504
505impl<T> Clone for ArrayObj<T>
506where
507    T: Element + PartialEq,
508{
509    fn clone(&self) -> Self {
510        ArrayObj {
511            vec: RefCell::new(self.borrow_data().iter().map(|x| x.clone()).collect()),
512        }
513    }
514}
515
516// ----------------------------------------------------------------------------
517// SliceObj
518
519#[derive(Clone)]
520pub struct SliceObj<T> {
521    array: GosValue,
522    begin: Cell<usize>,
523    end: Cell<usize>,
524    // This is not capacity, but rather the max index that can be sliced.
525    cap_end: Cell<usize>,
526    phantom: PhantomData<T>,
527}
528
529pub type GosSliceObj = SliceObj<GosElem>;
530
531impl<T> SliceObj<T>
532where
533    T: Element,
534{
535    pub fn with_array(arr: GosValue, begin: isize, end: isize) -> RuntimeResult<SliceObj<T>> {
536        let len = arr.as_array::<T>().0.len();
537        let (bi, ei, cap) = SliceObj::<T>::check_indices(0, len, len, begin, end, -1)?;
538        Ok(SliceObj {
539            begin: Cell::from(bi),
540            end: Cell::from(ei),
541            cap_end: Cell::from(cap),
542            array: arr,
543            phantom: PhantomData,
544        })
545    }
546
547    /// Get a reference to the slice obj's array.
548    #[must_use]
549    #[inline]
550    pub fn array(&self) -> &GosValue {
551        &self.array
552    }
553
554    #[inline(always)]
555    pub fn array_obj(&self) -> &ArrayObj<T> {
556        &self.array.as_array::<T>().0
557    }
558
559    #[inline(always)]
560    pub fn begin(&self) -> usize {
561        self.begin.get()
562    }
563
564    #[inline(always)]
565    pub fn end(&self) -> usize {
566        self.end.get()
567    }
568
569    #[inline(always)]
570    pub fn len(&self) -> usize {
571        self.end() - self.begin()
572    }
573
574    #[inline(always)]
575    pub fn cap(&self) -> usize {
576        self.cap_end.get() - self.begin()
577    }
578
579    #[inline(always)]
580    pub fn range(&self) -> Range<usize> {
581        self.begin.get()..self.end.get()
582    }
583
584    #[inline]
585    pub fn as_rust_slice(&self) -> Ref<[T]> {
586        Ref::map(self.borrow_all_data(), |x| {
587            &x[self.begin.get()..self.end.get()]
588        })
589    }
590
591    #[inline]
592    pub fn as_rust_slice_mut(&self) -> RefMut<[T]> {
593        RefMut::map(self.borrow_all_data_mut(), |x| {
594            &mut x[self.begin.get()..self.end.get()]
595        })
596    }
597
598    #[inline]
599    pub fn sharing_with(&self, other: &SliceObj<T>) -> bool {
600        self.array.as_addr() == other.array.as_addr()
601    }
602
603    /// get_array_equivalent returns the underlying array and mapped index
604    #[inline]
605    pub fn get_array_equivalent(&self, i: usize) -> (&GosValue, usize) {
606        (self.array(), self.begin() + i)
607    }
608
609    #[inline(always)]
610    pub fn index_elem(&self, i: usize) -> T {
611        self.array_obj().index_elem(self.begin() + i)
612    }
613
614    #[inline(always)]
615    pub fn get(&self, i: usize, t: ValueType) -> RuntimeResult<GosValue> {
616        self.array_obj().get(self.begin() + i, t)
617    }
618
619    #[inline(always)]
620    pub fn set(&self, i: usize, val: &GosValue) -> RuntimeResult<()> {
621        self.array_obj().set(i, val)
622    }
623
624    #[inline]
625    pub fn push(&mut self, val: GosValue) {
626        let mut data = self.borrow_all_data_mut();
627        if data.len() == self.len() {
628            data.push(T::from_value(val))
629        } else {
630            data[self.end()] = T::from_value(val);
631        }
632        drop(data);
633        *self.end.get_mut() += 1;
634        if self.cap_end.get() < self.end.get() {
635            *self.cap_end.get_mut() += 1;
636        }
637    }
638
639    #[inline]
640    pub fn append(&mut self, other: &SliceObj<T>) {
641        let mut data = self.borrow_all_data_mut();
642        let new_end = self.end() + other.len();
643        let after_end_len = data.len() - self.end();
644        let sharing = self.sharing_with(other);
645        if after_end_len <= other.len() {
646            data.truncate(self.end());
647            if !sharing {
648                data.extend_from_slice(&other.as_rust_slice());
649            } else {
650                data.extend_from_within(other.range());
651            }
652        } else {
653            if !sharing {
654                T::copy_or_clone_slice(&mut data[self.end()..new_end], &other.as_rust_slice());
655            } else {
656                let cloned = data[other.range()].to_vec();
657                T::copy_or_clone_slice(&mut data[self.end()..new_end], &cloned);
658            }
659        }
660        drop(data);
661        *self.end.get_mut() = new_end;
662        if self.cap_end.get() < self.end.get() {
663            *self.cap_end.get_mut() = self.end.get();
664        }
665    }
666
667    #[inline]
668    pub fn copy_from(&self, other: &SliceObj<T>) -> usize {
669        let other_range = other.range();
670        let (left, right) = match self.len() >= other.len() {
671            true => (self.begin()..self.begin() + other.len(), other_range),
672            false => (
673                self.begin()..self.end(),
674                other_range.start..other_range.start + self.len(),
675            ),
676        };
677        let len = left.len();
678        let sharing = self.sharing_with(other);
679        let data = &mut self.borrow_all_data_mut();
680        if !sharing {
681            T::copy_or_clone_slice(&mut data[left], &other.borrow_all_data()[right]);
682        } else {
683            let cloned = data[right].to_vec();
684            T::copy_or_clone_slice(&mut data[left], &cloned);
685        }
686        len
687    }
688
689    #[inline]
690    pub fn slice(&self, begin: isize, end: isize, max: isize) -> RuntimeResult<SliceObj<T>> {
691        let (bi, ei, cap) = SliceObj::<T>::check_indices(
692            self.begin(),
693            self.len(),
694            self.cap_end.get(),
695            begin,
696            end,
697            max,
698        )?;
699        Ok(SliceObj {
700            begin: Cell::from(bi),
701            end: Cell::from(ei),
702            cap_end: Cell::from(cap),
703            array: self.array.clone(),
704            phantom: PhantomData,
705        })
706    }
707
708    #[inline]
709    pub fn swap(&self, i: usize, j: usize) -> RuntimeResult<()> {
710        let len = self.len();
711        if i >= len {
712            Err(format!("index {} out of range", i).into())
713        } else if j >= len {
714            Err(format!("index {} out of range", j).into())
715        } else {
716            self.borrow_all_data_mut()
717                .swap(i + self.begin(), j + self.begin());
718            Ok(())
719        }
720    }
721
722    #[inline]
723    fn borrow_all_data_mut(&self) -> std::cell::RefMut<Vec<T>> {
724        self.array_obj().borrow_data_mut()
725    }
726
727    #[inline]
728    fn borrow_all_data(&self) -> std::cell::Ref<Vec<T>> {
729        self.array_obj().borrow_data()
730    }
731
732    #[inline]
733    fn check_indices(
734        this_begin: usize,
735        this_len: usize,
736        this_cap: usize,
737        begin: isize,
738        end: isize,
739        max: isize,
740    ) -> RuntimeResult<(usize, usize, usize)> {
741        let bi = this_begin + begin as usize;
742        if bi > this_cap {
743            return Err(format!("index {} out of range", begin).to_owned().into());
744        }
745
746        let cap = if max < 0 {
747            this_cap
748        } else {
749            let val = max as usize;
750            if val > this_cap {
751                return Err(format!("index {} out of range", max).to_owned().into());
752            }
753            val
754        };
755
756        let ei = if end < 0 {
757            this_len
758        } else {
759            let val = this_begin + end as usize;
760            if val < bi || val > cap {
761                return Err(format!("index {} out of range", end).to_owned().into());
762            }
763            val
764        };
765
766        Ok((bi, ei, cap))
767    }
768}
769
770impl<T> SliceObj<CellElem<T>>
771where
772    T: CellData,
773{
774    #[inline]
775    pub fn as_raw_slice<U>(&self) -> Ref<[U]> {
776        CellElem::<T>::slice_ref_into_inner(self.as_rust_slice())
777    }
778
779    #[inline]
780    pub fn as_raw_slice_mut<U>(&self) -> RefMut<[U]> {
781        CellElem::<T>::slice_ref_into_inner_mut(self.as_rust_slice_mut())
782    }
783}
784
785impl<T> PartialEq for SliceObj<T> {
786    fn eq(&self, _other: &SliceObj<T>) -> bool {
787        unreachable!() //false
788    }
789}
790
791impl<T> Eq for SliceObj<T> {}
792
793pub type SliceIter<'a, T> = std::slice::Iter<'a, T>;
794
795pub type SliceEnumIter<'a, T> = std::iter::Enumerate<SliceIter<'a, T>>;
796
797// ----------------------------------------------------------------------------
798// StringObj
799
800pub type StringIter<'a> = std::str::Chars<'a>;
801
802pub type StringEnumIter<'a> = std::iter::Enumerate<StringIter<'a>>;
803
804pub type StringObj = SliceObj<Elem8>;
805
806impl StringObj {
807    #[inline]
808    pub fn with_str(s: &str) -> StringObj {
809        let buf: Vec<Elem8> = unsafe { std::mem::transmute(s.as_bytes().to_vec()) };
810        Self::with_buf(buf)
811    }
812
813    #[inline]
814    fn with_buf(buf: Vec<Elem8>) -> StringObj {
815        let arr = GosValue::new_non_gc_array(ArrayObj::with_raw_data(buf), ValueType::Uint8);
816        SliceObj::with_array(arr, 0, -1).unwrap()
817    }
818
819    /// It's safe because strings are readonly
820    /// <https://stackoverflow.com/questions/50431702/is-it-safe-and-defined-behavior-to-transmute-between-a-t-and-an-unsafecellt>
821    /// <https://doc.rust-lang.org/src/core/str/converts.rs.html#173>
822    #[inline]
823    pub fn as_str(&self) -> Ref<str> {
824        unsafe { std::mem::transmute(self.as_rust_slice()) }
825    }
826
827    #[inline]
828    pub fn index(&self, i: usize) -> RuntimeResult<GosValue> {
829        self.get(i, ValueType::Uint8)
830    }
831
832    #[inline]
833    pub fn index_elem_u8(&self, i: usize) -> u8 {
834        self.index_elem(i).into_inner()
835    }
836
837    #[inline]
838    pub fn add(&self, other: &StringObj) -> StringObj {
839        let mut buf = self.as_rust_slice().to_vec();
840        buf.extend_from_slice(&other.as_rust_slice());
841        Self::with_buf(buf)
842    }
843}
844
845// ----------------------------------------------------------------------------
846// StructObj
847
848#[derive(Clone, Debug)]
849pub struct StructObj {
850    fields: RefCell<Vec<GosValue>>,
851}
852
853impl StructObj {
854    pub fn new(fields: Vec<GosValue>) -> StructObj {
855        StructObj {
856            fields: RefCell::new(fields),
857        }
858    }
859
860    #[inline]
861    pub fn borrow_fields(&self) -> Ref<Vec<GosValue>> {
862        self.fields.borrow()
863    }
864
865    #[inline]
866    pub fn borrow_fields_mut(&self) -> RefMut<Vec<GosValue>> {
867        self.fields.borrow_mut()
868    }
869}
870
871impl Eq for StructObj {}
872
873impl PartialEq for StructObj {
874    #[inline]
875    fn eq(&self, other: &StructObj) -> bool {
876        let other_fields = other.borrow_fields();
877        for (i, f) in self.borrow_fields().iter().enumerate() {
878            if f != &other_fields[i] {
879                return false;
880            }
881        }
882        return true;
883    }
884}
885
886impl PartialOrd for StructObj {
887    #[inline]
888    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
889        Some(self.cmp(other))
890    }
891}
892
893// For when used as a BTreeMap key
894impl Ord for StructObj {
895    fn cmp(&self, other: &Self) -> Ordering {
896        let other_fields = other.borrow_fields();
897        for (i, f) in self.borrow_fields().iter().enumerate() {
898            let order = f.cmp(&other_fields[i]);
899            if order != Ordering::Equal {
900                return order;
901            }
902        }
903        Ordering::Equal
904    }
905}
906
907impl Hash for StructObj {
908    #[inline]
909    fn hash<H: Hasher>(&self, state: &mut H) {
910        for f in self.borrow_fields().iter() {
911            f.hash(state)
912        }
913    }
914}
915
916impl Display for StructObj {
917    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
918        f.write_char('{')?;
919        for (i, fld) in self.borrow_fields().iter().enumerate() {
920            if i > 0 {
921                f.write_char(' ')?;
922            }
923            write!(f, "{}", fld)?
924        }
925        f.write_char('}')
926    }
927}
928
929// ----------------------------------------------------------------------------
930// InterfaceObj
931
932#[derive(Clone, Debug)]
933pub struct UnderlyingFfi {
934    pub ffi_obj: Rc<dyn Ffi>,
935    pub meta: Meta,
936}
937
938impl UnderlyingFfi {
939    pub fn new(ffi_obj: Rc<dyn Ffi>, meta: Meta) -> UnderlyingFfi {
940        UnderlyingFfi { ffi_obj, meta }
941    }
942}
943
944/// Info about how to invoke a method of the underlying value
945/// of an interface
946#[derive(Clone, Debug)]
947pub enum IfaceBinding {
948    Struct(Rc<RefCell<MethodDesc>>, Option<Vec<OpIndex>>),
949    Iface(usize, Option<Vec<OpIndex>>),
950}
951
952#[cfg_attr(feature = "serde_borsh", derive(BorshDeserialize, BorshSerialize))]
953#[derive(Clone, Debug)]
954pub enum Binding4Runtime {
955    Struct(FunctionKey, bool, Option<Vec<OpIndex>>),
956    Iface(usize, Option<Vec<OpIndex>>),
957}
958
959impl From<IfaceBinding> for Binding4Runtime {
960    fn from(item: IfaceBinding) -> Binding4Runtime {
961        match item {
962            IfaceBinding::Struct(f, indices) => {
963                let md = f.borrow();
964                Binding4Runtime::Struct(md.func.unwrap(), md.pointer_recv, indices)
965            }
966            IfaceBinding::Iface(a, b) => Binding4Runtime::Iface(a, b),
967        }
968    }
969}
970
971#[derive(Clone, Debug)]
972pub enum InterfaceObj {
973    /// The GosValue is the underlying value of the interface.
974    /// Meta is the type info of the underlying value.
975    /// Vec<Binding4Runtime>)> is used to invoke methods of the underlying value.
976    ///
977    /// The Meta and Binding info are all determined at compile time, unless you
978    /// create an interface via FFI.
979    Gos(GosValue, Option<(Meta, Vec<Binding4Runtime>)>),
980    Ffi(UnderlyingFfi),
981}
982
983impl InterfaceObj {
984    pub fn with_value(val: GosValue, meta: Option<(Meta, Vec<Binding4Runtime>)>) -> InterfaceObj {
985        InterfaceObj::Gos(val, meta)
986    }
987
988    #[inline]
989    pub fn underlying_value(&self) -> Option<&GosValue> {
990        match self {
991            Self::Gos(v, _) => Some(v),
992            _ => None,
993        }
994    }
995
996    #[inline]
997    pub fn equals_value(&self, val: &GosValue) -> bool {
998        match self.underlying_value() {
999            Some(v) => v == val,
1000            None => false,
1001        }
1002    }
1003
1004    /// for gc
1005    pub fn ref_sub_one(&self) {
1006        match self {
1007            Self::Gos(v, _) => v.ref_sub_one(),
1008            _ => {}
1009        };
1010    }
1011
1012    /// for gc
1013    pub fn mark_dirty(&self, queue: &mut RCQueue) {
1014        match self {
1015            Self::Gos(v, _) => v.mark_dirty(queue),
1016            _ => {}
1017        };
1018    }
1019}
1020
1021impl Eq for InterfaceObj {}
1022
1023impl PartialEq for InterfaceObj {
1024    #[inline]
1025    fn eq(&self, other: &Self) -> bool {
1026        match (self, other) {
1027            (Self::Gos(x, _), Self::Gos(y, _)) => x == y,
1028            (Self::Ffi(x), Self::Ffi(y)) => Rc::ptr_eq(&x.ffi_obj, &y.ffi_obj),
1029            _ => false,
1030        }
1031    }
1032}
1033
1034impl PartialOrd for InterfaceObj {
1035    #[inline]
1036    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1037        Some(self.cmp(other))
1038    }
1039}
1040
1041impl Ord for InterfaceObj {
1042    fn cmp(&self, other: &Self) -> Ordering {
1043        match (self, other) {
1044            (Self::Gos(x, _), Self::Gos(y, _)) => {
1045                let xt = x.typ();
1046                let yt = y.typ();
1047                if xt == yt {
1048                    x.cmp(y)
1049                } else {
1050                    xt.cmp(&yt)
1051                }
1052            }
1053            (Self::Ffi(x), Self::Ffi(y)) => Rc::as_ptr(&x.ffi_obj).cmp(&Rc::as_ptr(&y.ffi_obj)),
1054            (Self::Gos(_, _), Self::Ffi(_)) => Ordering::Greater,
1055            (Self::Ffi(_), Self::Gos(_, _)) => Ordering::Less,
1056        }
1057    }
1058}
1059
1060impl Hash for InterfaceObj {
1061    #[inline]
1062    fn hash<H: Hasher>(&self, state: &mut H) {
1063        match self {
1064            Self::Gos(v, _) => v.hash(state),
1065            Self::Ffi(ffi) => Rc::as_ptr(&ffi.ffi_obj).hash(state),
1066        }
1067    }
1068}
1069
1070impl Display for InterfaceObj {
1071    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1072        match self {
1073            Self::Gos(v, _) => write!(f, "{}", v),
1074            Self::Ffi(ffi) => write!(f, "<ffi>{:?}", ffi.ffi_obj),
1075        }
1076    }
1077}
1078
1079// ----------------------------------------------------------------------------
1080// ChannelObj
1081#[cfg(feature = "async")]
1082#[derive(Clone, Debug)]
1083pub struct ChannelObj {
1084    pub recv_zero: GosValue,
1085    pub chan: Channel,
1086}
1087
1088#[cfg(feature = "async")]
1089impl ChannelObj {
1090    pub fn new(cap: usize, recv_zero: GosValue) -> ChannelObj {
1091        ChannelObj {
1092            chan: Channel::new(cap),
1093            recv_zero: recv_zero,
1094        }
1095    }
1096
1097    pub fn with_chan(chan: Channel, recv_zero: GosValue) -> ChannelObj {
1098        ChannelObj {
1099            chan: chan,
1100            recv_zero: recv_zero,
1101        }
1102    }
1103
1104    #[inline]
1105    pub fn len(&self) -> usize {
1106        self.chan.len()
1107    }
1108
1109    #[inline]
1110    pub fn cap(&self) -> usize {
1111        self.chan.cap()
1112    }
1113
1114    #[inline]
1115    pub fn close(&self) {
1116        self.chan.close()
1117    }
1118
1119    pub async fn send(&self, v: &GosValue) -> RuntimeResult<()> {
1120        self.chan.send(v).await
1121    }
1122
1123    pub async fn recv(&self) -> Option<GosValue> {
1124        self.chan.recv().await
1125    }
1126}
1127
1128// ----------------------------------------------------------------------------
1129// PointerObj
1130
1131/// There are 4 types of pointers, they point to:
1132/// - local
1133/// - slice member
1134/// - struct field
1135/// - package member
1136/// References to outer function's local vars and pointers to local vars are all
1137/// UpValues
1138
1139#[derive(Debug, Clone)]
1140pub enum PointerObj {
1141    UpVal(UpValue),
1142    SliceMember(GosValue, OpIndex),
1143    StructField(GosValue, OpIndex),
1144    PkgMember(PackageKey, OpIndex),
1145}
1146
1147impl PointerObj {
1148    #[inline]
1149    pub fn new_closed_up_value(val: &GosValue) -> PointerObj {
1150        PointerObj::UpVal(UpValue::new_closed(val.clone()))
1151    }
1152
1153    #[inline]
1154    pub fn new_slice_member(
1155        val: GosValue,
1156        i: OpIndex,
1157        t: ValueType,
1158        t_elem: ValueType,
1159    ) -> RuntimeResult<PointerObj> {
1160        PointerObj::new_slice_member_internal(val, i, t, &ArrCaller::get_slow(t_elem))
1161    }
1162
1163    #[inline]
1164    pub(crate) fn new_array_member_internal(
1165        val: GosValue,
1166        i: OpIndex,
1167        caller: &Box<dyn Dispatcher>,
1168    ) -> RuntimeResult<PointerObj> {
1169        let slice = GosValue::slice_array(val, 0, -1, caller)?;
1170        // todo: index check!
1171        Ok(PointerObj::SliceMember(slice, i))
1172    }
1173
1174    #[inline]
1175    pub(crate) fn new_slice_member_internal(
1176        val: GosValue,
1177        i: OpIndex,
1178        t: ValueType,
1179        caller: &Box<dyn Dispatcher>,
1180    ) -> RuntimeResult<PointerObj> {
1181        match t {
1182            ValueType::Array => PointerObj::new_array_member_internal(val, i, caller),
1183            ValueType::Slice => match val.is_nil() {
1184                false => Ok(PointerObj::SliceMember(val, i)),
1185                true => Err("access nil value".to_owned().into()),
1186            },
1187            _ => unreachable!(),
1188        }
1189    }
1190
1191    #[inline]
1192    pub fn deref(&self, stack: &Stack, pkgs: &PackageObjs) -> RuntimeResult<GosValue> {
1193        match self {
1194            PointerObj::UpVal(uv) => Ok(uv.value(stack).into_owned()),
1195            PointerObj::SliceMember(s, index) => s.caller_slow().slice_get(s, *index as usize),
1196            PointerObj::StructField(s, index) => {
1197                Ok(s.as_struct().0.borrow_fields()[*index as usize].clone())
1198            }
1199            PointerObj::PkgMember(pkg, index) => Ok(pkgs[*pkg].member(*index).clone()),
1200        }
1201    }
1202
1203    /// cast returns the GosValue the pointer points to, with a new type
1204    /// obviously this is very unsafe, more rigorous checks should be done here.
1205    #[inline]
1206    pub fn cast(
1207        &self,
1208        new_type: ValueType,
1209        stack: &Stack,
1210        pkgs: &PackageObjs,
1211    ) -> RuntimeResult<PointerObj> {
1212        let val = self.deref(stack, pkgs)?;
1213        let val = val.cast(new_type);
1214        Ok(PointerObj::new_closed_up_value(&val))
1215    }
1216
1217    /// set_value is not used by VM, it's for FFI
1218    pub fn set_pointee(
1219        &self,
1220        val: &GosValue,
1221        stack: &mut Stack,
1222        pkgs: &PackageObjs,
1223        gcc: &GcContainer,
1224    ) -> RuntimeResult<()> {
1225        match self {
1226            PointerObj::UpVal(uv) => uv.set_value(val.copy_semantic(gcc), stack),
1227            PointerObj::SliceMember(s, index) => {
1228                s.caller_slow()
1229                    .slice_set(s, &val.copy_semantic(gcc), *index as usize)?;
1230            }
1231            PointerObj::StructField(s, index) => {
1232                let target: &mut GosValue =
1233                    &mut s.as_struct().0.borrow_fields_mut()[*index as usize];
1234                *target = val.copy_semantic(gcc);
1235            }
1236            PointerObj::PkgMember(p, index) => {
1237                let target: &mut GosValue = &mut pkgs[*p].member_mut(*index);
1238                *target = val.copy_semantic(gcc);
1239            }
1240        }
1241        Ok(())
1242    }
1243
1244    /// for gc
1245    pub(crate) fn ref_sub_one(&self) {
1246        match &self {
1247            PointerObj::UpVal(uv) => uv.ref_sub_one(),
1248            PointerObj::SliceMember(s, _) => {
1249                let rc = &s.as_gos_slice().unwrap().1;
1250                rc.set(rc.get() - 1);
1251            }
1252            PointerObj::StructField(s, _) => {
1253                let rc = &s.as_struct().1;
1254                rc.set(rc.get() - 1);
1255            }
1256            _ => {}
1257        };
1258    }
1259
1260    /// for gc
1261    pub(crate) fn mark_dirty(&self, queue: &mut RCQueue) {
1262        match &self {
1263            PointerObj::UpVal(uv) => uv.mark_dirty(queue),
1264            PointerObj::SliceMember(s, _) => {
1265                rcount_mark_and_queue(&s.as_gos_slice().unwrap().1, queue)
1266            }
1267            PointerObj::StructField(s, _) => rcount_mark_and_queue(&s.as_struct().1, queue),
1268            _ => {}
1269        };
1270    }
1271
1272    #[inline]
1273    fn order(&self) -> usize {
1274        match self {
1275            Self::UpVal(_) => 0,
1276            Self::SliceMember(_, _) => 1,
1277            Self::StructField(_, _) => 2,
1278            Self::PkgMember(_, _) => 3,
1279        }
1280    }
1281}
1282
1283impl Eq for PointerObj {}
1284
1285impl PartialEq for PointerObj {
1286    #[inline]
1287    fn eq(&self, other: &PointerObj) -> bool {
1288        match (self, other) {
1289            (Self::UpVal(x), Self::UpVal(y)) => x == y,
1290            (Self::SliceMember(x, ix), Self::SliceMember(y, iy)) => {
1291                x.as_addr() == y.as_addr() && ix == iy
1292            }
1293            (Self::StructField(x, ix), Self::StructField(y, iy)) => {
1294                x.as_addr() == y.as_addr() && ix == iy
1295            }
1296            (Self::PkgMember(ka, ix), Self::PkgMember(kb, iy)) => ka == kb && ix == iy,
1297            _ => false,
1298        }
1299    }
1300}
1301
1302impl Hash for PointerObj {
1303    fn hash<H: Hasher>(&self, state: &mut H) {
1304        match self {
1305            Self::UpVal(x) => x.hash(state),
1306            Self::SliceMember(s, index) => {
1307                s.as_addr().hash(state);
1308                index.hash(state);
1309            }
1310            Self::StructField(s, index) => {
1311                s.as_addr().hash(state);
1312                index.hash(state);
1313            }
1314            Self::PkgMember(p, index) => {
1315                p.hash(state);
1316                index.hash(state);
1317            }
1318        }
1319    }
1320}
1321
1322impl PartialOrd for PointerObj {
1323    #[inline]
1324    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1325        Some(self.cmp(other))
1326    }
1327}
1328
1329impl Ord for PointerObj {
1330    fn cmp(&self, other: &Self) -> Ordering {
1331        match (self, other) {
1332            (Self::UpVal(x), Self::UpVal(y)) => x.cmp(&y),
1333            (Self::SliceMember(x, ix), Self::SliceMember(y, iy)) => {
1334                x.as_addr().cmp(&y.as_addr()).then(ix.cmp(&iy))
1335            }
1336            (Self::StructField(x, ix), Self::StructField(y, iy)) => {
1337                x.as_addr().cmp(&y.as_addr()).then(ix.cmp(&iy))
1338            }
1339            (Self::PkgMember(ka, ix), Self::PkgMember(kb, iy)) => ka.cmp(&kb).then(ix.cmp(&iy)),
1340            _ => self.order().cmp(&other.order()),
1341        }
1342    }
1343}
1344
1345impl Display for PointerObj {
1346    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1347        match self {
1348            Self::UpVal(uv) => write!(f, "{:p}", Rc::as_ptr(&uv.inner)),
1349            Self::SliceMember(s, i) => write!(f, "{:p}i{}", s.as_addr(), i),
1350            Self::StructField(s, i) => write!(f, "{:p}i{}", s.as_addr(), i),
1351            Self::PkgMember(p, i) => write!(f, "{:x}i{}", p.as_usize(), i),
1352        }
1353    }
1354}
1355
1356// ----------------------------------------------------------------------------
1357// UnsafePtrObj
1358
1359pub trait UnsafePtr {
1360    /// For downcasting
1361    fn as_any(&self) -> &dyn Any;
1362
1363    fn eq(&self, _: &dyn UnsafePtr) -> bool {
1364        panic!("implement your own eq for your type");
1365    }
1366
1367    /// for gc
1368    fn ref_sub_one(&self) {}
1369
1370    /// for gc
1371    fn mark_dirty(&self, _: &mut RCQueue) {}
1372
1373    /// Returns true if the user data can make reference cycles, so that GC can
1374    fn can_make_cycle(&self) -> bool {
1375        false
1376    }
1377
1378    /// If can_make_cycle returns true, implement this to break cycle
1379    fn break_cycle(&self) {}
1380}
1381
1382impl std::fmt::Debug for dyn UnsafePtr {
1383    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1384        write!(f, "{}", "unsafe pointer")
1385    }
1386}
1387
1388/// PointerHandle is used when converting a runtime pointer to a unsafe.Default
1389#[derive(Debug, Clone)]
1390pub struct PointerHandle {
1391    ptr: PointerObj,
1392}
1393
1394impl UnsafePtr for PointerHandle {
1395    fn as_any(&self) -> &dyn Any {
1396        self
1397    }
1398
1399    fn eq(&self, other: &dyn UnsafePtr) -> bool {
1400        let a = self.as_any().downcast_ref::<PointerHandle>();
1401        let b = other.as_any().downcast_ref::<PointerHandle>();
1402        match b {
1403            Some(h) => h.ptr == a.unwrap().ptr,
1404            None => false,
1405        }
1406    }
1407
1408    /// for gc
1409    fn ref_sub_one(&self) {
1410        self.ptr.ref_sub_one()
1411    }
1412
1413    /// for gc
1414    fn mark_dirty(&self, q: &mut RCQueue) {
1415        self.ptr.mark_dirty(q)
1416    }
1417}
1418
1419impl PointerHandle {
1420    pub fn new(ptr: &GosValue) -> GosValue {
1421        match ptr.as_pointer() {
1422            Some(p) => {
1423                let handle = PointerHandle { ptr: p.clone() };
1424                GosValue::new_unsafe_ptr(Rc::new(handle))
1425            }
1426            None => GosValue::new_nil(ValueType::UnsafePtr),
1427        }
1428    }
1429
1430    /// Get a reference to the pointer handle's ptr.
1431    pub fn ptr(&self) -> &PointerObj {
1432        &self.ptr
1433    }
1434}
1435
1436#[derive(Debug, Clone)]
1437pub struct UnsafePtrObj {
1438    ptr: Rc<dyn UnsafePtr>,
1439}
1440
1441impl UnsafePtrObj {
1442    pub fn new(ptr: Rc<dyn UnsafePtr>) -> UnsafePtrObj {
1443        UnsafePtrObj { ptr }
1444    }
1445
1446    /// Get a reference to the unsafe ptr obj's ptr.
1447    pub fn ptr(&self) -> &dyn UnsafePtr {
1448        &*self.ptr
1449    }
1450
1451    pub fn as_rust_ptr(&self) -> *const dyn UnsafePtr {
1452        &*self.ptr
1453    }
1454
1455    pub fn downcast_ref<T: Any>(&self) -> RuntimeResult<&T> {
1456        self.ptr
1457            .as_any()
1458            .downcast_ref::<T>()
1459            .ok_or("Unexpected unsafe pointer type".to_owned().into())
1460    }
1461}
1462
1463impl Eq for UnsafePtrObj {}
1464
1465impl PartialEq for UnsafePtrObj {
1466    #[inline]
1467    fn eq(&self, other: &UnsafePtrObj) -> bool {
1468        self.ptr.eq(other.ptr())
1469    }
1470}
1471
1472impl Display for UnsafePtrObj {
1473    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1474        write!(f, "{:p}", &*self.ptr as *const dyn UnsafePtr)
1475    }
1476}
1477// ----------------------------------------------------------------------------
1478// ClosureObj
1479
1480#[cfg_attr(feature = "serde_borsh", derive(BorshDeserialize, BorshSerialize))]
1481#[derive(Clone)]
1482pub struct ValueDesc {
1483    pub func: FunctionKey,
1484    pub index: OpIndex,
1485    pub typ: ValueType,
1486    pub is_local: bool,
1487    #[cfg_attr(feature = "serde_borsh", borsh_skip)]
1488    pub stack: Weak<RefCell<Stack>>,
1489    #[cfg_attr(feature = "serde_borsh", borsh_skip)]
1490    pub stack_base: OpIndex,
1491}
1492
1493impl Eq for ValueDesc {}
1494
1495impl PartialEq for ValueDesc {
1496    #[inline]
1497    fn eq(&self, other: &ValueDesc) -> bool {
1498        self.stack_base + self.index == other.stack_base + other.index
1499            && self.stack.ptr_eq(&other.stack)
1500    }
1501}
1502
1503impl ValueDesc {
1504    pub fn new(func: FunctionKey, index: OpIndex, typ: ValueType, is_local: bool) -> ValueDesc {
1505        ValueDesc {
1506            func,
1507            index,
1508            typ,
1509            is_local,
1510            stack: Weak::new(),
1511            stack_base: 0,
1512        }
1513    }
1514
1515    #[inline]
1516    pub fn clone_with_stack(&self, stack: Weak<RefCell<Stack>>, stack_base: OpIndex) -> ValueDesc {
1517        ValueDesc {
1518            func: self.func,
1519            index: self.index,
1520            typ: self.typ,
1521            is_local: self.is_local,
1522            stack: stack,
1523            stack_base: stack_base,
1524        }
1525    }
1526
1527    #[inline]
1528    pub fn abs_index(&self) -> OpIndex {
1529        self.stack_base + self.index
1530    }
1531
1532    #[inline]
1533    pub fn load<'a>(&self, stack: &'a Stack) -> Cow<'a, GosValue> {
1534        let index = self.abs_index();
1535        let uv_stack = self.stack.upgrade().unwrap();
1536        if ptr::eq(uv_stack.as_ptr(), stack) {
1537            Cow::Borrowed(stack.get(index))
1538        } else {
1539            Cow::Owned(uv_stack.borrow().get(index).clone())
1540        }
1541    }
1542
1543    #[inline]
1544    pub fn store(&self, val: GosValue, stack: &mut Stack) {
1545        let index = self.abs_index();
1546        let uv_stack = self.stack.upgrade().unwrap();
1547        if ptr::eq(uv_stack.as_ptr(), stack) {
1548            stack.set(index, val);
1549        } else {
1550            uv_stack.borrow_mut().set(index, val);
1551        }
1552    }
1553}
1554
1555impl std::fmt::Debug for ValueDesc {
1556    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1557        f.debug_struct("ValueDesc")
1558            .field("type", &self.typ)
1559            .field("is_local", &self.is_local)
1560            .field("index", &self.abs_index())
1561            .field("stack", &self.stack.as_ptr())
1562            .finish()
1563    }
1564}
1565
1566#[derive(Clone, PartialEq, Eq)]
1567pub enum UpValueState {
1568    /// Parent CallFrame is still alive, pointing to a local variable
1569    Open(ValueDesc), // (what func is the var defined, the index of the var)
1570    // Parent CallFrame is released, pointing to a pointer value in the global pool
1571    Closed(GosValue),
1572}
1573
1574impl std::fmt::Debug for UpValueState {
1575    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1576        match &self {
1577            Self::Open(desc) => write!(f, "UpValue::Open(  {:#?} )", desc),
1578            Self::Closed(v) => write!(f, "UpValue::Closed(  {:#018x} )", v.data().as_uint()),
1579        }
1580    }
1581}
1582
1583#[derive(Clone, Debug)]
1584pub struct UpValue {
1585    pub inner: Rc<RefCell<UpValueState>>,
1586}
1587
1588impl UpValue {
1589    pub fn new(d: ValueDesc) -> UpValue {
1590        UpValue {
1591            inner: Rc::new(RefCell::new(UpValueState::Open(d))),
1592        }
1593    }
1594
1595    pub fn new_closed(v: GosValue) -> UpValue {
1596        UpValue {
1597            inner: Rc::new(RefCell::new(UpValueState::Closed(v))),
1598        }
1599    }
1600
1601    pub fn is_open(&self) -> bool {
1602        match &self.inner.borrow() as &UpValueState {
1603            UpValueState::Open(_) => true,
1604            UpValueState::Closed(_) => false,
1605        }
1606    }
1607
1608    pub fn downgrade(&self) -> WeakUpValue {
1609        WeakUpValue {
1610            inner: Rc::downgrade(&self.inner),
1611        }
1612    }
1613
1614    pub fn desc(&self) -> ValueDesc {
1615        let r: &UpValueState = &self.inner.borrow();
1616        match r {
1617            UpValueState::Open(d) => d.clone(),
1618            _ => unreachable!(),
1619        }
1620    }
1621
1622    pub fn close(&self, val: GosValue) {
1623        *self.inner.borrow_mut() = UpValueState::Closed(val);
1624    }
1625
1626    pub fn value<'a>(&self, stack: &'a Stack) -> Cow<'a, GosValue> {
1627        match &self.inner.borrow() as &UpValueState {
1628            UpValueState::Open(desc) => desc.load(stack),
1629            UpValueState::Closed(val) => Cow::Owned(val.clone()),
1630        }
1631    }
1632
1633    pub fn set_value(&self, val: GosValue, stack: &mut Stack) {
1634        match &mut self.inner.borrow_mut() as &mut UpValueState {
1635            UpValueState::Open(desc) => desc.store(val, stack),
1636            UpValueState::Closed(v) => {
1637                *v = val;
1638            }
1639        }
1640    }
1641
1642    /// for gc
1643    pub fn ref_sub_one(&self) {
1644        let state: &UpValueState = &self.inner.borrow();
1645        if let UpValueState::Closed(uvs) = state {
1646            uvs.ref_sub_one()
1647        }
1648    }
1649
1650    /// for gc
1651    pub fn mark_dirty(&self, queue: &mut RCQueue) {
1652        let state: &UpValueState = &self.inner.borrow();
1653        if let UpValueState::Closed(uvs) = state {
1654            uvs.mark_dirty(queue)
1655        }
1656    }
1657}
1658
1659impl Eq for UpValue {}
1660
1661impl PartialEq for UpValue {
1662    #[inline]
1663    fn eq(&self, b: &UpValue) -> bool {
1664        let state_a: &UpValueState = &self.inner.borrow();
1665        let state_b: &UpValueState = &b.inner.borrow();
1666        match (state_a, state_b) {
1667            (UpValueState::Closed(_), UpValueState::Closed(_)) => Rc::ptr_eq(&self.inner, &b.inner),
1668            (UpValueState::Open(da), UpValueState::Open(db)) => {
1669                da.abs_index() == db.abs_index() && Weak::ptr_eq(&da.stack, &db.stack)
1670            }
1671            _ => false,
1672        }
1673    }
1674}
1675
1676impl Hash for UpValue {
1677    #[inline]
1678    fn hash<H: Hasher>(&self, state: &mut H) {
1679        let b: &UpValueState = &self.inner.borrow();
1680        match b {
1681            UpValueState::Open(desc) => desc.abs_index().hash(state),
1682            UpValueState::Closed(_) => Rc::as_ptr(&self.inner).hash(state),
1683        }
1684    }
1685}
1686
1687impl PartialOrd for UpValue {
1688    #[inline]
1689    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1690        Some(self.cmp(other))
1691    }
1692}
1693
1694impl Ord for UpValue {
1695    fn cmp(&self, b: &Self) -> Ordering {
1696        let state_a: &UpValueState = &self.inner.borrow();
1697        let state_b: &UpValueState = &b.inner.borrow();
1698        match (state_a, state_b) {
1699            (UpValueState::Closed(_), UpValueState::Closed(_)) => {
1700                Rc::as_ptr(&self.inner).cmp(&Rc::as_ptr(&b.inner))
1701            }
1702            (UpValueState::Open(da), UpValueState::Open(db)) => da
1703                .abs_index()
1704                .cmp(&db.abs_index())
1705                .then(Weak::as_ptr(&da.stack).cmp(&Weak::as_ptr(&db.stack))),
1706            (UpValueState::Open(_), UpValueState::Closed(_)) => Ordering::Greater,
1707            (UpValueState::Closed(_), UpValueState::Open(_)) => Ordering::Less,
1708        }
1709    }
1710}
1711
1712#[cfg(feature = "serde_borsh")]
1713impl BorshSerialize for UpValue {
1714    fn serialize<W: BorshWrite>(&self, writer: &mut W) -> BorshResult<()> {
1715        match &self.inner.borrow() as &UpValueState {
1716            UpValueState::Open(uv) => uv,
1717            UpValueState::Closed(_) => unreachable!(),
1718        }
1719        .serialize(writer)
1720    }
1721}
1722
1723#[cfg(feature = "serde_borsh")]
1724impl BorshDeserialize for UpValue {
1725    fn deserialize_reader<R: std::io::Read>(reader: &mut R) -> BorshResult<Self> {
1726        let uv = ValueDesc::deserialize_reader(reader)?;
1727        Ok(Self::new(uv))
1728    }
1729}
1730
1731#[derive(Clone, Debug)]
1732pub struct WeakUpValue {
1733    pub inner: Weak<RefCell<UpValueState>>,
1734}
1735
1736impl WeakUpValue {
1737    pub fn upgrade(&self) -> Option<UpValue> {
1738        Weak::upgrade(&self.inner).map(|x| UpValue { inner: x })
1739    }
1740}
1741
1742#[cfg_attr(feature = "serde_borsh", derive(BorshDeserialize, BorshSerialize))]
1743#[derive(Clone, Debug)]
1744pub struct GosClosureObj {
1745    pub func: FunctionKey,
1746    pub uvs: Option<Map<usize, UpValue>>,
1747    #[cfg_attr(feature = "serde_borsh", borsh_skip)]
1748    pub recv: Option<GosValue>,
1749    pub meta: Meta,
1750}
1751
1752impl GosClosureObj {
1753    fn new(
1754        func: FunctionKey,
1755        up_ptrs: Option<&Vec<ValueDesc>>,
1756        recv: Option<GosValue>,
1757        meta: Meta,
1758    ) -> GosClosureObj {
1759        let uvs = up_ptrs.map(|uv| {
1760            uv.iter()
1761                .enumerate()
1762                .filter(|(_, x)| !x.is_local)
1763                .map(|(i, x)| (i, UpValue::new(x.clone())))
1764                .collect()
1765        });
1766        GosClosureObj {
1767            func,
1768            uvs,
1769            recv,
1770            meta,
1771        }
1772    }
1773}
1774
1775#[derive(Clone, Debug)]
1776pub struct FfiClosureObj {
1777    pub ffi: Rc<dyn Ffi>,
1778    pub func_name: String,
1779    pub is_async: bool,
1780    pub meta: Meta,
1781}
1782
1783#[derive(Clone, Debug)]
1784pub enum ClosureObj {
1785    Gos(GosClosureObj),
1786    Ffi(FfiClosureObj),
1787}
1788
1789impl ClosureObj {
1790    pub fn new_gos(
1791        func: FunctionKey,
1792        up_ptrs: Option<&Vec<ValueDesc>>,
1793        recv: Option<GosValue>,
1794        meta: Meta,
1795    ) -> ClosureObj {
1796        ClosureObj::Gos(GosClosureObj::new(func, up_ptrs, recv, meta))
1797    }
1798
1799    pub fn gos_from_func(
1800        func: FunctionKey,
1801        fobjs: &FunctionObjs,
1802        recv: Option<GosValue>,
1803    ) -> ClosureObj {
1804        let func_val = &fobjs[func];
1805        let uvs = if func_val.up_ptrs.is_empty() {
1806            None
1807        } else {
1808            Some(&func_val.up_ptrs)
1809        };
1810        ClosureObj::Gos(GosClosureObj::new(func, uvs, recv, func_val.meta))
1811    }
1812
1813    #[inline]
1814    pub fn new_ffi(ffi: FfiClosureObj) -> ClosureObj {
1815        ClosureObj::Ffi(ffi)
1816    }
1817
1818    #[inline]
1819    pub fn as_gos(&self) -> &GosClosureObj {
1820        match self {
1821            Self::Gos(c) => c,
1822            _ => unreachable!(),
1823        }
1824    }
1825
1826    /// for gc
1827    pub fn ref_sub_one(&self) {
1828        match self {
1829            Self::Gos(obj) => {
1830                if let Some(uvs) = &obj.uvs {
1831                    for (_, v) in uvs.iter() {
1832                        v.ref_sub_one()
1833                    }
1834                }
1835                if let Some(recv) = &obj.recv {
1836                    recv.ref_sub_one()
1837                }
1838            }
1839            Self::Ffi(_) => {}
1840        }
1841    }
1842
1843    /// for gc
1844    pub fn mark_dirty(&self, queue: &mut RCQueue) {
1845        match self {
1846            Self::Gos(obj) => {
1847                if let Some(uvs) = &obj.uvs {
1848                    for (_, v) in uvs.iter() {
1849                        v.mark_dirty(queue)
1850                    }
1851                }
1852                if let Some(recv) = &obj.recv {
1853                    recv.mark_dirty(queue)
1854                }
1855            }
1856            Self::Ffi(_) => {}
1857        }
1858    }
1859}
1860
1861// ----------------------------------------------------------------------------
1862// PackageObj
1863
1864/// PackageObj is part of the generated Bytecode, it stores imports, consts,
1865/// vars, funcs declared in a package
1866#[derive(Clone, Debug)]
1867pub struct PackageObj {
1868    name: String,
1869    members: Vec<RefCell<GosValue>>, // imports, const, var, func are all stored here
1870    member_indices: Map<String, OpIndex>,
1871    init_funcs: Vec<GosValue>,
1872    // maps func_member_index of the constructor to pkg_member_index
1873    var_mapping: RefCell<Option<Map<OpIndex, OpIndex>>>,
1874}
1875
1876impl PackageObj {
1877    pub fn new(name: String) -> PackageObj {
1878        PackageObj {
1879            name,
1880            members: vec![],
1881            member_indices: Map::new(),
1882            init_funcs: vec![],
1883            var_mapping: RefCell::new(Some(Map::new())),
1884        }
1885    }
1886
1887    pub fn name(&self) -> &str {
1888        &self.name
1889    }
1890
1891    pub fn add_member(&mut self, name: String, val: GosValue) -> OpIndex {
1892        self.members.push(RefCell::new(val));
1893        let index = (self.members.len() - 1) as OpIndex;
1894        self.member_indices.insert(name, index);
1895        index as OpIndex
1896    }
1897
1898    pub fn add_var_mapping(&mut self, name: String, fn_index: OpIndex) -> OpIndex {
1899        let index = *self.member_index(&name).unwrap();
1900        self.var_mapping
1901            .borrow_mut()
1902            .as_mut()
1903            .unwrap()
1904            .insert(fn_index, index);
1905        index
1906    }
1907
1908    pub fn add_init_func(&mut self, func: GosValue) {
1909        self.init_funcs.push(func);
1910    }
1911
1912    pub fn member_indices(&self) -> &Map<String, OpIndex> {
1913        &self.member_indices
1914    }
1915
1916    pub fn member_index(&self, name: &str) -> Option<&OpIndex> {
1917        self.member_indices.get(name)
1918    }
1919
1920    pub fn inited(&self) -> bool {
1921        self.var_mapping.borrow().is_none()
1922    }
1923
1924    #[inline]
1925    pub fn member(&self, i: OpIndex) -> Ref<GosValue> {
1926        self.members[i as usize].borrow()
1927    }
1928
1929    #[inline]
1930    pub fn member_mut(&self, i: OpIndex) -> RefMut<GosValue> {
1931        self.members[i as usize].borrow_mut()
1932    }
1933
1934    #[inline]
1935    pub fn init_func(&self, i: OpIndex) -> Option<&GosValue> {
1936        self.init_funcs.get(i as usize)
1937    }
1938
1939    #[inline]
1940    pub fn init_vars(&self, vals: Vec<GosValue>) {
1941        let mut borrow = self.var_mapping.borrow_mut();
1942        let mapping = borrow.as_ref().unwrap();
1943        for (i, v) in vals.into_iter().enumerate() {
1944            let vi = mapping[&(i as OpIndex)];
1945            *self.member_mut(vi) = v;
1946        }
1947        *borrow = None;
1948    }
1949}
1950
1951#[cfg(feature = "serde_borsh")]
1952impl BorshSerialize for PackageObj {
1953    fn serialize<W: BorshWrite>(&self, writer: &mut W) -> BorshResult<()> {
1954        self.name.serialize(writer)?;
1955        let members: Vec<GosValue> = self
1956            .members
1957            .iter()
1958            .map(|x| x.clone().into_inner())
1959            .collect();
1960        members.serialize(writer)?;
1961        self.member_indices.serialize(writer)?;
1962        self.init_funcs.serialize(writer)?;
1963        self.var_mapping.borrow().serialize(writer)
1964    }
1965}
1966
1967#[cfg(feature = "serde_borsh")]
1968impl BorshDeserialize for PackageObj {
1969    fn deserialize_reader<R: std::io::Read>(reader: &mut R) -> BorshResult<Self> {
1970        let name = String::deserialize_reader(reader)?;
1971        let members = Vec::<GosValue>::deserialize_reader(reader)?
1972            .into_iter()
1973            .map(|x| RefCell::new(x))
1974            .collect();
1975        let member_indices = Map::<String, OpIndex>::deserialize_reader(reader)?;
1976        let init_funcs = Vec::<GosValue>::deserialize_reader(reader)?;
1977        let var_mapping =
1978            RefCell::new(Option::<Map<OpIndex, OpIndex>>::deserialize_reader(reader)?);
1979        Ok(PackageObj {
1980            name,
1981            members,
1982            member_indices,
1983            init_funcs,
1984            var_mapping,
1985        })
1986    }
1987}
1988
1989// ----------------------------------------------------------------------------
1990// FunctionObj
1991
1992#[cfg_attr(feature = "serde_borsh", derive(BorshDeserialize, BorshSerialize))]
1993#[derive(Eq, PartialEq, Copy, Clone, Debug)]
1994pub enum FuncFlag {
1995    Default,
1996    PkgCtor,
1997    HasDefer,
1998}
1999
2000/// FunctionObj is the direct container of the Opcode.
2001#[cfg_attr(feature = "serde_borsh", derive(BorshDeserialize, BorshSerialize))]
2002#[derive(Clone, Debug)]
2003pub struct FunctionObj {
2004    pub package: PackageKey,
2005    pub meta: Meta,
2006    pub flag: FuncFlag,
2007    pub param_count: OpIndex,
2008    pub max_write_index: OpIndex,
2009    pub ret_zeros: Vec<GosValue>,
2010
2011    pub code: Vec<Instruction>,
2012    #[cfg_attr(
2013        all(feature = "serde_borsh", not(feature = "instruction_pos")),
2014        borsh_skip
2015    )]
2016    pub pos: Vec<Option<u32>>,
2017    pub up_ptrs: Vec<ValueDesc>,
2018    pub local_zeros: Vec<GosValue>,
2019}
2020
2021impl FunctionObj {
2022    pub fn new(
2023        package: PackageKey,
2024        meta: Meta,
2025        metas: &MetadataObjs,
2026        gcc: &GcContainer,
2027        flag: FuncFlag,
2028    ) -> FunctionObj {
2029        let s = &metas[meta.key].as_signature();
2030        let ret_zeros = s.results.iter().map(|m| m.zero(metas, gcc)).collect();
2031        let mut param_count = s.recv.map_or(0, |_| 1);
2032        param_count += s.params.len() as OpIndex;
2033        FunctionObj {
2034            package,
2035            meta,
2036            flag,
2037            param_count,
2038            max_write_index: 0,
2039            ret_zeros,
2040            code: Vec::new(),
2041            pos: Vec::new(),
2042            up_ptrs: Vec::new(),
2043            local_zeros: Vec::new(),
2044        }
2045    }
2046
2047    #[inline]
2048    pub fn param_count(&self) -> OpIndex {
2049        self.param_count
2050    }
2051
2052    #[inline]
2053    pub fn local_count(&self) -> OpIndex {
2054        self.local_zeros.len() as OpIndex
2055    }
2056
2057    #[inline]
2058    pub fn ret_count(&self) -> OpIndex {
2059        self.ret_zeros.len() as OpIndex
2060    }
2061
2062    #[inline]
2063    pub fn is_ctor(&self) -> bool {
2064        self.flag == FuncFlag::PkgCtor
2065    }
2066}