Skip to content

Commit

Permalink
MarkCompact: Add some visualization for relocate procs
Browse files Browse the repository at this point in the history
  • Loading branch information
nineonine committed Oct 30, 2023
1 parent dcb03cc commit ee4691c
Show file tree
Hide file tree
Showing 8 changed files with 46 additions and 25 deletions.
1 change: 0 additions & 1 deletion frontend/src/HeapGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ interface HeapGridProps {

const cellStyleMap: Record<CellStatus, string> = {
[CellStatus.Free]: 'white',
[CellStatus.ToBeFree]: 'magenta',
[CellStatus.Allocated]: '#7CCD7C',
[CellStatus.Marked]: 'yellow',
[CellStatus.Used]: '#228B22',
Expand Down
28 changes: 21 additions & 7 deletions frontend/src/Visualization.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,28 +141,38 @@ const Visualization: React.FC = () => {
if (pendingGCEvents.length > 0) {
const alterHeapState = (event: GCEvent): void => {
if (event.type === 'FreeObject') {
const cellIndex: number = cellIndexFromEvent(event)!;
const [cellIndex] = cellIndexesFromEvent(event)!;
setMemory(memory.map((c, i) => {
if (i === cellIndex) {
c.status = CellStatus.Free;
}
return c
}));
} else if (event.type === 'MarkObject') {
const cellIndex: number = cellIndexFromEvent(event)!;
const [cellIndex] = cellIndexesFromEvent(event)!;
setMemory(memory.map((c, i) => {
if (i === cellIndex) {
c.status = CellStatus.Marked;
}
return c
}));
} else if (event.type === 'MoveObject') {
const { from, to, size } = event;
setMemory(memory.map((c, i) => {
if (i >= from && i < from + size) {
c.status = CellStatus.Free;
} else if (i >= to && i < to + size) {
c.status = CellStatus.Allocated;
}
return c;
}));
}
}
const currentGCEvent: GCEvent = pendingGCEvents[0];
setGCEventLogs(prevLogs => [...prevLogs, currentGCEvent]);
if (eventHasAnimation(currentGCEvent)) {
const cellIndex: number = cellIndexFromEvent(currentGCEvent)!;
enqueueAnimation(cellIndex, animationFromGCEvent(currentGCEvent));
const cellIndexes: number[] = cellIndexesFromEvent(currentGCEvent)!;
enqueueAnimation(cellIndexes, animationFromGCEvent(currentGCEvent));
}

// Update heap cell state if needed.
Expand Down Expand Up @@ -288,14 +298,18 @@ const animationFromGCEvent = (event: GCEvent): TimedAnimation => {
return animation;
}

const cellIndexFromEvent = (event: GCEvent): number | null => {
const cellIndexesFromEvent = (event: GCEvent): number[] => {
switch (event.type) {
case 'MarkObject':
case 'FreeObject':
return event.addr;
return [event.addr];
case 'MoveObject':
return [event.from, event.to];
case 'UpdateFwdPtr':
return [event.old, event.new];
case 'GCPhase':
default:
return null;
return [];
}
};

Expand Down
5 changes: 5 additions & 0 deletions frontend/src/eventlog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ export const gcEventOps = (event: GCEvent): EventOps => ({
case "MarkObject":
case "FreeObject":
return [event.addr];
case "MoveObject":
return Array.from({ length: event.size }, (_, i) => event.to + i);
default:
return [];
}
Expand All @@ -54,6 +56,9 @@ export const gcEventOps = (event: GCEvent): EventOps => ({
case "FreeObject":
message = `Freed Object at address 0x${event.addr.toString(16)}`;
break;
case "MoveObject":
message = `Move object 0x${event.from.toString(16)} -> 0x${event.to.toString(16)}`;
break;
case "UpdateFwdPtr":
message = `Update Forward Pointer 0x${event.old.toString(16)} -> 0x${event.new.toString(16)}`;
break;
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/types.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
export enum CellStatus {
Free = "Free",
ToBeFree = "ToBeFree",
Allocated = "Allocated",
Marked = "Marked",
Used = "Used"
Expand Down Expand Up @@ -71,4 +70,5 @@ export type GCEvent =
| { type: "GCPhase", msg: string }
| { type: "MarkObject", addr: number, size: number }
| { type: "FreeObject", addr: number, size: number }
| { type: "MoveObject", from: number, to: number, size: number }
| { type: "UpdateFwdPtr", old: number, new: number };
25 changes: 15 additions & 10 deletions frontend/src/useHeapAnimation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,23 @@ const useHeapAnimation = () => {
setHighlightedCells([]);
};

const enqueueAnimation = (cellIndex: number, animation: TimedAnimation) => {
// Remove any existing animation for this cell
setAnimatedCells(prevState => prevState.filter(cell => cell.cellIndex !== cellIndex));
setAnimatedCells(prevState => [...prevState, { cellIndex, animation }]);
const enqueueAnimation = (cellIndexes: number[], animation: TimedAnimation) => {
// Remove any existing animations for these cells
setAnimatedCells(prevState => prevState.filter(cell => !cellIndexes.includes(cell.cellIndex)));

// Set timeout to clear the animation after its duration
const timeout = window.setTimeout(() => {
setAnimatedCells(prevState => prevState.filter(cell => cell.cellIndex !== cellIndex));
}, animation.duration);
// Add new animations for these cells
const newAnimations: AnimatedCell[] = cellIndexes.map(cellIndex => ({ cellIndex, animation }));
setAnimatedCells(prevState => [...prevState, ...newAnimations]);

setAnimationTimeouts(prevState => [...prevState, timeout]);
};
// Set timeouts to clear the animations after their duration
const timeouts = cellIndexes.map(cellIndex => {
return window.setTimeout(() => {
setAnimatedCells(prevState => prevState.filter(cell => cell.cellIndex !== cellIndex));
}, animation.duration);
});

setAnimationTimeouts(prevState => [...prevState, ...timeouts]);
}

const clearAnimations = () => {
// Clear all animated cells
Expand Down
8 changes: 3 additions & 5 deletions src/gc/compact/two_finger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,10 @@ use crate::{
};

// Two-Finger Algorithm,
// introduced by W. L. Edwards in 1974
// introduced by Edwards in 1974
pub fn compact(heap: &mut Heap, eventlog: &mut Vec<GCEvent>) {
let start: usize = 0;
let end: usize = heap.last_object_addr().unwrap();
eventlog.push(GCEvent::phase(format!(
"Run 2 finger compaction. Start: {start} End: {end}"
)));
let forwarding_ptrs = relocate(heap, eventlog, start, end);
update_references(heap, &forwarding_ptrs, eventlog);
}
Expand Down Expand Up @@ -104,7 +101,8 @@ fn can_fit_into(heap: &Heap, move_in: ObjAddr, dest: ObjAddr) -> bool {

fn move_object(heap: &mut Heap, eventlog: &mut Vec<GCEvent>, from: ObjAddr, to: ObjAddr) {
if heap.objects.get(&from).is_some() {
eventlog.push(GCEvent::phase(format!("Moving object from {from} to {to}")));
let size = heap.objects.get(&from).unwrap().size();
eventlog.push(GCEvent::MoveObject{from, to, size});
match heap.move_object(from, to) {
Ok(res) => res,
Err(_e) => panic!("move_object {_e}"),
Expand Down
1 change: 1 addition & 0 deletions src/gc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ pub enum GCEvent {
GCPhase { msg: String },
MarkObject { addr: usize, size: usize },
FreeObject { addr: usize, size: usize },
MoveObject { from: usize, to: usize, size: usize },
UpdateFwdPtr { old: usize, new: usize },
}

Expand Down
1 change: 0 additions & 1 deletion src/heap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ impl MemoryCell {
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub enum CellStatus {
Free,
ToBeFree,
Allocated,
Marked,
Used,
Expand Down

0 comments on commit ee4691c

Please sign in to comment.