blob: 6763c273d5c670e0abc8e1f2363b7104ce0fb0d0 [file] [log] [blame]
/*
* 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);
}
}