From 1ecca9f40b7dbbdf97905052f23e25699a3be8f8 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Wed, 9 Jul 2014 14:31:13 +0400 Subject: [PATCH] initial --- .../OptimizationClassBuilder.java | 54 ++++++ .../OptimizationClassBuilderFactory.java | 53 ++++++ .../OptimizationMethodVisitor.java | 62 +++++++ .../optimization/OptimizationUtils.java | 23 +++ .../optimization/boxing/BoxedBasicValue.java | 72 ++++++++ .../boxing/RedundantBoxingInterpreter.java | 162 ++++++++++++++++++ .../RedundantBoxingMethodTransformer.java | 52 ++++++ .../common/OptimizationBasicInterpreter.java | 84 +++++++++ .../transformer/MethodTransformer.java | 51 ++++++ 9 files changed, 613 insertions(+) create mode 100644 compiler/backend/src/org/jetbrains/jet/codegen/optimization/OptimizationClassBuilder.java create mode 100644 compiler/backend/src/org/jetbrains/jet/codegen/optimization/OptimizationClassBuilderFactory.java create mode 100644 compiler/backend/src/org/jetbrains/jet/codegen/optimization/OptimizationMethodVisitor.java create mode 100644 compiler/backend/src/org/jetbrains/jet/codegen/optimization/OptimizationUtils.java create mode 100644 compiler/backend/src/org/jetbrains/jet/codegen/optimization/boxing/BoxedBasicValue.java create mode 100644 compiler/backend/src/org/jetbrains/jet/codegen/optimization/boxing/RedundantBoxingInterpreter.java create mode 100644 compiler/backend/src/org/jetbrains/jet/codegen/optimization/boxing/RedundantBoxingMethodTransformer.java create mode 100644 compiler/backend/src/org/jetbrains/jet/codegen/optimization/common/OptimizationBasicInterpreter.java create mode 100644 compiler/backend/src/org/jetbrains/jet/codegen/optimization/transformer/MethodTransformer.java diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/optimization/OptimizationClassBuilder.java b/compiler/backend/src/org/jetbrains/jet/codegen/optimization/OptimizationClassBuilder.java new file mode 100644 index 00000000000..878c25f839f --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/optimization/OptimizationClassBuilder.java @@ -0,0 +1,54 @@ +/* + * Copyright 2010-2014 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.jet.codegen.optimization; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.codegen.ClassBuilder; +import org.jetbrains.jet.codegen.DelegatingClassBuilder; +import org.jetbrains.jet.lang.resolve.java.diagnostics.JvmDeclarationOrigin; +import org.jetbrains.org.objectweb.asm.MethodVisitor; + +public class OptimizationClassBuilder extends DelegatingClassBuilder { + private final ClassBuilder delegate; + + public OptimizationClassBuilder(@NotNull ClassBuilder delegate) { + this.delegate = delegate; + } + + @NotNull + @Override + public ClassBuilder getDelegate() { + return delegate; + } + + @NotNull + @Override + public MethodVisitor newMethod( + @NotNull JvmDeclarationOrigin origin, + int access, + @NotNull String name, + @NotNull String desc, + @Nullable String signature, + @Nullable String[] exceptions + ) { + return new OptimizationMethodVisitor( + super.newMethod(origin, access, name, desc, signature, exceptions), + access, name, desc, signature, exceptions + ); + } +} diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/optimization/OptimizationClassBuilderFactory.java b/compiler/backend/src/org/jetbrains/jet/codegen/optimization/OptimizationClassBuilderFactory.java new file mode 100644 index 00000000000..d2d441525bb --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/optimization/OptimizationClassBuilderFactory.java @@ -0,0 +1,53 @@ +/* + * Copyright 2010-2014 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.jet.codegen.optimization; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.codegen.ClassBuilder; +import org.jetbrains.jet.codegen.ClassBuilderFactory; +import org.jetbrains.jet.codegen.ClassBuilderMode; +import org.jetbrains.jet.lang.resolve.java.diagnostics.JvmDeclarationOrigin; + +public class OptimizationClassBuilderFactory implements ClassBuilderFactory { + private final ClassBuilderFactory delegate; + + public OptimizationClassBuilderFactory(ClassBuilderFactory delegate) { + this.delegate = delegate; + } + + @NotNull + @Override + public ClassBuilderMode getClassBuilderMode() { + return delegate.getClassBuilderMode(); + } + + @NotNull + @Override + public ClassBuilder newClassBuilder(@NotNull JvmDeclarationOrigin origin) { + return new OptimizationClassBuilder(delegate.newClassBuilder(origin)); + } + + @Override + public String asText(ClassBuilder builder) { + return delegate.asText(((OptimizationClassBuilder) builder).getDelegate()); + } + + @Override + public byte[] asBytes(ClassBuilder builder) { + return delegate.asBytes(((OptimizationClassBuilder) builder).getDelegate()); + } +} diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/optimization/OptimizationMethodVisitor.java b/compiler/backend/src/org/jetbrains/jet/codegen/optimization/OptimizationMethodVisitor.java new file mode 100644 index 00000000000..5a8366dc834 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/optimization/OptimizationMethodVisitor.java @@ -0,0 +1,62 @@ +/* + * Copyright 2010-2014 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.jet.codegen.optimization; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.codegen.inline.InlineCodegenUtil; +import org.jetbrains.jet.codegen.optimization.boxing.RedundantBoxingMethodTransformer; +import org.jetbrains.jet.codegen.optimization.transformer.MethodTransformer; +import org.jetbrains.org.objectweb.asm.MethodVisitor; +import org.jetbrains.org.objectweb.asm.tree.LocalVariableNode; +import org.jetbrains.org.objectweb.asm.tree.MethodNode; + +import java.util.ArrayList; + +public class OptimizationMethodVisitor extends MethodVisitor { + private final MethodTransformer methodTransformer = new RedundantBoxingMethodTransformer(null); + private final MethodNode methodNode; + private final MethodVisitor delegate; + + public OptimizationMethodVisitor( + @NotNull MethodVisitor delegate, + int access, + @NotNull String name, + @NotNull String desc, + @Nullable String signature, + @Nullable String[] exceptions + ) { + super(OptimizationUtils.API); + 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() { + if (methodNode.maxLocals <= 0 || methodNode.maxStack <= 0) { + mv.visitMaxs(-1, -1); + } + + super.visitEnd(); + + methodTransformer.transform("fake", methodNode); + + methodNode.accept(delegate); + } +} diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/optimization/OptimizationUtils.java b/compiler/backend/src/org/jetbrains/jet/codegen/optimization/OptimizationUtils.java new file mode 100644 index 00000000000..134019fb01f --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/optimization/OptimizationUtils.java @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2014 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.jet.codegen.optimization; + +import org.jetbrains.org.objectweb.asm.Opcodes; + +public class OptimizationUtils { + public final static int API = Opcodes.ASM5; +} diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/optimization/boxing/BoxedBasicValue.java b/compiler/backend/src/org/jetbrains/jet/codegen/optimization/boxing/BoxedBasicValue.java new file mode 100644 index 00000000000..c8670d2d5e3 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/optimization/boxing/BoxedBasicValue.java @@ -0,0 +1,72 @@ +/* + * Copyright 2010-2014 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.jet.codegen.optimization.boxing; + +import org.jetbrains.org.objectweb.asm.Type; +import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode; +import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class BoxedBasicValue extends BasicValue { + private final Set associatedInsns = new HashSet(); + private final AbstractInsnNode boxingInsn; + private final Type boxedType; + private boolean wasUnboxed = false; + + public BoxedBasicValue(Type type, Type boxedType, AbstractInsnNode insnNode) { + super(type); + this.boxedType = boxedType; + associatedInsns.add(insnNode); + boxingInsn = insnNode; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + BoxedBasicValue that = (BoxedBasicValue) o; + + if (!getType().equals(that.getType())) return false; + + return (boxingInsn == ((BoxedBasicValue) o).boxingInsn); + } + + public List getAssociatedInsns() { + return new ArrayList(associatedInsns); + } + + public void addInsn(AbstractInsnNode insnNode) { + associatedInsns.add(insnNode); + } + + public Type getBoxedType() { + return boxedType; + } + + public boolean wasUnboxed() { + return wasUnboxed; + } + + public void setWasUnboxed(boolean wasUnboxed) { + this.wasUnboxed = wasUnboxed; + } +} diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/optimization/boxing/RedundantBoxingInterpreter.java b/compiler/backend/src/org/jetbrains/jet/codegen/optimization/boxing/RedundantBoxingInterpreter.java new file mode 100644 index 00000000000..cf60cb5f9bb --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/optimization/boxing/RedundantBoxingInterpreter.java @@ -0,0 +1,162 @@ +/* + * Copyright 2010-2014 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.jet.codegen.optimization.boxing; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.codegen.optimization.common.OptimizationBasicInterpreter; +import org.jetbrains.org.objectweb.asm.Opcodes; +import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode; +import org.jetbrains.org.objectweb.asm.tree.InsnList; +import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode; +import org.jetbrains.org.objectweb.asm.tree.analysis.AnalyzerException; +import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue; + +import java.util.*; + +class RedundantBoxingInterpreter extends OptimizationBasicInterpreter { + private final Map boxingPlaces = new HashMap(); + private final Set candidatesBoxedValues = new HashSet(); + private final InsnList insnList; + + RedundantBoxingInterpreter(InsnList insnList) { + this.insnList = insnList; + } + + private static boolean isClassBox(@NotNull String owner) { + + if (!owner.startsWith("java/lang/")) { + return false; + } + + String className = owner.substring("java/lang/".length()); + + return (className.equals("Integer") || + className.equals("Double") || + className.equals("Long") || + className.equals("Char") || + className.equals("Byte") || + className.equals("Boolean")) || + className.endsWith("Number"); + } + + private static boolean isUnboxingMethod(@NotNull String name) { + return name.endsWith("Value"); + } + + private static boolean isUnboxing(@NotNull AbstractInsnNode insn) { + if (insn.getOpcode() != Opcodes.INVOKEVIRTUAL) { + return false; + } + + MethodInsnNode methodInsn = (MethodInsnNode) insn; + + return isClassBox(methodInsn.owner) && isUnboxingMethod(methodInsn.name); + } + + private static boolean isBoxing(@NotNull AbstractInsnNode insn) { + if (insn.getOpcode() != Opcodes.INVOKESTATIC) { + return false; + } + + MethodInsnNode methodInsnNode = (MethodInsnNode) insn; + + return isClassBox(methodInsnNode.owner) && methodInsnNode.name.equals("valueOf"); + } + + @Override + @Nullable + public BasicValue naryOperation(@NotNull AbstractInsnNode insn, @NotNull List values) throws AnalyzerException { + BasicValue value = super.naryOperation(insn, values); + + if (isBoxing(insn)) { + int index = insnList.indexOf(insn); + if (!boxingPlaces.containsKey(index)) { + BoxedBasicValue boxedBasicValue = new BoxedBasicValue(value.getType(), values.get(0).getType(), insn); + candidatesBoxedValues.add(boxedBasicValue); + boxingPlaces.put(index, boxedBasicValue); + } + + return boxingPlaces.get(index); + } + + if (isUnboxing(insn) && + values.get(0) instanceof BoxedBasicValue && + value.getType().equals(((BoxedBasicValue) values.get(0)).getBoxedType())) { + BoxedBasicValue boxedBasicValue = (BoxedBasicValue) values.get(0); + boxedBasicValue.addInsn(insn); + boxedBasicValue.setWasUnboxed(true); + } + + return value; + } + + @Override + @Nullable + public BasicValue unaryOperation(@NotNull AbstractInsnNode insn, @NotNull BasicValue value) throws AnalyzerException { + if (insn.getOpcode() == Opcodes.CHECKCAST && value instanceof BoxedBasicValue) { + ((BoxedBasicValue) value).addInsn(insn); + return value; + } + + return super.unaryOperation(insn, value); + } + + @Override + @NotNull + public BasicValue copyOperation(@NotNull AbstractInsnNode insn, @NotNull BasicValue value) throws AnalyzerException { + if (value instanceof BoxedBasicValue) { + candidatesBoxedValues.remove(value); + return new BasicValue(value.getType()); + } + + return super.copyOperation(insn, value); + } + + @Override + @NotNull + public BasicValue merge(@NotNull BasicValue v, @NotNull BasicValue w) { + if (v instanceof BoxedBasicValue && w instanceof BoxedBasicValue && v == w) { + return v; + } + + if (v instanceof BoxedBasicValue) { + candidatesBoxedValues.remove(v); + v = new BasicValue(v.getType()); + } + + if (w instanceof BoxedBasicValue) { + candidatesBoxedValues.remove(w); + w = new BasicValue(w.getType()); + } + + return super.merge(v, w); + } + + @NotNull + public List getCandidatesBoxedValues() { + List result = new ArrayList(); + + for (BoxedBasicValue value : candidatesBoxedValues) { + if (value.wasUnboxed()) { + result.add(value); + } + } + + return result; + } +} diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/optimization/boxing/RedundantBoxingMethodTransformer.java b/compiler/backend/src/org/jetbrains/jet/codegen/optimization/boxing/RedundantBoxingMethodTransformer.java new file mode 100644 index 00000000000..1f18f6212d3 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/optimization/boxing/RedundantBoxingMethodTransformer.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2014 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.jet.codegen.optimization.boxing; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.codegen.optimization.transformer.MethodTransformer; +import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode; +import org.jetbrains.org.objectweb.asm.tree.MethodNode; +import org.jetbrains.org.objectweb.asm.tree.analysis.Analyzer; +import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue; + +import java.util.List; + +public class RedundantBoxingMethodTransformer extends MethodTransformer { + public RedundantBoxingMethodTransformer(MethodTransformer methodTransformer) { + super(methodTransformer); + } + + @Override + public void transform(@NotNull String owner, @NotNull MethodNode node) { + for (BoxedBasicValue value : analyze(owner, node)) { + for (AbstractInsnNode insnNode : value.getAssociatedInsns()) { + node.instructions.remove(insnNode); + } + } + + super.transform(owner, node); + } + + private static List analyze(@NotNull String owner, @NotNull MethodNode node) { + RedundantBoxingInterpreter interpreter = new RedundantBoxingInterpreter(node.instructions); + Analyzer analyzer = new Analyzer(interpreter); + + runAnalyzer(analyzer, owner, node); + + return interpreter.getCandidatesBoxedValues(); + } +} diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/optimization/common/OptimizationBasicInterpreter.java b/compiler/backend/src/org/jetbrains/jet/codegen/optimization/common/OptimizationBasicInterpreter.java new file mode 100644 index 00000000000..80fea224f59 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/optimization/common/OptimizationBasicInterpreter.java @@ -0,0 +1,84 @@ +/* + * Copyright 2010-2014 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.jet.codegen.optimization.common; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.org.objectweb.asm.Opcodes; +import org.jetbrains.org.objectweb.asm.Type; +import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode; +import org.jetbrains.org.objectweb.asm.tree.LdcInsnNode; +import org.jetbrains.org.objectweb.asm.tree.analysis.AnalyzerException; +import org.jetbrains.org.objectweb.asm.tree.analysis.BasicInterpreter; +import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue; + +public class OptimizationBasicInterpreter extends BasicInterpreter { + private static final BasicValue MIXED_VALUE = new BasicValue(Type.getObjectType("#")); + + @Override + @Nullable + public BasicValue newValue(@Nullable Type type) { + if (type == null) { + return super.newValue(null); + } + if (type.getSort() == Type.OBJECT) { + return new BasicValue(type); + } + + return super.newValue(type); + } + + @Override + public BasicValue newOperation(@NotNull AbstractInsnNode insn) throws AnalyzerException { + if (insn.getOpcode() == Opcodes.LDC) { + Object cst = ((LdcInsnNode) insn).cst; + + if (cst instanceof Long) { + return BasicValue.LONG_VALUE; + } + + if (cst instanceof Boolean || + cst instanceof Integer || + cst instanceof Short || + cst instanceof Byte || + cst instanceof Character) { + return BasicValue.INT_VALUE; + } + + if (cst instanceof Float) { + return BasicValue.FLOAT_VALUE; + } + + if (cst instanceof Double) { + return BasicValue.DOUBLE_VALUE; + } + } + + return super.newOperation(insn); + } + + @NotNull + @Override + public BasicValue merge( + @NotNull BasicValue v, @NotNull BasicValue w + ) { + if (!v.equals(w)) { + return MIXED_VALUE; + } + return v; + } +} diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/optimization/transformer/MethodTransformer.java b/compiler/backend/src/org/jetbrains/jet/codegen/optimization/transformer/MethodTransformer.java new file mode 100644 index 00000000000..d34a72f7d98 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/optimization/transformer/MethodTransformer.java @@ -0,0 +1,51 @@ +/* + * Copyright 2010-2014 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.jet.codegen.optimization.transformer; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.org.objectweb.asm.tree.MethodNode; +import org.jetbrains.org.objectweb.asm.tree.analysis.Analyzer; +import org.jetbrains.org.objectweb.asm.tree.analysis.AnalyzerException; +import org.jetbrains.org.objectweb.asm.tree.analysis.Frame; +import org.jetbrains.org.objectweb.asm.tree.analysis.Value; + +public abstract class MethodTransformer { + private final MethodTransformer methodTransformer; + + protected MethodTransformer(MethodTransformer methodTransformer) { + this.methodTransformer = methodTransformer; + } + + protected static Frame[] runAnalyzer( + @NotNull Analyzer analyzer, + @NotNull String owner, + @NotNull MethodNode node + ) { + try { + return analyzer.analyze(owner, node); + } + catch (AnalyzerException e) { + throw new RuntimeException(e); + } + } + + public void transform(@NotNull String owner, @NotNull MethodNode methodNode) { + if (methodTransformer != null) { + methodTransformer.transform(owner, methodNode); + } + } +}