1 /* 2 * Copyright (c) 2015, 2015, 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.lir.dfa; 24 25 import static jdk.vm.ci.code.ValueUtil.asRegister; 26 import static jdk.vm.ci.code.ValueUtil.asStackSlot; 27 import static jdk.vm.ci.code.ValueUtil.isRegister; 28 import static jdk.vm.ci.code.ValueUtil.isStackSlot; 29 30 import java.util.EnumSet; 31 import java.util.HashSet; 32 import java.util.Objects; 33 import java.util.Set; 34 35 import org.graalvm.compiler.core.common.LIRKind; 36 import org.graalvm.compiler.lir.LIRInstruction.OperandFlag; 37 import org.graalvm.compiler.lir.LIRInstruction.OperandMode; 38 import org.graalvm.compiler.lir.ValueConsumer; 39 import org.graalvm.compiler.lir.framemap.FrameMap; 40 import org.graalvm.compiler.lir.framemap.ReferenceMapBuilder; 41 import org.graalvm.compiler.lir.util.IndexedValueMap; 42 import org.graalvm.compiler.lir.util.ValueSet; 43 44 import jdk.vm.ci.meta.Value; 45 46 final class RegStackValueSet extends ValueSet<RegStackValueSet> { 47 48 private final FrameMap frameMap; 49 private final IndexedValueMap registers; 50 private final IndexedValueMap stack; 51 private Set<Value> extraStack; 52 53 RegStackValueSet(FrameMap frameMap) { 54 this.frameMap = frameMap; 55 registers = new IndexedValueMap(); 56 stack = new IndexedValueMap(); 57 } 58 59 private RegStackValueSet(FrameMap frameMap, RegStackValueSet s) { 60 this.frameMap = frameMap; 61 registers = new IndexedValueMap(s.registers); 62 stack = new IndexedValueMap(s.stack); 63 if (s.extraStack != null) { 64 extraStack = new HashSet<>(s.extraStack); 65 } 66 } 67 68 @Override 69 public RegStackValueSet copy() { 70 return new RegStackValueSet(frameMap, this); 71 } 72 73 @Override 74 public void put(Value v) { 75 if (!shouldProcessValue(v)) { 76 return; 77 } 78 if (isRegister(v)) { 79 int index = asRegister(v).number; 80 registers.put(index, v); 81 } else if (isStackSlot(v)) { 82 int index = frameMap.offsetForStackSlot(asStackSlot(v)); 83 assert index >= 0; 84 if (index % 4 == 0) { 85 stack.put(index / 4, v); 86 } else { 87 if (extraStack == null) { 88 extraStack = new HashSet<>(); 89 } 90 extraStack.add(v); 91 } 92 } 93 } 94 95 @Override 96 public void putAll(RegStackValueSet v) { 97 registers.putAll(v.registers); 98 stack.putAll(v.stack); 99 if (v.extraStack != null) { 100 if (extraStack == null) { 101 extraStack = new HashSet<>(); 102 } 103 extraStack.addAll(v.extraStack); 104 } 105 } 106 107 @Override 108 public void remove(Value v) { 109 if (!shouldProcessValue(v)) { 110 return; 111 } 112 if (isRegister(v)) { 113 int index = asRegister(v).number; 114 registers.put(index, null); 115 } else if (isStackSlot(v)) { 116 int index = frameMap.offsetForStackSlot(asStackSlot(v)); 117 assert index >= 0; 118 if (index % 4 == 0) { 119 stack.put(index / 4, null); 120 } else if (extraStack != null) { 121 extraStack.remove(v); 122 } 123 } 124 } 125 126 @Override 127 public boolean equals(Object obj) { 128 if (obj instanceof RegStackValueSet) { 129 RegStackValueSet other = (RegStackValueSet) obj; 130 return registers.equals(other.registers) && stack.equals(other.stack) && Objects.equals(extraStack, other.extraStack); 131 } else { 132 return false; 133 } 134 } 135 136 @Override 137 public int hashCode() { 138 throw new UnsupportedOperationException(); 139 } 140 141 private static boolean shouldProcessValue(Value v) { 142 /* 143 * We always process registers because we have to track the largest register size that is 144 * alive across safepoints in order to save and restore them. 145 */ 146 return isRegister(v) || !LIRKind.isValue(v); 147 } 148 149 public void addLiveValues(ReferenceMapBuilder refMap) { 150 ValueConsumer addLiveValue = new ValueConsumer() { 151 @Override 152 public void visitValue(Value value, OperandMode mode, EnumSet<OperandFlag> flags) { 153 refMap.addLiveValue(value); 154 } 155 }; 156 registers.visitEach(null, null, null, addLiveValue); 157 stack.visitEach(null, null, null, addLiveValue); 158 if (extraStack != null) { 159 for (Value v : extraStack) { 160 refMap.addLiveValue(v); 161 } 162 } 163 } 164 }