<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<font size="4"><font face="monospace">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>
</font></font><font size="4"><font face="monospace"><font size="4"><font face="monospace"> CC.of(opts3).transform(cm, transform);<br>
</font></font><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>
</font></font><br>
<div class="moz-cite-prefix">On 5/19/2023 3:52 AM, Adam Sotona
wrote:<br>
</div>
<blockquote type="cite" cite="mid:CY4PR1001MB21508C93F6B00FE5FEB5BFF78C7C9@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;}@font-face
{font-family:"Times New Roman \(Body CS\)";
panose-1:2 11 6 4 2 2 2 2 2 4;}p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0cm;
font-size:10.0pt;
font-family:"Calibri",sans-serif;}pre
{mso-style-priority:99;
mso-style-link:"HTML Preformatted Char";
margin:0cm;
margin-bottom:.0001pt;
font-size:10.0pt;
font-family:"Courier New";}span.HTMLPreformattedChar
{mso-style-name:"HTML Preformatted Char";
mso-style-priority:99;
mso-style-link:"HTML Preformatted";
font-family:Consolas;}span.EmailStyle20
{mso-style-type:personal-reply;
font-family:"Calibri",sans-serif;
color:windowtext;}.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 think our current Classfile.Option is already
not so far from the proposed global context holder approach.<o:p></o:p></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.<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;font-family:Consolas;mso-fareast-language:EN-US" lang="EN-US">var options =
List.of(Option.classHierarchyResolver(resolver),
<o:p></o:p></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));<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Consolas;mso-fareast-language:EN-US" lang="EN-US"><o:p> </o:p></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);<o:p></o:p></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<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Consolas;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">What I’m missing much much more than “global
options holder” is per-transformation options (or even
option change for transformed method).
<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 I would like to use one class model
to transform into multiple classes with different options,
and I have to write:<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Consolas;mso-fareast-language:EN-US" lang="EN-US"><o:p> </o:p></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);<o:p></o:p></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><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"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">Instead of simple:<o:p></o:p></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);<o:p></o:p></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);<o:p></o:p></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);<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">Or maybe:<o:p></o:p></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);<o:p></o:p></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);<o:p></o:p></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);<o:p></o:p></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);<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">However it raises the main question about what
options are really tied to model parsing (I think it is only
attributeMapper).<o:p></o:p></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?<o:p></o:p></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).<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">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.<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">Thanks,<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US" lang="EN-US">Adam<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>
<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
<a class="moz-txt-link-rfc2396E" href="mailto:classfile-api-dev-retn@openjdk.org"><classfile-api-dev-retn@openjdk.org></a> on behalf of
Brian Goetz <a class="moz-txt-link-rfc2396E" href="mailto:brian.goetz@oracle.com"><brian.goetz@oracle.com></a><br>
<b>Date: </b>Thursday, 18 May 2023 16:16<br>
<b>To: </b><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"">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>
</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/17/2023 11:21 AM, Brian Goetz wrote:<o:p></o:p></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"">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><span style="font-size:11.0pt"><o:p></o:p></span></p>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">On
5/17/2023 9:59 AM, - wrote:<o:p></o:p></span></p>
</div>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<pre>Hi,<o:p></o:p></pre>
<pre>In the discussions a few weeks ago, we envisioned a Classfile context<o:p></o:p></pre>
<pre>object shared across multiple Classfile processing scenarios, mainly<o:p></o:p></pre>
<pre>for Class hierarchy information caching.<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre>I want to confirm that these are contents of the object, mainly<o:p></o:p></pre>
<pre>promoted from individual options:<o:p></o:p></pre>
<pre> - Class Hierarchy information caching<o:p></o:p></pre>
<pre> - Custom attribute processing<o:p></o:p></pre>
<pre> - A set of default options, propagated to individual processing (may<o:p></o:p></pre>
<pre>be overridden classfile-wise)<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre>What else is planned for the context object currently? Please don't<o:p></o:p></pre>
<pre>hesitate to propose. Thanks!<o:p></o:p></pre>
<pre><o:p> </o:p></pre>
<pre>Chen Liang<o:p></o:p></pre>
</blockquote>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</blockquote>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
</blockquote>
<br>
</body>
</html>