001/* 002 * Copyright (c) 2011, 2014, 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 com.oracle.graal.debug.*; 028 029import com.oracle.graal.nodes.*; 030import com.oracle.graal.nodes.java.*; 031import com.oracle.graal.nodes.virtual.*; 032import com.oracle.graal.virtual.nodes.*; 033 034/** 035 * This class describes the state of a virtual object while iterating over the graph. It describes 036 * the fields or array elements (called "entries") and the lock count if the object is still 037 * virtual. If the object was materialized, it contains the current materialized value. 038 */ 039public class ObjectState { 040 041 public static final DebugMetric CREATE_ESCAPED_OBJECT_STATE = Debug.metric("CreateEscapeObjectState"); 042 public static final DebugMetric GET_ESCAPED_OBJECT_STATE = Debug.metric("GetEscapeObjectState"); 043 044 private ValueNode[] entries; 045 private ValueNode materializedValue; 046 private LockState locks; 047 private boolean ensureVirtualized; 048 049 private EscapeObjectState cachedState; 050 051 boolean copyOnWrite; 052 053 public ObjectState(ValueNode[] entries, List<MonitorIdNode> locks, boolean ensureVirtualized) { 054 this(entries, (LockState) null, ensureVirtualized); 055 for (int i = locks.size() - 1; i >= 0; i--) { 056 this.locks = new LockState(locks.get(i), this.locks); 057 } 058 } 059 060 public ObjectState(ValueNode[] entries, LockState locks, boolean ensureVirtualized) { 061 this.entries = entries; 062 this.locks = locks; 063 this.ensureVirtualized = ensureVirtualized; 064 } 065 066 public ObjectState(ValueNode materializedValue, LockState locks, boolean ensureVirtualized) { 067 assert materializedValue != null; 068 this.materializedValue = materializedValue; 069 this.locks = locks; 070 this.ensureVirtualized = ensureVirtualized; 071 } 072 073 private ObjectState(ObjectState other) { 074 entries = other.entries == null ? null : other.entries.clone(); 075 materializedValue = other.materializedValue; 076 locks = other.locks; 077 cachedState = other.cachedState; 078 ensureVirtualized = other.ensureVirtualized; 079 } 080 081 public ObjectState cloneState() { 082 return new ObjectState(this); 083 } 084 085 public EscapeObjectState createEscapeObjectState(VirtualObjectNode virtual) { 086 GET_ESCAPED_OBJECT_STATE.increment(); 087 if (cachedState == null) { 088 CREATE_ESCAPED_OBJECT_STATE.increment(); 089 cachedState = isVirtual() ? new VirtualObjectState(virtual, entries) : new MaterializedObjectState(virtual, materializedValue); 090 } 091 return cachedState; 092 093 } 094 095 public boolean isVirtual() { 096 assert materializedValue == null ^ entries == null; 097 return materializedValue == null; 098 } 099 100 /** 101 * Users of this method are not allowed to change the entries of the returned array. 102 */ 103 public ValueNode[] getEntries() { 104 assert isVirtual(); 105 return entries; 106 } 107 108 public ValueNode getEntry(int index) { 109 assert isVirtual(); 110 return entries[index]; 111 } 112 113 public ValueNode getMaterializedValue() { 114 assert !isVirtual(); 115 return materializedValue; 116 } 117 118 public void setEntry(int index, ValueNode value) { 119 assert isVirtual(); 120 cachedState = null; 121 entries[index] = value; 122 } 123 124 public void escape(ValueNode materialized) { 125 assert isVirtual(); 126 assert materialized != null; 127 materializedValue = materialized; 128 entries = null; 129 cachedState = null; 130 assert !isVirtual(); 131 } 132 133 public void updateMaterializedValue(ValueNode value) { 134 assert !isVirtual(); 135 assert value != null; 136 cachedState = null; 137 materializedValue = value; 138 } 139 140 public void addLock(MonitorIdNode monitorId) { 141 locks = new LockState(monitorId, locks); 142 } 143 144 public MonitorIdNode removeLock() { 145 try { 146 return locks.monitorId; 147 } finally { 148 locks = locks.next; 149 } 150 } 151 152 public LockState getLocks() { 153 return locks; 154 } 155 156 public boolean hasLocks() { 157 return locks != null; 158 } 159 160 public boolean locksEqual(ObjectState other) { 161 LockState a = locks; 162 LockState b = other.locks; 163 while (a != null && b != null && a.monitorId == b.monitorId) { 164 a = a.next; 165 b = b.next; 166 } 167 return a == null && b == null; 168 } 169 170 public void setEnsureVirtualized(boolean ensureVirtualized) { 171 this.ensureVirtualized = ensureVirtualized; 172 } 173 174 public boolean getEnsureVirtualized() { 175 return ensureVirtualized; 176 } 177 178 @Override 179 public String toString() { 180 StringBuilder str = new StringBuilder().append('{'); 181 if (locks != null) { 182 str.append('l').append(locks).append(' '); 183 } 184 if (entries != null) { 185 for (int i = 0; i < entries.length; i++) { 186 str.append("entry").append(i).append('=').append(entries[i]).append(' '); 187 } 188 } 189 if (materializedValue != null) { 190 str.append("mat=").append(materializedValue); 191 } 192 193 return str.append('}').toString(); 194 } 195 196 @Override 197 public int hashCode() { 198 final int prime = 31; 199 int result = 1; 200 result = prime * result + Arrays.hashCode(entries); 201 result = prime * result + (locks != null ? locks.monitorId.getLockDepth() : 0); 202 result = prime * result + ((materializedValue == null) ? 0 : materializedValue.hashCode()); 203 return result; 204 } 205 206 @Override 207 public boolean equals(Object obj) { 208 if (this == obj) { 209 return true; 210 } 211 if (obj == null || getClass() != obj.getClass()) { 212 return false; 213 } 214 ObjectState other = (ObjectState) obj; 215 if (!Arrays.equals(entries, other.entries)) { 216 return false; 217 } 218 if (!locksEqual(other)) { 219 return false; 220 } 221 if (materializedValue == null) { 222 if (other.materializedValue != null) { 223 return false; 224 } 225 } else if (!materializedValue.equals(other.materializedValue)) { 226 return false; 227 } 228 return true; 229 } 230 231 public ObjectState share() { 232 copyOnWrite = true; 233 return this; 234 } 235}