001/*
002 * Copyright (c) 2015, 2015, 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.lir.dfa;
024
025import static jdk.internal.jvmci.code.ValueUtil.*;
026
027import java.util.*;
028
029import jdk.internal.jvmci.meta.*;
030
031import com.oracle.graal.lir.*;
032import com.oracle.graal.lir.LIRInstruction.*;
033import com.oracle.graal.lir.framemap.*;
034import com.oracle.graal.lir.util.*;
035
036final class RegStackValueSet extends ValueSet<RegStackValueSet> {
037
038    private final FrameMap frameMap;
039    private final IndexedValueMap registers;
040    private final IndexedValueMap stack;
041    private Set<Value> extraStack;
042
043    public RegStackValueSet(FrameMap frameMap) {
044        this.frameMap = frameMap;
045        registers = new IndexedValueMap();
046        stack = new IndexedValueMap();
047    }
048
049    private RegStackValueSet(FrameMap frameMap, RegStackValueSet s) {
050        this.frameMap = frameMap;
051        registers = new IndexedValueMap(s.registers);
052        stack = new IndexedValueMap(s.stack);
053        if (s.extraStack != null) {
054            extraStack = new HashSet<>(s.extraStack);
055        }
056    }
057
058    @Override
059    public RegStackValueSet copy() {
060        return new RegStackValueSet(frameMap, this);
061    }
062
063    @Override
064    public void put(Value v) {
065        if (!shouldProcessValue(v)) {
066            return;
067        }
068        if (isRegister(v)) {
069            int index = asRegister(v).getReferenceMapIndex();
070            registers.put(index, v);
071        } else if (isStackSlot(v)) {
072            int index = frameMap.offsetForStackSlot(asStackSlot(v));
073            assert index >= 0;
074            if (index % 4 == 0) {
075                stack.put(index / 4, v);
076            } else {
077                if (extraStack == null) {
078                    extraStack = new HashSet<>();
079                }
080                extraStack.add(v);
081            }
082        }
083    }
084
085    @Override
086    public void putAll(RegStackValueSet v) {
087        registers.putAll(v.registers);
088        stack.putAll(v.stack);
089        if (v.extraStack != null) {
090            if (extraStack == null) {
091                extraStack = new HashSet<>();
092            }
093            extraStack.addAll(v.extraStack);
094        }
095    }
096
097    @Override
098    public void remove(Value v) {
099        if (!shouldProcessValue(v)) {
100            return;
101        }
102        if (isRegister(v)) {
103            int index = asRegister(v).getReferenceMapIndex();
104            registers.put(index, null);
105        } else if (isStackSlot(v)) {
106            int index = frameMap.offsetForStackSlot(asStackSlot(v));
107            assert index >= 0;
108            if (index % 4 == 0) {
109                stack.put(index / 4, null);
110            } else if (extraStack != null) {
111                extraStack.remove(v);
112            }
113        }
114    }
115
116    @Override
117    public boolean equals(Object obj) {
118        if (obj instanceof RegStackValueSet) {
119            RegStackValueSet other = (RegStackValueSet) obj;
120            return registers.equals(other.registers) && stack.equals(other.stack) && Objects.equals(extraStack, other.extraStack);
121        } else {
122            return false;
123        }
124    }
125
126    @Override
127    public int hashCode() {
128        throw new UnsupportedOperationException();
129    }
130
131    private static boolean shouldProcessValue(Value v) {
132        /*
133         * We always process registers because we have to track the largest register size that is
134         * alive across safepoints in order to save and restore them.
135         */
136        return isRegister(v) || !v.getLIRKind().isValue();
137    }
138
139    public void addLiveValues(ReferenceMapBuilder refMap) {
140        ValueConsumer addLiveValue = new ValueConsumer() {
141            public void visitValue(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
142                refMap.addLiveValue(value);
143            }
144        };
145        registers.forEach(null, null, null, addLiveValue);
146        stack.forEach(null, null, null, addLiveValue);
147        if (extraStack != null) {
148            for (Value v : extraStack) {
149                refMap.addLiveValue(v);
150            }
151        }
152    }
153}