[External] : Re: Mapping byte code offsets in custom code attributes
Rafael Winterhalter
rafael.wth at gmail.com
Tue Nov 12 17:41:36 UTC 2024
Hei Adam,
as for ASM, I also think that the inline visiting of code type annotations
without a label is a limitation in its API design. It does not apply as
much to the tree API where one can walk up the stack to insert an
annotation in the correct position, but I have seen this being a hassle in
the visitor API, requiring a second pass. Not so much for annotations, but
for try-catch-segments, this is a particular problem and I have gone as far
as writing the exception table attribute by hand, which ASM allows by
implementing a custom Attribute. The class file format is flexible when it
comes to setting attributes independently from the attributed code, and I
therefore believe that this should be the primary abstraction. I have no
problem with the concept of pseudo instructions, but personally, I would
have dropped them and asked users to request if label positions represent
something that is not related to other instructions. Most people who
instrument code do either not care about attributes at all, or they do in
what case they exactly know what they want to do, and what attribute to
access for such metadata.
As you say, everything can be worked around, but this is my belief based on
my experience with using ASM. This is why I had hoped that all attributes
could still be label-centric and always allow for manual definition after
creating the code attribute. This way, power-users get the freedom they
want, while others might still want to visit the inline pseudo-instructions
for their convenience.
Best regards, Rafael
Am Di., 12. Nov. 2024 um 17:21 Uhr schrieb Chen Liang <
chen.l.liang at oracle.com>:
> Hi Rafael,
> I think the particular arrangement ASM has for line numbers is probably
> due to that line number was a later addition to a very early version of
> ASM: the label argument is largely redundant. If the extra label is
> useful, I guess that will be added for type-use annotations in code too,
> which ASM obviously didn't do.
>
> Also, I don't see the point of patching line numbers: this still requires
> you to know the labels ahead of time. If you really, really need this
> pattern, you can first generate methods in a class, and process with
> ClassBuilder::transformingMethods (which, at this stage, has a complete
> code view that your line number computation may need to access) to add line
> numbers.
>
> Regards,
> Chen Liang
> ------------------------------
> *From:* Rafael Winterhalter <rafael.wth at gmail.com>
> *Sent:* Monday, November 11, 2024 4:57 PM
> *To:* Adam Sotona <adam.sotona at oracle.com>
> *Cc:* classfile-api-dev <classfile-api-dev at openjdk.org>; Chen Liang <
> chen.l.liang at oracle.com>
> *Subject:* Re: [External] : Re: Mapping byte code offsets in custom code
> attributes
>
> I fully agree that the current API covers 99% of the use cases. However,
> in ASM, labels are visited before line numbers. The actual line numbers can
> be patched in at any time. If you are working with a large ASM-based
> application, and you want to migrate this application to using the Class
> File API, this migration is much less straight-forward.
>
> At the same time, this is an API limitation, and not inherent with the
> class file API. It feels like an unnecessary burden that could easily be
> resolved.
>
> Am Mo., 11. Nov. 2024 um 21:21 Uhr schrieb Adam Sotona <
> adam.sotona at oracle.com>:
>
> Hi Rafael,
>
> Here is an example method:
>
>
>
> static void *m*() {
>
> int a = 1;
>
> int b = 2;
>
> a = 3;
>
> b = 4;
>
> }
>
>
>
> This is a sample transformation manipulating line numbers and local
> variables:
>
> ClassFile.*of*().transformClass(clm, ClassTransform.
> *transformingMethodBodies*((cob, coe) -> {
>
> switch (coe) {
>
> case LineNumber ln ->
>
> cob.lineNumber(ln.line() + 100); // change line numers
>
> case LocalVariable lv when lv.name
> <https://urldefense.com/v3/__http://lv.name__;!!ACWV5N9M2RV99hQ!KreDZAW-VisNlVfaaDmJdOzX8VLJJX-qNrPFUKbK4TA4fMrqOokLXbz8pKyQf6ZuViqSXLiM1XQCs2l2WUILKQ$>
> ().equalsString("a") ->
>
> cob.localVariable(lv.slot(), "x", lv.typeSymbol(),
> cob.startLabel(), lv.endScope()); // rename var “a” to “x” and change its
> start scope
>
> case LocalVariable _ -> {} // drop var “b”
>
> default -> cob.with(coe);
>
> }
>
> }
>
> ).andThen(ClassTransform.*transformingMethodBodies*(CodeTransform.
> *endHandler*(cob -> cob
>
> .localVariable(1, "y", ConstantDescs.*CD_int*,
> cob.startLabel(), cob.endLabel()) // add var “y”
>
> .lineNumber(999))))); // add line number
>
>
>
> And as you can see there are no custom attributes nor bytecode offset
> conversions necessary.
>
>
>
> Yes, Class-File API contains several “raw” points where bytecode offsets
> are intentionally exposed to support specific use cases, however no one is
> obliged to use them.
>
>
>
> I hope this finally addressed your questions.
>
>
>
> Adam
>
>
>
> *From: *Rafael Winterhalter <rafael.wth at gmail.com>
> *Date: *Monday, 11 November 2024 at 18:59
> *To: *Adam Sotona <adam.sotona at oracle.com>, classfile-api-dev <
> classfile-api-dev at openjdk.org>, Chen Liang <chen.l.liang at oracle.com>
> *Subject: *Re: [External] : Re: Mapping byte code offsets in custom code
> attributes
>
> (I realized that I did not reply-all and wanted to add the mailing list
> again. Some of the discussion can be found in the quotation below, if
> anyone is reading.)
>
>
>
> I cannot describe a use case that goes beyond mere printing where I could
> work with BCIs in the context of a Class File API represented list of
> instructions. If I wanted to create a CharacterRangeTableAttribute, I would
> always have to resolve BCIs to labels. Why not let the AttributeMapper
> handle this translation consistently but require BCI as input to the
> factory method? To me, this seems more error prone and less type-safe.
>
>
>
> Maybe I should ask the question differently: what led to a choice of using
> labels over BCIs when dealing with stack map frames, and for the runtime
> (in-)visible type annotations? I think the answer is that those are more
> convenient, despite that they are inlined. I cannot make sense that two
> groups of attributes are represented in two different ways, when labels are
> obviously more expressive. I get that type annotations and stack map frames
> might be more central attributes, where the others are more often used by
> power users. But also power users would benefit from the better
> abstraction, so I think this should be the target? If the answer is that
> there is no time to adjust the API, I wonder if one should avoid exposing
> those four other attributes until there is time, especially with Java 24
> likely being less adopted compared to Java 25 where Oracle plans to offer
> LTS. I feel like exposing BCIs is premature, if labels could be used, and
> it would be a shame to lose the opportunity to use labels within these four
> info attributes. I already see the BCI factories and methods being
> deprecated in a future release, so why not aim for the best solution
> already today?
>
>
>
> I understand that this API change is out of scope for JDK-8341274, but I
> would love to see a follow up change that adjusts those four interfaces to
> use labels and not BCIs, such that the Class File API is consistent. If
> possible within the release of Java 24, or Java 25 with the BCI methods not
> exposed before that.
>
>
>
> Am Mo., 11. Nov. 2024 um 16:19 Uhr schrieb Adam Sotona <
> adam.sotona at oracle.com>:
>
> Purpose of JDK-8341274 is to enable labels translation for custom
> attributes, it means other attributes than LineNumberTable,
> LocalVariableTable, LocalVariableTypeTable or CharacterRangeTable. It does
> not include any plan to remodel existing architecture.
>
>
>
> What exact use case related to the above-mentioned attributes are you
> struggling with?
>
>
>
> Thanks,
>
> Adam
>
>
>
> *From: *Rafael Winterhalter <rafael.wth at gmail.com>
> *Date: *Monday, 11 November 2024 at 15:44
> *To: *Adam Sotona <adam.sotona at oracle.com>
> *Subject: *Re: [External] : Re: Mapping byte code offsets in custom code
> attributes
>
> Hello,
>
>
>
> As a goal of this conversation, I was hoping to give feedback on where I
> see limitations of the current API, something that resulted in JDK-8341274.
> As I wrote in previous emails on this list, I am evaluating it against a
> number of use cases, all of which use ASM as of today. When I speak of
> migration, I mean that users of ASM would take the class file API into use
> instead. This is why I hoped that JDK-8341274 could be concluded by using
> this API to remodel these four info attributes, to be consistent with
> TypeAnnotation and UninitializedVerificationTypeInfo. Clearly, if those
> attributes are using labels instead of BCIs, there should be a benefit of
> using labels exclusively? I had hoped that the Class File API could become
> as consistent as ASM in this regard.
>
>
>
> I also understand that the mentioned info elements are streamlined with
> the code instruction API. But as the use of code generation has evolved
> upon ASM over many years, where attributes are not always generated at the
> same time as the attributed code, but later. Rather, one notes down BCIs as
> labels in the generated code and writes the attribute upon completion. In
> some cases, such logic can be rewritten to fit the streamlined model. But
> sometimes this is really hard. Neither the class file format, nor the class
> file API require that attributes on code are created simultaneously, so I
> was hoping that explicit BCIs could be removed from the public API
> altogether. Today, they only appear at four locations (LocalVariable,
> LocalVariableType, CharacterRange and LineNumber) throughout the entire
> Class File API. Anywhere else, BCIs are resolved as labels. I think
> changing that would add to the Class File APIs quality, consistency and
> usability, when working with these attributes, similar to how it is
> suggested to work with custom ones. I hoped I could argue that case before
> the API becomes final and this can no longer be changed.
>
>
>
> Patching line numbers is indeed supported, if one reiterates over the
> code, but I would not call this a seamless solution in contrast to just
> writing that attribute after completing the code attribute, if this is what
> is desired.
>
>
>
> Thanks, Rafael
>
>
>
> Am Mo., 11. Nov. 2024 um 14:38 Uhr schrieb Adam Sotona <
> adam.sotona at oracle.com>:
>
> Hi Rafael,
>
> I’m not sure what is goal of this discussion. Let me answer your questions
> below.
>
>
>
> *From: *Rafael Winterhalter <rafael.wth at gmail.com>
>
>
>
> - What I do not understand is why this model should not be applied for
> LineNumberInfo, LocalVariableTypeInfo, LocalVariableInfo and
> CharacterRangeInfo?
>
>
>
> LocalVariable, LocalVariableType, CharacterRange and LineNumber are pseudo
> instructions (code elements). As such they are integral part of the
> CodeModel and they are streamed and transformed with the instructions. LineNumberInfo,
> LocalVariableTypeInfo, LocalVariableInfo are just inner structure data
> holders of the corresponding attributes and they serve only to specific use
> cases requesting the raw values.
>
>
>
>
>
> - Once a translation mechanism is in place, it should be
> straightforward to migrate?
>
>
>
> I’m not sure what migration do you have in mind.
>
>
>
>
>
> - What is the point of offering these attributes in a (public) API
> then, if not as ready for consumption?
>
>
>
> There are regular consumers of the API, like for example javap.
>
>
>
>
>
> - As I see it: Without labels, I would need to implement a custom
> mapper, for example for writing a custom LineNumberTableAttribute,
>
>
>
> There are two aspects:
>
> 1. A custom LineNumberTable attribute mapper overriding the default
> one is not accepted by the API.
> 2. Implementation of a custom attribute similar to LineNumberTable
> attribute is supported and after JDK-8341274 the support will improve.
>
>
>
>
>
> - if I wanted to patch line numbers after creating a method.
>
>
>
> Patching line numbers is seamlessly supported. CodeTransform can freely
> change, add, and remove line numbers.
>
>
>
>
>
> From the context I understand you call for indirect translation of each
> (currently inline) LocalVariable, LocalVariableType, CharacterRange and
> LineNumber into a Label-parametrized pseudo instructions + corresponding
> LabelTargets. Such model has been rejected in the early Class-File API
> prototypes for significant negative performance impact.
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/classfile-api-dev/attachments/20241112/d0a75e61/attachment-0001.htm>
More information about the classfile-api-dev
mailing list