001 /*
002 * Copyright 2010-2015 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package org.jetbrains.kotlin.codegen.optimization;
018
019 import org.jetbrains.annotations.NotNull;
020 import org.jetbrains.annotations.Nullable;
021 import org.jetbrains.kotlin.codegen.TransformationMethodVisitor;
022 import org.jetbrains.kotlin.codegen.optimization.boxing.RedundantBoxingMethodTransformer;
023 import org.jetbrains.kotlin.codegen.optimization.boxing.RedundantCoercionToUnitTransformer;
024 import org.jetbrains.kotlin.codegen.optimization.boxing.RedundantNullCheckMethodTransformer;
025 import org.jetbrains.kotlin.codegen.optimization.common.UtilKt;
026 import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer;
027 import org.jetbrains.org.objectweb.asm.MethodVisitor;
028 import org.jetbrains.org.objectweb.asm.tree.MethodNode;
029
030 public class OptimizationMethodVisitor extends TransformationMethodVisitor {
031 private static final int MEMORY_LIMIT_BY_METHOD_MB = 50;
032
033 private static final MethodTransformer MANDATORY_METHOD_TRANSFORMER = new FixStackWithLabelNormalizationMethodTransformer();
034
035 private static final MethodTransformer[] OPTIMIZATION_TRANSFORMERS = new MethodTransformer[] {
036 new RedundantNullCheckMethodTransformer(),
037 new RedundantBoxingMethodTransformer(),
038 new RedundantCoercionToUnitTransformer(),
039 new DeadCodeEliminationMethodTransformer(),
040 new RedundantGotoMethodTransformer(),
041 new RedundantNopsCleanupMethodTransformer()
042 };
043
044 private final boolean disableOptimization;
045
046 public OptimizationMethodVisitor(
047 @NotNull MethodVisitor delegate,
048 boolean disableOptimization,
049 int access,
050 @NotNull String name,
051 @NotNull String desc,
052 @Nullable String signature,
053 @Nullable String[] exceptions
054 ) {
055 super(delegate, access, name, desc, signature, exceptions);
056 this.disableOptimization = disableOptimization;
057 }
058
059 @Override
060 protected void performTransformations(@NotNull MethodNode methodNode) {
061 MANDATORY_METHOD_TRANSFORMER.transform("fake", methodNode);
062 if (canBeOptimized(methodNode) && !disableOptimization) {
063 for (MethodTransformer transformer : OPTIMIZATION_TRANSFORMERS) {
064 transformer.transform("fake", methodNode);
065 }
066 }
067 UtilKt.prepareForEmitting(methodNode);
068 }
069
070 private static boolean canBeOptimized(@NotNull MethodNode node) {
071 int totalFramesSizeMb = node.instructions.size() * (node.maxLocals + node.maxStack) / (1024 * 1024);
072 return totalFramesSizeMb < MEMORY_LIMIT_BY_METHOD_MB;
073 }
074 }