]>
Witch of Git - ivy/blob - rt/src/lib.rs
1 use crate::{int
::ObjInt
, lam
::ObjLam
};
2 use std
::sync
::atomic
::{AtomicU32
, Ordering
};
9 const _STDOUT
: i32 = 1;
10 const STDERR
: i32 = 2;
14 ($fmt
:literal $
(, $arg
:expr
)* $
(,)?
) => {
15 if std
::env
::var("IVY_RT_TRACE").is
_ok
() {
16 eprintln
!($fmt
, $
($arg
),*);
22 #[derive(PartialEq, Eq, Clone, Copy)]
29 pub struct ObjHeader
{
35 #[derive(Clone, Copy)]
39 header
: *mut ObjHeader
,
45 pub unsafe extern "C" fn ivy_debug(obj
: Obj
) -> Obj
{
46 println
!("DEBUG {:016x}", obj
.int
);
51 pub unsafe extern "C" fn ivy_abort(msg
: *const u8, len
: usize) -> ! {
52 sys
::write(STDERR
, msg
, len
);
57 pub unsafe extern "C" fn ivy_exit(code
: i32) -> ! {
62 pub unsafe extern "C" fn ivy_free(obj
: Obj
) {
66 sys
::free(obj
.header
as *mut u8)
70 pub unsafe extern "C" fn ivy_incref(obj
: Obj
) {
75 pub unsafe extern "C" fn ivy_decref(obj
: Obj
) {
80 pub unsafe extern "C" fn ivy_clone(obj
: Obj
) -> Obj
{
81 if obj
.is
_n
ull
() || !obj
.is
_box
() {
85 None
=> unreachable
!(),
86 Some(ObjTag
::Int
) => {
87 unimplemented
!("copying boxed integers")
89 Some(ObjTag
::Lam
) => {
90 let box_lam
= lam
::ivy_clone_lam(&*obj
.box_lam
);
97 fn is_null(self) -> bool
{
98 unsafe { self.int
== 0 }
101 fn is_box(self) -> bool
{
102 !self.is
_n
ull
() && unsafe { self.int
& 1 == 0 }
105 unsafe fn tag(self) -> Option
<ObjTag
> {
108 } else if self.is
_box
() {
109 Some((*self.header
).tag
)
115 unsafe fn incref(self) {
116 trace
!("INC {:016x}", self.int
);
120 // Ordering::Relaxed is appropriate here, since we assume that each thread with access to a
121 // reference owns at least one reference (rather than simply borrowing it). Therefore,
122 // another thread cannot decrement it to 0 while we are performing this increment (since we
123 // own a reference), so we only need consistency and not ordering.
124 (*self.header
).rc
.fetch
_add
(1, Ordering
::Relaxed
);
127 unsafe fn decref(self) {
128 trace
!("DEC {:016x}", self.int
);
132 // Ordering::AcqRel is appropriate here. I believe we need the Acquire in order to ensure
133 // we see all previous increments/decrements, so we can properly see that the decref is
134 // decrementing to 0, and we need the Release in order to ensure that we see all writes to
135 // the memory before we deallocate.
136 // (Check against 1 instead of 0 since we're loading the old refcount.)
137 if (*self.header
).rc
.fetch
_s
ub
(1, Ordering
::AcqRel
) == 1 {
142 unsafe fn dealloc(self) {
143 trace
!("FREE {:016x}", self.int
);
148 None
| Some(ObjTag
::Int
) => (),
149 Some(ObjTag
::Lam
) => {
150 let lam
= &mut *self.box_lam
;
151 for param
in lam
.params() {
154 for upvar
in lam
.upvars
() {
159 sys
::free(self.header
as *mut u8);