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;
018
019 import com.google.common.collect.Lists;
020 import com.intellij.openapi.util.Trinity;
021 import gnu.trove.TObjectIntHashMap;
022 import gnu.trove.TObjectIntIterator;
023 import org.jetbrains.org.objectweb.asm.Type;
024 import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
025
026 import java.util.ArrayList;
027 import java.util.Collections;
028 import java.util.Comparator;
029 import java.util.List;
030
031 public class FrameMap {
032 private final TObjectIntHashMap<DeclarationDescriptor> myVarIndex = new TObjectIntHashMap<DeclarationDescriptor>();
033 private final TObjectIntHashMap<DeclarationDescriptor> myVarSizes = new TObjectIntHashMap<DeclarationDescriptor>();
034 private int myMaxIndex = 0;
035
036 public int enter(DeclarationDescriptor descriptor, Type type) {
037 int index = myMaxIndex;
038 myVarIndex.put(descriptor, index);
039 myMaxIndex += type.getSize();
040 myVarSizes.put(descriptor, type.getSize());
041 return index;
042 }
043
044 public int leave(DeclarationDescriptor descriptor) {
045 int size = myVarSizes.get(descriptor);
046 myMaxIndex -= size;
047 myVarSizes.remove(descriptor);
048 int oldIndex = myVarIndex.remove(descriptor);
049 if (oldIndex != myMaxIndex) {
050 throw new IllegalStateException("descriptor can be left only if it is last");
051 }
052 return oldIndex;
053 }
054
055 public int enterTemp(Type type) {
056 int result = myMaxIndex;
057 myMaxIndex += type.getSize();
058 return result;
059 }
060
061 public void leaveTemp(Type type) {
062 myMaxIndex -= type.getSize();
063 }
064
065 public int getIndex(DeclarationDescriptor descriptor) {
066 return myVarIndex.contains(descriptor) ? myVarIndex.get(descriptor) : -1;
067 }
068
069 public Mark mark() {
070 return new Mark(myMaxIndex);
071 }
072
073 public int getCurrentSize() {
074 return myMaxIndex;
075 }
076
077 public class Mark {
078 private final int myIndex;
079
080 public Mark(int index) {
081 myIndex = index;
082 }
083
084 public void dropTo() {
085 List<DeclarationDescriptor> descriptorsToDrop = new ArrayList<DeclarationDescriptor>();
086 TObjectIntIterator<DeclarationDescriptor> iterator = myVarIndex.iterator();
087 while (iterator.hasNext()) {
088 iterator.advance();
089 if (iterator.value() >= myIndex) {
090 descriptorsToDrop.add(iterator.key());
091 }
092 }
093 for (DeclarationDescriptor declarationDescriptor : descriptorsToDrop) {
094 myVarIndex.remove(declarationDescriptor);
095 myVarSizes.remove(declarationDescriptor);
096 }
097 myMaxIndex = myIndex;
098 }
099 }
100
101 @Override
102 public String toString() {
103 StringBuilder sb = new StringBuilder();
104
105 if (myVarIndex.size() != myVarSizes.size()) {
106 return "inconsistent";
107 }
108
109 List<Trinity<DeclarationDescriptor, Integer, Integer>> descriptors = Lists.newArrayList();
110
111 for (Object descriptor0 : myVarIndex.keys()) {
112 DeclarationDescriptor descriptor = (DeclarationDescriptor) descriptor0;
113 int varIndex = myVarIndex.get(descriptor);
114 int varSize = myVarSizes.get(descriptor);
115 descriptors.add(Trinity.create(descriptor, varIndex, varSize));
116 }
117
118 Collections.sort(descriptors, new Comparator<Trinity<DeclarationDescriptor, Integer, Integer>>() {
119 @Override
120 public int compare(
121 Trinity<DeclarationDescriptor, Integer, Integer> left,
122 Trinity<DeclarationDescriptor, Integer, Integer> right
123 ) {
124 return left.second - right.second;
125 }
126 });
127
128 sb.append("size=").append(myMaxIndex);
129
130 boolean first = true;
131 for (Trinity<DeclarationDescriptor, Integer, Integer> t : descriptors) {
132 if (!first) {
133 sb.append(", ");
134 }
135 first = false;
136 sb.append(t.first).append(",i=").append(t.second).append(",s=").append(t.third);
137 }
138
139 return sb.toString();
140 }
141 }