Heap space exhausted - solution and why

I’m no closer to a solution for this, but in case it helps anyone, here’s the routine R_COLLECT_MATCH_ALL which is called at the end of a (determine object) construction. I’ve used approximately Inform 6 syntax since that’s what I’m used to, but with a couple modifications (e.g. indicating explicitly which local variables are parameters and which aren’t).

[ R_COLLECT_MATCH_ALL input / current keywords oldtop iter word tmp ;
	oldtop = top; ! `top` is a global that holds the top of the heap (grows upwards)
	R_COLLECT_END(keywords);
	
l2:
	input = R_DEREF(input);
	tmp = input & $E000;
	if(tmp != $C000) jump l3;
	
	current = input - $4000; ! ref to head element
	input = current + 1; ! ref to tail element
	current = R_DEREF(current);
	
	if(keywords == nil) jump l1;
	iter = keywords;

l4:
	iter = iter & nil;
	word = memory-->iter;
	iter = memory-->(iter+1);
	
	tmp = R_WOULD_UNIFY(word, current);
	if(tmp) jump l2;
	if(iter ~= nil) jump l4;

l1:
	@throw fail; ! `fail` is a global holding a throw destination for a predicate failing

l3:
	top = oldtop;
	if(input ~= nil) jump l1;
	
	rfalse;
];