001/* 002 * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.virtual.phases.ea; 024 025import java.util.*; 026 027import jdk.internal.jvmci.meta.*; 028 029import com.oracle.graal.compiler.common.*; 030import com.oracle.graal.nodes.*; 031 032public class ReadEliminationBlockState extends EffectsBlockState<ReadEliminationBlockState> { 033 034 final HashMap<CacheEntry<?>, ValueNode> readCache; 035 036 abstract static class CacheEntry<T> { 037 038 public final ValueNode object; 039 public final T identity; 040 041 public CacheEntry(ValueNode object, T identity) { 042 this.object = object; 043 this.identity = identity; 044 } 045 046 public abstract CacheEntry<T> duplicateWithObject(ValueNode newObject); 047 048 @Override 049 public int hashCode() { 050 int result = 31 + ((identity == null) ? 0 : identity.hashCode()); 051 return 31 * result + ((object == null) ? 0 : object.hashCode()); 052 } 053 054 @Override 055 public boolean equals(Object obj) { 056 if (!(obj instanceof CacheEntry<?>)) { 057 return false; 058 } 059 CacheEntry<?> other = (CacheEntry<?>) obj; 060 return identity == other.identity && object == other.object; 061 } 062 063 @Override 064 public String toString() { 065 return object + ":" + identity; 066 } 067 068 public abstract boolean conflicts(LocationIdentity other); 069 } 070 071 static class LoadCacheEntry extends CacheEntry<LocationIdentity> { 072 073 public LoadCacheEntry(ValueNode object, LocationIdentity identity) { 074 super(object, identity); 075 } 076 077 @Override 078 public CacheEntry<LocationIdentity> duplicateWithObject(ValueNode newObject) { 079 return new LoadCacheEntry(newObject, identity); 080 } 081 082 @Override 083 public boolean conflicts(LocationIdentity other) { 084 return identity.equals(other); 085 } 086 } 087 088 /** 089 * CacheEntry describing an Unsafe memory reference. The memory location and the location 090 * identity are separate so both must be considered when looking for optimizable memory 091 * accesses. 092 * 093 */ 094 static class UnsafeLoadCacheEntry extends CacheEntry<ValueNode> { 095 096 private LocationIdentity locationIdentity; 097 098 public UnsafeLoadCacheEntry(ValueNode object, ValueNode location, LocationIdentity locationIdentity) { 099 super(object, location); 100 this.locationIdentity = locationIdentity; 101 } 102 103 @Override 104 public CacheEntry<ValueNode> duplicateWithObject(ValueNode newObject) { 105 return new UnsafeLoadCacheEntry(newObject, identity, locationIdentity); 106 } 107 108 @Override 109 public boolean conflicts(LocationIdentity other) { 110 return locationIdentity.equals(other); 111 } 112 } 113 114 static class ReadCacheEntry extends CacheEntry<ValueNode> { 115 116 private final LocationIdentity location; 117 118 public ReadCacheEntry(ValueNode object, ValueNode offset, LocationIdentity location) { 119 super(object, offset); 120 this.location = location; 121 } 122 123 @Override 124 public CacheEntry<ValueNode> duplicateWithObject(ValueNode newObject) { 125 return new ReadCacheEntry(newObject, identity, location); 126 } 127 128 @Override 129 public boolean conflicts(LocationIdentity other) { 130 return location.equals(other); 131 } 132 133 @Override 134 public boolean equals(Object obj) { 135 if (!(obj instanceof ReadCacheEntry)) { 136 return false; 137 } 138 139 ReadCacheEntry other = (ReadCacheEntry) obj; 140 return this.location.equals(other.location) && super.equals(other); 141 } 142 143 @Override 144 public int hashCode() { 145 return location.hashCode() * 23 + super.hashCode(); 146 } 147 } 148 149 public ReadEliminationBlockState() { 150 readCache = CollectionsFactory.newMap(); 151 } 152 153 public ReadEliminationBlockState(ReadEliminationBlockState other) { 154 readCache = CollectionsFactory.newMap(other.readCache); 155 } 156 157 @Override 158 public String toString() { 159 return super.toString() + " " + readCache; 160 } 161 162 @Override 163 public boolean equivalentTo(ReadEliminationBlockState other) { 164 return compareMapsNoSize(readCache, other.readCache); 165 } 166 167 public void addCacheEntry(CacheEntry<?> identifier, ValueNode value) { 168 readCache.put(identifier, value); 169 } 170 171 public ValueNode getCacheEntry(CacheEntry<?> identifier) { 172 return readCache.get(identifier); 173 } 174 175 public void killReadCache() { 176 readCache.clear(); 177 } 178 179 public void killReadCache(LocationIdentity identity) { 180 readCache.entrySet().removeIf(entry -> entry.getKey().conflicts(identity)); 181 } 182 183 public Map<CacheEntry<?>, ValueNode> getReadCache() { 184 return readCache; 185 } 186}