1 /*
   2  * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 
  25 package jdk.tools.jaotc;
  26 
  27 import java.util.HashMap;
  28 import java.util.HashSet;
  29 import java.util.Set;
  30 
  31 import org.graalvm.compiler.hotspot.meta.HotSpotInvokeDynamicPlugin.DynamicTypeStore;
  32 
  33 import jdk.vm.ci.hotspot.HotSpotConstantPool;
  34 import jdk.vm.ci.hotspot.HotSpotConstantPoolObject;
  35 import jdk.vm.ci.hotspot.HotSpotObjectConstant;
  36 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
  37 import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
  38 import jdk.vm.ci.meta.JavaConstant;
  39 
  40 final class AOTDynamicTypeStore implements DynamicTypeStore {
  41 
  42     public static class Location {
  43         private HotSpotResolvedObjectType holder;
  44         private int cpi;
  45 
  46         Location(HotSpotResolvedObjectType holder, int cpi) {
  47             this.holder = holder;
  48             this.cpi = cpi;
  49         }
  50 
  51         public HotSpotResolvedObjectType getHolder() {
  52             return holder;
  53         }
  54 
  55         public int getCpi() {
  56             return cpi;
  57         }
  58 
  59         @Override
  60         public String toString() {
  61             return getHolder().getName() + "@" + cpi;
  62         }
  63 
  64         @Override
  65         public int hashCode() {
  66             return holder.hashCode() + getClass().hashCode() + cpi;
  67         }
  68 
  69         @Override
  70         public boolean equals(Object o) {
  71             if (this == o) {
  72                 return true;
  73             }
  74             if (getClass() != o.getClass()) {
  75                 return false;
  76             }
  77             Location l = (Location) o;
  78             return cpi == l.cpi && holder.equals(l.holder);
  79         }
  80     }
  81 
  82     public static class AdapterLocation extends Location {
  83         private int methodId;
  84 
  85         AdapterLocation(HotSpotResolvedObjectType holder, int cpi, int methodId) {
  86             super(holder, cpi);
  87             this.methodId = methodId;
  88         }
  89 
  90         public int getMethodId() {
  91             return methodId;
  92         }
  93 
  94         @Override
  95         public String toString() {
  96             return "adapter:" + methodId + "@" + super.toString();
  97         }
  98     }
  99 
 100     public static class AppendixLocation extends Location {
 101         AppendixLocation(HotSpotResolvedObjectType holder, int cpi) {
 102             super(holder, cpi);
 103         }
 104 
 105         @Override
 106         public String toString() {
 107             return "appendix@" + super.toString();
 108         }
 109     }
 110 
 111     private HashMap<HotSpotResolvedObjectType, HashSet<Location>> typeMap = new HashMap<>();
 112     private HashMap<HotSpotResolvedObjectType, HashSet<HotSpotResolvedObjectType>> holderMap = new HashMap<>();
 113 
 114     public Set<HotSpotResolvedObjectType> getDynamicTypes() {
 115         synchronized (typeMap) {
 116             return typeMap.keySet();
 117         }
 118     }
 119 
 120     public Set<HotSpotResolvedObjectType> getDynamicHolders() {
 121         synchronized (holderMap) {
 122             return holderMap.keySet();
 123         }
 124     }
 125 
 126     @Override
 127     public void recordAdapter(int opcode, HotSpotResolvedObjectType holder, int index, HotSpotResolvedJavaMethod adapter) {
 128         int cpi = ((HotSpotConstantPool) holder.getConstantPool()).rawIndexToConstantPoolIndex(index, opcode);
 129         int methodId = adapter.methodIdnum();
 130         HotSpotResolvedObjectType adapterType = adapter.getDeclaringClass();
 131         recordDynamicTypeLocation(new AdapterLocation(holder, cpi, methodId), adapterType);
 132     }
 133 
 134     @Override
 135     public JavaConstant recordAppendix(int opcode, HotSpotResolvedObjectType holder, int index, JavaConstant appendix) {
 136         int cpi = ((HotSpotConstantPool) holder.getConstantPool()).rawIndexToConstantPoolIndex(index, opcode);
 137         HotSpotResolvedObjectType appendixType = ((HotSpotObjectConstant) appendix).getType();
 138         recordDynamicTypeLocation(new AppendixLocation(holder, cpi), appendixType);
 139         // Make the constant locatable
 140         return HotSpotConstantPoolObject.forObject(holder, cpi, appendix);
 141     }
 142 
 143     private static <T> void recordDynamicMapValue(HashMap<HotSpotResolvedObjectType, HashSet<T>> map, HotSpotResolvedObjectType type, T v) {
 144         synchronized (map) {
 145             HashSet<T> set = map.get(type);
 146             if (set == null) {
 147                 set = new HashSet<>();
 148                 map.put(type, set);
 149             }
 150             set.add(v);
 151         }
 152     }
 153 
 154     private void recordDynamicTypeLocation(Location l, HotSpotResolvedObjectType type) {
 155         recordDynamicMapValue(typeMap, type, l);
 156         HotSpotResolvedObjectType holder = l.getHolder();
 157         recordDynamicMapValue(holderMap, holder, type);
 158     }
 159 
 160     public Set<Location> getDynamicClassLocationsForType(HotSpotResolvedObjectType type) {
 161         synchronized (typeMap) {
 162             return typeMap.get(type);
 163         }
 164     }
 165 
 166     public Set<HotSpotResolvedObjectType> getDynamicTypesForHolder(HotSpotResolvedObjectType holder) {
 167         synchronized (holderMap) {
 168             return holderMap.get(holder);
 169         }
 170     }
 171 
 172 }