1 /* 2 * Copyright (c) 2011, 2016, 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 package org.graalvm.compiler.virtual.phases.ea; 24 25 import java.util.Iterator; 26 import java.util.List; 27 28 import org.graalvm.compiler.debug.DebugContext; 29 import org.graalvm.compiler.nodes.FieldLocationIdentity; 30 import org.graalvm.compiler.nodes.ValueNode; 31 import org.graalvm.compiler.nodes.virtual.AllocatedObjectNode; 32 import org.graalvm.compiler.nodes.virtual.VirtualInstanceNode; 33 import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; 34 import org.graalvm.compiler.options.OptionValues; 35 import org.graalvm.util.EconomicMap; 36 import org.graalvm.util.Equivalence; 37 import org.graalvm.word.LocationIdentity; 38 39 public final class PEReadEliminationBlockState extends PartialEscapeBlockState<PEReadEliminationBlockState> { 40 41 final EconomicMap<ReadCacheEntry, ValueNode> readCache; 42 43 static final class ReadCacheEntry { 44 45 public final LocationIdentity identity; 46 public final ValueNode object; 47 public final int index; 48 49 ReadCacheEntry(LocationIdentity identity, ValueNode object, int index) { 50 this.identity = identity; 51 this.object = object; 52 this.index = index; 53 } 54 55 @Override 56 public int hashCode() { 57 int result = 31 + ((identity == null) ? 0 : identity.hashCode()); 58 result = 31 * result + ((object == null) ? 0 : System.identityHashCode(object)); 59 return result * 31 + index; 60 } 61 62 @Override 63 public boolean equals(Object obj) { 64 if (!(obj instanceof ReadCacheEntry)) { 65 return false; 66 } 67 ReadCacheEntry other = (ReadCacheEntry) obj; 68 return identity.equals(other.identity) && object == other.object && index == other.index; 69 } 70 71 @Override 72 public String toString() { 73 return index == -1 ? (object + ":" + identity) : (object + "[" + index + "]:" + identity); 74 } 75 } 76 77 public PEReadEliminationBlockState(OptionValues options, DebugContext debug) { 78 super(options, debug); 79 readCache = EconomicMap.create(Equivalence.DEFAULT); 80 } 81 82 public PEReadEliminationBlockState(PEReadEliminationBlockState other) { 83 super(other); 84 readCache = EconomicMap.create(Equivalence.DEFAULT, other.readCache); 85 } 86 87 @Override 88 public String toString() { 89 return super.toString() + " " + readCache; 90 } 91 92 @Override 93 protected void objectMaterialized(VirtualObjectNode virtual, AllocatedObjectNode representation, List<ValueNode> values) { 94 if (virtual instanceof VirtualInstanceNode) { 95 VirtualInstanceNode instance = (VirtualInstanceNode) virtual; 96 for (int i = 0; i < instance.entryCount(); i++) { 97 readCache.put(new ReadCacheEntry(new FieldLocationIdentity(instance.field(i)), representation, -1), values.get(i)); 98 } 99 } 100 } 101 102 @Override 103 public boolean equivalentTo(PEReadEliminationBlockState other) { 104 if (!isSubMapOf(readCache, other.readCache)) { 105 return false; 106 } 107 return super.equivalentTo(other); 108 } 109 110 public void addReadCache(ValueNode object, LocationIdentity identity, int index, ValueNode value, PartialEscapeClosure<?> closure) { 111 ValueNode cacheObject; 112 ObjectState obj = closure.getObjectState(this, object); 113 if (obj != null) { 114 assert !obj.isVirtual(); 115 cacheObject = obj.getMaterializedValue(); 116 } else { 117 cacheObject = object; 118 } 119 readCache.put(new ReadCacheEntry(identity, cacheObject, index), value); 120 } 121 122 public ValueNode getReadCache(ValueNode object, LocationIdentity identity, int index, PartialEscapeClosure<?> closure) { 123 ValueNode cacheObject; 124 ObjectState obj = closure.getObjectState(this, object); 125 if (obj != null) { 126 assert !obj.isVirtual() : object; 127 cacheObject = obj.getMaterializedValue(); 128 } else { 129 cacheObject = object; 130 } 131 ValueNode cacheValue = readCache.get(new ReadCacheEntry(identity, cacheObject, index)); 132 obj = closure.getObjectState(this, cacheValue); 133 if (obj != null) { 134 assert !obj.isVirtual(); 135 cacheValue = obj.getMaterializedValue(); 136 } else { 137 // assert !scalarAliases.containsKey(cacheValue); 138 cacheValue = closure.getScalarAlias(cacheValue); 139 } 140 return cacheValue; 141 } 142 143 public void killReadCache() { 144 readCache.clear(); 145 } 146 147 public void killReadCache(LocationIdentity identity, int index) { 148 Iterator<ReadCacheEntry> iter = readCache.getKeys().iterator(); 149 while (iter.hasNext()) { 150 ReadCacheEntry entry = iter.next(); 151 if (entry.identity.equals(identity) && (index == -1 || entry.index == -1 || index == entry.index)) { 152 iter.remove(); 153 } 154 } 155 } 156 157 public EconomicMap<ReadCacheEntry, ValueNode> getReadCache() { 158 return readCache; 159 } 160 }