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