Try/catch/finally builder

Brian Goetz brian.goetz at oracle.com
Thu Sep 1 18:45:00 UTC 2022



On 9/1/2022 2:20 PM, Paul Sandoz wrote:
>> I'm a little unsure of these terms.  How does the root builder differ from the terminal builder?
>>
> The root builder is that passed by the MethodBuilder::withCode method to its consumer argument.
>
> I am still uncertain how code transformers layer in. I think they interject a form of builder in the builder chain but I am currently unsure of any impact related to TCB.

In the absence of transforms, the root builder == terminal builder == 
direct builder.  Transforms introduce two kinds of additional builders, 
chained and buffered.

Chained builders are the obvious thing you'd expect from a transform.  
The chained builder embodies the transform, it applies the transform and 
sends any emitted elements to a downstream builder (which will bottom 
out at a direct builder.)  If our transform is composed with other 
transforms (CodeTransform::andThen), we'll have multiple steps of 
chained builders, one for each step in the transform chain.

Buffered builders arise from a more complicated situation, where we have 
lifted a CodeTransform to be a MethodTransform, and then want to chain 
that method transform with another.  In this case, we allocate not a 
direct builder at the terminal end of the chain, but a buffered builder, 
one that just accumulates the elements into an ArrayList, so we can lift 
it into a MethodModel.  When we are lifting and chaining, we need to do 
this because we don't know if the next transform in the method transform 
chain will want to explode the Code attribute, so we have to be able to 
wrap a MethodModel around it.  But buffered builders are more expensive, 
so we only employ them when absolutely necessary.  From the perspective 
of a builder chain, a buffered builder is also a terminal builder; you 
can't see through the lifting.

Block builders are technically not chained builders, but that's mostly 
an accident of naming.  Both block and chained builders are 
"nonterminal" builders, which is where we maintain the reference to the 
terminal builder.  Block builders remember their parent, but chained 
builders do not (only because they have not needed to, to date, this is 
easy to add back in, and maybe you'll want this for being able to find 
all the finally blocks.)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/classfile-api-dev/attachments/20220901/b45b0e6a/attachment-0001.htm>


More information about the classfile-api-dev mailing list