001    /*
002     * Copyright 2010-2014 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.jet.codegen.inline;
018    
019    import org.jetbrains.asm4.MethodVisitor;
020    import org.jetbrains.asm4.Opcodes;
021    import org.jetbrains.asm4.Type;
022    import org.jetbrains.asm4.tree.AbstractInsnNode;
023    import org.jetbrains.asm4.tree.MethodNode;
024    
025    import java.util.ListIterator;
026    
027    public class MaxCalcNode extends MethodVisitor {
028    
029        private int maxLocal;
030    
031        private final MethodNode node;
032    
033        public MaxCalcNode(MethodNode node) {
034            super(Opcodes.ASM4, node);
035            this.node = node;
036            int paramsSize = (node.access & Opcodes.ACC_STATIC) == 0 ? 1 : 0;
037    
038            Type[] types = Type.getArgumentTypes(node.desc);
039            for (Type type : types) {
040                paramsSize += type.getSize();
041            }
042            maxLocal = paramsSize;
043        }
044    
045        @Override
046        public void visitVarInsn(int opcode, int var) {
047            super.visitVarInsn(opcode, var);
048            int size = opcode == Opcodes.LLOAD || opcode == Opcodes.DLOAD || opcode == Opcodes.LSTORE || opcode == Opcodes.DSTORE ? 2 : 1;
049            updateMaxLocal(var, size);
050        }
051    
052        @Override
053        public void visitIincInsn(int var, int increment) {
054            super.visitIincInsn(var, increment);
055            updateMaxLocal(var, 1);
056        }
057    
058        private void updateMaxLocal(int index, int size) {
059            maxLocal = Math.max(maxLocal, index + size);
060        }
061    
062        @Override
063        public void visitMaxs(int maxStack, int maxLocals) {
064            //NB: it's hack for fast maxStack calculation cause it performed only in MethodWriter
065            //temporary solution: maxStack = instruction size (without labels and line numbers) * 2 (cause 1 instruction could put value of size 2)
066            int size = 0;
067            ListIterator<AbstractInsnNode> iterator = node.instructions.iterator();
068            while (iterator.hasNext()) {
069                AbstractInsnNode next = iterator.next();
070                int type = next.getType();
071                if (type != AbstractInsnNode.LINE && type != AbstractInsnNode.LABEL) {
072                    size++;
073                }
074            }
075            super.visitMaxs(Math.max(size * 2, maxStack), Math.max(maxLocals, this.maxLocal));
076        }
077    }