mirror of
https://github.com/urbit/ares.git
synced 2024-11-23 00:25:49 +03:00
Merge remote-tracking branch 'origin/status' into revert-177-revert-175-eamsden/gc-top-frame
This commit is contained in:
commit
be4a6552e1
@ -317,6 +317,7 @@ impl<T: Copy + Preserve> Hamt<T> {
|
|||||||
let chunk = mug & 0x1F; // 5 bits
|
let chunk = mug & 0x1F; // 5 bits
|
||||||
mug >>= 5;
|
mug >>= 5;
|
||||||
match stem.entry(chunk) {
|
match stem.entry(chunk) {
|
||||||
|
// No entry found at mug chunk index; add Leaf to current Stem
|
||||||
None => {
|
None => {
|
||||||
let new_leaf_buffer = stack.struct_alloc(1);
|
let new_leaf_buffer = stack.struct_alloc(1);
|
||||||
*new_leaf_buffer = (*n, t);
|
*new_leaf_buffer = (*n, t);
|
||||||
@ -341,6 +342,7 @@ impl<T: Copy + Preserve> Hamt<T> {
|
|||||||
};
|
};
|
||||||
break Hamt(stem_ret);
|
break Hamt(stem_ret);
|
||||||
}
|
}
|
||||||
|
// Stem found at mug chunk index; insert into found Stem
|
||||||
Some((Left(next_stem), idx)) => {
|
Some((Left(next_stem), idx)) => {
|
||||||
let new_buffer = stack.struct_alloc(stem.size());
|
let new_buffer = stack.struct_alloc(stem.size());
|
||||||
copy_nonoverlapping(stem.buffer, new_buffer, stem.size());
|
copy_nonoverlapping(stem.buffer, new_buffer, stem.size());
|
||||||
@ -354,7 +356,9 @@ impl<T: Copy + Preserve> Hamt<T> {
|
|||||||
depth += 1;
|
depth += 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
// Leaf found at mug chunk index
|
||||||
Some((Right(leaf), idx)) => {
|
Some((Right(leaf), idx)) => {
|
||||||
|
// Override existing value for key, if one exists
|
||||||
for (ldx, pair) in leaf.to_mut_slice().iter_mut().enumerate() {
|
for (ldx, pair) in leaf.to_mut_slice().iter_mut().enumerate() {
|
||||||
if unifying_equality(stack, n, &mut pair.0) {
|
if unifying_equality(stack, n, &mut pair.0) {
|
||||||
let new_leaf_buffer = stack.struct_alloc(leaf.len);
|
let new_leaf_buffer = stack.struct_alloc(leaf.len);
|
||||||
@ -376,6 +380,8 @@ impl<T: Copy + Preserve> Hamt<T> {
|
|||||||
break 'insert Hamt(stem_ret);
|
break 'insert Hamt(stem_ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// No existing pair in this Leaf matches the key, and we've maxxed out the
|
||||||
|
// Hamt depth; add the the key-value pair to the list of pairs for this Leaf
|
||||||
if depth >= 5 {
|
if depth >= 5 {
|
||||||
let new_leaf_buffer = stack.struct_alloc(leaf.len + 1);
|
let new_leaf_buffer = stack.struct_alloc(leaf.len + 1);
|
||||||
copy_nonoverlapping(leaf.buffer, new_leaf_buffer, leaf.len);
|
copy_nonoverlapping(leaf.buffer, new_leaf_buffer, leaf.len);
|
||||||
@ -394,15 +400,19 @@ impl<T: Copy + Preserve> Hamt<T> {
|
|||||||
buffer: new_buffer,
|
buffer: new_buffer,
|
||||||
};
|
};
|
||||||
break 'insert Hamt(stem_ret);
|
break 'insert Hamt(stem_ret);
|
||||||
|
// No existing pair in this Leaf matches the key, but we haven't maxxed out
|
||||||
|
// the Hamt depth yet. If we haven't hit the depth limit yet, we shouldn't
|
||||||
|
// be making a linked list of pairs. Turn the Leaf into a Stem and insert
|
||||||
|
// the new pair into the new Stem (also insert the pair in the existing
|
||||||
|
// Leaf, too).
|
||||||
} else {
|
} else {
|
||||||
// if we haven't hit depth limit yet we shouldn't be chaining
|
// Make a fake node pointing to the old leaf and "insert into it" the
|
||||||
// we'll make a fake node pointing to the old leaf and "insert into" that
|
|
||||||
// next time around
|
// next time around
|
||||||
assert!(leaf.len == 1);
|
assert!(leaf.len == 1);
|
||||||
let fake_buffer = stack.struct_alloc(1);
|
let fake_buffer = stack.struct_alloc(1);
|
||||||
*fake_buffer = Entry { leaf };
|
*fake_buffer = Entry { leaf };
|
||||||
// get the mug chunk for the noun at *the next level* so
|
// Get the mug chunk for the Noun at the *next* level so that we can
|
||||||
// we can build a fake stem for it
|
// build a fake stem for it
|
||||||
let fake_mug = mug_u32(stack, (*leaf.buffer).0);
|
let fake_mug = mug_u32(stack, (*leaf.buffer).0);
|
||||||
let fake_chunk = (fake_mug >> ((depth + 1) * 5)) & 0x1F;
|
let fake_chunk = (fake_mug >> ((depth + 1) * 5)) & 0x1F;
|
||||||
let next_stem = Stem {
|
let next_stem = Stem {
|
||||||
|
@ -31,6 +31,24 @@ const CELL_TAG: u64 = u64::MAX & INDIRECT_MASK;
|
|||||||
/** Tag mask for a cell. */
|
/** Tag mask for a cell. */
|
||||||
const CELL_MASK: u64 = !(u64::MAX >> 3);
|
const CELL_MASK: u64 = !(u64::MAX >> 3);
|
||||||
|
|
||||||
|
/* A note on forwarding pointers:
|
||||||
|
*
|
||||||
|
* Forwarding pointers are only used temporarily during copies between NockStack frames and between
|
||||||
|
* the NockStack and the PMA. Since unifying equality checks can create structural sharing between
|
||||||
|
* Noun objects, forwarding pointers act as a signal that a Noun has already been copied to the
|
||||||
|
* "to" space. The old Noun object in the "from" space is given a forwarding pointer so that any
|
||||||
|
* future refernces to the same structure know that it has already been copied and that they should
|
||||||
|
* retain the structural sharing relationship by referencing the new copy in the "to" copy space.
|
||||||
|
*
|
||||||
|
* The Nouns in the "from" space marked with forwarding pointers are dangling pointers after a copy
|
||||||
|
* operation. No code outside of the copying code checks for forwarding pointers. This invariant
|
||||||
|
* must be enforced in two ways:
|
||||||
|
* 1. The current frame must be immediately popped after preserving data, when
|
||||||
|
* copying from a junior NockStack frame to a senior NockStack frame.
|
||||||
|
* 2. All persistent derived state (e.g. Hot state, Warm state) must be preserved
|
||||||
|
* and the root NockStack frame flipped after saving data to the PMA.
|
||||||
|
*/
|
||||||
|
|
||||||
/** Tag for a forwarding pointer */
|
/** Tag for a forwarding pointer */
|
||||||
const FORWARDING_TAG: u64 = u64::MAX & CELL_MASK;
|
const FORWARDING_TAG: u64 = u64::MAX & CELL_MASK;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user