1/*
2 * Copyright (c) 2014, 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 */
23package org.graalvm.compiler.lir.util;
24
25import java.util.EnumSet;
26import java.util.Objects;
27
28import org.graalvm.compiler.lir.InstructionValueConsumer;
29import org.graalvm.compiler.lir.InstructionValueProcedure;
30import org.graalvm.compiler.lir.LIRInstruction;
31import org.graalvm.compiler.lir.LIRInstruction.OperandFlag;
32import org.graalvm.compiler.lir.LIRInstruction.OperandMode;
33
34import jdk.vm.ci.meta.Value;
35
36public final class IndexedValueMap {
37    private Value[] values;
38
39    public IndexedValueMap() {
40        values = Value.NO_VALUES;
41    }
42
43    public IndexedValueMap(IndexedValueMap other) {
44        int limit = other.values.length;
45        while (limit > 0) {
46            if (other.values[limit - 1] == null) {
47                limit--;
48                continue;
49            }
50            break;
51        }
52        if (limit == 0) {
53            values = Value.NO_VALUES;
54        } else {
55            values = new Value[limit];
56            System.arraycopy(other.values, 0, values, 0, values.length);
57        }
58    }
59
60    public Value get(int index) {
61        return values[index];
62    }
63
64    public void put(int index, Value value) {
65        if (values.length <= index) {
66            if (value == null) {
67                return;
68            }
69            Value[] newValues = new Value[index + 1];
70            if (values.length > 0) {
71                System.arraycopy(values, 0, newValues, 0, values.length);
72            }
73            values = newValues;
74            values[index] = value;
75        } else {
76            values[index] = value;
77        }
78    }
79
80    public void putAll(IndexedValueMap stack) {
81        Value[] otherValues = stack.values;
82        int limit = otherValues.length;
83        if (limit > values.length) {
84            while (limit > 0) {
85                if (otherValues[limit - 1] == null) {
86                    limit--;
87                    continue;
88                }
89                break;
90            }
91            if (limit > values.length) {
92                Value[] newValues = new Value[limit];
93                System.arraycopy(values, 0, newValues, 0, values.length);
94                values = newValues;
95            }
96        }
97        for (int i = 0; i < limit; i++) {
98            Value value = otherValues[i];
99            if (value != null) {
100                values[i] = value;
101            }
102        }
103    }
104
105    @Override
106    public boolean equals(Object other) {
107        if (other instanceof IndexedValueMap) {
108            IndexedValueMap that = (IndexedValueMap) other;
109            int limit = Math.min(values.length, that.values.length);
110            for (int i = 0; i < limit; i++) {
111                if (!Objects.equals(values[i], that.values[i])) {
112                    return false;
113                }
114            }
115            for (int i = limit; i < values.length; i++) {
116                if (values[i] != null) {
117                    return false;
118                }
119            }
120            for (int i = limit; i < that.values.length; i++) {
121                if (that.values[i] != null) {
122                    return false;
123                }
124            }
125            return true;
126        }
127        return false;
128    }
129
130    public void forEach(LIRInstruction inst, OperandMode mode, EnumSet<OperandFlag> flags, InstructionValueProcedure proc) {
131        for (int i = 0; i < values.length; i++) {
132            if (values[i] != null) {
133                values[i] = proc.doValue(inst, values[i], mode, flags);
134            }
135        }
136    }
137
138    public void visitEach(LIRInstruction inst, OperandMode mode, EnumSet<OperandFlag> flags, InstructionValueConsumer consumer) {
139        for (Value v : values) {
140            if (v != null) {
141                consumer.visitValue(inst, v, mode, flags);
142            }
143        }
144    }
145
146    @Override
147    public int hashCode() {
148        throw new UnsupportedOperationException();
149    }
150
151    @Override
152    public String toString() {
153        StringBuilder sb = new StringBuilder("[");
154        boolean comma = false;
155
156        for (int i = 0; i < values.length; i++) {
157            if (values[i] != null) {
158                if (comma) {
159                    sb.append(", ");
160                } else {
161                    comma = true;
162                }
163
164                sb.append(i);
165                sb.append(": ");
166                sb.append(values[i]);
167            }
168        }
169        sb.append(']');
170        return sb.toString();
171    }
172}
173