From bf3e6247aab174914570ec0dbd1eee7e8a6f993b Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Thu, 19 May 2016 13:55:28 +0300 Subject: [PATCH] Minor. Extract TransformationMethodVisitor with abstract performTransformations(@NotNull MethodNode methodNode) --- .../kotlin/codegen/FunctionCodegen.java | 4 +- .../codegen/TransformationMethodVisitor.java | 114 ++++++++++++++++++ .../OptimizationMethodVisitor.java | 87 ++----------- 3 files changed, 125 insertions(+), 80 deletions(-) create mode 100644 compiler/backend/src/org/jetbrains/kotlin/codegen/TransformationMethodVisitor.java diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java index 01780577de6..01262e389fd 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java @@ -541,8 +541,8 @@ public class FunctionCodegen { private static String renderByteCodeIfAvailable(MethodVisitor mv) { String bytecode = null; - if (mv instanceof OptimizationMethodVisitor) { - mv = ((OptimizationMethodVisitor) mv).getTraceMethodVisitorIfPossible(); + if (mv instanceof TransformationMethodVisitor) { + mv = ((TransformationMethodVisitor) mv).getTraceMethodVisitorIfPossible(); } if (mv instanceof TraceMethodVisitor) { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/TransformationMethodVisitor.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/TransformationMethodVisitor.java new file mode 100644 index 00000000000..3c22ec9dd8d --- /dev/null +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/TransformationMethodVisitor.java @@ -0,0 +1,114 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.codegen; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil; +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 java.util.ArrayList; +import java.util.List; + +public abstract class TransformationMethodVisitor extends MethodVisitor { + + 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 = InlineCodegenUtil.wrapWithMaxLocalCalc(methodNode); + } + + @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); + } + + super.visitEnd(); + + if (shouldBeTransformed(methodNode)) { + performTransformations(methodNode); + } + + methodNode.accept(new 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) { + List 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); + } + } + + delegate.visitEnd(); + } + + protected abstract void performTransformations(@NotNull 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() { + + } + } + + @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; + } +} diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/OptimizationMethodVisitor.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/OptimizationMethodVisitor.java index 3f218fed8d3..4e8c1e9c5e1 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/OptimizationMethodVisitor.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/OptimizationMethodVisitor.java @@ -18,23 +18,16 @@ package org.jetbrains.kotlin.codegen.optimization; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil; +import org.jetbrains.kotlin.codegen.TransformationMethodVisitor; import org.jetbrains.kotlin.codegen.optimization.boxing.RedundantBoxingMethodTransformer; import org.jetbrains.kotlin.codegen.optimization.boxing.RedundantCoercionToUnitTransformer; import org.jetbrains.kotlin.codegen.optimization.boxing.RedundantNullCheckMethodTransformer; import org.jetbrains.kotlin.codegen.optimization.common.UtilKt; import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer; 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 java.util.ArrayList; -import java.util.List; - -public class OptimizationMethodVisitor extends MethodVisitor { +public class OptimizationMethodVisitor extends TransformationMethodVisitor { private static final int MEMORY_LIMIT_BY_METHOD_MB = 50; private static final MethodTransformer MANDATORY_METHOD_TRANSFORMER = new MandatoryMethodTransformer(); @@ -47,8 +40,6 @@ public class OptimizationMethodVisitor extends MethodVisitor { new RedundantCoercionToUnitTransformer() }; - private final MethodNode methodNode; - private final MethodVisitor delegate; private final boolean disableOptimization; public OptimizationMethodVisitor( @@ -60,79 +51,19 @@ public class OptimizationMethodVisitor extends MethodVisitor { @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 = InlineCodegenUtil.wrapWithMaxLocalCalc(methodNode); + super(delegate, access, name, desc, signature, exceptions); this.disableOptimization = disableOptimization; } @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); - } - - super.visitEnd(); - - if (shouldBeTransformed(methodNode)) { - MANDATORY_METHOD_TRANSFORMER.transform("fake", methodNode); - if (canBeOptimized(methodNode) && !disableOptimization) { - for (MethodTransformer transformer : OPTIMIZATION_TRANSFORMERS) { - transformer.transform("fake", methodNode); - } - } - UtilKt.prepareForEmitting(methodNode); - } - - methodNode.accept(new 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) { - List 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); + protected void performTransformations(@NotNull MethodNode methodNode) { + MANDATORY_METHOD_TRANSFORMER.transform("fake", methodNode); + if (canBeOptimized(methodNode) && !disableOptimization) { + for (MethodTransformer transformer : OPTIMIZATION_TRANSFORMERS) { + transformer.transform("fake", methodNode); } } - - delegate.visitEnd(); - } - - /** - * 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() { - - } - } - - @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; + UtilKt.prepareForEmitting(methodNode); } private static boolean canBeOptimized(@NotNull MethodNode node) {