diff options
author | Eric Bruneton <ebruneton@free.fr> | 2022-09-11 09:09:10 +0200 |
---|---|---|
committer | Eric Bruneton <ebruneton@free.fr> | 2022-09-11 09:09:10 +0200 |
commit | edb880104a5f2b1a918b0da3ee668febe0ba45bb (patch) | |
tree | 5025016f05680f22f3f840cbafa0ac161d349d57 /asm/src | |
parent | dac1a9fd6526a2bf985f88c59b624b5e8dbae515 (diff) | |
download | ow2-asm-edb880104a5f2b1a918b0da3ee668febe0ba45bb.tar.gz |
Rewrite the code in a more concise way.
Diffstat (limited to 'asm/src')
3 files changed, 33 insertions, 98 deletions
diff --git a/asm/src/main/java/org/objectweb/asm/signature/SignatureWriter.java b/asm/src/main/java/org/objectweb/asm/signature/SignatureWriter.java index c834eef0..df5f61d0 100644 --- a/asm/src/main/java/org/objectweb/asm/signature/SignatureWriter.java +++ b/asm/src/main/java/org/objectweb/asm/signature/SignatureWriter.java @@ -27,8 +27,6 @@ // THE POSSIBILITY OF SUCH DAMAGE. package org.objectweb.asm.signature; -import java.util.ArrayList; -import java.util.List; import org.objectweb.asm.Opcodes; /** @@ -43,7 +41,7 @@ import org.objectweb.asm.Opcodes; public class SignatureWriter extends SignatureVisitor { /** The builder used to construct the visited signature. */ - private final StringBuilder stringBuilder = new StringBuilder(); + private final StringBuilder stringBuilder; /** Whether the visited signature contains formal type parameters. */ private boolean hasFormals; @@ -53,8 +51,9 @@ public class SignatureWriter extends SignatureVisitor { /** * The stack used to keep track of class types that have arguments. Each element of this stack is - * a boolean encoded in one bit. The top of the stack is the least significant bit. Pushing false - * {@code <<= 1}, pushing true {@code <<= 1; |= 1}, popping {@code >>>= 1}. + * a boolean encoded in one bit. The top of the stack is the least significant bit. The bottom of + * the stack is a sentinel element always equal to 1 (used to detect when the stack is full). + * Pushing false = {@code <<= 1}, pushing true = {@code '( <<= 1) | 1}, popping = {@code >>>= 1}. * * <p>Class type arguments must be surrounded with '<' and '>' and, because * @@ -65,20 +64,19 @@ public class SignatureWriter extends SignatureVisitor { * </ol> * * <p>we need a stack to properly balance these angle brackets. A new element is pushed on this - * stack for each new visited type, and popped when the visit of this type ends (either is + * stack for each new visited type, and popped when the visit of this type ends (either in * visitEnd, or because visitInnerClassType is called). */ - private int argumentStack; - - /** The sum of the depths of {@link #argumentStack} and {@link #deepArgStack}. */ - private long argumentStackDepth; - - /** Used when {@link #argumentStack} can no longer fit into a single 32-bit integer. */ - private List<Integer> deepArgStack; + private int argumentStack = 1; /** Constructs a new {@link SignatureWriter}. */ public SignatureWriter() { + this(new StringBuilder()); + } + + private SignatureWriter(final StringBuilder stringBuilder) { super(/* latest api =*/ Opcodes.ASM9); + this.stringBuilder = stringBuilder; } // ----------------------------------------------------------------------------------------------- @@ -167,7 +165,7 @@ public class SignatureWriter extends SignatureVisitor { stringBuilder.append(name); // Pushes 'false' on the stack, meaning that this type does not have type arguments (as far as // we can tell at this point). - pushArgStack(false); + argumentStack <<= 1; } @Override @@ -177,7 +175,7 @@ public class SignatureWriter extends SignatureVisitor { stringBuilder.append(name); // Pushes 'false' on the stack, meaning that this type does not have type arguments (as far as // we can tell at this point). - pushArgStack(false); + argumentStack <<= 1; } @Override @@ -185,7 +183,7 @@ public class SignatureWriter extends SignatureVisitor { // If the top of the stack is 'false', this means we are visiting the first type argument of the // currently visited type. We therefore need to append a '<', and to replace the top stack // element with 'true' (meaning that the current type does have type arguments). - if (argumentStackDepth > 0 && !peekArgStack()) { + if ((argumentStack & 1) == 0) { argumentStack |= 1; stringBuilder.append('<'); } @@ -197,14 +195,15 @@ public class SignatureWriter extends SignatureVisitor { // If the top of the stack is 'false', this means we are visiting the first type argument of the // currently visited type. We therefore need to append a '<', and to replace the top stack // element with 'true' (meaning that the current type does have type arguments). - if (argumentStackDepth > 0 && !peekArgStack()) { + if ((argumentStack & 1) == 0) { argumentStack |= 1; stringBuilder.append('<'); } if (wildcard != '=') { stringBuilder.append(wildcard); } - return this; + // If the stack is full, start a nested one by returning a new SignatureWriter. + return (argumentStack & (1 << 31)) == 0 ? this : new SignatureWriter(stringBuilder); } @Override @@ -240,40 +239,9 @@ public class SignatureWriter extends SignatureVisitor { // If the top of the stack is 'true', this means that some type arguments have been visited for // the type whose visit is now ending. We therefore need to append a '>', and to pop one element // from the stack. - if (argumentStackDepth > 0 && popArgStack()) { + if ((argumentStack & 1) == 1) { stringBuilder.append('>'); } - } - - private boolean peekArgStack() { - assert argumentStackDepth > 0 : this; - return (argumentStack & 1) == 1; - } - - private void pushArgStack(final boolean state) { - if (argumentStackDepth > 0 && (argumentStackDepth % 32) == 0) { - if (deepArgStack == null) { - deepArgStack = new ArrayList<>(5); - } - deepArgStack.add(argumentStack); - argumentStack = 0; - } else { - argumentStack <<= 1; - } - argumentStackDepth++; - if (state) { - argumentStack |= 1; - } - } - - private boolean popArgStack() { - assert argumentStackDepth > 0 : this; - boolean result = (argumentStack & 1) == 1; argumentStack >>>= 1; - argumentStackDepth--; - if (argumentStackDepth > 0 && (argumentStackDepth % 32) == 0) { - argumentStack = deepArgStack.remove(deepArgStack.size() - 1); - } - return result; } } diff --git a/asm/src/test/java/org/objectweb/asm/signature/SignatureWriterTest.java b/asm/src/test/java/org/objectweb/asm/signature/SignatureWriterTest.java index 3717f4bd..be1ba012 100644 --- a/asm/src/test/java/org/objectweb/asm/signature/SignatureWriterTest.java +++ b/asm/src/test/java/org/objectweb/asm/signature/SignatureWriterTest.java @@ -29,7 +29,6 @@ package org.objectweb.asm.signature; import static org.junit.jupiter.api.Assertions.assertEquals; -import java.util.stream.IntStream; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import org.objectweb.asm.test.AsmTest; @@ -41,10 +40,6 @@ import org.objectweb.asm.test.AsmTest; */ class SignatureWriterTest extends AsmTest { - private static final String TEST_CLOSE = "TestClose"; - private static final String TEST_GENERIC = "TestGeneric"; - private static final String TEST_OPEN = "TestOpen"; - @ParameterizedTest @MethodSource({ "org.objectweb.asm.signature.SignaturesProviders#classSignatures", @@ -67,47 +62,4 @@ class SignatureWriterTest extends AsmTest { assertEquals(signature, signatureWriter.toString()); } - - static IntStream deepSignatures() { - return IntStream.range(0, 48); - } - - @ParameterizedTest - @MethodSource("deepSignatures") - void testWrite_deepSignature(final int depth) { - SignatureWriter signatureWriter = new SignatureWriter(); - String expected = writeDeepSignature(signatureWriter, depth); - assertEquals(expected, signatureWriter.toString(), "depth=" + depth); - } - - private String writeDeepSignature(final SignatureVisitor signatureVisitor, final int maxDepth) { - StringBuilder expected = new StringBuilder(); - writeDeepSignatureInner(signatureVisitor, expected, 0, maxDepth); - return expected.toString(); - } - - private void writeDeepSignatureInner( - final SignatureVisitor signatureVisitor, - final StringBuilder expected, - final int currentDepth, - final int maxDepth) { - signatureVisitor.visitClassType(TEST_GENERIC); - expected.append('L' + TEST_GENERIC); - if (currentDepth < maxDepth) { - expected.append("<L" + TEST_OPEN + ';'); - SignatureVisitor v = signatureVisitor.visitTypeArgument('='); - v.visitClassType(TEST_OPEN); - v.visitEnd(); - - writeDeepSignatureInner( - signatureVisitor.visitTypeArgument('='), expected, currentDepth + 1, maxDepth); - - v = signatureVisitor.visitTypeArgument('='); - v.visitClassType(TEST_CLOSE); - v.visitEnd(); - expected.append('L' + TEST_CLOSE + ";>"); - } - signatureVisitor.visitEnd(); - expected.append(';'); - } } diff --git a/asm/src/test/java/org/objectweb/asm/signature/SignaturesProviders.java b/asm/src/test/java/org/objectweb/asm/signature/SignaturesProviders.java index ce6cf22a..a04d5801 100644 --- a/asm/src/test/java/org/objectweb/asm/signature/SignaturesProviders.java +++ b/asm/src/test/java/org/objectweb/asm/signature/SignaturesProviders.java @@ -32,6 +32,9 @@ public final class SignaturesProviders { assertFalse(CLASS_SIGNATURES.isEmpty()); assertFalse(FIELD_SIGNATURES.isEmpty()); assertFalse(METHOD_SIGNATURES.isEmpty()); + for (int depth = 0; depth < 48; ++depth) { + METHOD_SIGNATURES.add(buildDeepSignature(new StringBuilder(), depth).toString()); + } } private SignaturesProviders() {} @@ -82,6 +85,18 @@ public final class SignaturesProviders { 0); } + private static StringBuilder buildDeepSignature(final StringBuilder signature, final int depth) { + signature.append("LGeneric"); + if (depth == 0) { + signature.append(';'); + } else { + signature.append("<LOpen;"); + buildDeepSignature(signature, depth - 1); + signature.append("LClose;>;"); + } + return signature; + } + static Stream<String> classSignatures() { return CLASS_SIGNATURES.stream(); } |