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.asm4.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 class Mark {
074 private final int myIndex;
075
076 public Mark(int index) {
077 myIndex = index;
078 }
079
080 public void dropTo() {
081 List<DeclarationDescriptor> descriptorsToDrop = new ArrayList<DeclarationDescriptor>();
082 TObjectIntIterator<DeclarationDescriptor> iterator = myVarIndex.iterator();
083 while (iterator.hasNext()) {
084 iterator.advance();
085 if (iterator.value() >= myIndex) {
086 descriptorsToDrop.add(iterator.key());
087 }
088 }
089 for (DeclarationDescriptor declarationDescriptor : descriptorsToDrop) {
090 myVarIndex.remove(declarationDescriptor);
091 myVarSizes.remove(declarationDescriptor);
092 }
093 myMaxIndex = myIndex;
094 }
095 }
096
097 @Override
098 public String toString() {
099 StringBuilder sb = new StringBuilder();
100
101 if (myVarIndex.size() != myVarSizes.size()) {
102 return "inconsistent";
103 }
104
105 List<Trinity<DeclarationDescriptor, Integer, Integer>> descriptors = Lists.newArrayList();
106
107 for (Object descriptor0 : myVarIndex.keys()) {
108 DeclarationDescriptor descriptor = (DeclarationDescriptor) descriptor0;
109 int varIndex = myVarIndex.get(descriptor);
110 int varSize = myVarSizes.get(descriptor);
111 descriptors.add(Trinity.create(descriptor, varIndex, varSize));
112 }
113
114 Collections.sort(descriptors, new Comparator<Trinity<DeclarationDescriptor, Integer, Integer>>() {
115 @Override
116 public int compare(
117 Trinity<DeclarationDescriptor, Integer, Integer> left,
118 Trinity<DeclarationDescriptor, Integer, Integer> right
119 ) {
120 return left.second - right.second;
121 }
122 });
123
124 sb.append("size=").append(myMaxIndex);
125
126 boolean first = true;
127 for (Trinity<DeclarationDescriptor, Integer, Integer> t : descriptors) {
128 if (!first) {
129 sb.append(", ");
130 }
131 first = false;
132 sb.append(t.first).append(",i=").append(t.second).append(",s=").append(t.third);
133 }
134
135 return sb.toString();
136 }
137 }