Memoize only when every arg is immutable; mutable containers hash by heap idx and go stale. */
(args: &[Val], heap: &super::types::HeapPool)
| 217 | |
| 218 | /* Memoize only when every arg is immutable; mutable containers hash by heap idx and go stale. */ |
| 219 | fn args_memoizable(args: &[Val], heap: &super::types::HeapPool) -> bool { |
| 220 | use super::types::HeapObj; |
| 221 | args.iter().all(|v| { |
| 222 | if !v.is_heap() { return true; } |
| 223 | // Post-call args aren't rooted, so the body may have freed one; a freed slot (None) is not memoizable, nor are mutable containers. |
| 224 | match heap.try_get(*v) { |
| 225 | Some(o) => !matches!(o, HeapObj::List(_) | HeapObj::Dict(_) | HeapObj::Set(_) | HeapObj::Instance(..)), |
| 226 | None => false, |
| 227 | } |
| 228 | }) |
| 229 | } |
| 230 | |
| 231 | /* Memoize only immediates (int/float/bool/None) and immutable heap objects; fresh mutable containers or tuples/sets wrapping them must stay per-call to avoid aliasing and falsifying `is`. */ |
| 232 | fn result_memoizable(result: Val, heap: &super::types::HeapPool) -> bool { |