jlrs/memory/target/frame/
mod.rs1#[cfg(feature = "async")]
13pub mod async_frame;
14
15use std::{marker::PhantomData, pin::Pin, ptr::NonNull};
16
17use jlrs_sys::{RawGcFrame, UnsizedGcFrame, pop_frame};
18
19#[cfg(feature = "async")]
20pub use self::async_frame::*;
21use super::{
22 ExtendedTarget, Target,
23 output::Output,
24 reusable_slot::ReusableSlot,
25 slot_ref::{LocalSlotRef, StackSlotRef},
26 unrooted::Unrooted,
27};
28use crate::{
29 data::managed::Managed,
30 memory::{context::stack::Stack, scope::private::LocalScopePriv},
31 prelude::{LocalScope, Scope},
32 private::Private,
33};
34
35pub struct GcFrame<'scope> {
37 stack: &'scope Stack,
38 offset: usize,
39 _marker: PhantomData<&'scope mut &'scope ()>,
40}
41
42impl<'scope> GcFrame<'scope> {
43 #[inline]
45 pub fn as_mut(&mut self) -> &mut Self {
46 self
47 }
48
49 #[inline]
51 pub fn reserve(&mut self, additional: usize) {
52 self.stack.reserve(additional)
53 }
54
55 #[inline]
57 pub fn borrow<'borrow>(&'borrow mut self) -> BorrowedFrame<'borrow, 'scope, Self> {
58 BorrowedFrame(self, PhantomData)
59 }
60
61 #[inline]
63 pub fn extended_target<'target, 'borrow, Tgt>(
64 &'borrow mut self,
65 target: Tgt,
66 ) -> ExtendedTarget<'target, 'scope, 'borrow, Tgt>
67 where
68 Tgt: Target<'target>,
69 {
70 ExtendedTarget {
71 target,
72 frame: self,
73 _target_marker: PhantomData,
74 }
75 }
76
77 #[inline]
79 pub fn as_extended_target<'borrow>(
80 &'borrow mut self,
81 ) -> ExtendedTarget<'scope, 'scope, 'borrow, Output<'scope, StackSlotRef<'scope>>> {
82 let target = self.output();
83 ExtendedTarget {
84 target,
85 frame: self,
86 _target_marker: PhantomData,
87 }
88 }
89
90 #[inline]
92 pub fn n_roots(&self) -> usize {
93 self.stack_size() - self.offset
94 }
95
96 #[inline]
98 pub fn stack_size(&self) -> usize {
99 self.stack.size()
100 }
101
102 #[inline]
104 pub fn output(&mut self) -> Output<'scope, StackSlotRef<'scope>> {
105 unsafe {
106 let offset = self.stack.reserve_slot();
107 Output::new(StackSlotRef::new(self.stack, offset))
108 }
109 }
110
111 #[inline]
113 pub fn reusable_slot(&mut self) -> ReusableSlot<'scope, StackSlotRef<'scope>> {
114 unsafe {
115 let offset = self.stack.reserve_slot();
116 let slot = StackSlotRef::new(self.stack, offset);
117 ReusableSlot::new(slot)
118 }
119 }
120
121 #[inline]
123 pub const fn unrooted(&self) -> Unrooted<'scope> {
124 unsafe { Unrooted::new() }
125 }
126
127 #[inline]
129 #[track_caller]
130 pub(crate) unsafe fn root<'data, T: Managed<'scope, 'data>>(
131 &self,
132 ptr: NonNull<T::Wraps>,
133 ) -> T {
134 unsafe {
135 self.stack.push_root(ptr.cast());
136 T::wrap_non_null(ptr, Private)
137 }
138 }
139
140 #[inline]
141 pub(crate) fn stack(&self) -> &Stack {
142 self.stack
143 }
144
145 #[inline]
146 pub(crate) unsafe fn nest<'nested>(&'nested mut self) -> (usize, GcFrame<'nested>) {
147 let frame = GcFrame {
148 stack: self.stack(),
149 offset: self.stack.size(),
150 _marker: PhantomData,
151 };
152 (self.stack.size(), frame)
153 }
154
155 #[inline]
157 pub(crate) unsafe fn base(stack: &'scope Stack) -> GcFrame<'scope> {
158 debug_assert_eq!(stack.size(), 0);
159 GcFrame {
160 stack,
161 offset: 0,
162 _marker: PhantomData,
163 }
164 }
165
166 }
170
171unsafe impl<'f> Scope for GcFrame<'f> {
172 #[inline]
173 fn scope<T>(&mut self, func: impl for<'scope> FnOnce(GcFrame<'scope>) -> T) -> T {
174 unsafe {
175 let (offset, nested) = self.nest();
176 let res = func(nested);
177 self.stack.pop_roots(offset);
178 res
179 }
180 }
181}
182
183pub struct LocalGcFrame<'scope, const N: usize> {
185 frame: &'scope PinnedLocalFrame<'scope, N>,
186 offset: usize,
187}
188
189impl<'scope, const N: usize> LocalGcFrame<'scope, N> {
190 #[inline]
192 pub fn as_mut(&mut self) -> &mut Self {
193 self
194 }
195
196 #[inline]
198 pub fn n_roots(&self) -> usize {
199 self.offset
200 }
201
202 #[inline]
204 pub const fn frame_size(&self) -> usize {
205 N
206 }
207
208 #[inline]
210 pub fn output(&mut self) -> Output<'scope, LocalSlotRef<'scope>> {
211 unsafe {
212 let slot = self.frame.frame.raw.get_root(self.offset);
213 self.offset += 1;
214 Output::new(LocalSlotRef::new(slot))
215 }
216 }
217
218 #[inline]
220 pub fn reusable_slot(&mut self) -> ReusableSlot<'scope, LocalSlotRef<'scope>> {
221 unsafe {
222 let slot = self.frame.frame.raw.get_root(self.offset);
223 let slot = LocalSlotRef::new(slot);
224 self.offset += 1;
225 ReusableSlot::new(slot)
226 }
227 }
228
229 #[inline]
231 pub const fn unrooted(&self) -> Unrooted<'scope> {
232 unsafe { Unrooted::new() }
233 }
234
235 #[inline]
236 pub(crate) unsafe fn new(frame: &'scope PinnedLocalFrame<'scope, N>) -> Self {
237 LocalGcFrame { frame, offset: 0 }
238 }
239
240 #[inline]
241 #[track_caller]
242 pub(crate) unsafe fn root<'data, T: Managed<'scope, 'data>>(
243 &mut self,
244 ptr: NonNull<T::Wraps>,
245 ) -> T {
246 unsafe {
247 self.frame
248 .frame
249 .raw
250 .set_root(self.offset, ptr.as_ptr().cast());
251 self.offset += 1;
252 T::wrap_non_null(ptr, Private)
253 }
254 }
255}
256
257pub struct UnsizedLocalGcFrame<'scope> {
258 frame: UnsizedGcFrame<'scope>,
259 offset: usize,
260}
261
262impl<'scope> UnsizedLocalGcFrame<'scope> {
263 pub(crate) fn new(frame: UnsizedGcFrame<'scope>) -> Self {
264 UnsizedLocalGcFrame { frame, offset: 0 }
265 }
266
267 #[inline]
269 pub fn as_mut(&mut self) -> &mut Self {
270 self
271 }
272
273 #[inline]
275 pub fn n_roots(&self) -> usize {
276 self.offset
277 }
278
279 #[inline]
281 pub fn frame_size(&self) -> usize {
282 self.frame.size()
283 }
284
285 #[inline]
287 pub fn output(&mut self) -> Output<'scope, LocalSlotRef<'scope>> {
288 unsafe {
289 let slot = self.frame.get_root(self.offset);
290 self.offset += 1;
291 Output::new(LocalSlotRef::new(slot))
292 }
293 }
294
295 #[inline]
297 pub fn reusable_slot(&mut self) -> ReusableSlot<'scope, LocalSlotRef<'scope>> {
298 unsafe {
299 let slot = self.frame.get_root(self.offset);
300 let slot = LocalSlotRef::new(slot);
301 self.offset += 1;
302 ReusableSlot::new(slot)
303 }
304 }
305
306 #[inline]
308 pub const fn unrooted(&self) -> Unrooted<'scope> {
309 unsafe { Unrooted::new() }
310 }
311
312 #[inline]
313 #[track_caller]
314 pub(crate) unsafe fn root<'data, T: Managed<'scope, 'data>>(
315 &mut self,
316 ptr: NonNull<T::Wraps>,
317 ) -> T {
318 unsafe {
319 self.frame.get_root(self.offset).set(ptr.as_ptr().cast());
320 self.offset += 1;
321 T::wrap_non_null(ptr, Private)
322 }
323 }
324}
325
326pub struct BorrowedFrame<'borrow, 'current, F>(
330 pub(crate) &'borrow mut F,
331 pub(crate) PhantomData<&'current ()>,
332);
333
334impl<'borrow, 'current> LocalScopePriv for BorrowedFrame<'borrow, 'current, GcFrame<'current>> {}
335
336unsafe impl<'borrow, 'current> LocalScope for BorrowedFrame<'borrow, 'current, GcFrame<'current>> {}
337
338unsafe impl<'borrow, 'current> Scope for BorrowedFrame<'borrow, 'current, GcFrame<'current>> {
339 #[inline]
340 fn scope<T>(&mut self, func: impl for<'scope> FnOnce(GcFrame<'scope>) -> T) -> T {
341 self.0.scope(func)
342 }
343}
344
345#[cfg(feature = "async")]
346impl<'borrow, 'current> LocalScopePriv
347 for BorrowedFrame<'borrow, 'current, AsyncGcFrame<'current>>
348{
349}
350
351#[cfg(feature = "async")]
352unsafe impl<'borrow, 'current> LocalScope
353 for BorrowedFrame<'borrow, 'current, AsyncGcFrame<'current>>
354{
355}
356
357#[cfg(feature = "async")]
358unsafe impl<'borrow, 'current> Scope for BorrowedFrame<'borrow, 'current, AsyncGcFrame<'current>> {
359 #[inline]
360 fn scope<T>(&mut self, func: impl for<'scope> FnOnce(GcFrame<'scope>) -> T) -> T {
361 self.0.scope(func)
362 }
363}
364
365#[cfg(feature = "async")]
366unsafe impl<'borrow, 'current> crate::prelude::AsyncScope
367 for BorrowedFrame<'borrow, 'current, AsyncGcFrame<'current>>
368{
369 #[inline]
370 async fn async_scope<T>(
371 &mut self,
372 func: impl for<'scope> AsyncFnOnce(AsyncGcFrame<'scope>) -> T,
373 ) -> T {
374 self.0.async_scope(func).await
375 }
376}
377
378#[repr(C)]
379pub(crate) struct LocalFrame<const N: usize> {
380 raw: RawGcFrame<N>,
381}
382
383impl<const N: usize> LocalFrame<N> {
384 #[inline]
385 pub(crate) const fn new() -> Self {
386 unsafe {
387 LocalFrame {
388 raw: RawGcFrame::new(),
389 }
390 }
391 }
392
393 #[inline]
394 pub(crate) unsafe fn pin<'scope>(&'scope mut self) -> PinnedLocalFrame<'scope, N> {
395 unsafe { PinnedLocalFrame::new(self) }
396 }
397}
398
399pub(crate) struct PinnedLocalFrame<'scope, const N: usize> {
400 frame: Pin<&'scope mut LocalFrame<N>>,
401 _marker: PhantomData<&'scope mut &'scope ()>,
402}
403
404impl<'scope, const N: usize> PinnedLocalFrame<'scope, N> {
405 #[inline]
406 unsafe fn new(frame: &'scope mut LocalFrame<N>) -> Self {
407 unsafe {
408 if N > 0 {
409 frame.raw.push_frame();
410 }
411
412 PinnedLocalFrame {
413 frame: Pin::new_unchecked(frame),
414 _marker: PhantomData,
415 }
416 }
417 }
418
419 #[inline]
420 pub(crate) unsafe fn pop(&self) {
421 unsafe {
422 if N > 0 {
423 pop_frame()
424 }
425 }
426 }
427}