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 }