Question on locals allocation in BlockCodeBuilder

Brian Goetz brian.goetz at oracle.com
Tue Sep 13 15:12:04 UTC 2022


Right, that's probably a mistake.  (This is what I meant by the locals 
stuff is under-tested.)

Yes, CCB should probably delegate to parent.  If the parent is a block, 
any locals used by transforming that block should be local to that block.

On 9/13/2022 10:41 AM, Adam Sotona wrote:
>
> OK, understood.
>
> Problem is probably in ChainedCodeBuilder, which skips 
> BlockCodeBuilder downstream and allocates locals in the terminal 
> DirectCodeBuilder directly.
>
> *From: *Brian Goetz <brian.goetz at oracle.com>
> *Date: *Tuesday, 13 September 2022 16:28
> *To: *Adam Sotona <adam.sotona at oracle.com>, 
> classfile-api-dev at openjdk.org <classfile-api-dev at openjdk.org>
> *Subject: *Re: Question on locals allocation in BlockCodeBuilder
>
> This isn't intended to prohibit allocation of locals in blocks; it is 
> to detect when two different mechanisms are used to allocate locals 
> together.  Are you getting this error?
>
> We define allocateLocal in CodeBuilder.  In the base (Direct) code 
> builder, when you call allocateLocal, it bumps up a high water mark 
> (topLocal).  There is no way to "deallocate" a local; this is an 
> allocation that is global to the Code attribute being built.
>
> In the various BlockBuilder implementations, they implement their own 
> allocateLocal to:
>
>  - start counting initially at the high water mark of their parent;
>  - let the user allocate locals starting at that high water mark;
>  - when the block is finished, we reclaim all of the locals allocate 
> in the block, by dropping back down to the starting high water mark.
>
> The problem is that these two mechanisms -- the "global" allocation of 
> DirectCodeBuilder and the "local" allocation of BlockCodeBuilder don't 
> know about each other's work. Here's an example of what could go wrong:
>
> .withCode(db -> {
>     int x = db.allocateLocal(TypeKind.INT); // OK, global allocation
>     db.aconst_1();
>     db.ifThen(bb -> {
>         // both the DirectCodeBuilder and BlockCodeBuilder (db and bb) 
> are in scope here
>         int y = bb.allocateLocal(TypeKind.INT);  // OK, local allocation
>         int z = db.allocateLocal(TypeKind.INT);  // conflict!
>     });
> });
>
> The problem is that I used both mechanisms inside the block.  It would 
> be ok to exclusively use db, or exclusively use bb, to allocate 
> locals, but not both at once.  The error you've found detects this 
> conflict and throws, albeit with a not so helpful error message.
>
> Overall I think using both mechanisms at once will be rare, because 
> its rare to mix using both the "tip" and "root" builders at the same 
> time -- that's usually a bug.
>
> If a transform needs locals for its work, it should allocate a local 
> from the root builder in the (stateful) transform atStart() method.
>
> On 9/13/2022 9:06 AM, Adam Sotona wrote:
>
>     Hi,
>
>     I have a question related to an older fragment of code in
>     BlockCodeBuilderImpl, that actively prohibits allocation of locals
>     in BlockCodeBuilder:
>
>         public void *end*() {
>
>     terminal.with((LabelTarget) endLabel);
>
>             if (terminalMaxLocals != topLocal(terminal)) {
>
>                 throw new IllegalStateException("Interference in local
>     variable slot management");
>
>             }
>
>         }
>
>     Do we really want to prevent locals allocated and valid in the
>     context of BlockCodeBuilder only?
>
>     Thanks,
>
>     Adam
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/classfile-api-dev/attachments/20220913/c8752bdf/attachment.htm>


More information about the classfile-api-dev mailing list