001 /* 002 * Copyright 2010-2015 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.kotlin.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.kotlin.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: " + descriptor); 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 }