Skip to content

Commit d87ecd0

Browse files
JakobDegenmeta-codesync[bot]
authored andcommitted
Add ability to name frozen heaps and inspect refs
Summary: I want to be able to do a structured walk of the starlark heap refs; this will allow me to do it Reviewed By: cjhopman Differential Revision: D91489400 fbshipit-source-id: 234605991cc56b9d828005563a7934a3aab194b4
1 parent 9107b7a commit d87ecd0

File tree

2 files changed

+47
-2
lines changed

2 files changed

+47
-2
lines changed

starlark/src/environment/modules.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ use crate::values::OwnedFrozenValue;
5757
use crate::values::Trace;
5858
use crate::values::Tracer;
5959
use crate::values::Value;
60+
use crate::values::layout::heap::heap_type::FrozenHeapName;
6061
use crate::values::layout::heap::heap_type::HeapKind;
6162
use crate::values::layout::heap::profile::aggregated::AggregateHeapProfileInfo;
6263
use crate::values::layout::heap::profile::aggregated::RetainedHeapProfile;
@@ -425,6 +426,17 @@ impl<'v> Module<'v> {
425426

426427
/// Freeze the environment, all its value will become immutable afterwards.
427428
pub fn freeze(self) -> FreezeResult<FrozenModule> {
429+
self.freeze_impl(None)
430+
}
431+
432+
/// Freeze the environment and assign a name to the contained frozen heap.
433+
///
434+
/// See `FrozenHeapRef::name` for more details.
435+
pub fn freeze_and_name(self, name: FrozenHeapName) -> FreezeResult<FrozenModule> {
436+
self.freeze_impl(Some(name))
437+
}
438+
439+
fn freeze_impl(self, name: Option<FrozenHeapName>) -> FreezeResult<FrozenModule> {
428440
let Module {
429441
names,
430442
slots,
@@ -470,7 +482,7 @@ impl<'v> Module<'v> {
470482
}
471483

472484
Ok(FrozenModule {
473-
heap: frozen_heap.into_ref(),
485+
heap: frozen_heap.into_ref_impl(name),
474486
module: frozen_module_ref,
475487
extra_value,
476488
eval_duration: start.elapsed() + eval_duration.get(),

starlark/src/values/layout/heap/heap_type.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
* limitations under the License.
1616
*/
1717

18+
use std::any::Any;
1819
use std::cell::Cell;
1920
use std::cell::RefCell;
2021
use std::cell::RefMut;
@@ -215,13 +216,17 @@ pub struct FrozenHeap {
215216
str_interner: RefCell<FrozenStringValueInterner>,
216217
}
217218

219+
pub type FrozenHeapName = Box<dyn Any + Send + Sync + 'static>;
220+
218221
/// `FrozenHeap` when it is no longer modified and can be share between threads.
219222
/// Although, `arena` is not safe to share between threads, but at least `refs` is.
220-
#[derive(Default, Allocative)]
223+
#[derive(Allocative)]
221224
#[allow(clippy::non_send_fields_in_send_ty)]
222225
struct FrozenFrozenHeap {
223226
arena: Arena<ChunkAllocator>,
224227
refs: Box<[FrozenHeapRef]>,
228+
#[allocative(skip)] // We don't really expect it to be big
229+
name: Option<FrozenHeapName>,
225230
}
226231

227232
// Safe because we never mutate the Arena other than with &mut
@@ -302,6 +307,22 @@ impl FrozenHeapRef {
302307
.as_ref()
303308
.map_or_else(HeapSummary::default, |a| a.arena.allocated_summary())
304309
}
310+
311+
/// Get the name of this heap.
312+
///
313+
/// Names can be assigned when finalizing frozen heaps; in practice, this is done when freezing
314+
/// modules, see `Module::freeze_and_name`.
315+
///
316+
/// The name is intentionally made available here and not at a higher point like the module
317+
/// level so that it can be inspected even when traversing the dependency graph of frozen heaps.
318+
pub fn name(&self) -> Option<&FrozenHeapName> {
319+
self.0.as_ref().and_then(|a| a.name.as_ref())
320+
}
321+
322+
/// Get the frozen heaps that this frozen heap depends on.
323+
pub fn refs(&self) -> impl Iterator<Item = &FrozenHeapRef> {
324+
self.0.as_ref().map(|h| h.refs.iter()).into_iter().flatten()
325+
}
305326
}
306327

307328
impl FrozenHeap {
@@ -310,10 +331,21 @@ impl FrozenHeap {
310331
Self::default()
311332
}
312333

334+
/// `into_ref` but also assign a name
335+
///
336+
/// See `FrozenHeapRef::name` for more details.
337+
pub fn name_and_into_ref(self, name: FrozenHeapName) -> FrozenHeapRef {
338+
self.into_ref_impl(Some(name))
339+
}
340+
313341
/// After all values have been allocated, convert the [`FrozenHeap`] into a
314342
/// [`FrozenHeapRef`] which can be [`clone`](Clone::clone)d, shared between threads,
315343
/// and ensures the underlying values allocated on the [`FrozenHeap`] remain valid.
316344
pub fn into_ref(self) -> FrozenHeapRef {
345+
self.into_ref_impl(None)
346+
}
347+
348+
pub(crate) fn into_ref_impl(self, name: Option<FrozenHeapName>) -> FrozenHeapRef {
317349
let FrozenHeap {
318350
mut arena, refs, ..
319351
} = self;
@@ -325,6 +357,7 @@ impl FrozenHeap {
325357
FrozenHeapRef(Some(Arc::new(FrozenFrozenHeap {
326358
arena,
327359
refs: refs.into_iter().collect(),
360+
name,
328361
})))
329362
}
330363
}

0 commit comments

Comments
 (0)