From adam.sotona at oracle.com Wed Jan 3 13:55:56 2024 From: adam.sotona at oracle.com (Adam Sotona) Date: Wed, 3 Jan 2024 13:55:56 +0000 Subject: Using descriptor than internal name hashes for CP ClassEntry In-Reply-To: References: Message-ID: Hi Chen, It looks promising, do you have some benchmark numbers? Thanks, Adam From: classfile-api-dev on behalf of liangchenblue at gmail.com Date: Sunday, 24 December 2023 at 17:11 To: classfile-api-dev Subject: Using descriptor than internal name hashes for CP ClassEntry Hi, Since we are using ClassDesc quite often to represent Class constants in Class-File API, yet it's costly to hash them (as they are internal names in CP but descriptors in ClassDesc), that Adam has created shortcuts to speed up fetching of Object CE from CD_Object, I have thought of a new tactic to hash ClassEntry by full descriptor than by internal name alone. I have made a prototype at https://github.com/liachmodded/jdk/commit/2932a560b0029352f1309883b3c5eecfb3d2c771 The idea is that hashing CE as descriptors is easier than creating substrings for hashing; substring hashing is hard to compute, but appending and prepending and hash is much easier. Does this look like a good idea? I only included a test to confirm its correctness, but haven't got time to bench it against, say, the port of java.lang,invoke or ProxyGenerator. Chen -------------- next part -------------- An HTML attachment was scrubbed... URL: From liangchenblue at gmail.com Thu Jan 4 05:19:17 2024 From: liangchenblue at gmail.com (-) Date: Wed, 3 Jan 2024 23:19:17 -0600 Subject: Using descriptor than internal name hashes for CP ClassEntry In-Reply-To: References: Message-ID: Unfortunately not yet, and I am busy recently so cannot provide one until the weekends. I think this approach would work best for cases where we generate completely new class files, such as j.l.invoke, Proxy, and MethodHandleProxies. It probably won't make too much of a difference if we don't pass ClassDesc in directly. Also, the points you've mentioned before, that MethodType and Class should have their dedicated, validated fast-paths for Descriptor conversion, would probably have a similar boosts. In Class::descriptorString(), there's an extra allocation of the internal name from String::replace. We might have less allocation and better performance if we can avoid that allocation by moving the replacement to be done on the StringBuilder's array instead. For your previous descriptor to internal name conversion, I think we might add some fast-path conversions for frequently-occuring ClassDesc like Object to directly return "java/lang/Object" than to compute substring, to simulate the existing fast-paths in j.l.invoke generation. However, all these are speculation; we need benchmark to show their effectiveness in dedicated scenarios (in addition to the corpus transformation, say addition of new CF elements, spinning new class files, removing CF elements) Chen Liang On Wed, Jan 3, 2024 at 7:58?AM Adam Sotona wrote: > Hi Chen, > > It looks promising, do you have some benchmark numbers? > > > > Thanks, > > Adam > > > > *From: *classfile-api-dev on behalf > of liangchenblue at gmail.com > *Date: *Sunday, 24 December 2023 at 17:11 > *To: *classfile-api-dev > *Subject: *Using descriptor than internal name hashes for CP ClassEntry > > Hi, > > Since we are using ClassDesc quite often to represent Class constants in > Class-File API, yet it's costly to hash them (as they are internal names in > CP but descriptors in ClassDesc), that Adam has created shortcuts to speed > up fetching of Object CE from CD_Object, I have thought of a new tactic to > hash ClassEntry by full descriptor than by internal name alone. > > > > I have made a prototype at > https://github.com/liachmodded/jdk/commit/2932a560b0029352f1309883b3c5eecfb3d2c771 > > > > The idea is that hashing CE as descriptors is easier than creating > substrings for hashing; substring hashing is hard to compute, but appending > and prepending and hash is much easier. > > > > Does this look like a good idea? I only included a test to confirm its > correctness, but haven't got time to bench it against, say, the port of > java.lang,invoke or ProxyGenerator. > > > > Chen > -------------- next part -------------- An HTML attachment was scrubbed... URL: From adam.sotona at oracle.com Fri Jan 5 15:38:16 2024 From: adam.sotona at oracle.com (Adam Sotona) Date: Fri, 5 Jan 2024 15:38:16 +0000 Subject: Revisit j.l.classfile.CodeBuilder API surface Message-ID: Hi, j.l.classfile.CodeBuilder API consist of more than 230 methods. Existing ClassFile API use cases proved the concept of one big CodeBuilder is comfortable. However there are some redundancies, glitches in the naming, some frequently used methods are hard to find and some methods have low practical use. Majority of the methods may be divided into three main levels: 1. methods building low level bytecode instructions according to JVMS chapter 6.5 (aaload, aastore, aconst_null...) 2. methods reconstructing individual subtypes of j.l.classfile.Instruction from given arguments (loadInstruction, storeInstruction, incrementInstruction, branchInstruction...) 3. methods modeling high level code blocks (block, ifThen, ifThenElse, trying...) Many methods from level 2 (with suffix `Instruction`) seem to be obsolete or misplaced. Some of them are duplicates of methods from level 1, some are obsolete and some are very useful, however a bit hidden. The API should be cleaned a bit while in preview. I would like to open a discussion on the following proposed changes in the CodeBuilder methods: * incrementInstruction remove as duplicate of iinc * lookupSwitchInstruction remove as duplicate of lookupswitch * tableSwitchInstruction remove as duplicate of tableswitch * throwInstruction remove as duplicate of athrow * invokeDynamicInstruction remove as duplicate of invokedynamic * stackInstruction remove as obsolete with suggested replacements: with(StackInstruction.of(...)) * monitorInstruction remove as obsolete with suggested replacements: monitorenter, monitorexit, or with(MonitorInstruction.of(...)) * nopInstruction remove as duplicate of nop * typecheckInstruction remove as obsolete with suggested replacements: checkcast, instanceOf, or with(TypeCheckInstruction.of(...)) * loadInstruction rename to loadLocal * storeInstruction rename to storeLocal * branchInstruction rename to branch * invokeInstruction rename to invoke * newObjectInstruction rename to newObject * newPrimitiveArrayInstruction rename to newPrimitiveArray * newReferenceArrayInstruction rename to newReferenceArray * newMultidimensionalArrayInstruction rename to newMultidimensionalArray * arrayLoadInstruction rename to arrayLoad * arrayStoreInstruction rename to arrayStore * convertInstruction rename to conversion * operatorInstruction rename to operator * constantInstruction rename to loadConstant * fieldInstruction rename to fieldAccess * instanceof_ rename to instanceOf * returnInstruction rename to return_ Here is the related RFE: https://bugs.openjdk.org/browse/JDK-8323058 Draft of the CSR (no spec yet): https://bugs.openjdk.org/browse/JDK-8323067 And draft of the Pull Request: https://github.com/openjdk/jdk/pull/17282 Any comments are welcome. Thank you, Adam -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Fri Jan 5 15:52:18 2024 From: brian.goetz at oracle.com (Brian Goetz) Date: Fri, 5 Jan 2024 10:52:18 -0500 Subject: Revisit j.l.classfile.CodeBuilder API surface In-Reply-To: References: Message-ID: <47442f04-9358-498e-9c0e-b5ed64c72133@oracle.com> Let me fill in some history here. Much of the design process for this library could be described as an iterated game of "find the primitive."? The first version of the API had a zillion ad-hoc methods, with little structural relation.? At some point we hit upon a model-driven analysis, and broke down instructions into families (loads, stores, etc), and at that point, we thought methods like loadInstruction were the primitives.? But we hadn't actually hit bottom yet; after many rounds of refactoring, it became clear that there was one primitive for the builder hierarchy, now called `with`, and all of the builder methods now bottom out at that. At the same time, we added a number of "convenience" methods such as aload_0() and aload(int n) (which now just delegate to with() or loadInstruction()), and over time, we found that most generative use cases used these methods much more than the primitives (which is fine.) At this point, I think many of the xxxInstruction (and its rigid naming convention) are vestiges of a previous attempt to organize the API.? Some still have uses, though should be renamed to reflect that they are mere conveniences (such as arrayLoadInstruction to arrayLoad). (Does anyone use operator(opcode), or can we drop that one too?) So I support this simplification. Having done the refactor, were there any surprises in the usages of various CodeBuilder methods? On 1/5/2024 10:38 AM, Adam Sotona wrote: > > Hi, > > j.l.classfile.CodeBuilder API consist of more than 230 methods. > > Existing ClassFile API use cases proved the concept of one big > CodeBuilder is comfortable. However there are some redundancies, > glitches in the naming, some frequently used methods are hard to find > and some methods have low practical use. > > Majorityof the methods may be dividedinto three main levels: > 1.methods building low level bytecode instructions according to JVMS > chapter 6.5 (aaload, aastore, aconst_null...) > 2.methods reconstructing individual subtypes of > j.l.classfile.Instruction from given arguments (loadInstruction, > storeInstruction, incrementInstruction, branchInstruction...) > 3.methods modeling high level code blocks (block, ifThen, ifThenElse, > trying...) > > Many methods from level 2 (with suffix `Instruction`) seem to be > obsolete or misplaced. Some of them are duplicates of methods from > level 1, some are obsolete and some are very useful, however a bit > hidden. The API should be cleaned a bit while in preview. > > I would like to open a discussion on the following proposed changes in > the CodeBuilder?methods: > > * incrementInstruction?remove as duplicate of iinc > * lookupSwitchInstruction?remove as duplicate of lookupswitch > * tableSwitchInstruction?remove as duplicate of tableswitch > * throwInstruction?remove as duplicate of athrow > * invokeDynamicInstruction?remove as duplicate of invokedynamic > * stackInstruction?remove as obsolete with suggested replacements: > with(StackInstruction.of(...)) > * monitorInstruction?remove as obsolete with suggested replacements: > monitorenter, monitorexit, or with(MonitorInstruction.of(...)) > * nopInstruction?remove as duplicate of nop > * typecheckInstruction?remove as obsolete with suggested > replacements: checkcast, instanceOf, or > with(TypeCheckInstruction.of(...)) > * loadInstruction?rename to loadLocal > * storeInstruction?rename to storeLocal > * branchInstruction?rename to branch > * invokeInstruction?rename to invoke > * newObjectInstruction?rename to newObject > * newPrimitiveArrayInstruction?rename to newPrimitiveArray > * newReferenceArrayInstruction?rename to newReferenceArray > * newMultidimensionalArrayInstruction?rename to newMultidimensionalArray > * arrayLoadInstruction?rename to arrayLoad > * arrayStoreInstruction?rename to arrayStore > * convertInstruction?rename to conversion > * operatorInstruction?rename to operator > * constantInstruction?rename to loadConstant > * fieldInstruction?rename to fieldAccess > * instanceof_?rename to instanceOf > * returnInstruction?rename to return_ > > Here is the related RFE: https://bugs.openjdk.org/browse/JDK-8323058 > > Draft of the CSR (no spec yet): > https://bugs.openjdk.org/browse/JDK-8323067 > > And draft of the Pull Request: https://github.com/openjdk/jdk/pull/17282 > > Any comments are welcome. > > Thank you, > > Adam > -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Fri Jan 5 16:02:36 2024 From: brian.goetz at oracle.com (Brian Goetz) Date: Fri, 5 Jan 2024 11:02:36 -0500 Subject: Using descriptor than internal name hashes for CP ClassEntry In-Reply-To: References: Message-ID: The approach seems promising. Note that the EntryMap type is fussy about hash values -- you can't pass zero as a hash value.? The `hashString(String)` method ensured that the hash value was never zero. On 12/24/2023 11:11 AM, - wrote: > Hi, > Since we are using ClassDesc quite often to represent Class constants > in Class-File API, yet it's costly to hash them (as they are > internal?names in CP but descriptors in ClassDesc), that Adam has > created shortcuts to speed up fetching of Object CE from CD_Object, I > have thought of a new tactic to hash ClassEntry by full descriptor > than by internal name alone. > > I have made a prototype at > https://github.com/liachmodded/jdk/commit/2932a560b0029352f1309883b3c5eecfb3d2c771 > > The idea is that hashing CE as descriptors is easier than creating > substrings for hashing; substring hashing is hard to compute, but > appending and prepending and hash is much easier. > > Does this look like a good idea? I only included a test to confirm its > correctness, but haven't got time to bench it against, say, the port > of java.lang,invoke or ProxyGenerator. > > Chen -------------- next part -------------- An HTML attachment was scrubbed... URL: From adam.sotona at oracle.com Fri Jan 5 16:21:01 2024 From: adam.sotona at oracle.com (Adam Sotona) Date: Fri, 5 Jan 2024 16:21:01 +0000 Subject: Revisit j.l.classfile.CodeBuilder API surface In-Reply-To: <47442f04-9358-498e-9c0e-b5ed64c72133@oracle.com> References: <47442f04-9358-498e-9c0e-b5ed64c72133@oracle.com> Message-ID: >From JDK perspective I see no problem to drop operator(opcode). More of an expectation than a surprise is frequent use of constantInstruction, so refactored a lot of cases. One surprise is heavy use of xyzInstruction methods in our own tests (originated from the times before ?conveniences? appear). However, these are worth of update anyway. From: Brian Goetz Date: Friday, 5 January 2024 at 16:52 To: Adam Sotona , classfile-api-dev at openjdk.org Subject: Re: Revisit j.l.classfile.CodeBuilder API surface Let me fill in some history here. Much of the design process for this library could be described as an iterated game of "find the primitive." The first version of the API had a zillion ad-hoc methods, with little structural relation. At some point we hit upon a model-driven analysis, and broke down instructions into families (loads, stores, etc), and at that point, we thought methods like loadInstruction were the primitives. But we hadn't actually hit bottom yet; after many rounds of refactoring, it became clear that there was one primitive for the builder hierarchy, now called `with`, and all of the builder methods now bottom out at that. At the same time, we added a number of "convenience" methods such as aload_0() and aload(int n) (which now just delegate to with() or loadInstruction()), and over time, we found that most generative use cases used these methods much more than the primitives (which is fine.) At this point, I think many of the xxxInstruction (and its rigid naming convention) are vestiges of a previous attempt to organize the API. Some still have uses, though should be renamed to reflect that they are mere conveniences (such as arrayLoadInstruction to arrayLoad). (Does anyone use operator(opcode), or can we drop that one too?) So I support this simplification. Having done the refactor, were there any surprises in the usages of various CodeBuilder methods? On 1/5/2024 10:38 AM, Adam Sotona wrote: Hi, j.l.classfile.CodeBuilder API consist of more than 230 methods. Existing ClassFile API use cases proved the concept of one big CodeBuilder is comfortable. However there are some redundancies, glitches in the naming, some frequently used methods are hard to find and some methods have low practical use. Majority of the methods may be divided into three main levels: 1. methods building low level bytecode instructions according to JVMS chapter 6.5 (aaload, aastore, aconst_null...) 2. methods reconstructing individual subtypes of j.l.classfile.Instruction from given arguments (loadInstruction, storeInstruction, incrementInstruction, branchInstruction...) 3. methods modeling high level code blocks (block, ifThen, ifThenElse, trying...) Many methods from level 2 (with suffix `Instruction`) seem to be obsolete or misplaced. Some of them are duplicates of methods from level 1, some are obsolete and some are very useful, however a bit hidden. The API should be cleaned a bit while in preview. I would like to open a discussion on the following proposed changes in the CodeBuilder methods: * incrementInstruction remove as duplicate of iinc * lookupSwitchInstruction remove as duplicate of lookupswitch * tableSwitchInstruction remove as duplicate of tableswitch * throwInstruction remove as duplicate of athrow * invokeDynamicInstruction remove as duplicate of invokedynamic * stackInstruction remove as obsolete with suggested replacements: with(StackInstruction.of(...)) * monitorInstruction remove as obsolete with suggested replacements: monitorenter, monitorexit, or with(MonitorInstruction.of(...)) * nopInstruction remove as duplicate of nop * typecheckInstruction remove as obsolete with suggested replacements: checkcast, instanceOf, or with(TypeCheckInstruction.of(...)) * loadInstruction rename to loadLocal * storeInstruction rename to storeLocal * branchInstruction rename to branch * invokeInstruction rename to invoke * newObjectInstruction rename to newObject * newPrimitiveArrayInstruction rename to newPrimitiveArray * newReferenceArrayInstruction rename to newReferenceArray * newMultidimensionalArrayInstruction rename to newMultidimensionalArray * arrayLoadInstruction rename to arrayLoad * arrayStoreInstruction rename to arrayStore * convertInstruction rename to conversion * operatorInstruction rename to operator * constantInstruction rename to loadConstant * fieldInstruction rename to fieldAccess * instanceof_ rename to instanceOf * returnInstruction rename to return_ Here is the related RFE: https://bugs.openjdk.org/browse/JDK-8323058 Draft of the CSR (no spec yet): https://bugs.openjdk.org/browse/JDK-8323067 And draft of the Pull Request: https://github.com/openjdk/jdk/pull/17282 Any comments are welcome. Thank you, Adam -------------- next part -------------- An HTML attachment was scrubbed... URL: From liangchenblue at gmail.com Fri Jan 5 16:21:46 2024 From: liangchenblue at gmail.com (-) Date: Fri, 5 Jan 2024 10:21:46 -0600 Subject: Revisit j.l.classfile.CodeBuilder API surface In-Reply-To: <47442f04-9358-498e-9c0e-b5ed64c72133@oracle.com> References: <47442f04-9358-498e-9c0e-b5ed64c72133@oracle.com> Message-ID: I love this simplification too! One nitpick is that now we have `loadLocal` and `storeLocal`, maybe we should rename existing `allocateLocal` to something like `newLocalSlot` ("allocate" is disliked by panama devs too), so it's clear it returns a slot index like `parameterSlot` or `receiverSlot` do. In addition, the previous "instruction family" APIs have their downfalls too: some families are not complete, and may throw exceptions upon combination of certain arguments but are not well documented. For example, a `conversion(TypeKind.LongType, TypeKind.ByteType)` would fail, because bytecode actually uses 2 instructions: l2i and i2b. (maybe upgrading this `conversion` to emit multiple bytecode is a solution, too) Same for calling `newPrimitiveArray(TypeKind.VoidType)` etc. Similarly, the `operator(Opcode)` is just a watered-down version of ASM's `visitInsn`, yet is more risky as you can pass in other no-operand opcodes that fail at runtime without compile-time hints. In contrast, the more specific methods in CodeBuilder avoids these pitfalls. After all, my rant above is not against this change, but instead are improvements that are enabled by this simplification. Cheers, Chen Liang On Fri, Jan 5, 2024 at 9:52?AM Brian Goetz wrote: > Let me fill in some history here. > > Much of the design process for this library could be described as an > iterated game of "find the primitive." The first version of the API had a > zillion ad-hoc methods, with little structural relation. At some point we > hit upon a model-driven analysis, and broke down instructions into families > (loads, stores, etc), and at that point, we thought methods like > loadInstruction were the primitives. But we hadn't actually hit bottom > yet; after many rounds of refactoring, it became clear that there was one > primitive for the builder hierarchy, now called `with`, and all of the > builder methods now bottom out at that. > > At the same time, we added a number of "convenience" methods such as > aload_0() and aload(int n) (which now just delegate to with() or > loadInstruction()), and over time, we found that most generative use cases > used these methods much more than the primitives (which is fine.) > > At this point, I think many of the xxxInstruction (and its rigid naming > convention) are vestiges of a previous attempt to organize the API. Some > still have uses, though should be renamed to reflect that they are mere > conveniences (such as arrayLoadInstruction to arrayLoad). > > (Does anyone use operator(opcode), or can we drop that one too?) > > So I support this simplification. > > Having done the refactor, were there any surprises in the usages of > various CodeBuilder methods? > > > On 1/5/2024 10:38 AM, Adam Sotona wrote: > > Hi, > > j.l.classfile.CodeBuilder API consist of more than 230 methods. > > Existing ClassFile API use cases proved the concept of one big > CodeBuilder is comfortable. However there are some redundancies, glitches > in the naming, some frequently used methods are hard to find and some > methods have low practical use. > > > > Majority of the methods may be divided into three main levels: > 1. methods building low level bytecode instructions according to JVMS > chapter 6.5 (aaload, aastore, aconst_null...) > 2. methods reconstructing individual subtypes of > j.l.classfile.Instruction from given arguments (loadInstruction, > storeInstruction, incrementInstruction, branchInstruction...) > 3. methods modeling high level code blocks (block, ifThen, ifThenElse, > trying...) > > > > Many methods from level 2 (with suffix `Instruction`) seem to be obsolete > or misplaced. Some of them are duplicates of methods from level 1, some are > obsolete and some are very useful, however a bit hidden. The API should > be cleaned a bit while in preview. > > I would like to open a discussion on the following proposed changes in the > CodeBuilder methods: > > - incrementInstruction remove as duplicate of iinc > - lookupSwitchInstruction remove as duplicate of lookupswitch > - tableSwitchInstruction remove as duplicate of tableswitch > - throwInstruction remove as duplicate of athrow > - invokeDynamicInstruction remove as duplicate of invokedynamic > - stackInstruction remove as obsolete with suggested replacements: > with(StackInstruction.of(...)) > - monitorInstruction remove as obsolete with suggested replacements: > monitorenter, monitorexit, or with(MonitorInstruction.of(...)) > - nopInstruction remove as duplicate of nop > - typecheckInstruction remove as obsolete with suggested replacements: > checkcast, instanceOf, or with(TypeCheckInstruction.of(...)) > - loadInstruction rename to loadLocal > - storeInstruction rename to storeLocal > - branchInstruction rename to branch > - invokeInstruction rename to invoke > - newObjectInstruction rename to newObject > - newPrimitiveArrayInstruction rename to newPrimitiveArray > - newReferenceArrayInstruction rename to newReferenceArray > - newMultidimensionalArrayInstruction rename to > newMultidimensionalArray > - arrayLoadInstruction rename to arrayLoad > - arrayStoreInstruction rename to arrayStore > - convertInstruction rename to conversion > - operatorInstruction rename to operator > - constantInstruction rename to loadConstant > - fieldInstruction rename to fieldAccess > - instanceof_ rename to instanceOf > - returnInstruction rename to return_ > > Here is the related RFE: https://bugs.openjdk.org/browse/JDK-8323058 > > Draft of the CSR (no spec yet): > https://bugs.openjdk.org/browse/JDK-8323067 > > And draft of the Pull Request: https://github.com/openjdk/jdk/pull/17282 > > > > Any comments are welcome. > > > > Thank you, > > Adam > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Fri Jan 5 16:33:41 2024 From: brian.goetz at oracle.com (Brian Goetz) Date: Fri, 5 Jan 2024 11:33:41 -0500 Subject: Revisit j.l.classfile.CodeBuilder API surface In-Reply-To: References: <47442f04-9358-498e-9c0e-b5ed64c72133@oracle.com> Message-ID: <513bad3c-2c0c-4ba1-84fc-465480a77acb@oracle.com> One problem with `newLocalSlot` is that it now conflicts with the new instructions like `newObject`, and thus makes it less clear whether the method is _generating_ bytecode or merely setting up for a future operation.? But perhaps `allocateSlot` or `allocateLocalSlot` or `reserveLocalSlot` is more clear. On 1/5/2024 11:21 AM, - wrote: > I love this simplification too! > > One nitpick is that now we have `loadLocal` and `storeLocal`, maybe we > should rename existing `allocateLocal` to something like > `newLocalSlot` ("allocate" is disliked by panama devs too), so it's > clear it returns a slot index like `parameterSlot` or `receiverSlot` do. > > In addition, the previous "instruction family" APIs have their > downfalls too: some families are not complete, and may throw > exceptions upon combination of certain arguments?but are not well > documented. For example, a `conversion(TypeKind.LongType, > TypeKind.ByteType)` would fail, because bytecode actually uses 2 > instructions: l2i and i2b. (maybe upgrading this `conversion` to emit > multiple bytecode is a solution, too) Same for calling > `newPrimitiveArray(TypeKind.VoidType)` etc. Similarly, the > `operator(Opcode)` is just a watered-down version of ASM's > `visitInsn`, yet is more risky as you can pass in other no-operand > opcodes that fail at runtime without compile-time hints. > > In contrast, the more specific methods in CodeBuilder avoids these > pitfalls. > > After all, my rant above is not against this change, but instead are > improvements that are enabled by this simplification. > > Cheers, > Chen Liang > > On Fri, Jan 5, 2024 at 9:52?AM Brian Goetz wrote: > > Let me fill in some history here. > > Much of the design process for this library could be described as > an iterated game of "find the primitive." The first version of the > API had a zillion ad-hoc methods, with little structural > relation.? At some point we hit upon a model-driven analysis, and > broke down instructions into families (loads, stores, etc), and at > that point, we thought methods like loadInstruction were the > primitives. But we hadn't actually hit bottom yet; after many > rounds of refactoring, it became clear that there was one > primitive for the builder hierarchy, now called `with`, and all of > the builder methods now bottom out at that. > > At the same time, we added a number of "convenience" methods such > as aload_0() and aload(int n) (which now just delegate to with() > or loadInstruction()), and over time, we found that most > generative use cases used these methods much more than the > primitives (which is fine.) > > At this point, I think many of the xxxInstruction (and its rigid > naming convention) are vestiges of a previous attempt to organize > the API.? Some still have uses, though should be renamed to > reflect that they are mere conveniences (such as > arrayLoadInstruction to arrayLoad). > > (Does anyone use operator(opcode), or can we drop that one too?) > > So I support this simplification. > > Having done the refactor, were there any surprises in the usages > of various CodeBuilder methods? > > > On 1/5/2024 10:38 AM, Adam Sotona wrote: >> >> Hi, >> >> j.l.classfile.CodeBuilder API consist of more than 230 methods. >> >> Existing ClassFile API use cases proved the concept of one big >> CodeBuilder is comfortable. However there are some redundancies, >> glitches in the naming, some frequently used methods are hard to >> find and some methods have low practical use. >> >> Majorityof the methods may be dividedinto three main levels: >> 1.methods building low level bytecode instructions according to >> JVMS chapter 6.5 (aaload, aastore, aconst_null...) >> 2.methods reconstructing individual subtypes of >> j.l.classfile.Instruction from given arguments (loadInstruction, >> storeInstruction, incrementInstruction, branchInstruction...) >> 3.methods modeling high level code blocks (block, ifThen, >> ifThenElse, trying...) >> >> Many methods from level 2 (with suffix `Instruction`) seem to be >> obsolete or misplaced. Some of them are duplicates of methods >> from level 1, some are obsolete and some are very useful, however >> a bit hidden. The API should be cleaned a bit while in preview. >> >> I would like to open a discussion on the following proposed >> changes in the CodeBuilder?methods: >> >> * incrementInstruction?remove as duplicate of iinc >> * lookupSwitchInstruction?remove as duplicate of lookupswitch >> * tableSwitchInstruction?remove as duplicate of tableswitch >> * throwInstruction?remove as duplicate of athrow >> * invokeDynamicInstruction?remove as duplicate of invokedynamic >> * stackInstruction?remove as obsolete with suggested >> replacements: with(StackInstruction.of(...)) >> * monitorInstruction?remove as obsolete with suggested >> replacements: monitorenter, monitorexit, or >> with(MonitorInstruction.of(...)) >> * nopInstruction?remove as duplicate of nop >> * typecheckInstruction?remove as obsolete with suggested >> replacements: checkcast, instanceOf, or >> with(TypeCheckInstruction.of(...)) >> * loadInstruction?rename to loadLocal >> * storeInstruction?rename to storeLocal >> * branchInstruction?rename to branch >> * invokeInstruction?rename to invoke >> * newObjectInstruction?rename to newObject >> * newPrimitiveArrayInstruction?rename to newPrimitiveArray >> * newReferenceArrayInstruction?rename to newReferenceArray >> * newMultidimensionalArrayInstruction?rename to >> newMultidimensionalArray >> * arrayLoadInstruction?rename to arrayLoad >> * arrayStoreInstruction?rename to arrayStore >> * convertInstruction?rename to conversion >> * operatorInstruction?rename to operator >> * constantInstruction?rename to loadConstant >> * fieldInstruction?rename to fieldAccess >> * instanceof_?rename to instanceOf >> * returnInstruction?rename to return_ >> >> Here is the related RFE: https://bugs.openjdk.org/browse/JDK-8323058 >> >> Draft of the CSR (no spec yet): >> https://bugs.openjdk.org/browse/JDK-8323067 >> >> And draft of the Pull Request: >> https://github.com/openjdk/jdk/pull/17282 >> >> >> Any comments are welcome. >> >> Thank you, >> >> Adam >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From liangchenblue at gmail.com Mon Jan 8 17:52:47 2024 From: liangchenblue at gmail.com (-) Date: Mon, 8 Jan 2024 11:52:47 -0600 Subject: API change proposal for Builders and Models Message-ID: Hello Class-File API list, I have 2 API change recommendations for CF Builders and Models: 1. Remove all original() methods in ClassBuilder, MethodBuilder, FieldBuilder, and CodeBuilder. 2. Make all parent() methods return directly (than wrapping in an Optional) for MethodModel, FieldModel, and CodeModel. Rationale: 1. Removal of original() methods All builders are only accessible as lambda parameters only in Class-File API; and whether these builders are spinning new objects or transforming existing models is already determined by entrypoint methods, such as ClassBuilder::withMethod vs ClassBuilder::transformMethod. It's unlikely for a user to share Consumer for these distinct entrypoint methods. If needed, users can simply capture the existing class/method/field/code models they pass, instead of calling `original` and unwrapping the risky Optional. Currently, these methods have no usage within the JDK parts that migrated to Class-File API, except delegation in chained/buffered implementations. So the impact would be minimal. 2. Conversion of parent() methods to return directly instead of Optional When we examine the XxxModel implementations, we can find they may be non-bound in BufferedXxxBuilder.Model. However, these models, upon closer inspection, are not visible to users at all; they are purely created to serve as a stub ClassElement or MethodElement, to be passable to the ClassFileBuilder::with methods. Thus, we should make parent() always return directly instead of returning Optional. Currently, there are many usages of parent() methods within the JDK; all of them are immediately followed by a .get() or .orElseThrow() call, so this change can be helpful API-wise. In addition, there are other UOE-stubbed methods in these Models, notably BufferedMethodBuilder::code. Thus, the implementation changes can be as simple as changing those methods to throw UOE instead (for they shouldn't be visible to users first and foremost) What do you think of these 2 proposals? Any feedback is welcome. Chen Liang -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Mon Jan 8 19:30:59 2024 From: brian.goetz at oracle.com (Brian Goetz) Date: Mon, 8 Jan 2024 14:30:59 -0500 Subject: API change proposal for Builders and Models In-Reply-To: References: Message-ID: <1ae12df2-8679-4567-aa61-8d192b887975@oracle.com> I would want to review the code further, but what is common to both of these is that they were introduced early in the refactoring process, and may have been rendered obsolete by later refactorings, so both of these seem credible to me. BufferedXxxBuilder exists for composition of transforms; I think these builders might well be exposed to the transformed involved? On 1/8/2024 12:52 PM, - wrote: > Hello Class-File API list, > I have 2 API change recommendations for CF Builders and Models: > 1. Remove all original() methods in ClassBuilder, MethodBuilder, > FieldBuilder, and CodeBuilder. > 2. Make all parent() methods return directly (than wrapping in an > Optional) for MethodModel, FieldModel, and CodeModel. > > Rationale: > 1. Removal of original() methods > All builders are only accessible as lambda parameters?only in > Class-File API; and whether these builders are spinning new objects or > transforming existing models is already determined by entrypoint > methods, such as ClassBuilder::withMethod vs > ClassBuilder::transformMethod. It's unlikely for a user to share > Consumer for these distinct entrypoint methods. If needed, > users can simply capture the existing class/method/field/code models > they pass, instead of calling `original` and unwrapping the risky > Optional. > > Currently, these methods have no usage within the JDK parts that > migrated to Class-File API, except delegation in chained/buffered > implementations. So the impact would be minimal. > > 2. Conversion of parent() methods to return directly instead of Optional > When we examine the XxxModel implementations, we can find they may be > non-bound in BufferedXxxBuilder.Model. However, these models, upon > closer inspection, are not visible to users at all; they are purely > created to serve as a stub ClassElement or MethodElement, to be > passable to the ClassFileBuilder::with methods. Thus, we should make > parent() always return directly instead of returning Optional. > > Currently, there are many usages of parent() methods within the JDK; > all of them are immediately followed by a .get() or .orElseThrow() > call, so this change can be helpful API-wise. In addition, there are > other UOE-stubbed methods in these Models, notably > BufferedMethodBuilder::code. Thus, the implementation changes can be > as simple as changing those methods to throw UOE instead (for they > shouldn't be visible to users first and foremost) > > > What do you think of these 2 proposals? Any feedback is welcome. > > Chen Liang -------------- next part -------------- An HTML attachment was scrubbed... URL: From adam.sotona at oracle.com Tue Jan 9 16:32:25 2024 From: adam.sotona at oracle.com (Adam Sotona) Date: Tue, 9 Jan 2024 16:32:25 +0000 Subject: Revisit j.l.classfile.CodeBuilder API surface Message-ID: Hi, I?ve updated the PR draft with removal of operator method as obsolete and newPrimitiveArray, newReferenceArray and newMultidimensionalArray methods as duplicate. I?ve also extended conversion method to support the whole matrix (including multi-step conversions, no-op conversions and BooleanType conversions), see CodeBuilder.java#L548 Regarding the allocateLocal I would slightly prefer to keep it, however allocateSlot or allocateLocalSlot or reserveLocalSlot are also fine. Prefix new would be confusing. Thanks, Adam From: Brian Goetz Date: Friday, 5 January 2024 at 17:33 To: liangchenblue at gmail.com , classfile-api-dev Cc: Adam Sotona Subject: Re: Revisit j.l.classfile.CodeBuilder API surface One problem with `newLocalSlot` is that it now conflicts with the new instructions like `newObject`, and thus makes it less clear whether the method is _generating_ bytecode or merely setting up for a future operation. But perhaps `allocateSlot` or `allocateLocalSlot` or `reserveLocalSlot` is more clear. On 1/5/2024 11:21 AM, - wrote: I love this simplification too! One nitpick is that now we have `loadLocal` and `storeLocal`, maybe we should rename existing `allocateLocal` to something like `newLocalSlot` ("allocate" is disliked by panama devs too), so it's clear it returns a slot index like `parameterSlot` or `receiverSlot` do. In addition, the previous "instruction family" APIs have their downfalls too: some families are not complete, and may throw exceptions upon combination of certain arguments but are not well documented. For example, a `conversion(TypeKind.LongType, TypeKind.ByteType)` would fail, because bytecode actually uses 2 instructions: l2i and i2b. (maybe upgrading this `conversion` to emit multiple bytecode is a solution, too) Same for calling `newPrimitiveArray(TypeKind.VoidType)` etc. Similarly, the `operator(Opcode)` is just a watered-down version of ASM's `visitInsn`, yet is more risky as you can pass in other no-operand opcodes that fail at runtime without compile-time hints. In contrast, the more specific methods in CodeBuilder avoids these pitfalls. After all, my rant above is not against this change, but instead are improvements that are enabled by this simplification. Cheers, Chen Liang On Fri, Jan 5, 2024 at 9:52?AM Brian Goetz > wrote: Let me fill in some history here. Much of the design process for this library could be described as an iterated game of "find the primitive." The first version of the API had a zillion ad-hoc methods, with little structural relation. At some point we hit upon a model-driven analysis, and broke down instructions into families (loads, stores, etc), and at that point, we thought methods like loadInstruction were the primitives. But we hadn't actually hit bottom yet; after many rounds of refactoring, it became clear that there was one primitive for the builder hierarchy, now called `with`, and all of the builder methods now bottom out at that. At the same time, we added a number of "convenience" methods such as aload_0() and aload(int n) (which now just delegate to with() or loadInstruction()), and over time, we found that most generative use cases used these methods much more than the primitives (which is fine.) At this point, I think many of the xxxInstruction (and its rigid naming convention) are vestiges of a previous attempt to organize the API. Some still have uses, though should be renamed to reflect that they are mere conveniences (such as arrayLoadInstruction to arrayLoad). (Does anyone use operator(opcode), or can we drop that one too?) So I support this simplification. Having done the refactor, were there any surprises in the usages of various CodeBuilder methods? -------------- next part -------------- An HTML attachment was scrubbed... URL: From adam.sotona at oracle.com Tue Jan 9 16:35:19 2024 From: adam.sotona at oracle.com (Adam Sotona) Date: Tue, 9 Jan 2024 16:35:19 +0000 Subject: Revisit j.l.classfile.CodeBuilder API surface In-Reply-To: References: Message-ID: Sorry, wrong PR https://github.com/openjdk/jdk/pull/17282 in the link below. From: classfile-api-dev on behalf of Adam Sotona Date: Tuesday, 9 January 2024 at 17:32 To: Brian Goetz , liangchenblue at gmail.com , classfile-api-dev Subject: Re: Revisit j.l.classfile.CodeBuilder API surface Hi, I?ve updated the PR draft with removal of operator method as obsolete and newPrimitiveArray, newReferenceArray and newMultidimensionalArray methods as duplicate. I?ve also extended conversion method to support the whole matrix (including multi-step conversions, no-op conversions and BooleanType conversions), see CodeBuilder.java#L548 Regarding the allocateLocal I would slightly prefer to keep it, however allocateSlot or allocateLocalSlot or reserveLocalSlot are also fine. Prefix new would be confusing. Thanks, Adam -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Tue Jan 9 16:44:40 2024 From: brian.goetz at oracle.com (Brian Goetz) Date: Tue, 9 Jan 2024 11:44:40 -0500 Subject: Revisit j.l.classfile.CodeBuilder API surface In-Reply-To: References: Message-ID: These look good to me.? (Perhaps some of the instruction-specific methods could use the singleton instances of the single-bytecode instructions rather than the factory?) On 1/9/2024 11:35 AM, Adam Sotona wrote: > > Sorry, wrong PR https://github.com/openjdk/jdk/pull/17282 in the link > below. > > *From: *classfile-api-dev on > behalf of Adam Sotona > *Date: *Tuesday, 9 January 2024 at 17:32 > *To: *Brian Goetz , liangchenblue at gmail.com > , classfile-api-dev > > *Subject: *Re: Revisit j.l.classfile.CodeBuilder API surface > > Hi, > > I?ve updated the PR draft > with removal of operatormethod as obsolete and > > newPrimitiveArray, newReferenceArrayand > newMultidimensionalArraymethods as duplicate. > > I?ve also extended conversionmethod to support the whole matrix > (including multi-step conversions, no-op conversions and > BooleanTypeconversions), see CodeBuilder.java#L548 > > > Regarding the allocateLocalI would slightly prefer to keep it, however > allocateSlotor allocateLocalSlotor reserveLocalSlotare also fine. > > Prefix newwould be confusing. > > Thanks, > > Adam > -------------- next part -------------- An HTML attachment was scrubbed... URL: From adam.sotona at oracle.com Wed Jan 10 12:42:50 2024 From: adam.sotona at oracle.com (Adam Sotona) Date: Wed, 10 Jan 2024 12:42:50 +0000 Subject: Revisit j.l.classfile.CodeBuilder API surface In-Reply-To: References: Message-ID: We can probably attach the no-arg instructions to the Opcode enum, so the rest of the API will stay unchanged. BTW: I just barely remember there was some reason to have each instruction as unique instance, however I don?t see it now. From: Brian Goetz Date: Tuesday, 9 January 2024 at 17:44 To: Adam Sotona , liangchenblue at gmail.com , classfile-api-dev Subject: Re: Revisit j.l.classfile.CodeBuilder API surface These look good to me. (Perhaps some of the instruction-specific methods could use the singleton instances of the single-bytecode instructions rather than the factory?) On 1/9/2024 11:35 AM, Adam Sotona wrote: Sorry, wrong PR https://github.com/openjdk/jdk/pull/17282 in the link below. From: classfile-api-dev on behalf of Adam Sotona Date: Tuesday, 9 January 2024 at 17:32 To: Brian Goetz , liangchenblue at gmail.com , classfile-api-dev Subject: Re: Revisit j.l.classfile.CodeBuilder API surface Hi, I?ve updated the PR draft with removal of operator method as obsolete and newPrimitiveArray, newReferenceArray and newMultidimensionalArray methods as duplicate. I?ve also extended conversion method to support the whole matrix (including multi-step conversions, no-op conversions and BooleanType conversions), see CodeBuilder.java#L548 Regarding the allocateLocal I would slightly prefer to keep it, however allocateSlot or allocateLocalSlot or reserveLocalSlot are also fine. Prefix new would be confusing. Thanks, Adam -------------- next part -------------- An HTML attachment was scrubbed... URL: From adam.sotona at oracle.com Wed Jan 10 14:41:56 2024 From: adam.sotona at oracle.com (Adam Sotona) Date: Wed, 10 Jan 2024 14:41:56 +0000 Subject: Revisit j.l.classfile.CodeBuilder API surface In-Reply-To: References: Message-ID: I did a simple attempt to singleton (internally) no-arg instructions under Opcode (here: https://github.com/openjdk/jdk/commit/da9179f735f66718361a7e914ef61defc42959df) However, it does not have any effect on performance. >From the API perspective ? having some of the instructions exposed as singletons and some created through factories would be confusing. In that case we should probably convert all .of() factories into sigletons, including ClassFile.of() ? and that is huge refactoring with no benefits. From: classfile-api-dev on behalf of Adam Sotona Date: Wednesday, 10 January 2024 at 13:42 To: Brian Goetz , liangchenblue at gmail.com , classfile-api-dev Subject: Re: Revisit j.l.classfile.CodeBuilder API surface We can probably attach the no-arg instructions to the Opcode enum, so the rest of the API will stay unchanged. BTW: I just barely remember there was some reason to have each instruction as unique instance, however I don?t see it now. From: Brian Goetz Date: Tuesday, 9 January 2024 at 17:44 To: Adam Sotona , liangchenblue at gmail.com , classfile-api-dev Subject: Re: Revisit j.l.classfile.CodeBuilder API surface These look good to me. (Perhaps some of the instruction-specific methods could use the singleton instances of the single-bytecode instructions rather than the factory?) On 1/9/2024 11:35 AM, Adam Sotona wrote: Sorry, wrong PR https://github.com/openjdk/jdk/pull/17282 in the link below. From: classfile-api-dev on behalf of Adam Sotona Date: Tuesday, 9 January 2024 at 17:32 To: Brian Goetz , liangchenblue at gmail.com , classfile-api-dev Subject: Re: Revisit j.l.classfile.CodeBuilder API surface Hi, I?ve updated the PR draft with removal of operator method as obsolete and newPrimitiveArray, newReferenceArray and newMultidimensionalArray methods as duplicate. I?ve also extended conversion method to support the whole matrix (including multi-step conversions, no-op conversions and BooleanType conversions), see CodeBuilder.java#L548 Regarding the allocateLocal I would slightly prefer to keep it, however allocateSlot or allocateLocalSlot or reserveLocalSlot are also fine. Prefix new would be confusing. Thanks, Adam -------------- next part -------------- An HTML attachment was scrubbed... URL: From adam.sotona at oracle.com Mon Jan 15 14:30:44 2024 From: adam.sotona at oracle.com (Adam Sotona) Date: Mon, 15 Jan 2024 14:30:44 +0000 Subject: ClassFile API Labels limitations Message-ID: Hi, ClassFile API Labels are always strictly linked with the source CodeModel or with the target CodeBuilder. Only Labels coming from an existing CodeModel can be applied multiple times in various target CodeBuilders. Labels created by one CodeBuilder cannot be (re-)used in another CodeBuilder. All these restrictions serve to the purpose of maximum performance. However, this strict approach prevents to address not-yet existing code blocks or instructions outside of (or better say before the existence of) the CodeBuilder. As an example, let?s say we plan to build a complex code structure from a custom abstract model. Each of the addressable instruction or code block will be addressed by a Label at the build time, however that Label could not exist outside of the CodeBuilder. Current workaround is to provide an extra mapping layer (a ?CodeBuilderContext?) to translate from custom addressable elements to Labels (a unique new mapping for each CodeBuilder). I would like to simplify this situation and here are some alternatives: 1. Introduce new Proto/Global/Unbound/UnresolvedLabel (unsealed) interface. And add CodeBuilder::resolve(ProtoLabel) method, which will identity-map it to a local Label during the build process. or 2. Allow to statically create global Labels and make them reusable, it means to add static Label::newLabel() and fix current implementation. I expect the static factory Label::newLabel() may attract users more than CodeBuilder::newLabel(), so the implementation should keep performance of the existing use cases. Any comment and suggestions are welcome. Thanks, Adam -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Mon Jan 15 15:23:32 2024 From: brian.goetz at oracle.com (Brian Goetz) Date: Mon, 15 Jan 2024 15:23:32 +0000 Subject: ClassFile API Labels limitations In-Reply-To: References: Message-ID: <715C5653-F59D-4DAA-BD0E-CCAF3EF8F704@oracle.com> Be careful. When I revamped label handling (admittedly, early in the process), performance was very sensitive to the approach. I tried half a dozen approaches. Having multiple subtypes of labels definitely had a cost. The main case we probably want to avoid regressing on is the mostly-no-op-adapataion case. On Jan 15, 2024, at 9:30 AM, Adam Sotona > wrote: Hi, ClassFile API Labels are always strictly linked with the source CodeModel or with the target CodeBuilder. Only Labels coming from an existing CodeModel can be applied multiple times in various target CodeBuilders. Labels created by one CodeBuilder cannot be (re-)used in another CodeBuilder. All these restrictions serve to the purpose of maximum performance. However, this strict approach prevents to address not-yet existing code blocks or instructions outside of (or better say before the existence of) the CodeBuilder. As an example, let?s say we plan to build a complex code structure from a custom abstract model. Each of the addressable instruction or code block will be addressed by a Label at the build time, however that Label could not exist outside of the CodeBuilder. Current workaround is to provide an extra mapping layer (a ?CodeBuilderContext?) to translate from custom addressable elements to Labels (a unique new mapping for each CodeBuilder). I would like to simplify this situation and here are some alternatives: 1. Introduce new Proto/Global/Unbound/UnresolvedLabel (unsealed) interface. And add CodeBuilder::resolve(ProtoLabel) method, which will identity-map it to a local Label during the build process. or 2. Allow to statically create global Labels and make them reusable, it means to add static Label::newLabel() and fix current implementation. I expect the static factory Label::newLabel() may attract users more than CodeBuilder::newLabel(), so the implementation should keep performance of the existing use cases. Any comment and suggestions are welcome. Thanks, Adam -------------- next part -------------- An HTML attachment was scrubbed... URL: From david32768 at btinternet.com Sat Jan 27 17:11:59 2024 From: david32768 at btinternet.com (david32768@btinternet.com david32768@btinternet.com) Date: Sat, 27 Jan 2024 17:11:59 +0000 (GMT) Subject: Switch Message-ID: <12dbb0e6.275b.18d4be81e7e.Webtop.104@btinternet.com> Hi. # ClassPrinter ClassPrinter prints lookupswitch like tableswitch thus losing information (the values switched on) whereas the reverse would not. # Duplicate and ambiguous switch cases. Lookupswitch throws an exception but where depends on the ClassFile options specified but tableswitch silently ignores it by dropping a switch case. # SequencedSet ClassFile improves on ASM by using a List parameter rather than two arrays but would not a SequencedSet be better as the switch cases would be prechecked. # Switch Normally the user would just prefer the shortest code switch, so could there be a switch(Label default, SequencedSet cases) method. # Dead Code I was surprised that the default was to change deadcode to nop, throw. Also there is no dead code option to faill with an exception. Cheers David. -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Sat Jan 27 17:17:06 2024 From: brian.goetz at oracle.com (Brian Goetz) Date: Sat, 27 Jan 2024 12:17:06 -0500 Subject: Switch In-Reply-To: <12dbb0e6.275b.18d4be81e7e.Webtop.104@btinternet.com> References: <12dbb0e6.275b.18d4be81e7e.Webtop.104@btinternet.com> Message-ID: <3cc051cf-526c-4957-adda-5f33dc083ebf@oracle.com> Thanks for these reports.? Some of them seem obvious how to reproduce, but some could use some more information. > # Duplicate and ambiguous switch cases. > > > Lookupswitch throws an exception but where depends on the ClassFile > options specified but tableswitch silently ignores it by dropping a > switch case. > Can you provide an example of the code that causes the problem? > # Dead Code > > I was surprised that the default was to change deadcode to nop, throw. > Also there is no dead code option to faill with an exception. > Can you provide more detail of what you expected, in what case, and what was different? -------------- next part -------------- An HTML attachment was scrubbed... URL: From david32768 at btinternet.com Mon Jan 29 06:46:06 2024 From: david32768 at btinternet.com (david32768@btinternet.com david32768@btinternet.com) Date: Mon, 29 Jan 2024 06:46:06 +0000 (GMT) Subject: Duplicate and ambiguous switch cases Message-ID: <2958b568.380c.18d53f7d280.Webtop.107@btinternet.com> I apologise for the misleading comment about the error message. If the bad lookup is picked up by StackMapGenerate (V65) it also prints the code. If the bad lookup is picked up by StackCounter (V50) it does not. ``` import java.io.IOException; import java.lang.constant.ClassDesc; import java.lang.constant.MethodTypeDesc; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; import java.util.ArrayList; import java.lang.classfile.*; import java.lang.classfile.instruction.*; public class CBBuildDup { private static void build(CodeBuilder cob) { Label L1 = cob.newLabel(); Label L2 = cob.newLabel(); SwitchCase sc1 = SwitchCase.of(0,L2); // 0 -> L2 SwitchCase sc2 = SwitchCase.of(0,L2); // 0 -> L2 Duplicate // SwitchCase sc2 = SwitchCase.of(0,L1); // 0 -> L1 Ambiguous List cases = new ArrayList<>(); cases.add(sc1); cases.add(sc2); cob.iload(0) .lookupswitch(L1, cases) // .tableswitch(L1, cases) .labelBinding(L2) .iconst_1() .ireturn() .labelBinding(L1) .iconst_0() .ireturn(); } public static void main(String[] args) throws IOException { byte[] bytes = ClassFile.of() .build(ClassDesc.of("CBSwitchDup"), clb -> clb.withFlags(ClassFile.ACC_PUBLIC| ClassFile.ACC_SUPER) // .withVersion(50,0) // bad lookup (StackCounter) .withVersion(65,0) // bad lookup + code dump (StackMapGenerator) .withMethodBody("table", MethodTypeDesc.ofDescriptor("(I)I"), ClassFile.ACC_PUBLIC | ClassFile.ACC_STATIC, CBBuildDup::build)); for (VerifyError err:ClassFile.of().verify(bytes)) { System.err.println(err); } Path pathc = Paths.get("CBSwitchDup.class"); Files.write(pathc,bytes); } } ``` -------------- next part -------------- An HTML attachment was scrubbed... URL: From david32768 at btinternet.com Mon Jan 29 13:24:28 2024 From: david32768 at btinternet.com (david32768@btinternet.com david32768@btinternet.com) Date: Mon, 29 Jan 2024 13:24:28 +0000 (GMT) Subject: ClassFile.Option Documentation Message-ID: <547df36c.3f67.18d556487bd.Webtop.107@btinternet.com> In the ClassFile package description under OPTIONS there is no mention of DEADCODE. For a ClassFile.Option enum the default is only mentioned in the enum description but not in the enum constant detailed description. Should all the default options be listed in the detailed description of the ClassFile.of methods as these methods presumably decide what the defaults are. -------------- next part -------------- An HTML attachment was scrubbed... URL: From liangchenblue at gmail.com Tue Jan 30 02:50:13 2024 From: liangchenblue at gmail.com (-) Date: Mon, 29 Jan 2024 20:50:13 -0600 Subject: ClassFile.Option Documentation In-Reply-To: <547df36c.3f67.18d556487bd.Webtop.107@btinternet.com> References: <547df36c.3f67.18d556487bd.Webtop.107@btinternet.com> Message-ID: Hello, I think that we can consider removing the Options section from the package summary. Back in an earlier iteration, as seen in JDK 21, [1] the options were listed in a few methods, and there was no way to see the exhaustive list of options. However, with the refactor of ClassFile Options into a sealed interface hierarchy, all these options are now available in the permits list and the sealed graph (which, due to poor handling of nested classes, is not available ATM), so there's not that much value keeping a separate list in the package summary that may be out-of-date. For marking options as the default in the enum constants, I agree that is a good idea. A simple paragraph like

This is the default option. may work. In addition, I think we can change the {@code } references to the default constants to {@link } to improve accessibility. Chen Liang [1]: https://git.openjdk.org/jdk21/blob/890adb6410dab4606a4f26a942aed02fb2f55387/src/java.base/share/classes/jdk/internal/classfile/Classfile.java#L67 [2]: https://download.java.net/java/early_access/jdk22/docs/api/java.base/java/lang/classfile/ClassFile.Option.html On Mon, Jan 29, 2024 at 8:21?AM david32768 at btinternet.com david32768 at btinternet.com wrote: > In the ClassFile package description under OPTIONS there is no mention of > DEADCODE. > > > For a ClassFile.Option enum the default is only mentioned in the enum > description > > but not in the enum constant detailed description. > > > Should all the default options be listed in the detailed description of > the ClassFile.of methods > > as these methods presumably decide what the defaults are. > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From adam.sotona at oracle.com Tue Jan 30 14:30:28 2024 From: adam.sotona at oracle.com (Adam Sotona) Date: Tue, 30 Jan 2024 14:30:28 +0000 Subject: ClassFile.Option Documentation In-Reply-To: <547df36c.3f67.18d556487bd.Webtop.107@btinternet.com> References: <547df36c.3f67.18d556487bd.Webtop.107@btinternet.com> Message-ID: Good catch, I think the missing documentation should be fixed. Could you, please, fill a new bug on JDK core-libs / java.lang.classfile subcomponent? Thank you. Adam From: classfile-api-dev on behalf of david32768 at btinternet.com david32768 at btinternet.com Date: Monday, 29 January 2024 at 14:24 To: classfile-api-dev at openjdk.org Subject: ClassFile.Option Documentation In the ClassFile package description under OPTIONS there is no mention of DEADCODE. For a ClassFile.Option enum the default is only mentioned in the enum description but not in the enum constant detailed description. Should all the default options be listed in the detailed description of the ClassFile.of methods as these methods presumably decide what the defaults are. -------------- next part -------------- An HTML attachment was scrubbed... URL: From brian.goetz at oracle.com Tue Jan 30 14:33:31 2024 From: brian.goetz at oracle.com (Brian Goetz) Date: Tue, 30 Jan 2024 09:33:31 -0500 Subject: ClassFile.Option Documentation In-Reply-To: References: <547df36c.3f67.18d556487bd.Webtop.107@btinternet.com> Message-ID: <76585c4d-07c7-45a3-814b-899002afcaf5@oracle.com> The role of the package summary is to tie together the big picture, helping the user discover key concepts and find "the end of the string to start pulling on." The package summary is where we should say "first you need a Classfile object, which will faciliating both reading and writing of classfiles, and how it does that can be configured with various options."? We can put the option detail with the options, but it should be linked from the package Javadoc to help people _discover_ that they need to know about options. On 1/29/2024 9:50 PM, - wrote: > Hello, > I think that we can consider removing the Options section from the > package summary. > > Back in an earlier iteration, as seen in JDK 21, [1] the options were > listed in a few methods, and there was no way to see the exhaustive > list of options. > However, with the refactor of ClassFile Options into a sealed > interface hierarchy, all these options are now available in the > permits list and the sealed graph (which, due to poor handling of > nested classes, is not available ATM), so there's not that much value > keeping a separate list in the package summary that may be out-of-date. > > For marking options as the default in the enum constants, I agree that > is a good idea. A simple paragraph like

This is the default option. > may work. > In addition, I think we can change the {@code } references to the > default constants to {@link } to improve accessibility. > > Chen Liang > > [1]: > https://git.openjdk.org/jdk21/blob/890adb6410dab4606a4f26a942aed02fb2f55387/src/java.base/share/classes/jdk/internal/classfile/Classfile.java#L67 > [2]: > https://download.java.net/java/early_access/jdk22/docs/api/java.base/java/lang/classfile/ClassFile.Option.html > > On Mon, Jan 29, 2024 at 8:21?AM david32768 at btinternet.com > david32768 at btinternet.com wrote: > > In the ClassFile package description under OPTIONS there is no > mention of DEADCODE. > > > For a ClassFile.Option enum the default is only mentioned in the > enum description > > but not in the enum constant detailed description. > > > Should all the default options be listed in the detailed > description of the ClassFile.of methods > > as these methods presumably decide what the defaults are. > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From adam.sotona at oracle.com Tue Jan 30 14:35:14 2024 From: adam.sotona at oracle.com (Adam Sotona) Date: Tue, 30 Jan 2024 14:35:14 +0000 Subject: JEP Draft: Class-File API (Second Preview) Message-ID: Hi, Here is a JEP draft of Class-File API (Second Preview): https://bugs.openjdk.org/browse/JDK-8324965 Any suggestions and comments are welcome. Thanks, Adam -------------- next part -------------- An HTML attachment was scrubbed... URL: From adam.sotona at oracle.com Tue Jan 30 16:10:13 2024 From: adam.sotona at oracle.com (Adam Sotona) Date: Tue, 30 Jan 2024 16:10:13 +0000 Subject: Duplicate and ambiguous switch cases In-Reply-To: <2958b568.380c.18d53f7d280.Webtop.107@btinternet.com> References: <2958b568.380c.18d53f7d280.Webtop.107@btinternet.com> Message-ID: Thank you for reporting it. This can be a nice enhancement of the StackCounter error reporting. Please let me know if you have troubles to create a new JDK Enhancement issue on core-libs / java.lang.classfile subcomponent. Thank you, Adam From: classfile-api-dev on behalf of david32768 at btinternet.com david32768 at btinternet.com Date: Monday, 29 January 2024 at 7:46 To: classfile-api-dev at openjdk.org Subject: Duplicate and ambiguous switch cases I apologise for the misleading comment about the error message. If the bad lookup is picked up by StackMapGenerate (V65) it also prints the code. If the bad lookup is picked up by StackCounter (V50) it does not. ``` import java.io.IOException; import java.lang.constant.ClassDesc; import java.lang.constant.MethodTypeDesc; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; import java.util.ArrayList; import java.lang.classfile.*; import java.lang.classfile.instruction.*; public class CBBuildDup { private static void build(CodeBuilder cob) { Label L1 = cob.newLabel(); Label L2 = cob.newLabel(); SwitchCase sc1 = SwitchCase.of(0,L2); // 0 -> L2 SwitchCase sc2 = SwitchCase.of(0,L2); // 0 -> L2 Duplicate // SwitchCase sc2 = SwitchCase.of(0,L1); // 0 -> L1 Ambiguous List cases = new ArrayList<>(); cases.add(sc1); cases.add(sc2); cob.iload(0) .lookupswitch(L1, cases) // .tableswitch(L1, cases) .labelBinding(L2) .iconst_1() .ireturn() .labelBinding(L1) .iconst_0() .ireturn(); } public static void main(String[] args) throws IOException { byte[] bytes = ClassFile.of() .build(ClassDesc.of("CBSwitchDup"), clb -> clb.withFlags(ClassFile.ACC_PUBLIC| ClassFile.ACC_SUPER) // .withVersion(50,0) // bad lookup (StackCounter) .withVersion(65,0) // bad lookup + code dump (StackMapGenerator) .withMethodBody("table", MethodTypeDesc.ofDescriptor("(I)I"), ClassFile.ACC_PUBLIC | ClassFile.ACC_STATIC, CBBuildDup::build)); for (VerifyError err:ClassFile.of().verify(bytes)) { System.err.println(err); } Path pathc = Paths.get("CBSwitchDup.class"); Files.write(pathc,bytes); } } ``` -------------- next part -------------- An HTML attachment was scrubbed... URL: From paul.sandoz at oracle.com Tue Jan 30 23:55:46 2024 From: paul.sandoz at oracle.com (Paul Sandoz) Date: Tue, 30 Jan 2024 23:55:46 +0000 Subject: JEP Draft: Class-File API (Second Preview) In-Reply-To: References: Message-ID: <23C8DC69-97C6-4A40-87FD-A0791CFA1879@oracle.com> AFAICT the only substantial change to the text is the addition of the history section? Class-File API was proposed as a preview feature by JEP 457 and delivered in JDK 22 . -> The Class-File API... I think it would be useful to be a little more descriptive on the changes > - CodeBuilder API surface consolidation I am guessing this is removing redundant method, or vestiges from early designs, from the builder and using a more consistent pattern for method names and signatures? - Small API adjustments to better match JVM Specification -> - Minor API updates for improved alignment with the JVM specification. e.g., ? Implementation-wise were there any performance improvements? Or improvements to the validation of class files? Paul. > On Jan 30, 2024, at 6:35 AM, Adam Sotona wrote: > > Hi, > Here is a JEP draft of Class-File API (Second Preview): > https://bugs.openjdk.org/browse/JDK-8324965 > Any suggestions and comments are welcome. > Thanks, > Adam