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.inline;
018
019 import org.jetbrains.annotations.NotNull;
020 import org.jetbrains.org.objectweb.asm.Label;
021 import org.jetbrains.org.objectweb.asm.MethodVisitor;
022 import org.jetbrains.org.objectweb.asm.Opcodes;
023 import org.jetbrains.org.objectweb.asm.Type;
024
025 public class MaxLocalsCalculator extends MethodVisitor {
026
027 private int maxLocals;
028
029 public MaxLocalsCalculator(int api, int access, String descriptor, MethodVisitor mv) {
030 super(api, mv);
031
032 // updates maxLocals
033 int size = Type.getArgumentsAndReturnSizes(descriptor) >> 2;
034 if ((access & Opcodes.ACC_STATIC) != 0) {
035 --size;
036 }
037
038 maxLocals = size;
039 }
040
041 @Override
042 public void visitVarInsn(int opcode, int var) {
043 int n;
044 if (opcode == Opcodes.LLOAD || opcode == Opcodes.DLOAD ||
045 opcode == Opcodes.LSTORE || opcode == Opcodes.DSTORE) {
046 n = var + 2;
047 }
048 else {
049 n = var + 1;
050 }
051 updateMaxLocals(n);
052
053 super.visitVarInsn(opcode, var);
054 }
055
056 @Override
057 public void visitIincInsn(int var, int increment) {
058 updateMaxLocals(var + 1);
059
060 super.visitIincInsn(var, increment);
061 }
062
063 @Override
064 public void visitLocalVariable(
065 @NotNull String name, @NotNull String desc, String signature, @NotNull Label start, @NotNull Label end, int index
066 ) {
067 // updates max locals
068 char c = desc.charAt(0);
069 int n = index + (c == 'J' || c == 'D' ? 2 : 1);
070 updateMaxLocals(n);
071
072 super.visitLocalVariable(name, desc, signature, start, end, index);
073 }
074
075 @Override
076 public void visitMaxs(int maxStack, int maxLocals) {
077 super.visitMaxs(maxStack, this.maxLocals);
078 }
079
080 public int getMaxLocals() {
081 return maxLocals;
082 }
083
084 private void updateMaxLocals(int nextFreeSlotNumber) {
085 if (nextFreeSlotNumber > maxLocals) {
086 maxLocals = nextFreeSlotNumber;
087 }
088 }
089
090 }