/* * Copyright 2010-2015 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.optimization; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; 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.captured.CapturedVarsOptimizationMethodTransformer; import org.jetbrains.kotlin.codegen.optimization.common.UtilKt; import org.jetbrains.kotlin.codegen.optimization.nullCheck.RedundantNullCheckV2MethodTransformer; import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer; import org.jetbrains.org.objectweb.asm.MethodVisitor; import org.jetbrains.org.objectweb.asm.tree.MethodNode; public class OptimizationMethodVisitor extends TransformationMethodVisitor { private static final int MEMORY_LIMIT_BY_METHOD_MB = 50; private static final MethodTransformer MANDATORY_METHOD_TRANSFORMER = new FixStackWithLabelNormalizationMethodTransformer(); private static final MethodTransformer[] OPTIMIZATION_TRANSFORMERS = new MethodTransformer[] { new CapturedVarsOptimizationMethodTransformer(), new RedundantNullCheckV2MethodTransformer(), new RedundantCheckCastEliminationMethodTransformer(), new RedundantBoxingMethodTransformer(), new RedundantCoercionToUnitTransformer(), new DeadCodeEliminationMethodTransformer(), new RedundantGotoMethodTransformer(), new RedundantNopsCleanupMethodTransformer() }; private final boolean disableOptimization; public OptimizationMethodVisitor( @NotNull MethodVisitor delegate, boolean disableOptimization, int access, @NotNull String name, @NotNull String desc, @Nullable String signature, @Nullable String[] exceptions ) { super(delegate, access, name, desc, signature, exceptions); this.disableOptimization = disableOptimization; } @Override 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); } } UtilKt.prepareForEmitting(methodNode); } private static boolean canBeOptimized(@NotNull MethodNode node) { int totalFramesSizeMb = node.instructions.size() * (node.maxLocals + node.maxStack) / (1024 * 1024); return totalFramesSizeMb < MEMORY_LIMIT_BY_METHOD_MB; } }