allocator: avoid calling our own heap_free entry

STACK_CHECK-s don't chain well, and should be used only on the outermost
function of any compartment call.
diff --git a/sdk/core/allocator/main.cc b/sdk/core/allocator/main.cc
index 2dd9d28..35f74af 100644
--- a/sdk/core/allocator/main.cc
+++ b/sdk/core/allocator/main.cc
@@ -944,11 +944,8 @@
 	return heap_free_internal(heapCapability, rawPointer, false);
 }
 
-__cheriot_minimum_stack(0x260) int heap_free(SObj  heapCapability,
-                                             void *rawPointer)
+int heap_free_nostackcheck(SObj heapCapability, void *rawPointer)
 {
-	// If this value changes, update `heap_can_free` as well.
-	STACK_CHECK(0x260);
 	LockGuard g{lock};
 	int       ret = heap_free_internal(heapCapability, rawPointer, true);
 	if (ret != 0)
@@ -967,6 +964,14 @@
 	return 0;
 }
 
+__cheriot_minimum_stack(0x260) int heap_free(SObj  heapCapability,
+                                             void *rawPointer)
+{
+	// If this value changes, update `heap_can_free` as well.
+	STACK_CHECK(0x260);
+	return heap_free_nostackcheck(heapCapability, rawPointer);
+}
+
 __cheriot_minimum_stack(0x1a0) ssize_t heap_free_all(SObj heapCapability)
 {
 	STACK_CHECK(0x1a0);
@@ -1256,7 +1261,7 @@
 		// The key can't be revoked and so there is no race with the key going
 		// away after the check.
 	}
-	return heap_free(heapCapability, unsealed);
+	return heap_free_nostackcheck(heapCapability, unsealed);
 }
 
 __cheriot_minimum_stack(0xf0) int token_obj_can_destroy(SObj heapCapability,