001/* 002 * Copyright (c) 2009, 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.nodes.virtual; 024 025import java.util.*; 026 027import com.oracle.graal.compiler.common.type.*; 028import com.oracle.graal.graph.*; 029import com.oracle.graal.graph.spi.*; 030import com.oracle.graal.nodeinfo.*; 031import com.oracle.graal.nodes.*; 032import com.oracle.graal.nodes.java.*; 033import com.oracle.graal.nodes.spi.*; 034 035@NodeInfo(nameTemplate = "Alloc {i#virtualObjects}", allowedUsageTypes = {InputType.Extension}) 036public final class CommitAllocationNode extends FixedWithNextNode implements VirtualizableAllocation, Lowerable, Simplifiable { 037 038 public static final NodeClass<CommitAllocationNode> TYPE = NodeClass.create(CommitAllocationNode.class); 039 040 @Input NodeInputList<VirtualObjectNode> virtualObjects = new NodeInputList<>(this); 041 @Input NodeInputList<ValueNode> values = new NodeInputList<>(this); 042 @Input(InputType.Association) NodeInputList<MonitorIdNode> locks = new NodeInputList<>(this); 043 protected ArrayList<Integer> lockIndexes = new ArrayList<>(Arrays.asList(0)); 044 protected ArrayList<Boolean> ensureVirtual = new ArrayList<>(); 045 046 public CommitAllocationNode() { 047 super(TYPE, StampFactory.forVoid()); 048 } 049 050 public List<VirtualObjectNode> getVirtualObjects() { 051 return virtualObjects; 052 } 053 054 public List<ValueNode> getValues() { 055 return values; 056 } 057 058 public List<MonitorIdNode> getLocks(int objIndex) { 059 return locks.subList(lockIndexes.get(objIndex), lockIndexes.get(objIndex + 1)); 060 } 061 062 public List<Boolean> getEnsureVirtual() { 063 return ensureVirtual; 064 } 065 066 @Override 067 public boolean verify() { 068 assertTrue(virtualObjects.size() + 1 == lockIndexes.size(), "lockIndexes size doesn't match " + virtualObjects + ", " + lockIndexes); 069 assertTrue(lockIndexes.get(lockIndexes.size() - 1) == locks.size(), "locks size doesn't match " + lockIndexes + ", " + locks); 070 int valueCount = 0; 071 for (VirtualObjectNode virtual : virtualObjects) { 072 valueCount += virtual.entryCount(); 073 } 074 assertTrue(values.size() == valueCount, "values size doesn't match"); 075 assertTrue(virtualObjects.size() == ensureVirtual.size(), "ensureVirtual size doesn't match"); 076 return super.verify(); 077 } 078 079 @Override 080 public void lower(LoweringTool tool) { 081 for (int i = 0; i < virtualObjects.size(); i++) { 082 if (ensureVirtual.get(i)) { 083 EnsureVirtualizedNode.ensureVirtualFailure(this, virtualObjects.get(i).stamp()); 084 } 085 } 086 tool.getLowerer().lower(this, tool); 087 } 088 089 @Override 090 public void afterClone(Node other) { 091 lockIndexes = new ArrayList<>(lockIndexes); 092 } 093 094 public void addLocks(List<MonitorIdNode> monitorIds) { 095 locks.addAll(monitorIds); 096 lockIndexes.add(locks.size()); 097 } 098 099 @Override 100 public void virtualize(VirtualizerTool tool) { 101 int pos = 0; 102 for (int i = 0; i < virtualObjects.size(); i++) { 103 VirtualObjectNode virtualObject = virtualObjects.get(i); 104 int entryCount = virtualObject.entryCount(); 105 tool.createVirtualObject(virtualObject, values.subList(pos, pos + entryCount).toArray(new ValueNode[entryCount]), getLocks(i), ensureVirtual.get(i)); 106 pos += entryCount; 107 } 108 tool.delete(); 109 } 110 111 @Override 112 public Map<Object, Object> getDebugProperties(Map<Object, Object> map) { 113 Map<Object, Object> properties = super.getDebugProperties(map); 114 int valuePos = 0; 115 for (int objIndex = 0; objIndex < virtualObjects.size(); objIndex++) { 116 VirtualObjectNode virtual = virtualObjects.get(objIndex); 117 if (virtual == null) { 118 // Could occur in invalid graphs 119 properties.put("object(" + objIndex + ")", "null"); 120 continue; 121 } 122 StringBuilder s = new StringBuilder(); 123 s.append(virtual.type().toJavaName(false)).append("["); 124 for (int i = 0; i < virtual.entryCount(); i++) { 125 ValueNode value = values.get(valuePos++); 126 s.append(i == 0 ? "" : ",").append(value == null ? "_" : value.toString(Verbosity.Id)); 127 } 128 s.append("]"); 129 if (!getLocks(objIndex).isEmpty()) { 130 s.append(" locked(").append(getLocks(objIndex)).append(")"); 131 } 132 properties.put("object(" + virtual.toString(Verbosity.Id) + ")", s.toString()); 133 } 134 return properties; 135 } 136 137 @Override 138 public void simplify(SimplifierTool tool) { 139 boolean[] used = new boolean[virtualObjects.size()]; 140 int usedCount = 0; 141 for (Node usage : usages()) { 142 AllocatedObjectNode addObject = (AllocatedObjectNode) usage; 143 int index = virtualObjects.indexOf(addObject.getVirtualObject()); 144 assert !used[index]; 145 used[index] = true; 146 usedCount++; 147 } 148 if (usedCount == 0) { 149 List<Node> inputSnapshot = inputs().snapshot(); 150 graph().removeFixed(this); 151 for (Node input : inputSnapshot) { 152 tool.removeIfUnused(input); 153 } 154 return; 155 } 156 boolean progress; 157 do { 158 progress = false; 159 int valuePos = 0; 160 for (int objIndex = 0; objIndex < virtualObjects.size(); objIndex++) { 161 VirtualObjectNode virtualObject = virtualObjects.get(objIndex); 162 if (used[objIndex]) { 163 for (int i = 0; i < virtualObject.entryCount(); i++) { 164 int index = virtualObjects.indexOf(values.get(valuePos + i)); 165 if (index != -1 && !used[index]) { 166 progress = true; 167 used[index] = true; 168 usedCount++; 169 } 170 } 171 } 172 valuePos += virtualObject.entryCount(); 173 } 174 175 } while (progress); 176 177 if (usedCount < virtualObjects.size()) { 178 List<VirtualObjectNode> newVirtualObjects = new ArrayList<>(usedCount); 179 List<MonitorIdNode> newLocks = new ArrayList<>(usedCount); 180 ArrayList<Integer> newLockIndexes = new ArrayList<>(usedCount + 1); 181 ArrayList<Boolean> newEnsureVirtual = new ArrayList<>(usedCount); 182 newLockIndexes.add(0); 183 List<ValueNode> newValues = new ArrayList<>(); 184 int valuePos = 0; 185 for (int objIndex = 0; objIndex < virtualObjects.size(); objIndex++) { 186 VirtualObjectNode virtualObject = virtualObjects.get(objIndex); 187 if (used[objIndex]) { 188 newVirtualObjects.add(virtualObject); 189 newLocks.addAll(getLocks(objIndex)); 190 newLockIndexes.add(newLocks.size()); 191 newValues.addAll(values.subList(valuePos, valuePos + virtualObject.entryCount())); 192 newEnsureVirtual.add(ensureVirtual.get(objIndex)); 193 } 194 valuePos += virtualObject.entryCount(); 195 } 196 virtualObjects.clear(); 197 virtualObjects.addAll(newVirtualObjects); 198 locks.clear(); 199 locks.addAll(newLocks); 200 values.clear(); 201 values.addAll(newValues); 202 lockIndexes = newLockIndexes; 203 ensureVirtual = newEnsureVirtual; 204 } 205 } 206 207}