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 }