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