CommitAllocationNode.java revision 13083:b9a173f12fe6
1/* 2 * Copyright (c) 2009, 2014, 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 */ 23package org.graalvm.compiler.nodes.virtual; 24 25import static org.graalvm.compiler.nodeinfo.InputType.Association; 26import static org.graalvm.compiler.nodeinfo.InputType.Extension; 27import static org.graalvm.compiler.nodeinfo.InputType.Memory; 28import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN; 29import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_UNKNOWN; 30 31import java.util.ArrayList; 32import java.util.Arrays; 33import java.util.List; 34import java.util.Map; 35 36import org.graalvm.api.word.LocationIdentity; 37import org.graalvm.compiler.core.common.type.StampFactory; 38import org.graalvm.compiler.graph.Node; 39import org.graalvm.compiler.graph.NodeClass; 40import org.graalvm.compiler.graph.NodeInputList; 41import org.graalvm.compiler.graph.spi.Simplifiable; 42import org.graalvm.compiler.graph.spi.SimplifierTool; 43import org.graalvm.compiler.nodeinfo.NodeCycles; 44import org.graalvm.compiler.nodeinfo.NodeInfo; 45import org.graalvm.compiler.nodeinfo.NodeSize; 46import org.graalvm.compiler.nodeinfo.Verbosity; 47import org.graalvm.compiler.nodes.FixedWithNextNode; 48import org.graalvm.compiler.nodes.ValueNode; 49import org.graalvm.compiler.nodes.java.AbstractNewObjectNode; 50import org.graalvm.compiler.nodes.java.MonitorIdNode; 51import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; 52import org.graalvm.compiler.nodes.memory.WriteNode; 53import org.graalvm.compiler.nodes.spi.Lowerable; 54import org.graalvm.compiler.nodes.spi.LoweringTool; 55import org.graalvm.compiler.nodes.spi.VirtualizableAllocation; 56import org.graalvm.compiler.nodes.spi.VirtualizerTool; 57 58// @formatter:off 59@NodeInfo(nameTemplate = "Alloc {i#virtualObjects}", 60 allowedUsageTypes = {Extension, Memory}, 61 cycles = CYCLES_UNKNOWN, 62 cyclesRationale = "We don't know statically how many, and which, allocations are done.", 63 size = SIZE_UNKNOWN, 64 sizeRationale = "We don't know statically how much code for which allocations has to be generated." 65) 66// @formatter:on 67public final class CommitAllocationNode extends FixedWithNextNode implements VirtualizableAllocation, Lowerable, Simplifiable, MemoryCheckpoint.Single { 68 69 public static final NodeClass<CommitAllocationNode> TYPE = NodeClass.create(CommitAllocationNode.class); 70 71 @Input NodeInputList<VirtualObjectNode> virtualObjects = new NodeInputList<>(this); 72 @Input NodeInputList<ValueNode> values = new NodeInputList<>(this); 73 @Input(Association) NodeInputList<MonitorIdNode> locks = new NodeInputList<>(this); 74 protected ArrayList<Integer> lockIndexes = new ArrayList<>(Arrays.asList(0)); 75 protected ArrayList<Boolean> ensureVirtual = new ArrayList<>(); 76 77 public CommitAllocationNode() { 78 super(TYPE, StampFactory.forVoid()); 79 } 80 81 public List<VirtualObjectNode> getVirtualObjects() { 82 return virtualObjects; 83 } 84 85 public List<ValueNode> getValues() { 86 return values; 87 } 88 89 public List<MonitorIdNode> getLocks(int objIndex) { 90 return locks.subList(lockIndexes.get(objIndex), lockIndexes.get(objIndex + 1)); 91 } 92 93 public List<Boolean> getEnsureVirtual() { 94 return ensureVirtual; 95 } 96 97 @Override 98 public boolean verify() { 99 assertTrue(virtualObjects.size() + 1 == lockIndexes.size(), "lockIndexes size doesn't match %s, %s", virtualObjects, lockIndexes); 100 assertTrue(lockIndexes.get(lockIndexes.size() - 1) == locks.size(), "locks size doesn't match %s,%s", lockIndexes, locks); 101 int valueCount = 0; 102 for (VirtualObjectNode virtual : virtualObjects) { 103 valueCount += virtual.entryCount(); 104 } 105 assertTrue(values.size() == valueCount, "values size doesn't match"); 106 assertTrue(virtualObjects.size() == ensureVirtual.size(), "ensureVirtual size doesn't match"); 107 return super.verify(); 108 } 109 110 @Override 111 public void lower(LoweringTool tool) { 112 for (int i = 0; i < virtualObjects.size(); i++) { 113 if (ensureVirtual.get(i)) { 114 EnsureVirtualizedNode.ensureVirtualFailure(this, virtualObjects.get(i).stamp()); 115 } 116 } 117 tool.getLowerer().lower(this, tool); 118 } 119 120 @Override 121 public LocationIdentity getLocationIdentity() { 122 return locks.isEmpty() ? LocationIdentity.init() : LocationIdentity.any(); 123 } 124 125 @Override 126 public void afterClone(Node other) { 127 lockIndexes = new ArrayList<>(lockIndexes); 128 } 129 130 public void addLocks(List<MonitorIdNode> monitorIds) { 131 locks.addAll(monitorIds); 132 lockIndexes.add(locks.size()); 133 } 134 135 @Override 136 public void virtualize(VirtualizerTool tool) { 137 int pos = 0; 138 for (int i = 0; i < virtualObjects.size(); i++) { 139 VirtualObjectNode virtualObject = virtualObjects.get(i); 140 int entryCount = virtualObject.entryCount(); 141 tool.createVirtualObject(virtualObject, values.subList(pos, pos + entryCount).toArray(new ValueNode[entryCount]), getLocks(i), ensureVirtual.get(i)); 142 pos += entryCount; 143 } 144 tool.delete(); 145 } 146 147 @Override 148 public Map<Object, Object> getDebugProperties(Map<Object, Object> map) { 149 Map<Object, Object> properties = super.getDebugProperties(map); 150 int valuePos = 0; 151 for (int objIndex = 0; objIndex < virtualObjects.size(); objIndex++) { 152 VirtualObjectNode virtual = virtualObjects.get(objIndex); 153 if (virtual == null) { 154 // Could occur in invalid graphs 155 properties.put("object(" + objIndex + ")", "null"); 156 continue; 157 } 158 StringBuilder s = new StringBuilder(); 159 s.append(virtual.type().toJavaName(false)).append("["); 160 for (int i = 0; i < virtual.entryCount(); i++) { 161 ValueNode value = values.get(valuePos++); 162 s.append(i == 0 ? "" : ",").append(value == null ? "_" : value.toString(Verbosity.Id)); 163 } 164 s.append("]"); 165 if (!getLocks(objIndex).isEmpty()) { 166 s.append(" locked(").append(getLocks(objIndex)).append(")"); 167 } 168 properties.put("object(" + virtual.toString(Verbosity.Id) + ")", s.toString()); 169 } 170 return properties; 171 } 172 173 @Override 174 public void simplify(SimplifierTool tool) { 175 boolean[] used = new boolean[virtualObjects.size()]; 176 int usedCount = 0; 177 for (AllocatedObjectNode addObject : usages().filter(AllocatedObjectNode.class)) { 178 int index = virtualObjects.indexOf(addObject.getVirtualObject()); 179 assert !used[index]; 180 used[index] = true; 181 usedCount++; 182 } 183 if (usedCount == 0) { 184 List<Node> inputSnapshot = inputs().snapshot(); 185 graph().removeFixed(this); 186 for (Node input : inputSnapshot) { 187 tool.removeIfUnused(input); 188 } 189 return; 190 } 191 boolean progress; 192 do { 193 progress = false; 194 int valuePos = 0; 195 for (int objIndex = 0; objIndex < virtualObjects.size(); objIndex++) { 196 VirtualObjectNode virtualObject = virtualObjects.get(objIndex); 197 if (used[objIndex]) { 198 for (int i = 0; i < virtualObject.entryCount(); i++) { 199 int index = virtualObjects.indexOf(values.get(valuePos + i)); 200 if (index != -1 && !used[index]) { 201 progress = true; 202 used[index] = true; 203 usedCount++; 204 } 205 } 206 } 207 valuePos += virtualObject.entryCount(); 208 } 209 210 } while (progress); 211 212 if (usedCount < virtualObjects.size()) { 213 List<VirtualObjectNode> newVirtualObjects = new ArrayList<>(usedCount); 214 List<MonitorIdNode> newLocks = new ArrayList<>(usedCount); 215 ArrayList<Integer> newLockIndexes = new ArrayList<>(usedCount + 1); 216 ArrayList<Boolean> newEnsureVirtual = new ArrayList<>(usedCount); 217 newLockIndexes.add(0); 218 List<ValueNode> newValues = new ArrayList<>(); 219 int valuePos = 0; 220 for (int objIndex = 0; objIndex < virtualObjects.size(); objIndex++) { 221 VirtualObjectNode virtualObject = virtualObjects.get(objIndex); 222 if (used[objIndex]) { 223 newVirtualObjects.add(virtualObject); 224 newLocks.addAll(getLocks(objIndex)); 225 newLockIndexes.add(newLocks.size()); 226 newValues.addAll(values.subList(valuePos, valuePos + virtualObject.entryCount())); 227 newEnsureVirtual.add(ensureVirtual.get(objIndex)); 228 } 229 valuePos += virtualObject.entryCount(); 230 } 231 virtualObjects.clear(); 232 virtualObjects.addAll(newVirtualObjects); 233 locks.clear(); 234 locks.addAll(newLocks); 235 values.clear(); 236 values.addAll(newValues); 237 lockIndexes = newLockIndexes; 238 ensureVirtual = newEnsureVirtual; 239 } 240 } 241 242 @Override 243 public NodeCycles estimatedNodeCycles() { 244 List<VirtualObjectNode> v = getVirtualObjects(); 245 int fieldWriteCount = 0; 246 for (int i = 0; i < v.size(); i++) { 247 fieldWriteCount += v.get(i).entryCount(); 248 } 249 int rawValueWrites = NodeCycles.compute(WriteNode.TYPE.cycles(), fieldWriteCount).value; 250 int rawValuesTlabBumps = AbstractNewObjectNode.TYPE.cycles().value; 251 return NodeCycles.compute(rawValueWrites + rawValuesTlabBumps); 252 } 253 254 @Override 255 public NodeSize estimatedNodeSize() { 256 List<VirtualObjectNode> v = getVirtualObjects(); 257 int fieldWriteCount = 0; 258 for (int i = 0; i < v.size(); i++) { 259 fieldWriteCount += v.get(i).entryCount(); 260 } 261 int rawValueWrites = NodeSize.compute(WriteNode.TYPE.size(), fieldWriteCount).value; 262 int rawValuesTlabBumps = AbstractNewObjectNode.TYPE.size().value; 263 return NodeSize.compute(rawValueWrites + rawValuesTlabBumps); 264 } 265} 266