The only time you have to do anything special with a block is when someone assigns it to a non-temporary variable or returns it.
Correct. That means that you have to check, for every store into the heap, if the value being stored is a block. For some stores you'll be able to figure out that the value isn't a block, but I'm not convinced that this would be the common case. The check for blockness is likely to be relatively expensive (10 cycles).
Couldn't you modify self's gnarly inlining to handle this? I.e. wouldn't inlining be able to track a lot of cases when it is known that you don't assign a block to a non-temporary variable, return it, or have it returned for you (like from one of your blocks)?
This is true for all inlined blocks; they are never actually created and would be equally fast if we allowed non-LIFO blocks (NLBs).
There's no fundamental obstacle which makes NLBs impossible for Self. What our discussion boiled down to was:
- the desired MLB semantics are not clear (i.e. what would it mean to do a non-local return from a NLB? especially if the block was created in another process?) - NLBs would require considerable implementation effort - they are likely to add complexity to the system - the performance impact is not clear, but the store checks make it likely that the normal case (i.e. programs that do not use NLBs) is slowed down by the possibility of NLBs; on the other hand, we wouldn't need to mark blocks as 'dead' when exiting a scope.
We (or at least I) are not fundamentally opposed to NLBs; I even believe that an efficient implementation is possible. But it's a low-priority issue.