From 82eb7c17e64ff04af10b25a3ceeadfe333ce04fd Mon Sep 17 00:00:00 2001 From: Alexey Tsvetkov Date: Fri, 7 Dec 2018 19:21:01 +0300 Subject: [PATCH] Convert TransformationMethodVisitor: step 2 --- .../codegen/TransformationMethodVisitor.kt | 125 ++++++++---------- 1 file changed, 55 insertions(+), 70 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/TransformationMethodVisitor.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/TransformationMethodVisitor.kt index e05307aeac0..4b0a828b98f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/TransformationMethodVisitor.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/TransformationMethodVisitor.kt @@ -14,111 +14,96 @@ * limitations under the License. */ -package org.jetbrains.kotlin.codegen; +package org.jetbrains.kotlin.codegen -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.org.objectweb.asm.MethodVisitor; -import org.jetbrains.org.objectweb.asm.Opcodes; -import org.jetbrains.org.objectweb.asm.tree.LocalVariableNode; -import org.jetbrains.org.objectweb.asm.tree.MethodNode; -import org.jetbrains.org.objectweb.asm.util.Textifier; -import org.jetbrains.org.objectweb.asm.util.TraceMethodVisitor; +import org.jetbrains.org.objectweb.asm.MethodVisitor +import org.jetbrains.org.objectweb.asm.Opcodes +import org.jetbrains.org.objectweb.asm.tree.MethodNode +import org.jetbrains.org.objectweb.asm.util.Textifier +import org.jetbrains.org.objectweb.asm.util.TraceMethodVisitor -import java.util.ArrayList; -import java.util.List; +import java.util.ArrayList -import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.getNodeText; -import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.wrapWithMaxLocalCalc; +import org.jetbrains.kotlin.codegen.inline.nodeText +import org.jetbrains.kotlin.codegen.inline.wrapWithMaxLocalCalc -public abstract class TransformationMethodVisitor extends MethodVisitor { +abstract class TransformationMethodVisitor( + private val delegate: MethodVisitor, + access: Int, + name: String, + desc: String, + signature: String?, + exceptions: Array? +) : MethodVisitor(Opcodes.ASM5) { - private final MethodNode methodNode; - private final MethodVisitor delegate; - - public TransformationMethodVisitor( - @NotNull MethodVisitor delegate, - int access, - @NotNull String name, - @NotNull String desc, - @Nullable String signature, - @Nullable String[] exceptions - ) { - super(Opcodes.ASM5); - this.delegate = delegate; - this.methodNode = new MethodNode(access, name, desc, signature, exceptions); - this.methodNode.localVariables = new ArrayList<>(5); - this.mv = wrapWithMaxLocalCalc(methodNode); + private val methodNode = MethodNode(access, name, desc, signature, exceptions).apply { + localVariables = ArrayList(5) } - @Override - public void visitEnd() { - // force mv to calculate maxStack/maxLocals in case it didn't yet done - if (methodNode.maxLocals <= 0 || methodNode.maxStack <= 0) { - mv.visitMaxs(-1, -1); + val traceMethodVisitorIfPossible: TraceMethodVisitor? + get() { + val traceMethodVisitor = TraceMethodVisitor(Textifier()) + try { + methodNode.accept(traceMethodVisitor) + } catch (e: Throwable) { + return null + } + + return traceMethodVisitor } - super.visitEnd(); + init { + mv = wrapWithMaxLocalCalc(methodNode) + } + + override fun visitEnd() { + // force mv to calculate maxStack/maxLocals in case it didn't yet done + if (methodNode.maxLocals <= 0 || methodNode.maxStack <= 0) { + mv.visitMaxs(-1, -1) + } + + super.visitEnd() try { if (shouldBeTransformed(methodNode)) { - performTransformations(methodNode); + performTransformations(methodNode) } - methodNode.accept(new EndIgnoringMethodVisitorDecorator(Opcodes.ASM5, delegate)); + methodNode.accept(EndIgnoringMethodVisitorDecorator(Opcodes.ASM5, delegate)) // In case of empty instructions list MethodNode.accept doesn't call visitLocalVariables of delegate // So we just do it here if (methodNode.instructions.size() == 0 // MethodNode does not create a list of variables for abstract methods, so we would get NPE in accept() instead - && (!(delegate instanceof MethodNode) || methodNode.localVariables != null) + && (delegate !is MethodNode || methodNode.localVariables != null) ) { - List localVariables = methodNode.localVariables; + val localVariables = methodNode.localVariables // visits local variables - int n = localVariables == null ? 0 : localVariables.size(); - for (int i = 0; i < n; ++i) { - localVariables.get(i).accept(delegate); + val n = localVariables?.size ?: 0 + for (i in 0 until n) { + localVariables!![i].accept(delegate) } } - delegate.visitEnd(); - } - catch (Throwable t) { - throw new CompilationException("Couldn't transform method node:\n" + getNodeText(methodNode), t, null); + delegate.visitEnd() + } catch (t: Throwable) { + throw CompilationException("Couldn't transform method node:\n" + methodNode.nodeText, t, null) } } - protected abstract void performTransformations(@NotNull MethodNode methodNode); + protected abstract fun performTransformations(methodNode: MethodNode) /** * You can use it when you need to ignore visit end */ - private static class EndIgnoringMethodVisitorDecorator extends MethodVisitor { - public EndIgnoringMethodVisitorDecorator(int api, @NotNull MethodVisitor mv) { - super(api, mv); - } - - @Override - public void visitEnd() { + private class EndIgnoringMethodVisitorDecorator(api: Int, mv: MethodVisitor) : MethodVisitor(api, mv) { + override fun visitEnd() { } } - @Nullable - public TraceMethodVisitor getTraceMethodVisitorIfPossible() { - TraceMethodVisitor traceMethodVisitor = new TraceMethodVisitor(new Textifier()); - try { - methodNode.accept(traceMethodVisitor); - } - catch (Throwable e) { - return null; - } - - return traceMethodVisitor; - } - - private static boolean shouldBeTransformed(@NotNull MethodNode node) { - return node.instructions.size() > 0; + private fun shouldBeTransformed(node: MethodNode): Boolean { + return node.instructions.size() > 0 } }