<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<br>
<br>
<blockquote type="cite" cite="mid:CY4PR1001MB2150BF5CCB1E062DBA8D16268C7C9@CY4PR1001MB2150.namprd10.prod.outlook.com">
<meta name="Generator" content="Microsoft Word 15 (filtered
medium)">
<style>@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}@font-face
{font-family:Consolas;
panose-1:2 11 6 9 2 2 4 3 2 4;}p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0cm;
font-size:10.0pt;
font-family:"Calibri",sans-serif;}a:link, span.MsoHyperlink
{mso-style-priority:99;
color:blue;
text-decoration:underline;}pre
{mso-style-priority:99;
mso-style-link:"HTML Preformatted Char";
margin:0cm;
margin-bottom:.0001pt;
font-size:10.0pt;
font-family:"Courier New",serif;}span.HTMLPreformattedChar
{mso-style-name:"HTML Preformatted Char";
mso-style-priority:99;
mso-style-link:"HTML Preformatted";
font-family:Consolas;}.MsoChpDefault
{mso-style-type:export-only;
font-size:10.0pt;
mso-ligatures:none;}div.WordSection1
{page:WordSection1;}</style>
<div class="WordSection1">
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">I like the idea when the whole “context” is out
of the ClassModel, so using it with a different context will
do the job differently. However doesn’t it mean they are
rather mutable, when you get different content based on
context?</span></p>
</div>
</blockquote>
<br>
It means certain operations are, well, contextual. If you ask a
context to generate a class, it will do so with the options of that
context. So if you generate the same class twice with different
contexts, you get different results. <br>
<br>
It also means some entities might drag parts of their creating
context with them. For example, suppose we parse a classfile using
context A, which has a mapper for attribute "Foo". Then we adapt it
using context B, that doens't know about Foo. Well, B may not know
about Foo, but the FooAttribute will have a reference to its
creating AttributeMapper. That's fine too (well, if different
contexts have radically different ideas of how a FooAttribute is
laid out, maybe not, but in that case we have bigger problems.)<br>
<br>
<br>
<blockquote type="cite" cite="mid:CY4PR1001MB2150BF5CCB1E062DBA8D16268C7C9@CY4PR1001MB2150.namprd10.prod.outlook.com">
<div class="WordSection1">
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">Some of the options already behave that way and
are quite flexible (</span><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">processDebug, generateStackmap,
constantPoolSharing, fixShortJumps, patchDeadCode,
classHierarchyResolver, filterDeadLabels) and some can be
fixed to do so (processLineNumbers).</span></p>
</div>
</blockquote>
<br>
I think its been a while since we took a good look at our options
and asked "is this the way we want it"; now is a good time to review
this. <br>
<br>
<blockquote type="cite" cite="mid:CY4PR1001MB2150BF5CCB1E062DBA8D16268C7C9@CY4PR1001MB2150.namprd10.prod.outlook.com">
<div class="WordSection1">
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">However for example attributeMapper is closely
tied with the parsed model and it would require to re-parse
when. Also the last used context would have to be stored
with the model to know if any reset of already expanded
model is needed (for example did we skipped parsing line
numbers or are they just missing?)</span></p>
</div>
</blockquote>
<br>
I think this is a place where we have to lean on existing design
constraints of backward compatibility. We can parse the attribute
with the mapper found at parse time, and we can write it with either
that mapper or the one we find at generation time. <br>
<br>
<blockquote type="cite" cite="mid:CY4PR1001MB2150BF5CCB1E062DBA8D16268C7C9@CY4PR1001MB2150.namprd10.prod.outlook.com">
<div class="WordSection1">
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">Another confusion we are already facing is when
the actual option become effective.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">For example generateStackmap(false) does not
implicitly mean they will be dropped by the transformation
(unless we expand each Code attribute). The same for
processDebug, processLineNumbers and patchDeadCode.</span></p>
</div>
</blockquote>
<br>
Correct, this is part of what I mean by the "let's review our
options and make sure they mean what we think, and write that down"
above. <br>
<br>
<blockquote type="cite" cite="mid:CY4PR1001MB2150BF5CCB1E062DBA8D16268C7C9@CY4PR1001MB2150.namprd10.prod.outlook.com">
<div class="WordSection1">
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">While
</span><span style="font-size:11.0pt;mso-fareast-language:EN-US">DROP_DEBUG_ON_READ</span><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US"> is clearly an option,
</span><span style="font-size:11.0pt;mso-fareast-language:EN-US">DROP_DEBUG_ON_WRITE</span><span style="font-size:11.0pt;mso-fareast-language:EN-US">
<span lang="EN-US">suppose to be rather a CodeTransform,
because by setting the option we do not say it will be
effective.<o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">All attributes attached to code have very
specific position, as we must expand the whole code when we
want just filter them out.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">To your example I’m not quite sure what to
expect from:<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:13.5pt;font-family:"Courier
New",serif"> ClassModel cm = CC.of(DROP_DEBUG</span><span style="font-size:13.5pt;font-family:"Courier
New",serif" lang="EN-US">).</span><span style="font-size:13.5pt;font-family:"Courier
New",serif">parse(bytes);<br>
CC.of(</span><span style="font-size:13.5pt;font-family:"Courier
New",serif" lang="EN-US">do not
</span><span style="font-size:13.5pt;font-family:"Courier
New",serif">DROP_DEBUG).transform(cm, transform);<br>
</span></p>
</div>
</blockquote>
<br>
So, what happens here is that on reading, we drop the debug
information, so the ClassModel has no debug information. When we
use that as a source, there's no debug information in the source but
any debug information added by the transform is not dropped.<br>
<br>
<blockquote type="cite" cite="mid:CY4PR1001MB2150BF5CCB1E062DBA8D16268C7C9@CY4PR1001MB2150.namprd10.prod.outlook.com">
<div class="WordSection1">
<p class="MsoNormal"><span style="font-size:13.5pt;font-family:"Courier
New",serif">
</span><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<div style="border:none;border-top:solid #B5C4DF
1.0pt;padding:3.0pt 0cm 0cm 0cm">
<p class="MsoNormal" style="margin-bottom:12.0pt"><b><span style="font-size:12.0pt;color:black">From:
</span></b><span style="font-size:12.0pt;color:black">Brian
Goetz <a class="moz-txt-link-rfc2396E" href="mailto:brian.goetz@oracle.com"><brian.goetz@oracle.com></a><br>
<b>Date: </b>Friday, 19 May 2023 16:15<br>
<b>To: </b>Adam Sotona <a class="moz-txt-link-rfc2396E" href="mailto:adam.sotona@oracle.com"><adam.sotona@oracle.com></a>,
<a class="moz-txt-link-abbreviated" href="mailto:liangchenblue@gmail.com">liangchenblue@gmail.com</a> <a class="moz-txt-link-rfc2396E" href="mailto:liangchenblue@gmail.com"><liangchenblue@gmail.com></a>,
classfile-api-dev <a class="moz-txt-link-rfc2396E" href="mailto:classfile-api-dev@openjdk.org"><classfile-api-dev@openjdk.org></a><br>
<b>Subject: </b>Re: Planned features of a classfile
context object<o:p></o:p></span></p>
</div>
<p class="MsoNormal" style="margin-bottom:12.0pt"><span style="font-size:13.5pt;font-family:"Courier
New",serif">I agree that much of what such a context
would manage is options. But I think we can also agree that
the current treatment, where we stash Options in the
CPBuilder, isn't right either. <br>
<br>
I can buy that sometimes we want to parse with different
options than we generate with. We can add this in as as
goal for rationalizing the classfile context. I suspect
also that part of the problem is that our options are too
granular: "process debug" is just a boolean, which could be
broken down further. As a not-entirely-serious suggestion:
<br>
<br>
enum ProcessDebugOptions implements Option { <br>
DROP_DEBUG, DROP_DEBUG_ON_READ, DROP_DEBUG_ON_WRITE;<br>
}<br>
<br>
Originally all our options were booleans, and we've moved
past that structurally, but haven't really reexamined all
the options we defined.<br>
<br>
I think the problem with "can't transform with different
options" stems from the fact that transform lives only on
the model, not on the context. This would let you do what
you want as:<br>
<br>
ClassModel cm = CC.of(opts1).parse(bytes);<br>
CC.of(opts2).transform(cm, transform);<br>
CC.of(opts3).transform(cm, transform);<br>
<br>
This derives from the principle that all classfile entities
are immutable and can be used in any context; no need to
re-parse.
<br>
<br>
<br>
<br>
</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">On
5/19/2023 3:52 AM, Adam Sotona wrote:<o:p></o:p></span></p>
</div>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">I think our current Classfile.Option is
already not so far from the proposed global context holder
approach.</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">The most significant use cases to persist
(class hierarchy resolution and custom attributes) can be
very well cached by keeping the Classfile.Option instances
and re-using them as many times as user needs.</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US"> </span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Consolas;mso-fareast-language:EN-US" lang="EN-US">var options =
List.of(Option.classHierarchyResolver(resolver),
</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Consolas;mso-fareast-language:EN-US" lang="EN-US"> Option.attributeMapper(mapper));</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Consolas;mso-fareast-language:EN-US" lang="EN-US"> </span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Consolas;mso-fareast-language:EN-US" lang="EN-US">Classfile.build(clsDesc, options, handler);</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Consolas;mso-fareast-language:EN-US" lang="EN-US">Classfile.parse(bytes, options); //here we
have only vararg now</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Consolas;mso-fareast-language:EN-US" lang="EN-US"> </span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">What I’m missing much much more than “global
options holder” is per-transformation options (or even
option change for transformed method).
</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">For example I would like to use one class
model to transform into multiple classes with different
options, and I have to write:</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Consolas;mso-fareast-language:EN-US" lang="EN-US"> </span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Consolas;mso-fareast-language:EN-US" lang="EN-US">Classfile.parse(bytes,
options1).transform(classTransform1);</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Consolas;mso-fareast-language:EN-US" lang="EN-US">Classfile.parse(bytes,
options2).transform(classTransform2);</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US"> </span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">Instead of simple:</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Consolas;mso-fareast-language:EN-US" lang="EN-US">var clm = Classfile.parse(bytes);</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Consolas;mso-fareast-language:EN-US" lang="EN-US">clm.transform(classTransform1, options1);</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Consolas;mso-fareast-language:EN-US" lang="EN-US">clm.transform(classTransform2, options2);</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US"> </span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">Or maybe:</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Consolas;mso-fareast-language:EN-US" lang="EN-US">var clm = Classfile.parse(bytes, options1);</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Consolas;mso-fareast-language:EN-US" lang="EN-US">clm.transform(classTransform1);</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Consolas;mso-fareast-language:EN-US" lang="EN-US">clm.setOptions(options2);</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Consolas;mso-fareast-language:EN-US" lang="EN-US">clm.transform(classTransform2);</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US"> </span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">However it raises the main question about
what options are really tied to model parsing (I think it
is only attributeMapper).</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">And what options can be safely changed later.
For example can I change processDebug, processLineNumbers
or processUnknownAttributes on already parsed class model
to get different results of the following model traversal?</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">And there are majority of options unrelated
to the parsed class model but affecting only building and
transformations (generateStackmap, constantPoolSharing,
fixShortJumps, patchDeadCode, classHierarchyResolver,
filterDeadLabels).</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US"> </span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">I think we should make more clear which
options affect what actions (parsing, building,
transformation) and give more flexibility to change them
on the fly.</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US"> </span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">Thanks,</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">Adam</span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US"> </span></p>
<div style="border:none;border-top:solid #B5C4DF
1.0pt;padding:3.0pt 0cm 0cm 0cm">
<p class="MsoNormal" style="margin-bottom:12.0pt"><b><span style="font-size:12.0pt;color:black">From:
</span></b><span style="font-size:12.0pt;color:black">classfile-api-dev
</span><a href="mailto:classfile-api-dev-retn@openjdk.org" moz-do-not-send="true"><span style="font-size:12.0pt"><classfile-api-dev-retn@openjdk.org></span></a><span style="font-size:12.0pt;color:black"> on behalf of Brian
Goetz </span><a href="mailto:brian.goetz@oracle.com" moz-do-not-send="true"><span style="font-size:12.0pt"><brian.goetz@oracle.com></span></a><span style="font-size:12.0pt;color:black"><br>
<b>Date: </b>Thursday, 18 May 2023 16:16<br>
<b>To: </b></span><a href="mailto:liangchenblue@gmail.com" moz-do-not-send="true"><span style="font-size:12.0pt">liangchenblue@gmail.com</span></a><span style="font-size:12.0pt;color:black">
</span><a href="mailto:liangchenblue@gmail.com" moz-do-not-send="true"><span style="font-size:12.0pt"><liangchenblue@gmail.com></span></a><span style="font-size:12.0pt;color:black">, classfile-api-dev
</span><a href="mailto:classfile-api-dev@openjdk.org" moz-do-not-send="true"><span style="font-size:12.0pt"><classfile-api-dev@openjdk.org></span></a><span style="font-size:12.0pt;color:black"><br>
<b>Subject: </b>Re: Planned features of a classfile
context object</span></p>
</div>
<p class="MsoNormal" style="margin-bottom:12.0pt"><span style="font-size:13.5pt;font-family:"Courier
New",serif">Currently the ConstantPoolBuilder is
another place we we attach options. This was more of a
sin of convenience than anything else; the theory was that
if we are transforming a class, we'll parse it with a set
of options, and then generate a new class which shares its
CP, and the options came along for the ride.
<br>
<br>
Searching for a better name that ClassfileContext. The
name Classfile is too good to waste, but it doesn't
represent a classfile (that's ClassModel), so calling the
new thing Classfile would likely be weird. Also
ClassfileContext would make it harder to discover the key
entry points (build/parse). Classfile.Context is better
in that it is more discoverable at least.
<br>
<br>
Classfile{Parser,Generator} are more discoverable but only
tell half the story, and there's no obvious "first half"
of the story. ClassfileReaderWriter is discoverable and
honest but long. Classfile{Broker,Manager,Mediator} sound
like parodies of the Design Patterns era. <br>
<br>
A slightly cheeky but possibly viable option is
"Classfiles"; while not a collection of classfiles, it is
a collection of behaviors _about_ classfiles.
<br>
<br>
Classfiles.of(options).parse(bytes)<br>
Classfiles.of(options).generate(handler)<br>
<br>
<br>
<br>
<br>
<br>
</span></p>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">On
5/17/2023 11:21 AM, Brian Goetz wrote:</span></p>
</div>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<p class="MsoNormal" style="margin-bottom:12.0pt"><span style="font-size:13.5pt;font-family:"Courier
New",serif">These are basically what is on my list,
though I had in mind to move _all_ option information to
the context, and leave it out of individual processing
decisions. </span></p>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">On
5/17/2023 9:59 AM, - wrote:</span></p>
</div>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<pre>Hi,</pre>
<pre>In the discussions a few weeks ago, we envisioned a Classfile context</pre>
<pre>object shared across multiple Classfile processing scenarios, mainly</pre>
<pre>for Class hierarchy information caching.</pre>
<pre> </pre>
<pre>I want to confirm that these are contents of the object, mainly</pre>
<pre>promoted from individual options:</pre>
<pre> - Class Hierarchy information caching</pre>
<pre> - Custom attribute processing</pre>
<pre> - A set of default options, propagated to individual processing (may</pre>
<pre>be overridden classfile-wise)</pre>
<pre> </pre>
<pre>What else is planned for the context object currently? Please don't</pre>
<pre>hesitate to propose. Thanks!</pre>
<pre> </pre>
<pre>Chen Liang</pre>
</blockquote>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span></p>
</blockquote>
<p class="MsoNormal"><span style="font-size:11.0pt"> </span></p>
</blockquote>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
</blockquote>
<br>
</body>
</html>