001 /*
002 * Copyright 2010-2013 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.org.objectweb.asm.Label;
020 import org.jetbrains.org.objectweb.asm.MethodVisitor;
021 import org.jetbrains.org.objectweb.asm.Opcodes;
022 import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
023
024 import java.util.ArrayList;
025 import java.util.List;
026
027 public class InlineAdapter extends InstructionAdapter {
028
029 private int nextLocalIndex = 0;
030
031 private boolean isInlining = false;
032
033 private final List<CatchBlock> blocks = new ArrayList<CatchBlock>();
034
035 private int nextLocalIndexBeforeInline = -1;
036
037 public InlineAdapter(MethodVisitor mv, int localsSize) {
038 super(InlineCodegenUtil.API, mv);
039 nextLocalIndex = localsSize;
040 }
041
042 @Override
043 public void visitIincInsn(int var, int increment) {
044 super.visitIincInsn(var, increment);
045 updateIndex(var, 1);
046 }
047
048 @Override
049 public void visitVarInsn(int opcode, int var) {
050 super.visitVarInsn(opcode, var);
051 updateIndex(var, (opcode == Opcodes.DSTORE || opcode == Opcodes.LSTORE || opcode == Opcodes.DLOAD || opcode == Opcodes.LLOAD ? 2 : 1));
052 }
053
054 private void updateIndex(int var, int varSize) {
055 int newIndex = var + varSize;
056 if (newIndex > nextLocalIndex) {
057 nextLocalIndex = newIndex;
058 }
059 }
060
061 public int getNextLocalIndex() {
062 return nextLocalIndex;
063 }
064
065 public void setLambdaInlining(boolean isInlining) {
066 this.isInlining = isInlining;
067 if (isInlining) {
068 nextLocalIndexBeforeInline = nextLocalIndex;
069 } else {
070 nextLocalIndex = nextLocalIndexBeforeInline;
071 }
072 }
073
074 @Override
075 public void visitTryCatchBlock(Label start,
076 Label end, Label handler, String type) {
077 if(!isInlining) {
078 blocks.add(new CatchBlock(start, end, handler, type));
079 }
080 else {
081 super.visitTryCatchBlock(start, end, handler, type);
082 }
083 }
084
085 @Override
086 public void visitMaxs(int stack, int locals) {
087 for (CatchBlock b : blocks) {
088 super.visitTryCatchBlock(b.start, b.end, b.handler, b.type);
089 }
090 super.visitMaxs(stack, locals);
091 }
092
093 private static class CatchBlock {
094 private final Label start;
095 private final Label end;
096 private final Label handler;
097 private final String type;
098
099 public CatchBlock(Label start, Label end, Label handler, String type) {
100 this.start = start;
101 this.end = end;
102 this.handler = handler;
103 this.type = type;
104 }
105 }
106 }