| /* |
| * Copyright 2014 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
| * in compliance with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software distributed under the License |
| * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
| * or implied. See the License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| package com.google.gwt.dev; |
| |
| import com.google.gwt.dev.jjs.impl.RapidTypeAnalyzer.AnalyzableTypeEnvironment; |
| import com.google.gwt.dev.util.collect.IntHashMultimap; |
| import com.google.gwt.dev.util.collect.IntMultimap; |
| import com.google.gwt.thirdparty.guava.common.annotations.VisibleForTesting; |
| import com.google.gwt.thirdparty.guava.common.base.Objects; |
| import com.google.gwt.thirdparty.guava.common.collect.Lists; |
| import com.google.gwt.thirdparty.guava.common.collect.Maps; |
| |
| import cern.colt.list.IntArrayList; |
| import cern.colt.map.OpenIntIntHashMap; |
| |
| import java.io.Serializable; |
| import java.util.Collection; |
| import java.util.List; |
| import java.util.Map; |
| |
| /** |
| * An AnalyzableTypeEnvironment that is built up from inserted method and type name strings. |
| */ |
| public class StringAnalyzableTypeEnvironment implements AnalyzableTypeEnvironment, Serializable { |
| |
| @SuppressWarnings({"rawtypes", "unchecked"}) |
| private static void copyCollection(Collection fromCollection, Collection toCollection) { |
| toCollection.clear(); |
| toCollection.addAll(fromCollection); |
| } |
| |
| private static void copyCollection(IntArrayList fromCollection, IntArrayList toCollection) { |
| toCollection.clear(); |
| toCollection.addAllOf(fromCollection); |
| } |
| |
| @SuppressWarnings({"rawtypes", "unchecked"}) |
| private static void copyMap(Map fromMap, Map toMap) { |
| toMap.clear(); |
| toMap.putAll(fromMap); |
| } |
| |
| private static void copyMap(OpenIntIntHashMap fromMap, OpenIntIntHashMap toMap) { |
| IntArrayList keys = fromMap.keys(); |
| for (int i = 0; i < keys.size(); i++) { |
| int key = keys.get(i); |
| int value = fromMap.get(key); |
| toMap.put(key, value); |
| } |
| } |
| |
| private static void copyMultimap(IntMultimap fromMap, IntMultimap toMap) { |
| toMap.clear(); |
| toMap.putAll(fromMap); |
| } |
| |
| private final IntMultimap calleeMethodIdsByCallerMethodId = new IntMultimap(); |
| private final OpenIntIntHashMap enclosingTypeIdByMethodId = new OpenIntIntHashMap(); |
| private final IntArrayList entryMethodIds = new IntArrayList(); |
| private final IntMultimap exportedMethodIdsByTypeId = new IntMultimap(); |
| private final IntMultimap instantiatedTypeIdsByMethodId = new IntMultimap(); |
| private final IntHashMultimap memberMethodIdsByTypeId = new IntHashMultimap(); |
| private final Map<String, Integer> methodIdsByName = Maps.newHashMap(); |
| private final List<String> methodNamesById = Lists.newArrayList(); |
| private final IntMultimap overidingMethodIdsByOverriddenMethodId = new IntMultimap(); |
| private final IntHashMultimap overriddenMethodIdsByOverridingMethodId = new IntHashMultimap(); |
| private final IntHashMultimap staticallyReferencedTypeIdsByMethodId = new IntHashMultimap(); |
| private final Map<String, Integer> typeIdsByName = Maps.newHashMap(); |
| private final OpenIntIntHashMap typeIdsWithExportedStaticReferences = new OpenIntIntHashMap(); |
| private final List<String> typeNamesById = Lists.newArrayList(); |
| |
| StringAnalyzableTypeEnvironment() { |
| } |
| |
| @Override |
| public IntArrayList getMemberMethodIdsIn(int enclosingTypeId) { |
| return memberMethodIdsByTypeId.get(enclosingTypeId); |
| } |
| |
| @Override |
| public IntArrayList getMethodIdsCalledBy(int callerMethodId) { |
| return calleeMethodIdsByCallerMethodId.get(callerMethodId); |
| } |
| |
| @Override |
| public IntArrayList getOverriddenMethodIds(int overridingMethodId) { |
| return overriddenMethodIdsByOverridingMethodId.get(overridingMethodId); |
| } |
| |
| @Override |
| public IntArrayList getOverridingMethodIds(int overriddenMethodId) { |
| return overidingMethodIdsByOverriddenMethodId.get(overriddenMethodId); |
| } |
| |
| @Override |
| public IntArrayList getStaticallyReferencedTypeIdsIn(int reachableMethodId) { |
| return staticallyReferencedTypeIdsByMethodId.get(reachableMethodId); |
| } |
| |
| @Override |
| public IntArrayList getTypeIdsInstantiatedIn(int inMethodId) { |
| return instantiatedTypeIdsByMethodId.get(inMethodId); |
| } |
| |
| public void recordExportedMethodInType(String methodName, String typeName) { |
| int typeId = getTypeIdByName(typeName); |
| int methodId = getMethodIdByName(methodName); |
| exportedMethodIdsByTypeId.put(typeId, methodId); |
| } |
| |
| public void recordExportedStaticReferenceInType(String typeName) { |
| int typeId = getTypeIdByName(typeName); |
| typeIdsWithExportedStaticReferences.put(typeId, typeId); |
| } |
| |
| public void recordMethodCallsMethod(String callerMethodName, String calleeMethodName) { |
| calleeMethodIdsByCallerMethodId.put(getMethodIdByName(callerMethodName), |
| getMethodIdByName(calleeMethodName)); |
| } |
| |
| public void recordMethodInstantiatesType(String methodName, String instantiatedTypeName) { |
| instantiatedTypeIdsByMethodId.put(getMethodIdByName(methodName), |
| getTypeIdByName(instantiatedTypeName)); |
| } |
| |
| public void recordMethodOverridesMethod(String overriderMethodName, String overriddenMethodName) { |
| int overriderMethodId = getMethodIdByName(overriderMethodName); |
| int overriddenMethodId = getMethodIdByName(overriddenMethodName); |
| overriddenMethodIdsByOverridingMethodId.put(overriderMethodId, overriddenMethodId); |
| overidingMethodIdsByOverriddenMethodId.put(overriddenMethodId, overriderMethodId); |
| } |
| |
| public void recordStaticReferenceInMethod(String typeName, String methodName) { |
| staticallyReferencedTypeIdsByMethodId.put(getMethodIdByName(methodName), |
| getTypeIdByName(typeName)); |
| } |
| |
| public void recordTypeEnclosesMethod(String enclosingTypeName, String nestedMethodName) { |
| int enclosingTypeId = getTypeIdByName(enclosingTypeName); |
| int nestedMethodId = getMethodIdByName(nestedMethodName); |
| memberMethodIdsByTypeId.put(enclosingTypeId, nestedMethodId); |
| enclosingTypeIdByMethodId.put(nestedMethodId, enclosingTypeId); |
| } |
| |
| /** |
| * Remove control flow index entries that are created by the processing of the given type. |
| */ |
| public void removeControlFlowIndexesFor(String typeName) { |
| int typeId = getTypeIdByName(typeName); |
| exportedMethodIdsByTypeId.remove(typeId); |
| typeIdsWithExportedStaticReferences.removeKey(typeId); |
| |
| IntArrayList memberMethodIds = memberMethodIdsByTypeId.get(typeId); |
| if (memberMethodIds == null) { |
| return; |
| } |
| memberMethodIdsByTypeId.remove(typeId); |
| for (int i = 0; i < memberMethodIds.size(); i++) { |
| int memberMethodId = memberMethodIds.get(i); |
| enclosingTypeIdByMethodId.removeKey(memberMethodId); |
| calleeMethodIdsByCallerMethodId.remove(memberMethodId); |
| instantiatedTypeIdsByMethodId.remove(memberMethodId); |
| |
| IntArrayList overriddenMethodIds = |
| overriddenMethodIdsByOverridingMethodId.remove(memberMethodId); |
| if (overriddenMethodIds != null) { |
| for (int j = 0; j < overriddenMethodIds.size(); j++) { |
| int overriddenMethodId = overriddenMethodIds.get(j); |
| while (overidingMethodIdsByOverriddenMethodId |
| .remove(memberMethodId, overriddenMethodId)) { |
| // Remove all instances by repeating remove one. |
| } |
| } |
| } |
| staticallyReferencedTypeIdsByMethodId.remove(memberMethodId); |
| } |
| } |
| |
| public void setEntryMethodNames(List<String> entryMethodNames) { |
| this.entryMethodIds.clear(); |
| for (String entryMethodName : entryMethodNames) { |
| this.entryMethodIds.add(getMethodIdByName(entryMethodName)); |
| } |
| } |
| |
| void copyFrom(StringAnalyzableTypeEnvironment that) { |
| copyMap(that.typeIdsWithExportedStaticReferences, this.typeIdsWithExportedStaticReferences); |
| copyMap(that.enclosingTypeIdByMethodId, this.enclosingTypeIdByMethodId); |
| copyMap(that.methodIdsByName, this.methodIdsByName); |
| copyMap(that.typeIdsByName, this.typeIdsByName); |
| |
| copyMultimap(that.memberMethodIdsByTypeId, this.memberMethodIdsByTypeId); |
| copyMultimap(that.calleeMethodIdsByCallerMethodId, this.calleeMethodIdsByCallerMethodId); |
| copyMultimap(that.exportedMethodIdsByTypeId, this.exportedMethodIdsByTypeId); |
| copyMultimap(that.instantiatedTypeIdsByMethodId, this.instantiatedTypeIdsByMethodId); |
| copyMultimap(that.overidingMethodIdsByOverriddenMethodId, |
| this.overidingMethodIdsByOverriddenMethodId); |
| copyMultimap(that.overriddenMethodIdsByOverridingMethodId, |
| this.overriddenMethodIdsByOverridingMethodId); |
| copyMultimap(that.staticallyReferencedTypeIdsByMethodId, |
| this.staticallyReferencedTypeIdsByMethodId); |
| |
| copyCollection(that.entryMethodIds, this.entryMethodIds); |
| copyCollection(that.methodNamesById, this.methodNamesById); |
| copyCollection(that.typeNamesById, this.typeNamesById); |
| } |
| |
| int getEnclosingTypeId(int memberMethodId) { |
| return enclosingTypeIdByMethodId.get(memberMethodId); |
| } |
| |
| IntArrayList getEnclosingTypeIdsOfExportedMethods() { |
| return exportedMethodIdsByTypeId.keys(); |
| } |
| |
| IntArrayList getEntryMethodIds() { |
| return entryMethodIds; |
| } |
| |
| IntArrayList getExportedMemberMethodIdsIn(int enclosingTypeId) { |
| return exportedMethodIdsByTypeId.get(enclosingTypeId); |
| } |
| |
| int getMethodIdByName(String methodName) { |
| if (methodIdsByName.containsKey(methodName)) { |
| return methodIdsByName.get(methodName); |
| } |
| int methodId = methodNamesById.size(); |
| methodIdsByName.put(methodName, methodId); |
| methodNamesById.add(methodName); |
| return methodId; |
| } |
| |
| int getTypeIdByName(String typeName) { |
| if (typeIdsByName.containsKey(typeName)) { |
| return typeIdsByName.get(typeName); |
| } |
| int typeId = typeNamesById.size(); |
| typeIdsByName.put(typeName, typeId); |
| typeNamesById.add(typeName); |
| return typeId; |
| } |
| |
| IntArrayList getTypeIdsWithExportedStaticReferences() { |
| return typeIdsWithExportedStaticReferences.keys(); |
| } |
| |
| String getTypeNameById(int typeId) { |
| return typeNamesById.get(typeId); |
| } |
| |
| @VisibleForTesting |
| boolean hasSameContent(StringAnalyzableTypeEnvironment that) { |
| return Objects.equal(this.calleeMethodIdsByCallerMethodId, that.calleeMethodIdsByCallerMethodId) |
| && Objects.equal(this.memberMethodIdsByTypeId, that.memberMethodIdsByTypeId) |
| && Objects.equal(this.entryMethodIds, that.entryMethodIds) |
| && Objects.equal(this.instantiatedTypeIdsByMethodId, that.instantiatedTypeIdsByMethodId) |
| && Objects.equal(this.overidingMethodIdsByOverriddenMethodId, |
| that.overidingMethodIdsByOverriddenMethodId) && Objects.equal( |
| this.overriddenMethodIdsByOverridingMethodId, |
| that.overriddenMethodIdsByOverridingMethodId) && Objects.equal( |
| this.staticallyReferencedTypeIdsByMethodId, that.staticallyReferencedTypeIdsByMethodId) |
| && Objects.equal(this.enclosingTypeIdByMethodId, that.enclosingTypeIdByMethodId) && Objects |
| .equal(this.exportedMethodIdsByTypeId, that.exportedMethodIdsByTypeId) && Objects.equal( |
| this.typeIdsWithExportedStaticReferences, that.typeIdsWithExportedStaticReferences); |
| } |
| } |