1 /* 2 * Copyright (c) 2012, 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 */ 23 package org.graalvm.compiler.debug.internal; 24 25 import java.util.ArrayList; 26 import java.util.Arrays; 27 import java.util.Collections; 28 import java.util.HashMap; 29 import java.util.List; 30 import java.util.Map; 31 32 /** 33 * A node in a tree of {@link DebugValue}s. 34 */ 35 public class DebugValueMap { 36 37 private static final List<DebugValueMap> topLevelMaps = new ArrayList<>(); 38 39 private long[] values; 40 private List<DebugValueMap> children; 41 private String name; 42 43 public DebugValueMap(String name) { 44 this.name = name; 45 } 46 47 public void setCurrentValue(int index, long l) { 48 ensureSize(index); 49 values[index] = l; 50 } 51 52 public long getCurrentValue(int index) { 53 ensureSize(index); 54 return values[index]; 55 } 56 57 public void clearChildren() { 58 if (children != null) { 59 children.clear(); 60 } 61 } 62 63 public void reset() { 64 if (values != null) { 65 Arrays.fill(values, 0L); 66 } 67 if (children != null) { 68 for (DebugValueMap child : children) { 69 child.reset(); 70 } 71 } 72 } 73 74 private void ensureSize(int index) { 75 if (values == null) { 76 values = new long[index + 1]; 77 } 78 if (values.length <= index) { 79 values = Arrays.copyOf(values, index + 1); 80 } 81 } 82 83 private int capacity() { 84 return (values == null) ? 0 : values.length; 85 } 86 87 public void addChild(DebugValueMap map) { 88 if (children == null) { 89 children = new ArrayList<>(4); 90 } 91 children.add(map); 92 } 93 94 public List<DebugValueMap> getChildren() { 95 if (children == null) { 96 return Collections.emptyList(); 97 } else { 98 return Collections.unmodifiableList(children); 99 } 100 } 101 102 public boolean hasChildren() { 103 return children != null && !children.isEmpty(); 104 } 105 106 public String getName() { 107 return this.name; 108 } 109 110 @Override 111 public String toString() { 112 return "DebugValueMap<" + getName() + ">"; 113 } 114 115 public static synchronized void registerTopLevel(DebugValueMap map) { 116 topLevelMaps.add(map); 117 } 118 119 public static synchronized List<DebugValueMap> getTopLevelMaps() { 120 return topLevelMaps; 121 } 122 123 public void normalize() { 124 if (hasChildren()) { 125 Map<String, DebugValueMap> occurred = new HashMap<>(); 126 for (DebugValueMap map : children) { 127 String mapName = map.getName(); 128 if (!occurred.containsKey(mapName)) { 129 occurred.put(mapName, map); 130 map.normalize(); 131 } else { 132 occurred.get(mapName).mergeWith(map); 133 occurred.get(mapName).normalize(); 134 } 135 } 136 137 if (occurred.values().size() < children.size()) { 138 // At least one duplicate was found. 139 children.clear(); 140 for (DebugValueMap map : occurred.values()) { 141 addChild(map); 142 map.normalize(); 143 } 144 } 145 } 146 } 147 148 private void mergeWith(DebugValueMap map) { 149 if (map.hasChildren()) { 150 if (hasChildren()) { 151 children.addAll(map.children); 152 } else { 153 children = map.children; 154 } 155 map.children = null; 156 } 157 158 int size = Math.max(this.capacity(), map.capacity()); 159 ensureSize(size); 160 for (int i = 0; i < size; ++i) { 161 long curValue = getCurrentValue(i); 162 long otherValue = map.getCurrentValue(i); 163 setCurrentValue(i, curValue + otherValue); 164 } 165 } 166 167 public void group() { 168 if (this.hasChildren()) { 169 List<DebugValueMap> oldChildren = new ArrayList<>(this.children); 170 this.children.clear(); 171 for (DebugValueMap map : oldChildren) { 172 mergeWith(map); 173 } 174 } 175 } 176 }