blob: eff8beabd29733fa1ccd66dd966c0a48247e412c [file] [log] [blame]
// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.regalloc;
import com.android.tools.r8.errors.Unreachable;
import java.util.Arrays;
import java.util.BitSet;
/**
* Simple mapping from a register to an int value.
* <p>
* The backing for the mapping grows as needed up to a given limit. If no mapping exists for
* a register number the value is assumed to be Integer.MAX_VALUE.
*/
public class RegisterPositions {
enum Type { MONITOR, CONST_NUMBER, OTHER, ANY }
private static final int INITIAL_SIZE = 16;
private final int limit;
private int[] backing;
private final BitSet registerHoldsConstant;
private final BitSet registerHoldsMonitor;
private final BitSet registerHoldsNewStringInstanceDisallowingSpilling;
public RegisterPositions(int limit) {
this.limit = limit;
backing = new int[INITIAL_SIZE];
for (int i = 0; i < INITIAL_SIZE; i++) {
backing[i] = Integer.MAX_VALUE;
}
registerHoldsConstant = new BitSet(limit);
registerHoldsMonitor = new BitSet(limit);
registerHoldsNewStringInstanceDisallowingSpilling = new BitSet(limit);
}
public boolean hasType(int index, Type type) {
switch (type) {
case MONITOR:
return holdsMonitor(index);
case CONST_NUMBER:
return holdsConstant(index);
case OTHER:
return !holdsMonitor(index)
&& !holdsConstant(index)
&& !holdsNewStringInstanceDisallowingSpilling(index);
case ANY:
return true;
default:
throw new Unreachable("Unexpected register position type: " + type);
}
}
private boolean holdsConstant(int index) {
return registerHoldsConstant.get(index);
}
private boolean holdsMonitor(int index) { return registerHoldsMonitor.get(index); }
private boolean holdsNewStringInstanceDisallowingSpilling(int index) {
return registerHoldsNewStringInstanceDisallowingSpilling.get(index);
}
public void set(int index, int value) {
if (index >= backing.length) {
grow(index + 1);
}
backing[index] = value;
}
public void set(int index, int value, LiveIntervals intervals) {
set(index, value);
registerHoldsConstant.set(index, intervals.isConstantNumberInterval());
registerHoldsMonitor.set(index, intervals.usedInMonitorOperation());
registerHoldsNewStringInstanceDisallowingSpilling.set(
index, intervals.isNewStringInstanceDisallowingSpilling());
}
public int get(int index) {
if (index < backing.length) {
return backing[index];
}
assert index < limit;
return Integer.MAX_VALUE;
}
public void grow(int minSize) {
int size = backing.length;
while (size < minSize) {
size *= 2;
}
size = Math.min(size, limit);
int oldSize = backing.length;
backing = Arrays.copyOf(backing, size);
for (int i = oldSize; i < size; i++) {
backing[i] = Integer.MAX_VALUE;
}
}
}